pax_global_header00006660000000000000000000000064135770613710014524gustar00rootroot0000000000000052 comment=1f371947309c5ea6023b6d9065415697cbc75578 micropython-1.12/000077500000000000000000000000001357706137100140225ustar00rootroot00000000000000micropython-1.12/.gitattributes000066400000000000000000000013051357706137100167140ustar00rootroot00000000000000# Per default everything gets normalized and gets LF line endings on checkout. * text eol=lf # These will always have CRLF line endings on checkout. *.vcxproj text eol=crlf *.props text eol=crlf *.bat text eol=crlf # These are binary so should never be modified by git. *.a binary *.png binary *.jpg binary *.dxf binary *.mpy binary # These should also not be modified by git. tests/basics/string_cr_conversion.py -text tests/basics/string_crlf_conversion.py -text ports/stm32/pybcdc.inf_template -text ports/stm32/usbhost/** -text ports/cc3200/hal/aes.c -text ports/cc3200/hal/aes.h -text ports/cc3200/hal/des.c -text ports/cc3200/hal/i2s.c -text ports/cc3200/hal/i2s.h -text ports/cc3200/version.h -text micropython-1.12/.gitignore000066400000000000000000000010361357706137100160120ustar00rootroot00000000000000# Compiled Sources ################### *.o *.a *.elf *.bin *.map *.hex *.dis *.exe # Packages ############ # Logs and Databases ###################### *.log # VIM Swap Files ###################### *.swp # Build directories ###################### build/ build-*/ # Test failure outputs ###################### tests/*.exp tests/*.out # Python cache files ###################### __pycache__/ *.pyc # Customized Makefile/project overrides ###################### GNUmakefile user.props # Generated rst files ###################### genrst/ micropython-1.12/.gitmodules000066400000000000000000000017411357706137100162020ustar00rootroot00000000000000[submodule "lib/axtls"] path = lib/axtls url = https://github.com/pfalcon/axtls branch = micropython [submodule "lib/libffi"] path = lib/libffi url = https://github.com/atgreen/libffi [submodule "lib/lwip"] path = lib/lwip url = https://git.savannah.gnu.org/r/lwip.git [submodule "lib/berkeley-db-1.xx"] path = lib/berkeley-db-1.xx url = https://github.com/pfalcon/berkeley-db-1.xx [submodule "lib/stm32lib"] path = lib/stm32lib url = https://github.com/micropython/stm32lib branch = work-F4-1.13.1+F7-1.5.0+L4-1.3.0 [submodule "lib/nrfx"] path = lib/nrfx url = https://github.com/NordicSemiconductor/nrfx.git [submodule "lib/mbedtls"] path = lib/mbedtls url = https://github.com/ARMmbed/mbedtls.git [submodule "lib/asf4"] path = lib/asf4 url = https://github.com/adafruit/asf4 [submodule "lib/tinyusb"] path = lib/tinyusb url = https://github.com/hathach/tinyusb [submodule "lib/mynewt-nimble"] path = lib/mynewt-nimble url = https://github.com/apache/mynewt-nimble.git micropython-1.12/.travis.yml000066400000000000000000000267461357706137100161520ustar00rootroot00000000000000# global options dist: xenial language: - c compiler: - gcc cache: directories: - "${HOME}/persist" env: global: - MAKEOPTS="-j4" git: submodules: false # define the successive stages stages: - name: test # define the jobs for the stages # order of the jobs has longest running first to optimise total time jobs: include: # stm32 port - stage: test env: NAME="stm32 port build" install: # need newer gcc version for Cortex-M7 support - sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa - sudo apt-get update -qq || true - sudo apt-get install gcc-arm-embedded - sudo apt-get install libnewlib-arm-none-eabi - arm-none-eabi-gcc --version script: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/stm32 submodules - make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 - make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' - make ${MAKEOPTS} -C ports/stm32 BOARD=B_L072Z_LRWAN1 - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32L476DISC - make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_WB55 - make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBD_SF6 # qemu-arm port - stage: test env: NAME="qemu-arm port build and tests" install: - sudo apt-get install gcc-arm-none-eabi - sudo apt-get install libnewlib-arm-none-eabi - sudo apt-get install qemu-system - arm-none-eabi-gcc --version - qemu-system-arm --version script: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test test after_failure: - grep "FAIL" ports/qemu-arm/build/console.out # unix coverage - stage: test env: NAME="unix coverage build and tests" install: - sudo apt-get install python3-pip - sudo pip install cpp-coveralls - sudo pip3 install setuptools - sudo pip3 install pyelftools - gcc --version - python3 --version script: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix coverage # run the main test suite - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -d thread) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --emit native) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy -d basics float micropython) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy --emit native -d basics float micropython) # test when input script comes from stdin - cat tests/basics/0prelim.py | ports/unix/micropython_coverage | grep -q 'abc' # test building native mpy modules - make -C examples/natmod/features1 ARCH=x64 - make -C examples/natmod/features2 ARCH=x64 - make -C examples/natmod/btree ARCH=x64 - make -C examples/natmod/framebuf ARCH=x64 - make -C examples/natmod/uheapq ARCH=x64 - make -C examples/natmod/urandom ARCH=x64 - make -C examples/natmod/ure ARCH=x64 - make -C examples/natmod/uzlib ARCH=x64 # test importing .mpy generated by mpy_ld.py - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython_coverage -m features2 - (cd tests && ./run-natmodtests.py extmod/{btree*,framebuf*,uheapq*,ure*,uzlib*}.py) # run coveralls coverage analysis (try to, even if some builds/tests failed) - (cd ports/unix && coveralls --root ../.. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod) after_failure: - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) # standard unix port - stage: test env: NAME="unix port build and tests" script: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix - make ${MAKEOPTS} -C ports/unix test - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython ./run-perfbench.py 1000 1000) # unix nanbox (and using Python 2 to check it can run the build scripts) - stage: test env: NAME="unix nanbox port build and tests" install: - sudo apt-get install gcc-multilib libffi-dev:i386 script: - make ${MAKEOPTS} -C mpy-cross PYTHON=python2 - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix PYTHON=python2 deplibs - make ${MAKEOPTS} -C ports/unix PYTHON=python2 nanbox - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_nanbox ./run-tests) # unix stackless - stage: test env: NAME="unix stackless port build and tests with clang" install: - sudo apt-get install clang script: - make ${MAKEOPTS} -C mpy-cross CC=clang - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix CC=clang CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1" - make ${MAKEOPTS} -C ports/unix CC=clang test # unix with sys.settrace - stage: test env: NAME="unix port with sys.settrace build and tests" script: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/unix MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_USSL=0 CFLAGS_EXTRA="-DMICROPY_PY_SYS_SETTRACE=1" test - make ${MAKEOPTS} -C ports/unix clean - make ${MAKEOPTS} -C ports/unix MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_USSL=0 CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1 -DMICROPY_PY_SYS_SETTRACE=1" test after_failure: - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) # minimal unix port with tests - stage: test env: NAME="minimal unix port build and tests" script: - make ${MAKEOPTS} -C ports/unix minimal - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_minimal ./run-tests -e exception_chain -e self_type_check -e subclass_native_init -d basics) # windows port via mingw - stage: test env: NAME="windows port build via mingw" install: - sudo apt-get install gcc-mingw-w64 script: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=i686-w64-mingw32- # esp32 port - stage: test env: NAME="esp32 port build" install: - sudo apt-get install python3-pip - sudo pip3 install 'pyparsing<2.4' - wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz - zcat xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz | tar x - export PATH=$(pwd)/xtensa-esp32-elf/bin:$PATH - git clone https://github.com/espressif/esp-idf.git - export IDF_PATH=$(pwd)/esp-idf script: - make ${MAKEOPTS} -C mpy-cross # IDF v3 build - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V3 :=" ports/esp32/Makefile | cut -d " " -f 3) - git -C esp-idf submodule update --init components/json/cJSON components/esp32/lib components/esptool_py/esptool components/expat/expat components/lwip/lwip components/mbedtls/mbedtls components/micro-ecc/micro-ecc components/nghttp/nghttp2 - make ${MAKEOPTS} -C ports/esp32 submodules - make ${MAKEOPTS} -C ports/esp32 # clean - git -C esp-idf clean -f -f -d components/json/cJSON components/esp32/lib components/expat/expat components/micro-ecc/micro-ecc components/nghttp/nghttp2 - make ${MAKEOPTS} -C ports/esp32 clean # IDF v4 build - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V4 :=" ports/esp32/Makefile | cut -d " " -f 3) - git -C esp-idf submodule update --init components/bt/controller/lib components/bt/host/nimble/nimble components/esp_wifi/lib_esp32 components/esptool_py/esptool components/lwip/lwip components/mbedtls/mbedtls - make ${MAKEOPTS} -C ports/esp32 submodules - make ${MAKEOPTS} -C ports/esp32 # esp8266 port - stage: test env: NAME="esp8266 port build" install: - wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz - zcat xtensa-lx106-elf-standalone.tar.gz | tar x - export PATH=$(pwd)/xtensa-lx106-elf/bin:$PATH script: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/esp8266 submodules - make ${MAKEOPTS} -C ports/esp8266 - make ${MAKEOPTS} -C ports/esp8266 BOARD=GENERIC_512K # nrf port - stage: test env: NAME="nrf port build" install: - sudo apt-get install gcc-arm-none-eabi - sudo apt-get install libnewlib-arm-none-eabi - arm-none-eabi-gcc --version script: - make ${MAKEOPTS} -C ports/nrf submodules - make ${MAKEOPTS} -C ports/nrf # bare-arm and minimal ports - stage: test env: NAME="bare-arm and minimal ports build" install: - sudo apt-get install gcc-arm-none-eabi - sudo apt-get install libnewlib-arm-none-eabi - arm-none-eabi-gcc --version script: - make ${MAKEOPTS} -C ports/bare-arm - make ${MAKEOPTS} -C ports/minimal CROSS=1 build/firmware.bin - ls -l ports/minimal/build/firmware.bin - tools/check_code_size.sh - mkdir -p ${HOME}/persist # Save new firmware for reference, but only if building a main branch, not a pull request - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cp ports/minimal/build/firmware.bin ${HOME}/persist/; fi' # cc3200 port - stage: test env: NAME="cc3200 port build" install: - sudo apt-get install gcc-arm-none-eabi - sudo apt-get install libnewlib-arm-none-eabi script: - make ${MAKEOPTS} -C ports/cc3200 BTARGET=application BTYPE=release - make ${MAKEOPTS} -C ports/cc3200 BTARGET=bootloader BTYPE=release # samd port - stage: test env: NAME="samd port build" install: - sudo apt-get install gcc-arm-none-eabi - sudo apt-get install libnewlib-arm-none-eabi script: - make ${MAKEOPTS} -C ports/samd submodules - make ${MAKEOPTS} -C ports/samd # teensy port - stage: test env: NAME="teensy port build" install: - sudo apt-get install gcc-arm-none-eabi - sudo apt-get install libnewlib-arm-none-eabi script: - make ${MAKEOPTS} -C ports/teensy # powerpc port - stage: test env: NAME="powerpc port build" install: - sudo apt-get install gcc-powerpc64le-linux-gnu - sudo apt-get install libc6-dev-ppc64el-cross script: - make ${MAKEOPTS} -C ports/powerpc CROSS_COMPILE=powerpc64le-linux-gnu- micropython-1.12/ACKNOWLEDGEMENTS000066400000000000000000001243441357706137100163070ustar00rootroot00000000000000The MicroPython project was proudly and successfully crowdfunded via a Kickstarter campaign which ended on 13th December 2013. The project was supported by 1923 very generous backers, who pledged for a total of 2320 pyboards. Damien George, the project creator, is grateful to the people listed below (and others who asked not to be named), whose support of the project help make the code in this repository what it is today. The names appear in order of pledging. 3 Cliff Senkbeil 4 MacDefender (http://www.macdefender.org) 11 Shaun Walker - http://theshaun.com 12 Robert Joscelyne 17 Peter Simon, Germany 18 theNetImp 21 Eamonn Maguire 22 Rob Knegjens 27 Greg, https://www.logre.eu 28 Rick S 30 Norman Jaffe (OpenDragon) 34 UltraBob was here. 35 Geoffrey R. Thompson 36 MrAtoni 40 Proud to be a backer of Micro Python, Phil C. United Kingdom. 42 www.babybadger.co.uk 45 Mert 46 Miles Cederman-Haysom 47 unixarmy.com 52 Proud to be here! Tonton Pommes 54 Espen Sae-Tang Ottersen 56 howang.hk 58 Innovatology 59 Marzsman 63 Tristan A. Hearn 64 Patrick Clarke 65 Bryan Lyon 70 Craig Burkhead 72 Dr Igor Vizir 73 Steve Iltis, @steven_iltis 79 www.giacomo.inches.ch 80 Alexander Gordeyev 81 Steve Conklin www.ai4qr.com 83 n1c0la5 84 Matthew R. Johnson 86 Jeppe Rishede 87 Kirill Zakharenko - Russian Federation 88 beltwaybureau.com 93 felix svoboda 95 Smart 96 Stephen Goudge 97 Dr Richard Whitaker, www.drrich.co.uk, UK 99 Tim Robertson 101 Rudy De Volder, www.devolder.be, Belgium 104 August H., Wien 107 Jason Hsu 109 dstensnes 110 Joe Reynolds (professorlamp) 112 Michael Davies (AU) - @butterparty @spaceduststudio 113 Jim Kirk, Westborough, MA, USA 114 yfnt 117 Even when it looks like someone is reaching for blue sky. Some days you just have to blindly support that dreamer. 118 G. Todd Vaules - todd.vaules.net 122 Gunnar Wehrhahn 124 Eric Masser 126 Vaibhav Sagar 128 Eric Wallstedt 129 Richard G Wiater 130 Toby Nance 132 Michael Fogleman 133 Snepo Research www.snepo.com Gary says Hi! 137 nic gihl 138 Felix Yuan 139 mmhanif 141 James Snyder 144 roddyr2 146 Richard Jones 147 Jon-Eric Simmons 148 Craig "The Coder" Dunn 150 Jesse S (USA) 151 Matt I. - github.com/pengii23 153 Seth Borders - sethborders.com 155 David Zemon (http://david.zemon.name) 156 Garry DuBose 157 Apeiron Systems 158 BAR 160 Jakob Hedman 163 Bryan Moffatt 165 Moises Lorenzo, Tenerife Isl. 166 Erik H. 170 Peter George 171 Nikolas Akerblom 174 Chris (@chassing) 176 Wei-Ning Huang 178 Edd Barrett, UK 179 Alec Langford 180 Shunya Sato 181 Serge GUILLAUME 183 Dr. Ross A Lumley 184 Dorian Pula 189 Tendayi Mawushe 190 SDanziger 191 Sean O'Donnell 192 Kevin McLaughlin 193 Tommy Allen 194 Beedlebub 195 Brad Howes 196 Mike B 200 Aleš Bublík 202 David Dever 206 Danilo Bargen, https://dbrgn.ch/ 209 Brendan Curran-Johnson 210 Piotr Maliński http://www.rkblog.rk.edu.pl 211 SEE Co. - Science, Engineering and Education Co. - www.seeco.us 215 Richard Lancaster 218 Bilbo Baggins from Middle Zealand 219 Ollie Guy 221 Shlomo Zippel 222 Andy Kenny 223 Double-O-ren 226 For the pleasure of @tinproject 229 mfr 230 Eric Floehr 232 Matt from Adp.EU.Com 234 Joanna Tustanowska & Wojciech Bederski 235 Eric LeBlanc 236 Siggy , Belgium 238 Mauro De Giorgi 239 Belug http://belug.ca/ 241 Arik Baratz - @arikb 242 Zvika Palkovich 243 Yves Dorfsman - yves at zioup dot com 244 Asad Ansari, Canada 245 Brandon Bennett 246 Christoph Bluoss 248 Konstantin Renner 249 Abtin Afshar 250 A. Soltani 251 Jon Mills 256 NoisyGecko 258 Lothilius 262 Jay Deiman 263 flo at twigs dot de 265 _Mark_ eichin at thok dot org 267 Adrian Astley 268 aknerats[::-1] 271 @robberwick 272 Daniele Lacamera 273 Thanks to M. Derome 275 Paul Paradigm, Australia 276 lyuden 277 www.SamuelJohn.de 279 John Pinner, funthyme at gmail dot com 280 Michael and Vicky Twomey-Lee 281 Kenneth Ljungqvist 292 Karin Beitins, Australia 295 Nick Johnson 297 Chris Cole U.K. 298 The planet Andete is famous for its killer edible poets. 302 Patrick B (aged 11) 304 Chris Mason, Australia 306 Steven Foster 308 Pat Fleury, Andrew Hodgson 311 @moneywithwings 313 Neil Stephen 314 Cory A. Johannsen 315 Massimo Di Stefano - geofemengineering.it - Italy 317 James Luscher, Madison, Wisconsin, USA 319 Lindsay Watt 320 Nils Fischbeck 324 Peter J. Farrell - Maestro Publishing, LLC - Minneapolis, MN, USA 325 Alex Willmer (@moreati) 328 T.R. Renicker 329 William B. Phelps 330 David Goodger 331 Viktoriya Skoryk 334 JR Rickerson 336 Keven Webb 338 www.hcfengineering.com 341 Larry Lab Rat, Shalford. 342 Rob Hetland 343 Brush Technology (NZ) 346 Jason Fehr 347 Olivier Vigneresse 348 Nano Gennari, me at nngn dot net, Brasilia, Brazil 352 Petr Viktorin (http://encukou.cz) 355 Karijn Wessing (IN2TECH) 356 Arsham Hatambeiki 358 Alvaro Rivera-Rei 360 Nolan & Theo Baldwin 362 Tyler Baker, USA 363 Russell Warren (Canada) 365 Aaron Peterson 366 Al Billings 367 Jeremy Herbert 372 Dimitrios Bogiatzoules, www.bogiatzoules.de, Germany 375 Paul Nicholls 376 Robert F. Brost 378 Aideen (Cambridge, UK) - Very happy backer and follower of this great project 379 Caelan Borowiec 380 Caroline, Canada - carolinesimpson.ca 382 Rikard Anglerud 383 Scott Will 384 Jussi Ylanen 385 @joshbapiste 387 spongefile 389 Keith Baston 392 Holger Steinlechner 394 sent by State mail service 398 N.Pearce, Wells UK - @t #ashtag UK 399 Paid up & stood back;; 401 Mike M. Tempe, AZ, USA 406 Brandon Jasper 407 Dan Mahoney 411 George Bushnell, for use in CPSS 412 Per Konradsson 413 Supported by afinzel 417 Tom Igoe 418 Jonathan Saggau 419 Chris Allick http://chrisallick.com 420 joshuaalbers.com 423 B. Adryan 432 Tim Fuchs 433 steven antalics 434 BezouwenR 435 Andrew Addison 436 Hubert de L'arrêtdubus - France 437 Salim Fadhley 438 Ben Hockley 439 Geoffrey Webb 441 Vladimir Mikulik 442 7 Elements & Troy Benjegerdes - hozer at hozed dot org 443 Pashakun 444 Craig Barnes, UK 445 Andres Ayala 446 Stonly Baptiste (urban.us) 448 Brian Conner 452 Jeremy Blum (jeremyblum.com) 454 Pebble Technology 455 Andrew 456 Jeffrey Allen Randorf, PE PhD 457 J.A.Zaratiegui a.k.a. Zara 459 simon.vc and hack.rs 462 La vida es para vivirla y ser feliz, de esa forma damos gracias por tan gran regalo! 463 Alistair Walsh 469 fun, Ireland 474 martijnthe.nl 479 Andreas Kobara 486 Armanda 487 Richard Myhill 488 Ash Gibbons 489 Glenn Franxman HackerMojo.com 492 Russell Durrett 494 Pieter Ennes 495 Tom Gross, Washington D.C. 496 Mark Schafer 497 Sandro Dutra, Brazil 500 Can Bulbul 501 Chih-Chun Chen, http://abmcet.net/Chih-Chun_Chen/home.html 502 Lost Property Bureau Ltd 503 skakz 504 Chad Cooper 505 Makhan Virdi, mlvirdi.com, InfinityXLabs.com, USA 506 Glenn Ruben Bakke, Norway 507 Alasdair Allan 509 dlbrandon 511 Dr J Garcia, Sweden 513 Tiago Vieira 518 Team ME 519 OBD Solutions (http://www.obdsol.com) 520 @pors 521 Joo Chew Ang 523 garbas 526 http://epoz.org/ 527 J. Sabater 530 José-María Súnico 537 Erfundnix 538 Tontonisback Belgium 539 Greg Benson, Professor, University of San Francisco 542 Thomas Sarlandie aka @sarfata 545 JanTheMan kickstarter at embedded-systems dot craftx dot biz 546 Chuhan Frank Qin 549 Peb R Aryan, Indonesia 553 Johan Deimert, http://www.ldchome.org 555 Conny Sjöblom / Finland 558 AndyboyH, UK 559 Anthony Lupinetti 561 Travis Travelstead 566 Siegfried Boyd Isidro-Cloudas 567 G. Schroeer 568 mmths, http://randomaccessmemory.at/ 570 Andy Miller - NZ.. 571 Rodolfo Lara from México 572 Gary Patton Wolfe 574 Vend-lab Russia 578 Super Job! FXF 579 Oliver Heggelbacher, www.kickdrive.de 581 James Husum 585 David Lodge 587 Tess 592 PR Taylor 593 6306665119 598 Jorg Bliesener, Brazil - www.bliesener.com 602 Rodrigo, Germany 605 Tanja Kaiser, www.mrsminirobot.de, Germany 606 Franco Ponticelli - www.weblob.net 608 Piet Hoffman 609 Paul Cunnane 610 Balazs Kinszler 611 Nathan Ramella (synthesizerpatel) 612 Tyler Jones (squirly) 613 James Saffery 614 Christoffer Sjowall 615 Iman Shames 616 Thomas Dejanovic, Australia. 618 Tom Alker 619 Matt Davis, UK 621 Design for the real world! @UXnightingale 622 Budd Van Lines 624 __Gio__ 628 Chew Kok Hoor 630 Santiago Alarcon, Thanks Damien for Micro Python 632 hardtoneselector 633 supported by Chris Bunker 634 Sebus - France 635 Mechanical Men Sweden 638 A Fellow Electronics Enthusiast 639 Stan Seibert 642 Dave Curtis 652 Sebastian Ross - www.ross.sx 653 Julien Goodwin 654 Reinoud de Lange, the Netherlands 655 carl beck 659 John Gaidimas 660 Tyler Eckwright 661 Keith Rome (Wintellect - http://www.wintellect.com/blogs/krome) 662 Kashev Dalmia - kashevdalmia.com 666 Alberto Martín de la Torre 667 Niels Kjøller Hansen 668 pmst - Italy 671 Sergio Conde Gómez (skgsergio) 672 Micromint, www.micromint.com 673 Xie Yanbo, China 675 Thank you 677 Kacem Ben Dhiab 679 CornishSteve 680 Daniel Wood, Warrington, UK. 682 Greg "GothAck" Miell 688 Matt Williams & Sam Carter 691 Frédéric Lasnier 694 Tim K 697 Joshua Clarke, Guernsey! 700 daynewaterlow.com 703 Scott Winder 704 @DepletionMode 707 Maria Yablonina 710 Roger Hausermann 713 Crazy_Owl 714 mike hardin usa 717 C. Towne Springer 719 ursm gruesst euch 720 madnis 727 http://itay.bazoo.org 729 @0atman 730 Jerry Gagnon 732 Emmanuel Boyer 738 suspenders 739 Roland Frédéric - http://www.creativeconvergence.be/ 742 @herchu 745 Riley Lundquist 746 Go LOBOS 749 João Alves, http://jpralves.net, Portugal 751 Nick Porcino 753 Jack E. Wilkinson, Texas, USA 754 @rcarmo on Twitter/Github 758 Matt Manuel, www.mattmanuel.com 759 Padraic D. Hallinan 760 Rob Fairbairn 763 Zac Luzader 768 Sam Shams 773 terje nagel, dk 775 Luc LEGER 782 Luis M. Morales S. 785 Charles Edward Pax 786 Daryl Cumbo 787 Zephyris13 788 Wonderful project. 792 Sylvain Maziere 794 Milen 795 Robert Mai, Germany, hsapps.com 797 Angelo Compagnucci angelo.compagnucci at gmail dot com 801 Long Live Micro Python, airtripper.com 804 António M P Mendes 805 Marc Z. 809 Anoyomouse 810 in memory of Dan J. Schlacks III 817 Peter Froehlich - http://werk-schau.blogspot.com 818 Ahmad Albaqsami 821 Peter Lavelle (http://solderintheveins.co.uk) 822 Manuel Sagra de Diego http://manuelsagra.com/ 823 Sam Wilson 824 Khalis 825 c't Hacks 828 Georg Bremer 830 Ward en Sanne (WenS) 832 javacasm http://www.elcacharreo.com Spain 833 mctouch 835 Bruce Schreiner @ www.stevenscollege.edu/electronics 836 Jonas 839 Nick Ludlam 840 Patrick_Law, UK 843 Alex Crouzen, UK 848 Ben Banfield-Zanin 850 Wouter Slegers, Your Creative Solutions 851 Fred Zyda 853 Gianfranco Risaliti 854 Ron Hochsprung 858 Vianney Tran 862 Aaron Mahler - http://halfpress.com 868 Stephan Schulte, Germany 869 Kenneth Henderick 872 DaveP (www.davepeake.com) 873 Markus Schuss, Austria 876 Kyle Gordon, http://lodge.glasgownet.com 877 Joseph Gerard Campbell 881 Thanks for the board. Good luck to you. --Jason Doege 883 Garet McKinley 884 www.magtouchelectronics.co.za 889 Ben Johnson 896 Ruairi Newman 897 Gemma Hentsch 902 Alexander Steppke 906 Stephen Paulger 907 Martin Buhr, http://lonelycode.com, UK 912 Dale Drummond 913 Go Utah State 918 Jarturomartinez, Mexico 921 Barry Bourne Micro Python Supporter 923 Andreas Bolka 927 Thanks Susan, Tom, Paul, and Mark! 935 http://wall-y.fr 937 Eero af Heurlin, Finland, https://github.com/rambo/ 938 Guillaume DAVY 941 Alexander Steffen 942 Janne "Lietu" Enberg 945 Luca 'loop' de Marinis - https://github.com/loop23 946 Andras Veres-Szentkiralyi http://techblog.vsza.hu/ 948 Florian flowolf Klien (http://blog.flo.cx) 949 nickyb 951 Mark Walland, England 952 Ian Barfield 953 Andrew Murray, UK - eat my code - http://links.bloater.org/micropython 955 Kyle Howells 956 Chris Cadonic 957 LCS, USA: scripting___/||\===/||\___embedded 958 Sven Wegener 963 Kean Electronics http://www.kean.com.au/ 964 Beandob 965 Don't feed the troll. 966 Alexis Polti (http://rose.eu.org) 969 Scottyler 971 The Dead's Own Jones 974 Evseev Alexey 976 Arnaud 978 Jannis Rosenbaum 980 paul at fontenworks dot com 981 John Griessen ecosensory.com USA 982 Tobias Ammann 983 Simon V. 984 JaWi 987 Ergun Kucukkose 989 Jonathan Piat France 990 Steve Pemberton 993 Aaron Robson 994 Antoine Authier 995 Thomas Winkler, Austria 997 Jannes mit dem dicken Pannes 1001 Joe Baker 1002 Jon Hylands, Canada (blog.huv.com) 1004 Mike Asker (aka mpymike) 1007 Charles V Bock - Charles at CharlesBock dot com 1010 Remember June 4th, 1989 1012 Stuart Marsden 1013 Herbert Graef, Stuttgart 1014 Arthur P, USA 1015 John Hall & Jeremy Armijo 1017 Luciano Ramalho, Python.pro.br 1018 Quentin Stafford-Fraser 1019 Marcin Walendzik Ratingpedia.eu 1020 Wincent Balin 1022 rbp 1024 Frank Carver ( www.frankcarver.me ) 1026 Peter Farmer, http://geekytronics.com/ 1029 Rubens Altimari 1033 Sebastian 1035 Gerli, Estonia 1036 Maurin, Switzerland 1037 Kevin Houlihan (http://crimsoncookie.com) 1039 Jon Green of Adeptium Consulting (www.adeptium.com) 1040 Eirik S. Mikkelsen 1042 Jogy Sam 1043 GGG 1045 Sean E Palmer, epimetheon.com 1049 Greg O'Drobinak, USA 1050 RaptorBird Robotics Inc 1051 Desmond Larsen-Rosner 1056 Crusty 1057 ArthurGuy.co.uk 1059 Melissa-Ivan, 14/04/2013 1064 Enrico Spinielli, https://github.com/espinielli 1066 Dave Snowdon 1067 Martin P. Hellwig 1070 Carl Clement 1074 Paul Taylor 1076 Pandemon 1082 Thrilled to support Damien's effort to put this together: there will no doubt be many applications for this effort and many enhancements and ports.. 1083 Oddvar Lovaas 1090 BenScarb 1093 Www.qualnetics.com 1094 Manny Muro - Now Python can RULE from below as it does from above! PYTHON RULES!!! :) 1095 Michael Grazebrook 1098 Mark Shuttleworth, UK 1106 wyzzar 1110 Luca Zanetti 1112 Carl A Fagg 1115 Adam Klotblixt 1118 Breawn 1122 pippyisatruck 1124 Andrew "ClothBot" Plumb 1126 Realise the projects your heart beats for! Sven Wiebus (http://wiebus.tumblr.com) 1128 Citius Systems 1130 Benjamin & Reuben Fuller 1131 aglimme 1133 John Becker 1135 Mark Drummond 1138 JHProuty 1141 Lars Olsson Sweden 1144 daisuke, http://dkpyn.com 1145 Chris Pawley - http://www.pawley.co.uk/honey/ 1147 Daniel from EzSBC.com 1149 New York Mortgage Exchange NYME.COM 1150 Herb Winters,USA,www.ecs87.com 1151 renttu 1159 Joe Rickerby 1160 john guthrie 1161 PUBLIC 1163 dobra-dobra 1164 Neil Reynolds, Staffordshire 1165 GEHoward 1166 Frank Delporte 1167 Bauer Brauner Enterprise 1168 Francisco Mardones 1169 Ryan Kirkpatrick, @rkirkpatnet, http://rkirkpat.net/ 1170 Krister Svanlund 1174 Derek Patton Pearcy 1177 Roger Olsson, Sweden 1179 Jan-Niklas Braak 1180 Pete boy 1181 MilenX 1182 Ubbe Larsson 1183 Simon Freethy 1184 Daniel Andersson 1187 Daniele Procida 1190 Adrian Duke 1191 Pauline Middelink 1193 Ted Gueniche 1197 Craig Knott, University of Queensland, Australia 1198 Jamie Mackenzie - Australia 1199 ravenoak 1200 LucaP Luni Italy 1203 jacanterbury 1205 Bleachin, www.rhyspowell.com 1207 Supported by Andrew Maier via Kickstarter 1208 Rob, http://robjstanley.me.uk 1210 George Gingell 1213 Chris Elleman 1215 Jack Barham - @jackbarham - http://jackbarham.com 1221 Kyle Dausin 1222 Ben Lucker 1225 Gareth cheesewhisk Evans 1226 Jacob Forsyth 1227 Olof S - Germany 1231 Brasil 1233 glaslos 1234 Will Cooke - http://www.whizzy.org 1236 Andrew Wright - Canada 1239 Resourceful Robin 1240 Jay O'Neill @jayoneilluk 1241 Dennis G Daniels 1244 J. Peterson (www.saccade.com) 1245 Chipaca 1246 Nicko van Someren 1247 C. Cumbaa, Canada 1248 Gyro Gearloose was here 1249 Magnus Ericmats, Sweden 1253 Steve Wilson 1256 Adrian Bullock 1258 Sarevian & Longwall 1261 Skipp Savage 1265 Eric Nahon 1267 Stuart Dallas / 3ft9 Ltd 1270 USA 1271 Oliver 1277 jeffmcneill.com 1278 alnjxn 1283 Marc Liyanage 1285 Christian Lange 1286 Bryant Paul Umali from the Philippines 1290 W.B.Hill, Norwich, UK 1292 Michael Karliner 1293 Oli Larkin 1303 A. Pockberger 1304 dc - bagel 1305 Thadeus Arnel 1308 technoweenie 1309 Liam Welsh 1313 Per Thorell, Sweden 1314 peterlee 1316 Dustin Mierau 1317 tech-zen.tv 1320 Cheers from IDF :) 1322 www.a-d-k.de 1323 rixx 1324 @jlev 1325 e2e4 1328 Thomas J. Quinlan, London UK 1329 Don Bone 1331 Narayanamurthi 1333 PGS_Astra-ProjeX_Wilts 1337 Mark Schulz & Phillip Long, CEIT, The University of Queensland 1340 Tiegeng (Tim) Ren 1344 EMR_1344, DE 1348 Matt Ward, Nottingham 1351 Rupert 1352 Cory Li - http://cory.li 1354 Jim Davies, Brighton, UK 1355 Jon Watkins, UK 1356 Thomas, www.bitmix.de 1359 Markus Gritsch 1362 Carl H. Blomqvist 1371 Brian Green 1374 Ben Merryman 1375 O'Dea 1376 Josh Trujillo 1378 Daniel Halloran 1379 another_martin 1383 Thanks for innovating! 1385 CoderDojo Malahide 1397 Jacob Z 1398 Staffan Hillberg 1399 http://kim.ht 1402 Can't wait to plug it in! 1403 Márton Szinovszki 1405 sellorm says 'Hi!' 1406 Thomas Provoost 1411 Clive Freeman 1412 Norman Thomas 1415 Javier Llopis 1417 Ho Man Fai 1418 Anders Helland 1421 Richard lavanture 1425 Alan Churley, UK 1426 Robert'); DROP TABLE Students;--unicode is fun! 1427 Go Illini! 1430 MicroPy FTW 1431 Bryan Morrissey, www.browninnovations.com 1436 Krzysztof Chomski, Poland 1437 WellAware (USA) 1441 Tomas Hau 1443 Paul Way 1444 Benjamin Anderson 1445 Andrew Bates 1446 Davide Di Blasi 1451 Mathias Fischer 1453 Drexore, NL 1454 Marek Mroz 1455 Mark Easley Jr. - USA 1457 Joshua Warren 1459 Rohan Menon 1460 Paul Sokolovsky 1461 Chris Foresman, @foresmac 1475 USI 1478 Chris Emerson 1479 Ph. Truillet, France, http://www.irit.fr/~Philippe.Truillet 1480 WAB3 1481 Lucidologia.pl 1482 Ed Hardebeck | www.hardebeck.us 1484 Ludovic Léau-Mercier, www.coriolys.org, France 1487 BLUEBOBO 1488 Berno Kneer, Germany 1491 Julian Eccli 1494 Batman 1495 Manuel Núñez Sánchez 1496 Millie and Sadie Smith 1499 Ronald Eddy 1500 SynShop Las Vegas 1503 This is really cool. - Jack Conway 1505 Victor Suarez, Argentina 1507 Renesas Electronics America 1509 Team 1513 A. Lamborn KD0ZFY 1514 olifink 1520 mike at sustainable-opportunities dot com 1521 luis almeida, Teresina - Brazil 1523 Muhammad Jamaludin 1524 Sdlion 1525 Charles Rogers 1526 Diego M. Aires, Brazil 1529 muwatt.com 1532 Proud supporter of microPython 1535 Jesus J. de Felipe 1536 slminneman.com -- Wow, an acknowledgement? ...really? 1538 Mike (Meski) Smith 1541 Piero Steinger 1545 Alex Rembish (https://rembish.org) 1551 Sergey [BuG2BuG] Sobko, Russia 1553 Serge Krier 1556 Luuk Derksen 1561 Jimmy Caille (CH) 1562 Jesús Leganés Combarro "piranna" 1564 Viacheslav Olegovich Savitskiy 1565 Jamie Whitehorn 1567 Bagge Carlson 1568 Milan Cermak 1569 Matthias Lemp 1570 BOFG 1571 Johan Elmerfjord, Sweden 1573 Matt Finch • fnch.io 1574 Jean-Francois Paris 1575 Florian Franzen, Germany 1576 doganowscy.com 1579 Stan Yamane 1580 William Cirillo 1583 David Dibben 1584 Nicolás, Amelia, Luli y alecu 1586 Alex W 1591 Livia Maria Dias Tavares 1593 d freymann chicago il & his australian shepherd jaldi 1594 Barnstorm Studio, LLC 1595 Sashi Penta 1597 tflhyl 1598 clacktronics 1599 j3hyde 1600 Rik Williams 1602 Valeriy Van, Ukraine, w7software.com 1603 Louis Taylor - https://github.com/kragniz 1606 What's the derivative of (6.022 x 10^23)x? That's A(n)mol 1611 Bailey & Brayden Yoong Policarpio 1613 William Bettridge-Radford 1617 Urbane Jackson 1618 Henius 1622 Alister Galpin, New Zealand 1623 Marco Bertoldi 1627 Julian Pistorius 1628 www.neotral.com 1632 ChrisB 1633 Norbini 1634 Eric Rand at Brownhatsecurity.com 1636 Benjamin Eberle 1637 MG Projects bvba, Geert Maertens, Belgium 1640 Robson dos Santos França (Brasil) 1642 Udine 1643 Simon Critchley 1644 Sven Haiges, Germany 1646 "silicium" ("silicium_one", if "silicium" is busy) 1648 Andy O'Malia, @andyomalia 1650 RedCamelApps.com 1652 Christoph Heer 1653 AlisonW 1654 Yannick Allard (Belgium) supported this project. 1655 Andy Pointon, UK 1660 Diego Cantalapiedra 1664 Pepillou 1670 Sonny Cannon 1671 Rick W 1672 David Chan, USA 1674 Philip Rowlands 1675 dieresys 1676 T.R. Fullhart 1683 Oleg Sidorkin 1686 Tatsuro Yasukawa 1687 Brad Smith, Somerville MA, USA 1688 kristoffervikhansen.com 1690 Nice Project de W6AKB Alan Biocca 1691 Hiss Hisss Hissss Hiss Hiss Hissssssss 1692 Alan Kennedy 1698 ElChessu 1701 Flower Craswell 1702 David Fontenot 1707 To innovation & creativity. Tony J Winter 1708 Joakim Hentula 1711 Michael Schaefer 1713 Brody Radford ~ www.brodyradford.com 1714 Charles Durrant 1715 Rodrigo S. 1718 Dima Shylo 1719 Jiahao James Jian 1722 Helen Wilson, Christ's Hospital 1726 Martin Aule, http://hackest.org/ 1727 İsmail Etem Tezcan, Rasteda 1728 Charlie "Blackfrog" Sizer 1729 Matloob Qureshi 1730 Travis Saul http://travissaul.com 1731 Michael Cavins 1733 Peter Köllensperger, Norway 1734 Anne Harrison 1736 Peter Bradeen 1739 Fredrik Luthander 1740 Nick LaRosa 1744 Aladuino 1745 dgrebb 1746 Truls Unstad 1748 Jesus Saves 1750 Andy Stannard (@rockmonkey) 1751 Daniel Atkinson 1755 John Potter 1758 Ian V 1760 David Leinbach 1761 nemec-automation.com 1765 Supported by JoW with Hardwired TCP/IP from www.WIZnet.eu 1767 misskniss, Boise Idaho. It is our responsibility to code the freedom we want to see in the world. 1768 Jeff Vahue - Knowlogic Software Corp. 1769 Pat Molloy 1770 Greg Maxwell gregmaxwell-at-mac-dot-com 1771 Rich Robinson 1773 Ken Corey @ flippinbits.com 1782 Acknowledged 1785 Optimized Tomfoolery 1791 Nontakan Nuntachit, Thailand 1794 Rasit Eskicioglu - Canada 1795 Simon Elliston Ball 1796 pfh 1798 John W. C. McNabb 1799 Frank Sanborn 1803 Morgan Hough 1804 Sorcha Bowler 1805 http://www.WayneKeenan.info 1806 HBEE, hbee.eu 1807 Deadlight 1809 www.danenet.org 1811 Sergey Nebolsin 1813 Threv 1817 dynsne 1818 David Wright 1819 John Warren 1821 I wanted Erlang! (╯°□°)╯︵ ┻━┻ 1825 Howard R Hansen 1828 Kevin Schumacher 1833 Matthias Erll, Sweden 1836 Matt Graham 1837 thedawn 1838 Ruby Feinstein 1839 Gustavo Muñoz (timbergus) 1840 Ian Paczek 1841 Köteles Károly, Hungary 1843 Tobias Sette Ferreira 1846 x4FF3 <3 microPython 1847 Enrico Faulhaber (Germany) 1850 jolan00 1854 Red Harbinger Inc 1855 Noman 1858 @DerLinkshaender 1863 Jon Woodcock 1864 Elmo, hakkerikartano.fi 1865 Imaginals 1866 Sam Hathaway and Rachel Stevens 1874 Remo Sanges, SZN, Italy 1875 Devraj Mukherjee 1876 an Embedded fan 1877 Peter Huisers 1878 Kin-Wai Lee (Malaysia) 1879 Samuel Hawksby-Robinson 1881 R. Stock 1886 Randy of Capistrano street backed Damien's MicroPython! 1887 Rogério Bulha Siqueira - www.esd-talk.com - Brazil 1889 NickE is happy to support such a worthy project! 1892 John Boudreaux 1894 Riverfreeloader 1895 Jose Marcelino http://metavurt.net 1896 T Britto-Borges 1899 DannyWhitsonUSA 1904 José Iván Ferrer Ruiz. 1905 Tom Loredo 1906 Gregory Perry USA 1908 josephoberholtzer.com 1910 Michael Klos, USA 1912 Adam Mildenberger 1913 R Anderson 1914 Nikesh, USA 1915 Bogdan Chivoiu, Romania 1916 Scott C. Lemon, USA 1918 Konstantin Ufimtsev (@KestL) 1919 Benny Khoo 1922 Nicci Tofts 1925 Joshua Coxwell 1926 Franklin Hamilton 1928 Peter Korcz 1929 Leroy Douglas 1930 A ナルと fan from Nigeria who likes smileys, here's one for good measure :) 1931 Kimmo Lahtinen, Finland 1932 http://staybles.co.uk 1937 The Olivetti's: Emanuele Laura Nausicaa Sibilla Ettore 1940 Pascal Hirsch 1942 cbernander, Sweden 1944 Enrico M. 1947 Dinis Cruz 1949 Jonathan Greig, http://embroidermodder.github.io 1950 Andy Bower 1952 Gerard Hickey 1953 Fabrice BARRAL was here ... 1955 Pieter Röhling 1957 uomorando, Italy 1959 Acacio Cruz The MicroPython project raised further funds through a second Kickstarter campaign that was primarily targeted at porting the code to the ESP8266 WiFi chip. The campaign ended on 2nd March 2016 and gained the support of 1384 fantastic backers who believed in the project and the principles of Open Source code. Those backers who asked to be named are listed below, with an asterisk indicating that they also supported the first campaign. * 1 Gabriel, Seattle * 2 @robberwick * 6 Dave Hylands 7 Les, UK 8 Ryanteck LTD., UK 10 karlsruhe, HU * 11 Turbinenreiter 13 Ben Nuttall, UK * 14 Bryan Morrissey, MA, USA * 15 Jogy, Qatar * 16 BOB63,IT 19 ReaBoyd * 20 Andrew, MK * 21 chrisq, NO 22 Pascal RENOU, France 23 Javier G, ES 25 Forrest, US 26 Filip Korling, Sweden 27 roberthh - Rhineland * 28 Herbert Graef, Stuttgart, thanking the MicroPython Team for this great project * 29 johnsonfamily38, UK 30 CympleCy 31 OJ, PK 32 Daniel, SVK 33 Shabaz Mohammad * 35 Kenneth Henderick, BE * 37 Daniel Mouritzen, DK 39 Torntrousers, UK * 44 Scanner 45 Radomir Dopieralski 46 Nick, UK * 47 Jon Hylands, Canada * 48 Ben Barwise Clacktronics 50 Rob Kent, UK 52 Carlos Pereira Atencio 54 Andy, UK * 55 WMinarik, Canada 57 Hauffe, Germany 58 HyperTaz, IT * 61 Michael Kovacs, AT 62 Erick Navarro, PE 69 Karan,US * 71 Nick B, UK * 72 Anthony Lister, NZ * 73 Bryan Lyon 76 Miguel Angel Ajo, ES * 78 Sebastian, Regensburg (GER) * 80 iv3unm 81 Thierry BÉNET, FR 84 Jannis, Germany 86 Nathan Jeffrey 88 Cory Benfield, UK 90 Carlo, IT * 91 Wojciech Bederski (@wuub) 92 Steve Holden, UK 93 Tristan Roddis, UK 94 Balder, Sweden * 95 Rhys, UK 96 Rowan, UK * 97 Gary Martin, Edinburgh * 100 Mikael Eiman * 101 torwag * 102 Craig Barnes, UK 103 Andrea Grandi, UK 105 Piers, UK * 109 Wayne Keenan 110 makuk66 111 Hamine,DZ 112 Arahavica,JP * 113 Bill Eubanks, USA 114 Jonathan, UK 115 ghickman * 117 Christian Lange, Germany 119 Jonty Wareing 121 TheHetman 123 Víctor R. Ruiz, Spain * 124 Laurynas Paukste, Norway * 125 Taki 126 André Milette, Canada * 127 Ron Cromberge,NL 128 IJ, Thailand * 130 IGOR VIZIR 132 Bill Saturno 134 scibi 136 Timbo, AU 137 Raphael Vogel, DE * 139 jasonkirk, US 141 Linköping, Sweden * 142 Dugres 144 DarioS, UK 146 NelisW * 148 _Mark_ * 149 Folke Berglund, Sweden 150 Deniz Dag/Belgium 152 Jacques Thomas 153 Dag Henrik, Norway * 154 Alexander Steppke 158 stavros.io * 161 Seong-Woo Kim, KR 162 Aaron H, Seattle 164 Iwan, CZ 165 Jenning, DE 167 Oliver Z, Germany * 168 Chris Mason, Australia 169 Fabio P. Italy 171 Jonathan, Ireland 173 Philipp B., DE 174 Mancho, IT 175 Mikkel Sørensen, DK 176 Raphael Lullis * 177 Tim, China 179 JasperS, NL 180 Scott, AU 181 Roland Kay, UK 182 Adam Baxter 184 Hugo Herter 185 Simon AM, Malta 186 Leif Denby 190 Maxious * 192 Guido, GER * 193 Pierre Rousseau, Canada 195 Pete Hinch * 198 KoalaBear,USA. TRUMPED 2016! * 200 Pimoroni, UK 201 jpwsutton, UK 203 Felix, Sweden 204 Dmitri Don, Tallinn Estonia 205 PeteDemiSwede, UK * 207 Serge GUILLAUME 208 Gurtubay, ES 209 Geir-Olav, NO 210 RayDeo, Germany 215 DIYAbility 216 Josef Dunbar, USA * 217 Enrico, BE/IT 219 Damian Moore, UK 220 Wayne and Layne, LLC 221 The Old Crow, USA 224 Hackscribble, UK * 225 Alex March, UK 226 @rdslw 227 Mike, Canada * 228 Adrian Smith 229 Dinu Gherman, Germany 230 Tinamous.com * 231 Nikesh, US * 232 chrisallick.com 234 Daniel Von Fange * 235 Michal Muhlpachr, CZ * 236 Petr Viktorin 237 Ryan Aldredge 238 Patrik Wallström, SE * 239 MobiusNexus 240 Stray, US * 241 BOFG, no 244 Issac Kelly * 247 David Prime 249 James Marsh, UK * 250 BezouwenR 252 Avinash Magdum, India 253 Greg Abbas, Menlo Park CA 254 Jorge, ES 256 JohanP, swe * 258 Ben Doan 259 Jan van Haarst, NL * 263 JoshT, Los Angeles 264 cstuder, Switzerland 266 Jon Armani * 270 Liam Welsh 271 Jason Peacock 272 Alejandro Lopez 275 Dan O'Donovan, UK 276 N1TWC 277 Roland Tanglao, Vancouver 278 Twpsyn 280 Robert, ME-US * 282 Thomas, UK 283 Jeff Schroeder, USA 284 Paulus Schoutsen * 287 Neon22, NZ 290 kbmeister 291 Gary Hahn 292 Dave Matsumoto, USA 296 Sam Lee, SG 304 Poul Borg, Denmark 307 MightyPork 308 Dale * 312 Anton Kraft, Germany 315 Kism3t, UK 317 NateM * 318 N&T, Calvijn Meerpaal, NL 322 Andreas Monitzer 323 Rikard, SE 328 Olaf, DE * 329 John Boudreaux 330 DOCE, Germany 331 feilipu 332 Stefan Schwetschke 333 Wayneji, NZ 337 Alain de Lamirande, Canada 338 Hori, TW 340 Azmodie, UK 341 Lygon, UK * 342 JRM in STL, USA 344 R Colistete-Jr., BR * 345 ChristianG, DE 347 Nis Sarup, DK. 350 Nickedynick 351 Dazza, Oz 352 lispmeister, NL 355 Tomas Lubkowitz, SE 357 Mark, UK * 358 Team ME 363 Papahabla 364 Greg Chevalley 365 Maic Striepe, Germany 369 Ian McMahon 371 A. DARGA, Fr 372 Ernesto Maranesi, BR 373 Steve Lyon 374 James Cloos 375 Bas Zeppenfeldt, The Netherlands 378 Pycom Ltd 380 Wade Christensen, USA 382 Justin Wing Chung Hui, UK 383 C Paulson 384 Ian Tickle 386 Danny, Seattle 388 Erik Moe, Chicago, IL * 389 Eric B. Wertz, USA 390 Michael. CH 391 Christopher Baughman 392 James Churchill 393 Rob, DC 395 Whee Min, Singapore * 396 Jason Doege, TX 401 MrFish 403 Thejesh GN 404 Markus, Sweden 405 AMR, Spain 407 Svet, ES * 408 Thoralt, Germany 409 Emil, Sweden 410 David Moloney, ireland 411 Marco S, DE 415 Peter W., Austria 417 emendo A/S * 419 Kalestis, Switzerland 421 Ondra, CZ 422 Elheffe 423 thinkl33t, UK 424 TonyF 425 Herr Robert Linder, PA, USA * 426 Anders Astrom S(E|G) * 428 Jussi Ylanen, CT, USA 431 Neil H., USA 434 Rod Perez, MX 435 Carol, US 436 Gina Haeussge, DE 438 Weilinger, GER * 439 Ron Ward, Australia 441 Rex, UT, USA * 444 Slush, CZ 445 Bruce, Florida * 448 Patrick Di Justo 449 ScubaBearLA 450 Mike Causer, Sydney AU 451 Joel Fries, USA * 452 Andrew Bernstein, US 454 EAS, Seattle, WA, USA * 456 Christopher J. Morrone, USA * 457 Anthony Gilley, Sweden 458 Andre Breiler, DE * 460 Fuffkin, UK * 461 adent, CZ 462 Samuel Pickard 463 Mirko, Germany * 464 Ramin/US 465 Mike, Grenoble 466 Rolf, DE * 467 Dave Haynes * 469 Mac Ha, Vietnam * 470 Enno, DE * 473 Smudo, DE * 474 Duncan, Scotland 475 Chris, UK 476 Peter Groen, NL 478 Gertjan Geerling, Nijmegen * 479 Benjamin Eberle * 480 Mechanical Men Sweden * 482 Rémi de Chazelles, FR 483 mager, Bremen 484 jurekh, NL * 485 Craig Burkhead 487 JohanHartman, SouthAfrica * 489 Viktor, NL 491 Jean-Denis Carre 492 Jesse, Canada 493 Alex C. MacDonald, USA * 494 GustavoV, MX 495 Sebastian, Berlin 497 Bernard, Feluy * 500 Ron H, USA 501 Gregg "Cabe" Bond, UK 502 Colin, NI 504 Robin, USA * 507 pkropf * 510 6LhasaCo Canada 511 Tom Sepe, USA 513 Andrew McKenna 515 tom46037 516 G2, USA * 517 Pauline Middelink, NL * 518 Brush Technology, Ltd 520 Pierre Meyitang, USA 521 Stephanie Maks, Canada 526 John McClain * 527 Sigadore, US 528 Richard Hudspeth, US 530 Martin, Austria 531 Stephen Eaton, Australia * 533 RJCE, UK 535 Teiste, Finland 536 Pio, UK 537 DirtyHarry, DE * 540 Dom G. UK * 541 Nial, UK 543 Andreas, AUT 545 WisdomWolf * 549 MrMx,ES 552 Daniel Soto, Landscape. 554 Claus Fischer, DK 557 Aleksi Määttä 560 Justin Wilcott, USA 562 LoneTone, UK 567 Cameron, US 568 Dirck, Germany 569 Michael Keirnan 571 Harry, CN * 572 Ward Wouts 573 Dan Anaya, USA 574 Ben Bennett 575 nirvana2165, US 576 PDG, BZH * 581 Visit, Thailand 582 John Carr, UK * 583 Klankschap 587 jacky,FR 588 JD Marsters 591 Ryan Jarvis, US 595 Claudio Hediger, CH * 597 Bambam, Sweden 598 Timothé, FR * 599 Luís Manuel, Portugal 601 Eric, DE 602 Olaf, Cambridge, UK * 603 Tim, Dubai 604 Tyndell, US 606 Ciellt AB, SE 607 Ömer Boratav 609 Guy Molinari, US 614 Freek Dijkstra 615 Carlos Camargo CO 616 Michael Nemecky, Norway 618 Ovidiu G. 619 arobg, USA * 621 Geoff Shilling, US 623 EliotB, NZ 624 slos UK 625 Montreal, CA * 626 Peter Korcz 627 Kodi 628 Jim, Valdosta, USA 629 Sander Boele, NL 630 Max Lupo 631 Daniel.B, Newcastle Australia 632 Andrés Suárez García, Vigo (Spain) 633 Rens, NL 634 Max Petrich, DE 635 Fabian Affolter, CH 636 Cadair * 637 Mike Karliner 638 Daniel T, UK 639 Mark Campbell, UK 640 James S, Australia 641 PBTX! * 642 amaza,SP 644 se4mus * 645 Alexander Steffen * 647 Jim Richards Maine, USA 649 Doug D, US 650 Keaton Walker * 651 Scott Winder, USA 653 Jeff Fischer, USA 654 Andrej Mosat 655 Mohd Faizal Mansor, Malaysia 657 Mike "Cutter" Shievitz, US * 658 Daniel Andersson, SE 659 Alexander, NL 660 François, CH * 661 AndrewS, UK 662 Denisae, PT 663 KC8KZN 664 Angelo, Wales 665 BlueberryE, Germany 667 fvlmurat 668 Adam Wilson 675 Ulrich Norbisrath (http://ulno.net) 676 Daniel, Portland OR * 677 Andreas Lindquist, SE 680 Jason, NL 682 lapawa, GER 683 John Batty, UK 685 Addy, Netherlands 686 Marc, CA 690 APapantonatos 691 gmorell, US * 692 Jamie Mackenzie, Adelaide, SA * 693 Dave Dean, US 697 woojay, US 698 Webabot, NY * 699 Jason Fehr, Canada 700 Hadi (AU) * 701 Abraham Arce * 703 Must Be Art 712 Thanks for the great work!/datax-holding/Stuttgart * 714 Thomas Pr., BE 715 Black Country Atelier BCA 718 Don W, Arlington VA 721 Xavier C. (EU) 722 Chad P. Lung, U.S.A 726 Alexander Lash (@lexlash) 727 Sven, MX 728 Terence, PL * 730 Mauro De Giorgi, USA 735 Jay Ward, Canada 736 Fabian Topfstedt, AT 739 sjoerdDOTcom 740 David, Australia 743 Michael Niewiera, Germany 745 cbenhagen 746 berserck, CH 748 Lars Hansson, Sweden 750 Landrash 751 Richard B., CT USA 752 Neil Chandler, UK * 753 John Griessen US * 755 Caminiti, Mexico 757 Mikael Trieb, Sweden 760 S1GM9, MX 761 Dave C, US * 763 Su Zhou, China 765 Caitlyn - USA 769 Will, NZ 770 CJB,UK 771 Victor Claessen, NL 772 Antal, CH 773 Tokyo, Japan * 774 Join Business & Technology AB, Sweden 777 Overspeed Innovation * 778 Bruce, Chanute KS 779 TOPALIS, RO 780 klaas2 781 Matthias Schmitz, Berlin 783 Jan Studený wishes "Python everywhere" 788 Ian, USA 789 Mark K, UK 791 DerFlob, Germany 792 Staffan Johansson, Sweden 793 Stefan W., DE 795 Mark S. Harris, Small Dog Electronics 796 Kittikun, TH * 798 aerialist, Japan 799 Sweta * 800 Mark Shuttleworth 802 Kim Thostrup 803 Andy Fundinger 810 Matt Vallevand, Detroit MI 813 Jim McDonald 816 Rob Dobson 817 Rafał Zieliński, PL * 818 Shaun Walker, AUS 819 Timothy R, Belgium 820 clem 825 JuanB, ES 826 Randall Gaz, Colorado USA 827 Dick van Ginkel, The Netherlands 829 Jan-Pieter Van Impe 831 David Kirkpatrick, AU 832 Ravi Teja, India 833 AkosLukacs, HU 834 Dave Desson, CAN 837 LWQ.CZ, CZ 838 Robert W., Issaquah, WA 839 Daniel Hrynczenko 840 Martin Filtenborg, DK 841 InnHuchen, Ger 845 Raju Pillai,India 847 cfus/DE * 851 Juli H. 853 David Monterroso Cabello , SP 857 24x8, LLC, US 860 Sebastian, DE 861 pajusmar 864 Ronnie, UK * 867 Travis Travelstead, USA * 870 Woodat, US/UK 872 Gary Bake, UK 873 Ernesto Martinez * 874 Scottt, USA 876 Ronnie Kizzle, LA 880 Harish, Singapore 882 Wacht, Pittsburgh 883 PatrickF, US 886 Paolo, IT 888 Defragster 889 Rachel Rayns, UK * 890 Peak Data LLC 891 Mindwarp, AU 892 Vincent Smedley, UK * 894 Bailey & Brayden 898 Jacek Artymiak, UK 900 John Hudson, USA * 901 ReneS, NL * 902 B Stevens 903 Cptnslick, US 904 janlj@me.com 905 Fabricio Biazzotto 906 Lenz Hirsch 907 SerSher, RU 908 Florian, DE 909 Mathias Svendsen, DK * 910 Jeremiah Dey-Oh 911 Allan Joseph Medwick 913 Matt, Australia 914 Christian Pedersen * 915 SPIN 916 Denis M., Russia 917 Ahmed Alboori, Saudi Arabia 918 Luciano, Italy 919 Ragdehl * 921 Artur, HU 922 Greg, NC - USA 924 Gurzixo * 927 Gregg, Oregon 928 cwschroeder, BY 929 W. Bush - NY, USA. 932 ddparker 933 Enkion * 934 Eric G. Barron 936 thomasDOTwtf 940 mifous, cucurbitae.eu 942 VFL68, FR 943 Casey, Hong Kong * 945 Kean Electronics 946 Nima, UK 947 Klosinski, USA 948 PieWiE, NL * 949 Rui Carmo, PT * 950 basbrun.com 951 Aashu, UK * 952 vk2nq - Brian 954 gojimmypi 955 Jack, USA * 957 @SteveBattle * 958 Beshr, Sweden 962 PeterR, UK 964 Russell Calbert 965 LAurent_B, Fr 967 Qazi, USA 971 Jonas, FR 973 PK Shiu * 974 sea_kev 976 Radhika, USA 977 Chris Gibson, US * 978 Mike, AU * 979 Geeky Pete 981 Timmy the wonderdog 983 An Ostler it IT 984 Frank Ray Robles 985 Kurtsik 987 Johan, SE 988 NJBerland, Norway 992 Leon Noel - @leonnoel 994 Kjell, SE 995 boriskourt 997 Bartek B., CANADA 999 Thomas Wiradikusuma, Indonesia 1000 Trey, NOLA 1002 Jori, FI 1005 nmmarkin 1006 Mattias Fornander 1007 Panayot Daskalov, Bulgaria *1009 AndyP, UK 1011 TSD 1013 Chris, Berlin 1017 Gareth Edwards, UK 1018 Trixam,DE 1019 César from Makespace Madrid, Spain 1020 Prajwal, Australia *1024 Fred Dart - FTDI 1025 bsx *1026 Regis, FR 1027 Adrian Hill 1029 Alice, UK 1030 Erkan Shakir, BG 1031 Alexander, EE 1033 Patric, Luxembourg 1034 For my beloved mother, Colleen Clancy. 1035 NigelB 1037 François, Aus/Fr *1039 Thanura Siribaddana, Australia 1041 Harald, USA 1042 Jeremy Utting, NZ 1043 bejuryu, KR *1044 Daniel Wood, UK 1046 C. J. Blocker *1047 Rodrigo Benenson, Germany 1048 Håvard Gulldahl 1049 SeB, Belgium 1054 Ryan Miller, Austin TX 1055 Gianluca Cancelmi 1057 Francesco, IT 1058 RockTractor! 1060 Bill G., Atlanta GA USA 1061 joenotjoe 1064 ATrivedi, USA 1067 Jim Chandler, UK 1068 Aria Sabeti 1069 Noah Rosamilia, USA 1070 GAKgDavid, CA 1072 Markus, Austria *1073 Tarwin, MUC *1077 Balazs Kinszler, HU *1080 pfh *1082 Ovidiu Hossu, SG *1083 mmhanif, NJ *1084 Wincent Balin, DE *1086 Anatoly Verkhovsky *1087 Greg, Plano *1089 Angelo Compagnucci 1090 Ryan Shaw (ryannathans), AU 1092 Dries007, BE *1093 Dave Snowdon, UK *1094 halfpress *1096 DeuxVis, FR *1097 Your Creative Solutions 1099 Emanuele Goldoni, IT *1100 Tendayi Mawushe 1101 Rob, Tikitere *1102 SolidStateSoul *1103 Michael, GER *1106 Paul, San Francisco *1107 Oddvar Lovaas *1108 Doc Savage, Man of Bronze 1109 Stijn Debrouwere 1111 Ark Nieckarz, USA *1112 ECS87.com, USA *1114 Gary P. Wolfe, USA 1117 Tom Hodson *1118 @arikb (twitter) 1123 Piotr Gryko UK *1125 Cantalaweb, Spain 1126 Edward of Clovis 1127 Jim G *1128 billbr, Loveland, CO, USA 1129 dalanmiller *1130 StephenH, UK *1132 Thomas Sarlandie - @sarfata 1133 Doug Rohm, US *1134 Eric Floehr, Ohio, USA *1135 Sven Haiges 1136 relix42 *1137 Ralf Nyren *1138 nickgb 1139 zwack, DE 1140 Michal B., PL 1141 Matt, Australia 1143 slv, Mi2 1144 Pawel, CH *1145 James Saffery *1147 nekomatic *1149 @nt1, Earth *1150 Alister Galpin, NZ 1151 Jayemel, UK 1152 Koalabs 1153 James Myatt, UK *1154 DanS, Norway 1155 Sandeep, US *1156 Anil Kavipurapu *1158 Frederik Werner, DE 1160 Erik J, Canada 1164 bluezebra, Ireland 1168 Birk, DE 1169 Gabi, FR *1173 mliberty, USA 1174 Jamie Smith, Scotland 1175 Sebastian, Germany *1176 John Cooper, UK 1177 Moritz, DE 1178 Kevin, DE *1179 Ming Leung, Canada 1180 Laird Popkin 1181 tasmaniac, GA *1183 RichardW, UK *1187 Thomas Quinlan, London, UK 1188 LGnap, BE *1189 bloater, Edinburgh UK 1192 pakt, SE 1194 Sandsmark, NO *1195 Gert Menke 1197 Emsi88, SK 1199 GTtronics HK Ltd. 1200 Jo, Bergen *1202 MarkS, Australia 1203 Igor, HR 1204 Lord Nightmare 1205 Great Uncle Bulgaria, UK *1206 salomonderossi 1208 Master_Ipse, DE 1209 Luis G.F, ES 1211 Harald, FO *1212 Kimmo, Finland *1213 P. Perreijn, Netherlands 1214 jcea, Spain 1215 simon holmes à court 1217 Bill M, Newcastle *1218 snowball *1221 Georges, CDN 1222 JPLa 1225 Erik Gullberg, Sweden 1226 Matthias Fuchs, IN, Germany 1229 Majed, CA 1230 Michiel, Reeuwijk 1231 Clive, Essex UK 1232 Jan Kalina, CZ 1234 MBBest, Australia *1235 Reinoud de Lange, NL 1237 Jeffrey Park, South Korea 1238 David Olson 1239 Nathan Battan 1240 Marcus, TW 1241 randyrrt, USA 1242 Holger, Germany 1243 Dmitri Chapkine, FRANCE 1244 Ceyhun Kapucu, TR 1245 Hong Kong *1246 gPozo, US 1247 Peter M, Sweden *1249 Duncan, Cambridge *1251 Schaeferling, DE 1252 Christian Prior, DE *1256 ovig 1257 Kerry Channing, UK 1258 Exception42, GER *1259 nchalikias 1261 Kittie, US 1263 Alex, Norway 1264 wats0n, TW *1265 Henner *1266 Mike M, AZ, USA 1268 Bobby Ly, USA *1269 Espen STO, Norway 1270 arduware.cc 1274 Christopher Flynn, NH USA *1275 Bruce Boyes, USA 1276 DCH 1278 McGinkel, Netherlands 1279 Dieter, Wien 1280 R. Tummers, NL 1283 Pranav Maddula, USA 1286 Dusan, SLovakia 1290 Stephen Youndt *1291 Lertsenem, FR 1292 NuclearTide, London 1293 Ben Gift, USA 1294 rmg 1295 jmaybe, USA 1296 Allan G, Georgia 1297 Duncan Brassington, UK 1300 Hans, NL 1301 Valerio "valdez" Paolini, IT 1303 Neotreat, DE 1306 tomtoump 1307 Edward B Cox, England 1310 Oliver Steele 1311 merps, AUS 1313 n8henrie, USA *1314 YGA-KSD n7/ULB, FR-BE 1317 Adrian, Romania *1318 Luca "Loop", ITA *1319 Michael Twomey, Ireland 1321 Trey Aughenbaugh 1322 Marcel Hecko, SK 1323 Hugo Neira, CL 1326 JH, US *1330 Luthander, SE 1331 Rickard Dahlstrand, Sweden 1333 Olivier M., France 1334 DWVL, UK 1335 MRZANE, Sweden 1336 Benedikt, DE *1338 Tiegeng, US *1339 arthoo Eindhoven Nederland 1340 Magnus Gustavsson, Sweden 1341 Jan Bednařík 1344 Mike McGary: US 1346 mp3tobi *1350 Cyberhippy 1351 Sandro, PT 1355 Kwabena W. Agyeman 1357 Ryan Young *1358 Chiang Mai, Thailand 1359 AKLitman, USA 1360 JASK Enterprises, Ltd-John *1361 Tom Gidden, UK 1362 AdamT, USA 1363 Jose de la Campa, BOL 1365 Steve Laguna, U.S.A *1368 Walrusklasse, NL 1370 Timofei Korostelev, Belarus 1374 Janos,HU *1375 Paul Cunnane 1377 IanE, UK 1378 Hans, NL 1379 Jose Angel Jimenez Vadillo, Spain *1380 PaulT, Lancs 1383 Lutz; DE 1385 AnRkey 1387 Fredrik, FIN 1388 Matt W (funkyHat) 1389 Zeev Rotshtein, Israel 1391 joostd, NL 1392 Lukasz Blaszczyk, USA *1397 Wei-Ning Huang, TW 1398 myu *1399 Thorsten, Germany 1401 sm0ihr 1403 Xiaotian, Seattle US *1406 -gt-, Czech Republic 1407 Mike Y. Diallo, US 1409 ubii, US micropython-1.12/CODECONVENTIONS.md000066400000000000000000000157611357706137100166160ustar00rootroot00000000000000Git commit conventions ====================== Each commit message should start with a directory or full file path prefix, so it was clear which part of codebase a commit affects. If a change affects one file, it's better to use path to a file. If it affects few files in a subdirectory, using subdirectory as a prefix is ok. For longish paths, it's acceptable to drop intermediate components, which still should provide good context of a change. It's also ok to drop file extensions. Besides prefix, first line of a commit message should describe a change clearly and to the point, and be a grammatical sentence with final full stop. First line should fit within 78 characters. Examples of good first line of commit messages: py/objstr: Add splitlines() method. py: Rename FOO to BAR. docs/machine: Fix typo in reset() description. ports: Switch to use lib/foo instead of duplicated code. After the first line, add an empty line and in following lines describe a change in a detail, if needed. Any change beyond 5 lines would likely require such detailed description. To get good practical examples of good commits and their messages, browse the `git log` of the project. MicroPython doesn't require explicit sign-off for patches ("Signed-off-by" lines and similar). Instead, the commit message, and your name and email address on it construes your sign-off of the following: * That you wrote the change yourself, or took it from a project with a compatible license (in the latter case the commit message, and possibly source code should provide reference where the implementation was taken from and give credit to the original author, as required by the license). * That you are allowed to release these changes to an open-source project (for example, changes done during paid work for a third party may require explicit approval from that third party). * That you (or your employer) agree to release the changes under MicroPython's license, which is the MIT license. Note that you retain copyright for your changes (for smaller changes, the commit message conveys your copyright; if you make significant changes to a particular source module, you're welcome to add your name to the file header). * Your signature for all of the above, which is the 'Author' line in the commit message, and which should include your full real name and a valid and active email address by which you can be contacted in the foreseeable future. Python code conventions ======================= Python code follows [PEP 8](http://legacy.python.org/dev/peps/pep-0008/). Naming conventions: - Module names are short and all lowercase; eg pyb, stm. - Class names are CamelCase, with abreviations all uppercase; eg I2C, not I2c. - Function and method names are all lowercase with words separated by a single underscore as necessary to improve readability; eg mem_read. - Constants are all uppercase with words separated by a single underscore; eg GPIO_IDR. C code conventions ================== When writing new C code, please adhere to the following conventions. White space: - Expand tabs to 4 spaces. - Don't leave trailing whitespace at the end of a line. - For control blocks (if, for, while), put 1 space between the keyword and the opening parenthesis. - Put 1 space after a comma, and 1 space around operators. Braces: - Use braces for all blocks, even no-line and single-line pieces of code. - Put opening braces on the end of the line it belongs to, not on a new line. - For else-statements, put the else on the same line as the previous closing brace. Header files: - Header files should be protected from multiple inclusion with #if directives. See an existing header for naming convention. Names: - Use underscore_case, not camelCase for all names. - Use CAPS_WITH_UNDERSCORE for enums and macros. - When defining a type use underscore_case and put '_t' after it. Integer types: MicroPython runs on 16, 32, and 64 bit machines, so it's important to use the correctly-sized (and signed) integer types. The general guidelines are: - For most cases use mp_int_t for signed and mp_uint_t for unsigned integer values. These are guaranteed to be machine-word sized and therefore big enough to hold the value from a MicroPython small-int object. - Use size_t for things that count bytes / sizes of objects. - You can use int/uint, but remember that they may be 16-bits wide. - If in doubt, use mp_int_t/mp_uint_t. Comments: - Be concise and only write comments for things that are not obvious. - Use `// ` prefix, NOT `/* ... */`. No extra fluff. Memory allocation: - Use m_new, m_renew, m_del (and friends) to allocate and free heap memory. These macros are defined in py/misc.h. Examples -------- Braces, spaces, names and comments: #define TO_ADD (123) // This function will always recurse indefinitely and is only used to show // coding style int foo_function(int x, int some_value) { if (x < some_value) { foo(some_value, x); } else { foo(x + TO_ADD, some_value - 1); } for (int my_counter = 0; my_counter < x; my_counter++) { } } Type declarations: typedef struct _my_struct_t { int member; void *data; } my_struct_t; Documentation conventions ========================= MicroPython generally follows CPython in documentation process and conventions. reStructuredText syntax is used for the documention. Specific conventions/suggestions: * Use `*` markup to refer to arguments of a function, e.g.: ``` .. method:: poll.unregister(obj) Unregister *obj* from polling. ``` * Use following syntax for cross-references/cross-links: ``` :func:`foo` - function foo in current module :func:`module1.foo` - function foo in module "module1" (similarly for other referent types) :class:`Foo` - class Foo :meth:`Class.method1` - method1 in Class :meth:`~Class.method1` - method1 in Class, but rendered just as "method1()", not "Class.method1()" :meth:`title ` - reference method1, but render as "title" (use only if really needed) :mod:`module1` - module module1 `symbol` - generic xref syntax which can replace any of the above in case the xref is unambiguous. If there's ambiguity, there will be a warning during docs generation, which need to be fixed using one of the syntaxes above ``` * Cross-referencing arbitrary locations ~~~ .. _xref_target: Normal non-indented text. This is :ref:`reference `. (If xref target is followed by section title, can be just :ref:`xref_target`). ~~~ * Linking to external URL: ``` `link text `_ ``` * Referencing builtin singleton objects: ``` ``None``, ``True``, ``False`` ``` * Use following syntax to create common description for more than one element: ~~~ .. function:: foo(x) bar(y) Description common to foo() and bar(). ~~~ More detailed guides and quickrefs: * http://www.sphinx-doc.org/en/stable/rest.html * http://www.sphinx-doc.org/en/stable/markup/inline.html * http://docutils.sourceforge.net/docs/user/rst/quickref.html micropython-1.12/CODEOFCONDUCT.md000066400000000000000000000051201357706137100163210ustar00rootroot00000000000000MicroPython Code of Conduct =========================== The MicroPython community is made up of members from around the globe with a diverse set of skills, personalities, and experiences. It is through these differences that our community experiences great successes and continued growth. When you're working with members of the community, this Code of Conduct will help steer your interactions and keep MicroPython a positive, successful, and growing community. Members of the MicroPython community are open, considerate, and respectful. Behaviours that reinforce these values contribute to a positive environment, and include: acknowledging time and effort, being respectful of differing viewpoints and experiences, gracefully accepting constructive criticism, and using welcoming and inclusive language. Every member of our community has the right to have their identity respected. The MicroPython community is dedicated to providing a positive experience for everyone, regardless of age, gender identity and expression, sexual orientation, disability, physical appearance, body size, ethnicity, nationality, race, or religion (or lack thereof), education, or socio-economic status. Unacceptable behaviour includes: harassment, trolling, deliberate intimidation, violent threats or language directed against another person; insults, put downs, or jokes that are based upon stereotypes, that are exclusionary, or that hold others up for ridicule; unwelcome sexual attention or advances; sustained disruption of community discussions; publishing others' private information without explicit permission; and other conduct that is inappropriate for a professional audience including people of many different backgrounds. This code of conduct covers all online and offline presence related to the MicroPython project, including GitHub and the forum. If a participant engages in behaviour that violates this code of conduct, the MicroPython team may take action as they deem appropriate, including warning the offender or expulsion from the community. Community members asked to stop any inappropriate behaviour are expected to comply immediately. Thank you for helping make this a welcoming, friendly community for everyone. If you believe that someone is violating the code of conduct, or have any other concerns, please contact a member of the MicroPython team by emailing contact@micropython.org. License ------- This Code of Conduct is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. Attributions ------------ Based on the Python code of conduct found at https://www.python.org/psf/conduct/ micropython-1.12/CONTRIBUTING.md000066400000000000000000000004611357706137100162540ustar00rootroot00000000000000When reporting an issue and especially submitting a pull request, please make sure that you are acquainted with Contributor Guidelines: https://github.com/micropython/micropython/wiki/ContributorGuidelines and Code Conventions: https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md micropython-1.12/LICENSE000066400000000000000000000021001357706137100150200ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2013-2019 Damien P. George Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. micropython-1.12/README.md000066400000000000000000000177701357706137100153150ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/micropython/micropython.png?branch=master)](https://travis-ci.org/micropython/micropython) [![Coverage Status](https://coveralls.io/repos/micropython/micropython/badge.png?branch=master)](https://coveralls.io/r/micropython/micropython?branch=master) The MicroPython project =======================

MicroPython Logo

This is the MicroPython project, which aims to put an implementation of Python 3.x on microcontrollers and small embedded systems. You can find the official website at [micropython.org](http://www.micropython.org). WARNING: this project is in beta stage and is subject to changes of the code-base, including project-wide name changes and API changes. MicroPython implements the entire Python 3.4 syntax (including exceptions, `with`, `yield from`, etc., and additionally `async`/`await` keywords from Python 3.5). The following core datatypes are provided: `str` (including basic Unicode support), `bytes`, `bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`, `collections.namedtuple`, classes and instances. Builtin modules include `sys`, `time`, and `struct`, etc. Select ports have support for `_thread` module (multithreading). Note that only a subset of Python 3 functionality is implemented for the data types and modules. MicroPython can execute scripts in textual source form or from precompiled bytecode, in both cases either from an on-device filesystem or "frozen" into the MicroPython executable. See the repository http://github.com/micropython/pyboard for the MicroPython board (PyBoard), the officially supported reference electronic circuit board. Major components in this repository: - py/ -- the core Python implementation, including compiler, runtime, and core library. - mpy-cross/ -- the MicroPython cross-compiler which is used to turn scripts into precompiled bytecode. - ports/unix/ -- a version of MicroPython that runs on Unix. - ports/stm32/ -- a version of MicroPython that runs on the PyBoard and similar STM32 boards (using ST's Cube HAL drivers). - ports/minimal/ -- a minimal MicroPython port. Start with this if you want to port MicroPython to another microcontroller. - tests/ -- test framework and test scripts. - docs/ -- user documentation in Sphinx reStructuredText format. Rendered HTML documentation is available at http://docs.micropython.org. Additional components: - ports/bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used mostly to control code size. - ports/teensy/ -- a version of MicroPython that runs on the Teensy 3.1 (preliminary but functional). - ports/pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers. - ports/cc3200/ -- a version of MicroPython that runs on the CC3200 from TI. - ports/esp8266/ -- a version of MicroPython that runs on Espressif's ESP8266 SoC. - ports/esp32/ -- a version of MicroPython that runs on Espressif's ESP32 SoC. - ports/nrf/ -- a version of MicroPython that runs on Nordic's nRF51 and nRF52 MCUs. - extmod/ -- additional (non-core) modules implemented in C. - tools/ -- various tools, including the pyboard.py module. - examples/ -- a few example Python scripts. The subdirectories above may include READMEs with additional info. "make" is used to build the components, or "gmake" on BSD-based systems. You will also need bash, gcc, and Python 3.3+ available as the command `python3` (if your system only has Python 2.7 then invoke make with the additional option `PYTHON=python2`). The MicroPython cross-compiler, mpy-cross ----------------------------------------- Most ports require the MicroPython cross-compiler to be built first. This program, called mpy-cross, is used to pre-compile Python scripts to .mpy files which can then be included (frozen) into the firmware/executable for a port. To build mpy-cross use: $ cd mpy-cross $ make The Unix version ---------------- The "unix" port requires a standard Unix environment with gcc and GNU make. x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well as ARM and MIPS. Making full-featured port to another architecture requires writing some assembly code for the exception handling and garbage collection. Alternatively, fallback implementation based on setjmp/longjmp can be used. To build (see section below for required dependencies): $ cd ports/unix $ make submodules $ make Then to give it a try: $ ./micropython >>> list(5 * x + y for x in range(10) for y in [4, 2, 1]) Use `CTRL-D` (i.e. EOF) to exit the shell. Learn about command-line options (in particular, how to increase heap size which may be needed for larger applications): $ ./micropython --help Run complete testsuite: $ make test Unix version comes with a builtin package manager called upip, e.g.: $ ./micropython -m upip install micropython-pystone $ ./micropython -m pystone Browse available modules on [PyPI](https://pypi.python.org/pypi?%3Aaction=search&term=micropython). Standard library modules come from [micropython-lib](https://github.com/micropython/micropython-lib) project. External dependencies --------------------- Building MicroPython ports may require some dependencies installed. For Unix port, `libffi` library and `pkg-config` tool are required. On Debian/Ubuntu/Mint derivative Linux distros, install `build-essential` (includes toolchain and make), `libffi-dev`, and `pkg-config` packages. Other dependencies can be built together with MicroPython. This may be required to enable extra features or capabilities, and in recent versions of MicroPython, these may be enabled by default. To build these additional dependencies, in the port directory you're interested in (e.g. `ports/unix/`) first execute: $ make submodules This will fetch all the relevant git submodules (sub repositories) that the port needs. Use the same command to get the latest versions of submodules as they are updated from time to time. After that execute: $ make deplibs This will build all available dependencies (regardless whether they are used or not). If you intend to build MicroPython with additional options (like cross-compiling), the same set of options should be passed to `make deplibs`. To actually enable/disable use of dependencies, edit `ports/unix/mpconfigport.mk` file, which has inline descriptions of the options. For example, to build SSL module (required for `upip` tool described above, and so enabled by dfeault), `MICROPY_PY_USSL` should be set to 1. For some ports, building required dependences is transparent, and happens automatically. But they still need to be fetched with the `make submodules` command. The STM32 version ----------------- The "stm32" port requires an ARM compiler, arm-none-eabi-gcc, and associated bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils, arm-none-eabi-gcc and arm-none-eabi-newlib packages. Otherwise, try here: https://launchpad.net/gcc-arm-embedded To build: $ cd ports/stm32 $ make submodules $ make You then need to get your board into DFU mode. On the pyboard, connect the 3V3 pin to the P1/DFU pin with a wire (on PYBv1.0 they are next to each other on the bottom left of the board, second row from the bottom). Then to flash the code via USB DFU to your device: $ make deploy This will use the included `tools/pydfu.py` script. If flashing the firmware does not work it may be because you don't have the correct permissions, and need to use `sudo make deploy`. See the README.md file in the ports/stm32/ directory for further details. Contributing ------------ MicroPython is an open-source project and welcomes contributions. To be productive, please be sure to follow the [Contributors' Guidelines](https://github.com/micropython/micropython/wiki/ContributorGuidelines) and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md). Note that MicroPython is licenced under the MIT license, and all contributions should follow this license. micropython-1.12/docs/000077500000000000000000000000001357706137100147525ustar00rootroot00000000000000micropython-1.12/docs/Makefile000066400000000000000000000161611357706137100164170ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. PYTHON = python3 SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build/$(MICROPY_PORT) CPYDIFFDIR = ../tools CPYDIFF = gen-cpydiff.py GENRSTDIR = genrst # Run "make FORCE= ..." to avoid rebuilding from scratch (and risk # producing incorrect docs). FORCE = -E # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " cpydiff to generate the MicroPython differences from CPython" clean: rm -rf $(BUILDDIR)/* rm -f $(GENRSTDIR)/* cpydiff: @echo "Generating MicroPython Differences." rm -f $(GENRSTDIR)/* cd $(CPYDIFFDIR) && $(PYTHON) $(CPYDIFF) html: cpydiff $(SPHINXBUILD) $(FORCE) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MicroPython.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MicroPython.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/MicroPython" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MicroPython" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: cpydiff $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: cpydiff $(SPHINXBUILD) $(FORCE) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: cpydiff $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." micropython-1.12/docs/README.md000066400000000000000000000020221357706137100162250ustar00rootroot00000000000000MicroPython Documentation ========================= The MicroPython documentation can be found at: http://docs.micropython.org/en/latest/ The documentation you see there is generated from the files in the docs tree: https://github.com/micropython/micropython/tree/master/docs Building the documentation locally ---------------------------------- If you're making changes to the documentation, you may want to build the documentation locally so that you can preview your changes. Install Sphinx, and optionally (for the RTD-styling), sphinx_rtd_theme, preferably in a virtualenv: pip install sphinx pip install sphinx_rtd_theme In `micropython/docs`, build the docs: make html You'll find the index page at `micropython/docs/build/html/index.html`. PDF manual generation --------------------- This can be achieved with: make latexpdf but require rather complete install of LaTeX with various extensions. On Debian/Ubuntu, try (500MB+ download): apt-get install texlive-latex-recommended texlive-latex-extra micropython-1.12/docs/conf.py000077500000000000000000000233501357706137100162570ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # MicroPython documentation build configuration file, created by # sphinx-quickstart on Sun Sep 21 11:42:03 2014. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('.')) # The members of the html_context dict are available inside topindex.html micropy_version = os.getenv('MICROPY_VERSION') or 'latest' micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',') url_pattern = '%s/en/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',) html_context = { 'cur_version':micropy_version, 'all_versions':[ (ver, url_pattern % ver) for ver in micropy_all_versions ], 'downloads':[ ('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'), ], } # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = 'MicroPython' copyright = '2014-2019, Damien P. George, Paul Sokolovsky, and contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags" # breakdown, so use the same version identifier for both to avoid confusion. version = release = '1.12' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['build', '.venv'] # The reST default role (used for this markup: `text`) to use for all # documents. default_role = 'any' # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False # Global include files. Sphinx docs suggest using rst_epilog in preference # of rst_prolog, so we follow. Absolute paths below mean "from the base # of the doctree". rst_epilog = """ .. include:: /templates/replace.inc """ # -- Options for HTML output ---------------------------------------------- # on_rtd is whether we are on readthedocs.org on_rtd = os.environ.get('READTHEDOCS', None) == 'True' if not on_rtd: # only import and set the theme if we're building docs locally try: import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.'] except: html_theme = 'default' html_theme_path = ['.'] else: html_theme_path = ['.'] # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = ['.'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = '../../logo/trans-logo.png' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. html_favicon = 'static/favicon.ico' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. #html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%d %b %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. html_additional_pages = {"index": "topindex.html"} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'MicroPythondoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', # Include 3 levels of headers in PDF ToC 'preamble': '\setcounter{tocdepth}{2}', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'MicroPython.tex', 'MicroPython Documentation', 'Damien P. George, Paul Sokolovsky, and contributors', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'micropython', 'MicroPython Documentation', ['Damien P. George, Paul Sokolovsky, and contributors'], 1), ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'MicroPython', 'MicroPython Documentation', 'Damien P. George, Paul Sokolovsky, and contributors', 'MicroPython', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'python': ('https://docs.python.org/3.5', None)} micropython-1.12/docs/develop/000077500000000000000000000000001357706137100164105ustar00rootroot00000000000000micropython-1.12/docs/develop/cmodules.rst000066400000000000000000000137671357706137100207730ustar00rootroot00000000000000.. _cmodules: MicroPython external C modules ============================== When developing modules for use with MicroPython you may find you run into limitations with the Python environment, often due to an inability to access certain hardware resources or Python speed limitations. If your limitations can't be resolved with suggestions in :ref:`speed_python`, writing some or all of your module in C is a viable option. If your module is designed to access or work with commonly available hardware or libraries please consider implementing it inside the MicroPython source tree alongside similar modules and submitting it as a pull request. If however you're targeting obscure or proprietary systems it may make more sense to keep this external to the main MicroPython repository. This chapter describes how to compile such external modules into the MicroPython executable or firmware image. An alternative approach is to use :ref:`natmod` which allows writing custom C code that is placed in a .mpy file, which can be imported dynamically in to a running MicroPython system without the need to recompile the main firmware. Structure of an external C module --------------------------------- A MicroPython user C module is a directory with the following files: * ``*.c`` and/or ``*.h`` source code files for your module. These will typically include the low level functionality being implemented and the MicroPython binding functions to expose the functions and module(s). Currently the best reference for writing these functions/modules is to find similar modules within the MicroPython tree and use them as examples. * ``micropython.mk`` contains the Makefile fragment for this module. ``$(USERMOD_DIR)`` is available in ``micropython.mk`` as the path to your module directory. As it's redefined for each c module, is should be expanded in your ``micropython.mk`` to a local make variable, eg ``EXAMPLE_MOD_DIR := $(USERMOD_DIR)`` Your ``micropython.mk`` must add your modules C files relative to your expanded copy of ``$(USERMOD_DIR)`` to ``SRC_USERMOD``, eg ``SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c`` If you have custom ``CFLAGS`` settings or include folders to define, these should be added to ``CFLAGS_USERMOD``. See below for full usage example. Basic Example ------------- This simple module named ``example`` provides a single function ``example.add_ints(a, b)`` which adds the two integer args together and returns the result. Directory:: example/ ├── example.c └── micropython.mk ``example.c`` .. code-block:: c // Include required definitions first. #include "py/obj.h" #include "py/runtime.h" #include "py/builtin.h" // This is the function which will be called from Python as example.add_ints(a, b). STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) { // Extract the ints from the micropython input objects int a = mp_obj_get_int(a_obj); int b = mp_obj_get_int(b_obj); // Calculate the addition and convert to MicroPython object. return mp_obj_new_int(a + b); } // Define a Python reference to the function above STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints); // Define all properties of the example module. // Table entries are key/value pairs of the attribute name (a string) // and the MicroPython object reference. // All identifiers and strings are written as MP_QSTR_xxx and will be // optimized to word-sized integers by the build system (interned strings). STATIC const mp_rom_map_elem_t example_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) }, { MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) }, }; STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); // Define module object. const mp_obj_module_t example_user_cmodule = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&example_module_globals, }; // Register the module to make it available in Python MP_REGISTER_MODULE(MP_QSTR_example, example_user_cmodule, MODULE_EXAMPLE_ENABLED); ``micropython.mk`` .. code-block:: make EXAMPLE_MOD_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c # We can add our module folder to include paths if needed # This is not actually needed in this example. CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR) Finally you will need to define ``MODULE_EXAMPLE_ENABLED`` to 1. This can be done by adding ``CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1`` to the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h`` to add .. code-block:: c #define MODULE_EXAMPLE_ENABLED (1) Note that the exact method depends on the port as they have different structures. If not done correctly it will compile but importing will fail to find the module. Compiling the cmodule into MicroPython -------------------------------------- To build such a module, compile MicroPython (see `getting started `_) with an extra ``make`` flag named ``USER_C_MODULES`` set to the directory containing all modules you want included (not to the module itself). For example: Directory:: my_project/ ├── modules/ │ └──example/ │ ├──example.c │ └──micropython.mk └── micropython/ ├──ports/ ... ├──stm32/ ... Building for stm32 port: .. code-block:: bash cd my_project/micropython/ports/stm32 make USER_C_MODULES=../../../modules CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1 all Module usage in MicroPython --------------------------- Once built into your copy of MicroPython, the module implemented in ``example.c`` above can now be accessed in Python just like any other builtin module, eg .. code-block:: python import example print(example.add_ints(1, 3)) # should display 4 micropython-1.12/docs/develop/index.rst000066400000000000000000000006431357706137100202540ustar00rootroot00000000000000Developing and building MicroPython =================================== This chapter describes some options for extending MicroPython in C. Note that it doesn't aim to be a complete guide for developing with MicroPython. See the `getting started guide `_ for further information. .. toctree:: :maxdepth: 1 cmodules.rst qstr.rst natmod.rst micropython-1.12/docs/develop/natmod.rst000066400000000000000000000170721357706137100204330ustar00rootroot00000000000000.. _natmod: Native machine code in .mpy files ================================= This section describes how to build and work with .mpy files that contain native machine code from a language other than Python. This allows you to write code in a language like C, compile and link it into a .mpy file, and then import this file like a normal Python module. This can be used for implementing functionality which is performance critical, or for including an existing library written in another language. One of the main advantages of using native .mpy files is that native machine code can be imported by a script dynamically, without the need to rebuild the main MicroPython firmware. This is in contrast to :ref:`cmodules` which also allows defining custom modules in C but they must be compiled into the main firmware image. The focus here is on using C to build native modules, but in principle any language which can be compiled to stand-alone machine code can be put into a .mpy file. A native .mpy module is built using the ``mpy_ld.py`` tool, which is found in the ``tools/`` directory of the project. This tool takes a set of object files (.o files) and links them together to create a native .mpy files. Supported features and limitations ---------------------------------- A .mpy file can contain MicroPython bytecode and/or native machine code. If it contains native machine code then the .mpy file has a specific architecture associated with it. Current supported architectures are (these are the valid options for the ``ARCH`` variable, see below): * ``x86`` (32 bit) * ``x64`` (64 bit x86) * ``armv7m`` (ARM Thumb 2, eg Cortex-M3) * ``armv7emsp`` (ARM Thumb 2, single precision float, eg Cortex-M4F, Cortex-M7) * ``armv7emdp`` (ARM Thumb 2, double precision float, eg Cortex-M7) * ``xtensa`` (non-windowed, eg ESP8266) * ``xtensawin`` (windowed with window size 8, eg ESP32) When compiling and linking the native .mpy file the architecture must be chosen and the corresponding file can only be imported on that architecture. For more details about .mpy files see :ref:`mpy_files`. Native code must be compiled as position independent code (PIC) and use a global offset table (GOT), although the details of this varies from architecture to architecture. When importing .mpy files with native code the import machinery is able to do some basic relocation of the native code. This includes relocating text, rodata and BSS sections. Supported features of the linker and dynamic loader are: * executable code (text) * read-only data (rodata), including strings and constant data (arrays, structs, etc) * zeroed data (BSS) * pointers in text to text, rodata and BSS * pointers in rodata to text, rodata and BSS The known limitations are: * data sections are not supported; workaround: use BSS data and initialise the data values explicitly * static BSS variables are not supported; workaround: use global BSS variables So, if your C code has writable data, make sure the data is defined globally, without an initialiser, and only written to within functions. Defining a native module ------------------------ A native .mpy module is defined by a set of files that are used to build the .mpy. The filesystem layout consists of two main parts, the source files and the Makefile: * In the simplest case only a single C source file is required, which contains all the code that will be compiled into the .mpy module. This C source code must include the ``py/dynruntime.h`` file to access the MicroPython dynamic API, and must at least define a function called ``mpy_init``. This function will be the entry point of the module, called when the module is imported. The module can be split into multiple C source files if desired. Parts of the module can also be implemented in Python. All source files should be listed in the Makefile, by adding them to the ``SRC`` variable (see below). This includes both C source files as well as any Python files which will be included in the resulting .mpy file. * The ``Makefile`` contains the build configuration for the module and list the source files used to build the .mpy module. It should define ``MPY_DIR`` as the location of the MicroPython repository (to find header files, the relevant Makefile fragment, and the ``mpy_ld.py`` tool), ``MOD`` as the name of the module, ``SRC`` as the list of source files, optionally specify the machine architecture via ``ARCH``, and then include ``py/dynruntime.mk``. Minimal example --------------- This section provides a fully working example of a simple module named ``factorial``. This module provides a single function ``factorial.factorial(x)`` which computes the factorial of the input and returns the result. Directory layout:: factorial/ ├── factorial.c └── Makefile The file ``factorial.c`` contains: .. code-block:: c // Include the header file to get access to the MicroPython API #include "py/dynruntime.h" // Helper function to compute factorial STATIC mp_int_t factorial_helper(mp_int_t x) { if (x == 0) { return 1; } return x * factorial_helper(x - 1); } // This is the function which will be called from Python, as factorial(x) STATIC mp_obj_t factorial(mp_obj_t x_obj) { // Extract the integer from the MicroPython input object mp_int_t x = mp_obj_get_int(x_obj); // Calculate the factorial mp_int_t result = factorial_helper(x); // Convert the result to a MicroPython integer object and return it return mp_obj_new_int(result); } // Define a Python reference to the function above STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial); // This is the entry point and is called when the module is imported mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { // This must be first, it sets up the globals dict and other things MP_DYNRUNTIME_INIT_ENTRY // Make the function available in the module's namespace mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj)); // This must be last, it restores the globals dict MP_DYNRUNTIME_INIT_EXIT } The file ``Makefile`` contains: .. code-block:: make # Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module MOD = features0 # Source files (.c or .py) SRC = features0.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 # Include to get the rules for compiling and linking the module include $(MPY_DIR)/py/dynruntime.mk Compiling the module -------------------- Be sure to select the correct ``ARCH`` for the target you are going to run on. Then build with:: $ make Without modifying the Makefile you can specify the target architecture via:: $ make ARCH=armv7m Module usage in MicroPython --------------------------- Once the module is built there should be a file called ``factorial.mpy``. Copy this so it is accessible on the filesystem of your MicroPython system and can be found in the import path. The module con now be accessed in Python just like any other module, for example:: import factorial print(factorial.factorial(10)) # should display 3628800 Further examples ---------------- See ``examples/natmod/`` for further examples which show many of the available features of native .mpy modules. Such features include: * using multiple C source files * including Python code alongside C code * rodata and BSS data * memory allocation * use of floating point * exception handling * including external C libraries micropython-1.12/docs/develop/qstr.rst000066400000000000000000000124401357706137100201340ustar00rootroot00000000000000MicroPython string interning ============================ MicroPython uses `string interning`_ to save both RAM and ROM. This avoids having to store duplicate copies of the same string. Primarily, this applies to identifiers in your code, as something like a function or variable name is very likely to appear in multiple places in the code. In MicroPython an interned string is called a QSTR (uniQue STRing). A QSTR value (with type ``qstr``) is a index into a linked list of QSTR pools. QSTRs store their length and a hash of their contents for fast comparison during the de-duplication process. All bytecode operations that work with strings use a QSTR argument. Compile-time QSTR generation ---------------------------- In the MicroPython C code, any strings that should be interned in the final firmware are written as ``MP_QSTR_Foo``. At compile time this will evaluate to a ``qstr`` value that points to the index of ``"Foo"`` in the QSTR pool. A multi-step process in the ``Makefile`` makes this work. In summary this process has three parts: 1. Find all ``MP_QSTR_Foo`` tokens in the code. 2. Generate a static QSTR pool containing all the string data (including lengths and hashes). 3. Replace all ``MP_QSTR_Foo`` (via the preprocessor) with their corresponding index. ``MP_QSTR_Foo`` tokens are searched for in two sources: 1. All files referenced in ``$(SRC_QSTR)``. This is all C code (i.e. ``py``, ``extmod``, ``ports/stm32``) but not including third-party code such as ``lib``. 2. Additional ``$(QSTR_GLOBAL_DEPENDENCIES)`` (which includes ``mpconfig*.h``). *Note:* ``frozen_mpy.c`` (generated by mpy-tool.py) has its own QSTR generation and pool. Some additional strings that can't be expressed using the ``MP_QSTR_Foo`` syntax (e.g. they contain non-alphanumeric characters) are explicitly provided in ``qstrdefs.h`` and ``qstrdefsport.h`` via the ``$(QSTR_DEFS)`` variable. Processing happens in the following stages: 1. ``qstr.i.last`` is the concatenation of putting every single input file through the C pre-processor. This means that any conditionally disabled code will be removed, and macros expanded. This means we don't add strings to the pool that won't be used in the final firmware. Because at this stage (thanks to the ``NO_QSTR`` macro added by ``QSTR_GEN_EXTRA_CFLAGS``) there is no definition for ``MP_QSTR_Foo`` it passes through this stage unaffected. This file also includes comments from the preprocessor that include line number information. Note that this step only uses files that have changed, which means that ``qstr.i.last`` will only contain data from files that have changed since the last compile. 2. ``qstr.split`` is an empty file created after running ``makeqstrdefs.py split`` on qstr.i.last. It's just used as a dependency to indicate that the step ran. This script outputs one file per input C file, ``genhdr/qstr/...file.c.qstr``, which contains only the matched QSTRs. Each QSTR is printed as ``Q(Foo)``. This step is necessary to combine the existing files with the new data generated from the incremental update in ``qstr.i.last``. 3. ``qstrdefs.collected.h`` is the output of concatenating ``genhdr/qstr/*`` using ``makeqstrdefs.py cat``. This is now the full set of ``MP_QSTR_Foo``'s found in the code, now formatted as ``Q(Foo)``, one-per-line, with duplicates. This file is only updated if the set of qstrs has changed. A hash of the QSTR data is written to another file (``qstrdefs.collected.h.hash``) which allows it to track changes across builds. 4. ``qstrdefs.preprocessed.h`` adds in the QSTRs from qstrdefs*. It concatenates ``qstrdefs.collected.h`` with ``qstrdefs*.h``, then it transforms each line from ``Q(Foo)`` to ``"Q(Foo)"`` so they pass through the preprocessor unchanged. Then the preprocessor is used to deal with any conditional compilation in ``qstrdefs*.h``. Then the transformation is undone back to ``Q(Foo)``, and saved as ``qstrdefs.preprocessed.h``. 5. ``qstrdefs.generated.h`` is the output of ``makeqstrdata.py``. For each ``Q(Foo)`` in qstrdefs.preprocessed.h (plus some extra hard-coded ones), it outputs ``QDEF(MP_QSTR_Foo, (const byte*)"hash" "Foo")``. Then in the main compile, two things happen with ``qstrdefs.generated.h``: 1. In qstr.h, each QDEF becomes an entry in an enum, which makes ``MP_QSTR_Foo`` available to code and equal to the index of that string in the QSTR table. 2. In qstr.c, the actual QSTR data table is generated as elements of the ``mp_qstr_const_pool->qstrs``. .. _`string interning`: https://en.wikipedia.org/wiki/String_interning Run-time QSTR generation ------------------------ Additional QSTR pools can be created at runtime so that strings can be added to them. For example, the code:: foo[x] = 3 Will need to create a QSTR for the value of ``x`` so it can be used by the "load attr" bytecode. Also, when compiling Python code, identifiers and literals need to have QSTRs created. Note: only literals shorter than 10 characters become QSTRs. This is because a regular string on the heap always takes up a minimum of 16 bytes (one GC block), whereas QSTRs allow them to be packed more efficiently into the pool. QSTR pools (and the underlying "chunks" that store the string data) are allocated on-demand on the heap with a minimum size. micropython-1.12/docs/differences/000077500000000000000000000000001357706137100172275ustar00rootroot00000000000000micropython-1.12/docs/differences/index_template.txt000066400000000000000000000004741357706137100227770ustar00rootroot00000000000000.. _cpython_diffs: MicroPython differences from CPython ==================================== The operations listed in this section produce conflicting results in MicroPython when compared to standard Python. MicroPython implements Python 3.4 and some select features of Python 3.5. .. toctree:: :maxdepth: 2 micropython-1.12/docs/esp32/000077500000000000000000000000001357706137100157065ustar00rootroot00000000000000micropython-1.12/docs/esp32/general.rst000066400000000000000000000055261357706137100200650ustar00rootroot00000000000000.. _esp32_general: General information about the ESP32 port ======================================== The ESP32 is a popular WiFi and Bluetooth enabled System-on-Chip (SoC) by Espressif Systems. Multitude of boards ------------------- There is a multitude of modules and boards from different sources which carry the ESP32 chip. MicroPython tries to provide a generic port which would run on as many boards/modules as possible, but there may be limitations. Espressif development boards are taken as reference for the port (for example, testing is performed on them). For any board you are using please make sure you have a datasheet, schematics and other reference materials so you can look up any board-specific functions. To make a generic ESP32 port and support as many boards as possible the following design and implementation decision were made: * GPIO pin numbering is based on ESP32 chip numbering. Please have the manual/pin diagram of your board at hand to find correspondence between your board pins and actual ESP32 pins. * All pins are supported by MicroPython but not all are usable on any given board. For example pins that are connected to external SPI flash should not be used, and a board may only expose a certain selection of pins. Technical specifications and SoC datasheets ------------------------------------------- The datasheets and other reference material for ESP32 chip are available from the vendor site: https://www.espressif.com/en/support/download/documents?keys=esp32 . They are the primary reference for the chip technical specifications, capabilities, operating modes, internal functioning, etc. For your convenience, some of technical specifications are provided below: * Architecture: Xtensa Dual-Core 32-bit LX6 * CPU frequency: up to 240MHz * Total RAM available: 528KB (part of it reserved for system) * BootROM: 448KB * Internal FlashROM: none * External FlashROM: code and data, via SPI Flash; usual size 4MB * GPIO: 34 (GPIOs are multiplexed with other functions, including external FlashROM, UART, etc.) * UART: 3 RX/TX UART (no hardware handshaking), one TX-only UART * SPI: 4 SPI interfaces (one used for FlashROM) * I2C: 2 I2C (bitbang implementation available on any pins) * I2S: 2 * ADC: 12-bit SAR ADC up to 18 channels * DAC: 2 8-bit DACs * RMT: 8 channels allowing accurate pulse transmit/receive * Programming: using BootROM bootloader from UART - due to external FlashROM and always-available BootROM bootloader, the ESP32 is not brickable For more information see the ESP32 datasheet: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf MicroPython is implemented on top of the ESP-IDF, Espressif's development framework for the ESP32. This is a FreeRTOS based system. See the `ESP-IDF Programming Guide `_ for details. micropython-1.12/docs/esp32/img/000077500000000000000000000000001357706137100164625ustar00rootroot00000000000000micropython-1.12/docs/esp32/img/esp32.jpg000066400000000000000000002506711357706137100201330ustar00rootroot00000000000000JFIFHHC   %# , #&')*)-0-(0%()(C   (((((((((((((((((((((((((((((((((((((((((((((((((((Q!1A"Qaq2#BR3b$%Crc&'4DSes56Td3!1AQaq"2BR3Cbr ?k`YorV>C}  41 .3 ۃ |"mŰ Xf g6V&ۭ$KooO@G{47FL5 +_Ԏ`GLԖ0ba}<0cikyݰ ${w$lF$lsjBmwo{z$.݉' J>1wpۂ/nfл ){`<ĝ6w7}FHq` @G7'mi ;0} mB!}{`%k%6Q;透ʍa`   ' P8[{^JY 'Ն [o2_Ƃz[$MVk,$QHV\"m޾#2+8;nK^$aOorN9W 2);~ i<ݰ)ذ XrpHt6Xz|Am{)m B\3*l>uԀ'r9 ),,x68Wdks> o|ӧ\ oLh9;lLwE P#rIml'>`; Ms@K ly3_7+`]|/mo35}w RlN,_`-\`>sA}!u6|55e<`w@ A$7a{ `AGP- km@bUpl -ŶI./Y{vFvѸ=Ou)rS/k.﵀>Y7;Mp rP8`׌ m` f߃-z XtDlm-wX]@^I&/}6m 5[3ض۞p.ξ7 QHX/n |UR@JC`BYR 7l4l<҇r;z}piZm}pb ZP0t'n6RCHn,36k ɿlú lۓ *` $#^[Q't[{^@.^Òv>:H!W.׹l@ {y0Z۾fk 6 ?C%,w!\|#eԶk=6rԑlGƙsΑn߮C!og {l Inݰ <dv ^־IN732.[ll5ͯ1& =um.tb [atop}FPYH*KM}p V  v,ĭ/ '}ōH@na 5o3#8$m unGas{y 5;؎lxeJOT=Իo`ݽ7>SLQrnACJȽ Bnv`7 _Gs-n G7]a

;}pl׿`bq^0 N~_$ݍ׃|p@T'|Emr*FJ賈',56`,[AQ>clJ v,8'l_IbDj79-͎ [0r 60 cӤ 7;1Ì:am 4M($_{ۏL`VRok[Lg6o@?ZJM Nro;RR#p !֒!QtQ=ilk{[8xX}NKTmCxAJىG{B-26(M`-};` DEl`Jl|M q/k#?9MP,v m'! /m?m eC?w>M Y+{4MV }*,YM<0nOj>l26\[Ջ+؅[;P `/pوX7'mΗ%^}~!Nao }0G __57ɿ倉8kIa (?$Mp6:nn?{")\ ϯlP嵽6M#Rk$`33TB_ 7$q` ɫSr/|Do] ص~6?l2)ܟ{ T`}-q 6oR7>ޘܯ }م`d`5_k?|#HR|fak!{@L1]*|f6$WXT1'tu"S,rM?f]rEo~CŻ{ptj=jG{qHŔ!N@ C\ \@ C* Mž#qp K&##3k؏2E؝Wl sT*;\﨓qa^M$bER@6`R-ks P5Sgp|Ć 'o506Qp PF?lO=%RmϷmsCeV6 7V>Nf 0S&:`oL7a`mM:\#1P"1/Dxc7E}6k_O1%YXIV*oܜ*9ѥ%<U. { _nz6o5oo)zpnV[Z ,?R\N[NRY[27 M{ m)>VfW-|M`GӱVف8 kv6m aŃZ~r7`#Qc0rnAAmݷuAQȾǟ6 $$\_5.v'gSX1 YTlXuo9%7$F|"p|u7_}fn5L F׸$wc{ 8k9+f;²م:!V3[UP0C{7})f{X3 JW k?;<Pnx4l&"{c :IW/} ŵ3y<۵ƐGb#"kI[{ mesa !A]!߃!`*~k ュl7֬ Óq8#-R-[[{#{\H֊,MJZѭ770P#UےG'lfAlO_wTm϶@ø[7!mafk;_OE*D E!( fm [I+ۍ4E6>00i,[r=?߀&܍* mL}`[}` WͶm~p)F cv[FT8Ǘcmai{?`[jfr}"*e#{ky|y(i-eI"q%+| F[cr6#P@PC6I V{[0Xڷ W?2;R`t="[>a` vE`I}\{聉o-yuY|[ȣ4{rp ssh_^| RZsb»Xs ,;һ7|NnX+k$ p,,z;Zt*O&_v#EEP*-cOꄫW[`I䝍ŰX0.TصQX?C6m-,1̻؝l.bE?ӺZ(RNlo+ki5ov.6_f#IToF ]Mņ^0 n7` YT.&<~'~&Xz` 6v8O20ow7ѳ:v ~\~c}J,FEp./Np͠0o;z`[>QG8}% \%A{[l7v:I7~0 \r m`5[p PnH=:]+1ggb0 HO4 l8ҫ( c(ok3Vk9WQ(srA$m*F}\ }} xK6E^0<ʏpmӶt:pO%[_'MR_v$w U= _̻M&@ZN/#]X\ oX-rĶvo倎hl|@ eA~/]"\]'fq6MX;_#[;o`D`Fu{np}Ujmu &66L vfWs|b_nF!r=}{nI_`̓-,0 ĕ &Qop. 2oc?\b}n@GB @Qq41nvg ʍ2a7yv vH I0;[[}O?~0UG S"NpG`ccrOFĨc8woC2Y=fmynOv^ݰUJR-ױиL]JE`ܪ;%Q`5}p.6fp8MrN6VeӵӥAb@_,K*..wF6?|_  cA-nED-3wH ZnF )_I|jV![|i7;a(ٍ#zA م[w6ζ/}$\L)Y͵[%w @Op.nOo_SHaeb5ӓZH6dӀ- +@(*HO?\kU3o;| t_u`5k 8`YFqSl`[HXyo0w(\tk'}'`4EbT}!aM mK䐓`3Z>`np  bA!U@Em'5* ~ 0Y6acnv'moY*P#s83H<@XZ-HtkoJJk @:Q7 }p ٔ)nm>Kܨ[t z` Em*' )\p[b<*pMH=ŊIb*=եR;sd*4X/7&|ZMGqpVц Ł>!k ןOHalt-^}w'V8 6˩Wq98+h&ą0d'ը_lևfյ8`{NӖ&}ph_SǫH% E}} X>|`剾ma}}W59rH8k Wko`Eԣa Zѕ*8kq +דY@7kZ`$Fvb|@X 6!'cym'quE24{w+ܒ5ks%! -oόe}LY/` -mذsϏ |ċ_m ǥ@fUbkv?gԺv&%!NϮ*@A[PkceFA8!Ђs~ǿ {m#`CYX@%t@˾LpUԛ>cFk ę#܎oDKo<|i|! ;[pb}p!gԡwUI͎Al͸?l2'UEko.$(R1yJ[AܓǛ%Ro@?=.U-K L^}ZY-F]BXDB׶ԍ!U,+aҶ@͛B00!, m4~އ_ẖ?oQa{{s?e"F`0nP nΧ}\EC qv`P1;?r,H65b-= CHSlh,6: [l؁ZNN ^7Q7 >EnI$r]G ;ܵc0Eʃ&޽/ImeMy'[}{LܝGKyA $o3 i{` LcoMVʌǞ}Ͼ] t)S8\j jpP|!- E)7*t$<:#/օٗ{fQc;۞HM6ʄoep7o\cpTi;iZVuk[>P75oc^!/cl.  T[Nğ[[uax@YY%A ث6-Ji&ê_`Ş0BFK`Q^E]C\bFhv,>hkQl'VŬ[" _`[Պ|6NdyAWPkLʞ[~bIBkuEٌoF(;5 s7RtcD2{GgBiV8 ۣ3R ߍ$ĎMsh];F2ZzoGJiQ7"Stъi4cr4ïgM 4ۍIrO8ugM̪\konê{:j_H+pUF\j3uR4Wk'Ѳ4d)ٖ݈ DC(6;--a$ x|ڣ`.o~p L@xnnpE*np0݊l=} #Žm]$owm^{ʬ5y׾"]@aK\y?ŶNsm'[AVI|0 Lʖ5kҢ?5c\qYޫҺ52 uyrw7:}4hr޶<Дҏ *@%uzΛ/yۏ4*ھ6ɨc4@ i前;o}G\gS_QP`ЩGOO7Xnxcگ=d ts#iJE+,n鍙q{ۖ/;RVe9l4KZQ lDZ7 9kROԓ<_3U`6, a|fzj *˗'Si6rAԋcrj>&%JAtIOF5je{z-b}s^AwET:lel\.4~ =V]J P"ԓGce7\zj[vK_qfYSB:@4ơuX5O&roP0&IgWkY`ClF3;#̹lSAUKj42#\Bnѿ,֛*zia41Grm`G;uu6ퟨHӣeὌIAOp?T]L;KQIV-$-ڷI2%Hm< ?C֪BccX6.f7I5g[2QGF)cXkiӤ$O,[( -5\tI" xq1%]4x€{꣉زfMfUXo[! c0e;!9<ʓ.5JTcJ3PM? dP7fVW;lxƸ6iWTM3Bo*# <(#n6ۮitѢY+mIPlH[S幽Y2OUn{,  QR "qb*7lY76?F] f(VFR@P8xSEW0u;qlM.Kյ8&MY.3Iԛo]Y;8(z2MOR$x@QMrMu =^W/hdjB;{z=wNy"f++GW )[ApA>rn2JΘɣyTO"!*87V__ UC-dpы۳7;p-VE3<+͛/X)jdL(ñ'}'nx?\kme8F>ՖW[FFI KQ`dKﲨؓN>ʺ.j4(s1ŗWAq^={CHCSY$L$o7яeY5OEQTPdm.uVdFXвªk7=x\1uVb: cTȮ8Qw:1Ǽ7Ru/[Iui(i$LedP.&낲weu3r87o)s 6d#HAJK|38 31rv"x<ZNRw7Ia{nlXAkۛ>5u{-}or?" 1:l2TmLP^DY5wߜcc ,-ⶡkj_X6ӹgH$7iC'p v~]1кrh`C/iosm9fz4zi )an9,UB.7Ư0{OAf]tvvB 1mu2gjb@ $b}9kv.AswX~dG,T, ޕeAvfbK+1Yy|c\(]D mm7V9ܒH'|oLt]u-]|p01`w$u;g=BPJ8"a-ݻyeGT3@O:xFj,Mܔ$;bE&E`+*T"carvq[sjU6aJ|JjB0͏SnJ~+gx䧁F/ no|LƫT);ʜV))Қv_e=\k)]_+ꔦɅ0PJX^kհe4?8)JڴJu ؛DWU0(‹vBbSh䡲ӵ꠪ڲJy# 6:/͏61ᚹ*5S¦HX!)rZ%ѺzbL y<1CAE [1VKJPc[#aUIBEJ߄Nb#z37허Y#De֭  c^K|<7uA 4IA]IatIhdan]4{+I3Zt(™dh_)+-Jhg\H˶l41,[Ho݇0E%};"D 2X/n>?u0OUU$HJe[,Vf ,l" 6RIX 7XiH=KM -$3H<q17ϋ5RM<1Gr\OjIc뉗N#fGD *å>f!dFiF۞>M,eWCJ~Y@BSm,9kw˝ƿ~"S=h ≡_Z@0$ocl,4RtPCCEY4SIAޥ\]<]vtٗJuK6让˧ʨMSI:COV}tuw$ھ~TP^,0LBDLDK+r^a>Oʵ#A!a':X[Wznka=4ydU?Y*h_/}*>cn.Tf]=Q̨k+- ak6,eIHXHmLc =>Ss[tWRK+TRTC:J0RRx$_jNG6a6]%T7$@B .oo_sȺa:P/+}AIU|[{tViE[3)eRYuIws>K5)Rs^ZLGN/:V 03G]|TԋcRs\d }BhSM+A"Dquifx8Hh{s 4|5ԕ+ ^n^͜uxYyҏ321XCK#mA.mmӝ%5EFIIQ>Q{_H,EͷMIi@B{j ZI]ͤ.)*zB$I,\M퉭]U j , ڔzxAPYH-ssůi;s>j(%J%eJIs}@;aWu%SOg`RBو kjql\퓋&̛79Rs!?P?y^m|YdzO~UAQO-51ԅYVklM'|?Xg8]-D: -R*!ۑ}%(Jl҂X*4 1$D /H竒f9&Fs,NGZ|{_pF^ܓESY'QX"LdPwQ]9sj*WI $<؞|":CF_UZFJ{?;5Y&ctVeS6MN4W{w66~<-F`kj&_X]OЎ0WBʧRɕUK"R4 "I٭o e'J'1ʌt=ҧRv-6u=U56gAI,7BCf투<_T^оuU 43EDT8\]s_-'Vq_eZji!@JkNr f&vwX}Fsf ACJ^a)݀s97,2o6g5Rt Nagm^QAA%=d$,8Mn}XK=H6IMu~x.v틮6@’z/M3f]"$3tX+ug^[k)iƖGa{c:%wVtVhse5hLfն_m'J3uUTQVSTMR-[Ќj",UjUE$p~ %^Oз`pU0֦"oͻ~;[K9e+2j3XL2H`lOH5Hr>DFX )۽rۖklO~$/-q| {`q~9^곕i}k>^byG: @5( noЋ\0;N`#] bf]˨bN)dҢ} 6pnXc~AcA qKTTլ,gK((Ŷ{e=Yϳ1*ZʈuJt):X{1;p?_R@ )&42P*Gfi0RN-K9ϻ8;h*dCVJmni94y o){[csPAYl):hfV.%0+I̱gj^#(MeDiY+ / pqoa8]SM<aXr1 T֓r{ߞv۹οvnbrkz!2ir|8j-$N3Ƙie/rdV-_ۜn_2m}?5>SQ6aRLG,9N19k̕n7oOүҒft  ĂX@8%DZϭ%qOMuGYuwGZ' 2(/NS krEѭ__T5<[Tt*t{foT=m7SdRgUy}M,K59eJT/67]6KڛY yĬjMm,l.S,!vn$uq~ČTKO)RQxhT Ŀ/iX//՘uFibkJ( GFYNY3?=+E,9NEGYb Iv/a@cyvŚROVvZ{!@hW˽p9~|9s[teE |L3"F`JA7 5ߍYբd4OOgtK4R 륔z6sl}~\.d [WSII#8[]@PNA7[Y-M/Z;y6Y$(l3>ʨۦzLTfHUU<{soo7jvʳʌr+k*_ˡAƱ˦gM$`.,}F9Sݬ= io,O Vtet$-Ř( ,UP,7OAϗT ies|o.ֈ|b +7Sc_6}7~]krJ ħScrXܒob-s'K6y1WNAEi 8j`KN/<(z{r-oOCViTM寓T|$$b l?oִ+LڞHOyU]>d y.qcm'X:#+A:J1?~;=-jH)抻; XIZHc5':{1/21z0MᆈRm[`̲EsX {fe^QQI$2,2H $^-utY{TJԕ,( 8ܒG tcû򺜆cg[SWW\&@\vJ{bMna:fKTquoWڦ*ITj'fDS$ bAQolt{->%Ġ3"!Pn^l_Fˋy+ݩo; 9foQ 5).rDq7'@sY7jc!&+q擤+Y'̺C STv|SzZ;$],6Rm3geZ? ͺ.3ˣɪ'J}"7 1&cm{IbUYA'펒]gNONm\sDrP˖tEN[.E74QJFߞO[I3ҸxII7]ObN=G QV4 ꕣk 47 ?R43{ҚZzh35>iCPP"wM|2 /<1WBfrڑ ĞA0e&o6qxj2|Ext&{&ی%5fEe9EfM[_$<_MH%]5nHއ|]o<~z)_0deOH@)Q(֟}{*x|e|c}U[質Ȫ& uXzwujOѬ9Xń1@3}yMrU[I̅J`%)!`gX,w[\ AbPߛA+HZ(H<`$ lm5 qm@yQk`ZA`7OfBM~`(kÞ8F,lNߦ2)ez`OI5E0@DeLk51#s?U0MT5E  ^ͱ̭Ym˾yZf:W΂"bcV=MYYFH-vgOeGR$0P@6qmRc;;2MC&{A\=4SF%T}*Q][uUPf4mOMU c$_qqb ĖqgEeF*!Ee*{ðкWNVԌ=/ߋb : IJU"[ӽLėpkGHVoi\7?=4Ax`>"$$X \o1c, O4qrv߶i``M,#4"-f£MK-}J0R~}`lz~k{U7W59DD9El2Hy 'C|{بQLBo-/3A/ .jVgD%n؃-WQƧHi#Sz  yQF2W lCۺMͽQC&cݰ^Mй sXa/NDGSt;W.:{ }EA_O/'U![SsÊ`-FYR,?ͩYZL7^VyEѤf30MOI="gOQcozu6 ***,\I]{,,IL5߆,H" HAckk퉺hhe#b}刡 wQ ?\."Xeefiu 7" DV*!y |MZw>!mf zN]3Cƺ|+[ŽLY&sNc3b˲JZ9 C[_D&Fֿ1o;kYH_* g{o'OOL!hj@k\[s+%6m.lͤx8(rܫoEKB*C0 QQ1z<&[wcr?+}1nY>`p$m P%mݱ%YUH*xr [N2)>Sy]Vqǐ|hV6ɱ>Rxq.(=e9nYәe6O:rJb> #oPO5G_,M4qXJX[]Vvf^aԈב $P#5SauOŊӢ3ڣ_QV^5[|J*Ye-Ud1`b6, ԱSg8HQ5O@!lIwu#W:~0s|Tci7́;܋y0F-u{q;q\TX#u_M_M&ij$1l oQoK;5ÖSQKSSe\am78׆NEdv |J,0]/#H|X$X5M|JRWy<1WN/Y^@OTeut,Ng_۸$V[p(j:j RӰTMl]j rt>Ka~YT$9 DNn b+UtQK];M,U6]^IśX}+b9 qmn跅E'R:|55Qě.#\5u)Rrgd)tԙYYR Yk/`{Wμ):) F=B\/` 77q]-:=ꎗ8O48&6cceѤo%_cHi瞎(QN@R,Z'gU}&AQ冒EA't~ nFm]XU?Og[֑OUI˟WR6olsꮬLleeT R,ZEm5ȝ GRejcAyü/auL3ټy/Eg5OK%JբsFXg|R9oA-7ɠ%mkcQ7Lt^mP'",R{z9Ĵq#g= S6tTJSM 6.j+:& ,zZʼnebxq;WeUR즖+O&ct]ˀ-F;پqSl<:fE,+PFTfP=lgZR8s҃-oE^RYVP&Fv*,,#BXɨfƫXR-8sKDIEQSL Jڈ`Hc_Ϫ(󼆂al7W-<1mb#}}0;y0UNlrlQ{:# MP;zhHRnmn~`c>X_դC`;X<y 5y`"Q+Qh͆1F"c{(ۘLe+! uPrӏn3\H[H1 0`m ](9a M}I i=! 4Д6"IBuڎ 8d1ȥoalg-jƧ}CۧnL}S ;GWgy/Vtv}9e>e1AMqeqztV{QcS5C]`Qi!y6NmtMuVX49zSƮ/>K~X ܶtdh˲:: 2JjBY4bߋ-/vfSe?:I0C+1ul&ޚme494PLFf`N{eeZ \ EyHeiAlf|Wgoe6HȺ-:rEJ>ߞ5~;ekgT5G[u 5} Sj} E>.\ݗ] ;e jbhCZ+lL69ny ΟR|Qyq5\M$ Q= "Zm~1EE[UYd]G4Ü &+7ҲbN;f!j K[Q<f]K']{y1an ='?(J{c}c%̎SP )&M8KRͭ_˗GSA S/[ j j0K8̫ͫX޺F`nnUO~]!&Kf1QQ6NHsqJaW+VaQ̤_:+W\ŖLk-\*LܴX/28Nƫ]Y4?YO_MhVu^BM@#0~suw ޫ5̳L@PcZϪ'2Xr7zFooA,&2"BU 3I23{Ƥܨff!NVf|H+.Q([H']zbYWh:;wҔu/RTOW2)rwpԷm,3HwƯWh$I'RF{מ%gfd ,lYuv-:ޣ>L@+y)X޸MH˳3L0ʪRt52U4l%= ̥5h"Eծ-r z7z)░geTY#B ؛X tC7L3KT2t4o ouZ ajl#s|OB1am&qt5 B8_$/21ҍks3]W5;?&-4 w#'{㜕3}Hk:B *jA:%-A7yw=f]ٛKSg|캩L QsBq=j*Z٩x@# ZҶ*r';u"rjafI|Ha{npX~ tEHj<2o{kb0?"鬧,Ⱦu"hKTN$&r,G|\e^9!TV͵}m%@1"/{퀚J RT}u"瓵Tv.D/Z[HIo`Xmz 7oBpt3TW(XWBD 5C[Q񠭥#om&߯8|sVr;lo70qDE .X%m}ZI_|_TuVuǤL-Cɹ+lc/jwzyVM9E FE ͸|q|2Wl= c`{bfត)Wv\QJ#kbtk46lT?V;l!nJeCEqb-ptF%r,- .#ɚ)Ak~X9{M=.A+Lё }|D5{]&''>_KPJ|e,o}=um &l{Lgq9\vf5Y :o@FaVp#xLo9%ӾcR|$iqPdlα&~tf&RuqܲQWtf㪢.t˚հ$ q9?.e^vc}y,U!lO^m6d&eTc@/(߶7ٸ? Vp϶&>Z7YV1洝<e@˓x|@l]ȠRoi:%v]+3B-c'[m|Z-pv8DۢH W$T7J }0$r5CI,oOޟLimAVR-ŮOؒ)*Y ~D0 _QIm3Xڹ?Dqz Pċtí5(H O 9nQnۏnpЖ B.n0@CP d`FvgDxH`cEͯBVHm0N$ Q(oX}qw[:.].oUG\/cqXR|TlPEo+f*,!6.E[`:`I4 5VAa`m/+:3edz3B|v3/~8ԺMqQ֢B&R T;" ~jo<A{k|ѳsSiXA{X`.y~A'H4m$oV)$fOx|\K!w2HY>8{]NԪY<S\E9d`v,Y ċnp}MJ ^Lͧ8P5] y7]{CIə*j,GBW5] 1`Fߓ~1w 1~B^1[/γeefaIŶ EI a"o34LSOO_O;F|p2Lf,IZO 3uk_0kIKJ̆ČD5aqn' \KIR8)?oF f7dmcOOe=+/ a1T|v Kyb_N\LKXRyjK(e+nφg繟UOQF=LT joøiyi'Z'$jN}}"j/$#]3c[qEf8R%Q{-}bߓdŤdEM(/0Uwqo'z\Q*zFZ m'ޣ1eKYL˧rՒ6Y 2A9:) 6E6W-]6[E7PQ^VZu&)qztNIx6fQ,ӱ6`%@FIWy{k$+u%wKӫdUV@6:߆`$d=;G׏퀈 $\LAh i\#p'lU iيfi< 96繾I f%4P/̪rztQ$,{pof唜,ë!pj+>k\<ݗn>l8Yeϣ >V#`̱byqdc4%lAUúvOONIqo1&Q9R \*|t!&2@ Czv'kVڈO\<Yc󐏩v*m@#}pSI5  ;$ZD{q`w( tCYN0OS#`|A1T(]Ch؀<㓆7u/A1 5_clteHyuu*~x PTou#.*lM*g34UQ;!7 f;c\X=zJ|.i]J%ELl!. ~1Oa5=yiʾUP :ZJ1B"Yslٌf$D]KEca+ J&,]555I&} a~J{`\.E" K=9;\p@ybQf"`:#[A ;xo=KbszMe1>X*CHs)O>g~!w&mzmEP"r@s-7_OTSMeU%^ky:aIw<2T[.j|t/˜ygK$rϚ$IpVHXM[|rR:7ü$5е0HꑎT[kaSNތf:G:>;mYgLr,~,]"{O# {wŖcس}SKQ_5d#-\Qbo}¼.QK._ T2@7D#Ĝm5ae\Ks9EM}M6-*brDY$:u~W_Yu*%Z]UDIBCO~8jj҇z&سe!8Wca`1奄,ҾrYrǩ  ZTe-4Fד޸햷l_AKUtyVSYyj%XjY+ľĺI*ޗrΟ#}+2ӲMȿv^jjRc: ES+xn}HS'oY`ʷxe@O`MM7SR7Je[ OWfc͆$˕W>iBk*ڎP*UppU7>7=mOT$5Q4S !!IBARmǦ5ixhg\h 1  ]]&сh8dJcTJQLI |~xxfmr nx&BڕX-Oa`HYl/>q4٤z  ~\d }2 |Y4a"6{< i*<6rTw98Kfakw8(հh۵) \X y7؂)$UrAOoLK8X?;15-pُ>Oˏݬ{}dR2Gp5w|Hv욁<-ljy;9 m74킙d .5/dA6߷"HЪXsHZ!osD@ cúYEwD(xPt 0"B[לX[[X#~pP@H%כmX@i((%Braok{疴Fi)ਫ਼j6y~ظShbG}J++^"]/+m&`:銒,F_y2,#,Ƌeٷ鏗ey/w7ij4k`<[rQe嫟T&Hd̅-<ڼ R6 ,A'Mq\=g)rZIJL@bRiXzQAV6;\o|ǃOPmAS$"#)W ~,iGž.E\N?I?޺ѨX\Z鿭Ng73n"iZXÄw Lw Xư^f;)9z}#!9KxrЮoII%FZ 5DqvMLK2*@l$߮?{4ToA$6HUT&&ot^gf?gxrV},7؋Fs\ږ/n'yd9 Qξ [1k8o-yzղ̙g*)]5(#e:|hks bY" i$~xYi4ݺ=bvD%id#t S#ޜ SWSJy~YHSgfDV@x;+'VRvp1Fᄔ4*ijqSea$pZS*zW,$jЂx ^L5~$٭l+i[.HCKs32}yGϟYKS ,Wϔ8Yã)Y΍(*sHkibE%w"wS 9AY=W$TTTs 6-x^>oß0]սUEITz_(‹ "тb w8p-3|s\7ʿlPICQP,bIX9FSy^&*rVծMvCŷƦNψ2C.UmŚgkXYU_Ԣ@#Pj}qGXQ&US+ >2h{7a.aiESԂ QΕBK^[7-l-lčB$+|7 J ׿~ga}l/\*\Ƚ<`:߽\{1VQ@c+#K狼>/! c#ÐGjl|?[aɱ;XWC-oI+'@7>VjgH)k i"\m`HķStzO3&ERU%Zqȱ嗥?7.!j.NĒsc+]\ tE[)=0TtV*},>\"U5?/c8ue I*:l 'Q@.ٲ: hEXD3[1ɯPFieIu4|fc;?FG53*r35J Eo\.pha-%];0,rl^IC21z Z-& ;q5UOgs"*\n;QSfhWSI LJs|3o;GOKı6lr>\5˳^"G){|-Of/4CI%,Y< ~kp/Yޕ i)3_Nqq3iy'^-gٙ&î)u<2udQ_l:vxaqqmZeI2@I)ӱ&PG/IG ln@670WBQ差.ߓNjj_"Pe>JfUf>cښgzcuZz:Y<.^kJfc&Ⱦ:aO&"qk5c947Ҽ;#p #,d\ #RHƯ9_WTIcW2ܸm2(*#0U(EBYn/RIK=geXSY'\Njb2?ZeuVcx ^LtdT{=8S|>?fVVLdAdZOiloݽo;}սKIY5uC>}<2Ng؎ooRTB2ֻmm}NCM a2@xװn1D$&jFÐ(^G8r+z)L3P[ܐ7-?Q:(˒NmO2K S޿|t:h:g  0Dvkw=pn(Ұ@qo}=鉩ʺ^L<ž6jjXha@onr>VG{03$\iknO>,hzK1s3lڢ2ROLtFzϝ7btm޽e&u_(um'I!tN5[ quڵsjPc'5T.Y7-ٳɝWS<|sV־mO6̾SG3h .XJEZEvU[4@\q)j#UVi(QZ*bT0Ž>Ynv9Bƪ UfT k؞5EMUudDRrA=DR/c܏7#̆x(Gm-O?A[굺>讠&z9[EUK*Wq^]Tsl4(Pwll_MG*ToH7Ʒϥ&QYruV04>BHw@V-䵀,G:hHmvD2+m܅P;ፀ- 8Frl-bVXޘhlXFEy! 뵘Ƒk{H4$V/~\~޻VbJ#`-$<Ϊ\( ^/5"Ds눰B āTWy;+[CٌM7,(4`ȋMG: /7UٵM|rE4LZqn@?adUU/LƕUj16;mmj ^(~aY&3SL˧ENIHK)p$ -5RFRvFAmdl]"/᪓G0z6t95:YǗĞm`ḿ;җ^E䫧;*S{\\J̲k R}qђQ9 Kj>b Kz\qwJ 0!λly%[e\qc@+yOaq>p얣.ޡ)$F{#0 s1\n{>Q?I q>ͦ]_Bn8lvm㧖y >z~HjiR#ҺKݰK ڼX:hg`I#}l _nA^\⺮4QT׭> [O+9HtvF@߳M()GKGhR @7޻4>0"͖˨(sb?z z$ 3r4oO_?i,*Y#y1))HxYD9GfsfqS-$j䋟ɿ;˻QRG5*$Kˣi<*J+jyIYYe+-a٬omzf<滦riR" "Fw=-oOT7ǜs()Xd+Z6QNlWm-=tsP oYͮDT+龒 5dSw҃-ȟ&|-axɋMzm;_ zj(yNTmĸo.^%3(0]lF8O")he`@n7Ȗ R*dofe`5TM kq%~xb.RS et_r=v:Y]zn.m-@M1ԯQN_:J 44QU"PI6o,]zh:1&cRA,:sƋ ̃s,˧ʔ]E$$-x1,}5'QKO=$7 Zl?2p@ap#iG)8ހz_QRVrn4 oo[~wR]Zʂ8f/u4xx3?r$}!姄?M.έxGQhU%:E&S{Y';"ѝ %{9knnq稙.'ż|2Bt&=Ҩ 0ü<ҤT~[[jR;nl +,笓ŷemQUTFf 8+."fҭ]RB=wWuOݍOQ5-"zbyEUtFW+vHW2u9;C2RԬ6#JkjbB,yW[ctŗa*cx'^\1]qAmb,5i'pifk܌%/E6_AEI$,b*Kzg2o .aLU#Q‘,ؗVh֡K5;z_ba4U XnE$Y=1";. VD/|~ y_;'4R2_qyoc2U: ')+% m%} +9ܧTzc%*i+UDw$8c{-ƲrOɆ8`wo^IcĿ5S=* wUqr$r1Qs;z\]*w @<4-{;bEyob_PEؒ/_K+78lK 6!^֣X &FcV<]2Gea 忣t}UVIGS34)!4$\{ |LVJ6vd]2Ksn;ˆ>MH$5!,X8_[Me;*WZ y!U{wU"ck{maid+ǰ-T@jC"!k-' n Y#ew}܌.ZD`&P`.nI4XT'227zEW]GXsJ! H/}1Um$&dWX kkuL}cԬuo:ݔw|1xzTOOUUd4ԙɂyH;6YfiueNS~Rf+P,VӸܑnq/KTF?V'XaGCƓH<۸_\_iiVfIH7{H>obA.j3I40fFlv|^;[9az|ɠb]/\Or/KKSO._3Ȭo1"IJՒ}W,'ՙ~ֿcجL"1Pwivwk` mEDW-${H;#bΈI 3j^EVk,7 sFx:o{_`4Ƕ(b 7iF6oX{Zֺr?,r#cSS@m{a4uўH f[M#{k/D۳!̦4t/LN|*kVIe`!o6dJ*cB%cy?{ I4jP'=؃:xϖНc6EIowQRRi Hr}|Ev݉#o0ﱷ1fP I?X,KST+]EMkp7/hi@Is~܈RDI#"bCjGg dUY$ՒO}:w$JiYcWo Vj-=qvo$c낞0jUaxkrRw*C:>H^/矆z\!PSGSTsVve oMuZ|LƒH!kc}틎RMmn6_7UfJe6qixX̀6exn37qՓw7Ӏ 8 ^`_RlX/忢y~WUImF-̕j +ٹ~/y\, Bz )S|BgvV"SP $*8sUS2Nؔn?+pM:eoOнWCdU *ԗ:$xǗ/ Wi^cMQ86Xcx)1co) y4cY#ݷSCAGʨsSE7mwݯka;u wVG{ "?*lx{=#I!Pchm-rxo/P.OuA5&%>bL{&:3+ڒ=ʧs قUD#~ZϾ˂AT) es@Ǐ/&7im[CMf!8 ؋xϓ'=I{,fwIeк1ـ$t](\G~yDU,m=HYV@'H m`iU$w 0_IJcN+bӚl.&c{_ {# 1v7'=1DJX*(]+]Jl@$5ۍa7p73+e"S|Avl+|0"ofn` 5{&.4+}ɩ8 N^yLQ2@ ļE{y^OTorq?ˏݬ|CYc|VFY̗ek(a?8l#(,ohz:apLхRwo3hvѿ˘B [3+$$G `pޟU\7`JSn1gt]KP]ʭ18(`j}-dNy= f4nVC[{v0Ji߻/{}߸2}B+k$ɥ}GY/dYO?熵"$ ÌnvgϦIs1;YFm~xwYY, #ĴD+[Ok[1\iϣg>xs*;,ofRCcUcpHrp`mpI\Mv[4l/*ȳ Ȏ;o? '6wPƴūvYN]eUTzQYZ#@ {;c1en^]Trj&A`B,xƮv%m)H7%7Oʣ0- ]LIb{}b#,@p_sCc 3rTbƂ[.u!qԴa꒝\\'"0 !gYJK "Xb3I-Wη?]d4GWttȠ,{=3컾y kQ[Fim@c25 \:ze?o}?W-lQGkjč4q.eGQgqTe- hhO$B/eϯo|춰#4WT1$w&cO ᔦT>}v$P@VڛN{0S+Yl[m'nzVy+hHy[VcNgŚU5 nkvMeGQtTMf4##csoݼ>}͝²3L,zH(#vKu ꕛ:h֍"9 c:jk8<~<єk-Lxczt:JhMXwz{"#xhu Z4Udk'P01rKjeX]'oXPBAnr3)pWɟ9t;ad`fQk`, 5:TX`MTvM]f wc8*Qt]`!u;y[~0 DB $}M!Qam"k+k sӳmmS|$Z#;~rl/GJwrm r"qpޖYT[h'%?oO"C$b,@oxeuu=GАԕYmKJU!"<,t|2[q@~\~= &Y@*u}$b $ AOq*FqG\YU T%$5U""{ni( JjqpϙSou}@Kye3xmW' (=ؘOmB8VѢEÙ Zr9 uR&?Aþ,t-5PoRp0UL];}"&hdT_cpuZOQI HuƎHv[~cKAm.XrJN/| lZKmcc*;2O"#25"܏=#H(ͅL*H&@J79ԟ(/[Y?`R%P*x[{,j" .5k`#:~G_,H$ r* >O\wsGsyxo/(*l}EK\2%L'[ȣv$c0v5=YiʾqS'TKO1:$~9ߒݹ]Yޖ gUye:uM:eݜ|+Yh鲗:+TV,sNGoX _Ƒ@ 4BI`H,f?5>S$2RF*eR 8]lbvhrװƱNS{rHACCH[(35$4#1R?ݶL%UAtQE.w7ƭY[vzz^]zU!Lʥ\ ^0;5ݩʝav@}[W4t f YxOO^LҾRuORc[w+*ֆ yVf!:Rֿa kƙM6[d*4,ĉ#etJ%HҖvNz17ݣ)Mǥc^\HXOmb:}z.I keT/k6tKF4+C>%]Wʒ9CɤjX6 .|çl'Vu IIQ@;]r~,uZ2x WcT$v6v+YǛS:ᡬZ0B"*Xi'N&7ƙXԅ C5o-یA{ЬOV(fDL*1v~86 C}'Iߌs hҹRO]^**+J"j&݁ykϟ$BPg;[e\#s ELs2+6 'r3PyzR0\ܒþ1/6#I PL F_\| k^^mA K%qb8m5|^>\68)r^I@?}ƪ.jܳ_ɒQYF񱈬-Xlzr6#޶+Z3I u2ĒnT_CXk WR)JS˗/ԱcÞ?'~\yrEҙFwk3(dj->m卽YdYnCӌkr1񀍢V[~̗뽃烪3aACNfBʍZE"bxQQ =t&_jBă9 ?k\TdOKm/L1>vCҺQTg4ґpKqQl]Gh^e51("МN6i^EDbKsi[3" 'bqzwTIP1zj*m<`/Rypt]ET=wBzĺ8-y\Yܽ]gZ#y Ƒ waæ6Ptu"\K[S $; ~zzjXi:JU)4 [XׯzsfŪO^-k+ݝSԺ}1Pt՛ [lҐA+wr42Ur;`k)2~vr-S>Hoٗ޷ DzV K׋bk0 !H7*Jᛟ!`x6$[!D,fv<noo |t\| am:c+y,ہ Jy8"_킧@xیT'*n M.5 1/e`o껋^ GÌg1z$,0Qw0zaK# @Xb )YܰāÛ~W^Q aC +#[%Fw$L^yd@߷%֮ݳ c}aWC S<6-nOardOʤ+$`bwvw<*:1aS -(cWٝٴrFf5@.]p,$- {u_^Fy fbEy'JXCHBa+3.Ե: Qh?u!?zsO$ʫ*?]/\5Բ̓$򘩿deYeSQG;Iog56.2Νɲj=U^_|N(rΛ0ի<,<|3{= A$$a9=;zS ߻;[d6Y#fU-g<,TR*6 mⵍwJ\$28:-u\c}Ǘ?᰼-Vo״ٕebƝy78pVb=OpuZ>S$SPBlHیPKRJmrN i**!г$`ozbA ؒp(L^Ĺmԙ\׾cج3݁*INbT67CP̦_d]iW0f]Xil-mCl"R-fХytp{[f0-T,l4B1-Mm8hHU|4mBB^R/b1;װkv|P,.; AM@_S[~ :Ȩ'8~L~cFg]beO0|m 1:V@C472v\ݒխ(v6a/͢잣6 فq1+ ce5jb񦸞뉹MQuW,b*BFtmysJ4"HSɤKC]-BMݘJv&.OdtI4UV-0n1W%TAb69G܋bAJY`P یE Idΐ>oi/AamCfޢFiV!4뿰8%+b7;\}~.?Y)VsјE@!{ک*YVEnDѸFL5d#ӫkC;F򼶣>.fq#iji8ijJNms.R["b+z_k6\8txzl,uwf?͓V]iz> 'L"K3}8XIM,~TC _˲aZe/S%QP Iq`nޞIOO9{Ӕ=m$ԔI$oA<U 1{MqN:ޡ<2A1~i&50ڭns_ ^g>,{ {~ ^՘ds8Eyq)#PRk<1?˵LUb$(f0(=kA F4v& ~/*R &}wުގ4lWc8}AiQ *aui2#v;}USHEĀO6?q)q2U̹{[xޘ^&}ȔnXyQÛ=p65455vV7#nt&jQS[Ē8xl͆O RKv-Ҥ) l$oZ}D~jb҈9"j|!i,ʝPڊي% ,Dghd%K}xIH(v=J&Ue ߿}5U$&kY/s+G;ƏQ^;m+IֺGnIg{7Q{WGMG40+^c3r7^:,,7i∑4mmpoٔ:|w(+(:~<6+RYZ)iR=.(х[zFRp@^|GӈpjdLH] Ʒ>YZ~N{OR|pP\AV$n 5bϩ`kI=S sװ]5c+.hImKY'NT3L6FM닩;TiX$хPQ׾k(Mu=D3OGK!HAȾ%8STSe٠ij^|0A,n5wQ8zoMhrg_:5*sz*9@J^I_S]KtYS˕TP%*T˅7 /{c{UCgIIjVsiTDgl5zdO>QFayHGy09BN8h,XsLҪ/iklCXkaw-Mm=9y^΀\i"{zxޛi3 6'<㯛n3oU{HZ.y ױ}q_>ל{evi9o5I\K^Etm1%foOS~S5$l~fu#HۂAeܦX嫸5rx*:d3dL[Pn7?W6QQYVQtf}R IFk:܊3h:n>rL)A0 ٻ.m}5X,K:(Ϩ"-Fk$k]X]@-%l 꼒 JZLiȖ>b6%$4so:j|~ e]8*<19<*I/ `Xr}Iˏ2IíaP:k *5F8rIdyf"P?J.]:p5Nhs(v j JِoiiW絹ƬtY<ٕ[QE:+WQG*|LfXW7܎5g ^+49gSWm-$s{bRIԬ/5\pX\x c۟k`FX sik6G erָv [܍&,Wm@VvXvln<ݯP6JH CwO68y_B3vÉxW|7{WRE'ka$@(X{mqK ,{\tM ~t PV|*JaɹFaoaT#\rvnl":SK*9%G!t]o炘,MYo`;bU7[ ݻa{dy+yX(|kjbΜ A$}6QOY*HMY>IS5X {wæZj: c9Z&H) FزK7);Ĺ'Sd40S隠ȜY^p^ךoj-BH܈tuKRQ k_owuR冠ncc 5u-$R<}$0Yzg7 wKSuoZɳzo(Z{4ltݬv=3OWyE"RPy4u$}귿]F/nc(߼52gdZZ&0#kn 'uyez9*Ξ[<3*%zWƮMKTL IQ/7eŭx:Lu79b}z&1FJx1:̛L*g9^k_U7btܟ.A:Kcrt:Vt~E*ln_:#M'_QeL4i5 Y$Lm# 6&4JG#kcHɩ U] qI#G%- *V )#z mr xZW$ozՊ9-ާcIPTP@mQ 53)6[ ׋ BkZd,1yN[I3|ʞ8dhlFqekRUIJ(E72#_ުʩe:Y%t5 Zݽqe]ά:k?򾔣QӴe I%Dѵ;yLt,teCeGQ# yUdqn2LSvQ#댣r ޮg'Y7,.1Uϥ:6E_E]UWJ#),;AZv꜃3Q@3: $b!o -m;[gnxE]er?[,0#r ;?3/[eRP|C˺3˲캊q"눆X淚ɽ M7*: ө=sX8JDHIK6cSy/n>$w4mJevietK*En6fl'_=ELiMN:}uP+6ųcx\ut10%JY#򤀐k<_gJY3OghĆ} ǏYm%sTqt]xPD9.ՒLW,wQ嵙Nt]M5Mdh$%zw,tsOW6SW`Aq Gfe=EbceWtoQuS+3ZX#Fhh[_%ǵLq_?+*$<ͨ ɾY-*ȢmSӤDT*]Mȿz6:j#3J&xm@*mzuJW@9hJ.#-Da>1?*:_8IVwFÌI{\܁ͷܱuB5yKGSIjU]A+n,5%9fTMQg ^fyMSSI_6Xgԩ){'Nxu-,rM Y_t^t#![=?NRU)IQspZp-z=+d=##6oY%# Nڍ爛oxQO2?*Ϙ+@aCql7tO7>?w'囌Mf fD m1tJ av$hTpOɏݬ{zy PH,xhp2 ی#!?m͏Hē[^J|U>N,᜚=O`,튊e龔j4,cRlXaZ$z'΢˨*5TΰX,l,G5z{>1EK؜&eubH gLxyO yD Q4k6nxc:9>VG9WQ&ZVuؑ}$pOek圽uمJt_eՍiT幧Sf1Uҹ aR4@!m*G ֞;IVCN0ǠC- -pu}~q]Mu5"j*j8nH6F77MI_~"o^؏ِ3)"ՂTW$׍$ŏ7ߍ6 !YJ QDp{`& M\cZ%K +Y[`B`& 6=(bF`SlajUH 8eXVcm`,pM;cيKy#h3#&RkߜP;~+hd'{܌Kcβ08 (S! Sv~YZǽX!l/ U <9AV`X^m~آ9ĕH:[OU*y3'N~B!Vܓ)ĖEf{aAY%?^}L7iM^ar};+XR1ؐ=8" qbv}Ŧ44{X\Ǿ&4d\#Kbtz];HHVS*GwL3ܵXoug .L[n}v-T}SO5LP̌dյs5ռ\3fԫ(1IYi@ٵ3TT(Xᕻ0;Re5Ln;ӽ=9CP˘ޝj#H_Gn;ֲj}feUvcn<>3C4V2d[3;~Ef@Pϯltǎ̹s3Yc9eU\,SWaE_&[RLHwālxc>0ƿD~e=GBLuN$f7P"n1+SJs{-X3Pej)Lmqܟ w2'Q5nQWWXOvE0rtwƲ,ba/Y 33HkA?3>le:-WSg$qUW,Ok;bO3|*'ڦ;u:>ON+Ξ=_x Hy$~.Xߏ4ʲ:1OT%1WU y A6dӥ[AWIJchsttqbcLXku^cKǔtM8aFD7'IlYӾݎ} y.wrRf&al Kv c-kI哬}Y?9E=k2=I*`6sarMYo[euHYH1E@E-osejr֖]MzД6Pe{Lg̪}4]+>Nk@Fbe `}p|vs5ӔUG^~٩l)_!YolYq}90R:-j2nA\$Hu_QIY_MrzhQXKwb' z pjjh1=bu(cqZ]5ɫrtn]_˶Oi]!4ܝD l96,H,.-?LIbnl,H0凂ͭՍZm3@NK#թMGljAP;ױK{\E}PZ#:F)1Zx#Jy cZB:{ ӆ΍'?IGFū/&IG_Sb Cʓl]&b @S`뉥I!&NĽ=])ւ[$ 6ճcsO*[؂IƲĪ 4XUFVaomD2yXNv*2ylkw8D¥LF{78Sƪ  .J$<:@sY VCm\q*2"/!֚UTF>IS}$i-툨iWS/ HQP#k K$Y!QAq&U?3|,ξ,1 -gDr<Hl"iQDd $qb#82CȾ3lQquSn7I 7lԩ5iH/q˴QAzX)W!$;Vp3Urj)ѴW}yňM͟C]7BBH@,ƺm3̣'S5>&JQ/;[o[ugCfe_F*faM#,>gK .]ymת(A~c<6ď\g{1ڳ5/QONHv$n.=M r|aS4f)Z"/mcc}qCetfP5㑉&`/#z |ϟ= `>- Q*  :o v8דN=L|8㦖HzѼhou#h:~iZ5 tm8ӯsޢc|k^ΙbW*OsW5_`W[LcV>Vʚ$Χ%Pm<ǻ7N_ e"ֱca앺=*##* W[ݱ|ZSI9Tltrj!9JU+X:^Ou:X8}9>*t^dHȳ*chB@fnEއ x2SQU[ fO"ߜtj3Vk,rDCGpogk=bb7 ,'fJ:t^=mO%F펒K$ٻ ܎Auns5yRX"Qc@wk9d+߅us9d1,TĀlAŸ;x⛑\ 2L<2yKȱLbP7ㅲuA~/׭e'dfCCm&.;ceY}6yue&s>I4-! fq1 B ƄYaSMt'5 WV3,VT&ezŞ9!*MMy'|cdk|;~QyxcQkw|}g(,<(hc ה.]U0AbmruOmEr(&YRʄlO Y[7e֜Nq)fe:Ikw;onq4ѴTlXدnvJ30j ز[BS/EP(Bid4{:lxL&׍|X"fVc x3obU<]qG?J|?IIɖ~(2zX]U{lqlջir}o}[y~cCI,I tNDos8e7~)/$A##o$yiV|$_Ve6 caV%A%m^V"%=uqt=Nec:Q%M|mbolK8Y=K5(' moc$霮ٸFfT#ӈb@7AG|(jVGfksms:kr+Qӡ[H*yc=oD1飨zxz_D {s]<*̽Bjcfr+)qr̶#3@,F7V ?Q_ sԼSf d[]7?q=VlbX35LeU<'w:Fm`8h p{yn={p[Wln3`i>Z2R;h^;~i(Q9&3KF :96{%oQ~ۀGqah? m b1z*^~^kFP8$[{ 4 w9Lq@no4GV W\HFo?"Z5i) SkqǕ-nsN֟ zn5y!H 7݊<1ÖKMḁF3KtRez8-;R# . E?oy>i <0\. U̍fn".s_3. 5ҴY$7S DwE"MۜL~,\z?W rǮe'Cn*תHHҖ~?Yjw,x"7wnt f_uZU[='jjL-Yb:)&I7;q~Y״];n]=5>gJ4~ewmMrm{,7:c&*3?_O[*$džqM sSgn|:?g2H/ֵi\ݹ8MΨԙ^GӵfURUj;*xkf8!nJh('yFC57Ǧ1q{.zTYM˘PSV_G 0"&--7ͯ*\ƞ־+bQ4(TÆ ls鮙]ݯ:9~[_CWUQ%RQecS%dGI#7?&[fys{ j4cav[M󋔳ُ΃* ͩfQJ?.<0 V=+cS~6E=&Gͩ3ZH%0Cڈ'ͻ {=JQt4^ , 6$/w|?O\Z8jX$EX Xđlsռ~"QGDTEC_(X Jh*Uˑ1btk߿.S <:jh-XѦ U2j&o#nRހLec*ǐEE[L]81:hKm s-Rew_@rJ:L嵝w l{oX[a|>Mu[Lul:2ʳ5壣I\$]!ā%lmvYO ^g+RT#4uu-\_{[y2zlߨ3*ީ91JZ٩eL$\ .7?Yd%WFHc0ZǍ1IAaܓʪiȲXadBD!PxI>cltF:(R2<,G q/e[Ƿں2^u/USUCCWMO$M%mlG#7]d{˯>v^Xq&LdJbZ-3m򯆵+bjgaDH&ڎ9:K߅'N?2&,URQ1 p_b/+57'T\_Cu5.{p՝<:#hܝc5tomq_]]:&[!Ӣ\lxr_5*ʳndif%笁Xqy[[rG7Λ|S t;R6x`[ۧ>ѱ_ߥ2Yd^lKNN}qW5j><f㦫Y,>%T{G._E'uaD+byfl v>Kas ozixݣF1}LI]my-DtGjD_k/7=~̝oK==IB ^e%>eMQ:1,ǃ侟nLw:/z%sηjyֶ"lJ;=2- 9<6k.hG%H"ƀ-}{:e?^KεE5c)嵙mMmT1xZ K_}{i,v,_u-njk֢:YRjuX]7 ϸj%C}E9fY=CESƺRv{m-D=1]I&Y5[]J"Z8T~^̚*'x"-=±W~q5n,˹)t'Fg9Mnqfse4Mlg:iQcvçR]d9^Rt%POÕfSWɗ0H׭pRqM~ns9Fs5%Eu<) 6 -m#ӽ,Rn}rWr*=sy2hE8SImW߁8YYmMviP(ԎC [IIStNC=E0ͅ&Xi_5C!2`<Ř.}m5.q|lJ$)d+]Ŵq:ns@C˚rKS7wHBpޝ77DO=kjȓyϱYWBQKrd2gqΉ- L j ,|]f)3 bM8<%(eC]/ )6Gפ.,Oq=Wqì3$h fSY2-Ŷ[bug=~g'Kj* BQ$1@8<ۗ|T]?.uCU|0XV_8eYP%g9nYWUI!% .r;(;ض89Ȫ3:|'zZxH < J~ 3AGԥ9P;'Gc&|:4e܅6;Ƃ"MRTfG TIf+nHuw\.!y`LHH gMUcϦYӬNVMM.6sa,v('YurMRX<}q䗅mq#oɾc $6TRrAz`:c!iʃ+0 \yGxw6؆)`,.-8O'~0 ۝oepMV``!`\rLNYsٔvfX 8.nyC%d#k},./ӶS"E".>*s7(jetN=ӿ'{n_nw4jc2iCVx,GLqHP?[AgDfVm5voI Q(iV 򇿘, ϷLٙvr_ofYGENЮRQ6^qS)YYi_yyWƑOSJcofShR/l1ˢYlxٯ]CC}mSzNhaҖѡ`Ƶn6ee$TyO[#%,>4sF 91wl߅]y@et(Rۀcv`1Ma/o[LfA-|RG3lEyn}j:ULe:,Ydž-Ŝ/'***,:UASZl7)+_U[w_aW(̤I#:z*hHTمxˬ|O6ke=wWsx4P+'H*݇<ϥ\Hz#|LZ3%l!.F)e7."ꎙȺA2,ƫ8ZjrHJ/ }M,vƭַw%쓟꟬c⮣WU SM4O*ۛa}_Tw+βGSUd4TȆt&G Tܿ,\9鳒畴GGfYDΐS3JrĘ^;=6cn[:N*G(1J*rg"VoJr6qWk~ĺrP26Yԃ#|zzZ y; wgjņK]3'U]KQM)b.61㎥-~]OT٭UeMjf4}œku}ʼn{̨NnKM fbu)Y#k߰8)oW)of.j.[=w5 xR j;jusl./CcPALaE(*$ZvS%YbIZ|G]N{5z2DKQh{b%WLJkr:֞Rgc.sj̿doW=>ߵsjyZJ/Z5$QUlgzs]/l%3毧\[T6ct~qY4C]yoy~yU5CO 4}=2Isl_ԕPSd5:1,M`jTc2;8k( s>3$cIxÒb*}9sƾ5fECVZE1`dSm7Yors79f ] w^SSSO-(ʜ[Dlwk},oN u44p$ J5؁I,f"(^?)fR|R\fిnv=i c'΢8]'H+h6ԧc1^ueI-]@%͵Tz|9Tꐨv).}W*LTum*O sTH|id#S=ZH܏q*JҸ uq\iU9Xk^sk K'x8\鍲BǛeƶwQkõ9[f]_Jj(d;)! l{ta-]cM#4UG,TGIK+ğE|/ hs/HEߏ~:¬MWeoϜ1QKjy$6 [QID2fe;cVK (f`P,*Xdݎ%G0a;ޢC6c{GSe]a2Q{wC:ݘv6^-r.f)j "bI2<#M$[Kd&9d%<536L$/m81RYd";TnI;1mr~7Yުp-jBW[Zby-GTt9E\4( lm@n{{_3&[4faO hOӒL)NK)#s莡h:*8P**!rxW.W[xVLI6Ý_k߉QS1& Zw'HN6t5)WAk^ws5 Y_U dOvMcYW'N) IHQ0dLv&Xw3ö{12pޭ֢Gt!7-;"ǤN,V+K a:rǺ͞eL4BJ( Rook! 4Q,ۏ̜gU1R{~#辌9jE_O+UK7G$CBـ ^!-\+>P*5MBʎF(T{b m&E}cfO8N.(bG#~ycJψt2uKOy<&DGicoy[66˝)*M-鎲_f[,S5SI1BnJo?\s9oN]q4%_TČbin@Ʈ7l|4OTLio{no,썇@f59LH,EP{/o@.I:JyXi"li@lI'߃lLykn>jSNFjYlЉc6X?gy P$2tnA;ocmte'̨c $3: 7>Q54 T?rVV"vziN呏Sss:JoQ5!5R6*rˤReSt}mXEWK4T|zO0 \ZLh;Qxw_}LYٗjfϦ2˥&āpOlY6_$R :@X I ;xMȽŻ[!_+nы-|!XGv [Ti{թ=قI逍J+8"PQ-퀍ԩvisܜ: I=DJ7+mpR%cTAQ'A=YOl/\4sqk$HŻ(O~e[6m]#'JeSۑ[Z@6r>Ʒ}&%:̾i[35ҍ,[Jk΄yG`HUPz K\{p6OCr{V-ڞ3Otv3W#RH7ƺMOnn5A$m_,"y!0G$N3w]Gij~%}{ kYzq{ҫW9A˥\\b,m9֮?$.5Әu/Jwyh1>>wһ԰tzMF1\meJKMИou̢ij/yGTfL"i%s8.õάc{ǶjN1Ⱦ!k}cjq5WSa\ 6k/Iǵ;hҞJܢWUө`q`OͶI]YyrT+Ik ~r,q{A׸|CV3nS_UMuU|i*V%ml>I;Mþ.Yόzc}_KS,nE / f*UZl-/kN'OתǴz ߜcyYΌ'Ieȥn/n߿]sj>u* a3Hv0놛۽PbQtj6kT|gUuUS>*2v5QIb]A)#!Z3h(M+dv_ eSف5AcQI K8I6bw'czjfog魗Af10^d%U]-w5qEnkRCOOKM,u]aVt^"O.DAkEEELOjfU,G}jLkӳ̳t4o6$E w8L/O:Ψ*e+D(O53vNJr\Ŏ_T7O\^}EjS>xXNv^*:lhғ&1`xasUS ,ԓӦU=#rjߛ(,cXz׫W;#n/+vQ>2&`tu߻&I:j㥫s\Zj)@FNigKQ)& PFR1m~:aUGY̊Uw$Nuc=($SlU^N$n *ԮL/ ryT&ܓ{H$Aocxԕ;Zñ 5#}fpMO 3B݊)Qkp@MU[S`ov}&Iv7`!ko1P[AXz4[psM뾭Mԙ<ӷJ䶦vc{:0M{m$pշ-}Ta{ mp* `㍅9 9kE~& ,6``Xl X| F7~7퀞1`I;-xmG`:7j qo\Z-s~0 6qb'8, ~a*ʇĵff $m7NmoBCܷ`kw EgMKX3iPX 4ꏋ?| p i5sn60:Hau%N{w$+Qu ki"q`"eحǓ뀈!|/<`/;qJ}0 )X#oq_*w'0X\vA6=ANw%&w'8`:b܁K:!Bk?Q%kM+bs{Hb@mJ7^ X>ll7<~A!lT^bM/{ņLnb'W[me/1x%6#oaCnujL&p[RIp&ܜ,-m%޻\1~#bېx1axՀU6 d276r.Oq s\D<_2Cc`D pK:nF7pt\s-A]ỳp0"㸾xjC_ʾ(R ۋB27REǽZn1 = 5Gk6"Ď !Y OH!kJv7 a>_n_a^ X=#w8(6 A'<`lX{qp@u L,HĽlx{,x5lc C ܛ`І{Xx#{0h'bsbA "۱#F,8:O鰵H6ۛ}loJ*︾D6 #S],P$sRHc@&\vBŵ,q*; ;[\z`Xǝy$i>1; o\AX8 opYHwv(X"Elb{ @է|]. Ϯ-5ٯ~vMݖߦ JIk {[׳IhX|2oݍ>8l@[.l8_l4aFͨᗜ*RI;TY`rw0 cҗ>u~X:P E,Vw(VpI:FX3X7aHI2 mF˨-OW6" 'o/8*:@fC`-aK<U0p eV䓤-?\Sfe;0 Pl l;9Ҿ[7b,F$8eR[~m5kqaUx#xXI,0 p "}p@6O=!`w 3";nUӨ(0G`cLlA _.̀oU`0H mn98'Sv7sܳ 6tkYpĎ K7ܑͬ[{MľѦ6?lpFc}hl۶T,M`#+pt_Jb۱ unmZG{<`īYcq_qGRkqo@ `oioQlbX6n1K`{`MՋPJN޸bwqᨶ㾛UQ77`bI$k)F5nn8Ӥ^y`"=$~oaζb{1ih*O` @>@vܢ[g{--e\fR (i;\kpu ?`6 _ 'rapaR;7ecM}}+U|h!s"YS^> n8J@PrOIY;0[mm&8/cbo_hux`tf;[p *[X 8%KcslFJiwo\N ,p *J#u`XlNͨ}X]!ǀ78UQ&ƒܒHFyF[YS̭[0 ]7,l6[|).X#, { Hu,|SSmKfre}H09'~GmV[G+X67B[Jڏ}= _Ar !`-ֵ\K(ܞx? _; #ϧ44]. `x&b{8zv#./o+%pm{ ےAZ.{O=<FN( ݹ?Ac#7l7\j7t`PI[ ml)ܭ[ GBJX7=0ñfnXR U;{[]Dztq}=7g(`Fŀ 0Y ~meˢM,c`o{1BU;\ c*&M&n/E)&RY}`dus ʺUav8-z~#9:d+͈{}0 >M:v$5>[5(xƥptk=p Ut$j#l-aql l),HumEC. O6 ӥHdA$؜Jqcͯ G.aq"Hƽ= (|Xs_a;'o`e:_ulAG1o/[`X'5;` 4ǝ5j#{ {dZYv$`I p_c$~ǮtK6M=̪.t?v?r6m*W]` 9S{y@]R.k'-#%؝)R@{/k A:y2EyA(0C ]jw/~XfY=(T=?\H4؛b[K~tvAp@&rAvmC`$ݣ:ԐM:c /\p{ k%Q\(Bۍ+8Z&ca~XG,OQ;;` $4x$yIp @  (e߾:3f {{ Dz4sHΫƂ{v},EL`vl{ 6F]>!,HlpCMuh.դv ؟*/8Zbu!p>Ve>}*,,-q{v%Pm뀍mh#Xۑ0yph+-/B'̢col('uF;w- DX4Y X=HEi؜½kK{bm{%b"(rF@K\キtXeP@Xvs qO%-Qkƺc a{-pj0>$F#]O Y/ƃewUMr@Pb?ՀR6*rP`?]{`.aEK;.nSQ(|3bxwQuܧ7WK]6*I'_Ay n{\ R-+2}wm aͰF[$a8.Hck^:Gq\4x 6ֻXo^{|WJvtXW_WPi܉dX{0t@n@%fo10ĝoG>`GOm1cdUn},*J"0Hck eP>}-KlVPv;!<09hnI8 Nx f>aaS*W0 v[ rlE\֫?mqȽ qQpu[0C\Xp-5rEb?[IߖBe7{kIݑO7$K3i7k` PxH ΖV C:[-b xIث;tee],ǩT5U&<4ďvor7pMaI7"v.7 a[OlaFakX_{o@Pt8FRwXO&9*8IaLXorm|kTAf;)"l\ mɿf0Y*MYӥۏLfUViE*#oC(8ĎMxl:Pչ,K9cak0 i*Fĵ+hR@c̑WPm7ꡈ~` ;0-|\ȶ?M68Ij^ oA(IW,ʤ7  $0%G C4긱`  ~ #+;o}0בT!I#kΒ7nA$$0n0Mm%ʩ'L\9 `$Uw[s*nےNͶ)so˵ e ]@ |h>j`Up;}5+ ~xѐ5^2zDo!mZ؟+.|L y5 +l!̧{[r17kg"` ,@ ټBY6 ,ݓBbH @erXl0 1 ٔko;o` ]Qu6XZ ;T.7#[xp1RKJE$m=84FR (!=|2[rʒO@+z^d`n.;P sly&w[}R05ŇV7;T`[ͿM˟(# ;~;`$Y0˰_f_ ŎK$TVҨJI"`v_m'1rmq`-4 tksKۀzlՑGd  fQrlo;Hf`+s kd6"> Pײ{2o,E/)P_ 7q~pum:o#q>RŹ>ޘZJ=ݰ }N %UĖ'𝯀Rp A "rE` RP",uF7b.iqDo&Y2ԩmH }1ɾ0m {l9L\manu߾݆@S?I$}eі[z8 6,5okYYHP.@ѹ[i `$5ks ǵ}p0 ``і H]}~GR-BI]r  @Mgsmx`aF]7 ܂7 zSLŻ?{tcUB{>ue&Zv|.mbװ7Gp.Bk{ڣ@ ]A^ $(CDDnVlMk|BM7dؓkl?l¨LEFUH߀r 3CТrylIK0ܞVlߓh РnO%.ȂE68>?ɧ~nm뀌 7H.u1mu`@7fnSM{ k)9[r@Xy{z`5$[micropython-1.12/docs/esp32/quickref.rst000066400000000000000000000425671357706137100202670ustar00rootroot00000000000000.. _esp32_quickref: Quick reference for the ESP32 ============================= .. image:: img/esp32.jpg :alt: ESP32 board :width: 640px The Espressif ESP32 Development Board (image attribution: Adafruit). Below is a quick reference for ESP32-based boards. If it is your first time working with this board it may be useful to get an overview of the microcontroller: .. toctree:: :maxdepth: 1 general.rst tutorial/intro.rst Installing MicroPython ---------------------- See the corresponding section of tutorial: :ref:`esp32_intro`. It also includes a troubleshooting subsection. General board control --------------------- The MicroPython REPL is on UART0 (GPIO1=TX, GPIO3=RX) at baudrate 115200. Tab-completion is useful to find out what methods an object has. Paste mode (ctrl-E) is useful to paste a large slab of Python code into the REPL. The :mod:`machine` module:: import machine machine.freq() # get the current frequency of the CPU machine.freq(240000000) # set the CPU frequency to 240 MHz The :mod:`esp` module:: import esp esp.osdebug(None) # turn off vendor O/S debugging messages esp.osdebug(0) # redirect vendor O/S debugging messages to UART(0) # low level methods to interact with flash storage esp.flash_size() esp.flash_user_start() esp.flash_erase(sector_no) esp.flash_write(byte_offset, buffer) esp.flash_read(byte_offset, buffer) The :mod:`esp32` module:: import esp32 esp32.hall_sensor() # read the internal hall sensor esp32.raw_temperature() # read the internal temperature of the MCU, in Farenheit esp32.ULP() # access to the Ultra-Low-Power Co-processor Note that the temperature sensor in the ESP32 will typically read higher than ambient due to the IC getting warm while it runs. This effect can be minimised by reading the temperature sensor immediately after waking up from sleep. Networking ---------- The :mod:`network` module:: import network wlan = network.WLAN(network.STA_IF) # create station interface wlan.active(True) # activate the interface wlan.scan() # scan for access points wlan.isconnected() # check if the station is connected to an AP wlan.connect('essid', 'password') # connect to an AP wlan.config('mac') # get the interface's MAC address wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses ap = network.WLAN(network.AP_IF) # create access-point interface ap.config(essid='ESP-AP') # set the ESSID of the access point ap.active(True) # activate the interface A useful function for connecting to your local WiFi network is:: def do_connect(): import network wlan = network.WLAN(network.STA_IF) wlan.active(True) if not wlan.isconnected(): print('connecting to network...') wlan.connect('essid', 'password') while not wlan.isconnected(): pass print('network config:', wlan.ifconfig()) Once the network is established the :mod:`socket ` module can be used to create and use TCP/UDP sockets as usual, and the ``urequests`` module for convenient HTTP requests. Delay and timing ---------------- Use the :mod:`time ` module:: import time time.sleep(1) # sleep for 1 second time.sleep_ms(500) # sleep for 500 milliseconds time.sleep_us(10) # sleep for 10 microseconds start = time.ticks_ms() # get millisecond counter delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference Timers ------ Virtual (RTOS-based) timers are supported. Use the :ref:`machine.Timer ` class with timer ID of -1:: from machine import Timer tim = Timer(-1) tim.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1)) tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2)) The period is in milliseconds. .. _Pins_and_GPIO: Pins and GPIO ------------- Use the :ref:`machine.Pin ` class:: from machine import Pin p0 = Pin(0, Pin.OUT) # create output pin on GPIO0 p0.on() # set pin to "on" (high) level p0.off() # set pin to "off" (low) level p0.value(1) # set pin to on/high p2 = Pin(2, Pin.IN) # create input pin on GPIO2 print(p2.value()) # get value, 0 or 1 p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation Available Pins are from the following ranges (inclusive): 0-19, 21-23, 25-27, 32-39. These correspond to the actual GPIO pin numbers of ESP32 chip. Note that many end-user boards use their own adhoc pin numbering (marked e.g. D0, D1, ...). For mapping between board logical pins and physical chip pins consult your board documentation. Notes: * Pins 1 and 3 are REPL UART TX and RX respectively * Pins 6, 7, 8, 11, 16, and 17 are used for connecting the embedded flash, and are not recommended for other uses * Pins 34-39 are input only, and also do not have internal pull-up resistors * The pull value of some pins can be set to ``Pin.PULL_HOLD`` to reduce power consumption during deepsleep. PWM (pulse width modulation) ---------------------------- PWM can be enabled on all output-enabled pins. The base frequency can range from 1Hz to 40MHz but there is a tradeoff; as the base frequency *increases* the duty resolution *decreases*. See `LED Control `_ for more details. Use the ``machine.PWM`` class:: from machine import Pin, PWM pwm0 = PWM(Pin(0)) # create PWM object from a pin pwm0.freq() # get current frequency pwm0.freq(1000) # set frequency pwm0.duty() # get current duty cycle pwm0.duty(200) # set duty cycle pwm0.deinit() # turn off PWM on the pin pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go ADC (analog to digital conversion) ---------------------------------- On the ESP32 ADC functionality is available on Pins 32-39. Note that, when using the default configuration, input voltages on the ADC pin must be between 0.0v and 1.0v (anything above 1.0v will just read as 4095). Attenuation must be applied in order to increase this usable voltage range. Use the :ref:`machine.ADC ` class:: from machine import ADC adc = ADC(Pin(32)) # create ADC object on ADC pin adc.read() # read value, 0-4095 across voltage range 0.0v - 1.0v adc.atten(ADC.ATTN_11DB) # set 11dB input attenuation (voltage range roughly 0.0v - 3.6v) adc.width(ADC.WIDTH_9BIT) # set 9 bit return values (returned range 0-511) adc.read() # read value using the newly configured attenuation and width ESP32 specific ADC class method reference: .. method:: ADC.atten(attenuation) This method allows for the setting of the amount of attenuation on the input of the ADC. This allows for a wider possible input voltage range, at the cost of accuracy (the same number of bits now represents a wider range). The possible attenuation options are: - ``ADC.ATTN_0DB``: 0dB attenuation, gives a maximum input voltage of 1.00v - this is the default configuration - ``ADC.ATTN_2_5DB``: 2.5dB attenuation, gives a maximum input voltage of approximately 1.34v - ``ADC.ATTN_6DB``: 6dB attenuation, gives a maximum input voltage of approximately 2.00v - ``ADC.ATTN_11DB``: 11dB attenuation, gives a maximum input voltage of approximately 3.6v .. Warning:: Despite 11dB attenuation allowing for up to a 3.6v range, note that the absolute maximum voltage rating for the input pins is 3.6v, and so going near this boundary may be damaging to the IC! .. method:: ADC.width(width) This method allows for the setting of the number of bits to be utilised and returned during ADC reads. Possible width options are: - ``ADC.WIDTH_9BIT``: 9 bit data - ``ADC.WIDTH_10BIT``: 10 bit data - ``ADC.WIDTH_11BIT``: 11 bit data - ``ADC.WIDTH_12BIT``: 12 bit data - this is the default configuration Software SPI bus ---------------- There are two SPI drivers. One is implemented in software (bit-banging) and works on all pins, and is accessed via the :ref:`machine.SPI ` class:: from machine import Pin, SPI # construct an SPI bus on the given pins # polarity is the idle state of SCK # phase=0 means sample on the first edge of SCK, phase=1 means the second spi = SPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4)) spi.init(baudrate=200000) # set the baudrate spi.read(10) # read 10 bytes on MISO spi.read(10, 0xff) # read 10 bytes while outputting 0xff on MOSI buf = bytearray(50) # create a buffer spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case) spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI spi.write(b'12345') # write 5 bytes on MOSI buf = bytearray(4) # create a buffer spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf .. Warning:: Currently *all* of ``sck``, ``mosi`` and ``miso`` *must* be specified when initialising Software SPI. Hardware SPI bus ---------------- There are two hardware SPI channels that allow faster transmission rates (up to 80Mhz). These may be used on any IO pins that support the required direction and are otherwise unused (see :ref:`Pins_and_GPIO`) but if they are not configured to their default pins then they need to pass through an extra layer of GPIO multiplexing, which can impact their reliability at high speeds. Hardware SPI channels are limited to 40MHz when used on pins other than the default ones listed below. ===== =========== ============ \ HSPI (id=1) VSPI (id=2) ===== =========== ============ sck 14 18 mosi 13 23 miso 12 19 ===== =========== ============ Hardware SPI has the same methods as Software SPI above:: from machine import Pin, SPI hspi = SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) vspi = SPI(2, baudrate=80000000, polarity=0, phase=0, bits=8, firstbit=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19)) I2C bus ------- The I2C driver has both software and hardware implementations, and the two hardware peripherals have identifiers 0 and 1. Any available output-capable pins can be used for SCL and SDA. The driver is accessed via the :ref:`machine.I2C ` class:: from machine import Pin, I2C # construct a software I2C bus i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000) # construct a hardware I2C bus i2c = I2C(0) i2c = I2C(1, scl=Pin(5), sda=Pin(4), freq=400000) i2c.scan() # scan for slave devices i2c.readfrom(0x3a, 4) # read 4 bytes from slave device with address 0x3a i2c.writeto(0x3a, '12') # write '12' to slave device with address 0x3a buf = bytearray(10) # create a buffer with 10 bytes i2c.writeto(0x3a, buf) # write the given buffer to the slave Real time clock (RTC) --------------------- See :ref:`machine.RTC ` :: from machine import RTC rtc = RTC() rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time rtc.datetime() # get date and time Deep-sleep mode --------------- The following code can be used to sleep, wake and check the reset cause:: import machine # check if the device woke from a deep sleep if machine.reset_cause() == machine.DEEPSLEEP_RESET: print('woke from a deep sleep') # put the device to sleep for 10 seconds machine.deepsleep(10000) Notes: * Calling ``deepsleep()`` without an argument will put the device to sleep indefinitely * A software reset does not change the reset cause * There may be some leakage current flowing through enabled internal pullups. To further reduce power consumption it is possible to disable the internal pullups:: p1 = Pin(4, Pin.IN, Pin.PULL_HOLD) After leaving deepsleep it may be necessary to un-hold the pin explicitly (e.g. if it is an output pin) via:: p1 = Pin(4, Pin.OUT, None) RMT --- The RMT is ESP32-specific and allows generation of accurate digital pulses with 12.5ns resolution. See :ref:`esp32.RMT ` for details. Usage is:: import esp32 from machine import Pin r = esp32.RMT(0, pin=Pin(18), clock_div=8) r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8) # The channel resolution is 100ns (1/(source_freq/clock_div)). r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns OneWire driver -------------- The OneWire driver is implemented in software and works on all pins:: from machine import Pin import onewire ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12 ow.scan() # return a list of devices on the bus ow.reset() # reset the bus ow.readbyte() # read a byte ow.writebyte(0x12) # write a byte on the bus ow.write('123') # write bytes on the bus ow.select_rom(b'12345678') # select a specific device by its ROM code There is a specific driver for DS18S20 and DS18B20 devices:: import time, ds18x20 ds = ds18x20.DS18X20(ow) roms = ds.scan() ds.convert_temp() time.sleep_ms(750) for rom in roms: print(ds.read_temp(rom)) Be sure to put a 4.7k pull-up resistor on the data line. Note that the ``convert_temp()`` method must be called each time you want to sample the temperature. NeoPixel driver --------------- Use the ``neopixel`` module:: from machine import Pin from neopixel import NeoPixel pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels np[0] = (255, 255, 255) # set the first pixel to white np.write() # write data to all pixels r, g, b = np[0] # get first pixel colour For low-level driving of a NeoPixel:: import esp esp.neopixel_write(pin, grb_buf, is800khz) .. Warning:: By default ``NeoPixel`` is configured to control the more popular *800kHz* units. It is possible to use alternative timing to control other (typically 400kHz) devices by passing ``timing=0`` when constructing the ``NeoPixel`` object. Capacitive Touch ---------------- Use the ``TouchPad`` class in the ``machine`` module:: from machine import TouchPad, Pin t = TouchPad(Pin(14)) t.read() # Returns a smaller number when touched ``TouchPad.read`` returns a value relative to the capacitive variation. Small numbers (typically in the *tens*) are common when a pin is touched, larger numbers (above *one thousand*) when no touch is present. However the values are *relative* and can vary depending on the board and surrounding composition so some calibration may be required. There are ten capacitive touch-enabled pins that can be used on the ESP32: 0, 2, 4, 12, 13 14, 15, 27, 32, 33. Trying to assign to any other pins will result in a ``ValueError``. Note that TouchPads can be used to wake an ESP32 from sleep:: import machine from machine import TouchPad, Pin import esp32 t = TouchPad(Pin(14)) t.config(500) # configure the threshold at which the pin is considered touched esp32.wake_on_touch(True) machine.lightsleep() # put the MCU to sleep until a touchpad is touched For more details on touchpads refer to `Espressif Touch Sensor `_. DHT driver ---------- The DHT driver is implemented in software and works on all pins:: import dht import machine d = dht.DHT11(machine.Pin(4)) d.measure() d.temperature() # eg. 23 (°C) d.humidity() # eg. 41 (% RH) d = dht.DHT22(machine.Pin(4)) d.measure() d.temperature() # eg. 23.6 (°C) d.humidity() # eg. 41.3 (% RH) WebREPL (web browser interactive prompt) ---------------------------------------- WebREPL (REPL over WebSockets, accessible via a web browser) is an experimental feature available in ESP32 port. Download web client from https://github.com/micropython/webrepl (hosted version available at http://micropython.org/webrepl), and configure it by executing:: import webrepl_setup and following on-screen instructions. After reboot, it will be available for connection. If you disabled automatic start-up on boot, you may run configured daemon on demand using:: import webrepl webrepl.start() # or, start with a specific password webrepl.start(password='mypass') The WebREPL daemon listens on all active interfaces, which can be STA or AP. This allows you to connect to the ESP32 via a router (the STA interface) or directly when connected to its access point. In addition to terminal/command prompt access, WebREPL also has provision for file transfer (both upload and download). The web client has buttons for the corresponding functions, or you can use the command-line client ``webrepl_cli.py`` from the repository above. See the MicroPython forum for other community-supported alternatives to transfer files to an ESP32 board. micropython-1.12/docs/esp32/tutorial/000077500000000000000000000000001357706137100175515ustar00rootroot00000000000000micropython-1.12/docs/esp32/tutorial/intro.rst000066400000000000000000000136751357706137100214520ustar00rootroot00000000000000.. _esp32_intro: Getting started with MicroPython on the ESP32 ============================================= Using MicroPython is a great way to get the most of your ESP32 board. And vice versa, the ESP32 chip is a great platform for using MicroPython. This tutorial will guide you through setting up MicroPython, getting a prompt, using WebREPL, connecting to the network and communicating with the Internet, using the hardware peripherals, and controlling some external components. Let's get started! Requirements ------------ The first thing you need is a board with an ESP32 chip. The MicroPython software supports the ESP32 chip itself and any board should work. The main characteristic of a board is how the GPIO pins are connected to the outside world, and whether it includes a built-in USB-serial convertor to make the UART available to your PC. Names of pins will be given in this tutorial using the chip names (eg GPIO2) and it should be straightforward to find which pin this corresponds to on your particular board. Powering the board ------------------ If your board has a USB connector on it then most likely it is powered through this when connected to your PC. Otherwise you will need to power it directly. Please refer to the documentation for your board for further details. Getting the firmware -------------------- The first thing you need to do is download the most recent MicroPython firmware .bin file to load onto your ESP32 device. You can download it from the `MicroPython downloads page `_. From here, you have 3 main choices: * Stable firmware builds * Daily firmware builds * Daily firmware builds with SPIRAM support If you are just starting with MicroPython, the best bet is to go for the Stable firmware builds. If you are an advanced, experienced MicroPython ESP32 user who would like to follow development closely and help with testing new features, there are daily builds. If your board has SPIRAM support you can use either the standard firmware or the firmware with SPIRAM support, and in the latter case you will have access to more RAM for Python objects. Deploying the firmware ---------------------- Once you have the MicroPython firmware you need to load it onto your ESP32 device. There are two main steps to do this: first you need to put your device in bootloader mode, and second you need to copy across the firmware. The exact procedure for these steps is highly dependent on the particular board and you will need to refer to its documentation for details. Fortunately, most boards have a USB connector, a USB-serial convertor, and the DTR and RTS pins wired in a special way then deploying the firmware should be easy as all steps can be done automatically. Boards that have such features include the Adafruit Feather HUZZAH32, M5Stack, Wemos LOLIN32, and TinyPICO boards, along with the Espressif DevKitC, PICO-KIT, WROVER-KIT dev-kits. For best results it is recommended to first erase the entire flash of your device before putting on new MicroPython firmware. Currently we only support esptool.py to copy across the firmware. You can find this tool here: ``__, or install it using pip:: pip install esptool Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer). An older version (at least 1.2.1 is needed) works fine but will require Python 2.7. Using esptool.py you can erase the flash with the command:: esptool.py --port /dev/ttyUSB0 erase_flash And then deploy the new firmware using:: esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 esp32-20180511-v1.9.4.bin Notes: * You might need to change the "port" setting to something else relevant for your PC * You may need to reduce the baudrate if you get errors when flashing (eg down to 115200 by adding ``--baud 115200`` into the command) * For some boards with a particular FlashROM configuration you may need to change the flash mode (eg by adding ``-fm dio`` into the command) * The filename of the firmware should match the file that you have If the above commands run without error then MicroPython should be installed on your board! Serial prompt ------------- Once you have the firmware on the device you can access the REPL (Python prompt) over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial convertor, depending on your board. The baudrate is 115200. From here you can now follow the ESP8266 tutorial, because these two Espressif chips are very similar when it comes to using MicroPython on them. The ESP8266 tutorial is found at :ref:`esp8266_tutorial` (but skip the Introduction section). Troubleshooting installation problems ------------------------------------- If you experience problems during flashing or with running firmware immediately after it, here are troubleshooting recommendations: * Be aware of and try to exclude hardware problems. There are 2 common problems: bad power source quality, and worn-out/defective FlashROM. Speaking of power source, not just raw amperage is important, but also low ripple and noise/EMI in general. The most reliable and convenient power source is a USB port. * The flashing instructions above use flashing speed of 460800 baud, which is good compromise between speed and stability. However, depending on your module/board, USB-UART convertor, cables, host OS, etc., the above baud rate may be too high and lead to errors. Try a more common 115200 baud rate instead in such cases. * To catch incorrect flash content (e.g. from a defective sector on a chip), add ``--verify`` switch to the commands above. * If you still experience problems with flashing the firmware please refer to esptool.py project page, https://github.com/espressif/esptool for additional documentation and a bug tracker where you can report problems. * If you are able to flash the firmware but the ``--verify`` option returns errors even after multiple retries the you may have a defective FlashROM chip. micropython-1.12/docs/esp8266/000077500000000000000000000000001357706137100160675ustar00rootroot00000000000000micropython-1.12/docs/esp8266/general.rst000066400000000000000000000217661357706137100202520ustar00rootroot00000000000000.. _esp8266_general: General information about the ESP8266 port ========================================== ESP8266 is a popular WiFi-enabled System-on-Chip (SoC) by Espressif Systems. Multitude of boards ------------------- There is a multitude of modules and boards from different sources which carry the ESP8266 chip. MicroPython tries to provide a generic port which would run on as many boards/modules as possible, but there may be limitations. Adafruit Feather HUZZAH board is taken as a reference board for the port (for example, testing is performed on it). If you have another board, please make sure you have a datasheet, schematics and other reference materials for your board handy to look up various aspects of your board functioning. To make a generic ESP8266 port and support as many boards as possible, the following design and implementation decision were made: * GPIO pin numbering is based on ESP8266 chip numbering, not some "logical" numbering of a particular board. Please have the manual/pin diagram of your board at hand to find correspondence between your board pins and actual ESP8266 pins. We also encourage users of various boards to share this mapping via MicroPython forum, with the idea to collect community-maintained reference materials eventually. * All pins which make sense to support, are supported by MicroPython (for example, pins which are used to connect SPI flash are not exposed, as they're unlikely useful for anything else, and operating on them will lead to board lock-up). However, any particular board may expose only subset of pins. Consult your board reference manual. * Some boards may lack external pins/internal connectivity to support ESP8266 deepsleep mode. Technical specifications and SoC datasheets ------------------------------------------- The datasheets and other reference material for ESP8266 chip are available from the vendor site: http://bbs.espressif.com/viewtopic.php?f=67&t=225 . They are the primary reference for the chip technical specifications, capabilities, operating modes, internal functioning, etc. For your convenience, some of technical specifications are provided below: * Architecture: Xtensa lx106 * CPU frequency: 80MHz overclockable to 160MHz * Total RAM available: 96KB (part of it reserved for system) * BootROM: 64KB * Internal FlashROM: None * External FlashROM: code and data, via SPI Flash. Normal sizes 512KB-4MB. * GPIO: 16 + 1 (GPIOs are multiplexed with other functions, including external FlashROM, UART, deep sleep wake-up, etc.) * UART: One RX/TX UART (no hardware handshaking), one TX-only UART. * SPI: 2 SPI interfaces (one used for FlashROM). * I2C: No native external I2C (bitbang implementation available on any pins). * I2S: 1. * Programming: using BootROM bootloader from UART. Due to external FlashROM and always-available BootROM bootloader, ESP8266 is not brickable. Scarcity of runtime resources ----------------------------- ESP8266 has very modest resources (first of all, RAM memory). So, please avoid allocating too big container objects (lists, dictionaries) and buffers. There is also no full-fledged OS to keep track of resources and automatically clean them up, so that's the task of a user/user application: please be sure to close open files, sockets, etc. as soon as possible after use. Boot process ------------ On boot, MicroPython EPS8266 port executes ``_boot.py`` script from internal frozen modules. It mounts filesystem in FlashROM, or if it's not available, performs first-time setup of the module and creates the filesystem. This part of the boot process is considered fixed, and not available for customization for end users (even if you build from source, please refrain from changes to it; customization of early boot process is available only to advanced users and developers, who can diagnose themselves any issues arising from modifying the standard process). Once the filesystem is mounted, ``boot.py`` is executed from it. The standard version of this file is created during first-time module set up and has commands to start a WebREPL daemon (disabled by default, configurable with ``webrepl_setup`` module), etc. This file is customizable by end users (for example, you may want to set some parameters or add other services which should be run on a module start-up). But keep in mind that incorrect modifications to boot.py may still lead to boot loops or lock ups, requiring to reflash a module from scratch. (In particular, it's recommended that you use either ``webrepl_setup`` module or manual editing to configure WebREPL, but not both). As a final step of boot procedure, ``main.py`` is executed from filesystem, if exists. This file is a hook to start up a user application each time on boot (instead of going to REPL). For small test applications, you may name them directly as ``main.py``, and upload to module, but instead it's recommended to keep your application(s) in separate files, and have just the following in ``main.py``:: import my_app my_app.main() This will allow to keep the structure of your application clear, as well as allow to install multiple applications on a board, and switch among them. Known Issues ------------ Real-time clock ~~~~~~~~~~~~~~~ RTC in ESP8266 has very bad accuracy, drift may be seconds per minute. As a workaround, to measure short enough intervals you can use ``utime.time()``, etc. functions, and for wall clock time, synchronize from the net using included ``ntptime.py`` module. Due to limitations of the ESP8266 chip the internal real-time clock (RTC) will overflow every 7:45h. If a long-term working RTC time is required then ``time()`` or ``localtime()`` must be called at least once within 7 hours. MicroPython will then handle the overflow. Sockets and WiFi buffers overflow ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Socket instances remain active until they are explicitly closed. This has two consequences. Firstly they occupy RAM, so an application which opens sockets without closing them may eventually run out of memory. Secondly not properly closed socket can cause the low-level part of the vendor WiFi stack to emit ``Lmac`` errors. This occurs if data comes in for a socket and is not processed in a timely manner. This can overflow the WiFi stack input queue and lead to a deadlock. The only recovery is by a hard reset. The above may also happen after an application terminates and quits to the REPL for any reason including an exception. Subsequent arrival of data provokes the failure with the above error message repeatedly issued. So, sockets should be closed in any case, regardless whether an application terminates successfully or by an exception, for example using try/finally:: sock = socket(...) try: # Use sock finally: sock.close() SSL/TLS limitations ~~~~~~~~~~~~~~~~~~~ ESP8266 uses `axTLS `_ library, which is one of the smallest TLS libraries with the compatible licensing. However, it also has some known issues/limitations: 1. No support for Diffie-Hellman (DH) key exchange and Elliptic-curve cryptography (ECC). This means it can't work with sites which force the use of these features (it works ok with classic RSA certificates). 2. Half-duplex communication nature. axTLS uses a single buffer for both sending and receiving, which leads to considerable memory saving and works well with protocols like HTTP. But there may be problems with protocols which don't follow classic request-response model. Besides axTLS own limitations, the configuration used for MicroPython is highly optimized for code size, which leads to additional limitations (these may be lifted in the future): 3. Optimized RSA algorithms are not enabled, which may lead to slow SSL handshakes. 4. Stored sessions are not supported (may allow faster repeated connections to the same site in some circumstances). Besides axTLS specific limitations described above, there's another generic limitation with usage of TLS on the low-memory devices: 5. The TLS standard specifies the maximum length of the TLS record (unit of TLS communication, the entire record must be buffered before it can be processed) as 16KB. That's almost half of the available ESP8266 memory, and inside a more or less advanced application would be hard to allocate due to memory fragmentation issues. As a compromise, a smaller buffer is used, with the idea that the most interesting usage for SSL would be accessing various REST APIs, which usually require much smaller messages. The buffers size is on the order of 5KB, and is adjusted from time to time, taking as a reference being able to access https://google.com . The smaller buffer hower means that some sites can't be accessed using it, and it's not possible to stream large amounts of data. There are also some not implemented features specifically in MicroPython's ``ussl`` module based on axTLS: 6. Certificates are not validated (this may make connections susceptible to man-in-the-middle attacks). 7. There is no support for client certificates (scheduled to be fixed in 1.9.4 release). micropython-1.12/docs/esp8266/img/000077500000000000000000000000001357706137100166435ustar00rootroot00000000000000micropython-1.12/docs/esp8266/img/adafruit_products_pinoutstop.jpg000066400000000000000000002331371357706137100254040ustar00rootroot00000000000000JFIFHHC  !"$"$CG"  XFIdHιɅc) #Lg3HK8ȵEk1!$rg ea :$ɮȱȒֲXʬ-6Lc:Re,FܹP佚ѰZ;rxS#`&M #)kHԓX[hg楱6#yhs_qJòhe|o2jv[ Dr<tĖJ<;ic/#13:Eޱ1]m>VMRɇ-gb*Pc jW3לO'S+wdXMM'5-=+;m, 6 aHb7; 8Fg*kf׌Au㣭ޡ v'X֍DU&'seRTFHK.xtL#&fBΊ ϑ]#vdfgqfx%5 N4?ȯvAAcwbšmd&q3yZ7Wyܮ;^늉ϜkX]]UUUPX=-Z S툸<_Pi^[ؕu/E̐(EffbEF1{/R΍+Kږ=u:$&L, 71͂0hB<ȫ'ٚ.LZ]qT]TϬ&z3R9HrAo^gJ]nI6@=U֍_-ͪϭFkd4o]MYe^m4PBK3,jR 񨚾ϫʻzlcoLEa~PL{C[ \QzfuZW#f5^gn ,8?K ";lU_"uܷ^on7%jlA"yUt,AiӗHkq\zWejHAͅEkZ #"8.!;g+-ۜ.LBCԜ;fs-Aa׆]r~43"r M9ұo+)sCcpBva%7ͮpIy׹ŭKz8c^C Ȳw5~}(G.lNCƻc7\ ] 1}EI{'-bd:x9,%wk"w\bD=c֞JשnnMŏAG4MyN4AVV,zfxE {b 2 JʭR]6ľ9V5v=$}Fٰn4D"IX*ZY:R:7D(riH-󩡷o-&2૥;5Rd6- ux呉.f{* 0Ϊ{L AC Ek~ak &ڜ@]\g90sŠN[&>^jNT;>ůS\3@@5~z*VEnk&|i+AmFrH5=\zIC i#!1[kXۣY kbz 6v9̆=,aDR5 Vj>srڮԴgA;uʹ #=Ή ZN۳d9ݢ$C?ͽ+{YW dnF Yamӄ ܉҉=C&eX[ZAH,0+ Z]Jqq4ddw$seи.:rVpmY'tM@ܷ>i4޾j}HH(cJ:̓3O-+@q8d}MQ™:QJX ,ۘs}sGdP%=ultdXP (\4b 13UW%\AVbHvg z# KuQ>xKv - LB =xjc{zzsecӔ9mfԳXT45Gja%1+6K<zyԇoZ TLF":`ڗ-?Ҫly_vHFIG;钸FH:Tmo d%,D`X_; h+5,$O"2GiAH\r h)לA4>c6ˇQp>߁ m<0nva7Mvgk$^)Eo5LQ$ltoxvH&~n$nqVp)C<6qawκW]j'eGV9Ӣ18KY AVZiu&JKT)P9FehJc 7=QdU - UCD94%VcH*Y@+"m摠SB}A|Ũ0$o:DGR0b]"sfܺiSV)kW.xtP[ :"D]!pIJ#q1:@2MR:kVdIJ龸eY.0wj,ݝƥ3 oIxEe36`9Ұcɜ%Y]Ʌ[`;d+cEdkjKllT]3bٗEtGL>T~OOl_}~~'zyODbzy}W=wFzmÐ(.pWhJ&_għG9s1`BtsOúDww9.w.\s\svw+sq;ŕ$Y>;tܦw-Ĕ[)ܷ;ܳ;gr!:y!\yuEaX[uEQbYuEF.x\'+JH4>"'RKHɜPDU/;3gNX"gaܭⅱݨ]0$Gw)uvQjF<)AcWuCBZtœ_%UH-D|+&RW2^uT0re43k2LqDd:ic #UD8}elOB74,z@mmߴLmAB9P\؊?%]>D/Y5vZs;Ib""jG1EQglR&"8gx87dA鑮騧\k.~+Owzu?&k5: >3;=GE^N3J= &x{wiAT1R+W-ݚJ zɣi(XՍ#tmL(6}JM*,:̅iJ$$>"orQE)^ v)GV'NYC;_H njU3mʁX* \ b[>lj-KG4QDks,[&\y ~CAa"Dlz2 `QEʘKkuaSB1$GWʲXS!ljUiؾ;`q#PwƌLW c 0YEp^0#+gʇaYv Ų3O/Mj4 4wBLwz+:-$:AuF85wMM&mv7ªe~&k8!XyzJ^¤FG1&J -;E|QCj.mܲ$A#ZRJlx52d8kxDJsm`㓔i5: (SpծcN6-\ ʹ%Q3$HU(袉j: J(}R‹s sU-t,$9%y ]=c }0!kLc4ț/ҷ a#{qLqq7$OX$G=i+X+1ӶkپQ: -'=_10Jcb覫 &SPMRU$oJ?Ck3$~1/IadcL+ q,doz6K iF!ܥu+U:dNufbG*zǿl0H ͒I $+eW9__"Q dQW1hfAc+*d4lhBXxǏEhۈ1X>P.UU8_ͤR$gTڮh_h_G6Fsu]>SHQ|QUnNGƗä eXO߷\kH }]{R*'XBG3 keYGP{}̎O":KRWgSF4$ *ϻ!X#KmL;ZiXփcl1mDu99[G,_\. &8t"8 2$#GJe'k5f<16k!Dn5>@\fz5WDhtDssS|訛dGo?S{f ĆCu 0o,7#)۵k C!)HʶopY) +E0ŝF5+E'N6"٬s:g'wFۼ*2Pyl0΅[وKsl[(丰L,L/T;{d/撏Gpb Ŏ5[Q ,(4l`yfX2\frq~ڋWJ7!W0yYZ&k+⣳tuX 5AGdAF8#SIaZ=l̆cTNB6OlI6\FQ Qtl `Kggbiibr.M+锵 %w[?S)L]|RǍ%i p̲4Hi&,Hdk.cch*ӱD> Bmril/K6lF袵`"ʺxa ދ, KS4[غxosgb53P15 q52$ˏ'ei-- Λ3 :BA~ '̑qE<ۮǖ>yG&ln}=QlJhƼ2Lsi!aK$hܡ]G&]l ¬|*L#qL!s*임1:K@ɞŬ9ɥm?G]Ft57k4od2Via!+]YSWVgU 7]hZp)rTrY{vC!}Y&2H nPVĊY-pq^0C (!If(ƓIZͺhQh#:P4lw nn8u 97:л;|^lMx#͸^F83߻i"GӏdEn)ViT/JPFm[$wLKv3hvi>˅d6)2iiXOKiGej|KMpx W:੦_f*M+f򢾅ur)2wZtձ80oڸI4 )4bͿ},@mgKuh繂* Xk8ӪeSTh 5o̺RǬY'B[ oD/LB(͐g?<qBm܉W\JlAD\F.([F[]RȆ>-?d5Ա!lj!;VK@cB^9;[ N#L9qLᲽp}5kȨ 0QogfhjU=&6xIyйgÅi:]ƨt%CsJS>CC0Sk=#@h;iK_X;&#Q?iF+˘_defn7MP|.M|f#tz*ÔNK_qgndTWr!Ⱓ i `4V!#N3z2Dr]A^IW.I^D "CrZJKQѩ<%-Ads,iZGVϑUIak]J~MBq;cPY VnIe9EjȿD>6F8l?OW4eňĸvĵgj6VedSu_]D|zĎk}gIdw43C[62P6Z_tic#"UBi1!eVɑɍV6EV)Hw4kYHcU6eD/iKږ;MKkOdqYW_[R!UY@*X0i֎: h(7N }$ bJJRtbX@;#ɓgm7?DioΩ2ri.&s)j*N}/me(/@XrN.=F}I\en#L)!T YEvY#hrІP MSRW5 <``IrwoVn0JuSDj)$W׶)ݣ_V@k_UN:Y0'ȥ=RKT 2i&L"CVV0sFP@죉i4=THSk5q5+wnW|ٮ9_䅌86JEJǻ(cQ OkeBC _5L!a'Qk~7j d6bl~pl即Ր<` 0mYYr'Pk}ы "C,p+cDZllbR bQP9_  0cxLVYߓ"qU[:i)Yԑҵ 5 j:q^3:~d;H[[\-M Al+ZW멿yg*ʸ\342'ӥQe^\KYrI2#a5<:hv>4Vi ƃ:XiWULup›I|rmD7π{Xu=2n4+ >/4Btҩ2=x^٭J?+ym\#%}Ԗʴ3Ac#,d1N2{Q4ŪJEɞt$qGە Fp>ck{ gO*qW4Wz ?kҕ5jEQRFW_K/or("SѤݛNdtGýl]E"N2sנS\DjQ"㘈Ki*61%]*#ފc9\r}## SflkƱSomrTɻV=JPl)# ͫ[^_ok]4y:j`mR߷Ge\WtH`J+`ew QhJgZmo=*o'TJ]Hέ*,7BP+\~ݐ}-`9z\-wЂDA"\(JFВi`\^nB:R2 XM7-cK6=q%͛i!x!Ï Ԉ&EyqFpJp6t2cZTﻝٮ]g,B&**r+b|ʁTFcOiӍjPJU?ٝQ]f :SURw;#cɈ#!#`VJA8܊Fg724Z$A/FdHw ٣$pG2#ֽcȑCiMɮ:Iç(DYX"|WR r,Y3jOq^ҋÑ&Fpʰs$xM2l(/]%ŷQh(Qpx}L(”4a!Q91W^Pɐ W"{f$[9X2lZ"t, ~tGL959:EZQ`1%vi깣R}~La1@r1rQCzEmzMY 1c>H!ǂ.ͮi #*FHiJiXV2D0-0œLTly "3f$QpgmEsbDgsSd 1:g&6!Gaf&Og&Nr,Xl pȒHAq$m6Y93RxX[E<*bͿ)vdذbz1ɕW= ?}&z=a) !wPL` !bh+.#IRms0C }@m;ǚjJ$RdH@îtBI%SϬ|a:Օe$yRiCpDFJx}U1lxm?ë1ͨ΅|f[%<7wkU&c/Z^(Fctsī*Z6L>֯:#@-Zт r\]ݕr+;1yr&}1w~9f雦nҫqst!B7r#gk^9U{˂3Ǐ'Ͱ,,+3r=HUs[s3nj/+}K4wa_ 9Qre̙rB~v }.F;㕺c8v6)g^RP@o~C۲cS>.*b:yΞt,gO:I,gK:YLgK:YΖt,gK:YΖt,gK:YΒIs\t:nΛg3g.|ϟ>|#̈fϛ_meo_޻zmz&*fvͱ3l&mfɛx68ٲfٶlm&ll8mg3l8ͳlspL☍Ll_T\LLmlWoOE=>ޟl}>}3l\z틛ggg&}mfy>%;zxϯ_zox*b}S}m툾>>\?(!1 A"20aQ@P`q?T&5XjoDqlqFlqEƅƨPlZm卒礽Ͳ.gMH-"/B~>($7gd6{V_/M!,nŕ>^TQEQXX x,<٧5+4٩^VԥѶ/&.Տ7zddqq,Xٸeٸ,PЗn1vJ{B6PІE&ƢP*>H"mv> #٨kPXd~Ƨ؍(ٺ?Ѻ$|y.XDlI.;cMw+ aa#nF"1Q.j;NjB씷b(49~ƧVf}Gir?%xuI1x5+?cSEN5q e 윷QB"=4'%B->fd]QDWrke+)w2] I?fW{!ׂGryVh٪F7HլYcv_EKz|bjs"Noo$$Q~>9'a(ckׇ?x^9-[,leYfiqcv쵺vE!t ?_ğO1}x&zgKq쥸$ A+;\Gk---+!1A "2QBab0@P`?y`$VF[fiYbJJ*Œ2RQ#;tNj$gHHEHUDZK,S4աbuz~|E[>Q\*Hp6Vmmk&dcMJkƜ[1š'i 4jMQ좸J75h\<*B hB!O⋱w9#rMś"7Zx#tpd$;=s#Њh"͟/3ڪ?n-c ֢mNI#׵/`!&?=Xt.9;#ٵ13A*6!=1 PYIF)2Re] et+]9GvSnH]lxK MLNՉ 4;?Xc=/[]M'=#~X!6PEsdĆke\򙋈T2ΌNDbL̷p_^Hvf1^Jwx2qf}hC=HgM7tuȚ} eBV*F4q^D6#jflE#j6j6B:ͳ^cwC\p.#E=?p$2ki/h߃"b%ۡ]Lr{6)=qVIm:vu%Z˯]h8z4VVc"ZO  !"1A2Qaq#B 34Rr0bs$5CSct%TDPd?e-t_quei¯\kO8/µx|+ѥs:;OEo¹GJt^:m>^59vfԡm1jgF9W7FeLM=աOZҿҸ?C 4DX|U7Z$A"sǑ+6¸ +-]U_6+Ǿu??~5kZ_7S_7]CZ{kTjuZ55 ^j[_ʹ[?u U+]zXZ ƭƻ n9x{ZO #.ƾ+*ʘ04LVij(*eesu<]HxԯSvVkI_<浖C]ڙ> i]GApu |~%C6E<:i !$reL~Fþ,\ &a}J+Q}ULd{zM"1ّZ?}\I%kcʲ55f#mޜO)4p/az(mcLnpG`dxѬq{\RaqpHh1,Gʸ w GfL,5 K Gu3a6G] B/=gHm=%M fz[MI&#igöMTqgÝ׷mD'l P. [\y+͟ .؋# ,Af[PHHI'9"V>6֭ӈV*GI}u1ʸ.XxWm<`[MRZק;]J0FCb5>!ͭZ@?^UHՀ5$b5ͥJe"DSy6l;stXX(qVdgm$ɨ5S.|*^:nek^OyR-æB;TÛm]c|ИB=)h0ma+^W$+){(:IhA秲cǜ4ᮺYD) زV#Qa""MO:qG&%r#ekhumCqGe"jbU{l,,؄]X2xc#cι4gc$J }cP(嶳 GufX |F/#(OƦϱ&QT\yy0% uz >a7V%0MۑkDBĢܴHQö63+n6(Tcmh*$W"GekWNDo;V*9 x?J So5imrͳ'`+i-1;k|[TI(5T "{wV#bU[.L<($/1mk<ݮsZ[iE_t{{d * \ãF*R䉆I@4pYG^2Tg7*=)0Uk*EA2K\n$QIk]G·oQytCq {ÇD S~Ve ,t74sJcp/j1K{&n8^4Dr/p}_ HlšPeqc'a[q | @;<*H0>k;*(X1&#bH=|T&P-ÅG lDG6oo$fZ;u[-Zߍd"h߰Ey\ 3GL݀rQ3(9T짗um $m9Fm6Uͳӝ=uO*24EGm}Ն̉ ͧ:s1}Z3ƒ4GɽT{(ba&Ʒu>"oGPD(-P \6,faq:ռ1쩼 +{]5ÙⲾðj+v58LaoczL65MRkpIG qWl?%lS t c]r"X_&˲l&Ax>R.8SG>eZ&Os\V\Fn3}[S 6 w@C0~: c-+{HAR =9Fi`mjs"*5ҝ8nbܫ>PmcW礼 UӻZdܹW3 \wk[VB7Bt=QU~߅dcqkozQё(־ߕOn<7b~N/Rm[Txߕ.xTyUw g}f MPu ~5|:_4[J4ҴUZ&uZשּׂYˣg"#X6]jѳFӟߝpX_5 "s4UDӮ}[dlHxxT>RՈ\kP+YcK!_7ͼmΓe W2{AZss{u&eUE_:HW[`/@.&M=Q*[٭2J]4? gYvިC UǓ2q?"Dq ,?efj,FϏ<ւƘ "*9Æm[A)u&U1?ӗWx@_&us She($;vPN­*|maXQc\cqLZeVn#ƶ3- s@rk υkDj[9b":&ƨă]kN3 I\f7="8UXC椴}[CêݝSn{H},^ǕNTUcw-eu%_[R}Pubj9C1UomEyev%dUiI6$z^vIY.ٵ(D#7AufQY)hM{*4x7ͷiBI1Ư&b8)ƻJ۝fVh2bE1lDˠ25q5^# f>EŹf&[1/Xq eR K AXэ&MÍ/za?rfh[5;fP3kQQK= 1k\GHh#ӅQcDzc>uH$d']-Qry/C4M:@bCS+˳[\ ٸ&B-LսU%kv"]Uny x+n/Ma&PV6QH5pdc>6.Ǐ#XiơvE_΍{7nC ZU{*&:oݲƉFz)ޱb(j?6uZȒ+_W0&Y9ì j!m[x K.a֤$Xf(>=#TeP{f!'K,D9 y#Xη.rgH;LT8Z j1 M;Z j[nBf"&ՖDֽbܫʲÇH.SbE+JEm#i9ߥՌ854_ĎVlx֞ ˰Ⱥ’Uq:Ĝ1^gr+jP5k >V8x}>+*0ʾ>%{~ .'ծuk++* .qwB)r͚%mkI-™mx-^ʸ8{)n*i%B5"u6~g+4ѦEw,hlT{lTZ2ql9Pī(>jƖCo}@ ;mG5&ESXCѷmfՎi YS9Z粞hNRF5f:hx`U2av`7GA/ JKeaA ѣucye> 0MceZ8<Sq4٬%umql/~hI>50SCX&1o {dcvf֦_rb?*e X߀֢wȬ2ɋq7az>%޵I=J#3פch[ki<= \4N+&uKM3x kL<^bT< q(b}y]mk 4y3\X\>6ʰVFmv4dp??’&mSJ$[\ZқK}2&-۵VQ ەW_QiGlgm|* DI1rݳ/uVףwCi]3Po8 0͒)#ioM`o[$qaV ̎mN_|D~f)mSlj[6>TT/6,vK`ݥvJV_5/ߨF##¾z:8 !ʸ6Y}4d*kGD&'Zȋ+zOXp@MndKm$Ƥ\T JC_Cʋ.q@Yn5sQip/6]uFzz>n)7;;|jIJuQW9duYmMIMTbO`VTrWZ\p:9xGmQFК#Ius}/D%ť{,uR?#Y^zӀEIM9$ڧi1m|AcVT?*H3bjXYL-q!?_1[\+wlD-͙G "c wVmR4a\ Kp D5-R@6lDl~!{jC_ff=Y(/]nh29ab˛O>|6}<8)Bb#[|_Iaet }}/?Y}iWR)jkS+.w^=UM{.k+(Qʷvkt$3o%ă2@&/{8m+i}kk;ư {2eL1+/&:^|}d k.d~`X a$>= b5V2k8wW1a kWlټoƮimtp]|(4z8Rb./+$1Fĩ7֠ ·:r}H8xi Hq*7CW_E#_E'TI: Ea:چid} +M H;ڢviLI^$M.i J6Ea iE8*5 | es@e{^ɗ.c)%R8u"SbY8 3侔<ZBU^o; Fs."4g7|߈:+f[p.eoFP9J$B#:8 J(on^lKѳXXF.уNf0aZebM3GdՑR-{TGlKz<[?FZCřHP̨ELf5N[WKVX%\ X !@:3H8Uޅ45Jψbd<ZծUiYQK Q\|kW4.PYUEݮ2}Ѥ֓ ~AF=!̤j-Jp]<LAW hIY#u)vrPIx)a/m)ѯM~tU`ֿ*̈́iwU<rRNJ]ҟ4WH {k.kB4 &$юtKh#Y#Aa¤{C*HWƾSm2iiKa1`sƕdtͫzRwx/bM3Og-GYX&l{Ò[°ZʺiMY&|Iq3U&0E4?gT0GAkL͂* ڜUj)Ep,p~<,쇁 NBBQCk fe}o8ٹhȷVIa hlcpAh쑚/YB1d֬4RSB $]#A eW, WM}UI"_]k\&V8L!,'B6 d ү0z[ǣfg8uZEjmɴzr\:0AYWe,IwhFQ$ɚb "8gCʧ:||Vlk`+ [L_Z*"D.PkEvM:@JԋXvHEO5I:=" r6_8M Y= y$<Ǔ{7Jw3irCluc1EeK$GئiɎ6:TDz5GȦ yc5Y6KPd; OIIJ x-$@CRy=!;p+O!U 8y%gmc0yfp1v˘{4dmjÀ4"yCGʈYp4~Ӟyq`X +I%؁kUH oa5V=[Q=|eFX:Xo7z&;f&U{NQ\WҬm@[.LOC$/bZaiDIpTzQs}DqX[QƄ$]i )5͟.z2%DL+Wٛ xUzÅ{5dl݊A5e\H컊-^$vV0ڽ`E?Q -@!.ǝ va^|fRŢ6# *TvܟƢt8GӖ)8϶qƼ32㾓KQ"KWYA_ְ[R?c O%_~=W3+.𭤬2T5,Te5:IJx[ƺճsx -bc"q ㈯m'zެRx8khԛԼԻuQMLLql+zH_H"bt.iGw5my@Ks2^Æ" v\D:u4:mm}*24ܑT6=s֥Ȥaԛr} HOWtbxɦv"6RtV7wƼYշT܃>SAkLI9 z.}䂺Xʧ(~5XV ahXխ^ {_me2ǺȥOˀ~m-|zq 1$.Yd$Y 9]$xڶm&k 9E7a6$MðGb\מ|yvyo`w"f0-aobiKQB5<*{s+Rʟ9Zf84kgC\6&7_z5S )U/"2Ĭ6*EIh%tr7[Paش۟I5hcdE6Kt{A*W5 )T;1d%sʲ[-xvQ`*@ueNT;;6d7[ Y,Tmג8#+;Y W*--8޶8&0uwԸ[m/GeP pTqiIu[Tl}mkļK4R>+,9K|+ƘC(1{XTE txp\X[J,4Y\X/=y0r?~4V ϕƟyFȓӊZi[o{q}Z [EdRX)a'< *H$}osΰ/H[{X#bj̮ /R͜LҰjֲ&B:?k%O*' W{d8㖯Ç L6pIoݯђwu-/Rs@MGXÎYE|l I5`05/xVVr#iVC5=X:M?Zrar@<u`HP(9Qى)>_X JsՃc&<2k_a-=48FX)i *̚s~%F&sO>m+PejS Qsk2Lp(y\nږX+5c#6ˇ°lŊ֥ܵ3ʍm& <#^,s|-I+m#3 5Fa<€7M̶4LٟFʠ5z2ϚjPAR"9Ø8g9?DoZҰW6q)`#GĩV_e2jǠ#MG(~v-G6CkƆ8PWOĴ);ՇHɆ+I:b\c3jX01P5D)پ|K04pؙ؀hi?+$BoZu<EKI50@Ũ&eE$I&khi! !b@;iF'"sM(.rvV{-XY ; y)WSi?cr1;?J|wV\tx=Ӧa>MayT0bbdv>Fqb<*eY%e+mXDf[X!ZM\'/'JtkV=Ʊb#y+6!H,ـ<;bXP$q2isz,{2316ި9D$ʡvSLvk\WA.A,.&Ѽ*ia3%FQdy6'Z)F;_՜j1l[2Z.m<,1fYM ŴeHc8<=+6\Xx:fpDx{AsIbBa0ouE #kTO>< ${xLk 8v(jrMw$ lL~N{wl䦂fmg2BJg0EF J*G&)}eq`Z\N X!7>ObVd9&{[^Qm O\Yq8Ye^ܦPX 0즏#qC5 el<(pZ65s $侮M*p*r뚳Ό٫ȸ4G[E!>}(l~bՉf;^H2`캭 !Ga\V9E0@0oep4h؍mưѶ<0"R:PJ .21<.X| ɺ+ iųA m^F=yl2_FM FvOֲ60О2RijXv̒'rO >P<>ƥ4pݔ=.K0ƭ`6<|ø1z0vx|EMUk{5O:߁ 6*I7 ,yYK\rң(ڶ;[&$Wm=CkRa]e𤁜ɻz1df$7SCKĮriu #)yS̀4̷ey*xe;09_JE ۱`r>OU>O}iZWuvF+in]:tN#ZEE[CV#h54B] q΋WwET;<*_TzxBΕ\jt^6J*^55'!1AQaq ?!_MV8q)ܺ6n]xa^fĦ*q8c>u~'Y3&M.xfGF̽u뚕TS"^3 q<Ueh!ߦRi^;wuPx?P\/]*!n< 0+/=:GLjKp5^mq,\[Ƣajr D{lWRY#E1v"L; 7_s-/\$V:axPN/o3s)dww^5`\&rRw=k̠W&鎲`|jdgfs󙎰|.'< ߍKS\u"d -|k>M4bVF9̥mi!kŽ>Fd׋78dOJMV]>ԬFU(x.VM)wר^#MbuN̫-ߗSC䁀սv nǹˠo~lS`-͞E#YbRONJ6?mcɈjƒÁ|ɏF\V今Efsz2: bCA)Sta)eu+ ;&|(hJ{fJ|3B%S) H~ԥ{@fyrP49 @Ah Y4 bbܽ2coW]swg W2árz~߅YopD:Q_UlP' SkI9؞&r(כ=\|J[;$r\옄x~YhW 2Zܪx8OKPqs(8N>n1G|7|EEDs.U])rQSh M6胚}*!D ;߉!x*xaj,V iRO\ va#Yj1f=QH74!wPE $j߈^]Ɓ4!lneWQZ/§1)GN%1LF qgGP%)U%R nS_ċ@."p,chWbqʿ0/&XuNV3Vٜ DTU 0*&[j`rssܠA!&d *#eȒ K6q*|:IJOKVKK[ξgk;'SL૶44٪~IER֮D 2<(J {w0-5+fPڃ$U|c0mA_7Ԫx0`e{2r1<&Wt`% bh 􅾘$R5GG\w$EcV^ %3hN9a:Y%FLfTc2# pQеMbL{bx]<A-K  Lϓ[`ʶ8xm>AðC^"Ɯ)xf&p e{kzxeZ`8yVR|Uq2m_1uP= JbfK@΅EOKA!*@mobp ns8΁y TQ(O3N+M2 >AQ8mn#d]i/b Λ&֒#i`'씃]lF8beb_*0݇+{uR4i8k+d ` p=Ƴ3j(ن F=(&p13*coS Hmq_΋Uxe72 V*OA  Gž%4LgGBr8nVo5!fnYp!|LִeGTn Y2V/!Yџ fZ]eSa?riWԬ ՘:['l+\~+%DY@5mk<U*9ꬩ`PVfjU´IK7^淘Ԉ*PicXM[Tqzf)cw\ 2ֳ=nqYUe[TP,4mpxZ " ?a54Xx[NC%n|X9z¡q^'Io+={b8*>}NW)s}ig&.(9IcW@(cg )Ϲj(q?b8umb#erL) 򭘼5-L+Ţ> il3(P΁W/qw2Th8ZȺ'9# ch텧z ů*`PhLyTLc}FyЂa3bzOp_`C5EKa{(# Ί)e$_yR:k @I{4]F;R3<3ǜ w2 pX^qrB޵3\uc}i@#4-HS3 e{&SV=7#@GtGrͅ@0ޖ`roĥC`#<+fh#)KS:mks8Գ}HWzGU֦@穌䧢pZiӣ{`@'-L Ƶ»^4TmL4l]Nn 2)]@@sEk~\G_Tj?R <; ,(KN1tqz>ܭ _ ݜcQlz[T֜_trid*衴S5"a7pUcƻAnn]lljOxL  @T>mU܌3F*c A 4 C,7|LP | %@~e0E1RqC&)j&_no9MXgj`KXfd8 &ݷ.0pİEcpYIiPieM&*/XHbW>״ 21!xpb nmV}fbmL\@YrɉGg0?8#ysn{-9i䅏d4g)SMV0xx^aKxF ,ƶ'ge96zUĕ,5E~ JG߸P;W bªnb*. h("MVqKH Sי?6tX:,\+7 nowǗ̥Qe]@ŤbC/G ̎"tiKpXN^ş'0t R":_@Ly-G97GYj_Y_Rs&xBr(4(@CO8ׄbӜ\ W'G:Qe,so2X`XYaZ`qQPL#ȷXj8U1MȲ/ps\;}˞9e +};2:zw.K٬Ku(;{޷骢>k0?(.P"͗U|p8b,4 mZ (H XF$Ȧ<`rOl@5ˌ/DȖF:0.W=CY'} Q<i9q@ _G27^;N{I/ \(bVe*6X\*95M.Ω#L:[!z=u{{nPLG6osZ2Ğ-녱N>?O eKpo4T%SYxb68.5heG pncpLµ83UnZcO|վvM*FX\o\č\ aܼkPQ913<L9+~#r25 2R$[ ̆ cGze.[_#^>wp-gz$'ԡT&1;gu%s,2%+LYe]9潃w2S SYro-@I8?BM) ^<#| NͰ# ( )mƮpḧ1r[9(>ωW ?yp}nHƁ_L;+>fqd‚suFbezz363ˠ›)$?P:¿6z`QgU,渵MIt>&B8rËSPI̎pLnl\DN^J_Qve7 R B_ݝEp q08>ka5(J~|zAG˶ۻ 3]<;S#ALzB|=WT^}zT  2EV[t1,f*sO}n ^(/=-li~a] `8 0CӬBCK||L|a#ts,n~b܁jq\Fly *,j#(,8Cq sccuo3DoZ_jH] sVY7J//y gb:]J=Xqh;;;~6L+A1hk`0c~aeVA|ܺ?uRJXP}6/87GC>bN[)Yh~ \&/cQGGv㕜CVsiv\r"#߶@, O,67oi5St;!xu0BaoC׈ %ԠGvx1kCX}^+ ,1}E"iQ6yԦQp@[!iG!,F p8 *^qϜ07p+ .kK p4o&8"ZT.(TT~^"Y6&=Jfƹ)Yrz ]^z( щluFgH}jдR޳ |JyW)m]8ĕ)(*lL\ -s_Qha3qXʛ ` n_ ,Uq3K$z.-afjգVTsm# .|Aiȫ/ĬJ| _f Hcro -A_orw#ÇxmᩁWŠW\oGuo.COCA3(UpLzms>4wrSorΖpc٬Um5 huYt(/uP\]j>`$m`JU;"WTk1y쓤h`-9,8a(cтިybp/̱an`J\Sv%FׇDxoc}ToL>溭_ankQU51Wv^^q |@"{ȰyC=-8]V]p_T1e_d K* uk-gtE0jsE)vYݔ@~y<ϩ n5bBRQͰt.J,9KRt'rǯ 9{ZUe xQD/rn?0CVς'K u8jpߍ \ ݽʨ6+P.f43ie !F9"JT5/- : ʁJQ`C.}i|FjB@yKk{%4kpL^82::p^ޡi=[ u:ŗo+R''c- `0/-ܭ qE&~PrkY꿉B]wxꛀQi*2zq(jQ J)Ȩ|eve_b}Y3W_N>[eCӫq\zm )P+ VTRm -l#$,/SP? c۔~ <d5PUb̳vkf@k`Rs!W,9o۬J!ePӔ\lXx׽ 4n`7^ sUs3XۖeB4hh2].*V??,VF.]/xfjc^$l7W?PωT*2։yrfIjo;'0ÕOA, x^rm?DW sWkXK~NB斝/i7P(-iS6ԅIj;Eb66jeyc 2~AS fmҌp i/ȷ?Ruo4(EiMU;|0d13k9@߹UG|[(pG8PT*Vey]pj- &̱vM(3 Ga4(cTRͭkl@,rQ0 !J!M?`)4̧pLs\mM]BR0eywT֯П1&]oEg!HdB+rǚ]N֢5)Tw\*~V(06VU!QpsIafOdY?R4 jC¨Sub3pi"yhsM2P."-ĸ]D*y{y/ l-gLEh;Jix_  n<я7jp>Z,`ESj xgY%4l^"E#®%ac2A b^#Vx"KgwLiN1Ճ.Y" #E8Am>mu> ~ASP\$obS(Y}̋t~$zYoƫ%|cBa0QGZ#Pi۩´&1h|%pŲB @\}kjr#{T8,JiG06I^6ܹn/rC`rq8p 4-)}Bߓ4 ~qgkԽkN|B =p.-t$' `YmW(6["FTKUo#[3O~7nVdx ٫FV SAxwJբt5uk'hd\ķ_f`dl\7u75ZYu0`]K_K;ڻ B)U2@з T Wd].;9xMIb,c<;+5*=9ۓ+e1Vx7XZO;VRPO@f 9ĽB  JL](B⦭꾿)+z0y@E"o|)qѐήߔ#`͠nǻ0uߨ ;Ut^xJj!v)maV-Ingj6蕏8糩{ʟ[~-h#BT0*x*lj(l˙srﱃ\rEEdjh'ԹWTQZI[~*ZS ZĚw^qk85J{Fסj+qCExuE*L_YDR'>%4bTr"0Af{Q2w1 ze&?<1γyOj-I|Mn \ hA*W [4]5f¬|^;=ѱ~&MR|eeH8G=B͵Li/z!~`&&Dsl69r+ p ,ssu5c&co8esuGJ5drAyxUt |[~ Wt/"4:7,:&7yd׆r.:N2Q͋ssdЩm&<)`R3r)1p O:Ҡ yPVHquD I,%5&e@I8tXܯL_q j/mK¥w+WWH,}yF}2/2,?h` 'Kv7VD4lkwsܵ , £Ris|JAK7 s-FCX%8d4㻈#eG7qؽʖ":,m[%ZX2=\ӺybwQB)0=\u(&zl'#,Y=A@:ʽ\' =#_yaLDmi2"T 3 oA8/x\ɟlEUJFuo/E+s *t21Eog(6dכN-<2̨=u3nnu4-3 ~<[ ~V'qE͘}ajFG=x7hum  ˿=a|L?sy@.eA[N=vk->9Sa߉x[0l-~Nf3j*\h-u@YrŠ-\9+3Nuܽurc#`ԤšASj6ppJ_#fe50(T!*&?v|,ޢj+5sidVVܯ2>ѧ>E/ĢSl38Y{E·?Ɖ f?aqe"*|2b-;5jQ9`Gpڱ3R& #Z͹ P"-Nse70^I)%&P}4] pu # H6N~`ѹ u*9xX b:u,Wȼ2ֺ@}e=Zf'XʵiEyN-(30\&n`p]iw8K}?̴jWV8 $Zj>c 9xIpX9!ZTCUP JkXZrIJREFsrqeۓQ8 YȢم߶[RcJqG/;$DәGԇ.zÃx8Y@Sg{4bkTW MRU[)P>)sqiQ `6m"R‹kx3 ^_$9+J(8|%nÒ3y|@5nTarCcWau*{eYՑ~L3X/> >HqPt3Hs  lŭ5[ߘ\y0`h m@(1@+bYTVf+Ɩ!z\ɻz11s~ V2z:jK%Cyx bʘiEbVc/|#Y*;"RvA\탑#*]*3AjZk#Y6<,HA`(fCڳ[j JobA/"XɇUajԳǴ ZK49Fa,-UJYj?¡nCGh94I bt3|'?L.㘯 A 5NkQͣM +췣͋0桭5CߋAD#> ~  瓾 V0Ʀ\˳Cs)ܸ&e<5v8xsm5C,tZ IVu5aj?Ry-"p t:0 a5^p3ʓS6|EFx5DkO?QYvåf|n诰w-YS Mj O{46iTh>yuf8C䗧3[VvwWX#XmZ֨"»zikm[j~߂3?L8e];mo8ehqh祉q}틀FK_w ,7-Ү6P "\',-bNxA :|Bb*j$F+˼}1Mp1a/kg] ùg5~p@X6D;Fcyӌ1vG/w]J/sֱٵA:)d|O;yRЖ|. Ԫ tSTp`KT)P]hܰHH.]%u̲X=fr[>aV( [Ɉ+57Frf뒙D+hLmm0@jA帛. %gD7'o@kdm]D(#U9CEk4wwJ;-7c8_kϢ_3Z9Kc8[jr3 xO AL_$kD>!Z)P~r ya]ʼDW̦q)Ru+ZeO2_7lC5g<1< [t\6t{f`rÁ}̘_sZUR@ 'l{g`ˉfڕ+ha\2r99EFCZ%?}K\JP]U}N =B١[o Rp%.s1yFxP{1r4c 1)dG13)wt.6+`uC.΢ohg#Gܫ\Cg}Kb!,h"M]D7M~e6!9ʚ}F?R:$9qfsR~&}6f8JF*^dX~x7JߏAYS'yTø;V!Mqq²ꞥz+M_&`:n< }J4rE\UuW}8gW5=nM繀W5s+Ew/^?s>u&!t8&7&w Jm7Ks^JW^:>{U]&Ýu+KP\A'de(xICu2ߞB{q3*KhrSkUlsS[^e yo.%bP.R׺,lj[oq|y8YaUl Rڰa44Ь&G.!vX~J4EX*Hlqw]x,U[>Tàs4(魱kOqq7rqv/72q}2R;4yxdaw;8F Sr}ȤJf8}qͱ.|v`'U45u. 1eJ, \"U<:XѢʜoQ&A96{6(u? aaYbjC2.*)z{xWVl-HM3*L2쐰qF}K*C\uNYLI`}i4-!#?ܑ/RfĸUNa$%C '!CNA,aIV mИZtB8xIcÔx)ፊ X0K.Z)ILv`c|BM " 'q/?kbr.[HC:hnJym3#=s* DUO!s"6 x\9}0dt v-S;jM7q3+)f8Ttt(pҽOZZf.eX$ p΢@d bĨ}e-Yy"G:dϘ#H.@E^hJPU >UIT( ^j'ȣJY*v [s49+~mɽn3R6|NƁB*t/^'b}|91=%!1AQ aq0@?ߌ[||<\K؎`Zmݬ-Nzvw<'Ma7x3#I1H`Dr0{#R_Wh0ouwX}\G`v!0 |!Rv-$.QK0c|f9lvYk9E_a\KoiGWՙ6 pӒyۛ9c'- _2f|3%|1cK3M3>smK,@ ]HTܹe0;Gqw{i_},`Bmʧ:FK'R{xvNy,nc- ɞ/K#x$acr 4"x 0}_"DۋtϿP̄Z5%{'~Z߻ >ܔ>M -O,4iRV..?#WX8 7-WRzHr ާ''p.gF Sͷ0Υ6zկFg2YxLa9`pUxV*`n gwzݒZ7,Na3pkWB&-LKcƸzK!* Oς(!1AQaq ၑ0?>?]**BIlNR\*S(/+ USަq-;j~8TD2LU1 (bW aGg VzM+|@3=n+@C?5y@?g,ec!_Z`J{X^&ھѻj􃓻RՖwQ; 0~@;aŧlosRpDi)hD&`BPQ,ɞ)nIL u)Y,;_Mp+*T9+⾒u|W7,xc}K&!1AQaq?Hx/N:D/@(R46Ԝi@Sق٣g<8TG;!!*tW \'K;WCc*la'IъYf)xшvM.Ż2GL>CxH];}9 =kC(/F1 К++Løb\˃䐻C@QS~ ^<ql^RFk$^B?XJ@VR{_IT[t% Yl,WU 8c. N|cw6GwD*WT>Ywbq+gف 3HƚSU?7|~1PIh ܎no6j8hCyNo㟧X+q<⮈mZ/7XN|ze _wo~|}`U Uf! C}a R֚k5i\J?B +W\0|I^S,`ʟ{q QSߞμs z~! ]:i :MkMM.6l S=J5eu( yCXn`ڛ^H~nJ)wkll<`N#}nঃu'[Ȑ%?@OϷܔ~?_9a: KzB\v_(o sG5%|M1+0"OTGMv@C=לXGc''~v!xyȥو2T;"-?'z8KϬփhEWm<@ק8Tg6ͭA@Q{Yel֜ 6* <bݕZ.#5HUq H0OƍB?4T8OYC$]# v;yQh󳆁o{ny G~J1v}pWhjNS j4z|o̓ہB @?̀$)V>ǜ) پS_QKO}Ϝ#{m!Aj8+#~M4O*y>W Qֶ1|'[f** m-˞.^ 9C?z滃&0B^p> 1났w^E_e"Z8f8w-\R,6~ Aϗ"Gx`D;w5 UPH}uZ {06i8K; ty5ee|B+=P,`]@|f$ x\\$؇5*Ē}Oޱd[,j_X1C+@O SHqc$oYB;_2DKȜe)vG˻n_Ht<_B8?<22 c! $(ȫS }7TA.^a 9UE׽Usqjͺ8޶u;cj7'dt~?XuO4[%vq%aȃj]z)\|J~'7_#BD6;?T :x8䛺FoĢLEW %*]cH "xxXP5;M?0;I].L'|!Z/:ceʼ@.; [,q7 ] M>ڃ%'N\AeDpr6n6P iM=u~#M7]+'~"k͉K\`zXl7N9PV&cÛfIMs]`re tK/QuN sI p$?a0*K٧ و[Nwi.3 Ezq}Qgb #_1$Ce.Ph.rAS{Y:H@-8lp~Y1B3Ԯ2,C(7*iOrǷp$i q{8vPӑc-MƲZg@$5+ɉC@U >'vOyzJˀ- J@o} Q/m'>s:H`?l_KAx3\n[0C,ht5vU&$65,w*CB$, 'ȧ˃Ѻ q|]oNi)p^yOŠ'4rR cC&o;PcD_\G7h.+L/ BġR'-t 0MQ;ŁcLmJ(֓\F>ʀ@9D#DԊ)zSvbo` @6T'*L%:W\ x&G%/Mf ؀]Z,`T>5=#hř-(lM1brCǀÛG~nA$ofjo &Fz`/V=|Ut]%GX?6hW[POKg!q )j =e4fr!NAT\CoM&4HKMC핆/7.ѳ'2\c/x8|`!zM-kˠ;G\bQm:#FD :`̏ iE>I~ qFZ_[ČFݣY!@{L`4!95Hf(Z0It&B8$|J&|cp@#S:n(3mC&O DKMǻ S6p2۷bCI:5$ 7m m59LZYh獆6֞iCwG3P5}a`9RZLuU/eKg&rm7Aҡ'RNbS #:8MpvS8@"嫷U CwSKbgxQ((aUuȅxbCg&?{:pf3_! -V\$[1=b1]ZQgNs+].&$H" י%.} GѡTq7iѻ ;V7tcnш:AAy&ӗl޿d6UpOL h# \"!U4? c"i\!Uͥ!#KUgU7e'@QJB Nَp2"#Fr*9Ncc=΀֕^q8@{\]a=i|^ڬV^wτq~Iwƞ&#xG!|y `:DrZfLR]̘QT68x:Y׌L@[v7_(%N!WL)klu'*>w@SN2N`+q^*!'UA/=^Zv܇ oA-5 Á{c DCo3^a_2:g̏iϬ'DcdΎ'= Ej8X* U8fY#>kͼN&)A7ls#r?[6h66`EWn͜+<< t o1^KidUѨ{|Ox'#FZ"ǘ幆LP@/GsyT28z78׍eh:}umTk&Kycwm#[rہZ+wd~/jViNM E%[ y)wm>\;;1$C~ < "J !b;M{0ț؜c,bm'<= OVPwf]TфA!db@ۈ|rbu3XDަ|2w Ƶۅ ytX"2v h  m@9SxU0F @m־2j'MT"Zj̃kG@zHC#_,-^̒:P:{`8ĕvL(J^&܈Z=2uEcYYxGFZhu[|,MN UQ8 tZ&_I3dZ5)ʆ9R"<5=摴p;h&ьA@w'"9xJB'?(trT3  9SM<㭁NMW$gFuTTud4KQFOK/z\>lEjT`: I1*8'&1:b]q`(Z7 9N8ƛZk4 0e+MQ4?fo v5뉔"x:_X}YgWWm($ozϬmoYexӇ>dۀ60IX[*n!& ɝؘЧtN\ e`!nSL9RĤC4+{u7I_~2`E-"84_5bX$j/: Η.Chד-G?m5cmc {6;8iЉh9@"w.&Fj D8e!tYoh$7H*ND5ذxpg]<# #4!'<!o`>?^i x%S]kXRWZ9MҿH!O >\h OR@'Z[s)l(s(PS%5N\,<*EKK+xIUہ\ϛ>rvh@Dqm&:]9r#`xJ.M;@ŖdbPI8lDj{!w-X<`z< Zv]`/oڼ3QyqcvwGz e60@CQQaeIU:*ߪ"8zziՙŴyN4FP cr~Ȱ,Fl5X T.V6 [!U!E5Nntl\`uЍ,Xq|_PĄ @3T6`Кڤ3 0g-h yC`N 䤀vA^3\UZ.4]N 6l[oXX8Qiv9(hDgAPhA:lk!0͸sV@@aJЦ%18̊G)"aډ5f*eأjHY8â A7Ă+ten@I]v3,3 veŚ]8ȇa]^a.αfԠipIQ%!.hF^h-!t4Na(z5D' ͫeʽ͔PE<%'{…kto3i?o5hsf:p| )y9-vyu^SJqt<U;M:BȳxhT7e5? kP{oSы@$ vׂZ /& 55_EQB#&:B>8=<DgD< M V+`$Oob*HfQTYS\Pv b}i{HCS`ۼP|¶ƀl͕w6ychrQfA)\y\jҢD $˻=<$${(CCy`؀ddz:+{3}ܼ1!\XR6=,\*h+$1u ;Dh=  &}p =^|]6C43Ӕhc<)})>x 7;1Ѧ~6unt; [.|[m*@%=bX|wq#9=! W .U 0)a@ r>sF_Z3ˠwxu,"ޞ1W _/u0;< CEuxZ|Õ¯SYp9mDCfHa(oȔFvyDTay\X78XzwP9h.N(-nClD}~_ցũB"uah<ȥo*bZ+ip BSgl~pR"JT`Hd{OFͧuGPi+q?8nn}2 Eo;q7LQ7~YRYI"D8#XY \BT@xS̸ IMGQ!R$y׼sSSS" ={͆]"µ Q&9hЀNaZq2Agu``a_+`*mq(@8;użug&h#Fm?t' 8}ҮmΗfmao,2kAPSM.uJSMhZb*<5T_j\)P]UIeI751L (:G;DS%Bb) b%ŕGJDCƤy3lOPeSQJ{zJ45P5%;%3`g)Rab,hޮ/A72m,]pw]þ:p 28M+)1JHo^ RyJ[IHϣ5HsA1^$\eaL'HV|Mj=pq\J83<5,!v]ލaf` &M?8mX'?-StWU6j[_UVÔ^-10,%؍~a`:Xya;NX%a p-=..<]^9- !@TDCwu}xhGBiATl5xMɍ( 7o+wKyBΙo/JkTx燼PeHCOY ^)^Č%D ű"B5D%ap8wKU-tj ({ FAN`T[F  |\ w mxP>VV.@  GTؒƎ 4dt() 88%omzNĚ[^mM<6w}aYM7сt[5O!:r` (4u<4QU Y$I!n| !1XѬ p5_sx+Ӭơ16}ՠ~F̮Ҥl4AF' L (uyѴ Qr1FDv<߈*PjG<ͼ~ďsQs\.i܉`HsBANw+Aa޲BdD"̳7T,X(\@l;3E@oL\8 Phԍxpkb,;nXQ1k ӛ[[8tYy(~M澩.g}fT Ѣ^)&׈U-w*fUM 2"3Zɒli p칹_(/%m_E~@m1^pzZZ@njX_8t=YMg 6F"3PJJ %OFEx%'[–sifpBӧY\XwhqJ+_ -uToq0;~ w_Ne t8>_1eb Vx>|09",;'=b[R͠2&Z0N,C`K0{{U[&m!!66iIqCTb=C5#aE/3s 4Rh \54{uh)93ˈ]4o*p{[Oj^f%6g!a$XI!(`ɟ/q&=T)]nW嵔☛P ݿ.y +Թv|x<6tIȢ(f%HQ8.$BX+JM)")l%pcz5U<5OZsI[fpƓ$#F3B6%P&/;'nIFXpЊ`|O3FXEv?(O[xTv&0`JF?^-Wk<^AUՍ[8$l/i$'rú"8 DŽDАl?XphDxXsb4Y%pqw-uD> ށV@~r+ %iˮrٰŲ +G^?7 t! ~nX6%@ˏ- KIyܽ)!WEJ/&^:N[#U$E!)m +^/LaK"'h8kٵ(GrC0MwChC7he곝T o KF o}c)ѱֹ.&&R 8%#>4aUl-GJ1M$đ&@t4:Qed 1y S`CvT)*>mDg'6R5Iۊus.wb%:/pRp_^d[ۓ(\blr$PA{U9i 18w!*HCo1@njݓLNKn8zX|RUCf:ijjŪq[=.mFygVNU($B`QwQ5D:I/tNŁY 1G4 R-ĸPRcpA0u% D=񁷉H,hS^F< )S,HaӏIZ^vLÐl ̻SHQRPUN rTGGOcy4 |O jT/=<ΰ8Ia@ |+QX9ӿx^dS}\xYgXJ'+_y as8|g4~W)`xu*BMqV{{S:o-[zFf{cPR`#@u*k6B60X}s@ӧP ϜtUGE-}?^1--wt׼(J΁C@r6+SKJ"d-F7Ƿ;K'bXCGOD05$ FpWw'|A/V0;"$Fh?9 c汅X,Ú}= J 1+4`?pɢ x6SGv:q; o&q&Bj&*u$2B_:WcTuZA0 [<; Fm Ƃ sx0IQRdhD7q- ϔ2 ||s& y_pwZ8 Bq Vu*D%p"H7o$3QtIX&=~OfXWwEMLÀYȿ?=F$4/A>NX~nGɩ2ˤ8 ⚇\;e%^~G٩ 6#bd因ެ83Piy*8kfSQn4Y:י aJap嶭.]>^gj){wm%zgT[i;g+ :Xbf\ _H /;9"Upt,b@QpD Vغ+nru@a8QH ^ eϜ_]>&aHq.,a0LBud6Ol! NAx㋛ ":B-F)NBhMm%{ w7gVty4ues2cŠ@~{u<-Y7A“m.i8˗..ph8ֿ caFӋydůcswHl'k tv{X锈/ƪ7:Q~rs~b3מǀ hB|c#dADt1"_Rboaɳ)O/L\Jx .fl㕼 q񛏖o*5|ViӮPq P6<~q/m^Y@ ڤ5Gşt$\oFc{\wYB u@@8C__}%:0>\[A6pt_9ӂOXZAJy:|?"MRC9(c%Q1,PLu6' 7V>H<eBRM8Յb#aFq'lCXH͐ qҕQ vnMbIV",R-ӣU'f`;Rny[;K/\n ܘGGrb} .Lp^^niVO}"fޙTo A͌UVN bƀ&N>*wh@.QEǝo]a!vCXt(BFW2E2!Y7Zǜ8\J 9 &seO-=@)!`px 5'j) =Ӎ :k_ݛ眗*v# >~pC@I9b52f4[48Z+͗A/q#&Uvbx}bP)>0f>'{WUS;kHT8).Xw//+BttyA"&O)!NE] 5"xb0/Tx0h|8̊&9 V6]{ ww2>9HiU`\Hx. ?ŻcZ`28/nD7!{!mP"Ъ:BDBԽ)γx No jłrrP Gw3lmUI9*#HRAm@jt3@ISm8]] ]bTtQ7@l`˄7h:6{$##xyX0"}34X{.SHݎN1]Pw @hIq+]pae_"SM<F`].Me"@B-:n=>"u/ebӆ/&&_69(K/=;YjƪNu DenfS5=r#!TX-]XiZ&ZKqˆmqNr]ezy3U !4nQK{R3qO& jcʼnhw%렕 MMJ!u;bPÏ`PqhKX@xql)myCkjC[(Y S&ό ~H`^]GwnkQ),s J.!LDE}wH E&+v):"$*$A)mѢäQٷnliC|p)R x9cQQqd6hxk^OhH=R6*^۝ zq0^7DWxCN<!S=` /Ɏm,1FE>U '؀w@"쏜OL;OŝH BoYE.ժлL!oJ9$$aR`CG5䘼a`P3~kU[QnHTPA*;K>ll CKF.%اrpg >Ym (seE}bi4BFh!.|cvH)@6NNi=t5r,Vc%xʔp;sY;Xx.84gW A=piqG`8|lsٌI?Bi;x \QIlOX"j:UɪL ^ .ZT88+c kq $^`?< 6`~1Ύ|10"4Z4oUr݂+~yFh@UZ~xsf^ŏPib n-fZbHt}cO Y8zѬ-qJZQLe c IAV$8$iqHJ=sVL E%4P;,?He$:5\Rs"ZAXH)=@eGR* GXG1!RQH\+ZZ`૖n7+6~qSj:Pa9V"#*gK%}B( G:YQٵcgy5a숲eKʄ_F$Mքum`+Zdw+m%XiޮqDъ\ [ޅQobOHTH5ވ-M>W jP=y[R͊kٶ=+)!P3 UMd'$KDlvF;Uߑ=p{Ӆ!Q!8HM̃]skWVe죍J $=25hgn%(@4tVɤ!Gs)9[lJmAF'xR!`"ӦC; ,//)58' "N P u+D;QCCjQ85L\?.AntoEfn Z7"Y⬷4uqHM[ $?y`RVަ=X^n4#`6?x *C[b j|ֻ$zƻt("bAJӥq ix#=E@9iXJZ_DOuh닍M,Ksqx P"! ]wq#BҘ#FDo2Iϝ&ob7IF=fuGWڼ\6~r(eԧ=XC"& 5"@ A*a}8X+N~9vq! o킏iBAB^)k%8F .bx^Z*/w(^R1oT2u4:o+ŕ[v4w׳}_Np1,y_bEp4rRho?]`o4ލ9Jm<"ZHڎW|q4N=PB@[ҺƆX64Uw?.|϶ `|bj=b\'j( .j3#AېBMάLt ߉J jt0QAp!o0^P Ti be0.`}SRRS ݸ;+S*Ow,BL ;5K2[l/RSBo6ī /;_#c0* ۲"4@<}=tcu͡jBi p/Any_.Gӓֻi Ɲr ѣ#b̾kmu&!g4ؑ*Pᛊ2 )Z10wzgT4 <)Fo9Bv744 CˣzH:!+iZ+Y3QխmbF+ZYJc'Oj heќ(5>qc+l6j3 r~3hg k0B s*5-q>]>ц 6I,2DKr^݋;Uaݥ'('̸*jt>fj΢;3$<8y: 7J]!q6]j2va90QpBX&@ü2.i[C\(Odsh-1$N (G@t&+^ Q~]U%נ8׌ \>`X( ~Q|bD;cIAVjdV.[x[yFIJ;%⤢<rwABQ:7>o c#n;u@$EAjT|r DMαEEٽarFaYP9qzPHl8TXPLMAS8-ݻ֪cM8LqwVANCtpgJ+Ƙ(`($G&t%\Y ^35" ὾q/jmw^2|d%pNBAQWHu](xQP*.nx4 ?cDRE|& DE]~0J򽟲bE.3"~,M|go_D_XhDD t;th415v z-$Z׎2L:6Ph@ri5,EF^YWG1UJcM]&E^(G%AIa e>€),8XQLw9+ yAB. fD"pv.WYq*BzX9z<#\Ϩl O^%4.6 pi) @G,B>x}R}^%4$5ۈ.E^8ybHV-Rs <m͛@G<7LD*gccjFl !n8Nn۰z-s9ڡ28ɇ;NPҙ#Etӈ5Ŝ<}|oiZ pmX_+EiY?08)PθpUk aĻc3Ùy7fDf+t~A0!1sbZ cRGo t퉬,sp[>V^ )+678:>9£k\sQĪ3j;&@Cb_`+ G9)aFm.r}Do cufms|^1Tj.g؎sX"B =4"<{. !۳UudJ;7z"SZW3V>eLl8 5{W SǙn>nӓ7U~p `tVu|02mBÒe#mPvݪڄi Nʩ ncOGAJZ}CesЉJzIzp=K1ϼdJ_y)tS95 ;98risKe{N5z9x538I 8BLE 8N\þ kb6qB5B72G9 u !ٽbESIa=#rA6C_h <9sC4=Ig?9~|cTD} ZEm9XxCvל*&.8ur/};l5~{8H|[Np??8i9͠9 a4h tߜ#/gIq\WBl8{ |_9"vuUP(_!);8^ܿ]t,[a)hiu DθhI>; Bp[īk! %۱ vN޲YOhGUdPd,% +yL+?CM|muA^޵8гcV1P8ز @_8PaAVAǛ6wVa0j$|wQ,,Bg R/Oj'Hjw}?y_"U]))޽5n]i=&(cuM>0Bníbh s P%i/[gwAy$ck Oz?lB YF pj񼵱x+c0AOz =avaS__$IB:G{m[=|:j7@N P=zX%wXK7zȀ72(%O6Qo+_޾fBDÈwg\+eHzG.ZM8\H$UxBs̴_e}RM_aOUh8V;ku'0^`1C1b@;w[rR@7usǍa񿏏b?4FSt>rp)_9`$!yN*vrawz8AT@CNbFsU^AH` module can be used to create and use TCP/UDP sockets as usual. Delay and timing ---------------- Use the :mod:`time ` module:: import time time.sleep(1) # sleep for 1 second time.sleep_ms(500) # sleep for 500 milliseconds time.sleep_us(10) # sleep for 10 microseconds start = time.ticks_ms() # get millisecond counter delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference Timers ------ Virtual (RTOS-based) timers are supported. Use the :ref:`machine.Timer ` class with timer ID of -1:: from machine import Timer tim = Timer(-1) tim.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1)) tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2)) The period is in milliseconds. Pins and GPIO ------------- Use the :ref:`machine.Pin ` class:: from machine import Pin p0 = Pin(0, Pin.OUT) # create output pin on GPIO0 p0.on() # set pin to "on" (high) level p0.off() # set pin to "off" (low) level p0.value(1) # set pin to on/high p2 = Pin(2, Pin.IN) # create input pin on GPIO2 print(p2.value()) # get value, 0 or 1 p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation Available pins are: 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, which correspond to the actual GPIO pin numbers of ESP8266 chip. Note that many end-user boards use their own adhoc pin numbering (marked e.g. D0, D1, ...). As MicroPython supports different boards and modules, physical pin numbering was chosen as the lowest common denominator. For mapping between board logical pins and physical chip pins, consult your board documentation. Note that Pin(1) and Pin(3) are REPL UART TX and RX respectively. Also note that Pin(16) is a special pin (used for wakeup from deepsleep mode) and may be not available for use with higher-level classes like ``Neopixel``. PWM (pulse width modulation) ---------------------------- PWM can be enabled on all pins except Pin(16). There is a single frequency for all channels, with range between 1 and 1000 (measured in Hz). The duty cycle is between 0 and 1023 inclusive. Use the ``machine.PWM`` class:: from machine import Pin, PWM pwm0 = PWM(Pin(0)) # create PWM object from a pin pwm0.freq() # get current frequency pwm0.freq(1000) # set frequency pwm0.duty() # get current duty cycle pwm0.duty(200) # set duty cycle pwm0.deinit() # turn off PWM on the pin pwm2 = PWM(Pin(2), freq=500, duty=512) # create and configure in one go ADC (analog to digital conversion) ---------------------------------- ADC is available on a dedicated pin. Note that input voltages on the ADC pin must be between 0v and 1.0v. Use the :ref:`machine.ADC ` class:: from machine import ADC adc = ADC(0) # create ADC object on ADC pin adc.read() # read value, 0-1024 Software SPI bus ---------------- There are two SPI drivers. One is implemented in software (bit-banging) and works on all pins, and is accessed via the :ref:`machine.SPI ` class:: from machine import Pin, SPI # construct an SPI bus on the given pins # polarity is the idle state of SCK # phase=0 means sample on the first edge of SCK, phase=1 means the second spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4)) spi.init(baudrate=200000) # set the baudrate spi.read(10) # read 10 bytes on MISO spi.read(10, 0xff) # read 10 bytes while outputting 0xff on MOSI buf = bytearray(50) # create a buffer spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case) spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI spi.write(b'12345') # write 5 bytes on MOSI buf = bytearray(4) # create a buffer spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf Hardware SPI bus ---------------- The hardware SPI is faster (up to 80Mhz), but only works on following pins: ``MISO`` is GPIO12, ``MOSI`` is GPIO13, and ``SCK`` is GPIO14. It has the same methods as the bitbanging SPI class above, except for the pin parameters for the constructor and init (as those are fixed):: from machine import Pin, SPI hspi = SPI(1, baudrate=80000000, polarity=0, phase=0) (``SPI(0)`` is used for FlashROM and not available to users.) I2C bus ------- The I2C driver is implemented in software and works on all pins, and is accessed via the :ref:`machine.I2C ` class:: from machine import Pin, I2C # construct an I2C bus i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000) i2c.readfrom(0x3a, 4) # read 4 bytes from slave device with address 0x3a i2c.writeto(0x3a, '12') # write '12' to slave device with address 0x3a buf = bytearray(10) # create a buffer with 10 bytes i2c.writeto(0x3a, buf) # write the given buffer to the slave Real time clock (RTC) --------------------- See :ref:`machine.RTC ` :: from machine import RTC rtc = RTC() rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time rtc.datetime() # get date and time # synchronize with ntp # need to be connected to wifi import ntptime ntptime.settime() # set the rtc datetime from the remote server rtc.datetime() # get the date and time in UTC .. note:: Not all methods are implemented: `RTC.now()`, `RTC.irq(handler=*) ` (using a custom handler), `RTC.init()` and `RTC.deinit()` are currently not supported. Deep-sleep mode --------------- Connect GPIO16 to the reset pin (RST on HUZZAH). Then the following code can be used to sleep, wake and check the reset cause:: import machine # configure RTC.ALARM0 to be able to wake the device rtc = machine.RTC() rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) # check if the device woke from a deep sleep if machine.reset_cause() == machine.DEEPSLEEP_RESET: print('woke from a deep sleep') # set RTC.ALARM0 to fire after 10 seconds (waking the device) rtc.alarm(rtc.ALARM0, 10000) # put the device to sleep machine.deepsleep() OneWire driver -------------- The OneWire driver is implemented in software and works on all pins:: from machine import Pin import onewire ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12 ow.scan() # return a list of devices on the bus ow.reset() # reset the bus ow.readbyte() # read a byte ow.writebyte(0x12) # write a byte on the bus ow.write('123') # write bytes on the bus ow.select_rom(b'12345678') # select a specific device by its ROM code There is a specific driver for DS18S20 and DS18B20 devices:: import time, ds18x20 ds = ds18x20.DS18X20(ow) roms = ds.scan() ds.convert_temp() time.sleep_ms(750) for rom in roms: print(ds.read_temp(rom)) Be sure to put a 4.7k pull-up resistor on the data line. Note that the ``convert_temp()`` method must be called each time you want to sample the temperature. NeoPixel driver --------------- Use the ``neopixel`` module:: from machine import Pin from neopixel import NeoPixel pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels np[0] = (255, 255, 255) # set the first pixel to white np.write() # write data to all pixels r, g, b = np[0] # get first pixel colour For low-level driving of a NeoPixel:: import esp esp.neopixel_write(pin, grb_buf, is800khz) APA102 driver ------------- Use the ``apa102`` module:: from machine import Pin from apa102 import APA102 clock = Pin(14, Pin.OUT) # set GPIO14 to output to drive the clock data = Pin(13, Pin.OUT) # set GPIO13 to output to drive the data apa = APA102(clock, data, 8) # create APA102 driver on the clock and the data pin for 8 pixels apa[0] = (255, 255, 255, 31) # set the first pixel to white with a maximum brightness of 31 apa.write() # write data to all pixels r, g, b, brightness = apa[0] # get first pixel colour For low-level driving of an APA102:: import esp esp.apa102_write(clock_pin, data_pin, rgbi_buf) DHT driver ---------- The DHT driver is implemented in software and works on all pins:: import dht import machine d = dht.DHT11(machine.Pin(4)) d.measure() d.temperature() # eg. 23 (°C) d.humidity() # eg. 41 (% RH) d = dht.DHT22(machine.Pin(4)) d.measure() d.temperature() # eg. 23.6 (°C) d.humidity() # eg. 41.3 (% RH) WebREPL (web browser interactive prompt) ---------------------------------------- WebREPL (REPL over WebSockets, accessible via a web browser) is an experimental feature available in ESP8266 port. Download web client from https://github.com/micropython/webrepl (hosted version available at http://micropython.org/webrepl), and configure it by executing:: import webrepl_setup and following on-screen instructions. After reboot, it will be available for connection. If you disabled automatic start-up on boot, you may run configured daemon on demand using:: import webrepl webrepl.start() The supported way to use WebREPL is by connecting to ESP8266 access point, but the daemon is also started on STA interface if it is active, so if your router is set up and works correctly, you may also use WebREPL while connected to your normal Internet access point (use the ESP8266 AP connection method if you face any issues). Besides terminal/command prompt access, WebREPL also has provision for file transfer (both upload and download). Web client has buttons for the corresponding functions, or you can use command-line client ``webrepl_cli.py`` from the repository above. See the MicroPython forum for other community-supported alternatives to transfer files to ESP8266. micropython-1.12/docs/esp8266/tutorial/000077500000000000000000000000001357706137100177325ustar00rootroot00000000000000micropython-1.12/docs/esp8266/tutorial/adc.rst000066400000000000000000000011301357706137100212060ustar00rootroot00000000000000Analog to Digital Conversion ============================ The ESP8266 has a single pin (separate to the GPIO pins) which can be used to read analog voltages and convert them to a digital value. You can construct such an ADC pin object using:: >>> import machine >>> adc = machine.ADC(0) Then read its value with:: >>> adc.read() 58 The values returned from the ``read()`` function are between 0 (for 0.0 volts) and 1024 (for 1.0 volts). Please note that this input can only tolerate a maximum of 1.0 volts and you must use a voltage divider circuit to measure larger voltages. micropython-1.12/docs/esp8266/tutorial/apa102.rst000066400000000000000000000063441357706137100214570ustar00rootroot00000000000000Controlling APA102 LEDs ======================= APA102 LEDs, also known as DotStar LEDs, are individually addressable full-colour RGB LEDs, generally in a string formation. They differ from NeoPixels in that they require two pins to control - both a Clock and Data pin. They can operate at a much higher data and PWM frequencies than NeoPixels and are more suitable for persistence-of-vision effects. To create an APA102 object do the following:: >>> import machine, apa102 >>> strip = apa102.APA102(machine.Pin(5), machine.Pin(4), 60) This configures an 60 pixel APA102 strip with clock on GPIO5 and data on GPIO4. You can adjust the pin numbers and the number of pixels to suit your needs. The RGB colour data, as well as a brightness level, is sent to the APA102 in a certain order. Usually this is ``(Red, Green, Blue, Brightness)``. If you are using one of the newer APA102C LEDs the green and blue are swapped, so the order is ``(Red, Blue, Green, Brightness)``. The APA102 has more of a square lens while the APA102C has more of a round one. If you are using a APA102C strip and would prefer to provide colours in RGB order instead of RBG, you can customise the tuple colour order like so:: >>> strip.ORDER = (0, 2, 1, 3) To set the colour of pixels use:: >>> strip[0] = (255, 255, 255, 31) # set to white, full brightness >>> strip[1] = (255, 0, 0, 31) # set to red, full brightness >>> strip[2] = (0, 255, 0, 15) # set to green, half brightness >>> strip[3] = (0, 0, 255, 7) # set to blue, quarter brightness Use the ``write()`` method to output the colours to the LEDs:: >>> strip.write() Demonstration:: import time import machine, apa102 # 1M strip with 60 LEDs strip = apa102.APA102(machine.Pin(5), machine.Pin(4), 60) brightness = 1 # 0 is off, 1 is dim, 31 is max # Helper for converting 0-255 offset to a colour tuple def wheel(offset, brightness): # The colours are a transition r - g - b - back to r offset = 255 - offset if offset < 85: return (255 - offset * 3, 0, offset * 3, brightness) if offset < 170: offset -= 85 return (0, offset * 3, 255 - offset * 3, brightness) offset -= 170 return (offset * 3, 255 - offset * 3, 0, brightness) # Demo 1: RGB RGB RGB red = 0xff0000 green = red >> 8 blue = red >> 16 for i in range(strip.n): colour = red >> (i % 3) * 8 strip[i] = ((colour & red) >> 16, (colour & green) >> 8, (colour & blue), brightness) strip.write() # Demo 2: Show all colours of the rainbow for i in range(strip.n): strip[i] = wheel((i * 256 // strip.n) % 255, brightness) strip.write() # Demo 3: Fade all pixels together through rainbow colours, offset each pixel for r in range(5): for n in range(256): for i in range(strip.n): strip[i] = wheel(((i * 256 // strip.n) + n) & 255, brightness) strip.write() time.sleep_ms(25) # Demo 4: Same colour, different brightness levels for b in range(31,-1,-1): strip[0] = (255, 153, 0, b) strip.write() time.sleep_ms(250) # End: Turn off all the LEDs strip.fill((0, 0, 0, 0)) strip.write() micropython-1.12/docs/esp8266/tutorial/dht.rst000066400000000000000000000045261357706137100212520ustar00rootroot00000000000000Temperature and Humidity ======================== DHT (Digital Humidity & Temperature) sensors are low cost digital sensors with capacitive humidity sensors and thermistors to measure the surrounding air. They feature a chip that handles analog to digital conversion and provide a 1-wire interface. Newer sensors additionally provide an I2C interface. The DHT11 (blue) and DHT22 (white) sensors provide the same 1-wire interface, however, the DHT22 requires a separate object as it has more complex calculation. DHT22 have 1 decimal place resolution for both humidity and temperature readings. DHT11 have whole number for both. A custom 1-wire protocol, which is different to Dallas 1-wire, is used to get the measurements from the sensor. The payload consists of a humidity value, a temperature value and a checksum. To use the 1-wire interface, construct the objects referring to their data pin:: >>> import dht >>> import machine >>> d = dht.DHT11(machine.Pin(4)) >>> import dht >>> import machine >>> d = dht.DHT22(machine.Pin(4)) Then measure and read their values with:: >>> d.measure() >>> d.temperature() >>> d.humidity() Values returned from ``temperature()`` are in degrees Celsius and values returned from ``humidity()`` are a percentage of relative humidity. The DHT11 can be called no more than once per second and the DHT22 once every two seconds for most accurate results. Sensor accuracy will degrade over time. Each sensor supports a different operating range. Refer to the product datasheets for specifics. In 1-wire mode, only three of the four pins are used and in I2C mode, all four pins are used. Older sensors may still have 4 pins even though they do not support I2C. The 3rd pin is simply not connected. Pin configurations: Sensor without I2C in 1-wire mode (eg. DHT11, DHT22, AM2301, AM2302): 1=VDD, 2=Data, 3=NC, 4=GND Sensor with I2C in 1-wire mode (eg. DHT12, AM2320, AM2321, AM2322): 1=VDD, 2=Data, 3=GND, 4=GND Sensor with I2C in I2C mode (eg. DHT12, AM2320, AM2321, AM2322): 1=VDD, 2=SDA, 3=GND, 4=SCL You should use pull-up resistors for the Data, SDA and SCL pins. To make newer I2C sensors work in backwards compatible 1-wire mode, you must connect both pins 3 and 4 to GND. This disables the I2C interface. DHT22 sensors are now sold under the name AM2302 and are otherwise identical. micropython-1.12/docs/esp8266/tutorial/filesystem.rst000066400000000000000000000037621357706137100226600ustar00rootroot00000000000000The internal filesystem ======================= If your devices has 1Mbyte or more of storage then it will be set up (upon first boot) to contain a filesystem. This filesystem uses the FAT format and is stored in the flash after the MicroPython firmware. Creating and reading files -------------------------- MicroPython on the ESP8266 supports the standard way of accessing files in Python, using the built-in ``open()`` function. To create a file try:: >>> f = open('data.txt', 'w') >>> f.write('some data') 9 >>> f.close() The "9" is the number of bytes that were written with the ``write()`` method. Then you can read back the contents of this new file using:: >>> f = open('data.txt') >>> f.read() 'some data' >>> f.close() Note that the default mode when opening a file is to open it in read-only mode, and as a text file. Specify ``'wb'`` as the second argument to ``open()`` to open for writing in binary mode, and ``'rb'`` to open for reading in binary mode. Listing file and more --------------------- The os module can be used for further control over the filesystem. First import the module:: >>> import os Then try listing the contents of the filesystem:: >>> os.listdir() ['boot.py', 'port_config.py', 'data.txt'] You can make directories:: >>> os.mkdir('dir') And remove entries:: >>> os.remove('data.txt') Start up scripts ---------------- There are two files that are treated specially by the ESP8266 when it starts up: boot.py and main.py. The boot.py script is executed first (if it exists) and then once it completes the main.py script is executed. You can create these files yourself and populate them with the code that you want to run when the device starts up. Accessing the filesystem via WebREPL ------------------------------------ You can access the filesystem over WebREPL using the web client in a browser or via the command-line tool. Please refer to Quick Reference and Tutorial sections for more information about WebREPL. micropython-1.12/docs/esp8266/tutorial/index.rst000066400000000000000000000017261357706137100216010ustar00rootroot00000000000000.. _esp8266_tutorial: MicroPython tutorial for ESP8266 ================================ This tutorial is intended to get you started using MicroPython on the ESP8266 system-on-a-chip. If it is your first time it is recommended to follow the tutorial through in the order below. Otherwise the sections are mostly self contained, so feel free to skip to those that interest you. The tutorial does not assume that you know Python, but it also does not attempt to explain any of the details of the Python language. Instead it provides you with commands that are ready to run, and hopes that you will gain a bit of Python knowledge along the way. To learn more about Python itself please refer to ``__. .. toctree:: :maxdepth: 1 :numbered: intro.rst repl.rst filesystem.rst network_basics.rst network_tcp.rst pins.rst pwm.rst adc.rst powerctrl.rst onewire.rst neopixel.rst apa102.rst dht.rst nextsteps.rst micropython-1.12/docs/esp8266/tutorial/intro.rst000066400000000000000000000223271357706137100216250ustar00rootroot00000000000000.. _intro: Getting started with MicroPython on the ESP8266 =============================================== Using MicroPython is a great way to get the most of your ESP8266 board. And vice versa, the ESP8266 chip is a great platform for using MicroPython. This tutorial will guide you through setting up MicroPython, getting a prompt, using WebREPL, connecting to the network and communicating with the Internet, using the hardware peripherals, and controlling some external components. Let's get started! Requirements ------------ The first thing you need is a board with an ESP8266 chip. The MicroPython software supports the ESP8266 chip itself and any board should work. The main characteristic of a board is how much flash it has, how the GPIO pins are connected to the outside world, and whether it includes a built-in USB-serial convertor to make the UART available to your PC. The minimum requirement for flash size is 1Mbyte. There is also a special build for boards with 512KB, but it is highly limited comparing to the normal build: there is no support for filesystem, and thus features which depend on it won't work (WebREPL, upip, etc.). As such, 512KB build will be more interesting for users who build from source and fine-tune parameters for their particular application. Names of pins will be given in this tutorial using the chip names (eg GPIO0) and it should be straightforward to find which pin this corresponds to on your particular board. Powering the board ------------------ If your board has a USB connector on it then most likely it is powered through this when connected to your PC. Otherwise you will need to power it directly. Please refer to the documentation for your board for further details. Getting the firmware -------------------- The first thing you need to do is download the most recent MicroPython firmware .bin file to load onto your ESP8266 device. You can download it from the `MicroPython downloads page `_. From here, you have 3 main choices * Stable firmware builds for 1024kb modules and above. * Daily firmware builds for 1024kb modules and above. * Daily firmware builds for 512kb modules. If you are just starting with MicroPython, the best bet is to go for the Stable firmware builds. If you are an advanced, experienced MicroPython ESP8266 user who would like to follow development closely and help with testing new features, there are daily builds (note: you actually may need some development experience, e.g. being ready to follow git history to know what new changes and features were introduced). Support for 512kb modules is provided on a feature preview basis. For end users, it's recommended to use modules with flash of 1024kb or more. As such, only daily builds for 512kb modules are provided. Deploying the firmware ---------------------- Once you have the MicroPython firmware (compiled code), you need to load it onto your ESP8266 device. There are two main steps to do this: first you need to put your device in boot-loader mode, and second you need to copy across the firmware. The exact procedure for these steps is highly dependent on the particular board and you will need to refer to its documentation for details. If you have a board that has a USB connector, a USB-serial convertor, and has the DTR and RTS pins wired in a special way then deploying the firmware should be easy as all steps can be done automatically. Boards that have such features include the Adafruit Feather HUZZAH and NodeMCU boards. For best results it is recommended to first erase the entire flash of your device before putting on new MicroPython firmware. Currently we only support esptool.py to copy across the firmware. You can find this tool here: ``__, or install it using pip:: pip install esptool Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer). An older version (at least 1.2.1 is needed) works fine but will require Python 2.7. Any other flashing program should work, so feel free to try them out or refer to the documentation for your board to see its recommendations. Using esptool.py you can erase the flash with the command:: esptool.py --port /dev/ttyUSB0 erase_flash And then deploy the new firmware using:: esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20170108-v1.8.7.bin You might need to change the "port" setting to something else relevant for your PC. You may also need to reduce the baudrate if you get errors when flashing (eg down to 115200). The filename of the firmware should also match the file that you have. For some boards with a particular FlashROM configuration (e.g. some variants of a NodeMCU board) you may need to use the following command to deploy the firmware (note the ``-fm dio`` option):: esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-20170108-v1.8.7.bin If the above commands run without error then MicroPython should be installed on your board! Serial prompt ------------- Once you have the firmware on the device you can access the REPL (Python prompt) over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial convertor, depending on your board. The baudrate is 115200. The next part of the tutorial will discuss the prompt in more detail. WiFi ---- After a fresh install and boot the device configures itself as a WiFi access point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx where the x's are replaced with part of the MAC address of your device (so will be the same everytime, and most likely different for all ESP8266 chips). The password for the WiFi is micropythoN (note the upper-case N). Its IP address will be 192.168.4.1 once you connect to its network. WiFi configuration will be discussed in more detail later in the tutorial. Troubleshooting installation problems ------------------------------------- If you experience problems during flashing or with running firmware immediately after it, here are troubleshooting recommendations: * Be aware of and try to exclude hardware problems. There are 2 common problems: bad power source quality and worn-out/defective FlashROM. Speaking of power source, not just raw amperage is important, but also low ripple and noise/EMI in general. If you experience issues with self-made or wall-wart style power supply, try USB power from a computer. Unearthed power supplies are also known to cause problems as they source of increased EMI (electromagnetic interference) - at the very least, and may lead to electrical devices breakdown. So, you are advised to avoid using unearthed power connections when working with ESP8266 and other boards. In regard to FlashROM hardware problems, there are independent (not related to MicroPython in any way) reports `(e.g.) `_ that on some ESP8266 modules, FlashROM can be programmed as little as 20 times before programming errors occur. This is *much* less than 100,000 programming cycles cited for FlashROM chips of a type used with ESP8266 by reputable vendors, which points to either production rejects, or second-hand worn-out flash chips to be used on some (apparently cheap) modules/boards. You may want to use your best judgement about source, price, documentation, warranty, post-sales support for the modules/boards you purchase. * The flashing instructions above use flashing speed of 460800 baud, which is good compromise between speed and stability. However, depending on your module/board, USB-UART convertor, cables, host OS, etc., the above baud rate may be too high and lead to errors. Try a more common 115200 baud rate instead in such cases. * If lower baud rate didn't help, you may want to try older version of esptool.py, which had a different programming algorithm:: pip install esptool==1.0.1 This version doesn't support ``--flash_size=detect`` option, so you will need to specify FlashROM size explicitly (in megabits). It also requires Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in the command above. * The ``--flash_size`` option in the commands above is mandatory. Omitting it will lead to a corrupted firmware. * To catch incorrect flash content (e.g. from a defective sector on a chip), add ``--verify`` switch to the commands above. * Additionally, you can check the firmware integrity from a MicroPython REPL prompt (assuming you were able to flash it and ``--verify`` option doesn't report errors):: import esp esp.check_fw() If the last output value is True, the firmware is OK. Otherwise, it's corrupted and need to be reflashed correctly. * If you experience any issues with another flashing application (not esptool.py), try esptool.py, it is a generally accepted flashing application in the ESP8266 community. * If you still experience problems with even flashing the firmware, please refer to esptool.py project page, https://github.com/espressif/esptool for additional documentation and bug tracker where you can report problems. * If you are able to flash firmware, but ``--verify`` option or ``esp.check_fw()`` return errors even after multiple retries, you may have a defective FlashROM chip, as explained above. micropython-1.12/docs/esp8266/tutorial/neopixel.rst000066400000000000000000000050041357706137100223060ustar00rootroot00000000000000Controlling NeoPixels ===================== NeoPixels, also known as WS2812 LEDs, are full-colour LEDs that are connected in serial, are individually addressable, and can have their red, green and blue components set between 0 and 255. They require precise timing to control them and there is a special neopixel module to do just this. To create a NeoPixel object do the following:: >>> import machine, neopixel >>> np = neopixel.NeoPixel(machine.Pin(4), 8) This configures a NeoPixel strip on GPIO4 with 8 pixels. You can adjust the "4" (pin number) and the "8" (number of pixel) to suit your set up. To set the colour of pixels use:: >>> np[0] = (255, 0, 0) # set to red, full brightness >>> np[1] = (0, 128, 0) # set to green, half brightness >>> np[2] = (0, 0, 64) # set to blue, quarter brightness For LEDs with more than 3 colours, such as RGBW pixels or RGBY pixels, the NeoPixel class takes a ``bpp`` parameter. To setup a NeoPixel object for an RGBW Pixel, do the following:: >>> import machine, neopixel >>> np = neopixel.NeoPixel(machine.Pin(4), 8, bpp=4) In a 4-bpp mode, remember to use 4-tuples instead of 3-tuples to set the colour. For example to set the first three pixels use:: >>> np[0] = (255, 0, 0, 128) # Orange in an RGBY Setup >>> np[1] = (0, 255, 0, 128) # Yellow-green in an RGBY Setup >>> np[2] = (0, 0, 255, 128) # Green-blue in an RGBY Setup Then use the ``write()`` method to output the colours to the LEDs:: >>> np.write() The following demo function makes a fancy show on the LEDs:: import time def demo(np): n = np.n # cycle for i in range(4 * n): for j in range(n): np[j] = (0, 0, 0) np[i % n] = (255, 255, 255) np.write() time.sleep_ms(25) # bounce for i in range(4 * n): for j in range(n): np[j] = (0, 0, 128) if (i // n) % 2 == 0: np[i % n] = (0, 0, 0) else: np[n - 1 - (i % n)] = (0, 0, 0) np.write() time.sleep_ms(60) # fade in/out for i in range(0, 4 * 256, 8): for j in range(n): if (i // 256) % 2 == 0: val = i & 0xff else: val = 255 - (i & 0xff) np[j] = (val, 0, 0) np.write() # clear for i in range(n): np[i] = (0, 0, 0) np.write() Execute it using:: >>> demo(np) micropython-1.12/docs/esp8266/tutorial/network_basics.rst000066400000000000000000000050771357706137100235120ustar00rootroot00000000000000Network basics ============== The network module is used to configure the WiFi connection. There are two WiFi interfaces, one for the station (when the ESP8266 connects to a router) and one for the access point (for other devices to connect to the ESP8266). Create instances of these objects using:: >>> import network >>> sta_if = network.WLAN(network.STA_IF) >>> ap_if = network.WLAN(network.AP_IF) You can check if the interfaces are active by:: >>> sta_if.active() False >>> ap_if.active() True You can also check the network settings of the interface by:: >>> ap_if.ifconfig() ('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8') The returned values are: IP address, netmask, gateway, DNS. Configuration of the WiFi ------------------------- Upon a fresh install the ESP8266 is configured in access point mode, so the AP_IF interface is active and the STA_IF interface is inactive. You can configure the module to connect to your own network using the STA_IF interface. First activate the station interface:: >>> sta_if.active(True) Then connect to your WiFi network:: >>> sta_if.connect('', '') To check if the connection is established use:: >>> sta_if.isconnected() Once established you can check the IP address:: >>> sta_if.ifconfig() ('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8') You can then disable the access-point interface if you no longer need it:: >>> ap_if.active(False) Here is a function you can run (or put in your boot.py file) to automatically connect to your WiFi network:: def do_connect(): import network sta_if = network.WLAN(network.STA_IF) if not sta_if.isconnected(): print('connecting to network...') sta_if.active(True) sta_if.connect('', '') while not sta_if.isconnected(): pass print('network config:', sta_if.ifconfig()) Sockets ------- Once the WiFi is set up the way to access the network is by using sockets. A socket represents an endpoint on a network device, and when two sockets are connected together communication can proceed. Internet protocols are built on top of sockets, such as email (SMTP), the web (HTTP), telnet, ssh, among many others. Each of these protocols is assigned a specific port, which is just an integer. Given an IP address and a port number you can connect to a remote device and start talking with it. The next part of the tutorial discusses how to use sockets to do some common and useful network tasks. micropython-1.12/docs/esp8266/tutorial/network_tcp.rst000066400000000000000000000073761357706137100230400ustar00rootroot00000000000000Network - TCP sockets ===================== The building block of most of the internet is the TCP socket. These sockets provide a reliable stream of bytes between the connected network devices. This part of the tutorial will show how to use TCP sockets in a few different cases. Star Wars Asciimation --------------------- The simplest thing to do is to download data from the internet. In this case we will use the Star Wars Asciimation service provided by the blinkenlights.nl website. It uses the telnet protocol on port 23 to stream data to anyone that connects. It's very simple to use because it doesn't require you to authenticate (give a username or password), you can just start downloading data straight away. The first thing to do is make sure we have the socket module available:: >>> import socket Then get the IP address of the server:: >>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23) The ``getaddrinfo`` function actually returns a list of addresses, and each address has more information than we need. We want to get just the first valid address, and then just the IP address and port of the server. To do this use:: >>> addr = addr_info[0][-1] If you type ``addr_info`` and ``addr`` at the prompt you will see exactly what information they hold. Using the IP address we can make a socket and connect to the server:: >>> s = socket.socket() >>> s.connect(addr) Now that we are connected we can download and display the data:: >>> while True: ... data = s.recv(500) ... print(str(data, 'utf8'), end='') ... When this loop executes it should start showing the animation (use ctrl-C to interrupt it). You should also be able to run this same code on your PC using normal Python if you want to try it out there. HTTP GET request ---------------- The next example shows how to download a webpage. HTTP uses port 80 and you first need to send a "GET" request before you can download anything. As part of the request you need to specify the page to retrieve. Let's define a function that can download and print a URL:: def http_get(url): import socket _, _, host, path = url.split('/', 3) addr = socket.getaddrinfo(host, 80)[0][-1] s = socket.socket() s.connect(addr) s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8')) while True: data = s.recv(100) if data: print(str(data, 'utf8'), end='') else: break s.close() Then you can try:: >>> http_get('http://micropython.org/ks/test.html') This should retrieve the webpage and print the HTML to the console. Simple HTTP server ------------------ The following code creates an simple HTTP server which serves a single webpage that contains a table with the state of all the GPIO pins:: import machine pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)] html = """ ESP8266 Pins

ESP8266 Pins

%s
PinValue
""" import socket addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] s = socket.socket() s.bind(addr) s.listen(1) print('listening on', addr) while True: cl, addr = s.accept() print('client connected from', addr) cl_file = cl.makefile('rwb', 0) while True: line = cl_file.readline() if not line or line == b'\r\n': break rows = ['%s%d' % (str(p), p.value()) for p in pins] response = html % '\n'.join(rows) cl.send(response) cl.close() micropython-1.12/docs/esp8266/tutorial/nextsteps.rst000066400000000000000000000007011357706137100225170ustar00rootroot00000000000000Next steps ========== That brings us to the end of the tutorial! Hopefully by now you have a good feel for the capabilities of MicroPython on the ESP8266 and understand how to control both the WiFi and IO aspects of the chip. There are many features that were not covered in this tutorial. The best way to learn about them is to read the full documentation of the modules, and to experiment! Good luck creating your Internet of Things devices! micropython-1.12/docs/esp8266/tutorial/onewire.rst000066400000000000000000000023501357706137100221340ustar00rootroot00000000000000Controlling 1-wire devices ========================== The 1-wire bus is a serial bus that uses just a single wire for communication (in addition to wires for ground and power). The DS18B20 temperature sensor is a very popular 1-wire device, and here we show how to use the onewire module to read from such a device. For the following code to work you need to have at least one DS18S20 or DS18B20 temperature sensor with its data line connected to GPIO12. You must also power the sensors and connect a 4.7k Ohm resistor between the data pin and the power pin. :: import time import machine import onewire, ds18x20 # the device is on GPIO12 dat = machine.Pin(12) # create the onewire object ds = ds18x20.DS18X20(onewire.OneWire(dat)) # scan for devices on the bus roms = ds.scan() print('found devices:', roms) # loop 10 times and print all temperatures for i in range(10): print('temperatures:', end=' ') ds.convert_temp() time.sleep_ms(750) for rom in roms: print(ds.read_temp(rom), end=' ') print() Note that you must execute the ``convert_temp()`` function to initiate a temperature reading, then wait at least 750ms before reading the value. micropython-1.12/docs/esp8266/tutorial/pins.rst000066400000000000000000000047161357706137100214450ustar00rootroot00000000000000GPIO Pins ========= The way to connect your board to the external world, and control other components, is through the GPIO pins. Not all pins are available to use, in most cases only pins 0, 2, 4, 5, 12, 13, 14, 15, and 16 can be used. The pins are available in the machine module, so make sure you import that first. Then you can create a pin using:: >>> pin = machine.Pin(0) Here, the "0" is the pin that you want to access. Usually you want to configure the pin to be input or output, and you do this when constructing it. To make an input pin use:: >>> pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP) You can either use PULL_UP or None for the input pull-mode. If it's not specified then it defaults to None, which is no pull resistor. GPIO16 has no pull-up mode. You can read the value on the pin using:: >>> pin.value() 0 The pin on your board may return 0 or 1 here, depending on what it's connected to. To make an output pin use:: >>> pin = machine.Pin(0, machine.Pin.OUT) Then set its value using:: >>> pin.value(0) >>> pin.value(1) Or:: >>> pin.off() >>> pin.on() External interrupts ------------------- All pins except number 16 can be configured to trigger a hard interrupt if their input changes. You can set code (a callback function) to be executed on the trigger. Let's first define a callback function, which must take a single argument, being the pin that triggered the function. We will make the function just print the pin:: >>> def callback(p): ... print('pin change', p) Next we will create two pins and configure them as inputs:: >>> from machine import Pin >>> p0 = Pin(0, Pin.IN) >>> p2 = Pin(2, Pin.IN) An finally we need to tell the pins when to trigger, and the function to call when they detect an event:: >>> p0.irq(trigger=Pin.IRQ_FALLING, handler=callback) >>> p2.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=callback) We set pin 0 to trigger only on a falling edge of the input (when it goes from high to low), and set pin 2 to trigger on both a rising and falling edge. After entering this code you can apply high and low voltages to pins 0 and 2 to see the interrupt being executed. A hard interrupt will trigger as soon as the event occurs and will interrupt any running code, including Python code. As such your callback functions are limited in what they can do (they cannot allocate memory, for example) and should be as short and simple as possible. micropython-1.12/docs/esp8266/tutorial/powerctrl.rst000066400000000000000000000037601357706137100225130ustar00rootroot00000000000000Power control ============= The ESP8266 provides the ability to change the CPU frequency on the fly, and enter a deep-sleep state. Both can be used to manage power consumption. Changing the CPU frequency -------------------------- The machine module has a function to get and set the CPU frequency. To get the current frequency use:: >>> import machine >>> machine.freq() 80000000 By default the CPU runs at 80MHz. It can be changed to 160MHz if you need more processing power, at the expense of current consumption:: >>> machine.freq(160000000) >>> machine.freq() 160000000 You can change to the higher frequency just while your code does the heavy processing and then change back when it's finished. Deep-sleep mode --------------- The deep-sleep mode will shut down the ESP8266 and all its peripherals, including the WiFi (but not including the real-time-clock, which is used to wake the chip). This drastically reduces current consumption and is a good way to make devices that can run for a while on a battery. To be able to use the deep-sleep feature you must connect GPIO16 to the reset pin (RST on the Adafruit Feather HUZZAH board). Then the following code can be used to sleep and wake the device:: import machine # configure RTC.ALARM0 to be able to wake the device rtc = machine.RTC() rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) # set RTC.ALARM0 to fire after 10 seconds (waking the device) rtc.alarm(rtc.ALARM0, 10000) # put the device to sleep machine.deepsleep() Note that when the chip wakes from a deep-sleep it is completely reset, including all of the memory. The boot scripts will run as usual and you can put code in them to check the reset cause to perhaps do something different if the device just woke from a deep-sleep. For example, to print the reset cause you can use:: if machine.reset_cause() == machine.DEEPSLEEP_RESET: print('woke from a deep sleep') else: print('power on or hard reset') micropython-1.12/docs/esp8266/tutorial/pwm.rst000066400000000000000000000053561357706137100213000ustar00rootroot00000000000000Pulse Width Modulation ====================== Pulse width modulation (PWM) is a way to get an artificial analog output on a digital pin. It achieves this by rapidly toggling the pin from low to high. There are two parameters associated with this: the frequency of the toggling, and the duty cycle. The duty cycle is defined to be how long the pin is high compared with the length of a single period (low plus high time). Maximum duty cycle is when the pin is high all of the time, and minimum is when it is low all of the time. On the ESP8266 the pins 0, 2, 4, 5, 12, 13, 14 and 15 all support PWM. The limitation is that they must all be at the same frequency, and the frequency must be between 1Hz and 1kHz. To use PWM on a pin you must first create the pin object, for example:: >>> import machine >>> p12 = machine.Pin(12) Then create the PWM object using:: >>> pwm12 = machine.PWM(p12) You can set the frequency and duty cycle using:: >>> pwm12.freq(500) >>> pwm12.duty(512) Note that the duty cycle is between 0 (all off) and 1023 (all on), with 512 being a 50% duty. Values beyond this min/max will be clipped. If you print the PWM object then it will tell you its current configuration:: >>> pwm12 PWM(12, freq=500, duty=512) You can also call the ``freq()`` and ``duty()`` methods with no arguments to get their current values. The pin will continue to be in PWM mode until you deinitialise it using:: >>> pwm12.deinit() Fading an LED ------------- Let's use the PWM feature to fade an LED. Assuming your board has an LED connected to pin 2 (ESP-12 modules do) we can create an LED-PWM object using:: >>> led = machine.PWM(machine.Pin(2), freq=1000) Notice that we can set the frequency in the PWM constructor. For the next part we will use timing and some math, so import these modules:: >>> import time, math Then create a function to pulse the LED:: >>> def pulse(l, t): ... for i in range(20): ... l.duty(int(math.sin(i / 10 * math.pi) * 500 + 500)) ... time.sleep_ms(t) You can try this function out using:: >>> pulse(led, 50) For a nice effect you can pulse many times in a row:: >>> for i in range(10): ... pulse(led, 20) Remember you can use ctrl-C to interrupt the code. Control a hobby servo --------------------- Hobby servo motors can be controlled using PWM. They require a frequency of 50Hz and then a duty between about 40 and 115, with 77 being the centre value. If you connect a servo to the power and ground pins, and then the signal line to pin 12 (other pins will work just as well), you can control the motor using:: >>> servo = machine.PWM(machine.Pin(12), freq=50) >>> servo.duty(40) >>> servo.duty(115) >>> servo.duty(77) micropython-1.12/docs/esp8266/tutorial/repl.rst000066400000000000000000000175511357706137100214370ustar00rootroot00000000000000Getting a MicroPython REPL prompt ================================= REPL stands for Read Evaluate Print Loop, and is the name given to the interactive MicroPython prompt that you can access on the ESP8266. Using the REPL is by far the easiest way to test out your code and run commands. There are two ways to access the REPL: either via a wired connection through the UART serial port, or via WiFi. REPL over the serial port ------------------------- The REPL is always available on the UART0 serial peripheral, which is connected to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200. If your board has a USB-serial convertor on it then you should be able to access the REPL directly from your PC. Otherwise you will need to have a way of communicating with the UART. To access the prompt over USB-serial you need to use a terminal emulator program. On Windows TeraTerm is a good choice, on Mac you can use the built-in screen program, and Linux has picocom and minicom. Of course, there are many other terminal programs that will work, so pick your favourite! For example, on Linux you can try running:: picocom /dev/ttyUSB0 -b115200 Once you have made the connection over the serial port you can test if it is working by hitting enter a few times. You should see the Python REPL prompt, indicated by ``>>>``. WebREPL - a prompt over WiFi ---------------------------- WebREPL allows you to use the Python prompt over WiFi, connecting through a browser. The latest versions of Firefox and Chrome are supported. For your convenience, WebREPL client is hosted at ``__ . Alternatively, you can install it locally from the the GitHub repository ``__ . Before connecting to WebREPL, you should set a password and enable it via a normal serial connection. Initial versions of MicroPython for ESP8266 came with WebREPL automatically enabled on the boot and with the ability to set a password via WiFi on the first connection, but as WebREPL was becoming more widely known and popular, the initial setup has switched to a wired connection for improved security:: import webrepl_setup Follow the on-screen instructions and prompts. To make any changes active, you will need to reboot your device. To use WebREPL connect your computer to the ESP8266's access point (MicroPython-xxxxxx, see the previous section about this). If you have already reconfigured your ESP8266 to connect to a router then you can skip this part. Once you are on the same network as the ESP8266 you click the "Connect" button (if you are connecting via a router then you may need to change the IP address, by default the IP address is correct when connected to the ESP8266's access point). If the connection succeeds then you should see a password prompt. Once you type the password configured at the setup step above, press Enter once more and you should get a prompt looking like ``>>>``. You can now start typing Python commands! Using the REPL -------------- Once you have a prompt you can start experimenting! Anything you type at the prompt will be executed after you press the Enter key. MicroPython will run the code that you enter and print the result (if there is one). If there is an error with the text that you enter then an error message is printed. Try typing the following at the prompt:: >>> print('hello esp8266!') hello esp8266! Note that you shouldn't type the ``>>>`` arrows, they are there to indicate that you should type the text after it at the prompt. And then the line following is what the device should respond with. In the end, once you have entered the text ``print("hello esp8266!")`` and pressed the Enter key, the output on your screen should look exactly like it does above. If you already know some python you can now try some basic commands here. For example:: >>> 1 + 2 3 >>> 1 / 2 0.5 >>> 12**34 4922235242952026704037113243122008064 If your board has an LED attached to GPIO2 (the ESP-12 modules do) then you can turn it on and off using the following code:: >>> import machine >>> pin = machine.Pin(2, machine.Pin.OUT) >>> pin.on() >>> pin.off() Note that ``on`` method of a Pin might turn the LED off and ``off`` might turn it on (or vice versa), depending on how the LED is wired on your board. To resolve this, machine.Signal class is provided. Line editing ~~~~~~~~~~~~ You can edit the current line that you are entering using the left and right arrow keys to move the cursor, as well as the delete and backspace keys. Also, pressing Home or ctrl-A moves the cursor to the start of the line, and pressing End or ctrl-E moves to the end of the line. Input history ~~~~~~~~~~~~~ The REPL remembers a certain number of previous lines of text that you entered (up to 8 on the ESP8266). To recall previous lines use the up and down arrow keys. Tab completion ~~~~~~~~~~~~~~ Pressing the Tab key will do an auto-completion of the current word that you are entering. This can be very useful to find out functions and methods that a module or object has. Try it out by typing "ma" and then pressing Tab. It should complete to "machine" (assuming you imported machine in the above example). Then type "." and press Tab again to see a list of all the functions that the machine module has. Line continuation and auto-indent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Certain things that you type will need "continuing", that is, will need more lines of text to make a proper Python statement. In this case the prompt will change to ``...`` and the cursor will auto-indent the correct amount so you can start typing the next line straight away. Try this by defining the following function:: >>> def toggle(p): ... p.value(not p.value()) ... ... ... >>> In the above, you needed to press the Enter key three times in a row to finish the compound statement (that's the three lines with just dots on them). The other way to finish a compound statement is to press backspace to get to the start of the line, then press the Enter key. (If you did something wrong and want to escape the continuation mode then press ctrl-C; all lines will be ignored.) The function you just defined allows you to toggle a pin. The pin object you created earlier should still exist (recreate it if it doesn't) and you can toggle the LED using:: >>> toggle(pin) Let's now toggle the LED in a loop (if you don't have an LED then you can just print some text instead of calling toggle, to see the effect):: >>> import time >>> while True: ... toggle(pin) ... time.sleep_ms(500) ... ... ... >>> This will toggle the LED at 1Hz (half a second on, half a second off). To stop the toggling press ctrl-C, which will raise a KeyboardInterrupt exception and break out of the loop. The time module provides some useful functions for making delays and doing timing. Use tab completion to find out what they are and play around with them! Paste mode ~~~~~~~~~~ Pressing ctrl-E will enter a special paste mode. This allows you to copy and paste a chunk of text into the REPL. If you press ctrl-E you will see the paste-mode prompt:: paste mode; Ctrl-C to cancel, Ctrl-D to finish === You can then paste (or type) your text in. Note that none of the special keys or commands work in paste mode (eg Tab or backspace), they are just accepted as-is. Press ctrl-D to finish entering the text and execute it. Other control commands ~~~~~~~~~~~~~~~~~~~~~~ There are four other control commands: * Ctrl-A on a blank line will enter raw REPL mode. This is like a permanent paste mode, except that characters are not echoed back. * Ctrl-B on a blank like goes to normal REPL mode. * Ctrl-C cancels any input, or interrupts the currently running code. * Ctrl-D on a blank line will do a soft reset. Note that ctrl-A and ctrl-D do not work with WebREPL. micropython-1.12/docs/index.rst000066400000000000000000000004511357706137100166130ustar00rootroot00000000000000MicroPython documentation and references ======================================== .. toctree:: library/index.rst reference/index.rst genrst/index.rst develop/index.rst license.rst pyboard/quickref.rst esp8266/quickref.rst esp32/quickref.rst wipy/quickref.rst micropython-1.12/docs/library/000077500000000000000000000000001357706137100164165ustar00rootroot00000000000000micropython-1.12/docs/library/_thread.rst000066400000000000000000000005371357706137100205630ustar00rootroot00000000000000:mod:`_thread` -- multithreading support ======================================== .. module:: _thread :synopsis: multithreading support |see_cpython_module| :mod:`python:_thread`. This module implements multithreading support. This module is highly experimental and its API is not yet fully settled and not yet described in this documentation. micropython-1.12/docs/library/btree.rst000066400000000000000000000131311357706137100202500ustar00rootroot00000000000000:mod:`btree` -- simple BTree database ===================================== .. module:: btree :synopsis: simple BTree database The ``btree`` module implements a simple key-value database using external storage (disk files, or in general case, a random-access `stream`). Keys are stored sorted in the database, and besides efficient retrieval by a key value, a database also supports efficient ordered range scans (retrieval of values with the keys in a given range). On the application interface side, BTree database work as close a possible to a way standard `dict` type works, one notable difference is that both keys and values must be `bytes` objects (so, if you want to store objects of other types, you need to serialize them to `bytes` first). The module is based on the well-known BerkelyDB library, version 1.xx. Example:: import btree # First, we need to open a stream which holds a database # This is usually a file, but can be in-memory database # using uio.BytesIO, a raw flash partition, etc. # Oftentimes, you want to create a database file if it doesn't # exist and open if it exists. Idiom below takes care of this. # DO NOT open database with "a+b" access mode. try: f = open("mydb", "r+b") except OSError: f = open("mydb", "w+b") # Now open a database itself db = btree.open(f) # The keys you add will be sorted internally in the database db[b"3"] = b"three" db[b"1"] = b"one" db[b"2"] = b"two" # Assume that any changes are cached in memory unless # explicitly flushed (or database closed). Flush database # at the end of each "transaction". db.flush() # Prints b'two' print(db[b"2"]) # Iterate over sorted keys in the database, starting from b"2" # until the end of the database, returning only values. # Mind that arguments passed to values() method are *key* values. # Prints: # b'two' # b'three' for word in db.values(b"2"): print(word) del db[b"2"] # No longer true, prints False print(b"2" in db) # Prints: # b"1" # b"3" for key in db: print(key) db.close() # Don't forget to close the underlying stream! f.close() Functions --------- .. function:: open(stream, \*, flags=0, pagesize=0, cachesize=0, minkeypage=0) Open a database from a random-access `stream` (like an open file). All other parameters are optional and keyword-only, and allow to tweak advanced parameters of the database operation (most users will not need them): * *flags* - Currently unused. * *pagesize* - Page size used for the nodes in BTree. Acceptable range is 512-65536. If 0, a port-specific default will be used, optimized for port's memory usage and/or performance. * *cachesize* - Suggested memory cache size in bytes. For a board with enough memory using larger values may improve performance. Cache policy is as follows: entire cache is not allocated at once; instead, accessing a new page in database will allocate a memory buffer for it, until value specified by *cachesize* is reached. Then, these buffers will be managed using LRU (least recently used) policy. More buffers may still be allocated if needed (e.g., if a database contains big keys and/or values). Allocated cache buffers aren't reclaimed. * *minkeypage* - Minimum number of keys to store per page. Default value of 0 equivalent to 2. Returns a BTree object, which implements a dictionary protocol (set of methods), and some additional methods described below. Methods ------- .. method:: btree.close() Close the database. It's mandatory to close the database at the end of processing, as some unwritten data may be still in the cache. Note that this does not close underlying stream with which the database was opened, it should be closed separately (which is also mandatory to make sure that data flushed from buffer to the underlying storage). .. method:: btree.flush() Flush any data in cache to the underlying stream. .. method:: btree.__getitem__(key) btree.get(key, default=None) btree.__setitem__(key, val) btree.__detitem__(key) btree.__contains__(key) Standard dictionary methods. .. method:: btree.__iter__() A BTree object can be iterated over directly (similar to a dictionary) to get access to all keys in order. .. method:: btree.keys([start_key, [end_key, [flags]]]) btree.values([start_key, [end_key, [flags]]]) btree.items([start_key, [end_key, [flags]]]) These methods are similar to standard dictionary methods, but also can take optional parameters to iterate over a key sub-range, instead of the entire database. Note that for all 3 methods, *start_key* and *end_key* arguments represent key values. For example, `values()` method will iterate over values corresponding to they key range given. None values for *start_key* means "from the first key", no *end_key* or its value of None means "until the end of database". By default, range is inclusive of *start_key* and exclusive of *end_key*, you can include *end_key* in iteration by passing *flags* of `btree.INCL`. You can iterate in descending key direction by passing *flags* of `btree.DESC`. The flags values can be ORed together. Constants --------- .. data:: INCL A flag for `keys()`, `values()`, `items()` methods to specify that scanning should be inclusive of the end key. .. data:: DESC A flag for `keys()`, `values()`, `items()` methods to specify that scanning should be in descending direction of keys. micropython-1.12/docs/library/builtins.rst000066400000000000000000000056171357706137100210120ustar00rootroot00000000000000Builtin functions and exceptions ================================ All builtin functions and exceptions are described here. They are also available via ``builtins`` module. Functions and types ------------------- .. function:: abs() .. function:: all() .. function:: any() .. function:: bin() .. class:: bool() .. class:: bytearray() .. class:: bytes() |see_cpython| `python:bytes`. .. function:: callable() .. function:: chr() .. function:: classmethod() .. function:: compile() .. class:: complex() .. function:: delattr(obj, name) The argument *name* should be a string, and this function deletes the named attribute from the object given by *obj*. .. class:: dict() .. function:: dir() .. function:: divmod() .. function:: enumerate() .. function:: eval() .. function:: exec() .. function:: filter() .. class:: float() .. class:: frozenset() .. function:: getattr() .. function:: globals() .. function:: hasattr() .. function:: hash() .. function:: hex() .. function:: id() .. function:: input() .. class:: int() .. classmethod:: from_bytes(bytes, byteorder) In MicroPython, `byteorder` parameter must be positional (this is compatible with CPython). .. method:: to_bytes(size, byteorder) In MicroPython, `byteorder` parameter must be positional (this is compatible with CPython). .. function:: isinstance() .. function:: issubclass() .. function:: iter() .. function:: len() .. class:: list() .. function:: locals() .. function:: map() .. function:: max() .. class:: memoryview() .. function:: min() .. function:: next() .. class:: object() .. function:: oct() .. function:: open() .. function:: ord() .. function:: pow() .. function:: print() .. function:: property() .. function:: range() .. function:: repr() .. function:: reversed() .. function:: round() .. class:: set() .. function:: setattr() .. class:: slice() The *slice* builtin is the type that slice objects have. .. function:: sorted() .. function:: staticmethod() .. class:: str() .. function:: sum() .. function:: super() .. class:: tuple() .. function:: type() .. function:: zip() Exceptions ---------- .. exception:: AssertionError .. exception:: AttributeError .. exception:: Exception .. exception:: ImportError .. exception:: IndexError .. exception:: KeyboardInterrupt .. exception:: KeyError .. exception:: MemoryError .. exception:: NameError .. exception:: NotImplementedError .. exception:: OSError |see_cpython| `python:OSError`. MicroPython doesn't implement ``errno`` attribute, instead use the standard way to access exception arguments: ``exc.args[0]``. .. exception:: RuntimeError .. exception:: StopIteration .. exception:: SyntaxError .. exception:: SystemExit |see_cpython| `python:SystemExit`. .. exception:: TypeError |see_cpython| `python:TypeError`. .. exception:: ValueError .. exception:: ZeroDivisionError micropython-1.12/docs/library/cmath.rst000066400000000000000000000024421357706137100202460ustar00rootroot00000000000000:mod:`cmath` -- mathematical functions for complex numbers ========================================================== .. module:: cmath :synopsis: mathematical functions for complex numbers |see_cpython_module| :mod:`python:cmath`. The ``cmath`` module provides some basic mathematical functions for working with complex numbers. Availability: not available on WiPy and ESP8266. Floating point support required for this module. Functions --------- .. function:: cos(z) Return the cosine of ``z``. .. function:: exp(z) Return the exponential of ``z``. .. function:: log(z) Return the natural logarithm of ``z``. The branch cut is along the negative real axis. .. function:: log10(z) Return the base-10 logarithm of ``z``. The branch cut is along the negative real axis. .. function:: phase(z) Returns the phase of the number ``z``, in the range (-pi, +pi]. .. function:: polar(z) Returns, as a tuple, the polar form of ``z``. .. function:: rect(r, phi) Returns the complex number with modulus ``r`` and phase ``phi``. .. function:: sin(z) Return the sine of ``z``. .. function:: sqrt(z) Return the square-root of ``z``. Constants --------- .. data:: e base of the natural logarithm .. data:: pi the ratio of a circle's circumference to its diameter micropython-1.12/docs/library/esp.rst000066400000000000000000000074441357706137100177500ustar00rootroot00000000000000:mod:`esp` --- functions related to the ESP8266 and ESP32 ========================================================= .. module:: esp :synopsis: functions related to the ESP8266 and ESP32 The ``esp`` module contains specific functions related to both the ESP8266 and ESP32 modules. Some functions are only available on one or the other of these ports. Functions --------- .. function:: sleep_type([sleep_type]) **Note**: ESP8266 only Get or set the sleep type. If the *sleep_type* parameter is provided, sets the sleep type to its value. If the function is called without parameters, returns the current sleep type. The possible sleep types are defined as constants: * ``SLEEP_NONE`` -- all functions enabled, * ``SLEEP_MODEM`` -- modem sleep, shuts down the WiFi Modem circuit. * ``SLEEP_LIGHT`` -- light sleep, shuts down the WiFi Modem circuit and suspends the processor periodically. The system enters the set sleep mode automatically when possible. .. function:: deepsleep(time=0) **Note**: ESP8266 only - use `machine.deepsleep()` on ESP32 Enter deep sleep. The whole module powers down, except for the RTC clock circuit, which can be used to restart the module after the specified time if the pin 16 is connected to the reset pin. Otherwise the module will sleep until manually reset. .. function:: flash_id() **Note**: ESP8266 only Read the device ID of the flash memory. .. function:: flash_size() Read the total size of the flash memory. .. function:: flash_user_start() Read the memory offset at which the user flash space begins. .. function:: flash_read(byte_offset, length_or_buffer) .. function:: flash_write(byte_offset, bytes) .. function:: flash_erase(sector_no) .. function:: set_native_code_location(start, length) **Note**: ESP8266 only Set the location that native code will be placed for execution after it is compiled. Native code is emitted when the ``@micropython.native``, ``@micropython.viper`` and ``@micropython.asm_xtensa`` decorators are applied to a function. The ESP8266 must execute code from either iRAM or the lower 1MByte of flash (which is memory mapped), and this function controls the location. If *start* and *length* are both ``None`` then the native code location is set to the unused portion of memory at the end of the iRAM1 region. The size of this unused portion depends on the firmware and is typically quite small (around 500 bytes), and is enough to store a few very small functions. The advantage of using this iRAM1 region is that it does not get worn out by writing to it. If neither *start* nor *length* are ``None`` then they should be integers. *start* should specify the byte offset from the beginning of the flash at which native code should be stored. *length* specifies how many bytes of flash from *start* can be used to store native code. *start* and *length* should be multiples of the sector size (being 4096 bytes). The flash will be automatically erased before writing to it so be sure to use a region of flash that is not otherwise used, for example by the firmware or the filesystem. When using the flash to store native code *start+length* must be less than or equal to 1MByte. Note that the flash can be worn out if repeated erasures (and writes) are made so use this feature sparingly. In particular, native code needs to be recompiled and rewritten to flash on each boot (including wake from deepsleep). In both cases above, using iRAM1 or flash, if there is no more room left in the specified region then the use of a native decorator on a function will lead to `MemoryError` exception being raised during compilation of that function. micropython-1.12/docs/library/esp32.rst000066400000000000000000000147571357706137100201220ustar00rootroot00000000000000.. currentmodule:: esp32 :mod:`esp32` --- functionality specific to the ESP32 ==================================================== .. module:: esp32 :synopsis: functionality specific to the ESP32 The ``esp32`` module contains functions and classes specifically aimed at controlling ESP32 modules. Functions --------- .. function:: wake_on_touch(wake) Configure whether or not a touch will wake the device from sleep. *wake* should be a boolean value. .. function:: wake_on_ext0(pin, level) Configure how EXT0 wakes the device from sleep. *pin* can be ``None`` or a valid Pin object. *level* should be ``esp32.WAKEUP_ALL_LOW`` or ``esp32.WAKEUP_ANY_HIGH``. .. function:: wake_on_ext1(pins, level) Configure how EXT1 wakes the device from sleep. *pins* can be ``None`` or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW`` or ``esp32.WAKEUP_ANY_HIGH``. .. function:: raw_temperature() Read the raw value of the internal temperature sensor, returning an integer. .. function:: hall_sensor() Read the raw value of the internal Hall sensor, returning an integer. Flash partitions ---------------- This class gives access to the partitions in the device's flash memory. .. class:: Partition(id) Create an object representing a partition. *id* can be a string which is the label of the partition to retrieve, or one of the constants: ``BOOT`` or ``RUNNING``. .. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None) Find a partition specified by *type*, *subtype* and *label*. Returns a (possibly empty) list of Partition objects. .. method:: Partition.info() Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``. .. method:: Partition.readblocks(block_num, buf) .. method:: Partition.readblocks(block_num, buf, offset) .. method:: Partition.writeblocks(block_num, buf) .. method:: Partition.writeblocks(block_num, buf, offset) .. method:: Partition.ioctl(cmd, arg) These methods implement the simple and :ref:`extended ` block protocol defined by :class:`uos.AbstractBlockDev`. .. method:: Partition.set_boot() Sets the partition as the boot partition. .. method:: Partition.get_next_update() Gets the next update partition after this one, and returns a new Partition object. Constants ~~~~~~~~~ .. data:: Partition.BOOT Partition.RUNNING Used in the `Partition` constructor to fetch various partitions. .. data:: Partition.TYPE_APP Partition.TYPE_DATA Used in `Partition.find` to specify the partition type. .. _esp32.RMT: RMT --- The RMT (Remote Control) module, specific to the ESP32, was originally designed to send and receive infrared remote control signals. However, due to a flexible design and very accurate (as low as 12.5ns) pulse generation, it can also be used to transmit or receive many other types of digital signals:: import esp32 from machine import Pin r = esp32.RMT(0, pin=Pin(18), clock_div=8) r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8) # The channel resolution is 100ns (1/(source_freq/clock_div)). r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns The input to the RMT module is an 80MHz clock (in the future it may be able to configure the input clock but, for now, it's fixed). ``clock_div`` *divides* the clock input which determines the resolution of the RMT channel. The numbers specificed in ``write_pulses`` are multiplied by the resolution to define the pulses. ``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by multiplying the resolution by a 15-bit (0-32,768) number. There are eight channels (0-7) and each can have a different clock divider. So, in the example above, the 80MHz clock is divided by 8. Thus the resolution is (1/(80Mhz/8)) 100ns. Since the ``start`` level is 0 and toggles with each number, the bitstream is ``0101`` with durations of [100ns, 2000ns, 100ns, 4000ns]. For more details see Espressif's `ESP-IDF RMT documentation. `_. .. Warning:: The current MicroPython RMT implementation lacks some features, most notably receiving pulses and carrier transmit. RMT should be considered a *beta feature* and the interface may change in the future. .. class:: RMT(channel, \*, pin=None, clock_div=8) This class provides access to one of the eight RMT channels. *channel* is required and identifies which RMT channel (0-7) will be configured. *pin*, also required, configures which Pin is bound to the RMT channel. *clock_div* is an 8-bit clock divider that divides the source clock (80MHz) to the RMT channel allowing the resolution to be specified. .. method:: RMT.source_freq() Returns the source clock frequency. Currently the source clock is not configurable so this will always return 80MHz. .. method:: RMT.clock_div() Return the clock divider. Note that the channel resolution is ``1 / (source_freq / clock_div)``. .. method:: RMT.wait_done(timeout=0) Returns True if `RMT.write_pulses` has completed. If *timeout* (defined in ticks of ``source_freq / clock_div``) is specified the method will wait for *timeout* or until `RMT.write_pulses` is complete, returning ``False`` if the channel continues to transmit. .. Warning:: Avoid using ``wait_done()`` if looping is enabled. .. method:: RMT.loop(enable_loop) Configure looping on the channel, allowing a stream of pulses to be indefinitely repeated. *enable_loop* is bool, set to True to enable looping. .. method:: RMT.write_pulses(pulses, start) Begin sending *pulses*, a list or tuple defining the stream of pulses. The length of each pulse is defined by a number to be multiplied by the channel resolution ``(1 / (source_freq / clock_div))``. *start* defines whether the stream starts at 0 or 1. The Ultra-Low-Power co-processor -------------------------------- .. class:: ULP() This class provides access to the Ultra-Low-Power co-processor. .. method:: ULP.set_wakeup_period(period_index, period_us) Set the wake-up period. .. method:: ULP.load_binary(load_addr, program_binary) Load a *program_binary* into the ULP at the given *load_addr*. .. method:: ULP.run(entry_point) Start the ULP running at the given *entry_point*. Constants --------- .. data:: esp32.WAKEUP_ALL_LOW esp32.WAKEUP_ANY_HIGH Selects the wake level for pins. micropython-1.12/docs/library/framebuf.rst000066400000000000000000000132361357706137100207440ustar00rootroot00000000000000:mod:`framebuf` --- Frame buffer manipulation ============================================= .. module:: framebuf :synopsis: Frame buffer manipulation This module provides a general frame buffer which can be used to create bitmap images, which can then be sent to a display. class FrameBuffer ----------------- The FrameBuffer class provides a pixel buffer which can be drawn upon with pixels, lines, rectangles, text and even other FrameBuffer's. It is useful when generating output for displays. For example:: import framebuf # FrameBuffer needs 2 bytes for every RGB565 pixel fbuf = framebuf.FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565) fbuf.fill(0) fbuf.text('MicroPython!', 0, 0, 0xffff) fbuf.hline(0, 10, 96, 0xffff) Constructors ------------ .. class:: FrameBuffer(buffer, width, height, format, stride=width) Construct a FrameBuffer object. The parameters are: - *buffer* is an object with a buffer protocol which must be large enough to contain every pixel defined by the width, height and format of the FrameBuffer. - *width* is the width of the FrameBuffer in pixels - *height* is the height of the FrameBuffer in pixels - *format* specifies the type of pixel used in the FrameBuffer; permissible values are listed under Constants below. These set the number of bits used to encode a color value and the layout of these bits in *buffer*. Where a color value c is passed to a method, c is a small integer with an encoding that is dependent on the format of the FrameBuffer. - *stride* is the number of pixels between each horizontal line of pixels in the FrameBuffer. This defaults to *width* but may need adjustments when implementing a FrameBuffer within another larger FrameBuffer or screen. The *buffer* size must accommodate an increased step size. One must specify valid *buffer*, *width*, *height*, *format* and optionally *stride*. Invalid *buffer* size or dimensions may lead to unexpected errors. Drawing primitive shapes ------------------------ The following methods draw shapes onto the FrameBuffer. .. method:: FrameBuffer.fill(c) Fill the entire FrameBuffer with the specified color. .. method:: FrameBuffer.pixel(x, y[, c]) If *c* is not given, get the color value of the specified pixel. If *c* is given, set the specified pixel to the given color. .. method:: FrameBuffer.hline(x, y, w, c) .. method:: FrameBuffer.vline(x, y, h, c) .. method:: FrameBuffer.line(x1, y1, x2, y2, c) Draw a line from a set of coordinates using the given color and a thickness of 1 pixel. The `line` method draws the line up to a second set of coordinates whereas the `hline` and `vline` methods draw horizontal and vertical lines respectively up to a given length. .. method:: FrameBuffer.rect(x, y, w, h, c) .. method:: FrameBuffer.fill_rect(x, y, w, h, c) Draw a rectangle at the given location, size and color. The `rect` method draws only a 1 pixel outline whereas the `fill_rect` method draws both the outline and interior. Drawing text ------------ .. method:: FrameBuffer.text(s, x, y[, c]) Write text to the FrameBuffer using the the coordinates as the upper-left corner of the text. The color of the text can be defined by the optional argument but is otherwise a default value of 1. All characters have dimensions of 8x8 pixels and there is currently no way to change the font. Other methods ------------- .. method:: FrameBuffer.scroll(xstep, ystep) Shift the contents of the FrameBuffer by the given vector. This may leave a footprint of the previous colors in the FrameBuffer. .. method:: FrameBuffer.blit(fbuf, x, y[, key]) Draw another FrameBuffer on top of the current one at the given coordinates. If *key* is specified then it should be a color integer and the corresponding color will be considered transparent: all pixels with that color value will not be drawn. This method works between FrameBuffer instances utilising different formats, but the resulting colors may be unexpected due to the mismatch in color formats. Constants --------- .. data:: framebuf.MONO_VLSB Monochrome (1-bit) color format This defines a mapping where the bits in a byte are vertically mapped with bit 0 being nearest the top of the screen. Consequently each byte occupies 8 vertical pixels. Subsequent bytes appear at successive horizontal locations until the rightmost edge is reached. Further bytes are rendered at locations starting at the leftmost edge, 8 pixels lower. .. data:: framebuf.MONO_HLSB Monochrome (1-bit) color format This defines a mapping where the bits in a byte are horizontally mapped. Each byte occupies 8 horizontal pixels with bit 0 being the leftmost. Subsequent bytes appear at successive horizontal locations until the rightmost edge is reached. Further bytes are rendered on the next row, one pixel lower. .. data:: framebuf.MONO_HMSB Monochrome (1-bit) color format This defines a mapping where the bits in a byte are horizontally mapped. Each byte occupies 8 horizontal pixels with bit 7 being the leftmost. Subsequent bytes appear at successive horizontal locations until the rightmost edge is reached. Further bytes are rendered on the next row, one pixel lower. .. data:: framebuf.RGB565 Red Green Blue (16-bit, 5+6+5) color format .. data:: framebuf.GS2_HMSB Grayscale (2-bit) color format .. data:: framebuf.GS4_HMSB Grayscale (4-bit) color format .. data:: framebuf.GS8 Grayscale (8-bit) color format micropython-1.12/docs/library/gc.rst000066400000000000000000000042351357706137100175450ustar00rootroot00000000000000:mod:`gc` -- control the garbage collector ========================================== .. module:: gc :synopsis: control the garbage collector |see_cpython_module| :mod:`python:gc`. Functions --------- .. function:: enable() Enable automatic garbage collection. .. function:: disable() Disable automatic garbage collection. Heap memory can still be allocated, and garbage collection can still be initiated manually using :meth:`gc.collect`. .. function:: collect() Run a garbage collection. .. function:: mem_alloc() Return the number of bytes of heap RAM that are allocated. .. admonition:: Difference to CPython :class: attention This function is MicroPython extension. .. function:: mem_free() Return the number of bytes of available heap RAM, or -1 if this amount is not known. .. admonition:: Difference to CPython :class: attention This function is MicroPython extension. .. function:: threshold([amount]) Set or query the additional GC allocation threshold. Normally, a collection is triggered only when a new allocation cannot be satisfied, i.e. on an out-of-memory (OOM) condition. If this function is called, in addition to OOM, a collection will be triggered each time after *amount* bytes have been allocated (in total, since the previous time such an amount of bytes have been allocated). *amount* is usually specified as less than the full heap size, with the intention to trigger a collection earlier than when the heap becomes exhausted, and in the hope that an early collection will prevent excessive memory fragmentation. This is a heuristic measure, the effect of which will vary from application to application, as well as the optimal value of the *amount* parameter. Calling the function without argument will return the current value of the threshold. A value of -1 means a disabled allocation threshold. .. admonition:: Difference to CPython :class: attention This function is a MicroPython extension. CPython has a similar function - ``set_threshold()``, but due to different GC implementations, its signature and semantics are different. micropython-1.12/docs/library/index.rst000066400000000000000000000125021357706137100202570ustar00rootroot00000000000000.. _micropython_lib: MicroPython libraries ===================== .. warning:: Important summary of this section * MicroPython implements a subset of Python functionality for each module. * To ease extensibility, MicroPython versions of standard Python modules usually have ``u`` ("micro") prefix. * Any particular MicroPython variant or port may miss any feature/function described in this general documentation (due to resource constraints or other limitations). This chapter describes modules (function and class libraries) which are built into MicroPython. There are a few categories of such modules: * Modules which implement a subset of standard Python functionality and are not intended to be extended by the user. * Modules which implement a subset of Python functionality, with a provision for extension by the user (via Python code). * Modules which implement MicroPython extensions to the Python standard libraries. * Modules specific to a particular `MicroPython port` and thus not portable. Note about the availability of the modules and their contents: This documentation in general aspires to describe all modules and functions/classes which are implemented in MicroPython project. However, MicroPython is highly configurable, and each port to a particular board/embedded system makes available only a subset of MicroPython libraries. For officially supported ports, there is an effort to either filter out non-applicable items, or mark individual descriptions with "Availability:" clauses describing which ports provide a given feature. With that in mind, please still be warned that some functions/classes in a module (or even the entire module) described in this documentation **may be unavailable** in a particular build of MicroPython on a particular system. The best place to find general information of the availability/non-availability of a particular feature is the "General Information" section which contains information pertaining to a specific `MicroPython port`. On some ports you are able to discover the available, built-in libraries that can be imported by entering the following at the REPL:: help('modules') Beyond the built-in libraries described in this documentation, many more modules from the Python standard library, as well as further MicroPython extensions to it, can be found in `micropython-lib`. Python standard libraries and micro-libraries --------------------------------------------- The following standard Python libraries have been "micro-ified" to fit in with the philosophy of MicroPython. They provide the core functionality of that module and are intended to be a drop-in replacement for the standard Python library. Some modules below use a standard Python name, but prefixed with "u", e.g. ``ujson`` instead of ``json``. This is to signify that such a module is micro-library, i.e. implements only a subset of CPython module functionality. By naming them differently, a user has a choice to write a Python-level module to extend functionality for better compatibility with CPython (indeed, this is what done by the `micropython-lib` project mentioned above). On some embedded platforms, where it may be cumbersome to add Python-level wrapper modules to achieve naming compatibility with CPython, micro-modules are available both by their u-name, and also by their non-u-name. The non-u-name can be overridden by a file of that name in your library path (``sys.path``). For example, ``import json`` will first search for a file ``json.py`` (or package directory ``json``) and load that module if it is found. If nothing is found, it will fallback to loading the built-in ``ujson`` module. .. toctree:: :maxdepth: 1 builtins.rst cmath.rst gc.rst math.rst sys.rst uarray.rst ubinascii.rst ucollections.rst uerrno.rst uhashlib.rst uheapq.rst uio.rst ujson.rst uos.rst ure.rst uselect.rst usocket.rst ussl.rst ustruct.rst utime.rst uzlib.rst _thread.rst MicroPython-specific libraries ------------------------------ Functionality specific to the MicroPython implementation is available in the following libraries. .. toctree:: :maxdepth: 1 btree.rst framebuf.rst machine.rst micropython.rst network.rst ubluetooth.rst ucryptolib.rst uctypes.rst Port-specific libraries ----------------------- In some cases the following port/board-specific libraries have functions or classes similar to those in the :mod:`machine` library. Where this occurs, the entry in the port specific library exposes hardware functionality unique to that platform. To write portable code use functions and classes from the :mod:`machine` module. To access platform-specific hardware use the appropriate library, e.g. :mod:`pyb` in the case of the Pyboard. Libraries specific to the pyboard --------------------------------- The following libraries are specific to the pyboard. .. toctree:: :maxdepth: 2 pyb.rst lcd160cr.rst Libraries specific to the WiPy ------------------------------ The following libraries and classes are specific to the WiPy. .. toctree:: :maxdepth: 2 wipy.rst machine.ADCWiPy.rst machine.TimerWiPy.rst Libraries specific to the ESP8266 and ESP32 ------------------------------------------- The following libraries are specific to the ESP8266 and ESP32. .. toctree:: :maxdepth: 2 esp.rst esp32.rst micropython-1.12/docs/library/lcd160cr.rst000066400000000000000000000353111357706137100204710ustar00rootroot00000000000000:mod:`lcd160cr` --- control of LCD160CR display =============================================== .. module:: lcd160cr :synopsis: control of LCD160CR display This module provides control of the MicroPython LCD160CR display. .. image:: http://micropython.org/resources/LCD160CRv10-persp.jpg :alt: LCD160CRv1.0 picture :width: 640px Further resources are available via the following links: * `LCD160CRv1.0 reference manual `_ (100KiB PDF) * `LCD160CRv1.0 schematics `_ (1.6MiB PDF) class LCD160CR -------------- The LCD160CR class provides an interface to the display. Create an instance of this class and use its methods to draw to the LCD and get the status of the touch panel. For example:: import lcd160cr lcd = lcd160cr.LCD160CR('X') lcd.set_orient(lcd160cr.PORTRAIT) lcd.set_pos(0, 0) lcd.set_text_color(lcd.rgb(255, 0, 0), lcd.rgb(0, 0, 0)) lcd.set_font(1) lcd.write('Hello MicroPython!') print('touch:', lcd.get_touch()) Constructors ------------ .. class:: LCD160CR(connect=None, \*, pwr=None, i2c=None, spi=None, i2c_addr=98) Construct an LCD160CR object. The parameters are: - *connect* is a string specifying the physical connection of the LCD display to the board; valid values are "X", "Y", "XY", "YX". Use "X" when the display is connected to a pyboard in the X-skin position, and "Y" when connected in the Y-skin position. "XY" and "YX" are used when the display is connected to the right or left side of the pyboard, respectively. - *pwr* is a Pin object connected to the LCD's power/enabled pin. - *i2c* is an I2C object connected to the LCD's I2C interface. - *spi* is an SPI object connected to the LCD's SPI interface. - *i2c_addr* is the I2C address of the display. One must specify either a valid *connect* or all of *pwr*, *i2c* and *spi*. If a valid *connect* is given then any of *pwr*, *i2c* or *spi* which are not passed as parameters (i.e. they are ``None``) will be created based on the value of *connect*. This allows to override the default interface to the display if needed. The default values are: - "X" is for the X-skin and uses: ``pwr=Pin("X4")``, ``i2c=I2C("X")``, ``spi=SPI("X")`` - "Y" is for the Y-skin and uses: ``pwr=Pin("Y4")``, ``i2c=I2C("Y")``, ``spi=SPI("Y")`` - "XY" is for the right-side and uses: ``pwr=Pin("X4")``, ``i2c=I2C("Y")``, ``spi=SPI("X")`` - "YX" is for the left-side and uses: ``pwr=Pin("Y4")``, ``i2c=I2C("X")``, ``spi=SPI("Y")`` See `this image `_ for how the display can be connected to the pyboard. Static methods -------------- .. staticmethod:: LCD160CR.rgb(r, g, b) Return a 16-bit integer representing the given rgb color values. The 16-bit value can be used to set the font color (see :meth:`LCD160CR.set_text_color`) pen color (see :meth:`LCD160CR.set_pen`) and draw individual pixels. .. staticmethod:: LCD160CR.clip_line(data, w, h): Clip the given line data. This is for internal use. Instance members ---------------- The following instance members are publicly accessible. .. data:: LCD160CR.w .. data:: LCD160CR.h The width and height of the display, respectively, in pixels. These members are updated when calling :meth:`LCD160CR.set_orient` and should be considered read-only. Setup commands -------------- .. method:: LCD160CR.set_power(on) Turn the display on or off, depending on the given value of *on*: 0 or ``False`` will turn the display off, and 1 or ``True`` will turn it on. .. method:: LCD160CR.set_orient(orient) Set the orientation of the display. The *orient* parameter can be one of `PORTRAIT`, `LANDSCAPE`, `PORTRAIT_UPSIDEDOWN`, `LANDSCAPE_UPSIDEDOWN`. .. method:: LCD160CR.set_brightness(value) Set the brightness of the display, between 0 and 31. .. method:: LCD160CR.set_i2c_addr(addr) Set the I2C address of the display. The *addr* value must have the lower 2 bits cleared. .. method:: LCD160CR.set_uart_baudrate(baudrate) Set the baudrate of the UART interface. .. method:: LCD160CR.set_startup_deco(value) Set the start-up decoration of the display. The *value* parameter can be a logical or of `STARTUP_DECO_NONE`, `STARTUP_DECO_MLOGO`, `STARTUP_DECO_INFO`. .. method:: LCD160CR.save_to_flash() Save the following parameters to flash so they persist on restart and power up: initial decoration, orientation, brightness, UART baud rate, I2C address. Pixel access methods -------------------- The following methods manipulate individual pixels on the display. .. method:: LCD160CR.set_pixel(x, y, c) Set the specified pixel to the given color. The color should be a 16-bit integer and can be created by :meth:`LCD160CR.rgb`. .. method:: LCD160CR.get_pixel(x, y) Get the 16-bit value of the specified pixel. .. method:: LCD160CR.get_line(x, y, buf) Low-level method to get a line of pixels into the given buffer. To read *n* pixels *buf* should be *2*n+1* bytes in length. The first byte is a dummy byte and should be ignored, and subsequent bytes represent the pixels in the line starting at coordinate *(x, y)*. .. method:: LCD160CR.screen_dump(buf, x=0, y=0, w=None, h=None) Dump the contents of the screen to the given buffer. The parameters *x* and *y* specify the starting coordinate, and *w* and *h* the size of the region. If *w* or *h* are ``None`` then they will take on their maximum values, set by the size of the screen minus the given *x* and *y* values. *buf* should be large enough to hold ``2*w*h`` bytes. If it's smaller then only the initial horizontal lines will be stored. .. method:: LCD160CR.screen_load(buf) Load the entire screen from the given buffer. Drawing text ------------ To draw text one sets the position, color and font, and then uses `LCD160CR.write` to draw the text. .. method:: LCD160CR.set_pos(x, y) Set the position for text output using :meth:`LCD160CR.write`. The position is the upper-left corner of the text. .. method:: LCD160CR.set_text_color(fg, bg) Set the foreground and background color of the text. .. method:: LCD160CR.set_font(font, scale=0, bold=0, trans=0, scroll=0) Set the font for the text. Subsequent calls to `write` will use the newly configured font. The parameters are: - *font* is the font family to use, valid values are 0, 1, 2, 3. - *scale* is a scaling value for each character pixel, where the pixels are drawn as a square with side length equal to *scale + 1*. The value can be between 0 and 63. - *bold* controls the number of pixels to overdraw each character pixel, making a bold effect. The lower 2 bits of *bold* are the number of pixels to overdraw in the horizontal direction, and the next 2 bits are for the vertical direction. For example, a *bold* value of 5 will overdraw 1 pixel in both the horizontal and vertical directions. - *trans* can be either 0 or 1 and if set to 1 the characters will be drawn with a transparent background. - *scroll* can be either 0 or 1 and if set to 1 the display will do a soft scroll if the text moves to the next line. .. method:: LCD160CR.write(s) Write text to the display, using the current position, color and font. As text is written the position is automatically incremented. The display supports basic VT100 control codes such as newline and backspace. Drawing primitive shapes ------------------------ Primitive drawing commands use a foreground and background color set by the `set_pen` method. .. method:: LCD160CR.set_pen(line, fill) Set the line and fill color for primitive shapes. .. method:: LCD160CR.erase() Erase the entire display to the pen fill color. .. method:: LCD160CR.dot(x, y) Draw a single pixel at the given location using the pen line color. .. method:: LCD160CR.rect(x, y, w, h) .. method:: LCD160CR.rect_outline(x, y, w, h) .. method:: LCD160CR.rect_interior(x, y, w, h) Draw a rectangle at the given location and size using the pen line color for the outline, and the pen fill color for the interior. The `rect` method draws the outline and interior, while the other methods just draw one or the other. .. method:: LCD160CR.line(x1, y1, x2, y2) Draw a line between the given coordinates using the pen line color. .. method:: LCD160CR.dot_no_clip(x, y) .. method:: LCD160CR.rect_no_clip(x, y, w, h) .. method:: LCD160CR.rect_outline_no_clip(x, y, w, h) .. method:: LCD160CR.rect_interior_no_clip(x, y, w, h) .. method:: LCD160CR.line_no_clip(x1, y1, x2, y2) These methods are as above but don't do any clipping on the input coordinates. They are faster than the clipping versions and can be used when you know that the coordinates are within the display. .. method:: LCD160CR.poly_dot(data) Draw a sequence of dots using the pen line color. The *data* should be a buffer of bytes, with each successive pair of bytes corresponding to coordinate pairs (x, y). .. method:: LCD160CR.poly_line(data) Similar to :meth:`LCD160CR.poly_dot` but draws lines between the dots. Touch screen methods -------------------- .. method:: LCD160CR.touch_config(calib=False, save=False, irq=None) Configure the touch panel: - If *calib* is ``True`` then the call will trigger a touch calibration of the resistive touch sensor. This requires the user to touch various parts of the screen. - If *save* is ``True`` then the touch parameters will be saved to NVRAM to persist across reset/power up. - If *irq* is ``True`` then the display will be configured to pull the IRQ line low when a touch force is detected. If *irq* is ``False`` then this feature is disabled. If *irq* is ``None`` (the default value) then no change is made to this setting. .. method:: LCD160CR.is_touched() Returns a boolean: ``True`` if there is currently a touch force on the screen, ``False`` otherwise. .. method:: LCD160CR.get_touch() Returns a 3-tuple of: *(active, x, y)*. If there is currently a touch force on the screen then *active* is 1, otherwise it is 0. The *x* and *y* values indicate the position of the current or most recent touch. Advanced commands ----------------- .. method:: LCD160CR.set_spi_win(x, y, w, h) Set the window that SPI data is written to. .. method:: LCD160CR.fast_spi(flush=True) Ready the display to accept RGB pixel data on the SPI bus, resetting the location of the first byte to go to the top-left corner of the window set by :meth:`LCD160CR.set_spi_win`. The method returns an SPI object which can be used to write the pixel data. Pixels should be sent as 16-bit RGB values in the 5-6-5 format. The destination counter will increase as data is sent, and data can be sent in arbitrary sized chunks. Once the destination counter reaches the end of the window specified by :meth:`LCD160CR.set_spi_win` it will wrap around to the top-left corner of that window. .. method:: LCD160CR.show_framebuf(buf) Show the given buffer on the display. *buf* should be an array of bytes containing the 16-bit RGB values for the pixels, and they will be written to the area specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner. The `framebuf `_ module can be used to construct frame buffers and provides drawing primitives. Using a frame buffer will improve performance of animations when compared to drawing directly to the screen. .. method:: LCD160CR.set_scroll(on) Turn scrolling on or off. This controls globally whether any window regions will scroll. .. method:: LCD160CR.set_scroll_win(win, x=-1, y=0, w=0, h=0, vec=0, pat=0, fill=0x07e0, color=0) Configure a window region for scrolling: - *win* is the window id to configure. There are 0..7 standard windows for general purpose use. Window 8 is the text scroll window (the ticker). - *x*, *y*, *w*, *h* specify the location of the window in the display. - *vec* specifies the direction and speed of scroll: it is a 16-bit value of the form ``0bF.ddSSSSSSSSSSSS``. *dd* is 0, 1, 2, 3 for +x, +y, -x, -y scrolling. *F* sets the speed format, with 0 meaning that the window is shifted *S % 256* pixel every frame, and 1 meaning that the window is shifted 1 pixel every *S* frames. - *pat* is a 16-bit pattern mask for the background. - *fill* is the fill color. - *color* is the extra color, either of the text or pattern foreground. .. method:: LCD160CR.set_scroll_win_param(win, param, value) Set a single parameter of a scrolling window region: - *win* is the window id, 0..8. - *param* is the parameter number to configure, 0..7, and corresponds to the parameters in the `set_scroll_win` method. - *value* is the value to set. .. method:: LCD160CR.set_scroll_buf(s) Set the string for scrolling in window 8. The parameter *s* must be a string with length 32 or less. .. method:: LCD160CR.jpeg(buf) Display a JPEG. *buf* should contain the entire JPEG data. JPEG data should not include EXIF information. The following encodings are supported: Baseline DCT, Huffman coding, 8 bits per sample, 3 color components, YCbCr4:2:2. The origin of the JPEG is set by :meth:`LCD160CR.set_pos`. .. method:: LCD160CR.jpeg_start(total_len) .. method:: LCD160CR.jpeg_data(buf) Display a JPEG with the data split across multiple buffers. There must be a single call to `jpeg_start` to begin with, specifying the total number of bytes in the JPEG. Then this number of bytes must be transferred to the display using one or more calls to the `jpeg_data` command. .. method:: LCD160CR.feed_wdt() The first call to this method will start the display's internal watchdog timer. Subsequent calls will feed the watchdog. The timeout is roughly 30 seconds. .. method:: LCD160CR.reset() Reset the display. Constants --------- .. data:: lcd160cr.PORTRAIT lcd160cr.LANDSCAPE lcd160cr.PORTRAIT_UPSIDEDOWN lcd160cr.LANDSCAPE_UPSIDEDOWN Orientations of the display, used by :meth:`LCD160CR.set_orient`. .. data:: lcd160cr.STARTUP_DECO_NONE lcd160cr.STARTUP_DECO_MLOGO lcd160cr.STARTUP_DECO_INFO Types of start-up decoration, can be OR'ed together, used by :meth:`LCD160CR.set_startup_deco`. micropython-1.12/docs/library/machine.ADC.rst000066400000000000000000000017721357706137100211510ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.ADC: class ADC -- analog to digital conversion ========================================= The ADC class provides an interface to analog-to-digital convertors, and represents a single endpoint that can sample a continuous voltage and convert it to a discretised value. Example usage:: import machine adc = machine.ADC(pin) # create an ADC object acting on a pin val = adc.read_u16() # read a raw analog value in the range 0-65535 Constructors ------------ .. class:: ADC(id) Access the ADC associated with a source identified by *id*. This *id* may be an integer (usually specifying a channel number), a :ref:`Pin ` object, or other value supported by the underlying machine. Methods ------- .. method:: ADC.read_u16() Take an analog reading and return an integer in the range 0-65535. The return value represents the raw reading taken by the ADC, scaled such that the minimum value is 0 and the maximum value is 65535. micropython-1.12/docs/library/machine.ADCWiPy.rst000066400000000000000000000044511357706137100217570ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.ADCWiPy: class ADCWiPy -- analog to digital conversion ============================================= .. note:: This class is a non-standard ADC implementation for the WiPy. It is available simply as ``machine.ADC`` on the WiPy but is named in the documentation below as ``machine.ADCWiPy`` to distinguish it from the more general :ref:`machine.ADC ` class. Usage:: import machine adc = machine.ADC() # create an ADC object apin = adc.channel(pin='GP3') # create an analog pin on GP3 val = apin() # read an analog value Constructors ------------ .. class:: ADCWiPy(id=0, \*, bits=12) Create an ADC object associated with the given pin. This allows you to then read analog values on that pin. For more info check the `pinout and alternate functions table. `_ .. warning:: ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it can withstand). When GP2, GP3, GP4 or GP5 are remapped to the ADC block, 1.8 V is the maximum. If these pins are used in digital mode, then the maximum allowed input is 3.6V. Methods ------- .. method:: ADCWiPy.channel(id, \*, pin) Create an analog pin. If only channel ID is given, the correct pin will be selected. Alternatively, only the pin can be passed and the correct channel will be selected. Examples:: # all of these are equivalent and enable ADC channel 1 on GP3 apin = adc.channel(1) apin = adc.channel(pin='GP3') apin = adc.channel(id=1, pin='GP3') .. method:: ADCWiPy.init() Enable the ADC block. .. method:: ADCWiPy.deinit() Disable the ADC block. class ADCChannel --- read analog values from internal or external sources ========================================================================= ADC channels can be connected to internal points of the MCU or to GPIO pins. ADC channels are created using the ADC.channel method. .. method:: adcchannel() Fast method to read the channel value. .. method:: adcchannel.value() Read the channel value. .. method:: adcchannel.init() Re-init (and effectively enable) the ADC channel. .. method:: adcchannel.deinit() Disable the ADC channel. micropython-1.12/docs/library/machine.I2C.rst000066400000000000000000000161041357706137100211320ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.I2C: class I2C -- a two-wire serial protocol ======================================= I2C is a two-wire protocol for communicating between devices. At the physical level it consists of 2 wires: SCL and SDA, the clock and data lines respectively. I2C objects are created attached to a specific bus. They can be initialised when created, or initialised later on. Printing the I2C object gives you information about its configuration. Example usage:: from machine import I2C i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz # depending on the port, extra parameters may be required # to select the peripheral and/or pins to use i2c.scan() # scan for slaves, returning a list of 7-bit addresses i2c.writeto(42, b'123') # write 3 bytes to slave with 7-bit address 42 i2c.readfrom(42, 4) # read 4 bytes from slave with 7-bit address 42 i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of slave 42, # starting at memory-address 8 in the slave i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of slave 42 # starting at address 2 in the slave Constructors ------------ .. class:: I2C(id=-1, \*, scl, sda, freq=400000) Construct and return a new I2C object using the following parameters: - *id* identifies a particular I2C peripheral. The default value of -1 selects a software implementation of I2C which can work (in most cases) with arbitrary pins for SCL and SDA. If *id* is -1 then *scl* and *sda* must be specified. Other allowed values for *id* depend on the particular port/board, and specifying *scl* and *sda* may or may not be required or allowed in this case. - *scl* should be a pin object specifying the pin to use for SCL. - *sda* should be a pin object specifying the pin to use for SDA. - *freq* should be an integer which sets the maximum frequency for SCL. General Methods --------------- .. method:: I2C.init(scl, sda, \*, freq=400000) Initialise the I2C bus with the given arguments: - *scl* is a pin object for the SCL line - *sda* is a pin object for the SDA line - *freq* is the SCL clock rate .. method:: I2C.deinit() Turn off the I2C bus. Availability: WiPy. .. method:: I2C.scan() Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of those that respond. A device responds if it pulls the SDA line low after its address (including a write bit) is sent on the bus. Primitive I2C operations ------------------------ The following methods implement the primitive I2C master bus operations and can be combined to make any I2C transaction. They are provided if you need more control over the bus, otherwise the standard methods (see below) can be used. These methods are available on software I2C only. .. method:: I2C.start() Generate a START condition on the bus (SDA transitions to low while SCL is high). .. method:: I2C.stop() Generate a STOP condition on the bus (SDA transitions to high while SCL is high). .. method:: I2C.readinto(buf, nack=True) Reads bytes from the bus and stores them into *buf*. The number of bytes read is the length of *buf*. An ACK will be sent on the bus after receiving all but the last byte. After the last byte is received, if *nack* is true then a NACK will be sent, otherwise an ACK will be sent (and in this case the slave assumes more bytes are going to be read in a later call). .. method:: I2C.write(buf) Write the bytes from *buf* to the bus. Checks that an ACK is received after each byte and stops transmitting the remaining bytes if a NACK is received. The function returns the number of ACKs that were received. Standard bus operations ----------------------- The following methods implement the standard I2C master read and write operations that target a given slave device. .. method:: I2C.readfrom(addr, nbytes, stop=True) Read *nbytes* from the slave specified by *addr*. If *stop* is true then a STOP condition is generated at the end of the transfer. Returns a `bytes` object with the data read. .. method:: I2C.readfrom_into(addr, buf, stop=True) Read into *buf* from the slave specified by *addr*. The number of bytes read will be the length of *buf*. If *stop* is true then a STOP condition is generated at the end of the transfer. The method returns ``None``. .. method:: I2C.writeto(addr, buf, stop=True) Write the bytes from *buf* to the slave specified by *addr*. If a NACK is received following the write of a byte from *buf* then the remaining bytes are not sent. If *stop* is true then a STOP condition is generated at the end of the transfer, even if a NACK is received. The function returns the number of ACKs that were received. .. method:: I2C.writevto(addr, vector, stop=True) Write the bytes contained in *vector* to the slave specified by *addr*. *vector* should be a tuple or list of objects with the buffer protocol. The *addr* is sent once and then the bytes from each object in *vector* are written out sequentially. The objects in *vector* may be zero bytes in length in which case they don't contribute to the output. If a NACK is received following the write of a byte from one of the objects in *vector* then the remaining bytes, and any remaining objects, are not sent. If *stop* is true then a STOP condition is generated at the end of the transfer, even if a NACK is received. The function returns the number of ACKs that were received. Memory operations ----------------- Some I2C devices act as a memory device (or set of registers) that can be read from and written to. In this case there are two addresses associated with an I2C transaction: the slave address and the memory address. The following methods are convenience functions to communicate with such devices. .. method:: I2C.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8) Read *nbytes* from the slave specified by *addr* starting from the memory address specified by *memaddr*. The argument *addrsize* specifies the address size in bits. Returns a `bytes` object with the data read. .. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8) Read into *buf* from the slave specified by *addr* starting from the memory address specified by *memaddr*. The number of bytes read is the length of *buf*. The argument *addrsize* specifies the address size in bits (on ESP8266 this argument is not recognised and the address size is always 8 bits). The method returns ``None``. .. method:: I2C.writeto_mem(addr, memaddr, buf, \*, addrsize=8) Write *buf* to the slave specified by *addr* starting from the memory address specified by *memaddr*. The argument *addrsize* specifies the address size in bits (on ESP8266 this argument is not recognised and the address size is always 8 bits). The method returns ``None``. micropython-1.12/docs/library/machine.Pin.rst000066400000000000000000000234421357706137100213060ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.Pin: class Pin -- control I/O pins ============================= A pin object is used to control I/O pins (also known as GPIO - general-purpose input/output). Pin objects are commonly associated with a physical pin that can drive an output voltage and read input voltages. The pin class has methods to set the mode of the pin (IN, OUT, etc) and methods to get and set the digital logic level. For analog control of a pin, see the :class:`ADC` class. A pin object is constructed by using an identifier which unambiguously specifies a certain I/O pin. The allowed forms of the identifier and the physical pin that the identifier maps to are port-specific. Possibilities for the identifier are an integer, a string or a tuple with port and pin number. Usage Model:: from machine import Pin # create an output pin on pin #0 p0 = Pin(0, Pin.OUT) # set the value low then high p0.value(0) p0.value(1) # create an input pin on pin #2, with a pull up resistor p2 = Pin(2, Pin.IN, Pin.PULL_UP) # read and print the pin value print(p2.value()) # reconfigure pin #0 in input mode p0.mode(p0.IN) # configure an irq callback p0.irq(lambda p:print(p)) Constructors ------------ .. class:: Pin(id, mode=-1, pull=-1, \*, value, drive, alt) Access the pin peripheral (GPIO pin) associated with the given ``id``. If additional arguments are given in the constructor then they are used to initialise the pin. Any settings that are not specified will remain in their previous state. The arguments are: - ``id`` is mandatory and can be an arbitrary object. Among possible value types are: int (an internal Pin identifier), str (a Pin name), and tuple (pair of [port, pin]). - ``mode`` specifies the pin mode, which can be one of: - ``Pin.IN`` - Pin is configured for input. If viewed as an output the pin is in high-impedance state. - ``Pin.OUT`` - Pin is configured for (normal) output. - ``Pin.OPEN_DRAIN`` - Pin is configured for open-drain output. Open-drain output works in the following way: if the output value is set to 0 the pin is active at a low level; if the output value is 1 the pin is in a high-impedance state. Not all ports implement this mode, or some might only on certain pins. - ``Pin.ALT`` - Pin is configured to perform an alternative function, which is port specific. For a pin configured in such a way any other Pin methods (except :meth:`Pin.init`) are not applicable (calling them will lead to undefined, or a hardware-specific, result). Not all ports implement this mode. - ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as open-drain. Not all ports implement this mode. - ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be one of: - ``None`` - No pull up or down resistor. - ``Pin.PULL_UP`` - Pull up resistor enabled. - ``Pin.PULL_DOWN`` - Pull down resistor enabled. - ``value`` is valid only for Pin.OUT and Pin.OPEN_DRAIN modes and specifies initial output pin value if given, otherwise the state of the pin peripheral remains unchanged. - ``drive`` specifies the output power of the pin and can be one of: ``Pin.LOW_POWER``, ``Pin.MED_POWER`` or ``Pin.HIGH_POWER``. The actual current driving capabilities are port dependent. Not all ports implement this argument. - ``alt`` specifies an alternate function for the pin and the values it can take are port dependent. This argument is valid only for ``Pin.ALT`` and ``Pin.ALT_OPEN_DRAIN`` modes. It may be used when a pin supports more than one alternate function. If only one pin alternate function is supported the this argument is not required. Not all ports implement this argument. As specified above, the Pin class allows to set an alternate function for a particular pin, but it does not specify any further operations on such a pin. Pins configured in alternate-function mode are usually not used as GPIO but are instead driven by other hardware peripherals. The only operation supported on such a pin is re-initialising, by calling the constructor or :meth:`Pin.init` method. If a pin that is configured in alternate-function mode is re-initialised with ``Pin.IN``, ``Pin.OUT``, or ``Pin.OPEN_DRAIN``, the alternate function will be removed from the pin. Methods ------- .. method:: Pin.init(mode=-1, pull=-1, \*, value, drive, alt) Re-initialise the pin using the given parameters. Only those arguments that are specified will be set. The rest of the pin peripheral state will remain unchanged. See the constructor documentation for details of the arguments. Returns ``None``. .. method:: Pin.value([x]) This method allows to set and get the value of the pin, depending on whether the argument ``x`` is supplied or not. If the argument is omitted then this method gets the digital logic level of the pin, returning 0 or 1 corresponding to low and high voltage signals respectively. The behaviour of this method depends on the mode of the pin: - ``Pin.IN`` - The method returns the actual input value currently present on the pin. - ``Pin.OUT`` - The behaviour and return value of the method is undefined. - ``Pin.OPEN_DRAIN`` - If the pin is in state '0' then the behaviour and return value of the method is undefined. Otherwise, if the pin is in state '1', the method returns the actual input value currently present on the pin. If the argument is supplied then this method sets the digital logic level of the pin. The argument ``x`` can be anything that converts to a boolean. If it converts to ``True``, the pin is set to state '1', otherwise it is set to state '0'. The behaviour of this method depends on the mode of the pin: - ``Pin.IN`` - The value is stored in the output buffer for the pin. The pin state does not change, it remains in the high-impedance state. The stored value will become active on the pin as soon as it is changed to ``Pin.OUT`` or ``Pin.OPEN_DRAIN`` mode. - ``Pin.OUT`` - The output buffer is set to the given value immediately. - ``Pin.OPEN_DRAIN`` - If the value is '0' the pin is set to a low voltage state. Otherwise the pin is set to high-impedance state. When setting the value this method returns ``None``. .. method:: Pin.__call__([x]) Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin. It is equivalent to Pin.value([x]). See :meth:`Pin.value` for more details. .. method:: Pin.on() Set pin to "1" output level. .. method:: Pin.off() Set pin to "0" output level. .. method:: Pin.mode([mode]) Get or set the pin mode. See the constructor documentation for details of the ``mode`` argument. .. method:: Pin.pull([pull]) Get or set the pin pull state. See the constructor documentation for details of the ``pull`` argument. .. method:: Pin.drive([drive]) Get or set the pin drive strength. See the constructor documentation for details of the ``drive`` argument. Not all ports implement this method. Availability: WiPy. .. method:: Pin.irq(handler=None, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING), \*, priority=1, wake=None, hard=False) Configure an interrupt handler to be called when the trigger source of the pin is active. If the pin mode is ``Pin.IN`` then the trigger source is the external value on the pin. If the pin mode is ``Pin.OUT`` then the trigger source is the output buffer of the pin. Otherwise, if the pin mode is ``Pin.OPEN_DRAIN`` then the trigger source is the output buffer for state '0' and the external pin value for state '1'. The arguments are: - ``handler`` is an optional function to be called when the interrupt triggers. The handler must take exactly one argument which is the ``Pin`` instance. - ``trigger`` configures the event which can generate an interrupt. Possible values are: - ``Pin.IRQ_FALLING`` interrupt on falling edge. - ``Pin.IRQ_RISING`` interrupt on rising edge. - ``Pin.IRQ_LOW_LEVEL`` interrupt on low level. - ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level. These values can be OR'ed together to trigger on multiple events. - ``priority`` sets the priority level of the interrupt. The values it can take are port-specific, but higher values always represent higher priorities. - ``wake`` selects the power mode in which this interrupt can wake up the system. It can be ``machine.IDLE``, ``machine.SLEEP`` or ``machine.DEEPSLEEP``. These values can also be OR'ed together to make a pin generate interrupts in more than one power mode. - ``hard`` if true a hardware interrupt is used. This reduces the delay between the pin change and the handler being called. Hard interrupt handlers may not allocate memory; see :ref:`isr_rules`. This method returns a callback object. Constants --------- The following constants are used to configure the pin objects. Note that not all constants are available on all ports. .. data:: Pin.IN Pin.OUT Pin.OPEN_DRAIN Pin.ALT Pin.ALT_OPEN_DRAIN Selects the pin mode. .. data:: Pin.PULL_UP Pin.PULL_DOWN Pin.PULL_HOLD Selects whether there is a pull up/down resistor. Use the value ``None`` for no pull. .. data:: Pin.LOW_POWER Pin.MED_POWER Pin.HIGH_POWER Selects the pin drive strength. .. data:: Pin.IRQ_FALLING Pin.IRQ_RISING Pin.IRQ_LOW_LEVEL Pin.IRQ_HIGH_LEVEL Selects the IRQ trigger type. micropython-1.12/docs/library/machine.RTC.rst000066400000000000000000000031721357706137100212060ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.RTC: class RTC -- real time clock ============================ The RTC is and independent clock that keeps track of the date and time. Example usage:: rtc = machine.RTC() rtc.init((2014, 5, 1, 4, 13, 0, 0, 0)) print(rtc.now()) Constructors ------------ .. class:: RTC(id=0, ...) Create an RTC object. See init for parameters of initialization. Methods ------- .. method:: RTC.init(datetime) Initialise the RTC. Datetime is a tuple of the form: ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` .. method:: RTC.now() Get get the current datetime tuple. .. method:: RTC.deinit() Resets the RTC to the time of January 1, 2015 and starts running it again. .. method:: RTC.alarm(id, time, \*, repeat=False) Set the RTC alarm. Time might be either a millisecond value to program the alarm to current time + time_in_ms in the future, or a datetimetuple. If the time passed is in milliseconds, repeat can be set to ``True`` to make the alarm periodic. .. method:: RTC.alarm_left(alarm_id=0) Get the number of milliseconds left before the alarm expires. .. method:: RTC.cancel(alarm_id=0) Cancel a running alarm. .. method:: RTC.irq(\*, trigger, handler=None, wake=machine.IDLE) Create an irq object triggered by a real time clock alarm. - ``trigger`` must be ``RTC.ALARM0`` - ``handler`` is the function to be called when the callback is triggered. - ``wake`` specifies the sleep mode from where this interrupt can wake up the system. Constants --------- .. data:: RTC.ALARM0 irq trigger source micropython-1.12/docs/library/machine.SD.rst000066400000000000000000000025531357706137100210660ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.SD: class SD -- secure digital memory card (cc3200 port only) ========================================================= .. warning:: This is a non-standard class and is only available on the cc3200 port. The SD card class allows to configure and enable the memory card module of the WiPy and automatically mount it as ``/sd`` as part of the file system. There are several pin combinations that can be used to wire the SD card socket to the WiPy and the pins used can be specified in the constructor. Please check the `pinout and alternate functions table. `_ for more info regarding the pins which can be remapped to be used with a SD card. Example usage:: from machine import SD import os # clk cmd and dat0 pins must be passed along with # their respective alternate functions sd = machine.SD(pins=('GP10', 'GP11', 'GP15')) os.mount(sd, '/sd') # do normal file operations Constructors ------------ .. class:: SD(id,... ) Create a SD card object. See ``init()`` for parameters if initialization. Methods ------- .. method:: SD.init(id=0, pins=('GP10', 'GP11', 'GP15')) Enable the SD card. In order to initialize the card, give it a 3-tuple: ``(clk_pin, cmd_pin, dat0_pin)``. .. method:: SD.deinit() Disable the SD card. micropython-1.12/docs/library/machine.SDCard.rst000066400000000000000000000112451357706137100216560ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.SDCard: class SDCard -- secure digital memory card ========================================== SD cards are one of the most common small form factor removable storage media. SD cards come in a variety of sizes and physical form factors. MMC cards are similar removable storage devices while eMMC devices are electrically similar storage devices designed to be embedded into other systems. All three form share a common protocol for communication with their host system and high-level support looks the same for them all. As such in MicroPython they are implemented in a single class called :class:`machine.SDCard` . Both SD and MMC interfaces support being accessed with a variety of bus widths. When being accessed with a 1-bit wide interface they can be accessed using the SPI protocol. Different MicroPython hardware platforms support different widths and pin configurations but for most platforms there is a standard configuration for any given hardware. In general constructing an ``SDCard`` object with without passing any parameters will initialise the interface to the default card slot for the current hardware. The arguments listed below represent the common arguments that might need to be set in order to use either a non-standard slot or a non-standard pin assignment. The exact subset of arguments supported will vary from platform to platform. .. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None) This class provides access to SD or MMC storage cards using either a dedicated SD/MMC interface hardware or through an SPI channel. The class implements the block protocol defined by :class:`uos.AbstractBlockDev`. This allows the mounting of an SD card to be as simple as:: uos.mount(machine.SDCard(), "/sd") The constructor takes the following parameters: - *slot* selects which of the available interfaces to use. Leaving this unset will select the default interface. - *width* selects the bus width for the SD/MMC interface. - *cd* can be used to specify a card-detect pin. - *wp* can be used to specify a write-protect pin. - *sck* can be used to specify an SPI clock pin. - *miso* can be used to specify an SPI miso pin. - *mosi* can be used to specify an SPI mosi pin. - *cs* can be used to specify an SPI chip select pin. Implementation-specific details ------------------------------- Different implementations of the ``SDCard`` class on different hardware support varying subsets of the options above. PyBoard ``````` The standard PyBoard has just one slot. No arguments are necessary or supported. ESP32 ````` The ESP32 provides two channels of SD/MMC hardware and also supports access to SD Cards through either of the two SPI ports that are generally available to the user. As a result the *slot* argument can take a value between 0 and 3, inclusive. Slots 0 and 1 use the built-in SD/MMC hardware while slots 2 and 3 use the SPI ports. Slot 0 supports 1, 4 or 8-bit wide access while slot 1 supports 1 or 4-bit access; the SPI slots only support 1-bit access. .. note:: Slot 0 is used to communicate with on-board flash memory on most ESP32 modules and so will be unavailable to the user. .. note:: Most ESP32 modules that provide an SD card slot using the dedicated hardware only wire up 1 data pin, so the default value for *width* is 1. The pins used by the dedicated SD/MMC hardware are fixed. The pins used by the SPI hardware can be reassigned. .. note:: If any of the SPI signals are remapped then all of the SPI signals will pass through a GPIO multiplexer unit which can limit the performance of high frequency signals. Since the normal operating speed for SD cards is 40MHz this can cause problems on some cards. The default (and preferred) pin assignment are as follows: ====== ====== ====== ====== ====== Slot 0 1 2 3 ------ ------ ------ ------ ------ Signal Pin Pin Pin Pin ====== ====== ====== ====== ====== sck 6 14 18 14 cmd 11 15 cs 5 15 miso 19 12 mosi 23 13 D0 7 2 D1 8 4 D2 9 12 D3 10 13 D4 16 D5 17 D6 5 D7 18 ====== ====== ====== ====== ====== cc3200 `````` You can set the pins used for SPI access by passing a tuple as the *pins* argument. *Note:* The current cc3200 SD card implementation names the this class :class:`machine.SD` rather than :class:`machine.SDCard` . micropython-1.12/docs/library/machine.SPI.rst000066400000000000000000000074001357706137100212070ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.SPI: class SPI -- a Serial Peripheral Interface bus protocol (master side) ===================================================================== SPI is a synchronous serial protocol that is driven by a master. At the physical level, a bus consists of 3 lines: SCK, MOSI, MISO. Multiple devices can share the same bus. Each device should have a separate, 4th signal, SS (Slave Select), to select a particular device on a bus with which communication takes place. Management of an SS signal should happen in user code (via machine.Pin class). Constructors ------------ .. class:: SPI(id, ...) Construct an SPI object on the given bus, ``id``. Values of ``id`` depend on a particular port and its hardware. Values 0, 1, etc. are commonly used to select hardware SPI block #0, #1, etc. Value -1 can be used for bitbanging (software) implementation of SPI (if supported by a port). With no additional parameters, the SPI object is created but not initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. See ``init`` for parameters of initialisation. Methods ------- .. method:: SPI.init(baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=None, mosi=None, miso=None, pins=(SCK, MOSI, MISO)) Initialise the SPI bus with the given parameters: - ``baudrate`` is the SCK clock rate. - ``polarity`` can be 0 or 1, and is the level the idle clock line sits at. - ``phase`` can be 0 or 1 to sample data on the first or second clock edge respectively. - ``bits`` is the width in bits of each transfer. Only 8 is guaranteed to be supported by all hardware. - ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``. - ``sck``, ``mosi``, ``miso`` are pins (machine.Pin) objects to use for bus signals. For most hardware SPI blocks (as selected by ``id`` parameter to the constructor), pins are fixed and cannot be changed. In some cases, hardware blocks allow 2-3 alternative pin sets for a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver (``id`` = -1). - ``pins`` - WiPy port doesn't ``sck``, ``mosi``, ``miso`` arguments, and instead allows to specify them as a tuple of ``pins`` parameter. In the case of hardware SPI the actual clock frequency may be lower than the requested baudrate. This is dependant on the platform hardware. The actual rate may be determined by printing the SPI object. .. method:: SPI.deinit() Turn off the SPI bus. .. method:: SPI.read(nbytes, write=0x00) Read a number of bytes specified by ``nbytes`` while continuously writing the single byte given by ``write``. Returns a ``bytes`` object with the data that was read. .. method:: SPI.readinto(buf, write=0x00) Read into the buffer specified by ``buf`` while continuously writing the single byte given by ``write``. Returns ``None``. Note: on WiPy this function returns the number of bytes read. .. method:: SPI.write(buf) Write the bytes contained in ``buf``. Returns ``None``. Note: on WiPy this function returns the number of bytes written. .. method:: SPI.write_readinto(write_buf, read_buf) Write the bytes from ``write_buf`` while reading into ``read_buf``. The buffers can be the same or different, but both buffers must have the same length. Returns ``None``. Note: on WiPy this function returns the number of bytes written. Constants --------- .. data:: SPI.MASTER for initialising the SPI bus to master; this is only used for the WiPy .. data:: SPI.MSB set the first bit to be the most significant bit .. data:: SPI.LSB set the first bit to be the least significant bit micropython-1.12/docs/library/machine.Signal.rst000066400000000000000000000111761357706137100217760ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.Signal: class Signal -- control and sense external I/O devices ====================================================== The Signal class is a simple extension of the `Pin` class. Unlike Pin, which can be only in "absolute" 0 and 1 states, a Signal can be in "asserted" (on) or "deasserted" (off) states, while being inverted (active-low) or not. In other words, it adds logical inversion support to Pin functionality. While this may seem a simple addition, it is exactly what is needed to support wide array of simple digital devices in a way portable across different boards, which is one of the major MicroPython goals. Regardless of whether different users have an active-high or active-low LED, a normally open or normally closed relay - you can develop a single, nicely looking application which works with each of them, and capture hardware configuration differences in few lines in the config file of your app. Example:: from machine import Pin, Signal # Suppose you have an active-high LED on pin 0 led1_pin = Pin(0, Pin.OUT) # ... and active-low LED on pin 1 led2_pin = Pin(1, Pin.OUT) # Now to light up both of them using Pin class, you'll need to set # them to different values led1_pin.value(1) led2_pin.value(0) # Signal class allows to abstract away active-high/active-low # difference led1 = Signal(led1_pin, invert=False) led2 = Signal(led2_pin, invert=True) # Now lighting up them looks the same led1.value(1) led2.value(1) # Even better: led1.on() led2.on() Following is the guide when Signal vs Pin should be used: * Use Signal: If you want to control a simple on/off (including software PWM!) devices like LEDs, multi-segment indicators, relays, buzzers, or read simple binary sensors, like normally open or normally closed buttons, pulled high or low, Reed switches, moisture/flame detectors, etc. etc. Summing up, if you have a real physical device/sensor requiring GPIO access, you likely should use a Signal. * Use Pin: If you implement a higher-level protocol or bus to communicate with more complex devices. The split between Pin and Signal come from the usecases above and the architecture of MicroPython: Pin offers the lowest overhead, which may be important when bit-banging protocols. But Signal adds additional flexibility on top of Pin, at the cost of minor overhead (much smaller than if you implemented active-high vs active-low device differences in Python manually!). Also, Pin is a low-level object which needs to be implemented for each support board, while Signal is a high-level object which comes for free once Pin is implemented. If in doubt, give the Signal a try! Once again, it is offered to save developers from the need to handle unexciting differences like active-low vs active-high signals, and allow other users to share and enjoy your application, instead of being frustrated by the fact that it doesn't work for them simply because their LEDs or relays are wired in a slightly different way. Constructors ------------ .. class:: Signal(pin_obj, invert=False) Signal(pin_arguments..., \*, invert=False) Create a Signal object. There're two ways to create it: * By wrapping existing Pin object - universal method which works for any board. * By passing required Pin parameters directly to Signal constructor, skipping the need to create intermediate Pin object. Available on many, but not all boards. The arguments are: - ``pin_obj`` is existing Pin object. - ``pin_arguments`` are the same arguments as can be passed to Pin constructor. - ``invert`` - if True, the signal will be inverted (active low). Methods ------- .. method:: Signal.value([x]) This method allows to set and get the value of the signal, depending on whether the argument ``x`` is supplied or not. If the argument is omitted then this method gets the signal level, 1 meaning signal is asserted (active) and 0 - signal inactive. If the argument is supplied then this method sets the signal level. The argument ``x`` can be anything that converts to a boolean. If it converts to ``True``, the signal is active, otherwise it is inactive. Correspondence between signal being active and actual logic level on the underlying pin depends on whether signal is inverted (active-low) or not. For non-inverted signal, active status corresponds to logical 1, inactive - to logical 0. For inverted/active-low signal, active status corresponds to logical 0, while inactive - to logical 1. .. method:: Signal.on() Activate signal. .. method:: Signal.off() Deactivate signal. micropython-1.12/docs/library/machine.Timer.rst000066400000000000000000000036501357706137100216370ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.Timer: class Timer -- control hardware timers ====================================== Hardware timers deal with timing of periods and events. Timers are perhaps the most flexible and heterogeneous kind of hardware in MCUs and SoCs, differently greatly from a model to a model. MicroPython's Timer class defines a baseline operation of executing a callback with a given period (or once after some delay), and allow specific boards to define more non-standard behavior (which thus won't be portable to other boards). See discussion of :ref:`important constraints ` on Timer callbacks. .. note:: Memory can't be allocated inside irq handlers (an interrupt) and so exceptions raised within a handler don't give much information. See :func:`micropython.alloc_emergency_exception_buf` for how to get around this limitation. If you are using a WiPy board please refer to :ref:`machine.TimerWiPy ` instead of this class. Constructors ------------ .. class:: Timer(id, ...) Construct a new timer object of the given id. Id of -1 constructs a virtual timer (if supported by a board). Methods ------- .. method:: Timer.init(\*, mode=Timer.PERIODIC, period=-1, callback=None) Initialise the timer. Example:: tim.init(period=100) # periodic with 100ms period tim.init(mode=Timer.ONE_SHOT, period=1000) # one shot firing after 1000ms Keyword arguments: - ``mode`` can be one of: - ``Timer.ONE_SHOT`` - The timer runs once until the configured period of the channel expires. - ``Timer.PERIODIC`` - The timer runs periodically at the configured frequency of the channel. .. method:: Timer.deinit() Deinitialises the timer. Stops the timer, and disables the timer peripheral. Constants --------- .. data:: Timer.ONE_SHOT Timer.PERIODIC Timer operating mode. micropython-1.12/docs/library/machine.TimerWiPy.rst000066400000000000000000000133721357706137100224520ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.TimerWiPy: class TimerWiPy -- control hardware timers ========================================== .. note:: This class is a non-standard Timer implementation for the WiPy. It is available simply as ``machine.Timer`` on the WiPy but is named in the documentation below as ``machine.TimerWiPy`` to distinguish it from the more general :ref:`machine.Timer ` class. Hardware timers deal with timing of periods and events. Timers are perhaps the most flexible and heterogeneous kind of hardware in MCUs and SoCs, differently greatly from a model to a model. MicroPython's Timer class defines a baseline operation of executing a callback with a given period (or once after some delay), and allow specific boards to define more non-standard behavior (which thus won't be portable to other boards). See discussion of :ref:`important constraints ` on Timer callbacks. .. note:: Memory can't be allocated inside irq handlers (an interrupt) and so exceptions raised within a handler don't give much information. See :func:`micropython.alloc_emergency_exception_buf` for how to get around this limitation. Constructors ------------ .. class:: TimerWiPy(id, ...) Construct a new timer object of the given id. Id of -1 constructs a virtual timer (if supported by a board). Methods ------- .. method:: TimerWiPy.init(mode, \*, width=16) Initialise the timer. Example:: tim.init(Timer.PERIODIC) # periodic 16-bit timer tim.init(Timer.ONE_SHOT, width=32) # one shot 32-bit timer Keyword arguments: - ``mode`` can be one of: - ``TimerWiPy.ONE_SHOT`` - The timer runs once until the configured period of the channel expires. - ``TimerWiPy.PERIODIC`` - The timer runs periodically at the configured frequency of the channel. - ``TimerWiPy.PWM`` - Output a PWM signal on a pin. - ``width`` must be either 16 or 32 (bits). For really low frequencies < 5Hz (or large periods), 32-bit timers should be used. 32-bit mode is only available for ``ONE_SHOT`` AND ``PERIODIC`` modes. .. method:: TimerWiPy.deinit() Deinitialises the timer. Stops the timer, and disables the timer peripheral. .. method:: TimerWiPy.channel(channel, \**, freq, period, polarity=TimerWiPy.POSITIVE, duty_cycle=0) If only a channel identifier passed, then a previously initialized channel object is returned (or ``None`` if there is no previous channel). Otherwise, a TimerChannel object is initialized and returned. The operating mode is is the one configured to the Timer object that was used to create the channel. - ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``. If the width is 32-bit then it **must be** ``TIMER.A | TIMER.B``. Keyword only arguments: - ``freq`` sets the frequency in Hz. - ``period`` sets the period in microseconds. .. note:: Either ``freq`` or ``period`` must be given, never both. - ``polarity`` this is applicable for ``PWM``, and defines the polarity of the duty cycle - ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0.00-100.00). Since the WiPy doesn't support floating point numbers the duty cycle must be specified in the range 0-10000, where 10000 would represent 100.00, 5050 represents 50.50, and so on. .. note:: When the channel is in PWM mode, the corresponding pin is assigned automatically, therefore there's no need to assign the alternate function of the pin via the ``Pin`` class. The pins which support PWM functionality are the following: - ``GP24`` on Timer 0 channel A. - ``GP25`` on Timer 1 channel A. - ``GP9`` on Timer 2 channel B. - ``GP10`` on Timer 3 channel A. - ``GP11`` on Timer 3 channel B. class TimerChannel --- setup a channel for a timer ================================================== Timer channels are used to generate/capture a signal using a timer. TimerChannel objects are created using the Timer.channel() method. Methods ------- .. method:: timerchannel.irq(\*, trigger, priority=1, handler=None) The behavior of this callback is heavily dependent on the operating mode of the timer channel: - If mode is ``TimerWiPy.PERIODIC`` the callback is executed periodically with the configured frequency or period. - If mode is ``TimerWiPy.ONE_SHOT`` the callback is executed once when the configured timer expires. - If mode is ``TimerWiPy.PWM`` the callback is executed when reaching the duty cycle value. The accepted params are: - ``priority`` level of the interrupt. Can take values in the range 1-7. Higher values represent higher priorities. - ``handler`` is an optional function to be called when the interrupt is triggered. - ``trigger`` must be ``TimerWiPy.TIMEOUT`` when the operating mode is either ``TimerWiPy.PERIODIC`` or ``TimerWiPy.ONE_SHOT``. In the case that mode is ``TimerWiPy.PWM`` then trigger must be equal to ``TimerWiPy.MATCH``. Returns a callback object. .. method:: timerchannel.freq([value]) Get or set the timer channel frequency (in Hz). .. method:: timerchannel.period([value]) Get or set the timer channel period (in microseconds). .. method:: timerchannel.duty_cycle([value]) Get or set the duty cycle of the PWM signal. It's a percentage (0.00-100.00). Since the WiPy doesn't support floating point numbers the duty cycle must be specified in the range 0-10000, where 10000 would represent 100.00, 5050 represents 50.50, and so on. Constants --------- .. data:: TimerWiPy.ONE_SHOT .. data:: TimerWiPy.PERIODIC Timer operating mode. micropython-1.12/docs/library/machine.UART.rst000066400000000000000000000117531357706137100213350ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.UART: class UART -- duplex serial communication bus ============================================= UART implements the standard UART/USART duplex serial communications protocol. At the physical level it consists of 2 lines: RX and TX. The unit of communication is a character (not to be confused with a string character) which can be 8 or 9 bits wide. UART objects can be created and initialised using:: from machine import UART uart = UART(1, 9600) # init with given baudrate uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters Supported parameters differ on a board: Pyboard: Bits can be 7, 8 or 9. Stop can be 1 or 2. With *parity=None*, only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits are supported. WiPy/CC3200: Bits can be 5, 6, 7, 8. Stop can be 1 or 2. A UART object acts like a `stream` object and reading and writing is done using the standard stream methods:: uart.read(10) # read 10 characters, returns a bytes object uart.read() # read all available characters uart.readline() # read a line uart.readinto(buf) # read and store into the given buffer uart.write('abc') # write the 3 characters Constructors ------------ .. class:: UART(id, ...) Construct a UART object of the given id. Methods ------- .. method:: UART.init(baudrate=9600, bits=8, parity=None, stop=1, \*, ...) Initialise the UART bus with the given parameters: - *baudrate* is the clock rate. - *bits* is the number of bits per character, 7, 8 or 9. - *parity* is the parity, ``None``, 0 (even) or 1 (odd). - *stop* is the number of stop bits, 1 or 2. Additional keyword-only parameters that may be supported by a port are: - *tx* specifies the TX pin to use. - *rx* specifies the RX pin to use. - *txbuf* specifies the length in characters of the TX buffer. - *rxbuf* specifies the length in characters of the RX buffer. On the WiPy only the following keyword-only parameter is supported: - *pins* is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order). Any of the pins can be None if one wants the UART to operate with limited functionality. If the RTS pin is given the the RX pin must be given as well. The same applies to CTS. When no pins are given, then the default set of TX and RX pins is taken, and hardware flow control will be disabled. If *pins* is ``None``, no pin assignment will be made. .. method:: UART.deinit() Turn off the UART bus. .. method:: UART.any() Returns an integer counting the number of characters that can be read without blocking. It will return 0 if there are no characters available and a positive number if there are characters. The method may return 1 even if there is more than one character available for reading. For more sophisticated querying of available characters use select.poll:: poll = select.poll() poll.register(uart, select.POLLIN) poll.poll(timeout) .. method:: UART.read([nbytes]) Read characters. If ``nbytes`` is specified then read at most that many bytes, otherwise read as much data as possible. Return value: a bytes object containing the bytes read in. Returns ``None`` on timeout. .. method:: UART.readinto(buf[, nbytes]) Read bytes into the ``buf``. If ``nbytes`` is specified then read at most that many bytes. Otherwise, read at most ``len(buf)`` bytes. Return value: number of bytes read and stored into ``buf`` or ``None`` on timeout. .. method:: UART.readline() Read a line, ending in a newline character. Return value: the line read or ``None`` on timeout. .. method:: UART.write(buf) Write the buffer of bytes to the bus. Return value: number of bytes written or ``None`` on timeout. .. method:: UART.sendbreak() Send a break condition on the bus. This drives the bus low for a duration longer than required for a normal transmission of a character. .. method:: UART.irq(trigger, priority=1, handler=None, wake=machine.IDLE) Create a callback to be triggered when data is received on the UART. - *trigger* can only be ``UART.RX_ANY`` - *priority* level of the interrupt. Can take values in the range 1-7. Higher values represent higher priorities. - *handler* an optional function to be called when new characters arrive. - *wake* can only be ``machine.IDLE``. .. note:: The handler will be called whenever any of the following two conditions are met: - 8 new characters have been received. - At least 1 new character is waiting in the Rx buffer and the Rx line has been silent for the duration of 1 complete frame. This means that when the handler function is called there will be between 1 to 8 characters waiting. Returns an irq object. Availability: WiPy. Constants --------- .. data:: UART.RX_ANY IRQ trigger sources Availability: WiPy. micropython-1.12/docs/library/machine.WDT.rst000066400000000000000000000021171357706137100212120ustar00rootroot00000000000000.. currentmodule:: machine .. _machine.WDT: class WDT -- watchdog timer =========================== The WDT is used to restart the system when the application crashes and ends up into a non recoverable state. Once started it cannot be stopped or reconfigured in any way. After enabling, the application must "feed" the watchdog periodically to prevent it from expiring and resetting the system. Example usage:: from machine import WDT wdt = WDT(timeout=2000) # enable it with a timeout of 2s wdt.feed() Availability of this class: pyboard, WiPy. Constructors ------------ .. class:: WDT(id=0, timeout=5000) Create a WDT object and start it. The timeout must be given in seconds and the minimum value that is accepted is 1 second. Once it is running the timeout cannot be changed and the WDT cannot be stopped either. Methods ------- .. method:: wdt.feed() Feed the WDT to prevent it from resetting the system. The application should place this call in a sensible place ensuring that the WDT is only fed after verifying that everything is functioning correctly. micropython-1.12/docs/library/machine.rst000066400000000000000000000131301357706137100205520ustar00rootroot00000000000000:mod:`machine` --- functions related to the hardware ==================================================== .. module:: machine :synopsis: functions related to the hardware The ``machine`` module contains specific functions related to the hardware on a particular board. Most functions in this module allow to achieve direct and unrestricted access to and control of hardware blocks on a system (like CPU, timers, buses, etc.). Used incorrectly, this can lead to malfunction, lockups, crashes of your board, and in extreme cases, hardware damage. .. _machine_callbacks: A note of callbacks used by functions and class methods of :mod:`machine` module: all these callbacks should be considered as executing in an interrupt context. This is true for both physical devices with IDs >= 0 and "virtual" devices with negative IDs like -1 (these "virtual" devices are still thin shims on top of real hardware and real hardware interrupts). See :ref:`isr_rules`. Reset related functions ----------------------- .. function:: reset() Resets the device in a manner similar to pushing the external RESET button. .. function:: reset_cause() Get the reset cause. See :ref:`constants ` for the possible return values. Interrupt related functions --------------------------- .. function:: disable_irq() Disable interrupt requests. Returns the previous IRQ state which should be considered an opaque value. This return value should be passed to the `enable_irq()` function to restore interrupts to their original state, before `disable_irq()` was called. .. function:: enable_irq(state) Re-enable interrupt requests. The *state* parameter should be the value that was returned from the most recent call to the `disable_irq()` function. Power related functions ----------------------- .. function:: freq() Returns CPU frequency in hertz. .. function:: idle() Gates the clock to the CPU, useful to reduce power consumption at any time during short or long periods. Peripherals continue working and execution resumes as soon as any interrupt is triggered (on many ports this includes system timer interrupt occurring at regular intervals on the order of millisecond). .. function:: sleep() .. note:: This function is deprecated, use `lightsleep()` instead with no arguments. .. function:: lightsleep([time_ms]) deepsleep([time_ms]) Stops execution in an attempt to enter a low power state. If *time_ms* is specified then this will be the maximum time in milliseconds that the sleep will last for. Otherwise the sleep can last indefinitely. With or without a timout, execution may resume at any time if there are events that require processing. Such events, or wake sources, should be configured before sleeping, like `Pin` change or `RTC` timeout. The precise behaviour and power-saving capabilities of lightsleep and deepsleep is highly dependent on the underlying hardware, but the general properties are: * A lightsleep has full RAM and state retention. Upon wake execution is resumed from the point where the sleep was requested, with all subsystems operational. * A deepsleep may not retain RAM or any other state of the system (for example peripherals or network interfaces). Upon wake execution is resumed from the main script, similar to a hard or power-on reset. The `reset_cause()` function will return `machine.DEEPSLEEP` and this can be used to distinguish a deepsleep wake from other resets. .. function:: wake_reason() Get the wake reason. See :ref:`constants ` for the possible return values. Availability: ESP32, WiPy. Miscellaneous functions ----------------------- .. function:: unique_id() Returns a byte string with a unique identifier of a board/SoC. It will vary from a board/SoC instance to another, if underlying hardware allows. Length varies by hardware (so use substring of a full value if you expect a short ID). In some MicroPython ports, ID corresponds to the network MAC address. .. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000) Time a pulse on the given *pin*, and return the duration of the pulse in microseconds. The *pulse_level* argument should be 0 to time a low pulse or 1 to time a high pulse. If the current input value of the pin is different to *pulse_level*, the function first (*) waits until the pin input becomes equal to *pulse_level*, then (**) times the duration that the pin is equal to *pulse_level*. If the pin is already equal to *pulse_level* then timing starts straight away. The function will return -2 if there was timeout waiting for condition marked (*) above, and -1 if there was timeout during the main measurement, marked (**) above. The timeout is the same for both cases and given by *timeout_us* (which is in microseconds). .. function:: rng() Return a 24-bit software generated random number. Availability: WiPy. .. _machine_constants: Constants --------- .. data:: machine.IDLE machine.SLEEP machine.DEEPSLEEP IRQ wake values. .. data:: machine.PWRON_RESET machine.HARD_RESET machine.WDT_RESET machine.DEEPSLEEP_RESET machine.SOFT_RESET Reset causes. .. data:: machine.WLAN_WAKE machine.PIN_WAKE machine.RTC_WAKE Wake-up reasons. Classes ------- .. toctree:: :maxdepth: 1 machine.Pin.rst machine.Signal.rst machine.ADC.rst machine.UART.rst machine.SPI.rst machine.I2C.rst machine.RTC.rst machine.Timer.rst machine.WDT.rst machine.SD.rst machine.SDCard.rst micropython-1.12/docs/library/math.rst000066400000000000000000000066601357706137100201110ustar00rootroot00000000000000:mod:`math` -- mathematical functions ===================================== .. module:: math :synopsis: mathematical functions |see_cpython_module| :mod:`python:math`. The ``math`` module provides some basic mathematical functions for working with floating-point numbers. *Note:* On the pyboard, floating-point numbers have 32-bit precision. Availability: not available on WiPy. Floating point support required for this module. Functions --------- .. function:: acos(x) Return the inverse cosine of ``x``. .. function:: acosh(x) Return the inverse hyperbolic cosine of ``x``. .. function:: asin(x) Return the inverse sine of ``x``. .. function:: asinh(x) Return the inverse hyperbolic sine of ``x``. .. function:: atan(x) Return the inverse tangent of ``x``. .. function:: atan2(y, x) Return the principal value of the inverse tangent of ``y/x``. .. function:: atanh(x) Return the inverse hyperbolic tangent of ``x``. .. function:: ceil(x) Return an integer, being ``x`` rounded towards positive infinity. .. function:: copysign(x, y) Return ``x`` with the sign of ``y``. .. function:: cos(x) Return the cosine of ``x``. .. function:: cosh(x) Return the hyperbolic cosine of ``x``. .. function:: degrees(x) Return radians ``x`` converted to degrees. .. function:: erf(x) Return the error function of ``x``. .. function:: erfc(x) Return the complementary error function of ``x``. .. function:: exp(x) Return the exponential of ``x``. .. function:: expm1(x) Return ``exp(x) - 1``. .. function:: fabs(x) Return the absolute value of ``x``. .. function:: floor(x) Return an integer, being ``x`` rounded towards negative infinity. .. function:: fmod(x, y) Return the remainder of ``x/y``. .. function:: frexp(x) Decomposes a floating-point number into its mantissa and exponent. The returned value is the tuple ``(m, e)`` such that ``x == m * 2**e`` exactly. If ``x == 0`` then the function returns ``(0.0, 0)``, otherwise the relation ``0.5 <= abs(m) < 1`` holds. .. function:: gamma(x) Return the gamma function of ``x``. .. function:: isfinite(x) Return ``True`` if ``x`` is finite. .. function:: isinf(x) Return ``True`` if ``x`` is infinite. .. function:: isnan(x) Return ``True`` if ``x`` is not-a-number .. function:: ldexp(x, exp) Return ``x * (2**exp)``. .. function:: lgamma(x) Return the natural logarithm of the gamma function of ``x``. .. function:: log(x) Return the natural logarithm of ``x``. .. function:: log10(x) Return the base-10 logarithm of ``x``. .. function:: log2(x) Return the base-2 logarithm of ``x``. .. function:: modf(x) Return a tuple of two floats, being the fractional and integral parts of ``x``. Both return values have the same sign as ``x``. .. function:: pow(x, y) Returns ``x`` to the power of ``y``. .. function:: radians(x) Return degrees ``x`` converted to radians. .. function:: sin(x) Return the sine of ``x``. .. function:: sinh(x) Return the hyperbolic sine of ``x``. .. function:: sqrt(x) Return the square root of ``x``. .. function:: tan(x) Return the tangent of ``x``. .. function:: tanh(x) Return the hyperbolic tangent of ``x``. .. function:: trunc(x) Return an integer, being ``x`` rounded towards 0. Constants --------- .. data:: e base of the natural logarithm .. data:: pi the ratio of a circle's circumference to its diameter micropython-1.12/docs/library/micropython.rst000066400000000000000000000143571357706137100215350ustar00rootroot00000000000000:mod:`micropython` -- access and control MicroPython internals ============================================================== .. module:: micropython :synopsis: access and control MicroPython internals Functions --------- .. function:: const(expr) Used to declare that the expression is a constant so that the compile can optimise it. The use of this function should be as follows:: from micropython import const CONST_X = const(123) CONST_Y = const(2 * CONST_X + 1) Constants declared this way are still accessible as global variables from outside the module they are declared in. On the other hand, if a constant begins with an underscore then it is hidden, it is not available as a global variable, and does not take up any memory during execution. This `const` function is recognised directly by the MicroPython parser and is provided as part of the :mod:`micropython` module mainly so that scripts can be written which run under both CPython and MicroPython, by following the above pattern. .. function:: opt_level([level]) If *level* is given then this function sets the optimisation level for subsequent compilation of scripts, and returns ``None``. Otherwise it returns the current optimisation level. The optimisation level controls the following compilation features: - Assertions: at level 0 assertion statements are enabled and compiled into the bytecode; at levels 1 and higher assertions are not compiled. - Built-in ``__debug__`` variable: at level 0 this variable expands to ``True``; at levels 1 and higher it expands to ``False``. - Source-code line numbers: at levels 0, 1 and 2 source-code line number are stored along with the bytecode so that exceptions can report the line number they occurred at; at levels 3 and higher line numbers are not stored. The default optimisation level is usually level 0. .. function:: alloc_emergency_exception_buf(size) Allocate *size* bytes of RAM for the emergency exception buffer (a good size is around 100 bytes). The buffer is used to create exceptions in cases when normal RAM allocation would fail (eg within an interrupt handler) and therefore give useful traceback information in these situations. A good way to use this function is to put it at the start of your main script (eg ``boot.py`` or ``main.py``) and then the emergency exception buffer will be active for all the code following it. .. function:: mem_info([verbose]) Print information about currently used memory. If the *verbose* argument is given then extra information is printed. The information that is printed is implementation dependent, but currently includes the amount of stack and heap used. In verbose mode it prints out the entire heap indicating which blocks are used and which are free. .. function:: qstr_info([verbose]) Print information about currently interned strings. If the *verbose* argument is given then extra information is printed. The information that is printed is implementation dependent, but currently includes the number of interned strings and the amount of RAM they use. In verbose mode it prints out the names of all RAM-interned strings. .. function:: stack_use() Return an integer representing the current amount of stack that is being used. The absolute value of this is not particularly useful, rather it should be used to compute differences in stack usage at different points. .. function:: heap_lock() .. function:: heap_unlock() Lock or unlock the heap. When locked no memory allocation can occur and a `MemoryError` will be raised if any heap allocation is attempted. These functions can be nested, ie `heap_lock()` can be called multiple times in a row and the lock-depth will increase, and then `heap_unlock()` must be called the same number of times to make the heap available again. If the REPL becomes active with the heap locked then it will be forcefully unlocked. .. function:: kbd_intr(chr) Set the character that will raise a `KeyboardInterrupt` exception. By default this is set to 3 during script execution, corresponding to Ctrl-C. Passing -1 to this function will disable capture of Ctrl-C, and passing 3 will restore it. This function can be used to prevent the capturing of Ctrl-C on the incoming stream of characters that is usually used for the REPL, in case that stream is used for other purposes. .. function:: schedule(func, arg) Schedule the function *func* to be executed "very soon". The function is passed the value *arg* as its single argument. "Very soon" means that the MicroPython runtime will do its best to execute the function at the earliest possible time, given that it is also trying to be efficient, and that the following conditions hold: - A scheduled function will never preempt another scheduled function. - Scheduled functions are always executed "between opcodes" which means that all fundamental Python operations (such as appending to a list) are guaranteed to be atomic. - A given port may define "critical regions" within which scheduled functions will never be executed. Functions may be scheduled within a critical region but they will not be executed until that region is exited. An example of a critical region is a preempting interrupt handler (an IRQ). A use for this function is to schedule a callback from a preempting IRQ. Such an IRQ puts restrictions on the code that runs in the IRQ (for example the heap may be locked) and scheduling a function to call later will lift those restrictions. Note: If `schedule()` is called from a preempting IRQ, when memory allocation is not allowed and the callback to be passed to `schedule()` is a bound method, passing this directly will fail. This is because creating a reference to a bound method causes memory allocation. A solution is to create a reference to the method in the class constructor and to pass that reference to `schedule()`. This is discussed in detail here :ref:`reference documentation ` under "Creation of Python objects". There is a finite queue to hold the scheduled functions and `schedule()` will raise a `RuntimeError` if the queue is full. micropython-1.12/docs/library/network.CC3K.rst000066400000000000000000000047721357706137100213350ustar00rootroot00000000000000.. currentmodule:: network .. _network.CC3K: class CC3K -- control CC3000 WiFi modules ========================================= This class provides a driver for CC3000 WiFi modules. Example usage:: import network nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) nic.connect('your-ssid', 'your-password') while not nic.isconnected(): pyb.delay(50) print(nic.ifconfig()) # now use socket as usual ... For this example to work the CC3000 module must have the following connections: - MOSI connected to Y8 - MISO connected to Y7 - CLK connected to Y6 - CS connected to Y5 - VBEN connected to Y4 - IRQ connected to Y3 It is possible to use other SPI busses and other pins for CS, VBEN and IRQ. Constructors ------------ .. class:: CC3K(spi, pin_cs, pin_en, pin_irq) Create a CC3K driver object, initialise the CC3000 module using the given SPI bus and pins, and return the CC3K object. Arguments are: - *spi* is an :ref:`SPI object ` which is the SPI bus that the CC3000 is connected to (the MOSI, MISO and CLK pins). - *pin_cs* is a :ref:`Pin object ` which is connected to the CC3000 CS pin. - *pin_en* is a :ref:`Pin object ` which is connected to the CC3000 VBEN pin. - *pin_irq* is a :ref:`Pin object ` which is connected to the CC3000 IRQ pin. All of these objects will be initialised by the driver, so there is no need to initialise them yourself. For example, you can use:: nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) Methods ------- .. method:: CC3K.connect(ssid, key=None, \*, security=WPA2, bssid=None) Connect to a WiFi access point using the given SSID, and other security parameters. .. method:: CC3K.disconnect() Disconnect from the WiFi access point. .. method:: CC3K.isconnected() Returns True if connected to a WiFi access point and has a valid IP address, False otherwise. .. method:: CC3K.ifconfig() Returns a 7-tuple with (ip, subnet mask, gateway, DNS server, DHCP server, MAC address, SSID). .. method:: CC3K.patch_version() Return the version of the patch program (firmware) on the CC3000. .. method:: CC3K.patch_program('pgm') Upload the current firmware to the CC3000. You must pass 'pgm' as the first argument in order for the upload to proceed. Constants --------- .. data:: CC3K.WEP .. data:: CC3K.WPA .. data:: CC3K.WPA2 security type to use micropython-1.12/docs/library/network.WIZNET5K.rst000066400000000000000000000043231357706137100220620ustar00rootroot00000000000000.. currentmodule:: network .. _network.WIZNET5K: class WIZNET5K -- control WIZnet5x00 Ethernet modules ===================================================== This class allows you to control WIZnet5x00 Ethernet adaptors based on the W5200 and W5500 chipsets. The particular chipset that is supported by the firmware is selected at compile-time via the MICROPY_PY_WIZNET5K option. Example usage:: import network nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) print(nic.ifconfig()) # now use socket as usual ... For this example to work the WIZnet5x00 module must have the following connections: - MOSI connected to X8 - MISO connected to X7 - SCLK connected to X6 - nSS connected to X5 - nRESET connected to X4 It is possible to use other SPI busses and other pins for nSS and nRESET. Constructors ------------ .. class:: WIZNET5K(spi, pin_cs, pin_rst) Create a WIZNET5K driver object, initialise the WIZnet5x00 module using the given SPI bus and pins, and return the WIZNET5K object. Arguments are: - *spi* is an :ref:`SPI object ` which is the SPI bus that the WIZnet5x00 is connected to (the MOSI, MISO and SCLK pins). - *pin_cs* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nSS pin. - *pin_rst* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nRESET pin. All of these objects will be initialised by the driver, so there is no need to initialise them yourself. For example, you can use:: nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) Methods ------- .. method:: WIZNET5K.isconnected() Returns ``True`` if the physical Ethernet link is connected and up. Returns ``False`` otherwise. .. method:: WIZNET5K.ifconfig([(ip, subnet, gateway, dns)]) Get/set IP address, subnet mask, gateway and DNS. When called with no arguments, this method returns a 4-tuple with the above information. To set the above values, pass a 4-tuple with the required information. For example:: nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) .. method:: WIZNET5K.regs() Dump the WIZnet5x00 registers. Useful for debugging. micropython-1.12/docs/library/network.WLAN.rst000066400000000000000000000115471357706137100214110ustar00rootroot00000000000000.. currentmodule:: network .. _network.WLAN: class WLAN -- control built-in WiFi interfaces ============================================== This class provides a driver for WiFi network processors. Example usage:: import network # enable station interface and connect to WiFi access point nic = network.WLAN(network.STA_IF) nic.active(True) nic.connect('your-ssid', 'your-password') # now use sockets as usual Constructors ------------ .. class:: WLAN(interface_id) Create a WLAN network interface object. Supported interfaces are ``network.STA_IF`` (station aka client, connects to upstream WiFi access points) and ``network.AP_IF`` (access point, allows other WiFi clients to connect). Availability of the methods below depends on interface type. For example, only STA interface may `WLAN.connect()` to an access point. Methods ------- .. method:: WLAN.active([is_active]) Activate ("up") or deactivate ("down") network interface, if boolean argument is passed. Otherwise, query current state if no argument is provided. Most other methods require active interface. .. method:: WLAN.connect(ssid=None, password=None, \*, bssid=None) Connect to the specified wireless network, using the specified password. If *bssid* is given then the connection will be restricted to the access-point with that MAC address (the *ssid* must also be specified in this case). .. method:: WLAN.disconnect() Disconnect from the currently connected wireless network. .. method:: WLAN.scan() Scan for the available wireless networks. Scanning is only possible on STA interface. Returns list of tuples with the information about WiFi access points: (ssid, bssid, channel, RSSI, authmode, hidden) *bssid* is hardware address of an access point, in binary form, returned as bytes object. You can use `ubinascii.hexlify()` to convert it to ASCII form. There are five values for authmode: * 0 -- open * 1 -- WEP * 2 -- WPA-PSK * 3 -- WPA2-PSK * 4 -- WPA/WPA2-PSK and two for hidden: * 0 -- visible * 1 -- hidden .. method:: WLAN.status([param]) Return the current status of the wireless connection. When called with no argument the return value describes the network link status. The possible statuses are defined as constants: * ``STAT_IDLE`` -- no connection and no activity, * ``STAT_CONNECTING`` -- connecting in progress, * ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password, * ``STAT_NO_AP_FOUND`` -- failed because no access point replied, * ``STAT_CONNECT_FAIL`` -- failed due to other problems, * ``STAT_GOT_IP`` -- connection successful. When called with one argument *param* should be a string naming the status parameter to retrieve. Supported parameters in WiFI STA mode are: ``'rssi'``. .. method:: WLAN.isconnected() In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address. In AP mode returns ``True`` when a station is connected. Returns ``False`` otherwise. .. method:: WLAN.ifconfig([(ip, subnet, gateway, dns)]) Get/set IP-level network interface parameters: IP address, subnet mask, gateway and DNS server. When called with no arguments, this method returns a 4-tuple with the above information. To set the above values, pass a 4-tuple with the required information. For example:: nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) .. method:: WLAN.config('param') .. method:: WLAN.config(param=value, ...) Get or set general network interface parameters. These methods allow to work with additional parameters beyond standard IP configuration (as dealt with by `WLAN.ifconfig()`). These include network-specific and hardware-specific parameters. For setting parameters, keyword argument syntax should be used, multiple parameters can be set at once. For querying, parameters name should be quoted as a string, and only one parameter can be queries at time:: # Set WiFi access point name (formally known as ESSID) and WiFi channel ap.config(essid='My AP', channel=11) # Query params one by one print(ap.config('essid')) print(ap.config('channel')) Following are commonly supported parameters (availability of a specific parameter depends on network technology type, driver, and `MicroPython port`). ============= =========== Parameter Description ============= =========== mac MAC address (bytes) essid WiFi access point name (string) channel WiFi channel (integer) hidden Whether ESSID is hidden (boolean) authmode Authentication mode supported (enumeration, see module constants) password Access password (string) dhcp_hostname The DHCP hostname to use ============= =========== micropython-1.12/docs/library/network.WLANWiPy.rst000066400000000000000000000122721357706137100222160ustar00rootroot00000000000000.. currentmodule:: network .. _network.WLANWiPy: class WLANWiPy -- WiPy specific WiFi control ============================================ .. note:: This class is a non-standard WLAN implementation for the WiPy. It is available simply as ``network.WLAN`` on the WiPy but is named in the documentation below as ``network.WLANWiPy`` to distinguish it from the more general :ref:`network.WLAN ` class. This class provides a driver for the WiFi network processor in the WiPy. Example usage:: import network import time # setup as a station wlan = network.WLAN(mode=WLAN.STA) wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key')) while not wlan.isconnected(): time.sleep_ms(50) print(wlan.ifconfig()) # now use socket as usual ... Constructors ------------ .. class:: WLANWiPy(id=0, ...) Create a WLAN object, and optionally configure it. See `init()` for params of configuration. .. note:: The ``WLAN`` constructor is special in the sense that if no arguments besides the id are given, it will return the already existing ``WLAN`` instance without re-configuring it. This is because ``WLAN`` is a system feature of the WiPy. If the already existing instance is not initialized it will do the same as the other constructors an will initialize it with default values. Methods ------- .. method:: WLANWiPy.init(mode, \*, ssid, auth, channel, antenna) Set or get the WiFi network processor configuration. Arguments are: - *mode* can be either ``WLAN.STA`` or ``WLAN.AP``. - *ssid* is a string with the ssid name. Only needed when mode is ``WLAN.AP``. - *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``, ``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password. If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal values (e.g. 'ABC1DE45BF'). Only needed when mode is ``WLAN.AP``. - *channel* a number in the range 1-11. Only needed when mode is ``WLAN.AP``. - *antenna* selects between the internal and the external antenna. Can be either ``WLAN.INT_ANT`` or ``WLAN.EXT_ANT``. For example, you can do:: # create and configure as an access point wlan.init(mode=WLAN.AP, ssid='wipy-wlan', auth=(WLAN.WPA2,'www.wipy.io'), channel=7, antenna=WLAN.INT_ANT) or:: # configure as an station wlan.init(mode=WLAN.STA) .. method:: WLANWiPy.connect(ssid, \*, auth=None, bssid=None, timeout=None) Connect to a WiFi access point using the given SSID, and other security parameters. - *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``, ``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password. If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal values (e.g. 'ABC1DE45BF'). - *bssid* is the MAC address of the AP to connect to. Useful when there are several APs with the same ssid. - *timeout* is the maximum time in milliseconds to wait for the connection to succeed. .. method:: WLANWiPy.scan() Performs a network scan and returns a list of named tuples with (ssid, bssid, sec, channel, rssi). Note that channel is always ``None`` since this info is not provided by the WiPy. .. method:: WLANWiPy.disconnect() Disconnect from the WiFi access point. .. method:: WLANWiPy.isconnected() In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address. In AP mode returns ``True`` when a station is connected, ``False`` otherwise. .. method:: WLANWiPy.ifconfig(if_id=0, config=['dhcp' or configtuple]) With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*. if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params are negotiated with the AP. If the 4-tuple config is given then a static IP is configured. For instance:: wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) .. method:: WLANWiPy.mode([mode]) Get or set the WLAN mode. .. method:: WLANWiPy.ssid([ssid]) Get or set the SSID when in AP mode. .. method:: WLANWiPy.auth([auth]) Get or set the authentication type when in AP mode. .. method:: WLANWiPy.channel([channel]) Get or set the channel (only applicable in AP mode). .. method:: WLANWiPy.antenna([antenna]) Get or set the antenna type (external or internal). .. method:: WLANWiPy.mac([mac_addr]) Get or set a 6-byte long bytes object with the MAC address. .. method:: WLANWiPy.irq(\*, handler, wake) Create a callback to be triggered when a WLAN event occurs during ``machine.SLEEP`` mode. Events are triggered by socket activity or by WLAN connection/disconnection. - *handler* is the function that gets called when the IRQ is triggered. - *wake* must be ``machine.SLEEP``. Returns an IRQ object. Constants --------- .. data:: WLANWiPy.STA .. data:: WLANWiPy.AP selects the WLAN mode .. data:: WLANWiPy.WEP .. data:: WLANWiPy.WPA .. data:: WLANWiPy.WPA2 selects the network security .. data:: WLANWiPy.INT_ANT .. data:: WLANWiPy.EXT_ANT selects the antenna type micropython-1.12/docs/library/network.rst000066400000000000000000000153131357706137100206440ustar00rootroot00000000000000**************************************** :mod:`network` --- network configuration **************************************** .. module:: network :synopsis: network configuration This module provides network drivers and routing configuration. To use this module, a MicroPython variant/build with network capabilities must be installed. Network drivers for specific hardware are available within this module and are used to configure hardware network interface(s). Network services provided by configured interfaces are then available for use via the :mod:`usocket` module. For example:: # connect/ show IP config a specific network interface # see below for examples of specific drivers import network import utime nic = network.Driver(...) if not nic.isconnected(): nic.connect() print("Waiting for connection...") while not nic.isconnected(): utime.sleep(1) print(nic.ifconfig()) # now use usocket as usual import usocket as socket addr = socket.getaddrinfo('micropython.org', 80)[0][-1] s = socket.socket() s.connect(addr) s.send(b'GET / HTTP/1.1\r\nHost: micropython.org\r\n\r\n') data = s.recv(1000) s.close() Common network adapter interface ================================ This section describes an (implied) abstract base class for all network interface classes implemented by `MicroPython ports ` for different hardware. This means that MicroPython does not actually provide ``AbstractNIC`` class, but any actual NIC class, as described in the following sections, implements methods as described here. .. class:: AbstractNIC(id=None, ...) Instantiate a network interface object. Parameters are network interface dependent. If there are more than one interface of the same type, the first parameter should be `id`. .. method:: AbstractNIC.active([is_active]) Activate ("up") or deactivate ("down") the network interface, if a boolean argument is passed. Otherwise, query current state if no argument is provided. Most other methods require an active interface (behavior of calling them on inactive interface is undefined). .. method:: AbstractNIC.connect([service_id, key=None, \*, ...]) Connect the interface to a network. This method is optional, and available only for interfaces which are not "always connected". If no parameters are given, connect to the default (or the only) service. If a single parameter is given, it is the primary identifier of a service to connect to. It may be accompanied by a key (password) required to access said service. There can be further arbitrary keyword-only parameters, depending on the networking medium type and/or particular device. Parameters can be used to: a) specify alternative service identifier types; b) provide additional connection parameters. For various medium types, there are different sets of predefined/recommended parameters, among them: * WiFi: *bssid* keyword to connect to a specific BSSID (MAC address) .. method:: AbstractNIC.disconnect() Disconnect from network. .. method:: AbstractNIC.isconnected() Returns ``True`` if connected to network, otherwise returns ``False``. .. method:: AbstractNIC.scan(\*, ...) Scan for the available network services/connections. Returns a list of tuples with discovered service parameters. For various network media, there are different variants of predefined/ recommended tuple formats, among them: * WiFi: (ssid, bssid, channel, RSSI, authmode, hidden). There may be further fields, specific to a particular device. The function may accept additional keyword arguments to filter scan results (e.g. scan for a particular service, on a particular channel, for services of a particular set, etc.), and to affect scan duration and other parameters. Where possible, parameter names should match those in connect(). .. method:: AbstractNIC.status([param]) Query dynamic status information of the interface. When called with no argument the return value describes the network link status. Otherwise *param* should be a string naming the particular status parameter to retrieve. The return types and values are dependent on the network medium/technology. Some of the parameters that may be supported are: * WiFi STA: use ``'rssi'`` to retrieve the RSSI of the AP signal * WiFi AP: use ``'stations'`` to retrieve a list of all the STAs connected to the AP. The list contains tuples of the form (MAC, RSSI). .. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)]) Get/set IP-level network interface parameters: IP address, subnet mask, gateway and DNS server. When called with no arguments, this method returns a 4-tuple with the above information. To set the above values, pass a 4-tuple with the required information. For example:: nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) .. method:: AbstractNIC.config('param') AbstractNIC.config(param=value, ...) Get or set general network interface parameters. These methods allow to work with additional parameters beyond standard IP configuration (as dealt with by `ifconfig()`). These include network-specific and hardware-specific parameters. For setting parameters, the keyword argument syntax should be used, and multiple parameters can be set at once. For querying, a parameter name should be quoted as a string, and only one parameter can be queried at a time:: # Set WiFi access point name (formally known as ESSID) and WiFi channel ap.config(essid='My AP', channel=11) # Query params one by one print(ap.config('essid')) print(ap.config('channel')) Specific network class implementations ====================================== The following concrete classes implement the AbstractNIC interface and provide a way to control networking interfaces of various kinds. .. toctree:: :maxdepth: 1 network.WLAN.rst network.WLANWiPy.rst network.CC3K.rst network.WIZNET5K.rst Network functions ================= The following are functions available in the network module. .. function:: phy_mode([mode]) Get or set the PHY mode. If the *mode* parameter is provided, sets the mode to its value. If the function is called without parameters, returns the current mode. The possible modes are defined as constants: * ``MODE_11B`` -- IEEE 802.11b, * ``MODE_11G`` -- IEEE 802.11g, * ``MODE_11N`` -- IEEE 802.11n. Availability: ESP8266. micropython-1.12/docs/library/pyb.ADC.rst000066400000000000000000000176361357706137100203450ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.ADC: class ADC -- analog to digital conversion ========================================= Usage:: import pyb adc = pyb.ADC(pin) # create an analog object from a pin val = adc.read() # read an analog value adc = pyb.ADCAll(resolution) # create an ADCAll object adc = pyb.ADCAll(resolution, mask) # create an ADCAll object for selected analog channels val = adc.read_channel(channel) # read the given channel val = adc.read_core_temp() # read MCU temperature val = adc.read_core_vbat() # read MCU VBAT val = adc.read_core_vref() # read MCU VREF val = adc.read_vref() # read MCU supply voltage Constructors ------------ .. class:: pyb.ADC(pin) Create an ADC object associated with the given pin. This allows you to then read analog values on that pin. Methods ------- .. method:: ADC.read() Read the value on the analog pin and return it. The returned value will be between 0 and 4095. .. method:: ADC.read_timed(buf, timer) Read analog values into ``buf`` at a rate set by the ``timer`` object. ``buf`` can be bytearray or array.array for example. The ADC values have 12-bit resolution and are stored directly into ``buf`` if its element size is 16 bits or greater. If ``buf`` has only 8-bit elements (eg a bytearray) then the sample resolution will be reduced to 8 bits. ``timer`` should be a Timer object, and a sample is read each time the timer triggers. The timer must already be initialised and running at the desired sampling frequency. To support previous behaviour of this function, ``timer`` can also be an integer which specifies the frequency (in Hz) to sample at. In this case Timer(6) will be automatically configured to run at the given frequency. Example using a Timer object (preferred way):: adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 tim = pyb.Timer(6, freq=10) # create a timer running at 10Hz buf = bytearray(100) # creat a buffer to store the samples adc.read_timed(buf, tim) # sample 100 values, taking 10s Example using an integer for the frequency:: adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 buf = bytearray(100) # create a buffer of 100 bytes adc.read_timed(buf, 10) # read analog values into buf at 10Hz # this will take 10 seconds to finish for val in buf: # loop over all values print(val) # print the value out This function does not allocate any heap memory. It has blocking behaviour: it does not return to the calling program until the buffer is full. .. method:: ADC.read_timed_multi((adcx, adcy, ...), (bufx, bufy, ...), timer) This is a static method. It can be used to extract relative timing or phase data from multiple ADC's. It reads analog values from multiple ADC's into buffers at a rate set by the *timer* object. Each time the timer triggers a sample is rapidly read from each ADC in turn. ADC and buffer instances are passed in tuples with each ADC having an associated buffer. All buffers must be of the same type and length and the number of buffers must equal the number of ADC's. Buffers can be ``bytearray`` or ``array.array`` for example. The ADC values have 12-bit resolution and are stored directly into the buffer if its element size is 16 bits or greater. If buffers have only 8-bit elements (eg a ``bytearray``) then the sample resolution will be reduced to 8 bits. *timer* must be a Timer object. The timer must already be initialised and running at the desired sampling frequency. Example reading 3 ADC's:: adc0 = pyb.ADC(pyb.Pin.board.X1) # Create ADC's adc1 = pyb.ADC(pyb.Pin.board.X2) adc2 = pyb.ADC(pyb.Pin.board.X3) tim = pyb.Timer(8, freq=100) # Create timer rx0 = array.array('H', (0 for i in range(100))) # ADC buffers of rx1 = array.array('H', (0 for i in range(100))) # 100 16-bit words rx2 = array.array('H', (0 for i in range(100))) # read analog values into buffers at 100Hz (takes one second) pyb.ADC.read_timed_multi((adc0, adc1, adc2), (rx0, rx1, rx2), tim) for n in range(len(rx0)): print(rx0[n], rx1[n], rx2[n]) This function does not allocate any heap memory. It has blocking behaviour: it does not return to the calling program until the buffers are full. The function returns ``True`` if all samples were acquired with correct timing. At high sample rates the time taken to acquire a set of samples can exceed the timer period. In this case the function returns ``False``, indicating a loss of precision in the sample interval. In extreme cases samples may be missed. The maximum rate depends on factors including the data width and the number of ADC's being read. In testing two ADC's were sampled at a timer rate of 210kHz without overrun. Samples were missed at 215kHz. For three ADC's the limit is around 140kHz, and for four it is around 110kHz. At high sample rates disabling interrupts for the duration can reduce the risk of sporadic data loss. The ADCAll Object ----------------- Instantiating this changes all masked ADC pins to analog inputs. The preprocessed MCU temperature, VREF and VBAT data can be accessed on ADC channels 16, 17 and 18 respectively. Appropriate scaling is handled according to reference voltage used (usually 3.3V). The temperature sensor on the chip is factory calibrated and allows to read the die temperature to +/- 1 degree centigrade. Although this sounds pretty accurate, don't forget that the MCU's internal temperature is measured. Depending on processing loads and I/O subsystems active the die temperature may easily be tens of degrees above ambient temperature. On the other hand a pyboard woken up after a long standby period will show correct ambient temperature within limits mentioned above. The ``ADCAll`` ``read_core_vbat()``, ``read_vref()`` and ``read_core_vref()`` methods read the backup battery voltage, reference voltage and the (1.21V nominal) reference voltage using the actual supply as a reference. All results are floating point numbers giving direct voltage values. ``read_core_vbat()`` returns the voltage of the backup battery. This voltage is also adjusted according to the actual supply voltage. To avoid analog input overload the battery voltage is measured via a voltage divider and scaled according to the divider value. To prevent excessive loads to the backup battery, the voltage divider is only active during ADC conversion. ``read_vref()`` is evaluated by measuring the internal voltage reference and backscale it using factory calibration value of the internal voltage reference. In most cases the reading would be close to 3.3V. If the pyboard is operated from a battery, the supply voltage may drop to values below 3.3V. The pyboard will still operate fine as long as the operating conditions are met. With proper settings of MCU clock, flash access speed and programming mode it is possible to run the pyboard down to 2 V and still get useful ADC conversion. It is very important to make sure analog input voltages never exceed actual supply voltage. Other analog input channels (0..15) will return unscaled integer values according to the selected precision. To avoid unwanted activation of analog inputs (channel 0..15) a second parameter can be specified. This parameter is a binary pattern where each requested analog input has the corresponding bit set. The default value is 0xffffffff which means all analog inputs are active. If just the internal channels (16..18) are required, the mask value should be 0x70000. Example:: adcall = pyb.ADCAll(12, 0x70000) # 12 bit resolution, internal channels temp = adcall.read_core_temp() micropython-1.12/docs/library/pyb.Accel.rst000066400000000000000000000024721357706137100207550ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.Accel: class Accel -- accelerometer control ==================================== Accel is an object that controls the accelerometer. Example usage:: accel = pyb.Accel() for i in range(10): print(accel.x(), accel.y(), accel.z()) Raw values are between -32 and 31. Constructors ------------ .. class:: pyb.Accel() Create and return an accelerometer object. Methods ------- .. method:: Accel.filtered_xyz() Get a 3-tuple of filtered x, y and z values. Implementation note: this method is currently implemented as taking the sum of 4 samples, sampled from the 3 previous calls to this function along with the sample from the current call. Returned values are therefore 4 times the size of what they would be from the raw x(), y() and z() calls. .. method:: Accel.tilt() Get the tilt register. .. method:: Accel.x() Get the x-axis value. .. method:: Accel.y() Get the y-axis value. .. method:: Accel.z() Get the z-axis value. Hardware Note ------------- The accelerometer uses I2C bus 1 to communicate with the processor. Consequently when readings are being taken pins X9 and X10 should be unused (other than for I2C). Other devices using those pins, and which therefore cannot be used concurrently, are UART 1 and Timer 4 channels 1 and 2. micropython-1.12/docs/library/pyb.CAN.rst000066400000000000000000000304451357706137100203500ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.CAN: class CAN -- controller area network communication bus ====================================================== CAN implements the standard CAN communications protocol. At the physical level it consists of 2 lines: RX and TX. Note that to connect the pyboard to a CAN bus you must use a CAN transceiver to convert the CAN logic signals from the pyboard to the correct voltage levels on the bus. Example usage (works without anything connected):: from pyb import CAN can = CAN(1, CAN.LOOPBACK) can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126 can.send('message!', 123) # send a message with id 123 can.recv(0) # receive message on FIFO 0 Constructors ------------ .. class:: pyb.CAN(bus, ...) Construct a CAN object on the given bus. *bus* can be 1-2, or ``'YA'`` or ``'YB'``. With no additional parameters, the CAN object is created but not initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. See :meth:`CAN.init` for parameters of initialisation. The physical pins of the CAN busses are: - ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)`` - ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)`` Class Methods ------------- .. classmethod:: CAN.initfilterbanks(nr) Reset and disable all filter banks and assign how many banks should be available for CAN(1). STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers. This function configures how many filter banks should be assigned to each. *nr* is the number of banks that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2). At boot, 14 banks are assigned to each controller. Methods ------- .. method:: CAN.init(mode, extframe=False, prescaler=100, \*, sjw=1, bs1=6, bs2=8, auto_restart=False) Initialise the CAN bus with the given parameters: - *mode* is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK - if *extframe* is True then the bus uses extended identifiers in the frames (29 bits); otherwise it uses standard 11 bit identifiers - *prescaler* is used to set the duration of 1 time quanta; the time quanta will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler - *sjw* is the resynchronisation jump width in units of the time quanta; it can be 1, 2, 3, 4 - *bs1* defines the location of the sample point in units of the time quanta; it can be between 1 and 1024 inclusive - *bs2* defines the location of the transmit point in units of the time quanta; it can be between 1 and 16 inclusive - *auto_restart* sets whether the controller will automatically try and restart communications after entering the bus-off state; if this is disabled then :meth:`~CAN.restart()` can be used to leave the bus-off state The time quanta tq is the basic unit of time for the CAN bus. tq is the CAN prescaler value divided by PCLK1 (the frequency of internal peripheral bus 1); see :meth:`pyb.freq()` to determine PCLK1. A single bit is made up of the synchronisation segment, which is always 1 tq. Then follows bit segment 1, then bit segment 2. The sample point is after bit segment 1 finishes. The transmit point is after bit segment 2 finishes. The baud rate will be 1/bittime, where the bittime is 1 + BS1 + BS2 multiplied by the time quanta tq. For example, with PCLK1=42MHz, prescaler=100, sjw=1, bs1=6, bs2=8, the value of tq is 2.38 microseconds. The bittime is 35.7 microseconds, and the baudrate is 28kHz. See page 680 of the STM32F405 datasheet for more details. .. method:: CAN.deinit() Turn off the CAN bus. .. method:: CAN.restart() Force a software restart of the CAN controller without resetting its configuration. If the controller enters the bus-off state then it will no longer participate in bus activity. If the controller is not configured to automatically restart (see :meth:`~CAN.init()`) then this method can be used to trigger a restart, and the controller will follow the CAN protocol to leave the bus-off state and go into the error active state. .. method:: CAN.state() Return the state of the controller. The return value can be one of: - ``CAN.STOPPED`` -- the controller is completely off and reset; - ``CAN.ERROR_ACTIVE`` -- the controller is on and in the Error Active state (both TEC and REC are less than 96); - ``CAN.ERROR_WARNING`` -- the controller is on and in the Error Warning state (at least one of TEC or REC is 96 or greater); - ``CAN.ERROR_PASSIVE`` -- the controller is on and in the Error Passive state (at least one of TEC or REC is 128 or greater); - ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity (TEC overflowed beyond 255). .. method:: CAN.info([list]) Get information about the controller's error states and TX and RX buffers. If *list* is provided then it should be a list object with at least 8 entries, which will be filled in with the information. Otherwise a new list will be created and filled in. In both cases the return value of the method is the populated list. The values in the list are: - TEC value - REC value - number of times the controller enterted the Error Warning state (wrapped around to 0 after 65535) - number of times the controller enterted the Error Passive state (wrapped around to 0 after 65535) - number of times the controller enterted the Bus Off state (wrapped around to 0 after 65535) - number of pending TX messages - number of pending RX messages on fifo 0 - number of pending RX messages on fifo 1 .. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) Configure a filter bank: - *bank* is the filter bank that is to be configured. - *mode* is the mode the filter should operate in. - *fifo* is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter. - *params* is an array of values the defines the filter. The contents of the array depends on the *mode* argument. +-----------+---------------------------------------------------------+ |*mode* |contents of *params* array | +===========+=========================================================+ |CAN.LIST16 |Four 16 bit ids that will be accepted | +-----------+---------------------------------------------------------+ |CAN.LIST32 |Two 32 bit ids that will be accepted | +-----------+---------------------------------------------------------+ |CAN.MASK16 |Two 16 bit id/mask pairs. E.g. (1, 3, 4, 4) | | | | The first pair, 1 and 3 will accept all ids | | | | that have bit 0 = 1 and bit 1 = 0. | | | | The second pair, 4 and 4, will accept all ids | | | | that have bit 2 = 1. | +-----------+---------------------------------------------------------+ |CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.| +-----------+---------------------------------------------------------+ - *rtr* is an array of booleans that states if a filter should accept a remote transmission request message. If this argument is not given then it defaults to ``False`` for all entries. The length of the array depends on the *mode* argument. +-----------+----------------------+ |*mode* |length of *rtr* array | +===========+======================+ |CAN.LIST16 |4 | +-----------+----------------------+ |CAN.LIST32 |2 | +-----------+----------------------+ |CAN.MASK16 |2 | +-----------+----------------------+ |CAN.MASK32 |1 | +-----------+----------------------+ .. method:: CAN.clearfilter(bank) Clear and disables a filter bank: - *bank* is the filter bank that is to be cleared. .. method:: CAN.any(fifo) Return ``True`` if any message waiting on the FIFO, else ``False``. .. method:: CAN.recv(fifo, list=None, \*, timeout=5000) Receive data on the bus: - *fifo* is an integer, which is the FIFO to receive on - *list* is an optional list object to be used as the return value - *timeout* is the timeout in milliseconds to wait for the receive. Return value: A tuple containing four values. - The id of the message. - A boolean that indicates if the message is an RTR message. - The FMI (Filter Match Index) value. - An array containing the data. If *list* is ``None`` then a new tuple will be allocated, as well as a new bytes object to contain the data (as the fourth element in the tuple). If *list* is not ``None`` then it should be a list object with a least four elements. The fourth element should be a memoryview object which is created from either a bytearray or an array of type 'B' or 'b', and this array must have enough room for at least 8 bytes. The list object will then be populated with the first three return values above, and the memoryview object will be resized inplace to the size of the data and filled in with that data. The same list and memoryview objects can be reused in subsequent calls to this method, providing a way of receiving data without using the heap. For example:: buf = bytearray(8) lst = [0, 0, 0, memoryview(buf)] # No heap memory is allocated in the following call can.recv(0, lst) .. method:: CAN.send(data, id, \*, timeout=0, rtr=False) Send a message on the bus: - *data* is the data to send (an integer to send, or a buffer object). - *id* is the id of the message to be sent. - *timeout* is the timeout in milliseconds to wait for the send. - *rtr* is a boolean that specifies if the message shall be sent as a remote transmission request. If *rtr* is True then only the length of *data* is used to fill in the DLC slot of the frame; the actual bytes in *data* are unused. If timeout is 0 the message is placed in a buffer in one of three hardware buffers and the method returns immediately. If all three buffers are in use an exception is thrown. If timeout is not 0, the method waits until the message is transmitted. If the message can't be transmitted within the specified time an exception is thrown. Return value: ``None``. .. method:: CAN.rxcallback(fifo, fun) Register a function to be called when a message is accepted into a empty fifo: - *fifo* is the receiving fifo. - *fun* is the function to be called when the fifo becomes non empty. The callback function takes two arguments the first is the can object it self the second is a integer that indicates the reason for the callback. +--------+------------------------------------------------+ | Reason | | +========+================================================+ | 0 | A message has been accepted into a empty FIFO. | +--------+------------------------------------------------+ | 1 | The FIFO is full | +--------+------------------------------------------------+ | 2 | A message has been lost due to a full FIFO | +--------+------------------------------------------------+ Example use of rxcallback:: def cb0(bus, reason): print('cb0') if reason == 0: print('pending') if reason == 1: print('full') if reason == 2: print('overflow') can = CAN(1, CAN.LOOPBACK) can.rxcallback(0, cb0) Constants --------- .. data:: CAN.NORMAL CAN.LOOPBACK CAN.SILENT CAN.SILENT_LOOPBACK The mode of the CAN bus used in :meth:`~CAN.init()`. .. data:: CAN.STOPPED CAN.ERROR_ACTIVE CAN.ERROR_WARNING CAN.ERROR_PASSIVE CAN.BUS_OFF Possible states of the CAN controller returned from :meth:`~CAN.state()`. .. data:: CAN.LIST16 CAN.MASK16 CAN.LIST32 CAN.MASK32 The operation mode of a filter used in :meth:`~CAN.setfilter()`. micropython-1.12/docs/library/pyb.DAC.rst000066400000000000000000000101621357706137100203300ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.DAC: class DAC -- digital to analog conversion ========================================= The DAC is used to output analog values (a specific voltage) on pin X5 or pin X6. The voltage will be between 0 and 3.3V. *This module will undergo changes to the API.* Example usage:: from pyb import DAC dac = DAC(1) # create DAC 1 on pin X5 dac.write(128) # write a value to the DAC (makes X5 1.65V) dac = DAC(1, bits=12) # use 12 bit resolution dac.write(4095) # output maximum value, 3.3V To output a continuous sine-wave:: import math from pyb import DAC # create a buffer containing a sine-wave buf = bytearray(100) for i in range(len(buf)): buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf))) # output the sine-wave at 400Hz dac = DAC(1) dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) To output a continuous sine-wave at 12-bit resolution:: import math from array import array from pyb import DAC # create a buffer containing a sine-wave, using half-word samples buf = array('H', 2048 + int(2047 * math.sin(2 * math.pi * i / 128)) for i in range(128)) # output the sine-wave at 400Hz dac = DAC(1, bits=12) dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) Constructors ------------ .. class:: pyb.DAC(port, bits=8, \*, buffering=None) Construct a new DAC object. ``port`` can be a pin object, or an integer (1 or 2). DAC(1) is on pin X5 and DAC(2) is on pin X6. ``bits`` is an integer specifying the resolution, and can be 8 or 12. The maximum value for the write and write_timed methods will be 2\*\*``bits``-1. The *buffering* parameter selects the behaviour of the DAC op-amp output buffer, whose purpose is to reduce the output impedance. It can be ``None`` to select the default (buffering enabled for :meth:`DAC.noise`, :meth:`DAC.triangle` and :meth:`DAC.write_timed`, and disabled for :meth:`DAC.write`), ``False`` to disable buffering completely, or ``True`` to enable output buffering. When buffering is enabled the DAC pin can drive loads down to 5KΩ. Otherwise it has an output impedance of 15KΩ maximum: consequently to achieve a 1% accuracy without buffering requires the applied load to be less than 1.5MΩ. Using the buffer incurs a penalty in accuracy, especially near the extremes of range. Methods ------- .. method:: DAC.init(bits=8, \*, buffering=None) Reinitialise the DAC. *bits* can be 8 or 12. *buffering* can be ``None``, ``False`` or ``True``; see above constructor for the meaning of this parameter. .. method:: DAC.deinit() De-initialise the DAC making its pin available for other uses. .. method:: DAC.noise(freq) Generate a pseudo-random noise signal. A new random sample is written to the DAC output at the given frequency. .. method:: DAC.triangle(freq) Generate a triangle wave. The value on the DAC output changes at the given frequency and ramps through the full 12-bit range (up and down). Therefore the frequency of the repeating triangle wave itself is 8192 times smaller. .. method:: DAC.write(value) Direct access to the DAC output. The minimum value is 0. The maximum value is 2\*\*``bits``-1, where ``bits`` is set when creating the DAC object or by using the ``init`` method. .. method:: DAC.write_timed(data, freq, \*, mode=DAC.NORMAL) Initiates a burst of RAM to DAC using a DMA transfer. The input data is treated as an array of bytes in 8-bit mode, and an array of unsigned half-words (array typecode 'H') in 12-bit mode. ``freq`` can be an integer specifying the frequency to write the DAC samples at, using Timer(6). Or it can be an already-initialised Timer object which is used to trigger the DAC sample. Valid timers are 2, 4, 5, 6, 7 and 8. ``mode`` can be ``DAC.NORMAL`` or ``DAC.CIRCULAR``. Example using both DACs at the same time:: dac1 = DAC(1) dac2 = DAC(2) dac1.write_timed(buf1, pyb.Timer(6, freq=100), mode=DAC.CIRCULAR) dac2.write_timed(buf2, pyb.Timer(7, freq=200), mode=DAC.CIRCULAR) micropython-1.12/docs/library/pyb.ExtInt.rst000066400000000000000000000066351357706137100211660ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.ExtInt: class ExtInt -- configure I/O pins to interrupt on external events ================================================================== There are a total of 22 interrupt lines. 16 of these can come from GPIO pins and the remaining 6 are from internal sources. For lines 0 through 15, a given line can map to the corresponding line from an arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and line 1 can map to Px1 where x is A, B, C, ... :: def callback(line): print("line =", line) Note: ExtInt will automatically configure the gpio line as an input. :: extint = pyb.ExtInt(pin, pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, callback) Now every time a falling edge is seen on the X1 pin, the callback will be called. Caution: mechanical pushbuttons have "bounce" and pushing or releasing a switch will often generate multiple edges. See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed explanation, along with various techniques for debouncing. Trying to register 2 callbacks onto the same pin will throw an exception. If pin is passed as an integer, then it is assumed to map to one of the internal interrupt sources, and must be in the range 16 through 22. All other pin objects go through the pin mapper to come up with one of the gpio pins. :: extint = pyb.ExtInt(pin, mode, pull, callback) Valid modes are pyb.ExtInt.IRQ_RISING, pyb.ExtInt.IRQ_FALLING, pyb.ExtInt.IRQ_RISING_FALLING, pyb.ExtInt.EVT_RISING, pyb.ExtInt.EVT_FALLING, and pyb.ExtInt.EVT_RISING_FALLING. Only the IRQ_xxx modes have been tested. The EVT_xxx modes have something to do with sleep mode and the WFE instruction. Valid pull values are pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN, pyb.Pin.PULL_NONE. There is also a C API, so that drivers which require EXTI interrupt lines can also use this code. See extint.h for the available functions and usrsw.h for an example of using this. Constructors ------------ .. class:: pyb.ExtInt(pin, mode, pull, callback) Create an ExtInt object: - ``pin`` is the pin on which to enable the interrupt (can be a pin object or any valid pin name). - ``mode`` can be one of: - ``ExtInt.IRQ_RISING`` - trigger on a rising edge; - ``ExtInt.IRQ_FALLING`` - trigger on a falling edge; - ``ExtInt.IRQ_RISING_FALLING`` - trigger on a rising or falling edge. - ``pull`` can be one of: - ``pyb.Pin.PULL_NONE`` - no pull up or down resistors; - ``pyb.Pin.PULL_UP`` - enable the pull-up resistor; - ``pyb.Pin.PULL_DOWN`` - enable the pull-down resistor. - ``callback`` is the function to call when the interrupt triggers. The callback function must accept exactly 1 argument, which is the line that triggered the interrupt. Class methods ------------- .. classmethod:: ExtInt.regs() Dump the values of the EXTI registers. Methods ------- .. method:: ExtInt.disable() Disable the interrupt associated with the ExtInt object. This could be useful for debouncing. .. method:: ExtInt.enable() Enable a disabled interrupt. .. method:: ExtInt.line() Return the line number that the pin is mapped to. .. method:: ExtInt.swint() Trigger the callback from software. Constants --------- .. data:: ExtInt.IRQ_FALLING interrupt on a falling edge .. data:: ExtInt.IRQ_RISING interrupt on a rising edge .. data:: ExtInt.IRQ_RISING_FALLING interrupt on a rising or falling edge micropython-1.12/docs/library/pyb.Flash.rst000066400000000000000000000034771357706137100210110ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.Flash: class Flash -- access to built-in flash storage =============================================== The Flash class allows direct access to the primary flash device on the pyboard. In most cases, to store persistent data on the device, you'll want to use a higher-level abstraction, for example the filesystem via Python's standard file API, but this interface is useful to :ref:`customise the filesystem configuration ` or implement a low-level storage system for your application. Constructors ------------ .. class:: pyb.Flash() Create and return a block device that represents the flash device presented to the USB mass storage interface. It includes a virtual partition table at the start, and the actual flash starts at block ``0x100``. This constructor is deprecated and will be removed in a future version of MicroPython. .. class:: pyb.Flash(\*, start=-1, len=-1) Create and return a block device that accesses the flash at the specified offset. The length defaults to the remaining size of the device. The *start* and *len* offsets are in bytes, and must be a multiple of the block size (typically 512 for internal flash). Methods ------- .. method:: Flash.readblocks(block_num, buf) .. method:: Flash.readblocks(block_num, buf, offset) .. method:: Flash.writeblocks(block_num, buf) .. method:: Flash.writeblocks(block_num, buf, offset) .. method:: Flash.ioctl(cmd, arg) These methods implement the simple and :ref:`extended ` block protocol defined by :class:`uos.AbstractBlockDev`. Hardware Note ------------- On boards with external spiflash (e.g. Pyboard D), the MicroPython firmware will be configured to use that as the primary flash storage. On all other boards, the internal flash inside the :term:`MCU` will be used. micropython-1.12/docs/library/pyb.I2C.rst000066400000000000000000000134331357706137100203220ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.I2C: class I2C -- a two-wire serial protocol ======================================= I2C is a two-wire protocol for communicating between devices. At the physical level it consists of 2 wires: SCL and SDA, the clock and data lines respectively. I2C objects are created attached to a specific bus. They can be initialised when created, or initialised later on. Example:: from pyb import I2C i2c = I2C(1) # create on bus 1 i2c = I2C(1, I2C.MASTER) # create and init as a master i2c.init(I2C.MASTER, baudrate=20000) # init as a master i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address i2c.deinit() # turn off the peripheral Printing the i2c object gives you information about its configuration. The basic methods are send and recv:: i2c.send('abc') # send 3 bytes i2c.send(0x42) # send a single byte, given by the number data = i2c.recv(3) # receive 3 bytes To receive inplace, first create a bytearray:: data = bytearray(3) # create a buffer i2c.recv(data) # receive 3 bytes, writing them into data You can specify a timeout (in ms):: i2c.send(b'123', timeout=2000) # timeout after 2 seconds A master must specify the recipient's address:: i2c.init(I2C.MASTER) i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42 i2c.send(b'456', addr=0x42) # keyword for address Master also has other methods:: i2c.is_ready(0x42) # check if slave 0x42 is ready i2c.scan() # scan for slaves on the bus, returning # a list of valid addresses i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42, # starting at address 2 in the slave i2c.mem_write('abc', 0x42, 2, timeout=1000) # write 'abc' (3 bytes) to memory of slave 0x42 # starting at address 2 in the slave, timeout after 1 second Constructors ------------ .. class:: pyb.I2C(bus, ...) Construct an I2C object on the given bus. ``bus`` can be 1 or 2, 'X' or 'Y'. With no additional parameters, the I2C object is created but not initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. See ``init`` for parameters of initialisation. The physical pins of the I2C busses on Pyboards V1.0 and V1.1 are: - ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)`` - ``I2C(2)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PB10, PB11)`` On the Pyboard Lite: - ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)`` - ``I2C(3)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PA8, PB8)`` Calling the constructor with 'X' or 'Y' enables portability between Pyboard types. Methods ------- .. method:: I2C.deinit() Turn off the I2C bus. .. method:: I2C.init(mode, \*, addr=0x12, baudrate=400000, gencall=False, dma=False) Initialise the I2C bus with the given parameters: - ``mode`` must be either ``I2C.MASTER`` or ``I2C.SLAVE`` - ``addr`` is the 7-bit address (only sensible for a slave) - ``baudrate`` is the SCL clock rate (only sensible for a master) - ``gencall`` is whether to support general call mode - ``dma`` is whether to allow the use of DMA for the I2C transfers (note that DMA transfers have more precise timing but currently do not handle bus errors properly) .. method:: I2C.is_ready(addr) Check if an I2C device responds to the given address. Only valid when in master mode. .. method:: I2C.mem_read(data, addr, memaddr, \*, timeout=5000, addr_size=8) Read from the memory of an I2C device: - ``data`` can be an integer (number of bytes to read) or a buffer to read into - ``addr`` is the I2C device address - ``memaddr`` is the memory location within the I2C device - ``timeout`` is the timeout in milliseconds to wait for the read - ``addr_size`` selects width of memaddr: 8 or 16 bits Returns the read data. This is only valid in master mode. .. method:: I2C.mem_write(data, addr, memaddr, \*, timeout=5000, addr_size=8) Write to the memory of an I2C device: - ``data`` can be an integer or a buffer to write from - ``addr`` is the I2C device address - ``memaddr`` is the memory location within the I2C device - ``timeout`` is the timeout in milliseconds to wait for the write - ``addr_size`` selects width of memaddr: 8 or 16 bits Returns ``None``. This is only valid in master mode. .. method:: I2C.recv(recv, addr=0x00, \*, timeout=5000) Receive data on the bus: - ``recv`` can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with received bytes - ``addr`` is the address to receive from (only required in master mode) - ``timeout`` is the timeout in milliseconds to wait for the receive Return value: if ``recv`` is an integer then a new buffer of the bytes received, otherwise the same buffer that was passed in to ``recv``. .. method:: I2C.send(send, addr=0x00, \*, timeout=5000) Send data on the bus: - ``send`` is the data to send (an integer to send, or a buffer object) - ``addr`` is the address to send to (only required in master mode) - ``timeout`` is the timeout in milliseconds to wait for the send Return value: ``None``. .. method:: I2C.scan() Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. Only valid when in master mode. Constants --------- .. data:: I2C.MASTER for initialising the bus to master mode .. data:: I2C.SLAVE for initialising the bus to slave mode micropython-1.12/docs/library/pyb.LCD.rst000066400000000000000000000053661357706137100203550ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.LCD: class LCD -- LCD control for the LCD touch-sensor pyskin ======================================================== The LCD class is used to control the LCD on the LCD touch-sensor pyskin, LCD32MKv1.0. The LCD is a 128x32 pixel monochrome screen, part NHD-C12832A1Z. The pyskin must be connected in either the X or Y positions, and then an LCD object is made using:: lcd = pyb.LCD('X') # if pyskin is in the X position lcd = pyb.LCD('Y') # if pyskin is in the Y position Then you can use:: lcd.light(True) # turn the backlight on lcd.write('Hello world!\n') # print text to the screen This driver implements a double buffer for setting/getting pixels. For example, to make a bouncing dot, try:: x = y = 0 dx = dy = 1 while True: # update the dot's position x += dx y += dy # make the dot bounce of the edges of the screen if x <= 0 or x >= 127: dx = -dx if y <= 0 or y >= 31: dy = -dy lcd.fill(0) # clear the buffer lcd.pixel(x, y, 1) # draw the dot lcd.show() # show the buffer pyb.delay(50) # pause for 50ms Constructors ------------ .. class:: pyb.LCD(skin_position) Construct an LCD object in the given skin position. ``skin_position`` can be 'X' or 'Y', and should match the position where the LCD pyskin is plugged in. Methods ------- .. method:: LCD.command(instr_data, buf) Send an arbitrary command to the LCD. Pass 0 for ``instr_data`` to send an instruction, otherwise pass 1 to send data. ``buf`` is a buffer with the instructions/data to send. .. method:: LCD.contrast(value) Set the contrast of the LCD. Valid values are between 0 and 47. .. method:: LCD.fill(colour) Fill the screen with the given colour (0 or 1 for white or black). This method writes to the hidden buffer. Use ``show()`` to show the buffer. .. method:: LCD.get(x, y) Get the pixel at the position ``(x, y)``. Returns 0 or 1. This method reads from the visible buffer. .. method:: LCD.light(value) Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off. .. method:: LCD.pixel(x, y, colour) Set the pixel at ``(x, y)`` to the given colour (0 or 1). This method writes to the hidden buffer. Use ``show()`` to show the buffer. .. method:: LCD.show() Show the hidden buffer on the screen. .. method:: LCD.text(str, x, y, colour) Draw the given text to the position ``(x, y)`` using the given colour (0 or 1). This method writes to the hidden buffer. Use ``show()`` to show the buffer. .. method:: LCD.write(str) Write the string ``str`` to the screen. It will appear immediately. micropython-1.12/docs/library/pyb.LED.rst000066400000000000000000000022621357706137100203470ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.LED: class LED -- LED object ======================= The LED object controls an individual LED (Light Emitting Diode). Constructors ------------ .. class:: pyb.LED(id) Create an LED object associated with the given LED: - ``id`` is the LED number, 1-4. Methods ------- .. method:: LED.intensity([value]) Get or set the LED intensity. Intensity ranges between 0 (off) and 255 (full on). If no argument is given, return the LED intensity. If an argument is given, set the LED intensity and return ``None``. *Note:* Only LED(3) and LED(4) can have a smoothly varying intensity, and they use timer PWM to implement it. LED(3) uses Timer(2) and LED(4) uses Timer(3). These timers are only configured for PWM if the intensity of the relevant LED is set to a value between 1 and 254. Otherwise the timers are free for general purpose use. .. method:: LED.off() Turn the LED off. .. method:: LED.on() Turn the LED on, to maximum intensity. .. method:: LED.toggle() Toggle the LED between on (maximum intensity) and off. If the LED is at non-zero intensity then it is considered "on" and toggle will turn it off. micropython-1.12/docs/library/pyb.Pin.rst000066400000000000000000000161521357706137100204740ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.Pin: class Pin -- control I/O pins ============================= A pin is the basic object to control I/O pins. It has methods to set the mode of the pin (input, output, etc) and methods to get and set the digital logic level. For analog control of a pin, see the ADC class. Usage Model: All Board Pins are predefined as pyb.Pin.board.Name:: x1_pin = pyb.Pin.board.X1 g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN) CPU pins which correspond to the board pins are available as ``pyb.Pin.cpu.Name``. For the CPU pins, the names are the port letter followed by the pin number. On the PYBv1.0, ``pyb.Pin.board.X1`` and ``pyb.Pin.cpu.A0`` are the same pin. You can also use strings:: g = pyb.Pin('X1', pyb.Pin.OUT_PP) Users can add their own names:: MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 } pyb.Pin.dict(MyMapperDict) g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD) and can query mappings:: pin = pyb.Pin("LeftMotorDir") Users can also add their own mapping function:: def MyMapper(pin_name): if pin_name == "LeftMotorDir": return pyb.Pin.cpu.A0 pyb.Pin.mapper(MyMapper) So, if you were to call: ``pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)`` then ``"LeftMotorDir"`` is passed directly to the mapper function. To summarise, the following order determines how things get mapped into an ordinal pin number: 1. Directly specify a pin object 2. User supplied mapping function 3. User supplied mapping (object must be usable as a dictionary key) 4. Supply a string which matches a board pin 5. Supply a string which matches a CPU port/pin You can set ``pyb.Pin.debug(True)`` to get some debug information about how a particular object gets mapped to a pin. When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled, that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND respectively (except pin Y5 which has 11k Ohm resistors). Now every time a falling edge is seen on the gpio pin, the callback will be executed. Caution: mechanical push buttons have "bounce" and pushing or releasing a switch will often generate multiple edges. See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed explanation, along with various techniques for debouncing. All pin objects go through the pin mapper to come up with one of the gpio pins. Constructors ------------ .. class:: pyb.Pin(id, ...) Create a new Pin object associated with the id. If additional arguments are given, they are used to initialise the pin. See :meth:`pin.init`. Class methods ------------- .. classmethod:: Pin.debug([state]) Get or set the debugging state (``True`` or ``False`` for on or off). .. classmethod:: Pin.dict([dict]) Get or set the pin mapper dictionary. .. classmethod:: Pin.mapper([fun]) Get or set the pin mapper function. Methods ------- .. method:: Pin.init(mode, pull=Pin.PULL_NONE, af=-1) Initialise the pin: - ``mode`` can be one of: - ``Pin.IN`` - configure the pin for input; - ``Pin.OUT_PP`` - configure the pin for output, with push-pull control; - ``Pin.OUT_OD`` - configure the pin for output, with open-drain control; - ``Pin.AF_PP`` - configure the pin for alternate function, pull-pull; - ``Pin.AF_OD`` - configure the pin for alternate function, open-drain; - ``Pin.ANALOG`` - configure the pin for analog. - ``pull`` can be one of: - ``Pin.PULL_NONE`` - no pull up or down resistors; - ``Pin.PULL_UP`` - enable the pull-up resistor; - ``Pin.PULL_DOWN`` - enable the pull-down resistor. - when mode is ``Pin.AF_PP`` or ``Pin.AF_OD``, then af can be the index or name of one of the alternate functions associated with a pin. Returns: ``None``. .. method:: Pin.value([value]) Get or set the digital logic level of the pin: - With no argument, return 0 or 1 depending on the logic level of the pin. - With ``value`` given, set the logic level of the pin. ``value`` can be anything that converts to a boolean. If it converts to ``True``, the pin is set high, otherwise it is set low. .. method:: Pin.__str__() Return a string describing the pin object. .. method:: Pin.af() Returns the currently configured alternate-function of the pin. The integer returned will match one of the allowed constants for the af argument to the init function. .. method:: Pin.af_list() Returns an array of alternate functions available for this pin. .. method:: Pin.gpio() Returns the base address of the GPIO block associated with this pin. .. method:: Pin.mode() Returns the currently configured mode of the pin. The integer returned will match one of the allowed constants for the mode argument to the init function. .. method:: Pin.name() Get the pin name. .. method:: Pin.names() Returns the cpu and board names for this pin. .. method:: Pin.pin() Get the pin number. .. method:: Pin.port() Get the pin port. .. method:: Pin.pull() Returns the currently configured pull of the pin. The integer returned will match one of the allowed constants for the pull argument to the init function. Constants --------- .. data:: Pin.AF_OD initialise the pin to alternate-function mode with an open-drain drive .. data:: Pin.AF_PP initialise the pin to alternate-function mode with a push-pull drive .. data:: Pin.ANALOG initialise the pin to analog mode .. data:: Pin.IN initialise the pin to input mode .. data:: Pin.OUT_OD initialise the pin to output mode with an open-drain drive .. data:: Pin.OUT_PP initialise the pin to output mode with a push-pull drive .. data:: Pin.PULL_DOWN enable the pull-down resistor on the pin .. data:: Pin.PULL_NONE don't enable any pull up or down resistors on the pin .. data:: Pin.PULL_UP enable the pull-up resistor on the pin class PinAF -- Pin Alternate Functions ====================================== A Pin represents a physical pin on the microprocessor. Each pin can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF object represents a particular function for a pin. Usage Model:: x3 = pyb.Pin.board.X3 x3_af = x3.af_list() x3_af will now contain an array of PinAF objects which are available on pin X3. For the pyboard, x3_af would contain: [Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2] Normally, each peripheral would configure the af automatically, but sometimes the same function is available on multiple pins, and having more control is desired. To configure X3 to expose TIM2_CH3, you could use:: pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2) or:: pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1) Methods ------- .. method:: pinaf.__str__() Return a string describing the alternate function. .. method:: pinaf.index() Return the alternate function index. .. method:: pinaf.name() Return the name of the alternate function. .. method:: pinaf.reg() Return the base register associated with the peripheral assigned to this alternate function. For example, if the alternate function were TIM2_CH3 this would return stm.TIM2 micropython-1.12/docs/library/pyb.RTC.rst000066400000000000000000000043521357706137100203750ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.RTC: class RTC -- real time clock ============================ The RTC is and independent clock that keeps track of the date and time. Example usage:: rtc = pyb.RTC() rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0)) print(rtc.datetime()) Constructors ------------ .. class:: pyb.RTC() Create an RTC object. Methods ------- .. method:: RTC.datetime([datetimetuple]) Get or set the date and time of the RTC. With no arguments, this method returns an 8-tuple with the current date and time. With 1 argument (being an 8-tuple) it sets the date and time (and ``subseconds`` is reset to 255). The 8-tuple has the following format: (year, month, day, weekday, hours, minutes, seconds, subseconds) ``weekday`` is 1-7 for Monday through Sunday. ``subseconds`` counts down from 255 to 0 .. method:: RTC.wakeup(timeout, callback=None) Set the RTC wakeup timer to trigger repeatedly at every ``timeout`` milliseconds. This trigger can wake the pyboard from both the sleep states: :meth:`pyb.stop` and :meth:`pyb.standby`. If ``timeout`` is ``None`` then the wakeup timer is disabled. If ``callback`` is given then it is executed at every trigger of the wakeup timer. ``callback`` must take exactly one argument. .. method:: RTC.info() Get information about the startup time and reset source. - The lower 0xffff are the number of milliseconds the RTC took to start up. - Bit 0x10000 is set if a power-on reset occurred. - Bit 0x20000 is set if an external reset occurred .. method:: RTC.calibration(cal) Get or set RTC calibration. With no arguments, ``calibration()`` returns the current calibration value, which is an integer in the range [-511 : 512]. With one argument it sets the RTC calibration. The RTC Smooth Calibration mechanism adjusts the RTC clock rate by adding or subtracting the given number of ticks from the 32768 Hz clock over a 32 second period (corresponding to 2^20 clock ticks.) Each tick added will speed up the clock by 1 part in 2^20, or 0.954 ppm; likewise the RTC clock it slowed by negative values. The usable calibration range is: (-511 * 0.954) ~= -487.5 ppm up to (512 * 0.954) ~= 488.5 ppm micropython-1.12/docs/library/pyb.SPI.rst000066400000000000000000000107401357706137100203760ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.SPI: class SPI -- a master-driven serial protocol ============================================ SPI is a serial protocol that is driven by a master. At the physical level there are 3 lines: SCK, MOSI, MISO. See usage model of I2C; SPI is very similar. Main difference is parameters to init the SPI bus:: from pyb import SPI spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7) Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be 0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1 to sample data on the first or second clock edge respectively. Crc can be None for no CRC, or a polynomial specifier. Additional methods for SPI:: data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes buf = bytearray(4) spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf Constructors ------------ .. class:: pyb.SPI(bus, ...) Construct an SPI object on the given bus. ``bus`` can be 1 or 2, or 'X' or 'Y'. With no additional parameters, the SPI object is created but not initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. See ``init`` for parameters of initialisation. The physical pins of the SPI busses are: - ``SPI(1)`` is on the X position: ``(NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7)`` - ``SPI(2)`` is on the Y position: ``(NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)`` At the moment, the NSS pin is not used by the SPI driver and is free for other use. Methods ------- .. method:: SPI.deinit() Turn off the SPI bus. .. method:: SPI.init(mode, baudrate=328125, \*, prescaler, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) Initialise the SPI bus with the given parameters: - ``mode`` must be either ``SPI.MASTER`` or ``SPI.SLAVE``. - ``baudrate`` is the SCK clock rate (only sensible for a master). - ``prescaler`` is the prescaler to use to derive SCK from the APB bus frequency; use of ``prescaler`` overrides ``baudrate``. - ``polarity`` can be 0 or 1, and is the level the idle clock line sits at. - ``phase`` can be 0 or 1 to sample data on the first or second clock edge respectively. - ``bits`` can be 8 or 16, and is the number of bits in each transferred word. - ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``. - ``crc`` can be None for no CRC, or a polynomial specifier. Note that the SPI clock frequency will not always be the requested baudrate. The hardware only supports baudrates that are the APB bus frequency (see :meth:`pyb.freq`) divided by a prescaler, which can be 2, 4, 8, 16, 32, 64, 128 or 256. SPI(1) is on AHB2, and SPI(2) is on AHB1. For precise control over the SPI clock frequency, specify ``prescaler`` instead of ``baudrate``. Printing the SPI object will show you the computed baudrate and the chosen prescaler. .. method:: SPI.recv(recv, \*, timeout=5000) Receive data on the bus: - ``recv`` can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with received bytes. - ``timeout`` is the timeout in milliseconds to wait for the receive. Return value: if ``recv`` is an integer then a new buffer of the bytes received, otherwise the same buffer that was passed in to ``recv``. .. method:: SPI.send(send, \*, timeout=5000) Send data on the bus: - ``send`` is the data to send (an integer to send, or a buffer object). - ``timeout`` is the timeout in milliseconds to wait for the send. Return value: ``None``. .. method:: SPI.send_recv(send, recv=None, \*, timeout=5000) Send and receive data on the bus at the same time: - ``send`` is the data to send (an integer to send, or a buffer object). - ``recv`` is a mutable buffer which will be filled with received bytes. It can be the same as ``send``, or omitted. If omitted, a new buffer will be created. - ``timeout`` is the timeout in milliseconds to wait for the receive. Return value: the buffer with the received bytes. Constants --------- .. data:: SPI.MASTER .. data:: SPI.SLAVE for initialising the SPI bus to master or slave mode .. data:: SPI.LSB .. data:: SPI.MSB set the first bit to be the least or most significant bit micropython-1.12/docs/library/pyb.Servo.rst000066400000000000000000000052551357706137100210460ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.Servo: class Servo -- 3-wire hobby servo driver ======================================== Servo objects control standard hobby servo motors with 3-wires (ground, power, signal). There are 4 positions on the pyboard where these motors can be plugged in: pins X1 through X4 are the signal pins, and next to them are 4 sets of power and ground pins. Example usage:: import pyb s1 = pyb.Servo(1) # create a servo object on position X1 s2 = pyb.Servo(2) # create a servo object on position X2 s1.angle(45) # move servo 1 to 45 degrees s2.angle(0) # move servo 2 to 0 degrees # move servo1 and servo2 synchronously, taking 1500ms s1.angle(-60, 1500) s2.angle(30, 1500) .. note:: The Servo objects use Timer(5) to produce the PWM output. You can use Timer(5) for Servo control, or your own purposes, but not both at the same time. Constructors ------------ .. class:: pyb.Servo(id) Create a servo object. ``id`` is 1-4, and corresponds to pins X1 through X4. Methods ------- .. method:: Servo.angle([angle, time=0]) If no arguments are given, this function returns the current angle. If arguments are given, this function sets the angle of the servo: - ``angle`` is the angle to move to in degrees. - ``time`` is the number of milliseconds to take to get to the specified angle. If omitted, then the servo moves as quickly as possible to its new position. .. method:: Servo.speed([speed, time=0]) If no arguments are given, this function returns the current speed. If arguments are given, this function sets the speed of the servo: - ``speed`` is the speed to change to, between -100 and 100. - ``time`` is the number of milliseconds to take to get to the specified speed. If omitted, then the servo accelerates as quickly as possible. .. method:: Servo.pulse_width([value]) If no arguments are given, this function returns the current raw pulse-width value. If an argument is given, this function sets the raw pulse-width value. .. method:: Servo.calibration([pulse_min, pulse_max, pulse_centre, [pulse_angle_90, pulse_speed_100]]) If no arguments are given, this function returns the current calibration data, as a 5-tuple. If arguments are given, this function sets the timing calibration: - ``pulse_min`` is the minimum allowed pulse width. - ``pulse_max`` is the maximum allowed pulse width. - ``pulse_centre`` is the pulse width corresponding to the centre/zero position. - ``pulse_angle_90`` is the pulse width corresponding to 90 degrees. - ``pulse_speed_100`` is the pulse width corresponding to a speed of 100. micropython-1.12/docs/library/pyb.Switch.rst000066400000000000000000000021651357706137100212060ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.Switch: class Switch -- switch object ============================= A Switch object is used to control a push-button switch. Usage:: sw = pyb.Switch() # create a switch object sw.value() # get state (True if pressed, False otherwise) sw() # shorthand notation to get the switch state sw.callback(f) # register a callback to be called when the # switch is pressed down sw.callback(None) # remove the callback Example:: pyb.Switch().callback(lambda: pyb.LED(1).toggle()) Constructors ------------ .. class:: pyb.Switch() Create and return a switch object. Methods ------- .. method:: Switch.__call__() Call switch object directly to get its state: ``True`` if pressed down, ``False`` otherwise. .. method:: Switch.value() Get the switch state. Returns ``True`` if pressed down, otherwise ``False``. .. method:: Switch.callback(fun) Register the given function to be called when the switch is pressed down. If ``fun`` is ``None``, then it disables the callback. micropython-1.12/docs/library/pyb.Timer.rst000066400000000000000000000253421357706137100210270ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.Timer: class Timer -- control internal timers ====================================== Timers can be used for a great variety of tasks. At the moment, only the simplest case is implemented: that of calling a function periodically. Each timer consists of a counter that counts up at a certain rate. The rate at which it counts is the peripheral clock frequency (in Hz) divided by the timer prescaler. When the counter reaches the timer period it triggers an event, and the counter resets back to zero. By using the callback method, the timer event can call a Python function. Example usage to toggle an LED at a fixed frequency:: tim = pyb.Timer(4) # create a timer object using timer 4 tim.init(freq=2) # trigger at 2Hz tim.callback(lambda t:pyb.LED(1).toggle()) Example using named function for the callback:: def tick(timer): # we will receive the timer object when being called print(timer.counter()) # show current timer's counter value tim = pyb.Timer(4, freq=1) # create a timer object using timer 4 - trigger at 1Hz tim.callback(tick) # set the callback to our tick function Further examples:: tim = pyb.Timer(4, freq=100) # freq in Hz tim = pyb.Timer(4, prescaler=0, period=99) tim.counter() # get counter (can also set) tim.prescaler(2) # set prescaler (can also get) tim.period(199) # set period (can also get) tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance) tim.callback(None) # clear callback *Note:* Timer(2) and Timer(3) are used for PWM to set the intensity of LED(3) and LED(4) respectively. But these timers are only configured for PWM if the intensity of the relevant LED is set to a value between 1 and 254. If the intensity feature of the LEDs is not used then these timers are free for general purpose use. Similarly, Timer(5) controls the servo driver, and Timer(6) is used for timed ADC/DAC reading/writing. It is recommended to use the other timers in your programs. *Note:* Memory can't be allocated during a callback (an interrupt) and so exceptions raised within a callback don't give much information. See :func:`micropython.alloc_emergency_exception_buf` for how to get around this limitation. Constructors ------------ .. class:: pyb.Timer(id, ...) Construct a new timer object of the given id. If additional arguments are given, then the timer is initialised by ``init(...)``. ``id`` can be 1 to 14. Methods ------- .. method:: Timer.init(\*, freq, prescaler, period) Initialise the timer. Initialisation must be either by frequency (in Hz) or by prescaler and period:: tim.init(freq=100) # set the timer to trigger at 100Hz tim.init(prescaler=83, period=999) # set the prescaler and period directly Keyword arguments: - ``freq`` --- specifies the periodic frequency of the timer. You might also view this as the frequency with which the timer goes through one complete cycle. - ``prescaler`` [0-0xffff] - specifies the value to be loaded into the timer's Prescaler Register (PSC). The timer clock source is divided by (``prescaler + 1``) to arrive at the timer clock. Timers 2-7 and 12-14 have a clock source of 84 MHz (pyb.freq()[2] \* 2), and Timers 1, and 8-11 have a clock source of 168 MHz (pyb.freq()[3] \* 2). - ``period`` [0-0xffff] for timers 1, 3, 4, and 6-15. [0-0x3fffffff] for timers 2 & 5. Specifies the value to be loaded into the timer's AutoReload Register (ARR). This determines the period of the timer (i.e. when the counter cycles). The timer counter will roll-over after ``period + 1`` timer clock cycles. - ``mode`` can be one of: - ``Timer.UP`` - configures the timer to count from 0 to ARR (default) - ``Timer.DOWN`` - configures the timer to count from ARR down to 0. - ``Timer.CENTER`` - configures the timer to count from 0 to ARR and then back down to 0. - ``div`` can be one of 1, 2, or 4. Divides the timer clock to determine the sampling clock used by the digital filters. - ``callback`` - as per Timer.callback() - ``deadtime`` - specifies the amount of "dead" or inactive time between transitions on complimentary channels (both channels will be inactive) for this time). ``deadtime`` may be an integer between 0 and 1008, with the following restrictions: 0-128 in steps of 1. 128-256 in steps of 2, 256-512 in steps of 8, and 512-1008 in steps of 16. ``deadtime`` measures ticks of ``source_freq`` divided by ``div`` clock ticks. ``deadtime`` is only available on timers 1 and 8. You must either specify freq or both of period and prescaler. .. method:: Timer.deinit() Deinitialises the timer. Disables the callback (and the associated irq). Disables any channel callbacks (and the associated irq). Stops the timer, and disables the timer peripheral. .. method:: Timer.callback(fun) Set the function to be called when the timer triggers. ``fun`` is passed 1 argument, the timer object. If ``fun`` is ``None`` then the callback will be disabled. .. method:: Timer.channel(channel, mode, ...) If only a channel number is passed, then a previously initialized channel object is returned (or ``None`` if there is no previous channel). Otherwise, a TimerChannel object is initialized and returned. Each channel can be configured to perform pwm, output compare, or input capture. All channels share the same underlying timer, which means that they share the same timer clock. Keyword arguments: - ``mode`` can be one of: - ``Timer.PWM`` --- configure the timer in PWM mode (active high). - ``Timer.PWM_INVERTED`` --- configure the timer in PWM mode (active low). - ``Timer.OC_TIMING`` --- indicates that no pin is driven. - ``Timer.OC_ACTIVE`` --- the pin will be made active when a compare match occurs (active is determined by polarity) - ``Timer.OC_INACTIVE`` --- the pin will be made inactive when a compare match occurs. - ``Timer.OC_TOGGLE`` --- the pin will be toggled when an compare match occurs. - ``Timer.OC_FORCED_ACTIVE`` --- the pin is forced active (compare match is ignored). - ``Timer.OC_FORCED_INACTIVE`` --- the pin is forced inactive (compare match is ignored). - ``Timer.IC`` --- configure the timer in Input Capture mode. - ``Timer.ENC_A`` --- configure the timer in Encoder mode. The counter only changes when CH1 changes. - ``Timer.ENC_B`` --- configure the timer in Encoder mode. The counter only changes when CH2 changes. - ``Timer.ENC_AB`` --- configure the timer in Encoder mode. The counter changes when CH1 or CH2 changes. - ``callback`` - as per TimerChannel.callback() - ``pin`` None (the default) or a Pin object. If specified (and not None) this will cause the alternate function of the the indicated pin to be configured for this timer channel. An error will be raised if the pin doesn't support any alternate functions for this timer channel. Keyword arguments for Timer.PWM modes: - ``pulse_width`` - determines the initial pulse width value to use. - ``pulse_width_percent`` - determines the initial pulse width percentage to use. Keyword arguments for Timer.OC modes: - ``compare`` - determines the initial value of the compare register. - ``polarity`` can be one of: - ``Timer.HIGH`` - output is active high - ``Timer.LOW`` - output is active low Optional keyword arguments for Timer.IC modes: - ``polarity`` can be one of: - ``Timer.RISING`` - captures on rising edge. - ``Timer.FALLING`` - captures on falling edge. - ``Timer.BOTH`` - captures on both edges. Note that capture only works on the primary channel, and not on the complimentary channels. Notes for Timer.ENC modes: - Requires 2 pins, so one or both pins will need to be configured to use the appropriate timer AF using the Pin API. - Read the encoder value using the timer.counter() method. - Only works on CH1 and CH2 (and not on CH1N or CH2N) - The channel number is ignored when setting the encoder mode. PWM Example:: timer = pyb.Timer(2, freq=1000) ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.X2, pulse_width=8000) ch3 = timer.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width=16000) .. method:: Timer.counter([value]) Get or set the timer counter. .. method:: Timer.freq([value]) Get or set the frequency for the timer (changes prescaler and period if set). .. method:: Timer.period([value]) Get or set the period of the timer. .. method:: Timer.prescaler([value]) Get or set the prescaler for the timer. .. method:: Timer.source_freq() Get the frequency of the source of the timer. class TimerChannel --- setup a channel for a timer ================================================== Timer channels are used to generate/capture a signal using a timer. TimerChannel objects are created using the Timer.channel() method. Methods ------- .. method:: timerchannel.callback(fun) Set the function to be called when the timer channel triggers. ``fun`` is passed 1 argument, the timer object. If ``fun`` is ``None`` then the callback will be disabled. .. method:: timerchannel.capture([value]) Get or set the capture value associated with a channel. capture, compare, and pulse_width are all aliases for the same function. capture is the logical name to use when the channel is in input capture mode. .. method:: timerchannel.compare([value]) Get or set the compare value associated with a channel. capture, compare, and pulse_width are all aliases for the same function. compare is the logical name to use when the channel is in output compare mode. .. method:: timerchannel.pulse_width([value]) Get or set the pulse width value associated with a channel. capture, compare, and pulse_width are all aliases for the same function. pulse_width is the logical name to use when the channel is in PWM mode. In edge aligned mode, a pulse_width of ``period + 1`` corresponds to a duty cycle of 100% In center aligned mode, a pulse width of ``period`` corresponds to a duty cycle of 100% .. method:: timerchannel.pulse_width_percent([value]) Get or set the pulse width percentage associated with a channel. The value is a number between 0 and 100 and sets the percentage of the timer period for which the pulse is active. The value can be an integer or floating-point number for more accuracy. For example, a value of 25 gives a duty cycle of 25%. micropython-1.12/docs/library/pyb.UART.rst000066400000000000000000000216561357706137100205260ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.UART: class UART -- duplex serial communication bus ============================================= UART implements the standard UART/USART duplex serial communications protocol. At the physical level it consists of 2 lines: RX and TX. The unit of communication is a character (not to be confused with a string character) which can be 8 or 9 bits wide. UART objects can be created and initialised using:: from pyb import UART uart = UART(1, 9600) # init with given baudrate uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2. *Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits are supported. A UART object acts like a `stream` object and reading and writing is done using the standard stream methods:: uart.read(10) # read 10 characters, returns a bytes object uart.read() # read all available characters uart.readline() # read a line uart.readinto(buf) # read and store into the given buffer uart.write('abc') # write the 3 characters Individual characters can be read/written using:: uart.readchar() # read 1 character and returns it as an integer uart.writechar(42) # write 1 character To check if there is anything to be read, use:: uart.any() # returns the number of characters waiting *Note:* The stream functions ``read``, ``write``, etc. are new in MicroPython v1.3.4. Earlier versions use ``uart.send`` and ``uart.recv``. Constructors ------------ .. class:: pyb.UART(bus, ...) Construct a UART object on the given bus. ``bus`` can be 1-6, or 'XA', 'XB', 'YA', or 'YB'. With no additional parameters, the UART object is created but not initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. See ``init`` for parameters of initialisation. The physical pins of the UART busses are: - ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)`` - ``UART(1)`` is on ``XB``: ``(TX, RX) = (X9, X10) = (PB6, PB7)`` - ``UART(6)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PC6, PC7)`` - ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)`` - ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)`` The Pyboard Lite supports UART(1), UART(2) and UART(6) only. Pins are as above except: - ``UART(2)`` is on: ``(TX, RX) = (X1, X2) = (PA2, PA3)`` Methods ------- .. method:: UART.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=0, flow=0, timeout_char=0, read_buf_len=64) Initialise the UART bus with the given parameters: - ``baudrate`` is the clock rate. - ``bits`` is the number of bits per character, 7, 8 or 9. - ``parity`` is the parity, ``None``, 0 (even) or 1 (odd). - ``stop`` is the number of stop bits, 1 or 2. - ``flow`` sets the flow control type. Can be 0, ``UART.RTS``, ``UART.CTS`` or ``UART.RTS | UART.CTS``. - ``timeout`` is the timeout in milliseconds to wait for writing/reading the first character. - ``timeout_char`` is the timeout in milliseconds to wait between characters while writing or reading. - ``read_buf_len`` is the character length of the read buffer (0 to disable). This method will raise an exception if the baudrate could not be set within 5% of the desired value. The minimum baudrate is dictated by the frequency of the bus that the UART is on; UART(1) and UART(6) are APB2, the rest are on APB1. The default bus frequencies give a minimum baudrate of 1300 for UART(1) and UART(6) and 650 for the others. Use :func:`pyb.freq ` to reduce the bus frequencies to get lower baudrates. *Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits are supported. .. method:: UART.deinit() Turn off the UART bus. .. method:: UART.any() Returns the number of bytes waiting (may be 0). .. method:: UART.read([nbytes]) Read characters. If ``nbytes`` is specified then read at most that many bytes. If ``nbytes`` are available in the buffer, returns immediately, otherwise returns when sufficient characters arrive or the timeout elapses. If ``nbytes`` is not given then the method reads as much data as possible. It returns after the timeout has elapsed. *Note:* for 9 bit characters each character takes two bytes, ``nbytes`` must be even, and the number of characters is ``nbytes/2``. Return value: a bytes object containing the bytes read in. Returns ``None`` on timeout. .. method:: UART.readchar() Receive a single character on the bus. Return value: The character read, as an integer. Returns -1 on timeout. .. method:: UART.readinto(buf[, nbytes]) Read bytes into the ``buf``. If ``nbytes`` is specified then read at most that many bytes. Otherwise, read at most ``len(buf)`` bytes. Return value: number of bytes read and stored into ``buf`` or ``None`` on timeout. .. method:: UART.readline() Read a line, ending in a newline character. If such a line exists, return is immediate. If the timeout elapses, all available data is returned regardless of whether a newline exists. Return value: the line read or ``None`` on timeout if no data is available. .. method:: UART.write(buf) Write the buffer of bytes to the bus. If characters are 7 or 8 bits wide then each byte is one character. If characters are 9 bits wide then two bytes are used for each character (little endian), and ``buf`` must contain an even number of bytes. Return value: number of bytes written. If a timeout occurs and no bytes were written returns ``None``. .. method:: UART.writechar(char) Write a single character on the bus. ``char`` is an integer to write. Return value: ``None``. See note below if CTS flow control is used. .. method:: UART.sendbreak() Send a break condition on the bus. This drives the bus low for a duration of 13 bits. Return value: ``None``. Constants --------- .. data:: UART.RTS UART.CTS to select the flow control type. Flow Control ------------ On Pyboards V1 and V1.1 ``UART(2)`` and ``UART(3)`` support RTS/CTS hardware flow control using the following pins: - ``UART(2)`` is on: ``(TX, RX, nRTS, nCTS) = (X3, X4, X2, X1) = (PA2, PA3, PA1, PA0)`` - ``UART(3)`` is on :``(TX, RX, nRTS, nCTS) = (Y9, Y10, Y7, Y6) = (PB10, PB11, PB14, PB13)`` On the Pyboard Lite only ``UART(2)`` supports flow control on these pins: ``(TX, RX, nRTS, nCTS) = (X1, X2, X4, X3) = (PA2, PA3, PA1, PA0)`` In the following paragraphs the term "target" refers to the device connected to the UART. When the UART's ``init()`` method is called with ``flow`` set to one or both of ``UART.RTS`` and ``UART.CTS`` the relevant flow control pins are configured. ``nRTS`` is an active low output, ``nCTS`` is an active low input with pullup enabled. To achieve flow control the Pyboard's ``nCTS`` signal should be connected to the target's ``nRTS`` and the Pyboard's ``nRTS`` to the target's ``nCTS``. CTS: target controls Pyboard transmitter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If CTS flow control is enabled the write behaviour is as follows: If the Pyboard's ``UART.write(buf)`` method is called, transmission will stall for any periods when ``nCTS`` is ``False``. This will result in a timeout if the entire buffer was not transmitted in the timeout period. The method returns the number of bytes written, enabling the user to write the remainder of the data if required. In the event of a timeout, a character will remain in the UART pending ``nCTS``. The number of bytes composing this character will be included in the return value. If ``UART.writechar()`` is called when ``nCTS`` is ``False`` the method will time out unless the target asserts ``nCTS`` in time. If it times out ``OSError 116`` will be raised. The character will be transmitted as soon as the target asserts ``nCTS``. RTS: Pyboard controls target's transmitter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If RTS flow control is enabled, behaviour is as follows: If buffered input is used (``read_buf_len`` > 0), incoming characters are buffered. If the buffer becomes full, the next character to arrive will cause ``nRTS`` to go ``False``: the target should cease transmission. ``nRTS`` will go ``True`` when characters are read from the buffer. Note that the ``any()`` method returns the number of bytes in the buffer. Assume a buffer length of ``N`` bytes. If the buffer becomes full, and another character arrives, ``nRTS`` will be set False, and ``any()`` will return the count ``N``. When characters are read the additional character will be placed in the buffer and will be included in the result of a subsequent ``any()`` call. If buffered input is not used (``read_buf_len`` == 0) the arrival of a character will cause ``nRTS`` to go ``False`` until the character is read. micropython-1.12/docs/library/pyb.USB_HID.rst000066400000000000000000000022051357706137100210550ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.USB_HID: class USB_HID -- USB Human Interface Device (HID) ================================================= The USB_HID class allows creation of an object representing the USB Human Interface Device (HID) interface. It can be used to emulate a peripheral such as a mouse or keyboard. Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the USB mode to include the HID interface. Constructors ------------ .. class:: pyb.USB_HID() Create a new USB_HID object. Methods ------- .. method:: USB_HID.recv(data, \*, timeout=5000) Receive data on the bus: - ``data`` can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with received bytes. - ``timeout`` is the timeout in milliseconds to wait for the receive. Return value: if ``data`` is an integer then a new buffer of the bytes received, otherwise the number of bytes read into ``data`` is returned. .. method:: USB_HID.send(data) Send data over the USB HID interface: - ``data`` is the data to send (a tuple/list of integers, or a bytearray). micropython-1.12/docs/library/pyb.USB_VCP.rst000066400000000000000000000070311357706137100211030ustar00rootroot00000000000000.. currentmodule:: pyb .. _pyb.USB_VCP: class USB_VCP -- USB virtual comm port ====================================== The USB_VCP class allows creation of a `stream`-like object representing the USB virtual comm port. It can be used to read and write data over USB to the connected host. Constructors ------------ .. class:: pyb.USB_VCP(id=0) Create a new USB_VCP object. The *id* argument specifies which USB VCP port to use. Methods ------- .. method:: USB_VCP.init(\*, flow=-1) Configure the USB VCP port. If the *flow* argument is not -1 then the value sets the flow control, which can be a bitwise-or of ``USB_VCP.RTS`` and ``USB_VCP.CTS``. RTS is used to control read behaviour and CTS, to control write behaviour. .. method:: USB_VCP.setinterrupt(chr) Set the character which interrupts running Python code. This is set to 3 (CTRL-C) by default, and when a CTRL-C character is received over the USB VCP port, a KeyboardInterrupt exception is raised. Set to -1 to disable this interrupt feature. This is useful when you want to send raw bytes over the USB VCP port. .. method:: USB_VCP.isconnected() Return ``True`` if USB is connected as a serial device, else ``False``. .. method:: USB_VCP.any() Return ``True`` if any characters waiting, else ``False``. .. method:: USB_VCP.close() This method does nothing. It exists so the USB_VCP object can act as a file. .. method:: USB_VCP.read([nbytes]) Read at most ``nbytes`` from the serial device and return them as a bytes object. If ``nbytes`` is not specified then the method reads all available bytes from the serial device. USB_VCP `stream` implicitly works in non-blocking mode, so if no pending data available, this method will return immediately with ``None`` value. .. method:: USB_VCP.readinto(buf, [maxlen]) Read bytes from the serial device and store them into ``buf``, which should be a buffer-like object. At most ``len(buf)`` bytes are read. If ``maxlen`` is given and then at most ``min(maxlen, len(buf))`` bytes are read. Returns the number of bytes read and stored into ``buf`` or ``None`` if no pending data available. .. method:: USB_VCP.readline() Read a whole line from the serial device. Returns a bytes object containing the data, including the trailing newline character or ``None`` if no pending data available. .. method:: USB_VCP.readlines() Read as much data as possible from the serial device, breaking it into lines. Returns a list of bytes objects, each object being one of the lines. Each line will include the newline character. .. method:: USB_VCP.write(buf) Write the bytes from ``buf`` to the serial device. Returns the number of bytes written. .. method:: USB_VCP.recv(data, \*, timeout=5000) Receive data on the bus: - ``data`` can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with received bytes. - ``timeout`` is the timeout in milliseconds to wait for the receive. Return value: if ``data`` is an integer then a new buffer of the bytes received, otherwise the number of bytes read into ``data`` is returned. .. method:: USB_VCP.send(data, \*, timeout=5000) Send data over the USB VCP: - ``data`` is the data to send (an integer to send, or a buffer object). - ``timeout`` is the timeout in milliseconds to wait for the send. Return value: number of bytes sent. Constants --------- .. data:: USB_VCP.RTS USB_VCP.CTS to select the flow control type. micropython-1.12/docs/library/pyb.rst000066400000000000000000000260771357706137100177560ustar00rootroot00000000000000:mod:`pyb` --- functions related to the board ============================================= .. module:: pyb :synopsis: functions related to the board The ``pyb`` module contains specific functions related to the board. Time related functions ---------------------- .. function:: delay(ms) Delay for the given number of milliseconds. .. function:: udelay(us) Delay for the given number of microseconds. .. function:: millis() Returns the number of milliseconds since the board was last reset. The result is always a MicroPython smallint (31-bit signed number), so after 2^30 milliseconds (about 12.4 days) this will start to return negative numbers. Note that if :meth:`pyb.stop()` is issued the hardware counter supporting this function will pause for the duration of the "sleeping" state. This will affect the outcome of :meth:`pyb.elapsed_millis()`. .. function:: micros() Returns the number of microseconds since the board was last reset. The result is always a MicroPython smallint (31-bit signed number), so after 2^30 microseconds (about 17.8 minutes) this will start to return negative numbers. Note that if :meth:`pyb.stop()` is issued the hardware counter supporting this function will pause for the duration of the "sleeping" state. This will affect the outcome of :meth:`pyb.elapsed_micros()`. .. function:: elapsed_millis(start) Returns the number of milliseconds which have elapsed since ``start``. This function takes care of counter wrap, and always returns a positive number. This means it can be used to measure periods up to about 12.4 days. Example:: start = pyb.millis() while pyb.elapsed_millis(start) < 1000: # Perform some operation .. function:: elapsed_micros(start) Returns the number of microseconds which have elapsed since ``start``. This function takes care of counter wrap, and always returns a positive number. This means it can be used to measure periods up to about 17.8 minutes. Example:: start = pyb.micros() while pyb.elapsed_micros(start) < 1000: # Perform some operation pass Reset related functions ----------------------- .. function:: hard_reset() Resets the pyboard in a manner similar to pushing the external RESET button. .. function:: bootloader() Activate the bootloader without BOOT\* pins. .. function:: fault_debug(value) Enable or disable hard-fault debugging. A hard-fault is when there is a fatal error in the underlying system, like an invalid memory access. If the *value* argument is ``False`` then the board will automatically reset if there is a hard fault. If *value* is ``True`` then, when the board has a hard fault, it will print the registers and the stack trace, and then cycle the LEDs indefinitely. The default value is disabled, i.e. to automatically reset. Interrupt related functions --------------------------- .. function:: disable_irq() Disable interrupt requests. Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs respectively. This return value can be passed to enable_irq to restore the IRQ to its original state. .. function:: enable_irq(state=True) Enable interrupt requests. If ``state`` is ``True`` (the default value) then IRQs are enabled. If ``state`` is ``False`` then IRQs are disabled. The most common use of this function is to pass it the value returned by ``disable_irq`` to exit a critical section. Power related functions ----------------------- .. function:: freq([sysclk[, hclk[, pclk1[, pclk2]]]]) If given no arguments, returns a tuple of clock frequencies: (sysclk, hclk, pclk1, pclk2). These correspond to: - sysclk: frequency of the CPU - hclk: frequency of the AHB bus, core memory and DMA - pclk1: frequency of the APB1 bus - pclk2: frequency of the APB2 bus If given any arguments then the function sets the frequency of the CPU, and the busses if additional arguments are given. Frequencies are given in Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that not all values are supported and the largest supported frequency not greater than the given value will be selected. Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48, 54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168. The maximum frequency of hclk is 168MHz, of pclk1 is 42MHz, and of pclk2 is 84MHz. Be sure not to set frequencies above these values. The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency using a prescaler (divider). Supported prescalers for hclk are: 1, 2, 4, 8, 16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2, 4, 8. A prescaler will be chosen to best match the requested frequency. A sysclk frequency of 8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI (internal oscillator) directly. The higher frequencies use the HSE to drive the PLL (phase locked loop), and then use the output of the PLL. Note that if you change the frequency while the USB is enabled then the USB may become unreliable. It is best to change the frequency in boot.py, before the USB peripheral is started. Also note that sysclk frequencies below 36MHz do not allow the USB to function correctly. .. function:: wfi() Wait for an internal or external interrupt. This executes a ``wfi`` instruction which reduces power consumption of the MCU until any interrupt occurs (be it internal or external), at which point execution continues. Note that the system-tick interrupt occurs once every millisecond (1000Hz) so this function will block for at most 1ms. .. function:: stop() Put the pyboard in a "sleeping" state. This reduces power consumption to less than 500 uA. To wake from this sleep state requires an external interrupt or a real-time-clock event. Upon waking execution continues where it left off. See :meth:`rtc.wakeup` to configure a real-time-clock wakeup event. .. function:: standby() Put the pyboard into a "deep sleep" state. This reduces power consumption to less than 50 uA. To wake from this sleep state requires a real-time-clock event, or an external interrupt on X1 (PA0=WKUP) or X18 (PC13=TAMP1). Upon waking the system undergoes a hard reset. See :meth:`rtc.wakeup` to configure a real-time-clock wakeup event. Miscellaneous functions ----------------------- .. function:: have_cdc() Return True if USB is connected as a serial device, False otherwise. .. note:: This function is deprecated. Use pyb.USB_VCP().isconnected() instead. .. function:: hid((buttons, x, y, z)) Takes a 4-tuple (or list) and sends it to the USB host (the PC) to signal a HID mouse-motion event. .. note:: This function is deprecated. Use :meth:`pyb.USB_HID.send()` instead. .. function:: info([dump_alloc_table]) Print out lots of information about the board. .. function:: main(filename) Set the filename of the main script to run after boot.py is finished. If this function is not called then the default file main.py will be executed. It only makes sense to call this function from within boot.py. .. function:: mount(device, mountpoint, \*, readonly=False, mkfs=False) .. note:: This function is deprecated. Mounting and unmounting devices should be performed by :meth:`uos.mount` and :meth:`uos.umount` instead. Mount a block device and make it available as part of the filesystem. ``device`` must be an object that provides the block protocol. (The following is also deprecated. See :class:`uos.AbstractBlockDev` for the correct way to create a block device.) - ``readblocks(self, blocknum, buf)`` - ``writeblocks(self, blocknum, buf)`` (optional) - ``count(self)`` - ``sync(self)`` (optional) ``readblocks`` and ``writeblocks`` should copy data between ``buf`` and the block device, starting from block number ``blocknum`` on the device. ``buf`` will be a bytearray with length a multiple of 512. If ``writeblocks`` is not defined then the device is mounted read-only. The return value of these two functions is ignored. ``count`` should return the number of blocks available on the device. ``sync``, if implemented, should sync the data on the device. The parameter ``mountpoint`` is the location in the root of the filesystem to mount the device. It must begin with a forward-slash. If ``readonly`` is ``True``, then the device is mounted read-only, otherwise it is mounted read-write. If ``mkfs`` is ``True``, then a new filesystem is created if one does not already exist. .. function:: repl_uart(uart) Get or set the UART object where the REPL is repeated on. .. function:: rng() Return a 30-bit hardware generated random number. .. function:: sync() Sync all file systems. .. function:: unique_id() Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU. .. function:: usb_mode([modestr], port=-1, vid=0xf055, pid=-1, msc=(), hid=pyb.hid_mouse, high_speed=False) If called with no arguments, return the current USB mode as a string. If called with *modestr* provided, attempts to configure the USB mode. The following values of *modestr* are understood: - ``None``: disables USB - ``'VCP'``: enable with VCP (Virtual COM Port) interface - ``'MSC'``: enable with MSC (mass storage device class) interface - ``'VCP+MSC'``: enable with VCP and MSC - ``'VCP+HID'``: enable with VCP and HID (human interface device) - ``'VCP+MSC+HID'``: enabled with VCP, MSC and HID (only available on PYBD boards) For backwards compatibility, ``'CDC'`` is understood to mean ``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``). The *port* parameter should be an integer (0, 1, ...) and selects which USB port to use if the board supports multiple ports. A value of -1 uses the default or automatically selected port. The *vid* and *pid* parameters allow you to specify the VID (vendor id) and PID (product id). A *pid* value of -1 will select a PID based on the value of *modestr*. If enabling MSC mode, the *msc* parameter can be used to specify a list of SCSI LUNs to expose on the mass storage interface. For example ``msc=(pyb.Flash(), pyb.SDCard())``. If enabling HID mode, you may also specify the HID details by passing the *hid* keyword parameter. It takes a tuple of (subclass, protocol, max packet length, polling interval, report descriptor). By default it will set appropriate values for a USB mouse. There is also a ``pyb.hid_keyboard`` constant, which is an appropriate tuple for a USB keyboard. The *high_speed* parameter, when set to ``True``, enables USB HS mode if it is supported by the hardware. Classes ------- .. toctree:: :maxdepth: 1 pyb.Accel.rst pyb.ADC.rst pyb.CAN.rst pyb.DAC.rst pyb.ExtInt.rst pyb.Flash.rst pyb.I2C.rst pyb.LCD.rst pyb.LED.rst pyb.Pin.rst pyb.RTC.rst pyb.Servo.rst pyb.SPI.rst pyb.Switch.rst pyb.Timer.rst pyb.UART.rst pyb.USB_HID.rst pyb.USB_VCP.rst micropython-1.12/docs/library/sys.rst000066400000000000000000000105211357706137100177650ustar00rootroot00000000000000:mod:`sys` -- system specific functions ======================================= .. module:: sys :synopsis: system specific functions |see_cpython_module| :mod:`python:sys`. Functions --------- .. function:: exit(retval=0) Terminate current program with a given exit code. Underlyingly, this function raise as `SystemExit` exception. If an argument is given, its value given as an argument to `SystemExit`. .. function:: atexit(func) Register *func* to be called upon termination. *func* must be a callable that takes no arguments, or ``None`` to disable the call. The ``atexit`` function will return the previous value set by this function, which is initially ``None``. .. admonition:: Difference to CPython :class: attention This function is a MicroPython extension intended to provide similar functionality to the :mod:`atexit` module in CPython. .. function:: print_exception(exc, file=sys.stdout) Print exception with a traceback to a file-like object *file* (or `sys.stdout` by default). .. admonition:: Difference to CPython :class: attention This is simplified version of a function which appears in the ``traceback`` module in CPython. Unlike ``traceback.print_exception()``, this function takes just exception value instead of exception type, exception value, and traceback object; *file* argument should be positional; further arguments are not supported. CPython-compatible ``traceback`` module can be found in `micropython-lib`. Constants --------- .. data:: argv A mutable list of arguments the current program was started with. .. data:: byteorder The byte order of the system (``"little"`` or ``"big"``). .. data:: implementation Object with information about the current Python implementation. For MicroPython, it has following attributes: * *name* - string "micropython" * *version* - tuple (major, minor, micro), e.g. (1, 7, 0) This object is the recommended way to distinguish MicroPython from other Python implementations (note that it still may not exist in the very minimal ports). .. admonition:: Difference to CPython :class: attention CPython mandates more attributes for this object, but the actual useful bare minimum is implemented in MicroPython. .. data:: maxsize Maximum value which a native integer type can hold on the current platform, or maximum value representable by MicroPython integer type, if it's smaller than platform max value (that is the case for MicroPython ports without long int support). This attribute is useful for detecting "bitness" of a platform (32-bit vs 64-bit, etc.). It's recommended to not compare this attribute to some value directly, but instead count number of bits in it:: bits = 0 v = sys.maxsize while v: bits += 1 v >>= 1 if bits > 32: # 64-bit (or more) platform ... else: # 32-bit (or less) platform # Note that on 32-bit platform, value of bits may be less than 32 # (e.g. 31) due to peculiarities described above, so use "> 16", # "> 32", "> 64" style of comparisons. .. data:: modules Dictionary of loaded modules. On some ports, it may not include builtin modules. .. data:: path A mutable list of directories to search for imported modules. .. data:: platform The platform that MicroPython is running on. For OS/RTOS ports, this is usually an identifier of the OS, e.g. ``"linux"``. For baremetal ports it is an identifier of a board, e.g. ``"pyboard"`` for the original MicroPython reference board. It thus can be used to distinguish one board from another. If you need to check whether your program runs on MicroPython (vs other Python implementation), use `sys.implementation` instead. .. data:: stderr Standard error `stream`. .. data:: stdin Standard input `stream`. .. data:: stdout Standard output `stream`. .. data:: version Python language version that this implementation conforms to, as a string. .. data:: version_info Python language version that this implementation conforms to, as a tuple of ints. .. admonition:: Difference to CPython :class: attention Only the first three version numbers (major, minor, micro) are supported and they can be referenced only by index, not by name. micropython-1.12/docs/library/uarray.rst000066400000000000000000000014361357706137100204570ustar00rootroot00000000000000:mod:`uarray` -- arrays of numeric data ======================================= .. module:: uarray :synopsis: efficient arrays of numeric data |see_cpython_module| :mod:`python:array`. Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, ``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the floating-point support). Classes ------- .. class:: array(typecode, [iterable]) Create array with elements of given type. Initial contents of the array are given by *iterable*. If it is not provided, an empty array is created. .. method:: append(val) Append new element *val* to the end of array, growing it. .. method:: extend(iterable) Append new elements as contained in *iterable* to the end of array, growing it. micropython-1.12/docs/library/ubinascii.rst000066400000000000000000000022601357706137100211160ustar00rootroot00000000000000:mod:`ubinascii` -- binary/ASCII conversions ============================================ .. module:: ubinascii :synopsis: binary/ASCII conversions |see_cpython_module| :mod:`python:binascii`. This module implements conversions between binary data and various encodings of it in ASCII form (in both directions). Functions --------- .. function:: hexlify(data, [sep]) Convert binary data to hexadecimal representation. Returns bytes string. .. admonition:: Difference to CPython :class: attention If additional argument, *sep* is supplied, it is used as a separator between hexadecimal values. .. function:: unhexlify(data) Convert hexadecimal data to binary representation. Returns bytes string. (i.e. inverse of hexlify) .. function:: a2b_base64(data) Decode base64-encoded data, ignoring invalid characters in the input. Conforms to `RFC 2045 s.6.8 `_. Returns a bytes object. .. function:: b2a_base64(data) Encode binary data in base64 format, as in `RFC 3548 `_. Returns the encoded data followed by a newline character, as a bytes object. micropython-1.12/docs/library/ubluetooth.rst000066400000000000000000000356231357706137100213530ustar00rootroot00000000000000:mod:`ubluetooth` --- low-level Bluetooth ========================================= .. module:: ubluetooth :synopsis: Low-level Bluetooth radio functionality This module provides an interface to a Bluetooth controller on a board. Currently this supports Bluetooth Low Energy (BLE) in Central, Peripheral, Broadcaster, and Observer roles, and a device may operate in multiple roles concurrently. This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types. .. note:: This module is still under development and its classes, functions, methods and constants are subject to change. class BLE --------- Constructor ----------- .. class:: BLE() Returns the singleton BLE object. Configuration ------------- .. method:: BLE.active([active]) Optionally changes the active state of the BLE radio, and returns the current state. The radio must be made active before using any other methods on this class. .. method:: BLE.config('param') BLE.config(param=value, ...) Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string, and just one parameter is queried at a time. To set values use the keyword syntax, and one ore more parameter can be set at a time. Currently supported values are: - ``'mac'``: Returns the device MAC address. If a device has a fixed address (e.g. PYBD) then it will be returned. Otherwise (e.g. ESP32) a random address will be generated when the BLE interface is made active. - ``'rxbuf'``: Set the size in bytes of the internal buffer used to store incoming events. This buffer is global to the entire BLE driver and so handles incoming data for all events, including all characteristics. Increasing this allows better handling of bursty incoming data (for example scan results) and the ability for a central role to receive larger characteristic values. Event Handling -------------- .. method:: BLE.irq(handler, trigger=0xffff) Registers a callback for events from the BLE stack. The *handler* takes two arguments, ``event`` (which will be one of the codes below) and ``data`` (which is an event-specific tuple of values). The optional *trigger* parameter allows you to set a mask of events that your program is interested in. The default is all events. Note: the ``addr``, ``adv_data`` and ``uuid`` entries in the tuples are references to data managed by the :mod:`ubluetooth` module (i.e. the same instance will be re-used across multiple calls to the event handler). If your program wants to use this data outside of the handler, then it must copy them first, e.g. by using ``bytes(addr)`` or ``bluetooth.UUID(uuid)``. An event handler showing all possible events:: def bt_irq(event, data): if event == _IRQ_CENTRAL_CONNECT: # A central has connected to this peripheral. conn_handle, addr_type, addr = data elif event == _IRQ_CENTRAL_DISCONNECT: # A central has disconnected from this peripheral. conn_handle, addr_type, addr = data elif event == _IRQ_GATTS_WRITE: # A central has written to this characteristic or descriptor. conn_handle, attr_handle = data elif event == _IRQ_GATTS_READ_REQUEST: # A central has issued a read. Note: this is a hard IRQ. # Return None to deny the read. # Note: This event is not supported on ESP32. conn_handle, attr_handle = data elif event == _IRQ_SCAN_RESULT: # A single scan result. addr_type, addr, connectable, rssi, adv_data = data elif event == _IRQ_SCAN_COMPLETE: # Scan duration finished or manually stopped. pass elif event == _IRQ_PERIPHERAL_CONNECT: # A successful gap_connect(). conn_handle, addr_type, addr = data elif event == _IRQ_PERIPHERAL_DISCONNECT: # Connected peripheral has disconnected. conn_handle, addr_type, addr = data elif event == _IRQ_GATTC_SERVICE_RESULT: # Called for each service found by gattc_discover_services(). conn_handle, start_handle, end_handle, uuid = data elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT: # Called for each characteristic found by gattc_discover_services(). conn_handle, def_handle, value_handle, properties, uuid = data elif event == _IRQ_GATTC_DESCRIPTOR_RESULT: # Called for each descriptor found by gattc_discover_descriptors(). conn_handle, dsc_handle, uuid = data elif event == _IRQ_GATTC_READ_RESULT: # A gattc_read() has completed. conn_handle, value_handle, char_data = data elif event == _IRQ_GATTC_WRITE_STATUS: # A gattc_write() has completed. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_NOTIFY: # A peripheral has sent a notify request. conn_handle, value_handle, notify_data = data elif event == _IRQ_GATTC_INDICATE: # A peripheral has sent an indicate request. conn_handle, value_handle, notify_data = data The event codes are:: from micropython import const _IRQ_CENTRAL_CONNECT = const(1 << 0) _IRQ_CENTRAL_DISCONNECT = const(1 << 1) _IRQ_GATTS_WRITE = const(1 << 2) _IRQ_GATTS_READ_REQUEST = const(1 << 3) _IRQ_SCAN_RESULT = const(1 << 4) _IRQ_SCAN_COMPLETE = const(1 << 5) _IRQ_PERIPHERAL_CONNECT = const(1 << 6) _IRQ_PERIPHERAL_DISCONNECT = const(1 << 7) _IRQ_GATTC_SERVICE_RESULT = const(1 << 8) _IRQ_GATTC_CHARACTERISTIC_RESULT = const(1 << 9) _IRQ_GATTC_DESCRIPTOR_RESULT = const(1 << 10) _IRQ_GATTC_READ_RESULT = const(1 << 11) _IRQ_GATTC_WRITE_STATUS = const(1 << 12) _IRQ_GATTC_NOTIFY = const(1 << 13) _IRQ_GATTC_INDICATE = const(1 << 14) In order to save space in the firmware, these constants are not included on the :mod:`ubluetooth` module. Add the ones that you need from the list above to your program. Broadcaster Role (Advertiser) ----------------------------- .. method:: BLE.gap_advertise(interval_us, adv_data=None, resp_data=None, connectable=True) Starts advertising at the specified interval (in **micro**\ seconds). This interval will be rounded down to the nearest 625us. To stop advertising, set *interval_us* to ``None``. *adv_data* and *resp_data* can be any type that implements the buffer protocol (e.g. ``bytes``, ``bytearray``, ``str``). *adv_data* is included in all broadcasts, and *resp_data* is send in reply to an active scan. Note: if *adv_data* (or *resp_data*) is ``None``, then the data passed to the previous call to ``gap_advertise`` will be re-used. This allows a broadcaster to resume advertising with just ``gap_advertise(interval_us)``. To clear the advertising payload pass an empty ``bytes``, i.e. ``b''``. Observer Role (Scanner) ----------------------- .. method:: BLE.gap_scan(duration_ms, [interval_us], [window_us]) Run a scan operation lasting for the specified duration (in **milli**\ seconds). To scan indefinitely, set *duration_ms* to ``0``. To stop scanning, set *duration_ms* to ``None``. Use *interval_us* and *window_us* to optionally configure the duty cycle. The scanner will run for *window_us* **micro**\ seconds every *interval_us* **micro**\ seconds for a total of *duration_ms* **milli**\ seconds. The default interval and window are 1.28 seconds and 11.25 milliseconds respectively (background scanning). For each scan result, the ``_IRQ_SCAN_RESULT`` event will be raised. When scanning is stopped (either due to the duration finishing or when explicitly stopped), the ``_IRQ_SCAN_COMPLETE`` event will be raised. Peripheral Role (GATT Server) ----------------------------- A BLE peripheral has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. These values are stored locally, and are accessed by their "value handle" which is generated during service registration. They can also be read from or written to by a remote central device. Additionally, a peripheral can "notify" a characteristic to a connected central via a connection handle. Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a central will be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger writes from a central to a given characteristic, use :meth:`gatts_write` after registration. e.g. ``gatts_write(char_handle, bytes(100))``. .. method:: BLE.gatts_register_services(services_definition) Configures the peripheral with the specified services, replacing any existing services. *services_definition* is a list of **services**, where each **service** is a two-element tuple containing a UUID and a list of **characteristics**. Each **characteristic** is a two-or-three-element tuple containing a UUID, a **flags** value, and optionally a list of *descriptors*. Each **descriptor** is a two-element tuple containing a UUID and a **flags** value. The **flags** are a bitwise-OR combination of the :data:`ubluetooth.FLAG_READ`, :data:`ubluetooth.FLAG_WRITE` and :data:`ubluetooth.FLAG_NOTIFY` values defined below. The return value is a list (one element per service) of tuples (each element is a value handle). Characteristics and descriptor handles are flattened into the same tuple, in the order that they are defined. The following example registers two services (Heart Rate, and Nordic UART):: HR_UUID = bluetooth.UUID(0x180D) HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) HR_SERVICE = (HR_UUID, (HR_CHAR,),) UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E') UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,) UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),) SERVICES = (HR_SERVICE, UART_SERVICE,) ( (hr,), (tx, rx,), ) = bt.gatts_register_services(SERVICES) The three value handles (``hr``, ``tx``, ``rx``) can be used with :meth:`gatts_read `, :meth:`gatts_write `, and :meth:`gatts_notify `. **Note:** Advertising must be stopped before registering services. .. method:: BLE.gatts_read(value_handle) Reads the local value for this handle (which has either been written by :meth:`gatts_write ` or by a remote central). .. method:: BLE.gatts_write(value_handle, data) Writes the local value for this handle, which can be read by a central. .. method:: BLE.gatts_notify(conn_handle, value_handle, [data]) Notifies a connected central that this value has changed and that it should issue a read of the current value from this peripheral. If *data* is specified, then the that value is sent to the central as part of the notification, avoiding the need for a separate read request. Note that this will not update the local value stored. .. method:: BLE.gatts_set_buffer(value_handle, len, append=False) Sets the internal buffer size for a value in bytes. This will limit the largest possible write that can be received. The default is 20. Setting *append* to ``True`` will make all remote writes append to, rather than replace, the current value. At most *len* bytes can be buffered in this way. When you use :meth:`gatts_read `, the value will be cleared after reading. This feature is useful when implementing something like the Nordic UART Service. Central Role (GATT Client) -------------------------- .. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000) Connect to a peripheral. On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. .. method:: BLE.gap_disconnect(conn_handle) Disconnect the specified connection handle. On success, the ``_IRQ_PERIPHERAL_DISCONNECT`` event will be raised. Returns ``False`` if the connection handle wasn't connected, and ``True`` otherwise. .. method:: BLE.gattc_discover_services(conn_handle) Query a connected peripheral for its services. For each service discovered, the ``_IRQ_GATTC_SERVICE_RESULT`` event will be raised. .. method:: BLE.gattc_discover_characteristics(conn_handle, start_handle, end_handle) Query a connected peripheral for characteristics in the specified range. For each characteristic discovered, the ``_IRQ_GATTC_CHARACTERISTIC_RESULT`` event will be raised. .. method:: BLE.gattc_discover_descriptors(conn_handle, start_handle, end_handle) Query a connected peripheral for descriptors in the specified range. For each descriptor discovered, the ``_IRQ_GATTC_DESCRIPTOR_RESULT`` event will be raised. .. method:: BLE.gattc_read(conn_handle, value_handle) Issue a remote read to a connected peripheral for the specified characteristic or descriptor handle. On success, the ``_IRQ_GATTC_READ_RESULT`` event will be raised. .. method:: BLE.gattc_write(conn_handle, value_handle, data, mode=0) Issue a remote write to a connected peripheral for the specified characteristic or descriptor handle. The argument *mode* specifies the write behaviour, with the currently supported values being: * ``mode=0`` (default) is a write-without-response: the write will be sent to the remote peripheral but no confirmation will be returned, and no event will be raised. * ``mode=1`` is a write-with-response: the remote peripheral is requested to send a response/acknowledgement that it received the data. If a response is received from the remote peripheral the ``_IRQ_GATTC_WRITE_STATUS`` event will be raised. class UUID ---------- Constructor ----------- .. class:: UUID(value) Creates a UUID instance with the specified **value**. The **value** can be either: - A 16-bit integer. e.g. ``0x2908``. - A 128-bit UUID string. e.g. ``'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'``. Constants --------- .. data:: ubluetooth.FLAG_READ ubluetooth.FLAG_WRITE ubluetooth.FLAG_NOTIFY micropython-1.12/docs/library/ucollections.rst000066400000000000000000000052571357706137100216640ustar00rootroot00000000000000:mod:`ucollections` -- collection and container types ===================================================== .. module:: ucollections :synopsis: collection and container types |see_cpython_module| :mod:`python:collections`. This module implements advanced collection and container types to hold/accumulate various objects. Classes ------- .. function:: deque(iterable, maxlen[, flags]) Deques (double-ended queues) are a list-like container that support O(1) appends and pops from either side of the deque. New deques are created using the following arguments: - *iterable* must be the empty tuple, and the new deque is created empty. - *maxlen* must be specified and the deque will be bounded to this maximum length. Once the deque is full, any new items added will discard items from the opposite end. - The optional *flags* can be 1 to check for overflow when adding items. As well as supporting `bool` and `len`, deque objects have the following methods: .. method:: deque.append(x) Add *x* to the right side of the deque. Raises IndexError if overflow checking is enabled and there is no more room left. .. method:: deque.popleft() Remove and return an item from the left side of the deque. Raises IndexError if no items are present. .. function:: namedtuple(name, fields) This is factory function to create a new namedtuple type with a specific name and set of fields. A namedtuple is a subclass of tuple which allows to access its fields not just by numeric index, but also with an attribute access syntax using symbolic field names. Fields is a sequence of strings specifying field names. For compatibility with CPython it can also be a a string with space-separated field named (but this is less efficient). Example of use:: from ucollections import namedtuple MyTuple = namedtuple("MyTuple", ("id", "name")) t1 = MyTuple(1, "foo") t2 = MyTuple(2, "bar") print(t1.name) assert t2.name == t2[1] .. function:: OrderedDict(...) ``dict`` type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over, keys/items are returned in the order they were added:: from ucollections import OrderedDict # To make benefit of ordered keys, OrderedDict should be initialized # from sequence of (key, value) pairs. d = OrderedDict([("z", 1), ("a", 2)]) # More items can be added as usual d["w"] = 5 d["b"] = 3 for k, v in d.items(): print(k, v) Output:: z 1 a 2 w 5 b 3 micropython-1.12/docs/library/ucryptolib.rst000066400000000000000000000026761357706137100213570ustar00rootroot00000000000000:mod:`ucryptolib` -- cryptographic ciphers ========================================== .. module:: ucryptolib :synopsis: cryptographic ciphers Classes ------- .. class:: aes .. classmethod:: __init__(key, mode, [IV]) Initialize cipher object, suitable for encryption/decryption. Note: after initialization, cipher object can be use only either for encryption or decryption. Running decrypt() operation after encrypt() or vice versa is not supported. Parameters are: * *key* is an encryption/decryption key (bytes-like). * *mode* is: * ``1`` (or ``ucryptolib.MODE_ECB`` if it exists) for Electronic Code Book (ECB). * ``2`` (or ``ucryptolib.MODE_CBC`` if it exists) for Cipher Block Chaining (CBC). * ``6`` (or ``ucryptolib.MODE_CTR`` if it exists) for Counter mode (CTR). * *IV* is an initialization vector for CBC mode. * For Counter mode, *IV* is the initial value for the counter. .. method:: encrypt(in_buf, [out_buf]) Encrypt *in_buf*. If no *out_buf* is given result is returned as a newly allocated `bytes` object. Otherwise, result is written into mutable buffer *out_buf*. *in_buf* and *out_buf* can also refer to the same mutable buffer, in which case data is encrypted in-place. .. method:: decrypt(in_buf, [out_buf]) Like `encrypt()`, but for decryption. micropython-1.12/docs/library/uctypes.rst000066400000000000000000000301661357706137100206520ustar00rootroot00000000000000:mod:`uctypes` -- access binary data in a structured way ======================================================== .. module:: uctypes :synopsis: access binary data in a structured way This module implements "foreign data interface" for MicroPython. The idea behind it is similar to CPython's ``ctypes`` modules, but the actual API is different, streamlined and optimized for small size. The basic idea of the module is to define data structure layout with about the same power as the C language allows, and then access it using familiar dot-syntax to reference sub-fields. .. warning:: ``uctypes`` module allows access to arbitrary memory addresses of the machine (including I/O and control registers). Uncareful usage of it may lead to crashes, data loss, and even hardware malfunction. .. seealso:: Module :mod:`ustruct` Standard Python way to access binary data structures (doesn't scale well to large and complex structures). Usage examples:: import uctypes # Example 1: Subset of ELF file header # https://wikipedia.org/wiki/Executable_and_Linkable_Format#File_header ELF_HEADER = { "EI_MAG": (0x0 | uctypes.ARRAY, 4 | uctypes.UINT8), "EI_DATA": 0x5 | uctypes.UINT8, "e_machine": 0x12 | uctypes.UINT16, } # "f" is an ELF file opened in binary mode buf = f.read(uctypes.sizeof(ELF_HEADER, uctypes.LITTLE_ENDIAN)) header = uctypes.struct(uctypes.addressof(buf), ELF_HEADER, uctypes.LITTLE_ENDIAN) assert header.EI_MAG == b"\x7fELF" assert header.EI_DATA == 1, "Oops, wrong endianness. Could retry with uctypes.BIG_ENDIAN." print("machine:", hex(header.e_machine)) # Example 2: In-memory data structure, with pointers COORD = { "x": 0 | uctypes.FLOAT32, "y": 4 | uctypes.FLOAT32, } STRUCT1 = { "data1": 0 | uctypes.UINT8, "data2": 4 | uctypes.UINT32, "ptr": (8 | uctypes.PTR, COORD), } # Suppose you have address of a structure of type STRUCT1 in "addr" # uctypes.NATIVE is optional (used by default) struct1 = uctypes.struct(addr, STRUCT1, uctypes.NATIVE) print("x:", struct1.ptr[0].x) # Example 3: Access to CPU registers. Subset of STM32F4xx WWDG block WWDG_LAYOUT = { "WWDG_CR": (0, { # BFUINT32 here means size of the WWDG_CR register "WDGA": 7 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32, "T": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32, }), "WWDG_CFR": (4, { "EWI": 9 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32, "WDGTB": 7 << uctypes.BF_POS | 2 << uctypes.BF_LEN | uctypes.BFUINT32, "W": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32, }), } WWDG = uctypes.struct(0x40002c00, WWDG_LAYOUT) WWDG.WWDG_CFR.WDGTB = 0b10 WWDG.WWDG_CR.WDGA = 1 print("Current counter:", WWDG.WWDG_CR.T) Defining structure layout ------------------------- Structure layout is defined by a "descriptor" - a Python dictionary which encodes field names as keys and other properties required to access them as associated values:: { "field1": , "field2": , ... } Currently, ``uctypes`` requires explicit specification of offsets for each field. Offset are given in bytes from the structure start. Following are encoding examples for various field types: * Scalar types:: "field_name": offset | uctypes.UINT32 in other words, the value is a scalar type identifier ORed with a field offset (in bytes) from the start of the structure. * Recursive structures:: "sub": (offset, { "b0": 0 | uctypes.UINT8, "b1": 1 | uctypes.UINT8, }) i.e. value is a 2-tuple, first element of which is an offset, and second is a structure descriptor dictionary (note: offsets in recursive descriptors are relative to the structure it defines). Of course, recursive structures can be specified not just by a literal dictionary, but by referring to a structure descriptor dictionary (defined earlier) by name. * Arrays of primitive types:: "arr": (offset | uctypes.ARRAY, size | uctypes.UINT8), i.e. value is a 2-tuple, first element of which is ARRAY flag ORed with offset, and second is scalar element type ORed number of elements in the array. * Arrays of aggregate types:: "arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}), i.e. value is a 3-tuple, first element of which is ARRAY flag ORed with offset, second is a number of elements in the array, and third is a descriptor of element type. * Pointer to a primitive type:: "ptr": (offset | uctypes.PTR, uctypes.UINT8), i.e. value is a 2-tuple, first element of which is PTR flag ORed with offset, and second is a scalar element type. * Pointer to an aggregate type:: "ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}), i.e. value is a 2-tuple, first element of which is PTR flag ORed with offset, second is a descriptor of type pointed to. * Bitfields:: "bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN, i.e. value is a type of scalar value containing given bitfield (typenames are similar to scalar types, but prefixes with ``BF``), ORed with offset for scalar value containing the bitfield, and further ORed with values for bit position and bit length of the bitfield within the scalar value, shifted by BF_POS and BF_LEN bits, respectively. A bitfield position is counted from the least significant bit of the scalar (having position of 0), and is the number of right-most bit of a field (in other words, it's a number of bits a scalar needs to be shifted right to extract the bitfield). In the example above, first a UINT16 value will be extracted at offset 0 (this detail may be important when accessing hardware registers, where particular access size and alignment are required), and then bitfield whose rightmost bit is *lsbit* bit of this UINT16, and length is *bitsize* bits, will be extracted. For example, if *lsbit* is 0 and *bitsize* is 8, then effectively it will access least-significant byte of UINT16. Note that bitfield operations are independent of target byte endianness, in particular, example above will access least-significant byte of UINT16 in both little- and big-endian structures. But it depends on the least significant bit being numbered 0. Some targets may use different numbering in their native ABI, but ``uctypes`` always uses the normalized numbering described above. Module contents --------------- .. class:: struct(addr, descriptor, layout_type=NATIVE) Instantiate a "foreign data structure" object based on structure address in memory, descriptor (encoded as a dictionary), and layout type (see below). .. data:: LITTLE_ENDIAN Layout type for a little-endian packed structure. (Packed means that every field occupies exactly as many bytes as defined in the descriptor, i.e. the alignment is 1). .. data:: BIG_ENDIAN Layout type for a big-endian packed structure. .. data:: NATIVE Layout type for a native structure - with data endianness and alignment conforming to the ABI of the system on which MicroPython runs. .. function:: sizeof(struct, layout_type=NATIVE) Return size of data structure in bytes. The *struct* argument can be either a structure class or a specific instantiated structure object (or its aggregate field). .. function:: addressof(obj) Return address of an object. Argument should be bytes, bytearray or other object supporting buffer protocol (and address of this buffer is what actually returned). .. function:: bytes_at(addr, size) Capture memory at the given address and size as bytes object. As bytes object is immutable, memory is actually duplicated and copied into bytes object, so if memory contents change later, created object retains original value. .. function:: bytearray_at(addr, size) Capture memory at the given address and size as bytearray object. Unlike bytes_at() function above, memory is captured by reference, so it can be both written too, and you will access current value at the given memory address. .. data:: UINT8 INT8 UINT16 INT16 UINT32 INT32 UINT64 INT64 Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and unsigned. .. data:: FLOAT32 FLOAT64 Floating-point types for structure descriptors. .. data:: VOID ``VOID`` is an alias for ``UINT8``, and is provided to conviniently define C's void pointers: ``(uctypes.PTR, uctypes.VOID)``. .. data:: PTR ARRAY Type constants for pointers and arrays. Note that there is no explicit constant for structures, it's implicit: an aggregate type without ``PTR`` or ``ARRAY`` flags is a structure. Structure descriptors and instantiating structure objects --------------------------------------------------------- Given a structure descriptor dictionary and its layout type, you can instantiate a specific structure instance at a given memory address using :class:`uctypes.struct()` constructor. Memory address usually comes from following sources: * Predefined address, when accessing hardware registers on a baremetal system. Lookup these addresses in datasheet for a particular MCU/SoC. * As a return value from a call to some FFI (Foreign Function Interface) function. * From `uctypes.addressof()`, when you want to pass arguments to an FFI function, or alternatively, to access some data for I/O (for example, data read from a file or network socket). Structure objects ----------------- Structure objects allow accessing individual fields using standard dot notation: ``my_struct.substruct1.field1``. If a field is of scalar type, getting it will produce a primitive value (Python integer or float) corresponding to the value contained in a field. A scalar field can also be assigned to. If a field is an array, its individual elements can be accessed with the standard subscript operator ``[]`` - both read and assigned to. If a field is a pointer, it can be dereferenced using ``[0]`` syntax (corresponding to C ``*`` operator, though ``[0]`` works in C too). Subscripting a pointer with other integer values but 0 are also supported, with the same semantics as in C. Summing up, accessing structure fields generally follows the C syntax, except for pointer dereference, when you need to use ``[0]`` operator instead of ``*``. Limitations ----------- 1. Accessing non-scalar fields leads to allocation of intermediate objects to represent them. This means that special care should be taken to layout a structure which needs to be accessed when memory allocation is disabled (e.g. from an interrupt). The recommendations are: * Avoid accessing nested structures. For example, instead of ``mcu_registers.peripheral_a.register1``, define separate layout descriptors for each peripheral, to be accessed as ``peripheral_a.register1``. Or just cache a particular peripheral: ``peripheral_a = mcu_registers.peripheral_a``. If a register consists of multiple bitfields, you would need to cache references to a particular register: ``reg_a = mcu_registers.peripheral_a.reg_a``. * Avoid other non-scalar data, like arrays. For example, instead of ``peripheral_a.register[0]`` use ``peripheral_a.register0``. Again, an alternative is to cache intermediate values, e.g. ``register0 = peripheral_a.register[0]``. 2. Range of offsets supported by the ``uctypes`` module is limited. The exact range supported is considered an implementation detail, and the general suggestion is to split structure definitions to cover from a few kilobytes to a few dozen of kilobytes maximum. In most cases, this is a natural situation anyway, e.g. it doesn't make sense to define all registers of an MCU (spread over 32-bit address space) in one structure, but rather a peripheral block by peripheral block. In some extreme cases, you may need to split a structure in several parts artificially (e.g. if accessing native data structure with multi-megabyte array in the middle, though that would be a very synthetic case). micropython-1.12/docs/library/uerrno.rst000066400000000000000000000017441357706137100204700ustar00rootroot00000000000000:mod:`uerrno` -- system error codes =================================== .. module:: uerrno :synopsis: system error codes |see_cpython_module| :mod:`python:errno`. This module provides access to symbolic error codes for `OSError` exception. A particular inventory of codes depends on `MicroPython port`. Constants --------- .. data:: EEXIST, EAGAIN, etc. Error codes, based on ANSI C/POSIX standard. All error codes start with "E". As mentioned above, inventory of the codes depends on `MicroPython port`. Errors are usually accessible as ``exc.args[0]`` where ``exc`` is an instance of `OSError`. Usage example:: try: uos.mkdir("my_dir") except OSError as exc: if exc.args[0] == uerrno.EEXIST: print("Directory already exists") .. data:: errorcode Dictionary mapping numeric error codes to strings with symbolic error code (see above):: >>> print(uerrno.errorcode[uerrno.EEXIST]) EEXIST micropython-1.12/docs/library/uhashlib.rst000066400000000000000000000033531357706137100207530ustar00rootroot00000000000000:mod:`uhashlib` -- hashing algorithms ===================================== .. module:: uhashlib :synopsis: hashing algorithms |see_cpython_module| :mod:`python:hashlib`. This module implements binary data hashing algorithms. The exact inventory of available algorithms depends on a board. Among the algorithms which may be implemented: * SHA256 - The current generation, modern hashing algorithm (of SHA2 series). It is suitable for cryptographically-secure purposes. Included in the MicroPython core and any board is recommended to provide this, unless it has particular code size constraints. * SHA1 - A previous generation algorithm. Not recommended for new usages, but SHA1 is a part of number of Internet standards and existing applications, so boards targeting network connectivity and interoperability will try to provide this. * MD5 - A legacy algorithm, not considered cryptographically secure. Only selected boards, targeting interoperability with legacy applications, will offer this. Constructors ------------ .. class:: uhashlib.sha256([data]) Create an SHA256 hasher object and optionally feed ``data`` into it. .. class:: uhashlib.sha1([data]) Create an SHA1 hasher object and optionally feed ``data`` into it. .. class:: uhashlib.md5([data]) Create an MD5 hasher object and optionally feed ``data`` into it. Methods ------- .. method:: hash.update(data) Feed more binary data into hash. .. method:: hash.digest() Return hash for all data passed through hash, as a bytes object. After this method is called, more data cannot be fed into the hash any longer. .. method:: hash.hexdigest() This method is NOT implemented. Use ``ubinascii.hexlify(hash.digest())`` to achieve a similar effect. micropython-1.12/docs/library/uheapq.rst000066400000000000000000000011601357706137100204310ustar00rootroot00000000000000:mod:`uheapq` -- heap queue algorithm ===================================== .. module:: uheapq :synopsis: heap queue algorithm |see_cpython_module| :mod:`python:heapq`. This module implements the heap queue algorithm. A heap queue is simply a list that has its elements stored in a certain way. Functions --------- .. function:: heappush(heap, item) Push the ``item`` onto the ``heap``. .. function:: heappop(heap) Pop the first item from the ``heap``, and return it. Raises IndexError if heap is empty. .. function:: heapify(x) Convert the list ``x`` into a heap. This is an in-place operation. micropython-1.12/docs/library/uio.rst000066400000000000000000000133651357706137100177540ustar00rootroot00000000000000:mod:`uio` -- input/output streams ================================== .. module:: uio :synopsis: input/output streams |see_cpython_module| :mod:`python:io`. This module contains additional types of `stream` (file-like) objects and helper functions. Conceptual hierarchy -------------------- .. admonition:: Difference to CPython :class: attention Conceptual hierarchy of stream base classes is simplified in MicroPython, as described in this section. (Abstract) base stream classes, which serve as a foundation for behavior of all the concrete classes, adhere to few dichotomies (pair-wise classifications) in CPython. In MicroPython, they are somewhat simplified and made implicit to achieve higher efficiencies and save resources. An important dichotomy in CPython is unbuffered vs buffered streams. In MicroPython, all streams are currently unbuffered. This is because all modern OSes, and even many RTOSes and filesystem drivers already perform buffering on their side. Adding another layer of buffering is counter- productive (an issue known as "bufferbloat") and takes precious memory. Note that there still cases where buffering may be useful, so we may introduce optional buffering support at a later time. But in CPython, another important dichotomy is tied with "bufferedness" - it's whether a stream may incur short read/writes or not. A short read is when a user asks e.g. 10 bytes from a stream, but gets less, similarly for writes. In CPython, unbuffered streams are automatically short operation susceptible, while buffered are guarantee against them. The no short read/writes is an important trait, as it allows to develop more concise and efficient programs - something which is highly desirable for MicroPython. So, while MicroPython doesn't support buffered streams, it still provides for no-short-operations streams. Whether there will be short operations or not depends on each particular class' needs, but developers are strongly advised to favor no-short-operations behavior for the reasons stated above. For example, MicroPython sockets are guaranteed to avoid short read/writes. Actually, at this time, there is no example of a short-operations stream class in the core, and one would be a port-specific class, where such a need is governed by hardware peculiarities. The no-short-operations behavior gets tricky in case of non-blocking streams, blocking vs non-blocking behavior being another CPython dichotomy, fully supported by MicroPython. Non-blocking streams never wait for data either to arrive or be written - they read/write whatever possible, or signal lack of data (or ability to write data). Clearly, this conflicts with "no-short-operations" policy, and indeed, a case of non-blocking buffered (and this no-short-ops) streams is convoluted in CPython - in some places, such combination is prohibited, in some it's undefined or just not documented, in some cases it raises verbose exceptions. The matter is much simpler in MicroPython: non-blocking stream are important for efficient asynchronous operations, so this property prevails on the "no-short-ops" one. So, while blocking streams will avoid short reads/writes whenever possible (the only case to get a short read is if end of file is reached, or in case of error (but errors don't return short data, but raise exceptions)), non-blocking streams may produce short data to avoid blocking the operation. The final dichotomy is binary vs text streams. MicroPython of course supports these, but while in CPython text streams are inherently buffered, they aren't in MicroPython. (Indeed, that's one of the cases for which we may introduce buffering support.) Note that for efficiency, MicroPython doesn't provide abstract base classes corresponding to the hierarchy above, and it's not possible to implement, or subclass, a stream class in pure Python. Functions --------- .. function:: open(name, mode='r', **kwargs) Open a file. Builtin ``open()`` function is aliased to this function. All ports (which provide access to file system) are required to support *mode* parameter, but support for other arguments vary by port. Classes ------- .. class:: FileIO(...) This is type of a file open in binary mode, e.g. using ``open(name, "rb")``. You should not instantiate this class directly. .. class:: TextIOWrapper(...) This is type of a file open in text mode, e.g. using ``open(name, "rt")``. You should not instantiate this class directly. .. class:: StringIO([string]) .. class:: BytesIO([string]) In-memory file-like objects for input/output. `StringIO` is used for text-mode I/O (similar to a normal file opened with "t" modifier). `BytesIO` is used for binary-mode I/O (similar to a normal file opened with "b" modifier). Initial contents of file-like objects can be specified with *string* parameter (should be normal string for `StringIO` or bytes object for `BytesIO`). All the usual file methods like ``read()``, ``write()``, ``seek()``, ``flush()``, ``close()`` are available on these objects, and additionally, a following method: .. method:: getvalue() Get the current contents of the underlying buffer which holds data. .. class:: StringIO(alloc_size) .. class:: BytesIO(alloc_size) Create an empty `StringIO`/`BytesIO` object, preallocated to hold up to *alloc_size* number of bytes. That means that writing that amount of bytes won't lead to reallocation of the buffer, and thus won't hit out-of-memory situation or lead to memory fragmentation. These constructors are a MicroPython extension and are recommended for usage only in special cases and in system-level libraries, not for end-user applications. .. admonition:: Difference to CPython :class: attention These constructors are a MicroPython extension. micropython-1.12/docs/library/ujson.rst000066400000000000000000000016361357706137100203140ustar00rootroot00000000000000:mod:`ujson` -- JSON encoding and decoding ========================================== .. module:: ujson :synopsis: JSON encoding and decoding |see_cpython_module| :mod:`python:json`. This modules allows to convert between Python objects and the JSON data format. Functions --------- .. function:: dump(obj, stream) Serialise *obj* to a JSON string, writing it to the given *stream*. .. function:: dumps(obj) Return *obj* represented as a JSON string. .. function:: load(stream) Parse the given *stream*, interpreting it as a JSON string and deserialising the data to a Python object. The resulting object is returned. Parsing continues until end-of-file is encountered. A :exc:`ValueError` is raised if the data in *stream* is not correctly formed. .. function:: loads(str) Parse the JSON *str* and return an object. Raises :exc:`ValueError` if the string is not correctly formed. micropython-1.12/docs/library/uos.rst000066400000000000000000000272701357706137100177660ustar00rootroot00000000000000:mod:`uos` -- basic "operating system" services =============================================== .. module:: uos :synopsis: basic "operating system" services |see_cpython_module| :mod:`python:os`. The ``uos`` module contains functions for filesystem access and mounting, terminal redirection and duplication, and the ``uname`` and ``urandom`` functions. General functions ----------------- .. function:: uname() Return a tuple (possibly a named tuple) containing information about the underlying machine and/or its operating system. The tuple has five fields in the following order, each of them being a string: * ``sysname`` -- the name of the underlying system * ``nodename`` -- the network name (can be the same as ``sysname``) * ``release`` -- the version of the underlying system * ``version`` -- the MicroPython version and build date * ``machine`` -- an identifier for the underlying hardware (eg board, CPU) .. function:: urandom(n) Return a bytes object with *n* random bytes. Whenever possible, it is generated by the hardware random number generator. Filesystem access ----------------- .. function:: chdir(path) Change current directory. .. function:: getcwd() Get the current directory. .. function:: ilistdir([dir]) This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is listing. With no argument it lists the current directory, otherwise it lists the directory given by *dir*. The tuples have the form *(name, type, inode[, size])*: - *name* is a string (or bytes if *dir* is a bytes object) and is the name of the entry; - *type* is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files; - *inode* is an integer corresponding to the inode of the file, and may be 0 for filesystems that don't have such a notion. - Some platforms may return a 4-tuple that includes the entry's *size*. For file entries, *size* is an integer representing the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries. .. function:: listdir([dir]) With no argument, list the current directory. Otherwise list the given directory. .. function:: mkdir(path) Create a new directory. .. function:: remove(path) Remove a file. .. function:: rmdir(path) Remove a directory. .. function:: rename(old_path, new_path) Rename a file. .. function:: stat(path) Get the status of a file or directory. .. function:: statvfs(path) Get the status of a fileystem. Returns a tuple with the filesystem information in the following order: * ``f_bsize`` -- file system block size * ``f_frsize`` -- fragment size * ``f_blocks`` -- size of fs in f_frsize units * ``f_bfree`` -- number of free blocks * ``f_bavail`` -- number of free blocks for unprivileged users * ``f_files`` -- number of inodes * ``f_ffree`` -- number of free inodes * ``f_favail`` -- number of free inodes for unprivileged users * ``f_flag`` -- mount flags * ``f_namemax`` -- maximum filename length Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail`` and the ``f_flags`` parameter may return ``0`` as they can be unavailable in a port-specific implementation. .. function:: sync() Sync all filesystems. Terminal redirection and duplication ------------------------------------ .. function:: dupterm(stream_object, index=0) Duplicate or switch the MicroPython terminal (the REPL) on the given `stream`-like object. The *stream_object* argument must be a native stream object, or derive from ``uio.IOBase`` and implement the ``readinto()`` and ``write()`` methods. The stream should be in non-blocking mode and ``readinto()`` should return ``None`` if there is no data available for reading. After calling this function all terminal output is repeated on this stream, and any input that is available on the stream is passed on to the terminal input. The *index* parameter should be a non-negative integer and specifies which duplication slot is set. A given port may implement more than one slot (slot 0 will always be available) and in that case terminal input and output is duplicated on all the slots that are set. If ``None`` is passed as the *stream_object* then duplication is cancelled on the slot given by *index*. The function returns the previous stream-like object in the given slot. Filesystem mounting ------------------- Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple "real" filesystems within this VFS. Filesystem objects can be mounted at either the root of the VFS, or at a subdirectory that lives in the root. This allows dynamic and flexible configuration of the filesystem that is seen by Python programs. Ports that have this functionality provide the :func:`mount` and :func:`umount` functions, and possibly various filesystem implementations represented by VFS classes. .. function:: mount(fsobj, mount_point, \*, readonly) Mount the filesystem object *fsobj* at the location in the VFS given by the *mount_point* string. *fsobj* can be a a VFS object that has a ``mount()`` method, or a block device. If it's a block device then the filesystem type is automatically detected (an exception is raised if no filesystem was recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root, or ``'/'`` to mount it at a subdirectory under the root. If *readonly* is ``True`` then the filesystem is mounted read-only. During the mount process the method ``mount()`` is called on the filesystem object. Will raise ``OSError(EPERM)`` if *mount_point* is already mounted. .. function:: umount(mount_point) Unmount a filesystem. *mount_point* can be a string naming the mount location, or a previously-mounted filesystem object. During the unmount process the method ``umount()`` is called on the filesystem object. Will raise ``OSError(EINVAL)`` if *mount_point* is not found. .. class:: VfsFat(block_dev) Create a filesystem object that uses the FAT filesystem format. Storage of the FAT filesystem is provided by *block_dev*. Objects created by this constructor can be mounted using :func:`mount`. .. staticmethod:: mkfs(block_dev) Build a FAT filesystem on *block_dev*. .. class:: VfsLfs1(block_dev) Create a filesystem object that uses the `littlefs v1 filesystem format`_. Storage of the littlefs filesystem is provided by *block_dev*, which must support the :ref:`extended interface `. Objects created by this constructor can be mounted using :func:`mount`. See :ref:`filesystem` for more information. .. staticmethod:: mkfs(block_dev) Build a Lfs1 filesystem on *block_dev*. .. note:: There are reports of littlefs v1 failing in certain situations, for details see `littlefs issue 347`_. .. class:: VfsLfs2(block_dev) Create a filesystem object that uses the `littlefs v2 filesystem format`_. Storage of the littlefs filesystem is provided by *block_dev*, which must support the :ref:`extended interface `. Objects created by this constructor can be mounted using :func:`mount`. See :ref:`filesystem` for more information. .. staticmethod:: mkfs(block_dev) Build a Lfs2 filesystem on *block_dev*. .. note:: There are reports of littlefs v2 failing in certain situations, for details see `littlefs issue 295`_. .. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1 .. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs .. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295 .. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347 Block devices ------------- A block device is an object which implements the block protocol, which is a set of methods described below by the :class:`AbstractBlockDev` class. A concrete implementation of this class will usually allow access to the memory-like functionality a piece of hardware (like flash memory). A block device can be used by a particular filesystem driver to store the data for its filesystem. .. _block-device-interface: Simple and extended interface ............................. There are two compatible signatures for the ``readblocks`` and ``writeblocks`` methods (see below), in order to support a variety of use cases. A given block device may implement one form or the other, or both at the same time. The second form (with the offset parameter) is referred to as the "extended interface". Some filesystems (such as littlefs) that require more control over write operations, for example writing to sub-block regions without erasing, may require that the block device supports the extended interface. .. class:: AbstractBlockDev(...) Construct a block device object. The parameters to the constructor are dependent on the specific block device. .. method:: readblocks(block_num, buf) .. method:: readblocks(block_num, buf, offset) The first form reads aligned, multiples of blocks. Starting at the block given by the index *block_num*, read blocks from the device into *buf* (an array of bytes). The number of blocks to read is given by the length of *buf*, which will be a multiple of the block size. The second form allows reading at arbitrary locations within a block, and arbitrary lengths. Starting at block index *block_num*, and byte offset within that block of *offset*, read bytes from the device into *buf* (an array of bytes). The number of bytes to read is given by the length of *buf*. .. method:: writeblocks(block_num, buf) .. method:: writeblocks(block_num, buf, offset) The first form writes aligned, multiples of blocks, and requires that the blocks that are written to be first erased (if necessary) by this method. Starting at the block given by the index *block_num*, write blocks from *buf* (an array of bytes) to the device. The number of blocks to write is given by the length of *buf*, which will be a multiple of the block size. The second form allows writing at arbitrary locations within a block, and arbitrary lengths. Only the bytes being written should be changed, and the caller of this method must ensure that the relevant blocks are erased via a prior ``ioctl`` call. Starting at block index *block_num*, and byte offset within that block of *offset*, write bytes from *buf* (an array of bytes) to the device. The number of bytes to write is given by the length of *buf*. Note that implementations must never implicitly erase blocks if the offset argument is specified, even if it is zero. .. method:: ioctl(op, arg) Control the block device and query its parameters. The operation to perform is given by *op* which is one of the following integers: - 1 -- initialise the device (*arg* is unused) - 2 -- shutdown the device (*arg* is unused) - 3 -- sync the device (*arg* is unused) - 4 -- get a count of the number of blocks, should return an integer (*arg* is unused) - 5 -- get the number of bytes in a block, should return an integer, or ``None`` in which case the default value of 512 is used (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase See :ref:`filesystem` for example implementations of block devices using both protocols. micropython-1.12/docs/library/ure.rst000066400000000000000000000134541357706137100177520ustar00rootroot00000000000000:mod:`ure` -- simple regular expressions ======================================== .. module:: ure :synopsis: regular expressions |see_cpython_module| :mod:`python:re`. This module implements regular expression operations. Regular expression syntax supported is a subset of CPython ``re`` module (and actually is a subset of POSIX extended regular expressions). Supported operators and special sequences are: ``.`` Match any character. ``[...]`` Match set of characters. Individual characters and ranges are supported, including negated sets (e.g. ``[^a-c]``). ``^`` Match the start of the string. ``$`` Match the end of the string. ``?`` Match zero or one of the previous sub-pattern. ``*`` Match zero or more of the previous sub-pattern. ``+`` Match one or more of the previous sub-pattern. ``??`` Non-greedy version of ``?``, match zero or one, with the preference for zero. ``*?`` Non-greedy version of ``*``, match zero or more, with the preference for the shortest match. ``+?`` Non-greedy version of ``+``, match one or more, with the preference for the shortest match. ``|`` Match either the left-hand side or the right-hand side sub-patterns of this operator. ``(...)`` Grouping. Each group is capturing (a substring it captures can be accessed with `match.group()` method). ``\d`` Matches digit. Equivalent to ``[0-9]``. ``\D`` Matches non-digit. Equivalent to ``[^0-9]``. ``\s`` Matches whitespace. Equivalent to ``[ \t-\r]``. ``\S`` Matches non-whitespace. Equivalent to ``[^ \t-\r]``. ``\w`` Matches "word characters" (ASCII only). Equivalent to ``[A-Za-z0-9_]``. ``\W`` Matches non "word characters" (ASCII only). Equivalent to ``[^A-Za-z0-9_]``. ``\`` Escape character. Any other character following the backslash, except for those listed above, is taken literally. For example, ``\*`` is equivalent to literal ``*`` (not treated as the ``*`` operator). Note that ``\r``, ``\n``, etc. are not handled specially, and will be equivalent to literal letters ``r``, ``n``, etc. Due to this, it's not recommended to use raw Python strings (``r""``) for regular expressions. For example, ``r"\r\n"`` when used as the regular expression is equivalent to ``"rn"``. To match CR character followed by LF, use ``"\r\n"``. **NOT SUPPORTED**: * counted repetitions (``{m,n}``) * named groups (``(?P...)``) * non-capturing groups (``(?:...)``) * more advanced assertions (``\b``, ``\B``) * special character escapes like ``\r``, ``\n`` - use Python's own escaping instead * etc. Example:: import ure # As ure doesn't support escapes itself, use of r"" strings is not # recommended. regex = ure.compile("[\r\n]") regex.split("line1\rline2\nline3\r\n") # Result: # ['line1', 'line2', 'line3', '', ''] Functions --------- .. function:: compile(regex_str, [flags]) Compile regular expression, return `regex ` object. .. function:: match(regex_str, string) Compile *regex_str* and match against *string*. Match always happens from starting position in a string. .. function:: search(regex_str, string) Compile *regex_str* and search it in a *string*. Unlike `match`, this will search string for first position which matches regex (which still may be 0 if regex is anchored). .. function:: sub(regex_str, replace, string, count=0, flags=0) Compile *regex_str* and search for it in *string*, replacing all matches with *replace*, and returning the new string. *replace* can be a string or a function. If it is a string then escape sequences of the form ``\`` and ``\g`` can be used to expand to the corresponding group (or an empty string for unmatched groups). If *replace* is a function then it must take a single argument (the match) and should return a replacement string. If *count* is specified and non-zero then substitution will stop after this many substitutions are made. The *flags* argument is ignored. Note: availability of this function depends on `MicroPython port`. .. data:: DEBUG Flag value, display debug information about compiled expression. (Availability depends on `MicroPython port`.) .. _regex: Regex objects ------------- Compiled regular expression. Instances of this class are created using `ure.compile()`. .. method:: regex.match(string) regex.search(string) regex.sub(replace, string, count=0, flags=0) Similar to the module-level functions :meth:`match`, :meth:`search` and :meth:`sub`. Using methods is (much) more efficient if the same regex is applied to multiple strings. .. method:: regex.split(string, max_split=-1) Split a *string* using regex. If *max_split* is given, it specifies maximum number of splits to perform. Returns list of strings (there may be up to *max_split+1* elements if it's specified). Match objects ------------- Match objects as returned by `match()` and `search()` methods, and passed to the replacement function in `sub()`. .. method:: match.group(index) Return matching (sub)string. *index* is 0 for entire match, 1 and above for each capturing group. Only numeric groups are supported. .. method:: match.groups() Return a tuple containing all the substrings of the groups of the match. Note: availability of this method depends on `MicroPython port`. .. method:: match.start([index]) match.end([index]) Return the index in the original string of the start or end of the substring group that was matched. *index* defaults to the entire group, otherwise it will select a group. Note: availability of these methods depends on `MicroPython port`. .. method:: match.span([index]) Returns the 2-tuple ``(match.start(index), match.end(index))``. Note: availability of this method depends on `MicroPython port`. micropython-1.12/docs/library/uselect.rst000066400000000000000000000067001357706137100206170ustar00rootroot00000000000000:mod:`uselect` -- wait for events on a set of streams ======================================================================== .. module:: uselect :synopsis: wait for events on a set of streams |see_cpython_module| :mod:`python:select`. This module provides functions to efficiently wait for events on multiple `streams ` (select streams which are ready for operations). Functions --------- .. function:: poll() Create an instance of the Poll class. .. function:: select(rlist, wlist, xlist[, timeout]) Wait for activity on a set of objects. This function is provided by some MicroPython ports for compatibility and is not efficient. Usage of :class:`Poll` is recommended instead. .. _class: Poll class ``Poll`` -------------- Methods ~~~~~~~ .. method:: poll.register(obj[, eventmask]) Register `stream` *obj* for polling. *eventmask* is logical OR of: * ``uselect.POLLIN`` - data available for reading * ``uselect.POLLOUT`` - more data can be written Note that flags like ``uselect.POLLHUP`` and ``uselect.POLLERR`` are *not* valid as input eventmask (these are unsolicited events which will be returned from `poll()` regardless of whether they are asked for). This semantics is per POSIX. *eventmask* defaults to ``uselect.POLLIN | uselect.POLLOUT``. It is OK to call this function multiple times for the same *obj*. Successive calls will update *obj*'s eventmask to the value of *eventmask* (i.e. will behave as `modify()`). .. method:: poll.unregister(obj) Unregister *obj* from polling. .. method:: poll.modify(obj, eventmask) Modify the *eventmask* for *obj*. If *obj* is not registered, `OSError` is raised with error of ENOENT. .. method:: poll.poll(timeout=-1) Wait for at least one of the registered objects to become ready or have an exceptional condition, with optional timeout in milliseconds (if *timeout* arg is not specified or -1, there is no timeout). Returns list of (``obj``, ``event``, ...) tuples. There may be other elements in tuple, depending on a platform and version, so don't assume that its size is 2. The ``event`` element specifies which events happened with a stream and is a combination of ``uselect.POLL*`` constants described above. Note that flags ``uselect.POLLHUP`` and ``uselect.POLLERR`` can be returned at any time (even if were not asked for), and must be acted on accordingly (the corresponding stream unregistered from poll and likely closed), because otherwise all further invocations of `poll()` may return immediately with these flags set for this stream again. In case of timeout, an empty list is returned. .. admonition:: Difference to CPython :class: attention Tuples returned may contain more than 2 elements as described above. .. method:: poll.ipoll(timeout=-1, flags=0) Like :meth:`poll.poll`, but instead returns an iterator which yields a `callee-owned tuple`. This function provides an efficient, allocation-free way to poll on streams. If *flags* is 1, one-shot behavior for events is employed: streams for which events happened will have their event masks automatically reset (equivalent to ``poll.modify(obj, 0)``), so new events for such a stream won't be processed until new mask is set with `poll.modify()`. This behavior is useful for asynchronous I/O schedulers. .. admonition:: Difference to CPython :class: attention This function is a MicroPython extension. micropython-1.12/docs/library/usocket.rst000066400000000000000000000327111357706137100206310ustar00rootroot00000000000000******************************* :mod:`usocket` -- socket module ******************************* .. module:: usocket :synopsis: socket module |see_cpython_module| :mod:`python:socket`. This module provides access to the BSD socket interface. .. admonition:: Difference to CPython :class: attention For efficiency and consistency, socket objects in MicroPython implement a `stream` (file-like) interface directly. In CPython, you need to convert a socket to a file-like object using `makefile()` method. This method is still supported by MicroPython (but is a no-op), so where compatibility with CPython matters, be sure to use it. Socket address format(s) ------------------------ The native socket address format of the ``usocket`` module is an opaque data type returned by `getaddrinfo` function, which must be used to resolve textual address (including numeric addresses):: sockaddr = usocket.getaddrinfo('www.micropython.org', 80)[0][-1] # You must use getaddrinfo() even for numeric addresses sockaddr = usocket.getaddrinfo('127.0.0.1', 80)[0][-1] # Now you can use that address sock.connect(addr) Using `getaddrinfo` is the most efficient (both in terms of memory and processing power) and portable way to work with addresses. However, ``socket`` module (note the difference with native MicroPython ``usocket`` module described here) provides CPython-compatible way to specify addresses using tuples, as described below. Note that depending on a `MicroPython port`, ``socket`` module can be builtin or need to be installed from `micropython-lib` (as in the case of `MicroPython Unix port`), and some ports still accept only numeric addresses in the tuple format, and require to use `getaddrinfo` function to resolve domain names. Summing up: * Always use `getaddrinfo` when writing portable applications. * Tuple addresses described below can be used as a shortcut for quick hacks and interactive use, if your port supports them. Tuple address format for ``socket`` module: * IPv4: *(ipv4_address, port)*, where *ipv4_address* is a string with dot-notation numeric IPv4 address, e.g. ``"8.8.8.8"``, and *port* is and integer port number in the range 1-65535. Note the domain names are not accepted as *ipv4_address*, they should be resolved first using `usocket.getaddrinfo()`. * IPv6: *(ipv6_address, port, flowinfo, scopeid)*, where *ipv6_address* is a string with colon-notation numeric IPv6 address, e.g. ``"2001:db8::1"``, and *port* is an integer port number in the range 1-65535. *flowinfo* must be 0. *scopeid* is the interface scope identifier for link-local addresses. Note the domain names are not accepted as *ipv6_address*, they should be resolved first using `usocket.getaddrinfo()`. Availability of IPv6 support depends on a `MicroPython port`. Functions --------- .. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP) Create a new socket using the given address family, socket type and protocol number. Note that specifying *proto* in most cases is not required (and not recommended, as some MicroPython ports may omit ``IPPROTO_*`` constants). Instead, *type* argument will select needed protocol automatically:: # Create STREAM TCP socket socket(AF_INET, SOCK_STREAM) # Create DGRAM UDP socket socket(AF_INET, SOCK_DGRAM) .. function:: getaddrinfo(host, port, af=0, type=0, proto=0, flags=0) Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. Arguments *af*, *type*, and *proto* (which have the same meaning as for the `socket()` function) can be used to filter which kind of addresses are returned. If a parameter is not specified or zero, all combinations of addresses can be returned (requiring filtering on the user side). The resulting list of 5-tuples has the following structure:: (family, type, proto, canonname, sockaddr) The following example shows how to connect to a given url:: s = usocket.socket() # This assumes that if "type" is not specified, an address for # SOCK_STREAM will be returned, which may be not true s.connect(usocket.getaddrinfo('www.micropython.org', 80)[0][-1]) Recommended use of filtering params:: s = usocket.socket() # Guaranteed to return an address which can be connect'ed to for # stream operation. s.connect(usocket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1]) .. admonition:: Difference to CPython :class: attention CPython raises a ``socket.gaierror`` exception (`OSError` subclass) in case of error in this function. MicroPython doesn't have ``socket.gaierror`` and raises OSError directly. Note that error numbers of `getaddrinfo()` form a separate namespace and may not match error numbers from the :mod:`uerrno` module. To distinguish `getaddrinfo()` errors, they are represented by negative numbers, whereas standard system errors are positive numbers (error numbers are accessible using ``e.args[0]`` property from an exception object). The use of negative values is a provisional detail which may change in the future. .. function:: inet_ntop(af, bin_addr) Convert a binary network address *bin_addr* of the given address family *af* to a textual representation:: >>> usocket.inet_ntop(usocket.AF_INET, b"\x7f\0\0\1") '127.0.0.1' .. function:: inet_pton(af, txt_addr) Convert a textual network address *txt_addr* of the given address family *af* to a binary representation:: >>> usocket.inet_pton(usocket.AF_INET, "1.2.3.4") b'\x01\x02\x03\x04' Constants --------- .. data:: AF_INET AF_INET6 Address family types. Availability depends on a particular `MicroPython port`. .. data:: SOCK_STREAM SOCK_DGRAM Socket types. .. data:: IPPROTO_UDP IPPROTO_TCP IP protocol numbers. Availability depends on a particular `MicroPython port`. Note that you don't need to specify these in a call to `usocket.socket()`, because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants is as an argument to `setsockopt()`. .. data:: usocket.SOL_* Socket option levels (an argument to `setsockopt()`). The exact inventory depends on a `MicroPython port`. .. data:: usocket.SO_* Socket options (an argument to `setsockopt()`). The exact inventory depends on a `MicroPython port`. Constants specific to WiPy: .. data:: IPPROTO_SEC Special protocol value to create SSL-compatible socket. class socket ============ Methods ------- .. method:: socket.close() Mark the socket closed and release all resources. Once that happens, all future operations on the socket object will fail. The remote end will receive EOF indication if supported by protocol. Sockets are automatically closed when they are garbage-collected, but it is recommended to `close()` them explicitly as soon you finished working with them. .. method:: socket.bind(address) Bind the socket to *address*. The socket must not already be bound. .. method:: socket.listen([backlog]) Enable a server to accept connections. If *backlog* is specified, it must be at least 0 (if it's lower, it will be set to 0); and specifies the number of unaccepted connections that the system will allow before refusing new connections. If not specified, a default reasonable value is chosen. .. method:: socket.accept() Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection. .. method:: socket.connect(address) Connect to a remote socket at *address*. .. method:: socket.send(bytes) Send data to the socket. The socket must be connected to a remote socket. Returns number of bytes sent, which may be smaller than the length of data ("short write"). .. method:: socket.sendall(bytes) Send all data to the socket. The socket must be connected to a remote socket. Unlike `send()`, this method will try to send all of data, by sending data chunk by chunk consecutively. The behavior of this method on non-blocking sockets is undefined. Due to this, on MicroPython, it's recommended to use `write()` method instead, which has the same "no short writes" policy for blocking sockets, and will return number of bytes sent on non-blocking sockets. .. method:: socket.recv(bufsize) Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by bufsize. .. method:: socket.sendto(bytes, address) Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by *address*. .. method:: socket.recvfrom(bufsize) Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a bytes object representing the data received and *address* is the address of the socket sending the data. .. method:: socket.setsockopt(level, optname, value) Set the value of the given socket option. The needed symbolic constants are defined in the socket module (SO_* etc.). The *value* can be an integer or a bytes-like object representing a buffer. .. method:: socket.settimeout(value) **Note**: Not every port supports this method, see below. Set a timeout on blocking socket operations. The value argument can be a nonnegative floating point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations will raise an `OSError` exception if the timeout period value has elapsed before the operation has completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket is put in blocking mode. Not every `MicroPython port` supports this method. A more portable and generic solution is to use `uselect.poll` object. This allows to wait on multiple objects at the same time (and not just on sockets, but on generic `stream` objects which support polling). Example:: # Instead of: s.settimeout(1.0) # time in seconds s.read(10) # may timeout # Use: poller = uselect.poll() poller.register(s, uselect.POLLIN) res = poller.poll(1000) # time in milliseconds if not res: # s is still not ready for input, i.e. operation timed out .. admonition:: Difference to CPython :class: attention CPython raises a ``socket.timeout`` exception in case of timeout, which is an `OSError` subclass. MicroPython raises an OSError directly instead. If you use ``except OSError:`` to catch the exception, your code will work both in MicroPython and CPython. .. method:: socket.setblocking(flag) Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking, else to blocking mode. This method is a shorthand for certain `settimeout()` calls: * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)`` * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)`` .. method:: socket.makefile(mode='rb', buffering=0) Return a file object associated with the socket. The exact returned type depends on the arguments given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb'). CPython's arguments: *encoding*, *errors* and *newline* are not supported. .. admonition:: Difference to CPython :class: attention As MicroPython doesn't support buffered streams, values of *buffering* parameter is ignored and treated as if it was 0 (unbuffered). .. admonition:: Difference to CPython :class: attention Closing the file object returned by makefile() WILL close the original socket as well. .. method:: socket.read([size]) Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it reads all data available from the socket until EOF; as such the method will not return until the socket is closed. This function tries to read as much data as requested (no "short reads"). This may be not possible with non-blocking socket though, and then less data will be returned. .. method:: socket.readinto(buf[, nbytes]) Read bytes into the *buf*. If *nbytes* is specified then read at most that many bytes. Otherwise, read at most *len(buf)* bytes. Just as `read()`, this method follows "no short reads" policy. Return value: number of bytes read and stored into *buf*. .. method:: socket.readline() Read a line, ending in a newline character. Return value: the line read. .. method:: socket.write(buf) Write the buffer of bytes to the socket. This function will try to write all data to a socket (no "short writes"). This may be not possible with a non-blocking socket though, and returned value will be less than the length of *buf*. Return value: number of bytes written. .. exception:: usocket.error MicroPython does NOT have this exception. .. admonition:: Difference to CPython :class: attention CPython used to have a ``socket.error`` exception which is now deprecated, and is an alias of `OSError`. In MicroPython, use `OSError` directly. micropython-1.12/docs/library/ussl.rst000066400000000000000000000032441357706137100201410ustar00rootroot00000000000000:mod:`ussl` -- SSL/TLS module ============================= .. module:: ussl :synopsis: TLS/SSL wrapper for socket objects |see_cpython_module| :mod:`python:ssl`. This module provides access to Transport Layer Security (previously and widely known as “Secure Sockets Layer”) encryption and peer authentication facilities for network sockets, both client-side and server-side. Functions --------- .. function:: ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None) Takes a `stream` *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type), and returns an instance of ssl.SSLSocket, which wraps the underlying stream in an SSL context. Returned object has the usual `stream` interface methods like ``read()``, ``write()``, etc. In MicroPython, the returned object does not expose socket interface and methods like ``recv()``, ``send()``. In particular, a server-side SSL socket should be created from a normal socket returned from :meth:`~usocket.socket.accept()` on a non-SSL listening server socket. Depending on the underlying module implementation in a particular `MicroPython port`, some or all keyword arguments above may be not supported. .. warning:: Some implementations of ``ussl`` module do NOT validate server certificates, which makes an SSL connection established prone to man-in-the-middle attacks. Exceptions ---------- .. data:: ssl.SSLError This exception does NOT exist. Instead its base class, OSError, is used. Constants --------- .. data:: ussl.CERT_NONE ussl.CERT_OPTIONAL ussl.CERT_REQUIRED Supported values for *cert_reqs* parameter. micropython-1.12/docs/library/ustruct.rst000066400000000000000000000025631357706137100206670ustar00rootroot00000000000000:mod:`ustruct` -- pack and unpack primitive data types ====================================================== .. module:: ustruct :synopsis: pack and unpack primitive data types |see_cpython_module| :mod:`python:struct`. Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``. Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, ``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending on the floating-point support). Functions --------- .. function:: calcsize(fmt) Return the number of bytes needed to store the given *fmt*. .. function:: pack(fmt, v1, v2, ...) Pack the values *v1*, *v2*, ... according to the format string *fmt*. The return value is a bytes object encoding the values. .. function:: pack_into(fmt, buffer, offset, v1, v2, ...) Pack the values *v1*, *v2*, ... according to the format string *fmt* into a *buffer* starting at *offset*. *offset* may be negative to count from the end of *buffer*. .. function:: unpack(fmt, data) Unpack from the *data* according to the format string *fmt*. The return value is a tuple of the unpacked values. .. function:: unpack_from(fmt, data, offset=0) Unpack from the *data* starting at *offset* according to the format string *fmt*. *offset* may be negative to count from the end of *buffer*. The return value is a tuple of the unpacked values. micropython-1.12/docs/library/utime.rst000066400000000000000000000250611357706137100202770ustar00rootroot00000000000000:mod:`utime` -- time related functions ====================================== .. module:: utime :synopsis: time related functions |see_cpython_module| :mod:`python:time`. The ``utime`` module provides functions for getting the current time and date, measuring time intervals, and for delays. **Time Epoch**: Unix port uses standard for POSIX systems epoch of 1970-01-01 00:00:00 UTC. However, embedded ports use epoch of 2000-01-01 00:00:00 UTC. **Maintaining actual calendar date/time**: This requires a Real Time Clock (RTC). On systems with underlying OS (including some RTOS), an RTC may be implicit. Setting and maintaining actual calendar time is responsibility of OS/RTOS and is done outside of MicroPython, it just uses OS API to query date/time. On baremetal ports however system time depends on ``machine.RTC()`` object. The current calendar time may be set using ``machine.RTC().datetime(tuple)`` function, and maintained by following means: * By a backup battery (which may be an additional, optional component for a particular board). * Using networked time protocol (requires setup by a port/user). * Set manually by a user on each power-up (many boards then maintain RTC time across hard resets, though some may require setting it again in such case). If actual calendar time is not maintained with a system/MicroPython RTC, functions below which require reference to current absolute time may behave not as expected. Functions --------- .. function:: localtime([secs]) Convert a time expressed in seconds since the Epoch (see above) into an 8-tuple which contains: (year, month, mday, hour, minute, second, weekday, yearday) If secs is not provided or None, then the current time from the RTC is used. * year includes the century (for example 2014). * month is 1-12 * mday is 1-31 * hour is 0-23 * minute is 0-59 * second is 0-59 * weekday is 0-6 for Mon-Sun * yearday is 1-366 .. function:: mktime() This is inverse function of localtime. It's argument is a full 8-tuple which expresses a time as per localtime. It returns an integer which is the number of seconds since Jan 1, 2000. .. function:: sleep(seconds) Sleep for the given number of seconds. Some boards may accept *seconds* as a floating-point number to sleep for a fractional number of seconds. Note that other boards may not accept a floating-point argument, for compatibility with them use `sleep_ms()` and `sleep_us()` functions. .. function:: sleep_ms(ms) Delay for given number of milliseconds, should be positive or 0. .. function:: sleep_us(us) Delay for given number of microseconds, should be positive or 0. .. function:: ticks_ms() Returns an increasing millisecond counter with an arbitrary reference point, that wraps around after some value. The wrap-around value is not explicitly exposed, but we will refer to it as *TICKS_MAX* to simplify discussion. Period of the values is *TICKS_PERIOD = TICKS_MAX + 1*. *TICKS_PERIOD* is guaranteed to be a power of two, but otherwise may differ from port to port. The same period value is used for all of `ticks_ms()`, `ticks_us()`, `ticks_cpu()` functions (for simplicity). Thus, these functions will return a value in range [*0* .. *TICKS_MAX*], inclusive, total *TICKS_PERIOD* values. Note that only non-negative values are used. For the most part, you should treat values returned by these functions as opaque. The only operations available for them are `ticks_diff()` and `ticks_add()` functions described below. Note: Performing standard mathematical operations (+, -) or relational operators (<, <=, >, >=) directly on these value will lead to invalid result. Performing mathematical operations and then passing their results as arguments to `ticks_diff()` or `ticks_add()` will also lead to invalid results from the latter functions. .. function:: ticks_us() Just like `ticks_ms()` above, but in microseconds. .. function:: ticks_cpu() Similar to `ticks_ms()` and `ticks_us()`, but with the highest possible resolution in the system. This is usually CPU clocks, and that's why the function is named that way. But it doesn't have to be a CPU clock, some other timing source available in a system (e.g. high-resolution timer) can be used instead. The exact timing unit (resolution) of this function is not specified on ``utime`` module level, but documentation for a specific port may provide more specific information. This function is intended for very fine benchmarking or very tight real-time loops. Avoid using it in portable code. Availability: Not every port implements this function. .. function:: ticks_add(ticks, delta) Offset ticks value by a given number, which can be either positive or negative. Given a *ticks* value, this function allows to calculate ticks value *delta* ticks before or after it, following modular-arithmetic definition of tick values (see `ticks_ms()` above). *ticks* parameter must be a direct result of call to `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions (or from previous call to `ticks_add()`). However, *delta* can be an arbitrary integer number or numeric expression. `ticks_add()` is useful for calculating deadlines for events/tasks. (Note: you must use `ticks_diff()` function to work with deadlines.) Examples:: # Find out what ticks value there was 100ms ago print(ticks_add(time.ticks_ms(), -100)) # Calculate deadline for operation and test for it deadline = ticks_add(time.ticks_ms(), 200) while ticks_diff(deadline, time.ticks_ms()) > 0: do_a_little_of_something() # Find out TICKS_MAX used by this port print(ticks_add(0, -1)) .. function:: ticks_diff(ticks1, ticks2) Measure ticks difference between values returned from `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions, as a signed value which may wrap around. The argument order is the same as for subtraction operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. However, values returned by `ticks_ms()`, etc. functions may wrap around, so directly using subtraction on them will produce incorrect result. That is why `ticks_diff()` is needed, it implements modular (or more specifically, ring) arithmetics to produce correct result even for wrap-around values (as long as they not too distant inbetween, see below). The function returns **signed** value in the range [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for two's-complement signed binary integers). If the result is negative, it means that *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that *ticks1* occurred after *ticks2*. This holds **only** if *ticks1* and *ticks2* are apart from each other for no more than *TICKS_PERIOD/2-1* ticks. If that does not hold, incorrect result will be returned. Specifically, if two tick values are apart for *TICKS_PERIOD/2-1* ticks, that value will be returned by the function. However, if *TICKS_PERIOD/2* of real-time ticks has passed between them, the function will return *-TICKS_PERIOD/2* instead, i.e. result value will wrap around to the negative range of possible values. Informal rationale of the constraints above: Suppose you are locked in a room with no means to monitor passing of time except a standard 12-notch clock. Then if you look at dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a long sleep), then once you finally look again, it may seem to you that only 1 hour has passed. To avoid this mistake, just look at the clock regularly. Your application should do the same. "Too long sleep" metaphor also maps directly to application behavior: don't let your application run any single task for too long. Run tasks in steps, and do time-keeping inbetween. `ticks_diff()` is designed to accommodate various usage patterns, among them: * Polling with timeout. In this case, the order of events is known, and you will deal only with positive results of `ticks_diff()`:: # Wait for GPIO pin to be asserted, but at most 500us start = time.ticks_us() while pin.value() == 0: if time.ticks_diff(time.ticks_us(), start) > 500: raise TimeoutError * Scheduling events. In this case, `ticks_diff()` result may be negative if an event is overdue:: # This code snippet is not optimized now = time.ticks_ms() scheduled_time = task.scheduled_time() if ticks_diff(scheduled_time, now) > 0: print("Too early, let's nap") sleep_ms(ticks_diff(scheduled_time, now)) task.run() elif ticks_diff(scheduled_time, now) == 0: print("Right at time!") task.run() elif ticks_diff(scheduled_time, now) < 0: print("Oops, running late, tell task to run faster!") task.run(run_faster=true) Note: Do not pass `time()` values to `ticks_diff()`, you should use normal mathematical operations on them. But note that `time()` may (and will) also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem . .. function:: time() Returns the number of seconds, as an integer, since the Epoch, assuming that underlying RTC is set and maintained as described above. If an RTC is not set, this function returns number of seconds since a port-specific reference point in time (for embedded boards without a battery-backed RTC, usually since power up or reset). If you want to develop portable MicroPython application, you should not rely on this function to provide higher than second precision. If you need higher precision, use `ticks_ms()` and `ticks_us()` functions, if you need calendar time, `localtime()` without an argument is a better choice. .. admonition:: Difference to CPython :class: attention In CPython, this function returns number of seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point, usually having microsecond precision. With MicroPython, only Unix port uses the same Epoch, and if floating-point precision allows, returns sub-second precision. Embedded hardware usually doesn't have floating-point precision to represent both long time ranges and subsecond precision, so they use integer value with second precision. Some embedded hardware also lacks battery-powered RTC, so returns number of seconds since last power-up or from other relative, hardware-specific point (e.g. reset). micropython-1.12/docs/library/uzlib.rst000066400000000000000000000026601357706137100203010ustar00rootroot00000000000000:mod:`uzlib` -- zlib decompression ================================== .. module:: uzlib :synopsis: zlib decompression |see_cpython_module| :mod:`python:zlib`. This module allows to decompress binary data compressed with `DEFLATE algorithm `_ (commonly used in zlib library and gzip archiver). Compression is not yet implemented. Functions --------- .. function:: decompress(data, wbits=0, bufsize=0) Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window size used during compression (8-15, the dictionary size is power of 2 of that value). Additionally, if value is positive, *data* is assumed to be zlib stream (with zlib header). Otherwise, if it's negative, it's assumed to be raw DEFLATE stream. *bufsize* parameter is for compatibility with CPython and is ignored. .. class:: DecompIO(stream, wbits=0) Create a `stream` wrapper which allows transparent decompression of compressed data in another *stream*. This allows to process compressed streams with data larger than available heap size. In addition to values described in :func:`decompress`, *wbits* may take values 24..31 (16 + 8..15), meaning that input stream has gzip header. .. admonition:: Difference to CPython :class: attention This class is MicroPython extension. It's included on provisional basis and may be changed considerably or removed in later versions. micropython-1.12/docs/library/wipy.rst000066400000000000000000000007221357706137100201410ustar00rootroot00000000000000************************************* :mod:`wipy` -- WiPy specific features ************************************* .. module:: wipy :synopsis: WiPy specific features The ``wipy`` module contains functions to control specific features of the WiPy, such as the heartbeat LED. Functions --------- .. function:: heartbeat([enable]) Get or set the state (enabled or disabled) of the heartbeat LED. Accepts and returns boolean values (``True`` or ``False``). micropython-1.12/docs/license.rst000066400000000000000000000022151357706137100171260ustar00rootroot00000000000000MicroPython license information =============================== The MIT License (MIT) Copyright (c) 2013-2017 Damien P. George, and others Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. micropython-1.12/docs/make.bat000066400000000000000000000150671357706137100163700ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\MicroPython.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\MicroPython.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end micropython-1.12/docs/pyboard/000077500000000000000000000000001357706137100164125ustar00rootroot00000000000000micropython-1.12/docs/pyboard/general.rst000066400000000000000000000066551357706137100205750ustar00rootroot00000000000000.. _pyboard_general: General information about the pyboard ===================================== .. contents:: Local filesystem and SD card ---------------------------- There is a small internal filesystem (a drive) on the pyboard, called ``/flash``, which is stored within the microcontroller's flash memory. If a micro SD card is inserted into the slot, it is available as ``/sd``. When the pyboard boots up, it needs to choose a filesystem to boot from. If there is no SD card, then it uses the internal filesystem ``/flash`` as the boot filesystem, otherwise, it uses the SD card ``/sd``. After the boot, the current directory is set to one of the directories above. If needed, you can prevent the use of the SD card by creating an empty file called ``/flash/SKIPSD``. If this file exists when the pyboard boots up then the SD card will be skipped and the pyboard will always boot from the internal filesystem (in this case the SD card won't be mounted but you can still mount and use it later in your program using ``os.mount``). (Note that on older versions of the board, ``/flash`` is called ``0:/`` and ``/sd`` is called ``1:/``). The boot filesystem is used for 2 things: it is the filesystem from which the ``boot.py`` and ``main.py`` files are searched for, and it is the filesystem which is made available on your PC over the USB cable. The filesystem will be available as a USB flash drive on your PC. You can save files to the drive, and edit ``boot.py`` and ``main.py``. *Remember to eject (on Linux, unmount) the USB drive before you reset your pyboard.* Boot modes ---------- If you power up normally, or press the reset button, the pyboard will boot into standard mode: the ``boot.py`` file will be executed first, then the USB will be configured, then ``main.py`` will run. You can override this boot sequence by holding down the user switch as the board is booting up. Hold down user switch and press reset, and then as you continue to hold the user switch, the LEDs will count in binary. When the LEDs have reached the mode you want, let go of the user switch, the LEDs for the selected mode will flash quickly, and the board will boot. The modes are: 1. Green LED only, *standard boot*: run ``boot.py`` then ``main.py``. 2. Orange LED only, *safe boot*: don't run any scripts on boot-up. 3. Green and orange LED together, *filesystem reset*: resets the flash filesystem to its factory state, then boots in safe mode. If your filesystem becomes corrupt, boot into mode 3 to fix it. If resetting the filesystem while plugged into your compute doesn't work, you can try doing the same procedure while the board is plugged into a USB charger, or other USB power supply without data connection. Errors: flashing LEDs --------------------- There are currently 2 kinds of errors that you might see: 1. If the red and green LEDs flash alternatively, then a Python script (eg ``main.py``) has an error. Use the REPL to debug it. 2. If all 4 LEDs cycle on and off slowly, then there was a hard fault. This cannot be recovered from and you need to do a hard reset. Guide for using the pyboard with Windows ---------------------------------------- The following PDF guide gives information about using the pyboard with Windows, including setting up the serial prompt and downloading new firmware using DFU programming: `PDF guide `__. .. _hardware_index: .. include:: hardware/index.rst micropython-1.12/docs/pyboard/hardware/000077500000000000000000000000001357706137100202075ustar00rootroot00000000000000micropython-1.12/docs/pyboard/hardware/index.rst000066400000000000000000000033701357706137100220530ustar00rootroot00000000000000The pyboard hardware -------------------- For the pyboard: * v1.1 * `PYBv1.1 schematics and layout `_ (2.9MiB PDF) * v1.0 * `PYBv1.0 schematics and layout `_ (2.4MiB PDF) * `PYBv1.0 metric dimensions `_ (360KiB PDF) * `PYBv1.0 imperial dimensions `_ (360KiB PDF) For the official skin modules: * `LCD32MKv1.0 schematics `_ (194KiB PDF) * `AMPv1.0 schematics `_ (209KiB PDF) * LCD160CRv1.0: see :mod:`lcd160cr` Datasheets for the components on the pyboard -------------------------------------------- * The microcontroller: `STM32F405RGT6 `_ (link to manufacturer's site) * The accelerometer: `Freescale MMA7660 `_ (800kiB PDF) * The LDO voltage regulator: `Microchip MCP1802 `_ (400kiB PDF) Datasheets for other components ------------------------------- * The LCD display on the LCD touch-sensor skin: `Newhaven Display NHD-C12832A1Z-FSW-FBW-3V3 `_ (460KiB PDF) * The touch sensor chip on the LCD touch-sensor skin: `Freescale MPR121 `_ (280KiB PDF) * The digital potentiometer on the audio skin: `Microchip MCP4541 `_ (2.7MiB PDF) micropython-1.12/docs/pyboard/quickref.rst000066400000000000000000000137501357706137100207630ustar00rootroot00000000000000.. _pyboard_quickref: Quick reference for the pyboard =============================== The below pinout is for PYBv1.1. You can also view pinouts for other versions of the pyboard: `PYBv1.0 `__ or `PYBLITEv1.0-AC `__ or `PYBLITEv1.0 `__. .. only:: not latex .. image:: http://micropython.org/resources/pybv11-pinout.jpg :alt: PYBv1.1 pinout :width: 700px .. only:: latex .. image:: http://micropython.org/resources/pybv11-pinout-800px.jpg :alt: PYBv1.1 pinout Below is a quick reference for the pyboard. If it is your first time working with this board please consider reading the following sections first: .. toctree:: :maxdepth: 1 general.rst tutorial/index.rst General board control --------------------- See :mod:`pyb`. :: import pyb pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1) pyb.wfi() # pause CPU, waiting for interrupt pyb.freq() # get CPU and bus frequencies pyb.freq(60000000) # set CPU freq to 60MHz pyb.stop() # stop CPU, waiting for external interrupt Delay and timing ---------------- Use the :mod:`time ` module:: import time time.sleep(1) # sleep for 1 second time.sleep_ms(500) # sleep for 500 milliseconds time.sleep_us(10) # sleep for 10 microseconds start = time.ticks_ms() # get value of millisecond counter delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference Internal LEDs ------------- See :ref:`pyb.LED `. :: from pyb import LED led = LED(1) # 1=red, 2=green, 3=yellow, 4=blue led.toggle() led.on() led.off() # LEDs 3 and 4 support PWM intensity (0-255) LED(4).intensity() # get intensity LED(4).intensity(128) # set intensity to half Internal switch --------------- See :ref:`pyb.Switch `. :: from pyb import Switch sw = Switch() sw.value() # returns True or False sw.callback(lambda: pyb.LED(1).toggle()) Pins and GPIO ------------- See :ref:`pyb.Pin `. :: from pyb import Pin p_out = Pin('X1', Pin.OUT_PP) p_out.high() p_out.low() p_in = Pin('X2', Pin.IN, Pin.PULL_UP) p_in.value() # get value, 0 or 1 Servo control ------------- See :ref:`pyb.Servo `. :: from pyb import Servo s1 = Servo(1) # servo on position 1 (X1, VIN, GND) s1.angle(45) # move to 45 degrees s1.angle(-60, 1500) # move to -60 degrees in 1500ms s1.speed(50) # for continuous rotation servos External interrupts ------------------- See :ref:`pyb.ExtInt `. :: from pyb import Pin, ExtInt callback = lambda e: print("intr") ext = ExtInt(Pin('Y1'), ExtInt.IRQ_RISING, Pin.PULL_NONE, callback) Timers ------ See :ref:`pyb.Timer `. :: from pyb import Timer tim = Timer(1, freq=1000) tim.counter() # get counter value tim.freq(0.5) # 0.5 Hz tim.callback(lambda t: pyb.LED(1).toggle()) RTC (real time clock) --------------------- See :ref:`pyb.RTC ` :: from pyb import RTC rtc = RTC() rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time rtc.datetime() # get date and time PWM (pulse width modulation) ---------------------------- See :ref:`pyb.Pin ` and :ref:`pyb.Timer `. :: from pyb import Pin, Timer p = Pin('X1') # X1 has TIM2, CH1 tim = Timer(2, freq=1000) ch = tim.channel(1, Timer.PWM, pin=p) ch.pulse_width_percent(50) ADC (analog to digital conversion) ---------------------------------- See :ref:`pyb.Pin ` and :ref:`pyb.ADC `. :: from pyb import Pin, ADC adc = ADC(Pin('X19')) adc.read() # read value, 0-4095 DAC (digital to analog conversion) ---------------------------------- See :ref:`pyb.Pin ` and :ref:`pyb.DAC `. :: from pyb import Pin, DAC dac = DAC(Pin('X5')) dac.write(120) # output between 0 and 255 UART (serial bus) ----------------- See :ref:`pyb.UART `. :: from pyb import UART uart = UART(1, 9600) uart.write('hello') uart.read(5) # read up to 5 bytes SPI bus ------- See :ref:`pyb.SPI `. :: from pyb import SPI spi = SPI(1, SPI.MASTER, baudrate=200000, polarity=1, phase=0) spi.send('hello') spi.recv(5) # receive 5 bytes on the bus spi.send_recv('hello') # send and receive 5 bytes I2C bus ------- Hardware I2C is available on the X and Y halves of the pyboard via ``I2C('X')`` and ``I2C('Y')``. Alternatively pass in the integer identifier of the peripheral, eg ``I2C(1)``. Software I2C is also available by explicitly specifying the ``scl`` and ``sda`` pins instead of the bus name. For more details see :ref:`machine.I2C `. :: from machine import I2C i2c = I2C('X', freq=400000) # create hardware I2c object i2c = I2C(scl='X1', sda='X2', freq=100000) # create software I2C object i2c.scan() # returns list of slave addresses i2c.writeto(0x42, 'hello') # write 5 bytes to slave with address 0x42 i2c.readfrom(0x42, 5) # read 5 bytes from slave i2c.readfrom_mem(0x42, 0x10, 2) # read 2 bytes from slave 0x42, slave memory 0x10 i2c.writeto_mem(0x42, 0x10, 'xy') # write 2 bytes to slave 0x42, slave memory 0x10 Note: for legacy I2C support see :ref:`pyb.I2C `. CAN bus (controller area network) --------------------------------- See :ref:`pyb.CAN `. :: from pyb import CAN can = CAN(1, CAN.LOOPBACK) can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) can.send('message!', 123) # send a message with id 123 can.recv(0) # receive message on FIFO 0 Internal accelerometer ---------------------- See :ref:`pyb.Accel `. :: from pyb import Accel accel = Accel() print(accel.x(), accel.y(), accel.z(), accel.tilt()) micropython-1.12/docs/pyboard/tutorial/000077500000000000000000000000001357706137100202555ustar00rootroot00000000000000micropython-1.12/docs/pyboard/tutorial/accel.rst000066400000000000000000000061451357706137100220640ustar00rootroot00000000000000The accelerometer ================= Here you will learn how to read the accelerometer and signal using LEDs states like tilt left and tilt right. Using the accelerometer ----------------------- The pyboard has an accelerometer (a tiny mass on a tiny spring) that can be used to detect the angle of the board and motion. There is a different sensor for each of the x, y, z directions. To get the value of the accelerometer, create a pyb.Accel() object and then call the x() method. :: >>> accel = pyb.Accel() >>> accel.x() 7 This returns a signed integer with a value between around -30 and 30. Note that the measurement is very noisy, this means that even if you keep the board perfectly still there will be some variation in the number that you measure. Because of this, you shouldn't use the exact value of the x() method but see if it is in a certain range. We will start by using the accelerometer to turn on a light if it is not flat. :: accel = pyb.Accel() light = pyb.LED(3) SENSITIVITY = 3 while True: x = accel.x() if abs(x) > SENSITIVITY: light.on() else: light.off() pyb.delay(100) We create Accel and LED objects, then get the value of the x direction of the accelerometer. If the magnitude of x is bigger than a certain value ``SENSITIVITY``, then the LED turns on, otherwise it turns off. The loop has a small ``pyb.delay()`` otherwise the LED flashes annoyingly when the value of x is close to ``SENSITIVITY``. Try running this on the pyboard and tilt the board left and right to make the LED turn on and off. **Exercise: Change the above script so that the blue LED gets brighter the more you tilt the pyboard. HINT: You will need to rescale the values, intensity goes from 0-255.** Making a spirit level --------------------- The example above is only sensitive to the angle in the x direction but if we use the ``y()`` value and more LEDs we can turn the pyboard into a spirit level. :: xlights = (pyb.LED(2), pyb.LED(3)) ylights = (pyb.LED(1), pyb.LED(4)) accel = pyb.Accel() SENSITIVITY = 3 while True: x = accel.x() if x > SENSITIVITY: xlights[0].on() xlights[1].off() elif x < -SENSITIVITY: xlights[1].on() xlights[0].off() else: xlights[0].off() xlights[1].off() y = accel.y() if y > SENSITIVITY: ylights[0].on() ylights[1].off() elif y < -SENSITIVITY: ylights[1].on() ylights[0].off() else: ylights[0].off() ylights[1].off() pyb.delay(100) We start by creating a tuple of LED objects for the x and y directions. Tuples are immutable objects in python which means they can't be modified once they are created. We then proceed as before but turn on a different LED for positive and negative x values. We then do the same for the y direction. This isn't particularly sophisticated but it does the job. Run this on your pyboard and you should see different LEDs turning on depending on how you tilt the board. micropython-1.12/docs/pyboard/tutorial/amp_skin.rst000066400000000000000000000064131357706137100226140ustar00rootroot00000000000000The AMP audio skin ================== Soldering and using the AMP audio skin. .. image:: img/skin_amp_1.jpg :alt: AMP skin :width: 250px .. image:: img/skin_amp_2.jpg :alt: AMP skin :width: 250px The following video shows how to solder the headers, microphone and speaker onto the AMP skin. .. raw:: html For circuit schematics and datasheets for the components on the skin see :ref:`hardware_index`. Example code ------------ The AMP skin has a speaker which is connected to ``DAC(1)`` via a small power amplifier. The volume of the amplifier is controlled by a digital potentiometer, which is an I2C device with address 46 on the ``IC2(1)`` bus. To set the volume, define the following function:: import pyb def volume(val): pyb.I2C(1, pyb.I2C.MASTER).mem_write(val, 46, 0) Then you can do:: >>> volume(0) # minimum volume >>> volume(127) # maximum volume To play a sound, use the ``write_timed`` method of the ``DAC`` object. For example:: import math from pyb import DAC # create a buffer containing a sine-wave buf = bytearray(100) for i in range(len(buf)): buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf))) # output the sine-wave at 400Hz dac = DAC(1) dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) You can also play WAV files using the Python ``wave`` module. You can get the wave module `here `__ and you will also need the chunk module available `here `__. Put these on your pyboard (either on the flash or the SD card in the top-level directory). You will need an 8-bit WAV file to play, such as `this one `_, or to convert any file you have with the command:: avconv -i original.wav -ar 22050 -codec pcm_u8 test.wav Then you can do:: >>> import wave >>> from pyb import DAC >>> dac = DAC(1) >>> f = wave.open('test.wav') >>> dac.write_timed(f.readframes(f.getnframes()), f.getframerate()) This should play the WAV file. Note that this will read the whole file into RAM so it has to be small enough to fit in it. To play larger wave files you will have to use the micro-SD card to store it. Also the file must be read and sent to the DAC in small chunks that will fit the RAM limit of the microcontroller. Here is an example function that can play 8-bit wave files with up to 16kHz sampling:: import wave from pyb import DAC from pyb import delay dac = DAC(1) def play(filename): f = wave.open(filename, 'r') total_frames = f.getnframes() framerate = f.getframerate() for position in range(0, total_frames, framerate): f.setpos(position) dac.write_timed(f.readframes(framerate), framerate) delay(1000) This function reads one second worth of data and sends it to DAC. It then waits one second and moves the file cursor to the new position to read the next second of data in the next iteration of the for-loop. It plays one second of audio at a time every one second. micropython-1.12/docs/pyboard/tutorial/assembler.rst000066400000000000000000000076201357706137100227710ustar00rootroot00000000000000.. _pyboard_tutorial_assembler: Inline assembler ================ Here you will learn how to write inline assembler in MicroPython. **Note**: this is an advanced tutorial, intended for those who already know a bit about microcontrollers and assembly language. MicroPython includes an inline assembler. It allows you to write assembly routines as a Python function, and you can call them as you would a normal Python function. Returning a value ----------------- Inline assembler functions are denoted by a special function decorator. Let's start with the simplest example:: @micropython.asm_thumb def fun(): movw(r0, 42) You can enter this in a script or at the REPL. This function takes no arguments and returns the number 42. ``r0`` is a register, and the value in this register when the function returns is the value that is returned. MicroPython always interprets the ``r0`` as an integer, and converts it to an integer object for the caller. If you run ``print(fun())`` you will see it print out 42. Accessing peripherals --------------------- For something a bit more complicated, let's turn on an LED:: @micropython.asm_thumb def led_on(): movwt(r0, stm.GPIOA) movw(r1, 1 << 13) strh(r1, [r0, stm.GPIO_BSRRL]) This code uses a few new concepts: - ``stm`` is a module which provides a set of constants for easy access to the registers of the pyboard's microcontroller. Try running ``import stm`` and then ``help(stm)`` at the REPL. It will give you a list of all the available constants. - ``stm.GPIOA`` is the address in memory of the GPIOA peripheral. On the pyboard, the red LED is on port A, pin PA13. - ``movwt`` moves a 32-bit number into a register. It is a convenience function that turns into 2 thumb instructions: ``movw`` followed by ``movt``. The ``movt`` also shifts the immediate value right by 16 bits. - ``strh`` stores a half-word (16 bits). The instruction above stores the lower 16-bits of ``r1`` into the memory location ``r0 + stm.GPIO_BSRRL``. This has the effect of setting high all those pins on port A for which the corresponding bit in ``r0`` is set. In our example above, the 13th bit in ``r0`` is set, so PA13 is pulled high. This turns on the red LED. Accepting arguments ------------------- Inline assembler functions can accept up to 4 arguments. If they are used, they must be named ``r0``, ``r1``, ``r2`` and ``r3`` to reflect the registers and the calling conventions. Here is a function that adds its arguments:: @micropython.asm_thumb def asm_add(r0, r1): add(r0, r0, r1) This performs the computation ``r0 = r0 + r1``. Since the result is put in ``r0``, that is what is returned. Try ``asm_add(1, 2)``, it should return 3. Loops ----- We can assign labels with ``label(my_label)``, and branch to them using ``b(my_label)``, or a conditional branch like ``bgt(my_label)``. The following example flashes the green LED. It flashes it ``r0`` times. :: @micropython.asm_thumb def flash_led(r0): # get the GPIOA address in r1 movwt(r1, stm.GPIOA) # get the bit mask for PA14 (the pin LED #2 is on) movw(r2, 1 << 14) b(loop_entry) label(loop1) # turn LED on strh(r2, [r1, stm.GPIO_BSRRL]) # delay for a bit movwt(r4, 5599900) label(delay_on) sub(r4, r4, 1) cmp(r4, 0) bgt(delay_on) # turn LED off strh(r2, [r1, stm.GPIO_BSRRH]) # delay for a bit movwt(r4, 5599900) label(delay_off) sub(r4, r4, 1) cmp(r4, 0) bgt(delay_off) # loop r0 times sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) Further reading --------------- For further information about supported instructions of the inline assembler, see the :ref:`reference documentation `. micropython-1.12/docs/pyboard/tutorial/debounce.rst000066400000000000000000000022711357706137100225750ustar00rootroot00000000000000Debouncing a pin input ====================== A pin used as input from a switch or other mechanical device can have a lot of noise on it, rapidly changing from low to high when the switch is first pressed or released. This noise can be eliminated using a capacitor (a debouncing circuit). It can also be eliminated using a simple function that makes sure the value on the pin is stable. The following function does just this. It gets the current value of the given pin, and then waits for the value to change. The new pin value must be stable for a continuous 20ms for it to register the change. You can adjust this time (to say 50ms) if you still have noise. :: import pyb def wait_pin_change(pin): # wait for pin to change value # it needs to be stable for a continuous 20ms cur_value = pin.value() active = 0 while active < 20: if pin.value() != cur_value: active += 1 else: active = 0 pyb.delay(1) Use it something like this:: import pyb pin_x1 = pyb.Pin('X1', pyb.Pin.IN, pyb.Pin.PULL_DOWN) while True: wait_pin_change(pin_x1) pyb.LED(4).toggle() micropython-1.12/docs/pyboard/tutorial/fading_led.rst000066400000000000000000000072131357706137100230660ustar00rootroot00000000000000Fading LEDs =========== In addition to turning LEDs on and off, it is also possible to control the brightness of an LED using `Pulse-Width Modulation (PWM) `_, a common technique for obtaining variable output from a digital pin. This allows us to fade an LED: .. only:: not latex .. image:: http://upload.wikimedia.org/wikipedia/commons/a/a9/Fade.gif Components ---------- You will need: - Standard 5 or 3 mm LED - 100 Ohm resistor - Wires - `Breadboard `_ (optional, but makes things easier) Connecting Things Up -------------------- For this tutorial, we will use the ``X1`` pin. Connect one end of the resistor to ``X1``, and the other end to the **anode** of the LED, which is the longer leg. Connect the **cathode** of the LED to ground. .. image:: img/fading_leds_breadboard_fritzing.png Code ---- By examining the :ref:`pyboard_quickref`, we see that ``X1`` is connected to channel 1 of timer 5 (``TIM5 CH1``). Therefore we will first create a ``Timer`` object for timer 5, then create a ``TimerChannel`` object for channel 1:: from pyb import Timer from time import sleep # timer 5 will be created with a frequency of 100 Hz tim = pyb.Timer(5, freq=100) tchannel = tim.channel(1, Timer.PWM, pin=pyb.Pin.board.X1, pulse_width=0) Brightness of the LED in PWM is controlled by controlling the pulse-width, that is the amount of time the LED is on every cycle. With a timer frequency of 100 Hz, each cycle takes 0.01 second, or 10 ms. To achieve the fading effect shown at the beginning of this tutorial, we want to set the pulse-width to a small value, then slowly increase the pulse-width to brighten the LED, and start over when we reach some maximum brightness:: # maximum and minimum pulse-width, which corresponds to maximum # and minimum brightness max_width = 200000 min_width = 20000 # how much to change the pulse-width by each step wstep = 1500 cur_width = min_width while True: tchannel.pulse_width(cur_width) # this determines how often we change the pulse-width. It is # analogous to frames-per-second sleep(0.01) cur_width += wstep if cur_width > max_width: cur_width = min_width Breathing Effect ---------------- If we want to have a breathing effect, where the LED fades from dim to bright then bright to dim, then we simply need to reverse the sign of ``wstep`` when we reach maximum brightness, and reverse it again at minimum brightness. To do this we modify the ``while`` loop to be:: while True: tchannel.pulse_width(cur_width) sleep(0.01) cur_width += wstep if cur_width > max_width: cur_width = max_width wstep *= -1 elif cur_width < min_width: cur_width = min_width wstep *= -1 Advanced Exercise ----------------- You may have noticed that the LED brightness seems to fade slowly, but increases quickly. This is because our eyes interprets brightness logarithmically (`Weber's Law `_ ), while the LED's brightness changes linearly, that is by the same amount each time. How do you solve this problem? (Hint: what is the opposite of the logarithmic function?) Addendum -------- We could have also used the digital-to-analog converter (DAC) to achieve the same effect. The PWM method has the advantage that it drives the LED with the same current each time, but for different lengths of time. This allows better control over the brightness, because LEDs do not necessarily exhibit a linear relationship between the driving current and brightness. micropython-1.12/docs/pyboard/tutorial/img/000077500000000000000000000000001357706137100210315ustar00rootroot00000000000000micropython-1.12/docs/pyboard/tutorial/img/fading_leds_breadboard_fritzing.png000066400000000000000000001705751357706137100300760ustar00rootroot00000000000000PNG  IHDR:mIWE'iCCPICC ProfilehwT\3{Hcһ"HMAR Qz JaNs9w{;;;{e x@IHSҊ5 ,2;{>zM;Gv utp=O0nc5_?-o  Ǝ11R .8b@y9yI=P+8ځq}==8.#1\+G/8v,gN* x/8z/5p ؁mn=jNSxM@'ՏYE'fm/A~fkbkv@4v64N7۸i2}w1@x J:&%`8'xށ@ O " x& !``s` HA =b qxA!ahH$R)TC m^0d YAΠ0(! AP] z}MfA u6h?t݀ c `0} 2aFX7lۄ‘pr83\. ׂwx6 ^;+AC D "(E":"H-%2EV![e! AQ(;*5ZA1iYyEeU;'wO/o_?Ght$: ݉AH< "xGCHpJHFKJxП0a+>(a0~$L9 fsBDN$HMHt(hhX؆88= & > '*III$!)95R}RO ^U2':#C"/d0r6rUrhbN $6'o((v(((((s()0,'VM`'gT TTNTqToF騕㩫ǩhiiiRi>iyi iih;i7(dj~CyC202h20+3ncN.NsXΏ\\\!\\3nE܅cs׍SY. 9u60>2Q1I6667m7#6iVnvlff`!dnoIkfYo2*:Vΰ^)~3-[Azmhm3?}xȺlҽyp>vv0 {c C`FoOiM9*m D?gVBO0˜DNEyh2>r *vJw,ʟz&Vkfb8elffcdn!I]g/#*H(x*SxZHhXxDdTtLl\|BbҢ*fVN?7TF&fKv+mki>Lv,jN/k]ιsD{z|NNk{ M s X_ 6"'4a#Xx8x'O4ɿRRY=O3*2#Yf>'zݓSIwyKtV@RWe畁M߈|{\ҚayG~l 7ZBaa`tHE#ߢTQx.x.;3L(fȋ->i:4,C a`, *M-$],: F}&(S +k*;#Skn7.">~6%"A!6.("#)Z-/.#HtI&JJ3HȆȯw%eQ|E&,u? #Ma-bmA*=&7$ *SLM---G_|pF6-݀[DGw'-gveڵ-n\o?w|_` 8 *  1 MH@-)2j|.g? 7<2~dBO⧤ʔ33=e>̖|K_*YRVRٛ𷯫VyjZm՗7koA~֖f'{vO}ߣG'ΦW,$:῭k|0q Al}}>6B [(#T-^4!~#>#p%s &(hؙxČdTwy),{@IMJ]@#JK{.Xʤɴ"2ˆekbw p}vaS;/#(,'T'~MS\dIcq qITtܙ;x%'eeS ^zZ|ڿuuK]wj1X0l57766ÚYZXXsZUh[Ӗvî>Q4\rU z{/| OedžEO|PY=p?KX8N=݄ĂO)idOE22K!>7-~8sZm4CGs H tA!(&h'X "'! |O8B!bc<0O0>:>HrnDqDDDhb>b=bO$*a}   $-$ PRvRMR7'oHH($,~#yȽS?ORS(RS<(ئ$ ̣l\a{Ll#v BAEAB;53+uu5Ho44*4.4 4hihhhhi?Nt|2M@~efPdpfHbccD2 23g,cf\\}\܆ܯxP>;| `!"]'BB7ڄۄ\u-Z׵sa'EQ~Kbbbqbbg&}IepF#)1RUR[ҕ2|22odeeɞEu?UPPUTTLQVTԬl\GEN%^eJK5@SRINn^~q]#_cOSC斖Vֆvs]-|c=? v>~5DuCMb#mfc:)),cS z3is9< ޢӒ嶕U5uM͛o 5kjS2ZY[5J;2%{ZhMGS'.T3gG)BWkuwX$9uwtxIys닷w1 i{U38 Va[ % f4q'b"-#;D^FEEoG40m0]0;264+25;2:;6O:o;_5[bacQfR2ѲrO՟)?gVxVW@UkCtNUkk k.U776׶pjq1gzqvp.Ǯ{\{.{{+/gh 6 9MW>?1~>~+"f]& %#0'!%h#IG(@hل b1BSL(Ӎ" %''&l0hJMKJ/i.i3YY10%9/9Cy ,3.J6J#Hw+KUzcT0U*U;>5u,u >M${ZjZpwtX:m0wtT:5hn0D1|d`db4a|̸d͔t,Ȝ<Ȃ`aa)ea%gfZǺ5[[;]݇}Ð#Sӓsˈ+^a͓3K{1o'W˷/_KMN O`FVRPа0p5k`"!2)J-j%BtNEATlM_GI|O%K1J9JUHHKJKw,$!%(' ߪ@`P(HqDICAo򞊒Jʼ}A5&56CuTӰx hk<*:.>)9-ѽ3ѫ 7l" TΌ͌kLLMzL9LLrN,(-YXXZZZU[Zߵ)r̓[fWBcb3s[K[m]ݮG:%G '"'_ g|7Wgnvn]w9rvoH4lbzm w~e]֏/=@7AAAA*BCLʄ\¾ J|arC?y&4?r*J!(/3z×Pǔbbbk>{o DII Iɣ)J)oRR9tu0HxsϒRr矰?~~]!^1ZI_EW,^Y\uY-[]]Ys[+_[[Yw]/[Qɼibsj emݲ}Gϟ?+;L;;Ow"wwv1Y%u]}@`P0pHQ1X8 ÉII)ϩӊӱӫ33g=gαrχ./d/n]ܿ(hX]^*_^F\\__^^q])_Y_]%^\5_]%39qqq\/n/x?gZ  ր3pg 9X!pC ADHX!TPa6}t`60X6vK-!x3|EHBԀ}dFd-rEqT. ,#^Y|$~$~%8>̓6F_GЗ堻ْa5#q¤aZ1DD:DDeDHb $&>!!"I{Ԅ4ẗY&93 c& v D6#J>J[ >JV jJʟjKGE]OMNcVDi.iEA~I;AGHJ /zzzc8V#~:=ry&,SS=ffk4^f$K ,+%uGͬGll.l/٦c[8899~r2qZqfpqriqEsr]pK\ͽSʳ{7wς/oߘ)@ S1!J!3gBS´7^sVvm]D@Gȱ,X"K/_h$5%%ǤA~ #C"c)S .+*&%G,g)W$%/%%MZQJߧ JJJ8*y*۪ Ijjj} w5:45=5۴ZZmTڞ:::,`2Zok7To87g@`balnH(hиcaokoncVa6w7HcihYcEa`5e-kwrf-[IlLmn3܎VǶʎ.n^ž0(X4, j/eU5 6xGN;C#ѳK+wO];1aBfnɁAFA)CC2BBCkH¼@ _PȎ8op̓HH(֨h赇 ^>|TC0vǧqfq}?POOlu~\|FSҤҲҎ?N>!qi1Y,̬f벱999/L_R{IB"x}Qk1cqhTDIznҊWWZFW*++*oT~ 󛖷ط^o;Uc~𮿚ڿƷ={wI>}שԥަA!aѡqԧOMMכRƚϛжXdL|&l9sw+U5uͶ-m]=/ltpuwuvu&uu!T">uwut^qy3KkwOq_g?_?SWV۝oe~ n7?0;H7h9lp||p($pa#Ցȑ֑Qц11cB^7&x&\&J'~NNMO~n=Tz?L#զ[ffBf>Ίޝ};932W<44s>{~rbEEŖų%ɥ{K6_.i3g rEe%|~e/7~6g*͵uԺzzˆFF&dSj{tsvbKw+r6۶vv@zqy3 ەuD2@?޷܏o_;9:<(=?^;}# P=:ӂ \\N^\]1**_2.•jpq "nwW9-B9nPipÝpE`yZ=}og$ X_ux_.¶iTXtXML:com.adobe.xmp 570 365 e\@IDATxypu@lwbQVKd[qlK8v'xUR^xN]%kVKfKP" . ;pq{Ơg\/Q==gNs{fN+1=EBpE|X,'[rk˕T-Q㺞=9NB~<͓]r*mom/8mOeҹP(8lؖոgNړznsJ'0F&Wjpjzh`=9& `0 qW) `0qWKf0 qW) `0qWKf0 qW) `0qWKf0 qW) `0qWKf0 qW) `0@ϒ/ܝGv_2i@ &׈a0,ٻ'r>_O,p_*U^xasU/ sA`%0@443_jG?G"k s\..e8/SgJ66a&[{?tW^|;-o{є`89fvur A`"P>v_++E%=p"F4kԽ&a8wuz7V{/ 3iyG\$O?vCiXQZQx siF%`=kBܰDi~J"`ՊkN3$( =/e&[4+qW+alhƤ儞2DXi6 !ŹzqONDZm'& %4=z[b=B//F^7Ui@Fvu XyzTC`9JXJ{L\oy lNٿYW9uP}u wU,Y i/-[Asy} 毊X㮖K f~c<^&L] gH0O΢ʛeZ3d*uرX>M. wp  Pd8)Y tbbrN;5vɌ)"PL3[g,x*t.澿 b֛EoӋqWSA` \\ L&Ux<]l}N$v95b@ݔiXyR?IGK~+=+1";|8: xkq\=BMo2fr>_# zȜx^JlHqw1U:vk]EۈwbJEqz2q1_wfD6xC`tt?~6_{{瘴A`M `՚P 0[@U_UW]0/sA 0 `D0>h63馛.r{I5_ \Cu0 |ꫯ3yb;FET$ ̓qWͣ #A` 'W\qE׮a6 @ `UHbX6^zi}튠GM <w<0V bmV V iSA `0]xVA `X-Z-M9A p DERg"{"\>Y N*A`qX_X9H-u^r_._XGnXSwJ  Vt*K/Jk@>izk:o`0 C Tg_(fb7{ݙpEb3nȜ:rx$-T=ήwIوwbJ{bqH=BZ( 'J+b*azBk`ڨV95 @ `UHb0 50&4A `04]5.$A PjBc..~o-ng!]J7U6 k֞ΌA,DPA`!`ә `0wu*T `0=Z{:3 B* @7;1_ޞY'(1iGĒN<:^v@3 % '[>=5%-۶QUh #䉡׿ӒHPH.6ݶu,1kLºBZCU$[[wu!=({rl&3|yasEJ<*sM'ݻaC0M]mپ?ztmdHdUL: =n #x/zLDٌ#/Jed\* wtعK}$.W-' _tb&#[hHK|$(7*59SQ3wh NH4,B~ӧXص(y}h&imkX<Ϥb+yk":tڑW 8oBגLffvNͤ󺹫o`ClQ/r"x[хw}i[lԧ>w݊ DgO<8~bW}}=,7=e]ƞư@O+H]T.tUNw51[g`V83>e J} KW*we\}1Luvu{vҬ:u(t&?;giA5=ԇ F^F,#W&rWT*uګ sm%m/}#: kM"I9" -4:iC`xd%3ʡCC,5Qp0>ӓ̥ 8,U>1|?>ժoN>^O g K*'ݺ}R4+֓V@\9 e9qf/KE3pc^I3)#QT+Q+nA Tf}Njs+k<''?gB=y LqW g5AT(qlιH+/b*>5h6J'zw/2Xot yt(зnp97f~ ]Nز `04!`fNM_~i2-7gm[*&J#1S|P#nأK#kTXVע*@jTBh[J2x$k@DJ@B[M+^~{o˅bґoH#~W||ɱ>*/掰>_9cXd7Vl0YiHHi]P)rZͷV *X z6f*?B*U|$ۢ[]BRTȗA')^)w2kqv;xnjji V1/na!f*f=-w;HM+ M+Rs-V|O׃}Y_ZbC&+Z4" +pvPRvJഒ Ņ[ljIMM u$,/`'dEU P;Ď=U"4*X^U"xL$x 1Y @T)}A$Q瘝Qq!IuTn\D|ll ݠ?>uV}7|u0Y)1P(Jmb5mXTXa։Sl7T*/!<:v3@*I 8;8WAŜP#TSQ%e-*>ډ*"$_JP:JS%QBryј={P o}UbkVT o1#ţjvܗ v|5,S|eUM* ?g3PdU'Xu8<<Wes,̍UT J\$Uw;W֜ӵ9&ۄ-vUR¶ZK6UTʙop\r.So+BdL'~ފQ081=uy˱ïgzsf^UZ_|o~]̊$\/}%Yxꫯ(czzz4Kfl/ȨQQVso[HH0.O%d L,V/gT}4[k7$oy[D"!h6;+TJ]s5|LI&4P0@."1NPH_O_z{{7vwwk WgATxޖKH4JUx'|Ji#_U uΝRDS%q*iQU ΑVr6@F=[n4yZ=~Vk˅d|c4n|S-Xj_$"P?oƒn9g+ŕoJ&^1,El,>w:9vĬ`)/cG?ʗ^v+ ~7^xsn@p_ַEoLN G󙅙'4wtxzft&2otTbSb8?]覈jyI>ٟGXiT0a6&h䳟,F+n_׏;&Bd h{gaC]HrС}c`5*@կ~" _Kv$ħJ0L)!U$x4~ӟcDOeXCFES[CS% *lH :B*/RQJ5N}6ǃ;<8K/Í7Kj]>` xQ:5_ LuXYK_f %!4KwIiS8а7lL\$C,d8{Zб?t3h) E_ۇÝ=T"Uo W‰JBc?A3|4b "W?Tl_ַI,9*\Q}Qr8U$SЖF$w;\lǎ<,"-*Q*U"U" \{s|HF 1 ;;?A$ *U*5b/: 2#p+>lֻb1d15Vz2l[*7>>81=??e\Y??\wMEc]V }{Qop7 momm-LR` dXY^z#oPgsD'( LPdi@>]XcT|Rx"8QySq&?!V]/8ZELo2f}Jh'2gV͞$XO'(!FrTQU 0I,*ѦIF^SQ՘IIި*]G[ܕnarWyiG;dUURM/b$2_9yL@ 2"9EleCY, r Fg<c-3]fi|$B^}Q,=3a0sOW1"3'I`I+1E31BIJdcCElhuOK腼vjĐ!.g;"; !>u/FJ`!ȜBd&ۧfI@z![q`N1ȡhPS+1Ey)!U &A8`* E+UB)`R@Dbr\JJ]vb/ Mו e6& soZUۙK|!Z&Ah2|Ҋ'9NJ&tH*S&+unlHk5",]v;-ۓ'kϜI`AB˱>ȍ HuPlTTɡʪhHVeC6ԨwjH]զpWڊ 0{ת :)(!isg'1 @+\\7ʵLsj0 kEzeA p"`ՙYS/A pF!g2ˇ)O -w`/ xI'< &os ixZ'|YYa'ϢS0B+N$[yОF>?pm"6Hb禥 \B,oidr Ԭ%vRj %:OT1dD2: }}\ 2)/ڧQ $TM$Y!U &!U" :BHu$LJ:*i$p!KW#}AT ۓaNDl~Ts/wˆfm֥L9YyGK$~tB^q\N!& >;4F| (&6oؒAHB" ErB* aύ)ccY>.bӽ[[JcÃS)Gʑ{:# bK-D>>q\8o$Wbc?2UV+Jp@>>uUq> iT0QyQ:$t:gޠPuQ y+9" g_T U4? $J%&7S#{9'" 8հgJ>Q0њ/j7B gBie ?97|z#dr>uSbF#UļN>$gjrrmX72plIX8` &@(q tPzܾoLVJl0vh&HyC[ UET (ɝ %ʯ@ Ě$p؟?9:291YiJhwl&Ň&'O=QWf3r-צm\0$CH$,"/@ji:@lTmEU)|ɩFU@+J "۷T%}'PS5fW;ﲡA*)H09U"C:FYz5SsjX諬ZS+L '?IBqE^GOb'x 7܀ōi]z$=r<~|6=<$SM7=GGSݝ}YLqo[0xb9J 9_ve7"._ED{øpð25;u,vl?=ut( o!Ol' ~ӿxK8[{kh{h05ZlD$0,78X|VM~+_DStD$Ī*lʍRD$a@ ?NKndJ׾vRU"P ,yҨZqIkf #<#yGASG:UR A#}uirb8gɠR|G"'A?.1*PWSZ3U9GO>UMRq!~k@=RnGTUW^!rVT4 /فE|4u'R;<{WZ5D_UJ ֨ V1 qT-|ЭByoKpJPSj PZ]Osbd[ eI,ZxZDs7I#MyMYGVtCl۱CS:`%\,]~l!!I !?V?*l2|$kן-^TZ UIBlAlrZN"zڌEZ;$UԻVPSv3o`ͫU 9f0dӓ3SS,gaɇ L3=lDgKb.a;~Sرc|vez)lڲݞ\^ڞ$4+7 ?ba$M^ E46۩3Gl"1|U5I@P`2>y o{ۺvum.mvktpz%h<+7Tzr\2qDN+~RAdL86\`b$vU2kA:\PfJR7>ـfǑcA7V¨Tm\CCC?wWXN~FP#szDGCe*TW6.! bc\$0NƥHˍY ;lQ p `Y䳠<8xwԛQU<;/O\yzB@Dv9x.BY.CPl]!3)NSN߷{pDw\55'_;-dOpFIJ$㉎|xrWz/P;DdŞg z`X,!6}_l(-lN}IVZ:e=U/8PنL\99l_4Td'$d{ B/2TTpf2hXRi : y磌G\ kB\3v{S9ṪD upt@r6ٟ^jJTj跕 I1?D>u—mB˄-qVdcc^Dlo_k)L&'LlK3ݹ9X.sF@ U@Θ]+J$_%%']udd1SGʱ'hQWeZ;|8j= œ"*_U#6«@)|PO W9 uT =+D;(I\U.o@IDATp[fzz΁9]rfշt 4.Z7z> s:&:=s`j`Dxφ$!?_M 7kϱj^052u,k>;N38?4:+[oDv:s&NLMm89GW41:VKgs9L-*ΈA)%Ǽ_A;KUET%*Ib$NU/.[hT~$.O8#%XRN5^ P:_%!rSTI/H Jp/ "7֐*Pȃ$TL>TYqW˅Ѝ[8qt9UI!яR]Ĉ- ֭[ܢYD`؃/=]>8D [wH/ <:>fY)Lgٴ>\OvåǓǧCk{şH%vw-O 8 H{{BS਀[8> HTnMVT" v?~+-B+l:"ͩWK0@t͈ͩ %<3;FtƤqZ_Ewݗ^z)%6>{+}/! r93HyeyWK*ᣩ7m^d_^< D) Ezw:P6MQ"C"Stx'ą|$϶C!0L]āC obZ#m9^FjF!%k&b_|*bmPs)m >Ӑ$GX[@xG%j-RO} E0 v-Lkს @nVp"9C=/]@w]w1~"& =Ăm܏PMZ"*p5zAɥP]MF'lݸΤsp9"*lIc^;5WP|*a dr:o:벶dO8L_%ל)}g3P,;W76q^rZXv%g6*Y ,ipYgZaeS%zCC/U$|~)C`y4b.@e">l!Ĭ,*k[T֞l-n_xkZGF;;:ےm̢4NTWA,fTw'3 Nx {>~]1wU% $U0%:ņ@V5v^BlτY r@K)&6YMHfrd,1 |>c41d&IR_$6Ju҄ e7GFu l]S@ D,W 8*4::%pTI>^DI,1 О ut[G,g؋̝a,X!@8*yemJwRqГ>s_xd=P^ @1]pkkk6 =H]EBl83;7"F6nRD $^q+^$Dg3O-S=VGcXW+\ j+I>&[B JKj NnUT j\@jOJ$N$Tn N_i9B1v n f؟GʑP9)Ez}>hO(1OW_{}jt<_eKxjt2}#Ly.?'+M/Mʩܶc|2=ʥ3_4R3n`hmgLvtb]omS`)XW9K]mo(QA0o߱}p Fn[;[[,^p1`V}*.waj9؊|D]-i3'-+U˲iJT4kk~l#b]=ҫJd:H/^cn4*?pii8x]A,  $6 ֽ{r"9 __}EE& ]"wUje. %{tPKͮj2>&6:2h06:Q^U@>Ͱtl]gIFO l.1E؇BL)^>bAvؙYNKʑ{ܛock~]6WgxO64\b7x;\*/v%h; ~}OJl0P.w* &5H,r(~h08gy3Uڶuv9 "p@X.ag@ʥj)VjU =̅`YTnvIHk|\x"tb?JmRV1W^õ]?#1)sm݅nƏrJE&@6YLv:Z2'1%<P NgO>1Wl.XC%'s*Jd?Ew(IK}Q%AxT2mR-Lڕ`؈!9$P*R`U!_X 2]U)@MD} IJ:b1bBb\t:] b:k-4 '؋n"’?h{.SD k#BbRF<[un1Bll QBrT=YYMX1#mbm 3ĵC>ܻ*hIOd} U"L <pFIq{Qh!>$ UlDZbS/{_*D)wuۛ`U8tN׫L(ONnlqldZL(}|Ok={zν ]%ٹe뮹 PRb_`+R8;SyP8dH8gm^8̶;ÖQ/ v{ :s^uf"iVL PjqVTVn/swu@7E⾾뷵v2צx;.@dӫnZ+]C|Ύ2LjȾ{p*3bםdH:#j*u:h瓧oy&|z޲ kbͪn0&:}UěZX$OkJ$3O<2I<>L<Cy&Elhd-R0 \*H=JҨ*ã$^:w+Cޞ5)M^'#Ꜽ·ܢ)Fo9S޹sE݌v }r|j|8 d@KeClC[+oU!TOo uz$QI >Xd OQo2>; t/BD) lRCSB-GbrF`$`U$[W-v bAM++JĆH"&.A@{J$JjrLjըpTShN4o1VDn|x"|Qr &Ji4Ztr8D[QDG$`jbBX4{ISWqJ{0PK16g7ďO2L4M] bhh00sqCDB$Alp jBl2p5.##oTXdඳ@*oЃd_f@DdZ+Uj 9]>5QP$'[X52]ۊ)WdP)ڱgJzUiDT]UI@Z]BdR̞OU~I @8R% ULbZ똉UELRd>*Vz Q-P 0UFnF[ \~ɉ Jx<3=o^(I%G έފv'شpϿ|_>4JfyY!so~oI9% P"zѣַȗ/71 8_dT%E>rxvh_B]oޕە#`r:ٱΊex:?#ONmvͶJ;a>S(^ QXB"oy[vAL0*PO˥JLt39v_ U%XJgO&UW]E .vLrh4*!AnFz͞HcH*T%ZS.򦍻Z^< DvHUIGgMwWK]ýڒ#Had41:u`=$%>xO1NjJ||k_CV&b8i7%/2$a}w/cg)_Q-\HDG3sC-rWE6~O91]p#B} 7Y=~3|V o|Z@O;mذ4JHSWHBo}["6| _` IVH8u$GGR"Jc}ORƯШh#'> 6u)Bvwq0r]4R%hT]D}tCǖ|_^h-b6Hx26F@ZS$ Xa\)IÙ)廞 y8 GT]b\QX| :>$lwEﵻ+^zIڒOڀu/a1}~Dϛ{§2%-X#*dqM7$!I0"*,79-MD%"^|v/([/9w~8#?}->6 _%ݗ!6# @,1'İj 7@i @f-Ubm!v7RJ&+cMui,*5H"U.҈ǯkU"FĐf!dm6SA2Il]}B;{crc؇1eξd^anhPvCeSՇ$ׇjmA@LWUe/]$Q:&c_E>ZP겨jRw#ShyfPrvUH|լ*Da'M(-Y}`nN;tH k<¬wv۷XX{A~ĪZbcaX-{֋nH,#nE}_DzဥxO)c> ,iMh]=c&djn|F! J2^$yaT&m0|%Ē\~a={ß4rJzE2w)iJ#^!Ul̹W^YG*QUJn^T)_}՗\rŀF\T)ĪCO#>&7j]UA$J)k+2"v4$=>=}{FUgWduڞmodI`ǣ!]aQJ&kAyYfKr Ik&J%(db'l 2[=qD8.M(O'j<&xIxXVq$-! +ߎ3 `!DRlkۑv45zrFJy|K_N`g@L:W%f>?hT⫰(?s,>B}"2TR%_2MO*Ǒh@*PRtU%BjT `!"bZT'DZ\Ph;1i(cDva5hz wIDl-˞3(Zk6 VY.!-ݾgqDm gaqWrޑ|PO|| |3r2__%L~˷]q;D>_EⰉr,RٍHB>z뮻+؜cxǤ) NK(>s&7xe.Q}`U?z;&)#.4֟0Zb*و(U;%j2Y_8 j{׻ޅgT)S'|JQHsծJ੫V*g}o` 5&_Հ& (KEޞY+* Gjh"=FnG,|1ٸXfόG6nؖYHwgG[Ga{fN =$+>8u!U& -%#\Ve`+Ld.W`}Uj¤J$T>LYU^UIc<xBDlUҶPU&CQ̽Y] U' o`Cɖv0g%b/U2fgbr#17KٕXͷ bX{B0zwW}] "g>'OJwwf.mB 81I_ײ?8VTFfKE V$0Z6Dn,9|iS@lf*BaboF8\H퉻0INJBcRntB VbUJq)RGHd" I씤X?PyPb 1E~N\J'UtMcr5ԑĮJn_^UoJ0Aw^{w5QqfHeK%'tW n" Gc2lH8I'[bΑ"}:y"\JIٱ?OYd#Lj6퀘`C#XWpA27ydg_ EBݶΝ8`+wH# ƅ ̖7b+yufo*e䑏9x2-DA¡*$HG#ԋ*]KnܕqWzj*wEOcF1X#_u${5\' X#fiF_";kOѓg}!jucE!V6QNկpIDE& I4БY߬/_ߘXL rGo{gYQZ~U]]o4{()("328oż?^0E{f\FߨCgp\Xz~wտ_WunT*oޓ'O~O9yf>ub~64~)GIA]U)O\ QT\ Xw dN$ *]i3pWA}YY!Po"cwnX*E"mkjH%(4Ҫi'd17y5k]u wxeI-9KbJ"_AWqTް@87];ve~<Ӄ]]}4pGo;u.]+V3dIaP;ٓC\"6Ĉ퍫3uU%b#v%)JSgJ0KTN%G.5zh,d *ݶJCJͥsWӸgZ)K͗f&f%ʷ/m[JB.G$X.,{O[bu.=O\'ȎKsjieo|%}+*ym I"p%Euc 4UJ*Di ! 0PZ] I3Lk\C|".$EU3[S=]|UB̧-[BąĀ}$".TFCyq0 &B@Uul" sW DVLC dgyW2JOn!`j֠ F?D[ZZ2@U0sW  KܗWj.ayNi!2C`^#&ʛp殚Us&!P*Ule`vm6K__?br)3oՓDYBb [dq 1/D8Ll6۹B 2IF\s%;?-5RiJO7^w`xh=pGv)awsY"Ӂ}!t侨M<٠&I(9y(tGqzYHx_}}|wUXCUE[+ U_y!#`oW|[K~H}Q9Y{Zm=26 ?@dQ}TV+z&]eKmC.\~8*'ׅhjD7b Ύi'9X{wahB A"VFEUj2f귉f{ˤ殊eԆ*U%XfA Ɉ @ee`쟽nrjj" YBCsWu՘MlG&SBBѴHE?:I],]薥!wW(u+!ZL xs5YDžZK]%!0T6ar&՜kHC7R">"E p87I E;IsIZy"~t=0#;u8@cR 4*;:Z*Onho)%QK)IJ1f(Ko`K%[! ?@Tj90dũ  8\q*)Ki#č%==殼z?+])ૺ{zf%d"|YOg} ,^&s>Ggg%˄d9P Y 2w $J%($"k U( ]-lq`5>E{H Y֧ۭ!`oʟ ;wyt͋՝InwUdE0wUkD!ДTWvsWM.a+!mi=K]%!0Ȱ2ylG׋I@U0wWZ+!(jM Pբ*s{wU4C&E-H(q]w'AB}!,R q(}juܤ+&lfpT ŲJKf}whhM4qѢE˗/oooO-Ͳ``@vsgg-###0痄HxbS9$&$]lY$ypppll!6bNx.Y;B,N~<H`֧#3 $RyoRUR=$ڨ†0J }*@X$*ϫP*H"bEsHމC===9t,Yj12}{`5kww{hBHڒ5k$[)r =9XzuӘSeݳgK#5X E1a0O # I2=Pr'R-r_\reRᑨ_$;e"Dl1Xp*S-qʄ"pdŊU% )Qdz*6yjBHOx$TJ$eRuZۀij֭g+WWۡAAoqܺu-[?/ug"Zo<_|!F)D"g=UNWavi쫒Q\R`ERKd=VH@Aࡇq1,ӓʓJR%8.yn] Xc[3bj@YcR|_駉뮻J\-痿孷*LpZ{hXsY3FiܹK_i ׿0<”n|eǎ\y 1O~ȄE]XY(s } x7rˣwԧ(c)1| _sBoFl]ylhI;P#$¸TP#S c/\w%s=ʇ1;Z9.J\ iҌlwaOBL<+ZRp-K|k|H#޲eM6a\Otۏ;8XI^uŪ3gBtKa+Le҉x7N;k$lS%addÚY" M3H<6 /b #tiҞsm(2 /(WFW-w$TIjJL3C trݺuTlײ3'h{.1? Y=TG޸rѺ|d5kf}-LelbZ\c `IBtޙDJy}8t6UM';mdU*IURͨJ)U))sZt`*y QIL$`!u%7]% I#][!Hu?!p*4iSLuX[ĄF_j)/*:ZW,K%N<;_Z]9C t`".et?TmK%I!U" ˹T"j!Uj-7摒՛>M*ª&Tr3pW~Sn GU~4]Z#JCQa w?nrB awO6fIE qYI!91!08,I}pIbR0|p gbܟk$d]H%w$WQMj'>\*IIR*XQ%UQ*E;pJp e"m@jNVBpCY YJsmUm4ns-16HO oB`ŀ H$X@bZOXHPvk! XHXRj +@UjUU4>@S"wjZGUlKCUVֿ!`4$*'Yc]ͱ,{C`nλUen 2殬* Z,x7a&YV+}vaĻh.`ƉN̖ǩI` 8T*%Hj+^IELFV ͒Oio˜-m҆„R`أ(H%$S<5'Erܔ]34G ` 2WIc.%0㨑 k$! I4P5I(uR"QX%IuPBHꘛT=hFj POdb%~+RSUI @z!-u[q8C@E੪ne$ IRUS$J`P$`5ј =vs':VqKX UXN0 5*V-bqj V)FL-p+BX5J*|eOhRp_H""U$,Ij>HH<#33L썶G.H^ ΈM) 7+x2dO^.F$ L\gm{1HKxÇ(ٍDMFA/"[?a:yAOP6λ c90t5*'c3l:`r q7<ꨣ@tL{SpU. | ;<{Ȓ#\]blD*1[}IB0#OlLxF<͔8HhR L5H' '?3$eQ"7Sv=yHd&j-_1 lS MUUU2MRv{*=瑥J˳I"9[=T;'^ Әo`K9#;#'d!wd#;*\^Φ`ۑG.vrϫճQq yt\˞ݻWYj Xl(c#@$a<C hhxqKsb۱ g| 30q)O-Ē PIXT)*cRR@&* J7TRB*IUj Pm@#7v U:@6@׮_O3s%C` (c=9yǀzXC^<"B /_I<;N<ɮ%xMϷ@pI $t/dչ1ȳ~䳫tZ};O^]?ⓞAi$Da$btL..J&vң$*l1tbM +߹%Z!0ZaCXIܒ[iL%bqHBB?L 漖"eE09]ZDOS0A*MTlC0ijU"!Gu7*T%et? N(U("JDBORU);w?-}T*yd~CdC J@*RyRJZ_]U9K&o|cǎ͇zH"pr`i!8uHBKLXb쇋r-%G]馛6ϙh* GRqi9Y FP"-Xo~b%EfL?p #)ljXU~k|f086sr?EZ0'|I%9*9b(4*b*wyg]T4BO*9GCWeRK%hb;0k0;ŎO8Ϸ w 18mvMeE"|jg@v:2{YS[$ ,C?/ 0F(&j`6f F Y$r3bCwώs 2,Dz>&f $G c9J1qOK`+$x(8~(E$W0t"t/IөHJ&F)+˘R|v%e]t%LU%$ŀcVML`U]kڰaF|q  2* ^cSWBL2_"'Z5) ٻ:)$l[«G<[#i H/jv$3S%SLT̾*9C\J̛Q1Tl0TURTUJ[Ti8Cs 0h&5GQ%MၞŴ"A?C`. ehK'c>@At}1Ik7h۟0_%4%,l2-G6褓N(sL␧~@1ׂ\~rs0BB;H=<1$`rݓ[!a\>ӟ4VUX^ .x,oy[=\YbRJ9U>|bMVR8{xϓDU|U% ,L8&J&FbCSiR%䩪ԧV2Y4U~`~jTo _jܶJMDrG͇ȸ/;01gnI PqEOyDLUyĄ&J8j=(Y,e3$9tlx_."YHz$WIY, =I4 S$rQF"Iw>{h e.z`ŒPF&}JJI= T`J$T*[UUR+LmUekڸMtV4$:OHЋz>ձ s1'Hm$Ǹ@ bC$\oJB$%m&WeypWU nͭ*#$\!4*ET?*Tt'@W%LTpp g~Tܨ*!z#_l'Z]M5WЖs7Sӌq\OH!"sn>\9#M@,E,BE%5YUOQe6g v`%Y'2 @,&VDUcŤ2f ʂWQDBYȲ120wE :P~U)Bˬ}f93qDyN eBb"<ލJ$ 2oFUv UB9TEpI**[jQ"av$w,?c*b`!fĩkI {\M H?Jg2b)X@jry"$%19.wfu8`,I" dpȌ$bV,%ϒ9w@lV!@ HFа/uDl$A ɒUBK@Od-_VvIReIT%$IUhS*)'|c {J3CF&6\w$(UufEI*c P-QFJZqHl&0XL 0 $)Z#n^ r K^24DoW# Y$"NK.q)% =UIDJJM&JTJs W wJC ߐXQ+6i+Pi"H/)ö,I{U% eZfr ؁ _pD(1l]E#U)+l5%`(eb$bayHs/Ie΄7t[J̰Lkc\⺔jJ#ʄ Į"kK ]obb b 2xnu@ycwԖI#rJuɱܺ[mW^y%-P~J"Ş ;Nsjo++/ [VV12|Hcέ8/=$&FJ}9E+7f.w(cqv7`k/bX0XUV`Xb@ TU JJ!?]z饒[ʗDHS&U%PsJIIIU"TL* Uդ>w{j Kj^&V1 2W*=bL9V 1Cg*1Co*="HHNH" ++7 ƍElI# |D8 e\S8*)ܒ̳0Ara(C7&U`*(/WVrU 1IJ^aXyvH4n%F|I*&"6.z]a_whiMrMK&4x@B@eR+p>JFbzSyI2'FVd , -\B"g!I*VڅTT5j CIJ7IYL_+!0 S(R,E]"ؖ!x:&oFIm-D]-D[ E wWl"`K-fm˫.e,[U0XU̕s_%,/+sfkbYI$ fprPf Iܧ^"9Y'<'!# 4%Z5wW&@AsqdH"D@ EN\8o$1?U3|[1eJTUQl/(K*ɚͯ$vU%BTURT|U*Ymfc !NKzbp >*6{dN6e`k"'3" p!8B~!ؾ};MGɣG_0{b "Mȅ\㮩(Lxʅ%#ʢnF /=R&$o ^DW|l%%@ɥ'@sWIU" UsD N1(hPꃫJÄd@_-D^誆`F#N![o3~0}h,M v8$ .sCe-*??ӆyĞW_}5yGXfoƎCkeQ vTwC*:{8 4=<IbLoaVe+DJ}g!50WFxWe {t7+Ulb(=v(t$ŪJ8#fW%"^Ӫ<\5Ο˄UW]u 'm?䨒Zq(Tw pbrlpUޣ6d$6C'0q6#{FAgCvI'I^)$M"$brD}*1r)iDTIx1NDΉp%R~8]t*!O>YxTY1"zCĤ5bHo|CrxYױ#a~yq<^SL&UG8~=lSĆdU)h#L*D@WTepU!2JQ@vUCTeRn.9%ySYcف33f m{qgG!$c\%̛q~WgG!(jd́Gv. gqd_dsErLϞ-I|01xN(V䎖`%o_ҥ9`%1?ܳ)ijaByM2'}𤝻.*ySI IG0w$LLW$##F^$JWye`ոGZ%%I*2y%2)1"+65*JUHT,U#A)@**Y5hj/bY\jbn #Ζmؼ9uFov>۶=Jn!^pCB d!Hr&FL#F<7( 1/l45^P6" lsN#1H"yUᦌ>mA,\ǚ RW1EUIHө^@j1lp3-~mnօ$1"s{"({M.2B1/I!B)DL1 IRH$)v!⌺3h 9v`A) ]--/2[SW14& 4l7C*;{1;TD#V%}}gܼz2d:LX  ֮['YK%nzМej-2s,YfL{0sg.}+WVl9zhjzڥ3ˉy3Ը1F3(d/"_64E۷g]RJA& fI !-[۴iΝ,Y`FwWUeV0ABx̪T5']z[ϗ,苣|\bE;9i͑[C`!-YN(4uWS؀^9,1p2 ZS b溱Ě4_}}Hx{fgʸ@:sW2G`f0Y{4Hyv`KXLX=T<ah9%5sJk[6OamerA`,`eC*}( b#l]Rv L(ޟrphܵvb'ً6D2>??o14٭v~wO m֞ݼxsb*U%ɻ+ti$^@`o؀3,&dOLaM#(, 13۴Ū:={d7oȪd7{JC75+zxOQ:@W-[ ?@I[92XuZöA%]wΓUy`OJady[F@T~Qq%5’ ⒕V< B[f~M~o`m20^4!|bgE]].ޖ!`x(ͻ+jv !!P~wZjIJĆ@sW H,XH$&#nv!dem]5LC`P680Jbb1BBOw66[?&!Pg* Wecﮪఛ@Uc0ĻHsWs 6sWy3C`#P"pޗ jf@}U}p5C͎@廫 -&@У!wWIf%'ꉮ6zt_9x7 3h)H9G:(RM=FBwd<D IL?lGv&iood~8 IjbFWecQ[16Uӆ<'CAI8{U;7eND^p||2:̟Mun%N,܋RH* mqep[U ->2k96:"DDﴺn.si$&PGDŁCH`бL]Ln|Unذ!)ѳ`ς{?,>zW8mْг9s.,TJȱ>Gȫ׉VڴisR#n XS 5Uj G6$OQ 0jklEΙL8]ɸ*PH@b$]-U8sF3;2Y*e=pQLryvkͅ@eW FV  wE,b]J8 W%_A+{v˖-^q onsltIxJ<-JČ%"v"qӦSO=h>gqwo_a")GqhFw|[zay>߹߉ꪫN+ݲ_~p2Zz5Sj:o߾wUxCyk૾1曯:׽X2wM7_~qჇ|Lc>gt(EW\q3$G{/w-l3fOg8Xq ]ayτ]]]K{Sp}8t"y6dcfOߍ-^b><<<k}tI3Ӟ>]<ضmqQqk/JynSS[ZTlF7`ZH%0?I֎6NdPB}zwE[?M+'JV*g%M9Tfw,]9bᑑqTGfͨAcqAŘ}#%2Gs*#x"x:#GqđG*y^V]z0`f[nU_%dTS.}/2HUēO;ޖ#`-iكjm8u-S`b ɉ*rEdӦrOߞbDItV•Avhmmkop-Z,@%;-e:#W7&Q.U|"v5<#h Xr'uyZNrϓg|r[E)Z&%[+hL9UTÞf'ɑ 2<-\h(Jl a =#6X/a0;rvs簇O#3Nغwb'~7X+5O ɖ^0ק -]K?㒩,]*Owӳ瞓?!#|h#[_ضow1ZZ;[z;W\Edv%-VLۇ_ww~d9C4* pB8kBDEDSI GÈBQO]h#Jx9;kxaEG'EKT+]CK/W~{7\2usJBX'}}I ā#'3S9:B:IyU6f3)TYFrM DkLϺ>Qw/H+Wy%We\KR ,){Wvr IX 'S`.OWIͫx|D&bݳW"{.HwQgy8{y_Vla :29Ѳlmmg&vS[4EdbbŨL1SPJNp];rcQc tW)XMS$ >Iܘpv l1C"3c1fQeCIΕ‡uw-Z#p^IE| t`¸ @ tYfa뺫 dU7T[[~]ėVB rPWgG2rJE!<1*|j^K*+O25ixJB) Mgwa7,39ܹcMPY~%PIjf@{ζE^zV * ]IsVYa?>hrZ4=bmqX]^i1P813.G*H;ndNYT鿻C΋(߷x:,Y+>Y{cPo9g'Ч $%?opWJû8!s +,0DŽ#QP#Qu2ތ^4m)Ank8"y98$yDYř4@utDCVK+Ao4 )F+|'6TH'z{{Sj<_;$#(*9O0' 5$[o\spp|ds2)[GTMcD*-6~崱±i"6*V4&NuňJ*].pǹǴKO3/3/AgAY8^3dcQB!b%QL']Q}SؽM) =HqWr}Gx5/uF2xL:pK΋~bLy/>WΎYkhm9021پ.vup%p>lkiBn[J(iȨnoLVNE>q 2sxE QU<{<GyeH#:t9xTGN0PT)NY2Y/ܢw-JQVȦaS.a0!0{+FW>~w^|k+ΦM6e^r%ɹADxVk˗c @։\Jؼy~nzIDATSO^bn9Xѹݱ );z:ۖ--˔)EL-ɱ,+[iئ8UkKax'q fE|}ڟv/sKܓ㭋;EE9r8\ ǖu/o+ۑlcC %0e*S˦ZG!*3<08j钨{wpq_-[RO5+B9=?CøceK 9A ]g?^y:9t)3μm,"UWwF[FKC]7ޱ)'>%e;~~`(ڰ1H8.M!!`'-[.b)m/~g/sc._v3qʒ F,^] 7[\/ҥKc۷L կ~5O1_p0c- >_H.\80}l<سZzCN8ydZhl CXpdk9^~eY!6Kmو>1,aw8˿vIo׾۶m뮻Չ$pѕW^/g}6^@G_ N'$ެϋɨ|2{j!@J3(],1e370bi.Bq[{d[ed+%c䄱\9##nw!P1:^>PxR9MѪt(nbUFZ0 CM5ccn!`#`*+4 C3JLXge#"pGL.e|pA,Ih+A"2ӗlL SS+I]+I983L|Rc 117|,{*D Yd*6dtn(@&&-@Is$?8B _lR" ,=I3U&A1UzXZe94=Wس۽P~?'k#)BtHVJsOtKvpM^[S J ]hÐ@ lhn C0 Dlmy!`sW3Β!`&fm0 C`!p0 C`60w5h[^!`3D d!`D2 C!f%3 CM]&ږ!` 0w5C,!`l"`j6Ѷ C0fg C0fޜD:J sxDZ[zo}C-rHe72YpLD,H {L>JvPN?nU&VaR>ɋ;o%JIJcc=ݝYx9'k0e?@-2 q$#cwZX$CEM^Tab$$c*=X]XEmIENDB`micropython-1.12/docs/pyboard/tutorial/img/pyboard_servo.jpg000066400000000000000000002117621357706137100244220ustar00rootroot00000000000000JFIFHHExifII*  (1 2iSAMSUNGGT-I9105PHHGIMP 2.8.102014:06:05 22:29:14BJ"'d0220Rf z    |t0100|     '@Btg'2014:06:05 22:25:402014:06:05 22:25:40Abe@Bm'dm'd0100  f@P`\n0100 > JASCIIO08B00AFK01R98 @($]HHJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?+%gD*ʵqI2{!*Ipsq!jȫ$rKvQE1zY}ƶ7[jl+CS\ҡzg;EWQQEm}3\u.hYGA=tGeP1\H;0'?zw!Ӛ)A ~twZ]m"(@}Ǿzo%31s߅v~s㙑PJF8~=+Bw=|'_V5ޘRzZ \g!_k0WM煈QUdºm"/.s\KJ;c>TwC^c=+ٌN8hj7[Rf)%YEcTfD_imn[SRǡRtqZI73譸)@ ٭K:y&q4;O魶+^na]^9ܪHֶËB\ƾ*ӕѴ`ҳ<W'gR?%߂3'Y%t&0WbIrVy-S,PDHFMu^D6 9ek}cBpҺ7VMy7ڧ_~Z~u~'thaۡ7 BܤIZ -ǾM{,v$*>8},h5lLxU׃|Awp]4t7̎ '@ (J-b:@3 =8YbRΌT<ҙXI,N? 3Fr=|'4\?_tUN ǚZm MӒ1JkvB8 R::WNOVtƌRN$|hU}bq{v;[_ lC>+qG)},G{T״3{tQ%utd?42P;t(0,~c*>яI:vq)b}8/TlV\ep?.,}YT.ܬQOHK0"uS$p&]rW]̏(}?G=z3g YF2b _Nkp6I 8O"i~|jP4e>Ί[BAU.ʳRyur]ҧ ۨtG`>joi7~PU1zO iFI$\Mq\A^x%|,Ps18|Ϙ骽;U1JazU..G=wT-$%d|6o.xq׭u^ XԢSZu\t{7.nZ4=F=7Fu}FhVF;,OZPRz/$¸νgr_ts.s-.f}G R] GL\Wb:vC[r |\ÍYx,Sz;;tP|OL-(ueh~.o;Gf+J<[ &dUc-Ij}RJiPVGJ]vmJ jʱL߅hn>\[8ac9x^`#20ZQFI;-ͤM-b55j7~Ze-8 ?&nLv3zw*Y6zCv{XL,iA׭4 >HAGV3UϖxU\Hyus}FleL3_e!lg4*suZ`m^Top2^kw:4YIr9`2=3^WȌ @20E˰wJ5UNƞǗZ)=,ح)۝>rnܡpF1|%@CcަGܹ^>:Q[Hm'JפvE9IE5 CTm*>˧$8[^i ne{9v{扖J7).=>V=JL$dΟ3KvGV=Mhu6\Wclˣ˩E<[@Lꑢfcr "&Ě얖"Y' cӎ=MU|M?u3oo#[_=~,t}$Vb  Yrz+or`KEКG5&cg1ՏvZzXNn^CՍ%ὒ枲ՎLv9%h"444D0pZ"_T;meM@RǮ3i'kkEx˨vCZE#oMAMIi#ͧ2{ nQ'{9$D*|p~^HⲴX_K2ʅrTd}ȬQpzBy.oj<3{O]I%%p.Y^Уld 1:ʹ/_Kes .c2q.秂jQ]|6ъM|3W[]Te+>"oSϧ^#d@s fk-$̑\]RK,j~p;gڽN쑳;s,gx{NOE"Ew'aTuo>*pJ#X+<( YEn#O;?Z kUWO;X;7=9<~(iQ'Ö ʽ 6yJ2zO僂}Ev#5hv|J_FLzݲ|Q=:oe*W+etU8)*r~2inS] :؛r67bf#,c5ǂI짚 KZ? 5k]O6$ddgv\-z/+ζg|IuZL&xrJ ݒ$q^+-b^),Cq{:Ԋ=n Hu[Ma: )X2$+g }cE/Ls(1u/5տ9E 88펕&{w4f~9Dξ2 djhl}kU,\ ^]ׇYg>Ԝx~5=2 p$E}c6ų]J>fGxF*n*B)1Hd\6 U <R?zqVn-䍗**$V9+-6,0g_)q<HZXqixJM֥\8.{ OY$%0YԹiy}\rնmhW5I0s:+{BI>Ӑ\"_ۏݷy*)ּO4B yqsTu??M $C)׊WV{χNe9]zOִ"X&";pD[x*Fo4Revc=:$fP]=2OI5Y`h3x $D~lg&d5jO ʆFN[9$0,yT$z"K[v=k[uV$ 9/ώE'uďω4;|ǡx7z[_ZXh4=y}8Gef60[FH  Tح)A3Nym_EϺKF1ﳷWUJ<½␊~( #G$aԃSM"<kD B?&wh۹dL#G5aa=)*>~ej26Y`V?Q:mYz;:E{SnoPN~2h D[[Oɧ[ʢȴYމkEq 9SPZ6vw'ڵDPm罻R!%-3G߀?+$Df,Y[ M)IGF]Sz㷭nu\i;a@&Fp}3A= a&ׯ GA[)"gi:Pi~ͤ]d Q˟>5;Z[H ,zkB2믠`t=+okP^&RR{޽gU$ GO[rs78xgC7ҹM>g!6g^9El=J-)\UMbV,j@VNSԄX8+v cNmCM$q?Du//WV#k$0{H>Z϶Ҭ-s{1?=Y\ tϨ8dgMZkX"9c?jZ}ܷZiqͼ|2zrkFTW1RM,]!ڃo=pkt.mDp9`/5wǙ%$MiJҊ+PK1hT` }-mRPbF)cqKZ*aSA]%R4P$|;d.3`8>3 z?*n"+W~WWjvo4ih, uZk^fѯ/ίtD<󽺜|oJZ-yDE`qW^:27)0k{3KE9OdLQv(+= qF?&BIԝRsCv24 9$1; 41U!7}X1KZv1KEJ`!QLgx2*1>Y'14QXҺݮ4s}+Ѽ~Ŭۭ ǻ}hLK|A%#(Q/j()(4Q@Q@Š(BQފ)vch` http://ns.adobe.com/xap/1.0/ 3264 2448 SAMSUNG GT-I9105P Right-top 72 72 Inch I9105PXXUBNB1 2014:06:05 22:25:40 Centred 320 240 JPEG compression Right-top 72 72 Inch 1/100 sec. f/2.6 Aperture priority 100 Exif Version 2.2 2014:06:05 22:25:40 2014:06:05 22:25:40 Y Cb Cr - 6.64 EV (1/100 sec.) 2.81 EV (f/2.6) 2.49 EV (19.25 cd/m^2) 0.00 EV 2.81 EV (f/2.6) Centre-weighted average 4.0 mm 202 bytes undefined data FlashPix Version 1.0 sRGB 3264 2448 Directly photographed Auto exposure Auto white balance 1 Standard Normal Normal O08B00AFK01 R98 C  !"$"$CT F!1AQa"q#2BR3b$Cr%4ScsD7!1AQ"2aq#B$3Rb4 ?qp… vf݂3+HHC߰ +ěid9|e%$@ Bi2>K_,ԄY5En$3J*e'P]=/FAA@ @r5tY4ѲH(Fi.HߑuJ2g|1ϐ5.$2J+f-]4iIks!.UyHEƷ392-Cxuov%5T.`&2p5Quz\?qqiRiە y pZ% ;\=Wk1g_gxFRR#-g0D BLh$$P*3ͩDт>˥0р2因I>(E `Q1µFՐ"Efmב!vdkPdrxꎆGDpi*Euh@ @iu.l݅%Z7Q%f_tS~ WGLcθ! @ @2=}eݰ7ٝɝ8. ?A¤pX0!H:]{m?ҵ8&,Zm_eMZ;\~cZH?Lj5/~7O\s/vmzXU6? >(ѻfymਖ#V#U5~gɗ2@ @fVutO.}8\\Ǣn WEˣ3rO`ct;06Vڷ3IYɳY_oG 10 \0Nnr5 I]0[1}ApMlGl[N:1$IBy#l=KEe `/fXÖ͘43:%#4h#E$囅\zu}.WZ LqWrǂ1D畾[N>Q#[%QFL't?`| 9u3 }_GNecٙ:w>W+x2>k6[ 3 /}#I7i{^$]ȱ(sw~icyR>im&r BLH (@6ʖy]D]ˑ'lJ*DIz6}%w2ʑP{8H&bwNV&ʭFvhFFzEʣB*$]-UPȅ@ @ܵmKU9Ŀѻ-\#r7rު4'^ i(Y=J飞" @ BM5Msc'٣%g0ѫKY'QVu+.8-!/1ȯ㏓h$K;m\)R8L1K#6v!;`uOt7)rɗ"*٭ј ͫo li1.Lḅ̙vղ{D_dw~L0%9uN\Gt/vۭMs#d[9.$켏/zY2uq6 13~:JѮ,z g^G 7}j^~Az_ |fۍG젮A(I $LV!LVK݅S.(Ղ<afĨPh5pSHM=A9'fz̚pAf>:&v8UfiZ̀딄;)~9 ~uQ @⡥C"Kq"@.L&(QeA[N FpU^0=Q@0HcId=(mE[a):^ڛLy˲k|W_=.l~gZkh)cc/'2>_iۊ?#j^&/ZaIt5ULt].<-ru:Èڊ|\(|]9ƾ@1p>C<92ATL^˜rWB*/#r zĕ|!=ao55N9 WWݫ>K+fSkîh#niM9]o I&y_3~}G)ו>uF+xmg]z+oGvI@1652"ϧ>ߍRc4##d 0rp ۤeC{퉃;i vqV6t*xʃ+}T< T.H x[2;#փ8 @ $%h7R-}\%?UL%臺 +Ta溑|'" .a* 8$81 di7o^oeK'Y2= / ;;j5OttFӺVcԏ$/+_>]#h>D1\5$Ot$UN]At1=;NJ5|@_+cUQ<#G?w y! 'd290 0b&DDLь'Hil-.Lݻ:D%!3>˶7[\Mti#;rDVX`fiQc2rYdPYx9[˟Eh3 @>i>GZ-M+rdg!P1C#n#,w vE*Vr.LXR&! m' ɥe 4(; By=_pq:m*%_ٿ]yVtF7clzE{;hWCs̲]x]RF|ڼx{|US Y4uç'75t/>'f@Kz}V ifSmrf)dlQ10TRDJǧu}DrYOQ,i.|'%?EءJ+V6ӤYp0Ƥ}[o>ӧƖ/I)˥pWB-Ӹe+Vqi h]47dVx#N?dW"(6X?G|RbXO g?c^-4ֻ̌f5MY Ɖ- nl(?#_f|r9Tש*Em'騌` Nm6' vwKcXQQASy'hA[dV/B-B_??EUi*ƌEET@T?2Z @ BCuY\6NB4X'$ MeRbg./cفL&!0  RbjDϔ˱ڝ^4wdtlhsꥷlZW{]6mD㝇y-g˝`TsNa=T=&6\i#тvR c%2Hz$WQ UK.J_DŽFVLq#1$ď;YD s5yᦒhmNF\22Få/[wI}P%'Y)4RI ,Ym4~ߧ xQB .sq+v-> +VEMYoޣ,(݃+mS#k,F?_qLx2k)(ex@2Wd]7e+H"!{ ,*6q|}Fނ^*"2ANlp^O1W'y75tuF崍E{9I# NL@:BbG1Q\S6mH򛓀?ES,| (lBy}aAKpP6>T\y~;eM01cv*Cfg IZ~J dj"A] ~svhA@!! !ş^>J,3cӫixʒ`ʵ|>KJ"J+HekֿQyd FfYkĽZif-5q[ZIۜ}Mhn3A܈  =@}3h{Qw䳹\]gKxy"%8ӱ?\کocMvTq~d n,(&Hb Uro4XtyVCLwh C㤭~ [,{n|aa??|p (neu $z.zʇ5M͆2GL>'׳2l$s a|<.'^j<|rG^i:Hg h?q 4瑲eQl֪|2F-)(n&PUSrUY4}ao ;UU ɊQ5㚑Y¤ol(=FOtPtF'F&"SR<|'G=g+3dj2#25 1A߭~ٍ 0'c18sK%ee [<^lk)8zkb6cӗ'uq"kIڃI\$1UD㡛7anDx2bۤ$`&{/K9K\p0OP-V.t4fz"@?ݞ~I}Hڋ:FF~I,b(Wm.kG-l[DIbzD?F`xbzavbZ=;Bφ#£>f&>UY\x8?@^wQͫG{ǥVRfxt:$Wmi1R_O_;X7tΑjZ`BҿŁ.-_Vu/e-lm5|!]Uɩˋ,Ώ kZ:Ely>99_flr.Bԭ1Oj؂&ؚ@1C9)PnqGH1E1:G(=sTP]_Js^[LB =_x~y'$r]ObWG>k-&6f7#Vy=~m;ttj2c|ds4cs2H &ۄsSOrF'.d&{tԥs3)MeY'} ZtkTt fQ`)kRc1Sbf $+1o'<";)P>ҳdj$ 3#G=@&77ET4Z3f:yEKqc㟳v <ǹS/*GƯfrDt|t tU^C#:h݋IгAU+&#I\sT)埲(Qh&o+ċK50<+ÇIR@ 0xJX-5D't-KT-4_lR$Gi?5%!4zO1+\Xq/<ՂcCq5C !A} |Ժ(zfqBRlZA;@{8mGc ێ3v؜o yu.K&ثlҊ/nF+k<~8ySߟ P9̥; dg8خ 8geSlKf ZdIQҤEI*} B f5%A+h͛]<ß)Ub~Iv9,SGU胓cv4Dڥj/5@a+ Զ0܌R}FM@Ly>8!Xt%OϱKbYlhܩ5I(Q4}`1nf7UIa2}/wP2~-2'OCj(ڗT9'р3QXCW{ZϞO.1AWaӨ'BrɕګEJ6]l:Gw#YSY\N1׻t흇N]GEC22JrdݲXh_L<@ d z"]&c-N-E 3vDx38tWּ̓pGOCJ[5%H8~X.[Bٗ]ャАSGM h}avd Ϫb1c@Ɩp & 1s<0b=KthcV\Jky\.Zb;XG8r:8s)Bx\M# s2S Lb- znc-TzJ3[lěd~ť~~z%|;~>|qү7h|?eCp*bz^+txc[U⌕Vi'f:6a!EiG0}7%2OmO@"cʋєkn7#55}K'%L|Q3-2+[0%=̬BߪI"` @!R:F?9CL=J s@ BTi= VBrɒ0W"xUޠkZƎ^s[LJO[Id@+gҟ7gcKU.F㴙f+L䌚~<]w5("t=O ja(1.\͝{Gxyo5=pGղP/45 `LcP A% e:"{0 (`.=2;PZgT# {ǣGTe5le}W:i笕3}\{|2_X~mfrȄx)Yn[N厫Og4=!XP;[`0M逅$ 8j1MsO)mƛ]WD_S@ܷ?Q&:T$Aiɜ\{F/` 0F9Ty8ŘHJ׽3yFGqɫwóKc |tD19ge=T=k Keys9Jɩ2;HVZZ fsJllбdM44oڤ9 1:w1ǒr7q7FPq`A6=@I[Ϣ M" o|hQ rj˗ڹR\}-IO&OfWͨͭ<#|fyes|O.1nV:d ٺs5N *kdpilR=0^ʹBx(1 pȠqE q(P*<@ <zHB(jS4 L]ڕ4tI]& WSZ:뼲ᇖzO%f}{cDžƎ {3QQs;kOs. ,pU9YԼgF''6ܝGia1QUdpe%HK#۷ ~ٜM!it1HA# Vz <& Mr@_P1o)DoTh٨\\1feکOeNPX[<U>3>H˙?ԭX)#/lp:-X [P!S,EBP0`!oMyM ,2&9F3=Wȩc9&ҵVy\|E%β*+15.D-=F1 Qbւ1 `,p G C y9N {+0-ES b D0d7.zU^\,Ŋy% Sײ'^2v/^yfzxAo|Q vfv9öaç\Aǝ/eWSV#o8c溘49'8-Y+tct{ GqgEtKK1ǘfiЕ^G(s\tg:slYAsFN"i}6dZ+hROWO3eomÚ'PtѳCC= g!H`#ؘEF) {c`+B˪OKyTHK?`1y>729sJG႔Y\4̯c5,ǖݻp(9savSwlV=;A0EaWOMvF-WED-m}mUq?`J1QR60L|ZfOD  aB,BmH70 @@EODEAa7%-ud3OPmE[,ǍȞN}.~IiM H*G] ƭ,åf{%x38Ps^oz=1O pbhkִv$ܛv̻yt n; `:}Rp6-RC6!`Nao ꆀfz^״9< E^mnn@*%7rF&YuQ ON#n[IT($@dwYe)"\"ie>jKVZg/xƏ*'+ٶu˕Do>*`en ʧ攟dp!j51K)dսANVaF]l(j2FN~%z,Փ7/ֵ%ק2n3MAfJXSOgÞ9WeςX:rQKT^ nV}^3i$f}Ck 4t9 i5ZLW]?h gh dUeK;xfmǢp7?U AqM=Q@DŔqg)OrkuA?jE{(7}MPgu%Rg| ɪ=ΛA 6A%$fѦ}tජ~ ;ˣ JNQaӶʚE`'Y=OOUH!);oGJz .Ndǿ+yy$pV-JB& !@XӁԢcԏ 1Z2w u XTPc@(gt8 dd`=8pR)d%%IvJ0Qp5\C(!1X2stz}ioPkgS9ul9gؒ4l!һrVd흵aǵ;ZzS>cO#]O|ޢ,K,D &mv1:VXcSe(;7 xRQB=!@ -Q̔xf TJ}GbɝGuΉ>]6FYTYrO< u9զֺwq+Dts'f9[AM 4b8cdla_\ WURAh"&H4ugӡ 2^3HǵIzCG}k-;gرSѵsbRӗeSpt߶JW9ʲrъo5e#c}½qz3u*TVѻI]CBi]lvx2y\K&[WFc'`:j yi%4t1b%Q9&0;Kϣe[?'h[p96J3?5Qd|4T;/`I|鞟"͏쟗{L6i'|c`,giI/{`#V?xckA>rB:eKu_VogA)$'8^e)MEFR;;Đs[O[4'.9}5TtѾ˵ KkͻgmZh :Jp7'l-bmOTK]e4!ɅWDP3NKGԒ~$Q%؞rGv(А1Mo~G%H}nzHˣRhf7qAFؽC .g$'$ۤr5ɍ5;tC},:]CX#_5rM0n{㲫rt# eֻؒs($Wu%sryeOeiu=\Mȱ@Ǯ8^lHFhkGW,qQ^e^6ʑX$+p1`c1=HE&GMT1?4z`7!!hlqYGF\>GN]Sxdl cCZnc5`R(gwB7;}Il1YM!>^OGg5bZ? 5e;_n18m-uǯ"` Nˌn~sc˚_GApu?h@xsXR9r<%ZVZiqUaPǙi@a tҵfI yU&6vOoW;N:CCr3EkM.>|y.t tNXx_J/y[1J-tmGxF_epj=n]ܲ.>z>C5F\M1Oow_Zxle \5۰G2É.O4SzJfSآ`ZދI”v̝i㍧.p~158$v~i5w`,Td9E1#I`N]1pJi$aDAh݊@LVge~[hԚ(;S:"4@?F?Lvb0pdl.< &#}Nؖ*Y =#XroG裋g(\]U8np֎"DJ1DHEN3egs|tz"옢V)i,85d.;tR2,]엌W|<3Qv^q6&0T.@@@ SLmHǺc )nBN k p -SADP L$V `(@"(HCAf9}0Y/Vl"TcDꭋ//ۃÚ;'Oy:xx9l/Oaz?54h5S6:C w\WydgizI52< $͞h!ı_aۥLEZoQ.mkA=@py {, -5 $t8n _򓓶c8IRv$ uՒJ $&lbpx?(rO҃)mDR-c0"6㢍Ve3!!6/ BNJ(V.ߪCl@@> bMNFKNI%n5uJY1~9::srQ4z?n于-ΥqimULpYEr LC3yzC/MO=©4?c;o:EʖhY_V(d樜N,|"gJ##28ޥ} IOy dy' i0 6֟D ˜!z {A@ c`o\e: dT *8{(U4E 01RrBC4&85 MjLp{YBy>8/}MV_K&ב%J/3NQbgožSiK G#䢋G`;\9e%/}'v'e|liXݴOZljR_>r|xLE<5䆌иuEޅlvGT 2 0;B`@PU!+v V6RN I!\ L$G*Hɼ~Ig0wDR;yO3Ƞe~.AR$pemM^@ :4z R`&8 pg$ws ;! <;Eqs {nR^~nKBڬ{&>3x»\r{/?Ş׳y?ǛrRd-KB(bsP|La3QbxkmS$GJvk~ӱEۺi;QR-fkE;N`S eʹ<_?.ҳ8^ iT39cF($c56#vnBpByR 0 c) :ׄP$&P:~LПB23tg MQ4W=hY)IGn4\8UWI<ڊ>W8I7٣6 >mߌNJ-LTfl[8nw3+iErLgZz.F4K=^J-̵3U^n t`XXr:n(Uo~ KEϚYoG>y^GZR-WUݐCE͑cy<8tqc`cֵ/dJ&0{{$ԑ2Vk994؉;7aLLLa= @1@@ЪC eH=RCPL ; v&N=@|>h)< 3x衢u e0uq,(˻J,*9+^iԖ Gy'iUc%7׏g2)tC6kkqW FGM 3(W_=>cO hvuPhcPp\%EKDLi2pjXcڗQVԷJj7W~\2}V5 VY9_7ŒZmB3Y8Hژ^1휅fkxZTc%; 7*)bdd=Tvՠq Լ=fI+dyuw$tcFϞU֌#6^,6jm?o͵NH踚D?ʗFՂSn|A̎!k.E8g-&?᧊@0֎{AATU#&I\r@՗M;4<PHz@brd%AC؅d݁f `;=P9bpL&1q90 z& 4C{] :5K#pHe,ZHO+ʑ =i&BAP>7Yh䌴?t[V473PGO?q4RTwQxMMS7?.UhM}#vhrp2ny-LZ2*^?T5H.V4# Rq;j\*O8٦>!Pܾi.Py\Vif'36Y= nWc72d]⥩'£ @N*DѮ3`c Xw@#b,a6shFyvw(B36I ,\pXcHBa@Bm6PA:e[ ' i`|n;Yǒqʓe䓒8͍7#g |!END=&hli N>imh[6 $~)g,_Y|-;@O 6zpY l%cͫKofSemSV 6edr$6LtSԀGBW,LŸ UMCLy` xMhV 2U*7bu$Γc~L\`|יۑS=,eu }%lz~55?'Y!im=$ 7Q{zh:/Qqv8@11@9@ B\ *0)X 7=@>l<^]jZ6PDqS3OhU>]Α>7|Kq: & H c{R:vi(A[;nV׶;} ߵÙ٠w.w̳O#Y4Zm*#7sZ KS3Uj涥`>,bG-ⶴL\?MX1)oﳷNjiŲh#@ijFrM殶~ }8w-;\y3NEYN*(+]EޝߚR;'s3p|6sƺ\}5ۥ sf9&'Z:}t}]/WGUgȹJ%G( aǢa`[ =P_jJ=/j.UF|ʄYv ͑A:wڻ΢Y!|'h +=vŌлR=G|8>-T܃>SN\{,z,_HS6&7hh NNN!©ruږ3>5~(jFҴ;CGUEzf 1sHL2@'Ҍ ~;C&:O_%-nOZ1 Yߚ`&Ѐ  5 9EF@OcvC6!odf (@ )q8@PR@(@XP4p{! PX!)Ϛ:^L. hO͓i+= ,/ }UL)Y-58*妢K1:sE[&זQcA%凌P{І4|Lȥ?5#*3GQ$n83[&fQ&r;O' =(nbN\;80W_t,|Y^Y(8ey Vq>,;U`X;8/ 9<9oq;vd8+>7SF3_GcpD@=8@JMW4PR-d4YE.+rAUR:^7MG$tI&a NJ1]4;u̎p5:o: $tؒO-dg.>˗,QF|]S%81 %_N^wK?XG]>W(苿g p! ƿh]+RUCKOh%#ܼcN5iZuD8Ǯ*2蒄u˾3Ǝ䏴):CH5;w:J԰`}SoR ;vUc۩"=+ZIzIRF$cǡ{@@0Td 3f&Y z)$l58@c  0 h,Lr#cAN1HiϜ澎*}[_46BG<6rNӿf0^sFKN8ӟdj%FLu a?WB\9?Ijg|5s{*Oq"l7H" Y2xtupdyӗt wnZ-~59hҹDkPL 0u95< )vB4QgYdLc'cQo K&|Q<S#1m#kmn#a@dv\ٜ)HV#}1R@P U5nuqPPYPȡa{z(ɤ&ښ+t\܏|\K%d~Q Kb=O[eBֺyYc.yj ɞme#;R<-svM}ߨ.⺭P;d^|idtcSAFa`2Nj~/?KYMev7Jޙ3(WCkWpئP) 禹H`cŒwRK+7vP+XcJX[v%+s%ջJ52FUOpr[<ZqksCgH󫢈{Tz]>_<{P~&/6bַ$Kjq9puU$gg#sV^n~)QjJV UIvTAT$lM$92zeix|iSV==,1zӺz**M CD堲P\N ㅫObģ.J/{xmm<ֺQk<s]ۚ?ue]եnݜrYvX-"rgEeFw1c'u>9$6gd/)-f?,>]*aYR Hcs5cʌ⎥ͬM #X:;LnNn~ =TgI>tA 0ӳ~ǵ_˛0}6n:SGiѷ"kҹPO[ο48Z|͙0ǢBb(DkFצHEEuOLG_[ZOӞgl1/q24to+NrrgÉbZt} eOe己rʉ ]aG` j2q\/$;OhENlmqWҰXj3Q䗲D)5vWAINK4hs[uAmD׷8{!!8ߪ4ElaEdmkN9}Y~*v<[9:mSpYb.:5nWm<'#xH5K? HÛcxU=3{QwʪuET;vFcwCwۥuθVU!t(Äɾ+\ I']1EqXѴŸIZlIQDblܔ 6bc6r @5c1&=]C1G($0`4y)XTl`atٙpSl1n6Vt{e=?16Y<;p}ARoki63NxK fj EUMnҙiZZI#}?Ef Ie_/d@5g#VfFhq}v muu`G$f2s|?Fp[T=2Q2<55ãj`Y\dkiǷxa? 19+7?rV*sM3#x''I)n:Z.FGH!p8Y3Zf`)&Tƿ$.U!5!ˈ4$K\«W|LjԼ9="\``{/þ'\mO 9xr fMzg޴{kn辧u+Q<$JGeP 2gt8kFI(3MopO0s֞S:,K$mEGV<|#xM2(]W]-\\>CGg2yd]aԖo(jZy8 h?>.f}pU2t#g+[j-I:Op0E36B;aZPPf;+um w6:4}VX`{Ne8DOnQn=tXc58`^ksjZ8ֆ`@ Q'7.N:(>w$Eqڄ2XX\tnOnBC]Bl& <̚?%cpBfAb@co#C6Xe*ޅ: 35v8nS`<P &蘇c@&H1АB8Rj+u]MCF~q?w&t %sugsֵ#Zfu807ɺ)=kfM'N?hSBa%tF{4#iii8!=!BI8Jm> Rيf<6%r7$錫qNj9%KMr11l/8 eM_eѺNj9 |H*ٷ%Q0гe.oҲanʖ6t[,kyB"; ֟Mo>#i-0ʔgs¹TEIv:-3rpBjqmnĬz˾&`/tgf=\6݁{dvv?Ljy%dt{D8!@{ԧMy[mA뻠SŲIt|D7sqτ%mS\Dhn@7'8CRvCiQ r[&8@4vvWCa+roSsF\O̫cI$ BCLM"Fj:i*_]#/]LUZ J ܃~/)TPGV1:*sc;Y_Y-LI|q.99Evr2xLaKp>QH#-~~BeOxBq0-rnSP0f8 i6<5TRoŚ88! f[&?B.>qKQC<6Zt:zO/v@/D EvmYU>)ZGlt=nsҘ)_ IV:/ő.ȻESd෪Z|.3hZ><` q8JvGo:Ge~~>)>c =tR>YOGO.yDlo̞s{k~=]=$C8x9Rk96"ʗIOGcRrU3:5YGs XxwvsMMk"j,VԖykpݽx꫆yƋ^K04ckp\grDMD`Ing4ؖ,jEERr؅^//j* X=֯ y#kOM\TT>y\\q%}.1P[QI͹?cZ~ÞR} O~~:#A- ,aHFhi$.IYA3r1oHϷ:m8nۃWɻU9JTOi]JfPvdnpu zwUv$⤗&xĦ`0\Ќv!J)N$-жFOou]c+C8"TgL`pߪG_ /Z18[w>IF܀B6Z8Bb 4pB@mi18nfx9O쒋g|C(*#鴥iY |I#o5-[nJJN>]1Z|yw1Đ1\@ T=r'B~$\Y3>Xgrcs3\ ކ)Ϣ~8;['KF͓iI"Tp2GʚȽi١-'?%zҩhZr >ˣu݇ )X\OVIՖ1:F4ut 1iS7 dz(hf|F3ߔ5E'L" t\)c[TƓ I'Go+3ZnP'1ˇP$tZUxkp1T:Gqվy&o^Ԛ|CwPPIUaul} x\Z/LͨIJ™ĵֺjuKS'vۛ6 c';q'LiF{ԕԐQA=tqSnŭ@;\<1SݖFsOtZFK[.Cـ[mxԗ%*THܵae9k|ZfӎT>5d'&i@%z5q5*?>컾TQfgap4zƶș$'nh˳mѿ1z?Xqn}gɗ^v:y 9X@vf\`|GOEVk^rՕ<&)w+!gѥ)lZ(duL?g#p<:7|t)AWf8[_[vi~,ݤyP9_g띪 6BK w愣$gj cm߉j[ \ \x;d,P[:".ᶪhe%9n, =+S+G^(gc'k+Nx-̛9Fd5'hsG@<d $gO^*pi-KS UR@WEN5 +B L dqpkZ2G3׾6(D+ҭU)($y7U_[LF)kS#kM$/pHjd 2<ĝ2nЦ12lEWf4cjgqMO, E{mR_| ڐGM/7/zb3ϓԖ/ױͭwqo싄TKky?邋OSE*p?de@@ȫkHU;eOU\ᒌj)$nn . &n{,4r2\cEH. ` ʊ|ٵݔlvcJdI4 IGLA$+ead#+?@T'Bj9ֵ&5 rkihQw79*p{#T9., vi+ gk[UV6\ip6Q5|{"pB>d:;&iTVT2C?G5; KZm_[US3j(49|v=pFV]reWкhvk]v˕Y>i?kI?!gRW+Oq^/8SE(Hke28urwf8#=S`gƐA8@f\NKPQF8< <`s"c瞥&1@# eۀ$c$dgE+ev{|[ٿ»bG p~–*rՍGCh*?d-gY1GO&?\t|ߦD%T 7?oFt́b7`|N!L7|$F׊*gx?(/%IgRܩT=1u ;ss]-/`Hiu}5MUS=(5ޡxz&,WkOd{&|K2e ffniq|.5JdXHm7T/]:7pD%dǺ!fƗs&|6FBͬxs3MGOK.*-2p|)s#OJIj WǿT'$7HH_JM#3qؤHn=GK*j3zwRKvqS=[G[Ɗ6WEN? EJ9Wv97uX"qE}~T]dVFysMc=q.EjesJZ *ũqnLQ Z$ c0VP?M-Ζ&TS KwFX@q|D_eDUۤj*Ȝ:sދ.KܮPS6ITo:[d>~׹Gʆ%7 㳥 +CfN+MUCO[&wVI?ϧNG9z"װ=9dЏU4əp? j9, [? óNy' 117LPL|CJmf2ɀǴw,cK}P:H`8l=yC0w1>#耳F46x!8LQcc@鱩R!`Hh{K@$g8&- ,fnAr26P!ƒD3%x> ~5؍QO;{'Է}U_+#$]E$(Ӑ ؃I.ry%Qre P\vui敕#vm&ZV@ZI_)$Ь"` 0e;=?k!hiL NZpvWvԲ)~h-?UIJhӖxpx䑁ث"'PLne$g${DHJh,-MEM@H3<' T-;]D[̨HبZd- K{#N?JiE>6-;ivnq{eXneMZ+tNZm;b3}HS*5`{?$dVL# *ُ7t]QEEUl;dn@ |gh8r7v='el:sH !ā3Ӫ I"̘HXIS$쌽d3v9#]%%Tq>I%H!i .Vp WGAZ/׽csvHS)s.Ğ9i,RhC #&L\z%(n76,4&4vYct#)oV8+8fgoW}W{;* 5tw4÷ˊ_͸RTNqMȼ1⋴i]G-UGhsվ%Նk3N2ڍgi]Iaea"i@hvYbK2}AU. Sq(T#-s>,% ¼DJԶ[Hw<5d;V,!%Ed!>!]Z"쉬$x~p0$vQ}~j#^V9i’$660L>F7>Ez{#' = JB$ps@3 FӖe38a&S!)XP_@Pa<749 olzhY{0;MӋT2#^OGg eoZBX۽{/;uIWѩž nUO/ph"ZdttC8ryc?[;&Y26ۑ&kL8l@j㦊d7sFr:ߦYKvj⠹K@D)F(csA {'noJcR퉲<p.TUwdFú[M5ۜ^9 C\uSNv]i`}sh̔%YVD32 ?El\~.irkYn=DK󞤀Ix>m/rW+7udttP0l;N2\I.q>r++d\o!}FFQ3O$z. (ɉ$—_fѷos$b[oٻf7Fk,'RRvGCWUXy`Qic+CY(kI㞊~6u7LD`qAS6elѼ`0:nd*>O39kqsP_tT~>QlUj7͒m8g^\{%I> *[Y]Yu5EU$M_*9j""rg;wVO67L0侨zI)uM|wX+i`}CK kp;8\:ʣU|g.v(<46-um-:!nYZ|ٳɴ_xc\PjZZP5 L7;:g#y!,:ŖTxMswK4hx&ӕ,؛Vi]OaX%c*<̀1!Edĸ)OS1W=kNh@2wTY5>Aq%O%D( ު <&I@ V](B2ѫPC"{CgfE$Nk#?֌s*ϛ⅞YyqѱDsXf$%kUA5!`mP>lOhpt;NGCґ3RV_^֊FqM$F(3#}p?8H :[>Ƽˇ`i! 4ny8I8" mg̬adHn)! 5QM&]Ա $bmeal} ߺ[Qe~iX@G^ @gi=BNqV\88DL>00L2 "=lǻ[z9cd9Ap!y[2jacĴwNca#9$:3|plcop׹c1ʹ:f讚i#xLUmI+'YuL;]hwwc)+gZ356&SW1t 2/EvY/(XjDqϢ,K߄:>RUPh+.ɺ$gda[MdiK3#9oUqJ9P [# ;\QgTbdd|&>x%>HMs|uv2#a=G69[TǤji C(SII7-C.Uqsczndt2 :UU2ʺ۝c_$1LіGzciQJ4gNSu,es+qgSV]^قk?عG\ϠNbFy{ܒtzt9H`?=ú@6fJ,q}}5|aWd.qw?X$6I+<F}% v KtJ++➟˨oD!pc~ƦSoƗeil p\$s46ӋDUmjPYm=a 7g9K.x"f~7!"@d4w@PʤbԎN}jϹƶ.8i$ tY&HGA쵴К2j #k?3ݧyQ*t);YckCnc仓8U-Oi:֧Oi* K#yhhk0c 1"wr`*{Mu5KIsq.<c|:{d%#Rշֵ֪yTT{"qg`8U5텡r+]bj.B,5'g@A $)/;$\5 tSK$uw eSsۨ,n FwQi* uUYjqk v)d-O8XuC~<cvM*$st@oxGp#I@ }_e4G-|o,qܴ2BT4_[ݮ:|~M^6;Z-kW`# aekd#$@(lsW dTk98~z)wǡr9*i*fdN1p70\t裛$I `ȬR{kSY(p=UƌAdRE\Z6-UL06j<='4z&{,:€Ri Tʨ =Y*9vJg!vSIv #CwF1!j@яX#++&ghQ1qL"HQq5s269-nwrqQ';]+.I 5[ZGj@K\qi2en] 5.M IU%; 9ÃtpFG- ,DcsP!v8Q$c-p2dhX2Xd|ˆ| rp%KUa4l2-k^Ć9Ź$ PRT-z[HCgh2Z[49Pu"Ӣϸluw9VUF\vȭ/}C=f\#[SkF a}JX s4W4 C`@T>WaܙYllCGSuuqZWE5. 3IV(iLȚỶ9%Bɛ2m#mkj\{TJIs'ERj5%.m=E+i'rZ9(e&]m]tƢU$:y#ޝU1E)k`omCS|.h}G+dLf54u"ԑ?0$ԶJ!28㺚DMvI-0y1m1:6<.muM,uaѷ0s&#~`:͆mdCjӴ~.jwt`"B ˼Iܞpt,FSX}5Ty9FFaFPSEDhO' &%{(J1fέu['!-sG\sMcZW!HC^>\nʷznZ"$(R򅝒Fp9KdxrHtѤJhd âG!Þ=9M33YӠ^7w,q;#JW`(_MԔr\(樝 U!qp{יpF;g%hŴ朸oI]0ms6!z옌ގ.>J.0d1×O aOӰR7h ~*n~2ItPʭ9oMnk$"Po\~xŪ5.oXy06HC 2f`X?nAU *-xy(4nն:ZZ%Q$Ds\8-#)GtM(fwcp>WK;~yf1(ۤ\2`k:ޚv)pJ}Ӹ}rKSUbņIp[)[.YvntQ뎽U1# mdamKAJB4U Rv%+Ps 'a8E٘7U$#ΐRmek_xcGp;D#Zr> tr!1 ˿ȃ?#䝍2bC0 cGRN= uͫC4ad}9Fz;~Җ-#)ic`&dp+jveE:;p$1&6(E cBI aؘ@'q@'s "c\8萌2 mnk\~Qʥ e@ͪ;) O1I9%c[ʩAɐsK*UNoή \5,k9L+"eiKr3i;{bhk[N&Fdc Li;3F:+W(˒i%+-}mMttoӸap@ h˚'S]3B9&Rs 1spor$nU5Dac',B9i \a6'9#'M[  #.c) αP(bS&8)]=񞈴8V\oˤCOS$y9o#T^DHPj%6[""{D񹡎<}nH˕I;9k*J/K?k]ucTⅴXC !3ӮSQ:7cI&N~rdа278F˓*^Gܒ9<DZUΕq|&V*#HwGO'c96x2*iDkQװgÇl("QTQUvgg`ENVeˏO]~,֧L)!{dS3vd>Rbe2;g<:4LvZ*+)&5C$Ca] nVNܭfb&;%: 9Lcb9NB@&9Mq+G7 azG~H rQz R7 *姅炠k╅?ULX\[ñhCE5Oh*R)c㌌09.@NEW*vA8nVP$18NR#)'Ԧr"SD(/*({F2[*srT$o~G3NIP[@%:D8IYJ]S]&p$6UO#+dCO#'^Rܷm',MFzЕut:44#E a$)!h:(V8?J$?u=FRL& qmsG.%Kҕ 3Q1kN=F@%NhiCV Uv$(ԯ-4;7`qH*HVOťUn!.K=g[Sdm-V)(#|EzsejEcVPj4{[;civz-$7Y/b|$.loZÞo(/hй,uƾ5!o1QTܛ3YGq4#9(;7;bbDT /#jOB8 IQjm3 e&鍺5SV[ 9'=1%rE\-_1ja238Fy#e2n)Z{:Mrp<{!k#QJN8Ȱki/zʊFHdTLO.cvq>~qwE MDōk$@֌8 VLojV1Jc@ (v4֜z$C!!* $tL &}EԄƼr0&edy9P$>'êvy{Lv-OQ3(.rE3̵mMuTj\=4U&i!!=4`{+T*DT78ZPo<'HeO6`ٮMa9TXݕ((0O{ˣCm$3@$#[7HVEX8pЖEMtg*D𠀋{n4: =C%j]}TԊ+M$b( y8`W7ɩzD5x A o-tYG{-?sd k$;H 3mHڂ_[vC>~1VNѓTym=8vdd[wK]Xʩ|eNF96ᶁZ*R|:TH ^|STo(" dzI P['Y\gl2KQ$L>0sT<"Պ}D-((h|X5G:{}*|5uUuʫs1'K80 7D;T澭Ix@eiZT2fRTE7C|CnNX!|!,lpEYKK9q*UHmbn(ێq1mh:=IIАi09(mMoע OPWQ6'A7W ̯Qջsh$Ki/Wjzi+/4qTR2|>Wa~. -#I)_GXPO`yQK[,NN7``sII !׷(4HךI#ꫛ@;\]aoř˚x KslZUp_9l9y%k I$X]φԴwSMCW SkKG "eش#ܖ8cO 16( h{ahZ7b&L(SPODB@HFB@(bNP(Hr0! HH(*HE8C1f)4T{* d5|iUh1lUv~(a8<ߨ(%}<ѱƤ svF\ydS5[UUpLyc|o;>e9%-!%"1=T&,vX(Ysn*S -5}vy6 tiJ}p⯃&4'B!.$d~m%Ih8R] oD QL}GEM$t laO 3QV'eFi{m\/BcH\23t~?eNһ) 7Pifk!ps$};aˉQ=L>8ZLR0 C~2fHj %D͘715q=qOQn._hmH g݄qw7vY7Hت-̤xk`̆.Y1om:j176HǶK,.>U2~%JVc֊j GxsKZoxDSTr\ԅ<8#ESriZia81yZWBˋcTցI}|4{$:`t ImelvJat#•%F1S=cbcy (7DD.u;?)U:Li%RU(G'ypn{@eR|#h u5TW ֎d-1=c$;-pGbePV,se 5C%l]ed.%EP؇F岹' zT|1]V骭y ΘQ=M$R2R>:JO QRߴy5Dt9<ǒ}SHGx)rOteմ/WQyyܨ)7K)G/ k_MJN:Õ5lO'Тh B\lsb3 1@{& C1Hv;_Dn` I0!q@&dD{x(`jʨ©iMNʃD<4mzAIC0ΦdA3$@;3538)S++_HZNydN6b{&J02zQSRKL'`?:-|T4ˑ*W 䵛eTZƐ3Vɸ؜" ]gng*~McY)w;`01=>蚊hpvHI%H8C `LSUsK(5Ǩ29hÏl*}9-Uw֍l3ѣp^B.&y̙[/ӶGY4j?FK\06IUUBXԸ&q?ʪn7yfV׵`y9Uj?C/ZhU x),{*]%&;^Ih$AI;O8>T۲пsfH`{ih2Yĕ~;e]+V;<1N$,^Zю:K8p0=&fwLOyJ^e?ɪZho1I {`ڐh⤄SԆ=M{f`k9REsʢ] jokHLnD7p.v2ûJ=EnځYd:# k]psd[4on1G*2E2:H M®K A6Z8-e+Ϙiec\I#N*ݗ8?Q*KLTS3$9@D T81<1,N0'tԺVoc۵-"luoS'x>Sz%Rd饴5 ceYk.l 00ZfLN*Gc C00`$T! 0)@/R0 uH~HAǢQ! @!@ t@ dȌ{sʋN<Um6ӅS,MWǍ2jmM@R<8d`@?, jntMriӶKuytNd/ySdK$zAi>J^[}Dd1A $GaY.W(ZQr_H=]CH2U8'h&fT@ʩ<) 5<_|0"^Z<檒s)P". ta6wd\N]YUU;ph{=`@<n]eTyl /b74rp?eN|['ntĵUҲM`sڜsԃǯl,.zM*/X|)Q5kL Н=lO=EutUWT׻/mE$xQE E5qx o8~B;i qtі,PZc2zҗ`a[N=m&)IOpvs><籧mϲϩ0d9;KE "Gt=wIc7_O*m+8!BN , 'jPnҗiM|)cw}]Kv_,shz\L.wa#Za]JVf.u%ŲHS BIS(|Rmǰdd5JWUF 8%ȬҶio9%ǁeE};*ln i xѻ74gO)T;z~Mm< wmm}$.h& =1îFrWWD$Z.0juãM' >'nqF9ojQAϦ}Yh56|2r ծ1鐊\7T\+HeRiuElO mO"I(] Tt}n2G=:=0G}ОiiSPRPnGQRD "m5*xPS @0#P) ϲ=P2Ўo X;  `U?s\?B$cY$g=(eeE$ L@$>h9H?4@cDaEzfL;{* F$D\_r9PSk9杭/:&tO'c,\407jٟB9U;9]֎FPl,QV)yq$zeKbV:L.M9g=Pe(~ + &!}91і2HagYQifr*$=ccגXk;&V+#HkH}SfŁKT.pF~LLܨosn#=%(o$*ݞpDʓ rpЇԁ -^=;5dw/jкam'K%Dh{Aör ()=|-6_ -ZbVۮuN5uBXlc#Oc &ў#)Sg^i}a҆CO9Doshis[H渹$,MI..5G0TZjqc&uΖt9u*0ѩ5D,s9=rI'I"߱Xqgn?4O\A5QTmi)ܟE;NiX+|-x}{-S@kqb z ""C@*,`)&d9ϲT8wL/7[RP;%dlƳf{h`}Er#PPs  a 128!H3ۻ](oV DѐUQ%>m4W˹Zz[[)yD{s*'_MΙBy݄6 NmX{C\w$朌8µJ}\2ǤCkmB浻't躊n'`{G4f15]ddnoCZ#Y\F;ADDm5 !w*m.;\OLFLP}4g?! HvͩWvtSQO2#cJlBc 6E˂>χcxq6X+' ֺZ)aOx}s]-E9xsC/8S,CB*0T^}&1!o•9HÔ(m9I8 Ǫ!IC@F9c=5`P0LM k1(B{ hA@ϕ>.8贒ޚ9ٸg{4~XGMQL;=UElCD0 9!/d@`'d!CD0CHb@!DF!uk ʪHh򵺚]W1eةc^CafCK1fGM#^U:{PET㧦  xʾ2RTS%5+WK{]KrGTiEJ$EU;m@p*$aQgB@BfkEAe+AK&k y roM-z\?PdGM,8`8tq\#NN:'>Ǫ/CM Oo*mosv[U\.2)O[rcFm; xVʧfQQk٫%ehK=AxH+-cp{8RT٧s*2Oyd9sy''$r BَOvN)ls7'Kj]![B:+* #[&|EHJiiK0#rr싗आb4@I.ehh)10!&41Zv@2P4!0t CǢ(t@÷DLa!!#5feC=WkI*:=u3\Z"FsЬ:ٷO-ؗz^V*ic{ǷV (gva@tq(P&)DT4T B8C!Hc@JȌGP:~Lk%ijX deBo'að:qe\YNך2yu].uDBHI cʀr (=UX2w%*h\m(3ʪyrGqӎђoTn)u: X ~}M;^r>0LyCgQNTceTh~kq$d9K$l9,;=..yg5O5iq˜G ;%N= ;E&:)>$_a{cc0 ~Eײjg6O M[/ͤ9i)alrƹ^(6۲-T19I7HI$ēXQsMSP!&,'Mn|0ۼ>=ɉ>J"HSDX4;"ۡh[FT3#c=&8@ Ht8E *BcAQ &0c(z&4>HQlXeflzpS҇? Yy(pOF=ij=cb'ᗑjhʑ[6xdLBtJ;}Rw(o o@rQN\ $0) GBZ#PzAG9Ld6YϘ֟ߨʧ$[i'ce%ndr5N[I7ugS 8r$e EjJ?RVt61 @WORHDU}Mij}Ql*4t7c}C+$)nͥ2O3~߯TwzY%Gͤ{vο9n+kYk%_{ @;47X,rKLkq術-;,+Z3N5T6ʗb'rKTM̱ฝ?&pC<tYf9GiSRdm[A"6ݽ*C\}Bd@1{h('~P1E 0:"A@*(s 0&1;&+\,hw733mB.57?E?v'RLWsT3\dn՗)/U-'-9oȨG,¸,B$5JG=4=.]Uѕp|\9>KO7jC+)N1G"Tf-W۪c̑ _-5ٻ;$~IR1ۄ NJ@F{>I{&b :f[Iph5ALL|4(ʊ6m!'8 GX^"*q ovVMI[(T}Cd$^h8u;6q68Cg$=E-|M^v&jY+ZT t夸|N~}2@Y2=\x*ڢ[* nz`zr%7@HcKOʿt: nqi=C4~sX&3iԏP,U6b:i"<5 >v1Ry\rD5QN4wp;9 RoTQDLa  e4 y`&;a18@={&z&v@@ & w@&!p4'S.'lm<F+tRP%U6X%308V%rP|}7sZnɡv=BiNΞ)nدͧjin xGl&%7\v:XLn]>?}bɞqwu 1cɗĿ'D,XaqTs$zo'O+< RH6{E~M%^oV= $ihj5ǧW-q=cj\J'{.=pu!0LPT^LBbc R&(I#TWۧT%@xĭ4Ơ6L4M$9fym#4քڢa HxL=SR@Bp$`!t<dt)rJ`@ yNa@o2ѺS1 SeGjCh6;4G\,#f9 ^.[I 9,ݕܙ9^ciIZ"n4mh^I^Ib<̪%|{ew1X#OQ,ƵǡE*J-KCuuHb&3V $@v쓈#^Amד62RTs8tdqu⳥Oa\ͨtŷ-VcUL7?L*1e Z-{r*%爆1L gF@ϲQ Cr6APSy&@(@NHˆ!rH] tenۇ#J?QFwITtoakq cET^*W^<34D[B£I$p`B[10nԡ|02"uG4:\t\   8@ 8H/@('@8|9_bBۭ=\f ߒ6i%8QE#[5Gqi2&ƾɏTB8A>E/;Q]WnO$gsb"GT3IOZ5 4dchL.>э nf=L"@@Q@( y t@S:?$D)P;Bc@&1@ MC) E'\Rj{Z觝J>[}_cu G3]4 ND]I2|mv#gWb3dŔx94B ׁدSȳA;R*Iy,i(Ž `%)`fu{uMd e~:|i&2T)Pem*!s?Lfaի(2i掓;C`ה)~O@OB,7ۖX؍ ^(CrPPTP |^ ={L(q e-yELïf %.+OtɁF0`,rMq#5V}qciS;0nۅdROES=PE*8~CO[9kd/LGjf.Դ8\{7<vv)KtEk[Z7}Kr{r-=OhKКj0yM}Jx0y)2ʡE8ܤBRO++/H|ovY 7*-YĴ0V3QԲFSR],n/lΣi#)3!f%D,GG#Z 7e?WL!<]8[^!z+s6w|G<4>7{<2x{X]yOB zu=vx!xO?K@zL g;"@o?B@D@ ^#la/D \e&R8@=PB@(Έ)r8@ 0?T: @ u@AL4 LB} ^2AMSCƅ*0#@d/.;%Q%/Fz:Zny :6d;\OO6*l(,5IOy]6O}N=o$XFÿ^7U+<ߔΉ91Y՚#R1Dch.Š<4[*>ŭխvd3ծrezSoMČ r|,)QCI[_KS#\5K_9U/B)t,L!?*)ȸ&zu3U#l يP:%hdk"\bl갷T8+ORWbyURȗlm7-F6gǗ\ɮV_}D;.6l+Q= USt.s[Y;GOxsr#mD !4=`**T OT\*xHbx.}ת  ^Nɀa !Lh8@ b*4b@e:RrPB&tL0T?$NΪ(4;.nԮ>z%Fso5vꪚZY6Fp=%zgKPJ淂&U*lF]r9t!Lۃ_Hդsq꺚VQԥ4p ՒM. ЊohLټܬ˲&D%p f>YG3o+Ͱ:߄ JASCIIO08B00AFK01R98 @($ HHJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?/xNŚ2b? ׅiItu̜yo< zt^-v6!6܉&Y*L|IE}œ5E+9i==zbjf3ƾ:>VffvAF?KY&b|t>'@8B3)M4ȬAsRcr:Qr!@)!#uG"G\#HbmE~n=i\o8F_?{TbQ zpj~!~a߽6YSot1w6>Q>5@Q(z|#*AA։w'== "*`5Y/1Z3~tDkק0H<Ϲ֝OLAFzƗ_p7[he>%4>L;ZLz|ʧoΝx?E:9T=sPzmB?iosנ~+x V4|˯q_<5O?1FJjvGjhz+u l幕@ߨk#nJ GVo-)bvwßnt)4l篯oKG1T*-Ԍsڣ@7jnI)GCC)?v3tL@Jbc-`v$p$b҆aD]_jVDJ,g1ҙy֛'OI+`tc]tu΍@d^CޒM[p?:C*yxpeRU9T|+:6;iWXJ :Un7v IjtB8jWkC`a#^ztZ_%l +7N9$ Rb;|үRِ7"0znz߈)O k3#}q>{ɚ\O ~0Tï+۾AZ`5/,y}= р:Jl[p:zL}I,ј *n!Yci0x^,dD w4^ $[dCLiWSƛ,^\ >ᨔzJ<k*~O/JKʢyFW4Q7iE/07/Y@pߑy{QrKg/TSJ mt44zʁMx:hPdn[D^[FdQO(=[F>f{[Itʆ#!n5z8O}M{a /enrk?xb~$pZV- _qMkI[̑d~ҡ7ZNa+u ,u91\M ADx'/<%k7=Y3-TK0,;8!9JlzTQOF%{.UAF_4Ox9W2sFy7CM0"cz1Q(1/~uFxP1?ާC,`2r{ҘAHOG餎*9=OQ ysOsL/RD{&0c|۽#\}j59S^x˧:Jd3:ΣF)px<{O?:bO23Ho5U;k񷆢6%|5щ\zdңm">I5qZͽ>\YT<`uj oA`ז A^KiwZkO"-,t{;dV( uQ _Kqν&?j^M&MRo^p37voZgD 0ʡpF}y:|כ_ӥGk][ ưnĽUinifw8F; T1&`',d 󾅪8ŋ^BˏraCcZ<;McͦEG$ G͆ B31#nFy}+Z:ӑb]J7" 8$n]j5ڬṔN#ޠ{օkUK sJV&uYľf# V'' ȭ#dпr.{5Ax{N7&s@"&HncrsgzVn{kCnKq@P2$v@eCH?L΃U~ riz3օmq=>r01 ykQc3o=B̹bU+| տm.B%n=sڳN=/OC8JvނS)_5֯q+XO Q7CAHy~ϫ~GS6v= >^ǽ$r/~tg#QS 7"f I]Y ?:i 5:L5UW@@AwDҺW'NwsqmhW?<Ϩ>pdv2zķ\% e9Y*:xeV9]"lABW)%VRKxɁ{rOp׺wƥCTanKzvիinS̸@"!Ubqgl-P`WC \7,S3HA ONԒa#E62^>KY|/t=-o^)cׯYWAs-ckۘC%* ,={sѤOݷ֓O6'pL935oZ<W*+2*<Ĵvf)7TrSRg Ȥ;?շSC)bl5%L{)2+?dց5Ah^Jf[ZE~~ҘVA]M~sG+ĵ95{٢^g?JoJV6q9'4wutƌ]UO]|4VqGq_h>\AK,g?2xt\ޑd $r2:uֵ܏4QI3ѱiP"IϯE5̗N@SxKUV)8asKy~Z7بTE ?<92"d4Qi#-hCGz{?ۮZY;>՚YgfW=Ze9n!^yw9A4в[LPqW[RH#Hgk q#\t1K< tx;eU=۞kqamm,]K[*c yH]a]q\f`8fRH q*gV_-p< zZv=Ҧ{t,z\}9<ڛv3.;w!PJA̯ @89AG0ɑ R$ Q-ؒ*é?E FlCjNEI>s }fV"[YExAFdQdE|}sTl<2I2 Ek{X hY%ˇA)݀'?u?&Hn4o!bw(Nxk$c\ Zu_Eo)_?翭O!t; im{,ǖ5Hï4u] gqK"':{ˏS6/Wjb(!ǩI9)!}=jWA^ Ɛ7CCDgnDS/G7Aia FQ#tgkTZJ!~át"&%,R#ϔ#u5=1!mϘ3jڣͱ-p ^xXJ3yJs(ڄ)y>kYީX.-YЭ) :Kn`A:dO=֡kKx)BQgd ǸTϹE0 |ǰR{[woydlo@9ȢkH`??jD5m3;S# oonz;K\4J_Dn}{XmZƧCcӱ5DLIXU;1wc^5=qX.Ai3SknVM׾#;.8p?uVV ڥH0SHZDE 欉r2. x^'?~hމ&:_c@17vOʙ<_ΣS2{#?'4c5]֨ rx觸IK[ҭ8Z9x#nVRzjK;t gЈjއ*pUJJw{'HkZny@54lbْ=EI[&eT[wg~v=M~bȎYKr%bù8bmi.o%3(S*[6Y]/H|3;Zx*L጗e~y)F|(ݷ^S]K$OH"o jFdn݅EUe`x:UeF?xO;ZAP; I(8aDLοx 1)^`],tG#ybexnv󎙤FN޴nqRJv=1Sv}*Rx $-2>~rSwR$?nֳu(KSm*8'%Xv?OQZqcax3Mp<Bh}gOVi 6g-O__nִO^xT@lgg8z޳;Zװh6(@ QvhhyckViAz"qŻ*J_i2_&M*~}izw?$p?ILd1M/{ Y%;7 "#tAK)Θ:g`Y`1TQ':QLCv!?"" >)'24\R^{֔ĸ/EGjc1}Gڊ)v[4آSh =f$>ca:n$v$r:ֆQ@, Ή lEJT}OE http://ns.adobe.com/xap/1.0/ 3264 2448 SAMSUNG GT-I9105P Top-left 72 72 Inch I9105PXXUBNB1 2014:05:05 22:53:26 Centred 320 240 JPEG compression Top-left 72 72 Inch 1/50 sec. f/2.6 Aperture priority 80 Exif Version 2.2 2014:05:05 22:53:26 2014:05:05 22:53:26 Y Cb Cr - 5.64 EV (1/50 sec.) 2.81 EV (f/2.6) 2.48 EV (19.12 cd/m^2) 0.00 EV 2.81 EV (f/2.6) Centre-weighted average 4.0 mm 202 bytes undefined data FlashPix Version 1.0 sRGB 3264 2448 Directly photographed Auto exposure Auto white balance 1 Standard Normal Normal O08B00AFK01 R98 C  !"$"$CA K!1AQ"aq#2B$3Rbr4CS%cs5DT4!1AQ"aq2B#3R ?)i j#<6St*iqϡ5vvLSkvԅ!D)*WOѶ 8Z}Bv|OZ7j? 2B-\4Gpɴ >N=ݑk5`}y=x|#Y:sW51<V'TGEfe5 -DuDA|@Y#'ݧTC! j(d}VYbG]j I,sk .i"+Vd-!n: z ;45QQkAM`֌ M1dUۂba?օٿAgh#btP$~#L?L FFM$1Yd 㫆a|1C1Pa1aGm)i̡PD1N.G?R LV$k 4>rS$ ,ԂLM#DN.G e<@kkg" *B2(h?stؕY..䏔ow)P))5ٳ(m/ q 3u>H{:'WI챌6SÌîӝihJPz8?~#q_kSN6A5եt}}18K՚x;tl}~uL8ViV>j"#*$$F馵5wY !YlQ8T 6fIދ!SP@wdƁA*PNҢk +?JdNYKAU4vp9PPMdL'A%Qݪy**ڧ;wX>/bւƾuYc Sphc@v $Nf-h+0?I+V!dCDFԧj[v$< kBb ]Ժ,A}oڤU1 IISï-ҧH.nRzQbQVs˜5mCUeB c_ x:=f ??3Z4"4_?f^^h }S(Z'UųIt~t6T#k-ݝӨC@}ˉGwt˄Zu]ߴ~t .#GIRdū?:h§wtHh!WOF\ͪƿ**G$$Zu9VTf?FT6*F Mkil@~u"&a>cqVnYqdlYqL>:Оod*W&n7BR%fQnij^'{Tcxr~̭vy/gMێ5RLeOU~wÙMKfK_.9_I-uuqbF_(7|FA7z\JI(|4}M eqqi~v˂G٫Fmf'Zj8QT jc4[49A3ֲѤŲOmZ&r6Jv͞Օϩ&L ۓ%5P[lLUElCemEɂ\Z3ߘ9§]٤lΙ>h9 ܙkU){Jē1λGWhɟ4fƋ6 6̙'Th߻HMfj'VRgՁdmHѴ ewq <#oAfݩZ~L7#q$!?e `z\E^T#L7A L[Hա%;  .\IyV} #JOJ1 @T@v OiqAjL"j"7F.p?¤iIPDn@x} eI)27(Jw֡#sc'J }|^6?*؄+iBNB dR|v/`&Mu9jF~7bd9Ӎ%YAoX1ʴσ}p=co#=Q(Tn+P$uh8}.qƖ(ȲF$1Z-+tY1hi>gVA.i:Jv4b/Xw!Gzs1]OiRB @ @o=pRmR(@A)?:Ēf;`ؖx囩8sZvyޙg5X`d |e N?dPLT姭D4CAQ^~ߜ,T('P4jb1Q.N EiҳנM:֌$EI*iSG_evi(qZ0&֢H&6ESk>>HsS$5GMB dO{b„/ʶdEd9B4~h#_AzHLD5@QX)vs.AYBHN r#z]?aQ pInAAAIړ'bEBcӯ^ņi?Z@CӥBF@vyq TUlaf HF$-٧Qu6Cn"Πd6@J'G"<7Jpx3nFH:TD%jo֗Y!+V$'һO^[?o۸r(JO__:ĮE鏩֔\p%`悠 Aә ޏ7R˿-8{*!0d]`qJ%p)\kV}{ixWXk`jcXqݡ䩟V-\5rm%h=BY$*ʒ!E y@Y:ED1cI7Lh'JFH$H41hE&FkB1(oev/ݼ3BɍFRB+5 ?ֲ4 I8BZ1P:Lҁ?֒Ľq|XY )΢!Y bHrusP *' *&"s] Kn5 ޴d铭1{T@vw¥٦ FNQԈS&D \IP:*/fH+NFUڢDJRb9@V ƚ?ujP HP Q:Mr"RAa^_}@l;vN])5 }s-=~,[MVnq/cDͰ 6Ju9RJ?*f~scAut}V,TeXWS\k4JHϖvͭ+8"-YmAE]զӐEe/ VBECD&sjpE6,&:T~=χ]w mIit2N.GƮZ*$gc.n jV+ H,>Ȃ6(NV5)'O򚬨ޚ'7=2tDD¾@aC\DK4YQOXG}'!fjޑaq 9Wh (mM6qDL*l޸V2i^ B5XP~񚬨E_IؽVTktrzHL(L M)* T7诎Ϋ*9WNk;9~tXP-åGsE $t٦M+UB!;{Vʐz)_V@._:1XR1:ڐ&?E ?UƢ `nCk1B$eC}5B jh˽v!*hڤ.;8B4/@_z(0uuU-nMaB|^!uH+zCC;+w,TVSoTZwkᓗz=})ν U#NL)Hm[x̿/&&JނO;+@3~O'*89{Dհg(Y:ۗUt"6^F@rClPh܉Y1 H]۱slƝIC#E$ >;kvuuF"YtA)NnKz#q[29Hg1&fIYjirրH𶃫B2@$+#!/9z[ʹ3t+2ݻP$@k[[pܔ) fGܟo0KF^ɵ6NU.i"33[nG`JRvHִ`edB"s!lf£egٯA(Rda4"c:gٯA*@*#R֢c[4 ~&ADmZkQgAQY{q _ADr-(N=BD7G7ڢ:jƐ3A@@q)"% dkss +@$5gR Ubg"O4J:LV$B f MB gWZ'٧ ZL~jF 64JH{A@րnh!>ʈ )3L4z *ΐ36C:Q:Z:|>z ;dْPކ(h?A#P:E(dg}`GAUW Pk,]3gF}q]wnxT)P0GzXv(e#"w".^,ӘevLYiք|- %{$ #ki&gK2\flP djg3 ]Hxu ek48I~g= _\[HpDI5Ūtsj=q$E'!3f$ =*# "'!V=G 58< VBsb P"2 >uc!B9 @`CTdkAڟӞ'Իa:H 4*!%=Β"!ACTAMD dpB&~B cnoTTGNd,;q?aZH Qr1RimDk9F%nscsv84mҡ ~S2)P:5X8g!ޏfS&N**bβ Ac&doH 'X?e5fD jO{|B`!Gxi!@=* KTu(LQ}D6t1VHj"j kM\oAB t*zjI.\iP0n)!b CU5??ذz 5hD]5{iR})2&m4FuP NY*FSB+$1d41I&Ǯ{6 J=*F5&#QT@+1F-h70gҴ *vLDR.B|)PZ i4jÆGv=Euq֛eͺu1H!s,* ;)t;*\GY*YJ3[|iZ\awhlᑠҳ%figX{>ۮ?X zLR3#2mJeV-]KEA@uބG`xʓlhaN LV$4GDFLr_:j 8D0yVH"?6L'EVB*cmh ;zvґaJ#HlAQ[} @5X n[CSH_ji}9fFUՍ;Ub2HΞ h$`j*zQ '& #DPmt$TDǕ&NjuG| r#3Q @F~Uٞ`Kƺ|"Dƿ pD!5SpȈ:,Ri2FRA3={0xWWvHPr2+)C qqyOZNI0kddh(P =MhVzJIPyiXO\pTJK JR 1ZkָLv@fհ͂ZK/6u(fYa&frC}ʣ!2 24*]3QwzctⴶQ?wȚ8nіI;3# kpMӰ˭e 0 ץ@t TT@ֆI3$vQU!I b9ńfhI2MD>*GjHLPֈu0&#5ή@!:Q R,W/\*) ʉDoD=}>UQ2??w{4 TkJ#<S?ft+69f'H;ֈa<rT/H~U3k:41֢=l4sshfi2mut nHMbo@%NcgٯA0$E&N3c u%i}Hgk%&'vJpܭoܰB4HޜSI;$䏛q)VJ;b 9vNoX2HVU2ҨruNr#nn;Kݴ6 ϋ]}nظBCPi ]& I3/*`7H@{*BP!E?n}bu?=`t@M5aKi= s-Ȕ(I:6'Od;krwAC*'c^LG[RqH ᗎ++'\g $gT :3(x45%&#>XZ 󠆫2}* K: Ҳf*l zZSK x}&2G_sNqS`<:X p T`O(  4z!ΦpW_֚ 0Ѣ~@@BvD b'X­ɁP YDPڸs$n Pu)1jwj̟Yh Oq]ulsj6QM_o}ELBcB?(8p#?Xum-v45W,4ƋHj7IP-xފ#iUKAf?ZЊjIQU UQ!OLP"Y= F$ltD](-иS9@~g2:j=frZZn pgvkT{̈&t0'Z#Y(s(viQE?rGf$N,$}8OXa]'X~un&՗ĬܹfJTr 4VQ$Lk-4Iz+p[*ԑ4j \/)ZsRs tmjh6,(- JTD<=+=YuCSySf@R#_9r>U>l=Գ0R4 ;$:hbyt=y򮰖F.mE LA56}9Ŷp!8 嶸w{ԁ?'yF]ʛ cftEf{rNa$ 6 Z OJ@%?#A p\*q5%n>=IN(J.TI.tTZ#Z/ ehͫq2B%zkG(h-osG{Rr*#h[ܕJՠZ!tRnîjDR2.nRYQL$"Y/|UC`,"s aYh 5\6jeçhmY:a@4Jɦ['j ڰ樭M I[h "D}{4ސRlҩ;[HEl^ٴ}!a wHiROC6 SMiDRf#@4@izݶ%DK{v.Q?h2+̇c'qG$G 4kuFQjvi/Q+C)\Dͳ)TeDAИ]UTDK8S ur7um1 Ku{< )A-WL`uOJeH@ˆ_TuSPL#H::L0zݠ \JR3+ h*ٻy^iahq J6 ֻ1>}71qk=j /@!uYUp,(i|"7H?M I$΁c]5ԗR5 1K\| J,Aӣ_֪2 $$u4=jB1oU-9;M#PI^rjy"WGMJ =fFԀ| 6Eɏv?C54ʴLH֡mX=݀oQ wR`}k1+fG`ו0ZEbm:k, Δ yTfQנ)2r2j!$sSֲ74L&Z'ZHb Y xM:jk6kфY>5l=`֢t~yOZ]mpҚ}-*R`:~Άho\_RR$i\أJ 8JZ˙HH:tg!AwvJNT3PС)NM`ڵDR &?kHKL\>yQmm{)l+rŧ-Jd{B'9Vj7V9_bZ )ZeYB3ihf ^®Bx08cp fnܵp8Ө:ӝOz}'%.V L"'\hT:j9W.JBfAT`iPDF9N҆@f\FDEk@4Ң#wTO@Z/ L:b uJ~kP,/TnH*$>ȪuK'7g+ _ʺEb 3X))C('Dm:`֌uve'B6>bEڳϴ\K5Y4TժRl$lv Q8 }WZ#uXCƆZ0%CXATHKMX` UUTI( l)I-u[Ѕ)@Tt$D:$c*2 .HPC0m1̱'_*&FWIjN0:mM`1$%˓~YFP^4PVI +O2iX*$Jc_*I}|VGU gMT)*cUtP=qV(x3kJ +/jՀTA!*$IκG`{3!,(KIq3I =؝ʵEkjމ,-\,, q@| adewZK:wq.G*@+Bv\wG:FUG[pu$] TV1vMLʧs@ af{t Ё4#M $ynkTgm؃iV"ʆ%{(#AH\;PK-AlCehߚE-&"?tP#v_l؏iV9GSAlE[[v ٜG(}6ؐLzPi=3 $J@jAi'Ȋ#,4# yEe#V]Gj9Aّ'i&%E%gwVAtb4c F94PaѤ`u0BI 5iFD֌Tt"s A,ImVPApc^UIDn *:iB&4ε`1 C71<(m#7?{2+7|R+mnZSnCPA]MxOZF$w#bq)WJԗqdJ3mcO.7 )J= sh$\A[[I$FkJ_&Y[sy|m۲[V-,ևTTgCkJ+6Ina4ҙJCTaZ9K؍;M2HHH:ǜr"VA%`hը4fQIwLGekBݵCrFp/-\'$ڏuؚ5gnk0nQE @RdO@עhdԯ2 MFD>TR1L~4#R #mkHA=jl)D @.͸yvhaDǥ(Ll؂4Ê :v<sJyzRDjQ$@v.ܧ4@!2?:HbIj V9Cn7ˬ"(U[vWj :@bҁ#Q7iKUo&l6 J2I;gkΡTsAEOKFQ@ma29tǘIUh OlEhȇS#H@X|`!Zj3"Èq 5"`N@ h:ʒG-tNwu/YRJ.>K|u/L%ב ^]|3+*sAQ I{irgK40O\"/HN~=k) O;yq(/ق)H+w1'<ϝoTe-)b)+LFfYw^" @HBzs M˩XqeN!'Ġd3zMU !uw&/?O/1]"̕*Ҭ,'6{cG5¼@ƭ z`^!#cNח$L{~u(Kk գ(I3| چ JF:Ԇ]'M2!D/sPl- 0uΨ#AI,$n dnt.+ 'J)IIbCLd@.Iͮ֒9FtF<@Y6ZF$ 9 ,] N:AFi#`5ZkusR5}iK`pXTY YYب._VPʩ(dF :;ІA$Dl-)"7r'R:YS pk;[qJд(h ?gž8Е.Wnnlkي|3+Άt1[{5X"HO5Cel5%'X3??Z! ?R CNz?h P`\0IA* SfGE~5370Il$@kj&h P"H%KP RPi!8 7T jegք,%K3&*#}IMLJ{|dJ\HVւK@c@V yu~Y0Ժl OZl.j } ]I[΋ٿAA }1«*n&4V!ld Xt%r:5 *;`F)LoQ=O(b\/hV;«$*Ub 'B^lQȾGQ>| iM3 /ї%h(pۼM b/mTrP)Gju\VF r8BPu#(EUKߴ4c H_+f:W 65g4jF"JZRBdӧftS:$"'\ȤfJuΕvFb+cBBꙆ_b!vrd€:8!]AR%D=p?\vP˃m^` ӣ/FXt7wjЯY,'`MeP:L)VK?MCS`3],JF7rH؃jP29M<y?XD1=颰l6*ae.:@ldn!cE'CdNؠ+wdCd}ejQ6& W]i!5U>e"h#E­#tP>Ԉ-OPIHgEI&rA "=*՝ŖC@4oAЏڋci?iklGDՁ[T!SޡL+u-"ze -TXd~" JY0BE5,ժlelCen4 54IL[_R+`#&2ŻUd>=6 Q 5 TȨ#* q\Bm)3ւ#r 6=Ԝ+W?:˰F@Og.I%j?yb4J >vҞ=boHG*,>Z)Rv x;Of fQVkֽU H=zuw5ƨvNmef;GM(!q TF-dDJ J[jZ ́'Nf~M\Ft zDHjP LOO3|Mj][m%+rdv3L+qJ?* _:v^HSA:%I#+ϙ{}l€):WJLM@f6iZeim 3AQ>aD0ipIZz,;&SB:5_BÉ&*"}*+!~"A1՘?%Pi(yVaP#\O{QQ'8Ӧ.ŖrրL]j!'*hcr5穠}# qөb)#yR>$3~h0A:̝hzPڛ$t?{ĝ}jl,ҙQULھ"P .YZVP3XdysCAej3?}HdBFʚ@I3AJ j+ZX $ DEpBZ&~t @I:Z˰ʐ&!$gAC" 3/qlB9Ζd,SunHeG?7­/Wa}4wÑnK dFcᗅt`4hӀԇ$63sD.sv\G[۸ZD`G9*5lQ1XVkn7ż^n+g]Cvx}eJ8QjO8N1O"Y2mq~θwCa6{z ڭJʆr@DƠbt=ز97g]jdyWK=I2 TA=j*< C imFN:diP?.´Kmښ0"cA p5 'ܐ>(Fx4R $"Iޤ%{$}*1'Y2 8jr?N_ HE-IOT6)Ϊ+ĐLLykS5X >tgΡ ˓'lu.k^ފJ~;DlB(#u@'je9/u8Q I BEp !ԑ`֧TBc.ŠNZ\N'D.Oʫ",=imwB'. </*Hچ(q)<ۭ%i -h|OWr* ,P릜{1J.=}n).*>!Jģ/guJPH&bj͂΄m Oz;Q.=xJƽВsz3l+CA0wK$[==G@"BV8 fj3][HJD'z![iNc ХfxyOO<[mәEeLI5y θ >p*; 4\'+w{De$kSÓ$9ɳ}; kn炤% )`t'X8e9G\;Kx=KJem \}r (đG,e'|ܾ,l{M0\노X (C==#hP9MA&վ,ב:y+xOOil+`wKN)hBWtؐNT1%Gs& S 'N_>7CM{>J⋬F^R}܂R)OjL6gM1ߺt_bRlV &/oc1x}+qFC 3%I0A "5= ViŊ`O<(HJ~7F*TV [0Eބu3I"ك?UۘObf؝ ?Sǘd%@2~dkM4|".^/+*'x5՜bX@d~Pɉ`h@؃[,< WgXܙD%'QF*(YWCβ=b@dld @!:T@-FM gX6LSP'0Pj'B$ \tYb+Sjp|RV(nŰ5% uSqmR L^ս2 IFMTDu3(rj&Zm/%EjɴT(< I٪=_qlOUk (q@n y2yuIiG6Mvs 1n!J[;x۷g&œI8e)ØC79.mehI#Q_*A`>DZN2|xKÑkwgdyD%ԑW<˄2N._;-+s|aL?qN'iyOZ' /7r.քJ:*󉯣LpN!kuâJI'$5&MC ~ɯfgq9L;`}IXs*HPA*:hu־_|6%y-8wV^+Fx:ͻM!7k!9 Ț19/>TtzW pY].\\E!lK)IlB5su(S}'øŮ5"CSnT q&ڣL:, ӥ$Cpo]j4&փAB)$ `DoPu6(zT,:FSQ?\~!ayHhiP :zP 6?J ojAQ+H.JE%J !6&6HySd(I&gQHdƕ=|X}]p[ Bf:PЦ|W*]V J`,m|ُa|3h ^{$l^@E9:ͣwI:ĝlMg!~ݦ̪`06%gl+b9\g%{>iσ1|a.c/7+LFzfߦQx3eT3!v8u^YI:k^wwW8KI#ևf[`gj ?~a>&O25QyVzl&*̤ڸ/0 gicׄVM=^)Y%/U0;󯧏'%gpi\2} B96)" e%[L͵iŸ/1e6ͳ7wk[yԨI w2@O2(m#˙7fdX? 8^b-{ZضV0dJu3ץ|xGc<^}gЏU^}/;-Pj3$<Bu>l~vHuJl ΡfhۮVDzV9;C! 錣Ufi[\O*TMӮhb:S[CMX5UB417'A;QTލEl&Ģ ;R`n(`r51C` c [ ~U[֢8$PȦQ$>4i1K͡LkU#/)3@[n-y"rnmSwĖKp&l7;;PMݒU+KQr055=`𾴰.QujuD҄r q@tJe mtQ%NR?{tW qbJPEŒ[HB9Wť-aok[\yX%(i  »Grf\O=='[[lPjC6C3V@Aɕsҽ.VE7gp0[@C/:[PgSmJ8Eqˌ2(ñ7)a7Vd@ĎEp ~^ coRMe"k{mՇ!pG0÷X9RV|k5㏓JT}Qq|S]%ɀ&nʃ'X*3+J!z~w<}܍ qVXrCx2.RqJ!!LBN\זӨ9GzgОŸ+l3Ɯ8em% iBԠI) J@םNV.:=夠l ZW/3B7{ $4"d~uY-~,RyQHY36VF"@ q-?tVe%cYAR84EV(RE%{KˌwIhkCTLTG)fEDqu:!Z o-T?Ayuˈ#AWcBN0Ze :32{'iI>GvfO)(u(U(hn#6TGfa[Zhhk1;p-$)iljweUH91Gr`mCP4 Vm!LEZ3l!U&!v)m-ų bBCXmm$RLZ?mf8xQPr,-l1l9@iґ9{ īNYT8{ s RCe6&>gle69Xm3.+󡅲!Y.GG{5RH'N)*=% (Ni^y9X'b8 ո8VQhRN$ΚT%W^ w"WkfFnȱ;+]/,EfV-m}ˎ(JFbIȂ|Yz&+d;en#qW pᕐyIuixhn[k72ڟWkX[)NxǔFqx+ .D v. #N(HS&6&fjף JV`ٔҶ3O_*ZٖyM֝)%PU+TLkF% 5]w~ϱq y=+* m ?D'ſ=4q?Mcu}T1)f;7v/_0cf{C7\MAP * C&A3.L>0Vϗxą;{ vWp %%(ZH'i׏(.y{6~—)xF%vxݲrb';m0I XTlqGҒ$bZüMcsax~bzٕ!g!*RBT7H $M}/36wUxn?<=e\VVm>S4h]aPy_j<cvMnDۺ%GZOM#ϱL}](Im!Ê;3C$ɑăl7 yLZ.a ! @N6a=3 w m٨d[^JA50Jԙ$lqJ*ðnםBH VrČEP ,|BZؙGz';`6OfpǗvݫm뛧@%J$Lc\:Vrxǭ1KU%-:YyS}2R #I'JrF}[ Z1`XĚolIJs($` kXjI:LaOb%| l Z!~\p›m${3?yb`|IkۆUd]BJR<$H_?C_46n=_b/v~cڭ]mJA[;eGD7:WOaig|!8w-:TjD~Gp=)l`Mv&GfT/ҡO*nbDPC')qʒO? >`X Q i-HCJf_gC o0'jOE@8Ң&uQ[HK0r^A5RyA@X|io4T: 97 V+5Hb\9KPt+YزNc1An]1mjmZARZR'@(0xm;n`Vn@cki#yc7/ص{ gm]\FDϺI+5s=Gg4. ~vo GdFĝIIS<>'-[à$ NT,\6Ta{q7Ze HI! ]9M[:ۚ,GE-v靇324RLn+JI3QGCpB@ z֩3Q3U$MlfgofXzY dUz =?1a d ܼn_Q2I̔9l@OYe ZjawUY9ljAQd)MtIk38s8fbwe+%”4ͬED2IeR[¼!yb.YaJ>LVga4+fw'GgCβUo>^]IBVtfH39#H.).[7kC۬fE&S:5"SVqE)lo&+ԭ8sˡl$vҽ|vyܤZ\Xܽovӌ?nm0^VꏑÑGp_GbƸ7ux_liiY2J`F |Z( *BbMD|mPb: i&wi&zJ \Dڡ$X¢$ڡCUҡ+=Č[ZK{e "{@f)ahcUά}(6*'ET<#Y4ВG>Sa0{!3U}$c]iƜ:;$ĬmЂy)j52j<ϣٝ@?j'іW(7/ZJL `Tgq+K@; 9e[2&{$D,.f-^bNյk&da ܓFT&)YTU WD7 1;FݚY O:*BN&y[+)y Ty|T!DApǝ!b CENꠀajH/j@H 6E@ot|5g ,E`v\ێDgj4a=5G$6);j`؍jp2m%Kkhn.HhsFĺO3΢ B`?J+F":Fٵh8BVz 4mo7,hA.{ktÊe:=)9΂85]x&V@6.b6Ugv1ʂ+Ur'Nh9k,)0'zE@5P: IJH]Nγ#Q N=+V`]Ƶ/8Rp- ^KMa\ؕ,HDNW4n!qx#v4˩p/O첓!hAB~Q=!ˊrwN^ueN82I5; %’vc҆*(J3BUN#ʅvL+JNV̑TT!z-1y 1Ӊ ] jʧgi J=2*ݰEqb >۰v@OdrOG+Hʓ~\ chnl.VR`$ RX#@@fw}S"*=^֭]^1%pO qk}!˅";*-F~ʼ+_nSon1˧a,yS%$:T%JS*z Wx?$#g~x8|9ŪeKm܅9۠|.Pk;uL,C./_d" ~}jHcB @0n JPĞI"+-qF|EVҠ'z!T ]zGy(+dQZHYZMP& Osx!)ʤ,'Zi3I DRE9̛#h(fѶ{[} I?uv8.pW*LH'QAc_ 󯈟KFYI;{n58kq0f:A1@i.a!$֣G$-?f݅1絷a_%O Q*x>ڭn[} ,Y3.|){4s=E#&6lmSm,XQiJĀPivՕ%IʉO?_Zڊ@d)tdR3,8]Uسia=uszC)ZS)J]4֪ղJ-}VsՖ?bXaW R.[n!!!9nDvrKѸ431,mJBַhj)P^lJE$a5N>6#R흳{:_JanGT+]GH*8JS>N/+'K,T55R ;u6U}ucm/14ne{]pZGJ$IX#\ɴ?IKXթESr^URe^JkROrc,=6Ys򼯢qN/7.5Rﴌ~q,\]/[ ө2uKpVIvSǗ͛#pp5i7>\ZRK* !_Iҷ/.-NѤ8puXJ0@ZiOv-'ZԢRV9o(KʞϤ}+E¬?ۋ%l;$ic67:C -0; ?sYZۥ(8ML ʔ${.}b-6wN\&nHN|o n)S_'. M bLܻqm ,%FcmnI˂gZ"K9rcg)!z[f 6.aׇJytѾY^͟OF`_{y }׋lIΥx $ d@+H"N$) "i_y>2)й#AcƸ c~ŋf6h!}N<98@7I0Px:ݥ; yB<%e&#÷-I˭-l\2 jIV ~ںωxZ\,EܰUn+K݃RD|J]vhnVPQ؎ۛp%NeMiaN)nqĶe D8VQDJ0,QYaNK`{2 dC;7'Sin].͗ !*&@?u'7 iWW *Rz "lFomA)u!w ZJYsEځNDoPEv.[K!,*`1IXPɪ'a1^bv6InLbbs6; 8!Zq.2{arKũR'M 3o)A[8oq{joYE_5$|;9֥?GkvjobgV[W{ВK6FXh#ƩL׍oq'"d`o^7fյ ֢d:>Ƽ" G qAvZín:)Мec~UyH|lx~ `1 퓇;[!ATZzI:VH K}Rofu@qRFUi^D{,: &E`6HP#]=+F-VOJO<?2ǟZ01S; ('æY'PͧgBIDRd AlMrȟ1GRs28 ! [0:d@ ;žgc7 cax>N'^xSRFώvXŮrqʙeҒ+#U&|3"4$⠶xq*գ77엠֢G ^fԛtwGAhP+c_F"gD#a:Db^> {#]jEB~ Q cAi ~5]1P'#d 'tI!2MI'KK5C67ow8>e#NGF b#'| )Mh4FL42hU?: ИۖK6ރ\EEa;b[Zes۵kM_ fQvM}”0 wV_3g73DZh\CCxٸmVGac+ NW0t^4a1̲;n8*g`8xv/2`\$q{7zӸAZZ2YJQF-),qK5ܓĪ =m2!'.TYdH:d'>uJmjRTIԚr%m,kG#YCY FcVzňqfV$l$%K'XtZ{3)Y68Y eN!V!y,JJeIP΢s "k56IŤMlY;y/Z/ q Aͦy1f!74 -V*.u%+f+3(: p$v{ApLI=>3!|HJ8H'liY{!nVn2i$Lmgڻp+E&\R܀CF)\x+{LNKy FdAIA^ϥ͓rjW'))Vy};9f 3 Ud/!nw2ʓ!H h6lJL-I*@?vr!%G񤒱V\Emaok{owMlt6˭7(u'BMtj2(9B;2X׈8 Wp)Eϊ9zWh!Rw&mBA*: zVaIk.[6hRHkRrlۉGfZ*f_&Ӆ ;]ҟrջ!pTτBP FqeOk7W} Y\\8BЛ,ʔ4 Ɲ[3}oܱ;:֛qH0|$zdY}icŽ{(íqG;M»{SbxNYy.2XuH +,p6|G*sĄrSٿ*3l0[lR-6)5W4@'q |vcJMY )%nI~gybKlw+|޳qq [kʂV#*W)dwU|њıTƬ:om(^|C܃.4 ?#Fjwl0f+RJGiZTjr H jCT=%C8<;C6CD<B'Ud : OZZ"A u4,U7cĞdî/ ,f+uGgy(d+op͎4,\%?IcK0AI4gCF\&$&?bu*vo֚HQ ('::N.*׎#`xkmqqvo;) vm_) xbSTx6'nzm[ IsG\&G&'Lkpr ]LAvm A<axelÎ'pyq8Y;]O̜x{,qa חB䄶`B;j$Pܓ, ]"]CMjSe2'}ZG,\[zݹA%.Q[[(Au$AIL˙C'1[n_ :-% |sz=eg duR6/cZ-dN,3IiDͪҌHK,󩐥O΢N)6 VZľm uvJ#U'NmyAEUI xb9 "#I*A`BXT]XW Zb?TJJ0Lg_O>oyfUʪ7G J"\'Z #00&T2#\x50À*}^-];Q 35nS [WSi= zp;>k/Y:!"Wj jbH_?r}#9*0wͦqU!!}H`bpf7Srt)ȭL p'q\lfeğtG v )l.}#bl+ه\[$6J5$tKf7x60S3Ǚ؍GϔX?'u%T'j%%l(xo k,/Xx>IZ"VPGL(eFruO8v1.9ai:vt8Kcxnj85ͩP JNā$JPݚʹE%ݲWmjN^2ĸ13O-00Vw۲,[ΰ֐؟x% 0T*䮎|g{uac{l&6m!.1z'~&֦$S*-'GD`cn!*;zI5K aF)lT +DBGUGÔa8K() YI9t2F% q{9'a=݂[w2 5eZ Y$^q/e\2-5lo2Nq'<-_glgٳĖuHi=CR̨doץ]>  Ԣ5HFH'(D 1U-0;Dbune dx:rZ*Í#,O4٤mSjf- BP޾l<̭g~* ᘚ0u C%km:Υ#>]5^?r2/7pO#?gj2/ٵ`!n$&en m;_å 8>/m1=-n2fRA{[` m;%  @&)d?&J,ЋoOj"OL}Q}*#nuR8 sS3Ғ ƃ 5  5 9'H-m%j?}t 歷 $ʂ#Q * |/V\#@]YֈHT+5#۔ }5񾡼)q{lhg¿++Y?%v1onږTBiR4нxz=i5Y-?(sTamщđe(b:9YJ;ug$t@{;pژ۷$ A͔|%|?%՞VWxMݣ媖*9ɗ'ROιk>9G"_ɵ⚔L9{[X?u]])G2DJl7ҹMMܒųZi\'±|xbJXeEġV9NׅOʄ~H.? Ko6Q0m|bByM-#t i v8k6ݗ1W%neIo: DҹdƤsQc1| ./V$iQaJ$xDLN`$Ej3WM>̶W^$%A$:Fr}8io"kA z,1 p}-mznJUR F2TZGY'Ibmխ!r bD4ظJ#r̔i V+%PJH7$tDT$dhkJ%3JTu5Od*$T%&tZ"V2$BlGJR;DDr1Mgc\dvHmM(u֛!D!%$ʔCʤȏ1&1:[ufeh ?o<~[Kb5uSqsI 4NMacϭϰēutS7U:u'rALx4one4$|#4Ji'S(2a2OihvHSh iRVS$&L΃dXQ7)ZD?pݽkukXBP+R$~~}+WG.8Ç_9uot*qL-JJ~$&A414C$g`8Mw,e(INlk$X%$l-8BO\%]NfЮF& 1,֏/7Y]Ζ֥JD_J 8gnTh}ݏvWisul j#9g(F<#}q,^9qyZ?IJR Z|-I DlMyWkܷVml܁jEjz*xlpCbG+ɛPtF<.[1!qsve'B~fdge`Z+$; O̤HyS]-1P峉R!E)X0 Ѓǖ3Zg.=ںM>ͪ"'`j l ~ޝg_a"#TL TE8.BG)Q/F ?#q"utpdVjOL07'˕e VO V4AʔIP&&EDh 2^==t+iM34*@P=kcK*387jA*kG[OQ^O;="[{>px/WCH= >U"6s7/en-{5}7i[jd$Id'RkO"AAh5lPXa۴vr|tڶalԴpFv,NƚWabKϕ%`,$ nS>|`.0KimlX{ݪT> {w %D PHJ~GZCş8Gg`r6~ۛ~$gUVn A cp:^G8ڗM}WxC C }@Qo~%qǤIFlů_?[v*m*=FxWsv(e䶶:mb`@J*TmQȜqQ=F'078qRH$Z()Kf>k lHa&ݾѨax][{)@`(P(Hɸ¸vz@+6Z R($*& @ӕ@$ P:v걣Q0A:FRV> Tvj3"@;O"r,-R*b9z»BIJ3xUVS!PY&5KRV@h]X3E`yy֌ihnlrtt F|dyVg %z`4mJfZ,gwц1yihb{km"I j@53"uOj)"džp[.p㸃ݵtLާ,HNn|')>(CH8Oݴ,9UK9'ֺW&"% Xmj ǗWSB>3~ꬪBbjPKP:־\GgÎZ?t OMTRyr>!k1fYZ2v-+TLddD$xX9IC|7aJʕ4!&EFyQCU#o~8z±k\FME~%F4v$˽^^~S9#ƣzWφ'6{ag6bZOg\?~!{wESO2mf[n'%@}|:=_=٧ԅopHk׏QG vn㻋gcκsyQhj[w?:WuJCR@y-􃥻HQP%Ϣ&*&?Vy v+wT3JgHn`NQ]O;dzT*4Pݕ9% tQHLuP]P>u"q` 'J(J[f%eR5gks,6)~>u~m%v#rc^FcJl[:oɸՇYq{u=aj`-rp)ArGvkvn 1SAKGBDZ>Hɼ9x\jqfO{Jq {`m!%I!G@*:s:+ۉxM gw˝—o+dm[P!HX*qgW&u5@uZذսQ <*┨ Y Nim9KHa%s qnkK}X"&#X)3lsUkg0SiQZI9uP@'aP_+NM,x0%? 3fk:eZui2ͤ M1ȤEiѭ>?m' HnU0`F1H )-BNuXQj!3Q sœ a CJ0ϥ CveM:(RD:GJ.u[m xۅ?f +nQ'R'LqoO[;aᷘ$6MMCtV^]vo^2lĩ3YNLG37^:< ,92H\i_hkEN;ԹolS.BS WL[PVz"ܴjnq|prBҠyQ(: +y{cw_ʒWv@͛(<,j=aAI +O^UyzmpxwV{EH3% :wZ\Y )Q;'2HkcL{=$r#Е>'vͮ]rZwR@ΕI>ܬ|ih.nmG:{)޿ET>vJnqFIpl11mc\ⓈRȔ.S:LNWČuW,iک9A3}o.$|Xfؿ%ÐgT~TˆQ3IFսZ7pRa(QXΡ6WԤHd8*8CZo˨qܵCj az!gAk9}|| qhXlEKu0D8@(AQ&|qXHivŻ[2o$71=+h:=lp/.,eB G^eJ_ζv#y}>QT%2u^,qƪ!'g8uXN.^l%ׄb]gZFGiK"yT BɷTj’ 4JAO |4N+GuS*<T,")l! FXJB~l$YbEyΞ42C0-L/G΢#xPa@&Ԕ֣ЁiǥE78s !wP?&qRTϜ[x7XZ /^Fr հ5 $Ӓ[qZ}cfݎ?ݸ .qKIKLE+H0V6 YS:`ɓl75sC-..VnɠuIָebƯΐ_3%IE;sp+{v NE!k\0NnU)/NPvc\M7BBљ+J)$t3_VqRT|IZ #',+Cl-}+qJq_9VP흕e*}&ma'2$JINMZ>0{BSrе>V2##QNɻ[EjTbF::#n7Ԇ%Rt?9Ofd+#>tA PAjîц/BRZm. ()B@JILd :Wڋ,ðAr[U-{7EːJPV@NZյLi:L^wx-Y"زl3hFwA=4V[6 a[ZX^ ڜjn;3c$'w)Zi%k^eL}#ZQt BoPvڞ 7E;TZZ!JTxRI޲lQm4养*@E:BTƾ iB9/0@C8!}q]8?Eݽۯ+((u#<; fy$Hʂ+-1'M\a%+$GLW]lM$!b9!=I I07$+2bNFe} i V7r3hR H=u+7%Ufۇ-5uzpaŀPG _+'77i#bb✊,g8rٽZ'xMz|y8ly )E*Ӌq&e Z--QIA:0]7F±億I qZvq H1yRIE#Kp1e)6oa*T{Yl6IT'?_j>d%0u\Ğ/kL9[z~Ғ9eq_.SuԢO;9N^_}G O\aH@Ѻ=a=a5~䇝I2(aVm-&XFBDe "ӕ5~5 &w5@b"qĕ$xj75]]utUCkk\r]ԠTVoڹě`ABLC]%:?:sH4!E޲mЛeOzz D7[TqF2oQ֢6cti?mDǩg S2B\d!֪DO~R@zؘ,v:#QtDd[PdIP:$t$ht0Om<*hcsJ`v]Jmq0Fs\]KG˘/^+0nkl;7~*ZZJUmP']2(Gm 8s ZKL%*\Sƭ}?)OV[߻ըyx"B kp~-RoUņ^C\bͪ}$LcߛU׾c0/!҇ y'I_|A_E Ÿ \ݿnh%i..8W ;LfyEN MY9tRؓo^ߨ^Wd(*t& VI'iIZ%9@.UPTm 2IUz}#/;0ùPNFWMjDø3q<:v%nh.GF:  "G:%M=8.!HR@U+ .ƭU ]ɿ[Id\.307$_/u]86mmZ~_=xT2|+^[Ndh*qةٙ3ݭ)jSg2O3Zڥ I&컶žun?fCK"3i$g:l-_0fJx(Vԙ (5gLw[/caNOv6啬D'L: D!!oxq?cqR3%`N$Z> x̶AW;]}*1t_xJ.,nKDh:LL3r 2/p!hjNPyhG=]dۘFy $ʈSM1 3g®sfuRچVg%FZz n'1V7u5[< ,ARJωé$&p3))%I" HJ=^a=suhHJQ,c_~hM3b0>7Ű˴Y1jKh*͚2ʊg@ xXg)MUO3,f(w& |x=e8+n0uKm- E|#y]?A?iQ[vZ)^QjƓkE. gݹ83dTdeU$j3}S52*gWlN7]س_Z*L%NH9#xqWX\\M\%)R|!b=9x9|1揧RCB%BNG6eȆ;ʋH\޽xڢ[uڹ`PyFb#qAbVS u'*TTJ4wAT4rrןiQS®ľv#6E:P+;[PmB;D|")RȏiGH6(ObLӿ`:LL66| dY?4m!'*`;hu4  9lY '$m0yxH(kE>V~5 x8xn~e]IJ 1"B^#|ߍ% 'xvHub6 N8ɳjY`RhVԴ fVm$ YYZ²dPOWwYv<9}h-В:|~^FHǑ.c [YB^i.j!B`-DsTİq]1Փba̋~ͽ-F^ ?Sv0^nhQΓ,hmQm:ٞ}D^V)G%JʔMZZSLGrkm9^Z"YO@ #(I"r|?=ؾ x=ne۫L11r}T4 7ᤎš%⯶%vVRD',MzwFY sY[>-JCkD%Z@I֕+FZJ.. Bز,HVI*&I6SKl;vPU!H+]-u!I ʴ٧$"bV6wZ.4Ѷe9S뿕ki8SƸwh;?&[f iW SWĩ)W' nQ^XyθiOx(qUne[9o;epuqULhy3A)T?aFxwñ.SV8l*Bе(fHV_ Qw$(a#˪z"Z/K 'ƧT$IxwHš-[;= x&>z ׿ c}@qIM)[/o"a 0-r$|B/udZG('m-#@QIavKn;USԂͣ6FȦZ @V6iHO`mYXJRfFgֻDP΁A"`  SAё dTZ+Fk%6 DHS,Z;*btaL¢d54D LBLLrh`|ًw'} ޞ-It'*DXƀqg&.2Fg0_ŷ횓 eOwJdg$D_vp@\[ X YZwJ&IR|y5G?N5t1q-G) I3DlND;{x9q y9Utb;ڕ\Z( O(Lg_SR*˵GVVS uZ8nk#|.=ýcQˎ5l?GaȺƞp7agof^'2:`I[lj[! \nm+G`; f;"+uWgL/x cÛĮ˵K(+lO('s^L'Wӊze pf1D7l#*Fz5YAk3fX@Ǯӊ1`ivjU'P$:y/|(dnW]ٍcNqj)A$2A*uC_>ܟznT+.n0E?krmղ>.љEIS>p.2 ZbL$[(U[jTr yyp,"|$.bɳs}!3;4 $}Ft]a6|5n lhkLN~w=>]Tc4A2ї>{iCu@ˮ>-yzNq*og10a xk8yMBD&+[>4n׉\-,o_ jݩ0 HGv'8N[o}V7erqaVZ'ƤJ@ B]ʳ2t娝6R<=X`W0.Pʏn3ypG\hxj3"Y589#_e.\[QlQ ;:5172'J;> F?X)H*Q>__>O'ܛ+ftTI4y)q,#g!+K8]gʵp5~mFmq 6R'^AZeY|Ėwĸ A#6vO!E!e\>!mn60A4ocq 3^\KZg›T4BL'wIj9F]?bF;ql~?];vJz]ãҕٓ(`L$l olP Xd&FCHa=qV"RjB+~ioH UMMD7]Tu`G5)\BmJTZ6hb%ʮո[Mf%0* SUaHB?m!'/O‹-6n KΦI%? -ǁ?<(;:Qb WO`wS$=}˄#jSrxF:CxJ{겢.U_W΀.$~5X&++Ö-{HAYZԤj#Y|,'q- ޽sٸڒ UC0#wς9L/ߏcPGXsm۷lRHxyۄ?3qԢK]㘋6:#6N`$t? qW@o/q%w*a-SmsL8[ZV$Ē+9rZ▿cev=55omc8Ù.꒻f>*.]Po2Wx&T<+Z%J;uIR=g&Q%5>Kѫ=Ɇ-K-$! @Vt d'5KU7l % #[PDn4i$b},suȋpr nngh֥f44j3k] $Mvfls|DPAP]IY QA2`$uڦndPCT"J ,\2e12]4trɁҠh"|(T҂ {F0Q@5cFY PGb-H28'0CW!K!D8DˆAԓ]e)R<ڶWpkz ypW1n>_e]G)RR+*)G=VUdΆK Zʝw$r7Jρi,X]4HNlhKLJ-At]yonb \PZDFa511qla8G_฻{#9odӮ%;L֢fS3'A ֱ?ǍIY,/-ݹ슛ICűdi1]m)_yx$pPI%iJRy֣\%֭/neR[$#JӶ)[|gx D;. m7fЌ5@؍@_7㔟gєkFqZƭUqhIJB΃Bdf9J)Z2-aՃ7_[Cw-y(סI3:dz9t:T@ oV\(RN`RFy 7Ů\ol_V@͊: t4H쑆 dĶI&!:vŊ~CmlZR7XDoY,ǒvKC֥ B+IJ\Q12|1hceۧ2q,ۢrR $u`ļ{>o" pL!.YOX{fB}B\`$ʁ'nR'7C8> 7KB֤JJZRB2 4CO;Wü?s]6Ż QQVt=}a78{Aw,5lahk"Q˩ ­y 0d)WI[Ű滣tI4)Z͛vєljlXx)rSa".ϑt)rgi^uDZ: <Mտ~T+OU :wDUQdݮO'lا]T5TqFjruJٖ6I=(gzql w4 0FEʓPd 6u#AZv>"j$F~ȠIKK24H"3wdƢ?Q 3&4uEOnP4x~knZ`鿳0e)GhfB"L%IBn^<h5~qV-*Ȧ( "[Q>rU&yM?"8BTu32+IG8,lշVa,ڄ4jڨuQ_)B|T0E޴fK//IA1܂iz|16zN7!2D@O*JkHFHAp ٭υ;TS2D 'VYa 4i\{9|>EգUaͻD ]ėM^,wnT2[>BI>u*UeH=+n#vv*A!^fZʑ]e 8K ΃%NOS"`ˊ//N6IH9Е(ATFh 4ÏMG~iHoܱ+egB>u˃vp4`٩}8!06/m7I|Zt6$'ָܔ{;$ўRڰaJRQQS>a[iSgU'ep=|M2D2GN=%١]q%4l4M6dq"](:mC28Dm$qޑ@8ItCWa6mTL" j)$ti5Q#Yia_?Hu"BH *CQuU G*dL1JEDQN$ @ѳք> Az >C=`z@7o-c?aPZvXNXzF,@x$zDTd4+*򪈂ųfyyTCl'BLa ~tӮ(`0.=wc1 LS~۾VIMa4|8'G{"rݡ!d$3:c]Jj_<ߊ,1,?iY]-]l\*QmIb9,sSX3p8{)/L5,\O Q(BbFI rvt͏ёoq8~Bۄ6a5I]h ԩҚ1g%G,l=]g&eqf=h+C*˕[D4g"SS4ֺb}Ȕz2%;@5юHn{S)ma?H1y2ИcAJPB,Gg8h|6ish;&RބTҾj+,+l%KyNet:ׂ>Ro/M \|;xh_0<2g־7,#U<:_l>^qj3Qc,YE՗Xfqb%5%l<Ψo/f u Eev⎊.L⸍9]b79K.gRP! |#oBK F)FgS,PճHQ3lр4@_{"YhI-%"b#Jߝ$ sv`iBl'_a5:@@bI27@0侼B}`4sTCVtH N~HN!UAʉ{Gmp {?i3S*E*Ĕ-cZ'Eui_Vr_ժeCN%leBڇ\^ZJsG/JS}kۧSU1Sym"O*,(w| ֢JD5PKI7*0o]3juV (050mc[t @QSd)DkW'#/+2q[ھTG:J>YN5#c \J&l.M۩6.:[K6$JL&0,*ͥ @޼f[-#J)Cn_zU@>ҍ":DI6: \JUfsAӕ&dwɯH=N'왁>sP+چ>-MP zHiD i<*`:4_ s%q (LrtΠFQ H'hN|I䕝~U-&ZB%mӑ:[A !NBwm) 2G5)jr{6%IH;6C(>J[@O`Eb*4[TVF啨I"ݸPl )d:ɷdXؘA[#]@lkXٽ5ڣ0Z*P}t>Dq9f>\w{<_Ů#: uö֖*J Rdq/N dpfi \eB ip,{1ynIMz I*'i2$u TBT"F C*}iB3}PֲF(3@4U)5 왹P0Bz@j']7@(:ʢ’`S﹨_a"ATBvDD3²GSe;]T*Qg$#ɞ[Ę-g~Cÿk8 fZ̽tTLk]!5o}9.j.m h *OTW-M)JABhQbl9Ӡt#SP@zeGfJ}j*"pf4&F{^"e3<&PDeQC;LIF߷~[qJS)$3m۞MrnݰBᔆ2RFteSy=hw>ibն"T-"Ӭ4`F+gdX(QZֲa t, 3?#/0ypN<|:K̓4z?ȣf}qmЈniFu;ti%)uyJ}b܂{F Q#`LYPW`n%ZB $5 iME˘bo.q;wB-*Z@K9$!xpwQG͑(&bL?Lq2^EI"zإ( 'L`#vxܹ`ls7s6@ꔬ ;+i;$lqk<X1۴Ym:[aN"VrƄrMEE3Jҽ`PT6$@XȴV@I=E$ cTCT`DApU.$,0TOIzL<"H@]`3v@?1r2}8JËn NW2Yp|* B|]rAMQ^aw6{ k• -`%J‚3%FnQVv4TŰư. B/9\ 9ip S#BPUƒ o&&g,yS}!9:Y;2IZLal ֘!R$撔ܐZ>Xu %0Hӝ'PmNJ$syavcEIʾ'<#wp_!~Z@}2"*DMǞCs(Ԛ[0IET6Ò nz_5G_Noe '0"A+9Լ\,w,ےi2WI&-vkĂ&z)F5<)`xĘK7NwUȥ@ 0 r SE-N#AYD?ٷ Y`@EIϝYw:מO'dNVhΞuPRX8$Gֽ$…=f}*$vdJF__|ohfe@ғ(vLGrGbAveyuC06 =5 0i4 gґ#v2*"+~Fƣ"$L)])wg |\GvLg(kmJ?(cl9s=˶H` * ad 6Dl8m&3=jhAў:6 @Ρ;su?Ϋa`ځ0B\=+=(ڔKg5PXZ~r=QXX 'ګ+q, O\LQb;_G,Qn9ۄyT.GBTVAvad]&t5vltDGiI7Ux( ;9B1֮dsbfB%ԃ-Dj ?"<Y?i|5#p7lFݲmKihIRA0Li\^$_q<,{^\;}}nխjTۅ~2"[RO$HTÜ.IlԻov'eմ$H=$WtprV\ JK SIug,~uOUZY]! [%*YPF 5'^#',M2kN#mnrݻd{1= ?9Yƨ sp6D΢#oˏpnTaxBNEHE Jx2'$jq<y^N{T3}PIcZNM]mOMa֋aR[e IZInt}vϗ얍_'8B^am+eAI|& 3Okј31[*;ȶ+S)PSΐ%2mO3LSq[kmutT#:u5G4eb nݴ1 AWY"U-lmҔfyݳZa3؊-H$TM"ARfȼ)>]֋*_"ۨcbxbn(8f4U|')H(Q-C*6%C|Hp9E@XUP@ФX AZ~2j F<'.#-oͥ~T"#BjWHv%j=\xG?B(vn5'v:hUZ_F^EgZNާ(JFiޚ_HZDc#jtM2xTkr`>aPQ M}fD~5ќrG&7ֆ  >CZ!iO#Iɘ*jD$ L l *y}f* 4iuQ ?j(lDLzH,Fjl#ʁe"͑ ~< ¤CCi K?5, >RO@(O/N j#}py±7q '5) "[mƀMn<8^ӂ-y5FȤP[/eA!璳%C@>#&+xsG9 _*,PbF}7Ox|NVyᷲYe6W(ʣS^ƶx<"9]DRI@Vi 5?pMi2 &7?CI}@^ˌ>kҹXB <č4kwhB .* ,Znm-8Set*r60CMla8yx>8 un)ZXI PV2יM=2]8@rJqI`*̭TĮxol.q-YaZz:#{.EjkmBIh<鰡=EB)L@驥yASAbe JQ1 (M#_~M&` e% jHQ=|}vcEHS#"%2DU !x)! =ifAѬDL* lD)c &EElx}i6NˑzفRt*"5t֢3CAy\憅j@<5N"qKM< 6TBy(v~o!G}SP U>"G:& QԘ1ATSsL*H YI# .Ŵ?: ~6LFv,ӖZ@ >|> A*hdr(EAI&2Z5ylHuPP,JJH*GϜI#]mܸn}O- DST  tշgтۦ˫[0kb[q(%!j]NRLLu72n %㝙*PJ@<돝R=O>%,KMθ`P>|^&9GFJm,%%Z ҾF||y2cYpF oaVΣGZBrGA:@k=EhܦOa|c{b?ܓ|Ү-NE!vp2#"FPoF4M$[ۛsrhBUHJBR4ʴ ,p^ \:K3yi[5sppRr^\kh!d4;޴Vk3h>f,BBuD,")SS"? ZISMo8h5F*PSېZM" 6P@!R" KƆ,' dTR34ǝ!C#"D _hBq;5'n[iYn7#ZiOJzZ.NbfF$gDq"X&6 )읃'P9 G 4Md:D ސ kA#>@ RI;2O)1$:Ϙ}!JS&HߑQD,Jyj>’&9r$fmt'Wc'6'PQ@ɂS8OW@1DH$E&wsG^O5:4ւdK/^'b*iE)XI#)ќ ^Pj"V]L"k~&{$AaMIȳMEb(Ϊ+txT6mvu8iXk{wicb\;< šyl8EڨkcHɄfo)'𩰲55v zKbahyn)]! $ǭ^z|'󬲤wSM_X:Z-wJxd9c6AP_i|LU)vAصʂ" lGP킭SsB%WmA6) E0$Ty,PTq+͛ߡ9HiPNۉeWb#E 4ppxM3?Eݯ(iTkmpO@me\"BШ*Vu޶Šbgu@1xpyzA bU[#d$Gf|jэ3X['AHEiVnžR$t>DG>;V/h{a֊GKjRRYRiCb%CDk u$ɞ1g?8ێ2 "Ƕ]d%M4!HP w"eK}0$ⲛԽ.Z/֦~XoԓvG?C#{3Д%J$5;z~m7y%ڙW\?H{ p:ն-P JMZv+No1g)Q$)n" W4K7ELzq+3֊*!hnR*d=vpΨ9oCLZplp=3B7=~4T;=uֆThYեIZR:_B,|>(6Di 8s@j"R4.T.a0zPbJ[MO} R& )VMDD ?l* X6DQ1M, *A&da: ȍR@9ސ$^jX'"a Ju5MFЏDsuo>Ak*j C $j`}P^t|@&Y>9,ȠQ;R#ꍽ*Jf @Hj" ՖddBS#\}5e : Z%}$=id -') l8 }R[]a d|g,ݵqhT|'ʻY>'w'dV#~ Pڣآ}٥`pܴ(mh !( H+&ZPH.+hQ`P :U0)~fgJBmY6dV_hbi*[ R?P*mG-6,mU< #3I>2y -pD(mkƔ'd;vɘQ֛5k'JfSo.B 7@piCcn,He_PR+ ­\]kABŋ?.m"I$~T 7Rx Od9DifPgw)I4^Cw)'cz3)Z*Svbٝ &0<@" b$ʪ L*{R[#m(d"sm;@ RHt52GA@iTSQ1$ 2P@'eF>9ZsI&#zT W;圍{MF]ȒHyVh M$#z}hbGiLMT1!(HT"nzVhʄi5Q \+@2D_J q!ZDDɔyr>r<&Hmn" VGqW;re,t)lԤ]*T*4R٪G6 l+ FKyFhւ;.m9] r_+hbZ1ڳ@=<}QiA֔@:bPjk$VY w5ZU@ TsjLif‚ Q~tĵBtU@zH$DXR0A6ާ˲}u5PZGo,H4z,v;V@l=i!Nt;U}ԍM)QIi,Fd-44L.t좀jЀc xcAኗ}3L/y%P*2vYH=b L@h8uQޡ>^R7j?B|-rΪ?WAI(d*!*ŠXHӐu I`FÕ@*tG,oT􀓬V X1=>ԯM[>]f'ʀY]dckODs}(fN(Q )w`}-im&E#p>fN1ϭ?}dV]5+I,TX2EG#sU]=j@w_ԋ(2(fE7ZAQ1ϺO^)ED@B*)@Olƅj%Mi"AQQBP޺kR74֐U&zIiHVGNI=tg D(Ȃ9sP g"@|&|=GտXZBGA8C؞ST@bE [d~jd(|ٵTR9W7D1W7 ړ1QRX]Z,  (bXt$?:Ђq O?4/|DO(*jO+D'CZ UIH9^LEj){TYT*. W=\G@ҥi'AB):l1I@414T1[Uh͂T b h5񊂄GydthQwol8"@E6MؠZHLi4M- zu V'}T򩀄A Wð@,س=yyh}*j|$i Lr@ N%h2L*$FҏfFi f RtD2fdn|HP_bHc҃#knOuEClG--Ίl6B m^HmnKUJRAv}vjvgfm' If)Clc}Q {$,0e_]L$$G!4mGZ fхQ[$Yae{L$(+M^D:'Δٛ;ƣOUe6!p,ER#zf,W;hfV^\@zJ+ L?I=cr߻=?*Jir1a!GHjfot?YCEY7D4 Q!y UfAN S^RCN'] ]%XCjM1ĸ%=bfyRAIe{TGBe,%_ARnoZ7?ڤ4:ʛI"1qlq+!iY?{HXʑ@l$H+8:D'hRjIUE}jo~s1@|?:LZ`KHIX$r'7)_WLMiTJ=6γa#zTA(<+Y/+(;Z[?Eը*&1_+K/U~]2]_*!R/ChW? M2;as?ғ~5VY* }dTLǿ MDOʨN""{jE__Fj]L(c B?jKE@ ? Ef11y ,U|@qX wʑh;+֖CO߳I+HZD"Z&micropython-1.12/docs/pyboard/tutorial/img/skin_amp_1.jpg000066400000000000000000002427201357706137100235630ustar00rootroot00000000000000JFIFHH~ExifII*  (1 2iSAMSUNGGT-I9105PHHGIMP 2.8.102014:06:21 21:17:12BJ"'d0220Rf z    |t0100|     '@Btg'2014:06:21 21:11:102014:06:21 21:11:10Abe@Bm'dm'd0100  f@P`\n0100 > JASCIIO08B00AFK01R98 @($RHHJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222y" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (o.V{H\gހm5*ê"FE|ݮ^yKY#p!I=?s\ƹOr\p= k>w?Oio{kkC2!!xkh:o+RK{]zŠD䁍ݞ~85jHHPKk?-o#A]hrZb,T$^{w)Idd~CqP\O1ۗA\nuX&ԲXiJQ램==yyn.$VbO5.EnKn!(>qV:Q̼~{+Y#9Wr+~hN,sf*0̑zzRS0A t؛x0pK>GKÎWs]ĭ/Hpzc9*WWXz_ma[)bERGQi&ESQEQEQEQEW-R=?@2sH'GCֺ/p*BJ36ٰ _w{Lއ[5սKL@ ޙz)˪V1-Gf髳Rtcaa|pw8zVMKX3)T,K?rI]#=o1nc4BH-zտ "AEf-l3`:Fά0$}p+b Kb'T,乹Kx՞WTQ'րZO|eվ e{lr~^5Csc=Vff# 1=< < omxstǢ}GSge\!#>4/{[X3Nq3L f80=@nފr*jjje|M[`I&Wच_2Ѽ [^n%R!<+h挋/ziμ_OhKbxMZIlUkG/t)̖/.Q Tl0:QL'yZ[5>vQEX(( O P 8r#.Z[B Dc_ k+FܲFBɍTe gCehݜδ@2spxUeȸت!OPy튢 )b϶n~a']1BNV05mi7ēZז1BE4mtEw[XЬ #T)iW$w?|; n[*!* I }O_μ *:5KyyؠAjkSXJڤt^Q8^59Eߊ+fKb9vS?fHTբ[O_j&AzU,$Ŀyk\kS)+0*QEQEQEQEb(7O 7AhleQSs h7N>b'kE!daEKw4IXRI<3e\`|m^E'F#VSߥC?~IU"V |WQS<|7Ý~)oNkOI3E½j]C4جL[ihu}:1I QT (((((((((((((( http://ns.adobe.com/xap/1.0/ 3264 2448 SAMSUNG GT-I9105P Right-top 72 72 Inch I9105PXXUBNB1 2014:06:21 21:11:10 Centred 320 240 JPEG compression Right-top 72 72 Inch 1/100 sec. f/2.6 Aperture priority 100 Exif Version 2.2 2014:06:21 21:11:10 2014:06:21 21:11:10 Y Cb Cr - 6.64 EV (1/100 sec.) 2.81 EV (f/2.6) 2.49 EV (19.25 cd/m^2) 0.00 EV 2.81 EV (f/2.6) Centre-weighted average 4.0 mm 202 bytes undefined data FlashPix Version 1.0 sRGB 3264 2448 Directly photographed Auto exposure Auto white balance 1 Standard Normal Normal O08B00AFK01 R98 C     C  sX  L ! 1"AQaq 2#BR$3bCr%4Sc5DTd@!1AQaq"2#BR3br$4CD ?P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(>w ~*sڬ W{xrKm?QjS +ܿQ2} {;+֪/[8g|>M㫂ݕ/C7fUz/i/eiu!m,)*Jԩ5(P @(P @(P @(P @(P @(P @(P @(P @(.dh14MnROI6a~ 9;9!xD-=Z vJ 5BwuuۖKp۝ZgР'DZr=L])j%W$a=NuˊM0nxv{u?oG^Jy]0^ <ݗ/Te`m/GQ u X^x?_T^rSP @(P @(P @(P @(P @(P }1S̎( ~\ i mKY#d'R#%Q|W9+6 ҳ%unT|JjYd7a\/6)ZH$|*%=IpR䌧3D]},mp"2Ԁl)$)$ zU?MP'_L`(P @(P @Y/.GlRrLMm.4zC!γh%}5ViS辭엟MrQ7k7k%_uH WpC@{M 2>yW_y_ml_;ǰc l7(iP>$~ FF7=>w$o@y^-:kL8K΄򯨏~ Q{κu9ӍH{&fVY +} t::Yu'%Fp9˜[KL OG6mר﬍oP~+*)m$Laz~Zƪ@}*l]j|edVOIIߐj ֍z-7%w , \mp>5%?~@X ^UP9ֵǿ[k.|k&lƸ[dG萡 պu#V*QyLǺP @(P @(P @(P @(P @(Ps:w"}ҭ˚˲s{Ȥڜ-;JDԹN6inC{ 'OU$սp<<ak-i޺`^8Npf]c1qfǐޮM:CA=Ғ|>JJPODI̓KFN¼x}[EӒZOݓ}2?䑉qGHmw%o ur4eZm{y%$V>3Jړ]C\īVz~X}5.̫:Sr-"irNMe-},n8@JVͣ۲AWn~%wjZ=3xt=tLWmEoȗ=G: Ϳ"᮲k B&*K1]BI;7}4'$φ^ǒ>MfW~K-j2H (β-帯]Kd=of& q[ԏc^NJ7|>Xe{It$o,F!2{?Xk䨮6tqt/ojoݩkˎW/lmJ/L/a1f}B!2%A 0 h$A}uyƎqJ4SoMOz/L,_)b _zU#Rvm9 Zd|Vk&^p\B@B&My6N֏pJNHUũ/W _BV2LܥkML-_:gOu?ْn 5Si3qǮLI!m.Ũq5YF=œ۵]oB1[U4xc/[[d!{6CQ R+uwlyF[T_^Z {ak1ْw߮Ac}ȣ͝Ym|;qqjZI>=h'Z 5oT0lU1@Y.8V9{YrvjLKG hHH$)T*v^UϺK& `y>=" OE AuGd2=m+J%@׍h[~?x{RS@(P @(P @(P @(P @(P NOVQLn8$ ϋa.;NܣHJ_}RVARNぽl9VxMly5~ҥB*IGίn=a|Nx }mq[*ȼA0_q Ge@), QWK Ewce7,'˜lzb <*ˏ[Ee!wQ#[Oh)qdJ9oǦs6iCgS*z諞m,d6~d]kKX\%6 {m&rPRVYP^FStecV:T?2Ti!_M9!>=$-t8=ָ~I,۞g7_MƱ?ɵ7<%@]d͔%ٷ5ڧjXs:yg_Chp˧._>tLlgG-V"|^]-kEQ*!(%}PF%-ףЂJ1֏ԨthƲܺ 784TZN!hVgz* o*Nރc[+72>vә=Od;K_\Kk -7qLvJ[Ps*qM[*8mk*r_U-孭eaO=阮K>)*螙 Joo?oui9]dקqæK-`2H{JGiף+T㬨y} Qȋy?>:uZϽ/C=0mo}"O}kd+i%եJ$+JlRV_U*+9r&meeHqC1bh![HP HƫN)AF+ lrzIl".*~oO<õfYR.!'F`l= J@ҜRJUFE%?7Tu7X|#嫾[~y% LF@n;@iH5AFS%4VBTQijz#Xe==ݤ?~Յ%VzdfZw'Cg>puZzo S @k`k1om>GS~?o~ƚ7llk]V--g :TX. /gESY'{6719%D3QCЖ߄<5؍m$5U^cܞ5ћj"~YjN[ aLÃHm[Rɹm$JRGjXП,V_brsoZy[s;nEaUhe_!itA|^HU4^QMn`# &M*ީ7aOҕoi q*^Z|sGd̫"c|1b>c<묺̸eϴy[Pq B~4jZ^~z?QW <c)'@zgYr]cIWir$-׺e=u@(P @(P @(P @(P @((ȘqAʙcկʺ\\)?ZJr{":cFK&@Yx<{F2uÃc߸;Lq,-% #Ĥ4^YϮ:ok-6byFj/KL>oޱ3֦KonRp9Kc'q^1 PXy/w9%.$U>!]Ъ&^{hrxAǙL#;a^q>3 MkHl\e).4An,*SEޯ/}z}z8ѝ[tɫr9![YxEOdj4=nZҝ=ܤ*L^ΤNnpeip$GAQ/v<&K\lXqrkk D'rKm )ҕ!PT:9d^TU9hx7tqWpM=7!X362䋌ںZBYp6ھ;uaïamȖVoǦN)GEޥ)ӏSor韐GQ2sx#2;EN>n,iKA e]VYƛYk=mk{/;nɱu鯝sRN1Nnzs("Okr ˋq v(*\pz.浓̚xOb\/7_1LK̸AYN!r\k;Op6TmBGvWVD1e6\tzx87˞&:fwe@JV\%0 b[IRĒ.KWS]tZZve%6 H[:eL! h$$xI%u?ʲhֿ0| q2UӥcیSw'A+ڶA)GH'Sxɬl{*0[tzsk*Z{ڱ-a!WXB *y)/8 ͵WgUO|}W;'d b]S-okO!IPPPAd"=հ0?էΨs֮u藞rlG# ڳvطe6rJT -nIǎ/) n٨GO㼯^V\[wFݓ lm?U8רokW)a*C87ۚ[JJAjժͺ{~5xt$ /fY¯x] q͙RQ3[ZZvsOuWt*\yɚ6޻=O%L0pt0/37LR5Hw5%;ڷl\biSxzx|Zx<'::°7?dX&Tl7;_ła -6RGRA${;s)G .~JROWNP @(P @(P @(P @(1[ի#^rVw9ŻUJl(Js!JJUX-mmzrxS~n^Ѩvk32yr]Iv;=:hAqe=qaeJSlp o9>zOZނBI,+ fFn5z좤}~kwzk82*qI:^fIuY?(cVddu&Iefڛn+Ք-؄[WiR} #4hQ5V=*QphNaNY1wB*OhEuIBvgJPPm~/RȚs-4ޤY< ktB@i)Jy}C5)3;&ק?el)x/!NҹT.?< ~Ƨ)&->m|G7#W=)^N3(Y&&T(; f^d/aFZ;VrMrӽ܇RR΢,}яc.伖{9ִQ]KQmKJ5{E4-3{>@+^E՗3y(so.Z-n2H THBFJY? HbZ4)Rꓨ>MꛜzymYZ@hi JHWϙ|Ti)*Wݪei.qbAi% +#Cd[Yl<9j(-J 7~wywpލ6M<5JWPC P >6[Ӕj{pSQog>2G7TBKڴֺc\LÌ $ oW>ay5Ⳍ'i2ͤ7},%h}P 󽹟*ġW#sQ84pWZl#8.C cOgbU'GiH$Vs0H?Z7hoGk""Y5~>2ٍ$:%R[>WQfǻ. ⒠ mKFFտ6QYja` ^m \626;Bjㅸ(;ը?R%  CĝW6nu6]0;(`79_-o:Pm)HP *Aw:)3 s,OS8'V[ ܇c}3 zbƚ;Sʼw|:)m|4^L| noMǷ%@1SMImK5 ](Zړ6Br{#_ >TP5I'^j 4=ҶMf Mnht?A“< )+jhwu 76^{\&*U~^Ò7wNIՊ.b_'3k f7_B۳A;ޖpr1ˍsbgԾ'黋cӊ qSA š>⍩^KeM.lGҳS|ŸjN1JdHwg荒erKW EP.qFoOCT4 ZJ>[ _~\S*9}%[GjhT'L6q9%0P18&2Z)*Ix>!R'R?ܭT3S2DZL**H}]Ӳ 5x kTԳGI$7!1-S)J?J>kuR2iL}/w m>Q .('RJBt |h*7e`58`hSPf9(}GǑ5Rۖ9-ap{+vdip%[ҙ iސ6'JI .h=>Oiu_C3FGgu$Y+"I.Gmo  ;A: $|ƉrZ}*R5'~təCOwW2QVFݪjP-sG¾@t}϶%CUe^3FYO2N^|4-p ?[׏ 2o^fa{'ޓ?C(:c#^?Vj;q$cEYĨ#WgOÂWcV:Rxsս~Lg!%hl-$i_jq-Wk/c9XKkf]TR>f`_[rbzœ-n:Skud.)iQ ZE[QKw~w*Yr2;ۍx{,9'x5헵uU߄EbK{! 6~|GiVpOvާ#J hN*o[5x[M^r8b;+U(3vm6X^xh[+y#;uZZ"3(JJIV'l`lGRS Ҕ?<7cmN=MuG+-+Qo{Oh|hms6 /Vh[mgvV0%P[SJT65ܟ|ֲF3j-n | (GZގ>|:.6WbG cB}#TRAk4|귏C|:[hćB U$~Dɬ'ؕEa6Q02_C!l/~_qb޸&)qH\%e'+BtFҤӮᴝ*VVPI"fZdBZТLp۰ k{ MWh,wr"sb\wl0n ?gcaU ܺoŤڵJ[ٖ %jOH׮rl4]dgXl>|Ш.$~G_p?weKjq{ KmNK\-Q;|oFV[q=\XuB+p5ۺnYj;'(ӆ"ǖe[~*<6)r醒Imˋq% ZB^&9%{0ty!%;\z/&Dng*tOSJaE;V[j=_|Th {}>:͸'Y?-tx%N7"gʭ /ۮ dBZ)t}. +UYܵt.M%iw&=8(TM㢗~=ȿ:*UȳCCVTӋCH*JIO7 i~='pᑃ3޺'pP @(P @(P @(P @(ƿV^Y= ھñ=T‰yR}ej!)$x[R~ƪΟii{2:L?Y`hٲ8ThVv͒,kym-]&\f[m}))?>EX[c 采y]ҨgIǿ]62Ng{aymKv[o%]㴵!9ܶ=^+RtVU^Ru,gމ|^9 .uq.2c*lJZ -8ڐ\/JdlnZsOwvJ52.x+1 kW%Ηd'@xo RWN}ʻ&VeFRja|\wS*%\eˏdh\6Li=Kf".<u() "9B5.$pߜl= 7zW}%xXu \r˭I E}.)n?auOBR 5:'gc*X$_VSsԟ*8a)w#Ǭ]8L8e2RRʭu q7}/%$86ob\W9XĀ _^*xF-panvq"~V}6EOIKu¤dvw1h_8]nՓY\#7GRRM6CQ5.I\Frq;|2Еv_;%w-vxd;YEo}WcgAZ'cR572O%% S<X)Di9l.*{OZAPHho(>Ufrʥ4R ت`˩hjh8 ?cx F%LdZ0O:dv~ԟ0$uImIJ EQaI0Eߚ [L^GqBl~ui'd :=O?h %=hʽaʀӐ^d+qۂ Nn=ҵkuDYTsi_c.2XlČ I( vh:B7Uo+Ze)C:|@;\v"dܞ&lѐR7o)EH:6"8vulw;5,)K6_9=Yt-+ARAW~kQQX5߿_NMrlń.L7.Zqf@6ȡ{BoPDKhJ<WT]O)xK;M}rm,ck/顱?Ƹ1wK!Ļ'32ep PUJtH^[Lk#p )pY;BP @(P @(P @(P @(V22q'(gqmƸ!d ڮWI0md&+yHHC,$+q;B\+Z.I$sLa4qEN4ۏ%oe@-.z?^̻D ODd( -+@qEmtU8Qi8tV1ݷ-\ٸͧ)##mrȑ24gCal-+U֏ǏZqNo .#R~_Q,V32J}uIZjBxLw%~V[]}J+_IG\o~FcJdu tҜ+ut'0{l7[D5vQTH%|Ե)[:tL/U<ˍZf6\n5ixQuIIb2T$8{ JAR8+|GmP%d l璮nK1$oN}s.Ҝ+~Cd{Gb y\Ԍݾ{޽IJO;,|Ͳzilnz ~\fOl-w}֗^ϞŸBUF`t3NK[|I(JވKjsI@AO^}:\?-tea.˙ަmݐPHZ:'nj%˜YӸ2dݯL[nq_uDiVΉT+x=Bdk@^J)$~*)jFvq݄u>||xj6"/Reb{cG! oEA=)CDy G8{M`WK%Eɍ-"0 )CSjN (|O>^>Iך(ݴ{Bl q-vd$Ǎ[\ Ρh@ ~64|5$#6G4]QsE8o$,]u BU*.uԺ-bIrڽ 'CfO*]IYUӍ'Č$#-Rd{Mwq}ZGnԟ>y*Rzikrɨ~?s4lm3]Oi@RNJzA'B}(&7UWJ3iz{,(;2lF}uO: Z{*AJuSJE%EӮR+ Vd߄wo]5n^_ym vB2v۰>f}: 9N㗫3 {y' 4wG*6xDi^{e CWHsTxL/VbmG Wl{~}d]v!ݭxDo(0T-uNqk'OIl|ųHJ,$m@ڧ\B-p#ԮO%*E#l4u̪2Ԫ[nj)l+' ".HWWS"8 n4UZ3F;Ɂ@(P @(P @(P @([׊JUOS8O8>s ]YNhvxD :U Zq0ˈI6:9&)$י)=L1ES]\Y6nir@ <-'a*hw%HE:FZyGM__ t:<4.W-U LON> -9'8gKqY] -"0[hRR{{)Wv.-Q/uwLi|7gM";럧S]dZ=@73` =  JAWor9cdmܥi7ݞ_).-{)hgOU;[ڶ4Gy-OuJ Oz *:z Q_K[3.]p%G^r.Gls}̈́!):w(Z[]XI>loL'Fڊ8f1]He'0聩 [I_e5`luևSeƭ9Mz^Y]#ܛdf3EկN l>{ԡ?ӿnޟ|_48= \EzVő27&!/_iդ} ;Íܒ3{뮸ƅ[K_ mxXKF[CZYJR($|\[T7&ʋfO&?'Oc[3P> ly`~_Hr^(d̸o8$0.e{m+?*< w_G/V\S6^t΃6a!(h@ AJK /]KC}KʱgӅeखu+r>ڿ yJt&&8V71W+&f{{㺵߭|h@}GS+,ŧY2RZV$O~<S+V+J Q'#O 7^P. lf?Nsz?:0N:2w*,E÷ۊY[{ҕ+cMz{ޤMmg8sK|GőxTcg!6\fS2 iuƔT}LgZouF2?~&յӛ.rN-x{ ͜yh0y+@XQ V*_*EG˓7 yd iY#H޷uj1Ih[x2)iz رA]-7Q*ZI+[cDԭY, mOZYi rk-J 5Uy>ɬ7r+n6!pRJZC {>{C}_o_yze'8diE4Ў!|{~~ՈK8CuM4ft"cl,Yqs8NCnqߐ֌u^Kj#}?vk߶}WVl{>ßugW{%޺?KaG 86pݡc=~/iLpNSAnKX4y8-q Ko |H93q]_5aP72Id-K~Mۛid`$;*JeIJ@n6MG}>kJqumlupS[Wl$¶S_R&7 d):RDhaǎ%#i/(Ni(E5oǡ USDاT}DKL;\̤$.ۙ\m!Nь}ŏ,xl~^XidbtBP=3¼%Я_Ub.c^lROξzueN|s#$\KYmħ`@A5YQ\wt):Z~ú8B4ʊu;#PRK*A/ևr~80d7)q髅njmcJ-czP'*"m+x֦OlgNN,ՓR닢n.|Ͷ.$Z?i}l(-; JB({x\嗧38 /ξ 0-J2p2ޕBHq{F?^aSDeF:ͳ̴]~?6uRjVi˜3"]%qԴSR@ǟ'UPЍӌgrXF2#CNW#I#΅MPΧ#DB^-S[A[)BvA%\+=W,n}'Ja] wh hyr4Fڞu-W:tDKvq%c[))ΈP>5QeEcߏ:(=[RQw އSX$p[qL'(i)d)BvgZr}8䜝'>wYEITi\uD|)DY%'fEGEs4/1b6E`[Q8unJAt+jex\2/N@ȯ3 LinXBApio^z*<_#zEbEղ[b΃r'ne- 8Z\rzNu)ar+q.p-q&_2ֶ+=&{Iہ[!IYRU ԰^9+BNxI䜺aʥNj58ԧZ䝟ʻ4!{ܸzfo>wԒKCebQ?3L'&#rryzy?oʫTIm.LB<~*ɕ簭.[ZHkU9#5*퐊@(P @(P @(P @kկp>{-g$h}ko0v^i.$8 ʃtU縝/[~?Mc[%w˗fYw&%RT,VbK-$JqJ(m)8oW'ʒ a++˦[mBMW?NWrϘնqBc[-H'_7o R?R;\ /"Z5ckjC.ޕkK?Y42u'0jnT@LT4,㹡wsá CsXMF'S重Vj{ p᪼ޭ0%#ƙ $2rAc8WkvI9t~W2^ kV)xqvzEq6Fdx/ΐiu- zQܰJQ]\+z."{[i]Fw=OHg6_|4xVni]lbDhHlHuM-8 .jaEoxŽ 9ʪ7wOB|lѧD`ϔYx>6CpbՍr[ĔBC1Kւ{yw.oԹ\O-_#jQHϪ_Te J U_Z:s/mڭ.6)pJqd;!,ĥi֭Iʆi,9){=l{wp[Ӆk:U`sHPʲح,]{v2}EBJn+\k}>^XBS[_nq^W; ,^O騵ǵX(qNm~zⲠVQ% Զtaz}'rSy~:^Rt$3!IJBܤ cJiKl~ԧ8[깾E3n&/:Ռq֎C]dAYnzSx}OdgߣcO5^y7UYkSf9u_:tt۹ L&//Qt9r<@PJHJv*ʜ%IJ/+<ʔx1u̻GiyR- jt?ZN9D*-."PB–̨RARB_m$- yf/s"˒%DudLwwUMO_KԼkLi,e2c!hP!@{83i2[/NJ<-\rluq(~u ZGk#V敽Axcާ1 _ xeg) P?_RikH]Med=>^8[qm.ٓEy] tk#'u̫q 1~$ĞRȜAg%*zc !}q/)[|lbRVî I\B}uߪ>k SZ3X?WkI #cF7aqF7دwGAZIA$m ,VCI/G[̦tooIڡ֑pR3%), >8vor5qmA#jWGo_&jQ4H뭾¸Zp1LP//2vcyAGw}!(pnСR+iЋSz]OtinƸfnyOY*w)zVT]q[ɰ5U( {zz>?'x9$"%bӯNom6C#?OcWܼ,QO~kKv,d3NKpR^PAuKu_$l4(E[-d+qľSIPڊF*|У${ʧd7 YmtB~﯁ZVέ\[tٓzDi 㰭LtRYH)KO)  )5E->_x6*X~';f#{ 2DRb %⥄Zɭ/%x7;T%lg蛤<31>y+&U+inP9_ۼ#a\\_e6\גJ qէm]y)G~᯿ľ[%*\F _`KIyIC +S梛;<=KļWnʖ}VrY|)?տoד,ѽrI8 }|h?QjKgH7551 m`:?Tx'6 9Y#(Idyug8|WB@(P @(P @(P @(49߽Gy`ꏦ!]v&exբ|&꘏ . maAOw{{MZS|F^4xgEcNrވzF9uy.lMqȥo7B\G~~sNN5G%[-Zw.!y*vn,404\OD}.v(4w~Nҍ'}9\ԡhi%˕)#,Y<+\.%>RAWj;tRA "f£QIgx4C?hl'8Ss=tPrrs&ngۡ"K1#72 _RRaӂ:NO2^1ߡȻ5͢["z|O/a^pXe>Va-4SKS!-[m.,)<|9FjIwU뿯UܹpF31.)-m`g%y-ЏMU|x7yEy )?۱A.$t*qաRi>^tmʼ#yugII&ԿM)O2[k0#ҏ1~9{nC"{PW)*II5=XhX-S_5(jE)]tֆPgE8g)}1\wq8lJƤ%]6 'G`IQ",*y?ޛΞqt_\S/ | a]m}R^eiZIս%V ./ "yǥ:>xLo**wʅVgmYqMQ K\}qw5X<ΥB> ~ ZS>ΩNOiF _?/|es±pQOmM~m?=wKI>_èԛOY]W-$/aH]);YnRM{D&{OgjKz\Rp'[>wQ:M±csz1a!$G?WryO$/gNޕt" ;lEr3ڞ J~ko--,rަRkVdH|WAh`PߵaYE½gpN^_ʮu/r^Oّ#]s%]V{#N45_ES\]Ms%ː?+~n t͐V셭^AQB@ NiRϫ"VU%g"݋"tGƵu$pP-$ܓå-(((*}uO\d!.ǜ|ʌ9v+ٹem.-${a$'eZVZ2v)GSlt$ݫ3{%U~;2:_Z;-.@ J˿׸to8>(\(wnoT̄̚YCn9w{RW}E) 5Ƚ\$x- %s͓`ޢ&sO+SbϹwbaY<:Ӎ$>.t|m3<{rg%̗]yV 6>BPINRkC_v:SӍW%lN -Zww%S~jOeV$,e(qH֪T2]k5H]@~/i#b\tnQ{QhT)qDpW!P @(P @(P  iOP kP#$Va)<$e&,kS%Mr+;6Bk^m͌'pH_4:xUeT˫iΟg}L4>:nw eJZrN:,MKI4#Ekjt*ӓ덟^S{Σ{R9{O.`ޜެQwyYy0mYmy` B>U5t:/l7Wgr3k iM R676볎2,dg-џEٯp ٞ-[k0RRŠkxתRNkKh^*ҵg%+x u#=rpœ쟄ւqP=y=wE)-W~R: dwRyg S\5 1XO Ia,0[y%d2{ QMCZ듉I5qw{T:Mr'fYnClYaH`PLXK"#݌]i¦J a KzЫ͍iN/l_@w旘R.:y۩蒭xA˜i"d ]B[S qDȮ6FKӿ,g8Ӥ3uں0鋓-u[ L&SLxTmܓڝ:sUF]|M~ݽ(ДdĊxǭΑ%xgCF[?# [qg #*OR÷(-섏k%C@vY^8r-֭+-=5I.icJo[Zity&''N[!2.fO:.SHTwu#앤%z?*X˛ ڰkJ/fi4-F H:!dnVN:Ы\dz{קĥ;Z3PHR#`^2VclP @Aczsv,Iԯ5ڬ&\l  #oo.O/Z^ՓB˽h_+ Eψ:E|>G{nxS:?KWU쒛oļhwYw_ M&㒤[\W>QY?'ޮRlU"ƹ5 `ծ?ڕ9KB<.wXF>_a:iЕ:_Ru\n7FR|wkkZqQYVoC ;:aVm3sqeF=M\dH[uiKJpWzЅ5*V)Ҥ$ZIYGM8)95]n/-\0/1frK+m7%JB 9WU'?//3ĨJ4󟾥CJnIz>QG]ryɲ6x"..2SJiBVJA(*@OyJizjPR-oF]XIF^Ҹ|qkOؒ4l!>?Ltp[A[;XVq9HMo*m,Ҥ {Ӳ?O^YZlci^:X'wi:V%fj(EP @(P @(̜q-7)iw}/Kp|wF聳^__jl=GQv_^?aë+w]s땮&vq}y`oaEK{EJkqOwV^|ާv։*q׽ZNivOI|7RWyhZT^rӃൡ49Y4u-ŵ-D|;A^ӈsNKȖhc\`E?e]_R@;NvTpzxσ^Hn[\Sgzx??"J֦`1j$ʂ6ߒ539CI,eiY3*5 NUYu}9#"eU3%`қeI)In'ZOIIߞ>?w,zy6Ч^<|Kv hnZ7[-<˯:md2J|[TZ%3\VOKl`ԯA}VxO3lRCiKȷrKNR JJʴwW3Wƌ*vxx΋NWFγ̜WL6L$zc[862Y̞ \F\v\i‘ڗ>v@~)²ە?7 ${2*@ҊLN!n=^g]a&׍̣ zGtݙYx_1R݅X_9J V(mrYSS NʅxT_DߏS36w>aXÌG'zuZgXp9MeZ@)*ZJVUpe'׻k]sjW)Gx$ԙRǜyW⫇-a̹ܶ[Ov(dJ*#Fw 6OIڥ؂Vo*7UN'з+Wr~93 %?-(Zl'ZPY8)8,aKmtԯiJ QЯuÜ&y(u]V9ȷOA"AuAȷ/ˎP)*ZqmAji9EN8ʒ+V1U"*Oy8"^6䮑;ʬ=Aq@Moy8-ג\ b$x B~BPS[\N(Sƙy(ҨsȮUs>9KkLytiw1B֛S(q96EiN9{4y|rXt*Jk}u yϭL-W6>%PSGS`|UztźrRZlצP _l!sYKZ[BpQ }Z~۩4I/B~dž>Aqm %Og[.: KY FXÚnI;$GJܺ81{3qco#cDۄscjZ GK߬mf5^xmVQs<~RU:Gq-n8fE#TeDn2YZTmZWTWěR}'ZնiʤZy߷ 2{N]<*ɑ&/6Jbhr< m<ˁ+A B|~u:ÊV,2]ok:V]q]4:64U5u!)wm깬*e?5Yh^JUÄy>Z>=WbS_2o2W\x+[CIpw! oÈKeMKXY'DںoߎhVo-r&^b "sF!e8n֥en-zt/BW:U5s:z`/2.=~&^SJ5wں8N5{Bj jwG_-~fݵ'C>/_k+GY}L\eN̺^n yהOdaB-hP5, 6oo$\_iA7ȬZGGWWv$,-A2Z|T^M0QP3#Ez#\I;#c@m̖GYSg"V*@(P @(P @QܲvFudRjq'ouKEmIy mu^402d4=2jY: Hm?#&(q+sn]\K3ù/>emNނMh`OƙaټdRTc;'i H~n{3 je?"tnccٞOs7KlOsNܮ2?!K?@׏'ySQRKcUymfcoWh2P*N(% ocGh(FkϮSȞwB.J1냠>dR񿿊״>֬kگr];z\?2ވ~y|pVr4R0t>,xm>~\RӉQzsZ#ȟo|ϊf=&^.L.b&6噄:i-! IJ• h_FsyiWsF'}d?[=m#R\[0V`_ 9؟}Nisso)wgx.(Ti<,4xFi5. 1^B^] )} ;!*y4nPdyDxs,[-LDlZmH%${)Jl湟8]+Sk 5ݧORQawL]nHιO1FaqަU6y/OꔢΆ>»0iÕlQ{qs>jήOJު8YVaܟȱfYu2ߔ-?I*Os)HHPNIΟ4J)s>֏8me7$vim.ΝG-b~$ə Oyeoʢ@VO\gw%JZJ׶9צYYo}osx}voR-rO#}Y:B clۖܒ<"[KկkzwVZ焹K_^+Ni˒::``VOsCXD ܦT5#ijI{2 :sxly!,`yf#aOfζN5UW) &/^7g;e %V̄v$(gqC Fm/XwPL,8VxCY.{SYuk!.!!zPOW*ME:-2>+]V#Wqg\=-s^};/g]/4^%(JJUYTVk4N{r~.QQQrl?ӋJӆ_?YƢd53iC`:}T)oAhB * gGu^\޾xȣkQ8өJ^*8].;-ەCLToJ|'KjX\:y)z/M9XmD'n81p%1\1ȍ|udDswFM-IOxPR.~i*TN4>.gYpOYLZR\f2J߅! iwx־k29J:>)ƫfZ1~al08. \q ,b1XX_Y2S?>ĶA Bb2k.9/J+v׿OuNd0,e63_dսtJAKS+Jq+y';I򽾤Qsm6{bHyEJn/~ZPWHr<R)EFg%~19+"͒Bjltv6?NBw҉i&ބs}3‹rKx{S.1nl?/ϑNωea4"&qCT*>۩I:PFH)bMXy!->~ڒS'¿R…rMy/bqȠVIFVMl̪䉈~HXAʶrXrj*g'y_x$p#?gTd?qS?ZڶV0[D׭-K3 :ַZSR{.GY$}|V84X8.%Tke:qM#q#$$7YONg6p;HIjh<}Syj,4T XZƇrBJW[J91)([<}0#1N<ժS)D ) m#5ɕHɣRKR~މc+O{><!QXd}FRtMkr.qp /cGiA=RLw~=K+:Xou?Զ$RN|G\vLl牰r4$^8,ɟr}(J[=kAR \*P5]V;_YO1[ uk#{5nqع֔*XH2\ u'Zx<ڸ*Kd zTqS\bo^]-R[k;OSw8}@J6ҥ$[s:BRehm*[1mPqqCIJ<\»*\vp/D)ZwTS= ͂NP@jRM2Tf/I[qqUڐ~C\m- N(WGoV.2ⶱE^(P @(P @( wqV,O2e%`%#'WB+{h$ܟ%gZ5+Σc%^n\]m}氂@_"dn)5iÁV>ahB4Iu>}ZiEF-|R ߖ dߔ;kDDzJ>)k;'<>s.8unj{w8qUjgoR;{-|kX+Ou5|QYY{vgsm ("B4w8TGyJH)iBҭxR͆hVʜyYiyTc˫Xnkûzz~rUsp]*%{ј^z,*<0f.R*aGkBxU]g:e"ܩSbHzqw^9nJ\bie<V^ֵoNuVFQ+ mu%ͶGʭ"*rЀ3?Z_V%k TܽZmu鿆γH*B%,F RIm$jy:6qQ(ƾY)-`Y㦌JOޱ:fpe'%Ԥ}wShz-|5֗sDJwcҥ˒s1)j1VMz;Wiʜk_ZzZN8z2 ˑ2uұ٣z\Sb>b&üceL|Z&Iz?aFmrjg-'w[vkW`*8;[-yROZ:iKsI[V e|7?<~lJǯצ"`+(HV.$/@G<6Xd68ԑ93^(:f m<;7ߌN"2ARêSM%nIBoa+SR_`rp7ߍֺeax]Ua&ԑt9hK1y%,a;R\ ҭudo>7weg$wSwѿ:ca}AuW8=̋UᜩNb,)(ejIG[CIsx,=6؆v,Kꈃxߞ|%|v,V<_5Ek .㍼R SJ'U+nuu2]MZ UdpȿFe$i@z_<zVsڒSPo5OP4@9 ufWd6$JRjSvMA^Eܷy;y8'ĮUűoX#d%<ʎ\Hx/se9SNyӣR}9̼ ;5oBUݏ} -{f{5ZTwzkv봢Y>O2uo_av2%Et\n$Ci%<4 ҝT:ڢ'cqwUš%Ӯn8n9Ǎwk=n!k0pr}!w4""BTQgc4(N~O+8c[~'%,BAvugo$VZ@aQ#s_[Jݣ:gmK Ca!URQzYjA<;X!HsISLѦR!x?:Rp;u] P @(P @(PX,vlJ-$Oҗ?~^B+e|=N경?1ÐEryB#yiBZѬB\^K'ӟD܋;3W.3v{1 7 Tr(%w}Z!?q_ʛCMM7צttpH$W<9xF+djkJIhwx Q\/T8wzԹro޸-%ڡ%ջ6lUUtn̸gU/mSrQK$>>;:6ked[78_:LXynCk~kQBhm ƪ|5^eu{]py?HW1 6g z^Dsb Q]Gfm))Qij ~9X8.hˑ^Ra}.XT;臧O œK'c5{qbZ aL(%nT%J2sլ쳮cdOw:vcܨt{W՗Fzcl_aڈպ-H`,!!+U@;^)YJZe^^]V3oA]Ú/ k6%멎n.OojTdȍg)"{)jY)Di-TOׅˌyhmpr]>1,sSMeÐog7}Ա)Ƥ\D{q%勂VǸCoGJ{ߞ5,hRYM^ᦓmw٧hAO%=GN-#^ŭ²nvywIQ]2FIj:RS$ɐI!n0%:G&$|Q˔s-eF8ǒP~!eX0ðgiZ֘b<; NiJpZc~䰳r߮sR8\A7k[VL"Nj[-]Zj "~{اYt#p{;#g )ī= >>* W S o7 y5~cCZnF,Nƛu~vF UT~&qZz#.;S4}&\a컖qxZ8juJ/56C2\Sij@<5c t͝ЗJO?o?NX^g̹&5&^BeE1{Ҕ +>H'58v4[{v_%2_ ӋKuG>oehcxDdJKaskQ?My~+?=ݬ]EZpuܺgŷ N;ۉ3Wܱ՗?ٓ%MkYI0Z܅}!H+fԋ]='IrkdwιR9)uìZZ5oy u GUos;liHP @(P @(P bGlu4W;p~1êMy>x'iq/&fl²YXvM ?/h8~Ac_ӡSA~Y(ЍH"K#_\Ĕ 5UTbK)ѩO Sy)OZ3w?&sjF9-}fCkzWe&=CuzD{3 0Thk[|Wz?yf^+piIGϩwzVsx̻JARd埙fIO-=6^;B6(=m,EhEVg/}KY"ö\{!R.~ 'Rժ){!/%#>PRbƾ[u%{:QtZǸ.CaOMU9h-a}}ɛr”vog_[s[*<zVm:!Ohew#Y͏.j­t ~wπ>-:nHGEsmn1lۙF'%qݠLY!ҁ/m!;޵WoI(qypJ}9u%`L+~;b:-kNJԳTh>^:O5;IU2A/Y*rϙ86\aLIYԥqZl!@e: *\ߝ%?B 4izqWo朶f"q ykw9]b# 4ӎ<$PiZ%'&xZ<ECVgxn]e=P[鱖tsp^GY<cmF.HU: q(HUyO-x<|[P\SzG;O##9C_6<&ReG`pC:<\5Oq0ϩVҝ7N 73in\ frlf)ƱeS<8u>#(+V'%6ѵoU aJ Y,8u-7\ٹ Ek%ɹp{=xBVl+ʚRmw/9Zգ$ֻkH3=49,\# á]͞6KY[V+@qp-ڂ֮Д\΄iC)ߢi|.j}Ʊw3d?k#Kq7!TRvKk*NP}K:k2ODG̝uj.PLEqa: `. *)QgBo,+X]~D}G.M6$p>Tr^n*BjJH*7|UZ=6UNˮ=ZdEjd~2!*p7vxf6yold+k˅/1N;WiL8g'lgHSP?}k(Y^p,189D"4kW(2|VZ7-O5,d b9rPM+! vִTaWnhXZ~N퇲2Z:tdm2>Qx$νʻ^j=2%yWe,%k%"Mo_,Aتui)E:uj[U!2}S:|bHJrpF-e¥MJ@ A&G$uuZO>hY\r(ns$zzV(Ƣi:qݡ˻URxwO3cf]9g0VxU. Zб22=вC^j;Roo|'%KGW?C*46rmj[}E6{]+[mhZ[H??'rcu).D|U%v)n;]9?u_kGqoIM6,ү9CDL>,ȭձvøީȻZ\m5c{4O%eVލ>mWh=L를Gx'11sm\;kev*  GolPM1q7% Lӊq z9cLE_1MٯͷXLܤ (;^*㤥%63qonӖԳpNgpK 3-:ڀTO$VhQ^zzRpG׸uM~M`]C .z.#q^ZTT[C}+jeJx[~m*ǯmz_2F難\ ay1{r];1RaH=:7 n+pˍz=-DzWIv>n|`G̥y2Jc!_R O?_]btI,qZ~,4iQ Aג>|:ES|ڔ"@S_H޳ޤRЖjQ!( ARviF6 v>Q'kn\}uLĦXJos`iG*p-㯫>b%#ZC]S_0\k~U;ܣ]x+Ʃ"a/ u12ݏP\HSy/nftSI- zyGν*>VU*\~]`%QcS3ԣקg_ kƽC!Ź5̵O+ǐڶi^ʾSWom%ouIѨO*Ԫ8w}9:Ѽƿr?Zv]ng;kphRZ唂t+p2-&}S~KSn%:NjU*M6GOy{ ໊7[*RN:Œx5gvIco+'7p?U%yj-ACB)*B?5|C]sx'}?r>~7fA\2njMm!ܢiܨ )I PvS::w2v㷁s/W=V*#._Hpا*be QK6 'lJ•(Jo/$3ZjRKC!g&Xy#w+?9eWe2!%oRNֽ(]M{K?=g4'K+v8Vp"ՊYޔ El)GZUVB Z3Cq[}A~mMcc;!8RLMi(mԔku!qMacr6ZeI%dgnמ,rp/q5M\PlJ5!h/)eOTo.4eJ4⥌/ʄVKO3Foi̙ɹm 7? cDB"Jo>^BrZL/Ŵtܹeޙȝ }7#97Pa|2B}9K晞['⧧UJQQRm><_49u;W=gtl;̘(ؘ ;!fE1-n˹66T{{W2O]yɴ\Tl'뗬_≜EZqhQh!1=ZԠIQ U$mjG^Y^+ ᵍ<k~εW:丱x%8_}-^/ݭ.rDSH*Kzn}y<5zy/'0btb˖Ԅy{}7zvٟ/G*`-eQP$(IUoЯZܚqu͒$tmuBr%YRIJK!y){&xR^mw}HjЕ)-sY'cVVMqj\X?t_1J/*/z}KYÙe/E%\Ke܇̮½K*3ˊ߸ gH)|(HGn-ZwkI,ɷgnY`QfC\f2gQGrK-BPuZJ|JїW6SІeƜuA;%iY?-~o[oWJvj;[z4yz,nc%!S'^"tR;JRirD|AK4wv1H"DD]~P)c֔>^/h8d)XJ\;Em=vIJweguӏMlyǽ"٤3+Ara[%a~p,Ԝ?q;kZq%9Wӛφ"Ņ7 2Cjtӎ#cFt+w|fącokl r|SWi(:u`=٥jyk5(=yk:.%۝l<C▟y,coI@Z!#[PS,-MLg4K#ޤ:bZ|ueV[>AO >q,ZTjRH)?ǽMr4Z5]N $kA.Ag byᩚ@UBקSqZLˋ_ YW|DuP![;~ʥθ~1cǮ)ea>w`~]Kg}A<[׋Omke<,%Ťnj6h pZ$+2ThGG{I}[eWogX~OCD\"; D^B Z.픣8Xay-SM6 RIJXG6:X-q眖2Wl^?PPS?R-7,>gk6)6^0qHF[q%4q6b s^ڒIgۛwں--7{>xSxy~4}NyE8Ьi kSz;D)eA~@UkX\[:k9++}gl%wt[%r_Dxëywmc:b"|yrudYj. sFAJ? uH?'l|#}9ZtiK mzH}M'Fgɺ 2v^dtBJv \bTTY%$&/ďpJ岒{IG'5:5ޟf1t16-̜v=ٌ R]Iq=Qdkv%0G9;Ie:'pq:tTT!Іτ$XjQYZwW<|qk /By t0^6zCLT[D ʒ]e{)u);S'ԯ(JanQdnd嬋%M8kM 5qGxCFݹR6jM&s .;*޻[m!F 4M븏6nyceL<^R{Я lR~uq$<껶fx2+:c;O<R{ Lpe}N%}>>H5ϼeq8-5lBFLȜS5p}`FnA?}]2\PZQsrR1_Ytz^9q!ٖ/o+iMueRw@X) ,r8Kzt%W齕QR z[pLgVAh:92ȩq3ZGjZq#`hWZ޵gVXsz~3?gB|)#rIlo/rꛯ2^~0{ =&M Y$y[(oOj\#D1]&="qsYY[Yk)'T<)/#CS/̪W%[].nHCL>L6; :ׂи*a5t2m] 01$2?sj)R92'|9L̚ r\!omt6Ii+j^ګ -/G1ʗ|v]>_ڮVrķ^?ee{0Wlb^q~8\ eIz4-zݜ1d2=9xK6$Zg.Ko-T6Se\%Z4ҤҔ\II,SksYԒ)鉮"9s!KL'FWquo8"[<(Y\i,w~|%"IB 2ʌRi/XzwJrR[}0`?t=7Rmh!/څ-Ay+ʌ^~=N)3Z qݗEL?sbRi=u JY;%VmIS6>T |ic,R,2 k]2HpWπ<5?RgPwU3ItG¹:BL?`­#SUw[*t" $㉎\5()ߞv^vu|ՍJ1mkҷ]89JTu׍fJ*nuӴ6ϞС^Bڭ 9k8dJnf Gq2T?"t$vtM%/a륩L_Lm.Mp =4|𷓥[{`(P @(P @(Z$J4:YOem!NFAI' ~{?pr?eEFp i c|2xzpOY]#fv4ଶ@:u”|ՈK1RYn叫47j# ;W,{)MZ."[Z:*KeGCgƷ[Ur33Ja,o3vJHaz +%4zW] `LmTw_E#CROr8kVpOl׃MÉT[WFero9\9c|+ %ĒEz;~+u}gZOy9%XOCgc/[jo!9%;״տB?_ǡ"t7kac\^-ǘvQv} M*8&9= |! V [8Rc(/F?1Y]e]OR[Gf?v|{1Ugc#' R3cq]:yOkA㾍~>oi(44Z\'Wl+Pd_P\u{ueNZڔRvMBy0yv;FI?-MJOpG/Nn^->Y;?žQuwIzT-ss4zqM|Uʽ 7Zm\JNkCAE~:w^\BwrO<ϑ7xgcَ1L⎌l{eDҡ\-wjK씤kR*k_ܸ3t`ԼZz?(Af'5#OɈn,sdk=:78j9',b޳_~o J]fۮ7@+f@ 8ʉ B@񵟹ś;W׮m~:FKU;-/Z~:QM~OO&Jsg!7/l\e]S{Hl(D(kG{x攝8i>oĬ-ԣ4e&82&:b<ػL㣻`d$-0^SMVr^<!~8/]}:.j^ E-Fj~.wa/,og4>ǴzTW](j/xşT_BѓY7Kg|#}ɉ02QRT>qëi;gJ\Z bt܁Hoړ*-&T{o[%D~|T6%WpҡZy2O{(fz3+mIv-ˬVN'HGc@;M1bZia$3t keuSZbJ6>ANkBb';\^>IZOUyzgÒ#ndRrㄑo[wl:y%?SeyQάf4gקSn;s?ebeNɱm7gmQm};ZI~JR婕zw~grc_}S`l̺;}aYKDquYSR]u+_V*I^gCԸUV zw0r aQuVJާ7 6d̬jn0QJARO\ gYTKU]بZX?_#ƿ: w9Ɣ%HZlGʌeWYq'@nnD\k)-6.$m~u\=$r0O=2uyb$ZwW _BTII?O{h;Ў\nȓT 'J?GS?ɼOʴtuǘ-{GꗤOJ?ب>[o&|KT~_$QP @(P @(P @Dpe샌nvʕa&}H5CѩZjZ5r,%Bsy0䎖&Yo/;h:a { Y )yvǑμ)kgtc \m[qvo}Kk`\i5->Q/E -hș\ol.IW`o(RPvHQ~vo;5巢Ֆ*ӟ) 6'}iZ3'r[vxUE FԲ@ylWoScLv;oҍ˗ Ŗޒv@K-JROа4<}WU<7?qMaD?q"tiD]*ji)0]|1g5͔ fGޱQzlE]r/H8'&aH),;NJ+sisRNK^~zӈZѷTjżx Eczcf^lA3'uĶܠ%%|.qSm0 [Ƌ/[I5*WmFY%޳yg*t_߮5OOCsf0bJ#0H-3GJםx{1f,񗼛NM|tH\N/uBF8{o-F6K3ҧA0Up)\ܚ, A5pi^|TPWWK~WkGbQķXoMp|r/#5vFCGT8;aŸ JyK^D𣅢:tx8ʣaTb_V|ux^2I kޛ@-%%-´Dy$RyOüGZzPg1_㛲.G9rJwR>i $WUjݞvJC-2zͤtϙtbo\ri\m?N2OrRvF2{G*=x13fWVj =R}N(AOpHuKgǢ:5(G, ޖ`[Yors̕n3$H%_-@vyN#u;zI/#S{™E2&Yr) mуj}QҹN:y&aתKOLKp^5*јWu韆@DvRV;ߤ̻O.ʪ({ix~Y_Zv;*c̜Ә8DkNb-wS*Lb-$_HNW渗<3َ*w/[0me:,/|csNX<-{[Ǧ%O!u_,ė8GNo-+gGcUl!SIFr%h5*ҕJz/23 sg &x8jevԫEK?%i ~|k8.=:wwu>*~-T=xZ7\wRWЦʃ R4>NNNqq[ӏ᧯S?*Y9;ߩܓsNK/V9e&R w+I'dx]/e{[RWjh~w#^V§|3Ԋ':-:>JhNJ]rsˍp$@q~G¯u载g+G7oG_;_޵SמZE x`<{;=<)mN x\RN{\c\m5 1\,=RK4:O.۫YvծS$ۦϐ|w);qKT$|;}g9iV{eG7K447y{|~zt;sf1uq>8)׶Dy箕*ͬiԷ+^\Z ܐ13޽z|_c8+3 >!m+P.-N)[BEq89q᳊gLg_߯?׎`8=(s2U,Kl됮LPRvj*χN&& b8=Θ,Uqb-퍿~ܣwv7;>Tf5rJʢCrB!N%I BܐuO:_igU;᭶g.;*\/,2mEC2a+YV,동T S.Jԫv3h)w*mINձi:ѓMF?}V=|59uΥP+hƞzvN:8ɡ9Cqx$-o/dv|$/IFEcuBR^kOkkB SM1X^fy3\}rJZR{x־*6ܮ8Wd(ؒW }ZYlKc[RNRAتUmI,rt*,a\u6|?l#Gzz%)`Bj)ɵ:T׊G>j~]gfm6_3w\fJu4Swۚr[k.+ԋBLRRԣ~jtLW}[H+#VyEipڑ6t=/ v6Y%-'oH66~椥S܎\>C)%{%݅7m!uBIyJxOMz|uӮ3B7-+>3#8Yq1n0eIk|h<ԙ$6BM^\Vގ#u-j/_~;gClZ5 W^}OA 0p4ooXxvjwb)BajPichGȫT.R۴8+V&g?}*՘g% ~IQRK3D"ljFc=tvC]ٍդޝw/'ży{2KbtsSĘf369( !{}ڠqo* w3I<^ S {$g4;3_Z{;Ÿek8t|ϖ{_{oO1)ל%gL#:_GUbj&ǵ[w(HpwH r  %&~p*t&c^Oc5p"W^x'y}BqJ"Xcxˣ e8e\"ZZL[c!}'_SNZ“Z7,uVucv[}m7%u L)b>YvOb km*'Z' y[ָP&x3q5iL=kC}dk ?Z&H},~4\H%UPJ׳qW^~'r77KfuӖݟq5{&?SGzTڶB#`x|mNuQ}XW]۠ÕI !?NQ8w[y0Ő?Gw^AiIe䏭'_?V9NK/׿˿BdM~MM,d\ ec{MT{{Zx2@o+v[ZVr%[ ~7.]V'>_Wk z2rs =9(QAKv>J)[hZ0;$(*JSR'$*QEz5`S+޵To.g3 K770hUЖbK}tiN. H<y{?fKUUY-ŐgWY/dJpmpWm`,*Tg _Sۤ}KW>+4]RĔ2i:4& ˬ$TJJҴwW]{^) ˒VtZ&qYP @(P @(P @|R'uZ4Gk(mlP9r7+(:;qͬI7K]KsWMهO"/)# ~E"zU*aOϖ6ehz@p'͝/^q%&O".LuGY%)%{':GUf[Ttg_^DuNPE?/M1aȹhT6 ~|u~+dv'] T< kG:ؤ6򈕥^˕wIpf)ǞTèӅmh%ckHYjFgUmרnL~_qglhMQ Bj΂8߳.0P t߷ޱ$#(/XK~Y9-y&X>H%aѯZӭ*jYEAVJ;А8 韠 ? uo̭c,si:'I[F}T[I'04M%Z4,z>NU|ۼsx㳢!^l2$N۵*tYI-~M<`ʼcMEe3v-n:?\^^cr-w"ݱIFM' [BѰ7jC-s%gRKirgWާc3z\?'r$zq d#)Wj>}v>{+K\BQX%rײ朒kDmrÅ}Ew.t RֲKn8۷KaT[PK-v/z{~vT(\TSIctw4+3|BJ?uW6e{UXqL}q9F3^7٦s|/SBb`QB6Rڻw5Ψ95 e=ELzv7kNS\nvRIWʒH'4=<|y/5bƜuam7 oonbN,Rt7*xӹ\X\q Ӓ-3I,rGp'gG,do:¥)!kˀkjCι7)^o\BhQT+J o-2D_ּ_7.+#w-r>#dD-ЊC I/ {P-J2)gf22cK: \7#o)e(z#FW{PGc$jĮcSX-Zv &?N>99&\0 d%i*+Dy+TINµϝ=]g9AލVzp0b%%._1dl%ՠ%@Gz ~^nX\Zs*qk:jg&_*t;Riw>ShLZMgضIv6J6{ViJOa gnV]WR9C+u%)~Vz}b-JyǗ~9-rہ!i?PӬ^E_FI%-zʕ%']z|>ob8rK%͉+\yQ*w)WeGJK/2>\a({st }>qIQۥwmQeHܱR.K~$mAm^k*u<iTYL:(QV7*ZQ8" 5SL6K*޵Xu 5/X%ɻ{);ڀWv}P<#VSW&Bc}0x`j:kVbTj,LӀ&fԑܤ):<~eNfMn TIjjT|^hGo nAc˙(^OVxeg1`|-!-=O% Szt+[{ٗ-zP @(P @(P @S2 {۽@%_ tt?s[Fׇ>%fq^2KRwoq9đV'ʓF8)2$}"3w&jTɯ OoN)#tr<"IBw%Xp B[ɵvWzbW̆ %M:.G'74ditqI?֛|&I27 B^64 U}J-3([u*CݐˋWEJNa69rl7xY\#t=ImBԕi]soRmHL@ϱTaF-cWȵ:ʔXx#)*VWMN)<]>gfW652HV\,x[>Xr8tr=:uӜRK[^r4ygN^\8ɘbryG!~̮S+r ؍zcv)?NJQN=6\,4s]ړPwV9M2F⮬=5:pAb4ȃ\Kxy)d#jUmQypRic;-[iaDn(Q#?U}-?*]lS%[(pN}D{}I b>׮|GV~^3e쟅K?"v'ϞY#XjU}Y6NIឬT;oX0}ROjMmRu'T%9dzS.s.XZ!s˒Iԭ~[gNOU9`hG6$em$>kHŕƽ$#- bu! ?[KC; ue uJp?#P=ͺRO|Tnz)jI8xm^S!{RH?qP -Tѐ,TF+ZS82IKV @(P @(P @(:fluFi҅CqBR,3h}K~._8Ә|>’@vlhyߟ\^ϫw% 7y$ݻx1ËW ӷ; w+ev3Jp߯Oަu u.`kuC@UG+GO++R'@_[R wZinBƼq"-j(J~Ỉ01z>?_/r/t*'lKac';qc_Wӣ֣tLJyx ?;?kcB[M|Zi1 a5"Sl?8Hk[_ZjxI12t>ڶTA;;dS\t##gvjROwc#DG5ac89GL %['jg 2,PVMeI3{g+Je4qbBF }#\:OZTG.mT|z8FKY [KHNϙ64TMV_O<Ǚ#~?ܕVԩFޙ9-ɘ]+J=$h ʹѽi0~$ڤdni\7璄m:^y׃W]QU_/J\D6 ;+BVZher]2XVAm9&7Wd"I}+Gz(VT.U;V,#4yG/r"kW]iK)$xMlNѕ3X{k ڬ"CD-'DlSƋX^|e5׏rmQoznIҙ?I#?E*rxEZ:W<:dᙦy-ve[,N5 E_!R[HHLݍp?T*8ǓeocԐ,66w^ $,uV/~%}uEߋ\÷^X%2,A#6Ԕק?GH6_K)XvqyƖՕ Z/>dC;qzv%¸;BTR$dxƴf{y.fF.-w?@#v$GV $} y=@MRz9{?b7޷ռ4oe`K{Ϗk"#6ˁkHG|㔒z&dN܈C6ʇ |U9f8X3sim*Rm|UF矡-zN/wrLZĤ)I$$ӭwu9𷨦1[[dIG鯿ڪ2ѝahc:BXC'εkjs yVΛ>jkƆV{jX/nADd$5jӛ讙P @(P @(P @(.-RGjiMeMP}16d: Z61W6ɪZZSWWM8q-$ |\gzrG>3mgIAa`׳rЍ?JAX NƋ$aܹh;={a6WŎ*G>ժp#IS ڞ$z:?>Ro9#qYޑ(p:||zasz>VL5"TsYya5菠?V9 cGs`9:F# .odQcHI)OqyibTc'5Y!_:Fspm#Nh–5OVגT_} ѭEEXYyMGi)ڻюY\G!HQk#Φy=%M%VT}E;􄝁 ivMi/M^f$Hp}${Ʋ͟1$x5gʓ4X676{,šecq*+·Ϟ?oθ\Vj-R1urkqmѐ75ؓ[$Ui )*#gU55ZyAߒtAYn+| =L7z 1c|XcZ/ۑjᐤGCq.6F>Aս7$"^*r1'Vۋ. KOHX*H?>F R HV#']6ԫdN~m.S4V|:3_-=ꧫ-u,6HxŖ-"b4|ӣF4-%e w*ANvN Xpu.KS+PIlvD$;Ii)WHgPГ>MeSKOJ*)|w$QobC[ LԭxjҬTo5.Tm m@Gե8i ?朧Z;eRJQAJqْ;qmd5Х䜂H{Bv:z&HY;x'^q%)YrӾZV'2߅a4tc*yLDj(4m6:)3'r&P @(P @(P @(Xi0|(AH?ڣr#9gV|6kX#*r]O+v>:SYS/IO_7eL^z~KIn]:'h$YɎYvG2 Dj*X&FӺ%qJw%½s'3'r[J JTT婯3\G-ȱ߰9 III%#fJl5 }ۗ]r̉֒sqKV&L"j}|x< 9k)zur\+CJZ4) WeռcoYEŎK>qcipv$xuk| Itq"wP&\៑?άY[Tv?Que,=M9xyo $@ oIxg֑F+Q5ZgWiHivƏ71KPg]?oɎ)=oFY&Y$ D9hܓ6oCoy=%3w{hI{UzNӊZN0vۓz8z&$c)R?F);5Z\6cLeL I)' \&)#!Tװח&ݢ}K[!{;ZA=??EJ ݈n KSLm_b9$k>~Me)sӏ\iHDrrŪi`7O8sXKJPkJx>Y9$+TdmF5^œq?0~v6ypF`BHc⌺}NSƍ82P @(P @(P @(P @(P @(SV0ʁ~Ug=|֝<r%%cB] 4q0W oP*kX'u?h ͫRѪ%]FʴYRq)>?ʩ~7MN70ٮ%OXORVMO(78ui[*-xL\,ln#'Jz 3Sߊ;$RQV9a|*%~˪ I :Z(E6wCc[[mcg')c&}SiSvGAN| ⤴h+dS.{j }H-hoU^K:;V/!l֙:ן N"Em5д%e..=G%I<;̦\;x!/GFm\HҪ0RKJ[8-;߷זIxt/Vh_Q_G%Nr5iAg!\]o !xnf,Y$7Wgq Ng֟*lFiP\;B*wEP(?:3?]'JB Ei Y(-ԲgjIҒgwPԗ)%ϡx6$7kn+mi*NKDVp:XEYP @(P @(P @(P @(P @(P @(P @(a ʵq WȨF <}EF:3q[ P5^*TgD RUmm`4vR Ydǭ^JAl|~U=<8+|E )@?:v$]\nxfp 3Ay=+o׺o8ٹ?Ebۮ$⦇KOGt\zu))cqzjSVK0mƞ.qU6t$`H>}]R97x[mĂ6ւ4jyx-f[g'Gr:AZsՋ&T?N%e'dxNԙ[%2]0[Pa [d(lчoR$V7l6+hPn4x\bԦZJt* HH֧MS\[@(P @(P @(P @(P @(P @(P @(P @(g (>jt(ጟ=o}-9gД!"(A#>ԀP @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(micropython-1.12/docs/pyboard/tutorial/img/skin_amp_2.jpg000066400000000000000000002225031357706137100235610ustar00rootroot00000000000000JFIFHHExifII*  (1 2iSAMSUNGGT-I9105PHHGIMP 2.8.102014:06:21 21:23:52BJ"'d0220Rf z    |t0100|     '@Btg'2014:06:21 21:12:172014:06:21 21:12:17Abe@Bm'dm'd0100  f@P`\n0100 > JASCIIO08B00AFK01R98 @($mHHJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222w" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( (f hhC*O K:SiQEQEQEQEQEUMMiӐHm* -^mxc2eߗ>+)QE@QEQEQHHHͷu7VUc"<(ugPx7_kv1!_응Ihw屟=jdO |Tt$l%q[;hp$Nk.QE@QEQEQEQE_}Dѡ`$pCzzxkչפ'FhP4c'9]"k]AgRU,oeH+ʮI2ϒNGh6dZ(դ“Xp~KCxZ׷E) qr? Γ*5K0BՁO ڭEX\}owv kb,lWpqު4,gP_ԟZZonV2GveT{̊$Jw'ڟcFYÕyBzgkJ Tu%q N=FGwx]b d䞘ݴmȽs9:|sAlmM\{pH}jkfdHv`F>>{կZO% !"RB^[vbeMci_["K]Zŷ0ile3F `y?sjW, 6X+kæ.Vhtk krY#jG 90Ļ+SŦs -F9b~8+^%Ҧp'ڵ$ݚR+PAEPEPEPEP_(E>'ynq$ bppqu{-,nUUGB{(38&/ggۃ.fHr2qʼ8YU8jfӢ*wAk*"c6+)in-ydvާw8 *wPO3ma\VXrDT7ez xnG;q=d]]J?6iXEcZM;JfVRu}zsz8!$Ϋ!_9=};VL1w3w^Sdُ4ש{jO'i 31c]K=TY3Ȭ?yc}RWU|sj;O*AON+946o| X.U2Kb&a9 na\y$w 屖Pr{ l`108=R J-N85q^ .9^8޲e*ckbt6]20ʀg{*;Iqp4V {m6K5{@)~kt+ ԃָ_Z.hbsss]^!1I Tz}M6V'eV'Ò<<%w֭aQEXQ@Q@AU_R`MbV}7L =3ȮR'Fl)<apKVs(*qI9ο_bӮll/T޴%"`XC)u\J{נ?:2ʂ )8?kb١/ ֒f[#֗5&$6GG;ᮓg-Ԣmr4q9 9CڤztʽeO_AԬeV"y?)9ơߕMHc_$o/*7GTy5ֱD1"XHM9nWs׌|AvY0!:*2RCp9Uqڴ, 8;NvgA.KVLf$ $+"]3A$Zs;2X{ֶ{[}^ o9A;`=B'>Z-!bUH}S !!db8UO ˵fHXۗ$!BH0D(w}+qN,*!Tg 3n98A,cdG-fyfKpksoAuDY 8<`fh+z֤8_zֿkh^ H 0d5gu:j ,NpA6ѽh Þ7ӣC#3W麥oZKG S+j7]NR1^1I-m<7Br1^7H3]`qaڼG+I䁞ONQVGAzI{ %J6'N^hdxEbc!Yߍ5Q)] GO^\Gnq,6ߗo9ct 4K hhro ӏ3u}.i5θfL;g\`X'IIvlv,|36%GL-p\veG79&Rj[jo(w㓊l #=+Oi}Vcg!U }I+5H?SRrZ)O1G88wHHU=ztk֛";B1<|EfKvx~x&sk F֍ǿvHwMg$QEhHQEQE^B(7.j#@FQ?-iRKm]Gm ,K! 1f, *g z A@V>B>Nk ~U iӟfߕ}n|;[Gt[g!r"gO<moʾíK>cQdߕ86~@(ҿo| ='"&wKic|4(rGA?/&>3}S/֬~y45]R5u<_t.04Uӯ s3ɰ۶OkӬ>)tR <_{kv#{4Z}*`AU~Kq@F{REh (((((((((((((( http://ns.adobe.com/xap/1.0/ 3264 2448 SAMSUNG GT-I9105P Right-top 72 72 Inch I9105PXXUBNB1 2014:06:21 21:12:17 Centred 320 240 JPEG compression Right-top 72 72 Inch 1/100 sec. f/2.6 Aperture priority 100 Exif Version 2.2 2014:06:21 21:12:17 2014:06:21 21:12:17 Y Cb Cr - 6.64 EV (1/100 sec.) 2.81 EV (f/2.6) 2.48 EV (19.12 cd/m^2) 0.00 EV 2.81 EV (f/2.6) Centre-weighted average 4.0 mm 202 bytes undefined data FlashPix Version 1.0 sRGB 3264 2448 Directly photographed Auto exposure Auto white balance 1 Standard Normal Normal O08B00AFK01 R98 C     C  nX  J!1 AQ"aq2 #BR$3Cbr%46ESc?!1AQa"q2#B3R$Cbr%4 ?@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @   @ @ @ @ '@ @ @ @ @Zkg5;򛖧H;0򐜨%'O+Um<#4_Q5fڹn91\S!"ITHo%ڔ)J;A^yVT{` 7a @ @ @ @ ҵ:rXJ4ӿhY$''8$E:д[8?z|)j/.^\I#[}i''"Ƈp4gF7pw3X@ @ @ @ 5[GTW ZjS\bOՂR|ŧ P#ƻSitKGig̼u SmMR+nvTVJq "->)ԓ<% @ @ @ @ oz!p$K|>[PA--?d!;Ѥ<$ܥIVвl%BOͷA&5Uq:o,?&gRIOch# @ @ @ @ KƁs:#1@ @ @ @ ?\>(=,fHmRh8B6Q$q뭅7 aB~*]}ZGJ<]>6%j-91;;+:+Y̷*V9tS@ @ @ @ @W5PnP28pp;~^j4qQyMrv:[v9c:J(6[^F}uupqi;*'t9ˣWtW vܭ\ +0B uvm $' lX1@ @ @ @ =@ @ @ @ v57Ş`h7P&?qԓ4c#nvbp_*%>k3Jg4h+ҚѦu17lZ5;M+c;I?kT\C @ @ @ @ch3~X5+Mg%6qR$VG Fd^WК5Gڇ~t sNrZ$8덒Ry$U>ӹB~Rm#NjoQ:ҷ!.1 ៹lSQƆ]UYlבoTq,h ߟ/Sd{Uf9%/.*XҙIy (;h+^y%%*ؽp]֥6ǓSfixq _g=E&1@ @ @ ~"wP0- SF^VPjDfѪI<$xf71KdޛU*2J !!_(6jbI]/821xx{-䑷o[=@ubSvJfؠأ(|2+}c  #yZЯ*yMݧN2ޥq:~ !,T311l@ @ @ @ @^vV:+T?8N;^F5_Wl3 :r9?EkMzLz6QSUN!e-:ßP&88FXIRu({MNwgP=Ε$b~ޜ=5eʫꕨMyA$v=>n!YzcBQn[yK KJRIeGx2M+$n)A9 tD7e"D.?'3Nqe IAcFM[tT٦sitUI+xTK(!U2>Z5c"G2#?)~=4s_',O|0㟣1z)j?~T!=5mY{a-%gGwIqEw|/f-/CY06[IJɤ~GxqhWk{þG?rJ$ W_ৣ~Kw:\~Qi1?LmXh}X1oi5hlɨՋȬOGhkopi;Ļ~&o%e('rG7+ fn& 0l_zjj~LDߨ,;/14K;S$Ӻ&R&5>Yfg%?oO~ĦwF4דɃF'$FEKGH^&j^ q)I&rROeOkk^¶m= _kF$:)[XS(zqz{Am#u%#s'%C%ďX#,-+ZQRc=ieօV,-COd/4.Nyk .B9x՞׺*-7?g7Voi9WS->S>jp 58*zyse>|IzF[[5-M%)m;& ϜTU4qi aNTA#4nZF~Yo{t:j6K %w<~S7vQUvlL^Q&\+U9t#3+|a+݄۞)˷e^eZ\>wvrzO-#KbrOESN$k3LN?S]ZSVMN++)f^I!/=m֍%oZjJ4eQ^Ubeqn(, ac*`R3燾2r{wҔSq}x8Zhb/I)!`}A}&S/3&^x7㄄A!sLULj%lZruꌔJK:ZI { g9qlel8[6StʘBR[В0큈xU98JmQVj-w&}-uuYj٩㫕z[*ZR֓$Rce.ug_JRl[. @ @ @ @Q6{Jk6L^fw43 lZ{G7jVv5*jݵ8ֵrhΪzY{RU}S-ʯo˓d IAƵ58MMRXfkP/\˰۔CN2KjY"8A (b (M+{Qyꏙ":X=Dh Flna3(\&W& ΩX*]^CORiz"'vWJvGU#Oq叩K`F2O;XWg~K{&ϗ"*4Q_7/z㩹.̟'Oj%?kO _,GIv?K-NYevNIpP9.NVpJH6TM>NKY8Ǔ 5N{f3ɴdFM5rve7hy&#"XOi/5(_.6;;+ՓG֞*m5"]t9h}>\35B53JW_^rh s[gS/of2no!>(Dgʢ+5A(n1ۗNJQJgoI_0@Z{T9N%ΑX~vr>E?񂜺(ե o NtG%-P`-&uJRTˋAm8H#Io*rrK2ϗgdxKjsG _ |}ܥ.o̴xU(qJkm-u+,\w SE>7|=N꽴`dY")S<.&:cUjatƨ>B$ݭ=63 %Qbō'li){Y;g$P ӍBӭj/JI5byOkP ˡ*A;.ҤZ($wʜhe;McF3qig8[QLh[gwUpʖVeBm,̮]wIJ+I\jtz>x|o!pԟd.fM4fnfjrTj615J\Tt.APCh(RW+wmes}93$ M~rjnvj8.;08J%JG87TcQb8tSSaӕ[\}1-0O<n{Ve\7=IJ-򖰰2IRGH"DU:?"BӮٌxʒӘ޶訾MI3kK-ȉ+M8۫-(Zp斒M=_E|( z貧d^T9QKRe[idIXR=(ʋǟ茴y7gٳx"@ @ @ @ 9O3LQf5 ]K\HqCx&8{jN>%GC.uW~]_AToKct]ckTbNoםH&e&) >\wP8?HӒ؞-c?TJ JsJqo E Ņa \0z~O% Ȥgdŝ#PľR9P')8hT"jqN6/*}JSm9Qu6!)*5N OtZӭ)XQ_\5]{̼M3Wl%Y8i0&;G<ʚ9CJ:pK5x-#f!֭fvrRҪWZ spJ m#װծ.\Ŵ-QPF%vp#[BoN1MoڍB0Jl,r(.+HN!.Rk'DlSjoy>Lfyg* *?XV[-ʬ-QA-Ť(Y7A#,w,G)]Bq+' RIrϧx8j}(Y5LMˡ!&-~a2y4%U&/:z䈛?:?+.ƒUktgB&a#9#+tHy{IS1osJA]6zZjmUFOc"xMwe8<>=zmN5 Ϥ ~n]F]Cܿ734̳! k˅)Unll4_yxK&S=uښq=vv1TJJn()V eC8k]֞S\9omKMˏ8Em9HX,V\£[y{pRyOɃI(rHqzps(20o)F>ɺɦCxSyI+8mI8%^JKzR}mK;UT ٔIyJ*Pm =5V4NRSv9#׈eZ\"nN2Bi2V򳒑 VpN(SeJS [ rv(؋W}}ǘ;y"HO + >(,y,nc=^$),((_!G`ʽc3y .m>$2eUrg?L`NJ-IZF:1I\T20T'9!;[n`ȴ$ ]%G %/>X5M严3=4YLuNl; YbTXD 暴S ڒ&BR%\8fj[#הeǡٗzAFɤ&nWϚ&}-0BeA@􍾜4%J@ @ @ @ 8D2J%Jaf+mRS9 UJ757P§#ҕRvʺRQ3$w isWfd/y\RWK[7<&O2g2IQzؚBCI${(bR9)MBg͙Sa>V ?Mзfge6]ӱw.|BeДPԔHDHVqֹX෧6G8.wҽ~ev3EN3~Mv쇘K9hJ+IsꥆϗϿhPyk ~ NLt)f\3]cN62X$)#q~XC sI{]F1FIL̿,Ӌڌv>}W*mah#P~Ew.jH\ -V'>۹#te{UXn7(fgX[^sgޑ'(d}b'ZG4XJ+3_lTJT*) ^Diaˍ($+?'*ĪHtGz:iQ8& qD !9>񬹺lcM6y6&׽!MV Q]af亳a#5?Zrt74}UbKۏ¯C;nƋQ'nKH'qU~.nBB /~AkzWh6{vThR#8&NR ^hSQ(i'2-s^B@}3&]|9pQV=0Gl">QG<\SN JR@M#3~toYIf.Y~ٍ~&rUSl^em6Ia%X 1Gay-z,iM6Bli],IXy Rq>sYUo{W~$:;>uTҪЖ -O)KYHv; C`5:)+NUƒ+KZ\i$_9)YmoA*fYbIi7JTB̳A;C)aY r1ȥqg IŮkkZDgE<Q6cWSs4Y:{ܲZy|Ms,^^FbŪ6=)zgzԩ}Rz WS4Qf4-CȡTƩpN*VA&ʔ%Ң|NJJZVHˆ b^=29״M}iZ1bܺol=77g9f۴._-cS4Α{+o\4 VU嬶vSB5sTdܱ>>D㘧1k +=SRnKJoK֫TDU 8U6SMc JAaFwsPipߗZ1=sSDCSO,Bʎ{3=i(^ V#s'`5ztԩ\>sl' =8%u6ildg*f]9jF<:F>l$LLhVzyǔ\*F $ITJ᳹}-z=-qmkU*<2JNqGb;F2;M(Nf^F#mmbZ-"bj/<ir.giY\X@ɎO<rZUoT?r2#|u@@ @ @ @ 1XԊikSV&NN"Q28om*Z;' 3:F};DLlz~RFJSTq 8躕n8VUK1έ`OVk<̻iKάnl6$v‡%4\\S"MDrD2~ЗG|=򋐖* ue幉"U%8OM9ͤVY,4Uff\RY_$:b.k0zk+! D3}35,v:_BFwZdz?oɚM-V˥HFRBAG<Λ+:qI6o<}8go^Zk=O](ZZz8ԍξ]n>V ++^J>ѮteRR~S|.5 UİC^Az؜nSstݙ>Zl lji}?XTࣻǟr5u 5Ϩ_̶yxmN uDRgf,50n&Tx@ڼ!RiCs R8'&.F=V笚Txx"{NMPnK}6A˛ޔCQqMx6u-'SQi2?Sv~0(I%h'q9<i["HKXI(slfJAZ[/N%E\`URﱕj2{L\j]Ru+PZ pͺTVʐ!Ól1k#"5Z&u}֌̣!.R -$DteBIv*k_i2kbSbFc)4O@;zf0K}7NaKoMu[Yi@Rr3N)N9-R^n?.S C@U㨕Z $ {qDҋ]1Kf)8ܐ<rI@9 "B{i? " :[󹌌g?}}a,c1y[}X]nJM495*З~uw2XJ- aiJ1kJJI$~Z[mst#9<<~g?/^ۘ5P2 |lvӓ0JLY5ĚZi"^:jjᘠMcD :+@%S+PN3CO}4 *j:ѝ/^vuܹ/k13[[zK,SBpJV-q[TRI^[5a6)W-?bS$>b}|ͱ@\wLVh52ZT`-Ф,%:Isj\/1$+i i(8zSIڦG9-IvqITБ6q;5R3K3SxێGhTۄmsH}Fn̴.$SZoV~KsԱƙ]Ҳ7UrN2f!HSH`9:Hl' 䓓ۘPK(IRi2m궈ucb/""M|M_ ::sn/[c$7źax)y0^_QME_LM,][iͣ\8Q-FyH$qR:U޼|R%Hə"*T֢,N=3mr:cl*s1V‹Tɯ1Bځ:m'$=&f/a|lY8'wܡ]H̃0?X/nFp}"߬6/kHR8rLzZqOOĜk!)hT~üK*T=hY'ūMMjvT &ӛOgeP,) l e Hrx[z 81k)>-/GzN))smVuQjk}izYT)jYyPnmì0*i!nh5u+ҫO%yt\g?.f哧尹J]Uj~r\Syp hS(FR@tRNKԵKmeEPu-ֳڽtWi隔zb~rLLKX8KЅ% 澏^XWJN-aEp~$ZB.7J]9[f];UuJ=>Ϛys A$lAJ{Ei[ʊx&Jq%BZ&[N3ryuEM9/0esJ8 1: zll*y2Λz!HQ&4*yWVt')młVlYrZVeI<2>Ko &zo{UVԹfiV.7M$yYp%|q=>Z)y{65zrQT=,T--5ykS9Z@N;F/N {,hI8#$t>EӦ/ >F4ˎOM&]_ ,a* H I* bG)^X4[<yfeJwHB)<ŬdйK%k+lRi’m)B !*<{Dr:qr:(E/{>ؔ*BrnX͡(S^\JJK8pG!27q.#>HSR-92rPTyOc;zv4ڕ<*J㡲WWqUYkHի̵BfIBSPa$*HN@jQB]-z'^ԪYE,U^#KuwDQjW>2m6PraVn!+*4z6y.Vk)$juZjN~ed[ge͉7qm-=1KFKA=+)ӵQ%=?$۳l ¥#aNIFArO>z7t%EE-]'Y~ M3T-*RU(K'';r' Y ?3o ,'n ^}bj-vtz ,>iw$$''q@ @ @ yY(ص҈ v2Jak3ʵ[S$uJBj %Y(רK0jn[6[OP3.Jox]U:RkYlZRᝲMjZoKP+'8ԵZɪbbaAZKc@ 8H5%uw( {ZV^q ufrGj&:v%sri2uk7J+_rޱkn Wjx4gөOOx^^M*RQ%eʒA^aTuh-*\֕LdɇQK*PN>,3Ƣ k^ɿ%0W:g*F2^jvM?=>Ej40=%yI-I!N`O7ۦGq[zzp*J^*B?QՌeOq&Udl̴NYCJ͙h:|]nYH B@9=1XƦ\/#[lacIF:n4&g,ԗ']f3hq)Rҭ\FٷwyJRRxy|uǡl-jSYIeZ߰a}c9)6zd}~b{$ ˏT#[nCioFVNW5KiACTʽ,8ˊ lv`EVur}v}rksFFJMżEfzUz9'-YIOsj`Zމ7MMO@FUF7S N)BԝͼGN$DdxztF쑤Sjɛb,е2r= \Xz'BP͛tcӝOeܲCS-{K%Axa䀂683urN}*^3rJu՗M4L]jT,h˕ u8 skNT4WJ9\]SR'%+ JcgB-iQ} [iOڄy-)*a읣=18+Ѫ"Q[ oc>6Z׵EXq߼Rqү>:_ruV}Krh%D}xѩZJR[5}Xu7A̷.%~r3=MgK4d-jsؤ$(2ϊ.y,8eygf}xælhϭi!I pƮe],- ~*_^uzZ}y9kjtٍT<ġ[^qyh YԎjUǑڗJӌ="ʙiЦt@)8#zFd-$ӗ,-o0u6f%D>X?0jW6%k w!uNġg})<=6s0Ïῐ`d%T f\啾$ZC2o7595.*mkJN3]֔䢖= ]ٮ#E_\>}WmE%#;J˜ d;J%'>w^E Z5,Z1f?iZ}259U((:#n2Ius &EFJ,m03Pm)l nH̩&r|'߱0ܳa(9w,3rl𛞘W'GmD#5d/vUyj}bͥ??=2p,THJR=T1 jZ^dWU*싞i}=dL Xum:2$@ ^%yumueS闑Q5ok2MJA_ >˃w.I;}1UK9F/: ='z}bzޝ&mP[(3LK10ۏi\ $qºNrxi}QN3Z$V hSuiR+ROZHBvTnpat⍧~W.;E]>D~)uOE72ZH@`)~f7 cmR=l/_t^So1 VmWD̍ZZay68w*BG89b-[ՎV{GwF.XtQϪ2bmFy2Cᓀ₊A$spAOJscR-Ks7|'mI%KJgm9z|mT VҙUmoCR䲂JR[PS`6]2k|ur{bqq?hj>3zX]dnMRM:P,,]NJHr8t4갻$qɯZźɷٕ=>իJ&ny1Wu)@p5'V3Kzprs.ٶsƟL.VM76eh)s)H|=.%!)qS<,}{:Q/_WMg.}vy;nӧs7m1x3R[.ZVšĂAOdĒr;{~O4k :5 L*w,֕.jYL=/!3@ceBYr呭,)Jw%m#dq/җL[M醝4ʭ8]gMne&H`?w?7x:L2][ @ @ @rGַ5{uXӚ+MMէ]{cx!-9=;qNK ~-NuK?u,B:×f>vJmx#>FiO"RJRBRI>,{/K/*UfKHW2!iəijHE!;?XEc9*O(h$¹bozG3pԮdI0iTUiONN`mN85>'=6:e'\!SE}G!OrrGi[J!.nI$rx;LW%8^>H^mE*%9Vi[RT %9z駸WvHK|H+)ONTJTt&&˶ڔRp<"]MӨIWӾ y;oӓ>a).7|8I/w4QG#Zr-7LzeJP)׺nQ&{8e𸼴Ƿ{+ v^uP[ S%c;wEFm/\7.C5-riWTf*T鉹Z^Rǘ A KWZ(B9h=Xo[Юt/L},SnR7v>r ݰu֋qJ-_R4$2)I*/M$n[6QJ*>5`~KKc(\ԩJ5m wQM'H(ӵ*nIF[8U.)ZGͅ+#WBu4=[<}_ RLTRfP[Yڬv1MQ8%[!]_;v 3K*-a A#p8JKj?.uPK$oPH^7Ja(zq,?@8WJIpuJ+K-ۻ*pd)<yʓF"8=O |*`}33NK"trmAZ+r.IN7Y}y*ڴʙ%h@'|Ve‡imT^xY٢ն^{ѭfړ-֨V r(u<?o8B$:dtyC7kZ]^Vc:wS+sksɦ]-$A ^n9Rt*͡gƯn+TJkӥR4fRRw)G'Dej9 ,#s__QQ^K?kk^u5bz&Ra )Od3nMfzuKd$*:˿gN+:uGR2kj).$ Ua##EU•:nd=uN}X7.<=ԩL[so]gQ6y3CLnS'9W[I4Қs@})upTgeJڸI=mZU&%'jݽ S$'RAg]n%MRj*\eMGեUՖxE=,tO L+M@V]f_KIoARR$(rm%;ЭisNk8|j֑˩G#Ԭ%dG2O5K[ZO='y4Bw$p9LzNnt宔zMzȖ^܋R&\+A!89`ymRONa'}/H:q|({T+PU3SI>[ͥK@ )AAIǤn4lhuxT+Wq⿇x2aG7O--'p1Q,;2FBT|.2Ѫ(J?|U]oj~PΥUDqƒTHQ dpqo[J3N/$ARlϯg9J+2MK:_8Z55CrX”Ntoq̴#5VQ*[nU;,%Lcn8mtppꉝLT@ @ @ @Wҝ]4fsn~>q}m`Zc"Z*>(ڙYwơI!nQ 4Ҍ>kVP9fOgk'lUfuFY[JOJO#+3 >geѹǜ9QJxG3J-e*#Ol \ TQ vm Y<EmI8BS!;HI966v**qqԉ=VWeoTSOCmi K)u8SθbXAAln/+\v0ZvhS:HQH{f[%JeߴCE qP8:0gZGv3v6qeHáGoA gۈ4obiZJPjZrּVB3mE[ȥAEe'LJE2Qvug播R!xۂHg9?X[S,|bP*Y6aě( %T2۟HJ4G;-䱂z;$dmcu;ߐG>!KrxEaEv#TdԂG|\2~j***JTrHҼ\8&p9HßC )5?c @ @ @h0~*(cǦtTާmOLe2S>8KԽNQm"&2ȗR"9 0NiIDj3HKYSi\S fOo'(ѦfIaSc&5ڝ)\J5M no='qRyJyJF\٪\T\E2wV>m}#Y֧}N燍l죋)SSR +vvn8Шp~?1I8 e5ZPU&~)%%*Z2685ͤ4?j[ʊV_^jsZV+[թI2̈́7PJGH*OX-՝:JK~9˺UEsVu&u[(HZ *BB.(fy+T@1m:\s#-PO3ĉ5|0oc:mh֒O3}u>D<*Q`2|hUOg~Qsw΋jꔓ~7.Vﶦ KNeX9NN"+P)pcNZK]eܚeiէӅ~b^ͦT;RO~'#UCsX ,.[HJ1!QA]M|[8A$fwKOVT&r'.@;NBHܖQJ/Fe5VRMzZS!L$UŤo\ 󱍋BNrR Fvv nom4_FZY1]P襇{iLV%ni OѪN˻ہ+Re`m<7$R$j+ԥR8pᶽFBR.3Rb5rKR2[إdg%>Ҩ88dP3NZ,4ZҧЧf3(ܺ Ki!G'o*>ZЫ)C[ķq5gG%Z$~r]^|VΑ(/)&ulUI9Obɸ% &v[(9$s6LۮK2Zޙ9 PkvU7gVz^v< N 8Э+ #:Մqت=M;3.*BHNI?HEKH+D]`]vgmiP文ܝVp%,gc488ohRYeyăIWOާ)j[Lφp{O$k7J3:?QՖbZE9$'ej|J8@ϴsW+WS)J>Il}[ Nmjݳ'1 h1QY#oP~Y>vtNt %|o(jZ.i1f.jw@/*p-e:mR |!i sݵ Ul>QxooZզ*Uc\uJO4&~V~YĨ DIiSGY?{oR8竽+}UJ1MToNv,,%C=ѫNoe^}D[9(ʔhd Ub}5-2FB{gHTiⲲH=1'A5ժ̵pJ_͂m,;p~RJҧʬ-#Vk)վgWu']*ΠQ2)щ% |01:?`*J Mݬ㝾HhjT/*R}V NCJWKNϷTX d D4ҮęM"_Rv<]sRWJЊ 3]%F$` 0k~=誢{9ԍoZUY|6VHeKI$7$pI1£̱fRUkg܂۾gT=Lq m7'0L؏<pY'HMV ..g(VZAZ@TOP$mm4'~zۚSЋzbBic*vssISoHH8Pqn͝]'}2ivu{uuBFKv&^2sjYe.@ " 0Ie{GIitcTiO=L}åKI v$dpyK x)ױFx7tIW]:~˼YCi祤uJB [H;IOTsBʊr7EORwUӪ%o [q) 6&>&,ɕ[KBJBIVrOGgR._}Φc-`z׶P-:RbA戔l&Bom ;-qlmm.(u<ʲer=Rm-7- 6div򦦌r(N\ϴh-ߟ9R5nn!VUS\JةI|.)2RKWg07h5MJ/qוn%NK՝EwV4J~by˥++3,]NZpUԓX̂QIepbW ŵK/Q֥r#sdjKRBxʽWˆX*%{A-M|֮o)OZK:\N a3YR{q϶Th]媗jM[V"j5뚦J:+Zrv F)c'KJ%34q`$ 8>,^$% ݵi@)I{}FP,TrU8dׯΓ~u~vǭ0lc8'E])Df/P5hyfsչ__nA%[fuNNҜ=Em>?:GsWWZ_{,>4_'O]tBtsr@89K[ƅ4num=pJ2̲irH*ߵagA~#igUUNT rziyLBg*4R;J}I~zin /FPn3J̟榤IgfNģf|{M>u jo 8&/ 43]?wMd&AN!IG J)h Ze,zv8J#^QWa[q]=OyljyPJy;AQVNXK/~G#w^ʴJq]Ѭ2-eY42ឲ2~y,+A"&K(Ms=QS1\LZ' -9`}xW*mISqOs3z}-WRY~dFR ݥ*YJҬJO'cǑӮ û4c׬>\mgipS sX!jRndd Mhot%qJQ]>GA)׏Jj=ܛfNeZSԗ]fTT(%$>`c}FRN[>ޯ1`z\9O䲎9u/?F>=~̕ OoPVBJ4e{ÓE8PU9MshT7ަj/Q?9jS1"(%2<Bۣɕj,|F3OhVjty)rC3 m8JARw[Rp#ˇF5JӃ;}:_/s&RKm^uf˻eʊsc6m::;)S+y[!>7ZS:Y]\3dyFÅ*R JNR8#ף8<=Nf굤ܩ=H7[sz4/U"*Ogxmkmooeoo*H@i h몸η1&Ì#n6U ]bu'#{^ɴ!40ϵwW. r(mK8eJ@JR71**ç%9K <)gvfNʼ0TP)Zr9I$pq㌡o,;l *tV NFHue}6༨LQڊCcTi𿆭P(EmZ]ǚaܼ(3ʰXMFiygIӽmCOrv%9)Rl0Gaq^]Φ64-g+JЛK!υ(=:l鵅'ohkT[ݕ(svZmp3?OmiQ.њ: mJFq@(xObxcrs9PI_k4XKs|cMNIߵ*lԶҥzrdCS*#vF @ @ >]y'a7"?2٫IIY"K*֎YngmkPJR;U~m;U'UF;+ؗ5&JV*;Im?"˱y6:_T\GL*U-7f6avԎ4/N%'CeOҖR6C iOڹdx޶uy5޶&/ F@HQ^Bpc]ܽGrP#wo8KgN>ϙcssԵܫNChd(( &7Vm"5 ٱ0Y; [)& ~ R6(A+0cۍE5z)R[I?Yr^VPrI$zDOʗl2KO$GIG(Q.:詎wino+bM%D ߏcX*sMIUqy_ҽB= vy?ֶf PNpx#+CqOu7$'.kv-<Ə8J~,tZ?1TRiM):˼N)Vvq"Iz{?&n[djER̞Է\-/) -d(Oh4>+;O ~gnMS)~XD%JEjo5ˮB駮9WVh/STXSꂒvnEK(£Im>sĻ ecYWt;q]i99/+R.=1ܡQI|Ҭ\Jmr2UoL507"a>Pb'_:l+ģZ:qt;lsb"iVّJ| an;TpG'hOR)b* 0O8}wnrN5Zp}ѩ]کVo 8VR;)*R2F9IOAUqy;IƊZ9{)7 B/k.\>t3ep7Qԗl'G}.[O ܪL}I,- S%+ +*99pwokU,ѭF1@4jV:.[jzHeByl)N)%ԒH8niNXqZ76@^޻׍iZcpHSUʑ2A(8)<b(~{ ms WQPVM[,oܓiZbUq6IBv)KA#S Ϝ~|*Qr^-ҝ&'C՝-hs,.U-8ZT0R畆-AC'#{A+֬]+ <+VQrrnW,̽<$14ktuK Ωڵy~~eT3Ɏr__q&M]ZIy3^e Rq$zzhy9e伭mඉ1/VLLԥ-Ye3) zn]JxMZ i.ku $UOJh?;c7uw!y?8kn4Z]T}4:h6'dʺmJGU^M/,(IK q!@ @ ($dǍzGH[L%*ZUo/>EoNK;wN_mΟMj+_"'3\Ra scڧzZUo+Jmoe N)C rͼKVwP'UI-$-#:7e /g;wH-yThsR@ :>#yRQ\6VkB8R9_ĝ3e>ɭ[}on'$#M9\ZF}V9xSq_#>]PP:^qK˅9%_*)¯K{Im%xKroǏCgٶJKG'$q][H畳nR5)ʹܛݖ׷!?b?Ho6bdcW5WVڋsǘEAWR%՗7S]m#E%.SXЄ]z**vvyl'Z@;)m98Oʑ, Ԯ˒xri'<?%F]%%6jm JoDJ Kǖoѳ*;?~L+VugNӮ(W}(Z2Q sVjRQܷk6a}rI^e4:T/1Oǡqp2;ObB~PpBwM\չ:;yhLVT7=.;*%ǘTW8q9HQ eV;y5ԕIcYYȸj!Q)<F#mxݲ^sn-썫>XZu)-7(>4Y7؏Zv K-~jI8p6sbI-wX %RWR]]=}ksC ĭ|go^.ۙƨĪ(u;ʖpv}+*Ԯ%*0vR{7u)$?Mgқ[5 46v}m ө\RiuHRqsFzqZN\Quc[]}[zl%KSK)ZRF(8{:W94íCW'fXlkR32onބ;Os#e^nok5Jv.MЙ,cYkSIkOSS13/+eji,'8#R!.ۃ))x]箮:c,:Mjet#ZY62@A1]˭7=.1rn훔ao%ϩN˄#so7ͼ#fqfTԪ>q+8eM|R,9F*t5Aa48R˓n 'GhMPwSK{NIG /$:hZʌQ)=`MGQ֐ʗ.%璖Ekzַo+Eç9O{'Ys B[s[N;N4rj3蒽.zM.+u*YqD$%@'תJjQbq}yX{,g99XX{4ec叇箺;~vʦW')ms%)=ρ ljy+қGJ%}Ey_&jNS'JBTIF|(Uo%Y($>cԷNMJ:c֦?NZtU^)Kܵ̊c)yRQpyjI x=$.-^I5C)vڷ]Jj˸.mJJN@ʇ?yq;YޞMJYlQIo12Vҕ0n<4k]Octjt,#%cQVS>fY68X?;H>IFitxu}>ڏ7Qm3'@K7嶍%e;;@JwdP]rsR Y}jҤ˒#U&bN iJD3 HRpFBp25:A{3qo_x&*Ѳn~KReL55JPK~d%PQUH-eTOSC,,`֝QGKNk6*uOQ]y_ å>Yq-@Ng IJqIg)^"pRSz{3=DYRA rP P0M:[> JT}vrQq(Ɯ|aOYv%H'9va6$x]?=UK=,Գ Jq 锺TWE.ްhI-Gk{>WcYV)=馢nO[֌e4˄)]]ヹy3YP4IFP ṛk}{Ea^~x-ԭN=翑u|>؝g#iB =tJ1ɷ+}3+clSfeS|Z)ezAT*1VJy~䒝OVКܼܻ~Zf(G9џEHiJt{;%Zm>q'W2j$L1RT:g*%דmN[IwS*R5{j\oLeiYKP*AckSSyYO3\^'Jx @ @%eQ& VR ͫ8o&cVg-5SD[ܬ'e[*H8?>{ai;_#kNx5e:wKZPpgϟVߒxZYX45'~$AޔT?G :׎DV5R:t% -"鹯O*|Pʗ+l?Fuo#^cD:uIjM01SFX>R&?W:\6]Ѯhv!.Oeoh)8h %ch˧7A%uM;K[h9>nS>e%IKc[g@_0R>d@ܧd*O*mr9%N#%ֶdq]J*BR+H,(6e˜lo݂;3Q'=m giB=C&*Z\%9W')5io. Γd+tdť7׆M^$m^),TU+"Qշ,\AR%!P~`S`3;j55,s|-Ύ,)k׺7Z7MtΧTiDEoZ*C-n*C%hINҡ5 :4:R宧ӟ>3A;x>M,Q)'dRw$1::u$8ȶLPuyqaN~HTtu,^T!*k ;Z*T^8.[TW't&a6B*JY'mwqA=/{:j-~-/0ɔ 4O˵Gw\YY2G*}|\u:6Y!Y[h}8#W҅*9UՎn>U[W%3-%(#9TW5i{Jgn׌pMȶeZnm)2 #ci0i=)u2EtKKo{ܭV{ԩ;S\&x;F#Owj׾Q˖^yjm;yG2keCS8Wcq)*9gRxutq)]OڨcROr6|NBR9&t7ѫݺ3CrQh\˭{rq^PSx:[Xi5ME[݆RfWVIJ%O/riMEu ?fZY }Wun$}WCFevtW^e'Qhru*a;}bΏģ,m5T|4x4ik̪V.Y?5u²I@{lz W[}5Me*7[38rG.4k`g'J-vתԊjuG%;Ұ+b8Ϯ#V2EJ=o yBXƞ^׈'JL[z4+^ZץhS{tW ']y-<,rzqiqCFtEOfc5$IͿqbҏ\:I˄^*C%\KOBOr}i.MψQ?kV{}Hۄ '=z&Mcj)E1< $=7oSet(/Bh_-mJ s8FOߏh*aFX|]Fe*7, {δ1G#'=h? Oh]neޮJG?8XѲ7tdzvN/GkI)HcX FʂXI\G2{qѨ֛ԋxL-(<ȟR[WNڡsvHե"SkiڤJ}}YXSS2ťԨXuݩUf}/6>m)6IaJj:iW[>N+?n(H%HX#Fugi7֭:ʢ?F4@ @  i2enRZYԮ._Dٝ(:cݥ5ITSՉʟYqDRsw:rm>ЭP[-k~=&VkJUE-H锫^Nkx,/䡬U-J;u=kտ:׻$rFե8 j[4ﷶ9$ wq9on Zy^g_4CcM?C)UԀ]\&qn(zX>1h6[|}8K~ﺽ?$\GK%_-Uih[R=:qĩyRS$W3uEXSWL֩.!6,v0}:tWwl.+Զz\6ƚOyKt9Q>1^O嶋ݫruLÂbVu R~?HcsyJ|nw>uyRۙsMOMFNOƶa}קŴO7Snm=n3&Mu,WQ>y,g43_S&朖~`yH* @V?Dd8&V1/fH1ꤙiGc*(';9>O+sC֥KeԲV@$FS:6*J^6kJR]˳ԘC̽R8 IY**8WnޘQPJJ+˃YHKV(m'pn(Jj S*h*#O#ʒbezGF3fO[nR꼗$/i9O&ל*]Jl:o#(i{:K͝gSsdK~ԫZQmːr~Udk[ԧxUDwXQE{uAkmn'=㪆z= {ɗ--miUp:UODǖ>VFx=FE/#Fk_]z.&e/NI^]!>qiӌҍ:odu\Wz.dWf*6X[{FcSiiZd㷙fXTZ\LK*X')mBEo|Q#{9T6#3y>zjU¥),10LjVQT;Kolh~L&RjqY8:=%)g,gv9f Mtodj$vdWWzӧk4ˬ;(N-AJI}P*Ҍe|wMn[**A)gf |6=K%KR5󜸫y*/*qj8J@":ԭyo-|V.*~.HzM. ֿhq I<1ʇQEPX-[G30l Vk 񕑛Qree)Jӯ `c_WԨ[AǼ]kjG S:ޫ)Y ZȩL[%Ip:(N%E'z2=ΟB6t\]J_/Eѿ}ew _Gw Ǽw>w*.N0ifkXJW̪ MɒJYh6P=ƚQΌ嶜g2M=mcB9O[8v?,|qu;rr˓u&YH?h?XqEIk.1$m>Ij«vriR淆Դo hǼ{QEKGX7e:}󧮞-7yL\6T*/7#:nt KhIϠ/=)>?%MFߡ«5є-8'''3)gyZǮbjU;`k{Fz"\ΧVf)t!0.fmK*}h*VҢR3I#]mWKRf 7 =H/{> _ f +#SB47qS~dhgC:W1'GDaT)Nm%KZR1u7(MɳQ$Xv|+wT̤Anl4>Ś45ʳ*y.]tY+~M3oT'K J6r;1Fi#5f5nzNLԩm &'蒪 }O' {Ie\ԦfC.a$(r%JIH?LTeS;Rod3Kvf0Ҭ)9!S27,/ z'tk3?7\y+c))@)HLj+6xHF~ ɍxW|A:Ujnd钩mRI><ŝ261rg^#_!rXu1" HS󼡌W~"xls.1b~r,۔PqB8ԨԞ0mgMU늘|g>ԨBe͔hoCzO2TGSUb=}BOtUc&t;2SlJi)ʻ5smwW-m^c}%@*<(J]2Y y8;hRB%%69%>{ vKKp!@q=Hg6Ru^;I~.F̪ؐ)X^;GsQ>L+Y$kB0Ͽu8rk9}G9qs@ @Q\@Jr^q\kTeq\R2dTi$ 2Sos,?>mWMuZj~z4B JR39yPZZSe^֥LJ8ot:{J̻2TW4Q>ah u}IQ}%+}:=K<ZYl$|۔o[KzL&hyj0E2ߕx/r%'hO}XsWUO%>FOs,b?$봝⻮z֮ fW+uj*$l@N37sJ1Y7rV%$' $sW|8ϩ[ˆBa;:m.S=es3AOQtrmJ[u@zF¦R|~.YeT;G~n!%"T+8M*Ԕt\'&Kʽ42٤PCyH9垲Ku.w/J[I9߻lјjQԤdŮZU)G!$5*U Iʊ]@bV5~+/T[]?Ez-ZIp9GfmRRH݀L+%2GjZn̥IK{9+M=)oQ-瓅`% #ryk${uVjW05L)8pH*>z;SykwrX]qx>T9QFQ%[ˆO?3iܒGc&% ^IO:^ ZrT1 Z%\M@1&=Yj[+DܘQ;3νS:6~iJygJ4rjKf "i*oLF哘JP/rQ&[Ig,Sj(-jIR{V-pW:HV5R&VK zc= y <9na:uSI%TTnx6{}#ҳitڔ%d%[mi+׀2xjTُLOBejbY¤"$N;rän˜1+%ԩIJ@Fyy w훽6]E]3Ý3|w5C2_l9G'[鴗ASrlՍEuȸٚyKJ w I*爿vڴ-q-2öZ5qt%BrQ/Rm{~ p19 lZ2B۱m][]+TR}:yVeZRp8I 4C8h]#*E?k[WG;RrO9fWT Ws^6fP,LSRʼ;J\'9)^ICg_O.7x%Rײٿgٙ}A;#*sx4v5- p|#PylqDϦbeT54|i$-96n{\bn]){Q"BL~Fa(HX@8*b}Il_)ɗEI }A?#ۼ{'Id]l{.u矴K.4Q WtJ;Rie8*X* vz- 7챦ϸ*BkܣK]̀K{B9uORĶDo|X֮kRmfG3HNܭa:Jk Ӈ՘%ԛ^e6&w ;?l*K*}i ѫYʽRMF%a#g:E?X$ 'g"jJN&e%( qk>'ֻ ƣG;Om.0`y0%H' :3n2NDZ-g]:1'ʄ2R<J+_L}S{ow:ٵ(Av7.>g4 @ @[aY]Py?DG_?t-z RohV{+=,P?FoӮd:Ka;|[]dAxiH*z%rs|L.IhL!  _i4Izgo_VU:xgUp,*r$!iLWr{W?xj{cC+KդRy5 HU**m=2%KRk*jNd u %arr]@:5s(e|n*٨~tf)eܨr\)@l;Y҅G7/]?DN[flqUD̪ffؔv"7ZM+UR;grm*75ڜ3˸q8['qRQ=4w'ܐn:qBS3[d.U2|gjR{?.&NP! bJtar9UPCmrh5m屶ԎEercNZ^zvYNOmJYCXwSnhv;u^i7R+R3]e{G6JfkbWj$./x'QKgE|)<γ1NS[ೕcl2(% JWU rzWodFI֨z ǻ'WvMiU"I(QnI,W6Ys NpqRKI1n5BvfB2u%Ֆ߂ ǒY Fx(N0UVi״gm,*2ӉZ (hOn{EU0xq$ܕPiQGo[ĺqRؽM:a$th,㒢rċ3KiĤ~D<\-i2~xagrjsF+BɚZl HU)"&ϼ'Yc-e =Ȋ4:p=iNM*e2$8l)K}Y-}sNO^t Kp%)&$NYr=tyNPej5oK 8#?\=\GHqS>{'bj+-һ$q!U?H(VjX[iN6?5*^赾^o=qo 5mƕ)n٩G ,p[bc; t bm-M Rc׽ZN*[c3|wiT$2iЇL]O}Vܥ3A~RVNfY[Ge=qɎ^UЧټvɹGK;ʐRWJ,g3n5R4KR4Sj6cSy+ €'ԏQ0.F;'gm%*ox<}7)OA %4LL16A{#ڊ~[~ɚ1>VxR^klO[zuK\%n\7J'kMe!#?c5CI9KeG}cVPXJM};̻Zw xOrySUzLvmh;A*93w7Eqe]Nivۺ^ni2^Jҥ?LePRߛn VSYFIyoN|j4%^Á.,D9#wQ* Fq.v]t|PTg oQ_̦,r=~J.cg{FGN-yM%gڝDmLBM%Q')MNg% :.yhk-NilY$ژv7)e՟D%)*QqIF-(oSiJKo䎋xxZU Z粫R%뙹%fyA K) C9=k7'<>ghMKo7Sꆋt-1͆ rV5t͡2Fb]–ԔPؓ1kRi56k\ey_OmJݖ>[ń/2Z 2}#* O5h4jӔ޻iZOJ-ŵQtNӝwnRJnΧ,Sk7/7+;Jx#.ʝ*k=3oNȴ{JWŚ牾P궄޲g^Vƪ&PiTw)BR!8v-T!O<ro)VUTmNV<2A-L,XO3kKKڟnJג?T3\Dﺋ5uE,GY)A%$dВO'#[NV:D''qKeukK/Nvt'PvLZgeOyKK[iPKH9$+ėK}˞ӕIɷ&.zu:I4M.:ee6IA<?^";;զŒ:[Zeje]u5YW"V/\i亄ހJ{qR%)nxu|WCzKJ֫jzPT]]}>0ˆ J!# Lr7(ЫӪu$o~iCÆ.\-tnXZ+gfN2DUR9MB]I,{KJv5ϦLzrfi5^ژD܌3Ur #Ө6\gO)M5[Qa{=25饞0kkɒ/R!c"[nyov=V*!kirNfa@욓4˼ ot@)j\"ӫWC,;{DQ&C+ܘt?뒓t֞TIFRpⲲs7ӯ?*U;&9Nq vjE<%C??XƤv*u{J++qt!I1`sg[ ;}"AK̙{(;ѐ8Q9ץ*mԋnȨNfX`85lg(P-:2}Ju)>ޑZP2J96Y3RZJIQ?~Ǫ f 鷤nSRHRX#FN\e> U7IhјqҐNϘ${]o(`T' 7\g 8̫;T09o$M4MVm-+B•p9֤%(>M[&* `|WU-sy *R\~d%! @ 1L-+6L27{-kYX{?Կi]YDY_辑0VhP,X?}~{ᖥZqNX5eSW 3Y*W>a=yj}.e2jدF_ltqgSijO~bUM>댯(.~oENQcd?M;Fu;iEN*JsE^XY:巟5Q/zYODKvi‰/;$:p/~`Ol?A5۹-GWKl5 |%ҥ!' I'+kdE\4멻 YF8v1~$z#OZ4-֦ <~9x_(=ziզ2V~`=xS݈jvݙUlS^G̴֯eM}} sQ•mXl-m~NK=Smҧ%TaG ?Xs:ӷ?5j60uCqasmRj*>EKAs-,rp;*z.Iv͝ar}Jy\i-Uk/2pNݢ`gyVS2fѮn]ZzuwlXޫ#|A̕ ,)(݄JW9sMƬFI|l}7cZ7sԳE~Z֬l:&j6'iuJti?&::Kzqb6[{8rx][R: /wyHç΢V rU{R8mn# +]蓹&%iZ^o~{y:>:R|v9qy-W,x>f*[ OV޳JΚ 3">q/5SG__'Uvrfh70ʛ3Kp1qetկu珁^,)?N]}NV׽Z'su]Tݲ8]ԧS1.S ץcOioXz@rn oleNʑbG}NgOSeUԤwTԪ~zUHDARs{XCPU$, )Qe~tzYb0%RJwb@ʹ`v">Sk<Pq.Pڵ$Hy[Jscj.'lMW|/Ȑ)4pI/*J{sTZɰ&K'Qvi4+Qoj+it*K;d̖eo8Q)VSjhձ0u#9Qm.\)c !gmKxՓG@s%%%愺k`dWTQ3K$$.X[))#omEqu˫95O˷5:M q-YҒ/7SRjSOS ekArH(:X'ice[vg"w&QBJfy?7mwVgQOªVF@ @ {iT6šrbAƐT#EB*.\m{P*y)>e >siTS?6vӡ{8KUPL(V< G.|"* ʪ4tɉd8w%Jx1\8T}9QdZmgcF=L-YrH$&Ty"!I7RnLbcb{Ӫu q*f۔BR~;2CR/%ړ%);#>xkƿWm>iNL_%i\wMzWHit(?8 335wA.c'ǏSRsyfF5^:QuHӬjy'%.rm>U*4txV~Uo*wRzLTj fqzClP{FwU*UqyB +sΏoIꍫf']K2J#'=qjFNߙ"bi]Z놓uRZ5 ˭)pHpq7q)̠5v-0^oikL!^YkP$dE*\ZO|+ƓQXɴWMB^U ]>ĘMcZR1憈SbnJںbNKxpXo_:g)ڍCj 5oOJIQ)N!w(j1oRNU5z"+5ЋWI4^rvVߢm{ 4'sSIwB$RR;v#SqY5@n5sM&jtR !$^ PP7=:֊3y|[u}P۴.W?lFHLrA)pbErx*Yp q#ΤOjE c rgz}Ο͋]F3ivuV4IhR$[m %A q.kUyս-gsFOsx:_A4ӥ+B֭I^/t4qV̓d ez-]_`Z[R8l8y֎Rn-VVmUFpS1cWUc>2>it/gO<6GVNVJ|3.CG'V_dZm/aQ'Ŗ !e8?.NBDAF: F)32;XwBI$}DZU })KUfޖ)ZPx~(=!A*)$c'91 4rE˓i!!Fc똅AnsZLlbURe:>26̼[$ ʼcII2a)Kίu&E;'iJSTyVu8UF6/DUg+.8?2==~Q/2c^rnQ?>lDU1&Vݱ,ۄieI$A} @ @/NbsJ'.Z28oiz>ΰz}EjM fa/O~~}vݏ{]jUU-KfVt}376c8W' t^@mIpc Le9-S3^RއNNSɌV8|e άgob:sK(ڴT^VFp}SǑpkaM$.9fZ~O[ΩmGm3aadjF՗1J˫OFm4zn.YI4ɹD''HiP2/- MS˙ز;Ǯm)hg(+osp$8GLrIGJEM&ՃZ S3RϥGVҸ J}2[2{[7FbɿAzם4Ԫ[W\U,Jdp pqe]>(T[} *ɾI3~0]`ڶVLNrf^TqD$G~=1*e7пMZsxTL{p~c휜}clgv^Dn5\:s%,a?/־*DttK ibjh:|xMнNQRVGXyHd5ͦ&X*?N#=IǮy6䬿`:iٺ6]mN"eKH,'#$s3g6"qkWƵ^UOMT95707N{(SⰱK?4* 7-p)Oc[SGzzqܴLlJ "|vӒ '&!z\/Ϟ䊵N|i\qH[ԛmOO.jd*H,\z5!R8tX^Fu#Uڡ1RGД- ڞw1V#N/dkliudmK RUDo9(+^gഩ{z$c-/ ) Z(%TIWDNd`rʇ*PQme%rpS Ode93Zˤ}8H+GPKKۓV! $sx{iqTrsrT0<'-tTХ7i͏+O$ 0Sx餚>)œWAlgF>$*y>rK#O#-6Πu2+Nn6eCOaVMZ-~[^Hzji5kF>A’D¤!?ns#Er;JeS'MOO<֙їh'"֓*>%tڔ%#Vr[=6q4=%0<Ӂi_bh4y(Sh\=hU/CTjķŨ,#JszEIYZg?2g42 :iE=QkS@=鶑}3'RN9Ӯ PXzui RBܛSJ +`gsUPY0U+=1Qկ*-6ʷdy\cMPi :ȫؒ9CAO X)K&IlbSR/'aŤw0\]qcM&{֖ݎη"u\>, X&z2ړ@ן$ SLm:\Q1ܒ$zpؓHM/g!G?=:ћ}39NJF+'ƌRٙJdCì7ʚp‰?xnNXfhuZ]aҐ~bF9?XǑҮ?PTSϯRa/ um2MMʡ8Hi 5ufM6b@ @ --R⤽Ke+C͔)96+|?5sz<>̒T7$c*SRɣoJ[/8MEAVrp=\I3tww0һ{ŸU7 ٞfP{ǎP[2Υȴ).lvOXƦ{=Q1#Jjnum)Q1Svbul"O.FK%ԫ-fJL78>`=#eJʬ_i3llX[jYhERyįiIyX=aR2j.6$oZu ޢӥCjp(lA5TҳgZ6FNՂb/m̙ZkOal2Th)[F>JKG$i9.ԁ |GQ.d:w?'i}4$d)|g8HJX3{WJg~mmF-::iWF~q XTUd^'Rͥڲ)d 6kJr̫ɀ@ӱ1{> yUTYL ryF&ܟJ8#JLŤL`9s NAM., J1'8*=RO$(;I0%ܶNy8|J/ղ=$%*VBx}8ɓYeZYJHO*Qo1;~o#AZ +9V=XrHy*0[ n-tL_n"5.ʛ;c6D&owKZlAlJl J8#1}4{_32~HF J3_U}/ wHetzj]SOGoϸ*X {EzmmH%rWYT% F5,~ħ@ @ @ 5ĭjaiܴjc.)cK)f-sU鷘`ຢF3{Ek5ӎv%-oO2Y& 'o-8 czE%hFBy$vDeіCi#'?oXϥ42!xsa)\R\I:^2Fܡ3 T8#Qi#+[h= ^2G).,g8SF1FN=I#A! Dӊܙ, dq3J=OKkE b17&0Z+3Yq=銖W ݞDZv3oGJy?u T7030m$Q(Oqa^zۃiJ'A/#.4'RU@F2s9G4~RP9>Hu#Go$znzo$dn#e]hr[n@Ǯc'VYYF{spO/-Y>OrL 9?/ {G|yp8K2GO6PLy,(nY9Sf#sM&ׅ%7rgN!IX$ʟg)O ~^Iыs:kZ c FD$Eu7*t$TG@ @ @ @]B^rul$wr~i`4rWtTӹ=P!ĬB.,5D}1ƒG%_,InZftPmGpsv(,y;gq)F]8)q1}0cԒo=+^= h4 RgNKmL'<(zI.Os,no|oE21[[iD*ՙR#OcO9԰b`qہM ##5AjuC Jtt*% [OSGK-FU*)A^ O,fՊGB:*8aq3U¥7|~jtͥ6˘W F>}_ d:Rd Մ ɷԵv8`RONLWʾP0G #"XԦ3tJVh*՚$_(fͬŰM'\=SKs>)iKjnDZYRdS簥Qܒmy6n!qϷhWRDUm=Ÿ!:iU{+c/$h :j ފ)7, @ @ @ 9V'TIZ0RDVyO2^Qܝ1꟞es>?M XP{cbM-=iy ѕ> pBNB[#<Ѷd ޑ7ģz$m$ ayeeiy*=HĞN;-̔y/xuh-ROFXLzm ѐ @ 6ˎx$l9a~.ԃ$29wyMQk#Kcxwhi 4›I .Ԛ b߇%R²߿a-?RKv>t$b7gBNLy7Ss? Ѷ!9jrx{#x~x  KRXY1~=#a ?!=I򌞙/s$`WA:X4 )Ad|ӵ zJt#)rOdAo韧=0(0F<KO|>gF\U 'g[#Gti+MI?5Џt9TY?c1ug{G[*˔ >u,-II$mAwy^GCs(隤yiR9ma 麏xgF_sL{~_FuHvSrOg#SO9|cHQq"H*Ԕwh5)GG:Jӄ"Nᅏ,s4m)Qk@eiOt.ǼIQ,[e N=81澆J4=sJXq. e;++%&ITtɥ[v*h %zx1u4\^NJTሳOB̤>ЗӴ#M%l[R(ANqA}^0|.cL,p9+ AK3G[ 궤99đ-݇Zlfս(>H'kFx>mZ(8GЬǩz1l%S%hkT̜ m;;Ez}/`9r\EDŽb# @ @ @ @! 0@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @micropython-1.12/docs/pyboard/tutorial/img/skin_lcd_1.jpg000066400000000000000000003017701357706137100235510ustar00rootroot00000000000000JFIFHHExifII*  (1 2iSAMSUNGGT-I9105PHHGIMP 2.8.102014:06:22 00:52:38BJ"'d0220Rf z    |t0100Q|    N@Btg'2014:06:22 00:46:042014:06:22 00:46:04V@Bm'dm'd0100  f@P`\n0100 > JASCIIO08B00AFK01R98 @($HHJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( WvTm#̚(-iEfڔq 64LYHHiPQL((*9SAqȸ ]HK@\ W:*ZYG-,s~Wj!vƸ_= T.F9!G:.8bR2]=UG\fV,T(#W9|X%kՇ%g\|U&YUdk08aƸbSk88tpDmSW\cyQ9Enʌ_)}Y!V?79X]7IE=q՚NaEPEPER`yLj&գW&$l"v\lKq،ۅe. 6OLT-jz[&9ުKiAvr9Qȼ+θ\IwG!<Hu\dJԑ=(9ZZt[ ,@+XBrNH$t+>ėB; Y7d\`u_ u)&k$%6zgʚYwegn:jʱ. ,+xHeE @XG U[{moQv4dPl \}m|:\v 0f,Hn sB.N=:ŭŌܛ`(Cd` \q]|_C̈i3x[w8z }1]Pj\EU((L k&ao&l0d~!diCf*AÃzV O"}9 /֦ktC[.;v\"ܴ)4aHCtڙHx1iz%G#DHTKmF~Aq|47'|2 m88dG}2./|!V[Ȏ~x]Iu$M6SOF` ڸC`޶[-yIcۘev6x?I%'쩚m>y;܎߅}[[pp#F |:j6v|^\[8=9j>x`-/%p\+x tunQZCQEER)[}: FI1F&cNA6*1h}p lk.yfS2[DGbAdQh G(DF @\z}(H:f2EAvfL¼ $f;%Ȏ!xymW##l@ww[^[Gt$/.S?u|A jg,ml10SVw!;]RU&8gG`;rjakմ7rE);\t8#{)(G-Ԗ tbe T`0  kB}XdܲtnFHA! GN2yi& }$-m-a0=[' z3nmmRK` fr?SXΒTgRݣ ɸ@1+Գ6lk飞-$-$|~玷ǕCWXY$om`[*zYO:&u+23*Ȍx^sX9/6״+ufx "c (4ҜiMƌJ;pAMswhܓs\խt3#G_WkHI;}=O+̈́d4m:ޡms1>%xur9n}Mb$]%%C${^;|qwysEL:$39?yjW͋;l˥w{&̤k6qE;-XⶏyPNNzrO~k2IMq&S0;WA'I"yni7 asUѤR6ze!Fy]+n{s ģr:ҕd*y?H %B̊2 s]#}a| ]' Wi"tmq]~ylI);lPi\;W) ǭzǃ5?6Dǚm&Y+5xkMFB`R.v-4HQEXELEIrp5.5ZFl8rO/ZPQzt<|ͬUmWbONi&#շbhH>#>s@H5q.E+dmLĒ–ӛTFmīo.kL_tL.ҤnzTkk,qɮ]Y8S&Ie.,]d)>R9. P0F*z1A֮r`i nINN?LYko\ĸ4=@bsV`;y `x'Vu3T S@s 9Y ŷrQrwapCS[{Oek:dRZUE#ퟧcIЖ^q%*#ٺO4=xv (#xf%O> ׄ,4Pncv$'6?]DW$tU՜[xݿa: =*fKi| #Ǧ{^ș ?r.ҧG(W]dS+hyƗu b'8$f_)2wvA]}sB[27\'z!1ٸ̍A½@ di^Gc H-ƶJ⌒=wnxlܮ'0ݯXG!mZZ6f3Z( ((7q_>M[ @ۼqn1a+`*fRv^ICOۨTGG'`޸^:Pʷ$|wd 6r2:%)u4^eďrķNmJ٥i"%82t^o_m&&U%N`zU_a_o2,6eKQhg {zW_h3M1"' (מWN, 08kƼ[g ejQ]\C$# @#O| ѻOK9Qza$!L鍹9ċsۏ8i6+=Mq$?1 ?weVyn rd5s'c=xY`9?z݇ûMt˙=բWݞ@caieav1Kn3^&d/j(FcƛoKБUPw㚖3{EV ( (˺MwVU1vTeu 0A+9ROQ|}eD‚劏oJ|+j8bewZd6w'UiB9e' 3264 2448 SAMSUNG GT-I9105P Right-top 72 72 Inch I9105PXXUBNB1 2014:06:22 00:46:04 Centred 320 240 JPEG compression Right-top 72 72 Inch 1/50 sec. f/2.6 Aperture priority 100 Exif Version 2.2 2014:06:22 00:46:04 2014:06:22 00:46:04 Y Cb Cr - 5.64 EV (1/50 sec.) 2.81 EV (f/2.6) 2.48 EV (19.12 cd/m^2) 0.00 EV 2.81 EV (f/2.6) Centre-weighted average 4.0 mm 202 bytes undefined data FlashPix Version 1.0 sRGB 3264 2448 Directly photographed Auto exposure Auto white balance 1 Standard Normal Normal O08B00AFK01 R98 C     C   f L!1"AQaq2#BRbr $3C%DSc4&'s6!1AQ"aq2B#R$3r ?@(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(@ P @(P @(P @(P @(P @(P @(P @(P @( UkFP @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(h [2N(U`Z_:]V9mʷ Gk1Pl4Oūz^l4K}EdJ6Dc H#MR6xj6hP @(P @(P @(P @(P @(P @(P @(/ij6UY:VJ9nk%ZK/&,hBl>'^6v;$Q-+՞;)eKjDQ>xqg b-Q6?9Zl}Lzy}Q,7ߪZy}Q~|FTyZ H-GiW ?BJ>=CX:5ޡfR}?fߧ#ğ%4HNJյ g؛s'ŸɑmAy IR6!Gv\ǗvI8¢|Kkn{M#iǺ|rl9) ABRp={~$zPFW$Orn֦ipӭ+u+PurC!AEkQO͋Q,kCsozqvK7 H!#8ŷ_N bC|OGXBL&+쥧O!Ju)e%͞Ot=*h\H>r)$q$&q{_4_Eej&Aa/Ƽ2H'8`{k 旭.~~f&Tx7JP7@~䚢z80oɠ/+VIVA@Fݞ1Hq?rjc7o#B%#ft;]u;:0[*B}r= #}c c[G* (wO\98*,g6XjLEP @(P @(P @(P @(P @(!@SɹDM%\t8IY8xEvɣ|A;#:xG|ƒJ J9P稄]vJ|Ϧ˃ddu;tkm_ "2N %D`7:l9 MkC]ˍO2ݮߦ- }4Mސ@qXC $rɮ9)o9jc{W&ufjgI[c)(J@RN=O/߹ǨT1MKl3gϓ9گAJI62'8!qq|ɨϒ0ۯ-~ծ3Km2طV޺7;'!$NTWsfmѨWʍc1) 9gXPFq`;VB> 45ٮyb`L>ZI(JwUܓz(;! 9Ɇ/XIYi.dkF%3ڢcB'bJ*(Њ^u{qJđ($,V>z-2jZ|#H<$zЋk ۏ*(u$%AB=\!o9CjOiQD>O?٩= W[#gVgՕHSseDi_=Z=Oi?!;gfLw!.6y I}Mi>P @(P @( (P @(P @AJ $h u崇g-G;rϽg)vMY5Lf`}^LvVQRPW AJJ1Td*rֺ^rMGM[Ι;ZBJPϘ,bU}(IZUɨb09xqĻ,4pBi`2BNVu9!?nˇt~klVm.C$.:.Q'1\Fg*uzsk]VN5\ 7)Rmʯ(#9MW ʾG;hek1ŴfwV- .J Q p?c[ܫi3ojŖKrMu2ó\\yKR=P3Zx/J5X.*suJ-2 $z5cVcm[6XJoʎNUy烢8c-..,Nr8%^lԴ^1H-#sJs;HҊB >c㚑GK#\6ڢn>!>)ߑcP-'p7N;KÓ$er*tWiSRQo2ypmMMB*D/5=Ff*JJq!3MrIJ,G֎umݡyHCp$4RRG0BOk >8ϴc,-hP @(P @(P @( 8=P [ƴU}jJ=]bњ)qj;}DhJڒ`Y^IhLv滾kp-JQYqsWrND|0E5Ɗ3#1#:@ܲehIݏ8'+/^ =.[b}Q-\S/Up NԲI)J Is\uG|3oVޚ.Z~hiEY SkKoyB5ՔdӋǯ8G-͹>>eٓ $e)*I3VK4sO<&՚^᭛lJp)A!M%[ AJZAQwk¥:L _ E>" ,CaJ ~]Sᵹ|{ \Э99fv75˻>qI!s9Y"rIpd{TD;£I?z^DmX$AE3yjB)ZC&J_}Pޢ 2xHϠ .ķG00jJJT5GչqΦqJۤ:(;hQ[\ rHblDw{,Uv\ǁ#9j+ܫVjL*i~Gi.;$*7EtM2N'3U0Ƿ^쯎ě<Ou VJJ|j ;wӝĤqպ!(—h ?N_CcŖ;e31P @(P @(P @(Tk VWY?,ʷm; @aXe)9%>"kgO4;"ϯŌψ bxڵff,ŔT su%Rqʗ>sO_=2޻Rd>";.rw?=>Շ ^EJ$gAR֡b!BR#*l28uOSlj?VpZm)2)DL)JH<@?ʎyf|\Qk Siu4~6 eI RR@)RHg#I\5i Um( uDaM) 6NId㓘?Ns^8} S|fh:UV;V$8ҹ6XjÙPq*3\-WYquLW|pjx)cT LZnt/gKd>=?ʔ_a55^jk%6R* mмIr 2 .k C*ʎ9%DxQNoK4̉N\ۃ9б@D1^"hVO#%^ Wb0y*R}|s=D5!(i')CYe.ؤLHAϾH*4K͸̷9\oϞxNA^1ҚsJg6:ZWte};kԭ]}k+n Z}*mdFtt}(P @(P @(P @( V]4KĥI;|گ\;jKNzuj:(Yq-V̮2OkM>emfp3Yk_IG+X-V`MV  n5QE(ɜ>=pd@BŽEH+RN]* hZP닟yI+̩o-}MBH>8:/O:+N*-f"nvRJ6,\91rrc7[m5imCnP,47(0G <) +fsMĖ$ @ uK5|뀔@N~ג&s|jKm]LW TZx%JR2"/yڅkHQZJN'R [jQJ2s}I| ף%qᅡB'T .eAS4Su# VLJ2ZPI'J`sFD qZ'5"ˍtڒW҄ŐjEJRB V-og-,Zɫ+c -IIbN*JȺ^VpwP%~G(2(=;yimx8@ic,/Nqc) \oVN{XZ,-Om`穔;hL&VK odY$)YV$y2ŠKsیg5{lq 'HO* 1~u6 |vWI={PISLd"|RK66\ׄQ@> z9VJ,; 熞]e$DU{TaKL("P @(P @( @(+)iHpI$s\_StZL?cv"B۩#'qw>5>*()+UҤ|v9#[%1uRBA)#ʆJ1?$Z;i|yy; "x2I8QrN9 CRT$Ђ0 $OIY-O ?zXdH>dHn5b [ + <$ ~@ҪŕcKqJ Q*T~Ƕ-qR7 הpu[S zu 9+Ji_3 ?CCwyu֘zగ[UN*@1ʜ!#IN>ѐۯWaeDoJ8##Ƽ{8ћJToO\ȕ/0tTXSlx{}Mq[ؕMCK )- ( >Mr4'@8PxW*#E "T=<*͏ i.)cRMI).;(p$>|]EZ⏮=׿EĆ Ap8,l>=0B zg +p(P @(P @*, *9 @(2;G@yXyH8>$z.&i8ͺ\1-j,Z! %Jp0nv)QJgk.W͸%% 8$Jʔ%^a=+. 2JEh%2B|< ]O[> yqބB|1jFs B )RJvSvA=LY¿ 'VEh2y.=RDȲu6 x'q(;+|ܔصGe~!'ԁIsVVV]N;6`~CYC%@mqROTrQ- e=W9 X&yRmYړ'rOUYe2tEmFof8}d ,kudvFl*$g-0J#?7Qg E:*mضYaK)s99]ZHn*AHX!)?_Qz-4s#zUF)OP—T=TȲCÛBTH$dl椒n[hpcw?QJE(T2TF1c'jTwGJ] mbC%%kq--C}*vS XQZeYDCO^whDGӊA!ƂH*J8ʊs* &%@FA5R8@Z2H!)/jPEm 4MV']!I^W?^]ϣ]XMΨ9n!?̆T.$~DTv-zBP @(P PP  P @(0iwF}\]ZʷA,?馊Z B&>n^2=G+FJ/=,bR~s_OL./֒-IqQ,Hd%c܏Eʻ&JJȲK6 *"P ua)j=FI ^+ѽ6b7%SH} U+eɾK) 'mRI>ۆ?Z$!`6rSb_x6gԂSUlU"QTxc(Bd-xMJE*J%պ .8T>#U|.}Lebvq][/Vޗ*0FI>ฬ}8yͭ=%[x<0r|G>%$3KwJU Ç[u_</'a˨-]Q̿,ڔp EyLH.%g6ح] ./߹̀x>%!I[\œԕۃΒ38\_b+a%ϡ&B7Bch?\Ҧ9s{*)ش:6q{uEl~S%*PRzwgu"Bd[# $?OJ1*K )[@ #Qz:٢J#HR ZH;RKi*;~2G}jp7rH[a1@I8CzZ)w|=Y) ]^Ģ ҮUTdl9lUm,<%Jl*RA$NM܂ZZ+S O)҂6ۿZ'6yJ$N=GYS>OŎޮIdA\fs`Pzw׬̨Vyav(*SGoGu[$9;>hW\KN/ār- rKtS9/Up(P @(P HP @(-PJmą`I=<@qdhs})e .h댿=d=94N hq?1Oh%Bc)^h"BдdwWQSӍ5iVf&828xv'j" t+D\`"th ;miܡmD|%9 'ٛ'+H=rܤOJ9 K{d(V'W πOҳy& kGEd\!eKujڄÊnQ윚枳;࿧FghvU1Хm.dL=^^_u#=94˅lHnpH׏ceލkafn%cR.〒6=F}87'ux[meiNI\yg5%.@ }J#0%@Jd|2#96|Do**9ۃOV|h56 ~{2|NAsnԮ2]l@8FN3 Q %pmhބv⮛v,U! Sx%9ڢ蒚K#oA $SuSÓ&3).' >MdE gOl޴TM^hּ!)ѹ$VqU%, +Q$9_ȣR +d)ݏĐ{g%<訛(Vئԓ ],4% (~yk SkJ]!e]JжXm2I#G`zV8uk{1]:4(-kދܭڰP @(P *@ (P@q ݐpummWSF\_Mt͍Ÿբ[Bio8s98CpK:pQ彿BXRキ߰#q$  X oz x< eLH~20{բQÂk aI*W]M4Hs ڡo=<V%pUnjSy)$@ZjA8vS I ۅDEP>nn 'i?$q)(iIP;|9UhdiYp HҖ,p`J8=U gڠyJ+,H!cqݍn9< KS Q HYI}j֜𢭀v>J}S#2NZ&MQJ_Φ/ fٴ[><{Kԅ2JPu=F Ԕ< Egup&vv Y6INOS^և.l}re;6zP @(P @(`P RP鶺 ^N_Ct~fbM_a&nkt7C^EӽBL*_2|'>sY0am7%h %m/#yJ+ɉxJ.Nђzvgĸ `v>!>ǖPoigand.BT'='x޹iceD Ԇ>@l+p$9ۀI5e!8POoLw)Se\ddkK  Yx'&IN-*uBnX;w'p$ >1ZEQFoǎV%  (dxcr1^7ek}! |w(A#hsG8$ <)zJxa%ah!>*Ǯrc*+i3lV[ ~ ڮ8>Tآ%CoϝQh)=L"L_Զ0އ߅q<ŖGvK;]Jxg-'|0A;Zۥ%%;;I$#{ZߒZ)Pt+R¶d{7c?Y>xhJiL(VB%CN2ЦR++^H (}3ڬ|5wRBA_VVU:RZ%)H#* 9l{Gi!n4KjKҕ^" V3sjXK(i-6nr;~DŔ ^$ds/n\R:X7=d{$> r*R x#qތ"lO Ŭ]FH #?iZ/ߘ-a!!8I9<ݰ{ .*RT )?QvInq%Dr6+XI R|jY%m|`I'(@B{*_E;q HI!2RįA"Ƞ.@XK8ZBcץm4FW묎qGxW?oH?w|:ꕹd[C>%D͡;vڦIeM-bWМ"P @(P P P h .@@(*hߌ,MЫ3TW&upC׃G\e.θؓ>_i*a~_}̓ܫn^9b'g*NImԓC†>'5h2%'r2IyM"HiD_v#%Kށ;WWw Ů.HTѸeKC qԏ+iuPN?R9G95XP gIJNq0>Ve]U7Rڔg+f>ȭsC[4ڎVTX=4))ZN;09֫,Bq %e\ 'c c>W&+d زgڮ!e$(Z!yJ98#>XqHRPw|dv&i2QI%ח?j2,PN617$4ʕ|ڡ[@-}vmR#>qT/IpZws*Zi?]MJ[Բf,5.F ӊ鎙y%vIp4  ljACwx48-ެ+ EH?AHdVN7h-ɣ=x1fYq}#v5PI?V'|#1,NlV |5.81Xڑgb}O5ֱ-.hm#{[|nO>rLPZ``x?{2oW`崤wZIg|Jl[KKt%?.Js]5t,C%imALpxZdePԤ2Eae6I* {$vw@; `v$c  ثe/TA)BHXKx )Ƕ@ueNL*#^OТ)RJʱ6ӎ9FW][RNF{bp)/ +n78D#H>8]G.JbV7-oR 6]vUE(|g77 'rN)T=#9 (eKwsJYw)NA EMlSptɲY(Z7r3[>*S_1a)twjW{@L8J+a@(2h,xI!-䓻sډ <->FT !DBҮbsDRdq@~Ú0 cW={k6ʗ/jv%<]e} #dɇoH %̯ӿvCB-lyW;J`WTt)ZqO+Ykؓs_G9eFN[$):1RA–7#lkˋ8G&Eǣzi^9=9Ck' Om̡I>Wg6I?w֤I}qR}2:(Ij+0,x)8<WmIP)% ބoUpHǨn'䦓jCErB7n oա$.BpB$$dvP' Mݓi)aA->>U`AVJ}1"%+$k`PJ3Sc 'h9'ZRP-[-LHܦw$G֥2[[$ [qe[YRRqpJHvC|me 4NIZXKi@*zR9SЊl$>n(,,-IJ@#VJ8Gcj$].XXXq+=HI~׏|tۗ=Pmq]Ji"}t].Khn%UԞ>Vvza;j0ED<|s#z:rteU͡$~H[pUA-1ei>EvF @(P @* P @( f5% r\:/A L\(\PTUy>Kg+ǔH=wH 7$F@qU!M+ؠx+o&=:YBJ sыr:I"m(pi2@5Qu)<'|_߱#B ~@~3NXVF=?)D4ecnB9Wcz' -W bmѰ̯sZ40Lnm-nFBp8;Trf{ZL7n-ХsfFT#Os^kXRIP-*z<$vF`ve,r4Pڧ2QN#6?@?ZX^*CBVN;N=Ӟ?A[ 萦[ F% Vdo!H9 HQ7O>[qx?0i)qQn$F22EĦҀ dJqac>2}UYL&kGm!c#id+##Ѓ޻.GŊl/p`1*jaCpFz0^WEңuP\|A si]IRӁ s|3_3֑ݯ7Ӫrx\WOဿb( U]V 2ʐ,IJsr\pGT)JV\a[d,Bg)/rYs:FIuMN0I"a%.K$۳DK*CeI'Hܸ ;jp*!4Y]D #i V"Rb{j&Tͩ>VoJ>$/T|1y+F+H㏂%mFrk6BKY)hx N}$cPU1FnI8mNs9fj{7na ~]*Wo 4u(-|^wȟYQ *2PjKrph\e_+}SuzsWC)+}/g tA#;ˊ@(P @(EKTX`(`Y>z9{N,fL|҄wO[Mjx~L=KٛA^Zm2AjrӁ/WH{NܜS0~]5fm<6c 4ɼxĤ32쟛P<ͤ#^<RJVdEߚ$R%bnyXʲ̯_ԔJ[`?^|ܒ&܇@H@$S ^_tdeequIJ;8Uԟ߿g4ʶL>$- ϙ_0=9iٌ \[N%+\oq+8TFtYJj0hAVՅ 9(d`=(Oilq*@Dץ6յm3*U +jUHuO%!@9vl[jjg>􂖷 2FH䃂p<ɛMraom.$oVxFP͐9$3s]4?),'\d/xl+v}Ur=~C#M.]twT0mѬa :Aq)gOsc^&. Q+ jF8@ gW~=6 tcy -sZ%<$ z)aq9ت.OZ`ard)=8Ϊ(ZOقKmn1mo]"U#c'g,o܌vNe=kkY?cwSJ3-IZiG*췽۸nD C'Vŷ%wg|b)JOp۔ǃlbgյԒ.6h^~״~`뤎^_D/{ʟq.ɵʒxg p<j=TpgUگX\dH6smԉ:ͧ.exKhZBJW=Wg:TS龝sҮ7%\11 nKG$ ϊ;JG|\Z+58sEoYQ'Z%YQ&EaR]*.,$橧G dd9[u3>әa2®Ԩu &Cc*QJg>'/>Et##RP (@ TP@ `U VH1YC$G U_:EZmb77T6ex|4a? 7VvT*6gq5ZǩS9_/~em0g>sS,RGF7RDSeZvUa_eTkEս)$2P A#4;mWےp+Q҃,o(${%뫉YZ!-b=x|I/f>"(Nj %`a¥z$z82ˤjSwGvVm'@qǍ|Hpm2-j~_nI?]TXv,*9 [ $'n.>›쵗p^~ZӐU}AD։A`U7QeLm!9KT2FԑTnHMmpR zӶ^ OXa)^uu5sPU BO?!VѢ50JS󭡍4f%N (TJV2/'wڮqu{8 #eD g&NDž6+0G%<${03L-;Eemd$FG^v:XC>Lґ&\Ur` GqV)xP|<18#><* /3*6׻5n;-&ewRP.}2+|R8<8߃N-:4 aoK\\SLXAH RyJ'$޲|W#[fLW&ݦnޜtuV߯6]eNTv|y1ڐI=_;/gj)'{?cWehcWk]gh6iM"y}J@S$`ob3)5ͤfHi+W#>V }K馫mC筷u¥(*Q)RH#Y[f/" {=WRŧߪu>騘1$dTj @QR;{gߊ|O69 _6RКVtǩnkN7-s f$kWA2J35NYzy!+>M-їx9j_/BR6!X̚R8n%vIO$ \v'گܽ̿ҎX4-R)))Im $5mo(ˎ&֐x5ZRVj P @(@ {T5jMDHT0@U@*$ˌGu;uk$G0/4c_J$$(ĉΏդ{j˟Y^՛-k)jJL"K # JG^ IiN!YnĢcQ5)1o;)NpyoQ]*.fGԶOwqŕsjk U*11gDY?.}A/se'FΗkK ]Cq{ D+y?.A ^K(-A_4q@gμ,Z[ !JGo֏+i3B??,M֗뛼$ГJ3WZƒ3Mܽrx(;IQkE2M-ѫ6D@$$zn8mVD^Ecpfv*.6Rqw7jkwd*8#8\m2biw"v|xH#"ڌ7F>KhU9tC%hS*RPN0sR98+8c74%7_"ӬjW9J`ʐKJG׉?Í+JKO֝W7IedJҲj9#<JZ:K6k,3:Ϧ M!npV%I|$)9^H>(cfm;j+`4xut;CaF՚qi/mAR_Kgt|6[. 1xp(N=h趔:P}Y|kp",6@ =I˗ t[Td[վh/O.so\Ee0-Pj Ϡ |?7O[Tˮ4\"jNGo$i ̲n@|Il:Sۑ p パ^ZomyӵNyxu3(GAui!.lnlMm+Keq;w W$nO5]&Gr#ϗY7R|/c=.iΣ-z . ;jKSㄅoH'Z 8BUQ_nZvƮ: ݩ%xO >#Ē5˦?RWәWqO4=uQڻ 9*$~ǧWyь: LI2Gs ;]}'^+~'+KFR#9J/;:4ΙOLyˍK20VmW}F@tVE ONLP @( , r\ @(՜5"@PI͛u[l(p)V\k_Uٸu@TDvCc{nm6s9Z_lgV_Ѩy)]lgkY4;_܌rN*Qlf%.BxR?z)Gsڿ}:5WET5 ќ*m%*IV=awyLt_HW3sEUvkU7x-[;EߪSSi7:0S_Tp O+w+mrT2T}0?Z%#O 8T$+.2! ܮܟ׵^p鞞."/hZm:e%Cm@%K#Į6\U#L^jX\p VT d3[&55] _:{h[&էt}: tKhJSQB@˟iTWRdYSi]WzV80~ ؖR!Ex Tc_.kL2Z@ e~!l$%G,JJ}WgdÙJ&~^X ]wˁ! RA$07$Ay:mm0m:͂|.xh$%#9 zW>\T߳(jAWf Ԯή:xAm,% sP=5ӃMKO v܌-x*RёO5F{+wˍgr}W) jivmRgo&]:-VR]vܲc %H%'JO^'˗*k7dFƔcIhH5UPF46[[ rFryRq3(c7etZ7ڟqޏ:=%_L$$nOOfwWHR4pY#h;e&3OlxUG"FHrS6_QGsMuv=Cy,1y mwM7/s W F_t)jүMޟJiT?CHUЎ>nO<+S{Ҧs$mVWGqK%鵇JB _^j܁VP @*T;`U#VR fU$e+`珉 k6 BJ՞<~B yZն 'NH_HQ.Xdk$C~$p=Ü9/ߔzv6'S #$1N!sIa趙D}>7"Cs`Ar|KQ`ӽ%CJ[ϱd_戽M=7lvmQiX_(hHHqx\#=V 2JQm&sԌ7S鎒ubLTD_,nQsn%); {3c|W|ٶeMоz٥&[U4|Ch-2( *5-͍»e'nueի渵D×X>?OJU޽1>jy^ۍ#iif]馼$_ߵ,۰*b\s^{Wr[h+p] T1kٮ F{ڤ% D’Q1KzUJޟWSmn:OT4!$n;5ǩf~:I&ifͿ}A]ćd\WfYKa-RN2%=]EdoAǖz|r mrڹGAnSE HxOTEvegiim,?/Z B߆fU*_U7]3.hX}fVgnokUی=,AX;N88- MiDjJ%༷ÇR4Zk j"C?1IJ9mPQ8*  e]C$RFVgHҴmܝ$3pRp'VBg)$W&kaOR/:Jm7.+\[8[r PZ%*pIIk$mQ6@aڝcv%J9 3!d6 ΢l~BGyjoad!)ZOrq~vAKIdYՑW5Fm6T'f=ZC}bu!JJB}~<ARXLh*O<~%.,@[Gvvh$Ў,YTc),WD+*RIq x4j;vy UL.::p'U}((EW!O[½TZ@* P (`?d*c@zT@XWEE* I4ؒBue8Lp9ìI&slS\.C։!/$aRGL m?ϟLŗӂկjm"յCg\C ` (OQI[U$sꆨaĉwn2v ~I]oSf1ydΫp'𔋍5oj>-[a(pA#8So ynΓ/ze_%w^CˌZ[5B#M f K+b^1TGq؃aGp%gO}jvc:>u{Y$CQmlgn d +_|9FQʓ诈υusIEڟI\R(m lH H BT.C>=8pQ=tns:-w۫>p!Gi)qDwip c\rw_S5Yc)Z,nnZ˥:xC`Oi55Qe2?%9>-V-T#w((ܣQ5ДcU_S6wCy+h.;.Ip:jSLR~BLb`x>?IM4kIϹ.p.,rqkmImJNAd$vAP1զOz.*kn2l4>UŶZQ!K%KrI8IEx3͒YCP^K,l=܎q] q?u.>QYwc}6أc%JH.N@#S'L4)>Kq0eO'VcY󩐅IJrAGj6^"Z/:٭/fr\0|J֦M62|+kћtKŹ[}(~2j7R,i0Mme%?Q)-|"v.Y]hZkbHmp.:sקsC  m\<##M ~p-irbc;~y}8rQ%fSagMOX 训[bqn-%ml~^BSړ@lII_9n52)`!T1)<ХUt观DJ(yR$q$LW)BRT„!gq8U_y%Ѷ^输w,tP\EjBWel0P QVR OϪJy~ZRu/orIUz}Ћ5ZZ-VJ .8F|Ry3>opNq }`J薹Mt"kTqd:(Gb^P|ַumŦ.M0M}60A8½Jvdهp$7"ucjj)וՙo(1wuzpƂ)ۅAQ[v<% n՝8)tl*AƤcs师0e7G!ť NTOaomнG9k-IDˁk}.t&2V#ʴy#qϔsM uii"5N \=#9Vh<7hiA>#lB?~) P&[A8^|u\uߨ-\_bT4ZvᓁV9$W- Ƥʻzs7=ZX[3Y`wȌr`hĔ+'ck/9WFmg]ڵmcКzT6IRlWHVr@f06fJ#G5mێy[|EDHex|Fie;wa16n-,|c2+d슲` m!QQTF6bIYS蝥el[nQ8 86Khڑ=ڏ$|Sڡ<4fԐlHMpH17dHw=` =+ ۤmmUz=;z~ԽYoYj㨵[d'!mB$:+NⓄⳋolÅɆO-jVO!66v6FJ 5. f˲IzSψpG6l )ԽoJ=CrZWk 5G821cOZ}~4>"td;)(onA ډٙt]gQt fN7' 2G| 1l7_=/սEg+~۾X[o'`.5xd\3QHӺvK҉chJZԐJyvPߌyޝjxSdžKz456wTX5vs o6eVМ*QR)˛4xWmp}G3ŏu%^Ʋ鶊=d4K ,IMAaPSqG%c j8t>Y^-շG"դ#pi0TP%'k #,Wׁ6I>n}JԽJ=QCfkFkR*JV  V}k3IZ8i),RR2Dxm BF7Zˇʰ #WK#'_:6&47M\4nHq*n # KK"ZjM݇WO-%t}9t)PL[P$FT@O`$ ĒLZl:Ipw'TE&P1!&r/! ;1cߋOGDrt3׺}vVP:NE͸[DTZ[*%(N8[O#2{ VRPpmIJ`CL4{!2RtNiYѮ\i&i뭖c4d)"Aڕ SOGW<}q.4-750]KD!X ^6wcv^Upcӵ gDؤxxyW9xI݃+mrn"[q!)i(WR`eAF3}Oa$:~tI'jIfT[T%)a"L] 'S88`eKv[o̾C8A'89f`S_ӫ d4%yVm> ?c6wŋgݥ(`H jZ~L]LH3Nd@t%$Ą`jۓVCi}ڑq1dC }3ZԪ3I1)ifB^ Jm`Ea7 ^ z@R^e҅Co#f2ADqjtd}"Y@:'N,]jqv z:NJ8?y(Oxy6J*9W|zuR+Njrli#+p-JWZ]̿yu'X9AaKFMl)PZO:IO[ c?GRãI3竍@{4y' 9Qd+ .cQf!^$EٷH?cMf>n3m%ŤΎxFOf2R-1P)HZڦG"I'HOXjei+2b-=23n2 K_H LذFyLo׽k+L ݲ{i\KKYPHR+P#8)f^LouPuQ/CJK\-Qc!1CFqe[> H̾76~a5Ϣlms{[upzoZ * <p2I)*ݷh(+m<ϯ4,z S`YtnȧHP)_8sǛ9.8 ޺SٹoTjO)r:JF?#_cqe_ 㧬wPjCmR+JBBҤ# *Zs'^OE-}MmJ镆N! %H0.lq8 nm gXK<) 4ei_OAiԸΟGTY/cTv`vl>:92s]vr WՃ^۝rP;)x$6t^?lq0-Gfj,4-W صO. !LkصBrzٟrÉAH hCe^6. kT-?u515oZj1%A`sk9F[=,c[duh _Jeˬ"#G|D!+J|B/8}ϭ^JN4?_:28зtSZzMJecHj[!Fr2 &4ơVqi4͸y:I~",wK1P`x4,mHJRR  #"<> 7N]qlqptuG5I̵"2xZ)Z\I)Vm'8}YGvIs`ˉȻe'ԚɣwM-ۈ}9c@*YjI)"ǹ[fskNv ɓ?V[m,YpG/d#IJxI qTY>8E^J)j?=HmhM?Tiw8bLRo:\s{n*m`*N9"۵"KkItooYdMnc,ף䦖}Flj )0(j@TP!Voy,* [$imZA5b_NH5hzFfE8m^_BHn@*Y G˭2|;9k_i(hk;W'\dU2]teJu*lmLM*e3਒O%#9gF :ˢ2-_i uRs)23FrFĮ|]VhbDe%) >"p9}TbMQ $Hj싦[3Jb]SsiiacN+VFt+LIZK5{,P~m|}S) }k=O&_s@&J@8K 8#nr S+dPRɘ!!GqOsg^MrLwIoAs8Uݖcm| \jB^t=8Hu/#W4ܷᛯ{<=x'ں3nMj5.=;^Gږ?:&?R&ISuז]_Ve[PeՄéJ{~^NW Qxvvh6~t.շ;{y y$);mN8j%&ds6hOEu xNlvn!`[cyFB@']l+O Nl! 99&ˣ6(H]͉N8Lfq.<(BI?a܊7P($QםaY֤l$`pCLm9`y,hXޕi(RH KɃuf S$q"RETm7fjWDmVuս/ I}4ZNJ@PJx ߑL_6wυ.Z (G*~=)Jvk|F:4U8?xcU$:ZצlY [m,KN$J㐬d>6Mb[ꗳ>C,P-nXovS"1ӱo ?49IJI;qm\WpӴU菈N%%FtA߮S]|.4c_! 8HI<( 4.WgcnKK3LH76]TIO$n,!*ASԣ'EYj\K]Lxe$'fۀ0+1J)trK$/]=åAjZvh h*Il)zrSGޭ%Lگ֧ċe+r:?)9=U$=Z/i`P * VrGP *P @y5!YI$Y ˒H}pKyjIc7 1\.j.Za()NR9⯖α✖3hcfӭ:&KLSJGxb@*JVۉ ϊ@-Aősc$i>΅ԺFOMhE76JQAgrRq7AR3MUtƦ|5m}j3A CHprd͞$:Yョ߇*=Q1͋g.XLy?0[ ؓ#=Wg6cK7(xnvXLvT )'jG#sx $r+NS{9FjcE(raB?)(ZVScJ53.@m\Q0pFkk}U Vo6ԶZ|!JVu統Hΰut{f,֏ nTBJ}JB }RHLI?<sk,>Z.L v)RULJr; 'i⟩ {}jtÝ|Mި]m !^RY#Q+"s?zu}K+^4%@q% ISqX/>GHI60ǧyh%č3{Tʂr\ s]Gl<@ё ]$gisl8cۮAZ1'hϨu?k8ْ3_i2[ĩIgt)8? ܊'D>atŦɗmCB*BҴ%{b_1]k.5&i?njw2 AZJHU8o8[}Ӻ~7K3uEnG(Pv )]Ǧ_Ln. "TRdIگf ؟ IUQk)gֶ \'PdWȱm3ܜM~PXR<XJIu ]KSV1 B`T׭j yNnQB'8m pO|y~򚔈T$%q$ए:yݜ#ECQFCqPNӍҐ خդ xRV@qY(_͜O,= 8R+<Ϧ{=!%?MJo1$վil=!=!9[v!ᲟPn\"ͩ~*:-5dEjE"q&)#xw=+lbc L3 5GP؝N9;x)FRyg,ZJHƺF5-.i\{+ah@Rme!i@<)*/NES\5g.Iʼ2dt`zmJ*gl@kKqi(5)OFR٨r:.Jو3S?/)XV}M0q&Iwjuԏ2IԼF?{sg@tIzE:çZ`4pm's`{TݣLS&;aZZ]ii Br WWgMO܂5t@>|1ErMj<Ղ5 |šz9pѢ:}VOt;v,lsSs-PR28<.㏦ ͉d]њu/7@HgkRI*?$K7תG`s񟿵tSq2[DcÒe> œ=5[fu΂-4U&>agssfld k6O*m6":q2lǿUdTb°3Dzh&kw-ki=ϣ>.:Wdz~,ۖqhnaORR@f:Ў[Rq2+ɍK%u_|rZy $Ee៛cZ;!N5uZu i)!#9 yI':/t );߈ӏڲHwcY'<]tAl> έs33S|\-l-/-)#,WJn__k ש [2d_ݶ5WWr4!\dyֶLI:4x[n6Y9Zy[X;#_$G&YwF?v;ZT6iVsUpHoM} 3nNlʖTq ftcnFiXͥ(zjT@VW8T lf*d4VT u2A$;ݔ))+FєSyj'x3T1;U[!% 2(8sp~>dWRczJܮrq@25.s\PB"aO{OSW)3iGPx6 ֿ{Y\ض$}Z?@6u^Q5 эI:q:C@rlO\tt_Glu9in((OBHES|SWU0dkKS6M*GCqj6%i>-3#z@6]t~ՙ΁$z!I# >N>}|3~i?-"ݚ.a21moD#ڱnKk$ǣM]mw1"2-nAW5yFo&Q=/^٢ņiw|V8@Nڱˋ&jGK듶Qg wNͰ" P/r$NHErNSGwa9+sK+_WܰTK5[}i(vP9RQ>ֹ?|ɷ>OpM_kn٬(6%:c9_:G8IWx=&g-=ܞj<]N~6['+j!H'׏|q~j.JF[;&"&MC.LEoHBVddIلt3+ǎ/ <(=ґ_z}gX?Q-3$:]Bclֱt:~sЭ8jA[= W ڣUP PܑP<k5_zm;Vk[ŖAHJR9WcQ]tJEtbjop'kR5!<-*=Y90 +Ϋ vu/@bU1@./ ?Lֻ8Cgj鵢q-楸)WAeCHDB*Nb?5ɓw r4HRT VՐq*QV9'i>Z97Y&u RaBz#q؎燳ecyx=;cMښ:#WIV"uNqRVxio IS~!P!JRy 5ӡ͟S=2p9WEȼXy%\nᲒTCдeDwF QA5ۛ ^?|9Q[IGhI[ v: qX#ڼ|25|猘}J`Ivlkmgq@2RpޯQd9)j_OwR#]!i#>i#YJ?扢%ńumcb91\-_Mor[*mnDuLHV2PA]T0ٓqdo \^y''9h[/pCu6.r4r<}q[B2/2bKd c ũE` $zrNƤrqӫoPjI7֛yL% L*[Idrq'&ؚE$Hǯ=Km֋BmzBVPDM#֮5/Rٯ2RTN)ԭDEFNMJe*W :̖w(ǯ Φ|*[:I`A)M~TQC,.-G+YK@e\βdx7-hwt_ rZ^LwcҤ۔6vTџeӎE㿳 j{\2̴>bڳ-,+toB$L+K͙ A#( ZR(lP&LȺ ٽ^uNd!* ChHKqe(J}Ir[W6x7Ϋl:uFAj .<v2F.%M,9B@UǛ-N)dS=0ͨa=7-)xS޳ƺ\gۮS=!'{Mi$ =+QY1OLd7y.jv-N!m5rEM(?0 8QdQo|x q#lz\*9ܪ-[[o,2m7 a`g$w;Z.0Gz(沿BL*S:Ӧ}[MZN6;6iR]GЇR~Vu_$NZR6 k8 :'M;5gձZqìܧ9ر+DZQmRt^Q|?G[^]2~&1Z9ju`"KH27yq͗O-^ktC?aΠI؉%eK$p%d)9INYq(Pn[M|èD!ipyƇd SPp|>?񼏹jN&uy#^8KԓvmN.mNN0j H?BjRM3Lr+7ĵm[@m#ԛkWFg*HR;VXqリjM|;,Z;n٭l¼[ᷬ:Յ|u)@lĕqzeӮ(ZoZ.5]S(@qh{o;\67҂R,?-#*Oz2~8sWQFzSj+? O.ڳ7~B|@\-[}=jT[VԞ>jˍnp@#|xw^=}E>5Vm#Xq8yHퟵQ˄FmSk}q<5$NIqB|{bvW,Ԧ7M`q5{"iY.PkmBPϯ)8Oڬ:†>-EE(*01ds龹:cf*I򮛣mX8fއַ c^E+f[lZ}H "(G"+4GhW%azzD.5ŦŴ:;V7|ۓ<Vg$r\ K6;@̄89BU>F+¢Ԝ)E985xPb85d:"Wߺcr9<+ sٖKF\ks#9n+ڭzΊ9բ)FV&K +j#g;q0.;A(JאcX?oQYn]u^F_3^G#J pPQ$qpk88g[qio?xijWrx5;My-gCt碯', JU(cuGtI xDrҿmn)A=c5˦ǚ\L!2ro&iČ#ZqCKFS¤sA8Ƕk<3zfsHBIרm7H+•jXT⭦ՑR ga*ȯkKkȥOܘL=t=?Kd7f^حmRlHV0 ;gҽܓp|qjٳ[1׮Kwq٭!/;s裎T,ō,k}L)U[ +vU)Bj 3.Ipccn2 e[ܕTXw!!Jl sW(w]U-C-.J(F}HJ"- RjZMFmv AwsdmaRqگ\c_"x5]jg*SQo,S\2[j/죛DCHeg }JlL@e@M^/RtBzZ2Lڼ@eS@CHHʔd M]YMӷHIiX *?|HRIg߃[߬.ꎑh ҷ2 [}T?`\ӓi-cgf}+Y[.CYy tCfܨB"LG)@ TLcm6' p^dH) 8dV(͝iӽbZnOZ5;iؐ6^KGX_-Jy=)+Dk˵R<7[jN1RrL,vɚ /7Qu&T Hy 12FM$ 6_;1-ŕ6"}"#T9VMAq_R/7/gTAں_ڪ:)޻dXR2KxYR *Μj4x,KbfqYsle:q-)%vUEC z$S'I> T'ԋ.Oybm]ҏ?$1qڛdܜܣqvjʖ:TOs$繭۴pgn 6g`9mXtlM'g{?ӌqOCbK2;VI:<1(8u?F-6%-n G5INJ\#e;r3޹ ѣ'I+vF W TTJ]ڔ[@(jkrJ%2F仗x{g,hړf=6G)3]Ҽ47(kXg ѓ8kѯ?IwCXY#- p|'$Ja89M3p/9r[6u~鮟9ln \ LpjuqqꮍԷ}{iŸY[̩\ J덠 fH|{I)ԫ?ˆէџr$0Ety8CRG#֥% +؊*&S]SuDm.N1_J1KR.A&Ug%@^:Ƿs::OBKskhڰ.h䨮6BD XPUY"V1Q@[@( f!Y3SBBQc#qX'QI)JrG{ןNo\}-weF⢕z^+|?+4m1ƫaޅ{aJ2[F|-qRGGtnS+ԋEr? 1+TՙɆ?oT]"_:xLEntx[N+j`,stKll=Q۷X4L-Cq܅cZu EMVO7]=xBe XqieTV SN08dK܍Km ~B{T{͖ȨeI%H[A'׃"Lr_gL%ruiIwu@vY,[$8IM8挳Aq]唥$'̒s=D]yC2KCOȖp'j0G8HU;) վ$VH>em);߁QTʛGӺrY'=+`~qkLjG(W?QgDvHj/[ *vB}r>Ք.S2xzg]zF5'psW^ꇸanT9y,&'EtDuƥԏ4]'mM"2IYJ~NOB?%AW:OLHHwk>J$WPTQ_osZ|ƊiVX!%Io5ڍ&Q}po+P0t'VX,em{Mk)vm:]/NQV)x:#ǤJJV}jY.4 7udY@ʨ'kiˌ mY( ^JF~]/-$X2s'4}{k/0 2JY}lڹ䋝ӻ \N<ݣ~뀐Fsڢ<3)]hh"PM|;TTp?:AP @(CjRNJnHwH9Քq$`:wyןk,%nY{锲DXPHOW{q(++f֑۵k5x _]B)Z^o IЁYn xˈoMHSG )$$t)&jQN.Vifp/'6ǂUsy)iU["'DtxW*/]魃W]c"lvC~RSC%Ť7`;WS-zR_ɚ~ W"D9I%O:9$*8_$ɧRFѽԚ7e L:lVn'b0OqEw];嚷U.6tiqF/wuo8[,+qJ+̜?ĺ1rf(ٵyԗ^|ꡞo4cGiUpe!ǚS&\ oHO9k9L-&Mݨ"")pRBӒ8Uȯ&?׿_"9ZTBX*+G7T,5vj㒮 @"JnBxN;cDZRcJ ch}#Ou\M0[A_} }I伷5)rd>Z'b4,.\薸6㍖nJ%-֋cr}D=ON(Zˋ*'$ҢGE.b  Z7ֳ/f]xM(vF)d{EY'܀Y<[}6frVTE(@P FS#}mOo\b4KZ$G?Z@D{ v5Y"QYR9ՕFH-8xI5:;D]|Tdzs4]6SP+X3J2ʊ"*J` P @( kH< *I V쒛99ɜ3T?;nJ8˅;qG+)$GD1Z_Z05S.!3۞bi7{Pok7%ܱ}[y@ ڼ$P% '5eOu CXeNɄ 壜J  ›VC|QuU nxKaթ*N].mVAA w>#FwZ`KBE*!) ܴp{Wv{qS;Ճ+K$QVe?#A@d`e ``/B1u1c'p($`+$p}1͟ԂEdd8}Ջ4tһrBj#;)yJR U ;W._'4%mO/Iy^$g Hrg I6 蛳֟VЏ$]rB?׵7>W:_.6PܥWLhfu"vzC1[G<I8ӵeK$:"j#]x)[Î8@{LpqT䚗F_2W{7Ff{vn`}jTH|+~u kF^.1ή9#N8Ym,]7˃W^PzJL!!>FP *>Ȥ}]5V[S]2wwVG)(T'khl,k C<j-*MJ쒪" nd;+FI?aVV_:y edv9ipjFL9Y1]uƌEYz"t@"BOu@P @xXL˒޹$|pHh=$iG^8+kW5sqA<<%M_5[£x tUy_ n؀rF=Lݩmf-Ɍ);zm m(Ѫ:IT9 S`9Qʒ1 rxE& 9-rfk1f.EK($dR19K3=+Jqt/0:ͷi7MљЕ:2nl] YR+$|~֑MY:xe1E-FRHR}qoS1d~Km-S^v.=zLvu /8 +KX[R*QI#\V(G;Y{q&m6d0|+NᄩD=|fuft{p1$FwP)RCo]dn))F@pTnnO¯;Qݔͺ<9>q%Zpj{ܢn3hJ]u[I^ %-qOq $V-Im58ZZ͊ƘmBmqr>Sf`~Bd֛W.V[OޭBEL4/E4RnQ9[M>rgmTW6~'_M?Ӧ4~u;\g^+;rE Ї8/A/;qwwFڸ !H`{ ktzfuZr ol7+ҺV;>B34e(i r?yy -ɭ:xBn_LZǤI&0 T3 )ϥC5#ܐb"fÎ9ZpH^?4V`DLw$0Ҷ AhQ Cq\7(!u eX3DZ9ZGb&_BFxM!ԐCJd먁@((^{~V]@0*@$#I %${GW/ctEBV^ ZТ2)>_=ӏ4%I*Re;mg\^ibjdŐ%O(xj"H dlN#>%b'xwkk&jr#%--J@+'!Y59?OTN7 mݢQcnxIPJ(Y`QOّhET&uY_"sunJ6JNH)R]:9wuMW4rXY )9>9[F ^Dw2ŵeB/vO! u*HK¼du8('$\E+e2JN;l9hy߷ARvk[`creG=hp2VF@9UK/6jΜ42q->KU?m}WT0|p]nLgT{:DvH?KaNk:yO=gG $ kl8?zu7=ݚ).KQ#xCc=}*YRܣNkbe?vQrwQHQLI'OޮhBP AD,KxFZcᵽ6apX;'{0Ԇ/|kZqP\) pqWFNlww %zIǦj( (P pheKz:\pHe@=EyR>C_vҝ)*Qi~23rqg8氖y;C4ٞ:Sű7-%BK8R H'rٵ^Gj+z{P,؀9D%jFH'dlt, Vͣ!zW-՛#d{U"\+rqD${ջ d @(ڱȮ$Uy3TJ>I k)0GӽYGk V2zםWx`9(:mM[4B}6|wM#.mÂ,8ٜ=)B7q)!ǃ<ϰT)E ӟ.:PT/>D1hEUL͹0n+%dIDثd]wi;v6林oG޿/8ʎ;}jH.VN0BS\q;RNۭLvIR]8m?U+>䐔CrF/:dUKj8KIJXuB߀3GU}ѴMF_:_}{ӡf G|:0T=AZ3pS3t0rkD c֢"4O7>`U$],xe#?T%è'jͮ #x+ h(qh7Ɨ]Jy3e9tlҗ>!TILmt(P=9J%+ue,YlW|t+IW5 4[* CҎЧ]#?dWoǕ)Y=Ons],|?U)9 uGll7^2%#l$6! W^TV Yjި\oqI%h$ڶ*⎅/QZA8?%FOeucRV IUa৥rO&.Ug{!e(v <~bQznΔKc)Z@`_Gc4JI*[(׊늯(BcA[%KZQm".I;%; "ŸsRH(jBBQEA$v3$KT y e~P!_b1P6UmrSO* O˔0IQ ids >jJVP>tE\\*! JE8 l. #< g?!P]˦nhr  d!M!AA^zr~t~*ZFw0N=<Z+T tY`W#զ¨– z%}!X<Z}IZBJWבII+KۊwE,ԶmsoVJcg' (u#7m]ˣcY5:E,][im %')pث>z4cWhm@FvF(EqF\bRQEjq^K3&ڜ8}6vO4 |# m"FtҺ"3ҺEUl .yE`]D @(*KP3"ˣɮW,CW >e+]iWpeMծ\%NRn wUz,3WX-K}˖Dvq5~?R=i>5yE|)Jm;Pt-?4Bf7vJ (G>:0a$.6M#OR\%9 RI볣Eeg Ԯx#ؖ4bѮ+ßl=xQjKK!'(^V-Q% *B\ >^ҡHS jfCaRA}:\ }݋i }ǭC&& ) .= O%JRY2 $wmG`IՂ=1A 9P(T]%ǧޖI[6}N> G0T@]`iWě$A [nqw Sh*L-LA[f52\jR `23i:`0Odv檤Tm =r,Z|4mVSr>{7.heXjl{} 8RcJ*+ۂjneiYaӳ T]ȸ.8ahk~@?Jqm7_$\zD#Gv!' JTcOasn}4#Di #p} cmd}naX->$) ं>xdra.T8mh%)ܝ 175%HZT؊e7[mvH2,JFqɮo?3E2{C:ǤR^NJ<%QC*(!71,reG\t{ZL[6 |5ȃ]j[WuH 9$!" DDnljf-EBm>3<eB)J2GұTg!-%)v(jY| Lrཧֺ!G)*,T T=AP @(%pfV#_V| Q4Oğ{uCgzmu)J{@ AW}y VQ4qZA7LC?UrG;jn&Idc8$lE޻NAW"Y[زqUlr v3~aHRu'i䥷jIR*7 CiMM6//vC[%)H9'$|Q"㠞s?Zfej]kʚGR#<+?gvR4ٰwLcy!J_.Md[A @)(PW5G&Z;lnEMI3s≸ZfKԂG|`4،1n߷qJeKR'ƊZ=!{(s޶ʛRɤ7$?5{QFۑ(,Fy$vӧVsfs5n~Jpo7wUtEۣxO-b!!Jv6p7vZԢ|.ua[Z.DqG :t'<`y9|IIkYV)$Ig!Y<SW T๴h'>(/yuYh8R~fcmN,(W>_ Yףj6$᱓U[HTBdÊ.LJK]8S6QCu֤3!&fR^{V3jkhAIH*H=P @(u|Gh94#mEe\ ERP TɏU'@  Ɛ z8߃Yź1j[qхF KDc&[Lw?n8FZKKSQ,W rٹ@%Aۉ)$>k%(IR6΋{l](sTŵwx.2+;{nW:VW۟tA vj}*e8Is^B8;G}o'XVMeư(- / Rn})$}ѐܔdJ -'?݃~Tod;hvJ 21zBEgF7RRA†Ej̎kö́o䡅o Elz:E(uW`Rn3!*ka qiAAH*f)C sUD->lfDۉ}fոOSy)"{VpB@N -\ڍ$WZjk9qV$6\ʝ>ӫ xE~$ 1 ZyAɓngmimaƑWѶ!ix>IH(PBy[iA*Ҍ5ov\l V-9=?MvE懒Iݝqyƒo J s$6Ιõ[MkQmudJVՀ݊]>OWdxӆ4bg%vrDe&C) >IٓjJ_#p#IS0Т7$8AcSI||(17v8lFCnxH-|N(z%#?)G֥鉋K1&+>#'c#E.Mi퐼Ftyq!Y.FȭyC`(>Զ~VqQB^C+mMSGg]̙Q^n:d-B'#OӉm.͸b>oB#Z)E:_bmٰt>pvċmZݸ%+haRhp(RH'\ddmfOvji,V&Q7x%(8 a99)$MQ.6蚗P~ͶlSB%J' JZWۢCbQm7;{s<9 ڄ:T8VT;yRH#I7 %Eӫw}Ej{/wd0^eIj:+97٫irJZbsʯ(qWjT̺5농|Gv o!dGH9JÞ1߲ScKT+fkݥŌq %8%)JNTw+=#pWl w Y#JW N@ %;V$l R9yi 6g;ek E$?ʺa&Q馄>F JԒ'Uՠ/EC,o^ˡ'l*݃ Aي+Yke|Ս雜qeIL9mn;N2R$8gL9&ݨdGҟqIeѧ4KrrF9Svy<̈2+Ex9HҩQ_$dVNbVHӢSmg*(P @CMbP#V %hGZqW)'Ft~{ ۃ^z>sur#)HHg5V^k1۫%l/aY0fYE%@CDUHP=VqfX4wVK=Hٛ$g/˅>') ;f^9+rMƗ\ǴWEӻwýWzzث78I(PMKſJ,.+B+ilRNr2}8mTWV(]GFVWKUJbYHZB򢒕$~yŭuϏ&d4s֜oP;7=j :VTܞ6(¬־[zg捻q]N޶j=eWkH1$`-[T!XdV--I2R5V67}ljHo !<)< [V䒓޵RF]2ӗ'? s;06+*'(m޹ofHǤ_[N#)LNJRT%@g5zܾc8&VKm.[&K~3PRRWe8 /"&L[Fז۸%2p(}3["3o-i)c?ZMfO^7pܡ&aD0'+ rR_7]iNԛ$juDrZ<(^JFw@<LY2.r{zE?[\-i.wK%c,g}䂿N( $7+WeW(o#J @P7u T{+D}x5TEROJd HP @(P @( n^~Ze3:fF!I#ۊzlt<RN]Dwd% rtsܶh# =VKmN#”O{ZK"G$b:}0i0c^6%_=rOn+(w,qIrozi}bu4;t5AsK% 6؟ϵX9(Kn_i:9=7]wL7! g(}yRFH) xCM:I9g-^j,T"C!a$ TTz~,~"]KN6|E!GTp+]24+dm`Sk!L@i ԖX)ASۜ9GqHӣb! mf9n;{RKp8R*JxY%ŲR*ܻ^»MԪDk3"R2oYzbRaBURJR|rru#P'ݯDI*E댅JTeoq^ޕUj[2*e%5]5z?=?7t}2}+JHy^ugf|z>D[!,"N(rrrU5bTfw~ܴiv Mc Nw sq=̣LEb]Ж"dWwVcڊ*Y^) ${sY<\"|~"3:**C oxq.qm$f*m$WInHV}4xͨڞo}?A]N6sDe [ί{y}T={Jfah6Ԛ~b^|7 P⒥yIHJROV2CN|Yӎʪ& z,\IhĮv*FJGnRPUcj1Ȼ:q;PupNFU@A.8˫*JV)쐎'>9ةq.cY20{bhMQuӳDNzG~}) (˽=:\Zb禐HȌ_Xʳ)ɵ]Y90tfkYlp^Cs缦T-⺡o<ޯ6ajkWL3쫍 jv1iXe yLJqk$¼2qNS]YӺ;CIpN[!(d?zu$q&2Qdnq]=/R.D}"0/siS,6JT[S2:N_+iBTplY `)$ +ir7 YU/ZᛅalFWry<1Q^ {frT$#xUn:!6˴&-6?ۓMj뮌)䫍Bqx򼯦rN;k1k#7ňXOGlg:@<$r}ϠQ_ ;WQ_זZbSr-I)[iv=z2t<٭bG[ϺYm; JG'+2рh?tF;R\sJjڢh+uwrCY@@~fiu*z|ř,iLa0ecrmAIPpkҌ+G3M:dڛ_H< *չKj<&פPP @(P @( Yd\Y(ǵ[>4Ҽqjsd2ٷƏN' Nx3;;Z9*fvZnd2;9.C%qR ;N=pMa2l黔\ޝI$5hiH!kW 1k*D)*ΗIlhU8ش$Nr9) JPHJRP!_ݾ/;%hOQoRk!owvRRQv\ς*iz6Ԗ9|ɯ:¡Ɇ/9m\)B^ nkyR-z=&R+BZR @;W9Mӎ6i7K_.ZSH[kBR 9WyF\QRUtk;E3BLZ4ŘqòҧmkII*QW* fL6P][RU5]׺s[WR~Xtqݚ~u"Wşeջ̫PK6pq!IRV'y?>gu7s:?j6~WV-d!]r:\;Qq^R+ӊ'.)}5k;Cmvw"0HRݤ yɖ8:0BY#cJQ.RD!is`7>]dJnCZ~jBU)jӹk (,p'l{( K6)^/vTzL8 % x5K$%|ig\k苵0p$6WˋV0ON'w5bCvrټ..dszi)V @'hR5QϽˢEmַ..evnHs~J-܇v|!Fn;3v܍5CؼKjWhǗ2$2}KVV! N'5>M&88EKRpB=R3VmYql :Pҭ^٪vx(-Ld7bw9Ix-E'Ez-;ZhD68i6=Ic]NE˅r KQFJϠ:QǗJk/ÝY[8ڏK2 k-Hiܠ3l_2pRXbBRm%!вFl JF  $q+٦/GVؠvLj<%49u\}]tn]m{kimt7 m~R2_ +̄}]LpznӋ. io>c]L%2VNA'*4󇦪W7Μw-k 䌀M_6ҲRbu/ bV÷dL$Z 0>]\nbJ螲[^`DVlNȒJ\k-Ǩ#L"ڦ'Q|?yw+T=k c|ֳ Òg' ~ w. dMJ&T T*(H$븨P @(P @*%:"uSuJ^NܞWc]SSxPZś5h ;sJ~.tQw>FG$4큔:Yk+td1fԄ).8%G9}-~Ivi^_~L @r2vlzV9iFP|OkO*ևE5u}O'mNٚbzC30^:۪Stxua;1 TH)۴w+iܜNx(s|R^/eњQqm]VG޷J/&\`w㠤+ϦdSr/)cN* Gщ3Z[1oS˽I'Hڴsib2tGoP_5<^xJBN^ĠI.O0$Wux_j UԻΚ5;R.T t-Bח 8mD`˷d_͊;\=.vppd;# 8@n6jQÏ"ƹ*}OLK.[k&b8NnRWBm1aj S<\RG|N!kk_ժoa}T6GF=?:l4rRuˣMSO83B2ִPP1縫*{e'g\unծ ӌ&6#VӜwƯ mrtFmʋ@V6z&+VR4 AIVZo>n q Jz)RmcxAK.8--LZ1>f*3H=Gm#u5ˁÇɤ+UW-<Ǝbas~m˖奥 W(` rgp8Fכ_l.|otbaYZ^3|2v9L42-jJ{$qh58_s,|?;q-pt|UZyC rȊi|,tc/G{ }!>IXOrI ƓL(𾆝MeԦĉP.+7&F3T<}+ۊdj`_ܰ\eMe.ԭ۔AO5IttQ*~& :*'>dE3۪KN())p1j|;Q?jAiӍ)|$ #?JbDr;K Y1bksa3c; #ʱV]iN_HOrk feTmb/{¢P @(P @( {Ud Nx;,-&ӳXV|4'=Ş7cɹY;FU4sKZ` {F~'r6T +"칫-BDc%(Qj|Bk[j*"9zbi}KR;6؇K(#x/=mq;*O)әVvif l41]JCcO>Վ*SEqd3ק K,Eql?mR;m ؜njMrS%4F6pqn2ڕ $%azn$}NqZ96.m=E r6rP㱝m2OvHI\Zp)|:"sYp>6ƀ)(Q= ^ӳ<\6[tKNՏ!l)6xm-!j- {{|rA_fLh}#\Th6NҡwRJW߶ݤs]h' :e_]Α RmEſ{MԺe)H `Lg sV57:i"ۗ!Nne,)[Sx eAj2N1|ťx԰Ig?9SIsnGcV FwSDΛd2)H+*,yi^zP~ܜivk(ʺ~mp[ )qЄ#~е >¾s8ZVI} )JN3i`*T>C*xdJsڼsCO?_+xcVlVKNTs}m F{+$ >缳=(ItdLJ=g^)'~s6TO|w)_<nFI\h%`(,xZ\lҡjRDOZ6UؓϦ*QIo%^NAUhD7qeK9ڠ{>&/7T0hVJ `#C sXk1eOO$n$qr}򼔧g+uw Cԫ)CmS۔g޽\1| V7)'HuW7k6mn °A<>cJ,QƬJRQhD@ m/8ՆyQԜ+E]tjKkf>iWy^uEnY+꾙cܞ9rc,֔]mcvV|6+ٮ.Y$:S$^Gߊܓ 2It+.ͲRKr K!I^O)._\/;0oXڔ궁zH{.w. sb*T+g)ܝZe *<`r.'ξDͰ+.rTx681&sm!E~)RAd(cDܝ6KHэC4nwMqm[Z00I;ps{ړɖX-|魇LoLB|(VT6CiU5ϞRķA ,}Gz1N.V6+{%ͩBR;d\{ fy3֦o.֮R1Џݠ2 sUpviiƙfm*4ZcJ3a_9#)ЮEN*3V]&[fi_dɑ{vtvi+*B+ %@v%5:Kԏ%ӧNu^}Zn(m-FRҷxlIps\|4PΌir[nZYqiMO E6Żu )z\F{*qZv8-Kou*=#0շYZ[mC :g9ϣ6X74/˓5UCʈ[qLE8JUM=5MZ&ڐYZ0Bj8oؔrB;-Hs;\8RJTRI:Y1eI{E_C7r̒q싧˱I^^[U*Fz3JGU)1&ZJZJeDr5iE$UߖSm CjHT$M{ZI@j1]#]?*UΕ,UՊ Җ78U;Y4(Zv5ƹ9 {WB~5uςKUQ{¢P @(P @( @r+Nj5$l49z-&oG`R7Ϣ?ʦ))Y=cuVp6%.M?"2WV $c&9Bdʍ)J3oaB="GV` $sC~LS]|fܤ^gm~ [+q mH8Ad\Cz>8-VhimM]#2v߅'Ye\)ê`ډct΃UnN!I $ǯJJ?33[σ EMYI ӭQys kS:0i6وliP*#qWH15 ؕ.iPZIBT;O䍿>8v>|!=wD%*BpfTJG {}rWoc]f}O"ML?q&\BІwV_qLXԺ87WV.ne*wnG˙yM<!88Q*klJO$>LT]tŢ"!29Ck)Z$>ƵN0o kZ#rƔ.s#%E#.=Njq*$䳱!-nHIڷ75 mG.[#.RG8=«5G%]AM2--&a=tCNm`aĹ!\Vu|G1sc߷Dm!i[$  {$igK}CZWZG-lpBFǓ-&~qq鞾7ÊE4-UjDdoIK`\9d胓CֆБ~"w7 Ts$p3[$P!)G$yWDrn0uD3VP`7UlZH7 xBBp #Ӂ]PdF/$c5VʰtH.uIQm!U&ITٌ pE{Z:lxv\d<9;?$J뎛95eZW|jRP RqڵڗG,gRGCݺF렚bPv^{md^._3.?Ǖelt|6rQ$ 58GvӖiWNFpEOx1r6Ə/P'!ԃ${j͡aAUU16ƛ謻p\7̊K8>j=eO6O:r{QdTʹFFm(HFqN{Q[W1E`qZ%A*Tx P @(P @(9†A=nⶴFIʊ@(P @(TP.N"^EL'g5Y'G'|K~lR'A V^Z1|7ᢖ^W<`S,wAI4)S9#ī|.DʷB0>|Җ!He#)IؐrOt5vKt}Ukb>>b!{Y|G G$s[KtBYev^n'}1&i[u:YWx.6sT@ϗ9=u6˥mn=ōC&Ca%m KSc'=kԍ6p&+.wSȵ:Ze!ԩH SK @;UP+FVqmjT΃Kk.iZ_I:f7ХKJyġ+HVn`O"X+tSG@u"4M K}& J*М!IA ;Hr\_cэ&?:7󩺃 nim&urHn[KHKA'jJ~8̺gN:gzcm:KJikS-CR]ޥp@ !jlV9tڙ^/#etQ:ceӲK\m((8A4anSzxF~2ut/*'%8<8gY29U#u(W>Mat4ʑ1R $֘0,P2~}ry/ޱqDuJ Z6$wvVrF28ϧ@ERXXf!8ejl<@ddv.U{].i={wvFfȖ#$4PVvwdT0+֟#ӊKc'3^jqcKLȯ6e`l^g%mp3su&J:L HRwHXܕm8#^~[{Oy=ɶiZQNYf帕);"Gt\A z$(I.&>jVݯ ħVtA[n\8(%>e)DgM}Z嚇T?rsml%WRƒa6͓aږ)ts?&^v{=u3a{ ="m*”x@ b{OEz+ݴ`:n!"Aq,#ݍZ|;(mZZ[52s, 40<nxN%=>XBuZ9-Qސ.#2eq^mEjc,IWm)bxfivҳaƶ:@ylمAڜINTysgƢ7?DUm[i,(;IY=dfe]5\9usMBAϨ85fjIy8Wj@EGvC=ꖬ>">4U'K3>lir&ːPp 2T2H~s([eƫOz!IguѤ|ŵ`>5”d2]Kk9gf\z?j9zWl9 ;" ^I8ʐGШ9\XޛdMLw$L!-%BI#q-S|+Uexz>jkdv?..K8RuH= $W,x[am? ]İxa;$,=W 6x=!MuѴ[pij1"D(P|Q) [夗Y鶙~ҸHAm)j*i֢f/$pW+8ԕV씥#.^`_j63X(M\}8>TVXR3vڏFR* ?Zj]V]aGlzTRDmZ;Т9HQȲ{2 I8V(zt;/F]~RV0,.>-nm3,#ʟOJȖ:{ P"4Z2*;ezqtTu;\^N?Oi v"S5QWw zUКɃ`i*OuTP @(P @(POH}[^n~"[T{ZvtUpDw@*6GzQzm HR6o~&I=/s3UY~ 6i(@[VQjC#ju'kVI)䒞3s\tpœ-MjUF['vA'WG Ƙ\ZCIH9[s?. Y֟ =FcE_C܄njRZݽ Rs+˳̶{`PVRJ pgie8mܫvg&G0N8ʂ\Ck(Y|叀퓎ީ:|Aj%Xqz֨+ cq/B2y9z4vwQ-㩺i%oS|l)!$\{(lڄm4ӭ֍:~eڈQn;KNF2~zE(;:r8泞ҝ#lk%ɒ!ͶI \wⲤ|ܜc~pVO3w˖RYd<9A8<YcLpꥂ{_5g,ɪq;bQ|rcvy+x#*4jg|9JJk˸'>aBR/6{W!Ioq[(Kɘ[zqkk.V )tdQ,2hʊ|4vMl9٫Y4\i+fe/QtRӆ{MQ[oKmQIvYEkfLkISD#ҰTUVvL2늪jYSkM3`9dqVYeǷ$iZ2q|֮]N-MǃI'<'U_&_QZ}p릧b.jفݬF7e@SP/=;ː'?ע O%t 1T"6QHG ެROE$ Vj4\b\X5E&89$vrh[Slg>F.fWj霹)@ sCȒ.w) h^wT=ͅbZf}GV/4o囥Qa' z>ʼ]\ # NǦ)Me/LAij0Ͳ$JbE,Ui0Jy2qک"3]k]$ĭ@ޣͺ|Z4f/IG~elfVR&ܬFlzcV=* yivr<֩ s(&BɨLʊ@(P @(P g.8e7GDW@9'޹-Ck}劜#'9mEOͻ[q (֥eyF6!96Kܟ;i*G+l"kj֒F/N#ETl$e6nNPp0Fٲtí^_r2 ~J^vd_u%)gp'bXѓYz"5ORLF(^ƈ\ld{\(z ";w+3_bŢ<*[cҴP2y[+R8e6z PdhBB y]#-Qφ (絘=H,{4w&}' *X,zxClIs EG9[' Gpf3VH>޵MDZϭH&VEP @(P @(YM7ּ\jL[ұM#{񚤐l_yܟ"ݖˏ]"kt}?AEZJ\'g!}FѷMC2^ExBbCSk Se!)( Q+KgyfFeLK[hہs'vZa|ŚK1[͖dL}oq]qĠ&RIK z ,  )Il崼Hqȱ$?TuWS^q%MMAEoYJ'H9Jxq)`O.9FO>FIlh Ra\JrۊItK& w'LGZ|M2þ@ngV*قW:8rHpDAik?]|:yҳ}q~ikQ5p7_ec+K=àljpYꯢ.owxVVuHY2[O`p*Lm{9"6N7cLg5F;#5O'EFϴ;= K}qZzNOf/+^ !(JR;)HvJ]:KIϾ*=?I"r#!=RW&ɻjTmd`UY>j(>ID0*> $.+'jQu6'`d0H*E=ϳ3aڛ]F@犚(@HOެ7dN=h9&AQ@(P @(P @@$+6lM]3lڹ%itZNJ $F)5OykKF BFP> ?Q-T"ֺѧSG[^UP<i,tI>2N0)^E Qϓ$qGd?C ˂%. =־,yUEVp$Î>6؜(E; yQ6/LYR{$m.I;k8+ E#^ OTХW:b]5Բv KIrɢ*=]!EYEG9gpn !@1[5F['ҥ\3 sZ'B`g'Yٖm6ĝm={M6ٸ:|lzhlrr;JLkJI2k3ʝ+HQlc"I*+1Tw"$M_RW*D^ssb8Z.";Ƭ0N*IC95V 4$n֔Z'VT@(P @(P @(b8!5ƥ6x\tssIrYM~3@0u )JJKOqVx,rͧYar]3OQ'ֻ9#G.>3DZv_H^O>ƭK-)N3ǥV&Oleܥ5G5eW{2i|40YN!C;1v'0GR_gO J ਞ"Uǵ)xQb$ef3R (qQ.MQt6~=XVGֱIr^=kkKk1LJFzkvAPP %lM !T RHXh,Q^*y@U{jv!dH}ޭ25"sHDkFx} x86J&,̍X @(P @(P @(W5MD  K8޹3źk[_'uW =:$L$WFT2w *[E\\ːp}YrvہZ~O!g"''DU_R{^ IT˵S9Z]lRprG%ӫl,wSl+?EEߥwn+⫺Qzg.j bT6f!kF "y ţpՅiYBBN+7rhY\ 0u v{lT `TBFjUj5DڢSHu!Sm0*PT֮⢚dO+VL)p1RDvLJ@(P @(P @(T5`k8aPF({ԍhXi|$vcG4v6v}=+Є+)(m,B _kNp ,&of=>[Nw+v\0z(䇖$ߝt Qht;vs#g!I.#_PԻ6~H)ƆGObgߌ48jqYELbXܻ'񉝞^( X1U8  q`ETz Ec$aP sd &K$Q`5@$wWڶNy6A9_Hq}7"F{W6iBɢ(FP @(P @(P @(2X[j 羫hd-n(5rFj.đ&@۵v)FGXڲ:Ce>dk.KfĵŽj,>(Q!@yZG6 }+u0sN+]QK"YE "yXST9 z w`SE;U(@VbkaJxGd?ZpK@y犢VK<𓁜UZ'%{uz(AɢVčjP @(P @(P @(c%VD`ϒqgvEncR:8eբLH5*d7|ퟵ  ڐ+HƑ[#i1Jޡ*/@US$ j1R@PSD> I @sP"*=j-pQ+\pj N2?2j }*xIj‡tY._}jR*yQBq[]ﲠU陳teEHP @(P @(P @( V`%ڒXI1rrkIJ՞`ihXV栬FQoV8Vqd+v#j@X'CuUKhD @0@IDWFL=t9N #wau Ih!JTˎD@b8TX<>nI>ߎjDc. Qmicropython-1.12/docs/pyboard/tutorial/img/skin_lcd_2.jpg000066400000000000000000002075241357706137100235540ustar00rootroot00000000000000JFIFHHExifII*  (1 2iSAMSUNGGT-I9105PHHGIMP 2.8.102014:06:21 21:19:53BJ"'d0220Rf z    |t0100|    N@Btg'2014:06:21 21:12:492014:06:21 21:12:49V@Bm'dm'd0100  f@P`\n0100 > JASCIIO08B00AFK01R98 @($HHJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222~" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( )s2rzZ YF1@dAOsڐK$ O=>*5۶Xd\0rMMXpYNԊ5K˼a#C*3y }W@\_ѣrG2 Μ@~Ԝ~] Ӣ&eSV< c ( ( ( ( ( o2nm4"`R)M= U:Hb{_3kZ:ϋopDF)ecILƢ"n?5{{5/^̪ Dnyr;V/܋O3p}AϡVtm{=Ey$-!c$VTs0cUPdRB9HzW:nnkvdY%,dPN&Җ}ij1|9=Rx+]Z$E E13/ă3hn亊 *? ymJ \: 4*h_Coc쌈83ӿU5K<7Z2,b?9'qIzL6Ȅ;sGi꺮^ULaij ($>P|S50Tf:f0ǘO\c֡*ԕbD,[ ۿ5@iJ1$`\wiṮa-a:I7o rq(<oAbmm-o \gqvێʳCq-$X%deۂyе-&ee_'NzgԹb*ڝJQI";wY$]N-gDԢˈ;9| 7G2 s _,BeI35-HJQ}[+s@(((( #3&?|ڀOy1*; פa>ۯ1Y?yo? ഛiqʪ.;t5Ijs|u ^[,8*:tǥQ#ltƝ]asj~dRy#P礚b*;#EnSk ,*KB3\NN>+&A(ja޶ZNw{qL:U}^/$[xay'#<R;%Rq>Wp N3}k" k3걒@?b{ic)gt!vw#4/Ȩ[O-88tiۨƼC "6'#|N7pNy䰺a7U--s tZk6/$!`$dcqVQ>5l"0!|'8=kf^բ>y䰍`n6 Xqʶ9>ITgGQC5 rgsF>ieK, # @ >ݿrܪbsȓ$t=kix$O80yLd?.9|}Ihw^$yG%#ӵs2},3ёᑏª W$:Ɨwo 6cku>ΎWt@XlwFTIhs;uj{×QIr.~aN D2; E:tQEt((+ Ь焗w$u^Q[[R9JWž6wW9 8q^:n//{Wgc=h~|yf\`V-]Q?]\pPHŊ< _ɳ>hOlEYegvo?,? MoPJs1&x 5SY/O[8!?ƛ ſ'׶ݵٸܤ0q30ǬO6_J%>og؟Cſ'¥hzݿ$X%< u ~;_EGEƣrILQ*J*RWZw,((;[in%8$. gi$ԇ4{:?p~-yN("řfgƸ!$M|cpA|b䴔8fzlJ1ڻFnA w 6Dmt& P{cTA!bfΉ4\jb'9 zUgI'-ʏ0A$9h{1G"M k*N\9"qB?*ͷ{T,q~q6琪9H 9'UH#8rRA6{!ppAȦ~o*i-3súm43#6=:38kCPƅk{twFQE_Ke'7N񮪳5[8fCeYFOҢn-"dVGIv)g8#^k-H*{?OnoP!BܨڼBK+m*zo]K$a4ͤR sIBpkA bgxn56iMF?Zm ݘw <%e袝GE5sq}NI[I8ճ/XDݦ}Q˟EIRKOO AurzyvGho٥dQORgE{&?O)dS 4e3E~.iֆ;ESA6Iv0¨ 9;Wsf# - VS{80h1[D,p#0*jTS$6 |tZu彻GRA(ln.# Amcn'je%fRN.w wc cpUqUm`19?uقΞ(( ^Ҟr ϵpQ^EKz›)5Rh.yL`5d?z rQyR:$4QЎ|#)1O <:]EdpGM}Ӈ¿9,(|,[']{8 a'K ']{8°MwYHXdSZ){8 3264 2448 SAMSUNG GT-I9105P Right-top 72 72 Inch I9105PXXUBNB1 2014:06:21 21:12:49 Centred 320 240 JPEG compression Right-top 72 72 Inch 1/50 sec. f/2.6 Aperture priority 100 Exif Version 2.2 2014:06:21 21:12:49 2014:06:21 21:12:49 Y Cb Cr - 5.64 EV (1/50 sec.) 2.81 EV (f/2.6) 2.49 EV (19.25 cd/m^2) 0.00 EV 2.81 EV (f/2.6) Centre-weighted average 4.0 mm 202 bytes undefined data FlashPix Version 1.0 sRGB 3264 2448 Directly photographed Auto exposure Auto white balance 1 Standard Normal Normal O08B00AFK01 R98 C     C   X W  !1AQ"aq2 #BRr$34&5CTb%6DSEFtUcds7!1AQ"a2q#BR3$bC ?@(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P @(P U(IRH8jA̦d-6SgjҕR}BiIWTБ! ؀;3(] BRJ۬+Q&&$gR RH),KX<\Zj]*.]nH}hʂ384#=.Vt[0`NdHXBO'%%$+=) 8̆{Pk2.N4{Gȷ!^i)I2QUS0R>-- r SVdo\u+B {ѝEӝBMZz6*()'p #fvŜ\{ZzF?dM17{{^RX a8juQ6_تx~e517h3 x((vWZox/xS )V{MI WiEKRⳤUjJWE#/F\;CS_4/ A}_< AF&7oI^? m'?-"&Eҕ 8BZ5&xɯ;4C~F|/cߚT?J|krK;%Ohi){S .22{cez,2TLOƘlh@\>$Z?U`,ׯ 5AORJHUo-K}8T%n#Az}O=mQtŗJ +  ` dX,¯6*U^pX{{-t4i,OOsr#`Cܱ`qm8N/u-6 ɇ)kyJiC Oʴu*"rodءǨ:r&[[.%PSN%EA'H=t-kT־zW+"cly*Z/ uǹcf)U>趢E~嫵Qӫ IF^6){ԬZvWJIvNJՍ[wkޠ[tfjpJW;̤y3d㱂64E*mV9Qa')Q##qZD蓪_/Y*d&=b/#]4> p6#˛Br6Z*slEe~+Nog%>"o Rn ߭ה0܄a#+֩nbk~ƶ6f}Ir6jsi1bxqeIq%̤)* dn?ZZIJ[Y QKfwKPa;?{!$;V6<Ujsw,e<5L_YWU(#SlXK݄Vg5wYt&جyk-]ĥAH%A;@F'ԁ|- Y1d*=N; ѽ]!#nU/ROS)`HJ* =k ڃmg ZJnoYu-Q vLr /Us Q+?9aa/ےABfrkTMRk۝֠Vs/6͔eH!K0)zVYl[xO9W;,ܖn-=3֎[-ZM'1ᒯD!X~sX)(s5uFn2Rk6U" WAlo6'ttSәܢg }+fsym5>0 :$_M]+ȝ%@>3RKmA9- q4?T^'|}C~Ժ.Qr9aVK;;>dN13̽©{i#<c> nZcij1Qu%U#3=5qb:i&eۢhsTX09 Prd('}6JgM)'XtKOuZq̧`8oSw榫.=j=3q̇[WL8ӐZnr%'U`w3Wޖo}e_N_S.ړTkLJrpЀK^J8@}:-Dm-]1c;j9.ZM`#R]=M G<45jZ;C3n!*+?y]gYt^ԧ%ȉioG?C[_P)Sk=" |v5=WM|rge8 gi#+ՌV[ɦmn1Y]uo,-NSufTөLX:)Iݏq޴pߜ}Klk,Msqv5|;˒ܷ˄|ڐNIh)zlH--Dބ1]X%Xgf)ovR-^q4@@>߁Ynj?Trsq^a]X WdOz?P:O2{^[X#p>Ւ&']5^%u&z:qu”heCH>8Zޢ?'BZ{#ݹQ]$rmNqBC ϦFG5QeIm7G]ҞbZyrbU-0cd9 ,O.LQ|EFJDwfh۷&cɬSmIӶf럕!M!kۜ8qK}?,Sd_W]Gn^)Q|mGb=v|(wQʵ=ە(abU Fs~ձS'[T/fvi4Jrgz%^b%\\bAZF@<=ZncSOƷ2Q6k>Ʒ,],j\ Z JPP9;`VоRrI-=XAܿR˹@r˓CYuwcZ(˦o ׄNk1w֐ fo#kj!x$+yT՞gDGj!UYc[r7)##aOn=W̩/i@4VL{6[WkD^f0P @(P @(P @(P @(?Cc;St|Ghgdx|E|=lƥrEӷms,u X͸~+JWϿo=+-޴Yԯ[Tx~_еnkZKݬqXShuZ.g 'wmV3ⷛg=5N:!Y;OC^6C!h l T>֤%6GO}M#zCotTn>Ņ#*퓸(}ԞwI8+ڷKcuV yR ^l[*mJWʈgo/{y&Q_84t=8ۍ|5%VoI% EY#"6+I[M#2[3lCA!DĐ'ְk袹w $w9>Zpcw޴f{\*Rٻi^NpGp>S<oj?c\ SmV =? ,JKIF䧰Wk5(Er1 AoڥBWDȢO55q7$5Ozl͹ٚy-Yd[ŽA*QPN\JKOΌ_lњ]&i;CW5Fc̔[ 1[a,Ra}@\9d6Yq Nĝ *>=T\Qmt;N!xIm!$ͤ$*<G_N2й5[80O C׶m}kSRDR/ BX9!+ܕJf%[Ʀ'Ӌ=R^I\C=sH<mya#nS hɢ[Lw~KP0}jG\=o`j1BO9H7jTV\wN{oZ<Lj4Υ/yRVIZ?sVf>jD:[Q2.X&q>T`#|V̞>cT=wStԗ t?"JB|($R,0qmOVD\7#PĶ;w6) yΥ(# #Gx-Ӗ0i0By;gJC)Q LJv4K ڥ p9DPVy#F2X.QE_*3Ɣ"2ꚜ{/ƥ9TIM IGJ@A ~Q3\YFWj}S>w1,*ǣB\ieAdwg*K92d_tdZ&v*.q߁@cţU|n9U>y mOz12ѭMGoЭnN娄6OMC*_wYzV)Ā<[81o繸G-ubEbd\mi\EN s{ZgSfn>&ra>vҊHNc ݃fm&p%^gqֻM~ķ mvVqsjO#?(Oyue5/02@WKĿS>X>P @(P @(P @(P @( f^n9)IQ Yee%&ket$̟)Ɏ?$}\/'6JV$-=07uαu562Wl U: !;>U ,6t]TL RoJqd#>>Hs(vj\_XdUmUS' BXm 7|JPxN>JpqOFޤM SoպӐz.eɊ*mmB6%EN$wc MN۔_I͵BkŨ⺉I]#^P0Vr2J\*'|ewFts}S!*ޝ$Kd(;>ck41'ͪuѤ\:j>Mu[.3e&KgiwJ8@wfOTn[R}\ۓ#Pڻ+Z्K$ssx $ “IR@O̡SG%qo%n-tYޮzfBWqT7myRbP4}V닆BuٚzP Sv$QF0yfni8􊛾9mTttIMH%y*8m</wLcZz-Eu[nGKSgOSز>#5l|^5PKe^Џ!ovI5w)J]@iԸڔrXROvJiXQJwiQ+[;$%nN-jZr)Y*>MTͼ~5j6ͨ&꛾]ԥnE EKo75nm=Cө.x޵9Խ:Zcȑvͽ8uͮ$U&Wak%7Y,%GhyIq~bNFUؐF+\۔q5ug6)g ,k)&j"[K qtxlNRdV\phfoɨgۧܔ02>d {bW8JK5"ԕʑ{g<Ւ$I#ꩠ@,rqWTTGj=6؃py9qG$b.ݩ)K9ޡ @I9d85Z';#q B\/e鮸Bt267,Jue(7ɂs>JCn:S5[V!^[Aڔgf t!|t"ON6T`He\_;d H1qAloM'^$#@BvF-Qۄ9%hq.2|@BȪN;]2>buMVӈm1h3xBYR]2|RIJýDjQI#'-7Kz3AӪbtOlm ڬI*N=mES%3]P٠ :5{-)'"{h+P @(P @(P @(P @(i^E,:.^"Bin[儢rB͵l]|-Se8PJQQ{fMtP-?KtlĻd+kHIm[ ܾءmK6иZkZܴpj[Xd("ڙG/b2ް֭f+I75. mth 0Xm1ԧ!(x<օmHiqI=sc\7[[6m;ӻNF~b;WQj8He[e=*Vr qP!s>*2'}ieº m%;J q% ,spr\E{^Km19r[e  H9i9ڻ(ǴV y.0WAgic BASe5ܶK=2;HjbW%ŠA*'rA `1eݞ6L4԰d0l%01:p=JpLgoCX_ii͢=cC 16ͺ#NH_ 5 ),~ŽԷ9cU?z۩:B^jl<]Tf\os,d( 1@Tj)v"zX.zqqٖ8`S+Sn N9$Ni1OUFEZuez 67`JJ#n;AF3HY7>L+{PۤD}[V$\VU26VQf 4rS Sml$9Jrkk| XQFX%+9>|p[7z014 2tSzѢ K7Vhڮecۧ Rp7 Bɒ2V,26"Ty,j' QY>9(>L`JGnĻp#\w+ P L9Zw`)]OSpMFAN=Hbh-7EE6gu*vv#S1*[cH*¶(c8֧; ]-l]Sk[ BOr;VGnMwS(zfz?Z#,rv22m^6CKCZ- '$ J߃xt: \#WC[.1$ZaN2VI מ e?Ѫ:wvhvJ<3g8l9 6ڜs RI)YJv@V5eF9%MdSHueL[ 7;2{}1چ~[^3%}lP @(P @(P @(P4ɯ=SOP:yg~>j¿ -g}}K~"r쥀YV rd:a> pQ yv,$$+](tt7cJy6yݷLKJtL_:9udv-3-ϴyETznYƳ>K'I=MNv"-O!rHq$$NIVttU55+}9jk-T UV_bH}B>h qE+GN*ѓi6%Uq%Mvj[n5$DR.;I yϮѐOzĜ*Tf[%F%SD=]ѰOM"YhMF(D 9*C9Vw #\6H-tgNq[g)u7Jycj~\Sk]F×Ԕ;D|:e׾ vS"zf;}I8Ivc{'rta}Qi΅ENL0ĻeQox:;AKi:& + eU%=oOZ_k4kH5{'i{sAE(fRɵJɻL׃n EXv:tAg|d%#5VAsӗaQ.? ^I=NFEamn +VFmgwպjl-)sc*qXgBi?&YSMVb{՟)-KIF);|JRs 5U涯jjRdcEpyT5uUDg*a.6AY2ViazїhK]tcpLpZ6=G˘ NP\$(((rA4*QrI϶LmKe.vI65N[]w\k[5 ]Myݏ̗<KaDn0Ytܢc+Rk`]`ƞ̍3ED1)FԲA X@Mڍm:,3{maVޚ~b,fy%uraFFjILJ ,].zL2=N]&~ e H;y|V]x]$3JZ[qЃM|9cjKNZv݋fYgh8c~S@-$+ZoۃYE8(0 px#W*-VwXL.Ye-d$}jIB.R|", s,vy%*-JII=jurɳݤi]d҅,ds[qɤ^ZZ2KS=0ve!{wA)8k赻mi]EOoL;m=.| TR=ҟ$$()Ğ;KAgoFڕ =AfX`^"jnFf e%'h<}޶ps'ڙ/E:Wm+nmZuKvbc9nrJa#)YRYkx|*Wz4͗:\2paR[ڀk,^be)Yatkt.է[-!HRl-E^jJsFz_[ܖ=1kNctM!1ѝ;vHhc 0r7mSܙ$3sEԻEp00Ä.qN/E>62z":c˅RЄʘBFv!8*}䣻=5o(R^ޤHwWjgv@@8k2#MyZ&/ֶ\ӂӤt?eLaϲEc+2awS2[jR]|+ChȧcUv8ZmO'm!'MS^gֿyKRdƺ2Ǥsc5GUmryɛh_pjMmdxDMOgV1E[p1D5˃-vJr3y!D\:w. HʃPAN~rX#\g20ޯHIHM:k%˝4WD@$88ZVW攐pVhB`NmJX4X%\Zn[v$B/jT1lIi϶܍jz͓YpdzZstځJr('.<-=rڮM/} Q>OMDvjgeH5Ot0,cP @(P @(P @(Gp5)=VPO;aZryXi_RL%>D֑"&0I# !ʈHLcpO4>{Kߚi!Ycql&d8]iZRPO9 Rv\bsJкslG/B7Ojz"IZ#q+lc8>{b%4}*J/vo?6t䢷w9۹'?Z~J 'հI,_t>u}4Y KnC11xJy'ۃ0Ec*Iv6(rS[W'ajnC`?fmNсpM^QAHQ^,vCIVRrYٚ 8G\nNʘKS !JQQڑFIp$^4:.Ncas悗O6 ׵U*sluoKҮh-ṘcAq-Jy@QLF8LKzTK,I&]pK{ѸM4g.cսgTubXR"Jdg#lci: '/z]rϤ,r4ѻIԌ?j(m*֒pBc9BUv]UM>)Jԟ4Y,&mVfaQޅ,$ܕ-HRH;H~齩nl瞥ͷ:z0fLg\Uni@gi#9֚31Syg((. Lu]5`4ζ.3o.&26vY Y~YKr|KgY/G}q0H\-2Fm)((S/n2i. 7ffuwΰvm$H_7JJ?+ XFo ~jYo}XؿCPڤΑhZDU 䏕_]6O2|HME+4d6-z]-DAxZyXNrN*dVPi&7r\[qm֫jA!>C,9p8c$uN@ySzKr>K 1%2ZܞJ~\qVO&2}}kƠHdiGqZHiՔ1-8U (8)*ܑ 5g&zbb #fxܵU"֟,Ɨq\Y"?:J]VSl $^e2GW&ֺZM2,xz ۓ>s+>ɿ2gG&mKrv+0\I?ZrrUÿ?371<YZ]ʬMun-Rrsz-n~JRzm鳝cF-4&$oːM0FWbx9_9G;T"ԮCouTS”A2;zilȹL( mҭ3?[uŧm%7+$ =H9?jd(hԲn ftyKLVPҐW[ J#ӶA< U{eu&3Dx!6Xk'![O_Qz^BjM+AOCb_%II1^C~my^>X$ FV/9yUSf>Jiu]. mE2Zؤ%.{j;ϰZX{Mi4i}S$s5sTH"#ʙm@ 5FׂZitt]tNx%U%{-BPs텎Yz-4g>u;Bt7P,ܭrkjۜLԤn hYQnR5rpF.(^s<1-@`*C OX梟)H}Oѫ>aٻ ?k/(i#A-FxgޫY܌bz%ZA찠^m2N2bK-MA ~XXH띾>_S jCR)u%D$%)Ƹ>q`õ֬ޭ&}Vuc>?8B;~srAb*\.Q 9Ɋ]IcrC kZJ8'#>ƳFJ/%WGԮETy+YOڳanR"Q2GIr*G*Gޅ6EGSZ|;"8%f};Sk}SKCKs!\}XkM4ΖBr5\@(P @(P @(P @8Нv\/9WOk_,G''i;Xu2HHcW=O%e]uj?u,,tY+݋Mܬ%$NZնsMlGkID,der0!6 Q6=ULkLJֶ8:lqWɬx$rle <̨Lp suYm6sa끴QVivFz)T;rOe(YR\n:BP!'#28Mluk0MNCO?G<a 8aҜ% ~TPKres[[iMWwwUD6H A#jZrвUř>.uˠ-KJ9CUT{ɭaX8 2S'ӱv(w1{gfǨWԘqoĔYw'p]gM.jn8ɋVv:=y1{j|+<|3IJQ 7w[DJZros'q}P⠛/SiJ\֜XȰj'e2P#zJTT\.lqgSTڤ Q+ ^=崪?On*(HW;ϱu>~~ړ`B5xKr*6Q5gfKu&dnօCR*H JWrqjSܙWi|Gnͩu5v(Jp8ǮsSjrlW+@gOxW/isZc|Ia2(8e<l]RWLƓ7*HAJ\B=3.tۣ_`jA=ۀ6ۭ䵷 ĥp@[B89 ۱a>M5ιg[ͻbEQfS[$B{@S:a>m_r_we)x)A8m ;U)N*sBn0R+]b()q8ɷDpa_m;SYlzܿ)Cjdi)!ClsXMqui̫QNQ>{ыjkb7 -! $q b(uVdדs;bTR1 "/9>ScnjS-pwׇt4hpyޞf#iB2;JtGt+q5ӵlq,EP @(P @(P @(^F ~cjV5 cJqPgNU$ݴC IRߖ{W|7vAG[tKV\ֱ!?J2GqH{JkpAOq[RM/jy[=-)oH F};`T˂o]ʃJSaDdhArUtrVi_9q%d  VrYCSM%-a4ME*@d$FGz*ړFneXI!VP  'xך. da9%\3**5l08g QK=BI{zU&O$/uNCӒUzt;Ę%Q[MRG`vȭGtSq&ݯZmʗmjtW!>䶗^7HIVGV\E5؟Ljuvqe! )q6# BԓT E(}M CxR5qۚ*zDR QAaX Q]$Jkk^F!E+_5|udm2x'튣W8(zӯtC[`>VZG[UkɂW] *8!>RzkNSIuԄEm$}k> N[[e A.t=\cMlZ$U gN!2#X8nM]HP @(P @(P @(9Mc"[bFq@|E#N["7XV?ƽ}d%ϟ1e[,qdԚI//՚B1;\d%YzT3!z.Ϥj< "ٿ[bs7&EHZѓ=xLZjP p 0e>xIN┫ըdh룈|E3ިA[*w8⮸EB_R檻DYb FJy'@2J3 'Qd08n?OJñT$#rO(FG$K@sc%"N=) /&ٯ5 "T,-+ߎUjdlct[BifreCf'Gn`2>JRBBN m;'$mQ^K}X.lߛm+f0mr-DANG?JJr2Y_V O0c&C;I$cT;$z/ǡmXK6[hu77qV ^[(Z9'ک>\OQ5>"ay:RԖ RH@2OY[4pŊ1!QȐn Vv95PFۧ.wʘqʘeKkF@@ϥJOYBR쌎M}cʸ4]$Inu *QN繨&]5 SmvW(k3Sow ?vVCcnzcr6{dn GW ]JT)=zz+H?8,W)=ds{0%֮0-Qm@ -DiMHPIRY4[][nY;z=x09,]?z}ב- orxe?~k;'bČ[t_1jJ H2PR r9f3Y5K4XQm tqnq&}E]Ym#Pem'حoy)~U֒ 5~Ni 9.*kMq7vTvx'[:{cjKV\:c:%,Y-Zv[y؏*`oQev_Z̒Kº,Xr+;vzi a7^( 5z}5Xan|wG_Pxo)Rf5PW![NR6Y]2(K`Yaj+m6[ȇ|i%,d!?2@^{Y=ܶ)}LЂryihDž˞:onm!yXR[nu@d&+gՔ#Be#s޶v鬭=&e`I6ӂG) I^9kZU935hxYt֙Z:Lzs[=12ÿ/onrsY'jI+Ri5薴fQIyڽbF sҩnhNZQJIil=dhal+ hXfo`ݪ+|Q\){\^]uS"9t?].4|CkCZt|s/TEA/-A*5d&ҮkbQU~_wx@;6Lp|\ б܄MM> ;WUIMQveL{{+ϘDwT' N*7b mr.UvyL\zܯǿ]Ά>Z2dejm[v7FoҖH.P% IV2_Vߗz)hjtgɸkk?Sz+zK4ͺL>ؚ&,q6+8!8Q˶fLS.iBeî}0ڴKnR\.{|V8S8;r p˶ZNߠ@f<~#)ƙ-)&h|'_gPigJ&z+VΚ7]K.ACLm956 }++).J+|`gPGmyyzvUؘ 2%6ŧp*;ŽF.,4ɷax$^CjpmhvU/˖p# )@;բQ͏$LCz^h+Ŋe5DƐq6LczɹEd䠡50>gdl  j8Odm+'\zަm܌k %w*;zUuYSEdZ.#I2昛,gRjm%AJOr~eJa=ི_M?&7ʔv5bZy38LY [f0$Dp?*Ӓ[:ȴ0ұN?c}˙;=2Tכ3Ef`uctQX&\a-K^`.y*JG`F `igN2kҵQR OzSWlq yak ^3I62|[&9+OicRt\k Z G;늕I,ZvrEV}xة|Y=#Ifٸ?&ʫj@(P @(P @(  'S@|7Ԟ_8W|$?o!$HW7M:5p&JhGjBY9!W{Vw6E^5)8V̌k TNt_·UY!ZPOkstb٨'EH;gb?&Ԓ|23=RU5xtYzO^vVJ\~#N4{VMid٤&5rjGoKKd95<6scTʋ.hս-\" ۇW,+OW]WaZ;iڈA՗f_ :X('X4tL1|뮢{Y %Nʈ+ehk?:[у鮢Z4npҥw&sΐBvCi*AO#(?FE[ԪGƗ]FUF!se,JPd+Բw#AM52T.Z7O7cdۦ4TJ[ZNU|1Z^w^6ptZzt 復RQJFIWm+-~1sxض:qtPG=\+^7(v[?$[\!OJVqд`<yMFzS˽35ʾ(rzLɑquIaj98`Es$窵GS?ȥ?LB->{ytgG (Qz>v0bz+|sTw2؀r lN:Qf?fkW=O]QHPf n33-2BFrq=*WNb+nOiuLKz'P<{+/vogIzfaMށMsSRy,II<[yzܗu=&m5?Uz\}hhH`VUCM׳WVY/`IP<[Φ0_!%&Xt.B3%qod'Dtnr&̶ yA)F}I=k-skJؼ[gn[eW!QdYm*'$vSٚ5kk˓uColJm%%NRqTcQ&H*ʈU|F۫MQnZxT874sczGdup5NSܼnF"yY4HՀP @(P @(PQ?ѯFs˸Ko!㿚##)ܯʵ}O)쏖69q7f&SܟJ55i E_z2-7D?* RR Pm<Ǣ*uۺ^>OCmW\3qOt9ykm9 JI8y3B'k7]+NØBh*gl_T{EdbҠf,nɫ.Πa|HS,8;j> qkCEYrJ%@t`b0ycRVBpy [j\hiɘۣpO|V/kS]QZй=h/T :\J?S\oZhzUI3>/P,Ew7}Ѝ))s^}AS 'RxTOխķ(עF9|SHhHKICjH$}GE~~isyZuk ozITkd hejHJ~>꿆R>ƇzrMq>ʷH@*S zDq=_\4"d|HtoH\-aibSۦ(Gq,tyoZVсxv>_ 04]qWCJZ \5rn>>l^[fp51ny ;׈sO{~1%dǼPtJYMUZNRAlw{uZʛKt}</Z:~.9l '?ԕ^|FUv.3K\%+p:R K1?4SƶFZk F^RI }8zSu׺+}{Il$,h[2x v;%"pX?nUzxDU}سs3 9,C]/45⥶K9=Ϡtج/ӚylKSt( ڕ7wMz/QmM <QEpRs]xMkPk7ڽ%6\(?qG޽uҺ\'ݜD,SoDj~X5Ee+!ᴸ9$Wuif5=c1 /05%KnBIo~3qc+]6<4*{jS)mR1=;3w=vW*WKCTSoYV.sz =xhN-/Z+N7 uِBBPCdۂ{WZ[swҊ_]_Ly̩^֜$`{ddgһ]P^;E}^oeh~9Ũ$\Y(cJnC؍YWj;8l" z xɍs,2FkQ-DI猿=v:V7MxjM ǐңR0aA{oZ}jxϓv9k.U |_0n$ 8xc]j{ƿHD=;qGZ00w9HzSL^?y\NꨴƙԫgLs!Ҙq XLs&YpezKgg7=/_-z&+SH2sy í.$_]ZK1ёjׅ>s~ <08~L5/S58yZi,*)$-ڰ%dc77d)X;M6c?PB{fjÒպ5k-q4]&ی Zv*LOlԍ:՛;;qJ v* :SΦJGlWGy<80Oڠ$JtceT20ڙ24E$C}~b9Zk.t\SJIW35$g'is"[7C][!@(P @(P @(83QEX4oigϐx/8(ffX^zӍ+'ԗ3qDdĖgW6=ZleZ%bܥC޵ MбZֿԵǺd8KxƳHw7_D=PDy<̈́*LW/QlnÒsOZY8I}?JQV5\hח{Ȑߕn>_vL[UmPg#7u+qR'>5c8~~rjQ^K_8 a?S^Az|6Թ}ߓkJtx(z][I/XY\ic(q>_Q}F;1ۢkm럋'! c\|Wfz'"Iɑ{h4=Q&&CF.4=_y,/]^:wE%Qe7z=EgWӹd[ٶ񉪜l,YlI_ey^z?2|;A UMU 'o)JXae޻}5\K ȺGغ?]\:=*=ǫa9we-m[QZT=8&z7ϟkԜ/9Pj^O8ȗ5~חw=)'Н[+Sڣquu2l[w9Yʁ![;+)P?LVk)5aU-ռ3c7sl@TV4+$sC=3gX7^ɜmL +* S N> -Kjk?ڐJNL=MKXB1M39=e ͽz O=bx/ g,-§T6]GsfoBq~p2 )K\dҵ'F|ztH.\TMUJ(&1*g?9t 1֔컵#@ .+$dwBK|S)reZ{Pud]?6%ydĴ*,dea;6+^Z3O6]/ItfZk=h*-%ܗZ KX7YebҔK3c[IQĈζ5BRp[976;u_(`rG~i,Q)W;FOTl`+Q,&co?ESHPIR\oNt&2THuOtLސڏӎ+)wFUyiYiK[L<.80DNVk]_R>b\INTF}*A2~?3$]pZNA{/VzJTG^Ԩ)ij=nU<ھ9i!hZɭ+M2y5eܺ0;"ayx%bﰘp}aeD\s0ʼp+ I3fiU*b:R.'*W֫mfq\/jAm ))hpN:.drX\v‚@ >VNeq>IV<Y.+:2Yi$%;HP<-FEW- FeM9'Y[t+..哻%C֭[rFToULRS"shbLw3|bxΔkLǷ-+u;uj>D)K0%ƴbmFdTHt:>v-~kfxGqԛkkQ^DJdGABRW4hksr,qQkk`%-sJR$r{ M/;Zg)%=mŘq{Z95:vWdasoW6P἗@NT#Ӛږe)Gdl."$z{zJJJ N/&Q+'&;Jkj=gQ7-TMK͏lo:sWIض_ʀ[!@gڵkqF* iP`lJ:$ƞ4We<|ݸT6OHmk8F#$ֵQ.2ٸܴ֤.$Dh\p8}Q1n&߃abruOCq~ܨ/'!~/g4k`g5kyzdӶZഖ%8 _I.捚썇CkvfڨHu軥./ް[vMگYӂEOI~NՓl9ioˑup7 I`'+9[Sh-&]Nq " gV,sbE4MG@e ;+k*No ppIKG#j13M11 L}K)*ԗ5R])i}kZ`$_zZx7t8;UP4ix'-d<J-^Zx>TqNtɪwWBch8ھpȶ*E)q*3fUԦhʴ I [S i?Hκ꺏 Viy;W3)oUВҍ- PEw*&h5z@P @(P @(WvC=,iRW[ζܼn?zva}nV!$u5-ToNIiϔ} Ճ'N:u՝ &yB -v3(EpV۵MQ[Ks`Sж/FER(ͺSdH`$;s[Edٮ^RY[Y-s] <[Pԥy/A^y9>TflWv{_kiQd\4dɯ:o GY&TӤF=9>R^B6GFsfg8Q+칯9"BW=+WƄomy 4'$`+j dҡ%,,rn}mOn]ԶIVZN멹ZLV͹4Qe0r"%- .Q zbn*&O+j|ɆMyrJ ʑVu"ほy1>;+dE ԮOtHM`.JB8]=kZ /%#)}`Vl}s%[#xA<( \ޕ[;~_Oc\U\.JcU99Ң\^?KM[4<īv!)U$:\b3-dw-g߬v9oW_ڞzD SWrex"M0FHmwd7Δtj߅ Z;u˞K'Ek$0I.ݶoC_+-g*e> mՎ_zê~,F% H4GdMKw< BIMle2@ Þ4FOBɢX8j9ni. &tMb}i n234겠9݌W"4<&uBύ{V_mnr=- ìTQX&R6p g 4аmߨS}.KI ҇~A<ֶnc5ָG噝ž?.v=GRS*]ao$JZ+^2k:vzT+{)b,Q400~xzxW'$9k å$׋^GrP5K) $` ~wz̟mQKgUͽIռ@[ C"OrڲOn959[v6V9nk޺wp]mӶY=b;8F3QU8ZfN #FFfj|t! n^2H5qRiτ"VqʔűhrN`XɌ6bqE@%?*qkU~l)/G-)(!,1Z7ut4~QjזiyZ]]h^Z5LOzZ [JVWċv~ҝN[)iD?Ue(%71vKʐ; jlr\pmƒσku+ݜP_΀"z9;Yo|MErH5҄MIfO+' |N'%srCs,g$ȯd_uBi䶂C̝ͫW^",>|&if싎YF^+Qm6XG.u/˖ud]ᯥR~9ӍRqҺM kC_˄jO y6F)Ǿ|jm6ꌣMԫ\}QRRҰ.b|$lھUc*e>My FJqY\&δ@- wІ v-'$+rոYdI{hpylzz%5\Dd9!#?cXF{_O҆2AfݭnAO;Ymn.i(JqR}HNq5ŤrTǽv8y= JddB9UF|OУYUdҬYfo9䆀o&\[$`lxK`&IJ@`۸v o+ɪ;;TS= p REvXN`v'J@@7^Ƀ9(1.w2V]W[tܚGZJcP7M}iǙ)@RG'hԶm7f7|=amPCuYvj!ԡ.#8Z9k =Qmٴj˵ylm^hF$ペn1YMY˷6!j-2PJe+zVm(uEiۛ=jb,H{d!d/aBn7;<4HH%gkv5}194̴;(N}[:51/Γ"_V͏j¥yg'%x~7JpMeipi"2HcRAeE 6Px9RQ-d#%i@`ipfvF=xc'kqpxIeh_ԱY=zu9s.<w5G+Փ|cGH.:*h2S.+nk|1h;ebP @(P @(*g;~C1*y'H.=u9:QƵhiB_8hn2Uj.II fʏpFԸ'AJM3f)zm(..`k~HM.u6”ф1i,vRt9B;z.7oY>~ezc2ݯL֯vb6sQt%.)a}f2k%kY*WcYL$lFK[.1Q*6Jgzs:s}Z!Z YMׂΪΞ^~sw9FQ*F<um͉G֦l=.$gF:) գG=B_aa0ՑȲ#V|?PcO{?ue?Ą=?G@:JΧ/><udsD|B~g)Ւ` :-LW_?3Y { հ ?Op>QXj}^O2?S&%_kofIHMO_ ~a(ՠ#Y:#I\(?PΧEH]2?Ξ?~ 7gSU#~}\R@:|:Υj ?ao)?O0-!=^~$ ~#Ws}xyR}>߂W12YY>XuKf-ڞmkm%@'= Kth!k+%HasM2j`zֹ݄nӪUW/{Ǭi8Q.!)ihx ))N;sZӤZ`]1r鍋WcDnCw!hZgZszjۻHq}`TexeZ߬_5|r\pnsNGֵ^J.fuG4kmNR e I-'A'8pk3oj+چr8 u!,)ISe;sj4f3M'7ᵄG@CGV2+|g KBIN=1\Os$J̕}ɭ5: 3TGw`j'FYLa#kK[F2䑟^>Y|~ΐvBq]ɾ˺i[mK9І 1pHSsDZވ4+c5a[[Zd(]䦔fyM.: %րJph[醣{RPei{'۾9[WlP @(P @(&Cq# Jֵ UdSl>e ĶZôypO^OiMfRz]|"ny ۮsdd:)k(^lPo%Q  fs#)ɕ7R;?wXcv.?̿cr{r+iexE蔥b>m GRY\,گˆjeW $՜ȏNR&X!AY9ա&9.n / K, OgP x;dm27'" աܤ6B|vk6_-I<blՓ>Li }^ʔ?=s_  s S=lKGR_s%p;ZPu *O̍(/O:Gÿ]uYZBJq.HGu+EFڱZuSX[I=:`_-:sUSJOO-rruh=q^ x3.$֪=yء{ꫭ2Ě (BOZirͺWTXE28ըd䨞k:VRsm@xh{a{˕sn{nRW;iq=.7GC|9Ma(P @(PSP`z7sK.ys,ί9kKS<%SKN_4ԩڮ.i &Aյ;cZ]:SLq~!oIYu(pqVgtXkN_VS;PUҭ&+9~U']@v1,LbsVS%Q9I,fѧ`1m)Xq'*VSܧӰԣ9һw [-J=vq+Ѧ4( NdJ6lQ%귤SxbN]WwTPJIrSk>Q -M)QӹI  9)+ }s^Y`-65e|Me##D]&"ܯ:~ė U"J\p$ֱjs^e[$:}-%]a9k_1x255.(Ҙl8`q?Ҍs_Hvڝ3mJpqk$WӂFEBy(jwnq_%WJyL]tI[zG3XHZՕ\?,̲i* :ּؗpqp+ 2VsֹYcF?^v t0cg^=|j Z&%11\n,qQ_x'<5j)}ŝsu.X1jryeA*ۚ[Ww.C轵AkTV'Mh.1<9<޹NJReOH[XQk~WVym` p)_1 R$vU/j@~e ]O:\D)Qu@n9vO3B?~ [Wު{TR {]cHV߽޾}<)QbI"o2Rt ?'xIPȩVo_kn- cPI N?[Ë 6FuMu l2J^}ki'obՖZ5!SX YB#x#޹A|rN5G&ꟊtj^mgL!90˄nqYеKNie:j-5˟Oyn`5$M}I?^lo^}[z]4']4]F:}[eEeA@A2lUfWť%H#qKɐy y$ z>YƷ24FMKb=[ Pd<&2OW&W/˱jRТ-ѻj|4D%ӱL/}PYڰ ~G[hM7=3lϼ|q,ZP @(P @(@E;ۢԑؼU 5;c'ԽAvG K{s'95 Q0w/ ޠBu򴂑qp5==onvklua=GKh 3Zt.6,tb>cWv<$ͩmXa$gg>iyͩnI4th?/8>tw+a9]>Ǝ8-׭P $ׂ!HVd* \Hlב6}@ꝆװHJ1sZ:un>- OY[2{w: J]ٺs{>>)֮d:™6>\5˗/*aV[<߉}C{~+%ޘіQIqZH}824٦E\w<ۍ{)9 V |u&qjCym34/t'LN{.̱ⴷ@;[5(P%qd>i_ r;ҎLc'3&u+3cK|}ʱj3+U54Lt}S v~դ-OOK^q-)($xVU.DMM][q-jNRFޣ;Q 3`xm,gZ嶂UcYx#Ef*)yePH NOl9-d;/KL Ҕj(+" |]i)o֩sN\| wOt$!V) <)J]BqG6k<ٺzOV璂ܜJ/3`DoӲy+HeKpIסK"?u裂.8NLYs>Z¶Y'$;VGg'T{Uu"L_$Ip!+WN{ULnUr"lu]:zW2J ZV<,wYWczoKҖiʅ-g;(P9(&+&Ur-KtIe4| p+O4ROK7> IN*[ Z ZIZCw$v=pP jN2}+l67Ի^*%GhF' R zU䶡|ʺH/gVI:|n$J}o8}Ts\۱5]g$1w +d^<=34UXZ (S z{חG5k?u'<?*՟Dk.~N( ws}!*ASa P?s/l(2۽գ/j8qcq>('+n0q;Tj{ږ=O5sX>{sںEv0ɒi'Y,hJ,rA౩[~.V#uشz(q5J[0kե_c[K_ [Fe1{rYCiJHXm}럭55,喙ʰ<ܔ>_S'ڴ.3O=,HGw e! %Ǐ=Ithwٲџ%#*_ǵc{kp[{-⊑%;Ӊڂ*8՗Cyx١ qod>[ e,̏\(ܲԁI8Sɇۭ)z.5kQk]NEHCvU}~G5M8/{\M:rݰ%3]oVXn[2$U=ό"'ZiXGʆӎ W c\\~;/?Y)-*^\{'Z:SUUض8)/:6T2ҰJ̅$g Yax&MVڼ;3qˎȑg޲*t\$pGN̙4gq6VZT8X! Xa#n)ɋ-ѵJww {Ujo.)$lMCuԚ.n1meE˴vPE$ gQ]LpG9ƙBUAg۸?#Zq(Kaf#dc[7Q"< .mʖO֯{SBD.H[3l!;si z{Y ơi ͍ LyN)@5(+ؗN,UAW!J{UCIIIdyeV i _|2pުeT9'HjIc`[%󗖠ԄƝa֑ղrk!2Dw+IwY-{L'֯٧cd6m8HvⶵIZֈpLn-ƭ:*2}ei.dCBR{jӶT'"{>o5 K1H* ,Hze9nMdF;Ku9[ |}j?^a-sۥ$iH6[ktnʳ4t J2g/,Nq0o7mPQT}jV<ɤG[2U6v-my <͵))kq]ԥM![nq#%3z%8Qk_5%?%&|MC1]ܧg YgKN|j_3VkvSFsK[ At<̲'[O pW%LcC1Sά(@'*%_ٶO :/RA|~u=MQxl5]:#eT$s K"ZypL,a;+eKqq5u]Bڂ*sԑI ;K+ X:H4=u#&(P @( NO e?Φsí=E|`Q#rkܟ[>\%[ѳ)F\H*ږWP5/kD^G$=_dֻcNS*~ L?W?_ƬJK7_mG$:{&-I$~+CO|N<]58= = $z~>}Dx9&¡DO}BV=^1M[= njCV[ |P3uU_1zQ'AQW^ u7P5lDy;VO"GGT^pcrX53.(G$ku4[y:hKui ]Bp#Tk\}XK:ZT[Y:M=ӽz^$ (C_qzթ5)c'FUBF>[zS=C`!i1ȬEFU;.xFƖw6Qm\lsh0s  ׮PQɵ5)~Vi5:/%v+IQ[YI`ܽUhͣRʎ@>qԭ$9Y9:#RȷII iXvbԖQĶ[΅۫w4xǥ^]+7 )ciŸOqܜw`fі哔FP @(5׈ |tv Y19?jjem5u6trG au]RʎI$ւ\aJc嘛rRѝ8j w KB^U_;8dA-՘]:ŴHϫ) ZW\䍍p|a?5jw6r=jeSu(9ɵtaυsR66^!===fa*Ԩt |v-<̧ݜ]#~N2+r㊶J9 f@sL+*Ԣ75d)ɣcqS;w\'p OJ^ICo!H=73UC֪[yqS9߭JDoSxNZ*Tg\UH0A3 KO,Sm)w)~n4ګPXElo&n.8rU) qDrZ9nHεs~X lMգ.+*5I1ؙWOzfkp`KiJ{hS*S V"eҞ0Ʈ@mYۗz9R@:Qw~" 5׶92ǖgNtvZWc?yLǃX.\u`p~\}O,ŭo>[ֳ1}̝ mO^TQ{#NVOnj|Fek3ٷ>CZx7a#{۟)nA]+jDeǎO)3ѳNs1BP9N@ܞކLՑ}͉m,vlf @-L.(/oK"Q^O$gzV]QNʷ;N_sWG jDeo%*+Vkmk%is]=,C [hP @( ORd[4|eH)C 9l Kv.lE` (\VG8YofE5mk#"aw5OTu)+:Xpk+@95;*EaN{Y^%R@p[26X=+QkJMw6AF귖.Фsn(pѽR}L܊t=yIc&QD{jozZgB=Zɭ!]@"9*ֱ[&u'Pl3{+BJǯϯGYf۹% 2W]x-гKcO)dY˲/1$kNtTzbzthaDTib &˅[ rGiwKɶ_(վ$UܸL+P۵ikLr4ψxn,^˓*,җkn$Gf;:+T'F3%z}%&\lIVJ@i{MLxR3j@(P @R mfPCSQH5Ci,Lj=#^kŕrR?+GwY+UIڒr}2,R8.I H߶Xuz3pkYkMzDQk{UkYĿl mtw=_4ӭWGn$17 @ܵLYfԗ%i+R_m-Άgw FY.8}I@V+nu)7accϪnu e^pVɹ4Rq[X1ckP,h83p+ YU Jtԧ$RV1Xf;O^Z{*ZW3S,r}-(ȮWR6ƺˤ]4j,(?Io=-I3KQkn] g֌>VyYe{{cZ,6 jn4% V~jg=;Y2+5=?n6m]YJ[,:fjE 7kVԖY.c=`[*F@CH$$p=_vaxOӊ+SGڜ p2@'⬉ lہR)i2JBX mFH9hdhHV#$52lTY4Lq2ru~ZlMK.>706pA-ȬJ.&W 5ўI=ɒD|oZߨb8ߌq! lwe)#2q^6٣5^ҮxR~[x$}t]iJ=lj\z=YtDnC->p3 }֏JTW(VE<;Rĉ ly@$}S==I6aek8S)&cPi5R0V-U%aԼpo[aI Q.A]ʊ?L9S>*n3Hh6# Fe4}4+sP8LJ~'JYacn~գ;#^<Ż5f߶+AƹlM'LT@ ݪ?i'JܹFtgr[WV)5V^z% %$(=^C$h]_z:u2sAR%]iSVBڲmz+,|`i6%q^%{K3y{Ք1E)XVMF|FsQH ԔrQѯf8%i9#=Mwv l yN&?NТ92r1LQ{u[!m=GZh w$!/"!a>*kڧ.&]$Gڶj++Y-> J5 ?OJӞ3yn+3fRZx'V7XEֵ-o1.<07 G)Lphkns+Qꥅ)唤dge*CoBqP@ɫ 7jErCg9R*0NO72MG̃A!#<  1T2{~u3xUH\ ԂaQIF3Q8GjJ%E*8XILSuHWdes8C+x#<$e> {e}3NNY%䌸^x7!me1/1RҠ~dԩ:Ӵ7vʻsj[Zw+cV53賖/`e ɯmR{Nx,-R`V LSSY jk0&]^Rq`K(=?4N2s1i_.Uk@(PAR~u4YT+B<}^C]57dBd>V( ~|W4&#>FژvtDM(29[SأJ鿧RY]٭z+#LwjtYP삝)WvG{S,Eв=ɸRԀ\蘬Æbݫ&M\2`="0z`Td =Y$'ާdKR!Ş*y9#"IPP,kI(ȇjr62%I9;9L[OT+dq>UhʠcY,p"v2>hVAA\PNDH~l`<=XL?'c*bB^ARIH ؼcvn^ۻ3oi2.8)ێ+vFBUJHۗo g%g&ud^5A. {WCkKYKmB28mA>LEKsEis-L` HS@3,(Keafcr@d6XBpF4ՏҢӊ-^-:\ΘZT`MIH },&9$n&O(̶T߶k6LLX3RNH-^vD(|?/@q@V|pk;]%BGjkci#D0` U}s=J/阬D<I~pS64{r+mN+Wtbςi_C޸=z;o1f}37˼FɇU\ҟY8˩Cկ]XG#lMc74)wy>}Fۜ^jA"rW8~ǩյ,;ߎ(Jet/d9€P @(,zQ54S,g֮ΝoaUno٨O)̿%,^fjhޝ{,6\oi!I",=ޛ4m_˅ҖBp^6seBE]4Tz;XH/[z=HlraS(=u+{LdggE}_&,IiF EM-vo6춴_y Y=kѦaOY*:\!J 53*G̟C޲DZON}) ?"Gb*&jNfΈ崥+@-&.Mv:Kk[&ޖ4a`UUs&=4SNR3dpAQ\#⋱\)؏[ɀOڮcm:SUl&MҰ1U.{N:T3jHGeħ9⛑l˰8SAQ2I[%r&[qݽьm4J]8mMt0 i{Kܵ^~+[.lج1Y/X%mv2cFKr6P!(lԽ+)^/&YKoijI'gd1l}Bm7`d}]$5;nH^ÙHZPK!P.q2&Kn(9k" =d>\%ACY>HQ: s+=]J˹RT'ڪE=n䬴x/`KwԓE ؼ5w67WbMVk4\cJj-ᒱtou}?޴ZprdMT2;#:ǒSYlXi-H4iPت[k@(~0/2Xvے quĒ}Oʝpԋdخ${W*R% 5ЖpUƼ]cǽhN=NYR<&_nROҰ**Ot}Ka7I>bs[aNuU{cR".|S[x)5Qk")IOcYwȨbf n,e4u1tMA@(xz Wal?LjrcnGJʼFI6P*"~QV;5E`~ sGj&~ ,iq,䤔Q Z\\Iҩ5ۉ\ m9F 5B8¶qɉSZkl= f!HP⑓հKhK>\}RKIwL."e$Žy"HVoa] G%Ce rqPk'k YDK͌eC?zYmcUhֈrRev2dg8ԴC"n,T(9|78b9|V?r?j6GN_eFƇJ_ 6 1Lҗ)YHǝ˜ez2$r8U,1NT/%7Ny=20>\ 5P {oU5rOO$ձ:Lj6*!PTg" 8##R.:=mLd9#'2EjqUJ2U݆*6}%N$vmhґ1Ձ#S{b[>'2dTkr1P.VarqIP\N۽Q<ҲħP9JYq}"-# SрZՅ&YB¶$By2r|Jf)#aiK͜3.%{TL ήP @( V TF=VQSN/0zCYRdxꟖUF1#эV?]?,ʥUtWF86V?U//foH4Hʞ$Fu N+~(Eu*!T|xraOj7MƲ*er,zХr}q.$p∕)n5>Km]58޵=Q?:XFN_4IR;GeOufu%*W`1W 2KrX nK)`N*paq Md$S"%pAI=!'o"Q2pAMQIqL"$92%R Yw2C 6eQ!dcFINKm#cң#9dayPN2#Lah db%Q8k>`"`03V,35<vfDJTCb1=$: RO"M`{ջU#N*͒JcqۚL,܊v Y<(ATd}MO f7eA~*_NjYbNAFO 2 ,psPG@PAQ sX%똴Αy+L3(x=+9Q@(P @rt Zli|2R}k]Kv7W7/ϙRY$σBK,KXԢľOd=F <3A'i^ C<UʵEF9qLqvvF'F#*Q#U"0 Z^I~8Ij%GC c#"!jT&CIW&&A2H!$)jp 16RHm y㚕؝OTbGN!=QL튔-j?ɩe(MN ?X&`j'"!+|rW~ Yګd`L29U20DCY=0r~S0N>G)"CF$|@T%L8\POՒ,g?P2$@9~ةD ⌐ ,5Woj`L w2Tژ[nY#87yJh7Y20?*60T5cҥTʇlJ/ NG5-pYWB\i(9/4~3:ڳmi%}(P @S\%& 'Y[IUkjlْ_֢<ťm7.st#qD:XLGp|ٜa9;?*~>ʥK3 W0tJL+JIaQI'8d8# V?ڧa+KßjC?j+?0|pQoHfWbqeB4<# W8ꞟNQfr$z3ï50keղL.*W>-F=һo]yGU"L<7^ȈF_u$_iFES {۸_j,Zd&ELȮu~<G=h2/7xy::l?d562]71՜6Nt_܏"6S6Ofw,ِztqi)`fY2F=GXV=WVL1'=H9[c%k gR; =]?lU䝬 T??ߞ Pf]b*KgP|FZ_B li43Hkh @(P7pwyC)5}J/ IISSW_Js .Zk6վdMvRyNSl'?򓾯ݯtē*oIn>Jx2⧡+դgb ڝ GդwZONIU#ޜO'NlEFu%W;fHWQ|Xo qX^su+ftb@Xcsb٘܏R[P W3B犇|##IKkO~dllKGC ibG.ȫpE(?[_zõ=Gj|ytԪd9Dge憕TVh.i莗GVUQ|m1~-#z'OFFOo__nh,2zGO:WAQ|Hܟo]sZ)'2Q{GJ~/XgUDe|?s<9AY1OT "NEh>q:t-3qg1y/MviwaNcJK?*WC'콳?QZ?6*?2?cOF?f-gdJ?L~d6!?*}F?f6*䞣M[Cu/콷E?_$dM7o{Ց/͸F֐N'F~۳o5>Hk5W^^$ گke[ 7$GJIV'E2U(HiZ?*?7oõ*9ewQ[_]!ʣddGP" Z4(Qd| [idKrM*F`__). You can also find the driver in the GitHub repository `here `__, and to use this version you will need to copy the file to your board, into a directory that is searched by import (usually the lib/ directory). Once you have the driver installed you need to import it to use it:: import lcd160cr Testing the display ------------------- There is a test program which you can use to test the features of the display, and which also serves as a basis to start creating your own code that uses the LCD. This test program is included in recent versions of the pyboard firmware and is also available on GitHub `here `__. To run the test from the MicroPython prompt do:: >>> import lcd160cr_test It will then print some brief instructions. You will need to know which position your display is connected to (X or Y) and then you can run (assuming you have the display on position X):: >>> test_all('X') Drawing some graphics --------------------- You must first create an LCD160CR object which will control the display. Do this using:: >>> import lcd160cr >>> lcd = lcd160cr.LCD160CR('X') This assumes your display is connected in the X position. If it's in the Y position then use ``lcd = lcd160cr.LCD160CR('Y')`` instead. To erase the screen and draw a line, try:: >>> lcd.set_pen(lcd.rgb(255, 0, 0), lcd.rgb(64, 64, 128)) >>> lcd.erase() >>> lcd.line(10, 10, 50, 80) The next example draws random rectangles on the screen. You can copy-and-paste it into the MicroPython prompt by first pressing "Ctrl-E" at the prompt, then "Ctrl-D" once you have pasted the text. :: from random import randint for i in range(1000): fg = lcd.rgb(randint(128, 255), randint(128, 255), randint(128, 255)) bg = lcd.rgb(randint(0, 128), randint(0, 128), randint(0, 128)) lcd.set_pen(fg, bg) lcd.rect(randint(0, lcd.w), randint(0, lcd.h), randint(10, 40), randint(10, 40)) Using the touch sensor ---------------------- The display includes a resistive touch sensor that can report the position (in pixels) of a single force-based touch on the screen. To see if there is a touch on the screen use:: >>> lcd.is_touched() This will return either ``False`` or ``True``. Run the above command while touching the screen to see the result. To get the location of the touch you can use the method:: >>> lcd.get_touch() This will return a 3-tuple, with the first entry being 0 or 1 depending on whether there is currently anything touching the screen (1 if there is), and the second and third entries in the tuple being the x and y coordinates of the current (or most recent) touch. Directing the MicroPython output to the display ----------------------------------------------- The display supports input from a UART and implements basic VT100 commands, which means it can be used as a simple, general purpose terminal. Let's set up the pyboard to redirect its output to the display. First you need to create a UART object:: >>> import pyb >>> uart = pyb.UART('XA', 115200) This assumes your display is connected to position X. If it's on position Y then use ``uart = pyb.UART('YA', 115200)`` instead. Now, connect the REPL output to this UART:: >>> pyb.repl_uart(uart) From now on anything you type at the MicroPython prompt, and any output you receive, will appear on the display. No set-up commands are required for this mode to work and you can use the display to monitor the output of any UART, not just from the pyboard. All that is needed is for the display to have power, ground and the power/enable pin driven high. Then any characters on the display's UART input will be printed to the screen. You can adjust the UART baudrate from the default of 115200 using the `set_uart_baudrate` method. micropython-1.12/docs/pyboard/tutorial/lcd_skin.rst000066400000000000000000000052371357706137100226040ustar00rootroot00000000000000The LCD and touch-sensor skin ============================= Soldering and using the LCD and touch-sensor skin. .. image:: img/skin_lcd_1.jpg :alt: pyboard with LCD skin :width: 250px .. image:: img/skin_lcd_2.jpg :alt: pyboard with LCD skin :width: 250px The following video shows how to solder the headers onto the LCD skin. At the end of the video, it shows you how to correctly connect the LCD skin to the pyboard. .. raw:: html For circuit schematics and datasheets for the components on the skin see :ref:`hardware_index`. Using the LCD ------------- To get started using the LCD, try the following at the MicroPython prompt. Make sure the LCD skin is attached to the pyboard as pictured at the top of this page. :: >>> import pyb >>> lcd = pyb.LCD('X') >>> lcd.light(True) >>> lcd.write('Hello uPy!\n') You can make a simple animation using the code:: import pyb lcd = pyb.LCD('X') lcd.light(True) for x in range(-80, 128): lcd.fill(0) lcd.text('Hello uPy!', x, 10, 1) lcd.show() pyb.delay(25) Using the touch sensor ---------------------- To read the touch-sensor data you need to use the I2C bus. The MPR121 capacitive touch sensor has address 90. To get started, try:: >>> import pyb >>> i2c = pyb.I2C(1, pyb.I2C.MASTER) >>> i2c.mem_write(4, 90, 0x5e) >>> touch = i2c.mem_read(1, 90, 0)[0] The first line above makes an I2C object, and the second line enables the 4 touch sensors. The third line reads the touch status and the ``touch`` variable holds the state of the 4 touch buttons (A, B, X, Y). There is a simple driver `here `__ which allows you to set the threshold and debounce parameters, and easily read the touch status and electrode voltage levels. Copy this script to your pyboard (either flash or SD card, in the top directory or ``lib/`` directory) and then try:: >>> import pyb >>> import mpr121 >>> m = mpr121.MPR121(pyb.I2C(1, pyb.I2C.MASTER)) >>> for i in range(100): ... print(m.touch_status()) ... pyb.delay(100) ... This will continuously print out the touch status of all electrodes. Try touching each one in turn. Note that if you put the LCD skin in the Y-position, then you need to initialise the I2C bus using:: >>> m = mpr121.MPR121(pyb.I2C(2, pyb.I2C.MASTER)) There is also a demo which uses the LCD and the touch sensors together, and can be found `here `__. micropython-1.12/docs/pyboard/tutorial/leds.rst000066400000000000000000000112221357706137100217340ustar00rootroot00000000000000Turning on LEDs and basic Python concepts ========================================= The easiest thing to do on the pyboard is to turn on the LEDs attached to the board. Connect the board, and log in as described in tutorial 1. We will start by turning and LED on in the interpreter, type the following :: >>> myled = pyb.LED(1) >>> myled.on() >>> myled.off() These commands turn the LED on and off. This is all very well but we would like this process to be automated. Open the file MAIN.PY on the pyboard in your favourite text editor. Write or paste the following lines into the file. If you are new to python, then make sure you get the indentation correct since this matters! :: led = pyb.LED(2) while True: led.toggle() pyb.delay(1000) When you save, the red light on the pyboard should turn on for about a second. To run the script, do a soft reset (CTRL-D). The pyboard will then restart and you should see a green light continuously flashing on and off. Success, the first step on your path to building an army of evil robots! When you are bored of the annoying flashing light then press CTRL-C at your terminal to stop it running. So what does this code do? First we need some terminology. Python is an object-oriented language, almost everything in python is a *class* and when you create an instance of a class you get an *object*. Classes have *methods* associated to them. A method (also called a member function) is used to interact with or control the object. The first line of code creates an LED object which we have then called led. When we create the object, it takes a single parameter which must be between 1 and 4, corresponding to the 4 LEDs on the board. The pyb.LED class has three important member functions that we will use: on(), off() and toggle(). The other function that we use is pyb.delay() this simply waits for a given time in milliseconds. Once we have created the LED object, the statement while True: creates an infinite loop which toggles the led between on and off and waits for 1 second. **Exercise: Try changing the time between toggling the led and turning on a different LED.** **Exercise: Connect to the pyboard directly, create a pyb.LED object and turn it on using the on() method.** A Disco on your pyboard ----------------------- So far we have only used a single LED but the pyboard has 4 available. Let's start by creating an object for each LED so we can control each of them. We do that by creating a list of LEDS with a list comprehension. :: leds = [pyb.LED(i) for i in range(1,5)] If you call pyb.LED() with a number that isn't 1,2,3,4 you will get an error message. Next we will set up an infinite loop that cycles through each of the LEDs turning them on and off. :: n = 0 while True: n = (n + 1) % 4 leds[n].toggle() pyb.delay(50) Here, n keeps track of the current LED and every time the loop is executed we cycle to the next n (the % sign is a modulus operator that keeps n between 0 and 3.) Then we access the nth LED and toggle it. If you run this you should see each of the LEDs turning on then all turning off again in sequence. One problem you might find is that if you stop the script and then start it again that the LEDs are stuck on from the previous run, ruining our carefully choreographed disco. We can fix this by turning all the LEDs off when we initialise the script and then using a try/finally block. When you press CTRL-C, MicroPython generates a VCPInterrupt exception. Exceptions normally mean something has gone wrong and you can use a try: command to "catch" an exception. In this case it is just the user interrupting the script, so we don't need to catch the error but just tell MicroPython what to do when we exit. The finally block does this, and we use it to make sure all the LEDs are off. The full code is:: leds = [pyb.LED(i) for i in range(1,5)] for l in leds: l.off() n = 0 try: while True: n = (n + 1) % 4 leds[n].toggle() pyb.delay(50) finally: for l in leds: l.off() The Special LEDs ---------------- The yellow and blue LEDs are special. As well as turning them on and off, you can control their intensity using the intensity() method. This takes a number between 0 and 255 that determines how bright it is. The following script makes the blue LED gradually brighter then turns it off again. :: led = pyb.LED(4) intensity = 0 while True: intensity = (intensity + 1) % 255 led.intensity(intensity) pyb.delay(20) You can call intensity() on LEDs 1 and 2 but they can only be off or on. 0 sets them off and any other number up to 255 turns them on. micropython-1.12/docs/pyboard/tutorial/pass_through.rst000066400000000000000000000007031357706137100235150ustar00rootroot00000000000000Making a UART - USB pass through ================================ It's as simple as:: import pyb import select def pass_through(usb, uart): usb.setinterrupt(-1) while True: select.select([usb, uart], [], []) if usb.any(): uart.write(usb.read(256)) if uart.any(): usb.write(uart.read(256)) pass_through(pyb.USB_VCP(), pyb.UART(1, 9600, timeout=0)) micropython-1.12/docs/pyboard/tutorial/power_ctrl.rst000066400000000000000000000005261357706137100231720ustar00rootroot00000000000000Power control ============= :meth:`pyb.wfi` is used to reduce power consumption while waiting for an event such as an interrupt. You would use it in the following situation:: while True: do_some_processing() pyb.wfi() Control the frequency using :meth:`pyb.freq`:: pyb.freq(30000000) # set CPU frequency to 30MHz micropython-1.12/docs/pyboard/tutorial/repl.rst000066400000000000000000000104011357706137100217450ustar00rootroot00000000000000Getting a MicroPython REPL prompt ================================= REPL stands for Read Evaluate Print Loop, and is the name given to the interactive MicroPython prompt that you can access on the pyboard. Using the REPL is by far the easiest way to test out your code and run commands. You can use the REPL in addition to writing scripts in ``main.py``. To use the REPL, you must connect to the serial USB device on the pyboard. How you do this depends on your operating system. Windows ------- You need to install the pyboard driver to use the serial USB device. The driver is on the pyboard's USB flash drive, and is called ``pybcdc.inf``. To install this driver you need to go to Device Manager for your computer, find the pyboard in the list of devices (it should have a warning sign next to it because it's not working yet), right click on the pyboard device, select Properties, then Install Driver. You need to then select the option to find the driver manually (don't use Windows auto update), navigate to the pyboard's USB drive, and select that. It should then install. After installing, go back to the Device Manager to find the installed pyboard, and see which COM port it is (eg COM4). More comprehensive instructions can be found in the `Guide for pyboard on Windows (PDF) `_. Please consult this guide if you are having problems installing the driver. You now need to run your terminal program. You can use HyperTerminal if you have it installed, or download the free program PuTTY: `putty.exe `_. Using your serial program you must connect to the COM port that you found in the previous step. With PuTTY, click on "Session" in the left-hand panel, then click the "Serial" radio button on the right, then enter you COM port (eg COM4) in the "Serial Line" box. Finally, click the "Open" button. Mac OS X -------- Open a terminal and run:: screen /dev/tty.usbmodem* When you are finished and want to exit screen, type CTRL-A CTRL-\\. Linux ----- Open a terminal and run:: screen /dev/ttyACM0 You can also try ``picocom`` or ``minicom`` instead of screen. You may have to use ``/dev/ttyACM1`` or a higher number for ``ttyACM``. And, you may need to give yourself the correct permissions to access this devices (eg group ``uucp`` or ``dialout``, or use sudo). Using the REPL prompt --------------------- Now let's try running some MicroPython code directly on the pyboard. With your serial program open (PuTTY, screen, picocom, etc) you may see a blank screen with a flashing cursor. Press Enter and you should be presented with a MicroPython prompt, i.e. ``>>>``. Let's make sure it is working with the obligatory test:: >>> print("hello pyboard!") hello pyboard! In the above, you should not type in the ``>>>`` characters. They are there to indicate that you should type the text after it at the prompt. In the end, once you have entered the text ``print("hello pyboard!")`` and pressed Enter, the output on your screen should look like it does above. If you already know some python you can now try some basic commands here. If any of this is not working you can try either a hard reset or a soft reset; see below. Go ahead and try typing in some other commands. For example:: >>> pyb.LED(1).on() >>> pyb.LED(2).on() >>> 1 + 2 3 >>> 1 / 2 0.5 >>> 20 * 'py' 'pypypypypypypypypypypypypypypypypypypypy' Resetting the board ------------------- If something goes wrong, you can reset the board in two ways. The first is to press CTRL-D at the MicroPython prompt, which performs a soft reset. You will see a message something like :: >>> MPY: sync filesystems MPY: soft reboot Micro Python v1.0 on 2014-05-03; PYBv1.0 with STM32F405RG Type "help()" for more information. >>> If that isn't working you can perform a hard reset (turn-it-off-and-on-again) by pressing the RST switch (the small black button closest to the micro-USB socket on the board). This will end your session, disconnecting whatever program (PuTTY, screen, etc) that you used to connect to the pyboard. If you are going to do a hard-reset, it's recommended to first close your serial program and eject/unmount the pyboard drive. micropython-1.12/docs/pyboard/tutorial/reset.rst000066400000000000000000000050401357706137100221300ustar00rootroot00000000000000Safe mode and factory reset =========================== If something goes wrong with your pyboard, don't panic! It is almost impossible for you to break the pyboard by programming the wrong thing. The first thing to try is to enter safe mode: this temporarily skips execution of ``boot.py`` and ``main.py`` and gives default USB settings. If you have problems with the filesystem you can do a factory reset, which restores the filesystem to its original state. Safe mode --------- To enter safe mode, do the following steps: 1. Connect the pyboard to USB so it powers up. 2. Hold down the USR switch. 3. While still holding down USR, press and release the RST switch. 4. The LEDs will then cycle green to orange to green+orange and back again. 5. Keep holding down USR until *only the orange LED is lit*, and then let go of the USR switch. 6. The orange LED should flash quickly 4 times, and then turn off. 7. You are now in safe mode. In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so the pyboard boots up with default settings. This means you now have access to the filesystem (the USB drive should appear), and you can edit ``boot.py`` and ``main.py`` to fix any problems. Entering safe mode is temporary, and does not make any changes to the files on the pyboard. Factory reset the filesystem ---------------------------- If you pyboard's filesystem gets corrupted (for example, you forgot to eject/unmount it), or you have some code in ``boot.py`` or ``main.py`` which you can't escape from, then you can reset the filesystem. Resetting the filesystem deletes all files on the internal pyboard storage (not the SD card), and restores the files ``boot.py``, ``main.py``, ``README.txt`` and ``pybcdc.inf`` back to their original state. To do a factory reset of the filesystem you follow a similar procedure as you did to enter safe mode, but release USR on green+orange: 1. Connect the pyboard to USB so it powers up. 2. Hold down the USR switch. 3. While still holding down USR, press and release the RST switch. 4. The LEDs will then cycle green to orange to green+orange and back again. 5. Keep holding down USR until *both the green and orange LEDs are lit*, and then let go of the USR switch. 6. The green and orange LEDs should flash quickly 4 times. 7. The red LED will turn on (so red, green and orange are now on). 8. The pyboard is now resetting the filesystem (this takes a few seconds). 9. The LEDs all turn off. 10. You now have a reset filesystem, and are in safe mode. 11. Press and release the RST switch to boot normally. micropython-1.12/docs/pyboard/tutorial/script.rst000066400000000000000000000105071357706137100223160ustar00rootroot00000000000000Running your first script ========================= Let's jump right in and get a Python script running on the pyboard. After all, that's what it's all about! Connecting your pyboard ----------------------- Connect your pyboard to your PC (Windows, Mac or Linux) with a micro USB cable. There is only one way that the cable will connect, so you can't get it wrong. .. image:: img/pyboard_usb_micro.jpg When the pyboard is connected to your PC it will power on and enter the start up process (the boot process). The green LED should light up for half a second or less, and when it turns off it means the boot process has completed. Opening the pyboard USB drive ----------------------------- Your PC should now recognise the pyboard. It depends on the type of PC you have as to what happens next: - **Windows**: Your pyboard will appear as a removable USB flash drive. Windows may automatically pop-up a window, or you may need to go there using Explorer. Windows will also see that the pyboard has a serial device, and it will try to automatically configure this device. If it does, cancel the process. We will get the serial device working in the next tutorial. - **Mac**: Your pyboard will appear on the desktop as a removable disc. It will probably be called ``PYBFLASH``. Click on it to open the pyboard folder. - **Linux**: Your pyboard will appear as a removable medium. On Ubuntu it will mount automatically and pop-up a window with the pyboard folder. On other Linux distributions, the pyboard may be mounted automatically, or you may need to do it manually. At a terminal command line, type ``lsblk`` to see a list of connected drives, and then ``mount /dev/sdb1`` (replace ``sdb1`` with the appropriate device). You may need to be root to do this. Okay, so you should now have the pyboard connected as a USB flash drive, and a window (or command line) should be showing the files on the pyboard drive. The drive you are looking at is known as ``/flash`` by the pyboard, and should contain the following 4 files: * `boot.py `_ -- the various configuration options for the pyboard. It is executed when the pyboard boots up. * `main.py `_ -- the Python program to be run. It is executed after ``boot.py``. * `README.txt `_ -- basic information about getting started with the pyboard. This provides pointers for new users and can be safely deleted. * `pybcdc.inf `_ -- the Windows driver file to configure the serial USB device. More about this in the next tutorial. Editing ``main.py`` ------------------- Now we are going to write our Python program, so open the ``main.py`` file in a text editor. On Windows you can use notepad, or any other editor. On Mac and Linux, use your favourite text editor. With the file open you will see it contains 1 line:: # main.py -- put your code here! This line starts with a # character, which means that it is a *comment*. Such lines will not do anything, and are there for you to write notes about your program. Let's add 2 lines to this ``main.py`` file, to make it look like this:: # main.py -- put your code here! import pyb pyb.LED(4).on() The first line we wrote says that we want to use the ``pyb`` module. This module contains all the functions and classes to control the features of the pyboard. The second line that we wrote turns the blue LED on: it first gets the ``LED`` class from the ``pyb`` module, creates LED number 4 (the blue LED), and then turns it on. Resetting the pyboard --------------------- To run this little script, you need to first save and close the ``main.py`` file, and then eject (or unmount) the pyboard USB drive. Do this like you would a normal USB flash drive. When the drive is safely ejected/unmounted you can get to the fun part: press the RST switch on the pyboard to reset and run your script. The RST switch is the small black button just below the USB connector on the board, on the right edge. When you press RST the green LED will flash quickly, and then the blue LED should turn on and stay on. Congratulations! You have written and run your very first MicroPython program! micropython-1.12/docs/pyboard/tutorial/servo.rst000066400000000000000000000132351357706137100221510ustar00rootroot00000000000000Controlling hobby servo motors ============================== There are 4 dedicated connection points on the pyboard for connecting up hobby servo motors (see eg `Wikipedia `__). These motors have 3 wires: ground, power and signal. On the pyboard you can connect them in the bottom right corner, with the signal pin on the far right. Pins X1, X2, X3 and X4 are the 4 dedicated servo signal pins. .. image:: img/pyboard_servo.jpg In this picture there are male-male double adaptors to connect the servos to the header pins on the pyboard. The ground wire on a servo is usually the darkest coloured one, either black or dark brown. The power wire will most likely be red. The power pin for the servos (labelled VIN) is connected directly to the input power source of the pyboard. When powered via USB, VIN is powered through a diode by the 5V USB power line. Connect to USB, the pyboard can power at least 4 small to medium sized servo motors. If using a battery to power the pyboard and run servo motors, make sure it is not greater than 6V, since this is the maximum voltage most servo motors can take. (Some motors take only up to 4.8V, so check what type you are using.) Creating a Servo object ----------------------- Plug in a servo to position 1 (the one with pin X1) and create a servo object using:: >>> servo1 = pyb.Servo(1) To change the angle of the servo use the ``angle`` method:: >>> servo1.angle(45) >>> servo1.angle(-60) The angle here is measured in degrees, and ranges from about -90 to +90, depending on the motor. Calling ``angle`` without parameters will return the current angle:: >>> servo1.angle() -60 Note that for some angles, the returned angle is not exactly the same as the angle you set, due to rounding errors in setting the pulse width. You can pass a second parameter to the ``angle`` method, which specifies how long to take (in milliseconds) to reach the desired angle. For example, to take 1 second (1000 milliseconds) to go from the current position to 50 degrees, use :: >>> servo1.angle(50, 1000) This command will return straight away and the servo will continue to move to the desired angle, and stop when it gets there. You can use this feature as a speed control, or to synchronise 2 or more servo motors. If we have another servo motor (``servo2 = pyb.Servo(2)``) then we can do :: >>> servo1.angle(-45, 2000); servo2.angle(60, 2000) This will move the servos together, making them both take 2 seconds to reach their final angles. Note: the semicolon between the 2 expressions above is used so that they are executed one after the other when you press enter at the REPL prompt. In a script you don't need to do this, you can just write them one line after the other. Continuous rotation servos -------------------------- So far we have been using standard servos that move to a specific angle and stay at that angle. These servo motors are useful to create joints of a robot, or things like pan-tilt mechanisms. Internally, the motor has a variable resistor (potentiometer) which measures the current angle and applies power to the motor proportional to how far it is from the desired angle. The desired angle is set by the width of a high-pulse on the servo signal wire. A pulse width of 1500 microsecond corresponds to the centre position (0 degrees). The pulses are sent at 50 Hz, ie 50 pulses per second. You can also get **continuous rotation** servo motors which turn continuously clockwise or counterclockwise. The direction and speed of rotation is set by the pulse width on the signal wire. A pulse width of 1500 microseconds corresponds to a stopped motor. A pulse width smaller or larger than this means rotate one way or the other, at a given speed. On the pyboard, the servo object for a continuous rotation motor is the same as before. In fact, using ``angle`` you can set the speed. But to make it easier to understand what is intended, there is another method called ``speed`` which sets the speed:: >>> servo1.speed(30) ``speed`` has the same functionality as ``angle``: you can get the speed, set it, and set it with a time to reach the final speed. :: >>> servo1.speed() 30 >>> servo1.speed(-20) >>> servo1.speed(0, 2000) The final command above will set the motor to stop, but take 2 seconds to do it. This is essentially a control over the acceleration of the continuous servo. A servo speed of 100 (or -100) is considered maximum speed, but actually you can go a bit faster than that, depending on the particular motor. The only difference between the ``angle`` and ``speed`` methods (apart from the name) is the way the input numbers (angle or speed) are converted to a pulse width. Calibration ----------- The conversion from angle or speed to pulse width is done by the servo object using its calibration values. To get the current calibration, use :: >>> servo1.calibration() (640, 2420, 1500, 2470, 2200) There are 5 numbers here, which have meaning: 1. Minimum pulse width; the smallest pulse width that the servo accepts. 2. Maximum pulse width; the largest pulse width that the servo accepts. 3. Centre pulse width; the pulse width that puts the servo at 0 degrees or 0 speed. 4. The pulse width corresponding to 90 degrees. This sets the conversion in the method ``angle`` of angle to pulse width. 5. The pulse width corresponding to a speed of 100. This sets the conversion in the method ``speed`` of speed to pulse width. You can recalibrate the servo (change its default values) by using:: >>> servo1.calibration(700, 2400, 1510, 2500, 2000) Of course, you would change the above values to suit your particular servo motor. micropython-1.12/docs/pyboard/tutorial/switch.rst000066400000000000000000000110341357706137100223070ustar00rootroot00000000000000.. _pyboard_tutorial_switch: The Switch, callbacks and interrupts ==================================== The pyboard has 2 small switches, labelled USR and RST. The RST switch is a hard-reset switch, and if you press it then it restarts the pyboard from scratch, equivalent to turning the power off then back on. The USR switch is for general use, and is controlled via a Switch object. To make a switch object do:: >>> sw = pyb.Switch() Remember that you may need to type ``import pyb`` if you get an error that the name ``pyb`` does not exist. With the switch object you can get its status:: >>> sw.value() False This will print ``False`` if the switch is not held, or ``True`` if it is held. Try holding the USR switch down while running the above command. There is also a shorthand notation to get the switch status, by "calling" the switch object:: >>> sw() False Switch callbacks ---------------- The switch is a very simple object, but it does have one advanced feature: the ``sw.callback()`` function. The callback function sets up something to run when the switch is pressed, and uses an interrupt. It's probably best to start with an example before understanding how interrupts work. Try running the following at the prompt:: >>> sw.callback(lambda:print('press!')) This tells the switch to print ``press!`` each time the switch is pressed down. Go ahead and try it: press the USR switch and watch the output on your PC. Note that this print will interrupt anything you are typing, and is an example of an interrupt routine running asynchronously. As another example try:: >>> sw.callback(lambda:pyb.LED(1).toggle()) This will toggle the red LED each time the switch is pressed. And it will even work while other code is running. To disable the switch callback, pass ``None`` to the callback function:: >>> sw.callback(None) You can pass any function (that takes zero arguments) to the switch callback. Above we used the ``lambda`` feature of Python to create an anonymous function on the fly. But we could equally do:: >>> def f(): ... pyb.LED(1).toggle() ... >>> sw.callback(f) This creates a function called ``f`` and assigns it to the switch callback. You can do things this way when your function is more complicated than a ``lambda`` will allow. Note that your callback functions must not allocate any memory (for example they cannot create a tuple or list). Callback functions should be relatively simple. If you need to make a list, make it beforehand and store it in a global variable (or make it local and close over it). If you need to do a long, complicated calculation, then use the callback to set a flag which some other code then responds to. Technical details of interrupts ------------------------------- Let's step through the details of what is happening with the switch callback. When you register a function with ``sw.callback()``, the switch sets up an external interrupt trigger (falling edge) on the pin that the switch is connected to. This means that the microcontroller will listen on the pin for any changes, and the following will occur: 1. When the switch is pressed a change occurs on the pin (the pin goes from low to high), and the microcontroller registers this change. 2. The microcontroller finishes executing the current machine instruction, stops execution, and saves its current state (pushes the registers on the stack). This has the effect of pausing any code, for example your running Python script. 3. The microcontroller starts executing the special interrupt handler associated with the switch's external trigger. This interrupt handler get the function that you registered with ``sw.callback()`` and executes it. 4. Your callback function is executed until it finishes, returning control to the switch interrupt handler. 5. The switch interrupt handler returns, and the microcontroller is notified that the interrupt has been dealt with. 6. The microcontroller restores the state that it saved in step 2. 7. Execution continues of the code that was running at the beginning. Apart from the pause, this code does not notice that it was interrupted. The above sequence of events gets a bit more complicated when multiple interrupts occur at the same time. In that case, the interrupt with the highest priority goes first, then the others in order of their priority. The switch interrupt is set at the lowest priority. Further reading --------------- For further information about using hardware interrupts see :ref:`writing interrupt handlers `. micropython-1.12/docs/pyboard/tutorial/timer.rst000066400000000000000000000072101357706137100221270ustar00rootroot00000000000000The Timers ========== The pyboard has 14 timers which each consist of an independent counter running at a user-defined frequency. They can be set up to run a function at specific intervals. The 14 timers are numbered 1 through 14, but 3 is reserved for internal use, and 5 and 6 are used for servo and ADC/DAC control. Avoid using these timers if possible. Let's create a timer object:: >>> tim = pyb.Timer(4) Now let's see what we just created:: >>> tim Timer(4) The pyboard is telling us that ``tim`` is attached to timer number 4, but it's not yet initialised. So let's initialise it to trigger at 10 Hz (that's 10 times per second):: >>> tim.init(freq=10) Now that it's initialised, we can see some information about the timer:: >>> tim Timer(4, prescaler=624, period=13439, mode=UP, div=1) The information means that this timer is set to run at the peripheral clock speed divided by 624+1, and it will count from 0 up to 13439, at which point it triggers an interrupt, and then starts counting again from 0. These numbers are set to make the timer trigger at 10 Hz: the source frequency of the timer is 84MHz (found by running ``tim.source_freq()``) so we get 84MHz / 625 / 13440 = 10Hz. Timer counter ------------- So what can we do with our timer? The most basic thing is to get the current value of its counter:: >>> tim.counter() 21504 This counter will continuously change, and counts up. Timer callbacks --------------- The next thing we can do is register a callback function for the timer to execute when it triggers (see the :ref:`switch tutorial ` for an introduction to callback functions):: >>> tim.callback(lambda t:pyb.LED(1).toggle()) This should start the red LED flashing right away. It will be flashing at 5 Hz (2 toggle's are needed for 1 flash, so toggling at 10 Hz makes it flash at 5 Hz). You can change the frequency by re-initialising the timer:: >>> tim.init(freq=20) You can disable the callback by passing it the value ``None``:: >>> tim.callback(None) The function that you pass to callback must take 1 argument, which is the timer object that triggered. This allows you to control the timer from within the callback function. We can create 2 timers and run them independently:: >>> tim4 = pyb.Timer(4, freq=10) >>> tim7 = pyb.Timer(7, freq=20) >>> tim4.callback(lambda t: pyb.LED(1).toggle()) >>> tim7.callback(lambda t: pyb.LED(2).toggle()) Because the callbacks are proper hardware interrupts, we can continue to use the pyboard for other things while these timers are running. Making a microsecond counter ---------------------------- You can use a timer to create a microsecond counter, which might be useful when you are doing something which requires accurate timing. We will use timer 2 for this, since timer 2 has a 32-bit counter (so does timer 5, but if you use timer 5 then you can't use the Servo driver at the same time). We set up timer 2 as follows:: >>> micros = pyb.Timer(2, prescaler=83, period=0x3fffffff) The prescaler is set at 83, which makes this timer count at 1 MHz. This is because the CPU clock, running at 168 MHz, is divided by 2 and then by prescaler+1, giving a frequency of 168 MHz/2/(83+1)=1 MHz for timer 2. The period is set to a large number so that the timer can count up to a large number before wrapping back around to zero. In this case it will take about 17 minutes before it cycles back to zero. To use this timer, it's best to first reset it to 0:: >>> micros.counter(0) and then perform your timing:: >>> start_micros = micros.counter() ... do some stuff ... >>> end_micros = micros.counter() micropython-1.12/docs/pyboard/tutorial/usb_mouse.rst000066400000000000000000000120121357706137100230040ustar00rootroot00000000000000Making the pyboard act as a USB mouse ===================================== The pyboard is a USB device, and can configured to act as a mouse instead of the default USB flash drive. To do this we must first edit the ``boot.py`` file to change the USB configuration. If you have not yet touched your ``boot.py`` file then it will look something like this:: # boot.py -- run on boot-up # can run arbitrary Python, but best to keep it minimal import pyb #pyb.main('main.py') # main script to run after this one #pyb.usb_mode('VCP+MSC') # act as a serial and a storage device #pyb.usb_mode('VCP+HID') # act as a serial device and a mouse To enable the mouse mode, uncomment the last line of the file, to make it look like:: pyb.usb_mode('VCP+HID') # act as a serial device and a mouse If you already changed your ``boot.py`` file, then the minimum code it needs to work is:: import pyb pyb.usb_mode('VCP+HID') This tells the pyboard to configure itself as a VCP (Virtual COM Port, ie serial port) and HID (human interface device, in our case a mouse) USB device when it boots up. Eject/unmount the pyboard drive and reset it using the RST switch. Your PC should now detect the pyboard as a mouse! Sending mouse events by hand ---------------------------- To get the py-mouse to do anything we need to send mouse events to the PC. We will first do this manually using the REPL prompt. Connect to your pyboard using your serial program and type the following (no need to type the ``#`` and text following it):: >>> hid = pyb.USB_HID() >>> hid.send((0, 100, 0, 0)) # (button status, x-direction, y-direction, scroll) Your mouse should move 100 pixels to the right! In the command above you are sending 4 pieces of information: **button status**, **x-direction**, **y-direction**, and **scroll**. The number 100 is telling the PC that the mouse moved 100 pixels in the x direction. Let's make the mouse oscillate left and right:: >>> import math >>> def osc(n, d): ... for i in range(n): ... hid.send((0, int(20 * math.sin(i / 10)), 0, 0)) ... pyb.delay(d) ... >>> osc(100, 50) The first argument to the function ``osc`` is the number of mouse events to send, and the second argument is the delay (in milliseconds) between events. Try playing around with different numbers. **Exercise: make the mouse go around in a circle.** Making a mouse with the accelerometer ------------------------------------- Now lets make the mouse move based on the angle of the pyboard, using the accelerometer. The following code can be typed directly at the REPL prompt, or put in the ``main.py`` file. Here, we'll put in in ``main.py`` because to do that we will learn how to go into safe mode. At the moment the pyboard is acting as a serial USB device and an HID (a mouse). So you cannot access the filesystem to edit your ``main.py`` file. You also can't edit your ``boot.py`` to get out of HID-mode and back to normal mode with a USB drive... To get around this we need to go into *safe mode*. This was described in the [safe mode tutorial](tut-reset), but we repeat the instructions here: 1. Hold down the USR switch. 2. While still holding down USR, press and release the RST switch. 3. The LEDs will then cycle green to orange to green+orange and back again. 4. Keep holding down USR until *only the orange LED is lit*, and then let go of the USR switch. 5. The orange LED should flash quickly 4 times, and then turn off. 6. You are now in safe mode. In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so the pyboard boots up with default settings. This means you now have access to the filesystem (the USB drive should appear), and you can edit ``main.py``. (Leave ``boot.py`` as-is, because we still want to go back to HID-mode after we finish editing ``main.py``.) In ``main.py`` put the following code:: import pyb switch = pyb.Switch() accel = pyb.Accel() hid = pyb.USB_HID() while not switch(): hid.send((0, accel.x(), accel.y(), 0)) pyb.delay(20) Save your file, eject/unmount your pyboard drive, and reset it using the RST switch. It should now act as a mouse, and the angle of the board will move the mouse around. Try it out, and see if you can make the mouse stand still! Press the USR switch to stop the mouse motion. You'll note that the y-axis is inverted. That's easy to fix: just put a minus sign in front of the y-coordinate in the ``hid.send()`` line above. Restoring your pyboard to normal -------------------------------- If you leave your pyboard as-is, it'll behave as a mouse everytime you plug it in. You probably want to change it back to normal. To do this you need to first enter safe mode (see above), and then edit the ``boot.py`` file. In the ``boot.py`` file, comment out (put a # in front of) the line with the ``VCP+HID`` setting, so it looks like:: #pyb.usb_mode('VCP+HID') # act as a serial device and a mouse Save your file, eject/unmount the drive, and reset the pyboard. It is now back to normal operating mode. micropython-1.12/docs/readthedocs/000077500000000000000000000000001357706137100172375ustar00rootroot00000000000000micropython-1.12/docs/readthedocs/settings/000077500000000000000000000000001357706137100210775ustar00rootroot00000000000000micropython-1.12/docs/readthedocs/settings/local_settings.py000066400000000000000000000005001357706137100244560ustar00rootroot00000000000000import os # Directory that the project lives in, aka ../.. SITE_ROOT = '/'.join(os.path.dirname(__file__).split('/')[0:-2]) TEMPLATE_DIRS = ( "%s/templates/" % SITE_ROOT, # Your custom template directory, before the RTD one to override it. "%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir ) micropython-1.12/docs/reference/000077500000000000000000000000001357706137100167105ustar00rootroot00000000000000micropython-1.12/docs/reference/asm_thumb2_arith.rst000066400000000000000000000026061357706137100226760ustar00rootroot00000000000000Arithmetic instructions ======================= Document conventions -------------------- Notation: ``Rd, Rm, Rn`` denote ARM registers R0-R7. ``immN`` denotes an immediate value having a width of N bits e.g. ``imm8``, ``imm3``. ``carry`` denotes the carry condition flag, ``not(carry)`` denotes its complement. In the case of instructions with more than one register argument, it is permissible for some to be identical. For example the following will add the contents of R0 to itself, placing the result in R0: * add(r0, r0, r0) Arithmetic instructions affect the condition flags except where stated. Addition -------- * add(Rdn, imm8) ``Rdn = Rdn + imm8`` * add(Rd, Rn, imm3) ``Rd = Rn + imm3`` * add(Rd, Rn, Rm) ``Rd = Rn +Rm`` * adc(Rd, Rn) ``Rd = Rd + Rn + carry`` Subtraction ----------- * sub(Rdn, imm8) ``Rdn = Rdn - imm8`` * sub(Rd, Rn, imm3) ``Rd = Rn - imm3`` * sub(Rd, Rn, Rm) ``Rd = Rn - Rm`` * sbc(Rd, Rn) ``Rd = Rd - Rn - not(carry)`` Negation -------- * neg(Rd, Rn) ``Rd = -Rn`` Multiplication and division --------------------------- * mul(Rd, Rn) ``Rd = Rd * Rn`` This produces a 32 bit result with overflow lost. The result may be treated as signed or unsigned according to the definition of the operands. * sdiv(Rd, Rn, Rm) ``Rd = Rn / Rm`` * udiv(Rd, Rn, Rm) ``Rd = Rn / Rm`` These functions perform signed and unsigned division respectively. Condition flags are not affected. micropython-1.12/docs/reference/asm_thumb2_compare.rst000066400000000000000000000055211357706137100232140ustar00rootroot00000000000000Comparison instructions ======================= These perform an arithmetic or logical instruction on two arguments, discarding the result but setting the condition flags. Typically these are used to test data values without changing them prior to executing a conditional branch. Document conventions -------------------- Notation: ``Rd, Rm, Rn`` denote ARM registers R0-R7. ``imm8`` denotes an immediate value having a width of 8 bits. The Application Program Status Register (APSR) ---------------------------------------------- This contains four bits which are tested by the conditional branch instructions. Typically a conditional branch will test multiple bits, for example ``bge(LABEL)``. The meaning of condition codes can depend on whether the operands of an arithmetic instruction are viewed as signed or unsigned integers. Thus ``bhi(LABEL)`` assumes unsigned numbers were processed while ``bgt(LABEL)`` assumes signed operands. APSR Bits --------- * Z (zero) This is set if the result of an operation is zero or the operands of a comparison are equal. * N (negative) Set if the result is negative. * C (carry) An addition sets the carry flag when the result overflows out of the MSB, for example adding 0x80000000 and 0x80000000. By the nature of two's complement arithmetic this behaviour is reversed on subtraction, with a borrow indicated by the carry bit being clear. Thus 0x10 - 0x01 is executed as 0x10 + 0xffffffff which will set the carry bit. * V (overflow) The overflow flag is set if the result, viewed as a two's compliment number, has the "wrong" sign in relation to the operands. For example adding 1 to 0x7fffffff will set the overflow bit because the result (0x8000000), viewed as a two's complement integer, is negative. Note that in this instance the carry bit is not set. Comparison instructions ----------------------- These set the APSR (Application Program Status Register) N (negative), Z (zero), C (carry) and V (overflow) flags. * cmp(Rn, imm8) ``Rn - imm8`` * cmp(Rn, Rm) ``Rn - Rm`` * cmn(Rn, Rm) ``Rn + Rm`` * tst(Rn, Rm) ``Rn & Rm`` Conditional execution --------------------- The ``it`` and ``ite`` instructions provide a means of conditionally executing from one to four subsequent instructions without the need for a label. * it() If then Execute the next instruction if is true: :: cmp(r0, r1) it(eq) mov(r0, 100) # runs if r0 == r1 # execution continues here * ite() If then else If is true, execute the next instruction, otherwise execute the subsequent one. Thus: :: cmp(r0, r1) ite(eq) mov(r0, 100) # runs if r0 == r1 mov(r0, 200) # runs if r0 != r1 # execution continues here This may be extended to control the execution of upto four subsequent instructions: it[x[y[z]]] where x,y,z=t/e; e.g. itt, itee, itete, ittte, itttt, iteee, etc. micropython-1.12/docs/reference/asm_thumb2_directives.rst000066400000000000000000000022411357706137100237230ustar00rootroot00000000000000Assembler Directives ==================== Labels ------ * label(INNER1) This defines a label for use in a branch instruction. Thus elsewhere in the code a ``b(INNER1)`` will cause execution to continue with the instruction after the label directive. Defining inline data -------------------- The following assembler directives facilitate embedding data in an assembler code block. * data(size, d0, d1 .. dn) The data directive creates n array of data values in memory. The first argument specifies the size in bytes of the subsequent arguments. Hence the first statement below will cause the assembler to put three bytes (with values 2, 3 and 4) into consecutive memory locations while the second will cause it to emit two four byte words. :: data(1, 2, 3, 4) data(4, 2, 100000) Data values longer than a single byte are stored in memory in little-endian format. * align(nBytes) Align the following instruction to an nBytes value. ARM Thumb-2 instructions must be two byte aligned, hence it's advisable to issue ``align(2)`` after ``data`` directives and prior to any subsequent code. This ensures that the code will run irrespective of the size of the data array. micropython-1.12/docs/reference/asm_thumb2_float.rst000066400000000000000000000051661357706137100227000ustar00rootroot00000000000000Floating Point instructions ============================== These instructions support the use of the ARM floating point coprocessor (on platforms such as the Pyboard which are equipped with one). The FPU has 32 registers known as ``s0-s31`` each of which can hold a single precision float. Data can be passed between the FPU registers and the ARM core registers with the ``vmov`` instruction. Note that MicroPython doesn't support passing floats to assembler functions, nor can you put a float into ``r0`` and expect a reasonable result. There are two ways to overcome this. The first is to use arrays, and the second is to pass and/or return integers and convert to and from floats in code. Document conventions -------------------- Notation: ``Sd, Sm, Sn`` denote FPU registers, ``Rd, Rm, Rn`` denote ARM core registers. The latter can be any ARM core register although registers ``R13-R15`` are unlikely to be appropriate in this context. Arithmetic ---------- * vadd(Sd, Sn, Sm) ``Sd = Sn + Sm`` * vsub(Sd, Sn, Sm) ``Sd = Sn - Sm`` * vneg(Sd, Sm) ``Sd = -Sm`` * vmul(Sd, Sn, Sm) ``Sd = Sn * Sm`` * vdiv(Sd, Sn, Sm) ``Sd = Sn / Sm`` * vsqrt(Sd, Sm) ``Sd = sqrt(Sm)`` Registers may be identical: ``vmul(S0, S0, S0)`` will execute ``S0 = S0*S0`` Move between ARM core and FPU registers --------------------------------------- * vmov(Sd, Rm) ``Sd = Rm`` * vmov(Rd, Sm) ``Rd = Sm`` The FPU has a register known as FPSCR, similar to the ARM core's APSR, which stores condition codes plus other data. The following instructions provide access to this. * vmrs(APSR\_nzcv, FPSCR) Move the floating-point N, Z, C, and V flags to the APSR N, Z, C, and V flags. This is done after an instruction such as an FPU comparison to enable the condition codes to be tested by the assembler code. The following is a more general form of the instruction. * vmrs(Rd, FPSCR) ``Rd = FPSCR`` Move between FPU register and memory ------------------------------------ * vldr(Sd, [Rn, offset]) ``Sd = [Rn + offset]`` * vstr(Sd, [Rn, offset]) ``[Rn + offset] = Sd`` Where ``[Rn + offset]`` denotes the memory address obtained by adding Rn to the offset. This is specified in bytes. Since each float value occupies a 32 bit word, when accessing arrays of floats the offset must always be a multiple of four bytes. Data Comparison --------------- * vcmp(Sd, Sm) Compare the values in Sd and Sm and set the FPU N, Z, C, and V flags. This would normally be followed by ``vmrs(APSR_nzcv, FPSCR)`` to enable the results to be tested. Convert between integer and float --------------------------------- * vcvt\_f32\_s32(Sd, Sm) ``Sd = float(Sm)`` * vcvt\_s32\_f32(Sd, Sm) ``Sd = int(Sm)`` micropython-1.12/docs/reference/asm_thumb2_hints_tips.rst000066400000000000000000000172641357706137100237610ustar00rootroot00000000000000Hints and tips ============== The following are some examples of the use of the inline assembler and some information on how to work around its limitations. In this document the term "assembler function" refers to a function declared in Python with the ``@micropython.asm_thumb`` decorator, whereas "subroutine" refers to assembler code called from within an assembler function. Code branches and subroutines ----------------------------- It is important to appreciate that labels are local to an assembler function. There is currently no way for a subroutine defined in one function to be called from another. To call a subroutine the instruction ``bl(LABEL)`` is issued. This transfers control to the instruction following the ``label(LABEL)`` directive and stores the return address in the link register (``lr`` or ``r14``). To return the instruction ``bx(lr)`` is issued which causes execution to continue with the instruction following the subroutine call. This mechanism implies that, if a subroutine is to call another, it must save the link register prior to the call and restore it before terminating. The following rather contrived example illustrates a function call. Note that it's necessary at the start to branch around all subroutine calls: subroutines end execution with ``bx(lr)`` while the outer function simply "drops off the end" in the style of Python functions. :: @micropython.asm_thumb def quad(r0): b(START) label(DOUBLE) add(r0, r0, r0) bx(lr) label(START) bl(DOUBLE) bl(DOUBLE) print(quad(10)) The following code example demonstrates a nested (recursive) call: the classic Fibonacci sequence. Here, prior to a recursive call, the link register is saved along with other registers which the program logic requires to be preserved. :: @micropython.asm_thumb def fib(r0): b(START) label(DOFIB) push({r1, r2, lr}) cmp(r0, 1) ble(FIBDONE) sub(r0, 1) mov(r2, r0) # r2 = n -1 bl(DOFIB) mov(r1, r0) # r1 = fib(n -1) sub(r0, r2, 1) bl(DOFIB) # r0 = fib(n -2) add(r0, r0, r1) label(FIBDONE) pop({r1, r2, lr}) bx(lr) label(START) bl(DOFIB) for n in range(10): print(fib(n)) Argument passing and return --------------------------- The tutorial details the fact that assembler functions can support from zero to three arguments, which must (if used) be named ``r0``, ``r1`` and ``r2``. When the code executes the registers will be initialised to those values. The data types which can be passed in this way are integers and memory addresses. With current firmware all possible 32 bit values may be passed and returned. If the return value may have the most significant bit set a Python type hint should be employed to enable MicroPython to determine whether the value should be interpreted as a signed or unsigned integer: types are ``int`` or ``uint``. :: @micropython.asm_thumb def uadd(r0, r1) -> uint: add(r0, r0, r1) ``hex(uadd(0x40000000,0x40000000))`` will return 0x80000000, demonstrating the passing and return of integers where bits 30 and 31 differ. The limitations on the number of arguments and return values can be overcome by means of the ``array`` module which enables any number of values of any type to be accessed. Multiple arguments ~~~~~~~~~~~~~~~~~~ If a Python array of integers is passed as an argument to an assembler function, the function will receive the address of a contiguous set of integers. Thus multiple arguments can be passed as elements of a single array. Similarly a function can return multiple values by assigning them to array elements. Assembler functions have no means of determining the length of an array: this will need to be passed to the function. This use of arrays can be extended to enable more than three arrays to be used. This is done using indirection: the ``uctypes`` module supports ``addressof()`` which will return the address of an array passed as its argument. Thus you can populate an integer array with the addresses of other arrays: :: from uctypes import addressof @micropython.asm_thumb def getindirect(r0): ldr(r0, [r0, 0]) # Address of array loaded from passed array ldr(r0, [r0, 4]) # Return element 1 of indirect array (24) def testindirect(): a = array.array('i',[23, 24]) b = array.array('i',[0,0]) b[0] = addressof(a) print(getindirect(b)) Non-integer data types ~~~~~~~~~~~~~~~~~~~~~~ These may be handled by means of arrays of the appropriate data type. For example, single precision floating point data may be processed as follows. This code example takes an array of floats and replaces its contents with their squares. :: from array import array @micropython.asm_thumb def square(r0, r1): label(LOOP) vldr(s0, [r0, 0]) vmul(s0, s0, s0) vstr(s0, [r0, 0]) add(r0, 4) sub(r1, 1) bgt(LOOP) a = array('f', (x for x in range(10))) square(a, len(a)) print(a) The uctypes module supports the use of data structures beyond simple arrays. It enables a Python data structure to be mapped onto a bytearray instance which may then be passed to the assembler function. Named constants --------------- Assembler code may be made more readable and maintainable by using named constants rather than littering code with numbers. This may be achieved thus: :: MYDATA = const(33) @micropython.asm_thumb def foo(): mov(r0, MYDATA) The const() construct causes MicroPython to replace the variable name with its value at compile time. If constants are declared in an outer Python scope they can be shared between multiple assembler functions and with Python code. Assembler code as class methods ------------------------------- MicroPython passes the address of the object instance as the first argument to class methods. This is normally of little use to an assembler function. It can be avoided by declaring the function as a static method thus: :: class foo: @staticmethod @micropython.asm_thumb def bar(r0): add(r0, r0, r0) Use of unsupported instructions ------------------------------- These can be coded using the data statement as shown below. While ``push()`` and ``pop()`` are supported the example below illustrates the principle. The necessary machine code may be found in the ARM v7-M Architecture Reference Manual. Note that the first argument of data calls such as :: data(2, 0xe92d, 0x0f00) # push r8,r9,r10,r11 indicates that each subsequent argument is a two byte quantity. Overcoming MicroPython's integer restriction -------------------------------------------- The Pyboard chip includes a CRC generator. Its use presents a problem in MicroPython because the returned values cover the full gamut of 32 bit quantities whereas small integers in MicroPython cannot have differing values in bits 30 and 31. This limitation is overcome with the following code, which uses assembler to put the result into an array and Python code to coerce the result into an arbitrary precision unsigned integer. :: from array import array import stm def enable_crc(): stm.mem32[stm.RCC + stm.RCC_AHB1ENR] |= 0x1000 def reset_crc(): stm.mem32[stm.CRC+stm.CRC_CR] = 1 @micropython.asm_thumb def getval(r0, r1): movwt(r3, stm.CRC + stm.CRC_DR) str(r1, [r3, 0]) ldr(r2, [r3, 0]) str(r2, [r0, 0]) def getcrc(value): a = array('i', [0]) getval(a, value) return a[0] & 0xffffffff # coerce to arbitrary precision enable_crc() reset_crc() for x in range(20): print(hex(getcrc(0))) micropython-1.12/docs/reference/asm_thumb2_index.rst000066400000000000000000000057621357706137100227040ustar00rootroot00000000000000.. _asm_thumb2_index: Inline Assembler for Thumb2 architectures ========================================= This document assumes some familiarity with assembly language programming and should be read after studying the :ref:`tutorial `. For a detailed description of the instruction set consult the Architecture Reference Manual detailed below. The inline assembler supports a subset of the ARM Thumb-2 instruction set described here. The syntax tries to be as close as possible to that defined in the above ARM manual, converted to Python function calls. Instructions operate on 32 bit signed integer data except where stated otherwise. Most supported instructions operate on registers ``R0-R7`` only: where ``R8-R15`` are supported this is stated. Registers ``R8-R12`` must be restored to their initial value before return from a function. Registers ``R13-R15`` constitute the Link Register, Stack Pointer and Program Counter respectively. Document conventions -------------------- Where possible the behaviour of each instruction is described in Python, for example * add(Rd, Rn, Rm) ``Rd = Rn + Rm`` This enables the effect of instructions to be demonstrated in Python. In certain case this is impossible because Python doesn't support concepts such as indirection. The pseudocode employed in such cases is described on the relevant page. Instruction Categories ---------------------- The following sections details the subset of the ARM Thumb-2 instruction set supported by MicroPython. .. toctree:: :maxdepth: 1 :numbered: asm_thumb2_mov.rst asm_thumb2_ldr.rst asm_thumb2_str.rst asm_thumb2_logical_bit.rst asm_thumb2_arith.rst asm_thumb2_compare.rst asm_thumb2_label_branch.rst asm_thumb2_stack.rst asm_thumb2_misc.rst asm_thumb2_float.rst asm_thumb2_directives.rst Usage examples -------------- These sections provide further code examples and hints on the use of the assembler. .. toctree:: :maxdepth: 1 :numbered: asm_thumb2_hints_tips.rst References ---------- - :ref:`Assembler Tutorial ` - `Wiki hints and tips `__ - `uPy Inline Assembler source-code, emitinlinethumb.c `__ - `ARM Thumb2 Instruction Set Quick Reference Card `__ - `RM0090 Reference Manual `__ - ARM v7-M Architecture Reference Manual (Available on the ARM site after a simple registration procedure. Also available on academic sites but beware of out of date versions.) micropython-1.12/docs/reference/asm_thumb2_label_branch.rst000066400000000000000000000060471357706137100241660ustar00rootroot00000000000000Branch instructions =================== These cause execution to jump to a target location usually specified by a label (see the ``label`` assembler directive). Conditional branches and the ``it`` and ``ite`` instructions test the Application Program Status Register (APSR) N (negative), Z (zero), C (carry) and V (overflow) flags to determine whether the branch should be executed. Most of the exposed assembler instructions (including move operations) set the flags but there are explicit comparison instructions to enable values to be tested. Further detail on the meaning of the condition flags is provided in the section describing comparison functions. Document conventions -------------------- Notation: ``Rm`` denotes ARM registers R0-R15. ``LABEL`` denotes a label defined with the ``label()`` assembler directive. ```` indicates one of the following condition specifiers: * eq Equal to (result was zero) * ne Not equal * cs Carry set * cc Carry clear * mi Minus (negative) * pl Plus (positive) * vs Overflow set * vc Overflow clear * hi > (unsigned comparison) * ls <= (unsigned comparison) * ge >= (signed comparison) * lt < (signed comparison) * gt > (signed comparison) * le <= (signed comparison) Branch to label --------------- * b(LABEL) Unconditional branch * beq(LABEL) branch if equal * bne(LABEL) branch if not equal * bge(LABEL) branch if greater than or equal * bgt(LABEL) branch if greater than * blt(LABEL) branch if less than (<) (signed) * ble(LABEL) branch if less than or equal to (<=) (signed) * bcs(LABEL) branch if carry flag is set * bcc(LABEL) branch if carry flag is clear * bmi(LABEL) branch if negative * bpl(LABEL) branch if positive * bvs(LABEL) branch if overflow flag set * bvc(LABEL) branch if overflow flag is clear * bhi(LABEL) branch if higher (unsigned) * bls(LABEL) branch if lower or equal (unsigned) Long branches ------------- The code produced by the branch instructions listed above uses a fixed bit width to specify the branch destination, which is PC relative. Consequently in long programs where the branch instruction is remote from its destination the assembler will produce a "branch not in range" error. This can be overcome with the "wide" variants such as * beq\_w(LABEL) long branch if equal Wide branches use 4 bytes to encode the instruction (compared with 2 bytes for standard branch instructions). Subroutines (functions) ----------------------- When entering a subroutine the processor stores the return address in register r14, also known as the link register (lr). Return to the instruction after the subroutine call is performed by updating the program counter (r15 or pc) from the link register, This process is handled by the following instructions. * bl(LABEL) Transfer execution to the instruction after ``LABEL`` storing the return address in the link register (r14). * bx(Rm) Branch to address specified by Rm. Typically ``bx(lr)`` is issued to return from a subroutine. For nested subroutines the link register of outer scopes must be saved (usually on the stack) before performing inner subroutine calls. micropython-1.12/docs/reference/asm_thumb2_ldr.rst000066400000000000000000000020501357706137100223410ustar00rootroot00000000000000Load register from memory ========================= Document conventions -------------------- Notation: ``Rt, Rn`` denote ARM registers R0-R7 except where stated. ``immN`` represents an immediate value having a width of N bits hence ``imm5`` is constrained to the range 0-31. ``[Rn + immN]`` is the contents of the memory address obtained by adding Rn and the offset ``immN``. Offsets are measured in bytes. These instructions affect the condition flags. Register Load ------------- * ldr(Rt, [Rn, imm7]) ``Rt = [Rn + imm7]`` Load a 32 bit word * ldrb(Rt, [Rn, imm5]) ``Rt = [Rn + imm5]`` Load a byte * ldrh(Rt, [Rn, imm6]) ``Rt = [Rn + imm6]`` Load a 16 bit half word Where a byte or half word is loaded, it is zero-extended to 32 bits. The specified immediate offsets are measured in bytes. Hence in the case of ``ldr`` the 7 bit value enables 32 bit word aligned values to be accessed with a maximum offset of 31 words. In the case of ``ldrh`` the 6 bit value enables 16 bit half-word aligned values to be accessed with a maximum offset of 31 half-words. micropython-1.12/docs/reference/asm_thumb2_logical_bit.rst000066400000000000000000000035761357706137100240460ustar00rootroot00000000000000Logical & Bitwise instructions ============================== Document conventions -------------------- Notation: ``Rd, Rn`` denote ARM registers R0-R7 except in the case of the special instructions where R0-R15 may be used. ``Rn`` denotes an ARM register whose contents must lie in range ``a <= contents <= b``. In the case of instructions with two register arguments, it is permissible for them to be identical. For example the following will zero R0 (Python ``R0 ^= R0``) regardless of its initial contents. * eor(r0, r0) These instructions affect the condition flags except where stated. Logical instructions -------------------- * and\_(Rd, Rn) ``Rd &= Rn`` * orr(Rd, Rn) ``Rd |= Rn`` * eor(Rd, Rn) ``Rd ^= Rn`` * mvn(Rd, Rn) ``Rd = Rn ^ 0xffffffff`` i.e. Rd = 1's complement of Rn * bic(Rd, Rn) ``Rd &= ~Rn`` bit clear Rd using mask in Rn Note the use of "and\_" instead of "and", because "and" is a reserved keyword in Python. Shift and rotation instructions ------------------------------- * lsl(Rd, Rn<0-31>) ``Rd <<= Rn`` * lsr(Rd, Rn<1-32>) ``Rd = (Rd & 0xffffffff) >> Rn`` Logical shift right * asr(Rd, Rn<1-32>) ``Rd >>= Rn`` arithmetic shift right * ror(Rd, Rn<1-31>) ``Rd = rotate_right(Rd, Rn)`` Rd is rotated right Rn bits. A rotation by (for example) three bits works as follows. If Rd initially contains bits ``b31 b30..b0`` after rotation it will contain ``b2 b1 b0 b31 b30..b3`` Special instructions -------------------- Condition codes are unaffected by these instructions. * clz(Rd, Rn) ``Rd = count_leading_zeros(Rn)`` count_leading_zeros(Rn) returns the number of binary zero bits before the first binary one bit in Rn. * rbit(Rd, Rn) ``Rd = bit_reverse(Rn)`` bit_reverse(Rn) returns the bit-reversed contents of Rn. If Rn contains bits ``b31 b30..b0`` Rd will be set to ``b0 b1 b2..b31`` Trailing zeros may be counted by performing a bit reverse prior to executing clz. micropython-1.12/docs/reference/asm_thumb2_misc.rst000066400000000000000000000014641357706137100225230ustar00rootroot00000000000000Miscellaneous instructions ========================== * nop() ``pass`` no operation. * wfi() Suspend execution in a low power state until an interrupt occurs. * cpsid(flags) set the Priority Mask Register - disable interrupts. * cpsie(flags) clear the Priority Mask Register - enable interrupts. * mrs(Rd, special_reg) ``Rd = special_reg`` copy a special register to a general register. The special register may be IPSR (Interrupt Status Register) or BASEPRI (Base Priority Register). The IPSR provides a means of determining the exception number of an interrupt being processed. It contains zero if no interrupt is being processed. Currently the ``cpsie()`` and ``cpsid()`` functions are partially implemented. They require but ignore the flags argument and serve as a means of enabling and disabling interrupts. micropython-1.12/docs/reference/asm_thumb2_mov.rst000066400000000000000000000015221357706137100223640ustar00rootroot00000000000000Register move instructions ========================== Document conventions -------------------- Notation: ``Rd, Rn`` denote ARM registers R0-R15. ``immN`` denotes an immediate value having a width of N bits. These instructions affect the condition flags. Register moves -------------- Where immediate values are used, these are zero-extended to 32 bits. Thus ``mov(R0, 0xff)`` will set R0 to 255. * mov(Rd, imm8) ``Rd = imm8`` * mov(Rd, Rn) ``Rd = Rn`` * movw(Rd, imm16) ``Rd = imm16`` * movt(Rd, imm16) ``Rd = (Rd & 0xffff) | (imm16 << 16)`` movt writes an immediate value to the top halfword of the destination register. It does not affect the contents of the bottom halfword. * movwt(Rd, imm32) ``Rd = imm32`` movwt is a pseudo-instruction: the MicroPython assembler emits a ``movw`` followed by a ``movt`` to move a 32-bit value into Rd. micropython-1.12/docs/reference/asm_thumb2_stack.rst000066400000000000000000000013251357706137100226710ustar00rootroot00000000000000Stack push and pop ================== Document conventions -------------------- The ``push()`` and ``pop()`` instructions accept as their argument a register set containing a subset, or possibly all, of the general-purpose registers R0-R12 and the link register (lr or R14). As with any Python set the order in which the registers are specified is immaterial. Thus the in the following example the pop() instruction would restore R1, R7 and R8 to their contents prior to the push(): * push({r1, r8, r7}) Save three registers on the stack. * pop({r7, r1, r8}) Restore them Stack operations ---------------- * push({regset}) Push a set of registers onto the stack * pop({regset}) Restore a set of registers from the stack micropython-1.12/docs/reference/asm_thumb2_str.rst000066400000000000000000000017751357706137100224050ustar00rootroot00000000000000Store register to memory ======================== Document conventions -------------------- Notation: ``Rt, Rn`` denote ARM registers R0-R7 except where stated. ``immN`` represents an immediate value having a width of N bits hence ``imm5`` is constrained to the range 0-31. ``[Rn + imm5]`` is the contents of the memory address obtained by adding Rn and the offset ``imm5``. Offsets are measured in bytes. These instructions do not affect the condition flags. Register Store -------------- * str(Rt, [Rn, imm7]) ``[Rn + imm7] = Rt`` Store a 32 bit word * strb(Rt, [Rn, imm5]) ``[Rn + imm5] = Rt`` Store a byte (b0-b7) * strh(Rt, [Rn, imm6]) ``[Rn + imm6] = Rt`` Store a 16 bit half word (b0-b15) The specified immediate offsets are measured in bytes. Hence in the case of ``str`` the 7 bit value enables 32 bit word aligned values to be accessed with a maximum offset of 31 words. In the case of ``strh`` the 6 bit value enables 16 bit half-word aligned values to be accessed with a maximum offset of 31 half-words. micropython-1.12/docs/reference/constrained.rst000066400000000000000000000432151357706137100217600ustar00rootroot00000000000000.. _constrained: MicroPython on Microcontrollers =============================== MicroPython is designed to be capable of running on microcontrollers. These have hardware limitations which may be unfamiliar to programmers more familiar with conventional computers. In particular the amount of RAM and nonvolatile "disk" (flash memory) storage is limited. This tutorial offers ways to make the most of the limited resources. Because MicroPython runs on controllers based on a variety of architectures, the methods presented are generic: in some cases it will be necessary to obtain detailed information from platform specific documentation. Flash Memory ------------ On the Pyboard the simple way to address the limited capacity is to fit a micro SD card. In some cases this is impractical, either because the device does not have an SD card slot or for reasons of cost or power consumption; hence the on-chip flash must be used. The firmware including the MicroPython subsystem is stored in the onboard flash. The remaining capacity is available for use. For reasons connected with the physical architecture of the flash memory part of this capacity may be inaccessible as a filesystem. In such cases this space may be employed by incorporating user modules into a firmware build which is then flashed to the device. There are two ways to achieve this: frozen modules and frozen bytecode. Frozen modules store the Python source with the firmware. Frozen bytecode uses the cross compiler to convert the source to bytecode which is then stored with the firmware. In either case the module may be accessed with an import statement: .. code:: import mymodule The procedure for producing frozen modules and bytecode is platform dependent; instructions for building the firmware can be found in the README files in the relevant part of the source tree. In general terms the steps are as follows: * Clone the MicroPython `repository `_. * Acquire the (platform specific) toolchain to build the firmware. * Build the cross compiler. * Place the modules to be frozen in a specified directory (dependent on whether the module is to be frozen as source or as bytecode). * Build the firmware. A specific command may be required to build frozen code of either type - see the platform documentation. * Flash the firmware to the device. RAM --- When reducing RAM usage there are two phases to consider: compilation and execution. In addition to memory consumption, there is also an issue known as heap fragmentation. In general terms it is best to minimise the repeated creation and destruction of objects. The reason for this is covered in the section covering the `heap`_. Compilation Phase ~~~~~~~~~~~~~~~~~ When a module is imported, MicroPython compiles the code to bytecode which is then executed by the MicroPython virtual machine (VM). The bytecode is stored in RAM. The compiler itself requires RAM, but this becomes available for use when the compilation has completed. If a number of modules have already been imported the situation can arise where there is insufficient RAM to run the compiler. In this case the import statement will produce a memory exception. If a module instantiates global objects on import it will consume RAM at the time of import, which is then unavailable for the compiler to use on subsequent imports. In general it is best to avoid code which runs on import; a better approach is to have initialisation code which is run by the application after all modules have been imported. This maximises the RAM available to the compiler. If RAM is still insufficient to compile all modules one solution is to precompile modules. MicroPython has a cross compiler capable of compiling Python modules to bytecode (see the README in the mpy-cross directory). The resulting bytecode file has a .mpy extension; it may be copied to the filesystem and imported in the usual way. Alternatively some or all modules may be implemented as frozen bytecode: on most platforms this saves even more RAM as the bytecode is run directly from flash rather than being stored in RAM. Execution Phase ~~~~~~~~~~~~~~~ There are a number of coding techniques for reducing RAM usage. **Constants** MicroPython provides a ``const`` keyword which may be used as follows: .. code:: from micropython import const ROWS = const(33) _COLS = const(0x10) a = ROWS b = _COLS In both instances where the constant is assigned to a variable the compiler will avoid coding a lookup to the name of the constant by substituting its literal value. This saves bytecode and hence RAM. However the ``ROWS`` value will occupy at least two machine words, one each for the key and value in the globals dictionary. The presence in the dictionary is necessary because another module might import or use it. This RAM can be saved by prepending the name with an underscore as in ``_COLS``: this symbol is not visible outside the module so will not occupy RAM. The argument to ``const()`` may be anything which, at compile time, evaluates to an integer e.g. ``0x100`` or ``1 << 8``. It can even include other const symbols that have already been defined, e.g. ``1 << BIT``. **Constant data structures** Where there is a substantial volume of constant data and the platform supports execution from Flash, RAM may be saved as follows. The data should be located in Python modules and frozen as bytecode. The data must be defined as `bytes` objects. The compiler 'knows' that `bytes` objects are immutable and ensures that the objects remain in flash memory rather than being copied to RAM. The `ustruct` module can assist in converting between `bytes` types and other Python built-in types. When considering the implications of frozen bytecode, note that in Python strings, floats, bytes, integers and complex numbers are immutable. Accordingly these will be frozen into flash. Thus, in the line .. code:: mystring = "The quick brown fox" the actual string "The quick brown fox" will reside in flash. At runtime a reference to the string is assigned to the *variable* ``mystring``. The reference occupies a single machine word. In principle a long integer could be used to store constant data: .. code:: bar = 0xDEADBEEF0000DEADBEEF As in the string example, at runtime a reference to the arbitrarily large integer is assigned to the variable ``bar``. That reference occupies a single machine word. It might be expected that tuples of integers could be employed for the purpose of storing constant data with minimal RAM use. With the current compiler this is ineffective (the code works, but RAM is not saved). .. code:: foo = (1, 2, 3, 4, 5, 6, 100000) At runtime the tuple will be located in RAM. This may be subject to future improvement. **Needless object creation** There are a number of situations where objects may unwittingly be created and destroyed. This can reduce the usability of RAM through fragmentation. The following sections discuss instances of this. **String concatenation** Consider the following code fragments which aim to produce constant strings: .. code:: var = "foo" + "bar" var1 = "foo" "bar" var2 = """\ foo\ bar""" Each produces the same outcome, however the first needlessly creates two string objects at runtime, allocates more RAM for concatenation before producing the third. The others perform the concatenation at compile time which is more efficient, reducing fragmentation. Where strings must be dynamically created before being fed to a stream such as a file it will save RAM if this is done in a piecemeal fashion. Rather than creating a large string object, create a substring and feed it to the stream before dealing with the next. The best way to create dynamic strings is by means of the string ``format()`` method: .. code:: var = "Temperature {:5.2f} Pressure {:06d}\n".format(temp, press) **Buffers** When accessing devices such as instances of UART, I2C and SPI interfaces, using pre-allocated buffers avoids the creation of needless objects. Consider these two loops: .. code:: while True: var = spi.read(100) # process data buf = bytearray(100) while True: spi.readinto(buf) # process data in buf The first creates a buffer on each pass whereas the second re-uses a pre-allocated buffer; this is both faster and more efficient in terms of memory fragmentation. **Bytes are smaller than ints** On most platforms an integer consumes four bytes. Consider the two calls to the function ``foo()``: .. code:: def foo(bar): for x in bar: print(x) foo((1, 2, 0xff)) foo(b'\1\2\xff') In the first call a tuple of integers is created in RAM. The second efficiently creates a `bytes` object consuming the minimum amount of RAM. If the module were frozen as bytecode, the `bytes` object would reside in flash. **Strings Versus Bytes** Python3 introduced Unicode support. This introduced a distinction between a string and an array of bytes. MicroPython ensures that Unicode strings take no additional space so long as all characters in the string are ASCII (i.e. have a value < 126). If values in the full 8-bit range are required `bytes` and `bytearray` objects can be used to ensure that no additional space will be required. Note that most string methods (e.g. :meth:`str.strip()`) apply also to `bytes` instances so the process of eliminating Unicode can be painless. .. code:: s = 'the quick brown fox' # A string instance b = b'the quick brown fox' # A bytes instance Where it is necessary to convert between strings and bytes the :meth:`str.encode` and the :meth:`bytes.decode` methods can be used. Note that both strings and bytes are immutable. Any operation which takes as input such an object and produces another implies at least one RAM allocation to produce the result. In the second line below a new bytes object is allocated. This would also occur if ``foo`` were a string. .. code:: foo = b' empty whitespace' foo = foo.lstrip() **Runtime compiler execution** The Python funcitons `eval` and `exec` invoke the compiler at runtime, which requires significant amounts of RAM. Note that the ``pickle`` library from `micropython-lib` employs `exec`. It may be more RAM efficient to use the `ujson` library for object serialisation. **Storing strings in flash** Python strings are immutable hence have the potential to be stored in read only memory. The compiler can place in flash strings defined in Python code. As with frozen modules it is necessary to have a copy of the source tree on the PC and the toolchain to build the firmware. The procedure will work even if the modules have not been fully debugged, so long as they can be imported and run. After importing the modules, execute: .. code:: micropython.qstr_info(1) Then copy and paste all the Q(xxx) lines into a text editor. Check for and remove lines which are obviously invalid. Open the file qstrdefsport.h which will be found in ports/stm32 (or the equivalent directory for the architecture in use). Copy and paste the corrected lines at the end of the file. Save the file, rebuild and flash the firmware. The outcome can be checked by importing the modules and again issuing: .. code:: micropython.qstr_info(1) The Q(xxx) lines should be gone. .. _heap: The Heap -------- When a running program instantiates an object the necessary RAM is allocated from a fixed size pool known as the heap. When the object goes out of scope (in other words becomes inaccessible to code) the redundant object is known as "garbage". A process known as "garbage collection" (GC) reclaims that memory, returning it to the free heap. This process runs automatically, however it can be invoked directly by issuing `gc.collect()`. The discourse on this is somewhat involved. For a 'quick fix' issue the following periodically: .. code:: gc.collect() gc.threshold(gc.mem_free() // 4 + gc.mem_alloc()) Fragmentation ~~~~~~~~~~~~~ Say a program creates an object ``foo``, then an object ``bar``. Subsequently ``foo`` goes out of scope but ``bar`` remains. The RAM used by ``foo`` will be reclaimed by GC. However if ``bar`` was allocated to a higher address, the RAM reclaimed from ``foo`` will only be of use for objects no bigger than ``foo``. In a complex or long running program the heap can become fragmented: despite there being a substantial amount of RAM available, there is insufficient contiguous space to allocate a particular object, and the program fails with a memory error. The techniques outlined above aim to minimise this. Where large permanent buffers or other objects are required it is best to instantiate these early in the process of program execution before fragmentation can occur. Further improvements may be made by monitoring the state of the heap and by controlling GC; these are outlined below. Reporting ~~~~~~~~~ A number of library functions are available to report on memory allocation and to control GC. These are to be found in the `gc` and `micropython` modules. The following example may be pasted at the REPL (``ctrl e`` to enter paste mode, ``ctrl d`` to run it). .. code:: import gc import micropython gc.collect() micropython.mem_info() print('-----------------------------') print('Initial free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) def func(): a = bytearray(10000) gc.collect() print('Func definition: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) func() print('Func run free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) gc.collect() print('Garbage collect free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) print('-----------------------------') micropython.mem_info(1) Methods employed above: * `gc.collect()` Force a garbage collection. See footnote. * `micropython.mem_info()` Print a summary of RAM utilisation. * `gc.mem_free()` Return the free heap size in bytes. * `gc.mem_alloc()` Return the number of bytes currently allocated. * ``micropython.mem_info(1)`` Print a table of heap utilisation (detailed below). The numbers produced are dependent on the platform, but it can be seen that declaring the function uses a small amount of RAM in the form of bytecode emitted by the compiler (the RAM used by the compiler has been reclaimed). Running the function uses over 10KiB, but on return ``a`` is garbage because it is out of scope and cannot be referenced. The final `gc.collect()` recovers that memory. The final output produced by ``micropython.mem_info(1)`` will vary in detail but may be interpreted as follows: ====== ================= Symbol Meaning ====== ================= . free block h head block = tail block m marked head block T tuple L list D dict F float B byte code M module ====== ================= Each letter represents a single block of memory, a block being 16 bytes. So each line of the heap dump represents 0x400 bytes or 1KiB of RAM. Control of Garbage Collection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A GC can be demanded at any time by issuing `gc.collect()`. It is advantageous to do this at intervals, firstly to pre-empt fragmentation and secondly for performance. A GC can take several milliseconds but is quicker when there is little work to do (about 1ms on the Pyboard). An explicit call can minimise that delay while ensuring it occurs at points in the program when it is acceptable. Automatic GC is provoked under the following circumstances. When an attempt at allocation fails, a GC is performed and the allocation re-tried. Only if this fails is an exception raised. Secondly an automatic GC will be triggered if the amount of free RAM falls below a threshold. This threshold can be adapted as execution progresses: .. code:: gc.collect() gc.threshold(gc.mem_free() // 4 + gc.mem_alloc()) This will provoke a GC when more than 25% of the currently free heap becomes occupied. In general modules should instantiate data objects at runtime using constructors or other initialisation functions. The reason is that if this occurs on initialisation the compiler may be starved of RAM when subsequent modules are imported. If modules do instantiate data on import then `gc.collect()` issued after the import will ameliorate the problem. String Operations ----------------- MicroPython handles strings in an efficient manner and understanding this can help in designing applications to run on microcontrollers. When a module is compiled, strings which occur multiple times are stored once only, a process known as string interning. In MicroPython an interned string is known as a ``qstr``. In a module imported normally that single instance will be located in RAM, but as described above, in modules frozen as bytecode it will be located in flash. String comparisons are also performed efficiently using hashing rather than character by character. The penalty for using strings rather than integers may hence be small both in terms of performance and RAM usage - a fact which may come as a surprise to C programmers. Postscript ---------- MicroPython passes, returns and (by default) copies objects by reference. A reference occupies a single machine word so these processes are efficient in RAM usage and speed. Where variables are required whose size is neither a byte nor a machine word there are standard libraries which can assist in storing these efficiently and in performing conversions. See the `array`, `ustruct` and `uctypes` modules. Footnote: gc.collect() return value ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ On Unix and Windows platforms the `gc.collect()` method returns an integer which signifies the number of distinct memory regions that were reclaimed in the collection (more precisely, the number of heads that were turned into frees). For efficiency reasons bare metal ports do not return this value. micropython-1.12/docs/reference/filesystem.rst000066400000000000000000000230341357706137100216300ustar00rootroot00000000000000.. _filesystem: Working with filesystems ======================== .. contents:: This tutorial describes how MicroPython provides an on-device filesystem, allowing standard Python file I/O methods to be used with persistent storage. MicroPython automatically creates a default configuration and auto-detects the primary filesystem, so this tutorial will be mostly useful if you want to modify the partitioning, filesystem type, or use custom block devices. The filesystem is typically backed by internal flash memory on the device, but can also use external flash, RAM, or a custom block device. On some ports (e.g. STM32), the filesystem may also be available over USB MSC to a host PC. :ref:`pyboard_py` also provides a way for the host PC to access to the filesystem on all ports. Note: This is mainly for use on bare-metal ports like STM32 and ESP32. On ports with an operating system (e.g. the Unix port) the filesystem is provided by the host OS. VFS --- MicroPython implements a Unix-like Virtual File System (VFS) layer. All mounted filesystems are combined into a single virtual filesystem, starting at the root ``/``. Filesystems are mounted into directories in this structure, and at startup the working directory is changed to where the primary filesystem is mounted. On STM32 / Pyboard, the internal flash is mounted at ``/flash``, and optionally the SDCard at ``/sd``. On ESP8266/ESP32, the primary filesystem is mounted at ``/``. Block devices ------------- A block device is an instance of a class that implements the :class:`uos.AbstractBlockDev` protocol. Built-in block devices ~~~~~~~~~~~~~~~~~~~~~~ Ports provide built-in block devices to access their primary flash. On power-on, MicroPython will attempt to detect the filesystem on the default flash and configure and mount it automatically. If no filesystem is found, MicroPython will attempt to create a FAT filesystem spanning the entire flash. Ports can also provide a mechanism to "factory reset" the primary flash, usually by some combination of button presses at power on. STM32 / Pyboard ............... The :ref:`pyb.Flash ` class provides access to the internal flash. On some boards which have larger external flash (e.g. Pyboard D), it will use that instead. The ``start`` kwarg should always be specified, i.e. ``pyb.Flash(start=0)``. Note: For backwards compatibility, when constructed with no arguments (i.e. ``pyb.Flash()``), it only implements the simple block interface and reflects the virtual device presented to USB MSC (i.e. it includes a virtual partition table at the start). ESP8266 ....... The internal flash is exposed as a block device object which is created in the ``flashbdev`` module on start up. This object is by default added as a global variable so it can usually be accessed simply as ``bdev``. This implements the extended interface. ESP32 ..... The :class:`esp32.Partition` class implements a block device for partitions defined for the board. Like ESP8266, there is a global variable ``bdev`` which points to the default partition. This implements the extended interface. Custom block devices ~~~~~~~~~~~~~~~~~~~~ The following class implements a simple block device that stores its data in RAM using a ``bytearray``:: class RAMBlockDev: def __init__(self, block_size, num_blocks): self.block_size = block_size self.data = bytearray(block_size * num_blocks) def readblocks(self, block_num, buf): for i in range(len(buf)): buf[i] = self.data[block_num * self.block_size + i] def writeblocks(self, block_num, buf): for i in range(len(buf)): self.data[block_num * self.block_size + i] = buf[i] def ioctl(self, op, arg): if op == 4: # get number of blocks return len(self.data) // self.block_size if op == 5: # get block size return self.block_size It can be used as follows:: import os bdev = RAMBlockDev(512, 50) os.VfsFat.mkfs(bdev) os.mount(bdev, '/ramdisk') An example of a block device that supports both the simple and extended interface (i.e. both signatures and behaviours of the :meth:`uos.AbstractBlockDev.readblocks` and :meth:`uos.AbstractBlockDev.writeblocks` methods) is:: class RAMBlockDev: def __init__(self, block_size, num_blocks): self.block_size = block_size self.data = bytearray(block_size * num_blocks) def readblocks(self, block_num, buf, offset=0): addr = block_num * self.block_size + offset for i in range(len(buf)): buf[i] = self.data[addr + i] def writeblocks(self, block_num, buf, offset=None): if offset is None: # do erase, then write for i in range(len(buf) // self.block_size): self.ioctl(6, block_num + i) offset = 0 addr = block_num * self.block_size + offset for i in range(len(buf)): self.data[addr + i] = buf[i] def ioctl(self, op, arg): if op == 4: # block count return len(self.data) // self.block_size if op == 5: # block size return self.block_size if op == 6: # block erase return 0 As it supports the extended interface, it can be used with :class:`littlefs `:: import os bdev = RAMBlockDev(512, 50) os.VfsLfs2.mkfs(bdev) os.mount(bdev, '/ramdisk') Once mounted, the filesystem (regardless of its type) can be used as it normally would be used from Python code, for example:: with open('/ramdisk/hello.txt', 'w') as f: f.write('Hello world') print(open('/ramdisk/hello.txt').read()) Filesystems ----------- MicroPython ports can provide implementations of :class:`FAT `, :class:`littlefs v1 ` and :class:`littlefs v2 `. The following table shows which filesystems are included in the firmware by default for given port/board combinations, however they can be optionally enabled in a custom firmware build. ==================== ===== =========== =========== Board FAT littlefs v1 littlefs v2 ==================== ===== =========== =========== pyboard 1.0, 1.1, D Yes No Yes Other STM32 Yes No No ESP8266 Yes No No ESP32 Yes No Yes ==================== ===== =========== =========== FAT ~~~ The main advantage of the FAT filesystem is that it can be accessed over USB MSC on supported boards (e.g. STM32) without any additional drivers required on the host PC. However, FAT is not tolerant to power failure during writes and this can lead to filesystem corruption. For applications that do not require USB MSC, it is recommended to use littlefs instead. To format the entire flash using FAT:: # ESP8266 and ESP32 import os os.umount('/') os.VfsFat.mkfs(bdev) os.mount(bdev, '/') # STM32 import os, pyb os.umount('/flash') os.VfsFat.mkfs(pyb.Flash(start=0)) os.mount(pyb.Flash(start=0), '/flash') os.chdir('/flash') Littlefs ~~~~~~~~ Littlefs_ is a filesystem designed for flash-based devices, and is much more resistant to filesystem corruption. .. note:: There are reports of littlefs v1 and v2 failing in certain situations, for details see `littlefs issue 347`_ and `littlefs issue 295`_. Note: It can be still be accessed over USB MSC using the `littlefs FUSE driver`_. Note that you must use the ``-b=4096`` option to override the block size. .. _littlefs FUSE driver: https://github.com/ARMmbed/littlefs-fuse/tree/master/littlefs .. _Littlefs: https://github.com/ARMmbed/littlefs .. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295 .. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347 To format the entire flash using littlefs v2:: # ESP8266 and ESP32 import os os.umount('/') os.VfsLfs2.mkfs(bdev) os.mount(bdev, '/') # STM32 import os, pyb os.umount('/flash') os.VfsLfs2.mkfs(pyb.Flash(start=0)) os.mount(pyb.Flash(start=0), '/flash') os.chdir('/flash') Hybrid (STM32) ~~~~~~~~~~~~~~ By using the ``start`` and ``len`` kwargs to :class:`pyb.Flash`, you can create block devices spanning a subset of the flash device. For example, to configure the first 256kiB as FAT (and available over USB MSC), and the remainder as littlefs:: import os, pyb os.umount('/flash') p1 = pyb.Flash(start=0, len=256*1024) p2 = pyb.Flash(start=256*1024) os.VfsFat.mkfs(p1) os.VfsLfs2.mkfs(p2) os.mount(p1, '/flash') os.mount(p2, '/data') os.chdir('/flash') This might be useful to make your Python files, configuration and other rarely-modified content available over USB MSC, but allowing for frequently changing application data to reside on littlefs with better resilience to power failure, etc. The partition at offset ``0`` will be mounted automatically (and the filesystem type automatically detected), but you can add:: import os, pyb p2 = pyb.Flash(start=256*1024) os.mount(p2, '/data') to ``boot.py`` to mount the data partition. Hybrid (ESP32) ~~~~~~~~~~~~~~ On ESP32, if you build custom firmware, you can modify ``partitions.csv`` to define an arbitrary partition layout. At boot, the partition named "vfs" will be mounted at ``/`` by default, but any additional partitions can be mounted in your ``boot.py`` using:: import esp32, os p = esp32.Partition.find(esp32.Partition.TYPE_DATA, label='foo') os.mount(p, '/foo') micropython-1.12/docs/reference/glossary.rst000066400000000000000000000230221357706137100213040ustar00rootroot00000000000000Glossary ======== .. glossary:: baremetal A system without a (full-fledged) operating system, for example an :term:`MCU`-based system. When running on a baremetal system, MicroPython effectively functions like a small operating system, running user programs and providing a command interpreter (:term:`REPL`). buffer protocol Any Python object that can be automatically converted into bytes, such as ``bytes``, ``bytearray``, ``memoryview`` and ``str`` objects, which all implement the "buffer protocol". board Typically this refers to a printed circuit board (PCB) containing a :term:`microcontroller ` and supporting components. MicroPython firmware is typically provided per-board, as the firmware contains both MCU-specific functionality but also board-level functionality such as drivers or pin names. bytecode A compact representation of a Python program that generated by compiling the Python source code. This is what the VM actually executes. Bytecode is typically generated automatically at runtime and is invisible to the user. Note that while :term:`CPython` and MicroPython both use bytecode, the format is different. You can also pre-compile source code offline using the :term:`cross-compiler`. callee-owned tuple This is a MicroPython-specific construct where, for efficiency reasons, some built-in functions or methods may re-use the same underlying tuple object to return data. This avoids having to allocate a new tuple for every call, and reduces heap fragmentation. Programs should not hold references to callee-owned tuples and instead only extract data from them (or make a copy). CircuitPython A variant of MicroPython developed by `Adafruit Industries `_. CPython CPython is the reference implementation of the Python programming language, and the most well-known one. It is, however, one of many implementations (including Jython, IronPython, PyPy, and MicroPython). While MicroPython's implementation differs substantially from CPython, it aims to maintain as much compatibility as possible. cross-compiler Also known as ``mpy-cross``. This tool runs on your PC and converts a :term:`.py file` containing MicroPython code into a :term:`.mpy file` containing MicroPython bytecode. This means it loads faster (the board doesn't have to compile the code), and uses less space on flash (the bytecode is more space efficient). driver A MicroPython library that implements support for a particular component, such as a sensor or display. FFI Acronym for Foreign Function Interface. A mechanism used by the :term:`MicroPython Unix port` to access operating system functionality. This is not available on :term:`baremetal` ports. filesystem Most MicroPython ports and boards provide a filesystem stored in flash that is available to user code via the standard Python file APIs such as ``open()``. Some boards also make this internal filesystem accessible to the host via USB mass-storage. frozen module A Python module that has been cross compiled and bundled into the firmware image. This reduces RAM requirements as the code is executed directly from flash. Garbage Collector A background process that runs in Python (and MicroPython) to reclaim unused memory in the :term:`heap`. GPIO General-purpose input/output. The simplest means to control electrical signals (commonly referred to as "pins") on a microcontroller. GPIO typically allows pins to be either input or output, and to set or get their digital value (logical "0" or "1"). MicroPython abstracts GPIO access using the :class:`machine.Pin` and :class:`machine.Signal` classes. GPIO port A group of :term:`GPIO` pins, usually based on hardware properties of these pins (e.g. controllable by the same register). heap A region of RAM where MicroPython stores dynamic data. It is managed automatically by the :term:`Garbage Collector`. Different MCUs and boards have vastly different amounts of RAM available for the heap, so this will affect how complex your program can be. interned string An optimisation used by MicroPython to improve the efficiency of working with strings. An interned string is referenced by its (unique) identity rather than its address and can therefore be quickly compared just by its identifier. It also means that identical strings can be de-duplicated in memory. String interning is almost always invisible to the user. MCU Microcontroller. Microcontrollers usually have much less resources than a desktop, laptop, or phone, but are smaller, cheaper and require much less power. MicroPython is designed to be small and optimized enough to run on an average modern microcontroller. micropython-lib MicroPython is (usually) distributed as a single executable/binary file with just few builtin modules. There is no extensive standard library comparable with :term:`CPython`'s. Instead, there is a related, but separate project `micropython-lib `_ which provides implementations for many modules from CPython's standard library. Some of the modules are are implemented in pure Python, and are able to be used on all ports. However, the majority of these modules use :term:`FFI` to access operating system functionality, and as such can only be used on the :term:`MicroPython Unix port` (with limited support for Windows). Unlike the :term:`CPython` stdlib, micropython-lib modules are intended to be installed individually - either using manual copying or using :term:`upip`. MicroPython port MicroPython supports different :term:`boards `, RTOSes, and OSes, and can be relatively easily adapted to new systems. MicroPython with support for a particular system is called a "port" to that system. Different ports may have widely different functionality. This documentation is intended to be a reference of the generic APIs available across different ports ("MicroPython core"). Note that some ports may still omit some APIs described here (e.g. due to resource constraints). Any such differences, and port-specific extensions beyond the MicroPython core functionality, would be described in the separate port-specific documentation. MicroPython Unix port The unix port is one of the major :term:`MicroPython ports `. It is intended to run on POSIX-compatible operating systems, like Linux, MacOS, FreeBSD, Solaris, etc. It also serves as the basis of Windows port. The Unix port is very useful for quick development and testing of the MicroPython language and machine-independent features. It can also function in a similar way to :term:`CPython`'s ``python`` executable. .mpy file The output of the :term:`cross-compiler`. A compiled form of a :term:`.py file` that contains MicroPython bytecode instead of Python source code. native Usually refers to "native code", i.e. machine code for the target microcontroller (such as ARM Thumb, Xtensa, x86/x64). The ``@native`` decorator can be applied to a MicroPython function to generate native code instead of bytecode for that function, which will likely be faster but use more RAM. port Usually short for :term:`MicroPython port`, but could also refer to :term:`GPIO port`. .py file A file containing Python source code. REPL An acronym for "Read, Eval, Print, Loop". This is the interactive Python prompt, useful for debugging or testing short snippets of code. Most MicroPython boards make a REPL available over a UART, and this is typically accessible on a host PC via USB. stream Also known as a "file-like object". An Python object which provides sequential read-write access to the underlying data. A stream object implements a corresponding interface, which consists of methods like ``read()``, ``write()``, ``readinto()``, ``seek()``, ``flush()``, ``close()``, etc. A stream is an important concept in MicroPython; many I/O objects implement the stream interface, and thus can be used consistently and interchangeably in different contexts. For more information on streams in MicroPython, see the `uio` module. UART Acronym for "Universal Asynchronous Receiver/Transmitter". This is a peripheral that sends data over a pair of pins (TX & RX). Many boards include a way to make at least one of the UARTs available to a host PC as a serial port over USB. upip (Literally, "micro pip"). A package manager for MicroPython, inspired by :term:`CPython`'s pip, but much smaller and with reduced functionality. upip runs both on the :term:`Unix port ` and on :term:`baremetal` ports which offer filesystem and networking support. micropython-1.12/docs/reference/index.rst000066400000000000000000000017151357706137100205550ustar00rootroot00000000000000The MicroPython language ======================== MicroPython aims to implement the Python 3.4 standard (with selected features from later versions) with respect to language syntax, and most of the features of MicroPython are identical to those described by the "Language Reference" documentation at `docs.python.org `_. The MicroPython standard library is described in the :ref:`corresponding chapter `. The :ref:`cpython_diffs` chapter describes differences between MicroPython and CPython (which mostly concern standard library and types, but also some language-level features). This chapter describes features and peculiarities of MicroPython implementation and the best practices to use them. .. toctree:: :maxdepth: 1 glossary.rst repl.rst mpyfiles.rst isr_rules.rst speed_python.rst constrained.rst packages.rst asm_thumb2_index.rst filesystem.rst pyboard.py.rst micropython-1.12/docs/reference/isr_rules.rst000066400000000000000000000516751357706137100214670ustar00rootroot00000000000000.. _isr_rules: Writing interrupt handlers ========================== On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR's) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin. Such events can occur at any point in the execution of the program code. This carries significant consequences, some specific to the MicroPython language. Others are common to all systems capable of responding to real time events. This document covers the language specific issues first, followed by a brief introduction to real time programming for those new to it. This introduction uses vague terms like "slow" or "as fast as possible". This is deliberate, as speeds are application dependent. Acceptable durations for an ISR are dependent on the rate at which interrupts occur, the nature of the main program, and the presence of other concurrent events. Tips and recommended practices ------------------------------ This summarises the points detailed below and lists the principal recommendations for interrupt handler code. * Keep the code as short and simple as possible. * Avoid memory allocation: no appending to lists or insertion into dictionaries, no floating point. * Consider using ``micropython.schedule`` to work around the above constraint. * Where an ISR returns multiple bytes use a pre-allocated ``bytearray``. If multiple integers are to be shared between an ISR and the main program consider an array (``array.array``). * Where data is shared between the main program and an ISR, consider disabling interrupts prior to accessing the data in the main program and re-enabling them immediately afterwards (see Critical Sections). * Allocate an emergency exception buffer (see below). MicroPython Issues ------------------ The emergency exception buffer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If an error occurs in an ISR, MicroPython is unable to produce an error report unless a special buffer is created for the purpose. Debugging is simplified if the following code is included in any program using interrupts. .. code:: python import micropython micropython.alloc_emergency_exception_buf(100) Simplicity ~~~~~~~~~~ For a variety of reasons it is important to keep ISR code as short and simple as possible. It should do only what has to be done immediately after the event which caused it: operations which can be deferred should be delegated to the main program loop. Typically an ISR will deal with the hardware device which caused the interrupt, making it ready for the next interrupt to occur. It will communicate with the main loop by updating shared data to indicate that the interrupt has occurred, and it will return. An ISR should return control to the main loop as quickly as possible. This is not a specific MicroPython issue so is covered in more detail :ref:`below `. Communication between an ISR and the main program ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Normally an ISR needs to communicate with the main program. The simplest means of doing this is via one or more shared data objects, either declared as global or shared via a class (see below). There are various restrictions and hazards around doing this, which are covered in more detail below. Integers, ``bytes`` and ``bytearray`` objects are commonly used for this purpose along with arrays (from the array module) which can store various data types. The use of object methods as callbacks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MicroPython supports this powerful technique which enables an ISR to share instance variables with the underlying code. It also enables a class implementing a device driver to support multiple device instances. The following example causes two LED's to flash at different rates. .. code:: python import pyb, micropython micropython.alloc_emergency_exception_buf(100) class Foo(object): def __init__(self, timer, led): self.led = led timer.callback(self.cb) def cb(self, tim): self.led.toggle() red = Foo(pyb.Timer(4, freq=1), pyb.LED(1)) green = Foo(pyb.Timer(2, freq=0.8), pyb.LED(2)) In this example the ``red`` instance associates timer 4 with LED 1: when a timer 4 interrupt occurs ``red.cb()`` is called causing LED 1 to change state. The ``green`` instance operates similarly: a timer 2 interrupt results in the execution of ``green.cb()`` and toggles LED 2. The use of instance methods confers two benefits. Firstly a single class enables code to be shared between multiple hardware instances. Secondly, as a bound method the callback function's first argument is ``self``. This enables the callback to access instance data and to save state between successive calls. For example, if the class above had a variable ``self.count`` set to zero in the constructor, ``cb()`` could increment the counter. The ``red`` and ``green`` instances would then maintain independent counts of the number of times each LED had changed state. Creation of Python objects ~~~~~~~~~~~~~~~~~~~~~~~~~~ ISR's cannot create instances of Python objects. This is because MicroPython needs to allocate memory for the object from a store of free memory block called the heap. This is not permitted in an interrupt handler because heap allocation is not re-entrant. In other words the interrupt might occur when the main program is part way through performing an allocation - to maintain the integrity of the heap the interpreter disallows memory allocations in ISR code. A consequence of this is that ISR's can't use floating point arithmetic; this is because floats are Python objects. Similarly an ISR can't append an item to a list. In practice it can be hard to determine exactly which code constructs will attempt to perform memory allocation and provoke an error message: another reason for keeping ISR code short and simple. One way to avoid this issue is for the ISR to use pre-allocated buffers. For example a class constructor creates a ``bytearray`` instance and a boolean flag. The ISR method assigns data to locations in the buffer and sets the flag. The memory allocation occurs in the main program code when the object is instantiated rather than in the ISR. The MicroPython library I/O methods usually provide an option to use a pre-allocated buffer. For example ``pyb.i2c.recv()`` can accept a mutable buffer as its first argument: this enables its use in an ISR. A means of creating an object without employing a class or globals is as follows: .. code:: python def set_volume(t, buf=bytearray(3)): buf[0] = 0xa5 buf[1] = t >> 4 buf[2] = 0x5a return buf The compiler instantiates the default ``buf`` argument when the function is loaded for the first time (usually when the module it's in is imported). An instance of object creation occurs when a reference to a bound method is created. This means that an ISR cannot pass a bound method to a function. One solution is to create a reference to the bound method in the class constructor and to pass that reference in the ISR. For example: .. code:: python class Foo(): def __init__(self): self.bar_ref = self.bar # Allocation occurs here self.x = 0.1 tim = pyb.Timer(4) tim.init(freq=2) tim.callback(self.cb) def bar(self, _): self.x *= 1.2 print(self.x) def cb(self, t): # Passing self.bar would cause allocation. micropython.schedule(self.bar_ref, 0) Other techniques are to define and instantiate the method in the constructor or to pass :meth:`Foo.bar` with the argument *self*. Use of Python objects ~~~~~~~~~~~~~~~~~~~~~ A further restriction on objects arises because of the way Python works. When an ``import`` statement is executed the Python code is compiled to bytecode, with one line of code typically mapping to multiple bytecodes. When the code runs the interpreter reads each bytecode and executes it as a series of machine code instructions. Given that an interrupt can occur at any time between machine code instructions, the original line of Python code may be only partially executed. Consequently a Python object such as a set, list or dictionary modified in the main loop may lack internal consistency at the moment the interrupt occurs. A typical outcome is as follows. On rare occasions the ISR will run at the precise moment in time when the object is partially updated. When the ISR tries to read the object, a crash results. Because such problems typically occur on rare, random occasions they can be hard to diagnose. There are ways to circumvent this issue, described in :ref:`Critical Sections ` below. It is important to be clear about what constitutes the modification of an object. An alteration to a built-in type such as a dictionary is problematic. Altering the contents of an array or bytearray is not. This is because bytes or words are written as a single machine code instruction which is not interruptible: in the parlance of real time programming the write is atomic. A user defined object might instantiate an integer, array or bytearray. It is valid for both the main loop and the ISR to alter the contents of these. MicroPython supports integers of arbitrary precision. Values between 2**30 -1 and -2**30 will be stored in a single machine word. Larger values are stored as Python objects. Consequently changes to long integers cannot be considered atomic. The use of long integers in ISR's is unsafe because memory allocation may be attempted as the variable's value changes. Overcoming the float limitation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In general it is best to avoid using floats in ISR code: hardware devices normally handle integers and conversion to floats is normally done in the main loop. However there are a few DSP algorithms which require floating point. On platforms with hardware floating point (such as the Pyboard) the inline ARM Thumb assembler can be used to work round this limitation. This is because the processor stores float values in a machine word; values can be shared between the ISR and main program code via an array of floats. Using micropython.schedule ~~~~~~~~~~~~~~~~~~~~~~~~~~ This function enables an ISR to schedule a callback for execution "very soon". The callback is queued for execution which will take place at a time when the heap is not locked. Hence it can create Python objects and use floats. The callback is also guaranteed to run at a time when the main program has completed any update of Python objects, so the callback will not encounter partially updated objects. Typical usage is to handle sensor hardware. The ISR acquires data from the hardware and enables it to issue a further interrupt. It then schedules a callback to process the data. Scheduled callbacks should comply with the principles of interrupt handler design outlined below. This is to avoid problems resulting from I/O activity and the modification of shared data which can arise in any code which pre-empts the main program loop. Execution time needs to be considered in relation to the frequency with which interrupts can occur. If an interrupt occurs while the previous callback is executing, a further instance of the callback will be queued for execution; this will run after the current instance has completed. A sustained high interrupt repetition rate therefore carries a risk of unconstrained queue growth and eventual failure with a ``RuntimeError``. If the callback to be passed to `schedule()` is a bound method, consider the note in "Creation of Python objects". Exceptions ---------- If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the exception is handled by the ISR code. General Issues -------------- This is merely a brief introduction to the subject of real time programming. Beginners should note that design errors in real time programs can lead to faults which are particularly hard to diagnose. This is because they can occur rarely and at intervals which are essentially random. It is crucial to get the initial design right and to anticipate issues before they arise. Both interrupt handlers and the main program need to be designed with an appreciation of the following issues. .. _ISR: Interrupt Handler Design ~~~~~~~~~~~~~~~~~~~~~~~~ As mentioned above, ISR's should be designed to be as simple as possible. They should always return in a short, predictable period of time. This is important because when the ISR is running, the main loop is not: inevitably the main loop experiences pauses in its execution at random points in the code. Such pauses can be a source of hard to diagnose bugs particularly if their duration is long or variable. In order to understand the implications of ISR run time, a basic grasp of interrupt priorities is required. Interrupts are organised according to a priority scheme. ISR code may itself be interrupted by a higher priority interrupt. This has implications if the two interrupts share data (see Critical Sections below). If such an interrupt occurs it interposes a delay into the ISR code. If a lower priority interrupt occurs while the ISR is running, it will be delayed until the ISR is complete: if the delay is too long, the lower priority interrupt may fail. A further issue with slow ISR's is the case where a second interrupt of the same type occurs during its execution. The second interrupt will be handled on termination of the first. However if the rate of incoming interrupts consistently exceeds the capacity of the ISR to service them the outcome will not be a happy one. Consequently looping constructs should be avoided or minimised. I/O to devices other than to the interrupting device should normally be avoided: I/O such as disk access, ``print`` statements and UART access is relatively slow, and its duration may vary. A further issue here is that filesystem functions are not reentrant: using filesystem I/O in an ISR and the main program would be hazardous. Crucially ISR code should not wait on an event. I/O is acceptable if the code can be guaranteed to return in a predictable period, for example toggling a pin or LED. Accessing the interrupting device via I2C or SPI may be necessary but the time taken for such accesses should be calculated or measured and its impact on the application assessed. There is usually a need to share data between the ISR and the main loop. This may be done either through global variables or via class or instance variables. Variables are typically integer or boolean types, or integer or byte arrays (a pre-allocated integer array offers faster access than a list). Where multiple values are modified by the ISR it is necessary to consider the case where the interrupt occurs at a time when the main program has accessed some, but not all, of the values. This can lead to inconsistencies. Consider the following design. An ISR stores incoming data in a bytearray, then adds the number of bytes received to an integer representing total bytes ready for processing. The main program reads the number of bytes, processes the bytes, then clears down the number of bytes ready. This will work until an interrupt occurs just after the main program has read the number of bytes. The ISR puts the added data into the buffer and updates the number received, but the main program has already read the number, so processes the data originally received. The newly arrived bytes are lost. There are various ways of avoiding this hazard, the simplest being to use a circular buffer. If it is not possible to use a structure with inherent thread safety other ways are described below. Reentrancy ~~~~~~~~~~ A potential hazard may occur if a function or method is shared between the main program and one or more ISR's or between multiple ISR's. The issue here is that the function may itself be interrupted and a further instance of that function run. If this is to occur, the function must be designed to be reentrant. How this is done is an advanced topic beyond the scope of this tutorial. .. _Critical: Critical Sections ~~~~~~~~~~~~~~~~~ An example of a critical section of code is one which accesses more than one variable which can be affected by an ISR. If the interrupt happens to occur between accesses to the individual variables, their values will be inconsistent. This is an instance of a hazard known as a race condition: the ISR and the main program loop race to alter the variables. To avoid inconsistency a means must be employed to ensure that the ISR does not alter the values for the duration of the critical section. One way to achieve this is to issue ``pyb.disable_irq()`` before the start of the section, and ``pyb.enable_irq()`` at the end. Here is an example of this approach: .. code:: python import pyb, micropython, array micropython.alloc_emergency_exception_buf(100) class BoundsException(Exception): pass ARRAYSIZE = const(20) index = 0 data = array.array('i', 0 for x in range(ARRAYSIZE)) def callback1(t): global data, index for x in range(5): data[index] = pyb.rng() # simulate input index += 1 if index >= ARRAYSIZE: raise BoundsException('Array bounds exceeded') tim4 = pyb.Timer(4, freq=100, callback=callback1) for loop in range(1000): if index > 0: irq_state = pyb.disable_irq() # Start of critical section for x in range(index): print(data[x]) index = 0 pyb.enable_irq(irq_state) # End of critical section print('loop {}'.format(loop)) pyb.delay(1) tim4.callback(None) A critical section can comprise a single line of code and a single variable. Consider the following code fragment. .. code:: python count = 0 def cb(): # An interrupt callback count +=1 def main(): # Code to set up the interrupt callback omitted while True: count += 1 This example illustrates a subtle source of bugs. The line ``count += 1`` in the main loop carries a specific race condition hazard known as a read-modify-write. This is a classic cause of bugs in real time systems. In the main loop MicroPython reads the value of ``t.counter``, adds 1 to it, and writes it back. On rare occasions the interrupt occurs after the read and before the write. The interrupt modifies ``t.counter`` but its change is overwritten by the main loop when the ISR returns. In a real system this could lead to rare, unpredictable failures. As mentioned above, care should be taken if an instance of a Python built in type is modified in the main code and that instance is accessed in an ISR. The code performing the modification should be regarded as a critical section to ensure that the instance is in a valid state when the ISR runs. Particular care needs to be taken if a dataset is shared between different ISR's. The hazard here is that the higher priority interrupt may occur when the lower priority one has partially updated the shared data. Dealing with this situation is an advanced topic beyond the scope of this introduction other than to note that mutex objects described below can sometimes be used. Disabling interrupts for the duration of a critical section is the usual and simplest way to proceed, but it disables all interrupts rather than merely the one with the potential to cause problems. It is generally undesirable to disable an interrupt for long. In the case of timer interrupts it introduces variability to the time when a callback occurs. In the case of device interrupts, it can lead to the device being serviced too late with possible loss of data or overrun errors in the device hardware. Like ISR's, a critical section in the main code should have a short, predictable duration. An approach to dealing with critical sections which radically reduces the time for which interrupts are disabled is to use an object termed a mutex (name derived from the notion of mutual exclusion). The main program locks the mutex before running the critical section and unlocks it at the end. The ISR tests whether the mutex is locked. If it is, it avoids the critical section and returns. The design challenge is defining what the ISR should do in the event that access to the critical variables is denied. A simple example of a mutex may be found `here `_. Note that the mutex code does disable interrupts, but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are virtually unaffected. Interrupts and the REPL ~~~~~~~~~~~~~~~~~~~~~~~ Interrupt handlers, such as those associated with timers, can continue to run after a program terminates. This may produce unexpected results where you might have expected the object raising the callback to have gone out of scope. For example on the Pyboard: .. code:: python def bar(): foo = pyb.Timer(2, freq=4, callback=lambda t: print('.', end='')) bar() This continues to run until the timer is explicitly disabled or the board is reset with ``ctrl D``. micropython-1.12/docs/reference/mpyfiles.rst000066400000000000000000000156001357706137100212740ustar00rootroot00000000000000.. _mpy_files: MicroPython .mpy files ====================== MicroPython defines the concept of an .mpy file which is a binary container file format that holds precompiled code, and which can be imported like a normal .py module. The file ``foo.mpy`` can be imported via ``import foo``, as long as ``foo.mpy`` can be found in the usual way by the import machinery. Usually, each directory listed in ``sys.path`` is searched in order. When searching a particular directory ``foo.py`` is looked for first and if that is not found then ``foo.mpy`` is looked for, then the search continues in the next directory if neither is found. As such, ``foo.py`` will take precedence over ``foo.mpy``. These .mpy files can contain bytecode which is usually generated from Python source files (.py files) via the ``mpy-cross`` program. For some architectures an .mpy file can also contain native machine code, which can be generated in a variety of ways, most notably from C source code. Versioning and compatibility of .mpy files ------------------------------------------ A given .mpy file may or may not be compatible with a given MicroPython system. Compatibility is based on the following: * Version of the .mpy file: the version of the file must match the version supported by the system loading it. * Bytecode features used in the .mpy file: there are two bytecode features which must match between the file and the system: unicode support and inline caching of map lookups in the bytecode. * Small integer bits: the .mpy file will require a minimum number of bits in a small integer and the system loading it must support at least this many bits. * Qstr compression window size: the .mpy file will require a minimum window size for qstr decompression and the system loading it must have a window greater or equal to this size. * Native architecture: if the .mpy file contains native machine code then it will specify the architecture of that machine code and the system loading it must support execution of that architecture's code. If a MicroPython system supports importing .mpy files then the ``sys.implementation.mpy`` field will exist and return an integer which encodes the version (lower 8 bits), features and native architecture. Trying to import an .mpy file that fails one of the first four tests will raise ``ValueError('incompatible .mpy file')``. Trying to import an .mpy file that fails the native architecture test (if it contains native machine code) will raise ``ValueError('incompatible .mpy arch')``. If importing an .mpy file fails then try the following: * Determine the .mpy version and flags supported by your MicroPython system by executing:: import sys sys_mpy = sys.implementation.mpy arch = [None, 'x86', 'x64', 'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp', 'xtensa', 'xtensawin'][sys_mpy >> 10] print('mpy version:', sys_mpy & 0xff) print('mpy flags:', end='') if arch: print(' -march=' + arch, end='') if sys_mpy & 0x100: print(' -mcache-lookup-bc', end='') if not sys_mpy & 0x200: print(' -mno-unicode', end='') print() * Check the validity of the .mpy file by inspecting the first two bytes of the file. The first byte should be an uppercase 'M' and the second byte will be the version number, which should match the system version from above. If it doesn't match then rebuild the .mpy file. * Check if the system .mpy version matches the version emitted by ``mpy-cross`` that was used to build the .mpy file, found by ``mpy-cross --version``. If it doesn't match then recompile ``mpy-cross`` from the Git repository checked out at the tag (or hash) reported by ``mpy-cross --version``. * Make sure you are using the correct ``mpy-cross`` flags, found by the code above, or by inspecting the ``MPY_CROSS_FLAGS`` Makefile variable for the port that you are using. The following table shows the correspondence between MicroPython release and .mpy version. =================== ============ MicroPython release .mpy version =================== ============ v1.12 and up 5 v1.11 4 v1.9.3 - v1.10 3 v1.9 - v1.9.2 2 v1.5.1 - v1.8.7 0 =================== ============ For completeness, the next table shows the Git commit of the main MicroPython repository at which the .mpy version was changed. =================== ======================================== .mpy version change Git commit =================== ======================================== 4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517 3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e 2 to 3 ff93fd4f50321c6190e1659b19e64fef3045a484 1 to 2 dd11af209d226b7d18d5148b239662e30ed60bad 0 to 1 6a11048af1d01c78bdacddadd1b72dc7ba7c6478 initial version 0 d8c834c95d506db979ec871417de90b7951edc30 =================== ======================================== Binary encoding of .mpy files ----------------------------- MicroPython .mpy files are a binary container format with code objects stored internally in a nested hierarchy. To keep files small while still providing a large range of possible values it uses the concept of a variably-encoded-unsigned-integer (vuint) in many places. Similar to utf-8 encoding, this encoding stores 7 bits per byte with the 8th bit (MSB) set if one or more bytes follow. The bits of the unsigned integer are stored in the vuint in LSB form. The top-level of an .mpy file consists of two parts: * The header. * The raw-code for the outer scope of the module. This outer scope is executed when the .mpy file is imported. The header ~~~~~~~~~~ The .mpy header is: ====== ================================ size field ====== ================================ byte value 0x4d (ASCII 'M') byte .mpy version number byte feature flags byte number of bits in a small int vuint size of qstr window ====== ================================ Raw code elements ~~~~~~~~~~~~~~~~~ A raw-code element contains code, either bytecode or native machine code. Its contents are: ====== ================================ size field ====== ================================ vuint type and size ... code (bytecode or machine code) vuint number of constant objects vuint number of sub-raw-code elements ... constant objects ... sub-raw-code elements ====== ================================ The first vuint in a raw-code element encodes the type of code stored in this element (the two least-significant bits), and the decompressed length of the code (the amount of RAM to allocate for it). Following the vuint comes the code itself. In the case of bytecode it also contains compressed qstr values. Following the code comes a vuint counting the number of constant objects, and another vuint counting the number of sub-raw-code elements. The constant objects are then stored next. Finally any sub-raw-code elements are stored, recursively. micropython-1.12/docs/reference/packages.rst000066400000000000000000000323061357706137100212240ustar00rootroot00000000000000Distribution packages, package management, and deploying applications ===================================================================== Just as the "big" Python, MicroPython supports creation of "third party" packages, distributing them, and easily installing them in each user's environment. This chapter discusses how these actions are achieved. Some familiarity with Python packaging is recommended. Overview -------- Steps below represent a high-level workflow when creating and consuming packages: 1. Python modules and packages are turned into distribution package archives, and published at the Python Package Index (PyPI). 2. `upip` package manager can be used to install a distribution package on a `MicroPython port` with networking capabilities (for example, on the Unix port). 3. For ports without networking capabilities, an "installation image" can be prepared on the Unix port, and transferred to a device by suitable means. 4. For low-memory ports, the installation image can be frozen as the bytecode into MicroPython executable, thus minimizing the memory storage overheads. The sections below describe this process in details. Distribution packages --------------------- Python modules and packages can be packaged into archives suitable for transfer between systems, storing at the well-known location (PyPI), and downloading on demand for deployment. These archives are known as *distribution packages* (to differentiate them from Python packages (means to organize Python source code)). The MicroPython distribution package format is a well-known tar.gz format, with some adaptations however. The Gzip compressor, used as an external wrapper for TAR archives, by default uses 32KB dictionary size, which means that to uncompress a compressed stream, 32KB of contiguous memory needs to be allocated. This requirement may be not satisfiable on low-memory devices, which may have total memory available less than that amount, and even if not, a contiguous block like that may be hard to allocate due to memory fragmentation. To accommodate these constraints, MicroPython distribution packages use Gzip compression with the dictionary size of 4K, which should be a suitable compromise with still achieving some compression while being able to uncompressed even by the smallest devices. Besides the small compression dictionary size, MicroPython distribution packages also have other optimizations, like removing any files from the archive which aren't used by the installation process. In particular, `upip` package manager doesn't execute ``setup.py`` during installation (see below), and thus that file is not included in the archive. At the same time, these optimizations make MicroPython distribution packages not compatible with `CPython`'s package manager, ``pip``. This isn't considered a big problem, because: 1. Packages can be installed with `upip`, and then can be used with CPython (if they are compatible with it). 2. In the other direction, majority of CPython packages would be incompatible with MicroPython by various reasons, first of all, the reliance on features not implemented by MicroPython. Summing up, the MicroPython distribution package archives are highly optimized for MicroPython's target environments, which are highly resource constrained devices. ``upip`` package manager ------------------------ MicroPython distribution packages are intended to be installed using the `upip` package manager. `upip` is a Python application which is usually distributed (as frozen bytecode) with network-enabled `MicroPython ports `. At the very least, `upip` is available in the `MicroPython Unix port`. On any `MicroPython port` providing `upip`, it can be accessed as following:: import upip upip.help() upip.install(package_or_package_list, [path]) Where *package_or_package_list* is the name of a distribution package to install, or a list of such names to install multiple packages. Optional *path* parameter specifies filesystem location to install under and defaults to the standard library location (see below). An example of installing a specific package and then using it:: >>> import upip >>> upip.install("micropython-pystone_lowmem") [...] >>> import pystone_lowmem >>> pystone_lowmem.main() Note that the name of Python package and the name of distribution package for it in general don't have to match, and oftentimes they don't. This is because PyPI provides a central package repository for all different Python implementations and versions, and thus distribution package names may need to be namespaced for a particular implementation. For example, all packages from `micropython-lib` follow this naming convention: for a Python module or package named ``foo``, the distribution package name is ``micropython-foo``. For the ports which run MicroPython executable from the OS command prompts (like the Unix port), `upip` can be (and indeed, usually is) run from the command line instead of MicroPython's own REPL. The commands which corresponds to the example above are:: micropython -m upip -h micropython -m upip install [-p ] ... micropython -m upip install micropython-pystone_lowmem [TODO: Describe installation path.] Cross-installing packages ------------------------- For `MicroPython ports ` without native networking capabilities, the recommend process is "cross-installing" them into a "directory image" using the `MicroPython Unix port`, and then transferring this image to a device by suitable means. Installing to a directory image involves using ``-p`` switch to `upip`:: micropython -m upip install -p install_dir micropython-pystone_lowmem After this command, the package content (and contents of every dependency packages) will be available in the ``install_dir/`` subdirectory. You would need to transfer contents of this directory (without the ``install_dir/`` prefix) to the device, at the suitable location, where it can be found by the Python ``import`` statement (see discussion of the `upip` installation path above). Cross-installing packages with freezing --------------------------------------- For the low-memory `MicroPython ports `, the process described in the previous section does not provide the most efficient resource usage,because the packages are installed in the source form, so need to be compiled to the bytecome on each import. This compilation requires RAM, and the resulting bytecode is also stored in RAM, reducing its amount available for storing application data. Moreover, the process above requires presence of the filesystem on a device, and the most resource-constrained devices may not even have it. The bytecode freezing is a process which resolves all the issues mentioned above: * The source code is pre-compiled into bytecode and store as such. * The bytecode is stored in ROM, not RAM. * Filesystem is not required for frozen packages. Using frozen bytecode requires building the executable (firmware) for a given `MicroPython port` from the C source code. Consequently, the process is: 1. Follow the instructions for a particular port on setting up a toolchain and building the port. For example, for ESP8266 port, study instructions in ``ports/esp8266/README.md`` and follow them. Make sure you can build the port and deploy the resulting executable/firmware successfully before proceeding to the next steps. 2. Build `MicroPython Unix port` and make sure it is in your PATH and you can execute ``micropython``. 3. Change to port's directory (e.g. ``ports/esp8266/`` for ESP8266). 4. Run ``make clean-frozen``. This step cleans up any previous modules which were installed for freezing (consequently, you need to skip this step to add additional modules, instead of starting from scratch). 5. Run ``micropython -m upip install -p modules ...`` to install packages you want to freeze. 6. Run ``make clean``. 7. Run ``make``. After this, you should have the executable/firmware with modules as the bytecode inside, which you can deploy the usual way. Few notes: 1. Step 5 in the sequence above assumes that the distribution package is available from PyPI. If that is not the case, you would need to copy Python source files manually to ``modules/`` subdirectory of the port port directory. (Note that upip does not support installing from e.g. version control repositories). 2. The firmware for baremetal devices usually has size restrictions, so adding too many frozen modules may overflow it. Usually, you would get a linking error if this happens. However, in some cases, an image may be produced, which is not runnable on a device. Such cases are in general bugs, and should be reported and further investigated. If you face such a situation, as an initial step, you may want to decrease the amount of frozen modules included. Creating distribution packages ------------------------------ Distribution packages for MicroPython are created in the same manner as for CPython or any other Python implementation, see references at the end of chapter. Setuptools (instead of distutils) should be used, because distutils do not support dependencies and other features. "Source distribution" (``sdist``) format is used for packaging. The post-processing discussed above, (and pre-processing discussed in the following section) is achieved by using custom ``sdist`` command for setuptools. Thus, packaging steps remain the same as for the standard setuptools, the user just needs to override ``sdist`` command implementation by passing the appropriate argument to ``setup()`` call:: from setuptools import setup import sdist_upip setup( ..., cmdclass={'sdist': sdist_upip.sdist} ) The sdist_upip.py module as referenced above can be found in `micropython-lib`: https://github.com/micropython/micropython-lib/blob/master/sdist_upip.py Application resources --------------------- A complete application, besides the source code, oftentimes also consists of data files, e.g. web page templates, game images, etc. It's clear how to deal with those when application is installed manually - you just put those data files in the filesystem at some location and use the normal file access functions. The situation is different when deploying applications from packages - this is more advanced, streamlined and flexible way, but also requires more advanced approach to accessing data files. This approach is treating the data files as "resources", and abstracting away access to them. Python supports resource access using its "setuptools" library, using ``pkg_resources`` module. MicroPython, following its usual approach, implements subset of the functionality of that module, specifically ``pkg_resources.resource_stream(package, resource)`` function. The idea is that an application calls this function, passing a resource identifier, which is a relative path to data file within the specified package (usually top-level application package). It returns a stream object which can be used to access resource contents. Thus, the ``resource_stream()`` emulates interface of the standard `open()` function. Implementation-wise, ``resource_stream()`` uses file operations underlyingly, if distribution package is install in the filesystem. However, it also supports functioning without the underlying filesystem, e.g. if the package is frozen as the bytecode. This however requires an extra intermediate step when packaging application - creation of "Python resource module". The idea of this module is to convert binary data to a Python bytes object, and put it into the dictionary, indexed by the resource name. This conversion is done automatically using overridden ``sdist`` command described in the previous section. Let's trace the complete process using the following example. Suppose your application has the following structure:: my_app/ __main__.py utils.py data/ page.html image.png ``__main__.py`` and ``utils.py`` should access resources using the following calls:: import pkg_resources pkg_resources.resource_stream(__name__, "data/page.html") pkg_resources.resource_stream(__name__, "data/image.png") You can develop and debug using the `MicroPython Unix port` as usual. When time comes to make a distribution package out of it, just use overridden "sdist" command from sdist_upip.py module as described in the previous section. This will create a Python resource module named ``R.py``, based on the files declared in ``MANIFEST`` or ``MANIFEST.in`` files (any non-``.py`` file will be considered a resource and added to ``R.py``) - before proceeding with the normal packaging steps. Prepared like this, your application will work both when deployed to filesystem and as frozen bytecode. If you would like to debug ``R.py`` creation, you can run:: python3 setup.py sdist --manifest-only Alternatively, you can use tools/mpy_bin2res.py script from the MicroPython distribution, in which can you will need to pass paths to all resource files:: mpy_bin2res.py data/page.html data/image.png References ---------- * Python Packaging User Guide: https://packaging.python.org/ * Setuptools documentation: https://setuptools.readthedocs.io/ * Distutils documentation: https://docs.python.org/3/library/distutils.html micropython-1.12/docs/reference/pyboard.py.rst000066400000000000000000000110761357706137100215360ustar00rootroot00000000000000.. _pyboard_py: The pyboard.py tool =================== This is a standalone Python tool that runs on your PC that provides a way to: * Quickly run a Python script or command on a MicroPython device. This is useful while developing MicroPython programs to quickly test code without needing to copy files to/from the device. * Access the filesystem on a device. This allows you to deploy your code to the device (even if the board doesn't support USB MSC). Despite the name, ``pyboard.py`` works on all MicroPython ports that support the raw REPL (including STM32, ESP32, ESP8266, NRF). You can download the latest version from `GitHub `_. The only dependency is the ``pyserial`` library which can be installed from PiPy or your system package manager. Running ``pyboard.py --help`` gives the following output: .. code-block:: text usage: pyboard [-h] [--device DEVICE] [-b BAUDRATE] [-u USER] [-p PASSWORD] [-c COMMAND] [-w WAIT] [--follow] [-f] [files [files ...]] Run scripts on the pyboard. positional arguments: files input files optional arguments: -h, --help show this help message and exit --device DEVICE the serial device or the IP address of the pyboard -b BAUDRATE, --baudrate BAUDRATE the baud rate of the serial device -u USER, --user USER the telnet login username -p PASSWORD, --password PASSWORD the telnet login password -c COMMAND, --command COMMAND program passed in as string -w WAIT, --wait WAIT seconds to wait for USB connected board to become available --follow follow the output after running the scripts [default if no scripts given] -f, --filesystem perform a filesystem action Running a command on the device ------------------------------- This is useful for testing short snippets of code, or to script an interaction with the device.:: $ pyboard.py --device /dev/ttyACM0 -c 'print(1+1)' 2 Running a script on the device ------------------------------ If you have a script, ``app.py`` that you want to run on a device, then use:: $ pyboard.py --device /dev/ttyACM0 app.py Note that this doesn't actually copy app.py to the device's filesystem, it just loads the code into RAM and executes it. Any output generated by the program will be displayed. If the program app.py does not finish then you'll need to stop ``pyboard.py``, eg with Ctrl-C. The program ``app.py`` will still continue to run on the MicroPython device. Filesystem access ----------------- Using the ``-f`` flag, the following filesystem operations are supported: * ``cp src [src...] dest`` Copy files to/from the device. * ``cat path`` Print the contents of a file on the device. * ``ls [path]`` List contents of a directory (defaults to current working directory). * ``rm path`` Remove a file. * ``mkdir path`` Create a directory. * ``rmdir path`` Remove a directory. The ``cp`` command uses a ``ssh``-like convention for referring to local and remote files. Any path starting with a ``:`` will be interpreted as on the device, otherwise it will be local. So:: $ pyboard.py --device /dev/ttyACM0 -f cp main.py :main.py will copy main.py from the current directory on the PC to a file named main.py on the device. The filename can be omitted, e.g.:: $ pyboard.py --device /dev/ttyACM0 -f cp main.py : is equivalent to the above. Some more examples:: # Copy main.py from the device to the local PC. $ pyboard.py --device /dev/ttyACM0 -f cp :main.py main.py # Same, but using . instead. $ pyboard.py --device /dev/ttyACM0 -f cp :main.py . # Copy three files to the device, keeping their names # and paths (note: `lib` must exist on the device) $ pyboard.py --device /dev/ttyACM0 -f cp main.py app.py lib/foo.py : # Remove a file from the device. $ pyboard.py --device /dev/ttyACM0 -f rm util.py # Print the contents of a file on the device. $ pyboard.py --device /dev/ttyACM0 -f cat boot.py ...contents of boot.py... Using the pyboard library ------------------------- You can also use ``pyboard.py`` as a library for scripting interactions with a MicroPython board. .. code-block:: python import pyboard pyb = pyboard.Pyboard('/dev/ttyACM0', 115200) pyb.enter_raw_repl() ret = pyb.exec('print(1+1)') print(ret) pyb.exit_raw_repl() micropython-1.12/docs/reference/repl.rst000066400000000000000000000145461357706137100204160ustar00rootroot00000000000000The MicroPython Interactive Interpreter Mode (aka REPL) ======================================================= This section covers some characteristics of the MicroPython Interactive Interpreter Mode. A commonly used term for this is REPL (read-eval-print-loop) which will be used to refer to this interactive prompt. Auto-indent ----------- When typing python statements which end in a colon (for example if, for, while) then the prompt will change to three dots (...) and the cursor will be indented by 4 spaces. When you press return, the next line will continue at the same level of indentation for regular statements or an additional level of indentation where appropriate. If you press the backspace key then it will undo one level of indentation. If your cursor is all the way back at the beginning, pressing RETURN will then execute the code that you've entered. The following shows what you'd see after entering a for statement (the underscore shows where the cursor winds up): >>> for i in range(30): ... _ If you then enter an if statement, an additional level of indentation will be provided: >>> for i in range(30): ... if i > 3: ... _ Now enter ``break`` followed by RETURN and press BACKSPACE: >>> for i in range(30): ... if i > 3: ... break ... _ Finally type ``print(i)``, press RETURN, press BACKSPACE and press RETURN again: >>> for i in range(30): ... if i > 3: ... break ... print(i) ... 0 1 2 3 >>> Auto-indent won't be applied if the previous two lines were all spaces. This means that you can finish entering a compound statement by pressing RETURN twice, and then a third press will finish and execute. Auto-completion --------------- While typing a command at the REPL, if the line typed so far corresponds to the beginning of the name of something, then pressing TAB will show possible things that could be entered. For example, first import the machine module by entering ``import machine`` and pressing RETURN. Then type ``m`` and press TAB and it should expand to ``machine``. Enter a dot ``.`` and press TAB again. You should see something like: >>> machine. __name__ info unique_id reset bootloader freq rng idle sleep deepsleep disable_irq enable_irq Pin The word will be expanded as much as possible until multiple possibilities exist. For example, type ``machine.Pin.AF3`` and press TAB and it will expand to ``machine.Pin.AF3_TIM``. Pressing TAB a second time will show the possible expansions: >>> machine.Pin.AF3_TIM AF3_TIM10 AF3_TIM11 AF3_TIM8 AF3_TIM9 >>> machine.Pin.AF3_TIM Interrupting a running program ------------------------------ You can interrupt a running program by pressing Ctrl-C. This will raise a KeyboardInterrupt which will bring you back to the REPL, providing your program doesn't intercept the KeyboardInterrupt exception. For example: >>> for i in range(1000000): ... print(i) ... 0 1 2 3 ... 6466 6467 6468 Traceback (most recent call last): File "", line 2, in KeyboardInterrupt: >>> Paste Mode ---------- If you want to paste some code into your terminal window, the auto-indent feature will mess things up. For example, if you had the following python code: :: def foo(): print('This is a test to show paste mode') print('Here is a second line') foo() and you try to paste this into the normal REPL, then you will see something like this: >>> def foo(): ... print('This is a test to show paste mode') ... print('Here is a second line') ... foo() ... Traceback (most recent call last): File "", line 3 IndentationError: unexpected indent If you press Ctrl-E, then you will enter paste mode, which essentially turns off the auto-indent feature, and changes the prompt from ``>>>`` to ``===``. For example: >>> paste mode; Ctrl-C to cancel, Ctrl-D to finish === def foo(): === print('This is a test to show paste mode') === print('Here is a second line') === foo() === This is a test to show paste mode Here is a second line >>> Paste Mode allows blank lines to be pasted. The pasted text is compiled as if it were a file. Pressing Ctrl-D exits paste mode and initiates the compilation. Soft Reset ---------- A soft reset will reset the python interpreter, but tries not to reset the method by which you're connected to the MicroPython board (USB-serial, or Wifi). You can perform a soft reset from the REPL by pressing Ctrl-D, or from your python code by executing: :: machine.soft_reset() For example, if you reset your MicroPython board, and you execute a dir() command, you'd see something like this: >>> dir() ['__name__', 'pyb'] Now create some variables and repeat the dir() command: >>> i = 1 >>> j = 23 >>> x = 'abc' >>> dir() ['j', 'x', '__name__', 'pyb', 'i'] >>> Now if you enter Ctrl-D, and repeat the dir() command, you'll see that your variables no longer exist: .. code-block:: python MPY: sync filesystems MPY: soft reboot MicroPython v1.5-51-g6f70283-dirty on 2015-10-30; PYBv1.0 with STM32F405RG Type "help()" for more information. >>> dir() ['__name__', 'pyb'] >>> The special variable _ (underscore) ----------------------------------- When you use the REPL, you may perform computations and see the results. MicroPython stores the results of the previous statement in the variable _ (underscore). So you can use the underscore to save the result in a variable. For example: >>> 1 + 2 + 3 + 4 + 5 15 >>> x = _ >>> x 15 >>> Raw Mode -------- Raw mode is not something that a person would normally use. It is intended for programmatic use. It essentially behaves like paste mode with echo turned off. Raw mode is entered using Ctrl-A. You then send your python code, followed by a Ctrl-D. The Ctrl-D will be acknowledged by 'OK' and then the python code will be compiled and executed. Any output (or errors) will be sent back. Entering Ctrl-B will leave raw mode and return the the regular (aka friendly) REPL. The ``tools/pyboard.py`` program uses the raw REPL to execute python files on the MicroPython board. micropython-1.12/docs/reference/speed_python.rst000066400000000000000000000357231357706137100221550ustar00rootroot00000000000000.. _speed_python: Maximising MicroPython Speed ============================ .. contents:: This tutorial describes ways of improving the performance of MicroPython code. Optimisations involving other languages are covered elsewhere, namely the use of modules written in C and the MicroPython inline assembler. The process of developing high performance code comprises the following stages which should be performed in the order listed. * Design for speed. * Code and debug. Optimisation steps: * Identify the slowest section of code. * Improve the efficiency of the Python code. * Use the native code emitter. * Use the viper code emitter. * Use hardware-specific optimisations. Designing for speed ------------------- Performance issues should be considered at the outset. This involves taking a view on the sections of code which are most performance critical and devoting particular attention to their design. The process of optimisation begins when the code has been tested: if the design is correct at the outset optimisation will be straightforward and may actually be unnecessary. Algorithms ~~~~~~~~~~ The most important aspect of designing any routine for performance is ensuring that the best algorithm is employed. This is a topic for textbooks rather than for a MicroPython guide but spectacular performance gains can sometimes be achieved by adopting algorithms known for their efficiency. RAM Allocation ~~~~~~~~~~~~~~ To design efficient MicroPython code it is necessary to have an understanding of the way the interpreter allocates RAM. When an object is created or grows in size (for example where an item is appended to a list) the necessary RAM is allocated from a block known as the heap. This takes a significant amount of time; further it will on occasion trigger a process known as garbage collection which can take several milliseconds. Consequently the performance of a function or method can be improved if an object is created once only and not permitted to grow in size. This implies that the object persists for the duration of its use: typically it will be instantiated in a class constructor and used in various methods. This is covered in further detail :ref:`Controlling garbage collection ` below. Buffers ~~~~~~~ An example of the above is the common case where a buffer is required, such as one used for communication with a device. A typical driver will create the buffer in the constructor and use it in its I/O methods which will be called repeatedly. The MicroPython libraries typically provide support for pre-allocated buffers. For example, objects which support stream interface (e.g., file or UART) provide ``read()`` method which allocates new buffer for read data, but also a ``readinto()`` method to read data into an existing buffer. Floating Point ~~~~~~~~~~~~~~ Some MicroPython ports allocate floating point numbers on heap. Some other ports may lack dedicated floating-point coprocessor, and perform arithmetic operations on them in "software" at considerably lower speed than on integers. Where performance is important, use integer operations and restrict the use of floating point to sections of the code where performance is not paramount. For example, capture ADC readings as integers values to an array in one quick go, and only then convert them to floating-point numbers for signal processing. Arrays ~~~~~~ Consider the use of the various types of array classes as an alternative to lists. The `array` module supports various element types with 8-bit elements supported by Python's built in `bytes` and `bytearray` classes. These data structures all store elements in contiguous memory locations. Once again to avoid memory allocation in critical code these should be pre-allocated and passed as arguments or as bound objects. When passing slices of objects such as `bytearray` instances, Python creates a copy which involves allocation of the size proportional to the size of slice. This can be alleviated using a `memoryview` object. `memoryview` itself is allocated on heap, but is a small, fixed-size object, regardless of the size of slice it points too. .. code:: python ba = bytearray(10000) # big array func(ba[30:2000]) # a copy is passed, ~2K new allocation mv = memoryview(ba) # small object is allocated func(mv[30:2000]) # a pointer to memory is passed A `memoryview` can only be applied to objects supporting the buffer protocol - this includes arrays but not lists. Small caveat is that while memoryview object is live, it also keeps alive the original buffer object. So, a memoryview isn't a universal panacea. For instance, in the example above, if you are done with 10K buffer and just need those bytes 30:2000 from it, it may be better to make a slice, and let the 10K buffer go (be ready for garbage collection), instead of making a long-living memoryview and keeping 10K blocked for GC. Nonetheless, `memoryview` is indispensable for advanced preallocated buffer management. ``readinto()`` method discussed above puts data at the beginning of buffer and fills in entire buffer. What if you need to put data in the middle of existing buffer? Just create a memoryview into the needed section of buffer and pass it to ``readinto()``. Identifying the slowest section of code --------------------------------------- This is a process known as profiling and is covered in textbooks and (for standard Python) supported by various software tools. For the type of smaller embedded application likely to be running on MicroPython platforms the slowest function or method can usually be established by judicious use of the timing ``ticks`` group of functions documented in `utime`. Code execution time can be measured in ms, us, or CPU cycles. The following enables any function or method to be timed by adding an ``@timed_function`` decorator: .. code:: python def timed_function(f, *args, **kwargs): myname = str(f).split(' ')[1] def new_func(*args, **kwargs): t = utime.ticks_us() result = f(*args, **kwargs) delta = utime.ticks_diff(utime.ticks_us(), t) print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000)) return result return new_func MicroPython code improvements ----------------------------- The const() declaration ~~~~~~~~~~~~~~~~~~~~~~~ MicroPython provides a ``const()`` declaration. This works in a similar way to ``#define`` in C in that when the code is compiled to bytecode the compiler substitutes the numeric value for the identifier. This avoids a dictionary lookup at runtime. The argument to ``const()`` may be anything which, at compile time, evaluates to an integer e.g. ``0x100`` or ``1 << 8``. .. _Caching: Caching object references ~~~~~~~~~~~~~~~~~~~~~~~~~~ Where a function or method repeatedly accesses objects performance is improved by caching the object in a local variable: .. code:: python class foo(object): def __init__(self): self.ba = bytearray(100) def bar(self, obj_display): ba_ref = self.ba fb = obj_display.framebuffer # iterative code using these two objects This avoids the need repeatedly to look up ``self.ba`` and ``obj_display.framebuffer`` in the body of the method ``bar()``. .. _controlling_gc: Controlling garbage collection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When memory allocation is required, MicroPython attempts to locate an adequately sized block on the heap. This may fail, usually because the heap is cluttered with objects which are no longer referenced by code. If a failure occurs, the process known as garbage collection reclaims the memory used by these redundant objects and the allocation is then tried again - a process which can take several milliseconds. There may be benefits in pre-empting this by periodically issuing `gc.collect()`. Firstly doing a collection before it is actually required is quicker - typically on the order of 1ms if done frequently. Secondly you can determine the point in code where this time is used rather than have a longer delay occur at random points, possibly in a speed critical section. Finally performing collections regularly can reduce fragmentation in the heap. Severe fragmentation can lead to non-recoverable allocation failures. The Native code emitter ----------------------- This causes the MicroPython compiler to emit native CPU opcodes rather than bytecode. It covers the bulk of the MicroPython functionality, so most functions will require no adaptation (but see below). It is invoked by means of a function decorator: .. code:: python @micropython.native def foo(self, arg): buf = self.linebuf # Cached object # code There are certain limitations in the current implementation of the native code emitter. * Context managers are not supported (the ``with`` statement). * Generators are not supported. * If ``raise`` is used an argument must be supplied. The trade-off for the improved performance (roughly twice as fast as bytecode) is an increase in compiled code size. The Viper code emitter ---------------------- The optimisations discussed above involve standards-compliant Python code. The Viper code emitter is not fully compliant. It supports special Viper native data types in pursuit of performance. Integer processing is non-compliant because it uses machine words: arithmetic on 32 bit hardware is performed modulo 2**32. Like the Native emitter Viper produces machine instructions but further optimisations are performed, substantially increasing performance especially for integer arithmetic and bit manipulations. It is invoked using a decorator: .. code:: python @micropython.viper def foo(self, arg: int) -> int: # code As the above fragment illustrates it is beneficial to use Python type hints to assist the Viper optimiser. Type hints provide information on the data types of arguments and of the return value; these are a standard Python language feature formally defined here `PEP0484 `_. Viper supports its own set of types namely ``int``, ``uint`` (unsigned integer), ``ptr``, ``ptr8``, ``ptr16`` and ``ptr32``. The ``ptrX`` types are discussed below. Currently the ``uint`` type serves a single purpose: as a type hint for a function return value. If such a function returns ``0xffffffff`` Python will interpret the result as 2**32 -1 rather than as -1. In addition to the restrictions imposed by the native emitter the following constraints apply: * Functions may have up to four arguments. * Default argument values are not permitted. * Floating point may be used but is not optimised. Viper provides pointer types to assist the optimiser. These comprise * ``ptr`` Pointer to an object. * ``ptr8`` Points to a byte. * ``ptr16`` Points to a 16 bit half-word. * ``ptr32`` Points to a 32 bit machine word. The concept of a pointer may be unfamiliar to Python programmers. It has similarities to a Python `memoryview` object in that it provides direct access to data stored in memory. Items are accessed using subscript notation, but slices are not supported: a pointer can return a single item only. Its purpose is to provide fast random access to data stored in contiguous memory locations - such as data stored in objects which support the buffer protocol, and memory-mapped peripheral registers in a microcontroller. It should be noted that programming using pointers is hazardous: bounds checking is not performed and the compiler does nothing to prevent buffer overrun errors. Typical usage is to cache variables: .. code:: python @micropython.viper def foo(self, arg: int) -> int: buf = ptr8(self.linebuf) # self.linebuf is a bytearray or bytes object for x in range(20, 30): bar = buf[x] # Access a data item through the pointer # code omitted In this instance the compiler "knows" that ``buf`` is the address of an array of bytes; it can emit code to rapidly compute the address of ``buf[x]`` at runtime. Where casts are used to convert objects to Viper native types these should be performed at the start of the function rather than in critical timing loops as the cast operation can take several microseconds. The rules for casting are as follows: * Casting operators are currently: ``int``, ``bool``, ``uint``, ``ptr``, ``ptr8``, ``ptr16`` and ``ptr32``. * The result of a cast will be a native Viper variable. * Arguments to a cast can be a Python object or a native Viper variable. * If argument is a native Viper variable, then cast is a no-op (i.e. costs nothing at runtime) that just changes the type (e.g. from ``uint`` to ``ptr8``) so that you can then store/load using this pointer. * If the argument is a Python object and the cast is ``int`` or ``uint``, then the Python object must be of integral type and the value of that integral object is returned. * The argument to a bool cast must be integral type (boolean or integer); when used as a return type the viper function will return True or False objects. * If the argument is a Python object and the cast is ``ptr``, ``ptr``, ``ptr16`` or ``ptr32``, then the Python object must either have the buffer protocol (in which case a pointer to the start of the buffer is returned) or it must be of integral type (in which case the value of that integral object is returned). Writing to a pointer which points to a read-only object will lead to undefined behaviour. The following example illustrates the use of a ``ptr16`` cast to toggle pin X1 ``n`` times: .. code:: python BIT0 = const(1) @micropython.viper def toggle_n(n: int): odr = ptr16(stm.GPIOA + stm.GPIO_ODR) for _ in range(n): odr[0] ^= BIT0 A detailed technical description of the three code emitters may be found on Kickstarter here `Note 1 `_ and here `Note 2 `_ Accessing hardware directly --------------------------- .. note:: Code examples in this section are given for the Pyboard. The techniques described however may be applied to other MicroPython ports too. This comes into the category of more advanced programming and involves some knowledge of the target MCU. Consider the example of toggling an output pin on the Pyboard. The standard approach would be to write .. code:: python mypin.value(mypin.value() ^ 1) # mypin was instantiated as an output pin This involves the overhead of two calls to the :class:`~machine.Pin` instance's :meth:`~machine.Pin.value()` method. This overhead can be eliminated by performing a read/write to the relevant bit of the chip's GPIO port output data register (odr). To facilitate this the ``stm`` module provides a set of constants providing the addresses of the relevant registers. A fast toggle of pin ``P4`` (CPU pin ``A14``) - corresponding to the green LED - can be performed as follows: .. code:: python import machine import stm BIT14 = const(1 << 14) machine.mem16[stm.GPIOA + stm.GPIO_ODR] ^= BIT14 micropython-1.12/docs/static/000077500000000000000000000000001357706137100162415ustar00rootroot00000000000000micropython-1.12/docs/static/customstyle.css000066400000000000000000000002651357706137100213510ustar00rootroot00000000000000/* custom CSS for MicroPython docs */ .admonition-difference-to-cpython { border: 1px solid black; } .admonition-difference-to-cpython .admonition-title { margin: 4px; } micropython-1.12/docs/static/favicon.ico000066400000000000000000000025761357706137100203740ustar00rootroot00000000000000h( ]]]ppptttuuuvvvxxx{{{~~~ % "/,//////& /&/-..-/#/'////(//'// //'//'////'//'////'//'////'//'////'//'////'//* .//. )//,.+//+.+/!//////////!$ $"micropython-1.12/docs/templates/000077500000000000000000000000001357706137100167505ustar00rootroot00000000000000micropython-1.12/docs/templates/layout.html000066400000000000000000000003651357706137100211570ustar00rootroot00000000000000{% extends "!layout.html" %} {% set css_files = css_files + ["_static/customstyle.css"] %} {# we change the master_doc variable so that links to the index page are to index.html instead of _index.html #} {% set master_doc = "index" %} micropython-1.12/docs/templates/replace.inc000066400000000000000000000005151357706137100210570ustar00rootroot00000000000000.. comment: This file is intended for global "replace" definitions. .. |see_cpython| replace:: See CPython documentation: .. |see_cpython_module| replace:: *This module implements a subset of the corresponding* `CPython` *module, as described below. For more information, refer to the original CPython documentation:* micropython-1.12/docs/templates/topindex.html000066400000000000000000000112101357706137100214630ustar00rootroot00000000000000{% extends "layout.html" %} {% set title = _('Overview') %} {% block body %}

MicroPython documentation

{{ _('Welcome! This is the documentation for MicroPython') }} v{{ release|e }}{% if last_updated %}, {{ _('last updated') }} {{ last_updated|e }}{% endif %}.

MicroPython runs on a variety of systems and hardware platforms. Here you can read the general documentation which applies to all systems, as well as specific information about the various platforms - also known as ports - that MicroPython runs on.

General documentation for MicroPython:

References and tutorials for specific platforms:

Indices and tables:

External links:

{% endblock %} micropython-1.12/docs/templates/versions.html000066400000000000000000000016161357706137100215120ustar00rootroot00000000000000
Versions and Downloads {{ cur_version }}
Versions
{% for slug, url in all_versions %}
{{ slug }}
{% endfor %}
Downloads
{% for type, url in downloads %}
{{ type }}
{% endfor %}

External links
micropython.org
GitHub
micropython-1.12/docs/wipy/000077500000000000000000000000001357706137100157425ustar00rootroot00000000000000micropython-1.12/docs/wipy/general.rst000066400000000000000000000354531357706137100201230ustar00rootroot00000000000000.. _wipy_general: General information about the WiPy ================================== No floating point support ------------------------- Due to space reasons, there's no floating point support, and no math module. This means that floating point numbers cannot be used anywhere in the code, and that all divisions must be performed using '//' instead of '/'. Example:: >>> r = 4 // 2 # this will work >>> r = 4 / 2 # this WON'T Before applying power --------------------- .. warning:: The GPIO pins of the WiPy are NOT 5V tolerant, connecting them to voltages higher than 3.6V will cause irreparable damage to the board. ADC pins, when configured in analog mode cannot withstand voltages above 1.8V. Keep these considerations in mind when wiring your electronics. WLAN default behaviour ---------------------- When the WiPy boots with the default factory configuration starts in Access Point mode with ``ssid`` that starts with: ``wipy-wlan`` and ``key: www.wipy.io``. Connect to this network and the WiPy will be reachable at ``192.168.1.1``. In order to gain access to the interactive prompt, open a telnet session to that IP address on the default port (23). You will be asked for credentials: ``login: micro`` and ``password: python`` .. _wipy_telnet: Telnet REPL ----------- Linux stock telnet works like a charm (also on OSX), but other tools like putty work quite well too. The default credentials are: **user:** ``micro``, **password:** ``python``. See :class:`network.Server` for info on how to change the defaults. For instance, on a linux shell (when connected to the WiPy in AP mode):: $ telnet 192.168.1.1 .. _wipy_filesystem: Local file system and FTP access -------------------------------- There is a small internal file system (a drive) on the WiPy, called ``/flash``, which is stored within the external serial flash memory. If a micro SD card is hooked-up and mounted, it will be available as well. When the WiPy starts up, it always boots from the ``boot.py`` located in the ``/flash`` file system. On boot up, the current directory is ``/flash``. The file system is accessible via the native FTP server running in the WiPy. Open your FTP client of choice and connect to: **url:** ``ftp://192.168.1.1``, **user:** ``micro``, **password:** ``python`` See :class:`network.Server` for info on how to change the defaults. The recommended clients are: Linux stock FTP (also in OSX), Filezilla and FireFTP. For example, on a linux shell:: $ ftp 192.168.1.1 The FTP server on the WiPy doesn't support active mode, only passive, therefore, if using the native unix ftp client, just after logging in do:: ftp> passive Besides that, the FTP server only supports one data connection at a time. Check out the Filezilla settings section below for more info. FileZilla settings ------------------ Do not use the quick connect button, instead, open the site manager and create a new configuration. In the ``General`` tab make sure that encryption is set to: ``Only use plain FTP (insecure)``. In the Transfer Settings tab limit the max number of connections to one, otherwise FileZilla will try to open a second command connection when retrieving and saving files, and for simplicity and to reduce code size, only one command and one data connections are possible. Other FTP clients might behave in a similar way. .. _wipy_firmware_upgrade: Upgrading the firmware Over The Air ----------------------------------- OTA software updates can be performed through the FTP server. Upload the ``mcuimg.bin`` file to: ``/flash/sys/mcuimg.bin`` it will take around 6s. You won't see the file being stored inside ``/flash/sys/`` because it's actually saved bypassing the user file system, so it ends up inside the internal **hidden** file system, but rest assured that it was successfully transferred, and it has been signed with a MD5 checksum to verify its integrity. Now, reset the WiPy by pressing the switch on the board, or by typing:: >>> import machine >>> machine.reset() Software updates can be found in: https://github.com/wipy/wipy/releases (**Binaries.zip**). It's always recommended to update to the latest software, but make sure to read the **release notes** before. .. note:: The ``bootloader.bin`` found inside ``Binaries.zip`` is there only for reference, it's not needed for the Over The Air update. In order to check your software version, do:: >>> import os >>> os.uname().release If the version number is lower than the latest release found in `the releases `_, go ahead and update your WiPy! .. _wipy_boot_modes: Boot modes and safe boot ------------------------ If you power up normally, or press the reset button, the WiPy will boot into standard mode; the ``boot.py`` file will be executed first, then ``main.py`` will run. You can override this boot sequence by pulling ``GP28`` **up** (connect it to the 3v3 output pin) during reset. This procedure also allows going back in time to old firmware versions. The WiPy can hold up to 3 different firmware versions, which are: the factory firmware plus 2 user updates. After reset, if ``GP28`` is held high, the heartbeat LED will start flashing slowly, if after 3 seconds the pin is still being held high, the LED will start blinking a bit faster and the WiPy will select the previous user update to boot. If the previous user update is the desired firmware image, ``GP28`` must be released before 3 more seconds elapse. If 3 seconds later the pin is still high, the factory firmware will be selected, the LED will flash quickly for 1.5 seconds and the WiPy will proceed to boot. The firmware selection mechanism is as follows: **Safe Boot Pin** ``GP28`` **released during:** +-------------------------+-------------------------+----------------------------+ | 1st 3 secs window | 2nd 3 secs window | Final 1.5 secs window | +=========================+=========================+============================+ | | Safe boot, *latest* | | Safe boot, *previous* | | Safe boot, the *factory* | | | firmware is selected | | user update selected | | firmware is selected | +-------------------------+-------------------------+----------------------------+ On all of the above 3 scenarios, safe boot mode is entered, meaning that the execution of both ``boot.py`` and ``main.py`` is skipped. This is useful to recover from crash situations caused by the user scripts. The selection made during safe boot is not persistent, therefore after the next normal reset the latest firmware will run again. The heartbeat LED ------------------ By default the heartbeat LED flashes once every 4s to signal that the system is alive. This can be overridden through the :mod:`wipy` module:: >>> import wipy >>> wipy.heartbeat(False) There are currently 2 kinds of errors that you might see: 1. If the heartbeat LED flashes quickly, then a Python script (eg ``main.py``) has an error. Use the REPL to debug it. 2. If the heartbeat LED stays on, then there was a hard fault, you cannot recover from this, the only way out is to press the reset switch. Details on sleep modes ---------------------- * ``machine.idle()``: Power consumption: ~12mA (in WLAN STA mode). Wake sources: any hardware interrupt (including systick with period of 1ms), no special configuration required. * ``machine.lightsleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC`` and ``WLAN`` * ``machine.deepsleep()``: ~350uA. Wake sources are ``Pin`` and ``RTC``. Additional details for machine.Pin ---------------------------------- On the WiPy board the pins are identified by their string id:: from machine import Pin g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1) You can also configure the Pin to generate interrupts. For instance:: from machine import Pin def pincb(pin): print(pin.id()) pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN) pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb) # the callback can be triggered manually pin_int.irq()() # to disable the callback pin_int.irq().disable() Now every time a falling edge is seen on the gpio pin, the callback will be executed. Caution: mechanical push buttons have "bounce" and pushing or releasing a switch will often generate multiple edges. See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed explanation, along with various techniques for debouncing. All pin objects go through the pin mapper to come up with one of the gpio pins. For the ``drive`` parameter the strengths are: - ``Pin.LOW_POWER`` - 2mA drive capability. - ``Pin.MED_POWER`` - 4mA drive capability. - ``Pin.HIGH_POWER`` - 6mA drive capability. For the ``alt`` parameter please refer to the pinout and alternate functions table at `_ for the specific alternate functions that each pin supports. For interrupts, the ``priority`` can take values in the range 1-7. And the ``wake`` parameter has the following properties: - If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board. - If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``, ``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1 of this pins can be enabled as a wake source at the same time, so, only the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect. - If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``, ``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the 6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time. Additional Pin methods: .. method:: machine.Pin.alt_list() Returns a list of the alternate functions supported by the pin. List items are a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)`` Additional details for machine.I2C ---------------------------------- On the WiPy there is a single hardware I2C peripheral, identified by "0". By default this is the peripheral that is used when constructing an I2C instance. The default pins are GP23 for SCL and GP13 for SDA, and one can create the default I2C peripheral simply by doing:: i2c = machine.I2C() The pins and frequency can be specified as:: i2c = machine.I2C(freq=400000, scl='GP23', sda='GP13') Only certain pins can be used as SCL/SDA. Please refer to the pinout for further information. Known issues ------------ Incompatible way to create SSL sockets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SSL sockets need to be created the following way before wrapping them with. ``ssl.wrap_socket``:: import socket import ssl s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) ss = ssl.wrap_socket(s) Certificates must be used in order to validate the other side of the connection, and also to authenticate ourselves with the other end. Such certificates must be stored as files using the FTP server, and they must be placed in specific paths with specific names. - The certificate to validate the other side goes in: **'/flash/cert/ca.pem'** - The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'** - The key for our own certificate goes in: **'/flash/cert/private.key'** .. note:: When these files are stored, they are placed inside the internal **hidden** file system (just like firmware updates), and therefore they are never visible. For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located in the `blynk examples folder `_. and put it in '/flash/cert/'. Then do:: import socket import ssl s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem') ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1]) Incompatibilities in uhashlib module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Due to hardware implementation details of the WiPy, data must be buffered before being digested, which would make it impossible to calculate the hash of big blocks of data that do not fit in RAM. In this case, since most likely the total size of the data is known in advance, the size can be passed to the constructor and hence the HASH hardware engine of the WiPy can be properly initialized without needing buffering. If ``block_size`` is to be given, an initial chunk of ``data`` must be passed as well. **When using this extension, care must be taken to make sure that the length of all intermediate chunks (including the initial one) is a multiple of 4 bytes.** The last chunk may be of any length. Example:: hash = uhashlib.sha1('abcd1234', 1001) # length of the initial piece is multiple of 4 bytes hash.update('1234') # also multiple of 4 bytes ... hash.update('12345') # last chunk may be of any length hash.digest() Unrelated function in machine module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. function:: main(filename) Set the filename of the main script to run after boot.py is finished. If this function is not called then the default file main.py will be executed. It only makes sense to call this function from within boot.py. Adhoc way to control telnet/FTP server via network module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``Server`` class controls the behaviour and the configuration of the FTP and telnet services running on the WiPy. Any changes performed using this class' methods will affect both. Example:: import network server = network.Server() server.deinit() # disable the server # enable the server again with new settings server.init(login=('user', 'password'), timeout=600) .. class:: network.Server(id, ...) Create a server instance, see ``init`` for parameters of initialization. .. method:: server.init(\*, login=('micro', 'python'), timeout=300) Init (and effectively start the server). Optionally a new ``user``, ``password`` and ``timeout`` (in seconds) can be passed. .. method:: server.deinit() Stop the server .. method:: server.timeout([timeout_in_seconds]) Get or set the server timeout. .. method:: server.isrunning() Returns ``True`` if the server is running, ``False`` otherwise. Adhoc VFS-like support ~~~~~~~~~~~~~~~~~~~~~~ WiPy doesn't implement full MicroPython VFS support, instead following functions are defined in ``uos`` module: .. function:: mount(block_device, mount_point, \*, readonly=False) Mounts a block device (like an ``SD`` object) in the specified mount point. Example:: os.mount(sd, '/sd') .. function:: unmount(path) Unmounts a previously mounted block device from the given path. .. function:: mkfs(block_device or path) Formats the specified path, must be either ``/flash`` or ``/sd``. A block device can also be passed like an ``SD`` object before being mounted. micropython-1.12/docs/wipy/quickref.rst000066400000000000000000000141561357706137100203140ustar00rootroot00000000000000.. _wipy_quickref: Quick reference for the WiPy ============================ .. image:: https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png :alt: WiPy pinout and alternate functions table :width: 800px Below is a quick reference for CC3200/WiPy. If it is your first time working with this board please consider reading the following sections first: .. toctree:: :maxdepth: 1 general.rst tutorial/index.rst General board control (including sleep modes) --------------------------------------------- See the :mod:`machine` module:: import machine help(machine) # display all members from the machine module machine.freq() # get the CPU frequency machine.unique_id() # return the 6-byte unique id of the board (the WiPy's MAC address) machine.idle() # average current decreases to (~12mA), any interrupts wake it up machine.lightsleep() # everything except for WLAN is powered down (~950uA avg. current) # wakes from Pin, RTC or WLAN machine.deepsleep() # deepest sleep mode, MCU starts from reset. Wakes from Pin and RTC. Pins and GPIO ------------- See :ref:`machine.Pin `. :: from machine import Pin # initialize GP2 in gpio mode (alt=0) and make it an output p_out = Pin('GP2', mode=Pin.OUT) p_out.value(1) p_out.value(0) p_out.toggle() p_out(True) # make GP1 an input with the pull-up enabled p_in = Pin('GP1', mode=Pin.IN, pull=Pin.PULL_UP) p_in() # get value, 0 or 1 Timers ------ See :ref:`machine.TimerWiPy ` and :ref:`machine.Pin `. Timer ``id``'s take values from 0 to 3.:: from machine import Timer from machine import Pin tim = Timer(0, mode=Timer.PERIODIC) tim_a = tim.channel(Timer.A, freq=1000) tim_a.freq(5) # 5 Hz p_out = Pin('GP2', mode=Pin.OUT) tim_a.irq(trigger=Timer.TIMEOUT, handler=lambda t: p_out.toggle()) PWM (pulse width modulation) ---------------------------- See :ref:`machine.Pin ` and :ref:`machine.Timer `. :: from machine import Timer # timer 1 in PWM mode and width must be 16 buts tim = Timer(1, mode=Timer.PWM, width=16) # enable channel A @1KHz with a 50.55% duty cycle tim_a = tim.channel(Timer.A, freq=1000, duty_cycle=5055) ADC (analog to digital conversion) ---------------------------------- See :ref:`machine.ADCWiPy `. :: from machine import ADC adc = ADC() apin = adc.channel(pin='GP3') apin() # read value, 0-4095 UART (serial bus) ----------------- See :ref:`machine.UART `. :: from machine import UART uart = UART(0, baudrate=9600) uart.write('hello') uart.read(5) # read up to 5 bytes SPI bus ------- See :ref:`machine.SPI `. :: from machine import SPI # configure the SPI master @ 2MHz spi = SPI(0, SPI.MASTER, baudrate=200000, polarity=0, phase=0) spi.write('hello') spi.read(5) # receive 5 bytes on the bus rbuf = bytearray(5) spi.write_readinto('hello', rbuf) # send and receive 5 bytes I2C bus ------- See :ref:`machine.I2C `. :: from machine import I2C # configure the I2C bus i2c = I2C(baudrate=100000) i2c.scan() # returns list of slave addresses i2c.writeto(0x42, 'hello') # send 5 bytes to slave with address 0x42 i2c.readfrom(0x42, 5) # receive 5 bytes from slave i2c.readfrom_mem(0x42, 0x10, 2) # read 2 bytes from slave 0x42, slave memory 0x10 i2c.writeto_mem(0x42, 0x10, 'xy') # write 2 bytes to slave 0x42, slave memory 0x10 Watchdog timer (WDT) -------------------- See :ref:`machine.WDT `. :: from machine import WDT # enable the WDT with a timeout of 5s (1s is the minimum) wdt = WDT(timeout=5000) wdt.feed() Real time clock (RTC) --------------------- See :ref:`machine.RTC ` :: from machine import RTC rtc = RTC() # init with default time and date rtc = RTC(datetime=(2015, 8, 29, 9, 0, 0, 0, None)) # init with a specific time and date print(rtc.now()) def alarm_handler (rtc_o): pass # do some non blocking operations # warning printing on an irq via telnet is not # possible, only via UART # create a RTC alarm that expires after 5 seconds rtc.alarm(time=5000, repeat=False) # enable RTC interrupts rtc_i = rtc.irq(trigger=RTC.ALARM0, handler=alarm_handler, wake=machine.SLEEP) # go into suspended mode waiting for the RTC alarm to expire and wake us up machine.lightsleep() SD card ------- See :ref:`machine.SD `. :: from machine import SD import os # clock pin, cmd pin, data0 pin sd = SD(pins=('GP10', 'GP11', 'GP15')) # or use default ones for the expansion board sd = SD() os.mount(sd, '/sd') WLAN (WiFi) ----------- See :ref:`network.WLAN ` and :mod:`machine`. :: import machine from network import WLAN # configure the WLAN subsystem in station mode (the default is AP) wlan = WLAN(mode=WLAN.STA) # go for fixed IP settings wlan.ifconfig(config=('192.168.0.107', '255.255.255.0', '192.168.0.1', '8.8.8.8')) wlan.scan() # scan for available networks wlan.connect(ssid='mynetwork', auth=(WLAN.WPA2, 'mynetworkkey')) while not wlan.isconnected(): pass print(wlan.ifconfig()) # enable wake on WLAN wlan.irq(trigger=WLAN.ANY_EVENT, wake=machine.SLEEP) # go to sleep machine.lightsleep() # now, connect to the FTP or the Telnet server and the WiPy will wake-up Telnet and FTP server --------------------- See :class:`network.Server` :: from network import Server # init with new user, password and seconds timeout server = Server(login=('user', 'password'), timeout=60) server.timeout(300) # change the timeout server.timeout() # get the timeout server.isrunning() # check whether the server is running or not Heart beat LED -------------- See :mod:`wipy`. :: import wipy wipy.heartbeat(False) # disable the heartbeat LED wipy.heartbeat(True) # enable the heartbeat LED wipy.heartbeat() # get the heartbeat state micropython-1.12/docs/wipy/tutorial/000077500000000000000000000000001357706137100176055ustar00rootroot00000000000000micropython-1.12/docs/wipy/tutorial/blynk.rst000066400000000000000000000017531357706137100214640ustar00rootroot00000000000000Getting started with Blynk and the WiPy --------------------------------------- Blynk provides iOS and Android apps to control any hardware over the Internet or directly using Bluetooth. You can easily build graphic interfaces for all your projects by simply dragging and dropping widgets, right on your smartphone. Before anything else, make sure that your WiPy is running the latest software, check :ref:`OTA How-To ` for instructions. 1. Get the `Blynk library `_ and put it in ``/flash/lib/`` via FTP. 2. Get the `Blynk example for WiPy `_, edit the network settings, and afterwards upload it to ``/flash/`` via FTP as well. 3. Follow the instructions on each example to setup the Blynk dashboard on your smartphone or tablet. 4. Give it a try, for instance:: >>> execfile('sync_virtual.py') micropython-1.12/docs/wipy/tutorial/index.rst000066400000000000000000000005131357706137100214450ustar00rootroot00000000000000.. _wipy_tutorial: WiPy tutorials and examples =========================== Before starting, make sure that you are running the latest firmware, for instructions see :ref:`OTA How-To `. .. toctree:: :maxdepth: 1 :numbered: intro.rst repl.rst blynk.rst wlan.rst timer.rst reset.rst micropython-1.12/docs/wipy/tutorial/intro.rst000066400000000000000000000051641357706137100215000ustar00rootroot00000000000000Introduction to the WiPy ======================== To get the most out of your WiPy, there are a few basic things to understand about how it works. Caring for your WiPy and expansion board ---------------------------------------- Because the WiPy/expansion board does not have a housing it needs a bit of care: - Be gentle when plugging/unplugging the USB cable. Whilst the USB connector is well soldered and is relatively strong, if it breaks off it can be very difficult to fix. - Static electricity can shock the components on the WiPy and destroy them. If you experience a lot of static electricity in your area (eg dry and cold climates), take extra care not to shock the WiPy. If your WiPy came in a ESD bag, then this bag is the best way to store and carry the WiPy as it will protect it against static discharges. As long as you take care of the hardware, you should be okay. It's almost impossible to break the software on the WiPy, so feel free to play around with writing code as much as you like. If the filesystem gets corrupt, see below on how to reset it. In the worst case you might need to do a safe boot, which is explained in detail in :ref:`wipy_boot_modes`. Plugging into the expansion board and powering on ------------------------------------------------- The expansion board can power the WiPy via USB. The WiPy comes with a sticker on top of the RF shield that labels all pins, and this should match the label numbers on the expansion board headers. When plugging it in, the WiPy antenna will end up on top of the SD card connector of the expansion board. A video showing how to do this can be found `here on YouTube `_. Expansion board hardware guide ------------------------------ The document explaining the hardware details of the expansion board can be found `in this PDF `_. Powering by an external power source ------------------------------------ The WiPy can be powered by a battery or other external power source. **Be sure to connect the positive lead of the power supply to VIN, and ground to GND. There is no polarity protection on the WiPy so you must be careful when connecting anything to VIN.** - When powering via ``VIN``: **The input voltage must be between 3.6V and 5.5V.** - When powering via ``3V3``: **The input voltage must be exactly 3V3, ripple free and from a supply capable of sourcing at least 300mA of current** Performing firmware upgrades ---------------------------- For detailed instructions see :ref:`OTA How-To `. micropython-1.12/docs/wipy/tutorial/repl.rst000066400000000000000000000104001357706137100212740ustar00rootroot00000000000000Getting a MicroPython REPL prompt ================================= REPL stands for Read Evaluate Print Loop, and is the name given to the interactive MicroPython prompt that you can access on the WiPy. Using the REPL is by far the easiest way to test out your code and run commands. You can use the REPL in addition to writing scripts in ``main.py``. .. _wipy_uart: To use the REPL, you must connect to the WiPy either via :ref:`telnet `, or with a USB to serial converter wired to one of the two UARTs on the WiPy. To enable REPL duplication on UART0 (the one accessible via the expansion board) do:: >>> from machine import UART >>> import os >>> uart = UART(0, 115200) >>> os.dupterm(uart) Place this piece of code inside your ``boot.py`` so that it's done automatically after reset. Windows ------- First you need to install the FTDI drivers for the expansion board's USB to serial converter. Then you need a terminal software. The best option is to download the free program PuTTY: `putty.exe `_. **In order to get to the telnet REPL:** Using putty, select ``Telnet`` as connection type, leave the default port (23) and enter the IP address of your WiPy (192.168.1.1 when in ``WLAN.AP`` mode), then click open. **In order to get to the REPL UART:** Using your serial program you must connect to the COM port that you found in the previous step. With PuTTY, click on "Session" in the left-hand panel, then click the "Serial" radio button on the right, then enter you COM port (eg COM4) in the "Serial Line" box. Finally, click the "Open" button. Mac OS X -------- Open a terminal and run:: $ telnet 192.168.1.1 or:: $ screen /dev/tty.usbmodem* 115200 When you are finished and want to exit ``screen``, type CTRL-A CTRL-\\. If your keyboard does not have a \\-key (i.e. you need an obscure combination for \\ like ALT-SHIFT-7) you can remap the ``quit`` command: - create ``~/.screenrc`` - add ``bind q quit`` This will allow you to quit ``screen`` by hitting CTRL-A Q. Linux ----- Open a terminal and run:: $ telnet 192.168.1.1 or:: $ screen /dev/ttyUSB0 115200 You can also try ``picocom`` or ``minicom`` instead of screen. You may have to use ``/dev/ttyUSB01`` or a higher number for ``ttyUSB``. And, you may need to give yourself the correct permissions to access this devices (eg group ``uucp`` or ``dialout``, or use sudo). Using the REPL prompt --------------------- Now let's try running some MicroPython code directly on the WiPy. With your serial program open (PuTTY, screen, picocom, etc) you may see a blank screen with a flashing cursor. Press Enter and you should be presented with a MicroPython prompt, i.e. ``>>>``. Let's make sure it is working with the obligatory test:: >>> print("hello WiPy!") hello WiPy! In the above, you should not type in the ``>>>`` characters. They are there to indicate that you should type the text after it at the prompt. In the end, once you have entered the text ``print("hello WiPy!")`` and pressed Enter, the output on your screen should look like it does above. If you already know some Python you can now try some basic commands here. If any of this is not working you can try either a hard reset or a soft reset; see below. Go ahead and try typing in some other commands. For example:: >>> from machine import Pin >>> import wipy >>> wipy.heartbeat(False) # disable the heartbeat >>> led = Pin('GP25', mode=Pin.OUT) >>> led(1) >>> led(0) >>> led.toggle() >>> 1 + 2 3 >>> 4 // 2 2 >>> 20 * 'py' 'pypypypypypypypypypypypypypypypypypypypy' Resetting the board ------------------- If something goes wrong, you can reset the board in two ways. The first is to press CTRL-D at the MicroPython prompt, which performs a soft reset. You will see a message something like:: >>> MPY: soft reboot MicroPython v1.4.6-146-g1d8b5e5 on 2015-10-21; WiPy with CC3200 Type "help()" for more information. >>> If that isn't working you can perform a hard reset (turn-it-off-and-on-again) by pressing the RST switch (the small black button next to the heartbeat LED). During telnet, this will end your session, disconnecting whatever program that you used to connect to the WiPy. micropython-1.12/docs/wipy/tutorial/reset.rst000066400000000000000000000034151357706137100214640ustar00rootroot00000000000000Reset and boot modes ==================== There are soft resets and hard resets. - A soft reset simply clears the state of the MicroPython virtual machine, but leaves hardware peripherals unaffected. To do a soft reset, simply press **Ctrl+D** on the REPL, or within a script do:: import sys sys.exit() - A hard reset is the same as performing a power cycle to the board. In order to hard reset the WiPy, press the switch on the board or:: import machine machine.reset() Safe boot --------- If something goes wrong with your WiPy, don't panic! It is almost impossible for you to break the WiPy by programming the wrong thing. The first thing to try is to boot in safe mode: this temporarily skips execution of ``boot.py`` and ``main.py`` and gives default WLAN settings. If you have problems with the filesystem you can :ref:`format the internal flash drive `. To boot in safe mode, follow the detailed instructions described :ref:`here `. In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so the WiPy boots up with default settings. This means you now have access to the filesystem, and you can edit ``boot.py`` and ``main.py`` to fix any problems. Entering safe mode is temporary, and does not make any changes to the files on the WiPy. .. _wipy_factory_reset: Factory reset the filesystem ---------------------------- If you WiPy's filesystem gets corrupted (very unlikely, but possible), you can format it very easily by doing:: >>> import os >>> os.mkfs('/flash') Resetting the filesystem deletes all files on the internal WiPy storage (not the SD card), and restores the files ``boot.py`` and ``main.py`` back to their original state after the next reset. micropython-1.12/docs/wipy/tutorial/timer.rst000066400000000000000000000061201357706137100214560ustar00rootroot00000000000000Hardware timers =============== Timers can be used for a great variety of tasks, calling a function periodically, counting events, and generating a PWM signal are among the most common use cases. Each timer consists of two 16-bit channels and this channels can be tied together to form one 32-bit timer. The operating mode needs to be configured per timer, but then the period (or the frequency) can be independently configured on each channel. By using the callback method, the timer event can call a Python function. Example usage to toggle an LED at a fixed frequency:: from machine import Timer from machine import Pin led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED tim = Timer(3) # create a timer object using timer 3 tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode tim_ch = tim.channel(Timer.A, freq=5) # configure channel A at a frequency of 5Hz tim_ch.irq(handler=lambda t:led.toggle(), trigger=Timer.TIMEOUT) # toggle a LED on every cycle of the timer Example using named function for the callback:: from machine import Timer from machine import Pin tim = Timer(1, mode=Timer.PERIODIC, width=32) tim_a = tim.channel(Timer.A | Timer.B, freq=1) # 1 Hz frequency requires a 32 bit timer led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED def tick(timer): # we will receive the timer object when being called global led led.toggle() # toggle the LED tim_a.irq(handler=tick, trigger=Timer.TIMEOUT) # create the interrupt Further examples:: from machine import Timer tim1 = Timer(1, mode=Timer.ONE_SHOT) # initialize it in one shot mode tim2 = Timer(2, mode=Timer.PWM) # initialize it in PWM mode tim1_ch = tim1.channel(Timer.A, freq=10, polarity=Timer.POSITIVE) # start the event counter with a frequency of 10Hz and triggered by positive edges tim2_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=5000) # start the PWM on channel B with a 50% duty cycle tim2_ch.freq(20) # set the frequency (can also get) tim2_ch.duty_cycle(3010) # set the duty cycle to 30.1% (can also get) tim2_ch.duty_cycle(3020, Timer.NEGATIVE) # set the duty cycle to 30.2% and change the polarity to negative tim2_ch.period(2000000) # change the period to 2 seconds Additional constants for Timer class ------------------------------------ .. data:: Timer.PWM PWM timer operating mode. .. data:: Timer.A .. data:: Timer.B Selects the timer channel. Must be ORed (``Timer.A`` | ``Timer.B``) when using a 32-bit timer. .. data:: Timer.POSITIVE .. data:: Timer.NEGATIVE Timer channel polarity selection (only relevant in PWM mode). .. data:: Timer.TIMEOUT .. data:: Timer.MATCH Timer channel IRQ triggers. micropython-1.12/docs/wipy/tutorial/wlan.rst000066400000000000000000000051271357706137100213050ustar00rootroot00000000000000WLAN step by step ================= The WLAN is a system feature of the WiPy, therefore it is always enabled (even while in ``machine.SLEEP``), except when deepsleep mode is entered. In order to retrieve the current WLAN instance, do:: >>> from network import WLAN >>> wlan = WLAN() # we call the constructor without params You can check the current mode (which is always ``WLAN.AP`` after power up):: >>> wlan.mode() .. warning:: When you change the WLAN mode following the instructions below, your WLAN connection to the WiPy will be broken. This means you will not be able to run these commands interactively over the WLAN. There are two ways around this:: 1. put this setup code into your :ref:`boot.py file` so that it gets executed automatically after reset. 2. :ref:`duplicate the REPL on UART `, so that you can run commands via USB. Connecting to your home router ------------------------------ The WLAN network card always boots in ``WLAN.AP`` mode, so we must first configure it as a station:: from network import WLAN wlan = WLAN(mode=WLAN.STA) Now you can proceed to scan for networks:: nets = wlan.scan() for net in nets: if net.ssid == 'mywifi': print('Network found!') wlan.connect(net.ssid, auth=(net.sec, 'mywifikey'), timeout=5000) while not wlan.isconnected(): machine.idle() # save power while waiting print('WLAN connection succeeded!') break Assigning a static IP address when booting ------------------------------------------ If you want your WiPy to connect to your home router after boot-up, and with a fixed IP address so that you can access it via telnet or FTP, use the following script as /flash/boot.py:: import machine from network import WLAN wlan = WLAN() # get current object, without changing the mode if machine.reset_cause() != machine.SOFT_RESET: wlan.init(WLAN.STA) # configuration below MUST match your home router settings!! wlan.ifconfig(config=('192.168.178.107', '255.255.255.0', '192.168.178.1', '8.8.8.8')) if not wlan.isconnected(): # change the line below to match your network ssid, security and password wlan.connect('mywifi', auth=(WLAN.WPA2, 'mywifikey'), timeout=5000) while not wlan.isconnected(): machine.idle() # save power while waiting .. note:: Notice how we check for the reset cause and the connection status, this is crucial in order to be able to soft reset the WiPy during a telnet session without breaking the connection. micropython-1.12/drivers/000077500000000000000000000000001357706137100155005ustar00rootroot00000000000000micropython-1.12/drivers/README.md000066400000000000000000000001601357706137100167540ustar00rootroot00000000000000This directory contains drivers for specific hardware. The drivers are intended to work across multiple ports. micropython-1.12/drivers/bus/000077500000000000000000000000001357706137100162715ustar00rootroot00000000000000micropython-1.12/drivers/bus/qspi.h000066400000000000000000000042571357706137100174260ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H #define MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H #include "py/mphal.h" enum { MP_QSPI_IOCTL_INIT, MP_QSPI_IOCTL_DEINIT, MP_QSPI_IOCTL_BUS_ACQUIRE, MP_QSPI_IOCTL_BUS_RELEASE, }; typedef struct _mp_qspi_proto_t { int (*ioctl)(void *self, uint32_t cmd); void (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data); void (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src); uint32_t (*read_cmd)(void *self, uint8_t cmd, size_t len); void (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest); } mp_qspi_proto_t; typedef struct _mp_soft_qspi_obj_t { mp_hal_pin_obj_t cs; mp_hal_pin_obj_t clk; mp_hal_pin_obj_t io0; mp_hal_pin_obj_t io1; mp_hal_pin_obj_t io2; mp_hal_pin_obj_t io3; } mp_soft_qspi_obj_t; extern const mp_qspi_proto_t mp_soft_qspi_proto; #endif // MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H micropython-1.12/drivers/bus/softqspi.c000066400000000000000000000162001357706137100203040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "drivers/bus/qspi.h" #define CS_LOW(self) mp_hal_pin_write(self->cs, 0) #define CS_HIGH(self) mp_hal_pin_write(self->cs, 1) #ifdef MICROPY_HW_SOFTQSPI_SCK_LOW // Use externally provided functions for SCK control and IO reading #define SCK_LOW(self) MICROPY_HW_SOFTQSPI_SCK_LOW(self) #define SCK_HIGH(self) MICROPY_HW_SOFTQSPI_SCK_HIGH(self) #define NIBBLE_READ(self) MICROPY_HW_SOFTQSPI_NIBBLE_READ(self) #else // Use generic pin functions for SCK control and IO reading #define SCK_LOW(self) mp_hal_pin_write(self->clk, 0) #define SCK_HIGH(self) mp_hal_pin_write(self->clk, 1) #define NIBBLE_READ(self) ( \ mp_hal_pin_read(self->io0) \ | (mp_hal_pin_read(self->io1) << 1) \ | (mp_hal_pin_read(self->io2) << 2) \ | (mp_hal_pin_read(self->io3) << 3)) #endif STATIC void nibble_write(mp_soft_qspi_obj_t *self, uint8_t v) { mp_hal_pin_write(self->io0, v & 1); mp_hal_pin_write(self->io1, (v >> 1) & 1); mp_hal_pin_write(self->io2, (v >> 2) & 1); mp_hal_pin_write(self->io3, (v >> 3) & 1); } STATIC int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; switch (cmd) { case MP_QSPI_IOCTL_INIT: mp_hal_pin_high(self->cs); mp_hal_pin_output(self->cs); // Configure pins mp_hal_pin_write(self->clk, 0); mp_hal_pin_output(self->clk); //mp_hal_pin_write(self->clk, 1); mp_hal_pin_output(self->io0); mp_hal_pin_input(self->io1); mp_hal_pin_write(self->io2, 1); mp_hal_pin_output(self->io2); mp_hal_pin_write(self->io3, 1); mp_hal_pin_output(self->io3); break; } return 0; // success } STATIC void mp_soft_qspi_transfer(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest) { // Will run as fast as possible, limited only by CPU speed and GPIO time mp_hal_pin_input(self->io1); mp_hal_pin_output(self->io0); if (self->io3) { mp_hal_pin_write(self->io2, 1); mp_hal_pin_output(self->io2); mp_hal_pin_write(self->io3, 1); mp_hal_pin_output(self->io3); } if (src) { for (size_t i = 0; i < len; ++i) { uint8_t data_out = src[i]; uint8_t data_in = 0; for (int j = 0; j < 8; ++j, data_out <<= 1) { mp_hal_pin_write(self->io0, (data_out >> 7) & 1); mp_hal_pin_write(self->clk, 1); data_in = (data_in << 1) | mp_hal_pin_read(self->io1); mp_hal_pin_write(self->clk, 0); } if (dest != NULL) { dest[i] = data_in; } } } else { for (size_t i = 0; i < len; ++i) { uint8_t data_in = 0; for (int j = 0; j < 8; ++j) { mp_hal_pin_write(self->clk, 1); data_in = (data_in << 1) | mp_hal_pin_read(self->io1); mp_hal_pin_write(self->clk, 0); } if (dest != NULL) { dest[i] = data_in; } } } } STATIC void mp_soft_qspi_qread(mp_soft_qspi_obj_t *self, size_t len, uint8_t *buf) { // Make all IO lines input mp_hal_pin_input(self->io2); mp_hal_pin_input(self->io3); mp_hal_pin_input(self->io0); mp_hal_pin_input(self->io1); // Will run as fast as possible, limited only by CPU speed and GPIO time while (len--) { SCK_HIGH(self); uint8_t data_in = NIBBLE_READ(self); SCK_LOW(self); SCK_HIGH(self); *buf++ = (data_in << 4) | NIBBLE_READ(self); SCK_LOW(self); } } STATIC void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *buf) { // Make all IO lines output mp_hal_pin_output(self->io2); mp_hal_pin_output(self->io3); mp_hal_pin_output(self->io0); mp_hal_pin_output(self->io1); // Will run as fast as possible, limited only by CPU speed and GPIO time for (size_t i = 0; i < len; ++i) { nibble_write(self, buf[i] >> 4); SCK_HIGH(self); SCK_LOW(self); nibble_write(self, buf[i]); SCK_HIGH(self); SCK_LOW(self); } //mp_hal_pin_input(self->io1); } STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; uint32_t cmd_buf = cmd | data << 8; CS_LOW(self); mp_soft_qspi_transfer(self, 1 + len, (uint8_t*)&cmd_buf, NULL); CS_HIGH(self); } STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; uint8_t cmd_buf[4] = {cmd, addr >> 16, addr >> 8, addr}; CS_LOW(self); mp_soft_qspi_transfer(self, 4, cmd_buf, NULL); mp_soft_qspi_transfer(self, len, src, NULL); CS_HIGH(self); } STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; uint32_t cmd_buf = cmd; CS_LOW(self); mp_soft_qspi_transfer(self, 1 + len, (uint8_t*)&cmd_buf, (uint8_t*)&cmd_buf); CS_HIGH(self); return cmd_buf >> 8; } STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; uint8_t cmd_buf[7] = {cmd, addr >> 16, addr >> 8, addr}; CS_LOW(self); mp_soft_qspi_transfer(self, 1, cmd_buf, NULL); mp_soft_qspi_qwrite(self, 6, &cmd_buf[1]); // 3 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles) mp_soft_qspi_qread(self, len, dest); CS_HIGH(self); } const mp_qspi_proto_t mp_soft_qspi_proto = { .ioctl = mp_soft_qspi_ioctl, .write_cmd_data = mp_soft_qspi_write_cmd_data, .write_cmd_addr_data = mp_soft_qspi_write_cmd_addr_data, .read_cmd = mp_soft_qspi_read_cmd, .read_cmd_qaddr_qdata = mp_soft_qspi_read_cmd_qaddr_qdata, }; micropython-1.12/drivers/bus/softspi.c000066400000000000000000000075311357706137100201320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "drivers/bus/spi.h" int mp_soft_spi_ioctl(void *self_in, uint32_t cmd) { mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t*)self_in; switch (cmd) { case MP_SPI_IOCTL_INIT: mp_hal_pin_write(self->sck, self->polarity); mp_hal_pin_output(self->sck); mp_hal_pin_output(self->mosi); mp_hal_pin_input(self->miso); break; case MP_SPI_IOCTL_DEINIT: break; } return 0; } void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) { mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t*)self_in; uint32_t delay_half = self->delay_half; // only MSB transfer is implemented // If a port defines MICROPY_HW_SOFTSPI_MIN_DELAY, and the configured // delay_half is equal to this value, then the software SPI implementation // will run as fast as possible, limited only by CPU speed and GPIO time. #ifdef MICROPY_HW_SOFTSPI_MIN_DELAY if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) { for (size_t i = 0; i < len; ++i) { uint8_t data_out = src[i]; uint8_t data_in = 0; for (int j = 0; j < 8; ++j, data_out <<= 1) { mp_hal_pin_write(self->mosi, (data_out >> 7) & 1); mp_hal_pin_write(self->sck, 1 - self->polarity); data_in = (data_in << 1) | mp_hal_pin_read(self->miso); mp_hal_pin_write(self->sck, self->polarity); } if (dest != NULL) { dest[i] = data_in; } } return; } #endif for (size_t i = 0; i < len; ++i) { uint8_t data_out = src[i]; uint8_t data_in = 0; for (int j = 0; j < 8; ++j, data_out <<= 1) { mp_hal_pin_write(self->mosi, (data_out >> 7) & 1); if (self->phase == 0) { mp_hal_delay_us_fast(delay_half); mp_hal_pin_write(self->sck, 1 - self->polarity); } else { mp_hal_pin_write(self->sck, 1 - self->polarity); mp_hal_delay_us_fast(delay_half); } data_in = (data_in << 1) | mp_hal_pin_read(self->miso); if (self->phase == 0) { mp_hal_delay_us_fast(delay_half); mp_hal_pin_write(self->sck, self->polarity); } else { mp_hal_pin_write(self->sck, self->polarity); mp_hal_delay_us_fast(delay_half); } } if (dest != NULL) { dest[i] = data_in; } } } const mp_spi_proto_t mp_soft_spi_proto = { .ioctl = mp_soft_spi_ioctl, .transfer = mp_soft_spi_transfer, }; micropython-1.12/drivers/bus/spi.h000066400000000000000000000040021357706137100172310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_DRIVERS_BUS_SPI_H #define MICROPY_INCLUDED_DRIVERS_BUS_SPI_H #include "py/mphal.h" enum { MP_SPI_IOCTL_INIT, MP_SPI_IOCTL_DEINIT, }; typedef struct _mp_spi_proto_t { int (*ioctl)(void *self, uint32_t cmd); void (*transfer)(void *self, size_t len, const uint8_t *src, uint8_t *dest); } mp_spi_proto_t; typedef struct _mp_soft_spi_obj_t { uint32_t delay_half; // microsecond delay for half SCK period uint8_t polarity; uint8_t phase; mp_hal_pin_obj_t sck; mp_hal_pin_obj_t mosi; mp_hal_pin_obj_t miso; } mp_soft_spi_obj_t; extern const mp_spi_proto_t mp_soft_spi_proto; int mp_soft_spi_ioctl(void *self, uint32_t cmd); void mp_soft_spi_transfer(void *self, size_t len, const uint8_t *src, uint8_t *dest); #endif // MICROPY_INCLUDED_DRIVERS_BUS_SPI_H micropython-1.12/drivers/cc3000/000077500000000000000000000000001357706137100163705ustar00rootroot00000000000000micropython-1.12/drivers/cc3000/inc/000077500000000000000000000000001357706137100171415ustar00rootroot00000000000000micropython-1.12/drivers/cc3000/inc/cc3000_common.h000066400000000000000000000325521357706137100215610ustar00rootroot00000000000000/***************************************************************************** * * cc3000_common.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_COMMON_H__ #define __CC3000_COMMON_H__ #include "data_types.h" //****************************************************************************** // Include files //****************************************************************************** #include #include //***************************************************************************** // Prefix exported names to avoid name clash //***************************************************************************** #define CC3000_EXPORT(name) cc3000_ ## name //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif extern int CC3000_EXPORT(errno); //***************************************************************************** // ERROR CODES //***************************************************************************** #define ESUCCESS 0 #define EFAIL -1 #define EERROR EFAIL //***************************************************************************** // COMMON DEFINES //***************************************************************************** #define ERROR_SOCKET_INACTIVE -57 #define WLAN_ENABLE (1) #define WLAN_DISABLE (0) #define MAC_ADDR_LEN (6) #define SP_PORTION_SIZE (32) /*Defines for minimal and maximal RX buffer size. This size includes the spi header and hci header. The maximal buffer size derives from: MTU + HCI header + SPI header + sendto() agrs size The minimum buffer size derives from: HCI header + SPI header + max args size This buffer is used for receiving events and data. The packet can not be longer than MTU size and CC3000 does not support fragmentation. Note that the same buffer is used for reception of the data and events from CC3000. That is why the minimum is defined. The calculation for the actual size of buffer for reception is: Given the maximal data size MAX_DATA that is expected to be received by application, the required buffer is: Using recv() or recvfrom(): max(CC3000_MINIMAL_RX_SIZE, MAX_DATA + HEADERS_SIZE_DATA + fromlen + ucArgsize + 1) Using gethostbyname() with minimal buffer size will limit the host name returned to 99 bytes only. The 1 is used for the overrun detection Buffer size increased to 130 following the add_profile() with WEP security which requires TX buffer size of 130 bytes: HEADERS_SIZE_EVNT + WLAN_ADD_PROFILE_WEP_PARAM_LEN + MAX SSID LEN + 4 * MAX KEY LEN = 130 MAX SSID LEN = 32 MAX SSID LEN = 13 (with add_profile only ascii key setting is supported, therfore maximum key size is 13) */ #define CC3000_MINIMAL_RX_SIZE (130 + 1) #define CC3000_MAXIMAL_RX_SIZE (1519 + 1) /*Defines for minimal and maximal TX buffer size. This buffer is used for sending events and data. The packet can not be longer than MTU size and CC3000 does not support fragmentation. Note that the same buffer is used for transmission of the data and commands. That is why the minimum is defined. The calculation for the actual size of buffer for transmission is: Given the maximal data size MAX_DATA, the required buffer is: Using Sendto(): max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE + SOCKET_SENDTO_PARAMS_LEN + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1) Using Send(): max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE + HCI_CMND_SEND_ARG_LENGTH + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1) The 1 is used for the overrun detection */ #define CC3000_MINIMAL_TX_SIZE (130 + 1) #define CC3000_MAXIMAL_TX_SIZE (1519 + 1) //TX and RX buffer sizes, allow to receive and transmit maximum data at length 8. #ifdef CC3000_TINY_DRIVER #define TINY_CC3000_MAXIMAL_RX_SIZE 44 #define TINY_CC3000_MAXIMAL_TX_SIZE 59 #endif /*In order to determine your preferred buffer size, change CC3000_MAXIMAL_RX_SIZE and CC3000_MAXIMAL_TX_SIZE to a value between the minimal and maximal specified above. Note that the buffers are allocated by SPI. In case you change the size of those buffers, you might need also to change the linker file, since for example on MSP430 FRAM devices the buffers are allocated in the FRAM section that is allocated manually and not by IDE. */ #ifndef CC3000_TINY_DRIVER #define CC3000_RX_BUFFER_SIZE (CC3000_MAXIMAL_RX_SIZE) #define CC3000_TX_BUFFER_SIZE (CC3000_MAXIMAL_TX_SIZE) //if defined TINY DRIVER we use smaller RX and TX buffer in order to minimize RAM consumption #else #define CC3000_RX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_RX_SIZE) #define CC3000_TX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_TX_SIZE) #endif //***************************************************************************** // Compound Types //***************************************************************************** typedef INT32 cc3000_time_t; typedef UINT32 clock_t; typedef INT32 suseconds_t; typedef struct cc3000_timeval cc3000_timeval; struct cc3000_timeval { cc3000_time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; typedef CHAR *(*tFWPatches)(UINT32 *usLength); typedef CHAR *(*tDriverPatches)(UINT32 *usLength); typedef CHAR *(*tBootLoaderPatches)(UINT32 *usLength); typedef void (*tWlanCB)(INT32 event_type, CHAR * data, UINT8 length ); typedef INT32 (*tWlanReadInteruptPin)(void); typedef void (*tWlanInterruptEnable)(void); typedef void (*tWlanInterruptDisable)(void); typedef void (*tWriteWlanPin)(UINT8 val); typedef struct { UINT16 usRxEventOpcode; UINT16 usEventOrDataReceived; UINT8 *pucReceivedData; UINT8 *pucTxCommandBuffer; tFWPatches sFWPatches; tDriverPatches sDriverPatches; tBootLoaderPatches sBootLoaderPatches; tWlanCB sWlanCB; tWlanReadInteruptPin ReadWlanInterruptPin; tWlanInterruptEnable WlanInterruptEnable; tWlanInterruptDisable WlanInterruptDisable; tWriteWlanPin WriteWlanPin; INT32 slTransmitDataError; UINT16 usNumberOfFreeBuffers; UINT16 usSlBufferLength; UINT16 usBufferSize; UINT16 usRxDataPending; UINT32 NumberOfSentPackets; UINT32 NumberOfReleasedPackets; UINT8 InformHostOnTxComplete; }sSimplLinkInformation; extern volatile sSimplLinkInformation tSLInformation; //***************************************************************************** // Prototypes for the APIs. //***************************************************************************** //***************************************************************************** // //! SimpleLinkWaitEvent //! //! @param usOpcode command operation code //! @param pRetParams command return parameters //! //! @return none //! //! @brief Wait for event, pass it to the hci_event_handler and //! update the event opcode in a global variable. // //***************************************************************************** extern void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams); //***************************************************************************** // //! SimpleLinkWaitData //! //! @param pBuf data buffer //! @param from from information //! @param fromlen from information length //! //! @return none //! //! @brief Wait for data, pass it to the hci_event_handler //! and update in a global variable that there is //! data to read. // //***************************************************************************** extern void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen); //***************************************************************************** // //! UINT32_TO_STREAM_f //! //! \param p pointer to the new stream //! \param u32 pointer to the 32 bit //! //! \return pointer to the new stream //! //! \brief This function is used for copying 32 bit to stream //! while converting to little endian format. // //***************************************************************************** extern UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32); //***************************************************************************** // //! UINT16_TO_STREAM_f //! //! \param p pointer to the new stream //! \param u32 pointer to the 16 bit //! //! \return pointer to the new stream //! //! \brief This function is used for copying 16 bit to stream //! while converting to little endian format. // //***************************************************************************** extern UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16); //***************************************************************************** // //! STREAM_TO_UINT16_f //! //! \param p pointer to the stream //! \param offset offset in the stream //! //! \return pointer to the new 16 bit //! //! \brief This function is used for copying received stream to //! 16 bit in little endian format. // //***************************************************************************** extern UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset); //***************************************************************************** // //! STREAM_TO_UINT32_f //! //! \param p pointer to the stream //! \param offset offset in the stream //! //! \return pointer to the new 32 bit //! //! \brief This function is used for copying received stream to //! 32 bit in little endian format. // //***************************************************************************** extern UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset); //***************************************************************************** // COMMON MACROs //***************************************************************************** //This macro is used for copying 8 bit to stream while converting to little endian format. #define UINT8_TO_STREAM(_p, _val) {*(_p)++ = (_val);} //This macro is used for copying 16 bit to stream while converting to little endian format. #define UINT16_TO_STREAM(_p, _u16) (UINT16_TO_STREAM_f(_p, _u16)) //This macro is used for copying 32 bit to stream while converting to little endian format. #define UINT32_TO_STREAM(_p, _u32) (UINT32_TO_STREAM_f(_p, _u32)) //This macro is used for copying a specified value length bits (l) to stream while converting to little endian format. #define ARRAY_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(p)++ = ((UINT8 *) a)[_i];} //This macro is used for copying received stream to 8 bit in little endian format. #define STREAM_TO_UINT8(_p, _offset, _u8) {_u8 = (UINT8)(*(_p + _offset));} //This macro is used for copying received stream to 16 bit in little endian format. #define STREAM_TO_UINT16(_p, _offset, _u16) {_u16 = STREAM_TO_UINT16_f(_p, _offset);} //This macro is used for copying received stream to 32 bit in little endian format. #define STREAM_TO_UINT32(_p, _offset, _u32) {_u32 = STREAM_TO_UINT32_f(_p, _offset);} #define STREAM_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(a)++= ((UINT8 *) p)[_i];} //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif // __cplusplus #endif // __CC3000_COMMON_H__ micropython-1.12/drivers/cc3000/inc/ccspi.h000066400000000000000000000066001357706137100204150ustar00rootroot00000000000000/***************************************************************************** * * spi.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_SPI_H__ #define __CC3000_SPI_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif typedef void (*gcSpiHandleRx)(void *p); typedef void (*gcSpiHandleTx)(void); extern unsigned char wlan_tx_buffer[]; //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** // the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* extern void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq); extern void SpiOpen(gcSpiHandleRx pfRxHandler); extern void SpiClose(void); extern void SpiPauseSpi(void); extern void SpiResumeSpi(void); extern long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength); extern void SpiConfigureHwMapping(void); extern void SpiCleanGPIOISR(void); extern void SSIConfigure(unsigned long ulSSIFreq, unsigned long bForceGpioConfiguration, unsigned long uiReconfigureSysClock); extern int init_spi(void); extern long ReadWlanInterruptPin(void); extern void WriteWlanPin(unsigned char val); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif // __cplusplus #endif micropython-1.12/drivers/cc3000/inc/data_types.h000066400000000000000000000057161357706137100214600ustar00rootroot00000000000000/***************************************************************************** * * data_types.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_DATA_TYPES__ #define __CC3000_DATA_TYPES__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif #ifndef NULL #define NULL (0) #endif #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #ifndef OK #define OK (0) #endif #ifndef _INT8 #define _INT8 typedef signed char INT8; #endif #ifndef _UINT8 #define _UINT8 typedef unsigned char UINT8; #endif #ifndef _INT16 #define _INT16 typedef signed short INT16; #endif #ifndef _UINT16 #define _UINT16 typedef unsigned short UINT16; #endif #ifndef _BOOLEAN #define _BOOLEAN typedef unsigned char BOOLEAN; #endif #ifndef _INT32 #define _INT32 typedef signed long INT32; #endif #ifndef _UINT32 #define _UINT32 typedef unsigned long UINT32; #endif typedef int INT; typedef char CHAR; #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __CC3000_DATA_TYPES__ */ micropython-1.12/drivers/cc3000/inc/evnt_handler.h000066400000000000000000000133501357706137100217650ustar00rootroot00000000000000/***************************************************************************** * * evnt_handler.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_EVENT_HANDLER_H__ #define __CC3000_EVENT_HANDLER_H__ #include "hci.h" #include "socket.h" //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** //***************************************************************************** // //! hci_event_handler //! //! @param pRetParams incoming data buffer //! @param from from information (in case of data received) //! @param fromlen from information length (in case of data received) //! //! @return none //! //! @brief Parse the incoming events packets and issues corresponding //! event handler from global array of handlers pointers // //***************************************************************************** extern UINT8 *hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen); //***************************************************************************** // //! hci_unsol_event_handler //! //! @param event_hdr event header //! //! @return 1 if event supported and handled //! 0 if event is not supported //! //! @brief Handle unsolicited events // //***************************************************************************** extern INT32 hci_unsol_event_handler(CHAR *event_hdr); //***************************************************************************** // //! hci_unsolicited_event_handler //! //! @param None //! //! @return ESUCCESS if successful, EFAIL if an error occurred //! //! @brief Parse the incoming unsolicited event packets and issues //! corresponding event handler. // //***************************************************************************** extern INT32 hci_unsolicited_event_handler(void); #define M_BSD_RESP_PARAMS_OFFSET(hci_event_hdr)((CHAR *)(hci_event_hdr) + HCI_EVENT_HEADER_SIZE) #define SOCKET_STATUS_ACTIVE 0 #define SOCKET_STATUS_INACTIVE 1 /* Init socket_active_status = 'all ones': init all sockets with SOCKET_STATUS_INACTIVE. Will be changed by 'set_socket_active_status' upon 'connect' and 'accept' calls */ #define SOCKET_STATUS_INIT_VAL 0xFFFF #define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7)) #define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE)) extern UINT32 socket_active_status; extern void set_socket_active_status(INT32 Sd, INT32 Status); extern INT32 get_socket_active_status(INT32 Sd); typedef struct _bsd_accept_return_t { INT32 iSocketDescriptor; INT32 iStatus; sockaddr tSocketAddress; } tBsdReturnParams; typedef struct _bsd_read_return_t { INT32 iSocketDescriptor; INT32 iNumberOfBytes; UINT32 uiFlags; } tBsdReadReturnParams; #define BSD_RECV_FROM_FROMLEN_OFFSET (4) #define BSD_RECV_FROM_FROM_OFFSET (16) typedef struct _bsd_select_return_t { INT32 iStatus; UINT32 uiRdfd; UINT32 uiWrfd; UINT32 uiExfd; } tBsdSelectRecvParams; typedef struct _bsd_getsockopt_return_t { UINT8 ucOptValue[4]; CHAR iStatus; } tBsdGetSockOptReturnParams; typedef struct _bsd_gethostbyname_return_t { INT32 retVal; INT32 outputAddress; } tBsdGethostbynameParams; //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif // __cplusplus #endif // __CC3000_EVENT_HANDLER_H__ micropython-1.12/drivers/cc3000/inc/hci.h000066400000000000000000000277631357706137100200740ustar00rootroot00000000000000/***************************************************************************** * * hci.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_HCI_H__ #define __CC3000_HCI_H__ #include "cc3000_common.h" //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif #define SPI_HEADER_SIZE (5) #define SIMPLE_LINK_HCI_CMND_HEADER_SIZE (4) #define HEADERS_SIZE_CMD (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) #define SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE (5) #define SIMPLE_LINK_HCI_DATA_HEADER_SIZE (5) #define SIMPLE_LINK_HCI_PATCH_HEADER_SIZE (2) //***************************************************************************** // // Values that can be used as HCI Commands and HCI Packet header defines // //***************************************************************************** #define HCI_TYPE_CMND 0x1 #define HCI_TYPE_DATA 0x2 #define HCI_TYPE_PATCH 0x3 #define HCI_TYPE_EVNT 0x4 #define HCI_EVENT_PATCHES_DRV_REQ (1) #define HCI_EVENT_PATCHES_FW_REQ (2) #define HCI_EVENT_PATCHES_BOOTLOAD_REQ (3) #define HCI_CMND_WLAN_BASE (0x0000) #define HCI_CMND_WLAN_CONNECT 0x0001 #define HCI_CMND_WLAN_DISCONNECT 0x0002 #define HCI_CMND_WLAN_IOCTL_SET_SCANPARAM 0x0003 #define HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY 0x0004 #define HCI_CMND_WLAN_IOCTL_ADD_PROFILE 0x0005 #define HCI_CMND_WLAN_IOCTL_DEL_PROFILE 0x0006 #define HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS 0x0007 #define HCI_CMND_EVENT_MASK 0x0008 #define HCI_CMND_WLAN_IOCTL_STATUSGET 0x0009 #define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START 0x000A #define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP 0x000B #define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX 0x000C #define HCI_CMND_WLAN_CONFIGURE_PATCH 0x000D #define HCI_CMND_SOCKET_BASE 0x1000 #define HCI_CMND_SOCKET 0x1001 #define HCI_CMND_BIND 0x1002 #define HCI_CMND_RECV 0x1004 #define HCI_CMND_ACCEPT 0x1005 #define HCI_CMND_LISTEN 0x1006 #define HCI_CMND_CONNECT 0x1007 #define HCI_CMND_BSD_SELECT 0x1008 #define HCI_CMND_SETSOCKOPT 0x1009 #define HCI_CMND_GETSOCKOPT 0x100A #define HCI_CMND_CLOSE_SOCKET 0x100B #define HCI_CMND_RECVFROM 0x100D #define HCI_CMND_GETHOSTNAME 0x1010 #define HCI_CMND_MDNS_ADVERTISE 0x1011 #define HCI_CMND_GETMSSVALUE 0x1012 #define HCI_DATA_BASE 0x80 #define HCI_CMND_SEND (0x01 + HCI_DATA_BASE) #define HCI_CMND_SENDTO (0x03 + HCI_DATA_BASE) #define HCI_DATA_BSD_RECVFROM (0x04 + HCI_DATA_BASE) #define HCI_DATA_BSD_RECV (0x05 + HCI_DATA_BASE) #define HCI_CMND_NVMEM_CBASE (0x0200) #define HCI_CMND_NVMEM_CREATE_ENTRY (0x0203) #define HCI_CMND_NVMEM_SWAP_ENTRY (0x0205) #define HCI_CMND_NVMEM_READ (0x0201) #define HCI_CMND_NVMEM_WRITE (0x0090) #define HCI_CMND_NVMEM_WRITE_PATCH (0x0204) #define HCI_CMND_READ_SP_VERSION (0x0207) #define HCI_CMND_READ_BUFFER_SIZE 0x400B #define HCI_CMND_SIMPLE_LINK_START 0x4000 #define HCI_CMND_NETAPP_BASE 0x2000 #define HCI_NETAPP_DHCP (0x0001 + HCI_CMND_NETAPP_BASE) #define HCI_NETAPP_PING_SEND (0x0002 + HCI_CMND_NETAPP_BASE) #define HCI_NETAPP_PING_REPORT (0x0003 + HCI_CMND_NETAPP_BASE) #define HCI_NETAPP_PING_STOP (0x0004 + HCI_CMND_NETAPP_BASE) #define HCI_NETAPP_IPCONFIG (0x0005 + HCI_CMND_NETAPP_BASE) #define HCI_NETAPP_ARP_FLUSH (0x0006 + HCI_CMND_NETAPP_BASE) #define HCI_NETAPP_SET_DEBUG_LEVEL (0x0008 + HCI_CMND_NETAPP_BASE) #define HCI_NETAPP_SET_TIMERS (0x0009 + HCI_CMND_NETAPP_BASE) //***************************************************************************** // // Values that can be used as HCI Events defines // //***************************************************************************** #define HCI_EVNT_WLAN_BASE 0x0000 #define HCI_EVNT_WLAN_CONNECT 0x0001 #define HCI_EVNT_WLAN_DISCONNECT \ 0x0002 #define HCI_EVNT_WLAN_IOCTL_ADD_PROFILE \ 0x0005 #define HCI_EVNT_SOCKET HCI_CMND_SOCKET #define HCI_EVNT_BIND HCI_CMND_BIND #define HCI_EVNT_RECV HCI_CMND_RECV #define HCI_EVNT_ACCEPT HCI_CMND_ACCEPT #define HCI_EVNT_LISTEN HCI_CMND_LISTEN #define HCI_EVNT_CONNECT HCI_CMND_CONNECT #define HCI_EVNT_SELECT HCI_CMND_BSD_SELECT #define HCI_EVNT_CLOSE_SOCKET HCI_CMND_CLOSE_SOCKET #define HCI_EVNT_RECVFROM HCI_CMND_RECVFROM #define HCI_EVNT_SETSOCKOPT HCI_CMND_SETSOCKOPT #define HCI_EVNT_GETSOCKOPT HCI_CMND_GETSOCKOPT #define HCI_EVNT_BSD_GETHOSTBYNAME HCI_CMND_GETHOSTNAME #define HCI_EVNT_MDNS_ADVERTISE HCI_CMND_MDNS_ADVERTISE #define HCI_EVNT_GETMSSVALUE HCI_CMND_GETMSSVALUE #define HCI_EVNT_SEND 0x1003 #define HCI_EVNT_WRITE 0x100E #define HCI_EVNT_SENDTO 0x100F #define HCI_EVNT_PATCHES_REQ 0x1000 #define HCI_EVNT_UNSOL_BASE 0x4000 #define HCI_EVNT_WLAN_UNSOL_BASE (0x8000) #define HCI_EVNT_WLAN_UNSOL_CONNECT (0x0001 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_WLAN_UNSOL_DISCONNECT (0x0002 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_WLAN_UNSOL_INIT (0x0004 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_WLAN_TX_COMPLETE (0x0008 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_WLAN_UNSOL_DHCP (0x0010 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_WLAN_ASYNC_PING_REPORT (0x0040 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE (0x0080 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_WLAN_KEEPALIVE (0x0200 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_BSD_TCP_CLOSE_WAIT (0x0800 + HCI_EVNT_WLAN_UNSOL_BASE) #define HCI_EVNT_DATA_UNSOL_FREE_BUFF \ 0x4100 #define HCI_EVNT_NVMEM_CREATE_ENTRY \ HCI_CMND_NVMEM_CREATE_ENTRY #define HCI_EVNT_NVMEM_SWAP_ENTRY HCI_CMND_NVMEM_SWAP_ENTRY #define HCI_EVNT_NVMEM_READ HCI_CMND_NVMEM_READ #define HCI_EVNT_NVMEM_WRITE (0x0202) #define HCI_EVNT_READ_SP_VERSION \ HCI_CMND_READ_SP_VERSION #define HCI_EVNT_INPROGRESS 0xFFFF #define HCI_DATA_RECVFROM 0x84 #define HCI_DATA_RECV 0x85 #define HCI_DATA_NVMEM 0x91 #define HCI_EVENT_CC3000_CAN_SHUT_DOWN 0x99 //***************************************************************************** // // Prototypes for the structures for APIs. // //***************************************************************************** #define HCI_DATA_HEADER_SIZE (5) #define HCI_EVENT_HEADER_SIZE (5) #define HCI_DATA_CMD_HEADER_SIZE (5) #define HCI_PATCH_HEADER_SIZE (6) #define HCI_PACKET_TYPE_OFFSET (0) #define HCI_PACKET_ARGSIZE_OFFSET (2) #define HCI_PACKET_LENGTH_OFFSET (3) #define HCI_EVENT_OPCODE_OFFSET (1) #define HCI_EVENT_LENGTH_OFFSET (3) #define HCI_EVENT_STATUS_OFFSET (4) #define HCI_DATA_LENGTH_OFFSET (3) //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** //***************************************************************************** // //! hci_command_send //! //! @param usOpcode command operation code //! @param pucBuff pointer to the command's arguments buffer //! @param ucArgsLength length of the arguments //! //! @return none //! //! @brief Initiate an HCI command. // //***************************************************************************** extern UINT16 hci_command_send(UINT16 usOpcode, UINT8 *ucArgs, UINT8 ucArgsLength); //***************************************************************************** // //! hci_data_send //! //! @param usOpcode command operation code //! @param ucArgs pointer to the command's arguments buffer //! @param usArgsLength length of the arguments //! @param ucTail pointer to the data buffer //! @param usTailLength buffer length //! //! @return none //! //! @brief Initiate an HCI data write operation // //***************************************************************************** extern INT32 hci_data_send(UINT8 ucOpcode, UINT8 *ucArgs, UINT16 usArgsLength, UINT16 usDataLength, const UINT8 *ucTail, UINT16 usTailLength); //***************************************************************************** // //! hci_data_command_send //! //! @param usOpcode command operation code //! @param pucBuff pointer to the data buffer //! @param ucArgsLength arguments length //! @param ucDataLength data length //! //! @return none //! //! @brief Prepare HCI header and initiate an HCI data write operation // //***************************************************************************** extern void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength, UINT16 ucDataLength); //***************************************************************************** // //! hci_patch_send //! //! @param usOpcode command operation code //! @param pucBuff pointer to the command's arguments buffer //! @param patch pointer to patch content buffer //! @param usDataLength data length //! //! @return none //! //! @brief Prepare HCI header and initiate an HCI patch write operation // //***************************************************************************** extern void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif // __cplusplus #endif // __CC3000_HCI_H__ micropython-1.12/drivers/cc3000/inc/host_driver_version.h000066400000000000000000000037101357706137100234100ustar00rootroot00000000000000/***************************************************************************** * * host_driver_version.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_HOST_DRIVER_VERSION_H__ #define __CC3000_HOST_DRIVER_VERSION_H__ #define DRIVER_VERSION_NUMBER 15 #endif // __CC3000_HOST_DRIVER_VERSION_H__ micropython-1.12/drivers/cc3000/inc/inet_ntop.h000066400000000000000000000002121357706137100213040ustar00rootroot00000000000000#ifndef __INET_NTOP_H #define __INET_NTOP_H char *inet_ntop(int af, const void *addr, char *buf, size_t size); #endif /* __INET_NTOP_H */ micropython-1.12/drivers/cc3000/inc/inet_pton.h000066400000000000000000000001611357706137100213070ustar00rootroot00000000000000#ifndef __INET_PTON_H #define __INET_PTON_H int inet_pton(int, const char *, void *); #endif /* __INET_PTON_H */ micropython-1.12/drivers/cc3000/inc/netapp.h000066400000000000000000000330601357706137100206030ustar00rootroot00000000000000/***************************************************************************** * * netapp.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_NETAPP_H__ #define __CC3000_NETAPP_H__ #include "data_types.h" //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // //! \addtogroup netapp_api //! @{ // //***************************************************************************** typedef struct _netapp_dhcp_ret_args_t { UINT8 aucIP[4]; UINT8 aucSubnetMask[4]; UINT8 aucDefaultGateway[4]; UINT8 aucDHCPServer[4]; UINT8 aucDNSServer[4]; }tNetappDhcpParams; typedef struct _netapp_ipconfig_ret_args_t { UINT8 aucIP[4]; UINT8 aucSubnetMask[4]; UINT8 aucDefaultGateway[4]; UINT8 aucDHCPServer[4]; UINT8 aucDNSServer[4]; UINT8 uaMacAddr[6]; UINT8 uaSSID[32]; }tNetappIpconfigRetArgs; /*Ping send report parameters*/ typedef struct _netapp_pingreport_args { UINT32 packets_sent; UINT32 packets_received; UINT32 min_round_time; UINT32 max_round_time; UINT32 avg_round_time; } netapp_pingreport_args_t; //***************************************************************************** // //! netapp_config_mac_adrress //! //! @param mac device mac address, 6 bytes. Saved: yes //! //! @return return on success 0, otherwise error. //! //! @brief Configure device MAC address and store it in NVMEM. //! The value of the MAC address configured through the API will //! be stored in CC3000 non volatile memory, thus preserved //! over resets. // //***************************************************************************** extern INT32 netapp_config_mac_adrress( UINT8 *mac ); //***************************************************************************** // //! netapp_dhcp //! //! @param aucIP device mac address, 6 bytes. Saved: yes //! @param aucSubnetMask device mac address, 6 bytes. Saved: yes //! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes //! @param aucDNSServer device mac address, 6 bytes. Saved: yes //! //! @return return on success 0, otherwise error. //! //! @brief netapp_dhcp is used to configure the network interface, //! static or dynamic (DHCP).\n In order to activate DHCP mode, //! aucIP, aucSubnetMask, aucDefaultGateway must be 0. //! The default mode of CC3000 is DHCP mode. //! Note that the configuration is saved in non volatile memory //! and thus preserved over resets. //! //! @note If the mode is altered a reset of CC3000 device is required //! in order to apply changes.\nAlso note that asynchronous event //! of DHCP_EVENT, which is generated when an IP address is //! allocated either by the DHCP server or due to static //! allocation is generated only upon a connection to the //! AP was established. //! //***************************************************************************** extern INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer); //***************************************************************************** // //! netapp_timeout_values //! //! @param aucDHCP DHCP lease time request, also impact //! the DHCP renew timeout. Range: [0-0xffffffff] seconds, //! 0 or 0xffffffff == infinity lease timeout. //! Resolution:10 seconds. Influence: only after //! reconnecting to the AP. //! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds. //! The parameter is saved into the CC3000 NVMEM. //! The default value on CC3000 is 14400 seconds. //! //! @param aucARP ARP refresh timeout, if ARP entry is not updated by //! incoming packet, the ARP entry will be deleted by //! the end of the timeout. //! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout //! Resolution: 10 seconds. Influence: on runtime. //! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds //! The parameter is saved into the CC3000 NVMEM. //! The default value on CC3000 is 3600 seconds. //! //! @param aucKeepalive Keepalive event sent by the end of keepalive timeout //! Range: [0-0xffffffff] seconds, 0 == infinity timeout //! Resolution: 10 seconds. //! Influence: on runtime. //! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec //! The parameter is saved into the CC3000 NVMEM. //! The default value on CC3000 is 10 seconds. //! //! @param aucInactivity Socket inactivity timeout, socket timeout is //! refreshed by incoming or outgoing packet, by the //! end of the socket timeout the socket will be closed //! Range: [0-0xffffffff] sec, 0 == infinity timeout. //! Resolution: 10 seconds. Influence: on runtime. //! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec //! The parameter is saved into the CC3000 NVMEM. //! The default value on CC3000 is 60 seconds. //! //! @return return on success 0, otherwise error. //! //! @brief Set new timeout values. Function set new timeout values for: //! DHCP lease timeout, ARP refresh timeout, keepalive event //! timeout and socket inactivity timeout //! //! @note If a parameter set to non zero value which is less than 10s, //! it will be set automatically to 10s. //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP, UINT32 *aucKeepalive, UINT32 *aucInactivity); #endif //***************************************************************************** // //! netapp_ping_send //! //! @param ip destination IP address //! @param pingAttempts number of echo requests to send //! @param pingSize send buffer size which may be up to 1400 bytes //! @param pingTimeout Time to wait for a response,in milliseconds. //! //! @return return on success 0, otherwise error. //! //! @brief send ICMP ECHO_REQUEST to network hosts //! //! @note If an operation finished successfully asynchronous ping report //! event will be generated. The report structure is as defined //! by structure netapp_pingreport_args_t. //! //! @warning Calling this function while a previous Ping Requests are in //! progress will stop the previous ping request. //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern INT32 netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout); #endif //***************************************************************************** // //! netapp_ping_stop //! //! @param none //! //! @return On success, zero is returned. On error, -1 is returned. //! //! @brief Stop any ping request. //! //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern INT32 netapp_ping_stop(); #endif //***************************************************************************** // //! netapp_ping_report //! //! @param none //! //! @return none //! //! @brief Request for ping status. This API triggers the CC3000 to send //! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT. //! This event will carry the report structure: //! netapp_pingreport_args_t. This structure is filled in with ping //! results up till point of triggering API. //! netapp_pingreport_args_t:\n packets_sent - echo sent, //! packets_received - echo reply, min_round_time - minimum //! round time, max_round_time - max round time, //! avg_round_time - average round time //! //! @note When a ping operation is not active, the returned structure //! fields are 0. //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern void netapp_ping_report(); #endif //***************************************************************************** // //! netapp_ipconfig //! //! @param[out] ipconfig This argument is a pointer to a //! tNetappIpconfigRetArgs structure. This structure is //! filled in with the network interface configuration. //! tNetappIpconfigRetArgs:\n aucIP - ip address, //! aucSubnetMask - mask, aucDefaultGateway - default //! gateway address, aucDHCPServer - dhcp server address //! aucDNSServer - dns server address, uaMacAddr - mac //! address, uaSSID - connected AP ssid //! //! @return none //! //! @brief Obtain the CC3000 Network interface information. //! Note that the information is available only after the WLAN //! connection was established. Calling this function before //! associated, will cause non-defined values to be returned. //! //! @note The function is useful for figuring out the IP Configuration of //! the device when DHCP is used and for figuring out the SSID of //! the Wireless network the device is associated with. //! //***************************************************************************** extern void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ); //***************************************************************************** // //! netapp_arp_flush //! //! @param none //! //! @return none //! //! @brief Flushes ARP table //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern INT32 netapp_arp_flush(); #endif //***************************************************************************** // //! netapp_set_debug_level //! //! @param[in] level debug level. Bitwise [0-8], //! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical //! message, 1 information message, 2 - core messages, 3 - //! HCI messages, 4 - Network stack messages, 5 - wlan //! messages, 6 - wlan driver messages, 7 - epprom messages, //! 8 - general messages. Default: 0x13f. Saved: no //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Debug messages sent via the UART debug channel, this function //! enable/disable the debug level //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 netapp_set_debug_level(UINT32 ulLevel); #endif //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif // __cplusplus #endif // __CC3000_NETAPP_H__ micropython-1.12/drivers/cc3000/inc/nvmem.h000066400000000000000000000226251357706137100204430ustar00rootroot00000000000000/***************************************************************************** * * nvmem.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_NVRAM_H__ #define __CC3000_NVRAM_H__ #include "cc3000_common.h" //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // //! \addtogroup nvmem_api //! @{ // //***************************************************************************** /**************************************************************************** ** ** Definitions for File IDs ** ****************************************************************************/ /* NVMEM file ID - system files*/ #define NVMEM_NVS_FILEID (0) #define NVMEM_NVS_SHADOW_FILEID (1) #define NVMEM_WLAN_CONFIG_FILEID (2) #define NVMEM_WLAN_CONFIG_SHADOW_FILEID (3) #define NVMEM_WLAN_DRIVER_SP_FILEID (4) #define NVMEM_WLAN_FW_SP_FILEID (5) #define NVMEM_MAC_FILEID (6) #define NVMEM_FRONTEND_VARS_FILEID (7) #define NVMEM_IP_CONFIG_FILEID (8) #define NVMEM_IP_CONFIG_SHADOW_FILEID (9) #define NVMEM_BOOTLOADER_SP_FILEID (10) #define NVMEM_RM_FILEID (11) /* NVMEM file ID - user files*/ #define NVMEM_AES128_KEY_FILEID (12) #define NVMEM_SHARED_MEM_FILEID (13) /* max entry in order to invalid nvmem */ #define NVMEM_MAX_ENTRY (16) //***************************************************************************** // //! nvmem_read //! //! @param ulFileId nvmem file id:\n //! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID, //! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID, //! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, //! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID, //! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID, //! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID, //! and user files 12-15. //! @param ulLength number of bytes to read //! @param ulOffset ulOffset in file from where to read //! @param buff output buffer pointer //! //! @return on success 0, error otherwise. //! //! @brief Reads data from the file referred by the ulFileId parameter. //! Reads data from file ulOffset till length. Err if the file can't //! be used, is invalid, or if the read is out of bounds. //! //***************************************************************************** extern INT32 nvmem_read(UINT32 file_id, UINT32 length, UINT32 offset, UINT8 *buff); //***************************************************************************** // //! nvmem_write //! //! @param ulFileId nvmem file id:\n //! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, //! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID, //! and user files 12-15. //! @param ulLength number of bytes to write //! @param ulEntryOffset offset in file to start write operation from //! @param buff data to write //! //! @return on success 0, error otherwise. //! //! @brief Write data to nvmem. //! writes data to file referred by the ulFileId parameter. //! Writes data to file ulOffset till ulLength.The file id will be //! marked invalid till the write is done. The file entry doesn't //! need to be valid - only allocated. //! //***************************************************************************** extern INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff); //***************************************************************************** // //! nvmem_set_mac_address //! //! @param mac mac address to be set //! //! @return on success 0, error otherwise. //! //! @brief Write MAC address to EEPROM. //! mac address as appears over the air (OUI first) //! //***************************************************************************** extern UINT8 nvmem_set_mac_address(UINT8 *mac); //***************************************************************************** // //! nvmem_get_mac_address //! //! @param[out] mac mac address //! //! @return on success 0, error otherwise. //! //! @brief Read MAC address from EEPROM. //! mac address as appears over the air (OUI first) //! //***************************************************************************** extern UINT8 nvmem_get_mac_address(UINT8 *mac); //***************************************************************************** // //! nvmem_write_patch //! //! @param ulFileId nvmem file id:\n //! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, //! @param spLength number of bytes to write //! @param spData SP data to write //! //! @return on success 0, error otherwise. //! //! @brief program a patch to a specific file ID. //! The SP data is assumed to be organized in 2-dimensional. //! Each line is SP_PORTION_SIZE bytes long. Actual programming is //! applied in SP_PORTION_SIZE bytes portions. //! //***************************************************************************** extern UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData); //***************************************************************************** // //! nvmem_read_sp_version //! //! @param[out] patchVer first number indicates package ID and the second //! number indicates package build number //! //! @return on success 0, error otherwise. //! //! @brief Read patch version. read package version (WiFi FW patch, //! driver-supplicant-NS patch, bootloader patch) //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern UINT8 nvmem_read_sp_version(UINT8* patchVer); #endif //***************************************************************************** // //! nvmem_create_entry //! //! @param ulFileId nvmem file Id:\n //! * NVMEM_AES128_KEY_FILEID: 12 //! * NVMEM_SHARED_MEM_FILEID: 13 //! * and fileIDs 14 and 15 //! @param ulNewLen entry ulLength //! //! @return on success 0, error otherwise. //! //! @brief Create new file entry and allocate space on the NVMEM. //! Applies only to user files. //! Modify the size of file. //! If the entry is unallocated - allocate it to size //! ulNewLen (marked invalid). //! If it is allocated then deallocate it first. //! To just mark the file as invalid without resizing - //! set ulNewLen=0. //! //***************************************************************************** extern INT32 nvmem_create_entry(UINT32 file_id, UINT32 newlen); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** #ifdef __cplusplus } #endif // __cplusplus #endif // __CC3000_NVRAM_H__ micropython-1.12/drivers/cc3000/inc/patch_prog.h000066400000000000000000000005051357706137100214400ustar00rootroot00000000000000#ifndef __CC3000_PATCH_PROG_H__ #define __CC3000_PATCH_PROG_H__ extern unsigned short fw_length; extern const unsigned char fw_patch[]; extern unsigned short drv_length; extern const unsigned char wlan_drv_patch[]; extern const unsigned char cRMdefaultParams[128]; void patch_prog_start(); #endif //__CC3000_PATCH_PROG_H__ micropython-1.12/drivers/cc3000/inc/security.h000066400000000000000000000106711357706137100211660ustar00rootroot00000000000000/***************************************************************************** * * security.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_SECURITY__ #define __CC3000_SECURITY__ #include "nvmem.h" //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif #define AES128_KEY_SIZE 16 #ifndef CC3000_UNENCRYPTED_SMART_CONFIG //***************************************************************************** // //! aes_encrypt //! //! @param[in] key AES128 key of size 16 bytes //! @param[in\out] state 16 bytes of plain text and cipher text //! //! @return none //! //! @brief AES128 encryption: //! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes //! is computed. The AES implementation is in mode ECB (Electronic //! Code Book). //! //! //***************************************************************************** extern void aes_encrypt(UINT8 *state, UINT8 *key); //***************************************************************************** // //! aes_decrypt //! //! @param[in] key AES128 key of size 16 bytes //! @param[in\out] state 16 bytes of cipher text and plain text //! //! @return none //! //! @brief AES128 decryption: //! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes //! is computed The AES implementation is in mode ECB //! (Electronic Code Book). //! //! //***************************************************************************** extern void aes_decrypt(UINT8 *state, UINT8 *key); //***************************************************************************** // //! aes_read_key //! //! @param[out] key AES128 key of size 16 bytes //! //! @return on success 0, error otherwise. //! //! @brief Reads AES128 key from EEPROM //! Reads the AES128 key from fileID #12 in EEPROM //! returns an error if the key does not exist. //! //! //***************************************************************************** extern INT32 aes_read_key(UINT8 *key); //***************************************************************************** // //! aes_write_key //! //! @param[out] key AES128 key of size 16 bytes //! //! @return on success 0, error otherwise. //! //! @brief writes AES128 key from EEPROM //! Writes the AES128 key to fileID #12 in EEPROM //! //! //***************************************************************************** extern INT32 aes_write_key(UINT8 *key); #endif //CC3000_UNENCRYPTED_SMART_CONFIG #ifdef __cplusplus } #endif // __cplusplus #endif micropython-1.12/drivers/cc3000/inc/socket.h000066400000000000000000000732501357706137100206110ustar00rootroot00000000000000/***************************************************************************** * * socket.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_SOCKET_H__ #define __CC3000_SOCKET_H__ #include "cc3000_common.h" //***************************************************************************** // //! \addtogroup socket_api //! @{ // //***************************************************************************** //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif #define HOSTNAME_MAX_LENGTH (230) // 230 bytes + header shouldn't exceed 8 bit value //--------- Address Families -------- #define AF_INET 2 #define AF_INET6 23 //------------ Socket Types ------------ #define SOCK_STREAM 1 #define SOCK_DGRAM 2 #define SOCK_RAW 3 // Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers #define SOCK_RDM 4 #define SOCK_SEQPACKET 5 //----------- Socket Protocol ---------- #define IPPROTO_IP 0 // dummy for IP #define IPPROTO_ICMP 1 // control message protocol #define IPPROTO_IPV4 IPPROTO_IP // IP inside IP #define IPPROTO_TCP 6 // tcp #define IPPROTO_UDP 17 // user datagram protocol #define IPPROTO_IPV6 41 // IPv6 in IPv6 #define IPPROTO_NONE 59 // No next header #define IPPROTO_RAW 255 // raw IP packet #define IPPROTO_MAX 256 //----------- Socket retunr codes ----------- #define SOC_ERROR (-1) // error #define SOC_IN_PROGRESS (-2) // socket in progress //----------- Socket Options ----------- #define SOL_SOCKET 0xffff // socket level #define SOCKOPT_RECV_NONBLOCK 0 // recv non block mode, set SOCK_ON or SOCK_OFF (default block mode) #define SOCKOPT_RECV_TIMEOUT 1 // optname to configure recv and recvfromtimeout #define SOCKOPT_ACCEPT_NONBLOCK 2 // accept non block mode, set SOCK_ON or SOCK_OFF (default block mode) #define SOCK_ON 0 // socket non-blocking mode is enabled #define SOCK_OFF 1 // socket blocking mode is enabled #define MAX_PACKET_SIZE 1500 #define MAX_LISTEN_QUEUE 4 #define IOCTL_SOCKET_EVENTMASK #define ENOBUFS 55 // No buffer space available #define __FD_SETSIZE 32 #define ASIC_ADDR_LEN 8 #define NO_QUERY_RECIVED -3 typedef struct _in_addr_t { UINT32 s_addr; // load with inet_aton() } in_addr; typedef struct _sockaddr_t { UINT16 sa_family; UINT8 sa_data[14]; } sockaddr; typedef struct _sockaddr_in_t { INT16 sin_family; // e.g. AF_INET UINT16 sin_port; // e.g. htons(3490) in_addr sin_addr; // see struct in_addr, below CHAR sin_zero[8]; // zero this if you want to } sockaddr_in; typedef UINT32 socklen_t; // The fd_set member is required to be an array of INT32s. typedef INT32 __fd_mask; // It's easier to assume 8-bit bytes than to get CHAR_BIT. #define __NFDBITS (8 * sizeof (__fd_mask)) #define __FDELT(d) ((d) / __NFDBITS) #define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) // fd_set for select and pselect. typedef struct { __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; #define __FDS_BITS(set) ((set)->fds_bits) } fd_set; // We don't use `memset' because this would require a prototype and // the array isn't too big. #define __FD_ZERO(set) \ do { \ UINT16 __i; \ fd_set *__arr = (set); \ for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ __FDS_BITS (__arr)[__i] = 0; \ } while (0) #define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d)) #define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d)) #define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d)) // Access macros for 'fd_set'. #define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) #define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) #define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) #define FD_ZERO(fdsetp) __FD_ZERO (fdsetp) //Use in case of Big Endian only #define htonl(A) ((((UINT32)(A) & 0xff000000) >> 24) | \ (((UINT32)(A) & 0x00ff0000) >> 8) | \ (((UINT32)(A) & 0x0000ff00) << 8) | \ (((UINT32)(A) & 0x000000ff) << 24)) #define ntohl htonl //Use in case of Big Endian only #define htons(A) ((((UINT32)(A) & 0xff00) >> 8) | \ (((UINT32)(A) & 0x00ff) << 8)) #define ntohs htons // mDNS port - 5353 mDNS multicast address - 224.0.0.251 #define SET_mDNS_ADD(sockaddr) sockaddr.sa_data[0] = 0x14; \ sockaddr.sa_data[1] = 0xe9; \ sockaddr.sa_data[2] = 0xe0; \ sockaddr.sa_data[3] = 0x0; \ sockaddr.sa_data[4] = 0x0; \ sockaddr.sa_data[5] = 0xfb; //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** //***************************************************************************** // //! socket //! //! @param domain selects the protocol family which will be used for //! communication. On this version only AF_INET is supported //! @param type specifies the communication semantics. On this version //! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported //! @param protocol specifies a particular protocol to be used with the //! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are //! supported. //! //! @return On success, socket handle that is used for consequent socket //! operations. On error, -1 is returned. //! //! @brief create an endpoint for communication //! The socket function creates a socket that is bound to a specific //! transport service provider. This function is called by the //! application layer to obtain a socket handle. // //***************************************************************************** extern INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol); //***************************************************************************** // //! closesocket //! //! @param sd socket handle. //! //! @return On success, zero is returned. On error, -1 is returned. //! //! @brief The socket function closes a created socket. // //***************************************************************************** extern INT32 CC3000_EXPORT(closesocket)(INT32 sd); //***************************************************************************** // //! accept //! //! @param[in] sd socket descriptor (handle) //! @param[out] addr the argument addr is a pointer to a sockaddr structure //! This structure is filled in with the address of the //! peer socket, as known to the communications layer. //! determined. The exact format of the address returned //! addr is by the socket's address sockaddr. //! On this version only AF_INET is supported. //! This argument returns in network order. //! @param[out] addrlen the addrlen argument is a value-result argument: //! it should initially contain the size of the structure //! pointed to by addr. //! //! @return For socket in blocking mode: //! On success, socket handle. on failure negative //! For socket in non-blocking mode: //! - On connection establishment, socket handle //! - On connection pending, SOC_IN_PROGRESS (-2) //! - On failure, SOC_ERROR (-1) //! //! @brief accept a connection on a socket: //! This function is used with connection-based socket types //! (SOCK_STREAM). It extracts the first connection request on the //! queue of pending connections, creates a new connected socket, and //! returns a new file descriptor referring to that socket. //! The newly created socket is not in the listening state. //! The original socket sd is unaffected by this call. //! The argument sd is a socket that has been created with socket(), //! bound to a local address with bind(), and is listening for //! connections after a listen(). The argument addr is a pointer //! to a sockaddr structure. This structure is filled in with the //! address of the peer socket, as known to the communications layer. //! The exact format of the address returned addr is determined by the //! socket's address family. The addrlen argument is a value-result //! argument: it should initially contain the size of the structure //! pointed to by addr, on return it will contain the actual //! length (in bytes) of the address returned. //! //! @sa socket ; bind ; listen // //***************************************************************************** extern INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen); //***************************************************************************** // //! bind //! //! @param[in] sd socket descriptor (handle) //! @param[out] addr specifies the destination address. On this version //! only AF_INET is supported. //! @param[out] addrlen contains the size of the structure pointed to by addr. //! //! @return On success, zero is returned. On error, -1 is returned. //! //! @brief assign a name to a socket //! This function gives the socket the local address addr. //! addr is addrlen bytes long. Traditionally, this is called when a //! socket is created with socket, it exists in a name space (address //! family) but has no name assigned. //! It is necessary to assign a local address before a SOCK_STREAM //! socket may receive connections. //! //! @sa socket ; accept ; listen // //***************************************************************************** extern INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen); //***************************************************************************** // //! listen //! //! @param[in] sd socket descriptor (handle) //! @param[in] backlog specifies the listen queue depth. On this version //! backlog is not supported. //! @return On success, zero is returned. On error, -1 is returned. //! //! @brief listen for connections on a socket //! The willingness to accept incoming connections and a queue //! limit for incoming connections are specified with listen(), //! and then the connections are accepted with accept. //! The listen() call applies only to sockets of type SOCK_STREAM //! The backlog parameter defines the maximum length the queue of //! pending connections may grow to. //! //! @sa socket ; accept ; bind //! //! @note On this version, backlog is not supported // //***************************************************************************** extern INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog); //***************************************************************************** // //! gethostbyname //! //! @param[in] hostname host name //! @param[in] usNameLen name length //! @param[out] out_ip_addr This parameter is filled in with host IP address. //! In case that host name is not resolved, //! out_ip_addr is zero. //! @return On success, positive is returned. On error, negative is returned //! //! @brief Get host IP by name. Obtain the IP Address of machine on network, //! by its name. //! //! @note On this version, only blocking mode is supported. Also note that //! the function requires DNS server to be configured prior to its usage. // //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, UINT32* out_ip_addr); #endif //***************************************************************************** // //! connect //! //! @param[in] sd socket descriptor (handle) //! @param[in] addr specifies the destination addr. On this version //! only AF_INET is supported. //! @param[out] addrlen contains the size of the structure pointed to by addr //! @return On success, zero is returned. On error, -1 is returned //! //! @brief initiate a connection on a socket //! Function connects the socket referred to by the socket descriptor //! sd, to the address specified by addr. The addrlen argument //! specifies the size of addr. The format of the address in addr is //! determined by the address space of the socket. If it is of type //! SOCK_DGRAM, this call specifies the peer with which the socket is //! to be associated; this address is that to which datagrams are to be //! sent, and the only address from which datagrams are to be received. //! If the socket is of type SOCK_STREAM, this call attempts to make a //! connection to another socket. The other socket is specified by //! address, which is an address in the communications space of the //! socket. Note that the function implements only blocking behavior //! thus the caller will be waiting either for the connection //! establishment or for the connection establishment failure. //! //! @sa socket // //***************************************************************************** extern INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen); //***************************************************************************** // //! select //! //! @param[in] nfds the highest-numbered file descriptor in any of the //! three sets, plus 1. //! @param[out] writesds socket descriptors list for write monitoring //! @param[out] readsds socket descriptors list for read monitoring //! @param[out] exceptsds socket descriptors list for exception monitoring //! @param[in] timeout is an upper bound on the amount of time elapsed //! before select() returns. Null means infinity //! timeout. The minimum timeout is 5 milliseconds, //! less than 5 milliseconds will be set //! automatically to 5 milliseconds. //! @return On success, select() returns the number of file descriptors //! contained in the three returned descriptor sets (that is, the //! total number of bits that are set in readfds, writefds, //! exceptfds) which may be zero if the timeout expires before //! anything interesting happens. //! On error, -1 is returned. //! *readsds - return the sockets on which Read request will //! return without delay with valid data. //! *writesds - return the sockets on which Write request //! will return without delay. //! *exceptsds - return the sockets which closed recently. //! //! @brief Monitor socket activity //! Select allow a program to monitor multiple file descriptors, //! waiting until one or more of the file descriptors become //! "ready" for some class of I/O operation //! //! @Note If the timeout value set to less than 5ms it will automatically set //! to 5ms to prevent overload of the system //! //! @sa socket // //***************************************************************************** extern INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, struct cc3000_timeval *timeout); //***************************************************************************** // //! setsockopt //! //! @param[in] sd socket handle //! @param[in] level defines the protocol level for this option //! @param[in] optname defines the option name to Interrogate //! @param[in] optval specifies a value for the option //! @param[in] optlen specifies the length of the option value //! @return On success, zero is returned. On error, -1 is returned //! //! @brief set socket options //! This function manipulate the options associated with a socket. //! Options may exist at multiple protocol levels; they are always //! present at the uppermost socket level. //! When manipulating socket options the level at which the option //! resides and the name of the option must be specified. //! To manipulate options at the socket level, level is specified as //! SOL_SOCKET. To manipulate options at any other level the protocol //! number of the appropriate protocol controlling the option is //! supplied. For example, to indicate that an option is to be //! interpreted by the TCP protocol, level should be set to the //! protocol number of TCP; //! The parameters optval and optlen are used to access optval - //! use for setsockopt(). For getsockopt() they identify a buffer //! in which the value for the requested option(s) are to //! be returned. For getsockopt(), optlen is a value-result //! parameter, initially containing the size of the buffer //! pointed to by option_value, and modified on return to //! indicate the actual size of the value returned. If no option //! value is to be supplied or returned, option_value may be NULL. //! //! @Note On this version the following two socket options are enabled: //! The only protocol level supported in this version //! is SOL_SOCKET (level). //! 1. SOCKOPT_RECV_TIMEOUT (optname) //! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout //! in milliseconds. //! In that case optval should be pointer to UINT32. //! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on //! or off. //! In that case optval should be SOCK_ON or SOCK_OFF (optval). //! //! @sa getsockopt // //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval, socklen_t optlen); #endif //***************************************************************************** // //! getsockopt //! //! @param[in] sd socket handle //! @param[in] level defines the protocol level for this option //! @param[in] optname defines the option name to Interrogate //! @param[out] optval specifies a value for the option //! @param[out] optlen specifies the length of the option value //! @return On success, zero is returned. On error, -1 is returned //! //! @brief set socket options //! This function manipulate the options associated with a socket. //! Options may exist at multiple protocol levels; they are always //! present at the uppermost socket level. //! When manipulating socket options the level at which the option //! resides and the name of the option must be specified. //! To manipulate options at the socket level, level is specified as //! SOL_SOCKET. To manipulate options at any other level the protocol //! number of the appropriate protocol controlling the option is //! supplied. For example, to indicate that an option is to be //! interpreted by the TCP protocol, level should be set to the //! protocol number of TCP; //! The parameters optval and optlen are used to access optval - //! use for setsockopt(). For getsockopt() they identify a buffer //! in which the value for the requested option(s) are to //! be returned. For getsockopt(), optlen is a value-result //! parameter, initially containing the size of the buffer //! pointed to by option_value, and modified on return to //! indicate the actual size of the value returned. If no option //! value is to be supplied or returned, option_value may be NULL. //! //! @Note On this version the following two socket options are enabled: //! The only protocol level supported in this version //! is SOL_SOCKET (level). //! 1. SOCKOPT_RECV_TIMEOUT (optname) //! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout //! in milliseconds. //! In that case optval should be pointer to UINT32. //! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on //! or off. //! In that case optval should be SOCK_ON or SOCK_OFF (optval). //! //! @sa setsockopt // //***************************************************************************** extern INT16 CC3000_EXPORT(getsockopt)(INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen); //***************************************************************************** // //! recv //! //! @param[in] sd socket handle //! @param[out] buf Points to the buffer where the message should be stored //! @param[in] len Specifies the length in bytes of the buffer pointed to //! by the buffer argument. //! @param[in] flags Specifies the type of message reception. //! On this version, this parameter is not supported. //! //! @return Return the number of bytes received, or -1 if an error //! occurred //! //! @brief function receives a message from a connection-mode socket //! //! @sa recvfrom //! //! @Note On this version, only blocking mode is supported. // //***************************************************************************** extern INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags); //***************************************************************************** // //! recvfrom //! //! @param[in] sd socket handle //! @param[out] buf Points to the buffer where the message should be stored //! @param[in] len Specifies the length in bytes of the buffer pointed to //! by the buffer argument. //! @param[in] flags Specifies the type of message reception. //! On this version, this parameter is not supported. //! @param[in] from pointer to an address structure indicating the source //! address: sockaddr. On this version only AF_INET is //! supported. //! @param[in] fromlen source address structure size //! //! @return Return the number of bytes received, or -1 if an error //! occurred //! //! @brief read data from socket //! function receives a message from a connection-mode or //! connectionless-mode socket. Note that raw sockets are not //! supported. //! //! @sa recv //! //! @Note On this version, only blocking mode is supported. // //***************************************************************************** extern INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, socklen_t *fromlen); //***************************************************************************** // //! send //! //! @param sd socket handle //! @param buf Points to a buffer containing the message to be sent //! @param len message size in bytes //! @param flags On this version, this parameter is not supported //! //! @return Return the number of bytes transmitted, or -1 if an //! error occurred //! //! @brief Write data to TCP socket //! This function is used to transmit a message to another //! socket. //! //! @Note On this version, only blocking mode is supported. //! //! @sa sendto // //***************************************************************************** extern INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags); //***************************************************************************** // //! sendto //! //! @param sd socket handle //! @param buf Points to a buffer containing the message to be sent //! @param len message size in bytes //! @param flags On this version, this parameter is not supported //! @param to pointer to an address structure indicating the destination //! address: sockaddr. On this version only AF_INET is //! supported. //! @param tolen destination address structure size //! //! @return Return the number of bytes transmitted, or -1 if an //! error occurred //! //! @brief Write data to TCP socket //! This function is used to transmit a message to another //! socket. //! //! @Note On this version, only blocking mode is supported. //! //! @sa send // //***************************************************************************** extern INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to, socklen_t tolen); //***************************************************************************** // //! mdnsAdvertiser //! //! @param[in] mdnsEnabled flag to enable/disable the mDNS feature //! @param[in] deviceServiceName Service name as part of the published //! canonical domain name //! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars //! //! //! @return On success, zero is returned, return SOC_ERROR if socket was not //! opened successfully, or if an error occurred. //! //! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. // //***************************************************************************** extern INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength); //***************************************************************************** // //! getmssvalue //! //! @param[in] sd socket descriptor //! //! @return On success, returns the MSS value of a TCP connection //! //! @brief Returns the MSS value of a TCP connection according to the socket descriptor // //***************************************************************************** extern UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd); //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif // __cplusplus #endif // __SOCKET_H__ micropython-1.12/drivers/cc3000/inc/wlan.h000066400000000000000000000533531357706137100202640ustar00rootroot00000000000000/***************************************************************************** * * wlan.h - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #ifndef __CC3000_WLAN_H__ #define __CC3000_WLAN_H__ #include "cc3000_common.h" //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif #define WLAN_SEC_UNSEC (0) #define WLAN_SEC_WEP (1) #define WLAN_SEC_WPA (2) #define WLAN_SEC_WPA2 (3) //***************************************************************************** // //! \addtogroup wlan_api //! @{ // //***************************************************************************** //***************************************************************************** // //! wlan_init //! //! @param sWlanCB Asynchronous events callback. //! 0 no event call back. //! -call back parameters: //! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, //! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, //! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, //! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, //! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR //! HCI_EVNT_WLAN_KEEPALIVE keepalive. //! 2) data: pointer to extra data that received by the event //! (NULL no data). //! 3) length: data length. //! -Events with extra data: //! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, //! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes //! for DNS server. //! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, //! 4 bytes Packets received, 4 bytes Min round time, //! 4 bytes Max round time and 4 bytes for Avg round time. //! //! @param sFWPatches 0 no patch or pointer to FW patches //! @param sDriverPatches 0 no patch or pointer to driver patches //! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches //! @param sReadWlanInterruptPin init callback. the callback read wlan //! interrupt status. //! @param sWlanInterruptEnable init callback. the callback enable wlan //! interrupt. //! @param sWlanInterruptDisable init callback. the callback disable wlan //! interrupt. //! @param sWriteWlanPin init callback. the callback write value //! to device pin. //! //! @return none //! //! @sa wlan_set_event_mask , wlan_start , wlan_stop //! //! @brief Initialize wlan driver //! //! @warning This function must be called before ANY other wlan driver function // //***************************************************************************** extern void wlan_init( tWlanCB sWlanCB, tFWPatches sFWPatches, tDriverPatches sDriverPatches, tBootLoaderPatches sBootLoaderPatches, tWlanReadInteruptPin sReadWlanInterruptPin, tWlanInterruptEnable sWlanInterruptEnable, tWlanInterruptDisable sWlanInterruptDisable, tWriteWlanPin sWriteWlanPin); //***************************************************************************** // //! wlan_start //! //! @param usPatchesAvailableAtHost - flag to indicate if patches available //! from host or from EEPROM. Due to the //! fact the patches are burn to the EEPROM //! using the patch programmer utility, the //! patches will be available from the EEPROM //! and not from the host. //! //! @return none //! //! @brief Start WLAN device. This function asserts the enable pin of //! the device (WLAN_EN), starting the HW initialization process. //! The function blocked until device Initialization is completed. //! Function also configure patches (FW, driver or bootloader) //! and calls appropriate device callbacks. //! //! @Note Prior calling the function wlan_init shall be called. //! @Warning This function must be called after wlan_init and before any //! other wlan API //! @sa wlan_init , wlan_stop //! // //***************************************************************************** extern int wlan_start(UINT16 usPatchesAvailableAtHost); //***************************************************************************** // //! wlan_stop //! //! @param none //! //! @return none //! //! @brief Stop WLAN device by putting it into reset state. //! //! @sa wlan_start // //***************************************************************************** extern void wlan_stop(void); //***************************************************************************** // //! wlan_connect //! //! @param sec_type security options: //! WLAN_SEC_UNSEC, //! WLAN_SEC_WEP (ASCII support only), //! WLAN_SEC_WPA or WLAN_SEC_WPA2 //! @param ssid up to 32 bytes and is ASCII SSID of the AP //! @param ssid_len length of the SSID //! @param bssid 6 bytes specified the AP bssid //! @param key up to 32 bytes specified the AP security key //! @param key_len key length //! //! @return On success, zero is returned. On error, negative is returned. //! Note that even though a zero is returned on success to trigger //! connection operation, it does not mean that CCC3000 is already //! connected. An asynchronous "Connected" event is generated when //! actual association process finishes and CC3000 is connected to //! the AP. If DHCP is set, An asynchronous "DHCP" event is //! generated when DHCP process is finish. //! //! //! @brief Connect to AP //! @warning Please Note that when connection to AP configured with security //! type WEP, please confirm that the key is set as ASCII and not //! as HEX. //! @sa wlan_disconnect // //***************************************************************************** #ifndef CC3000_TINY_DRIVER extern INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len, UINT8 *bssid, UINT8 *key, INT32 key_len); #else extern INT32 wlan_connect(CHAR *ssid, INT32 ssid_len); #endif //***************************************************************************** // //! wlan_disconnect //! //! @return 0 disconnected done, other CC3000 already disconnected //! //! @brief Disconnect connection from AP. //! //! @sa wlan_connect // //***************************************************************************** extern INT32 wlan_disconnect(void); //***************************************************************************** // //! wlan_add_profile //! //! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 //! @param ucSsid ssid SSID up to 32 bytes //! @param ulSsidLen ssid length //! @param ucBssid bssid 6 bytes //! @param ulPriority ulPriority profile priority. Lowest priority:0. //! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security //! @param ulGroupCipher_TxKeyIndex key index //! @param ulKeyMgmt KEY management //! @param ucPf_OrKey security key //! @param ulPassPhraseLen security key length for WPA\WPA2 //! //! @return On success, index (1-7) of the stored profile is returned. //! On error, -1 is returned. //! //! @brief When auto start is enabled, the device connects to //! station from the profiles table. Up to 7 profiles are supported. //! If several profiles configured the device choose the highest //! priority profile, within each priority group, device will choose //! profile based on security policy, signal strength, etc //! parameters. All the profiles are stored in CC3000 NVMEM. //! //! @sa wlan_ioctl_del_profile // //***************************************************************************** extern INT32 wlan_add_profile(UINT32 ulSecType, UINT8* ucSsid, UINT32 ulSsidLen, UINT8 *ucBssid, UINT32 ulPriority, UINT32 ulPairwiseCipher_Or_Key, UINT32 ulGroupCipher_TxKeyLen, UINT32 ulKeyMgmt, UINT8* ucPf_OrKey, UINT32 ulPassPhraseLen); //***************************************************************************** // //! wlan_ioctl_del_profile //! //! @param index number of profile to delete //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Delete WLAN profile //! //! @Note In order to delete all stored profile, set index to 255. //! //! @sa wlan_add_profile // //***************************************************************************** extern INT32 wlan_ioctl_del_profile(UINT32 ulIndex); //***************************************************************************** // //! wlan_set_event_mask //! //! @param mask mask option: //! HCI_EVNT_WLAN_UNSOL_CONNECT connect event //! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event //! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done //! HCI_EVNT_WLAN_UNSOL_INIT init done //! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report //! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report //! HCI_EVNT_WLAN_KEEPALIVE keepalive //! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission //! Saved: no. //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Mask event according to bit mask. In case that event is //! masked (1), the device will not send the masked event to host. // //***************************************************************************** extern INT32 wlan_set_event_mask(UINT32 ulMask); //***************************************************************************** // //! wlan_ioctl_statusget //! //! @param none //! //! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, //! STATUS_CONNECTING or WLAN_STATUS_CONNECTED //! //! @brief get wlan status: disconnected, scanning, connecting or connected // //***************************************************************************** extern INT32 wlan_ioctl_statusget(void); //***************************************************************************** // //! wlan_ioctl_set_connection_policy //! //! @param should_connect_to_open_ap enable(1), disable(0) connect to any //! available AP. This parameter corresponds to the configuration of //! item # 3 in the brief description. //! @param should_use_fast_connect enable(1), disable(0). if enabled, tries //! to connect to the last connected AP. This parameter corresponds //! to the configuration of item # 1 in the brief description. //! @param auto_start enable(1), disable(0) auto connect //! after reset and periodically reconnect if needed. This //! configuration configures option 2 in the above description. //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief When auto is enabled, the device tries to connect according //! the following policy: //! 1) If fast connect is enabled and last connection is valid, //! the device will try to connect to it without the scanning //! procedure (fast). The last connection will be marked as //! invalid, due to adding/removing profile. //! 2) If profile exists, the device will try to connect it //! (Up to seven profiles). //! 3) If fast and profiles are not found, and open mode is //! enabled, the device will try to connect to any AP. //! * Note that the policy settings are stored in the CC3000 NVMEM. //! //! @sa wlan_add_profile , wlan_ioctl_del_profile // //***************************************************************************** extern INT32 wlan_ioctl_set_connection_policy( UINT32 should_connect_to_open_ap, UINT32 should_use_fast_connect, UINT32 ulUseProfiles); //***************************************************************************** // //! wlan_ioctl_get_scan_results //! //! @param[in] scan_timeout parameter not supported //! @param[out] ucResults scan result (_wlan_full_scan_results_args_t) //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Gets entry from scan result table. //! The scan results are returned one by one, and each entry //! represents a single AP found in the area. The following is a //! format of the scan result: //! - 4 Bytes: number of networks found //! - 4 Bytes: The status of the scan: 0 - aged results, //! 1 - results valid, 2 - no results //! - 42 bytes: Result entry, where the bytes are arranged as follows: //! //! - 1 bit isValid - is result valid or not //! - 7 bits rssi - RSSI value; //! - 2 bits: securityMode - security mode of the AP: //! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 //! - 6 bits: SSID name length //! - 2 bytes: the time at which the entry has entered into //! scans result table //! - 32 bytes: SSID name //! - 6 bytes: BSSID //! //! @Note scan_timeout, is not supported on this version. //! //! @sa wlan_ioctl_set_scan_params // //***************************************************************************** extern INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout, UINT8 *ucResults); //***************************************************************************** // //! wlan_ioctl_set_scan_params //! //! @param uiEnable - start/stop application scan: //! 1 = start scan with default interval value of 10 min. //! in order to set a different scan interval value apply the value //! in milliseconds. minimum 1 second. 0=stop). Wlan reset //! (wlan_stop() wlan_start()) is needed when changing scan interval //! value. Saved: No //! @param uiMinDwellTime minimum dwell time value to be used for each //! channel, in milliseconds. Saved: yes //! Recommended Value: 100 (Default: 20) //! @param uiMaxDwellTime maximum dwell time value to be used for each //! channel, in milliseconds. Saved: yes //! Recommended Value: 100 (Default: 30) //! @param uiNumOfProbeRequests max probe request between dwell time. //! Saved: yes. Recommended Value: 5 (Default:2) //! @param uiChannelMask bitwise, up to 13 channels (0x1fff). //! Saved: yes. Default: 0x7ff //! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) //! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0) //! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) //! @param aiIntervalList pointer to array with 16 entries (16 channels) //! each entry (UINT32) holds timeout between periodic scan //! (connection scan) - in milliseconds. Saved: yes. Default 2000ms. //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief start and stop scan procedure. Set scan parameters. //! //! @Note uiDefaultTxPower, is not supported on this version. //! //! @sa wlan_ioctl_get_scan_results // //***************************************************************************** extern INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 uiMinDwellTime,UINT32 uiMaxDwellTime, UINT32 uiNumOfProbeRequests, UINT32 uiChannelMask, INT32 iRSSIThreshold,UINT32 uiSNRThreshold, UINT32 uiDefaultTxPower, UINT32 *aiIntervalList); //***************************************************************************** // //! wlan_smart_config_start //! //! @param algoEncryptedFlag indicates whether the information is encrypted //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Start to acquire device profile. The device acquire its own //! profile, if profile message is found. The acquired AP information //! is stored in CC3000 EEPROM only in case AES128 encryption is used. //! In case AES128 encryption is not used, a profile is created by //! CC3000 internally. //! //! @Note An asynchronous event - Smart Config Done will be generated as soon //! as the process finishes successfully. //! //! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop // //***************************************************************************** extern INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag); //***************************************************************************** // //! wlan_smart_config_stop //! //! @param algoEncryptedFlag indicates whether the information is encrypted //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Stop the acquire profile procedure //! //! @sa wlan_smart_config_start , wlan_smart_config_set_prefix // //***************************************************************************** extern INT32 wlan_smart_config_stop(void); //***************************************************************************** // //! wlan_smart_config_set_prefix //! //! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config. //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Configure station ssid prefix. The prefix is used internally //! in CC3000. It should always be TTT. //! //! @Note The prefix is stored in CC3000 NVMEM //! //! @sa wlan_smart_config_start , wlan_smart_config_stop // //***************************************************************************** extern INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix); //***************************************************************************** // //! wlan_smart_config_process //! //! @param none //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief process the acquired data and store it as a profile. The acquired //! AP information is stored in CC3000 EEPROM encrypted. //! The encrypted data is decrypted and stored as a profile. //! behavior is as defined by connection policy. // //***************************************************************************** extern INT32 wlan_smart_config_process(void); //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif // __cplusplus #endif // __CC3000_WLAN_H__ micropython-1.12/drivers/cc3000/src/000077500000000000000000000000001357706137100171575ustar00rootroot00000000000000micropython-1.12/drivers/cc3000/src/cc3000_common.c000066400000000000000000000127201357706137100215650ustar00rootroot00000000000000/***************************************************************************** * * cc3000_common.c.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ //***************************************************************************** // //! \addtogroup common_api //! @{ // //***************************************************************************** /****************************************************************************** * * Include files * *****************************************************************************/ #include "cc3000_common.h" #include "socket.h" #include "wlan.h" #include "evnt_handler.h" //***************************************************************************** // //! __error__ //! //! @param pcFilename - file name, where error occurred //! @param ulLine - line number, where error occurred //! //! @return none //! //! @brief stub function for ASSERT macro // //***************************************************************************** void __error__(CHAR *pcFilename, UINT32 ulLine) { //TODO full up function } //***************************************************************************** // //! UINT32_TO_STREAM_f //! //! @param p pointer to the new stream //! @param u32 pointer to the 32 bit //! //! @return pointer to the new stream //! //! @brief This function is used for copying 32 bit to stream //! while converting to little endian format. // //***************************************************************************** UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32) { *(p)++ = (UINT8)(u32); *(p)++ = (UINT8)((u32) >> 8); *(p)++ = (UINT8)((u32) >> 16); *(p)++ = (UINT8)((u32) >> 24); return p; } //***************************************************************************** // //! UINT16_TO_STREAM_f //! //! @param p pointer to the new stream //! @param u32 pointer to the 16 bit //! //! @return pointer to the new stream //! //! @brief This function is used for copying 16 bit to stream //! while converting to little endian format. // //***************************************************************************** UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16) { *(p)++ = (UINT8)(u16); *(p)++ = (UINT8)((u16) >> 8); return p; } //***************************************************************************** // //! STREAM_TO_UINT16_f //! //! @param p pointer to the stream //! @param offset offset in the stream //! //! @return pointer to the new 16 bit //! //! @brief This function is used for copying received stream to //! 16 bit in little endian format. // //***************************************************************************** UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset) { return (UINT16)((UINT16)((UINT16) (*(p + offset + 1)) << 8) + (UINT16)(*(p + offset))); } //***************************************************************************** // //! STREAM_TO_UINT32_f //! //! @param p pointer to the stream //! @param offset offset in the stream //! //! @return pointer to the new 32 bit //! //! @brief This function is used for copying received stream to //! 32 bit in little endian format. // //***************************************************************************** UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset) { return (UINT32)((UINT32)((UINT32) (*(p + offset + 3)) << 24) + (UINT32)((UINT32) (*(p + offset + 2)) << 16) + (UINT32)((UINT32) (*(p + offset + 1)) << 8) + (UINT32)(*(p + offset))); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/drivers/cc3000/src/ccspi.c000066400000000000000000000361211357706137100204270ustar00rootroot00000000000000/***************************************************************************** * * spi.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #include #include "py/runtime.h" #include "pin.h" #include "led.h" #include "extint.h" #include "spi.h" #include "ccspi.h" #include "evnt_handler.h" #if 0 // print debugging info #include #define DEBUG_printf(args...) printf(args) #else // don't print debugging info #define DEBUG_printf(args...) (void)0 #endif // these need to be set to valid values before anything in this file will work STATIC const spi_t *SPI_HANDLE = NULL; STATIC const pin_obj_t *PIN_CS = NULL; STATIC const pin_obj_t *PIN_EN = NULL; STATIC const pin_obj_t *PIN_IRQ = NULL; #define CS_LOW() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_RESET) #define CS_HIGH() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET) #define READ 3 #define WRITE 1 #define HI(value) (((value) & 0xFF00) >> 8) #define LO(value) ((value) & 0x00FF) #define SPI_TIMEOUT (1000) #define HEADERS_SIZE_EVNT (SPI_HEADER_SIZE + 5) /* SPI bus states */ #define eSPI_STATE_POWERUP (0) #define eSPI_STATE_INITIALIZED (1) #define eSPI_STATE_IDLE (2) #define eSPI_STATE_WRITE_IRQ (3) #define eSPI_STATE_WRITE_FIRST_PORTION (4) #define eSPI_STATE_WRITE_EOT (5) #define eSPI_STATE_READ_IRQ (6) #define eSPI_STATE_READ_FIRST_PORTION (7) #define eSPI_STATE_READ_EOT (8) // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) // for the purpose of detection of the overrun. The location of the memory where the magic number // resides shall never be written. In case it is written - the overrun occured and either recevie function // or send function will stuck forever. #define CC3000_BUFFER_MAGIC_NUMBER (0xDE) typedef struct { gcSpiHandleRx SPIRxHandler; unsigned short usTxPacketLength; unsigned short usRxPacketLength; unsigned long ulSpiState; unsigned char *pTxPacket; unsigned char *pRxPacket; } tSpiInformation; STATIC tSpiInformation sSpiInformation; STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE]; unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE]; STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj; // set the pins to use to communicate with the CC3000 // the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) { SPI_HANDLE = spi; PIN_CS = pin_cs; PIN_EN = pin_en; PIN_IRQ = pin_irq; } void SpiClose(void) { if (sSpiInformation.pRxPacket) { sSpiInformation.pRxPacket = 0; } tSLInformation.WlanInterruptDisable(); //HAL_SPI_DeInit(SPI_HANDLE); } void SpiOpen(gcSpiHandleRx pfRxHandler) { DEBUG_printf("SpiOpen\n"); /* initialize SPI state */ sSpiInformation.ulSpiState = eSPI_STATE_POWERUP; sSpiInformation.SPIRxHandler = pfRxHandler; sSpiInformation.usTxPacketLength = 0; sSpiInformation.pTxPacket = NULL; sSpiInformation.pRxPacket = (unsigned char *)spi_buffer; sSpiInformation.usRxPacketLength = 0; spi_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; /* SPI configuration */ SPI_InitTypeDef *init = &SPI_HANDLE->spi->Init; init->Mode = SPI_MODE_MASTER; init->Direction = SPI_DIRECTION_2LINES; init->DataSize = SPI_DATASIZE_8BIT; init->CLKPolarity = SPI_POLARITY_LOW; init->CLKPhase = SPI_PHASE_2EDGE; init->NSS = SPI_NSS_SOFT; init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; init->FirstBit = SPI_FIRSTBIT_MSB; init->TIMode = SPI_TIMODE_DISABLED; init->CRCCalculation = SPI_CRCCALCULATION_DISABLED; init->CRCPolynomial = 7; spi_init(SPI_HANDLE, false); // configure wlan CS and EN pins GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Alternate = 0; GPIO_InitStructure.Pin = PIN_CS->pin_mask; HAL_GPIO_Init(PIN_CS->gpio, &GPIO_InitStructure); GPIO_InitStructure.Pin = PIN_EN->pin_mask; HAL_GPIO_Init(PIN_EN->gpio, &GPIO_InitStructure); HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET); HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, GPIO_PIN_RESET); /* do a dummy read, this ensures SCLK is low before actual communications start, it might be required */ CS_LOW(); uint8_t buf[1]; HAL_SPI_Receive(SPI_HANDLE->spi, buf, sizeof(buf), SPI_TIMEOUT); CS_HIGH(); // register EXTI extint_register((mp_obj_t)PIN_IRQ, GPIO_MODE_IT_FALLING, GPIO_PULLUP, (mp_obj_t)&irq_callback_obj, true); extint_enable(PIN_IRQ->pin); DEBUG_printf("SpiOpen finished; IRQ.pin=%d IRQ_LINE=%d\n", PIN_IRQ->pin, PIN_IRQ->pin); } long ReadWlanInterruptPin(void) { return HAL_GPIO_ReadPin(PIN_IRQ->gpio, PIN_IRQ->pin_mask); } void WriteWlanPin(unsigned char val) { HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, (WLAN_ENABLE)? GPIO_PIN_SET:GPIO_PIN_RESET); } STATIC void SpiWriteDataSynchronous(unsigned char *data, unsigned short size) { DEBUG_printf("SpiWriteDataSynchronous(data=%p [%x %x %x %x], size=%u)\n", data, data[0], data[1], data[2], data[3], size); __disable_irq(); if (HAL_SPI_TransmitReceive(SPI_HANDLE->spi, data, data, size, SPI_TIMEOUT) != HAL_OK) { //BREAK(); } __enable_irq(); DEBUG_printf(" - rx data = [%x %x %x %x]\n", data[0], data[1], data[2], data[3]); } STATIC void SpiReadDataSynchronous(unsigned char *data, unsigned short size) { memset(data, READ, size); __disable_irq(); if (HAL_SPI_TransmitReceive(SPI_HANDLE->spi, data, data, size, SPI_TIMEOUT) != HAL_OK) { //BREAK(); } __enable_irq(); } STATIC void __delay_cycles(volatile int x) { x *= 6; // for 168 MHz CPU while (x--); } STATIC long SpiFirstWrite(unsigned char *ucBuf, unsigned short usLength) { DEBUG_printf("SpiFirstWrite %lu\n", sSpiInformation.ulSpiState); CS_LOW(); // Assuming we are running on 24 MHz ~50 micro delay is 1200 cycles; __delay_cycles(1200); // SPI writes first 4 bytes of data SpiWriteDataSynchronous(ucBuf, 4); __delay_cycles(1200); SpiWriteDataSynchronous(ucBuf + 4, usLength - 4); // From this point on - operate in a regular way sSpiInformation.ulSpiState = eSPI_STATE_IDLE; CS_HIGH(); return(0); } long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength) { DEBUG_printf("SpiWrite %lu\n", sSpiInformation.ulSpiState); unsigned char ucPad = 0; // Figure out the total length of the packet in order to figure out if there // is padding or not if(!(usLength & 0x0001)) { ucPad++; } pUserBuffer[0] = WRITE; pUserBuffer[1] = HI(usLength + ucPad); pUserBuffer[2] = LO(usLength + ucPad); pUserBuffer[3] = 0; pUserBuffer[4] = 0; usLength += (SPI_HEADER_SIZE + ucPad); // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun // occurred - and we will stuck here forever! if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { while (1); } if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) { while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED); } if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) { // This is time for first TX/RX transactions over SPI: // the IRQ is down - so need to send read buffer size command SpiFirstWrite(pUserBuffer, usLength); } else { // // We need to prevent here race that can occur in case 2 back to back packets are sent to the // device, so the state will move to IDLE and once again to not IDLE due to IRQ // tSLInformation.WlanInterruptDisable(); while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE); sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ; sSpiInformation.pTxPacket = pUserBuffer; sSpiInformation.usTxPacketLength = usLength; // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation CS_LOW(); // Re-enable IRQ - if it was not disabled - this is not a problem... tSLInformation.WlanInterruptEnable(); // check for a missing interrupt between the CS assertion and enabling back the interrupts if (tSLInformation.ReadWlanInterruptPin() == 0) { SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); sSpiInformation.ulSpiState = eSPI_STATE_IDLE; CS_HIGH(); } } // Due to the fact that we are currently implementing a blocking situation // here we will wait till end of transaction while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState); return(0); } #if 0 unused STATIC void SpiReadPacket(void) { int length; /* read SPI header */ SpiReadDataSynchronous(sSpiInformation.pRxPacket, SPI_HEADER_SIZE); /* parse data length */ STREAM_TO_UINT8(sSpiInformation.pRxPacket, SPI_HEADER_SIZE-1, length); /* read the remainder of the packet */ SpiReadDataSynchronous(sSpiInformation.pRxPacket + SPI_HEADER_SIZE, length); sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; } #endif STATIC void SpiReadHeader(void) { SpiReadDataSynchronous(sSpiInformation.pRxPacket, 10); } STATIC void SpiTriggerRxProcessing(void) { SpiPauseSpi(); CS_HIGH(); // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun // occurred - and we will stuck here forever! if (sSpiInformation.pRxPacket[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { while (1); } sSpiInformation.ulSpiState = eSPI_STATE_IDLE; sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket + SPI_HEADER_SIZE); } STATIC long SpiReadDataCont(void) { long data_to_recv=0; unsigned char *evnt_buff, type; //determine what type of packet we have evnt_buff = sSpiInformation.pRxPacket; STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); switch (type) { case HCI_TYPE_DATA:{ // We need to read the rest of data.. STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv); if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) { data_to_recv++; } if (data_to_recv) { SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); } break; } case HCI_TYPE_EVNT: { // Calculate the rest length of the data STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv); data_to_recv -= 1; // Add padding byte if needed if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) { data_to_recv++; } if (data_to_recv) { SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); } sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; break; } } return 0; } STATIC void SSIContReadOperation(void) { // The header was read - continue with the payload read if (!SpiReadDataCont()) { /* All the data was read - finalize handling by switching to the task and calling from task Event Handler */ SpiTriggerRxProcessing(); } } STATIC mp_obj_t irq_callback(mp_obj_t line) { DEBUG_printf("<< IRQ; state=%lu >>\n", sSpiInformation.ulSpiState); switch (sSpiInformation.ulSpiState) { case eSPI_STATE_POWERUP: /* This means IRQ line was low call a callback of HCI Layer to inform on event */ DEBUG_printf(" - POWERUP\n"); sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED; break; case eSPI_STATE_IDLE: DEBUG_printf(" - IDLE\n"); sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ; /* IRQ line goes down - we are start reception */ CS_LOW(); // Wait for TX/RX Compete which will come as DMA interrupt SpiReadHeader(); sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; SSIContReadOperation(); break; case eSPI_STATE_WRITE_IRQ: DEBUG_printf(" - WRITE IRQ\n"); SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); sSpiInformation.ulSpiState = eSPI_STATE_IDLE; CS_HIGH(); break; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback); void SpiPauseSpi(void) { DEBUG_printf("SpiPauseSpi\n"); extint_disable(PIN_IRQ->pin); } void SpiResumeSpi(void) { DEBUG_printf("SpiResumeSpi\n"); extint_enable(PIN_IRQ->pin); } micropython-1.12/drivers/cc3000/src/evnt_handler.c000066400000000000000000000642151357706137100220040ustar00rootroot00000000000000/***************************************************************************** * * evnt_handler.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ //***************************************************************************** // //! \addtogroup evnt_handler_api //! @{ // //****************************************************************************** //****************************************************************************** // INCLUDE FILES //****************************************************************************** #include "cc3000_common.h" #include "string.h" #include "hci.h" #include "evnt_handler.h" #include "wlan.h" #include "socket.h" #include "netapp.h" #include "ccspi.h" //***************************************************************************** // COMMON DEFINES //***************************************************************************** #define FLOW_CONTROL_EVENT_HANDLE_OFFSET (0) #define FLOW_CONTROL_EVENT_BLOCK_MODE_OFFSET (1) #define FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET (2) #define FLOW_CONTROL_EVENT_SIZE (4) #define BSD_RSP_PARAMS_SOCKET_OFFSET (0) #define BSD_RSP_PARAMS_STATUS_OFFSET (4) #define GET_HOST_BY_NAME_RETVAL_OFFSET (0) #define GET_HOST_BY_NAME_ADDR_OFFSET (4) #define ACCEPT_SD_OFFSET (0) #define ACCEPT_RETURN_STATUS_OFFSET (4) #define ACCEPT_ADDRESS__OFFSET (8) #define SL_RECEIVE_SD_OFFSET (0) #define SL_RECEIVE_NUM_BYTES_OFFSET (4) #define SL_RECEIVE__FLAGS__OFFSET (8) #define SELECT_STATUS_OFFSET (0) #define SELECT_READFD_OFFSET (4) #define SELECT_WRITEFD_OFFSET (8) #define SELECT_EXFD_OFFSET (12) #define NETAPP_IPCONFIG_IP_OFFSET (0) #define NETAPP_IPCONFIG_SUBNET_OFFSET (4) #define NETAPP_IPCONFIG_GW_OFFSET (8) #define NETAPP_IPCONFIG_DHCP_OFFSET (12) #define NETAPP_IPCONFIG_DNS_OFFSET (16) #define NETAPP_IPCONFIG_MAC_OFFSET (20) #define NETAPP_IPCONFIG_SSID_OFFSET (26) #define NETAPP_IPCONFIG_IP_LENGTH (4) #define NETAPP_IPCONFIG_MAC_LENGTH (6) #define NETAPP_IPCONFIG_SSID_LENGTH (32) #define NETAPP_PING_PACKETS_SENT_OFFSET (0) #define NETAPP_PING_PACKETS_RCVD_OFFSET (4) #define NETAPP_PING_MIN_RTT_OFFSET (8) #define NETAPP_PING_MAX_RTT_OFFSET (12) #define NETAPP_PING_AVG_RTT_OFFSET (16) #define GET_SCAN_RESULTS_TABlE_COUNT_OFFSET (0) #define GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET (4) #define GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET (8) #define GET_SCAN_RESULTS_FRAME_TIME_OFFSET (10) #define GET_SCAN_RESULTS_SSID_MAC_LENGTH (38) #define GET_MSS_VAL_RETVAL_OFFSET (0) //***************************************************************************** // GLOBAL VARAIABLES //***************************************************************************** UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL; //***************************************************************************** // Prototypes for the static functions //***************************************************************************** static INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent); static void update_socket_active_status(CHAR *resp_params); //***************************************************************************** // //! hci_unsol_handle_patch_request //! //! @param event_hdr event header //! //! @return none //! //! @brief Handle unsolicited event from type patch request // //***************************************************************************** void hci_unsol_handle_patch_request(CHAR *event_hdr) { CHAR *params = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE; UINT32 ucLength = 0; CHAR *patch; switch (*params) { case HCI_EVENT_PATCHES_DRV_REQ: if (tSLInformation.sDriverPatches) { patch = tSLInformation.sDriverPatches(&ucLength); if (patch) { hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ, tSLInformation.pucTxCommandBuffer, patch, ucLength); return; } } // Send 0 length Patches response event hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ, tSLInformation.pucTxCommandBuffer, 0, 0); break; case HCI_EVENT_PATCHES_FW_REQ: if (tSLInformation.sFWPatches) { patch = tSLInformation.sFWPatches(&ucLength); // Build and send a patch if (patch) { hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, tSLInformation.pucTxCommandBuffer, patch, ucLength); return; } } // Send 0 length Patches response event hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, tSLInformation.pucTxCommandBuffer, 0, 0); break; case HCI_EVENT_PATCHES_BOOTLOAD_REQ: if (tSLInformation.sBootLoaderPatches) { patch = tSLInformation.sBootLoaderPatches(&ucLength); if (patch) { hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, tSLInformation.pucTxCommandBuffer, patch, ucLength); return; } } // Send 0 length Patches response event hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, tSLInformation.pucTxCommandBuffer, 0, 0); break; } } //***************************************************************************** // //! hci_event_handler //! //! @param pRetParams incoming data buffer //! @param from from information (in case of data received) //! @param fromlen from information length (in case of data received) //! //! @return none //! //! @brief Parse the incoming events packets and issues corresponding //! event handler from global array of handlers pointers // //***************************************************************************** UINT8 * hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen) { UINT8 *pucReceivedData, ucArgsize; UINT16 usLength; UINT8 *pucReceivedParams; UINT16 usReceivedEventOpcode = 0; UINT32 retValue32; UINT8 * RecvParams; UINT8 *RetParams; while (1) { if (tSLInformation.usEventOrDataReceived != 0) { pucReceivedData = (tSLInformation.pucReceivedData); if (*pucReceivedData == HCI_TYPE_EVNT) { // Event Received STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_EVENT_OPCODE_OFFSET, usReceivedEventOpcode); pucReceivedParams = pucReceivedData + HCI_EVENT_HEADER_SIZE; RecvParams = pucReceivedParams; RetParams = pRetParams; // In case unsolicited event received - here the handling finished if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 0) { STREAM_TO_UINT8(pucReceivedData, HCI_DATA_LENGTH_OFFSET, usLength); switch(usReceivedEventOpcode) { case HCI_CMND_READ_BUFFER_SIZE: { STREAM_TO_UINT8((CHAR *)pucReceivedParams, 0, tSLInformation.usNumberOfFreeBuffers); STREAM_TO_UINT16((CHAR *)pucReceivedParams, 1, tSLInformation.usSlBufferLength); } break; case HCI_CMND_WLAN_CONFIGURE_PATCH: case HCI_NETAPP_DHCP: case HCI_NETAPP_PING_SEND: case HCI_NETAPP_PING_STOP: case HCI_NETAPP_ARP_FLUSH: case HCI_NETAPP_SET_DEBUG_LEVEL: case HCI_NETAPP_SET_TIMERS: case HCI_EVNT_NVMEM_READ: case HCI_EVNT_NVMEM_CREATE_ENTRY: case HCI_CMND_NVMEM_WRITE_PATCH: case HCI_NETAPP_PING_REPORT: case HCI_EVNT_MDNS_ADVERTISE: STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET ,*(UINT8 *)pRetParams); break; case HCI_CMND_SETSOCKOPT: case HCI_CMND_WLAN_CONNECT: case HCI_CMND_WLAN_IOCTL_STATUSGET: case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE: case HCI_CMND_WLAN_IOCTL_DEL_PROFILE: case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: case HCI_CMND_EVENT_MASK: case HCI_EVNT_WLAN_DISCONNECT: case HCI_EVNT_SOCKET: case HCI_EVNT_BIND: case HCI_CMND_LISTEN: case HCI_EVNT_CLOSE_SOCKET: case HCI_EVNT_CONNECT: case HCI_EVNT_NVMEM_WRITE: STREAM_TO_UINT32((CHAR *)pucReceivedParams,0 ,*(UINT32 *)pRetParams); break; case HCI_EVNT_READ_SP_VERSION: STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET ,*(UINT8 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 1; STREAM_TO_UINT32((CHAR *)pucReceivedParams, 0, retValue32); UINT32_TO_STREAM((UINT8 *)pRetParams, retValue32); break; case HCI_EVNT_BSD_GETHOSTBYNAME: STREAM_TO_UINT32((CHAR *)pucReceivedParams ,GET_HOST_BY_NAME_RETVAL_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams ,GET_HOST_BY_NAME_ADDR_OFFSET,*(UINT32 *)pRetParams); break; case HCI_EVNT_GETMSSVALUE: STREAM_TO_UINT16((CHAR *)pucReceivedParams ,GET_MSS_VAL_RETVAL_OFFSET,*(UINT16 *)pRetParams); break; case HCI_EVNT_ACCEPT: { STREAM_TO_UINT32((CHAR *)pucReceivedParams,ACCEPT_SD_OFFSET ,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams ,ACCEPT_RETURN_STATUS_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; //This argument returns in network order memcpy((UINT8 *)pRetParams, pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr)); break; } case HCI_EVNT_RECV: case HCI_EVNT_RECVFROM: { STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(UINT32 *)pRetParams); if(((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == ERROR_SOCKET_INACTIVE) { set_socket_active_status(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE); } break; } case HCI_EVNT_SEND: case HCI_EVNT_SENDTO: { STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; break; } case HCI_EVNT_SELECT: { STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_STATUS_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_READFD_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_EXFD_OFFSET,*(UINT32 *)pRetParams); break; } case HCI_CMND_GETSOCKOPT: STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)pRetParams)->iStatus); //This argument returns in network order memcpy((UINT8 *)pRetParams, pucReceivedParams, 4); break; case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS: STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 4; STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 2; STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(UINT32 *)pRetParams); pRetParams = ((CHAR *)pRetParams) + 2; memcpy((UINT8 *)pRetParams, (CHAR *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH); break; case HCI_CMND_SIMPLE_LINK_START: break; case HCI_NETAPP_IPCONFIG: //Read IP address STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read subnet STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read default GW STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read DHCP server STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read DNS server STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read Mac address STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH); RecvParams += 6; //Read SSID STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH); } } if (usReceivedEventOpcode == tSLInformation.usRxEventOpcode) { tSLInformation.usRxEventOpcode = 0; } } else { pucReceivedParams = pucReceivedData; STREAM_TO_UINT8((CHAR *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize); STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength); // Data received: note that the only case where from and from length // are not null is in recv from, so fill the args accordingly if (from) { STREAM_TO_UINT32((CHAR *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(UINT32 *)fromlen); memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen); } memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize, usLength - ucArgsize); tSLInformation.usRxDataPending = 0; } tSLInformation.usEventOrDataReceived = 0; SpiResumeSpi(); // Since we are going to TX - we need to handle this event after the // ResumeSPi since we need interrupts if ((*pucReceivedData == HCI_TYPE_EVNT) && (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ)) { hci_unsol_handle_patch_request((CHAR *)pucReceivedData); } if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0)) { return NULL; } } } } //***************************************************************************** // //! hci_unsol_event_handler //! //! @param event_hdr event header //! //! @return 1 if event supported and handled //! 0 if event is not supported //! //! @brief Handle unsolicited events // //***************************************************************************** INT32 hci_unsol_event_handler(CHAR *event_hdr) { CHAR * data = NULL; INT32 event_type; UINT32 NumberOfReleasedPackets; UINT32 NumberOfSentPackets; STREAM_TO_UINT16(event_hdr, HCI_EVENT_OPCODE_OFFSET,event_type); if (event_type & HCI_EVNT_UNSOL_BASE) { switch(event_type) { case HCI_EVNT_DATA_UNSOL_FREE_BUFF: { hci_event_unsol_flowcontrol_handler(event_hdr); NumberOfReleasedPackets = tSLInformation.NumberOfReleasedPackets; NumberOfSentPackets = tSLInformation.NumberOfSentPackets; if (NumberOfReleasedPackets == NumberOfSentPackets) { if (tSLInformation.InformHostOnTxComplete) { tSLInformation.sWlanCB(HCI_EVENT_CC3000_CAN_SHUT_DOWN, NULL, 0); } } return 1; } } } if(event_type & HCI_EVNT_WLAN_UNSOL_BASE) { switch(event_type) { case HCI_EVNT_WLAN_KEEPALIVE: case HCI_EVNT_WLAN_UNSOL_CONNECT: case HCI_EVNT_WLAN_UNSOL_DISCONNECT: case HCI_EVNT_WLAN_UNSOL_INIT: case HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE: if( tSLInformation.sWlanCB ) { tSLInformation.sWlanCB(event_type, 0, 0); } break; case HCI_EVNT_WLAN_UNSOL_DHCP: { UINT8 params[NETAPP_IPCONFIG_MAC_OFFSET + 1]; // extra byte is for the status UINT8 *recParams = params; data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE; //Read IP address STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); data += 4; //Read subnet STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); data += 4; //Read default GW STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); data += 4; //Read DHCP server STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); data += 4; //Read DNS server STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); // read the status STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, *recParams); if( tSLInformation.sWlanCB ) { tSLInformation.sWlanCB(event_type, (CHAR *)params, sizeof(params)); } } break; case HCI_EVNT_WLAN_ASYNC_PING_REPORT: { netapp_pingreport_args_t params; data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE; STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_SENT_OFFSET, params.packets_sent); STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_RCVD_OFFSET, params.packets_received); STREAM_TO_UINT32(data, NETAPP_PING_MIN_RTT_OFFSET, params.min_round_time); STREAM_TO_UINT32(data, NETAPP_PING_MAX_RTT_OFFSET, params.max_round_time); STREAM_TO_UINT32(data, NETAPP_PING_AVG_RTT_OFFSET, params.avg_round_time); if( tSLInformation.sWlanCB ) { tSLInformation.sWlanCB(event_type, (CHAR *)¶ms, sizeof(params)); } } break; case HCI_EVNT_BSD_TCP_CLOSE_WAIT: { data = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE; if( tSLInformation.sWlanCB ) { //data[0] represents the socket id, for which FIN was received by remote. //Upon receiving this event, the user can close the socket, or else the //socket will be closded after inacvitity timeout (by default 60 seconds) tSLInformation.sWlanCB(event_type, data, 1); } } break; //'default' case which means "event not supported" default: return (0); } return(1); } if ((event_type == HCI_EVNT_SEND) || (event_type == HCI_EVNT_SENDTO) || (event_type == HCI_EVNT_WRITE)) { CHAR *pArg; INT32 status; pArg = M_BSD_RESP_PARAMS_OFFSET(event_hdr); STREAM_TO_UINT32(pArg, BSD_RSP_PARAMS_STATUS_OFFSET,status); if (ERROR_SOCKET_INACTIVE == status) { // The only synchronous event that can come from SL device in form of // command complete is "Command Complete" on data sent, in case SL device // was unable to transmit STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, tSLInformation.slTransmitDataError); update_socket_active_status(M_BSD_RESP_PARAMS_OFFSET(event_hdr)); return (1); } else return (0); } //handle a case where unsolicited event arrived, but was not handled by any of the cases above if ((event_type != tSLInformation.usRxEventOpcode) && (event_type != HCI_EVNT_PATCHES_REQ)) { return(1); } return(0); } //***************************************************************************** // //! hci_unsolicited_event_handler //! //! @param None //! //! @return ESUCCESS if successful, EFAIL if an error occurred //! //! @brief Parse the incoming unsolicited event packets and issues //! corresponding event handler. // //***************************************************************************** INT32 hci_unsolicited_event_handler(void) { UINT32 res = 0; UINT8 *pucReceivedData; if (tSLInformation.usEventOrDataReceived != 0) { pucReceivedData = (tSLInformation.pucReceivedData); if (*pucReceivedData == HCI_TYPE_EVNT) { // In case unsolicited event received - here the handling finished if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 1) { // There was an unsolicited event received - we can release the buffer // and clean the event received tSLInformation.usEventOrDataReceived = 0; res = 1; SpiResumeSpi(); } } } return res; } //***************************************************************************** // //! set_socket_active_status //! //! @param Sd //! @param Status //! @return none //! //! @brief Check if the socket ID and status are valid and set //! accordingly the global socket status // //***************************************************************************** void set_socket_active_status(INT32 Sd, INT32 Status) { if(M_IS_VALID_SD(Sd) && M_IS_VALID_STATUS(Status)) { socket_active_status &= ~(1 << Sd); /* clean socket's mask */ socket_active_status |= (Status << Sd); /* set new socket's mask */ } } //***************************************************************************** // //! hci_event_unsol_flowcontrol_handler //! //! @param pEvent pointer to the string contains parameters for IPERF //! @return ESUCCESS if successful, EFAIL if an error occurred //! //! @brief Called in case unsolicited event from type //! HCI_EVNT_DATA_UNSOL_FREE_BUFF has received. //! Keep track on the number of packets transmitted and update the //! number of free buffer in the SL device. // //***************************************************************************** INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent) { INT32 temp, value; UINT16 i; UINT16 pusNumberOfHandles=0; CHAR *pReadPayload; STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles); pReadPayload = ((CHAR *)pEvent + HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles)); temp = 0; for(i = 0; i < pusNumberOfHandles ; i++) { STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value); temp += value; pReadPayload += FLOW_CONTROL_EVENT_SIZE; } tSLInformation.usNumberOfFreeBuffers += temp; tSLInformation.NumberOfReleasedPackets += temp; return(ESUCCESS); } //***************************************************************************** // //! get_socket_active_status //! //! @param Sd Socket IS //! @return Current status of the socket. //! //! @brief Retrieve socket status // //***************************************************************************** INT32 get_socket_active_status(INT32 Sd) { if(M_IS_VALID_SD(Sd)) { return (socket_active_status & (1 << Sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE; } return SOCKET_STATUS_INACTIVE; } //***************************************************************************** // //! update_socket_active_status //! //! @param resp_params Socket IS //! @return Current status of the socket. //! //! @brief Retrieve socket status // //***************************************************************************** void update_socket_active_status(CHAR *resp_params) { INT32 status, sd; STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_SOCKET_OFFSET,sd); STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_STATUS_OFFSET,status); if(ERROR_SOCKET_INACTIVE == status) { set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); } } //***************************************************************************** // //! SimpleLinkWaitEvent //! //! @param usOpcode command operation code //! @param pRetParams command return parameters //! //! @return none //! //! @brief Wait for event, pass it to the hci_event_handler and //! update the event opcode in a global variable. // //***************************************************************************** void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams) { // In the blocking implementation the control to caller will be returned only // after the end of current transaction tSLInformation.usRxEventOpcode = usOpcode; hci_event_handler(pRetParams, 0, 0); } //***************************************************************************** // //! SimpleLinkWaitData //! //! @param pBuf data buffer //! @param from from information //! @param fromlen from information length //! //! @return none //! //! @brief Wait for data, pass it to the hci_event_handler //! and update in a global variable that there is //! data to read. // //***************************************************************************** void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen) { // In the blocking implementation the control to caller will be returned only // after the end of current transaction, i.e. only after data will be received tSLInformation.usRxDataPending = 1; hci_event_handler(pBuf, from, fromlen); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/drivers/cc3000/src/hci.c000066400000000000000000000167401357706137100200760ustar00rootroot00000000000000/***************************************************************************** * * hci.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ //***************************************************************************** // //! \addtogroup hci_app //! @{ // //***************************************************************************** #include #include "cc3000_common.h" #include "hci.h" #include "ccspi.h" #include "evnt_handler.h" #include "wlan.h" #define SL_PATCH_PORTION_SIZE (1000) //***************************************************************************** // //! hci_command_send //! //! @param usOpcode command operation code //! @param pucBuff pointer to the command's arguments buffer //! @param ucArgsLength length of the arguments //! //! @return none //! //! @brief Initiate an HCI command. // //***************************************************************************** UINT16 hci_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength) { UINT8 *stream; stream = (pucBuff + SPI_HEADER_SIZE); UINT8_TO_STREAM(stream, HCI_TYPE_CMND); stream = UINT16_TO_STREAM(stream, usOpcode); UINT8_TO_STREAM(stream, ucArgsLength); //Update the opcode of the event we will be waiting for SpiWrite(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE); return(0); } //***************************************************************************** // //! hci_data_send //! //! @param usOpcode command operation code //! @param ucArgs pointer to the command's arguments buffer //! @param usArgsLength length of the arguments //! @param ucTail pointer to the data buffer //! @param usTailLength buffer length //! //! @return none //! //! @brief Initiate an HCI data write operation // //***************************************************************************** INT32 hci_data_send(UINT8 ucOpcode, UINT8 *ucArgs, UINT16 usArgsLength, UINT16 usDataLength, const UINT8 *ucTail, UINT16 usTailLength) { UINT8 *stream; stream = ((ucArgs) + SPI_HEADER_SIZE); UINT8_TO_STREAM(stream, HCI_TYPE_DATA); UINT8_TO_STREAM(stream, ucOpcode); UINT8_TO_STREAM(stream, usArgsLength); stream = UINT16_TO_STREAM(stream, usArgsLength + usDataLength + usTailLength); // Send the packet over the SPI SpiWrite(ucArgs, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + usArgsLength + usDataLength + usTailLength); return(ESUCCESS); } //***************************************************************************** // //! hci_data_command_send //! //! @param usOpcode command operation code //! @param pucBuff pointer to the data buffer //! @param ucArgsLength arguments length //! @param ucDataLength data length //! //! @return none //! //! @brief Prepeare HCI header and initiate an HCI data write operation // //***************************************************************************** void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength,UINT16 ucDataLength) { UINT8 *stream = (pucBuff + SPI_HEADER_SIZE); UINT8_TO_STREAM(stream, HCI_TYPE_DATA); UINT8_TO_STREAM(stream, usOpcode); UINT8_TO_STREAM(stream, ucArgsLength); stream = UINT16_TO_STREAM(stream, ucArgsLength + ucDataLength); // Send the command over SPI on data channel SpiWrite(pucBuff, ucArgsLength + ucDataLength + SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE); return; } //***************************************************************************** // //! hci_patch_send //! //! @param usOpcode command operation code //! @param pucBuff pointer to the command's arguments buffer //! @param patch pointer to patch content buffer //! @param usDataLength data length //! //! @return none //! //! @brief Prepeare HCI header and initiate an HCI patch write operation // //***************************************************************************** void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength) { UINT8 *data_ptr = (pucBuff + SPI_HEADER_SIZE); UINT16 usTransLength; UINT8 *stream = (pucBuff + SPI_HEADER_SIZE); UINT8_TO_STREAM(stream, HCI_TYPE_PATCH); UINT8_TO_STREAM(stream, ucOpcode); stream = UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); if (usDataLength <= SL_PATCH_PORTION_SIZE) { UINT16_TO_STREAM(stream, usDataLength); stream = UINT16_TO_STREAM(stream, usDataLength); memcpy((pucBuff + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, usDataLength); // Update the opcode of the event we will be waiting for SpiWrite(pucBuff, usDataLength + HCI_PATCH_HEADER_SIZE); } else { usTransLength = (usDataLength/SL_PATCH_PORTION_SIZE); UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE); memcpy(pucBuff + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE); usDataLength -= SL_PATCH_PORTION_SIZE; patch += SL_PATCH_PORTION_SIZE; // Update the opcode of the event we will be waiting for SpiWrite(pucBuff, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE); while (usDataLength) { if (usDataLength <= SL_PATCH_PORTION_SIZE) { usTransLength = usDataLength; usDataLength = 0; } else { usTransLength = SL_PATCH_PORTION_SIZE; usDataLength -= usTransLength; } *(UINT16 *)data_ptr = usTransLength; memcpy(data_ptr + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength); patch += usTransLength; // Update the opcode of the event we will be waiting for SpiWrite((UINT8 *)data_ptr, usTransLength + sizeof(usTransLength)); } } } //***************************************************************************** // // Close the Doxygen group. //! @} // // //***************************************************************************** micropython-1.12/drivers/cc3000/src/inet_ntop.c000066400000000000000000000126101357706137100213220ustar00rootroot00000000000000/* * Copyright (C) 1996-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include "cc3000_common.h" #include "socket.h" #include "inet_ntop.h" // We can't include stdio.h because it defines _types_fd_set, but we // need to use the CC3000 version of this type. So we must provide // our own declaration of snprintf. Grrr. int snprintf(char *str, size_t size, const char *fmt, ...); #define IN6ADDRSZ 16 #define INADDRSZ 4 #define INT16SZ 2 #define ENOSPC (28) #define EAFNOSUPPORT (106) #define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err) /* * Format an IPv4 address, more or less like inet_ntoa(). * * Returns `dst' (as a const) * Note: * - uses no statics * - takes a unsigned char* not an in_addr as input */ static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size) { size_t len; char tmp[sizeof "255.255.255.255"]; tmp[0] = '\0'; (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", ((int)((unsigned char)src[3])) & 0xff, ((int)((unsigned char)src[2])) & 0xff, ((int)((unsigned char)src[1])) & 0xff, ((int)((unsigned char)src[0])) & 0xff); len = strlen(tmp); if(len == 0 || len >= size) { SET_ERRNO(ENOSPC); return (NULL); } strcpy(dst, tmp); return dst; } #ifdef ENABLE_IPV6 /* * Convert IPv6 binary address into presentation (printable) format. */ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; char *tp; struct { long base; long len; } best, cur; unsigned long words[IN6ADDRSZ / INT16SZ]; int i; /* Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ memset(words, '\0', sizeof(words)); for (i = 0; i < IN6ADDRSZ; i++) words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); best.base = -1; cur.base = -1; best.len = 0; cur.len = 0; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { if(words[i] == 0) { if(cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else if(cur.base != -1) { if(best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } if((cur.base != -1) && (best.base == -1 || cur.len > best.len)) best = cur; if(best.base != -1 && best.len < 2) best.base = -1; /* Format the result. */ tp = tmp; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ if(best.base != -1 && i >= best.base && i < (best.base + best.len)) { if(i == best.base) *tp++ = ':'; continue; } /* Are we following an initial run of 0x00s or any real hex? */ if(i != 0) *tp++ = ':'; /* Is this address an encapsulated IPv4? */ if(i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) { SET_ERRNO(ENOSPC); return (NULL); } tp += strlen(tp); break; } tp += snprintf(tp, 5, "%lx", words[i]); } /* Was it a trailing run of 0x00's? */ if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) *tp++ = ':'; *tp++ = '\0'; /* Check for overflow, copy, and we're done. */ if((size_t)(tp - tmp) > size) { SET_ERRNO(ENOSPC); return (NULL); } strcpy(dst, tmp); return dst; } #endif /* ENABLE_IPV6 */ /* * Convert a network format address to presentation format. * * Returns pointer to presentation format address (`buf'). * Returns NULL on error and errno set with the specific * error, EAFNOSUPPORT or ENOSPC. * * On Windows we store the error in the thread errno, not * in the winsock error code. This is to avoid loosing the * actual last winsock error. So use macro ERRNO to fetch the * errno this funtion sets when returning NULL, not SOCKERRNO. */ char *inet_ntop(int af, const void *src, char *buf, size_t size) { switch (af) { case AF_INET: return inet_ntop4((const unsigned char*)src, buf, size); #ifdef ENABLE_IPV6 case AF_INET6: return inet_ntop6((const unsigned char*)src, buf, size); #endif default: SET_ERRNO(EAFNOSUPPORT); return NULL; } } micropython-1.12/drivers/cc3000/src/inet_pton.c000066400000000000000000000133571357706137100213330ustar00rootroot00000000000000/* This is from the BIND 4.9.4 release, modified to compile by itself */ /* Copyright (c) 1996 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ #include #include "cc3000_common.h" #include "socket.h" #include "inet_pton.h" #define IN6ADDRSZ 16 #define INADDRSZ 4 #define INT16SZ 2 static int inet_pton4(const char *src, unsigned char *dst); #ifdef ENABLE_IPV6 static int inet_pton6(const char *src, unsigned char *dst); #endif #define EAFNOSUPPORT (106) #define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err) /* int * inet_pton(af, src, dst) * convert from presentation format (which usually means ASCII printable) * to network format (which is usually some kind of binary format). * return: * 1 if the address was valid for the specified address family * 0 if the address wasn't valid (`dst' is untouched in this case) * -1 if some other error occurred (`dst' is untouched in this case, too) * notice: * On Windows we store the error in the thread errno, not * in the winsock error code. This is to avoid loosing the * actual last winsock error. So use macro ERRNO to fetch the * errno this funtion sets when returning (-1), not SOCKERRNO. * author: * Paul Vixie, 1996. */ int inet_pton(int af, const char *src, void *dst) { switch (af) { case AF_INET: return (inet_pton4(src, (unsigned char *)dst)); #ifdef ENABLE_IPV6 case AF_INET6: return (inet_pton6(src, (unsigned char *)dst)); #endif default: SET_ERRNO(EAFNOSUPPORT); return (-1); } /* NOTREACHED */ } /* int * inet_pton4(src, dst) * like inet_aton() but without all the hexadecimal and shorthand. * return: * 1 if `src' is a valid dotted quad, else 0. * notice: * does not touch `dst' unless it's returning 1. * author: * Paul Vixie, 1996. */ static int inet_pton4(const char *src, unsigned char *dst) { static const char digits[] = "0123456789"; int saw_digit, octets, ch; unsigned char tmp[INADDRSZ], *tp; saw_digit = 0; octets = 0; tp = tmp; *tp = 0; while((ch = *src++) != '\0') { const char *pch; if((pch = strchr(digits, ch)) != NULL) { unsigned int val = *tp * 10 + (unsigned int)(pch - digits); if(saw_digit && *tp == 0) return (0); if(val > 255) return (0); *tp = (unsigned char)val; if(! saw_digit) { if(++octets > 4) return (0); saw_digit = 1; } } else if(ch == '.' && saw_digit) { if(octets == 4) return (0); *++tp = 0; saw_digit = 0; } else return (0); } if(octets < 4) return (0); memcpy(dst, tmp, INADDRSZ); return (1); } #ifdef ENABLE_IPV6 /* int * inet_pton6(src, dst) * convert presentation level address to network order binary form. * return: * 1 if `src' is a valid [RFC1884 2.2] address, else 0. * notice: * (1) does not touch `dst' unless it's returning 1. * (2) :: in a full address is silently ignored. * credit: * inspired by Mark Andrews. * author: * Paul Vixie, 1996. */ static int inet_pton6(const char *src, unsigned char *dst) { static const char xdigits_l[] = "0123456789abcdef", xdigits_u[] = "0123456789ABCDEF"; unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; const char *xdigits, *curtok; int ch, saw_xdigit; unsigned int val; memset((tp = tmp), 0, IN6ADDRSZ); endp = tp + IN6ADDRSZ; colonp = NULL; /* Leading :: requires some special handling. */ if(*src == ':') if(*++src != ':') return (0); curtok = src; saw_xdigit = 0; val = 0; while((ch = *src++) != '\0') { const char *pch; if((pch = strchr((xdigits = xdigits_l), ch)) == NULL) pch = strchr((xdigits = xdigits_u), ch); if(pch != NULL) { val <<= 4; val |= (pch - xdigits); if(++saw_xdigit > 4) return (0); continue; } if(ch == ':') { curtok = src; if(!saw_xdigit) { if(colonp) return (0); colonp = tp; continue; } if(tp + INT16SZ > endp) return (0); *tp++ = (unsigned char) (val >> 8) & 0xff; *tp++ = (unsigned char) val & 0xff; saw_xdigit = 0; val = 0; continue; } if(ch == '.' && ((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) { tp += INADDRSZ; saw_xdigit = 0; break; /* '\0' was seen by inet_pton4(). */ } return (0); } if(saw_xdigit) { if(tp + INT16SZ > endp) return (0); *tp++ = (unsigned char) (val >> 8) & 0xff; *tp++ = (unsigned char) val & 0xff; } if(colonp != NULL) { /* * Since some memmove()'s erroneously fail to handle * overlapping regions, we'll do the shift by hand. */ const long n = tp - colonp; long i; if(tp == endp) return (0); for (i = 1; i <= n; i++) { endp[- i] = colonp[n - i]; colonp[n - i] = 0; } tp = endp; } if(tp != endp) return (0); memcpy(dst, tmp, IN6ADDRSZ); return (1); } #endif /* ENABLE_IPV6 */ micropython-1.12/drivers/cc3000/src/netapp.c000066400000000000000000000372061357706137100206220ustar00rootroot00000000000000/***************************************************************************** * * netapp.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #include #include "netapp.h" #include "hci.h" #include "socket.h" #include "evnt_handler.h" #include "nvmem.h" #define MIN_TIMER_VAL_SECONDS 10 #define MIN_TIMER_SET(t) if ((0 != t) && (t < MIN_TIMER_VAL_SECONDS)) \ { \ t = MIN_TIMER_VAL_SECONDS; \ } #define NETAPP_DHCP_PARAMS_LEN (20) #define NETAPP_SET_TIMER_PARAMS_LEN (20) #define NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN (4) #define NETAPP_PING_SEND_PARAMS_LEN (16) //***************************************************************************** // //! netapp_config_mac_adrress //! //! @param mac device mac address, 6 bytes. Saved: yes //! //! @return return on success 0, otherwise error. //! //! @brief Configure device MAC address and store it in NVMEM. //! The value of the MAC address configured through the API will //! be stored in CC3000 non volatile memory, thus preserved //! over resets. // //***************************************************************************** INT32 netapp_config_mac_adrress(UINT8 * mac) { return nvmem_set_mac_address(mac); } //***************************************************************************** // //! netapp_dhcp //! //! @param aucIP device mac address, 6 bytes. Saved: yes //! @param aucSubnetMask device mac address, 6 bytes. Saved: yes //! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes //! @param aucDNSServer device mac address, 6 bytes. Saved: yes //! //! @return return on success 0, otherwise error. //! //! @brief netapp_dhcp is used to configure the network interface, //! static or dynamic (DHCP).\n In order to activate DHCP mode, //! aucIP, aucSubnetMask, aucDefaultGateway must be 0. //! The default mode of CC3000 is DHCP mode. //! Note that the configuration is saved in non volatile memory //! and thus preserved over resets. //! //! @note If the mode is altered a reset of CC3000 device is required //! in order to apply changes.\nAlso note that asynchronous event //! of DHCP_EVENT, which is generated when an IP address is //! allocated either by the DHCP server or due to static //! allocation is generated only upon a connection to the //! AP was established. //! //***************************************************************************** INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer) { INT8 scRet; UINT8 *ptr; UINT8 *args; scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer ARRAY_TO_STREAM(args,aucIP,4); ARRAY_TO_STREAM(args,aucSubnetMask,4); ARRAY_TO_STREAM(args,aucDefaultGateway,4); args = UINT32_TO_STREAM(args, 0); ARRAY_TO_STREAM(args,aucDNSServer,4); // Initiate a HCI command hci_command_send(HCI_NETAPP_DHCP, ptr, NETAPP_DHCP_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_NETAPP_DHCP, &scRet); return(scRet); } //***************************************************************************** // //! netapp_timeout_values //! //! @param aucDHCP DHCP lease time request, also impact //! the DHCP renew timeout. Range: [0-0xffffffff] seconds, //! 0 or 0xffffffff == infinity lease timeout. //! Resolution:10 seconds. Influence: only after //! reconnecting to the AP. //! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds. //! The parameter is saved into the CC3000 NVMEM. //! The default value on CC3000 is 14400 seconds. //! //! @param aucARP ARP refresh timeout, if ARP entry is not updated by //! incoming packet, the ARP entry will be deleted by //! the end of the timeout. //! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout //! Resolution: 10 seconds. Influence: on runtime. //! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds //! The parameter is saved into the CC3000 NVMEM. //! The default value on CC3000 is 3600 seconds. //! //! @param aucKeepalive Keepalive event sent by the end of keepalive timeout //! Range: [0-0xffffffff] seconds, 0 == infinity timeout //! Resolution: 10 seconds. //! Influence: on runtime. //! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec //! The parameter is saved into the CC3000 NVMEM. //! The default value on CC3000 is 10 seconds. //! //! @param aucInactivity Socket inactivity timeout, socket timeout is //! refreshed by incoming or outgoing packet, by the //! end of the socket timeout the socket will be closed //! Range: [0-0xffffffff] sec, 0 == infinity timeout. //! Resolution: 10 seconds. Influence: on runtime. //! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec //! The parameter is saved into the CC3000 NVMEM. //! The default value on CC3000 is 60 seconds. //! //! @return return on success 0, otherwise error. //! //! @brief Set new timeout values. Function set new timeout values for: //! DHCP lease timeout, ARP refresh timeout, keepalive event //! timeout and socket inactivity timeout //! //! @note If a parameter set to non zero value which is less than 10s, //! it will be set automatically to 10s. //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP,UINT32 *aucKeepalive, UINT32 *aucInactivity) { INT8 scRet; UINT8 *ptr; UINT8 *args; scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Set minimal values of timers MIN_TIMER_SET(*aucDHCP) MIN_TIMER_SET(*aucARP) MIN_TIMER_SET(*aucKeepalive) MIN_TIMER_SET(*aucInactivity) // Fill in temporary command buffer args = UINT32_TO_STREAM(args, *aucDHCP); args = UINT32_TO_STREAM(args, *aucARP); args = UINT32_TO_STREAM(args, *aucKeepalive); args = UINT32_TO_STREAM(args, *aucInactivity); // Initiate a HCI command hci_command_send(HCI_NETAPP_SET_TIMERS, ptr, NETAPP_SET_TIMER_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_NETAPP_SET_TIMERS, &scRet); return(scRet); } #endif //***************************************************************************** // //! netapp_ping_send //! //! @param ip destination IP address //! @param pingAttempts number of echo requests to send //! @param pingSize send buffer size which may be up to 1400 bytes //! @param pingTimeout Time to wait for a response,in milliseconds. //! //! @return return on success 0, otherwise error. //! //! @brief send ICMP ECHO_REQUEST to network hosts //! //! @note If an operation finished successfully asynchronous ping report //! event will be generated. The report structure is as defined //! by structure netapp_pingreport_args_t. //! //! @warning Calling this function while a previous Ping Requests are in //! progress will stop the previous ping request. //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout) { INT8 scRet; UINT8 *ptr, *args; scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, *ip); args = UINT32_TO_STREAM(args, ulPingAttempts); args = UINT32_TO_STREAM(args, ulPingSize); args = UINT32_TO_STREAM(args, ulPingTimeout); // Initiate a HCI command hci_command_send(HCI_NETAPP_PING_SEND, ptr, NETAPP_PING_SEND_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_NETAPP_PING_SEND, &scRet); return(scRet); } #endif //***************************************************************************** // //! netapp_ping_report //! //! @param none //! //! @return none //! //! @brief Request for ping status. This API triggers the CC3000 to send //! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT. //! This event will carry the report structure: //! netapp_pingreport_args_t. This structure is filled in with ping //! results up till point of triggering API. //! netapp_pingreport_args_t:\n packets_sent - echo sent, //! packets_received - echo reply, min_round_time - minimum //! round time, max_round_time - max round time, //! avg_round_time - average round time //! //! @note When a ping operation is not active, the returned structure //! fields are 0. //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER void netapp_ping_report() { UINT8 *ptr; ptr = tSLInformation.pucTxCommandBuffer; INT8 scRet; scRet = EFAIL; // Initiate a HCI command hci_command_send(HCI_NETAPP_PING_REPORT, ptr, 0); // Wait for command complete event SimpleLinkWaitEvent(HCI_NETAPP_PING_REPORT, &scRet); } #endif //***************************************************************************** // //! netapp_ping_stop //! //! @param none //! //! @return On success, zero is returned. On error, -1 is returned. //! //! @brief Stop any ping request. //! //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 netapp_ping_stop() { INT8 scRet; UINT8 *ptr; scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; // Initiate a HCI command hci_command_send(HCI_NETAPP_PING_STOP, ptr, 0); // Wait for command complete event SimpleLinkWaitEvent(HCI_NETAPP_PING_STOP, &scRet); return(scRet); } #endif //***************************************************************************** // //! netapp_ipconfig //! //! @param[out] ipconfig This argument is a pointer to a //! tNetappIpconfigRetArgs structure. This structure is //! filled in with the network interface configuration. //! tNetappIpconfigRetArgs:\n aucIP - ip address, //! aucSubnetMask - mask, aucDefaultGateway - default //! gateway address, aucDHCPServer - dhcp server address //! aucDNSServer - dns server address, uaMacAddr - mac //! address, uaSSID - connected AP ssid //! //! @return none //! //! @brief Obtain the CC3000 Network interface information. //! Note that the information is available only after the WLAN //! connection was established. Calling this function before //! associated, will cause non-defined values to be returned. //! //! @note The function is useful for figuring out the IP Configuration of //! the device when DHCP is used and for figuring out the SSID of //! the Wireless network the device is associated with. //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ) { UINT8 *ptr; ptr = tSLInformation.pucTxCommandBuffer; // Initiate a HCI command hci_command_send(HCI_NETAPP_IPCONFIG, ptr, 0); // Wait for command complete event SimpleLinkWaitEvent(HCI_NETAPP_IPCONFIG, ipconfig ); } #else void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ) { } #endif //***************************************************************************** // //! netapp_arp_flush //! //! @param none //! //! @return none //! //! @brief Flushes ARP table //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 netapp_arp_flush(void) { INT8 scRet; UINT8 *ptr; scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; // Initiate a HCI command hci_command_send(HCI_NETAPP_ARP_FLUSH, ptr, 0); // Wait for command complete event SimpleLinkWaitEvent(HCI_NETAPP_ARP_FLUSH, &scRet); return(scRet); } #endif //***************************************************************************** // //! netapp_set_debug_level //! //! @param[in] level debug level. Bitwise [0-8], //! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical //! message, 1 information message, 2 - core messages, 3 - //! HCI messages, 4 - Network stack messages, 5 - wlan //! messages, 6 - wlan driver messages, 7 - epprom messages, //! 8 - general messages. Default: 0x13f. Saved: no //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Debug messages sent via the UART debug channel, this function //! enable/disable the debug level //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 netapp_set_debug_level(UINT32 ulLevel) { INT8 scRet; UINT8 *ptr, *args; scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // // Fill in temporary command buffer // args = UINT32_TO_STREAM(args, ulLevel); // // Initiate a HCI command // hci_command_send(HCI_NETAPP_SET_DEBUG_LEVEL, ptr, NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN); // // Wait for command complete event // SimpleLinkWaitEvent(HCI_NETAPP_SET_DEBUG_LEVEL, &scRet); return(scRet); } #endif micropython-1.12/drivers/cc3000/src/nvmem.c000066400000000000000000000260531357706137100204530ustar00rootroot00000000000000/***************************************************************************** * * nvmem.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ //***************************************************************************** // //! \addtogroup nvmem_api //! @{ // //***************************************************************************** #include #include "nvmem.h" #include "hci.h" #include "socket.h" #include "evnt_handler.h" //***************************************************************************** // // Prototypes for the structures for APIs. // //***************************************************************************** #define NVMEM_READ_PARAMS_LEN (12) #define NVMEM_CREATE_PARAMS_LEN (8) #define NVMEM_WRITE_PARAMS_LEN (16) //***************************************************************************** // //! nvmem_read //! //! @param ulFileId nvmem file id:\n //! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID, //! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID, //! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, //! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID, //! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID, //! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID, //! and user files 12-15. //! @param ulLength number of bytes to read //! @param ulOffset ulOffset in file from where to read //! @param buff output buffer pointer //! //! @return on success 0, error otherwise. //! //! @brief Reads data from the file referred by the ulFileId parameter. //! Reads data from file ulOffset till length. Err if the file can't //! be used, is invalid, or if the read is out of bounds. //! //***************************************************************************** INT32 nvmem_read(UINT32 ulFileId, UINT32 ulLength, UINT32 ulOffset, UINT8 *buff) { UINT8 ucStatus = 0xFF; UINT8 *ptr; UINT8 *args; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, ulFileId); args = UINT32_TO_STREAM(args, ulLength); args = UINT32_TO_STREAM(args, ulOffset); // Initiate a HCI command hci_command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN); SimpleLinkWaitEvent(HCI_CMND_NVMEM_READ, &ucStatus); // In case there is data - read it - even if an error code is returned // Note: It is the user responsibility to ignore the data in case of an error code // Wait for the data in a synchronous way. Here we assume that the buffer is // big enough to store also parameters of nvmem SimpleLinkWaitData(buff, 0, 0); return(ucStatus); } //***************************************************************************** // //! nvmem_write //! //! @param ulFileId nvmem file id:\n //! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, //! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID, //! and user files 12-15. //! @param ulLength number of bytes to write //! @param ulEntryOffset offset in file to start write operation from //! @param buff data to write //! //! @return on success 0, error otherwise. //! //! @brief Write data to nvmem. //! writes data to file referred by the ulFileId parameter. //! Writes data to file ulOffset till ulLength.The file id will be //! marked invalid till the write is done. The file entry doesn't //! need to be valid - only allocated. //! //***************************************************************************** INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff) { INT32 iRes; UINT8 *ptr; UINT8 *args; iRes = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, ulFileId); args = UINT32_TO_STREAM(args, 12); args = UINT32_TO_STREAM(args, ulLength); args = UINT32_TO_STREAM(args, ulEntryOffset); memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE + NVMEM_WRITE_PARAMS_LEN),buff,ulLength); // Initiate a HCI command but it will come on data channel hci_data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN, ulLength); SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes); return(iRes); } //***************************************************************************** // //! nvmem_set_mac_address //! //! @param mac mac address to be set //! //! @return on success 0, error otherwise. //! //! @brief Write MAC address to EEPROM. //! mac address as appears over the air (OUI first) //! //***************************************************************************** UINT8 nvmem_set_mac_address(UINT8 *mac) { return nvmem_write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); } //***************************************************************************** // //! nvmem_get_mac_address //! //! @param[out] mac mac address //! //! @return on success 0, error otherwise. //! //! @brief Read MAC address from EEPROM. //! mac address as appears over the air (OUI first) //! //***************************************************************************** UINT8 nvmem_get_mac_address(UINT8 *mac) { return nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); } //***************************************************************************** // //! nvmem_write_patch //! //! @param ulFileId nvmem file id:\n //! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, //! @param spLength number of bytes to write //! @param spData SP data to write //! //! @return on success 0, error otherwise. //! //! @brief program a patch to a specific file ID. //! The SP data is assumed to be organized in 2-dimensional. //! Each line is SP_PORTION_SIZE bytes long. Actual programming is //! applied in SP_PORTION_SIZE bytes portions. //! //***************************************************************************** UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData) { UINT8 status = 0; UINT16 offset = 0; UINT8* spDataPtr = (UINT8*)spData; while ((status == 0) && (spLength >= SP_PORTION_SIZE)) { status = nvmem_write(ulFileId, SP_PORTION_SIZE, offset, spDataPtr); offset += SP_PORTION_SIZE; spLength -= SP_PORTION_SIZE; spDataPtr += SP_PORTION_SIZE; } if (status !=0) { // NVMEM error occurred return status; } if (spLength != 0) { // if reached here, a reminder is left status = nvmem_write(ulFileId, spLength, offset, spDataPtr); } return status; } //***************************************************************************** // //! nvmem_read_sp_version //! //! @param[out] patchVer first number indicates package ID and the second //! number indicates package build number //! //! @return on success 0, error otherwise. //! //! @brief Read patch version. read package version (WiFi FW patch, //! driver-supplicant-NS patch, bootloader patch) //! //***************************************************************************** #ifndef CC3000_TINY_DRIVER UINT8 nvmem_read_sp_version(UINT8* patchVer) { UINT8 *ptr; // 1st byte is the status and the rest is the SP version UINT8 retBuf[5]; ptr = tSLInformation.pucTxCommandBuffer; // Initiate a HCI command, no args are required hci_command_send(HCI_CMND_READ_SP_VERSION, ptr, 0); SimpleLinkWaitEvent(HCI_CMND_READ_SP_VERSION, retBuf); // package ID *patchVer = retBuf[3]; // package build number *(patchVer+1) = retBuf[4]; return(retBuf[0]); } #endif //***************************************************************************** // //! nvmem_create_entry //! //! @param ulFileId nvmem file Id:\n //! * NVMEM_AES128_KEY_FILEID: 12 //! * NVMEM_SHARED_MEM_FILEID: 13 //! * and fileIDs 14 and 15 //! @param ulNewLen entry ulLength //! //! @return on success 0, error otherwise. //! //! @brief Create new file entry and allocate space on the NVMEM. //! Applies only to user files. //! Modify the size of file. //! If the entry is unallocated - allocate it to size //! ulNewLen (marked invalid). //! If it is allocated then deallocate it first. //! To just mark the file as invalid without resizing - //! set ulNewLen=0. //! //***************************************************************************** INT32 nvmem_create_entry(UINT32 ulFileId, UINT32 ulNewLen) { UINT8 *ptr; UINT8 *args; UINT8 retval; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, ulFileId); args = UINT32_TO_STREAM(args, ulNewLen); // Initiate a HCI command hci_command_send(HCI_CMND_NVMEM_CREATE_ENTRY,ptr, NVMEM_CREATE_PARAMS_LEN); SimpleLinkWaitEvent(HCI_CMND_NVMEM_CREATE_ENTRY, &retval); return(retval); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/drivers/cc3000/src/patch.c000066400000000000000000002437641357706137100204420ustar00rootroot00000000000000/***************************************************************************** * * {PatchProgrammer_DR_Patch.c} * * Burn Patches to EEPROM * * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ * ALL RIGHTS RESERVED * *****************************************************************************/ // // Service Pack version P1.13.7.15.28 - Driver patches // This file contains the CC3K driver and firmware patches // From CC3000-FRAM-PATCH V:1.13.7 15-MAY-2014 unsigned short fw_length = 5700; unsigned short drv_length = 8024; const unsigned char wlan_drv_patch[8024] = { 0x00, 0x01, 0x00, 0x00, 0x50, 0x1F, 0x00, 0x00, 0xF0, 0x03, 0x18, 0x00, 0xE4, 0x62, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7A, 0x63, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x0C, 0x49, 0x08, 0x60, 0x0C, 0x48, 0x19, 0x30, 0xF7, 0x46, 0x30, 0xB5, 0x05, 0x1C, 0xAC, 0x69, 0x68, 0x68, 0x5F, 0x30, 0x09, 0xD1, 0x60, 0x6B, 0x0C, 0x38, 0x01, 0x21, 0x8E, 0x46, 0x06, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x00, 0x20, 0x60, 0x63, 0xAC, 0x69, 0x6C, 0x60, 0x04, 0x48, 0x5B, 0x30, 0x30, 0xBD, 0x40, 0x3B, 0x08, 0x00, 0x49, 0xD0, 0x01, 0x00, 0x09, 0xEA, 0x02, 0x00, 0x91, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3C, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x05, 0x1C, 0xA8, 0x88, 0x00, 0x90, 0x28, 0x89, 0x01, 0x90, 0xE9, 0x68, 0x02, 0x91, 0x28, 0x7C, 0x03, 0x90, 0x2A, 0x6A, 0x00, 0x20, 0x17, 0x56, 0x68, 0x60, 0x00, 0x29, 0x4C, 0xD0, 0x00, 0x2F, 0x4A, 0xDC , 0xCA, 0x49, 0x0C, 0x1C, 0x08, 0x26, 0x04, 0x90, 0x21, 0x88, 0x00, 0x98, 0x81, 0x42, 0x0C, 0xD1, 0x62, 0x88, 0x01, 0x98, 0x82, 0x42, 0x08, 0xD1, 0x46, 0x20, 0x02, 0x5D, 0x03, 0x98, 0x82, 0x42, 0x03, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xB8, 0x42, 0x0A, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x22, 0xD1, 0x00, 0x98, 0x81, 0x42, 0x1F, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xFF, 0xFF, 0xD2, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB8, 0x42, 0x1B, 0xD1, 0x04, 0x20, 0x02, 0x1C, 0x02, 0x98, 0xB9, 0x49, 0x01, 0x23, 0x9E, 0x46, 0xEC, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x17, 0xD0, 0x20, 0x1D, 0x02, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x0D, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x09, 0xD0, 0xA0, 0x6D, 0x00, 0x28, 0x06, 0xD0, 0xAC, 0x34, 0x04, 0x98, 0x01, 0x30, 0x04, 0x90, 0x01, 0x3E, 0xC1, 0xD1, 0x07, 0xE0, 0x04, 0x98, 0x00, 0x06, 0x00, 0x0E , 0xAC, 0x21, 0x41, 0x43, 0xA6, 0x48, 0x40, 0x18, 0x68, 0x60, 0xA6, 0x48, 0xAD, 0x30, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xB5, 0xC2, 0x68, 0x90, 0x69, 0x02, 0x21, 0x01, 0x23, 0x9E, 0x46, 0xA2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xA2, 0x48, 0x61, 0x30, 0x00, 0xBD, 0x01, 0x79, 0x0B, 0x29, 0x03, 0xD0, 0x89, 0x00, 0x9F, 0x4A, 0x51, 0x5A, 0x01, 0xE0, 0x01, 0x21, 0x49, 0x02, 0x41, 0x60, 0x9D, 0x48, 0x0D, 0x30, 0xF7, 0x46, 0x01, 0x1C, 0xFF, 0xFF, 0x68, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x9C, 0x48, 0x02, 0x68, 0x9C, 0x48, 0x01, 0x2A, 0x01, 0xD1, 0x25, 0x30, 0xF7, 0x46, 0x9B, 0x4A, 0x12, 0x68, 0x4A, 0x60, 0x19, 0x30, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x99, 0x48, 0x98, 0x49, 0x08, 0x18, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x97, 0x48, 0xE7, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xFF, 0xB5, 0x46, 0x69, 0x40, 0x68, 0x01, 0x90, 0x94, 0x49, 0x0A, 0x7C, 0x9A, 0x4F, 0x01, 0x2A, 0x63, 0xD0, 0x09, 0x7C, 0x03, 0x29 , 0x60, 0xD0, 0x91, 0x4A, 0x92, 0x4B, 0x00, 0x21, 0x02, 0x91, 0x59, 0x56, 0x24, 0x23, 0x59, 0x43, 0x53, 0x18, 0x03, 0x93, 0x01, 0x28, 0x17, 0xD1, 0x8A, 0x18, 0x04, 0x23, 0x6C, 0x46, 0x8C, 0x49, 0x15, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x28, 0x43, 0x20, 0x70, 0x01, 0x32, 0x01, 0x31, 0x01, 0x34, 0x01, 0x3B, 0xF5, 0xD1, 0x31, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x40, 0xD0, 0x35, 0x1D, 0x82, 0x48, 0x00, 0x78, 0xFF, 0x28, 0xFF, 0xFF, 0xFE, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x11, 0xD0, 0x00, 0x28, 0x0F, 0xD0, 0x03, 0x98, 0x01, 0x1D, 0x28, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x7E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x00, 0x28, 0x05, 0xD1, 0x7A, 0x48, 0xA6, 0x46, 0x7B, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x05, 0xE0, 0x28, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0x78, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x99, 0x01, 0x29, 0x01, 0xD1, 0x00, 0x28, 0x1E, 0xD1 , 0x01, 0x99, 0x5F, 0x31, 0x01, 0xD0, 0x00, 0x28, 0x0F, 0xD1, 0xA8, 0x20, 0x81, 0x5D, 0x00, 0x29, 0x08, 0xD0, 0x49, 0x1E, 0x81, 0x55, 0x80, 0x5D, 0x00, 0x28, 0x09, 0xD1, 0x38, 0x1C, 0xFF, 0x30, 0x08, 0x30, 0x11, 0xE0, 0x03, 0x21, 0x02, 0x91, 0x00, 0xE0, 0xA8, 0x20, 0x02, 0x99, 0x81, 0x55, 0x38, 0x1C, 0xFF, 0x30, 0x16, 0x30, 0x07, 0xE0, 0x01, 0x98, 0x01, 0x28, 0x02, 0xD1, 0x38, 0x1C, 0xA3, 0x30, 0x01, 0xE0, 0x38, 0x1C, 0x9F, 0x30, 0x00, 0x90, 0xFF, 0xBD, 0x00, 0xB5, 0x02, 0x1C, 0x10, 0x6A, 0xD1, 0x69, 0x52, 0x69, 0xC3, 0x69, 0x5A, 0x60, 0xFF, 0xFF, 0x94, 0x67, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x22, 0x96, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5E, 0x48, 0xFF, 0x30, 0x6E, 0x30, 0x00, 0xBD, 0x10, 0xB5, 0x0A, 0x1C, 0x41, 0x69, 0x00, 0x6A, 0x93, 0x69, 0xDB, 0x69, 0x58, 0x60, 0x90, 0x69, 0x01, 0x24, 0xA6, 0x46, 0x56, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xA6, 0x46, 0x56, 0x48, 0xFE, 0x44 , 0x00, 0x47, 0x55, 0x48, 0xFF, 0x30, 0xB6, 0x30, 0x10, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0x6E, 0x69, 0x53, 0x48, 0x02, 0x68, 0x5C, 0x21, 0x88, 0x5D, 0x04, 0x28, 0x15, 0xD1, 0x07, 0x20, 0x88, 0x55, 0x10, 0x0B, 0x11, 0xD2, 0x01, 0x24, 0xA6, 0x46, 0x4E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x0A, 0xD0, 0x47, 0x21, 0x89, 0x57, 0xC1, 0x60, 0x11, 0x21, 0xC9, 0x02, 0x00, 0x22, 0x04, 0x23, 0xA6, 0x46, 0xE8, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x01, 0x20, 0x68, 0x60, 0x43, 0x48, 0xED, 0x49, 0x08, 0x18, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0xAE, 0x69, 0x9C, 0x20, 0x80, 0x19, 0x4B, 0x21, 0x89, 0x00, 0x01, 0x24, 0xFF, 0xFF, 0x2A, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA6, 0x46, 0xE8, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5C, 0x21, 0x88, 0x5D, 0x07, 0x28, 0x01, 0xD1, 0x09, 0x20, 0x00, 0xE0, 0x05, 0x20, 0xAA, 0x69, 0x88, 0x54, 0x30, 0x1C, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x68, 0x60, 0xE8, 0x48 , 0x4D, 0x30, 0x70, 0xBD, 0xF0, 0xB5, 0x41, 0x68, 0x82, 0x68, 0x88, 0x23, 0x5E, 0x18, 0x37, 0x88, 0x0B, 0x6F, 0x00, 0x2B, 0x01, 0xD1, 0x00, 0x2F, 0x10, 0xD1, 0x06, 0x2F, 0x02, 0xDD, 0x00, 0x21, 0xC9, 0x43, 0x07, 0xE0, 0x33, 0x88, 0x9B, 0x00, 0xC9, 0x18, 0x0A, 0x67, 0x31, 0x88, 0x01, 0x31, 0x31, 0x80, 0x01, 0x21, 0x81, 0x60, 0xE1, 0x48, 0x1D, 0x30, 0xF0, 0xBD, 0x0B, 0x1C, 0x01, 0x24, 0x5D, 0x6F, 0x1D, 0x67, 0x04, 0x33, 0x01, 0x34, 0x06, 0x2C, 0xE1, 0xDA, 0xF8, 0xE7, 0x00, 0xB5, 0x00, 0x21, 0xC1, 0x60, 0xE9, 0x48, 0x01, 0x68, 0x10, 0x31, 0xE6, 0x48, 0x20, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE5, 0x48, 0xFB, 0x30, 0x00, 0xBD, 0xFF, 0xFF, 0xC0, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0x54, 0x19, 0x1B, 0x00, 0x91, 0x1A, 0x01, 0x00, 0x4B, 0xAD, 0x03, 0x00, 0x61, 0x4E, 0x01, 0x00, 0x06, 0x32, 0x08, 0x00, 0x1F, 0x0B, 0x02, 0x00, 0x54, 0x3F , 0x08, 0x00, 0x45, 0xC1, 0x00, 0x00, 0x84, 0x3C, 0x08, 0x00, 0x1B, 0x02, 0x00, 0x00, 0xED, 0x17, 0x00, 0x00, 0xF3, 0xC1, 0x01, 0x00, 0x34, 0x19, 0x1B, 0x00, 0x08, 0x19, 0x1B, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xCB, 0x67, 0x03, 0x00, 0x0D, 0x47, 0x02, 0x00, 0x39, 0x42, 0x03, 0x00, 0xBD, 0xE7, 0x02, 0x00, 0xB1, 0x40, 0x03, 0x00, 0xB9, 0xEA, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0x24, 0x41, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0xF0, 0xB5, 0x88, 0xB0, 0x06, 0x91, 0x07, 0x90, 0x86, 0x69, 0xF0, 0x1C, 0xD9, 0xA1, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x14, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x32, 0xD1, 0xF2, 0x79, 0xD7, 0x48, 0x02, 0x70, 0x35, 0x7A, 0x77, 0x7A, 0x78, 0x1B, 0xFF, 0xFF, 0x56, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x43, 0x1C, 0x93, 0x42, 0x1D, 0xD0, 0x16, 0x2A, 0x0C, 0xDB, 0x00, 0x2D, 0x0A, 0xD1, 0xD6, 0x48, 0x04, 0x70, 0x0A, 0x20 , 0x81, 0x19, 0xD0, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x74, 0xE0, 0xD2, 0x48, 0x04, 0x70, 0xCC, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0xB1, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x67, 0xE0, 0x8F, 0xC6, 0x03, 0x00, 0xC9, 0x48, 0x04, 0x70, 0xC9, 0x48, 0x04, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xC2, 0x48, 0xA6, 0x46, 0xAA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x59, 0xE0, 0xF0, 0x1C, 0x03, 0x21, 0x0A, 0x1C, 0xBC, 0xA1, 0xA6, 0x46, 0xC6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x4F, 0xD1, 0xF1, 0x79, 0xBB, 0x48, 0x01, 0x70, 0xBB, 0x4D, 0xB2, 0x79, 0x2A, 0x70, 0x03, 0x20, 0x17, 0x49, 0xF4, 0x31, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x28, 0x78, 0x00, 0x28, 0x0B, 0xD1, 0xFF, 0xE7, 0xB8, 0x49, 0x0C, 0x70, 0xB8, 0x49, 0xFF, 0xFF, 0xEC, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x03, 0x20, 0x0F, 0x49, 0xF5, 0x31, 0xA6, 0x46 , 0xB6, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x20, 0x1C, 0xF2, 0x79, 0x35, 0x7A, 0x77, 0x7A, 0x79, 0x1B, 0x4B, 0x1C, 0x93, 0x42, 0x20, 0xD0, 0xA9, 0x49, 0x09, 0x78, 0x16, 0x29, 0x0F, 0xDB, 0x00, 0x2D, 0x0D, 0xD1, 0xAB, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xE9, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0x8B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x1A, 0xE0, 0xC0, 0x46, 0xC7, 0x04, 0x00, 0x00, 0xA5, 0x49, 0x08, 0x70, 0xE3, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0A, 0xE0, 0x9E, 0x49, 0x08, 0x70, 0x9E, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xDB, 0x48, 0xA6, 0x46, 0x7D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x96, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x95, 0x48, 0x00, 0x78, 0x00, 0x28, 0x06, 0xD0, 0x94, 0x48, 0x00, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x93, 0x48, 0x00, 0x78, 0x00, 0x28, 0xFF, 0xFF, 0x82, 0x6A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 , 0x00, 0xD1, 0x8C, 0xE0, 0x03, 0x20, 0x17, 0x21, 0x89, 0x01, 0xA6, 0x46, 0x90, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x87, 0x48, 0x01, 0x78, 0x87, 0x48, 0x07, 0x78, 0x84, 0x4E, 0x83, 0x4D, 0xE0, 0x48, 0x00, 0x68, 0x00, 0x28, 0x2E, 0xD1, 0x07, 0x98, 0x41, 0x61, 0x06, 0x62, 0xC6, 0x48, 0x06, 0x9A, 0x10, 0x64, 0x02, 0x2F, 0x01, 0xD0, 0x03, 0x2F, 0x01, 0xD1, 0x03, 0x22, 0x00, 0xE0, 0x3A, 0x1C, 0x06, 0x9B, 0xDA, 0x63, 0x2A, 0x78, 0x9A, 0x63, 0x01, 0x2F, 0x03, 0xD1, 0x05, 0x29, 0x04, 0xD0, 0x0D, 0x29, 0x02, 0xD0, 0xEC, 0x48, 0xDB, 0x30, 0x64, 0xE0, 0x00, 0x25, 0x00, 0x95, 0x01, 0x91, 0x02, 0x96, 0x03, 0x95, 0x04, 0x90, 0x2B, 0x1C, 0x20, 0x1C, 0x01, 0x1C, 0x8E, 0x46, 0xE6, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0xE6, 0x48, 0x04, 0x60, 0x28, 0x1C, 0xA6, 0x46, 0xE5, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x4C, 0xE0, 0x0D, 0x27, 0x00, 0x20, 0x39, 0x1C, 0x05, 0xAA, 0xA6, 0x46, 0xE3, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x46 , 0xFF, 0xFF, 0x18, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x80, 0x8A, 0x40, 0x08, 0x05, 0xD2, 0x38, 0x1C, 0x50, 0x21, 0xA6, 0x46, 0xDC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x38, 0x1C, 0x21, 0x1C, 0x0B, 0x1C, 0x29, 0x1C, 0x00, 0x22, 0xA6, 0x46, 0xD9, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x2B, 0x78, 0x0D, 0x20, 0x31, 0x1C, 0x22, 0x1C, 0xA6, 0x46, 0xD5, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x28, 0x78, 0x01, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x57, 0x49, 0x23, 0x1C, 0xA6, 0x46, 0xD0, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x55, 0x4E, 0x28, 0x78, 0x02, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x31, 0x1C, 0x23, 0x1C, 0xA6, 0x46, 0xCA, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x30, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x28, 0x78, 0x03, 0x30, 0x02, 0x1C, 0x4C, 0x48, 0x03, 0x78, 0x0D, 0x20, 0x8F, 0x49, 0xA6, 0x46, 0xC3, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xBF, 0x48, 0x04, 0x60, 0x00, 0x20, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xB9, 0x48, 0xEC, 0x49 , 0x08, 0x18, 0x08, 0xB0, 0xF0, 0xBD, 0xC0, 0x46, 0x7B, 0xC0, 0xFF, 0xFF, 0xAE, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x1C, 0xE9, 0x48, 0x02, 0x68, 0xE9, 0x48, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x22, 0x0A, 0x62, 0x8A, 0x61, 0x1D, 0x30, 0xF7, 0x46, 0xD7, 0x30, 0xF7, 0x46, 0xC0, 0x46, 0x9F, 0x03, 0x00, 0x00, 0x7D, 0xB8, 0x03, 0x00, 0x01, 0x1C, 0xE2, 0x48, 0x02, 0x68, 0xE2, 0x48, 0x00, 0x2A, 0x02, 0xD0, 0xFF, 0x30, 0xB4, 0x30, 0xF7, 0x46, 0x00, 0x22, 0xCA, 0x61, 0x8A, 0x61, 0x4F, 0x30, 0xF7, 0x46, 0xC9, 0x21, 0x01, 0x00, 0x91, 0xE1, 0x00, 0x00, 0xDB, 0x48, 0x01, 0x68, 0x8A, 0x69, 0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0x88, 0x61, 0x00, 0x20, 0x08, 0x61, 0xD8, 0x48, 0x23, 0x30, 0xF7, 0x46, 0x89, 0x17, 0x02, 0x00, 0x70, 0xB5, 0x05, 0x1C, 0xD5, 0x4E, 0x29, 0x6A, 0xEA, 0x69, 0x30, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x0B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x69, 0xA6, 0x46, 0xD1, 0x49 , 0xFE, 0x44, 0x08, 0x47, 0xA8, 0x69, 0x06, 0x30, 0xA8, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x68, 0x60, 0xEE, 0x60, 0xCE, 0x48, 0xFF, 0xFF, 0x44, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x6D, 0x30, 0x70, 0xBD, 0x46, 0x17, 0x1B, 0x00, 0x30, 0x3F, 0x08, 0x00, 0x41, 0xEB, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x30, 0xB5, 0xEE, 0x48, 0x01, 0x6D, 0x80, 0x6C, 0x08, 0x43, 0x18, 0xD0, 0xEC, 0x49, 0x08, 0x1C, 0x07, 0x22, 0xFF, 0x23, 0x09, 0x33, 0x1B, 0x58, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0x30, 0x1D, 0x30, 0x01, 0x3A, 0xF6, 0xD1, 0x0B, 0xE0, 0x02, 0x20, 0xF0, 0x4A, 0xF1, 0x4B, 0x01, 0x24, 0xA6, 0x46, 0xF0, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xA6, 0x46, 0xEF, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xEF, 0x48, 0xFF, 0x30, 0x5C, 0x30, 0x30, 0xBD, 0xC0, 0x46, 0x53, 0x53, 0x49, 0x44, 0x00, 0xC0, 0x46, 0xC0, 0x4B, 0x45, 0x59, 0x00, 0xEE, 0x62, 0x08, 0x00, 0xF0, 0x62, 0x08, 0x00, 0xEC, 0x62, 0x08, 0x00, 0xED, 0x62, 0x08, 0x00 , 0xE7, 0x7E, 0x03, 0x00, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0xF0, 0xB5, 0xFF, 0xFF, 0xDA, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x87, 0xB0, 0x00, 0x91, 0x01, 0x90, 0x6B, 0x48, 0x01, 0x68, 0xCC, 0x4A, 0x14, 0x1C, 0x02, 0x94, 0x07, 0x26, 0x00, 0x25, 0x03, 0x95, 0x04, 0x94, 0x05, 0x95, 0xDF, 0x48, 0x00, 0x68, 0x08, 0x43, 0x27, 0xD0, 0xE0, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0A, 0xDD, 0x03, 0x90, 0x40, 0x1C, 0x00, 0x99, 0x88, 0x60, 0xC2, 0x49, 0xFF, 0x20, 0x1D, 0x30, 0x68, 0x43, 0x0C, 0x18, 0xE0, 0x68, 0x04, 0x91, 0x02, 0x99, 0xC9, 0x68, 0x88, 0x42, 0x10, 0xDB, 0x88, 0x42, 0x10, 0xD1, 0x02, 0x98, 0x01, 0x27, 0xBE, 0x46, 0xCE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x90, 0x20, 0x1C, 0xBE, 0x46, 0xCB, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x99, 0x88, 0x42, 0x01, 0xDA, 0x05, 0x95, 0x02, 0x94 , 0x51, 0x48, 0x01, 0x68, 0xFF, 0x27, 0x09, 0x37, 0x38, 0x59, 0x00, 0x28, 0x06, 0xD0, 0xC7, 0x48, 0x00, 0x68, 0x07, 0x2E, 0x00, 0xD1, 0x2E, 0x1C, 0x08, 0x43, 0x04, 0xD0, 0xFF, 0x34, 0x1D, 0x34, 0x01, 0x35, 0x07, 0x2D, 0xC2, 0xDB, 0x07, 0x2E, 0xFF, 0xFF, 0x70, 0x6D, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0A, 0xD1, 0xC0, 0x48, 0x00, 0x68, 0x08, 0x43, 0x06, 0xD0, 0x05, 0x9E, 0x30, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0xBA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x98, 0x47, 0x61, 0x00, 0x21, 0x81, 0x61, 0xFF, 0x22, 0x1D, 0x32, 0x72, 0x43, 0x04, 0x99, 0x89, 0x18, 0xC1, 0x61, 0x06, 0x62, 0xB4, 0x48, 0x39, 0x30, 0x07, 0xB0, 0xF0, 0xBD, 0x10, 0xB5, 0x04, 0x1C, 0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x40, 0x1E, 0x00, 0xD5, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x61, 0xAE, 0x48, 0x21, 0x30, 0x10, 0xBD, 0xC0, 0x46, 0x10, 0x63, 0x08, 0x00, 0x70, 0xB5, 0x04, 0x1C, 0xE5, 0x69, 0x66, 0x69 , 0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xA7, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x60, 0x60, 0xAB, 0x19, 0xA6, 0x4A, 0xA5, 0x49, 0x93, 0x42, 0x02, 0xD3, 0x9A, 0x1A, 0x82, 0x42, 0x02, 0xD9, 0x08, 0x1C, 0x99, 0x30, 0x70, 0xBD, 0x08, 0x1C, 0xAB, 0x30, 0x70, 0xBD, 0x08, 0x6B, 0x41, 0x7D, 0x02, 0x88, 0x92, 0x00, 0xFF, 0xFF, 0x06, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x51, 0x1A, 0x3C, 0x39, 0xFF, 0x22, 0x5F, 0x32, 0x91, 0x42, 0x03, 0xD9, 0x65, 0x21, 0x01, 0x80, 0x02, 0x21, 0x81, 0x73, 0x9B, 0x48, 0x99, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0xF8, 0xB5, 0x40, 0x68, 0x24, 0x21, 0x41, 0x43, 0x97, 0x48, 0x45, 0x18, 0x28, 0x1D, 0x0C, 0x21, 0x49, 0x19, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x91, 0x4C, 0x00, 0x28, 0x1B, 0xD0, 0x2B, 0x1C, 0x04, 0x22, 0x6E, 0x46, 0x91, 0x49, 0x1F, 0x7B, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33 , 0x01, 0x31, 0x01, 0x36, 0x01, 0x3A, 0xF5, 0xD1, 0x0C, 0x20, 0x41, 0x19, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x87, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x02, 0xD0, 0x20, 0x1C, 0x4A, 0x30, 0xF8, 0xBD, 0x20, 0x1C, 0xF8, 0xBD, 0xB1, 0xBD, 0x00, 0x00, 0x15, 0x95, 0x00, 0x00, 0x58, 0x3F, 0x08, 0x00, 0xF3, 0xF8, 0x00, 0x00, 0xE9, 0x09, 0x02, 0x00, 0xFF, 0xFF, 0x9C, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2B, 0x09, 0x02, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0xF8, 0xB5, 0x05, 0x1C, 0xAA, 0x69, 0x7D, 0x49, 0x00, 0x20, 0x08, 0x56, 0x24, 0x21, 0x41, 0x43, 0x76, 0x48, 0x43, 0x18, 0x04, 0x24, 0x6E, 0x46, 0x76, 0x49, 0x1F, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33, 0x01, 0x31, 0x01, 0x36, 0x01, 0x3C, 0xF5, 0xD1, 0x11, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x6D, 0x48, 0x04, 0xD0, 0x6E, 0x49, 0x09, 0x78 , 0x69, 0x60, 0x45, 0x30, 0xF8, 0xBD, 0xEC, 0x61, 0xAF, 0x30, 0xF8, 0xBD, 0x70, 0xB5, 0xC5, 0x68, 0x81, 0x68, 0x0A, 0x89, 0x6D, 0x4E, 0x00, 0x2A, 0x22, 0xD0, 0x01, 0x24, 0xC2, 0x6D, 0xA2, 0x18, 0xC2, 0x65, 0x08, 0x89, 0x0D, 0x28, 0x1B, 0xD1, 0x68, 0x6B, 0x21, 0x1C, 0xA6, 0x46, 0x63, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x22, 0x1C, 0x28, 0x1C, 0x00, 0x21, 0xA6, 0x46, 0x60, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x2C, 0x60, 0xE9, 0x6B, 0xFF, 0xFF, 0x32, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0x5C, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x1C, 0x3D, 0x30, 0x70, 0xBD, 0x30, 0x1C, 0x23, 0x30, 0x70, 0xBD, 0xC0, 0x46, 0xB1, 0x02, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x19, 0xC6, 0x00, 0x00, 0x5C, 0x3F, 0x08, 0x00, 0x1D, 0xC2, 0x00, 0x00, 0x68, 0x44, 0x08, 0x00, 0x43, 0x12, 0x03, 0x00, 0x34, 0x63, 0x08, 0x00, 0x2F, 0x7A, 0x02, 0x00 , 0xB4, 0x36, 0x08, 0x00, 0x8F, 0xF4, 0x01, 0x00, 0xF0, 0xB5, 0x05, 0x1C, 0xAB, 0x69, 0xEC, 0x69, 0x60, 0x68, 0x00, 0x68, 0x2A, 0x30, 0x01, 0x78, 0x0A, 0x06, 0x41, 0x78, 0x09, 0x04, 0x8A, 0x18, 0x81, 0x78, 0x09, 0x02, 0x8A, 0x18, 0xC1, 0x78, 0x8A, 0x18, 0x8E, 0x26, 0xF1, 0x5A, 0x09, 0x0A, 0x01, 0x70, 0xF0, 0x5C, 0x61, 0x68, 0x09, 0x68, 0x2B, 0x26, 0x70, 0x54, 0x8C, 0x20, 0xC0, 0x18, 0x61, 0x68, 0x0E, 0x68, 0x01, 0x88, 0x09, 0x0A, 0x2C, 0x27, 0xB9, 0x55, 0x61, 0x68, 0x09, 0x68, 0xFF, 0xFF, 0xC8, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2D, 0x26, 0x00, 0x78, 0x70, 0x54, 0x60, 0x68, 0x01, 0x68, 0x32, 0x31, 0x08, 0x78, 0x00, 0x02, 0x49, 0x78, 0x08, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x8C, 0x21, 0xCB, 0x58, 0x35, 0x49, 0x41, 0x40, 0x08, 0x04, 0x00, 0x0C, 0xC0, 0x18, 0x80, 0x1A, 0x01, 0x21, 0x8E, 0x46, 0x32, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x61, 0x68, 0x0A, 0x68, 0x32, 0x23, 0x01, 0x0A, 0x99, 0x54 , 0x61, 0x68, 0x09, 0x68, 0x33, 0x22, 0x50, 0x54, 0x60, 0x68, 0x68, 0x60, 0x2C, 0x48, 0xF0, 0xBD, 0x00, 0x00, 0x1B, 0x00, 0x34, 0x04, 0x1B, 0x00, 0x02, 0x6A, 0x8B, 0x69, 0xDB, 0x69, 0x1B, 0x68, 0x83, 0x60, 0x88, 0x69, 0xC0, 0x69, 0x41, 0x68, 0x8A, 0x42, 0x00, 0xDA, 0x42, 0x60, 0x25, 0x48, 0x79, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x57, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x91, 0x30, 0xF7, 0x46, 0x32, 0x04, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0x15, 0x09, 0x02, 0x00, 0xC5, 0x93, 0x00, 0x00, 0x0D, 0x91, 0x00, 0x00, 0x40, 0x1E, 0x80, 0x00, 0x1E, 0x4B, 0xFF, 0xFF, 0x5E, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x19, 0x50, 0x1C, 0x49, 0x0A, 0x50, 0xF7, 0x46, 0xC0, 0x46, 0xBD, 0xB5, 0x00, 0x00, 0x95, 0x92, 0x00, 0x00, 0xFD, 0x93, 0x00, 0x00, 0x54, 0x3F, 0x08, 0x00, 0x29, 0x4F, 0x03, 0x00, 0xDF, 0xE8, 0x02, 0x00, 0x36, 0x89, 0x41, 0x00, 0x81, 0x06, 0x00, 0x00, 0xB1, 0x78, 0x00, 0x00, 0x94, 0xEC, 0x01, 0x00 , 0x08, 0x19, 0x1B, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x67, 0x66, 0x03, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xA7, 0x2F, 0x02, 0x00, 0x91, 0x44, 0x03, 0x00, 0x91, 0x63, 0x03, 0x00, 0x5B, 0x44, 0x03, 0x00, 0xE7, 0x44, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xA2, 0x03, 0x00, 0x6A, 0x1E, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0xD7, 0xE8, 0x01, 0x00, 0xE9, 0x78, 0x02, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x7B, 0x08, 0x00, 0xFC, 0xB5, 0x04, 0x1C, 0xA5, 0x69, 0x60, 0x6A, 0x01, 0x90, 0x20, 0x69, 0x00, 0x28, 0x35, 0xD4, 0x08, 0x28, 0x33, 0xDA, 0xE1, 0x69, 0x09, 0x68, 0xFF, 0xFF, 0xF4, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x2F, 0xD1, 0xAC, 0x21, 0x41, 0x43, 0x9E, 0x4A, 0x51, 0x5C, 0x49, 0x08, 0x27, 0xD3, 0x00, 0x06, 0x00, 0x16, 0xA2, 0x68, 0x69, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x39, 0x30, 0x1F, 0xD0 , 0x00, 0x2E, 0x1D, 0xD0, 0x00, 0x98, 0x07, 0x68, 0x00, 0x99, 0x0C, 0x39, 0x01, 0x98, 0x01, 0x60, 0x28, 0x1D, 0x10, 0x21, 0x79, 0x1A, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x91, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x22, 0x2A, 0x80, 0xA8, 0x1C, 0x08, 0x21, 0x79, 0x1A, 0x01, 0x23, 0x9E, 0x46, 0x8C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x03, 0xE0, 0x38, 0x20, 0x00, 0xE0, 0x00, 0x20, 0xC6, 0x43, 0x26, 0x60, 0x89, 0x48, 0x7C, 0x30, 0x20, 0x62, 0xFC, 0xBD, 0x30, 0xB5, 0x05, 0x1C, 0x28, 0x69, 0xA9, 0x69, 0x90, 0x29, 0x1D, 0xD1, 0x69, 0x69, 0x09, 0x78, 0x04, 0x29, 0x19, 0xD0, 0x05, 0x29, 0x17, 0xD0, 0x0A, 0x29, 0x15, 0xD0, 0x06, 0x29, 0x13, 0xD0, 0x0C, 0x29, 0x01, 0xDB, 0xFF, 0xFF, 0x8A, 0x71, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x0F, 0xD1, 0x01, 0x24, 0xA6, 0x46, 0x7D, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x7C, 0x48, 0x7D, 0x49, 0x00, 0x22, 0xA6, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x7C, 0x48 , 0xFF, 0x30, 0x5F, 0x30, 0x28, 0x62, 0x30, 0xBD, 0xF0, 0xB5, 0x89, 0xB0, 0x05, 0x90, 0x41, 0x69, 0x02, 0x69, 0x75, 0x48, 0x79, 0x4E, 0x82, 0x42, 0x3A, 0xD0, 0x04, 0x30, 0x82, 0x42, 0x25, 0xD0, 0x74, 0x4D, 0xAA, 0x42, 0x00, 0xD0, 0xCC, 0xE0, 0x08, 0x68, 0x06, 0x1C, 0x0C, 0x22, 0x8F, 0x1A, 0x4A, 0x68, 0x89, 0x18, 0x09, 0x1D, 0x10, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x09, 0xD1, 0xAC, 0x22, 0x72, 0x43, 0xCB, 0x48, 0x80, 0x18, 0x46, 0x22, 0x12, 0x5C, 0x11, 0x2A, 0x01, 0xD1, 0x44, 0x22, 0x14, 0x54, 0x28, 0x1C, 0x3A, 0x1C, 0xA6, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x69, 0x48, 0xEC, 0x30, 0xAB, 0xE0, 0x08, 0x68, 0xC0, 0x00, 0x30, 0x18, 0x8A, 0x68, 0x02, 0x2A, 0x02, 0xD0, 0xFF, 0xFF, 0x20, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xE7, 0x20, 0x80, 0x00, 0xA2, 0xE0, 0xCA, 0x68, 0x89, 0x18, 0x09, 0x7B, 0x41, 0x60, 0x80, 0x21, 0x01, 0x60, 0x3B, 0x20 , 0x00, 0x01, 0x99, 0xE0, 0x08, 0x68, 0x06, 0x90, 0xC0, 0x00, 0x34, 0x58, 0x10, 0x20, 0x04, 0x90, 0x01, 0x25, 0xAE, 0x46, 0x57, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x07, 0x90, 0x00, 0x28, 0x00, 0xD1, 0x89, 0xE0, 0x0C, 0x21, 0x07, 0x98, 0x0F, 0x18, 0xB0, 0x49, 0xAC, 0x20, 0x06, 0x9A, 0x50, 0x43, 0x08, 0x18, 0x48, 0x22, 0x13, 0x5C, 0x5B, 0x06, 0x5B, 0x0E, 0x13, 0x54, 0x06, 0x9A, 0xD2, 0x00, 0xB6, 0x18, 0x71, 0x68, 0x00, 0x29, 0x47, 0xD1, 0x00, 0x2C, 0x01, 0xDD, 0x08, 0x2C, 0x21, 0xDB, 0x00, 0x22, 0x69, 0x46, 0x0A, 0x70, 0x01, 0x92, 0x0A, 0x81, 0x8A, 0x72, 0xCD, 0x72, 0x0D, 0x73, 0x4D, 0x73, 0x01, 0x88, 0x44, 0x48, 0x06, 0x23, 0xAE, 0x46, 0x44, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x04, 0x1C, 0x02, 0xDC, 0x00, 0x20, 0xC0, 0x43, 0x36, 0xE0, 0x34, 0x60, 0xAC, 0x20, 0x60, 0x43, 0x9A, 0x49, 0xFF, 0xFF, 0xB6, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x18, 0x5C, 0x22, 0x28, 0x1C, 0x50, 0x54, 0x48, 0x20 , 0x42, 0x5C, 0x52, 0x06, 0x52, 0x0E, 0x42, 0x54, 0xAC, 0x20, 0x60, 0x43, 0x94, 0x49, 0x08, 0x18, 0x5C, 0x21, 0x09, 0x5C, 0x49, 0x1E, 0x02, 0x29, 0x16, 0xD9, 0x03, 0x39, 0x08, 0xD0, 0x00, 0x20, 0x30, 0x56, 0xAE, 0x46, 0xEA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x80, 0x20, 0x30, 0x60, 0xDB, 0xE7, 0x08, 0x94, 0x80, 0x21, 0x31, 0x60, 0x48, 0x22, 0x13, 0x5C, 0x19, 0x43, 0x11, 0x54, 0xAE, 0x46, 0xE4, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0xE0, 0x01, 0x20, 0xCE, 0xE7, 0x06, 0x98, 0x39, 0x1C, 0x04, 0xAA, 0xAE, 0x46, 0xE0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x1C, 0x08, 0x90, 0x06, 0x98, 0x38, 0x60, 0x08, 0x98, 0x78, 0x60, 0x00, 0x28, 0x15, 0xD0, 0xAC, 0x20, 0x60, 0x43, 0x7C, 0x49, 0x09, 0x18, 0x48, 0x88, 0x02, 0x04, 0x02, 0x20, 0x10, 0x43, 0xB8, 0x60, 0x48, 0x68, 0x02, 0x0E, 0x01, 0x02, 0x09, 0x0E, 0x09, 0x02, 0x11, 0x43, 0x02, 0x04, 0x12, 0x0E, 0xFF, 0xFF, 0x4C, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 , 0x12, 0x04, 0x0A, 0x43, 0x00, 0x06, 0x10, 0x43, 0xF8, 0x60, 0x07, 0x98, 0x0D, 0x49, 0x00, 0x22, 0x10, 0x23, 0xAE, 0x46, 0xCE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x13, 0x48, 0x00, 0xE0, 0x16, 0x20, 0xCC, 0x49, 0x09, 0x18, 0x05, 0x98, 0x01, 0x62, 0x09, 0xB0, 0xF0, 0xBD, 0x5D, 0x0D, 0x1B, 0x00, 0x81, 0xE7, 0x02, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x27, 0x1A, 0x02, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0xD5, 0xF4, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x91, 0x19, 0x02, 0x00, 0x50, 0x65, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0x50, 0x19, 0x1B, 0x00, 0x29, 0x16, 0x01, 0x00, 0x2A, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0x8B, 0xB0, 0x07, 0x90, 0x05, 0x69, 0x47, 0x69, 0x0C, 0x20, 0x38, 0x1A, 0x08, 0x90, 0xB6, 0x49, 0x8D, 0x42, 0x16, 0xD1, 0x78, 0x68, 0x0F, 0x30, 0x00, 0x11, 0x00, 0x01, 0x78, 0x60, 0x38, 0x68, 0x0B, 0x28, 0x0E, 0xD8, 0x00, 0x23, 0x68, 0x46 , 0xFF, 0xFF, 0xE2, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x03, 0x70, 0x08, 0x98, 0x05, 0x22, 0x01, 0x24, 0xA6, 0x46, 0xAE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0xAE, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xAC, 0x48, 0x85, 0x42, 0x23, 0xD1, 0xAC, 0x48, 0x02, 0x78, 0x6C, 0x46, 0x22, 0x72, 0x43, 0x78, 0x63, 0x72, 0x81, 0x78, 0xA1, 0x72, 0xC0, 0x78, 0xE0, 0x72, 0x00, 0x91, 0x01, 0x90, 0x03, 0x20, 0xA6, 0x49, 0x01, 0x39, 0x01, 0x26, 0xB6, 0x46, 0xF3, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x04, 0x20, 0x20, 0x70, 0x08, 0x98, 0x9F, 0x49, 0x00, 0x22, 0x02, 0xAB, 0x01, 0x24, 0xA6, 0x46, 0x9B, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x9A, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xEB, 0x49, 0x8D, 0x42, 0x14, 0xD1, 0x02, 0x22, 0x68, 0x46, 0x02, 0x70, 0x3A, 0x68, 0xAC, 0x20, 0x42, 0x43, 0x30, 0x48, 0x68, 0x30, 0x83, 0x18, 0x08, 0x98, 0x00, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x8F, 0x4C, 0xFE, 0x44 , 0x20, 0x47, 0x8E, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0xFF, 0xFF, 0x78, 0x74, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x08, 0x62, 0xEF, 0x48, 0x85, 0x42, 0x00, 0xD0, 0x04, 0xE1, 0x03, 0x20, 0x8C, 0x49, 0x01, 0x22, 0x96, 0x46, 0xEC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x86, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x09, 0x90, 0x38, 0x68, 0xEA, 0x4D, 0x00, 0x28, 0x00, 0xD1, 0xE2, 0xE0, 0x01, 0x24, 0xA6, 0x46, 0xE6, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x00, 0xD1, 0xD6, 0xE0, 0xE4, 0x48, 0x02, 0x68, 0x03, 0x20, 0x7F, 0x49, 0x01, 0x31, 0xA6, 0x46, 0xE2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xDF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x5A, 0xD1, 0xDF, 0x4D, 0x2E, 0x20, 0x41, 0x19, 0xB8, 0x68, 0x03, 0x30, 0x08, 0x70, 0x38, 0x7A, 0x48, 0x70, 0x2E, 0x1C, 0x30, 0x36, 0xB8, 0x68, 0x28, 0x18, 0x30, 0x30, 0xDA, 0x49, 0x0A, 0x68, 0x30, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xD8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18 , 0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xD9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x41, 0x19, 0x97, 0x22, 0xFF, 0xFF, 0x0E, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x30, 0x50, 0x54, 0xB8, 0x68, 0x46, 0x19, 0x9E, 0x36, 0x30, 0x70, 0x01, 0x36, 0xB8, 0x68, 0x01, 0xE0, 0x14, 0x0D, 0x1B, 0x00, 0x30, 0x18, 0xCA, 0x49, 0x0A, 0x68, 0x9E, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xC8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18, 0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xC9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x40, 0x00, 0xC0, 0x49, 0x09, 0x68, 0x08, 0x18, 0x28, 0x18, 0xC0, 0x49, 0x0A, 0x79, 0x02, 0x70, 0x4A, 0x79, 0x42, 0x70, 0x8A, 0x79, 0x82, 0x70, 0xC9, 0x79, 0xC1, 0x70, 0x04, 0x30, 0x0F, 0x21, 0x41, 0x1A, 0x0A, 0x78, 0xBB, 0x68, 0x9A, 0x18, 0x0A, 0x70, 0x40, 0x1B, 0x00, 0x04, 0x00, 0x0C, 0xB5, 0x49, 0x08, 0x60, 0xB1, 0x48, 0x04, 0x60, 0x02, 0x20, 0x01, 0x1C , 0x11, 0x22, 0xA6, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x63, 0xD4, 0x03, 0x20, 0xA6, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0x90, 0x00, 0x25, 0x01, 0x1C, 0xFF, 0xFF, 0xA4, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x8D, 0x42, 0x50, 0xD0, 0x29, 0x1C, 0x2B, 0x22, 0xA6, 0x46, 0xAD, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0C, 0x20, 0x0A, 0x99, 0x40, 0x18, 0xAC, 0x22, 0x72, 0x43, 0xAB, 0x49, 0x8F, 0x18, 0x78, 0x63, 0x29, 0x1C, 0x18, 0x22, 0xA6, 0x46, 0xA6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x9F, 0x48, 0x02, 0x68, 0x79, 0x6B, 0x4A, 0x60, 0x0A, 0x98, 0xAC, 0x30, 0x08, 0x60, 0x08, 0x68, 0x9A, 0x49, 0xA6, 0x46, 0xA0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x29, 0x1C, 0x03, 0xA8, 0x10, 0x22, 0xA6, 0x46, 0x9C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE0, 0x21, 0x68, 0x46, 0x01, 0x74, 0x45, 0x74, 0x85, 0x74, 0xFB, 0x21, 0xC1, 0x74, 0xEE, 0x49, 0xC1, 0x81, 0x02, 0x21, 0x81, 0x81, 0x79, 0x6B, 0xCA, 0x68 , 0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0xC8, 0x60, 0x48, 0x68, 0x00, 0x90, 0x2A, 0x1C, 0x30, 0x1C, 0x0A, 0x9D, 0x29, 0x1C, 0x03, 0xAB, 0xA6, 0x46, 0xE6, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x07, 0x1C, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xEF, 0x49, 0xFF, 0xFF, 0x3A, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xFE, 0x44, 0x08, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0xEE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x11, 0xE0, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x20, 0xC7, 0x43, 0x08, 0xE0, 0x07, 0x1C, 0x06, 0xE0, 0x00, 0x20, 0x00, 0x21, 0xCF, 0x43, 0x01, 0xE0, 0x00, 0x20, 0x07, 0x1C, 0x28, 0x60, 0x00, 0x23, 0x68, 0x46, 0x03, 0x70, 0x3A, 0x06, 0x12, 0x0E, 0x08, 0x98, 0x6F, 0x49, 0x01, 0x24, 0xA6, 0x46, 0x09, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x07, 0x98, 0x09, 0x99, 0x01, 0x62, 0x0B, 0xB0, 0xF0, 0xBD, 0xC1, 0x18, 0x01, 0x00, 0xF1, 0x1B, 0x01, 0x00, 0xF3, 0x1C, 0x02, 0x00, 0x7B, 0xC0 , 0x02, 0x00, 0x91, 0xF0, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0xA3, 0xC0, 0x02, 0x00, 0xA9, 0xE9, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xAC, 0x05, 0x00, 0x00, 0xFE, 0xB5, 0x07, 0x1C, 0x7D, 0x69, 0xBE, 0x69, 0x0C, 0x20, 0x30, 0x1A, 0x01, 0x90, 0xDF, 0x4C, 0x0A, 0x2D, 0x13, 0xD1, 0xFF, 0xFF, 0xD0, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0x68, 0xDB, 0x49, 0x08, 0x60, 0x01, 0x20, 0x86, 0x46, 0xDA, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x0A, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xE6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x38, 0x62, 0x03, 0x2D, 0x79, 0xD1, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x02, 0x90, 0x70, 0x68, 0x00, 0x28, 0x0C, 0xD1, 0x00, 0x21, 0xCF, 0x48, 0x01, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x61, 0xD0, 0x01, 0x21, 0x8E, 0x46, 0xCD, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x5B, 0xE0, 0xCC, 0x48, 0xB1, 0x68, 0x01, 0x60 , 0xF1, 0x68, 0x41, 0x60, 0x31, 0x69, 0x81, 0x60, 0x71, 0x69, 0xC1, 0x60, 0xB1, 0x69, 0xC1, 0x63, 0xF1, 0x69, 0x01, 0x64, 0x31, 0x6A, 0xC1, 0x64, 0x01, 0x24, 0xA6, 0x46, 0xC5, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xA6, 0x46, 0xC4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x70, 0x68, 0x7D, 0x25, 0xED, 0x00, 0xA8, 0x42, 0x21, 0xD8, 0x01, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xFF, 0xFF, 0x66, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x1C, 0xE0, 0xB9, 0x48, 0x00, 0x23, 0x19, 0x1C, 0x59, 0x43, 0x3E, 0x22, 0x4A, 0x43, 0x82, 0x83, 0x02, 0x30, 0x01, 0x33, 0x10, 0x2B, 0xF6, 0xDB, 0xA6, 0x46, 0xB4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xB5, 0x48, 0x0D, 0xE0, 0xB5, 0x4D, 0x28, 0x1C, 0xA6, 0x46, 0xB2, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x04, 0xE0, 0xA6, 0x46, 0xAF, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x75, 0x68, 0xAE, 0x48, 0x05, 0x60, 0x05, 0x1C, 0xA7, 0x4E, 0x30, 0x68 , 0x00, 0x28, 0x06, 0xD1, 0xAD, 0x48, 0x00, 0x68, 0xA6, 0x46, 0xAC, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x60, 0x00, 0x94, 0x2B, 0x68, 0xAA, 0x49, 0xAB, 0x4A, 0xA6, 0x46, 0xAB, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0x9C, 0x48, 0x04, 0x60, 0x03, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xA7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x38, 0x62, 0xFE, 0xBD, 0xC0, 0x46, 0x13, 0x7F, 0x03, 0x00, 0x12, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x00, 0x20, 0x01, 0x24, 0xA6, 0x46, 0xA0, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9F, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x7D, 0x21, 0xC9, 0x00, 0xA6, 0x46, 0x9E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x9B, 0x49, 0x08, 0x18, 0x99, 0x49, 0x08, 0x80, 0x9B, 0x48, 0x0A, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x11, 0x10, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xB9, 0x90 , 0x00, 0x00, 0x6C, 0x64, 0x08, 0x00, 0xE7, 0x7E, 0x03, 0x00, 0x74, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0x6D, 0xC6, 0x03, 0x00, 0x08, 0x19, 0x1B, 0x00, 0x11, 0x18, 0x02, 0x00, 0xD1, 0x78, 0x02, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0xFE, 0xB5, 0x02, 0x90, 0x45, 0x69, 0x68, 0x46, 0x01, 0x21, 0x8E, 0x46, 0x89, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x89, 0x48, 0x04, 0x1C, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x00, 0x27, 0x3E, 0x1C, 0x20, 0x88, 0xFF, 0xFF, 0x92, 0x78, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x40, 0x08, 0x22, 0xD3, 0x20, 0x1D, 0x89, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x07, 0xD1, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x21, 0x88, 0x09, 0x04, 0x89, 0x16, 0x81, 0x42, 0x3D, 0xD0, 0x02, 0x20, 0x00, 0x5F, 0x00, 0x99, 0x08, 0x1A, 0x00, 0x04, 0x00, 0x14, 0x3C, 0x28, 0x03, 0xDD, 0x20, 0x88, 0x40, 0x10, 0x40, 0x00 , 0x20, 0x80, 0x78, 0x1C, 0x07, 0x06, 0x3F, 0x0E, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x2A, 0x34, 0x01, 0x36, 0x14, 0x2E, 0xD5, 0xDB, 0x00, 0x2A, 0x02, 0xD1, 0xAB, 0x20, 0x40, 0x00, 0x50, 0xE0, 0x00, 0x9B, 0x6D, 0x48, 0x14, 0x21, 0x00, 0x22, 0x04, 0x88, 0x64, 0x08, 0x03, 0xD3, 0x2A, 0x30, 0x01, 0x32, 0x01, 0x39, 0xF8, 0xD1, 0x12, 0x06, 0x12, 0x0E, 0x14, 0x2F, 0x16, 0xD1, 0x66, 0x48, 0x00, 0x88, 0x00, 0x06, 0x44, 0x16, 0x64, 0x49, 0x00, 0x22, 0x01, 0x20, 0x4E, 0x8D, 0x36, 0x06, 0x76, 0x16, 0xA6, 0x42, 0x02, 0xDD, 0x34, 0x1C, 0x02, 0x06, 0xFF, 0xFF, 0x28, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x12, 0x0E, 0x2A, 0x31, 0x01, 0x30, 0x14, 0x28, 0xF3, 0xDB, 0x02, 0xE0, 0x32, 0x06, 0x12, 0x0E, 0x00, 0x9B, 0x2A, 0x20, 0x42, 0x43, 0x5A, 0x48, 0x11, 0x18, 0x0C, 0x88, 0x01, 0x20, 0x20, 0x43, 0x00, 0x04, 0x00, 0x0C, 0x08, 0x80, 0xFE, 0x24, 0xA0, 0x43, 0x14, 0x24, 0x64, 0x57, 0x64, 0x06, 0x24, 0x0E , 0x04, 0x43, 0x52, 0x48, 0x14, 0x52, 0x14, 0x18, 0x63, 0x80, 0x08, 0x88, 0x80, 0x05, 0x82, 0x0D, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x80, 0x02, 0x10, 0x43, 0x08, 0x80, 0x68, 0x68, 0x02, 0x69, 0x20, 0x1D, 0x91, 0x1C, 0x52, 0x78, 0x01, 0x23, 0x9E, 0x46, 0x4B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x04, 0x61, 0xFE, 0x20, 0x47, 0x49, 0x09, 0x18, 0x02, 0x98, 0x01, 0x62, 0xFE, 0xBD, 0x82, 0x69, 0x41, 0x69, 0x03, 0x69, 0x02, 0x2B, 0x0A, 0xD1, 0x01, 0x2A, 0x01, 0xD1, 0x00, 0x29, 0x05, 0xD0, 0x02, 0x2A, 0x04, 0xD1, 0x00, 0x29, 0x02, 0xD1, 0x11, 0x21, 0x00, 0xE0, 0x06, 0x21, 0x41, 0x61, 0xF7, 0x46, 0xFF, 0xFF, 0xBE, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xC0, 0x46, 0x14, 0xE9, 0x00, 0x00, 0xC9, 0x18, 0x02, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x3A, 0x48, 0x00, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x01, 0x20, 0x86, 0x46, 0x38, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x01, 0x24, 0xA6, 0x46, 0x37, 0x48, 0xFE, 0x44 , 0x00, 0x47, 0xA6, 0x46, 0x36, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x35, 0x48, 0x0E, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x49, 0x19, 0x01, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x18, 0xB5, 0x43, 0x69, 0x81, 0x69, 0x31, 0x48, 0x81, 0x29, 0x00, 0xD1, 0x0B, 0x38, 0x00, 0x21, 0x00, 0x91, 0x1A, 0x68, 0x9B, 0x68, 0x01, 0x24, 0xA6, 0x46, 0x2D, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0x18, 0xB5, 0x40, 0x69, 0x00, 0x21, 0x00, 0x91, 0x02, 0x68, 0x83, 0x68, 0x27, 0x48, 0x01, 0x30, 0x01, 0x24, 0xA6, 0x46, 0x26, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0x19, 0x9E, 0x00, 0x00, 0xB9, 0xEC, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x80, 0x3F, 0x08, 0x00, 0xFF, 0xFF, 0x54, 0x7A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB7, 0x5D, 0x03, 0x00, 0x00, 0x00, 0x1B, 0x00, 0xD3, 0x8E, 0x00, 0x00, 0xF7, 0xC6, 0x00, 0x00, 0xE5, 0x90, 0x00, 0x00, 0x68, 0x64, 0x08, 0x00, 0xC0, 0x27, 0x09, 0x00, 0xA0, 0x3B , 0x08, 0x00, 0x3D, 0x5D, 0x03, 0x00, 0x19, 0xC6, 0x00, 0x00, 0xE8, 0x3A, 0x08, 0x00, 0x81, 0x5D, 0x03, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0x4B, 0x4F, 0x03, 0x00, 0x6B, 0xC0, 0x03, 0x00, 0x95, 0x1E, 0x01, 0x00, 0xDA, 0x40, 0x08, 0x00, 0xDC, 0x05, 0x00, 0x00, 0x55, 0xAA, 0x03, 0x00, 0x0D, 0x91, 0x00, 0x00, 0xD7, 0x56, 0x03, 0x00, 0x08, 0x51, 0x08, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x65, 0xB8, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x84, 0x17, 0x1B, 0x00, 0xB5, 0x86, 0x01, 0x00, 0x3D, 0x47, 0x02, 0x00, 0x73, 0x49, 0x02, 0x00, 0x5F, 0x90, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, 0xF7, 0xF6, 0x00, 0x00, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x76, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x5A, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0xFF, 0xFF, 0xEA, 0x7A, 0x08, 0x00, 0x58, 0x00, 0x00, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5 , 0x68, 0x46, 0xFF, 0xF7, 0xB6, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x55, 0xFC, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x27, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xDD, 0xFA, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x68, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x3D, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xBE, 0xFD, 0xFF, 0xBD, 0x78, 0x7B, 0x08, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xF8, 0xF0, 0x43, 0xFA, 0x00, 0xBD, 0x35, 0x66, 0x08, 0x00, 0x67, 0x66, 0x08, 0x00, 0x71, 0x65, 0x08, 0x00, 0x4D, 0x66, 0x08, 0x00, 0x25, 0x64, 0x08, 0x00, 0x81, 0x66, 0x08, 0x00, 0x8D, 0x66, 0x08, 0x00, 0x99, 0x66, 0x08, 0x00, 0x87, 0x67, 0x08, 0x00, 0xA7, 0x67, 0x08, 0x00, 0xD1, 0x67, 0x08, 0x00, 0x1B, 0x68, 0x08, 0x00, 0x57, 0x68, 0x08, 0x00, 0x2D, 0x69, 0x08, 0x00, 0xB1, 0x6B, 0x08, 0x00, 0xD5, 0x6B, 0x08, 0x00, 0xF9, 0x6B , 0x08, 0x00, 0x15, 0x6C, 0x08, 0x00, 0xA1, 0x68, 0x08, 0x00, 0x59, 0x6C, 0x08, 0x00, 0xA7, 0x6D, 0x08, 0x00, 0xFF, 0x6D, 0x08, 0x00, 0x29, 0x6E, 0x08, 0x00, 0xF9, 0x6E, 0x08, 0x00, 0xD9, 0x6C, 0x08, 0x00, 0xA5, 0x6E, 0x08, 0x00, 0xCD, 0x6D, 0x08, 0x00, 0x81, 0x6F, 0x08, 0x00, 0x1D, 0x70, 0x08, 0x00, 0x31, 0x64, 0x08, 0x00, 0x39, 0x70, 0x08, 0x00, 0x3F, 0x70, 0x08, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x00, 0xB2, 0x4E, 0x01, 0x00, 0x5A, 0xC1, 0x00, 0x00, 0x96, 0x1A, 0x01, 0x00, 0x22, 0x0B, 0x02, 0x00, 0x60, 0xD0, 0x01, 0x00, 0x06, 0x1A, 0x00, 0x00, 0xB8, 0xC6, 0x01, 0x00, 0xD8, 0x42, 0x03, 0x00, 0x16, 0x42, 0x03, 0x00, 0xEE, 0xDB, 0x00, 0x00, 0x62, 0xDC, 0x00, 0x00, 0xC8, 0xE1, 0x00, 0x00, 0x8A, 0x17, 0x02, 0x00, 0x38, 0xBE, 0x00, 0x00, 0x26, 0xC6, 0x00, 0x00, 0x56, 0xC2, 0x00, 0x00, 0x62, 0x12, 0x03, 0x00, 0xE4, 0xF4, 0x01, 0x00, 0x3A, 0xEC, 0x00, 0x00, 0x5E, 0x92, 0x00, 0x00 , 0xFE, 0xE8, 0x02, 0x00, 0x18, 0x7F, 0x00, 0x00, 0x64, 0xEC, 0x01, 0x00, 0xFE, 0x44, 0x03, 0x00, 0x1C, 0x94, 0x00, 0x00, 0xA8, 0x66, 0x03, 0x00, 0x74, 0xE9, 0x02, 0x00, 0x68, 0x1E, 0x01, 0x00, 0xBC, 0xDA, 0x00, 0x00, 0xEA, 0xE1, 0x00, 0x00, 0x24, 0xE9, 0x01, 0x00, 0x70, 0x79, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x1C, 0xF0, 0xB5, 0x88, 0xB0, 0xCA, 0x4C, 0x03, 0x20, 0x22, 0x78, 0x63, 0x78, 0xCA, 0x4E, 0x31, 0x1C, 0x01, 0x39, 0x01, 0x25, 0xAE, 0x46, 0xC7, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0xA2, 0x78, 0xE3, 0x78, 0x03, 0x20, 0x31, 0x1C, 0xAE, 0x46, 0xC3, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x03, 0x20, 0x31, 0x1C, 0x01, 0x31, 0xAE, 0x46, 0xC1, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xC1, 0x48, 0x21, 0x78, 0x01, 0x70, 0x61, 0x78, 0x41, 0x70, 0xE1, 0x78, 0xC1, 0x70, 0xA1, 0x78, 0x81, 0x70, 0xBF, 0x48, 0x04, 0x1C, 0x33, 0x3C, 0x20, 0x1C, 0x00, 0x21, 0xDC, 0x22, 0xAE, 0x46 , 0xBA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x84, 0x20, 0xA0, 0x70, 0x05, 0x27, 0xE7, 0x71, 0x0C, 0x26, 0x26, 0x73, 0x0D, 0x20, 0x00, 0x19, 0x98, 0xA1, 0x32, 0x1C, 0xAE, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20, 0x60, 0x76, 0x1A, 0x20, 0x00, 0x19, 0x97, 0xA1, 0x06, 0x91, 0x04, 0x22, 0xAE, 0x46, 0xAE, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xFF, 0xFF, 0x96, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA7, 0x77, 0x1F, 0x34, 0x95, 0xA1, 0x07, 0x91, 0x20, 0x1C, 0x3A, 0x1C, 0xAE, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x28, 0x1C, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0xC0, 0x25, 0x65, 0x74, 0xA6, 0x74, 0x09, 0x22, 0xE2, 0x74, 0xA3, 0x4C, 0x20, 0x1C, 0x8C, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9F, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x07, 0x22, 0x62, 0x72, 0x9E, 0x4C, 0x0A, 0x34, 0x20, 0x1C, 0x89, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20 , 0xE0, 0x71, 0x98, 0x4C, 0x12, 0x34, 0x20, 0x1C, 0x06, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x27, 0x71, 0x93, 0x4C, 0x17, 0x34, 0x20, 0x1C, 0x07, 0x99, 0x3A, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x8E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x01, 0x20, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0x02, 0x20, 0xE0, 0x73, 0x25, 0x74, 0x66, 0x74, 0xFF, 0xFF, 0x2C, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA5, 0x74, 0x2F, 0x27, 0xE7, 0x74, 0x10, 0x20, 0x60, 0x75, 0x80, 0x26, 0xA6, 0x75, 0x01, 0x20, 0xE0, 0x75, 0x11, 0x20, 0xA0, 0x76, 0x94, 0x20, 0xE0, 0x76, 0x24, 0x20, 0x60, 0x77, 0x0A, 0x22, 0xA2, 0x77, 0x80, 0x4C, 0x36, 0x34, 0x20, 0x1C, 0x6D, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x18, 0x22, 0xA2, 0x72, 0x7A, 0x4C, 0x41, 0x34, 0x20, 0x1C, 0x6B, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x76, 0x4B, 0xFE, 0x44, 0x18, 0x47 , 0x25, 0x76, 0x67, 0x76, 0x21, 0x20, 0xE0, 0x76, 0x26, 0x77, 0x01, 0x20, 0x60, 0x77, 0x72, 0x48, 0x61, 0x30, 0x11, 0x21, 0x01, 0x70, 0x94, 0x21, 0x41, 0x70, 0x04, 0x21, 0x01, 0x72, 0xD2, 0x21, 0x41, 0x72, 0xC5, 0x72, 0x1E, 0x21, 0x01, 0x73, 0x45, 0x73, 0x9E, 0x21, 0x81, 0x73, 0x01, 0x21, 0x01, 0x74, 0x46, 0x74, 0x81, 0x74, 0x11, 0x21, 0x41, 0x75, 0x94, 0x21, 0x81, 0x75, 0x04, 0x21, 0x01, 0x76, 0xAD, 0x20, 0x66, 0x49, 0x08, 0x60, 0x00, 0x24, 0x0F, 0x25, 0xFF, 0xFF, 0xC2, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x29, 0x06, 0x09, 0x0E, 0x00, 0x20, 0x6A, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x6B, 0x46, 0x18, 0x88, 0x40, 0x08, 0x0E, 0xD3, 0xA0, 0x00, 0x0F, 0x21, 0xCA, 0x43, 0x69, 0x46, 0x0E, 0x88, 0x16, 0x40, 0x01, 0xAF, 0x3E, 0x52, 0x49, 0x88, 0x11, 0x40, 0x68, 0x44, 0xC1, 0x80, 0x60, 0x1C, 0x04, 0x04, 0x24, 0x0C, 0x01, 0x3D, 0x0B, 0x2D, 0xE0, 0xDA, 0x60, 0x1E , 0x00, 0x04, 0x00, 0x0C, 0x1D, 0xD0, 0x86, 0x46, 0x01, 0x1C, 0x01, 0xAD, 0x01, 0x22, 0xAE, 0x88, 0x90, 0x00, 0xC7, 0x5A, 0xB7, 0x42, 0x0A, 0xDA, 0xBC, 0x46, 0x07, 0x1C, 0x6F, 0x44, 0x7F, 0x88, 0x68, 0x44, 0x06, 0x80, 0xEE, 0x88, 0x46, 0x80, 0x60, 0x46, 0xA8, 0x80, 0xEF, 0x80, 0x04, 0x35, 0x50, 0x1C, 0x02, 0x04, 0x12, 0x0C, 0x01, 0x39, 0xE9, 0xD1, 0x70, 0x46, 0x01, 0x38, 0x86, 0x46, 0xE2, 0xD1, 0x99, 0x88, 0x68, 0x46, 0xC0, 0x88, 0x40, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x42, 0x4B, 0x18, 0x80, 0x42, 0x49, 0x08, 0x1A, 0xFF, 0xFF, 0x58, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x58, 0x80, 0x02, 0x2C, 0x1E, 0xDB, 0x65, 0x1E, 0x01, 0xAA, 0x01, 0x20, 0x01, 0x1C, 0x8C, 0x00, 0x6B, 0x46, 0xE6, 0x5A, 0x93, 0x88, 0xD4, 0x88, 0xE7, 0x18, 0xB7, 0x42, 0x0C, 0xDA, 0x06, 0x24, 0x44, 0x43, 0x38, 0x4B, 0x1B, 0x19, 0x1F, 0x80, 0x1C, 0x88, 0x34, 0x1B, 0x5C, 0x80, 0x01, 0x24, 0x1C, 0x71, 0x40, 0x1C, 0x00, 0x04 , 0x00, 0x0C, 0x04, 0x32, 0x49, 0x1C, 0x09, 0x06, 0x09, 0x0E, 0x01, 0x3D, 0xE4, 0xD1, 0x00, 0x24, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x01, 0x20, 0x86, 0x46, 0x30, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x2F, 0x49, 0x22, 0x1C, 0x08, 0x68, 0x00, 0x28, 0x02, 0xD0, 0x01, 0x20, 0x90, 0x40, 0x04, 0x43, 0x04, 0x31, 0x01, 0x32, 0x20, 0x2A, 0xF5, 0xD3, 0x2A, 0x48, 0x04, 0x60, 0x08, 0xB0, 0xF0, 0xBD, 0x5F, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2D, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0xC0, 0x46, 0xC0, 0x5F, 0x75, 0x64, 0x70, 0x00, 0xC0, 0xFF, 0xFF, 0xEE, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x46, 0xC0, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0xC0, 0x46, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00, 0xC0, 0x46, 0x5F, 0x64, 0x6E, 0x73, 0x2D, 0x73, 0x64, 0x00, 0x64, 0x65, 0x76, 0x3D, 0x43, 0x43, 0x33, 0x30, 0x30, 0x30, 0x00, 0xC0, 0x76, 0x65 , 0x6E, 0x64, 0x6F, 0x72, 0x3D, 0x54, 0x65, 0x78, 0x61, 0x73, 0x2D, 0x49, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x00, 0xC0, 0x46, 0xC0, 0x00, 0x00, 0x18, 0x00, 0xF3, 0x7E, 0x03, 0x00, 0xC6, 0x05, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0xA7, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0x48, 0x32, 0x08, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0x81, 0x03, 0x18, 0x00, 0x80, 0x7B, 0x08, 0x00, 0x84, 0xF3, 0x1A, 0x00, 0x0D, 0x49, 0x0E, 0x48, 0xFF, 0xFF, 0x84, 0x03, 0x18, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x88, 0x67, 0x0E, 0x48, 0x88, 0x64, 0x0E, 0x48, 0x48, 0x64, 0x0E, 0x48, 0xC8, 0x64, 0x0E, 0x48, 0x08, 0x65, 0x11, 0x48, 0x02, 0x1C, 0x04, 0x32, 0x0C, 0x4B, 0x13, 0x60, 0x0C, 0x4B, 0x93, 0x62, 0x0C, 0x4A , 0x8A, 0x66, 0x0D, 0x49, 0x01, 0x60, 0x0D, 0x48, 0x0E, 0x49, 0x01, 0x60, 0x0E, 0x49, 0x41, 0x60, 0xF7, 0x46, 0x1C, 0x21, 0x08, 0x00, 0x1B, 0x7B, 0x08, 0x00, 0x11, 0x7B, 0x08, 0x00, 0x07, 0x7B, 0x08, 0x00, 0x39, 0x7B, 0x08, 0x00, 0x2F, 0x7B, 0x08, 0x00, 0x25, 0x7B, 0x08, 0x00, 0xFD, 0x7A, 0x08, 0x00, 0xDF, 0x7A, 0x08, 0x00, 0x50, 0x23, 0x08, 0x00, 0xD5, 0x7A, 0x08, 0x00, 0x58, 0x26, 0x08, 0x00, 0xF3, 0x7A, 0x08, 0x00, 0xE9, 0x7A, 0x08, 0x00 }; const unsigned char cRMdefaultParams[128] = { 0x03, 0x00, 0x01, 0x01, 0x14, 0x14, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x23, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x01, 0x77, 0x80, 0x1D, 0x1F, 0x22, 0x26, 0x28, 0x29, 0x1A, 0x1F, 0x22, 0x24, 0x26, 0x28, 0x16, 0x1D, 0x1E, 0x20, 0x24, 0x25, 0x1E, 0x2D, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x15, 0x15, 0x15, 0x11, 0x15, 0x15, 0x0E, 0x00}; // //Service Pack version P1.13.7.15.15 - FW patches // const unsigned char fw_patch[5700] = { 0x00, 0x01, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x25, 0xF0, 0x95, 0xFB, 0xE0, 0x6B, 0xD0, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x38, 0xFB, 0x2C, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x0A, 0xFB, 0x04, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB8, 0xF1, 0x90, 0x0F, 0xA4, 0x16, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x66, 0xE0, 0x04, 0xA8, 0x35, 0x1D, 0x21, 0xF0, 0x99, 0xFC, 0x68, 0x46, 0x23, 0xF0, 0x28, 0xFB, 0x9A, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x07, 0xD1, 0x28, 0x46, 0x05, 0xF0, 0xC3, 0xFE, 0x01, 0x46, 0x01, 0xAA, 0x00, 0x20, 0x21, 0xF0, 0x50, 0xF9, 0x28, 0x46, 0x05, 0xF0, 0xBB, 0xFE, 0x01, 0xA9, 0x21, 0xF0, 0x2A, 0xFA, 0xE9, 0x79, 0x4F, 0xEA, 0xE0, 0x00, 0x40, 0xB2, 0x11, 0xB1, 0x00, 0xF1, 0x06, 0x00, 0x40, 0xB2, 0xA8, 0x71, 0x1F, 0x38, 0x40, 0x00, 0xE8, 0x71, 0x30, 0x46 , 0x01, 0xF0, 0x0D, 0xFF, 0x10, 0xF1, 0x00, 0x09, 0x4F, 0xF0, 0x00, 0x01, 0x09, 0xD0, 0x28, 0x68, 0x40, 0x0C, 0x09, 0xD3, 0xE8, 0x68, 0xC0, 0x0B, 0x03, 0xD2, 0x48, 0x46, 0xFF, 0xF7, 0xDD, 0xFE, 0x01, 0x21, 0x28, 0x68, 0x40, 0x0C, 0x0A, 0xD2, 0x38, 0x68, 0x40, 0x1C, 0x38, 0x60, 0x20, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0x20, 0x60, 0x22, 0x68, 0x38, 0x68, 0x10, 0x43, 0x20, 0x60, 0xE8, 0x68, 0xC0, 0x0B, 0x0F, 0xD3, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0xC8, 0xF8, 0x00, 0x00, 0x20, 0x68, 0x6F, 0xF3, 0x1F, 0x40, 0x20, 0x60, 0xD8, 0xF8, 0x00, 0x20, 0x20, 0x68, 0x40, 0xEA, 0x02, 0x40, 0x20, 0x60, 0x49, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x03, 0xD1, 0x30, 0x46, 0x07, 0xF0, 0xBE, 0xF9, 0x02, 0xE0, 0x48, 0x46, 0x07, 0xF0, 0x06, 0xFA, 0x6C, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x68, 0x46, 0x0E, 0xF0, 0x85, 0xFB, 0x00, 0x9E, 0x00, 0x2E, 0x96, 0xD1, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46 , 0x9C, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0xF0, 0x2A, 0xFE, 0x74, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x21, 0x21, 0xF0, 0x41, 0xFA, 0x20, 0x68, 0x18, 0x4B, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0xF0, 0x1C, 0xF9, 0x0A, 0xE0, 0x20, 0x68, 0x00, 0x68, 0x0C, 0x21, 0x40, 0xF0, 0x20, 0x00, 0x21, 0xF0, 0x14, 0xF9, 0x10, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x20, 0xF0, 0x97, 0xF9, 0x01, 0x98, 0x5C, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x20, 0xF0, 0x71, 0xF9, 0x03, 0x98, 0x00, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x20, 0xF9, 0x1C, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x12, 0xF9, 0x54, 0x58, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xA8, 0x20, 0xF0, 0xF5, 0xF8, 0x04, 0xAB, 0x04, 0x62, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x79, 0x1F, 0xF0, 0x1B, 0xFD, 0x69, 0xE0, 0x60, 0x93, 0x00, 0x00, 0x40, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA6, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x39, 0xFB, 0x28, 0x46, 0x90, 0xA8, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x69, 0xF9, 0x1E, 0x48, 0x34, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x68, 0xFF, 0x29, 0x98, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD4, 0x21, 0xD4, 0xB2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xD0, 0x1A, 0xF0, 0x47, 0xFC, 0x20, 0x98, 0xAC, 0xC5, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0xF0 , 0xDB, 0xFA, 0x09, 0x49, 0x28, 0xC6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0xF0, 0x9E, 0xFA, 0xDC, 0xD3, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x18, 0xF0, 0xAB, 0xFC, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xDF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0xF0, 0xA8, 0xFD, 0xCC, 0xEB, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x78, 0x17, 0xF0, 0x77, 0xF8, 0x38, 0x78, 0x16, 0xF0, 0xF0, 0xFF, 0xA8, 0xF7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x49, 0x09, 0x68, 0x23, 0x22, 0x41, 0x61, 0xC8, 0xF7, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x31, 0x39, 0x2E, 0x33, 0x31, 0x34, 0x5F, 0x4E, 0x65, 0x77, 0x5F, 0x43, 0x43, 0x41, 0x5F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 0xC0, 0x74, 0x56, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xF9, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x16, 0xF0, 0x79, 0xF8 , 0x12, 0xE0, 0x38, 0xFA, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x16, 0xF0, 0x03, 0xF8, 0x32, 0x20, 0x94, 0xFB, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0C, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x14, 0xF0, 0x05, 0xFF, 0x01, 0xF0, 0x10, 0x1B, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x46, 0xBF, 0x18, 0x30, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x30, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0xF0, 0xD8, 0xFC, 0x9C, 0x31, 0x01, 0x00, 0x08, 0x00 , 0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x51, 0xFC, 0xFE, 0xF7, 0xF0, 0x35, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x27, 0xFA, 0xFE, 0xF7, 0xF0, 0x3D, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA9, 0x11, 0xF0, 0x27, 0xFE, 0x20, 0x6F, 0xD0, 0x62, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0xB8, 0xFB, 0x80, 0x7E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDF, 0xF8, 0x58, 0x82, 0xE0, 0x7E, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x6A, 0xFE, 0x0B, 0xF0, 0x9A, 0xF9, 0x03, 0x20, 0xA8, 0xF5, 0x88, 0x71, 0x08, 0x60, 0xF2, 0xF7, 0x16, 0xF9, 0x7A, 0x48, 0x6B, 0x49, 0x9C, 0x7F, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x51, 0x4D, 0xC4, 0x7F, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0xF1, 0x52, 0x00, 0x3A, 0x4A, 0xA8, 0x81, 0x28, 0x83, 0xE8, 0x83, 0xE8, 0x84, 0xA8, 0x85, 0x2A, 0x60, 0x39, 0x48, 0x41, 0xF2, 0x11, 0x12, 0x2A, 0x85, 0x18, 0x90, 0x19, 0x91 , 0x39, 0x49, 0x1A, 0x91, 0x39, 0x49, 0x1B, 0x91, 0x39, 0x49, 0x20, 0x46, 0xDF, 0xF8, 0xC4, 0x90, 0x1C, 0x91, 0x38, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x31, 0x4E, 0x1D, 0x91, 0x48, 0x80, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x7C, 0xFA, 0xB4, 0x80, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x12, 0x66, 0x09, 0x84, 0x6B, 0x00, 0x20, 0x94, 0x70, 0x00, 0x20, 0xB4, 0x70, 0x00, 0x20, 0xC4, 0x78, 0x00, 0x20, 0x50, 0x7A, 0x00, 0x20, 0xFE, 0xFF, 0x03, 0x00, 0xA4, 0x70, 0x00, 0x20, 0xB0, 0x70, 0x00, 0x20, 0xB8, 0x70, 0x00, 0x20, 0x60, 0x55, 0x30, 0x80, 0x3C, 0x5C, 0x00, 0x20, 0x04, 0x74, 0x00, 0x20, 0xB8, 0xE4, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x78, 0x07, 0xF0, 0x01, 0xFC, 0x20, 0x78, 0x07, 0xF0, 0x7A, 0xFB, 0x04, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF1, 0x8C, 0x0D, 0x04, 0x68, 0x0F, 0x30, 0x03, 0x94, 0xFE, 0xF7, 0xDB, 0xFA, 0x04, 0xF1, 0x14, 0x00 , 0x04, 0x90, 0x21, 0x7D, 0x00, 0x20, 0x21, 0xF0, 0x73, 0x01, 0x88, 0x29, 0x08, 0xBF, 0x01, 0x20, 0x05, 0x90, 0x03, 0x98, 0x00, 0x1D, 0x06, 0x90, 0x5D, 0x48, 0x00, 0x68, 0x01, 0x28, 0x40, 0xF0, 0xFA, 0x83, 0x5B, 0x4D, 0x5C, 0x48, 0xDF, 0xF8, 0x70, 0x91, 0x29, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0xDF, 0xF8, 0x74, 0xA1, 0x88, 0x42, 0x21, 0xD1, 0x10, 0x22, 0x00, 0x21, 0x48, 0x46, 0x4F, 0x46, 0xFB, 0xF7, 0xB7, 0xFE, 0x10, 0x22, 0x00, 0x21, 0x40, 0x46, 0xFB, 0xF7, 0xB2, 0xFE, 0x54, 0x49, 0x08, 0x68, 0x40, 0xF4, 0x80, 0x10, 0x08, 0x60, 0x01, 0x20, 0x51, 0x46, 0x08, 0x60, 0x00, 0x21, 0x29, 0x60, 0x39, 0x78, 0x46, 0x46, 0x00, 0x91, 0x31, 0x78, 0x41, 0xF2, 0x11, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x41, 0xFC, 0x51, 0x46, 0x07, 0x91, 0x08, 0x68, 0x56, 0x49, 0xDF, 0xF8, 0x5C, 0xB1, 0x01, 0x28, 0x08, 0x91, 0x56, 0x49, 0xDF, 0xF8, 0x48, 0xA1, 0x09, 0x91, 0x55, 0x49 , 0x0A, 0x91, 0x44, 0x49, 0x0B, 0x91, 0x44, 0x49, 0x0C, 0x91, 0x44, 0x49, 0x0D, 0x91, 0x44, 0x49, 0x0E, 0x91, 0x44, 0x49, 0x0F, 0x91, 0x44, 0x49, 0x10, 0x91, 0x44, 0x49, 0xCC, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x11, 0x91, 0x44, 0x49, 0x12, 0x91, 0x44, 0x49, 0x13, 0x91, 0x44, 0x49, 0x14, 0x91, 0x44, 0x49, 0x15, 0x91, 0x44, 0x49, 0x16, 0x91, 0x9F, 0x49, 0x17, 0x91, 0x9F, 0x49, 0x18, 0x91, 0x9F, 0x49, 0x19, 0x91, 0x9F, 0x49, 0x1A, 0x91, 0x9F, 0x49, 0x1B, 0x91, 0x9F, 0x49, 0x1C, 0x91, 0x9F, 0x49, 0x1D, 0x91, 0x9F, 0x49, 0x1E, 0x91, 0x9F, 0x49, 0x1F, 0x91, 0x40, 0xF0, 0x00, 0x81, 0x04, 0x98, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF9, 0x80, 0x04, 0x99, 0x09, 0x78, 0x01, 0xF0, 0x0C, 0x01, 0x08, 0x29, 0x40, 0xF0, 0xF2, 0x80, 0x06, 0x99, 0x09, 0x88, 0xA1, 0xF1, 0x3C, 0x01, 0x0E, 0xB2, 0x05, 0x99, 0x11, 0xB1, 0xA6, 0xF1, 0x02, 0x06, 0x36, 0xB2, 0xC0, 0x09, 0x4F, 0xF0 , 0x00, 0x07, 0x15, 0xD3, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x10, 0xD0, 0x17, 0x2E, 0x0E, 0xD0, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x08, 0xD0, 0x17, 0x2E, 0x06, 0xD0, 0x36, 0x1F, 0x36, 0xB2, 0x03, 0x2E, 0x14, 0xBF, 0x17, 0x2E, 0x02, 0x27, 0x02, 0xE0, 0x03, 0x27, 0x00, 0xE0, 0x01, 0x27, 0x03, 0x2E, 0x18, 0xBF, 0x17, 0x2E, 0x04, 0x9A, 0x40, 0xF0, 0xC8, 0x80, 0x0A, 0x32, 0x12, 0xF8, 0x01, 0x1B, 0x05, 0x24, 0x12, 0xF8, 0x01, 0x3B, 0x4B, 0x40, 0x64, 0x1E, 0xD9, 0xB2, 0xF9, 0xD1, 0x81, 0xEA, 0x21, 0x11, 0x03, 0x2E, 0x94, 0x4E, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x0F, 0x01, 0x48, 0x46, 0x35, 0xD0, 0x43, 0x46, 0xCA, 0x5C, 0x52, 0x1C, 0xCA, 0x54, 0x0C, 0x18, 0x33, 0xE0, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0xC8, 0x48, 0x30, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x88, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00 , 0x18, 0x58, 0x02, 0x00, 0x20, 0x58, 0x02, 0x00, 0x28, 0x58, 0x02, 0x00, 0x30, 0x58, 0x02, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58, 0x02, 0x00, 0xE4, 0x58, 0x02, 0x00, 0xE2, 0x58, 0x02, 0x00, 0x14, 0x58, 0x02, 0x00, 0xEF, 0x58, 0x02, 0x00, 0xE0, 0x58, 0x02, 0x00, 0xEE, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x0C, 0x18, 0x20, 0x78, 0x40, 0x1C, 0x20, 0x70, 0x20, 0x78, 0x43, 0x46, 0x03, 0xEB, 0x01, 0x08, 0x0A, 0x28, 0x76, 0xDB, 0x98, 0xF8, 0x00, 0x00, 0x0A, 0x28, 0x72, 0xDB, 0x94, 0x48, 0x00, 0x25, 0x01, 0x60, 0x04, 0x98, 0x00, 0xF1, 0x0A, 0x09, 0x40, 0x78, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x04, 0xD2, 0x80, 0x08, 0x2E, 0xBF, 0x49, 0x46, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0x06, 0x22, 0xFA, 0xF7, 0xB9, 0xFC, 0x0C, 0x98, 0x06, 0x22, 0x49, 0x46, 0xFA, 0xF7, 0xB4, 0xFC, 0x9B, 0x48, 0x9A, 0x49, 0x5C, 0x4F, 0x02, 0x00, 0xC8, 0x00 , 0x00, 0x00, 0x00, 0x78, 0x08, 0x22, 0x08, 0x60, 0x58, 0x46, 0x07, 0x60, 0x0D, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAF, 0xFD, 0x08, 0x22, 0x0E, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAA, 0xFD, 0x08, 0x22, 0x0F, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA5, 0xFD, 0x08, 0x22, 0x10, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, 0x08, 0x22, 0x11, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x9B, 0xFD, 0x08, 0x22, 0x12, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x96, 0xFD, 0x07, 0x99, 0x02, 0x20, 0x08, 0x60, 0x13, 0x99, 0x28, 0x46, 0x08, 0x80, 0x08, 0x99, 0x08, 0x70, 0x14, 0x99, 0x08, 0x70, 0x15, 0x99, 0x08, 0x60, 0x16, 0x99, 0x08, 0x70, 0x17, 0x99, 0x08, 0x60, 0x18, 0x99, 0x08, 0x60, 0x19, 0x99, 0x08, 0x60, 0x09, 0x99, 0x08, 0x80, 0x0A, 0x99, 0x08, 0x80, 0x1A, 0x99, 0x08, 0x80, 0x7D, 0x49, 0x0D, 0x60, 0x1B, 0x99, 0x08, 0x70, 0x1C, 0x99, 0x08, 0x70, 0x1D, 0x99, 0x08, 0x70, 0x1E, 0x99, 0x08, 0x80, 0x1F, 0x99, 0x08, 0x80, 0x51, 0x46, 0x08, 0x80 , 0x20, 0x78, 0x00, 0x96, 0x04, 0x22, 0x01, 0x90, 0x98, 0xF8, 0x00, 0x00, 0x41, 0xF2, 0x14, 0x13, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x07, 0xFB, 0x07, 0x98, 0xA2, 0x49, 0x00, 0x68, 0x20, 0x91, 0xA2, 0x49, 0x05, 0x28, 0x21, 0x91, 0x9E, 0x49, 0x22, 0x91, 0x40, 0xF0, 0x37, 0x82, 0x04, 0x98, 0x40, 0x78, 0x24, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x05, 0xD2, 0x80, 0x08, 0x27, 0xBF, 0x04, 0x99, 0x0A, 0x31, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0xF8, 0xF7, 0x2D, 0xFC, 0x01, 0x28, 0x04, 0x98, 0x40, 0xF0, 0x23, 0x82, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x00, 0x03, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x07, 0xBF, 0x04, 0x99, 0x10, 0x31, 0x04, 0x99, 0x0A, 0x31, 0x13, 0xE0, 0x48, 0x58, 0x02, 0x00, 0x4C, 0x58, 0x02, 0x00, 0x50, 0x58, 0x02, 0x00, 0xF0, 0x58, 0x02, 0x00, 0xF2, 0x58, 0x02, 0x00, 0xF3, 0x58, 0x02, 0x00, 0xF4, 0x58, 0x02, 0x00, 0xEA, 0x58 , 0x02, 0x00, 0xEC, 0x58, 0x02, 0x00, 0x04, 0x99, 0x18, 0x31, 0x0C, 0x98, 0xF8, 0xF7, 0x06, 0xFC, 0x04, 0x99, 0x01, 0x28, 0x40, 0xF0, 0xFC, 0x81, 0x49, 0x78, 0x01, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF6, 0x81, 0x59, 0x46, 0x09, 0x68, 0x04, 0x9A, 0x8E, 0x46, 0x51, 0x46, 0xD2, 0x8A, 0x0B, 0x88, 0x12, 0x11, 0x93, 0x42, 0x00, 0xF0, 0x37, 0x82, 0x0A, 0x80, 0x06, 0x99, 0x09, 0x88, 0x3C, 0x39, 0x0B, 0xB2, 0x71, 0x46, 0x49, 0x1E, 0x09, 0xD0, 0x49, 0x1E, 0x04, 0xD0, 0x49, 0x1E, 0x08, 0xD1, 0xA3, 0xF1, 0x10, 0x03, 0x04, 0xE0, 0xA3, 0xF1, 0x14, 0x03, 0x01, 0xE0, 0xA3, 0xF1, 0x08, 0x03, 0x1B, 0xB2, 0x05, 0x98, 0x10, 0xB1, 0xA3, 0xF1, 0x02, 0x03, 0x1B, 0xB2, 0xEC, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0xF1, 0xCE, 0x81, 0x16, 0x98, 0x40, 0xF2, 0x77, 0x51, 0x99, 0x42, 0x0B, 0x90, 0x14, 0x98, 0x05, 0x90, 0x00, 0xF0, 0xA3, 0x81, 0x08, 0x46, 0x00, 0xF1, 0x3C, 0x00, 0x98, 0x42 , 0x05, 0x9A, 0x00, 0xF0, 0x9A, 0x81, 0xDF, 0xF8, 0x48, 0x82, 0x14, 0x78, 0x0B, 0x9A, 0xBB, 0x2C, 0x12, 0x78, 0x0C, 0x92, 0x63, 0xD1, 0xDD, 0xF8, 0x68, 0xC0, 0xBC, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x18, 0xBF, 0x90, 0x42, 0x5B, 0xD1, 0x1C, 0x2B, 0x4F, 0xF0, 0x00, 0x00, 0xC0, 0xF2, 0x82, 0x81, 0x3D, 0x2B, 0x13, 0x9D, 0x80, 0xF2, 0x7E, 0x81, 0xA3, 0xF1, 0x1C, 0x01, 0x09, 0xB2, 0x29, 0x80, 0x1E, 0x9A, 0xDD, 0xF8, 0x30, 0x90, 0xB2, 0xF9, 0x00, 0x60, 0xB9, 0xF1, 0x01, 0x0F, 0x15, 0xD1, 0xDD, 0xF8, 0x24, 0x90, 0x03, 0x2E, 0x0D, 0xDA, 0xB9, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x07, 0xD0, 0x01, 0x26, 0x16, 0x80, 0x4A, 0x46, 0x0E, 0x46, 0x03, 0xE0, 0xC0, 0x46, 0x90, 0x57, 0x02, 0x00, 0x76, 0x1C, 0x16, 0x80, 0x1B, 0x9A, 0x16, 0x78, 0x1D, 0x9A, 0x16, 0x70, 0x0C, 0x9A, 0x1F, 0x9E, 0x02, 0x2A, 0x28, 0xD1, 0xB6, 0xF9, 0x00, 0x20, 0xBE, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x03, 0x2A, 0x35, 0x46, 0x0B, 0xDA, 0x0A, 0x9E , 0xB6, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x04, 0xD0, 0x01, 0x22, 0x2A, 0x80, 0x0A, 0x46, 0x35, 0x46, 0x00, 0xE0, 0xB4, 0x51, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x52, 0x1C, 0x2A, 0x80, 0x1C, 0x99, 0x0A, 0x78, 0x1D, 0x99, 0x0A, 0x70, 0x0F, 0xE0, 0xC0, 0x46, 0x58, 0x57, 0x02, 0x00, 0xA6, 0x64, 0x00, 0x20, 0x54, 0x57, 0x02, 0x00, 0x28, 0x80, 0x05, 0x99, 0x08, 0x70, 0x08, 0x9A, 0x11, 0x78, 0x41, 0xF0, 0x04, 0x01, 0x11, 0x70, 0x04, 0x46, 0x45, 0x46, 0xAC, 0xF8, 0x00, 0x00, 0x28, 0x70, 0xCC, 0x2C, 0x09, 0x9A, 0x40, 0xF0, 0x00, 0x81, 0xDD, 0xF8, 0x7C, 0xC0, 0x0A, 0x99, 0x1E, 0x9F, 0x45, 0x46, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x00, 0x90, 0x28, 0x78, 0xCD, 0xF8, 0x50, 0xC0, 0x16, 0x91, 0x0A, 0x97, 0x13, 0x92, 0x09, 0x95, 0x0C, 0x99, 0x01, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x49, 0x0F, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0x0C, 0x99, 0x02, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x46, 0x0F , 0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0xB3, 0xF5, 0x14, 0x7F, 0x40, 0xF3, 0xBA, 0x80, 0x40, 0xF2, 0x51, 0x31, 0x99, 0x42, 0x08, 0x99, 0x40, 0xF3, 0xB4, 0x80, 0x09, 0x78, 0x06, 0x29, 0x00, 0xF0, 0xB0, 0x80, 0xA3, 0xF2, 0x51, 0x21, 0x0B, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x4F, 0xEA, 0x21, 0x11, 0xCA, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x15, 0x9D, 0x21, 0xF0, 0x0F, 0x01, 0xA3, 0xEB, 0x01, 0x03, 0x1D, 0x99, 0x2E, 0x68, 0x7C, 0x52, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x91, 0xF8, 0x00, 0xE0, 0x5F, 0xFA, 0x83, 0xF8, 0x60, 0xB1, 0x31, 0x18, 0x11, 0xF8, 0x01, 0x1C, 0x51, 0x40, 0xCB, 0xB2, 0x07, 0xE0, 0xC0, 0x46, 0x58, 0x58, 0x02, 0x00, 0x54, 0x58, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0x13, 0x46, 0x19, 0x99, 0xDD, 0xF8, 0x6C, 0xA0, 0xDD, 0xF8, 0x70, 0xB0, 0xD1, 0xF8, 0x00, 0xC0, 0x00, 0xF0, 0x0F, 0x01, 0x99, 0x42, 0x22, 0xD0, 0x0A, 0x9B, 0x86, 0x45, 0x9A, 0xF8 , 0x00, 0x10, 0xB3, 0xF9, 0x00, 0x30, 0x9B, 0xF8, 0x00, 0x50, 0x15, 0xDD, 0x37, 0x5C, 0x44, 0x1C, 0x82, 0xEA, 0x07, 0x0C, 0x04, 0xF0, 0x0F, 0x07, 0x67, 0x45, 0x0B, 0xD0, 0xA6, 0x45, 0x06, 0x44, 0x0A, 0xDD, 0x76, 0x78, 0x72, 0x40, 0x86, 0x1C, 0x06, 0xF0, 0x0F, 0x06, 0x96, 0x42, 0x03, 0xD1, 0xC0, 0x1C, 0x4D, 0xE0, 0x80, 0x1C, 0x4B, 0xE0, 0x05, 0x9E, 0x00, 0x22, 0x32, 0x70, 0x4A, 0xE0, 0x00, 0xF0, 0x1F, 0x01, 0x01, 0x22, 0x8A, 0x40, 0x17, 0x99, 0xC4, 0x10, 0x0B, 0x68, 0x24, 0xF0, 0x03, 0x01, 0x5C, 0xF8, 0x01, 0x70, 0x3A, 0x42, 0x32, 0xD1, 0x5F, 0x58, 0x3A, 0x42, 0x06, 0x44, 0x1F, 0xD0, 0x18, 0x9B, 0x37, 0x78, 0x1B, 0x68, 0xB8, 0x45, 0x04, 0xD1, 0x58, 0x58, 0x02, 0x42, 0x19, 0xD0, 0x63, 0x46, 0x15, 0xE0, 0xA1, 0x10, 0x8C, 0x00, 0x19, 0x59, 0x91, 0x43, 0x19, 0x51, 0x00, 0x90, 0x30, 0x78, 0x01, 0x90, 0x44, 0x53, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x20, 0x06, 0x21, 0x02, 0x46, 0x4D, 0xF6 , 0x80, 0x53, 0xF3, 0xF7, 0x63, 0xF9, 0x09, 0x99, 0x28, 0x68, 0x0E, 0x78, 0x36, 0x18, 0x06, 0xE0, 0xE3, 0x58, 0x02, 0x00, 0xA0, 0x10, 0x81, 0x00, 0x58, 0x58, 0x02, 0x43, 0x5A, 0x50, 0x86, 0xF8, 0x00, 0x80, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x13, 0x98, 0xB0, 0xF9, 0x00, 0x90, 0x09, 0x98, 0x00, 0x78, 0x0A, 0x9A, 0x40, 0x1C, 0x9B, 0xF8, 0x00, 0x50, 0x9A, 0xF8, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x09, 0x9A, 0xC0, 0xB2, 0x10, 0x70, 0x0C, 0x9A, 0x01, 0x2A, 0x03, 0xD1, 0x88, 0x42, 0xC8, 0xBF, 0x8A, 0xF8, 0x00, 0x00, 0x0C, 0x99, 0x02, 0x29, 0x07, 0xD1, 0xA8, 0x42, 0xC8, 0xBF, 0x8B, 0xF8, 0x00, 0x00, 0x02, 0xE0, 0x0A, 0x98, 0xB0, 0xF9, 0x00, 0x30, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x03, 0x2B, 0x04, 0xD1, 0x11, 0x98, 0x01, 0x22, 0x49, 0x46, 0x00, 0xF0, 0x72, 0xFB, 0x16, 0x98, 0xB0, 0xF9, 0x00, 0x10, 0x14, 0x98, 0x00, 0x29, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xDD, 0x03, 0x28, 0x03, 0xD1, 0x12, 0x98 , 0x02, 0x22, 0x00, 0xF0, 0x64, 0xFB, 0x05, 0x98, 0x04, 0x78, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x08, 0x98, 0xBB, 0x2C, 0x01, 0x78, 0x02, 0xD0, 0xAA, 0x2C, 0x2F, 0xD0, 0x31, 0xE0, 0x0C, 0x98, 0x01, 0x28, 0x0B, 0xD1, 0x0D, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x0C, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x0F, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x11, 0x98, 0x10, 0x60, 0x47, 0x4A, 0x15, 0x98, 0x02, 0x60, 0x0C, 0x98, 0x02, 0x28, 0x0B, 0xD1, 0x0E, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x10, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x12, 0x98, 0x10, 0x60, 0x41, 0x4A, 0x15, 0x98, 0x02, 0x60, 0xCC, 0x20, 0x0F, 0xE0, 0x08, 0x99, 0x09, 0x78, 0x0C, 0xE0, 0x02, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x0B, 0x99, 0x08, 0x70, 0x1A, 0x99, 0x0B, 0x80, 0x13, 0x99, 0x00, 0x20, 0x08, 0x80, 0x08, 0x98, 0x01, 0x78, 0xBB, 0x20, 0x05, 0x9A, 0x10, 0x70, 0x06, 0x29, 0x07, 0x99, 0x11, 0xD1, 0x06, 0x20, 0x08, 0x60, 0x20, 0x98 , 0x00, 0x25, 0x05, 0x70, 0x21, 0x98, 0x29, 0x46, 0x04, 0x22, 0xFB, 0xF7, 0x27, 0xFB, 0x01, 0x20, 0x00, 0xF0, 0x3A, 0xFA, 0x02, 0x20, 0x00, 0xF0, 0x37, 0xFA, 0x22, 0x98, 0x05, 0x60, 0x07, 0x98, 0x04, 0x99, 0x00, 0x68, 0x07, 0x28, 0x44, 0xD1, 0x09, 0x78, 0x03, 0x9C, 0x80, 0x29, 0x40, 0xD1, 0x38, 0x34, 0x21, 0x78, 0x64, 0x1C, 0x22, 0x46, 0x00, 0x29, 0x3A, 0xD1, 0x20, 0x98, 0x90, 0xF8, 0x00, 0xA0, 0x22, 0x98, 0x05, 0x90, 0xD0, 0xF8, 0x00, 0x90, 0x51, 0x46, 0x48, 0x46, 0xFD, 0xF7, 0x79, 0xF9, 0x5F, 0xFA, 0x80, 0xF8, 0x21, 0x9F, 0x15, 0x78, 0x51, 0x46, 0x48, 0x46, 0x17, 0xF8, 0x08, 0x30, 0xFD, 0xF7, 0xD4, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x6F, 0xF9, 0x1E, 0x46, 0x1B, 0x1D, 0xC0, 0xB2, 0x38, 0x5C, 0x00, 0x1D, 0xA8, 0x42, 0x28, 0x46, 0x07, 0xDD, 0x80, 0x18, 0x82, 0x1C, 0x10, 0x78, 0x2D, 0x18, 0xAD, 0x1C, 0xAD, 0xB2, 0xAB, 0x42, 0xF7, 0xDC, 0x04, 0xF8, 0x01, 0x6B, 0x11, 0x49, 0x32, 0x46 , 0x20, 0x46, 0x01, 0xEB, 0x48, 0x11, 0xFA, 0xF7, 0xDC, 0xF9, 0xAD, 0x1B, 0xFF, 0x20, 0x34, 0x19, 0xAD, 0x1E, 0x04, 0xF8, 0x01, 0x0B, 0x25, 0x70, 0x05, 0x98, 0x01, 0x68, 0x49, 0x1C, 0x01, 0x60, 0x07, 0x98, 0x00, 0x68, 0x07, 0x28, 0x04, 0xD0, 0x06, 0x99, 0x08, 0x68, 0x20, 0xF4, 0x80, 0x30, 0x08, 0x60, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC0, 0x46, 0x94, 0x57, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x6E, 0x48, 0x2D, 0xE9, 0xF0, 0x47, 0x6E, 0x4D, 0x82, 0x89, 0x4A, 0xF6, 0x55, 0x21, 0xAD, 0xF5, 0xFE, 0x7D, 0x91, 0x42, 0x4F, 0xF0, 0x00, 0x01, 0xAD, 0xF1, 0x38, 0x0D, 0x12, 0xD1, 0x29, 0x60, 0x68, 0x4A, 0x11, 0x70, 0x41, 0xF2, 0x10, 0x41, 0x81, 0x81, 0x4F, 0xF6, 0xFF, 0x70, 0x66, 0x49, 0x08, 0x60, 0x28, 0x68, 0x00, 0x90, 0x02, 0x22, 0x05, 0x21, 0x03, 0x20, 0x41, 0xF2, 0x34, 0x23, 0xF3, 0xF7, 0x48, 0xF8, 0x29, 0x68, 0x61, 0x4C, 0x01, 0x29, 0x20, 0x68, 0x40, 0xF0, 0xAF, 0x80 , 0x5F, 0x4D, 0x02, 0x28, 0x29, 0x68, 0x23, 0xD1, 0x9C, 0x55, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x68, 0x5F, 0x4A, 0x12, 0x5C, 0x00, 0x92, 0x01, 0x91, 0x5E, 0x49, 0x09, 0x68, 0x02, 0x91, 0x5B, 0x49, 0x0B, 0x5C, 0x03, 0x20, 0x07, 0x21, 0x04, 0x22, 0xF3, 0xF7, 0x2E, 0xF8, 0x5B, 0x49, 0x4A, 0x79, 0x59, 0x48, 0x00, 0x92, 0x02, 0x79, 0x01, 0x92, 0x40, 0x79, 0x04, 0x22, 0x02, 0x90, 0x03, 0x20, 0x0B, 0x79, 0x07, 0x21, 0xF3, 0xF7, 0x20, 0xF8, 0x03, 0x20, 0x20, 0x60, 0xEC, 0xF7, 0x1A, 0xFF, 0x20, 0x68, 0x29, 0x68, 0x04, 0x28, 0x15, 0xD1, 0x0D, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x00, 0x25, 0x8D, 0xF8, 0x14, 0x50, 0x8D, 0xF8, 0x15, 0x10, 0x28, 0x46, 0x63, 0x21, 0x00, 0xF0, 0xAA, 0xFB, 0x63, 0x21, 0x28, 0x46, 0x00, 0xF0, 0xFA, 0xFA, 0x03, 0xA9, 0x04, 0xA8, 0xE0, 0xF7, 0xCA, 0xFC, 0x05, 0x20, 0x20, 0x60, 0x46, 0x4D, 0x05, 0x28, 0x29, 0x68, 0x01, 0xF1, 0x01, 0x01, 0x29, 0x60, 0x1D, 0xD1 , 0x44, 0x4A, 0x8A, 0x42, 0x1A, 0xD1, 0x43, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0x06, 0x21, 0x41, 0x4E, 0x33, 0x46, 0x22, 0x3B, 0xF2, 0xF7, 0xEB, 0xFF, 0x3E, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x33, 0x46, 0x06, 0x21, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xE0, 0xFF, 0x00, 0x20, 0x28, 0x60, 0x20, 0x68, 0x06, 0x28, 0x47, 0xD1, 0x4F, 0xF0, 0x64, 0x56, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x07, 0x0A, 0xC4, 0xF8, 0x00, 0xA0, 0x03, 0x20, 0x48, 0xF2, 0x70, 0x53, 0x01, 0x22, 0x04, 0x21, 0xF2, 0xF7, 0xD0, 0xFF, 0xDF, 0xF8, 0xCC, 0x80, 0x31, 0x4F, 0x48, 0xF2, 0x70, 0x59, 0x01, 0x25, 0x49, 0xEA, 0x05, 0x03, 0x01, 0x22, 0x04, 0x21, 0x03, 0x20, 0xF2, 0xF7, 0xC3, 0xFF, 0x00, 0x24, 0x17, 0xF8, 0x02, 0x0F, 0x20, 0xE0, 0x69, 0x01, 0x04, 0xEB, 0x08, 0x02, 0x88, 0x18, 0xC6, 0x1C, 0x43, 0x78, 0x00, 0x93, 0x80, 0x78, 0x01, 0x90, 0x30, 0x78, 0x02, 0x90 , 0x53, 0x5C, 0x51, 0x46, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xAE, 0xFF, 0x38, 0x78, 0x01, 0x1B, 0xB1, 0xF1, 0xFF, 0x3F, 0x08, 0xD1, 0xF0, 0x78, 0x00, 0x90, 0xB3, 0x78, 0x03, 0x20, 0x02, 0x22, 0x05, 0x21, 0xF2, 0xF7, 0xA1, 0xFF, 0x38, 0x78, 0x24, 0x1D, 0xE4, 0xB2, 0xA0, 0x42, 0xDC, 0xDC, 0xAD, 0x1C, 0xED, 0xB2, 0x04, 0x2D, 0xCD, 0xDB, 0x63, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0xF1, 0xF7, 0xA3, 0xFC, 0xE1, 0xF7, 0x85, 0xFD, 0x7F, 0xB0, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46, 0x04, 0x74, 0x00, 0x20, 0x50, 0x57, 0x02, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x40, 0x00, 0x3D, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x58, 0x57, 0x02, 0x00, 0x90, 0x57, 0x02, 0x00, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00, 0x2C, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x88, 0x57, 0x02, 0x00, 0x54, 0x57, 0x02, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58 , 0x02, 0x00, 0x66, 0x55, 0xDD, 0xEE, 0xDB, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x58, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x4A, 0x4A, 0x49, 0x4D, 0x00, 0x90, 0xB2, 0xF9, 0x00, 0x20, 0x43, 0xA3, 0x29, 0x78, 0x01, 0x93, 0x43, 0xA3, 0x01, 0x28, 0x02, 0x93, 0x47, 0x4E, 0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0x91, 0x1E, 0xD0, 0x43, 0x48, 0x04, 0x78, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0xC8, 0xFF, 0x40, 0x46, 0x01, 0x78, 0x00, 0x68, 0x07, 0xF1, 0x06, 0x07, 0x07, 0xF8, 0x01, 0x1B, 0x07, 0xF8, 0x01, 0x4B, 0x4F, 0xF0, 0x00, 0x01, 0x07, 0xF8, 0x01, 0x1B, 0x20, 0xB9, 0x39, 0x70, 0x28, 0x78, 0x4E, 0x46, 0x0A, 0x21, 0x58, 0xE0, 0xDF, 0xF8, 0xE4, 0xB0, 0x0F, 0xE0, 0xD4, 0xB2, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0xAA, 0xFF, 0xFF, 0x1D, 0x00, 0x20, 0xDF, 0xF8, 0xCC, 0xB0, 0x07, 0xF8, 0x01, 0x4B, 0x07, 0xF8, 0x01, 0x0B, 0x16, 0x2C, 0xB2, 0x46, 0xAE, 0xBF, 0x14, 0x20, 0x84, 0x59 , 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x60, 0x1E, 0xC0, 0xB2, 0x38, 0x70, 0x4E, 0x46, 0x7F, 0x1C, 0x40, 0x1C, 0xC2, 0xB2, 0x28, 0x78, 0x5B, 0x46, 0x00, 0x21, 0x32, 0x54, 0x38, 0x46, 0x00, 0xF0, 0xBC, 0xF9, 0x28, 0x78, 0x16, 0x2C, 0x31, 0x5C, 0x01, 0xF1, 0x0A, 0x01, 0x31, 0x54, 0x00, 0xF1, 0x01, 0x00, 0xC0, 0xB2, 0x28, 0x70, 0x2B, 0xDB, 0x00, 0x99, 0x0A, 0xEB, 0x40, 0x10, 0x07, 0x46, 0x01, 0x29, 0xA4, 0xF1, 0x01, 0x09, 0x09, 0xD0, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0x79, 0xFF, 0x40, 0x46, 0x00, 0x78, 0xBF, 0x1D, 0x07, 0xF8, 0x01, 0x0B, 0x04, 0xE0, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0x6F, 0xFF, 0xFF, 0x1D, 0x07, 0xF8, 0x01, 0x4B, 0x15, 0x3C, 0x15, 0x21, 0x28, 0x78, 0xE2, 0xB2, 0x5B, 0x46, 0x07, 0xF8, 0x01, 0x1B, 0x32, 0x54, 0x07, 0xF8, 0x01, 0x9B, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF9, 0x28, 0x78, 0x31, 0x5C, 0x0A, 0x31, 0x31, 0x54, 0x40, 0x1C, 0x28, 0x70, 0xBD, 0xE8, 0xFE, 0x8F, 0xC0, 0x46 , 0x54, 0x54, 0x54, 0x4B, 0x45, 0x59, 0x00, 0xC0, 0x54, 0x54, 0x54, 0x53, 0x53, 0x49, 0x44, 0x00, 0x54, 0x58, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x94, 0x57, 0x02, 0x00, 0xFF, 0xB5, 0x0C, 0x46, 0x06, 0x46, 0xF7, 0xF7, 0x4C, 0x5A, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE3, 0xFE, 0x15, 0x49, 0x15, 0x4A, 0x0D, 0x68, 0x01, 0xA9, 0x92, 0xE8, 0x8C, 0x00, 0x81, 0xE8, 0x8C, 0x00, 0xF7, 0xF7, 0xFD, 0xFE, 0x01, 0x98, 0x11, 0x49, 0x28, 0x1A, 0x03, 0x9D, 0x25, 0x60, 0x02, 0x9A, 0x80, 0x18, 0x82, 0x42, 0x30, 0x60, 0x0E, 0xD8, 0x08, 0x46, 0x00, 0x68, 0x22, 0x68, 0x82, 0x42, 0x0E, 0xD2, 0x68, 0x46, 0xE8, 0xF7, 0xB9, 0xFF, 0x9D, 0xF8, 0x00, 0x00, 0x05, 0xF1, 0x01, 0x05, 0x30, 0xB9, 0x03, 0x95, 0x03, 0xE0, 0x25, 0x68, 0x6D, 0x1C, 0x25, 0x60, 0x0C, 0x46, 0x25, 0x60, 0x00, 0x20, 0x00, 0x90 , 0xFF, 0xBD, 0x60, 0x55, 0x30, 0x80, 0x24, 0x5D, 0x00, 0x20, 0x6C, 0x5D, 0x02, 0x00, 0x70, 0xB5, 0x4D, 0x00, 0x20, 0x2D, 0x4F, 0xF0, 0x00, 0x01, 0x0C, 0x46, 0x4F, 0xEA, 0x55, 0x13, 0x09, 0xD3, 0x50, 0xF8, 0x21, 0x60, 0xB6, 0xF1, 0xFF, 0x3F, 0x04, 0xD1, 0x49, 0x1C, 0xC9, 0xB2, 0x20, 0x3D, 0x5B, 0x1E, 0xF5, 0xD1, 0x4D, 0xB1, 0x20, 0x2D, 0x09, 0xD2, 0x01, 0x23, 0xAB, 0x40, 0x5B, 0x1E, 0x50, 0xF8, 0x21, 0x00, 0x18, 0x40, 0x83, 0x42, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x04, 0x07, 0x48, 0x03, 0x78, 0x2C, 0xB9, 0x01, 0x21, 0x91, 0x40, 0xC9, 0x43, 0xC9, 0xB2, 0x0B, 0x40, 0x03, 0xE0, 0x01, 0x21, 0x91, 0x40, 0xC9, 0xB2, 0x0B, 0x43, 0x03, 0x70, 0x70, 0xBD, 0xC0, 0x46, 0xEE, 0x58, 0x02, 0x00, 0x14, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x7E, 0xB5, 0x05, 0x46, 0x95, 0xF8, 0x36, 0x20, 0x0E, 0x46, 0x0F, 0x49, 0x07, 0x2A, 0x12, 0xBF, 0x08, 0x68, 0x01, 0x20, 0x08, 0x60, 0x0D, 0x4C, 0x00, 0x92, 0x21, 0x68 , 0x41, 0xF2, 0x12, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF2, 0xF7, 0x6B, 0xFD, 0x31, 0x46, 0x28, 0x46, 0xE7, 0xF7, 0x21, 0xFC, 0x21, 0x68, 0x00, 0x22, 0x05, 0x29, 0x02, 0xD1, 0x04, 0x49, 0x08, 0x31, 0x0A, 0x60, 0x7E, 0xBD, 0xC0, 0x46, 0x50, 0x57, 0x02, 0x00, 0x4C, 0x57, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x20, 0x0E, 0x49, 0x09, 0x68, 0x49, 0x08, 0x15, 0xD2, 0x0D, 0x49, 0x09, 0x78, 0x91, 0xB1, 0x44, 0xF2, 0xE9, 0x21, 0x68, 0xB9, 0x0B, 0x48, 0x01, 0x78, 0x07, 0x48, 0x01, 0x29, 0x03, 0xD1, 0x0A, 0x49, 0x09, 0x78, 0x0E, 0x29, 0x02, 0xD0, 0x44, 0xF2, 0xDE, 0x21, 0x41, 0x60, 0x01, 0x21, 0x00, 0xE0, 0x06, 0x48, 0x01, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x97, 0x3C, 0x80, 0x10, 0x0C, 0x30, 0x80, 0xDD, 0x6A, 0x00, 0x20, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x00, 0xB5, 0xAD, 0xF1, 0x18, 0x0D, 0x4F, 0xF0, 0x09, 0x00, 0x00, 0x90, 0x4F, 0xF4 , 0x0C, 0x60, 0x03, 0x90, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0x90, 0x02, 0x90, 0x08, 0x48, 0x08, 0x49, 0x05, 0x90, 0x08, 0x68, 0x20, 0xB9, 0xDC, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0x3A, 0xFA, 0x03, 0xE0, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0xC1, 0xFC, 0x06, 0xB0, 0x00, 0xBD, 0xC0, 0x46, 0x81, 0x5C, 0x02, 0x00, 0xDC, 0x7C, 0x00, 0x20, 0x1C, 0xB5, 0x0F, 0x4C, 0x22, 0x68, 0x01, 0x2A, 0x15, 0xD1, 0x0C, 0x48, 0x00, 0x68, 0x07, 0x28, 0x14, 0xBF, 0x40, 0x20, 0x4F, 0xF4, 0x05, 0x70, 0x63, 0x21, 0xF1, 0xF7, 0x0F, 0xFA, 0x20, 0x68, 0x00, 0x90, 0x43, 0xF2, 0x33, 0x33, 0x06, 0x21, 0x40, 0x20, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xF4, 0xFC, 0x1C, 0xBD, 0xF1, 0xF7, 0x01, 0xFA, 0x1C, 0xBD, 0x4C, 0x57, 0x02, 0x00, 0x50, 0x57, 0x02, 0x00, 0x1E, 0xB5, 0x04, 0x46, 0x0A, 0x49, 0x00, 0x20, 0x0A, 0x4A, 0x08, 0x60, 0x0A, 0x49, 0x00, 0x90, 0x01, 0x90, 0x11, 0x60 , 0x09, 0x4A, 0x45, 0xF2, 0x55, 0x53, 0x02, 0x91, 0x10, 0x60, 0x07, 0x21, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xD8, 0xFC, 0x20, 0x46, 0xE7, 0xF7, 0x59, 0xFD, 0x1E, 0xBD, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x4C, 0x57, 0x02, 0x00, 0x00, 0xB5, 0x0B, 0x49, 0x00, 0x20, 0x08, 0x60, 0xE0, 0x20, 0xF7, 0xF7, 0xAA, 0xFD, 0x09, 0x49, 0x09, 0x78, 0x49, 0xB1, 0x08, 0x49, 0x0A, 0x78, 0x08, 0x49, 0x00, 0x2A, 0x06, 0xBF, 0x01, 0x22, 0x09, 0x1F, 0x44, 0xF2, 0xA4, 0x5C, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE9, 0x22, 0x0A, 0x60, 0xF7, 0xF7, 0xA1, 0xFD, 0x00, 0xBD, 0xC0, 0x46, 0xDC, 0x7C, 0x00, 0x20, 0xDD, 0x6A, 0x00, 0x20, 0xA7, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x50, 0xB9, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x06, 0xD1, 0x08, 0x48, 0x00, 0x78, 0x0E, 0x28, 0x08, 0xBF, 0x44, 0xF2, 0xCB, 0x20, 0x01, 0xD0, 0x44, 0xF2, 0xDE, 0x20, 0x04, 0x49, 0x08, 0x60, 0x01, 0x20 , 0x41, 0xF8, 0x04, 0x0C, 0x70, 0x47, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x30, 0xB5, 0x0D, 0x46, 0x84, 0x69, 0xDC, 0xF7, 0x97, 0xFB, 0x24, 0x1D, 0x01, 0x28, 0x04, 0xEB, 0x45, 0x01, 0x06, 0xD1, 0x89, 0x8E, 0x04, 0xEB, 0x85, 0x04, 0x11, 0xB9, 0x21, 0x69, 0x01, 0xB9, 0x00, 0x20, 0x30, 0xBD, 0x30, 0xB5, 0x05, 0x46, 0x5A, 0xB1, 0x03, 0xEB, 0x41, 0x03, 0x1C, 0x78, 0x59, 0x78, 0x41, 0xEA, 0x04, 0x11, 0x52, 0x1E, 0x03, 0xF1, 0x02, 0x03, 0x05, 0xF8, 0x01, 0x1B, 0xF5, 0xD1, 0x30, 0xBD, 0x00, 0xB5, 0x00, 0x20, 0xE7, 0xF7, 0xD6, 0xFE, 0x03, 0x48, 0x01, 0x68, 0x03, 0x29, 0x04, 0xBF, 0x04, 0x21, 0x01, 0x60, 0x00, 0xBD, 0xC0, 0x46, 0x4C, 0x57, 0x02, 0x00, 0x03, 0x4A, 0x12, 0x68, 0x01, 0x2A, 0x04, 0xBF, 0x02, 0x48, 0x63, 0x21, 0xF1, 0xF7, 0x76, 0xB9, 0x50, 0x57, 0x02, 0x00, 0x02, 0x20, 0x01, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; micropython-1.12/drivers/cc3000/src/patch_prog.c000066400000000000000000000303571357706137100214610ustar00rootroot00000000000000#include #include #include "cc3000_common.h" #include "nvmem.h" #include "ccspi.h" #include "hci.h" #include "wlan.h" #include "patch_prog.h" #define BIT0 0x1 #define BIT1 0x2 #define BIT2 0x4 #define BIT3 0x8 #define BIT4 0x10 #define BIT5 0x20 #define BIT6 0x40 #define BIT7 0x80 static unsigned char ucStatus_Dr; static unsigned char ucStatus_FW; static unsigned char return_status = 0xFF; static signed char mac_status = -1; static unsigned char counter = 0; // Array to store RM parameters from EEPROM. static unsigned char cRMParamsFromEeprom[128]; // Array to store MAC address from EEPROM. static unsigned char cMacFromEeprom[MAC_ADDR_LEN]; // Smart Config Prefix static const char aucCC3000_prefix[] = {'T', 'T', 'T'}; static void systick_sleep(unsigned long ms) { extern void HAL_Delay(volatile uint32_t Delay); HAL_Delay(ms); } // 2 dim array to store address and length of new FAT static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] = /* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830}, /* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}}; /* 0. NVS */ /* 1. NVS Shadow */ /* 2. Wireless Conf */ /* 3. Wireless Conf Shadow */ /* 4. BT (WLAN driver) Patches */ /* 5. WiLink (Firmware) Patches */ /* 6. MAC addr */ /* 7. Frontend Vars */ /* 8. IP config */ /* 9. IP config Shadow */ /* 10. Bootloader Patches */ /* 11. Radio Module params */ /* 12. AES128 for smart config */ /* 13. user file */ /* 14. user file */ /* 15. user file */ //***************************************************************************** // //! sendDriverPatch //! //! \param pointer to the length //! //! \return none //! //! \brief The function returns a pointer to the driver patch: //! since there is no patch yet - it returns 0 // //***************************************************************************** static char *sendDriverPatch(unsigned long *Length) { *Length = 0; return NULL; } //***************************************************************************** // //! sendBootLoaderPatch //! //! \param pointer to the length //! //! \return none //! //! \brief The function returns a pointer to the boot loader patch: //! since there is no patch yet - it returns 0 // //***************************************************************************** static char *sendBootLoaderPatch(unsigned long *Length) { *Length = 0; return NULL; } //***************************************************************************** // //! sendWLFWPatch //! //! \param pointer to the length //! //! \return none //! //! \brief The function returns a pointer to the FW patch: //! since there is no patch yet - it returns 0 // //***************************************************************************** static char *sendWLFWPatch(unsigned long *Length) { *Length = 0; return NULL; } //***************************************************************************** // //! CC3000_UsynchCallback //! //! \param Event type //! //! \return none //! //! \brief The function handles asynchronous events that come from CC3000 //! device and operates a LED4 to have an on-board indication // //***************************************************************************** static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length) { } //***************************************************************************** // //! initDriver //! //! \param[in] cRequestPatch 0 to load with EEPROM patches //! and 1 to load with no patches //! //! \return none //! //! \brief The function initializes a CC3000 device //! and triggers it to start operation // //***************************************************************************** static int initDriver(unsigned short cRequestPatch) { // WLAN On API Implementation wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin); // Trigger a WLAN device wlan_start(cRequestPatch); wlan_smart_config_set_prefix((char*)aucCC3000_prefix); wlan_ioctl_set_connection_policy(0, 0, 0); wlan_ioctl_del_profile(255); // Mask out all non-required events from CC3000 wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE| HCI_EVNT_WLAN_UNSOL_INIT| HCI_EVNT_WLAN_ASYNC_PING_REPORT); //unsolicicted_events_timer_init(); systick_sleep(100); return(0); } //***************************************************************************** // //! fat_read_content //! //! \param[out] is_allocated array of is_allocated in FAT table:\n //! an allocated entry implies the address and length of the //! file are valid. //! 0: not allocated; 1: allocated. //! \param[out] is_valid array of is_valid in FAT table:\n //! a valid entry implies the content of the file is relevant. //! 0: not valid; 1: valid. //! \param[out] write_protected array of write_protected in FAT table:\n //! a write protected entry implies it is not possible to write //! into this entry. //! 0: not protected; 1: protected. //! \param[out] file_address array of file address in FAT table:\n //! this is the absolute address of the file in the EEPROM. //! \param[out] file_length array of file length in FAT table:\n //! this is the upper limit of the file size in the EEPROM. //! //! \return on succes 0, error otherwise //! //! \brief parse the FAT table from eeprom // //***************************************************************************** static unsigned char __attribute__ ((unused)) fat_read_content(unsigned char *is_allocated, unsigned char *is_valid, unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length) { unsigned short index; unsigned char ucStatus; unsigned char fatTable[48]; unsigned char* fatTablePtr = fatTable; // // Read in 6 parts to work with tiny driver // for (index = 0; index < 6; index++) { ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr); fatTablePtr += 8; } fatTablePtr = fatTable; for (index = 0; index <= NVMEM_RM_FILEID; index++) { *is_allocated++ = (*fatTablePtr) & BIT0; *is_valid++ = ((*fatTablePtr) & BIT1) >> 1; *write_protected++ = ((*fatTablePtr) & BIT2) >> 2; *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7); *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7); // // Move to next file ID // fatTablePtr += 4; } return ucStatus; } //***************************************************************************** // //! fat_write_content //! //! \param[in] file_address array of file address in FAT table:\n //! this is the absolute address of the file in the EEPROM. //! \param[in] file_length array of file length in FAT table:\n //! this is the upper limit of the file size in the EEPROM. //! //! \return on succes 0, error otherwise //! //! \brief parse the FAT table from eeprom // //***************************************************************************** static unsigned char fat_write_content(unsigned short const *file_address, unsigned short const *file_length) { unsigned short index = 0; unsigned char ucStatus; unsigned char fatTable[48]; unsigned char* fatTablePtr = fatTable; // // First, write the magic number. // ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS"); for (; index <= NVMEM_RM_FILEID; index++) { // // Write address low char and mark as allocated. // *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0; // // Write address high char. // *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff); // // Write length low char. // *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff); // // Write length high char. // *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff); } // // Second, write the FAT. // Write in two parts to work with tiny driver. // ucStatus = nvmem_write(16, 24, 4, fatTable); ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]); // // Third, we want to erase any user files. // memset(fatTable, 0, sizeof(fatTable)); ucStatus = nvmem_write(16, 16, 52, fatTable); return ucStatus; } void patch_prog_start() { unsigned short index; unsigned char *pRMParams; printf("Initializing module...\n"); // Init module and request to load with no patches. // This is in order to overwrite restrictions to // write to specific places in EEPROM. initDriver(1); // Read MAC address. mac_status = nvmem_get_mac_address(cMacFromEeprom); return_status = 1; printf("Reading RM parameters...\n"); while ((return_status) && (counter < 3)) { // Read RM parameters. // Read in 16 parts to work with tiny driver. return_status = 0; pRMParams = cRMParamsFromEeprom; for (index = 0; index < 16; index++) { return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams); pRMParams += 8; } counter++; } // If RM file is not valid, load the default one. if (counter == 3) { printf("RM is not valid, loading default one...\n"); pRMParams = (unsigned char *)cRMdefaultParams; } else { printf("RM is valid.\n"); pRMParams = cRMParamsFromEeprom; } return_status = 1; printf("Writing new FAT\n"); while (return_status) { // Write new FAT. return_status = fat_write_content(aFATEntries[0], aFATEntries[1]); } return_status = 1; printf("Writing RM parameters...\n"); while (return_status) { // Write RM parameters. // Write in 4 parts to work with tiny driver. return_status = 0; for (index = 0; index < 4; index++) { return_status |= nvmem_write(NVMEM_RM_FILEID, 32, 32*index, (pRMParams + 32*index)); } } return_status = 1; // Write back the MAC address, only if exists. if (mac_status == 0) { // Zero out MCAST bit if set. cMacFromEeprom[0] &= 0xfe; printf("Writing back MAC address..\n"); while (return_status) { return_status = nvmem_set_mac_address(cMacFromEeprom); } } // Update driver ucStatus_Dr = 1; printf("Updating driver patch...\n"); while (ucStatus_Dr) { // Writing driver patch to EEPRROM - PROTABLE CODE // Note that the array itself is changing between the // different Service Packs. ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID, drv_length, wlan_drv_patch); } // Update firmware ucStatus_FW = 1; printf("Updating firmware patch...\n"); while (ucStatus_FW) { // Writing FW patch to EEPRROM - PROTABLE CODE // Note that the array itself is changing between the // different Service Packs. ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID, fw_length, fw_patch); } printf("Update complete, resetting module\n"\ "If this doesn't work, reset manually...\n"); wlan_stop(); systick_sleep(500); // Re-Init module and request to load with patches. initDriver(0); // If MAC does not exist, it is recommended // that the user will write a valid mac address. if (mac_status != 0) { printf("MAC address is not valid, please write a new one\n"); } // Patch update done printf("All done, call wlan.patch_version()\n"); } micropython-1.12/drivers/cc3000/src/security.c000066400000000000000000000551551357706137100212050ustar00rootroot00000000000000/***************************************************************************** * * security.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ //***************************************************************************** // //! \addtogroup security_api //! @{ // //***************************************************************************** #include "security.h" #ifndef CC3000_UNENCRYPTED_SMART_CONFIG // foreward sbox const UINT8 sbox[256] = { //0 1 2 3 4 5 6 7 8 9 A B C D E F 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F // inverse sbox const UINT8 rsbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b , 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; // round constant const UINT8 Rcon[11] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; UINT8 expandedKey[176]; //***************************************************************************** // //! expandKey //! //! @param key AES128 key - 16 bytes //! @param expandedKey expanded AES128 key //! //! @return none //! //! @brief expend a 16 bytes key for AES128 implementation //! //***************************************************************************** void expandKey(UINT8 *expandedKey, UINT8 *key) { UINT16 ii, buf1; for (ii=0;ii<16;ii++) expandedKey[ii] = key[ii]; for (ii=1;ii<11;ii++){ buf1 = expandedKey[ii*16 - 4]; expandedKey[ii*16 + 0] = sbox[expandedKey[ii*16 - 3]]^expandedKey[(ii-1)*16 + 0]^Rcon[ii]; expandedKey[ii*16 + 1] = sbox[expandedKey[ii*16 - 2]]^expandedKey[(ii-1)*16 + 1]; expandedKey[ii*16 + 2] = sbox[expandedKey[ii*16 - 1]]^expandedKey[(ii-1)*16 + 2]; expandedKey[ii*16 + 3] = sbox[buf1 ]^expandedKey[(ii-1)*16 + 3]; expandedKey[ii*16 + 4] = expandedKey[(ii-1)*16 + 4]^expandedKey[ii*16 + 0]; expandedKey[ii*16 + 5] = expandedKey[(ii-1)*16 + 5]^expandedKey[ii*16 + 1]; expandedKey[ii*16 + 6] = expandedKey[(ii-1)*16 + 6]^expandedKey[ii*16 + 2]; expandedKey[ii*16 + 7] = expandedKey[(ii-1)*16 + 7]^expandedKey[ii*16 + 3]; expandedKey[ii*16 + 8] = expandedKey[(ii-1)*16 + 8]^expandedKey[ii*16 + 4]; expandedKey[ii*16 + 9] = expandedKey[(ii-1)*16 + 9]^expandedKey[ii*16 + 5]; expandedKey[ii*16 +10] = expandedKey[(ii-1)*16 +10]^expandedKey[ii*16 + 6]; expandedKey[ii*16 +11] = expandedKey[(ii-1)*16 +11]^expandedKey[ii*16 + 7]; expandedKey[ii*16 +12] = expandedKey[(ii-1)*16 +12]^expandedKey[ii*16 + 8]; expandedKey[ii*16 +13] = expandedKey[(ii-1)*16 +13]^expandedKey[ii*16 + 9]; expandedKey[ii*16 +14] = expandedKey[(ii-1)*16 +14]^expandedKey[ii*16 +10]; expandedKey[ii*16 +15] = expandedKey[(ii-1)*16 +15]^expandedKey[ii*16 +11]; } } //***************************************************************************** // //! galois_mul2 //! //! @param value argument to multiply //! //! @return multiplied argument //! //! @brief multiply by 2 in the galois field //! //***************************************************************************** UINT8 galois_mul2(UINT8 value) { if (value>>7) { value = value << 1; return (value^0x1b); } else return value<<1; } //***************************************************************************** // //! aes_encr //! //! @param[in] expandedKey expanded AES128 key //! @param[in/out] state 16 bytes of plain text and cipher text //! //! @return none //! //! @brief internal implementation of AES128 encryption. //! straight forward aes encryption implementation //! first the group of operations //! - addRoundKey //! - subbytes //! - shiftrows //! - mixcolums //! is executed 9 times, after this addroundkey to finish the 9th //! round, after that the 10th round without mixcolums //! no further subfunctions to save cycles for function calls //! no structuring with "for (....)" to save cycles. //! //! //***************************************************************************** void aes_encr(UINT8 *state, UINT8 *expandedKey) { UINT8 buf1, buf2, buf3, round; for (round = 0; round < 9; round ++){ // addroundkey, sbox and shiftrows // row 0 state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])]; state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])]; state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])]; state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])]; // row 1 buf1 = state[1] ^ expandedKey[(round*16) + 1]; state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])]; state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])]; state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])]; state[13] = sbox[buf1]; // row 2 buf1 = state[2] ^ expandedKey[(round*16) + 2]; buf2 = state[6] ^ expandedKey[(round*16) + 6]; state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])]; state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])]; state[10] = sbox[buf1]; state[14] = sbox[buf2]; // row 3 buf1 = state[15] ^ expandedKey[(round*16) + 15]; state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])]; state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])]; state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])]; state[ 3] = sbox[buf1]; // mixcolums ////////// // col1 buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; buf2 = state[0]; buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; // col2 buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; buf2 = state[4]; buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; // col3 buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; buf2 = state[8]; buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; // col4 buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; buf2 = state[12]; buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; } // 10th round without mixcols state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])]; state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])]; state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])]; state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])]; // row 1 buf1 = state[1] ^ expandedKey[(round*16) + 1]; state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])]; state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])]; state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])]; state[13] = sbox[buf1]; // row 2 buf1 = state[2] ^ expandedKey[(round*16) + 2]; buf2 = state[6] ^ expandedKey[(round*16) + 6]; state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])]; state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])]; state[10] = sbox[buf1]; state[14] = sbox[buf2]; // row 3 buf1 = state[15] ^ expandedKey[(round*16) + 15]; state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])]; state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])]; state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])]; state[ 3] = sbox[buf1]; // last addroundkey state[ 0]^=expandedKey[160]; state[ 1]^=expandedKey[161]; state[ 2]^=expandedKey[162]; state[ 3]^=expandedKey[163]; state[ 4]^=expandedKey[164]; state[ 5]^=expandedKey[165]; state[ 6]^=expandedKey[166]; state[ 7]^=expandedKey[167]; state[ 8]^=expandedKey[168]; state[ 9]^=expandedKey[169]; state[10]^=expandedKey[170]; state[11]^=expandedKey[171]; state[12]^=expandedKey[172]; state[13]^=expandedKey[173]; state[14]^=expandedKey[174]; state[15]^=expandedKey[175]; } //***************************************************************************** // //! aes_decr //! //! @param[in] expandedKey expanded AES128 key //! @param[in\out] state 16 bytes of cipher text and plain text //! //! @return none //! //! @brief internal implementation of AES128 decryption. //! straight forward aes decryption implementation //! the order of substeps is the exact reverse of decryption //! inverse functions: //! - addRoundKey is its own inverse //! - rsbox is inverse of sbox //! - rightshift instead of leftshift //! - invMixColumns = barreto + mixColumns //! no further subfunctions to save cycles for function calls //! no structuring with "for (....)" to save cycles //! //***************************************************************************** void aes_decr(UINT8 *state, UINT8 *expandedKey) { UINT8 buf1, buf2, buf3; INT8 round; round = 9; // initial addroundkey state[ 0]^=expandedKey[160]; state[ 1]^=expandedKey[161]; state[ 2]^=expandedKey[162]; state[ 3]^=expandedKey[163]; state[ 4]^=expandedKey[164]; state[ 5]^=expandedKey[165]; state[ 6]^=expandedKey[166]; state[ 7]^=expandedKey[167]; state[ 8]^=expandedKey[168]; state[ 9]^=expandedKey[169]; state[10]^=expandedKey[170]; state[11]^=expandedKey[171]; state[12]^=expandedKey[172]; state[13]^=expandedKey[173]; state[14]^=expandedKey[174]; state[15]^=expandedKey[175]; // 10th round without mixcols state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ]; state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4]; state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8]; state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12]; // row 1 buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1]; state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13]; state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9]; state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5]; state[ 1] = buf1; // row 2 buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10]; buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14]; state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2]; state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6]; state[10] = buf1; state[14] = buf2; // row 3 buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15]; state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3]; state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7]; state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11]; state[15] = buf1; for (round = 8; round >= 0; round--){ // barreto //col1 buf1 = galois_mul2(galois_mul2(state[0]^state[2])); buf2 = galois_mul2(galois_mul2(state[1]^state[3])); state[0] ^= buf1; state[1] ^= buf2; state[2] ^= buf1; state[3] ^= buf2; //col2 buf1 = galois_mul2(galois_mul2(state[4]^state[6])); buf2 = galois_mul2(galois_mul2(state[5]^state[7])); state[4] ^= buf1; state[5] ^= buf2; state[6] ^= buf1; state[7] ^= buf2; //col3 buf1 = galois_mul2(galois_mul2(state[8]^state[10])); buf2 = galois_mul2(galois_mul2(state[9]^state[11])); state[8] ^= buf1; state[9] ^= buf2; state[10] ^= buf1; state[11] ^= buf2; //col4 buf1 = galois_mul2(galois_mul2(state[12]^state[14])); buf2 = galois_mul2(galois_mul2(state[13]^state[15])); state[12] ^= buf1; state[13] ^= buf2; state[14] ^= buf1; state[15] ^= buf2; // mixcolums ////////// // col1 buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; buf2 = state[0]; buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; // col2 buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; buf2 = state[4]; buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; // col3 buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; buf2 = state[8]; buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; // col4 buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; buf2 = state[12]; buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; // addroundkey, rsbox and shiftrows // row 0 state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ]; state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4]; state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8]; state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12]; // row 1 buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1]; state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13]; state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9]; state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5]; state[ 1] = buf1; // row 2 buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10]; buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14]; state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2]; state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6]; state[10] = buf1; state[14] = buf2; // row 3 buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15]; state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3]; state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7]; state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11]; state[15] = buf1; } } //***************************************************************************** // //! aes_encrypt //! //! @param[in] key AES128 key of size 16 bytes //! @param[in\out] state 16 bytes of plain text and cipher text //! //! @return none //! //! @brief AES128 encryption: //! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes //! is computed. The AES implementation is in mode ECB (Electronic //! Code Book). //! //! //***************************************************************************** void aes_encrypt(UINT8 *state, UINT8 *key) { // expand the key into 176 bytes expandKey(expandedKey, key); aes_encr(state, expandedKey); } //***************************************************************************** // //! aes_decrypt //! //! @param[in] key AES128 key of size 16 bytes //! @param[in\out] state 16 bytes of cipher text and plain text //! //! @return none //! //! @brief AES128 decryption: //! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes //! is computed The AES implementation is in mode ECB //! (Electronic Code Book). //! //! //***************************************************************************** void aes_decrypt(UINT8 *state, UINT8 *key) { expandKey(expandedKey, key); // expand the key into 176 bytes aes_decr(state, expandedKey); } //***************************************************************************** // //! aes_read_key //! //! @param[out] key AES128 key of size 16 bytes //! //! @return on success 0, error otherwise. //! //! @brief Reads AES128 key from EEPROM //! Reads the AES128 key from fileID #12 in EEPROM //! returns an error if the key does not exist. //! //! //***************************************************************************** INT32 aes_read_key(UINT8 *key) { INT32 returnValue; returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); return returnValue; } //***************************************************************************** // //! aes_write_key //! //! @param[out] key AES128 key of size 16 bytes //! //! @return on success 0, error otherwise. //! //! @brief writes AES128 key from EEPROM //! Writes the AES128 key to fileID #12 in EEPROM //! //! //***************************************************************************** INT32 aes_write_key(UINT8 *key) { INT32 returnValue; returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); return returnValue; } #endif //CC3000_UNENCRYPTED_SMART_CONFIG //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/drivers/cc3000/src/socket.c000066400000000000000000001216631357706137100206240ustar00rootroot00000000000000/***************************************************************************** * * socket.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ //***************************************************************************** // //! \addtogroup socket_api //! @{ // //***************************************************************************** #include #include #include "hci.h" #include "socket.h" #include "evnt_handler.h" #include "netapp.h" //Enable this flag if and only if you must comply with BSD socket //close() function #ifdef _API_USE_BSD_CLOSE #define close(sd) closesocket(sd) #endif //Enable this flag if and only if you must comply with BSD socket read() and //write() functions #ifdef _API_USE_BSD_READ_WRITE #define read(sd, buf, len, flags) recv(sd, buf, len, flags) #define write(sd, buf, len, flags) send(sd, buf, len, flags) #endif #define SOCKET_OPEN_PARAMS_LEN (12) #define SOCKET_CLOSE_PARAMS_LEN (4) #define SOCKET_ACCEPT_PARAMS_LEN (4) #define SOCKET_BIND_PARAMS_LEN (20) #define SOCKET_LISTEN_PARAMS_LEN (8) #define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9) #define SOCKET_CONNECT_PARAMS_LEN (20) #define SOCKET_SELECT_PARAMS_LEN (44) #define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20) #define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12) #define SOCKET_RECV_FROM_PARAMS_LEN (12) #define SOCKET_SENDTO_PARAMS_LEN (24) #define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12) #define SOCKET_GET_MSS_VALUE_PARAMS_LEN (4) // The legnth of arguments for the SEND command: sd + buff_offset + len + flags, // while size of each parameter is 32 bit - so the total length is 16 bytes; #define HCI_CMND_SEND_ARG_LENGTH (16) #define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000 #define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5) #define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) #define MDNS_DEVICE_SERVICE_MAX_LENGTH (32) //***************************************************************************** // //! HostFlowControlConsumeBuff //! //! @param sd socket descriptor //! //! @return 0 in case there are buffers available, //! -1 in case of bad socket //! -2 if there are no free buffers present (only when //! SEND_NON_BLOCKING is enabled) //! //! @brief if SEND_NON_BLOCKING not define - block until have free buffer //! becomes available, else return immediately with correct status //! regarding the buffers available. // //***************************************************************************** static INT16 HostFlowControlConsumeBuff(INT16 sd) { #ifndef SEND_NON_BLOCKING /* wait in busy loop */ do { // In case last transmission failed then we will return the last failure // reason here. // Note that the buffer will not be allocated in this case if (tSLInformation.slTransmitDataError != 0) { CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError; tSLInformation.slTransmitDataError = 0; return CC3000_EXPORT(errno); } if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) return -1; } while(0 == tSLInformation.usNumberOfFreeBuffers); tSLInformation.usNumberOfFreeBuffers--; return 0; #else // In case last transmission failed then we will return the last failure // reason here. // Note that the buffer will not be allocated in this case if (tSLInformation.slTransmitDataError != 0) { CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError; tSLInformation.slTransmitDataError = 0; return CC3000_EXPORT(errno); } if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) return -1; //If there are no available buffers, return -2. It is recommended to use // select or receive to see if there is any buffer occupied with received data // If so, call receive() to release the buffer. if(0 == tSLInformation.usNumberOfFreeBuffers) { return -2; } else { tSLInformation.usNumberOfFreeBuffers--; return 0; } #endif } //***************************************************************************** // //! socket //! //! @param domain selects the protocol family which will be used for //! communication. On this version only AF_INET is supported //! @param type specifies the communication semantics. On this version //! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported //! @param protocol specifies a particular protocol to be used with the //! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are //! supported. //! //! @return On success, socket handle that is used for consequent socket //! operations. On error, -1 is returned. //! //! @brief create an endpoint for communication //! The socket function creates a socket that is bound to a specific //! transport service provider. This function is called by the //! application layer to obtain a socket handle. // //***************************************************************************** INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol) { INT32 ret; UINT8 *ptr, *args; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, domain); args = UINT32_TO_STREAM(args, type); args = UINT32_TO_STREAM(args, protocol); // Initiate a HCI command hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret); // Process the event CC3000_EXPORT(errno) = ret; set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); return(ret); } //***************************************************************************** // //! closesocket //! //! @param sd socket handle. //! //! @return On success, zero is returned. On error, -1 is returned. //! //! @brief The socket function closes a created socket. // //***************************************************************************** INT32 CC3000_EXPORT(closesocket)(INT32 sd) { INT32 ret; UINT8 *ptr, *args; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, sd); // Initiate a HCI command hci_command_send(HCI_CMND_CLOSE_SOCKET, ptr, SOCKET_CLOSE_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret); CC3000_EXPORT(errno) = ret; // since 'close' call may result in either OK (and then it closed) or error // mark this socket as invalid set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); return(ret); } //***************************************************************************** // //! accept //! //! @param[in] sd socket descriptor (handle) //! @param[out] addr the argument addr is a pointer to a sockaddr structure //! This structure is filled in with the address of the //! peer socket, as known to the communications layer. //! determined. The exact format of the address returned //! addr is by the socket's address sockaddr. //! On this version only AF_INET is supported. //! This argument returns in network order. //! @param[out] addrlen the addrlen argument is a value-result argument: //! it should initially contain the size of the structure //! pointed to by addr. //! //! @return For socket in blocking mode: //! On success, socket handle. on failure negative //! For socket in non-blocking mode: //! - On connection establishment, socket handle //! - On connection pending, SOC_IN_PROGRESS (-2) //! - On failure, SOC_ERROR (-1) //! //! @brief accept a connection on a socket: //! This function is used with connection-based socket types //! (SOCK_STREAM). It extracts the first connection request on the //! queue of pending connections, creates a new connected socket, and //! returns a new file descriptor referring to that socket. //! The newly created socket is not in the listening state. //! The original socket sd is unaffected by this call. //! The argument sd is a socket that has been created with socket(), //! bound to a local address with bind(), and is listening for //! connections after a listen(). The argument addr is a pointer //! to a sockaddr structure. This structure is filled in with the //! address of the peer socket, as known to the communications layer. //! The exact format of the address returned addr is determined by the //! socket's address family. The addrlen argument is a value-result //! argument: it should initially contain the size of the structure //! pointed to by addr, on return it will contain the actual //! length (in bytes) of the address returned. //! //! @sa socket ; bind ; listen // //***************************************************************************** INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen) { INT32 ret; UINT8 *ptr, *args; tBsdReturnParams tAcceptReturnArguments; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, sd); // Initiate a HCI command hci_command_send(HCI_CMND_ACCEPT, ptr, SOCKET_ACCEPT_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments); // need specify return parameters!!! memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN); *addrlen = ASIC_ADDR_LEN; CC3000_EXPORT(errno) = tAcceptReturnArguments.iStatus; ret = CC3000_EXPORT(errno); // if succeeded, iStatus = new socket descriptor. otherwise - error number if(M_IS_VALID_SD(ret)) { set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); } else { set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); } return(ret); } //***************************************************************************** // //! bind //! //! @param[in] sd socket descriptor (handle) //! @param[out] addr specifies the destination address. On this version //! only AF_INET is supported. //! @param[out] addrlen contains the size of the structure pointed to by addr. //! //! @return On success, zero is returned. On error, -1 is returned. //! //! @brief assign a name to a socket //! This function gives the socket the local address addr. //! addr is addrlen bytes long. Traditionally, this is called when a //! socket is created with socket, it exists in a name space (address //! family) but has no name assigned. //! It is necessary to assign a local address before a SOCK_STREAM //! socket may receive connections. //! //! @sa socket ; accept ; listen // //***************************************************************************** INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen) { INT32 ret; UINT8 *ptr, *args; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); addrlen = ASIC_ADDR_LEN; // Fill in temporary command buffer args = UINT32_TO_STREAM(args, sd); args = UINT32_TO_STREAM(args, 0x00000008); args = UINT32_TO_STREAM(args, addrlen); ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen); // Initiate a HCI command hci_command_send(HCI_CMND_BIND, ptr, SOCKET_BIND_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_CMND_BIND, &ret); CC3000_EXPORT(errno) = ret; return(ret); } //***************************************************************************** // //! listen //! //! @param[in] sd socket descriptor (handle) //! @param[in] backlog specifies the listen queue depth. On this version //! backlog is not supported. //! @return On success, zero is returned. On error, -1 is returned. //! //! @brief listen for connections on a socket //! The willingness to accept incoming connections and a queue //! limit for incoming connections are specified with listen(), //! and then the connections are accepted with accept. //! The listen() call applies only to sockets of type SOCK_STREAM //! The backlog parameter defines the maximum length the queue of //! pending connections may grow to. //! //! @sa socket ; accept ; bind //! //! @note On this version, backlog is not supported // //***************************************************************************** INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog) { INT32 ret; UINT8 *ptr, *args; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, sd); args = UINT32_TO_STREAM(args, backlog); // Initiate a HCI command hci_command_send(HCI_CMND_LISTEN, ptr, SOCKET_LISTEN_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret); CC3000_EXPORT(errno) = ret; return(ret); } //***************************************************************************** // //! gethostbyname //! //! @param[in] hostname host name //! @param[in] usNameLen name length //! @param[out] out_ip_addr This parameter is filled in with host IP address. //! In case that host name is not resolved, //! out_ip_addr is zero. //! @return On success, positive is returned. On error, negative is returned //! //! @brief Get host IP by name. Obtain the IP Address of machine on network, //! by its name. //! //! @note On this version, only blocking mode is supported. Also note that //! the function requires DNS server to be configured prior to its usage. // //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, UINT32* out_ip_addr) { tBsdGethostbynameParams ret; UINT8 *ptr, *args; CC3000_EXPORT(errno) = EFAIL; if (usNameLen > HOSTNAME_MAX_LENGTH) { return CC3000_EXPORT(errno); } ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, 8); args = UINT32_TO_STREAM(args, usNameLen); ARRAY_TO_STREAM(args, hostname, usNameLen); // Initiate a HCI command hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN + usNameLen - 1); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret); CC3000_EXPORT(errno) = ret.retVal; (*((INT32*)out_ip_addr)) = ret.outputAddress; return CC3000_EXPORT(errno); } #endif //***************************************************************************** // //! connect //! //! @param[in] sd socket descriptor (handle) //! @param[in] addr specifies the destination addr. On this version //! only AF_INET is supported. //! @param[out] addrlen contains the size of the structure pointed to by addr //! @return On success, zero is returned. On error, -1 is returned //! //! @brief initiate a connection on a socket //! Function connects the socket referred to by the socket descriptor //! sd, to the address specified by addr. The addrlen argument //! specifies the size of addr. The format of the address in addr is //! determined by the address space of the socket. If it is of type //! SOCK_DGRAM, this call specifies the peer with which the socket is //! to be associated; this address is that to which datagrams are to be //! sent, and the only address from which datagrams are to be received. //! If the socket is of type SOCK_STREAM, this call attempts to make a //! connection to another socket. The other socket is specified by //! address, which is an address in the communications space of the //! socket. Note that the function implements only blocking behavior //! thus the caller will be waiting either for the connection //! establishment or for the connection establishment failure. //! //! @sa socket // //***************************************************************************** INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen) { INT32 ret; UINT8 *ptr, *args; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); addrlen = 8; // Fill in temporary command buffer args = UINT32_TO_STREAM(args, sd); args = UINT32_TO_STREAM(args, 0x00000008); args = UINT32_TO_STREAM(args, addrlen); ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen); // Initiate a HCI command hci_command_send(HCI_CMND_CONNECT, ptr, SOCKET_CONNECT_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret); CC3000_EXPORT(errno) = ret; return((INT32)ret); } //***************************************************************************** // //! select //! //! @param[in] nfds the highest-numbered file descriptor in any of the //! three sets, plus 1. //! @param[out] writesds socket descriptors list for write monitoring //! @param[out] readsds socket descriptors list for read monitoring //! @param[out] exceptsds socket descriptors list for exception monitoring //! @param[in] timeout is an upper bound on the amount of time elapsed //! before select() returns. Null means infinity //! timeout. The minimum timeout is 5 milliseconds, //! less than 5 milliseconds will be set //! automatically to 5 milliseconds. //! @return On success, select() returns the number of file descriptors //! contained in the three returned descriptor sets (that is, the //! total number of bits that are set in readfds, writefds, //! exceptfds) which may be zero if the timeout expires before //! anything interesting happens. //! On error, -1 is returned. //! *readsds - return the sockets on which Read request will //! return without delay with valid data. //! *writesds - return the sockets on which Write request //! will return without delay. //! *exceptsds - return the sockets which closed recently. //! //! @brief Monitor socket activity //! Select allow a program to monitor multiple file descriptors, //! waiting until one or more of the file descriptors become //! "ready" for some class of I/O operation //! //! @Note If the timeout value set to less than 5ms it will automatically set //! to 5ms to prevent overload of the system //! //! @sa socket // //***************************************************************************** INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, struct cc3000_timeval *timeout) { UINT8 *ptr, *args; tBsdSelectRecvParams tParams; UINT32 is_blocking; if( timeout == NULL) { is_blocking = 1; /* blocking , infinity timeout */ } else { is_blocking = 0; /* no blocking, timeout */ } // Fill in HCI packet structure ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, nfds); args = UINT32_TO_STREAM(args, 0x00000014); args = UINT32_TO_STREAM(args, 0x00000014); args = UINT32_TO_STREAM(args, 0x00000014); args = UINT32_TO_STREAM(args, 0x00000014); args = UINT32_TO_STREAM(args, is_blocking); args = UINT32_TO_STREAM(args, ((readsds) ? *(UINT32*)readsds : 0)); args = UINT32_TO_STREAM(args, ((writesds) ? *(UINT32*)writesds : 0)); args = UINT32_TO_STREAM(args, ((exceptsds) ? *(UINT32*)exceptsds : 0)); if (timeout) { if ( 0 == timeout->tv_sec && timeout->tv_usec < SELECT_TIMEOUT_MIN_MICRO_SECONDS) { timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS; } args = UINT32_TO_STREAM(args, timeout->tv_sec); args = UINT32_TO_STREAM(args, timeout->tv_usec); } // Initiate a HCI command hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams); // Update actually read FD if (tParams.iStatus >= 0) { if (readsds) { memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd)); } if (writesds) { memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); } if (exceptsds) { memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); } return(tParams.iStatus); } else { CC3000_EXPORT(errno) = tParams.iStatus; return(-1); } } //***************************************************************************** // //! setsockopt //! //! @param[in] sd socket handle //! @param[in] level defines the protocol level for this option //! @param[in] optname defines the option name to Interrogate //! @param[in] optval specifies a value for the option //! @param[in] optlen specifies the length of the option value //! @return On success, zero is returned. On error, -1 is returned //! //! @brief set socket options //! This function manipulate the options associated with a socket. //! Options may exist at multiple protocol levels; they are always //! present at the uppermost socket level. //! When manipulating socket options the level at which the option //! resides and the name of the option must be specified. //! To manipulate options at the socket level, level is specified as //! SOL_SOCKET. To manipulate options at any other level the protocol //! number of the appropriate protocol controlling the option is //! supplied. For example, to indicate that an option is to be //! interpreted by the TCP protocol, level should be set to the //! protocol number of TCP; //! The parameters optval and optlen are used to access optval - //! use for setsockopt(). For getsockopt() they identify a buffer //! in which the value for the requested option(s) are to //! be returned. For getsockopt(), optlen is a value-result //! parameter, initially containing the size of the buffer //! pointed to by option_value, and modified on return to //! indicate the actual size of the value returned. If no option //! value is to be supplied or returned, option_value may be NULL. //! //! @Note On this version the following two socket options are enabled: //! The only protocol level supported in this version //! is SOL_SOCKET (level). //! 1. SOCKOPT_RECV_TIMEOUT (optname) //! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout //! in milliseconds. //! In that case optval should be pointer to UINT32. //! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on //! or off. //! In that case optval should be SOCK_ON or SOCK_OFF (optval). //! //! @sa getsockopt // //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval, socklen_t optlen) { INT32 ret; UINT8 *ptr, *args; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, sd); args = UINT32_TO_STREAM(args, level); args = UINT32_TO_STREAM(args, optname); args = UINT32_TO_STREAM(args, 0x00000008); args = UINT32_TO_STREAM(args, optlen); ARRAY_TO_STREAM(args, ((UINT8 *)optval), optlen); // Initiate a HCI command hci_command_send(HCI_CMND_SETSOCKOPT, ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret); if (ret >= 0) { return (0); } else { CC3000_EXPORT(errno) = ret; return ret; } } #endif //***************************************************************************** // //! getsockopt //! //! @param[in] sd socket handle //! @param[in] level defines the protocol level for this option //! @param[in] optname defines the option name to Interrogate //! @param[out] optval specifies a value for the option //! @param[out] optlen specifies the length of the option value //! @return On success, zero is returned. On error, -1 is returned //! //! @brief set socket options //! This function manipulate the options associated with a socket. //! Options may exist at multiple protocol levels; they are always //! present at the uppermost socket level. //! When manipulating socket options the level at which the option //! resides and the name of the option must be specified. //! To manipulate options at the socket level, level is specified as //! SOL_SOCKET. To manipulate options at any other level the protocol //! number of the appropriate protocol controlling the option is //! supplied. For example, to indicate that an option is to be //! interpreted by the TCP protocol, level should be set to the //! protocol number of TCP; //! The parameters optval and optlen are used to access optval - //! use for setsockopt(). For getsockopt() they identify a buffer //! in which the value for the requested option(s) are to //! be returned. For getsockopt(), optlen is a value-result //! parameter, initially containing the size of the buffer //! pointed to by option_value, and modified on return to //! indicate the actual size of the value returned. If no option //! value is to be supplied or returned, option_value may be NULL. //! //! @Note On this version the following two socket options are enabled: //! The only protocol level supported in this version //! is SOL_SOCKET (level). //! 1. SOCKOPT_RECV_TIMEOUT (optname) //! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout //! in milliseconds. //! In that case optval should be pointer to UINT32. //! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on //! or off. //! In that case optval should be SOCK_ON or SOCK_OFF (optval). //! //! @sa setsockopt // //***************************************************************************** INT16 CC3000_EXPORT(getsockopt) (INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen) { UINT8 *ptr, *args; tBsdGetSockOptReturnParams tRetParams; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, sd); args = UINT32_TO_STREAM(args, level); args = UINT32_TO_STREAM(args, optname); // Initiate a HCI command hci_command_send(HCI_CMND_GETSOCKOPT, ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams); if (((INT8)tRetParams.iStatus) >= 0) { *optlen = 4; memcpy(optval, tRetParams.ucOptValue, 4); return (0); } else { CC3000_EXPORT(errno) = tRetParams.iStatus; return CC3000_EXPORT(errno); } } //***************************************************************************** // //! simple_link_recv //! //! @param sd socket handle //! @param buf read buffer //! @param len buffer length //! @param flags indicates blocking or non-blocking operation //! @param from pointer to an address structure indicating source address //! @param fromlen source address structure size //! //! @return Return the number of bytes received, or -1 if an error //! occurred //! //! @brief Read data from socket //! Return the length of the message on successful completion. //! If a message is too long to fit in the supplied buffer, //! excess bytes may be discarded depending on the type of //! socket the message is received from // //***************************************************************************** static INT16 simple_link_recv(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, socklen_t *fromlen, INT32 opcode) { UINT8 *ptr, *args; tBsdReadReturnParams tSocketReadEvent; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, sd); args = UINT32_TO_STREAM(args, len); args = UINT32_TO_STREAM(args, flags); // Generate the read command, and wait for the hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(opcode, &tSocketReadEvent); // In case the number of bytes is more then zero - read data if (tSocketReadEvent.iNumberOfBytes > 0) { // Wait for the data in a synchronous way. Here we assume that the bug is // big enough to store also parameters of receive from too.... SimpleLinkWaitData(buf, (UINT8 *)from, (UINT8 *)fromlen); } CC3000_EXPORT(errno) = tSocketReadEvent.iNumberOfBytes; return(tSocketReadEvent.iNumberOfBytes); } //***************************************************************************** // //! recv //! //! @param[in] sd socket handle //! @param[out] buf Points to the buffer where the message should be stored //! @param[in] len Specifies the length in bytes of the buffer pointed to //! by the buffer argument. //! @param[in] flags Specifies the type of message reception. //! On this version, this parameter is not supported. //! //! @return Return the number of bytes received, or -1 if an error //! occurred //! //! @brief function receives a message from a connection-mode socket //! //! @sa recvfrom //! //! @Note On this version, only blocking mode is supported. // //***************************************************************************** INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags) { return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); } //***************************************************************************** // //! recvfrom //! //! @param[in] sd socket handle //! @param[out] buf Points to the buffer where the message should be stored //! @param[in] len Specifies the length in bytes of the buffer pointed to //! by the buffer argument. //! @param[in] flags Specifies the type of message reception. //! On this version, this parameter is not supported. //! @param[in] from pointer to an address structure indicating the source //! address: sockaddr. On this version only AF_INET is //! supported. //! @param[in] fromlen source address tructure size //! //! @return Return the number of bytes received, or -1 if an error //! occurred //! //! @brief read data from socket //! function receives a message from a connection-mode or //! connectionless-mode socket. Note that raw sockets are not //! supported. //! //! @sa recv //! //! @Note On this version, only blocking mode is supported. // //***************************************************************************** INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, socklen_t *fromlen) { return(simple_link_recv(sd, buf, len, flags, from, fromlen, HCI_CMND_RECVFROM)); } //***************************************************************************** // //! simple_link_send //! //! @param sd socket handle //! @param buf write buffer //! @param len buffer length //! @param flags On this version, this parameter is not supported //! @param to pointer to an address structure indicating destination //! address //! @param tolen destination address structure size //! //! @return Return the number of bytes transmitted, or -1 if an error //! occurred, or -2 in case there are no free buffers available //! (only when SEND_NON_BLOCKING is enabled) //! //! @brief This function is used to transmit a message to another //! socket // //***************************************************************************** static INT16 simple_link_send(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to, INT32 tolen, INT32 opcode) { UINT8 uArgSize=0, addrlen; UINT8 *ptr, *pDataPtr=0, *args; UINT32 addr_offset=0; INT16 res; tBsdReadReturnParams tSocketSendEvent; // Check the bsd_arguments if (0 != (res = HostFlowControlConsumeBuff(sd))) { return res; } //Update the number of sent packets tSLInformation.NumberOfSentPackets++; // Allocate a buffer and construct a packet and send it over spi ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_DATA); // Update the offset of data and parameters according to the command switch(opcode) { case HCI_CMND_SENDTO: { addr_offset = len + sizeof(len) + sizeof(len); addrlen = 8; uArgSize = SOCKET_SENDTO_PARAMS_LEN; pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN; break; } case HCI_CMND_SEND: { tolen = 0; to = NULL; uArgSize = HCI_CMND_SEND_ARG_LENGTH; pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH; break; } default: { break; } } // Fill in temporary command buffer args = UINT32_TO_STREAM(args, sd); args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd)); args = UINT32_TO_STREAM(args, len); args = UINT32_TO_STREAM(args, flags); if (opcode == HCI_CMND_SENDTO) { args = UINT32_TO_STREAM(args, addr_offset); args = UINT32_TO_STREAM(args, addrlen); } // Copy the data received from user into the TX Buffer ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)buf), len); // In case we are using SendTo, copy the to parameters if (opcode == HCI_CMND_SENDTO) { ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)to), tolen); } // Initiate a HCI command hci_data_send(opcode, ptr, uArgSize, len,(UINT8*)to, tolen); if (opcode == HCI_CMND_SENDTO) SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent); else SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent); return (len); } //***************************************************************************** // //! send //! //! @param sd socket handle //! @param buf Points to a buffer containing the message to be sent //! @param len message size in bytes //! @param flags On this version, this parameter is not supported //! //! @return Return the number of bytes transmitted, or -1 if an //! error occurred //! //! @brief Write data to TCP socket //! This function is used to transmit a message to another //! socket. //! //! @Note On this version, only blocking mode is supported. //! //! @sa sendto // //***************************************************************************** INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags) { return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); } //***************************************************************************** // //! sendto //! //! @param sd socket handle //! @param buf Points to a buffer containing the message to be sent //! @param len message size in bytes //! @param flags On this version, this parameter is not supported //! @param to pointer to an address structure indicating the destination //! address: sockaddr. On this version only AF_INET is //! supported. //! @param tolen destination address structure size //! //! @return Return the number of bytes transmitted, or -1 if an //! error occurred //! //! @brief Write data to TCP socket //! This function is used to transmit a message to another //! socket. //! //! @Note On this version, only blocking mode is supported. //! //! @sa send // //***************************************************************************** INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to, socklen_t tolen) { return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); } //***************************************************************************** // //! mdnsAdvertiser //! //! @param[in] mdnsEnabled flag to enable/disable the mDNS feature //! @param[in] deviceServiceName Service name as part of the published //! canonical domain name //! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars //! //! //! @return On success, zero is returned, return SOC_ERROR if socket was not //! opened successfully, or if an error occurred. //! //! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. // //***************************************************************************** INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength) { INT8 ret; UINT8 *pTxBuffer, *pArgs; if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) { return EFAIL; } pTxBuffer = tSLInformation.pucTxCommandBuffer; pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); // Fill in HCI packet structure pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled); pArgs = UINT32_TO_STREAM(pArgs, 8); pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength); ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength); // Initiate a HCI command hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret); return ret; } //***************************************************************************** // //! getmssvalue //! //! @param[in] sd socket descriptor //! //! @return On success, returns the MSS value of a TCP connection //! //! @brief Returns the MSS value of a TCP connection according to the socket descriptor // //***************************************************************************** UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd) { UINT8 *ptr, *args; UINT16 ret; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, sd); // Initiate a HCI command hci_command_send(HCI_CMND_GETMSSVALUE, ptr, SOCKET_GET_MSS_VALUE_PARAMS_LEN); // Since we are in blocking state - wait for event complete SimpleLinkWaitEvent(HCI_EVNT_GETMSSVALUE, &ret); return ret; } micropython-1.12/drivers/cc3000/src/wlan.c000066400000000000000000001151271357706137100202730ustar00rootroot00000000000000/***************************************************************************** * * wlan.c - CC3000 Host Driver Implementation. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ //***************************************************************************** // //! \addtogroup wlan_api //! @{ // //***************************************************************************** #include #include "wlan.h" #include "hci.h" #include "ccspi.h" #include "socket.h" #include "nvmem.h" #include "security.h" #include "evnt_handler.h" volatile sSimplLinkInformation tSLInformation; #define SMART_CONFIG_PROFILE_SIZE 67 // 67 = 32 (max ssid) + 32 (max key) + 1 (SSID length) + 1 (security type) + 1 (key length) #ifndef CC3000_UNENCRYPTED_SMART_CONFIG UINT8 key[AES128_KEY_SIZE]; UINT8 profileArray[SMART_CONFIG_PROFILE_SIZE]; #endif //CC3000_UNENCRYPTED_SMART_CONFIG /* patches type */ #define PATCHES_HOST_TYPE_WLAN_DRIVER 0x01 #define PATCHES_HOST_TYPE_WLAN_FW 0x02 #define PATCHES_HOST_TYPE_BOOTLOADER 0x03 #define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE (16) #define SL_SIMPLE_CONFIG_PREFIX_LENGTH (3) #define ETH_ALEN (6) #define MAXIMAL_SSID_LENGTH (32) #define SL_PATCHES_REQUEST_DEFAULT (0) #define SL_PATCHES_REQUEST_FORCE_HOST (1) #define SL_PATCHES_REQUEST_FORCE_NONE (2) #define WLAN_SEC_UNSEC (0) #define WLAN_SEC_WEP (1) #define WLAN_SEC_WPA (2) #define WLAN_SEC_WPA2 (3) #define WLAN_SL_INIT_START_PARAMS_LEN (1) #define WLAN_PATCH_PARAMS_LENGTH (8) #define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN (12) #define WLAN_DEL_PROFILE_PARAMS_LEN (4) #define WLAN_SET_MASK_PARAMS_LEN (4) #define WLAN_SET_SCAN_PARAMS_LEN (100) #define WLAN_GET_SCAN_RESULTS_PARAMS_LEN (4) #define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN (24) #define WLAN_ADD_PROFILE_WEP_PARAM_LEN (36) #define WLAN_ADD_PROFILE_WPA_PARAM_LEN (44) #define WLAN_CONNECT_PARAM_LEN (29) #define WLAN_SMART_CONFIG_START_PARAMS_LEN (4) //***************************************************************************** // //! SimpleLink_Init_Start //! //! @param usPatchesAvailableAtHost flag to indicate if patches available //! from host or from EEPROM. Due to the //! fact the patches are burn to the EEPROM //! using the patch programmer utility, the //! patches will be available from the EEPROM //! and not from the host. //! //! @return none //! //! @brief Send HCI_CMND_SIMPLE_LINK_START to CC3000 // //***************************************************************************** static void SimpleLink_Init_Start(UINT16 usPatchesAvailableAtHost) { UINT8 *ptr; UINT8 *args; ptr = tSLInformation.pucTxCommandBuffer; args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_NONE : SL_PATCHES_REQUEST_DEFAULT)); // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000 hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN); SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0); } //***************************************************************************** // //! wlan_init //! //! @param sWlanCB Asynchronous events callback. //! 0 no event call back. //! -call back parameters: //! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, //! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, //! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, //! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, //! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR //! HCI_EVNT_WLAN_KEEPALIVE keepalive. //! 2) data: pointer to extra data that received by the event //! (NULL no data). //! 3) length: data length. //! -Events with extra data: //! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, //! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes //! for DNS server. //! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, //! 4 bytes Packets received, 4 bytes Min round time, //! 4 bytes Max round time and 4 bytes for Avg round time. //! //! @param sFWPatches 0 no patch or pointer to FW patches //! @param sDriverPatches 0 no patch or pointer to driver patches //! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches //! @param sReadWlanInterruptPin init callback. the callback read wlan //! interrupt status. //! @param sWlanInterruptEnable init callback. the callback enable wlan //! interrupt. //! @param sWlanInterruptDisable init callback. the callback disable wlan //! interrupt. //! @param sWriteWlanPin init callback. the callback write value //! to device pin. //! //! @return none //! //! @sa wlan_set_event_mask , wlan_start , wlan_stop //! //! @brief Initialize wlan driver //! //! @warning This function must be called before ANY other wlan driver function // //***************************************************************************** void wlan_init( tWlanCB sWlanCB, tFWPatches sFWPatches, tDriverPatches sDriverPatches, tBootLoaderPatches sBootLoaderPatches, tWlanReadInteruptPin sReadWlanInterruptPin, tWlanInterruptEnable sWlanInterruptEnable, tWlanInterruptDisable sWlanInterruptDisable, tWriteWlanPin sWriteWlanPin) { tSLInformation.sFWPatches = sFWPatches; tSLInformation.sDriverPatches = sDriverPatches; tSLInformation.sBootLoaderPatches = sBootLoaderPatches; // init io callback tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin; tSLInformation.WlanInterruptEnable = sWlanInterruptEnable; tSLInformation.WlanInterruptDisable = sWlanInterruptDisable; tSLInformation.WriteWlanPin = sWriteWlanPin; //init asynchronous events callback tSLInformation.sWlanCB= sWlanCB; // By default TX Complete events are routed to host too tSLInformation.InformHostOnTxComplete = 1; } //***************************************************************************** // //! SpiReceiveHandler //! //! @param pvBuffer - pointer to the received data buffer //! The function triggers Received event/data processing //! //! @param Pointer to the received data //! @return none //! //! @brief The function triggers Received event/data processing. It is //! called from the SPI library to receive the data // //***************************************************************************** void SpiReceiveHandler(void *pvBuffer) { tSLInformation.usEventOrDataReceived = 1; tSLInformation.pucReceivedData = (UINT8 *)pvBuffer; hci_unsolicited_event_handler(); } //***************************************************************************** // //! wlan_start //! //! @param usPatchesAvailableAtHost - flag to indicate if patches available //! from host or from EEPROM. Due to the //! fact the patches are burn to the EEPROM //! using the patch programmer utility, the //! patches will be available from the EEPROM //! and not from the host. //! //! @return none //! //! @brief Start WLAN device. This function asserts the enable pin of //! the device (WLAN_EN), starting the HW initialization process. //! The function blocked until device Initialization is completed. //! Function also configure patches (FW, driver or bootloader) //! and calls appropriate device callbacks. //! //! @Note Prior calling the function wlan_init shall be called. //! @Warning This function must be called after wlan_init and before any //! other wlan API //! @sa wlan_init , wlan_stop //! // //***************************************************************************** #define TIMEOUT (500000) int wlan_start(UINT16 usPatchesAvailableAtHost) { UINT32 ulSpiIRQState; UINT32 wlan_timeout; tSLInformation.NumberOfSentPackets = 0; tSLInformation.NumberOfReleasedPackets = 0; tSLInformation.usRxEventOpcode = 0; tSLInformation.usNumberOfFreeBuffers = 0; tSLInformation.usSlBufferLength = 0; tSLInformation.usBufferSize = 0; tSLInformation.usRxDataPending = 0; tSLInformation.slTransmitDataError = 0; tSLInformation.usEventOrDataReceived = 0; tSLInformation.pucReceivedData = 0; // Allocate the memory for the RX/TX data transactions tSLInformation.pucTxCommandBuffer = (UINT8 *)wlan_tx_buffer; // init spi SpiOpen(SpiReceiveHandler); // Check the IRQ line ulSpiIRQState = tSLInformation.ReadWlanInterruptPin(); // Chip enable: toggle WLAN EN line tSLInformation.WriteWlanPin( WLAN_ENABLE ); wlan_timeout = TIMEOUT; if (ulSpiIRQState) { // wait till the IRQ line goes low while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout) { } } else { // wait till the IRQ line goes high and than low while(tSLInformation.ReadWlanInterruptPin() == 0 && --wlan_timeout) { } if (wlan_timeout == 0) { return -1; } wlan_timeout = TIMEOUT; while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout) { } } if (wlan_timeout ==0) { return -1; } SimpleLink_Init_Start(usPatchesAvailableAtHost); // Read Buffer's size and finish hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0); SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0); return 0; } //***************************************************************************** // //! wlan_stop //! //! @param none //! //! @return none //! //! @brief Stop WLAN device by putting it into reset state. //! //! @sa wlan_start // //***************************************************************************** void wlan_stop(void) { // Chip disable tSLInformation.WriteWlanPin( WLAN_DISABLE ); // Wait till IRQ line goes high... while(tSLInformation.ReadWlanInterruptPin() == 0) { } // Free the used by WLAN Driver memory if (tSLInformation.pucTxCommandBuffer) { tSLInformation.pucTxCommandBuffer = 0; } SpiClose(); } //***************************************************************************** // //! wlan_connect //! //! @param sec_type security options: //! WLAN_SEC_UNSEC, //! WLAN_SEC_WEP (ASCII support only), //! WLAN_SEC_WPA or WLAN_SEC_WPA2 //! @param ssid up to 32 bytes and is ASCII SSID of the AP //! @param ssid_len length of the SSID //! @param bssid 6 bytes specified the AP bssid //! @param key up to 32 bytes specified the AP security key //! @param key_len key length //! //! @return On success, zero is returned. On error, negative is returned. //! Note that even though a zero is returned on success to trigger //! connection operation, it does not mean that CCC3000 is already //! connected. An asynchronous "Connected" event is generated when //! actual association process finishes and CC3000 is connected to //! the AP. If DHCP is set, An asynchronous "DHCP" event is //! generated when DHCP process is finish. //! //! //! @brief Connect to AP //! @warning Please Note that when connection to AP configured with security //! type WEP, please confirm that the key is set as ASCII and not //! as HEX. //! @sa wlan_disconnect // //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len, UINT8 *bssid, UINT8 *key, INT32 key_len) { INT32 ret; UINT8 *ptr; UINT8 *args; UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in command buffer args = UINT32_TO_STREAM(args, 0x0000001c); args = UINT32_TO_STREAM(args, ssid_len); args = UINT32_TO_STREAM(args, ulSecType); args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); args = UINT32_TO_STREAM(args, key_len); args = UINT16_TO_STREAM(args, 0); // padding shall be zeroed if(bssid) { ARRAY_TO_STREAM(args, bssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } ARRAY_TO_STREAM(args, ssid, ssid_len); if(key_len && key) { ARRAY_TO_STREAM(args, key, key_len); } // Initiate a HCI command hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + ssid_len + key_len - 1); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); CC3000_EXPORT(errno) = ret; return(ret); } #else INT32 wlan_connect(CHAR *ssid, INT32 ssid_len) { INT32 ret; UINT8 *ptr; UINT8 *args; UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in command buffer args = UINT32_TO_STREAM(args, 0x0000001c); args = UINT32_TO_STREAM(args, ssid_len); args = UINT32_TO_STREAM(args, 0); args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); args = UINT32_TO_STREAM(args, 0); args = UINT16_TO_STREAM(args, 0); // padding shall be zeroed ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); ARRAY_TO_STREAM(args, ssid, ssid_len); // Initiate a HCI command hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + ssid_len - 1); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); CC3000_EXPORT(errno) = ret; return(ret); } #endif //***************************************************************************** // //! wlan_disconnect //! //! @return 0 disconnected done, other CC3000 already disconnected //! //! @brief Disconnect connection from AP. //! //! @sa wlan_connect // //***************************************************************************** INT32 wlan_disconnect() { INT32 ret; UINT8 *ptr; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret); CC3000_EXPORT(errno) = ret; return(ret); } //***************************************************************************** // //! wlan_ioctl_set_connection_policy //! //! @param should_connect_to_open_ap enable(1), disable(0) connect to any //! available AP. This parameter corresponds to the configuration of //! item # 3 in the brief description. //! @param should_use_fast_connect enable(1), disable(0). if enabled, tries //! to connect to the last connected AP. This parameter corresponds //! to the configuration of item # 1 in the brief description. //! @param auto_start enable(1), disable(0) auto connect //! after reset and periodically reconnect if needed. This //! configuration configures option 2 in the above description. //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief When auto is enabled, the device tries to connect according //! the following policy: //! 1) If fast connect is enabled and last connection is valid, //! the device will try to connect to it without the scanning //! procedure (fast). The last connection will be marked as //! invalid, due to adding/removing profile. //! 2) If profile exists, the device will try to connect it //! (Up to seven profiles). //! 3) If fast and profiles are not found, and open mode is //! enabled, the device will try to connect to any AP. //! * Note that the policy settings are stored in the CC3000 NVMEM. //! //! @sa wlan_add_profile , wlan_ioctl_del_profile // //***************************************************************************** INT32 wlan_ioctl_set_connection_policy(UINT32 should_connect_to_open_ap, UINT32 ulShouldUseFastConnect, UINT32 ulUseProfiles) { INT32 ret; UINT8 *ptr; UINT8 *args; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, should_connect_to_open_ap); args = UINT32_TO_STREAM(args, ulShouldUseFastConnect); args = UINT32_TO_STREAM(args, ulUseProfiles); // Initiate a HCI command hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret); return(ret); } //***************************************************************************** // //! wlan_add_profile //! //! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 //! @param ucSsid ssid SSID up to 32 bytes //! @param ulSsidLen ssid length //! @param ucBssid bssid 6 bytes //! @param ulPriority ulPriority profile priority. Lowest priority:0. //! Important Note: Smartconfig process (in unencrypted mode) //! stores the profile internally with priority 1, so changing //! priorities when adding new profiles should be done with extra care //! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security //! @param ulGroupCipher_TxKeyIndex key index //! @param ulKeyMgmt KEY management //! @param ucPf_OrKey security key //! @param ulPassPhraseLen security key length for WPA\WPA2 //! //! @return On success, index (1-7) of the stored profile is returned. //! On error, -1 is returned. //! //! @brief When auto start is enabled, the device connects to //! station from the profiles table. Up to 7 profiles are supported. //! If several profiles configured the device choose the highest //! priority profile, within each priority group, device will choose //! profile based on security policy, signal strength, etc //! parameters. All the profiles are stored in CC3000 NVMEM. //! //! @sa wlan_ioctl_del_profile // //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 wlan_add_profile(UINT32 ulSecType, UINT8* ucSsid, UINT32 ulSsidLen, UINT8 *ucBssid, UINT32 ulPriority, UINT32 ulPairwiseCipher_Or_TxKeyLen, UINT32 ulGroupCipher_TxKeyIndex, UINT32 ulKeyMgmt, UINT8* ucPf_OrKey, UINT32 ulPassPhraseLen) { UINT16 arg_len=0; INT32 ret; UINT8 *ptr; INT32 i = 0; UINT8 *args; UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); args = UINT32_TO_STREAM(args, ulSecType); // Setup arguments in accordance with the security type switch (ulSecType) { //OPEN case WLAN_SEC_UNSEC: { args = UINT32_TO_STREAM(args, 0x00000014); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if(ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen; } break; //WEP case WLAN_SEC_WEP: { args = UINT32_TO_STREAM(args, 0x00000020); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if(ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen); args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); for(i = 0; i < 4; i++) { UINT8 *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen]; ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen); } arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen + ulPairwiseCipher_Or_TxKeyLen * 4; } break; //WPA //WPA2 case WLAN_SEC_WPA: case WLAN_SEC_WPA2: { args = UINT32_TO_STREAM(args, 0x00000028); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if(ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); args = UINT32_TO_STREAM(args, ulKeyMgmt); args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen); args = UINT32_TO_STREAM(args, ulPassPhraseLen); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen); arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen; } break; } // Initiate a HCI command hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, ptr, arg_len); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); return(ret); } #else INT32 wlan_add_profile(UINT32 ulSecType, UINT8* ucSsid, UINT32 ulSsidLen, UINT8 *ucBssid, UINT32 ulPriority, UINT32 ulPairwiseCipher_Or_TxKeyLen, UINT32 ulGroupCipher_TxKeyIndex, UINT32 ulKeyMgmt, UINT8* ucPf_OrKey, UINT32 ulPassPhraseLen) { return -1; } #endif //***************************************************************************** // //! wlan_ioctl_del_profile //! //! @param index number of profile to delete //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Delete WLAN profile //! //! @Note In order to delete all stored profile, set index to 255. //! //! @sa wlan_add_profile // //***************************************************************************** INT32 wlan_ioctl_del_profile(UINT32 ulIndex) { INT32 ret; UINT8 *ptr; UINT8 *args; ptr = tSLInformation.pucTxCommandBuffer; args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, ulIndex); ret = EFAIL; // Initiate a HCI command hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, ptr, WLAN_DEL_PROFILE_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret); return(ret); } //***************************************************************************** // //! wlan_ioctl_get_scan_results //! //! @param[in] scan_timeout parameter not supported //! @param[out] ucResults scan results (_wlan_full_scan_results_args_t) //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Gets entry from scan result table. //! The scan results are returned one by one, and each entry //! represents a single AP found in the area. The following is a //! format of the scan result: //! - 4 Bytes: number of networks found //! - 4 Bytes: The status of the scan: 0 - aged results, //! 1 - results valid, 2 - no results //! - 42 bytes: Result entry, where the bytes are arranged as follows: //! //! - 1 bit isValid - is result valid or not //! - 7 bits rssi - RSSI value; //! - 2 bits: securityMode - security mode of the AP: //! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 //! - 6 bits: SSID name length //! - 2 bytes: the time at which the entry has entered into //! scans result table //! - 32 bytes: SSID name //! - 6 bytes: BSSID //! //! @Note scan_timeout, is not supported on this version. //! //! @sa wlan_ioctl_set_scan_params // //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout, UINT8 *ucResults) { UINT8 *ptr; UINT8 *args; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, ulScanTimeout); // Initiate a HCI command hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults); return(0); } #endif //***************************************************************************** // //! wlan_ioctl_set_scan_params //! //! @param uiEnable - start/stop application scan: //! 1 = start scan with default interval value of 10 min. //! in order to set a different scan interval value apply the value //! in milliseconds. minimum 1 second. 0=stop). Wlan reset //! (wlan_stop() wlan_start()) is needed when changing scan interval //! value. Saved: No //! @param uiMinDwellTime minimum dwell time value to be used for each //! channel, in milliseconds. Saved: yes //! Recommended Value: 100 (Default: 20) //! @param uiMaxDwellTime maximum dwell time value to be used for each //! channel, in milliseconds. Saved: yes //! Recommended Value: 100 (Default: 30) //! @param uiNumOfProbeRequests max probe request between dwell time. //! Saved: yes. Recommended Value: 5 (Default:2) //! @param uiChannelMask bitwise, up to 13 channels (0x1fff). //! Saved: yes. Default: 0x7ff //! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) //! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0) //! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) //! @param aiIntervalList pointer to array with 16 entries (16 channels) //! each entry (UINT32) holds timeout between periodic scan //! (connection scan) - in millisecond. Saved: yes. Default 2000ms. //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief start and stop scan procedure. Set scan parameters. //! //! @Note uiDefaultTxPower, is not supported on this version. //! //! @sa wlan_ioctl_get_scan_results // //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 uiMinDwellTime, UINT32 uiMaxDwellTime, UINT32 uiNumOfProbeRequests, UINT32 uiChannelMask,INT32 iRSSIThreshold, UINT32 uiSNRThreshold, UINT32 uiDefaultTxPower, UINT32 *aiIntervalList) { UINT32 uiRes; UINT8 *ptr; UINT8 *args; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); // Fill in temporary command buffer args = UINT32_TO_STREAM(args, 36); args = UINT32_TO_STREAM(args, uiEnable); args = UINT32_TO_STREAM(args, uiMinDwellTime); args = UINT32_TO_STREAM(args, uiMaxDwellTime); args = UINT32_TO_STREAM(args, uiNumOfProbeRequests); args = UINT32_TO_STREAM(args, uiChannelMask); args = UINT32_TO_STREAM(args, iRSSIThreshold); args = UINT32_TO_STREAM(args, uiSNRThreshold); args = UINT32_TO_STREAM(args, uiDefaultTxPower); ARRAY_TO_STREAM(args, aiIntervalList, sizeof(UINT32) * SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE); // Initiate a HCI command hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, ptr, WLAN_SET_SCAN_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes); return(uiRes); } #endif //***************************************************************************** // //! wlan_set_event_mask //! //! @param mask mask option: //! HCI_EVNT_WLAN_UNSOL_CONNECT connect event //! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event //! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done //! HCI_EVNT_WLAN_UNSOL_INIT init done //! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report //! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report //! HCI_EVNT_WLAN_KEEPALIVE keepalive //! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission //! Saved: no. //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Mask event according to bit mask. In case that event is //! masked (1), the device will not send the masked event to host. // //***************************************************************************** INT32 wlan_set_event_mask(UINT32 ulMask) { INT32 ret; UINT8 *ptr; UINT8 *args; if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE) { tSLInformation.InformHostOnTxComplete = 0; // Since an event is a virtual event - i.e. it is not coming from CC3000 // there is no need to send anything to the device if it was an only event if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE) { return 0; } ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE; ulMask |= HCI_EVNT_WLAN_UNSOL_BASE; } else { tSLInformation.InformHostOnTxComplete = 1; } ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, ulMask); // Initiate a HCI command hci_command_send(HCI_CMND_EVENT_MASK, ptr, WLAN_SET_MASK_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret); return(ret); } //***************************************************************************** // //! wlan_ioctl_statusget //! //! @param none //! //! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, //! STATUS_CONNECTING or WLAN_STATUS_CONNECTED //! //! @brief get wlan status: disconnected, scanning, connecting or connected // //***************************************************************************** #ifndef CC3000_TINY_DRIVER INT32 wlan_ioctl_statusget(void) { INT32 ret; UINT8 *ptr; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET, ptr, 0); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret); return(ret); } #endif //***************************************************************************** // //! wlan_smart_config_start //! //! @param algoEncryptedFlag indicates whether the information is encrypted //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Start to acquire device profile. The device acquire its own //! profile, if profile message is found. The acquired AP information //! is stored in CC3000 EEPROM only in case AES128 encryption is used. //! In case AES128 encryption is not used, a profile is created by //! CC3000 internally. //! //! @Note An asynchronous event - Smart Config Done will be generated as soon //! as the process finishes successfully. //! //! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop // //***************************************************************************** INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag) { INT32 ret; UINT8 *ptr; UINT8 *args; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); // Fill in HCI packet structure args = UINT32_TO_STREAM(args, algoEncryptedFlag); ret = EFAIL; hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr, WLAN_SMART_CONFIG_START_PARAMS_LEN); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret); return(ret); } //***************************************************************************** // //! wlan_smart_config_stop //! //! @param algoEncryptedFlag indicates whether the information is encrypted //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Stop the acquire profile procedure //! //! @sa wlan_smart_config_start , wlan_smart_config_set_prefix // //***************************************************************************** INT32 wlan_smart_config_stop(void) { INT32 ret; UINT8 *ptr; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret); return(ret); } //***************************************************************************** // //! wlan_smart_config_set_prefix //! //! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config. //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief Configure station ssid prefix. The prefix is used internally //! in CC3000. It should always be TTT. //! //! @Note The prefix is stored in CC3000 NVMEM //! //! @sa wlan_smart_config_start , wlan_smart_config_stop // //***************************************************************************** INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix) { INT32 ret; UINT8 *ptr; UINT8 *args; ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); if (cNewPrefix == NULL) return ret; else // with the new Smart Config, prefix must be TTT { *cNewPrefix = 'T'; *(cNewPrefix + 1) = 'T'; *(cNewPrefix + 2) = 'T'; } ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH); hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr, SL_SIMPLE_CONFIG_PREFIX_LENGTH); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret); return(ret); } //***************************************************************************** // //! wlan_smart_config_process //! //! @param none //! //! @return On success, zero is returned. On error, -1 is returned //! //! @brief process the acquired data and store it as a profile. The acquired //! AP information is stored in CC3000 EEPROM encrypted. //! The encrypted data is decrypted and stored as a profile. //! behavior is as defined by connection policy. // //***************************************************************************** #ifndef CC3000_UNENCRYPTED_SMART_CONFIG INT32 wlan_smart_config_process() { INT32 returnValue; UINT32 ssidLen, keyLen; UINT8 *decKeyPtr; UINT8 *ssidPtr; // read the key from EEPROM - fileID 12 returnValue = aes_read_key(key); if (returnValue != 0) return returnValue; // read the received data from fileID #13 and parse it according to the followings: // 1) SSID LEN - not encrypted // 2) SSID - not encrypted // 3) KEY LEN - not encrypted. always 32 bytes long // 4) Security type - not encrypted // 5) KEY - encrypted together with true key length as the first byte in KEY // to elaborate, there are two corner cases: // 1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length // 2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31 returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray); if (returnValue != 0) return returnValue; ssidPtr = &profileArray[1]; ssidLen = profileArray[0]; decKeyPtr = &profileArray[profileArray[0] + 3]; aes_decrypt(decKeyPtr, key); if (profileArray[profileArray[0] + 1] > 16) aes_decrypt((UINT8 *)(decKeyPtr + 16), key); if (*(UINT8 *)(decKeyPtr +31) != 0) { if (*decKeyPtr == 31) { keyLen = 31; decKeyPtr++; } else { keyLen = 32; } } else { keyLen = *decKeyPtr; decKeyPtr++; } // add a profile switch (profileArray[profileArray[0] + 2]) { case WLAN_SEC_UNSEC://None { returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type ssidPtr, // SSID ssidLen, // SSID length NULL, // BSSID 1, // Priority 0, 0, 0, 0, 0); break; } case WLAN_SEC_WEP://WEP { returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type ssidPtr, // SSID ssidLen, // SSID length NULL, // BSSID 1, // Priority keyLen, // KEY length 0, // KEY index 0, decKeyPtr, // KEY 0); break; } case WLAN_SEC_WPA://WPA case WLAN_SEC_WPA2://WPA2 { returnValue = wlan_add_profile(WLAN_SEC_WPA2, // security type ssidPtr, ssidLen, NULL, // BSSID 1, // Priority 0x18, // PairwiseCipher 0x1e, // GroupCipher 2, // KEY management decKeyPtr, // KEY keyLen); // KEY length break; } } return returnValue; } #endif //CC3000_UNENCRYPTED_SMART_CONFIG //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/drivers/cc3100/000077500000000000000000000000001357706137100163715ustar00rootroot00000000000000micropython-1.12/drivers/cc3100/inc/000077500000000000000000000000001357706137100171425ustar00rootroot00000000000000micropython-1.12/drivers/cc3100/inc/device.h000066400000000000000000000650751357706137100205670ustar00rootroot00000000000000/* * device.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #ifndef __DEVICE_H__ #define __DEVICE_H__ #ifdef __cplusplus extern "C" { #endif /*! \addtogroup device @{ */ /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ /* SL internal Error codes */ /* Receive this error in case there are no resources to issue the command If possible, increase the number of MAX_CUNCURENT_ACTIONS (result in memory increase) If not, try again later */ #define SL_POOL_IS_EMPTY (-2000) /* Receive this error in case a given length for RX buffer was too small. Receive payload was bigger than the given buffer size. Therefore, payload is cut according to receive size Recommend to increase buffer size */ #define SL_ESMALLBUF (-2001) /* Receive this error in case zero length is supplied to a "get" API Recommend to supply length according to requested information (view options defines for help) */ #define SL_EZEROLEN (-2002) /* User supplied invalid parameter */ #define SL_INVALPARAM (-2003) /* Failed to open interface */ #define SL_BAD_INTERFACE (-2004) /* End of SL internal Error codes */ /*****************************************************************************/ /* Errors returned from the general error async event */ /*****************************************************************************/ /* Send types */ typedef enum { SL_ERR_SENDER_HEALTH_MON, SL_ERR_SENDER_CLI_UART, SL_ERR_SENDER_SUPPLICANT, SL_ERR_SENDER_NETWORK_STACK, SL_ERR_SENDER_WLAN_DRV_IF, SL_ERR_SENDER_WILINK, SL_ERR_SENDER_INIT_APP, SL_ERR_SENDER_NETX, SL_ERR_SENDER_HOST_APD, SL_ERR_SENDER_MDNS, SL_ERR_SENDER_HTTP_SERVER, SL_ERR_SENDER_DHCP_SERVER, SL_ERR_SENDER_DHCP_CLIENT, SL_ERR_DISPATCHER, SL_ERR_NUM_SENDER_LAST=0xFF }SlErrorSender_e; /* Error codes */ #define SL_ERROR_STATIC_ADDR_SUBNET_ERROR (-60) /* network stack error*/ #define SL_ERROR_ILLEGAL_CHANNEL (-61) /* supplicant error */ #define SL_ERROR_SUPPLICANT_ERROR (-72) /* init error code */ #define SL_ERROR_HOSTAPD_INIT_FAIL (-73) /* init error code */ #define SL_ERROR_HOSTAPD_INIT_IF_FAIL (-74) /* init error code */ #define SL_ERROR_WLAN_DRV_INIT_FAIL (-75) /* init error code */ #define SL_ERROR_WLAN_DRV_START_FAIL (-76) /* wlan start error */ #define SL_ERROR_FS_FILE_TABLE_LOAD_FAILED (-77) /* init file system failed */ #define SL_ERROR_PREFERRED_NETWORKS_FILE_LOAD_FAILED (-78) /* init file system failed */ #define SL_ERROR_HOSTAPD_BSSID_VALIDATION_ERROR (-79) /* Ap configurations BSSID error */ #define SL_ERROR_HOSTAPD_FAILED_TO_SETUP_INTERFACE (-80) /* Ap configurations interface error */ #define SL_ERROR_MDNS_ENABLE_FAIL (-81) /* mDNS enable failed */ #define SL_ERROR_HTTP_SERVER_ENABLE_FAILED (-82) /* HTTP server enable failed */ #define SL_ERROR_DHCP_SERVER_ENABLE_FAILED (-83) /* DHCP server enable failed */ #define SL_ERROR_PREFERRED_NETWORK_LIST_FULL (-93) /* supplicant error */ #define SL_ERROR_PREFERRED_NETWORKS_FILE_WRITE_FAILED (-94) /* supplicant error */ #define SL_ERROR_DHCP_CLIENT_RENEW_FAILED (-100) /* DHCP client error */ /* WLAN Connection management status */ #define SL_ERROR_CON_MGMT_STATUS_UNSPECIFIED (-102) #define SL_ERROR_CON_MGMT_STATUS_AUTH_REJECT (-103) #define SL_ERROR_CON_MGMT_STATUS_ASSOC_REJECT (-104) #define SL_ERROR_CON_MGMT_STATUS_SECURITY_FAILURE (-105) #define SL_ERROR_CON_MGMT_STATUS_AP_DEAUTHENTICATE (-106) #define SL_ERROR_CON_MGMT_STATUS_AP_DISASSOCIATE (-107) #define SL_ERROR_CON_MGMT_STATUS_ROAMING_TRIGGER (-108) #define SL_ERROR_CON_MGMT_STATUS_DISCONNECT_DURING_CONNECT (-109) #define SL_ERROR_CON_MGMT_STATUS_SG_RESELECT (-110) #define SL_ERROR_CON_MGMT_STATUS_ROC_FAILURE (-111) #define SL_ERROR_CON_MGMT_STATUS_MIC_FAILURE (-112) /* end of WLAN connection management error statuses */ #define SL_ERROR_WAKELOCK_ERROR_PREFIX (-115) /* Wake lock expired */ #define SL_ERROR_LENGTH_ERROR_PREFIX (-116) /* Uart header length error */ #define SL_ERROR_MDNS_CREATE_FAIL (-121) /* mDNS create failed */ #define SL_ERROR_GENERAL_ERROR (-127) #define SL_DEVICE_GENERAL_CONFIGURATION (1) #define SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME (11) #define SL_DEVICE_GENERAL_VERSION (12) #define SL_DEVICE_STATUS (2) /* Declare the different event group classifications The SimpleLink device send asynchronous events. Each event has a group classification according to its nature. */ /* SL_EVENT_CLASS_WLAN connection user events */ #define SL_WLAN_CONNECT_EVENT (1) #define SL_WLAN_DISCONNECT_EVENT (2) /* WLAN Smart Config user events */ #define SL_WLAN_SMART_CONFIG_COMPLETE_EVENT (3) #define SL_WLAN_SMART_CONFIG_STOP_EVENT (4) /* WLAN AP user events */ #define SL_WLAN_STA_CONNECTED_EVENT (5) #define SL_WLAN_STA_DISCONNECTED_EVENT (6) /* WLAN P2P user events */ #define SL_WLAN_P2P_DEV_FOUND_EVENT (7) #define SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT (8) #define SL_WLAN_CONNECTION_FAILED_EVENT (9) /* SL_EVENT_CLASS_DEVICE user events */ #define SL_DEVICE_FATAL_ERROR_EVENT (1) #define SL_DEVICE_ABORT_ERROR_EVENT (2) /* SL_EVENT_CLASS_BSD user events */ #define SL_SOCKET_TX_FAILED_EVENT (1) #define SL_SOCKET_ASYNC_EVENT (2) /* SL_EVENT_CLASS_NETAPP user events */ #define SL_NETAPP_IPV4_IPACQUIRED_EVENT (1) #define SL_NETAPP_IPV6_IPACQUIRED_EVENT (2) #define SL_NETAPP_IP_LEASED_EVENT (3) #define SL_NETAPP_IP_RELEASED_EVENT (4) /* Server Events */ #define SL_NETAPP_HTTPGETTOKENVALUE_EVENT (1) #define SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT (2) /* Declare the different event group classifications for sl_DevGet for getting status indications */ /* Events list to mask/unmask*/ #define SL_EVENT_CLASS_GLOBAL (0) #define SL_EVENT_CLASS_DEVICE (1) #define SL_EVENT_CLASS_WLAN (2) #define SL_EVENT_CLASS_BSD (3) #define SL_EVENT_CLASS_NETAPP (4) #define SL_EVENT_CLASS_NETCFG (5) #define SL_EVENT_CLASS_FS (6) /****************** DEVICE CLASS status ****************/ #define EVENT_DROPPED_DEVICE_ASYNC_GENERAL_ERROR (0x00000001L) #define STATUS_DEVICE_SMART_CONFIG_ACTIVE (0x80000000L) /****************** WLAN CLASS status ****************/ #define EVENT_DROPPED_WLAN_WLANASYNCONNECTEDRESPONSE (0x00000001L) #define EVENT_DROPPED_WLAN_WLANASYNCDISCONNECTEDRESPONSE (0x00000002L) #define EVENT_DROPPED_WLAN_STA_CONNECTED (0x00000004L) #define EVENT_DROPPED_WLAN_STA_DISCONNECTED (0x00000008L) #define STATUS_WLAN_STA_CONNECTED (0x80000000L) /****************** NETAPP CLASS status ****************/ #define EVENT_DROPPED_NETAPP_IPACQUIRED (0x00000001L) #define EVENT_DROPPED_NETAPP_IPACQUIRED_V6 (0x00000002L) #define EVENT_DROPPED_NETAPP_IP_LEASED (0x00000004L) #define EVENT_DROPPED_NETAPP_IP_RELEASED (0x00000008L) /****************** BSD CLASS status ****************/ #define EVENT_DROPPED_SOCKET_TXFAILEDASYNCRESPONSE (0x00000001L) /****************** FS CLASS ****************/ /*****************************************************************************/ /* Structure/Enum declarations */ /*****************************************************************************/ #define ROLE_UNKNOWN_ERR (-1) #ifdef SL_IF_TYPE_UART typedef struct { _u32 BaudRate; _u8 FlowControlEnable; _u8 CommPort; } SlUartIfParams_t; #endif typedef struct { _u32 ChipId; _u32 FwVersion[4]; _u8 PhyVersion[4]; }_SlPartialVersion; typedef struct { _SlPartialVersion ChipFwAndPhyVersion; _u32 NwpVersion[4]; _u16 RomVersion; _u16 Padding; }SlVersionFull; typedef struct { _u32 AbortType; _u32 AbortData; }sl_DeviceReportAbort; typedef struct { _i8 status; SlErrorSender_e sender; }sl_DeviceReport; typedef union { sl_DeviceReport deviceEvent; sl_DeviceReportAbort deviceReport; } _SlDeviceEventData_u; typedef struct { _u32 Event; _SlDeviceEventData_u EventData; } SlDeviceEvent_t; typedef struct { /* time */ _u32 sl_tm_sec; _u32 sl_tm_min; _u32 sl_tm_hour; /* date */ _u32 sl_tm_day; /* 1-31 */ _u32 sl_tm_mon; /* 1-12 */ _u32 sl_tm_year; /* YYYY 4 digits */ _u32 sl_tm_week_day; /* not required */ _u32 sl_tm_year_day; /* not required */ _u32 reserved[3]; }SlDateTime_t; /******************************************************************************/ /* Type declarations */ /******************************************************************************/ typedef void (*P_INIT_CALLBACK)(_u32 Status); /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ /*! \brief Start the SimpleLink device This function initialize the communication interface, set the enable pin of the device, and call to the init complete callback. \param[in] pIfHdl Opened Interface Object. In case the interface must be opened outside the SimpleLink Driver, the user might give the handler to be used in \n any access of the communication interface with the device (UART/SPI). \n The SimpleLink driver will open an interface port only if this parameter is null! \n \param[in] pDevName The name of the device to open. Could be used when the pIfHdl is null, to transfer information to the open interface function \n This pointer could be used to pass additional information to sl_IfOpen in case it is required (e.g. UART com port name) \param[in] pInitCallBack Pointer to function that would be called on completion of the initialization process.\n If this parameter is NULL the function is blocked until the device initialization is completed, otherwise the function returns immediately. \return Returns the current active role (STA/AP/P2P) or an error code: - ROLE_STA, ROLE_AP, ROLE_P2P in case of success, otherwise in failure one of the following is return: - ROLE_STA_ERR (Failure to load MAC/PHY in STA role) - ROLE_AP_ERR (Failure to load MAC/PHY in AP role) - ROLE_P2P_ERR (Failure to load MAC/PHY in P2P role) \sa sl_Stop \note belongs to \ref basic_api \warning This function must be called before any other SimpleLink API is used, or after sl_Stop is called for reinit the device \par Example: \code An example for open interface without callback routine. The interface name and handler are handled by the sl_IfOpen routine: if( sl_Start(NULL, NULL, NULL) < 0 ) { LOG("Error opening interface to device\n"); } \endcode */ #if _SL_INCLUDE_FUNC(sl_Start) _i16 sl_Start(const void* pIfHdl, _i8* pDevName, const P_INIT_CALLBACK pInitCallBack); #endif /*! \brief Stop the SimpleLink device This function clears the enable pin of the device, closes the communication \n interface and invokes the stop complete callback \param[in] timeout Stop timeout in msec. Should be used to give the device time to finish \n any transmission/reception that is not completed when the function was called. \n Additional options: - 0 Enter to hibernate immediately \n - 0xFFFF Host waits for device's response before \n hibernating, without timeout protection \n - 0 < Timeout[msec] < 0xFFFF Host waits for device's response before \n hibernating, with a defined timeout protection \n This timeout defines the max time to wait. The NWP \n response can be sent earlier than this timeout. \return On success, zero is returned. On error, -1 is returned \sa sl_Start \note This API will shutdown the device and invoke the "i/f close" function regardless \n if it was opened implicitly or explicitly. \n It is up to the platform interface library to properly handle interface close \n routine \n belongs to \ref basic_api \n \warning */ #if _SL_INCLUDE_FUNC(sl_Stop) _i16 sl_Stop(const _u16 timeout); #endif /*! \brief Internal function for setting device configurations \return On success, zero is returned. On error, -1 is returned \param[in] DeviceSetId configuration id \param[in] Option configurations option \param[in] ConfigLen configurations len \param[in] pValues configurations values \sa \note \warning \par Examples: \code Setting device time and date example: SlDateTime_t dateTime= {0}; dateTime.sl_tm_day = (_u32)23; // Day of month (DD format) range 1-31 dateTime.sl_tm_mon = (_u32)6; // Month (MM format) in the range of 1-12 dateTime.sl_tm_year = (_u32)2014; // Year (YYYY format) dateTime.sl_tm_hour = (_u32)17; // Hours in the range of 0-23 dateTime.sl_tm_min = (_u32)55; // Minutes in the range of 0-59 dateTime.sl_tm_sec = (_u32)22; // Seconds in the range of 0-59 sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, sizeof(SlDateTime_t), (_u8 *)(&dateTime)); \endcode */ #if _SL_INCLUDE_FUNC(sl_DevSet) _i32 sl_DevSet(const _u8 DeviceSetId ,const _u8 Option,const _u8 ConfigLen,const _u8 *pValues); #endif /*! \brief Internal function for getting device configurations \return On success, zero is returned. On error, -1 is returned \param[in] DeviceGetId configuration id - example SL_DEVICE_STATUS \param[out] pOption Get configurations option, example for get status options - SL_EVENT_CLASS_GLOBAL - SL_EVENT_CLASS_DEVICE - SL_EVENT_CLASS_WLAN - SL_EVENT_CLASS_BSD - SL_EVENT_CLASS_NETAPP - SL_EVENT_CLASS_NETCFG - SL_EVENT_CLASS_FS \param[out] pConfigLen The length of the allocated memory as input, when the function complete, the value of this parameter would be the len that actually read from the device.\n If the device return length that is longer from the input value, the function will cut the end of the returned structure and will return SL_ESMALLBUF \param[out] pValues Get configurations values \sa \note \warning \par Examples: \code Example for getting WLAN class status: _u32 statusWlan; _u8 pConfigOpt; _u8 pConfigLen; pConfigOpt = SL_EVENT_CLASS_WLAN; pConfigLen = sizeof(_u32); sl_DevGet(SL_DEVICE_STATUS,&pConfigOpt,&pConfigLen,(_u8 *)(&statusWlan)); Example for getting version: SlVersionFull ver; pConfigLen = sizeof(ver); pConfigOpt = SL_DEVICE_GENERAL_VERSION; sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION,&pConfigOpt,&pConfigLen,(_u8 *)(&ver)); printf("CHIP %d\nMAC 31.%d.%d.%d.%d\nPHY %d.%d.%d.%d\nNWP %d.%d.%d.%d\nROM %d\nHOST %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.ChipId, ver.ChipFwAndPhyVersion.FwVersion[0],ver.ChipFwAndPhyVersion.FwVersion[1], ver.ChipFwAndPhyVersion.FwVersion[2],ver.ChipFwAndPhyVersion.FwVersion[3], ver.ChipFwAndPhyVersion.PhyVersion[0],ver.ChipFwAndPhyVersion.PhyVersion[1], ver.ChipFwAndPhyVersion.PhyVersion[2],ver.ChipFwAndPhyVersion.PhyVersion[3], ver.NwpVersion[0],ver.NwpVersion[1],ver.NwpVersion[2],ver.NwpVersion[3], ver.RomVersion, SL_MAJOR_VERSION_NUM,SL_MINOR_VERSION_NUM,SL_VERSION_NUM,SL_SUB_VERSION_NUM); \endcode \code Getting Device time and date example: SlDateTime_t dateTime = {0}; _i8 configLen = sizeof(SlDateTime_t); _i8 configOpt = SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME; sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION,&configOpt, &configLen,(_u8 *)(&dateTime)); printf("Day %d,Mon %d,Year %d,Hour %,Min %d,Sec %d\n",dateTime.sl_tm_day,dateTime.sl_tm_mon,dateTime.sl_tm_year dateTime.sl_tm_hour,dateTime.sl_tm_min,dateTime.sl_tm_sec); \endcode */ #if _SL_INCLUDE_FUNC(sl_DevGet) _i32 sl_DevGet(const _u8 DeviceGetId,_u8 *pOption,_u8 *pConfigLen, _u8 *pValues); #endif /*! \brief Set asynchronous event mask Mask asynchronous events from the device. Masked events do not generate asynchronous messages from the device. By default - all events are active \param[in] EventClass The classification groups that the mask is referred to. Need to be one of the following: - SL_EVENT_CLASS_GLOBAL - SL_EVENT_CLASS_DEVICE - SL_EVENT_CLASS_WLAN - SL_EVENT_CLASS_BSD - SL_EVENT_CLASS_NETAPP - SL_EVENT_CLASS_NETCFG - SL_EVENT_CLASS_FS \param[in] Mask Event Mask bitmap. Valid mask are (per group): - SL_EVENT_CLASS_WLAN user events - SL_WLAN_CONNECT_EVENT - SL_WLAN_DISCONNECT_EVENT - SL_EVENT_CLASS_DEVICE user events - SL_DEVICE_FATAL_ERROR_EVENT - SL_EVENT_CLASS_BSD user events - SL_SOCKET_TX_FAILED_EVENT - SL_SOCKET_ASYNC_EVENT - SL_EVENT_CLASS_NETAPP user events - SL_NETAPP_IPV4_IPACQUIRED_EVENT - SL_NETAPP_IPV6_IPACQUIRED_EVENT \return On success, zero is returned. On error, -1 is returned \sa sl_EventMaskGet \note belongs to \ref ext_api \warning \par Example: \code An example of masking connection/disconnection async events from WLAN class: sl_EventMaskSet(SL_EVENT_CLASS_WLAN, (SL_WLAN_CONNECT_EVENT | SL_WLAN_DISCONNECT_EVENT) ); \endcode */ #if _SL_INCLUDE_FUNC(sl_EventMaskSet) _i16 sl_EventMaskSet(const _u8 EventClass ,const _u32 Mask); #endif /*! \brief Get current event mask of the device return the events bit mask from the device. In case that event is masked, the device is not sending this event. \param[in] EventClass The classification groups that the mask is referred to. Need to be one of the following: - SL_EVENT_CLASS_GLOBAL - SL_EVENT_CLASS_DEVICE - SL_EVENT_CLASS_WLAN - SL_EVENT_CLASS_BSD - SL_EVENT_CLASS_NETAPP - SL_EVENT_CLASS_NETCFG - SL_EVENT_CLASS_FS \param[out] pMask Pointer to Mask bitmap where the value should be stored. Bitmasks are the same as in \ref sl_EventMaskSet \return On success, zero is returned. On error, -1 is returned \sa sl_EventMaskSet \note belongs to \ref ext_api \warning \par Example: \code An example of getting an event mask for WLAN class _u32 maskWlan; sl_StatusGet(SL_EVENT_CLASS_WLAN,&maskWlan); \endcode */ #if _SL_INCLUDE_FUNC(sl_EventMaskGet) _i16 sl_EventMaskGet(const _u8 EventClass,_u32 *pMask); #endif /*! \brief the simple link task entry \Param This function must be called from the main loop or from dedicated thread in the following cases: - Non-Os Platform - should be called from the mail loop - Multi Threaded Platform when the user does not implement the external spawn functions - should be called from dedicated thread allocated to the simplelink driver. In this mode the function never return. \return None \sa sl_Stop \note belongs to \ref basic_api \warning This function must be called from a thread that is start running before any call to other simple link API */ #if _SL_INCLUDE_FUNC(sl_Task) void sl_Task(void); #endif /*! \brief Setting the internal uart mode \param[in] pUartParams Pointer to the uart configuration parameter set: baudrate - up to 711 Kbps flow control - enable/disable comm port - the comm port number \return On success zero is returned, otherwise - Failed. \sa sl_Stop \note belongs to \ref basic_api \warning This function must consider the host uart capability */ #ifdef SL_IF_TYPE_UART #if _SL_INCLUDE_FUNC(sl_UartSetMode) _i16 sl_UartSetMode(const SlUartIfParams_t* pUartParams); #endif #endif /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __DEVICE_H__ */ micropython-1.12/drivers/cc3100/inc/driver.h000066400000000000000000000200721357706137100206070ustar00rootroot00000000000000/* * driver.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __DRIVER_INT_H__ #define __DRIVER_INT_H__ /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #ifndef CPU_FREQ_IN_MHZ #define CPU_FREQ_IN_MHZ (200) #endif #define USEC_DELAY (50) /*****************************************************************************/ /* Structure/Enum declarations */ /*****************************************************************************/ typedef struct { _SlOpcode_t Opcode; _SlArgSize_t TxDescLen; _SlArgSize_t RxDescLen; }_SlCmdCtrl_t; typedef struct { _u16 TxPayloadLen; _i16 RxPayloadLen; _i16 ActualRxPayloadLen; _u8 *pTxPayload; _u8 *pRxPayload; }_SlCmdExt_t; typedef struct _SlArgsData_t { _u8 *pArgs; _u8 *pData; } _SlArgsData_t; typedef struct _SlPoolObj_t { _SlSyncObj_t SyncObj; _u8 *pRespArgs; _u8 ActionID; _u8 AdditionalData; /* use for socketID and one bit which indicate supprt IPV6 or not (1=support, 0 otherwise) */ _u8 NextIndex; } _SlPoolObj_t; typedef enum { SOCKET_0, SOCKET_1, SOCKET_2, SOCKET_3, SOCKET_4, SOCKET_5, SOCKET_6, SOCKET_7, MAX_SOCKET_ENUM_IDX, #ifndef SL_TINY_EXT ACCEPT_ID = MAX_SOCKET_ENUM_IDX, CONNECT_ID, #else CONNECT_ID = MAX_SOCKET_ENUM_IDX, #endif #ifndef SL_TINY_EXT SELECT_ID, #endif GETHOSYBYNAME_ID, #ifndef SL_TINY_EXT GETHOSYBYSERVICE_ID, PING_ID, #endif START_STOP_ID, RECV_ID }_SlActionID_e; typedef struct _SlActionLookup_t { _u8 ActionID; _u16 ActionAsyncOpcode; _SlSpawnEntryFunc_t AsyncEventHandler; } _SlActionLookup_t; typedef struct { _u8 TxPoolCnt; _SlLockObj_t TxLockObj; _SlSyncObj_t TxSyncObj; }_SlFlowContCB_t; typedef enum { RECV_RESP_CLASS, CMD_RESP_CLASS, ASYNC_EVT_CLASS, DUMMY_MSG_CLASS }_SlRxMsgClass_e; typedef struct { _u8 *pAsyncBuf; /* place to write pointer to buffer with CmdResp's Header + Arguments */ _u8 ActionIndex; _SlSpawnEntryFunc_t AsyncEvtHandler; /* place to write pointer to AsyncEvent handler (calc-ed by Opcode) */ _SlRxMsgClass_e RxMsgClass; /* type of Rx message */ } AsyncExt_t; typedef _u8 _SlSd_t; typedef struct { _SlCmdCtrl_t *pCmdCtrl; _u8 *pTxRxDescBuff; _SlCmdExt_t *pCmdExt; AsyncExt_t AsyncExt; }_SlFunctionParams_t; typedef struct { _SlFd_t FD; _SlLockObj_t GlobalLockObj; _SlCommandHeader_t TempProtocolHeader; P_INIT_CALLBACK pInitCallback; _SlPoolObj_t ObjPool[MAX_CONCURRENT_ACTIONS]; _u8 FreePoolIdx; _u8 PendingPoolIdx; _u8 ActivePoolIdx; _u32 ActiveActionsBitmap; _SlLockObj_t ProtectionLockObj; _SlSyncObj_t CmdSyncObj; _u8 IsCmdRespWaited; _SlFlowContCB_t FlowContCB; _u8 TxSeqNum; _u8 RxDoneCnt; _u8 SocketNonBlocking; _u8 SocketTXFailure; /* for stack reduction the parameters are globals */ _SlFunctionParams_t FunctionParams; _u8 ActionIndex; }_SlDriverCb_t; extern _volatile _u8 RxIrqCnt; extern _SlDriverCb_t* g_pCB; extern P_SL_DEV_PING_CALLBACK pPingCallBackFunc; /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ extern void _SlDrvDriverCBInit(void); extern void _SlDrvDriverCBDeinit(void); extern void _SlDrvRxIrqHandler(void *pValue); extern _SlReturnVal_t _SlDrvCmdOp(_SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); extern _SlReturnVal_t _SlDrvCmdSend(_SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); extern _SlReturnVal_t _SlDrvDataReadOp(_SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); extern _SlReturnVal_t _SlDrvDataWriteOp(_SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); extern void _sl_HandleAsync_InitComplete(void *pVoidBuf); extern void _sl_HandleAsync_Connect(void *pVoidBuf); #ifndef SL_TINY_EXT extern _i16 _SlDrvBasicCmd(_SlOpcode_t Opcode); extern void _sl_HandleAsync_Accept(void *pVoidBuf); extern void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf); extern void _sl_HandleAsync_Select(void *pVoidBuf); #endif extern void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf); extern void _sl_HandleAsync_DnsGetHostByAddr(void *pVoidBuf); extern void _sl_HandleAsync_PingResponse(void *pVoidBuf); extern void _SlDrvNetAppEventHandler(void* pArgs); extern void _SlDrvDeviceEventHandler(void* pArgs); extern void _sl_HandleAsync_Stop(void *pVoidBuf); extern _u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID); extern void _SlDrvReleasePoolObj(_u8 pObj); extern _u16 _SlDrvAlignSize(_u16 msgLen); extern _u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID); extern void _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj); extern void _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj); extern void _SlDrvObjLock(_SlLockObj_t *pLockObj, _SlTime_t Timeout); extern void _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj); extern void _SlDrvProtectionObjLockWaitForever(); extern void _SlDrvObjUnLock(_SlLockObj_t *pLockObj); extern void _SlDrvProtectionObjUnLock(); extern void _SlDrvMemZero(void* Addr, _u16 size); extern void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt); #define _SL_PROTOCOL_ALIGN_SIZE(msgLen) (((msgLen)+3) & (~3)) #define _SL_IS_PROTOCOL_ALIGNED_SIZE(msgLen) (!((msgLen) & 3)) #define _SL_PROTOCOL_CALC_LEN(pCmdCtrl,pCmdExt) ((pCmdExt) ? \ (_SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen) + _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayloadLen)) : \ (_SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen))) #endif /* __DRIVER_INT_H__ */ micropython-1.12/drivers/cc3100/inc/flowcont.h000066400000000000000000000046361357706137100211570ustar00rootroot00000000000000/* * flowcont.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __FLOWCONT_H__ #define __FLOWCONT_H__ #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #define FLOW_CONT_MIN 1 /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ extern void _SlDrvFlowContInit(void); extern void _SlDrvFlowContDeinit(void); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __FLOWCONT_H__ */ micropython-1.12/drivers/cc3100/inc/fs.h000066400000000000000000000431401357706137100177250ustar00rootroot00000000000000/* * fs.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #ifndef __FS_H__ #define __FS_H__ #ifdef __cplusplus extern "C" { #endif /*! \addtogroup FileSystem @{ */ /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ /* FS error codes */ #define SL_FS_OK (0) #define SL_FS_ERR_EMPTY_SFLASH (-67) #define SL_FS_ERR_FILE_IS_NOT_SECURE_AND_SIGN (-66) #define SL_FS_ERASING_FLASH (-65) #define SL_FS_FILE_HAS_NOT_BEEN_CLOSE_CORRECTLY (-64) #define SL_FS_WRONG_SIGNATURE (-63) #define SL_FS_WRONG_SIGNATURE_OR_CERTIFIC_NAME_LENGTH (-62) #define SL_FS_NOT_16_ALIGNED (-61) #define SL_FS_CERT_CHAIN_ERROR (-60) #define SL_FS_FILE_NAME_EXIST (-59) #define SL_FS_SECURITY_BUF_ALREADY_ALLOC (-58) #define SL_FS_SECURE_FILE_MUST_BE_COMMIT (-57) #define SL_FS_ERR_INCORRECT_OFFSET_ALIGNMENT (-56) #define SL_FS_ERR_FAILED_READ_NVMEM_HEADER (-55) #define SL_FS_WRONG_FILE_NAME (-54) #define SL_FS_FILE_SYSTEM_IS_LOCKED (-53) #define SL_FS_SECURITY_ALLERT (-52) #define SL_FS_FILE_UNVALID_FILE_SIZE (-51) #define SL_FS_ERR_TOKEN_IS_NOT_VALID (-50) #define SL_FS_NO_DEVICE_IS_LOADED (-49) #define SL_FS_DATA_ADDRESS_SHOUD_BE_IN_DATA_RAM (-48) #define SL_FS_DATA_IS_NOT_ALIGNED (-47) #define SL_FS_ERR_OVERLAP_DETECTION_THRESHHOLD (-46) #define SL_FS_FILE_HAS_RESERVED_NV_INDEX (-45) #define SL_FS_ERR_MAX_FS_FILES_IS_LARGER (-44) #define SL_FS_ERR_MAX_FS_FILES_IS_SMALLER (-43) #define SL_FS_FILE_MAX_SIZE_EXCEEDED (-42) #define SL_FS_INVALID_BUFFER_FOR_READ (-41) #define SL_FS_INVALID_BUFFER_FOR_WRITE (-40) #define SL_FS_ERR_FILE_IMAGE_IS_CORRUPTED (-39) #define SL_FS_ERR_SIZE_OF_FILE_EXT_EXCEEDED (-38) #define SL_FS_WARNING_FILE_NAME_NOT_KEPT (-37) #define SL_FS_ERR_DEVICE_IS_NOT_FORMATTED (-36) #define SL_FS_ERR_FAILED_WRITE_NVMEM_HEADER (-35) #define SL_FS_ERR_NO_AVAILABLE_NV_INDEX (-34) #define SL_FS_ERR_FAILED_TO_ALLOCATE_MEM (-33) #define SL_FS_ERR_FAILED_TO_READ_INTEGRITY_HEADER_2 (-32) #define SL_FS_ERR_FAILED_TO_READ_INTEGRITY_HEADER_1 (-31) #define SL_FS_ERR_NO_AVAILABLE_BLOCKS (-30) #define SL_FS_ERR_FILE_MAX_SIZE_BIGGER_THAN_EXISTING_FILE (-29) #define SL_FS_ERR_FILE_EXISTS_ON_DIFFERENT_DEVICE_ID (-28) #define SL_FS_ERR_INVALID_ACCESS_TYPE (-27) #define SL_FS_ERR_FILE_ALREADY_EXISTS (-26) #define SL_FS_ERR_PROGRAM (-25) #define SL_FS_ERR_NO_ENTRIES_AVAILABLE (-24) #define SL_FS_ERR_FILE_ACCESS_IS_DIFFERENT (-23) #define SL_FS_ERR_BAD_FILE_MODE (-22) #define SL_FS_ERR_FAILED_READ_NVFILE (-21) #define SL_FS_ERR_FAILED_INIT_STORAGE (-20) #define SL_FS_ERR_CONTINUE_WRITE_MUST_BE_MOD_4 (-19) #define SL_FS_ERR_FAILED_LOAD_FILE (-18) #define SL_FS_ERR_INVALID_HANDLE (-17) #define SL_FS_ERR_FAILED_TO_WRITE (-16) #define SL_FS_ERR_OFFSET_OUT_OF_RANGE (-15) #define SL_FS_ERR_ALLOC (-14) #define SL_FS_ERR_READ_DATA_LENGTH (-13) #define SL_FS_ERR_INVALID_FILE_ID (-12) #define SL_FS_ERR_FILE_NOT_EXISTS (-11) #define SL_FS_ERR_EMPTY_ERROR (-10) #define SL_FS_ERR_INVALID_ARGS (-9) #define SL_FS_ERR_FAILED_TO_CREATE_FILE (-8) #define SL_FS_ERR_FS_ALREADY_LOADED (-7) #define SL_FS_ERR_UNKNOWN (-6) #define SL_FS_ERR_FAILED_TO_CREATE_LOCK_OBJ (-5) #define SL_FS_ERR_DEVICE_NOT_LOADED (-4) #define SL_FS_ERR_INVALID_MAGIC_NUM (-3) #define SL_FS_ERR_FAILED_TO_READ (-2) #define SL_FS_ERR_NOT_SUPPORTED (-1) /* end of error codes */ #define _FS_MODE_ACCESS_RESERVED_OFFSET (24) #define _FS_MODE_ACCESS_RESERVED_MASK (0xFF) #define _FS_MODE_ACCESS_FLAGS_OFFSET (16) #define _FS_MODE_ACCESS_FLAGS_MASK (0xFF) #define _FS_MODE_ACCESS_OFFSET (12) #define _FS_MODE_ACCESS_MASK (0xF) #define _FS_MODE_OPEN_SIZE_GRAN_OFFSET (8) #define _FS_MODE_OPEN_SIZE_GRAN_MASK (0xF) #define _FS_MODE_OPEN_SIZE_OFFSET (0) #define _FS_MODE_OPEN_SIZE_MASK (0xFF) #define MAX_MODE_SIZE (0xFF) #define _FS_MODE(Access, SizeGran, Size,Flags) (_u32)(((_u32)((Access) & _FS_MODE_ACCESS_MASK)<<_FS_MODE_ACCESS_OFFSET) | \ ((_u32)((SizeGran) & _FS_MODE_OPEN_SIZE_GRAN_MASK)<<_FS_MODE_OPEN_SIZE_GRAN_OFFSET) | \ ((_u32)((Size) & _FS_MODE_OPEN_SIZE_MASK)<<_FS_MODE_OPEN_SIZE_OFFSET) | \ ((_u32)((Flags) & _FS_MODE_ACCESS_FLAGS_MASK)<<_FS_MODE_ACCESS_FLAGS_OFFSET)) /* sl_FsOpen options */ /* Open for Read */ #define FS_MODE_OPEN_READ _FS_MODE(_FS_MODE_OPEN_READ,0,0,0) /* Open for Write (in case file exist) */ #define FS_MODE_OPEN_WRITE _FS_MODE(_FS_MODE_OPEN_WRITE,0,0,0) /* Open for Creating a new file */ #define FS_MODE_OPEN_CREATE(maxSizeInBytes,accessModeFlags) _sl_GetCreateFsMode(maxSizeInBytes,accessModeFlags) /*****************************************************************************/ /* Structure/Enum declarations */ /*****************************************************************************/ typedef struct { _u16 flags; _u32 FileLen; _u32 AllocatedLen; _u32 Token[4]; }SlFsFileInfo_t; typedef enum { _FS_MODE_OPEN_READ = 0, _FS_MODE_OPEN_WRITE, _FS_MODE_OPEN_CREATE, _FS_MODE_OPEN_WRITE_CREATE_IF_NOT_EXIST }SlFsFileOpenAccessType_e; typedef enum { _FS_FILE_OPEN_FLAG_COMMIT = 0x1, /* MIRROR - for fail safe */ _FS_FILE_OPEN_FLAG_SECURE = 0x2, /* SECURE */ _FS_FILE_OPEN_FLAG_NO_SIGNATURE_TEST = 0x4, /* Relevant to secure file only */ _FS_FILE_OPEN_FLAG_STATIC = 0x8, /* Relevant to secure file only */ _FS_FILE_OPEN_FLAG_VENDOR = 0x10, /* Relevant to secure file only */ _FS_FILE_PUBLIC_WRITE= 0x20, /* Relevant to secure file only, the file can be opened for write without Token */ _FS_FILE_PUBLIC_READ = 0x40 /* Relevant to secure file only, the file can be opened for read without Token */ }SlFileOpenFlags_e; typedef enum { _FS_MODE_SIZE_GRAN_256B = 0, /* MAX_SIZE = 64K */ _FS_MODE_SIZE_GRAN_1KB, /* MAX_SIZE = 256K */ _FS_MODE_SIZE_GRAN_4KB, /* MAX_SZIE = 1M */ _FS_MODE_SIZE_GRAN_16KB, /* MAX_SIZE = 4M */ _FS_MODE_SIZE_GRAN_64KB, /* MAX_SIZE = 16M */ _FS_MAX_MODE_SIZE_GRAN }_SlFsFileOpenMaxSizeGran_e; /*****************************************************************************/ /* Internal Function prototypes */ /*****************************************************************************/ _u32 _sl_GetCreateFsMode(_u32 maxSizeInBytes,_u32 accessFlags); /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ /*! \brief open file for read or write from/to storage device \param[in] pFileName File Name buffer pointer \param[in] AccessModeAndMaxSize Options: As described below \param[in] pToken Reserved for future use. Use NULL for this field \param[out] pFileHandle Pointing on the file and used for read and write commands to the file AccessModeAndMaxSize possible input \n FS_MODE_OPEN_READ - Read a file \n FS_MODE_OPEN_WRITE - Open for write for an existing file \n FS_MODE_OPEN_CREATE(maxSizeInBytes,accessModeFlags) - Open for creating a new file. Max file size is defined in bytes. \n For optimal FS size, use max size in 4K-512 bytes steps (e.g. 3584,7680,117760) \n Several access modes bits can be combined together from SlFileOpenFlags_e enum \return On success, zero is returned. On error, an error code is returned \sa sl_FsRead sl_FsWrite sl_FsClose \note belongs to \ref basic_api \warning \par Example: \code char* DeviceFileName = "MyFile.txt"; unsigned long MaxSize = 63 * 1024; //62.5K is max file size long DeviceFileHandle = -1; long RetVal; //negative retval is an error unsigned long Offset = 0; unsigned char InputBuffer[100]; // Create a file and write data. The file in this example is secured, without signature and with a fail safe commit RetVal = sl_FsOpen((unsigned char *)DeviceFileName, FS_MODE_OPEN_CREATE(MaxSize , _FS_FILE_OPEN_FLAG_NO_SIGNATURE_TEST | _FS_FILE_OPEN_FLAG_COMMIT ), NULL, &DeviceFileHandle); Offset = 0; //Preferred in secure file that the Offset and the length will be aligned to 16 bytes. RetVal = sl_FsWrite( DeviceFileHandle, Offset, (unsigned char *)"HelloWorld", strlen("HelloWorld")); RetVal = sl_FsClose(DeviceFileHandle, NULL, NULL , 0); // open the same file for read, using the Token we got from the creation procedure above RetVal = sl_FsOpen((unsigned char *)DeviceFileName, FS_MODE_OPEN_READ, NULL, &DeviceFileHandle); Offset = 0; RetVal = sl_FsRead( DeviceFileHandle, Offset, (unsigned char *)InputBuffer, strlen("HelloWorld")); RetVal = sl_FsClose(DeviceFileHandle, NULL, NULL , 0); \endcode */ #if _SL_INCLUDE_FUNC(sl_FsOpen) _i32 sl_FsOpen(const _u8 *pFileName,const _u32 AccessModeAndMaxSize,_u32 *pToken,_i32 *pFileHandle); #endif /*! \brief close file in storage device \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) \param[in] pCeritificateFileName Reserved for future use. Use NULL. \param[in] pSignature Reserved for future use. Use NULL. \param[in] SignatureLen Reserved for future use. Use 0. \return On success, zero is returned. On error, an error code is returned \sa sl_FsRead sl_FsWrite sl_FsOpen \note Call the fs_Close with signature = 'A' signature len = 1 for activating an abort action \warning \par Example: \code sl_FsClose(FileHandle,0,0,0); \endcode */ #if _SL_INCLUDE_FUNC(sl_FsClose) _i16 sl_FsClose(const _i32 FileHdl,const _u8* pCeritificateFileName,const _u8* pSignature,const _u32 SignatureLen); #endif /*! \brief Read block of data from a file in storage device \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) \param[in] Offset Offset to specific read block \param[out] pData Pointer for the received data \param[in] Len Length of the received data \return On success, returns the number of read bytes. On error, negative number is returned \sa sl_FsClose sl_FsWrite sl_FsOpen \note belongs to \ref basic_api \warning \par Example: \code Status = sl_FsRead(FileHandle, 0, &readBuff[0], readSize); \endcode */ #if _SL_INCLUDE_FUNC(sl_FsRead) _i32 sl_FsRead(const _i32 FileHdl,_u32 Offset ,_u8* pData,_u32 Len); #endif /*! \brief write block of data to a file in storage device \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) \param[in] Offset Offset to specific block to be written \param[in] pData Pointer the transmitted data to the storage device \param[in] Len Length of the transmitted data \return On success, returns the number of written bytes. On error, an error code is returned \sa \note belongs to \ref basic_api \warning \par Example: \code Status = sl_FsWrite(FileHandle, 0, &buff[0], readSize); \endcode */ #if _SL_INCLUDE_FUNC(sl_FsWrite) _i32 sl_FsWrite(const _i32 FileHdl,_u32 Offset,_u8* pData,_u32 Len); #endif /*! \brief get info on a file \param[in] pFileName File name \param[in] Token Reserved for future use. Use 0 \param[out] pFsFileInfo Returns the File's Information: flags,file size, allocated size and Tokens \return On success, zero is returned. On error, an error code is returned \sa sl_FsOpen \note belongs to \ref basic_api \warning \par Example: \code Status = sl_FsGetInfo("FileName.html",0,&FsFileInfo); \endcode */ #if _SL_INCLUDE_FUNC(sl_FsGetInfo) _i16 sl_FsGetInfo(const _u8 *pFileName,const _u32 Token,SlFsFileInfo_t* pFsFileInfo); #endif /*! \brief Delete specific file from a storage or all files from a storage (format) \param[in] pFileName File Name \param[in] Token Reserved for future use. Use 0 \return On success, zero is returned. On error, an error code is returned \sa \note belongs to \ref basic_api \warning \par Example: \code Status = sl_FsDel("FileName.html",0); \endcode */ #if _SL_INCLUDE_FUNC(sl_FsDel) _i16 sl_FsDel(const _u8 *pFileName,const _u32 Token); #endif /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __FS_H__ */ micropython-1.12/drivers/cc3100/inc/netapp.h000066400000000000000000001236411357706137100206110ustar00rootroot00000000000000/* * netapp.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #ifndef __NETAPP_H__ #define __NETAPP_H__ #ifdef __cplusplus extern "C" { #endif /*! \addtogroup netapp @{ */ /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ /*ERROR code*/ #define SL_ERROR_NETAPP_RX_BUFFER_LENGTH_ERROR (-230) /* Http Server interface */ #define MAX_INPUT_STRING (64) /* because of WPA */ #define MAX_AUTH_NAME_LEN (20) #define MAX_AUTH_PASSWORD_LEN (20) #define MAX_AUTH_REALM_LEN (20) #define MAX_DEVICE_URN_LEN (15+1) #define MAX_DOMAIN_NAME_LEN (24+1) #define MAX_ACTION_LEN (30) /* Important: in case the max len is changed, make sure the struct sl_NetAppHttpServerSendToken_t in protocol.h is padded correctly! */ #define MAX_TOKEN_NAME_LEN (20) #define MAX_TOKEN_VALUE_LEN MAX_INPUT_STRING #define NETAPP_MAX_SERVICE_TEXT_SIZE (256) #define NETAPP_MAX_SERVICE_NAME_SIZE (60) #define NETAPP_MAX_SERVICE_HOST_NAME_SIZE (64) /* Server Responses */ #define SL_NETAPP_RESPONSE_NONE (0) #define SL_NETAPP_HTTPSETTOKENVALUE (1) #define SL_NETAPP_FAMILY_MASK (0x80) /* mDNS types */ #define SL_NET_APP_MASK_IPP_TYPE_OF_SERVICE (0x00000001) #define SL_NET_APP_MASK_DEVICE_INFO_TYPE_OF_SERVICE (0x00000002) #define SL_NET_APP_MASK_HTTP_TYPE_OF_SERVICE (0x00000004) #define SL_NET_APP_MASK_HTTPS_TYPE_OF_SERVICE (0x00000008) #define SL_NET_APP_MASK_WORKSATION_TYPE_OF_SERVICE (0x00000010) #define SL_NET_APP_MASK_GUID_TYPE_OF_SERVICE (0x00000020) #define SL_NET_APP_MASK_H323_TYPE_OF_SERVICE (0x00000040) #define SL_NET_APP_MASK_NTP_TYPE_OF_SERVICE (0x00000080) #define SL_NET_APP_MASK_OBJECITVE_TYPE_OF_SERVICE (0x00000100) #define SL_NET_APP_MASK_RDP_TYPE_OF_SERVICE (0x00000200) #define SL_NET_APP_MASK_REMOTE_TYPE_OF_SERVICE (0x00000400) #define SL_NET_APP_MASK_RTSP_TYPE_OF_SERVICE (0x00000800) #define SL_NET_APP_MASK_SIP_TYPE_OF_SERVICE (0x00001000) #define SL_NET_APP_MASK_SMB_TYPE_OF_SERVICE (0x00002000) #define SL_NET_APP_MASK_SOAP_TYPE_OF_SERVICE (0x00004000) #define SL_NET_APP_MASK_SSH_TYPE_OF_SERVICE (0x00008000) #define SL_NET_APP_MASK_TELNET_TYPE_OF_SERVICE (0x00010000) #define SL_NET_APP_MASK_TFTP_TYPE_OF_SERVICE (0x00020000) #define SL_NET_APP_MASK_XMPP_CLIENT_TYPE_OF_SERVICE (0x00040000) #define SL_NET_APP_MASK_RAOP_TYPE_OF_SERVICE (0x00080000) #define SL_NET_APP_MASK_ALL_TYPE_OF_SERVICE (0xFFFFFFFF) /********************************************************************************************************/ /* sl_NetAppDnsGetHostByName error codes */ #define SL_NET_APP_DNS_QUERY_NO_RESPONSE (-159) /* DNS query failed, no response */ #define SL_NET_APP_DNS_NO_SERVER (-161) /* No DNS server was specified */ #define SL_NET_APP_DNS_PARAM_ERROR (-162) /* mDNS parameters error */ #define SL_NET_APP_DNS_QUERY_FAILED (-163) /* DNS query failed; no DNS server sent an 'answer' */ #define SL_NET_APP_DNS_INTERNAL_1 (-164) #define SL_NET_APP_DNS_INTERNAL_2 (-165) #define SL_NET_APP_DNS_MALFORMED_PACKET (-166) /* Improperly formed or corrupted DNS packet received */ #define SL_NET_APP_DNS_INTERNAL_3 (-167) #define SL_NET_APP_DNS_INTERNAL_4 (-168) #define SL_NET_APP_DNS_INTERNAL_5 (-169) #define SL_NET_APP_DNS_INTERNAL_6 (-170) #define SL_NET_APP_DNS_INTERNAL_7 (-171) #define SL_NET_APP_DNS_INTERNAL_8 (-172) #define SL_NET_APP_DNS_INTERNAL_9 (-173) #define SL_NET_APP_DNS_MISMATCHED_RESPONSE (-174) /* Server response type does not match the query request*/ #define SL_NET_APP_DNS_INTERNAL_10 (-175) #define SL_NET_APP_DNS_INTERNAL_11 (-176) #define SL_NET_APP_DNS_NO_ANSWER (-177) /* No response for one-shot query */ #define SL_NET_APP_DNS_NO_KNOWN_ANSWER (-178) /* No known answer for query */ #define SL_NET_APP_DNS_NAME_MISMATCH (-179) /* Illegal service name according to the RFC */ #define SL_NET_APP_DNS_NOT_STARTED (-180) /* mDNS is not running */ #define SL_NET_APP_DNS_HOST_NAME_ERROR (-181) /* Host name error. Host name format is not allowed according to RFC 1033,1034,1035, 6763 */ #define SL_NET_APP_DNS_NO_MORE_ENTRIES (-182) /* No more entries be found. */ #define SL_NET_APP_DNS_MAX_SERVICES_ERROR (-200) /* Maximum advertise services are already configured */ #define SL_NET_APP_DNS_IDENTICAL_SERVICES_ERROR (-201) /* Trying to register a service that is already exists */ #define SL_NET_APP_DNS_NOT_EXISTED_SERVICE_ERROR (-203) /* Trying to delete service that does not existed */ #define SL_NET_APP_DNS_ERROR_SERVICE_NAME_ERROR (-204) /* Illegal service name according to the RFC */ #define SL_NET_APP_DNS_RX_PACKET_ALLOCATION_ERROR (-205) /* Retry request */ #define SL_NET_APP_DNS_BUFFER_SIZE_ERROR (-206) /* List size buffer is bigger than internally allowed in the NWP */ #define SL_NET_APP_DNS_NET_APP_SET_ERROR (-207) /* Illegal length of one of the mDNS Set functions */ #define SL_NET_APP_DNS_GET_SERVICE_LIST_FLAG_ERROR (-208) #define SL_NET_APP_DNS_NO_CONFIGURATION_ERROR (-209) /* Set Dev name error codes (NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN) */ #define SL_ERROR_DEVICE_NAME_LEN_ERR (-117) #define SL_ERROR_DEVICE_NAME_INVALID (-118) /* Set domain name error codes (NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME) */ #define SL_ERROR_DOMAIN_NAME_LEN_ERR (-119) #define SL_ERROR_DOMAIN_NAME_INVALID (-120) /********************************************************************************************************/ /* NetApp application IDs */ #define SL_NET_APP_HTTP_SERVER_ID (1) #define SL_NET_APP_DHCP_SERVER_ID (2) #define SL_NET_APP_MDNS_ID (4) #define SL_NET_APP_DNS_SERVER_ID (8) #define SL_NET_APP_DEVICE_CONFIG_ID (16) /* NetApp application set/get options */ #define NETAPP_SET_DHCP_SRV_BASIC_OPT (0) /* HTTP server set/get options */ #define NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER (0) #define NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK (1) #define NETAPP_SET_GET_HTTP_OPT_AUTH_NAME (2) #define NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD (3) #define NETAPP_SET_GET_HTTP_OPT_AUTH_REALM (4) #define NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS (5) #define NETAPP_SET_GET_MDNS_CONT_QUERY_OPT (1) #define NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT (2) #define NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT (3) /* DNS server set/get options */ #define NETAPP_SET_GET_DNS_OPT_DOMAIN_NAME (0) /* Device Config set/get options */ #define NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN (0) #define NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME (1) /*****************************************************************************/ /* Structure/Enum declarations */ /*****************************************************************************/ typedef struct { _u32 PacketsSent; _u32 PacketsReceived; _u16 MinRoundTime; _u16 MaxRoundTime; _u16 AvgRoundTime; _u32 TestTime; }SlPingReport_t; typedef struct { _u32 PingIntervalTime; /* delay between pings, in milliseconds */ _u16 PingSize; /* ping packet size in bytes */ _u16 PingRequestTimeout; /* timeout time for every ping in milliseconds */ _u32 TotalNumberOfAttempts; /* max number of ping requests. 0 - forever */ _u32 Flags; /* flag - 0 report only when finished, 1 - return response for every ping, 2 - stop after 1 successful ping. */ _u32 Ip; /* IPv4 address or IPv6 first 4 bytes */ _u32 Ip1OrPaadding; _u32 Ip2OrPaadding; _u32 Ip3OrPaadding; }SlPingStartCommand_t; typedef struct _slHttpServerString_t { _u8 len; _u8 *data; } slHttpServerString_t; typedef struct _slHttpServerData_t { _u8 value_len; _u8 name_len; _u8 *token_value; _u8 *token_name; } slHttpServerData_t; typedef struct _slHttpServerPostData_t { slHttpServerString_t action; slHttpServerString_t token_name; slHttpServerString_t token_value; }slHttpServerPostData_t; typedef union { slHttpServerString_t httpTokenName; /* SL_NETAPP_HTTPGETTOKENVALUE */ slHttpServerPostData_t httpPostData; /* SL_NETAPP_HTTPPOSTTOKENVALUE */ } SlHttpServerEventData_u; typedef union { slHttpServerString_t token_value; } SlHttpServerResponsedata_u; typedef struct { _u32 Event; SlHttpServerEventData_u EventData; }SlHttpServerEvent_t; typedef struct { _u32 Response; SlHttpServerResponsedata_u ResponseData; }SlHttpServerResponse_t; typedef struct { _u32 lease_time; _u32 ipv4_addr_start; _u32 ipv4_addr_last; }SlNetAppDhcpServerBasicOpt_t; /*mDNS parameters*/ typedef enum { SL_NET_APP_FULL_SERVICE_WITH_TEXT_IPV4_TYPE = 1, SL_NET_APP_FULL_SERVICE_IPV4_TYPE, SL_NET_APP_SHORT_SERVICE_IPV4_TYPE } SlNetAppGetServiceListType_e; typedef struct { _u32 service_ipv4; _u16 service_port; _u16 Reserved; }SlNetAppGetShortServiceIpv4List_t; typedef struct { _u32 service_ipv4; _u16 service_port; _u16 Reserved; _u8 service_name[NETAPP_MAX_SERVICE_NAME_SIZE]; _u8 service_host[NETAPP_MAX_SERVICE_HOST_NAME_SIZE]; }SlNetAppGetFullServiceIpv4List_t; typedef struct { _u32 service_ipv4; _u16 service_port; _u16 Reserved; _u8 service_name[NETAPP_MAX_SERVICE_NAME_SIZE]; _u8 service_host[NETAPP_MAX_SERVICE_HOST_NAME_SIZE]; _u8 service_text[NETAPP_MAX_SERVICE_TEXT_SIZE]; }SlNetAppGetFullServiceWithTextIpv4List_t; typedef struct { /*The below parameters are used to configure the advertise times and interval For example: If: Period is set to T Repetitions are set to P Telescopic factor is K=2 The transmission shall be: advertise P times wait T advertise P times wait 4 * T advertise P time wait 16 * T ... (till max time reached / configuration changed / query issued) */ _u32 t; /* Number of ticks for the initial period. Default is 100 ticks for 1 second. */ _u32 p; /* Number of repetitions. Default value is 1 */ _u32 k; /* Telescopic factor. Default value is 2. */ _u32 RetransInterval;/* Announcing retransmission interval */ _u32 Maxinterval; /* Announcing max period interval */ _u32 max_time; /* Announcing max time */ }SlNetAppServiceAdvertiseTimingParameters_t; /*****************************************************************************/ /* Types declarations */ /*****************************************************************************/ typedef void (*P_SL_DEV_PING_CALLBACK)(SlPingReport_t*); /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ /*! \brief Starts a network application Gets and starts network application for the current WLAN mode \param[in] AppBitMap application bitmap, could be one or combination of the following: \n - SL_NET_APP_HTTP_SERVER_ID - SL_NET_APP_DHCP_SERVER_ID - SL_NET_APP_MDNS_ID \return On error, negative number is returned \sa Stop one or more the above started applications using sl_NetAppStop \note This command activates the application for the current WLAN mode (AP or STA) \warning \par Example: \code For example: Starting internal HTTP server + DHCP server: sl_NetAppStart(SL_NET_APP_HTTP_SERVER_ID | SL_NET_APP_DHCP_SERVER_ID) \endcode */ #if _SL_INCLUDE_FUNC(sl_NetAppStart) _i16 sl_NetAppStart(const _u32 AppBitMap); #endif /*! \brief Stops a network application Gets and stops network application for the current WLAN mode \param[in] AppBitMap application id, could be one of the following: \n - SL_NET_APP_HTTP_SERVER_ID - SL_NET_APP_DHCP_SERVER_ID - SL_NET_APP_MDNS_ID \return On error, negative number is returned \sa \note This command disables the application for the current active WLAN mode (AP or STA) \warning \par Example: \code For example: Stopping internal HTTP server: sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); \endcode */ #if _SL_INCLUDE_FUNC(sl_NetAppStop) _i16 sl_NetAppStop(const _u32 AppBitMap); #endif /*! \brief Get host IP by name Obtain the IP Address of machine on network, by machine name. \param[in] hostname host name \param[in] usNameLen name length \param[out] out_ip_addr This parameter is filled in with host IP address. In case that host name is not resolved, out_ip_addr is zero. \param[in] family protocol family \return On success, 0 is returned. On error, negative is returned SL_POOL_IS_EMPTY may be return in case there are no resources in the system In this case try again later or increase MAX_CONCURRENT_ACTIONS Possible DNS error codes: - SL_NET_APP_DNS_QUERY_NO_RESPONSE - SL_NET_APP_DNS_NO_SERVER - SL_NET_APP_DNS_QUERY_FAILED - SL_NET_APP_DNS_MALFORMED_PACKET - SL_NET_APP_DNS_MISMATCHED_RESPONSE \sa \note Only one sl_NetAppDnsGetHostByName can be handled at a time. Calling this API while the same command is called from another thread, may result in one of the two scenarios: 1. The command will wait (internal) until the previous command finish, and then be executed. 2. There are not enough resources and POOL_IS_EMPTY error will return. In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try again later to issue the command. \warning In case an IP address in a string format is set as input, without any prefix (e.g. "1.2.3.4") the device will not try to access the DNS and it will return the input address on the 'out_ip_addr' field \par Example: \code _u32 DestinationIP; sl_NetAppDnsGetHostByName("www.google.com", strlen("www.google.com"), &DestinationIP,SL_AF_INET); Addr.sin_family = SL_AF_INET; Addr.sin_port = sl_Htons(80); Addr.sin_addr.s_addr = sl_Htonl(DestinationIP); AddrSize = sizeof(SlSockAddrIn_t); SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); \endcode */ #if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByName) _i16 sl_NetAppDnsGetHostByName(_i8 * hostname,const _u16 usNameLen, _u32* out_ip_addr,const _u8 family ); #endif /*! \brief Return service attributes like IP address, port and text according to service name \par The user sets a service name Full/Part (see example below), and should get: - IP of service - The port of service - The text of service Hence it can make a connection to the specific service and use it. It is similar to get host by name method. It is done by a single shot query with PTR type on the service name. The command that is sent is from constant parameters and variables parameters. \param[in] pService Service name can be full or partial. \n Example for full service name: 1. PC1._ipp._tcp.local 2. PC2_server._ftp._tcp.local \n . Example for partial service name: 1. _ipp._tcp.local 2. _ftp._tcp.local \param[in] ServiceLen The length of the service name (in_pService). \param[in] Family IPv4 or IPv6 (SL_AF_INET , SL_AF_INET6). \param[out] pAddr Contains the IP address of the service. \param[out] pPort Contains the port of the service. \param[out] pTextLen Has 2 options. One as Input field and the other one as output: - Input: \n Contains the max length of the text that the user wants to get.\n It means that if the text len of service is bigger that its value than the text is cut to inout_TextLen value. - Output: \n Contain the length of the text that is returned. Can be full text or part of the text (see above). \param[out] pOut_pText Contains the text of the service full or partial \return On success, zero is returned SL_POOL_IS_EMPTY may be return in case there are no resources in the system In this case try again later or increase MAX_CONCURRENT_ACTIONS In case No service is found error SL_NET_APP_DNS_NO_ANSWER will be returned \note The returns attributes belongs to the first service found. There may be other services with the same service name that will response to the query. The results of these responses are saved in the peer cache of the Device and should be read by another API. Only one sl_NetAppDnsGetHostByService can be handled at a time. Calling this API while the same command is called from another thread, may result in one of the two scenarios: 1. The command will wait (internal) until the previous command finish, and then be executed. 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try again later to issue the command. \warning Text length can be 120 bytes only */ #if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByService) _i32 sl_NetAppDnsGetHostByService(_i8 *pServiceName, /* string containing all (or only part): name + subtype + service */ const _u8 ServiceLen, const _u8 Family, /* 4-IPv4 , 16-IPv6 */ _u32 pAddr[], _u32 *pPort, _u16 *pTextLen, /* in: max len , out: actual len */ _i8 *pText ); #endif /*! \brief Get service List Insert into out pBuffer a list of peer's services that are the NWP. The list is in a form of service struct. The user should chose the type of the service struct like: - Full service parameters with text. - Full service parameters. - Short service parameters (port and IP only) especially for tiny hosts. The different types of struct are made to give the Possibility to save memory in the host The user also chose how many max services to get and start point index NWP peer cache. For example: 1. Get max of 3 full services from index 0.Up to 3 full services from index 0 are inserted into pBuffer (services that are in indexes 0,1,2). 2. Get max of 4 full services from index 3.Up to 4 full services from index 3 are inserted into pBuffer (services that are in indexes 3,4,5,6). 3. Get max of 2 int services from index 6.Up to 2 int services from index 6 are inserted into pBuffer (services that are in indexes 6,7). See below - command parameters. \param[in] indexOffset - The start index in the peer cache that from it the first service is returned. \param[in] MaxServiceCount - The Max services that can be returned if existed or if not exceed the max index in the peer cache \param[in] Flags - an ENUM number that means which service struct to use (means which types of service to fill) - use SlNetAppGetFullServiceWithTextIpv4List_t - use SlNetAppGetFullServiceIpv4List_t - use SlNetAppGetShortServiceIpv4List_t \param[out] Buffer - The Services are inserted into this buffer. In the struct form according to the bit that is set in the Flags input parameter. \return ServiceFoundCount - The number of the services that were inserted into the buffer. zero means no service is found negative number means an error \sa sl_NetAppMDNSRegisterService \note \warning if the out pBuffer size is bigger than an RX packet(1480), than an error is returned because there is no place in the RX packet. The size is a multiply of MaxServiceCount and size of service struct(that is set according to flag value). */ #if _SL_INCLUDE_FUNC(sl_NetAppGetServiceList) _i16 sl_NetAppGetServiceList(const _u8 IndexOffest, const _u8 MaxServiceCount, const _u8 Flags, _i8 *pBuffer, const _u32 RxBufferLength ); #endif /*! \brief Unregister mDNS service This function deletes the mDNS service from the mDNS package and the database. The mDNS service that is to be unregistered is a service that the application no longer wishes to provide. \n The service name should be the full service name according to RFC of the DNS-SD - meaning the value in name field in the SRV answer. Examples for service names: 1. PC1._ipp._tcp.local 2. PC2_server._ftp._tcp.local \param[in] pServiceName Full service name. \n Example for service name: 1. PC1._ipp._tcp.local 2. PC2_server._ftp._tcp.local \param[in] ServiceLen The length of the service. \return On success, zero is returned \sa sl_NetAppMDNSRegisterService \note \warning The size of the service length should be smaller than 255. */ #if _SL_INCLUDE_FUNC(sl_NetAppMDNSUnRegisterService) _i16 sl_NetAppMDNSUnRegisterService(const _i8 *pServiceName,const _u8 ServiceNameLen); #endif /*! \brief Register a new mDNS service \par This function registers a new mDNS service to the mDNS package and the DB. This registered service is a service offered by the application. The service name should be full service name according to RFC of the DNS-SD - meaning the value in name field in the SRV answer. Example for service name: 1. PC1._ipp._tcp.local 2. PC2_server._ftp._tcp.local If the option is_unique is set, mDNS probes the service name to make sure it is unique before starting to announce the service on the network. Instance is the instance portion of the service name. \param[in] ServiceLen The length of the service. \param[in] TextLen The length of the service should be smaller than 64. \param[in] port The port on this target host port. \param[in] TTL The TTL of the service \param[in] Options bitwise parameters: \n - bit 0 - service is unique (means that the service needs to be unique) - bit 31 - for internal use if the service should be added or deleted (set means ADD). - bit 1-30 for future. \param[in] pServiceName The service name. Example for service name: \n 1. PC1._ipp._tcp.local 2. PC2_server._ftp._tcp.local \param[in] pText The description of the service. should be as mentioned in the RFC (according to type of the service IPP,FTP...) \return On success, zero is returned Possible error codes: - Maximum advertise services are already configured. Delete another existed service that is registered and then register again the new service - Trying to register a service that is already exists - Trying to delete service that does not existed - Illegal service name according to the RFC - Retry request - Illegal length of one of the mDNS Set functions - mDNS is not operational as the device has no IP.Connect the device to an AP to get an IP address. - mDNS parameters error - mDNS internal cache error - mDNS internal error - Adding a service is not allowed as it is already exist (duplicate service) - mDNS is not running - Host name error. Host name format is not allowed according to RFC 1033,1034,1035, 6763 - List size buffer is bigger than internally allowed in the NWP (API get service list), change the APIs parameters to decrease the size of the list \sa sl_NetAppMDNSUnRegisterService \warning 1) Temporary - there is an allocation on stack of internal buffer. Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. \n It means that the sum of the text length and service name length cannot be bigger than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH.\n If it is - An error is returned. \n 2) According to now from certain constraints the variables parameters are set in the attribute part (contain constant parameters) */ #if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterService) _i16 sl_NetAppMDNSRegisterService( const _i8* pServiceName, const _u8 ServiceNameLen, const _i8* pText, const _u8 TextLen, const _u16 Port, const _u32 TTL, _u32 Options); #endif /*! \brief send ICMP ECHO_REQUEST to network hosts Ping uses the ICMP protocol's mandatory ECHO_REQUEST \param[in] pPingParams Pointer to the ping request structure: \n - if flags parameter is set to 0, ping will report back once all requested pings are done (as defined by TotalNumberOfAttempts). \n - if flags parameter is set to 1, ping will report back after every ping, for TotalNumberOfAttempts. - if flags parameter is set to 2, ping will stop after the first successful ping, and report back for the successful ping, as well as any preceding failed ones. For stopping an ongoing ping activity, set parameters IP address to 0 \param[in] family SL_AF_INET or SL_AF_INET6 \param[out] pReport Ping pReport \param[out] pCallback Callback function upon completion. If callback is NULL, the API is blocked until data arrives \return On success, zero is returned. On error, -1 is returned SL_POOL_IS_EMPTY may be return in case there are no resources in the system In this case try again later or increase MAX_CONCURRENT_ACTIONS \sa sl_NetAppPingReport \note Only one sl_NetAppPingStart can be handled at a time. Calling this API while the same command is called from another thread, may result in one of the two scenarios: 1. The command will wait (internal) until the previous command finish, and then be executed. 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try again later to issue the command. \warning \par Example: \code An example of sending 20 ping requests and reporting results to a callback routine when all requests are sent: // callback routine void pingRes(SlPingReport_t* pReport) { // handle ping results } // ping activation void PingTest() { SlPingReport_t report; SlPingStartCommand_t pingCommand; pingCommand.Ip = SL_IPV4_VAL(10,1,1,200); // destination IP address is 10.1.1.200 pingCommand.PingSize = 150; // size of ping, in bytes pingCommand.PingIntervalTime = 100; // delay between pings, in milliseconds pingCommand.PingRequestTimeout = 1000; // timeout for every ping in milliseconds pingCommand.TotalNumberOfAttempts = 20; // max number of ping requests. 0 - forever pingCommand.Flags = 0; // report only when finished sl_NetAppPingStart( &pingCommand, SL_AF_INET, &report, pingRes ) ; } \endcode */ #if _SL_INCLUDE_FUNC(sl_NetAppPingStart) _i16 sl_NetAppPingStart(const SlPingStartCommand_t* pPingParams,const _u8 family,SlPingReport_t *pReport,const P_SL_DEV_PING_CALLBACK pPingCallback); #endif /*! \brief Internal function for setting network application configurations \return On success, zero is returned. On error, -1 is returned \param[in] AppId Application id, could be one of the following: \n - SL_NET_APP_HTTP_SERVER_ID - SL_NET_APP_DHCP_SERVER_ID - SL_NET_APP_MDNS_ID - SL_NET_APP_DEVICE_CONFIG_ID \param[in] SetOptions set option, could be one of the following: \n - SL_NET_APP_DHCP_SERVER_ID - NETAPP_SET_DHCP_SRV_BASIC_OPT - SL_NET_APP_HTTP_SERVER_ID - NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER - NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK - NETAPP_SET_GET_HTTP_OPT_AUTH_NAME - NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD - NETAPP_SET_GET_HTTP_OPT_AUTH_REALM - NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS - SL_NET_APP_MDNS_ID - NETAPP_SET_GET_MDNS_CONT_QUERY_OPT - NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT - NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT - SL_NET_APP_DEVICE_CONFIG_ID - NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN - NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME \param[in] OptionLen option structure length \param[in] pOptionValues pointer to the option structure \sa \note \warning \par \code Set DHCP Server (AP mode) parameters example: SlNetAppDhcpServerBasicOpt_t dhcpParams; _u8 outLen = sizeof(SlNetAppDhcpServerBasicOpt_t); dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address dhcpParams.ipv4_addr_start = SL_IPV4_VAL(192,168,1,10); // first IP Address for allocation. IP Address should be set as Hex number - i.e. 0A0B0C01 for (10.11.12.1) dhcpParams.ipv4_addr_last = SL_IPV4_VAL(192,168,1,16); // last IP Address for allocation. IP Address should be set as Hex number - i.e. 0A0B0C01 for (10.11.12.1) sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID); // Stop DHCP server before settings sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, outLen, (_u8* )&dhcpParams); // set parameters sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID); // Start DHCP server with new settings \endcode \code Set Device URN name example: Device name, maximum length of 33 characters Device name affects URN name, own SSID name in AP mode, and WPS file "device name" in WPS I.E (STA-WPS / P2P) In case no device URN name set, the default name is "mysimplelink" Allowed characters in device name are: 'a - z' , 'A - Z' , '0-9' and '-' _u8 *my_device = "MY-SIMPLELINK-DEV"; sl_NetAppSet (SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, strlen(my_device), (_u8 *) my_device); \endcode */ #if _SL_INCLUDE_FUNC(sl_NetAppSet) _i32 sl_NetAppSet(const _u8 AppId ,const _u8 Option,const _u8 OptionLen,const _u8 *pOptionValue); #endif /*! \brief Internal function for getting network applications configurations \return On success, zero is returned. On error, -1 is returned \param[in] AppId Application id, could be one of the following: \n - SL_NET_APP_HTTP_SERVER_ID - SL_NET_APP_DHCP_SERVER_ID - SL_NET_APP_MDNS_ID - SL_NET_APP_DEVICE_CONFIG_ID \param[in] SetOptions set option, could be one of the following: \n - SL_NET_APP_DHCP_SERVER_ID - NETAPP_SET_DHCP_SRV_BASIC_OPT - SL_NET_APP_HTTP_SERVER_ID - NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER - NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK - NETAPP_SET_GET_HTTP_OPT_AUTH_NAME - NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD - NETAPP_SET_GET_HTTP_OPT_AUTH_REALM - NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS - SL_NET_APP_MDNS_ID - NETAPP_SET_GET_MDNS_CONT_QUERY_OPT - NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT - NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT - SL_NET_APP_DEVICE_CONFIG_ID - NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN - NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME \param[in] OptionLen The length of the allocated memory as input, when the function complete, the value of this parameter would be the len that actually read from the device. If the device return length that is longer from the input value, the function will cut the end of the returned structure and will return ESMALLBUF \param[out] pValues pointer to the option structure which will be filled with the response from the device \sa \note \warning \par \code Get DHCP Server parameters example: SlNetAppDhcpServerBasicOpt_t dhcpParams; _u8 outLen = sizeof(SlNetAppDhcpServerBasicOpt_t); sl_NetAppGet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, &outLen, (_u8* )&dhcpParams); printf("DHCP Start IP %d.%d.%d.%d End IP %d.%d.%d.%d Lease time seconds %d\n", SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,3),SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,2), SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,1),SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,0), SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,3),SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,2), SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,1),SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,0), dhcpParams.lease_time); \endcode \code Get Device URN name example: Maximum length of 33 characters of device name. Device name affects URN name, own SSID name in AP mode, and WPS file "device name" in WPS I.E (STA-WPS / P2P) in case no device URN name set, the default name is "mysimplelink" _u8 my_device_name[35]; sl_NetAppGet (SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, strlen(my_device_name), (_u8 *)my_device_name); \endcode */ #if _SL_INCLUDE_FUNC(sl_NetAppGet) _i32 sl_NetAppGet(const _u8 AppId,const _u8 Option,_u8 *pOptionLen, _u8 *pOptionValue); #endif /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __NETAPP_H__ */ micropython-1.12/drivers/cc3100/inc/netcfg.h000066400000000000000000000260471357706137100205720ustar00rootroot00000000000000/* * netcfg.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #ifndef __NETCFG_H__ #define __NETCFG_H__ #ifdef __cplusplus extern "C" { #endif /*! \addtogroup netcfg @{ */ /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #define SL_MAC_ADDR_LEN (6) #define SL_IPV4_VAL(add_3,add_2,add_1,add_0) ((((_u32)add_3 << 24) & 0xFF000000) | (((_u32)add_2 << 16) & 0xFF0000) | (((_u32)add_1 << 8) & 0xFF00) | ((_u32)add_0 & 0xFF) ) #define SL_IPV4_BYTE(val,index) ( (val >> (index*8)) & 0xFF ) #define IPCONFIG_MODE_DISABLE_IPV4 (0) #define IPCONFIG_MODE_ENABLE_IPV4 (1) /*****************************************************************************/ /* Structure/Enum declarations */ /*****************************************************************************/ typedef enum { SL_MAC_ADDRESS_SET = 1, SL_MAC_ADDRESS_GET = 2, SL_IPV4_STA_P2P_CL_GET_INFO = 3, SL_IPV4_STA_P2P_CL_DHCP_ENABLE = 4, SL_IPV4_STA_P2P_CL_STATIC_ENABLE = 5, SL_IPV4_AP_P2P_GO_GET_INFO = 6, SL_IPV4_AP_P2P_GO_STATIC_ENABLE = 7, SL_SET_HOST_RX_AGGR = 8, MAX_SETTINGS = 0xFF }Sl_NetCfg_e; typedef struct { _u32 ipV4; _u32 ipV4Mask; _u32 ipV4Gateway; _u32 ipV4DnsServer; }SlNetCfgIpV4Args_t; /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ /*! \brief Internal function for setting network configurations \return On success, zero is returned. On error, -1 is returned \param[in] ConfigId configuration id \param[in] ConfigOpt configurations option \param[in] ConfigLen configurations len \param[in] pValues configurations values \sa \note \warning \par Examples: \code SL_MAC_ADDRESS_SET: Setting MAC address to the Device. The new MAC address will override the default MAC address and it be saved in the FileSystem. Requires restarting the device for updating this setting. _u8 MAC_Address[6]; MAC_Address[0] = 0x8; MAC_Address[1] = 0x0; MAC_Address[2] = 0x28; MAC_Address[3] = 0x22; MAC_Address[4] = 0x69; MAC_Address[5] = 0x31; sl_NetCfgSet(SL_MAC_ADDRESS_SET,1,SL_MAC_ADDR_LEN,(_u8 *)newMacAddress); sl_Stop(0); sl_Start(NULL,NULL,NULL); \endcode \code SL_IPV4_STA_P2P_CL_STATIC_ENABLE: Setting a static IP address to the device working in STA mode or P2P client. The IP address will be stored in the FileSystem. In order to disable the static IP and get the address assigned from DHCP one should use SL_STA_P2P_CL_IPV4_DHCP_SET SlNetCfgIpV4Args_t ipV4; ipV4.ipV4 = (_u32)SL_IPV4_VAL(10,1,1,201); // _u32 IP address ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this STA/P2P ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(10,1,1,1); // _u32 Default gateway address ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(8,16,32,64); // _u32 DNS server address sl_NetCfgSet(SL_IPV4_STA_P2P_CL_STATIC_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,sizeof(SlNetCfgIpV4Args_t),(_u8 *)&ipV4); sl_Stop(0); sl_Start(NULL,NULL,NULL); \endcode \code SL_IPV4_STA_P2P_CL_DHCP_ENABLE: Setting IP address by DHCP to FileSystem using WLAN sta mode or P2P client. This should be done once if using Serial Flash. This is the system's default mode for acquiring an IP address after WLAN connection. _u8 val = 1; sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,1,&val); sl_Stop(0); sl_Start(NULL,NULL,NULL); \endcode \code SL_IPV4_AP_P2P_GO_STATIC_ENABLE: Setting a static IP address to the device working in AP mode or P2P go. The IP address will be stored in the FileSystem. Requires restart. SlNetCfgIpV4Args_t ipV4; ipV4.ipV4 = (_u32)SL_IPV4_VAL(10,1,1,201); // _u32 IP address ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP/P2P ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(10,1,1,1); // _u32 Default gateway address ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(8,16,32,64); // _u32 DNS server address sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,sizeof(SlNetCfgIpV4Args_t),(_u8 *)&ipV4); sl_Stop(0); sl_Start(NULL,NULL,NULL); \endcode */ #if _SL_INCLUDE_FUNC(sl_NetCfgSet) _i32 sl_NetCfgSet(const _u8 ConfigId,const _u8 ConfigOpt,const _u8 ConfigLen,const _u8 *pValues); #endif /*! \brief Internal function for getting network configurations \return On success, zero is returned. On error, -1 is returned \param[in] ConfigId configuration id \param[out] pConfigOpt Get configurations option \param[out] pConfigLen The length of the allocated memory as input, when the function complete, the value of this parameter would be the len that actually read from the device.\n If the device return length that is longer from the input value, the function will cut the end of the returned structure and will return ESMALLBUF \param[out] pValues - get configurations values \sa \note \warning \par Examples: \code SL_MAC_ADDRESS_GET: Get the device MAC address. The returned MAC address is taken from FileSystem first. If the MAC address was not set by SL_MAC_ADDRESS_SET, the default MAC address is retrieved from HW. _u8 macAddressVal[SL_MAC_ADDR_LEN]; _u8 macAddressLen = SL_MAC_ADDR_LEN; sl_NetCfgGet(SL_MAC_ADDRESS_GET,NULL,&macAddressLen,(_u8 *)macAddressVal); \endcode \code SL_IPV4_STA_P2P_CL_GET_INFO: Get IP address from WLAN station or P2P client. A DHCP flag is returned to indicate if the IP address is static or from DHCP. _u8 len = sizeof(SlNetCfgIpV4Args_t); _u8 dhcpIsOn = 0; SlNetCfgIpV4Args_t ipV4 = {0}; sl_NetCfgGet(SL_IPV4_STA_P2P_CL_GET_INFO,&dhcpIsOn,&len,(_u8 *)&ipV4); printf("DHCP is %s IP %d.%d.%d.%d MASK %d.%d.%d.%d GW %d.%d.%d.%d DNS %d.%d.%d.%d\n", (dhcpIsOn > 0) ? "ON" : "OFF", SL_IPV4_BYTE(ipV4.ipV4,3),SL_IPV4_BYTE(ipV4.ipV4,2),SL_IPV4_BYTE(ipV4.ipV4,1),SL_IPV4_BYTE(ipV4.ipV4,0), SL_IPV4_BYTE(ipV4.ipV4Mask,3),SL_IPV4_BYTE(ipV4.ipV4Mask,2),SL_IPV4_BYTE(ipV4.ipV4Mask,1),SL_IPV4_BYTE(ipV4.ipV4Mask,0), SL_IPV4_BYTE(ipV4.ipV4Gateway,3),SL_IPV4_BYTE(ipV4.ipV4Gateway,2),SL_IPV4_BYTE(ipV4.ipV4Gateway,1),SL_IPV4_BYTE(ipV4.ipV4Gateway,0), SL_IPV4_BYTE(ipV4.ipV4DnsServer,3),SL_IPV4_BYTE(ipV4.ipV4DnsServer,2),SL_IPV4_BYTE(ipV4.ipV4DnsServer,1),SL_IPV4_BYTE(ipV4.ipV4DnsServer,0)); \endcode \code SL_IPV4_AP_P2P_GO_GET_INFO: Get static IP address for AP or P2P go. _u8 len = sizeof(SlNetCfgIpV4Args_t); _u8 dhcpIsOn = 0; // this flag is meaningless on AP/P2P go. SlNetCfgIpV4Args_t ipV4 = {0}; sl_NetCfgGet(SL_IPV4_AP_P2P_GO_GET_INFO,&dhcpIsOn,&len,(_u8 *)&ipV4); printf("IP %d.%d.%d.%d MASK %d.%d.%d.%d GW %d.%d.%d.%d DNS %d.%d.%d.%d\n", SL_IPV4_BYTE(ipV4.ipV4,3),SL_IPV4_BYTE(ipV4.ipV4,2),SL_IPV4_BYTE(ipV4.ipV4,1),SL_IPV4_BYTE(ipV4.ipV4,0), SL_IPV4_BYTE(ipV4.ipV4Mask,3),SL_IPV4_BYTE(ipV4.ipV4Mask,2),SL_IPV4_BYTE(ipV4.ipV4Mask,1),SL_IPV4_BYTE(ipV4.ipV4Mask,0), SL_IPV4_BYTE(ipV4.ipV4Gateway,3),SL_IPV4_BYTE(ipV4.ipV4Gateway,2),SL_IPV4_BYTE(ipV4.ipV4Gateway,1),SL_IPV4_BYTE(ipV4.ipV4Gateway,0), SL_IPV4_BYTE(ipV4.ipV4DnsServer,3),SL_IPV4_BYTE(ipV4.ipV4DnsServer,2),SL_IPV4_BYTE(ipV4.ipV4DnsServer,1),SL_IPV4_BYTE(ipV4.ipV4DnsServer,0)); \endcode */ #if _SL_INCLUDE_FUNC(sl_NetCfgGet) _i32 sl_NetCfgGet(const _u8 ConfigId ,_u8 *pConfigOpt, _u8 *pConfigLen, _u8 *pValues); #endif /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __NETCFG_H__ */ micropython-1.12/drivers/cc3100/inc/nonos.h000066400000000000000000000255271357706137100204620ustar00rootroot00000000000000/* * nonos.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __NONOS_H__ #define __NONOS_H__ #ifdef __cplusplus extern "C" { #endif #ifndef SL_PLATFORM_MULTI_THREADED /* This function call the user defined function, if defined, from the sync wait loop */ /* The use case of this function is to allow nonos system to call a user function to put the device into sleep */ /* The wake up should be activated after getting an interrupt from the device to Host */ /* The user function must return without blocking to prevent a delay on the event handling */ /* #define _SlSyncWaitLoopCallback UserSleepFunction */ #define NONOS_WAIT_FOREVER 0xFF #define NONOS_NO_WAIT 0x00 #define NONOS_RET_OK (0) #define NONOS_RET_ERR (0xFF) #define OSI_OK NONOS_RET_OK #define __NON_OS_SYNC_OBJ_CLEAR_VALUE 0x11 #define __NON_OS_SYNC_OBJ_SIGNAL_VALUE 0x22 #define __NON_OS_LOCK_OBJ_UNLOCK_VALUE 0x33 #define __NON_OS_LOCK_OBJ_LOCK_VALUE 0x44 /*! \brief type definition for the return values of this adaptation layer */ typedef _i8 _SlNonOsRetVal_t; /*! \brief type definition for a time value */ typedef _u8 _SlNonOsTime_t; /*! \brief type definition for a sync object container Sync object is object used to synchronize between two threads or thread and interrupt handler. One thread is waiting on the object and the other thread send a signal, which then release the waiting thread. The signal must be able to be sent from interrupt context. This object is generally implemented by binary semaphore or events. */ typedef _u8 _SlNonOsSemObj_t; #define _SlTime_t _SlNonOsTime_t #define _SlSyncObj_t _SlNonOsSemObj_t #define _SlLockObj_t _SlNonOsSemObj_t #define SL_OS_WAIT_FOREVER NONOS_WAIT_FOREVER #define SL_OS_RET_CODE_OK NONOS_RET_OK #define SL_OS_NO_WAIT NONOS_NO_WAIT /*! \brief This function creates a sync object The sync object is used for synchronization between different thread or ISR and a thread. \param pSyncObj - pointer to the sync object control block \return upon successful creation the function return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define _SlNonOsSyncObjCreate(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) /*! \brief This function deletes a sync object \param pSyncObj - pointer to the sync object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define _SlNonOsSyncObjDelete(pSyncObj) _SlNonOsSemSet(pSyncObj,0) /*! \brief This function generates a sync signal for the object. All suspended threads waiting on this sync object are resumed \param pSyncObj - pointer to the sync object control block \return upon successful signaling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function could be called from ISR context \warning */ #define _SlNonOsSyncObjSignal(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) /*! \brief This function waits for a sync signal of the specific sync object \param pSyncObj - pointer to the sync object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the sync signal Currently, the simple link driver uses only two values: - NONOS_WAIT_FOREVER - NONOS_NO_WAIT \return upon successful reception of the signal within the timeout window return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define _SlNonOsSyncObjWait(pSyncObj , Timeout) _SlNonOsSemGet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE,__NON_OS_SYNC_OBJ_CLEAR_VALUE,Timeout) /*! \brief This function clears a sync object \param pSyncObj - pointer to the sync object control block \return upon successful clearing the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define _SlNonOsSyncObjClear(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) /*! \brief This function creates a locking object. The locking object is used for protecting a shared resources between different threads. \param pLockObj - pointer to the locking object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define _SlNonOsLockObjCreate(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) /*! \brief This function deletes a locking object. \param pLockObj - pointer to the locking object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define _SlNonOsLockObjDelete(pLockObj) _SlNonOsSemSet(pLockObj,0) /*! \brief This function locks a locking object. All other threads that call this function before this thread calls the _SlNonOsLockObjUnlock would be suspended \param pLockObj - pointer to the locking object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the locking object Currently, the simple link driver uses only two values: - NONOS_WAIT_FOREVER - NONOS_NO_WAIT \return upon successful reception of the locking object the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define _SlNonOsLockObjLock(pLockObj , Timeout) _SlNonOsSemGet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE,__NON_OS_LOCK_OBJ_LOCK_VALUE,Timeout) /*! \brief This function unlock a locking object. \param pLockObj - pointer to the locking object control block \return upon successful unlocking the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define _SlNonOsLockObjUnlock(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) /*! \brief This function call the pEntry callback from a different context \param pEntry - pointer to the entry callback function \param pValue - pointer to any type of memory structure that would be passed to pEntry callback from the execution thread. \param flags - execution flags - reserved for future usage \return upon successful registration of the spawn the function return 0 (the function is not blocked till the end of the execution of the function and could be returned before the execution is actually completed) Otherwise, a negative value indicating the error code shall be returned \note \warning */ _SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); /*! \brief This function must be called from the main loop in non-os paltforms \param None \return 0 - No more activities 1 - Activity still in progress \note \warning */ _SlNonOsRetVal_t _SlNonOsMainLoopTask(void); extern _SlNonOsRetVal_t _SlNonOsSemGet(_SlNonOsSemObj_t* pSyncObj, _SlNonOsSemObj_t WaitValue, _SlNonOsSemObj_t SetValue, _SlNonOsTime_t Timeout); extern _SlNonOsRetVal_t _SlNonOsSemSet(_SlNonOsSemObj_t* pSemObj , _SlNonOsSemObj_t Value); extern _SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); #if (defined(_SlSyncWaitLoopCallback)) extern void _SlSyncWaitLoopCallback(void); #endif /***************************************************************************** Overwrite SimpleLink driver OS adaptation functions *****************************************************************************/ #undef sl_SyncObjCreate #define sl_SyncObjCreate(pSyncObj,pName) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) #undef sl_SyncObjDelete #define sl_SyncObjDelete(pSyncObj) _SlNonOsSemSet(pSyncObj,0) #undef sl_SyncObjSignal #define sl_SyncObjSignal(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) #undef sl_SyncObjSignalFromIRQ #define sl_SyncObjSignalFromIRQ(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) #undef sl_SyncObjWait #define sl_SyncObjWait(pSyncObj,Timeout) _SlNonOsSemGet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE,__NON_OS_SYNC_OBJ_CLEAR_VALUE,Timeout) #undef sl_LockObjCreate #define sl_LockObjCreate(pLockObj,pName) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) #undef sl_LockObjDelete #define sl_LockObjDelete(pLockObj) _SlNonOsSemSet(pLockObj,0) #undef sl_LockObjLock #define sl_LockObjLock(pLockObj,Timeout) _SlNonOsSemGet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE,__NON_OS_LOCK_OBJ_LOCK_VALUE,Timeout) #undef sl_LockObjUnlock #define sl_LockObjUnlock(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) #undef sl_Spawn #define sl_Spawn(pEntry,pValue,flags) _SlNonOsSpawn(pEntry,pValue,flags) #undef _SlTaskEntry #define _SlTaskEntry _SlNonOsMainLoopTask #endif /* !SL_PLATFORM_MULTI_THREADED */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif micropython-1.12/drivers/cc3100/inc/objInclusion.h000066400000000000000000000200551357706137100217530ustar00rootroot00000000000000/* * objInclusion.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifndef OBJINCLUSION_H_ #define OBJINCLUSION_H_ #ifdef __cplusplus extern "C" { #endif /****************************************************************************** For future use *******************************************************************************/ #define __inln /* if inline functions requiered: #define __inln inline */ #define SL_DEVICE /* Device silo is currently always mandatory */ /****************************************************************************** Qualifiers for package customizations *******************************************************************************/ #if defined (SL_DEVICE) #define __dev 1 #else #define __dev 0 #endif #if defined (SL_DEVICE) && defined (SL_INC_EXT_API) #define __dev__ext 1 #else #define __dev__ext 0 #endif #if (!defined (SL_PLATFORM_MULTI_THREADED)) || (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) #define __int__spwn 1 #else #define __int__spwn 0 #endif #if defined (SL_INC_NET_APP_PKG) #define __nap 1 #else #define __nap 0 #endif #if defined (SL_INC_NET_APP_PKG) && defined (SL_INC_SOCK_CLIENT_SIDE_API) #define __nap__clt 1 #else #define __nap__clt 0 #endif #if defined (SL_INC_NET_APP_PKG) && defined (SL_INC_EXT_API) #define __nap__ext 1 #else #define __nap__ext 0 #endif #if defined (SL_INC_NET_CFG_PKG) #define __ncg 1 #else #define __ncg 0 #endif #if defined (SL_INC_NET_CFG_PKG) && defined (SL_INC_EXT_API) #define __ncg__ext 1 #else #define __ncg__ext 0 #endif #if defined (SL_INC_NVMEM_PKG) #define __nvm 1 #else #define __nvm 0 #endif #if defined (SL_INC_SOCKET_PKG) #define __sck 1 #else #define __sck 0 #endif #if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_EXT_API) #define __sck__ext 1 #else #define __sck__ext 0 #endif #if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_SERVER_SIDE_API) #define __sck__srv 1 #else #define __sck__srv 0 #endif #if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_CLIENT_SIDE_API) #define __sck__clt 1 #else #define __sck__clt 0 #endif #if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_RECV_API) #define __sck__rcv 1 #else #define __sck__rcv 0 #endif #if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_SEND_API) #define __sck__snd 1 #else #define __sck__snd 0 #endif #if defined (SL_INC_WLAN_PKG) #define __wln 1 #else #define __wln 0 #endif #if defined (SL_INC_WLAN_PKG) && defined (SL_INC_EXT_API) #define __wln__ext 1 #else #define __wln__ext 0 #endif /* The return 1 is the function need to be included in the output */ #define _SL_INCLUDE_FUNC(Name) (_SL_INC_##Name) /* Driver */ #define _SL_INC_sl_NetAppStart __nap__ext #define _SL_INC_sl_NetAppStop __nap__ext #define _SL_INC_sl_NetAppDnsGetHostByName __nap__clt #define _SL_INC_sl_NetAppDnsGetHostByService __nap__ext #define _SL_INC_sl_NetAppMDNSRegisterService __nap__ext #define _SL_INC_sl_NetAppMDNSUnRegisterService __nap__ext #define _SL_INC_sl_NetAppMDNSRegisterUnregisterService __nap__ext #define _SL_INC_sl_NetAppGetServiceList __nap__ext #define _SL_INC_sl_DnsGetHostByAddr __nap__ext #define _SL_INC_sl_NetAppPingStart __nap__ext #define _SL_INC_sl_NetAppPingReport __nap__ext #define _SL_INC_sl_NetAppSet __nap__ext #define _SL_INC_sl_NetAppGet __nap__ext /* FS */ #define _SL_INC_sl_FsOpen __nvm #define _SL_INC_sl_FsClose __nvm #define _SL_INC_sl_FsRead __nvm #define _SL_INC_sl_FsWrite __nvm #define _SL_INC_sl_FsGetInfo __nvm #define _SL_INC_sl_FsDel __nvm /* netcfg */ #define _SL_INC_sl_MacAdrrSet __ncg #define _SL_INC_sl_MacAdrrGet __ncg #define _SL_INC_sl_NetCfgGet __ncg #define _SL_INC_sl_NetCfgSet __ncg /* socket */ #define _SL_INC_sl_Socket __sck #define _SL_INC_sl_Close __sck #define _SL_INC_sl_Accept __sck__srv #define _SL_INC_sl_Bind __sck #define _SL_INC_sl_Listen __sck__srv #define _SL_INC_sl_Connect __sck__clt #define _SL_INC_sl_Select __sck #define _SL_INC_sl_SetSockOpt __sck #define _SL_INC_sl_GetSockOpt __sck__ext #define _SL_INC_sl_Recv __sck__rcv #define _SL_INC_sl_RecvFrom __sck__rcv #define _SL_INC_sl_Write __sck__snd #define _SL_INC_sl_Send __sck__snd #define _SL_INC_sl_SendTo __sck__snd #define _SL_INC_sl_Htonl __sck #define _SL_INC_sl_Htons __sck /* wlan */ #define _SL_INC_sl_WlanConnect __wln__ext #define _SL_INC_sl_WlanDisconnect __wln__ext #define _SL_INC_sl_WlanProfileAdd __wln__ext #define _SL_INC_sl_WlanProfileGet __wln__ext #define _SL_INC_sl_WlanProfileDel __wln__ext #define _SL_INC_sl_WlanPolicySet __wln__ext #define _SL_INC_sl_WlanPolicyGet __wln__ext #define _SL_INC_sl_WlanGetNetworkList __wln__ext #define _SL_INC_sl_WlanRxFilterAdd __wln__ext #define _SL_INC_sl_WlanRxFilterSet __wln__ext #define _SL_INC_sl_WlanRxFilterGet __wln__ext #define _SL_INC_sl_SmartConfigStart __wln #define _SL_INC_sl_SmartConfigOptSet __wln__ext #define _SL_INC_sl_WlanSmartConfigStart __wln #define _SL_INC_sl_WlanSmartConfigStop __wln #define _SL_INC_sl_WlanSetMode __wln #define _SL_INC_sl_WlanSet __wln #define _SL_INC_sl_WlanGet __wln #define _SL_INC_sl_SmartConfigOptSet __wln__ext #define _SL_INC_sl_SmartConfigOptGet __wln__ext #define _SL_INC_sl_WlanRxStatStart __wln__ext #define _SL_INC_sl_WlanRxStatStop __wln__ext #define _SL_INC_sl_WlanRxStatGet __wln__ext /* device */ #define _SL_INC_sl_Task __int__spwn #define _SL_INC_sl_Start __dev #define _SL_INC_sl_Stop __dev #define _SL_INC_sl_StatusGet __dev #ifdef SL_IF_TYPE_UART #define _SL_INC_sl_UartSetMode __dev__ext #endif #define _SL_INC_sl_EventMaskGet __dev__ext #define _SL_INC_sl_EventMaskSet __dev__ext #define _SL_INC_sl_DevGet __dev__ext #define _SL_INC_sl_DevSet __dev__ext #ifdef __cplusplus } #endif /* __cplusplus */ #endif /*OBJINCLUSION_H_ */ micropython-1.12/drivers/cc3100/inc/protocol.h000066400000000000000000001074261357706137100211660ustar00rootroot00000000000000/* * protocol.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*******************************************************************************\ * * FILE NAME: protocol.h * * DESCRIPTION: Constant and data structure definitions and function * prototypes for the SL protocol module, which implements * processing of SimpleLink Commands. * * AUTHOR: * \*******************************************************************************/ #ifndef _SL_PROTOCOL_TYPES_H_ #define _SL_PROTOCOL_TYPES_H_ /**************************************************************************** ** ** User I/F pools definitions ** ****************************************************************************/ /**************************************************************************** ** ** Definitions for SimpleLink Commands ** ****************************************************************************/ /* pattern for LE 8/16/32 or BE*/ #define H2N_SYNC_PATTERN {0xBBDDEEFF,0x4321,0x34,0x12} #define H2N_CNYS_PATTERN {0xBBDDEEFF,0x8765,0x78,0x56} #define H2N_DUMMY_PATTERN (_u32)0xFFFFFFFF #define N2H_SYNC_PATTERN (_u32)0xABCDDCBA #define SYNC_PATTERN_LEN (_u32)sizeof(_u32) #define UART_SET_MODE_MAGIC_CODE (_u32)0xAA55AA55 #define SPI_16BITS_BUG(pattern) (_u32)((_u32)pattern & (_u32)0xFFFF7FFF) #define SPI_8BITS_BUG(pattern) (_u32)((_u32)pattern & (_u32)0xFFFFFF7F) typedef struct { _u16 Opcode; _u16 Len; }_SlGenericHeader_t; typedef struct { _u32 Long; _u16 Short; _u8 Byte1; _u8 Byte2; }_SlSyncPattern_t; typedef _SlGenericHeader_t _SlCommandHeader_t; typedef struct { _SlGenericHeader_t GenHeader; _u8 TxPoolCnt; _u8 DevStatus; _u8 SocketTXFailure; _u8 SocketNonBlocking; }_SlResponseHeader_t; #define _SL_RESP_SPEC_HDR_SIZE (sizeof(_SlResponseHeader_t) - sizeof(_SlGenericHeader_t)) #define _SL_RESP_HDR_SIZE sizeof(_SlResponseHeader_t) #define _SL_CMD_HDR_SIZE sizeof(_SlCommandHeader_t) #define _SL_RESP_ARGS_START(_pMsg) (((_SlResponseHeader_t *)(_pMsg)) + 1) /* Used only in NWP! */ typedef struct { _SlCommandHeader_t sl_hdr; _u8 func_args_start; } T_SCMD; #define WLAN_CONN_STATUS_BIT 0x01 #define EVENTS_Q_STATUS_BIT 0x02 #define PENDING_RCV_CMD_BIT 0x04 #define FW_BUSY_PACKETS_BIT 0x08 #define INIT_STA_OK 0x11111111 #define INIT_STA_ERR 0x22222222 #define INIT_AP_OK 0x33333333 #define INIT_AP_ERR 0x44444444 #define INIT_P2P_OK 0x55555555 #define INIT_P2P_ERR 0x66666666 /**************************************************************************** ** OPCODES ****************************************************************************/ #define SL_IPV4_IPV6_OFFSET ( 9 ) #define SL_OPCODE_IPV4 ( 0x0 << SL_IPV4_IPV6_OFFSET ) #define SL_OPCODE_IPV6 ( 0x1 << SL_IPV4_IPV6_OFFSET ) #define SL_SYNC_ASYNC_OFFSET ( 10 ) #define SL_OPCODE_SYNC (0x1 << SL_SYNC_ASYNC_OFFSET ) #define SL_OPCODE_SILO_OFFSET ( 11 ) #define SL_OPCODE_SILO_MASK ( 0xF << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_DEVICE ( 0x0 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_WLAN ( 0x1 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_SOCKET ( 0x2 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_NETAPP ( 0x3 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_NVMEM ( 0x4 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_NETCFG ( 0x5 << SL_OPCODE_SILO_OFFSET ) #define SL_FAMILY_SHIFT (0x4) #define SL_FLAGS_MASK (0xF) #define SL_OPCODE_DEVICE_INITCOMPLETE 0x0008 #define SL_OPCODE_DEVICE_ABORT 0x000C #define SL_OPCODE_DEVICE_STOP_COMMAND 0x8473 #define SL_OPCODE_DEVICE_STOP_RESPONSE 0x0473 #define SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE 0x0073 #define SL_OPCODE_DEVICE_DEVICEASYNCDUMMY 0x0063 #define SL_OPCODE_DEVICE_VERSIONREADCOMMAND 0x8470 #define SL_OPCODE_DEVICE_VERSIONREADRESPONSE 0x0470 #define SL_OPCODE_DEVICE_DEVICEASYNCFATALERROR 0x0078 #define SL_OPCODE_WLAN_WLANCONNECTCOMMAND 0x8C80 #define SL_OPCODE_WLAN_WLANCONNECTRESPONSE 0x0C80 #define SL_OPCODE_WLAN_WLANASYNCCONNECTEDRESPONSE 0x0880 #define SL_OPCODE_WLAN_P2P_DEV_FOUND 0x0830 #define SL_OPCODE_WLAN_CONNECTION_FAILED 0x0831 #define SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED 0x0832 #define SL_OPCODE_WLAN_WLANDISCONNECTCOMMAND 0x8C81 #define SL_OPCODE_WLAN_WLANDISCONNECTRESPONSE 0x0C81 #define SL_OPCODE_WLAN_WLANASYNCDISCONNECTEDRESPONSE 0x0881 #define SL_OPCODE_WLAN_WLANCONNECTEAPCOMMAND 0x8C82 #define SL_OPCODE_WLAN_WLANCONNECTEAPCRESPONSE 0x0C82 #define SL_OPCODE_WLAN_PROFILEADDCOMMAND 0x8C83 #define SL_OPCODE_WLAN_PROFILEADDRESPONSE 0x0C83 #define SL_OPCODE_WLAN_PROFILEGETCOMMAND 0x8C84 #define SL_OPCODE_WLAN_PROFILEGETRESPONSE 0x0C84 #define SL_OPCODE_WLAN_PROFILEDELCOMMAND 0x8C85 #define SL_OPCODE_WLAN_PROFILEDELRESPONSE 0x0C85 #define SL_OPCODE_WLAN_POLICYSETCOMMAND 0x8C86 #define SL_OPCODE_WLAN_POLICYSETRESPONSE 0x0C86 #define SL_OPCODE_WLAN_POLICYGETCOMMAND 0x8C87 #define SL_OPCODE_WLAN_POLICYGETRESPONSE 0x0C87 #define SL_OPCODE_WLAN_FILTERADD 0x8C88 #define SL_OPCODE_WLAN_FILTERADDRESPONSE 0x0C88 #define SL_OPCODE_WLAN_FILTERGET 0x8C89 #define SL_OPCODE_WLAN_FILTERGETRESPONSE 0x0C89 #define SL_OPCODE_WLAN_FILTERDELETE 0x8C8A #define SL_OPCODE_WLAN_FILTERDELETERESPOSNE 0x0C8A #define SL_OPCODE_WLAN_WLANGETSTATUSCOMMAND 0x8C8F #define SL_OPCODE_WLAN_WLANGETSTATUSRESPONSE 0x0C8F #define SL_OPCODE_WLAN_STARTTXCONTINUESCOMMAND 0x8CAA #define SL_OPCODE_WLAN_STARTTXCONTINUESRESPONSE 0x0CAA #define SL_OPCODE_WLAN_STOPTXCONTINUESCOMMAND 0x8CAB #define SL_OPCODE_WLAN_STOPTXCONTINUESRESPONSE 0x0CAB #define SL_OPCODE_WLAN_STARTRXSTATCOMMAND 0x8CAC #define SL_OPCODE_WLAN_STARTRXSTATRESPONSE 0x0CAC #define SL_OPCODE_WLAN_STOPRXSTATCOMMAND 0x8CAD #define SL_OPCODE_WLAN_STOPRXSTATRESPONSE 0x0CAD #define SL_OPCODE_WLAN_GETRXSTATCOMMAND 0x8CAF #define SL_OPCODE_WLAN_GETRXSTATRESPONSE 0x0CAF #define SL_OPCODE_WLAN_POLICYSETCOMMANDNEW 0x8CB0 #define SL_OPCODE_WLAN_POLICYSETRESPONSENEW 0x0CB0 #define SL_OPCODE_WLAN_POLICYGETCOMMANDNEW 0x8CB1 #define SL_OPCODE_WLAN_POLICYGETRESPONSENEW 0x0CB1 #define SL_OPCODE_WLAN_SMART_CONFIG_START_COMMAND 0x8CB2 #define SL_OPCODE_WLAN_SMART_CONFIG_START_RESPONSE 0x0CB2 #define SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE 0x08B2 #define SL_OPCODE_WLAN_SMART_CONFIG_STOP_COMMAND 0x8CB3 #define SL_OPCODE_WLAN_SMART_CONFIG_STOP_RESPONSE 0x0CB3 #define SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE 0x08B3 #define SL_OPCODE_WLAN_SET_MODE 0x8CB4 #define SL_OPCODE_WLAN_SET_MODE_RESPONSE 0x0CB4 #define SL_OPCODE_WLAN_CFG_SET 0x8CB5 #define SL_OPCODE_WLAN_CFG_SET_RESPONSE 0x0CB5 #define SL_OPCODE_WLAN_CFG_GET 0x8CB6 #define SL_OPCODE_WLAN_CFG_GET_RESPONSE 0x0CB6 #define SL_OPCODE_WLAN_STA_CONNECTED 0x082E #define SL_OPCODE_WLAN_STA_DISCONNECTED 0x082F #define SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND 0x8C67 #define SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND_RESPONSE 0x0C67 #define SL_OPCODE_SOCKET_SOCKET 0x9401 #define SL_OPCODE_SOCKET_SOCKETRESPONSE 0x1401 #define SL_OPCODE_SOCKET_CLOSE 0x9402 #define SL_OPCODE_SOCKET_CLOSERESPONSE 0x1402 #define SL_OPCODE_SOCKET_ACCEPT 0x9403 #define SL_OPCODE_SOCKET_ACCEPTRESPONSE 0x1403 #define SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE 0x1003 #define SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 0x1203 #define SL_OPCODE_SOCKET_BIND 0x9404 #define SL_OPCODE_SOCKET_BIND_V6 0x9604 #define SL_OPCODE_SOCKET_BINDRESPONSE 0x1404 #define SL_OPCODE_SOCKET_LISTEN 0x9405 #define SL_OPCODE_SOCKET_LISTENRESPONSE 0x1405 #define SL_OPCODE_SOCKET_CONNECT 0x9406 #define SL_OPCODE_SOCKET_CONNECT_V6 0x9606 #define SL_OPCODE_SOCKET_CONNECTRESPONSE 0x1406 #define SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE 0x1006 #define SL_OPCODE_SOCKET_SELECT 0x9407 #define SL_OPCODE_SOCKET_SELECTRESPONSE 0x1407 #define SL_OPCODE_SOCKET_SELECTASYNCRESPONSE 0x1007 #define SL_OPCODE_SOCKET_SETSOCKOPT 0x9408 #define SL_OPCODE_SOCKET_SETSOCKOPTRESPONSE 0x1408 #define SL_OPCODE_SOCKET_GETSOCKOPT 0x9409 #define SL_OPCODE_SOCKET_GETSOCKOPTRESPONSE 0x1409 #define SL_OPCODE_SOCKET_RECV 0x940A #define SL_OPCODE_SOCKET_RECVASYNCRESPONSE 0x100A #define SL_OPCODE_SOCKET_RECVFROM 0x940B #define SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE 0x100B #define SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 0x120B #define SL_OPCODE_SOCKET_SEND 0x940C #define SL_OPCODE_SOCKET_SENDTO 0x940D #define SL_OPCODE_SOCKET_SENDTO_V6 0x960D #define SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE 0x100E #define SL_OPCODE_SOCKET_SOCKETASYNCEVENT 0x100F #define SL_OPCODE_NETAPP_START_COMMAND 0x9C0A #define SL_OPCODE_NETAPP_START_RESPONSE 0x1C0A #define SL_OPCODE_NETAPP_NETAPPSTARTRESPONSE 0x1C0A #define SL_OPCODE_NETAPP_STOP_COMMAND 0x9C61 #define SL_OPCODE_NETAPP_STOP_RESPONSE 0x1C61 #define SL_OPCODE_NETAPP_NETAPPSET 0x9C0B #define SL_OPCODE_NETAPP_NETAPPSETRESPONSE 0x1C0B #define SL_OPCODE_NETAPP_NETAPPGET 0x9C27 #define SL_OPCODE_NETAPP_NETAPPGETRESPONSE 0x1C27 #define SL_OPCODE_NETAPP_DNSGETHOSTBYNAME 0x9C20 #define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMERESPONSE 0x1C20 #define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE 0x1820 #define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE_V6 0x1A20 #define SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE 0x9C71 #define SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE_RESPONSE 0x1C72 #define SL_OPCODE_NETAPP_MDNSREGISTERSERVICE 0x9C34 #define SL_OPCODE_NETAPP_MDNSREGISTERSERVICERESPONSE 0x1C34 #define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICE 0x9C35 #define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICERESPONSE 0x1C35 #define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE 0x1835 #define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE_V6 0x1A35 #define SL_OPCODE_NETAPP_DNSGETHOSTBYADDR 0x9C26 #define SL_OPCODE_NETAPP_DNSGETHOSTBYADDR_V6 0x9E26 #define SL_OPCODE_NETAPP_DNSGETHOSTBYADDRRESPONSE 0x1C26 #define SL_OPCODE_NETAPP_DNSGETHOSTBYADDRASYNCRESPONSE 0x1826 #define SL_OPCODE_NETAPP_PINGSTART 0x9C21 #define SL_OPCODE_NETAPP_PINGSTART_V6 0x9E21 #define SL_OPCODE_NETAPP_PINGSTARTRESPONSE 0x1C21 #define SL_OPCODE_NETAPP_PINGREPORTREQUEST 0x9C22 #define SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE 0x1822 #define SL_OPCODE_NETAPP_PINGSTOP 0x9C23 #define SL_OPCODE_NETAPP_PINGSTOPRESPONSE 0x1C23 #define SL_OPCODE_NETAPP_ARPFLUSH 0x9C24 #define SL_OPCODE_NETAPP_ARPFLUSHRESPONSE 0x1C24 #define SL_OPCODE_NETAPP_IPACQUIRED 0x1825 #define SL_OPCODE_NETAPP_IPV4_LOST 0x1832 #define SL_OPCODE_NETAPP_DHCP_IPV4_ACQUIRE_TIMEOUT 0x1833 #define SL_OPCODE_NETAPP_IPACQUIRED_V6 0x1A25 #define SL_OPCODE_NETAPP_IPERFSTARTCOMMAND 0x9C28 #define SL_OPCODE_NETAPP_IPERFSTARTRESPONSE 0x1C28 #define SL_OPCODE_NETAPP_IPERFSTOPCOMMAND 0x9C29 #define SL_OPCODE_NETAPP_IPERFSTOPRESPONSE 0x1C29 #define SL_OPCODE_NETAPP_CTESTSTARTCOMMAND 0x9C2A #define SL_OPCODE_NETAPP_CTESTSTARTRESPONSE 0x1C2A #define SL_OPCODE_NETAPP_CTESTASYNCRESPONSE 0x182A #define SL_OPCODE_NETAPP_CTESTSTOPCOMMAND 0x9C2B #define SL_OPCODE_NETAPP_CTESTSTOPRESPONSE 0x1C2B #define SL_OPCODE_NETAPP_IP_LEASED 0x182C #define SL_OPCODE_NETAPP_IP_RELEASED 0x182D #define SL_OPCODE_NETAPP_HTTPGETTOKENVALUE 0x182E #define SL_OPCODE_NETAPP_HTTPSENDTOKENVALUE 0x9C2F #define SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE 0x1830 #define SL_OPCODE_NVMEM_FILEOPEN 0xA43C #define SL_OPCODE_NVMEM_FILEOPENRESPONSE 0x243C #define SL_OPCODE_NVMEM_FILECLOSE 0xA43D #define SL_OPCODE_NVMEM_FILECLOSERESPONSE 0x243D #define SL_OPCODE_NVMEM_FILEREADCOMMAND 0xA440 #define SL_OPCODE_NVMEM_FILEREADRESPONSE 0x2440 #define SL_OPCODE_NVMEM_FILEWRITECOMMAND 0xA441 #define SL_OPCODE_NVMEM_FILEWRITERESPONSE 0x2441 #define SL_OPCODE_NVMEM_FILEGETINFOCOMMAND 0xA442 #define SL_OPCODE_NVMEM_FILEGETINFORESPONSE 0x2442 #define SL_OPCODE_NVMEM_FILEDELCOMMAND 0xA443 #define SL_OPCODE_NVMEM_FILEDELRESPONSE 0x2443 #define SL_OPCODE_NVMEM_NVMEMFORMATCOMMAND 0xA444 #define SL_OPCODE_NVMEM_NVMEMFORMATRESPONSE 0x2444 #define SL_OPCODE_DEVICE_SETDEBUGLEVELCOMMAND 0x846A #define SL_OPCODE_DEVICE_SETDEBUGLEVELRESPONSE 0x046A #define SL_OPCODE_DEVICE_NETCFG_SET_COMMAND 0x8432 #define SL_OPCODE_DEVICE_NETCFG_SET_RESPONSE 0x0432 #define SL_OPCODE_DEVICE_NETCFG_GET_COMMAND 0x8433 #define SL_OPCODE_DEVICE_NETCFG_GET_RESPONSE 0x0433 /* */ #define SL_OPCODE_DEVICE_SETUARTMODECOMMAND 0x846B #define SL_OPCODE_DEVICE_SETUARTMODERESPONSE 0x046B #define SL_OPCODE_DEVICE_SSISIZESETCOMMAND 0x846B #define SL_OPCODE_DEVICE_SSISIZESETRESPONSE 0x046B /* */ #define SL_OPCODE_DEVICE_EVENTMASKSET 0x8464 #define SL_OPCODE_DEVICE_EVENTMASKSETRESPONSE 0x0464 #define SL_OPCODE_DEVICE_EVENTMASKGET 0x8465 #define SL_OPCODE_DEVICE_EVENTMASKGETRESPONSE 0x0465 #define SL_OPCODE_DEVICE_DEVICEGET 0x8466 #define SL_OPCODE_DEVICE_DEVICEGETRESPONSE 0x0466 #define SL_OPCODE_DEVICE_DEVICESET 0x84B7 #define SL_OPCODE_DEVICE_DEVICESETRESPONSE 0x04B7 #define SL_OPCODE_WLAN_SCANRESULTSGETCOMMAND 0x8C8C #define SL_OPCODE_WLAN_SCANRESULTSGETRESPONSE 0x0C8C #define SL_OPCODE_WLAN_SMARTCONFIGOPTSET 0x8C8D #define SL_OPCODE_WLAN_SMARTCONFIGOPTSETRESPONSE 0x0C8D #define SL_OPCODE_WLAN_SMARTCONFIGOPTGET 0x8C8E #define SL_OPCODE_WLAN_SMARTCONFIGOPTGETRESPONSE 0x0C8E /* Rx Filters opcodes */ #define SL_OPCODE_WLAN_WLANRXFILTERADDCOMMAND 0x8C6C #define SL_OPCODE_WLAN_WLANRXFILTERADDRESPONSE 0x0C6C #define SL_OPCODE_WLAN_WLANRXFILTERSETCOMMAND 0x8C6D #define SL_OPCODE_WLAN_WLANRXFILTERSETRESPONSE 0x0C6D #define SL_OPCODE_WLAN_WLANRXFILTERGETSTATISTICSINFOCOMMAND 0x8C6E #define SL_OPCODE_WLAN_WLANRXFILTERGETSTATISTICSINFORESPONSE 0x0C6E #define SL_OPCODE_WLAN_WLANRXFILTERGETCOMMAND 0x8C6F #define SL_OPCODE_WLAN_WLANRXFILTERGETRESPONSE 0x0C6F #define SL_OPCODE_WLAN_WLANRXFILTERGETINFO 0x8C70 #define SL_OPCODE_WLAN_WLANRXFILTERGETINFORESPONSE 0x0C70 /******************************************************************************************/ /* Device structs */ /******************************************************************************************/ typedef _u32 InitStatus_t; typedef struct { _i32 Status; }InitComplete_t; typedef struct { _i16 status; _u16 padding; }_BasicResponse_t; typedef struct { _u16 Timeout; _u16 padding; }_DevStopCommand_t; typedef struct { _u32 group; _u32 mask; }_DevMaskEventSetCommand_t; typedef _BasicResponse_t _DevMaskEventSetResponse_t; typedef struct { _u32 group; }_DevMaskEventGetCommand_t; typedef struct { _u32 group; _u32 mask; }_DevMaskEventGetResponse_t; typedef struct { _u32 group; }_DevStatusGetCommand_t; typedef struct { _u32 group; _u32 status; }_DevStatusGetResponse_t; typedef struct { _u32 ChipId; _u32 FwVersion[4]; _u8 PhyVersion[4]; }_Device_VersionReadResponsePart_t; typedef struct { _Device_VersionReadResponsePart_t part; _u32 NwpVersion[4]; _u16 RomVersion; _u16 Padding; }_Device_VersionReadResponseFull_t; typedef struct { _u32 BaudRate; _u8 FlowControlEnable; }_DevUartSetModeCommand_t; typedef _BasicResponse_t _DevUartSetModeResponse_t; /******************************************************/ typedef struct { _u8 SsiSizeInBytes; _u8 Padding[3]; }_StellarisSsiSizeSet_t; /*****************************************************************************************/ /* WLAN structs */ /*****************************************************************************************/ #define MAXIMAL_PASSWORD_LENGTH (64) typedef struct{ _u8 SecType; _u8 SsidLen; _u8 Bssid[6]; _u8 PasswordLen; }_WlanConnectCommon_t; #define SSID_STRING(pCmd) (_i8 *)((_WlanConnectCommon_t *)(pCmd) + 1) #define PASSWORD_STRING(pCmd) (SSID_STRING(pCmd) + ((_WlanConnectCommon_t *)(pCmd))->SsidLen) typedef struct{ _WlanConnectCommon_t Common; _u8 UserLen; _u8 AnonUserLen; _u8 CertIndex; _u32 EapBitmask; }_WlanConnectEapCommand_t; #define EAP_SSID_STRING(pCmd) (_i8 *)((_WlanConnectEapCommand_t *)(pCmd) + 1) #define EAP_PASSWORD_STRING(pCmd) (EAP_SSID_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->Common.SsidLen) #define EAP_USER_STRING(pCmd) (EAP_PASSWORD_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->Common.PasswordLen) #define EAP_ANON_USER_STRING(pCmd) (EAP_USER_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->UserLen) typedef struct { _u8 PolicyType; _u8 Padding; _u8 PolicyOption; _u8 PolicyOptionLen; }_WlanPoliciySetGet_t; typedef struct{ _u32 minDwellTime; _u32 maxDwellTime; _u32 numProbeResponse; _u32 G_Channels_mask; _i32 rssiThershold; _i32 snrThershold; _i32 defaultTXPower; _u16 intervalList[16]; }_WlanScanParamSetCommand_t; typedef struct{ _i8 SecType; _u8 SsidLen; _u8 Priority; _u8 Bssid[6]; _u8 PasswordLen; _u8 WepKeyId; }_WlanAddGetProfile_t; typedef struct{ _WlanAddGetProfile_t Common; _u8 UserLen; _u8 AnonUserLen; _u8 CertIndex; _u16 padding; _u32 EapBitmask; }_WlanAddGetEapProfile_t; #define PROFILE_SSID_STRING(pCmd) ((_i8 *)((_WlanAddGetProfile_t *)(pCmd) + 1)) #define PROFILE_PASSWORD_STRING(pCmd) (PROFILE_SSID_STRING(pCmd) + ((_WlanAddGetProfile_t *)(pCmd))->SsidLen) #define EAP_PROFILE_SSID_STRING(pCmd) (_i8 *)((_WlanAddGetEapProfile_t *)(pCmd) + 1) #define EAP_PROFILE_PASSWORD_STRING(pCmd) (EAP_PROFILE_SSID_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->Common.SsidLen) #define EAP_PROFILE_USER_STRING(pCmd) (EAP_PROFILE_PASSWORD_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->Common.PasswordLen) #define EAP_PROFILE_ANON_USER_STRING(pCmd) (EAP_PROFILE_USER_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->UserLen) typedef struct { _u8 index; _u8 padding[3]; }_WlanProfileDelGetCommand_t; typedef _BasicResponse_t _WlanGetNetworkListResponse_t; typedef struct { _u8 index; _u8 count; _i8 padding[2]; }_WlanGetNetworkListCommand_t; typedef struct { _u32 groupIdBitmask; _u8 cipher; _u8 publicKeyLen; _u8 group1KeyLen; _u8 group2KeyLen; }_WlanSmartConfigStartCommand_t; #define SMART_CONFIG_START_PUBLIC_KEY_STRING(pCmd) ((_i8 *)((_WlanSmartConfigStartCommand_t *)(pCmd) + 1)) #define SMART_CONFIG_START_GROUP1_KEY_STRING(pCmd) ((_i8 *) (SMART_CONFIG_START_PUBLIC_KEY_STRING(pCmd) + ((_WlanSmartConfigStartCommand_t *)(pCmd))->publicKeyLen)) #define SMART_CONFIG_START_GROUP2_KEY_STRING(pCmd) ((_i8 *) (SMART_CONFIG_START_GROUP1_KEY_STRING(pCmd) + ((_WlanSmartConfigStartCommand_t *)(pCmd))->group1KeyLen)) typedef struct { _u8 mode; _u8 padding[3]; }_WlanSetMode_t; typedef struct { _u16 Status; _u16 ConfigId; _u16 ConfigOpt; _u16 ConfigLen; }_WlanCfgSetGet_t; /* ******************************************************************************/ /* RX filters - Start */ /* ******************************************************************************/ /* -- 80 bytes */ typedef struct _WlanRxFilterAddCommand_t { /* -- 1 byte */ SlrxFilterRuleType_t RuleType; /* -- 1 byte */ SlrxFilterFlags_t FilterFlags; /* -- 1 byte */ SlrxFilterID_t FilterId; /* -- 1 byte */ _u8 Padding; /* -- 56 byte */ SlrxFilterRule_t Rule; /* -- 12 byte ( 3 padding ) */ SlrxFilterTrigger_t Trigger; /* -- 8 byte */ SlrxFilterAction_t Action; }_WlanRxFilterAddCommand_t; /* -- 4 bytes */ typedef struct l_WlanRxFilterAddCommandReponse_t { /* -- 1 byte */ SlrxFilterID_t FilterId; /* -- 1 Byte */ _u8 Status; /* -- 2 byte */ _u8 Padding[2]; }_WlanRxFilterAddCommandReponse_t; /* * \struct _WlanRxFilterSetCommand_t */ typedef struct _WlanRxFilterSetCommand_t { _u16 InputBufferLength; /* 1 byte */ SLrxFilterOperation_t RxFilterOperation; _u8 Padding[1]; }_WlanRxFilterSetCommand_t; /** * \struct _WlanRxFilterSetCommandReponse_t */ typedef struct _WlanRxFilterSetCommandReponse_t { /* 1 byte */ _u8 Status; /* 3 bytes */ _u8 Padding[3]; }_WlanRxFilterSetCommandReponse_t; /** * \struct _WlanRxFilterGetCommand_t */ typedef struct _WlanRxFilterGetCommand_t { _u16 OutputBufferLength; /* 1 byte */ SLrxFilterOperation_t RxFilterOperation; _u8 Padding[1]; }_WlanRxFilterGetCommand_t; /** * \struct _WlanRxFilterGetCommandReponse_t */ typedef struct _WlanRxFilterGetCommandReponse_t { /* 1 byte */ _u8 Status; /* 1 bytes */ _u8 Padding; /* 2 byte */ _u16 OutputBufferLength; }_WlanRxFilterGetCommandReponse_t; /* ******************************************************************************/ /* RX filters -- End */ /* ******************************************************************************/ typedef struct { _u16 status; _u8 WlanRole; /* 0 = station, 2 = AP */ _u8 Ipv6Enabled; _u8 Ipv6DhcpEnabled; _u32 ipV6Global[4]; _u32 ipV6Local[4]; _u32 ipV6DnsServer[4]; _u8 Ipv6DhcpState; }_NetappIpV6configRetArgs_t; typedef struct { _u8 ipV4[4]; _u8 ipV4Mask[4]; _u8 ipV4Gateway[4]; _u8 ipV4DnsServer[4]; _u8 ipV4Start[4]; _u8 ipV4End[4]; }_NetCfgIpV4AP_Args_t; typedef struct { _u16 status; _u8 MacAddr[6]; } _MAC_Address_SetGet_t; typedef struct { _u16 Status; _u16 ConfigId; _u16 ConfigOpt; _u16 ConfigLen; }_NetCfgSetGet_t; typedef struct { _u16 Status; _u16 DeviceSetId; _u16 Option; _u16 ConfigLen; }_DeviceSetGet_t; /******************************************************************************************/ /* Socket structs */ /******************************************************************************************/ typedef struct { _u8 Domain; _u8 Type; _u8 Protocol; _u8 Padding; }_SocketCommand_t; typedef struct { _i16 statusOrLen; _u8 sd; _u8 padding; }_SocketResponse_t; typedef struct { _u8 sd; _u8 family; _u8 padding1; _u8 padding2; }_AcceptCommand_t; typedef struct { _i16 statusOrLen; _u8 sd; _u8 family; _u16 port; _u16 paddingOrAddr; _u32 address; }_SocketAddrAsyncIPv4Response_t; typedef struct { _i16 statusOrLen; _u8 sd; _u8 family; _u16 port; _u8 address[6]; }_SocketAddrAsyncIPv6EUI48Response_t; typedef struct { _i16 statusOrLen; _u8 sd; _u8 family; _u16 port; _u16 paddingOrAddr; _u32 address[4]; }_SocketAddrAsyncIPv6Response_t; typedef struct { _i16 lenOrPadding; _u8 sd; _u8 FamilyAndFlags; _u16 port; _u16 paddingOrAddr; _u32 address; }_SocketAddrIPv4Command_t; typedef struct { _i16 lenOrPadding; _u8 sd; _u8 FamilyAndFlags; _u16 port; _u8 address[6]; }_SocketAddrIPv6EUI48Command_t; typedef struct { _i16 lenOrPadding; _u8 sd; _u8 FamilyAndFlags; _u16 port; _u16 paddingOrAddr; _u32 address[4]; }_SocketAddrIPv6Command_t; typedef union { _SocketAddrIPv4Command_t IpV4; _SocketAddrIPv6EUI48Command_t IpV6EUI48; #ifdef SL_SUPPORT_IPV6 _SocketAddrIPv6Command_t IpV6; #endif } _SocketAddrCommand_u; typedef union { _SocketAddrAsyncIPv4Response_t IpV4; _SocketAddrAsyncIPv6EUI48Response_t IpV6EUI48; #ifdef SL_SUPPORT_IPV6 _SocketAddrAsyncIPv6Response_t IpV6; #endif } _SocketAddrResponse_u; typedef struct { _u8 sd; _u8 backlog; _u8 padding1; _u8 padding2; }_ListenCommand_t; typedef struct { _u8 sd; _u8 padding0; _u8 padding1; _u8 padding2; }_CloseCommand_t; typedef struct { _u8 nfds; _u8 readFdsCount; _u8 writeFdsCount; _u8 padding; _u16 readFds; _u16 writeFds; _u16 tv_usec; _u16 tv_sec; }_SelectCommand_t; typedef struct { _u16 status; _u8 readFdsCount; _u8 writeFdsCount; _u16 readFds; _u16 writeFds; }_SelectAsyncResponse_t; typedef struct { _u8 sd; _u8 level; _u8 optionName; _u8 optionLen; }_setSockOptCommand_t; typedef struct { _u8 sd; _u8 level; _u8 optionName; _u8 optionLen; }_getSockOptCommand_t; typedef struct { _i16 status; _u8 sd; _u8 optionLen; }_getSockOptResponse_t; typedef struct { _u16 StatusOrLen; _u8 sd; _u8 FamilyAndFlags; }_sendRecvCommand_t; /***************************************************************************************** * NETAPP structs ******************************************************************************************/ typedef _BasicResponse_t _NetAppStartStopResponse_t; typedef struct { _u32 appId; }_NetAppStartStopCommand_t; typedef struct { _u16 Status; _u16 AppId; _u16 ConfigOpt; _u16 ConfigLen; }_NetAppSetGet_t; typedef struct { _u16 port_number; } _NetAppHttpServerGetSet_port_num_t; typedef struct { _u8 auth_enable; }_NetAppHttpServerGetSet_auth_enable_t; typedef struct _sl_NetAppHttpServerGetToken_t { _u8 token_name_len; _u8 padd1; _u16 padd2; }sl_NetAppHttpServerGetToken_t; typedef struct _sl_NetAppHttpServerSendToken_t { _u8 token_value_len; _u8 token_name_len; _u8 token_name[MAX_TOKEN_NAME_LEN]; _u16 padd; }sl_NetAppHttpServerSendToken_t; typedef struct _sl_NetAppHttpServerPostToken_t { _u8 post_action_len; _u8 token_name_len; _u8 token_value_len; _u8 padding; }sl_NetAppHttpServerPostToken_t; typedef struct { _u16 Len; _u8 family; _u8 padding; }_GetHostByNameCommand_t; typedef struct { _u16 status; _u16 padding; _u32 ip0; _u32 ip1; _u32 ip2; _u32 ip3; }_GetHostByNameIPv6AsyncResponse_t; typedef struct { _u16 status; _u8 padding1; _u8 padding2; _u32 ip0; }_GetHostByNameIPv4AsyncResponse_t; typedef enum { CTST_BSD_UDP_TX, CTST_BSD_UDP_RX, CTST_BSD_TCP_TX, CTST_BSD_TCP_RX, CTST_BSD_TCP_SERVER_BI_DIR, CTST_BSD_TCP_CLIENT_BI_DIR, CTST_BSD_UDP_BI_DIR, CTST_BSD_RAW_TX, CTST_BSD_RAW_RX, CTST_BSD_RAW_BI_DIR, CTST_BSD_SECURED_TCP_TX, CTST_BSD_SECURED_TCP_RX, CTST_BSD_SECURED_TCP_SERVER_BI_DIR, CTST_BSD_SECURED_TCP_CLIENT_BI_DIR }CommTest_e; typedef struct _sl_protocol_CtestStartCommand_t { _u32 Test; _u16 DestPort; _u16 SrcPort; _u32 DestAddr[4]; _u32 PayloadSize; _u32 timeout; _u32 csEnabled; _u32 secure; _u32 rawProtocol; _u8 reserved1[4]; }_CtestStartCommand_t; typedef struct { _u8 test; _u8 socket; _i16 status; _u32 startTime; _u32 endTime; _u16 txKbitsSec; _u16 rxKbitsSec; _u32 outOfOrderPackets; _u32 missedPackets; _i16 token; }_CtestAsyncResponse_t; typedef struct { _u32 pingIntervalTime; _u16 PingSize; _u16 pingRequestTimeout; _u32 totalNumberOfAttempts; _u32 flags; _u32 ip0; _u32 ip1OrPaadding; _u32 ip2OrPaadding; _u32 ip3OrPaadding; }_PingStartCommand_t; typedef struct { _u16 status; _u16 rttMin; _u16 rttMax; _u16 rttAvg; _u32 numSuccsessPings; _u32 numSendsPings; _u32 testTime; }_PingReportResponse_t; typedef struct { _u32 ip; _u32 gateway; _u32 dns; }_IpV4AcquiredAsync_t; typedef enum { ACQUIRED_IPV6_LOCAL = 1, ACQUIRED_IPV6_GLOBAL }IpV6AcquiredType_e; typedef struct { _u32 type; _u32 ip[4]; _u32 gateway[4]; _u32 dns[4]; }_IpV6AcquiredAsync_t; typedef union { _SocketCommand_t EventMask; _sendRecvCommand_t DeviceInit; }_device_commands_t; /***************************************************************************************** * FS structs ******************************************************************************************/ typedef struct { _u32 FileHandle; _u32 Offset; _u16 Len; _u16 Padding; }_FsReadCommand_t; typedef struct { _u32 Mode; _u32 Token; }_FsOpenCommand_t; typedef struct { _u32 FileHandle; _u32 Token; }_FsOpenResponse_t; typedef struct { _u32 FileHandle; _u32 CertificFileNameLength; _u32 SignatureLen; }_FsCloseCommand_t; typedef _BasicResponse_t _FsReadResponse_t; typedef _BasicResponse_t _FsDeleteResponse_t; typedef _BasicResponse_t _FsCloseResponse_t; typedef struct { _u16 Status; _u16 flags; _u32 FileLen; _u32 AllocatedLen; _u32 Token[4]; }_FsGetInfoResponse_t; typedef struct { _u8 DeviceID; _u8 Padding[3]; }_FsFormatCommand_t; typedef _BasicResponse_t _FsFormatResponse_t; typedef struct { _u32 Token; }_FsDeleteCommand_t; typedef _FsDeleteCommand_t _FsGetInfoCommand_t; typedef struct { _u32 FileHandle; _u32 Offset; _u16 Len; _u16 Padding; }_FsWriteCommand_t; typedef _BasicResponse_t _FsWriteResponse_t; /* TODO: Set MAx Async Payload length depending on flavor (Tiny, Small, etc.) */ #ifdef SL_TINY_EXT #define SL_ASYNC_MAX_PAYLOAD_LEN 120 /* size must be aligned to 4 */ #else #define SL_ASYNC_MAX_PAYLOAD_LEN 160 /* size must be aligned to 4 */ #endif #define SL_ASYNC_MAX_MSG_LEN (_SL_RESP_HDR_SIZE + SL_ASYNC_MAX_PAYLOAD_LEN) #define RECV_ARGS_SIZE (sizeof(_SocketResponse_t)) #define RECVFROM_IPV4_ARGS_SIZE (sizeof(_SocketAddrAsyncIPv4Response_t)) #define RECVFROM_IPV6_ARGS_SIZE (sizeof(_SocketAddrAsyncIPv6Response_t)) #define SL_IPV4_ADDRESS_SIZE (sizeof(_u32)) #define SL_IPV6_ADDRESS_SIZE (4 * sizeof(_u32)) #endif /* _SL_PROTOCOL_TYPES_H_ */ micropython-1.12/drivers/cc3100/inc/simplelink.h000066400000000000000000001052161357706137100214670ustar00rootroot00000000000000/* * simplelink.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*! \mainpage SimpleLink Driver \section intro_sec Introduction The SimpleLink CC31xx/CC2xx family allows to add Wi-Fi and networking capabilities to low-cost embedded products without having prior Wi-Fi, RF or networking expertise. The CC31xx/CC32xx is an ideal solution for microcontroller-based sensor and control applications such as home appliances, home automation and smart metering. The CC31xx/CC32xx has integrated a comprehensive TCP/IP network stack, Wi-Fi driver and security supplicant leading to easier portability to microcontrollers, to an ultra-low memory footprint, all without compromising the capabilities and robustness of the final application. \section modules_sec Module Names To make it simple, TI's SimpleLink CC31xx/CC32xx platform capabilities were divided into modules by topic (Silo). These capabilities range from basic device management through wireless network configuration, standard BSD socket and much more. Listed below are the various modules in the SimpleLink CC31xx/CC32xx driver: -# \ref device - controls the behaviour of the CC31xx/CC32xx device (start/stop, events masking and obtaining specific device status) -# \ref wlan - controls the use of the WiFi WLAN module including: - Connection features, such as: profiles, policies, SmartConfig� - Advanced WLAN features, such as: scans, rx filters and rx statistics collection -# \ref socket - controls standard client/server sockets programming options and capabilities -# \ref netapp - activates networking applications, such as: HTTP Server, DHCP Server, Ping, DNS and mDNS. -# \ref netcfg - controls the configuration of the device addresses (i.e. IP and MAC addresses) -# \ref FileSystem - provides file system capabilities to TI's CC31XX that can be used by both the CC31XX device and the user. \section proting_sec Porting Guide The porting of the SimpleLink driver to any new platform is based on few simple steps. This guide takes you through this process step by step. Please follow the instructions carefully to avoid any problems during this process and to enable efficient and proper work with the device. Please notice that all modifications and porting adjustments of the driver should be made in the user.h header file only. Keep making any of the changes only in this file will ensure smoothly transaction to new versions of the driver at the future! \subsection porting_step1 Step 1 - Create your own user.h file The first step is to create a user.h file that will include your configurations and adjustments. You can use the empty template provided as part of this driver or you can choose to base your file on file from one of the wide range of examples applications provided by Texas Instruments \subsection porting_step2 Step 2 - Select the capabilities set required for your application Texas Instruments made a lot of efforts to build set of predefined capability sets that would fit most of the target application. It is recommended to try and choose one of this predefined capabilities set before going to build your own customized set. If you find compatible set you can skip the rest of this step. The available sets are: -# SL_TINY - Compatible to be used on platforms with very limited resources. Provides the best in class foot print in terms of Code and Data consumption. -# SL_SMALL - Compatible to most common networking applications. Provide the most common APIs with decent balance between code size, data size, functionality and performances -# SL_FULL - Provide access to all SimpleLink functionalities \subsection porting_step3 Step 3 - Bind the device enable/disable output line The enable/disable line (nHib) provide mechanism to enter the device into the least current consumption mode. This mode could be used when no traffic is required (tx/rx). when this line is not connected to any IO of the host this define should be left empty. Not connecting this line results in ability to start the driver only once. \subsection porting_step4 Step 4 - Writing your interface communication driver The SimpleLink device support several standard communication protocol among SPI and UART. Depending on your needs and your hardware design, you should choose the communication channel type. The interface for this communication channel should include 4 simple access functions: -# open -# close -# read -# write The way this driver would be implemented is directly effecting the efficiency and the performances of the SimpleLink device on this platform. If your system has DMA you should consider to use it in order to increase the utilization of the communication channel If you have enough memory resources you should consider using a buffer to increase the efficiency of the write operations. \subsection porting_step5 Step 5 - Choose your memory management model The SimpleLink driver support two memory models: -# Static (default) -# Dynamic If you choose to work in dynamic model you will have to provide alloc and free functions to be used by the Simple Link driver otherwise nothing need to be done. \subsection porting_step6 Step 6 - OS adaptation The SimpleLink driver could run on two kind of platforms: -# Non-Os / Single Threaded (default) -# Multi-Threaded If you choose to work in multi-threaded environment under operating system you will have to provide some basic adaptation routines to allow the driver to protect access to resources for different threads (locking object) and to allow synchronization between threads (sync objects). In additional the driver support running without dedicated thread allocated solely to the simple link driver. If you choose to work in this mode, you should also supply a spawn method that will enable to run function on a temporary context. \subsection porting_step7 Step 7 - Set your asynchronous event handlers routines The SimpleLink device generate asynchronous events in several situations. These asynchronous events could be masked. In order to catch these events you have to provide handler routines. Please notice that if you not provide a handler routine and the event is received, the driver will drop this event without any indication of this drop. \subsection porting_step8 Step 8 - Run diagnostic tools to validate the correctness of your porting The driver is delivered with some porting diagnostic tools to simplify the porting validation process and to reduce issues latter. It is very important to follow carefully this process. The diagnostic process include: -# Validating Interface Communication Driver -# Validating OS adaptation layer -# Validating HW integrity -# Validating basic work with the device \section sw_license License * * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __SIMPLELINK_H__ #define __SIMPLELINK_H__ #include "user.h" #ifdef __cplusplus extern "C" { #endif /*! \attention Async event activation notes Function prototypes for event callback handlers Event handler function names should be defined in the user.h file e.g. "#define sl_WlanEvtHdlr SLWlanEventHandler" Indicates all WLAN events are handled by User func "SLWlanEventHandler" Important notes: 1. Event handlers cannot activate another SimpleLink API from the event's context 2. Event's data is valid during event's context. Any application data which is required for the user application should be copied or marked into user's variables 3. It is not recommended to delay the execution of the event callback handler */ /*! \addtogroup UserEvents @{ */ /*****************************************************************************/ /* Macro declarations for Host Driver version */ /*****************************************************************************/ #define SL_DRIVER_VERSION "1.0.0.10" #define SL_MAJOR_VERSION_NUM 1L #define SL_MINOR_VERSION_NUM 0L #define SL_VERSION_NUM 0L #define SL_SUB_VERSION_NUM 10L /*****************************************************************************/ /* Macro declarations for predefined configurations */ /*****************************************************************************/ #ifdef SL_TINY #undef SL_INC_ARG_CHECK #undef SL_INC_EXT_API #undef SL_INC_SOCK_SERVER_SIDE_API #undef SL_INC_WLAN_PKG #undef SL_INC_NET_CFG_PKG #undef SL_INC_FS_PKG #undef SL_INC_SET_UART_MODE #undef SL_INC_STD_BSD_API_NAMING #undef SL_INC_SOCK_CLIENT_SIDE_API #undef SL_INC_NET_APP_PKG #undef SL_INC_SOCK_RECV_API #undef SL_INC_SOCK_SEND_API #undef SL_INC_SOCKET_PKG #endif #ifdef SL_SMALL #undef SL_INC_EXT_API #undef SL_INC_NET_APP_PKG #undef SL_INC_NET_CFG_PKG #undef SL_INC_FS_PKG #define SL_INC_ARG_CHECK #define SL_INC_WLAN_PKG #define SL_INC_SOCKET_PKG #define SL_INC_SOCK_CLIENT_SIDE_API #define SL_INC_SOCK_SERVER_SIDE_API #define SL_INC_SOCK_RECV_API #define SL_INC_SOCK_SEND_API #define SL_INC_SET_UART_MODE #endif #ifdef SL_FULL #define SL_INC_EXT_API #define SL_INC_NET_APP_PKG #define SL_INC_NET_CFG_PKG #define SL_INC_FS_PKG #define SL_INC_ARG_CHECK #define SL_INC_WLAN_PKG #define SL_INC_SOCKET_PKG #define SL_INC_SOCK_CLIENT_SIDE_API #define SL_INC_SOCK_SERVER_SIDE_API #define SL_INC_SOCK_RECV_API #define SL_INC_SOCK_SEND_API #define SL_INC_SET_UART_MODE #endif #define SL_RET_CODE_OK (0) #define SL_RET_CODE_INVALID_INPUT (-2) #define SL_RET_CODE_SELF_ERROR (-3) #define SL_RET_CODE_NWP_IF_ERROR (-4) #define SL_RET_CODE_MALLOC_ERROR (-5) #define sl_Memcpy memcpy #define sl_Memset memset #define sl_SyncObjClear(pObj) sl_SyncObjWait(pObj,SL_OS_NO_WAIT) #ifndef SL_TINY_EXT #define SL_MAX_SOCKETS (8) #else #define SL_MAX_SOCKETS (2) #endif /*****************************************************************************/ /* Types definitions */ /*****************************************************************************/ typedef void (*_SlSpawnEntryFunc_t)(void* pValue); #ifndef NULL #define NULL (0) #endif #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #ifndef OK #define OK (0) #endif #ifndef _SL_USER_TYPES typedef unsigned char _u8; typedef signed char _i8; typedef unsigned short _u16; typedef signed short _i16; typedef unsigned long _u32; typedef signed long _i32; #define _volatile volatile #define _const const #endif typedef _u16 _SlOpcode_t; typedef _u8 _SlArgSize_t; typedef _i16 _SlDataSize_t; typedef _i16 _SlReturnVal_t; #ifdef __cplusplus } #endif /* __cplusplus */ /* * This event status used to block or continue the event propagation * through all the registered external libs/user application * */ typedef enum { EVENT_PROPAGATION_BLOCK = 0, EVENT_PROPAGATION_CONTINUE } _SlEventPropogationStatus_e; /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #ifdef SL_PLATFORM_MULTI_THREADED #include "spawn.h" #else #include "nonos.h" #endif /* objInclusion.h and user.h must be included before all api header files objInclusion.h must be the last arrangement just before including the API header files since it based on the other configurations to decide which object should be included */ #include "objInclusion.h" #include "trace.h" #include "fs.h" #include "socket.h" #include "netapp.h" #include "wlan.h" #include "device.h" #include "netcfg.h" #include "wlan_rx_filters.h" /* The general events dispatcher which is * initialized to the user handler */ #ifdef sl_GeneralEvtHdlr #define _SlDrvHandleGeneralEvents sl_GeneralEvtHdlr #endif /* The wlan events dispatcher which is * initialized to the user handler */ #ifdef sl_WlanEvtHdlr #define _SlDrvHandleWlanEvents sl_WlanEvtHdlr #endif /* The NetApp events dispatcher which is * initialized to the user handler */ #ifdef sl_NetAppEvtHdlr #define _SlDrvHandleNetAppEvents sl_NetAppEvtHdlr #endif /* The http server events dispatcher which is * initialized to the user handler if exists */ #ifdef sl_HttpServerCallback #define _SlDrvHandleHttpServerEvents sl_HttpServerCallback #endif /* The socket events dispatcher which is * initialized to the user handler */ #ifdef sl_SockEvtHdlr #define _SlDrvHandleSockEvents sl_SockEvtHdlr #endif #ifndef __CONCAT #define __CONCAT(x,y) x ## y #endif #define __CONCAT2(x,y) __CONCAT(x,y) /* * The section below handles the external lib event registration * according to the desired events it specified in its API header file. * The external lib should be first installed by the user (see user.h) */ #ifdef SL_EXT_LIB_1 /* General Event Registration */ #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_GENERAL_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _GeneralEventHdl) (SlDeviceEvent_t *); #define SlExtLib1GeneralEventHandler __CONCAT2(SL_EXT_LIB_1, _GeneralEventHdl) #undef EXT_LIB_REGISTERED_GENERAL_EVENTS #define EXT_LIB_REGISTERED_GENERAL_EVENTS #endif /* Wlan Event Registration */ #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_WLAN_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _WlanEventHdl) (SlWlanEvent_t *); #define SlExtLib1WlanEventHandler __CONCAT2(SL_EXT_LIB_1, _WlanEventHdl) #undef EXT_LIB_REGISTERED_WLAN_EVENTS #define EXT_LIB_REGISTERED_WLAN_EVENTS #endif /* NetApp Event Registration */ #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_NETAPP_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _NetAppEventHdl) (SlNetAppEvent_t *); #define SlExtLib1NetAppEventHandler __CONCAT2(SL_EXT_LIB_1, _NetAppEventHdl) #undef EXT_LIB_REGISTERED_NETAPP_EVENTS #define EXT_LIB_REGISTERED_NETAPP_EVENTS #endif /* Http Server Event Registration */ #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_HTTP_SERVER_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); #define SlExtLib1HttpServerEventHandler __CONCAT2(SL_EXT_LIB_1, _HttpServerEventHdl) #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #endif /* Socket Event Registration */ #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_SOCK_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _SockEventHdl) (SlSockEvent_t *); #define SlExtLib1SockEventHandler __CONCAT2(SL_EXT_LIB_1, _SockEventHdl) #undef EXT_LIB_REGISTERED_SOCK_EVENTS #define EXT_LIB_REGISTERED_SOCK_EVENTS #endif #endif #ifdef SL_EXT_LIB_2 /* General Event Registration */ #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_GENERAL_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _GeneralEventHdl) (SlDeviceEvent_t *); #define SlExtLib2GeneralEventHandler __CONCAT2(SL_EXT_LIB_2, _GeneralEventHdl) #undef EXT_LIB_REGISTERED_GENERAL_EVENTS #define EXT_LIB_REGISTERED_GENERAL_EVENTS #endif /* Wlan Event Registration */ #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_WLAN_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _WlanEventHdl) (SlWlanEvent_t *); #define SlExtLib2WlanEventHandler __CONCAT2(SL_EXT_LIB_2, _WlanEventHdl) #undef EXT_LIB_REGISTERED_WLAN_EVENTS #define EXT_LIB_REGISTERED_WLAN_EVENTS #endif /* NetApp Event Registration */ #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_NETAPP_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _NetAppEventHdl) (SlNetAppEvent_t *); #define SlExtLib2NetAppEventHandler __CONCAT2(SL_EXT_LIB_2, _NetAppEventHdl) #undef EXT_LIB_REGISTERED_NETAPP_EVENTS #define EXT_LIB_REGISTERED_NETAPP_EVENTS #endif /* Http Server Event Registration */ #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_HTTP_SERVER_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); #define SlExtLib2HttpServerEventHandler __CONCAT2(SL_EXT_LIB_2, _HttpServerEventHdl) #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #endif /* Socket Event Registration */ #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_SOCK_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _SockEventHdl) (SlSockEvent_t *); #define SlExtLib2SockEventHandler __CONCAT2(SL_EXT_LIB_2, _SockEventHdl) #undef EXT_LIB_REGISTERED_SOCK_EVENTS #define EXT_LIB_REGISTERED_SOCK_EVENTS #endif #endif #ifdef SL_EXT_LIB_3 /* General Event Registration */ #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_GENERAL_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _GeneralEventHdl) (SlDeviceEvent_t *); #define SlExtLib3GeneralEventHandler __CONCAT2(SL_EXT_LIB_3, _GeneralEventHdl) #undef EXT_LIB_REGISTERED_GENERAL_EVENTS #define EXT_LIB_REGISTERED_GENERAL_EVENTS #endif /* Wlan Event Registration */ #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_WLAN_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _WlanEventHdl) (SlWlanEvent_t *); #define SlExtLib3WlanEventHandler __CONCAT2(SL_EXT_LIB_3, _WlanEventHdl) #undef EXT_LIB_REGISTERED_WLAN_EVENTS #define EXT_LIB_REGISTERED_WLAN_EVENTS #endif /* NetApp Event Registration */ #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_NETAPP_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _NetAppEventHdl) (SlNetAppEvent_t *); #define SlExtLib3NetAppEventHandler __CONCAT2(SL_EXT_LIB_3, _NetAppEventHdl) #undef EXT_LIB_REGISTERED_NETAPP_EVENTS #define EXT_LIB_REGISTERED_NETAPP_EVENTS #endif /* Http Server Event Registration */ #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_HTTP_SERVER_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); #define SlExtLib3HttpServerEventHandler __CONCAT2(SL_EXT_LIB_3, _HttpServerEventHdl) #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #endif /* Socket Event Registration */ #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_SOCK_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _SockEventHdl) (SlSockEvent_t *); #define SlExtLib3SockEventHandler __CONCAT2(SL_EXT_LIB_3, _SockEventHdl) #undef EXT_LIB_REGISTERED_SOCK_EVENTS #define EXT_LIB_REGISTERED_SOCK_EVENTS #endif #endif #ifdef SL_EXT_LIB_4 /* General Event Registration */ #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_GENERAL_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _GeneralEventHdl) (SlDeviceEvent_t *); #define SlExtLib4GeneralEventHandler __CONCAT2(SL_EXT_LIB_4, _GeneralEventHdl) #undef EXT_LIB_REGISTERED_GENERAL_EVENTS #define EXT_LIB_REGISTERED_GENERAL_EVENTS #endif /* Wlan Event Registration */ #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_WLAN_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _WlanEventHdl) (SlWlanEvent_t *); #define SlExtLib4WlanEventHandler __CONCAT2(SL_EXT_LIB_4, _WlanEventHdl) #undef EXT_LIB_REGISTERED_WLAN_EVENTS #define EXT_LIB_REGISTERED_WLAN_EVENTS #endif /* NetApp Event Registration */ #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_NETAPP_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _NetAppEventHdl) (SlNetAppEvent_t *); #define SlExtLib4NetAppEventHandler __CONCAT2(SL_EXT_LIB_4, _NetAppEventHdl) #undef EXT_LIB_REGISTERED_NETAPP_EVENTS #define EXT_LIB_REGISTERED_NETAPP_EVENTS #endif /* Http Server Event Registration */ #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_HTTP_SERVER_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); #define SlExtLib4HttpServerEventHandler __CONCAT2(SL_EXT_LIB_4, _HttpServerEventHdl) #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #endif /* Socket Event Registration */ #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_SOCK_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _SockEventHdl) (SlSockEvent_t *); #define SlExtLib4SockEventHandler __CONCAT2(SL_EXT_LIB_4, _SockEventHdl) #undef EXT_LIB_REGISTERED_SOCK_EVENTS #define EXT_LIB_REGISTERED_SOCK_EVENTS #endif #endif #ifdef SL_EXT_LIB_5 /* General Event Registration */ #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_GENERAL_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _GeneralEventHdl) (SlDeviceEvent_t *); #define SlExtLib5GeneralEventHandler __CONCAT2(SL_EXT_LIB_5, _GeneralEventHdl) #undef EXT_LIB_REGISTERED_GENERAL_EVENTS #define EXT_LIB_REGISTERED_GENERAL_EVENTS #endif /* Wlan Event Registration */ #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_WLAN_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _WlanEventHdl) (SlWlanEvent_t *); #define SlExtLib5WlanEventHandler __CONCAT2(SL_EXT_LIB_5, _WlanEventHdl) #undef EXT_LIB_REGISTERED_WLAN_EVENTS #define EXT_LIB_REGISTERED_WLAN_EVENTS #endif /* NetApp Event Registration */ #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_NETAPP_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _NetAppEventHdl) (SlNetAppEvent_t *); #define SlExtLib5NetAppEventHandler __CONCAT2(SL_EXT_LIB_5, _NetAppEventHdl) #undef EXT_LIB_REGISTERED_NETAPP_EVENTS #define EXT_LIB_REGISTERED_NETAPP_EVENTS #endif /* Http Server Event Registration */ #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_HTTP_SERVER_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); #define SlExtLib5HttpServerEventHandler __CONCAT2(SL_EXT_LIB_5, _HttpServerEventHdl) #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS #endif /* Socket Event Registration */ #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_SOCK_EVENT) extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _SockEventHdl) (SlSockEvent_t *); #define SlExtLib5SockEventHandler __CONCAT2(SL_EXT_LIB_5, _SockEventHdl) #undef EXT_LIB_REGISTERED_SOCK_EVENTS #define EXT_LIB_REGISTERED_SOCK_EVENTS #endif #endif #if defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) extern void _SlDrvHandleGeneralEvents(SlDeviceEvent_t *slGeneralEvent); #endif #if defined(EXT_LIB_REGISTERED_WLAN_EVENTS) extern void _SlDrvHandleWlanEvents(SlWlanEvent_t *slWlanEvent); #endif #if defined (EXT_LIB_REGISTERED_NETAPP_EVENTS) extern void _SlDrvHandleNetAppEvents(SlNetAppEvent_t *slNetAppEvent); #endif #if defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) extern void _SlDrvHandleHttpServerEvents(SlHttpServerEvent_t *slHttpServerEvent, SlHttpServerResponse_t *slHttpServerResponse); #endif #if defined(EXT_LIB_REGISTERED_SOCK_EVENTS) extern void _SlDrvHandleSockEvents(SlSockEvent_t *slSockEvent); #endif typedef void (*_SlSpawnEntryFunc_t)(void* pValue); /* Async functions description*/ /*! \brief General async event for inspecting general events \param[out] pSlDeviceEvent pointer to SlDeviceEvent_t \par Parameters: \n - pSlDeviceEvent->Event = SL_DEVICE_FATAL_ERROR_EVENT - pSlDeviceEvent->EventData.deviceEvent fields: - status: An error code indication from the device - sender: The sender originator which is based on SlErrorSender_e enum - pSlDeviceEvent->Event = SL_DEVICE_ABORT_ERROR_EVENT Indicates a severe error occured and the device stopped - pSlDeviceEvent->EventData.deviceReport fields: - AbortType: An idication of the event type - AbortData: Additional info about the data error \par Example for fatal error: \code printf(General Event Handler - ID=%d Sender=%d\n\n", pSlDeviceEvent->EventData.deviceEvent.status, // status of the general event pSlDeviceEvent->EventData.deviceEvent.sender); // sender type \endcode \par Example for abort request: \code printf(Abort type =%d Abort Data=%d\n\n", pSlDeviceEvent->EventData.deviceReport.AbortType, pSlDeviceEvent->EventData.deviceReport.AbortData); \endcode */ #if (defined(sl_GeneralEvtHdlr)) extern void sl_GeneralEvtHdlr(SlDeviceEvent_t *pSlDeviceEvent); #endif /*! \brief WLAN Async event handler \param[out] pSlWlanEvent pointer to SlWlanEvent_t data \par Parameters: - pSlWlanEvent->Event = SL_WLAN_CONNECT_EVENT , STA or P2P client connection indication event - pSlWlanEvent->EventData.STAandP2PModeWlanConnected main fields: - ssid_name - ssid_len - bssid - go_peer_device_name - go_peer_device_name_len - pSlWlanEvent->Event = SL_WLAN_DISCONNECT_EVENT , STA or P2P client disconnection event - pSlWlanEvent->EventData.STAandP2PModeDisconnected main fields: - ssid_name - ssid_len - reason_code - pSlWlanEvent->Event = SL_WLAN_STA_CONNECTED_EVENT , AP/P2P(Go) connected STA/P2P(Client) - pSlWlanEvent->EventData.APModeStaConnected fields: - go_peer_device_name - mac - go_peer_device_name_len - wps_dev_password_id - own_ssid: relevant for event sta-connected only - own_ssid_len: relevant for event sta-connected only - pSlWlanEvent->Event = SL_WLAN_STA_DISCONNECTED_EVENT , AP/P2P(Go) disconnected STA/P2P(Client) - pSlWlanEvent->EventData.APModestaDisconnected fields: - go_peer_device_name - mac - go_peer_device_name_len - wps_dev_password_id - own_ssid: relevant for event sta-connected only - own_ssid_len: relevant for event sta-connected only - pSlWlanEvent->Event = SL_WLAN_SMART_CONFIG_COMPLETE_EVENT - pSlWlanEvent->EventData.smartConfigStartResponse fields: - status - ssid_len - ssid - private_token_len - private_token - pSlWlanEvent->Event = SL_WLAN_SMART_CONFIG_STOP_EVENT - pSlWlanEvent->EventData.smartConfigStopResponse fields: - status - pSlWlanEvent->Event = SL_WLAN_P2P_DEV_FOUND_EVENT - pSlWlanEvent->EventData.P2PModeDevFound fields: - go_peer_device_name - mac - go_peer_device_name_len - wps_dev_password_id - own_ssid: relevant for event sta-connected only - own_ssid_len: relevant for event sta-connected only - pSlWlanEvent->Event = SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT - pSlWlanEvent->EventData.P2PModeNegReqReceived fields - go_peer_device_name - mac - go_peer_device_name_len - wps_dev_password_id - own_ssid: relevant for event sta-connected only - pSlWlanEvent->Event = SL_WLAN_CONNECTION_FAILED_EVENT , P2P only - pSlWlanEvent->EventData.P2PModewlanConnectionFailure fields: - status */ #if (defined(sl_WlanEvtHdlr)) extern void sl_WlanEvtHdlr(SlWlanEvent_t* pSlWlanEvent); #endif /*! \brief NETAPP Async event handler \param[out] pSlNetApp pointer to SlNetAppEvent_t data \par Parameters: - pSlNetApp->Event = SL_NETAPP_IPV4_IPACQUIRED_EVENT, IPV4 acquired event - pSlNetApp->EventData.ipAcquiredV4 fields: - ip - gateway - dns - pSlNetApp->Event = SL_NETAPP_IP_LEASED_EVENT, AP or P2P go dhcp lease event - pSlNetApp->EventData.ipLeased fields: - ip_address - lease_time - mac - pSlNetApp->Event = SL_NETAPP_IP_RELEASED_EVENT, AP or P2P go dhcp ip release event - pSlNetApp->EventData.ipReleased fields - ip_address - mac - reason */ #if (defined(sl_NetAppEvtHdlr)) extern void sl_NetAppEvtHdlr(SlNetAppEvent_t* pSlNetApp); #endif /*! \brief Socket Async event handler \param[out] pSlSockEvent pointer to SlSockEvent_t data \par Parameters:\n - pSlSockEvent->Event = SL_SOCKET_TX_FAILED_EVENT - pSlSockEvent->SockTxFailData fields: - sd - status - pSlSockEvent->Event = SL_SOCKET_ASYNC_EVENT - pSlSockEvent->SockAsyncData fields: - sd - type: SSL_ACCEPT or RX_FRAGMENTATION_TOO_BIG or OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED - val */ #if (defined(sl_SockEvtHdlr)) extern void sl_SockEvtHdlr(SlSockEvent_t* pSlSockEvent); #endif /*! \brief HTTP server async event \param[out] pSlHttpServerEvent pointer to SlHttpServerEvent_t \param[in] pSlHttpServerResponse pointer to SlHttpServerResponse_t \par Parameters: \n - pSlHttpServerEvent->Event = SL_NETAPP_HTTPGETTOKENVALUE_EVENT - pSlHttpServerEvent->EventData fields: - httpTokenName - data - len - pSlHttpServerResponse->ResponseData fields: - data - len - pSlHttpServerEvent->Event = SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT - pSlHttpServerEvent->EventData.httpPostData fields: - action - token_name - token_value - pSlHttpServerResponse->ResponseData fields: - data - len */ #if (defined(sl_HttpServerCallback)) extern void sl_HttpServerCallback(SlHttpServerEvent_t *pSlHttpServerEvent, SlHttpServerResponse_t *pSlHttpServerResponse); #endif /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __SIMPLELINK_H__ */ micropython-1.12/drivers/cc3100/inc/socket.h000066400000000000000000002316711357706137100206150ustar00rootroot00000000000000/* * socket.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #ifndef __SL_SOCKET_H__ #define __SL_SOCKET_H__ #ifdef __cplusplus extern "C" { #endif /*! \addtogroup socket @{ */ /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #define SL_FD_SETSIZE SL_MAX_SOCKETS /* Number of sockets to select on - same is max sockets! */ #define BSD_SOCKET_ID_MASK (0x0F) /* Index using the LBS 4 bits for socket id 0-7 */ /* Define some BSD protocol constants. */ #define SL_SOCK_STREAM (1) /* TCP Socket */ #define SL_SOCK_DGRAM (2) /* UDP Socket */ #define SL_SOCK_RAW (3) /* Raw socket */ #define SL_IPPROTO_TCP (6) /* TCP Raw Socket */ #define SL_IPPROTO_UDP (17) /* UDP Raw Socket */ #define SL_IPPROTO_RAW (255) /* Raw Socket */ #define SL_SEC_SOCKET (100) /* Secured Socket Layer (SSL,TLS) */ /* Address families. */ #define SL_AF_INET (2) /* IPv4 socket (UDP, TCP, etc) */ #define SL_AF_INET6 (3) /* IPv6 socket (UDP, TCP, etc) */ #define SL_AF_INET6_EUI_48 (9) #define SL_AF_RF (6) /* data include RF parameter, All layer by user (Wifi could be disconnected) */ #define SL_AF_PACKET (17) /* Protocol families, same as address families. */ #define SL_PF_INET AF_INET #define SL_PF_INET6 AF_INET6 #define SL_INADDR_ANY (0) /* bind any address */ /* error codes */ #define SL_SOC_ERROR (-1) /* Failure. */ #define SL_SOC_OK ( 0) /* Success. */ #define SL_INEXE (-8) /* socket command in execution */ #define SL_EBADF (-9) /* Bad file number */ #define SL_ENSOCK (-10) /* The system limit on the total number of open socket, has been reached */ #define SL_EAGAIN (-11) /* Try again */ #define SL_EWOULDBLOCK SL_EAGAIN #define SL_ENOMEM (-12) /* Out of memory */ #define SL_EACCES (-13) /* Permission denied */ #define SL_EFAULT (-14) /* Bad address */ #define SL_ECLOSE (-15) /* close socket operation failed to transmit all queued packets */ #define SL_EALREADY_ENABLED (-21) /* Transceiver - Transceiver already ON. there could be only one */ #define SL_EINVAL (-22) /* Invalid argument */ #define SL_EAUTO_CONNECT_OR_CONNECTING (-69) /* Transceiver - During connection, connected or auto mode started */ #define SL_CONNECTION_PENDING (-72) /* Transceiver - Device is connected, disconnect first to open transceiver */ #define SL_EUNSUPPORTED_ROLE (-86) /* Transceiver - Trying to start when WLAN role is AP or P2P GO */ #define SL_EDESTADDRREQ (-89) /* Destination address required */ #define SL_EPROTOTYPE (-91) /* Protocol wrong type for socket */ #define SL_ENOPROTOOPT (-92) /* Protocol not available */ #define SL_EPROTONOSUPPORT (-93) /* Protocol not supported */ #define SL_ESOCKTNOSUPPORT (-94) /* Socket type not supported */ #define SL_EOPNOTSUPP (-95) /* Operation not supported on transport endpoint */ #define SL_EAFNOSUPPORT (-97) /* Address family not supported by protocol */ #define SL_EADDRINUSE (-98) /* Address already in use */ #define SL_EADDRNOTAVAIL (-99) /* Cannot assign requested address */ #define SL_ENETUNREACH (-101) /* Network is unreachable */ #define SL_ENOBUFS (-105) /* No buffer space available */ #define SL_EOBUFF SL_ENOBUFS #define SL_EISCONN (-106) /* Transport endpoint is already connected */ #define SL_ENOTCONN (-107) /* Transport endpoint is not connected */ #define SL_ETIMEDOUT (-110) /* Connection timed out */ #define SL_ECONNREFUSED (-111) /* Connection refused */ #define SL_EALREADY (-114) /* Non blocking connect in progress, try again */ #define SL_ESEC_RSA_WRONG_TYPE_E (-130) /* RSA wrong block type for RSA function */ #define SL_ESEC_RSA_BUFFER_E (-131) /* RSA buffer error, output too small or */ #define SL_ESEC_BUFFER_E (-132) /* output buffer too small or input too large */ #define SL_ESEC_ALGO_ID_E (-133) /* setting algo id error */ #define SL_ESEC_PUBLIC_KEY_E (-134) /* setting public key error */ #define SL_ESEC_DATE_E (-135) /* setting date validity error */ #define SL_ESEC_SUBJECT_E (-136) /* setting subject name error */ #define SL_ESEC_ISSUER_E (-137) /* setting issuer name error */ #define SL_ESEC_CA_TRUE_E (-138) /* setting CA basic constraint true error */ #define SL_ESEC_EXTENSIONS_E (-139) /* setting extensions error */ #define SL_ESEC_ASN_PARSE_E (-140) /* ASN parsing error, invalid input */ #define SL_ESEC_ASN_VERSION_E (-141) /* ASN version error, invalid number */ #define SL_ESEC_ASN_GETINT_E (-142) /* ASN get big _i16 error, invalid data */ #define SL_ESEC_ASN_RSA_KEY_E (-143) /* ASN key init error, invalid input */ #define SL_ESEC_ASN_OBJECT_ID_E (-144) /* ASN object id error, invalid id */ #define SL_ESEC_ASN_TAG_NULL_E (-145) /* ASN tag error, not null */ #define SL_ESEC_ASN_EXPECT_0_E (-146) /* ASN expect error, not zero */ #define SL_ESEC_ASN_BITSTR_E (-147) /* ASN bit string error, wrong id */ #define SL_ESEC_ASN_UNKNOWN_OID_E (-148) /* ASN oid error, unknown sum id */ #define SL_ESEC_ASN_DATE_SZ_E (-149) /* ASN date error, bad size */ #define SL_ESEC_ASN_BEFORE_DATE_E (-150) /* ASN date error, current date before */ #define SL_ESEC_ASN_AFTER_DATE_E (-151) /* ASN date error, current date after */ #define SL_ESEC_ASN_SIG_OID_E (-152) /* ASN signature error, mismatched oid */ #define SL_ESEC_ASN_TIME_E (-153) /* ASN time error, unknown time type */ #define SL_ESEC_ASN_INPUT_E (-154) /* ASN input error, not enough data */ #define SL_ESEC_ASN_SIG_CONFIRM_E (-155) /* ASN sig error, confirm failure */ #define SL_ESEC_ASN_SIG_HASH_E (-156) /* ASN sig error, unsupported hash type */ #define SL_ESEC_ASN_SIG_KEY_E (-157) /* ASN sig error, unsupported key type */ #define SL_ESEC_ASN_DH_KEY_E (-158) /* ASN key init error, invalid input */ #define SL_ESEC_ASN_NTRU_KEY_E (-159) /* ASN ntru key decode error, invalid input */ #define SL_ESEC_ECC_BAD_ARG_E (-170) /* ECC input argument of wrong type */ #define SL_ESEC_ASN_ECC_KEY_E (-171) /* ASN ECC bad input */ #define SL_ESEC_ECC_CURVE_OID_E (-172) /* Unsupported ECC OID curve type */ #define SL_ESEC_BAD_FUNC_ARG (-173) /* Bad function argument provided */ #define SL_ESEC_NOT_COMPILED_IN (-174) /* Feature not compiled in */ #define SL_ESEC_UNICODE_SIZE_E (-175) /* Unicode password too big */ #define SL_ESEC_NO_PASSWORD (-176) /* no password provided by user */ #define SL_ESEC_ALT_NAME_E (-177) /* alt name size problem, too big */ #define SL_ESEC_AES_GCM_AUTH_E (-180) /* AES-GCM Authentication check failure */ #define SL_ESEC_AES_CCM_AUTH_E (-181) /* AES-CCM Authentication check failure */ #define SL_SOCKET_ERROR_E (-208) /* Error state on socket */ #define SL_ESEC_MEMORY_ERROR (-203) /* out of memory */ #define SL_ESEC_VERIFY_FINISHED_ERROR (-204) /* verify problem on finished */ #define SL_ESEC_VERIFY_MAC_ERROR (-205) /* verify mac problem */ #define SL_ESEC_UNKNOWN_HANDSHAKE_TYPE (-207) /* weird handshake type */ #define SL_ESEC_SOCKET_ERROR_E (-208) /* error state on socket */ #define SL_ESEC_SOCKET_NODATA (-209) /* expected data, not there */ #define SL_ESEC_INCOMPLETE_DATA (-210) /* don't have enough data to complete task */ #define SL_ESEC_UNKNOWN_RECORD_TYPE (-211) /* unknown type in record hdr */ #define SL_ESEC_FATAL_ERROR (-213) /* recvd alert fatal error */ #define SL_ESEC_ENCRYPT_ERROR (-214) /* error during encryption */ #define SL_ESEC_NO_PEER_KEY (-216) /* need peer's key */ #define SL_ESEC_NO_PRIVATE_KEY (-217) /* need the private key */ #define SL_ESEC_RSA_PRIVATE_ERROR (-218) /* error during rsa priv op */ #define SL_ESEC_NO_DH_PARAMS (-219) /* server missing DH params */ #define SL_ESEC_BUILD_MSG_ERROR (-220) /* build message failure */ #define SL_ESEC_BAD_HELLO (-221) /* client hello malformed */ #define SL_ESEC_DOMAIN_NAME_MISMATCH (-222) /* peer subject name mismatch */ #define SL_ESEC_WANT_READ (-223) /* want read, call again */ #define SL_ESEC_NOT_READY_ERROR (-224) /* handshake layer not ready */ #define SL_ESEC_PMS_VERSION_ERROR (-225) /* pre m secret version error */ #define SL_ESEC_VERSION_ERROR (-226) /* record layer version error */ #define SL_ESEC_WANT_WRITE (-227) /* want write, call again */ #define SL_ESEC_BUFFER_ERROR (-228) /* malformed buffer input */ #define SL_ESEC_VERIFY_CERT_ERROR (-229) /* verify cert error */ #define SL_ESEC_VERIFY_SIGN_ERROR (-230) /* verify sign error */ #define SL_ESEC_LENGTH_ERROR (-241) /* record layer length error */ #define SL_ESEC_PEER_KEY_ERROR (-242) /* can't decode peer key */ #define SL_ESEC_ZERO_RETURN (-243) /* peer sent close notify */ #define SL_ESEC_SIDE_ERROR (-244) /* wrong client/server type */ #define SL_ESEC_NO_PEER_CERT (-245) /* peer didn't send key */ #define SL_ESEC_ECC_CURVETYPE_ERROR (-250) /* Bad ECC Curve Type */ #define SL_ESEC_ECC_CURVE_ERROR (-251) /* Bad ECC Curve */ #define SL_ESEC_ECC_PEERKEY_ERROR (-252) /* Bad Peer ECC Key */ #define SL_ESEC_ECC_MAKEKEY_ERROR (-253) /* Bad Make ECC Key */ #define SL_ESEC_ECC_EXPORT_ERROR (-254) /* Bad ECC Export Key */ #define SL_ESEC_ECC_SHARED_ERROR (-255) /* Bad ECC Shared Secret */ #define SL_ESEC_NOT_CA_ERROR (-257) /* Not a CA cert error */ #define SL_ESEC_BAD_PATH_ERROR (-258) /* Bad path for opendir */ #define SL_ESEC_BAD_CERT_MANAGER_ERROR (-259) /* Bad Cert Manager */ #define SL_ESEC_MAX_CHAIN_ERROR (-268) /* max chain depth exceeded */ #define SL_ESEC_SUITES_ERROR (-271) /* suites pointer error */ #define SL_ESEC_SSL_NO_PEM_HEADER (-272) /* no PEM header found */ #define SL_ESEC_OUT_OF_ORDER_E (-273) /* out of order message */ #define SL_ESEC_SANITY_CIPHER_E (-275) /* sanity check on cipher error */ #define SL_ESEC_GEN_COOKIE_E (-277) /* Generate Cookie Error */ #define SL_ESEC_NO_PEER_VERIFY (-278) /* Need peer cert verify Error */ #define SL_ESEC_UNKNOWN_SNI_HOST_NAME_E (-281) /* Unrecognized host name Error */ /* begin negotiation parameter errors */ #define SL_ESEC_UNSUPPORTED_SUITE (-290) /* unsupported cipher suite */ #define SL_ESEC_MATCH_SUITE_ERROR (-291 ) /* can't match cipher suite */ /* ssl tls security start with -300 offset */ #define SL_ESEC_CLOSE_NOTIFY (-300) /* ssl/tls alerts */ #define SL_ESEC_UNEXPECTED_MESSAGE (-310) /* ssl/tls alerts */ #define SL_ESEC_BAD_RECORD_MAC (-320) /* ssl/tls alerts */ #define SL_ESEC_DECRYPTION_FAILED (-321) /* ssl/tls alerts */ #define SL_ESEC_RECORD_OVERFLOW (-322) /* ssl/tls alerts */ #define SL_ESEC_DECOMPRESSION_FAILURE (-330) /* ssl/tls alerts */ #define SL_ESEC_HANDSHAKE_FAILURE (-340) /* ssl/tls alerts */ #define SL_ESEC_NO_CERTIFICATE (-341) /* ssl/tls alerts */ #define SL_ESEC_BAD_CERTIFICATE (-342) /* ssl/tls alerts */ #define SL_ESEC_UNSUPPORTED_CERTIFICATE (-343) /* ssl/tls alerts */ #define SL_ESEC_CERTIFICATE_REVOKED (-344) /* ssl/tls alerts */ #define SL_ESEC_CERTIFICATE_EXPIRED (-345) /* ssl/tls alerts */ #define SL_ESEC_CERTIFICATE_UNKNOWN (-346) /* ssl/tls alerts */ #define SL_ESEC_ILLEGAL_PARAMETER (-347) /* ssl/tls alerts */ #define SL_ESEC_UNKNOWN_CA (-348) /* ssl/tls alerts */ #define SL_ESEC_ACCESS_DENIED (-349) /* ssl/tls alerts */ #define SL_ESEC_DECODE_ERROR (-350) /* ssl/tls alerts */ #define SL_ESEC_DECRYPT_ERROR (-351) /* ssl/tls alerts */ #define SL_ESEC_EXPORT_RESTRICTION (-360) /* ssl/tls alerts */ #define SL_ESEC_PROTOCOL_VERSION (-370) /* ssl/tls alerts */ #define SL_ESEC_INSUFFICIENT_SECURITY (-371) /* ssl/tls alerts */ #define SL_ESEC_INTERNAL_ERROR (-380) /* ssl/tls alerts */ #define SL_ESEC_USER_CANCELLED (-390) /* ssl/tls alerts */ #define SL_ESEC_NO_RENEGOTIATION (-400) /* ssl/tls alerts */ #define SL_ESEC_UNSUPPORTED_EXTENSION (-410) /* ssl/tls alerts */ #define SL_ESEC_CERTIFICATE_UNOBTAINABLE (-411) /* ssl/tls alerts */ #define SL_ESEC_UNRECOGNIZED_NAME (-412) /* ssl/tls alerts */ #define SL_ESEC_BAD_CERTIFICATE_STATUS_RESPONSE (-413) /* ssl/tls alerts */ #define SL_ESEC_BAD_CERTIFICATE_HASH_VALUE (-414) /* ssl/tls alerts */ /* propierty secure */ #define SL_ESECGENERAL (-450) /* error secure level general error */ #define SL_ESECDECRYPT (-451) /* error secure level, decrypt recv packet fail */ #define SL_ESECCLOSED (-452) /* secure layrer is closed by other size , tcp is still connected */ #define SL_ESECSNOVERIFY (-453) /* Connected without server verification */ #define SL_ESECNOCAFILE (-454) /* error secure level CA file not found*/ #define SL_ESECMEMORY (-455) /* error secure level No memory space available */ #define SL_ESECBADCAFILE (-456) /* error secure level bad CA file */ #define SL_ESECBADCERTFILE (-457) /* error secure level bad Certificate file */ #define SL_ESECBADPRIVATEFILE (-458) /* error secure level bad private file */ #define SL_ESECBADDHFILE (-459) /* error secure level bad DH file */ #define SL_ESECT00MANYSSLOPENED (-460) /* MAX SSL Sockets are opened */ #define SL_ESECDATEERROR (-461) /* connected with certificate date verification error */ #define SL_ESECHANDSHAKETIMEDOUT (-462) /* connection timed out due to handshake time */ /* end error codes */ /* Max payload size by protocol */ #define SL_SOCKET_PAYLOAD_TYPE_MASK (0xF0) /*4 bits type, 4 bits sockets id */ #define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 (0x00) /* 1472 bytes */ #define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 (0x10) /* 1460 bytes */ #define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 (0x20) /* 1452 bytes */ #define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 (0x30) /* 1440 bytes */ #define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE (0x40) /* */ #define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE (0x50) /* */ #define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE (0x60) /* */ #define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE (0x70) /* */ #define SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER (0x80) /* 1536 bytes */ #define SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET (0x90) /* 1536 bytes */ #define SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 (0xa0) #define SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 (SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 ) #define SL_SOL_SOCKET (1) /* Define the socket option category. */ #define SL_IPPROTO_IP (2) /* Define the IP option category. */ #define SL_SOL_PHY_OPT (3) /* Define the PHY option category. */ #define SL_SO_RCVBUF (8) /* Setting TCP receive buffer size */ #define SL_SO_KEEPALIVE (9) /* Connections are kept alive with periodic messages */ #define SL_SO_RCVTIMEO (20) /* Enable receive timeout */ #define SL_SO_NONBLOCKING (24) /* Enable . disable nonblocking mode */ #define SL_SO_SECMETHOD (25) /* security metohd */ #define SL_SO_SECURE_MASK (26) /* security mask */ #define SL_SO_SECURE_FILES (27) /* security files */ #define SL_SO_CHANGE_CHANNEL (28) /* This option is available only when transceiver started */ #define SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME (30) /* This option used to configue secure file */ #define SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME (31) /* This option used to configue secure file */ #define SL_SO_SECURE_FILES_CA_FILE_NAME (32) /* This option used to configue secure file */ #define SL_SO_SECURE_FILES_DH_KEY_FILE_NAME (33) /* This option used to configue secure file */ #define SL_IP_MULTICAST_IF (60) /* Specify outgoing multicast interface */ #define SL_IP_MULTICAST_TTL (61) /* Specify the TTL value to use for outgoing multicast packet. */ #define SL_IP_ADD_MEMBERSHIP (65) /* Join IPv4 multicast membership */ #define SL_IP_DROP_MEMBERSHIP (66) /* Leave IPv4 multicast membership */ #define SL_IP_HDRINCL (67) /* Raw socket IPv4 header included. */ #define SL_IP_RAW_RX_NO_HEADER (68) /* Proprietary socket option that does not includeIPv4/IPv6 header (and extension headers) on received raw sockets*/ #define SL_IP_RAW_IPV6_HDRINCL (69) /* Transmitted buffer over IPv6 socket contains IPv6 header. */ #define SL_SO_PHY_RATE (100) /* WLAN Transmit rate */ #define SL_SO_PHY_TX_POWER (101) /* TX Power level */ #define SL_SO_PHY_NUM_FRAMES_TO_TX (102) /* Number of frames to transmit */ #define SL_SO_PHY_PREAMBLE (103) /* Preamble for transmission */ #define SL_SO_SEC_METHOD_SSLV3 (0) /* security metohd SSL v3*/ #define SL_SO_SEC_METHOD_TLSV1 (1) /* security metohd TLS v1*/ #define SL_SO_SEC_METHOD_TLSV1_1 (2) /* security metohd TLS v1_1*/ #define SL_SO_SEC_METHOD_TLSV1_2 (3) /* security metohd TLS v1_2*/ #define SL_SO_SEC_METHOD_SSLv3_TLSV1_2 (4) /* use highest possible version from SSLv3 - TLS 1.2*/ #define SL_SO_SEC_METHOD_DLSV1 (5) /* security metohd DTL v1 */ #define SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA (1 << 0) #define SL_SEC_MASK_SSL_RSA_WITH_RC4_128_MD5 (1 << 1) #define SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA (1 << 2) #define SL_SEC_MASK_TLS_DHE_RSA_WITH_AES_256_CBC_SHA (1 << 3) #define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (1 << 4) #define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_RC4_128_SHA (1 << 5) #define SL_SEC_MASK_TLS_RSA_WITH_AES_128_CBC_SHA256 (1 << 6) #define SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA256 (1 << 7) #define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (1 << 8) #define SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (1 << 9) #define SL_SEC_MASK_SECURE_DEFAULT ((SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 << 1) - 1) #define SL_MSG_DONTWAIT (0x00000008) /* Nonblocking IO */ /* AP DHCP Server - IP Release reason code */ #define SL_IP_LEASE_PEER_RELEASE (0) #define SL_IP_LEASE_PEER_DECLINE (1) #define SL_IP_LEASE_EXPIRED (2) /* possible types when receiving SL_SOCKET_ASYNC_EVENT*/ #define SSL_ACCEPT (1) /* accept failed due to ssl issue ( tcp pass) */ #define RX_FRAGMENTATION_TOO_BIG (2) /* connection less mode, rx packet fragmentation > 16K, packet is being released */ #define OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED (3) /* remote side down from secure to unsecure */ #ifdef SL_INC_STD_BSD_API_NAMING #define FD_SETSIZE SL_FD_SETSIZE #define SOCK_STREAM SL_SOCK_STREAM #define SOCK_DGRAM SL_SOCK_DGRAM #define SOCK_RAW SL_SOCK_RAW #define IPPROTO_TCP SL_IPPROTO_TCP #define IPPROTO_UDP SL_IPPROTO_UDP #define IPPROTO_RAW SL_IPPROTO_RAW #define AF_INET SL_AF_INET #define AF_INET6 SL_AF_INET6 #define AF_INET6_EUI_48 SL_AF_INET6_EUI_48 #define AF_RF SL_AF_RF #define AF_PACKET SL_AF_PACKET #define PF_INET SL_PF_INET #define PF_INET6 SL_PF_INET6 #define INADDR_ANY SL_INADDR_ANY #define ERROR SL_SOC_ERROR #define INEXE SL_INEXE #define EBADF SL_EBADF #define ENSOCK SL_ENSOCK #define EAGAIN SL_EAGAIN #define EWOULDBLOCK SL_EWOULDBLOCK #define ENOMEM SL_ENOMEM #define EACCES SL_EACCES #define EFAULT SL_EFAULT #define EINVAL SL_EINVAL #define EDESTADDRREQ SL_EDESTADDRREQ #define EPROTOTYPE SL_EPROTOTYPE #define ENOPROTOOPT SL_ENOPROTOOPT #define EPROTONOSUPPORT SL_EPROTONOSUPPORT #define ESOCKTNOSUPPORT SL_ESOCKTNOSUPPORT #define EOPNOTSUPP SL_EOPNOTSUPP #define EAFNOSUPPORT SL_EAFNOSUPPORT #define EADDRINUSE SL_EADDRINUSE #define EADDRNOTAVAIL SL_EADDRNOTAVAIL #define ENETUNREACH SL_ENETUNREACH #define ENOBUFS SL_ENOBUFS #define EOBUFF SL_EOBUFF #define EISCONN SL_EISCONN #define ENOTCONN SL_ENOTCONN #define ETIMEDOUT SL_ETIMEDOUT #define ECONNREFUSED SL_ECONNREFUSED #define SOL_SOCKET SL_SOL_SOCKET #define IPPROTO_IP SL_IPPROTO_IP #define SO_KEEPALIVE SL_SO_KEEPALIVE #define SO_RCVTIMEO SL_SO_RCVTIMEO #define SO_NONBLOCKING SL_SO_NONBLOCKING #define IP_MULTICAST_IF SL_IP_MULTICAST_IF #define IP_MULTICAST_TTL SL_IP_MULTICAST_TTL #define IP_ADD_MEMBERSHIP SL_IP_ADD_MEMBERSHIP #define IP_DROP_MEMBERSHIP SL_IP_DROP_MEMBERSHIP #define socklen_t SlSocklen_t #define timeval SlTimeval_t #define sockaddr SlSockAddr_t #define in6_addr SlIn6Addr_t #define sockaddr_in6 SlSockAddrIn6_t #define in_addr SlInAddr_t #define sockaddr_in SlSockAddrIn_t #define MSG_DONTWAIT SL_MSG_DONTWAIT #define FD_SET SL_FD_SET #define FD_CLR SL_FD_CLR #define FD_ISSET SL_FD_ISSET #define FD_ZERO SL_FD_ZERO #define fd_set SlFdSet_t #define socket sl_Socket #define close sl_Close #define accept sl_Accept #define bind sl_Bind #define listen sl_Listen #define connect sl_Connect #define select sl_Select #define setsockopt sl_SetSockOpt #define getsockopt sl_GetSockOpt #define recv sl_Recv #define recvfrom sl_RecvFrom #define write sl_Write #define send sl_Send #define sendto sl_SendTo #define gethostbyname sl_NetAppDnsGetHostByName #define htonl sl_Htonl #define ntohl sl_Ntohl #define htons sl_Htons #define ntohs sl_Ntohs #endif /*****************************************************************************/ /* Structure/Enum declarations */ /*****************************************************************************/ /* Internet address */ typedef struct SlInAddr_t { #ifndef s_addr _u32 s_addr; /* Internet address 32 bits */ #else union S_un { struct { _u8 s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { _u8 s_w1,s_w2; } S_un_w; _u32 S_addr; } S_un; #endif }SlInAddr_t; /* sockopt */ typedef struct { _u32 KeepaliveEnabled; /* 0 = disabled;1 = enabled; default = 1*/ }SlSockKeepalive_t; typedef struct { _u32 ReuseaddrEnabled; /* 0 = disabled; 1 = enabled; default = 1*/ }SlSockReuseaddr_t; typedef struct { _u32 Winsize; /* receive window size for tcp sockets */ }SlSockWinsize_t; typedef struct { _u32 NonblockingEnabled;/* 0 = disabled;1 = enabled;default = 1*/ }SlSockNonblocking_t; typedef struct { _u8 sd; _u8 type; _i16 val; _u8* pExtraInfo; } SlSocketAsyncEvent_t; typedef struct { _i16 status; _u8 sd; _u8 padding; } SlSockTxFailEventData_t; typedef union { SlSockTxFailEventData_t SockTxFailData; SlSocketAsyncEvent_t SockAsyncData; } SlSockEventData_u; typedef struct { _u32 Event; SlSockEventData_u socketAsyncEvent; } SlSockEvent_t; typedef struct { _u32 secureMask; } SlSockSecureMask; typedef struct { _u8 secureMethod; } SlSockSecureMethod; typedef enum { SL_BSD_SECURED_PRIVATE_KEY_IDX = 0, SL_BSD_SECURED_CERTIFICATE_IDX, SL_BSD_SECURED_CA_IDX, SL_BSD_SECURED_DH_IDX }slBsd_secureSocketFilesIndex_e; typedef struct { SlInAddr_t imr_multiaddr; /* The IPv4 multicast address to join */ SlInAddr_t imr_interface; /* The interface to use for this group */ } SlSockIpMreq; /* sockopt */ typedef _u32 SlTime_t; typedef _u32 SlSuseconds_t; typedef struct SlTimeval_t { SlTime_t tv_sec; /* Seconds */ SlSuseconds_t tv_usec; /* Microseconds */ }SlTimeval_t; typedef _u16 SlSocklen_t; /* IpV4 socket address */ typedef struct SlSockAddr_t { _u16 sa_family; /* Address family (e.g. , AF_INET) */ _u8 sa_data[14]; /* Protocol- specific address information*/ }SlSockAddr_t; /* IpV6 or Ipv6 EUI64 */ typedef struct SlIn6Addr_t { union { _u8 _S6_u8[16]; _u32 _S6_u32[4]; } _S6_un; }SlIn6Addr_t; typedef struct SlSockAddrIn6_t { _u16 sin6_family; /* AF_INET6 || AF_INET6_EUI_48*/ _u16 sin6_port; /* Transport layer port. */ _u32 sin6_flowinfo; /* IPv6 flow information. */ SlIn6Addr_t sin6_addr; /* IPv6 address. */ _u32 sin6_scope_id; /* set of interfaces for a scope. */ }SlSockAddrIn6_t; /* Socket address, Internet style. */ typedef struct SlSockAddrIn_t { _u16 sin_family; /* Internet Protocol (AF_INET). */ _u16 sin_port; /* Address port (16 bits). */ SlInAddr_t sin_addr; /* Internet address (32 bits). */ _i8 sin_zero[8]; /* Not used. */ }SlSockAddrIn_t; typedef struct { _u32 ip; _u32 gateway; _u32 dns; }SlIpV4AcquiredAsync_t; typedef struct { _u32 type; _u32 ip[4]; _u32 gateway[4]; _u32 dns[4]; }SlIpV6AcquiredAsync_t; typedef struct { _u32 ip_address; _u32 lease_time; _u8 mac[6]; _u16 padding; }SlIpLeasedAsync_t; typedef struct { _u32 ip_address; _u8 mac[6]; _u16 reason; }SlIpReleasedAsync_t; typedef union { SlIpV4AcquiredAsync_t ipAcquiredV4; /*SL_NETAPP_IPV4_IPACQUIRED_EVENT*/ SlIpV6AcquiredAsync_t ipAcquiredV6; /*SL_NETAPP_IPV6_IPACQUIRED_EVENT*/ _u32 sd; /*SL_SOCKET_TX_FAILED_EVENT*/ SlIpLeasedAsync_t ipLeased; /* SL_NETAPP_IP_LEASED_EVENT */ SlIpReleasedAsync_t ipReleased; /* SL_NETAPP_IP_RELEASED_EVENT */ } SlNetAppEventData_u; typedef struct { _u32 Event; SlNetAppEventData_u EventData; }SlNetAppEvent_t; typedef struct sock_secureFiles { _u8 secureFiles[4]; }SlSockSecureFiles_t; typedef struct SlFdSet_t /* The select socket array manager */ { _u32 fd_array[(SL_FD_SETSIZE + 31)/32]; /* Bit map of SOCKET Descriptors */ } SlFdSet_t; typedef struct { _u8 rate; /* Recevied Rate */ _u8 channel; /* The received channel*/ _i8 rssi; /* The computed RSSI value in db of current frame */ _u8 padding; /* pad to align to 32 bits */ _u32 timestamp; /* Timestamp in microseconds, */ }SlTransceiverRxOverHead_t; /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ /*! \brief create an endpoint for communication The socket function creates a new socket of a certain socket type, identified by an integer number, and allocates system resources to it. This function is called by the application layer to obtain a socket handle. \param[in] domain specifies the protocol family of the created socket. For example: AF_INET for network protocol IPv4 AF_RF for starting transceiver mode. Notes: - sending and receiving any packet overriding 802.11 header - for optimized power consumption the socket will be started in TX only mode until receive command is activated AF_INET6 for IPv6 \param[in] type specifies the communication semantic, one of: SOCK_STREAM (reliable stream-oriented service or Stream Sockets) SOCK_DGRAM (datagram service or Datagram Sockets) SOCK_RAW (raw protocols atop the network layer) when used with AF_RF: SOCK_DGRAM - L2 socket SOCK_RAW - L1 socket - bypass WLAN CCA (Clear Channel Assessment) \param[in] protocol specifies a particular transport to be used with the socket. The most common are IPPROTO_TCP, IPPROTO_SCTP, IPPROTO_UDP, IPPROTO_DCCP. The value 0 may be used to select a default protocol from the selected domain and type \return On success, socket handle that is used for consequent socket operations. A successful return code should be a positive number (int16) On error, a negative (int16) value will be returned specifying the error code. SL_EAFNOSUPPORT - illegal domain parameter SL_EPROTOTYPE - illegal type parameter SL_EACCES - permission denied SL_ENSOCK - exceeded maximal number of socket SL_ENOMEM - memory allocation error SL_EINVAL - error in socket configuration SL_EPROTONOSUPPORT - illegal protocol parameter SL_EOPNOTSUPP - illegal combination of protocol and type parameters \sa sl_Close \note belongs to \ref basic_api \warning */ #if _SL_INCLUDE_FUNC(sl_Socket) _i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol); #endif /*! \brief gracefully close socket This function causes the system to release resources allocated to a socket. \n In case of TCP, the connection is terminated. \param[in] sd socket handle (received in sl_Socket) \return On success, zero is returned. On error, a negative number is returned. \sa sl_Socket \note belongs to \ref ext_api \warning */ #if _SL_INCLUDE_FUNC(sl_Close) _i16 sl_Close(_i16 sd); #endif /*! \brief Accept a connection on a socket This function is used with connection-based socket types (SOCK_STREAM). It extracts the first connection request on the queue of pending connections, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket sd is unaffected by this call. The argument sd is a socket that has been created with sl_Socket(), bound to a local address with sl_Bind(), and is listening for connections after a sl_Listen(). The argument \b \e addr is a pointer to a sockaddr structure. This structure is filled in with the address of the peer socket, as known to the communications layer. The exact format of the address returned addr is determined by the socket's address family. The \b \e addrlen argument is a value-result argument: it should initially contain the size of the structure pointed to by addr, on return it will contain the actual length (in bytes) of the address returned. \param[in] sd socket descriptor (handle) \param[out] addr the argument addr is a pointer to a sockaddr structure. This structure is filled in with the address of the peer socket, as known to the communications layer. The exact format of the address returned addr is determined by the socket's address\n sockaddr:\n - code for the address format. On this version only AF_INET is supported.\n - socket address, the length depends on the code format \param[out] addrlen the addrlen argument is a value-result argument: it should initially contain the size of the structure pointed to by addr \return On success, a socket handle. On a non-blocking accept a possible negative value is SL_EAGAIN. On failure, negative value. SL_POOL_IS_EMPTY may be return in case there are no resources in the system In this case try again later or increase MAX_CONCURRENT_ACTIONS \sa sl_Socket sl_Bind sl_Listen \note belongs to \ref server_side \warning */ #if _SL_INCLUDE_FUNC(sl_Accept) _i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen); #endif /*! \brief assign a name to a socket This function gives the socket the local address addr. addr is addrlen bytes long. Traditionally, this is called When a socket is created with socket, it exists in a name space (address family) but has no name assigned. It is necessary to assign a local address before a SOCK_STREAM socket may receive connections. \param[in] sd socket descriptor (handle) \param[in] addr specifies the destination addrs\n sockaddr:\n - code for the address format. On this version only AF_INET is supported.\n - socket address, the length depends on the code format \param[in] addrlen contains the size of the structure pointed to by addr \return On success, zero is returned. On error, a negative error code is returned. \sa sl_Socket sl_Accept sl_Listen \note belongs to \ref basic_api \warning */ #if _SL_INCLUDE_FUNC(sl_Bind) _i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen); #endif /*! \brief listen for connections on a socket The willingness to accept incoming connections and a queue limit for incoming connections are specified with listen(), and then the connections are accepted with accept. The listen() call applies only to sockets of type SOCK_STREAM The backlog parameter defines the maximum length the queue of pending connections may grow to. \param[in] sd socket descriptor (handle) \param[in] backlog specifies the listen queue depth. \return On success, zero is returned. On error, a negative error code is returned. \sa sl_Socket sl_Accept sl_Bind \note belongs to \ref server_side \warning */ #if _SL_INCLUDE_FUNC(sl_Listen) _i16 sl_Listen(_i16 sd, _i16 backlog); #endif /*! \brief Initiate a connection on a socket Function connects the socket referred to by the socket descriptor sd, to the address specified by addr. The addrlen argument specifies the size of addr. The format of the address in addr is determined by the address space of the socket. If it is of type SOCK_DGRAM, this call specifies the peer with which the socket is to be associated; this address is that to which datagrams are to be sent, and the only address from which datagrams are to be received. If the socket is of type SOCK_STREAM, this call attempts to make a connection to another socket. The other socket is specified by address, which is an address in the communications space of the socket. \param[in] sd socket descriptor (handle) \param[in] addr specifies the destination addr\n sockaddr:\n - code for the address format. On this version only AF_INET is supported.\n - socket address, the length depends on the code format \param[in] addrlen contains the size of the structure pointed to by addr \return On success, a socket handle. On a non-blocking connect a possible negative value is SL_EALREADY. On failure, negative value. SL_POOL_IS_EMPTY may be return in case there are no resources in the system In this case try again later or increase MAX_CONCURRENT_ACTIONS \sa sl_Socket \note belongs to \ref client_side \warning */ #if _SL_INCLUDE_FUNC(sl_Connect) _i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen); #endif /*! \brief Monitor socket activity Select allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation \param[in] nfds the highest-numbered file descriptor in any of the three sets, plus 1. \param[out] readsds socket descriptors list for read monitoring and accept monitoring \param[out] writesds socket descriptors list for connect monitoring only, write monitoring is not supported, non blocking connect is supported \param[out] exceptsds socket descriptors list for exception monitoring, not supported. \param[in] timeout is an upper bound on the amount of time elapsed before select() returns. Null or above 0xffff seconds means infinity timeout. The minimum timeout is 10 milliseconds, less than 10 milliseconds will be set automatically to 10 milliseconds. Max microseconds supported is 0xfffc00. \return On success, select() returns the number of file descriptors contained in the three returned descriptor sets (that is, the total number of bits that are set in readfds, writefds, exceptfds) which may be zero if the timeout expires before anything interesting happens. On error, a negative value is returned. readsds - return the sockets on which Read request will return without delay with valid data. writesds - return the sockets on which Write request will return without delay. exceptsds - return the sockets closed recently. SL_POOL_IS_EMPTY may be return in case there are no resources in the system In this case try again later or increase MAX_CONCURRENT_ACTIONS \sa sl_Socket \note If the timeout value set to less than 5ms it will automatically set to 5ms to prevent overload of the system belongs to \ref basic_api Only one sl_Select can be handled at a time. Calling this API while the same command is called from another thread, may result in one of the two scenarios: 1. The command will wait (internal) until the previous command finish, and then be executed. 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try again later to issue the command. \warning */ #if _SL_INCLUDE_FUNC(sl_Select) _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout); /*! \brief Select's SlFdSet_t SET function Sets current socket descriptor on SlFdSet_t container */ void SL_FD_SET(_i16 fd, SlFdSet_t *fdset); /*! \brief Select's SlFdSet_t CLR function Clears current socket descriptor on SlFdSet_t container */ void SL_FD_CLR(_i16 fd, SlFdSet_t *fdset); /*! \brief Select's SlFdSet_t ISSET function Checks if current socket descriptor is set (TRUE/FALSE) \return Returns TRUE if set, FALSE if unset */ _i16 SL_FD_ISSET(_i16 fd, SlFdSet_t *fdset); /*! \brief Select's SlFdSet_t ZERO function Clears all socket descriptors from SlFdSet_t */ void SL_FD_ZERO(SlFdSet_t *fdset); #endif /*! \brief set socket options This function manipulate the options associated with a socket. Options may exist at multiple protocol levels; they are always present at the uppermost socket level. When manipulating socket options the level at which the option resides and the name of the option must be specified. To manipulate options at the socket level, level is specified as SOL_SOCKET. To manipulate options at any other level the protocol number of the appropriate proto- col controlling the option is supplied. For example, to indicate that an option is to be interpreted by the TCP protocol, level should be set to the protocol number of TCP; The parameters optval and optlen are used to access optval - ues for setsockopt(). For getsockopt() they identify a buffer in which the value for the requested option(s) are to be returned. For getsockopt(), optlen is a value-result parameter, initially containing the size of the buffer pointed to by option_value, and modified on return to indicate the actual size of the value returned. If no option value is to be supplied or returned, option_value may be NULL. \param[in] sd socket handle \param[in] level defines the protocol level for this option - SL_SOL_SOCKET Socket level configurations (L4, transport layer) - SL_IPPROTO_IP IP level configurations (L3, network layer) - SL_SOL_PHY_OPT Link level configurations (L2, link layer) \param[in] optname defines the option name to interrogate - SL_SOL_SOCKET - SL_SO_KEEPALIVE \n Enable/Disable periodic keep alive. Keeps TCP connections active by enabling the periodic transmission of messages \n Timeout is 5 minutes.\n Default: Enabled \n This options takes SlSockKeepalive_t struct as parameter - SL_SO_RCVTIMEO \n Sets the timeout value that specifies the maximum amount of time an input function waits until it completes. \n Default: No timeout \n This options takes SlTimeval_t struct as parameter - SL_SO_RCVBUF \n Sets tcp max recv window size. \n This options takes SlSockWinsize_t struct as parameter - SL_SO_NONBLOCKING \n Sets socket to non-blocking operation Impacts: connect, accept, send, sendto, recv and recvfrom. \n Default: Blocking. This options takes SlSockNonblocking_t struct as parameter - SL_SO_SECMETHOD \n Sets method to tcp secured socket (SL_SEC_SOCKET) \n Default: SL_SO_SEC_METHOD_SSLv3_TLSV1_2 \n This options takes SlSockSecureMethod struct as parameter - SL_SO_SEC_MASK \n Sets specific cipher to tcp secured socket (SL_SEC_SOCKET) \n Default: "Best" cipher suitable to method \n This options takes SlSockSecureMask struct as parameter - SL_SO_SECURE_FILES_CA_FILE_NAME \n Map secured socket to CA file by name \n This options takes _u8 buffer as parameter - SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME \n Map secured socket to private key by name \n This options takes _u8 buffer as parameter - SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME \n Map secured socket to certificate file by name \n This options takes _u8 buffer as parameter - SL_SO_SECURE_FILES_DH_KEY_FILE_NAME \n Map secured socket to Diffie Hellman file by name \n This options takes _u8 buffer as parameter - SL_SO_CHANGE_CHANNEL \n Sets channel in transceiver mode. This options takes _u32 as channel number parameter - SL_IPPROTO_IP - SL_IP_MULTICAST_TTL \n Set the time-to-live value of outgoing multicast packets for this socket. \n This options takes _u8 as parameter - SL_IP_ADD_MEMBERSHIP \n UDP socket, Join a multicast group. \n This options takes SlSockIpMreq struct as parameter - SL_IP_DROP_MEMBERSHIP \n UDP socket, Leave a multicast group \n This options takes SlSockIpMreq struct as parameter - SL_IP_RAW_RX_NO_HEADER \n Raw socket remove IP header from received data. \n Default: data includes ip header \n This options takes _u32 as parameter - SL_IP_HDRINCL \n RAW socket only, the IPv4 layer generates an IP header when sending a packet unless \n the IP_HDRINCL socket option is enabled on the socket. \n When it is enabled, the packet must contain an IP header. \n Default: disabled, IPv4 header generated by Network Stack \n This options takes _u32 as parameter - SL_IP_RAW_IPV6_HDRINCL (inactive) \n RAW socket only, the IPv6 layer generates an IP header when sending a packet unless \n the IP_HDRINCL socket option is enabled on the socket. When it is enabled, the packet must contain an IP header \n Default: disabled, IPv4 header generated by Network Stack \n This options takes _u32 as parameter - SL_SOL_PHY_OPT - SL_SO_PHY_RATE \n RAW socket, set WLAN PHY transmit rate \n The values are based on RateIndex_e \n This options takes _u32 as parameter - SL_SO_PHY_TX_POWER \n RAW socket, set WLAN PHY TX power \n Valid rage is 1-15 \n This options takes _u32 as parameter - SL_SO_PHY_NUM_FRAMES_TO_TX \n RAW socket, set number of frames to transmit in transceiver mode. Default: 1 packet This options takes _u32 as parameter - SL_SO_PHY_PREAMBLE \n RAW socket, set WLAN PHY preamble for Long/Short\n This options takes _u32 as parameter \param[in] optval specifies a value for the option \param[in] optlen specifies the length of the option value \return On success, zero is returned. On error, a negative value is returned. \sa sl_getsockopt \note belongs to \ref basic_api \warning \par Examples: \par SL_SO_KEEPALIVE: (disable Keepalive) \code SlSockKeepalive_t enableOption; enableOption.KeepaliveEnabled = 0; sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_KEEPALIVE, (_u8 *)&enableOption,sizeof(enableOption)); \endcode \par SL_SO_RCVTIMEO: \code struct SlTimeval_t timeVal; timeVal.tv_sec = 1; // Seconds timeVal.tv_usec = 0; // Microseconds. 10000 microseconds resolution sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_RCVTIMEO, (_u8 *)&timeVal, sizeof(timeVal)); // Enable receive timeout \endcode \par SL_SO_RCVBUF: \code SlSockWinsize_t size; size.Winsize = 3000; // bytes sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_RCVBUF, (_u8 *)&size, sizeof(size)); \endcode \par SL_SO_NONBLOCKING: \code SlSockNonblocking_t enableOption; enableOption.NonblockingEnabled = 1; sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_NONBLOCKING, (_u8 *)&enableOption,sizeof(enableOption)); // Enable/disable nonblocking mode \endcode \par SL_SO_SECMETHOD: \code SlSockSecureMethod method; method.secureMethod = SL_SO_SEC_METHOD_SSLV3; // security method we want to use SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET); sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_SECMETHOD, (_u8 *)&method, sizeof(method)); \endcode \par SL_SO_SECURE_MASK: \code SlSockSecureMask cipher; cipher.secureMask = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA; // cipher type SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET); sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_SEC_MASK,(_u8 *)&cipher, sizeof(cipher)); \endcode \par SL_SO_SECURE_FILES_CA_FILE_NAME: \code sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_CA_FILE_NAME,"exuifaxCaCert.der",strlen("exuifaxCaCert.der")); \endcode \par SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME: \code sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME,"myPrivateKey.der",strlen("myPrivateKey.der")); \endcode \par SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME: \code sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME,"myCertificate.der",strlen("myCertificate.der")); \endcode \par SL_SO_SECURE_FILES_DH_KEY_FILE_NAME: \code sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_DH_KEY_FILE_NAME,"myDHinServerMode.der",strlen("myDHinServerMode.der")); \endcode \par SL_IP_MULTICAST_TTL: \code _u8 ttl = 20; sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_MULTICAST_TTL, &ttl, sizeof(ttl)); \endcode \par SL_IP_ADD_MEMBERSHIP: \code SlSockIpMreq mreq; sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); \endcode \par SL_IP_DROP_MEMBERSHIP: \code SlSockIpMreq mreq; sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); \endcode \par SL_SO_CHANGE_CHANNEL: \code _u32 newChannel = 6; // range is 1-13 sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_CHANGE_CHANNEL, &newChannel, sizeof(newChannel)); \endcode \par SL_IP_RAW_RX_NO_HEADER: \code _u32 header = 1; // remove ip header sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_RAW_RX_NO_HEADER, &header, sizeof(header)); \endcode \par SL_IP_HDRINCL: \code _u32 header = 1; sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_HDRINCL, &header, sizeof(header)); \endcode \par SL_IP_RAW_IPV6_HDRINCL: \code _u32 header = 1; sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_RAW_IPV6_HDRINCL, &header, sizeof(header)); \endcode \par SL_SO_PHY_RATE: \code _u32 rate = 6; // see wlan.h RateIndex_e for values sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_RATE, &rate, sizeof(rate)); \endcode \par SL_SO_PHY_TX_POWER: \code _u32 txpower = 1; // valid range is 1-15 sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_TX_POWER, &txpower, sizeof(txpower)); \endcode \par SL_SO_PHY_NUM_FRAMES_TO_TX: \code _u32 numframes = 1; sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_NUM_FRAMES_TO_TX, &numframes, sizeof(numframes)); \endcode \par SL_SO_PHY_PREAMBLE: \code _u32 preamble = 1; sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_PREAMBLE, &preamble, sizeof(preamble)); \endcode */ #if _SL_INCLUDE_FUNC(sl_SetSockOpt) _i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen); #endif /*! \brief Get socket options This function manipulate the options associated with a socket. Options may exist at multiple protocol levels; they are always present at the uppermost socket level. When manipulating socket options the level at which the option resides and the name of the option must be specified. To manipulate options at the socket level, level is specified as SOL_SOCKET. To manipulate options at any other level the protocol number of the appropriate proto- col controlling the option is supplied. For example, to indicate that an option is to be interpreted by the TCP protocol, level should be set to the protocol number of TCP; The parameters optval and optlen are used to access optval - ues for setsockopt(). For getsockopt() they identify a buffer in which the value for the requested option(s) are to be returned. For getsockopt(), optlen is a value-result parameter, initially containing the size of the buffer pointed to by option_value, and modified on return to indicate the actual size of the value returned. If no option value is to be supplied or returned, option_value may be NULL. \param[in] sd socket handle \param[in] level defines the protocol level for this option \param[in] optname defines the option name to interrogate \param[out] optval specifies a value for the option \param[out] optlen specifies the length of the option value \return On success, zero is returned. On error, a negative value is returned. \sa sl_SetSockOpt \note See sl_SetSockOpt belongs to \ref ext_api \warning */ #if _SL_INCLUDE_FUNC(sl_GetSockOpt) _i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen); #endif /*! \brief read data from TCP socket function receives a message from a connection-mode socket \param[in] sd socket handle \param[out] buf Points to the buffer where the message should be stored. \param[in] Len Specifies the length in bytes of the buffer pointed to by the buffer argument. Range: 1-16000 bytes \param[in] flags Specifies the type of message reception. On this version, this parameter is not supported. \return return the number of bytes received, or a negative value if an error occurred. using a non-blocking recv a possible negative value is SL_EAGAIN. SL_POOL_IS_EMPTY may be return in case there are no resources in the system In this case try again later or increase MAX_CONCURRENT_ACTIONS \sa sl_RecvFrom \note belongs to \ref recv_api \warning \par Examples: \code An example of receiving data using TCP socket: SlSockAddrIn_t Addr; SlSockAddrIn_t LocalAddr; _i16 AddrSize = sizeof(SlSockAddrIn_t); _i16 SockID, newSockID; _i16 Status; _i8 Buf[RECV_BUF_LEN]; LocalAddr.sin_family = SL_AF_INET; LocalAddr.sin_port = sl_Htons(5001); LocalAddr.sin_addr.s_addr = 0; Addr.sin_family = SL_AF_INET; Addr.sin_port = sl_Htons(5001); Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); Status = sl_Bind(SockID, (SlSockAddr_t *)&LocalAddr, AddrSize); Status = sl_Listen(SockID, 0); newSockID = sl_Accept(SockID, (SlSockAddr_t*)&Addr, (SlSocklen_t*) &AddrSize); Status = sl_Recv(newSockID, Buf, 1460, 0); \endcode \code Example code for Rx transceiver mode using a raw socket _i8 buffer[1536]; _i16 sd; _u16 size; SlTransceiverRxOverHead_t *transHeader; sd = sl_Socket(SL_AF_RF,SL_SOCK_RAW,11); // channel 11 while(1) { size = sl_Recv(sd,buffer,1536,0); transHeader = (SlTransceiverRxOverHead_t *)buffer; printf("RSSI is %d frame type is 0x%x size %d\n",transHeader->rssi,buffer[sizeof(SlTransceiverRxOverHead_t)],size); } \endcode */ #if _SL_INCLUDE_FUNC(sl_Recv) _i16 sl_Recv(_i16 sd, void *buf, _i16 Len, _i16 flags); #endif /*! \brief read data from socket function receives a message from a connection-mode or connectionless-mode socket \param[in] sd socket handle \param[out] buf Points to the buffer where the message should be stored. \param[in] Len Specifies the length in bytes of the buffer pointed to by the buffer argument. Range: 1-16000 bytes \param[in] flags Specifies the type of message reception. On this version, this parameter is not supported. \param[in] from pointer to an address structure indicating the source address.\n sockaddr:\n - code for the address format. On this version only AF_INET is supported.\n - socket address, the length depends on the code format \param[in] fromlen source address structure size. This parameter MUST be set to the size of the structure pointed to by addr. \return return the number of bytes received, or a negative value if an error occurred. using a non-blocking recv a possible negative value is SL_EAGAIN. SL_RET_CODE_INVALID_INPUT (-2) will be returned if fromlen has incorrect length. SL_POOL_IS_EMPTY may be return in case there are no resources in the system In this case try again later or increase MAX_CONCURRENT_ACTIONS \sa sl_Recv \note belongs to \ref recv_api \warning \par Example: \code An example of receiving data: SlSockAddrIn_t Addr; SlSockAddrIn_t LocalAddr; _i16 AddrSize = sizeof(SlSockAddrIn_t); _i16 SockID; _i16 Status; _i8 Buf[RECV_BUF_LEN]; LocalAddr.sin_family = SL_AF_INET; LocalAddr.sin_port = sl_Htons(5001); LocalAddr.sin_addr.s_addr = 0; SockID = sl_Socket(SL_AF_INET,SL_SOCK_DGRAM, 0); Status = sl_Bind(SockID, (SlSockAddr_t *)&LocalAddr, AddrSize); Status = sl_RecvFrom(SockID, Buf, 1472, 0, (SlSockAddr_t *)&Addr, (SlSocklen_t*)&AddrSize); \endcode */ #if _SL_INCLUDE_FUNC(sl_RecvFrom) _i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen); #endif /*! \brief write data to TCP socket This function is used to transmit a message to another socket. Returns immediately after sending data to device. In case of TCP failure an async event SL_SOCKET_TX_FAILED_EVENT is going to be received. In case of a RAW socket (transceiver mode), extra 4 bytes should be reserved at the end of the frame data buffer for WLAN FCS \param[in] sd socket handle \param[in] buf Points to a buffer containing the message to be sent \param[in] Len message size in bytes. Range: 1-1460 bytes \param[in] flags Specifies the type of message transmission. On this version, this parameter is not supported for TCP. For transceiver mode, the SL_RAW_RF_TX_PARAMS macro can be used to determine transmission parameters (channel,rate,tx_power,preamble) \return Return the number of bytes transmitted, or -1 if an error occurred \sa sl_SendTo \note belongs to \ref send_api \warning \par Example: \code An example of sending data: SlSockAddrIn_t Addr; _i16 AddrSize = sizeof(SlSockAddrIn_t); _i16 SockID; _i16 Status; _i8 Buf[SEND_BUF_LEN]; Addr.sin_family = SL_AF_INET; Addr.sin_port = sl_Htons(5001); Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); Status = sl_Connect(SockID, (SlSockAddr_t *)&Addr, AddrSize); Status = sl_Send(SockID, Buf, 1460, 0 ); \endcode */ #if _SL_INCLUDE_FUNC(sl_Send ) _i16 sl_Send(_i16 sd, const void *buf, _i16 Len, _i16 flags); #endif /*! \brief write data to socket This function is used to transmit a message to another socket (connection less socket SOCK_DGRAM, SOCK_RAW). Returns immediately after sending data to device. In case of transmission failure an async event SL_SOCKET_TX_FAILED_EVENT is going to be received. \param[in] sd socket handle \param[in] buf Points to a buffer containing the message to be sent \param[in] Len message size in bytes. Range: 1-1460 bytes \param[in] flags Specifies the type of message transmission. On this version, this parameter is not supported \param[in] to pointer to an address structure indicating the destination address.\n sockaddr:\n - code for the address format. On this version only AF_INET is supported.\n - socket address, the length depends on the code format \param[in] tolen destination address structure size \return Return the number of transmitted bytes, or -1 if an error occurred \sa sl_Send \note belongs to \ref send_api \warning \par Example: \code An example of sending data: SlSockAddrIn_t Addr; _i16 AddrSize = sizeof(SlSockAddrIn_t); _i16 SockID; _i16 Status; _i8 Buf[SEND_BUF_LEN]; Addr.sin_family = SL_AF_INET; Addr.sin_port = sl_Htons(5001); Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); SockID = sl_Socket(SL_AF_INET,SL_SOCK_DGRAM, 0); Status = sl_SendTo(SockID, Buf, 1472, 0, (SlSockAddr_t *)&Addr, AddrSize); \endcode */ #if _SL_INCLUDE_FUNC(sl_SendTo) _i16 sl_SendTo(_i16 sd, const void *buf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen); #endif /*! \brief Reorder the bytes of a 32-bit unsigned value This function is used to Reorder the bytes of a 32-bit unsigned value from processor order to network order. \param[in] var variable to reorder \return Return the reorder variable, \sa sl_SendTo sl_Bind sl_Connect sl_RecvFrom sl_Accept \note belongs to \ref send_api \warning */ #if _SL_INCLUDE_FUNC(sl_Htonl ) _u32 sl_Htonl( _u32 val ); #define sl_Ntohl sl_Htonl /* Reorder the bytes of a 16-bit unsigned value from network order to processor orde. */ #endif /*! \brief Reorder the bytes of a 16-bit unsigned value This function is used to Reorder the bytes of a 16-bit unsigned value from processor order to network order. \param[in] var variable to reorder \return Return the reorder variable, \sa sl_SendTo sl_Bind sl_Connect sl_RecvFrom sl_Accept \note belongs to \ref send_api \warning */ #if _SL_INCLUDE_FUNC(sl_Htons ) _u16 sl_Htons( _u16 val ); #define sl_Ntohs sl_Htons /* Reorder the bytes of a 16-bit unsigned value from network order to processor orde. */ #endif /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __SOCKET_H__ */ micropython-1.12/drivers/cc3100/inc/spawn.h000066400000000000000000000043451357706137100204510ustar00rootroot00000000000000/* * spawn.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __NONOS_H__ #define __NONOS_H__ #ifdef __cplusplus extern "C" { #endif #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) extern void _SlInternalSpawnTaskEntry(); extern _i16 _SlInternalSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); #undef sl_Spawn #define sl_Spawn(pEntry,pValue,flags) _SlInternalSpawn(pEntry,pValue,flags) #undef _SlTaskEntry #define _SlTaskEntry _SlInternalSpawnTaskEntry #endif #ifdef __cplusplus } #endif /* __cplusplus */ #endif micropython-1.12/drivers/cc3100/inc/trace.h000066400000000000000000000156541357706137100204240ustar00rootroot00000000000000/* * trace.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "simplelink.h" #ifndef __SIMPLELINK_TRACE_H__ #define __SIMPLELINK_TRACE_H__ #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #define SL_SYNC_SCAN_THRESHOLD (( _u32 )2000) #define _SL_ASSERT(expr) { ASSERT(expr); } #define _SL_ERROR(expr, error) { if(!(expr)){return (error); } } #define SL_HANDLING_ASSERT 2 #define SL_HANDLING_ERROR 1 #define SL_HANDLING_NONE 0 #define SL_SELF_COND_HANDLING SL_HANDLING_NONE #define SL_PROTOCOL_HANDLING SL_HANDLING_NONE #define SL_DRV_RET_CODE_HANDLING SL_HANDLING_NONE #define SL_NWP_IF_HANDLING SL_HANDLING_NONE #define SL_OSI_RET_OK_HANDLING SL_HANDLING_NONE #define SL_MALLOC_OK_HANDLING SL_HANDLING_NONE #define SL_USER_ARGS_HANDLING SL_HANDLING_NONE #if (SL_DRV_RET_CODE_HANDLING == SL_HANDLING_ASSERT) #define VERIFY_RET_OK(Func) {_SlReturnVal_t _RetVal = (Func); _SL_ASSERT((_SlReturnVal_t)SL_OS_RET_CODE_OK == _RetVal)} #elif (SL_DRV_RET_CODE_HANDLING == SL_HANDLING_ERROR) #define VERIFY_RET_OK(Func) {_SlReturnVal_t _RetVal = (Func); if (SL_OS_RET_CODE_OK != _RetVal) return _RetVal;} #else #define VERIFY_RET_OK(Func) (Func); #endif #if (SL_PROTOCOL_HANDLING == SL_HANDLING_ASSERT) #define VERIFY_PROTOCOL(expr) _SL_ASSERT(expr) #elif (SL_PROTOCOL_HANDLING == SL_HANDLING_ERROR) #define VERIFY_PROTOCOL(expr) _SL_ERROR(expr, SL_RET_CODE_PROTOCOL_ERROR) #else #define VERIFY_PROTOCOL(expr) #endif #if (defined(PROTECT_SOCKET_ASYNC_RESP) && (SL_SELF_COND_HANDLING == SL_HANDLING_ASSERT)) #define VERIFY_SOCKET_CB(expr) _SL_ASSERT(expr) #elif (defined(PROTECT_SOCKET_ASYNC_RESP) && (SL_SELF_COND_HANDLING == SL_HANDLING_ERROR)) #define VERIFY_SOCKET_CB(expr) _SL_ERROR(expr, SL_RET_CODE_SELF_ERROR) #else #define VERIFY_SOCKET_CB(expr) #endif #if (SL_NWP_IF_HANDLING == SL_HANDLING_ASSERT) #define NWP_IF_WRITE_CHECK(fd,pBuff,len) { _i16 RetSize, ExpSize = (len); RetSize = sl_IfWrite((fd),(pBuff),ExpSize); _SL_ASSERT(ExpSize == RetSize)} #define NWP_IF_READ_CHECK(fd,pBuff,len) { _i16 RetSize, ExpSize = (len); RetSize = sl_IfRead((fd),(pBuff),ExpSize); _SL_ASSERT(ExpSize == RetSize)} #elif (SL_NWP_IF_HANDLING == SL_HANDLING_ERROR) #define NWP_IF_WRITE_CHECK(fd,pBuff,len) { _SL_ERROR((len == sl_IfWrite((fd),(pBuff),(len))), SL_RET_CODE_NWP_IF_ERROR);} #define NWP_IF_READ_CHECK(fd,pBuff,len) { _SL_ERROR((len == sl_IfRead((fd),(pBuff),(len))), SL_RET_CODE_NWP_IF_ERROR);} #else #define NWP_IF_WRITE_CHECK(fd,pBuff,len) { sl_IfWrite((fd),(pBuff),(len));} #define NWP_IF_READ_CHECK(fd,pBuff,len) { sl_IfRead((fd),(pBuff),(len));} #endif #if (SL_OSI_RET_OK_HANDLING == SL_HANDLING_ASSERT) #define OSI_RET_OK_CHECK(Func) {_SlReturnVal_t _RetVal = (Func); _SL_ASSERT((_SlReturnVal_t)SL_OS_RET_CODE_OK == _RetVal)} #elif (SL_OSI_RET_OK_HANDLING == SL_HANDLING_ERROR) #define OSI_RET_OK_CHECK(Func) {_SlReturnVal_t _RetVal = (Func); if (SL_OS_RET_CODE_OK != _RetVal) return _RetVal;} #else #define OSI_RET_OK_CHECK(Func) (Func); #endif #if (SL_MALLOC_OK_HANDLING == SL_HANDLING_ASSERT) #define MALLOC_OK_CHECK(Ptr) _SL_ASSERT(NULL != Ptr) #elif (SL_MALLOC_OK_HANDLING == SL_HANDLING_ERROR) #define MALLOC_OK_CHECK(Ptr) _SL_ERROR((NULL != Ptr), SL_RET_CODE_MALLOC_ERROR) #else #define MALLOC_OK_CHECK(Ptr) #endif #ifdef SL_INC_ARG_CHECK #if (SL_USER_ARGS_HANDLING == SL_HANDLING_ASSERT) #define ARG_CHECK_PTR(Ptr) _SL_ASSERT(NULL != Ptr) #elif (SL_USER_ARGS_HANDLING == SL_HANDLING_ERROR) #define ARG_CHECK_PTR(Ptr) _SL_ERROR((NULL != Ptr), SL_RET_CODE_INVALID_INPUT) #else #define ARG_CHECK_PTR(Ptr) #endif #else #define ARG_CHECK_PTR(Ptr) #endif #define SL_TRACE0(level,msg_id,str) #define SL_TRACE1(level,msg_id,str,p1) #define SL_TRACE2(level,msg_id,str,p1,p2) #define SL_TRACE3(level,msg_id,str,p1,p2,p3) #define SL_TRACE4(level,msg_id,str,p1,p2,p3,p4) #define SL_ERROR_TRACE(msg_id,str) #define SL_ERROR_TRACE1(msg_id,str,p1) #define SL_ERROR_TRACE2(msg_id,str,p1,p2) #define SL_ERROR_TRACE3(msg_id,str,p1,p2,p3) #define SL_ERROR_TRACE4(msg_id,str,p1,p2,p3,p4) #define SL_TRACE_FLUSH() /* #define SL_DBG_CNT_ENABLE */ #ifdef SL_DBG_CNT_ENABLE #define _SL_DBG_CNT_INC(Cnt) g_DbgCnt. ## Cnt++ #define _SL_DBG_SYNC_LOG(index,value) {if(index < SL_DBG_SYNC_LOG_SIZE){*(_u32 *)&g_DbgCnt.SyncLog[index] = *(_u32 *)(value);}} #else #define _SL_DBG_CNT_INC(Cnt) #define _SL_DBG_SYNC_LOG(index,value) #endif #define SL_DBG_LEVEL_1 1 #define SL_DBG_LEVEL_2 2 #define SL_DBG_LEVEL_3 4 #define SL_DBG_LEVEL_MASK (SL_DBG_LEVEL_2|SL_DBG_LEVEL_3) #define SL_INCLUDE_DBG_FUNC(Name) ((Name ## _DBG_LEVEL) & SL_DBG_LEVEL_MASK) #define _SlDrvPrintStat_DBG_LEVEL SL_DBG_LEVEL_3 #define _SlDrvOtherFunc_DBG_LEVEL SL_DBG_LEVEL_1 #ifdef __cplusplus } #endif #endif /*__SIMPLELINK_TRACE_H__*/ micropython-1.12/drivers/cc3100/inc/wlan.h000066400000000000000000002006071357706137100202610ustar00rootroot00000000000000/* * wlan.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #ifndef __WLAN_H__ #define __WLAN_H__ #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ /*! \addtogroup wlan @{ */ #define SL_BSSID_LENGTH (6) #define MAXIMAL_SSID_LENGTH (32) #define NUM_OF_RATE_INDEXES (20) #define SIZE_OF_RSSI_HISTOGRAM (6) /* WLAN Disconnect Reason Codes */ #define SL_DISCONNECT_RESERVED_0 (0) #define SL_DISCONNECT_UNSPECIFIED_REASON (1) #define SL_PREVIOUS_AUTHENTICATION_NO_LONGER_VALID (2) #define SL_DEAUTHENTICATED_BECAUSE_SENDING_STATION_IS_LEAVING (3) #define SL_DISASSOCIATED_DUE_TO_INACTIVITY (4) #define SL_DISASSOCIATED_BECAUSE_AP_IS_UNABLE_TO_HANDLE_ALL_CURRENTLY_ASSOCIATED_STATIONS (5) #define SL_CLASS_2_FRAME_RECEIVED_FROM_NONAUTHENTICATED_STATION (6) #define SL_CLASS_3_FRAME_RECEIVED_FROM_NONASSOCIATED_STATION (7) #define SL_DISASSOCIATED_BECAUSE_SENDING_STATION_IS_LEAVING_BSS (8) #define SL_STATION_REQUESTING_ASSOCIATION_IS_NOT_AUTHENTICATED_WITH_RESPONDING_STATION (9) #define SL_DISASSOCIATED_BECAUSE_THE_INFORMATION_IN_THE_POWER_CAPABILITY_ELEMENT_IS_UNACCEPTABLE (10) #define SL_DISASSOCIATED_BECAUSE_THE_INFORMATION_IN_THE_SUPPORTED_CHANNELS_ELEMENT_IS_UNACCEPTABLE (11) #define SL_DISCONNECT_RESERVED_1 (12) #define SL_INVALID_INFORMATION_ELEMENT (13) #define SL_MESSAGE_INTEGRITY_CODE_MIC_FAILURE (14) #define SL_FOUR_WAY_HANDSHAKE_TIMEOUT (15) #define SL_GROUP_KEY_HANDSHAKE_TIMEOUT (16) #define SL_RE_ASSOCIATION_REQUEST_PROBE_RESPONSE_BEACON_FRAME (17) #define SL_INVALID_GROUP_CIPHER (18) #define SL_INVALID_PAIRWISE_CIPHER (19) #define SL_INVALID_AKMP (20) #define SL_UNSUPPORTED_RSN_INFORMATION_ELEMENT_VERSION (21) #define SL_INVALID_RSN_INFORMATION_ELEMENT_CAPABILITIES (22) #define SL_IEEE_802_1X_AUTHENTICATION_FAILED (23) #define SL_CIPHER_SUITE_REJECTED_BECAUSE_OF_THE_SECURITY_POLICY (24) #define SL_DISCONNECT_RESERVED_2 (25) #define SL_DISCONNECT_RESERVED_3 (26) #define SL_DISCONNECT_RESERVED_4 (27) #define SL_DISCONNECT_RESERVED_5 (28) #define SL_DISCONNECT_RESERVED_6 (29) #define SL_DISCONNECT_RESERVED_7 (30) #define SL_DISCONNECT_RESERVED_8 (31) #define SL_USER_INITIATED_DISCONNECTION (200) /* Wlan error codes */ #define SL_ERROR_KEY_ERROR (-3) #define SL_ERROR_INVALID_ROLE (-71) #define SL_ERROR_INVALID_SECURITY_TYPE (-84) #define SL_ERROR_PASSPHRASE_TOO_LONG (-85) #define SL_ERROR_WPS_NO_PIN_OR_WRONG_PIN_LEN (-87) #define SL_ERROR_EAP_WRONG_METHOD (-88) #define SL_ERROR_PASSWORD_ERROR (-89) #define SL_ERROR_EAP_ANONYMOUS_LEN_ERROR (-90) #define SL_ERROR_SSID_LEN_ERROR (-91) #define SL_ERROR_USER_ID_LEN_ERROR (-92) #define SL_ERROR_ILLEGAL_WEP_KEY_INDEX (-95) #define SL_ERROR_INVALID_DWELL_TIME_VALUES (-96) #define SL_ERROR_INVALID_POLICY_TYPE (-97) #define SL_ERROR_PM_POLICY_INVALID_OPTION (-98) #define SL_ERROR_PM_POLICY_INVALID_PARAMS (-99) #define SL_ERROR_WIFI_ALREADY_DISCONNECTED (-129) #define SL_ERROR_WIFI_NOT_CONNECTED (-59) #define SL_SEC_TYPE_OPEN (0) #define SL_SEC_TYPE_WEP (1) #define SL_SEC_TYPE_WPA (2) /* deprecated */ #define SL_SEC_TYPE_WPA_WPA2 (2) #define SL_SEC_TYPE_WPS_PBC (3) #define SL_SEC_TYPE_WPS_PIN (4) #define SL_SEC_TYPE_WPA_ENT (5) #define SL_SEC_TYPE_P2P_PBC (6) #define SL_SEC_TYPE_P2P_PIN_KEYPAD (7) #define SL_SEC_TYPE_P2P_PIN_DISPLAY (8) #define SL_SEC_TYPE_P2P_PIN_AUTO (9) /* NOT Supported yet */ #define SL_SCAN_SEC_TYPE_OPEN (0) #define SL_SCAN_SEC_TYPE_WEP (1) #define SL_SCAN_SEC_TYPE_WPA (2) #define SL_SCAN_SEC_TYPE_WPA2 (3) #define TLS (0x1) #define MSCHAP (0x0) #define PSK (0x2) #define TTLS (0x10) #define PEAP0 (0x20) #define PEAP1 (0x40) #define FAST (0x80) #define FAST_AUTH_PROVISIONING (0x02) #define FAST_UNAUTH_PROVISIONING (0x01) #define FAST_NO_PROVISIONING (0x00) #define EAPMETHOD_PHASE2_SHIFT (8) #define EAPMETHOD_PAIRWISE_CIPHER_SHIFT (19) #define EAPMETHOD_GROUP_CIPHER_SHIFT (27) #define WPA_CIPHER_CCMP (0x1) #define WPA_CIPHER_TKIP (0x2) #define CC31XX_DEFAULT_CIPHER (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) #define EAPMETHOD(phase1,phase2,pairwise_cipher,group_cipher) \ ((phase1) | \ ((phase2) << EAPMETHOD_PHASE2_SHIFT ) |\ ((_u32)(pairwise_cipher) << EAPMETHOD_PAIRWISE_CIPHER_SHIFT ) |\ ((_u32)(group_cipher) << EAPMETHOD_GROUP_CIPHER_SHIFT )) /* phase1 phase2 pairwise_cipher group_cipher */ #define SL_ENT_EAP_METHOD_TLS EAPMETHOD(TLS , 0 , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_TTLS_TLS EAPMETHOD(TTLS , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_TTLS_MSCHAPv2 EAPMETHOD(TTLS , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_TTLS_PSK EAPMETHOD(TTLS , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_PEAP0_TLS EAPMETHOD(PEAP0 , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_PEAP0_MSCHAPv2 EAPMETHOD(PEAP0 , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_PEAP0_PSK EAPMETHOD(PEAP0 , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_PEAP1_TLS EAPMETHOD(PEAP1 , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_PEAP1_MSCHAPv2 EAPMETHOD(PEAP1 , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_PEAP1_PSK EAPMETHOD(PEAP1 , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_FAST_AUTH_PROVISIONING EAPMETHOD(FAST , FAST_AUTH_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_FAST_UNAUTH_PROVISIONING EAPMETHOD(FAST , FAST_UNAUTH_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_ENT_EAP_METHOD_FAST_NO_PROVISIONING EAPMETHOD(FAST , FAST_NO_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) #define SL_LONG_PREAMBLE (0) #define SL_SHORT_PREAMBLE (1) #define SL_RAW_RF_TX_PARAMS_CHANNEL_SHIFT (0) #define SL_RAW_RF_TX_PARAMS_RATE_SHIFT (6) #define SL_RAW_RF_TX_PARAMS_POWER_SHIFT (11) #define SL_RAW_RF_TX_PARAMS_PREAMBLE_SHIFT (15) #define SL_RAW_RF_TX_PARAMS(chan,rate,power,preamble) \ ((chan << SL_RAW_RF_TX_PARAMS_CHANNEL_SHIFT) | \ (rate << SL_RAW_RF_TX_PARAMS_RATE_SHIFT) | \ (power << SL_RAW_RF_TX_PARAMS_POWER_SHIFT) | \ (preamble << SL_RAW_RF_TX_PARAMS_PREAMBLE_SHIFT)) /* wlan config application IDs */ #define SL_WLAN_CFG_AP_ID (0) #define SL_WLAN_CFG_GENERAL_PARAM_ID (1) #define SL_WLAN_CFG_P2P_PARAM_ID (2) /* wlan AP Config set/get options */ #define WLAN_AP_OPT_SSID (0) #define WLAN_AP_OPT_CHANNEL (3) #define WLAN_AP_OPT_HIDDEN_SSID (4) #define WLAN_AP_OPT_SECURITY_TYPE (6) #define WLAN_AP_OPT_PASSWORD (7) #define WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE (9) #define WLAN_GENERAL_PARAM_OPT_STA_TX_POWER (10) #define WLAN_GENERAL_PARAM_OPT_AP_TX_POWER (11) #define WLAN_P2P_OPT_DEV_NAME (12) #define WLAN_P2P_OPT_DEV_TYPE (13) #define WLAN_P2P_OPT_CHANNEL_N_REGS (14) #define WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT (16) #define WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS (18) /* change the scan channels and RSSI threshold using this configuration option */ /* SmartConfig CIPHER options */ #define SMART_CONFIG_CIPHER_SFLASH (0) /* password is not delivered by the application. The Simple Manager should */ /* check if the keys are stored in the Flash. */ #define SMART_CONFIG_CIPHER_AES (1) /* AES (other types are not supported) */ #define SMART_CONFIG_CIPHER_NONE (0xFF) /* do not check in the flash */ #define SL_POLICY_CONNECTION (0x10) #define SL_POLICY_SCAN (0x20) #define SL_POLICY_PM (0x30) #define SL_POLICY_P2P (0x40) #define VAL_2_MASK(position,value) ((1 & (value))<<(position)) #define MASK_2_VAL(position,mask) (((1 << position) & (mask)) >> (position)) #define SL_CONNECTION_POLICY(Auto,Fast,Open,anyP2P,autoSmartConfig) (VAL_2_MASK(0,Auto) | VAL_2_MASK(1,Fast) | VAL_2_MASK(2,Open) | VAL_2_MASK(3,anyP2P) | VAL_2_MASK(4,autoSmartConfig)) #define SL_SCAN_POLICY_EN(policy) (MASK_2_VAL(0,policy)) #define SL_SCAN_POLICY(Enable) (VAL_2_MASK(0,Enable)) #define SL_NORMAL_POLICY (0) #define SL_LOW_LATENCY_POLICY (1) #define SL_LOW_POWER_POLICY (2) #define SL_ALWAYS_ON_POLICY (3) #define SL_LONG_SLEEP_INTERVAL_POLICY (4) #define SL_P2P_ROLE_NEGOTIATE (3) #define SL_P2P_ROLE_GROUP_OWNER (15) #define SL_P2P_ROLE_CLIENT (0) #define SL_P2P_NEG_INITIATOR_ACTIVE (0) #define SL_P2P_NEG_INITIATOR_PASSIVE (1) #define SL_P2P_NEG_INITIATOR_RAND_BACKOFF (2) #define POLICY_VAL_2_OPTIONS(position,mask,policy) ((mask & policy) << position ) #define SL_P2P_POLICY(p2pNegType,p2pNegInitiator) (POLICY_VAL_2_OPTIONS(0,0xF,(p2pNegType > SL_P2P_ROLE_GROUP_OWNER ? SL_P2P_ROLE_GROUP_OWNER : p2pNegType)) | \ POLICY_VAL_2_OPTIONS(4,0x1,(p2pNegType > SL_P2P_ROLE_GROUP_OWNER ? 1:0)) | \ POLICY_VAL_2_OPTIONS(5,0x3, p2pNegInitiator)) /* Info elements */ #define INFO_ELEMENT_DEFAULT_ID (0) /* 221 will be used */ /* info element size is up to 252 bytes (+ 3 bytes of OUI). */ #define INFO_ELEMENT_MAX_SIZE (252) /* For AP - the total length of all info elements is 300 bytes (for example - 4 info elements of 75 bytes each) */ #define INFO_ELEMENT_MAX_TOTAL_LENGTH_AP (300) /* For P2P - the total length of all info elements is 150 bytes (for example - 4 info elements of 40 bytes each) */ #define INFO_ELEMENT_MAX_TOTAL_LENGTH_P2P_GO (160) #define INFO_ELEMENT_AP_ROLE (0) #define INFO_ELEMENT_P2P_GO_ROLE (1) /* we support up to 4 info elements per Role. */ #define MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED (4) #define INFO_ELEMENT_DEFAULT_OUI_0 (0x08) #define INFO_ELEMENT_DEFAULT_OUI_1 (0x00) #define INFO_ELEMENT_DEFAULT_OUI_2 (0x28) #define INFO_ELEMENT_DEFAULT_OUI (0x000000) /* 08, 00, 28 will be used */ /*****************************************************************************/ /* Structure/Enum declarations */ /*****************************************************************************/ typedef enum { RATE_1M = 1, RATE_2M = 2, RATE_5_5M = 3, RATE_11M = 4, RATE_6M = 6, RATE_9M = 7, RATE_12M = 8, RATE_18M = 9, RATE_24M = 10, RATE_36M = 11, RATE_48M = 12, RATE_54M = 13, RATE_MCS_0 = 14, RATE_MCS_1 = 15, RATE_MCS_2 = 16, RATE_MCS_3 = 17, RATE_MCS_4 = 18, RATE_MCS_5 = 19, RATE_MCS_6 = 20, RATE_MCS_7 = 21, MAX_NUM_RATES = 0xFF }SlRateIndex_e; typedef enum { DEV_PW_DEFAULT=0, DEV_PW_PIN_KEYPAD=1, DEV_PW_PUSH_BUTTON=4, DEV_PW_PIN_DISPLAY=5 } sl_p2p_dev_password_method; typedef struct { _u32 status; _u32 ssid_len; _u8 ssid[32]; _u32 private_token_len; _u8 private_token[32]; }slSmartConfigStartAsyncResponse_t; typedef struct { _u16 status; _u16 padding; }slSmartConfigStopAsyncResponse_t; typedef struct { _u16 status; _u16 padding; }slWlanConnFailureAsyncResponse_t; typedef struct { _u8 connection_type;/* 0-STA,3-P2P_CL */ _u8 ssid_len; _u8 ssid_name[32]; _u8 go_peer_device_name_len; _u8 go_peer_device_name[32]; _u8 bssid[6]; _u8 reason_code; _u8 padding[2]; } slWlanConnectAsyncResponse_t; typedef struct { _u8 go_peer_device_name[32]; _u8 mac[6]; _u8 go_peer_device_name_len; _u8 wps_dev_password_id; _u8 own_ssid[32];/* relevant for event sta-connected only */ _u8 own_ssid_len;/* relevant for event sta-connected only */ _u8 padding[3]; }slPeerInfoAsyncResponse_t; typedef union { slSmartConfigStartAsyncResponse_t smartConfigStartResponse; /*SL_WLAN_SMART_CONFIG_COMPLETE_EVENT*/ slSmartConfigStopAsyncResponse_t smartConfigStopResponse; /*SL_WLAN_SMART_CONFIG_STOP_EVENT */ slPeerInfoAsyncResponse_t APModeStaConnected; /* SL_WLAN_STA_CONNECTED_EVENT - relevant only in AP mode - holds information regarding a new STA connection */ slPeerInfoAsyncResponse_t APModestaDisconnected; /* SL_WLAN_STA_DISCONNECTED_EVENT - relevant only in AP mode - holds information regarding a STA disconnection */ slWlanConnectAsyncResponse_t STAandP2PModeWlanConnected; /* SL_WLAN_CONNECT_EVENT - relevant only in STA and P2P mode - holds information regarding a new connection */ slWlanConnectAsyncResponse_t STAandP2PModeDisconnected; /* SL_WLAN_DISCONNECT_EVENT - relevant only in STA and P2P mode - holds information regarding a disconnection */ slPeerInfoAsyncResponse_t P2PModeDevFound; /* SL_WLAN_P2P_DEV_FOUND_EVENT - relevant only in P2P mode */ slPeerInfoAsyncResponse_t P2PModeNegReqReceived; /* SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT - relevant only in P2P mode */ slWlanConnFailureAsyncResponse_t P2PModewlanConnectionFailure; /* SL_WLAN_CONNECTION_FAILED_EVENT - relevant only in P2P mode */ } SlWlanEventData_u; typedef struct { _u32 Event; SlWlanEventData_u EventData; } SlWlanEvent_t; typedef struct { _u32 ReceivedValidPacketsNumber; /* sum of the packets that been received OK (include filtered) */ _u32 ReceivedFcsErrorPacketsNumber; /* sum of the packets that been dropped due to FCS error */ _u32 ReceivedAddressMismatchPacketsNumber; /* sum of the packets that been received but filtered out by one of the HW filters */ _i16 AvarageDataCtrlRssi; /* average RSSI for all valid data packets received */ _i16 AvarageMgMntRssi; /* average RSSI for all valid management packets received */ _u16 RateHistogram[NUM_OF_RATE_INDEXES]; /* rate histogram for all valid packets received */ _u16 RssiHistogram[SIZE_OF_RSSI_HISTOGRAM]; /* RSSI histogram from -40 until -87 (all below and above\n RSSI will appear in the first and last cells */ _u32 StartTimeStamp; /* the time stamp started collecting the statistics in uSec */ _u32 GetTimeStamp; /* the time stamp called the get statistics command */ }SlGetRxStatResponse_t; typedef struct { _u8 ssid[MAXIMAL_SSID_LENGTH]; _u8 ssid_len; _u8 sec_type; _u8 bssid[SL_BSSID_LENGTH]; _i8 rssi; _i8 reserved[3]; }Sl_WlanNetworkEntry_t; typedef struct { _u8 Type; _i8* Key; _u8 KeyLen; }SlSecParams_t; typedef struct { _i8* User; _u8 UserLen; _i8* AnonUser; _u8 AnonUserLen; _u8 CertIndex; /* not supported */ _u32 EapMethod; }SlSecParamsExt_t; typedef struct { _i8 User[32]; _u8 UserLen; _i8 AnonUser[32]; _u8 AnonUserLen; _u8 CertIndex; /* not supported */ _u32 EapMethod; }SlGetSecParamsExt_t; typedef enum { ROLE_STA = 0, ROLE_AP = 2, ROLE_P2P = 3, ROLE_STA_ERR = -1, /* Failure to load MAC/PHY in STA role */ ROLE_AP_ERR = -ROLE_AP, /* Failure to load MAC/PHY in AP role */ ROLE_P2P_ERR = -ROLE_P2P /* Failure to load MAC/PHY in P2P role */ }SlWlanMode_t; typedef struct { _u32 G_Channels_mask; _i32 rssiThershold; }slWlanScanParamCommand_t; typedef struct { _u8 id; _u8 oui[3]; _u16 length; _u8 data[252]; } sl_protocol_InfoElement_t; typedef struct { _u8 index; /* 0 - MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED */ _u8 role; /* bit0: AP = 0, GO = 1 */ sl_protocol_InfoElement_t ie; } sl_protocol_WlanSetInfoElement_t; /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ /*! \brief Connect to wlan network as a station \param[in] pName up to 32 bytes in case of STA the name is the SSID of the Access Point \param[in] NameLen name length \param[in] pMacAddr 6 bytes for MAC address \param[in] pSecParams Security parameters (use NULL key for SL_SEC_TYPE_OPEN) Security types options: \n - SL_SEC_TYPE_OPEN - SL_SEC_TYPE_WEP - SL_SEC_TYPE_WPA_WPA2 - SL_SEC_TYPE_WPA_ENT - SL_SEC_TYPE_WPS_PBC - SL_SEC_TYPE_WPS_PIN \param[in] pSecExtParams Enterprise parameters (set NULL in case Enterprise parameters is not in use) \return On success, zero is returned. On error, negative is returned In case error number (-71) is returned, it indicates a connection was activated while the device it running in AP role \sa sl_WlanDisconnect \note belongs to \ref ext_api \warning In this version only single enterprise mode could be used SL_SEC_TYPE_WPA is a deprecated definition, the new definition is SL_SEC_TYPE_WPA_WPA2 */ #if _SL_INCLUDE_FUNC(sl_WlanConnect) _i16 sl_WlanConnect(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams); #endif /*! \brief wlan disconnect Disconnect connection \return 0 disconnected done, other already disconnected \sa sl_WlanConnect \note belongs to \ref ext_api \warning */ #if _SL_INCLUDE_FUNC(sl_WlanDisconnect) _i16 sl_WlanDisconnect(void); #endif /*! \brief add profile When auto start is enabled, the device connects to a station from the profiles table. Up to 7 profiles are supported. If several profiles configured the device chose the highest priority profile, within each priority group, device will chose profile based on security policy, signal strength, etc parameters. \param[in] pName up to 32 bytes in case of STA the name is the SSID of the Access Point in case of P2P the name is the remote device name \param[in] NameLen name length \param[in] pMacAddr 6 bytes for MAC address \param[in] pSecParams Security parameters - security type (SL_SEC_TYPE_OPEN,SL_SEC_TYPE_WEP,SL_SEC_TYPE_WPA_WPA2, SL_SEC_TYPE_P2P_PBC,SL_SEC_TYPE_P2P_PIN_KEYPAD,SL_SEC_TYPE_P2P_PIN_DISPLAY, SL_SEC_TYPE_WPA_ENT), key, and key length in case of p2p security type pin the key refers to pin code \param[in] pSecExtParams Enterprise parameters - identity, identity length, Anonymous, Anonymous length, CertIndex (not supported, certificates need to be placed in a specific file ID), EapMethod.Use NULL in case Enterprise parameters is not in use \param[in] Priority profile priority. Lowest priority: 0 \param[in] Options Not supported \return On success, profile stored index is returned. On error, negative value is returned \sa sl_WlanProfileGet , sl_WlanProfileDel \note belongs to \ref ext_api \warning Only one Enterprise profile is supported. Please Note that in case of adding an existing profile (compared by pName,pMACAddr and security type) the old profile will be deleted and the same index will be returned. SL_SEC_TYPE_WPA is a deprecated definition, the new definition is SL_SEC_TYPE_WPA_WPA2 */ #if _SL_INCLUDE_FUNC(sl_WlanProfileAdd) _i16 sl_WlanProfileAdd(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams,const _u32 Priority,const _u32 Options); #endif /*! \brief get profile read profile from the device \param[in] Index profile stored index, if index does not exists error is return \param[out] pName up to 32 bytes, in case of sta mode the name of the Access Point in case of p2p mode the name of the Remote Device \param[out] pNameLen name length \param[out] pMacAddr 6 bytes for MAC address \param[out] pSecParams security parameters - security type (SL_SEC_TYPE_OPEN, SL_SEC_TYPE_WEP, SL_SEC_TYPE_WPA_WPA2 or SL_SEC_TYPE_WPS_PBC, SL_SEC_TYPE_WPS_PIN, SL_SEC_TYPE_WPA_ENT,SL_SEC_TYPE_P2P_PBC,SL_SEC_TYPE_P2P_PIN_KEYPAD or SL_SEC_TYPE_P2P_PIN_DISPLAY), key and key length are not in case of p2p security type pin the key refers to pin code return due to security reasons. \param[out] pSecExtParams enterprise parameters - identity, identity length, Anonymous, Anonymous length CertIndex (not supported), EapMethod. \param[out] Priority profile priority \return On success, Profile security type is returned (0 or positive number). On error, -1 is returned \sa sl_WlanProfileAdd , sl_WlanProfileDel \note belongs to \ref ext_api \warning */ #if _SL_INCLUDE_FUNC(sl_WlanProfileGet) _i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAddr, SlSecParams_t* pSecParams, SlGetSecParamsExt_t* pSecExtParams, _u32 *pPriority); #endif /*! \brief Delete WLAN profile Delete WLAN profile \param[in] index number of profile to delete.Possible values are 0 to 6. Index value 255 will delete all saved profiles \return On success, zero is returned. On error, -1 is returned \sa sl_WlanProfileAdd , sl_WlanProfileGet \note belongs to \ref ext_api \warning */ #if _SL_INCLUDE_FUNC(sl_WlanProfileDel) _i16 sl_WlanProfileDel(const _i16 Index); #endif /*! \brief Set policy values \param[in] Type Type of policy to be modified. The Options are:\n - SL_POLICY_CONNECTION - SL_POLICY_SCAN - SL_POLICY_PM - SL_POLICY_P2P \param[in] Policy The option value which depends on action type \param[in] pVal An optional value pointer \param[in] ValLen An optional value length, in bytes \return On success, zero is returned. On error, -1 is returned \sa sl_WlanPolicyGet \note belongs to \ref ext_api \warning \par SL_POLICY_CONNECTION type defines three options available to connect the CC31xx device to the AP: \n - If Auto Connect is set, the CC31xx device tries to automatically reconnect to one of its stored profiles, each time the connection fails or the device is rebooted.\n To set this option, use: \n sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(1,0,0,0,0),NULL,0) - If Fast Connect is set, the CC31xx device tries to establish a fast connection to AP. \n To set this option, use: \n sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,1,0,0,0),NULL,0) - (relevant for P2P mode only) - If Any P2P is set, CC31xx/CC32xx device tries to automatically connect to the first P2P device available, \n supporting push button only. To set this option, use: \n sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,0,0,1,0),NULL,0) - For auto smart config upon restart (any command from Host will end this state) use: \n sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,0,0,0,1),NULL,0) \n The options above could be combined to a single action, if more than one action is required. \n \par SL_POLICY_SCAN defines system scan time interval.Default interval is 10 minutes. \n After settings scan interval, an immediate scan is activated. The next scan will be based on the interval settings. \n - For example, setting scan interval to 1 minute interval use: \n _u32 intervalInSeconds = 60; \n #define SL_SCAN_ENABLE 1 \n sl_WlanPolicySet(SL_POLICY_SCAN,SL_SCAN_ENABLE, (_u8 *)&intervalInSeconds,sizeof(intervalInSeconds)); \n - For example, disable scan: \n #define SL_SCAN_DISABLE 0 \n sl_WlanPolicySet(SL_POLICY_SCAN,SL_SCAN_DISABLE,0,0); \n \par SL_POLICY_PM defines a power management policy for Station mode only: - For setting normal power management (default) policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_NORMAL_POLICY, NULL,0) - For setting low latency power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_LOW_LATENCY_POLICY, NULL,0) - For setting low power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_LOW_POWER_POLICY, NULL,0) - For setting always on power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_ALWAYS_ON_POLICY, NULL,0) - For setting Long Sleep Interval policy use: \n _u16 PolicyBuff[4] = {0,0,800,0}; // PolicyBuff[2] is max sleep time in mSec \n sl_WlanPolicySet(SL_POLICY_PM , SL_LONG_SLEEP_INTERVAL_POLICY, (_u8*)PolicyBuff,sizeof(PolicyBuff)); \n SL_POLICY_P2P defines p2p negotiation policy parameters for P2P role: - To set intent negotiation value, set on of the following: SL_P2P_ROLE_NEGOTIATE - intent 3 SL_P2P_ROLE_GROUP_OWNER - intent 15 SL_P2P_ROLE_CLIENT - intent 0 - To set negotiation initiator value (initiator policy of first negotiation action frame), set on of the following: SL_P2P_NEG_INITIATOR_ACTIVE SL_P2P_NEG_INITIATOR_PASSIVE SL_P2P_NEG_INITIATOR_RAND_BACKOFF For example: \n sl_WlanPolicySet(SL_POLICY_P2P, SL_P2P_POLICY(SL_P2P_ROLE_NEGOTIATE,SL_P2P_NEG_INITIATOR_RAND_BACKOFF),NULL,0) */ #if _SL_INCLUDE_FUNC(sl_WlanPolicySet) _i16 sl_WlanPolicySet(const _u8 Type , const _u8 Policy, _u8 *pVal,const _u8 ValLen); #endif /*! \brief get policy values \param[in] Type SL_POLICY_CONNECTION, SL_POLICY_SCAN, SL_POLICY_PM,SL_POLICY_P2P \n \param[in] Policy argument may be set to any value \n \param[out] The returned values, depends on each policy type, will be stored in the allocated buffer pointed by pVal with a maximum buffer length set by the calling function and pointed to by argument *pValLen \return On success, zero is returned. On error, -1 is returned \sa sl_WlanPolicySet \note belongs to \ref ext_api \warning The value pointed by the argument *pValLen should be set to a value different from 0 and greater than the buffer length returned from the SL device. Otherwise, an error will be returned. */ #if _SL_INCLUDE_FUNC(sl_WlanPolicyGet) _i16 sl_WlanPolicyGet(const _u8 Type , _u8 Policy,_u8 *pVal,_u8 *pValLen); #endif /*! \brief Gets the WLAN scan operation results Gets scan results , gets entry from scan result table \param[in] Index - Starting index identifier (range 0-19) for getting scan results \param[in] Count - How many entries to fetch. Max is (20-"Index"). \param[out] pEntries - pointer to an allocated Sl_WlanNetworkEntry_t. the number of array items should match "Count" sec_type: SL_SCAN_SEC_TYPE_OPEN, SL_SCAN_SEC_TYPE_WEP, SL_SCAN_SEC_TYPE_WPA or SL_SCAN_SEC_TYPE_WPA2 \return Number of valid networks list items \sa \note belongs to \ref ext_api \warning This command do not initiate any active scanning action \par Example: \code An example of fetching max 10 results: Sl_WlanNetworkEntry_t netEntries[10]; _i16 resultsCount = sl_WlanGetNetworkList(0,10,&netEntries[0]); for(i=0; i< resultsCount; i++) { printf("%s\n",netEntries[i].ssid); } \endcode */ #if _SL_INCLUDE_FUNC(sl_WlanGetNetworkList) _i16 sl_WlanGetNetworkList(const _u8 Index,const _u8 Count, Sl_WlanNetworkEntry_t *pEntries); #endif /*! \brief Start collecting wlan RX statistics, for unlimited time. \return On success, zero is returned. On error, -1 is returned \sa sl_WlanRxStatStop sl_WlanRxStatGet \note belongs to \ref ext_api \warning \par Example: \code Getting wlan RX statistics: void RxStatCollectTwice() { SlGetRxStatResponse_t rxStat; _i16 rawSocket; _i8 DataFrame[200]; struct SlTimeval_t timeval; timeval.tv_sec = 0; // Seconds timeval.tv_usec = 20000; // Microseconds. 10000 microseconds resolution sl_WlanRxStatStart(); // set statistics mode rawSocket = sl_Socket(SL_AF_RF, SL_SOCK_RAW, eChannel); // set timeout - in case we have no activity for the specified channel sl_SetSockOpt(rawSocket,SL_SOL_SOCKET,SL_SO_RCVTIMEO, &timeval, sizeof(timeval)); // Enable receive timeout status = sl_Recv(rawSocket, DataFrame, sizeof(DataFrame), 0); Sleep(1000); // sleep for 1 sec sl_WlanRxStatGet(&rxStat,0); // statistics has been cleared upon read Sleep(1000); // sleep for 1 sec sl_WlanRxStatGet(&rxStat,0); } \endcode */ #if _SL_INCLUDE_FUNC(sl_WlanRxStatStart) _i16 sl_WlanRxStatStart(void); #endif /*! \brief Stop collecting wlan RX statistic, (if previous called sl_WlanRxStatStart) \return On success, zero is returned. On error, -1 is returned \sa sl_WlanRxStatStart sl_WlanRxStatGet \note belongs to \ref ext_api \warning */ #if _SL_INCLUDE_FUNC(sl_WlanRxStatStop) _i16 sl_WlanRxStatStop(void); #endif /*! \brief Get wlan RX statistics. upon calling this command, the statistics counters will be cleared. \param[in] Flags should be 0 ( not applicable right now, will be added the future ) \param[in] pRxStat a pointer to SlGetRxStatResponse_t filled with Rx statistics results \return On success, zero is returned. On error, -1 is returned \sa sl_WlanRxStatStart sl_WlanRxStatStop \note belongs to \ref ext_api \warning */ #if _SL_INCLUDE_FUNC(sl_WlanRxStatGet) _i16 sl_WlanRxStatGet(SlGetRxStatResponse_t *pRxStat,const _u32 Flags); #endif /*! \brief Stop Smart Config procedure. Once Smart Config will be stopped, Asynchronous event will be received - SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE. \param[in] none \param[out] none \return 0 - if Stop Smart Config is about to be executed without errors. \sa sl_WlanSmartConfigStart \note belongs to \ref ext_api \warning */ #if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStop) _i16 sl_WlanSmartConfigStop(void); #endif /*! \brief Start Smart Config procedure \par The target of the procedure is to let the \n device to gain the network parameters: SSID and Password (if network is secured) \n and to connect to it once located in the network range. \n An external application should be used on a device connected to any mobile network. \n The external application will transmit over the air the network parameters in secured manner.\n The Password may be decrypted using a Key. \n The decryption method may be decided in the command or embedded in the Flash. \n The procedure can be activated for 1-3 group ID in the range of BIT_0 - BIT_15 where the default group ID id 0 (BIT_0) \n Once Smart Config has ended successfully, Asynchronous event will be received - \n SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE. \n The Event will hold the SSID and an extra field that might have been delivered as well (i.e. - device name) \param[in] groupIdBitmask - each bit represent a group ID that should be searched. The Default group ID id BIT_0. 2 more group can be searched in addition. The range is BIT_0 - BIT_15. \param[in] chiper - 0: check in flash, 1 - AES, 0xFF - do not check in flash \param[in] publicKeyLen - public key len (used for the default group ID - BIT_0) \param[in] group1KeyLen - group ID1 length \param[in] group2KeyLen - group ID2 length \param[in] publicKey - public key (used for the default group ID - BIT_0) \param[in] group1Key - group ID1 key \param[in] group2Key - group ID2 key \param[out] none \return 0 - if Smart Config started successfully. \sa sl_WlanSmartConfigStop \note belongs to \ref ext_api \warning \par \code An example of starting smart Config on group ID's 0 + 1 + 2 sl_WlanSmartConfigStart(7, //group ID's (BIT_0 | BIT_1 | BIT_2) 1, //decrypt key by AES method 16, //decryption key length for group ID0 16, //decryption key length for group ID1 16, //decryption key length for group ID2 "Key0Key0Key0Key0", //decryption key for group ID0 "Key1Key1Key1Key1", //decryption key for group ID1 "Key2Key2Key2Key2" //decryption key for group ID2 ); \endcode */ #if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStart) _i16 sl_WlanSmartConfigStart(const _u32 groupIdBitmask, const _u8 cipher, const _u8 publicKeyLen, const _u8 group1KeyLen, const _u8 group2KeyLen, const _u8* publicKey, const _u8* group1Key, const _u8* group2Key); #endif /*! \brief Wlan set mode Setting WLAN mode \param[in] mode - WLAN mode to start the CC31xx device. Possible options are: - ROLE_STA - for WLAN station mode - ROLE_AP - for WLAN AP mode - ROLE_P2P -for WLAN P2P mode \return 0 - if mode was set correctly \sa sl_Start sl_Stop \note belongs to \ref ext_api \warning After setting the mode the system must be restarted for activating the new mode \par Example: \code //Switch from any role to STA: sl_WlanSetMode(ROLE_STA); sl_Stop(0); sl_Start(NULL,NULL,NULL); \endcode */ #if _SL_INCLUDE_FUNC(sl_WlanSetMode) _i16 sl_WlanSetMode(const _u8 mode); #endif /*! \brief Internal function for setting WLAN configurations \return On success, zero is returned. On error one of the following error codes returned: - CONF_ERROR (-1) - CONF_NVMEM_ACCESS_FAILED (-2) - CONF_OLD_FILE_VERSION (-3) - CONF_ERROR_NO_SUCH_COUNTRY_CODE (-4) \param[in] ConfigId - configuration id - SL_WLAN_CFG_AP_ID - SL_WLAN_CFG_GENERAL_PARAM_ID - SL_WLAN_CFG_P2P_PARAM_ID \param[in] ConfigOpt - configurations option - SL_WLAN_CFG_AP_ID - WLAN_AP_OPT_SSID \n Set SSID for AP mode. \n This options takes _u8 buffer as parameter - WLAN_AP_OPT_CHANNEL \n Set channel for AP mode. \n The channel is dependant on the country code which is set. i.e. for "US" the channel should be in the range of [1-11] \n This option takes _u8 as a parameter - WLAN_AP_OPT_HIDDEN_SSID \n Set Hidden SSID Mode for AP mode.Hidden options: \n 0: disabled \n 1: Send empty (length=0) SSID in beacon and ignore probe request for broadcast SSID \n 2: Clear SSID (ASCII 0), but keep the original length (this may be required with some \n clients that do not support empty SSID) and ignore probe requests for broadcast SSID \n This option takes _u8 as a parameter - WLAN_AP_OPT_SECURITY_TYPE \n Set Security type for AP mode. Security options are: - Open security: SL_SEC_TYPE_OPEN - WEP security: SL_SEC_TYPE_WEP - WPA security: SL_SEC_TYPE_WPA_WPA2 \n This option takes _u8 pointer as a parameter - WLAN_AP_OPT_PASSWORD \n Set Password for for AP mode (for WEP or for WPA): \n Password - for WPA: 8 - 63 characters \n for WEP: 5 / 13 characters (ascii) \n This options takes _u8 buffer as parameter - SL_WLAN_CFG_GENERAL_PARAM_ID - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS \n Set scan parameters. This option uses slWlanScanParamCommand_t as parameter - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE \n Set Country Code for AP mode \n This options takes _u8 2 bytes buffer as parameter - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER \n Set STA mode Tx power level \n Number between 0-15, as dB offset from max power (0 will set MAX power) \n This options takes _u8 as parameter - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER Set AP mode Tx power level \n Number between 0-15, as dB offset from max power (0 will set MAX power) \n This options takes _u8 as parameter - WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT Set Info Element for AP mode. \n The Application can set up to MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED info elements per Role (AP / P2P GO). \n To delete an info element use the relevant index and length = 0. \n The Application can set up to MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED to the same role. \n However, for AP - no more than INFO_ELEMENT_MAX_TOTAL_LENGTH_AP bytes can be stored for all info elements. \n For P2P GO - no more than INFO_ELEMENT_MAX_TOTAL_LENGTH_P2P_GO bytes can be stored for all info elements. \n This option takes sl_protocol_WlanSetInfoElement_t as parameter - SL_WLAN_CFG_P2P_PARAM_ID - WLAN_P2P_OPT_DEV_TYPE \n Set P2P Device type.Maximum length of 17 characters. Device type is published under P2P I.E, \n allows to make devices easier to recognize. \n In case no device type is set, the default type is "1-0050F204-1" \n This options takes _u8 buffer as parameter - WLAN_P2P_OPT_CHANNEL_N_REGS \n Set P2P Channels. \n listen channel (either 1/6/11 for 2.4GHz) \n listen regulatory class (81 for 2.4GHz) \n oper channel (either 1/6/11 for 2.4GHz) \n oper regulatory class (81 for 2.4GHz) \n listen channel and regulatory class will determine the device listen channel during p2p find listen phase \n oper channel and regulatory class will determine the operating channel preferred by this device (in case it is group owner this will be the operating channel) \n channels should be one of the social channels (1/6/11). In case no listen/oper channel selected, a random 1/6/11 will be selected. This option takes pointer to _u8[4] as parameter \param[in] ConfigLen - configurations len \param[in] pValues - configurations values \sa \note \warning \par Examples: \par WLAN_AP_OPT_SSID: \code _u8 str[33]; memset(str, 0, 33); memcpy(str, ssid, len); // ssid string of 32 characters sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID, strlen(ssid), str); \endcode \par WLAN_AP_OPT_CHANNEL: \code _u8 val = channel; sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_CHANNEL, 1, (_u8 *)&val); \endcode \par WLAN_AP_OPT_HIDDEN_SSID: \code _u8 val = hidden; sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_HIDDEN_SSID, 1, (_u8 *)&val); \endcode \par WLAN_AP_OPT_SECURITY_TYPE: \code _u8 val = SL_SEC_TYPE_WPA_WPA2; sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SECURITY_TYPE, 1, (_u8 *)&val); \endcode \par WLAN_AP_OPT_PASSWORD: \code _u8 str[65]; _u16 len = strlen(password); memset(str, 0, 65); memcpy(str, password, len); sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, len, (_u8 *)str); \endcode \par WLAN_GENERAL_PARAM_OPT_STA_TX_POWER: \code _u8 stapower=(_u8)power; sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER,1,(_u8 *)&stapower); \endcode \par WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS: \code slWlanScanParamCommand_t ScanParamConfig; ScanParamConfig.G_Channels_mask = 0x01; // bit mask for channels:1 means channel 1 is enabled, 3 means channels 1 + 2 are enabled ScanParamConfig.rssiThershold = -70; // only for RSSI level which is higher than -70 sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID ,WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS,sizeof(slWlanScanParamCommand_t),(_u8*)&ScanParamConfig); \endcode \par WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE: \code _u8* str = (_u8 *) country; // string of 2 characters. i.e. - "US" sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, str); \endcode \par WLAN_GENERAL_PARAM_OPT_AP_TX_POWER: \code _u8 appower=(_u8)power; sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_AP_TX_POWER,1,(_u8 *)&appower); \endcode \par WLAN_P2P_OPT_DEV_TYPE: \code _u8 str[17]; _u16 len = strlen(device_type); memset(str, 0, 17); memcpy(str, device_type, len); sl_WlanSet(SL_WLAN_CFG_P2P_PARAM_ID, WLAN_P2P_OPT_DEV_TYPE, len, str); \endcode \par WLAN_P2P_OPT_CHANNEL_N_REGS: \code _u8 str[4]; str[0] = (_u8)11; // listen channel str[1] = (_u8)81; // listen regulatory class str[2] = (_u8)6; // oper channel str[3] = (_u8)81; // oper regulatory class sl_WlanSet(SL_WLAN_CFG_P2P_PARAM_ID, WLAN_P2P_OPT_CHANNEL_N_REGS, 4, str); \endcode \par WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT: \code sl_protocol_WlanSetInfoElement_t infoele; infoele.index = Index; // Index of the info element. range: 0 - MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED infoele.role = Role; // INFO_ELEMENT_AP_ROLE (0) or INFO_ELEMENT_P2P_GO_ROLE (1) infoele.ie.id = Id; // Info element ID. if INFO_ELEMENT_DEFAULT_ID (0) is set, ID will be set to 221. // Organization unique ID. If all 3 bytes are zero - it will be replaced with 08,00,28. infoele.ie.oui[0] = Oui0; // Organization unique ID first Byte infoele.ie.oui[1] = Oui1; // Organization unique ID second Byte infoele.ie.oui[2] = Oui2; // Organization unique ID third Byte infoele.ie.length = Len; // Length of the info element. must be smaller than 253 bytes memset(infoele.ie.data, 0, INFO_ELEMENT_MAX_SIZE); if ( Len <= INFO_ELEMENT_MAX_SIZE ) { memcpy(infoele.ie.data, IE, Len); // Info element. length of the info element is [0-252] sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT,sizeof(sl_protocol_WlanSetInfoElement_t),(_u8* ) &infoele); } sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT,sizeof(sl_protocol_WlanSetInfoElement_t),(_u8* ) &infoele); \endcode */ #if _SL_INCLUDE_FUNC(sl_WlanSet) _i16 sl_WlanSet(const _u16 ConfigId ,const _u16 ConfigOpt,const _u16 ConfigLen,const _u8 *pValues); #endif /*! \brief Internal function for getting WLAN configurations \return On success, zero is returned. On error, -1 is returned \param[in] ConfigId - configuration id - SL_WLAN_CFG_AP_ID - SL_WLAN_CFG_GENERAL_PARAM_ID - SL_WLAN_CFG_P2P_PARAM_ID \param[out] pConfigOpt - get configurations option - SL_WLAN_CFG_AP_ID - WLAN_AP_OPT_SSID \n Get SSID for AP mode. \n Get up to 32 characters of SSID \n This options takes _u8 as parameter - WLAN_AP_OPT_CHANNEL \n Get channel for AP mode. \n This option takes _u8 as a parameter - WLAN_AP_OPT_HIDDEN_SSID \n Get Hidden SSID Mode for AP mode.Hidden options: \n 0: disabled \n 1: Send empty (length=0) SSID in beacon and ignore probe request for broadcast SSID \n 2: Clear SSID (ASCII 0), but keep the original length (this may be required with some \n clients that do not support empty SSID) and ignore probe requests for broadcast SSID \n This option takes _u8 as a parameter - WLAN_AP_OPT_SECURITY_TYPE \n Get Security type for AP mode. Security options are: - Open security: SL_SEC_TYPE_OPEN - WEP security: SL_SEC_TYPE_WEP - WPA security: SL_SEC_TYPE_WPA_WPA2 \n This option takes _u8 as a parameter - WLAN_AP_OPT_PASSWORD \n Get Password for for AP mode (for WEP or for WPA): \n Returns password - string, fills up to 64 characters. \n This options takes _u8 buffer as parameter - SL_WLAN_CFG_GENERAL_PARAM_ID - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS \n Get scan parameters. This option uses slWlanScanParamCommand_t as parameter - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE \n Get Country Code for AP mode \n This options takes _u8 buffer as parameter - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER \n Get STA mode Tx power level \n Number between 0-15, as dB offset from max power (0 indicates MAX power) \n This options takes _u8 as parameter - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER Get AP mode Tx power level \n Number between 0-15, as dB offset from max power (0 indicates MAX power) \n This options takes _u8 as parameter - SL_WLAN_CFG_P2P_PARAM_ID - WLAN_P2P_OPT_CHANNEL_N_REGS \n Get P2P Channels. \n listen channel (either 1/6/11 for 2.4GHz) \n listen regulatory class (81 for 2.4GHz) \n oper channel (either 1/6/11 for 2.4GHz) \n oper regulatory class (81 for 2.4GHz) \n listen channel and regulatory class will determine the device listen channel during p2p find listen phase \n oper channel and regulatory class will determine the operating channel preferred by this device (in case it is group owner this will be the operating channel) \n channels should be one of the social channels (1/6/11). In case no listen/oper channel selected, a random 1/6/11 will be selected. \n This option takes pointer to _u8[4] as parameter \param[out] pConfigLen - The length of the allocated memory as input, when the function complete, the value of this parameter would be the len that actually read from the device. If the device return length that is longer from the input value, the function will cut the end of the returned structure and will return SL_ESMALLBUF. \param[out] pValues - get configurations values \sa sl_WlanSet \note \warning \par Examples: \par WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS: \code slWlanScanParamCommand_t ScanParamConfig; _u16 Option = WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS; _u16 OptionLen = sizeof(slWlanScanParamCommand_t); sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&ScanParamConfig); \endcode \par WLAN_GENERAL_PARAM_OPT_AP_TX_POWER: \code _i8 TXPower = 0; _u16 Option = WLAN_GENERAL_PARAM_OPT_AP_TX_POWER; _u16 OptionLen = sizeof(_i8); sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&TXPower); \endcode \par WLAN_GENERAL_PARAM_OPT_STA_TX_POWER: \code _i8 TXPower = 0; _u16 Option = WLAN_GENERAL_PARAM_OPT_STA_TX_POWER; _u16 OptionLen = sizeof(_i8); sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&TXPower); \endcode \par WLAN_P2P_OPT_DEV_TYPE: \code _i8 device_type[18]; _u16 len = 18; _u16 config_opt = WLAN_P2P_OPT_DEV_TYPE; sl_WlanGet(SL_WLAN_CFG_P2P_PARAM_ID, &config_opt , &len, (_u8* )device_type); \endcode \par WLAN_AP_OPT_SSID: \code _i8 ssid[32]; _u16 len = 32; _u16 config_opt = WLAN_AP_OPT_SSID; sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt , &len, (_u8* )ssid); \endcode \par WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE: \code _i8 country[3]; _u16 len = 3; _u16 config_opt = WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE; sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID, &config_opt, &len, (_u8* )country); \endcode \par WLAN_AP_OPT_CHANNEL: \code _i8 channel; _u16 len = 1; _u16 config_opt = WLAN_AP_OPT_CHANNEL; sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&channel); \endcode \par WLAN_AP_OPT_HIDDEN_SSID: \code _u8 hidden; _u16 len = 1; _u16 config_opt = WLAN_AP_OPT_HIDDEN_SSID; sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&hidden); \endcode \par WLAN_AP_OPT_SECURITY_TYPE: \code _u8 sec_type; _u16 len = 1; _u16 config_opt = WLAN_AP_OPT_SECURITY_TYPE; sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&sec_type); \endcode \par WLAN_AP_OPT_PASSWORD: \code _u8 password[64]; _u16 len = 64; memset(password,0,64); _u16 config_opt = WLAN_AP_OPT_PASSWORD; sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )password); \endcode \par WLAN_P2P_OPT_CHANNEL_N_REGS: \code _u16 listen_channel,listen_reg,oper_channel,oper_reg; _u16 len = 4; _u16 config_opt = WLAN_P2P_OPT_CHANNEL_N_REGS; _u8 channel_n_regs[4]; sl_WlanGet(SL_WLAN_CFG_P2P_PARAM_ID, &config_opt, &len, (_u8* )channel_n_regs); listen_channel = channel_n_regs[0]; listen_reg = channel_n_regs[1]; oper_channel = channel_n_regs[2]; oper_reg = channel_n_regs[3]; \endcode */ #if _SL_INCLUDE_FUNC(sl_WlanGet) _i16 sl_WlanGet(const _u16 ConfigId, _u16 *pConfigOpt,_u16 *pConfigLen, _u8 *pValues); #endif /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __WLAN_H__ */ micropython-1.12/drivers/cc3100/inc/wlan_rx_filters.h000066400000000000000000001042711357706137100225220ustar00rootroot00000000000000/* * wlan_rx_filters.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #ifndef RX_FILTERS_PREPROCESSOR_CLI_IF_H_ #define RX_FILTERS_PREPROCESSOR_CLI_IF_H_ #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ /*! * \def SL_RX_FILTER_MAX_FILTERS * The Max number of filters for 64 filters */ #define SL_RX_FILTER_MAX_FILTERS 64 /*! * \def SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS * The Max number of software filters */ #define SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS (32) /*! * \def SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS * */ #define SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS (2) /*! * \def SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS * */ #define SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS (2) /*! * \def SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS * */ #define SL_RX_FILTER_NUM_OF_COMBINATION_TYPE_ARGS (2) /*! * \def SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH * */ #define SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH (32) /* List of possible error numbers */ #define RXFL_OK (0) /* O.K */ #define RXFL_OUTPUT_OR_INPUT_BUFFER_LENGTH_TOO_SMALL (76) /* ! The output buffer length is smaller than required for that operation */ #define RXFL_DEPENDENT_FILTER_SOFTWARE_FILTER_NOT_FIT (75) /* Node filter can't be child of software filter and vice_versa */ #define RXFL_DEPENDENCY_IS_NOT_PERSISTENT (74) /* Dependency filter is not persistent */ #define RXFL_SYSTEM_STATE_NOT_SUPPORTED_FOR_THIS_FILTER (72) /* System state is not supported */ #define RXFL_TRIGGER_USE_REG5_TO_REG8 (71) /* Only counters 5 - 8 are allowed, for Tigger */ #define RXFL_TRIGGER_USE_REG1_TO_REG4 (70) /* Only counters 1 - 4 are allowed, for trigger */ #define RXFL_ACTION_USE_REG5_TO_REG8 (69) /* Only counters 5 - 8 are allowed, for action */ #define RXFL_ACTION_USE_REG1_TO_REG4 (68) /* Only counters 1 - 4 are allowed, for action */ #define RXFL_FIELD_SUPPORT_ONLY_EQUAL_AND_NOTEQUAL (67) /* Rule compare function Id is out of range */ #define RXFL_WRONG_MULTICAST_BROADCAST_ADDRESS (66) /* The address should be of type mutlicast or broadcast */ #define RXFL_THE_FILTER_IS_NOT_OF_HEADER_TYPE (65) /* The filter should be of header type */ #define RXFL_WRONG_COMPARE_FUNC_FOR_BROADCAST_ADDRESS (64) /* The compare funcion is not suitable for broadcast address */ #define RXFL_WRONG_MULTICAST_ADDRESS (63) /* The address should be of muticast type */ #define RXFL_DEPENDENT_FILTER_IS_NOT_PERSISTENT (62) /* The dependency filter is not persistent */ #define RXFL_DEPENDENT_FILTER_IS_NOT_ENABLED (61) /* The dependency filter is not enabled */ #define RXFL_FILTER_HAS_CHILDS (60) /* The filter has childs and can't be removed */ #define RXFL_CHILD_IS_ENABLED (59) /* Can't disable filter while the child is enabled */ #define RXFL_DEPENDENCY_IS_DISABLED (58) /* Can't enable filetr in case its depndency filter is disabled */ #define RXFL_NUMBER_OF_CONNECTION_POINTS_EXCEEDED (52) /* Number of connection points exceeded */ #define RXFL_DEPENDENT_FILTER_DEPENDENCY_ACTION_IS_DROP (51) /* The dependent filter has Drop action, thus the filter can't be created */ #define RXFL_FILTER_DO_NOT_EXISTS (50) /* The filter doesn't exists */ #define RXFL_DEPEDENCY_NOT_ON_THE_SAME_LAYER (49) /* The filter and its dependency must be on the same layer */ #define RXFL_NUMBER_OF_ARGS_EXCEEDED (48) /* Number of arguments excceded */ #define RXFL_ACTION_NO_REG_NUMBER (47) /* Action require counter number */ #define RXFL_DEPENDENT_FILTER_LAYER_DO_NOT_FIT (46) /* the filter and its dependency should be from the same layer */ #define RXFL_DEPENDENT_FILTER_SYSTEM_STATE_DO_NOT_FIT (45) /* The filter and its dependency system state don't fit */ #define RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_2 (44) /* The parent filter don't exist */ #define RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_1 (43) /* The parent filter is null */ #define RXFL_RULE_HEADER_ACTION_TYPE_NOT_SUPPORTED (42) /* The action type is not supported */ #define RXFL_RULE_HEADER_TRIGGER_COMPARE_FUNC_OUT_OF_RANGE (41) /* The Trigger comparision function is out of range */ #define RXFL_RULE_HEADER_TRIGGER_OUT_OF_RANGE (40) /* The Trigger is out of range */ #define RXFL_RULE_HEADER_COMPARE_FUNC_OUT_OF_RANGE (39) /* The rule compare function is out of range */ #define RXFL_FRAME_TYPE_NOT_SUPPORTED (38) /* ASCII frame type string is illegal */ #define RXFL_RULE_FIELD_ID_NOT_SUPPORTED (37) /* Rule field ID is out of range */ #define RXFL_RULE_HEADER_FIELD_ID_ASCII_NOT_SUPPORTED (36) /* This ASCII field ID is not supported */ #define RXFL_RULE_HEADER_NOT_SUPPORTED (35) /* The header rule is not supported on current release */ #define RXFL_RULE_HEADER_OUT_OF_RANGE (34) /* The header rule is out of range */ #define RXFL_RULE_HEADER_COMBINATION_OPERATOR_OUT_OF_RANGE (33) /* Combination function Id is out of ramge */ #define RXFL_RULE_HEADER_FIELD_ID_OUT_OF_RANGE (32) /* rule field Id is out of range */ #define RXFL_UPDATE_NOT_SUPPORTED (31) /* Update not supported */ #define RXFL_NO_FILTERS_ARE_DEFINED (24) /* No filters are defined in the system */ #define RXFL_NUMBER_OF_FILTER_EXCEEDED (23) /* Number of max filters excceded */ /******************************************************************************/ /* Type declarations */ /******************************************************************************/ /*! * \typedef SlrxFilterID_t * Unique filter ID which is allocated by the system , negative number means error */ typedef _i8 SlrxFilterID_t; /*! * \typedef SlrxFilterCompareMask_t * The mask is used for the rule comparison function */ typedef _u8 SlrxFilterCompareMask_t; /*! * \typedef SlrxFilterIdMask_t * Representation of filters Id as a bit field * The bit field is used to declare which filters are involved * in operation. Number of filter can be up to 128 filters. i.e. 128 bits are needed. * On the current release, up to 64 filters can be defined. */ typedef _u8 SlrxFilterIdMask_t[128/8]; /*! * \typedef SlrxFilterPrePreparedFilters_t * Describes the supported software filter sets, */ typedef _u8 SlrxFilterPrePreparedFilters_t; #define SL_ARP_AUTO_REPLY_PRE_PREPARED_FILTERS (0) #define SL_MULTICASTSIPV4_DROP_PREPREPARED_FILTERS (1) #define SL_MULTICASTSIPV6_DROP_PREPREPARED_FILTERS (2) #define SL_MULTICASTSWIFI_DROP_PREPREPARED_FILTERS (3) /*! * \typedef SlrxFilterPrePreparedFiltersMask_t * Describes the supported software filter sets, * each bit represents different software filter set * The filter sets are defined at SlrxFilterPrePreparedFilters_t */ typedef _u8 SlrxFilterPrePreparedFiltersMask_t[SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS/8]; /*! \typedef SlrxFilterRegxPattern_t * The struct contains the regular expression pattern which is used in case of payload rule. * Not supported in the current release */ typedef struct SlrxFilterRegxPattern_t { _u8 x[SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH]; }SlrxFilterRegxPattern_t; /*! \typedef SlrxFilterAsciiArg_t * The buffer is used to provide container for ASCII argument, which may be used in case of HEADER rule. * example for ASCII argument can be : IP = 256.0.67.1 */ typedef _u8 SlrxFilterAsciiArg_t; /*! \typedef SlrxFilterBinaryArg_t * The buffer provides container for binary argument, which may be used in case of HEADER rule */ typedef _u8 SlrxFilterBinaryArg_t ; /*! \typedef SlrxFilterActionArg_t * Provides container for the filter action argument. * for example: in case action is to send automatic response , the argument is the template to be used for the automatic response. * * */ typedef _u8 SlrxFilterActionArg_t ; /*! \typedef SlrxFilterOffset_t * The offset relative to the packet payload start location. * Not supported on current release */ typedef _u32 SlrxFilterOffset_t; /*! \typedef SlrxFilterRuleType_t * Enumerates the different filter types. * On the current release only HEADER and COMBINATION are supported. */ typedef _u8 SlrxFilterRuleType_t; /* possible values for SlrxFilterRuleType_t */ #define HEADER (0) #define COMBINATION (1) #define EXACT_PATTERN (2) #define LIKELIHOOD_PATTERN (3) #define ALWAYS_TRUE (4) #define NUM_OF_FILTER_TYPES (5) /*! \typedef SlrxFilterFlags_t * Bit field which sets the behaviour of the RX filter * */ #define RX_FILTER_BINARY (0x1) #define RX_FILTER_PERSISTENT (0x8) #define RX_FILTER_ENABLE (0x10) typedef union SlrxFilterFlags_t { /* struct { */ /*! * The filter argument can be set as binary argument or ASCII arguments. * When the bit is on the argument are binary. */ /* _u8 Binary: 1; */ /*! * */ /* _u8 AutoSort : 1; */ /*! * */ /* _u8 AutoFaultDetect : 1; */ /*! * When the bit is on it means the the node is enabled . */ /* _u8 Enabled : 1; */ /* _u8 padding : 3; */ /* };*/ _u8 IntRepresentation; }SlrxFilterFlags_t; /*! \typedef SlrxFilterCompareFunction_t * Used as comparison function for the header type arguments * */ typedef _u8 SlrxFilterCompareFunction_t; /* Possible values for SlrxFilterCompareFunction_t */ #define COMPARE_FUNC_IN_BETWEEN (0) #define COMPARE_FUNC_EQUAL (1) #define COMPARE_FUNC_NOT_EQUAL_TO (2) #define COMPARE_FUNC_NOT_IN_BETWEEN (3) #define COMPARE_FUNC_NUM_OF_FILTER_COMPARE_FUNC (4) /*! \typedef SlrxFilterCompareFunction_t * Used as comparison function for the header type arguments * */ typedef _u8 SlrxTriggerCompareFunction_t; /* Possible values for SlrxTriggerCompareFunction_t */ #define TRIGGER_COMPARE_FUNC_EQUAL (0) /* arg1 == protocolVal ,not supported in current release */ #define TRIGGER_COMPARE_FUNC_NOT_EQUAL_TO (1) /* arg1 == protocolVal */ #define TRIGGER_COMPARE_FUNC_SMALLER_THAN (2) /* arg1 == protocolVal */ #define TRIGGER_COMPARE_FUNC_BIGGER_THAN (3) /* definition */ #define TRIGGER_COMPARE_FUNC_NUM_OF_FILTER_COMPARE_FUNC (4) /*! \typedef SlrxFilterHdrField_t * Provides list of possible header types which may be defined as part of the rule * */ typedef _u8 SlrxFilterHdrField_t; /* Possible values for SlrxFilterHdrField_t */ #define NULL_FIELD_ID_TYPE (0) /* 802.11 control\data\management */ #define FRAME_TYPE_FIELD (1) /* 802.11 beacon\probe\.. */ #define FRAME_SUBTYPE_FIELD (2) /* 802.11 bssid type */ #define BSSID_FIELD (3) /* */ #define MAC_SRC_ADDRESS_FIELD (4) /* */ #define MAC_DST_ADDRESS_FIELD (5) /* */ #define FRAME_LENGTH_FIELD (6) /* */ #define PROTOCOL_TYPE_FIELD (7) /* */ #define IP_VERSION_FIELD (8) /* TCP / UDP */ #define IP_PROTOCOL_FIELD (9) /* */ #define IPV4_SRC_ADRRESS_FIELD (10) /* */ #define IPV4_DST_ADDRESS_FIELD (11) /* */ #define IPV6_SRC_ADRRESS_FIELD (12) /* */ #define IPV6_DST_ADDRESS_FIELD (13) /* */ #define SRC_PORT_FIELD (14) /* */ #define DST_PORT_FIELD (15) /* Definition */ #define NUM_OF_FIELD_NAME_FIELD (16) /*! \union SlrxFilterHeaderArg_t * The structure holds the header ARGS which are used in case of HDR rule. */ /* -- 36 bytes */ typedef union SlrxFilterHeaderArg_t { /*----------------------------- Large size ---------------------------------*/ /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS * example : IPV6 16 bytes, 39 characters * ipv6 Ascii address: 2001:0db8:3c4d:0015:0000:0000:abcd:ef12 */ SlrxFilterBinaryArg_t RxFilterDB16BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][16 ]; /* Binary Values for comparition */ /*! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS * example : IPV6 16 bytes, 39 characters * ipv6 Ascii address: 2001:0db8:3c4d:0015:0000:0000:abcd:ef12 * Ascii format for ipV6 is not supported */ /*----------------------------- Medium size ---------------------------------*/ /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS * MAC address: 6 bytes, 17 chars */ SlrxFilterBinaryArg_t RxFilterDB6BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][6]; /* Binary Values for comparition */ /*! * ! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS * IP address: 4 bytes, 15 chars * 2 bytes are added for padding */ SlrxFilterAsciiArg_t RxFilterDB18BytesAsciiRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][18]; /* Ascii Values for comparison */ /*----------------------------- Small size ---------------------------------*/ /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS * IP address: 4 bytes, 15 chars * Port: 2 bytes, chars: 5 chars */ SlrxFilterBinaryArg_t RxFilterDB4BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][4]; /* Binary Values for comparison */ /*! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS * Port: 2 bytes, chars: 5 chars */ SlrxFilterAsciiArg_t RxFilterDB5BytesRuleAsciiArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][5]; /* Ascii Values for comparison */ /*----------------------------- 1 byte size ---------------------------------*/ /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS */ SlrxFilterBinaryArg_t RxFilterDB1BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][1]; /* Binary Values for comparison */ }SlrxFilterHeaderArg_t; /*! \typedef SlrxFilterRuleHeaderArgsAndMask_t * Structure which defines the Header Args and mask */ /* -- 52 bytes */ typedef struct SlrxFilterRuleHeaderArgsAndMask_t { /*! Argument for the comparison function */ /* -- 36 byte */ SlrxFilterHeaderArg_t RuleHeaderArgs; /*! the mask is used in order to enable partial comparison, * Use the 0xFFFFFFFF in case you don't want to use mask */ /* -- 16 bytes */ SlrxFilterCompareMask_t RuleHeaderArgsMask[16]; }SlrxFilterRuleHeaderArgsAndMask_t; /*! \typedef SlrxFilterHeaderType_t * Structure which defines the Header rule * The header rule defines compare function on the protocol header * For example destMacAddre is between ( 12:6::78:77, 12:6::78:90 ) * */ /* -- 56 byte */ typedef struct SlrxFilterHeaderType_t { /*! see :: SlrxFilterRuleHeaderArgsAndMask_t */ /* -- 52 bytes */ SlrxFilterRuleHeaderArgsAndMask_t RuleHeaderArgsAndMask; /*! Packet HDR field which will be compared to the argument */ /* -- 1 byte */ SlrxFilterHdrField_t RuleHeaderfield; /* -- 1 byte */ /*! type of the comparison function * see :: SlrxFilterCompareFunction_t */ SlrxFilterCompareFunction_t RuleCompareFunc; /*! padding */ /* -- 2 bytes */ _u8 RulePadding[2]; }SlrxFilterHeaderType_t; /*! \typedef SlrxFilterPayloadType_t * Structure which defines payload rule. * Not supported on current release. */ /* -- 40 byte */ typedef struct SlrxFilterPayloadType_t { /*! Not supported on current release */ /* -- 32 byte */ SlrxFilterRegxPattern_t RegxPattern; /*! Not supported on current release */ /* -- 4 byte */ SlrxFilterOffset_t LowerOffset; /*! Not supported on current release */ /* -- 4 byte */ SlrxFilterOffset_t UpperOffset; }SlrxFilterPayloadType_t; /*! \typedef SlrxFilterCombinationTypeOperator_t * Enumerate the optional operators for the combination type * filterID1 is located in the first arg , filterId2 is the second arg,see ::SlrxFilterCombinationType_t.CombinationFilterId */ typedef _u8 SlrxFilterCombinationTypeOperator_t; /* Possible values for SlrxFilterCombinationTypeOperator_t */ /*! !filterID1 */ #define COMBINED_FUNC_NOT (0) /*! filterID1 && filterID2 */ #define COMBINED_FUNC_AND (1) /*! filterID1 && filterID2 */ #define COMBINED_FUNC_OR (2) /*! \typedef SlrxFilterCombinationType_t * Defines the structure which define the combination type filter * The combined filter enable to make operation on one or two filter, * for example !filterId1 or and(filterId2,filterId3). * */ /* -- 4 byte */ typedef struct SlrxFilterCombinationType_t { /* ! combination operator */ /* -- 1 byte */ SlrxFilterCombinationTypeOperator_t CombinationTypeOperator; /* ! filterID, may be one or two depends on the combination operator type */ /* -- 2 byte */ SlrxFilterID_t CombinationFilterId[SL_RX_FILTER_NUM_OF_COMBINATION_TYPE_ARGS]; /* ! Padding */ /* -- 1 byte */ _u8 Padding; }SlrxFilterCombinationType_t; /*! \typedef SlrxFilterRule_t * Rule structure composed of behavioral flags and the filter rule definitions * */ /* -- 56 byte */ typedef union SlrxFilterRule_t { /* ! Header type rule , see explanation on the ::SlrxFilterHeaderType_t structure */ /* -- 56 byte */ SlrxFilterHeaderType_t HeaderType; /* ! Payload rule, not supported in current release */ /* -- 40 byte */ SlrxFilterPayloadType_t PayLoadHeaderType; /* future for exact pattern or like hood pattern */ /* ! Combined type rule , see explanation in ::SlrxFilterCombinationType_t structure */ /* -- 4 byte */ SlrxFilterCombinationType_t CombinationType; }SlrxFilterRule_t; /*! \typedef SlrxFilterTriggerRoles_t * Bit field which represents the roleId possible values * In the current release only Station/AP roles are supported. */ #define RX_FILTER_ROLE_AP (1) #define RX_FILTER_ROLE_STA (2) #define RX_FILTER_ROLE_PROMISCUOUS (4) #define RX_FILTER_ROLE_NULL (0) typedef union SlrxFilterTriggerRoles_t { /* struct */ /* { */ /* _u8 RoleAP :1; */ /* _u8 RoleStation :1; */ /* The filter is activated only in Promiscuous mode */ /* _u8 PromiscuousMode :1; */ /* _u8 RoleReserved :5; */ /* }; */ /* ! Bit fiels of the Filter role */ _u8 IntRepresentation; }SlrxFilterTriggerRoles_t; /*! \typedef SlrxFilterTriggerConnectionStates_t * Bit field representing the possible values of the When section of the rule * */ #define RX_FILTER_CONNECTION_STATE_STA_CONNECTED (1) #define RX_FILTER_CONNECTION_STATE_STA_NOT_CONNECTED (2) #define RX_FILTER_CONNECTION_STATE_STA_HAS_IP (4) #define RX_FILTER_CONNECTION_STATE_STA_HAS_NO_IP (8) typedef union SlrxFilterTriggerConnectionStates_t { /* struct */ /* { */ /* _u8 RoleStationWiFiConnected :1; */ /* _u8 RoleStationWiFiDisconneted:1; */ /* _u8 RoleStationWiFiHasIp:1; */ /* _u8 RoleStationWiFiHasNoIp:1; */ /* _u8 RoleStationWiFiSocketOpened:1; */ /* _u8 RoleStationWiFiSocketclosed:1; */ /* }; */ /* */ /* ! */ _u8 IntRepresentation; }SlrxFilterTriggerConnectionStates_t; /*! \typedef SlrxFilterDBTriggerArg_t * Provides container for entering the filter 'when' argument. * The current release support 'When rules' which has no arguments. * For example : * When connect to specific AP -- the AP bssid is the argument. * */ typedef _u32 SlrxFilterDBTriggerArg_t; /*! \typedef SlrxFilterCounterId_t * the counter ID we have 4 counters */ typedef _u8 SlrxFilterCounterId_t; /* Possible values for SlrxFilterCounterId_t */ #define NO_TRIGGER (0) #define RX_FILTER_COUNTER1 (1) #define RX_FILTER_COUNTER2 (2) #define RX_FILTER_COUNTER3 (3) #define RX_FILTER_COUNTER4 (4) #define RX_FILTER_COUNTER5 (5) #define RX_FILTER_COUNTER6 (6) #define RX_FILTER_COUNTER7 (7) #define RX_FILTER_COUNTER8 (8) #define MAX_RX_FILTER_COUNTER (9) /*! \typedef SlrxFilterActionArgs_t * Possible value for filter action args * */ typedef _u8 SlrxFilterActionArgs_t; /* Possible values for SlrxFilterActionArgs_t */ #define ACTION_ARG_REG_1_4 (0) /* ! Can be use as counter */ #define ACTION_ARG_TEMPLATE (1) /* ! Can be use as counter */ #define ACTION_ARG_EVENT (2) /* ! GPIO number */ #define ACTION_ARG_GPIO (4) /*! * \def SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS * */ #define SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS (5) /*! \typedef SlrxFilterTrigger_t * The filter trigger, determine when the filter is triggered, * The filter is triggered in the following condition :\n * 1. The filter parent is triggered\n * 2. The requested connection type exists, i.e. wlan_connect\n * 3. The filter role is the same as the system role\n * */ /* -- 12 byte */ typedef struct SlrxFilterTrigger_t { /*! The parent filter ID, this is the way to build filter tree. */ /* NULL value means tree root. */ /* -- 1 byte */ SlrxFilterID_t ParentFilterID; /* ! See ::SlrxFilterCounterId_t explanation */ /* -- 1 byte */ SlrxFilterCounterId_t Trigger; /* ! See :: SlrxFilterTriggerConnectionStates_t */ /* -- 1 byte */ SlrxFilterTriggerConnectionStates_t TriggerArgConnectionState; /* ! See ::SlrxFilterTriggerRoles_t */ /* -- 1 byte */ SlrxFilterTriggerRoles_t TriggerArgRoleStatus; /* ! The Trigger arguments are in the same order as the Trigger bit field order. */ /* -- 4 byte */ SlrxFilterDBTriggerArg_t TriggerArg; /** The compare function which will be operate for each bit that is turned on in the ::SlrxFilterTrigger_t.Trigger field, * for example , in case the second bit in the Trigger function is on the second function in the list will be executed. * */ /* -- 1 byte */ SlrxTriggerCompareFunction_t TriggerCompareFunction; /* ! padding */ /* -- 3 byte */ _u8 Padding[3]; } SlrxFilterTrigger_t; /*! \typedef SlrxFilterActionType_t * The actions are executed only if the filter is matched,\n * In case of false match the packet is transfered to the HOST. \n * The action is composed of bit field structure, * up to 2 actions can be defined per filter. * */ #define RX_FILTER_ACTION_NULL (0x0) #define RX_FILTER_ACTION_DROP (0x1) #define RX_FILTER_ACTION_GPIO (0x2) #define RX_FILTER_ACTION_ON_REG_INCREASE (0x4) #define RX_FILTER_ACTION_ON_REG_DECREASE (0x8) #define RX_FILTER_ACTION_ON_REG_RESET (0x10) #define RX_FILTER_ACTION_SEND_TEMPLATE (0x20) /* unsupported */ #define RX_FILTER_ACTION_EVENT_TO_HOST (0x40) /* unsupported */ typedef union SlrxFilterActionType_t { /* struct */ /* { */ /* ! No action to execute the packet is dropped,drop is always on leaf. */ /* ! If not dropped ,The packet is passed to the next filter or in case it is the last filter to the host */ /* _u8 ActionDrop : 1; */ /* ! Not Supported in the current release */ /* _u8 ActionGpio : 1; */ /*! action can increase counter registers. * 1 = Increase * 2 = decrease * 3 = reset */ /* _u8 ActionOnREGIncrease : 1; */ /* _u8 ActionOnREGDecrease : 1; */ /* _u8 ActionOnREGReset : 1; */ /* ! Not Supported in the current release */ /* _u8 ActionSendTemplate : 1; */ /* ! Not Supported in the current release */ /* _u8 ActionEventToHost: 1; */ /* _u8 padding: 1; */ /* }; */ _u8 IntRepresentation; }SlrxFilterActionType_t; /*! \typedef SlrxFilterAction_t * Several actions can be defined,\n * The action is executed in case the filter rule is matched. */ /* -- 8 byte */ typedef struct SlrxFilterAction_t { /* -- 1 byte */ /* ! Determine which actions are supported */ SlrxFilterActionType_t ActionType; /* ! Buffer for the action arguments */ /** * location 0 - The counter to increase * In case the action is of type "increase" the arg will contain the counter number, * The counter number values are as in ::SlrxFilterCounterId_t.\n * location 1 - The template arg.\n * location 2 - The event arg.\n * */ /* -- 5 byte */ SlrxFilterActionArg_t ActionArg[SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS]; /* ! Padding */ /* - 2 Bytes */ _u8 Padding[2]; } SlrxFilterAction_t; /*! \struct _WlanRxFilterOperationCommandBuff_t * The structure is used for the interface HOST NWP.\n * The supported operation : \n * ::ENABLE_DISABLE_RX_FILTER,\n * ::REMOVE_RX_FILTER,\n * */ /* 20 bytes */ typedef struct _WlanRxFilterOperationCommandBuff_t { /* -- 16 bytes */ SlrxFilterIdMask_t FilterIdMask; /* 4 bytes */ _u8 Padding[4]; }_WlanRxFilterOperationCommandBuff_t; /* -- 56 bytes */ typedef struct _WlanRxFilterUpdateArgsCommandBuff_t { /* -- 1 bytes */ _u8 FilterId; /* -- 1 bytes */ /* ! the args representation */ _u8 BinaryRepresentation; /* -- 52 byte */ SlrxFilterRuleHeaderArgsAndMask_t FilterRuleHeaderArgsAndMask; /* -- 2 bytes */ _u8 Padding[2]; }_WlanRxFilterUpdateArgsCommandBuff_t; /*! \typedef _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t * The structure is used for the interface HOST NWP.\n * */ /* -- 16 bytes */ typedef struct _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t { /* ! the filter set bit map */ /* -- 16 bytes */ SlrxFilterIdMask_t FilterIdMask; }_WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t; /*! \struct _WlanRxFilterPrePreparedFiltersCommandBuff_t * The function enables to perform operations on pre-prepared filters * */ typedef struct _WlanRxFilterPrePreparedFiltersCommandBuff_t { /* ! the filter set bit map */ /* -- 4 bytes */ SlrxFilterPrePreparedFiltersMask_t FilterPrePreparedFiltersMask; }_WlanRxFilterPrePreparedFiltersCommandBuff_t; /*! \typedef sl_protocol_WlanRxFilterPrePreparedFiltersCommandResponseBuff_t * */ /*-- 4 bytes */ typedef struct _WlanRxFilterPrePreparedFiltersCommandResponseBuff_t { /* -- 4 bytes */ /* ! the filter set bit map */ SlrxFilterPrePreparedFiltersMask_t FilterPrePreparedFiltersMask; }_WlanRxFilterPrePreparedFiltersCommandResponseBuff_t; typedef _u8 SLrxFilterOperation_t; #define SL_ENABLE_DISABLE_RX_FILTER (0) #define SL_REMOVE_RX_FILTER (1) #define SL_STORE_RX_FILTERS (2) #define SL_UPDATE_RX_FILTER_ARGS (3) #define SL_FILTER_RETRIEVE_ENABLE_STATE (4) #define SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE (5) #define SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE (6) /* Bit manipulation for 8 bit */ #define ISBITSET8(x,i) ((x[i>>3] & (0x80>>(i&7)))!=0) /* < Is bit set, 8 bit unsigned numbers = x , location = i */ #define SETBIT8(x,i) x[i>>3]|=(0x80>>(i&7)); /* < Set bit,8 bit unsigned numbers = x , location = i */ #define CLEARBIT8(x,i) x[i>>3]&=(0x80>>(i&7))^0xFF; /* < Clear bit,8 bit unsigned numbers = x , location = i */ /*********************************************************************************************/ /* Function prototypes */ /*********************************************************************************************/ /*! \addtogroup wlan @{ */ /*! \brief Adds new filter rule to the system \param[in] RuleType The rule type \param[in] FilterFlags Flags which set the type of header rule Args and sets the persistent flag \param[in] pRule Determine the filter rule logic \param[in] pTrigger Determine when the rule is triggered also sets rule parent. \param[in] pAction Sets the action to be executed in case the match functions pass \param[out] pFilterId The filterId which was created \return On success, zero is returned. Otherwise error code is returned */ #if _SL_INCLUDE_FUNC(sl_WlanRxFilterAdd) SlrxFilterID_t sl_WlanRxFilterAdd( SlrxFilterRuleType_t RuleType, SlrxFilterFlags_t FilterFlags, const SlrxFilterRule_t* const Rule, const SlrxFilterTrigger_t* const Trigger, const SlrxFilterAction_t* const Action, SlrxFilterID_t* pFilterId); #endif /*! \brief Sets parameters to Rx filters \param[in] RxFilterOperation possible operations : - SL_ENABLE_DISABLE_RX_FILTER - Enables\disables filter in a filter list - SL_REMOVE_RX_FILTER - Removes filter from memory ( to remove from flash call SL_STORE_RX_FILTERS after this command) - SL_STORE_RX_FILTERS - Save the filters for persistent - SL_UPDATE_RX_FILTER_ARGS - Update the arguments of existing filter - SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE - Change the default creation of the pre-prepared filters \param[in] pInputBuffer options: The buffer input is _WlanRxFilterOperationCommandBuff_t: - SL_ENABLE_DISABLE_RX_FILTER - SL_REMOVE_RX_FILTER - SL_STORE_RX_FILTERS The buffer input is _WlanRxFilterUpdateArgsCommandBuff_t: - SL_UPDATE_RX_FILTER_ARGS The buffer input is _WlanRxFilterPrePreparedFiltersCommandBuff_t: - SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE \param[in] InputbufferLength The length in byte of the input buffer \return On success, zero is returned. Otherwise error code is returned */ #if _SL_INCLUDE_FUNC(sl_WlanRxFilterSet) _i16 sl_WlanRxFilterSet( const SLrxFilterOperation_t RxFilterOperation, const _u8* const pInputBuffer, _u16 InputbufferLength); #endif /*! \brief Gets parameters of Rx filters \param[in] RxFilterOperation possible operations : - SL_FILTER_RETRIEVE_ENABLE_STATE - Retrieves the enable disable status - SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE - Retrieves the pre-prepared filters creation status \param[in] pOutputBuffer The buffer input is _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t: - SL_FILTER_RETRIEVE_ENABLE_STATE The buffer input is _WlanRxFilterPrePreparedFiltersCommandResponseBuff_t: - SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE \param[in] OutputbufferLength The length in byte of the output buffer \return On success, zero is returned. Otherwise error code is returned */ #if _SL_INCLUDE_FUNC(sl_WlanRxFilterGet) _i16 sl_WlanRxFilterGet(const SLrxFilterOperation_t RxFilterOperation, _u8* pOutputBuffer, _u16 OutputbufferLength); #endif /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* RX_FILTERS_PREPROCESSOR_CLI_IF_H_ */ micropython-1.12/drivers/cc3100/src/000077500000000000000000000000001357706137100171605ustar00rootroot00000000000000micropython-1.12/drivers/cc3100/src/device.c000066400000000000000000000362111357706137100205660ustar00rootroot00000000000000/* * device.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "flowcont.h" #include "driver.h" /*****************************************************************************/ /* Internal functions */ /*****************************************************************************/ const _i8 StartResponseLUT[8] = { ROLE_UNKNOWN_ERR, ROLE_STA, ROLE_STA_ERR, ROLE_AP, ROLE_AP_ERR, ROLE_P2P, ROLE_P2P_ERR, ROLE_UNKNOWN_ERR }; _i16 _sl_GetStartResponseConvert(_u32 Status) { return (_i16)StartResponseLUT[Status & 0x7]; } /*****************************************************************************/ /* API Functions */ /*****************************************************************************/ /*****************************************************************************/ /* sl_Task */ /*****************************************************************************/ #if _SL_INCLUDE_FUNC(sl_Task) void sl_Task(void) { #ifdef _SlTaskEntry _SlTaskEntry(); #endif } #endif /*****************************************************************************/ /* sl_Start */ /*****************************************************************************/ #if _SL_INCLUDE_FUNC(sl_Start) _i16 sl_Start(const void* pIfHdl, _i8* pDevName, const P_INIT_CALLBACK pInitCallBack) { _i16 ObjIdx = MAX_CONCURRENT_ACTIONS; InitComplete_t AsyncRsp; /* Perform any preprocessing before enable networking services */ sl_DeviceEnablePreamble(); /* ControlBlock init */ _SlDrvDriverCBInit(); /* open the interface: usually SPI or UART */ if (NULL == pIfHdl) { g_pCB->FD = sl_IfOpen((void *)pDevName, 0); } else { g_pCB->FD = (_SlFd_t)pIfHdl; } ObjIdx = _SlDrvProtectAsyncRespSetting((_u8 *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } if( g_pCB->FD >= (_SlFd_t)0) { sl_DeviceDisable(); sl_IfRegIntHdlr((SL_P_EVENT_HANDLER)_SlDrvRxIrqHandler, NULL); g_pCB->pInitCallback = pInitCallBack; sl_DeviceEnable(); if (NULL == pInitCallBack) { _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); /* release Pool Object */ _SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex); return _sl_GetStartResponseConvert(AsyncRsp.Status); } else { return SL_RET_CODE_OK; } } return SL_BAD_INTERFACE; } #endif /*************************************************************************** _sl_HandleAsync_InitComplete - handles init complete signalling to a waiting object ****************************************************************************/ void _sl_HandleAsync_InitComplete(void *pVoidBuf) { InitComplete_t *pMsgArgs = (InitComplete_t *)_SL_RESP_ARGS_START(pVoidBuf); _SlDrvProtectionObjLockWaitForever(); if(g_pCB->pInitCallback) { g_pCB->pInitCallback(_sl_GetStartResponseConvert(pMsgArgs->Status)); } else { sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(InitComplete_t)); _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); } _SlDrvProtectionObjUnLock(); if(g_pCB->pInitCallback) { _SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex); } } /*************************************************************************** _sl_HandleAsync_Stop - handles stop signalling to a waiting object ****************************************************************************/ void _sl_HandleAsync_Stop(void *pVoidBuf) { _BasicResponse_t *pMsgArgs = (_BasicResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); VERIFY_SOCKET_CB(NULL != g_pCB->StopCB.pAsyncRsp); _SlDrvProtectionObjLockWaitForever(); sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_BasicResponse_t)); _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); _SlDrvProtectionObjUnLock(); return; } /***************************************************************************** sl_stop ******************************************************************************/ typedef union { _DevStopCommand_t Cmd; _BasicResponse_t Rsp; }_SlStopMsg_u; const _SlCmdCtrl_t _SlStopCmdCtrl = { SL_OPCODE_DEVICE_STOP_COMMAND, sizeof(_DevStopCommand_t), sizeof(_BasicResponse_t) }; #if _SL_INCLUDE_FUNC(sl_Stop) _i16 sl_Stop(const _u16 timeout) { _i16 RetVal=0; _SlStopMsg_u Msg; _BasicResponse_t AsyncRsp; _i8 ObjIdx = MAX_CONCURRENT_ACTIONS; /* if timeout is 0 the shutdown is forced immediately */ if( 0 == timeout ) { sl_IfRegIntHdlr(NULL, NULL); sl_DeviceDisable(); RetVal = sl_IfClose(g_pCB->FD); } else { /* let the device make the shutdown using the defined timeout */ Msg.Cmd.Timeout = timeout; ObjIdx = _SlDrvProtectAsyncRespSetting((_u8 *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlStopCmdCtrl, &Msg, NULL)); if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) { _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); Msg.Rsp.status = AsyncRsp.status; RetVal = Msg.Rsp.status; } _SlDrvReleasePoolObj(ObjIdx); sl_IfRegIntHdlr(NULL, NULL); sl_DeviceDisable(); sl_IfClose(g_pCB->FD); } _SlDrvDriverCBDeinit(); return RetVal; } #endif /***************************************************************************** sl_EventMaskSet *****************************************************************************/ typedef union { _DevMaskEventSetCommand_t Cmd; _BasicResponse_t Rsp; }_SlEventMaskSetMsg_u; #if _SL_INCLUDE_FUNC(sl_EventMaskSet) const _SlCmdCtrl_t _SlEventMaskSetCmdCtrl = { SL_OPCODE_DEVICE_EVENTMASKSET, sizeof(_DevMaskEventSetCommand_t), sizeof(_BasicResponse_t) }; _i16 sl_EventMaskSet(const _u8 EventClass ,const _u32 Mask) { _SlEventMaskSetMsg_u Msg; Msg.Cmd.group = EventClass; Msg.Cmd.mask = Mask; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskSetCmdCtrl, &Msg, NULL)); return (_i16)Msg.Rsp.status; } #endif /****************************************************************************** sl_EventMaskGet ******************************************************************************/ typedef union { _DevMaskEventGetCommand_t Cmd; _DevMaskEventGetResponse_t Rsp; }_SlEventMaskGetMsg_u; #if _SL_INCLUDE_FUNC(sl_EventMaskGet) const _SlCmdCtrl_t _SlEventMaskGetCmdCtrl = { SL_OPCODE_DEVICE_EVENTMASKGET, sizeof(_DevMaskEventGetCommand_t), sizeof(_DevMaskEventGetResponse_t) }; _i16 sl_EventMaskGet(const _u8 EventClass,_u32 *pMask) { _SlEventMaskGetMsg_u Msg; Msg.Cmd.group = EventClass; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskGetCmdCtrl, &Msg, NULL)); *pMask = Msg.Rsp.mask; return SL_RET_CODE_OK; } #endif /****************************************************************************** sl_DevGet ******************************************************************************/ typedef union { _DeviceSetGet_t Cmd; _DeviceSetGet_t Rsp; }_SlDeviceMsgGet_u; #if _SL_INCLUDE_FUNC(sl_DevGet) const _SlCmdCtrl_t _SlDeviceGetCmdCtrl = { SL_OPCODE_DEVICE_DEVICEGET, sizeof(_DeviceSetGet_t), sizeof(_DeviceSetGet_t) }; _i32 sl_DevGet(const _u8 DeviceGetId,_u8 *pOption,_u8 *pConfigLen, _u8 *pValues) { _SlDeviceMsgGet_u Msg; _SlCmdExt_t CmdExt; if (*pConfigLen == 0) { return SL_EZEROLEN; } if( pOption ) { _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = *pConfigLen; CmdExt.pRxPayload = (_u8 *)pValues; Msg.Cmd.DeviceSetId = DeviceGetId; Msg.Cmd.Option = (_u16)*pOption; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceGetCmdCtrl, &Msg, &CmdExt)); if( pOption ) { *pOption = (_u8)Msg.Rsp.Option; } if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) { *pConfigLen = (_u8)CmdExt.RxPayloadLen; return SL_ESMALLBUF; } else { *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; } return (_i16)Msg.Rsp.Status; } else { return -1; } } #endif /****************************************************************************** sl_DevSet ******************************************************************************/ typedef union { _DeviceSetGet_t Cmd; _BasicResponse_t Rsp; }_SlDeviceMsgSet_u; #if _SL_INCLUDE_FUNC(sl_DevSet) const _SlCmdCtrl_t _SlDeviceSetCmdCtrl = { SL_OPCODE_DEVICE_DEVICESET, sizeof(_DeviceSetGet_t), sizeof(_BasicResponse_t) }; _i32 sl_DevSet(const _u8 DeviceSetId ,const _u8 Option,const _u8 ConfigLen,const _u8 *pValues) { _SlDeviceMsgSet_u Msg; _SlCmdExt_t CmdExt; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); CmdExt.pTxPayload = (_u8 *)pValues; Msg.Cmd.DeviceSetId = DeviceSetId; Msg.Cmd.ConfigLen = ConfigLen; Msg.Cmd.Option = Option; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceSetCmdCtrl, &Msg, &CmdExt)); return (_i16)Msg.Rsp.status; } #endif /****************************************************************************** _SlDrvDeviceEventHandler - handles internally device async events ******************************************************************************/ void _SlDrvDeviceEventHandler(void* pArgs) { _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)pArgs; switch(pHdr->GenHeader.Opcode) { case SL_OPCODE_DEVICE_INITCOMPLETE: _sl_HandleAsync_InitComplete(pHdr); break; case SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE: _sl_HandleAsync_Stop(pHdr); break; case SL_OPCODE_DEVICE_ABORT: { #if defined (sl_GeneralEvtHdlr) || defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) SlDeviceEvent_t devHandler; devHandler.Event = SL_DEVICE_ABORT_ERROR_EVENT; devHandler.EventData.deviceReport.AbortType = *((_u32*)pArgs + 2); devHandler.EventData.deviceReport.AbortData = *((_u32*)pArgs + 3); _SlDrvHandleGeneralEvents(&devHandler); #endif } break; case SL_OPCODE_DEVICE_DEVICEASYNCFATALERROR: #if defined (sl_GeneralEvtHdlr) || defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) { _BasicResponse_t *pMsgArgs = (_BasicResponse_t *)_SL_RESP_ARGS_START(pHdr); SlDeviceEvent_t devHandler; devHandler.Event = SL_DEVICE_FATAL_ERROR_EVENT; devHandler.EventData.deviceEvent.status = pMsgArgs->status & 0xFF; devHandler.EventData.deviceEvent.sender = (SlErrorSender_e)((pMsgArgs->status >> 8) & 0xFF); _SlDrvHandleGeneralEvents(&devHandler); } #endif break; default: SL_ERROR_TRACE2(MSG_306, "ASSERT: _SlDrvDeviceEventHandler : invalid opcode = 0x%x = %1", pHdr->GenHeader.Opcode, pHdr->GenHeader.Opcode); } } /****************************************************************************** sl_UartSetMode ******************************************************************************/ #ifdef SL_IF_TYPE_UART typedef union { _DevUartSetModeCommand_t Cmd; _DevUartSetModeResponse_t Rsp; }_SlUartSetModeMsg_u; #if _SL_INCLUDE_FUNC(sl_UartSetMode) const _SlCmdCtrl_t _SlUartSetModeCmdCtrl = { SL_OPCODE_DEVICE_SETUARTMODECOMMAND, sizeof(_DevUartSetModeCommand_t), sizeof(_DevUartSetModeResponse_t) }; _i16 sl_UartSetMode(const SlUartIfParams_t* pUartParams) { _SlUartSetModeMsg_u Msg; _u32 magicCode = 0xFFFFFFFF; Msg.Cmd.BaudRate = pUartParams->BaudRate; Msg.Cmd.FlowControlEnable = pUartParams->FlowControlEnable; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlUartSetModeCmdCtrl, &Msg, NULL)); /* cmd response OK, we can continue with the handshake */ if (SL_RET_CODE_OK == Msg.Rsp.status) { sl_IfMaskIntHdlr(); /* Close the comm port */ sl_IfClose(g_pCB->FD); /* Re-open the comm port */ sl_IfOpen((void * )pUartParams, UART_IF_OPEN_FLAG_RE_OPEN); sl_IfUnMaskIntHdlr(); /* send the magic code and wait for the response */ sl_IfWrite(g_pCB->FD, (_u8* )&magicCode, 4); magicCode = UART_SET_MODE_MAGIC_CODE; sl_IfWrite(g_pCB->FD, (_u8* )&magicCode, 4); /* clear magic code */ magicCode = 0; /* wait (blocking) till the magic code to be returned from device */ sl_IfRead(g_pCB->FD, (_u8* )&magicCode, 4); /* check for the received magic code matching */ if (UART_SET_MODE_MAGIC_CODE != magicCode) { _SL_ASSERT(0); } } return (_i16)Msg.Rsp.status; } #endif #endif micropython-1.12/drivers/cc3100/src/driver.c000066400000000000000000001747011357706137100206310ustar00rootroot00000000000000/* * driver.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "driver.h" #include "flowcont.h" /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #define _SL_PENDING_RX_MSG(pDriverCB) (RxIrqCnt != (pDriverCB)->RxDoneCnt) /* 2 LSB of the N2H_SYNC_PATTERN are for sequence number only in SPI interface support backward sync pattern */ #define N2H_SYNC_PATTERN_SEQ_NUM_BITS ((_u32)0x00000003) /* Bits 0..1 - use the 2 LBS for seq num */ #define N2H_SYNC_PATTERN_SEQ_NUM_EXISTS ((_u32)0x00000004) /* Bit 2 - sign that sequence number exists in the sync pattern */ #define N2H_SYNC_PATTERN_MASK ((_u32)0xFFFFFFF8) /* Bits 3..31 - constant SYNC PATTERN */ #define N2H_SYNC_SPI_BUGS_MASK ((_u32)0x7FFF7F7F) /* Bits 7,15,31 - ignore the SPI (8,16,32 bites bus) error bits */ #define BUF_SYNC_SPIM(pBuf) ((*(_u32 *)(pBuf)) & N2H_SYNC_SPI_BUGS_MASK) _u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID); #define N2H_SYNC_SPIM (N2H_SYNC_PATTERN & N2H_SYNC_SPI_BUGS_MASK) #define N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum) ((N2H_SYNC_SPIM & N2H_SYNC_PATTERN_MASK) | N2H_SYNC_PATTERN_SEQ_NUM_EXISTS | ((TxSeqNum) & (N2H_SYNC_PATTERN_SEQ_NUM_BITS))) #define MATCH_WOUT_SEQ_NUM(pBuf) ( BUF_SYNC_SPIM(pBuf) == N2H_SYNC_SPIM ) #define MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ( BUF_SYNC_SPIM(pBuf) == (N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum)) ) #define N2H_SYNC_PATTERN_MATCH(pBuf, TxSeqNum) \ ( \ ( (*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ) ) || \ ( !(*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WOUT_SEQ_NUM(pBuf ) ) ) \ ) #define OPCODE(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Opcode) #define RSP_PAYLOAD_LEN(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Len - _SL_RESP_SPEC_HDR_SIZE) #define SD(_ptr) (((_SocketAddrResponse_u *)(_ptr))->IpV4.sd) /* Actual size of Recv/Recvfrom response data */ #define ACT_DATA_SIZE(_ptr) (((_SocketAddrResponse_u *)(_ptr))->IpV4.statusOrLen) /* General Events handling*/ #if defined (EXT_LIB_REGISTERED_GENERAL_EVENTS) typedef _SlEventPropogationStatus_e (*general_callback) (SlDeviceEvent_t *); static const general_callback general_callbacks[] = { #ifdef SlExtLib1GeneralEventHandler SlExtLib1GeneralEventHandler, #endif #ifdef SlExtLib2GeneralEventHandler SlExtLib2GeneralEventHandler, #endif #ifdef SlExtLib3GeneralEventHandler SlExtLib3GeneralEventHandler, #endif #ifdef SlExtLib4GeneralEventHandler SlExtLib4GeneralEventHandler, #endif #ifdef SlExtLib5GeneralEventHandler SlExtLib5GeneralEventHandler, #endif }; #undef _SlDrvHandleGeneralEvents /******************************************************************** _SlDrvHandleGeneralEvents Iterates through all the general(device) event handlers which are registered by the external libs/user application. *********************************************************************/ void _SlDrvHandleGeneralEvents(SlDeviceEvent_t *slGeneralEvent) { _u8 i; /* Iterate over all the extenal libs handlers */ for ( i = 0 ; i < sizeof(general_callbacks)/sizeof(general_callbacks[0]) ; i++ ) { if (EVENT_PROPAGATION_BLOCK == general_callbacks[i](slGeneralEvent) ) { /* exit immediately and do not call the user specific handler as well */ return; } } /* At last call the Application specific handler if registered */ #ifdef sl_GeneralEvtHdlr sl_GeneralEvtHdlr(slGeneralEvent); #endif } #endif /* WLAN Events handling*/ #if defined (EXT_LIB_REGISTERED_WLAN_EVENTS) typedef _SlEventPropogationStatus_e (*wlan_callback) (SlWlanEvent_t *); static wlan_callback wlan_callbacks[] = { #ifdef SlExtLib1WlanEventHandler SlExtLib1WlanEventHandler, #endif #ifdef SlExtLib2WlanEventHandler SlExtLib2WlanEventHandler, #endif #ifdef SlExtLib3WlanEventHandler SlExtLib3WlanEventHandler, #endif #ifdef SlExtLib4WlanEventHandler SlExtLib4WlanEventHandler, #endif #ifdef SlExtLib5WlanEventHandler SlExtLib5WlanEventHandler, #endif }; #undef _SlDrvHandleWlanEvents /*********************************************************** _SlDrvHandleWlanEvents Iterates through all the wlan event handlers which are registered by the external libs/user application. ************************************************************/ void _SlDrvHandleWlanEvents(SlWlanEvent_t *slWlanEvent) { _u8 i; /* Iterate over all the extenal libs handlers */ for ( i = 0 ; i < sizeof(wlan_callbacks)/sizeof(wlan_callbacks[0]) ; i++ ) { if ( EVENT_PROPAGATION_BLOCK == wlan_callbacks[i](slWlanEvent) ) { /* exit immediately and do not call the user specific handler as well */ return; } } /* At last call the Application specific handler if registered */ #ifdef sl_WlanEvtHdlr sl_WlanEvtHdlr(slWlanEvent); #endif } #endif /* NetApp Events handling */ #if defined (EXT_LIB_REGISTERED_NETAPP_EVENTS) typedef _SlEventPropogationStatus_e (*netApp_callback) (SlNetAppEvent_t *); static const netApp_callback netApp_callbacks[] = { #ifdef SlExtLib1NetAppEventHandler SlExtLib1NetAppEventHandler, #endif #ifdef SlExtLib2NetAppEventHandler SlExtLib2NetAppEventHandler, #endif #ifdef SlExtLib3NetAppEventHandler SlExtLib3NetAppEventHandler, #endif #ifdef SlExtLib4NetAppEventHandler SlExtLib4NetAppEventHandler, #endif #ifdef SlExtLib5NetAppEventHandler SlExtLib5NetAppEventHandler, #endif }; #undef _SlDrvHandleNetAppEvents /************************************************************ _SlDrvHandleNetAppEvents Iterates through all the net app event handlers which are registered by the external libs/user application. ************************************************************/ void _SlDrvHandleNetAppEvents(SlNetAppEvent_t *slNetAppEvent) { _u8 i; /* Iterate over all the extenal libs handlers */ for ( i = 0 ; i < sizeof(netApp_callbacks)/sizeof(netApp_callbacks[0]) ; i++ ) { if (EVENT_PROPAGATION_BLOCK == netApp_callbacks[i](slNetAppEvent) ) { /* exit immediately and do not call the user specific handler as well */ return; } } /* At last call the Application specific handler if registered */ #ifdef sl_NetAppEvtHdlr sl_NetAppEvtHdlr(slNetAppEvent); #endif } #endif /* Http Server Events handling */ #if defined (EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) typedef _SlEventPropogationStatus_e (*httpServer_callback) (SlHttpServerEvent_t*, SlHttpServerResponse_t*); static const httpServer_callback httpServer_callbacks[] = { #ifdef SlExtLib1HttpServerEventHandler SlExtLib1HttpServerEventHandler, #endif #ifdef SlExtLib2HttpServerEventHandler SlExtLib2HttpServerEventHandler, #endif #ifdef SlExtLib3HttpServerEventHandler SlExtLib3HttpServerEventHandler, #endif #ifdef SlExtLib4HttpServerEventHandler SlExtLib4HttpServerEventHandler, #endif #ifdef SlExtLib5HttpServerEventHandler SlExtLib5HttpServerEventHandler, #endif }; #undef _SlDrvHandleHttpServerEvents /******************************************************************* _SlDrvHandleHttpServerEvents Iterates through all the http server event handlers which are registered by the external libs/user application. ********************************************************************/ void _SlDrvHandleHttpServerEvents(SlHttpServerEvent_t *slHttpServerEvent, SlHttpServerResponse_t *slHttpServerResponse) { _u8 i; /* Iterate over all the external libs handlers */ for ( i = 0 ; i < sizeof(httpServer_callbacks)/sizeof(httpServer_callbacks[0]) ; i++ ) { if ( EVENT_PROPAGATION_BLOCK == httpServer_callbacks[i](slHttpServerEvent, slHttpServerResponse) ) { /* exit immediately and do not call the user specific handler as well */ return; } } /* At last call the Application specific handler if registered */ #ifdef sl_HttpServerCallback sl_HttpServerCallback(slHttpServerEvent, slHttpServerResponse); #endif } #endif /* Socket Events */ #if defined (EXT_LIB_REGISTERED_SOCK_EVENTS) typedef _SlEventPropogationStatus_e (*sock_callback) (SlSockEvent_t *); static const sock_callback sock_callbacks[] = { #ifdef SlExtLib1SockEventHandler SlExtLib1SockEventHandler, #endif #ifdef SlExtLib2SockEventHandler SlExtLib2SockEventHandler, #endif #ifdef SlExtLib3SockEventHandler SlExtLib3SockEventHandler, #endif #ifdef SlExtLib4SockEventHandler SlExtLib4SockEventHandler, #endif #ifdef SlExtLib5SockEventHandler SlExtLib5SockEventHandler, #endif }; /************************************************************* _SlDrvHandleSockEvents Iterates through all the socket event handlers which are registered by the external libs/user application. **************************************************************/ void _SlDrvHandleSockEvents(SlSockEvent_t *slSockEvent) { _u8 i; /* Iterate over all the external libs handlers */ for ( i = 0 ; i < sizeof(sock_callbacks)/sizeof(sock_callbacks[0]) ; i++ ) { if ( EVENT_PROPAGATION_BLOCK == sock_callbacks[i](slSockEvent) ) { /* exit immediately and do not call the user specific handler as well */ return; } } /* At last call the Application specific handler if registered */ #ifdef sl_SockEvtHdlr sl_SockEvtHdlr(slSockEvent); #endif } #endif #if (SL_MEMORY_MGMT != SL_MEMORY_MGMT_DYNAMIC) typedef struct { _u32 Align; _SlDriverCb_t DriverCB; _u8 AsyncRespBuf[SL_ASYNC_MAX_MSG_LEN]; }_SlStatMem_t; _SlStatMem_t g_StatMem; #endif _u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID) { _u8 ObjIdx; /* Use Obj to issue the command, if not available try later */ ObjIdx = _SlDrvWaitForPoolObj(ActionID, SocketID); if (MAX_CONCURRENT_ACTIONS != ObjIdx) { _SlDrvProtectionObjLockWaitForever(); g_pCB->ObjPool[ObjIdx].pRespArgs = pAsyncRsp; _SlDrvProtectionObjUnLock(); } return ObjIdx; } /*****************************************************************************/ /* Variables */ /*****************************************************************************/ const _SlSyncPattern_t g_H2NSyncPattern = H2N_SYNC_PATTERN; const _SlSyncPattern_t g_H2NCnysPattern = H2N_CNYS_PATTERN; _volatile _u8 RxIrqCnt; #ifndef SL_TINY_EXT const _SlActionLookup_t _SlActionLookupTable[] = { {ACCEPT_ID, SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE, (_SlSpawnEntryFunc_t)_sl_HandleAsync_Accept}, {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect}, {SELECT_ID, SL_OPCODE_SOCKET_SELECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Select}, {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName}, {GETHOSYBYSERVICE_ID, SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByService}, {PING_ID, SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE, (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse}, {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop} }; #else const _SlActionLookup_t _SlActionLookupTable[] = { {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect}, {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName}, {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop} }; #endif typedef struct { _u16 opcode; _u8 event; } OpcodeKeyVal_t; /* The table translates opcode to user's event type */ const OpcodeKeyVal_t OpcodeTranslateTable[] = { {SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE, SL_WLAN_SMART_CONFIG_COMPLETE_EVENT}, {SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE,SL_WLAN_SMART_CONFIG_STOP_EVENT}, {SL_OPCODE_WLAN_STA_CONNECTED, SL_WLAN_STA_CONNECTED_EVENT}, {SL_OPCODE_WLAN_STA_DISCONNECTED,SL_WLAN_STA_DISCONNECTED_EVENT}, {SL_OPCODE_WLAN_P2P_DEV_FOUND,SL_WLAN_P2P_DEV_FOUND_EVENT}, {SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED, SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT}, {SL_OPCODE_WLAN_CONNECTION_FAILED, SL_WLAN_CONNECTION_FAILED_EVENT}, {SL_OPCODE_WLAN_WLANASYNCCONNECTEDRESPONSE, SL_WLAN_CONNECT_EVENT}, {SL_OPCODE_WLAN_WLANASYNCDISCONNECTEDRESPONSE, SL_WLAN_DISCONNECT_EVENT}, {SL_OPCODE_NETAPP_IPACQUIRED, SL_NETAPP_IPV4_IPACQUIRED_EVENT}, {SL_OPCODE_NETAPP_IPACQUIRED_V6, SL_NETAPP_IPV6_IPACQUIRED_EVENT}, {SL_OPCODE_NETAPP_IP_LEASED, SL_NETAPP_IP_LEASED_EVENT}, {SL_OPCODE_NETAPP_IP_RELEASED, SL_NETAPP_IP_RELEASED_EVENT}, {SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE, SL_SOCKET_TX_FAILED_EVENT}, {SL_OPCODE_SOCKET_SOCKETASYNCEVENT, SL_SOCKET_ASYNC_EVENT} }; _SlDriverCb_t* g_pCB = NULL; P_SL_DEV_PING_CALLBACK pPingCallBackFunc = NULL; _u8 gFirstCmdMode = 0; /*****************************************************************************/ /* Function prototypes */ /*****************************************************************************/ _SlReturnVal_t _SlDrvMsgRead(void); _SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t *pCmdCtrl,_SlCmdExt_t *pCmdExt, _u8 *pTxRxDescBuff); _SlReturnVal_t _SlDrvMsgReadCmdCtx(void); _SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue); void _SlDrvClassifyRxMsg(_SlOpcode_t Opcode ); _SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf, _u8 *pAlignSize); void _SlDrvShiftDWord(_u8 *pBuf); void _SlDrvDriverCBInit(void); void _SlAsyncEventGenericHandler(void); _u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID); void _SlDrvReleasePoolObj(_u8 pObj); void _SlRemoveFromList(_u8* ListIndex, _u8 ItemIndex); _SlReturnVal_t _SlFindAndSetActiveObj(_SlOpcode_t Opcode, _u8 Sd); /*****************************************************************************/ /* Internal functions */ /*****************************************************************************/ /***************************************************************************** _SlDrvDriverCBInit - init Driver Control Block *****************************************************************************/ void _SlDrvDriverCBInit(void) { _u8 Idx =0; #if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) g_pCB = sl_Malloc(sizeof(_SlDriverCb_t)); #else g_pCB = &(g_StatMem.DriverCB); #endif MALLOC_OK_CHECK(g_pCB); _SlDrvMemZero(g_pCB, sizeof(_SlDriverCb_t)); RxIrqCnt = 0; OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->CmdSyncObj, "CmdSyncObj") ); sl_SyncObjClear(&g_pCB->CmdSyncObj); OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->GlobalLockObj, "GlobalLockObj") ); OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->ProtectionLockObj, "ProtectionLockObj") ); /* Init Drv object */ _SlDrvMemZero(&g_pCB->ObjPool[0], MAX_CONCURRENT_ACTIONS*sizeof(_SlPoolObj_t)); /* place all Obj in the free list*/ g_pCB->FreePoolIdx = 0; for (Idx = 0 ; Idx < MAX_CONCURRENT_ACTIONS ; Idx++) { g_pCB->ObjPool[Idx].NextIndex = Idx + 1; g_pCB->ObjPool[Idx].AdditionalData = SL_MAX_SOCKETS; OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->ObjPool[Idx].SyncObj, "SyncObj")); sl_SyncObjClear(&g_pCB->ObjPool[Idx].SyncObj); } g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS; g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS; /* Flow control init */ g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN; OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj")); OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj")); gFirstCmdMode = 0; } /***************************************************************************** _SlDrvDriverCBDeinit - De init Driver Control Block *****************************************************************************/ void _SlDrvDriverCBDeinit() { _u8 Idx =0; /* Flow control de-init */ g_pCB->FlowContCB.TxPoolCnt = 0; OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj)); OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj)); OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->CmdSyncObj) ); OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->GlobalLockObj) ); OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->ProtectionLockObj) ); #ifndef SL_TINY_EXT for (Idx = 0; Idx < MAX_CONCURRENT_ACTIONS; Idx++) #endif { OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->ObjPool[Idx].SyncObj) ); } g_pCB->FreePoolIdx = 0; g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS; g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS; #if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) sl_Free(g_pCB); #else g_pCB = NULL; #endif g_pCB = NULL; } /***************************************************************************** _SlDrvRxIrqHandler - Interrupt handler *****************************************************************************/ void _SlDrvRxIrqHandler(void *pValue) { sl_IfMaskIntHdlr(); RxIrqCnt++; if (TRUE == g_pCB->IsCmdRespWaited) { OSI_RET_OK_CHECK( sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) ); } else { sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0); } } /***************************************************************************** _SlDrvCmdOp *****************************************************************************/ _SlReturnVal_t _SlDrvCmdOp( _SlCmdCtrl_t *pCmdCtrl , void *pTxRxDescBuff , _SlCmdExt_t *pCmdExt) { _SlReturnVal_t RetVal; _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); g_pCB->IsCmdRespWaited = TRUE; SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdOp: call _SlDrvMsgWrite"); /* send the message */ RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); if(SL_OS_RET_CODE_OK == RetVal) { #ifndef SL_IF_TYPE_UART /* Waiting for SPI to stabilize after first command */ if( 0 == gFirstCmdMode ) { volatile _u32 CountVal = 0; gFirstCmdMode = 1; CountVal = CPU_FREQ_IN_MHZ*USEC_DELAY; while( CountVal-- ); } #endif /* wait for respond */ RetVal = _SlDrvMsgReadCmdCtx(); /* will free global lock */ SL_TRACE0(DBG_MSG, MSG_314, "_SlDrvCmdOp: exited _SlDrvMsgReadCmdCtx"); } else { _SlDrvObjUnLock(&g_pCB->GlobalLockObj); } return RetVal; } /***************************************************************************** _SlDrvDataReadOp *****************************************************************************/ _SlReturnVal_t _SlDrvDataReadOp( _SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl , void *pTxRxDescBuff , _SlCmdExt_t *pCmdExt) { _SlReturnVal_t RetVal; _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; _SlArgsData_t pArgsData; /* Validate input arguments */ VERIFY_PROTOCOL(NULL != pCmdExt->pRxPayload); /* If zero bytes is requested, return error. */ /* This allows us not to fill remote socket's IP address in return arguments */ VERIFY_PROTOCOL(0 != pCmdExt->RxPayloadLen); /* Validate socket */ if((Sd & BSD_SOCKET_ID_MASK) >= SL_MAX_SOCKETS) { return SL_EBADF; } /*Use Obj to issue the command, if not available try later*/ ObjIdx = (_u8)_SlDrvWaitForPoolObj(RECV_ID, Sd & BSD_SOCKET_ID_MASK); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } _SlDrvProtectionObjLockWaitForever(); pArgsData.pData = pCmdExt->pRxPayload; pArgsData.pArgs = (_u8 *)pTxRxDescBuff; g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&pArgsData; _SlDrvProtectionObjUnLock(); /* Do Flow Control check/update for DataWrite operation */ _SlDrvObjLockWaitForever(&g_pCB->FlowContCB.TxLockObj); /* Clear SyncObj for the case it was signalled before TxPoolCnt */ /* dropped below '1' (last Data buffer was taken) */ /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */ sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj); if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN) { /* If TxPoolCnt was increased by other thread at this moment, TxSyncObj won't wait here */ _SlDrvSyncObjWaitForever(&g_pCB->FlowContCB.TxSyncObj); } _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN); g_pCB->FlowContCB.TxPoolCnt--; _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); /* send the message */ RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (_u8 *)pTxRxDescBuff); _SlDrvObjUnLock(&g_pCB->GlobalLockObj); if(SL_OS_RET_CODE_OK == RetVal) { /* Wait for response message. Will be signaled by _SlDrvMsgRead. */ _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); } _SlDrvReleasePoolObj(ObjIdx); return RetVal; } /* ******************************************************************************/ /* _SlDrvDataWriteOp */ /* ******************************************************************************/ _SlReturnVal_t _SlDrvDataWriteOp( _SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl , void *pTxRxDescBuff , _SlCmdExt_t *pCmdExt) { _SlReturnVal_t RetVal = SL_EAGAIN; /* initiated as SL_EAGAIN for the non blocking mode */ while( 1 ) { /* Do Flow Control check/update for DataWrite operation */ _SlDrvObjLockWaitForever(&g_pCB->FlowContCB.TxLockObj); /* Clear SyncObj for the case it was signalled before TxPoolCnt */ /* dropped below '1' (last Data buffer was taken) */ /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */ sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj); /* we have indication that the last send has failed - socket is no longer valid for operations */ if(g_pCB->SocketTXFailure & (1<<(Sd & BSD_SOCKET_ID_MASK))) { _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); return SL_SOC_ERROR; } if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN + 1) { /* we have indication that this socket is set as blocking and we try to */ /* unblock it - return an error */ if( g_pCB->SocketNonBlocking & (1<< (Sd & BSD_SOCKET_ID_MASK))) { _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); return RetVal; } /* If TxPoolCnt was increased by other thread at this moment, */ /* TxSyncObj won't wait here */ _SlDrvSyncObjWaitForever(&g_pCB->FlowContCB.TxSyncObj); } if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 ) { break; } else { _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); } } _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 ); g_pCB->FlowContCB.TxPoolCnt--; _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); /* send the message */ RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); _SlDrvObjUnLock(&g_pCB->GlobalLockObj); return RetVal; } /* ******************************************************************************/ /* _SlDrvMsgWrite */ /* ******************************************************************************/ _SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t *pCmdCtrl,_SlCmdExt_t *pCmdExt, _u8 *pTxRxDescBuff) { _u8 sendRxPayload = FALSE; VERIFY_PROTOCOL(NULL != pCmdCtrl); g_pCB->FunctionParams.pCmdCtrl = pCmdCtrl; g_pCB->FunctionParams.pTxRxDescBuff = pTxRxDescBuff; g_pCB->FunctionParams.pCmdExt = pCmdExt; g_pCB->TempProtocolHeader.Opcode = pCmdCtrl->Opcode; g_pCB->TempProtocolHeader.Len = _SL_PROTOCOL_CALC_LEN(pCmdCtrl, pCmdExt); if (pCmdExt && pCmdExt->RxPayloadLen < 0 && pCmdExt->TxPayloadLen) { pCmdExt->RxPayloadLen = pCmdExt->RxPayloadLen * (-1); /* change sign */ sendRxPayload = TRUE; g_pCB->TempProtocolHeader.Len = g_pCB->TempProtocolHeader.Len + pCmdExt->RxPayloadLen; } #ifdef SL_START_WRITE_STAT sl_IfStartWriteSequence(g_pCB->FD); #endif #ifdef SL_IF_TYPE_UART /* Write long sync pattern */ NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Long, 2*SYNC_PATTERN_LEN); #else /* Write short sync pattern */ NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Short, SYNC_PATTERN_LEN); #endif /* Header */ NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_pCB->TempProtocolHeader, _SL_CMD_HDR_SIZE); /* Descriptors */ if (pTxRxDescBuff && pCmdCtrl->TxDescLen > 0) { NWP_IF_WRITE_CHECK(g_pCB->FD, pTxRxDescBuff, _SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen)); } /* A special mode where Rx payload and Rx length are used as Tx as well */ /* This mode requires no Rx payload on the response and currently used by fs_Close and sl_Send on */ /* transceiver mode */ if (sendRxPayload == TRUE ) { NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pRxPayload, _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->RxPayloadLen)); } /* Payload */ if (pCmdExt && pCmdExt->TxPayloadLen > 0) { /* If the message has payload, it is mandatory that the message's arguments are protocol aligned. */ /* Otherwise the aligning of arguments will create a gap between arguments and payload. */ VERIFY_PROTOCOL(_SL_IS_PROTOCOL_ALIGNED_SIZE(pCmdCtrl->TxDescLen)); NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload, _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayloadLen)); } _SL_DBG_CNT_INC(MsgCnt.Write); #ifdef SL_START_WRITE_STAT sl_IfEndWriteSequence(g_pCB->FD); #endif return SL_OS_RET_CODE_OK; } /* ******************************************************************************/ /* _SlDrvMsgRead */ /* ******************************************************************************/ _SlReturnVal_t _SlDrvMsgRead(void) { /* alignment for small memory models */ union { _u8 TempBuf[_SL_RESP_HDR_SIZE]; _u32 DummyBuf[2]; } uBuf; _u8 TailBuffer[4]; _u16 LengthToCopy; _u16 AlignedLengthRecv; _u8 AlignSize; _u8 *pAsyncBuf = NULL; _u16 OpCode; _u16 RespPayloadLen; _u8 sd = SL_MAX_SOCKETS; _SlRxMsgClass_e RxMsgClass; /* save params in global CB */ g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler= NULL; VERIFY_RET_OK(_SlDrvRxHdrRead((_u8*)(uBuf.TempBuf), &AlignSize)); OpCode = OPCODE(uBuf.TempBuf); RespPayloadLen = RSP_PAYLOAD_LEN(uBuf.TempBuf); /* 'Init Compelete' message bears no valid FlowControl info */ if(SL_OPCODE_DEVICE_INITCOMPLETE != OpCode) { g_pCB->FlowContCB.TxPoolCnt = ((_SlResponseHeader_t *)uBuf.TempBuf)->TxPoolCnt; g_pCB->SocketNonBlocking = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketNonBlocking; g_pCB->SocketTXFailure = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketTXFailure; if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN) { _SlDrvSyncObjSignal(&g_pCB->FlowContCB.TxSyncObj); } } /* Find the RX messaage class and set its async event handler */ _SlDrvClassifyRxMsg(OpCode); RxMsgClass = g_pCB->FunctionParams.AsyncExt.RxMsgClass; switch(RxMsgClass) { case ASYNC_EVT_CLASS: VERIFY_PROTOCOL(NULL == pAsyncBuf); #if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) g_pCB->FunctionParams.AsyncExt.pAsyncBuf = sl_Malloc(SL_ASYNC_MAX_MSG_LEN); #else g_pCB->FunctionParams.AsyncExt.pAsyncBuf = g_StatMem.AsyncRespBuf; #endif /* set the local pointer to the allocated one */ pAsyncBuf = g_pCB->FunctionParams.AsyncExt.pAsyncBuf; /* clear the async buffer */ _SlDrvMemZero(pAsyncBuf, SL_ASYNC_MAX_MSG_LEN); MALLOC_OK_CHECK(pAsyncBuf); sl_Memcpy(pAsyncBuf, uBuf.TempBuf, _SL_RESP_HDR_SIZE); if (_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) <= SL_ASYNC_MAX_PAYLOAD_LEN) { AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen); } else { AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(SL_ASYNC_MAX_PAYLOAD_LEN); } if (RespPayloadLen > 0) { NWP_IF_READ_CHECK(g_pCB->FD, pAsyncBuf + _SL_RESP_HDR_SIZE, AlignedLengthRecv); } /* In case ASYNC RX buffer length is smaller then the received data length, dump the rest */ if ((_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) > SL_ASYNC_MAX_PAYLOAD_LEN)) { AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) - SL_ASYNC_MAX_PAYLOAD_LEN; while (AlignedLengthRecv > 0) { NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); AlignedLengthRecv = AlignedLengthRecv - 4; } } _SlDrvProtectionObjLockWaitForever(); if ( #ifndef SL_TINY_EXT (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE == OpCode) || (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 == OpCode) || #endif (SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE == OpCode) ) { /* go over the active list if exist to find obj waiting for this Async event */ sd = ((((_SocketResponse_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->sd) & BSD_SOCKET_ID_MASK); } _SlFindAndSetActiveObj(OpCode, sd); _SlDrvProtectionObjUnLock(); break; case RECV_RESP_CLASS: { _u8 ExpArgSize; /* Expected size of Recv/Recvfrom arguments */ switch(OpCode) { case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE: ExpArgSize = RECVFROM_IPV4_ARGS_SIZE; break; #ifndef SL_TINY_EXT case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6: ExpArgSize = RECVFROM_IPV6_ARGS_SIZE; break; #endif default: /* SL_OPCODE_SOCKET_RECVASYNCRESPONSE: */ ExpArgSize = RECV_ARGS_SIZE; } /* Read first 4 bytes of Recv/Recvfrom response to get SocketId and actual */ /* response data length */ NWP_IF_READ_CHECK(g_pCB->FD, &uBuf.TempBuf[4], RECV_ARGS_SIZE); /* Validate Socket ID and Received Length value. */ VERIFY_PROTOCOL((SD(&uBuf.TempBuf[4])& BSD_SOCKET_ID_MASK) < SL_MAX_SOCKETS); _SlDrvProtectionObjLockWaitForever(); /* go over the active list if exist to find obj waiting for this Async event */ VERIFY_RET_OK(_SlFindAndSetActiveObj(OpCode,SD(&uBuf.TempBuf[4]) & BSD_SOCKET_ID_MASK)); /* Verify data is waited on this socket. The pArgs should have been set by _SlDrvDataReadOp(). */ VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData))->pArgs); sl_Memcpy( ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs, &uBuf.TempBuf[4], RECV_ARGS_SIZE); if(ExpArgSize > RECV_ARGS_SIZE) { NWP_IF_READ_CHECK(g_pCB->FD, ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs + RECV_ARGS_SIZE, ExpArgSize - RECV_ARGS_SIZE); } /* Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */ /* Overwrite requested DataSize with actual one. */ /* If error is received, this information will be read from arguments. */ if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0) { VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData); /* Read 4 bytes aligned from interface */ /* therefore check the requested length and read only */ /* 4 bytes aligned data. The rest unaligned (if any) will be read */ /* and copied to a TailBuffer */ LengthToCopy = ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3); AlignedLengthRecv = ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3); if( AlignedLengthRecv >= 4) { NWP_IF_READ_CHECK(g_pCB->FD,((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData,AlignedLengthRecv ); } /* copy the unaligned part, if any */ if( LengthToCopy > 0) { NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); /* copy TailBuffer unaligned part (1/2/3 bytes) */ sl_Memcpy(((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData + AlignedLengthRecv,TailBuffer,LengthToCopy); } } _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); _SlDrvProtectionObjUnLock(); } break; case CMD_RESP_CLASS: /* Some commands pass a maximum arguments size. */ /* In this case Driver will send extra dummy patterns to NWP if */ /* the response message is smaller than maximum. */ /* When RxDescLen is not exact, using RxPayloadLen is forbidden! */ /* If such case cannot be avoided - parse message here to detect */ /* arguments/payload border. */ NWP_IF_READ_CHECK(g_pCB->FD, g_pCB->FunctionParams.pTxRxDescBuff, _SL_PROTOCOL_ALIGN_SIZE(g_pCB->FunctionParams.pCmdCtrl->RxDescLen)); if((NULL != g_pCB->FunctionParams.pCmdExt) && (0 != g_pCB->FunctionParams.pCmdExt->RxPayloadLen)) { /* Actual size of command's response payload: - */ _i16 ActDataSize = RSP_PAYLOAD_LEN(uBuf.TempBuf) - g_pCB->FunctionParams.pCmdCtrl->RxDescLen; g_pCB->FunctionParams.pCmdExt->ActualRxPayloadLen = ActDataSize; /* Check that the space prepared by user for the response data is sufficient. */ if(ActDataSize <= 0) { g_pCB->FunctionParams.pCmdExt->RxPayloadLen = 0; } else { /* In case the user supplied Rx buffer length which is smaller then the received data length, copy according to user length */ if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen) { LengthToCopy = g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (3); AlignedLengthRecv = g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3); } else { LengthToCopy = ActDataSize & (3); AlignedLengthRecv = ActDataSize & (~3); } /* Read 4 bytes aligned from interface */ /* therefore check the requested length and read only */ /* 4 bytes aligned data. The rest unaligned (if any) will be read */ /* and copied to a TailBuffer */ if( AlignedLengthRecv >= 4) { NWP_IF_READ_CHECK(g_pCB->FD, g_pCB->FunctionParams.pCmdExt->pRxPayload, AlignedLengthRecv ); } /* copy the unaligned part, if any */ if( LengthToCopy > 0) { NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); /* copy TailBuffer unaligned part (1/2/3 bytes) */ sl_Memcpy(g_pCB->FunctionParams.pCmdExt->pRxPayload + AlignedLengthRecv, TailBuffer, LengthToCopy); ActDataSize = ActDataSize-4; } /* In case the user supplied Rx buffer length which is smaller then the received data length, dump the rest */ if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen) { /* calculate the rest of the data size to dump */ AlignedLengthRecv = ActDataSize - (g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3)); while( AlignedLengthRecv > 0) { NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer, 4 ); AlignedLengthRecv = AlignedLengthRecv - 4; } } } } break; default: /* DUMMY_MSG_CLASS: Flow control message has no payload. */ break; } if(AlignSize > 0) { NWP_IF_READ_CHECK(g_pCB->FD, uBuf.TempBuf, AlignSize); } _SL_DBG_CNT_INC(MsgCnt.Read); /* Unmask Interrupt call */ sl_IfUnMaskIntHdlr(); return SL_OS_RET_CODE_OK; } /* ******************************************************************************/ /* _SlAsyncEventGenericHandler */ /* ******************************************************************************/ void _SlAsyncEventGenericHandler(void) { _u32 SlAsyncEvent = 0; _u8 OpcodeFound = FALSE; _u8 i; _u32* pEventLocation = NULL; /* This pointer will override the async buffer with the translated event type */ _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)g_pCB->FunctionParams.AsyncExt.pAsyncBuf; /* if no async event registered nothing to do..*/ if (g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler == NULL) return; /* Iterate through all the opcode in the table */ for (i=0; i< (sizeof(OpcodeTranslateTable) / sizeof(OpcodeKeyVal_t)); i++) { if (OpcodeTranslateTable[i].opcode == pHdr->GenHeader.Opcode) { SlAsyncEvent = OpcodeTranslateTable[i].event; OpcodeFound = TRUE; break; } } /* No Async event found in the table */ if (OpcodeFound == FALSE) { /* This case handles all the async events handlers of the DEVICE & SOCK Silos which are handled internally. For these cases we send the async even buffer as is */ g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); } else { /* calculate the event type location to be filled in the async buffer */ pEventLocation = (_u32*)(g_pCB->FunctionParams.AsyncExt.pAsyncBuf + sizeof (_SlResponseHeader_t) - sizeof(SlAsyncEvent) ); /* Override the async buffer (before the data starts ) with our event type */ *pEventLocation = SlAsyncEvent; /* call the event handler registered by the user with our async buffer which now holds the User's event type and its related data */ g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pEventLocation); } } /* ******************************************************************************/ /* _SlDrvMsgReadCmdCtx */ /* ******************************************************************************/ _SlReturnVal_t _SlDrvMsgReadCmdCtx(void) { /* after command response is received and isCmdRespWaited */ /* flag is set FALSE, it is necessary to read out all */ /* Async messages in Commands context, because ssiDma_IsrHandleSignalFromSlave */ /* could have dispatched some Async messages to g_NwpIf.CmdSyncObj */ /* after command response but before this response has been processed */ /* by spi_singleRead and isCmdRespWaited was set FALSE. */ while (TRUE == g_pCB->IsCmdRespWaited) { if(_SL_PENDING_RX_MSG(g_pCB)) { VERIFY_RET_OK(_SlDrvMsgRead()); g_pCB->RxDoneCnt++; if (CMD_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass) { g_pCB->IsCmdRespWaited = FALSE; /* In case CmdResp has been read without waiting on CmdSyncObj - that */ /* Sync object. That to prevent old signal to be processed. */ sl_SyncObjClear(&g_pCB->CmdSyncObj); } else if (ASYNC_EVT_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass) { /* If Async event has been read in CmdResp context, check whether */ /* there is a handler for this event. If there is, spawn specific */ /* handler. Otherwise free the event's buffer. */ /* This way there will be no "dry shots" from CmdResp context to */ /* temporary context, i.e less waste of CPU and faster buffer */ /* release. */ _SlAsyncEventGenericHandler(); #if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); #else g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; #endif } } else { /* CmdSyncObj will be signaled by IRQ */ _SlDrvSyncObjWaitForever(&g_pCB->CmdSyncObj); } } /* If there are more pending Rx Msgs after CmdResp is received, */ /* that means that these are Async, Dummy or Read Data Msgs. */ /* Spawn _SlDrvMsgReadSpawnCtx to trigger reading these messages from */ /* Temporary context. */ /* sl_Spawn is activated, using a different context */ _SlDrvObjUnLock(&g_pCB->GlobalLockObj); if(_SL_PENDING_RX_MSG(g_pCB)) { sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0); } return SL_OS_RET_CODE_OK; } /* ******************************************************************************/ /* _SlDrvMsgReadSpawnCtx */ /* ******************************************************************************/ _SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue) { #ifdef SL_POLLING_MODE_USED _i16 retCode = OSI_OK; /* for polling based systems */ do { retCode = sl_LockObjLock(&g_pCB->GlobalLockObj, 0); if ( OSI_OK != retCode ) { if (TRUE == g_pCB->IsCmdRespWaited) { _SlDrvSyncObjSignal(&g_pCB->CmdSyncObj); return SL_RET_CODE_OK; } } } while (OSI_OK != retCode); #else _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); #endif /* Messages might have been read by CmdResp context. Therefore after */ /* getting LockObj, check again where the Pending Rx Msg is still present. */ if(FALSE == (_SL_PENDING_RX_MSG(g_pCB))) { _SlDrvObjUnLock(&g_pCB->GlobalLockObj); return SL_RET_CODE_OK; } VERIFY_RET_OK(_SlDrvMsgRead()); g_pCB->RxDoneCnt++; switch(g_pCB->FunctionParams.AsyncExt.RxMsgClass) { case ASYNC_EVT_CLASS: /* If got here and protected by LockObj a message is waiting */ /* to be read */ VERIFY_PROTOCOL(NULL != g_pCB->FunctionParams.AsyncExt.pAsyncBuf); _SlAsyncEventGenericHandler(); #if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); #else g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; #endif break; case DUMMY_MSG_CLASS: case RECV_RESP_CLASS: /* These types are legal in this context. Do nothing */ break; case CMD_RESP_CLASS: /* Command response is illegal in this context. */ /* No 'break' here: Assert! */ default: VERIFY_PROTOCOL(0); } _SlDrvObjUnLock(&g_pCB->GlobalLockObj); return(SL_RET_CODE_OK); } /* #define SL_OPCODE_SILO_DEVICE ( 0x0 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_WLAN ( 0x1 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_SOCKET ( 0x2 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_NETAPP ( 0x3 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_NVMEM ( 0x4 << SL_OPCODE_SILO_OFFSET ) #define SL_OPCODE_SILO_NETCFG ( 0x5 << SL_OPCODE_SILO_OFFSET ) */ /* The Lookup table below holds the event handlers to be called according to the incoming RX message SILO type */ const _SlSpawnEntryFunc_t RxMsgClassLUT[] = { (_SlSpawnEntryFunc_t)_SlDrvDeviceEventHandler, /* SL_OPCODE_SILO_DEVICE */ #if defined(sl_WlanEvtHdlr) || defined(EXT_LIB_REGISTERED_WLAN_EVENTS) (_SlSpawnEntryFunc_t)_SlDrvHandleWlanEvents, /* SL_OPCODE_SILO_WLAN */ #else NULL, #endif #if defined (sl_SockEvtHdlr) || defined(EXT_LIB_REGISTERED_SOCK_EVENTS) (_SlSpawnEntryFunc_t)_SlDrvHandleSockEvents, /* SL_OPCODE_SILO_SOCKET */ #else NULL, #endif #if defined(sl_NetAppEvtHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_EVENTS) (_SlSpawnEntryFunc_t)_SlDrvHandleNetAppEvents, /* SL_OPCODE_SILO_NETAPP */ #else NULL, #endif NULL, /* SL_OPCODE_SILO_NVMEM */ NULL, /* SL_OPCODE_SILO_NETCFG */ NULL, NULL }; /* ******************************************************************************/ /* _SlDrvClassifyRxMsg */ /* ******************************************************************************/ void _SlDrvClassifyRxMsg( _SlOpcode_t Opcode) { _SlSpawnEntryFunc_t AsyncEvtHandler = NULL; _SlRxMsgClass_e RxMsgClass = CMD_RESP_CLASS; _u8 Silo; if (0 == (SL_OPCODE_SYNC & Opcode)) { /* Async event has received */ if (SL_OPCODE_DEVICE_DEVICEASYNCDUMMY == Opcode) { RxMsgClass = DUMMY_MSG_CLASS; } else if ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode) #ifndef SL_TINY_EXT || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) #endif ) { RxMsgClass = RECV_RESP_CLASS; } else { /* This is Async Event class message */ RxMsgClass = ASYNC_EVT_CLASS; /* Despite the fact that 4 bits are allocated in the SILO field, we actually have only 6 SILOs So we can use the 8 options of SILO in look up table */ Silo = ((Opcode >> SL_OPCODE_SILO_OFFSET) & 0x7); VERIFY_PROTOCOL(Silo < (sizeof(RxMsgClassLUT)/sizeof(_SlSpawnEntryFunc_t))); /* Set the async event hander according to the LUT */ AsyncEvtHandler = RxMsgClassLUT[Silo]; if ((SL_OPCODE_NETAPP_HTTPGETTOKENVALUE == Opcode) || (SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE == Opcode)) { AsyncEvtHandler = _SlDrvNetAppEventHandler; } #ifndef SL_TINY_EXT else if (SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE == Opcode) { AsyncEvtHandler = (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse; } #endif } } g_pCB->FunctionParams.AsyncExt.RxMsgClass = RxMsgClass; g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = AsyncEvtHandler; } /* ******************************************************************************/ /* _SlDrvRxHdrRead */ /* ******************************************************************************/ _SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf, _u8 *pAlignSize) { _u32 SyncCnt = 0; _u8 ShiftIdx; #ifndef SL_IF_TYPE_UART /* 1. Write CNYS pattern to NWP when working in SPI mode only */ NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NCnysPattern.Short, SYNC_PATTERN_LEN); #endif /* 2. Read 4 bytes (protocol aligned) */ NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 4); _SL_DBG_SYNC_LOG(SyncCnt,pBuf); /* Wait for SYNC_PATTERN_LEN from the device */ while ( ! N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) ) { /* 3. Debug limit of scan */ VERIFY_PROTOCOL(SyncCnt < SL_SYNC_SCAN_THRESHOLD); /* 4. Read next 4 bytes to Low 4 bytes of buffer */ if(0 == (SyncCnt % (_u32)SYNC_PATTERN_LEN)) { NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4); _SL_DBG_SYNC_LOG(SyncCnt,pBuf); } /* 5. Shift Buffer Up for checking if the sync is shifted */ for(ShiftIdx = 0; ShiftIdx< 7; ShiftIdx++) { pBuf[ShiftIdx] = pBuf[ShiftIdx+1]; } pBuf[7] = 0; SyncCnt++; } /* 5. Sync pattern found. If needed, complete number of read bytes to multiple of 4 (protocol align) */ SyncCnt %= SYNC_PATTERN_LEN; if(SyncCnt > 0) { *(_u32 *)&pBuf[0] = *(_u32 *)&pBuf[4]; NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN - SyncCnt], (_u16)SyncCnt); } else { NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 4); } /* 6. Scan for Double pattern. */ while ( N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) ) { _SL_DBG_CNT_INC(Work.DoubleSyncPattern); NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], SYNC_PATTERN_LEN); } g_pCB->TxSeqNum++; /* 7. Here we've read Generic Header (4 bytes). Read the Resp Specific header (4 more bytes). */ NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN], _SL_RESP_SPEC_HDR_SIZE); /* 8. Here we've read the entire Resp Header. */ /* Return number bytes needed to be sent after read for NWP Rx 4-byte alignment (protocol alignment) */ *pAlignSize = (_u8)((SyncCnt > 0) ? (SYNC_PATTERN_LEN - SyncCnt) : 0); return SL_RET_CODE_OK; } /* ***************************************************************************** */ /* _SlDrvBasicCmd */ /* ***************************************************************************** */ typedef union { _BasicResponse_t Rsp; }_SlBasicCmdMsg_u; #ifndef SL_TINY_EXT _i16 _SlDrvBasicCmd(_SlOpcode_t Opcode) { _SlBasicCmdMsg_u Msg = {{0, 0}}; _SlCmdCtrl_t CmdCtrl; CmdCtrl.Opcode = Opcode; CmdCtrl.TxDescLen = 0; CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); return (_i16)Msg.Rsp.status; } /***************************************************************************** _SlDrvCmdSend Send SL command without waiting for command response This function is unprotected and the caller should make sure global lock is active *****************************************************************************/ _SlReturnVal_t _SlDrvCmdSend( _SlCmdCtrl_t *pCmdCtrl , void *pTxRxDescBuff , _SlCmdExt_t *pCmdExt) { _SlReturnVal_t RetVal; _u8 IsCmdRespWaitedOriginalVal; _SlFunctionParams_t originalFuncParms; /* save the current RespWait flag before clearing it */ IsCmdRespWaitedOriginalVal = g_pCB->IsCmdRespWaited; /* save the current command parameters */ sl_Memcpy(&originalFuncParms, &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t)); g_pCB->IsCmdRespWaited = FALSE; SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdSend: call _SlDrvMsgWrite"); /* send the message */ RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); /* restore the original RespWait flag */ g_pCB->IsCmdRespWaited = IsCmdRespWaitedOriginalVal; /* restore the original command parameters */ sl_Memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t)); return RetVal; } #endif /* ***************************************************************************** */ /* _SlDrvWaitForPoolObj */ /* ***************************************************************************** */ _u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID) { _u8 CurrObjIndex = MAX_CONCURRENT_ACTIONS; /* Get free object */ _SlDrvProtectionObjLockWaitForever(); if (MAX_CONCURRENT_ACTIONS > g_pCB->FreePoolIdx) { /* save the current obj index */ CurrObjIndex = g_pCB->FreePoolIdx; /* set the new free index */ #ifndef SL_TINY_EXT if (MAX_CONCURRENT_ACTIONS > g_pCB->ObjPool[CurrObjIndex].NextIndex) { g_pCB->FreePoolIdx = g_pCB->ObjPool[CurrObjIndex].NextIndex; } else #endif { /* No further free actions available */ g_pCB->FreePoolIdx = MAX_CONCURRENT_ACTIONS; } } else { _SlDrvProtectionObjUnLock(); return CurrObjIndex; } g_pCB->ObjPool[CurrObjIndex].ActionID = (_u8)ActionID; if (SL_MAX_SOCKETS > SocketID) { g_pCB->ObjPool[CurrObjIndex].AdditionalData = SocketID; } #ifndef SL_TINY_EXT /*In case this action is socket related, SocketID bit will be on In case SocketID is set to SL_MAX_SOCKETS, the socket is not relevant to the action. In that case ActionID bit will be on */ while ( ( (SL_MAX_SOCKETS > SocketID) && (g_pCB->ActiveActionsBitmap & (1<ActiveActionsBitmap & (1<ObjPool[CurrObjIndex].NextIndex = g_pCB->PendingPoolIdx; g_pCB->PendingPoolIdx = CurrObjIndex; _SlDrvProtectionObjUnLock(); /* wait for action to be free */ _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[CurrObjIndex].SyncObj); /* set params and move to active (remove from pending list at _SlDrvReleasePoolObj) */ _SlDrvProtectionObjLockWaitForever(); } #endif /* mark as active. Set socket as active if action is on socket, otherwise mark action as active */ if (SL_MAX_SOCKETS > SocketID) { g_pCB->ActiveActionsBitmap |= (1<ActiveActionsBitmap |= (1<ObjPool[CurrObjIndex].NextIndex = g_pCB->ActivePoolIdx; g_pCB->ActivePoolIdx = CurrObjIndex; /* unlock */ _SlDrvProtectionObjUnLock(); return CurrObjIndex; } /* ******************************************************************************/ /* _SlDrvReleasePoolObj */ /* ******************************************************************************/ void _SlDrvReleasePoolObj(_u8 ObjIdx) { #ifndef SL_TINY_EXT _u8 PendingIndex; #endif _SlDrvProtectionObjLockWaitForever(); /* In Tiny mode, there is only one object pool so no pending actions are available */ #ifndef SL_TINY_EXT /* go over the pending list and release other pending action if needed */ PendingIndex = g_pCB->PendingPoolIdx; while(MAX_CONCURRENT_ACTIONS > PendingIndex) { /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */ if ( (g_pCB->ObjPool[PendingIndex].ActionID == g_pCB->ObjPool[ObjIdx].ActionID) && ( (SL_MAX_SOCKETS == (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK)) || ((SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)) && ( (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK) == (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK) ))) ) { /* remove from pending list */ _SlRemoveFromList(&g_pCB->PendingPoolIdx, PendingIndex); _SlDrvSyncObjSignal(&g_pCB->ObjPool[PendingIndex].SyncObj); break; } PendingIndex = g_pCB->ObjPool[PendingIndex].NextIndex; } #endif if (SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)) { /* unset socketID */ g_pCB->ActiveActionsBitmap &= ~(1<<(g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)); } else { /* unset actionID */ g_pCB->ActiveActionsBitmap &= ~(1<ObjPool[ObjIdx].ActionID); } /* delete old data */ g_pCB->ObjPool[ObjIdx].pRespArgs = NULL; g_pCB->ObjPool[ObjIdx].ActionID = 0; g_pCB->ObjPool[ObjIdx].AdditionalData = SL_MAX_SOCKETS; /* remove from active list */ _SlRemoveFromList(&g_pCB->ActivePoolIdx, ObjIdx); /* move to free list */ g_pCB->ObjPool[ObjIdx].NextIndex = g_pCB->FreePoolIdx; g_pCB->FreePoolIdx = ObjIdx; _SlDrvProtectionObjUnLock(); } /* ******************************************************************************/ /* _SlRemoveFromList */ /* ******************************************************************************/ void _SlRemoveFromList(_u8 *ListIndex, _u8 ItemIndex) { #ifndef SL_TINY_EXT _u8 Idx; #endif if (MAX_CONCURRENT_ACTIONS == g_pCB->ObjPool[*ListIndex].NextIndex) { *ListIndex = MAX_CONCURRENT_ACTIONS; } /* As MAX_CONCURRENT_ACTIONS is equal to 1 in Tiny mode */ #ifndef SL_TINY_EXT /* need to remove the first item in the list and therefore update the global which holds this index */ else if (*ListIndex == ItemIndex) { *ListIndex = g_pCB->ObjPool[ItemIndex].NextIndex; } else { Idx = *ListIndex; while(MAX_CONCURRENT_ACTIONS > Idx) { /* remove from list */ if (g_pCB->ObjPool[Idx].NextIndex == ItemIndex) { g_pCB->ObjPool[Idx].NextIndex = g_pCB->ObjPool[ItemIndex].NextIndex; break; } Idx = g_pCB->ObjPool[Idx].NextIndex; } } #endif } /* ******************************************************************************/ /* _SlFindAndSetActiveObj */ /* ******************************************************************************/ _SlReturnVal_t _SlFindAndSetActiveObj(_SlOpcode_t Opcode, _u8 Sd) { _u8 ActiveIndex; ActiveIndex = g_pCB->ActivePoolIdx; /* go over the active list if exist to find obj waiting for this Async event */ #ifndef SL_TINY_EXT while (MAX_CONCURRENT_ACTIONS > ActiveIndex) #else /* Only one Active action is availabe in tiny mode, so we can replace the loop with if condition */ if (MAX_CONCURRENT_ACTIONS > ActiveIndex) #endif { /* unset the Ipv4\IPv6 bit in the opcode if family bit was set */ if (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) { Opcode &= ~SL_OPCODE_IPV6; } if ((g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID) && (Sd == g_pCB->ObjPool[ActiveIndex].AdditionalData) && ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode) #ifndef SL_TINY_EXT || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) #endif ) ) { g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex; return SL_RET_CODE_OK; } /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */ if ( (_SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].ActionAsyncOpcode == Opcode) && ( ((Sd == (g_pCB->ObjPool[ActiveIndex].AdditionalData & BSD_SOCKET_ID_MASK) ) && (SL_MAX_SOCKETS > Sd)) || (SL_MAX_SOCKETS == (g_pCB->ObjPool[ActiveIndex].AdditionalData & BSD_SOCKET_ID_MASK)) ) ) { /* set handler */ g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = _SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].AsyncEventHandler; g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex; return SL_RET_CODE_OK; } ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex; } return SL_RET_CODE_SELF_ERROR; } /* Wrappers for the object functions */ void _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj) { OSI_RET_OK_CHECK(sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER)); } void _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj) { OSI_RET_OK_CHECK(sl_SyncObjSignal(pSyncObj)); } void _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj) { OSI_RET_OK_CHECK(sl_LockObjLock(pLockObj, SL_OS_WAIT_FOREVER)); } void _SlDrvProtectionObjLockWaitForever() { OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER)); } void _SlDrvObjUnLock(_SlLockObj_t *pLockObj) { OSI_RET_OK_CHECK(sl_LockObjUnlock(pLockObj)); } void _SlDrvProtectionObjUnLock() { OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj)); } void _SlDrvMemZero(void* Addr, _u16 size) { sl_Memset(Addr, 0, size); } void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt) { _SlDrvMemZero(pCmdExt, sizeof (_SlCmdExt_t)); } micropython-1.12/drivers/cc3100/src/flowcont.c000066400000000000000000000055051357706137100211640ustar00rootroot00000000000000/* * flowcont.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "driver.h" #include "flowcont.h" /*****************************************************************************/ /* _SlDrvFlowContInit */ /*****************************************************************************/ void _SlDrvFlowContInit(void) { g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN; OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj")); OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj")); } /*****************************************************************************/ /* _SlDrvFlowContDeinit */ /*****************************************************************************/ void _SlDrvFlowContDeinit(void) { g_pCB->FlowContCB.TxPoolCnt = 0; OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj)); OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj)); } micropython-1.12/drivers/cc3100/src/fs.c000066400000000000000000000315331357706137100177410ustar00rootroot00000000000000/* * fs.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "driver.h" /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #define sl_min(a,b) (((a) < (b)) ? (a) : (b)) #define MAX_NVMEM_CHUNK_SIZE 1460 /*****************************************************************************/ /* Internal functions */ /*****************************************************************************/ /*****************************************************************************/ /* _sl_Strlen */ /*****************************************************************************/ _u16 _sl_Strlen(const _u8 *buffer) { _u16 len = 0; if( buffer != NULL ) { while(*buffer++) len++; } return len; } /*****************************************************************************/ /* _sl_GetCreateFsMode */ /*****************************************************************************/ _u32 _sl_GetCreateFsMode(_u32 maxSizeInBytes,_u32 accessFlags) { _u32 granIdx = 0; _u32 granNum = 0; _u32 granTable[_FS_MAX_MODE_SIZE_GRAN] = {256,1024,4096,16384,65536}; for(granIdx= _FS_MODE_SIZE_GRAN_256B ;granIdx< _FS_MAX_MODE_SIZE_GRAN;granIdx++) { if( granTable[granIdx]*255 >= maxSizeInBytes ) break; } granNum = maxSizeInBytes/granTable[granIdx]; if( maxSizeInBytes % granTable[granIdx] != 0 ) granNum++; return _FS_MODE(_FS_MODE_OPEN_WRITE_CREATE_IF_NOT_EXIST, granIdx, granNum, accessFlags); } /*****************************************************************************/ /* API functions */ /*****************************************************************************/ /*****************************************************************************/ /* sl_FsOpen */ /*****************************************************************************/ typedef union { _FsOpenCommand_t Cmd; _FsOpenResponse_t Rsp; }_SlFsOpenMsg_u; #if _SL_INCLUDE_FUNC(sl_FsOpen) const _SlCmdCtrl_t _SlFsOpenCmdCtrl = { SL_OPCODE_NVMEM_FILEOPEN, sizeof(_FsOpenCommand_t), sizeof(_FsOpenResponse_t) }; _i32 sl_FsOpen(const _u8 *pFileName,const _u32 AccessModeAndMaxSize, _u32 *pToken,_i32 *pFileHandle) { _SlReturnVal_t RetVal; _SlFsOpenMsg_u Msg; _SlCmdExt_t CmdExt; CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ CmdExt.RxPayloadLen = 0; CmdExt.pTxPayload = (_u8*)pFileName; CmdExt.pRxPayload = NULL; Msg.Cmd.Mode = AccessModeAndMaxSize; if(pToken != NULL) { Msg.Cmd.Token = *pToken; } else { Msg.Cmd.Token = 0; } RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsOpenCmdCtrl, &Msg, &CmdExt); *pFileHandle = Msg.Rsp.FileHandle; if (pToken != NULL) { *pToken = Msg.Rsp.Token; } /* in case of an error, return the erros file handler as an error code */ if( *pFileHandle < 0 ) { return *pFileHandle; } return (_i32)RetVal; } #endif /*****************************************************************************/ /* sl_FsClose */ /*****************************************************************************/ typedef union { _FsCloseCommand_t Cmd; _BasicResponse_t Rsp; }_SlFsCloseMsg_u; #if _SL_INCLUDE_FUNC(sl_FsClose) const _SlCmdCtrl_t _SlFsCloseCmdCtrl = { SL_OPCODE_NVMEM_FILECLOSE, sizeof(_FsCloseCommand_t), sizeof(_FsCloseResponse_t) }; _i16 sl_FsClose(const _i32 FileHdl, const _u8* pCeritificateFileName,const _u8* pSignature ,const _u32 SignatureLen) { _SlFsCloseMsg_u Msg = {{0, 0}}; _SlCmdExt_t ExtCtrl; Msg.Cmd.FileHandle = FileHdl; if( pCeritificateFileName != NULL ) { Msg.Cmd.CertificFileNameLength = (_sl_Strlen(pCeritificateFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ } Msg.Cmd.SignatureLen = SignatureLen; ExtCtrl.TxPayloadLen = ((SignatureLen+3) & (~3)); /* align */ ExtCtrl.pTxPayload = (_u8*)pSignature; ExtCtrl.RxPayloadLen = (_i16)Msg.Cmd.CertificFileNameLength; ExtCtrl.pRxPayload = (_u8*)pCeritificateFileName; /* Add signature */ if(ExtCtrl.pRxPayload != NULL && ExtCtrl.RxPayloadLen != 0) { ExtCtrl.RxPayloadLen = ExtCtrl.RxPayloadLen * (-1); } VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsCloseCmdCtrl, &Msg, &ExtCtrl)); return (_i16)((_i16)Msg.Rsp.status); } #endif /*****************************************************************************/ /* sl_FsRead */ /*****************************************************************************/ typedef union { _FsReadCommand_t Cmd; _FsReadResponse_t Rsp; }_SlFsReadMsg_u; #if _SL_INCLUDE_FUNC(sl_FsRead) const _SlCmdCtrl_t _SlFsReadCmdCtrl = { SL_OPCODE_NVMEM_FILEREADCOMMAND, sizeof(_FsReadCommand_t), sizeof(_FsReadResponse_t) }; _i32 sl_FsRead(const _i32 FileHdl,_u32 Offset, _u8* pData,_u32 Len) { _SlFsReadMsg_u Msg; _SlCmdExt_t ExtCtrl; _u16 ChunkLen; _SlReturnVal_t RetVal =0; _i32 RetCount = 0; ExtCtrl.TxPayloadLen = 0; ExtCtrl.pTxPayload = NULL; ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); ExtCtrl.RxPayloadLen = ChunkLen; ExtCtrl.pRxPayload = (_u8 *)(pData); Msg.Cmd.Offset = Offset; Msg.Cmd.Len = ChunkLen; Msg.Cmd.FileHandle = FileHdl; do { RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsReadCmdCtrl, &Msg, &ExtCtrl); if(SL_OS_RET_CODE_OK == RetVal) { if( Msg.Rsp.status < 0) { if( RetCount > 0) { return RetCount; } else { return Msg.Rsp.status; } } RetCount += (_i32)Msg.Rsp.status; Len -= ChunkLen; Offset += ChunkLen; Msg.Cmd.Offset = Offset; ExtCtrl.pRxPayload += ChunkLen; ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); ExtCtrl.RxPayloadLen = ChunkLen; Msg.Cmd.Len = ChunkLen; Msg.Cmd.FileHandle = FileHdl; } else { return RetVal; } }while(ChunkLen > 0); return (_i32)RetCount; } #endif /*****************************************************************************/ /* sl_FsWrite */ /*****************************************************************************/ typedef union { _FsWriteCommand_t Cmd; _FsWriteResponse_t Rsp; }_SlFsWriteMsg_u; #if _SL_INCLUDE_FUNC(sl_FsWrite) const _SlCmdCtrl_t _SlFsWriteCmdCtrl = { SL_OPCODE_NVMEM_FILEWRITECOMMAND, sizeof(_FsWriteCommand_t), sizeof(_FsWriteResponse_t) }; _i32 sl_FsWrite(const _i32 FileHdl,_u32 Offset, _u8* pData,_u32 Len) { _SlFsWriteMsg_u Msg; _SlCmdExt_t ExtCtrl; _u16 ChunkLen; _SlReturnVal_t RetVal; _i32 RetCount = 0; ExtCtrl.RxPayloadLen = 0; ExtCtrl.pRxPayload = NULL; ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); ExtCtrl.TxPayloadLen = ChunkLen; ExtCtrl.pTxPayload = (_u8 *)(pData); Msg.Cmd.Offset = Offset; Msg.Cmd.Len = ChunkLen; Msg.Cmd.FileHandle = FileHdl; do { RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsWriteCmdCtrl, &Msg, &ExtCtrl); if(SL_OS_RET_CODE_OK == RetVal) { if( Msg.Rsp.status < 0) { if( RetCount > 0) { return RetCount; } else { return Msg.Rsp.status; } } RetCount += (_i32)Msg.Rsp.status; Len -= ChunkLen; Offset += ChunkLen; Msg.Cmd.Offset = Offset; ExtCtrl.pTxPayload += ChunkLen; ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); ExtCtrl.TxPayloadLen = ChunkLen; Msg.Cmd.Len = ChunkLen; Msg.Cmd.FileHandle = FileHdl; } else { return RetVal; } }while(ChunkLen > 0); return (_i32)RetCount; } #endif /*****************************************************************************/ /* sl_FsGetInfo */ /*****************************************************************************/ typedef union { _FsGetInfoCommand_t Cmd; _FsGetInfoResponse_t Rsp; }_SlFsGetInfoMsg_u; #if _SL_INCLUDE_FUNC(sl_FsGetInfo) const _SlCmdCtrl_t _SlFsGetInfoCmdCtrl = { SL_OPCODE_NVMEM_FILEGETINFOCOMMAND, sizeof(_FsGetInfoCommand_t), sizeof(_FsGetInfoResponse_t) }; _i16 sl_FsGetInfo(const _u8 *pFileName,const _u32 Token,SlFsFileInfo_t* pFsFileInfo) { _SlFsGetInfoMsg_u Msg; _SlCmdExt_t CmdExt; CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ CmdExt.RxPayloadLen = 0; CmdExt.pTxPayload = (_u8*)pFileName; CmdExt.pRxPayload = NULL; Msg.Cmd.Token = Token; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsGetInfoCmdCtrl, &Msg, &CmdExt)); pFsFileInfo->flags = Msg.Rsp.flags; pFsFileInfo->FileLen = Msg.Rsp.FileLen; pFsFileInfo->AllocatedLen = Msg.Rsp.AllocatedLen; pFsFileInfo->Token[0] = Msg.Rsp.Token[0]; pFsFileInfo->Token[1] = Msg.Rsp.Token[1]; pFsFileInfo->Token[2] = Msg.Rsp.Token[2]; pFsFileInfo->Token[3] = Msg.Rsp.Token[3]; return (_i16)((_i16)Msg.Rsp.Status); } #endif /*****************************************************************************/ /* sl_FsDel */ /*****************************************************************************/ typedef union { _FsDeleteCommand_t Cmd; _FsDeleteResponse_t Rsp; }_SlFsDeleteMsg_u; #if _SL_INCLUDE_FUNC(sl_FsDel) const _SlCmdCtrl_t _SlFsDeleteCmdCtrl = { SL_OPCODE_NVMEM_FILEDELCOMMAND, sizeof(_FsDeleteCommand_t), sizeof(_FsDeleteResponse_t) }; _i16 sl_FsDel(const _u8 *pFileName,const _u32 Token) { _SlFsDeleteMsg_u Msg; _SlCmdExt_t CmdExt; CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ CmdExt.RxPayloadLen = 0; CmdExt.pTxPayload = (_u8*)pFileName; CmdExt.pRxPayload = NULL; Msg.Cmd.Token = Token; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsDeleteCmdCtrl, &Msg, &CmdExt)); return (_i16)((_i16)Msg.Rsp.status); } #endif micropython-1.12/drivers/cc3100/src/netapp.c000066400000000000000000001223601357706137100206170ustar00rootroot00000000000000/* * netapp.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "driver.h" /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #define NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT ((_u32)0x1 << 31) #ifdef SL_TINY #define NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH 63 #else #define NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH 255 #endif /*****************************************************************************/ /* Functions prototypes */ /*****************************************************************************/ void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf); #ifndef SL_TINY_EXT void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf); void _sl_HandleAsync_PingResponse(void *pVoidBuf); #endif void CopyPingResultsToReport(_PingReportResponse_t *pResults,SlPingReport_t *pReport); _i16 sl_NetAppMDNSRegisterUnregisterService(const _i8* pServiceName, const _u8 ServiceNameLen, const _i8* pText, const _u8 TextLen, const _u16 Port, const _u32 TTL, const _u32 Options); #if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) _u16 _sl_NetAppSendTokenValue(slHttpServerData_t * Token); #endif typedef union { _NetAppStartStopCommand_t Cmd; _NetAppStartStopResponse_t Rsp; }_SlNetAppStartStopMsg_u; #if _SL_INCLUDE_FUNC(sl_NetAppStart) const _SlCmdCtrl_t _SlNetAppStartCtrl = { SL_OPCODE_NETAPP_START_COMMAND, sizeof(_NetAppStartStopCommand_t), sizeof(_NetAppStartStopResponse_t) }; _i16 sl_NetAppStart(const _u32 AppBitMap) { _SlNetAppStartStopMsg_u Msg; Msg.Cmd.appId = AppBitMap; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppStartCtrl, &Msg, NULL)); return Msg.Rsp.status; } #endif /***************************************************************************** sl_NetAppStop *****************************************************************************/ #if _SL_INCLUDE_FUNC(sl_NetAppStop) const _SlCmdCtrl_t _SlNetAppStopCtrl = { SL_OPCODE_NETAPP_STOP_COMMAND, sizeof(_NetAppStartStopCommand_t), sizeof(_NetAppStartStopResponse_t) }; _i16 sl_NetAppStop(const _u32 AppBitMap) { _SlNetAppStartStopMsg_u Msg; Msg.Cmd.appId = AppBitMap; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppStopCtrl, &Msg, NULL)); return Msg.Rsp.status; } #endif /******************************************************************************/ /* sl_NetAppGetServiceList */ /******************************************************************************/ typedef struct { _u8 IndexOffest; _u8 MaxServiceCount; _u8 Flags; _i8 Padding; }NetappGetServiceListCMD_t; typedef union { NetappGetServiceListCMD_t Cmd; _BasicResponse_t Rsp; }_SlNetappGetServiceListMsg_u; #if _SL_INCLUDE_FUNC(sl_NetAppGetServiceList) const _SlCmdCtrl_t _SlGetServiceListeCtrl = { SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE, sizeof(NetappGetServiceListCMD_t), sizeof(_BasicResponse_t) }; _i16 sl_NetAppGetServiceList(const _u8 IndexOffest, const _u8 MaxServiceCount, const _u8 Flags, _i8 *pBuffer, const _u32 RxBufferLength ) { _i32 retVal= 0; _SlNetappGetServiceListMsg_u Msg; _SlCmdExt_t CmdExt; _u16 ServiceSize = 0; _u16 BufferSize = 0; /* Calculate RX pBuffer size WARNING: if this size is BufferSize than 1480 error should be returned because there is no place in the RX packet. */ switch(Flags) { case SL_NET_APP_FULL_SERVICE_WITH_TEXT_IPV4_TYPE: ServiceSize = sizeof(SlNetAppGetFullServiceWithTextIpv4List_t); break; case SL_NET_APP_FULL_SERVICE_IPV4_TYPE: ServiceSize = sizeof(SlNetAppGetFullServiceIpv4List_t); break; case SL_NET_APP_SHORT_SERVICE_IPV4_TYPE: ServiceSize = sizeof(SlNetAppGetShortServiceIpv4List_t); break; default: ServiceSize = sizeof(_BasicResponse_t); break; } BufferSize = MaxServiceCount * ServiceSize; /*Check the size of the requested services is smaller than size of the user buffer. If not an error is returned in order to avoid overwriting memory. */ if(RxBufferLength <= BufferSize) { return SL_ERROR_NETAPP_RX_BUFFER_LENGTH_ERROR; } _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = BufferSize; CmdExt.pRxPayload = (_u8 *)pBuffer; Msg.Cmd.IndexOffest = IndexOffest; Msg.Cmd.MaxServiceCount = MaxServiceCount; Msg.Cmd.Flags = Flags; Msg.Cmd.Padding = 0; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetServiceListeCtrl, &Msg, &CmdExt)); retVal = Msg.Rsp.status; return (_i16)retVal; } #endif /*****************************************************************************/ /* sl_mDNSRegisterService */ /*****************************************************************************/ /* * The below struct depicts the constant parameters of the command/API RegisterService. * 1. ServiceLen - The length of the service should be smaller than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. 2. TextLen - The length of the text should be smaller than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. 3. port - The port on this target host. 4. TTL - The TTL of the service 5. Options - bitwise parameters: bit 0 - is unique (means if the service needs to be unique) bit 31 - for internal use if the service should be added or deleted (set means ADD). bit 1-30 for future. NOTE: 1. There are another variable parameter is this API which is the service name and the text. 2. According to now there is no warning and Async event to user on if the service is a unique. * */ typedef struct { _u8 ServiceNameLen; _u8 TextLen; _u16 Port; _u32 TTL; _u32 Options; }NetappMdnsSetService_t; typedef union { NetappMdnsSetService_t Cmd; _BasicResponse_t Rsp; }_SlNetappMdnsRegisterServiceMsg_u; #if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterUnregisterService) const _SlCmdCtrl_t _SlRegisterServiceCtrl = { SL_OPCODE_NETAPP_MDNSREGISTERSERVICE, sizeof(NetappMdnsSetService_t), sizeof(_BasicResponse_t) }; /****************************************************************************** sl_NetAppMDNSRegisterService CALLER user from its host DESCRIPTION: Add/delete service The function manipulates the command that register the service and call to the NWP in order to add/delete the service to/from the mDNS package and to/from the DB. This register service is a service offered by the application. This unregister service is a service offered by the application before. The service name should be full service name according to RFC of the DNS-SD - means the value in name field in SRV answer. Example for service name: 1. PC1._ipp._tcp.local 2. PC2_server._ftp._tcp.local If the option is_unique is set, mDNS probes the service name to make sure it is unique before starting to announce the service on the network. Instance is the instance portion of the service name. PARAMETERS: The command is from constant parameters and variables parameters. Constant parameters are: ServiceLen - The length of the service. TextLen - The length of the service should be smaller than 64. port - The port on this target host. TTL - The TTL of the service Options - bitwise parameters: bit 0 - is unique (means if the service needs to be unique) bit 31 - for internal use if the service should be added or deleted (set means ADD). bit 1-30 for future. The variables parameters are: Service name(full service name) - The service name. Example for service name: 1. PC1._ipp._tcp.local 2. PC2_server._ftp._tcp.local Text - The description of the service. should be as mentioned in the RFC (according to type of the service IPP,FTP...) NOTE - pay attention 1. Temporary - there is an allocation on stack of internal buffer. Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. It means that the sum of the text length and service name length cannot be bigger than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. If it is - An error is returned. 2. According to now from certain constraints the variables parameters are set in the attribute part (contain constant parameters) RETURNS: Status - the immediate response of the command status. 0 means success. ******************************************************************************/ _i16 sl_NetAppMDNSRegisterUnregisterService( const _i8* pServiceName, const _u8 ServiceNameLen, const _i8* pText, const _u8 TextLen, const _u16 Port, const _u32 TTL, const _u32 Options) { _SlNetappMdnsRegisterServiceMsg_u Msg; _SlCmdExt_t CmdExt ; _i8 ServiceNameAndTextBuffer[NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH]; _i8 *TextPtr; /* NOTE - pay attention 1. Temporary - there is an allocation on stack of internal buffer. Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. It means that the sum of the text length and service name length cannot be bigger than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. If it is - An error is returned. 2. According to now from certain constraints the variables parameters are set in the attribute part (contain constant parameters) */ /*build the attribute part of the command. It contains the constant parameters of the command*/ Msg.Cmd.ServiceNameLen = ServiceNameLen; Msg.Cmd.Options = Options; Msg.Cmd.Port = Port; Msg.Cmd.TextLen = TextLen; Msg.Cmd.TTL = TTL; /*Build the payload part of the command Copy the service name and text to one buffer. NOTE - pay attention The size of the service length + the text length should be smaller than 255, Until the simplelink drive supports to variable length through SPI command. */ if(TextLen + ServiceNameLen > (NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH - 1 )) /*-1 is for giving a place to set null termination at the end of the text*/ { return -1; } _SlDrvMemZero(ServiceNameAndTextBuffer, NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH); /*Copy the service name*/ sl_Memcpy(ServiceNameAndTextBuffer, pServiceName, ServiceNameLen); if(TextLen > 0 ) { TextPtr = &ServiceNameAndTextBuffer[ServiceNameLen]; /*Copy the text just after the service name*/ sl_Memcpy(TextPtr, pText, TextLen); } _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = (TextLen + ServiceNameLen); CmdExt.pTxPayload = (_u8 *)ServiceNameAndTextBuffer; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRegisterServiceCtrl, &Msg, &CmdExt)); return (_i16)Msg.Rsp.status; } #endif /**********************************************************************************************/ #if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterService) _i16 sl_NetAppMDNSRegisterService( const _i8* pServiceName, const _u8 ServiceNameLen, const _i8* pText, const _u8 TextLen, const _u16 Port, const _u32 TTL, _u32 Options) { /* NOTE - pay attention 1. Temporary - there is an allocation on stack of internal buffer. Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. It means that the sum of the text length and service name length cannot be bigger than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. If it is - An error is returned. 2. According to now from certain constraints the variables parameters are set in the attribute part (contain constant parameters) */ /*Set the add service bit in the options parameter. In order not use different opcodes for the register service and unregister service bit 31 in option is taken for this purpose. if it is set it means in NWP that the service should be added if it is cleared it means that the service should be deleted and there is only meaning to pServiceName and ServiceNameLen values. */ Options |= NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT; return sl_NetAppMDNSRegisterUnregisterService( pServiceName, ServiceNameLen, pText, TextLen, Port, TTL, Options); } #endif /**********************************************************************************************/ /**********************************************************************************************/ #if _SL_INCLUDE_FUNC(sl_NetAppMDNSUnRegisterService) _i16 sl_NetAppMDNSUnRegisterService( const _i8* pServiceName, const _u8 ServiceNameLen) { _u32 Options = 0; /* NOTE - pay attention The size of the service length should be smaller than 255, Until the simplelink drive supports to variable length through SPI command. */ /*Clear the add service bit in the options parameter. In order not use different opcodes for the register service and unregister service bit 31 in option is taken for this purpose. if it is set it means in NWP that the service should be added if it is cleared it means that the service should be deleted and there is only meaning to pServiceName and ServiceNameLen values.*/ Options &= (~NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT); return sl_NetAppMDNSRegisterUnregisterService( pServiceName, ServiceNameLen, NULL, 0, 0, 0, Options); } #endif /**********************************************************************************************/ /*****************************************************************************/ /* sl_DnsGetHostByService */ /*****************************************************************************/ /* * The below struct depicts the constant parameters of the command/API sl_DnsGetHostByService. * 1. ServiceLen - The length of the service should be smaller than 255. 2. AddrLen - TIPv4 or IPv6 (SL_AF_INET , SL_AF_INET6). * */ typedef struct { _u8 ServiceLen; _u8 AddrLen; _u16 Padding; }_GetHostByServiceCommand_t; /* * The below structure depict the constant parameters that are returned in the Async event answer * according to command/API sl_DnsGetHostByService for IPv4 and IPv6. * 1Status - The status of the response. 2.Address - Contains the IP address of the service. 3.Port - Contains the port of the service. 4.TextLen - Contains the max length of the text that the user wants to get. it means that if the test of service is bigger that its value than the text is cut to inout_TextLen value. Output: Contain the length of the text that is returned. Can be full text or part of the text (see above). * */ typedef struct { _u16 Status; _u16 TextLen; _u32 Port; _u32 Address; }_GetHostByServiceIPv4AsyncResponse_t; typedef struct { _u16 Status; _u16 TextLen; _u32 Port; _u32 Address[4]; }_GetHostByServiceIPv6AsyncResponse_t; typedef union { _GetHostByServiceIPv4AsyncResponse_t IpV4; _GetHostByServiceIPv6AsyncResponse_t IpV6; }_GetHostByServiceAsyncResponseAttribute_u; /* * The below struct contains pointers to the output parameters that the user gives * */ typedef struct { _i16 Status; _u32 *out_pAddr; _u32 *out_pPort; _u16 *inout_TextLen; /* in: max len , out: actual len */ _i8 *out_pText; }_GetHostByServiceAsyncResponse_t; typedef union { _GetHostByServiceCommand_t Cmd; _BasicResponse_t Rsp; }_SlGetHostByServiceMsg_u; #if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByService) const _SlCmdCtrl_t _SlGetHostByServiceCtrl = { SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICE, sizeof(_GetHostByServiceCommand_t), sizeof(_BasicResponse_t) }; /******************************************************************************/ _i32 sl_NetAppDnsGetHostByService(_i8 *pServiceName, /* string containing all (or only part): name + subtype + service */ const _u8 ServiceLen, const _u8 Family, /* 4-IPv4 , 16-IPv6 */ _u32 pAddr[], _u32 *pPort, _u16 *pTextLen, /* in: max len , out: actual len */ _i8 *pText ) { _SlGetHostByServiceMsg_u Msg; _SlCmdExt_t CmdExt ; _GetHostByServiceAsyncResponse_t AsyncRsp; _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; /* Note: 1. The return's attributes are belonged to first service that is found. It can be other services with the same service name will response to the query. The results of these responses are saved in the peer cache of the NWP, and should be read by another API. 2. Text length can be 120 bytes only - not more It is because of constraints in the NWP on the buffer that is allocated for the Async event. 3.The API waits to Async event by blocking. It means that the API is finished only after an Async event is sent by the NWP. 4.No rolling option!!! - only PTR type is sent. */ /*build the attribute part of the command. It contains the constant parameters of the command */ Msg.Cmd.ServiceLen = ServiceLen; Msg.Cmd.AddrLen = Family; /*Build the payload part of the command Copy the service name and text to one buffer.*/ _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = ServiceLen; CmdExt.pTxPayload = (_u8 *)pServiceName; /*set pointers to the output parameters (the returned parameters). This pointers are belonged to local struct that is set to global Async response parameter. It is done in order not to run more than one sl_DnsGetHostByService at the same time. The API should be run only if global parameter is pointed to NULL. */ AsyncRsp.out_pText = pText; AsyncRsp.inout_TextLen = (_u16* )pTextLen; AsyncRsp.out_pPort = pPort; AsyncRsp.out_pAddr = (_u32 *)pAddr; ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, GETHOSYBYSERVICE_ID, SL_MAX_SOCKETS); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } if (SL_AF_INET6 == Family) { g_pCB->ObjPool[ObjIdx].AdditionalData |= SL_NETAPP_FAMILY_MASK; } /* Send the command */ VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetHostByServiceCtrl, &Msg, &CmdExt)); /* If the immediate reponse is O.K. than wait for aSYNC event response. */ if(SL_RET_CODE_OK == Msg.Rsp.status) { _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); /* If we are - it means that Async event was sent. The results are copied in the Async handle return functions */ Msg.Rsp.status = AsyncRsp.Status; } _SlDrvReleasePoolObj(ObjIdx); return Msg.Rsp.status; } #endif /******************************************************************************/ /****************************************************************************** _sl_HandleAsync_DnsGetHostByService CALLER NWP - Async event on sl_DnsGetHostByService with IPv4 Family DESCRIPTION: Async event on sl_DnsGetHostByService command with IPv4 Family. Return service attributes like IP address, port and text according to service name. The user sets a service name Full/Part (see example below), and should get the: 1. IP of the service 2. The port of service. 3. The text of service. Hence it can make a connection to the specific service and use it. It is similar to get host by name method. It is done by a single shot query with PTR type on the service name. Note: 1. The return's attributes are belonged to first service that is found. It can be other services with the same service name will response to the query. The results of these responses are saved in the peer cache of the NWP, and should be read by another API. PARAMETERS: pVoidBuf - is point to opcode of the event. it contains the outputs that are given to the user outputs description: 1.out_pAddr[] - output: Contain the IP address of the service. 2.out_pPort - output: Contain the port of the service. 3.inout_TextLen - Input: Contain the max length of the text that the user wants to get. it means that if the test of service is bigger that its value than the text is cut to inout_TextLen value. Output: Contain the length of the text that is returned. Can be full text or part of the text (see above). 4.out_pText - Contain the text of the service (full or part see above- inout_TextLen description). * RETURNS: success or fail. ******************************************************************************/ #ifndef SL_TINY_EXT void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf) { _GetHostByServiceAsyncResponse_t* Res; _u16 TextLen; _u16 UserTextLen; /*pVoidBuf - is point to opcode of the event.*/ /*set pMsgArgs to point to the attribute of the event.*/ _GetHostByServiceIPv4AsyncResponse_t *pMsgArgs = (_GetHostByServiceIPv4AsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); /*IPv6*/ if(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) { return; } /*IPv4*/ else { /************************************************************************************************* 1. Copy the attribute part of the evnt to the attribute part of the response sl_Memcpy(g_pCB->GetHostByServiceCB.pAsyncRsp, pMsgArgs, sizeof(_GetHostByServiceIPv4AsyncResponse_t)); set to TextLen the text length of the service.*/ TextLen = pMsgArgs->TextLen; /*Res pointed to mDNS global object struct */ Res = (_GetHostByServiceAsyncResponse_t*)g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs; /*It is 4 bytes so we avoid from memcpy*/ Res->out_pAddr[0] = pMsgArgs->Address; Res->out_pPort[0] = pMsgArgs->Port; Res->Status = pMsgArgs->Status; /*set to TextLen the text length of the user (input fromthe user).*/ UserTextLen = Res->inout_TextLen[0]; /*Cut the service text if the user requested for smaller text.*/ UserTextLen = (TextLen <= UserTextLen) ? TextLen : UserTextLen; Res->inout_TextLen[0] = UserTextLen ; /************************************************************************************************** 2. Copy the payload part of the evnt (the text) to the payload part of the response the lenght of the copy is according to the text length in the attribute part. */ sl_Memcpy(Res->out_pText , (_i8 *)(& pMsgArgs[1]) , /* & pMsgArgs[1] -> 1st byte after the fixed header = 1st byte of variable text.*/ UserTextLen ); /**************************************************************************************************/ _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); return; } } /*****************************************************************************/ /* _sl_HandleAsync_DnsGetHostByAddr */ /*****************************************************************************/ void _sl_HandleAsync_DnsGetHostByAddr(void *pVoidBuf) { SL_TRACE0(DBG_MSG, MSG_303, "STUB: _sl_HandleAsync_DnsGetHostByAddr not implemented yet!"); return; } #endif /*****************************************************************************/ /* sl_DnsGetHostByName */ /*****************************************************************************/ typedef union { _GetHostByNameIPv4AsyncResponse_t IpV4; _GetHostByNameIPv6AsyncResponse_t IpV6; }_GetHostByNameAsyncResponse_u; typedef union { _GetHostByNameCommand_t Cmd; _BasicResponse_t Rsp; }_SlGetHostByNameMsg_u; #if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByName) const _SlCmdCtrl_t _SlGetHostByNameCtrl = { SL_OPCODE_NETAPP_DNSGETHOSTBYNAME, sizeof(_GetHostByNameCommand_t), sizeof(_BasicResponse_t) }; _i16 sl_NetAppDnsGetHostByName(_i8 * hostname,const _u16 usNameLen, _u32* out_ip_addr,const _u8 family) { _SlGetHostByNameMsg_u Msg; _SlCmdExt_t ExtCtrl; _GetHostByNameAsyncResponse_u AsyncRsp; _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; _SlDrvResetCmdExt(&ExtCtrl); ExtCtrl.TxPayloadLen = usNameLen; ExtCtrl.pTxPayload = (_u8 *)hostname; Msg.Cmd.Len = usNameLen; Msg.Cmd.family = family; /*Use Obj to issue the command, if not available try later */ ObjIdx = (_u8)_SlDrvWaitForPoolObj(GETHOSYBYNAME_ID,SL_MAX_SOCKETS); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } _SlDrvProtectionObjLockWaitForever(); g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&AsyncRsp; /*set bit to indicate IPv6 address is expected */ if (SL_AF_INET6 == family) { g_pCB->ObjPool[ObjIdx].AdditionalData |= SL_NETAPP_FAMILY_MASK; } _SlDrvProtectionObjUnLock(); VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetHostByNameCtrl, &Msg, &ExtCtrl)); if(SL_RET_CODE_OK == Msg.Rsp.status) { _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); Msg.Rsp.status = AsyncRsp.IpV4.status; if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) { sl_Memcpy((_i8 *)out_ip_addr, (_i8 *)&AsyncRsp.IpV4.ip0, (SL_AF_INET == family) ? SL_IPV4_ADDRESS_SIZE : SL_IPV6_ADDRESS_SIZE); } } _SlDrvReleasePoolObj(ObjIdx); return Msg.Rsp.status; } #endif /******************************************************************************/ /* _sl_HandleAsync_DnsGetHostByName */ /******************************************************************************/ void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf) { _GetHostByNameIPv4AsyncResponse_t *pMsgArgs = (_GetHostByNameIPv4AsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); _SlDrvProtectionObjLockWaitForever(); VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); /*IPv6 */ if(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) { sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_GetHostByNameIPv6AsyncResponse_t)); } /*IPv4 */ else { sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_GetHostByNameIPv4AsyncResponse_t)); } _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); _SlDrvProtectionObjUnLock(); return; } #ifndef SL_TINY_EXT void CopyPingResultsToReport(_PingReportResponse_t *pResults,SlPingReport_t *pReport) { pReport->PacketsSent = pResults->numSendsPings; pReport->PacketsReceived = pResults->numSuccsessPings; pReport->MinRoundTime = pResults->rttMin; pReport->MaxRoundTime = pResults->rttMax; pReport->AvgRoundTime = pResults->rttAvg; pReport->TestTime = pResults->testTime; } /*****************************************************************************/ /* _sl_HandleAsync_PingResponse */ /*****************************************************************************/ void _sl_HandleAsync_PingResponse(void *pVoidBuf) { _PingReportResponse_t *pMsgArgs = (_PingReportResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); SlPingReport_t pingReport; if(pPingCallBackFunc) { CopyPingResultsToReport(pMsgArgs,&pingReport); pPingCallBackFunc(&pingReport); } else { _SlDrvProtectionObjLockWaitForever(); VERIFY_SOCKET_CB(NULL != g_pCB->PingCB.PingAsync.pAsyncRsp); if (NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs) { sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_PingReportResponse_t)); _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); } _SlDrvProtectionObjUnLock(); } return; } #endif /*****************************************************************************/ /* sl_PingStart */ /*****************************************************************************/ typedef union { _PingStartCommand_t Cmd; _PingReportResponse_t Rsp; }_SlPingStartMsg_u; typedef enum { CMD_PING_TEST_RUNNING = 0, CMD_PING_TEST_STOPPED }_SlPingStatus_e; #if _SL_INCLUDE_FUNC(sl_NetAppPingStart) _i16 sl_NetAppPingStart(const SlPingStartCommand_t* pPingParams,const _u8 family,SlPingReport_t *pReport,const P_SL_DEV_PING_CALLBACK pPingCallback) { _SlCmdCtrl_t CmdCtrl = {0, sizeof(_PingStartCommand_t), sizeof(_BasicResponse_t)}; _SlPingStartMsg_u Msg; _PingReportResponse_t PingRsp; _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; if( 0 == pPingParams->Ip ) {/* stop any ongoing ping */ return _SlDrvBasicCmd(SL_OPCODE_NETAPP_PINGSTOP); } if(SL_AF_INET == family) { CmdCtrl.Opcode = SL_OPCODE_NETAPP_PINGSTART; sl_Memcpy(&Msg.Cmd.ip0, &pPingParams->Ip, SL_IPV4_ADDRESS_SIZE); } else { CmdCtrl.Opcode = SL_OPCODE_NETAPP_PINGSTART_V6; sl_Memcpy(&Msg.Cmd.ip0, &pPingParams->Ip, SL_IPV6_ADDRESS_SIZE); } Msg.Cmd.pingIntervalTime = pPingParams->PingIntervalTime; Msg.Cmd.PingSize = pPingParams->PingSize; Msg.Cmd.pingRequestTimeout = pPingParams->PingRequestTimeout; Msg.Cmd.totalNumberOfAttempts = pPingParams->TotalNumberOfAttempts; Msg.Cmd.flags = pPingParams->Flags; if( pPingCallback ) { pPingCallBackFunc = pPingCallback; } else { /*Use Obj to issue the command, if not available try later */ ObjIdx = (_u8)_SlDrvWaitForPoolObj(PING_ID,SL_MAX_SOCKETS); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER)); /* async response handler for non callback mode */ g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&PingRsp; pPingCallBackFunc = NULL; OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj)); } VERIFY_RET_OK(_SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); /*send the command*/ if(CMD_PING_TEST_RUNNING == (_i16)Msg.Rsp.status || CMD_PING_TEST_STOPPED == (_i16)Msg.Rsp.status ) { /* block waiting for results if no callback function is used */ if( NULL == pPingCallback ) { _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); if( SL_OS_RET_CODE_OK == (_i16)PingRsp.status ) { CopyPingResultsToReport(&PingRsp,pReport); } _SlDrvReleasePoolObj(ObjIdx); } } else { /* ping failure, no async response */ if( NULL == pPingCallback ) { _SlDrvReleasePoolObj(ObjIdx); } } return Msg.Rsp.status; } #endif /*****************************************************************************/ /* sl_NetAppSet */ /*****************************************************************************/ typedef union { _NetAppSetGet_t Cmd; _BasicResponse_t Rsp; }_SlNetAppMsgSet_u; #if _SL_INCLUDE_FUNC(sl_NetAppSet) const _SlCmdCtrl_t _SlNetAppSetCmdCtrl = { SL_OPCODE_NETAPP_NETAPPSET, sizeof(_NetAppSetGet_t), sizeof(_BasicResponse_t) }; _i32 sl_NetAppSet(const _u8 AppId ,const _u8 Option,const _u8 OptionLen,const _u8 *pOptionValue) { _SlNetAppMsgSet_u Msg; _SlCmdExt_t CmdExt; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = (OptionLen+3) & (~3); CmdExt.pTxPayload = (_u8 *)pOptionValue; Msg.Cmd.AppId = AppId; Msg.Cmd.ConfigLen = OptionLen; Msg.Cmd.ConfigOpt = Option; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppSetCmdCtrl, &Msg, &CmdExt)); return (_i16)Msg.Rsp.status; } #endif /*****************************************************************************/ /* sl_NetAppSendTokenValue */ /*****************************************************************************/ typedef union { sl_NetAppHttpServerSendToken_t Cmd; _BasicResponse_t Rsp; }_SlNetAppMsgSendTokenValue_u; #if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) const _SlCmdCtrl_t _SlNetAppSendTokenValueCmdCtrl = { SL_OPCODE_NETAPP_HTTPSENDTOKENVALUE, sizeof(sl_NetAppHttpServerSendToken_t), sizeof(_BasicResponse_t) }; _u16 _sl_NetAppSendTokenValue(slHttpServerData_t * Token_value) { _SlNetAppMsgSendTokenValue_u Msg; _SlCmdExt_t CmdExt; CmdExt.TxPayloadLen = (Token_value->value_len+3) & (~3); CmdExt.RxPayloadLen = 0; CmdExt.pTxPayload = (_u8 *) Token_value->token_value; CmdExt.pRxPayload = NULL; Msg.Cmd.token_value_len = Token_value->value_len; Msg.Cmd.token_name_len = Token_value->name_len; sl_Memcpy(&Msg.Cmd.token_name[0], Token_value->token_name, Token_value->name_len); VERIFY_RET_OK(_SlDrvCmdSend((_SlCmdCtrl_t *)&_SlNetAppSendTokenValueCmdCtrl, &Msg, &CmdExt)); return Msg.Rsp.status; } #endif /*****************************************************************************/ /* sl_NetAppGet */ /*****************************************************************************/ typedef union { _NetAppSetGet_t Cmd; _NetAppSetGet_t Rsp; }_SlNetAppMsgGet_u; #if _SL_INCLUDE_FUNC(sl_NetAppGet) const _SlCmdCtrl_t _SlNetAppGetCmdCtrl = { SL_OPCODE_NETAPP_NETAPPGET, sizeof(_NetAppSetGet_t), sizeof(_NetAppSetGet_t) }; _i32 sl_NetAppGet(const _u8 AppId,const _u8 Option,_u8 *pOptionLen, _u8 *pOptionValue) { _SlNetAppMsgGet_u Msg; _SlCmdExt_t CmdExt; if (*pOptionLen == 0) { return SL_EZEROLEN; } _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = *pOptionLen; CmdExt.pRxPayload = (_u8 *)pOptionValue; Msg.Cmd.AppId = AppId; Msg.Cmd.ConfigOpt = Option; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppGetCmdCtrl, &Msg, &CmdExt)); if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) { *pOptionLen = (_u8)CmdExt.RxPayloadLen; return SL_ESMALLBUF; } else { *pOptionLen = (_u8)CmdExt.ActualRxPayloadLen; } return (_i16)Msg.Rsp.Status; } #endif /*****************************************************************************/ /* _SlDrvNetAppEventHandler */ /*****************************************************************************/ void _SlDrvNetAppEventHandler(void* pArgs) { _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)pArgs; #if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) SlHttpServerEvent_t httpServerEvent; SlHttpServerResponse_t httpServerResponse; #endif switch(pHdr->GenHeader.Opcode) { case SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE: case SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE_V6: _sl_HandleAsync_DnsGetHostByName(pArgs); break; #ifndef SL_TINY_EXT case SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE: case SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE_V6: _sl_HandleAsync_DnsGetHostByService(pArgs); break; case SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE: _sl_HandleAsync_PingResponse(pArgs); break; #endif #if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) case SL_OPCODE_NETAPP_HTTPGETTOKENVALUE: { _u8 *pTokenName; slHttpServerData_t Token_value; sl_NetAppHttpServerGetToken_t *httpGetToken = (sl_NetAppHttpServerGetToken_t *)_SL_RESP_ARGS_START(pHdr); pTokenName = (_u8 *)((sl_NetAppHttpServerGetToken_t *)httpGetToken + 1); httpServerResponse.Response = SL_NETAPP_HTTPSETTOKENVALUE; httpServerResponse.ResponseData.token_value.len = MAX_TOKEN_VALUE_LEN; /* Reuse the async buffer for getting the token value response from the user */ httpServerResponse.ResponseData.token_value.data = (_u8 *)_SL_RESP_ARGS_START(pHdr) + MAX_TOKEN_NAME_LEN; httpServerEvent.Event = SL_NETAPP_HTTPGETTOKENVALUE_EVENT; httpServerEvent.EventData.httpTokenName.len = httpGetToken->token_name_len; httpServerEvent.EventData.httpTokenName.data = pTokenName; Token_value.token_name = pTokenName; _SlDrvHandleHttpServerEvents (&httpServerEvent, &httpServerResponse); Token_value.value_len = httpServerResponse.ResponseData.token_value.len; Token_value.name_len = httpServerEvent.EventData.httpTokenName.len; Token_value.token_value = httpServerResponse.ResponseData.token_value.data; _sl_NetAppSendTokenValue(&Token_value); } break; case SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE: { _u8 *pPostParams; sl_NetAppHttpServerPostToken_t *httpPostTokenArgs = (sl_NetAppHttpServerPostToken_t *)_SL_RESP_ARGS_START(pHdr); pPostParams = (_u8 *)((sl_NetAppHttpServerPostToken_t *)httpPostTokenArgs + 1); httpServerEvent.Event = SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT; httpServerEvent.EventData.httpPostData.action.len = httpPostTokenArgs->post_action_len; httpServerEvent.EventData.httpPostData.action.data = pPostParams; pPostParams+=httpPostTokenArgs->post_action_len; httpServerEvent.EventData.httpPostData.token_name.len = httpPostTokenArgs->token_name_len; httpServerEvent.EventData.httpPostData.token_name.data = pPostParams; pPostParams+=httpPostTokenArgs->token_name_len; httpServerEvent.EventData.httpPostData.token_value.len = httpPostTokenArgs->token_value_len; httpServerEvent.EventData.httpPostData.token_value.data = pPostParams; httpServerResponse.Response = SL_NETAPP_RESPONSE_NONE; _SlDrvHandleHttpServerEvents (&httpServerEvent, &httpServerResponse); } break; #endif default: SL_ERROR_TRACE2(MSG_305, "ASSERT: _SlDrvNetAppEventHandler : invalid opcode = 0x%x = %1", pHdr->GenHeader.Opcode, pHdr->GenHeader.Opcode); VERIFY_PROTOCOL(0); } } micropython-1.12/drivers/cc3100/src/netcfg.c000066400000000000000000000106501357706137100205740ustar00rootroot00000000000000/* * netcfg.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "driver.h" /*****************************************************************************/ /* sl_NetCfgSet */ /*****************************************************************************/ typedef union { _NetCfgSetGet_t Cmd; _BasicResponse_t Rsp; }_SlNetCfgMsgSet_u; #if _SL_INCLUDE_FUNC(sl_NetCfgSet) const _SlCmdCtrl_t _SlNetCfgSetCmdCtrl = { SL_OPCODE_DEVICE_NETCFG_SET_COMMAND, sizeof(_NetCfgSetGet_t), sizeof(_BasicResponse_t) }; _i32 sl_NetCfgSet(const _u8 ConfigId ,const _u8 ConfigOpt,const _u8 ConfigLen,const _u8 *pValues) { _SlNetCfgMsgSet_u Msg; _SlCmdExt_t CmdExt; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); CmdExt.pTxPayload = (_u8 *)pValues; Msg.Cmd.ConfigId = ConfigId; Msg.Cmd.ConfigLen = ConfigLen; Msg.Cmd.ConfigOpt = ConfigOpt; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetCfgSetCmdCtrl, &Msg, &CmdExt)); return (_i16)Msg.Rsp.status; } #endif /*****************************************************************************/ /* sl_NetCfgGet */ /*****************************************************************************/ typedef union { _NetCfgSetGet_t Cmd; _NetCfgSetGet_t Rsp; }_SlNetCfgMsgGet_u; #if _SL_INCLUDE_FUNC(sl_NetCfgGet) const _SlCmdCtrl_t _SlNetCfgGetCmdCtrl = { SL_OPCODE_DEVICE_NETCFG_GET_COMMAND, sizeof(_NetCfgSetGet_t), sizeof(_NetCfgSetGet_t) }; _i32 sl_NetCfgGet(const _u8 ConfigId, _u8 *pConfigOpt,_u8 *pConfigLen, _u8 *pValues) { _SlNetCfgMsgGet_u Msg; _SlCmdExt_t CmdExt; if (*pConfigLen == 0) { return SL_EZEROLEN; } _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = *pConfigLen; CmdExt.pRxPayload = (_u8 *)pValues; Msg.Cmd.ConfigLen = *pConfigLen; Msg.Cmd.ConfigId = ConfigId; if( pConfigOpt ) { Msg.Cmd.ConfigOpt = (_u16)*pConfigOpt; } VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetCfgGetCmdCtrl, &Msg, &CmdExt)); if( pConfigOpt ) { *pConfigOpt = (_u8)Msg.Rsp.ConfigOpt; } if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) { *pConfigLen = (_u8)CmdExt.RxPayloadLen; if( SL_MAC_ADDRESS_GET == ConfigId ) { return SL_RET_CODE_OK; /* sp fix */ } else { return SL_ESMALLBUF; } } else { *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; } return (_i16)Msg.Rsp.Status; } #endif micropython-1.12/drivers/cc3100/src/nonos.c000066400000000000000000000105371357706137100204660ustar00rootroot00000000000000/* * nonos.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "driver.h" #ifndef SL_PLATFORM_MULTI_THREADED #include "nonos.h" #ifndef SL_TINY_EXT #define NONOS_MAX_SPAWN_ENTRIES 5 #else #define NONOS_MAX_SPAWN_ENTRIES 1 #endif typedef struct { _SlSpawnEntryFunc_t pEntry; void* pValue; }_SlNonOsSpawnEntry_t; typedef struct { _SlNonOsSpawnEntry_t SpawnEntries[NONOS_MAX_SPAWN_ENTRIES]; }_SlNonOsCB_t; _SlNonOsCB_t g__SlNonOsCB; _SlNonOsRetVal_t _SlNonOsSemSet(_SlNonOsSemObj_t* pSemObj , _SlNonOsSemObj_t Value) { *pSemObj = Value; return NONOS_RET_OK; } _SlNonOsRetVal_t _SlNonOsSemGet(_SlNonOsSemObj_t* pSyncObj, _SlNonOsSemObj_t WaitValue, _SlNonOsSemObj_t SetValue, _SlNonOsTime_t Timeout) { #ifdef _SlSyncWaitLoopCallback _SlNonOsTime_t timeOutRequest = Timeout; #endif while (Timeout>0) { if (WaitValue == *pSyncObj) { *pSyncObj = SetValue; break; } if (Timeout != NONOS_WAIT_FOREVER) { Timeout--; } _SlNonOsMainLoopTask(); #ifdef _SlSyncWaitLoopCallback if( (__NON_OS_SYNC_OBJ_SIGNAL_VALUE == WaitValue) && (timeOutRequest != NONOS_NO_WAIT) ) { if (WaitValue == *pSyncObj) { *pSyncObj = SetValue; break; } _SlSyncWaitLoopCallback(); } #endif } if (0 == Timeout) { return NONOS_RET_ERR; } else { return NONOS_RET_OK; } } _SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags) { _i8 i = 0; #ifndef SL_TINY_EXT for (i=0 ; ipEntry) { pE->pValue = pValue; pE->pEntry = pEntry; #ifndef SL_TINY_EXT break; #endif } } return NONOS_RET_OK; } _SlNonOsRetVal_t _SlNonOsMainLoopTask(void) { _i8 i=0; #ifndef SL_TINY_EXT for (i=0 ; ipEntry; if (NULL != pF) { if(RxIrqCnt != (g_pCB)->RxDoneCnt) { pF(0); /* (pValue) */ } pE->pEntry = NULL; pE->pValue = NULL; } } return NONOS_RET_OK; } #endif /*(SL_PLATFORM != SL_PLATFORM_NON_OS)*/ micropython-1.12/drivers/cc3100/src/socket.c000066400000000000000000001001301357706137100206070ustar00rootroot00000000000000/* * socket.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "driver.h" void _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u *pCmd); void _sl_HandleAsync_Connect(void *pVoidBuf); #ifndef SL_TINY_EXT void _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen); void _sl_HandleAsync_Accept(void *pVoidBuf); void _sl_HandleAsync_Select(void *pVoidBuf); #endif _u16 _sl_TruncatePayloadByProtocol(const _i16 pSd, const _u16 length); /*******************************************************************************/ /* Functions */ /*******************************************************************************/ /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */ /* is possible as _i32 as these parameters are in the same offset and size for these */ /* three families. */ #define SL_SOCKET_PAYLOAD_BASE (1350) const _u8 _SlPayloadByProtocolLUT[16] = { (1472 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 */ (1460 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 */ (1452 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 */ (1440 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 */ (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE */ (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE */ (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE */ (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE */ (1476 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER */ (1514 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET */ (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 */ (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 */ (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ (1440 - SL_SOCKET_PAYLOAD_BASE) /* Default */ }; /* ******************************************************************************/ /* _sl_BuildAddress */ /* ******************************************************************************/ void _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u *pCmd) { /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 is possible as long as these parameters are in the same offset and size for these three families. */ pCmd->IpV4.FamilyAndFlags = (addr->sa_family << 4) & 0xF0; pCmd->IpV4.port = ((SlSockAddrIn_t *)addr)->sin_port; if(SL_AF_INET == addr->sa_family) { pCmd->IpV4.address = ((SlSockAddrIn_t *)addr)->sin_addr.s_addr; } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) { sl_Memcpy( pCmd->IpV6EUI48.address,((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, 6); } #ifdef SL_SUPPORT_IPV6 else { sl_Memcpy(pCmd->IpV6.address, ((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, 16 ); } #endif } /***************************************************************************** _sl_TruncatePayloadByProtocol *****************************************************************************/ _u16 _sl_TruncatePayloadByProtocol(const _i16 sd, const _u16 length) { unsigned int maxLength; maxLength = SL_SOCKET_PAYLOAD_BASE + _SlPayloadByProtocolLUT[((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) >> 4)]; if( length > maxLength ) { return maxLength; } else { return length; } } /*******************************************************************************/ /* _sl_ParseAddress */ /*******************************************************************************/ #ifndef SL_TINY_EXT void _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen) { /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */ /* is possible as long as these parameters are in the same offset and size for these */ /* three families. */ addr->sa_family = pRsp->IpV4.family; ((SlSockAddrIn_t *)addr)->sin_port = pRsp->IpV4.port; *addrlen = (SL_AF_INET == addr->sa_family) ? sizeof(SlSockAddrIn_t) : sizeof(SlSockAddrIn6_t); if(SL_AF_INET == addr->sa_family) { ((SlSockAddrIn_t *)addr)->sin_addr.s_addr = pRsp->IpV4.address; } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) { sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, pRsp->IpV6EUI48.address, 6); } #ifdef SL_SUPPORT_IPV6 else { sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.address, 16); } #endif } #endif /*******************************************************************************/ /* sl_Socket */ /*******************************************************************************/ typedef union { _u32 Dummy; _SocketCommand_t Cmd; _SocketResponse_t Rsp; }_SlSockSocketMsg_u; #if _SL_INCLUDE_FUNC(sl_Socket) const _SlCmdCtrl_t _SlSockSocketCmdCtrl = { SL_OPCODE_SOCKET_SOCKET, sizeof(_SocketCommand_t), sizeof(_SocketResponse_t) }; _i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol) { _SlSockSocketMsg_u Msg; Msg.Cmd.Domain = (_u8)Domain; Msg.Cmd.Type = (_u8)Type; Msg.Cmd.Protocol = (_u8)Protocol; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL)); if( Msg.Rsp.statusOrLen < 0 ) { return( Msg.Rsp.statusOrLen ); } else { return (_i16)((_u8)Msg.Rsp.sd); } } #endif /*******************************************************************************/ /* sl_Close */ /*******************************************************************************/ typedef union { _CloseCommand_t Cmd; _SocketResponse_t Rsp; }_SlSockCloseMsg_u; #if _SL_INCLUDE_FUNC(sl_Close) const _SlCmdCtrl_t _SlSockCloseCmdCtrl = { SL_OPCODE_SOCKET_CLOSE, sizeof(_CloseCommand_t), sizeof(_SocketResponse_t) }; _i16 sl_Close(_i16 sd) { _SlSockCloseMsg_u Msg; Msg.Cmd.sd = (_u8)sd; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockCloseCmdCtrl, &Msg, NULL)); return Msg.Rsp.statusOrLen; } #endif /*******************************************************************************/ /* sl_Bind */ /*******************************************************************************/ typedef union { _SocketAddrCommand_u Cmd; _SocketResponse_t Rsp; }_SlSockBindMsg_u; #if _SL_INCLUDE_FUNC(sl_Bind) _i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen) { _SlSockBindMsg_u Msg; _SlCmdCtrl_t CmdCtrl = {0, 0, sizeof(_SocketResponse_t)}; switch(addr->sa_family) { case SL_AF_INET : CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); break; #ifndef SL_TINY_EXT case SL_AF_INET6_EUI_48: CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); break; #ifdef SL_SUPPORT_IPV6 case AF_INET6: CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); break; #endif #endif case SL_AF_RF : default: return SL_RET_CODE_INVALID_INPUT; } Msg.Cmd.IpV4.lenOrPadding = 0; Msg.Cmd.IpV4.sd = (_u8)sd; _sl_BuildAddress(addr, &Msg.Cmd); VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); return Msg.Rsp.statusOrLen; } #endif /*******************************************************************************/ /* sl_Sendto */ /*******************************************************************************/ typedef union { _SocketAddrCommand_u Cmd; /* no response for 'sendto' commands*/ }_SlSendtoMsg_u; #if _SL_INCLUDE_FUNC(sl_SendTo) _i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen) { _SlSendtoMsg_u Msg; _SlCmdCtrl_t CmdCtrl = {0, 0, 0}; _SlCmdExt_t CmdExt; _u16 ChunkLen; _i16 RetVal; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = (_u16)Len; CmdExt.pTxPayload = (_u8 *)pBuf; switch(to->sa_family) { case SL_AF_INET: CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); break; #ifndef SL_TINY_EXT case SL_AF_INET6_EUI_48: CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); break; #ifdef SL_SUPPORT_IPV6 case AF_INET6: CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); break; #endif #endif case SL_AF_RF: default: return SL_RET_CODE_INVALID_INPUT; } ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len); Msg.Cmd.IpV4.lenOrPadding = ChunkLen; CmdExt.TxPayloadLen = ChunkLen; Msg.Cmd.IpV4.sd = (_u8)sd; _sl_BuildAddress(to, &Msg.Cmd); Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F; do { RetVal = _SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt); if(SL_OS_RET_CODE_OK == RetVal) { CmdExt.pTxPayload += ChunkLen; ChunkLen = (_u16)((_u8 *)pBuf + Len - CmdExt.pTxPayload); ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen); CmdExt.TxPayloadLen = ChunkLen; Msg.Cmd.IpV4.lenOrPadding = ChunkLen; } else { return RetVal; } }while(ChunkLen > 0); return (_i16)Len; } #endif /*******************************************************************************/ /* sl_Recvfrom */ /*******************************************************************************/ typedef union { _sendRecvCommand_t Cmd; _SocketAddrResponse_u Rsp; }_SlRecvfromMsg_u; const _SlCmdCtrl_t _SlRecvfomCmdCtrl = { SL_OPCODE_SOCKET_RECVFROM, sizeof(_sendRecvCommand_t), sizeof(_SocketAddrResponse_u) }; #if _SL_INCLUDE_FUNC(sl_RecvFrom) _i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen) { _SlRecvfromMsg_u Msg; _SlCmdExt_t CmdExt; _i16 RetVal; _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = Len; CmdExt.pRxPayload = (_u8 *)buf; Msg.Cmd.sd = (_u8)sd; Msg.Cmd.StatusOrLen = Len; /* no size truncation in recv path */ CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen; Msg.Cmd.FamilyAndFlags = flags & 0x0F; if(sizeof(SlSockAddrIn_t) == *fromlen) { Msg.Cmd.FamilyAndFlags |= (SL_AF_INET << 4); } else if (sizeof(SlSockAddrIn6_t) == *fromlen) { Msg.Cmd.FamilyAndFlags |= (SL_AF_INET6 << 4); } else { return SL_RET_CODE_INVALID_INPUT; } RetVal = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt); if( RetVal != SL_OS_RET_CODE_OK ) { return RetVal; } RetVal = Msg.Rsp.IpV4.statusOrLen; if(RetVal >= 0) { VERIFY_PROTOCOL(sd == Msg.Rsp.IpV4.sd); #if 0 _sl_ParseAddress(&Msg.Rsp, from, fromlen); #else from->sa_family = Msg.Rsp.IpV4.family; if(SL_AF_INET == from->sa_family) { ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.port; ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.address; *fromlen = sizeof(SlSockAddrIn_t); } else if (SL_AF_INET6_EUI_48 == from->sa_family ) { ((SlSockAddrIn6_t *)from)->sin6_port = Msg.Rsp.IpV6EUI48.port; sl_Memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u8, Msg.Rsp.IpV6EUI48.address, 6); } #ifdef SL_SUPPORT_IPV6 else if(AF_INET6 == from->sa_family) { VERIFY_PROTOCOL(*fromlen >= sizeof(sockaddr_in6)); ((sockaddr_in6 *)from)->sin6_port = Msg.Rsp.IpV6.port; sl_Memcpy(((sockaddr_in6 *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.address, 16); *fromlen = sizeof(sockaddr_in6); } #endif #endif } return (_i16)RetVal; } #endif /*******************************************************************************/ /* sl_Connect */ /*******************************************************************************/ typedef union { _SocketAddrCommand_u Cmd; _SocketResponse_t Rsp; }_SlSockConnectMsg_u; #if _SL_INCLUDE_FUNC(sl_Connect) _i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen) { _SlSockConnectMsg_u Msg; _SlReturnVal_t RetVal; _SlCmdCtrl_t CmdCtrl = {0, 0, sizeof(_SocketResponse_t)}; _SocketResponse_t AsyncRsp; _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; switch(addr->sa_family) { case SL_AF_INET : CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); /* Do nothing - cmd already initialized to this type */ break; case SL_AF_INET6_EUI_48: CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); break; #ifdef SL_SUPPORT_IPV6 case AF_INET6: CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6; CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); break; #endif case SL_AF_RF: default: return SL_RET_CODE_INVALID_INPUT; } Msg.Cmd.IpV4.lenOrPadding = 0; Msg.Cmd.IpV4.sd = (_u8)sd; _sl_BuildAddress(addr, &Msg.Cmd); ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CONNECT_ID, sd & BSD_SOCKET_ID_MASK); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } /* send the command */ VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); VERIFY_PROTOCOL(Msg.Rsp.sd == sd) RetVal = Msg.Rsp.statusOrLen; if(SL_RET_CODE_OK == RetVal) { /* wait for async and get Data Read parameters */ _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); VERIFY_PROTOCOL(AsyncRsp.sd == sd); RetVal = AsyncRsp.statusOrLen; } _SlDrvReleasePoolObj(ObjIdx); return RetVal; } #endif /*******************************************************************************/ /* _sl_HandleAsync_Connect */ /*******************************************************************************/ void _sl_HandleAsync_Connect(void *pVoidBuf) { _SocketResponse_t *pMsgArgs = (_SocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); _SlDrvProtectionObjLockWaitForever(); VERIFY_PROTOCOL((pMsgArgs->sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS); VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->sd = pMsgArgs->sd; ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->statusOrLen = pMsgArgs->statusOrLen; _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); _SlDrvProtectionObjUnLock(); return; } /*******************************************************************************/ /* sl_Send */ /*******************************************************************************/ typedef union { _sendRecvCommand_t Cmd; /* no response for 'sendto' commands*/ }_SlSendMsg_u; const _SlCmdCtrl_t _SlSendCmdCtrl = { SL_OPCODE_SOCKET_SEND, sizeof(_sendRecvCommand_t), 0 }; #if _SL_INCLUDE_FUNC(sl_Send) _i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags) { _SlSendMsg_u Msg; _SlCmdExt_t CmdExt; _u16 ChunkLen; _i16 RetVal; _u32 tempVal; _u8 runSingleChunk = FALSE; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = Len; CmdExt.pTxPayload = (_u8 *)pBuf; /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */ if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER) { tempVal = flags; CmdExt.pRxPayload = (_u8 *)&tempVal; CmdExt.RxPayloadLen = -4; /* mark as Rx data to send */ runSingleChunk = TRUE; } else { CmdExt.pRxPayload = NULL; } ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len); CmdExt.TxPayloadLen = ChunkLen; Msg.Cmd.StatusOrLen = ChunkLen; Msg.Cmd.sd = (_u8)sd; Msg.Cmd.FamilyAndFlags |= flags & 0x0F; do { RetVal = _SlDrvDataWriteOp((_u8)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt); if(SL_OS_RET_CODE_OK == RetVal) { CmdExt.pTxPayload += ChunkLen; ChunkLen = (_u8 *)pBuf + Len - CmdExt.pTxPayload; ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen); CmdExt.TxPayloadLen = ChunkLen; Msg.Cmd.StatusOrLen = ChunkLen; } else { return RetVal; } }while((ChunkLen > 0) && (runSingleChunk==FALSE)); return (_i16)Len; } #endif /*******************************************************************************/ /* sl_Listen */ /*******************************************************************************/ typedef union { _ListenCommand_t Cmd; _BasicResponse_t Rsp; }_SlListenMsg_u; #if _SL_INCLUDE_FUNC(sl_Listen) const _SlCmdCtrl_t _SlListenCmdCtrl = { SL_OPCODE_SOCKET_LISTEN, sizeof(_ListenCommand_t), sizeof(_BasicResponse_t), }; _i16 sl_Listen(_i16 sd, _i16 backlog) { _SlListenMsg_u Msg; Msg.Cmd.sd = (_u8)sd; Msg.Cmd.backlog = (_u8)backlog; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL)); return (_i16)Msg.Rsp.status; } #endif /*******************************************************************************/ /* sl_Accept */ /*******************************************************************************/ typedef union { _AcceptCommand_t Cmd; _SocketResponse_t Rsp; }_SlSockAcceptMsg_u; #if _SL_INCLUDE_FUNC(sl_Accept) const _SlCmdCtrl_t _SlAcceptCmdCtrl = { SL_OPCODE_SOCKET_ACCEPT, sizeof(_AcceptCommand_t), sizeof(_BasicResponse_t), }; _i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen) { _SlSockAcceptMsg_u Msg; _SlReturnVal_t RetVal; _SocketAddrResponse_u AsyncRsp; _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; Msg.Cmd.sd = (_u8)sd; Msg.Cmd.family = (sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6; ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, ACCEPT_ID, sd & BSD_SOCKET_ID_MASK ); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } /* send the command */ VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL)); VERIFY_PROTOCOL(Msg.Rsp.sd == sd); RetVal = Msg.Rsp.statusOrLen; if(SL_OS_RET_CODE_OK == RetVal) { /* wait for async and get Data Read parameters */ _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); VERIFY_PROTOCOL(AsyncRsp.IpV4.sd == sd); RetVal = AsyncRsp.IpV4.statusOrLen; if( (NULL != addr) && (NULL != addrlen) ) { #if 0 /* Kept for backup */ _sl_ParseAddress(&AsyncRsp, addr, addrlen); #else addr->sa_family = AsyncRsp.IpV4.family; if(SL_AF_INET == addr->sa_family) { if( *addrlen == sizeof( SlSockAddrIn_t ) ) { ((SlSockAddrIn_t *)addr)->sin_port = AsyncRsp.IpV4.port; ((SlSockAddrIn_t *)addr)->sin_addr.s_addr = AsyncRsp.IpV4.address; } else { *addrlen = 0; } } else if (SL_AF_INET6_EUI_48 == addr->sa_family ) { if( *addrlen == sizeof( SlSockAddrIn6_t ) ) { ((SlSockAddrIn6_t *)addr)->sin6_port = AsyncRsp.IpV6EUI48.port ; /* will be called from here and from _sl_BuildAddress*/ sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, AsyncRsp.IpV6EUI48.address, 6); } else { *addrlen = 0; } } #ifdef SL_SUPPORT_IPV6 else { if( *addrlen == sizeof( sockaddr_in6 ) ) { ((sockaddr_in6 *)addr)->sin6_port = AsyncRsp.IpV6.port ; sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.address, 16); } else { *addrlen = 0; } } #endif #endif } } _SlDrvReleasePoolObj(ObjIdx); return (_i16)RetVal; } #endif /*******************************************************************************/ /* sl_Htonl */ /*******************************************************************************/ _u32 sl_Htonl( _u32 val ) { _u32 i = 1; _i8 *p = (_i8 *)&i; if (p[0] == 1) /* little endian */ { p[0] = ((_i8* )&val)[3]; p[1] = ((_i8* )&val)[2]; p[2] = ((_i8* )&val)[1]; p[3] = ((_i8* )&val)[0]; return i; } else /* big endian */ { return val; } } /*******************************************************************************/ /* sl_Htonl */ /*******************************************************************************/ _u16 sl_Htons( _u16 val ) { _i16 i = 1; _i8 *p = (_i8 *)&i; if (p[0] == 1) /* little endian */ { p[0] = ((_i8* )&val)[1]; p[1] = ((_i8* )&val)[0]; return i; } else /* big endian */ { return val; } } /*******************************************************************************/ /* _sl_HandleAsync_Accept */ /*******************************************************************************/ #ifndef SL_TINY_EXT void _sl_HandleAsync_Accept(void *pVoidBuf) { _SocketAddrResponse_u *pMsgArgs = (_SocketAddrResponse_u *)_SL_RESP_ARGS_START(pVoidBuf); _SlDrvProtectionObjLockWaitForever(); VERIFY_PROTOCOL(( pMsgArgs->IpV4.sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS); VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs,sizeof(_SocketAddrResponse_u)); _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); _SlDrvProtectionObjUnLock(); return; } /*******************************************************************************/ /* _sl_HandleAsync_Select */ /*******************************************************************************/ void _sl_HandleAsync_Select(void *pVoidBuf) { _SelectAsyncResponse_t *pMsgArgs = (_SelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); _SlDrvProtectionObjLockWaitForever(); VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_SelectAsyncResponse_t)); _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); _SlDrvProtectionObjUnLock(); return; } #endif /*******************************************************************************/ /* sl_Recv */ /*******************************************************************************/ typedef union { _sendRecvCommand_t Cmd; _SocketResponse_t Rsp; }_SlRecvMsg_u; #if _SL_INCLUDE_FUNC(sl_Recv) const _SlCmdCtrl_t _SlRecvCmdCtrl = { SL_OPCODE_SOCKET_RECV, sizeof(_sendRecvCommand_t), sizeof(_SocketResponse_t) }; _i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags) { _SlRecvMsg_u Msg; _SlCmdExt_t CmdExt; _SlReturnVal_t status; _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = Len; CmdExt.pRxPayload = (_u8 *)pBuf; Msg.Cmd.sd = (_u8)sd; Msg.Cmd.StatusOrLen = Len; /* no size truncation in recv path */ CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen; Msg.Cmd.FamilyAndFlags = flags & 0x0F; status = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt); if( status != SL_OS_RET_CODE_OK ) { return status; } /* if the Device side sends less than expected it is not the Driver's role */ /* the returned value could be smaller than the requested size */ return (_i16)Msg.Rsp.statusOrLen; } #endif /*******************************************************************************/ /* sl_SetSockOpt */ /*******************************************************************************/ typedef union { _setSockOptCommand_t Cmd; _SocketResponse_t Rsp; }_SlSetSockOptMsg_u; const _SlCmdCtrl_t _SlSetSockOptCmdCtrl = { SL_OPCODE_SOCKET_SETSOCKOPT, sizeof(_setSockOptCommand_t), sizeof(_SocketResponse_t) }; #if _SL_INCLUDE_FUNC(sl_SetSockOpt) _i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen) { _SlSetSockOptMsg_u Msg; _SlCmdExt_t CmdExt; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = optlen; CmdExt.pTxPayload = (_u8 *)optval; Msg.Cmd.sd = (_u8)sd; Msg.Cmd.level = (_u8)level; Msg.Cmd.optionLen = (_u8)optlen; Msg.Cmd.optionName = (_u8)optname; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt)); return (_i16)Msg.Rsp.statusOrLen; } #endif /*******************************************************************************/ /* sl_GetSockOpt */ /*******************************************************************************/ typedef union { _getSockOptCommand_t Cmd; _getSockOptResponse_t Rsp; }_SlGetSockOptMsg_u; #if _SL_INCLUDE_FUNC(sl_GetSockOpt) const _SlCmdCtrl_t _SlGetSockOptCmdCtrl = { SL_OPCODE_SOCKET_GETSOCKOPT, sizeof(_getSockOptCommand_t), sizeof(_getSockOptResponse_t) }; _i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen) { _SlGetSockOptMsg_u Msg; _SlCmdExt_t CmdExt; if (*optlen == 0) { return SL_EZEROLEN; } _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = *optlen; CmdExt.pRxPayload = optval; Msg.Cmd.sd = (_u8)sd; Msg.Cmd.level = (_u8)level; Msg.Cmd.optionLen = (_u8)(*optlen); Msg.Cmd.optionName = (_u8)optname; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt)); if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) { *optlen = Msg.Rsp.optionLen; return SL_ESMALLBUF; } else { *optlen = (_u8)CmdExt.ActualRxPayloadLen; } return (_i16)Msg.Rsp.status; } #endif /*******************************************************************************/ /* sl_Select */ /* ******************************************************************************/ typedef union { _SelectCommand_t Cmd; _BasicResponse_t Rsp; }_SlSelectMsg_u; #ifndef SL_TINY_EXT #if _SL_INCLUDE_FUNC(sl_Select) const _SlCmdCtrl_t _SlSelectCmdCtrl = { SL_OPCODE_SOCKET_SELECT, sizeof(_SelectCommand_t), sizeof(_BasicResponse_t) }; _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout) { _SlSelectMsg_u Msg; _SelectAsyncResponse_t AsyncRsp; _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; Msg.Cmd.nfds = (_u8)nfds; Msg.Cmd.readFdsCount = 0; Msg.Cmd.writeFdsCount = 0; Msg.Cmd.readFds = 0; Msg.Cmd.writeFds = 0; if( readsds ) { Msg.Cmd.readFds = (_u16)readsds->fd_array[0]; } if( writesds ) { Msg.Cmd.writeFds = (_u16)writesds->fd_array[0]; } if( NULL == timeout ) { Msg.Cmd.tv_sec = 0xffff; Msg.Cmd.tv_usec = 0xffff; } else { if( 0xffff <= timeout->tv_sec ) { Msg.Cmd.tv_sec = 0xffff; } else { Msg.Cmd.tv_sec = (_u16)timeout->tv_sec; } timeout->tv_usec = timeout->tv_usec >> 10; /* convert to milliseconds */ if( 0xffff <= timeout->tv_usec ) { Msg.Cmd.tv_usec = 0xffff; } else { Msg.Cmd.tv_usec = (_u16)timeout->tv_usec; } } /* Use Obj to issue the command, if not available try later */ ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS); if (MAX_CONCURRENT_ACTIONS == ObjIdx) { return SL_POOL_IS_EMPTY; } /* send the command */ VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL)); if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) { _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); Msg.Rsp.status = AsyncRsp.status; if( ((_i16)Msg.Rsp.status) >= 0 ) { if( readsds ) { readsds->fd_array[0] = AsyncRsp.readFds; } if( writesds ) { writesds->fd_array[0] = AsyncRsp.writeFds; } } } _SlDrvReleasePoolObj(ObjIdx); return (_i16)Msg.Rsp.status; } /* Select helper functions */ /*******************************************************************************/ /* SL_FD_SET */ /* ******************************************************************************/ void SL_FD_SET(_i16 fd, SlFdSet_t *fdset) { fdset->fd_array[0] |= (1<< (fd & BSD_SOCKET_ID_MASK)); } /*******************************************************************************/ /* SL_FD_CLR */ /*******************************************************************************/ void SL_FD_CLR(_i16 fd, SlFdSet_t *fdset) { fdset->fd_array[0] &= ~(1<< (fd & BSD_SOCKET_ID_MASK)); } /*******************************************************************************/ /* SL_FD_ISSET */ /*******************************************************************************/ _i16 SL_FD_ISSET(_i16 fd, SlFdSet_t *fdset) { if( fdset->fd_array[0] & (1<< (fd & BSD_SOCKET_ID_MASK)) ) { return 1; } return 0; } /*******************************************************************************/ /* SL_FD_ZERO */ /*******************************************************************************/ void SL_FD_ZERO(SlFdSet_t *fdset) { fdset->fd_array[0] = 0; } #endif #endif micropython-1.12/drivers/cc3100/src/spawn.c000066400000000000000000000147141357706137100204630ustar00rootroot00000000000000/* * spawn.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) #define _SL_MAX_INTERNAL_SPAWN_ENTRIES 10 typedef struct _SlInternalSpawnEntry_t { _SlSpawnEntryFunc_t pEntry; void* pValue; struct _SlInternalSpawnEntry_t* pNext; }_SlInternalSpawnEntry_t; typedef struct { _SlInternalSpawnEntry_t SpawnEntries[_SL_MAX_INTERNAL_SPAWN_ENTRIES]; _SlInternalSpawnEntry_t* pFree; _SlInternalSpawnEntry_t* pWaitForExe; _SlInternalSpawnEntry_t* pLastInWaitList; _SlSyncObj_t SyncObj; _SlLockObj_t LockObj; }_SlInternalSpawnCB_t; _SlInternalSpawnCB_t g_SlInternalSpawnCB; void _SlInternalSpawnTaskEntry() { _i16 i; _SlInternalSpawnEntry_t* pEntry; _u8 LastEntry; /* create and lock the locking object. lock in order to avoid race condition on the first creation */ sl_LockObjCreate(&g_SlInternalSpawnCB.LockObj,"SlSpawnProtect"); sl_LockObjLock(&g_SlInternalSpawnCB.LockObj,SL_OS_NO_WAIT); /* create and clear the sync object */ sl_SyncObjCreate(&g_SlInternalSpawnCB.SyncObj,"SlSpawnSync"); sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_NO_WAIT); g_SlInternalSpawnCB.pFree = &g_SlInternalSpawnCB.SpawnEntries[0]; g_SlInternalSpawnCB.pWaitForExe = NULL; g_SlInternalSpawnCB.pLastInWaitList = NULL; /* create the link list between the entries */ for (i=0 ; i<_SL_MAX_INTERNAL_SPAWN_ENTRIES - 1 ; i++) { g_SlInternalSpawnCB.SpawnEntries[i].pNext = &g_SlInternalSpawnCB.SpawnEntries[i+1]; g_SlInternalSpawnCB.SpawnEntries[i].pEntry = NULL; } g_SlInternalSpawnCB.SpawnEntries[i].pNext = NULL; _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); /* here we ready to execute entries */ while (TRUE) { sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_WAIT_FOREVER); /* go over all entries that already waiting for execution */ LastEntry = FALSE; do { /* get entry to execute */ _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); pEntry = g_SlInternalSpawnCB.pWaitForExe; if ( NULL == pEntry ) { _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); break; } g_SlInternalSpawnCB.pWaitForExe = pEntry->pNext; if (pEntry == g_SlInternalSpawnCB.pLastInWaitList) { g_SlInternalSpawnCB.pLastInWaitList = NULL; LastEntry = TRUE; } _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); /* pEntry could be null in case that the sync was already set by some of the entries during execution of earlier entry */ if (NULL != pEntry) { pEntry->pEntry(pEntry->pValue); /* free the entry */ _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); pEntry->pNext = g_SlInternalSpawnCB.pFree; g_SlInternalSpawnCB.pFree = pEntry; if (NULL != g_SlInternalSpawnCB.pWaitForExe) { /* new entry received meanwhile */ LastEntry = FALSE; } _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); } }while (!LastEntry); } } _i16 _SlInternalSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags) { _i16 Res = 0; _SlInternalSpawnEntry_t* pSpawnEntry; if (NULL == pEntry) { Res = -1; } else { _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); pSpawnEntry = g_SlInternalSpawnCB.pFree; g_SlInternalSpawnCB.pFree = pSpawnEntry->pNext; pSpawnEntry->pEntry = pEntry; pSpawnEntry->pValue = pValue; pSpawnEntry->pNext = NULL; if (NULL == g_SlInternalSpawnCB.pWaitForExe) { g_SlInternalSpawnCB.pWaitForExe = pSpawnEntry; g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry; } else { g_SlInternalSpawnCB.pLastInWaitList->pNext = pSpawnEntry; g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry; } _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); /* this sync is called after releasing the lock object to avoid unnecessary context switches */ _SlDrvSyncObjSignal(&g_SlInternalSpawnCB.SyncObj); } return Res; } #endif micropython-1.12/drivers/cc3100/src/wlan.c000066400000000000000000000723641357706137100203010ustar00rootroot00000000000000/* * wlan.c - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*****************************************************************************/ /* Include files */ /*****************************************************************************/ #include "simplelink.h" #include "protocol.h" #include "driver.h" /*****************************************************************************/ /* Macro declarations */ /*****************************************************************************/ #define MAX_SSID_LEN (32) #define MAX_KEY_LEN (63) #define MAX_USER_LEN (32) #define MAX_ANON_USER_LEN (32) #define MAX_SMART_CONFIG_KEY (16) /***************************************************************************** sl_WlanConnect *****************************************************************************/ typedef struct { _WlanConnectEapCommand_t Args; _i8 Strings[MAX_SSID_LEN + MAX_KEY_LEN + MAX_USER_LEN + MAX_ANON_USER_LEN]; }_WlanConnectCmd_t; typedef union { _WlanConnectCmd_t Cmd; _BasicResponse_t Rsp; }_SlWlanConnectMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanConnect) _i16 sl_WlanConnect(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams) { _SlWlanConnectMsg_u Msg; _SlCmdCtrl_t CmdCtrl; sl_Memset (&Msg, 0, sizeof(Msg)); CmdCtrl.TxDescLen = 0;/* init */ CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); /* verify SSID length */ VERIFY_PROTOCOL(NameLen <= MAX_SSID_LEN); /* verify SSID is not NULL */ if( NULL == pName ) { return SL_INVALPARAM; } /* update SSID length */ Msg.Cmd.Args.Common.SsidLen = (_u8)NameLen; /* Profile with no security */ /* Enterprise security profile */ if (NULL != pSecExtParams) { /* Update command opcode */ CmdCtrl.Opcode = SL_OPCODE_WLAN_WLANCONNECTEAPCOMMAND; CmdCtrl.TxDescLen += sizeof(_WlanConnectEapCommand_t); /* copy SSID */ sl_Memcpy(EAP_SSID_STRING(&Msg), pName, NameLen); CmdCtrl.TxDescLen += NameLen; /* Copy password if supplied */ if ((NULL != pSecParams) && (pSecParams->KeyLen > 0)) { /* update security type */ Msg.Cmd.Args.Common.SecType = pSecParams->Type; /* verify key length */ if (pSecParams->KeyLen > MAX_KEY_LEN) { return SL_INVALPARAM; } /* update key length */ Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; ARG_CHECK_PTR(pSecParams->Key); /* copy key */ sl_Memcpy(EAP_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); CmdCtrl.TxDescLen += pSecParams->KeyLen; } else { Msg.Cmd.Args.Common.PasswordLen = 0; } ARG_CHECK_PTR(pSecExtParams); /* Update Eap bitmask */ Msg.Cmd.Args.EapBitmask = pSecExtParams->EapMethod; /* Update Certificate file ID index - currently not supported */ Msg.Cmd.Args.CertIndex = pSecExtParams->CertIndex; /* verify user length */ if (pSecExtParams->UserLen > MAX_USER_LEN) { return SL_INVALPARAM; } Msg.Cmd.Args.UserLen = pSecExtParams->UserLen; /* copy user name (identity) */ if(pSecExtParams->UserLen > 0) { sl_Memcpy(EAP_USER_STRING(&Msg), pSecExtParams->User, pSecExtParams->UserLen); CmdCtrl.TxDescLen += pSecExtParams->UserLen; } /* verify Anonymous user length */ if (pSecExtParams->AnonUserLen > MAX_ANON_USER_LEN) { return SL_INVALPARAM; } Msg.Cmd.Args.AnonUserLen = pSecExtParams->AnonUserLen; /* copy Anonymous user */ if(pSecExtParams->AnonUserLen > 0) { sl_Memcpy(EAP_ANON_USER_STRING(&Msg), pSecExtParams->AnonUser, pSecExtParams->AnonUserLen); CmdCtrl.TxDescLen += pSecExtParams->AnonUserLen; } } /* Regular or open security profile */ else { /* Update command opcode */ CmdCtrl.Opcode = SL_OPCODE_WLAN_WLANCONNECTCOMMAND; CmdCtrl.TxDescLen += sizeof(_WlanConnectCommon_t); /* copy SSID */ sl_Memcpy(SSID_STRING(&Msg), pName, NameLen); CmdCtrl.TxDescLen += NameLen; /* Copy password if supplied */ if( NULL != pSecParams ) { /* update security type */ Msg.Cmd.Args.Common.SecType = pSecParams->Type; /* verify key length is valid */ if (pSecParams->KeyLen > MAX_KEY_LEN) { return SL_INVALPARAM; } /* update key length */ Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; CmdCtrl.TxDescLen += pSecParams->KeyLen; /* copy key (could be no key in case of WPS pin) */ if( NULL != pSecParams->Key ) { sl_Memcpy(PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); } } /* Profile with no security */ else { Msg.Cmd.Args.Common.PasswordLen = 0; Msg.Cmd.Args.Common.SecType = SL_SEC_TYPE_OPEN; } } /* If BSSID is not null, copy to buffer, otherwise set to 0 */ if(NULL != pMacAddr) { sl_Memcpy(Msg.Cmd.Args.Common.Bssid, pMacAddr, sizeof(Msg.Cmd.Args.Common.Bssid)); } else { _SlDrvMemZero(Msg.Cmd.Args.Common.Bssid, sizeof(Msg.Cmd.Args.Common.Bssid)); } VERIFY_RET_OK ( _SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); return (_i16)Msg.Rsp.status; } #endif /*******************************************************************************/ /* sl_Disconnect */ /* ******************************************************************************/ #if _SL_INCLUDE_FUNC(sl_WlanDisconnect) _i16 sl_WlanDisconnect(void) { return _SlDrvBasicCmd(SL_OPCODE_WLAN_WLANDISCONNECTCOMMAND); } #endif /******************************************************************************/ /* sl_PolicySet */ /******************************************************************************/ typedef union { _WlanPoliciySetGet_t Cmd; _BasicResponse_t Rsp; }_SlPolicyMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanPolicySet) const _SlCmdCtrl_t _SlPolicySetCmdCtrl = { SL_OPCODE_WLAN_POLICYSETCOMMAND, sizeof(_WlanPoliciySetGet_t), sizeof(_BasicResponse_t) }; _i16 sl_WlanPolicySet(const _u8 Type , const _u8 Policy, _u8 *pVal,const _u8 ValLen) { _SlPolicyMsg_u Msg; _SlCmdExt_t CmdExt; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = ValLen; CmdExt.pTxPayload = (_u8 *)pVal; Msg.Cmd.PolicyType = Type; Msg.Cmd.PolicyOption = Policy; Msg.Cmd.PolicyOptionLen = ValLen; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlPolicySetCmdCtrl, &Msg, &CmdExt)); return (_i16)Msg.Rsp.status; } #endif /******************************************************************************/ /* sl_PolicyGet */ /******************************************************************************/ typedef union { _WlanPoliciySetGet_t Cmd; _WlanPoliciySetGet_t Rsp; }_SlPolicyGetMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanPolicyGet) const _SlCmdCtrl_t _SlPolicyGetCmdCtrl = { SL_OPCODE_WLAN_POLICYGETCOMMAND, sizeof(_WlanPoliciySetGet_t), sizeof(_WlanPoliciySetGet_t) }; _i16 sl_WlanPolicyGet(const _u8 Type ,_u8 Policy,_u8 *pVal,_u8 *pValLen) { _SlPolicyGetMsg_u Msg; _SlCmdExt_t CmdExt; if (*pValLen == 0) { return SL_EZEROLEN; } _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = *pValLen; CmdExt.pRxPayload = pVal; Msg.Cmd.PolicyType = Type; Msg.Cmd.PolicyOption = Policy; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlPolicyGetCmdCtrl, &Msg, &CmdExt)); if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) { *pValLen = Msg.Rsp.PolicyOptionLen; return SL_ESMALLBUF; } else { /* no pointer valus, fill the results into _i8 */ *pValLen = (_u8)CmdExt.ActualRxPayloadLen; if( 0 == CmdExt.ActualRxPayloadLen ) { *pValLen = 1; pVal[0] = Msg.Rsp.PolicyOption; } } return (_i16)SL_OS_RET_CODE_OK; } #endif /*******************************************************************************/ /* sl_ProfileAdd */ /*******************************************************************************/ typedef struct { _WlanAddGetEapProfile_t Args; _i8 Strings[MAX_SSID_LEN + MAX_KEY_LEN + MAX_USER_LEN + MAX_ANON_USER_LEN]; }_SlProfileParams_t; typedef union { _SlProfileParams_t Cmd; _BasicResponse_t Rsp; }_SlProfileAddMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanProfileAdd) _i16 sl_WlanProfileAdd(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams,const _u32 Priority,const _u32 Options) { _SlProfileAddMsg_u Msg; _SlCmdCtrl_t CmdCtrl = {0}; CmdCtrl.TxDescLen = 0;/* init */ CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); /* update priority */ Msg.Cmd.Args.Common.Priority = (_u8)Priority; /* verify SSID is not NULL */ if( NULL == pName ) { return SL_INVALPARAM; } /* verify SSID length */ VERIFY_PROTOCOL(NameLen <= MAX_SSID_LEN); /* update SSID length */ Msg.Cmd.Args.Common.SsidLen = (_u8)NameLen; /* Enterprise security profile */ if (NULL != pSecExtParams) { /* Update command opcode */ CmdCtrl.Opcode = SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND; CmdCtrl.TxDescLen += sizeof(_WlanAddGetEapProfile_t); /* copy SSID */ sl_Memcpy(EAP_PROFILE_SSID_STRING(&Msg), pName, NameLen); CmdCtrl.TxDescLen += NameLen; /* Copy password if supplied */ if ((NULL != pSecParams) && (pSecParams->KeyLen > 0)) { /* update security type */ Msg.Cmd.Args.Common.SecType = pSecParams->Type; if( SL_SEC_TYPE_WEP == Msg.Cmd.Args.Common.SecType ) { Msg.Cmd.Args.Common.WepKeyId = 0; } /* verify key length */ if (pSecParams->KeyLen > MAX_KEY_LEN) { return SL_INVALPARAM; } VERIFY_PROTOCOL(pSecParams->KeyLen <= MAX_KEY_LEN); /* update key length */ Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; CmdCtrl.TxDescLen += pSecParams->KeyLen; ARG_CHECK_PTR(pSecParams->Key); /* copy key */ sl_Memcpy(EAP_PROFILE_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); } else { Msg.Cmd.Args.Common.PasswordLen = 0; } ARG_CHECK_PTR(pSecExtParams); /* Update Eap bitmask */ Msg.Cmd.Args.EapBitmask = pSecExtParams->EapMethod; /* Update Certificate file ID index - currently not supported */ Msg.Cmd.Args.CertIndex = pSecExtParams->CertIndex; /* verify user length */ if (pSecExtParams->UserLen > MAX_USER_LEN) { return SL_INVALPARAM; } Msg.Cmd.Args.UserLen = pSecExtParams->UserLen; /* copy user name (identity) */ if(pSecExtParams->UserLen > 0) { sl_Memcpy(EAP_PROFILE_USER_STRING(&Msg), pSecExtParams->User, pSecExtParams->UserLen); CmdCtrl.TxDescLen += pSecExtParams->UserLen; } /* verify Anonymous user length (for tunneled) */ if (pSecExtParams->AnonUserLen > MAX_ANON_USER_LEN) { return SL_INVALPARAM; } Msg.Cmd.Args.AnonUserLen = pSecExtParams->AnonUserLen; /* copy Anonymous user */ if(pSecExtParams->AnonUserLen > 0) { sl_Memcpy(EAP_PROFILE_ANON_USER_STRING(&Msg), pSecExtParams->AnonUser, pSecExtParams->AnonUserLen); CmdCtrl.TxDescLen += pSecExtParams->AnonUserLen; } } /* Regular or open security profile */ else { /* Update command opcode */ CmdCtrl.Opcode = SL_OPCODE_WLAN_PROFILEADDCOMMAND; /* update commnad length */ CmdCtrl.TxDescLen += sizeof(_WlanAddGetProfile_t); if (NULL != pName) { /* copy SSID */ sl_Memcpy(PROFILE_SSID_STRING(&Msg), pName, NameLen); CmdCtrl.TxDescLen += NameLen; } /* Copy password if supplied */ if( NULL != pSecParams ) { /* update security type */ Msg.Cmd.Args.Common.SecType = pSecParams->Type; if( SL_SEC_TYPE_WEP == Msg.Cmd.Args.Common.SecType ) { Msg.Cmd.Args.Common.WepKeyId = 0; } /* verify key length */ if (pSecParams->KeyLen > MAX_KEY_LEN) { return SL_INVALPARAM; } /* update key length */ Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; CmdCtrl.TxDescLen += pSecParams->KeyLen; /* copy key (could be no key in case of WPS pin) */ if( NULL != pSecParams->Key ) { sl_Memcpy(PROFILE_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); } } else { Msg.Cmd.Args.Common.SecType = SL_SEC_TYPE_OPEN; Msg.Cmd.Args.Common.PasswordLen = 0; } } /* If BSSID is not null, copy to buffer, otherwise set to 0 */ if(NULL != pMacAddr) { sl_Memcpy(Msg.Cmd.Args.Common.Bssid, pMacAddr, sizeof(Msg.Cmd.Args.Common.Bssid)); } else { _SlDrvMemZero(Msg.Cmd.Args.Common.Bssid, sizeof(Msg.Cmd.Args.Common.Bssid)); } VERIFY_RET_OK(_SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); return (_i16)Msg.Rsp.status; } #endif /*******************************************************************************/ /* sl_ProfileGet */ /*******************************************************************************/ typedef union { _WlanProfileDelGetCommand_t Cmd; _SlProfileParams_t Rsp; }_SlProfileGetMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanProfileGet) const _SlCmdCtrl_t _SlProfileGetCmdCtrl = { SL_OPCODE_WLAN_PROFILEGETCOMMAND, sizeof(_WlanProfileDelGetCommand_t), sizeof(_SlProfileParams_t) }; _i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAddr, SlSecParams_t* pSecParams, SlGetSecParamsExt_t* pEntParams, _u32 *pPriority) { _SlProfileGetMsg_u Msg; Msg.Cmd.index = (_u8)Index; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlProfileGetCmdCtrl, &Msg, NULL)); pSecParams->Type = Msg.Rsp.Args.Common.SecType; /* since password is not transferred in getprofile, password length should always be zero */ pSecParams->KeyLen = Msg.Rsp.Args.Common.PasswordLen; if (NULL != pEntParams) { pEntParams->UserLen = Msg.Rsp.Args.UserLen; /* copy user name */ if (pEntParams->UserLen > 0) { sl_Memcpy(pEntParams->User, EAP_PROFILE_USER_STRING(&Msg), pEntParams->UserLen); } pEntParams->AnonUserLen = Msg.Rsp.Args.AnonUserLen; /* copy anonymous user name */ if (pEntParams->AnonUserLen > 0) { sl_Memcpy(pEntParams->AnonUser, EAP_PROFILE_ANON_USER_STRING(&Msg), pEntParams->AnonUserLen); } } *pNameLen = Msg.Rsp.Args.Common.SsidLen; *pPriority = Msg.Rsp.Args.Common.Priority; if (NULL != Msg.Rsp.Args.Common.Bssid) { sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid)); } sl_Memcpy(pName, EAP_PROFILE_SSID_STRING(&Msg), *pNameLen); return (_i16)Msg.Rsp.Args.Common.SecType; } #endif /*******************************************************************************/ /* sl_ProfileDel */ /*******************************************************************************/ typedef union { _WlanProfileDelGetCommand_t Cmd; _BasicResponse_t Rsp; }_SlProfileDelMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanProfileDel) const _SlCmdCtrl_t _SlProfileDelCmdCtrl = { SL_OPCODE_WLAN_PROFILEDELCOMMAND, sizeof(_WlanProfileDelGetCommand_t), sizeof(_BasicResponse_t) }; _i16 sl_WlanProfileDel(const _i16 Index) { _SlProfileDelMsg_u Msg; Msg.Cmd.index = (_u8)Index; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlProfileDelCmdCtrl, &Msg, NULL)); return (_i16)Msg.Rsp.status; } #endif /******************************************************************************/ /* sl_WlanGetNetworkList */ /******************************************************************************/ typedef union { _WlanGetNetworkListCommand_t Cmd; _WlanGetNetworkListResponse_t Rsp; }_SlWlanGetNetworkListMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanGetNetworkList) const _SlCmdCtrl_t _SlWlanGetNetworkListCtrl = { SL_OPCODE_WLAN_SCANRESULTSGETCOMMAND, sizeof(_WlanGetNetworkListCommand_t), sizeof(_WlanGetNetworkListResponse_t) }; _i16 sl_WlanGetNetworkList(const _u8 Index,const _u8 Count, Sl_WlanNetworkEntry_t *pEntries) { _i16 retVal = 0; _SlWlanGetNetworkListMsg_u Msg; _SlCmdExt_t CmdExt; if (Count == 0) { return SL_EZEROLEN; } _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = sizeof(Sl_WlanNetworkEntry_t)*(Count); CmdExt.pRxPayload = (_u8 *)pEntries; Msg.Cmd.index = Index; Msg.Cmd.count = Count; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanGetNetworkListCtrl, &Msg, &CmdExt)); retVal = Msg.Rsp.status; return (_i16)retVal; } #endif /******************************************************************************/ /* RX filters message command response structures */ /******************************************************************************/ /* Set command */ typedef union { _WlanRxFilterAddCommand_t Cmd; _WlanRxFilterAddCommandReponse_t Rsp; }_SlrxFilterAddMsg_u; /* Set command */ typedef union _SlRxFilterSetMsg_u { _WlanRxFilterSetCommand_t Cmd; _WlanRxFilterSetCommandReponse_t Rsp; }_SlRxFilterSetMsg_u; /* Get command */ typedef union _SlRxFilterGetMsg_u { _WlanRxFilterGetCommand_t Cmd; _WlanRxFilterGetCommandReponse_t Rsp; }_SlRxFilterGetMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanRxFilterAdd) const _SlCmdCtrl_t _SlRxFilterAddtCmdCtrl = { SL_OPCODE_WLAN_WLANRXFILTERADDCOMMAND, sizeof(_WlanRxFilterAddCommand_t), sizeof(_WlanRxFilterAddCommandReponse_t) }; /***************************************************************************** RX filters *****************************************************************************/ SlrxFilterID_t sl_WlanRxFilterAdd( SlrxFilterRuleType_t RuleType, SlrxFilterFlags_t FilterFlags, const SlrxFilterRule_t* const Rule, const SlrxFilterTrigger_t* const Trigger, const SlrxFilterAction_t* const Action, SlrxFilterID_t* pFilterId) { _SlrxFilterAddMsg_u Msg; Msg.Cmd.RuleType = RuleType; /* filterId is zero */ Msg.Cmd.FilterId = 0; Msg.Cmd.FilterFlags = FilterFlags; sl_Memcpy( &(Msg.Cmd.Rule), Rule, sizeof(SlrxFilterRule_t) ); sl_Memcpy( &(Msg.Cmd.Trigger), Trigger, sizeof(SlrxFilterTrigger_t) ); sl_Memcpy( &(Msg.Cmd.Action), Action, sizeof(SlrxFilterAction_t) ); VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterAddtCmdCtrl, &Msg, NULL) ); *pFilterId = Msg.Rsp.FilterId; return (_i16)Msg.Rsp.Status; } #endif /*******************************************************************************/ /* RX filters */ /*******************************************************************************/ #if _SL_INCLUDE_FUNC(sl_WlanRxFilterSet) const _SlCmdCtrl_t _SlRxFilterSetCmdCtrl = { SL_OPCODE_WLAN_WLANRXFILTERSETCOMMAND, sizeof(_WlanRxFilterSetCommand_t), sizeof(_WlanRxFilterSetCommandReponse_t) }; _i16 sl_WlanRxFilterSet(const SLrxFilterOperation_t RxFilterOperation, const _u8* const pInputBuffer, _u16 InputbufferLength) { _SlRxFilterSetMsg_u Msg; _SlCmdExt_t CmdExt; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = InputbufferLength; CmdExt.pTxPayload = (_u8 *)pInputBuffer; Msg.Cmd.RxFilterOperation = RxFilterOperation; Msg.Cmd.InputBufferLength = InputbufferLength; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterSetCmdCtrl, &Msg, &CmdExt) ); return (_i16)Msg.Rsp.Status; } #endif /******************************************************************************/ /* RX filters */ /******************************************************************************/ #if _SL_INCLUDE_FUNC(sl_WlanRxFilterGet) const _SlCmdCtrl_t _SlRxFilterGetCmdCtrl = { SL_OPCODE_WLAN_WLANRXFILTERGETCOMMAND, sizeof(_WlanRxFilterGetCommand_t), sizeof(_WlanRxFilterGetCommandReponse_t) }; _i16 sl_WlanRxFilterGet(const SLrxFilterOperation_t RxFilterOperation, _u8* pOutputBuffer, _u16 OutputbufferLength) { _SlRxFilterGetMsg_u Msg; _SlCmdExt_t CmdExt; if (OutputbufferLength == 0) { return SL_EZEROLEN; } _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = OutputbufferLength; CmdExt.pRxPayload = (_u8 *)pOutputBuffer; Msg.Cmd.RxFilterOperation = RxFilterOperation; Msg.Cmd.OutputBufferLength = OutputbufferLength; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterGetCmdCtrl, &Msg, &CmdExt) ); if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) { return SL_ESMALLBUF; } return (_i16)Msg.Rsp.Status; } #endif /*******************************************************************************/ /* sl_WlanRxStatStart */ /*******************************************************************************/ #if _SL_INCLUDE_FUNC(sl_WlanRxStatStart) _i16 sl_WlanRxStatStart(void) { return _SlDrvBasicCmd(SL_OPCODE_WLAN_STARTRXSTATCOMMAND); } #endif #if _SL_INCLUDE_FUNC(sl_WlanRxStatStop) _i16 sl_WlanRxStatStop(void) { return _SlDrvBasicCmd(SL_OPCODE_WLAN_STOPRXSTATCOMMAND); } #endif #if _SL_INCLUDE_FUNC(sl_WlanRxStatGet) _i16 sl_WlanRxStatGet(SlGetRxStatResponse_t *pRxStat,const _u32 Flags) { _SlCmdCtrl_t CmdCtrl = {SL_OPCODE_WLAN_GETRXSTATCOMMAND, 0, sizeof(SlGetRxStatResponse_t)}; _SlDrvMemZero(pRxStat, sizeof(SlGetRxStatResponse_t)); VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, pRxStat, NULL)); return 0; } #endif /******************************************************************************/ /* sl_WlanSmartConfigStop */ /******************************************************************************/ #if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStop) _i16 sl_WlanSmartConfigStop(void) { return _SlDrvBasicCmd(SL_OPCODE_WLAN_SMART_CONFIG_STOP_COMMAND); } #endif /******************************************************************************/ /* sl_WlanSmartConfigStart */ /******************************************************************************/ typedef struct { _WlanSmartConfigStartCommand_t Args; _i8 Strings[3 * MAX_SMART_CONFIG_KEY]; /* public key + groupId1 key + groupId2 key */ }_SlSmartConfigStart_t; typedef union { _SlSmartConfigStart_t Cmd; _BasicResponse_t Rsp; }_SlSmartConfigStartMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStart) const _SlCmdCtrl_t _SlSmartConfigStartCmdCtrl = { SL_OPCODE_WLAN_SMART_CONFIG_START_COMMAND, sizeof(_SlSmartConfigStart_t), sizeof(_BasicResponse_t) }; _i16 sl_WlanSmartConfigStart( const _u32 groupIdBitmask, const _u8 cipher, const _u8 publicKeyLen, const _u8 group1KeyLen, const _u8 group2KeyLen, const _u8* pPublicKey, const _u8* pGroup1Key, const _u8* pGroup2Key) { _SlSmartConfigStartMsg_u Msg; Msg.Cmd.Args.groupIdBitmask = (_u8)groupIdBitmask; Msg.Cmd.Args.cipher = (_u8)cipher; Msg.Cmd.Args.publicKeyLen = (_u8)publicKeyLen; Msg.Cmd.Args.group1KeyLen = (_u8)group1KeyLen; Msg.Cmd.Args.group2KeyLen = (_u8)group2KeyLen; /* copy keys (if exist) after command (one after another) */ sl_Memcpy(SMART_CONFIG_START_PUBLIC_KEY_STRING(&Msg), pPublicKey, publicKeyLen); sl_Memcpy(SMART_CONFIG_START_GROUP1_KEY_STRING(&Msg), pGroup1Key, group1KeyLen); sl_Memcpy(SMART_CONFIG_START_GROUP2_KEY_STRING(&Msg), pGroup2Key, group2KeyLen); VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSmartConfigStartCmdCtrl , &Msg, NULL)); return (_i16)Msg.Rsp.status; } #endif /*******************************************************************************/ /* sl_WlanSetMode */ /*******************************************************************************/ typedef union { _WlanSetMode_t Cmd; _BasicResponse_t Rsp; }_SlwlanSetModeMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanSetMode) const _SlCmdCtrl_t _SlWlanSetModeCmdCtrl = { SL_OPCODE_WLAN_SET_MODE, sizeof(_WlanSetMode_t), sizeof(_BasicResponse_t) }; /* possible values are: WLAN_SET_STA_MODE = 1 WLAN_SET_AP_MODE = 2 WLAN_SET_P2P_MODE = 3 */ _i16 sl_WlanSetMode(const _u8 mode) { _SlwlanSetModeMsg_u Msg; Msg.Cmd.mode = mode; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanSetModeCmdCtrl , &Msg, NULL)); return (_i16)Msg.Rsp.status; } #endif /*******************************************************************************/ /* sl_WlanSet */ /* ******************************************************************************/ typedef union { _WlanCfgSetGet_t Cmd; _BasicResponse_t Rsp; }_SlWlanCfgSetMsg_u; #if _SL_INCLUDE_FUNC(sl_WlanSet) const _SlCmdCtrl_t _SlWlanCfgSetCmdCtrl = { SL_OPCODE_WLAN_CFG_SET, sizeof(_WlanCfgSetGet_t), sizeof(_BasicResponse_t) }; _i16 sl_WlanSet(const _u16 ConfigId ,const _u16 ConfigOpt,const _u16 ConfigLen,const _u8 *pValues) { _SlWlanCfgSetMsg_u Msg; _SlCmdExt_t CmdExt; _SlDrvResetCmdExt(&CmdExt); CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); CmdExt.pTxPayload = (_u8 *)pValues; Msg.Cmd.ConfigId = ConfigId; Msg.Cmd.ConfigLen = ConfigLen; Msg.Cmd.ConfigOpt = ConfigOpt; VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanCfgSetCmdCtrl, &Msg, &CmdExt)); return (_i16)Msg.Rsp.status; } #endif /******************************************************************************/ /* sl_WlanGet */ /******************************************************************************/ typedef union { _WlanCfgSetGet_t Cmd; _WlanCfgSetGet_t Rsp; }_SlWlanCfgMsgGet_u; #if _SL_INCLUDE_FUNC(sl_WlanGet) const _SlCmdCtrl_t _SlWlanCfgGetCmdCtrl = { SL_OPCODE_WLAN_CFG_GET, sizeof(_WlanCfgSetGet_t), sizeof(_WlanCfgSetGet_t) }; _i16 sl_WlanGet(const _u16 ConfigId, _u16 *pConfigOpt,_u16 *pConfigLen, _u8 *pValues) { _SlWlanCfgMsgGet_u Msg; _SlCmdExt_t CmdExt; if (*pConfigLen == 0) { return SL_EZEROLEN; } _SlDrvResetCmdExt(&CmdExt); CmdExt.RxPayloadLen = *pConfigLen; CmdExt.pRxPayload = (_u8 *)pValues; Msg.Cmd.ConfigId = ConfigId; if( pConfigOpt ) { Msg.Cmd.ConfigOpt = (_u16)*pConfigOpt; } VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanCfgGetCmdCtrl, &Msg, &CmdExt)); if( pConfigOpt ) { *pConfigOpt = (_u8)Msg.Rsp.ConfigOpt; } if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) { *pConfigLen = (_u8)CmdExt.RxPayloadLen; return SL_ESMALLBUF; } else { *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; } return (_i16)Msg.Rsp.Status; } #endif micropython-1.12/drivers/cyw43/000077500000000000000000000000001357706137100164515ustar00rootroot00000000000000micropython-1.12/drivers/cyw43/README.md000066400000000000000000000010701357706137100177260ustar00rootroot00000000000000CYW43xx WiFi SoC driver ======================= This is a driver for the CYW43xx WiFi SoC. There are four layers to the driver: 1. SDIO bus interface, provided by the host device/system. 2. Low-level CYW43xx interface, managing the bus, control messages, Ethernet frames and asynchronous events. Includes download of SoC firmware. The header file `cyw43_ll.h` defines the interface to this layer. 3. Mid-level CYW43xx control, to control and set WiFi parameters and manage events. See `cyw43_ctrl.c`. 4. TCP/IP bindings to lwIP. See `cyw43_lwip.c`. micropython-1.12/drivers/cyw43/cyw43.h000066400000000000000000000112631357706137100175760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_CYW43_H #define MICROPY_INCLUDED_STM32_CYW43_H #include "lwip/netif.h" #include "lwip/dhcp.h" #include "lib/netutils/dhcpserver.h" #include "drivers/cyw43/cyw43_ll.h" // For trace_flags #define CYW43_TRACE_ASYNC_EV (0x0001) #define CYW43_TRACE_ETH_TX (0x0002) #define CYW43_TRACE_ETH_RX (0x0004) #define CYW43_TRACE_ETH_FULL (0x0008) #define CYW43_TRACE_MAC (0x0010) // Return value of cyw43_wifi_link_status #define CYW43_LINK_DOWN (0) #define CYW43_LINK_JOIN (1) #define CYW43_LINK_NOIP (2) #define CYW43_LINK_UP (3) #define CYW43_LINK_FAIL (-1) #define CYW43_LINK_NONET (-2) #define CYW43_LINK_BADAUTH (-3) typedef struct _cyw43_t { cyw43_ll_t cyw43_ll; uint8_t itf_state; uint32_t trace_flags; // State for async events volatile uint32_t wifi_scan_state; uint32_t wifi_join_state; void *wifi_scan_env; int (*wifi_scan_cb)(void*, const cyw43_ev_scan_result_t*); // Pending things to do bool pend_disassoc; bool pend_rejoin; bool pend_rejoin_wpa; // AP settings uint8_t ap_channel; uint8_t ap_auth; uint8_t ap_ssid_len; uint8_t ap_key_len; uint8_t ap_ssid[32]; uint8_t ap_key[64]; // lwIP data struct netif netif[2]; struct dhcp dhcp_client; dhcp_server_t dhcp_server; } cyw43_t; extern cyw43_t cyw43_state; extern void (*cyw43_poll)(void); extern uint32_t cyw43_sleep; void cyw43_init(cyw43_t *self); void cyw43_deinit(cyw43_t *self); int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface); int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf); int cyw43_wifi_pm(cyw43_t *self, uint32_t pm); int cyw43_wifi_link_status(cyw43_t *self, int itf); void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up); int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]); int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*)); static inline bool cyw43_wifi_scan_active(cyw43_t *self) { return self->wifi_scan_state == 1; } int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel); int cyw43_wifi_leave(cyw43_t *self, int itf); static inline void cyw43_wifi_ap_get_ssid(cyw43_t *self, size_t *len, const uint8_t **buf) { *len = self->ap_ssid_len; *buf = self->ap_ssid; } static inline void cyw43_wifi_ap_set_channel(cyw43_t *self, uint32_t channel) { self->ap_channel = channel; } static inline void cyw43_wifi_ap_set_ssid(cyw43_t *self, size_t len, const uint8_t *buf) { self->ap_ssid_len = MIN(len, sizeof(self->ap_ssid)); memcpy(self->ap_ssid, buf, self->ap_ssid_len); } static inline void cyw43_wifi_ap_set_password(cyw43_t *self, size_t len, const uint8_t *buf) { self->ap_key_len = MIN(len, sizeof(self->ap_key)); memcpy(self->ap_key, buf, self->ap_key_len); } static inline void cyw43_wifi_ap_set_auth(cyw43_t *self, uint32_t auth) { self->ap_auth = auth; } void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs); void cyw43_tcpip_init(cyw43_t *self, int itf); void cyw43_tcpip_deinit(cyw43_t *self, int itf); void cyw43_tcpip_set_link_up(cyw43_t *self, int itf); void cyw43_tcpip_set_link_down(cyw43_t *self, int itf); int cyw43_tcpip_link_status(cyw43_t *self, int itf); #endif // MICROPY_INCLUDED_STM32_CYW43_H micropython-1.12/drivers/cyw43/cyw43_ctrl.c000066400000000000000000000425251357706137100206220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mphal.h" #include "drivers/cyw43/cyw43.h" #include "pendsv.h" #include "sdio.h" #define CYW_ENTER MICROPY_PY_LWIP_ENTER #define CYW_EXIT MICROPY_PY_LWIP_EXIT #ifdef pyb_pin_WL_HOST_WAKE #define USE_SDIOIT (0) #else #define USE_SDIOIT (1) #endif #define CYW43_SLEEP_MAX (50) #define WIFI_JOIN_STATE_ACTIVE (0x0001) #define WIFI_JOIN_STATE_FAIL (0x0002) #define WIFI_JOIN_STATE_NONET (0x0003) #define WIFI_JOIN_STATE_BADAUTH (0x0004) #define WIFI_JOIN_STATE_AUTH (0x0200) #define WIFI_JOIN_STATE_LINK (0x0400) #define WIFI_JOIN_STATE_KEYED (0x0800) #define WIFI_JOIN_STATE_ALL (0x0e01) cyw43_t cyw43_state; void (*cyw43_poll)(void); uint32_t cyw43_sleep; STATIC void cyw43_poll_func(void); STATIC void cyw43_wifi_ap_init(cyw43_t *self); STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up); static inline uint32_t cyw43_get_be16(const uint8_t *buf) { return buf[0] << 8 | buf[1]; } static inline uint32_t cyw43_get_be32(const uint8_t *buf) { return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; } static inline void cyw43_delay_ms(uint32_t ms) { mp_hal_delay_ms(ms); } /*******************************************************************************/ // Initialisation and polling void cyw43_init(cyw43_t *self) { #ifdef pyb_pin_WL_HOST_WAKE mp_hal_pin_config(pyb_pin_WL_HOST_WAKE, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); #endif mp_hal_pin_config(pyb_pin_WL_REG_ON, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); mp_hal_pin_low(pyb_pin_WL_REG_ON); #ifdef pyb_pin_WL_RFSW_VDD mp_hal_pin_config(pyb_pin_WL_RFSW_VDD, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power mp_hal_pin_low(pyb_pin_WL_RFSW_VDD); #endif cyw43_ll_init(&self->cyw43_ll, self); self->itf_state = 0; self->wifi_scan_state = 0; self->wifi_join_state = 0; self->pend_disassoc = false; self->pend_rejoin= false; self->pend_rejoin_wpa = false; self->ap_channel = 3; self->ap_ssid_len = 0; self->ap_key_len = 0; cyw43_poll = NULL; } void cyw43_deinit(cyw43_t *self) { CYW_ENTER cyw43_ll_bus_sleep(&self->cyw43_ll, true); cyw43_delay_ms(2); cyw43_tcpip_deinit(self, 0); cyw43_tcpip_deinit(self, 1); self->itf_state = 0; // Disable async polling SDMMC1->MASK &= ~SDMMC_MASK_SDIOITIE; cyw43_poll = NULL; #ifdef pyb_pin_WL_RFSW_VDD // Turn the RF-switch off mp_hal_pin_low(pyb_pin_WL_RFSW_VDD); #endif // Power down the WL chip and the SDIO bus mp_hal_pin_low(pyb_pin_WL_REG_ON); sdio_deinit(); CYW_EXIT } STATIC int cyw43_ensure_up(cyw43_t *self) { if (cyw43_poll != NULL) { cyw43_ll_bus_sleep(&self->cyw43_ll, false); return 0; } CYW_ENTER // Disable the netif if it was previously up cyw43_tcpip_deinit(self, CYW43_ITF_STA); cyw43_tcpip_deinit(self, CYW43_ITF_AP); self->itf_state = 0; // Reset and power up the WL chip mp_hal_pin_low(pyb_pin_WL_REG_ON); cyw43_delay_ms(20); mp_hal_pin_high(pyb_pin_WL_REG_ON); cyw43_delay_ms(50); // Initialise SDIO bus // IRQ priority only needs to be higher than CYW_ENTER/EXIT protection (PENDSV) sdio_init(NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0)); // Initialise the low-level driver uint8_t mac[6]; mp_hal_get_mac(MP_HAL_MAC_WLAN0, mac); int ret = cyw43_ll_bus_init(&self->cyw43_ll, mac); if (ret != 0) { CYW_EXIT return ret; } // Enable async events from low-level driver cyw43_sleep = CYW43_SLEEP_MAX; cyw43_poll = cyw43_poll_func; #if USE_SDIOIT SDMMC1->MASK |= SDMMC_MASK_SDIOITIE; #else extern void extint_set(const pin_obj_t *pin, uint32_t mode); extint_set(pyb_pin_WL_HOST_WAKE, GPIO_MODE_IT_FALLING); #endif CYW_EXIT return ret; } // This function must always be executed at the level where CYW_ENTER is effectively active STATIC void cyw43_poll_func(void) { if (cyw43_poll == NULL) { // Poll scheduled during deinit, just ignore it return; } cyw43_t *self = &cyw43_state; cyw43_ll_process_packets(&self->cyw43_ll); if (self->pend_disassoc) { self->pend_disassoc = false; cyw43_ll_ioctl(&self->cyw43_ll, CYW43_IOCTL_SET_DISASSOC, 0, NULL, CYW43_ITF_STA); } if (self->pend_rejoin_wpa) { self->pend_rejoin_wpa = false; cyw43_ll_wifi_set_wpa_auth(&self->cyw43_ll); } if (self->pend_rejoin) { self->pend_rejoin = false; cyw43_ll_wifi_rejoin(&self->cyw43_ll); self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; } if (cyw43_sleep == 0) { cyw43_ll_bus_sleep(&self->cyw43_ll, true); #if !USE_SDIOIT sdio_deinit(); // save power while WLAN bus sleeps #endif } #if USE_SDIOIT SDMMC1->MASK |= SDMMC_MASK_SDIOITIE; #endif } /*******************************************************************************/ // Callback interface to low-level driver int cyw43_cb_read_host_interrupt_pin(void *cb_data) { #ifdef pyb_pin_WL_HOST_WAKE return mp_hal_pin_read(pyb_pin_WL_HOST_WAKE); #else return mp_hal_pin_read(pyb_pin_WL_SDIO_1); #endif } void cyw43_cb_ensure_awake(void *cb_data) { cyw43_sleep = CYW43_SLEEP_MAX; #if !USE_SDIOIT if (__HAL_RCC_SDMMC1_IS_CLK_DISABLED()) { __HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral sdio_enable_high_speed_4bit(); } #endif } STATIC const char *cyw43_async_event_name_table[89] = { [0 ... 88] = NULL, [CYW43_EV_SET_SSID] = "SET_SSID", [CYW43_EV_JOIN] = "JOIN", [CYW43_EV_AUTH] = "AUTH", [CYW43_EV_DEAUTH_IND] = "DEAUTH_IND", [CYW43_EV_ASSOC] = "ASSOC", [CYW43_EV_DISASSOC] = "DISASSOC", [CYW43_EV_DISASSOC_IND] = "DISASSOC_IND", [CYW43_EV_LINK] = "LINK", [CYW43_EV_PSK_SUP] = "PSK_SUP", [CYW43_EV_ESCAN_RESULT] = "ESCAN_RESULT", [CYW43_EV_CSA_COMPLETE_IND] = "CSA_COMPLETE_IND", [CYW43_EV_ASSOC_REQ_IE] = "ASSOC_REQ_IE", [CYW43_EV_ASSOC_RESP_IE] = "ASSOC_RESP_IE", }; STATIC void cyw43_dump_async_event(const cyw43_async_event_t *ev) { printf("[% 8d] ASYNC(%04x,", mp_hal_ticks_ms(), (unsigned int)ev->flags ); if (ev->event_type < MP_ARRAY_SIZE(cyw43_async_event_name_table) && cyw43_async_event_name_table[ev->event_type] != NULL) { printf("%s", cyw43_async_event_name_table[ev->event_type]); } else { printf("%u", (unsigned int)ev->event_type); } printf(",%u,%u,%u)\n", (unsigned int)ev->status, (unsigned int)ev->reason, (unsigned int)ev->interface ); } void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev) { cyw43_t *self = cb_data; if (self->trace_flags & CYW43_TRACE_ASYNC_EV) { cyw43_dump_async_event(ev); } if (ev->event_type == CYW43_EV_ESCAN_RESULT && self->wifi_scan_state == 1) { // Escan result event if (ev->status == 8) { // Partial result int ret = self->wifi_scan_cb(self->wifi_scan_env, &ev->u.scan_result); if (ret != 0) { // TODO need to abort scan, or just ignore any more results } } else if (ev->status == 0) { // Scan complete self->wifi_scan_state = 2; } } else if (ev->event_type == CYW43_EV_DISASSOC) { cyw43_tcpip_set_link_down(self, CYW43_ITF_STA); self->wifi_join_state = 0x0000; /* } else if (ev->event_type == CYW43_EV_DISASSOC_IND) { if (ev->interface == CYW43_ITF_AP) { // Station disassociated with our AP, let DHCP server know so it can free the IP address dhcp_server_disassoc(&self->dhcp_server, buf + 24); } */ // WiFi join events } else if (ev->event_type == CYW43_EV_PRUNE) { if (ev->status == 0 && ev->reason == 8) { // RSN mismatch, retry join with WPA auth self->pend_rejoin = true; self->pend_rejoin_wpa = true; pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); } } else if (ev->event_type == CYW43_EV_SET_SSID) { if (ev->status == 0) { // Success setting SSID } else if (ev->status == 3 && ev->reason == 0) { self->wifi_join_state = WIFI_JOIN_STATE_NONET; // No matching SSID found (could be out of range, or down) } else { // Other failure setting SSID self->wifi_join_state = WIFI_JOIN_STATE_FAIL; } } else if (ev->event_type == CYW43_EV_AUTH) { if (ev->status == 0) { self->wifi_join_state |= WIFI_JOIN_STATE_AUTH; } else if (ev->status == 6) { // Unsolicited auth packet, ignore it } else { // Cannot authenticate self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH; } } else if (ev->event_type == CYW43_EV_DEAUTH_IND) { if (ev->status == 0 && ev->reason == 2) { // Deauth, probably because password was wrong; disassociate self->pend_disassoc = true; pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); } } else if (ev->event_type == CYW43_EV_LINK) { if (ev->status == 0) { if (ev->flags & 1) { // Link is up if (ev->interface == CYW43_ITF_STA) { self->wifi_join_state |= WIFI_JOIN_STATE_LINK; } else { cyw43_tcpip_set_link_up(self, ev->interface); } } else { // Link is down cyw43_tcpip_set_link_down(self, ev->interface); } } } else if (ev->event_type == CYW43_EV_PSK_SUP) { if (ev->status == 6) { // WLC_SUP_KEYED self->wifi_join_state |= WIFI_JOIN_STATE_KEYED; } else if ((ev->status == 4 || ev->status == 8 || ev->status == 11) && ev->reason == 15) { // Timeout waiting for key exchange M1/M3/G1 // Probably at edge of the cell, retry self->pend_rejoin = true; pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); } else { // PSK_SUP failure self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH; } } if (self->wifi_join_state == WIFI_JOIN_STATE_ALL) { // STA connected self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; cyw43_tcpip_set_link_up(self, CYW43_ITF_STA); } } /*******************************************************************************/ // Ioctl and Ethernet interface int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) { int ret = cyw43_ensure_up(self); if (ret) { return ret; } CYW_ENTER ret = cyw43_ll_ioctl(&self->cyw43_ll, cmd, len, buf, iface); CYW_EXIT return ret; } int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf) { int ret = cyw43_ensure_up(self); if (ret) { return ret; } CYW_ENTER ret = cyw43_ll_send_ethernet(&self->cyw43_ll, itf, len, buf, is_pbuf); CYW_EXIT return ret; } /*******************************************************************************/ // WiFi control STATIC int cyw43_wifi_on(cyw43_t *self, uint32_t country) { int ret = cyw43_ensure_up(self); if (ret) { return ret; } #ifdef pyb_pin_WL_RFSW_VDD // Turn the RF-switch on mp_hal_pin_high(pyb_pin_WL_RFSW_VDD); #endif CYW_ENTER ret = cyw43_ll_wifi_on(&self->cyw43_ll, country); CYW_EXIT return ret; } int cyw43_wifi_pm(cyw43_t *self, uint32_t pm_in) { int ret = cyw43_ensure_up(self); if (ret) { return ret; } // pm_in: 0x00adbrrm uint32_t pm = pm_in & 0xf; uint32_t pm_sleep_ret = (pm_in >> 4) & 0xff; uint32_t li_bcn = (pm_in >> 12) & 0xf; uint32_t li_dtim = (pm_in >> 16) & 0xf; uint32_t li_assoc = (pm_in >> 20) & 0xf; CYW_ENTER ret = cyw43_ll_wifi_pm(&self->cyw43_ll, pm, pm_sleep_ret, li_bcn, li_dtim, li_assoc); CYW_EXIT return ret; } int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]) { mp_hal_get_mac(MP_HAL_MAC_WLAN0, &mac[0]); return 0; } #define MAKE_COUNTRY(a, b, rev) ((a) | (b) << 8 | (rev) << 16) void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up) { if (up) { if (self->itf_state == 0) { uint32_t country; extern char pyb_country_code[2]; if (pyb_country_code[0] == '\0' || pyb_country_code[1] == '\0') { country = MAKE_COUNTRY('X', 'X', 17); // default to world-wide (passive ch 12-14) } else { country = MAKE_COUNTRY(pyb_country_code[0], pyb_country_code[1], 0); } cyw43_wifi_on(self, country); cyw43_wifi_pm(self, 10 << 20 | 1 << 16 | 1 << 12 | 20 << 4 | 2); } if (itf == CYW43_ITF_AP) { cyw43_wifi_ap_init(self); cyw43_wifi_ap_set_up(self, true); } if ((self->itf_state & (1 << itf)) == 0) { CYW_ENTER cyw43_tcpip_deinit(self, itf); cyw43_tcpip_init(self, itf); self->itf_state |= 1 << itf; CYW_EXIT } } else { if (itf == CYW43_ITF_AP) { cyw43_wifi_ap_set_up(self, false); } } } int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*)) { if (self->itf_state == 0) { return -1; } cyw43_ensure_up(self); CYW_ENTER // Set state and callback data self->wifi_scan_state = 1; self->wifi_scan_env = env; self->wifi_scan_cb = result_cb; // Start the scan int ret = cyw43_ll_wifi_scan(&self->cyw43_ll, opts); CYW_EXIT return ret; } int cyw43_wifi_link_status(cyw43_t *self, int itf) { if (itf == CYW43_ITF_STA) { int s = self->wifi_join_state & 0xf; if (s == WIFI_JOIN_STATE_ACTIVE) { return CYW43_LINK_JOIN; } else if (s == WIFI_JOIN_STATE_FAIL) { return CYW43_LINK_FAIL; } else if (s == WIFI_JOIN_STATE_NONET) { return CYW43_LINK_NONET; } else if (s == WIFI_JOIN_STATE_BADAUTH) { return CYW43_LINK_BADAUTH; } else { return CYW43_LINK_DOWN; } } else { return CYW43_LINK_DOWN; } } /*******************************************************************************/ // WiFi STA int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel) { int ret = cyw43_ensure_up(self); if (ret) { return ret; } CYW_ENTER ret = cyw43_ll_wifi_join(&self->cyw43_ll, ssid_len, ssid, key_len, key, auth_type, bssid, channel); if (ret == 0) { // Wait for responses: EV_AUTH, EV_LINK, EV_SET_SSID, EV_PSK_SUP // Will get EV_DEAUTH_IND if password is invalid self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; if (auth_type == 0) { // For open security we don't need EV_PSK_SUP, so set that flag indicator now self->wifi_join_state |= WIFI_JOIN_STATE_KEYED; } } CYW_EXIT return ret; } int cyw43_wifi_leave(cyw43_t *self, int itf) { // Disassociate with SSID return cyw43_ioctl(self, CYW43_IOCTL_SET_DISASSOC, 0, NULL, itf); } /*******************************************************************************/ // WiFi AP STATIC void cyw43_wifi_ap_init(cyw43_t *self) { int ret = cyw43_ensure_up(self); if (ret) { return; } CYW_ENTER cyw43_ll_wifi_ap_init(&self->cyw43_ll, self->ap_ssid_len, self->ap_ssid, self->ap_auth, self->ap_key_len, self->ap_key, self->ap_channel); CYW_EXIT } STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up) { int ret = cyw43_ensure_up(self); if (ret) { return; } CYW_ENTER cyw43_ll_wifi_ap_set_up(&self->cyw43_ll, up); CYW_EXIT } void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs) { int ret = cyw43_ensure_up(self); if (ret) { return; } CYW_ENTER cyw43_ll_wifi_ap_get_stas(&self->cyw43_ll, num_stas, macs); CYW_EXIT } micropython-1.12/drivers/cyw43/cyw43_ll.h000066400000000000000000000120531357706137100202630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_CYW43_LL_H #define MICROPY_INCLUDED_STM32_CYW43_LL_H // IOCTL commands #define CYW43_IOCTL_GET_SSID (0x32) #define CYW43_IOCTL_GET_CHANNEL (0x3a) #define CYW43_IOCTL_SET_DISASSOC (0x69) #define CYW43_IOCTL_GET_ANTDIV (0x7e) #define CYW43_IOCTL_SET_ANTDIV (0x81) #define CYW43_IOCTL_SET_MONITOR (0xd9) #define CYW43_IOCTL_GET_VAR (0x20c) #define CYW43_IOCTL_SET_VAR (0x20f) // Async events, event_type field #define CYW43_EV_SET_SSID (0) #define CYW43_EV_JOIN (1) #define CYW43_EV_AUTH (3) #define CYW43_EV_DEAUTH_IND (6) #define CYW43_EV_ASSOC (7) #define CYW43_EV_DISASSOC (11) #define CYW43_EV_DISASSOC_IND (12) #define CYW43_EV_LINK (16) #define CYW43_EV_PRUNE (23) #define CYW43_EV_PSK_SUP (46) #define CYW43_EV_ESCAN_RESULT (69) #define CYW43_EV_CSA_COMPLETE_IND (80) #define CYW43_EV_ASSOC_REQ_IE (87) #define CYW43_EV_ASSOC_RESP_IE (88) enum { CYW43_ITF_STA, CYW43_ITF_AP, }; typedef struct _cyw43_ev_scan_result_t { uint32_t _0[5]; uint8_t bssid[6]; uint16_t _1[2]; uint8_t ssid_len; uint8_t ssid[32]; uint32_t _2[5]; uint16_t channel; uint16_t _3; uint8_t auth_mode; int16_t rssi; } cyw43_ev_scan_result_t; typedef struct _cyw43_async_event_t { uint16_t _0; uint16_t flags; uint32_t event_type; uint32_t status; uint32_t reason; uint8_t _1[30]; uint8_t interface; uint8_t _2; union { cyw43_ev_scan_result_t scan_result; } u; } cyw43_async_event_t; typedef struct _cyw43_wifi_scan_options_t { uint32_t version; uint16_t action; uint16_t _; uint32_t ssid_len; // 0 to select all uint8_t ssid[32]; uint8_t bssid[6]; int8_t bss_type; // fill with 0xff to select all int8_t scan_type; // 0=active, 1=passive int32_t nprobes; int32_t active_time; int32_t passive_time; int32_t home_time; int32_t channel_num; uint16_t channel_list[1]; } cyw43_wifi_scan_options_t; typedef struct _cyw43_ll_t { uint32_t opaque[528]; } cyw43_ll_t; void cyw43_ll_init(cyw43_ll_t *self, void *cb_data); void cyw43_ll_deinit(cyw43_ll_t *self); int cyw43_ll_bus_init(cyw43_ll_t *self, const uint8_t *mac); void cyw43_ll_bus_sleep(cyw43_ll_t *self, bool can_sleep); void cyw43_ll_process_packets(cyw43_ll_t *self); int cyw43_ll_ioctl(cyw43_ll_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface); int cyw43_ll_send_ethernet(cyw43_ll_t *self, int itf, size_t len, const void *buf, bool is_pbuf); int cyw43_ll_wifi_on(cyw43_ll_t *self, uint32_t country); int cyw43_ll_wifi_pm(cyw43_ll_t *self, uint32_t pm, uint32_t pm_sleep_ret, uint32_t li_bcn, uint32_t li_dtim, uint32_t li_assoc); int cyw43_ll_wifi_scan(cyw43_ll_t *self, cyw43_wifi_scan_options_t *opts); int cyw43_ll_wifi_join(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel); void cyw43_ll_wifi_set_wpa_auth(cyw43_ll_t *self); void cyw43_ll_wifi_rejoin(cyw43_ll_t *self); int cyw43_ll_wifi_ap_init(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, uint32_t auth, size_t key_len, const uint8_t *key, uint32_t channel); int cyw43_ll_wifi_ap_set_up(cyw43_ll_t *self, bool up); int cyw43_ll_wifi_ap_get_stas(cyw43_ll_t *self, int *num_stas, uint8_t *macs); // Callbacks to be provided by mid-level interface int cyw43_cb_read_host_interrupt_pin(void *cb_data); void cyw43_cb_ensure_awake(void *cb_data); void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev); void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf); #endif // MICROPY_INCLUDED_STM32_CYW43_LL_H micropython-1.12/drivers/cyw43/cyw43_lwip.c000066400000000000000000000152351357706137100206270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mphal.h" #include "lib/netutils/netutils.h" #include "lwip/etharp.h" #include "lwip/dns.h" #include "lwip/apps/mdns.h" #include "drivers/cyw43/cyw43.h" STATIC void cyw43_ethernet_trace(cyw43_t *self, struct netif *netif, size_t len, const void *data, unsigned int flags) { bool is_tx = flags & NETUTILS_TRACE_IS_TX; if ((is_tx && (self->trace_flags & CYW43_TRACE_ETH_TX)) || (!is_tx && (self->trace_flags & CYW43_TRACE_ETH_RX))) { const uint8_t *buf; if (len == (size_t)-1) { // data is a pbuf const struct pbuf *pbuf = data; buf = pbuf->payload; len = pbuf->len; // restricted to print only the first chunk of the pbuf } else { // data is actual data buffer buf = data; } if (self->trace_flags & CYW43_TRACE_MAC) { printf("[% 8d] ETH%cX itf=%c%c len=%u", mp_hal_ticks_ms(), is_tx ? 'T' : 'R', netif->name[0], netif->name[1], len); printf(" MAC type=%d subtype=%d data=", buf[0] >> 2 & 3, buf[0] >> 4); for (size_t i = 0; i < len; ++i) { printf(" %02x", buf[i]); } printf("\n"); return; } if (self->trace_flags & CYW43_TRACE_ETH_FULL) { flags |= NETUTILS_TRACE_PAYLOAD; } netutils_ethernet_trace(MP_PYTHON_PRINTER, len, buf, flags); } } STATIC err_t cyw43_netif_output(struct netif *netif, struct pbuf *p) { cyw43_t *self = netif->state; if (self->trace_flags != 0) { cyw43_ethernet_trace(self, netif, (size_t)-1, p, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE); } int itf = netif->name[1] - '0'; int ret = cyw43_send_ethernet(self, itf, p->tot_len, (void*)p, true); if (ret) { printf("[CYW43] send_ethernet failed: %d\n", ret); return ERR_IF; } return ERR_OK; } STATIC err_t cyw43_netif_init(struct netif *netif) { netif->linkoutput = cyw43_netif_output; netif->output = etharp_output; netif->mtu = 1500; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; cyw43_wifi_get_mac(netif->state, netif->name[1] - '0', netif->hwaddr); netif->hwaddr_len = sizeof(netif->hwaddr); return ERR_OK; } void cyw43_tcpip_init(cyw43_t *self, int itf) { ip_addr_t ipconfig[4]; #if LWIP_IPV6 #define IP(x) ((x).u_addr.ip4) #else #define IP(x) (x) #endif if (itf == 0) { // need to zero out to get isconnected() working IP4_ADDR(&IP(ipconfig[0]), 0, 0, 0, 0); IP4_ADDR(&IP(ipconfig[2]), 192, 168, 0, 1); } else { IP4_ADDR(&IP(ipconfig[0]), 192, 168, 4, 1); IP4_ADDR(&IP(ipconfig[2]), 192, 168, 4, 1); } IP4_ADDR(&IP(ipconfig[1]), 255, 255, 255, 0); IP4_ADDR(&IP(ipconfig[3]), 8, 8, 8, 8); #undef IP struct netif *n = &self->netif[itf]; n->name[0] = 'w'; n->name[1] = '0' + itf; #if LWIP_IPV6 netif_add(n, &ipconfig[0].u_addr.ip4, &ipconfig[1].u_addr.ip4, &ipconfig[2].u_addr.ip4, self, cyw43_netif_init, ethernet_input); #else netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, cyw43_netif_init, netif_input); #endif netif_set_hostname(n, "PYBD"); netif_set_default(n); netif_set_up(n); if (itf == CYW43_ITF_STA) { dns_setserver(0, &ipconfig[3]); dhcp_set_struct(n, &self->dhcp_client); dhcp_start(n); } else { dhcp_server_init(&self->dhcp_server, &ipconfig[0], &ipconfig[1]); } #if LWIP_MDNS_RESPONDER // TODO better to call after IP address is set char mdns_hostname[9]; memcpy(&mdns_hostname[0], "PYBD", 4); mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, &mdns_hostname[4]); mdns_hostname[8] = '\0'; mdns_resp_add_netif(n, mdns_hostname, 60); #endif } void cyw43_tcpip_deinit(cyw43_t *self, int itf) { struct netif *n = &self->netif[itf]; if (itf == CYW43_ITF_STA) { dhcp_stop(n); } else { dhcp_server_deinit(&self->dhcp_server); } #if LWIP_MDNS_RESPONDER mdns_resp_remove_netif(n); #endif for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { if (netif == n) { netif_remove(netif); netif->ip_addr.addr = 0; netif->flags = 0; } } } void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) { cyw43_t *self = cb_data; struct netif *netif = &self->netif[itf]; if (self->trace_flags) { cyw43_ethernet_trace(self, netif, len, buf, NETUTILS_TRACE_NEWLINE); } if (netif->flags & NETIF_FLAG_LINK_UP) { struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != NULL) { pbuf_take(p, buf, len); if (netif->input(p, netif) != ERR_OK) { pbuf_free(p); } } } } void cyw43_tcpip_set_link_up(cyw43_t *self, int itf) { netif_set_link_up(&self->netif[itf]); } void cyw43_tcpip_set_link_down(cyw43_t *self, int itf) { netif_set_link_down(&self->netif[itf]); } int cyw43_tcpip_link_status(cyw43_t *self, int itf) { struct netif *netif = &self->netif[itf]; if ((netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) { if (netif->ip_addr.addr != 0) { return CYW43_LINK_UP; } else { return CYW43_LINK_NOIP; } } else { return cyw43_wifi_link_status(self, itf); } } micropython-1.12/drivers/cyw43/cywbt.c000066400000000000000000000150221357706137100177450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/mphal.h" #include "pin_static_af.h" #include "uart.h" #include "cywbt.h" #include "nimble/hci_uart.h" #if MICROPY_PY_NETWORK_CYW43 extern const char fw_4343WA1_7_45_98_50_start; #define CYWBT_FW_ADDR (&fw_4343WA1_7_45_98_50_start + 749 * 512 + 29 * 256) /******************************************************************************/ // CYW BT HCI low-level driver static void cywbt_wait_cts_low(void) { mp_hal_pin_config(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); for (int i = 0; i < 200; ++i) { if (mp_hal_pin_read(pyb_pin_BT_CTS) == 0) { break; } mp_hal_delay_ms(1); } mp_hal_pin_config_alt_static(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_USART6_CTS); } static int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) { uart_tx_strn(&bt_hci_uart_obj, (void*)buf, len); for (int i = 0; i < 6; ++i) { while (!uart_rx_any(&bt_hci_uart_obj)) { MICROPY_EVENT_POLL_HOOK } buf[i] = uart_rx_char(&bt_hci_uart_obj); } // expect a comand complete event (event 0x0e) if (buf[0] != 0x04 || buf[1] != 0x0e) { printf("unknown response: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); return -1; } /* if buf[3:6] != cmd[:3]: print('response doesn\'t match cmd:', cmd, ev) return b'' */ int sz = buf[2] - 3; for (int i = 0; i < sz; ++i) { while (!uart_rx_any(&bt_hci_uart_obj)) { MICROPY_EVENT_POLL_HOOK } buf[i] = uart_rx_char(&bt_hci_uart_obj); } return 0; } static int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) { uint8_t *buf = bt_hci_cmd_buf; buf[0] = 0x01; buf[1] = ocf; buf[2] = ogf << 2 | ocf >> 8; buf[3] = param_len; if (param_len) { memcpy(buf + 4, param_buf, param_len); } return cywbt_hci_cmd_raw(4 + param_len, buf); } static void put_le16(uint8_t *buf, uint16_t val) { buf[0] = val; buf[1] = val >> 8; } static void put_le32(uint8_t *buf, uint32_t val) { buf[0] = val; buf[1] = val >> 8; buf[2] = val >> 16; buf[3] = val >> 24; } static int cywbt_set_baudrate(uint32_t baudrate) { uint8_t buf[6]; put_le16(buf, 0); put_le32(buf + 2, baudrate); return cywbt_hci_cmd(0x3f, 0x18, 6, buf); } // download firmware static int cywbt_download_firmware(const uint8_t *firmware) { cywbt_hci_cmd(0x3f, 0x2e, 0, NULL); bool last_packet = false; while (!last_packet) { uint8_t *buf = bt_hci_cmd_buf; memcpy(buf + 1, firmware, 3); firmware += 3; last_packet = buf[1] == 0x4e; if (buf[2] != 0xfc) { printf("fail1 %02x\n", buf[2]); break; } uint8_t len = buf[3]; memcpy(buf + 4, firmware, len); firmware += len; buf[0] = 1; cywbt_hci_cmd_raw(4 + len, buf); if (buf[0] != 0) { printf("fail3 %02x\n", buf[0]); break; } } // RF switch must select high path during BT patch boot mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); mp_hal_delay_ms(10); // give some time for CTS to go high cywbt_wait_cts_low(); mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_DOWN, 0); // Select chip antenna (could also select external) nimble_hci_uart_set_baudrate(115200); cywbt_set_baudrate(3000000); nimble_hci_uart_set_baudrate(3000000); return 0; } int cywbt_init(void) { // This is called from Nimble via hal_uart_config which will have already initialized the UART. mp_hal_pin_output(pyb_pin_BT_REG_ON); mp_hal_pin_low(pyb_pin_BT_REG_ON); mp_hal_pin_input(pyb_pin_BT_HOST_WAKE); mp_hal_pin_output(pyb_pin_BT_DEV_WAKE); mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // TODO don't select antenna if wifi is enabled mp_hal_pin_config(pyb_pin_WL_GPIO_4, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power mp_hal_pin_high(pyb_pin_WL_GPIO_4); // Turn the RF-switch on return 0; } int cywbt_activate(void) { uint8_t buf[256]; mp_hal_pin_low(pyb_pin_BT_REG_ON); nimble_hci_uart_set_baudrate(115200); mp_hal_delay_ms(100); mp_hal_pin_high(pyb_pin_BT_REG_ON); cywbt_wait_cts_low(); // Reset cywbt_hci_cmd(0x03, 0x0003, 0, NULL); // Change baudrate cywbt_set_baudrate(3000000); nimble_hci_uart_set_baudrate(3000000); cywbt_download_firmware((const uint8_t*)CYWBT_FW_ADDR); // Reset cywbt_hci_cmd(0x03, 0x0003, 0, NULL); // Set BD_ADDR (sent as little endian) uint8_t bdaddr[6]; mp_hal_get_mac(MP_HAL_MAC_BDADDR, bdaddr); buf[0] = bdaddr[5]; buf[1] = bdaddr[4]; buf[2] = bdaddr[3]; buf[3] = bdaddr[2]; buf[4] = bdaddr[1]; buf[5] = bdaddr[0]; cywbt_hci_cmd(0x3f, 0x0001, 6, buf); // Set local name // memset(buf, 0, 248); // memcpy(buf, "PYBD-BLE", 8); // cywbt_hci_cmd(0x03, 0x0013, 248, buf); // Configure sleep mode cywbt_hci_cmd(0x3f, 0x27, 12, (const uint8_t*)"\x01\x02\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00"); // HCI_Write_LE_Host_Support cywbt_hci_cmd(3, 109, 2, (const uint8_t*)"\x01\x00"); mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep return 0; } #endif micropython-1.12/drivers/cyw43/cywbt.h000066400000000000000000000027321357706137100177560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_DRIVERS_CYW43_CYWBT_H #define MICROPY_INCLUDED_DRIVERS_CYW43_CYWBT_H extern uint8_t bt_hci_cmd_buf[4 + 256]; extern pyb_uart_obj_t bt_hci_uart_obj; int cywbt_init(void); int cywbt_activate(void); #endif // MICROPY_INCLUDED_DRIVERS_CYW43_CYWBT_H micropython-1.12/drivers/cyw43/libcyw43.a000066400000000000000000015264421357706137100202710ustar00rootroot00000000000000! / 0 0 0 0 484 ` vvvvvvvvvvvvvvvv***cyw43_ll_initcyw43_ll_deinitcyw43_ll_send_ethernetcyw43_ll_process_packetscyw43_ll_ioctlcyw43_ll_bus_sleepcyw43_ll_bus_initcyw43_ll_wifi_oncyw43_ll_wifi_pmcyw43_ll_wifi_scancyw43_ll_wifi_joincyw43_ll_wifi_set_wpa_authcyw43_ll_wifi_rejoincyw43_ll_wifi_ap_initcyw43_ll_wifi_ap_set_upcyw43_ll_wifi_ap_get_stasfw_4343WA1_7_45_98_50_startfw_4343WA1_7_45_98_50_endfw_4343WA1_7_45_98_50_size// 18 ` cyw43_resource.o/ cyw43_ll_cm7.o/ 0 0 0 644 10240 ` ELF( &4( hpG pCp pppGpG8OztDCF@B800 -OD F FB,"C##FF E* + Ѵ0`> B O308Fh3C,:O lDF.DBظ ##CJ  HC 0   B +x0+ +"YF(FUDF@+𴋿 FOf&DB$@%FDr)FBr2CBbҲBr4 BA!AA]8!DhF$Bc@O" I +hc@" I +hc@O" I ,`8   -OFFFF)HsDғ #Ho "YF X  EOP  4L5$%I @FMEQF4 OK. 0FF(FOQ1 Fp F!#-CFFI "FI %'F@&PDAF4 ( ѝ(@B%/F B"FIF >!FHI>F#}# ##u8 KF L")Fd!F"!F(FHo8 @0dpF FNK F"-F#e)F()F" F[a#" F #)F FF)F F"F p@0@C}FFF Fc}c"bI F-"^I F"!F#7  Q cuh(O0#cuOsBLH +11!!"F #FC/b!CB^ )_` s(ؔ!pb{Ҳ*gs )P(,Bj(o + 1;1!!?)? iB>44F3`,`)8Dx2xCs3`*`)+Dx2{)#Q{l) | })Q});23`owotoqonokohoeobo _ ~-OF{FFFB{{B<8F)JFBٰF#"&I F  F(F F{b{#{BѦ ^E c{"{Hom0 O ! ! +Ck#{q!+q3q*j#sK#?@ @B-OF3FFoFi%$40Z@\@ < @$,A3 CC2F@<)F FbF HE3FBF9FHomiF FqFXB (2F(F( :F F0( h!B(FXF-G4FFFFFGFAF:F FQFs@!(FIi-G4FFFFFGFAF:F FQFhIF D#@!0FC @4FFFF(F#2F! FW+-C4FFFFFD:FIF("FAF(F#@!0FS #Or``sapGpG-AFFFop #(*0<#<! !@ 4! @$ &O)"I $9F C@ "I "I "! "! "! ! ! F2! F.! FL#"I F#"I Fz[FJ! F ~KO r~I F}K"}I Fg! F)"yI F(vH"uI FqHOzveO9F i@#"lI F=Ozv#"iI F5"gI ! OB@cI HaI² B"! "KI YI 3²VI Bsh F4S'W"AgA5BO HB V C66Of !#2F&dcda>6#@QF F&_OS/KBF ySKEB Fx!p#Orck$H""I Fp `>ϮHd V>ӮH@]w@D@|_48$ 4 \AY >H >H,#-AFF@!F48#iI FF#"gI F#"eI F#"cI F#aI FFch^JB 3sFBVJ<hccShs`F9 @#@0A0B0C0%FD'#@! Fe"!0FA0! F#A0D0#D0E0#@E0G0G04KhbcZhr`z2@r#e2 m^#)F4p:0#5P6"=0>6P7P8p9P;PP'?P@Pe0FFF0F)F"3 Fh0F 8HF(F~Pmanfid=0x2d0prodid=0x0726vendid=0x14e4devid=0x43e2boardtype=0x0726boardrev=0x1202boardnum=22macaddr=00:90:4c:c5:12:38sromrev=11boardflags=0x00404201boardflags3=0x08000000xtalfreq=37400nocrc=1ag0=0aa2g=1ccode=ALLextpagain2g=0pa2ga0=-145,6667,-751AvVmid_c0=0x0,0xc8cckpwroffset0=2maxp2ga0=74cckbw202gpo=0legofdmbw202gpo=0x88888888mcsbw202gpo=0xaaaaaaaapropbw202gpo=0xddofdmdigfilttype=18ofdmdigfilttypebe=18papdmode=1papdvalidtest=1pacalidx2g=48papdepsoffset=-22papdendidx=58il0macaddr=00:90:4c:c5:12:38wl0id=0x431bmuxenab=0x10swdiv_en=1swdiv_gpio=1clmloadclmload_statuscountrybssmaxassocVersion: [CYW43] could not find valid firmware[CYW43] SDIO cmd52 errorcyw43_kso_set(%d): failed [CYW43] core not in reset[CYW43] error: hdr mismatch %04x ^ %04x [CYW43] STALL(%u;%u-%u): timeout [CYW43] do_ioctl: got unexpected packet %d [CYW43] do_ioctl(%lu, %lu, %u): timeout [CYW43] got unexpected packet %d [CYW43] SDIO enumerate error[CYW43] SDIO select error[CYW43] no response from CYW43[CYW43] can't set block size[CYW43] timeout waiting for backplane[CYW43] core not up[CYW43] timeout waiting for ALP to be set[CYW43] HT not ready[CYW43] F2 not ready[CYW43] CLM load failedcur_etheraddrbus:txglomapstaampdu_ba_wsizeampdu_mpduampdu_rx_factorevent_msgsmcast_listpm2_sleep_retbcn_li_bcnbcn_li_dtimassoc_listenescanbsscfg:sup_wpabsscfg:sup_wpa2_eapverbsscfg:sup_wpa_tmojoinbsscfg:ssidbsscfg:wsecbsscfg:wpa_auth2g_mratebssGCC: (Arch Repository) 8.3.0A3aeabi)7E-M M  "(,t| (  x  L\Hdtx2@EMTj   Z u X8 G Z lh]4d #J9eQy$t$dmp_hal_ticks_usmemcmpsdio_transfer_cmd53sdio_transferputsstrncmpprintfcyw43_cb_ensure_awakecyw43_cb_read_host_interrupt_pincyw43_cb_process_async_eventmemcpymemmovecyw43_cb_process_ethernetstrlencyw43_ll_initcyw43_ll_deinitcyw43_ll_send_ethernetpbuf_copy_partialcyw43_ll_process_packetscyw43_ll_ioctlcyw43_ll_bus_sleepcyw43_ll_bus_initsdio_enable_high_speed_4bitfw_4343WA1_7_45_98_50_startcyw43_ll_wifi_onmemsetcyw43_ll_wifi_pmcyw43_ll_wifi_scancyw43_ll_wifi_joincyw43_ll_wifi_set_wpa_authcyw43_ll_wifi_rejoincyw43_ll_wifi_ap_initcyw43_ll_wifi_ap_set_upcyw43_ll_wifi_ap_get_stas 1& 1 2()t 4 5 6++ 4 5+n 4 7+ 8 7+ 9 7$+B 1T 1 : 7+P ;d 1r 1 7 < : = 7++ >  ;V >d ; > < ;P Bf ; : = 7 + 1 4 4" 4, 7@ 4 G 7 7 ;@ 7` 5x +| + + + ) + ) + + + + H )+ +b 1z 1 1 Jr J+++++)++L+P+T+X++ ;j ;v J ;+++++ J ; J ;H)L+P+T+\+`+t+ ;)\3.symtab.strtab.shstrtab.rel.text.data.bss.rodata.rodata.str1.1.comment.ARM.attributes4 @" %<+<0<82cG0'PpE4|0 1 k%`/0 0 0 0 644 426548 ` ELFa(l4(! HG!DBPPŐ<=743!52s3==Y2s272M<m2:%!!!a!##?'{'gcg_c1hWdhhgWM+͟ymaM+nnn5ɑnənc%M+Q'{|Y U[ }Ō!т{ǒ݁+}MGM+}|}| -ɔ+ËS||SNjWiM+M+)G;c-#M+]%)')$$(& ) (('$Y#U&M+QM+M+QM+M+M+M+M+#XM+M+M+Y_-_M+\^\^[E|g|k|w|M+MnCpKntM+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+$!1M+M+M+9JEJKM+M+M+M+M+AM+##$$%+-1911m445]7G:E<@EF)HJM+KKKL5MMMeMyNOPPPP}QQ R)TRQ7TTWUUViiiijQjej)ќ͟QYGY#]AլM+? ue]Q-K7Ssm&,7i;CKeTŤ'M+m-M [/"P?XKXYWYYYYYYZZ' P nn2Rܜ"@4TTVbڞ# ƚ;9{)tj4((wƟBМΝ$̙š R<<ŞMƞ3ܞ'ZџМrʚğ@v~BjLzNH}b4MיݙnFID8tǚU͛(_~3xce˞|&yS#D|:.x]՞;:Gf%CU4r ({0P|8p@$NHP6XB`xhƀphȀxLh69蓁TlqprHsty|~~ІЕ 영(08@HHXPxX`h%ph+x-2$A`-2=@4ORSkz䂃,`ȥh (ஃ08ı@(H0PXă`΃hDكpx@)-00EPCK?0łłȂab|c oЂ t(0"8Ȑ@HPܥX `قh݂pTxTHʆx$܆߆DąthFiAi iZFQFJFAFhhAhhiiHh)hFG!bpGrpGI@(I hC `pGI@(I hC@ `pGI h"XpG!I h"PpG!ݺJh`pG!VHWI" PhVJ @VO@?BPFB@FB)!AX h#@++11KK@KLBFFGLB hFL#@$@FFFAI!"BP7J@IX#BQh>KBh4K@jBF 9IXB8IX@B6KiBIF?Bј#X$@1KX$#@+@F.I`HF-I`PF-I``F,I`,I`,M-I `-H-I"B=FC#AB$ 'M,`kF&H&M(`,h`30<܁"KI h `lFFhF F*8 !!!!!8l\@<h"1@*J@Fh"1@*р"BJ@F0#\\BؓB 0O00 0*-OFMH@KKB \ @0B* D "B8(' "h`1311qq F[F  \T0BXFHpGlHpGHpGFh@h!FGHpG#@-O(O+8#0 5K"FFF'E"   B 9/ _EBF5FoFF FFAh);JFh1`/F FR) h*@9`)QYhQ`Z`"Fh)Zh ZP`[ H"hZ`h` Hh1`JhB`,(Lx8KP,hF`Kh:`PBFCh+U,Bh[hR2E,c`hBU,3`chC`D` 8Lx!@"F\K#`Kc`K`K`K#aKcaKaKaK#bKcbKbKbK#cKccKcKc58ll\\%%\-MhF)x)7 $"F !F "F$I$H'$K$p#+p"MM+h+3x*0П^ +hJىh4F0Kh;٣BK)hh" N1x $"F !FH I"F#+p#3p4؇דtXD ̇KhpG8 pG J Kh Jhh Jhzxn~t4 RJxL,tj3#b 00 p#N0h(@   3$Kh hB%ch hG$h ,KFh0h Kh@,M+h#hXh+h#h[h+ p@p8p@HdKh2`pGKhpG-O ^Fa   nN  D2hRRJDZD$ dLdO"hPcH:h  ~q~s3 1 ~r 2# YFKFUH3h h9h~p~s ~v~r03 26 HHcF ~r~s3 2 )F AH@KAOhAH9h@K hFFB>H% Fh9HBFB3h6H+F;h3H F3hY/H F-KhKx:Y݉85MC~s3(~s3#H3Fi#h [~p~r0 2 HWKhF)FF"FHJL, X(ؔKATSNstƕ<xF w Fv FMqFH @FFF&X% F jFP_)FFر)Fchg"c`: bO〧` F# p0K$h2` FP-AF Fs:& F jF`(ED@8B&-(F1FWF1Fs`ch=bc` eO F# p0K$h2` FP8!FF hh F8-AFFFF.*/(< !F󉿲[Lk5Fx!3p<"߲hchBDbc` gO㉢`C@ FDإc $ F#BhpÈSh2[ [K#@`É SÁ!0("@ߞ8FY!Ԣx:Ҳp*'xbK FS"P(F!F8@ K F`! F8@K F`!k F,F8ᆳKhS"@ F( N" F0h!!"F0h-Fd0h!a"~,FD-d8$0hAa"hD 50h)F"@]$ F8)KFh"QpG8F FF!)`3F3x * *h @"02*` "* с4_Zx+*;F3x) *,*"+D(h!F0(`4,+h"@# 7KhPxF;(h!hh- khh"FG FJH>|eЈF #`K!h0KhG8-GIKFbh+GKh #h*G:+@Jl"B bl3aclO2`9K:Nelhi2h8H ݣl!hcl"Fh3Hh'li#j.HcjO jFݣk,k&H#lFh#HiHyzY* KBbCH9Fg  7E3h CcGR8%8$H^Ɩ1h+FKh FD#h+Kh@˽8KhpGphl@pGp|1F+M0@jGعko`jGP`jG( ؔ A F FJw# 2p`j aG0 pІq92+ Бy1SJiKj@+OsFb pG-O(!F8F(@B1B= F o!8F(F@2!!&R7O(!*FPݸ ѫhjh#C#` +ݫh[yЇKhS"P-FF&8F!F(8F! !F(.@0hE1I hIDF(π:5-1F@F )F"@F}0C)F"0r `FjXJhFF Q" *ѭ0hy-PJJ C:A-"C !.F ! 2 "60Q6ɲ" C66"# ! !Zr!S[SC Y00F9"F8F!F()FRF8Ff 3 "`0 C" 0I@cC@s:A=" 18F 1)F<2F4ܔ131;  F!#h !hJ@#@ -C(!F8F( FԿOOO :@h)F0hB8FAF*F =h#q|1)F3r 1 1sr2`j32ry*K jG02xpxB 0   hq|!rPO 0h+8FAF[F(#00ci"Zd F !8F61B iCs!8F)1B iC\ІF1FB * Ѡh" 1%31( !!2F(b!(F( FI(F!F(Q--2- F61B F F+~!*@cu~1#=3`PlBkxB&FhADF(Qclh` иQFBFDFFfkhB8>F1FF8hAF"OQF2Fh*D/MFAFj`+` C`K h`hiG-AFL FFF;F!L"Oc{cOzsc#;d #{d# >`}``d8F-Oh h #F F lFl@zh ВE  Fo  F _&  ZE8Fbh{ [1J2B[`h 3`Kh R! 1"! JEإhah%B"`R6B"&@Y1FXDPh5]40!`"F# CF,FFd E,FFSPF{@ &F{khE8SFFbI hR `> &9࣊R#h"SVKx۱ ZE bJDB٣c "# "  #h F, o F, O7-;F,GFF(FZF)8KE ѻ@ 53F2F#F"Fh2`3F2F#F"F: C D(FJعWй[@E@ ER!J<0%FxjxC#*xxCCaF'j(F I"$F(0 J!hi)FZF >e(FBI"@K hi)F GFF1 pA  #%S  RF+F9F A# o oA!F" 4 .3F#F# 1!Fc4F @FQF;FNZF Fo %-Ah FFlh`h"C#`B0Ҵ 0FAD F0!F0F"$,F6É# CÁLC#Á|htlhBF!F0F",FࣉR`h "p$"pZp"p|p FFplhB-ӊhx- n.'ȉVx  0Cȁx@ȁxЎi&@6F@a- xtl `p" p)k ݂l*9BlS!0#FpGKhh[iGpFF@hFFhGF F1F*F^()F`hn KFh hh)FG0icia3caj3b p-O$FF'F&FZ2K hS"0  0xhQF\F(FIFF0hhQFsFF5hhQF2F/O hhQFdFF"j3bϱлE#3ikh1F:FG(j$3b'FFFF+i3+a s FF)**(Ёkk!ccZbSb@h!F"hg`( O0 BkBІl #lS 00*`QbBO0|pG;;%:;F: FA{ F@8-AFF$>ti5"))++H8HC888#88H#!FH )9 H H1F45p3Bӽk{З-AFEF FFِ0+E-?!|c|C#E6{{C"HB2H"X}}C#+%G-ٔ-0, Cc/ C. C#H3E . 8F0" ooHpGHpGKC pGKS CXB@pG#pFtF&j F)kG6|5B tppiF+hihG|>#cc|2F>*F 2Sh FhG5|Bc|ct pBhKJaFA`"h#3#X8FlDh"ci!FC`Kh#ca+;+ F8XFGmFH| F FFpfxf_gm Fm*F#G )F F5F(FF#}C|3#|# F@-CF F %0Fbx݁F FIF580FIF"1O5B%o|##| FT(FB<)(]0 +,F-,F&&jx0*Zxx*X*3"3" * x0(Xxx(X(3 " DB ^)+Fx5\D `O0 FF,x3D 0<W<7@ 6 B0s<#@ $J@BlV%`&dE B$`4F`5>5@B ` O0lFٱki @$@$ @n XoP"@2H@B Fl pn0:pGh# C CkhAd`Ckho`"`FFFF(Y)H ѳJ@"@]kB ,i`n4@4@$ @)iiP)@nIP)@ BL8@ JB&kIhHhH`kMl`%Q"A"PF29 @B(гFJ@H L"@9Y`Fᆳ pG*)))3@B&@Bб&@B@B pG pG pG pG pG pG pG pG2 pG pGFFnPp0BSд0B ѣk i@[@ 0BAco"S%`C% K1Fh"200OѴl05Z@pnPM*@;0!l*hK5`!l`l0pZ@nPM*@;0&>F0FXᆳްl0 FpG8FXxKFX!$j"!(FF(4!F8@8-AF% F!F(ZУhh0[3203 XB8F2HBز"RP ಁp//ݣh[ՠj1F""002B:FFB(*F/FF F!z(ѢhѠj1Ffh3`0F8H J0FB F8hԠj"N)F FFF(8-G#FFFJP FLCI h Q'pFH9  Ehb4гBOOC WCN CCBCS0C#+F FkF05;@H0B*;F+Y ԴF i: @kCCPF0hZl@A `JPРnakH`H m*@;c` j1F"#c`ciO03ca -O# h2  F O O ) ##0x ډ b!rOs2l p`nUq)@AB 0+ #O xxk+ ~I^x9YDj!Fp F0 #i3#ahЃh 2 @Ъh`co'pC&P`K)Fh:F20F+6ѴpPOC- =FOu l {:B BR BԿ3FJF F!ll06;@/DscoOBC& # GDl0 ;BOS AAC3FBF F!lRpl0@DP6- =FOu;@ $FboOAB&" l {:BOR BԿ,0 !l Fݴl06;@/##B RCFFWD$  E kp`^`<XHpGHpG` pGAxx# Cx@B-COFFFFEF# +ci F"+ iZ@'"F F!Ob;ci F"+ i[@'"F F!@$b%hCѝ(0KE# F+F9F2FC(Fh8@<BF(h +Oq@ +I#BI@CB M Mci F"+ iY@'"F F!@b`88CiF"+ i]@'"{F F F!Obh F|GxB 0+ F?OzpXC8pFF F`# K(#*h#\3* d#oB+`2`p-GFCiF""+FF i_@')F F F!Obp`#j F +ci"+ i^@'"F F!ObXh?  "+ iY@'"F F!ObAh? #@& FIFBFF"+B FIFBF%6. Fu&% 5F#@  FIFBFB8F5-Ѹ-AFFF(p,ci F"+ iZ@'"F F!@bciF"+ F i[@'"F F!@bhC3`/+ci F"+ i^@'"jF F!ObciF"+ F iY@'"UF F!ObhC7`Խ \@T1<ѽFCiF"+FF iZ@'"'F F F!O3Obci"+ i[ @' F"F F F!@Tb+FFCiF"+FF i[@'"F F F!O3Obci"+ iY @' F"F F F!@\b+FFCiF"+FF iY@'"F F F!O3Oblci"+ iZ @' F"F F F!@db+FTCi"+F i[ @'"OcF FOc F!Ob7-O:Ҳ*FF7K\7K\7K6K\6K5K\5K4K\%FFF/F.Fci"+ i[ @' F"EF F F!O3Obci"+iX @' F"* @F F @ F!@\bH  H F)F@ OENW`iԭ-CFF4!F F}ހF FF F#IFFBF;x F #0XCK1FEC Fb #?B8CiF"+ i]@'"F F F!@bcih"+ F iY@'"F F!@bhBci F"+ iZ@'"F F!@bh(F88FhF#`@8-C%FFFF(ci F"+ i[@'"[F F!ObڹhPE F9F2F-  m`-O&FFF%@FIFRFC#F@#@FIFRF 8D^DC#B(F F-CFCiF"+FF iZ@'"F F F!Ob?h F0ci"+ i[@'"F F!@b(h F01;`F(r1 F1F*Fci F"+ iZ@'"F F!ObciF"+ F i[@'"F F!ObhC;@3`ci F"+ i^@'"F F!@bciF"+ F iY@'"uF F!@bh@T@7` ~1pFF]!F F1FF F)FF F0FpK`pGLHOF:h*@Ci"+ i[@'F F F!@b2cih"+ F i^@'"F F!@bhBci F"+ iY@'"F F!@bhBpci F"+ iZ@'"F F!@bcih"+ F i[@'"F F!@bhBci F"+ i^@'"yF F!@bhud&uC=`8hL-OFFFFڃF(@ـ FYFF FciF-+ 0#sCs0 Fx&@𱀹^ci F"+ iY@'ZF,F F!ObthAF;`C# F;F*F ciC"+ F iZ@'" F F!ObSAF`*F FOzp@W  ci F"+ i[@'"F F!@ b/h3BB??:hci F"+ i_@'F F!Obh"# F;FAF*FciC7B &&"+ F iY@'"F F!ObAF`*F Fa&@- +iS?? FQFO𵉰F FOa)F FZOzv"F! F"FF! FOs;@ O B3F#wC-`OcOS # F FF F@pFFciF"+ F i[@'"F F!ObY#`d6Ozp۲hCppFFC!F F1FF F)FF F0Fp7FOajFF F"F F! @ ` F(F>pFF !F FT1FF F~ FciF"+ F iZ@'"F F!@ bx!h)FB && F*0FppG-Gn"F Fc!nB`nGFFF F!F FF F&;F F)FBFOci8C"+ F iY@'2FOF F!Ob`'3F F)FBF-ci0C"+ F iZ@':F-F F!@bu`)FBF F FQFn[ "nB`nIFG! pGFFFF#h3#`" Fޠ KhxzډB F Kh2`Kh2`tPT8F F"hh"G Kh+Fx!h9!`R#0+(F8@ FF#h3#`JFh Fxh4`P" *F JFh Fxh<`P" *F ~+@i8 pG pGpi%BFFhh2F#fPh[`#i]ci%a3cap pKhAhB ӁhBCi3CapG;CapGKpG\KpG-CF FFFݧnFo0 #nB`nGF' F!`0`h>h#`hC ` FAFn[ "nB`n9FG(F FF!"F@ FF!"F@ FF!"F@-AnFFFm0 nB@nGF% F݀FG F9F:F;F.O 3FF'O'O Fp F!O";Fp FAF;n[ "nB`n)FG0FpG! F FM pGpFر%(F9h@hG(5-$F0FB0F!"Fp@pKpKh2`pG|F Fm  @KxpG|F(7 Fnm0 #nB`nGF% FpFX&0Fh @hG6. F9Fn[ "nB`n)FG KhFBZhBFciJBѐi2B F   O@"8@ AFF3"F@ A(F,"F@ A(F%@(F@ AF $"(F@ AF<#F@ A@(F "F#F@ A(F"F#F@ A(F#F(F@ AO@"ONd!F#(FO24ܴVo87F@7F#@ At" F F!"J F!"E F!"@! F# FR#!@bO3 F#!@bO3 FA!@DBO3 FܔU0 FO^aO2 ### F@QO2# F@QO2z# F@QO2r# F@QO2j# FO]aO2b "# F@TA[(K! F@RO3$K! F@RO3 K! F@RO3w"F F@$a6@s!M F@RO3d! F@RO3[K#! F@RO3P FO\aO2+F0@ @ABCDEFGHIJK2Tv FII h@ hC$"@!p"#FFBi *))) ф"x"|"!#FO0-AF! F FF F! F FF F"F! FFx0 * (F8F2@BG FAF*F+FA(O0pGipGsF F) FH-Os# F!OrOslձ@V 1%+F F)FOr\>! FOr FP|8%p0Oa`*FFF81 F!(F8si%FPHOa*F`c(?ci"+ؿhQdQ`Qci"+KD1#H1#L1ci"+O1|1x1t1p11F FE F vߐci F"+ٿO! FI@"#HO0 |@UUsF FL` F!FjF }F@- 1= @-1Y= F!)0 F|F F 𵅰F FF (𔀦nn0 #nB`nGF& F!F ,(c/a'5@JU F!OrO3N! FOr FGO3 F!Or?! FOr FQ9% # F!# F)FOr"#&! FOr F8% ! FOr F-Ų! FOr F#@% F!Or#F%0 FWnk "nB`n1FGF(FCi-C"+FF@g@(.(FOa"̐F(.(F!O01#01#B01. # # #.01O01.#01.EO!OrCF(F(FO1RFh!OrCF(F;i(F!OrCF#!#Or(FI*F(F>(#!Or#(Fw؁#(F!Or#n01(F#pC0a01IF#01F$ Fsi[FOBF@tQ FI Fp F@TA"#? 8F/OaF" Fh#@<>)F#C#pCSC>#@memenfnf F8@JpGF"!F F F!"# F@-AFFFF8F1F*F#FA"OqFr-CF-KFh / FhS"F2{s{C#o ! /9"H"\(1!xZxB"OјB#yZy3B"@BѠ ( 08( ٿ3* +` O0o s"FF'p$1F" 4,  |h-O*O*O2FFXhAFFF@+h h0m2em "hYFJO HF/I" F-I FIF"( IF"##s "I"##u#cu##s#csDD1F" F#q#qIF"""YF"\1(h3\19Fh! b }}-CM+hF@h+ (d1+1 F 1F F F1 F'F1 F!/&&O O OONDFD1(6"2ˈhL1(3L1(@ .>A/G/ F2 +h F -@"1"0CI F V F k(p"1(h+hdP13P1W F S(X(hU F NGT13T1 .CBBBB;B$$BB1JO3+h0#"(F0 F2 B(F F ( F2 4 F ( X13X1  O0 T}-AF\2$\rfиY`G!Q "4 , O0O00#\<, DDD3B0o@#FFF0ı#v F w) DD3Bەqr 0 # ) D@D3Bە b0#00<3pAhPH@@-l i*U1`B1F PM 0  @OD 0#pCj| ,Y*Zi*TА3!*PА BL2ҲB F[i(1*ѐ41##04131+4Cj ||aCB2 !|BZhh(!,1# 1|@QCB ( !I(,I,2"|BJ-AFBF:F%F7ϴEOxFE8'5 F!@o$(F0F+F 3 + +J $+A%+B+C CjAEIFi-;"+7hhi B0bj(Ftcj0"|;SC831)1#Dh1hi BԿ ` `n o oooO00pFFF"!-4*F"1F@ FF(@1## 1C1 Fri+h! F e!*Q F! F Fu *O n! F F F@ F!"^#011 !B+q+є+є" **2!B"! 1 F!F 1(F$p-OiF O FF!lړWFikj+ дB0+fbj$F` ?*(h (+0O  "F(vЕ%0rkj#CCsZa#a 13 13iԔ1C1j3iCS3a+)󁫎s*hF+h3vFO2)h_a#bi3B!`858 #7#O#OFF +ci6XYci"ZQ50Bۤ F!O8FooooFFH1#F1hH1\hOzr@ZC# F!Hi+є21chhh! F2@]8Fi)T-@Cjh* 2B $} FmF(yV 11 +є1+є1+ ##+F1"cj !Xh!(h4!,a F^?<-:-h!h`hhh]!2a FF F F)F*F F)F*F FۄQQPPQQQQ%o(F8 pGEkF{+c+C#+ Fbjh`@0R|B3@0khckck..cj@+(gkU%8F1F"h765cj|B8F1F"#007065cj|Bkck `cc!cjac@ [|B F F9#Y -OFFF 4MF %kO,  < XFF@@0+ F)F*F5!ZF3#`+` Fc`JE##k`5F 4FO 3,"SC<3)FWFx(FU@0+e F9F:F9#O!#;` F'E`##{`BFGF1F Fn F)FZF.!#R#(F  F9F-"#S#8F0 0_`_OK8Fh F F!-1 - -#!" Fz" F!G#001111cj[|3ck# F!`k !!^#aci+h^cjFh3 F#acj[|+ck F!| )K@cjcд1; F!#1k F!# Fcjh2Д!**Д2Ҳ!hYhB љa F FS##1 Fi+ F!8@8-O FFF hVakF)0cj* _ F0+h \F")F$qj rF)F"BFqk,s 1++@ɀp0!:(€kyF^l0)F" (@_(е*0OCEhF+E0 F`P@0+ F F9#aޑ JF0rhh "p030131 "p030131!"psԔ131x*"ps Ԕ0;01;1p!hZx Ѐ Ե* BF 舀ռhBZphx**њ[B cjQ0 ZBBۙBp!h_6h.JF&F0[Ep!0 1+p0!](@ci)FS+`0FD(؀ F1F*FZ(Ѐ3iS#pcCs3a030131) bj F)FRF3i#pcCc3a#pcCs3a030131 #pcCc3aԔ131k0Fsr)F3iCS#S3a"c(F1F" 0(A2iF\Љ Ե* BFpr 鈈ռiBRqr2a2i"pbBb2a0;01;1),qzB#bjI QBBۓB* bj B"0F)FXksr3iCS#S3ap!0Bp!3i[  O F0ENF.McjYI 1+EѸ Bfh iCEBF6h./chm+ FAFSF A ch"s0`h301"310)Fchj߁ꈒZ{BZsc3cc1+HpG8|h`pGph D o}( (2LB.}((+Lc CC$ xزphEl@ u@,CA@ CTЉۉXB@ p p p݆ pGhF8#B=h!h0S0!@ FhL FAh#o hߠ`ho-Oi#iFB,O FhQF0FEbh>0s!2 yk"2KE08#!#&7FFF)Fb;KʊhS"0#˂chXiYF)F F:ch.0 FIFX)F (ch)FXi";ch>0+* F*F;F FhCS6+.F.F/F9FhRF ( F'>FOѠh)FRF (O)ch>0KGh9FRF (O@F -CChFh F#Ih^i"C#`[+.ش 0F F0!F0F",F,É# CÁ≡hLC#ÁhJF0k!F0F",Fࣉ:3`h!"pZpp:p F-GFiF$FF/D +F(*D"!f`'`^kh`bb JJOh0F*K$dh@F[h1FG( xqo9Fޠ`DF F F$4'88Fchh~˹AF FychY xKK"h F%(F8DJFJFJIhhKyHJmpG pG-OFF^x. x*@𥀢h'*0ڲ # pKx3Kp0O  ψO OW8?? "gFF" FFFRx,ID dhx  _ O)DOR;   B MEoѼEѸЗB 6@TFp0 2 (O x4۲BTF*F00["p02*F00 O0 FhF&F@c xF#@@F0[x+1F F*Fh F)9F!@F)ѐhpG) h pG-GFFF iNhuj 0 C *Hl  J P F9F٘ 0C#Oј 0C#bh. *3гo@B1 FIFF!h}FF@F9F(((Й0;0Kch9FXi"MFOO-@к i c}K F9F ch9FXiRF2ch0S9F& ch9FXiBF #9F= F|F0tchXis+iFh0F)F"FGH Fch9FXi*F%-Ah?F9FXhFFh:F1h 00F 0#0!#0j"Fb#A iHj(iiFFGsFFF@o\kh+.++4 +J!+ .++Cch!="ch!6" !2ch!-"ch!Q&h*#"x#u##B=h/yF`y#i%Nܳyh1F9B|pGChF~{ Uޠh)ch! F @!pGOppGh(8 ( h0l2hB(ђr2+I{|͍k``CC-CC," SkC ! B ӛB  0 0F0 0d)c)!J)))<)P)\9)))ڨ9) ܱq)opG pG pGȈopG5XpGHBH7 HB@pG pGC+jx pG+jxpG pGz+jx0  pG+jxpG pGȈpGȈpG|IQ@`P`R_в_ pG pG pG i%yh,x@p@ p1xHHB@pGFpG pG pGhHOrBZx x pG" `@rò вCs-òCs@rCHCBHC HC?C3?C3 @?C@3/C# ` pGopGph@fh6f`h`i4a ihFfi6fa ihiaikiH\H\Yh1Y`hR`pT‡hXkpK\J\3Zh2Z`h`pGT‡JhBL)h~+&!h~+#ТC~+!c""(Ճy+Ѓy+ o oooo oFoo Fn8 FF(h#fl0 F)FOr8@q-CF FFF̐E0EhBѣyհhh:FCFx$h,ѽ@h FFFYkBh|ӧBwZ[]+sSx+pѓx+mx(jy)jSy+`ш @!2H BZѧ].KhS"(QЃhb-Jx:Ҳ*EZx*BZ A"^*=y**)YyyB" '$n.ѭϹa`8&ԀyR e_.F&F&FF0FFF -CBF FFL=x8((F!F=[E(F*B>` 1bhKX H"  NE #} );`>` @-Ch+\}{(Xg{M|/|&{L6 (BDєcz z*9Аh*8}-5х{n{.+ѕnzO i6ND O )OhNDCD O ,cDNDB01"(F!F 8 F 0HhHM h H hdh    L F#F J90 Á-GFFFF F(qF F(F0(10[70[@C@LC 3Xhx1F F# FIFRF* FjF ЙD0!0b Ͳk-O@G'+F-H)F$ H)F($$$%EU=C\)FED)F\D)F(\DDD@\)FDRD  Fɇɇh1y+8  8F4h<h8%5t4h 5(F88 Fyyhcl2zB1x##hx07빔7ӱ7#hڪhR "##"7'78-AF/FFX I"X3y +P!F2F;FAWvD-AFF*%  F N D0@  t0 >#h~*:Гx0+6Д.2Ash ڄ.R&h#.20hOzr .2 FhQ)FF0F##.2p.2+pphF{+hF<0#TQ$(F1F"F;݀p-Ch FFFbO F1h(shBѳhEбFh. x0` 0FHFo-OQF# FFd FFFF6'R59F3F OrB72FRhFF $"ZDj9FF@2F[DFjO5 8 "h BFCFF+. #h0B*2[Dj'R5 ZF9F02F[Dj 5 8 %F0F#h0BF#h0Bo `F3+ SF# h [3CH9F"NF(Fѹo  k"AF  F  F3# F bFcF<=ڃFo FYF  FYFiCsah1KbpG$ ! 0!j 0bj#b 0HjPbHkPcKci K@aOw 1wi@Ca kcpGF_-OF C hiD0`F8 Fj2|F !  y2  L  8F1F>"BH>HGq"@BLԩiI [`2BӈYр0 #~c#ChիCSi իB0댤D0#CS#;hE0c *Kd O2CF@W۪iCay+H3{՘0˱J vQO8FAF*F//1C# !#$! #V2$F2$3?1 T‡pFh F&`0% P% % Ј% (RFjF8 C #qq#+r#krr1F F3 ( C&rp-Ch FFʉIh#C#`[+FPԣx+=HF!F3h0j2b/;ihj2b\1$3\1zh!F3`*F;0hP뉡h#H`h;83`"$,Fh,zh*K@CT2۱ B#O "hFh(3`iF "vOH#+ 3h[k382#ぢh A#@QBHBiAHBAAacwi0FCaIF#F F@8F+ٔhNސh`:ځ"bZ"bZ88 FFFJI)JI F%II F!HI FGI FFI F FDI4 h 8* F>I4 Z F;I8* F7I0+i F4I0 F0I F/IPV F,I+h<0 F)I(I F'I F&I F%I F+ji!I F F I FI FI FI FII F8@󖳚ïʯԯޯ +4AGMR\0FhF FE(FiF' F0-CvF FFFoГiWj@ _h4ոqkRR #S`O3,23A2BB3>34RGs@C00; +yA cK;@+@@r*0ٳi-++ۖ0+'"jWKH#@s yfDOK#@s yY y0ՙPpFI#0'`IF&); |H+ + AF"!~ٙPpF#i2Cca8# ղiBRa"h IF _P "FFFGF#GF"htO 𜁂x* !jMA!*_"jM 2 B0!-"@"@в_* *U:*IV*ڸ((@x@r кѲHHx@* *U:*IV*/''@w@r кѲGGwH$`R_,"@ "h< yz R`R_ O2O2O2O2@_ )O2 _ *Ox )OwO2'*@((HJ "jJ:QlVJ @*S@qN@ "*H (@ "*J *@* + '2%@_W) c*d*e*f*H@_W) c*d*e*f*J FIF@rE)+2 K O _**!! *ТU)!!!ɲ9!1!**"" *U:*"""Ҳ* F"  F @r&%_**"" *U:*"""Ҳ* (('*H8J: F3$B3²$!1?0@w_@F&j(ЈX4Bܳi[ y+ #jY}A3/J_V+#hO0'7 3*+ O0 O iJ:#caFxg+ + ++O O @q+lJ@b_+ 013#  @q +\J@j_+ 0!2"0)h3JД2+FД2+B*0K+,+, +-+. y+ *)4*&سiCSa ( ""CCZ#` C R"#     FAF " FQF "@9FBb +J@<< ;޳iCa)t$( * *T‡-OxpF pt wh F FpDFP 2И0+.1+ږ2+m 2h0 B+ +غУh " 0h!F SF$^$%3˹ 3 F bF0F!F#$0$FO 1 KX  H "  И 0Dh4h\0 "!FbF0F$ jܽDyFp$0 bOsBУ#Cw#0<Ж2ù+mԘ0 +3h0k0+ 3h 0Bңi սDh v KD`0F +F"F$_ܣh$`D y3H3+BЛ{?+#М0+8 30JKBC\0FQaF"F[F$- .c$Z$p$HnZnz+л0CS0 )1+x۱є0+ە%3aFD F v3 "Fh%@T‡i8 CpG-A FFF@"F!hF!F@0FP0Km0@C@BSBC 3V#0i2p"9F F%F + +ѣ+x.04VC.0 ;xzxCxC.04VC.0c.0C .0@w<ѽ P`S_#?o##?# 0)՝ 0C 0j՝ 0C@ 0՝ 0C 00F  ]ۭ (F%Os 0#;0 00@O jj+ OhB@ O@r@Ob@##/+"J@ #*0,p+ ##K[W+ #*0#,0#&0#(0#*0#,0c + ##&0#BChiFBFX(F#;p#{p FFF%@S(O@@ C C x!F(FKHBCcC#C x`!F(F`1F F%b`8FF+hB#h;#`(`8h;}F!`O7r'j*zBs@O ## 3T#p{l+;@q&/ p#ji;`P_C3 _C3 _C# 2+ѸC F!@q*F F$~(D (F(F[5 ;}-CFFFFF([|(W6!DF(Q "HF6#"0c`ba|ihD٠c8|!FCD{yp#p0#pD0p;y+Ѳy02S+ ##S##ql2(Fh!F2F;F s(F!FC-O)F FFh1y+Ѱ5 !*$0m#B#&0YFE"Th1+H# &h# h6l ) 9!v32B0FF(g FO!S" F:FSFиl 9ٴZ (HFAFbFйZ0HFAF0"FpZ0oгoHFAFD"Fxrx|yh2#C!ިc(rx1F2ja8F!F*FSF8F)FGI-ONhF@ FFFC!("&F&v+f``/Ѐ;xC(x1F3c`+hB C0F&41f`]0{Д$0(F!F&(F!F&ܢhb" ++ C"!11!!1Bєav&&&@chCCc`УhC` УhC`@УhC`h  E&chCc`OchCsc`@*6p0IF";Й0chCsc`0 0@B[A@C@O FF2+hR0뱚0ӹ" (F"&PFB (F!F""N(F!F&>FF" %t4x$bl(F#"FF$ch3 #aB3+##bh1BBca) %""K&chC#c`CEFt4{0(F!F'&𵇰F F;F(@k+GNN#h'Op#hQp8È# À80$%j9Fe" kl3@od Fثl#@#d%h2ZY$\[" FFY$'F(5 -7t4x- %%! F F -#h""O 8ÈC Àt480y$! F8S485"#)F(FF$( j8e0M1"0FhFE0 FFO; hd\=((+i!hD#y\)A!h2hh O0j1bj2b\13\19!`)y\A T‡-OF#Bhh h~FF(20 Yj1Ybat"*@~pi:|z Ԙ$0 Zj2ZbG!j0IhB0Zj2Zb# 90I@ yҹ  R R@B@LB 2Rh X"C- F AF*F"F+@ O O #hb0`0iK B)F7(F#h0j2b0hZj2Zb\13\1hy[x9FKF+(@۲Y0[0Ԙ$0+!C\R Ԙ$ +:m@7@%#ʹRD` `3i+&k `^nZvnp&P3%3s F)F"#Z8x#I!+FT>3z+"  #ioї%3[ FAFZFKF( )F" J6@i[hhBKZ"X2#X28@} O C"TFpphFc~+3al2FB"3|7(Ou%hhs'7hz"r7"` FOq*FH1FN Fp@ wp1rhFji F@-CF FFFP1FF*F FCF* m#h[~; iEhVE)F"*#.h! ..ڳ+4.@ B.. @B-0@,?.k=.&0.@&q.@.@y.𻀶@y*283"4 F9Ft4a%10#h~.t$1˲&1t$rt$" i"^ FI( րt4 Fr x F( F F#t4q0I"h~y#j i 0F+`t4y+`Z*3#t4!jɲt4"%1 i"=#jɲit4qO {#h~+it4a0+`3MbB\OrBX@,  .yT F9F*&2FiyC!2F[ F[T(`3!Fi*`@y.54Ѿy.11i+`hp0)FD"ychX y9F*F;z^xi)F4q݁Fo Fo o O9o o o HF-AFFFFp/  8F1F*FCFAo-G FFQF(@Т>TC,:%F&#0!qC`a iki01HF9FP 5 p65.hHFy!##cpFL Ft4" i&10 i@Dis EAZX"F CX"  "0RB+ѐt28ޔt2 F+5ޔt2 t4P0C F't2# t2t2[ F(t2#@t2#h/0su2[i$0;u2 F!@"0h+hh[ùi  "0RB $42S"p@p-AhF!FHM^F! "(FO0F!"OsH#0AF#" 0"AF" 40FI "+F!1 i+-A |'F 4h+07'HNٝ@0 F2FCFfiFfOQ F F^G1!qfCF2FfHN@ FOQ"4HN`&5F(5,3(5F,5BrB#(5,5#7FF"3*%+5E#)$5 Fo$#h~ F F|!$%!t۴$5 "! F+F# FM(F>7hF[~+@!iD(@#h 03 i#h" i F9Ot4"Q0"+F# F!#hn i7 0"hnCfh2YYAy3Ky# | F85 -#hn F i6~ i4M!6t6#cv Fj#h FYk#!Or!FOr Fnߠh #h"v1s F 83 FY#1 F,&! F F Eߴ$ F* i6# " FF!=#h/0*k#h10%h2YYQyCKy30 F2s5 - F F[%Ozr#h .R) F(%t4 F= F!D F!- F)F!hHV$!)FB@$!#j"iX FtV8~! i6BOsB@@@8B@! F\'!EڴBI FD(!= oF>S#"@ @ pG0B  pGp\$@$PB,Cf%@@4ѽp@p-GF FF ihhi)o"h Fi40:F"`h9FT#h0j2b3ihj2b\13\1#hZkmkCE F)F"O3S0 J \ !RBE F)F"GH‡-A@F F$*#C0"$B@,O3Aq$"@0@0F)F#Fe4ҽ0 F;O3"V#08FxB!F(F$h,8yrHj jamlHmdF1H"pG-OͰZFF["FGFXXd F* I(i1#FW(iI[FF,W+ "FYF`W+G "W@B)Y/~=/8/9/.O/!X/XN/@/тؓ/*/@胾/𕂷@ރ@##Bطgط|@B@ʃ@#BĂ@"#B(@#B@@*#B @'#B @= @-#B@𞃀+jKiJ2F(@𞃝/1(!+OC#C#`+ji"Hhh`QTaBA!aF(?M"F\H! F"=+jOOri#F!FFhh!RaO3H W+@^"HYF *PFrF(H)FRFH0F8)FFRF Fz(Fb91F(F8TF(Bx2E1 Ff O /(@##{+-@B)!H" MO DF  E {xDEJK:F3(F1F8{xF34HBxڸ@PF F(!FRF @FIFHIfRSEQڝ/1+H+#/1(1+I+#(18FI (0FAFJF8L 8FI80FAFJF8M܀FPo3|+Oo !8FyRFF8FI(8FI(Fo 8F@u3y+q/1(F1Fٝ(1+e(F1F",^" !F +A@I 7(F1F HoظFFD"J*3,DDP#ZZ *n22m"Ts:x0$DZ`"p0 L?#p ":p&%J 0(F1F F(@J)y B F1"#J4r@*BʁJ$!F(FBF4b,ѱ+h(Fpm 1h0 1$0 1B0AAAXAAAdef?af#g@fgAag0Bg0C0#&#(#*#O0#`Ooooo oFoFo@FMo O-G&FFFF4FkiS& hhBF6$̂ FJK!HFkGF(6/u RBKh(FS"#!F(F!Fhh!F"65J\iCs#Ba "rҊB Yj41F"F "hh!F+h0j2b.3ihj2b\13\1HF"F@DF,VFkiS$0SiD+(F!FS4v.Aeed(FF FV؃VІ H‡85˹F?$iCPR3d+#R5?!i" 8F85h<0+%5B#5 pG1F+@h~.#1 iF iCqF'=FBh!Y?h2_YGy;;y# F9F7a68F/t{y6ñ#h F109F[07M6\?76Oz`5 -2k+"R%G6587#h0B۔.2Kh6#.2 F#h!v#jO2i FE FxR#)`h"J-h-|A6 i5&%h2YYayS#h100 FG5 -#cv1&0F-C FHO(H( H F F aP3K9F"#(F!F7^ߔ F S1H0[9Fhh`!FJF FSܸ36hX(.h`hh9F2F# }X3hh B#9F q@+hO00Zn2Zf !F2F3(`(O0 @FD!3BRD3BND3BJD*3BFD3BBD3B>D-3B:DR3B6DZ3B2DH3B.D33B*D3B&D3B"D3BD3BD3BD3BD3BD3B DO3BD3XB@pG pG pG-Gt2FF񷀐5+@5B@𭀐 1+@# 1 XRj9i03[Փi F7(xi[49F GPF"iiX41FE#F F! ] F !(1!) #h0+4"Oyh FL yh#`j%# F!W/! E0HFt2KX2"@%X2B FMHF)FF(i F1F # 1"-A FiFFF)HXh,K@#+h[k (K]bD0!0 "!FF(F2i!Ky#QՖ ri ] *2"(F!F !] +3#(F"F>8(0(FAF hh"!F+h 0j2b @H‡-O p FXpFFFL۹pp HF!@!( ( (РPB@  ' 0 :F F(.A@p  ;FF   F/FN3x-+!+A+*+>=+2+2F4J++0-xO ($ F1F*FE  F1F*FEt F1F*FD* ٰ"I(+FF v[ +rx SB=F / FYFE" -w@ + FZxD1(|+@z+0X B@1 F1F(E0FIF CF(=@>p FIF#(.;##hI1+*!jt4P1"8x!2@0FIF CF #2| FzBB1F}"' ' N5F' >@O O O   F)F:F[F$HF+|+@! F)F:F[F$F( F1FZ r2+ > F 1Z#Fsh 'xxXgxx O O fshCs`O O ͱy۹+z0[`SRSBC HB@  '  r2+#j[}ñ l/O@B"GQC 8#T-#hO0 p/O@C#GQC UGؔr2+G! ". K.K8F!$"/0X 0z`F! "x|- #h'>O0(p+0|!".CU۔p2++ /'#hO / /03|)F@L(w Fzx9xF@O "" 2T"  b҈  :xzx  ڲBF B@ށ *-FFB" RB2.0*z*- F*F(F$ F)F:F_б F)F:FF B`S_г_@A#;p#hO0Ю 7 F1F  +|Ssh F1F:F;F +|+> F)FJF \#h<0C F)F2FKFKښ 0(F!ޚ 0۱7h z7(F!%΁)΁7iz"r(F9F7h+H# F$ۘ0C#p CFCc20C#4 C/d'Cc@=28F23e7hB ZhB?_`H)F"L7#j[}+ F!\>݀\>#ji3B! F FJF H)FL0XP)FBF@P@#۲>rhB"r`"jR}Jl)FT#hO0 p)F T l2B (FIF CF((FIF CF*ߔr2[l2B(F( FAF! ". /K./K!$"8F/0X0& "z0F!x|- #h'>O0(p0+".|)FCEٚ0;۲+ثy*|!l *O2 F)F/' &5%΁)΁-O0%FF{k`#h 0F!N0`h+ BciS!(; *2pK!kGF8 F ـF(' FAFX#h0+й @0B@0aN\`MAF\   F#hO08#h0"2"8#h0"2"0Zl F)F KF4BF#h0+Y)VнH F0Z` $D*0 PQ(PQ624KFBF#hF0H F0Z` $(~y+@z R_t F4pg` P#h0h:`g<":<" ІT‡H":H"5#h0h:R` k AF8O 0 j*y#h0!2!!:!+ihk1c.|T=|TB"h 1+ihQk1Qc|$r"h 1+ihj2b|4+#h0!2!+ihk2c[/8"28"D"2D""hjb+做y*@ς|-̂0FqS?#h0!2!+ihk1c"h 1i*hQk1Qc8"28"D"2D"*+𤁝y-@#hjb(("h 1)##hZk: H\H\2Jh02J`"$U2"-x F%r)y{k}ԓ$0 FAFJF[F mR' F  %.FF]*G*E)0՛ PP(PQ=6)y[$0Ջh^" FF)0]DCs00#C00 FBF)F( 2"h k1cx<~#h0!2!+ihk2c#h0!2!+ihZk2Zc.׀#h0!2!--i-hk2c+CКy*@|+= |9>#h0!2!#h0!2!+ihZk2Zc.#h0!2!-[+i+Qhk2cKT‡ Z4Bڴ\4BI#h0QQg!t2!1 F1't4" !t4h!#/@"2@"L"2L"hj2b&#H F"%*#h%0.Fi'2aF&F7FF&F7F%&7FFF'F .F' FFF]F5F%^F/F$5C(5++ FEN+KpF0F;۲+ F# ) YJS\C:"  ^4`$"D 2`JF$#h0H F0Y`` $ F"t  FFPFi +Ј+ѻ R" }y|zzj  0[y+ FJF3F0  FAFFxQ AF" O |O O XF AF"/hlx13x1%&7F/\!2\!i+T‡FF F`p+h0+\y>(\y> \y>w(Fڳk +OOR@##u#z+  Qh)ђhv3 (F!hr#F"#0(F!FFGo F@Gә-OFOh2SP-3y+@/+z++l#+|@+ڀ)F:F0F#F0H#"j;<0##l3#d\03hj,0 + cm+*02cecm(F y)Hл.uOzsO*! ЩzyOY OsE(FAzKSx;8FP(F!ڔ0c0KhOJ`#0yOzrSCKE#0y+ٔ00F +۔є0 IF"8F^IF"XFY0F!:F+Fy#hBٔ0c0F)F-80[h0F)Fcj ;cbj ;b4Sh1 y+(F/+|빢y#hBٔ0F)FM'0F)F"KF 3؄phsy"hB 2h1 " Rh*3qP0l#F" h!9h!2 3B #P0 -AF Faڣy+@#|#3Y@񃀅3+t F)Foy1#|##z FQ)F FD FoF FQ0~+`#z+] F(0=0+Sжz#z.&&K'|G:''3Z-'5+' !FTԟh1#y/'#@F!F# F1F )F Fh F)FAۙ#l0s`0~+юp@O@ m eyF F[1FzU#z F!3h~ñ#m]@(2S%03i#0F)F"FD5%3h0B p-CFjF iFFyi(,@ (   (X!x* F*F# ݫi kj F9F";` F)F:F. Ori AIDOsB i!4ci)FS& KBFjG( ڸi 6F І)FFFq6:x˲B5;ph~K(FQ-1ۋ(FQ{ v. ѫyK+|3[(F01(F!(F)F(F8 F9x O0 ph&#b?0Fh2Y}yi+z[+yK(Fg(F!#56 . Fi"j!!x i3x! i!34#|4p-C F FFFji/i/`Уhih=J @22hRk8J "bD+! Р+ +P+;|iCa, 2" 0F!F ںy&K#QՕ zi  *2"0F!F $0  +3#0F"F= 0FIF"ph!F3h0j2b+i;hj2b \1 3\1@H‡FhFy F 2#{F8$ F# R F !"Bw"0F!F%A( O0 pFF FFWyF+ai0;hOb0FZC0F)Fbi#ca-O+ # # i (  #FFF!("HF` !("8F! "PF3k F)Fj- c(@0!jK} m T1 0P)FJFPO# F)F8 j&!"dj+&3k'gK)gK(gK*&! "8FQ !" /!x|D#h)FO 2 |B -0A}  1 FBFMF0 F9F!-ڀ F)FBFĐߩs0131 $ HF1IF1"U1 31/1|)FAށF(`h9F"ZB1 F)FW"KFZpk4#1  ;11  ;1PF<0pcc1RF8b0@#9F F%[F(''8F3 ́́9́-Oh?0FhFT (F#j8#! F 8 `S _г_г_ ###(#'"t4yXFQFJFCF E;F)F:F iY F 8V! i31@B i!3@ F23 iL!3  FO FDGF 2CDj#"R'G78#h0B'h2S@F@F7 / F)F t! FX#ٔ"Bs* FOb! F#ji F%.#hAk0kBkD12B#D`2BJBJ"BDR2B""AABћj@'RB@RB "%"% FjIa%iI*F FZ8#:#hO t$0 FS!$J F#h[k˱6%C6h2YYQ#h[k;  F'5 - Fa FQ F!(C!48 F; F ݴ$ F Fh;J&4`%F# F@qڵ:2#C:2:2#C:2:2po#pcpbC:2:2  ~` C:65.#h FR ؔt2t2#h~b/03#r2' F-%h2XYy ,5 -h!WT#*8K-OFF  ۊh@O ##)F)cL@иPjW30 ظWظSY Oи0ظи@I@=и@A F)F (@:8F!F*F (@2 c 8F! "F!@u'@! "0F ;h%0m2e O %O %O % 9F8F "F.G y|z  ииѰ0a"Y@0Z@ C0K@C 8O O FO F0иииѼ0"08 0FFF .1񕀌~$0@(@@_#yt$0Yo;j[hBj@s  +O c8F! "0F ; " l2 ;ji 4 2F#F8F"8F #F-%"y;j[hB1i8F2F  Q;h0o2g%FFMF(F` -GFFF F)mX3+i3F:F d ! "HF #j!e3"!hl#hO00S8#$ =)F@"#|A4-#F@! F,F #|)F@"#A(`h1F"C0SP)F2FP F1F%$-OlYFFFFF XF;. @.=xO  F)F( FF-- --0  #;" FIF -Ѫ +- 0 cF FYF`# FIFK" -N-Y򖀕-q^ - --iщ----a#h0+|.n t AF:F3Fn#h[k+gB.Y#hE0+`HFQFd!CF9 V FIFBF;F@K#hO0F FQFCF = FIFBF;F@ C2#h0+-к*.(IF + FBF;F!( FAF:F3Fx FAF:F3Fq#h0o2g -C7F+#7OF#h~2g F!a iA2hpS"iD1!h+#3Yh1Y`D F#i04] F FA#j Fil2!y|x#8Fq*Ft6#i0$Q@ Fz#jtVi)F*F4 F%#h Fj2b%#jiqF FE"#jiyF FV#h>0{$"W#a$"F(є1K F (1;1 F F Fܔ1 F#hn-@ F F3#h/ ±00 F#وh"SY+yYy y5 -&5h F5Zhh# F -5Zh2Z` #hj## Fnڔp2C4;۲+ F %h2_Yy ;z1z۱8Fڸ;|1z;z{0FF@O2 F9F2F5 - F#j[}#hj<#%uh2XY8y+z| 5 - F &1 #j !i"#j !i"m&h2Yű+z#hO0\3xky(F rګy\3y(F [6 .&h2Y0;0p?py+m Օ0S->pp6 .Ѵ<7;<7 F&5F 2[j#"R%G586#h0B F$#h(F1FBF!p(7А$03+hZkʱWI\VI0\HF2Qh1Q`!FTXDX`+h,0c!FHFuF0(FRFO (F!FRF{O *h0l1dYl Yd5Yi1Ya09ihFl0d ;ihYl YdSk,I\+I \3Zh2Z`h`HBHB(F!F:F3F+hZkO0 Fҹ1չвy`8i*""P I\ I_`\ui(F3a1F:F#FB T‡-Oh!# `&Fc4 <0jBB% ? FF h 1a "h`AF0F Fh; :``ho s`h "`&s#Wh b`19F3`1d#C# 0C C`YFr!)l0+R 1Fq#i0Xj F1FE%؀FAF #PFE|1F& FD߁FIFPF"EF #"1@XF* * *ТJBB"O0 F  BF$(OP @7@X0{ : F9F 3F(@׀)hBA! ؊Q ى8! Cځ:F ih:0`0 ?# U(@𚀓 \+3љ0+/љ0++љ0C0+0K0 F A!vh0+ѹ0 F A!hP :h9[A` :hAsD @!`  ـ*hX鉙Zm (؀iZh)Y? b*MQUjBB"?  :0 FQF 3Fh ډ BRځ<0-3<0 09 R#0 ˂ 0S"0" #S#h}0 2Qh1Q`})F 6`h@D`)F`h" - +?PF -s h< 3B,3lP[dSlSd;}3_h_`;}3h}`5]im]a 0ljmd]l]d( A hh2F#N)Kh S"p`h1FV(د`h9FO( F1F:FH`h#S1F"L15F5FF>FF.CFJيh FR!P"ڂډ"Rځ"h 1j"h+F+ -OiF FF+.%#*O * "F, ;h0L#2L#4"24"H~ B!2!y 0,0k ѕ cjR0F ;h[k˱0*0(0!0F0բRP1FM#@FCcc% c#;2m@7@뱖X0ӱ#c8F#FQF*FXck@+%t13t1#p13p1,0CX~C",0+@I~ @ yFPFU0N0E"0( h 0Z R9h J  iD hsDB0PF(bihhSh!N.`aihJh#C#`0h`"PF:hihHR:R ah"khC#k`Hah"hC # `Ih!%ü#h0!2!0"iѺ Д"*'01F*FG! O  F9F2F+FG⺹ F9F2F+FG y#h0o2g8F)F"G8F$h2S$ J1(Fx++!<4,88F$h2S$ *+(F+*4,8-C# F+F<h ".:@5(F0El8F)F2 -6&FEڻ]+.^!"9F2F.U F9F(M F (K("0FI#h0;` C F (9h#X"yz*23 +3y!Tf"h#oz0kr+\):: #hor(r o ooooh(-A Rhh" "hF *QpGL`h9FF#j2i +F(F)FDz`hF#jiF\9 0"j3!m-5 P3m-5 P/7! "i pc Dh h#` F!"@9@h"!2 8hLhh0[Eh`YH Fk!2`Q@x08F8F92 }"ѓ#C wh%FIO #q":IXF)F?r .Z/I"#ct%F %.HO0%I"#  {t5>#. cs1   5 +#"I"zq5F+ I"6#05#`{pep5d F8:-OZXFFFPJ(@7 + .@0##p#p"#_ pQIF#qAq/@ EI"0#cs%O O /tݮ 0:I"#5ss  ?#/%rcr`@ o.N(I"#0 FFo.6 I"7#05>_." I"7#05>p#.0 #Pث5cpd FB-OFFhZ0"bF F`@򕀔xB "*@Ҳ* [@"(@#D0#dw HF=I"^F(o0F)Fy(hH HFYF۲+ZZ0F)F"p(S@#D0#dPFMbz#zC#+F HF#I"+(=0F)Fb{S(6Ш HFYF_}[(@#"{{C#+ I"ȹ|+@+ "(0D0 B-G F FF #ZO0FIFOHF)F, )FH'0F!F+OZ #Z0 !F:F+FGJÇt8 pG0hCh,X ձr@" :"<c b@2"4Ih$ iBhhiRi * " "hhiihhi Ri ZqZy#FBzC\q42Bѐ( Q1ZqYy#B8 Fhq9OdB( Fqy=#B8 Fq00"4!QC$2F!F#C\KhS"0 "!F? +;hIFh2F4F&!"FιKK&FhphhSS 0[ܳQ#`.k۲+y\F&CF5FFNFF!QFF(7Ѓi5Cca!F0:h hл BR C9@41 TmK1FZF0GMEѴT0FFT0;hh մ0CE" 0`0v``F%(F; H‡-ChF F鱏hOpHFȱ9FOrD P,`8a!l 8FF opFd FpQ03##rC prCFpop-GFzFF +Qz,NИ1' B8F3q0F1OR`1(F 3=1AF6 IV*@ );` E6ڹй0ѻv0Ccv0xH2p0Cd#3:@003041TmK[\ +3#9FRFG#:hpT0;T0rxl030KAF##h0!2!@23@2\13\1#cFKFBҲ#`hQF"^#h *P2 F91XaE co%cih!S,XKkGF(I#CO| dO`@ph3`;6 3@z1CFFFP2^@k2Bc4 K$$ (FYF ^@ p"t&pQ!"R +i+@F2FYFs}CFFp "FFR>`O7 ㊶T‡piOD"ra C\#@8# #H0I0+h0+- 7  x pi@3 ϱB-0 CFFFO3@C#c&CSc'' ?;p:0?'8p70?pib!Л0+0#CFFF0#0+ss0qp#? s0rpCFFF&`f&66 &&P x#P2h2`30 $J6+ +h0+@̀iB}B ua @F"s Bs p0~B~B @Fvs0"#v L0+ @F "#`JF#0pJ0K  " 3ZhkFvBPFH0TxKEPFL @Fps FR S@F69 :T#T0U0O #C Ppi_ }Br@ - CP0}, C@0+h0+ $*S77{cz8#r#sP2n2f@F9F 0^'^0Fv+#F" +  FfFcOV@7Os;@$ zp!8!&p/C +h00+a(@^'ps`6 x9`B@򧀘T2+𢀔p0SE9`SF`L aDz; )+I9I9 #?ѵH4`S_ @ + J@))I9//## / ЧN+##(#۲+7t)x)@y+*jM * @r++jM03KhY0!hF9`P2Ij2bt4{+Iy 2(F+I IFH$* G '6(O  PF @C3X#0Eh PF@C3X#0 ʱK"6 3h h 3[h X- {CB(Fp Cw DCs60'" BwDBr"/@"#s&"#m(/1H$(F3] 'n;(F/ "" a"1F.Os@q3*XH@!C+h0+QK" 3Zh;kBPF88xB/-0B{yB ѡB@F (?2(% #,hpIB'hpp)kЋiX\ՋjBXˉBRѕJ6 iq[hhBP2Zi2ZaC+h0+) p;0;B,?;FB-p#: @, [Dx2B4/ Bp%8|p(+h0+@F "#pp)vCFFF F(bCF&FFP2ZhRZ` *hB2`DPFh,0T 03D 0Z/S"0Oh @Bb!3 3ѓ;:0 870 '/h; r0s0qpCs0C@F:F }O O @0K@F:F oۤ@ !K" 3ZhkB *!hZB8FH#H0I0" H3O &@F ܤ`O3@F ܴ`0〠wP2iL\ai2as0Cs090C90P2j2brGPFV0{h3{`90s0+P2j2brGPFV0{h3{`s00P2Zj2ZbrGPFnv0W 03G 0 'P2i2aL0+ `#00+.$#.' #@FqT/a7B 3CBC.0@FqW/a4LE.+phL0+#`P2@Fhq2`#pa00+(F "o u-GhFF,;Хjoh'P2!Fn`F2f"p8FGhY65W%P/x/P2n2f%T0;T0`F!F" tB4Gϸ Fo-OhF1hF0+FFz$#ZCr4จڈ]Bڀ>Rڀia0XchY063[#К0+ FAF:F# /0ӱj %(0 = = FAF:F+F hp!t1F % FIFBF;F00FYFRFA(F-CC~F#!I!H: HI+h0+$4A&H1F^"\2'X OI(F9FFJFHu7Z2 E6$4.41 HP2 0] PQ^x-CFCh*FXP2 2 l62W"@,gД`##p.(K HF1FHF1FC HHF1FXHF1F?"pT0;T0(F9F"F63BشT01+hhS khXx#62F"0)hxHh#+h"Fx I#p F2h(h0 ihh"OsCphF$"Qkh[ch&X Rx+ѲT " F)F2F_67.#h$F(ChXFF$"F4#(F1FA,*h#Ph"X0hF$"QkhZ F)F#h$}F( Fb(F0pDh FBY60F{#+Qp-OChQ0F+FP2(ySyxC#<Oy6Z"@"x*Q! Ѩ|@Bћ ڲB PF!FP2 2 cp` DH0" Z0^0;"p \0X0P2(FYmYe!F0 3ihh .K/FMF"O FD$F(=ЃiYՂjBc x(F"F0(F "FCFZй"hh!F+h0j2bP2k2c3ihj2b\13\1  E8FQFJF#OĽH‡P2m2epGChFXx<+P2 2  *63P#! x+AP2 2  pG-Ah"#hFB ݃ FO?O#hOp,hOr# FF!#h@"` O@'#h"O` GF#hB0BP!"#hBPoFoFF%#h BE Ѓ# F!@";FV F! B(F-AFChFQFp/3h/B(4/#h2[#?+|38#@(F}(B ݆H8F '"F!hFv!h"1hF FH!"kFv-A"%FFF+F2)F3+ D(0FI"2,S" d#SC0FIK#@+;c3+DE0F I4$DE0FI ˳ճ-O;KFh0F0+hѺ0C 0 0[ 0C 0 @F!f2F&#@ -$#sCs *@\brj@F9F"F @Fj@FIF@F@F"٥\6 7.P2" F!F"P!0"!0"00!0"`0}!("4pu!|"0n!|"pf!|"p^!p|"V!#h[~ñ p0"D hh0+ !"B h!"@;F#FFF 02F h+F9FP2 2 -Oh FFF$FQx:chZ7Ք$0341%[hTFK_!0x;۲+'#0F!FJF#0F!FJF#3h h#Pi#*F5-$F(0TCMY*i۲ Ck0l"0j3b@Ҳ0@03D Ys0*O2B"r""@w-OF$"O PFsh2*O Y@݀41'[hV @,ǀ#x+Àx#(FIF"F0+1+)ѣx "gJh)!`hO BFx  FPi"P"k  1cE(F!F"5 1*'#(F1F:F#s "00kT0#030@F1F"F0+ZP2(FZn1F2Zf'#:F#(F1F:F#F0Z+ HF!F<||/ @F1F:F}P2m2e+0Z+ P2(FZn1F2Zf:F#(F1F:F#0Z;+ (FIF:F#(#0O 73/+$F(3+Њ F߳ d-G# F+F 1F"HF FKeLQWbmqc{cccccccccccccccccccccccccccccccc  cc"cccccc*-cccccccc1C0B0 F 3x+z8Fsp1F";x+{x3#r'0;`++@'00B *ۀC0+րy+ҀHF)F:F;(̀chX)ˀCh[@ǀy6Q#0+@ F#( O0 0B *𨀓C0+𣀻y+)FHF:FF(chX+ChX@y% 3y# FQ|#z#rw F q33j3~(0{+o +m܄(0 FMY2m2R00d3aZ*TO0A@PՄ30 FB83L O -3A3&4!X"0F$#z8F3pd1F"}ྈz۲"# F)F"G F)F"3F@ o o ooo0FFP2 2 #P2 2 )41 "Or#pG##9Kh#ChX0pGFpGFpGFKh[ChXd%F  0h!Fh5BhF F$"P3iB shZ ch hX1H F1F#h$F(7#F+F"- 48+ o>8F F48)F 8-CtrF FFF/p i "!BF3hF(a"p_p>#p:>#2>#x2p<B8 RI < ZqO)"qF q rˉ#Cˁ0 #ihh(F#Fb!iy|1xȱKJ]\A(FBF;FV8Foo T‡-GtFF FF"p$N!F(Fo{0")i" 10 OB2@CO 0#C0 +ih!"4 !Fh0F+F($ F0F F$P khX 4)F8)Fr$F(0-O[hFFFh+`8!'*Pڈ=@Ix9p!h1)HhP"p*#"qڈ2 ڀ"h "Z!#{j F1F;F0"$c F1Fb FQF$[FhرB[h8!5* :@*3 *!h!Y)' -GFFZhFF h*[\81Ј*9@2 (h(;P(6ѓx;p+h Q#0.K1hS,0"Zj(F!F0"$(F!F(FIF$SFBZh"ii1a#qӈ?3 Ӏ/& -C^hF FF./h0Kk*0#8!*F 8 F  63F2 cEC (F!F:F3CV)pFFs,<C<Cieh2`Zh2Z`,Ԛh2`i  (ݠW+٠c+V 03F 0<+ڣiii2a  (ݠW+٠c+0sh3s`<0$УiiZi2Za  (ݠW+٠c+^>0T 03D 0pZh2Z`pih2`p-O+FFF"h F&ChQiBFKFg _hǹi+ < J"$ ii2a FAF*FZ0ԫi+ < J"$ ii2a~0@.* 9B  E":q 00"`#h0 FAF*F F1F(@E@#h`x6& FYFRF#h0+.# F9FjiKFڍzx B 7i!hٱ )o"`hiih#h0!2!iZj2Zbx8 Bf FYFRF _h#h0 " ii`hki 'ډoBBoRBځki ' Zbx3p)0;#)0hqid" FYFRFI#h0˱{xBO #  F9FjiKF FAF*Fij2bT1p#h0# " `hiiHji  F'Ӊ9FoCCoSCӁ#KF FAF*Fki   'Zb)0;#)0hqid"kij2b`hii"i0FZlAF2Zd#RF#m -CFh@FFF0$@h!aF(F9FBF+h0+. ##(FOsIF"Fc٣h3`;3iD0!00h 3ihh"F#w# 89hBF#C-Gh+hF~;) *Yр)0hR$"PO 6shZ3ch'VFY/:xy+O #qp۱x1ɲpsh OdB ӣi(Fj1b1FCFhO 7/$F(Ѻ є)0+#h)hai81ijpGi#F FFX3`+D(FIƱ$i(FS$ d#SC I+,(FI4,(FI ճ-OChFXF iy/y)zBkxFA'< O Xhyz٣iZl2Zd@ )E(F!RB  ԫx h1F%"٤ hhBaC J|sh  03x1F%"2"z@BЫx1F&"&RF F1F "hFh0+Ph! FF#hh0 ѫx h1F"٣ik2cQ@F!" hh0 ̰ ۲ [E8F XE8F_A# 0#0#h?hG0# Fܨi hZk1F2ZcOr:@x"3٣ik2cc3c!FP"i6ix!|"0i!|"|0*i!0|"$ hh0+C~3Oq"@ &NCnFih!Ch"Xi#Q`k`nm2e!F F! 7#F+F"H,+h hD0A= ; o>-A-+FFFnCh0Zn2Zf"h2F2~ nZk2Zc3|ch0Zo2Zg #w }``n l2d pGnhF!|#nh+ F!@s-O׉ChWFFF,hhinB%ړhRh#C#`PFADFh@D`hBD!FPF:F4F &n j/nI2)bY).) 2k(F2cIF#+* ѣ+0!*Кk2cG#Q+kh0Zn2Zf;0"@2k(F2cIF#Q(FIF"F$ YO+*0@i@BQajh0nk0c)Qi(hZF (FIFPF!F"I##FF-OhhChF_i8F1F$8F5FOFL#hS"0#8F)F"dƀ艼 0P  P FLFnl2dRO,L#"h3R, *pJ FELFnk2c0P [P0ુ9F*F~hX@[x)8`&0c k H@L @ p+M\ L O O "hR#0 FO R! )ꂪ" CJhFb`BRF-+LF#nZl2Zd %8F)FG D&M+hS")"8F6"VES"0"8F!F&TE`+hS"@,O0  F ijy$ |"r R $3 " -OF#/8: [F0j CBC F< +:O0 3 O !("B!("=\3+Wq(" D 8cF(F:F!Ft49Fx%" @8F! "M&h0)(-F!"%rhB !FRF#|.9D؂  / FQF(F ބF"h /"!pZp*jh*є! !"p!m@7 @2X Bb$2*jR}Bbh !FZ /-3/|RF#8^(@ hh(F3FaF/;/h0+}Ѹ 01F0(FO !`00FB8F 1O0 (F!F ((F!F,+hjbS " HFhhHF%*hO S#ZrhB"! L"(F1F `i "(k0P!FF(F!F" ;:/HF!F[F0HF!FZFCF1FShF#SS`Fh4jjyBK#01*hjb03B0#4$0#!i%(F!FOQ#b-Cj# FDF@F "IF  "N. . .@Ҁ"P.Q.@ʀ5%*F FF+y;`3@=`+o .ЦNBF&*9F FF+03,*F+F F,Fo F)Fm F)F, r+уy+ + уy+Ѫy F)F8",+\+Z52V+TR+$+y+M#hnoEy+ F)F'> RO35+~ F)F%|+kyK F)F,Y$yXp0 !0 8`y !2(F",+yc F)F x F)F" oo 8j r#h F<0[*0 FZ  F@Z F+لr(FT Fݔr"* i!)p"#h ""? p"#h ""? xZF\8@fj F"FH $*FO'$0 FFO7$F(?#)F FK$"0F)F F! #! F+F0F!"1 }-AjF#h/0 &>#ji bF(+ F+ (! Fڵn0Bѵl0*3Bl0 Fl`n`O0l`n$"O\Ch# C`$ (Ѿh2Y/.лyc;yS\3x30[`S_p9FJ؀F8F\3"hjh[KCB8F!8FAFBFa6 .#h/ *Hh! y F"h4j(N0B!!(+j#CPFE4[(F#4(!2(!Q0(F!NؕP0m3e%h2^Yy{3yk F1F @ F1F F1F" 95 - -GhFO0Fhh1y+bh,_3hiyCU+O@C#Ch2SJИ0+FИ0+B02\3x+9HFF(F~ ((FwFHFHFqF(Fm ԿO O @Fhـ@FQF `Y@F ڹ_!@F F4 , -O} oFX F jl",! 002 00./-1# i,ؤ !("G  G{ $0$+ѣh h1y+@#3h/0+mՕ0{o$(#000' (@ *@    'Dpdؐ@偙03E߁9F "}*K9F}K$"~eFQ |f[g`F9F "equ3h)FO01| }8n(@𣁽$1 8Ax1PB@ 0F Q[G (@k %01B@d$0 Ք0#0F!F" F!NݕD)W$0@R Q(K3h0Kt$(3m"!#Fl) VH@\0@yT2 ("3sEah3j!a`X} O Aa`[}3ochCc` chCc` k# <A\)3B3hO0*hAJx0F2:F"F0F!F:F#L"0L#@B@3+O E𭀵Z ")m@7 @+mX մD0#l@7 @#+mA)m@7 @˹I 0F #")F" q߀ཆm*m@7@ñՔ0+ѴD0{'0F)F"F|\3h00K3jh+ѕ1(G3jh+ј0o?0F00B:0F)F0B20P!FJFSFF@ G!:("#1#"w1,0F)Fv#F"' ''''' ' ,@F)Fv q@F)F , }KS pG885 Fi8F`8@885 F(i CF`8@ 8pF F ih }hAh 9A`i(F!a"FF0hh!F"u0Fp p-A5 iiD hOtP40FF +(0+T F)F0B P0B8P#4+? F)F1#00%0B  F)FF(%=-0B5 F)F5P50iiB#01i@FA(PP85Fi F0-((F!F8@8!FF #(F((F!F8@8 h yiyAՓ$ FSpG-OuiF F*L1O 6<1F(FiF CaF1F(F{h ;{`h3`#i @F!F@FFpO # SSDS rѕ0@F!F-AFe Fi#}sh ;s`ihh#a"F0(FAFjF+!8FNF(Ѵ030(F!F-G5Fii F FD*sO~O O݀>> "21#0c R@B@@BBB2Rh0i$0[u2C@"u FAFFO F)FȀʀvЀ  F)FOr#( F)FI0 F9F#0-AuiF F!"&$+}{h ;{`ck3"Fi)F#a"F#0F0F!"F#0F)F"F@F3~F(53hFXi"]@F3{h3{`3gF(ѵ0300F)F4-AjF$ FF*i|*.Ei"iEahbiBF8F1FcFбch3c`0S0S8F)F   FFFFFEh8F3`i1F 2 *F@-C '<F FF7(F!FjFE.F!F(FHFAF#F&;hB< ?aѽs iFy F|+e5DhOv0i0a i )0c@@@@N@0Rhu"2u2 F@"x" F)F{ F)F F)FC)F Fgi  " +ݔt2Ct2|E-CFFFOh2Spgy ;y ;|3(F9FJFF( $0 ;|[t"(i* ""IFR85i B" 0#(F!FF#00ԕt2Մ`0#(F!F2Ft2(iXf2F) 5iF 0 FF+Tє0ZPC0ع#0F#)i#0C w#00# 0k+} Ԕ0!:C00F)F( ݕC)FF0F0F)FOr#@-O jOYF FF  H0+(F"!F(F iѸ *н  ڊ Iڂ N# +Ѹ#0"JCw03}ԣi\ *2"(F!F 0 300300 3ihh1\ +3#(F"F[8 H‡5$i%F&@F8F5C4,(Fj!0jЉPBJCB(FXjbAZbpG-OLFO8s,F$2otBF @I 1@OO O KEFF*.А 1S"A2[$t0[@C@O##KE 0{"B [$toBFOWFF);x+++cF(F1F"  0 PB@ x";@{xD@7D0EC(F1F"cFO x@F-OF`FDO Csk + Ѡh"(F"58Fh"+G(`C=0+lFO !ahb1"xh`0PBѹh0(F"  lE  544hE۽hzr#hFR0F31\0  F!0#h<03& F)F? (#0 F)FZ Z?/r(F,&.r!h"psSX{yhzXp0p|#s23s21 )p"#h ""? "h#j? i8" Ft܄q(Fo(F(FF(F F)F2FL#h0Sr2;p2# F@"0hQ *@Xm$\,dBB Q= Zb j 08Q X Z2BX "Q ZeX j B B 92 -CFZ FFV0o0o)Zh00Z0oгoі0#"8F)F"3F$ Fc+m0S#M(#0Уxax+x)) FY(@@cx+ F![0+vѣxbx+x *~*l F!Yd(ze E0+^ѵZ0+Zѣx+x#bx:Ҳ*`cx F !YFفF([ F!Y?ـF(V F !Y8(Lѣx+ єcx+E+Ccx+* F!Y"فF(7 F!Y(3 F !YKFbx *%0cx+ єcx++#2 $8F)F"3FFDF$LF F-OhF4hFDF( F9F*F̔ F)F"q/׀ F( F"F F8Ck+3j F#FF4h _#FTFFF#T "@йchXfFP`B [hDFU77Y'0*0?/DFFCk* +#F0F!F"$x3j0B ܻ D O 4'hU7 B OFF&FLFF=FA7B0F9CDhJC@B@C@O""@O##B "C-0FQB S0 I:0CDT"h  D"`74hB^FMFФ(Fj0Q-Q`¹vyE1)q p7мE5)3q! ]^jPePPPPPjM4,͈P Icb$qYb:hi B,YbZb-OFhFF#X B3 +Lp`0 6&2I(F !{j +8 #{bб̐.#040+й й FIF Z0[ F!$k1k0S F$@ F!̴04+W#z^!"q#0=0dO KFF P@B@O3۲  _ BF   $hEӺ+##z 0(F!F$N 01 F!i! F F N= 2l"=0<0{b 0$# 0ұ(F!"FO36.4 Fh! Fo(F!"FO3O6w4 *Е zIF"(F!F(I! FJF FO!F<0j F! !R FO Fl 0Z FO!$0Ֆ0+(F!F F!;(F!FO* F!O--OhF𰕰(Fb(F!FB$3R#`(Fs@B@GzBB 2U"p"F9F (сp@Pp(O@A!I F (O h2S iy[ zKB0F1"(  ;0+#T0O 08"]H0Z0 0+0"  $cI"KH0Ҳ*@aO00 #2016hXyXDCDC#m#s#C##h"xIF(F## (F!F"3F;۶b0 "m@7@+|0"I0FF#"@h!F2F;(#Z(U+h0ñt(і40{by \yh1 ܀#7+h040{|nl 38#"2 +h0s4 \q2# 4\q2BX#20 Z0c"m@7@;(F!F2F(@;h+ z}:#8# !F(F #"8Fv+jP7q`Q _б_б_ !!!(!8Ft49F"x0 #V M0 5B5і40r(F@B8@O"" 0 #+h00(F!F2F豐$0ChS "(F!F"3F 4;44+ 4+9#0$P2Q"` * (F!F "3FhXh+!F 3zPrP( F!!b!^ F#Z0#z#P!FE+h<0C(3+#z(F!F>#zv#" F!"40! F8#1; 0 F_"40"! FC!C!F"PQەt2 F#t2!1+A-O)FFFhp※h+ހI@@ڀJ(F!F<F !LF(F!Fڸ70F !IMDshb #s`DCs`sh FCSs` !!K#z!F2F(FKF!FF(F\FxmI!3FEAےh9hOr3F!0@񺀗I0Z+I $42AX0S" F!! ݴT0#@bѣn0FYlO !L#I0V0+P0+L +Iѹb0E#mBջ?Л0++9$42O S" F!!0#b0 F@3FBFFHx)I! OE𶚨h9hOr O7&&0<0; FQFp(F!F#"SFh.ии Ѻ;B F O F O4#I0 )-OFh0+hF?0F`p+Yz+U|9F"+hE0d-w"|H!F"? (i6%٠ F!C F!"P#| F8#!#"#|+𞀳h#+ F!"2F!F(FO QFF FQF F FQF=+dX(^\y10\y1?()йN\y1(G+j~i B@"(F!FBF&F(1xeIJFE&(+j2i E#(F3F!FBFFxIFZF3FE0D0F!0&&@F!L+hE0#dAF-AF(F4O F z&F!F"(F F!+h?0+c$2b4l!FF+hO0p!FG PFF0 F#"ەr2 F;l2B1F"aB Fݸn(#fl0#&(F!#FF!F2F3F(F; F:x(F!F2F3F(d(Fܹ(F1FZFG!"MPF!"H O0 i؃-OFFhFa) 0)FZ F# u(@ F}#h1030SBC!(F!.P#h<023 F)FJFFo #ji HE F+ FIF#h<0c (3Yh5B F( F #h<0(3Zh5B F(3 FYh F F 8#h/ 200o F!*FO35,߶(F9F F)F}";F$hp9F"40O  F)F;F"  #h10sn# F+FIFH#00 -Ah0t"p"`t"[hO+FT4̀*0d#00#|C#(F!"FO35(Fj#1F"F(F(F  F!+h[k[0s(F!F" #|+H!F">+hO ГR0 F O#(F#F! F !!0(FZh!Fh(ۖ40 F!! F 2z F )4 Fh (F!F"AhFFF !L(F!F#|#z۱0(F[!F@C@G{BC FHB!!L(F9F! F! FN!0FL$ݴZ0 FD0)shO?ѳl+"(FF(F!"# sh+h0i1!(FOr# -Oˈ FFh Am[ o!Wȹ!Wޘ15  Ցo0ԑ0Ԕ15ѕ%3˱p#fc@Pp0(O@@ C# w0 F)Fr#Z(@s F@O "" 2T"*FYF #(F t2Ct2#h<0; F)F:F(@#ji B3#ji SF8FOE #ji `S`PB9F\0* F F9F#h<0K(3Yh5B F F \9F1H\9F0! F F #h<0(3Zh5B F(3 FYh F t PPF1FOr02p+ћp8''  #hO00S8#۲ 8 "/# HFIF";Ft4HF"xgX / F9F 20`S _г_г_ ###(#!t4HFy[F0 )F F #IFHF"# FIFږ4 F2)F"+400"` H)F~(F1F(F! )F F) F)F 0(0P)FRFC F)F2FF8 F)FBF O?h0l YFRF F7RFYF F7"hFR0 FYFRF69F F Ch  F9FF{h CS{`ROLHF#"HFF F9F\ F)F.ܗ$ iѵT !8FL0+! Sk ;+ؒFF 0b0"0Orh "P  lEO (F!O  b02F@;F(FQFF F%hOrKFHFxI!3FD hOr3F"hF0030 -O)FFFP h)|ѻ F)F)ۺ hpQF"'#3rr/#h<0;T=0  #h FIF+h[ks0 8FAF (0Cs0(F!F"l  (F[FnKn$ fl +h  QՓ0S40+!F:FCF1ڣy#71ۋ33x+ FD F F! ;x+ F Fh&40(FSBC!F" F1F(F +-GFFh@!#cb8Fj+ŀl(٩ +"!FFh`23 1BњBcѽ^1i+j1#(F9F"l0Bܔ=)𱀲B@0+ h1y+@0+#=0cbd<)ak)@𘀕B0+ h1Cy3fj8F s#fbcc#<0+j1+y(F9F"GPck ;+biiB0+h1#y8F M#=0<0cbcacccj+Q!l"k=PB8%=0%0+0+:"8FIFF##(2j#<0bb .*cd##d1*ji oBcjby#k8Fcb!FG"1i+j0B`-Ah+hF~p+t!(F&(i4Fhg+h10{h+ ѻh+ F Y+x` F Rh. )K@ մT0 F!BF#B +{h F3#40BF8#!#*ι43y#cy#z"~(F!F!=. F! T$42 FS">-OFFF+遃h[hX]hh*9AXFqhq#W߀F(сh#_" #tFbtPFhG t"u*  auuIFXF " IF " "*`F0+AWG+Aw+fSж 0F#u0F#0f0| 2# q SDXFqhW߀F(ih_"O  "tIFPF; t'u+ ubu "SqhMf0 B#o00+!F f0F#۽f00F B#o0{)FRF;F#0〔o p0C#" B## #z0|0AG`w#T q y f0XFcFqhWF(h_#O  #tIFPF; t'u|0 ubu ""?"O| Zqf f00F B#o0{)FRF#0e"f0o0+@𚀪|f qqhXFW0ހF(Єh_"O  GW"tIFPF; t'u+ ubu "hhqb2=0F A#o0!F#ڽf00F B#o0{)FRF;F#50AFJF]9o p0C#" B## #+`O + FV M"shAFhXFOzr#O FO FHF#s0PF+##;\"п-AF(_i+\^i.Yгh+V[hX+R]h-OЃh_ԇl/'''+h + +! +<ѕ0Z+ \!0F9F"'0Z+ \!0F9F"0Z+ 0FA#!\ 0F*9F"#FA-AF! ",Q#h+Nbh*K$Kz%+$0'գh[hX F#A #0h[Էl/'''\!q F9F"3FE5#h$F(U !Z#hh3F ###-OFFF+Ch[hY0\h,;90ZH0+###0+Ѐ+@%\ F#p`RB#hF& + +ۀ +@ s@<F "ih 8F1"( H  ih18Fи0 B#\+@@FbF(€0 B"^*@򒀘op0C#_BC√Bqhc(hh9F"Wݝ+hhi!(F"KF_s@@FY(y#0+hhD" #XFDihWݴ0+##`+ ##`+(F# (F#*0N!D(F"KF0++khXFhy!2F#:0+1$ո0 B#\+00Zn2Zf@F#0+hh##`(F""F FPF  -G FFFF)G.GЃhh[hX]hh)F #+`0 h0+ch)FZ0JF 0 CFW2(ci+#0#hh #+`hYԱl)!!! F"3F F0FpGp F071@Q NHi0G( @1@F3o`iG(`iK[oGpІ0jKB O`OppGP  h+؂oP(C` pG pG-C FFF#F" Mi%@$2[1+F%FKxijGAAx P1Oиm7-Kpi[jGd6,ѽІFo FkAkBуjs+I@ Z!#!o F#@Զ@O0pGh-AO@AF"tdp%ݣoi F$%m1Ou;1#"on8)o"f08!!*CCCB4F)Fo*F#A_8D1FP0;0ù 1h*8 !! F%r#(1 1(1 F!8@&Ǟ80`1`pG-OFhhFF>i@O;OCFGFFFEF@!RNIЊ hQ @!т PiHJoG(hК h (FFFF:3FFF7_EXi.K[oG hAF>% h)F5: F"1 KhS"`##hhh)F0#2#a0XjbaO@BSB+ OSOSC h5F-0_E;D04   І8hFh P-$o! F&oz)F F$o F$80Xj#hvPh" o8@j80pF+-( c%a \@! F%(@! F%( =[ +@! F%((#D1p F@!p@%rp :ht41 $pGFh Ftd(q P %1 1+gЎ! F%IANL1-##=!-1(10%%**Q%1*)" F&ۖ08!*۲0ЅC F"&1 1 F&ۖ00 F 9F&0X! Գ6#h)Fji@pF"!0 30β;F&@sCoBcoSC@5 e,U@503P2I* F!Z&b0 F!&[0 Fڈ!C"&P0 FZ!C"&E Fp@$p!Foh%ݣo@hZ*Ejrb%o FYjIZ[5&%-/"wD6+.%ڈz ӡoIjzr* !0 *ءo FIB&5D6Bxo[ Fp@#'php!tTF%6ݕ!F*;1P6++8"  81+C F&ڕ0"@ F1F F!& F1F!0"@ F& F1F"L6Oq F1@p@&p1F$I F@$L0p3+FP0Ah*8[!"% F@#"p@&_!& 13$(!Q # F!%sBm k(1>(1#D1p 13#hhp@ѸppF FF F)F F##hh *4)F F h)F2F F)Fp@#-A qF FFF9F$0XjP8!0 130AFXj*F0)FXjGVF0D2B>D2B9 D2B4D2B0D2$D2B)D2B%D2D2B D2BD2BD2 D2BD2B D2B0XjB0)FXj!0AFXj*FK F1F"%&/ F!A$#8C|FB F9%f8O08 8O08 vet8-AF#/F F "AFl/ "d]-p'&---Q -J-@@J -|!-@:jR-'-D-@/Z-;\-HT-@'p-/f-c-ˀd-@i-j-h-@y-q-x-@|-}-@-@o@II ! FD1O33`11! Bր F3F#/@΀)΀#o" k/@)#"oF]0` /@) +oo/@) *%o+FI0`#hh/FooFo!3hosh6#Ah h(O5%oo9Fo(oo#hAFhfX1&\1#1F"] 5(F@F(K1F*FQ# F +5O5E0=#h6Oc3`%91獲-.#Q F! "F%H+F%D# F#[K+ FI%F881o o  oooo(F VV8hFi3:(5єQ-1! F+Fo@oM0)FXj0)FXjN F)F$ݴt03oO1*F+F%o)F Q0)FXj8@I8-GFoF_ FF%ـFر#mcmoiiiYnF F%(?أo2wo*س"wOo F% 1գo}Oq*B"uoBu}2Ҳ*u٣o"uo }3po"w)F FmCmoiiiYnemУo~-%%9o[h+#o@ˀ! "o!p/ q -OB Zh*"mO Br 0"` "a="r 8-!-ш!- Oq!bmoiiiQnB@ Zh*ѽ0CS0B" o`0 F& 0 F!"$޽0 F!Or$޽0 F1FOR$ F#ٔ0 F0)FXj m-em(oi$nP #hOph@tQF#h@dQhohOp(Foo -CFPh! "'O1oJ  FI}$= F#L F%O8 F[#$!0iJF$:F9FoI`I F#_ Fr F#܀!" F% "\! F% F #{TJ FTI$OC1Os1OC(1O3kb! F$o! FH %! Fl %! Fn %! F#$# F!$ۖ@6@v0i$!JF#$ FD! % FF! %ݵ6 6#6%ccXi K[hG5-M`imGko`iG! F% F2o FYOr1%jc|""+F# F!$ F!$Oc@$(10F#@@І-C qFFFh9F#ۨh@A@NAF F%01FXj~0`Xj F F(! F F$ݔT(F!ORU(F!OB F!%" F1F""ߨhAF0C0 F!#x#717zFF ۃo[jzq)# 0Coju)"PFh F% O0oo>zFۃo[jñzq)0;oju)3\@ F$O0@08F($#hi3F#e #hh F)F#۔1 F#6 F!~ F#C0Xj8@r88mFtCmqoiiiXenb0Ou&B& 6# 6#mcmoiXn0!0& ?0"&0!&06*#d =Ou= 0&Գ&B&80F F! "{03 !F - A!  F/" F 0!$۔0 F8 O00(1pFXhRF(\ Ld(VL F(O ?(H 8l(AT 1Fг *(`Q#k bXOp Opx , D XX \( p !F0F&0$ Fpy+r":s"""Jq#&O0pGFpG2 |"B F t!h{y{#|;0C`0#`0 )o` pGh2S!( o#`pGlpG y++ipG iipG pGpFF F+xh"Xi@`L@)q@ C`q@!C 3 + p ppFF Fs+xh"Xxi@`L@)q@ C`q@!C)3 + p pFF FM+xhXyr nT/f@|@4Cr@"C*3 + -AFFF%h2\Y\. #~B8F2FJ5 -$ Fh"#XAB3 + 0pC`0D# 0hFi FiDc0#q t#P30["$`a(&. a("(F!F&R 3k0 !" F!"&(F!Fp@%DO0popop-G`$Fq Fq"!F0F}!FL"HFx!Fx"8Fs#3`F#3cx#Z0#0#0#@00O itb0,0#0:I*F#F5(cOzs@"0 F(NЀ@,I*F#Fa(F(I*F#F 8a(<$I*F#F(12Uc(*2Nڸc('#bb#o0@F)Fr@n@p@&D3"$ (F!"F&@F)FG%oooBȂ!y >-Ch# FDF@$F "AF" /N>+M"AF F&F0E FT;F1F"&\F(9 F9FF F9F"u.vh:hhhV"FP"@FDsy F1F& F1F&- oo o(F -OF"*` FF`FO@ FF a.6@УW*٣c) ئ2Qh$1BS`.`F+l3Yh$!Z`T#$!D# B.`F0FHE`F ѽ3#C hȹ0 %ZN~@o2}@.C%E}@5CM3"#B F # pGpG pG pG pG( O0 pG8l FY#+Q8po FlRaU6iB ڑpP=#"p0FlRiB ۑp R"p F#p@pFFF F)1FBs:Bj i@1(M1f rl *> iO{q1AKSB i@11m *"f 1g#3p1m 2m n*#3p!!l!f0!g0 l0C#3p0p1"l i@1#0;p1"n 8p#3p;p!#l0!n01f1f "n "F1fP1gP!#l0!n0!m0pFi#F ia#0f(FppFiF ia#0a ia#0f(Fp1fgpG1npG F)1RZ" , ", , ¹?h0io~+0+ ##F B~ji@a$ O0oFhF=0+@&(@ F&|( i#4#hFnlr*@~+1# F f(~1yMl21i[BB̿%%+%yOv+040;z;|#-q2+єr2#XZ0:m@7@{\0ӱ q2[p"K@;|s5C r2;(%F! FOr+F _5B#h"Xyz zj |ZH;FH@;ҝ3 +shF F&1F> 2> #jh+( F1F F& Fl"0#jh+P#00]-)#hB *C h! y깓?0ӱ1Br9B[])=- F! F  0ABAC"0 FFD F"#= |8C~A*i!yc8PM-)F"$8P9P8C~F FF!i#F6 i1F#@  i1F@$W8Fh+(i!#@(F!Or 8)i!c8FFhF)F,"p8@8hFp1rs8F$H)FN 4(, 8 8SChpFӱiKi[Xh6 5%.F#jBӠi#a`h#c`p-OFhFFFf.@khB(FrI"F(@ۀih 9O2hCB@ƀhh```()Fhch iXCaa(𱀣h'bFF2F E𩀣iiIiQ`(F 7p`(!j 1!bahiE#`#aO3UFFcach+~hFE!i#jB;gh#whiBB87F/O i  E4FF Hh)F:FZ(F9FbiwE`a"iahCj`aBB2O3"aca7Fh`.'"i#jB/`hf`\i"j G7FFiXh 7 6#jBӠi#-a F%(F%%%%%4𵉰#.FF)F"//&. )F"  +#01 K4 (0O00!` o &#FxB= KF/FF8F1FF@9F"!` FoFFF# FB=h0FP!F:F!FF"(F8 #B=\1h8 -C FFFFF (%1F(F"##`1Fu8F1F*F#F(F!hBFP#hC!(FBF!`Cɿ KhF Fjh`hK+3jhB `i_%#-KFh)FjF-#\B53+F(5#hB%`o M,(BѭtF6-F(/ѡh)FjF-U#\B0F,б""-#t"53+(%` o -GDh각FFFF d(@ @C@FsBC 3HF9FT#`-ހ#h0+hF F,0h#e11 [e_h-F(@Ӏi_2-A(@ˀq1+.Ц ABAF1F i##h/ 00sH9"F\-]xSl`S_O%d!2F_CFd,F(@#F1F"(F8#1F2F#(FC 4"(F1F3Fo_n!$ z  _2FCFd,F(Z|W_'F'CF _2F,؀F(E !FBF#F(F!FBF#F(F !F"FCF(FAF"FSF(F3AFBF#F(F5AF"FCF(F!"FSF(F!BF#F(FP(F!"FCFjEhFk~F+1еHh`Q^XiAF "FH0F+jiy F!F0F,+j!FiH$3h!FXi o O0-GGhF;jFib1FF(Ԑйy(FFPAF"(F'#h)FXiBF(F1F"(F1F`0! F,1F F=i-"(F1F#Gо`Q\#hXiA F($*F1F FJxSA(Fy)F F,1F F?i-1F8F+F"#h)FXiGox-AEhFF(F F,݀F?I:F F$(F!F,݀FPI:F F(F!F,݀F!F-A F`!FIb0F!F-X@F·)*FXKi+U ixXxB"xxCBbJBH0&MhhN`c0F;```0E(F(,(F' %Hx#00ijF##a!"" F"`%%(FPpF爸`S_pF̲,١!(F,١!(F,ء!(F,ء_,١!(F,ء!(F(F!F0Fp@, FK)F 0"41 FIF F I !|F0I F@`; F#+ B x KK@![@ CI)pG2pGKT"0pGxHpG$ Fh#Y#@hFF F!@h F8s ` @@`pGH) OA!"@B C2`pGx31pG-AFFFF!,".t (hiF%'hhiF%hiF%/FhiF%'@2BK@2BIh6FS&xC0F@x0200KZ+<c`` `!` !`[ aK0neaC60a -CF3h F}.` F*a F&a F"bS!)!F F#.hvh+@  0 06&% FX3T FyhF F `5- F J FJ ,& hFHhB0 xB AxB܁xA0B 0AF0Q xB xBFF2B0-O FFFF([!"-U,S!F(FFDH?+xh9h"\ O O  J  x[cE21$PC(F9Fȱ!\MEBT CxBڃx(F9FxME\Eѽ8FhFx:B"JxPB@8B!KxB)FSF)FhCxBxD8 8F8 8xB 8-GLlT\T< #@] "U]5CUEU 4DEѽFF FF.v0FCI(~s+Ѷ *;+s'Fj(Fc`1k `'50 +dfcCk;Fbb?Ck+ ####cCk;FcGCk%!(F@!c(F! d(FL!d(F#h e[k X!(Fv\!`d(Fqlcdd!(Fh!F(Fcc`dd&dd eF``(F- J   ˇx xB BxKxB рxx @ pG pG pGx xB@xKxXB@pG pG xpKxCppGhx[x K`pG-A F0!FFFAh F3h &FF 4B F)F(иK_CpB($F F FpF FhFmhEE4B0F!F( F$ Fppx FFjKyv@v5C -@3-F@5@5(Fp"@3PB@p F(!FFPYh FF F{k`p-C F(!FF{!F FF Ff0$ 0F)F!G<`4ND0B&0F-AD|F F FE!F"(F8<+`8|G58!8!G F<FhBYh FBFYh F;X70`k`k F7CFFF"#(F"F>p FF=!FF"(Fp@-OL#FFh "1F1"2Ӹ@ˀ\+t?0B€\+k&F" Fp\+``\+YF\+T9FB FRIo">ybyC#"y\CyCbsF!"!F/:F""!,OF(l /ݧycy?G'#yCy"GgO7!,1F(Nѝ0\+:F+F(>(Fe "(1 A.!"o1F"J##`"P#h 2B3Q`#`(&oo 0F iV-Ah|F0tX#h~+ i/Fh h:*+"t9F !O3 F:F/0h+ $428FS"0!408F8#ysz+$*FFR}0X Ԑ$ qx+$ ('y++sz+,(FOt)F"# \$*FF"0X}Ԑ$01 pSp$(sy 3it)F ڀ իy3a(Ft)F"# %ګy;sz+$t)F";F $*FF0X}Ԑ$01 pSp$(ѫyg2"# F)FP"#sq3q -OF F FFHF%"AF2 FAx) PFo1gYF:F FOpHFAF>" Cx+чx5"-"HFAFJ Cx+чyF'y#z "=FshPFTx:F0+y0xو!F0F,[-AChhXply!F(1CC1cx+ ٠F!8(1C 1cx+ ٠G!*(1C1cx+ ٠F!(1C 1cx+ ٠G!(1C1p0F Fnl 0 9"Y󸱔`#Fx#B(FF asx9@T3)FBFFHh FF`i iViB o  FIh`#ڱ# +а++!F@׿iXq 1i3iB o FHhiF(ȿ0Kh`3K *а* 뿘pGFpGF F!q1"t 1r b F T1ۋ# F@?S-A hLhiFhy FQD*@"|*ih  F{3hF<  ,#jl*s)4*x*0F!F@[k;'0#0++z#0F!F /O20F!F $%0 +z;{h#c{` F* F.+{# F 1ۋC+x++j+ F>h1+y+x+ 0F!F"aб0r ۍ0FB,bb!F@+0jۍb F -CiF &(FFF`/ h0Fm20XjK#e3(F /wK3@C FAK FAF g߰ #h/ B00r2 F q(F9F xmC@e(F9F !%mCSe0 Fl߭1$1#1c#h0k2c0300 (F!:FKFmCCe(F!! F r0Xj+h*8+B#hcklBABF0F(T!F45H!FXF6K!ACXFH16A HF6FߔD0AF$0h(F(F5|(F; QFBFSF(FDBF5N#0(F9FJFyTÏz o э kY"FB~FF±HH0F+F(%z9Fo F2F+F  o -A FhF6F8F1F60 ԢyrS+ '' OO!'FA'O!F(F6ـG$Os(F1FH@r#@6[ -OFChXF FFO *n  >F6ROv)F@ F6O8FOFCF"OK+zy +|C";FO&  F)F6+z3O F B6@ FZD D6F)F6#  B BFO F B6 F B6 F D2F6 -GF FF6F/jchU+z00ߍ Fp)F68FO0FKF"O+zy +|$0S"O$0KE"F;FO)F F6(F97hF- [h_ FI6`#^C F@6W Or F::@-7Fй'wC F:*F6A F@*F6;_ FI*F64 F>*F6.FF Fh6&(F!F6L'kh Xҍ8F2y "|Z(F!F5,(F!F"6(F!F6(F!F"6q(F!F2F5hF@QFP!(FLF(4#(FP!2Fy3+h<0C{hB{+uhh(F!FOz"i"Ca  "(F!F:Fk<i hFX*yh*/Ъy2 bxJ*z*#b "*Hq)F8F5߫ys0 "@#8F)FҲ6O#cp0F!F"@8'-Ah #F0FF /!F" "kh{"s"xE* S*h0F2!";"4?h"0FIF@oO0o P-A;F#HaF)-+E9F(FF(?(F F0<;F(FO2 F(4 F9F8ـF8F g`i 0F9FY#h9F"B0F9F6O8(F9F F#c`#s O oooF@F-ChkHFF@F!F59FF"0F7gߣy0++   @F!FҲ6p(F!"FO3,R0F!F":O1z F! +h[k;1 F!k1{ F!(F!FC;DhFB{)F$"@{Bs$@iF Yha !F8F03h<0T!F(F9B!F(F:0(F!F9pF8FpGp}F FFh F)F2Fp@;J-A $&' \E E6#m`7 4GE0FWtupG)F ",!pGOppG0#pG #3#,1@vp@pG0",!pG0AB#pG#0#1,2pGpG0@O۲ @pGpGopGopGopGopGopGopGpGpG}2pBF FF0Gb}Rpp$NBuEU4 ,Yz Zrp"*F"o@"*F"os"F* FF"@3BY/@#BX@#Bش-@𨀅@#B@#B@𝀊@3BشA@𒀇@3B2@3B@.FR @3B).@3B=@3Bu2@3B&@3B4@3Bg!@3B<@3B^1003$\03A0(08602323.0(08#0(080(08 (F2F#(F2F#f23`Zoҥf2$AM0F"oo F|"*F"o"*F"o1C1F! "!"!" z!"u!"p!"k!"f1 #1 84F!!jkOqi S4p"p "!4Ozq!1JC*4tRp@Ĉ€,lRJtB*nRlB"""8Fkn*ѓ,1# F@&1FS<13уk2!i > 8F FR#T1X1w F F)Fo0 F)FQ 8 F" "" #:1l#5 FGpFFF$ ! F(F"F 03 ѝ0!00(F"F FP WpKx+ ppG$4F(! F@# F"-AF FFF8(F!F:F3FA$/0F#鿐t33۲+t3؃ki opGt3;۲t3ki gpGF#F+ F9F";ص7z,еo0+ F F1FA F'@"9Fs0 +3p#3&$"43$Dt 0`k[k3`o pF FF!F(Fp@ƼpF FF@!F(Fp@F FFF >@2C(F!F@#,10pG0pG0 @##,1pG0 C##,1pG@@!C##,1p FFRFV4+`B O<ز_.вO!z< O+زO5@Oв`O.)FZ(F4?FZ(F4?}>(FZO(FZ)(FZ (FZK(FZ(FZOr*p0 G #3#0pG0pG0pGpGkYwpGkwpG F*o4d!lnOHqtd!vxz|~ !! !P! !p"! !!!!4!!!!!lG#0$Aki 8 F-OF80 F<0 @0hFF*q1F Fk+FF&=FF] @ظMиOD<и@и0E FH FOA F FOAz*O F*,5j  W& F  F7&  F7 ] F 6  50B-OF80 <0 F@0hFiF*AF FFFO_ /:/N/RDH! @ pP?8( 05H! @ px`8( 0,H! @ p@8( 0!( }!h* xFHOzc00!( gKFdK<,$`!V/n__U B7?vp"FPFOaa F"#OaZ6OB F@@qO6OB F@2A@p@Bp $"OaF7(F@:A@"p@. OB@A@&C[p@uFCO"F F@iO`RxCp@ "FF@ F#@Opr F#@AOROR FF@tQOr FF@uQ F"#@OB FF@LAOB FF@MAOb FF@8Ob FF@9Ob FF@uQOB FF@tQOb FF@8Ob F@9F@-GFFOB@@AF P$(,; F@AOpbC| F@AO`RxCr F"+F@ F@A})@A Fv@AF Fp@@h`@! FhOaF Fb@@`@A FZ@AF FT@@(`-O"%F@aFF>@F F8@yF F2)FF FK "F F@aOrF F@a F@yOr+F"F F@y| F@Oprt"F F@m F!*F '#Or # F;5 -AH<?/! F F@yJF F@RF F@aZF -KF"Ah%WqEGqF5E2 *@ "SBDF>b # FP`L K+[B+ؽP0s0Ox`x-A0Fp5+3JOa+Կ\]@1F FW@2F FQoCOFOa FP F@1IuC F@2A?-AF@F'"FF@ Fh!+ F@tQ@uQF FOBFF@tQ FvOb F@uQFn%/F@WB@VB# F "1Fh!+ F@tQ:F F@uQ*F F@BFA#0# #iFb# ##c#iF#8@#r5F@s(F@At(F@v(F@ax(F@tQz(F@uQ|(F}@KA~(Fv@LA(Fo@MA(Fh@8(Fa@9(FZ@(FS80##`# FiF#F0#0+0-AF@F/"FF@ Fh!+ F@tQ@uQF FOBFF@tQ F~Ob F@uQFv%/F@WB@VB# F "1Fzh!+ F@tQ:F F@uQ*F F@BFApư`F!(FOr#C #E4AC#B FOPsAD@#B F#ADFpr3cK####qX###c#FiF#Zs# FiFT8@#Fr5s(Ft%@(Fv%@A{(Fx%@t(Fz%@am(F|%@tQf(F~%@uQ_(F%@KAX(F%@LAQ(F%@MAJ(F%@8C(F%@9<%(F@8@3###iF`# ## #b# -C0 'DEs  E,=OFO )FF  F )F F Z [ ۲0Ҳ[  0c FI ɲ FI ɲ" FF@Ar  F@ FAFOs F )F ` F  ^# F )FvL F(b F@aAr# -C@uFc@iF F]@xF FW! F_ F F@q"#"F F@e F!""F FOa"F F@JA F@JA"#%"F F@JA F@JA"#O  F@tչ F@x(=-" F#Oad###% # FiF F @A FR  @A FiF F:F@u F2F@i F"CF@q-" F@eF&#` ##F F0FOqA"v(KeFF#B,FF>3NL^RxNL>NB+A+э iF# FA#B,F2FyQy@@A@y3@+G+Os FiF%0A!U5pPTdFnBT4@A" F(1F"#f!1F2F#v"1F3F*F+F#0V6@BA\3.)F#!W3vB@old1+#V3@BA2 +ѕ4s# ## FOPsr3 F# F@AF" F@36@A F1&C2f۲OB@ F@A's F@A" F$p-A F@AF``GB@"# F@a"`OF# F@aOR`O F# F@7aOR`O F# F@7a"`OF F#Oa"# FOa`O Fz F@nA"_`O FCtOs F;@@A@tOs F;@Oa@44 F|C@AOR" F@nA-k!i$!6 FC#D4 F@"#{!5 F@AO`B+FAm8@AF!F FF F F`A8@.d#]C@B F%% F/ki.%(F-GW~OOqF@A 2F(s#O`耍@# F! 0 C"F#U#aCE#3B Os*F !3F FkA!1OI Oq A$2FH!b# F#! =# % 3B"Os F!*F3F3A11p$FN '!!#(F4@,#F'(F! J!F" F!F" F>!F" F!F F*F8!#Or F!F" F8!F" F!F F=!#OROR F=!F " F!FOB F=!F" F!F " F>!FOr F!FxOb F-!Fq@" F!FkOr FF-!d" F!F^ObF F-!W F!" F!FM F!*F+FG" F!FAOR F&!F:" F!F4 F!*F+F. " F!F(" F!Fp@ " !FF F! "# F !#Or F !#Or F !#Or F !#Or Fh!"# Fy! "# Fh!"#@0PF(FOqAoy(# ###@;3+ FWO0s FPAd F!R F>I6"4 F@OBkFX$V4 F@ Q@"0I F Fx Fh!"# F!"# F|!"# Fv!@"# Fp!"# Fj!"# Fd0"# F!^o! FOR#WORF Fo!P"F F@A@AOpbOs F{ F F@uQOr#p0 pP&y!d eFz! F=! F! Fo! F/! F'! F2! F~!  F8!" F!$ F!& F>!( F-!* Fz!, Ft&!. Fn!0 Fh|!2 Fb}! F\a1 F F> Fo!<# FOR#OpR F/!! F8! F2! F,! F&! F " ! FFr F'!Opb#k F2!Ob#d F2!#Ob] F!2F3FWOr F~!FP" F!FJOB F~!FCOr F!F< F8!"#6Ob F!F/@" F!F)Or F!F" " F!F F!2F3F>!" FF" F!F F8!2F#Or F!F" F8!F" F!F F=!#OROR F=!F " F!FOB F=!F" F!F " F>!FOr FF!Ob F-!F@" F!FOr F-!F" F!FObF F-! F!" F!F F!2F3F" F!FOR F&!F" F!F F!2F3Fy " FF!s!" FFp@k-CF FF!0"hFF,@v # F@r- F@fOrH F@g"#n #"# # F# F@n@r#h" F@eFai?K X hYhrF3cEF F@hOrESI F@gOBO S@ F@i#"9 $#O O# F 4!"+F F=!OR+Fp@8@#F4 5!%0(F!%*(F!%$(F!%(F! %(Fy!%(Fz!% (F=!%(F!%(Fo!%(F/!%(F'!%(F2! %(F~!"%(F}!%(F$%8!!(F&%(F!(%(F>!*%(F-!,%(F!.%(F&!0%(F!2%(F|!%%(F}!a(F1T(F><(F8@!Fx@r! F F!#ObQ!"# F " FQ!FOr F!F FB!"#Or F!FB! "# F " FFB!B! "F F " FB!F@"B!F F} FB!"#t FB!@"#n2 @pFFd% e! F=-.d ! FOb@! Fp@809 6B%5Fb! FS! FT!* FW!j FX! Fd! FQ!* F\!j F]! FZ! F[!* Fc!j FV! FY! Fa!* FjU! F_! FR! FN!* FO!j FM! FL! FJ!* FK!j| FH!w FI!r FE!*m FF!jh F!c F\ F!OB5 F!Ar7?-!"# F' `"F! F# W" F!FOdd 8J F!#"! F! F!F FOH OH1 H H !"# F5-|! Flxp@! FOr#! F\O2@! FAc(!FM!FL0F+P, M"*# F!#OpB F!O|bO c F!?"# F{!ObOc F{!@#p" F{!"# F!:"#@-Oh8FLhhFF0FF FEF   F  D FF   EKoD B  O` /̿_D`@@C@jh@6+`0FM0@ ( 8A @.Od̿Ock`8h`0FFd#`+`08 F@T88 FP84#8#P~0F4FSoCP4L44+Eь ~ F@ FO@{A@A F (pp~0B8Fq4BFFPdLtC/'.&&7F81S#1B>FBF#a7\P3X+ F@Ay#XEBiP3+S+B݉C,B# ## FOPs!p09 6B"3^K"S!P@FC0FOa. F@5 F2FOa. F*F@( F2F@" F@*Fp@p#FFOb@1aPo# F@1aOrgOrF F@1a_ F1F"Z# F@*aT" F@Hh%."r .ѵn5յj5H#l5! F !l% F FOaO@rOsp@%(NmFFFŖ0? 6B"3^W8\ F@Or F+ @@2# FOB@1FO`.Oc@ FArOb F@F@Ը8F F F)F" F@^hK hYhF3B*Fh(`&%' F# <#0#0 F# ` Or FF@;QOr FF@;QOb FF@;Q|" FF@Au" F!F4" F!F." F!F(OB F!F!" F!FOB F=!F " FF!>! F*F#" F!F " F>!F" F!FOR F&!F" F!F" FF@A@" FF@ F@cAOBOC !"# Fb F F0!?"3F F~"+F1!9! F"#p@JAOrF F@JAOb@k,!J+i @ pG+8 pG pG pGF)$#O0a"# F@1"# "O0aF" F@1F O0a"#opFkF,1#h13OzsT3d#\3#X3#`37#x3y3a#v3w3t3u3@W! F"gw3 F@W!OB]kjh3 F"#O0aR F"#O0aK F"#O0aD F"#O0a=" FFO0a6Opb FFO0a. F#O0aOR& F"#@1 F"#@1 F8"#@1 F#@1Or F0"#@ 1@" FF@ 1 F@ 1ObOc F@ 1OBOS F@ 1OrOS F@ 1OrOPC F@1OrOxC F#@1Or FO1aOrOxC F@1OrO}C F"#@1 F"#@1 F#@1Opb F"#@1 F"#@1 F#@1Opb F"#@1 F"#@1z F#@1Opbr" F#@1k F"#@1d F#@1Opb\ F"#@1U F "#@1N F0"#@1G F"@#@1@ F#@1O@r8 F@1O@bOc/ F"#@1( F "@1Os F0"@1Os F"#@1 F@1O@rOC F@1O@bO|C F"#@1" FF@1Or FF@1Or FF@1 F@ 1OrGs F#@ 1Or F?#@1Or F#@1Or" FF@1" FF@1" FO0aFp@86!F#OBPd6! FObOc\6!p"@# FV6!"# FP5!# FOBIOb5!F FB5!# FOB;5!~" # F5:!"# F/:!# F")" F#@ Q]"# F@qAV"# F@qAO"A# F@AH" # FOaA"# FOa: FOaOBO@S1"'# F@Q* F@QOBOS!"'# F@Q F@QOBOS"# F@Q F@QOBOS F@Q"#"# F@! F@!OBO@c"# F@!"# F@Q F@QO~ROc"# F@Q# F@QO~R"# F@Q F@QO~ROc"# FOa# FOaO~R"# F@Q F@QO~ROc"# F@! F@!O~ROHc"6# F@Q~"# F@Qw F@QOBO4Sn"$# F@Qg F@QOBOS^"$# F@QW F@QOBOSN"$# FOaG FOaOBOS>"$# F@Q7"# F@!0 F@!OBOS'"# FO)a F@QO~R#" F(#@Q F@QO~ROS"# F@Q# F@QO~R"# F@Q# F@QO~R"# F@Q# F@QO~R"# F@! F@!O~ROc"# F@! F@QOBO@S F@QOBOzC F@QOpbOs"# F@eQ"F F0! F@qAOBOC?" F@QOs F@QOBOwC"# F@7A{ F@)AOBOCr"Q# F@rAk F@BQOBOCb"# F@4Q["# F@QT FOa@2@iK@# F@R!ORC"# F@S!<"# F@X!5".# F@BQ.# F@AAOB&" F@BAb# F@QOBOC F@(!OBOC F@(!"_# F@)!OBOC F@)!"_# F@U!"^#(6 F@O!"ӱa#OrF F@ F@UaOpBOC F@Ua@r#[#0 F< h!a! F- FP F" F8@pFkFOqiAd#dh1)kjh@#i!h1Pv3t3w3u3ki&v3(F@W!"|w3T3B\3Bݫkjh3h1\3B##33St3;t3u3;u3h1*Օ:t# ۲B8t3}3:u# ۲B~38u3x3t#Bt3u#y3Bu3kjh3h! XB?B!h!ki/`#B1#3t3v#3۲uBt3(t#w31ɲBut(u3BҔu#B h1!#h1kikjh3(F@W!tc\B (F@W!ucR BЫkiZt3(F@W!"u3(F@W!OB(Fkip@Bp8 F!F|(F!F8@"pP&Fd Ff F$@ F$@$ F@1a FU F$@LA F$@MA F$Oa F$@A F$@A F$@A F$@8 F$@9 F$@=Q F$@!T F!#! " F F F F!0@`8@!l%Fr#4(FB%@tQ.(FD%@uQ'(FF%@ (F$@LA(F$@MA(F$Oa (F$@A(F$@A(F$@A(F$@8(F$@9(F$@=Q(F$@a|36 "F F@A#@A@" F F"! F F@A FX@>a FS F@A@ F@A"#+F@ F@A)F F*#OB F@LA FAF FIFS F FOaRF(@3F F@ Q FYF FaQOs+@ FOaGrnki pPF"&!3d F@tQ@uQB FOBDF F@tQDObF F@uQ< F@LA@MA FOa F@A F@A F@A F@8 F@9 F@=Q F@ FOa@#_6 F[V4@ Q@Q4cX$V4 F@ Q@A<# F@A":34[F&4 d4d4444 FO`A/ki@p0F$ FB Ob@!,F#(FOa", ##p@8#Oa"pFP FN F!e5;! F F Fp@Rp#p@Dat1FV % F@DaP ! F F" F@?aF F@SAOB F@Da1=Ѐ " FI F! F@A"#p@~-CFFFOaA~RFF(P"F F@Atql F@w(" F9FFAQ2 F@a"#R"F F@aK(#BF( F3F9F#& # FD0 F)FOr3FAQ -OMFF(hih *& !2F F Fu F! F F@a@ORF F@A" F@Q" F@Q}" F@Qw" F@Qq"@Q Fk F F %#" F{I(4 F@SAH "Q F@RAGvJ//@FD@#nK)F F #! 4 B`# F)F#@# F)F#b# F)F;FC# F)F;F" @  C#KK F)F # L %FFEK\[QCOd ZxB#&=FOFUFO F F!="5+ F@QABBBw F@QA@O? F@QAz'p`O+@# FYF#@# FYF#H# F!#C# F!#  _EӺЀ#% F!#`# F!#p# F!##% F!#b# F!#r# F!# F Fd F F!dp@AFF F#O`bF@yQ F> FF! F! F!" F F`Ap@ -O fNKOJ')F#KI";FF >FFO8 %f5+ODXxxx! F F FS F! FIFIO 7! FJ7!F FE` {+D_  # FOb qs n7 B@WFBسB&&&& _AX2BؓB=B@VBB 5_& - F l7F!P F Fe5ñ"#% F I! FK F" F)FF F F0@%0%'fUeuF)F F#M0#N0#LPO0=F\UY#K"YC F##OR F # F@ #kC32 F5z 7- F1F*F F@B-O% ; FOa_Fp"(@FOa F*F#Oa F(F*F+FOa F(F# &#! F+F*F)F F0@A F:`@! F@QA F.@RA F(@A F"! Fh! F ! F! F! F! F! F! F)F FQ# F@MAOB[OBF F@LAS!"# F@"!F F h!"# F"!F Fh!*F# F!*F+F F !*F# F!*F+F F*F F!#"F F!"# F+F !1 F~S !+F#a 3&R  F@QK)F FORF F@tQOrF F@uQOzqbF +F F> F@QAOB3F F@QAOB3F F@QAOpbOsOBF F@SA F@RAB":Osh0FEFORF F@AOB F@QAFBw F@QA @O?ќ#' F! j## F!#j# F! n#wn l0RC# F@AOR#@OB F@QAF8Bw 3 F@QA@O?ќ#' F! j#Aj0 FD#!#4# n# F!)n l0RC#D6B]I [D# A=% Fd h0 Fs*F+F F)FQ F)F F+F@uQOr+F FOB@LA F)F F! - Fh! ( F ! # F! F! F! F! F! F @A% F@QA F@RA F^ F"+FOaq FOa"j-G!䀐P24F! "#60666!IB +5іK + KKIB +5ѓK+ KK IB@s+5ѐK+ KK-d F!!.F6OzrrC F!,&kc6OzrZC F1F. ޱ#!# F F#!# F F F F!Or 2&7FF[! # Os F4 20:B#[7##,# O 6.## 6%# F#(PK! F# 65@-% F)F*F+Fz@O 99l5Ozr F)F&9aF@A0F u u5t0F-tp-O@AFp`K F]@_ F@:A F F F!"# F@ F! F?!I&?%OBF F@A!" Fd F!"F F d F\5DOi +ZZR3+٭-%! F%uh F)F >`5 FAF Z F  FQFi FYFr-% F@"%p-CF"FF@FF䐽(m"F F@fORF F@F^ F@9:F4 F@5 " " FOa" F@4"3F@ FOaOCO@B74 F@6Or" F@F"#$d F@F"V# F@FOpbOc3F F@FOpb3F+F F@3"O# F@3OBC% F5Id"#eORF F@*F+F@ FOp*F F@7pD!e F@7Z0= D!e F@7K= F@7CՔ3C3# F@OR F F#@aArHUOr F@ C%&-A0LUJ5&ȰFDEO@O+@"k F F #KOH!!# FD6@." FAFF&!!#O  FD6q.>-:N F!!E#U5 #5!!# FEU@-@ "# F FU Fp"F@ F F@tQ F@uQF FOBFF@tQ FObF F@uQ% #( F!!@# F@tQ:Fz F@uQBFtXFG5H0-A 1F FkiY Fp@A Fp8 @!A#@+D b-""k!i%ki- F!A#@kjx1-! " F-Ъ F-k F -06 F F F[-) Pd5# F-T F Fhki F!036s F! F@7aO@BOCA$F!@#@1{ Ԕ1S FG0 FOq@?kFOBqikF@ 1ikFOCqikF@1i~6-uOs0u#m - F K+[Bp+ ٔ*Oxc08"":F[#k3+ #:k(! k(!*2"(!1+#1@x0 ,6c*V0F#B0 CT0&*г$" !T0&*г$CD 00)6!ÿpG*0 xQy :R&Ͻ6 `pG0@O 4353 3"!@#@FFβ#4 p FF F!0 1ki F1F| F9F? F1Fz F1F !# F F F !A#@ FOq! F0kiy! F FOrF FOa"F F@"F FOAq" # F@1@rF F@'1:+ Fk#:4 Fp F Fr3 Fa F4 F FY F&:+ F@;h>hahPhhthChhнhhho}ppGh!h!h-@h@h'YhęhȾ-ChLi+F FghQ#h+F hF@h"G(:#5B2@D#h1ak+ \\ B3#B+chD\\ B3#B 0@E +{k{f0h(-G F8F FFFF(\ :Fhfa+./WsBQѨ3!x0EH7"   2JE1E3x+3rh+ ##B1B њ2q#\\(@T3phB3h+ۣh+c{Ccs ooo (F1F22$ FpyFF`#j˱h){]{ Io љ{ ) }+cj3cbh3`pciC38 p F1F2s#f0ei h F+)F2F20k{f0+i3+a-h-#yBѣCf0 F1F2 h 3`ph 3`p ppQhFk"l2B#zCjkJ#Fp@"qp?phFQ0F&1ۋ+x+ #zkxkhӹ4#h1ky[0F!F"[`h!8 F! F2?ܫz kh1ۋCkh F+ ##+b2 Fp@2-#y# Fp@pQF+xh+j53h~+1+kA="|ڧ (ٸB٫j Fbb Frh1y0F!F"p0F!FY0jhI8~ F 1z FO0-GFhF Fl0X L@FiO yPF t" p 8 CD,4F1E+hhX;y+$)FRF+z(hh0+56ۈ+0CMRF)F-Z&"sz3$sxoFp# 0sx%3sp CDW"sx53spBOќ F pG pG (K\ pG8 FF(F`C8 0pG pG))0pG0pG pG)OC@ OC@OS@0pG0pG00pG pG )   0pG0pG00pGF0pG pG)   0pG0pGF0pG\0pG00pG pGpxh#JR3`BShGp3+ p) pG*0pG pG) + ;IQ"0ZpG pG pG(K\ pG#pG8 F!FB(F!B 8pF!FB(F!F $!(FB(F!p@̿ FpFh F"F#h 3#`-C#F pT; FKpF F FFO iIiHI)I&n`8FF8F @&n&.rnr 3hx %F F:F4-6FE(FFT hoF F@ ]08FF FoF F%`88F F<F)F F8h F F@.p% F IhFe`h!0F#`phpG pG8FFP!FF((F" 8(Fo" 8pFFX)F2FF( F" p Fo" ppFF`)F2FF( F " p Fo "} ppFF`)F2FF( F " p Fo "a p8FFzFH!FF )F"#F88FFgFP!F*F{F "#F88FFSFX!F*FlF  " #F88FF>FX!F*FWF  "s #F8FF%sWB;FsU5 hSB(F pGFyF${4BF(hF>FN`5>F0;BۣN`#q0&F'&Krz5S" FB@@FczY#0C@@E5%rP760B۽-C F FF F! "8#+p(O,I}Z+$ "HC   I AqRAx@}PաZAqRZ3+p۲CEo+x+ ٳ}#c+x+}#+x+#@HI L-OFFO%-̿CF#2zJKS"@F@}{hh23їа 8O O FW(X(FO O F0F-X(ܺSкF кݪ  ,Ѻ+Ѻ RF+ѺRFTF$PF#!F#: 0Y#0C@B؛ KS"0C@`B:+056_0Bg-OFJ FFQhhFzpR Qhzp*h# y)3B###00 ch(F 0 "0+䀁Kxdf 0+# ` # d OF( B!B" -yBє"  F  (r2BEӔ 0*]F0" OrVCzC *,bhh"2&+F(03AՔ0"Fw FG1` F9Fr6.є 0Bн(0#(0'O F3 Z+A(-2K[ l Fv FFA0 0 F1Fl  5-  70Eػ %0EF 0Ow0+A # T  # H OF. B'B#"ओ -yBє"  F  (r2BEӔ00 F F F$#08S+""FF0 F0Bڔ$"zKS"0C@8J0ѐ8 pG pG0#00 "`pG-G0F FOF 4<"EطB(7FB7FF0ziK)"0 KE*} FJFCF)KEє0SEE0Z30 F!JFSF(  E@𚀸?@1 F3@1H%G#&@13@1ch~-y%E F50cch [B0" `0SchZ{B O m80O8񛱔0ZҲ * ! l!3" l!0! 1# ch!hh0 F2?81& # 81ch[hj<10X300Y30 (F -OFFF8@p/D0 __ѻ EE###۲E##P5% FyEFO fKzS"0 CC@۲#*KE1EBFRFҲ%E̿##+F F!JF*KEє0BECFSF۲E̿%% F!JF;FT(  0CchZ{B4{z 41!B<0 vvK0;۲ +q" chqhh ! h3 ` CEȿ1Fh3'`#SEݍ '@ h;D `ѱB3h3;3`chhh0# FsBch[hj<1#@1@1 F3@10Y30 {C#s#rpG"srpGӹ  `0#01 !`#1pG-OFJF0FF8-A2F$SQ2=$"5qRr& Kh#+hAF*2$56B}sFhmhh%F6hh2XY8y+z| 5 -! F Fh%!#hOb! F Fhޣh" "hqhht" jiUhht""t"&hh2Y-9Ъy*61Yl!Ydv)v +zC1x*Z zhh<0;(3#F4B)F" FH!1Rb(F,(F76 .Ѡhhp@^hFhhpG\H'h(5+;/9ѳC hh"Yy!QlAQd)zzh< :(#"F4B (F!1z"v 7 /Ѡhh$2# h' Уhh@"#v -ChFCc$bرyh{ F!3#h#1F"hh13#1zhh~+uo#c F3(@hD#131iCh1F0c\LHh1F\O1OBe2Bѫ#i9BCߋ'1B6Ѵ!*2/@0!1B ڣh1F\0h9F\ FMSF3ah0s#1[[ 1ԣhH$FBB F3 F(@ F3D(@#11+&OCE"kj 0FhFHBРh[ F3۠h'h1F#h F1F3lډૈ FCS'HF#O3a!F&3ݮqh2Fj!i' F3ݠhhthhh "1FhhO ГR0 F!3 F9F3 h+&hh"Yyz j]Q<9Ql)!Qd 6 .Ѡh&hh2YpyczS|C1x*z 6 .ѫ#S#cFǸpG8#hF` h F)F)8hhhpGFhhX 12) pG0!i"Rh!!By,85EhL,@,0L,@MB+ѐ$@&HC{B乳Z@mm@7#@l[ h[z+ё2+#BR!0@@$0iy xQ#0D@PyD@z@S 0hhTL@i@ Ci@!C[h+F0p h FF"F!,` F!hs0s%`41p8F F h(hhh#`8"zbD(F1M``(ih#`b`ch+#`F8hhpG8i Fh"4`Y8@8j[h-G %FFFFPh2\YԱs Z@3K@CK@CS8F!FBFKF_@5 - -AFxFFFh#y(((F1F"F;F=h 7U'0(F1F"FA4 ֿj[hҿhXpG pG131pG1;1pGiy1ipG4`1ph FBЎhYR.Qp`1-Ah Fh@F=Fh)FBFQ(FF o8FF F4@l K@@p0 8hX8@8pFF0!F2F+Fp@ppFFP{0!F2F+Fp@Mph9-GFRF P$(,p0`^`!FRF+F $ GGh8FFF!F*F8@-O0F48 `X_ OOOt$H7 ')7' 1 Ѹ@F&!F@chFt4{0+M 0Tp(" L+hO0 #i0Ԕ1#>0 t$x+В< *+#?01+ v# QF"F[Fe!F5)"F#t{B!b3۲2+O t4{0a U  ьl+&xF$"4 F&$kF(50 FF$*F4 F $PF()F500F F`Q$4m$6 hXt0-AF1F*F#FAlhXpG@ph@.h`VU?ѐ(-ѝIkQ2 BрB   pRiBёBؑiBѐB4   `\ Ap p p-OF`_hh}FFi3z +;xx c,0IF0F*Fk!Fc *m@7@+0F!FJF5 0hB݀i z ( і8y(#  z+Z ++@ÀxC *{yOHH(;yHyhpHh@𮀔,0(FZFCF9(𡀫y+@y3h0!2!, ""2"!2!140(F!-ޔ,p/V3h0"2"k;xC *yOHHh;yH{yH(+|Z0XԴhpSє,0(FZFCF(GЫy+@ 3h0!2!, ""2"!2!140(F!->ޔ,p/3h0"2"71"8F&( ڌH9F"kH1"'OF2+mԠkz+|@ciiԣiciiZԣiBk z; +΀5 5lFS+|Kk EГ ZE Сk"h@8F1 2CFed3ekJ8F1mSF8F!ah"mki0eki1k`h0hk`h0hO2kDKiB# C|chx  iH1#!hbiHF5L'kiH#hh.ѣiBY0W3h0!2!!2!, *"2""2"h$1#hd(k0303|C'")F @ y/3h0!2!, *Հ"2">ȈDȈ ޣkah b` h` !i"ai*dѫy+ˮD 0F1#593h0!2!!2!!2!, r"2""2""2"kz***"2",p/i"2""2"!2!,p/U"2""2"iai`-  ciډճP0kh0` kF 3hd0b"2", ""2"kz++ Ѵh00F!F5FF'8F }Kj˲+ 1P!0LpGopGt4X{pG pGopGjMpGpt4Zx*""!u FLt$ ]CUut$|`HT`U_OCR$.R$u]V}b]u31+pDxCxB6)%ѐ| * (   B pG* (   B pG(   B pG)* ""B F pG pG pG`x"O2B(#F۲BFFAR R x@S @T @U @V pGt4@Xѓ *XxpppG8Ft!xt4Xx8-Gt4jHdxFF"H\2*A,ف-@ց`VQ NBF"y+#r F!"!" F- F)F*FO"1F" F1F- F1F 2t$x   2t$x  -  2t$x  AF@AF :KEF#-!- KEo@BB# Fα!" FV"! FFN- F!"+FDO#1F2F<" F1FF4- F1F 2t$x   2t$x  -  2t$x  AFAF KEF#-! KEo@BB#O F#AFBF O  FAFBFKF- FAFBFKFOD1FBF3FO  F1FBFKF- F1F 2t$x   2t$x  -  2t$x  AF4AF .KEF#-W!! KEo@BB#" Ff!"# " F!# 1F"3Fr " F1F3Fi$ V2t$x TV2t$x T4,!F !FFmBB#UF$Xt4, t4z @"*р"ZxZiYԹ8K+F F)&t4x+"Qt4x+#ji]Դ2# 2C2j MPjMP8 8 82F#@sC#2h~; F!@ϵ*pF F* ֲ1F}L#zK(F!F2F p p ps#t4Fj#K# j Fi+h ?0F4c#c`t4j80FhG|s-F F0F!qt4xB#0!0Fet4xB ѝZx1 Bэ - :ZxBEu Eu#jh+-)+&-t4Y ic~ӱ#j Fh# F F^ FH$ F?|* $$d))d FC!F oFpt4FH Փz@d,(d$d$ՓI0B(F+h~k!F"#(F"(F!FFp@ppG# h~ FO3 `Qt4"^Aj# F! )  @p pGopG@OH4t$ђW۲3+ؒX c+ؒY+Z[I߿tdFFhF!"$;]Z* 04,\61F"FX9F"F0FS+jiFiF80F"FGo(Fst4ɲZyFBjx1cBa! 3t4 y^yZqt4BqD()@%l2@S#h/ t4"jYxiZy F)F#h?(5?`- t4"jYxiZy F)F Fl*Ft4"jYxiZy F)F0FB t4"jYxiZyo |st4F{jFi7tC{‰OsB|Qx+08!!ɲ #jB)t4|)x+ЖL!Bt4s i t4<0K#h0C+ @##@#" F!@" |8t4F[{ FBji=t F1H$t4 F]s!j 8SjӲ+ 2P"0)t$x*؃LFs   pFt!P06t4FP ]xZpt4Yx)9Э" %@BЃ t4"" t4[oC FG  " t4! Yx@BЃ t4"! t4[oC FG  ! t4%PPt4 Fp#jMj F Fj t4x*Yx)r)"r F F FH* F>Rt4"jYxiZyp@-AFtFFʲ1FRpYt4ZxBux0BўRpojX!!F (4Ѹ1٣jXlI(أjlC(=t4O0RpFjXl4(j"Zdl,(٣j"d F(Ѣj#M0jM0t4 P t4[x@Bi  "0RBДt2C t2t2 F# t2 t$ Fx"kpt4 FZxx$ BF xB,""BjBr(F!F ұBxBёB"FEt4ZyxBєB ҜB(F!F"p@pFt4x@p++ + + J˲V+F{0 t4(( @} F!pG-O#/+FF*,/F "1F/1"~x"ӲG5HNUY^b3hm333.3_3-{BG3 333fT}k 3333 FO8= FQF| W F=2 FF0 F8) FIFRFTDt4<0t<B𫂃< F)F~ F)FO2( FE F(`#jiU F F<#jiF-o F"( o%t4xft4[xb?t4x" FFt4+e`0L[?Ft4`t4Yy[xC Fp/t4x*t!0~t4[yt4x FQF"'F(@)t4yqt48y80l F8cn86#1F0F*F+Fb F)Ft4 Bb~ CB"~}B"b~: F@QE Ax)ٛy+## FF۲BSt4% &Bb# C$B"" !0C#(F"ut400t40t(F\1"e F1FpFs+@/@3+@@(F1F:F)F F,(%ot4O0ixt4xErO]t4N0Wft4xE`N _REHNt4HP-U F!qt4H "H t4HP?! F]t4H "H "ht4jZkct4[l +t4Dt4H0@t$#W3+E/@#V+ҲZT2Ҳ*3+ F^Lt4Q0t FQ "!"F#h FQF"~ F(@րt4x L t4L0#h FQF"~F(@t4x J t4J0dt4O It4I0dt4O z Fxt4z0r!t_Eut4 F{ lF(i F9Wt4{0Q F@Q F@Qo@BoRBBR F@Q.4 FG(Fh"~* F#+`F9 +0t4+t4+1t4!"0! FQF41uwt4!,1+`%o$o o  oO5oo(F!st$#(0't$F(0t4'Pj2iF%m 6&KtY]5-[x000000t4Z!   ER}xB#0! t4xB#0 F1F 5c- F!4>m|DK+  !t4 rpGopGt4XpGt4haFPx`.>[l3&0FBt4Zl B "HҲBv!H:t4H BH #h~+et4H a0FО- %% F?F#hAk0kBўj@f.&&&j@nQB AkB+УCBC##t$a # F)F" F)F"#z  F9F" F!t4a0 F@h@nRpjFBkAkB+УjBB"" kղAkB+++@B + +УpBBB""A@BҲ@V F &CAkB,ѳ+г(@B$@7B @3Bгг@)Bг@5B г@BBB""A@BҲ@` @ CAkB@1YKBC#t at۲ +c a=ta@a!hj( @B(Р|@  t ##OS0 # F#" t4&HP`Փa  "I FFt4 FI2F "J FFt4 FL*F#p@p-O \ | }#FF IF:FQB*E%qл0 B#\+@XF(0 B#^+@op B"_2B  IF"8FdIF"q(IFOpFPF!i" }F0(F{PF!i"POppF`(Fn0FkPF!i"6k=F# `F(FV0FS8FPPF!i"6MMF0C )'й  ع й PF!i" PF!i"PF!i"''''0B!iPF"6%X*#00X%՛op0" qC! F8Cx+PF!i"cj!iH3 % F24~(@+cj݀ aj BH1cjـcjۈ+  "%F8F<U 1F "!i(F1"(cj!iHۈ(F01:F3F@;b@PF!i#5#PF!i "59P- Ou%%LA3(Os%B@ B@0;+AF#A;  "O(@𣁛o`p0C&(0 q HF1F0"F`BxB0+PF!i" jxIB!o(0"!iPF"5 0B q2F0 i"?LR@ "@PF!i#5:F8#@0PF!i "  0 h!i>߸ 1PF!i" q1FFPF!i "Bxl: y00F 0 Oy h!i2F>߸xp#0PF!i"5#i hhy!JF#00+@ـ#jZBг9PF!i "`s`@ŀ#0D(3Лop0 qC!!FPF!i "wBxl: y00FW 0 h Oy!i2FfOp(F0!iPF "5)5F{ H0F!iPF "5lOp F0FPF!i "5eFUl 8F0F`F-!iPF "51 h0 O!i@KF>9PF !i#50#0PF!i"!iPF "5#i hhy!#%(F FFhX*uh(uЈ{({(h?/O,L'L/ؓYh0Zn2ZfY|..(FF Oh+K(Iы}+Gы|+D*j0++[9#`kj%݀3 X@3S@C 3S@C F1Fб'|hpyOBG1F"E h!F}"3Ff(FF phX FE*y2X+h5!F4$!F*h4#!F"5p-AFhFX%.F 7&v<6 F1F"5kBӻkB -7&v5<6c0F!F"! " Foyj "H1 FAF"AĽ-OFh8FX@FF<m(WFF 7&V<6@F1F"4kBӫkB ,7&V4<6c0FAF".7 F! "% FQFJF gFHP bF F` RFKF6@F) FQ(FNXF 1F"[ oO0o-O8F  FF<*𐀸& ΀N@*<F3F>%ܰB~۷ бhXy{0[ D)FHI(eѷѺ]H 0Q7+E6 *;H XF0 ԺYF㈤0hX6y`@ к&)FZF0FFO0oPFhpX FF50F!Fbhr2#z!F0F5mF FQ+j"`0Fp8FhXsF0"v@)F "8@n8tD1FP 1Jj i0+!!8" F" 0 #* B٘C R P)q%0i*F F Q-OtDF0FD 0 1FF@H͐+8 1;h# 1!(i *CN3Oq@(i "ؔ81+Д0"@0CE#,S`JBB,200S`.@H Πt4[y+% Ұ H3` ..&&t$Ry* ٴp //''0 B3 0#H &K# fDN`F ,րJh 2J` 1FNh6N``BDpG Kp`(BcB  8!B+6#$aдpvypvy=ۚB; 8!B8T"1D""!!)8:"(i F BҔ1# 1h!#O󠲸 BF"!!tdF1 Fi 11j i0"0)1+!! F(iv0T# 2D# tD1k 0B00t4"Oq  !! ! pGt4 `!d!  J`! `(!JeJhe d Jd!d ! e ` a Ja a a b Jb b b c Jc c c,!e0!41 fKfpGtD,QB0QB4!B;-9-7*3 /. *)*'О."О .41j,h0+>F*F*F1Ft4"&i F~ o-Ah$#F FF "hF9F9"w . .+r#h? F F!} (F <o-CFjFi FF#jFiF\yD#jAH0F##-=;p#-%{poOBFpppGKzSBCppGp$F%Fsx5CxB FpB8   Fqhh F!"@22=L3PP@ P@Ln  $0H`l   Iwwvuzu   $ % & ! ' ( ) " # 0 1 2             ((8HXUPPp@- ffffffffffffffffffffffffff @w @e4tVe4 $0H`l $0H`l  7.45.98.50 (r688715 CY)reclaim section %s: Returned %d bytes to the heap Memory usage: Text: %ld(%ldK), Data: %ld(%ldK), Bss: %ld(%ldK), Stack: %dK Arena total: %d(%dK), Free: %d(%dK), In use: %d(%dK), HWM: %d(%dK) In use + overhead: %d(%dK), Max memory in use: %ld(%ldK) Malloc failure count: %d Stack bottom has been overwritten Stack bottom: 0x%p, lwm: 0x%p, curr: 0x%p, top: 0x%p Free stack: 0x%x(%d) lwm: 0x%x(%d) Inuse stack: 0x%x(%d) hwm: 0x%x(%d) In use pool %d(%d): %d(%dK), w/oh: %d(%dK) In use - pool: %d(%dK), w/oh: %d(%dK) PktId Total: %d, Free: %d, Failed: %d mwmdUNIMPL: ra=%p TCAM: %d used: %d exceed:%d FWID 01-%x flags %x TRAP %x(%x): pc %x, lr %x, sp %x, cpsr %x, spsr %x r0 %x, r1 %x, r2 %x, r3 %x, r4 %x, r5 %x, r6 %x r7 %x, r8 %x, r9 %x, r10 %x, r11 %x, r12 %x sp+0 %08x %08x %08x %08x sp+10 %08x %08x %08x %08x sp+%x %08x hndarm_armr addr: 0x%x, cr4_idx: %d busstatsAXI slave errorAXI timeoutAXI decode error errlog: lo 0x%08x, hi 0x%08x, id 0x%08x, flags 0x%08x, status 0x%08x pa%d=0x%%xpd%d=0x%%xpdh%d=0x%%xpdl%d=0x%%xgcr%d=0x%%x%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02XUndefined error %d %04x:  `d'$(,04 p44404 4H4444440840X4084 444tuvw4440h4n34ܺP44ں444444 44BRCM4_TES4T_SS4ID4440h4 (4ܺ444444Я4444BRCM4_TES4T_SS4ID4440h4 (4ܺ444444Я4444BRCM4_TES4T_SS4ID444 H  @@@ @@ @@ ,@@ (,@@ )1@@ 2?@@ @A@.0  0  PNR[T^`dddGGddd0 @` ddddddddGd`d@<dd `d`d'`d d'`%d2`(dL d?ddFd `.d`ddd@d`d`d`d`d` d` d`#dd `&d  d`2d dd|`XdBRCMd_TESdT_SSdID``d9dPd`pddddddd dddddddd dddd"d.dddd:ddd"d.dddd:dddd`dddd`dddd`dddd`d7$7$d7$7$`ddd`d dTddddddDdddddd<dddTddd4ddDd dd0ddd<ddd,dd4ddd,ddd0ddd,dd0dd dpd: d(,d dd`d8dd,ddd"7dd7de,d.7d/dnd dnd3,dnddddNd 4ddb'dBdddddddd`Pddqd`Tddqd`Xddqd`\ddqd``d`ld `d `Pdd::dddddȯad NdddP`[dd`_d Ndd`eddddȯdd,@`ld,d`odd,d dDddd@dFdPPdd `zd @d Nd `~d Ndd?dqd0u`d `d`d N N`d @d dd8J`dd`d`d`d0u`ddX`dd`ddd`d` d`d`d`d`d`d`d` d` d` d` d` d`d`d`d`d`d`d`d`d >>><`d`f `d`d`%d`d+`f`d<`f4`d0`f,`d,`f(`d(`f(yquvuqx!wxxuuUxt]xWU RPPs)ts5wrIu)uuPuTV7T)T}QPqqpQQssR1sppRrp(wl0:dma0 j1ȍ j1. j1  j'vb  j C  j.P2I@8B<>H?;^BA9I$K2XM0| N 0] (a &fffe $N0u  @$I3>V2@0( $Nboardflags3spurconfig  j;  j1 z4  j@  j  j N  jRSSI %d thresh %d chan %d A-trig %x BG-trig %x rssi %d, score %d > %d? is_secure %d wl_rte_iovarspfn_add_swc_bssidpfn_gscan_cfgpfn_ssid_cfg6<® 7L7 Юwds%d.%dwl%d%04xwlwl%d: %s %s version %s FWID 01-%x Apr 30 201804:14:19     ap sta wme 802.11d 802.11h rm cac ampdu ampdu_tx ampdu_rx amsdurx amsdutx radio_pwrsave p2p mchan p2po anqpo dfrts txpwrcache stbc-tx stbc-rx-1ss epno pfnx wnm bsstrans mfp wl%d: PSM microcode watchdog fired (%d) at %d (seconds) wl%d: PSM Keep Alive (%d) # %d wlcmin_txpowercustomvar2logtracepm_bcmc_moredata_waitroam_bcnloss_offroamoffl_bssid_list˰*Q'@e@ @ְ߰Z flڇf`<DLt2018-04-30 04:06:44#nCLM DATA 9.10.391.29.4ClmImport: 1.36.3Broadcom-0.0?d]cntrydump_info %s:------ @eventqXm22333iemLhL3PL5XL6LZPPPoPo Po@@@@Poierlqnoise_lte_resetrssi_monitorG &ίDIRECT-C2-G  8*rL9S)s9l q v {      `0 lH$8C7 TG^v@erzQRSZ[@ҽ@@޽@@@(@@NBYCdEq@@()ľоCܾ鐈@@@ HH&H3HBHPHYHjphycal_periodnoise_meas_timerphy_mutedpavarspaparambwversromrevphy_glitchthrshphy_noise_upphy_noise_dwnphy_percalphy_percal_delayphy_force_crsminphy_rxiqestphy_rssi_gain_delta_5glphy_rssi_gain_delta_5gmlphy_rssi_gain_delta_5gmuphy_rssi_gain_delta_5ghphynoise_sromnum_streamband_rangesubband5gverant_diversity_sw_core0ant_diversity_sw_core1phy_oclscdenablelnldo2phy_rxantselphy_crs_warsubband_idxpavars2phy_dssfphy_ed_threshphy_txswctrlmapphy_sromtempsenserxg_rssirssi_cal_revrud_agc_enablegain_cal_tempint_ovr2temp_comp_trlossphy_ocl_force_core0FJ  A >>>CaHaH&  qM A0^^Ue {ÐÐ9 y)0$S.aHsv}5MyM &A09`jH&5MM+ &x3V@f A0aH>DZZJF l:h.$GByB nAm a HdfUQ@Q3((a-MM=p4,s#^^P^]6_^]p_^sc_BYF$zxwю΍̌("H{rS[ 8v\ެʵ:Ǒq}OkS[+8s@ , @ p@@p@ @J@JdDJDJ@k1a@u~y O+?Q/ +%g,,4Ate#A-46:I$$%L%$$5%$%5v>IKQe2"63z362[35<3VmbqNOpZVZUiVZU4VdU> 0`` 8 7x@p < @JDO:DuELDDD8I=EqEsEND4ML6@JDU @@ #2Gd eeIxeBey efddndw:d@d@cucjcb #2Gdddddddd      `(444 @@@@[lZ@- [@` L }d }{ ~}{ywuspmkpmk4Nh4h8N8p h8p@88ll8""p8l8l<""pp  Z6lDlD`8DT`pD*`**nn``88*nnTTH@l00000000000000GHH I IJJKKLLMMNNOOP@1@1@1@1@1@1@1@1@1P1Q1Q1R1R1S1S1T1T1U1ZZ[ [ \ \ ]]^^  -@  -@@ r  B ;  jkbcccc c d d e e(e0e8#+3;;;;8;55  55 5  mm m(m0pkt_filterapf_size_limitapf_ver[j % ,Bprot_gprot_n $0H`llll  $ 0H`l $0H`l      WX      (d,,,,,,,,%s: only support 1-stream 11n_256QAM for non-11ac compiled device! ratesel_dummyWXcdef      (2<    (2<wlc_ratesel_filter_mcsset@mimo_psmimo_ss_stfstf_ss_autostbc_rxstbc_txsiso_txtxstreamshw_txchainrxstreamshw_rxchaintxcoretxcore_overridetempsense_disabletxchain_pwr_offsetcurpprpwrthrottle_testpwrthrottle_maskpwrthrottlepwrthrottle_statespatial_policyrssi_pwrdn_disableratetbl_ppronechaindutycycle_cckdutycycle_ofdmdutycycle_pwrdutycycle_thermaltx_nsscck_txmodeswdiv_statsswdiv_reset_statsswdiv_tx_weightswdiv_cell_policyswdiv_rx_policyswdiv_tx_policyV@^@jv@~@      );J]0ir@!@h"#$ idsuptpctxpwr_target_max3txcwapi8sdpcmdeveʀʀ?]?%ʀ]G?Iˀ?eˀˀ %      wl8f횁-͚            9 9    9 9 9 9 9 9 a 9  9    9  9 (#@ 0x(#p`x93-($ ;uu;uu++u;[u++a;[afF l s z| tWV }=!2DW^k-b@  @b-k^WD2!=} VWt| z s lF f a [f V1Q Mp`@ܸ 0XH@ 0(#@ 0x x@h޸ 0XHH&}=&6.,31@ 2@"8,p`XpH`@ 0--zH@@@@H@@@@R@@x .@@.1Th\5h\R\h\bb`^\ttE\ ( V+\3@3V'uX}.@fH 1nr.keH>h\R\ryr.1=z=T?DDrr(h\5r2 @ A X p`X@H 0@ 0 --Q@@w%L%t  w%L%t  35j5 55+6 @ k)w%L%t  rrbB$H$ yxA$H$ ??A$H$ x : v0D&L& xxUY$H$ xxMe#F# ?? xx_#F#   $$ xph`XHH& @ 0xhXHH&  "$&-CFF6!(F>F(Fnii .F.(FN.F٣h#`h.C`٣hC`.(F0F#C0##M0#h* O& @s0IF*F#G6B۽>-CFFF F!F F"FFI@h "SCPU` F$0 MC.` F+h%$03 2+% F9F(Fl8L!H" FJ# %I" +PO#cOcK c#dKecied`8DEBG$Ci+pGCi +F I"F F!@$iYF K"hI F"#F@hDyK`FL`3|B$ K  H`#` H9` H ` H` HR` J`D`KATS,Lx(! K!`"@d-GM)FFL `O HF!OF8`NhJF! h!;h"`5`PF!h)0 <O!8h(>F$ф !L `б!"%#B=8h!hOc)0 h2!%`0h DtosFFFi!h F K"huF#i"h F+FG8Kahea"b` O0|8-C F!FFQF N0h F#0h!FJFC0h#@`` Jh` J)`h0h C`9F; o8pH!F)K`Kp``ci"+iX@'" FF FK!` F OaF K( @7\Lhys7K7L7K! " Fh&i##`3K&ahaELHQ<9 F.H;cs! ((M)L(`g ` h) h<"K hh2` Kh2`Kh2`"HI"HI"HI"IH h h h)(h@ h|ޭ$8H\D8,L%({}ypGpM,h, !FF(`!F"bO`!F.h:`(hh.` Ob`!F0FM+hJ F`JSapO0pO0pd|$pLF#h3N3h 3h#` h#`0C`#0kl;+(F I Kh"h0 h#0HI"h hp|d1Ta#F" I! F" FOQK" F`@!T8F FQ K` 0Oc`8hKFhhpA ,p` 0#HC+ Ctal34d#FB!h@h#3B  pGKJhB` pGD-AH#4ѝBJ5Fh"\ p2BўB)=6&# "2bEт pT0B[R 0B.]#\T3B"\T2BFO0 -GKL&KOGF)#h# %  0B 15- FcKF 7  zB 5-6 4FE۽ K-GhMhO #J &DF(F+46 5FE"FOU4#HIFG! +A18BcFce% #k+=8jCCbpGj#CbpGhF$Fbb$ࡲ(F"4B-ANKpOK(FFF]G!@F:Fa@F9FwF! H2FW H1FmU! F*FM F)FAa BK-OhAI(F@JAKh@JZCq BF(FQ9K hF*؆&O1LLch;+أh , Fa8jF  !' F9Fm |h"h0"+ 2CF(F+"h0"2+ 2CF(F 4E(FO! !-CF FkH F:xpOzs0gO8` F.dKeJaicJ")`cNcMiX3h+hc30h+h")iRbb2hE")iRcc3~1hF`i*h%"(i[cc3hE"(i^cc3=Z:h@8K2`Ozs#5H@` l9h#:BF@@fU@O&J`&K@2`#j+$KȿoB`ci"+ iX @'FKl FI "# I1M(`x + F-hsOzuECKe`0H?B@Bh\U K!hB`h"r` JhCsC3`K"`CYhZ`K "`pG$pFF_ FF@*F FQiCi&BBCC"B#Ca)FCa Fp@K-CFFF F7 FAF2FF F, FFN@*F F OFi3@FM6 @:Pp>@F-0C` F9FC-CF F@"F(8 FF F F F/h(F%(@? OIBع? ?./a .+l@c@oEK ka/1#1@*F F=MF(`1FF:H Fb8K`+hhBr`hB`"!bi'*!B@!@V +h1>! F FOb2! F F@+! F F@)$ F! I FFz@*F FLF F#@C {aH0 F1FE+hjBb!l=t #1 #1111#1#!1#1@! #"1Oa#!!"!1#!"!11#!!!2pGACBD0 XB@pG pG8FYhF6#2 F(F8F# %!"%#h6F0RO60Fp-AF FFF@7 cim*?8FFD6FF*xBre@6 cim++p >0F-CFHKFFFu(0O pF()!O rh` FKhb6x6&(@F!A"f#8F)FJF`( `hgiJ{hI+Fz1@)E``hswwO0  pF$`b(dO x0GbI"Fw_I"F. F (@! F0`jG F!h+Fn a(! F FQJ#}1NH&%#@KH1EI  1;! F@J Fx >I(" F(5 %*R6I R4H 3I&hOs  O@r F# #=ci"ogOs F#cig!I"F!HV H KrQ`2` Y`q`Za F$F F t#І91-:8bZĀ-AMĀbMx8%FyQi Fh)F((}hh2#x F F8@4ihh7 i!4"Khcb$b 5ˀ-G'MF+hF+FF@FP F(:!P"+hH'a FAAJFCF` K@Fh{hu+ha! J0Fs H1F+h3+`$F Feˀk-AOF;xF+F&T F!T"\;x"D03;p#` L P N R d F0d@!"?&0F0F&Fk#SbkSbhJK~pYpQpppG\H-OmGNGM3h+h_DODI8hX(z+h0$#h008J 0 5Khh 4I0 h aF8!F*h8h-J (I)J`` `O21<`@,`@@>CB)*`!hJ`"`  `I  ` I`F `1*h0!FO\@<!!!ݺ!8!!!pGwK-Oh;+tKhT!Fr F!>FX F-+j+ F'OC+b Fk"F F@ >F F:F F6F FF FF FF FF F F F4 4BHJJBEB@ BJ BIxBGBFuBA BLp | z ywvqf.K *I+J+H &H@ D28"H@)D2 J KM`% FD3OrBFF@HI(!MAK(Fh[hG+i(F[hG F`)F F!!@BLx FpG-O0 `cF q"# F c(F Fl" FW@aN: >@@;C6 xBO@sBJxSOS++C*x O: %@g3B   F F(# X3@SB@ SB@'B@P1FD#pD# F' " F F(@7GE  ' F :F;Fw F'O F@#  " F F`(ѹ +@ŀ+@_@𼀙F !'!  " F ;F4`/ _ 27(7FO.F%#   F BF+F 5-uE5F>F'#   F :F#([+X_T' D# 7WE'9#   :Fz F# @;CB @5B p3 3tp3_Ѻ' D# 7Bѹ030 B#0p##pOLtI30B-C'FFFFF 0F!"7FvOEp FFرѱhƱ˹s+is #s1F!# ;#(`popop-O FF48F(W+T)R*PлMЛ0+I@FF(Dй W F8@F!F5OF!$" FJ"`c F#ICcYF#q Ѥa 9F2FSFfhca+ 3+`oo-CFFF*-(+)) UF@!"`$'fHFGF0 FEo!JF F@AF:F3F$,` oopF`hT%] h F5`(Fpopop$ F#F5 Q)#`1!` pGopG-AF FF0F(F!F.{CEӳ (F#!F;FoFh#@h h#`h F@-AF FFFF!"OJ'`e`#(F !2FFX J (F !BF F$ FipG@pGi"ҲBBBCa#3i J(ړBB@ppGOppGOppGh#diKa0,Ŀ0~0@ɿ-A$FF%F@F9FOsBШ@5C-F F# #pG9)  #C@##@#COs `#C@#Os#C@# pG9 ) @# `# ###OsOsC #BSC pGopGpFh!Fh^hSi"+l 3F1FPm8ppFh FF0 F)F2Fp@if5pFhFF!Fh*:FF F)F0h 9-OFFF)qp(ppp4pppppp;. Ōŋi.3hB3ӧ6.  ŌEi3hB#'&iOo3h+هj7ŌioŌi@5`o3hB5`o ht!FhOF  FQFh) EѠhYF os#00hF[i F'+i ;+Ob@ #b$+'+#+ #++#bi#?OCa#3i*.JړBWBU+ija2 F)F(Ki @Ca@s"@. #.0j 3# F 0ci F)Fj ࣋# Fip@` բj F)F2 `#|CiF++<(FF(6(F(3(F1FF(FFkiF0+ipA i` i# + FB F F1F) F(F9F$F FChhGChhGs&FKL"1FFci++`+Bh`khӱ` F` FUF F!kh FiGF6 F1FyF(F|-CF#FFF5F F!d F+x F%X FPCh9F^iBFKFGFoO6% F)FE0F`A``pG-AT,FF FFp9F"F ,` `(`ohF)E@hCFУh;B `6`h=!@gh%h!(F:Fh]=+(FbhGsR(Fchc`h`+F+F*ahBӣhp`chc` @pG-O+OP&(7ORr!ORhٱ x˱Dh+:`DhL<+D8 h8#0O2#"Qk#I\_:Ҳ*] \JҲ*؀" F_%{` +(+ +Brd")50Ӏ)BjgZx]+ݼ4"FI7 F I7Obx]7I xx7I<]8 +/0+B/]+B+ F?(B!0' F1Byy yy7IC"]+R#qU 5I?;w!aog???? E Y }!A#??$ue_&s&&&?iw??ug)&) 7 u)6????'1's'''-(k(((?M???W????17?)*,,-...01922O713m4y567o977788%878I8888>?????????(E)??9)::5;a<s<<<=>O _O>OU _OOU _Odx7I"F}x"yCcbx7Cx IC"m6]xcxI7T"yx7IL-B򆄢ycy7IA-B{#zy7I6 -Bp   3]7I&02]7IXxbxQK"pOF$CF!{JCF!yJ/cxxC"7cyyCcx7C"y/C"40E-7gIbxxbx7bI xcx-D#yx [C7YI-ByYy- Dzy  C7PI -BzYz - D{z  C7GIл7EIbxɻxbx78I5#𹻣xbx7:IB"t𯻔#yO JJjcx J H xO J*_O$CD!"J/0!CDJRF/7Fx"yCcbx7CxC"8  <4E0ۛDe KpOFIWw1{CF!JCF!J/x"yCcbxCx7C"y"zCcby7Cy/C"40E#yO JJjcx J H xO J*_O;CD!J/T0!CDJL0!CDJ3DRF/7y"zCcby3Cy7C"z"{Ccbz7CzC"  4̑E0ۛDnK "pOF>CF!dJ3CF!cJCF!aJ/x"yCcbx3Cx7C"Hy"zCcby/Cy7C":z"{Ccbz7CzC", 40E`x"yCcbx7CxCIC"Pxbx7?IB" FO _Ocx!7J/#ybyCcx7Cx/C"4E"7+Ibx-B7(Ix"7%Icx-BM"7!Ix-D"7Ix-I7"#y!bx7I7I"x7Ibxڹ+R#????Y'??Y'7IbxY7IbzR -O OO7IzC -ٸOO I 71"7I 0* -ٸOOO xcxIID7 4 -BIOLDD$  0!F7 4LE.---B'tI 7rI 77oI 7mI|FFO%FxkxhIAD7 5MFO"zy`IAD7 4!$ 0XI 7 4!,  Ӹxbxx!y7ayyy!zKI𿸩FO%F?+7EIBFuѹ MFB[x+7;IBFa -B[x+72IBFObx7 x+I@*I<7(Ix6qxbx7%IB",gx"yCcbx7CxIC"W7Ibx-BO7Ix H++ >?A#@|2]7I2]7 I2]7I2]7~I|2]7zI2]7 vI2]7uI2]7rIۿ7oIbxԿbx7lIx7jI7iIxÿ7gIbx7dIbxz F(A0 F'3AZyy𖿢xcx7QIB"Pbx7MIIx7LID#yx7II<w7GIbx5p7DIbx.ixbx7@I$_cxO(D:IO"7b 7I7 4I7R2I770I-A3#yx 7*Ib 7'I7%IR7"I7!I L>,?\$fJM$<1;I"cxgI7OeIx7"yx"`ICF7vycy"#YI7i"zy"7RIF\-Abz7OITz7MIOz7LIJ"{7JIE{c{"CF7@I8"|{"#79I+|c|"#73I"}|"l#O 7/I }c}"l#O 7'I"~}"l#7I~c~"h#7I"~"7h#Ib7 I"h#<~"cxI7OIx7"yx"#I7ycy"ICF7"zy"7IFz-Abz7Irz7Imz7Ih"{7Ic{c{"#7uIV"|{"CF7nII|c|"#O 7gI:"}|"l#7dI+}c}"l#O 7\I"~}"l#7TI ~c~"h#7MI"~"7h#EIb7?I"h#xcx:I7ycy#y7x4I-Azcz#z7y-I{c{#{7z'I|c|"|7{!IԼxcx"CF7I4E¼xcx"CF7Ix4E2J'~nZkxcx"l#7IG4EOU _   DD O"x 0"h#7I$4E\xbx7IRxbx7I Hxbx7I>xbx7I4"yxx7cxI"zyy7cyI"{zz7bzIxcx7I-A#yx7|I"yxx7cxuI-A"zyy7bynIһOE˃"yxxIFcx7~4  OE"yxxIFcx7_4   HOE"yxxIFcx7@4   u OEn"yxxIFcx7!4   VԐOEO"yxxIFcx74   7xbx7I-xbx7I#"yxxdx7I"XLnZH"yxxdx7I"غ7IbxѺIbx7 I 7 7I~-Ax7Iv"y7Io 7Ih 7I`7Iy[𖺔cxO(DO"7wIKc" 7tICs"[ 7qI;s" 7nI3"[7kI+"7iI$#yx 7eIc" 7\Is"[ 7YI s" 7VI"[7SI7RI".xcx7MIxO."sD7II!zy cyzbz O.sD7"?I"{zb{7{;I"|b| {!}| }b} !~} ~b~ !~ b   "! $#  & %RO. 7I"sDt𯹓W/aji/0yFcxO."sD7I;yby x!zy O.sD7"I&zczz7"{I"!|{ c{|b| !}| }b} !~} ~b~ !~ b   "!  $ #RO. 7zI"sDcxO."sD7pIyby x!zy O.sD7"fIzczz7"{bI"!|{ c{|b| !}| }b} !~} ~b~ !~ b   "!  $ #RO. 7@I"sD^bx7 -<ѣxbx7AI#yx7>Iyby7;I#zy78Izcz75Ix"yCcbx7Cx/IC"!"{)}a2B}QQ7"I0#7 I' + IT8)7I#8#;D8kFo F;!WuL-OFF!"F YKx,@ki#+ "(F!F#F&(&'F'& '&F(F(F((FQF@ (FF8 F (NF(nлл !(FSF RC-(F!"F [ (@"Os:B FuGbW"C# K$&PF2FCFP(Fh K` F;J#p `o 0FCL%`%`0@,F0 F0K"ppGp N F0h IL$ F!F43hBK(F`pO0pޭKhF2#3B# ` pG-G FhFFF"!F$p F(2##p 0p3#p<#<.FO< gp&PFAF:F~0ch+ o x6pchCa#``3#NE #c+`O0F F% {i0Fc`#{ap9Fx5gh/# F[#c]eHp'p8F|+М3a``t O0-C&Q O HF FPF(;!JFg値`!F"F#O0a32BVO2{ZhZ`#W'"O5`21BCO3@7zhS@{` FFCk#Ob`CkkKOb`kh8 pG pGF 0[pG hC@3 `h h@0#@3 `@1HB@pGAk k!j F-G  FFFF9FBF+FF#+h;_Cc_@  F0PF1 FBF+FGضPFp#) F l D0)F0 FjAs)\BO1OQP (@н0mQKCe`0ccf+BO1OQx z0% QKC00 d0(Fp-O FF @ LF(y!"K!F F FU 0cK!+`"04(F" #'0bb?[F# 0D0Fp0H0l`0 +EЪkh#`k`kO2` F@<Bj( j(j (ѫkO2`kh ZhBAr h h`R h@s0Mjkh#`jk`kkO2`j@<Bj( j(j (kkO2`kkh ZhBAr h hr h`R h@s0bh#*00Ѣho@<BOCOB 00000 Fd@)B Fm Fi( FT@4B F] FY(#10(F1(Fh #/D0 . #Hl#D0O Fdh!"FN Fhg!"F{'(F!&(F!0[10CmO0O#0(F%(FF0! F F FZ( @  -GF&j .fj ̿x"v OK1(EїE_:*5%.ci F"+ iZ@'"\F F!Ob`ci F"+ i[@'"GF F!@db S%05`벳BxE -CFF+CjYO)U<> ' FG("@U<Bci F"+ iZ@'"F F!ObI` ,"*2uDci F"+ i[@'F F!@$b-U<`]ci F"+ iY@'"F F!@$bciF"+ F iZ@'"F F!@$bU<hC-ci F"+ i[@'"F F!@$bciF"+ F iY@'"F F!@$bU,h#07OEc=.SpIF j(1 IcIF ^IF YeO!F F"!F F^ci F"+ iZ@'"<F F!Obh%vOzpEci F"+ i[@'2FF F!Obgh5vzpzԀOzp "!F F#!" FOzpci F"+ iY@'"F F!Ob2h&Ozpci F"+ iZ@'"F F!Obh6zz F!"y)FO+F Fw F!"+FnspOF)F Fi"!F FOzp"!F F!"+F FOzpci F"+ i^@'*FzF F!Obh%Ozpci F"+ iY@'2F]F F!Obh5zz F!" !O F F F!"#p@LpPFSBF I#BбO ##*#<#!" FOO!F F * F!O#@jFj+̿xFv %;!hFJ+F iF(.! FBciF"+ F iY@'"F F!Ob#`ci F"+ iZ@'"F F!@db`5벳B-j+FFjf vv %;!hFJ+F iF(.! FciF"+ F iZ@'"F F!Ob`ci F"+ i[@'"rF F!@\b`5벳Bd j+FFjVv%;!hFJ+F^ iFl(.! FciF"+ F i[@'"5F F!Ob}`ci F"+ iY@'" F F!@Tbh`5Bs HpG:-CFF IFF` F9FOzuF I(( ЃKJ(FF)F F F!F FhyKF.K#9F F2F+F -F(7ci F"+ i[@'2FF F!ObhOs@| ?BGCci F"+ iY@'"F F!Ob`)FTHS! # F9F+F - FJFBci"+ 6.t3+piZ@' F"VF F F!Obhx|W5yx-pep!Ob+C Flsy!-JC3 FchoB!@ F[ci F"+ i[@'"F F!ObbhOs5@x5=|BECci F"+ i^@'"F F!Ob?`& FAF0FD\t^h-CF# jGj+̿xF FF & !3J3F  6BN  F)FBF#)FJF F F)F#j+,ci F"+ i^@'"F F!ObciF"+ F iY@'"tF F!ObhCc3` F )FBF F)FJF#K( --O%FF)FF FIF(F`H#`3)F*F\` IOH#!h3 F}dh FKgjBK %!%FW? ci F"+ iZ@'"F F!ObG<=`ci F"+ i[@'"F F!Ob/X<`-G!oJ+F (:! F!#jF +ݰ?òO(CHci F"+ iY@'"F F!Ob`ci F"+ iZ@'"F F!Ob5B F1FKJ#Y%>!HJ+F F(0ci F"+ i[@'"lF F!Ob`ci F"+ iY@'"WF F!@$b!F FHF5B FRF;F1F% F(8C F*<Cci"+ F iZ@'*FF F!@bgciF"+ F i[@'" F F!@bRh:X:X?t:++ci F"+ iY@'F F!@b+ciF"+ F iZ@'"F F!@bhC+`ci F"+ i[@'"F F!Ob`ci F"+ iY@'"F F!@b`1FRF FTO` FYFFFF!F F1FF+F F F1F*F F9F@8jF+-Ci"+ iZ@'"VF F F!ObciF"+ F i[@'"@F F!Obh#s+`8,Ci"+ iY@'"'F F F!ObnciF"+ F iZ@'"F F!ObYhCs+`8pG pG8F F(F!F"(F!F8@8F F 1I @! F>)Fò" F F)F"#a (IH! F*)Fò " FR "IH! F)Fò" FC IH! F )Fò" F4! FOxbO8c! FO`BO CO"!F F"! FF F)F8@պj3j "8jF +iCi"+ i[@'"pF F F!ObhSci F"+ i]@'XF F!@lbOC`Ozpcci F"+ iY@'"=F F!@lbhci "+ F iZ@'"&F F!@lbnm#`BEHud hC8 8 88!F !F"e` F8 pGF``` hch` a#`#v8Fn L!" ` h`I"h(F8@zXj-O FQAh(| F 2pҲCF9x=F7=)2p)FFF"27pҲfFD /phhB+x/FcF"%F#hF*;YF+BO +**'  bE\ O=   " 2JEzO DW  DE35+ѽO:FFF0 +Fh`N0#C`3h``)F F^5` oKh;Kh!Kh <@KFhFh M*hBh#+`8F%h F,F,#3`snFm0 nB@nGF% F#A=FiF F O F1FUn[ "nB`n)FG|F"(OХnm0 #nB`nGF% F!F F(!F" FO F F@! F FOq F F FK!5Os5 F F F9Fn[ "nB`n)FG9@p FF%(FhPFp5-O0pO0p pGkDX2B DV2BJ."BJ/"B3J2#3J1#cpG3DT3cpG8ACFc F)FI b@(F IbOsb I(F Ib(FI`c(FU8 {    pG0$@M"+F " 43,KB(F0g00Dffff#ffgpG-CFF u! F1F F (ȿ,0`aȿd"(0ȿ aȿa"(iY" F@'xF F 6!cb F6cb$0#bOc`O3`##aFOAF F F1B0B  0 FE)h "F F!F!(" FF Fu)F F!" F!" F!"!;F FO2 F!("O3Q  IFIPIOs(F  Ci + 1!$"!#!O0!" F-G0F4FOcr!FFO[##a`\X@ŀ FAF:FKFa(OShp!#`p bdDX2 Bc!d DV2B*C.;+ F?cl F;+##L0OQ:F0+'C}H FOQ:F;F(| F2 F9F2Fm(p-h:N F)F,2x*Bci+Oa F3IF(FT8(F/I+? #ee F Fm Fm(F%IF FmF#m F FV Fm Fm #3p F(FI8I(FF F(FI x(F IF F$FFȳ(pF(hIh"F%F& )j)#hh#+bil65chB Fp@bp(pF(<Ёhhhl8%#21hhh Fj&aAb F@YhhM5h@hhIh"F;`i%`j" FF(Fp0FOpF(EA3`01#71s813<1#31hI"F#`HOp`a `bK(h#KIKJ#FFF`hIh"Fm@#D1 Fg$ F09w`eFot`o@h{ F@-OF FFFF(O !"/&`8Fs *FFAA F3F F(~Р`+i!`@K``d@J3F'add8Ff+io(IB+io !F6J 5JF! M1F 2K2H2F 0K]F(Dch'xp! F(i=6!:F|(F`g(/ch(Fp%0(F(Fб(FgchIpKH(hJ#FR H!F FIF'$ F =B0 ͚ᖁG pGK"pQ4h AkkB ѓj+(++#@BГj@RB@tRBj"H"!j!* H"!pGjJ?pGF)h#1)h#2t49ht4"!4)h#43<)h#<5)h#5)h#7Fhh #h6 #1 )#1D _#D1X =#X10 #014 #418 #81 FP #P1L #L1H #H1` #`1,1#,1d #d1 F4 F+T #T1t #t1| #|1 #1x #x1 #1 #1h V#h4l #l4p "#p4 #1 #6 #6 l#6 b#6 #6 x#6snid V#1 #6 #7 "#6| #|6$  #$1( D#(1x #x4 #5  Z# 6 F@θjFC,#h| *%PI(FI(FI(F%.FxWvU5BF-0F #ja g m ht$pP#qt$Frt$AI0t$(F0t@ (F ;@m 8? 6C 4j 2G 00e0 ᆳEᆳ I "H J @ @ K Z [ ^ _ c e g l n o r s F(=8&!h!6 F F F $| x#|2'ji F"%ah2YY Fd5 -\ F[ C#5 F Fr#h1`he#h" #h(#h" R(Fh=F-!FR h hI"FhJhQ #2H#4 FahCx"*`0L FahF0F-O$Fh x F F HF1F F# HF1FF# F HI[()F*F0FAF KFhF(hF` t$!p0`Bj#a `J na"*&"c""AF! 1#15H#hbi`hn2|F(@L F9F- F2FCFh#zK(FyKzIzKzJ#F.#H F JFCFG (@#io(0 0T 0 #b ih(= F19F F9F F< 7/Os0*#02#06#O}b0@S 0O]r#p 70+ل#0OpU#Or!"F#2A#Q#q3+#0#jiT#jiU)F F+I( @nQjFBkAkBZ++t4"I t4O2Zdd"z t4"0 Yس2++.+,+*+'s+E#ҳ@B 2b-[ض &ٳٳ t42"z t4d"I AAB@RB t$d#z0t$I0t4O2ZdItIJtL Ft4"jxixh`6O 4i i1#jtio@z iQF*"(QF}#ji#h@=`0 0T 0 F#b#!j#@21 !s F #j ! h*"Zu+ ##O0#ji`#hГO "Q Q!j F1! F :"# PF - FW@c6 F (@^p!, T FAFOzs( F\@3 F4 F1Fv@31F FjO{s#0 F@3#`0b00+@"` b 0 "OTrZ0&"Z0=b2CSC2#jit4"tt4"t"Os@t$2x*#c#  2&!"bbb F!2F F #jO8i F ! < O 1F b#ji9# 2 F!բj#M0jM02# 2~ F!8մ2# 2B0C0` @8! F8"0 T&pl F8J;F"MٸaT&i@LC!P1("L0 @MCm FCe FOc F@s ##h IpFF+I\Q! "lh!5#7#0 #  Fl $0\F F0F9Fw w8Fph!F(h(hI"Fu F8@]8pjF8 F(1K`#KIKJ(h#FK!F(hJ#F)F" 0i1h#Fz\5 Cr3- F$ Fp9 l‡iV\‡ 8Fph!F(h0(hI"F F8@800F F(?#`! J(F K(``2K|!!"K8K|!$"KKI(hJ#F&pK(h!FJ#p(*h#`0 F$ F0W}‡0‡a0F(m BF(h#`!5J(F5K[(``^3KOqk"|0K%(Q/K!k"|,K(E+KOql"|(K (8&KOqo"|#K(+"K !n"|K(| !n"KK(hIJ#F@+h" F F0 F$XXXA‡4FPhIh"F F@4FPhIh"F F@Ϻ pF F(SK`Oq0"|PKr(@NK|Oq"KK(@IK|Oq"FK(vDK|!0"BKJ(j@K|!">K(^|!".K(4|!0"*KX|!"'Kw|!0"#KF!(FJ K(`` K(hHIJ#F F@$ Fp,+,+,+*'*)(*'E)q)(/0Q,U-Q-u.|Ç  #@" b"Bc"cde"e"e"-AOa $%fOr'Of`Da!ab$ %O fO'"0`aabAbDfdCeg0cfgBg|@$@H$@`$@0$OPP@%$0Oa0#PP PP p@p@`0  pGpG8F `#3 X#30#h#N#7#h D%R(#h:Rh38%hR+8S $#2%c25- t #t4 #4 #58 Fѱi#a #0 #0 F@ԸpFOpFF ax1FOTp}( w )F F%(Fp-AF&hb0F8 XC_(V#hU@3OpK(hb AhO~sOp78@3wOp-t@3m fj#b@CdOp@3ZOpO|sP O}sG @3>Odp2s+p2&F#hi@2@36BOp@3Op @3+`8 `Oc 8 FF(+| F)Fyjcj[j cj"b`j#cb` #`6!h!(F##` F8@8-AF@TFFFnF@37AF7:F0F `@3+`-A#J0#hh` O pIb@pb, A`b0@3@3 F1FBF+F8 F1FBF+F F1Fz$ Fth "i ZaapGFPO J#2 B#3#hIh"FL F@4HpG𵇰F@@!F(Ԁ!@B@&%`c P(!"#rcssst3"?+tt#(0 #"tbt"sr!"3#'- A(P,0`(h!u(  F. O`u`c"F!F u w#Op 321+&' FA(Q/`0p! Frc!(F2J2KBN!(F.J.KB``CO>p(;1FO>r? H(/!K(h!K!I!K"J#FKTrʍ"Fh(F!"#3+h FB#2 F1 #3PP FM$ FYkcjd_H FhIBpGvkFIJ#FhsK h# K I KJ#F FO0vkOCÇ8F4F8)F8@0F((Aii)0hh#haihl#cai ki#a#hIh"F F@½g(pGpF8 F(!8"`@#&`*0P a(y!P"R# 0!0"0#0$0%0&0'0#r#cr*0+cr3j%i Ozs###(   (0# sr Fr!0F(J(KIB`c7!0F$J%KB``,۰h!I"F+F`a OpGa)FOrK0hKIKJ#FF@3h FC[)P i% k! F$ FpUuUUUeV\ÇWg pG#t@cÁpGF`hI"Fn n F@j0Fp F(=!p"+h%`c` f(,!"|d f!d"sKI#KJKKK`h#F`#c F)F( F F$ F0d$ćhj/pFjFj(FlAhhl #d"F0FI(h!F Fp@jpS-A<#4 '#4uF RF(!"&.p,b$(F4!(cWJ F3F!B(g FF(@𕀠hOI*F3Fd(KK@FKKKIKKLJLKKK+FF(v)F hGJF(mэ!l! F2FBK-(gbx1F">KY(Y=K|9F":K(M9K|9F2"6K(A|!"3K(7|!"/Kyp|!2"+Kp(|!"(K|!-"$K^|!-"!KPIOzs+(F%(FppćSLxzyՇa-f8UFuIF!I"F hj(FT#58qFO `AF O0!O b"h +`&#ka.a!e F{J|KRBa FovK"C+tI' x *O@x! *GGROBCC,#cI'JxS *O@x! *G GROBCBC,q#PI' yS *O@Jy! *G GROBCBC,2#=I'yS *O@y! *G GROBCBC,6.e*K! h)J#Fp!x F#KHx!" K K|!"KKʍ F!"Fh FI"F!pU o oooo٪=8H‡Y!壃 qpFFBVB FBUB-BPB)B`BNBB ˉ+o;+`#oE+`#3`h0+h;+`oJ+`#o+`#oJ+`#3`0!@"!#p!)hQp!p12hp1"q1"Zq1"ڀF" "Z" "ځpFhIh"Fh3!FQ ;$h3!FQ;$ F@LpF F(7!"3$!Jg0$!J ^Fํ!(FJK(``K(hKIKJ#F%` F$ Fp/.'/Ƈ'L pG)pFFK!F0 FGpKP1FF FG F!2FG F!2FG F!"G FOq"G FOq2FG F@2FGpІl 8(؀#3pG pGoN0j+ 8(p` (x(  (  F kAABѢa9)?+ @ AB@!ABP+  v0F;KIh^#v0<'@'p FFFF "!McC+mf#Cc#0BPB[+FfpI F q 8 "! 1"rF  a# 1pFF$hi8KhG0F!F" 45,pІ-CiF o;0b(s o4pb(l&7F!hF7J3FEiFR76@3B7.ID(Cи0D(G#&!hF$J3FiF,DiFD62΀6@3BI DfPID6"pp0poXjP#À#C oN f -Ohh+hi#FF !J3F@1yho qFh(& !J 3FosCFq XF hO9hPF 1F(*F{K F!#*F F! #% !sJ3F c:h0PF osF(ǀ:FeK F)F:F F! !^J !3F 80PF o s F(:FPK F)F:F F! p# !IJ3F 0PF o0s F(s:FpZbh*F#p!olF D* k l( Zl L j N k"mbmZhh#>1  8 C    p | [    7Os81F O IF F,0 ""`+j""`o\1#C{Jf#gl !#0;0 F9F,AF 3F$#O1 F 0nXjT0"Xj 34$<(0 Xj3$.0ڋ7#)jXjaJXȁ"@0؂ F9F#! FUDI0Fo:BI8v0Fo4#m8` cmoiiiXn0F3I=01I0F F F! F!o Fo'I(J#E F!+ Fn#41Fp0F0F#% Fa(Fl+hxI"F+hI"FP`i0+hK0G(Fr#h  IIІF((hIh"F#j Di>i8ci2#i, F@th0iFXm$0&F(8FC$[` h 0    Occ` K K I(h J#F F$ F0}vĵ(Ahhi@mBh.C`5`Q``h`Y!a`o(1iq(iʹpG(1ie(1i´sFIF+hORl/ (F!F"3FP(F!FF o0F|(F!FHFPhIh"F F@ iFt eF(a#`!2J(F2K( dT(F/I"F(M-K-K,K(h,K,I,J#F(;*K|!"(KP|!"%K5F0,+i!Ig9Fo"- 8p9pIy8IO?#?0 F$ F5yƇ   0F(@ 1hh# 1#hh/ "$" "ChZ 0QEh1(#h$(hD1D(#hIh"F F0_0FOpF(l!Orw7K%`6K7J#(h4I4J#F!(T+jh*[}+ #0#0#"D0tѨh)I*F#7 (9OzsEsR1!(F(OqJK(0K|!"KK|!"K@| !"K F<$ F0]LJ_M 嬄ᡄɳIF01 F@1F$ `FChIh"F1<4 F@-AuK'`uKhF`OpF(؀9FOr`0F\AF400FF< FDF!"D!"p|"9Fw3h| *UIFX"G!ܐOI NI NI (FLI"/")3hFI0Akk`Bћj+А+ (=I"#`0AkkB ћj+ 5I" h+#`0AkkBњj@5B*I"X(I"(&I"#`%#H"PPPPPP FK0h(KIKJ#F( F\Q,F Ft| 9  ʇ gԇʇههɇ0F FK`Oq"|KK K K(h I J#F9 F0 F$-i>0hFIh"F F@pF \F(c`&!(F3J4KuB``Y!(F0J1KB`N(F-I"F(G+K|Oq%"(K-(:'K|Oq<"$K (-|!" K$(#|!%"Kй|!<"KKKI(hJ#F Fp F0$]e Q  %= l:8hF"F(hI(FI"F F8@:FIh"0 K#F I J#FhL(O5% Fo(F0E8"-CF8 FFFF(8!8"o$@!J F F$%K` &aI#F0FJF`h I"F0Fa@ i I"F F,F F[} PFI i"Fia#}#h~##uhi#ah $S FU  7F8 FPO3`IJK^ F>888pF ,F(8!"&%`!F(FJKB`!K(hHIJ#FzK|(!"KJ@|!" K+ F$ Fp;;: ;m;;Fy#h##q#hIh"F F@ʼ ļpG7F F(U-K`@?-"|*Kl(G(K|Oq="%K_(:$K|OqJ"!KRp K|!P"K|!-"K.й|!-"K%|!="K@|!P"K F$ F>E?<?=<?%<>;<]=}=<Fho"Za=8`h4 F@/-AFOp FFFF@3```( g@3X @,00 x``O}s@38F0'#0`a8F# P3+pGOcL6h#P6OsT6#X6\6pGFPhIh"F F@ɻ-Oh hiFEFNJ\ځy)\2MU2E1BӁBO727PDEE#D BF  " 011F"F0 12 )  ! 1# 3#ooo X-G(,FFFF$V !8F*FCFe4 , -OhhFiF ENjPڂy*P6727PDEED BF  " 01v1F"F0 12 )  ! 1cFI# 3#oo -G(,FFFF$V !8F*FCF{4 , -Oh hFiF "EnjLڂy*L6727PDEED BF O 1F"F0 12 ) cF# 3#oohi % F32"4 OqjC!@APOr @Oq@aOr @00Or@YOs@Ow@78FF(!:F0#c3hOri&`3@!1Or @2bOr@!1Or @2bOr@1Or @2bOs@3Or@%OW50cK)" FK("5 -%W50S)" FK(5 -K!0h J#F F$ FXAA1BA-C(FFFF$V !8F*FCF4 , -Oh(hFiF *EǍLڂy*L6727PDEED BF O 1F"F0 12 ) cFo# 3#oo-C(FFFF$V !8F*FCF4 , -GFF$`F%  B E҆B5BѪB AF h aJF@FQF:FfU  #(0#07%K|VF@?(F"!K (:K(FA?Q@"KxK(F@?"K K(F@/"Kvȹ(F@"K(F@"KN8(F@" KE>L)M[WZWy[XXX=I7K|VF!(F" K K(F!" K@K(F!2"K>qR9RRERUR)R7%K|VFOq(F"!K|(:K(FOq"KpxK(FOq2"Ke K(FOq"KZȹK(FOq"KOp(F!"K0(F!" K>1WTmWTVmTVYTVTMIV7K|VF@!(F"KK(F@!"K K(F@!2" K@ K(F@!"Ky>\\]\\\\q\7 K|VF!(F"K[0(F!"K>SRR7|VF!(F"K(F!"K(F!" Kp(F!" K!0(F!"K>Y]]9]]!]FPhIh"F F@;8F F8! "q #%` F8(hڈ:ڀpG JF"J I JhJ (O0 Q4<VFIhFHh!Fh F@v7F /F`" !(F KJ(``K(h!FJ# F$ F>ݒFhG#`F 0F 8KKK(hIJ#Fh FV F! 2#b&#cb Fh$ Fp1̅̅̅ͅ=υ̅i@i۶@i:iնi4i϶i.jɶj(pF DF K%`E` I(0h J#F F1,F Fp8+FPhIh"F1 F@+pF(-h"FI0hHQ FI"F0FI "F0FI"F(FI"F(F I"F(F I(F I"F Fp@p=HaFX F(!X"v F !JJ@ ['O3a@pL00FDI"FJ(z0FBI"FI(s0F?I"FH(l0F=I"FG(e(F:I"FF(]э!(F6J6Km( aR(F9F2F3Fb(`aG!(F.J.K(a<(F+I"Fm(5)KS60cRhR1|"36 .KJ#KK(hIJ#Fh Fr F!} clCcd F$ F𽈺m1= ayqX8Fбh#iC#iS55%hB i F8@8-AF F(3+h`i i3XC`@+h ii[ob`` aI"&7FKyx#iHY6C7hBkhJ`` F$ F`YthB i$yBP1 A"0oo*F ( ! #k"B2#C"44444^2 314#1O3<1$s02d#Or0##x2z2pG4F(0<4"((3#40Fk[k + !#4#0F F!"k[k + OpF(!Or#FpF@x F(1!@x 4&p4 F``4`k`kgg<#`1#d1hak- oo fgcfcpopj3FFFFH?78FFȱj39FJ3F)FF(FG1F@F8F-GFj3FFF`+2FF"HD  PF_F(/зj3QFJCFp8F)FzFh0F)Fl@HE0F)FJFXFF(F?0FAFYXHE 0FAFJFGBFFPF8" FIFO(#B y2̿ 4y8IFH8(s#44 F4I6(#4$44#44#4p" F,F F0F/FHI"F@h> F@&/FXK!FXhJ F@sF FȱK"!E`# J(F( ` ## K(h!FJ# F$ F| ,H8F K!FX(h(hI"F F8@͹8F F(V/K"E`&!(F,J,KB `F# ##(K"'K(h&I'J#F(0#K(h!F"J#Q8 K|Oq*"KAع|!*"K} 0U 0h+ ! F F F$ FKKEN]Nd<qMaOQLaKKFPXIh"FO F@7pF F(D&K"#`!#J(F#K( `4#" ##|!="Ks(KKI(hJ#Fi+hO *"" F!U F!O2O F$ FpTTQTViWp8Fh"F(FI!F(h(hI"F F8@8`0F hF(>#`! J(F K(``1(FI"FXKI(hJ#FK(h!FJ#>K|Oq("K.@|!("K F$ F0%`_`Eaaq = _pF F(4`K0h%``IJ#Ft4"x"a"r"#w"s# "v#rcabsvOrw0#s`rr"00 F ,F Fp)l$ 0pGFHI"F@h F@l$-CFOApFFFF(z!OAr( F ` FHFj!("z#hOAr`ba`O2%a`q#2(#2-#2n# 2# 2d#82 R0F#I"F+F<@s22K&bKKIKJK8h#FF`8h!hJ;(@bAb hhh iC hd Fa Ti-,3ňQY8Fh1hh#1h"FhIIh!hhb(F. F8@)83ňF0Z F@hFim7?8F F!:F`!&(FJKBa  caO7s`  F4F FYFHi0 F@־$Ah%iimBgi.5%aC`Q``hY!`O07F F8!"_+h%`c`kh(F`7`!#F(F J K( a`ahY F$ F>ᴆF8hH F@vsF mF(8!" cF(-! "+hfa%`c`(F`#F((FJKv(` I a Jh K> hA F7$F F|[ZZZZFPh(`i F@pCK#F?Ih?J#FtF(ot4!dj&Lj FL`j=j F9 F)F4jMPjMP#jilt4O2^st4ځ#htT^iF0Fb(6t4"x t"W0O1p#ht$Q !QcIC +tT#hhcIt4"Q t4 xN t4XgO0pt$t$$x$t4jF@hD hI"F@t$8hFtT'Ip(p#h$ItTgpt4x:Ҳ*"pt4xZp#t$x3+R tT!(F]pt4x:Ҳ*"pt4!xZqtTI(qt4 FyqqH F8@$$Fر@h I"F#j ##`hI"FhI"F F@Ά̆0F$ F(>!$"+h"`he``kh!#a#(FK( `"(FI"F##w(FI"F  ]h K I(h J#F  F$ F0̆̆Άm͆\ptdF FIItdItd8I8#81ItduItdlItdcItdZItdQt4 " Itd@td0#0xI1td0LP300"@B "kI0td0Os0cItd0#0]It4!YI!t4!(!t4y t4z%!tdOs0000" B0#000000$i-8Fph!F(h(hI"F F8@ͺ80F F(F'K`Oq "|#Kq(8"K|Oq#"Kd(+K|@!"Kx|! "KKKI(hJ#F@K(h!FJ#; F$ F0a][][][y[\[F`KI"FXh_ F@G,F F KF$"K#G`3r`tr!J8FKPBp` K8h!F J+F(F%(F^^^,pF F(Z+h&"C``! 2F(F3FB aK!(F'J'KB?#`#K`!|D" K(0K|OqD"K(#|!D"Keй|!D"K\KKI(hJ#F Fp F$)h hgfggfkyilD0FHI"F@h F@r0wlc_bmac_info_initdeadman_toramstbydisdeadman_tospi_pu_enabSDIODEVgspidwordPCMCIADEVsd_oobonlysd_gpoutGSPI Dword Mode enabled sd_gpdcsd_gpval%s: Broadcom SDPCMD CDC driver sdpcmdcdc%dSDIO RTE (%s-%s%s%s) %s on BCM%s r%d @ %d.%d/%d.%d/%d.%dMHz CDCnocrcnotif_cnotif_sofdm2gpo=0x%xpa%dgw%da%d=0x%xpa1hib0=%dpa1hib1=%dpa1hib2=%dgainctrlsph=%dpa1maxpwr=%dmeaspower%d=0x%xrxgains%dg%ctrelnabypa%d=%dpa2ga%d=0x%x,0x%x,0x%xrssismc5g=%dusbflags=0x%xpa2gccka%d=0x%x,0x%x,0x%xpdetrange2g=0x%xusb30u1u2=0x%xsubvendid=0x%xag%d=0x%xoem=%02x%02x%02x%02x%02x%02x%02x%02xofdmpo=0x%xtempoffset=%dmeaspower=0x%xrssismf2g=%dpaparambwver=%ddot11agofdmhrbw202gpo=0x%xitt2ga0=0x%xbxa2g=%drssismc2g=%dpa5gbw40a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%xmcsbw205glpo=0x%xmcsbw20ul5glpo=0x%xmcsbw405glpo=0x%xusbutmi_ctl=0x%xextpagain2g=0x%xantswctl2g=0x%xproductname=%stx_duty_cycle_thresh_%d_5g=%drxgainerr2ga%d=0x%xag0maxp2ga%d=0x%xbwduppo=0x%xnoiselvl5ga%d=%d,%d,%d,%dbw40po=0x%xpa5gbw80a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%xusb30u1u2=0x%xpdetrange5g=0x%xmacaddr=%stemps_hysteresis=%dmcs%dgpo%d=0x%xboardflags2=0x%xboardflags3=0x%xledbh%d=0x%xrxgains%dg%ctrisoa%d=%daa2g=0x%xprodid=0x%xtempthresh=%dchiprev=%dlegofdmbw205glpo=0x%xlegofdmbw20ul5glpo=0x%xlegofdmbw205gmpo=0x%xlegofdmbw20ul5gmpo=0x%xlegofdmbw205ghpo=0x%xlegofdmbw20ul5ghpo=0x%xusbfs=%dtemps_period=%dsb40and80%cr5g%cpo=0x%xcc=%d dot11agdup%crpo=0x%xaga%d=0x%xtriso5g=0x%xtempsense_slope=%dmaxp5ga%d=0x%x,0x%x,0x%x,0x%xpa1itssit=%dpa0b0=%dpa0b1=%dpa0b2=%dpa5ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%xmcsbw805g%cpo=0x%xsubband5gver=%drssisav5g=%dmcsbw202gpo=0x%xmcsbw20ul2gpo=0x%xmcsbw402gpo=0x%xregrev=0x%xcctl=0x%xnoiselvl2ga%d=%dusb30regs0=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%xusb30regs1=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%xcckpo=0x%xtri5g=%dcckdigfilttype=%dvendid=0x%xfemctrl=%dusb30regs%d=0x%x,0x%x,0x%x,0x%xpdoffset2g%dma%d=0x%xusbepnum=0x%xpa1himaxpwr=%drxchain=0x%xboardflags=0x%xpa1b0=%dpa1b1=%dpa1b2=%dtxchain=0x%xrxgains%dg%celnagaina%d=%dgpdn=0x%xpa0maxpwr=%dbxa5g=%dagbg%d=0x%xusbssphy_sleep0=0x%xusbssphy_sleep1=0x%xusbssphy_sleep2=0x%xusbssphy_sleep3=0x%xleddc=0x%04xmcs32po=0x%xrssisav2g=%dopo=%ditt2ga1=0x%xrxpo5g=%dextpagain5g=0x%xofdm5ghpo=0x%xtworangetssi%dg=%dsb20in40%crpo=0x%xmanfid=0x%xelna2g=0x%xrpcal2g=0x%xrpcal5gb0=0x%xrpcal5gb1=0x%xrpcal5gb2=0x%xrpcal5gb3=0x%xpa0b0_lo=%dpa0b1_lo=%dpa0b2_lo=%dsb20in80and160%cr5g%cpo=0x%xcddpo=0x%xboardtype=0x%xantswitch=0x%xboardnum=%drdlid=0x%xxtalfreq=%dmaxp5gha0=0x%xrxgains%dgelnagaina%d=%dusbssmdio%d=0x%x,0x%x,0x%x,0x%xsubdevid=0x%xpa1lob0=%dpa1lob1=%dpa1lob2=%dstbcpo=0x%xrxgainerr5ga%d=0x%x,0x%x,0x%x,0x%xpa1lomaxpwr=%dpdoffset%dma%d=0x%xtempcorrx=%dofdm5gpo=0x%xusbnoss=0x%xaa5g=0x%xcustomvar%d=0x%xtx_duty_cycle_ofdm_%d_5g=%duuid=%susbdesc_composite=0x%xtempsense_option=%dpapdcap%dg=%dlegofdmbw202gpo=0x%xlegofdmbw20ul2gpo=0x%xpdgain%dg=%dmaxp5ga0=0x%xmaxp5ga1=0x%xmcs%dg%cpo%d=0x%xphycal_tempdelta=%dpa%dg%cw%da%d=0x%xccode=0x0regwindowsz=%dofdmlrbw202gpo=0x%xwowl_gpiopol=%dantswctl5g=0x%xcck2gpo=0x%xtri2g=%dcckbw202gpo=0x%xcckbw20ul2gpo=0x%xitt5ga0=0x%xitt5ga1=0x%xmcslr5g%cpo=0x%xpdoffset2g%dmvalid=0x%xrxgains%dgtrelnabypa%d=%dboardrev=0x%xrawtempsense=0x%xusbssphy_utmi_ctl0=0x%xusbssphy_utmi_ctl1=0x%xusbssphy_utmi_ctl2=0x%xofdm5glpo=0x%xpa0itssit=%dtssipos5g=0x%xrxpo2g=%dtssiposslope%dg=%dtri5gh=%dmanf=%stri5gl=%dmcsbw205ghpo=0x%xmcsbw20ul5ghpo=0x%xmcsbw405ghpo=0x%xsromrev=%dlegofdm40duppo=0x%xmaxp5gha1=0x%xdevid=0x%xrxgains%dgtrisoa%d=%dmaxp5gla0=0x%xmaxp5gla1=0x%xepagain%dg=%dwpsgpio=%dwowl_gpio=%drssismf5g=%dtriso2g=0x%xtssipos2g=0x%xwpsled=%delna5g=0x%xpa5gbw4080a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%xmcsbw205gmpo=0x%xmcsbw20ul5gmpo=0x%xmcsbw405gmpo=0x%xccode=%c%cmcsbw1605g%cpo=0x%xInvalid/Unsupported xtal value %drmincldo_burstpll%dlnldo1r%ddr%dtxtalfreq        0 0rmaxKe lpldo1 W@WW @===== =@==@ == =@=>reg%dcldo_pwmchipc%dboardtypeprodidbtcxseci3p4mbaudswdenablegpdnboardflagsxtalfreqboardrev:"devidmuxenabwl0idwl%d: Broadcom BCM%s 802.11 Wireless Controller %s tx_duty_cycle_ofdmtx_duty_cycle_cckagbg0agbg1agbg2aa0NVRAMRevsar2g) C%CC!C$CCCCCCCCCCCCC(C)C*C+C,C-CAC@CPCQCRCSCWCvTC_C?COC/C4C5C6C7C8C9CGHG'GCC`CFCGCHC1C2C3CCXCYCZCCUCVCcCCCCdCeCfCtCgCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"C֨ghبCC1CۨѨܨRƩ12devidaa2g11n_disableag0akmU~#a[ѫwl%d:dma%daa2gbtc_modeboardflagsmacaddrbtcxhybridhwgpio4invvendidcustomvar1customvar2btc_params%dantswctl2gbtc_flagsboardflags2boardflags4boardrevdevidsromrevbtcxhybridhwantswctl5gsco_rssi_threshprot_btrssi_threshccodeccregreveventqhs20)iA)iA)i y y)i)i)i 0@rssicorrnormglacialtimerldpctssilimucod%s.fab.%dtempthresh.fab.txpwrbckofinterferenceglitch_based_crsmin2g_cgarssicorrattenphycal_tempdeltatemps_hysteresisrssicorrperrg2gtssifloor2gtssitimevbat_addpapdvalidtestswdiv_gpio_1pminspurconfigcckdigfilttypeeu_edthresh2gred_rxblockingl Kv20A~ '% l [?X/ Q'a `?pq Kv20A~ '% q  ?X/ Q'a `?pv Kv20A~ '% v ?X/ Q'a `?p{ Kv20A~ '% { q?X/ Q'a `?p Kv20A~ '% #R?X/!Q'a `?p Kv20A~ '% ?X/!Q'a `?p Kv20A~ '% ?X/!Q'a`?p Kv20A~ '% 9"?X/!Q'a`?p Kv20A~ '% ?X/!Q'a`?` Kv20A~ '% W?X/!Q'a`?` Kv20A~ '% O?X/!Q'a`?` Kv20A~ '% ?X/!Q'a`?` Kv20A~ '% '?X/!Q(a`?` Kv20A~ '% ^?X/!Q(a`?`maxp2ga0l 4 #0OA~ ' l 'v?X<;Qa `?pq 4 #0OA~ ' q ?X<;Qa `?pv 4 #0OA~ ' v ;?X</</;/;-:-:,:+:)9)8(8'8&8%8$7$7#7"7!5!5 4 4233120/-+*)((''&$#"!! ?b?^?Y?U?Q?M?J?G?D?A?>?<?:?7?5?3?2?0?.=.9/:-9,7,6+6*5)5(3(1(0'/'-'.%,%+%)%($&%$&"&!&!%"# ##"!"!          rateselstfcck_onecore_txtemps_periodtxchainrxchainswdiv_snrthreshswdiv_tx_weightswdiv_snrlimswdiv_swctrl_maskswdiv_timeoutswdiv_swctrl_ant0swdiv_swctrl_ant1swdiv_weightswdiv_settleswdiv_enswdiv_rx_policyswdiv_swctrl_enswdiv_threshswdiv_gpio_1swdiv_tx_policyswdiv_log2avgswdiv_gpioswdiv_cell_policyswdiv_ccksnrcorrsCiF"/+F F3+F! ! F FK@  F3`*F|FFF@"F FU F F9F\K3`Oc+` FoFF!Fooq 7$iFFF(F F>8Fo H FF8 F(F8O08 8-AFOpFFFqF(2!Or 8F1F*FCFg#ct@" !"o F Fol% % F?%(Fܩ`N '^^^S^^޻޳^^,;c@[^`C^^^kDeV`` ^!kDeU !{&Deaw`m^@&,{ h+O+kDeZ`w^2-/`` +ע+WmDj`3+ `h+;De]i^whދ;mލ^;;`@DeZ7m^Z@` h,oFaDecwm^ F` ,{+h*QDeW7mޅV@Mh+#QDeYmޅV@OQ` ` ` ` ޳TBT^ sW^h޷Yy*+`+mޅ[h^`h+`+h*fDeWW`׮mކ@^Tmކ@`׮޻yh*yDeUס*Wnކ@r׮`c` ` ` yn x*7*7n*@w*iކ@y޷^h* h*h*h*h`DeV7m^V^h+#+++n+`޷h*`h*,'DeV7EZEZ^WiޅWleV`^,;^ZchE chE s^kDeV `޻,'޻޳ޯ^^` lY^^a){+c#^ ^ ^L ?^ :s%^)^K^ ~7 ~^ 3cl0j#  `^p20chK BE#cnE `A#H^ w ` ^^E#0c x`   Chޛ``Lhޛ@`,^0cBE#^ z ` ` ^^cl0n#  0cl0r#!` Bh^KAh^KA` H`E ^^^^ ޳E#^F#w^s^&.^9^"V^` H^j^#'^#7^^(` U !^' \@c)0@c+@c-^ 0`c{`z`~puA4`c{`z`puA9`c{^z`~0uA>`c{^z`0uAC`O`^c`^0e`^0d`(i^^^W^7^WZ0cZV bTb`(kAb hއA^^7^W^^`Hk`^0e`^0d``ZbXc`7c```P@C@G@3@ m^ay^7z^7`7^7Amކa8ZC[0````#дh^KT rcc`BL`BL` ChޗdO^7Df `   s ^ H u`j^#^B^ H0Sew^7^W^ Wf` Wh'^`#eA0`^P``#no އDx އ$u^"^6~^"^6~ އ$|^"6^V~^"6^V`0ZZBBZ Z`^'7^'``P3S`hB07`#д`` HD^?E`^C^^DDE`B``^^w`^ 2^2chއ` H2c l`׮PPDgDkccB `$`c` c PT^tPkB P+B0:0PR0P_PcPgPkBP``c`cд`` qc`еcд_"^ P^7^+#QB` (QB^dX#6hXDgX 1Pe`Z36PZ'62`Z z8ZZ0; k wCAh^O'A`^C^L` H+?m* { ` ^)޳\ (3^\*m 'W`3 ^Z`'rc^Z)^\`'\` H )Cpqc`cf0e^I` Hh^;gh;h)^kPkh^;r7^h^;'rPqq H^xnA0gxZZh{ }m^.}41^37h2g^m.g^nA0gZZm^.41^77h6g^m^.g HhKPOPSPW``Q)^^^DhA PhK)41h;' ^D` H)^) )CnoPm 'Ddwn^'w^Kh^K'h^'^^Dh^;'``` `'hA`')^`41) ` H`{^`mz ` ^^ 8DL^jބ^`"0``DgDk^^``cRRR`TiފRPhG`T'T/```` 3 3`ס_Th Gކ0T ^``R#R'R+^# h^O( ch^Oh^O``h^O( ```7`D F G^3^סj^ R0#`8#` Ha7h^Oh^O^ 3Ac5`I` (lm` X^1&q34w^F^7^{#` X=h+O=DeZJ^?a3E`W^)`0@g^-7G `(D` M` O x@BT`` `W` HDgDkDoDshz#(W# @;mb^_7hb`7C Ch^(f ބ'`w l@7l  ``` $`$`H#`*``` ` ` ׮DgL7 {^@7~^ |h3HkDeȎA'A'I^^^^^^^^^^^I C^y@7h^_ |h^_L|R7h_)>^i^iU Bm_I@ U+/ Uhޏ Uh* U+mIUh^IHh^OH Q+*' Mh, Nm^d)N,m^\P,K hOU^u U+*h_ XhޫIXa h+O Zc+^ ]OR G G $ #``^S f`S jGQ jGm@3-h^OmhޫIh#u#^0eG u^ץ^ xR x ^ xR  }h^z^hޗ}R  `7G0eAPeG^ ^m@1Im@1J-` WhޗZ R ,^ h^g^g^f0d*Xޗ^f^g7X ^0d*X 7R Z hޒ)^g  hޒ)^g Xhޛɨ^އ ^gwddhޛI m R R; ^ 7^Aw^ #`#ׁ^w^c`A0cVVhކIhފi^Z`#dbO^G^ n2)n2,{h^Ibqhޛa ``^k1 h^ihޛ`= $ #`h_I^k^=`=hޛ`=`=d b``` H# % #j`$` `w h^O8R^_޷ h^ `w`7 `W^EhޫI^Owh^L h^L   ~7 {^^  ^@7  ~7 {^gn@0 3 3hޫ +^ +  R C  W h^O `h^O`h^O h^O h^O h^O hޫ*,+^ /  "R !G  "[ h^Okh^O.h^Oh^Oh^O+kh^O-^Owh^.h^O   ``;  H ^ 7^ 6 ^ :@7 7^7^ lD` H7 { ~^C^ ?7 { ^0^ ^`PeA0e8@+-@k^7@' M`ZV' P` ס^)@g` ^)@gZ Z7^WކW^gi^` `n@0 f m ) d. e`+ i H H ~`` `) q ` ^ ~h^*h^ | Rh^*xh^Jz  ~ ^ ~ ^ ~ `K ` `+ ~^ R 0  hޫJR;R;`( ^S  ` HR;R;^R^7ކwa0R:k:^~ע^`#dkR:^ ^`WApdXVkʪR; ^ #(R;  ^S  H h_ T '^І'B*0 ^G^Oh^*^ R hޫJS ^S R  ^  ,^ h^O ^ dކކ$$h0SDg ^ Deh^O   1^ hޫJ^ dhޫJ?  h^JR/ A h^O h^OS ( DE^(FA ` +^ h^Oh^O+ hޫJm*` `׮^ h+O DeZJh+k+k*^S c  # )P hޏ*  p` H^n* hޫK' h^O h^O h^O^ e    G d) ޯR8^KފwR#R'R+R^1[G4nބ`B  ^ ^S @3h^k$@1 $  $^cn^ f^` *^G` _^Sބ ~^^ -`=ǃ^ 6Ǘ^ 3^*^ >^K) = = l```@'@k@o@+` ס^)@g` ^)@g^7^WކW^^Gh3 [`'h3+X^)@dע^ YA8hއ [`'`^gcר^I^K` @P2  g  ` H H +^ hOo;  p7 # hN˒ t p` H^n+x yh^O+`3)^ ~޳ `'  E -qk Eo +q[^ p H^* P ` H ^ hO+O  ^ A A 3 A 3` 3 h ``^  ^S  Chއ+c'8ކK^ R R/ 3^  `e`^t^hޓ 8ZסBFJwW^d^ɧފǂގޒ`w^ eZ^4^7ޘW{ޖץh^m^w^hZ ZօhZ Zև^4ޛ``iޛ ccގWY66M:VN>vOBP ^ h^O,^ `e`^thޓ ?h?```#`a ````C `0a`P``"^DqE x^\``` ~P ~R^n.V ~noY`B!^^ J( KfPcP^.7^.'fP^.7^.'hl'!hr (!`(!@+^@+jފ.r`!AADg{ފ#W`pe``d`PchZ`bAPbTk^nZZՀZvZ/6i/Z6l.Z7Zwnޒ`6` C`' Z `' Z  ,' Z `&Q(c$k^hZ`VV^ЖZՀ Z `hZk^Ю` VV^Ж`6` C`'hZk^Z Z6Z'Zv`bAPbZ+TuZ60T`VZ#Zv`VhZl.Z `6`6` C`'Ae^7AdA0cm^|` Oc SbZZ Z !`@ww^ BhE#hh^sh0Oēh0Sh0Sh0Wke`pdAh/ AdmANēhK^SAS `Q`RbS`QP``w`v`^6CGVGJ1UEWwE[v`^6EW E[ `U`V00^` `G^ca```pe`d`7`hZL`Z Z ^D {Z (hZ+(hއ/S^ 3ZhZ/$hZ//$`7hZ(lޒЯ(Z`7 /+hZF.^ o^Z ^lޒFZ /2`7F L^ZZ/7i9Z7<oh?8oh^B^7B^77^ h^F^^7Bh^Ik^OJL`7^^^7AeA0dm^h^^Dg{ޖ#W^^^'+hwYnno^^^^ngw`ha#i ;dfhA'uE#ghkhkhnDgDf7m^Ol'p ^z^^^`|`\`]`S^`_` \`]`C^`_` ` Q ;Rn*h;#(Dg*Q;Rapwcv`^6EKwEGv`^6`/eEWE[D DcRcQ`U`V`uAAADg-Dk,Do+Ds*Ddli`1PECh``@hW`/eZGUZKVZOZS```f`uAAQARhEG*;``w`v`^6`PECDgh^#/x`@ `f` `c{`z`uAAv7vW0r7An7^v s}^z}^v^sW 1ᠲQᠮqࠫ #jCkDD#WD#פD D^#7ފ#WiދD q^#7i#'7` `@ 0F#7J#Whދ`Omކo`@`]` _^q4ފ&5c3` _^h`CDf7`^slDfh' S^`@ Dd W`@/*1 / a \`]a^`; _^^^`mDgwhކ#0 ^І^^ІG G8R'^h GP*T^h G02hG.T2'1;^ІThO6T>Ae`סhO;`^^CC^C^C7TWG^HDEYhY^7m^Y. ^)@ghޣV^pwmUmPWVhW^pw^-`ZZWV6V7V 8V9V:VH;Z48^5 `Ae^^Pc^^w^7^wAPeVVnދg^ע^7 H6 ^^7 H7 7 H8 7 H9 7 H: 7 H; ^^7^5`<`<`<`<^cVVV V`B<`<`<^c`WV`A0cVVV ^c``^S`A0cVVV `S^c^SV?V3^`h^`hޛPG````````aBQXXX XXXXX^hޛ`wޓ`XXX XXXXXFd`1XXX XXXXX@`0@@@^10hU^^h` 0Ih^^` 0I 0IA'+`xhTA'A'I^^^^^^^^^^^IS`7 ^)`7hޛ`7^-A%^S`DgDkDgDiwhmޓQDg^"#"hގ#1`G`C``h%h%8^+`wDgDkDeסi^wފ7^&ފ&i^8a3D16DQ7`w`G`PC;#E` eApe.?Ae` nA1CZ)6` `IE`d`e`ޯ`Xhބ,1PX#6h^`VX^ 7^ YX^ 7^ 7^W^D^ ^ hX^WjޗfXif`XXAdAe^7^7hއK`G`m`l`m` d`wB^^nchz``7 1hފ!l!mh^ ^nފщmފщ^AfX`l`mAd^7iއz^edXEbaXXX XXdnA*D^X6XEmA(ޯ` QB^o^^`wE#ē`׮,#,++ `a ^**`^޳hB^^+/h*ޯ^^E#+/^^#a ůoE#Bh^Kh^Kh^K1E##*mމU+/^/a ^a ,#`a `7`EEEbw`Pv^@h*DeWWcm^QDfJleVqDg*mgQ` ů[Eo[` N޷a ޳h h+`+\` N` N`+\` N` N^`+\^^EZEZn^T<޷8+*` h,G$,G+`.+*'+h,,m^d2,,m+R.8+ Dg ++n^6mމ^R68` ^h* ^EB+B++n+s^EDg ޷Sh*rHDeUʶh,GJ,G++*+*'Ph,Qm^d2Q,m+2S` hVDg Dk h2ZDg +Z,{ ]` N޷d޳sDeV7m^U`׮#n` mERkE DeZ^.*s` mERqE DeZ^,*`׮``{E|Eo^w` DeV7m^]~m^U+c**`xEE `xEE `xEE `xEE `xEE `1xEE `QxEE `qxEE a a +(^ `W++ޚwA,'``n*`W \R*`w ^\r``n*`W ^``hG Z*`w ^Z``h h^^W^ ``h,G``h,+#`hh#޻*4+nއ*n^dr` #` `a h^4+mލ`2h^``+ Dk h2'`` h,/Deawm^a,3^amކR#``a h* `h*2h*+h*h`* hh+# + h+ * ޻*mމU+*' h,m^d3,mS``W ޅc*`7 ^ch,o4+n^,{+,{+hDg ^T`׮,+*m^U%^6'm^_;,#6`pe`Pd`פhZ2X4^#7#Wފhދ2nގs6A0dAemA*;h*;h*S;h*s;`׮^Z`W4+ފwAh*SHh*SHh*sHh*sHh*SHh*sHh*Hh*HWh^R^ ׮h,On^dSO`c+*n^`R``DeV7Dgh*V^*`޳s**hg+g+m^Xsc`h+Oc` ^2h^gh+g++h^ph*pDeWW^Wm^Sp``h+Op` ^2/u^uE#uu`',^+,,+,,,^ޯ޻w^6DeV7mޅT+\+\ N`QxE`/1y޳#h7Dg Dk ,kB#3DgK`+\` N` N`+\kB#3DgK`+\` N` N`+\`QxE`/1y޳#h7Dg Dk ^^h*w+'*`׮׮` ` ` ` `_jDg Dk `c;m` p[` _`m*nE`]*^EkkB#3DgK`+\` N` N`-Qj`+\`QxE`/1y޳#h7Dg Dk `+QZA?Oh*``/Dfj` ^Di_סnއ4 + ` h* Dg DeUJ***޻,ůEosch4,chņ4,`+\` N` N)`+\`QxE+./1yh07)Dei׻øc` w)4`+\1` N2` N^6`+\^w:`a )` _?`-Qj@`+QZVJkB#4EDgK`+\H` NI` Nj`+\`QxE`/1y޳R#h7UDg Dk j_kB#4ZDgK`+\]` N^` Nj`+\`QxE`/1y޳g#h7jDg Dk w^Dk ޳zx`+\u` Nv` N^z`+\^skB#4DgK`+\` N` N`+\`QxE+./1yh07Dei׻øc` Dglft`+\` N` N`+\`QxE`/1y޳#h7Dg Dk `7  B ^BE#^hOh*DeU׹*7',;h*j^T޷)^2)*mޅU)޳,h^^޻+nj4sh*h*jTjZT#h*Sצ^+ )`Wc` ^p`ph*p`^ TC[0`c**aw^ a^`#^l^'h**ůEoi^^V`ׂ^ awG^^` H`^^޻))`*޻*`h^K5+7m5`7+;m*5+`w`7^E 0T `W`^ET^ ph*)ޯ)DeWn^T)^7m^T)^6DeW^7^6ޯ-׮6h+g2De[*h+k1DeZJ`h*6DeW^`` ` ` ޯ^ޯ?` lsY*#C*޻E*DfjDg LkB#5KDgK+\Y+\O N`QxE`/1y޳V#h7YDg Dk ޳ec`+\`` Na` N^{`+\^sjޯj޻j^j^q`+\o` Np` N{`+\`QxE+./1yh07{Dei׻øc` a `w` `h+[+[m^UU*+7+ ^7+ + + B^ a `w` `Dg 'DdwWhwwhwn^{U`7`bw`v^@E bw`v^@a#,';kDdw;,;޻`^` צ` a^`W a`a^Z`Wü C`Ph^hއ5`h^5`` Њh^B*0h^5B* ^Ph^P Z^aWޖץއ^w^סޏ`^`7^Wޖ7Aއޖwކ ޏz^w^W^^W^c ץކAއ^W^Wc ކbAއ^סS`$ $ # `$`%^7 { ~^\@^7^cwSބn^c%`$`` $(^'AApd ^APc^`B7V6hA#A0cA0dh^VWXvhA'A0d`#^`0Pe8Ph;6/Z36n2 Z cPdn264Z7X``׶A0ePd```7`R3Ah^V[^c 6OPUV^`7mއU ^`7^Pc`7 V6UX6Z+6jvQhV^7h^6VVjvQ^7^7^@A0d@h^e*7*26P&n&v&&&&..666>6>>fffnfffn~nnAEARATAUBEBGBNCACHCYCZDEDKEEESFIFRGBGRHRHUIDIEISITJPKRKWLILTLULVMAMTMXNLNOPLPTPYRORUSESISKTRTWUSLLB H:DJJ D B @8HLLH B :DB: \V~\ V FPPL H LLLLLF L6<D@0,@@@.@0,>BB> B*TNEOx\$dLL8@ 8LJ0J1J2J3J4J5J6J7J8J9%             ".$0$@$t$$$$$4<4@4|4448@@@@ddddtdddhhh0112 1&(,01.11&11!&1!1&01E0XAXUAUJP|  ".$@d2018-04-11 22:31:21@@1(('8:<'F14@H'<<&<18<<'TT<8TXTT1TT'BB066'\P1XL'B@188'80<8<8Tp1Xt'8F:"D&F14 BD4>H!J':P/P3P4: BH&P)8D8"D$D*D10D0>J!H'8N@"D$N+ > >N28N N#N%<&N)xxxx8F:"F10>0<'8B<"B18<<'TT1XX'8F:"F10>0<'<D188'pp1pp'@@00<<000'8D10<'>ZP#Z)V-v2JbBJb"v(TXTX8<10<'HH,LL#<<&8@<<&8TT&8TXTXTp&D`BB&*@>B&*@<<&8@<<%<,<18<<#<'TT.XX$<<18<'<<1TTTXTp(Xt<<&<18@<'<14'P1P'P1P'PP1PP'L1L'L0D'<1<'T1X'N1N'8!D&D10>J!H'8:&>1.088'D!D1B<'T0AEARATAUBEBGBNCACHCYCZDEDKEEESFIFRGBGRHRHUIDIEISITJPKRKWLILTLULVMAMTMXNLNOPLPTPYRORUSESISKTWUSLLL L B >B> : :B: *2<6 . 8 :DJ D B 0:B: 6 V~V N~N FPP P H :DPD < @@LH@<@, ,(4. @.@,6@4 LLLLLLL@@THOxxx@P@X<dX@48@ 8.4DEJP USh  p 0 RC E n 1 XAXT/sXV0g #a#n#r0A0B0C ACAD!'0AE AE!+ AF!'0AG)/ AIAL!+ AM AN AOAQARARASAT!+ AT%$ AU*.AU*-AW"AXAZ BA!+ BB BD.;BE!+ BE%$ BF!'BG!+ BG%$ BHBI!'BJ!'0BLBMBNBN)/BO  BQBR+4 BSBT 0BVBW- 30BY!BZ CACACCCD!'0CF!'CG!'0CH!+ CH%$ CI!'0CK, 2CLCM!'CN15CO  CPCR CU0CV!'CWCX*.CY!+ CY%$ CZ!+ CZ%$ DE!+ DE%$ DJDK!+ DK%$ DM DO DZ E0  EC EE!+ EE%$ EG)0EH ERES!+ ES%$ ET!+FI!+ FI%$ FJ* .FK!'FMFO!'0FR!+ FR%$ GA!'GB!+ GB%$ GD+4GE!'0GF!+GG!'GH!'0GI!'GLGM!'GN!'0GP!+GQ!'GR!+ GR%$ GSGT GUGW!'GY. 6HK+4HMHN/ =HR!+ HR%$ HT. 6HU!+ HU%$ IDID7AIE!+ IE%$ IL IM!'IN)/ IO!'IQ!'IR0IS!+ IS%$ IT!+ IT%$ J0&*J1 J2J3&J4J5J6J7J8(J9JE!'JM.<JO JP'(JPJP')JPXKAKC.6KD3:KE!& KG!'KH+4KI*.KKKM!'KN KPKR7,KRKW KW KX08KYKZ$ "LA"LB.; LC LI!+LI%$LK+4LR+2LS!+LT!+ LT%$ LU!+ LU%$ LV!+ LV%$ LYMA  MA MC!+MD!+ ME!+ MF- 3MG!'0MHMK!+ ML!'MM!'MN  MO2;MPMQ!+MR!+MS!'0MT!+ MT%$ MU!+ MV  MW.; MXMXMY)/MZ NA NC!'NE!'NF* -NG0NI NL!+ NL%$ NO!+ NO%$ NP NR!'NUNZ+4 OM!+ PA PE PF!'PGPH+4 PK2 7 PL!+ PL%$ PM!'PNPRPSPT!+ PT%$ PW PY.;PY+4Q1Q2QA290RE!+RO!+ RO%$ RS!+ RURU RW!'0SA" SBSC- 3SD0SE!+ SE%$ SG,2 SHSI!+ SI%$ SJSK!+ SK%$ SL!'SM!'SN!+ SOSR!'ST!'SV  SXSYSZ!'TATC!'TD!'TF!'TG!'TH+4 TJ!'TKTL!'0TM!'TN TOTR TR!'0TT+4 TVTW4@TW5>TZ!'UAUG" UMUS US  USUY+4UZ!'VA!+VC VE)/VG!+VIVNVU+ 1WF! +WS+ 1X0X1)/X2X3!# XAXBXR6?XS   XT   XU %% XV   XW#! XX ! XY!+ XZ Y1Y2Y3Y4Y5Y6Y7YE- 3YT!+YYZ1Z2Z3Z4Z5Z6Z7Z8Z9ZA!+ ZM)/ZW!'0 18F:"F11TT11BB1&1TT118:<'F1TT1TT10BB01B@11\P1 T 8 18F:"D&F1 18N@"D$N+(Tp11:P1xx 18F:"F1 18B<"B1!1TT1 18F:"F1 &T&1<D11pp1TTTT&TT000<<018D1 2>ZP#Z)V-v2&TT18<1,HH,&T>B&&Tp&T1TT1%.TT.'1T'1T(Tp("1T1"1N11TT1"1T1"1L1!0L0!1D!D1!&18!D&D1&18:&>1!0T0x  4'11LF!BRCMcfgS2CCR!LR!BRCMcfgDO(BCM4343A1 UART 37.4 MHz wlbga_ref wicedS22bpd2/2x2`, 2l` p`t`x`|``!`A3dALM!):dA):hAhlA0pA>tA2xA3|A0 PATA \A `AdAlA tA xA @ADA LA PATA\LH!A `A dA Aq `d` "( 2>(24(, d ( 2>(24(, d ( 2>(24(, d 222LC!2LL 2>$2(24(4282P2, d dQxd #!`````8`\LLLLLAAAAAe_____MMMMMflllllXXXXXf̅iiiiiL9!f̙tttttg̳g# #H\Hz`BL`LD0&lbNXH4* zp\f``L4!```8`\C977885565eLEABC@<;;<f\RRRRKGGGGfjc__dWSRRSf|qnnqa]\\]ǧohgghgL/!#8tPFZF<"`LLLLL_____lllll\>H\Hz`BL`L`C9778LEABC\SRRRjc__L* !d|qnnq? (( ,,((00AA44II PP$$XX@@``dd``ddhhllppPPTTttxxd @@@@@AIL%!!$P@X`RHSLTPUTVXW\fnv~:(  >?     2Ud  P d ##&*L "! +=?:?O2Ud  P d ##&* +=?:?O+   L#!  $  (xZ3 !"   0 H, $3 N  ( % 2 *, ' 4  f  (P? L$!PP8 2@ 0`] < 4 , p] [  L  P w[Gjg !   ab;V]|  ~}];  g8 !0L%!{   ? 8 w9 } e9 a9 gd Nf!G#F%'((*+L &!,- /0 1123p41556F778 99B::Q;;Q<>?h??3@@@QAAB^BBC[CCCJDDD-EvEEFIFFFGUGGGHQHHHI?IxIII JWJJJJ+K^KKKK&LVLLLLMAMoMMMM NKNvNNNNOFOnOOOO P3PYPPPPPQ8Q\QQQQQ R.RPRrRRRRRS7SWSwSSSL'!SST1TPTnTTTTTUU:UWUsUUUUUUV4VOVjVVVVVVW W:WSWlWWWWWWXX1XIXaXxXXXXXXYY1YHY^YtYYYYYYYZ#Z8ZNZcZxZZZZZZZ[[1[E[Y[l[[[[[[[[\\.\A\T\g\z\\\\\\\\ ]]0]B]T]e]w]]]]]]]]^peL(!`eAN CCCC`!CCCC ``@``A,`0$`AO CCCC`@dA@`AL(!PiN CCCC4A``U0AAA!AO CCCCP CCCCyO CCCC`````L)!`````N CCCCCCCCdd d0``N CCCC `3P CCL*!CC`epedd ````$`,`0`AdA@4AH`EO L+!CCCCP CCCCiN CCCCN CCCC?Q CCCCSP CCCCA!P CCCCO CCCCdd d0 EN 9WӠ{Ţ    L,!!#%')   d`h`l`p`t`x`|``Q( 0  S1 S2 e2 E) D U) #IV ( / s0 ) ) u2 U+ + )  + 2 %5 L-!, !+ !* !( !) !$ ! ! ! ! ! !( !Rf>R*>* ! ! ! ! ! ! ! !( ! ! !L.! ! !( ! ! ! !8 !````AA ]]l ]]l]]l]]l]]l!]]l'L/!]]l-]]l1]]l1]]l1]\1]]J1]]D1D4 !1 !2 !3 !L0!0 ! !h!@ \7 $Ham? $ 0F{jF :m4 ipfol lH F}( FGmDX HxA 3 lc0 !p !Cup | F > [q "Y  FL1! hF Fuy| `hupQ !xBӣ6Ⱦ 1)ѰFM]  | ^]pG  sPr6 Fk 0Fup& F d8 F fH F e|XL2! x!dl ees| Bӧ D! i F@jľ 0 F  j Fp  CT F$Ͻ F)F&OO a)(OOuO y) (ӄ뼄L3!  !"@3V OWJFAF F4 FO, FlL p}^[[[k[d 0~ F0v0X0x Kx3F1Z)S1)SS׾4 ! !z) (SپSݾSɾ (FH4L4! GBHx uGB"HpL^   . -@  qp  F, ` v hv< rr&LH I xA Ix( p IOp I ` HiAahA` pG ! N^ 4 d`eL5! fmis{sz Hx`}V V !  ()ЈBȿ@ pG pG hoRoZ$ Ք~Дoo, {pF0hp1B0hnn8 jjnJ D`L6!>:\  !}l -p@kkZ| F  p        p @ Uf h?  6  O b dFL7!  =d  )F2F-F,9FFb&b, --cB  *p&  Kl 4  `$\A\P  F)FtOؿ ` (p f Ypl F -p,x 0KFbKBbL8!u^  X   ~p FI2M[  H$޿l   2 F FJ2p  (JJ F7L F)FL * b Fk(J-$ pF\M8HJAhA@`L9!J H*JhR` F [tAt p p"!p 5 u 1 1 D p F @FF @BFpM"F3F)Fp@FpGFpB"F3F)Fp@Fp0 tF0 F@t( K"S"@B@R *@p]  A|)L:!)|(( pG pG< -CLfxxF"&xH%Fh oFW%h `$hW%Bm- HxBp1FC th1 !`] ]  /H!aAaaapG +KF3S! IC)pG &NFO,(-4hL;!hFqI xB'Ҁ(%A "V!0 CB%@@\!@C!  ]H>F@ht` Ft]WH&( F(`h@tL (ݸ$ -_&FF4F0X%_ ((и@%F F F FF,J,U,^,lі'(h0Fj(c0FA(*x*( x)kxoMB o@AoIh0FAk x)2)x)/LvC!)+!#8Fi HxA,)x)(HhA} x) )x) (!FA0 ,"sItH+qHaqI`r -AFF)"&FlMFCZ) bI xA)h@qto  h AIC ٲBFFRҲ*(hq 4LqD! JHxpG: -AF@lqtД!|!Fi!8Fi!8FiDEHh eDHhCITAH h 0V(Wh;N`c6j`9H0h0hc6hlq5"1F F%a@ou% oOPAմ` !8Fi!8FLlE!i!8Fi 9 xp )1 a $3  4 !2 < 2 (h 2 2 71 IH` * FA( (Сm F@y0  F,(Hh!`] 2 l1  +I*H`pGB LgF!Fh( 0#Hm F@IJ(HhA`,:  F, Ѱ((Hh!`Zb Fo ѡ28Hhp@ HBF] 2 l10 W   FFVPq)I xB$Ҁ("'JA LbG!R! #@B#JR!"|@ I(&* h," `q_JhH2``Hh@h{oWiFo.0(HhA`* hBB@"@n K) g g h1p1@ pF F !!(ٕ CJxB!Fp,4 H +J!RhL]H!0Bܙ0,BII)) !HpGP O:xB*)L9p"xhhuQ-hD"Phi`T"(`R*0T IIhIi@DpG ^ Th p  -O!IIKxhh iI h!h *LXI!l -o('u 1x)qH@Enpx(aѶ"pK*F,Q@ !-% RE)I i@II h@q@ ZE"p,mB@h ,,@,@ ,@LSJ!,( , D܏ @BzJE rD -ALhxxM1(FsQ!aI1` Z: 0KByňhѲ% ` zOE `% rzr{ s{* Ѱ {Js|sȀx@p0Z LNK!Dy& h)I` %l;BлCdq xR p@B -OF$F \I'&hF- "(xб HE ѕ;AEhp@5 k O A7F,F B7F,FvFHxBӺ1BHxB-d;khxIpLIL!k`A csF  иииs-FPF -_&FO F#I'%hF$  x/@Eє;B ZF`p?0k /F&F@4mBӚQFB Nk0 c0phxIp8FX` M#$hF@LDM!(^ 4 h 3 ;B xQk!BСCcphxvp@2[۲xBX -GOFAhO$%; xBЂ( zxkB"aHFp8@4mxB  -CTFFFFAEOJF;\ T#\I|#TB2F!FHF9CFJF8FL?N! JF )\N|3@T#\I| @#T@AF@E F!F FJFAF F|3FAF LFK:\)\ @T"\ @"T@BӹI2FhFpf  -_FH&7Fh$( FO (ܠ(f (((;(Y   F (Hh$%!x; BBxk L:O!B "FQFQ CGw@4mHxB F AE%!x; B ј k B"F! !H@4mB0F9F CC" FmHh@xhF pGJ fMF hlxOFFxx\;@dEk5B CAL5P!q@2[۲BL -OF! E FFFFOHOIFhIx+**h@h( FFCfп08x@B-,,,xx(xx(((!F8F@A xx(!F8FCA  )IMD-,,#Hh@x@Hh@xL0Q!( + "C"+ C C@ C  t #"h z #"e -AN" Rsx@h (^ lh !xqJB bx* *@@d@ D( -'O*x;( x@B sxkBСhp0@5xBL+R!8F -O F! OHOFh@xh $ FCrЭT(x@PERhx(DHh$&9 x;)0)xIB,ܜ L !Kx@Kp)x@@!xB؜ kOB "xI`pe CIy@4vœB IODܳHL&S!h@x+# C  C > -O F! GOHFFh@xh@  LFCnЭJ(x@BGhx(<ѓHh$&/ xP;)&)xIB"ܜ ( !Kx@Kp)x@@!xB؜ k @B"x}I`p@4v L!T!B 9IOD/pHh@x@+ # C @@ Jz  C  X! -_F^JFPph%.F 0h{0((&&SHB=ݑF>YFPFF(3,3YFPF[(+#:FYFPFY(#$OFX$ YFPFG(йxBLU!yxhzxd,yxhz( (0Fyxhz(m.:" -A%FF,F$NBF9F FCdxB(F$d" HhլoHy(н@:" Lh(x"shx s i@-s p`p q6" Hy8HhHhhLV! pG pG(^ lh ) 4 >" pFFFB+ "! F2F)F p@s(x phx`p ppp&# -OдPN BF(DN lF(D dajO Q  i`b,$U WLjB.Fi 8D h2FGT0j2FXFBU(j2FLW!XF j0DbLB,@F@F,ر$]N N l diN hٱ+ i`bF-烋BًуB!hiGiA FHFd$ -CFFF `i( rF`i)F 8CP#h"iF@FGF`iL X!*FDaiiN h+уBًуB!hiG0Fr(F^$ -AFF zI1pa9Д$(`irF`i)FB`i*F1F8FAr0FAFN% -AQ`i(N0Fy^Z_HZ8]Hh@`iL` .0F`iLY!NAx.0Fx B x.x% B.5F%`i`iL`<.1F   FhF!{ (I " o( p O> hq>N^  L^ A D) |HhL\!h pG>T) pyLF i1 p@ !0lsHqBrHaoHq 0pp,) pF FF(#FF 2F)F Fp@() p F6hy("xp@# p) -A &B@WHDhBЫw &}EP a ㊢a EVȱaL]! oF(Х8FowF?Hqpb!(FE[y0&O &M &K zV (e T{W H`J!aA(h(F%HqC)F F(& 8F  y I !FYnhI` 1FA0˽L + F@ L^!@ I @ !0 ) c) \ 4 jT+ -AF FFpбi))F(pEi 8h09h 0p8hq BF1F(FA|n A!0r6+ -AFF F!pC0:F1F(FA| A!0YT+ #* )hAhB L_!౱zB{BAq B 1!#B#FpGd<, FK h_!@ вz_вzo!8`O0pG!80`Oz0pG!80`O pGX , -GF FO ()h y!O(by;xB(z*(hAq.hq y8(! L`!o8xJ`yhh)h Hq:xB F F9x0r(h@y( yq)hD- -AF FUO(G y'(!{)JayxB(hGq.h(((wq { F@ ($()h Hq { F@ ( M(h@y( yq)hHhIx xLa!0r)h- -GF F&O (m y(ҡxβOȱ(ءx)(؝JayxB (.. . .)h4v/h0((&Ї'xcy(2F 6(1( )h Hqxcy(2F ( xay( (h@y( yq)hwHhvIxLb! x8r )h. -AF F'(m#yO+ؠx(cJayxB)h+²x.h((c#+!+2<ІR( F(  (:(' F  )h Hq( F(  !( F  ((   T(h@y( yq(h9IGLc!p7H xhx0r(hGq/ p ( &`xmF(" )I yp  F< F F FT  ) F8 AyFpB0 p80Nr0 FPIx H Hx(rHx s `s+^ (^ 4^ 0^ *^ ,^ Ld! !T) 0 -A {@{NyrqAFq)) Pq -lIkI Ol h# C CeJ`hOO `O(F'(FƲ1F(Fq `q,R1 p {!F0 Pqpqxq `qp*z1 FrlJJA!Le!@raN1 pF FrXAKF $,, "B"@"p p@Fr<,1 0L8 _* h@ ` h  `@ _D2 F'HxZ*!F OT]K !F F@]k F@R2 I{|btd2 H|q PqLf!pGt2 p 0FxzyB(F `qp22  F{,q `qh22 55`, A 2 p#LGDFF hB0ܡA?9)>*м*-=! q hrZ(Fkp@! qH p@JrIp@AT I i) нp@GIz x pr7p@0p' Ȟ ( Lg!$X3 F$H $G F ` x3 !L!K!hBBD ` ` JPhDP` Fh#Bzr@( 4\B^d\@( H|@ Hx H DHxDp# H` A & & L# *4 FmH>J@q#xZCQCq FLh!@LuB4 pFgF F Fpp i ( Fn h`Hi) h0a FKi$H1A)sish` H`)F FK r"FIqH@q"xPCAC(FqX%e pX4 pF F!px! ) ay!ipp@!s(Fp@"!xѼ71 dLi!dcM^ H45 i1 I *  K$[h{S*щh #  # HP0h0 ac*с@@B`c@1H8Lq!/I `,HkAcOcO`/HiAahA`$IG`#IO@`"HhKr"hA1`Hh!J!hAA@`IO@`p< pGr< I kH`Jh`kbJhaJhBa Jha Jha Jhb hAb I hA`pG ^ d``AAAXA(AA`e !:@= Lr!J(2pG!d#XC#0221DDpGv= -A!K FFFOGMh/`+h.` D@IBӠB  OzqHC!@ !@POBqI hHh @DI hI h@@B@B@8> pF(4 FFLs! 0Fv)F4 p*F> FHh лHDCO $ Fl> H@IP9x> kX8b LP<0  ЦH;@ՠL h@ Hx@H@"! T h@ `z> p%kLPFgq(tlC(pє2(ldH0 c٠{l^M((Lwu!(! (h@B @!lE(h@{FiFlhFlF萔2  hDBصDz%O F 246 & DB+ DDD@>4(V@*HxFDI!&I F4N(ل2 Lrv!FnmBӔ<@<N( ٔ2(ф2 FXR _ !A^ !^ ^ V |  A  ~ [ D+ `PdA |%F))є2(YN{iFl.C UHhs1hBح2P|A ML <@i>@iGj}EHLmw! CHhjBH8;(iiV hP|)8IIx!; ;(hI i(IDB p(L <i%Op%aaij4!Hf HhiiH`Zi:h w h8|)IIx ~HxE h H<(hILhx! pH"FhF[hD+ $1? D <  4 " C -OOFO8h (x(~pqzH"!`OF&b!OH&f`2 IrHeOEO I(xO OaiH` 8hH pi!ah!`qd(x4Fг ! p9`iBahBLcy!`HFbx*"B " B"KJF`ixIJ2`ix`FI` OzsOEF@Bkh OHO1f Io಩x@`)'*. 0 @`$ !Aa$@`x a`$(y( @B@ 0 0( (L^z!~ y}F!@FEHh H`(x 8ho[>` 0D F 0( `q a A 1 `$ E n_HhA`@, @E -A F&I#x@B\+[۲+#$ #$NHD/DDp`8D(DDLY{!H/DDmq`(DDm`p`0`HQ6(   ,Q   E -O&FzFp78F_ @`F``_ O p``_ LO @ (ҭNLT|!@ B@oDHABH-~д#k"@1Hp'Yc^<'D@ո J;FBHAhF_B( IIh@ iFHD@ոJF!FhF _3йRF!FhF _+LO}!2F!FhF_$XhF_0`J@]    @`B``-k@ya2H -OFFFF0_(xЊ@HhhHhh hHhh `LJ~!H``hF_^N LhF`%O OF  @ BBO @&$hF_Q(BO ) hhF_!BdDEӽAv .m/ӹ` `@bHh`A``HF jI pFLE!L% h_K i%_.(zTHxi%  h ho !FhF^BNѽBO-Fѭ x%7Hx(PBѴ,0x8iԭPP'BFpxiB ^@BL@!@BF#*FhF_UhF_pMаx-б-%3hi  ԴBҴB٤ P1 2G1 !I1 i  ԴBҴB٤%'I" h@`A``! F(FpjF!n 0A O9 @()J0B Bm- `hh@`d ,8h0D8`` `L1! !LM 4Hh4H`4I hA`4IIh`pGbM 3Hh/H`2I hA`.I h`pGxM p/H&%h.L|").)))%!)'()*)+)%`p@&`p%`p9(@C1B`@jeY(M qQ@G> N  L x GM pL,!  h`  !  ? dda DN JIHPnIpVN IH9`I``pG,hN JK(( hHx(C`pGCHN JL2@c(( h Ix) ЭI9ɈQa@`hcpN pJKLx;MR}Q J Kt:(( hHx(O``pG%  , c + a + A( & , $ `D d`H 0L! 4 8 AL A< @ * Q F0 *R JG>;) EEG;JJ))N0Xv0W;JhoB99L:K)|QiHAQaO1`0pGh gahR|`h`QicCQa0W0W0Wٿ 0W0FW0W ||R IE `HxOHL!!|QAQh!p!A!`Am!Ae!?Ah!paAa`Am!1AepG2 !e 1R -AY pFL!%o7F Fo !oF Fo!Opo0Fo%(Fp>Z pHh )F Fo0D)F Fp@o$h,ѽp@!Opop2VZ p MF$(xPFo(|@|*xPCB$ Fp + !(Z I hHh!p1`Op pGg X X  <^ZlL͖!  {X|   Sں ! I"^b #,W $Shd" %$Q½ &hS'" 'dpk_&# (kiڻ )lk$ *ikN% +hk& Lȗ!,`s, -D&`h' .r / 0M{ 1|F  2: 34 4HL 5x: 6 d 7xBx 8`B  9x  LØ!: sܿ ;psB < lyn =F 0>dlǿB4 ?gi @amp4 A  Biʼx5 Cf, D3Ը< E>H F8~ Ge L!H L[̼ Ib6 J K p L  M a8 NaJ Oڻ\ P,B|l QG{>| R$ ػ7 Sl ۻ&8 9 T@9 L!: UDN VN WNԻ XNr YNB ZbT [4t \x> ]x> ^Dt _ `L@ҺE aK btML! cG d45޸ e7 fK g8  hDM i& j Q k 4 |U hX l`X m  P nd9Q0Y odV|`L! p #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "extmod/machine_pulse.h" #include "drivers/dht/dht.h" // Allow the open-drain-high call to be DHT specific for ports that need it #ifndef mp_hal_pin_od_high_dht #define mp_hal_pin_od_high_dht mp_hal_pin_od_high #endif STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in); mp_hal_pin_open_drain(pin); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); if (bufinfo.len < 5) { mp_raise_ValueError("buffer too small"); } // issue start command mp_hal_pin_od_high_dht(pin); mp_hal_delay_ms(250); mp_hal_pin_od_low(pin); mp_hal_delay_ms(18); mp_uint_t irq_state = mp_hal_quiet_timing_enter(); // release the line so the device can respond mp_hal_pin_od_high_dht(pin); mp_hal_delay_us_fast(10); // wait for device to respond mp_uint_t ticks = mp_hal_ticks_us(); while (mp_hal_pin_read(pin) != 0) { if ((mp_uint_t)(mp_hal_ticks_us() - ticks) > 100) { goto timeout; } } // time pulse, should be 80us ticks = machine_time_pulse_us(pin, 1, 150); if ((mp_int_t)ticks < 0) { goto timeout; } // time 40 pulses for data (either 26us or 70us) uint8_t *buf = bufinfo.buf; for (int i = 0; i < 40; ++i) { ticks = machine_time_pulse_us(pin, 1, 100); if ((mp_int_t)ticks < 0) { goto timeout; } buf[i / 8] = (buf[i / 8] << 1) | (ticks > 48); } mp_hal_quiet_timing_exit(irq_state); return mp_const_none; timeout: mp_hal_quiet_timing_exit(irq_state); mp_raise_OSError(MP_ETIMEDOUT); } MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto); micropython-1.12/drivers/dht/dht.h000066400000000000000000000003101357706137100172010ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_DRIVERS_DHT_DHT_H #define MICROPY_INCLUDED_DRIVERS_DHT_DHT_H #include "py/obj.h" MP_DECLARE_CONST_FUN_OBJ_2(dht_readinto_obj); #endif // MICROPY_INCLUDED_DRIVERS_DHT_DHT_H micropython-1.12/drivers/dht/dht.py000066400000000000000000000015321357706137100174110ustar00rootroot00000000000000# DHT11/DHT22 driver for MicroPython on ESP8266 # MIT license; Copyright (c) 2016 Damien P. George try: from esp import dht_readinto except: from pyb import dht_readinto class DHTBase: def __init__(self, pin): self.pin = pin self.buf = bytearray(5) def measure(self): buf = self.buf dht_readinto(self.pin, buf) if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xff != buf[4]: raise Exception("checksum error") class DHT11(DHTBase): def humidity(self): return self.buf[0] def temperature(self): return self.buf[2] class DHT22(DHTBase): def humidity(self): return (self.buf[0] << 8 | self.buf[1]) * 0.1 def temperature(self): t = ((self.buf[2] & 0x7f) << 8 | self.buf[3]) * 0.1 if self.buf[2] & 0x80: t = -t return t micropython-1.12/drivers/display/000077500000000000000000000000001357706137100171455ustar00rootroot00000000000000micropython-1.12/drivers/display/lcd160cr.py000066400000000000000000000341041357706137100210370ustar00rootroot00000000000000# Driver for official MicroPython LCD160CR display # MIT license; Copyright (c) 2017 Damien P. George from micropython import const from utime import sleep_ms from ustruct import calcsize, pack_into import uerrno, machine # for set_orient PORTRAIT = const(0) LANDSCAPE = const(1) PORTRAIT_UPSIDEDOWN = const(2) LANDSCAPE_UPSIDEDOWN = const(3) # for set_startup_deco; can be or'd STARTUP_DECO_NONE = const(0) STARTUP_DECO_MLOGO = const(1) STARTUP_DECO_INFO = const(2) _uart_baud_table = { 2400: 0, 4800: 1, 9600: 2, 19200: 3, 38400: 4, 57600: 5, 115200: 6, 230400: 7, 460800: 8, } class LCD160CR: def __init__(self, connect=None, *, pwr=None, i2c=None, spi=None, i2c_addr=98): if connect in ('X', 'Y', 'XY', 'YX'): i = connect[-1] j = connect[0] y = j + '4' elif connect == 'C': i = 2 j = 2 y = 'A7' else: if pwr is None or i2c is None or spi is None: raise ValueError('must specify valid "connect" or all of "pwr", "i2c" and "spi"') if pwr is None: pwr = machine.Pin(y, machine.Pin.OUT) if i2c is None: i2c = machine.I2C(i, freq=1000000) if spi is None: spi = machine.SPI(j, baudrate=13500000, polarity=0, phase=0) if not pwr.value(): pwr(1) sleep_ms(10) # else: # alread have power # lets be optimistic... # set connections self.pwr = pwr self.i2c = i2c self.spi = spi self.i2c_addr = i2c_addr # create temp buffers and memoryviews self.buf16 = bytearray(16) self.buf19 = bytearray(19) self.buf = [None] * 10 for i in range(1, 10): self.buf[i] = memoryview(self.buf16)[0:i] self.buf1 = self.buf[1] self.array4 = [0, 0, 0, 0] # set default orientation and window self.set_orient(PORTRAIT) self._fcmd2b('= n: self.i2c.readfrom_into(self.i2c_addr, buf) return t -= 1 sleep_ms(1) raise OSError(uerrno.ETIMEDOUT) def oflush(self, n=255): t = 5000 while t: self.i2c.readfrom_into(self.i2c_addr + 1, self.buf1) r = self.buf1[0] if r >= n: return t -= 1 machine.idle() raise OSError(uerrno.ETIMEDOUT) def iflush(self): t = 5000 while t: self.i2c.readfrom_into(self.i2c_addr, self.buf16) if self.buf16[0] == 0: return t -= 1 sleep_ms(1) raise OSError(uerrno.ETIMEDOUT) #### MISC METHODS #### @staticmethod def rgb(r, g, b): return ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | (r >> 3) @staticmethod def clip_line(c, w, h): while True: ca = ce = 0 if c[1] < 0: ca |= 8 elif c[1] > h: ca |= 4 if c[0] < 0: ca |= 1 elif c[0] > w: ca |= 2 if c[3] < 0: ce |= 8 elif c[3] > h: ce |= 4 if c[2] < 0: ce |= 1 elif c[2] > w: ce |= 2 if ca & ce: return False elif ca | ce: ca |= ce if ca & 1: if c[2] < c[0]: c[0], c[2] = c[2], c[0] c[1], c[3] = c[3], c[1] c[1] += ((-c[0]) * (c[3] - c[1])) // (c[2] - c[0]) c[0] = 0 elif ca & 2: if c[2] < c[0]: c[0], c[2] = c[2], c[0] c[1], c[3] = c[3], c[1] c[3] += ((w - 1 - c[2]) * (c[3] - c[1])) // (c[2] - c[0]) c[2] = w - 1 elif ca & 4: if c[0] == c[2]: if c[1] >= h: c[1] = h - 1 if c[3] >= h: c[3] = h - 1 else: if c[3] < c[1]: c[0], c[2] = c[2], c[0] c[1], c[3] = c[3], c[1] c[2] += ((h - 1 - c[3]) * (c[2] - c[0])) // (c[3] - c[1]) c[3] = h - 1 else: if c[0] == c[2]: if c[1] < 0: c[1] = 0 if c[3] < 0: c[3] = 0 else: if c[3] < c[1]: c[0], c[2] = c[2], c[0] c[1], c[3] = c[3], c[1] c[0] += ((-c[1]) * (c[2] - c[0])) // (c[3] - c[1]) c[1] = 0 else: return True #### SETUP COMMANDS #### def set_power(self, on): self.pwr(on) sleep_ms(15) def set_orient(self, orient): self._fcmd2('= 2: self.i2c.readfrom_into(self.i2c_addr, self.buf[3]) return self.buf[3][1] | self.buf[3][2] << 8 t -= 1 sleep_ms(1) raise OSError(uerrno.ETIMEDOUT) def get_line(self, x, y, buf): l = len(buf) // 2 self._fcmd2b('= l: self.i2c.readfrom_into(self.i2c_addr, buf) return t -= 1 sleep_ms(1) raise OSError(uerrno.ETIMEDOUT) def screen_dump(self, buf, x=0, y=0, w=None, h=None): if w is None: w = self.w - x if h is None: h = self.h - y if w <= 127: line = bytearray(2 * w + 1) line2 = None else: # split line if more than 254 bytes needed buflen = (w + 1) // 2 line = bytearray(2 * buflen + 1) line2 = memoryview(line)[:2 * (w - buflen) + 1] for i in range(min(len(buf) // (2 * w), h)): ix = i * w * 2 self.get_line(x, y + i, line) buf[ix:ix + len(line) - 1] = memoryview(line)[1:] ix += len(line) - 1 if line2: self.get_line(x + buflen, y + i, line2) buf[ix:ix + len(line2) - 1] = memoryview(line2)[1:] ix += len(line2) - 1 def screen_load(self, buf): l = self.w * self.h * 2+2 self._fcmd2b('= 0x200: self._send(ar[n:n + 0x200]) n += 0x200 else: self._send(ar[n:]) while n < self.w * self.h * 2: self._send(b'\x00') n += 1 #### TEXT COMMANDS #### def set_pos(self, x, y): self._fcmd2('= self.w or y >= self.h: return elif x < 0 or y < 0: left = top = True if x < 0: left = False w += x x = 0 if y < 0: top = False h += y y = 0 if cmd == 0x51 or cmd == 0x72: # draw interior self._fcmd2b('> 7 != 0 def get_touch(self): self._send(b'\x02T') # implicit LCD output flush b = self.buf[4] self._waitfor(3, b) return b[1] >> 7, b[2], b[3] #### ADVANCED COMMANDS #### def set_spi_win(self, x, y, w, h): pack_into(' 32: raise ValueError('length must be 32 or less') self._fcmd2(' 0xffff: raise ValueError('length must be 65535 or less') self.oflush() self._fcmd2(' 0: s = '%6.3fV' % data[i] else: s = '%5.1f°C' % data[i] if lcd.h == 160: lcd.set_font(1, bold=0, scale=1) else: lcd.set_font(1, bold=0, scale=1, trans=1) lcd.set_pos(45, lcd.h-60 + i * 16) lcd.write(s) def test_features(lcd, orient=lcd160cr.PORTRAIT): # if we run on pyboard then use ADC and RTC features try: import pyb adc = pyb.ADCAll(12, 0xf0000) rtc = pyb.RTC() except: adc = None rtc = None # set orientation and clear screen lcd = get_lcd(lcd) lcd.set_orient(orient) lcd.set_pen(0, 0) lcd.erase() # create M-logo mlogo = framebuf.FrameBuffer(bytearray(17 * 17 * 2), 17, 17, framebuf.RGB565) mlogo.fill(0) mlogo.fill_rect(1, 1, 15, 15, 0xffffff) mlogo.vline(4, 4, 12, 0) mlogo.vline(8, 1, 12, 0) mlogo.vline(12, 4, 12, 0) mlogo.vline(14, 13, 2, 0) # create inline framebuf offx = 14 offy = 19 w = 100 h = 75 fbuf = framebuf.FrameBuffer(bytearray(w * h * 2), w, h, framebuf.RGB565) lcd.set_spi_win(offx, offy, w, h) # initialise loop parameters tx = ty = 0 t0 = time.ticks_us() for i in range(300): # update position of cross-hair t, tx2, ty2 = lcd.get_touch() if t: tx2 -= offx ty2 -= offy if tx2 >= 0 and ty2 >= 0 and tx2 < w and ty2 < h: tx, ty = tx2, ty2 else: tx = (tx + 1) % w ty = (ty + 1) % h # create and show the inline framebuf fbuf.fill(lcd.rgb(128 + int(64 * math.cos(0.1 * i)), 128, 192)) fbuf.line(w // 2, h // 2, w // 2 + int(40 * math.cos(0.2 * i)), h // 2 + int(40 * math.sin(0.2 * i)), lcd.rgb(128, 255, 64)) fbuf.hline(0, ty, w, lcd.rgb(64, 64, 64)) fbuf.vline(tx, 0, h, lcd.rgb(64, 64, 64)) fbuf.rect(tx - 3, ty - 3, 7, 7, lcd.rgb(64, 64, 64)) for phase in (-0.2, 0, 0.2): x = w // 2 - 8 + int(50 * math.cos(0.05 * i + phase)) y = h // 2 - 8 + int(32 * math.sin(0.05 * i + phase)) fbuf.blit(mlogo, x, y) for j in range(-3, 3): fbuf.text('MicroPython', 5, h // 2 + 9 * j + int(20 * math.sin(0.1 * (i + j))), lcd.rgb(128 + 10 * j, 0, 128 - 10 * j)) lcd.show_framebuf(fbuf) # show results from the ADC if adc: show_adc(lcd, adc) # show the time if rtc: lcd.set_pos(2, 0) lcd.set_font(1) t = rtc.datetime() lcd.write('%4d-%02d-%02d %2d:%02d:%02d.%01d' % (t[0], t[1], t[2], t[4], t[5], t[6], t[7] // 100000)) # compute the frame rate t1 = time.ticks_us() dt = time.ticks_diff(t1, t0) t0 = t1 # show the frame rate lcd.set_pos(2, 9) lcd.write('%.2f fps' % (1000000 / dt)) def test_mandel(lcd, orient=lcd160cr.PORTRAIT): # set orientation and clear screen lcd = get_lcd(lcd) lcd.set_orient(orient) lcd.set_pen(0, 0xffff) lcd.erase() # function to compute Mandelbrot pixels def in_set(c): z = 0 for i in range(32): z = z * z + c if abs(z) > 100: return i return 0 # cache width and height of LCD w = lcd.w h = lcd.h # create the buffer for each line and set SPI parameters line = bytearray(w * 2) lcd.set_spi_win(0, 0, w, h) spi = lcd.fast_spi() # draw the Mandelbrot set line-by-line hh = ((h - 1) / 3.2) ww = ((w - 1) / 2.4) for v in range(h): for u in range(w): c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j) if c < 16: rgb = c << 12 | c << 6 else: rgb = 0xf800 | c << 6 line[2 * u] = rgb line[2 * u + 1] = rgb >> 8 spi.write(line) def test_all(lcd, orient=lcd160cr.PORTRAIT): lcd = get_lcd(lcd) test_features(lcd, orient) test_mandel(lcd, orient) print('To run all tests: test_all()') print('Individual tests are: test_features, test_mandel') print(' argument should be a connection, eg "X", or an LCD160CR object') micropython-1.12/drivers/display/ssd1306.py000066400000000000000000000106711357706137100206270ustar00rootroot00000000000000# MicroPython SSD1306 OLED driver, I2C and SPI interfaces from micropython import const import framebuf # register definitions SET_CONTRAST = const(0x81) SET_ENTIRE_ON = const(0xa4) SET_NORM_INV = const(0xa6) SET_DISP = const(0xae) SET_MEM_ADDR = const(0x20) SET_COL_ADDR = const(0x21) SET_PAGE_ADDR = const(0x22) SET_DISP_START_LINE = const(0x40) SET_SEG_REMAP = const(0xa0) SET_MUX_RATIO = const(0xa8) SET_COM_OUT_DIR = const(0xc0) SET_DISP_OFFSET = const(0xd3) SET_COM_PIN_CFG = const(0xda) SET_DISP_CLK_DIV = const(0xd5) SET_PRECHARGE = const(0xd9) SET_VCOM_DESEL = const(0xdb) SET_CHARGE_PUMP = const(0x8d) # Subclassing FrameBuffer provides support for graphics primitives # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html class SSD1306(framebuf.FrameBuffer): def __init__(self, width, height, external_vcc): self.width = width self.height = height self.external_vcc = external_vcc self.pages = self.height // 8 self.buffer = bytearray(self.pages * self.width) super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB) self.init_display() def init_display(self): for cmd in ( SET_DISP | 0x00, # off # address setting SET_MEM_ADDR, 0x00, # horizontal # resolution and layout SET_DISP_START_LINE | 0x00, SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 SET_MUX_RATIO, self.height - 1, SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 SET_DISP_OFFSET, 0x00, SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12, # timing and driving scheme SET_DISP_CLK_DIV, 0x80, SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1, SET_VCOM_DESEL, 0x30, # 0.83*Vcc # display SET_CONTRAST, 0xff, # maximum SET_ENTIRE_ON, # output follows RAM contents SET_NORM_INV, # not inverted # charge pump SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14, SET_DISP | 0x01): # on self.write_cmd(cmd) self.fill(0) self.show() def poweroff(self): self.write_cmd(SET_DISP | 0x00) def poweron(self): self.write_cmd(SET_DISP | 0x01) def contrast(self, contrast): self.write_cmd(SET_CONTRAST) self.write_cmd(contrast) def invert(self, invert): self.write_cmd(SET_NORM_INV | (invert & 1)) def show(self): x0 = 0 x1 = self.width - 1 if self.width == 64: # displays with width of 64 pixels are shifted by 32 x0 += 32 x1 += 32 self.write_cmd(SET_COL_ADDR) self.write_cmd(x0) self.write_cmd(x1) self.write_cmd(SET_PAGE_ADDR) self.write_cmd(0) self.write_cmd(self.pages - 1) self.write_data(self.buffer) class SSD1306_I2C(SSD1306): def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False): self.i2c = i2c self.addr = addr self.temp = bytearray(2) self.write_list = [b'\x40', None] # Co=0, D/C#=1 super().__init__(width, height, external_vcc) def write_cmd(self, cmd): self.temp[0] = 0x80 # Co=1, D/C#=0 self.temp[1] = cmd self.i2c.writeto(self.addr, self.temp) def write_data(self, buf): self.write_list[1] = buf self.i2c.writevto(self.addr, self.write_list) class SSD1306_SPI(SSD1306): def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): self.rate = 10 * 1024 * 1024 dc.init(dc.OUT, value=0) res.init(res.OUT, value=0) cs.init(cs.OUT, value=1) self.spi = spi self.dc = dc self.res = res self.cs = cs import time self.res(1) time.sleep_ms(1) self.res(0) time.sleep_ms(10) self.res(1) super().__init__(width, height, external_vcc) def write_cmd(self, cmd): self.spi.init(baudrate=self.rate, polarity=0, phase=0) self.cs(1) self.dc(0) self.cs(0) self.spi.write(bytearray([cmd])) self.cs(1) def write_data(self, buf): self.spi.init(baudrate=self.rate, polarity=0, phase=0) self.cs(1) self.dc(1) self.cs(0) self.spi.write(buf) self.cs(1) micropython-1.12/drivers/memory/000077500000000000000000000000001357706137100170105ustar00rootroot00000000000000micropython-1.12/drivers/memory/spiflash.c000066400000000000000000000367171357706137100210030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mperrno.h" #include "py/mphal.h" #include "drivers/memory/spiflash.h" #define QSPI_QE_MASK (0x02) #define USE_WR_DELAY (1) #define CMD_WRSR (0x01) #define CMD_WRITE (0x02) #define CMD_READ (0x03) #define CMD_RDSR (0x05) #define CMD_WREN (0x06) #define CMD_SEC_ERASE (0x20) #define CMD_RDCR (0x35) #define CMD_RD_DEVID (0x9f) #define CMD_CHIP_ERASE (0xc7) #define CMD_C4READ (0xeb) #define WAIT_SR_TIMEOUT (1000000) #define PAGE_SIZE (256) // maximum bytes we can write in one SPI transfer #define SECTOR_SIZE MP_SPIFLASH_ERASE_BLOCK_SIZE STATIC void mp_spiflash_acquire_bus(mp_spiflash_t *self) { const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) { c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_ACQUIRE); } } STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) { const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_QSPI) { c->bus.u_qspi.proto->ioctl(c->bus.u_qspi.data, MP_QSPI_IOCTL_BUS_RELEASE); } } STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) { const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { // Note: len/data are unused for standard SPI mp_hal_pin_write(c->bus.u_spi.cs, 0); c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 1, &cmd, NULL); mp_hal_pin_write(c->bus.u_spi.cs, 1); } else { c->bus.u_qspi.proto->write_cmd_data(c->bus.u_qspi.data, cmd, len, data); } } STATIC void mp_spiflash_write_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { uint8_t buf[4] = {cmd, addr >> 16, addr >> 8, addr}; mp_hal_pin_write(c->bus.u_spi.cs, 0); c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL); if (len) { c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, src, NULL); } mp_hal_pin_write(c->bus.u_spi.cs, 1); } else { c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src); } } STATIC uint32_t mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len) { const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { uint32_t buf; mp_hal_pin_write(c->bus.u_spi.cs, 0); c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 1, &cmd, NULL); c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, (void*)&buf, (void*)&buf); mp_hal_pin_write(c->bus.u_spi.cs, 1); return buf; } else { return c->bus.u_qspi.proto->read_cmd(c->bus.u_qspi.data, cmd, len); } } STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { uint8_t buf[4] = {CMD_READ, addr >> 16, addr >> 8, addr}; mp_hal_pin_write(c->bus.u_spi.cs, 0); c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL); c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest); mp_hal_pin_write(c->bus.u_spi.cs, 1); } else { c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, CMD_C4READ, addr, len, dest); } } STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) { mp_spiflash_write_cmd_data(self, cmd, 0, 0); } STATIC void mp_spiflash_write_cmd_addr(mp_spiflash_t *self, uint8_t cmd, uint32_t addr) { mp_spiflash_write_cmd_addr_data(self, cmd, addr, 0, NULL); } STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) { uint8_t sr; do { sr = mp_spiflash_read_cmd(self, CMD_RDSR, 1); if ((sr & mask) == val) { return 0; // success } } while (timeout--); return -MP_ETIMEDOUT; } STATIC int mp_spiflash_wait_wel1(mp_spiflash_t *self) { return mp_spiflash_wait_sr(self, 2, 2, WAIT_SR_TIMEOUT); } STATIC int mp_spiflash_wait_wip0(mp_spiflash_t *self) { return mp_spiflash_wait_sr(self, 1, 0, WAIT_SR_TIMEOUT); } static inline void mp_spiflash_deepsleep_internal(mp_spiflash_t *self, int value) { mp_spiflash_write_cmd(self, value ? 0xb9 : 0xab); // sleep/wake } void mp_spiflash_init(mp_spiflash_t *self) { self->flags = 0; if (self->config->bus_kind == MP_SPIFLASH_BUS_SPI) { mp_hal_pin_write(self->config->bus.u_spi.cs, 1); mp_hal_pin_output(self->config->bus.u_spi.cs); self->config->bus.u_spi.proto->ioctl(self->config->bus.u_spi.data, MP_SPI_IOCTL_INIT); } else { self->config->bus.u_qspi.proto->ioctl(self->config->bus.u_qspi.data, MP_QSPI_IOCTL_INIT); } mp_spiflash_acquire_bus(self); // Ensure SPI flash is out of sleep mode mp_spiflash_deepsleep_internal(self, 0); #if defined(CHECK_DEVID) // Validate device id uint32_t devid = mp_spiflash_read_cmd(self, CMD_RD_DEVID, 3); if (devid != CHECK_DEVID) { return 0; } #endif if (self->config->bus_kind == MP_SPIFLASH_BUS_QSPI) { // Set QE bit uint32_t data = (mp_spiflash_read_cmd(self, CMD_RDSR, 1) & 0xff) | (mp_spiflash_read_cmd(self, CMD_RDCR, 1) & 0xff) << 8; if (!(data & (QSPI_QE_MASK << 8))) { data |= QSPI_QE_MASK << 8; mp_spiflash_write_cmd(self, CMD_WREN); mp_spiflash_write_cmd_data(self, CMD_WRSR, 2, data); mp_spiflash_wait_wip0(self); } } mp_spiflash_release_bus(self); } void mp_spiflash_deepsleep(mp_spiflash_t *self, int value) { if (value) { mp_spiflash_acquire_bus(self); } mp_spiflash_deepsleep_internal(self, value); if (!value) { mp_spiflash_release_bus(self); } } STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) { // enable writes mp_spiflash_write_cmd(self, CMD_WREN); // wait WEL=1 int ret = mp_spiflash_wait_wel1(self); if (ret != 0) { return ret; } // erase the sector mp_spiflash_write_cmd_addr(self, CMD_SEC_ERASE, addr); // wait WIP=0 return mp_spiflash_wait_wip0(self); } STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { // enable writes mp_spiflash_write_cmd(self, CMD_WREN); // wait WEL=1 int ret = mp_spiflash_wait_wel1(self); if (ret != 0) { return ret; } // write the page mp_spiflash_write_cmd_addr_data(self, CMD_WRITE, addr, len, src); // wait WIP=0 return mp_spiflash_wait_wip0(self); } /******************************************************************************/ // Interface functions that go direct to the SPI flash device int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr) { mp_spiflash_acquire_bus(self); int ret = mp_spiflash_erase_block_internal(self, addr); mp_spiflash_release_bus(self); return ret; } void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { if (len == 0) { return; } mp_spiflash_acquire_bus(self); mp_spiflash_read_data(self, addr, len, dest); mp_spiflash_release_bus(self); } int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { mp_spiflash_acquire_bus(self); int ret = 0; uint32_t offset = addr & (PAGE_SIZE - 1); while (len) { size_t rest = PAGE_SIZE - offset; if (rest > len) { rest = len; } ret = mp_spiflash_write_page(self, addr, rest, src); if (ret != 0) { break; } len -= rest; addr += rest; src += rest; offset = 0; } mp_spiflash_release_bus(self); return ret; } /******************************************************************************/ // Interface functions that use the cache void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { if (len == 0) { return; } mp_spiflash_acquire_bus(self); mp_spiflash_cache_t *cache = self->config->cache; if (cache->user == self && cache->block != 0xffffffff) { uint32_t bis = addr / SECTOR_SIZE; uint32_t bie = (addr + len - 1) / SECTOR_SIZE; if (bis <= cache->block && cache->block <= bie) { // Read straddles current buffer size_t rest = 0; if (bis < cache->block) { // Read direct from flash for first part rest = cache->block * SECTOR_SIZE - addr; mp_spiflash_read_data(self, addr, rest, dest); len -= rest; dest += rest; addr += rest; } uint32_t offset = addr & (SECTOR_SIZE - 1); rest = SECTOR_SIZE - offset; if (rest > len) { rest = len; } memcpy(dest, &cache->buf[offset], rest); len -= rest; if (len == 0) { mp_spiflash_release_bus(self); return; } dest += rest; addr += rest; } } // Read rest direct from flash mp_spiflash_read_data(self, addr, len, dest); mp_spiflash_release_bus(self); } STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) { #if USE_WR_DELAY if (!(self->flags & 1)) { return; } self->flags &= ~1; mp_spiflash_cache_t *cache = self->config->cache; // Erase sector int ret = mp_spiflash_erase_block_internal(self, cache->block * SECTOR_SIZE); if (ret != 0) { return; } // Write for (int i = 0; i < 16; i += 1) { uint32_t addr = cache->block * SECTOR_SIZE + i * PAGE_SIZE; int ret = mp_spiflash_write_page(self, addr, PAGE_SIZE, cache->buf + i * PAGE_SIZE); if (ret != 0) { return; } } #endif } void mp_spiflash_cache_flush(mp_spiflash_t *self) { mp_spiflash_acquire_bus(self); mp_spiflash_cache_flush_internal(self); mp_spiflash_release_bus(self); } STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { // Align to 4096 sector uint32_t offset = addr & 0xfff; uint32_t sec = addr >> 12; addr = sec << 12; // Restriction for now, so we don't need to erase multiple pages if (offset + len > SECTOR_SIZE) { printf("mp_spiflash_cached_write_part: len is too large\n"); return -MP_EIO; } mp_spiflash_cache_t *cache = self->config->cache; // Acquire the sector buffer if (cache->user != self) { if (cache->user != NULL) { mp_spiflash_cache_flush(cache->user); } cache->user = self; cache->block = 0xffffffff; } if (cache->block != sec) { // Read sector #if USE_WR_DELAY if (cache->block != 0xffffffff) { mp_spiflash_cache_flush_internal(self); } #endif mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf); } #if USE_WR_DELAY cache->block = sec; // Just copy to buffer memcpy(cache->buf + offset, src, len); // And mark dirty self->flags |= 1; #else uint32_t dirty = 0; for (size_t i = 0; i < len; ++i) { if (cache->buf[offset + i] != src[i]) { if (cache->buf[offset + i] != 0xff) { // Erase sector int ret = mp_spiflash_erase_block_internal(self, addr); if (ret != 0) { return ret; } dirty = 0xffff; break; } else { dirty |= (1 << ((offset + i) >> 8)); } } } cache->block = sec; // Copy new block into buffer memcpy(cache->buf + offset, src, len); // Write sector in pages of 256 bytes for (size_t i = 0; i < 16; ++i) { if (dirty & (1 << i)) { int ret = mp_spiflash_write_page(self, addr + i * PAGE_SIZE, PAGE_SIZE, cache->buf + i * PAGE_SIZE); if (ret != 0) { return ret; } } } #endif return 0; // success } int mp_spiflash_cached_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { uint32_t bis = addr / SECTOR_SIZE; uint32_t bie = (addr + len - 1) / SECTOR_SIZE; mp_spiflash_acquire_bus(self); mp_spiflash_cache_t *cache = self->config->cache; if (cache->user == self && bis <= cache->block && bie >= cache->block) { // Write straddles current buffer uint32_t pre; uint32_t offset; if (cache->block * SECTOR_SIZE >= addr) { pre = cache->block * SECTOR_SIZE - addr; offset = 0; } else { pre = 0; offset = addr - cache->block * SECTOR_SIZE; } // Write buffered part first uint32_t len_in_buf = len - pre; len = 0; if (len_in_buf > SECTOR_SIZE - offset) { len = len_in_buf - (SECTOR_SIZE - offset); len_in_buf = SECTOR_SIZE - offset; } memcpy(&cache->buf[offset], &src[pre], len_in_buf); self->flags |= 1; // Mark dirty // Write part before buffer sector while (pre) { int rest = pre & (SECTOR_SIZE - 1); if (rest == 0) { rest = SECTOR_SIZE; } int ret = mp_spiflash_cached_write_part(self, addr, rest, src); if (ret != 0) { mp_spiflash_release_bus(self); return ret; } src += rest; addr += rest; pre -= rest; } src += len_in_buf; addr += len_in_buf; // Fall through to write remaining part } uint32_t offset = addr & (SECTOR_SIZE - 1); while (len) { int rest = SECTOR_SIZE - offset; if (rest > len) { rest = len; } int ret = mp_spiflash_cached_write_part(self, addr, rest, src); if (ret != 0) { mp_spiflash_release_bus(self); return ret; } len -= rest; addr += rest; src += rest; offset = 0; } mp_spiflash_release_bus(self); return 0; } micropython-1.12/drivers/memory/spiflash.h000066400000000000000000000063041357706137100207750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H #define MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H #include "drivers/bus/spi.h" #include "drivers/bus/qspi.h" #define MP_SPIFLASH_ERASE_BLOCK_SIZE (4096) // must be a power of 2 enum { MP_SPIFLASH_BUS_SPI, MP_SPIFLASH_BUS_QSPI, }; struct _mp_spiflash_t; // A cache must be provided by the user in the config struct. The same cache // struct can be shared by multiple SPI flash instances. typedef struct _mp_spiflash_cache_t { uint8_t buf[MP_SPIFLASH_ERASE_BLOCK_SIZE] __attribute__((aligned(4))); struct _mp_spiflash_t *user; // current user of buf, for shared use uint32_t block; // current block stored in buf; 0xffffffff if invalid } mp_spiflash_cache_t; typedef struct _mp_spiflash_config_t { uint32_t bus_kind; union { struct { mp_hal_pin_obj_t cs; void *data; const mp_spi_proto_t *proto; } u_spi; struct { void *data; const mp_qspi_proto_t *proto; } u_qspi; } bus; mp_spiflash_cache_t *cache; // can be NULL if cache functions not used } mp_spiflash_config_t; typedef struct _mp_spiflash_t { const mp_spiflash_config_t *config; volatile uint32_t flags; } mp_spiflash_t; void mp_spiflash_init(mp_spiflash_t *self); void mp_spiflash_deepsleep(mp_spiflash_t *self, int value); // These functions go direct to the SPI flash device int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr); void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest); int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src); // These functions use the cache (which must already be configured) void mp_spiflash_cache_flush(mp_spiflash_t *self); void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest); int mp_spiflash_cached_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src); #endif // MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H micropython-1.12/drivers/nrf24l01/000077500000000000000000000000001357706137100167505ustar00rootroot00000000000000micropython-1.12/drivers/nrf24l01/nrf24l01.py000066400000000000000000000167341357706137100206050ustar00rootroot00000000000000"""NRF24L01 driver for MicroPython """ from micropython import const import utime # nRF24L01+ registers CONFIG = const(0x00) EN_RXADDR = const(0x02) SETUP_AW = const(0x03) SETUP_RETR = const(0x04) RF_CH = const(0x05) RF_SETUP = const(0x06) STATUS = const(0x07) RX_ADDR_P0 = const(0x0a) TX_ADDR = const(0x10) RX_PW_P0 = const(0x11) FIFO_STATUS = const(0x17) DYNPD = const(0x1c) # CONFIG register EN_CRC = const(0x08) # enable CRC CRCO = const(0x04) # CRC encoding scheme; 0=1 byte, 1=2 bytes PWR_UP = const(0x02) # 1=power up, 0=power down PRIM_RX = const(0x01) # RX/TX control; 0=PTX, 1=PRX # RF_SETUP register POWER_0 = const(0x00) # -18 dBm POWER_1 = const(0x02) # -12 dBm POWER_2 = const(0x04) # -6 dBm POWER_3 = const(0x06) # 0 dBm SPEED_1M = const(0x00) SPEED_2M = const(0x08) SPEED_250K = const(0x20) # STATUS register RX_DR = const(0x40) # RX data ready; write 1 to clear TX_DS = const(0x20) # TX data sent; write 1 to clear MAX_RT = const(0x10) # max retransmits reached; write 1 to clear # FIFO_STATUS register RX_EMPTY = const(0x01) # 1 if RX FIFO is empty # constants for instructions R_RX_PL_WID = const(0x60) # read RX payload width R_RX_PAYLOAD = const(0x61) # read RX payload W_TX_PAYLOAD = const(0xa0) # write TX payload FLUSH_TX = const(0xe1) # flush TX FIFO FLUSH_RX = const(0xe2) # flush RX FIFO NOP = const(0xff) # use to read STATUS register class NRF24L01: def __init__(self, spi, cs, ce, channel=46, payload_size=16): assert payload_size <= 32 self.buf = bytearray(1) # store the pins self.spi = spi self.cs = cs self.ce = ce # init the SPI bus and pins self.init_spi(4000000) # reset everything ce.init(ce.OUT, value=0) cs.init(cs.OUT, value=1) self.payload_size = payload_size self.pipe0_read_addr = None utime.sleep_ms(5) # set address width to 5 bytes and check for device present self.reg_write(SETUP_AW, 0b11) if self.reg_read(SETUP_AW) != 0b11: raise OSError("nRF24L01+ Hardware not responding") # disable dynamic payloads self.reg_write(DYNPD, 0) # auto retransmit delay: 1750us # auto retransmit count: 8 self.reg_write(SETUP_RETR, (6 << 4) | 8) # set rf power and speed self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links # init CRC self.set_crc(2) # clear status flags self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) # set channel self.set_channel(channel) # flush buffers self.flush_rx() self.flush_tx() def init_spi(self, baudrate): try: master = self.spi.MASTER except AttributeError: self.spi.init(baudrate=baudrate, polarity=0, phase=0) else: self.spi.init(master, baudrate=baudrate, polarity=0, phase=0) def reg_read(self, reg): self.cs(0) self.spi.readinto(self.buf, reg) self.spi.readinto(self.buf) self.cs(1) return self.buf[0] def reg_write_bytes(self, reg, buf): self.cs(0) self.spi.readinto(self.buf, 0x20 | reg) self.spi.write(buf) self.cs(1) return self.buf[0] def reg_write(self, reg, value): self.cs(0) self.spi.readinto(self.buf, 0x20 | reg) ret = self.buf[0] self.spi.readinto(self.buf, value) self.cs(1) return ret def flush_rx(self): self.cs(0) self.spi.readinto(self.buf, FLUSH_RX) self.cs(1) def flush_tx(self): self.cs(0) self.spi.readinto(self.buf, FLUSH_TX) self.cs(1) # power is one of POWER_x defines; speed is one of SPEED_x defines def set_power_speed(self, power, speed): setup = self.reg_read(RF_SETUP) & 0b11010001 self.reg_write(RF_SETUP, setup | power | speed) # length in bytes: 0, 1 or 2 def set_crc(self, length): config = self.reg_read(CONFIG) & ~(CRCO | EN_CRC) if length == 0: pass elif length == 1: config |= EN_CRC else: config |= EN_CRC | CRCO self.reg_write(CONFIG, config) def set_channel(self, channel): self.reg_write(RF_CH, min(channel, 125)) # address should be a bytes object 5 bytes long def open_tx_pipe(self, address): assert len(address) == 5 self.reg_write_bytes(RX_ADDR_P0, address) self.reg_write_bytes(TX_ADDR, address) self.reg_write(RX_PW_P0, self.payload_size) # address should be a bytes object 5 bytes long # pipe 0 and 1 have 5 byte address # pipes 2-5 use same 4 most-significant bytes as pipe 1, plus 1 extra byte def open_rx_pipe(self, pipe_id, address): assert len(address) == 5 assert 0 <= pipe_id <= 5 if pipe_id == 0: self.pipe0_read_addr = address if pipe_id < 2: self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address) else: self.reg_write(RX_ADDR_P0 + pipe_id, address[0]) self.reg_write(RX_PW_P0 + pipe_id, self.payload_size) self.reg_write(EN_RXADDR, self.reg_read(EN_RXADDR) | (1 << pipe_id)) def start_listening(self): self.reg_write(CONFIG, self.reg_read(CONFIG) | PWR_UP | PRIM_RX) self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) if self.pipe0_read_addr is not None: self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr) self.flush_rx() self.flush_tx() self.ce(1) utime.sleep_us(130) def stop_listening(self): self.ce(0) self.flush_tx() self.flush_rx() # returns True if any data available to recv def any(self): return not bool(self.reg_read(FIFO_STATUS) & RX_EMPTY) def recv(self): # get the data self.cs(0) self.spi.readinto(self.buf, R_RX_PAYLOAD) buf = self.spi.read(self.payload_size) self.cs(1) # clear RX ready flag self.reg_write(STATUS, RX_DR) return buf # blocking wait for tx complete def send(self, buf, timeout=500): self.send_start(buf) start = utime.ticks_ms() result = None while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout: result = self.send_done() # 1 == success, 2 == fail if result == 2: raise OSError("send failed") # non-blocking tx def send_start(self, buf): # power up self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX) utime.sleep_us(150) # send the data self.cs(0) self.spi.readinto(self.buf, W_TX_PAYLOAD) self.spi.write(buf) if len(buf) < self.payload_size: self.spi.write(b'\x00' * (self.payload_size - len(buf))) # pad out data self.cs(1) # enable the chip so it can send the data self.ce(1) utime.sleep_us(15) # needs to be >10us self.ce(0) # returns None if send still in progress, 1 for success, 2 for fail def send_done(self): if not (self.reg_read(STATUS) & (TX_DS | MAX_RT)): return None # tx not finished # either finished or failed: get and clear status flags, power down status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT) self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP) return 1 if status & TX_DS else 2 micropython-1.12/drivers/nrf24l01/nrf24l01test.py000066400000000000000000000110261357706137100214720ustar00rootroot00000000000000"""Test for nrf24l01 module. Portable between MicroPython targets.""" import sys import ustruct as struct import utime from machine import Pin, SPI from nrf24l01 import NRF24L01 from micropython import const # Slave pause between receiving data and checking for further packets. _RX_POLL_DELAY = const(15) # Slave pauses an additional _SLAVE_SEND_DELAY ms after receiving data and before # transmitting to allow the (remote) master time to get into receive mode. The # master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266. _SLAVE_SEND_DELAY = const(10) if sys.platform == 'pyboard': cfg = {'spi': 2, 'miso': 'Y7', 'mosi': 'Y8', 'sck': 'Y6', 'csn': 'Y5', 'ce': 'Y4'} elif sys.platform == 'esp8266': # Hardware SPI cfg = {'spi': 1, 'miso': 12, 'mosi': 13, 'sck': 14, 'csn': 4, 'ce': 5} elif sys.platform == 'esp32': # Software SPI cfg = {'spi': -1, 'miso': 32, 'mosi': 33, 'sck': 25, 'csn': 26, 'ce': 27} else: raise ValueError('Unsupported platform {}'.format(sys.platform)) pipes = (b'\xf0\xf0\xf0\xf0\xe1', b'\xf0\xf0\xf0\xf0\xd2') def master(): csn = Pin(cfg['csn'], mode=Pin.OUT, value=1) ce = Pin(cfg['ce'], mode=Pin.OUT, value=0) if cfg['spi'] == -1: spi = SPI(-1, sck=Pin(cfg['sck']), mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso'])) nrf = NRF24L01(spi, csn, ce, payload_size=8) else: nrf = NRF24L01(SPI(cfg['spi']), csn, ce, payload_size=8) nrf.open_tx_pipe(pipes[0]) nrf.open_rx_pipe(1, pipes[1]) nrf.start_listening() num_needed = 16 num_successes = 0 num_failures = 0 led_state = 0 print('NRF24L01 master mode, sending %d packets...' % num_needed) while num_successes < num_needed and num_failures < num_needed: # stop listening and send packet nrf.stop_listening() millis = utime.ticks_ms() led_state = max(1, (led_state << 1) & 0x0f) print('sending:', millis, led_state) try: nrf.send(struct.pack('ii', millis, led_state)) except OSError: pass # start listening again nrf.start_listening() # wait for response, with 250ms timeout start_time = utime.ticks_ms() timeout = False while not nrf.any() and not timeout: if utime.ticks_diff(utime.ticks_ms(), start_time) > 250: timeout = True if timeout: print('failed, response timed out') num_failures += 1 else: # recv packet got_millis, = struct.unpack('i', nrf.recv()) # print response and round-trip delay print('got response:', got_millis, '(delay', utime.ticks_diff(utime.ticks_ms(), got_millis), 'ms)') num_successes += 1 # delay then loop utime.sleep_ms(250) print('master finished sending; successes=%d, failures=%d' % (num_successes, num_failures)) def slave(): csn = Pin(cfg['csn'], mode=Pin.OUT, value=1) ce = Pin(cfg['ce'], mode=Pin.OUT, value=0) if cfg['spi'] == -1: spi = SPI(-1, sck=Pin(cfg['sck']), mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso'])) nrf = NRF24L01(spi, csn, ce, payload_size=8) else: nrf = NRF24L01(SPI(cfg['spi']), csn, ce, payload_size=8) nrf.open_tx_pipe(pipes[1]) nrf.open_rx_pipe(1, pipes[0]) nrf.start_listening() print('NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)') while True: if nrf.any(): while nrf.any(): buf = nrf.recv() millis, led_state = struct.unpack('ii', buf) print('received:', millis, led_state) for led in leds: if led_state & 1: led.on() else: led.off() led_state >>= 1 utime.sleep_ms(_RX_POLL_DELAY) # Give master time to get into receive mode. utime.sleep_ms(_SLAVE_SEND_DELAY) nrf.stop_listening() try: nrf.send(struct.pack('i', millis)) except OSError: pass print('sent response') nrf.start_listening() try: import pyb leds = [pyb.LED(i + 1) for i in range(4)] except: leds = [] print('NRF24L01 test module loaded') print('NRF24L01 pinout for test:') print(' CE on', cfg['ce']) print(' CSN on', cfg['csn']) print(' SCK on', cfg['sck']) print(' MISO on', cfg['miso']) print(' MOSI on', cfg['mosi']) print('run nrf24l01test.slave() on slave, then nrf24l01test.master() on master') micropython-1.12/drivers/onewire/000077500000000000000000000000001357706137100171505ustar00rootroot00000000000000micropython-1.12/drivers/onewire/ds18x20.py000066400000000000000000000026531357706137100206410ustar00rootroot00000000000000# DS18x20 temperature sensor driver for MicroPython. # MIT license; Copyright (c) 2016 Damien P. George from micropython import const _CONVERT = const(0x44) _RD_SCRATCH = const(0xbe) _WR_SCRATCH = const(0x4e) class DS18X20: def __init__(self, onewire): self.ow = onewire self.buf = bytearray(9) def scan(self): return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)] def convert_temp(self): self.ow.reset(True) self.ow.writebyte(self.ow.SKIP_ROM) self.ow.writebyte(_CONVERT) def read_scratch(self, rom): self.ow.reset(True) self.ow.select_rom(rom) self.ow.writebyte(_RD_SCRATCH) self.ow.readinto(self.buf) if self.ow.crc8(self.buf): raise Exception('CRC error') return self.buf def write_scratch(self, rom, buf): self.ow.reset(True) self.ow.select_rom(rom) self.ow.writebyte(_WR_SCRATCH) self.ow.write(buf) def read_temp(self, rom): buf = self.read_scratch(rom) if rom[0] == 0x10: if buf[1]: t = buf[0] >> 1 | 0x80 t = -((~t + 1) & 0xff) else: t = buf[0] >> 1 return t - 0.25 + (buf[7] - buf[6]) / buf[7] else: t = buf[1] << 8 | buf[0] if t & 0x8000: # sign bit set t = -((t ^ 0xffff) + 1) return t / 16 micropython-1.12/drivers/onewire/onewire.py000066400000000000000000000046001357706137100211720ustar00rootroot00000000000000# 1-Wire driver for MicroPython # MIT license; Copyright (c) 2016 Damien P. George from micropython import const import _onewire as _ow class OneWireError(Exception): pass class OneWire: SEARCH_ROM = const(0xf0) MATCH_ROM = const(0x55) SKIP_ROM = const(0xcc) def __init__(self, pin): self.pin = pin self.pin.init(pin.OPEN_DRAIN, pin.PULL_UP) def reset(self, required=False): reset = _ow.reset(self.pin) if required and not reset: raise OneWireError return reset def readbit(self): return _ow.readbit(self.pin) def readbyte(self): return _ow.readbyte(self.pin) def readinto(self, buf): for i in range(len(buf)): buf[i] = _ow.readbyte(self.pin) def writebit(self, value): return _ow.writebit(self.pin, value) def writebyte(self, value): return _ow.writebyte(self.pin, value) def write(self, buf): for b in buf: _ow.writebyte(self.pin, b) def select_rom(self, rom): self.reset() self.writebyte(MATCH_ROM) self.write(rom) def scan(self): devices = [] diff = 65 rom = False for i in range(0xff): rom, diff = self._search_rom(rom, diff) if rom: devices += [rom] if diff == 0: break return devices def _search_rom(self, l_rom, diff): if not self.reset(): return None, 0 self.writebyte(SEARCH_ROM) if not l_rom: l_rom = bytearray(8) rom = bytearray(8) next_diff = 0 i = 64 for byte in range(8): r_b = 0 for bit in range(8): b = self.readbit() if self.readbit(): if b: # there are no devices or there is an error on the bus return None, 0 else: if not b: # collision, two devices with different bit meaning if diff > i or ((l_rom[byte] & (1 << bit)) and diff != i): b = 1 next_diff = i self.writebit(b) if b: r_b |= 1 << bit i -= 1 rom[byte] = r_b return rom, next_diff def crc8(self, data): return _ow.crc8(data) micropython-1.12/drivers/sdcard/000077500000000000000000000000001357706137100167405ustar00rootroot00000000000000micropython-1.12/drivers/sdcard/sdcard.py000066400000000000000000000206511357706137100205560ustar00rootroot00000000000000""" MicroPython driver for SD cards using SPI bus. Requires an SPI bus and a CS pin. Provides readblocks and writeblocks methods so the device can be mounted as a filesystem. Example usage on pyboard: import pyb, sdcard, os sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5) pyb.mount(sd, '/sd2') os.listdir('/') Example usage on ESP8266: import machine, sdcard, os sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15)) os.mount(sd, '/sd') os.listdir('/') """ from micropython import const import time _CMD_TIMEOUT = const(100) _R1_IDLE_STATE = const(1 << 0) #R1_ERASE_RESET = const(1 << 1) _R1_ILLEGAL_COMMAND = const(1 << 2) #R1_COM_CRC_ERROR = const(1 << 3) #R1_ERASE_SEQUENCE_ERROR = const(1 << 4) #R1_ADDRESS_ERROR = const(1 << 5) #R1_PARAMETER_ERROR = const(1 << 6) _TOKEN_CMD25 = const(0xfc) _TOKEN_STOP_TRAN = const(0xfd) _TOKEN_DATA = const(0xfe) class SDCard: def __init__(self, spi, cs): self.spi = spi self.cs = cs self.cmdbuf = bytearray(6) self.dummybuf = bytearray(512) self.tokenbuf = bytearray(1) for i in range(512): self.dummybuf[i] = 0xff self.dummybuf_memoryview = memoryview(self.dummybuf) # initialise the card self.init_card() def init_spi(self, baudrate): try: master = self.spi.MASTER except AttributeError: # on ESP8266 self.spi.init(baudrate=baudrate, phase=0, polarity=0) else: # on pyboard self.spi.init(master, baudrate=baudrate, phase=0, polarity=0) def init_card(self): # init CS pin self.cs.init(self.cs.OUT, value=1) # init SPI bus; use low data rate for initialisation self.init_spi(100000) # clock card at least 100 cycles with cs high for i in range(16): self.spi.write(b'\xff') # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) for _ in range(5): if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: break else: raise OSError("no SD card") # CMD8: determine card version r = self.cmd(8, 0x01aa, 0x87, 4) if r == _R1_IDLE_STATE: self.init_card_v2() elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): self.init_card_v1() else: raise OSError("couldn't determine SD card version") # get the number of sectors # CMD9: response R2 (R1 byte + 16-byte block read) if self.cmd(9, 0, 0, 0, False) != 0: raise OSError("no response from SD card") csd = bytearray(16) self.readinto(csd) if csd[0] & 0xc0 == 0x40: # CSD version 2.0 self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024 elif csd[0] & 0xc0 == 0x00: # CSD version 1.0 (old, <=2GB) c_size = csd[6] & 0b11 | csd[7] << 2 | (csd[8] & 0b11000000) << 4 c_size_mult = ((csd[9] & 0b11) << 1) | csd[10] >> 7 self.sectors = (c_size + 1) * (2 ** (c_size_mult + 2)) else: raise OSError("SD card CSD format not supported") #print('sectors', self.sectors) # CMD16: set block length to 512 bytes if self.cmd(16, 512, 0) != 0: raise OSError("can't set 512 block size") # set to high data rate now that it's initialised self.init_spi(1320000) def init_card_v1(self): for i in range(_CMD_TIMEOUT): self.cmd(55, 0, 0) if self.cmd(41, 0, 0) == 0: self.cdv = 512 #print("[SDCard] v1 card") return raise OSError("timeout waiting for v1 card") def init_card_v2(self): for i in range(_CMD_TIMEOUT): time.sleep_ms(50) self.cmd(58, 0, 0, 4) self.cmd(55, 0, 0) if self.cmd(41, 0x40000000, 0) == 0: self.cmd(58, 0, 0, 4) self.cdv = 1 #print("[SDCard] v2 card") return raise OSError("timeout waiting for v2 card") def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False): self.cs(0) # create and send the command buf = self.cmdbuf buf[0] = 0x40 | cmd buf[1] = arg >> 24 buf[2] = arg >> 16 buf[3] = arg >> 8 buf[4] = arg buf[5] = crc self.spi.write(buf) if skip1: self.spi.readinto(self.tokenbuf, 0xff) # wait for the response (response[7] == 0) for i in range(_CMD_TIMEOUT): self.spi.readinto(self.tokenbuf, 0xff) response = self.tokenbuf[0] if not (response & 0x80): # this could be a big-endian integer that we are getting here for j in range(final): self.spi.write(b'\xff') if release: self.cs(1) self.spi.write(b'\xff') return response # timeout self.cs(1) self.spi.write(b'\xff') return -1 def readinto(self, buf): self.cs(0) # read until start byte (0xff) for i in range(_CMD_TIMEOUT): self.spi.readinto(self.tokenbuf, 0xff) if self.tokenbuf[0] == _TOKEN_DATA: break else: self.cs(1) raise OSError("timeout waiting for response") # read data mv = self.dummybuf_memoryview if len(buf) != len(mv): mv = mv[:len(buf)] self.spi.write_readinto(mv, buf) # read checksum self.spi.write(b'\xff') self.spi.write(b'\xff') self.cs(1) self.spi.write(b'\xff') def write(self, token, buf): self.cs(0) # send: start of block, data, checksum self.spi.read(1, token) self.spi.write(buf) self.spi.write(b'\xff') self.spi.write(b'\xff') # check the response if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05: self.cs(1) self.spi.write(b'\xff') return # wait for write to finish while self.spi.read(1, 0xff)[0] == 0: pass self.cs(1) self.spi.write(b'\xff') def write_token(self, token): self.cs(0) self.spi.read(1, token) self.spi.write(b'\xff') # wait for write to finish while self.spi.read(1, 0xff)[0] == 0x00: pass self.cs(1) self.spi.write(b'\xff') def readblocks(self, block_num, buf): nblocks = len(buf) // 512 assert nblocks and not len(buf) % 512, 'Buffer length is invalid' if nblocks == 1: # CMD17: set read address for single block if self.cmd(17, block_num * self.cdv, 0, release=False) != 0: # release the card self.cs(1) raise OSError(5) # EIO # receive the data and release card self.readinto(buf) else: # CMD18: set read address for multiple blocks if self.cmd(18, block_num * self.cdv, 0, release=False) != 0: # release the card self.cs(1) raise OSError(5) # EIO offset = 0 mv = memoryview(buf) while nblocks: # receive the data and release card self.readinto(mv[offset : offset + 512]) offset += 512 nblocks -= 1 if self.cmd(12, 0, 0xff, skip1=True): raise OSError(5) # EIO def writeblocks(self, block_num, buf): nblocks, err = divmod(len(buf), 512) assert nblocks and not err, 'Buffer length is invalid' if nblocks == 1: # CMD24: set write address for single block if self.cmd(24, block_num * self.cdv, 0) != 0: raise OSError(5) # EIO # send the data self.write(_TOKEN_DATA, buf) else: # CMD25: set write address for first block if self.cmd(25, block_num * self.cdv, 0) != 0: raise OSError(5) # EIO # send the data offset = 0 mv = memoryview(buf) while nblocks: self.write(_TOKEN_CMD25, mv[offset : offset + 512]) offset += 512 nblocks -= 1 self.write_token(_TOKEN_STOP_TRAN) def ioctl(self, op, arg): if op == 4: # get number of blocks return self.sectors micropython-1.12/drivers/sdcard/sdtest.py000066400000000000000000000030131357706137100206150ustar00rootroot00000000000000# Test for sdcard block protocol # Peter hinch 30th Jan 2016 import os, sdcard, machine def sdtest(): spi = machine.SPI(1) spi.init() # Ensure right baudrate sd = sdcard.SDCard(spi, machine.Pin.board.X21) # Compatible with PCB vfs = os.VfsFat(sd) os.mount(vfs, '/fc') print('Filesystem check') print(os.listdir('/fc')) line = 'abcdefghijklmnopqrstuvwxyz\n' lines = line * 200 # 5400 chars short = '1234567890\n' fn = '/fc/rats.txt' print() print('Multiple block read/write') with open(fn,'w') as f: n = f.write(lines) print(n, 'bytes written') n = f.write(short) print(n, 'bytes written') n = f.write(lines) print(n, 'bytes written') with open(fn,'r') as f: result1 = f.read() print(len(result1), 'bytes read') fn = '/fc/rats1.txt' print() print('Single block read/write') with open(fn,'w') as f: n = f.write(short) # one block print(n, 'bytes written') with open(fn,'r') as f: result2 = f.read() print(len(result2), 'bytes read') os.umount('/fc') print() print('Verifying data read back') success = True if result1 == ''.join((lines, short, lines)): print('Large file Pass') else: print('Large file Fail') success = False if result2 == short: print('Small file Pass') else: print('Small file Fail') success = False print() print('Tests', 'passed' if success else 'failed') micropython-1.12/drivers/wiznet5k/000077500000000000000000000000001357706137100172605ustar00rootroot00000000000000micropython-1.12/drivers/wiznet5k/README.md000066400000000000000000000003051357706137100205350ustar00rootroot00000000000000This is the driver for the WIZnet5x00 series of Ethernet controllers. Adapted for MicroPython. Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary Taken on: 30 August 2014 micropython-1.12/drivers/wiznet5k/ethernet/000077500000000000000000000000001357706137100210765ustar00rootroot00000000000000micropython-1.12/drivers/wiznet5k/ethernet/socket.c000066400000000000000000000515711357706137100225430ustar00rootroot00000000000000//***************************************************************************** // //! \file socket.c //! \brief SOCKET APIs Implements file. //! \details SOCKET APIs like as Berkeley Socket APIs. //! \version 1.0.3 //! \date 2013/10/21 //! \par Revision history //! <2014/05/01> V1.0.3. Refer to M20140501 //! 1. Implicit type casting -> Explicit type casting. //! 2. replace 0x01 with PACK_REMAINED in recvfrom() //! 3. Validation a destination ip in connect() & sendto(): //! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address. //! Copy 4 byte addr value into temporary uint32 variable and then compares it. //! <2013/12/20> V1.0.2 Refer to M20131220 //! Remove Warning. //! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104". //! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT) //! <2013/10/21> 1st Release //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #include #include "py/mpthread.h" #include "socket.h" #define SOCK_ANY_PORT_NUM 0xC000; static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; static uint16_t sock_io_mode = 0; static uint16_t sock_is_sending = 0; static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; #if _WIZCHIP_ == 5200 static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,}; #endif #define CHECK_SOCKNUM() \ do{ \ if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ }while(0); \ #define CHECK_SOCKMODE(mode) \ do{ \ if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ }while(0); \ #define CHECK_SOCKINIT() \ do{ \ if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ }while(0); \ #define CHECK_SOCKDATA() \ do{ \ if(len == 0) return SOCKERR_DATALEN; \ }while(0); \ void WIZCHIP_EXPORT(socket_reset)(void) { sock_any_port = SOCK_ANY_PORT_NUM; sock_io_mode = 0; sock_is_sending = 0; /* memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t)); */ #if _WIZCHIP_ == 5200 memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); #endif } int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) { CHECK_SOCKNUM(); switch(protocol) { case Sn_MR_TCP : case Sn_MR_UDP : case Sn_MR_MACRAW : break; #if ( _WIZCHIP_ < 5200 ) case Sn_MR_IPRAW : case Sn_MR_PPPoE : break; #endif default : return SOCKERR_SOCKMODE; } if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; #if _WIZCHIP_ == 5200 if(flag & 0x10) return SOCKERR_SOCKFLAG; #endif if(flag != 0) { switch(protocol) { case Sn_MR_TCP: if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; break; case Sn_MR_UDP: if(flag & SF_IGMP_VER2) { if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; } #if _WIZCHIP_ == 5500 if(flag & SF_UNI_BLOCK) { if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; } #endif break; default: break; } } WIZCHIP_EXPORT(close)(sn); setSn_MR(sn, (protocol | (flag & 0xF0))); if(!port) { port = sock_any_port++; if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; } setSn_PORT(sn,port); setSn_CR(sn,Sn_CR_OPEN); while(getSn_CR(sn)); sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); sock_is_sending &= ~(1< freesize) len = freesize; // check size not to exceed MAX size. while(1) { freesize = getSn_TX_FSR(sn); tmp = getSn_SR(sn); if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) { WIZCHIP_EXPORT(close)(sn); return SOCKERR_SOCKSTATUS; } if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; if(len <= freesize) break; MICROPY_THREAD_YIELD(); } wiz_send_data(sn, buf, len); #if _WIZCHIP_ == 5200 sock_next_rd[sn] = getSn_TX_RD(sn) + len; #endif setSn_CR(sn,Sn_CR_SEND); /* wait to process the command... */ while(getSn_CR(sn)); sock_is_sending |= (1 << sn); return len; } int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len) { uint8_t tmp = 0; uint16_t recvsize = 0; CHECK_SOCKNUM(); CHECK_SOCKMODE(Sn_MR_TCP); CHECK_SOCKDATA(); recvsize = getSn_RxMAX(sn); if(recvsize < len) len = recvsize; while(1) { recvsize = getSn_RX_RSR(sn); tmp = getSn_SR(sn); if (tmp != SOCK_ESTABLISHED) { if(tmp == SOCK_CLOSE_WAIT) { if(recvsize != 0) break; else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) { // dpgeorge: Getting here seems to be an orderly shutdown of the // socket, and trying to get POSIX behaviour we return 0 because: // "If no messages are available to be received and the peer has per‐ // formed an orderly shutdown, recv() shall return 0". // TODO this return value clashes with SOCK_BUSY in non-blocking mode. WIZCHIP_EXPORT(close)(sn); return 0; } } else { WIZCHIP_EXPORT(close)(sn); return SOCKERR_SOCKSTATUS; } } if((sock_io_mode & (1< freesize) len = freesize; // check size not to exceed MAX size. while(1) { freesize = getSn_TX_FSR(sn); if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; if(len <= freesize) break; MICROPY_THREAD_YIELD(); }; wiz_send_data(sn, buf, len); #if _WIZCHIP_ == 5200 // for W5200 ARP errata setSUBR(wizchip_getsubn()); #endif setSn_CR(sn,Sn_CR_SEND); /* wait to process the command... */ while(getSn_CR(sn)); while(1) { tmp = getSn_IR(sn); if(tmp & Sn_IR_SENDOK) { setSn_IR(sn, Sn_IR_SENDOK); break; } //M:20131104 //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT; else if(tmp & Sn_IR_TIMEOUT) { setSn_IR(sn, Sn_IR_TIMEOUT); #if _WIZCHIP_ == 5200 // for W5200 ARP errata setSUBR((uint8_t*)"\x00\x00\x00\x00"); #endif return SOCKERR_TIMEOUT; } //////////// MICROPY_THREAD_YIELD(); } #if _WIZCHIP_ == 5200 // for W5200 ARP errata setSUBR((uint8_t*)"\x00\x00\x00\x00"); #endif return len; } int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) { uint8_t mr; uint8_t head[8]; uint16_t pack_len=0; CHECK_SOCKNUM(); //CHECK_SOCKMODE(Sn_MR_UDP); switch((mr=getSn_MR(sn)) & 0x0F) { case Sn_MR_UDP: case Sn_MR_MACRAW: break; #if ( _WIZCHIP_ < 5200 ) case Sn_MR_IPRAW: case Sn_MR_PPPoE: break; #endif default: return SOCKERR_SOCKMODE; } CHECK_SOCKDATA(); if(sock_remained_size[sn] == 0) { while(1) { pack_len = getSn_RX_RSR(sn); if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; if( (sock_io_mode & (1< 1514) { WIZCHIP_EXPORT(close)(sn); return SOCKFATAL_PACKLEN; } sock_pack_info[sn] = PACK_FIRST; } if(len < sock_remained_size[sn]) pack_len = len; else pack_len = sock_remained_size[sn]; wiz_recv_data(sn,buf,pack_len); break; #if ( _WIZCHIP_ < 5200 ) case Sn_MR_IPRAW: if(sock_remained_size[sn] == 0) { wiz_recv_data(sn, head, 6); setSn_CR(sn,Sn_CR_RECV); while(getSn_CR(sn)); addr[0] = head[0]; addr[1] = head[1]; addr[2] = head[2]; addr[3] = head[3]; sock_remained_size[sn] = head[4]; sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5]; sock_pack_info[sn] = PACK_FIRST; } // // Need to packet length check // if(len < sock_remained_size[sn]) pack_len = len; else pack_len = sock_remained_size[sn]; wiz_recv_data(sn, buf, pack_len); // data copy. break; #endif default: wiz_recv_ignore(sn, pack_len); // data copy. sock_remained_size[sn] = pack_len; break; } setSn_CR(sn,Sn_CR_RECV); /* wait to process the command... */ while(getSn_CR(sn)) ; sock_remained_size[sn] -= pack_len; //M20140501 : replace 0x01 with PACK_REMAINED //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01; if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED; // return pack_len; } int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg) { uint8_t tmp = 0; CHECK_SOCKNUM(); switch(cstype) { case CS_SET_IOMODE: tmp = *((uint8_t*)arg); if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1< explict type casting //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001; *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001); // break; case CS_GET_MAXTXBUF: *((uint16_t*)arg) = getSn_TxMAX(sn); break; case CS_GET_MAXRXBUF: *((uint16_t*)arg) = getSn_RxMAX(sn); break; case CS_CLR_INTERRUPT: if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; setSn_IR(sn,*(uint8_t*)arg); break; case CS_GET_INTERRUPT: *((uint8_t*)arg) = getSn_IR(sn); break; case CS_SET_INTMASK: if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; setSn_IMR(sn,*(uint8_t*)arg); break; case CS_GET_INTMASK: *((uint8_t*)arg) = getSn_IMR(sn); default: return SOCKERR_ARG; } return SOCK_OK; } int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg) { // M20131220 : Remove warning //uint8_t tmp; CHECK_SOCKNUM(); switch(sotype) { case SO_TTL: setSn_TTL(sn,*(uint8_t*)arg); break; case SO_TOS: setSn_TOS(sn,*(uint8_t*)arg); break; case SO_MSS: setSn_MSSR(sn,*(uint16_t*)arg); break; case SO_DESTIP: setSn_DIPR(sn, (uint8_t*)arg); break; case SO_DESTPORT: setSn_DPORT(sn, *(uint16_t*)arg); break; #if _WIZCHIP_ != 5100 case SO_KEEPALIVESEND: CHECK_SOCKMODE(Sn_MR_TCP); #if _WIZCHIP_ > 5200 if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; #endif setSn_CR(sn,Sn_CR_SEND_KEEP); while(getSn_CR(sn) != 0) { // M20131220 //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT) if (getSn_IR(sn) & Sn_IR_TIMEOUT) { setSn_IR(sn, Sn_IR_TIMEOUT); return SOCKERR_TIMEOUT; } } break; #if _WIZCHIP_ > 5200 case SO_KEEPALIVEAUTO: CHECK_SOCKMODE(Sn_MR_TCP); setSn_KPALVTR(sn,*(uint8_t*)arg); break; #endif #endif default: return SOCKERR_ARG; } return SOCK_OK; } int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg) { CHECK_SOCKNUM(); switch(sotype) { case SO_FLAG: *(uint8_t*)arg = getSn_MR(sn) & 0xF0; break; case SO_TTL: *(uint8_t*) arg = getSn_TTL(sn); break; case SO_TOS: *(uint8_t*) arg = getSn_TOS(sn); break; case SO_MSS: *(uint8_t*) arg = getSn_MSSR(sn); case SO_DESTIP: getSn_DIPR(sn, (uint8_t*)arg); break; case SO_DESTPORT: *(uint16_t*) arg = getSn_DPORT(sn); break; #if _WIZCHIP_ > 5200 case SO_KEEPALIVEAUTO: CHECK_SOCKMODE(Sn_MR_TCP); *(uint16_t*) arg = getSn_KPALVTR(sn); break; #endif case SO_SENDBUF: *(uint16_t*) arg = getSn_TX_FSR(sn); case SO_RECVBUF: *(uint16_t*) arg = getSn_RX_RSR(sn); case SO_STATUS: *(uint8_t*) arg = getSn_SR(sn); break; case SO_REMAINSIZE: if(getSn_MR(sn) == Sn_MR_TCP) *(uint16_t*)arg = getSn_RX_RSR(sn); else *(uint16_t*)arg = sock_remained_size[sn]; break; case SO_PACKINFO: CHECK_SOCKMODE(Sn_MR_TCP); *(uint8_t*)arg = sock_pack_info[sn]; break; default: return SOCKERR_SOCKOPT; } return SOCK_OK; } micropython-1.12/drivers/wiznet5k/ethernet/socket.h000066400000000000000000000652751357706137100225560ustar00rootroot00000000000000//***************************************************************************** // //! \file socket.h //! \brief SOCKET APIs Header file. //! \details SOCKET APIs like as berkeley socket api. //! \version 1.0.2 //! \date 2013/10/21 //! \par Revision history //! <2014/05/01> V1.0.2. Refer to M20140501 //! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED //! 2. Add the comment as zero byte udp data reception in getsockopt(). //! <2013/10/21> 1st Release //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** /** * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface. * But there is a little bit of difference. * @details * Comparison between WIZnet and Berkeley SOCKET APIs * * * * * * * * * * * * *
API WIZnet Berkeley
socket() O O
bind() X O
listen() O O
connect() O O
accept() X O
recv() O O
send() O O
recvfrom() O O
sendto() O O
closesocket() O
close() & disconnect()
O
* There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but, * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number, * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port. * When the listen SOCKET accepts a connection request from a client, it keeps listening. * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n * Following figure shows network flow diagram by Berkeley SOCKET API. * @image html Berkeley_SOCKET.jpg "" * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client, * it is changed in order to communicate with the client. * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n * If there're many listen SOCKET with same listen port number and a client requests a connection, * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n * Following figure shows network flow diagram by WIZnet SOCKET API. * @image html WIZnet_SOCKET.jpg "" */ #ifndef _WIZCHIP_SOCKET_H_ #define _WIZCHIP_SOCKET_H_ // use this macro for exported names to avoid name clashes #define WIZCHIP_EXPORT(name) wizchip_ ## name #include "wizchip_conf.h" #define SOCKET uint8_t ///< SOCKET type define for legacy driver #define SOCK_OK 1 ///< Result is OK about socket process. #define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. #define SOCK_FATAL -1000 ///< Result is fatal error about socket process. #define SOCK_ERROR 0 #define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number #define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option #define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized #define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. #define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. #define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag #define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. #define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument. #define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero #define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address #define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred #define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size. #define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. #define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. /* * SOCKET FLAG */ #define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet #define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2. #define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack. #define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode. #if _WIZCHIP_ == 5500 #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500 #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500 #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500 #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500 #endif #define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket(). /* * UDP & MACRAW Packet Infomation */ #define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. #define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. #define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. // resets all global state associated with the socket interface void WIZCHIP_EXPORT(socket_reset)(void); /** * @ingroup WIZnet_socket_APIs * @brief Open a socket. * @details Initializes the socket with 'sn' passed as parameter and open. * * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * @param protocol Protocol type to operate such as TCP, UDP and MACRAW. * @param port Port number to be bined. * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK. * @sa Sn_MR * * @return @b Success : The socket number @b 'sn' passed as parameter\n * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n * @ref SOCKERR_SOCKFLAG - Invaild socket flag. */ int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); /** * @ingroup WIZnet_socket_APIs * @brief Close a socket. * @details It closes the socket with @b'sn' passed as parameter. * * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * * @return @b Success : @ref SOCK_OK \n * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number */ int8_t WIZCHIP_EXPORT(close)(uint8_t sn); /** * @ingroup WIZnet_socket_APIs * @brief Listen to a connection request from a client. * @details It is listening to a connection request from a client. * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode. * * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * @return @b Success : @ref SOCK_OK \n * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. */ int8_t WIZCHIP_EXPORT(listen)(uint8_t sn); /** * @ingroup WIZnet_socket_APIs * @brief Try to connect a server. * @details It requests connection to the server with destination IP address and port number passed as parameter.\n * @note It is valid only in TCP client mode. * In block io mode, it does not return until connection is completed. * In Non-block io mode, it return @ref SOCK_BUSY immediately. * * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. * @param port Destination port number. * * @return @b Success : @ref SOCK_OK \n * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n * @ref SOCKERR_SOCKMODE - Invalid socket mode\n * @ref SOCKERR_SOCKINIT - Socket is not initialized\n * @ref SOCKERR_IPINVALID - Wrong server IP address\n * @ref SOCKERR_PORTZERO - Server port zero\n * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n */ int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port); /** * @ingroup WIZnet_socket_APIs * @brief Try to disconnect a connection socket. * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client. * @note It is valid only in TCP server or client mode. \n * In block io mode, it does not return until disconnection is completed. \n * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * @return @b Success : @ref SOCK_OK \n * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n * @ref SOCKERR_TIMEOUT - Timeout occurred \n * @ref SOCK_BUSY - Socket is busy. */ int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn); /** * @ingroup WIZnet_socket_APIs * @brief Send data to the connected peer in TCP socket. * @details It is used to send outgoing data to the connected socket. * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * @param buf Pointer buffer containing data to be sent. * @param len The byte length of data in buf. * @return @b Success : The sent data size \n * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n * @ref SOCKERR_TIMEOUT - Timeout occurred \n * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n * @ref SOCKERR_SOCKNUM - Invalid socket number \n * @ref SOCKERR_DATALEN - zero data length \n * @ref SOCK_BUSY - Socket is busy. */ int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len); /** * @ingroup WIZnet_socket_APIs * @brief Receive data from the connected peer. * @details It is used to read incoming data from the connected socket.\n * It waits for data as much as the application wants to receive. * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n * In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer. \n * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. \n * * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * @param buf Pointer buffer to read incoming data. * @param len The max data length of data in buf. * @return @b Success : The real received data size \n * @b Fail :\n * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n * @ref SOCKERR_SOCKNUM - Invalid socket number \n * @ref SOCKERR_DATALEN - zero data length \n * @ref SOCK_BUSY - Socket is busy. */ int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len); /** * @ingroup WIZnet_socket_APIs * @brief Sends datagram to the peer with destination IP address and port number passed as parameter. * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n * Even if the connectionless socket has been previously connected to a specific address, * the address and port number parameters override the destination address for that particular datagram only. * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than len. * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. * * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * @param buf Pointer buffer to send outgoing data. * @param len The byte length of data in buf. * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. * @param port Destination port number. * * @return @b Success : The sent data size \n * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n * @ref SOCKERR_DATALEN - zero data length \n * @ref SOCKERR_IPINVALID - Wrong server IP address\n * @ref SOCKERR_PORTZERO - Server port zero\n * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n * @ref SOCKERR_TIMEOUT - Timeout occurred \n * @ref SOCK_BUSY - Socket is busy. */ int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); /** * @ingroup WIZnet_socket_APIs * @brief Receive datagram of UDP or MACRAW * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n * This function is used to receive UDP and MAC_RAW mode, and handle the header as well. * This function can divide to received the packet data. * On the MACRAW SOCKET, the addr and port parameters are ignored. * @note In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. * * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. * @param buf Pointer buffer to read incoming data. * @param len The max data length of data in buf. * When the received packet size <= len, receives data as packet sized. * When others, receives data as len. * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. * It is valid only when the first call recvfrom for receiving the packet. * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). * @param port Pointer variable of destination port number. * It is valid only when the first call recvform for receiving the packet. * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). * * @return @b Success : This function return real received data size for success.\n * @b Fail : @ref SOCKERR_DATALEN - zero data length \n * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n * @ref SOCKERR_SOCKNUM - Invalid socket number \n * @ref SOCKBUSY - Socket is busy. */ int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); ///////////////////////////// // SOCKET CONTROL & OPTION // ///////////////////////////// #define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt(). #define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt(). /** * @defgroup DATA_TYPE DATA TYPE */ /** * @ingroup DATA_TYPE * @brief The kind of Socket Interrupt. * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR() */ typedef enum { SIK_CONNECTED = (1 << 0), ///< connected SIK_DISCONNECTED = (1 << 1), ///< disconnected SIK_RECEIVED = (1 << 2), ///< data received SIK_TIMEOUT = (1 << 3), ///< timeout occurred SIK_SENT = (1 << 4), ///< send ok SIK_ALL = 0x1F, ///< all interrupt }sockint_kind; /** * @ingroup DATA_TYPE * @brief The type of @ref ctlsocket(). */ typedef enum { CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK CS_GET_IOMODE, ///< get socket IO mode CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind }ctlsock_type; /** * @ingroup DATA_TYPE * @brief The type of socket option in @ref setsockopt() or @ref getsockopt() */ typedef enum { SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to flag in @ref socket(). SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() ) SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() ) SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() ) SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() ) SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() ) #if _WIZCHIP_ != 5100 SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode #if _WIZCHIP_ > 5200 SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode #endif #endif SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR() SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR() SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR() SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode. SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode. }sockopt_type; /** * @ingroup WIZnet_socket_APIs * @brief Control socket. * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information. * Refer to @ref ctlsock_type. * @param sn socket number * @param cstype type of control socket. refer to @ref ctlsock_type. * @param arg Data type and value is determined according to @ref ctlsock_type. \n * * * * * *
@b cstype @b data type@b value
@ref CS_SET_IOMODE \n @ref CS_GET_IOMODE uint8_t @ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK
@ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF uint16_t 0 ~ 16K
@ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK @ref sockint_kind @ref SIK_CONNECTED, etc.
* @return @b Success @ref SOCK_OK \n * @b fail @ref SOCKERR_ARG - Invalid argument\n */ int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg); /** * @ingroup WIZnet_socket_APIs * @brief set socket options * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. * * @param sn socket number * @param sotype socket option type. refer to @ref sockopt_type * @param arg Data type and value is determined according to sotype. \n * * * * * * * * * *
@b sotype @b data type@b value
@ref SO_TTL uint8_t 0 ~ 255
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t 0 ~ 65535
@ref SO_KEEPALIVESEND null null
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
* @return * - @b Success : @ref SOCK_OK \n * - @b Fail * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n */ int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg); /** * @ingroup WIZnet_socket_APIs * @brief get socket options * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type * @param sn socket number * @param sotype socket option type. refer to @ref sockopt_type * @param arg Data type and value is determined according to sotype. \n * * * * * * * * * * * * * *
@b sotype @b data type@b value
@ref SO_FLAG uint8_t @ref SF_ETHER_OWN, etc...
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
@ref SO_SENDBUF uint16_t 0 ~ 65535
@ref SO_RECVBUF uint16_t 0 ~ 65535
@ref SO_STATUS uint8_t @ref SOCK_ESTABLISHED, etc..
@ref SO_REMAINSIZE uint16_t 0~ 65535
@ref SO_PACKINFO uint8_t @ref PACK_FIRST, etc...
* @return * - @b Success : @ref SOCK_OK \n * - @b Fail * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n * @note * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, * This means the zero byte UDP data(UDP Header only) received. */ int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg); #endif // _WIZCHIP_SOCKET_H_ micropython-1.12/drivers/wiznet5k/ethernet/w5200/000077500000000000000000000000001357706137100216535ustar00rootroot00000000000000micropython-1.12/drivers/wiznet5k/ethernet/w5200/w5200.c000066400000000000000000000152501357706137100225770ustar00rootroot00000000000000// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200 //***************************************************************************** // //! \file w5500.c //! \brief W5500 HAL Interface. //! \version 1.0.1 //! \date 2013/10/21 //! \par Revision history //! <2014/05/01> V1.0.2 //! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 //! Fixed the problem on porting into under 32bit MCU //! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh //! Thank for your interesting and serious advices. //! <2013/10/21> 1st Release //! <2013/12/20> V1.0.1 //! 1. Remove warning //! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ //! for loop optimized(removed). refer to M20131220 //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #include "w5200.h" #if WIZCHIP_USE_MAX_BUFFER // This option is intended to be used when MACRAW mode is enabled, to allow // the single raw socket to use all the available buffer space. #define SMASK (16 * 1024 - 1) /* tx buffer mask */ #define RMASK (16 * 1024 - 1) /* rx buffer mask */ #define SSIZE (16 * 1024) /* max tx buffer size */ #define RSIZE (16 * 1024) /* max rx buffer size */ #else #define SMASK (0x7ff) /* tx buffer mask */ #define RMASK (0x7ff) /* rx buffer mask */ #define SSIZE (2048) /* max tx buffer size */ #define RSIZE (2048) /* max rx buffer size */ #endif #define TXBUF_BASE (0x8000) #define RXBUF_BASE (0xc000) #define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */ #define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */ uint8_t WIZCHIP_READ(uint32_t AddrSel) { WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); uint8_t spi_data[4] = { AddrSel >> 8, AddrSel, 0x00, 0x01, }; WIZCHIP.IF.SPI._write_bytes(spi_data, 4); uint8_t ret; WIZCHIP.IF.SPI._read_bytes(&ret, 1); WIZCHIP.CS._deselect(); WIZCHIP_CRITICAL_EXIT(); return ret; } void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) { WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); uint8_t spi_data[5] = { AddrSel >> 8, AddrSel, 0x80, 0x01, wb, }; WIZCHIP.IF.SPI._write_bytes(spi_data, 5); WIZCHIP.CS._deselect(); WIZCHIP_CRITICAL_EXIT(); } void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); uint8_t spi_data[4] = { AddrSel >> 8, AddrSel, 0x00 | ((len >> 8) & 0x7f), len & 0xff, }; WIZCHIP.IF.SPI._write_bytes(spi_data, 4); WIZCHIP.IF.SPI._read_bytes(pBuf, len); WIZCHIP.CS._deselect(); WIZCHIP_CRITICAL_EXIT(); } void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); uint8_t spi_data[4] = { AddrSel >> 8, AddrSel, 0x80 | ((len >> 8) & 0x7f), len & 0xff, }; WIZCHIP.IF.SPI._write_bytes(spi_data, 4); WIZCHIP.IF.SPI._write_bytes(pBuf, len); WIZCHIP.CS._deselect(); WIZCHIP_CRITICAL_EXIT(); } uint16_t getSn_TX_FSR(uint8_t sn) { uint16_t val = 0, val1 = 0; do { val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); if (val1 != 0) { val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); } } while (val != val1); return val; } uint16_t getSn_RX_RSR(uint8_t sn) { uint16_t val = 0, val1 = 0; do { val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); if (val1 != 0) { val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); } } while (val != val1); return val; } void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { if (len == 0) { return; } uint16_t ptr = getSn_TX_WR(sn); uint16_t offset = ptr & SMASK; uint32_t addr = offset + SBASE(sn); if (offset + len > SSIZE) { // implement wrap-around circular buffer uint16_t size = SSIZE - offset; WIZCHIP_WRITE_BUF(addr, wizdata, size); WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size); } else { WIZCHIP_WRITE_BUF(addr, wizdata, len); } ptr += len; setSn_TX_WR(sn, ptr); } void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { if (len == 0) { return; } uint16_t ptr = getSn_RX_RD(sn); uint16_t offset = ptr & RMASK; uint16_t addr = RBASE(sn) + offset; if (offset + len > RSIZE) { // implement wrap-around circular buffer uint16_t size = RSIZE - offset; WIZCHIP_READ_BUF(addr, wizdata, size); WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size); } else { WIZCHIP_READ_BUF(addr, wizdata, len); } ptr += len; setSn_RX_RD(sn, ptr); } void wiz_recv_ignore(uint8_t sn, uint16_t len) { uint16_t ptr = getSn_RX_RD(sn); ptr += len; setSn_RX_RD(sn, ptr); } micropython-1.12/drivers/wiznet5k/ethernet/w5200/w5200.h000066400000000000000000002266631357706137100226200ustar00rootroot00000000000000// dpgeorge: this file taken from w5500/w5500.h and adapted to W5200 //***************************************************************************** // //! \file w5500.h //! \brief W5500 HAL Header File. //! \version 1.0.0 //! \date 2013/10/21 //! \par Revision history //! <2013/10/21> 1st Release //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef _W5200_H_ #define _W5200_H_ #include #include "../wizchip_conf.h" //#include "board.h" #define _W5200_IO_BASE_ 0x00000000 #define WIZCHIP_CREG_ADDR(addr) (_W5200_IO_BASE_ + (addr)) #define WIZCHIP_CH_BASE (0x4000) #define WIZCHIP_CH_SIZE (0x100) #define WIZCHIP_SREG_ADDR(sn, addr) (_W5200_IO_BASE_ + WIZCHIP_CH_BASE + (sn) * WIZCHIP_CH_SIZE + (addr)) ////////////////////////////// //-------------------------- defgroup --------------------------------- /** * @defgroup W5500 W5500 * * @brief WHIZCHIP register defines and I/O functions of @b W5500. * * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function */ /** * @defgroup WIZCHIP_register WIZCHIP register * @ingroup W5500 * * @brief WHIZCHIP register defines register group of @b W5500. * * - @ref Common_register_group : Common register group * - @ref Socket_register_group : \c SOCKET n register group */ /** * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions * @ingroup W5500 * * @brief This supports the basic I/O functions for @ref WIZCHIP_register. * * - Basic I/O function \n * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n * * - @ref Common_register_group access functions \n * -# @b Mode \n * getMR(), setMR() * -# @b Interrupt \n * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() * -# Network Information \n * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() * -# @b Retransmission \n * getRCR(), setRCR(), getRTR(), setRTR() * -# @b PPPoE \n * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() * -# ICMP packet \n * getUIPR(), getUPORTR() * -# @b etc. \n * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n * * - \ref Socket_register_group access functions \n * -# SOCKET control \n * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() * -# SOCKET information \n * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() * getSn_MSSR(), setSn_MSSR() * -# SOCKET communication \n * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() * -# IP header field \n * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n * getSn_TTL(), setSn_TTL() */ /** * @defgroup Common_register_group Common register * @ingroup WIZCHIP_register * * @brief Common register group\n * It set the basic for the networking\n * It set the configuration such as interrupt, network information, ICMP, etc. * @details * @sa MR : Mode register. * @sa GAR, SUBR, SHAR, SIPR * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. * @sa RTR, RCR : Data retransmission. * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. * @sa UIPR, UPORTR : ICMP message. * @sa PHYCFGR, VERSIONR : etc. */ /** * @defgroup Socket_register_group Socket register * @ingroup WIZCHIP_register * * @brief Socket register group.\n * Socket register configures and control SOCKETn which is necessary to data communication. * @details * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication */ /** * @defgroup Basic_IO_function Basic I/O function * @ingroup WIZCHIP_IO_Functions * @brief These are basic input/output functions to read values from register or write values to register. */ /** * @defgroup Common_register_access_function Common register access functions * @ingroup WIZCHIP_IO_Functions * @brief These are functions to access common registers. */ /** * @defgroup Socket_register_access_function Socket register access functions * @ingroup WIZCHIP_IO_Functions * @brief These are functions to access socket registers. */ //------------------------------- defgroup end -------------------------------------------- //----------------------------- W5500 Common Registers IOMAP ----------------------------- /** * @ingroup Common_register_group * @brief Mode Register address(R/W)\n * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. * @details Each bit of @ref MR defined as follows. * * * *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
* - \ref MR_RST : Reset * - \ref MR_WOL : Wake on LAN * - \ref MR_PB : Ping block * - \ref MR_PPPOE : PPPoE mode * - \ref MR_FARP : Force ARP mode */ #define MR WIZCHIP_CREG_ADDR(0x0000) /** * @ingroup Common_register_group * @brief Gateway IP Register address(R/W) * @details @ref GAR configures the default gateway address. */ #define GAR WIZCHIP_CREG_ADDR(0x0001) /** * @ingroup Common_register_group * @brief Subnet mask Register address(R/W) * @details @ref SUBR configures the subnet mask address. */ #define SUBR WIZCHIP_CREG_ADDR(0x0005) /** * @ingroup Common_register_group * @brief Source MAC Register address(R/W) * @details @ref SHAR configures the source hardware address. */ #define SHAR WIZCHIP_CREG_ADDR(0x0009) /** * @ingroup Common_register_group * @brief Source IP Register address(R/W) * @details @ref SIPR configures the source IP address. */ #define SIPR WIZCHIP_CREG_ADDR(0x000f) /** * @ingroup Common_register_group * @brief Set Interrupt low level timer register address(R/W) * @details @ref INTLEVEL configures the Interrupt Assert Time. */ //#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Interrupt Register(R/W) * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n * Each bit of @ref IR defined as follows. * * * *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
* - \ref IR_CONFLICT : IP conflict * - \ref IR_UNREACH : Destination unreachable * - \ref IR_PPPoE : PPPoE connection close * - \ref IR_MP : Magic packet */ #define IR WIZCHIP_CREG_ADDR(0x0015) /** * @ingroup Common_register_group * @brief Interrupt mask register(R/W) * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n * Each bit of @ref IMR defined as the following. * * * *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
* - \ref IM_IR7 : IP Conflict Interrupt Mask * - \ref IM_IR6 : Destination unreachable Interrupt Mask * - \ref IM_IR5 : PPPoE Close Interrupt Mask * - \ref IM_IR4 : Magic Packet Interrupt Mask */ #define IMR WIZCHIP_CREG_ADDR(0x0016) /** * @ingroup Common_register_group * @brief Socket Interrupt Register(R/W) * @details @ref SIR indicates the interrupt status of Socket.\n * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ //#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Socket Interrupt Mask Register(R/W) * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is */ //#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Timeout register address( 1 is 100us )(R/W) * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. */ #define RTR WIZCHIP_CREG_ADDR(0x0017) /** * @ingroup Common_register_group * @brief Retry count register(R/W) * @details @ref RCR configures the number of time of retransmission. * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . */ #define RCR WIZCHIP_CREG_ADDR(0x0019) /** * @ingroup Common_register_group * @brief PPP LCP Request Timer register in PPPoE mode(R/W) * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. */ #define PTIMER WIZCHIP_CREG_ADDR(0x0028) /** * @ingroup Common_register_group * @brief PPP LCP Magic number register in PPPoE mode(R/W) * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. */ #define PMAGIC WIZCHIP_CREG_ADDR(0x0029) /** * @ingroup Common_register_group * @brief PPP Destination MAC Register address(R/W) * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. */ //#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PPP Session Identification Register(R/W) * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. */ //#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PPP Maximum Segment Size(MSS) register(R/W) * @details @ref PMRU configures the maximum receive unit of PPPoE. */ //#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Unreachable IP register address in UDP mode(R) * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates * the destination IP address & port number respectively. */ //#define UIPR (_W5500_IO_BASE_ + (0x002a << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Unreachable Port register address in UDP mode(R) * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR * indicates the destination IP address & port number respectively. */ //#define UPORTR (_W5500_IO_BASE_ + (0x002e << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PHY Status Register(R/W) * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. */ //#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) #define PHYSTATUS WIZCHIP_CREG_ADDR(0x0035) // Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief chip version register address(R) * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. */ //#define VERSIONR (_W5200_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) //----------------------------- W5500 Socket Registers IOMAP ----------------------------- /** * @ingroup Socket_register_group * @brief socket Mode register(R/W) * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n * Each bit of @ref Sn_MR defined as the following. * * * *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
* - @ref Sn_MR_MULTI : Support UDP Multicasting * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode * - Protocol * * * * * * *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
* - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n * - @ref Sn_MR_UDP : UDP * - @ref Sn_MR_TCP : TCP * - @ref Sn_MR_CLOSE : Unused socket * @note MACRAW mode should be only used in Socket 0. */ #define Sn_MR(N) WIZCHIP_SREG_ADDR(N, 0x0000) /** * @ingroup Socket_register_group * @brief Socket command register(R/W) * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. * - @ref Sn_CR_OPEN : Initialize or open socket. * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) * - @ref Sn_CR_DISCON : Send closing request in TCP mode. * - @ref Sn_CR_CLOSE : Close socket. * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. * - @ref Sn_CR_SEND_KEEP : Send keep alive message. * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. */ #define Sn_CR(N) WIZCHIP_SREG_ADDR(N, 0x0001) /** * @ingroup Socket_register_group * @brief Socket interrupt register(R) * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n * In order to clear the @ref Sn_IR bit, the host should write the bit to \n * * * *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
* - \ref Sn_IR_SENDOK : SEND_OK Interrupt * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt * - \ref Sn_IR_RECV : RECV Interrupt * - \ref Sn_IR_DISCON : DISCON Interrupt * - \ref Sn_IR_CON : CON Interrupt */ #define Sn_IR(N) WIZCHIP_SREG_ADDR(N, 0x0002) /** * @ingroup Socket_register_group * @brief Socket status register(R) * @details @ref Sn_SR indicates the status of Socket n.\n * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. * @par Normal status * - @ref SOCK_CLOSED : Closed * - @ref SOCK_INIT : Initiate state * - @ref SOCK_LISTEN : Listen state * - @ref SOCK_ESTABLISHED : Success to connect * - @ref SOCK_CLOSE_WAIT : Closing state * - @ref SOCK_UDP : UDP socket * - @ref SOCK_MACRAW : MAC raw mode socket *@par Temporary status during changing the status of Socket n. * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. * - @ref SOCK_FIN_WAIT : Connection state * - @ref SOCK_CLOSING : Closing state * - @ref SOCK_TIME_WAIT : Closing state * - @ref SOCK_LAST_ACK : Closing state */ #define Sn_SR(N) WIZCHIP_SREG_ADDR(N, 0x0003) /** * @ingroup Socket_register_group * @brief source port register(R/W) * @details @ref Sn_PORT configures the source port number of Socket n. * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. */ #define Sn_PORT(N) WIZCHIP_SREG_ADDR(N, 0x0004) /** * @ingroup Socket_register_group * @brief Peer MAC register address(R/W) * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or * it indicates that it is acquired in ARP-process by CONNECT/SEND command. */ #define Sn_DHAR(N) WIZCHIP_SREG_ADDR(N, 0x0006) /** * @ingroup Socket_register_group * @brief Peer IP register address(R/W) * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. */ #define Sn_DIPR(N) WIZCHIP_SREG_ADDR(N, 0x000c) /** * @ingroup Socket_register_group * @brief Peer port register address(R/W) * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. */ #define Sn_DPORT(N) WIZCHIP_SREG_ADDR(N, 0x0010) /** * @ingroup Socket_register_group * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. */ #define Sn_MSSR(N) WIZCHIP_SREG_ADDR(N, 0x0012) // Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief IP Type of Service(TOS) Register(R/W) * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. * It is set before OPEN command. */ #define Sn_TOS(N) WIZCHIP_SREG_ADDR(N, 0x0015) /** * @ingroup Socket_register_group * @brief IP Time to live(TTL) Register(R/W) * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. * It is set before OPEN command. */ #define Sn_TTL(N) WIZCHIP_SREG_ADDR(N, 0x0016) // Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Receive memory size register(R/W) * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. * If a different size is configured, the data cannot be normally received from a peer. * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. * When exceeded, the data reception error is occurred. */ #define Sn_RXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001e) /** * @ingroup Socket_register_group * @brief Transmit memory size register(R/W) * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. * If a different size is configured, the data can�t be normally transmitted to a peer. * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. * When exceeded, the data transmission error is occurred. */ #define Sn_TXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001f) /** * @ingroup Socket_register_group * @brief Transmit free memory size register(R) * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. */ #define Sn_TX_FSR(N) WIZCHIP_SREG_ADDR(N, 0x0020) /** * @ingroup Socket_register_group * @brief Transmit memory read pointer register address(R) * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. * After its initialization, it is auto-increased by SEND command. * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), * then the carry bit is ignored and will automatically update with the lower 16bits value. */ #define Sn_TX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0022) /** * @ingroup Socket_register_group * @brief Transmit memory write pointer register address(R/W) * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n * It should be read or be updated like as follows.\n * 1. Read the starting address for saving the transmitting data.\n * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), * then the carry bit is ignored and will automatically update with the lower 16bits value.\n * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command */ #define Sn_TX_WR(N) WIZCHIP_SREG_ADDR(N, 0x0024) /** * @ingroup Socket_register_group * @brief Received data size register(R) * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) */ #define Sn_RX_RSR(N) WIZCHIP_SREG_ADDR(N, 0x0026) /** * @ingroup Socket_register_group * @brief Read point of Receive memory(R/W) * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n * 1. Read the starting save address of the received data.\n * 2. Read data from the starting address of Socket n RX Buffer.\n * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, * update with the lower 16bits value ignored the carry bit.\n * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. */ #define Sn_RX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0028) /** * @ingroup Socket_register_group * @brief Write point of Receive memory(R) * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), * then the carry bit is ignored and will automatically update with the lower 16bits value. */ #define Sn_RX_WR(N) WIZCHIP_SREG_ADDR(N, 0x002a) /** * @ingroup Socket_register_group * @brief socket interrupt mask register(R) * @details @ref Sn_IMR masks the interrupt of Socket n. * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is * Host is interrupted by asserted INTn PIN to low. */ //#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Fragment field value in IP header register(R/W) * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). */ //#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Keep Alive Timer register(R/W) * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, * and ignored in other modes. The time unit is 5s. * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. */ //#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) //#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) //----------------------------- W5500 Register values ----------------------------- /* MODE register values */ /** * @brief Reset * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. */ #define MR_RST 0x80 /** * @brief Wake on LAN * @details 0 : Disable WOL mode\n * 1 : Enable WOL mode\n * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. */ #define MR_WOL 0x20 /** * @brief Ping block * @details 0 : Disable Ping block\n * 1 : Enable Ping block\n * If the bit is it blocks the response to a ping request. */ #define MR_PB 0x10 /** * @brief Enable PPPoE * @details 0 : DisablePPPoE mode\n * 1 : EnablePPPoE mode\n * If you use ADSL, this bit should be */ #define MR_PPPOE 0x08 /** * @brief Enable UDP_FORCE_ARP CHECHK * @details 0 : Disable Force ARP mode\n * 1 : Enable Force ARP mode\n * In Force ARP mode, It forces on sending ARP Request whenever data is sent. */ #define MR_FARP 0x02 /* IR register values */ /** * @brief Check IP conflict. * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. */ #define IR_CONFLICT 0x80 /** * @brief Get the destination unreachable message in UDP sending. * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. */ #define IR_UNREACH 0x40 /** * @brief Get the PPPoE close message. * @details When PPPoE is disconnected during PPPoE mode, this bit is set. */ #define IR_PPPoE 0x20 /** * @brief Get the magic packet interrupt. * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. */ #define IR_MP 0x10 /* PHYCFGR register value */ #define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. #define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value #define PHYCFGR_OPMDC_ALLA (7<<3) #define PHYCFGR_OPMDC_PDOWN (6<<3) #define PHYCFGR_OPMDC_NA (5<<3) #define PHYCFGR_OPMDC_100FA (4<<3) #define PHYCFGR_OPMDC_100F (3<<3) #define PHYCFGR_OPMDC_100H (2<<3) #define PHYCFGR_OPMDC_10F (1<<3) #define PHYCFGR_OPMDC_10H (0<<3) #define PHYCFGR_DPX_FULL (1<<2) #define PHYCFGR_DPX_HALF (0<<2) #define PHYCFGR_SPD_100 (1<<1) #define PHYCFGR_SPD_10 (0<<1) #define PHYCFGR_LNK_ON (1<<0) #define PHYCFGR_LNK_OFF (0<<0) // PHYSTATUS register #define PHYSTATUS_POWERDOWN (0x08) #define PHYSTATUS_LINK (0x20) /* IMR register values */ /** * @brief IP Conflict Interrupt Mask. * @details 0: Disable IP Conflict Interrupt\n * 1: Enable IP Conflict Interrupt */ #define IM_IR7 0x80 /** * @brief Destination unreachable Interrupt Mask. * @details 0: Disable Destination unreachable Interrupt\n * 1: Enable Destination unreachable Interrupt */ #define IM_IR6 0x40 /** * @brief PPPoE Close Interrupt Mask. * @details 0: Disable PPPoE Close Interrupt\n * 1: Enable PPPoE Close Interrupt */ #define IM_IR5 0x20 /** * @brief Magic Packet Interrupt Mask. * @details 0: Disable Magic Packet Interrupt\n * 1: Enable Magic Packet Interrupt */ #define IM_IR4 0x10 /* Sn_MR Default values */ /** * @brief Support UDP Multicasting * @details 0 : disable Multicasting\n * 1 : enable Multicasting\n * This bit is applied only during UDP mode(P[3:0] = 010.\n * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number * before Socket n is opened by OPEN command of @ref Sn_CR. */ #define Sn_MR_MULTI 0x80 /** * @brief Broadcast block in UDP Multicasting. * @details 0 : disable Broadcast Blocking\n * 1 : enable Broadcast Blocking\n * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m * In addition, This bit does when MACRAW mode(P[3:0] = 100 */ //#define Sn_MR_BCASTB 0x40 /** * @brief No Delayed Ack(TCP), Multicast flag * @details 0 : Disable No Delayed ACK option\n * 1 : Enable No Delayed ACK option\n * This bit is applied only during TCP mode (P[3:0] = 001.\n * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. */ #define Sn_MR_ND 0x20 /** * @brief Unicast Block in UDP Multicasting * @details 0 : disable Unicast Blocking\n * 1 : enable Unicast Blocking\n * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = */ //#define Sn_MR_UCASTB 0x10 /** * @brief MAC LAYER RAW SOCK * @details This configures the protocol mode of Socket n. * @note MACRAW mode should be only used in Socket 0. */ #define Sn_MR_MACRAW 0x04 #define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ /** * @brief UDP * @details This configures the protocol mode of Socket n. */ #define Sn_MR_UDP 0x02 /** * @brief TCP * @details This configures the protocol mode of Socket n. */ #define Sn_MR_TCP 0x01 /** * @brief Unused socket * @details This configures the protocol mode of Socket n. */ #define Sn_MR_CLOSE 0x00 /* Sn_MR values used with Sn_MR_MACRAW */ /** * @brief MAC filter enable in @ref Sn_MR_MACRAW mode * @details 0 : disable MAC Filtering\n * 1 : enable MAC Filtering\n * This bit is applied only during MACRAW mode(P[3:0] = 100.\n * When set as W5500 can only receive broadcasting packet or packet sent to itself. * When this bit is W5500 can receive all packets on Ethernet. * If user wants to implement Hybrid TCP/IP stack, * it is recommended that this bit is set as for reducing host overhead to process the all received packets. */ #define Sn_MR_MFEN Sn_MR_MULTI /** * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode * @details 0 : using IGMP version 2\n * 1 : using IGMP version 1\n * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = * It configures the version for IGMP messages (Join/Leave/Report). */ #define Sn_MR_MMB Sn_MR_ND /** * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode * @details 0 : disable IPv6 Blocking\n * 1 : enable IPv6 Blocking\n * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. */ #define Sn_MR_MIP6B Sn_MR_UCASTB /* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ /** * @brief IGMP version used in UDP mulitcasting * @details 0 : disable Multicast Blocking\n * 1 : enable Multicast Blocking\n * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. */ #define Sn_MR_MC Sn_MR_ND /* Sn_MR alternate values */ /** * @brief For Berkeley Socket API */ #define SOCK_STREAM Sn_MR_TCP /** * @brief For Berkeley Socket API */ #define SOCK_DGRAM Sn_MR_UDP /* Sn_CR values */ /** * @brief Initialize or open socket * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n * * * * * * *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000
Sn_MR_TCP (001 SOCK_INIT (0x13)
Sn_MR_UDP (010 SOCK_UDP (0x22)
S0_MR_MACRAW (100 SOCK_MACRAW (0x02)
*/ #define Sn_CR_OPEN 0x01 /** * @brief Wait connection request in TCP mode(Server mode) * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. * When a �TCP clientconnection request is successfully established, * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. */ #define Sn_CR_LISTEN 0x02 /** * @brief Send connection request in TCP mode(Client mode) * @details To connect, a connect-request (SYN packet) is sent to b>TCP server
configured by @ref Sn_DIPR & Sn_DPORT(destination address & port). * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n * The connect-request fails in the following three cases.\n * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client */ #define Sn_CR_CONNECT 0x04 /** * @brief Send closing request in TCP mode * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n * @par Active close * it transmits disconnect-request(FIN packet) to the connected peer\n * @par Passive close * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. * @note Valid only in TCP mode. */ #define Sn_CR_DISCON 0x08 /** * @brief Close socket * @details Sn_SR is changed to @ref SOCK_CLOSED. */ #define Sn_CR_CLOSE 0x10 /** * @brief Update TX buffer pointer and send data * @details SEND transmits all the data in the Socket n TX buffer.\n * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). */ #define Sn_CR_SEND 0x20 /** * @brief Send data with MAC address, so without ARP process * @details The basic operation is same as SEND.\n * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n * But SEND_MAC transmits data without the automatic ARP-process.\n * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. * @note Valid only in UDP mode. */ #define Sn_CR_SEND_MAC 0x21 /** * @brief Send keep alive message * @details It checks the connection status by sending 1byte keep-alive packet.\n * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. * @note Valid only in TCP mode. */ #define Sn_CR_SEND_KEEP 0x22 /** * @brief Update RX buffer pointer and receive data * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). */ #define Sn_CR_RECV 0x40 /* Sn_IR values */ /** * @brief SEND_OK Interrupt * @details This is issued when SEND command is completed. */ #define Sn_IR_SENDOK 0x10 /** * @brief TIMEOUT Interrupt * @details This is issued when ARPTO or TCPTO occurs. */ #define Sn_IR_TIMEOUT 0x08 /** * @brief RECV Interrupt * @details This is issued whenever data is received from a peer. */ #define Sn_IR_RECV 0x04 /** * @brief DISCON Interrupt * @details This is issued when FIN or FIN/ACK packet is received from a peer. */ #define Sn_IR_DISCON 0x02 /** * @brief CON Interrupt * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. */ #define Sn_IR_CON 0x01 /* Sn_SR values */ /** * @brief Closed * @details This indicates that Socket n is released.\N * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. */ #define SOCK_CLOSED 0x00 /** * @brief Initiate state * @details This indicates Socket n is opened with TCP mode.\N * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. */ #define SOCK_INIT 0x13 /** * @brief Listen state * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . */ #define SOCK_LISTEN 0x14 /** * @brief Connection state * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. */ #define SOCK_SYNSENT 0x15 /** * @brief Connection state * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . */ #define SOCK_SYNRECV 0x16 /** * @brief Success to connect * @details This indicates the status of the connection of Socket n.\n * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or * when the CONNECT command is successful.\n * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. */ #define SOCK_ESTABLISHED 0x17 /** * @brief Closing state * @details These indicate Socket n is closing.\n * These are shown in disconnect-process such as active-close and passive-close.\n * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. */ #define SOCK_FIN_WAIT 0x18 /** * @brief Closing state * @details These indicate Socket n is closing.\n * These are shown in disconnect-process such as active-close and passive-close.\n * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. */ #define SOCK_CLOSING 0x1A /** * @brief Closing state * @details These indicate Socket n is closing.\n * These are shown in disconnect-process such as active-close and passive-close.\n * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. */ #define SOCK_TIME_WAIT 0x1B /** * @brief Closing state * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n * This is half-closing status, and data can be transferred.\n * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. */ #define SOCK_CLOSE_WAIT 0x1C /** * @brief Closing state * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . */ #define SOCK_LAST_ACK 0x1D /** * @brief UDP socket * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n * Unlike TCP mode, data can be transfered without the connection-process. */ #define SOCK_UDP 0x22 //#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ /** * @brief MAC raw mode socket * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. */ #define SOCK_MACRAW 0x42 //#define SOCK_PPPOE 0x5F /* IP PROTOCOL */ #define IPPROTO_IP 0 //< Dummy for IP #define IPPROTO_ICMP 1 //< Control message protocol #define IPPROTO_IGMP 2 //< Internet group management protocol #define IPPROTO_GGP 3 //< Gateway^2 (deprecated) #define IPPROTO_TCP 6 //< TCP #define IPPROTO_PUP 12 //< PUP #define IPPROTO_UDP 17 //< UDP #define IPPROTO_IDP 22 //< XNS idp #define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol #define IPPROTO_RAW 255 //< Raw IP packet /** * @brief Enter a critical section * * @details It is provided to protect your shared code which are executed without distribution. \n \n * * In non-OS environment, It can be just implemented by disabling whole interrupt.\n * In OS environment, You can replace it to critical section api supported by OS. * * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() * \sa WIZCHIP_CRITICAL_EXIT() */ #define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() /** * @brief Exit a critical section * * @details It is provided to protect your shared code which are executed without distribution. \n\n * * In non-OS environment, It can be just implemented by disabling whole interrupt. \n * In OS environment, You can replace it to critical section api supported by OS. * * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() * @sa WIZCHIP_CRITICAL_ENTER() */ #ifdef _exit #undef _exit #endif #define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() //////////////////////// // Basic I/O Function // //////////////////////// /** * @ingroup Basic_IO_function * @brief It reads 1 byte value from a register. * @param AddrSel Register address * @return The value of register */ uint8_t WIZCHIP_READ (uint32_t AddrSel); /** * @ingroup Basic_IO_function * @brief It writes 1 byte value to a register. * @param AddrSel Register address * @param wb Write data * @return void */ void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); /** * @ingroup Basic_IO_function * @brief It reads sequence data from registers. * @param AddrSel Register address * @param pBuf Pointer buffer to read data * @param len Data length */ void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); /** * @ingroup Basic_IO_function * @brief It writes sequence data to registers. * @param AddrSel Register address * @param pBuf Pointer buffer to write data * @param len Data length */ void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); ///////////////////////////////// // Common Register I/O function // ///////////////////////////////// /** * @ingroup Common_register_access_function * @brief Set Mode Register * @param (uint8_t)mr The value to be set. * @sa getMR() */ #define setMR(mr) \ WIZCHIP_WRITE(MR,mr) /** * @ingroup Common_register_access_function * @brief Get Mode Register * @return uint8_t. The value of Mode register. * @sa setMR() */ #define getMR() \ WIZCHIP_READ(MR) /** * @ingroup Common_register_access_function * @brief Set gateway IP address * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. * @sa getGAR() */ #define setGAR(gar) \ WIZCHIP_WRITE_BUF(GAR,gar,4) /** * @ingroup Common_register_access_function * @brief Get gateway IP address * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. * @sa setGAR() */ #define getGAR(gar) \ WIZCHIP_READ_BUF(GAR,gar,4) /** * @ingroup Common_register_access_function * @brief Set subnet mask address * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. * @sa getSUBR() */ #define setSUBR(subr) \ WIZCHIP_WRITE_BUF(SUBR, subr,4) /** * @ingroup Common_register_access_function * @brief Get subnet mask address * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. * @sa setSUBR() */ #define getSUBR(subr) \ WIZCHIP_READ_BUF(SUBR, subr, 4) /** * @ingroup Common_register_access_function * @brief Set local MAC address * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. * @sa getSHAR() */ #define setSHAR(shar) \ WIZCHIP_WRITE_BUF(SHAR, shar, 6) /** * @ingroup Common_register_access_function * @brief Get local MAC address * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. * @sa setSHAR() */ #define getSHAR(shar) \ WIZCHIP_READ_BUF(SHAR, shar, 6) /** * @ingroup Common_register_access_function * @brief Set local IP address * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. * @sa getSIPR() */ #define setSIPR(sipr) \ WIZCHIP_WRITE_BUF(SIPR, sipr, 4) /** * @ingroup Common_register_access_function * @brief Get local IP address * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. * @sa setSIPR() */ #define getSIPR(sipr) \ WIZCHIP_READ_BUF(SIPR, sipr, 4) /** * @ingroup Common_register_access_function * @brief Set INTLEVEL register * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. * @sa getINTLEVEL() */ // dpgeorge: not yet implemented #define setINTLEVEL(intlevel) (void)intlevel #if 0 #define setINTLEVEL(intlevel) {\ WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ } #endif /** * @ingroup Common_register_access_function * @brief Get INTLEVEL register * @return uint16_t. Value of @ref INTLEVEL register. * @sa setINTLEVEL() */ // dpgeorge: not yet implemented #define getINTLEVEL() (0) #if 0 #define getINTLEVEL() \ ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) #endif /** * @ingroup Common_register_access_function * @brief Set @ref IR register * @param (uint8_t)ir Value to set @ref IR register. * @sa getIR() */ #define setIR(ir) \ WIZCHIP_WRITE(IR, (ir & 0xF0)) /** * @ingroup Common_register_access_function * @brief Get @ref IR register * @return uint8_t. Value of @ref IR register. * @sa setIR() */ #define getIR() \ (WIZCHIP_READ(IR) & 0xF0) /** * @ingroup Common_register_access_function * @brief Set @ref IMR register * @param (uint8_t)imr Value to set @ref IMR register. * @sa getIMR() */ #define setIMR(imr) \ WIZCHIP_WRITE(IMR, imr) /** * @ingroup Common_register_access_function * @brief Get @ref IMR register * @return uint8_t. Value of @ref IMR register. * @sa setIMR() */ #define getIMR() \ WIZCHIP_READ(IMR) /** * @ingroup Common_register_access_function * @brief Set @ref SIR register * @param (uint8_t)sir Value to set @ref SIR register. * @sa getSIR() */ // dpgeorge: not yet implemented #define setSIR(sir) ((void)sir) #if 0 #define setSIR(sir) \ WIZCHIP_WRITE(SIR, sir) #endif /** * @ingroup Common_register_access_function * @brief Get @ref SIR register * @return uint8_t. Value of @ref SIR register. * @sa setSIR() */ // dpgeorge: not yet implemented #define getSIR() (0) #if 0 #define getSIR() \ WIZCHIP_READ(SIR) #endif /** * @ingroup Common_register_access_function * @brief Set @ref SIMR register * @param (uint8_t)simr Value to set @ref SIMR register. * @sa getSIMR() */ // dpgeorge: not yet implemented #define setSIMR(simr) ((void)simr) #if 0 #define setSIMR(simr) \ WIZCHIP_WRITE(SIMR, simr) #endif /** * @ingroup Common_register_access_function * @brief Get @ref SIMR register * @return uint8_t. Value of @ref SIMR register. * @sa setSIMR() */ // dpgeorge: not yet implemented #define getSIMR() (0) #if 0 #define getSIMR() \ WIZCHIP_READ(SIMR) #endif /** * @ingroup Common_register_access_function * @brief Set @ref RTR register * @param (uint16_t)rtr Value to set @ref RTR register. * @sa getRTR() */ #define setRTR(rtr) {\ WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ WIZCHIP_WRITE(RTR + 1, (uint8_t) rtr); \ } /** * @ingroup Common_register_access_function * @brief Get @ref RTR register * @return uint16_t. Value of @ref RTR register. * @sa setRTR() */ #define getRTR() \ ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(RTR + 1)) /** * @ingroup Common_register_access_function * @brief Set @ref RCR register * @param (uint8_t)rcr Value to set @ref RCR register. * @sa getRCR() */ #define setRCR(rcr) \ WIZCHIP_WRITE(RCR, rcr) /** * @ingroup Common_register_access_function * @brief Get @ref RCR register * @return uint8_t. Value of @ref RCR register. * @sa setRCR() */ #define getRCR() \ WIZCHIP_READ(RCR) //================================================== test done =========================================================== /** * @ingroup Common_register_access_function * @brief Set @ref PTIMER register * @param (uint8_t)ptimer Value to set @ref PTIMER register. * @sa getPTIMER() */ #define setPTIMER(ptimer) \ WIZCHIP_WRITE(PTIMER, ptimer) /** * @ingroup Common_register_access_function * @brief Get @ref PTIMER register * @return uint8_t. Value of @ref PTIMER register. * @sa setPTIMER() */ #define getPTIMER() \ WIZCHIP_READ(PTIMER) /** * @ingroup Common_register_access_function * @brief Set @ref PMAGIC register * @param (uint8_t)pmagic Value to set @ref PMAGIC register. * @sa getPMAGIC() */ #define setPMAGIC(pmagic) \ WIZCHIP_WRITE(PMAGIC, pmagic) /** * @ingroup Common_register_access_function * @brief Get @ref PMAGIC register * @return uint8_t. Value of @ref PMAGIC register. * @sa setPMAGIC() */ #define getPMAGIC() \ WIZCHIP_READ(PMAGIC) /** * @ingroup Common_register_access_function * @brief Set PHAR address * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. * @sa getPHAR() */ #if 0 #define setPHAR(phar) \ WIZCHIP_WRITE_BUF(PHAR, phar, 6) /** * @ingroup Common_register_access_function * @brief Get local IP address * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. * @sa setPHAR() */ #define getPHAR(phar) \ WIZCHIP_READ_BUF(PHAR, phar, 6) /** * @ingroup Common_register_access_function * @brief Set @ref PSID register * @param (uint16_t)psid Value to set @ref PSID register. * @sa getPSID() */ #define setPSID(psid) {\ WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ } /** * @ingroup Common_register_access_function * @brief Get @ref PSID register * @return uint16_t. Value of @ref PSID register. * @sa setPSID() */ //uint16_t getPSID(void); #define getPSID() \ ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) /** * @ingroup Common_register_access_function * @brief Set @ref PMRU register * @param (uint16_t)pmru Value to set @ref PMRU register. * @sa getPMRU() */ #define setPMRU(pmru) { \ WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ } /** * @ingroup Common_register_access_function * @brief Get @ref PMRU register * @return uint16_t. Value of @ref PMRU register. * @sa setPMRU() */ #define getPMRU() \ ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) /** * @ingroup Common_register_access_function * @brief Get unreachable IP address * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. */ #define getUIPR(uipr) \ WIZCHIP_READ_BUF(UIPR,uipr,6) /** * @ingroup Common_register_access_function * @brief Get @ref UPORTR register * @return uint16_t. Value of @ref UPORTR register. */ #define getUPORTR() \ ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) /** * @ingroup Common_register_access_function * @brief Set @ref PHYCFGR register * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. * @sa getPHYCFGR() */ #define setPHYCFGR(phycfgr) \ WIZCHIP_WRITE(PHYCFGR, phycfgr) #endif /** * @ingroup Common_register_access_function * @brief Get @ref PHYCFGR register * @return uint8_t. Value of @ref PHYCFGR register. * @sa setPHYCFGR() */ #define getPHYSTATUS() \ WIZCHIP_READ(PHYSTATUS) /** * @ingroup Common_register_access_function * @brief Get @ref VERSIONR register * @return uint8_t. Value of @ref VERSIONR register. */ /* #define getVERSIONR() \ WIZCHIP_READ(VERSIONR) */ ///////////////////////////////////// /////////////////////////////////// // Socket N register I/O function // /////////////////////////////////// /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_MR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)mr Value to set @ref Sn_MR * @sa getSn_MR() */ #define setSn_MR(sn, mr) \ WIZCHIP_WRITE(Sn_MR(sn),mr) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_MR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_MR. * @sa setSn_MR() */ #define getSn_MR(sn) \ WIZCHIP_READ(Sn_MR(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_CR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)cr Value to set @ref Sn_CR * @sa getSn_CR() */ #define setSn_CR(sn, cr) \ WIZCHIP_WRITE(Sn_CR(sn), cr) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_CR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_CR. * @sa setSn_CR() */ #define getSn_CR(sn) \ WIZCHIP_READ(Sn_CR(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_IR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)ir Value to set @ref Sn_IR * @sa getSn_IR() */ #define setSn_IR(sn, ir) \ WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_IR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_IR. * @sa setSn_IR() */ #define getSn_IR(sn) \ (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_IMR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)imr Value to set @ref Sn_IMR * @sa getSn_IMR() */ // dpgeorge: not yet implemented #define setSn_IMR(sn, imr) (void)sn; (void)imr #if 0 #define setSn_IMR(sn, imr) \ WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) #endif /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_IMR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_IMR. * @sa setSn_IMR() */ // dpgeorge: not yet implemented #define getSn_IMR(sn) (0) #if 0 #define getSn_IMR(sn) \ (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) #endif /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_SR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_SR. */ #define getSn_SR(sn) \ WIZCHIP_READ(Sn_SR(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_PORT register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)port Value to set @ref Sn_PORT. * @sa getSn_PORT() */ #define setSn_PORT(sn, port) { \ WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ WIZCHIP_WRITE(Sn_PORT(sn) + 1, (uint8_t) port); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_PORT register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_PORT. * @sa setSn_PORT() */ #define getSn_PORT(sn) \ ((WIZCHIP_READ(Sn_PORT(sn)) << 8) | WIZCHIP_READ(Sn_PORT(sn) + 1)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_DHAR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. * @sa getSn_DHAR() */ #define setSn_DHAR(sn, dhar) \ WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_MR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. * @sa setSn_DHAR() */ #define getSn_DHAR(sn, dhar) \ WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_DIPR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. * @sa getSn_DIPR() */ #define setSn_DIPR(sn, dipr) \ WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_DIPR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. * @sa SetSn_DIPR() */ #define getSn_DIPR(sn, dipr) \ WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_DPORT register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)dport Value to set @ref Sn_DPORT * @sa getSn_DPORT() */ #define setSn_DPORT(sn, dport) { \ WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ WIZCHIP_WRITE(Sn_DPORT(sn) + 1, (uint8_t) dport); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_DPORT register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_DPORT. * @sa setSn_DPORT() */ #define getSn_DPORT(sn) \ ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ((Sn_DPORT(sn)+1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_MSSR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)mss Value to set @ref Sn_MSSR * @sa setSn_MSSR() */ #define setSn_MSSR(sn, mss) { \ WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ WIZCHIP_WRITE((Sn_MSSR(sn)+1), (uint8_t) mss); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_MSSR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_MSSR. * @sa setSn_MSSR() */ #define getSn_MSSR(sn) \ ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ((Sn_MSSR(sn)+1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_TOS register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)tos Value to set @ref Sn_TOS * @sa getSn_TOS() */ #define setSn_TOS(sn, tos) \ WIZCHIP_WRITE(Sn_TOS(sn), tos) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TOS register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of Sn_TOS. * @sa setSn_TOS() */ #define getSn_TOS(sn) \ WIZCHIP_READ(Sn_TOS(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_TTL register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)ttl Value to set @ref Sn_TTL * @sa getSn_TTL() */ #define setSn_TTL(sn, ttl) \ WIZCHIP_WRITE(Sn_TTL(sn), ttl) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TTL register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_TTL. * @sa setSn_TTL() */ #define getSn_TTL(sn) \ WIZCHIP_READ(Sn_TTL(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_RXBUF_SIZE register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE * @sa getSn_RXBUF_SIZE() */ #define setSn_RXBUF_SIZE(sn, rxbufsize) \ WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_RXBUF_SIZE register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. * @sa setSn_RXBUF_SIZE() */ #define getSn_RXBUF_SIZE(sn) \ WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_TXBUF_SIZE register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE * @sa getSn_TXBUF_SIZE() */ #define setSn_TXBUF_SIZE(sn, txbufsize) \ WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TXBUF_SIZE register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. * @sa setSn_TXBUF_SIZE() */ #define getSn_TXBUF_SIZE(sn) \ WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TX_FSR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_TX_FSR. */ uint16_t getSn_TX_FSR(uint8_t sn); /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TX_RD register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_TX_RD. */ #define getSn_TX_RD(sn) \ ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ((Sn_TX_RD(sn)+1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_TX_WR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)txwr Value to set @ref Sn_TX_WR * @sa GetSn_TX_WR() */ #define setSn_TX_WR(sn, txwr) { \ WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ WIZCHIP_WRITE((Sn_TX_WR(sn)+1), (uint8_t) txwr); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TX_WR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_TX_WR. * @sa setSn_TX_WR() */ #define getSn_TX_WR(sn) \ ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ((Sn_TX_WR(sn)+1))) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_RX_RSR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_RX_RSR. */ uint16_t getSn_RX_RSR(uint8_t sn); /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_RX_RD register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD * @sa getSn_RX_RD() */ #define setSn_RX_RD(sn, rxrd) { \ WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ WIZCHIP_WRITE((Sn_RX_RD(sn)+1), (uint8_t) rxrd); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_RX_RD register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @regurn uint16_t. Value of @ref Sn_RX_RD. * @sa setSn_RX_RD() */ #define getSn_RX_RD(sn) \ ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ((Sn_RX_RD(sn)+1))) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_RX_WR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_RX_WR. */ #define getSn_RX_WR(sn) \ ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ((Sn_RX_WR(sn)+1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_FRAG register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)frag Value to set @ref Sn_FRAG * @sa getSn_FRAD() */ #if 0 // dpgeorge #define setSn_FRAG(sn, frag) { \ WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_FRAG register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_FRAG. * @sa setSn_FRAG() */ #define getSn_FRAG(sn) \ ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_KPALVTR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR * @sa getSn_KPALVTR() */ #define setSn_KPALVTR(sn, kpalvt) \ WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_KPALVTR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_KPALVTR. * @sa setSn_KPALVTR() */ #define getSn_KPALVTR(sn) \ WIZCHIP_READ(Sn_KPALVTR(sn)) ////////////////////////////////////// #endif ///////////////////////////////////// // Sn_TXBUF & Sn_RXBUF IO function // ///////////////////////////////////// /** * @brief Gets the max buffer size of socket sn passed as parameter. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of Socket n RX max buffer size. */ #define getSn_RxMAX(sn) \ (getSn_RXBUF_SIZE(sn) << 10) /** * @brief Gets the max buffer size of socket sn passed as parameters. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of Socket n TX max buffer size. */ //uint16_t getSn_TxMAX(uint8_t sn); #define getSn_TxMAX(sn) \ (getSn_TXBUF_SIZE(sn) << 10) void wiz_init(void); /** * @ingroup Basic_IO_function * @brief It copies data to internal TX memory * * @details This function reads the Tx write pointer register and after that, * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory * and updates the Tx write pointer register. * This function is being called by send() and sendto() function also. * * @note User should read upper byte first and lower byte later to get proper value. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param wizdata Pointer buffer to write data * @param len Data length * @sa wiz_recv_data() */ void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); /** * @ingroup Basic_IO_function * @brief It copies data to your buffer from internal RX memory * * @details This function read the Rx read pointer register and after that, * it copies the received data from internal RX memory * to wizdata(pointer variable) of the length of len(variable) bytes. * This function is being called by recv() also. * * @note User should read upper byte first and lower byte later to get proper value. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param wizdata Pointer buffer to read data * @param len Data length * @sa wiz_send_data() */ void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); /** * @ingroup Basic_IO_function * @brief It discard the received data in RX memory. * @details It discards the data of the length of len(variable) bytes in internal RX memory. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param len Data length */ void wiz_recv_ignore(uint8_t sn, uint16_t len); #endif // _W5500_H_ micropython-1.12/drivers/wiznet5k/ethernet/w5500/000077500000000000000000000000001357706137100216565ustar00rootroot00000000000000micropython-1.12/drivers/wiznet5k/ethernet/w5500/w5500.c000066400000000000000000000173751357706137100226170ustar00rootroot00000000000000//***************************************************************************** // //! \file w5500.c //! \brief W5500 HAL Interface. //! \version 1.0.1 //! \date 2013/10/21 //! \par Revision history //! <2014/05/01> V1.0.2 //! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 //! Fixed the problem on porting into under 32bit MCU //! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh //! Thank for your interesting and serious advices. //! <2013/10/21> 1st Release //! <2013/12/20> V1.0.1 //! 1. Remove warning //! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ //! for loop optimized(removed). refer to M20131220 //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //#include #include "w5500.h" #define _W5500_SPI_VDM_OP_ 0x00 #define _W5500_SPI_FDM_OP_LEN1_ 0x01 #define _W5500_SPI_FDM_OP_LEN2_ 0x02 #define _W5500_SPI_FDM_OP_LEN4_ 0x03 //////////////////////////////////////////////////// #define LPC_SSP0 (0) static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) { WIZCHIP.IF.SPI._read_bytes(buf, len); } static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) { WIZCHIP.IF.SPI._write_bytes(buf, len); } uint8_t WIZCHIP_READ(uint32_t AddrSel) { uint8_t ret; uint8_t spi_data[3]; WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); //ret = WIZCHIP.IF.SPI._read_byte(); spi_data[0] = (AddrSel & 0x00FF0000) >> 16; spi_data[1] = (AddrSel & 0x0000FF00) >> 8; spi_data[2] = (AddrSel & 0x000000FF) >> 0; Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1); WIZCHIP.CS._deselect(); WIZCHIP_CRITICAL_EXIT(); return ret; } void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) { uint8_t spi_data[4]; WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); //WIZCHIP.IF.SPI._write_byte(wb); spi_data[0] = (AddrSel & 0x00FF0000) >> 16; spi_data[1] = (AddrSel & 0x0000FF00) >> 8; spi_data[2] = (AddrSel & 0x000000FF) >> 0; spi_data[3] = wb; Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4); WIZCHIP.CS._deselect(); WIZCHIP_CRITICAL_EXIT(); } void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { uint8_t spi_data[3]; //uint16_t i; WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); //for(i = 0; i < len; i++) // pBuf[i] = WIZCHIP.IF.SPI._read_byte(); spi_data[0] = (AddrSel & 0x00FF0000) >> 16; spi_data[1] = (AddrSel & 0x0000FF00) >> 8; spi_data[2] = (AddrSel & 0x000000FF) >> 0; Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len); WIZCHIP.CS._deselect(); WIZCHIP_CRITICAL_EXIT(); } void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { uint8_t spi_data[3]; //uint16_t i; WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); //for(i = 0; i < len; i++) // WIZCHIP.IF.SPI._write_byte(pBuf[i]); spi_data[0] = (AddrSel & 0x00FF0000) >> 16; spi_data[1] = (AddrSel & 0x0000FF00) >> 8; spi_data[2] = (AddrSel & 0x000000FF) >> 0; Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len); WIZCHIP.CS._deselect(); WIZCHIP_CRITICAL_EXIT(); } uint16_t getSn_TX_FSR(uint8_t sn) { uint16_t val=0,val1=0; do { val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); if (val1 != 0) { val = WIZCHIP_READ(Sn_TX_FSR(sn)); val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); } }while (val != val1); return val; } uint16_t getSn_RX_RSR(uint8_t sn) { uint16_t val=0,val1=0; do { val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); if (val1 != 0) { val = WIZCHIP_READ(Sn_RX_RSR(sn)); val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); } }while (val != val1); return val; } void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { uint16_t ptr = 0; uint32_t addrsel = 0; if(len == 0) return; ptr = getSn_TX_WR(sn); //M20140501 : implict type casting -> explict type casting //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); // WIZCHIP_WRITE_BUF(addrsel,wizdata, len); ptr += len; setSn_TX_WR(sn,ptr); } void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { uint16_t ptr = 0; uint32_t addrsel = 0; if(len == 0) return; ptr = getSn_RX_RD(sn); //M20140501 : implict type casting -> explict type casting //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); // WIZCHIP_READ_BUF(addrsel, wizdata, len); ptr += len; setSn_RX_RD(sn,ptr); } void wiz_recv_ignore(uint8_t sn, uint16_t len) { uint16_t ptr = 0; ptr = getSn_RX_RD(sn); ptr += len; setSn_RX_RD(sn,ptr); } micropython-1.12/drivers/wiznet5k/ethernet/w5500/w5500.h000066400000000000000000002317521357706137100226210ustar00rootroot00000000000000//***************************************************************************** // //! \file w5500.h //! \brief W5500 HAL Header File. //! \version 1.0.0 //! \date 2013/10/21 //! \par Revision history //! <2013/10/21> 1st Release //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef _W5500_H_ #define _W5500_H_ #include #include "../wizchip_conf.h" #define _W5500_IO_BASE_ 0x00000000 #define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase #define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase #define WIZCHIP_CREG_BLOCK 0x00 //< Common register block #define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block #define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block #define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block #define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address /////////////////////////////////////// // Definition For Legacy Chip Driver // /////////////////////////////////////// #define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver #define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver #define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver #define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver ////////////////////////////// //-------------------------- defgroup --------------------------------- /** * @defgroup W5500 W5500 * * @brief WHIZCHIP register defines and I/O functions of @b W5500. * * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function */ /** * @defgroup WIZCHIP_register WIZCHIP register * @ingroup W5500 * * @brief WHIZCHIP register defines register group of @b W5500. * * - @ref Common_register_group : Common register group * - @ref Socket_register_group : \c SOCKET n register group */ /** * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions * @ingroup W5500 * * @brief This supports the basic I/O functions for @ref WIZCHIP_register. * * - Basic I/O function \n * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n * * - @ref Common_register_group access functions \n * -# @b Mode \n * getMR(), setMR() * -# @b Interrupt \n * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() * -# Network Information \n * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() * -# @b Retransmission \n * getRCR(), setRCR(), getRTR(), setRTR() * -# @b PPPoE \n * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() * -# ICMP packet \n * getUIPR(), getUPORTR() * -# @b etc. \n * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n * * - \ref Socket_register_group access functions \n * -# SOCKET control \n * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() * -# SOCKET information \n * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() * getSn_MSSR(), setSn_MSSR() * -# SOCKET communication \n * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() * -# IP header field \n * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n * getSn_TTL(), setSn_TTL() */ /** * @defgroup Common_register_group Common register * @ingroup WIZCHIP_register * * @brief Common register group\n * It set the basic for the networking\n * It set the configuration such as interrupt, network information, ICMP, etc. * @details * @sa MR : Mode register. * @sa GAR, SUBR, SHAR, SIPR * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. * @sa RTR, RCR : Data retransmission. * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. * @sa UIPR, UPORTR : ICMP message. * @sa PHYCFGR, VERSIONR : etc. */ /** * @defgroup Socket_register_group Socket register * @ingroup WIZCHIP_register * * @brief Socket register group.\n * Socket register configures and control SOCKETn which is necessary to data communication. * @details * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication */ /** * @defgroup Basic_IO_function Basic I/O function * @ingroup WIZCHIP_IO_Functions * @brief These are basic input/output functions to read values from register or write values to register. */ /** * @defgroup Common_register_access_function Common register access functions * @ingroup WIZCHIP_IO_Functions * @brief These are functions to access common registers. */ /** * @defgroup Socket_register_access_function Socket register access functions * @ingroup WIZCHIP_IO_Functions * @brief These are functions to access socket registers. */ //------------------------------- defgroup end -------------------------------------------- //----------------------------- W5500 Common Registers IOMAP ----------------------------- /** * @ingroup Common_register_group * @brief Mode Register address(R/W)\n * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. * @details Each bit of @ref MR defined as follows. * * * *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
* - \ref MR_RST : Reset * - \ref MR_WOL : Wake on LAN * - \ref MR_PB : Ping block * - \ref MR_PPPOE : PPPoE mode * - \ref MR_FARP : Force ARP mode */ #define MR (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Gateway IP Register address(R/W) * @details @ref GAR configures the default gateway address. */ #define GAR (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Subnet mask Register address(R/W) * @details @ref SUBR configures the subnet mask address. */ #define SUBR (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Source MAC Register address(R/W) * @details @ref SHAR configures the source hardware address. */ #define SHAR (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Source IP Register address(R/W) * @details @ref SIPR configures the source IP address. */ #define SIPR (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Set Interrupt low level timer register address(R/W) * @details @ref INTLEVEL configures the Interrupt Assert Time. */ #define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Interrupt Register(R/W) * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n * Each bit of @ref IR defined as follows. * * * *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
* - \ref IR_CONFLICT : IP conflict * - \ref IR_UNREACH : Destination unreachable * - \ref IR_PPPoE : PPPoE connection close * - \ref IR_MP : Magic packet */ #define IR (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Interrupt mask register(R/W) * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n * Each bit of @ref IMR defined as the following. * * * *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
* - \ref IM_IR7 : IP Conflict Interrupt Mask * - \ref IM_IR6 : Destination unreachable Interrupt Mask * - \ref IM_IR5 : PPPoE Close Interrupt Mask * - \ref IM_IR4 : Magic Packet Interrupt Mask */ #define IMR (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Socket Interrupt Register(R/W) * @details @ref SIR indicates the interrupt status of Socket.\n * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ #define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Socket Interrupt Mask Register(R/W) * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is */ #define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Timeout register address( 1 is 100us )(R/W) * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. */ #define RTR (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Retry count register(R/W) * @details @ref RCR configures the number of time of retransmission. * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . */ #define RCR (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PPP LCP Request Timer register in PPPoE mode(R/W) * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. */ #define PTIMER (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PPP LCP Magic number register in PPPoE mode(R/W) * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. */ #define PMAGIC (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PPP Destination MAC Register address(R/W) * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. */ #define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PPP Session Identification Register(R/W) * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. */ #define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PPP Maximum Segment Size(MSS) register(R/W) * @details @ref PMRU configures the maximum receive unit of PPPoE. */ #define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Unreachable IP register address in UDP mode(R) * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates * the destination IP address & port number respectively. */ #define UIPR (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief Unreachable Port register address in UDP mode(R) * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR * indicates the destination IP address & port number respectively. */ #define UPORTR (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief PHY Status Register(R/W) * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. */ #define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) // Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) /** * @ingroup Common_register_group * @brief chip version register address(R) * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. */ #define VERSIONR (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) //----------------------------- W5500 Socket Registers IOMAP ----------------------------- /** * @ingroup Socket_register_group * @brief socket Mode register(R/W) * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n * Each bit of @ref Sn_MR defined as the following. * * * *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
* - @ref Sn_MR_MULTI : Support UDP Multicasting * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode * - Protocol * * * * * * *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
* - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n * - @ref Sn_MR_UDP : UDP * - @ref Sn_MR_TCP : TCP * - @ref Sn_MR_CLOSE : Unused socket * @note MACRAW mode should be only used in Socket 0. */ #define Sn_MR(N) (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Socket command register(R/W) * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. * - @ref Sn_CR_OPEN : Initialize or open socket. * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) * - @ref Sn_CR_DISCON : Send closing request in TCP mode. * - @ref Sn_CR_CLOSE : Close socket. * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. * - @ref Sn_CR_SEND_KEEP : Send keep alive message. * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. */ #define Sn_CR(N) (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Socket interrupt register(R) * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n * In order to clear the @ref Sn_IR bit, the host should write the bit to \n * * * *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
* - \ref Sn_IR_SENDOK : SEND_OK Interrupt * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt * - \ref Sn_IR_RECV : RECV Interrupt * - \ref Sn_IR_DISCON : DISCON Interrupt * - \ref Sn_IR_CON : CON Interrupt */ #define Sn_IR(N) (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Socket status register(R) * @details @ref Sn_SR indicates the status of Socket n.\n * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. * @par Normal status * - @ref SOCK_CLOSED : Closed * - @ref SOCK_INIT : Initiate state * - @ref SOCK_LISTEN : Listen state * - @ref SOCK_ESTABLISHED : Success to connect * - @ref SOCK_CLOSE_WAIT : Closing state * - @ref SOCK_UDP : UDP socket * - @ref SOCK_MACRAW : MAC raw mode socket *@par Temporary status during changing the status of Socket n. * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. * - @ref SOCK_FIN_WAIT : Connection state * - @ref SOCK_CLOSING : Closing state * - @ref SOCK_TIME_WAIT : Closing state * - @ref SOCK_LAST_ACK : Closing state */ #define Sn_SR(N) (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief source port register(R/W) * @details @ref Sn_PORT configures the source port number of Socket n. * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. */ #define Sn_PORT(N) (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Peer MAC register address(R/W) * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or * it indicates that it is acquired in ARP-process by CONNECT/SEND command. */ #define Sn_DHAR(N) (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Peer IP register address(R/W) * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. */ #define Sn_DIPR(N) (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Peer port register address(R/W) * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. */ #define Sn_DPORT(N) (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. */ #define Sn_MSSR(N) (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief IP Type of Service(TOS) Register(R/W) * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. * It is set before OPEN command. */ #define Sn_TOS(N) (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief IP Time to live(TTL) Register(R/W) * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. * It is set before OPEN command. */ #define Sn_TTL(N) (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) // Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Receive memory size register(R/W) * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. * If a different size is configured, the data cannot be normally received from a peer. * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. * When exceeded, the data reception error is occurred. */ #define Sn_RXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Transmit memory size register(R/W) * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. * If a different size is configured, the data can�t be normally transmitted to a peer. * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. * When exceeded, the data transmission error is occurred. */ #define Sn_TXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Transmit free memory size register(R) * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. */ #define Sn_TX_FSR(N) (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Transmit memory read pointer register address(R) * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. * After its initialization, it is auto-increased by SEND command. * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), * then the carry bit is ignored and will automatically update with the lower 16bits value. */ #define Sn_TX_RD(N) (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Transmit memory write pointer register address(R/W) * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n * It should be read or be updated like as follows.\n * 1. Read the starting address for saving the transmitting data.\n * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), * then the carry bit is ignored and will automatically update with the lower 16bits value.\n * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command */ #define Sn_TX_WR(N) (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Received data size register(R) * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) */ #define Sn_RX_RSR(N) (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Read point of Receive memory(R/W) * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n * 1. Read the starting save address of the received data.\n * 2. Read data from the starting address of Socket n RX Buffer.\n * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, * update with the lower 16bits value ignored the carry bit.\n * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. */ #define Sn_RX_RD(N) (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Write point of Receive memory(R) * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), * then the carry bit is ignored and will automatically update with the lower 16bits value. */ #define Sn_RX_WR(N) (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief socket interrupt mask register(R) * @details @ref Sn_IMR masks the interrupt of Socket n. * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is * Host is interrupted by asserted INTn PIN to low. */ #define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Fragment field value in IP header register(R/W) * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). */ #define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) /** * @ingroup Socket_register_group * @brief Keep Alive Timer register(R/W) * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, * and ignored in other modes. The time unit is 5s. * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. */ #define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) //#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) //----------------------------- W5500 Register values ----------------------------- /* MODE register values */ /** * @brief Reset * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. */ #define MR_RST 0x80 /** * @brief Wake on LAN * @details 0 : Disable WOL mode\n * 1 : Enable WOL mode\n * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. */ #define MR_WOL 0x20 /** * @brief Ping block * @details 0 : Disable Ping block\n * 1 : Enable Ping block\n * If the bit is it blocks the response to a ping request. */ #define MR_PB 0x10 /** * @brief Enable PPPoE * @details 0 : DisablePPPoE mode\n * 1 : EnablePPPoE mode\n * If you use ADSL, this bit should be */ #define MR_PPPOE 0x08 /** * @brief Enable UDP_FORCE_ARP CHECHK * @details 0 : Disable Force ARP mode\n * 1 : Enable Force ARP mode\n * In Force ARP mode, It forces on sending ARP Request whenever data is sent. */ #define MR_FARP 0x02 /* IR register values */ /** * @brief Check IP conflict. * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. */ #define IR_CONFLICT 0x80 /** * @brief Get the destination unreachable message in UDP sending. * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. */ #define IR_UNREACH 0x40 /** * @brief Get the PPPoE close message. * @details When PPPoE is disconnected during PPPoE mode, this bit is set. */ #define IR_PPPoE 0x20 /** * @brief Get the magic packet interrupt. * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. */ #define IR_MP 0x10 /* PHYCFGR register value */ #define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. #define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value #define PHYCFGR_OPMDC_ALLA (7<<3) #define PHYCFGR_OPMDC_PDOWN (6<<3) #define PHYCFGR_OPMDC_NA (5<<3) #define PHYCFGR_OPMDC_100FA (4<<3) #define PHYCFGR_OPMDC_100F (3<<3) #define PHYCFGR_OPMDC_100H (2<<3) #define PHYCFGR_OPMDC_10F (1<<3) #define PHYCFGR_OPMDC_10H (0<<3) #define PHYCFGR_DPX_FULL (1<<2) #define PHYCFGR_DPX_HALF (0<<2) #define PHYCFGR_SPD_100 (1<<1) #define PHYCFGR_SPD_10 (0<<1) #define PHYCFGR_LNK_ON (1<<0) #define PHYCFGR_LNK_OFF (0<<0) /* IMR register values */ /** * @brief IP Conflict Interrupt Mask. * @details 0: Disable IP Conflict Interrupt\n * 1: Enable IP Conflict Interrupt */ #define IM_IR7 0x80 /** * @brief Destination unreachable Interrupt Mask. * @details 0: Disable Destination unreachable Interrupt\n * 1: Enable Destination unreachable Interrupt */ #define IM_IR6 0x40 /** * @brief PPPoE Close Interrupt Mask. * @details 0: Disable PPPoE Close Interrupt\n * 1: Enable PPPoE Close Interrupt */ #define IM_IR5 0x20 /** * @brief Magic Packet Interrupt Mask. * @details 0: Disable Magic Packet Interrupt\n * 1: Enable Magic Packet Interrupt */ #define IM_IR4 0x10 /* Sn_MR Default values */ /** * @brief Support UDP Multicasting * @details 0 : disable Multicasting\n * 1 : enable Multicasting\n * This bit is applied only during UDP mode(P[3:0] = 010.\n * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number * before Socket n is opened by OPEN command of @ref Sn_CR. */ #define Sn_MR_MULTI 0x80 /** * @brief Broadcast block in UDP Multicasting. * @details 0 : disable Broadcast Blocking\n * 1 : enable Broadcast Blocking\n * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m * In addition, This bit does when MACRAW mode(P[3:0] = 100 */ #define Sn_MR_BCASTB 0x40 /** * @brief No Delayed Ack(TCP), Multicast flag * @details 0 : Disable No Delayed ACK option\n * 1 : Enable No Delayed ACK option\n * This bit is applied only during TCP mode (P[3:0] = 001.\n * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. */ #define Sn_MR_ND 0x20 /** * @brief Unicast Block in UDP Multicasting * @details 0 : disable Unicast Blocking\n * 1 : enable Unicast Blocking\n * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = */ #define Sn_MR_UCASTB 0x10 /** * @brief MAC LAYER RAW SOCK * @details This configures the protocol mode of Socket n. * @note MACRAW mode should be only used in Socket 0. */ #define Sn_MR_MACRAW 0x04 //#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ /** * @brief UDP * @details This configures the protocol mode of Socket n. */ #define Sn_MR_UDP 0x02 /** * @brief TCP * @details This configures the protocol mode of Socket n. */ #define Sn_MR_TCP 0x01 /** * @brief Unused socket * @details This configures the protocol mode of Socket n. */ #define Sn_MR_CLOSE 0x00 /* Sn_MR values used with Sn_MR_MACRAW */ /** * @brief MAC filter enable in @ref Sn_MR_MACRAW mode * @details 0 : disable MAC Filtering\n * 1 : enable MAC Filtering\n * This bit is applied only during MACRAW mode(P[3:0] = 100.\n * When set as W5500 can only receive broadcasting packet or packet sent to itself. * When this bit is W5500 can receive all packets on Ethernet. * If user wants to implement Hybrid TCP/IP stack, * it is recommended that this bit is set as for reducing host overhead to process the all received packets. */ #define Sn_MR_MFEN Sn_MR_MULTI /** * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode * @details 0 : using IGMP version 2\n * 1 : using IGMP version 1\n * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = * It configures the version for IGMP messages (Join/Leave/Report). */ #define Sn_MR_MMB Sn_MR_ND /** * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode * @details 0 : disable IPv6 Blocking\n * 1 : enable IPv6 Blocking\n * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. */ #define Sn_MR_MIP6B Sn_MR_UCASTB /* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ /** * @brief IGMP version used in UDP mulitcasting * @details 0 : disable Multicast Blocking\n * 1 : enable Multicast Blocking\n * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. */ #define Sn_MR_MC Sn_MR_ND /* Sn_MR alternate values */ /** * @brief For Berkeley Socket API */ #define SOCK_STREAM Sn_MR_TCP /** * @brief For Berkeley Socket API */ #define SOCK_DGRAM Sn_MR_UDP /* Sn_CR values */ /** * @brief Initialize or open socket * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n * * * * * * *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000
Sn_MR_TCP (001 SOCK_INIT (0x13)
Sn_MR_UDP (010 SOCK_UDP (0x22)
S0_MR_MACRAW (100 SOCK_MACRAW (0x02)
*/ #define Sn_CR_OPEN 0x01 /** * @brief Wait connection request in TCP mode(Server mode) * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. * When a �TCP clientconnection request is successfully established, * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. */ #define Sn_CR_LISTEN 0x02 /** * @brief Send connection request in TCP mode(Client mode) * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port). * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n * The connect-request fails in the following three cases.\n * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client */ #define Sn_CR_CONNECT 0x04 /** * @brief Send closing request in TCP mode * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n * @par Active close * it transmits disconnect-request(FIN packet) to the connected peer\n * @par Passive close * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. * @note Valid only in TCP mode. */ #define Sn_CR_DISCON 0x08 /** * @brief Close socket * @details Sn_SR is changed to @ref SOCK_CLOSED. */ #define Sn_CR_CLOSE 0x10 /** * @brief Update TX buffer pointer and send data * @details SEND transmits all the data in the Socket n TX buffer.\n * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). */ #define Sn_CR_SEND 0x20 /** * @brief Send data with MAC address, so without ARP process * @details The basic operation is same as SEND.\n * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n * But SEND_MAC transmits data without the automatic ARP-process.\n * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. * @note Valid only in UDP mode. */ #define Sn_CR_SEND_MAC 0x21 /** * @brief Send keep alive message * @details It checks the connection status by sending 1byte keep-alive packet.\n * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. * @note Valid only in TCP mode. */ #define Sn_CR_SEND_KEEP 0x22 /** * @brief Update RX buffer pointer and receive data * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). */ #define Sn_CR_RECV 0x40 /* Sn_IR values */ /** * @brief SEND_OK Interrupt * @details This is issued when SEND command is completed. */ #define Sn_IR_SENDOK 0x10 /** * @brief TIMEOUT Interrupt * @details This is issued when ARPTO or TCPTO occurs. */ #define Sn_IR_TIMEOUT 0x08 /** * @brief RECV Interrupt * @details This is issued whenever data is received from a peer. */ #define Sn_IR_RECV 0x04 /** * @brief DISCON Interrupt * @details This is issued when FIN or FIN/ACK packet is received from a peer. */ #define Sn_IR_DISCON 0x02 /** * @brief CON Interrupt * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. */ #define Sn_IR_CON 0x01 /* Sn_SR values */ /** * @brief Closed * @details This indicates that Socket n is released.\N * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. */ #define SOCK_CLOSED 0x00 /** * @brief Initiate state * @details This indicates Socket n is opened with TCP mode.\N * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. */ #define SOCK_INIT 0x13 /** * @brief Listen state * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . */ #define SOCK_LISTEN 0x14 /** * @brief Connection state * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. */ #define SOCK_SYNSENT 0x15 /** * @brief Connection state * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . */ #define SOCK_SYNRECV 0x16 /** * @brief Success to connect * @details This indicates the status of the connection of Socket n.\n * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or * when the CONNECT command is successful.\n * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. */ #define SOCK_ESTABLISHED 0x17 /** * @brief Closing state * @details These indicate Socket n is closing.\n * These are shown in disconnect-process such as active-close and passive-close.\n * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. */ #define SOCK_FIN_WAIT 0x18 /** * @brief Closing state * @details These indicate Socket n is closing.\n * These are shown in disconnect-process such as active-close and passive-close.\n * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. */ #define SOCK_CLOSING 0x1A /** * @brief Closing state * @details These indicate Socket n is closing.\n * These are shown in disconnect-process such as active-close and passive-close.\n * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. */ #define SOCK_TIME_WAIT 0x1B /** * @brief Closing state * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n * This is half-closing status, and data can be transferred.\n * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. */ #define SOCK_CLOSE_WAIT 0x1C /** * @brief Closing state * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . */ #define SOCK_LAST_ACK 0x1D /** * @brief UDP socket * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n * Unlike TCP mode, data can be transfered without the connection-process. */ #define SOCK_UDP 0x22 //#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ /** * @brief MAC raw mode socket * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. */ #define SOCK_MACRAW 0x42 //#define SOCK_PPPOE 0x5F /* IP PROTOCOL */ #define IPPROTO_IP 0 //< Dummy for IP #define IPPROTO_ICMP 1 //< Control message protocol #define IPPROTO_IGMP 2 //< Internet group management protocol #define IPPROTO_GGP 3 //< Gateway^2 (deprecated) #define IPPROTO_TCP 6 //< TCP #define IPPROTO_PUP 12 //< PUP #define IPPROTO_UDP 17 //< UDP #define IPPROTO_IDP 22 //< XNS idp #define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol #define IPPROTO_RAW 255 //< Raw IP packet /** * @brief Enter a critical section * * @details It is provided to protect your shared code which are executed without distribution. \n \n * * In non-OS environment, It can be just implemented by disabling whole interrupt.\n * In OS environment, You can replace it to critical section api supported by OS. * * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() * \sa WIZCHIP_CRITICAL_EXIT() */ #define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() /** * @brief Exit a critical section * * @details It is provided to protect your shared code which are executed without distribution. \n\n * * In non-OS environment, It can be just implemented by disabling whole interrupt. \n * In OS environment, You can replace it to critical section api supported by OS. * * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() * @sa WIZCHIP_CRITICAL_ENTER() */ #ifdef _exit #undef _exit #endif #define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() //////////////////////// // Basic I/O Function // //////////////////////// /** * @ingroup Basic_IO_function * @brief It reads 1 byte value from a register. * @param AddrSel Register address * @return The value of register */ uint8_t WIZCHIP_READ (uint32_t AddrSel); /** * @ingroup Basic_IO_function * @brief It writes 1 byte value to a register. * @param AddrSel Register address * @param wb Write data * @return void */ void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); /** * @ingroup Basic_IO_function * @brief It reads sequence data from registers. * @param AddrSel Register address * @param pBuf Pointer buffer to read data * @param len Data length */ void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); /** * @ingroup Basic_IO_function * @brief It writes sequence data to registers. * @param AddrSel Register address * @param pBuf Pointer buffer to write data * @param len Data length */ void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); ///////////////////////////////// // Common Register I/O function // ///////////////////////////////// /** * @ingroup Common_register_access_function * @brief Set Mode Register * @param (uint8_t)mr The value to be set. * @sa getMR() */ #define setMR(mr) \ WIZCHIP_WRITE(MR,mr) /** * @ingroup Common_register_access_function * @brief Get Mode Register * @return uint8_t. The value of Mode register. * @sa setMR() */ #define getMR() \ WIZCHIP_READ(MR) /** * @ingroup Common_register_access_function * @brief Set gateway IP address * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. * @sa getGAR() */ #define setGAR(gar) \ WIZCHIP_WRITE_BUF(GAR,gar,4) /** * @ingroup Common_register_access_function * @brief Get gateway IP address * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. * @sa setGAR() */ #define getGAR(gar) \ WIZCHIP_READ_BUF(GAR,gar,4) /** * @ingroup Common_register_access_function * @brief Set subnet mask address * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. * @sa getSUBR() */ #define setSUBR(subr) \ WIZCHIP_WRITE_BUF(SUBR, subr,4) /** * @ingroup Common_register_access_function * @brief Get subnet mask address * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. * @sa setSUBR() */ #define getSUBR(subr) \ WIZCHIP_READ_BUF(SUBR, subr, 4) /** * @ingroup Common_register_access_function * @brief Set local MAC address * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. * @sa getSHAR() */ #define setSHAR(shar) \ WIZCHIP_WRITE_BUF(SHAR, shar, 6) /** * @ingroup Common_register_access_function * @brief Get local MAC address * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. * @sa setSHAR() */ #define getSHAR(shar) \ WIZCHIP_READ_BUF(SHAR, shar, 6) /** * @ingroup Common_register_access_function * @brief Set local IP address * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. * @sa getSIPR() */ #define setSIPR(sipr) \ WIZCHIP_WRITE_BUF(SIPR, sipr, 4) /** * @ingroup Common_register_access_function * @brief Get local IP address * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. * @sa setSIPR() */ #define getSIPR(sipr) \ WIZCHIP_READ_BUF(SIPR, sipr, 4) /** * @ingroup Common_register_access_function * @brief Set INTLEVEL register * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. * @sa getINTLEVEL() */ #define setINTLEVEL(intlevel) {\ WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ } /** * @ingroup Common_register_access_function * @brief Get INTLEVEL register * @return uint16_t. Value of @ref INTLEVEL register. * @sa setINTLEVEL() */ #define getINTLEVEL() \ ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) /** * @ingroup Common_register_access_function * @brief Set @ref IR register * @param (uint8_t)ir Value to set @ref IR register. * @sa getIR() */ #define setIR(ir) \ WIZCHIP_WRITE(IR, (ir & 0xF0)) /** * @ingroup Common_register_access_function * @brief Get @ref IR register * @return uint8_t. Value of @ref IR register. * @sa setIR() */ #define getIR() \ (WIZCHIP_READ(IR) & 0xF0) /** * @ingroup Common_register_access_function * @brief Set @ref IMR register * @param (uint8_t)imr Value to set @ref IMR register. * @sa getIMR() */ #define setIMR(imr) \ WIZCHIP_WRITE(IMR, imr) /** * @ingroup Common_register_access_function * @brief Get @ref IMR register * @return uint8_t. Value of @ref IMR register. * @sa setIMR() */ #define getIMR() \ WIZCHIP_READ(IMR) /** * @ingroup Common_register_access_function * @brief Set @ref SIR register * @param (uint8_t)sir Value to set @ref SIR register. * @sa getSIR() */ #define setSIR(sir) \ WIZCHIP_WRITE(SIR, sir) /** * @ingroup Common_register_access_function * @brief Get @ref SIR register * @return uint8_t. Value of @ref SIR register. * @sa setSIR() */ #define getSIR() \ WIZCHIP_READ(SIR) /** * @ingroup Common_register_access_function * @brief Set @ref SIMR register * @param (uint8_t)simr Value to set @ref SIMR register. * @sa getSIMR() */ #define setSIMR(simr) \ WIZCHIP_WRITE(SIMR, simr) /** * @ingroup Common_register_access_function * @brief Get @ref SIMR register * @return uint8_t. Value of @ref SIMR register. * @sa setSIMR() */ #define getSIMR() \ WIZCHIP_READ(SIMR) /** * @ingroup Common_register_access_function * @brief Set @ref RTR register * @param (uint16_t)rtr Value to set @ref RTR register. * @sa getRTR() */ #define setRTR(rtr) {\ WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RTR,1), (uint8_t) rtr); \ } /** * @ingroup Common_register_access_function * @brief Get @ref RTR register * @return uint16_t. Value of @ref RTR register. * @sa setRTR() */ #define getRTR() \ ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(RTR,1))) /** * @ingroup Common_register_access_function * @brief Set @ref RCR register * @param (uint8_t)rcr Value to set @ref RCR register. * @sa getRCR() */ #define setRCR(rcr) \ WIZCHIP_WRITE(RCR, rcr) /** * @ingroup Common_register_access_function * @brief Get @ref RCR register * @return uint8_t. Value of @ref RCR register. * @sa setRCR() */ #define getRCR() \ WIZCHIP_READ(RCR) //================================================== test done =========================================================== /** * @ingroup Common_register_access_function * @brief Set @ref PTIMER register * @param (uint8_t)ptimer Value to set @ref PTIMER register. * @sa getPTIMER() */ #define setPTIMER(ptimer) \ WIZCHIP_WRITE(PTIMER, ptimer) /** * @ingroup Common_register_access_function * @brief Get @ref PTIMER register * @return uint8_t. Value of @ref PTIMER register. * @sa setPTIMER() */ #define getPTIMER() \ WIZCHIP_READ(PTIMER) /** * @ingroup Common_register_access_function * @brief Set @ref PMAGIC register * @param (uint8_t)pmagic Value to set @ref PMAGIC register. * @sa getPMAGIC() */ #define setPMAGIC(pmagic) \ WIZCHIP_WRITE(PMAGIC, pmagic) /** * @ingroup Common_register_access_function * @brief Get @ref PMAGIC register * @return uint8_t. Value of @ref PMAGIC register. * @sa setPMAGIC() */ #define getPMAGIC() \ WIZCHIP_READ(PMAGIC) /** * @ingroup Common_register_access_function * @brief Set PHAR address * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. * @sa getPHAR() */ #define setPHAR(phar) \ WIZCHIP_WRITE_BUF(PHAR, phar, 6) /** * @ingroup Common_register_access_function * @brief Get local IP address * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. * @sa setPHAR() */ #define getPHAR(phar) \ WIZCHIP_READ_BUF(PHAR, phar, 6) /** * @ingroup Common_register_access_function * @brief Set @ref PSID register * @param (uint16_t)psid Value to set @ref PSID register. * @sa getPSID() */ #define setPSID(psid) {\ WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ } /** * @ingroup Common_register_access_function * @brief Get @ref PSID register * @return uint16_t. Value of @ref PSID register. * @sa setPSID() */ //uint16_t getPSID(void); #define getPSID() \ ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) /** * @ingroup Common_register_access_function * @brief Set @ref PMRU register * @param (uint16_t)pmru Value to set @ref PMRU register. * @sa getPMRU() */ #define setPMRU(pmru) { \ WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ } /** * @ingroup Common_register_access_function * @brief Get @ref PMRU register * @return uint16_t. Value of @ref PMRU register. * @sa setPMRU() */ #define getPMRU() \ ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) /** * @ingroup Common_register_access_function * @brief Get unreachable IP address * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. */ #define getUIPR(uipr) \ WIZCHIP_READ_BUF(UIPR,uipr,6) /** * @ingroup Common_register_access_function * @brief Get @ref UPORTR register * @return uint16_t. Value of @ref UPORTR register. */ #define getUPORTR() \ ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) /** * @ingroup Common_register_access_function * @brief Set @ref PHYCFGR register * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. * @sa getPHYCFGR() */ #define setPHYCFGR(phycfgr) \ WIZCHIP_WRITE(PHYCFGR, phycfgr) /** * @ingroup Common_register_access_function * @brief Get @ref PHYCFGR register * @return uint8_t. Value of @ref PHYCFGR register. * @sa setPHYCFGR() */ #define getPHYCFGR() \ WIZCHIP_READ(PHYCFGR) /** * @ingroup Common_register_access_function * @brief Get @ref VERSIONR register * @return uint8_t. Value of @ref VERSIONR register. */ #define getVERSIONR() \ WIZCHIP_READ(VERSIONR) ///////////////////////////////////// /////////////////////////////////// // Socket N register I/O function // /////////////////////////////////// /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_MR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)mr Value to set @ref Sn_MR * @sa getSn_MR() */ #define setSn_MR(sn, mr) \ WIZCHIP_WRITE(Sn_MR(sn),mr) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_MR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_MR. * @sa setSn_MR() */ #define getSn_MR(sn) \ WIZCHIP_READ(Sn_MR(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_CR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)cr Value to set @ref Sn_CR * @sa getSn_CR() */ #define setSn_CR(sn, cr) \ WIZCHIP_WRITE(Sn_CR(sn), cr) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_CR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_CR. * @sa setSn_CR() */ #define getSn_CR(sn) \ WIZCHIP_READ(Sn_CR(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_IR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)ir Value to set @ref Sn_IR * @sa getSn_IR() */ #define setSn_IR(sn, ir) \ WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_IR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_IR. * @sa setSn_IR() */ #define getSn_IR(sn) \ (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_IMR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)imr Value to set @ref Sn_IMR * @sa getSn_IMR() */ #define setSn_IMR(sn, imr) \ WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_IMR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_IMR. * @sa setSn_IMR() */ #define getSn_IMR(sn) \ (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_SR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_SR. */ #define getSn_SR(sn) \ WIZCHIP_READ(Sn_SR(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_PORT register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)port Value to set @ref Sn_PORT. * @sa getSn_PORT() */ #define setSn_PORT(sn, port) { \ WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_PORT register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_PORT. * @sa setSn_PORT() */ #define getSn_PORT(sn) \ ((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_DHAR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. * @sa getSn_DHAR() */ #define setSn_DHAR(sn, dhar) \ WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_MR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. * @sa setSn_DHAR() */ #define getSn_DHAR(sn, dhar) \ WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_DIPR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. * @sa getSn_DIPR() */ #define setSn_DIPR(sn, dipr) \ WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_DIPR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. * @sa SetSn_DIPR() */ #define getSn_DIPR(sn, dipr) \ WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_DPORT register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)dport Value to set @ref Sn_DPORT * @sa getSn_DPORT() */ #define setSn_DPORT(sn, dport) { \ WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_DPORT register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_DPORT. * @sa setSn_DPORT() */ #define getSn_DPORT(sn) \ ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_MSSR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)mss Value to set @ref Sn_MSSR * @sa setSn_MSSR() */ #define setSn_MSSR(sn, mss) { \ WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_MSSR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_MSSR. * @sa setSn_MSSR() */ #define getSn_MSSR(sn) \ ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_TOS register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)tos Value to set @ref Sn_TOS * @sa getSn_TOS() */ #define setSn_TOS(sn, tos) \ WIZCHIP_WRITE(Sn_TOS(sn), tos) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TOS register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of Sn_TOS. * @sa setSn_TOS() */ #define getSn_TOS(sn) \ WIZCHIP_READ(Sn_TOS(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_TTL register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)ttl Value to set @ref Sn_TTL * @sa getSn_TTL() */ #define setSn_TTL(sn, ttl) \ WIZCHIP_WRITE(Sn_TTL(sn), ttl) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TTL register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_TTL. * @sa setSn_TTL() */ #define getSn_TTL(sn) \ WIZCHIP_READ(Sn_TTL(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_RXBUF_SIZE register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE * @sa getSn_RXBUF_SIZE() */ #define setSn_RXBUF_SIZE(sn, rxbufsize) \ WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_RXBUF_SIZE register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. * @sa setSn_RXBUF_SIZE() */ #define getSn_RXBUF_SIZE(sn) \ WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_TXBUF_SIZE register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE * @sa getSn_TXBUF_SIZE() */ #define setSn_TXBUF_SIZE(sn, txbufsize) \ WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TXBUF_SIZE register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. * @sa setSn_TXBUF_SIZE() */ #define getSn_TXBUF_SIZE(sn) \ WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TX_FSR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_TX_FSR. */ uint16_t getSn_TX_FSR(uint8_t sn); /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TX_RD register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_TX_RD. */ #define getSn_TX_RD(sn) \ ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_TX_WR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)txwr Value to set @ref Sn_TX_WR * @sa GetSn_TX_WR() */ #define setSn_TX_WR(sn, txwr) { \ WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_TX_WR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_TX_WR. * @sa setSn_TX_WR() */ #define getSn_TX_WR(sn) \ ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_RX_RSR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_RX_RSR. */ uint16_t getSn_RX_RSR(uint8_t sn); /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_RX_RD register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD * @sa getSn_RX_RD() */ #define setSn_RX_RD(sn, rxrd) { \ WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_RX_RD register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @regurn uint16_t. Value of @ref Sn_RX_RD. * @sa setSn_RX_RD() */ #define getSn_RX_RD(sn) \ ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_RX_WR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_RX_WR. */ #define getSn_RX_WR(sn) \ ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_FRAG register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint16_t)frag Value to set @ref Sn_FRAG * @sa getSn_FRAD() */ #define setSn_FRAG(sn, frag) { \ WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ } /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_FRAG register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of @ref Sn_FRAG. * @sa setSn_FRAG() */ #define getSn_FRAG(sn) \ ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) /** * @ingroup Socket_register_access_function * @brief Set @ref Sn_KPALVTR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR * @sa getSn_KPALVTR() */ #define setSn_KPALVTR(sn, kpalvt) \ WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) /** * @ingroup Socket_register_access_function * @brief Get @ref Sn_KPALVTR register * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint8_t. Value of @ref Sn_KPALVTR. * @sa setSn_KPALVTR() */ #define getSn_KPALVTR(sn) \ WIZCHIP_READ(Sn_KPALVTR(sn)) ////////////////////////////////////// ///////////////////////////////////// // Sn_TXBUF & Sn_RXBUF IO function // ///////////////////////////////////// /** * @brief Gets the max buffer size of socket sn passed as parameter. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of Socket n RX max buffer size. */ #define getSn_RxMAX(sn) \ (getSn_RXBUF_SIZE(sn) << 10) /** * @brief Gets the max buffer size of socket sn passed as parameters. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @return uint16_t. Value of Socket n TX max buffer size. */ //uint16_t getSn_TxMAX(uint8_t sn); #define getSn_TxMAX(sn) \ (getSn_TXBUF_SIZE(sn) << 10) /** * @ingroup Basic_IO_function * @brief It copies data to internal TX memory * * @details This function reads the Tx write pointer register and after that, * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory * and updates the Tx write pointer register. * This function is being called by send() and sendto() function also. * * @note User should read upper byte first and lower byte later to get proper value. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param wizdata Pointer buffer to write data * @param len Data length * @sa wiz_recv_data() */ void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); /** * @ingroup Basic_IO_function * @brief It copies data to your buffer from internal RX memory * * @details This function read the Rx read pointer register and after that, * it copies the received data from internal RX memory * to wizdata(pointer variable) of the length of len(variable) bytes. * This function is being called by recv() also. * * @note User should read upper byte first and lower byte later to get proper value. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param wizdata Pointer buffer to read data * @param len Data length * @sa wiz_send_data() */ void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); /** * @ingroup Basic_IO_function * @brief It discard the received data in RX memory. * @details It discards the data of the length of len(variable) bytes in internal RX memory. * @param (uint8_t)sn Socket number. It should be 0 ~ 7. * @param len Data length */ void wiz_recv_ignore(uint8_t sn, uint16_t len); #endif // _W5500_H_ micropython-1.12/drivers/wiznet5k/ethernet/wizchip_conf.c000066400000000000000000000423721357706137100237340ustar00rootroot00000000000000//****************************************************************************/ //! //! \file wizchip_conf.c //! \brief WIZCHIP Config Header File. //! \version 1.0.1 //! \date 2013/10/21 //! \par Revision history //! <2014/05/01> V1.0.1 Refer to M20140501 //! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte() // Issued by Mathias ClauBen. //! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t* //! For remove the warning when pointer type size is not 32bit. //! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type. //! <2013/10/21> 1st Release //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //*****************************************************************************/ //A20140501 : for use the type - ptrdiff_t #include // #include "wizchip_conf.h" #include "socket.h" /** * @brief Default function to enable interrupt. * @note This function help not to access wrong address. If you do not describe this function or register any functions, * null function is called. */ void wizchip_cris_enter(void) {}; /** * @brief Default function to disable interrupt. * @note This function help not to access wrong address. If you do not describe this function or register any functions, * null function is called. */ void wizchip_cris_exit(void) {}; /** * @brief Default function to select chip. * @note This function help not to access wrong address. If you do not describe this function or register any functions, * null function is called. */ void wizchip_cs_select(void) {}; /** * @brief Default function to deselect chip. * @note This function help not to access wrong address. If you do not describe this function or register any functions, * null function is called. */ void wizchip_cs_deselect(void) {}; /** * @brief Default function to read in direct or indirect interface. * @note This function help not to access wrong address. If you do not describe this function or register any functions, * null function is called. */ //M20140501 : Explict pointer type casting //uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); }; uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); }; /** * @brief Default function to write in direct or indirect interface. * @note This function help not to access wrong address. If you do not describe this function or register any functions, * null function is called. */ //M20140501 : Explict pointer type casting //void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; }; void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; }; /** * @brief Default function to read in SPI interface. * @note This function help not to access wrong address. If you do not describe this function or register any functions, * null function is called. */ void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {} /** * @brief Default function to write in SPI interface. * @note This function help not to access wrong address. If you do not describe this function or register any functions, * null function is called. */ void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {} /** * @\ref _WIZCHIP instance */ _WIZCHIP WIZCHIP = { .id = _WIZCHIP_ID_, .if_mode = _WIZCHIP_IO_MODE_, .CRIS._enter = wizchip_cris_enter, .CRIS._exit = wizchip_cris_exit, .CS._select = wizchip_cs_select, .CS._deselect = wizchip_cs_deselect, .IF.BUS._read_byte = wizchip_bus_readbyte, .IF.BUS._write_byte = wizchip_bus_writebyte // .IF.SPI._read_byte = wizchip_spi_readbyte, // .IF.SPI._write_byte = wizchip_spi_writebyte }; #if _WIZCHIP_ == 5200 // for W5200 ARP errata static uint8_t _SUBN_[4]; // subnet #endif static uint8_t _DNS_[4]; // DNS server ip address static dhcp_mode _DHCP_; // DHCP mode void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)) { if(!cris_en || !cris_ex) { WIZCHIP.CRIS._enter = wizchip_cris_enter; WIZCHIP.CRIS._exit = wizchip_cris_exit; } else { WIZCHIP.CRIS._enter = cris_en; WIZCHIP.CRIS._exit = cris_ex; } } void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)) { if(!cs_sel || !cs_desel) { WIZCHIP.CS._select = wizchip_cs_select; WIZCHIP.CS._deselect = wizchip_cs_deselect; } else { WIZCHIP.CS._select = cs_sel; WIZCHIP.CS._deselect = cs_desel; } } void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)) { while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_)); if(!bus_rb || !bus_wb) { WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte; WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte; } else { WIZCHIP.IF.BUS._read_byte = bus_rb; WIZCHIP.IF.BUS._write_byte = bus_wb; } } void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)) { while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_)); if(!spi_rb || !spi_wb) { WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes; WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes; } else { WIZCHIP.IF.SPI._read_bytes = spi_rb; WIZCHIP.IF.SPI._write_bytes = spi_wb; } } int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) { uint8_t tmp = 0; uint8_t* ptmp[2] = {0,0}; switch(cwtype) { case CW_RESET_WIZCHIP: wizchip_sw_reset(); break; case CW_INIT_WIZCHIP: if(arg != 0) { ptmp[0] = (uint8_t*)arg; ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_; } return wizchip_init(ptmp[0], ptmp[1]); case CW_CLR_INTERRUPT: wizchip_clrinterrupt(*((intr_kind*)arg)); break; case CW_GET_INTERRUPT: *((intr_kind*)arg) = wizchip_getinterrupt(); break; case CW_SET_INTRMASK: wizchip_setinterruptmask(*((intr_kind*)arg)); break; case CW_GET_INTRMASK: *((intr_kind*)arg) = wizchip_getinterruptmask(); break; #if _WIZCHIP_ > 5100 case CW_SET_INTRTIME: setINTLEVEL(*(uint16_t*)arg); break; case CW_GET_INTRTIME: *(uint16_t*)arg = getINTLEVEL(); break; #endif case CW_GET_ID: ((uint8_t*)arg)[0] = WIZCHIP.id[0]; ((uint8_t*)arg)[1] = WIZCHIP.id[1]; ((uint8_t*)arg)[2] = WIZCHIP.id[2]; ((uint8_t*)arg)[3] = WIZCHIP.id[3]; ((uint8_t*)arg)[4] = WIZCHIP.id[4]; ((uint8_t*)arg)[5] = 0; break; #if _WIZCHIP_ == 5500 case CW_RESET_PHY: wizphy_reset(); break; case CW_SET_PHYCONF: wizphy_setphyconf((wiz_PhyConf*)arg); break; case CW_GET_PHYCONF: wizphy_getphyconf((wiz_PhyConf*)arg); break; case CW_GET_PHYSTATUS: break; case CW_SET_PHYPOWMODE: return wizphy_setphypmode(*(uint8_t*)arg); #endif case CW_GET_PHYPOWMODE: tmp = wizphy_getphypmode(); if((int8_t)tmp == -1) return -1; *(uint8_t*)arg = tmp; break; case CW_GET_PHYLINK: tmp = wizphy_getphylink(); if((int8_t)tmp == -1) return -1; *(uint8_t*)arg = tmp; break; default: return -1; } return 0; } int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) { switch(cntype) { case CN_SET_NETINFO: wizchip_setnetinfo((wiz_NetInfo*)arg); break; case CN_GET_NETINFO: wizchip_getnetinfo((wiz_NetInfo*)arg); break; case CN_SET_NETMODE: return wizchip_setnetmode(*(netmode_type*)arg); case CN_GET_NETMODE: *(netmode_type*)arg = wizchip_getnetmode(); break; case CN_SET_TIMEOUT: wizchip_settimeout((wiz_NetTimeout*)arg); break; case CN_GET_TIMEOUT: wizchip_gettimeout((wiz_NetTimeout*)arg); break; default: return -1; } return 0; } void wizchip_sw_reset(void) { uint8_t gw[4], sn[4], sip[4]; uint8_t mac[6]; getSHAR(mac); getGAR(gw); getSUBR(sn); getSIPR(sip); setMR(MR_RST); getMR(); // for delay setSHAR(mac); setGAR(gw); setSUBR(sn); setSIPR(sip); } int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize) { int8_t i; int8_t tmp = 0; wizchip_sw_reset(); if(txsize) { tmp = 0; for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) tmp += txsize[i]; if(tmp > 16) return -1; for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) setSn_TXBUF_SIZE(i, txsize[i]); } if(rxsize) { tmp = 0; for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) tmp += rxsize[i]; if(tmp > 16) return -1; for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) setSn_RXBUF_SIZE(i, rxsize[i]); } WIZCHIP_EXPORT(socket_reset)(); return 0; } void wizchip_clrinterrupt(intr_kind intr) { uint8_t ir = (uint8_t)intr; uint8_t sir = (uint8_t)((uint16_t)intr >> 8); #if _WIZCHIP_ < 5500 ir |= (1<<4); // IK_WOL #endif #if _WIZCHIP_ == 5200 ir |= (1 << 6); #endif #if _WIZCHIP_ < 5200 sir &= 0x0F; #endif #if _WIZCHIP_ == 5100 ir |= sir; setIR(ir); #else setIR(ir); setSIR(sir); #endif } intr_kind wizchip_getinterrupt(void) { uint8_t ir = 0; uint8_t sir = 0; uint16_t ret = 0; #if _WIZCHIP_ == 5100 ir = getIR(); sir = ir 0x0F; #else ir = getIR(); sir = getSIR(); #endif #if _WIZCHIP_ < 5500 ir &= ~(1<<4); // IK_WOL #endif #if _WIZCHIP_ == 5200 ir &= ~(1 << 6); #endif ret = sir; ret = (ret << 8) + ir; return (intr_kind)ret; } void wizchip_setinterruptmask(intr_kind intr) { uint8_t imr = (uint8_t)intr; uint8_t simr = (uint8_t)((uint16_t)intr >> 8); #if _WIZCHIP_ < 5500 imr &= ~(1<<4); // IK_WOL #endif #if _WIZCHIP_ == 5200 imr &= ~(1 << 6); #endif #if _WIZCHIP_ < 5200 simr &= 0x0F; #endif #if _WIZCHIP_ == 5100 imr |= simr; setIMR(imr); #else setIMR(imr); setSIMR(simr); #endif } intr_kind wizchip_getinterruptmask(void) { uint8_t imr = 0; uint8_t simr = 0; uint16_t ret = 0; #if _WIZCHIP_ == 5100 imr = getIMR(); simr = imr 0x0F; #else imr = getIMR(); simr = getSIMR(); #endif #if _WIZCHIP_ < 5500 imr &= ~(1<<4); // IK_WOL #endif #if _WIZCHIP_ == 5200 imr &= ~(1 << 6); // IK_DEST_UNREACH #endif ret = simr; ret = (ret << 8) + imr; return (intr_kind)ret; } int8_t wizphy_getphylink(void) { int8_t tmp; #if _WIZCHIP_ == 5200 if(getPHYSTATUS() & PHYSTATUS_LINK) tmp = PHY_LINK_ON; else tmp = PHY_LINK_OFF; #elif _WIZCHIP_ == 5500 if(getPHYCFGR() & PHYCFGR_LNK_ON) tmp = PHY_LINK_ON; else tmp = PHY_LINK_OFF; #else tmp = -1; #endif return tmp; } #if _WIZCHIP_ > 5100 int8_t wizphy_getphypmode(void) { int8_t tmp = 0; #if _WIZCHIP_ == 5200 if(getPHYSTATUS() & PHYSTATUS_POWERDOWN) tmp = PHY_POWER_DOWN; else tmp = PHY_POWER_NORM; #elif _WIZCHIP_ == 5500 if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN) tmp = PHY_POWER_DOWN; else tmp = PHY_POWER_NORM; #else tmp = -1; #endif return tmp; } #endif #if _WIZCHIP_ == 5500 void wizphy_reset(void) { uint8_t tmp = getPHYCFGR(); tmp &= PHYCFGR_RST; setPHYCFGR(tmp); tmp = getPHYCFGR(); tmp |= ~PHYCFGR_RST; setPHYCFGR(tmp); } void wizphy_setphyconf(wiz_PhyConf* phyconf) { uint8_t tmp = 0; if(phyconf->by == PHY_CONFBY_SW) tmp |= PHYCFGR_OPMD; else tmp &= ~PHYCFGR_OPMD; if(phyconf->mode == PHY_MODE_AUTONEGO) tmp |= PHYCFGR_OPMDC_ALLA; else { if(phyconf->duplex == PHY_DUPLEX_FULL) { if(phyconf->speed == PHY_SPEED_100) tmp |= PHYCFGR_OPMDC_100F; else tmp |= PHYCFGR_OPMDC_10F; } else { if(phyconf->speed == PHY_SPEED_100) tmp |= PHYCFGR_OPMDC_100H; else tmp |= PHYCFGR_OPMDC_10H; } } setPHYCFGR(tmp); wizphy_reset(); } void wizphy_getphyconf(wiz_PhyConf* phyconf) { uint8_t tmp = 0; tmp = getPHYCFGR(); phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW; switch(tmp & PHYCFGR_OPMDC_ALLA) { case PHYCFGR_OPMDC_ALLA: case PHYCFGR_OPMDC_100FA: phyconf->mode = PHY_MODE_AUTONEGO; break; default: phyconf->mode = PHY_MODE_MANUAL; break; } switch(tmp & PHYCFGR_OPMDC_ALLA) { case PHYCFGR_OPMDC_100FA: case PHYCFGR_OPMDC_100F: case PHYCFGR_OPMDC_100H: phyconf->speed = PHY_SPEED_100; break; default: phyconf->speed = PHY_SPEED_10; break; } switch(tmp & PHYCFGR_OPMDC_ALLA) { case PHYCFGR_OPMDC_100FA: case PHYCFGR_OPMDC_100F: case PHYCFGR_OPMDC_10F: phyconf->duplex = PHY_DUPLEX_FULL; break; default: phyconf->duplex = PHY_DUPLEX_HALF; break; } } void wizphy_getphystat(wiz_PhyConf* phyconf) { uint8_t tmp = getPHYCFGR(); phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10; } int8_t wizphy_setphypmode(uint8_t pmode) { uint8_t tmp = 0; tmp = getPHYCFGR(); if((tmp & PHYCFGR_OPMD)== 0) return -1; tmp &= ~PHYCFGR_OPMDC_ALLA; if( pmode == PHY_POWER_DOWN) tmp |= PHYCFGR_OPMDC_PDOWN; else tmp |= PHYCFGR_OPMDC_ALLA; setPHYCFGR(tmp); wizphy_reset(); tmp = getPHYCFGR(); if( pmode == PHY_POWER_DOWN) { if(tmp & PHYCFGR_OPMDC_PDOWN) return 0; } else { if(tmp & PHYCFGR_OPMDC_ALLA) return 0; } return -1; } #endif void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) { setSHAR(pnetinfo->mac); setGAR(pnetinfo->gw); setSUBR(pnetinfo->sn); setSIPR(pnetinfo->ip); #if _WIZCHIP_ == 5200 // for W5200 ARP errata _SUBN_[0] = pnetinfo->sn[0]; _SUBN_[1] = pnetinfo->sn[1]; _SUBN_[2] = pnetinfo->sn[2]; _SUBN_[3] = pnetinfo->sn[3]; #endif _DNS_[0] = pnetinfo->dns[0]; _DNS_[1] = pnetinfo->dns[1]; _DNS_[2] = pnetinfo->dns[2]; _DNS_[3] = pnetinfo->dns[3]; _DHCP_ = pnetinfo->dhcp; } void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) { getSHAR(pnetinfo->mac); getGAR(pnetinfo->gw); getSUBR(pnetinfo->sn); getSIPR(pnetinfo->ip); #if _WIZCHIP_ == 5200 // for W5200 ARP errata pnetinfo->sn[0] = _SUBN_[0]; pnetinfo->sn[1] = _SUBN_[1]; pnetinfo->sn[2] = _SUBN_[2]; pnetinfo->sn[3] = _SUBN_[3]; #endif pnetinfo->dns[0]= _DNS_[0]; pnetinfo->dns[1]= _DNS_[1]; pnetinfo->dns[2]= _DNS_[2]; pnetinfo->dns[3]= _DNS_[3]; pnetinfo->dhcp = _DHCP_; } #if _WIZCHIP_ == 5200 // for W5200 ARP errata uint8_t *wizchip_getsubn(void) { return _SUBN_; } #endif int8_t wizchip_setnetmode(netmode_type netmode) { uint8_t tmp = 0; #if _WIZCHIP_ != 5500 if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1; #else if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1; #endif tmp = getMR(); tmp |= (uint8_t)netmode; setMR(tmp); return 0; } netmode_type wizchip_getnetmode(void) { return (netmode_type) getMR(); } void wizchip_settimeout(wiz_NetTimeout* nettime) { setRCR(nettime->retry_cnt); setRTR(nettime->time_100us); } void wizchip_gettimeout(wiz_NetTimeout* nettime) { nettime->retry_cnt = getRCR(); nettime->time_100us = getRTR(); } micropython-1.12/drivers/wiznet5k/ethernet/wizchip_conf.h000066400000000000000000000510231357706137100237320ustar00rootroot00000000000000//***************************************************************************** // //! \file wizchip_conf.h //! \brief WIZCHIP Config Header File. //! \version 1.0.0 //! \date 2013/10/21 //! \par Revision history //! <2013/10/21> 1st Release //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** /** * @defgroup extra_functions 2. WIZnet Extra Functions * * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions. * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n * */ #ifndef _WIZCHIP_CONF_H_ #define _WIZCHIP_CONF_H_ #include /** * @brief Select WIZCHIP. * @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n * ex> #define \_WIZCHIP_ 5500 */ #ifndef _WIZCHIP_ #define _WIZCHIP_ 5200 // 5100, 5200, 5500 #endif #define _WIZCHIP_IO_MODE_NONE_ 0x0000 #define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */ #define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */ //#define _WIZCHIP_IO_MODE_IIC_ 0x0400 //#define _WIZCHIP_IO_MODE_SDIO_ 0x0800 // Add to // #define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */ #define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */ #define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/ #define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/ #if (_WIZCHIP_ == 5100) #define _WIZCHIP_ID_ "W5100\0" /** * @brief Define interface mode. * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ */ // #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_ // #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ #elif (_WIZCHIP_ == 5200) #define _WIZCHIP_ID_ "W5200\0" /** * @brief Define interface mode. * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ */ // #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ #include "w5200/w5200.h" #elif (_WIZCHIP_ == 5500) #define _WIZCHIP_ID_ "W5500\0" /** * @brief Define interface mode. \n * @todo Should select interface mode as chip. * - @ref \_WIZCHIP_IO_MODE_SPI_ \n * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n * - @ref \_WIZCHIP_IO_MODE_BUS_ \n * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n * - Others will be defined in future. \n\n * ex> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ * */ //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_ #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_ #include "w5500/w5500.h" #else #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!" #endif #ifndef _WIZCHIP_IO_MODE_ #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!" #endif /** * @brief Define I/O base address when BUS IF mode. * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_, * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n * ex> #define \_WIZCHIP_IO_BASE_ 0x00008000 */ #define _WIZCHIP_IO_BASE_ 0x00000000 // #if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS #ifndef _WIZCHIP_IO_BASE_ #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map." #endif #endif #if _WIZCHIP_ > 5100 #define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP #else #define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP #endif /******************************************************** * WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC. *********************************************************/ /** * @ingroup DATA_TYPE * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200 */ typedef struct __WIZCHIP { uint16_t if_mode; ///< host interface mode uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on. /** * The set of critical section callback func. */ struct _CRIS { void (*_enter) (void); ///< crtical section enter void (*_exit) (void); ///< critial section exit }CRIS; /** * The set of @ref\_WIZCHIP_ select control callback func. */ struct _CS { void (*_select) (void); ///< @ref \_WIZCHIP_ selected void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected }CS; /** * The set of interface IO callback func. */ union _IF { /** * For BUS interface IO */ struct { uint8_t (*_read_byte) (uint32_t AddrSel); void (*_write_byte) (uint32_t AddrSel, uint8_t wb); }BUS; /** * For SPI interface IO */ struct { void (*_read_bytes) (uint8_t *buf, uint32_t len); void (*_write_bytes) (const uint8_t *buf, uint32_t len); }SPI; // To be added // }IF; }_WIZCHIP; extern _WIZCHIP WIZCHIP; /** * @ingroup DATA_TYPE * WIZCHIP control type enumration used in @ref ctlwizchip(). */ typedef enum { CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t. CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP CW_CLR_INTERRUPT, ///< Clears interrupt CW_SET_INTRMASK, ///< Masks interrupt CW_GET_INTRMASK, ///< Get interrupt mask CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt. CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt. CW_GET_ID, ///< Gets WIZCHIP name. #if _WIZCHIP_ == 5500 CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000 CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000 CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000 CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000 CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000 #endif CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal CW_GET_PHYLINK ///< Get PHY Link status }ctlwizchip_type; /** * @ingroup DATA_TYPE * Network control type enumration used in @ref ctlnetwork(). */ typedef enum { CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode CN_SET_TIMEOUT, ///< Set network timeout as retry count and time. CN_GET_TIMEOUT, ///< Get network timeout as retry count and time. }ctlnetwork_type; /** * @ingroup DATA_TYPE * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK * and CW_GET_INTRMASK is used in @ref ctlnetwork(). * It can be used with OR operation. */ typedef enum { #if _WIZCHIP_ > 5200 IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500. #endif IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected #if _WIZCHIP_ != 5200 IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200 #endif IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt #if _WIZCHIP_ > 5100 IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100 IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100 IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100 IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100 #endif #if _WIZCHIP_ > 5100 IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt #else IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt #endif }intr_kind; #define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin #define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register #define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting. #define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation #define PHY_SPEED_10 0 ///< Link Speed 10 #define PHY_SPEED_100 1 ///< Link Speed 100 #define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex #define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex #define PHY_LINK_OFF 0 ///< Link Off #define PHY_LINK_ON 1 ///< Link On #define PHY_POWER_NORM 0 ///< PHY power normal mode #define PHY_POWER_DOWN 1 ///< PHY power down mode #if _WIZCHIP_ == 5500 /** * @ingroup DATA_TYPE * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500, * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n * Valid only in W5500. */ typedef struct wiz_PhyConf_t { uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100 uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF }wiz_PhyConf; #endif /** * @ingroup DATA_TYPE * It used in setting dhcp_mode of @ref wiz_NetInfo. */ typedef enum { NETINFO_STATIC = 1, ///< Static IP configuration by manually. NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever }dhcp_mode; /** * @ingroup DATA_TYPE * Network Information for WIZCHIP */ typedef struct wiz_NetInfo_t { uint8_t mac[6]; ///< Source Mac Address uint8_t ip[4]; ///< Source IP Address uint8_t sn[4]; ///< Subnet Mask uint8_t gw[4]; ///< Gateway IP Address uint8_t dns[4]; ///< DNS server IP Address dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP }wiz_NetInfo; /** * @ingroup DATA_TYPE * Network mode */ typedef enum { #if _WIZCHIP_ == 5500 NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500 #endif NM_WAKEONLAN = (1<<5), ///< Wake On Lan NM_PINGBLOCK = (1<<4), ///< Block ping-request NM_PPPOE = (1<<3), ///< PPPoE mode }netmode_type; /** * @ingroup DATA_TYPE * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation. */ typedef struct wiz_NetTimeout_t { uint8_t retry_cnt; ///< retry count uint16_t time_100us; ///< time unit 100us }wiz_NetTimeout; /** *@brief Registers call back function for critical section of I/O functions such as *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF. *@param cris_en : callback function for critical section enter. *@param cris_ex : callback function for critical section exit. *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions. *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called. */ void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)); /** *@brief Registers call back function for WIZCHIP select & deselect. *@param cs_sel : callback function for WIZCHIP select *@param cs_desel : callback fucntion for WIZCHIP deselect *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions. *@note If you do not describe or register, null function is called. */ void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)); /** *@brief Registers call back function for bus interface. *@param bus_rb : callback function to read byte data using system bus *@param bus_wb : callback function to write byte data using system bus *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function *or register your functions. *@note If you do not describe or register, null function is called. */ void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)); /** *@brief Registers call back function for SPI interface. *@param spi_rb : callback function to read byte usig SPI *@param spi_wb : callback function to write byte usig SPI *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function *or register your functions. *@note If you do not describe or register, null function is called. */ void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)); /** * @ingroup extra_functions * @brief Controls to the WIZCHIP. * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto), * controls interrupt & mask and so on. * @param cwtype : Decides to the control type * @param arg : arg type is dependent on cwtype. * @return 0 : Success \n * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP */ int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg); /** * @ingroup extra_functions * @brief Controls to network. * @details Controls to network environment, mode, timeout and so on. * @param cntype : Input. Decides to the control type * @param arg : Inout. arg type is dependent on cntype. * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n * 0 : Success */ int8_t ctlnetwork(ctlnetwork_type cntype, void* arg); /* * The following functions are implemented for internal use. * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork(). */ /** * @ingroup extra_functions * @brief Reset WIZCHIP by softly. */ void wizchip_sw_reset(void); /** * @ingroup extra_functions * @brief Initializes WIZCHIP with socket buffer size * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB. * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB. * @return 0 : succcess \n * -1 : fail. Invalid buffer size */ int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize); /** * @ingroup extra_functions * @brief Clear Interrupt of WIZCHIP. * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. */ void wizchip_clrinterrupt(intr_kind intr); /** * @ingroup extra_functions * @brief Get Interrupt of WIZCHIP. * @return @ref intr_kind value operated OR. It can type-cast to uint16_t. */ intr_kind wizchip_getinterrupt(void); /** * @ingroup extra_functions * @brief Mask or Unmask Interrupt of WIZCHIP. * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. */ void wizchip_setinterruptmask(intr_kind intr); /** * @ingroup extra_functions * @brief Get Interrupt mask of WIZCHIP. * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t. */ intr_kind wizchip_getinterruptmask(void); #if _WIZCHIP_ > 5100 int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100 int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100 #endif #if _WIZCHIP_ == 5500 void wizphy_reset(void); ///< Reset phy. Vailid only in W5500 /** * @ingroup extra_functions * @brief Set the phy information for WIZCHIP without power mode * @param phyconf : @ref wiz_PhyConf */ void wizphy_setphyconf(wiz_PhyConf* phyconf); /** * @ingroup extra_functions * @brief Get phy configuration information. * @param phyconf : @ref wiz_PhyConf */ void wizphy_getphyconf(wiz_PhyConf* phyconf); /** * @ingroup extra_functions * @brief Get phy status. * @param phyconf : @ref wiz_PhyConf */ void wizphy_getphystat(wiz_PhyConf* phyconf); /** * @ingroup extra_functions * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200 * @param pmode Settig value of power down mode. */ int8_t wizphy_setphypmode(uint8_t pmode); #endif /** * @ingroup extra_functions * @brief Set the network information for WIZCHIP * @param pnetinfo : @ref wizNetInfo */ void wizchip_setnetinfo(wiz_NetInfo* pnetinfo); /** * @ingroup extra_functions * @brief Get the network information for WIZCHIP * @param pnetinfo : @ref wizNetInfo */ void wizchip_getnetinfo(wiz_NetInfo* pnetinfo); #if _WIZCHIP_ == 5200 // for W5200 ARP errata uint8_t *wizchip_getsubn(void); #endif /** * @ingroup extra_functions * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc. * @param pnetinfo Value of network mode. Refer to @ref netmode_type. */ int8_t wizchip_setnetmode(netmode_type netmode); /** * @ingroup extra_functions * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc. * @return Value of network mode. Refer to @ref netmode_type. */ netmode_type wizchip_getnetmode(void); /** * @ingroup extra_functions * @brief Set retry time value(@ref RTR) and retry count(@ref RCR). * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. */ void wizchip_settimeout(wiz_NetTimeout* nettime); /** * @ingroup extra_functions * @brief Get retry time value(@ref RTR) and retry count(@ref RCR). * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. */ void wizchip_gettimeout(wiz_NetTimeout* nettime); #endif // _WIZCHIP_CONF_H_ micropython-1.12/drivers/wiznet5k/internet/000077500000000000000000000000001357706137100211105ustar00rootroot00000000000000micropython-1.12/drivers/wiznet5k/internet/dhcp/000077500000000000000000000000001357706137100220265ustar00rootroot00000000000000micropython-1.12/drivers/wiznet5k/internet/dhcp/dhcp.c000066400000000000000000000702061357706137100231150ustar00rootroot00000000000000//***************************************************************************** // //! \file dhcp.c //! \brief DHCP APIs implement file. //! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. //! \version 1.1.0 //! \date 2013/11/18 //! \par Revision history //! <2013/11/18> 1st Release //! <2012/12/20> V1.1.0 //! 1. Optimize code //! 2. Add reg_dhcp_cbfunc() //! 3. Add DHCP_stop() //! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run() //! 5. Don't care system endian //! 6. Add comments //! <2012/12/26> V1.1.1 //! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization //! \author Eric Jung & MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //#include "Ethernet/socket.h" //#include "Internet/DHCP/dhcp.h" #include "../../Ethernet/socket.h" #include "dhcp.h" /* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ #ifdef _DHCP_DEBUG_ #include #endif /* DHCP state machine. */ #define STATE_DHCP_INIT 0 ///< Initialize #define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER #define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK #define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased #define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP #define STATE_DHCP_RELEASE 5 ///< No use #define STATE_DHCP_STOP 6 ///< Stop processing DHCP #define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG #define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG /* DHCP message OP code */ #define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG #define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG /* DHCP message type */ #define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG #define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG #define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG #define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG #define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG #define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG #define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use #define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use #define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG #define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG #define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG #define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG #define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG #define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time #define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG #define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG /* * @brief DHCP option and value (cf. RFC1533) */ enum { padOption = 0, subnetMask = 1, timerOffset = 2, routersOnSubnet = 3, timeServer = 4, nameServer = 5, dns = 6, logServer = 7, cookieServer = 8, lprServer = 9, impressServer = 10, resourceLocationServer = 11, hostName = 12, bootFileSize = 13, meritDumpFile = 14, domainName = 15, swapServer = 16, rootPath = 17, extentionsPath = 18, IPforwarding = 19, nonLocalSourceRouting = 20, policyFilter = 21, maxDgramReasmSize = 22, defaultIPTTL = 23, pathMTUagingTimeout = 24, pathMTUplateauTable = 25, ifMTU = 26, allSubnetsLocal = 27, broadcastAddr = 28, performMaskDiscovery = 29, maskSupplier = 30, performRouterDiscovery = 31, routerSolicitationAddr = 32, staticRoute = 33, trailerEncapsulation = 34, arpCacheTimeout = 35, ethernetEncapsulation = 36, tcpDefaultTTL = 37, tcpKeepaliveInterval = 38, tcpKeepaliveGarbage = 39, nisDomainName = 40, nisServers = 41, ntpServers = 42, vendorSpecificInfo = 43, netBIOSnameServer = 44, netBIOSdgramDistServer = 45, netBIOSnodeType = 46, netBIOSscope = 47, xFontServer = 48, xDisplayManager = 49, dhcpRequestedIPaddr = 50, dhcpIPaddrLeaseTime = 51, dhcpOptionOverload = 52, dhcpMessageType = 53, dhcpServerIdentifier = 54, dhcpParamRequest = 55, dhcpMsg = 56, dhcpMaxMsgSize = 57, dhcpT1value = 58, dhcpT2value = 59, dhcpClassIdentifier = 60, dhcpClientIdentifier = 61, endOption = 255 }; /* * @brief DHCP message format */ typedef struct { uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB uint8_t hlen; ///< @ref DHCP_HLENETHERNET uint8_t hops; ///< @ref DHCP_HOPS uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction. uint16_t secs; ///< @ref DHCP_SECS uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server uint8_t siaddr[4]; ///< No use uint8_t giaddr[4]; ///< No use uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero uint8_t sname[64]; ///< No use uint8_t file[128]; ///< No use uint8_t OPT[OPT_SIZE]; ///< Option } RIP_MSG; uint8_t DHCP_SOCKET; // Socket number for DHCP uint8_t DHCP_SIP[4]; // DHCP Server IP address // Network information from DHCP Server uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state int8_t dhcp_retry_count = 0; uint32_t dhcp_lease_time = INFINITE_LEASETIME; volatile uint32_t dhcp_tick_1s = 0; // unit 1 second uint32_t dhcp_tick_next = DHCP_WAIT_TIME ; uint32_t DHCP_XID; // Any number RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing uint8_t HOST_NAME[] = DCHP_HOST_NAME; uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address. /* The default callback function */ void default_ip_assign(void); void default_ip_update(void); void default_ip_conflict(void); /* Callback handler */ void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */ void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */ void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */ void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); /* send DISCOVER message to DHCP server */ void send_DHCP_DISCOVER(void); /* send REQEUST message to DHCP server */ void send_DHCP_REQUEST(void); /* send DECLINE message to DHCP server */ void send_DHCP_DECLINE(void); /* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ int8_t check_DHCP_leasedIP(void); /* check the timeout in DHCP process */ uint8_t check_DHCP_timeout(void); /* Intialize to timeout process. */ void reset_DHCP_timeout(void); /* Parse message as OFFER and ACK and NACK from DHCP server.*/ int8_t parseDHCPCMSG(void); /* The default handler of ip assign first */ void default_ip_assign(void) { setSIPR(DHCP_allocated_ip); setSUBR(DHCP_allocated_sn); setGAR (DHCP_allocated_gw); } /* The default handler of ip changed */ void default_ip_update(void) { /* WIZchip Software Reset */ setMR(MR_RST); getMR(); // for delay default_ip_assign(); setSHAR(DHCP_CHADDR); } /* The default handler of ip changed */ void default_ip_conflict(void) { // WIZchip Software Reset setMR(MR_RST); getMR(); // for delay setSHAR(DHCP_CHADDR); } /* register the call back func. */ void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)) { dhcp_ip_assign = default_ip_assign; dhcp_ip_update = default_ip_update; dhcp_ip_conflict = default_ip_conflict; if(ip_assign) dhcp_ip_assign = ip_assign; if(ip_update) dhcp_ip_update = ip_update; if(ip_conflict) dhcp_ip_conflict = ip_conflict; } /* make the common DHCP message */ void makeDHCPMSG(void) { uint8_t bk_mac[6]; uint8_t* ptmp; uint8_t i; getSHAR(bk_mac); pDHCPMSG->op = DHCP_BOOTREQUEST; pDHCPMSG->htype = DHCP_HTYPE10MB; pDHCPMSG->hlen = DHCP_HLENETHERNET; pDHCPMSG->hops = DHCP_HOPS; ptmp = (uint8_t*)(&pDHCPMSG->xid); *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24); *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16); *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8); *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0); pDHCPMSG->secs = DHCP_SECS; ptmp = (uint8_t*)(&pDHCPMSG->flags); *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8); *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0); pDHCPMSG->ciaddr[0] = 0; pDHCPMSG->ciaddr[1] = 0; pDHCPMSG->ciaddr[2] = 0; pDHCPMSG->ciaddr[3] = 0; pDHCPMSG->yiaddr[0] = 0; pDHCPMSG->yiaddr[1] = 0; pDHCPMSG->yiaddr[2] = 0; pDHCPMSG->yiaddr[3] = 0; pDHCPMSG->siaddr[0] = 0; pDHCPMSG->siaddr[1] = 0; pDHCPMSG->siaddr[2] = 0; pDHCPMSG->siaddr[3] = 0; pDHCPMSG->giaddr[0] = 0; pDHCPMSG->giaddr[1] = 0; pDHCPMSG->giaddr[2] = 0; pDHCPMSG->giaddr[3] = 0; pDHCPMSG->chaddr[0] = DHCP_CHADDR[0]; pDHCPMSG->chaddr[1] = DHCP_CHADDR[1]; pDHCPMSG->chaddr[2] = DHCP_CHADDR[2]; pDHCPMSG->chaddr[3] = DHCP_CHADDR[3]; pDHCPMSG->chaddr[4] = DHCP_CHADDR[4]; pDHCPMSG->chaddr[5] = DHCP_CHADDR[5]; for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0; for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0; for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0; // MAGIC_COOKIE pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24); pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16); pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8); pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0; } /* SEND DHCP DISCOVER */ void send_DHCP_DISCOVER(void) { uint16_t i; uint8_t ip[4]; uint16_t k = 0; makeDHCPMSG(); k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() // Option Request Param pDHCPMSG->OPT[k++] = dhcpMessageType; pDHCPMSG->OPT[k++] = 0x01; pDHCPMSG->OPT[k++] = DHCP_DISCOVER; // Client identifier pDHCPMSG->OPT[k++] = dhcpClientIdentifier; pDHCPMSG->OPT[k++] = 0x07; pDHCPMSG->OPT[k++] = 0x01; pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; // host name pDHCPMSG->OPT[k++] = hostName; pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname for(i = 0 ; HOST_NAME[i] != 0; i++) pDHCPMSG->OPT[k++] = HOST_NAME[i]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname pDHCPMSG->OPT[k++] = dhcpParamRequest; pDHCPMSG->OPT[k++] = 0x06; // length of request pDHCPMSG->OPT[k++] = subnetMask; pDHCPMSG->OPT[k++] = routersOnSubnet; pDHCPMSG->OPT[k++] = dns; pDHCPMSG->OPT[k++] = domainName; pDHCPMSG->OPT[k++] = dhcpT1value; pDHCPMSG->OPT[k++] = dhcpT2value; pDHCPMSG->OPT[k++] = endOption; for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; // send broadcasting packet ip[0] = 255; ip[1] = 255; ip[2] = 255; ip[3] = 255; #ifdef _DHCP_DEBUG_ printf("> Send DHCP_DISCOVER\r\n"); #endif sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); } /* SEND DHCP REQUEST */ void send_DHCP_REQUEST(void) { int i; uint8_t ip[4]; uint16_t k = 0; makeDHCPMSG(); if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) { *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0]; pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1]; pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2]; pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3]; ip[0] = DHCP_SIP[0]; ip[1] = DHCP_SIP[1]; ip[2] = DHCP_SIP[2]; ip[3] = DHCP_SIP[3]; } else { ip[0] = 255; ip[1] = 255; ip[2] = 255; ip[3] = 255; } k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() // Option Request Param. pDHCPMSG->OPT[k++] = dhcpMessageType; pDHCPMSG->OPT[k++] = 0x01; pDHCPMSG->OPT[k++] = DHCP_REQUEST; pDHCPMSG->OPT[k++] = dhcpClientIdentifier; pDHCPMSG->OPT[k++] = 0x07; pDHCPMSG->OPT[k++] = 0x01; pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE) { pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; pDHCPMSG->OPT[k++] = 0x04; pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; pDHCPMSG->OPT[k++] = dhcpServerIdentifier; pDHCPMSG->OPT[k++] = 0x04; pDHCPMSG->OPT[k++] = DHCP_SIP[0]; pDHCPMSG->OPT[k++] = DHCP_SIP[1]; pDHCPMSG->OPT[k++] = DHCP_SIP[2]; pDHCPMSG->OPT[k++] = DHCP_SIP[3]; } // host name pDHCPMSG->OPT[k++] = hostName; pDHCPMSG->OPT[k++] = 0; // length of hostname for(i = 0 ; HOST_NAME[i] != 0; i++) pDHCPMSG->OPT[k++] = HOST_NAME[i]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname pDHCPMSG->OPT[k++] = dhcpParamRequest; pDHCPMSG->OPT[k++] = 0x08; pDHCPMSG->OPT[k++] = subnetMask; pDHCPMSG->OPT[k++] = routersOnSubnet; pDHCPMSG->OPT[k++] = dns; pDHCPMSG->OPT[k++] = domainName; pDHCPMSG->OPT[k++] = dhcpT1value; pDHCPMSG->OPT[k++] = dhcpT2value; pDHCPMSG->OPT[k++] = performRouterDiscovery; pDHCPMSG->OPT[k++] = staticRoute; pDHCPMSG->OPT[k++] = endOption; for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; #ifdef _DHCP_DEBUG_ printf("> Send DHCP_REQUEST\r\n"); #endif sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); } /* SEND DHCP DHCPDECLINE */ void send_DHCP_DECLINE(void) { int i; uint8_t ip[4]; uint16_t k = 0; makeDHCPMSG(); k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); // Option Request Param. pDHCPMSG->OPT[k++] = dhcpMessageType; pDHCPMSG->OPT[k++] = 0x01; pDHCPMSG->OPT[k++] = DHCP_DECLINE; pDHCPMSG->OPT[k++] = dhcpClientIdentifier; pDHCPMSG->OPT[k++] = 0x07; pDHCPMSG->OPT[k++] = 0x01; pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; pDHCPMSG->OPT[k++] = 0x04; pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; pDHCPMSG->OPT[k++] = dhcpServerIdentifier; pDHCPMSG->OPT[k++] = 0x04; pDHCPMSG->OPT[k++] = DHCP_SIP[0]; pDHCPMSG->OPT[k++] = DHCP_SIP[1]; pDHCPMSG->OPT[k++] = DHCP_SIP[2]; pDHCPMSG->OPT[k++] = DHCP_SIP[3]; pDHCPMSG->OPT[k++] = endOption; for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; //send broadcasting packet ip[0] = 0xFF; ip[1] = 0xFF; ip[2] = 0xFF; ip[3] = 0xFF; #ifdef _DHCP_DEBUG_ printf("\r\n> Send DHCP_DECLINE\r\n"); #endif sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); } /* PARSE REPLY pDHCPMSG */ int8_t parseDHCPMSG(void) { uint8_t svr_addr[6]; uint16_t svr_port; uint16_t len; uint8_t * p; uint8_t * e; uint8_t type; uint8_t opt_len; if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) { len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); #ifdef _DHCP_DEBUG_ printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len); #endif } else return 0; if (svr_port == DHCP_SERVER_PORT) { // compare mac address if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) || (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) || (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) ) return 0; type = 0; p = (uint8_t *)(&pDHCPMSG->op); p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt) e = p + (len - 240); while ( p < e ) { switch ( *p ) { case endOption : p = e; // for break while(p < e) break; case padOption : p++; break; case dhcpMessageType : p++; p++; type = *p++; break; case subnetMask : p++; p++; DHCP_allocated_sn[0] = *p++; DHCP_allocated_sn[1] = *p++; DHCP_allocated_sn[2] = *p++; DHCP_allocated_sn[3] = *p++; break; case routersOnSubnet : p++; opt_len = *p++; DHCP_allocated_gw[0] = *p++; DHCP_allocated_gw[1] = *p++; DHCP_allocated_gw[2] = *p++; DHCP_allocated_gw[3] = *p++; p = p + (opt_len - 4); break; case dns : p++; opt_len = *p++; DHCP_allocated_dns[0] = *p++; DHCP_allocated_dns[1] = *p++; DHCP_allocated_dns[2] = *p++; DHCP_allocated_dns[3] = *p++; p = p + (opt_len - 4); break; case dhcpIPaddrLeaseTime : p++; opt_len = *p++; dhcp_lease_time = *p++; dhcp_lease_time = (dhcp_lease_time << 8) + *p++; dhcp_lease_time = (dhcp_lease_time << 8) + *p++; dhcp_lease_time = (dhcp_lease_time << 8) + *p++; #ifdef _DHCP_DEBUG_ dhcp_lease_time = 10; #endif break; case dhcpServerIdentifier : p++; opt_len = *p++; DHCP_SIP[0] = *p++; DHCP_SIP[1] = *p++; DHCP_SIP[2] = *p++; DHCP_SIP[3] = *p++; break; default : p++; opt_len = *p++; p += opt_len; break; } // switch } // while } // if return type; } uint8_t DHCP_run(void) { uint8_t type; uint8_t ret; if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED; if(getSn_SR(DHCP_SOCKET) != SOCK_UDP) socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); ret = DHCP_RUNNING; type = parseDHCPMSG(); switch ( dhcp_state ) { case STATE_DHCP_INIT : DHCP_allocated_ip[0] = 0; DHCP_allocated_ip[1] = 0; DHCP_allocated_ip[2] = 0; DHCP_allocated_ip[3] = 0; send_DHCP_DISCOVER(); dhcp_state = STATE_DHCP_DISCOVER; break; case STATE_DHCP_DISCOVER : if (type == DHCP_OFFER){ #ifdef _DHCP_DEBUG_ printf("> Receive DHCP_OFFER\r\n"); #endif DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0]; DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1]; DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2]; DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3]; send_DHCP_REQUEST(); dhcp_state = STATE_DHCP_REQUEST; } else ret = check_DHCP_timeout(); break; case STATE_DHCP_REQUEST : if (type == DHCP_ACK) { #ifdef _DHCP_DEBUG_ printf("> Receive DHCP_ACK\r\n"); #endif if (check_DHCP_leasedIP()) { // Network info assignment from DHCP dhcp_ip_assign(); reset_DHCP_timeout(); dhcp_state = STATE_DHCP_LEASED; } else { // IP address conflict occurred reset_DHCP_timeout(); dhcp_ip_conflict(); dhcp_state = STATE_DHCP_INIT; } } else if (type == DHCP_NAK) { #ifdef _DHCP_DEBUG_ printf("> Receive DHCP_NACK\r\n"); #endif reset_DHCP_timeout(); dhcp_state = STATE_DHCP_DISCOVER; } else ret = check_DHCP_timeout(); break; case STATE_DHCP_LEASED : ret = DHCP_IP_LEASED; if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) { #ifdef _DHCP_DEBUG_ printf("> Maintains the IP address \r\n"); #endif type = 0; OLD_allocated_ip[0] = DHCP_allocated_ip[0]; OLD_allocated_ip[1] = DHCP_allocated_ip[1]; OLD_allocated_ip[2] = DHCP_allocated_ip[2]; OLD_allocated_ip[3] = DHCP_allocated_ip[3]; DHCP_XID++; send_DHCP_REQUEST(); reset_DHCP_timeout(); dhcp_state = STATE_DHCP_REREQUEST; } break; case STATE_DHCP_REREQUEST : ret = DHCP_IP_LEASED; if (type == DHCP_ACK) { dhcp_retry_count = 0; if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] || OLD_allocated_ip[1] != DHCP_allocated_ip[1] || OLD_allocated_ip[2] != DHCP_allocated_ip[2] || OLD_allocated_ip[3] != DHCP_allocated_ip[3]) { ret = DHCP_IP_CHANGED; dhcp_ip_update(); #ifdef _DHCP_DEBUG_ printf(">IP changed.\r\n"); #endif } #ifdef _DHCP_DEBUG_ else printf(">IP is continued.\r\n"); #endif reset_DHCP_timeout(); dhcp_state = STATE_DHCP_LEASED; } else if (type == DHCP_NAK) { #ifdef _DHCP_DEBUG_ printf("> Receive DHCP_NACK, Failed to maintain ip\r\n"); #endif reset_DHCP_timeout(); dhcp_state = STATE_DHCP_DISCOVER; } else ret = check_DHCP_timeout(); break; default : break; } return ret; } void DHCP_stop(void) { close(DHCP_SOCKET); dhcp_state = STATE_DHCP_STOP; } uint8_t check_DHCP_timeout(void) { uint8_t ret = DHCP_RUNNING; if (dhcp_retry_count < MAX_DHCP_RETRY) { if (dhcp_tick_next < dhcp_tick_1s) { switch ( dhcp_state ) { case STATE_DHCP_DISCOVER : // printf("<> state : STATE_DHCP_DISCOVER\r\n"); send_DHCP_DISCOVER(); break; case STATE_DHCP_REQUEST : // printf("<> state : STATE_DHCP_REQUEST\r\n"); send_DHCP_REQUEST(); break; case STATE_DHCP_REREQUEST : // printf("<> state : STATE_DHCP_REREQUEST\r\n"); send_DHCP_REQUEST(); break; default : break; } dhcp_tick_1s = 0; dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME; dhcp_retry_count++; } } else { // timeout occurred switch(dhcp_state) { case STATE_DHCP_DISCOVER: dhcp_state = STATE_DHCP_INIT; ret = DHCP_FAILED; break; case STATE_DHCP_REQUEST: case STATE_DHCP_REREQUEST: send_DHCP_DISCOVER(); dhcp_state = STATE_DHCP_DISCOVER; break; default : break; } reset_DHCP_timeout(); } return ret; } int8_t check_DHCP_leasedIP(void) { uint8_t tmp; int32_t ret; //WIZchip RCR value changed for ARP Timeout count control tmp = getRCR(); setRCR(0x03); // IP conflict detection : ARP request - ARP reply // Broadcasting ARP Request for check the IP conflict using UDP sendto() function ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); // RCR value restore setRCR(tmp); if(ret == SOCKERR_TIMEOUT) { // UDP send Timeout occurred : allocated IP address is unique, DHCP Success #ifdef _DHCP_DEBUG_ printf("\r\n> Check leased IP - OK\r\n"); #endif return 1; } else { // Received ARP reply or etc : IP address conflict occur, DHCP Failed send_DHCP_DECLINE(); ret = dhcp_tick_1s; while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message; return 0; } } void DHCP_init(uint8_t s, uint8_t * buf) { uint8_t zeroip[4] = {0,0,0,0}; getSHAR(DHCP_CHADDR); if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00) { // assign temporary mac address, you should be set SHAR before call this function. DHCP_CHADDR[0] = 0x00; DHCP_CHADDR[1] = 0x08; DHCP_CHADDR[2] = 0xdc; DHCP_CHADDR[3] = 0x00; DHCP_CHADDR[4] = 0x00; DHCP_CHADDR[5] = 0x00; setSHAR(DHCP_CHADDR); } DHCP_SOCKET = s; // SOCK_DHCP pDHCPMSG = (RIP_MSG*)buf; DHCP_XID = 0x12345678; // WIZchip Netinfo Clear setSIPR(zeroip); setSIPR(zeroip); setGAR(zeroip); reset_DHCP_timeout(); dhcp_state = STATE_DHCP_INIT; } /* Rset the DHCP timeout count and retry count. */ void reset_DHCP_timeout(void) { dhcp_tick_1s = 0; dhcp_tick_next = DHCP_WAIT_TIME; dhcp_retry_count = 0; } void DHCP_time_handler(void) { dhcp_tick_1s++; } void getIPfromDHCP(uint8_t* ip) { ip[0] = DHCP_allocated_ip[0]; ip[1] = DHCP_allocated_ip[1]; ip[2] = DHCP_allocated_ip[2]; ip[3] = DHCP_allocated_ip[3]; } void getGWfromDHCP(uint8_t* ip) { ip[0] =DHCP_allocated_gw[0]; ip[1] =DHCP_allocated_gw[1]; ip[2] =DHCP_allocated_gw[2]; ip[3] =DHCP_allocated_gw[3]; } void getSNfromDHCP(uint8_t* ip) { ip[0] = DHCP_allocated_sn[0]; ip[1] = DHCP_allocated_sn[1]; ip[2] = DHCP_allocated_sn[2]; ip[3] = DHCP_allocated_sn[3]; } void getDNSfromDHCP(uint8_t* ip) { ip[0] = DHCP_allocated_dns[0]; ip[1] = DHCP_allocated_dns[1]; ip[2] = DHCP_allocated_dns[2]; ip[3] = DHCP_allocated_dns[3]; } uint32_t getDHCPLeasetime(void) { return dhcp_lease_time; } micropython-1.12/drivers/wiznet5k/internet/dhcp/dhcp.h000066400000000000000000000121521357706137100231160ustar00rootroot00000000000000//***************************************************************************** // //! \file dhcp.h //! \brief DHCP APIs Header file. //! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. //! \version 1.1.0 //! \date 2013/11/18 //! \par Revision history //! <2013/11/18> 1st Release //! <2012/12/20> V1.1.0 //! 1. Move unreferenced DEFINE to dhcp.c //! <2012/12/26> V1.1.1 //! \author Eric Jung & MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef _DHCP_H_ #define _DHCP_H_ /* * @brief * @details If you want to display debug & processing message, Define _DHCP_DEBUG_ * @note If defined, it depends on */ //#define _DHCP_DEBUG_ /* Retry to processing DHCP */ #define MAX_DHCP_RETRY 2 ///< Maximum retry count #define DHCP_WAIT_TIME 10 ///< Wait Time 10s /* UDP port numbers for DHCP */ #define DHCP_SERVER_PORT 67 ///< DHCP server port number #define DHCP_CLIENT_PORT 68 ///< DHCP client port number #define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number #define DCHP_HOST_NAME "WIZnet\0" /* * @brief return value of @ref DHCP_run() */ enum { DHCP_FAILED = 0, ///< Processing Fail DHCP_RUNNING, ///< Processing DHCP protocol DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign) DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update) DHCP_IP_LEASED, ///< Stand by DHCP_STOPPED ///< Stop processing DHCP protocol }; /* * @brief DHCP client initialization (outside of the main loop) * @param s - socket number * @param buf - buffer for processing DHCP message */ void DHCP_init(uint8_t s, uint8_t * buf); /* * @brief DHCP 1s Tick Timer handler * @note SHOULD BE register to your system 1s Tick timer handler */ void DHCP_time_handler(void); /* * @brief Register call back function * @param ip_assign - callback func when IP is assigned from DHCP server first * @param ip_update - callback func when IP is changed * @prarm ip_conflict - callback func when the assigned IP is conflict with others. */ void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); /* * @brief DHCP client in the main loop * @return The value is as the follow \n * @ref DHCP_FAILED \n * @ref DHCP_RUNNING \n * @ref DHCP_IP_ASSIGN \n * @ref DHCP_IP_CHANGED \n * @ref DHCP_IP_LEASED \n * @ref DHCP_STOPPED \n * * @note This function is always called by you main task. */ uint8_t DHCP_run(void); /* * @brief Stop DHCP processing * @note If you want to restart. call DHCP_init() and DHCP_run() */ void DHCP_stop(void); /* Get Network information assigned from DHCP server */ /* * @brief Get IP address * @param ip - IP address to be returned */ void getIPfromDHCP(uint8_t* ip); /* * @brief Get Gateway address * @param ip - Gateway address to be returned */ void getGWfromDHCP(uint8_t* ip); /* * @brief Get Subnet mask value * @param ip - Subnet mask to be returned */ void getSNfromDHCP(uint8_t* ip); /* * @brief Get DNS address * @param ip - DNS address to be returned */ void getDNSfromDHCP(uint8_t* ip); /* * @brief Get the leased time by DHCP sever * @return unit 1s */ uint32_t getDHCPLeasetime(void); #endif /* _DHCP_H_ */ micropython-1.12/drivers/wiznet5k/internet/dns/000077500000000000000000000000001357706137100216745ustar00rootroot00000000000000micropython-1.12/drivers/wiznet5k/internet/dns/dns.c000066400000000000000000000344111357706137100226270ustar00rootroot00000000000000//***************************************************************************** // //! \file dns.c //! \brief DNS APIs Implement file. //! \details Send DNS query & Receive DNS reponse. \n //! It depends on stdlib.h & string.h in ansi-c library //! \version 1.1.0 //! \date 2013/11/18 //! \par Revision history //! <2013/10/21> 1st Release //! <2013/12/20> V1.1.0 //! 1. Remove secondary DNS server in DNS_run //! If 1st DNS_run failed, call DNS_run with 2nd DNS again //! 2. DNS_timerHandler -> DNS_time_handler //! 3. Remove the unused define //! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c //! <2013/12/20> V1.1.0 //! //! \author Eric Jung & MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #include #include //#include "Ethernet/socket.h" //#include "Internet/DNS/dns.h" #include "../../ethernet/socket.h" #include "dns.h" #ifdef _DNS_DEBUG_ #include #endif #define INITRTT 2000L /* Initial smoothed response time */ #define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */ #define TYPE_A 1 /* Host address */ #define TYPE_NS 2 /* Name server */ #define TYPE_MD 3 /* Mail destination (obsolete) */ #define TYPE_MF 4 /* Mail forwarder (obsolete) */ #define TYPE_CNAME 5 /* Canonical name */ #define TYPE_SOA 6 /* Start of Authority */ #define TYPE_MB 7 /* Mailbox name (experimental) */ #define TYPE_MG 8 /* Mail group member (experimental) */ #define TYPE_MR 9 /* Mail rename name (experimental) */ #define TYPE_NULL 10 /* Null (experimental) */ #define TYPE_WKS 11 /* Well-known sockets */ #define TYPE_PTR 12 /* Pointer record */ #define TYPE_HINFO 13 /* Host information */ #define TYPE_MINFO 14 /* Mailbox information (experimental)*/ #define TYPE_MX 15 /* Mail exchanger */ #define TYPE_TXT 16 /* Text strings */ #define TYPE_ANY 255 /* Matches any type */ #define CLASS_IN 1 /* The ARPA Internet */ /* Round trip timing parameters */ #define AGAIN 8 /* Average RTT gain = 1/8 */ #define LAGAIN 3 /* Log2(AGAIN) */ #define DGAIN 4 /* Mean deviation gain = 1/4 */ #define LDGAIN 2 /* log2(DGAIN) */ /* Header for all domain messages */ struct dhdr { uint16_t id; /* Identification */ uint8_t qr; /* Query/Response */ #define QUERY 0 #define RESPONSE 1 uint8_t opcode; #define IQUERY 1 uint8_t aa; /* Authoratative answer */ uint8_t tc; /* Truncation */ uint8_t rd; /* Recursion desired */ uint8_t ra; /* Recursion available */ uint8_t rcode; /* Response code */ #define NO_ERROR 0 #define FORMAT_ERROR 1 #define SERVER_FAIL 2 #define NAME_ERROR 3 #define NOT_IMPL 4 #define REFUSED 5 uint16_t qdcount; /* Question count */ uint16_t ancount; /* Answer count */ uint16_t nscount; /* Authority (name server) count */ uint16_t arcount; /* Additional record count */ }; uint8_t* pDNSMSG; // DNS message buffer uint8_t DNS_SOCKET; // SOCKET number for DNS uint16_t DNS_MSGID; // DNS message ID extern uint32_t HAL_GetTick(void); uint32_t hal_sys_tick; /* converts uint16_t from network buffer to a host byte order integer. */ uint16_t get16(uint8_t * s) { uint16_t i; i = *s++ << 8; i = i + *s; return i; } /* copies uint16_t to the network buffer with network byte order. */ uint8_t * put16(uint8_t * s, uint16_t i) { *s++ = i >> 8; *s++ = i; return s; } /* * CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM * * Description : This function converts a compressed domain name to the human-readable form * Arguments : msg - is a pointer to the reply message * compressed - is a pointer to the domain name in reply message. * buf - is a pointer to the buffer for the human-readable form name. * len - is the MAX. size of buffer. * Returns : the length of compressed message */ int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len) { uint16_t slen; /* Length of current segment */ uint8_t * cp; int clen = 0; /* Total length of compressed name */ int indirect = 0; /* Set if indirection encountered */ int nseg = 0; /* Total number of segments in name */ cp = compressed; for (;;) { slen = *cp++; /* Length of this segment */ if (!indirect) clen++; if ((slen & 0xc0) == 0xc0) { if (!indirect) clen++; indirect = 1; /* Follow indirection */ cp = &msg[((slen & 0x3f)<<8) + *cp]; slen = *cp++; } if (slen == 0) /* zero length == all done */ break; len -= slen + 1; if (len < 0) return -1; if (!indirect) clen += slen; while (slen-- != 0) *buf++ = (char)*cp++; *buf++ = '.'; nseg++; } if (nseg == 0) { /* Root name; represent as single dot */ *buf++ = '.'; len--; } *buf++ = '\0'; len--; return clen; /* Length of compressed message */ } /* * PARSE QUESTION SECTION * * Description : This function parses the question record of the reply message. * Arguments : msg - is a pointer to the reply message * cp - is a pointer to the question record. * Returns : a pointer the to next record. */ uint8_t * dns_question(uint8_t * msg, uint8_t * cp) { int len; char name[MAXCNAME]; len = parse_name(msg, cp, name, MAXCNAME); if (len == -1) return 0; cp += len; cp += 2; /* type */ cp += 2; /* class */ return cp; } /* * PARSE ANSER SECTION * * Description : This function parses the answer record of the reply message. * Arguments : msg - is a pointer to the reply message * cp - is a pointer to the answer record. * Returns : a pointer the to next record. */ uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns) { int len, type; char name[MAXCNAME]; len = parse_name(msg, cp, name, MAXCNAME); if (len == -1) return 0; cp += len; type = get16(cp); cp += 2; /* type */ cp += 2; /* class */ cp += 4; /* ttl */ cp += 2; /* len */ switch (type) { case TYPE_A: /* Just read the address directly into the structure */ ip_from_dns[0] = *cp++; ip_from_dns[1] = *cp++; ip_from_dns[2] = *cp++; ip_from_dns[3] = *cp++; break; case TYPE_CNAME: case TYPE_MB: case TYPE_MG: case TYPE_MR: case TYPE_NS: case TYPE_PTR: /* These types all consist of a single domain name */ /* convert it to ASCII format */ len = parse_name(msg, cp, name, MAXCNAME); if (len == -1) return 0; cp += len; break; case TYPE_HINFO: len = *cp++; cp += len; len = *cp++; cp += len; break; case TYPE_MX: cp += 2; /* Get domain name of exchanger */ len = parse_name(msg, cp, name, MAXCNAME); if (len == -1) return 0; cp += len; break; case TYPE_SOA: /* Get domain name of name server */ len = parse_name(msg, cp, name, MAXCNAME); if (len == -1) return 0; cp += len; /* Get domain name of responsible person */ len = parse_name(msg, cp, name, MAXCNAME); if (len == -1) return 0; cp += len; cp += 4; cp += 4; cp += 4; cp += 4; cp += 4; break; case TYPE_TXT: /* Just stash */ break; default: /* Ignore */ break; } return cp; } /* * PARSE THE DNS REPLY * * Description : This function parses the reply message from DNS server. * Arguments : dhdr - is a pointer to the header for DNS message * buf - is a pointer to the reply message. * len - is the size of reply message. * Returns : -1 - Domain name length is too big * 0 - Fail (Timeout or parse error) * 1 - Success, */ int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns) { uint16_t tmp; uint16_t i; uint8_t * msg; uint8_t * cp; msg = pbuf; memset(pdhdr, 0, sizeof(*pdhdr)); pdhdr->id = get16(&msg[0]); tmp = get16(&msg[2]); if (tmp & 0x8000) pdhdr->qr = 1; pdhdr->opcode = (tmp >> 11) & 0xf; if (tmp & 0x0400) pdhdr->aa = 1; if (tmp & 0x0200) pdhdr->tc = 1; if (tmp & 0x0100) pdhdr->rd = 1; if (tmp & 0x0080) pdhdr->ra = 1; pdhdr->rcode = tmp & 0xf; pdhdr->qdcount = get16(&msg[4]); pdhdr->ancount = get16(&msg[6]); pdhdr->nscount = get16(&msg[8]); pdhdr->arcount = get16(&msg[10]); /* Now parse the variable length sections */ cp = &msg[12]; /* Question section */ for (i = 0; i < pdhdr->qdcount; i++) { cp = dns_question(msg, cp); if(!cp) { #ifdef _DNS_DEBUG_ printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); #endif return -1; } } /* Answer section */ for (i = 0; i < pdhdr->ancount; i++) { cp = dns_answer(msg, cp, ip_from_dns); if(!cp) { #ifdef _DNS_DEBUG_ printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); #endif return -1; } } /* Name server (authority) section */ for (i = 0; i < pdhdr->nscount; i++) { ; } /* Additional section */ for (i = 0; i < pdhdr->arcount; i++) { ; } if(pdhdr->rcode == 0) return 1; // No error else return 0; } /* * MAKE DNS QUERY MESSAGE * * Description : This function makes DNS query message. * Arguments : op - Recursion desired * name - is a pointer to the domain name. * buf - is a pointer to the buffer for DNS message. * len - is the MAX. size of buffer. * Returns : the pointer to the DNS message. */ int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len) { uint8_t *cp; char *cp1; char sname[MAXCNAME]; char *dname; uint16_t p; uint16_t dlen; cp = buf; DNS_MSGID++; cp = put16(cp, DNS_MSGID); p = (op << 11) | 0x0100; /* Recursion desired */ cp = put16(cp, p); cp = put16(cp, 1); cp = put16(cp, 0); cp = put16(cp, 0); cp = put16(cp, 0); strcpy(sname, name); dname = sname; dlen = strlen(dname); for (;;) { /* Look for next dot */ cp1 = strchr(dname, '.'); if (cp1 != NULL) len = cp1 - dname; /* More to come */ else len = dlen; /* Last component */ *cp++ = len; /* Write length of component */ if (len == 0) break; /* Copy component up to (but not including) dot */ memcpy(cp, dname, len); cp += len; if (cp1 == NULL) { *cp++ = 0; /* Last one; write null and finish */ break; } dname += len+1; dlen -= len+1; } cp = put16(cp, 0x0001); /* type */ cp = put16(cp, 0x0001); /* class */ return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf))); } /* * CHECK DNS TIMEOUT * * Description : This function check the DNS timeout * Arguments : None. * Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur * Note : timeout : retry count and timer both over. */ int8_t check_DNS_timeout(void) { static uint8_t retry_count; uint32_t tick = HAL_GetTick(); if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000) { hal_sys_tick = tick; if(retry_count >= MAX_DNS_RETRY) { retry_count = 0; return -1; // timeout occurred } retry_count++; return 0; // timer over, but no timeout } return 1; // no timer over, no timeout occur } /* DNS CLIENT INIT */ void DNS_init(uint8_t s, uint8_t * buf) { DNS_SOCKET = s; // SOCK_DNS pDNSMSG = buf; // User's shared buffer DNS_MSGID = DNS_MSG_ID; } /* DNS CLIENT RUN */ int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns) { int8_t ret; struct dhdr dhp; uint8_t ip[4]; uint16_t len, port; int8_t ret_check_timeout; hal_sys_tick = HAL_GetTick(); // Socket open WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0); #ifdef _DNS_DEBUG_ printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); #endif len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE); WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); while (1) { if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0) { if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE; len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port); #ifdef _DNS_DEBUG_ printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len); #endif ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns); break; } // Check Timeout ret_check_timeout = check_DNS_timeout(); if (ret_check_timeout < 0) { #ifdef _DNS_DEBUG_ printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); #endif return 0; // timeout occurred } else if (ret_check_timeout == 0) { #ifdef _DNS_DEBUG_ printf("> DNS Timeout\r\n"); #endif WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); } } WIZCHIP_EXPORT(close)(DNS_SOCKET); // Return value // 0 > : failed / 1 - success return ret; } micropython-1.12/drivers/wiznet5k/internet/dns/dns.h000066400000000000000000000076611357706137100226430ustar00rootroot00000000000000//***************************************************************************** // //! \file dns.h //! \brief DNS APIs Header file. //! \details Send DNS query & Receive DNS reponse. //! \version 1.1.0 //! \date 2013/11/18 //! \par Revision history //! <2013/10/21> 1st Release //! <2013/12/20> V1.1.0 //! 1. Remove secondary DNS server in DNS_run //! If 1st DNS_run failed, call DNS_run with 2nd DNS again //! 2. DNS_timerHandler -> DNS_time_handler //! 3. Move the no reference define to dns.c //! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c //! <2013/12/20> V1.1.0 //! //! \author Eric Jung & MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef _DNS_H_ #define _DNS_H_ #include /* * @brief Define it for Debug & Monitor DNS processing. * @note If defined, it depends on */ //#define _DNS_DEBUG_ #define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */ /* * @brief Maximum length of your queried Domain name * @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1) * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack. */ #define MAX_DOMAIN_NAME 32 // for example "www.google.com" #define MAX_DNS_RETRY 2 ///< Requery Count #define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s. #define IPPORT_DOMAIN 53 ///< DNS server port number #define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number /* * @brief DNS process initialize * @param s : Socket number for DNS * @param buf : Buffer for DNS message */ void DNS_init(uint8_t s, uint8_t * buf); /* * @brief DNS process * @details Send DNS query and receive DNS response * @param dns_ip : DNS server ip address * @param name : Domain name to be queried * @param ip_from_dns : IP address from DNS server * @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n * 0 : failed (Timeout or Parse error)\n * 1 : success * @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME */ int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns); #endif /* _DNS_H_ */ micropython-1.12/examples/000077500000000000000000000000001357706137100156405ustar00rootroot00000000000000micropython-1.12/examples/SDdatalogger/000077500000000000000000000000001357706137100202005ustar00rootroot00000000000000micropython-1.12/examples/SDdatalogger/README.md000066400000000000000000000007441357706137100214640ustar00rootroot00000000000000This is a SDdatalogger, to log data from the accelerometer to the SD-card. It also functions as card reader, so you can easily get the data on your PC. To run, put the boot.py, cardreader.py and datalogger.py files on either the flash or the SD-card of your pyboard. Upon reset, the datalogger script is run and logs the data. If you press the user button after reset and hold it until the orange LED goes out, you enter the cardreader mode and the filesystem is mounted to your PC. micropython-1.12/examples/SDdatalogger/boot.py000066400000000000000000000016671357706137100215270ustar00rootroot00000000000000# boot.py -- runs on boot-up # Let's you choose which script to run. # > To run 'datalogger.py': # * press reset and do nothing else # > To run 'cardreader.py': # * press reset # * press user switch and hold until orange LED goes out import pyb pyb.LED(3).on() # indicate we are waiting for switch press pyb.delay(2000) # wait for user to maybe press the switch switch_value = pyb.Switch()() # sample the switch at end of delay pyb.LED(3).off() # indicate that we finished waiting for the switch pyb.LED(4).on() # indicate that we are selecting the mode if switch_value: pyb.usb_mode('VCP+MSC') pyb.main('cardreader.py') # if switch was pressed, run this else: pyb.usb_mode('VCP+HID') pyb.main('datalogger.py') # if switch wasn't pressed, run this pyb.LED(4).off() # indicate that we finished selecting the mode micropython-1.12/examples/SDdatalogger/cardreader.py000066400000000000000000000001261357706137100226450ustar00rootroot00000000000000# cardread.py # This is called when the user enters cardreader mode. It does nothing. micropython-1.12/examples/SDdatalogger/datalogger.py000066400000000000000000000022201357706137100226570ustar00rootroot00000000000000# datalogger.py # Logs the data from the acceleromter to a file on the SD-card import pyb # creating objects accel = pyb.Accel() blue = pyb.LED(4) switch = pyb.Switch() # loop while True: # wait for interrupt # this reduces power consumption while waiting for switch press pyb.wfi() # start if switch is pressed if switch(): pyb.delay(200) # delay avoids detection of multiple presses blue.on() # blue LED indicates file open log = open('/sd/log.csv', 'w') # open file on SD (SD: '/sd/', flash: '/flash/) # until switch is pressed again while not switch(): t = pyb.millis() # get time x, y, z = accel.filtered_xyz() # get acceleration data log.write('{},{},{},{}\n'.format(t,x,y,z)) # write data to file # end after switch is pressed again log.close() # close file blue.off() # blue LED indicates file closed pyb.delay(200) # delay avoids detection of multiple presses micropython-1.12/examples/accel_i2c.py000066400000000000000000000017141357706137100200210ustar00rootroot00000000000000# This is an example on how to access accelerometer on # PyBoard directly using I2C bus. As such, it's more # intended to be an I2C example, rather than accelerometer # example. For the latter, using pyb.Accel class is # much easier. from machine import Pin from machine import I2C import time # Accelerometer needs to be powered on first. Even # though signal is called "AVDD", and there's separate # "DVDD", without AVDD, it won't event talk on I2C bus. accel_pwr = Pin("MMA_AVDD") accel_pwr.value(1) i2c = I2C(1, baudrate=100000) addrs = i2c.scan() print("Scanning devices:", [hex(x) for x in addrs]) if 0x4c not in addrs: print("Accelerometer is not detected") ACCEL_ADDR = 0x4c ACCEL_AXIS_X_REG = 0 ACCEL_MODE_REG = 7 # Now activate measurements i2c.mem_write(b"\x01", ACCEL_ADDR, ACCEL_MODE_REG) print("Try to move accelerometer and watch the values") while True: val = i2c.mem_read(1, ACCEL_ADDR, ACCEL_AXIS_X_REG) print(val[0]) time.sleep(1) micropython-1.12/examples/accellog.py000066400000000000000000000017441357706137100177710ustar00rootroot00000000000000# log the accelerometer values to a .csv-file on the SD-card import pyb accel = pyb.Accel() # create object of accelerometer blue = pyb.LED(4) # create object of blue LED log = open('/sd/log.csv', 'w') # open file to write data - /sd/ is the SD-card, /flash/ the internal memory blue.on() # turn on blue LED for i in range(100): # do 100 times (if the board is connected via USB, you can't write longer because the PC tries to open the filesystem which messes up your file.) t = pyb.millis() # get time since reset x, y, z = accel.filtered_xyz() # get acceleration data log.write('{},{},{},{}\n'.format(t,x,y,z)) # write data to file log.close() # close file blue.off() # turn off LED micropython-1.12/examples/asmled.py000066400000000000000000000032151357706137100174600ustar00rootroot00000000000000# flash LED #1 using inline assembler # this version is overly verbose and uses word stores @micropython.asm_thumb def flash_led(r0): movw(r1, (stm.GPIOA + stm.GPIO_BSRRL) & 0xffff) movt(r1, ((stm.GPIOA + stm.GPIO_BSRRL) >> 16) & 0x7fff) movw(r2, 1 << 13) movt(r2, 0) movw(r3, 0) movt(r3, 1 << 13) b(loop_entry) label(loop1) # turn LED on str(r2, [r1, 0]) # delay for a bit movw(r4, 5599900 & 0xffff) movt(r4, (5599900 >> 16) & 0xffff) label(delay_on) sub(r4, r4, 1) cmp(r4, 0) bgt(delay_on) # turn LED off str(r3, [r1, 0]) # delay for a bit movw(r4, 5599900 & 0xffff) movt(r4, (5599900 >> 16) & 0xffff) label(delay_off) sub(r4, r4, 1) cmp(r4, 0) bgt(delay_off) # loop r0 times sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) # flash LED #2 using inline assembler # this version uses half-word sortes, and the convenience assembler operation 'movwt' @micropython.asm_thumb def flash_led_v2(r0): # get the GPIOA address in r1 movwt(r1, stm.GPIOA) # get the bit mask for PA14 (the pin LED #2 is on) movw(r2, 1 << 14) b(loop_entry) label(loop1) # turn LED on strh(r2, [r1, stm.GPIO_BSRRL]) # delay for a bit movwt(r4, 5599900) label(delay_on) sub(r4, r4, 1) cmp(r4, 0) bgt(delay_on) # turn LED off strh(r2, [r1, stm.GPIO_BSRRH]) # delay for a bit movwt(r4, 5599900) label(delay_off) sub(r4, r4, 1) cmp(r4, 0) bgt(delay_off) # loop r0 times sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) flash_led(5) flash_led_v2(5) micropython-1.12/examples/asmsum.py000066400000000000000000000014741357706137100175250ustar00rootroot00000000000000@micropython.asm_thumb def asm_sum_words(r0, r1): # r0 = len # r1 = ptr # r2 = sum # r3 = dummy mov(r2, 0) b(loop_entry) label(loop1) ldr(r3, [r1, 0]) add(r2, r2, r3) add(r1, r1, 4) sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) mov(r0, r2) @micropython.asm_thumb def asm_sum_bytes(r0, r1): # r0 = len # r1 = ptr # r2 = sum # r3 = dummy mov(r2, 0) b(loop_entry) label(loop1) ldrb(r3, [r1, 0]) add(r2, r2, r3) add(r1, r1, 1) sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) mov(r0, r2) import array b = array.array('l', (100, 200, 300, 400)) n = asm_sum_words(len(b), b) print(b, n) b = array.array('b', (10, 20, 30, 40, 50, 60, 70, 80)) n = asm_sum_bytes(len(b), b) print(b, n) micropython-1.12/examples/bluetooth/000077500000000000000000000000001357706137100176455ustar00rootroot00000000000000micropython-1.12/examples/bluetooth/ble_advertising.py000066400000000000000000000051211357706137100233570ustar00rootroot00000000000000# Helpers for generating BLE advertising payloads. from micropython import const import struct import bluetooth # Advertising payloads are repeated packets of the following form: # 1 byte data length (N + 1) # 1 byte type (see constants below) # N bytes type-specific data _ADV_TYPE_FLAGS = const(0x01) _ADV_TYPE_NAME = const(0x09) _ADV_TYPE_UUID16_COMPLETE = const(0x3) _ADV_TYPE_UUID32_COMPLETE = const(0x5) _ADV_TYPE_UUID128_COMPLETE = const(0x7) _ADV_TYPE_UUID16_MORE = const(0x2) _ADV_TYPE_UUID32_MORE = const(0x4) _ADV_TYPE_UUID128_MORE = const(0x6) _ADV_TYPE_APPEARANCE = const(0x19) # Generate a payload to be passed to gap_advertise(adv_data=...). def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): payload = bytearray() def _append(adv_type, value): nonlocal payload payload += struct.pack('BB', len(value) + 1, adv_type) + value _append(_ADV_TYPE_FLAGS, struct.pack('B', (0x01 if limited_disc else 0x02) + (0x00 if br_edr else 0x04))) if name: _append(_ADV_TYPE_NAME, name) if services: for uuid in services: b = bytes(uuid) if len(b) == 2: _append(_ADV_TYPE_UUID16_COMPLETE, b) elif len(b) == 4: _append(_ADV_TYPE_UUID32_COMPLETE, b) elif len(b) == 16: _append(_ADV_TYPE_UUID128_COMPLETE, b) # See org.bluetooth.characteristic.gap.appearance.xml _append(_ADV_TYPE_APPEARANCE, struct.pack(' #include #include #include "py/compile.h" #include "py/runtime.h" #include "py/gc.h" #include "py/stackctrl.h" static char heap[16384]; mp_obj_t execute_from_str(const char *str) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr src_name = 1/*MP_QSTR_*/; mp_lexer_t *lex = mp_lexer_new_from_str_len(src_name, str, strlen(str), false); mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_obj_t module_fun = mp_compile(&pt, src_name, false); mp_call_function_0(module_fun); nlr_pop(); return 0; } else { // uncaught exception return (mp_obj_t)nlr.ret_val; } } int main() { // Initialized stack limit mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); // Initialize heap gc_init(heap, heap + sizeof(heap)); // Initialize interpreter mp_init(); const char str[] = "print('Hello world of easy embedding!')"; if (execute_from_str(str)) { printf("Error\n"); } } uint mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } void nlr_jump_fail(void *val) { printf("FATAL: uncaught NLR %p\n", val); exit(1); } micropython-1.12/examples/embedding/mpconfigport.h000066400000000000000000000000421357706137100224320ustar00rootroot00000000000000#include "mpconfigport_minimal.h" micropython-1.12/examples/embedding/mpconfigport_minimal.h000066400000000000000000000117521357706137100241520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // options to control how MicroPython is built #define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (0) #define MICROPY_STACK_CHECK (0) #define MICROPY_COMP_CONST (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_READER_POSIX (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (1) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_WARNINGS (0) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_STREAMS_NON_BLOCK (0) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #define MICROPY_CAN_OVERRIDE_BUILTINS (0) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_PY_BUILTINS_BYTEARRAY (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) #define MICROPY_PY_BUILTINS_COMPILE (0) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_SLICE (0) #define MICROPY_PY_BUILTINS_STR_UNICODE (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_BUILTINS_MIN_MAX (0) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (0) #define MICROPY_PY_GC (0) #define MICROPY_PY_GC_COLLECT_RETVAL (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_EXIT (0) #define MICROPY_PY_SYS_PLATFORM "linux" #define MICROPY_PY_SYS_MAXSIZE (0) #define MICROPY_PY_SYS_STDFILES (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_UCTYPES (0) #define MICROPY_PY_UZLIB (0) #define MICROPY_PY_UJSON (0) #define MICROPY_PY_URE (0) #define MICROPY_PY_UHEAPQ (0) #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_UBINASCII (0) extern const struct _mp_obj_module_t mp_module_os; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \ #define MICROPY_PORT_ROOT_POINTERS \ ////////////////////////////////////////// // Do not change anything beyond this line ////////////////////////////////////////// // Define to 1 to use undertested inefficient GC helper implementation // (if more efficient arch-specific one is not available). #ifndef MICROPY_GCREGS_SETJMP #ifdef __mips__ #define MICROPY_GCREGS_SETJMP (1) #else #define MICROPY_GCREGS_SETJMP (0) #endif #endif // type definitions for the specific machine #ifdef __LP64__ typedef long mp_int_t; // must be pointer size typedef unsigned long mp_uint_t; // must be pointer size #else // These are definitions for machines where sizeof(int) == sizeof(void*), // regardless for actual size. typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size #endif // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; #else typedef long mp_off_t; #endif // We need to provide a declaration/definition of alloca() #ifdef __FreeBSD__ #include #else #include #endif micropython-1.12/examples/hwapi/000077500000000000000000000000001357706137100167505ustar00rootroot00000000000000micropython-1.12/examples/hwapi/README.md000066400000000000000000000132501357706137100202300ustar00rootroot00000000000000This directory shows the best practices for using MicroPython hardware API (`machine` module). `machine` module strives to provide consistent API across various boards, with the aim to enable writing portable applications, which would work from a board to board, from a system to another systems. This is inherently a hard problem, because hardware is different from one board type to another, and even from examplar of board to another. For example, if your app requires an external LED, one user may connect it to one GPIO pin, while another user may find it much more convinient to use another pin. This of course applies to relays, buzzers, sensors, etc. With complications above in mind, it's still possible to write portable applications by using "low[est] denominator" subset of hardware API and following simple rules outlined below. The applications won't be able to rely on advanced hardware capabilities of a particular board and will be limited to generic capabilities, but it's still possible to write many useful applications in such a way, with the obvious benefit of "write once - run everywhere" approach (only configuration for a particular board is required). The key to this approach is splitting your application into (at least) 2 parts: * main application logic * hardware configuration The key point is that hardware configuration should be a separate file (module in Python terms). A good name would be `hwconfig.py`, and that's how we'll call it from now on. Another key point is that main application should never instantiate (construct) hardware objects directly. Instead, they should be defined in `hwconfig.py`, and main application should import and reference hardware objects via this module. The simplest application of this idea would look like: `hwconfig.py`: from machine import Pin LED = Pin("A3", Pin.OUT) `app.py`: from hwconfig import * import utime while True: LED.value(1) utime.sleep_ms(500) LED.value(0) utime.sleep_ms(500) To deploy this application to a particular board, a user will need: 1. Edit `hwconfig.py` to adjust Pin and other hardware peripheral parameters and locations. 2. Actually deploy `hwconfig.py` and `app.py` to a board (e.g. copy to board's filesystem, or build new firmware with these modules frozen into it). Note that there's no need to edit the main application code! (Which may be complex, while `hwconfig.py` should usually remain short enough, and focused solely on hardware configuration). An obvious improvement to this approach is the following. There're few well-known boards which run MicroPython, and most of them include an onboard LED. So, to help users of these boards to do configuration quickly (that's especially important for novice users, for who may be stumped by the need to reach out to a board reference to find LED pin assignments), `hwconfig.py` your application ships may include commented out sections with working configurations for different boards. The step 1 above then will be: 1. Look thru `hwconfig.py` to find a section which either exactly matches your board, or the closest to it. Uncomment, and if any adjustments required, apply them. It's important to keep in mind that adjustments may be always required, and that there may be users whose configuration doesn't match any of the available. So, always include a section or instructions for them. Consider for example that even on a supported board, user may want to blink not an on-board LED, but the one they connected externally. MicroPython's Hardware API offers portability not just among "supported" boards, but to any board at all, so make sure users can enjoy it. There's next step of improvement to make. While having one `hwconfig.py` with many sections would work for smaller projects with few hardware objects, it may become more cumbersome to maintain both on programmer's and user's sides for larger projects. Then instead of single `hwconfig.py` file, you can provide few "template" ones for well-known boards: * `hwconfig_pyboard.py` * `hwconfig_wipy.py` * `hwconfig_esp8266.py` * etc. Then step 1 above will be: 1. Look thru available `hwconfig_*.py` files and find one which matches your board the best, then rename to `hwconfig.py` and make adjustments, if any. Again, please keep in mind that there may be users whose hardware will be completely unlike you heard of. Give them some helpful hints too, perhaps provide `hwconfig_custom.py` with some instructions. That's where we stop with improvements to the "separate file for hardware configuration" idea, as it is already pretty flexible and viable. An application in this directory shows it in practice, using slightly less trivial example than just a blinking LED: `soft_pwm.py` implements a software PWM (pulse width modulation) to produce an LED fade-in/fade-out effect - without any dependence on hardware PWM availability. Note that improvements to board configuration handling may continue further. For example, one may invent a "configuration manager" helper module which will try to detect current board (among well-known ones), and load appropriate `hwconfig_*.py` - this assumes that a user would lazily deploy them all (or that application will be automatically installed, e.g. using MicroPython's `upip` package manager). The key point in this case remains the same as elaborated above - always assume there can, and will be a custom configuration, and it should be well supported. So, any automatic detection should be overridable by a user, and instructions how to do so are among the most important you may provide for your application. By following these best practices, you will use MicroPython at its full potential, and let users enjoy it too. Good luck! micropython-1.12/examples/hwapi/button_led.py000066400000000000000000000002641357706137100214630ustar00rootroot00000000000000import utime from hwconfig import LED, BUTTON # Light LED when (and while) a BUTTON is pressed while 1: LED.value(BUTTON.value()) # Don't burn CPU utime.sleep_ms(10) micropython-1.12/examples/hwapi/button_reaction.py000066400000000000000000000007201357706137100225200ustar00rootroot00000000000000import utime import machine from hwconfig import LED, BUTTON # machine.time_pulse_us() function demo print("""\ Let's play an interesting game: You click button as fast as you can, and I tell you how slow you are. Ready? Cliiiiick! """) while 1: delay = machine.time_pulse_us(BUTTON, 1, 10*1000*1000) if delay < 0: print("Well, you're *really* slow") else: print("You are as slow as %d microseconds!" % delay) utime.sleep_ms(10) micropython-1.12/examples/hwapi/hwconfig_console.py000066400000000000000000000005621357706137100226530ustar00rootroot00000000000000# This is hwconfig for "emulation" for cases when there's no real hardware. # It just prints information to console. class LEDClass: def __init__(self, id): self.id = "LED(%d):" % id def value(self, v): print(self.id, v) def on(self): self.value(1) def off(self): self.value(0) LED = LEDClass(1) LED2 = LEDClass(12) micropython-1.12/examples/hwapi/hwconfig_dragonboard410c.py000066400000000000000000000014121357706137100240560ustar00rootroot00000000000000from machine import Pin, Signal # 96Boards/Qualcomm DragonBoard 410c # # By default, on-board LEDs are controlled by kernel LED driver. # To make corresponding pins be available as normal GPIO, # corresponding driver needs to be unbound first (as root): # echo -n "soc:leds" >/sys/class/leds/apq8016-sbc:green:user1/device/driver/unbind # Note that application also either should be run as root, or # /sys/class/gpio ownership needs to be changed. # Likewise, onboard buttons are controlled by gpio_keys driver. # To release corresponding GPIOs: # echo -n "gpio_keys" >/sys/class/input/input1/device/driver/unbind # User LED 1 on gpio21 LED = Signal(Pin(21, Pin.OUT)) # User LED 2 on gpio120 LED2 = Signal(Pin(120, Pin.OUT)) # Button S3 on gpio107 BUTTON = Pin(107, Pin.IN) micropython-1.12/examples/hwapi/hwconfig_esp8266_esp12.py000066400000000000000000000002301357706137100233300ustar00rootroot00000000000000from machine import Pin, Signal # ESP12 module as used by many boards # Blue LED on pin 2, active low (inverted) LED = Signal(2, Pin.OUT, invert=True) micropython-1.12/examples/hwapi/hwconfig_pyboard.py000066400000000000000000000005471357706137100226540ustar00rootroot00000000000000from machine import Pin, Signal # Red LED on pin LED_RED also kown as A13 LED = Signal('LED_RED', Pin.OUT) # Green LED on pin LED_GREEN also known as A14 LED2 = Signal('LED_GREEN', Pin.OUT) # Yellow LED on pin LED_YELLOW also known as A15 LED3 = Signal('LED_YELLOW', Pin.OUT) # Blue LED on pin LED_BLUE also known as B4 LED4 = Signal('LED_BLUE', Pin.OUT) micropython-1.12/examples/hwapi/hwconfig_z_96b_carbon.py000066400000000000000000000005211357706137100234610ustar00rootroot00000000000000from machine import Signal # 96Boards Carbon board # USR1 - User controlled led, connected to PD2 # USR2 - User controlled led, connected to PA15 # BT - Bluetooth indicator, connected to PB5. # Note - 96b_carbon uses (at the time of writing) non-standard # for Zephyr port device naming convention. LED = Signal(("GPIOA", 15), Pin.OUT) micropython-1.12/examples/hwapi/hwconfig_z_frdm_k64f.py000066400000000000000000000002041357706137100233150ustar00rootroot00000000000000from machine import Pin, Signal # Freescale/NXP FRDM-K64F board # Blue LED on port B, pin 21 LED = Signal(("GPIO_1", 21), Pin.OUT) micropython-1.12/examples/hwapi/soft_pwm.py000066400000000000000000000025271357706137100211660ustar00rootroot00000000000000import utime from hwconfig import LED # Using sleep_ms() gives pretty poor PWM resolution and # brightness control, but we use it in the attempt to # make this demo portable to even more boards (e.g. to # those which don't provide sleep_us(), or provide, but # it's not precise, like would be on non realtime OSes). # We otherwise use 20ms period, to make frequency not less # than 50Hz to avoid visible flickering (you may still see # if you're unlucky). def pwm_cycle(led, duty, cycles): duty_off = 20 - duty for i in range(cycles): if duty: led.on() utime.sleep_ms(duty) if duty_off: led.off() utime.sleep_ms(duty_off) # At the duty setting of 1, an LED is still pretty bright, then # at duty 0, it's off. This makes rather unsmooth transition, and # breaks fade effect. So, we avoid value of 0 and oscillate between # 1 and 20. Actually, highest values like 19 and 20 are also # barely distinguishible (like, both of them too bright and burn # your eye). So, improvement to the visible effect would be to use # more steps (at least 10x), and then higher frequency, and use # range which includes 1 but excludes values at the top. while True: # Fade in for i in range(1, 21): pwm_cycle(LED, i, 2) # Fade out for i in range(20, 0, -1): pwm_cycle(LED, i, 2) micropython-1.12/examples/hwapi/soft_pwm2_uasyncio.py000066400000000000000000000014131357706137100231530ustar00rootroot00000000000000# Like soft_pwm_uasyncio.py, but fading 2 LEDs with different phase. # Also see original soft_pwm.py. import uasyncio from hwconfig import LED, LED2 async def pwm_cycle(led, duty, cycles): duty_off = 20 - duty for i in range(cycles): if duty: led.value(1) await uasyncio.sleep_ms(duty) if duty_off: led.value(0) await uasyncio.sleep_ms(duty_off) async def fade_in_out(LED): while True: # Fade in for i in range(1, 21): await pwm_cycle(LED, i, 2) # Fade out for i in range(20, 0, -1): await pwm_cycle(LED, i, 2) loop = uasyncio.get_event_loop() loop.create_task(fade_in_out(LED)) loop.call_later_ms(800, fade_in_out(LED2)) loop.run_forever() micropython-1.12/examples/hwapi/soft_pwm_uasyncio.py000066400000000000000000000012321357706137100230700ustar00rootroot00000000000000# See original soft_pwm.py for detailed comments. import uasyncio from hwconfig import LED async def pwm_cycle(led, duty, cycles): duty_off = 20 - duty for i in range(cycles): if duty: led.value(1) await uasyncio.sleep_ms(duty) if duty_off: led.value(0) await uasyncio.sleep_ms(duty_off) async def fade_in_out(LED): while True: # Fade in for i in range(1, 21): await pwm_cycle(LED, i, 2) # Fade out for i in range(20, 0, -1): await pwm_cycle(LED, i, 2) loop = uasyncio.get_event_loop() loop.run_until_complete(fade_in_out(LED)) micropython-1.12/examples/ledangle.py000066400000000000000000000010121357706137100177570ustar00rootroot00000000000000import pyb def led_angle(seconds_to_run_for): # make LED objects l1 = pyb.LED(1) l2 = pyb.LED(2) accel = pyb.Accel() for i in range(20 * seconds_to_run_for): # get x-axis x = accel.x() # turn on LEDs depending on angle if x < -10: l1.on() l2.off() elif x > 10: l1.off() l2.on() else: l1.off() l2.off() # delay so that loop runs at at 1/50ms = 20Hz pyb.delay(50) micropython-1.12/examples/mandel.py000066400000000000000000000010361357706137100174520ustar00rootroot00000000000000try: import micropython except: pass def mandelbrot(): # returns True if c, complex, is in the Mandelbrot set #@micropython.native def in_set(c): z = 0 for i in range(40): z = z*z + c if abs(z) > 60: return False return True lcd.clear() for u in range(91): for v in range(31): if in_set((u / 30 - 2) + (v / 15 - 1) * 1j): lcd.set(u, v) lcd.show() # PC testing import lcd lcd = lcd.LCD(128, 32) mandelbrot() micropython-1.12/examples/micropython.py000066400000000000000000000002151357706137100205630ustar00rootroot00000000000000# micropython module placeholder for CPython # Dummy function decorators def nodecor(x): return x bytecode = native = viper = nodecor micropython-1.12/examples/natmod/000077500000000000000000000000001357706137100171225ustar00rootroot00000000000000micropython-1.12/examples/natmod/btree/000077500000000000000000000000001357706137100202235ustar00rootroot00000000000000micropython-1.12/examples/natmod/btree/Makefile000066400000000000000000000017061357706137100216670ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module (different to built-in btree so it can coexist) MOD = btree_$(ARCH) # Source files (.c or .py) SRC = btree_c.c btree_py.py # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 BTREE_DIR = $(MPY_DIR)/lib/berkeley-db-1.xx BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error="(void)" -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) CFLAGS += -I$(BTREE_DIR)/PORT/include CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) SRC += $(addprefix $(realpath $(BTREE_DIR))/,\ btree/bt_close.c \ btree/bt_conv.c \ btree/bt_delete.c \ btree/bt_get.c \ btree/bt_open.c \ btree/bt_overflow.c \ btree/bt_page.c \ btree/bt_put.c \ btree/bt_search.c \ btree/bt_seq.c \ btree/bt_split.c \ btree/bt_utils.c \ mpool/mpool.c \ ) include $(MPY_DIR)/py/dynruntime.mk # btree needs gnu99 defined CFLAGS += -std=gnu99 micropython-1.12/examples/natmod/btree/btree_c.c000066400000000000000000000116501357706137100217750ustar00rootroot00000000000000#define MICROPY_ENABLE_DYNRUNTIME (1) #define MICROPY_PY_BTREE (1) #include "py/dynruntime.h" #include #if !defined(__linux__) void *memcpy(void *dst, const void *src, size_t n) { return mp_fun_table.memmove_(dst, src, n); } void *memset(void *s, int c, size_t n) { return mp_fun_table.memset_(s, c, n); } #endif void *memmove(void *dest, const void *src, size_t n) { return mp_fun_table.memmove_(dest, src, n); } void *malloc(size_t n) { void *ptr = m_malloc(n); return ptr; } void *realloc(void *ptr, size_t n) { mp_printf(&mp_plat_print, "UNDEF %d\n", __LINE__); return NULL; } void *calloc(size_t n, size_t m) { void *ptr = m_malloc(n * m); // memory already cleared by conservative GC return ptr; } void free(void *ptr) { m_free(ptr); } void abort_(void) { nlr_raise(mp_obj_new_exception(mp_load_global(MP_QSTR_RuntimeError))); } int native_errno; #if defined(__linux__) int *__errno_location (void) #else int *__errno (void) #endif { return &native_errno; } ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { mp_obj_base_t* o = stream; const mp_stream_p_t *stream_p = o->type->protocol; mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno); if (out_sz == MP_STREAM_ERROR) { return -1; } else { return out_sz; } } ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { mp_obj_base_t* o = stream; const mp_stream_p_t *stream_p = o->type->protocol; mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno); if (out_sz == MP_STREAM_ERROR) { return -1; } else { return out_sz; } } off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { const mp_obj_base_t* o = stream; const mp_stream_p_t *stream_p = o->type->protocol; struct mp_stream_seek_t seek_s; seek_s.offset = offset; seek_s.whence = whence; mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &native_errno); if (res == MP_STREAM_ERROR) { return -1; } return seek_s.offset; } int mp_stream_posix_fsync(void *stream) { mp_obj_base_t* o = stream; const mp_stream_p_t *stream_p = o->type->protocol; mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno); if (res == MP_STREAM_ERROR) { return -1; } return res; } mp_obj_type_t btree_type; #include "extmod/modbtree.c" mp_map_elem_t btree_locals_dict_table[8]; STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table); STATIC mp_obj_t btree_open(size_t n_args, const mp_obj_t *args) { // Make sure we got a stream object mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); BTREEINFO openinfo = {0}; openinfo.flags = mp_obj_get_int(args[1]); openinfo.cachesize = mp_obj_get_int(args[2]); openinfo.psize = mp_obj_get_int(args[3]); openinfo.minkeypage = mp_obj_get_int(args[4]); DB *db = __bt_open(MP_OBJ_TO_PTR(args[0]), &btree_stream_fvtable, &openinfo, 0); if (db == NULL) { mp_raise_OSError(native_errno); } return MP_OBJ_FROM_PTR(btree_new(db)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open); mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { MP_DYNRUNTIME_INIT_ENTRY btree_type.base.type = (void*)&mp_fun_table.type_type; btree_type.name = MP_QSTR_btree; btree_type.print = btree_print; btree_type.getiter = btree_getiter; btree_type.iternext = btree_iternext; btree_type.binary_op = btree_binary_op; btree_type.subscr = btree_subscr; btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) }; btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) }; btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) }; btree_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_put), MP_OBJ_FROM_PTR(&btree_put_obj) }; btree_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_seq), MP_OBJ_FROM_PTR(&btree_seq_obj) }; btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) }; btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) }; btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) }; btree_type.locals_dict = (void*)&btree_locals_dict; mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj)); mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL)); mp_store_global(MP_QSTR_DESC, MP_OBJ_NEW_SMALL_INT(FLAG_DESC)); MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/natmod/btree/btree_py.py000066400000000000000000000002731357706137100224100ustar00rootroot00000000000000# Implemented in Python to support keyword arguments def open(stream, *, flags=0, cachesize=0, pagesize=0, minkeypage=0): return _open(stream, flags, cachesize, pagesize, minkeypage) micropython-1.12/examples/natmod/features0/000077500000000000000000000000001357706137100210205ustar00rootroot00000000000000micropython-1.12/examples/natmod/features0/Makefile000066400000000000000000000005041357706137100224570ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module MOD = features0 # Source files (.c or .py) SRC = features0.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 # Include to get the rules for compiling and linking the module include $(MPY_DIR)/py/dynruntime.mk micropython-1.12/examples/natmod/features0/features0.c000066400000000000000000000026741357706137100230730ustar00rootroot00000000000000/* This example demonstrates the following features in a native module: - defining a simple function exposed to Python - defining a local, helper C function - getting and creating integer objects */ // Include the header file to get access to the MicroPython API #include "py/dynruntime.h" // Helper function to compute factorial STATIC mp_int_t factorial_helper(mp_int_t x) { if (x == 0) { return 1; } return x * factorial_helper(x - 1); } // This is the function which will be called from Python, as factorial(x) STATIC mp_obj_t factorial(mp_obj_t x_obj) { // Extract the integer from the MicroPython input object mp_int_t x = mp_obj_get_int(x_obj); // Calculate the factorial mp_int_t result = factorial_helper(x); // Convert the result to a MicroPython integer object and return it return mp_obj_new_int(result); } // Define a Python reference to the function above STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial); // This is the entry point and is called when the module is imported mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { // This must be first, it sets up the globals dict and other things MP_DYNRUNTIME_INIT_ENTRY // Make the function available in the module's namespace mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj)); // This must be last, it restores the globals dict MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/natmod/features1/000077500000000000000000000000001357706137100210215ustar00rootroot00000000000000micropython-1.12/examples/natmod/features1/Makefile000066400000000000000000000005041357706137100224600ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module MOD = features1 # Source files (.c or .py) SRC = features1.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 # Include to get the rules for compiling and linking the module include $(MPY_DIR)/py/dynruntime.mk micropython-1.12/examples/natmod/features1/features1.c000066400000000000000000000076741357706137100231020ustar00rootroot00000000000000/* This example demonstrates the following features in a native module: - defining simple functions exposed to Python - defining local, helper C functions - defining constant integers and strings exposed to Python - getting and creating integer objects - creating Python lists - raising exceptions - allocating memory - BSS and constant data (rodata) - relocated pointers in rodata */ // Include the header file to get access to the MicroPython API #include "py/dynruntime.h" // BSS (zero) data uint16_t data16[4]; // Constant data (rodata) const uint8_t table8[] = { 0, 1, 1, 2, 3, 5, 8, 13 }; const uint16_t table16[] = { 0x1000, 0x2000 }; // Constant data pointing to BSS/constant data uint16_t *const table_ptr16a[] = { &data16[0], &data16[1], &data16[2], &data16[3] }; const uint16_t *const table_ptr16b[] = { &table16[0], &table16[1] }; // A simple function that adds its 2 arguments (must be integers) STATIC mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) { mp_int_t x = mp_obj_get_int(x_in); mp_int_t y = mp_obj_get_int(y_in); return mp_obj_new_int(x + y); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); // A local helper function (not exposed to Python) STATIC mp_int_t fibonacci_helper(mp_int_t x) { if (x < MP_ARRAY_SIZE(table8)) { return table8[x]; } else { return fibonacci_helper(x - 1) + fibonacci_helper(x - 2); } } // A function which computes Fibonacci numbers STATIC mp_obj_t fibonacci(mp_obj_t x_in) { mp_int_t x = mp_obj_get_int(x_in); if (x < 0) { mp_raise_ValueError("can't compute negative Fibonacci number"); } return mp_obj_new_int(fibonacci_helper(x)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci); // A function that accesses the BSS data STATIC mp_obj_t access(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // Create a list holding all items from data16 mp_obj_list_t *lst = MP_OBJ_TO_PTR(mp_obj_new_list(MP_ARRAY_SIZE(data16), NULL)); for (int i = 0; i < MP_ARRAY_SIZE(data16); ++i) { lst->items[i] = mp_obj_new_int(data16[i]); } return MP_OBJ_FROM_PTR(lst); } else if (n_args == 1) { // Get one item from data16 mp_int_t idx = mp_obj_get_int(args[0]) & 3; return mp_obj_new_int(data16[idx]); } else { // Set one item in data16 (via table_ptr16a) mp_int_t idx = mp_obj_get_int(args[0]) & 3; *table_ptr16a[idx] = mp_obj_get_int(args[1]); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access); // A function that allocates memory and creates a bytearray STATIC mp_obj_t make_array(void) { uint16_t *ptr = m_new(uint16_t, MP_ARRAY_SIZE(table_ptr16b)); for (int i = 0; i < MP_ARRAY_SIZE(table_ptr16b); ++i) { ptr[i] = *table_ptr16b[i]; } return mp_obj_new_bytearray_by_ref(sizeof(uint16_t) * MP_ARRAY_SIZE(table_ptr16b), ptr); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array); // This is the entry point and is called when the module is imported mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { // This must be first, it sets up the globals dict and other things MP_DYNRUNTIME_INIT_ENTRY // Messages can be printed as usualy mp_printf(&mp_plat_print, "initialising module self=%p\n", self); // Make the functions available in the module's namespace mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); mp_store_global(MP_QSTR_fibonacci, MP_OBJ_FROM_PTR(&fibonacci_obj)); mp_store_global(MP_QSTR_access, MP_OBJ_FROM_PTR(&access_obj)); mp_store_global(MP_QSTR_make_array, MP_OBJ_FROM_PTR(&make_array_obj)); // Add some constants to the module's namespace mp_store_global(MP_QSTR_VAL, MP_OBJ_NEW_SMALL_INT(42)); mp_store_global(MP_QSTR_MSG, MP_OBJ_NEW_QSTR(MP_QSTR_HELLO_MICROPYTHON)); // This must be last, it restores the globals dict MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/natmod/features2/000077500000000000000000000000001357706137100210225ustar00rootroot00000000000000micropython-1.12/examples/natmod/features2/Makefile000066400000000000000000000005161357706137100224640ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module MOD = features2 # Source files (.c or .py) SRC = main.c prod.c test.py # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 # Include to get the rules for compiling and linking the module include $(MPY_DIR)/py/dynruntime.mk micropython-1.12/examples/natmod/features2/main.c000066400000000000000000000063351357706137100221210ustar00rootroot00000000000000/* This example demonstrates the following features in a native module: - using floats - defining additional code in Python (see test.py) - have extra C code in a separate file (see prod.c) */ // Include the header file to get access to the MicroPython API #include "py/dynruntime.h" // Include the header for auxiliary C code for this module #include "prod.h" // Automatically detect if this module should include double-precision code. // If double precision is supported by the target architecture then it can // be used in native module regardless of what float setting the target // MicroPython runtime uses (being none, float or double). #if defined(__i386__) || defined(__x86_64__) || (defined(__ARM_FP) && (__ARM_FP & 8)) #define USE_DOUBLE 1 #else #define USE_DOUBLE 0 #endif // A function that uses the default float type configured for the current target // This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) { return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y)); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); // A function that explicitly uses single precision floats STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) { return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y)); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f); #if USE_DOUBLE // A function that explicitly uses double precision floats STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) { return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y)); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d); #endif // A function that computes the product of floats in an array. // This function uses the most general C argument interface, which is more difficult // to use but has access to the globals dict of the module via self->globals. STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { // Check number of arguments is valid mp_arg_check_num(n_args, n_kw, 1, 1, false); // Extract buffer pointer and verify typecode mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_RW); if (bufinfo.typecode != 'f') { mp_raise_ValueError("expecting float array"); } // Compute product, store result back in first element of array float *ptr = bufinfo.buf; float prod = prod_array(bufinfo.len / sizeof(*ptr), ptr); ptr[0] = prod; return mp_const_none; } // This is the entry point and is called when the module is imported mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { // This must be first, it sets up the globals dict and other things MP_DYNRUNTIME_INIT_ENTRY // Make the functions available in the module's namespace mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); mp_store_global(MP_QSTR_add_f, MP_OBJ_FROM_PTR(&add_f_obj)); #if USE_DOUBLE mp_store_global(MP_QSTR_add_d, MP_OBJ_FROM_PTR(&add_d_obj)); #endif // The productf function uses the most general C argument interface mp_store_global(MP_QSTR_productf, MP_DYNRUNTIME_MAKE_FUNCTION(productf)); // This must be last, it restores the globals dict MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/natmod/features2/prod.c000066400000000000000000000002331357706137100221300ustar00rootroot00000000000000#include "prod.h" float prod_array(int n, float *ar) { float ans = 1; for (int i = 0; i < n; ++i) { ans *= ar[i]; } return ans; } micropython-1.12/examples/natmod/features2/prod.h000066400000000000000000000000441357706137100221350ustar00rootroot00000000000000float prod_array(int n, float *ar); micropython-1.12/examples/natmod/features2/test.py000066400000000000000000000007451357706137100223610ustar00rootroot00000000000000# This Python code will be merged with the C code in main.c import array def isclose(a, b): return abs(a - b) < 1e-3 def test(): tests = [ isclose(add(0.1, 0.2), 0.3), isclose(add_f(0.1, 0.2), 0.3), ] ar = array.array('f', [1, 2, 3.5]) productf(ar) tests.append(isclose(ar[0], 7)) if 'add_d' in globals(): tests.append(isclose(add_d(0.1, 0.2), 0.3)) print(tests) if not all(tests): raise SystemExit(1) test() micropython-1.12/examples/natmod/framebuf/000077500000000000000000000000001357706137100207115ustar00rootroot00000000000000micropython-1.12/examples/natmod/framebuf/Makefile000066400000000000000000000004751357706137100223570ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module (different to built-in framebuf so it can coexist) MOD = framebuf_$(ARCH) # Source files (.c or .py) SRC = framebuf.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 include $(MPY_DIR)/py/dynruntime.mk micropython-1.12/examples/natmod/framebuf/framebuf.c000066400000000000000000000054651357706137100226560ustar00rootroot00000000000000#define MICROPY_ENABLE_DYNRUNTIME (1) #define MICROPY_PY_FRAMEBUF (1) #include "py/dynruntime.h" #if !defined(__linux__) void *memset(void *s, int c, size_t n) { return mp_fun_table.memset_(s, c, n); } #endif mp_obj_type_t mp_type_framebuf; #include "extmod/modframebuf.c" mp_map_elem_t framebuf_locals_dict_table[10]; STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table); mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { MP_DYNRUNTIME_INIT_ENTRY mp_type_framebuf.base.type = (void*)&mp_type_type; mp_type_framebuf.name = MP_QSTR_FrameBuffer; mp_type_framebuf.make_new = framebuf_make_new; mp_type_framebuf.buffer_p.get_buffer = framebuf_get_buffer; framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) }; framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) }; framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) }; framebuf_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_hline), MP_OBJ_FROM_PTR(&framebuf_hline_obj) }; framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) }; framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) }; framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) }; framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) }; framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) }; framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) }; mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict; mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf)); mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj)); mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB)); mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB)); mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565)); mp_store_global(MP_QSTR_GS2_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS2_HMSB)); mp_store_global(MP_QSTR_GS4_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB)); mp_store_global(MP_QSTR_GS8, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS8)); mp_store_global(MP_QSTR_MONO_HLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB)); mp_store_global(MP_QSTR_MONO_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB)); MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/natmod/uheapq/000077500000000000000000000000001357706137100204055ustar00rootroot00000000000000micropython-1.12/examples/natmod/uheapq/Makefile000066400000000000000000000004671357706137100220540ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module (different to built-in uheapq so it can coexist) MOD = uheapq_$(ARCH) # Source files (.c or .py) SRC = uheapq.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 include $(MPY_DIR)/py/dynruntime.mk micropython-1.12/examples/natmod/uheapq/uheapq.c000066400000000000000000000011161357706137100220330ustar00rootroot00000000000000#define MICROPY_ENABLE_DYNRUNTIME (1) #define MICROPY_PY_UHEAPQ (1) #include "py/dynruntime.h" #include "extmod/moduheapq.c" mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { MP_DYNRUNTIME_INIT_ENTRY mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uheapq)); mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_uheapq_heappush_obj)); mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_uheapq_heappop_obj)); mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_uheapq_heapify_obj)); MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/natmod/urandom/000077500000000000000000000000001357706137100205675ustar00rootroot00000000000000micropython-1.12/examples/natmod/urandom/Makefile000066400000000000000000000004721357706137100222320ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module (different to built-in urandom so it can coexist) MOD = urandom_$(ARCH) # Source files (.c or .py) SRC = urandom.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 include $(MPY_DIR)/py/dynruntime.mk micropython-1.12/examples/natmod/urandom/urandom.c000066400000000000000000000024151357706137100224020ustar00rootroot00000000000000#define MICROPY_ENABLE_DYNRUNTIME (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #include "py/dynruntime.h" // Dynamic native modules don't support a data section so these must go in the BSS uint32_t yasmarang_pad, yasmarang_n, yasmarang_d; uint8_t yasmarang_dat; #include "extmod/modurandom.c" mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { MP_DYNRUNTIME_INIT_ENTRY yasmarang_pad = 0xeda4baba; yasmarang_n = 69; yasmarang_d = 233; mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_urandom)); mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_urandom_getrandbits_obj)); mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_urandom_seed_obj)); #if MICROPY_PY_URANDOM_EXTRA_FUNCS mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_urandom_randrange_obj)); mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_urandom_randint_obj)); mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_urandom_choice_obj)); #if MICROPY_PY_BUILTINS_FLOAT mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_urandom_random_obj)); mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_urandom_uniform_obj)); #endif #endif MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/natmod/ure/000077500000000000000000000000001357706137100177155ustar00rootroot00000000000000micropython-1.12/examples/natmod/ure/Makefile000066400000000000000000000004561357706137100213620ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module (different to built-in ure so it can coexist) MOD = ure_$(ARCH) # Source files (.c or .py) SRC = ure.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 include $(MPY_DIR)/py/dynruntime.mk micropython-1.12/examples/natmod/ure/ure.c000066400000000000000000000060411357706137100206550ustar00rootroot00000000000000#define MICROPY_ENABLE_DYNRUNTIME (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_URE_MATCH_GROUPS (1) #define MICROPY_PY_URE_MATCH_SPAN_START_END (1) #define MICROPY_PY_URE_SUB (0) // requires vstr interface #include #include "py/dynruntime.h" #define STACK_LIMIT (2048) const char *stack_top; void mp_stack_check(void) { // Assumes descending stack on target volatile char dummy; if (stack_top - &dummy >= STACK_LIMIT) { mp_raise_msg(&mp_type_RuntimeError, "maximum recursion depth exceeded"); } } #if !defined(__linux__) void *memcpy(void *dst, const void *src, size_t n) { return mp_fun_table.memmove_(dst, src, n); } void *memset(void *s, int c, size_t n) { return mp_fun_table.memset_(s, c, n); } #endif void *memmove(void *dest, const void *src, size_t n) { return mp_fun_table.memmove_(dest, src, n); } mp_obj_type_t match_type; mp_obj_type_t re_type; #include "extmod/modure.c" mp_map_elem_t match_locals_dict_table[5]; STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); mp_map_elem_t re_locals_dict_table[3]; STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { MP_DYNRUNTIME_INIT_ENTRY char dummy; stack_top = &dummy; // Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section // to copy in this key/value pair if they are specified as a struct, so assign them separately. match_type.base.type = (void*)&mp_fun_table.type_type; match_type.name = MP_QSTR_match; match_type.print = match_print; match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) }; match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) }; match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) }; match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) }; match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) }; match_type.locals_dict = (void*)&match_locals_dict; re_type.base.type = (void*)&mp_fun_table.type_type; re_type.name = MP_QSTR_ure; re_type.print = re_print; re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) }; re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) }; re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) }; re_type.locals_dict = (void*)&re_locals_dict; mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj)); mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&mod_re_match_obj)); mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&mod_re_search_obj)); MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/natmod/uzlib/000077500000000000000000000000001357706137100202475ustar00rootroot00000000000000micropython-1.12/examples/natmod/uzlib/Makefile000066400000000000000000000004641357706137100217130ustar00rootroot00000000000000# Location of top-level MicroPython directory MPY_DIR = ../../.. # Name of module (different to built-in uzlib so it can coexist) MOD = uzlib_$(ARCH) # Source files (.c or .py) SRC = uzlib.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = x64 include $(MPY_DIR)/py/dynruntime.mk micropython-1.12/examples/natmod/uzlib/uzlib.c000066400000000000000000000026261357706137100215460ustar00rootroot00000000000000#define MICROPY_ENABLE_DYNRUNTIME (1) #define MICROPY_PY_UZLIB (1) #include "py/dynruntime.h" #if !defined(__linux__) void *memset(void *s, int c, size_t n) { return mp_fun_table.memset_(s, c, n); } #endif mp_obj_type_t decompio_type; #include "extmod/moduzlib.c" mp_map_elem_t decompio_locals_dict_table[3]; STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { MP_DYNRUNTIME_INIT_ENTRY decompio_type.base.type = mp_fun_table.type_type; decompio_type.name = MP_QSTR_DecompIO; decompio_type.make_new = decompio_make_new; decompio_type.protocol = &decompio_stream_p; decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) }; decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) }; decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) }; decompio_type.locals_dict = (void*)&decompio_locals_dict; mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib)); mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj)); mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type)); MP_DYNRUNTIME_INIT_EXIT } micropython-1.12/examples/network/000077500000000000000000000000001357706137100173315ustar00rootroot00000000000000micropython-1.12/examples/network/http_client.py000066400000000000000000000011661357706137100222240ustar00rootroot00000000000000try: import usocket as socket except: import socket def main(use_stream=False): s = socket.socket() ai = socket.getaddrinfo("google.com", 80) print("Address infos:", ai) addr = ai[0][-1] print("Connect address:", addr) s.connect(addr) if use_stream: # MicroPython socket objects support stream (aka file) interface # directly, but the line below is needed for CPython. s = s.makefile("rwb", 0) s.write(b"GET / HTTP/1.0\r\n\r\n") print(s.read()) else: s.send(b"GET / HTTP/1.0\r\n\r\n") print(s.recv(4096)) s.close() main() micropython-1.12/examples/network/http_client_ssl.py000066400000000000000000000014011357706137100230750ustar00rootroot00000000000000try: import usocket as _socket except: import _socket try: import ussl as ssl except: import ssl def main(use_stream=True): s = _socket.socket() ai = _socket.getaddrinfo("google.com", 443) print("Address infos:", ai) addr = ai[0][-1] print("Connect address:", addr) s.connect(addr) s = ssl.wrap_socket(s) print(s) if use_stream: # Both CPython and MicroPython SSLSocket objects support read() and # write() methods. s.write(b"GET / HTTP/1.0\r\n\r\n") print(s.read(4096)) else: # MicroPython SSLSocket objects implement only stream interface, not # socket interface s.send(b"GET / HTTP/1.0\r\n\r\n") print(s.recv(4096)) s.close() main() micropython-1.12/examples/network/http_server.py000066400000000000000000000035321357706137100222530ustar00rootroot00000000000000try: import usocket as socket except: import socket CONTENT = b"""\ HTTP/1.0 200 OK Hello #%d from MicroPython! """ def main(micropython_optimize=False): s = socket.socket() # Binding to all interfaces - server will be accessible to other hosts! ai = socket.getaddrinfo("0.0.0.0", 8080) print("Bind address info:", ai) addr = ai[0][-1] s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(addr) s.listen(5) print("Listening, connect your browser to http://:8080/") counter = 0 while True: res = s.accept() client_sock = res[0] client_addr = res[1] print("Client address:", client_addr) print("Client socket:", client_sock) if not micropython_optimize: # To read line-oriented protocol (like HTTP) from a socket (and # avoid short read problem), it must be wrapped in a stream (aka # file-like) object. That's how you do it in CPython: client_stream = client_sock.makefile("rwb") else: # .. but MicroPython socket objects support stream interface # directly, so calling .makefile() method is not required. If # you develop application which will run only on MicroPython, # especially on a resource-constrained embedded device, you # may take this shortcut to save resources. client_stream = client_sock print("Request:") req = client_stream.readline() print(req) while True: h = client_stream.readline() if h == b"" or h == b"\r\n": break print(h) client_stream.write(CONTENT % counter) client_stream.close() if not micropython_optimize: client_sock.close() counter += 1 print() main() micropython-1.12/examples/network/http_server_simplistic.py000066400000000000000000000014371357706137100245150ustar00rootroot00000000000000# Do not use this code in real projects! Read # http_server_simplistic_commented.py for details. try: import usocket as socket except: import socket CONTENT = b"""\ HTTP/1.0 200 OK Hello #%d from MicroPython! """ def main(): s = socket.socket() ai = socket.getaddrinfo("0.0.0.0", 8080) addr = ai[0][-1] s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(addr) s.listen(5) print("Listening, connect your browser to http://:8080/") counter = 0 while True: res = s.accept() client_s = res[0] client_addr = res[1] req = client_s.recv(4096) print("Request:") print(req) client_s.send(CONTENT % counter) client_s.close() counter += 1 print() main() micropython-1.12/examples/network/http_server_simplistic_commented.py000066400000000000000000000054651357706137100265550ustar00rootroot00000000000000# # MicroPython http_server_simplistic.py example # # This example shows how to write the smallest possible HTTP # server in MicroPython. With comments and convenience code # removed, this example can be compressed literally to ten # lines. There's a catch though - read comments below for # details, and use this code only for quick hacks, preferring # http_server.py for "real thing". # try: import usocket as socket except: import socket CONTENT = b"""\ HTTP/1.0 200 OK Hello #%d from MicroPython! """ def main(): s = socket.socket() # Bind to (allow to be connected on ) all interfaces. This means # this server will be accessible to other hosts on your local # network, and if your server has direct (non-firewalled) connection # to the Internet, then to anyone on the Internet. We bind to all # interfaces to let this example work easily on embedded MicroPython # targets, which you will likely access from another machine on your # local network. Take care when running this on an Internet-connected # machine though! Replace "0.0.0.0" with "127.0.0.1" if in doubt, to # make the server accessible only on the machine it runs on. ai = socket.getaddrinfo("0.0.0.0", 8080) print("Bind address info:", ai) addr = ai[0][-1] # A port on which a socket listened remains inactive during some time. # This means that if you run this sample, terminate it, and run again # you will likely get an error. To avoid this timeout, set SO_REUSEADDR # socket option. s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(addr) s.listen(5) print("Listening, connect your browser to http://:8080/") counter = 0 while True: res = s.accept() client_s = res[0] client_addr = res[1] print("Client address:", client_addr) print("Client socket:", client_s) # We assume here that .recv() call will read entire HTTP request # from client. This is usually true, at least on "big OS" systems # like Linux/MacOS/Windows. But that doesn't have to be true in # all cases, in particular on embedded systems, when there can # easily be "short recv", where it returns much less than requested # data size. That's why this example is called "simplistic" - it # shows that writing a web server in Python that *usually works* is # ten lines of code, and you can use this technique for quick hacks # and experimentation. But don't do it like that in production # applications - instead, parse HTTP request properly, as shown # by http_server.py example. req = client_s.recv(4096) print("Request:") print(req) client_s.send(CONTENT % counter) client_s.close() counter += 1 print() main() micropython-1.12/examples/network/http_server_ssl.py000066400000000000000000000075741357706137100231460ustar00rootroot00000000000000import ubinascii as binascii try: import usocket as socket except: import socket import ussl as ssl # This self-signed key/cert pair is randomly generated and to be used for # testing/demonstration only. You should always generate your own key/cert. key = binascii.unhexlify( b'3082013b020100024100cc20643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef' b'610a6a6ba14abb891745cd18a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f' b'872d0203010001024100bb17a54aeb3dd7ae4edec05e775ca9632cf02d29c2a089b563b0' b'd05cdf95aeca507de674553f28b4eadaca82d5549a86058f9996b07768686a5b02cb240d' b'd9f1022100f4a63f5549e817547dca97b5c658038e8593cb78c5aba3c4642cc4cd031d86' b'8f022100d598d870ffe4a34df8de57047a50b97b71f4d23e323f527837c9edae88c79483' b'02210098560c89a70385c36eb07fd7083235c4c1184e525d838aedf7128958bedfdbb102' b'2051c0dab7057a8176ca966f3feb81123d4974a733df0f958525f547dfd1c271f9022044' b'6c2cafad455a671a8cf398e642e1be3b18a3d3aec2e67a9478f83c964c4f1f') cert = binascii.unhexlify( b'308201d53082017f020203e8300d06092a864886f70d01010505003075310b3009060355' b'0406130258583114301206035504080c0b54686550726f76696e63653110300e06035504' b'070c075468654369747931133011060355040a0c0a436f6d70616e7958595a3113301106' b'0355040b0c0a436f6d70616e7958595a3114301206035504030c0b546865486f73744e61' b'6d65301e170d3139313231383033333935355a170d3239313231353033333935355a3075' b'310b30090603550406130258583114301206035504080c0b54686550726f76696e636531' b'10300e06035504070c075468654369747931133011060355040a0c0a436f6d70616e7958' b'595a31133011060355040b0c0a436f6d70616e7958595a3114301206035504030c0b5468' b'65486f73744e616d65305c300d06092a864886f70d0101010500034b003048024100cc20' b'643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef610a6a6ba14abb891745cd18' b'a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f872d0203010001300d06092a' b'864886f70d0101050500034100b0513fe2829e9ecbe55b6dd14c0ede7502bde5d46153c8' b'e960ae3ebc247371b525caeb41bbcf34686015a44c50d226e66aef0a97a63874ca5944ef' b'979b57f0b3') CONTENT = b"""\ HTTP/1.0 200 OK Hello #%d from MicroPython! """ def main(use_stream=True): s = socket.socket() # Binding to all interfaces - server will be accessible to other hosts! ai = socket.getaddrinfo("0.0.0.0", 8443) print("Bind address info:", ai) addr = ai[0][-1] s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(addr) s.listen(5) print("Listening, connect your browser to https://:8443/") counter = 0 while True: res = s.accept() client_s = res[0] client_addr = res[1] print("Client address:", client_addr) print("Client socket:", client_s) # CPython uses key keyfile/certfile arguments, but MicroPython uses key/cert client_s = ssl.wrap_socket(client_s, server_side=True, key=key, cert=cert) print(client_s) print("Request:") if use_stream: # Both CPython and MicroPython SSLSocket objects support read() and # write() methods. # Browsers are prone to terminate SSL connection abruptly if they # see unknown certificate, etc. We must continue in such case - # next request they issue will likely be more well-behaving and # will succeed. try: req = client_s.readline() print(req) while True: h = client_s.readline() if h == b"" or h == b"\r\n": break print(h) if req: client_s.write(CONTENT % counter) except Exception as e: print("Exception serving request:", e) else: print(client_s.recv(4096)) client_s.send(CONTENT % counter) client_s.close() counter += 1 print() main() micropython-1.12/examples/pins.py000066400000000000000000000040021357706137100171570ustar00rootroot00000000000000# Print a nice list of pins, their current settings, and available afs. # Requires pins_af.py from ports/stm32/build-PYBV10/ directory. import pyb import pins_af def af(): max_name_width = 0 max_af_width = 0 for pin_entry in pins_af.PINS_AF: max_name_width = max(max_name_width, len(pin_entry[0])) for af_entry in pin_entry[1:]: max_af_width = max(max_af_width, len(af_entry[1])) for pin_entry in pins_af.PINS_AF: pin_name = pin_entry[0] print('%-*s ' % (max_name_width, pin_name), end='') for af_entry in pin_entry[1:]: print('%2d: %-*s ' % (af_entry[0], max_af_width, af_entry[1]), end='') print('') def pins(): mode_str = { pyb.Pin.IN : 'IN', pyb.Pin.OUT_PP : 'OUT_PP', pyb.Pin.OUT_OD : 'OUT_OD', pyb.Pin.AF_PP : 'AF_PP', pyb.Pin.AF_OD : 'AF_OD', pyb.Pin.ANALOG : 'ANALOG' } pull_str = { pyb.Pin.PULL_NONE : '', pyb.Pin.PULL_UP : 'PULL_UP', pyb.Pin.PULL_DOWN : 'PULL_DOWN' } width = [0, 0, 0, 0] rows = [] for pin_entry in pins_af.PINS_AF: row = [] pin_name = pin_entry[0] pin = pyb.Pin(pin_name) pin_mode = pin.mode() row.append(pin_name) row.append(mode_str[pin_mode]) row.append(pull_str[pin.pull()]) if pin_mode == pyb.Pin.AF_PP or pin_mode == pyb.Pin.AF_OD: pin_af = pin.af() for af_entry in pin_entry[1:]: if pin_af == af_entry[0]: af_str = '%d: %s' % (pin_af, af_entry[1]) break else: af_str = '%d' % pin_af else: af_str = '' row.append(af_str) for col in range(len(width)): width[col] = max(width[col], len(row[col])) rows.append(row) for row in rows: for col in range(len(width)): print('%-*s ' % (width[col], row[col]), end='') print('') micropython-1.12/examples/pyb.py000066400000000000000000000027361357706137100170140ustar00rootroot00000000000000# pyboard testing functions for CPython import time def delay(n): #time.sleep(float(n) / 1000) pass rand_seed = 1 def rng(): global rand_seed # for these choice of numbers, see P L'Ecuyer, "Tables of linear congruential generators of different sizes and good lattice structure" rand_seed = (rand_seed * 653276) % 8388593 return rand_seed # LCD testing object for PC # uses double buffering class LCD: def __init__(self, port): self.width = 128 self.height = 32 self.buf1 = [[0 for x in range(self.width)] for y in range(self.height)] self.buf2 = [[0 for x in range(self.width)] for y in range(self.height)] def light(self, value): pass def fill(self, value): for y in range(self.height): for x in range(self.width): self.buf1[y][x] = self.buf2[y][x] = value def show(self): print('') # blank line to separate frames for y in range(self.height): for x in range(self.width): self.buf1[y][x] = self.buf2[y][x] for y in range(self.height): row = ''.join(['*' if self.buf1[y][x] else ' ' for x in range(self.width)]) print(row) def get(self, x, y): if 0 <= x < self.width and 0 <= y < self.height: return self.buf1[y][x] else: return 0 def pixel(self, x, y, value): if 0 <= x < self.width and 0 <= y < self.height: self.buf2[y][x] = value micropython-1.12/examples/switch.py000066400000000000000000000020051357706137100175100ustar00rootroot00000000000000""" switch.py ========= Light up some leds when the USR switch on the pyboard is pressed. Example Usage:: Micro Python v1.0.1 on 2014-05-12; PYBv1.0 with STM32F405RG Type "help()" for more information. >>> import switch >>> switch.run_loop() Loop started. Press Ctrl+C to break out of the loop. """ import pyb switch = pyb.Switch() red_led = pyb.LED(1) green_led = pyb.LED(2) orange_led = pyb.LED(3) blue_led = pyb.LED(4) all_leds = (red_led, green_led, orange_led, blue_led) def run_loop(leds=all_leds): """ Start the loop. :param `leds`: Which LEDs to light up upon switch press. :type `leds`: sequence of LED objects """ print('Loop started.\nPress Ctrl+C to break out of the loop.') while 1: try: if switch(): [led.on() for led in leds] else: [led.off() for led in leds] except OSError: # VCPInterrupt # Ctrl+C in interpreter mode. break if __name__ == '__main__': run_loop() micropython-1.12/examples/unix/000077500000000000000000000000001357706137100166235ustar00rootroot00000000000000micropython-1.12/examples/unix/ffi_example.py000066400000000000000000000015241357706137100214560ustar00rootroot00000000000000import ffi import uctypes libc = ffi.open("libc.so.6") print("libc:", libc) print() # Declare few functions perror = libc.func("v", "perror", "s") time = libc.func("i", "time", "p") open = libc.func("i", "open", "si") qsort = libc.func("v", "qsort", "piiC") # And one variable errno = libc.var("i", "errno") print("time:", time) print("UNIX time is:", time(None)) print() perror("perror before error") open("somethingnonexistent__", 0) print("errno object:", errno) print("errno value:", errno.get()) perror("perror after error") print() def cmp(pa, pb): a = uctypes.bytearray_at(pa, 1) b = uctypes.bytearray_at(pb, 1) print("cmp:", a, b) return a[0] - b[0] cmp_cb = ffi.callback("i", cmp, "PP") print("callback:", cmp_cb) s = bytearray(b"foobar") print("org string:", s) qsort(s, len(s), 1, cmp_cb) print("qsort'ed string:", s) micropython-1.12/examples/unix/machine_bios.py000066400000000000000000000004771357706137100216250ustar00rootroot00000000000000# This example shows how to access Video BIOS memory area via machine.mem # It requires root privilege and x86 legacy harfware (which has mentioned # Video BIOS at all). # It is expected to print 0xaa55, which is a signature at the start of # Video BIOS. import umachine as machine print(hex(machine.mem16[0xc0000])) micropython-1.12/extmod/000077500000000000000000000000001357706137100153225ustar00rootroot00000000000000micropython-1.12/extmod/axtls-include/000077500000000000000000000000001357706137100200765ustar00rootroot00000000000000micropython-1.12/extmod/axtls-include/config.h000066400000000000000000000062211357706137100215150ustar00rootroot00000000000000/* * Automatically generated header file: don't edit */ #define HAVE_DOT_CONFIG 1 #define CONFIG_PLATFORM_LINUX 1 #undef CONFIG_PLATFORM_CYGWIN #undef CONFIG_PLATFORM_WIN32 /* * General Configuration */ #define PREFIX "/usr/local" #undef CONFIG_DEBUG #undef CONFIG_STRIP_UNWANTED_SECTIONS #undef CONFIG_VISUAL_STUDIO_7_0 #undef CONFIG_VISUAL_STUDIO_8_0 #undef CONFIG_VISUAL_STUDIO_10_0 #define CONFIG_VISUAL_STUDIO_7_0_BASE "" #define CONFIG_VISUAL_STUDIO_8_0_BASE "" #define CONFIG_VISUAL_STUDIO_10_0_BASE "" #define CONFIG_EXTRA_CFLAGS_OPTIONS "" #define CONFIG_EXTRA_LDFLAGS_OPTIONS "" /* * SSL Library */ #undef CONFIG_SSL_SERVER_ONLY #undef CONFIG_SSL_CERT_VERIFICATION #undef CONFIG_SSL_FULL_MODE #define CONFIG_SSL_SKELETON_MODE 1 #define CONFIG_SSL_ENABLE_SERVER 1 #define CONFIG_SSL_ENABLE_CLIENT 1 #undef CONFIG_SSL_DIAGNOSTICS #define CONFIG_SSL_PROT_LOW 1 #undef CONFIG_SSL_PROT_MEDIUM #undef CONFIG_SSL_PROT_HIGH #define CONFIG_SSL_AES 1 #define CONFIG_SSL_USE_DEFAULT_KEY 1 #define CONFIG_SSL_PRIVATE_KEY_LOCATION "" #define CONFIG_SSL_PRIVATE_KEY_PASSWORD "" #define CONFIG_SSL_X509_CERT_LOCATION "" #undef CONFIG_SSL_GENERATE_X509_CERT #define CONFIG_SSL_X509_COMMON_NAME "" #define CONFIG_SSL_X509_ORGANIZATION_NAME "" #define CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME "" #undef CONFIG_SSL_HAS_PEM #undef CONFIG_SSL_USE_PKCS12 #define CONFIG_SSL_EXPIRY_TIME #define CONFIG_X509_MAX_CA_CERTS 0 #define CONFIG_SSL_MAX_CERTS 3 #undef CONFIG_SSL_CTX_MUTEXING #undef CONFIG_USE_DEV_URANDOM #undef CONFIG_WIN32_USE_CRYPTO_LIB #undef CONFIG_OPENSSL_COMPATIBLE #undef CONFIG_PERFORMANCE_TESTING #undef CONFIG_SSL_TEST #undef CONFIG_AXTLSWRAP #undef CONFIG_AXHTTPD #undef CONFIG_HTTP_STATIC_BUILD #define CONFIG_HTTP_PORT #define CONFIG_HTTP_HTTPS_PORT #define CONFIG_HTTP_SESSION_CACHE_SIZE #define CONFIG_HTTP_WEBROOT "" #define CONFIG_HTTP_TIMEOUT #undef CONFIG_HTTP_HAS_CGI #define CONFIG_HTTP_CGI_EXTENSIONS "" #undef CONFIG_HTTP_ENABLE_LUA #define CONFIG_HTTP_LUA_PREFIX "" #undef CONFIG_HTTP_BUILD_LUA #define CONFIG_HTTP_CGI_LAUNCHER "" #undef CONFIG_HTTP_DIRECTORIES #undef CONFIG_HTTP_HAS_AUTHORIZATION #undef CONFIG_HTTP_HAS_IPV6 #undef CONFIG_HTTP_ENABLE_DIFFERENT_USER #define CONFIG_HTTP_USER "" #undef CONFIG_HTTP_VERBOSE #undef CONFIG_HTTP_IS_DAEMON /* * Language Bindings */ #undef CONFIG_BINDINGS #undef CONFIG_CSHARP_BINDINGS #undef CONFIG_VBNET_BINDINGS #define CONFIG_DOT_NET_FRAMEWORK_BASE "" #undef CONFIG_JAVA_BINDINGS #define CONFIG_JAVA_HOME "" #undef CONFIG_PERL_BINDINGS #define CONFIG_PERL_CORE "" #define CONFIG_PERL_LIB "" #undef CONFIG_LUA_BINDINGS #define CONFIG_LUA_CORE "" /* * Samples */ #undef CONFIG_SAMPLES #undef CONFIG_C_SAMPLES #undef CONFIG_CSHARP_SAMPLES #undef CONFIG_VBNET_SAMPLES #undef CONFIG_JAVA_SAMPLES #undef CONFIG_PERL_SAMPLES #undef CONFIG_LUA_SAMPLES #undef CONFIG_BIGINT_CLASSICAL #undef CONFIG_BIGINT_MONTGOMERY #undef CONFIG_BIGINT_BARRETT #undef CONFIG_BIGINT_CRT #undef CONFIG_BIGINT_KARATSUBA #define MUL_KARATSUBA_THRESH #define SQU_KARATSUBA_THRESH #undef CONFIG_BIGINT_SLIDING_WINDOW #undef CONFIG_BIGINT_SQUARE #undef CONFIG_BIGINT_CHECK_ON #undef CONFIG_INTEGER_32BIT #undef CONFIG_INTEGER_16BIT #undef CONFIG_INTEGER_8BIT micropython-1.12/extmod/axtls-include/version.h000066400000000000000000000000501357706137100217270ustar00rootroot00000000000000#define AXTLS_VERSION "(no version)" micropython-1.12/extmod/crypto-algorithms/000077500000000000000000000000001357706137100210115ustar00rootroot00000000000000micropython-1.12/extmod/crypto-algorithms/sha256.c000066400000000000000000000124021357706137100221640ustar00rootroot00000000000000/********************************************************************* * Source: https://github.com/B-Con/crypto-algorithms * Filename: sha256.c * Author: Brad Conte (brad AT bradconte.com) * Copyright: This code is released into the public domain. * Disclaimer: This code is presented "as is" without any guarantees. * Details: Implementation of the SHA-256 hashing algorithm. SHA-256 is one of the three algorithms in the SHA2 specification. The others, SHA-384 and SHA-512, are not offered in this implementation. Algorithm specification can be found here: * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf This implementation uses little endian byte order. *********************************************************************/ /*************************** HEADER FILES ***************************/ #include #include "sha256.h" /****************************** MACROS ******************************/ #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) /**************************** VARIABLES *****************************/ static const WORD k[64] = { 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 }; /*********************** FUNCTION DEFINITIONS ***********************/ static void sha256_transform(CRYAL_SHA256_CTX *ctx, const BYTE data[]) { WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; for (i = 0, j = 0; i < 16; ++i, j += 4) m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); for ( ; i < 64; ++i) m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; e = ctx->state[4]; f = ctx->state[5]; g = ctx->state[6]; h = ctx->state[7]; for (i = 0; i < 64; ++i) { t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; t2 = EP0(a) + MAJ(a,b,c); h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; } ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d; ctx->state[4] += e; ctx->state[5] += f; ctx->state[6] += g; ctx->state[7] += h; } void sha256_init(CRYAL_SHA256_CTX *ctx) { ctx->datalen = 0; ctx->bitlen = 0; ctx->state[0] = 0x6a09e667; ctx->state[1] = 0xbb67ae85; ctx->state[2] = 0x3c6ef372; ctx->state[3] = 0xa54ff53a; ctx->state[4] = 0x510e527f; ctx->state[5] = 0x9b05688c; ctx->state[6] = 0x1f83d9ab; ctx->state[7] = 0x5be0cd19; } void sha256_update(CRYAL_SHA256_CTX *ctx, const BYTE data[], size_t len) { WORD i; for (i = 0; i < len; ++i) { ctx->data[ctx->datalen] = data[i]; ctx->datalen++; if (ctx->datalen == 64) { sha256_transform(ctx, ctx->data); ctx->bitlen += 512; ctx->datalen = 0; } } } void sha256_final(CRYAL_SHA256_CTX *ctx, BYTE hash[]) { WORD i; i = ctx->datalen; // Pad whatever data is left in the buffer. if (ctx->datalen < 56) { ctx->data[i++] = 0x80; while (i < 56) ctx->data[i++] = 0x00; } else { ctx->data[i++] = 0x80; while (i < 64) ctx->data[i++] = 0x00; sha256_transform(ctx, ctx->data); memset(ctx->data, 0, 56); } // Append to the padding the total message's length in bits and transform. ctx->bitlen += ctx->datalen * 8; ctx->data[63] = ctx->bitlen; ctx->data[62] = ctx->bitlen >> 8; ctx->data[61] = ctx->bitlen >> 16; ctx->data[60] = ctx->bitlen >> 24; ctx->data[59] = ctx->bitlen >> 32; ctx->data[58] = ctx->bitlen >> 40; ctx->data[57] = ctx->bitlen >> 48; ctx->data[56] = ctx->bitlen >> 56; sha256_transform(ctx, ctx->data); // Since this implementation uses little endian byte ordering and SHA uses big endian, // reverse all the bytes when copying the final state to the output hash. for (i = 0; i < 4; ++i) { hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; } } micropython-1.12/extmod/crypto-algorithms/sha256.h000066400000000000000000000024771357706137100222040ustar00rootroot00000000000000/********************************************************************* * Source: https://github.com/B-Con/crypto-algorithms * Filename: sha256.h * Author: Brad Conte (brad AT bradconte.com) * Copyright: This code is released into the public domain. * Disclaimer: This code is presented "as is" without any guarantees. * Details: Defines the API for the corresponding SHA1 implementation. *********************************************************************/ #ifndef SHA256_H #define SHA256_H /*************************** HEADER FILES ***************************/ #include /****************************** MACROS ******************************/ #define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest /**************************** DATA TYPES ****************************/ typedef unsigned char BYTE; // 8-bit byte typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines typedef struct { BYTE data[64]; WORD datalen; unsigned long long bitlen; WORD state[8]; } CRYAL_SHA256_CTX; /*********************** FUNCTION DECLARATIONS **********************/ void sha256_init(CRYAL_SHA256_CTX *ctx); void sha256_update(CRYAL_SHA256_CTX *ctx, const BYTE data[], size_t len); void sha256_final(CRYAL_SHA256_CTX *ctx, BYTE hash[]); #endif // SHA256_H micropython-1.12/extmod/extmod.mk000066400000000000000000000120401357706137100171500ustar00rootroot00000000000000# This makefile fragment provides rules to build 3rd-party components for extmod modules ################################################################################ # VFS FAT FS OOFATFS_DIR = lib/oofatfs # this sets the config file for FatFs CFLAGS_MOD += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\" ifeq ($(MICROPY_VFS_FAT),1) CFLAGS_MOD += -DMICROPY_VFS_FAT=1 SRC_MOD += $(addprefix $(OOFATFS_DIR)/,\ ff.c \ ffunicode.c \ ) endif ################################################################################ # VFS littlefs LITTLEFS_DIR = lib/littlefs ifeq ($(MICROPY_VFS_LFS1),1) CFLAGS_MOD += -DMICROPY_VFS_LFS1=1 CFLAGS_MOD += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ lfs1.c \ lfs1_util.c \ ) endif ifeq ($(MICROPY_VFS_LFS2),1) CFLAGS_MOD += -DMICROPY_VFS_LFS2=1 CFLAGS_MOD += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ lfs2.c \ lfs2_util.c \ ) endif ################################################################################ # ussl ifeq ($(MICROPY_PY_USSL),1) CFLAGS_MOD += -DMICROPY_PY_USSL=1 ifeq ($(MICROPY_SSL_AXTLS),1) CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include AXTLS_DIR = lib/axtls $(BUILD)/$(AXTLS_DIR)/%.o: CFLAGS += -Wno-all -Wno-unused-parameter -Wno-uninitialized -Wno-sign-compare -Wno-old-style-definition $(AXTLS_DEFS_EXTRA) SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ ssl/asn1.c \ ssl/loader.c \ ssl/tls1.c \ ssl/tls1_svr.c \ ssl/tls1_clnt.c \ ssl/x509.c \ crypto/aes.c \ crypto/bigint.c \ crypto/crypto_misc.c \ crypto/hmac.c \ crypto/md5.c \ crypto/rsa.c \ crypto/sha1.c \ ) else ifeq ($(MICROPY_SSL_MBEDTLS),1) MBEDTLS_DIR = lib/mbedtls CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\ aes.c \ aesni.c \ arc4.c \ asn1parse.c \ asn1write.c \ base64.c \ bignum.c \ blowfish.c \ camellia.c \ ccm.c \ certs.c \ chacha20.c \ chachapoly.c \ cipher.c \ cipher_wrap.c \ cmac.c \ ctr_drbg.c \ debug.c \ des.c \ dhm.c \ ecdh.c \ ecdsa.c \ ecjpake.c \ ecp.c \ ecp_curves.c \ entropy.c \ entropy_poll.c \ error.c \ gcm.c \ havege.c \ hmac_drbg.c \ md2.c \ md4.c \ md5.c \ md.c \ md_wrap.c \ oid.c \ padlock.c \ pem.c \ pk.c \ pkcs11.c \ pkcs12.c \ pkcs5.c \ pkparse.c \ pk_wrap.c \ pkwrite.c \ platform.c \ platform_util.c \ poly1305.c \ ripemd160.c \ rsa.c \ rsa_internal.c \ sha1.c \ sha256.c \ sha512.c \ ssl_cache.c \ ssl_ciphersuites.c \ ssl_cli.c \ ssl_cookie.c \ ssl_srv.c \ ssl_ticket.c \ ssl_tls.c \ timing.c \ x509.c \ x509_create.c \ x509_crl.c \ x509_crt.c \ x509_csr.c \ x509write_crt.c \ x509write_csr.c \ xtea.c \ ) endif endif ################################################################################ # lwip ifeq ($(MICROPY_PY_LWIP),1) # A port should add an include path where lwipopts.h can be found (eg extmod/lwip-include) LWIP_DIR = lib/lwip/src INC += -I$(TOP)/$(LWIP_DIR)/include CFLAGS_MOD += -DMICROPY_PY_LWIP=1 $(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address SRC_MOD += extmod/modlwip.c lib/netutils/netutils.c SRC_MOD += $(addprefix $(LWIP_DIR)/,\ apps/mdns/mdns.c \ core/def.c \ core/dns.c \ core/inet_chksum.c \ core/init.c \ core/ip.c \ core/mem.c \ core/memp.c \ core/netif.c \ core/pbuf.c \ core/raw.c \ core/stats.c \ core/sys.c \ core/tcp.c \ core/tcp_in.c \ core/tcp_out.c \ core/timeouts.c \ core/udp.c \ core/ipv4/autoip.c \ core/ipv4/dhcp.c \ core/ipv4/etharp.c \ core/ipv4/icmp.c \ core/ipv4/igmp.c \ core/ipv4/ip4_addr.c \ core/ipv4/ip4.c \ core/ipv4/ip4_frag.c \ core/ipv6/dhcp6.c \ core/ipv6/ethip6.c \ core/ipv6/icmp6.c \ core/ipv6/inet6.c \ core/ipv6/ip6_addr.c \ core/ipv6/ip6.c \ core/ipv6/ip6_frag.c \ core/ipv6/mld6.c \ core/ipv6/nd6.c \ netif/ethernet.c \ ) ifeq ($(MICROPY_PY_LWIP_SLIP),1) CFLAGS_MOD += -DMICROPY_PY_LWIP_SLIP=1 SRC_MOD += $(LWIP_DIR)/netif/slipif.c endif endif ################################################################################ # btree ifeq ($(MICROPY_PY_BTREE),1) BTREE_DIR = lib/berkeley-db-1.xx BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) INC += -I$(TOP)/$(BTREE_DIR)/PORT/include SRC_MOD += extmod/modbtree.c SRC_MOD += $(addprefix $(BTREE_DIR)/,\ btree/bt_close.c \ btree/bt_conv.c \ btree/bt_debug.c \ btree/bt_delete.c \ btree/bt_get.c \ btree/bt_open.c \ btree/bt_overflow.c \ btree/bt_page.c \ btree/bt_put.c \ btree/bt_search.c \ btree/bt_seq.c \ btree/bt_split.c \ btree/bt_utils.c \ mpool/mpool.c \ ) CFLAGS_MOD += -DMICROPY_PY_BTREE=1 # we need to suppress certain warnings to get berkeley-db to compile cleanly # and we have separate BTREE_DEFS so the definitions don't interfere with other source code $(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) $(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS) endif micropython-1.12/extmod/lwip-include/000077500000000000000000000000001357706137100177165ustar00rootroot00000000000000micropython-1.12/extmod/lwip-include/arch/000077500000000000000000000000001357706137100206335ustar00rootroot00000000000000micropython-1.12/extmod/lwip-include/arch/cc.h000066400000000000000000000016131357706137100213720ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H #define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H #include // Generate lwip's internal types from stdint typedef uint8_t u8_t; typedef int8_t s8_t; typedef uint16_t u16_t; typedef int16_t s16_t; typedef uint32_t u32_t; typedef int32_t s32_t; typedef u32_t mem_ptr_t; #define U16_F "hu" #define S16_F "hd" #define X16_F "hx" #define U32_F "u" #define S32_F "d" #define X32_F "x" #define X8_F "02x" #define SZT_F "u" #define BYTE_ORDER LITTLE_ENDIAN #define LWIP_CHKSUM_ALGORITHM 2 #include #define LWIP_PLATFORM_DIAG(x) #define LWIP_PLATFORM_ASSERT(x) { assert(1); } //#define PACK_STRUCT_FIELD(x) x __attribute__((packed)) #define PACK_STRUCT_FIELD(x) x #define PACK_STRUCT_STRUCT __attribute__((packed)) #define PACK_STRUCT_BEGIN #define PACK_STRUCT_END #endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H micropython-1.12/extmod/lwip-include/arch/perf.h000066400000000000000000000004071357706137100217410ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H #define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H #define PERF_START /* null definition */ #define PERF_STOP(x) /* null definition */ #endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H micropython-1.12/extmod/lwip-include/lwipopts.h000066400000000000000000000017431357706137100217550ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H #define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H #include #include #include // We're running without an OS for this port. We don't provide any services except light protection. #define NO_SYS 1 #define SYS_LIGHTWEIGHT_PROT 1 #include typedef uint32_t sys_prot_t; #define TCP_LISTEN_BACKLOG 1 // We'll put these into a proper ifdef once somebody implements an ethernet driver #define LWIP_ARP 0 #define LWIP_ETHERNET 0 #define LWIP_DNS 1 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 #ifdef MICROPY_PY_LWIP_SLIP #define LWIP_HAVE_SLIPIF 1 #endif // For now, we can simply define this as a macro for the timer code. But this function isn't // universal and other ports will need to do something else. It may be necessary to move // things like this into a port-provided header file. #define sys_now mp_hal_ticks_ms #endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H micropython-1.12/extmod/machine_i2c.c000066400000000000000000000607711357706137100176420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mperrno.h" #include "py/mphal.h" #include "py/runtime.h" #include "extmod/machine_i2c.h" #if MICROPY_PY_MACHINE_I2C typedef mp_machine_soft_i2c_obj_t machine_i2c_obj_t; STATIC void mp_hal_i2c_delay(machine_i2c_obj_t *self) { // We need to use an accurate delay to get acceptable I2C // speeds (eg 1us should be not much more than 1us). mp_hal_delay_us_fast(self->us_delay); } STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) { mp_hal_pin_od_low(self->scl); } STATIC int mp_hal_i2c_scl_release(machine_i2c_obj_t *self) { uint32_t count = self->us_timeout; mp_hal_pin_od_high(self->scl); mp_hal_i2c_delay(self); // For clock stretching, wait for the SCL pin to be released, with timeout. for (; mp_hal_pin_read(self->scl) == 0 && count; --count) { mp_hal_delay_us_fast(1); } if (count == 0) { return -MP_ETIMEDOUT; } return 0; // success } STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) { mp_hal_pin_od_low(self->sda); } STATIC void mp_hal_i2c_sda_release(machine_i2c_obj_t *self) { mp_hal_pin_od_high(self->sda); } STATIC int mp_hal_i2c_sda_read(machine_i2c_obj_t *self) { return mp_hal_pin_read(self->sda); } STATIC int mp_hal_i2c_start(machine_i2c_obj_t *self) { mp_hal_i2c_sda_release(self); mp_hal_i2c_delay(self); int ret = mp_hal_i2c_scl_release(self); if (ret != 0) { return ret; } mp_hal_i2c_sda_low(self); mp_hal_i2c_delay(self); return 0; // success } STATIC int mp_hal_i2c_stop(machine_i2c_obj_t *self) { mp_hal_i2c_delay(self); mp_hal_i2c_sda_low(self); mp_hal_i2c_delay(self); int ret = mp_hal_i2c_scl_release(self); mp_hal_i2c_sda_release(self); mp_hal_i2c_delay(self); return ret; } STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t freq) { self->us_delay = 500000 / freq; if (self->us_delay == 0) { self->us_delay = 1; } mp_hal_pin_open_drain(self->scl); mp_hal_pin_open_drain(self->sda); mp_hal_i2c_stop(self); // ignore error } // return value: // 0 - byte written and ack received // 1 - byte written and nack received // <0 - error, with errno being the negative of the return value STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) { mp_hal_i2c_delay(self); mp_hal_i2c_scl_low(self); for (int i = 7; i >= 0; i--) { if ((val >> i) & 1) { mp_hal_i2c_sda_release(self); } else { mp_hal_i2c_sda_low(self); } mp_hal_i2c_delay(self); int ret = mp_hal_i2c_scl_release(self); if (ret != 0) { mp_hal_i2c_sda_release(self); return ret; } mp_hal_i2c_scl_low(self); } mp_hal_i2c_sda_release(self); mp_hal_i2c_delay(self); int ret = mp_hal_i2c_scl_release(self); if (ret != 0) { return ret; } int ack = mp_hal_i2c_sda_read(self); mp_hal_i2c_delay(self); mp_hal_i2c_scl_low(self); return ack; } // return value: // 0 - success // <0 - error, with errno being the negative of the return value STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) { mp_hal_i2c_delay(self); mp_hal_i2c_scl_low(self); mp_hal_i2c_delay(self); uint8_t data = 0; for (int i = 7; i >= 0; i--) { int ret = mp_hal_i2c_scl_release(self); if (ret != 0) { return ret; } data = (data << 1) | mp_hal_i2c_sda_read(self); mp_hal_i2c_scl_low(self); mp_hal_i2c_delay(self); } *val = data; // send ack/nack bit if (!nack) { mp_hal_i2c_sda_low(self); } mp_hal_i2c_delay(self); int ret = mp_hal_i2c_scl_release(self); if (ret != 0) { mp_hal_i2c_sda_release(self); return ret; } mp_hal_i2c_scl_low(self); mp_hal_i2c_sda_release(self); return 0; // success } // return value: // >=0 - success; for read it's 0, for write it's number of acks received // <0 - error, with errno being the negative of the return value int mp_machine_soft_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in; // start the I2C transaction int ret = mp_hal_i2c_start(self); if (ret != 0) { return ret; } // write the slave address ret = mp_hal_i2c_write_byte(self, (addr << 1) | (flags & MP_MACHINE_I2C_FLAG_READ)); if (ret < 0) { return ret; } else if (ret != 0) { // nack received, release the bus cleanly mp_hal_i2c_stop(self); return -MP_ENODEV; } int transfer_ret = 0; for (; n--; ++bufs) { size_t len = bufs->len; uint8_t *buf = bufs->buf; if (flags & MP_MACHINE_I2C_FLAG_READ) { // read bytes from the slave into the given buffer(s) while (len--) { ret = mp_hal_i2c_read_byte(self, buf++, (n | len) == 0); if (ret != 0) { return ret; } } } else { // write bytes from the given buffer(s) to the slave while (len--) { ret = mp_hal_i2c_write_byte(self, *buf++); if (ret < 0) { return ret; } else if (ret != 0) { // nack received, stop sending n = 0; break; } ++transfer_ret; // count the number of acks } } } // finish the I2C transaction if (flags & MP_MACHINE_I2C_FLAG_STOP) { ret = mp_hal_i2c_stop(self); if (ret != 0) { return ret; } } return transfer_ret; } /******************************************************************************/ // Generic helper functions // For use by ports that require a single buffer of data for a read/write transfer int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { size_t len; uint8_t *buf; if (n == 1) { // Use given single buffer len = bufs[0].len; buf = bufs[0].buf; } else { // Combine buffers into a single one len = 0; for (size_t i = 0; i < n; ++i) { len += bufs[i].len; } buf = m_new(uint8_t, len); if (!(flags & MP_MACHINE_I2C_FLAG_READ)) { len = 0; for (size_t i = 0; i < n; ++i) { memcpy(buf + len, bufs[i].buf, bufs[i].len); len += bufs[i].len; } } } mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; int ret = i2c_p->transfer_single(self, addr, len, buf, flags); if (n > 1) { if (flags & MP_MACHINE_I2C_FLAG_READ) { // Copy data from single buffer to individual ones len = 0; for (size_t i = 0; i < n; ++i) { memcpy(bufs[i].buf, buf + len, bufs[i].len); len += bufs[i].len; } } m_del(uint8_t, buf, len); } return ret; } STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self, uint16_t addr, uint8_t *dest, size_t len, bool stop) { mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; mp_machine_i2c_buf_t buf = {.len = len, .buf = dest}; unsigned int flags = MP_MACHINE_I2C_FLAG_READ | (stop ? MP_MACHINE_I2C_FLAG_STOP : 0); return i2c_p->transfer(self, addr, 1, &buf, flags); } STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint8_t *src, size_t len, bool stop) { mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; mp_machine_i2c_buf_t buf = {.len = len, .buf = (uint8_t*)src}; unsigned int flags = stop ? MP_MACHINE_I2C_FLAG_STOP : 0; return i2c_p->transfer(self, addr, 1, &buf, flags); } /******************************************************************************/ // MicroPython bindings for I2C STATIC void machine_i2c_obj_init_helper(machine_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_scl, ARG_sda, ARG_freq, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj); self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj); self->us_timeout = args[ARG_timeout].u_int; mp_hal_i2c_init(self, args[ARG_freq].u_int); } STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check the id argument, if given if (n_args > 0) { if (args[0] != MP_OBJ_NEW_SMALL_INT(-1)) { #if defined(MICROPY_PY_MACHINE_I2C_MAKE_NEW) // dispatch to port-specific constructor extern mp_obj_t MICROPY_PY_MACHINE_I2C_MAKE_NEW(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); return MICROPY_PY_MACHINE_I2C_MAKE_NEW(type, n_args, n_kw, args); #else mp_raise_ValueError("invalid I2C peripheral"); #endif } --n_args; ++args; } // create new soft I2C object machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t); self->base.type = &machine_i2c_type; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); machine_i2c_obj_init_helper(self, n_args, args, &kw_args); return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t machine_i2c_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_i2c_obj_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 1, machine_i2c_obj_init); STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t list = mp_obj_new_list(0, NULL); // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved for (int addr = 0x08; addr < 0x78; ++addr) { int ret = mp_machine_i2c_writeto(self, addr, NULL, 0, true); if (ret == 0) { mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); } } return list; } MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; if (i2c_p->start == NULL) { mp_raise_msg(&mp_type_OSError, "I2C operation not supported"); } int ret = i2c_p->start(self); if (ret != 0) { mp_raise_OSError(-ret); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start); STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; if (i2c_p->stop == NULL) { mp_raise_msg(&mp_type_OSError, "I2C operation not supported"); } int ret = i2c_p->stop(self); if (ret != 0) { mp_raise_OSError(-ret); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop); STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; if (i2c_p->read == NULL) { mp_raise_msg(&mp_type_OSError, "I2C operation not supported"); } // get the buffer to read into mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); // work out if we want to send a nack at the end bool nack = (n_args == 2) ? true : mp_obj_is_true(args[2]); // do the read int ret = i2c_p->read(self, bufinfo.buf, bufinfo.len, nack); if (ret != 0) { mp_raise_OSError(-ret); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_readinto); STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; if (i2c_p->write == NULL) { mp_raise_msg(&mp_type_OSError, "I2C operation not supported"); } // get the buffer to write from mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); // do the write int ret = i2c_p->write(self, bufinfo.buf, bufinfo.len); if (ret < 0) { mp_raise_OSError(-ret); } // return number of acks received return MP_OBJ_NEW_SMALL_INT(ret); } MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write); STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); mp_int_t addr = mp_obj_get_int(args[1]); vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(args[2])); bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t*)vstr.buf, vstr.len, stop); if (ret < 0) { mp_raise_OSError(-ret); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom); STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); mp_int_t addr = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); int ret = mp_machine_i2c_readfrom(self, addr, bufinfo.buf, bufinfo.len, stop); if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine_i2c_readfrom_into); STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); mp_int_t addr = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); int ret = mp_machine_i2c_writeto(self, addr, bufinfo.buf, bufinfo.len, stop); if (ret < 0) { mp_raise_OSError(-ret); } // return number of acks received return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto); STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); mp_int_t addr = mp_obj_get_int(args[1]); // Get the list of data buffer(s) to write size_t nitems; const mp_obj_t *items; mp_obj_get_array(args[2], &nitems, (mp_obj_t**)&items); // Get the stop argument bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); // Extract all buffer data, skipping zero-length buffers size_t alloc = nitems == 0 ? 1 : nitems; size_t nbufs = 0; mp_machine_i2c_buf_t *bufs = mp_local_alloc(alloc * sizeof(mp_machine_i2c_buf_t)); for (; nitems--; ++items) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ); if (bufinfo.len > 0) { bufs[nbufs].len = bufinfo.len; bufs[nbufs++].buf = bufinfo.buf; } } // Make sure there is at least one buffer, empty if needed if (nbufs == 0) { bufs[0].len = 0; bufs[0].buf = NULL; nbufs = 1; } // Do the I2C transfer mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0); mp_local_free(bufs); if (ret < 0) { mp_raise_OSError(-ret); } // Return number of acks received return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto); STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); uint8_t memaddr_buf[4]; size_t memaddr_len = 0; for (int16_t i = addrsize - 8; i >= 0; i -= 8) { memaddr_buf[memaddr_len++] = memaddr >> i; } int ret = mp_machine_i2c_writeto(self, addr, memaddr_buf, memaddr_len, false); if (ret != memaddr_len) { // must generate STOP mp_machine_i2c_writeto(self, addr, NULL, 0, true); return ret; } return mp_machine_i2c_readfrom(self, addr, buf, len, true); } STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); // Create buffer with memory address size_t memaddr_len = 0; uint8_t memaddr_buf[4]; for (int16_t i = addrsize - 8; i >= 0; i -= 8) { memaddr_buf[memaddr_len++] = memaddr >> i; } // Create partial write buffers mp_machine_i2c_buf_t bufs[2] = { {.len = memaddr_len, .buf = memaddr_buf}, {.len = len, .buf = (uint8_t*)buf}, }; // Do I2C transfer mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; return i2c_p->transfer(self, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP); } STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, }; STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize }; mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); // create the buffer to store data into vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj)); // do the transfer int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int, args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len); if (ret < 0) { mp_raise_OSError(-ret); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem); STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); // get the buffer to store data into mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); // do the transfer int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int, args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len); if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into); STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); // get the buffer to write the data from mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); // do the transfer int ret = write_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int, args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len); if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem); STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2c_init_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) }, // primitive I2C operations { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_i2c_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_i2c_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_i2c_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) }, // standard bus operations { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) }, { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) }, { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) }, { MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) }, // memory operations { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) }, { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) }, { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) }, }; MP_DEFINE_CONST_DICT(mp_machine_soft_i2c_locals_dict, machine_i2c_locals_dict_table); int mp_machine_soft_i2c_read(mp_obj_base_t *self_in, uint8_t *dest, size_t len, bool nack) { machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in; while (len--) { int ret = mp_hal_i2c_read_byte(self, dest++, nack && (len == 0)); if (ret != 0) { return ret; } } return 0; // success } int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t len) { machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in; int num_acks = 0; while (len--) { int ret = mp_hal_i2c_write_byte(self, *src++); if (ret < 0) { return ret; } else if (ret != 0) { // nack received, stop sending break; } ++num_acks; } return num_acks; } STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = { .start = (int(*)(mp_obj_base_t*))mp_hal_i2c_start, .stop = (int(*)(mp_obj_base_t*))mp_hal_i2c_stop, .read = mp_machine_soft_i2c_read, .write = mp_machine_soft_i2c_write, .transfer = mp_machine_soft_i2c_transfer, }; const mp_obj_type_t machine_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, .make_new = machine_i2c_make_new, .protocol = &mp_machine_soft_i2c_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict, }; #endif // MICROPY_PY_MACHINE_I2C micropython-1.12/extmod/machine_i2c.h000066400000000000000000000054241357706137100176410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H #define MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H #include "py/obj.h" #define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write #define MP_MACHINE_I2C_FLAG_STOP (0x02) typedef struct _mp_machine_i2c_buf_t { size_t len; uint8_t *buf; } mp_machine_i2c_buf_t; // I2C protocol // the first 4 methods can be NULL, meaning operation is not supported // transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor typedef struct _mp_machine_i2c_p_t { int (*start)(mp_obj_base_t *obj); int (*stop)(mp_obj_base_t *obj); int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack); int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len); int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags); } mp_machine_i2c_p_t; typedef struct _mp_machine_soft_i2c_obj_t { mp_obj_base_t base; uint32_t us_delay; uint32_t us_timeout; mp_hal_pin_obj_t scl; mp_hal_pin_obj_t sda; } mp_machine_soft_i2c_obj_t; extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_dict_t mp_machine_soft_i2c_locals_dict; int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); #endif // MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H micropython-1.12/extmod/machine_mem.c000066400000000000000000000101541357706137100177310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "extmod/machine_mem.h" #if MICROPY_PY_MACHINE // If you wish to override the functions for mapping the machine_mem read/write // address, then add a #define for MICROPY_MACHINE_MEM_GET_READ_ADDR and/or // MICROPY_MACHINE_MEM_GET_WRITE_ADDR in your mpconfigport.h. Since the // prototypes are identical, it is allowable for both of the macros to evaluate // the to same function. // // It is expected that the modmachine.c file for a given port will provide the // implementations, if the default implementation isn't used. #if !defined(MICROPY_MACHINE_MEM_GET_READ_ADDR) || !defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR) STATIC uintptr_t machine_mem_get_addr(mp_obj_t addr_o, uint align) { uintptr_t addr = mp_obj_int_get_truncated(addr_o); if ((addr & (align - 1)) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align)); } return addr; } #if !defined(MICROPY_MACHINE_MEM_GET_READ_ADDR) #define MICROPY_MACHINE_MEM_GET_READ_ADDR machine_mem_get_addr #endif #if !defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR) #define MICROPY_MACHINE_MEM_GET_WRITE_ADDR machine_mem_get_addr #endif #endif STATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "<%u-bit memory>", 8 * self->elem_size); } STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { // TODO support slice index to read/write multiple values at once machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in); if (value == MP_OBJ_NULL) { // delete return MP_OBJ_NULL; // op not supported } else if (value == MP_OBJ_SENTINEL) { // load uintptr_t addr = MICROPY_MACHINE_MEM_GET_READ_ADDR(index, self->elem_size); uint32_t val; switch (self->elem_size) { case 1: val = (*(uint8_t*)addr); break; case 2: val = (*(uint16_t*)addr); break; default: val = (*(uint32_t*)addr); break; } return mp_obj_new_int(val); } else { // store uintptr_t addr = MICROPY_MACHINE_MEM_GET_WRITE_ADDR(index, self->elem_size); uint32_t val = mp_obj_get_int_truncated(value); switch (self->elem_size) { case 1: (*(uint8_t*)addr) = val; break; case 2: (*(uint16_t*)addr) = val; break; default: (*(uint32_t*)addr) = val; break; } return mp_const_none; } } const mp_obj_type_t machine_mem_type = { { &mp_type_type }, .name = MP_QSTR_mem, .print = machine_mem_print, .subscr = machine_mem_subscr, }; const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1}; const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2}; const machine_mem_obj_t machine_mem32_obj = {{&machine_mem_type}, 4}; #endif // MICROPY_PY_MACHINE micropython-1.12/extmod/machine_mem.h000066400000000000000000000036501357706137100177410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H #define MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H #include "py/obj.h" typedef struct _machine_mem_obj_t { mp_obj_base_t base; unsigned elem_size; // in bytes } machine_mem_obj_t; extern const mp_obj_type_t machine_mem_type; extern const machine_mem_obj_t machine_mem8_obj; extern const machine_mem_obj_t machine_mem16_obj; extern const machine_mem_obj_t machine_mem32_obj; #if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR) uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align); #endif #if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR) uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align); #endif #endif // MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H micropython-1.12/extmod/machine_pinbase.c000066400000000000000000000055631357706137100206040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_MACHINE #include "py/obj.h" #include "py/runtime.h" #include "extmod/virtpin.h" #include "extmod/machine_pinbase.h" // PinBase class // As this is abstract class, its instance is null. // But there should be an instance, as the rest of instance code // expects that there will be concrete object for inheritance. typedef struct _mp_pinbase_t { mp_obj_base_t base; } mp_pinbase_t; STATIC const mp_pinbase_t pinbase_singleton = { .base = { &machine_pinbase_type }, }; STATIC mp_obj_t pinbase_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type; (void)n_args; (void)n_kw; (void)args; return MP_OBJ_FROM_PTR(&pinbase_singleton); } mp_uint_t pinbase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode); mp_uint_t pinbase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; switch (request) { case MP_PIN_READ: { mp_obj_t dest[2]; mp_load_method(obj, MP_QSTR_value, dest); return mp_obj_get_int(mp_call_method_n_kw(0, 0, dest)); } case MP_PIN_WRITE: { mp_obj_t dest[3]; mp_load_method(obj, MP_QSTR_value, dest); dest[2] = (arg == 0 ? mp_const_false : mp_const_true); mp_call_method_n_kw(1, 0, dest); return 0; } } return -1; } STATIC const mp_pin_p_t pinbase_pin_p = { .ioctl = pinbase_ioctl, }; const mp_obj_type_t machine_pinbase_type = { { &mp_type_type }, .name = MP_QSTR_PinBase, .make_new = pinbase_make_new, .protocol = &pinbase_pin_p, }; #endif // MICROPY_PY_MACHINE micropython-1.12/extmod/machine_pinbase.h000066400000000000000000000026501357706137100206030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H #define MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H #include "py/obj.h" extern const mp_obj_type_t machine_pinbase_type; #endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H micropython-1.12/extmod/machine_pulse.c000066400000000000000000000046351357706137100203120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/machine_pulse.h" #if MICROPY_PY_MACHINE_PULSE MP_WEAK mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { mp_uint_t start = mp_hal_ticks_us(); while (mp_hal_pin_read(pin) != pulse_level) { if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) { return (mp_uint_t)-2; } } start = mp_hal_ticks_us(); while (mp_hal_pin_read(pin) == pulse_level) { if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) { return (mp_uint_t)-1; } } return mp_hal_ticks_us() - start; } STATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) { mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(args[0]); int level = 0; if (mp_obj_is_true(args[1])) { level = 1; } mp_uint_t timeout_us = 1000000; if (n_args > 2) { timeout_us = mp_obj_get_int(args[2]); } mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us); // May return -1 or -2 in case of timeout return mp_obj_new_int(us); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_); #endif micropython-1.12/extmod/machine_pulse.h000066400000000000000000000030501357706137100203050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H #define MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H #include "py/obj.h" #include "py/mphal.h" mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj); #endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H micropython-1.12/extmod/machine_signal.c000066400000000000000000000141271357706137100204340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_MACHINE #include #include "py/obj.h" #include "py/runtime.h" #include "extmod/virtpin.h" #include "extmod/machine_signal.h" // Signal class typedef struct _machine_signal_t { mp_obj_base_t base; mp_obj_t pin; bool invert; } machine_signal_t; STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_t pin; bool invert = false; #if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW) mp_pin_p_t *pin_p = NULL; if (n_args > 0 && mp_obj_is_obj(args[0])) { mp_obj_base_t *pin_base = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); pin_p = (mp_pin_p_t*)pin_base->type->protocol; } if (pin_p == NULL) { // If first argument isn't a Pin-like object, we filter out "invert" // from keyword arguments and pass them all to the exported Pin // constructor to create one. mp_obj_t *pin_args = mp_local_alloc((n_args + n_kw * 2) * sizeof(mp_obj_t)); memcpy(pin_args, args, n_args * sizeof(mp_obj_t)); const mp_obj_t *src = args + n_args; mp_obj_t *dst = pin_args + n_args; mp_obj_t *sig_value = NULL; for (size_t cnt = n_kw; cnt; cnt--) { if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) { invert = mp_obj_is_true(src[1]); n_kw--; } else { *dst++ = *src; *dst++ = src[1]; } if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_value)) { // Value is pertained to Signal, so we should invert // it for Pin if needed, and we should do it only when // inversion status is guaranteedly known. sig_value = dst - 1; } src += 2; } if (invert && sig_value != NULL) { *sig_value = mp_obj_is_true(*sig_value) ? MP_OBJ_NEW_SMALL_INT(0) : MP_OBJ_NEW_SMALL_INT(1); } // Here we pass NULL as a type, hoping that mp_pin_make_new() // will just ignore it as set a concrete type. If not, we'd need // to expose port's "default" pin type too. pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args); mp_local_free(pin_args); } else #endif // Otherwise there should be 1 or 2 args { if (n_args == 1) { pin = args[0]; if (n_kw == 0) { } else if (n_kw == 1 && args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) { invert = mp_obj_is_true(args[2]); } else { goto error; } } else { error: mp_raise_TypeError(NULL); } } machine_signal_t *o = m_new_obj(machine_signal_t); o->base.type = type; o->pin = pin; o->invert = invert; return MP_OBJ_FROM_PTR(o); } STATIC mp_uint_t signal_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; machine_signal_t *self = MP_OBJ_TO_PTR(self_in); switch (request) { case MP_PIN_READ: { return mp_virtual_pin_read(self->pin) ^ self->invert; } case MP_PIN_WRITE: { mp_virtual_pin_write(self->pin, arg ^ self->invert); return 0; } } return -1; } // fast method for getting/setting signal value STATIC mp_obj_t signal_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); if (n_args == 0) { // get pin return MP_OBJ_NEW_SMALL_INT(mp_virtual_pin_read(self_in)); } else { // set pin mp_virtual_pin_write(self_in, mp_obj_is_true(args[0])); return mp_const_none; } } STATIC mp_obj_t signal_value(size_t n_args, const mp_obj_t *args) { return signal_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(signal_value_obj, 1, 2, signal_value); STATIC mp_obj_t signal_on(mp_obj_t self_in) { mp_virtual_pin_write(self_in, 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(signal_on_obj, signal_on); STATIC mp_obj_t signal_off(mp_obj_t self_in) { mp_virtual_pin_write(self_in, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(signal_off_obj, signal_off); STATIC const mp_rom_map_elem_t signal_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&signal_value_obj) }, { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&signal_on_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&signal_off_obj) }, }; STATIC MP_DEFINE_CONST_DICT(signal_locals_dict, signal_locals_dict_table); STATIC const mp_pin_p_t signal_pin_p = { .ioctl = signal_ioctl, }; const mp_obj_type_t machine_signal_type = { { &mp_type_type }, .name = MP_QSTR_Signal, .make_new = signal_make_new, .call = signal_call, .protocol = &signal_pin_p, .locals_dict = (void*)&signal_locals_dict, }; #endif // MICROPY_PY_MACHINE micropython-1.12/extmod/machine_signal.h000066400000000000000000000026441357706137100204420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H #define MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H #include "py/obj.h" extern const mp_obj_type_t machine_signal_type; #endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H micropython-1.12/extmod/machine_spi.c000066400000000000000000000274441357706137100177600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "extmod/machine_spi.h" #if MICROPY_PY_MACHINE_SPI // if a port didn't define MSB/LSB constants then provide them #ifndef MICROPY_PY_MACHINE_SPI_MSB #define MICROPY_PY_MACHINE_SPI_MSB (0) #define MICROPY_PY_MACHINE_SPI_LSB (1) #endif /******************************************************************************/ // MicroPython bindings for generic machine.SPI STATIC mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check the id argument, if given if (n_args > 0) { if (args[0] != MP_OBJ_NEW_SMALL_INT(-1)) { #if defined(MICROPY_PY_MACHINE_SPI_MAKE_NEW) // dispatch to port-specific constructor extern mp_obj_t MICROPY_PY_MACHINE_SPI_MAKE_NEW(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); return MICROPY_PY_MACHINE_SPI_MAKE_NEW(type, n_args, n_kw, args); #else mp_raise_ValueError("invalid SPI peripheral"); #endif } --n_args; ++args; } // software SPI return mp_machine_soft_spi_make_new(type, n_args, n_kw, args); } STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol; spi_p->init(s, n_args - 1, args + 1, kw_args); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init); STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) { mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self); mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol; if (spi_p->deinit != NULL) { spi_p->deinit(s); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit); STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t len, const void *src, void *dest) { mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self); mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol; spi_p->transfer(s, len, src, dest); } STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) { vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(args[1])); memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len); mp_machine_spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read); STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); memset(bufinfo.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, bufinfo.len); mp_machine_spi_transfer(args[0], bufinfo.len, bufinfo.buf, bufinfo.buf); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto); STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self, mp_obj_t wr_buf) { mp_buffer_info_t src; mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, NULL); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write); STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self, mp_obj_t wr_buf, mp_obj_t rd_buf) { mp_buffer_info_t src; mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); mp_buffer_info_t dest; mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE); if (src.len != dest.len) { mp_raise_ValueError("buffers must be the same length"); } mp_machine_spi_transfer(self, src.len, src.buf, dest.buf); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto); STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_spi_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_MSB) }, { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_LSB) }, }; MP_DEFINE_CONST_DICT(mp_machine_spi_locals_dict, machine_spi_locals_dict_table); /******************************************************************************/ // Implementation of soft SPI STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) { #ifdef MICROPY_HW_SOFTSPI_MIN_DELAY if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) { return MICROPY_HW_SOFTSPI_MAX_BAUDRATE; } else #endif { return 500000 / delay_half; } } STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) { #ifdef MICROPY_HW_SOFTSPI_MIN_DELAY if (baudrate >= MICROPY_HW_SOFTSPI_MAX_BAUDRATE) { return MICROPY_HW_SOFTSPI_MIN_DELAY; } else #endif { uint32_t delay_half = 500000 / baudrate; // round delay_half up so that: actual_baudrate <= requested_baudrate if (500000 % baudrate != 0) { delay_half += 1; } return delay_half; } } STATIC void mp_machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "SoftSPI(baudrate=%u, polarity=%u, phase=%u," " sck=" MP_HAL_PIN_FMT ", mosi=" MP_HAL_PIN_FMT ", miso=" MP_HAL_PIN_FMT ")", baudrate_from_delay_half(self->spi.delay_half), self->spi.polarity, self->spi.phase, mp_hal_pin_name(self->spi.sck), mp_hal_pin_name(self->spi.mosi), mp_hal_pin_name(self->spi.miso)); } STATIC mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso }; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // create new object mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t); self->base.type = &mp_machine_soft_spi_type; // set parameters self->spi.delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int); self->spi.polarity = args[ARG_polarity].u_int; self->spi.phase = args[ARG_phase].u_int; if (args[ARG_bits].u_int != 8) { mp_raise_ValueError("bits must be 8"); } if (args[ARG_firstbit].u_int != MICROPY_PY_MACHINE_SPI_MSB) { mp_raise_ValueError("firstbit must be MSB"); } if (args[ARG_sck].u_obj == MP_OBJ_NULL || args[ARG_mosi].u_obj == MP_OBJ_NULL || args[ARG_miso].u_obj == MP_OBJ_NULL) { mp_raise_ValueError("must specify all of sck/mosi/miso"); } self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj); self->spi.mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj); self->spi.miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj); // configure bus mp_soft_spi_ioctl(&self->spi, MP_SPI_IOCTL_INIT); return MP_OBJ_FROM_PTR(self); } STATIC void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in; enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso }; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_baudrate].u_int != -1) { self->spi.delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int); } if (args[ARG_polarity].u_int != -1) { self->spi.polarity = args[ARG_polarity].u_int; } if (args[ARG_phase].u_int != -1) { self->spi.phase = args[ARG_phase].u_int; } if (args[ARG_sck].u_obj != MP_OBJ_NULL) { self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj); } if (args[ARG_mosi].u_obj != MP_OBJ_NULL) { self->spi.mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj); } if (args[ARG_miso].u_obj != MP_OBJ_NULL) { self->spi.miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj); } // configure bus mp_soft_spi_ioctl(&self->spi, MP_SPI_IOCTL_INIT); } STATIC void mp_machine_soft_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in; mp_soft_spi_transfer(&self->spi, len, src, dest); } const mp_machine_spi_p_t mp_machine_soft_spi_p = { .init = mp_machine_soft_spi_init, .deinit = NULL, .transfer = mp_machine_soft_spi_transfer, }; const mp_obj_type_t mp_machine_soft_spi_type = { { &mp_type_type }, .name = MP_QSTR_SoftSPI, .print = mp_machine_soft_spi_print, .make_new = mp_machine_spi_make_new, // delegate to master constructor .protocol = &mp_machine_soft_spi_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_spi_locals_dict, }; #endif // MICROPY_PY_MACHINE_SPI micropython-1.12/extmod/machine_spi.h000066400000000000000000000045451357706137100177620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H #define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H #include "py/obj.h" #include "py/mphal.h" #include "drivers/bus/spi.h" // SPI protocol typedef struct _mp_machine_spi_p_t { void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); void (*deinit)(mp_obj_base_t *obj); // can be NULL void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest); } mp_machine_spi_p_t; typedef struct _mp_machine_soft_spi_obj_t { mp_obj_base_t base; mp_soft_spi_obj_t spi; } mp_machine_soft_spi_obj_t; extern const mp_machine_spi_p_t mp_machine_soft_spi_p; extern const mp_obj_type_t mp_machine_soft_spi_type; extern const mp_obj_dict_t mp_machine_spi_locals_dict; mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj); MP_DECLARE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj); #endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H micropython-1.12/extmod/misc.h000066400000000000000000000035671357706137100164410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2016 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MISC_H #define MICROPY_INCLUDED_EXTMOD_MISC_H // This file contains cumulative declarations for extmod/ . #include #include "py/runtime.h" MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj); #if MICROPY_PY_OS_DUPTERM bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream); uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags); int mp_uos_dupterm_rx_chr(void); void mp_uos_dupterm_tx_strn(const char *str, size_t len); void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc); #else #define mp_uos_dupterm_tx_strn(s, l) #endif #endif // MICROPY_INCLUDED_EXTMOD_MISC_H micropython-1.12/extmod/modbluetooth.c000066400000000000000000001331111357706137100201730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Ayke van Laethem * Copyright (c) 2019 Jim Mussared * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/binary.h" #include "py/misc.h" #include "py/mperrno.h" #include "py/obj.h" #include "py/objstr.h" #include "py/objarray.h" #include "py/qstr.h" #include "py/runtime.h" #include "py/mphal.h" #include "extmod/modbluetooth.h" #include #if MICROPY_PY_BLUETOOTH #if !MICROPY_ENABLE_SCHEDULER #error modbluetooth requires MICROPY_ENABLE_SCHEDULER #endif #define MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS 2000 #define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5 // This formula is intended to allow queuing the data of a large characteristic // while still leaving room for a couple of normal (small, fixed size) events. #define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN(ringbuf_size) (MAX((int)((ringbuf_size) / 2), (int)(ringbuf_size) - 64)) STATIC const mp_obj_type_t bluetooth_ble_type; STATIC const mp_obj_type_t bluetooth_uuid_type; typedef struct { mp_obj_base_t base; mp_obj_t irq_handler; uint16_t irq_trigger; bool irq_scheduled; mp_obj_t irq_data_tuple; uint8_t irq_data_addr_bytes[6]; uint16_t irq_data_data_alloc; uint8_t *irq_data_data_bytes; mp_obj_str_t irq_data_addr; mp_obj_str_t irq_data_data; mp_obj_bluetooth_uuid_t irq_data_uuid; ringbuf_t ringbuf; } mp_obj_bluetooth_ble_t; // TODO: this seems like it could be generic? STATIC mp_obj_t bluetooth_handle_errno(int err) { if (err != 0) { mp_raise_OSError(err); } return mp_const_none; } // ---------------------------------------------------------------------------- // UUID object // ---------------------------------------------------------------------------- STATIC mp_obj_t bluetooth_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_obj_bluetooth_uuid_t *self = m_new_obj(mp_obj_bluetooth_uuid_t); self->base.type = &bluetooth_uuid_type; if (mp_obj_is_int(all_args[0])) { self->type = MP_BLUETOOTH_UUID_TYPE_16; mp_int_t value = mp_obj_get_int(all_args[0]); if (value > 65535) { mp_raise_ValueError("invalid UUID"); } self->data[0] = value & 0xff; self->data[1] = (value >> 8) & 0xff; } else { mp_buffer_info_t uuid_bufinfo = {0}; mp_get_buffer_raise(all_args[0], &uuid_bufinfo, MP_BUFFER_READ); if (uuid_bufinfo.len == 2 || uuid_bufinfo.len == 4 || uuid_bufinfo.len == 16) { // Bytes data -- infer UUID type from length and copy data. self->type = uuid_bufinfo.len; memcpy(self->data, uuid_bufinfo.buf, self->type); } else { // Assume UUID string (e.g. '6E400001-B5A3-F393-E0A9-E50E24DCCA9E') self->type = MP_BLUETOOTH_UUID_TYPE_128; int uuid_i = 32; for (int i = 0; i < uuid_bufinfo.len; i++) { char c = ((char*)uuid_bufinfo.buf)[i]; if (c == '-') { continue; } if (!unichar_isxdigit(c)) { mp_raise_ValueError("invalid char in UUID"); } c = unichar_xdigit_value(c); uuid_i--; if (uuid_i < 0) { mp_raise_ValueError("UUID too long"); } if (uuid_i % 2 == 0) { // lower nibble self->data[uuid_i/2] |= c; } else { // upper nibble self->data[uuid_i/2] = c << 4; } } if (uuid_i > 0) { mp_raise_ValueError("UUID too short"); } } } return self; } STATIC mp_obj_t bluetooth_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_HASH: { // Use the QSTR hash function. return MP_OBJ_NEW_SMALL_INT(qstr_compute_hash(self->data, self->type)); } default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t bluetooth_uuid_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { if (!mp_obj_is_type(rhs_in, &bluetooth_uuid_type)) { return MP_OBJ_NULL; } mp_obj_bluetooth_uuid_t *lhs = MP_OBJ_TO_PTR(lhs_in); mp_obj_bluetooth_uuid_t *rhs = MP_OBJ_TO_PTR(rhs_in); switch (op) { case MP_BINARY_OP_EQUAL: case MP_BINARY_OP_LESS: case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: if (lhs->type == rhs->type) { return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs->data, lhs->type, rhs->data, rhs->type)); } else { return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(lhs->type), MP_OBJ_NEW_SMALL_INT(rhs->type)); } default: return MP_OBJ_NULL; // op not supported } } STATIC void bluetooth_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "UUID%u(%s", self->type * 8, self->type <= 4 ? "0x" : "'"); for (int i = 0; i < self->type; ++i) { if (i == 4 || i == 6 || i == 8 || i == 10) { mp_printf(print, "-"); } mp_printf(print, "%02x", self->data[self->type - 1 - i]); } if (self->type == MP_BLUETOOTH_UUID_TYPE_128) { mp_printf(print, "'"); } mp_printf(print, ")"); } mp_int_t bluetooth_uuid_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); if (flags != MP_BUFFER_READ) { return 1; } bufinfo->buf = self->data; bufinfo->len = self->type; bufinfo->typecode = 'B'; return 0; } #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC void ringbuf_put_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) { assert(ringbuf_free(ringbuf) >= uuid->type + 1); ringbuf_put(ringbuf, uuid->type); for (int i = 0; i < uuid->type; ++i) { ringbuf_put(ringbuf, uuid->data[i]); } } STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) { assert(ringbuf_avail(ringbuf) >= 1); uuid->type = ringbuf_get(ringbuf); assert(ringbuf_avail(ringbuf) >= uuid->type); for (int i = 0; i < uuid->type; ++i) { uuid->data[i] = ringbuf_get(ringbuf); } } #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC const mp_obj_type_t bluetooth_uuid_type = { { &mp_type_type }, .name = MP_QSTR_UUID, .make_new = bluetooth_uuid_make_new, .unary_op = bluetooth_uuid_unary_op, .binary_op = bluetooth_uuid_binary_op, .locals_dict = NULL, .print = bluetooth_uuid_print, .buffer_p = { .get_buffer = bluetooth_uuid_get_buffer }, }; // ---------------------------------------------------------------------------- // Bluetooth object: General // ---------------------------------------------------------------------------- STATIC mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { if (MP_STATE_VM(bluetooth) == MP_OBJ_NULL) { mp_obj_bluetooth_ble_t *o = m_new0(mp_obj_bluetooth_ble_t, 1); o->base.type = &bluetooth_ble_type; o->irq_handler = mp_const_none; o->irq_trigger = 0; // Pre-allocate the event data tuple to prevent needing to allocate in the IRQ handler. o->irq_data_tuple = mp_obj_new_tuple(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN, NULL); // Pre-allocated buffers for address, payload and uuid. o->irq_data_addr.base.type = &mp_type_bytes; o->irq_data_addr.data = o->irq_data_addr_bytes; o->irq_data_data_alloc = MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN(MICROPY_PY_BLUETOOTH_RINGBUF_SIZE); o->irq_data_data.base.type = &mp_type_bytes; o->irq_data_data.data = m_new(uint8_t, o->irq_data_data_alloc); o->irq_data_uuid.base.type = &bluetooth_uuid_type; // Allocate the default ringbuf. ringbuf_alloc(&o->ringbuf, MICROPY_PY_BLUETOOTH_RINGBUF_SIZE); MP_STATE_VM(bluetooth) = MP_OBJ_FROM_PTR(o); } return MP_STATE_VM(bluetooth); } STATIC mp_obj_t bluetooth_ble_active(size_t n_args, const mp_obj_t *args) { if (n_args == 2) { // Boolean enable/disable argument supplied, set current state. if (mp_obj_is_true(args[1])) { int err = mp_bluetooth_init(); if (err != 0) { mp_raise_OSError(err); } } else { mp_bluetooth_deinit(); } } // Return current state. return mp_obj_new_bool(mp_bluetooth_is_enabled()); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_active_obj, 1, 2, bluetooth_ble_active); STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { mp_obj_bluetooth_ble_t *self = MP_OBJ_TO_PTR(args[0]); if (kwargs->used == 0) { // Get config value if (n_args != 2) { mp_raise_TypeError("must query one param"); } switch (mp_obj_str_get_qstr(args[1])) { case MP_QSTR_mac: { uint8_t addr[6]; mp_bluetooth_get_device_addr(addr); return mp_obj_new_bytes(addr, MP_ARRAY_SIZE(addr)); } default: mp_raise_ValueError("unknown config param"); } } else { // Set config value(s) if (n_args != 1) { mp_raise_TypeError("can't specify pos and kw args"); } for (size_t i = 0; i < kwargs->alloc; ++i) { if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { mp_map_elem_t *e = &kwargs->table[i]; switch (mp_obj_str_get_qstr(e->key)) { case MP_QSTR_rxbuf: { // Determine new buffer sizes mp_int_t ringbuf_alloc = mp_obj_get_int(e->value); if (ringbuf_alloc < 16 || ringbuf_alloc > 0xffff) { mp_raise_ValueError(NULL); } size_t irq_data_alloc = MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN(ringbuf_alloc); // Allocate new buffers uint8_t *ringbuf = m_new(uint8_t, ringbuf_alloc); uint8_t *irq_data = m_new(uint8_t, irq_data_alloc); // Get old buffer sizes and pointers uint8_t *old_ringbuf_buf = self->ringbuf.buf; size_t old_ringbuf_alloc = self->ringbuf.size; uint8_t *old_irq_data_buf = (uint8_t*)self->irq_data_data.data; size_t old_irq_data_alloc = self->irq_data_data_alloc; // Atomically update the ringbuf and irq data MICROPY_PY_BLUETOOTH_ENTER self->ringbuf.size = ringbuf_alloc; self->ringbuf.buf = ringbuf; self->ringbuf.iget = 0; self->ringbuf.iput = 0; self->irq_data_data_alloc = irq_data_alloc; self->irq_data_data.data = irq_data; MICROPY_PY_BLUETOOTH_EXIT // Free old buffers m_del(uint8_t, old_ringbuf_buf, old_ringbuf_alloc); m_del(uint8_t, old_irq_data_buf, old_irq_data_alloc); break; } default: mp_raise_ValueError("unknown config param"); } } } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_config_obj, 1, bluetooth_ble_config); STATIC mp_obj_t bluetooth_ble_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_handler, ARG_trigger }; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ|MP_ARG_REQUIRED, {.u_obj = mp_const_none} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = MP_BLUETOOTH_IRQ_ALL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_obj_t callback = args[ARG_handler].u_obj; if (callback != mp_const_none && !mp_obj_is_callable(callback)) { mp_raise_ValueError("invalid callback"); } // Update the callback. MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t* o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); o->irq_handler = callback; o->irq_trigger = args[ARG_trigger].u_int; MICROPY_PY_BLUETOOTH_EXIT return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_irq_obj, 1, bluetooth_ble_irq); // ---------------------------------------------------------------------------- // Bluetooth object: GAP // ---------------------------------------------------------------------------- STATIC mp_obj_t bluetooth_ble_gap_advertise(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_interval_us, ARG_adv_data, ARG_resp_data, ARG_connectable }; static const mp_arg_t allowed_args[] = { { MP_QSTR_interval_us, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(500000)} }, { MP_QSTR_adv_data, MP_ARG_OBJ, {.u_obj = mp_const_none } }, { MP_QSTR_resp_data, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, { MP_QSTR_connectable, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_true } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_interval_us].u_obj == mp_const_none) { mp_bluetooth_gap_advertise_stop(); return mp_const_none; } mp_int_t interval_us = mp_obj_get_int(args[ARG_interval_us].u_obj); bool connectable = mp_obj_is_true(args[ARG_connectable].u_obj); mp_buffer_info_t adv_bufinfo = {0}; if (args[ARG_adv_data].u_obj != mp_const_none) { mp_get_buffer_raise(args[ARG_adv_data].u_obj, &adv_bufinfo, MP_BUFFER_READ); } mp_buffer_info_t resp_bufinfo = {0}; if (args[ARG_resp_data].u_obj != mp_const_none) { mp_get_buffer_raise(args[ARG_resp_data].u_obj, &resp_bufinfo, MP_BUFFER_READ); } return bluetooth_handle_errno(mp_bluetooth_gap_advertise_start(connectable, interval_us, adv_bufinfo.buf, adv_bufinfo.len, resp_bufinfo.buf, resp_bufinfo.len)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_gap_advertise_obj, 1, bluetooth_ble_gap_advertise); STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t characteristics_in, uint16_t **handles, size_t *num_handles) { if (!mp_obj_is_type(uuid_in, &bluetooth_uuid_type)) { mp_raise_ValueError("invalid service UUID"); } mp_obj_bluetooth_uuid_t *service_uuid = MP_OBJ_TO_PTR(uuid_in); mp_obj_t len_in = mp_obj_len(characteristics_in); size_t len = mp_obj_get_int(len_in); mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(characteristics_in, &iter_buf); mp_obj_t characteristic_obj; // Lists of characteristic uuids and flags. mp_obj_bluetooth_uuid_t **characteristic_uuids = m_new(mp_obj_bluetooth_uuid_t*, len); uint8_t *characteristic_flags = m_new(uint8_t, len); // Flattened list of descriptor uuids and flags. Grows (realloc) as more descriptors are encountered. mp_obj_bluetooth_uuid_t **descriptor_uuids = NULL; uint8_t *descriptor_flags = NULL; // How many descriptors in the flattened list per characteristic. uint8_t *num_descriptors = m_new(uint8_t, len); // Inititally allocate enough room for the number of characteristics. // Will be grown to accommodate descriptors as necessary. *num_handles = len; *handles = m_new(uint16_t, *num_handles); // Extract out characteristic uuids & flags. int characteristic_index = 0; // characteristic index. int handle_index = 0; // handle index. int descriptor_index = 0; // descriptor index. while ((characteristic_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { // (uuid, flags, (optional descriptors),) size_t characteristic_len; mp_obj_t *characteristic_items; mp_obj_get_array(characteristic_obj, &characteristic_len, &characteristic_items); if (characteristic_len < 2 || characteristic_len > 3) { mp_raise_ValueError("invalid characteristic tuple"); } mp_obj_t uuid_obj = characteristic_items[0]; if (!mp_obj_is_type(uuid_obj, &bluetooth_uuid_type)) { mp_raise_ValueError("invalid characteristic UUID"); } (*handles)[handle_index++] = 0xffff; // Optional third element, iterable of descriptors. if (characteristic_len >= 3) { mp_obj_t descriptors_len_in = mp_obj_len(characteristic_items[2]); num_descriptors[characteristic_index] = mp_obj_get_int(descriptors_len_in); if (num_descriptors[characteristic_index] == 0) { continue; } // Grow the flattened uuids and flags arrays with this many more descriptors. descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t*, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]); descriptor_flags = m_renew(uint8_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]); // Also grow the handles array. *handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]); mp_obj_iter_buf_t iter_buf_desc; mp_obj_t iterable_desc = mp_getiter(characteristic_items[2], &iter_buf_desc); mp_obj_t descriptor_obj; // Extract out descriptors for this characteristic. while ((descriptor_obj = mp_iternext(iterable_desc)) != MP_OBJ_STOP_ITERATION) { // (uuid, flags,) mp_obj_t *descriptor_items; mp_obj_get_array_fixed_n(descriptor_obj, 2, &descriptor_items); mp_obj_t desc_uuid_obj = descriptor_items[0]; if (!mp_obj_is_type(desc_uuid_obj, &bluetooth_uuid_type)) { mp_raise_ValueError("invalid descriptor UUID"); } descriptor_uuids[descriptor_index] = MP_OBJ_TO_PTR(desc_uuid_obj); descriptor_flags[descriptor_index] = mp_obj_get_int(descriptor_items[1]); ++descriptor_index; (*handles)[handle_index++] = 0xffff; } // Reflect that we've grown the handles array. *num_handles += num_descriptors[characteristic_index]; } characteristic_uuids[characteristic_index] = MP_OBJ_TO_PTR(uuid_obj); characteristic_flags[characteristic_index] = mp_obj_get_int(characteristic_items[1]); ++characteristic_index; } // Add service. return mp_bluetooth_gatts_register_service(service_uuid, characteristic_uuids, characteristic_flags, descriptor_uuids, descriptor_flags, num_descriptors, *handles, len); } STATIC mp_obj_t bluetooth_ble_gatts_register_services(mp_obj_t self_in, mp_obj_t services_in) { mp_obj_t len_in = mp_obj_len(services_in); size_t len = mp_obj_get_int(len_in); mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(services_in, &iter_buf); mp_obj_t service_tuple_obj; mp_obj_tuple_t *result = mp_obj_new_tuple(len, NULL); uint16_t **handles = m_new0(uint16_t*, len); size_t *num_handles = m_new0(size_t, len); // TODO: Add a `append` kwarg (defaulting to False) to make this behavior optional. bool append = false; int err = mp_bluetooth_gatts_register_service_begin(append); if (err != 0) { return bluetooth_handle_errno(err); } int i = 0; while ((service_tuple_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { // (uuid, chars) mp_obj_t *service_items; mp_obj_get_array_fixed_n(service_tuple_obj, 2, &service_items); err = bluetooth_gatts_register_service(service_items[0], service_items[1], &handles[i], &num_handles[i]); if (err != 0) { return bluetooth_handle_errno(err); } ++i; } // On Nimble, this will actually perform the registration, making the handles valid. err = mp_bluetooth_gatts_register_service_end(); if (err != 0) { return bluetooth_handle_errno(err); } // Return tuple of tuple of value handles. // TODO: Also the Generic Access service characteristics? for (i = 0; i < len; ++i) { mp_obj_tuple_t *service_handles = mp_obj_new_tuple(num_handles[i], NULL); for (int j = 0; j < num_handles[i]; ++j) { service_handles->items[j] = MP_OBJ_NEW_SMALL_INT(handles[i][j]); } result->items[i] = MP_OBJ_FROM_PTR(service_handles); } return MP_OBJ_FROM_PTR(result); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gatts_register_services_obj, bluetooth_ble_gatts_register_services); #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) { uint8_t addr_type = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo = {0}; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); if (bufinfo.len != 6) { mp_raise_ValueError("invalid addr"); } mp_int_t scan_duration_ms = MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS; if (n_args == 4) { scan_duration_ms = mp_obj_get_int(args[3]); } int err = mp_bluetooth_gap_peripheral_connect(addr_type, bufinfo.buf, scan_duration_ms); return bluetooth_handle_errno(err); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 3, 4, bluetooth_ble_gap_connect); STATIC mp_obj_t bluetooth_ble_gap_scan(size_t n_args, const mp_obj_t *args) { // Default is indefinite scan, with the NimBLE "background scan" interval and window. mp_int_t duration_ms = 0; mp_int_t interval_us = 1280000; mp_int_t window_us = 11250; if (n_args > 1) { if (args[1] == mp_const_none) { // scan(None) --> stop scan. return bluetooth_handle_errno(mp_bluetooth_gap_scan_stop()); } duration_ms = mp_obj_get_int(args[1]); if (n_args > 2) { interval_us = mp_obj_get_int(args[2]); if (n_args > 3) { window_us = mp_obj_get_int(args[3]); } } } return bluetooth_handle_errno(mp_bluetooth_gap_scan_start(duration_ms, interval_us, window_us)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_scan_obj, 1, 4, bluetooth_ble_gap_scan); #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC mp_obj_t bluetooth_ble_gap_disconnect(mp_obj_t self_in, mp_obj_t conn_handle_in) { uint16_t conn_handle = mp_obj_get_int(conn_handle_in); int err = mp_bluetooth_gap_disconnect(conn_handle); if (err == 0) { return mp_const_true; } else if (err == MP_ENOTCONN) { return mp_const_false; } else { return bluetooth_handle_errno(err); } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gap_disconnect_obj, bluetooth_ble_gap_disconnect); // ---------------------------------------------------------------------------- // Bluetooth object: GATTS (Peripheral/Advertiser role) // ---------------------------------------------------------------------------- STATIC mp_obj_t bluetooth_ble_gatts_read(mp_obj_t self_in, mp_obj_t value_handle_in) { size_t len = 0; uint8_t* buf; mp_bluetooth_gatts_read(mp_obj_get_int(value_handle_in), &buf, &len); return mp_obj_new_bytes(buf, len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gatts_read_obj, bluetooth_ble_gatts_read); STATIC mp_obj_t bluetooth_ble_gatts_write(mp_obj_t self_in, mp_obj_t value_handle_in, mp_obj_t data) { mp_buffer_info_t bufinfo = {0}; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); int err = mp_bluetooth_gatts_write(mp_obj_get_int(value_handle_in), bufinfo.buf, bufinfo.len); if (err != 0) { mp_raise_OSError(err); } return MP_OBJ_NEW_SMALL_INT(bufinfo.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bluetooth_ble_gatts_write_obj, bluetooth_ble_gatts_write); STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) { mp_int_t conn_handle = mp_obj_get_int(args[1]); mp_int_t value_handle = mp_obj_get_int(args[2]); if (n_args == 4) { mp_buffer_info_t bufinfo = {0}; mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); size_t len = bufinfo.len; int err = mp_bluetooth_gatts_notify_send(conn_handle, value_handle, bufinfo.buf, &len); if (err != 0) { mp_raise_OSError(err); } return MP_OBJ_NEW_SMALL_INT(len); } else { int err = mp_bluetooth_gatts_notify(conn_handle, value_handle); return bluetooth_handle_errno(err); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify); STATIC mp_obj_t bluetooth_ble_gatts_set_buffer(size_t n_args, const mp_obj_t *args) { mp_int_t value_handle = mp_obj_get_int(args[1]); mp_int_t len = mp_obj_get_int(args[2]); bool append = n_args >= 4 && mp_obj_is_true(args[3]); return bluetooth_handle_errno(mp_bluetooth_gatts_set_buffer(value_handle, len, append)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_set_buffer_obj, 3, 4, bluetooth_ble_gatts_set_buffer); // ---------------------------------------------------------------------------- // Bluetooth object: GATTC (Central/Scanner role) // ---------------------------------------------------------------------------- #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC mp_obj_t bluetooth_ble_gattc_discover_services(mp_obj_t self_in, mp_obj_t conn_handle_in) { mp_int_t conn_handle = mp_obj_get_int(conn_handle_in); return bluetooth_handle_errno(mp_bluetooth_gattc_discover_primary_services(conn_handle)); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gattc_discover_services_obj, bluetooth_ble_gattc_discover_services); STATIC mp_obj_t bluetooth_ble_gattc_discover_characteristics(size_t n_args, const mp_obj_t *args) { mp_int_t conn_handle = mp_obj_get_int(args[1]); mp_int_t start_handle = mp_obj_get_int(args[2]); mp_int_t end_handle = mp_obj_get_int(args[3]); return bluetooth_handle_errno(mp_bluetooth_gattc_discover_characteristics(conn_handle, start_handle, end_handle)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_discover_characteristics_obj, 4, 4, bluetooth_ble_gattc_discover_characteristics); STATIC mp_obj_t bluetooth_ble_gattc_discover_descriptors(size_t n_args, const mp_obj_t *args) { mp_int_t conn_handle = mp_obj_get_int(args[1]); mp_int_t start_handle = mp_obj_get_int(args[2]); mp_int_t end_handle = mp_obj_get_int(args[3]); return bluetooth_handle_errno(mp_bluetooth_gattc_discover_descriptors(conn_handle, start_handle, end_handle)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_discover_descriptors_obj, 4, 4, bluetooth_ble_gattc_discover_descriptors); STATIC mp_obj_t bluetooth_ble_gattc_read(mp_obj_t self_in, mp_obj_t conn_handle_in, mp_obj_t value_handle_in) { mp_int_t conn_handle = mp_obj_get_int(conn_handle_in); mp_int_t value_handle = mp_obj_get_int(value_handle_in); return bluetooth_handle_errno(mp_bluetooth_gattc_read(conn_handle, value_handle)); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bluetooth_ble_gattc_read_obj, bluetooth_ble_gattc_read); STATIC mp_obj_t bluetooth_ble_gattc_write(size_t n_args, const mp_obj_t *args) { mp_int_t conn_handle = mp_obj_get_int(args[1]); mp_int_t value_handle = mp_obj_get_int(args[2]); mp_obj_t data = args[3]; mp_buffer_info_t bufinfo = {0}; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); size_t len = bufinfo.len; unsigned int mode = MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE; if (n_args == 5) { mode = mp_obj_get_int(args[4]); } return bluetooth_handle_errno(mp_bluetooth_gattc_write(conn_handle, value_handle, bufinfo.buf, &len, mode)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_write_obj, 4, 5, bluetooth_ble_gattc_write); #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE // ---------------------------------------------------------------------------- // Bluetooth object: Definition // ---------------------------------------------------------------------------- STATIC const mp_rom_map_elem_t bluetooth_ble_locals_dict_table[] = { // General { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&bluetooth_ble_active_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&bluetooth_ble_config_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&bluetooth_ble_irq_obj) }, // GAP { MP_ROM_QSTR(MP_QSTR_gap_advertise), MP_ROM_PTR(&bluetooth_ble_gap_advertise_obj) }, #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE { MP_ROM_QSTR(MP_QSTR_gap_connect), MP_ROM_PTR(&bluetooth_ble_gap_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_gap_scan), MP_ROM_PTR(&bluetooth_ble_gap_scan_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_gap_disconnect), MP_ROM_PTR(&bluetooth_ble_gap_disconnect_obj) }, // GATT Server (i.e. peripheral/advertiser role) { MP_ROM_QSTR(MP_QSTR_gatts_register_services), MP_ROM_PTR(&bluetooth_ble_gatts_register_services_obj) }, { MP_ROM_QSTR(MP_QSTR_gatts_read), MP_ROM_PTR(&bluetooth_ble_gatts_read_obj) }, { MP_ROM_QSTR(MP_QSTR_gatts_write), MP_ROM_PTR(&bluetooth_ble_gatts_write_obj) }, { MP_ROM_QSTR(MP_QSTR_gatts_notify), MP_ROM_PTR(&bluetooth_ble_gatts_notify_obj) }, { MP_ROM_QSTR(MP_QSTR_gatts_set_buffer), MP_ROM_PTR(&bluetooth_ble_gatts_set_buffer_obj) }, #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE // GATT Client (i.e. central/scanner role) { MP_ROM_QSTR(MP_QSTR_gattc_discover_services), MP_ROM_PTR(&bluetooth_ble_gattc_discover_services_obj) }, { MP_ROM_QSTR(MP_QSTR_gattc_discover_characteristics), MP_ROM_PTR(&bluetooth_ble_gattc_discover_characteristics_obj) }, { MP_ROM_QSTR(MP_QSTR_gattc_discover_descriptors), MP_ROM_PTR(&bluetooth_ble_gattc_discover_descriptors_obj) }, { MP_ROM_QSTR(MP_QSTR_gattc_read), MP_ROM_PTR(&bluetooth_ble_gattc_read_obj) }, { MP_ROM_QSTR(MP_QSTR_gattc_write), MP_ROM_PTR(&bluetooth_ble_gattc_write_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(bluetooth_ble_locals_dict, bluetooth_ble_locals_dict_table); STATIC const mp_obj_type_t bluetooth_ble_type = { { &mp_type_type }, .name = MP_QSTR_BLE, .make_new = bluetooth_ble_make_new, .locals_dict = (void*)&bluetooth_ble_locals_dict, }; STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluetooth) }, { MP_ROM_QSTR(MP_QSTR_BLE), MP_ROM_PTR(&bluetooth_ble_type) }, { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bluetooth_uuid_type) }, { MP_ROM_QSTR(MP_QSTR_FLAG_READ), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) }, { MP_ROM_QSTR(MP_QSTR_FLAG_WRITE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE) }, { MP_ROM_QSTR(MP_QSTR_FLAG_NOTIFY), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_bluetooth_globals, mp_module_bluetooth_globals_table); const mp_obj_module_t mp_module_ubluetooth = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_bluetooth_globals, }; // Helpers #include STATIC void ringbuf_extract(ringbuf_t* ringbuf, mp_obj_tuple_t *data_tuple, size_t n_u16, size_t n_u8, mp_obj_str_t *bytes_addr, size_t n_b, size_t n_i8, mp_obj_bluetooth_uuid_t *uuid, mp_obj_str_t *bytes_data) { assert(ringbuf_avail(ringbuf) >= n_u16 * 2 + n_u8 + (bytes_addr ? 6 : 0) + n_b + n_i8 + (uuid ? 1 : 0) + (bytes_data ? 1 : 0)); int j = 0; for (int i = 0; i < n_u16; ++i) { data_tuple->items[j++] = MP_OBJ_NEW_SMALL_INT(ringbuf_get16(ringbuf)); } if (n_u8) { data_tuple->items[j++] = MP_OBJ_NEW_SMALL_INT(ringbuf_get(ringbuf)); } if (bytes_addr) { bytes_addr->len = 6; for (int i = 0; i < bytes_addr->len; ++i) { // cast away const, this is actually bt->irq_addr_bytes. ((uint8_t*)bytes_addr->data)[i] = ringbuf_get(ringbuf); } data_tuple->items[j++] = MP_OBJ_FROM_PTR(bytes_addr); } if (n_b) { data_tuple->items[j++] = mp_obj_new_bool(ringbuf_get(ringbuf)); } if (n_i8) { // Note the int8_t got packed into the ringbuf as a uint8_t. data_tuple->items[j++] = MP_OBJ_NEW_SMALL_INT((int8_t)ringbuf_get(ringbuf)); } if (uuid) { ringbuf_get_uuid(ringbuf, uuid); data_tuple->items[j++] = MP_OBJ_FROM_PTR(uuid); } // The code that enqueues into the ringbuf should ensure that it doesn't // put more than bt->irq_data_data_alloc bytes into the ringbuf, because // that's what's available here in bt->irq_data_bytes. if (bytes_data) { bytes_data->len = ringbuf_get(ringbuf); for (int i = 0; i < bytes_data->len; ++i) { // cast away const, this is actually bt->irq_data_bytes. ((uint8_t*)bytes_data->data)[i] = ringbuf_get(ringbuf); } data_tuple->items[j++] = MP_OBJ_FROM_PTR(bytes_data); } data_tuple->len = j; } STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) { // This is always executing in schedule context. mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); o->irq_scheduled = false; for (;;) { MICROPY_PY_BLUETOOTH_ENTER mp_int_t event = event = ringbuf_get16(&o->ringbuf); if (event < 0) { // Nothing available in ringbuf. MICROPY_PY_BLUETOOTH_EXIT break; } // Although we're in schedule context, this code still avoids using any allocations: // - IRQs are disabled (to protect the ringbuf), and we need to avoid triggering GC // - The user's handler might not alloc, so we shouldn't either. mp_obj_t handler = handler = o->irq_handler; mp_obj_tuple_t *data_tuple = MP_OBJ_TO_PTR(o->irq_data_tuple); if (event == MP_BLUETOOTH_IRQ_CENTRAL_CONNECT || event == MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT || event == MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT || event == MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT) { // conn_handle, addr_type, addr ringbuf_extract(&o->ringbuf, data_tuple, 1, 1, &o->irq_data_addr, 0, 0, NULL, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTS_WRITE) { // conn_handle, value_handle ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, NULL, NULL); #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE } else if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT) { // addr_type, addr, connectable, rssi, adv_data ringbuf_extract(&o->ringbuf, data_tuple, 0, 1, &o->irq_data_addr, 1, 1, NULL, &o->irq_data_data); } else if (event == MP_BLUETOOTH_IRQ_SCAN_COMPLETE) { // No params required. data_tuple->len = 0; } else if (event == MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT) { // conn_handle, start_handle, end_handle, uuid ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, 0, &o->irq_data_uuid, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT) { // conn_handle, def_handle, value_handle, properties, uuid ringbuf_extract(&o->ringbuf, data_tuple, 3, 1, NULL, 0, 0, &o->irq_data_uuid, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT) { // conn_handle, handle, uuid ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, &o->irq_data_uuid, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTC_READ_RESULT || event == MP_BLUETOOTH_IRQ_GATTC_NOTIFY || event == MP_BLUETOOTH_IRQ_GATTC_INDICATE) { // conn_handle, value_handle, data ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, NULL, &o->irq_data_data); } else if (event == MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS) { // conn_handle, value_handle, status ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, 0, NULL, NULL); #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE } MICROPY_PY_BLUETOOTH_EXIT mp_call_function_2(handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_invoke_irq); // ---------------------------------------------------------------------------- // Port API // ---------------------------------------------------------------------------- // Callbacks are called in interrupt context (i.e. can't allocate), so we need to push the data // into the ringbuf and schedule the callback via mp_sched_schedule. STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event) { if (!o || !(o->irq_trigger & event) || o->irq_handler == mp_const_none) { return false; } if (ringbuf_free(&o->ringbuf) < len + 2) { // Ringbuffer doesn't have room (and is therefore non-empty). // If this is another scan result, or the front of the ringbuffer isn't a scan result, then nothing to do. if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT || ringbuf_peek16(&o->ringbuf) != MP_BLUETOOTH_IRQ_SCAN_RESULT) { return false; } // Front of the queue is a scan result, remove it. // event, addr_type, addr, connectable, rssi int n = 2 + 1 + 6 + 1 + 1; for (int i = 0; i < n; ++i) { ringbuf_get(&o->ringbuf); } // adv_data n = ringbuf_get(&o->ringbuf); for (int i = 0; i < n; ++i) { ringbuf_get(&o->ringbuf); } } // Append this event, the caller will then append the arguments. ringbuf_put16(&o->ringbuf, event); return true; } STATIC void schedule_ringbuf(void) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (!o->irq_scheduled) { o->irq_scheduled = true; mp_sched_schedule(MP_OBJ_FROM_PTR(MP_ROM_PTR(&bluetooth_ble_invoke_irq_obj)), mp_const_none); } } void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 2 + 1 + 6, event)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put(&o->ringbuf, addr_type); for (int i = 0; i < 6; ++i) { ringbuf_put(&o->ringbuf, addr[i]); } } schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT } void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 2 + 2, MP_BLUETOOTH_IRQ_GATTS_WRITE)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); } schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT } #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE void mp_bluetooth_gap_on_scan_complete(void) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 0, MP_BLUETOOTH_IRQ_SCAN_COMPLETE)) { } schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT } void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, bool connectable, const int8_t rssi, const uint8_t *data, size_t data_len) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); data_len = MIN(o->irq_data_data_alloc, data_len); if (enqueue_irq(o, 1 + 6 + 1 + 1 + 1 + data_len, MP_BLUETOOTH_IRQ_SCAN_RESULT)) { ringbuf_put(&o->ringbuf, addr_type); for (int i = 0; i < 6; ++i) { ringbuf_put(&o->ringbuf, addr[i]); } ringbuf_put(&o->ringbuf, connectable ? 1 : 0); // Note conversion of int8_t rssi to uint8_t. Must un-convert on the way out. ringbuf_put(&o->ringbuf, (uint8_t)rssi); ringbuf_put(&o->ringbuf, data_len); for (int i = 0; i < data_len; ++i) { ringbuf_put(&o->ringbuf, data[i]); } } schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT } void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 2 + 2 + 2 + 1 + service_uuid->type, MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, start_handle); ringbuf_put16(&o->ringbuf, end_handle); ringbuf_put_uuid(&o->ringbuf, service_uuid); } schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT } void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 2 + 2 + 2 + 1 + characteristic_uuid->type, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, def_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put(&o->ringbuf, properties); ringbuf_put_uuid(&o->ringbuf, characteristic_uuid); } schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT } void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 2 + 2 + 1 + descriptor_uuid->type, MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, handle); ringbuf_put_uuid(&o->ringbuf, descriptor_uuid); } schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT } size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); data_len = MIN(o->irq_data_data_alloc, data_len); if (enqueue_irq(o, 2 + 2 + 1 + data_len, event)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put(&o->ringbuf, data_len); return data_len; } else { return 0; } } void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data_len) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); for (int i = 0; i < data_len; ++i) { ringbuf_put(&o->ringbuf, data[i]); } } void mp_bluetooth_gattc_on_data_available_end(void) { schedule_ringbuf(); } void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (enqueue_irq(o, 2 + 2 + 2, MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put16(&o->ringbuf, status); } schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT } #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK // This can only be enabled when the thread invoking this is a MicroPython thread. // On ESP32, for example, this is not the case. bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if ((o->irq_trigger & MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST) && o->irq_handler != mp_const_none) { // Use pre-allocated tuple because this is a hard IRQ. mp_obj_tuple_t *data = MP_OBJ_FROM_PTR(o->irq_data_tuple); data->items[0] = MP_OBJ_NEW_SMALL_INT(conn_handle); data->items[1] = MP_OBJ_NEW_SMALL_INT(value_handle); data->len = 2; mp_obj_t irq_ret = mp_call_function_2_protected(o->irq_handler, MP_OBJ_NEW_SMALL_INT(MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST), o->irq_data_tuple); // If the IRQ handler explicitly returned false, then deny the read. Otherwise if it returns None/True, allow it. return irq_ret != MP_OBJ_NULL && (irq_ret == mp_const_none || mp_obj_is_true(irq_ret)); } else { // No IRQ handler, allow the read. return true; } } #endif #endif // MICROPY_PY_BLUETOOTH micropython-1.12/extmod/modbluetooth.h000066400000000000000000000324531357706137100202070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Ayke van Laethem * Copyright (c) 2019 Jim Mussared * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_H #define MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_H #include #include "py/obj.h" #include "py/objlist.h" #include "py/ringbuf.h" // Port specific configuration. #ifndef MICROPY_PY_BLUETOOTH_RINGBUF_SIZE #define MICROPY_PY_BLUETOOTH_RINGBUF_SIZE (128) #endif #ifndef MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (0) #endif #ifndef MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK #define MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK (0) #endif // This is used to protect the ringbuffer. #ifndef MICROPY_PY_BLUETOOTH_ENTER #define MICROPY_PY_BLUETOOTH_ENTER mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); #define MICROPY_PY_BLUETOOTH_EXIT MICROPY_END_ATOMIC_SECTION(atomic_state); #endif // Common constants. #ifndef MP_BLUETOOTH_MAX_ATTR_SIZE #define MP_BLUETOOTH_MAX_ATTR_SIZE (20) #endif // Advertisement packet lengths #define MP_BLUETOOTH_GAP_ADV_MAX_LEN (32) #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ (1 << 1) #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (1 << 3) #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (1 << 4) // For mp_bluetooth_gattc_write, the mode parameter #define MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE (0) #define MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE (1) // Type value also doubles as length. #define MP_BLUETOOTH_UUID_TYPE_16 (2) #define MP_BLUETOOTH_UUID_TYPE_32 (4) #define MP_BLUETOOTH_UUID_TYPE_128 (16) // Address types (for the addr_type params). // Ports will need to map these to their own values. #define MP_BLUETOOTH_ADDR_PUBLIC (0x00) // Public (identity) address. (Same as NimBLE and NRF SD) #define MP_BLUETOOTH_ADDR_RANDOM_STATIC (0x01) // Random static (identity) address. (Same as NimBLE and NRF SD) #define MP_BLUETOOTH_ADDR_PUBLIC_ID (0x02) // (Same as NimBLE) #define MP_BLUETOOTH_ADDR_RANDOM_ID (0x03) // (Same as NimBLE) #define MP_BLUETOOTH_ADDR_RANDOM_PRIVATE_RESOLVABLE (0x12) // Random private resolvable address. (NRF SD 0x02) #define MP_BLUETOOTH_ADDR_RANDOM_PRIVATE_NON_RESOLVABLE (0x13) // Random private non-resolvable address. (NRF SD 0x03) // Event codes for the IRQ handler. // Can also be combined to pass to the trigger param to select which events you // are interested in. // Note this is currently stored in a uint16_t (in irq_trigger, and the event // arg to the irq handler), so one spare value remaining. #define MP_BLUETOOTH_IRQ_CENTRAL_CONNECT (1 << 0) #define MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT (1 << 1) #define MP_BLUETOOTH_IRQ_GATTS_WRITE (1 << 2) #define MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST (1 << 3) #define MP_BLUETOOTH_IRQ_SCAN_RESULT (1 << 4) #define MP_BLUETOOTH_IRQ_SCAN_COMPLETE (1 << 5) #define MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT (1 << 6) #define MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT (1 << 7) #define MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT (1 << 8) #define MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT (1 << 9) #define MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT (1 << 10) #define MP_BLUETOOTH_IRQ_GATTC_READ_RESULT (1 << 11) #define MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS (1 << 12) #define MP_BLUETOOTH_IRQ_GATTC_NOTIFY (1 << 13) #define MP_BLUETOOTH_IRQ_GATTC_INDICATE (1 << 14) #define MP_BLUETOOTH_IRQ_ALL (0xffff) /* These aren't included in the module for space reasons, but can be used in your Python code if necessary. from micropython import const _IRQ_CENTRAL_CONNECT = const(1 << 0) _IRQ_CENTRAL_DISCONNECT = const(1 << 1) _IRQ_GATTS_WRITE = const(1 << 2) _IRQ_GATTS_READ_REQUEST = const(1 << 3) _IRQ_SCAN_RESULT = const(1 << 4) _IRQ_SCAN_COMPLETE = const(1 << 5) _IRQ_PERIPHERAL_CONNECT = const(1 << 6) _IRQ_PERIPHERAL_DISCONNECT = const(1 << 7) _IRQ_GATTC_SERVICE_RESULT = const(1 << 8) _IRQ_GATTC_CHARACTERISTIC_RESULT = const(1 << 9) _IRQ_GATTC_DESCRIPTOR_RESULT = const(1 << 10) _IRQ_GATTC_READ_RESULT = const(1 << 11) _IRQ_GATTC_WRITE_STATUS = const(1 << 12) _IRQ_GATTC_NOTIFY = const(1 << 13) _IRQ_GATTC_INDICATE = const(1 << 14) _IRQ_ALL = const(0xffff) */ // Common UUID type. // Ports are expected to map this to their own internal UUID types. // Internally the UUID data is little-endian, but the user should only // ever see this if they use the buffer protocol, e.g. in order to // construct an advertising payload (which needs to be in LE). // Both the constructor and the print function work in BE. typedef struct { mp_obj_base_t base; uint8_t type; uint8_t data[16]; } mp_obj_bluetooth_uuid_t; ////////////////////////////////////////////////////////////// // API implemented by ports (i.e. called from modbluetooth.c): // TODO: At the moment this only allows for a single `Bluetooth` instance to be created. // Ideally in the future we'd be able to have multiple instances or to select a specific BT driver or HCI UART. // So these global methods should be replaced with a struct of function pointers (like the machine.I2C implementations). // Any method returning an int returns errno on failure, otherwise zero. // Note: All methods dealing with addresses (as 6-byte uint8 pointers) are in big-endian format. // (i.e. the same way they would be printed on a device sticker or in a UI), so the user sees // addresses in a way that looks like what they'd expect. // This means that the lower level implementation will likely need to reorder them (e.g. Nimble // works in little-endian, as does BLE itself). // Enables the Bluetooth stack. int mp_bluetooth_init(void); // Disables the Bluetooth stack. Is a no-op when not enabled. void mp_bluetooth_deinit(void); // Returns true when the Bluetooth stack is enabled. bool mp_bluetooth_is_enabled(void); // Gets the MAC addr of this device in big-endian format. void mp_bluetooth_get_device_addr(uint8_t *addr); // Start advertisement. Will re-start advertisement when already enabled. // Returns errno on failure. int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len); // Stop advertisement. No-op when already stopped. void mp_bluetooth_gap_advertise_stop(void); // Start adding services. Must be called before mp_bluetooth_register_service. int mp_bluetooth_gatts_register_service_begin(bool append); // // Add a service with the given list of characteristics to the queue to be registered. // The value_handles won't be valid until after mp_bluetooth_register_service_end is called. int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics); // Register any queued services. int mp_bluetooth_gatts_register_service_end(); // Read the value from the local gatts db (likely this has been written by a central). int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len); // Write a value to the local gatts db (ready to be queried by a central). int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len); // Notify the central that it should do a read. int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle); // Notify the central, including a data payload. (Note: does not set the gatts db value). int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len); // Indicate the central. int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle); // Resize and enable/disable append-mode on a value. // Append-mode means that remote writes will append and local reads will clear after reading. int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append); // Disconnect from a central or peripheral. int mp_bluetooth_gap_disconnect(uint16_t conn_handle); #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE // Start a discovery (scan). Set duration to zero to run continuously. int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us); // Stop discovery (if currently active). int mp_bluetooth_gap_scan_stop(void); // Connect to a found peripheral. int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms); // Find all primary services on the connected peripheral. int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle); // Find all characteristics on the specified service on a connected peripheral. int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle); // Find all descriptors on the specified characteristic on a connected peripheral. int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle); // Initiate read of a value from the remote peripheral. int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle); // Write the value to the remote peripheral. int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode); #endif ///////////////////////////////////////////////////////////////////////////// // API implemented by modbluetooth (called by port-specific implementations): // Notify modbluetooth that a connection/disconnection event has occurred. void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr); // Call this when a characteristic is written to. void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle); #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK // Call this when a characteristic is read from. Return false to deny the read. bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle); #endif #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE // Notify modbluetooth that scan has finished, either timeout, manually, or by some other action (e.g. connecting). void mp_bluetooth_gap_on_scan_complete(void); // Notify modbluetooth of a scan result. void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, bool connectable, const int8_t rssi, const uint8_t *data, size_t data_len); // Notify modbluetooth that a service was found (either by discover-all, or discover-by-uuid). void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid); // Notify modbluetooth that a characteristic was found (either by discover-all-on-service, or discover-by-uuid-on-service). void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid); // Notify modbluetooth that a descriptor was found. void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid); // Notify modbluetooth that a read has completed with data (or notify/indicate data available, use `event` to disambiguate). // Note: these functions are to be called in a group protected by MICROPY_PY_BLUETOOTH_ENTER/EXIT. // _start returns the number of bytes to submit to the calls to _chunk, followed by a call to _end. size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len); void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data_len); void mp_bluetooth_gattc_on_data_available_end(void); // Notify modbluetooth that a write has completed. void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status); #endif #endif // MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_H micropython-1.12/extmod/modbluetooth_nimble.c000066400000000000000000001010631357706137100215220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * Copyright (c) 2019 Jim Mussared * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE #include "modbluetooth_nimble.h" #include "modbluetooth.h" #include "host/ble_hs.h" #include "host/util/util.h" #include "nimble/ble.h" #include "nimble/nimble_port.h" #include "services/gap/ble_svc_gap.h" #ifndef MICROPY_PY_BLUETOOTH_DEFAULT_NAME #define MICROPY_PY_BLUETOOTH_DEFAULT_NAME "PYBD" #endif #define DEBUG_EVENT_printf(...) //printf(__VA_ARGS__) STATIC int8_t ble_hs_err_to_errno_table[] = { [BLE_HS_EAGAIN] = MP_EAGAIN, [BLE_HS_EALREADY] = MP_EALREADY, [BLE_HS_EINVAL] = MP_EINVAL, [BLE_HS_EMSGSIZE] = MP_EIO, [BLE_HS_ENOENT] = MP_ENOENT, [BLE_HS_ENOMEM] = MP_ENOMEM, [BLE_HS_ENOTCONN] = MP_ENOTCONN, [BLE_HS_ENOTSUP] = MP_EOPNOTSUPP, [BLE_HS_EAPP] = MP_EIO, [BLE_HS_EBADDATA] = MP_EIO, [BLE_HS_EOS] = MP_EIO, [BLE_HS_ECONTROLLER] = MP_EIO, [BLE_HS_ETIMEOUT] = MP_ETIMEDOUT, [BLE_HS_EDONE] = MP_EIO, // TODO: Maybe should be MP_EISCONN (connect uses this for "already connected"). [BLE_HS_EBUSY] = MP_EBUSY, [BLE_HS_EREJECT] = MP_EIO, [BLE_HS_EUNKNOWN] = MP_EIO, [BLE_HS_EROLE] = MP_EIO, [BLE_HS_ETIMEOUT_HCI] = MP_EIO, [BLE_HS_ENOMEM_EVT] = MP_EIO, [BLE_HS_ENOADDR] = MP_EIO, [BLE_HS_ENOTSYNCED] = MP_EIO, [BLE_HS_EAUTHEN] = MP_EIO, [BLE_HS_EAUTHOR] = MP_EIO, [BLE_HS_EENCRYPT] = MP_EIO, [BLE_HS_EENCRYPT_KEY_SZ] = MP_EIO, [BLE_HS_ESTORE_CAP] = MP_EIO, [BLE_HS_ESTORE_FAIL] = MP_EIO, [BLE_HS_EPREEMPTED] = MP_EIO, [BLE_HS_EDISABLED] = MP_EIO, }; STATIC int ble_hs_err_to_errno(int err) { if (0 <= err && err < MP_ARRAY_SIZE(ble_hs_err_to_errno_table)) { return ble_hs_err_to_errno_table[err]; } else { return MP_EIO; } } // Note: modbluetooth UUIDs store their data in LE. STATIC ble_uuid_t* create_nimble_uuid(const mp_obj_bluetooth_uuid_t *uuid) { if (uuid->type == MP_BLUETOOTH_UUID_TYPE_16) { ble_uuid16_t *result = m_new(ble_uuid16_t, 1); result->u.type = BLE_UUID_TYPE_16; result->value = (uuid->data[1] << 8) | uuid->data[0]; return (ble_uuid_t*)result; } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_32) { ble_uuid32_t *result = m_new(ble_uuid32_t, 1); result->u.type = BLE_UUID_TYPE_32; result->value = (uuid->data[1] << 24) | (uuid->data[1] << 16) | (uuid->data[1] << 8) | uuid->data[0]; return (ble_uuid_t*)result; } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_128) { ble_uuid128_t *result = m_new(ble_uuid128_t, 1); result->u.type = BLE_UUID_TYPE_128; memcpy(result->value, uuid->data, 16); return (ble_uuid_t*)result; } else { return NULL; } } #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(const ble_uuid_any_t *uuid) { mp_obj_bluetooth_uuid_t result; switch (uuid->u.type) { case BLE_UUID_TYPE_16: result.type = MP_BLUETOOTH_UUID_TYPE_16; result.data[0] = uuid->u16.value & 0xff; result.data[1] = (uuid->u16.value >> 8) & 0xff; break; case BLE_UUID_TYPE_32: result.type = MP_BLUETOOTH_UUID_TYPE_32; result.data[0] = uuid->u32.value & 0xff; result.data[1] = (uuid->u32.value >> 8) & 0xff; result.data[2] = (uuid->u32.value >> 16) & 0xff; result.data[3] = (uuid->u32.value >> 24) & 0xff; break; case BLE_UUID_TYPE_128: result.type = MP_BLUETOOTH_UUID_TYPE_128; memcpy(result.data, uuid->u128.value, 16); break; default: assert(false); } return result; } // modbluetooth (and the layers above it) work in BE for addresses, Nimble works in LE. STATIC void reverse_addr_byte_order(uint8_t *addr_out, const uint8_t *addr_in) { for (int i = 0; i < 6; ++i) { addr_out[i] = addr_in[5-i]; } } STATIC ble_addr_t create_nimble_addr(uint8_t addr_type, const uint8_t *addr) { ble_addr_t addr_nimble; addr_nimble.type = addr_type; // Incoming addr is from modbluetooth (BE), so copy and convert to LE for Nimble. reverse_addr_byte_order(addr_nimble.val, addr); return addr_nimble; } #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE typedef struct { // Pointer to heap-allocated data. uint8_t *data; // Allocated size of data. size_t data_alloc; // Current bytes in use. size_t data_len; // Whether new writes append or replace existing data (default false). bool append; } gatts_db_entry_t; volatile int mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF; STATIC void reset_cb(int reason) { (void)reason; } STATIC void sync_cb(void) { int rc; ble_addr_t addr; rc = ble_hs_util_ensure_addr(0); // prefer public address if (rc != 0) { // https://mynewt.apache.org/latest/tutorials/ble/eddystone.html#configure-the-nimble-stack-with-an-address #if MICROPY_PY_BLUETOOTH_RANDOM_ADDR rc = ble_hs_id_gen_rnd(1, &addr); assert(rc == 0); rc = ble_hs_id_set_rnd(addr.val); assert(rc == 0); #else uint8_t addr_be[6]; mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr_be); reverse_addr_byte_order(addr.val, addr_be); // ble_hs_id_set_pub(addr.val); rc = ble_hs_id_set_rnd(addr.val); assert(rc == 0); #endif rc = ble_hs_util_ensure_addr(0); // prefer public address assert(rc == 0); } if (MP_BLUETOOTH_MAX_ATTR_SIZE > 20) { rc = ble_att_set_preferred_mtu(MP_BLUETOOTH_MAX_ATTR_SIZE+3); assert(rc == 0); } ble_svc_gap_device_name_set(MICROPY_PY_BLUETOOTH_DEFAULT_NAME); mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE; } STATIC void create_gatts_db_entry(uint16_t handle) { mp_map_elem_t *elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(handle), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); gatts_db_entry_t *entry = m_new(gatts_db_entry_t, 1); entry->data = m_new(uint8_t, MP_BLUETOOTH_MAX_ATTR_SIZE); entry->data_alloc = MP_BLUETOOTH_MAX_ATTR_SIZE; entry->data_len = 0; entry->append = false; elem->value = MP_OBJ_FROM_PTR(entry); } STATIC void gatts_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) { switch (ctxt->op) { case BLE_GATT_REGISTER_OP_SVC: // Called when a service is successfully registered. DEBUG_EVENT_printf("gatts_register_cb: svc uuid=%p handle=%d\n", &ctxt->svc.svc_def->uuid, ctxt->svc.handle); break; case BLE_GATT_REGISTER_OP_CHR: // Called when a characteristic is successfully registered. DEBUG_EVENT_printf("gatts_register_cb: chr uuid=%p def_handle=%d val_handle=%d\n", &ctxt->chr.chr_def->uuid, ctxt->chr.def_handle, ctxt->chr.val_handle); // Note: We will get this event for the default GAP Service, meaning that we allocate storage for the // "device name" and "appearance" characteristics, even though we never see the reads for them. // TODO: Possibly check if the service UUID is 0x1801 and ignore? // Allocate the gatts_db storage for this characteristic. // Although this function is a callback, it's called synchronously from ble_hs_sched_start/ble_gatts_start, so safe to allocate. create_gatts_db_entry(ctxt->chr.val_handle); break; case BLE_GATT_REGISTER_OP_DSC: // Called when a descriptor is successfully registered. // Note: This is event is not called for the CCCD. DEBUG_EVENT_printf("gatts_register_cb: dsc uuid=%p handle=%d\n", &ctxt->dsc.dsc_def->uuid, ctxt->dsc.handle); // See above, safe to alloc. create_gatts_db_entry(ctxt->dsc.handle); // Unlike characteristics, we have to manually provide a way to get the handle back to the register method. *((uint16_t*)ctxt->dsc.dsc_def->arg) = ctxt->dsc.handle; break; default: DEBUG_EVENT_printf("gatts_register_cb: unknown op %d\n", ctxt->op); break; } } STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("gap_event_cb: type=%d\n", event->type); struct ble_gap_conn_desc desc; uint8_t addr[6] = {0}; switch (event->type) { case BLE_GAP_EVENT_CONNECT: if (event->connect.status == 0) { // Connection established. ble_gap_conn_find(event->connect.conn_handle, &desc); reverse_addr_byte_order(addr, desc.peer_id_addr.val); mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_CONNECT, event->connect.conn_handle, desc.peer_id_addr.type, addr); } else { // Connection failed. mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->connect.conn_handle, 0xff, addr); } break; case BLE_GAP_EVENT_DISCONNECT: // Disconnect. reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val); mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr); break; } return 0; } int mp_bluetooth_init(void) { // Clean up if necessary. mp_bluetooth_deinit(); ble_hs_cfg.reset_cb = reset_cb; ble_hs_cfg.sync_cb = sync_cb; ble_hs_cfg.gatts_register_cb = gatts_register_cb; ble_hs_cfg.store_status_cb = ble_store_util_status_rr; MP_STATE_PORT(bluetooth_nimble_root_pointers) = m_new0(mp_bluetooth_nimble_root_pointers_t, 1); MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db = m_new(mp_map_t, 1); mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_STARTING; mp_bluetooth_nimble_port_preinit(); nimble_port_init(); mp_bluetooth_nimble_port_postinit(); // By default, just register the default gap service. ble_svc_gap_init(); mp_bluetooth_nimble_port_start(); // Wait for sync callback while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE) { MICROPY_EVENT_POLL_HOOK } return 0; } // Called when the host stop procedure has completed. STATIC void ble_hs_shutdown_stop_cb(int status, void *arg) { mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF; } STATIC struct ble_hs_stop_listener ble_hs_shutdown_stop_listener; void mp_bluetooth_deinit(void) { if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { return; } mp_bluetooth_gap_advertise_stop(); #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE mp_bluetooth_gap_scan_stop(); #endif ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, NULL); while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { MICROPY_EVENT_POLL_HOOK } mp_bluetooth_nimble_port_deinit(); MP_STATE_PORT(bluetooth_nimble_root_pointers) = NULL; } bool mp_bluetooth_is_enabled(void) { return mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE; } void mp_bluetooth_get_device_addr(uint8_t *addr) { #if MICROPY_PY_BLUETOOTH_RANDOM_ADDR ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr, NULL); #else mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr); #endif } int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) { int ret; mp_bluetooth_gap_advertise_stop(); if (adv_data) { ret = ble_gap_adv_set_data(adv_data, adv_data_len); if (ret != 0) { return ble_hs_err_to_errno(ret); } } if (sr_data) { ret = ble_gap_adv_rsp_set_data(sr_data, sr_data_len); if (ret != 0) { return ble_hs_err_to_errno(ret); } } struct ble_gap_adv_params adv_params = { .conn_mode = connectable ? BLE_GAP_CONN_MODE_UND : BLE_GAP_CONN_MODE_NON, .disc_mode = BLE_GAP_DISC_MODE_GEN, .itvl_min = interval_us / BLE_HCI_ADV_ITVL, // convert to 625us units. .itvl_max = interval_us / BLE_HCI_ADV_ITVL, .channel_map = 7, // all 3 channels. }; ret = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); if (ret == 0) { return 0; } ret = ble_gap_adv_start(BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); if (ret == 0) { return 0; } ret = ble_gap_adv_start(BLE_OWN_ADDR_RPA_RANDOM_DEFAULT, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); if (ret == 0) { return 0; } ret = ble_gap_adv_start(BLE_OWN_ADDR_RANDOM, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); if (ret == 0) { return 0; } DEBUG_EVENT_printf("ble_gap_adv_start: %d\n", ret); return ble_hs_err_to_errno(ret); } void mp_bluetooth_gap_advertise_stop(void) { if (ble_gap_adv_active()) { ble_gap_adv_stop(); } } static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { DEBUG_EVENT_printf("characteristic_access_cb: conn_handle=%u value_handle=%u op=%u\n", conn_handle, value_handle, ctxt->op); mp_map_elem_t *elem; gatts_db_entry_t *entry; switch (ctxt->op) { case BLE_GATT_ACCESS_OP_READ_CHR: case BLE_GATT_ACCESS_OP_READ_DSC: #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK // Allow Python code to override (by using gatts_write), or deny (by returning false) the read. if (!mp_bluetooth_gatts_on_read_request(conn_handle, value_handle)) { return BLE_ATT_ERR_READ_NOT_PERMITTED; } #endif elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return BLE_ATT_ERR_ATTR_NOT_FOUND; } entry = MP_OBJ_TO_PTR(elem->value); os_mbuf_append(ctxt->om, entry->data, entry->data_len); return 0; case BLE_GATT_ACCESS_OP_WRITE_CHR: case BLE_GATT_ACCESS_OP_WRITE_DSC: elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return BLE_ATT_ERR_ATTR_NOT_FOUND; } entry = MP_OBJ_TO_PTR(elem->value); size_t offset = 0; if (entry->append) { offset = entry->data_len; } entry->data_len = MIN(entry->data_alloc, OS_MBUF_PKTLEN(ctxt->om) + offset); os_mbuf_copydata(ctxt->om, 0, entry->data_len - offset, entry->data + offset); mp_bluetooth_gatts_on_write(conn_handle, value_handle); return 0; } return BLE_ATT_ERR_UNLIKELY; } int mp_bluetooth_gatts_register_service_begin(bool append) { int ret = ble_gatts_reset(); if (ret != 0) { return ble_hs_err_to_errno(ret); } // Reset the gatt characteristic value db. mp_map_init(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, 0); // By default, just register the default gap service. ble_svc_gap_init(); if (!append) { // Unref any previous service definitions. for (int i = 0; i < MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services; ++i) { MP_STATE_PORT(bluetooth_nimble_root_pointers)->services[i] = NULL; } MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services = 0; } return 0; } int mp_bluetooth_gatts_register_service_end() { int ret = ble_gatts_start(); if (ret != 0) { return ble_hs_err_to_errno(ret); } return 0; } int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) { if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services == MP_BLUETOOTH_NIMBLE_MAX_SERVICES) { return MP_E2BIG; } size_t handle_index = 0; size_t descriptor_index = 0; struct ble_gatt_chr_def *characteristics = m_new(struct ble_gatt_chr_def, num_characteristics + 1); for (size_t i = 0; i < num_characteristics; ++i) { characteristics[i].uuid = create_nimble_uuid(characteristic_uuids[i]); characteristics[i].access_cb = characteristic_access_cb; characteristics[i].arg = NULL; characteristics[i].flags = characteristic_flags[i]; characteristics[i].min_key_size = 0; characteristics[i].val_handle = &handles[handle_index]; ++handle_index; if (num_descriptors[i] == 0) { characteristics[i].descriptors = NULL; } else { struct ble_gatt_dsc_def *descriptors = m_new(struct ble_gatt_dsc_def, num_descriptors[i] + 1); for (size_t j = 0; j < num_descriptors[i]; ++j) { descriptors[j].uuid = create_nimble_uuid(descriptor_uuids[descriptor_index]); descriptors[j].access_cb = characteristic_access_cb; descriptors[j].att_flags = descriptor_flags[i]; descriptors[j].min_key_size = 0; // Unlike characteristic, Nimble doesn't provide an automatic way to remember the handle, so use the arg. descriptors[j].arg = &handles[handle_index]; ++descriptor_index; ++handle_index; } descriptors[num_descriptors[i]].uuid = NULL; // no more descriptors characteristics[i].descriptors = descriptors; } } characteristics[num_characteristics].uuid = NULL; // no more characteristics struct ble_gatt_svc_def *service = m_new(struct ble_gatt_svc_def, 2); service[0].type = BLE_GATT_SVC_TYPE_PRIMARY; service[0].uuid = create_nimble_uuid(service_uuid); service[0].includes = NULL; service[0].characteristics = characteristics; service[1].type = 0; // no more services MP_STATE_PORT(bluetooth_nimble_root_pointers)->services[MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services++] = service; // Note: advertising must be stopped for gatts registration to work int ret = ble_gatts_count_cfg(service); if (ret != 0) { return ble_hs_err_to_errno(ret); } ret = ble_gatts_add_svcs(service); if (ret != 0) { return ble_hs_err_to_errno(ret); } return 0; } int mp_bluetooth_gap_disconnect(uint16_t conn_handle) { return ble_hs_err_to_errno(ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM)); } int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) { mp_map_elem_t *elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return MP_EINVAL; } gatts_db_entry_t *entry = MP_OBJ_TO_PTR(elem->value); *value = entry->data; *value_len = entry->data_len; if (entry->append) { entry->data_len = 0; } return 0; } int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len) { mp_map_elem_t *elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return MP_EINVAL; } gatts_db_entry_t *entry = MP_OBJ_TO_PTR(elem->value); if (value_len > entry->data_alloc) { entry->data = m_new(uint8_t, value_len); entry->data_alloc = value_len; } memcpy(entry->data, value, value_len); entry->data_len = value_len; return 0; } // TODO: Could use ble_gatts_chr_updated to send to all subscribed centrals. int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) { // Confusingly, notify/notify_custom/indicate are "gattc" function (even though they're used by peripherals (i.e. gatt servers)). // See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html return ble_hs_err_to_errno(ble_gattc_notify(conn_handle, value_handle)); } int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len) { struct os_mbuf *om = ble_hs_mbuf_from_flat(value, *value_len); if (om == NULL) { return -1; } // TODO: check that notify_custom takes ownership of om, if not os_mbuf_free_chain(om). return ble_hs_err_to_errno(ble_gattc_notify_custom(conn_handle, value_handle, om)); } int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) { return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle)); } int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) { mp_map_elem_t *elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return MP_EINVAL; } gatts_db_entry_t *entry = MP_OBJ_TO_PTR(elem->value); entry->data = m_renew(uint8_t, entry->data, entry->data_alloc, len); entry->data_alloc = len; entry->data_len = 0; entry->append = append; return 0; } #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC void gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const struct os_mbuf *om) { MICROPY_PY_BLUETOOTH_ENTER size_t len = OS_MBUF_PKTLEN(om); len = mp_bluetooth_gattc_on_data_available_start(event, conn_handle, value_handle, len); while (len > 0 && om != NULL) { size_t n = MIN(om->om_len, len); mp_bluetooth_gattc_on_data_available_chunk(OS_MBUF_DATA(om, const uint8_t*), n); len -= n; om = SLIST_NEXT(om, om_next); } mp_bluetooth_gattc_on_data_available_end(); MICROPY_PY_BLUETOOTH_EXIT } STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("gap_scan_cb: event=%d type=%d\n", event->type, event->type == BLE_GAP_EVENT_DISC ? event->disc.event_type : -1); if (event->type == BLE_GAP_EVENT_DISC_COMPLETE) { mp_bluetooth_gap_on_scan_complete(); return 0; } if (event->type != BLE_GAP_EVENT_DISC) { return 0; } if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND) { bool connectable = event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND; uint8_t addr[6]; reverse_addr_byte_order(addr, event->disc.addr.val); mp_bluetooth_gap_on_scan_result(event->disc.addr.type, addr, connectable, event->disc.rssi, event->disc.data, event->disc.length_data); } else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { // TODO } else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND) { // TODO } return 0; } int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us) { if (duration_ms == 0) { duration_ms = BLE_HS_FOREVER; } struct ble_gap_disc_params discover_params = { .itvl = MAX(BLE_HCI_SCAN_ITVL_MIN, MIN(BLE_HCI_SCAN_ITVL_MAX, interval_us / BLE_HCI_SCAN_ITVL)), .window = MAX(BLE_HCI_SCAN_WINDOW_MIN, MIN(BLE_HCI_SCAN_WINDOW_MAX, window_us / BLE_HCI_SCAN_ITVL)), .filter_policy = BLE_HCI_CONN_FILT_NO_WL, .limited = 0, .passive = 1, // TODO: Handle BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP in gap_scan_cb above. .filter_duplicates = 0, }; int err = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, duration_ms, &discover_params, gap_scan_cb, NULL); return ble_hs_err_to_errno(err); } int mp_bluetooth_gap_scan_stop(void) { if (!ble_gap_disc_active()) { return 0; } int err = ble_gap_disc_cancel(); if (err == 0) { mp_bluetooth_gap_on_scan_complete(); return 0; } return ble_hs_err_to_errno(err); } // Central role: GAP events for a connected peripheral. STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("peripheral_gap_event_cb: event=%d\n", event->type); struct ble_gap_conn_desc desc; uint8_t addr[6] = {0}; switch (event->type) { case BLE_GAP_EVENT_CONNECT: if (event->connect.status == 0) { // Connection established. ble_gap_conn_find(event->connect.conn_handle, &desc); reverse_addr_byte_order(addr, desc.peer_id_addr.val); mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT, event->connect.conn_handle, desc.peer_id_addr.type, addr); } else { // Connection failed. mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT, event->connect.conn_handle, 0xff, addr); } break; case BLE_GAP_EVENT_DISCONNECT: // Disconnect. reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val); mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr); break; case BLE_GAP_EVENT_NOTIFY_RX: { uint16_t ev = event->notify_rx.indication == 0 ? MP_BLUETOOTH_IRQ_GATTC_NOTIFY : MP_BLUETOOTH_IRQ_GATTC_INDICATE; gattc_on_data_available(ev, event->notify_rx.conn_handle, event->notify_rx.attr_handle, event->notify_rx.om); break; } case BLE_GAP_EVENT_CONN_UPDATE: // TODO break; case BLE_GAP_EVENT_CONN_UPDATE_REQ: // TODO break; default: break; } return 0; } int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) { if (ble_gap_disc_active()) { mp_bluetooth_gap_scan_stop(); } // TODO: This is the same as ble_gap_conn_params_dflt (i.e. passing NULL). STATIC const struct ble_gap_conn_params params = { .scan_itvl = 0x0010, .scan_window = 0x0010, .itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN, .itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX, .latency = BLE_GAP_INITIAL_CONN_LATENCY, .supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT, .min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN, .max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN, }; ble_addr_t addr_nimble = create_nimble_addr(addr_type, addr); int err = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &addr_nimble, duration_ms, ¶ms, &peripheral_gap_event_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int peripheral_discover_service_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg) { DEBUG_EVENT_printf("peripheral_discover_service_cb: conn_handle=%d status=%d start_handle=%d\n", conn_handle, error->status, service ? service->start_handle : -1); if (error->status == 0) { mp_obj_bluetooth_uuid_t service_uuid = create_mp_uuid(&service->uuid); mp_bluetooth_gattc_on_primary_service_result(conn_handle, service->start_handle, service->end_handle, &service_uuid); } return 0; } int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle) { int err = ble_gattc_disc_all_svcs(conn_handle, &peripheral_discover_service_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int ble_gatt_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) { DEBUG_EVENT_printf("ble_gatt_characteristic_cb: conn_handle=%d status=%d def_handle=%d val_handle=%d\n", conn_handle, error->status, characteristic ? characteristic->def_handle : -1, characteristic ? characteristic->val_handle : -1); if (error->status == 0) { mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(&characteristic->uuid); mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic->def_handle, characteristic->val_handle, characteristic->properties, &characteristic_uuid); } return 0; } int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) { int err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gatt_characteristic_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int ble_gatt_descriptor_cb(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t characteristic_val_handle, const struct ble_gatt_dsc *descriptor, void *arg) { DEBUG_EVENT_printf("ble_gatt_descriptor_cb: conn_handle=%d status=%d chr_handle=%d dsc_handle=%d\n", conn_handle, error->status, characteristic_val_handle, descriptor ? descriptor->handle : -1); if (error->status == 0) { mp_obj_bluetooth_uuid_t descriptor_uuid = create_mp_uuid(&descriptor->uuid); mp_bluetooth_gattc_on_descriptor_result(conn_handle, descriptor->handle, &descriptor_uuid); } return 0; } int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) { int err = ble_gattc_disc_all_dscs(conn_handle, start_handle, end_handle, &ble_gatt_descriptor_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int ble_gatt_attr_read_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { DEBUG_EVENT_printf("ble_gatt_attr_read_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1); // TODO: Maybe send NULL if error->status non-zero. if (error->status == 0) { gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, attr->handle, attr->om); } return 0; } // Initiate read of a value from the remote peripheral. int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) { int err = ble_gattc_read(conn_handle, value_handle, &ble_gatt_attr_read_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int ble_gatt_attr_write_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { DEBUG_EVENT_printf("ble_gatt_attr_write_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1); mp_bluetooth_gattc_on_write_status(conn_handle, attr->handle, error->status); return 0; } // Write the value to the remote peripheral. int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) { int err; if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) { err = ble_gattc_write_no_rsp_flat(conn_handle, value_handle, value, *value_len); } else if (mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) { err = ble_gattc_write_flat(conn_handle, value_handle, value, *value_len, &ble_gatt_attr_write_cb, NULL); } else { err = BLE_HS_EINVAL; } return ble_hs_err_to_errno(err); } #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE micropython-1.12/extmod/modbluetooth_nimble.h000066400000000000000000000040711357706137100215300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Jim Mussared * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_NIMBLE_H #define MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_NIMBLE_H #define MP_BLUETOOTH_NIMBLE_MAX_SERVICES (8) typedef struct _mp_bluetooth_nimble_root_pointers_t { // Characteristic (and descriptor) value storage. mp_map_t *gatts_db; // Pending service definitions. size_t n_services; struct ble_gatt_svc_def *services[MP_BLUETOOTH_NIMBLE_MAX_SERVICES]; } mp_bluetooth_nimble_root_pointers_t; enum { MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF, MP_BLUETOOTH_NIMBLE_BLE_STATE_STARTING, MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE, }; extern volatile int mp_bluetooth_nimble_ble_state; void mp_bluetooth_nimble_port_preinit(void); void mp_bluetooth_nimble_port_postinit(void); void mp_bluetooth_nimble_port_deinit(void); void mp_bluetooth_nimble_port_start(void); #endif // MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_NIMBLE_H micropython-1.12/extmod/modbtree.c000066400000000000000000000313571357706137100173000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include // for declaration of global errno variable #include #include "py/runtime.h" #include "py/stream.h" #if MICROPY_PY_BTREE #include #include <../../btree/btree.h> typedef struct _mp_obj_btree_t { mp_obj_base_t base; DB *db; mp_obj_t start_key; mp_obj_t end_key; #define FLAG_END_KEY_INCL 1 #define FLAG_DESC 2 #define FLAG_ITER_TYPE_MASK 0xc0 #define FLAG_ITER_KEYS 0x40 #define FLAG_ITER_VALUES 0x80 #define FLAG_ITER_ITEMS 0xc0 byte flags; byte next_flags; } mp_obj_btree_t; #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_obj_type_t btree_type; #endif #define CHECK_ERROR(res) \ if (res == RET_ERROR) { \ mp_raise_OSError(errno); \ } void __dbpanic(DB *db) { mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db); } STATIC mp_obj_btree_t *btree_new(DB *db) { mp_obj_btree_t *o = m_new_obj(mp_obj_btree_t); o->base.type = &btree_type; o->db = db; o->start_key = mp_const_none; o->end_key = mp_const_none; o->next_flags = 0; return o; } STATIC void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->db); } STATIC mp_obj_t btree_flush(mp_obj_t self_in) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(__bt_sync(self->db, 0)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(btree_flush_obj, btree_flush); STATIC mp_obj_t btree_close(mp_obj_t self_in) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(__bt_close(self->db)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(btree_close_obj, btree_close); STATIC mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); DBT key, val; key.data = (void*)mp_obj_str_get_data(args[1], &key.size); val.data = (void*)mp_obj_str_get_data(args[2], &val.size); return MP_OBJ_NEW_SMALL_INT(__bt_put(self->db, &key, &val, 0)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put); STATIC mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); DBT key, val; key.data = (void*)mp_obj_str_get_data(args[1], &key.size); int res = __bt_get(self->db, &key, &val, 0); if (res == RET_SPECIAL) { if (n_args > 2) { return args[2]; } else { return mp_const_none; } } CHECK_ERROR(res); return mp_obj_new_bytes(val.data, val.size); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_get_obj, 2, 3, btree_get); STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); int flags = MP_OBJ_SMALL_INT_VALUE(args[1]); DBT key, val; if (n_args > 2) { key.data = (void*)mp_obj_str_get_data(args[2], &key.size); } int res = __bt_seq(self->db, &key, &val, flags); CHECK_ERROR(res); if (res == RET_SPECIAL) { return mp_const_none; } mp_obj_t pair_o = mp_obj_new_tuple(2, NULL); mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(pair_o); pair->items[0] = mp_obj_new_bytes(key.data, key.size); pair->items[1] = mp_obj_new_bytes(val.data, val.size); return pair_o; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_seq_obj, 2, 4, btree_seq); STATIC mp_obj_t btree_init_iter(size_t n_args, const mp_obj_t *args, byte type) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]); self->next_flags = type; self->start_key = mp_const_none; self->end_key = mp_const_none; if (n_args > 1) { self->start_key = args[1]; if (n_args > 2) { self->end_key = args[2]; if (n_args > 3) { self->next_flags = type | MP_OBJ_SMALL_INT_VALUE(args[3]); } } } return args[0]; } STATIC mp_obj_t btree_keys(size_t n_args, const mp_obj_t *args) { return btree_init_iter(n_args, args, FLAG_ITER_KEYS); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_keys_obj, 1, 4, btree_keys); STATIC mp_obj_t btree_values(size_t n_args, const mp_obj_t *args) { return btree_init_iter(n_args, args, FLAG_ITER_VALUES); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_values_obj, 1, 4, btree_values); STATIC mp_obj_t btree_items(size_t n_args, const mp_obj_t *args) { return btree_init_iter(n_args, args, FLAG_ITER_ITEMS); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_items_obj, 1, 4, btree_items); STATIC mp_obj_t btree_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { (void)iter_buf; mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); if (self->next_flags != 0) { // If we're called immediately after keys(), values(), or items(), // use their setup for iteration. self->flags = self->next_flags; self->next_flags = 0; } else { // Otherwise, iterate over all keys. self->flags = FLAG_ITER_KEYS; self->start_key = mp_const_none; self->end_key = mp_const_none; } return self_in; } STATIC mp_obj_t btree_iternext(mp_obj_t self_in) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); DBT key, val; int res; bool desc = self->flags & FLAG_DESC; if (self->start_key != MP_OBJ_NULL) { int flags = R_FIRST; if (self->start_key != mp_const_none) { key.data = (void*)mp_obj_str_get_data(self->start_key, &key.size); flags = R_CURSOR; } else if (desc) { flags = R_LAST; } res = __bt_seq(self->db, &key, &val, flags); self->start_key = MP_OBJ_NULL; } else { res = __bt_seq(self->db, &key, &val, desc ? R_PREV : R_NEXT); } if (res == RET_SPECIAL) { return MP_OBJ_STOP_ITERATION; } CHECK_ERROR(res); if (self->end_key != mp_const_none) { DBT end_key; end_key.data = (void*)mp_obj_str_get_data(self->end_key, &end_key.size); BTREE *t = self->db->internal; int cmp = t->bt_cmp(&key, &end_key); if (desc) { cmp = -cmp; } if (self->flags & FLAG_END_KEY_INCL) { cmp--; } if (cmp >= 0) { self->end_key = MP_OBJ_NULL; return MP_OBJ_STOP_ITERATION; } } switch (self->flags & FLAG_ITER_TYPE_MASK) { case FLAG_ITER_KEYS: return mp_obj_new_bytes(key.data, key.size); case FLAG_ITER_VALUES: return mp_obj_new_bytes(val.data, val.size); default: { mp_obj_t pair_o = mp_obj_new_tuple(2, NULL); mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(pair_o); pair->items[0] = mp_obj_new_bytes(key.data, key.size); pair->items[1] = mp_obj_new_bytes(val.data, val.size); return pair_o; } } } STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); if (value == MP_OBJ_NULL) { // delete DBT key; key.data = (void*)mp_obj_str_get_data(index, &key.size); int res = __bt_delete(self->db, &key, 0); if (res == RET_SPECIAL) { nlr_raise(mp_obj_new_exception(&mp_type_KeyError)); } CHECK_ERROR(res); return mp_const_none; } else if (value == MP_OBJ_SENTINEL) { // load DBT key, val; key.data = (void*)mp_obj_str_get_data(index, &key.size); int res = __bt_get(self->db, &key, &val, 0); if (res == RET_SPECIAL) { nlr_raise(mp_obj_new_exception(&mp_type_KeyError)); } CHECK_ERROR(res); return mp_obj_new_bytes(val.data, val.size); } else { // store DBT key, val; key.data = (void*)mp_obj_str_get_data(index, &key.size); val.data = (void*)mp_obj_str_get_data(value, &val.size); int res = __bt_put(self->db, &key, &val, 0); CHECK_ERROR(res); return mp_const_none; } } STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in); switch (op) { case MP_BINARY_OP_CONTAINS: { DBT key, val; key.data = (void*)mp_obj_str_get_data(rhs_in, &key.size); int res = __bt_get(self->db, &key, &val, 0); CHECK_ERROR(res); return mp_obj_new_bool(res != RET_SPECIAL); } default: // op not supported return MP_OBJ_NULL; } } #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&btree_close_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&btree_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&btree_get_obj) }, { MP_ROM_QSTR(MP_QSTR_put), MP_ROM_PTR(&btree_put_obj) }, { MP_ROM_QSTR(MP_QSTR_seq), MP_ROM_PTR(&btree_seq_obj) }, { MP_ROM_QSTR(MP_QSTR_keys), MP_ROM_PTR(&btree_keys_obj) }, { MP_ROM_QSTR(MP_QSTR_values), MP_ROM_PTR(&btree_values_obj) }, { MP_ROM_QSTR(MP_QSTR_items), MP_ROM_PTR(&btree_items_obj) }, }; STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table); STATIC const mp_obj_type_t btree_type = { { &mp_type_type }, // Save on qstr's, reuse same as for module .name = MP_QSTR_btree, .print = btree_print, .getiter = btree_getiter, .iternext = btree_iternext, .binary_op = btree_binary_op, .subscr = btree_subscr, .locals_dict = (void*)&btree_locals_dict, }; #endif STATIC const FILEVTABLE btree_stream_fvtable = { mp_stream_posix_read, mp_stream_posix_write, mp_stream_posix_lseek, mp_stream_posix_fsync }; #if !MICROPY_ENABLE_DYNRUNTIME STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_cachesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_pagesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_minkeypage, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; // Make sure we got a stream object mp_get_stream_raise(pos_args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); struct { mp_arg_val_t flags; mp_arg_val_t cachesize; mp_arg_val_t pagesize; mp_arg_val_t minkeypage; } args; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); BTREEINFO openinfo = {0}; openinfo.flags = args.flags.u_int; openinfo.cachesize = args.cachesize.u_int; openinfo.psize = args.pagesize.u_int; openinfo.minkeypage = args.minkeypage.u_int; DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, /*dflags*/0); if (db == NULL) { mp_raise_OSError(errno); } return MP_OBJ_FROM_PTR(btree_new(db)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_btree_open_obj, 1, mod_btree_open); STATIC const mp_rom_map_elem_t mp_module_btree_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_btree) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_btree_open_obj) }, { MP_ROM_QSTR(MP_QSTR_INCL), MP_ROM_INT(FLAG_END_KEY_INCL) }, { MP_ROM_QSTR(MP_QSTR_DESC), MP_ROM_INT(FLAG_DESC) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_btree_globals, mp_module_btree_globals_table); const mp_obj_module_t mp_module_btree = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_btree_globals, }; #endif #endif // MICROPY_PY_BTREE micropython-1.12/extmod/modframebuf.c000066400000000000000000000523131357706137100177610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_FRAMEBUF #include "ports/stm32/font_petme128_8x8.h" typedef struct _mp_obj_framebuf_t { mp_obj_base_t base; mp_obj_t buf_obj; // need to store this to prevent GC from reclaiming buf void *buf; uint16_t width, height, stride; uint8_t format; } mp_obj_framebuf_t; typedef void (*setpixel_t)(const mp_obj_framebuf_t*, int, int, uint32_t); typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t*, int, int); typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, int, int, int, int, uint32_t); typedef struct _mp_framebuf_p_t { setpixel_t setpixel; getpixel_t getpixel; fill_rect_t fill_rect; } mp_framebuf_p_t; // constants for formats #define FRAMEBUF_MVLSB (0) #define FRAMEBUF_RGB565 (1) #define FRAMEBUF_GS2_HMSB (5) #define FRAMEBUF_GS4_HMSB (2) #define FRAMEBUF_GS8 (6) #define FRAMEBUF_MHLSB (3) #define FRAMEBUF_MHMSB (4) // Functions for MHLSB and MHMSB STATIC void mono_horiz_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { size_t index = (x + y * fb->stride) >> 3; int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07); ((uint8_t*)fb->buf)[index] = (((uint8_t*)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset); } STATIC uint32_t mono_horiz_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { size_t index = (x + y * fb->stride) >> 3; int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07); return (((uint8_t*)fb->buf)[index] >> (offset)) & 0x01; } STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { int reverse = fb->format == FRAMEBUF_MHMSB; int advance = fb->stride >> 3; while (w--) { uint8_t *b = &((uint8_t*)fb->buf)[(x >> 3) + y * advance]; int offset = reverse ? x & 7 : 7 - (x & 7); for (int hh = h; hh; --hh) { *b = (*b & ~(0x01 << offset)) | ((col != 0) << offset); b += advance; } ++x; } } // Functions for MVLSB format STATIC void mvlsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { size_t index = (y >> 3) * fb->stride + x; uint8_t offset = y & 0x07; ((uint8_t*)fb->buf)[index] = (((uint8_t*)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset); } STATIC uint32_t mvlsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { return (((uint8_t*)fb->buf)[(y >> 3) * fb->stride + x] >> (y & 0x07)) & 0x01; } STATIC void mvlsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { while (h--) { uint8_t *b = &((uint8_t*)fb->buf)[(y >> 3) * fb->stride + x]; uint8_t offset = y & 0x07; for (int ww = w; ww; --ww) { *b = (*b & ~(0x01 << offset)) | ((col != 0) << offset); ++b; } ++y; } } // Functions for RGB565 format STATIC void rgb565_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { ((uint16_t*)fb->buf)[x + y * fb->stride] = col; } STATIC uint32_t rgb565_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { return ((uint16_t*)fb->buf)[x + y * fb->stride]; } STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { uint16_t *b = &((uint16_t*)fb->buf)[x + y * fb->stride]; while (h--) { for (int ww = w; ww; --ww) { *b++ = col; } b += fb->stride - w; } } // Functions for GS2_HMSB format STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2]; uint8_t shift = (x & 0x3) << 1; uint8_t mask = 0x3 << shift; uint8_t color = (col & 0x3) << shift; *pixel = color | (*pixel & (~mask)); } STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { uint8_t pixel = ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2]; uint8_t shift = (x & 0x3) << 1; return (pixel >> shift) & 0x3; } STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { for (int xx=x; xx < x+w; xx++) { for (int yy=y; yy < y+h; yy++) { gs2_hmsb_setpixel(fb, xx, yy, col); } } } // Functions for GS4_HMSB format STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 1]; if (x % 2) { *pixel = ((uint8_t)col & 0x0f) | (*pixel & 0xf0); } else { *pixel = ((uint8_t)col << 4) | (*pixel & 0x0f); } } STATIC uint32_t gs4_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { if (x % 2) { return ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 1] & 0x0f; } return ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 1] >> 4; } STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { col &= 0x0f; uint8_t *pixel_pair = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 1]; uint8_t col_shifted_left = col << 4; uint8_t col_pixel_pair = col_shifted_left | col; int pixel_count_till_next_line = (fb->stride - w) >> 1; bool odd_x = (x % 2 == 1); while (h--) { int ww = w; if (odd_x && ww > 0) { *pixel_pair = (*pixel_pair & 0xf0) | col; pixel_pair++; ww--; } memset(pixel_pair, col_pixel_pair, ww >> 1); pixel_pair += ww >> 1; if (ww % 2) { *pixel_pair = col_shifted_left | (*pixel_pair & 0x0f); if (!odd_x) { pixel_pair++; } } pixel_pair += pixel_count_till_next_line; } } // Functions for GS8 format STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride)]; *pixel = col & 0xff; } STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { return ((uint8_t*)fb->buf)[(x + y * fb->stride)]; } STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride)]; while (h--) { memset(pixel, col, w); pixel += fb->stride; } } STATIC mp_framebuf_p_t formats[] = { [FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect}, [FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect}, [FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect}, [FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect}, [FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect}, [FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, }; static inline void setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { formats[fb->format].setpixel(fb, x, y, col); } static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, int x, int y) { return formats[fb->format].getpixel(fb, x, y); } STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { if (h < 1 || w < 1 || x + w <= 0 || y + h <= 0 || y >= fb->height || x >= fb->width) { // No operation needed. return; } // clip to the framebuffer int xend = MIN(fb->width, x + w); int yend = MIN(fb->height, y + h); x = MAX(x, 0); y = MAX(y, 0); formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col); } STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 4, 5, false); mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t); o->base.type = type; o->buf_obj = args[0]; mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE); o->buf = bufinfo.buf; o->width = mp_obj_get_int(args[1]); o->height = mp_obj_get_int(args[2]); o->format = mp_obj_get_int(args[3]); if (n_args >= 5) { o->stride = mp_obj_get_int(args[4]); } else { o->stride = o->width; } switch (o->format) { case FRAMEBUF_MVLSB: case FRAMEBUF_RGB565: break; case FRAMEBUF_MHLSB: case FRAMEBUF_MHMSB: o->stride = (o->stride + 7) & ~7; break; case FRAMEBUF_GS2_HMSB: o->stride = (o->stride + 3) & ~3; break; case FRAMEBUF_GS4_HMSB: o->stride = (o->stride + 1) & ~1; break; case FRAMEBUF_GS8: break; default: mp_raise_ValueError("invalid format"); } return MP_OBJ_FROM_PTR(o); } STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { (void)flags; mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); bufinfo->buf = self->buf; bufinfo->len = self->stride * self->height * (self->format == FRAMEBUF_RGB565 ? 2 : 1); bufinfo->typecode = 'B'; // view framebuf as bytes return 0; } STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) { mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t col = mp_obj_get_int(col_in); formats[self->format].fill_rect(self, 0, 0, self->width, self->height, col); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill); STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t x = mp_obj_get_int(args[1]); mp_int_t y = mp_obj_get_int(args[2]); mp_int_t width = mp_obj_get_int(args[3]); mp_int_t height = mp_obj_get_int(args[4]); mp_int_t col = mp_obj_get_int(args[5]); fill_rect(self, x, y, width, height, col); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect); STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) { mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t x = mp_obj_get_int(args[1]); mp_int_t y = mp_obj_get_int(args[2]); if (0 <= x && x < self->width && 0 <= y && y < self->height) { if (n_args == 3) { // get return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y)); } else { // set setpixel(self, x, y, mp_obj_get_int(args[3])); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel); STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t x = mp_obj_get_int(args[1]); mp_int_t y = mp_obj_get_int(args[2]); mp_int_t w = mp_obj_get_int(args[3]); mp_int_t col = mp_obj_get_int(args[4]); fill_rect(self, x, y, w, 1, col); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline); STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t x = mp_obj_get_int(args[1]); mp_int_t y = mp_obj_get_int(args[2]); mp_int_t h = mp_obj_get_int(args[3]); mp_int_t col = mp_obj_get_int(args[4]); fill_rect(self, x, y, 1, h, col); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline); STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t x = mp_obj_get_int(args[1]); mp_int_t y = mp_obj_get_int(args[2]); mp_int_t w = mp_obj_get_int(args[3]); mp_int_t h = mp_obj_get_int(args[4]); mp_int_t col = mp_obj_get_int(args[5]); fill_rect(self, x, y, w, 1, col); fill_rect(self, x, y + h- 1, w, 1, col); fill_rect(self, x, y, 1, h, col); fill_rect(self, x + w- 1, y, 1, h, col); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect); STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t x1 = mp_obj_get_int(args[1]); mp_int_t y1 = mp_obj_get_int(args[2]); mp_int_t x2 = mp_obj_get_int(args[3]); mp_int_t y2 = mp_obj_get_int(args[4]); mp_int_t col = mp_obj_get_int(args[5]); mp_int_t dx = x2 - x1; mp_int_t sx; if (dx > 0) { sx = 1; } else { dx = -dx; sx = -1; } mp_int_t dy = y2 - y1; mp_int_t sy; if (dy > 0) { sy = 1; } else { dy = -dy; sy = -1; } bool steep; if (dy > dx) { mp_int_t temp; temp = x1; x1 = y1; y1 = temp; temp = dx; dx = dy; dy = temp; temp = sx; sx = sy; sy = temp; steep = true; } else { steep = false; } mp_int_t e = 2 * dy - dx; for (mp_int_t i = 0; i < dx; ++i) { if (steep) { if (0 <= y1 && y1 < self->width && 0 <= x1 && x1 < self->height) { setpixel(self, y1, x1, col); } } else { if (0 <= x1 && x1 < self->width && 0 <= y1 && y1 < self->height) { setpixel(self, x1, y1, col); } } while (e >= 0) { y1 += sy; e -= 2 * dx; } x1 += sx; e += 2 * dy; } if (0 <= x2 && x2 < self->width && 0 <= y2 && y2 < self->height) { setpixel(self, x2, y2, col); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line); STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) { mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(args[1]); mp_int_t x = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[3]); mp_int_t key = -1; if (n_args > 4) { key = mp_obj_get_int(args[4]); } if ( (x >= self->width) || (y >= self->height) || (-x >= source->width) || (-y >= source->height) ) { // Out of bounds, no-op. return mp_const_none; } // Clip. int x0 = MAX(0, x); int y0 = MAX(0, y); int x1 = MAX(0, -x); int y1 = MAX(0, -y); int x0end = MIN(self->width, x + source->width); int y0end = MIN(self->height, y + source->height); for (; y0 < y0end; ++y0) { int cx1 = x1; for (int cx0 = x0; cx0 < x0end; ++cx0) { uint32_t col = getpixel(source, cx1, y1); if (col != (uint32_t)key) { setpixel(self, cx0, y0, col); } ++cx1; } ++y1; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 5, framebuf_blit); STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ystep_in) { mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t xstep = mp_obj_get_int(xstep_in); mp_int_t ystep = mp_obj_get_int(ystep_in); int sx, y, xend, yend, dx, dy; if (xstep < 0) { sx = 0; xend = self->width + xstep; dx = 1; } else { sx = self->width - 1; xend = xstep - 1; dx = -1; } if (ystep < 0) { y = 0; yend = self->height + ystep; dy = 1; } else { y = self->height - 1; yend = ystep - 1; dy = -1; } for (; y != yend; y += dy) { for (int x = sx; x != xend; x += dx) { setpixel(self, x, y, getpixel(self, x - xstep, y - ystep)); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll); STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) { // extract arguments mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); const char *str = mp_obj_str_get_str(args[1]); mp_int_t x0 = mp_obj_get_int(args[2]); mp_int_t y0 = mp_obj_get_int(args[3]); mp_int_t col = 1; if (n_args >= 5) { col = mp_obj_get_int(args[4]); } // loop over chars for (; *str; ++str) { // get char and make sure its in range of font int chr = *(uint8_t*)str; if (chr < 32 || chr > 127) { chr = 127; } // get char data const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8]; // loop over char data for (int j = 0; j < 8; j++, x0++) { if (0 <= x0 && x0 < self->width) { // clip x uint vline_data = chr_data[j]; // each byte is a column of 8 pixels, LSB at top for (int y = y0; vline_data; vline_data >>= 1, y++) { // scan over vertical column if (vline_data & 1) { // only draw if pixel set if (0 <= y && y < self->height) { // clip y setpixel(self, x0, y, col); } } } } } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_text_obj, 4, 5, framebuf_text); #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&framebuf_fill_obj) }, { MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&framebuf_fill_rect_obj) }, { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&framebuf_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_hline), MP_ROM_PTR(&framebuf_hline_obj) }, { MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) }, { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) }, { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) }, { MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) }, { MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) }, { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) }, }; STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table); STATIC const mp_obj_type_t mp_type_framebuf = { { &mp_type_type }, .name = MP_QSTR_FrameBuffer, .make_new = framebuf_make_new, .buffer_p = { .get_buffer = framebuf_get_buffer }, .locals_dict = (mp_obj_dict_t*)&framebuf_locals_dict, }; #endif // this factory function is provided for backwards compatibility with old FrameBuffer1 class STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) { mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t); o->base.type = &mp_type_framebuf; mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE); o->buf = bufinfo.buf; o->width = mp_obj_get_int(args[1]); o->height = mp_obj_get_int(args[2]); o->format = FRAMEBUF_MVLSB; if (n_args >= 4) { o->stride = mp_obj_get_int(args[3]); } else { o->stride = o->width; } return MP_OBJ_FROM_PTR(o); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1); #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) }, { MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) }, { MP_ROM_QSTR(MP_QSTR_FrameBuffer1), MP_ROM_PTR(&legacy_framebuffer1_obj) }, { MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) }, { MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) }, { MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) }, { MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) }, { MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) }, { MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) }, { MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MHLSB) }, { MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MHMSB) }, }; STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table); const mp_obj_module_t mp_module_framebuf = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&framebuf_module_globals, }; #endif #endif // MICROPY_PY_FRAMEBUF micropython-1.12/extmod/modlwip.c000066400000000000000000001702541357706137100171520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2015 Galen Hazelwood * Copyright (c) 2015-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objlist.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "lib/netutils/netutils.h" #include "lwip/init.h" #include "lwip/tcp.h" #include "lwip/udp.h" #include "lwip/raw.h" #include "lwip/dns.h" #include "lwip/igmp.h" #if LWIP_VERSION_MAJOR < 2 #include "lwip/timers.h" #include "lwip/tcp_impl.h" #else #include "lwip/timeouts.h" #include "lwip/priv/tcp_priv.h" #endif #if 0 // print debugging info #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif // Timeout between closing a TCP socket and doing a tcp_abort on that // socket, if the connection isn't closed cleanly in that time. #define MICROPY_PY_LWIP_TCP_CLOSE_TIMEOUT_MS (10000) // All socket options should be globally distinct, // because we ignore option levels for efficiency. #define IP_ADD_MEMBERSHIP 0x400 // For compatibilily with older lwIP versions. #ifndef ip_set_option #define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) #endif #ifndef ip_reset_option #define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) #endif // A port can define these hooks to provide concurrency protection #ifndef MICROPY_PY_LWIP_ENTER #define MICROPY_PY_LWIP_ENTER #define MICROPY_PY_LWIP_REENTER #define MICROPY_PY_LWIP_EXIT #endif #ifdef MICROPY_PY_LWIP_SLIP #include "netif/slipif.h" #include "lwip/sio.h" #endif #ifdef MICROPY_PY_LWIP_SLIP /******************************************************************************/ // Slip object for modlwip. Requires a serial driver for the port that supports // the lwip serial callback functions. typedef struct _lwip_slip_obj_t { mp_obj_base_t base; struct netif lwip_netif; } lwip_slip_obj_t; // Slip object is unique for now. Possibly can fix this later. FIXME STATIC lwip_slip_obj_t lwip_slip_obj; // Declare these early. void mod_lwip_register_poll(void (*poll)(void *arg), void *poll_arg); void mod_lwip_deregister_poll(void (*poll)(void *arg), void *poll_arg); STATIC void slip_lwip_poll(void *netif) { slipif_poll((struct netif*)netif); } STATIC const mp_obj_type_t lwip_slip_type; // lwIP SLIP callback functions sio_fd_t sio_open(u8_t dvnum) { // We support singleton SLIP interface, so just return any truish value. return (sio_fd_t)1; } void sio_send(u8_t c, sio_fd_t fd) { mp_obj_type_t *type = mp_obj_get_type(MP_STATE_VM(lwip_slip_stream)); int error; type->stream_p->write(MP_STATE_VM(lwip_slip_stream), &c, 1, &error); } u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len) { mp_obj_type_t *type = mp_obj_get_type(MP_STATE_VM(lwip_slip_stream)); int error; mp_uint_t out_sz = type->stream_p->read(MP_STATE_VM(lwip_slip_stream), data, len, &error); if (out_sz == MP_STREAM_ERROR) { if (mp_is_nonblocking_error(error)) { return 0; } // Can't do much else, can we? return 0; } return out_sz; } // constructor lwip.slip(device=integer, iplocal=string, ipremote=string) STATIC mp_obj_t lwip_slip_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 3, 3, false); lwip_slip_obj.base.type = &lwip_slip_type; MP_STATE_VM(lwip_slip_stream) = args[0]; ip_addr_t iplocal, ipremote; if (!ipaddr_aton(mp_obj_str_get_str(args[1]), &iplocal)) { mp_raise_ValueError("not a valid local IP"); } if (!ipaddr_aton(mp_obj_str_get_str(args[2]), &ipremote)) { mp_raise_ValueError("not a valid remote IP"); } struct netif *n = &lwip_slip_obj.lwip_netif; if (netif_add(n, &iplocal, IP_ADDR_BROADCAST, &ipremote, NULL, slipif_init, ip_input) == NULL) { mp_raise_ValueError("out of memory"); } netif_set_up(n); netif_set_default(n); mod_lwip_register_poll(slip_lwip_poll, n); return (mp_obj_t)&lwip_slip_obj; } STATIC mp_obj_t lwip_slip_status(mp_obj_t self_in) { // Null function for now. return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(lwip_slip_status_obj, lwip_slip_status); STATIC const mp_rom_map_elem_t lwip_slip_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lwip_slip_status_obj) }, }; STATIC MP_DEFINE_CONST_DICT(lwip_slip_locals_dict, lwip_slip_locals_dict_table); STATIC const mp_obj_type_t lwip_slip_type = { { &mp_type_type }, .name = MP_QSTR_slip, .make_new = lwip_slip_make_new, .locals_dict = (mp_obj_dict_t*)&lwip_slip_locals_dict, }; #endif // MICROPY_PY_LWIP_SLIP /******************************************************************************/ // Table to convert lwIP err_t codes to socket errno codes, from the lwIP // socket API. // lwIP 2 changed LWIP_VERSION and it can no longer be used in macros, // so we define our own equivalent version that can. #define LWIP_VERSION_MACRO (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 \ | LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) // Extension to lwIP error codes #define _ERR_BADF -16 // TODO: We just know that change happened somewhere between 1.4.0 and 1.4.1, // investigate in more detail. #if LWIP_VERSION_MACRO < 0x01040100 static const int error_lookup_table[] = { 0, /* ERR_OK 0 No error, everything OK. */ MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */ MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */ MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ MP_EINVAL, /* ERR_VAL -6 Illegal value. */ MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ MP_ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */ MP_ECONNRESET, /* ERR_RST -9 Connection reset. */ MP_ENOTCONN, /* ERR_CLSD -10 Connection closed. */ MP_ENOTCONN, /* ERR_CONN -11 Not connected. */ MP_EIO, /* ERR_ARG -12 Illegal argument. */ MP_EADDRINUSE, /* ERR_USE -13 Address in use. */ -1, /* ERR_IF -14 Low-level netif error */ MP_EALREADY, /* ERR_ISCONN -15 Already connected. */ MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */ }; #elif LWIP_VERSION_MACRO < 0x02000000 static const int error_lookup_table[] = { 0, /* ERR_OK 0 No error, everything OK. */ MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */ MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */ MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ MP_EINVAL, /* ERR_VAL -6 Illegal value. */ MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ MP_EADDRINUSE, /* ERR_USE -8 Address in use. */ MP_EALREADY, /* ERR_ISCONN -9 Already connected. */ MP_ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */ MP_ECONNRESET, /* ERR_RST -11 Connection reset. */ MP_ENOTCONN, /* ERR_CLSD -12 Connection closed. */ MP_ENOTCONN, /* ERR_CONN -13 Not connected. */ MP_EIO, /* ERR_ARG -14 Illegal argument. */ -1, /* ERR_IF -15 Low-level netif error */ MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */ }; #else // Matches lwIP 2.0.3 #undef _ERR_BADF #define _ERR_BADF -17 static const int error_lookup_table[] = { 0, /* ERR_OK 0 No error, everything OK */ MP_ENOMEM, /* ERR_MEM -1 Out of memory error */ MP_ENOBUFS, /* ERR_BUF -2 Buffer error */ MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem */ MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ MP_EINVAL, /* ERR_VAL -6 Illegal value */ MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block */ MP_EADDRINUSE, /* ERR_USE -8 Address in use */ MP_EALREADY, /* ERR_ALREADY -9 Already connecting */ MP_EALREADY, /* ERR_ISCONN -10 Conn already established */ MP_ENOTCONN, /* ERR_CONN -11 Not connected */ -1, /* ERR_IF -12 Low-level netif error */ MP_ECONNABORTED, /* ERR_ABRT -13 Connection aborted */ MP_ECONNRESET, /* ERR_RST -14 Connection reset */ MP_ENOTCONN, /* ERR_CLSD -15 Connection closed */ MP_EIO, /* ERR_ARG -16 Illegal argument. */ MP_EBADF, /* _ERR_BADF -17 Closed socket (null pcb) */ }; #endif /*******************************************************************************/ // The socket object provided by lwip.socket. #define MOD_NETWORK_AF_INET (2) #define MOD_NETWORK_AF_INET6 (10) #define MOD_NETWORK_SOCK_STREAM (1) #define MOD_NETWORK_SOCK_DGRAM (2) #define MOD_NETWORK_SOCK_RAW (3) typedef struct _lwip_socket_obj_t { mp_obj_base_t base; volatile union { struct tcp_pcb *tcp; struct udp_pcb *udp; struct raw_pcb *raw; } pcb; volatile union { struct pbuf *pbuf; struct { uint8_t alloc; uint8_t iget; uint8_t iput; union { struct tcp_pcb *item; // if alloc == 0 struct tcp_pcb **array; // if alloc != 0 } tcp; } connection; } incoming; mp_obj_t callback; byte peer[4]; mp_uint_t peer_port; mp_uint_t timeout; uint16_t recv_offset; uint8_t domain; uint8_t type; #define STATE_NEW 0 #define STATE_LISTENING 1 #define STATE_CONNECTING 2 #define STATE_CONNECTED 3 #define STATE_PEER_CLOSED 4 // Negative value is lwIP error int8_t state; } lwip_socket_obj_t; static inline void poll_sockets(void) { #ifdef MICROPY_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK; #else mp_hal_delay_ms(1); #endif } STATIC struct tcp_pcb *volatile *lwip_socket_incoming_array(lwip_socket_obj_t *socket) { if (socket->incoming.connection.alloc == 0) { return &socket->incoming.connection.tcp.item; } else { return &socket->incoming.connection.tcp.array[0]; } } STATIC void lwip_socket_free_incoming(lwip_socket_obj_t *socket) { bool socket_is_listener = socket->type == MOD_NETWORK_SOCK_STREAM && socket->pcb.tcp->state == LISTEN; if (!socket_is_listener) { if (socket->incoming.pbuf != NULL) { pbuf_free(socket->incoming.pbuf); socket->incoming.pbuf = NULL; } } else { uint8_t alloc = socket->incoming.connection.alloc; struct tcp_pcb *volatile *tcp_array = lwip_socket_incoming_array(socket); for (uint8_t i = 0; i < alloc; ++i) { // Deregister callback and abort if (tcp_array[i] != NULL) { tcp_poll(tcp_array[i], NULL, 0); tcp_abort(tcp_array[i]); tcp_array[i] = NULL; } } } } /*******************************************************************************/ // Callback functions for the lwIP raw API. static inline void exec_user_callback(lwip_socket_obj_t *socket) { if (socket->callback != MP_OBJ_NULL) { // Schedule the user callback to execute outside the lwIP context mp_sched_schedule(socket->callback, MP_OBJ_FROM_PTR(socket)); } } #if MICROPY_PY_LWIP_SOCK_RAW // Callback for incoming raw packets. #if LWIP_VERSION_MAJOR < 2 STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr) #else STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) #endif { lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; if (socket->incoming.pbuf != NULL) { pbuf_free(p); } else { socket->incoming.pbuf = p; memcpy(&socket->peer, addr, sizeof(socket->peer)); } return 1; // we ate the packet } #endif // Callback for incoming UDP packets. We simply stash the packet and the source address, // in case we need it for recvfrom. #if LWIP_VERSION_MAJOR < 2 STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port) #else STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) #endif { lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; if (socket->incoming.pbuf != NULL) { // That's why they call it "unreliable". No room in the inn, drop the packet. pbuf_free(p); } else { socket->incoming.pbuf = p; socket->peer_port = (mp_uint_t)port; memcpy(&socket->peer, addr, sizeof(socket->peer)); } } // Callback for general tcp errors. STATIC void _lwip_tcp_error(void *arg, err_t err) { lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; // Free any incoming buffers or connections that are stored lwip_socket_free_incoming(socket); // Pass the error code back via the connection variable. socket->state = err; // If we got here, the lwIP stack either has deallocated or will deallocate the pcb. socket->pcb.tcp = NULL; } // Callback for tcp connection requests. Error code err is unused. (See tcp.h) STATIC err_t _lwip_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) { lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; socket->state = STATE_CONNECTED; return ERR_OK; } // Handle errors (eg connection aborted) on TCP PCBs that have been put on the // accept queue but are not yet actually accepted. STATIC void _lwip_tcp_err_unaccepted(void *arg, err_t err) { struct tcp_pcb *pcb = (struct tcp_pcb*)arg; // The ->connected entry is repurposed to store the parent socket; this is safe // because it's only ever used by lwIP if tcp_connect is called on the TCP PCB. lwip_socket_obj_t *socket = (lwip_socket_obj_t*)pcb->connected; // Array is not volatile because thiss callback is executed within the lwIP context uint8_t alloc = socket->incoming.connection.alloc; struct tcp_pcb **tcp_array = (struct tcp_pcb**)lwip_socket_incoming_array(socket); // Search for PCB on the accept queue of the parent socket struct tcp_pcb **shift_down = NULL; uint8_t i = socket->incoming.connection.iget; do { if (shift_down == NULL) { if (tcp_array[i] == pcb) { shift_down = &tcp_array[i]; } } else { *shift_down = tcp_array[i]; shift_down = &tcp_array[i]; } if (++i >= alloc) { i = 0; } } while (i != socket->incoming.connection.iput); // PCB found in queue, remove it if (shift_down != NULL) { *shift_down = NULL; socket->incoming.connection.iput = shift_down - tcp_array; } } // By default, a child socket of listen socket is created with recv // handler which discards incoming pbuf's. We don't want to do that, // so set this handler which requests lwIP to keep pbuf's and deliver // them later. We cannot cache pbufs in child socket on Python side, // until it is created in accept(). STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { return ERR_BUF; } // Callback for incoming tcp connections. STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { // err can be ERR_MEM to notify us that there was no memory for an incoming connection if (err != ERR_OK) { return ERR_OK; } lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; tcp_recv(newpcb, _lwip_tcp_recv_unaccepted); // Search for an empty slot to store the new connection struct tcp_pcb *volatile *slot = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iput]; if (*slot == NULL) { // Have an empty slot to store waiting connection *slot = newpcb; if (++socket->incoming.connection.iput >= socket->incoming.connection.alloc) { socket->incoming.connection.iput = 0; } // Schedule user accept callback exec_user_callback(socket); // Set the error callback to handle the case of a dropped connection before we // have a chance to take it off the accept queue. // The ->connected entry is repurposed to store the parent socket; this is safe // because it's only ever used by lwIP if tcp_connect is called on the TCP PCB. newpcb->connected = (void*)socket; tcp_arg(newpcb, newpcb); tcp_err(newpcb, _lwip_tcp_err_unaccepted); return ERR_OK; } DEBUG_printf("_lwip_tcp_accept: No room to queue pcb waiting for accept\n"); return ERR_BUF; } // Callback for inbound tcp packets. STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err_t err) { lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; if (p == NULL) { // Other side has closed connection. DEBUG_printf("_lwip_tcp_recv[%p]: other side closed connection\n", socket); socket->state = STATE_PEER_CLOSED; exec_user_callback(socket); return ERR_OK; } if (socket->incoming.pbuf == NULL) { socket->incoming.pbuf = p; } else { #ifdef SOCKET_SINGLE_PBUF return ERR_BUF; #else pbuf_cat(socket->incoming.pbuf, p); #endif } exec_user_callback(socket); return ERR_OK; } /*******************************************************************************/ // Functions for socket send/receive operations. Socket send/recv and friends call // these to do the work. // Helper function for send/sendto to handle raw/UDP packets. STATIC mp_uint_t lwip_raw_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { if (len > 0xffff) { // Any packet that big is probably going to fail the pbuf_alloc anyway, but may as well try len = 0xffff; } MICROPY_PY_LWIP_ENTER // FIXME: maybe PBUF_ROM? struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); if (p == NULL) { MICROPY_PY_LWIP_EXIT *_errno = MP_ENOMEM; return -1; } memcpy(p->payload, buf, len); err_t err; if (ip == NULL) { #if MICROPY_PY_LWIP_SOCK_RAW if (socket->type == MOD_NETWORK_SOCK_RAW) { err = raw_send(socket->pcb.raw, p); } else #endif { err = udp_send(socket->pcb.udp, p); } } else { ip_addr_t dest; IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]); #if MICROPY_PY_LWIP_SOCK_RAW if (socket->type == MOD_NETWORK_SOCK_RAW) { err = raw_sendto(socket->pcb.raw, p, &dest); } else #endif { err = udp_sendto(socket->pcb.udp, p, &dest, port); } } pbuf_free(p); MICROPY_PY_LWIP_EXIT // udp_sendto can return 1 on occasion for ESP8266 port. It's not known why // but it seems that the send actually goes through without error in this case. // So we treat such cases as a success until further investigation. if (err != ERR_OK && err != 1) { *_errno = error_lookup_table[-err]; return -1; } return len; } // Helper function for recv/recvfrom to handle raw/UDP packets STATIC mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { if (socket->incoming.pbuf == NULL) { if (socket->timeout != -1) { for (mp_uint_t retries = socket->timeout / 100; retries--;) { mp_hal_delay_ms(100); if (socket->incoming.pbuf != NULL) break; } if (socket->incoming.pbuf == NULL) { *_errno = MP_ETIMEDOUT; return -1; } } else { while (socket->incoming.pbuf == NULL) { poll_sockets(); } } } if (ip != NULL) { memcpy(ip, &socket->peer, sizeof(socket->peer)); *port = socket->peer_port; } struct pbuf *p = socket->incoming.pbuf; MICROPY_PY_LWIP_ENTER u16_t result = pbuf_copy_partial(p, buf, ((p->tot_len > len) ? len : p->tot_len), 0); pbuf_free(p); socket->incoming.pbuf = NULL; MICROPY_PY_LWIP_EXIT return (mp_uint_t) result; } // For use in stream virtual methods #define STREAM_ERROR_CHECK(socket) \ if (socket->state < 0) { \ *_errno = error_lookup_table[-socket->state]; \ return MP_STREAM_ERROR; \ } \ assert(socket->pcb.tcp); // Version of above for use when lock is held #define STREAM_ERROR_CHECK_WITH_LOCK(socket) \ if (socket->state < 0) { \ *_errno = error_lookup_table[-socket->state]; \ MICROPY_PY_LWIP_EXIT \ return MP_STREAM_ERROR; \ } \ assert(socket->pcb.tcp); // Helper function for send/sendto to handle TCP packets STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { // Check for any pending errors STREAM_ERROR_CHECK(socket); MICROPY_PY_LWIP_ENTER u16_t available = tcp_sndbuf(socket->pcb.tcp); if (available == 0) { // Non-blocking socket if (socket->timeout == 0) { MICROPY_PY_LWIP_EXIT *_errno = MP_EAGAIN; return MP_STREAM_ERROR; } mp_uint_t start = mp_hal_ticks_ms(); // Assume that STATE_PEER_CLOSED may mean half-closed connection, where peer closed it // sending direction, but not receiving. Consequently, check for both STATE_CONNECTED // and STATE_PEER_CLOSED as normal conditions and still waiting for buffers to be sent. // If peer fully closed socket, we would have socket->state set to ERR_RST (connection // reset) by error callback. // Avoid sending too small packets, so wait until at least 16 bytes available while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) { MICROPY_PY_LWIP_EXIT if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) { *_errno = MP_ETIMEDOUT; return MP_STREAM_ERROR; } poll_sockets(); MICROPY_PY_LWIP_REENTER } // While we waited, something could happen STREAM_ERROR_CHECK_WITH_LOCK(socket); } u16_t write_len = MIN(available, len); // If tcp_write returns ERR_MEM then there's currently not enough memory to // queue the write, so wait and keep trying until it succeeds (with 10s limit). // Note: if the socket is non-blocking then this code will actually block until // there's enough memory to do the write, but by this stage we have already // committed to being able to write the data. err_t err; for (int i = 0; i < 200; ++i) { err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY); if (err != ERR_MEM) { break; } err = tcp_output(socket->pcb.tcp); if (err != ERR_OK) { break; } MICROPY_PY_LWIP_EXIT mp_hal_delay_ms(50); MICROPY_PY_LWIP_REENTER } // If the output buffer is getting full then send the data to the lower layers if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) { err = tcp_output(socket->pcb.tcp); } MICROPY_PY_LWIP_EXIT if (err != ERR_OK) { *_errno = error_lookup_table[-err]; return MP_STREAM_ERROR; } return write_len; } // Helper function for recv/recvfrom to handle TCP packets STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { // Check for any pending errors STREAM_ERROR_CHECK(socket); if (socket->incoming.pbuf == NULL) { // Non-blocking socket if (socket->timeout == 0) { if (socket->state == STATE_PEER_CLOSED) { return 0; } *_errno = MP_EAGAIN; return -1; } mp_uint_t start = mp_hal_ticks_ms(); while (socket->state == STATE_CONNECTED && socket->incoming.pbuf == NULL) { if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) { *_errno = MP_ETIMEDOUT; return -1; } poll_sockets(); } if (socket->state == STATE_PEER_CLOSED) { if (socket->incoming.pbuf == NULL) { // socket closed and no data left in buffer return 0; } } else if (socket->state != STATE_CONNECTED) { assert(socket->state < 0); *_errno = error_lookup_table[-socket->state]; return -1; } } MICROPY_PY_LWIP_ENTER assert(socket->pcb.tcp != NULL); struct pbuf *p = socket->incoming.pbuf; mp_uint_t remaining = p->len - socket->recv_offset; if (len > remaining) { len = remaining; } memcpy(buf, (byte*)p->payload + socket->recv_offset, len); remaining -= len; if (remaining == 0) { socket->incoming.pbuf = p->next; // If we don't ref here, free() will free the entire chain, // if we ref, it does what we need: frees 1st buf, and decrements // next buf's refcount back to 1. pbuf_ref(p->next); pbuf_free(p); socket->recv_offset = 0; } else { socket->recv_offset += len; } tcp_recved(socket->pcb.tcp, len); MICROPY_PY_LWIP_EXIT return len; } /*******************************************************************************/ // The socket functions provided by lwip.socket. STATIC const mp_obj_type_t lwip_socket_type; STATIC void lwip_socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { lwip_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->state, self->timeout, self->incoming.pbuf, self->recv_offset); } // FIXME: Only supports two arguments at present STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 4, false); lwip_socket_obj_t *socket = m_new_obj_with_finaliser(lwip_socket_obj_t); socket->base.type = &lwip_socket_type; socket->domain = MOD_NETWORK_AF_INET; socket->type = MOD_NETWORK_SOCK_STREAM; socket->callback = MP_OBJ_NULL; if (n_args >= 1) { socket->domain = mp_obj_get_int(args[0]); if (n_args >= 2) { socket->type = mp_obj_get_int(args[1]); } } switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: socket->pcb.tcp = tcp_new(); socket->incoming.connection.alloc = 0; socket->incoming.connection.tcp.item = NULL; break; case MOD_NETWORK_SOCK_DGRAM: socket->pcb.udp = udp_new(); socket->incoming.pbuf = NULL; break; #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: { mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int(args[2]); socket->pcb.raw = raw_new(proto); break; } #endif default: mp_raise_OSError(MP_EINVAL); } if (socket->pcb.tcp == NULL) { mp_raise_OSError(MP_ENOMEM); } switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { // Register the socket object as our callback argument. tcp_arg(socket->pcb.tcp, (void*)socket); // Register our error callback. tcp_err(socket->pcb.tcp, _lwip_tcp_error); break; } case MOD_NETWORK_SOCK_DGRAM: { // Register our receive callback now. Since UDP sockets don't require binding or connection // before use, there's no other good time to do it. udp_recv(socket->pcb.udp, _lwip_udp_incoming, (void*)socket); break; } #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: { // Register our receive callback now. Since raw sockets don't require binding or connection // before use, there's no other good time to do it. raw_recv(socket->pcb.raw, _lwip_raw_incoming, (void*)socket); break; } #endif } socket->timeout = -1; socket->state = STATE_NEW; socket->recv_offset = 0; return MP_OBJ_FROM_PTR(socket); } STATIC mp_obj_t lwip_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); ip_addr_t bind_addr; IP4_ADDR(&bind_addr, ip[0], ip[1], ip[2], ip[3]); err_t err = ERR_ARG; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { err = tcp_bind(socket->pcb.tcp, &bind_addr, port); break; } case MOD_NETWORK_SOCK_DGRAM: { err = udp_bind(socket->pcb.udp, &bind_addr, port); break; } } if (err != ERR_OK) { mp_raise_OSError(error_lookup_table[-err]); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_bind_obj, lwip_socket_bind); STATIC mp_obj_t lwip_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); mp_int_t backlog = mp_obj_get_int(backlog_in); if (socket->pcb.tcp == NULL) { mp_raise_OSError(MP_EBADF); } if (socket->type != MOD_NETWORK_SOCK_STREAM) { mp_raise_OSError(MP_EOPNOTSUPP); } struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog); if (new_pcb == NULL) { mp_raise_OSError(MP_ENOMEM); } socket->pcb.tcp = new_pcb; // Allocate memory for the backlog of connections if (backlog <= 1) { socket->incoming.connection.alloc = 0; socket->incoming.connection.tcp.item = NULL; } else { socket->incoming.connection.alloc = backlog; socket->incoming.connection.tcp.array = m_new0(struct tcp_pcb*, backlog); } socket->incoming.connection.iget = 0; socket->incoming.connection.iput = 0; tcp_accept(new_pcb, _lwip_tcp_accept); // Socket is no longer considered "new" for purposes of polling socket->state = STATE_LISTENING; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_listen_obj, lwip_socket_listen); STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); if (socket->type != MOD_NETWORK_SOCK_STREAM) { mp_raise_OSError(MP_EOPNOTSUPP); } // Create new socket object, do it here because we must not raise an out-of-memory // exception when the LWIP concurrency lock is held lwip_socket_obj_t *socket2 = m_new_obj_with_finaliser(lwip_socket_obj_t); socket2->base.type = &lwip_socket_type; MICROPY_PY_LWIP_ENTER if (socket->pcb.tcp == NULL) { MICROPY_PY_LWIP_EXIT m_del_obj(lwip_socket_obj_t, socket2); mp_raise_OSError(MP_EBADF); } // I need to do this because "tcp_accepted", later, is a macro. struct tcp_pcb *listener = socket->pcb.tcp; if (listener->state != LISTEN) { MICROPY_PY_LWIP_EXIT m_del_obj(lwip_socket_obj_t, socket2); mp_raise_OSError(MP_EINVAL); } // accept incoming connection struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iget]; if (*incoming_connection == NULL) { if (socket->timeout == 0) { MICROPY_PY_LWIP_EXIT m_del_obj(lwip_socket_obj_t, socket2); mp_raise_OSError(MP_EAGAIN); } else if (socket->timeout != -1) { mp_uint_t retries = socket->timeout / 100; while (*incoming_connection == NULL) { MICROPY_PY_LWIP_EXIT if (retries-- == 0) { m_del_obj(lwip_socket_obj_t, socket2); mp_raise_OSError(MP_ETIMEDOUT); } mp_hal_delay_ms(100); MICROPY_PY_LWIP_REENTER } } else { while (*incoming_connection == NULL) { MICROPY_PY_LWIP_EXIT poll_sockets(); MICROPY_PY_LWIP_REENTER } } } // We get a new pcb handle... socket2->pcb.tcp = *incoming_connection; if (++socket->incoming.connection.iget >= socket->incoming.connection.alloc) { socket->incoming.connection.iget = 0; } *incoming_connection = NULL; // ...and set up the new socket for it. socket2->domain = MOD_NETWORK_AF_INET; socket2->type = MOD_NETWORK_SOCK_STREAM; socket2->incoming.pbuf = NULL; socket2->timeout = socket->timeout; socket2->state = STATE_CONNECTED; socket2->recv_offset = 0; socket2->callback = MP_OBJ_NULL; tcp_arg(socket2->pcb.tcp, (void*)socket2); tcp_err(socket2->pcb.tcp, _lwip_tcp_error); tcp_recv(socket2->pcb.tcp, _lwip_tcp_recv); tcp_accepted(listener); MICROPY_PY_LWIP_EXIT // make the return value uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE]; memcpy(ip, &(socket2->pcb.tcp->remote_ip), sizeof(ip)); mp_uint_t port = (mp_uint_t)socket2->pcb.tcp->remote_port; mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); client->items[0] = MP_OBJ_FROM_PTR(socket2); client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return MP_OBJ_FROM_PTR(client); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(lwip_socket_accept_obj, lwip_socket_accept); STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); if (socket->pcb.tcp == NULL) { mp_raise_OSError(MP_EBADF); } // get address uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); ip_addr_t dest; IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]); err_t err = ERR_ARG; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { if (socket->state != STATE_NEW) { if (socket->state == STATE_CONNECTED) { mp_raise_OSError(MP_EISCONN); } else { mp_raise_OSError(MP_EALREADY); } } // Register our receive callback. MICROPY_PY_LWIP_ENTER tcp_recv(socket->pcb.tcp, _lwip_tcp_recv); socket->state = STATE_CONNECTING; err = tcp_connect(socket->pcb.tcp, &dest, port, _lwip_tcp_connected); if (err != ERR_OK) { MICROPY_PY_LWIP_EXIT socket->state = STATE_NEW; mp_raise_OSError(error_lookup_table[-err]); } socket->peer_port = (mp_uint_t)port; memcpy(socket->peer, &dest, sizeof(socket->peer)); MICROPY_PY_LWIP_EXIT // And now we wait... if (socket->timeout != -1) { for (mp_uint_t retries = socket->timeout / 100; retries--;) { mp_hal_delay_ms(100); if (socket->state != STATE_CONNECTING) break; } if (socket->state == STATE_CONNECTING) { mp_raise_OSError(MP_EINPROGRESS); } } else { while (socket->state == STATE_CONNECTING) { poll_sockets(); } } if (socket->state == STATE_CONNECTED) { err = ERR_OK; } else { err = socket->state; } break; } case MOD_NETWORK_SOCK_DGRAM: { err = udp_connect(socket->pcb.udp, &dest, port); break; } #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: { err = raw_connect(socket->pcb.raw, &dest); break; } #endif } if (err != ERR_OK) { mp_raise_OSError(error_lookup_table[-err]); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_connect_obj, lwip_socket_connect); STATIC void lwip_socket_check_connected(lwip_socket_obj_t *socket) { if (socket->pcb.tcp == NULL) { // not connected int _errno = error_lookup_table[-socket->state]; socket->state = _ERR_BADF; mp_raise_OSError(_errno); } } STATIC mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); int _errno; lwip_socket_check_connected(socket); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno); break; } case MOD_NETWORK_SOCK_DGRAM: #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: #endif ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, NULL, 0, &_errno); break; } if (ret == -1) { mp_raise_OSError(_errno); } return mp_obj_new_int_from_uint(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_send_obj, lwip_socket_send); STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); int _errno; lwip_socket_check_connected(socket); mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno); break; } case MOD_NETWORK_SOCK_DGRAM: #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: #endif ret = lwip_raw_udp_receive(socket, (byte*)vstr.buf, len, NULL, NULL, &_errno); break; } if (ret == -1) { mp_raise_OSError(_errno); } if (ret == 0) { return mp_const_empty_bytes; } vstr.len = ret; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recv_obj, lwip_socket_recv); STATIC mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); int _errno; lwip_socket_check_connected(socket); mp_buffer_info_t bufinfo; mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno); break; } case MOD_NETWORK_SOCK_DGRAM: #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: #endif ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, ip, port, &_errno); break; } if (ret == -1) { mp_raise_OSError(_errno); } return mp_obj_new_int_from_uint(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(lwip_socket_sendto_obj, lwip_socket_sendto); STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); int _errno; lwip_socket_check_connected(socket); mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); byte ip[4]; mp_uint_t port; mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { memcpy(ip, &socket->peer, sizeof(socket->peer)); port = (mp_uint_t) socket->peer_port; ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno); break; } case MOD_NETWORK_SOCK_DGRAM: #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: #endif ret = lwip_raw_udp_receive(socket, (byte*)vstr.buf, len, ip, &port, &_errno); break; } if (ret == -1) { mp_raise_OSError(_errno); } mp_obj_t tuple[2]; if (ret == 0) { tuple[0] = mp_const_empty_bytes; } else { vstr.len = ret; tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recvfrom_obj, lwip_socket_recvfrom); STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); lwip_socket_check_connected(socket); int _errno; mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { if (socket->timeout == 0) { // Behavior of sendall() for non-blocking sockets isn't explicitly specified. // But it's specified that "On error, an exception is raised, there is no // way to determine how much data, if any, was successfully sent." Then, the // most useful behavior is: check whether we will be able to send all of input // data without EAGAIN, and if won't be, raise it without sending any. if (bufinfo.len > tcp_sndbuf(socket->pcb.tcp)) { mp_raise_OSError(MP_EAGAIN); } } // TODO: In CPython3.5, socket timeout should apply to the // entire sendall() operation, not to individual send() chunks. while (bufinfo.len != 0) { ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno); if (ret == -1) { mp_raise_OSError(_errno); } bufinfo.len -= ret; bufinfo.buf = (char*)bufinfo.buf + ret; } break; } case MOD_NETWORK_SOCK_DGRAM: mp_raise_NotImplementedError(NULL); break; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_sendall_obj, lwip_socket_sendall); STATIC mp_obj_t lwip_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); mp_uint_t timeout; if (timeout_in == mp_const_none) { timeout = -1; } else { #if MICROPY_PY_BUILTINS_FLOAT timeout = 1000 * mp_obj_get_float(timeout_in); #else timeout = 1000 * mp_obj_get_int(timeout_in); #endif } socket->timeout = timeout; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_settimeout_obj, lwip_socket_settimeout); STATIC mp_obj_t lwip_socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); bool val = mp_obj_is_true(flag_in); if (val) { socket->timeout = -1; } else { socket->timeout = 0; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_setblocking_obj, lwip_socket_setblocking); STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) { (void)n_args; // always 4 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(args[0]); int opt = mp_obj_get_int(args[2]); if (opt == 20) { if (args[3] == mp_const_none) { socket->callback = MP_OBJ_NULL; } else { socket->callback = args[3]; } return mp_const_none; } switch (opt) { // level: SOL_SOCKET case SOF_REUSEADDR: { mp_int_t val = mp_obj_get_int(args[3]); // Options are common for UDP and TCP pcb's. if (val) { ip_set_option(socket->pcb.tcp, SOF_REUSEADDR); } else { ip_reset_option(socket->pcb.tcp, SOF_REUSEADDR); } break; } // level: IPPROTO_IP case IP_ADD_MEMBERSHIP: { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); if (bufinfo.len != sizeof(ip_addr_t) * 2) { mp_raise_ValueError(NULL); } // POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa err_t err = igmp_joingroup((ip_addr_t*)bufinfo.buf + 1, bufinfo.buf); if (err != ERR_OK) { mp_raise_OSError(error_lookup_table[-err]); } break; } default: printf("Warning: lwip.setsockopt() not implemented\n"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_socket_setsockopt_obj, 4, 4, lwip_socket_setsockopt); STATIC mp_obj_t lwip_socket_makefile(size_t n_args, const mp_obj_t *args) { (void)n_args; return args[0]; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_socket_makefile_obj, 1, 3, lwip_socket_makefile); STATIC mp_uint_t lwip_socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: return lwip_tcp_receive(socket, buf, size, errcode); case MOD_NETWORK_SOCK_DGRAM: #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: #endif return lwip_raw_udp_receive(socket, buf, size, NULL, NULL, errcode); } // Unreachable return MP_STREAM_ERROR; } STATIC mp_uint_t lwip_socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: return lwip_tcp_send(socket, buf, size, errcode); case MOD_NETWORK_SOCK_DGRAM: #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: #endif return lwip_raw_udp_send(socket, buf, size, NULL, 0, errcode); } // Unreachable return MP_STREAM_ERROR; } STATIC err_t _lwip_tcp_close_poll(void *arg, struct tcp_pcb *pcb) { // Connection has not been cleanly closed so just abort it to free up memory tcp_poll(pcb, NULL, 0); tcp_abort(pcb); return ERR_OK; } STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; MICROPY_PY_LWIP_ENTER if (request == MP_STREAM_POLL) { uintptr_t flags = arg; ret = 0; if (flags & MP_STREAM_POLL_RD) { if (socket->state == STATE_LISTENING) { // Listening TCP socket may have one or multiple connections waiting if (lwip_socket_incoming_array(socket)[socket->incoming.connection.iget] != NULL) { ret |= MP_STREAM_POLL_RD; } } else { // Otherwise there is just one slot for incoming data if (socket->incoming.pbuf != NULL) { ret |= MP_STREAM_POLL_RD; } } } if (flags & MP_STREAM_POLL_WR) { if (socket->type == MOD_NETWORK_SOCK_DGRAM && socket->pcb.udp != NULL) { // UDP socket is writable ret |= MP_STREAM_POLL_WR; #if MICROPY_PY_LWIP_SOCK_RAW } else if (socket->type == MOD_NETWORK_SOCK_RAW && socket->pcb.raw != NULL) { // raw socket is writable ret |= MP_STREAM_POLL_WR; #endif } else if (socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) { // TCP socket is writable // Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf ret |= MP_STREAM_POLL_WR; } } if (socket->state == STATE_NEW) { // New sockets are not connected so set HUP ret |= MP_STREAM_POLL_HUP; } else if (socket->state == STATE_PEER_CLOSED) { // Peer-closed socket is both readable and writable: read will // return EOF, write - error. Without this poll will hang on a // socket which was closed by peer. ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR); } else if (socket->state == ERR_RST) { // Socket was reset by peer, a write will return an error ret |= flags & MP_STREAM_POLL_WR; ret |= MP_STREAM_POLL_HUP; } else if (socket->state == _ERR_BADF) { ret |= MP_STREAM_POLL_NVAL; } else if (socket->state < 0) { // Socket in some other error state, use catch-all ERR flag // TODO: may need to set other return flags here ret |= MP_STREAM_POLL_ERR; } } else if (request == MP_STREAM_CLOSE) { if (socket->pcb.tcp == NULL) { MICROPY_PY_LWIP_EXIT return 0; } // Deregister callback (pcb.tcp is set to NULL below so must deregister now) tcp_arg(socket->pcb.tcp, NULL); tcp_err(socket->pcb.tcp, NULL); tcp_recv(socket->pcb.tcp, NULL); // Free any incoming buffers or connections that are stored lwip_socket_free_incoming(socket); switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { if (socket->pcb.tcp->state != LISTEN) { // Schedule a callback to abort the connection if it's not cleanly closed after // the given timeout. The callback must be set before calling tcp_close since // the latter may free the pcb; if it doesn't then the callback will be active. tcp_poll(socket->pcb.tcp, _lwip_tcp_close_poll, MICROPY_PY_LWIP_TCP_CLOSE_TIMEOUT_MS / 500); } if (tcp_close(socket->pcb.tcp) != ERR_OK) { DEBUG_printf("lwip_close: had to call tcp_abort()\n"); tcp_abort(socket->pcb.tcp); } break; } case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break; #if MICROPY_PY_LWIP_SOCK_RAW case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break; #endif } socket->pcb.tcp = NULL; socket->state = _ERR_BADF; ret = 0; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; } MICROPY_PY_LWIP_EXIT return ret; } STATIC const mp_rom_map_elem_t lwip_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&lwip_socket_bind_obj) }, { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&lwip_socket_listen_obj) }, { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&lwip_socket_accept_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&lwip_socket_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&lwip_socket_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&lwip_socket_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&lwip_socket_sendto_obj) }, { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&lwip_socket_recvfrom_obj) }, { MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&lwip_socket_sendall_obj) }, { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&lwip_socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&lwip_socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&lwip_socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&lwip_socket_makefile_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, }; STATIC MP_DEFINE_CONST_DICT(lwip_socket_locals_dict, lwip_socket_locals_dict_table); STATIC const mp_stream_p_t lwip_socket_stream_p = { .read = lwip_socket_read, .write = lwip_socket_write, .ioctl = lwip_socket_ioctl, }; STATIC const mp_obj_type_t lwip_socket_type = { { &mp_type_type }, .name = MP_QSTR_socket, .print = lwip_socket_print, .make_new = lwip_socket_make_new, .protocol = &lwip_socket_stream_p, .locals_dict = (mp_obj_dict_t*)&lwip_socket_locals_dict, }; /******************************************************************************/ // Support functions for memory protection. lwIP has its own memory management // routines for its internal structures, and since they might be called in // interrupt handlers, they need some protection. sys_prot_t sys_arch_protect() { return (sys_prot_t)MICROPY_BEGIN_ATOMIC_SECTION(); } void sys_arch_unprotect(sys_prot_t state) { MICROPY_END_ATOMIC_SECTION((mp_uint_t)state); } /******************************************************************************/ // Polling callbacks for the interfaces connected to lwIP. Right now it calls // itself a "list" but isn't; we only support a single interface. typedef struct nic_poll { void (* poll)(void *arg); void *poll_arg; } nic_poll_t; STATIC nic_poll_t lwip_poll_list; void mod_lwip_register_poll(void (* poll)(void *arg), void *poll_arg) { lwip_poll_list.poll = poll; lwip_poll_list.poll_arg = poll_arg; } void mod_lwip_deregister_poll(void (* poll)(void *arg), void *poll_arg) { lwip_poll_list.poll = NULL; } /******************************************************************************/ // The lwip global functions. STATIC mp_obj_t mod_lwip_reset() { lwip_init(); lwip_poll_list.poll = NULL; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(mod_lwip_reset_obj, mod_lwip_reset); STATIC mp_obj_t mod_lwip_callback() { if (lwip_poll_list.poll != NULL) { lwip_poll_list.poll(lwip_poll_list.poll_arg); } sys_check_timeouts(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(mod_lwip_callback_obj, mod_lwip_callback); typedef struct _getaddrinfo_state_t { volatile int status; volatile ip_addr_t ipaddr; } getaddrinfo_state_t; // Callback for incoming DNS requests. #if LWIP_VERSION_MAJOR < 2 STATIC void lwip_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg) #else STATIC void lwip_getaddrinfo_cb(const char *name, const ip_addr_t *ipaddr, void *arg) #endif { getaddrinfo_state_t *state = arg; if (ipaddr != NULL) { state->status = 1; state->ipaddr = *ipaddr; } else { // error state->status = -2; } } // lwip.getaddrinfo STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) { mp_obj_t host_in = args[0], port_in = args[1]; const char *host = mp_obj_str_get_str(host_in); mp_int_t port = mp_obj_get_int(port_in); // If constraints were passed then check they are compatible with the supported params if (n_args > 2) { mp_int_t family = mp_obj_get_int(args[2]); mp_int_t type = 0; mp_int_t proto = 0; mp_int_t flags = 0; if (n_args > 3) { type = mp_obj_get_int(args[3]); if (n_args > 4) { proto = mp_obj_get_int(args[4]); if (n_args > 5) { flags = mp_obj_get_int(args[5]); } } } if (!((family == 0 || family == MOD_NETWORK_AF_INET) && (type == 0 || type == MOD_NETWORK_SOCK_STREAM) && proto == 0 && flags == 0)) { mp_warning(MP_WARN_CAT(RuntimeWarning), "unsupported getaddrinfo constraints"); } } getaddrinfo_state_t state; state.status = 0; MICROPY_PY_LWIP_ENTER err_t ret = dns_gethostbyname(host, (ip_addr_t*)&state.ipaddr, lwip_getaddrinfo_cb, &state); MICROPY_PY_LWIP_EXIT switch (ret) { case ERR_OK: // cached state.status = 1; break; case ERR_INPROGRESS: while (state.status == 0) { poll_sockets(); } break; default: state.status = ret; } if (state.status < 0) { // TODO: CPython raises gaierror, we raise with native lwIP negative error // values, to differentiate from normal errno's at least in such way. mp_raise_OSError(state.status); } mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr((uint8_t*)&state.ipaddr, port, NETUTILS_BIG); return mp_obj_new_list(1, (mp_obj_t*)&tuple); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_getaddrinfo_obj, 2, 6, lwip_getaddrinfo); // Debug functions STATIC mp_obj_t lwip_print_pcbs() { tcp_debug_print_pcbs(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(lwip_print_pcbs_obj, lwip_print_pcbs); #if MICROPY_PY_LWIP STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_lwip) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mod_lwip_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&mod_lwip_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&lwip_getaddrinfo_obj) }, { MP_ROM_QSTR(MP_QSTR_print_pcbs), MP_ROM_PTR(&lwip_print_pcbs_obj) }, // objects { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&lwip_socket_type) }, #ifdef MICROPY_PY_LWIP_SLIP { MP_ROM_QSTR(MP_QSTR_slip), MP_ROM_PTR(&lwip_slip_type) }, #endif // class constants { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(MOD_NETWORK_AF_INET) }, { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) }, { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) }, { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) }, #if MICROPY_PY_LWIP_SOCK_RAW { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) }, #endif { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(1) }, { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SOF_REUSEADDR) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(0) }, { MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_lwip_globals, mp_module_lwip_globals_table); const mp_obj_module_t mp_module_lwip = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_lwip_globals, }; #endif // MICROPY_PY_LWIP micropython-1.12/extmod/modonewire.c000066400000000000000000000132351357706137100176420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "py/mphal.h" /******************************************************************************/ // Low-level 1-Wire routines #define TIMING_RESET1 (480) #define TIMING_RESET2 (70) #define TIMING_RESET3 (410) #define TIMING_READ1 (5) #define TIMING_READ2 (5) #define TIMING_READ3 (40) #define TIMING_WRITE1 (10) #define TIMING_WRITE2 (50) #define TIMING_WRITE3 (10) STATIC int onewire_bus_reset(mp_hal_pin_obj_t pin) { mp_hal_pin_write(pin, 0); mp_hal_delay_us(TIMING_RESET1); uint32_t i = mp_hal_quiet_timing_enter(); mp_hal_pin_write(pin, 1); mp_hal_delay_us_fast(TIMING_RESET2); int status = !mp_hal_pin_read(pin); mp_hal_quiet_timing_exit(i); mp_hal_delay_us(TIMING_RESET3); return status; } STATIC int onewire_bus_readbit(mp_hal_pin_obj_t pin) { mp_hal_pin_write(pin, 1); uint32_t i = mp_hal_quiet_timing_enter(); mp_hal_pin_write(pin, 0); mp_hal_delay_us_fast(TIMING_READ1); mp_hal_pin_write(pin, 1); mp_hal_delay_us_fast(TIMING_READ2); int value = mp_hal_pin_read(pin); mp_hal_quiet_timing_exit(i); mp_hal_delay_us_fast(TIMING_READ3); return value; } STATIC void onewire_bus_writebit(mp_hal_pin_obj_t pin, int value) { uint32_t i = mp_hal_quiet_timing_enter(); mp_hal_pin_write(pin, 0); mp_hal_delay_us_fast(TIMING_WRITE1); if (value) { mp_hal_pin_write(pin, 1); } mp_hal_delay_us_fast(TIMING_WRITE2); mp_hal_pin_write(pin, 1); mp_hal_delay_us_fast(TIMING_WRITE3); mp_hal_quiet_timing_exit(i); } /******************************************************************************/ // MicroPython bindings STATIC mp_obj_t onewire_reset(mp_obj_t pin_in) { return mp_obj_new_bool(onewire_bus_reset(mp_hal_get_pin_obj(pin_in))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_reset_obj, onewire_reset); STATIC mp_obj_t onewire_readbit(mp_obj_t pin_in) { return MP_OBJ_NEW_SMALL_INT(onewire_bus_readbit(mp_hal_get_pin_obj(pin_in))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbit_obj, onewire_readbit); STATIC mp_obj_t onewire_readbyte(mp_obj_t pin_in) { mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in); uint8_t value = 0; for (int i = 0; i < 8; ++i) { value |= onewire_bus_readbit(pin) << i; } return MP_OBJ_NEW_SMALL_INT(value); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbyte_obj, onewire_readbyte); STATIC mp_obj_t onewire_writebit(mp_obj_t pin_in, mp_obj_t value_in) { onewire_bus_writebit(mp_hal_get_pin_obj(pin_in), mp_obj_get_int(value_in)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebit_obj, onewire_writebit); STATIC mp_obj_t onewire_writebyte(mp_obj_t pin_in, mp_obj_t value_in) { mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in); int value = mp_obj_get_int(value_in); for (int i = 0; i < 8; ++i) { onewire_bus_writebit(pin, value & 1); value >>= 1; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebyte_obj, onewire_writebyte); STATIC mp_obj_t onewire_crc8(mp_obj_t data) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); uint8_t crc = 0; for (size_t i = 0; i < bufinfo.len; ++i) { uint8_t byte = ((uint8_t*)bufinfo.buf)[i]; for (int b = 0; b < 8; ++b) { uint8_t fb_bit = (crc ^ byte) & 0x01; if (fb_bit == 0x01) { crc = crc ^ 0x18; } crc = (crc >> 1) & 0x7f; if (fb_bit == 0x01) { crc = crc | 0x80; } byte = byte >> 1; } } return MP_OBJ_NEW_SMALL_INT(crc); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_crc8_obj, onewire_crc8); STATIC const mp_rom_map_elem_t onewire_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_onewire) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&onewire_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_readbit), MP_ROM_PTR(&onewire_readbit_obj) }, { MP_ROM_QSTR(MP_QSTR_readbyte), MP_ROM_PTR(&onewire_readbyte_obj) }, { MP_ROM_QSTR(MP_QSTR_writebit), MP_ROM_PTR(&onewire_writebit_obj) }, { MP_ROM_QSTR(MP_QSTR_writebyte), MP_ROM_PTR(&onewire_writebyte_obj) }, { MP_ROM_QSTR(MP_QSTR_crc8), MP_ROM_PTR(&onewire_crc8_obj) }, }; STATIC MP_DEFINE_CONST_DICT(onewire_module_globals, onewire_module_globals_table); const mp_obj_module_t mp_module_onewire = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&onewire_module_globals, }; micropython-1.12/extmod/modubinascii.c000066400000000000000000000202361357706137100201370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/binary.h" #include "extmod/modubinascii.h" mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) { // Second argument is for an extension to allow a separator to be used // between values. const char *sep = NULL; mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); // Code below assumes non-zero buffer length when computing size with // separator, so handle the zero-length case here. if (bufinfo.len == 0) { return mp_const_empty_bytes; } vstr_t vstr; size_t out_len = bufinfo.len * 2; if (n_args > 1) { // 1-char separator between hex numbers out_len += bufinfo.len - 1; sep = mp_obj_str_get_str(args[1]); } vstr_init_len(&vstr, out_len); byte *in = bufinfo.buf, *out = (byte*)vstr.buf; for (mp_uint_t i = bufinfo.len; i--;) { byte d = (*in >> 4); if (d > 9) { d += 'a' - '9' - 1; } *out++ = d + '0'; d = (*in++ & 0xf); if (d > 9) { d += 'a' - '9' - 1; } *out++ = d + '0'; if (sep != NULL && i != 0) { *out++ = *sep; } } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify); mp_obj_t mod_binascii_unhexlify(mp_obj_t data) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); if ((bufinfo.len & 1) != 0) { mp_raise_ValueError("odd-length string"); } vstr_t vstr; vstr_init_len(&vstr, bufinfo.len / 2); byte *in = bufinfo.buf, *out = (byte*)vstr.buf; byte hex_byte = 0; for (mp_uint_t i = bufinfo.len; i--;) { byte hex_ch = *in++; if (unichar_isxdigit(hex_ch)) { hex_byte += unichar_xdigit_value(hex_ch); } else { mp_raise_ValueError("non-hex digit found"); } if (i & 1) { hex_byte <<= 4; } else { *out++ = hex_byte; hex_byte = 0; } } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify); // If ch is a character in the base64 alphabet, and is not a pad character, then // the corresponding integer between 0 and 63, inclusively, is returned. // Otherwise, -1 is returned. static int mod_binascii_sextet(byte ch) { if (ch >= 'A' && ch <= 'Z') { return ch - 'A'; } else if (ch >= 'a' && ch <= 'z') { return ch - 'a' + 26; } else if (ch >= '0' && ch <= '9') { return ch - '0' + 52; } else if (ch == '+') { return 62; } else if (ch == '/') { return 63; } else { return -1; } } mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); byte *in = bufinfo.buf; vstr_t vstr; vstr_init(&vstr, (bufinfo.len / 4) * 3 + 1); // Potentially over-allocate byte *out = (byte *)vstr.buf; uint shift = 0; int nbits = 0; // Number of meaningful bits in shift bool hadpad = false; // Had a pad character since last valid character for (size_t i = 0; i < bufinfo.len; i++) { if (in[i] == '=') { if ((nbits == 2) || ((nbits == 4) && hadpad)) { nbits = 0; break; } hadpad = true; } int sextet = mod_binascii_sextet(in[i]); if (sextet == -1) { continue; } hadpad = false; shift = (shift << 6) | sextet; nbits += 6; if (nbits >= 8) { nbits -= 8; out[vstr.len++] = (shift >> nbits) & 0xFF; } } if (nbits) { mp_raise_ValueError("incorrect padding"); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64); mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); vstr_t vstr; vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + 1); // First pass, we convert input buffer to numeric base 64 values byte *in = bufinfo.buf, *out = (byte*)vstr.buf; mp_uint_t i; for (i = bufinfo.len; i >= 3; i -= 3) { *out++ = (in[0] & 0xFC) >> 2; *out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4; *out++ = (in[1] & 0x0F) << 2 | (in[2] & 0xC0) >> 6; *out++ = in[2] & 0x3F; in += 3; } if (i != 0) { *out++ = (in[0] & 0xFC) >> 2; if (i == 2) { *out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4; *out++ = (in[1] & 0x0F) << 2; } else { *out++ = (in[0] & 0x03) << 4; *out++ = 64; } *out = 64; } // Second pass, we convert number base 64 values to actual base64 ascii encoding out = (byte*)vstr.buf; for (mp_uint_t j = vstr.len - 1; j--;) { if (*out < 26) { *out += 'A'; } else if (*out < 52) { *out += 'a' - 26; } else if (*out < 62) { *out += '0' - 52; } else if (*out == 62) { *out ='+'; } else if (*out == 63) { *out = '/'; } else { *out = '='; } out++; } *out = '\n'; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64); #if MICROPY_PY_UBINASCII_CRC32 #include "uzlib/tinf.h" mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); uint32_t crc = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 0; crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff); return mp_obj_new_int_from_uint(crc ^ 0xffffffff); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32); #endif #if MICROPY_PY_UBINASCII STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubinascii) }, { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&mod_binascii_hexlify_obj) }, { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) }, { MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) }, { MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) }, #if MICROPY_PY_UBINASCII_CRC32 { MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table); const mp_obj_module_t mp_module_ubinascii = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_binascii_globals, }; #endif //MICROPY_PY_UBINASCII micropython-1.12/extmod/modubinascii.h000066400000000000000000000036751357706137100201540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H #define MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H extern mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args); extern mp_obj_t mod_binascii_unhexlify(mp_obj_t data); extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data); extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data); extern mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj); MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj); MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj); MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj); #endif // MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H micropython-1.12/extmod/moducryptolib.c000066400000000000000000000301611357706137100203630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017-2018 Paul Sokolovsky * Copyright (c) 2018 Yonatan Goldschmidt * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_UCRYPTOLIB #include #include #include "py/runtime.h" // This module implements crypto ciphers API, roughly following // https://www.python.org/dev/peps/pep-0272/ . Exact implementation // of PEP 272 can be made with a simple wrapper which adds all the // needed boilerplate. // values follow PEP 272 enum { UCRYPTOLIB_MODE_ECB = 1, UCRYPTOLIB_MODE_CBC = 2, UCRYPTOLIB_MODE_CTR = 6, }; struct ctr_params { // counter is the IV of the AES context. size_t offset; // in encrypted_counter // encrypted counter uint8_t encrypted_counter[16]; }; #if MICROPY_SSL_AXTLS #include "lib/axtls/crypto/crypto.h" #define AES_CTX_IMPL AES_CTX #endif #if MICROPY_SSL_MBEDTLS #include // we can't run mbedtls AES key schedule until we know whether we're used for encrypt or decrypt. // therefore, we store the key & keysize and on the first call to encrypt/decrypt we override them // with the mbedtls_aes_context, as they are not longer required. (this is done to save space) struct mbedtls_aes_ctx_with_key { union { mbedtls_aes_context mbedtls_ctx; struct { uint8_t key[32]; uint8_t keysize; } init_data; } u; unsigned char iv[16]; }; #define AES_CTX_IMPL struct mbedtls_aes_ctx_with_key #endif typedef struct _mp_obj_aes_t { mp_obj_base_t base; AES_CTX_IMPL ctx; uint8_t block_mode: 6; #define AES_KEYTYPE_NONE 0 #define AES_KEYTYPE_ENC 1 #define AES_KEYTYPE_DEC 2 uint8_t key_type: 2; } mp_obj_aes_t; static inline bool is_ctr_mode(int block_mode) { #if MICROPY_PY_UCRYPTOLIB_CTR return block_mode == UCRYPTOLIB_MODE_CTR; #else return false; #endif } static inline struct ctr_params *ctr_params_from_aes(mp_obj_aes_t *o) { // ctr_params follows aes object struct return (struct ctr_params*)&o[1]; } #if MICROPY_SSL_AXTLS STATIC void aes_initial_set_key_impl(AES_CTX_IMPL *ctx, const uint8_t *key, size_t keysize, const uint8_t iv[16]) { assert(16 == keysize || 32 == keysize); AES_set_key(ctx, key, iv, (16 == keysize) ? AES_MODE_128 : AES_MODE_256); } STATIC void aes_final_set_key_impl(AES_CTX_IMPL *ctx, bool encrypt) { if (!encrypt) { AES_convert_key(ctx); } } STATIC void aes_process_ecb_impl(AES_CTX_IMPL *ctx, const uint8_t in[16], uint8_t out[16], bool encrypt) { memcpy(out, in, 16); // We assume that out (vstr.buf or given output buffer) is uint32_t aligned uint32_t *p = (uint32_t*)out; // axTLS likes it weird and complicated with byteswaps for (int i = 0; i < 4; i++) { p[i] = MP_HTOBE32(p[i]); } if (encrypt) { AES_encrypt(ctx, p); } else { AES_decrypt(ctx, p); } for (int i = 0; i < 4; i++) { p[i] = MP_BE32TOH(p[i]); } } STATIC void aes_process_cbc_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, bool encrypt) { if (encrypt) { AES_cbc_encrypt(ctx, in, out, in_len); } else { AES_cbc_decrypt(ctx, in, out, in_len); } } #if MICROPY_PY_UCRYPTOLIB_CTR // axTLS doesn't have CTR support out of the box. This implements the counter part using the ECB primitive. STATIC void aes_process_ctr_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, struct ctr_params *ctr_params) { size_t n = ctr_params->offset; uint8_t *const counter = ctx->iv; while (in_len--) { if (n == 0) { aes_process_ecb_impl(ctx, counter, ctr_params->encrypted_counter, true); // increment the 128-bit counter for (int i = 15; i >= 0; --i) { if (++counter[i] != 0) { break; } } } *out++ = *in++ ^ ctr_params->encrypted_counter[n]; n = (n + 1) & 0xf; } ctr_params->offset = n; } #endif #endif #if MICROPY_SSL_MBEDTLS STATIC void aes_initial_set_key_impl(AES_CTX_IMPL *ctx, const uint8_t *key, size_t keysize, const uint8_t iv[16]) { ctx->u.init_data.keysize = keysize; memcpy(ctx->u.init_data.key, key, keysize); if (NULL != iv) { memcpy(ctx->iv, iv, sizeof(ctx->iv)); } } STATIC void aes_final_set_key_impl(AES_CTX_IMPL *ctx, bool encrypt) { // first, copy key aside uint8_t key[32]; uint8_t keysize = ctx->u.init_data.keysize; memcpy(key, ctx->u.init_data.key, keysize); // now, override key with the mbedtls context object mbedtls_aes_init(&ctx->u.mbedtls_ctx); // setkey call will succeed, we've already checked the keysize earlier. assert(16 == keysize || 32 == keysize); if (encrypt) { mbedtls_aes_setkey_enc(&ctx->u.mbedtls_ctx, key, keysize * 8); } else { mbedtls_aes_setkey_dec(&ctx->u.mbedtls_ctx, key, keysize * 8); } } STATIC void aes_process_ecb_impl(AES_CTX_IMPL *ctx, const uint8_t in[16], uint8_t out[16], bool encrypt) { mbedtls_aes_crypt_ecb(&ctx->u.mbedtls_ctx, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, in, out); } STATIC void aes_process_cbc_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, bool encrypt) { mbedtls_aes_crypt_cbc(&ctx->u.mbedtls_ctx, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, in_len, ctx->iv, in, out); } #if MICROPY_PY_UCRYPTOLIB_CTR STATIC void aes_process_ctr_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, struct ctr_params *ctr_params) { mbedtls_aes_crypt_ctr(&ctx->u.mbedtls_ctx, in_len, &ctr_params->offset, ctx->iv, ctr_params->encrypted_counter, in, out); } #endif #endif STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 3, false); const mp_int_t block_mode = mp_obj_get_int(args[1]); switch (block_mode) { case UCRYPTOLIB_MODE_ECB: case UCRYPTOLIB_MODE_CBC: #if MICROPY_PY_UCRYPTOLIB_CTR case UCRYPTOLIB_MODE_CTR: #endif break; default: mp_raise_ValueError("mode"); } mp_obj_aes_t *o = m_new_obj_var(mp_obj_aes_t, struct ctr_params, !!is_ctr_mode(block_mode)); o->base.type = type; o->block_mode = block_mode; o->key_type = AES_KEYTYPE_NONE; mp_buffer_info_t keyinfo; mp_get_buffer_raise(args[0], &keyinfo, MP_BUFFER_READ); if (32 != keyinfo.len && 16 != keyinfo.len) { mp_raise_ValueError("key"); } mp_buffer_info_t ivinfo; ivinfo.buf = NULL; if (n_args > 2 && args[2] != mp_const_none) { mp_get_buffer_raise(args[2], &ivinfo, MP_BUFFER_READ); if (16 != ivinfo.len) { mp_raise_ValueError("IV"); } } else if (o->block_mode == UCRYPTOLIB_MODE_CBC || is_ctr_mode(o->block_mode)) { mp_raise_ValueError("IV"); } if (is_ctr_mode(block_mode)) { ctr_params_from_aes(o)->offset = 0; } aes_initial_set_key_impl(&o->ctx, keyinfo.buf, keyinfo.len, ivinfo.buf); return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) { mp_obj_aes_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_t in_buf = args[1]; mp_obj_t out_buf = MP_OBJ_NULL; if (n_args > 2) { out_buf = args[2]; } mp_buffer_info_t in_bufinfo; mp_get_buffer_raise(in_buf, &in_bufinfo, MP_BUFFER_READ); if (!is_ctr_mode(self->block_mode) && in_bufinfo.len % 16 != 0) { mp_raise_ValueError("blksize % 16"); } vstr_t vstr; mp_buffer_info_t out_bufinfo; uint8_t *out_buf_ptr; if (out_buf != MP_OBJ_NULL) { mp_get_buffer_raise(out_buf, &out_bufinfo, MP_BUFFER_WRITE); if (out_bufinfo.len < in_bufinfo.len) { mp_raise_ValueError("output too small"); } out_buf_ptr = out_bufinfo.buf; } else { vstr_init_len(&vstr, in_bufinfo.len); out_buf_ptr = (uint8_t*)vstr.buf; } if (AES_KEYTYPE_NONE == self->key_type) { // always set key for encryption if CTR mode. const bool encrypt_mode = encrypt || is_ctr_mode(self->block_mode); aes_final_set_key_impl(&self->ctx, encrypt_mode); self->key_type = encrypt ? AES_KEYTYPE_ENC : AES_KEYTYPE_DEC; } else { if ((encrypt && self->key_type == AES_KEYTYPE_DEC) || (!encrypt && self->key_type == AES_KEYTYPE_ENC)) { mp_raise_ValueError("can't encrypt & decrypt"); } } switch (self->block_mode) { case UCRYPTOLIB_MODE_ECB: { uint8_t *in = in_bufinfo.buf, *out = out_buf_ptr; uint8_t *top = in + in_bufinfo.len; for (; in < top; in += 16, out += 16) { aes_process_ecb_impl(&self->ctx, in, out, encrypt); } break; } case UCRYPTOLIB_MODE_CBC: aes_process_cbc_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len, encrypt); break; #if MICROPY_PY_UCRYPTOLIB_CTR case UCRYPTOLIB_MODE_CTR: aes_process_ctr_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len, ctr_params_from_aes(self)); break; #endif } if (out_buf != MP_OBJ_NULL) { return out_buf; } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC mp_obj_t ucryptolib_aes_encrypt(size_t n_args, const mp_obj_t *args) { return aes_process(n_args, args, true); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ucryptolib_aes_encrypt_obj, 2, 3, ucryptolib_aes_encrypt); STATIC mp_obj_t ucryptolib_aes_decrypt(size_t n_args, const mp_obj_t *args) { return aes_process(n_args, args, false); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ucryptolib_aes_decrypt_obj, 2, 3, ucryptolib_aes_decrypt); STATIC const mp_rom_map_elem_t ucryptolib_aes_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_encrypt), MP_ROM_PTR(&ucryptolib_aes_encrypt_obj) }, { MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&ucryptolib_aes_decrypt_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ucryptolib_aes_locals_dict, ucryptolib_aes_locals_dict_table); STATIC const mp_obj_type_t ucryptolib_aes_type = { { &mp_type_type }, .name = MP_QSTR_aes, .make_new = ucryptolib_aes_make_new, .locals_dict = (void*)&ucryptolib_aes_locals_dict, }; STATIC const mp_rom_map_elem_t mp_module_ucryptolib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ucryptolib) }, { MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&ucryptolib_aes_type) }, #if MICROPY_PY_UCRYPTOLIB_CONSTS { MP_ROM_QSTR(MP_QSTR_MODE_ECB), MP_ROM_INT(UCRYPTOLIB_MODE_ECB) }, { MP_ROM_QSTR(MP_QSTR_MODE_CBC), MP_ROM_INT(UCRYPTOLIB_MODE_CBC) }, #if MICROPY_PY_UCRYPTOLIB_CTR { MP_ROM_QSTR(MP_QSTR_MODE_CTR), MP_ROM_INT(UCRYPTOLIB_MODE_CTR) }, #endif #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_ucryptolib_globals, mp_module_ucryptolib_globals_table); const mp_obj_module_t mp_module_ucryptolib = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_ucryptolib_globals, }; #endif //MICROPY_PY_UCRYPTOLIB micropython-1.12/extmod/moductypes.c000066400000000000000000000725041357706137100176720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/objtuple.h" #include "py/binary.h" #if MICROPY_PY_UCTYPES /// \module uctypes - Access data structures in memory /// /// The module allows to define layout of raw data structure (using terms /// of C language), and then access memory buffers using this definition. /// The module also provides convenience functions to access memory buffers /// contained in Python objects or wrap memory buffers in Python objects. /// \constant UINT8_1 - uint8_t value type /// \class struct - C-like structure /// /// Encapsulalation of in-memory data structure. This class doesn't define /// any methods, only attribute access (for structure fields) and /// indexing (for pointer and array fields). /// /// Usage: /// /// # Define layout of a structure with 2 fields /// # 0 and 4 are byte offsets of fields from the beginning of struct /// # they are logically ORed with field type /// FOO_STRUCT = {"a": 0 | uctypes.UINT32, "b": 4 | uctypes.UINT8} /// /// # Example memory buffer to access (contained in bytes object) /// buf = b"\x64\0\0\0\0x14" /// /// # Create structure object referring to address of /// # the data in the buffer above /// s = uctypes.struct(FOO_STRUCT, uctypes.addressof(buf)) /// /// # Access fields /// print(s.a, s.b) /// # Result: /// # 100, 20 #define LAYOUT_LITTLE_ENDIAN (0) #define LAYOUT_BIG_ENDIAN (1) #define LAYOUT_NATIVE (2) #define VAL_TYPE_BITS 4 #define BITF_LEN_BITS 5 #define BITF_OFF_BITS 5 #define OFFSET_BITS 17 #if VAL_TYPE_BITS + BITF_LEN_BITS + BITF_OFF_BITS + OFFSET_BITS != 31 #error Invalid encoding field length #endif enum { UINT8, INT8, UINT16, INT16, UINT32, INT32, UINT64, INT64, BFUINT8, BFINT8, BFUINT16, BFINT16, BFUINT32, BFINT32, FLOAT32, FLOAT64, }; #define AGG_TYPE_BITS 2 enum { STRUCT, PTR, ARRAY, }; // Here we need to set sign bit right #define TYPE2SMALLINT(x, nbits) ((((int)x) << (32 - nbits)) >> 1) #define GET_TYPE(x, nbits) (((x) >> (31 - nbits)) & ((1 << nbits) - 1)) // Bit 0 is "is_signed" #define GET_SCALAR_SIZE(val_type) (1 << ((val_type) >> 1)) #define VALUE_MASK(type_nbits) ~((int)0x80000000 >> type_nbits) #define IS_SCALAR_ARRAY(tuple_desc) ((tuple_desc)->len == 2) // We cannot apply the below to INT8, as their range [-128, 127] #define IS_SCALAR_ARRAY_OF_BYTES(tuple_desc) (GET_TYPE(MP_OBJ_SMALL_INT_VALUE((tuple_desc)->items[1]), VAL_TYPE_BITS) == UINT8) // "struct" in uctypes context means "structural", i.e. aggregate, type. STATIC const mp_obj_type_t uctypes_struct_type; typedef struct _mp_obj_uctypes_struct_t { mp_obj_base_t base; mp_obj_t desc; byte *addr; uint32_t flags; } mp_obj_uctypes_struct_t; STATIC NORETURN void syntax_error(void) { mp_raise_TypeError("syntax error in uctypes descriptor"); } STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 3, false); mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); o->base.type = type; o->addr = (void*)(uintptr_t)mp_obj_int_get_truncated(args[0]); o->desc = args[1]; o->flags = LAYOUT_NATIVE; if (n_args == 3) { o->flags = mp_obj_get_int(args[2]); } return MP_OBJ_FROM_PTR(o); } STATIC void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); const char *typen = "unk"; if (mp_obj_is_type(self->desc, &mp_type_dict) #if MICROPY_PY_COLLECTIONS_ORDEREDDICT || mp_obj_is_type(self->desc, &mp_type_ordereddict) #endif ) { typen = "STRUCT"; } else if (mp_obj_is_type(self->desc, &mp_type_tuple)) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc); mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS); switch (agg_type) { case PTR: typen = "PTR"; break; case ARRAY: typen = "ARRAY"; break; } } else { typen = "ERROR"; } mp_printf(print, "", typen, self->addr); } // Get size of any type descriptor STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size); // Get size of scalar type descriptor static inline mp_uint_t uctypes_struct_scalar_size(int val_type) { if (val_type == FLOAT32) { return 4; } else { return GET_SCALAR_SIZE(val_type & 7); } } // Get size of aggregate type descriptor STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_uint_t *max_field_size) { mp_uint_t total_size = 0; mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]); mp_uint_t agg_type = GET_TYPE(offset_, AGG_TYPE_BITS); switch (agg_type) { case STRUCT: return uctypes_struct_size(t->items[1], layout_type, max_field_size); case PTR: if (sizeof(void*) > *max_field_size) { *max_field_size = sizeof(void*); } return sizeof(void*); case ARRAY: { mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]); uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS); arr_sz &= VALUE_MASK(VAL_TYPE_BITS); mp_uint_t item_s; if (t->len == 2) { // Elements of array are scalar item_s = GET_SCALAR_SIZE(val_type); if (item_s > *max_field_size) { *max_field_size = item_s; } } else { // Elements of array are aggregates item_s = uctypes_struct_size(t->items[2], layout_type, max_field_size); } return item_s * arr_sz; } default: assert(0); } return total_size; } STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size) { if (!mp_obj_is_type(desc_in, &mp_type_dict) #if MICROPY_PY_COLLECTIONS_ORDEREDDICT && !mp_obj_is_type(desc_in, &mp_type_ordereddict) #endif ) { if (mp_obj_is_type(desc_in, &mp_type_tuple)) { return uctypes_struct_agg_size((mp_obj_tuple_t*)MP_OBJ_TO_PTR(desc_in), layout_type, max_field_size); } else if (mp_obj_is_small_int(desc_in)) { // We allow sizeof on both type definitions and structures/structure fields, // but scalar structure field is lowered into native Python int, so all // type info is lost. So, we cannot say if it's scalar type description, // or such lowered scalar. mp_raise_TypeError("Cannot unambiguously get sizeof scalar"); } syntax_error(); } mp_obj_dict_t *d = MP_OBJ_TO_PTR(desc_in); mp_uint_t total_size = 0; for (mp_uint_t i = 0; i < d->map.alloc; i++) { if (mp_map_slot_is_filled(&d->map, i)) { mp_obj_t v = d->map.table[i].value; if (mp_obj_is_small_int(v)) { mp_uint_t offset = MP_OBJ_SMALL_INT_VALUE(v); mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS); offset &= VALUE_MASK(VAL_TYPE_BITS); if (val_type >= BFUINT8 && val_type <= BFINT32) { offset &= (1 << OFFSET_BITS) - 1; } mp_uint_t s = uctypes_struct_scalar_size(val_type); if (s > *max_field_size) { *max_field_size = s; } if (offset + s > total_size) { total_size = offset + s; } } else { if (!mp_obj_is_type(v, &mp_type_tuple)) { syntax_error(); } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(v); mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); offset &= VALUE_MASK(AGG_TYPE_BITS); mp_uint_t s = uctypes_struct_agg_size(t, layout_type, max_field_size); if (offset + s > total_size) { total_size = offset + s; } } } } // Round size up to alignment of biggest field if (layout_type == LAYOUT_NATIVE) { total_size = (total_size + *max_field_size - 1) & ~(*max_field_size - 1); } return total_size; } STATIC mp_obj_t uctypes_struct_sizeof(size_t n_args, const mp_obj_t *args) { mp_obj_t obj_in = args[0]; mp_uint_t max_field_size = 0; if (mp_obj_is_type(obj_in, &mp_type_bytearray)) { return mp_obj_len(obj_in); } int layout_type = LAYOUT_NATIVE; // We can apply sizeof either to structure definition (a dict) // or to instantiated structure if (mp_obj_is_type(obj_in, &uctypes_struct_type)) { if (n_args != 1) { mp_raise_TypeError(NULL); } // Extract structure definition mp_obj_uctypes_struct_t *obj = MP_OBJ_TO_PTR(obj_in); obj_in = obj->desc; layout_type = obj->flags; } else { if (n_args == 2) { layout_type = mp_obj_get_int(args[1]); } } mp_uint_t size = uctypes_struct_size(obj_in, layout_type, &max_field_size); return MP_OBJ_NEW_SMALL_INT(size); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uctypes_struct_sizeof_obj, 1, 2, uctypes_struct_sizeof); static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) { char struct_type = big_endian ? '>' : '<'; static const char type2char[16] = "BbHhIiQq------fd"; return mp_binary_get_val(struct_type, type2char[val_type], p, &p); } static inline void set_unaligned(uint val_type, byte *p, int big_endian, mp_obj_t val) { char struct_type = big_endian ? '>' : '<'; static const char type2char[16] = "BbHhIiQq------fd"; mp_binary_set_val(struct_type, type2char[val_type], val, p, &p); } static inline mp_uint_t get_aligned_basic(uint val_type, void *p) { switch (val_type) { case UINT8: return *(uint8_t*)p; case UINT16: return *(uint16_t*)p; case UINT32: return *(uint32_t*)p; } assert(0); return 0; } static inline void set_aligned_basic(uint val_type, void *p, mp_uint_t v) { switch (val_type) { case UINT8: *(uint8_t*)p = (uint8_t)v; return; case UINT16: *(uint16_t*)p = (uint16_t)v; return; case UINT32: *(uint32_t*)p = (uint32_t)v; return; } assert(0); } STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) { switch (val_type) { case UINT8: return MP_OBJ_NEW_SMALL_INT(((uint8_t*)p)[index]); case INT8: return MP_OBJ_NEW_SMALL_INT(((int8_t*)p)[index]); case UINT16: return MP_OBJ_NEW_SMALL_INT(((uint16_t*)p)[index]); case INT16: return MP_OBJ_NEW_SMALL_INT(((int16_t*)p)[index]); case UINT32: return mp_obj_new_int_from_uint(((uint32_t*)p)[index]); case INT32: return mp_obj_new_int(((int32_t*)p)[index]); case UINT64: return mp_obj_new_int_from_ull(((uint64_t*)p)[index]); case INT64: return mp_obj_new_int_from_ll(((int64_t*)p)[index]); #if MICROPY_PY_BUILTINS_FLOAT case FLOAT32: return mp_obj_new_float(((float*)p)[index]); case FLOAT64: return mp_obj_new_float(((double*)p)[index]); #endif default: assert(0); return MP_OBJ_NULL; } } STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) { #if MICROPY_PY_BUILTINS_FLOAT if (val_type == FLOAT32 || val_type == FLOAT64) { mp_float_t v = mp_obj_get_float(val); if (val_type == FLOAT32) { ((float*)p)[index] = v; } else { ((double*)p)[index] = v; } return; } #endif mp_int_t v = mp_obj_get_int_truncated(val); switch (val_type) { case UINT8: ((uint8_t*)p)[index] = (uint8_t)v; return; case INT8: ((int8_t*)p)[index] = (int8_t)v; return; case UINT16: ((uint16_t*)p)[index] = (uint16_t)v; return; case INT16: ((int16_t*)p)[index] = (int16_t)v; return; case UINT32: ((uint32_t*)p)[index] = (uint32_t)v; return; case INT32: ((int32_t*)p)[index] = (int32_t)v; return; case INT64: case UINT64: if (sizeof(mp_int_t) == 8) { ((uint64_t*)p)[index] = (uint64_t)v; } else { // TODO: Doesn't offer atomic store semantics, but should at least try set_unaligned(val_type, p, MP_ENDIANNESS_BIG, val); } return; default: assert(0); } } STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set_val) { mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); if (!mp_obj_is_type(self->desc, &mp_type_dict) #if MICROPY_PY_COLLECTIONS_ORDEREDDICT && !mp_obj_is_type(self->desc, &mp_type_ordereddict) #endif ) { mp_raise_TypeError("struct: no fields"); } mp_obj_t deref = mp_obj_dict_get(self->desc, MP_OBJ_NEW_QSTR(attr)); if (mp_obj_is_small_int(deref)) { mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(deref); mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS); offset &= VALUE_MASK(VAL_TYPE_BITS); //printf("scalar type=%d offset=%x\n", val_type, offset); if (val_type <= INT64 || val_type == FLOAT32 || val_type == FLOAT64) { // printf("size=%d\n", GET_SCALAR_SIZE(val_type)); if (self->flags == LAYOUT_NATIVE) { if (set_val == MP_OBJ_NULL) { return get_aligned(val_type, self->addr + offset, 0); } else { set_aligned(val_type, self->addr + offset, 0, set_val); return set_val; // just !MP_OBJ_NULL } } else { if (set_val == MP_OBJ_NULL) { return get_unaligned(val_type, self->addr + offset, self->flags); } else { set_unaligned(val_type, self->addr + offset, self->flags, set_val); return set_val; // just !MP_OBJ_NULL } } } else if (val_type >= BFUINT8 && val_type <= BFINT32) { uint bit_offset = (offset >> 17) & 31; uint bit_len = (offset >> 22) & 31; offset &= (1 << 17) - 1; mp_uint_t val; if (self->flags == LAYOUT_NATIVE) { val = get_aligned_basic(val_type & 6, self->addr + offset); } else { val = mp_binary_get_int(GET_SCALAR_SIZE(val_type & 7), val_type & 1, self->flags, self->addr + offset); } if (set_val == MP_OBJ_NULL) { val >>= bit_offset; val &= (1 << bit_len) - 1; // TODO: signed assert((val_type & 1) == 0); return mp_obj_new_int(val); } else { mp_uint_t set_val_int = (mp_uint_t)mp_obj_get_int(set_val); mp_uint_t mask = (1 << bit_len) - 1; set_val_int &= mask; set_val_int <<= bit_offset; mask <<= bit_offset; val = (val & ~mask) | set_val_int; if (self->flags == LAYOUT_NATIVE) { set_aligned_basic(val_type & 6, self->addr + offset, val); } else { mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN, self->addr + offset, val); } return set_val; // just !MP_OBJ_NULL } } assert(0); return MP_OBJ_NULL; } if (!mp_obj_is_type(deref, &mp_type_tuple)) { syntax_error(); } if (set_val != MP_OBJ_NULL) { // Cannot assign to aggregate syntax_error(); } mp_obj_tuple_t *sub = MP_OBJ_TO_PTR(deref); mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(sub->items[0]); mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS); offset &= VALUE_MASK(AGG_TYPE_BITS); //printf("agg type=%d offset=%x\n", agg_type, offset); switch (agg_type) { case STRUCT: { mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); o->base.type = &uctypes_struct_type; o->desc = sub->items[1]; o->addr = self->addr + offset; o->flags = self->flags; return MP_OBJ_FROM_PTR(o); } case ARRAY: { mp_uint_t dummy; if (IS_SCALAR_ARRAY(sub) && IS_SCALAR_ARRAY_OF_BYTES(sub)) { return mp_obj_new_bytearray_by_ref(uctypes_struct_agg_size(sub, self->flags, &dummy), self->addr + offset); } // Fall thru to return uctypes struct object } case PTR: { mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); o->base.type = &uctypes_struct_type; o->desc = MP_OBJ_FROM_PTR(sub); o->addr = self->addr + offset; o->flags = self->flags; //printf("PTR/ARR base addr=%p\n", o->addr); return MP_OBJ_FROM_PTR(o); } } // Should be unreachable once all cases are handled return MP_OBJ_NULL; } STATIC void uctypes_struct_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_t val = uctypes_struct_attr_op(self_in, attr, MP_OBJ_NULL); dest[0] = val; } else { // delete/store attribute if (uctypes_struct_attr_op(self_in, attr, dest[1]) != MP_OBJ_NULL) { dest[0] = MP_OBJ_NULL; // indicate success } } } STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); if (value == MP_OBJ_NULL) { // delete return MP_OBJ_NULL; // op not supported } else { // load / store if (!mp_obj_is_type(self->desc, &mp_type_tuple)) { mp_raise_TypeError("struct: cannot index"); } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc); mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS); mp_int_t index = MP_OBJ_SMALL_INT_VALUE(index_in); if (agg_type == ARRAY) { mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]); uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS); arr_sz &= VALUE_MASK(VAL_TYPE_BITS); if (index >= arr_sz) { mp_raise_msg(&mp_type_IndexError, "struct: index out of range"); } if (t->len == 2) { // array of scalars if (self->flags == LAYOUT_NATIVE) { if (value == MP_OBJ_SENTINEL) { return get_aligned(val_type, self->addr, index); } else { set_aligned(val_type, self->addr, index, value); return value; // just !MP_OBJ_NULL } } else { byte *p = self->addr + GET_SCALAR_SIZE(val_type) * index; if (value == MP_OBJ_SENTINEL) { return get_unaligned(val_type, p, self->flags); } else { set_unaligned(val_type, p, self->flags, value); return value; // just !MP_OBJ_NULL } } } else if (value == MP_OBJ_SENTINEL) { mp_uint_t dummy = 0; mp_uint_t size = uctypes_struct_size(t->items[2], self->flags, &dummy); mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); o->base.type = &uctypes_struct_type; o->desc = t->items[2]; o->addr = self->addr + size * index; o->flags = self->flags; return MP_OBJ_FROM_PTR(o); } else { return MP_OBJ_NULL; // op not supported } } else if (agg_type == PTR) { byte *p = *(void**)self->addr; if (mp_obj_is_small_int(t->items[1])) { uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS); return get_aligned(val_type, p, index); } else { mp_uint_t dummy = 0; mp_uint_t size = uctypes_struct_size(t->items[1], self->flags, &dummy); mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); o->base.type = &uctypes_struct_type; o->desc = t->items[1]; o->addr = p + size * index; o->flags = self->flags; return MP_OBJ_FROM_PTR(o); } } assert(0); return MP_OBJ_NULL; } } STATIC mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_INT: if (mp_obj_is_type(self->desc, &mp_type_tuple)) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc); mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS); if (agg_type == PTR) { byte *p = *(void**)self->addr; return mp_obj_new_int((mp_int_t)(uintptr_t)p); } } /* fallthru */ default: return MP_OBJ_NULL; // op not supported } } STATIC mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { (void)flags; mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t max_field_size = 0; mp_uint_t size = uctypes_struct_size(self->desc, self->flags, &max_field_size); bufinfo->buf = self->addr; bufinfo->len = size; bufinfo->typecode = BYTEARRAY_TYPECODE; return 0; } /// \function addressof() /// Return address of object's data (applies to object providing buffer /// interface). STATIC mp_obj_t uctypes_struct_addressof(mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); return mp_obj_new_int((mp_int_t)(uintptr_t)bufinfo.buf); } MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof); /// \function bytearray_at() /// Capture memory at given address of given size as bytearray. Memory is /// captured by reference (and thus memory pointed by bytearray may change /// or become invalid at later time). Use bytes_at() to capture by value. STATIC mp_obj_t uctypes_struct_bytearray_at(mp_obj_t ptr, mp_obj_t size) { return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void*)(uintptr_t)mp_obj_int_get_truncated(ptr)); } MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytearray_at); /// \function bytes_at() /// Capture memory at given address of given size as bytes. Memory is /// captured by value, i.e. copied. Use bytearray_at() to capture by reference /// ("zero copy"). STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) { return mp_obj_new_bytes((void*)(uintptr_t)mp_obj_int_get_truncated(ptr), mp_obj_int_get_truncated(size)); } MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at); STATIC const mp_obj_type_t uctypes_struct_type = { { &mp_type_type }, .name = MP_QSTR_struct, .print = uctypes_struct_print, .make_new = uctypes_struct_make_new, .attr = uctypes_struct_attr, .subscr = uctypes_struct_subscr, .unary_op = uctypes_struct_unary_op, .buffer_p = { .get_buffer = uctypes_get_buffer }, }; STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uctypes) }, { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&uctypes_struct_type) }, { MP_ROM_QSTR(MP_QSTR_sizeof), MP_ROM_PTR(&uctypes_struct_sizeof_obj) }, { MP_ROM_QSTR(MP_QSTR_addressof), MP_ROM_PTR(&uctypes_struct_addressof_obj) }, { MP_ROM_QSTR(MP_QSTR_bytes_at), MP_ROM_PTR(&uctypes_struct_bytes_at_obj) }, { MP_ROM_QSTR(MP_QSTR_bytearray_at), MP_ROM_PTR(&uctypes_struct_bytearray_at_obj) }, /// \moduleref uctypes /// \constant NATIVE - Native structure layout - native endianness, /// platform-specific field alignment { MP_ROM_QSTR(MP_QSTR_NATIVE), MP_ROM_INT(LAYOUT_NATIVE) }, /// \constant LITTLE_ENDIAN - Little-endian structure layout, tightly packed /// (no alignment constraints) { MP_ROM_QSTR(MP_QSTR_LITTLE_ENDIAN), MP_ROM_INT(LAYOUT_LITTLE_ENDIAN) }, /// \constant BIG_ENDIAN - Big-endian structure layout, tightly packed /// (no alignment constraints) { MP_ROM_QSTR(MP_QSTR_BIG_ENDIAN), MP_ROM_INT(LAYOUT_BIG_ENDIAN) }, /// \constant VOID - void value type, may be used only as pointer target type. { MP_ROM_QSTR(MP_QSTR_VOID), MP_ROM_INT(TYPE2SMALLINT(UINT8, VAL_TYPE_BITS)) }, /// \constant UINT8 - uint8_t value type { MP_ROM_QSTR(MP_QSTR_UINT8), MP_ROM_INT(TYPE2SMALLINT(UINT8, 4)) }, /// \constant INT8 - int8_t value type { MP_ROM_QSTR(MP_QSTR_INT8), MP_ROM_INT(TYPE2SMALLINT(INT8, 4)) }, /// \constant UINT16 - uint16_t value type { MP_ROM_QSTR(MP_QSTR_UINT16), MP_ROM_INT(TYPE2SMALLINT(UINT16, 4)) }, /// \constant INT16 - int16_t value type { MP_ROM_QSTR(MP_QSTR_INT16), MP_ROM_INT(TYPE2SMALLINT(INT16, 4)) }, /// \constant UINT32 - uint32_t value type { MP_ROM_QSTR(MP_QSTR_UINT32), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) }, /// \constant INT32 - int32_t value type { MP_ROM_QSTR(MP_QSTR_INT32), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) }, /// \constant UINT64 - uint64_t value type { MP_ROM_QSTR(MP_QSTR_UINT64), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) }, /// \constant INT64 - int64_t value type { MP_ROM_QSTR(MP_QSTR_INT64), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) }, { MP_ROM_QSTR(MP_QSTR_BFUINT8), MP_ROM_INT(TYPE2SMALLINT(BFUINT8, 4)) }, { MP_ROM_QSTR(MP_QSTR_BFINT8), MP_ROM_INT(TYPE2SMALLINT(BFINT8, 4)) }, { MP_ROM_QSTR(MP_QSTR_BFUINT16), MP_ROM_INT(TYPE2SMALLINT(BFUINT16, 4)) }, { MP_ROM_QSTR(MP_QSTR_BFINT16), MP_ROM_INT(TYPE2SMALLINT(BFINT16, 4)) }, { MP_ROM_QSTR(MP_QSTR_BFUINT32), MP_ROM_INT(TYPE2SMALLINT(BFUINT32, 4)) }, { MP_ROM_QSTR(MP_QSTR_BFINT32), MP_ROM_INT(TYPE2SMALLINT(BFINT32, 4)) }, { MP_ROM_QSTR(MP_QSTR_BF_POS), MP_ROM_INT(17) }, { MP_ROM_QSTR(MP_QSTR_BF_LEN), MP_ROM_INT(22) }, #if MICROPY_PY_BUILTINS_FLOAT { MP_ROM_QSTR(MP_QSTR_FLOAT32), MP_ROM_INT(TYPE2SMALLINT(FLOAT32, 4)) }, { MP_ROM_QSTR(MP_QSTR_FLOAT64), MP_ROM_INT(TYPE2SMALLINT(FLOAT64, 4)) }, #endif #if MICROPY_PY_UCTYPES_NATIVE_C_TYPES // C native type aliases. These depend on GCC-compatible predefined // preprocessor macros. #if __SIZEOF_SHORT__ == 2 { MP_ROM_QSTR(MP_QSTR_SHORT), MP_ROM_INT(TYPE2SMALLINT(INT16, 4)) }, { MP_ROM_QSTR(MP_QSTR_USHORT), MP_ROM_INT(TYPE2SMALLINT(UINT16, 4)) }, #endif #if __SIZEOF_INT__ == 4 { MP_ROM_QSTR(MP_QSTR_INT), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) }, { MP_ROM_QSTR(MP_QSTR_UINT), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) }, #endif #if __SIZEOF_LONG__ == 4 { MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) }, { MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) }, #elif __SIZEOF_LONG__ == 8 { MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) }, { MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) }, #endif #if __SIZEOF_LONG_LONG__ == 8 { MP_ROM_QSTR(MP_QSTR_LONGLONG), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) }, { MP_ROM_QSTR(MP_QSTR_ULONGLONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) }, #endif #endif // MICROPY_PY_UCTYPES_NATIVE_C_TYPES { MP_ROM_QSTR(MP_QSTR_PTR), MP_ROM_INT(TYPE2SMALLINT(PTR, AGG_TYPE_BITS)) }, { MP_ROM_QSTR(MP_QSTR_ARRAY), MP_ROM_INT(TYPE2SMALLINT(ARRAY, AGG_TYPE_BITS)) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_uctypes_globals, mp_module_uctypes_globals_table); const mp_obj_module_t mp_module_uctypes = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_uctypes_globals, }; #endif micropython-1.12/extmod/moduhashlib.c000066400000000000000000000303131357706137100177650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_UHASHLIB #if MICROPY_SSL_MBEDTLS #include "mbedtls/version.h" #endif #if MICROPY_PY_UHASHLIB_SHA256 #if MICROPY_SSL_MBEDTLS #include "mbedtls/sha256.h" #else #include "crypto-algorithms/sha256.h" #endif #endif #if MICROPY_PY_UHASHLIB_SHA1 || MICROPY_PY_UHASHLIB_MD5 #if MICROPY_SSL_AXTLS #include "lib/axtls/crypto/crypto.h" #endif #if MICROPY_SSL_MBEDTLS #include "mbedtls/md5.h" #include "mbedtls/sha1.h" #endif #endif typedef struct _mp_obj_hash_t { mp_obj_base_t base; char state[0]; } mp_obj_hash_t; #if MICROPY_PY_UHASHLIB_SHA256 STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg); #if MICROPY_SSL_MBEDTLS #if MBEDTLS_VERSION_NUMBER < 0x02070000 #define mbedtls_sha256_starts_ret mbedtls_sha256_starts #define mbedtls_sha256_update_ret mbedtls_sha256_update #define mbedtls_sha256_finish_ret mbedtls_sha256_finish #endif STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context)); o->base.type = type; mbedtls_sha256_init((mbedtls_sha256_context*)&o->state); mbedtls_sha256_starts_ret((mbedtls_sha256_context*)&o->state, 0); if (n_args == 1) { uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); mbedtls_sha256_update_ret((mbedtls_sha256_context*)&self->state, bufinfo.buf, bufinfo.len); return mp_const_none; } STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; vstr_init_len(&vstr, 32); mbedtls_sha256_finish_ret((mbedtls_sha256_context*)&self->state, (unsigned char *)vstr.buf); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } #else #include "crypto-algorithms/sha256.c" STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX)); o->base.type = type; sha256_init((CRYAL_SHA256_CTX*)o->state); if (n_args == 1) { uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); sha256_update((CRYAL_SHA256_CTX*)self->state, bufinfo.buf, bufinfo.len); return mp_const_none; } STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; vstr_init_len(&vstr, SHA256_BLOCK_SIZE); sha256_final((CRYAL_SHA256_CTX*)self->state, (byte*)vstr.buf); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } #endif STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_sha256_update_obj, uhashlib_sha256_update); STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_sha256_digest_obj, uhashlib_sha256_digest); STATIC const mp_rom_map_elem_t uhashlib_sha256_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_sha256_update_obj) }, { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_sha256_digest_obj) }, }; STATIC MP_DEFINE_CONST_DICT(uhashlib_sha256_locals_dict, uhashlib_sha256_locals_dict_table); STATIC const mp_obj_type_t uhashlib_sha256_type = { { &mp_type_type }, .name = MP_QSTR_sha256, .make_new = uhashlib_sha256_make_new, .locals_dict = (void*)&uhashlib_sha256_locals_dict, }; #endif #if MICROPY_PY_UHASHLIB_SHA1 STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg); #if MICROPY_SSL_AXTLS STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(SHA1_CTX)); o->base.type = type; SHA1_Init((SHA1_CTX*)o->state); if (n_args == 1) { uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); SHA1_Update((SHA1_CTX*)self->state, bufinfo.buf, bufinfo.len); return mp_const_none; } STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; vstr_init_len(&vstr, SHA1_SIZE); SHA1_Final((byte*)vstr.buf, (SHA1_CTX*)self->state); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } #endif #if MICROPY_SSL_MBEDTLS #if MBEDTLS_VERSION_NUMBER < 0x02070000 #define mbedtls_sha1_starts_ret mbedtls_sha1_starts #define mbedtls_sha1_update_ret mbedtls_sha1_update #define mbedtls_sha1_finish_ret mbedtls_sha1_finish #endif STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context)); o->base.type = type; mbedtls_sha1_init((mbedtls_sha1_context*)o->state); mbedtls_sha1_starts_ret((mbedtls_sha1_context*)o->state); if (n_args == 1) { uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); mbedtls_sha1_update_ret((mbedtls_sha1_context*)self->state, bufinfo.buf, bufinfo.len); return mp_const_none; } STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; vstr_init_len(&vstr, 20); mbedtls_sha1_finish_ret((mbedtls_sha1_context*)self->state, (byte*)vstr.buf); mbedtls_sha1_free((mbedtls_sha1_context*)self->state); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } #endif STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_sha1_update_obj, uhashlib_sha1_update); STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_sha1_digest_obj, uhashlib_sha1_digest); STATIC const mp_rom_map_elem_t uhashlib_sha1_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_sha1_update_obj) }, { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_sha1_digest_obj) }, }; STATIC MP_DEFINE_CONST_DICT(uhashlib_sha1_locals_dict, uhashlib_sha1_locals_dict_table); STATIC const mp_obj_type_t uhashlib_sha1_type = { { &mp_type_type }, .name = MP_QSTR_sha1, .make_new = uhashlib_sha1_make_new, .locals_dict = (void*)&uhashlib_sha1_locals_dict, }; #endif #if MICROPY_PY_UHASHLIB_MD5 STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg); #if MICROPY_SSL_AXTLS STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(MD5_CTX)); o->base.type = type; MD5_Init((MD5_CTX*)o->state); if (n_args == 1) { uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); MD5_Update((MD5_CTX*)self->state, bufinfo.buf, bufinfo.len); return mp_const_none; } STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; vstr_init_len(&vstr, MD5_SIZE); MD5_Final((byte*)vstr.buf, (MD5_CTX*)self->state); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } #endif // MICROPY_SSL_AXTLS #if MICROPY_SSL_MBEDTLS #if MBEDTLS_VERSION_NUMBER < 0x02070000 #define mbedtls_md5_starts_ret mbedtls_md5_starts #define mbedtls_md5_update_ret mbedtls_md5_update #define mbedtls_md5_finish_ret mbedtls_md5_finish #endif STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context)); o->base.type = type; mbedtls_md5_init((mbedtls_md5_context*)o->state); mbedtls_md5_starts_ret((mbedtls_md5_context*)o->state); if (n_args == 1) { uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); mbedtls_md5_update_ret((mbedtls_md5_context*)self->state, bufinfo.buf, bufinfo.len); return mp_const_none; } STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; vstr_init_len(&vstr, 16); mbedtls_md5_finish_ret((mbedtls_md5_context*)self->state, (byte*)vstr.buf); mbedtls_md5_free((mbedtls_md5_context*)self->state); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } #endif // MICROPY_SSL_MBEDTLS STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_md5_update_obj, uhashlib_md5_update); STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_md5_digest_obj, uhashlib_md5_digest); STATIC const mp_rom_map_elem_t uhashlib_md5_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_md5_update_obj) }, { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_md5_digest_obj) }, }; STATIC MP_DEFINE_CONST_DICT(uhashlib_md5_locals_dict, uhashlib_md5_locals_dict_table); STATIC const mp_obj_type_t uhashlib_md5_type = { { &mp_type_type }, .name = MP_QSTR_md5, .make_new = uhashlib_md5_make_new, .locals_dict = (void*)&uhashlib_md5_locals_dict, }; #endif // MICROPY_PY_UHASHLIB_MD5 STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uhashlib) }, #if MICROPY_PY_UHASHLIB_SHA256 { MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&uhashlib_sha256_type) }, #endif #if MICROPY_PY_UHASHLIB_SHA1 { MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&uhashlib_sha1_type) }, #endif #if MICROPY_PY_UHASHLIB_MD5 { MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&uhashlib_md5_type) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_uhashlib_globals, mp_module_uhashlib_globals_table); const mp_obj_module_t mp_module_uhashlib = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_uhashlib_globals, }; #endif //MICROPY_PY_UHASHLIB micropython-1.12/extmod/moduheapq.c000066400000000000000000000107271357706137100174600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/objlist.h" #include "py/runtime.h" #if MICROPY_PY_UHEAPQ // the algorithm here is modelled on CPython's heapq.py STATIC mp_obj_list_t *uheapq_get_heap(mp_obj_t heap_in) { if (!mp_obj_is_type(heap_in, &mp_type_list)) { mp_raise_TypeError("heap must be a list"); } return MP_OBJ_TO_PTR(heap_in); } STATIC void uheapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) { mp_obj_t item = heap->items[pos]; while (pos > start_pos) { mp_uint_t parent_pos = (pos - 1) >> 1; mp_obj_t parent = heap->items[parent_pos]; if (mp_binary_op(MP_BINARY_OP_LESS, item, parent) == mp_const_true) { heap->items[pos] = parent; pos = parent_pos; } else { break; } } heap->items[pos] = item; } STATIC void uheapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) { mp_uint_t start_pos = pos; mp_uint_t end_pos = heap->len; mp_obj_t item = heap->items[pos]; for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) { // choose right child if it's <= left child if (child_pos + 1 < end_pos && mp_binary_op(MP_BINARY_OP_LESS, heap->items[child_pos], heap->items[child_pos + 1]) == mp_const_false) { child_pos += 1; } // bubble up the smaller child heap->items[pos] = heap->items[child_pos]; pos = child_pos; } heap->items[pos] = item; uheapq_heap_siftdown(heap, start_pos, pos); } STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) { mp_obj_list_t *heap = uheapq_get_heap(heap_in); mp_obj_list_append(heap_in, item); uheapq_heap_siftdown(heap, 0, heap->len - 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush); STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) { mp_obj_list_t *heap = uheapq_get_heap(heap_in); if (heap->len == 0) { mp_raise_msg(&mp_type_IndexError, "empty heap"); } mp_obj_t item = heap->items[0]; heap->len -= 1; heap->items[0] = heap->items[heap->len]; heap->items[heap->len] = MP_OBJ_NULL; // so we don't retain a pointer if (heap->len) { uheapq_heap_siftup(heap, 0); } return item; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heappop_obj, mod_uheapq_heappop); STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) { mp_obj_list_t *heap = uheapq_get_heap(heap_in); for (mp_uint_t i = heap->len / 2; i > 0;) { uheapq_heap_siftup(heap, --i); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heapify_obj, mod_uheapq_heapify); #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t mp_module_uheapq_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uheapq) }, { MP_ROM_QSTR(MP_QSTR_heappush), MP_ROM_PTR(&mod_uheapq_heappush_obj) }, { MP_ROM_QSTR(MP_QSTR_heappop), MP_ROM_PTR(&mod_uheapq_heappop_obj) }, { MP_ROM_QSTR(MP_QSTR_heapify), MP_ROM_PTR(&mod_uheapq_heapify_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_uheapq_globals, mp_module_uheapq_globals_table); const mp_obj_module_t mp_module_uheapq = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_uheapq_globals, }; #endif #endif //MICROPY_PY_UHEAPQ micropython-1.12/extmod/modujson.c000066400000000000000000000254331357706137100173330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/objlist.h" #include "py/objstringio.h" #include "py/parsenum.h" #include "py/runtime.h" #include "py/stream.h" #if MICROPY_PY_UJSON STATIC mp_obj_t mod_ujson_dump(mp_obj_t obj, mp_obj_t stream) { mp_get_stream_raise(stream, MP_STREAM_OP_WRITE); mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor}; mp_obj_print_helper(&print, obj, PRINT_JSON); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ujson_dump_obj, mod_ujson_dump); STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 8, &print); mp_obj_print_helper(&print, obj, PRINT_JSON); return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); // The function below implements a simple non-recursive JSON parser. // // The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt // The parser here will parse any valid JSON and return the correct // corresponding Python object. It allows through a superset of JSON, since // it treats commas and colons as "whitespace", and doesn't care if // brackets/braces are correctly paired. It will raise a ValueError if the // input is outside it's specs. // // Most of the work is parsing the primitives (null, false, true, numbers, // strings). It does 1 pass over the input stream. It tries to be fast and // small in code size, while not using more RAM than necessary. typedef struct _ujson_stream_t { mp_obj_t stream_obj; mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); int errcode; byte cur; } ujson_stream_t; #define S_EOF (0) // null is not allowed in json stream so is ok as EOF marker #define S_END(s) ((s).cur == S_EOF) #define S_CUR(s) ((s).cur) #define S_NEXT(s) (ujson_stream_next(&(s))) STATIC byte ujson_stream_next(ujson_stream_t *s) { mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode); if (s->errcode != 0) { mp_raise_OSError(s->errcode); } if (ret == 0) { s->cur = S_EOF; } return s->cur; } STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ); ujson_stream_t s = {stream_obj, stream_p->read, 0, 0}; vstr_t vstr; vstr_init(&vstr, 8); mp_obj_list_t stack; // we use a list as a simple stack for nested JSON stack.len = 0; stack.items = NULL; mp_obj_t stack_top = MP_OBJ_NULL; mp_obj_type_t *stack_top_type = NULL; mp_obj_t stack_key = MP_OBJ_NULL; S_NEXT(s); for (;;) { cont: if (S_END(s)) { break; } mp_obj_t next = MP_OBJ_NULL; bool enter = false; byte cur = S_CUR(s); S_NEXT(s); switch (cur) { case ',': case ':': case ' ': case '\t': case '\n': case '\r': goto cont; case 'n': if (S_CUR(s) == 'u' && S_NEXT(s) == 'l' && S_NEXT(s) == 'l') { S_NEXT(s); next = mp_const_none; } else { goto fail; } break; case 'f': if (S_CUR(s) == 'a' && S_NEXT(s) == 'l' && S_NEXT(s) == 's' && S_NEXT(s) == 'e') { S_NEXT(s); next = mp_const_false; } else { goto fail; } break; case 't': if (S_CUR(s) == 'r' && S_NEXT(s) == 'u' && S_NEXT(s) == 'e') { S_NEXT(s); next = mp_const_true; } else { goto fail; } break; case '"': vstr_reset(&vstr); for (; !S_END(s) && S_CUR(s) != '"';) { byte c = S_CUR(s); if (c == '\\') { c = S_NEXT(s); switch (c) { case 'b': c = 0x08; break; case 'f': c = 0x0c; break; case 'n': c = 0x0a; break; case 'r': c = 0x0d; break; case 't': c = 0x09; break; case 'u': { mp_uint_t num = 0; for (int i = 0; i < 4; i++) { c = (S_NEXT(s) | 0x20) - '0'; if (c > 9) { c -= ('a' - ('9' + 1)); } num = (num << 4) | c; } vstr_add_char(&vstr, num); goto str_cont; } } } vstr_add_byte(&vstr, c); str_cont: S_NEXT(s); } if (S_END(s)) { goto fail; } S_NEXT(s); next = mp_obj_new_str(vstr.buf, vstr.len); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { bool flt = false; vstr_reset(&vstr); for (;;) { vstr_add_byte(&vstr, cur); cur = S_CUR(s); if (cur == '.' || cur == 'E' || cur == 'e') { flt = true; } else if (cur == '+' || cur == '-' || unichar_isdigit(cur)) { // pass } else { break; } S_NEXT(s); } if (flt) { next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL); } else { next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } break; } case '[': next = mp_obj_new_list(0, NULL); enter = true; break; case '{': next = mp_obj_new_dict(0); enter = true; break; case '}': case ']': { if (stack_top == MP_OBJ_NULL) { // no object at all goto fail; } if (stack.len == 0) { // finished; compound object goto success; } stack.len -= 1; stack_top = stack.items[stack.len]; stack_top_type = mp_obj_get_type(stack_top); goto cont; } default: goto fail; } if (stack_top == MP_OBJ_NULL) { stack_top = next; stack_top_type = mp_obj_get_type(stack_top); if (!enter) { // finished; single primitive only goto success; } } else { // append to list or dict if (stack_top_type == &mp_type_list) { mp_obj_list_append(stack_top, next); } else { if (stack_key == MP_OBJ_NULL) { stack_key = next; if (enter) { goto fail; } } else { mp_obj_dict_store(stack_top, stack_key, next); stack_key = MP_OBJ_NULL; } } if (enter) { if (stack.items == NULL) { mp_obj_list_init(&stack, 1); stack.items[0] = stack_top; } else { mp_obj_list_append(MP_OBJ_FROM_PTR(&stack), stack_top); } stack_top = next; stack_top_type = mp_obj_get_type(stack_top); } } } success: // eat trailing whitespace while (unichar_isspace(S_CUR(s))) { S_NEXT(s); } if (!S_END(s)) { // unexpected chars goto fail; } if (stack_top == MP_OBJ_NULL || stack.len != 0) { // not exactly 1 object goto fail; } vstr_clear(&vstr); return stack_top; fail: mp_raise_ValueError("syntax error in JSON"); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load); STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ); vstr_t vstr = {bufinfo.len, bufinfo.len, (char*)bufinfo.buf, true}; mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL}; return mod_ujson_load(MP_OBJ_FROM_PTR(&sio)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads); STATIC const mp_rom_map_elem_t mp_module_ujson_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ujson) }, { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_ujson_dump_obj) }, { MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_ujson_dumps_obj) }, { MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_ujson_load_obj) }, { MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_ujson_loads_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_ujson_globals, mp_module_ujson_globals_table); const mp_obj_module_t mp_module_ujson = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_ujson_globals, }; #endif //MICROPY_PY_UJSON micropython-1.12/extmod/modurandom.c000066400000000000000000000176401357706137100176430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_URANDOM // Yasmarang random number generator // by Ilya Levin // http://www.literatecode.com/yasmarang // Public Domain #if !MICROPY_ENABLE_DYNRUNTIME STATIC uint32_t yasmarang_pad = 0xeda4baba, yasmarang_n = 69, yasmarang_d = 233; STATIC uint8_t yasmarang_dat = 0; #endif STATIC uint32_t yasmarang(void) { yasmarang_pad += yasmarang_dat + yasmarang_d * yasmarang_n; yasmarang_pad = (yasmarang_pad<<3) + (yasmarang_pad>>29); yasmarang_n = yasmarang_pad | 2; yasmarang_d ^= (yasmarang_pad<<31) + (yasmarang_pad>>1); yasmarang_dat ^= (char) yasmarang_pad ^ (yasmarang_d>>8) ^ 1; return (yasmarang_pad^(yasmarang_d<<5)^(yasmarang_pad>>18)^(yasmarang_dat<<1)); } /* yasmarang */ // End of Yasmarang #if MICROPY_PY_URANDOM_EXTRA_FUNCS // returns an unsigned integer below the given argument // n must not be zero STATIC uint32_t yasmarang_randbelow(uint32_t n) { uint32_t mask = 1; while ((n & mask) < n) { mask = (mask << 1) | 1; } uint32_t r; do { r = yasmarang() & mask; } while (r >= n); return r; } #endif STATIC mp_obj_t mod_urandom_getrandbits(mp_obj_t num_in) { int n = mp_obj_get_int(num_in); if (n > 32 || n == 0) { mp_raise_ValueError(NULL); } uint32_t mask = ~0; // Beware of C undefined behavior when shifting by >= than bit size mask >>= (32 - n); return mp_obj_new_int_from_uint(yasmarang() & mask); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_urandom_getrandbits_obj, mod_urandom_getrandbits); STATIC mp_obj_t mod_urandom_seed(mp_obj_t seed_in) { mp_uint_t seed = mp_obj_get_int_truncated(seed_in); yasmarang_pad = seed; yasmarang_n = 69; yasmarang_d = 233; yasmarang_dat = 0; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_urandom_seed_obj, mod_urandom_seed); #if MICROPY_PY_URANDOM_EXTRA_FUNCS STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) { mp_int_t start = mp_obj_get_int(args[0]); if (n_args == 1) { // range(stop) if (start > 0) { return mp_obj_new_int(yasmarang_randbelow(start)); } else { goto error; } } else { mp_int_t stop = mp_obj_get_int(args[1]); if (n_args == 2) { // range(start, stop) if (start < stop) { return mp_obj_new_int(start + yasmarang_randbelow(stop - start)); } else { goto error; } } else { // range(start, stop, step) mp_int_t step = mp_obj_get_int(args[2]); mp_int_t n; if (step > 0) { n = (stop - start + step - 1) / step; } else if (step < 0) { n = (stop - start + step + 1) / step; } else { goto error; } if (n > 0) { return mp_obj_new_int(start + step * yasmarang_randbelow(n)); } else { goto error; } } } error: mp_raise_ValueError(NULL); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_urandom_randrange_obj, 1, 3, mod_urandom_randrange); STATIC mp_obj_t mod_urandom_randint(mp_obj_t a_in, mp_obj_t b_in) { mp_int_t a = mp_obj_get_int(a_in); mp_int_t b = mp_obj_get_int(b_in); if (a <= b) { return mp_obj_new_int(a + yasmarang_randbelow(b - a + 1)); } else { mp_raise_ValueError(NULL); } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_randint_obj, mod_urandom_randint); STATIC mp_obj_t mod_urandom_choice(mp_obj_t seq) { mp_int_t len = mp_obj_get_int(mp_obj_len(seq)); if (len > 0) { return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL); } else { nlr_raise(mp_obj_new_exception(&mp_type_IndexError)); } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_urandom_choice_obj, mod_urandom_choice); #if MICROPY_PY_BUILTINS_FLOAT // returns a number in the range [0..1) using Yasmarang to fill in the fraction bits STATIC mp_float_t yasmarang_float(void) { #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE typedef uint64_t mp_float_int_t; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT typedef uint32_t mp_float_int_t; #endif union { mp_float_t f; #if MP_ENDIANNESS_LITTLE struct { mp_float_int_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p; #else struct { mp_float_int_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p; #endif } u; u.p.sgn = 0; u.p.exp = (1 << (MP_FLOAT_EXP_BITS - 1)) - 1; if (MP_FLOAT_FRAC_BITS <= 32) { u.p.frc = yasmarang(); } else { u.p.frc = ((uint64_t)yasmarang() << 32) | (uint64_t)yasmarang(); } return u.f - 1; } STATIC mp_obj_t mod_urandom_random(void) { return mp_obj_new_float(yasmarang_float()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_urandom_random_obj, mod_urandom_random); STATIC mp_obj_t mod_urandom_uniform(mp_obj_t a_in, mp_obj_t b_in) { mp_float_t a = mp_obj_get_float(a_in); mp_float_t b = mp_obj_get_float(b_in); return mp_obj_new_float(a + (b - a) * yasmarang_float()); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_uniform_obj, mod_urandom_uniform); #endif #endif // MICROPY_PY_URANDOM_EXTRA_FUNCS #ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC STATIC mp_obj_t mod_urandom___init__() { mod_urandom_seed(MP_OBJ_NEW_SMALL_INT(MICROPY_PY_URANDOM_SEED_INIT_FUNC)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_urandom___init___obj, mod_urandom___init__); #endif #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t mp_module_urandom_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_urandom) }, #ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&mod_urandom___init___obj) }, #endif { MP_ROM_QSTR(MP_QSTR_getrandbits), MP_ROM_PTR(&mod_urandom_getrandbits_obj) }, { MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_urandom_seed_obj) }, #if MICROPY_PY_URANDOM_EXTRA_FUNCS { MP_ROM_QSTR(MP_QSTR_randrange), MP_ROM_PTR(&mod_urandom_randrange_obj) }, { MP_ROM_QSTR(MP_QSTR_randint), MP_ROM_PTR(&mod_urandom_randint_obj) }, { MP_ROM_QSTR(MP_QSTR_choice), MP_ROM_PTR(&mod_urandom_choice_obj) }, #if MICROPY_PY_BUILTINS_FLOAT { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_urandom_random_obj) }, { MP_ROM_QSTR(MP_QSTR_uniform), MP_ROM_PTR(&mod_urandom_uniform_obj) }, #endif #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_urandom_globals, mp_module_urandom_globals_table); const mp_obj_module_t mp_module_urandom = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_urandom_globals, }; #endif #endif //MICROPY_PY_URANDOM micropython-1.12/extmod/modure.c000066400000000000000000000374711357706137100167750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/binary.h" #include "py/objstr.h" #include "py/stackctrl.h" #if MICROPY_PY_URE #define re1_5_stack_chk() MP_STACK_CHECK() #include "re1.5/re1.5.h" #define FLAG_DEBUG 0x1000 typedef struct _mp_obj_re_t { mp_obj_base_t base; ByteProg re; } mp_obj_re_t; typedef struct _mp_obj_match_t { mp_obj_base_t base; int num_matches; mp_obj_t str; const char *caps[0]; } mp_obj_match_t; STATIC void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->num_matches); } STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) { mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t no = mp_obj_get_int(no_in); if (no < 0 || no >= self->num_matches) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, no_in)); } const char *start = self->caps[no * 2]; if (start == NULL) { // no match for this group return mp_const_none; } return mp_obj_new_str_of_type(mp_obj_get_type(self->str), (const byte*)start, self->caps[no * 2 + 1] - start); } MP_DEFINE_CONST_FUN_OBJ_2(match_group_obj, match_group); #if MICROPY_PY_URE_MATCH_GROUPS STATIC mp_obj_t match_groups(mp_obj_t self_in) { mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in); if (self->num_matches <= 1) { return mp_const_empty_tuple; } mp_obj_tuple_t *groups = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->num_matches - 1, NULL)); for (int i = 1; i < self->num_matches; ++i) { groups->items[i - 1] = match_group(self_in, MP_OBJ_NEW_SMALL_INT(i)); } return MP_OBJ_FROM_PTR(groups); } MP_DEFINE_CONST_FUN_OBJ_1(match_groups_obj, match_groups); #endif #if MICROPY_PY_URE_MATCH_SPAN_START_END STATIC void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span[2]) { mp_obj_match_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t no = 0; if (n_args == 2) { no = mp_obj_get_int(args[1]); if (no < 0 || no >= self->num_matches) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, args[1])); } } mp_int_t s = -1; mp_int_t e = -1; const char *start = self->caps[no * 2]; if (start != NULL) { // have a match for this group const char *begin = mp_obj_str_get_str(self->str); s = start - begin; e = self->caps[no * 2 + 1] - begin; } span[0] = mp_obj_new_int(s); span[1] = mp_obj_new_int(e); } STATIC mp_obj_t match_span(size_t n_args, const mp_obj_t *args) { mp_obj_t span[2]; match_span_helper(n_args, args, span); return mp_obj_new_tuple(2, span); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_span_obj, 1, 2, match_span); STATIC mp_obj_t match_start(size_t n_args, const mp_obj_t *args) { mp_obj_t span[2]; match_span_helper(n_args, args, span); return span[0]; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_start_obj, 1, 2, match_start); STATIC mp_obj_t match_end(size_t n_args, const mp_obj_t *args) { mp_obj_t span[2]; match_span_helper(n_args, args, span); return span[1]; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_end_obj, 1, 2, match_end); #endif #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t match_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_group), MP_ROM_PTR(&match_group_obj) }, #if MICROPY_PY_URE_MATCH_GROUPS { MP_ROM_QSTR(MP_QSTR_groups), MP_ROM_PTR(&match_groups_obj) }, #endif #if MICROPY_PY_URE_MATCH_SPAN_START_END { MP_ROM_QSTR(MP_QSTR_span), MP_ROM_PTR(&match_span_obj) }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&match_start_obj) }, { MP_ROM_QSTR(MP_QSTR_end), MP_ROM_PTR(&match_end_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); STATIC const mp_obj_type_t match_type = { { &mp_type_type }, .name = MP_QSTR_match, .print = match_print, .locals_dict = (void*)&match_locals_dict, }; #endif STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_re_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self); } STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { (void)n_args; mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]); Subject subj; size_t len; subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; int caps_num = (self->re.sub + 1) * 2; mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, char*, caps_num); // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char memset((char*)match->caps, 0, caps_num * sizeof(char*)); int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, is_anchored); if (res == 0) { m_del_var(mp_obj_match_t, char*, caps_num, match); return mp_const_none; } match->base.type = &match_type; match->num_matches = caps_num / 2; // caps_num counts start and end pointers match->str = args[1]; return MP_OBJ_FROM_PTR(match); } STATIC mp_obj_t re_match(size_t n_args, const mp_obj_t *args) { return ure_exec(true, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match); STATIC mp_obj_t re_search(size_t n_args, const mp_obj_t *args) { return ure_exec(false, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search); STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) { mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]); Subject subj; size_t len; const mp_obj_type_t *str_type = mp_obj_get_type(args[1]); subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; int caps_num = (self->re.sub + 1) * 2; int maxsplit = 0; if (n_args > 2) { maxsplit = mp_obj_get_int(args[2]); } mp_obj_t retval = mp_obj_new_list(0, NULL); const char **caps = mp_local_alloc(caps_num * sizeof(char*)); while (true) { // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char memset((char**)caps, 0, caps_num * sizeof(char*)); int res = re1_5_recursiveloopprog(&self->re, &subj, caps, caps_num, false); // if we didn't have a match, or had an empty match, it's time to stop if (!res || caps[0] == caps[1]) { break; } mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte*)subj.begin, caps[0] - subj.begin); mp_obj_list_append(retval, s); if (self->re.sub > 0) { mp_raise_NotImplementedError("Splitting with sub-captures"); } subj.begin = caps[1]; if (maxsplit > 0 && --maxsplit == 0) { break; } } // cast is a workaround for a bug in msvc (see above) mp_local_free((char**)caps); mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte*)subj.begin, subj.end - subj.begin); mp_obj_list_append(retval, s); return retval; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split); #if MICROPY_PY_URE_SUB STATIC mp_obj_t re_sub_helper(mp_obj_t self_in, size_t n_args, const mp_obj_t *args) { mp_obj_re_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t replace = args[1]; mp_obj_t where = args[2]; mp_int_t count = 0; if (n_args > 3) { count = mp_obj_get_int(args[3]); // Note: flags are currently ignored } size_t where_len; const char *where_str = mp_obj_str_get_data(where, &where_len); Subject subj; subj.begin = where_str; subj.end = subj.begin + where_len; int caps_num = (self->re.sub + 1) * 2; vstr_t vstr_return; vstr_return.buf = NULL; // We'll init the vstr after the first match mp_obj_match_t *match = mp_local_alloc(sizeof(mp_obj_match_t) + caps_num * sizeof(char*)); match->base.type = &match_type; match->num_matches = caps_num / 2; // caps_num counts start and end pointers match->str = where; for (;;) { // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char memset((char*)match->caps, 0, caps_num * sizeof(char*)); int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, false); // If we didn't have a match, or had an empty match, it's time to stop if (!res || match->caps[0] == match->caps[1]) { break; } // Initialise the vstr if it's not already if (vstr_return.buf == NULL) { vstr_init(&vstr_return, match->caps[0] - subj.begin); } // Add pre-match string vstr_add_strn(&vstr_return, subj.begin, match->caps[0] - subj.begin); // Get replacement string const char* repl = mp_obj_str_get_str((mp_obj_is_callable(replace) ? mp_call_function_1(replace, MP_OBJ_FROM_PTR(match)) : replace)); // Append replacement string to result, substituting any regex groups while (*repl != '\0') { if (*repl == '\\') { ++repl; bool is_g_format = false; if (*repl == 'g' && repl[1] == '<') { // Group specified with syntax "\g" repl += 2; is_g_format = true; } if ('0' <= *repl && *repl <= '9') { // Group specified with syntax "\g" or "\number" unsigned int match_no = 0; do { match_no = match_no * 10 + (*repl++ - '0'); } while ('0' <= *repl && *repl <= '9'); if (is_g_format && *repl == '>') { ++repl; } if (match_no >= (unsigned int)match->num_matches) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, MP_OBJ_NEW_SMALL_INT(match_no))); } const char *start_match = match->caps[match_no * 2]; if (start_match != NULL) { // Add the substring matched by group const char *end_match = match->caps[match_no * 2 + 1]; vstr_add_strn(&vstr_return, start_match, end_match - start_match); } } } else { // Just add the current byte from the replacement string vstr_add_byte(&vstr_return, *repl++); } } // Move start pointer to end of last match subj.begin = match->caps[1]; // Stop substitutions if count was given and gets to 0 if (count > 0 && --count == 0) { break; } } mp_local_free(match); if (vstr_return.buf == NULL) { // Optimisation for case of no substitutions return where; } // Add post-match string vstr_add_strn(&vstr_return, subj.begin, subj.end - subj.begin); return mp_obj_new_str_from_vstr(mp_obj_get_type(where), &vstr_return); } STATIC mp_obj_t re_sub(size_t n_args, const mp_obj_t *args) { return re_sub_helper(args[0], n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub); #endif #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t re_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) }, { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) }, { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&re_split_obj) }, #if MICROPY_PY_URE_SUB { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&re_sub_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); STATIC const mp_obj_type_t re_type = { { &mp_type_type }, .name = MP_QSTR_ure, .print = re_print, .locals_dict = (void*)&re_locals_dict, }; #endif STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { (void)n_args; const char *re_str = mp_obj_str_get_str(args[0]); int size = re1_5_sizecode(re_str); if (size == -1) { goto error; } mp_obj_re_t *o = m_new_obj_var(mp_obj_re_t, char, size); o->base.type = &re_type; #if MICROPY_PY_URE_DEBUG int flags = 0; if (n_args > 1) { flags = mp_obj_get_int(args[1]); } #endif int error = re1_5_compilecode(&o->re, re_str); if (error != 0) { error: mp_raise_ValueError("Error in regex"); } #if MICROPY_PY_URE_DEBUG if (flags & FLAG_DEBUG) { re1_5_dumpcode(&o->re); } #endif return MP_OBJ_FROM_PTR(o); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_compile_obj, 1, 2, mod_re_compile); STATIC mp_obj_t mod_re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { (void)n_args; mp_obj_t self = mod_re_compile(1, args); const mp_obj_t args2[] = {self, args[1]}; mp_obj_t match = ure_exec(is_anchored, 2, args2); return match; } STATIC mp_obj_t mod_re_match(size_t n_args, const mp_obj_t *args) { return mod_re_exec(true, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_match_obj, 2, 4, mod_re_match); STATIC mp_obj_t mod_re_search(size_t n_args, const mp_obj_t *args) { return mod_re_exec(false, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_search_obj, 2, 4, mod_re_search); #if MICROPY_PY_URE_SUB STATIC mp_obj_t mod_re_sub(size_t n_args, const mp_obj_t *args) { mp_obj_t self = mod_re_compile(1, args); return re_sub_helper(self, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_sub_obj, 3, 5, mod_re_sub); #endif #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ure) }, { MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mod_re_compile_obj) }, { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&mod_re_match_obj) }, { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&mod_re_search_obj) }, #if MICROPY_PY_URE_SUB { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&mod_re_sub_obj) }, #endif #if MICROPY_PY_URE_DEBUG { MP_ROM_QSTR(MP_QSTR_DEBUG), MP_ROM_INT(FLAG_DEBUG) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table); const mp_obj_module_t mp_module_ure = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_re_globals, }; #endif // Source files #include'd here to make sure they're compiled in // only if module is enabled by config setting. #define re1_5_fatal(x) assert(!x) #include "re1.5/compilecode.c" #if MICROPY_PY_URE_DEBUG #include "re1.5/dumpcode.c" #endif #include "re1.5/recursiveloop.c" #include "re1.5/charclass.c" #endif //MICROPY_PY_URE micropython-1.12/extmod/moduselect.c000066400000000000000000000327361357706137100176450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2015-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_USELECT #include #include "py/runtime.h" #include "py/obj.h" #include "py/objlist.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" // Flags for poll() #define FLAG_ONESHOT (1) /// \module select - Provides select function to wait for events on a stream /// /// This module provides the select function. typedef struct _poll_obj_t { mp_obj_t obj; mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode); mp_uint_t flags; mp_uint_t flags_ret; } poll_obj_t; STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) { for (mp_uint_t i = 0; i < obj_len; i++) { mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); if (elem->value == MP_OBJ_NULL) { // object not found; get its ioctl and add it to the poll list const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL); poll_obj_t *poll_obj = m_new_obj(poll_obj_t); poll_obj->obj = obj[i]; poll_obj->ioctl = stream_p->ioctl; poll_obj->flags = flags; poll_obj->flags_ret = 0; elem->value = MP_OBJ_FROM_PTR(poll_obj); } else { // object exists; update its flags if (or_flags) { ((poll_obj_t*)MP_OBJ_TO_PTR(elem->value))->flags |= flags; } else { ((poll_obj_t*)MP_OBJ_TO_PTR(elem->value))->flags = flags; } } } } // poll each object in the map STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) { mp_uint_t n_ready = 0; for (mp_uint_t i = 0; i < poll_map->alloc; ++i) { if (!mp_map_slot_is_filled(poll_map, i)) { continue; } poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map->table[i].value); int errcode; mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj->flags, &errcode); poll_obj->flags_ret = ret; if (ret == -1) { // error doing ioctl mp_raise_OSError(errcode); } if (ret != 0) { // object is ready n_ready += 1; if (rwx_num != NULL) { if (ret & MP_STREAM_POLL_RD) { rwx_num[0] += 1; } if (ret & MP_STREAM_POLL_WR) { rwx_num[1] += 1; } if ((ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) { rwx_num[2] += 1; } } } } return n_ready; } /// \function select(rlist, wlist, xlist[, timeout]) STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) { // get array data from tuple/list arguments size_t rwx_len[3]; mp_obj_t *r_array, *w_array, *x_array; mp_obj_get_array(args[0], &rwx_len[0], &r_array); mp_obj_get_array(args[1], &rwx_len[1], &w_array); mp_obj_get_array(args[2], &rwx_len[2], &x_array); // get timeout mp_uint_t timeout = -1; if (n_args == 4) { if (args[3] != mp_const_none) { #if MICROPY_PY_BUILTINS_FLOAT float timeout_f = mp_obj_get_float(args[3]); if (timeout_f >= 0) { timeout = (mp_uint_t)(timeout_f * 1000); } #else timeout = mp_obj_get_int(args[3]) * 1000; #endif } } // merge separate lists and get the ioctl function for each object mp_map_t poll_map; mp_map_init(&poll_map, rwx_len[0] + rwx_len[1] + rwx_len[2]); poll_map_add(&poll_map, r_array, rwx_len[0], MP_STREAM_POLL_RD, true); poll_map_add(&poll_map, w_array, rwx_len[1], MP_STREAM_POLL_WR, true); poll_map_add(&poll_map, x_array, rwx_len[2], MP_STREAM_POLL_ERR | MP_STREAM_POLL_HUP, true); mp_uint_t start_tick = mp_hal_ticks_ms(); rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; for (;;) { // poll the objects mp_uint_t n_ready = poll_map_poll(&poll_map, rwx_len); if (n_ready > 0 || (timeout != -1 && mp_hal_ticks_ms() - start_tick >= timeout)) { // one or more objects are ready, or we had a timeout mp_obj_t list_array[3]; list_array[0] = mp_obj_new_list(rwx_len[0], NULL); list_array[1] = mp_obj_new_list(rwx_len[1], NULL); list_array[2] = mp_obj_new_list(rwx_len[2], NULL); rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; for (mp_uint_t i = 0; i < poll_map.alloc; ++i) { if (!mp_map_slot_is_filled(&poll_map, i)) { continue; } poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map.table[i].value); if (poll_obj->flags_ret & MP_STREAM_POLL_RD) { ((mp_obj_list_t*)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj; } if (poll_obj->flags_ret & MP_STREAM_POLL_WR) { ((mp_obj_list_t*)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj; } if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) { ((mp_obj_list_t*)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj; } } mp_map_deinit(&poll_map); return mp_obj_new_tuple(3, list_array); } MICROPY_EVENT_POLL_HOOK } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select); /// \class Poll - poll class typedef struct _mp_obj_poll_t { mp_obj_base_t base; mp_map_t poll_map; short iter_cnt; short iter_idx; int flags; // callee-owned tuple mp_obj_t ret_tuple; } mp_obj_poll_t; /// \method register(obj[, eventmask]) STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); mp_uint_t flags; if (n_args == 3) { flags = mp_obj_get_int(args[2]); } else { flags = MP_STREAM_POLL_RD | MP_STREAM_POLL_WR; } poll_map_add(&self->poll_map, &args[1], 1, flags, false); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); /// \method unregister(obj) STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND); // TODO raise KeyError if obj didn't exist in map return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister); /// \method modify(obj, eventmask) STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP); if (elem == NULL) { mp_raise_OSError(MP_ENOENT); } ((poll_obj_t*)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); // work out timeout (its given already in ms) mp_uint_t timeout = -1; int flags = 0; if (n_args >= 2) { if (args[1] != mp_const_none) { mp_int_t timeout_i = mp_obj_get_int(args[1]); if (timeout_i >= 0) { timeout = timeout_i; } } if (n_args >= 3) { flags = mp_obj_get_int(args[2]); } } self->flags = flags; mp_uint_t start_tick = mp_hal_ticks_ms(); mp_uint_t n_ready; for (;;) { // poll the objects n_ready = poll_map_poll(&self->poll_map, NULL); if (n_ready > 0 || (timeout != -1 && mp_hal_ticks_ms() - start_tick >= timeout)) { break; } MICROPY_EVENT_POLL_HOOK } return n_ready; } STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); mp_uint_t n_ready = poll_poll_internal(n_args, args); // one or more objects are ready, or we had a timeout mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL)); n_ready = 0; for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) { if (!mp_map_slot_is_filled(&self->poll_map, i)) { continue; } poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value); if (poll_obj->flags_ret != 0) { mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)}; ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple); if (self->flags & FLAG_ONESHOT) { // Don't poll next time, until new event flags will be set explicitly poll_obj->flags = 0; } } } return MP_OBJ_FROM_PTR(ret_list); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll); STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); if (self->ret_tuple == MP_OBJ_NULL) { self->ret_tuple = mp_obj_new_tuple(2, NULL); } int n_ready = poll_poll_internal(n_args, args); self->iter_cnt = n_ready; self->iter_idx = 0; return args[0]; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll); STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); if (self->iter_cnt == 0) { return MP_OBJ_STOP_ITERATION; } self->iter_cnt--; for (mp_uint_t i = self->iter_idx; i < self->poll_map.alloc; ++i) { self->iter_idx++; if (!mp_map_slot_is_filled(&self->poll_map, i)) { continue; } poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value); if (poll_obj->flags_ret != 0) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple); t->items[0] = poll_obj->obj; t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret); if (self->flags & FLAG_ONESHOT) { // Don't poll next time, until new event flags will be set explicitly poll_obj->flags = 0; } return MP_OBJ_FROM_PTR(t); } } assert(!"inconsistent number of poll active entries"); self->iter_cnt = 0; return MP_OBJ_STOP_ITERATION; } STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) }, { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) }, { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) }, { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) }, { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) }, }; STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); STATIC const mp_obj_type_t mp_type_poll = { { &mp_type_type }, .name = MP_QSTR_poll, .getiter = mp_identity_getiter, .iternext = poll_iternext, .locals_dict = (void*)&poll_locals_dict, }; /// \function poll() STATIC mp_obj_t select_poll(void) { mp_obj_poll_t *poll = m_new_obj(mp_obj_poll_t); poll->base.type = &mp_type_poll; mp_map_init(&poll->poll_map, 0); poll->iter_cnt = 0; poll->ret_tuple = MP_OBJ_NULL; return MP_OBJ_FROM_PTR(poll); } MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll); STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uselect) }, { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_select_select_obj) }, { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) }, { MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(MP_STREAM_POLL_RD) }, { MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(MP_STREAM_POLL_WR) }, { MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(MP_STREAM_POLL_ERR) }, { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(MP_STREAM_POLL_HUP) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table); const mp_obj_module_t mp_module_uselect = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_select_globals, }; #endif // MICROPY_PY_USELECT micropython-1.12/extmod/modussl_axtls.c000066400000000000000000000226161357706137100203760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015-2019 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/stream.h" #if MICROPY_PY_USSL && MICROPY_SSL_AXTLS #include "ssl.h" typedef struct _mp_obj_ssl_socket_t { mp_obj_base_t base; mp_obj_t sock; SSL_CTX *ssl_ctx; SSL *ssl_sock; byte *buf; uint32_t bytes_left; bool blocking; } mp_obj_ssl_socket_t; struct ssl_args { mp_arg_val_t key; mp_arg_val_t cert; mp_arg_val_t server_side; mp_arg_val_t server_hostname; mp_arg_val_t do_handshake; }; STATIC const mp_obj_type_t ussl_socket_type; STATIC mp_obj_ssl_socket_t *ussl_socket_new(mp_obj_t sock, struct ssl_args *args) { #if MICROPY_PY_USSL_FINALISER mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t); #else mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t); #endif o->base.type = &ussl_socket_type; o->buf = NULL; o->bytes_left = 0; o->sock = sock; o->blocking = true; uint32_t options = SSL_SERVER_VERIFY_LATER; if (!args->do_handshake.u_bool) { options |= SSL_CONNECT_IN_PARTS; } if (args->key.u_obj != mp_const_none) { options |= SSL_NO_DEFAULT_KEY; } if ((o->ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) { mp_raise_OSError(MP_EINVAL); } if (args->key.u_obj != mp_const_none) { size_t len; const byte *data = (const byte*)mp_obj_str_get_data(args->key.u_obj, &len); int res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_RSA_KEY, data, len, NULL); if (res != SSL_OK) { mp_raise_ValueError("invalid key"); } data = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &len); res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_X509_CERT, data, len, NULL); if (res != SSL_OK) { mp_raise_ValueError("invalid cert"); } } if (args->server_side.u_bool) { o->ssl_sock = ssl_server_new(o->ssl_ctx, (long)sock); } else { SSL_EXTENSIONS *ext = ssl_ext_new(); if (args->server_hostname.u_obj != mp_const_none) { ext->host_name = (char*)mp_obj_str_get_str(args->server_hostname.u_obj); } o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0, ext); if (args->do_handshake.u_bool) { int res = ssl_handshake_status(o->ssl_sock); if (res != SSL_OK) { printf("ssl_handshake_status: %d\n", res); ssl_display_error(res); mp_raise_OSError(MP_EIO); } } } return o; } STATIC void ussl_socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "<_SSLSocket %p>", self->ssl_sock); } STATIC mp_uint_t ussl_socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); if (o->ssl_sock == NULL) { *errcode = EBADF; return MP_STREAM_ERROR; } while (o->bytes_left == 0) { mp_int_t r = ssl_read(o->ssl_sock, &o->buf); if (r == SSL_OK) { // SSL_OK from ssl_read() means "everything is ok, but there's // no user data yet". It may happen e.g. if handshake is not // finished yet. The best way we can treat it is by returning // EAGAIN. This may be a bit unexpected in blocking mode, but // default is to perform complete handshake in constructor, so // this should not happen in blocking mode. On the other hand, // in nonblocking mode EAGAIN (comparing to the alternative of // looping) is really preferrable. if (o->blocking) { continue; } else { goto eagain; } } if (r < 0) { if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) { // EOF return 0; } if (r == SSL_EAGAIN) { eagain: r = MP_EAGAIN; } *errcode = r; return MP_STREAM_ERROR; } o->bytes_left = r; } if (size > o->bytes_left) { size = o->bytes_left; } memcpy(buf, o->buf, size); o->buf += size; o->bytes_left -= size; return size; } STATIC mp_uint_t ussl_socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); if (o->ssl_sock == NULL) { *errcode = EBADF; return MP_STREAM_ERROR; } mp_int_t r = ssl_write(o->ssl_sock, buf, size); if (r < 0) { *errcode = r; return MP_STREAM_ERROR; } return r; } STATIC mp_uint_t ussl_socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in); if (request == MP_STREAM_CLOSE && self->ssl_sock != NULL) { ssl_free(self->ssl_sock); ssl_ctx_free(self->ssl_ctx); self->ssl_sock = NULL; } // Pass all requests down to the underlying socket return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode); } STATIC mp_obj_t ussl_socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in); mp_obj_t sock = o->sock; mp_obj_t dest[3]; mp_load_method(sock, MP_QSTR_setblocking, dest); dest[2] = flag_in; mp_obj_t res = mp_call_method_n_kw(1, 0, dest); o->blocking = mp_obj_is_true(flag_in); return res; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(ussl_socket_setblocking_obj, ussl_socket_setblocking); STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&ussl_socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, #if MICROPY_PY_USSL_FINALISER { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table); STATIC const mp_stream_p_t ussl_socket_stream_p = { .read = ussl_socket_read, .write = ussl_socket_write, .ioctl = ussl_socket_ioctl, }; STATIC const mp_obj_type_t ussl_socket_type = { { &mp_type_type }, // Save on qstr's, reuse same as for module .name = MP_QSTR_ussl, .print = ussl_socket_print, .getiter = NULL, .iternext = NULL, .protocol = &ussl_socket_stream_p, .locals_dict = (void*)&ussl_socket_locals_dict, }; STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO: Implement more args static const mp_arg_t allowed_args[] = { { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; // TODO: Check that sock implements stream protocol mp_obj_t sock = pos_args[0]; struct ssl_args args; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); return MP_OBJ_FROM_PTR(ussl_socket_new(sock, &args)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket); STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) }, { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table); const mp_obj_module_t mp_module_ussl = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_ssl_globals, }; #endif // MICROPY_PY_USSL micropython-1.12/extmod/modussl_mbedtls.c000066400000000000000000000314241357706137100206720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Linaro Ltd. * Copyright (c) 2019 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS #include #include #include // needed because mp_is_nonblocking_error uses system error codes #include "py/runtime.h" #include "py/stream.h" // mbedtls_time_t #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "mbedtls/x509_crt.h" #include "mbedtls/pk.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/debug.h" typedef struct _mp_obj_ssl_socket_t { mp_obj_base_t base; mp_obj_t sock; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; mbedtls_x509_crt cert; mbedtls_pk_context pkey; } mp_obj_ssl_socket_t; struct ssl_args { mp_arg_val_t key; mp_arg_val_t cert; mp_arg_val_t server_side; mp_arg_val_t server_hostname; mp_arg_val_t do_handshake; }; STATIC const mp_obj_type_t ussl_socket_type; #ifdef MBEDTLS_DEBUG_C STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) { (void)ctx; (void)level; printf("DBG:%s:%04d: %s\n", file, line, str); } #endif STATIC int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) { mp_obj_t sock = *(mp_obj_t*)ctx; const mp_stream_p_t *sock_stream = mp_get_stream(sock); int err; mp_uint_t out_sz = sock_stream->write(sock, buf, len, &err); if (out_sz == MP_STREAM_ERROR) { if (mp_is_nonblocking_error(err)) { return MBEDTLS_ERR_SSL_WANT_WRITE; } return -err; } else { return out_sz; } } STATIC int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) { mp_obj_t sock = *(mp_obj_t*)ctx; const mp_stream_p_t *sock_stream = mp_get_stream(sock); int err; mp_uint_t out_sz = sock_stream->read(sock, buf, len, &err); if (out_sz == MP_STREAM_ERROR) { if (mp_is_nonblocking_error(err)) { return MBEDTLS_ERR_SSL_WANT_READ; } return -err; } else { return out_sz; } } STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { // Verify the socket object has the full stream protocol mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); #if MICROPY_PY_USSL_FINALISER mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t); #else mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t); #endif o->base.type = &ussl_socket_type; o->sock = sock; int ret; mbedtls_ssl_init(&o->ssl); mbedtls_ssl_config_init(&o->conf); mbedtls_x509_crt_init(&o->cacert); mbedtls_x509_crt_init(&o->cert); mbedtls_pk_init(&o->pkey); mbedtls_ctr_drbg_init(&o->ctr_drbg); #ifdef MBEDTLS_DEBUG_C // Debug level (0-4) mbedtls_debug_set_threshold(0); #endif mbedtls_entropy_init(&o->entropy); const byte seed[] = "upy"; ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, mbedtls_entropy_func, &o->entropy, seed, sizeof(seed)); if (ret != 0) { goto cleanup; } ret = mbedtls_ssl_config_defaults(&o->conf, args->server_side.u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { goto cleanup; } mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg); #ifdef MBEDTLS_DEBUG_C mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL); #endif ret = mbedtls_ssl_setup(&o->ssl, &o->conf); if (ret != 0) { goto cleanup; } if (args->server_hostname.u_obj != mp_const_none) { const char *sni = mp_obj_str_get_str(args->server_hostname.u_obj); ret = mbedtls_ssl_set_hostname(&o->ssl, sni); if (ret != 0) { goto cleanup; } } mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL); if (args->key.u_obj != mp_const_none) { size_t key_len; const byte *key = (const byte*)mp_obj_str_get_data(args->key.u_obj, &key_len); // len should include terminating null ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0); if (ret != 0) { ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; // use general error for all key errors goto cleanup; } size_t cert_len; const byte *cert = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &cert_len); // len should include terminating null ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1); if (ret != 0) { ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; // use general error for all cert errors goto cleanup; } ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey); if (ret != 0) { goto cleanup; } } if (args->do_handshake.u_bool) { while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { printf("mbedtls_ssl_handshake error: -%x\n", -ret); goto cleanup; } } } return o; cleanup: mbedtls_pk_free(&o->pkey); mbedtls_x509_crt_free(&o->cert); mbedtls_x509_crt_free(&o->cacert); mbedtls_ssl_free(&o->ssl); mbedtls_ssl_config_free(&o->conf); mbedtls_ctr_drbg_free(&o->ctr_drbg); mbedtls_entropy_free(&o->entropy); if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) { mp_raise_OSError(MP_ENOMEM); } else if (ret == MBEDTLS_ERR_PK_BAD_INPUT_DATA) { mp_raise_ValueError("invalid key"); } else if (ret == MBEDTLS_ERR_X509_BAD_INPUT_DATA) { mp_raise_ValueError("invalid cert"); } else { mp_raise_OSError(MP_EIO); } } STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); if (!mp_obj_is_true(binary_form)) { mp_raise_NotImplementedError(NULL); } const mbedtls_x509_crt* peer_cert = mbedtls_ssl_get_peer_cert(&o->ssl); if (peer_cert == NULL) { return mp_const_none; } return mp_obj_new_bytes(peer_cert->raw.p, peer_cert->raw.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert); STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "<_SSLSocket %p>", self); } STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); int ret = mbedtls_ssl_read(&o->ssl, buf, size); if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { // end of stream return 0; } if (ret >= 0) { return ret; } if (ret == MBEDTLS_ERR_SSL_WANT_READ) { ret = MP_EWOULDBLOCK; } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { // If handshake is not finished, read attempt may end up in protocol // wanting to write next handshake message. The same may happen with // renegotation. ret = MP_EWOULDBLOCK; } *errcode = ret; return MP_STREAM_ERROR; } STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); int ret = mbedtls_ssl_write(&o->ssl, buf, size); if (ret >= 0) { return ret; } if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { ret = MP_EWOULDBLOCK; } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) { // If handshake is not finished, write attempt may end up in protocol // wanting to read next handshake message. The same may happen with // renegotation. ret = MP_EWOULDBLOCK; } *errcode = ret; return MP_STREAM_ERROR; } STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in); mp_obj_t sock = o->sock; mp_obj_t dest[3]; mp_load_method(sock, MP_QSTR_setblocking, dest); dest[2] = flag_in; return mp_call_method_n_kw(1, 0, dest); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in); if (request == MP_STREAM_CLOSE) { mbedtls_pk_free(&self->pkey); mbedtls_x509_crt_free(&self->cert); mbedtls_x509_crt_free(&self->cacert); mbedtls_ssl_free(&self->ssl); mbedtls_ssl_config_free(&self->conf); mbedtls_ctr_drbg_free(&self->ctr_drbg); mbedtls_entropy_free(&self->entropy); } // Pass all requests down to the underlying socket return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode); } STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, #if MICROPY_PY_USSL_FINALISER { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table); STATIC const mp_stream_p_t ussl_socket_stream_p = { .read = socket_read, .write = socket_write, .ioctl = socket_ioctl, }; STATIC const mp_obj_type_t ussl_socket_type = { { &mp_type_type }, // Save on qstr's, reuse same as for module .name = MP_QSTR_ussl, .print = socket_print, .getiter = NULL, .iternext = NULL, .protocol = &ussl_socket_stream_p, .locals_dict = (void*)&ussl_socket_locals_dict, }; STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO: Implement more args static const mp_arg_t allowed_args[] = { { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; // TODO: Check that sock implements stream protocol mp_obj_t sock = pos_args[0]; struct ssl_args args; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); return MP_OBJ_FROM_PTR(socket_new(sock, &args)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket); STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) }, { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table); const mp_obj_module_t mp_module_ussl = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_ssl_globals, }; #endif // MICROPY_PY_USSL micropython-1.12/extmod/modutimeq.c000066400000000000000000000173141357706137100175000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2016-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/objlist.h" #include "py/runtime.h" #include "py/smallint.h" #if MICROPY_PY_UTIMEQ #define MODULO MICROPY_PY_UTIME_TICKS_PERIOD #define DEBUG 0 // the algorithm here is modelled on CPython's heapq.py struct qentry { mp_uint_t time; mp_uint_t id; mp_obj_t callback; mp_obj_t args; }; typedef struct _mp_obj_utimeq_t { mp_obj_base_t base; mp_uint_t alloc; mp_uint_t len; struct qentry items[]; } mp_obj_utimeq_t; STATIC mp_uint_t utimeq_id; STATIC mp_obj_utimeq_t *utimeq_get_heap(mp_obj_t heap_in) { return MP_OBJ_TO_PTR(heap_in); } STATIC bool time_less_than(struct qentry *item, struct qentry *parent) { mp_uint_t item_tm = item->time; mp_uint_t parent_tm = parent->time; mp_uint_t res = parent_tm - item_tm; if (res == 0) { // TODO: This actually should use the same "ring" logic // as for time, to avoid artifacts when id's overflow. return item->id < parent->id; } if ((mp_int_t)res < 0) { res += MODULO; } return res && res < (MODULO / 2); } STATIC mp_obj_t utimeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_uint_t alloc = mp_obj_get_int(args[0]); mp_obj_utimeq_t *o = m_new_obj_var(mp_obj_utimeq_t, struct qentry, alloc); o->base.type = type; memset(o->items, 0, sizeof(*o->items) * alloc); o->alloc = alloc; o->len = 0; return MP_OBJ_FROM_PTR(o); } STATIC void utimeq_heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t pos) { struct qentry item = heap->items[pos]; while (pos > start_pos) { mp_uint_t parent_pos = (pos - 1) >> 1; struct qentry *parent = &heap->items[parent_pos]; bool lessthan = time_less_than(&item, parent); if (lessthan) { heap->items[pos] = *parent; pos = parent_pos; } else { break; } } heap->items[pos] = item; } STATIC void utimeq_heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) { mp_uint_t start_pos = pos; mp_uint_t end_pos = heap->len; struct qentry item = heap->items[pos]; for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) { // choose right child if it's <= left child if (child_pos + 1 < end_pos) { bool lessthan = time_less_than(&heap->items[child_pos], &heap->items[child_pos + 1]); if (!lessthan) { child_pos += 1; } } // bubble up the smaller child heap->items[pos] = heap->items[child_pos]; pos = child_pos; } heap->items[pos] = item; utimeq_heap_siftdown(heap, start_pos, pos); } STATIC mp_obj_t mod_utimeq_heappush(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_t heap_in = args[0]; mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); if (heap->len == heap->alloc) { mp_raise_msg(&mp_type_IndexError, "queue overflow"); } mp_uint_t l = heap->len; heap->items[l].time = MP_OBJ_SMALL_INT_VALUE(args[1]); heap->items[l].id = utimeq_id++; heap->items[l].callback = args[2]; heap->items[l].args = args[3]; utimeq_heap_siftdown(heap, 0, heap->len); heap->len++; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_utimeq_heappush_obj, 4, 4, mod_utimeq_heappush); STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) { mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); if (heap->len == 0) { mp_raise_msg(&mp_type_IndexError, "empty heap"); } mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref); if (!mp_obj_is_type(list_ref, &mp_type_list) || ret->len < 3) { mp_raise_TypeError(NULL); } struct qentry *item = &heap->items[0]; ret->items[0] = MP_OBJ_NEW_SMALL_INT(item->time); ret->items[1] = item->callback; ret->items[2] = item->args; heap->len -= 1; heap->items[0] = heap->items[heap->len]; heap->items[heap->len].callback = MP_OBJ_NULL; // so we don't retain a pointer heap->items[heap->len].args = MP_OBJ_NULL; if (heap->len) { utimeq_heap_siftup(heap, 0); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_utimeq_heappop_obj, mod_utimeq_heappop); STATIC mp_obj_t mod_utimeq_peektime(mp_obj_t heap_in) { mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); if (heap->len == 0) { mp_raise_msg(&mp_type_IndexError, "empty heap"); } struct qentry *item = &heap->items[0]; return MP_OBJ_NEW_SMALL_INT(item->time); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_peektime_obj, mod_utimeq_peektime); #if DEBUG STATIC mp_obj_t mod_utimeq_dump(mp_obj_t heap_in) { mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); for (int i = 0; i < heap->len; i++) { printf(UINT_FMT "\t%p\t%p\n", heap->items[i].time, MP_OBJ_TO_PTR(heap->items[i].callback), MP_OBJ_TO_PTR(heap->items[i].args)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_dump_obj, mod_utimeq_dump); #endif STATIC mp_obj_t utimeq_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_utimeq_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len); default: return MP_OBJ_NULL; // op not supported } } STATIC const mp_rom_map_elem_t utimeq_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&mod_utimeq_heappush_obj) }, { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&mod_utimeq_heappop_obj) }, { MP_ROM_QSTR(MP_QSTR_peektime), MP_ROM_PTR(&mod_utimeq_peektime_obj) }, #if DEBUG { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_utimeq_dump_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(utimeq_locals_dict, utimeq_locals_dict_table); STATIC const mp_obj_type_t utimeq_type = { { &mp_type_type }, .name = MP_QSTR_utimeq, .make_new = utimeq_make_new, .unary_op = utimeq_unary_op, .locals_dict = (void*)&utimeq_locals_dict, }; STATIC const mp_rom_map_elem_t mp_module_utimeq_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utimeq) }, { MP_ROM_QSTR(MP_QSTR_utimeq), MP_ROM_PTR(&utimeq_type) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_utimeq_globals, mp_module_utimeq_globals_table); const mp_obj_module_t mp_module_utimeq = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_utimeq_globals, }; #endif //MICROPY_PY_UTIMEQ micropython-1.12/extmod/moduwebsocket.c000066400000000000000000000256071357706137100203530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/stream.h" #include "extmod/moduwebsocket.h" #if MICROPY_PY_UWEBSOCKET enum { FRAME_HEADER, FRAME_OPT, PAYLOAD, CONTROL }; enum { BLOCKING_WRITE = 0x80 }; typedef struct _mp_obj_websocket_t { mp_obj_base_t base; mp_obj_t sock; uint32_t msg_sz; byte mask[4]; byte state; byte to_recv; byte mask_pos; byte buf_pos; byte buf[6]; byte opts; // Copy of last data frame flags byte ws_flags; // Copy of current frame flags byte last_flags; } mp_obj_websocket_t; STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode); STATIC mp_obj_t websocket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); mp_obj_websocket_t *o = m_new_obj(mp_obj_websocket_t); o->base.type = type; o->sock = args[0]; o->state = FRAME_HEADER; o->to_recv = 2; o->mask_pos = 0; o->buf_pos = 0; o->opts = FRAME_TXT; if (n_args > 1 && args[1] == mp_const_true) { o->opts |= BLOCKING_WRITE; } return MP_OBJ_FROM_PTR(o); } STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in); const mp_stream_p_t *stream_p = mp_get_stream(self->sock); while (1) { if (self->to_recv != 0) { mp_uint_t out_sz = stream_p->read(self->sock, self->buf + self->buf_pos, self->to_recv, errcode); if (out_sz == 0 || out_sz == MP_STREAM_ERROR) { return out_sz; } self->buf_pos += out_sz; self->to_recv -= out_sz; if (self->to_recv != 0) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } } switch (self->state) { case FRAME_HEADER: { // TODO: Split frame handling below is untested so far, so conservatively disable it assert(self->buf[0] & 0x80); // "Control frames MAY be injected in the middle of a fragmented message." // So, they must be processed before data frames (and not alter // self->ws_flags) byte frame_type = self->buf[0]; self->last_flags = frame_type; frame_type &= FRAME_OPCODE_MASK; if ((self->buf[0] & FRAME_OPCODE_MASK) == FRAME_CONT) { // Preserve previous frame type self->ws_flags = (self->ws_flags & FRAME_OPCODE_MASK) | (self->buf[0] & ~FRAME_OPCODE_MASK); } else { self->ws_flags = self->buf[0]; } // Reset mask in case someone will use "simplified" protocol // without masks. memset(self->mask, 0, sizeof(self->mask)); int to_recv = 0; size_t sz = self->buf[1] & 0x7f; if (sz == 126) { // Msg size is next 2 bytes to_recv += 2; } else if (sz == 127) { // Msg size is next 8 bytes assert(0); } if (self->buf[1] & 0x80) { // Next 4 bytes is mask to_recv += 4; } self->buf_pos = 0; self->to_recv = to_recv; self->msg_sz = sz; // May be overridden by FRAME_OPT if (to_recv != 0) { self->state = FRAME_OPT; } else { if (frame_type >= FRAME_CLOSE) { self->state = CONTROL; } else { self->state = PAYLOAD; } } continue; } case FRAME_OPT: { if ((self->buf_pos & 3) == 2) { // First two bytes are message length self->msg_sz = (self->buf[0] << 8) | self->buf[1]; } if (self->buf_pos >= 4) { // Last 4 bytes is mask memcpy(self->mask, self->buf + self->buf_pos - 4, 4); } self->buf_pos = 0; if ((self->last_flags & FRAME_OPCODE_MASK) >= FRAME_CLOSE) { self->state = CONTROL; } else { self->state = PAYLOAD; } continue; } case PAYLOAD: case CONTROL: { mp_uint_t out_sz = 0; if (self->msg_sz == 0) { // In case message had zero payload goto no_payload; } size_t sz = MIN(size, self->msg_sz); out_sz = stream_p->read(self->sock, buf, sz, errcode); if (out_sz == 0 || out_sz == MP_STREAM_ERROR) { return out_sz; } sz = out_sz; for (byte *p = buf; sz--; p++) { *p ^= self->mask[self->mask_pos++ & 3]; } self->msg_sz -= out_sz; if (self->msg_sz == 0) { byte last_state; no_payload: last_state = self->state; self->state = FRAME_HEADER; self->to_recv = 2; self->mask_pos = 0; self->buf_pos = 0; // Handle control frame if (last_state == CONTROL) { byte frame_type = self->last_flags & FRAME_OPCODE_MASK; if (frame_type == FRAME_CLOSE) { static const char close_resp[2] = {0x88, 0}; int err; websocket_write(self_in, close_resp, sizeof(close_resp), &err); return 0; } //DEBUG_printf("Finished receiving ctrl message %x, ignoring\n", self->last_flags); continue; } } if (out_sz != 0) { return out_sz; } // Empty (data) frame received is not EOF continue; } } } } STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in); assert(size < 0x10000); byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)}; int hdr_sz; if (size < 126) { header[1] = size; hdr_sz = 2; } else { header[1] = 126; header[2] = size >> 8; header[3] = size & 0xff; hdr_sz = 4; } mp_obj_t dest[3]; if (self->opts & BLOCKING_WRITE) { mp_load_method(self->sock, MP_QSTR_setblocking, dest); dest[2] = mp_const_true; mp_call_method_n_kw(1, 0, dest); } mp_uint_t out_sz = mp_stream_write_exactly(self->sock, header, hdr_sz, errcode); if (*errcode == 0) { out_sz = mp_stream_write_exactly(self->sock, buf, size, errcode); } if (self->opts & BLOCKING_WRITE) { dest[2] = mp_const_false; mp_call_method_n_kw(1, 0, dest); } if (*errcode != 0) { return MP_STREAM_ERROR; } return out_sz; } STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in); switch (request) { case MP_STREAM_CLOSE: // TODO: Send close signaling to the other side, otherwise it's // abrupt close (connection abort). mp_stream_close(self->sock); return 0; case MP_STREAM_GET_DATA_OPTS: return self->ws_flags & FRAME_OPCODE_MASK; case MP_STREAM_SET_DATA_OPTS: { int cur = self->opts & FRAME_OPCODE_MASK; self->opts = (self->opts & ~FRAME_OPCODE_MASK) | (arg & FRAME_OPCODE_MASK); return cur; } default: *errcode = MP_EINVAL; return MP_STREAM_ERROR; } } STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, }; STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table); STATIC const mp_stream_p_t websocket_stream_p = { .read = websocket_read, .write = websocket_write, .ioctl = websocket_ioctl, }; STATIC const mp_obj_type_t websocket_type = { { &mp_type_type }, .name = MP_QSTR_websocket, .make_new = websocket_make_new, .protocol = &websocket_stream_p, .locals_dict = (void*)&websocket_locals_dict, }; STATIC const mp_rom_map_elem_t uwebsocket_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uwebsocket) }, { MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&websocket_type) }, }; STATIC MP_DEFINE_CONST_DICT(uwebsocket_module_globals, uwebsocket_module_globals_table); const mp_obj_module_t mp_module_uwebsocket = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&uwebsocket_module_globals, }; #endif // MICROPY_PY_UWEBSOCKET micropython-1.12/extmod/moduwebsocket.h000066400000000000000000000004211357706137100203430ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H #define MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H #define FRAME_OPCODE_MASK 0x0f enum { FRAME_CONT, FRAME_TXT, FRAME_BIN, FRAME_CLOSE = 0x8, FRAME_PING, FRAME_PONG }; #endif // MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H micropython-1.12/extmod/moduzlib.c000066400000000000000000000163441357706137100173230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #if MICROPY_PY_UZLIB #include "uzlib/tinf.h" #if 0 // print debugging info #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif typedef struct _mp_obj_decompio_t { mp_obj_base_t base; mp_obj_t src_stream; TINF_DATA decomp; bool eof; } mp_obj_decompio_t; STATIC int read_src_stream(TINF_DATA *data) { byte *p = (void*)data; p -= offsetof(mp_obj_decompio_t, decomp); mp_obj_decompio_t *self = (mp_obj_decompio_t*)p; const mp_stream_p_t *stream = mp_get_stream(self->src_stream); int err; byte c; mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err); if (out_sz == MP_STREAM_ERROR) { mp_raise_OSError(err); } if (out_sz == 0) { nlr_raise(mp_obj_new_exception(&mp_type_EOFError)); } return c; } STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_get_stream_raise(args[0], MP_STREAM_OP_READ); mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t); o->base.type = type; memset(&o->decomp, 0, sizeof(o->decomp)); o->decomp.readSource = read_src_stream; o->src_stream = args[0]; o->eof = false; mp_int_t dict_opt = 0; int dict_sz; if (n_args > 1) { dict_opt = mp_obj_get_int(args[1]); } if (dict_opt >= 16) { int st = uzlib_gzip_parse_header(&o->decomp); if (st != TINF_OK) { goto header_error; } dict_sz = 1 << (dict_opt - 16); } else if (dict_opt >= 0) { dict_opt = uzlib_zlib_parse_header(&o->decomp); if (dict_opt < 0) { header_error: mp_raise_ValueError("compression header"); } dict_sz = 1 << dict_opt; } else { dict_sz = 1 << -dict_opt; } uzlib_uncompress_init(&o->decomp, m_new(byte, dict_sz), dict_sz); return MP_OBJ_FROM_PTR(o); } STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in); if (o->eof) { return 0; } o->decomp.dest = buf; o->decomp.dest_limit = (byte*)buf + size; int st = uzlib_uncompress_chksum(&o->decomp); if (st == TINF_DONE) { o->eof = true; } if (st < 0) { *errcode = MP_EINVAL; return MP_STREAM_ERROR; } return o->decomp.dest - (byte*)buf; } #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, }; STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); #endif STATIC const mp_stream_p_t decompio_stream_p = { .read = decompio_read, }; #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_obj_type_t decompio_type = { { &mp_type_type }, .name = MP_QSTR_DecompIO, .make_new = decompio_make_new, .protocol = &decompio_stream_p, .locals_dict = (void*)&decompio_locals_dict, }; #endif STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { mp_obj_t data = args[0]; mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); TINF_DATA *decomp = m_new_obj(TINF_DATA); memset(decomp, 0, sizeof(*decomp)); DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp)); uzlib_uncompress_init(decomp, NULL, 0); mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15; byte *dest_buf = m_new(byte, dest_buf_size); decomp->dest = dest_buf; decomp->dest_limit = dest_buf + dest_buf_size; DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", dest_buf_size); decomp->source = bufinfo.buf; decomp->source_limit = (byte*)bufinfo.buf + bufinfo.len; int st; bool is_zlib = true; if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) { is_zlib = false; } if (is_zlib) { st = uzlib_zlib_parse_header(decomp); if (st < 0) { goto error; } } while (1) { st = uzlib_uncompress_chksum(decomp); if (st < 0) { goto error; } if (st == TINF_DONE) { break; } size_t offset = decomp->dest - dest_buf; dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256); dest_buf_size += 256; decomp->dest = dest_buf + offset; decomp->dest_limit = decomp->dest + 256; } mp_uint_t final_sz = decomp->dest - dest_buf; DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", dest_buf_size, final_sz); dest_buf = (byte*)m_renew(byte, dest_buf, dest_buf_size, final_sz); mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, dest_buf); m_del_obj(TINF_DATA, decomp); return res; error: nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st))); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress); #if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) }, { MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) }, { MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table); const mp_obj_module_t mp_module_uzlib = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_uzlib_globals, }; #endif // Source files #include'd here to make sure they're compiled in // only if module is enabled by config setting. #include "uzlib/tinflate.c" #include "uzlib/tinfzlib.c" #include "uzlib/tinfgzip.c" #include "uzlib/adler32.c" #include "uzlib/crc32.c" #endif // MICROPY_PY_UZLIB micropython-1.12/extmod/modwebrepl.c000066400000000000000000000303761357706137100176370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/builtin.h" #ifdef MICROPY_PY_WEBREPL_DELAY #include "py/mphal.h" #endif #include "extmod/moduwebsocket.h" #if MICROPY_PY_WEBREPL #if 0 // print debugging info #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif struct webrepl_file { char sig[2]; char type; char flags; uint64_t offset; uint32_t size; uint16_t fname_len; char fname[64]; } __attribute__((packed)); enum { PUT_FILE = 1, GET_FILE, GET_VER }; enum { STATE_PASSWD, STATE_NORMAL }; typedef struct _mp_obj_webrepl_t { mp_obj_base_t base; mp_obj_t sock; byte state; byte hdr_to_recv; uint32_t data_to_recv; struct webrepl_file hdr; mp_obj_t cur_file; } mp_obj_webrepl_t; STATIC const char passwd_prompt[] = "Password: "; STATIC const char connected_prompt[] = "\r\nWebREPL connected\r\n>>> "; STATIC const char denied_prompt[] = "\r\nAccess denied\r\n"; STATIC char webrepl_passwd[10]; STATIC void write_webrepl(mp_obj_t websock, const void *buf, size_t len) { const mp_stream_p_t *sock_stream = mp_get_stream(websock); int err; int old_opts = sock_stream->ioctl(websock, MP_STREAM_SET_DATA_OPTS, FRAME_BIN, &err); sock_stream->write(websock, buf, len, &err); sock_stream->ioctl(websock, MP_STREAM_SET_DATA_OPTS, old_opts, &err); } #define SSTR(s) s, sizeof(s) - 1 STATIC void write_webrepl_str(mp_obj_t websock, const char *str, int sz) { int err; const mp_stream_p_t *sock_stream = mp_get_stream(websock); sock_stream->write(websock, str, sz, &err); } STATIC void write_webrepl_resp(mp_obj_t websock, uint16_t code) { char buf[4] = {'W', 'B', code & 0xff, code >> 8}; write_webrepl(websock, buf, sizeof(buf)); } STATIC mp_obj_t webrepl_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); DEBUG_printf("sizeof(struct webrepl_file) = %lu\n", sizeof(struct webrepl_file)); mp_obj_webrepl_t *o = m_new_obj(mp_obj_webrepl_t); o->base.type = type; o->sock = args[0]; o->hdr_to_recv = sizeof(struct webrepl_file); o->data_to_recv = 0; o->state = STATE_PASSWD; write_webrepl_str(args[0], SSTR(passwd_prompt)); return o; } STATIC void check_file_op_finished(mp_obj_webrepl_t *self) { if (self->data_to_recv == 0) { mp_stream_close(self->cur_file); self->hdr_to_recv = sizeof(struct webrepl_file); DEBUG_printf("webrepl: Finished file operation %d\n", self->hdr.type); write_webrepl_resp(self->sock, 0); } } STATIC int write_file_chunk(mp_obj_webrepl_t *self) { const mp_stream_p_t *file_stream = mp_get_stream(self->cur_file); byte readbuf[2 + 256]; int err; mp_uint_t out_sz = file_stream->read(self->cur_file, readbuf + 2, sizeof(readbuf) - 2, &err); if (out_sz == MP_STREAM_ERROR) { return out_sz; } readbuf[0] = out_sz; readbuf[1] = out_sz >> 8; DEBUG_printf("webrepl: Sending %d bytes of file\n", out_sz); write_webrepl(self->sock, readbuf, 2 + out_sz); return out_sz; } STATIC void handle_op(mp_obj_webrepl_t *self) { // Handle operations not requiring opened file switch (self->hdr.type) { case GET_VER: { static const char ver[] = {MICROPY_VERSION_MAJOR, MICROPY_VERSION_MINOR, MICROPY_VERSION_MICRO}; write_webrepl(self->sock, ver, sizeof(ver)); self->hdr_to_recv = sizeof(struct webrepl_file); return; } } // Handle operations requiring opened file mp_obj_t open_args[2] = { mp_obj_new_str(self->hdr.fname, strlen(self->hdr.fname)), MP_OBJ_NEW_QSTR(MP_QSTR_rb) }; if (self->hdr.type == PUT_FILE) { open_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_wb); } self->cur_file = mp_builtin_open(2, open_args, (mp_map_t*)&mp_const_empty_map); #if 0 struct mp_stream_seek_t seek = { .offset = self->hdr.offset, .whence = 0 }; int err; mp_uint_t res = file_stream->ioctl(self->cur_file, MP_STREAM_SEEK, (uintptr_t)&seek, &err); assert(res != MP_STREAM_ERROR); #endif write_webrepl_resp(self->sock, 0); if (self->hdr.type == PUT_FILE) { self->data_to_recv = self->hdr.size; check_file_op_finished(self); } else if (self->hdr.type == GET_FILE) { self->data_to_recv = 1; } } STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode); STATIC mp_uint_t webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { mp_uint_t out_sz; do { out_sz = _webrepl_read(self_in, buf, size, errcode); } while (out_sz == -2); return out_sz; } STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { // We know that os.dupterm always calls with size = 1 assert(size == 1); mp_obj_webrepl_t *self = self_in; const mp_stream_p_t *sock_stream = mp_get_stream(self->sock); mp_uint_t out_sz = sock_stream->read(self->sock, buf, size, errcode); //DEBUG_printf("webrepl: Read %d initial bytes from websocket\n", out_sz); if (out_sz == 0 || out_sz == MP_STREAM_ERROR) { return out_sz; } if (self->state == STATE_PASSWD) { char c = *(char*)buf; if (c == '\r' || c == '\n') { self->hdr.fname[self->data_to_recv] = 0; DEBUG_printf("webrepl: entered password: %s\n", self->hdr.fname); if (strcmp(self->hdr.fname, webrepl_passwd) != 0) { write_webrepl_str(self->sock, SSTR(denied_prompt)); return 0; } self->state = STATE_NORMAL; self->data_to_recv = 0; write_webrepl_str(self->sock, SSTR(connected_prompt)); } else if (self->data_to_recv < 10) { self->hdr.fname[self->data_to_recv++] = c; } return -2; } // If last read data belonged to text record (== REPL) int err; if (sock_stream->ioctl(self->sock, MP_STREAM_GET_DATA_OPTS, 0, &err) == 1) { return out_sz; } DEBUG_printf("webrepl: received bin data, hdr_to_recv: %d, data_to_recv=%d\n", self->hdr_to_recv, self->data_to_recv); if (self->hdr_to_recv != 0) { char *p = (char*)&self->hdr + sizeof(self->hdr) - self->hdr_to_recv; *p++ = *(char*)buf; if (--self->hdr_to_recv != 0) { mp_uint_t hdr_sz = sock_stream->read(self->sock, p, self->hdr_to_recv, errcode); if (hdr_sz == MP_STREAM_ERROR) { return hdr_sz; } self->hdr_to_recv -= hdr_sz; if (self->hdr_to_recv != 0) { return -2; } } DEBUG_printf("webrepl: op: %d, file: %s, chunk @%x, sz=%d\n", self->hdr.type, self->hdr.fname, (uint32_t)self->hdr.offset, self->hdr.size); handle_op(self); return -2; } if (self->data_to_recv != 0) { // Ports that don't have much available stack can make this filebuf static #if MICROPY_PY_WEBREPL_STATIC_FILEBUF static #endif byte filebuf[512]; filebuf[0] = *(byte*)buf; mp_uint_t buf_sz = 1; if (--self->data_to_recv != 0) { size_t to_read = MIN(sizeof(filebuf) - 1, self->data_to_recv); mp_uint_t sz = sock_stream->read(self->sock, filebuf + 1, to_read, errcode); if (sz == MP_STREAM_ERROR) { return sz; } self->data_to_recv -= sz; buf_sz += sz; } if (self->hdr.type == PUT_FILE) { DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz); int err; mp_uint_t res = mp_stream_write_exactly(self->cur_file, filebuf, buf_sz, &err); if (err != 0 || res != buf_sz) { assert(0); } } else if (self->hdr.type == GET_FILE) { assert(buf_sz == 1); assert(self->data_to_recv == 0); assert(filebuf[0] == 0); mp_uint_t out_sz = write_file_chunk(self); if (out_sz != 0) { self->data_to_recv = 1; } } check_file_op_finished(self); #ifdef MICROPY_PY_WEBREPL_DELAY // Some platforms may have broken drivers and easily gets // overloaded with modest traffic WebREPL file transfers // generate. The basic workaround is a crude rate control // done in such way. mp_hal_delay_ms(MICROPY_PY_WEBREPL_DELAY); #endif } return -2; } STATIC mp_uint_t webrepl_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_webrepl_t *self = self_in; if (self->state == STATE_PASSWD) { // Don't forward output until passwd is entered return size; } const mp_stream_p_t *stream_p = mp_get_stream(self->sock); return stream_p->write(self->sock, buf, size, errcode); } STATIC mp_uint_t webrepl_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_webrepl_t *self = MP_OBJ_TO_PTR(o_in); (void)arg; switch (request) { case MP_STREAM_CLOSE: // TODO: This is a place to do cleanup mp_stream_close(self->sock); return 0; default: *errcode = MP_EINVAL; return MP_STREAM_ERROR; } } STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) { size_t len; const char *passwd = mp_obj_str_get_data(passwd_in, &len); if (len > sizeof(webrepl_passwd) - 1) { mp_raise_ValueError(NULL); } strcpy(webrepl_passwd, passwd); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_set_password_obj, webrepl_set_password); STATIC const mp_rom_map_elem_t webrepl_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, }; STATIC MP_DEFINE_CONST_DICT(webrepl_locals_dict, webrepl_locals_dict_table); STATIC const mp_stream_p_t webrepl_stream_p = { .read = webrepl_read, .write = webrepl_write, .ioctl = webrepl_ioctl, }; STATIC const mp_obj_type_t webrepl_type = { { &mp_type_type }, .name = MP_QSTR__webrepl, .make_new = webrepl_make_new, .protocol = &webrepl_stream_p, .locals_dict = (mp_obj_dict_t*)&webrepl_locals_dict, }; STATIC const mp_rom_map_elem_t webrepl_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__webrepl) }, { MP_ROM_QSTR(MP_QSTR__webrepl), MP_ROM_PTR(&webrepl_type) }, { MP_ROM_QSTR(MP_QSTR_password), MP_ROM_PTR(&webrepl_set_password_obj) }, }; STATIC MP_DEFINE_CONST_DICT(webrepl_module_globals, webrepl_module_globals_table); const mp_obj_module_t mp_module_webrepl = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&webrepl_module_globals, }; #endif // MICROPY_PY_WEBREPL micropython-1.12/extmod/network_cyw43.c000066400000000000000000000446661357706137100202300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/objstr.h" #include "py/mphal.h" #if MICROPY_PY_NETWORK_CYW43 #include "lwip/netif.h" #include "drivers/cyw43/cyw43.h" #include "extmod/network_cyw43.h" #include "modnetwork.h" typedef struct _network_cyw43_obj_t { mp_obj_base_t base; cyw43_t *cyw; int itf; } network_cyw43_obj_t; STATIC const network_cyw43_obj_t network_cyw43_wl0 = { { &mp_network_cyw43_type }, &cyw43_state, 0 }; STATIC const network_cyw43_obj_t network_cyw43_wl1 = { { &mp_network_cyw43_type }, &cyw43_state, 1 }; STATIC void network_cyw43_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); struct netif *netif = &self->cyw->netif[self->itf]; int status = cyw43_tcpip_link_status(self->cyw, self->itf); const char *status_str; if (status == CYW43_LINK_DOWN) { status_str = "down"; } else if (status == CYW43_LINK_JOIN || status == CYW43_LINK_NOIP) { status_str = "join"; } else if (status == CYW43_LINK_UP) { status_str = "up"; } else if (status == CYW43_LINK_NONET) { status_str = "nonet"; } else if (status == CYW43_LINK_BADAUTH) { status_str = "badauth"; } else { status_str = "fail"; } mp_printf(print, "", self->itf == 0 ? "STA" : "AP", status_str, netif->ip_addr.addr & 0xff, netif->ip_addr.addr >> 8 & 0xff, netif->ip_addr.addr >> 16 & 0xff, netif->ip_addr.addr >> 24 ); } STATIC mp_obj_t network_cyw43_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); if (n_args == 0 || mp_obj_get_int(args[0]) == 0) { return MP_OBJ_FROM_PTR(&network_cyw43_wl0); } else { return MP_OBJ_FROM_PTR(&network_cyw43_wl1); } } STATIC mp_obj_t network_cyw43_send_ethernet(mp_obj_t self_in, mp_obj_t buf_in) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t buf; mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ); int ret = cyw43_send_ethernet(self->cyw, self->itf, buf.len, buf.buf, false); if (ret) { mp_raise_OSError(-ret); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_cyw43_send_ethernet_obj, network_cyw43_send_ethernet); STATIC mp_obj_t network_cyw43_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t buf_in) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t buf; mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ | MP_BUFFER_WRITE); cyw43_ioctl(self->cyw, mp_obj_get_int(cmd_in), buf.len, buf.buf, self->itf); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(network_cyw43_ioctl_obj, network_cyw43_ioctl); /*******************************************************************************/ // network API STATIC mp_obj_t network_cyw43_deinit(mp_obj_t self_in) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); cyw43_deinit(self->cyw); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_deinit_obj, network_cyw43_deinit); STATIC mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf)); } else { cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1])); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_active_obj, 1, 2, network_cyw43_active); STATIC int network_cyw43_scan_cb(void *env, const cyw43_ev_scan_result_t *res) { mp_obj_t list = MP_OBJ_FROM_PTR(env); // Search for existing BSSID to remove duplicates bool found = false; size_t len; mp_obj_t *items; mp_obj_get_array(list, &len, &items); for (size_t i = 0; i < len; ++i) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(items[i]); if (memcmp(res->bssid, ((mp_obj_str_t*)MP_OBJ_TO_PTR(t->items[1]))->data, sizeof(res->bssid)) == 0) { if (res->rssi > MP_OBJ_SMALL_INT_VALUE(t->items[3])) { t->items[3] = MP_OBJ_NEW_SMALL_INT(res->rssi); } t->items[5] = MP_OBJ_NEW_SMALL_INT(MP_OBJ_SMALL_INT_VALUE(t->items[5]) + 1); found = true; break; } } // Add to list of results if wanted if (!found) { mp_obj_t tuple[6] = { mp_obj_new_bytes(res->ssid, res->ssid_len), mp_obj_new_bytes(res->bssid, sizeof(res->bssid)), MP_OBJ_NEW_SMALL_INT(res->channel), MP_OBJ_NEW_SMALL_INT(res->rssi), MP_OBJ_NEW_SMALL_INT(res->auth_mode), //mp_const_false, // hidden MP_OBJ_NEW_SMALL_INT(1), // N }; mp_obj_list_append(list, mp_obj_new_tuple(6, tuple)); } return 0; // continue scan } STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_passive, ARG_essid, ARG_bssid }; static const mp_arg_t allowed_args[] = { { MP_QSTR_passive, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_essid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; network_cyw43_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); cyw43_wifi_scan_options_t opts; opts.scan_type = args[ARG_passive].u_bool ? 1 : 0; if (args[ARG_essid].u_obj == mp_const_none) { opts.ssid_len = 0; } else { mp_buffer_info_t ssid; mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ); opts.ssid_len = MIN(ssid.len, sizeof(opts.ssid)); memcpy(opts.ssid, ssid.buf, opts.ssid_len); } if (args[ARG_bssid].u_obj == mp_const_none) { memset(opts.bssid, 0xff, sizeof(opts.bssid)); } else { mp_buffer_info_t bssid; mp_get_buffer_raise(args[ARG_bssid].u_obj, &bssid, MP_BUFFER_READ); memcpy(opts.bssid, bssid.buf, sizeof(opts.bssid)); } mp_obj_t res = mp_obj_new_list(0, NULL); int scan_res = cyw43_wifi_scan(self->cyw, &opts, MP_OBJ_TO_PTR(res), network_cyw43_scan_cb); if (scan_res < 0) { mp_raise_msg(&mp_type_OSError, "STA must be active"); } // Wait for scan to finish, with a 10s timeout uint32_t start = mp_hal_ticks_ms(); while (cyw43_wifi_scan_active(self->cyw) && mp_hal_ticks_ms() - start < 10000) { MICROPY_EVENT_POLL_HOOK } return res; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_scan_obj, 1, network_cyw43_scan); STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_essid, ARG_key, ARG_auth, ARG_bssid, ARG_channel }; static const mp_arg_t allowed_args[] = { { MP_QSTR_essid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_key, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; network_cyw43_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_buffer_info_t ssid; mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ); mp_buffer_info_t key; key.buf = NULL; if (args[ARG_key].u_obj != mp_const_none) { mp_get_buffer_raise(args[ARG_key].u_obj, &key, MP_BUFFER_READ); } mp_buffer_info_t bssid; bssid.buf = NULL; if (args[ARG_bssid].u_obj != mp_const_none) { mp_get_buffer_raise(args[ARG_bssid].u_obj, &bssid, MP_BUFFER_READ); if (bssid.len != 6) { mp_raise_ValueError(NULL); } } int ret = cyw43_wifi_join(self->cyw, ssid.len, ssid.buf, key.len, key.buf, args[ARG_auth].u_int, bssid.buf, args[ARG_channel].u_int); if (ret != 0) { mp_raise_OSError(ret); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_connect_obj, 1, network_cyw43_connect); STATIC mp_obj_t network_cyw43_disconnect(mp_obj_t self_in) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); cyw43_wifi_leave(self->cyw, self->itf); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_disconnect_obj, network_cyw43_disconnect); STATIC mp_obj_t network_cyw43_isconnected(mp_obj_t self_in) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf) == 3); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_isconnected_obj, network_cyw43_isconnected); STATIC mp_obj_t network_cyw43_ifconfig(size_t n_args, const mp_obj_t *args) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); return mod_network_nic_ifconfig(&self->cyw->netif[self->itf], n_args - 1, args + 1); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_ifconfig_obj, 1, 2, network_cyw43_ifconfig); STATIC mp_obj_t network_cyw43_status(size_t n_args, const mp_obj_t *args) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); (void)self; if (n_args == 1) { // no arguments: return link status return MP_OBJ_NEW_SMALL_INT(cyw43_tcpip_link_status(self->cyw, self->itf)); } // one argument: return status based on query parameter switch (mp_obj_str_get_qstr(args[1])) { case MP_QSTR_stations: { // return list of connected stations if (self->itf != CYW43_ITF_AP) { mp_raise_ValueError("AP required"); } int num_stas; uint8_t macs[32 * 6]; cyw43_wifi_ap_get_stas(self->cyw, &num_stas, macs); mp_obj_t list = mp_obj_new_list(num_stas, NULL); for (int i = 0; i < num_stas; ++i) { mp_obj_t tuple[1] = { mp_obj_new_bytes(&macs[i * 6], 6), }; ((mp_obj_list_t*)MP_OBJ_TO_PTR(list))->items[i] = mp_obj_new_tuple(1, tuple); } return list; } } mp_raise_ValueError("unknown status param"); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_status_obj, 1, 2, network_cyw43_status); static inline uint32_t nw_get_le32(const uint8_t *buf) { return buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24; } static inline void nw_put_le32(uint8_t *buf, uint32_t x) { buf[0] = x; buf[1] = x >> 8; buf[2] = x >> 16; buf[3] = x >> 24; } STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (kwargs->used == 0) { // Get config value if (n_args != 2) { mp_raise_TypeError("must query one param"); } switch (mp_obj_str_get_qstr(args[1])) { case MP_QSTR_antenna: { uint8_t buf[4]; cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_ANTDIV, 4, buf, self->itf); return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf)); } case MP_QSTR_channel: { uint8_t buf[4]; cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_CHANNEL, 4, buf, self->itf); return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf)); } case MP_QSTR_essid: { if (self->itf == CYW43_ITF_STA) { uint8_t buf[36]; cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_SSID, 36, buf, self->itf); return mp_obj_new_str((const char*)buf + 4, nw_get_le32(buf)); } else { size_t len; const uint8_t *buf; cyw43_wifi_ap_get_ssid(self->cyw, &len, &buf); return mp_obj_new_str((const char*)buf, len); } } case MP_QSTR_mac: { uint8_t buf[6]; cyw43_wifi_get_mac(self->cyw, self->itf, buf); return mp_obj_new_bytes(buf, 6); } case MP_QSTR_txpower: { uint8_t buf[13]; memcpy(buf, "qtxpower\x00\x00\x00\x00\x00", 13); cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_VAR, 13, buf, self->itf); return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf) / 4); } default: mp_raise_ValueError("unknown config param"); } } else { // Set config value(s) if (n_args != 1) { mp_raise_TypeError("can't specify pos and kw args"); } for (size_t i = 0; i < kwargs->alloc; ++i) { if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { mp_map_elem_t *e = &kwargs->table[i]; switch (mp_obj_str_get_qstr(e->key)) { case MP_QSTR_antenna: { uint8_t buf[4]; nw_put_le32(buf, mp_obj_get_int(e->value)); cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_ANTDIV, 4, buf, self->itf); break; } case MP_QSTR_channel: { cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value)); break; } case MP_QSTR_essid: { size_t len; const char *str = mp_obj_str_get_data(e->value, &len); cyw43_wifi_ap_set_ssid(self->cyw, len, (const uint8_t*)str); break; } case MP_QSTR_monitor: { mp_int_t value = mp_obj_get_int(e->value); uint8_t buf[9 + 4]; memcpy(buf, "allmulti\x00", 9); nw_put_le32(buf + 9, value); cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf); nw_put_le32(buf, value); cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_MONITOR, 4, buf, self->itf); if (value) { self->cyw->trace_flags |= CYW43_TRACE_MAC; } else { self->cyw->trace_flags &= ~CYW43_TRACE_MAC; } break; } case MP_QSTR_password: { size_t len; const char *str = mp_obj_str_get_data(e->value, &len); cyw43_wifi_ap_set_password(self->cyw, len, (const uint8_t*)str); break; } case MP_QSTR_pm: { cyw43_wifi_pm(self->cyw, mp_obj_get_int(e->value)); break; } case MP_QSTR_trace: { self->cyw->trace_flags = mp_obj_get_int(e->value); break; } case MP_QSTR_txpower: { mp_int_t dbm = mp_obj_get_int(e->value); uint8_t buf[9 + 4]; memcpy(buf, "qtxpower\x00", 9); nw_put_le32(buf + 9, dbm * 4); cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf); break; } default: mp_raise_ValueError("unknown config param"); } } } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_config_obj, 1, network_cyw43_config); /*******************************************************************************/ // class bindings STATIC const mp_rom_map_elem_t network_cyw43_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_send_ethernet), MP_ROM_PTR(&network_cyw43_send_ethernet_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&network_cyw43_ioctl_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_cyw43_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_cyw43_active_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_cyw43_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_cyw43_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_cyw43_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_cyw43_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_cyw43_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_cyw43_status_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_cyw43_config_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_cyw43_locals_dict, network_cyw43_locals_dict_table); const mp_obj_type_t mp_network_cyw43_type = { { &mp_type_type }, .name = MP_QSTR_CYW43, .print = network_cyw43_print, .make_new = network_cyw43_make_new, .locals_dict = (mp_obj_dict_t*)&network_cyw43_locals_dict, }; #endif // MICROPY_PY_NETWORK_CYW43 micropython-1.12/extmod/network_cyw43.h000066400000000000000000000026171357706137100202230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H #define MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H extern const mp_obj_type_t mp_network_cyw43_type; #endif // MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H micropython-1.12/extmod/nimble/000077500000000000000000000000001357706137100165705ustar00rootroot00000000000000micropython-1.12/extmod/nimble/bsp/000077500000000000000000000000001357706137100173545ustar00rootroot00000000000000micropython-1.12/extmod/nimble/bsp/bsp.h000066400000000000000000000000111357706137100203010ustar00rootroot00000000000000// empty micropython-1.12/extmod/nimble/hal/000077500000000000000000000000001357706137100173345ustar00rootroot00000000000000micropython-1.12/extmod/nimble/hal/hal_gpio.h000066400000000000000000000000111357706137100212570ustar00rootroot00000000000000// empty micropython-1.12/extmod/nimble/hal/hal_uart.h000066400000000000000000000012361357706137100213060ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H #define MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H #include #define SYSINIT_PANIC_ASSERT_MSG(cond, msg) #define HAL_UART_PARITY_NONE (0) typedef int (*hal_uart_tx_cb_t)(void *arg); typedef int (*hal_uart_rx_cb_t)(void *arg, uint8_t data); int hal_uart_init_cbs(uint32_t port, hal_uart_tx_cb_t tx_cb, void *tx_arg, hal_uart_rx_cb_t rx_cb, void *rx_arg); int hal_uart_config(uint32_t port, uint32_t baud, uint32_t bits, uint32_t stop, uint32_t parity, uint32_t flow); void hal_uart_start_tx(uint32_t port); int hal_uart_close(uint32_t port); #endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H micropython-1.12/extmod/nimble/nimble.mk000066400000000000000000000044321357706137100203720ustar00rootroot00000000000000# Makefile directives for Apache mynewt nimble BLE component ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) NIMBLE_LIB_DIR = lib/mynewt-nimble NIMBLE_EXTMOD_DIR = extmod/nimble SRC_LIB += $(addprefix $(NIMBLE_LIB_DIR)/, \ $(addprefix ext/tinycrypt/src/, \ aes_encrypt.c \ cmac_mode.c \ ecc.c \ ecc_dh.c \ utils.c \ ) \ nimble/host/services/gap/src/ble_svc_gap.c \ nimble/host/services/gatt/src/ble_svc_gatt.c \ $(addprefix nimble/host/src/, \ ble_att.c \ ble_att_clt.c \ ble_att_cmd.c \ ble_att_svr.c \ ble_eddystone.c \ ble_gap.c \ ble_gattc.c \ ble_gatts.c \ ble_hs_adv.c \ ble_hs_atomic.c \ ble_hs.c \ ble_hs_cfg.c \ ble_hs_conn.c \ ble_hs_dbg.c \ ble_hs_flow.c \ ble_hs_hci.c \ ble_hs_hci_cmd.c \ ble_hs_hci_evt.c \ ble_hs_hci_util.c \ ble_hs_id.c \ ble_hs_log.c \ ble_hs_mbuf.c \ ble_hs_misc.c \ ble_hs_mqueue.c \ ble_hs_pvcy.c \ ble_hs_startup.c \ ble_hs_stop.c \ ble_ibeacon.c \ ble_l2cap.c \ ble_l2cap_coc.c \ ble_l2cap_sig.c \ ble_l2cap_sig_cmd.c \ ble_monitor.c \ ble_sm_alg.c \ ble_sm.c \ ble_sm_cmd.c \ ble_sm_lgcy.c \ ble_sm_sc.c \ ble_store.c \ ble_store_util.c \ ble_uuid.c \ ) \ nimble/host/store/ram/src/ble_store_ram.c \ nimble/host/util/src/addr.c \ nimble/transport/uart/src/ble_hci_uart.c \ $(addprefix porting/nimble/src/, \ endian.c \ mem.c \ nimble_port.c \ os_mbuf.c \ os_mempool.c \ os_msys_init.c \ ) \ ) EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \ nimble/npl_os.c \ nimble/hci_uart.c \ ) CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1 INC += -I$(TOP)/$(NIMBLE_EXTMOD_DIR) INC += -I$(TOP)/$(NIMBLE_LIB_DIR) INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/ext/tinycrypt/include INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/include INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/services/gap/include INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/services/gatt/include INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/store/ram/include INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/util/include INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/include INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/transport/uart/include INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/porting/nimble/include $(BUILD)/$(NIMBLE_LIB_DIR)/%.o: CFLAGS += -Wno-maybe-uninitialized -Wno-pointer-arith -Wno-unused-but-set-variable -Wno-format endif micropython-1.12/extmod/nimble/nimble/000077500000000000000000000000001357706137100200365ustar00rootroot00000000000000micropython-1.12/extmod/nimble/nimble/hci_uart.c000066400000000000000000000054551357706137100220110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mphal.h" #include "pin_static_af.h" #include "nimble/ble.h" #include "hal/hal_uart.h" #include "hci_uart.h" #if MICROPY_BLUETOOTH_NIMBLE /******************************************************************************/ // Bindings Uart to Nimble uint8_t bt_hci_cmd_buf[4 + 256]; static hal_uart_tx_cb_t hal_uart_tx_cb; static void *hal_uart_tx_arg; static hal_uart_rx_cb_t hal_uart_rx_cb; static void *hal_uart_rx_arg; int hal_uart_init_cbs(uint32_t port, hal_uart_tx_cb_t tx_cb, void *tx_arg, hal_uart_rx_cb_t rx_cb, void *rx_arg) { hal_uart_tx_cb = tx_cb; hal_uart_tx_arg = tx_arg; hal_uart_rx_cb = rx_cb; hal_uart_rx_arg = rx_arg; return 0; // success } int hal_uart_config(uint32_t port, uint32_t baudrate, uint32_t bits, uint32_t stop, uint32_t parity, uint32_t flow) { nimble_hci_uart_configure(port); nimble_hci_uart_set_baudrate(baudrate); return nimble_hci_uart_activate(); } void hal_uart_start_tx(uint32_t port) { size_t len = 0; for (;;) { int data = hal_uart_tx_cb(hal_uart_tx_arg); if (data == -1) { break; } bt_hci_cmd_buf[len++] = data; } #if 0 printf("[% 8d] BTUTX: %02x", mp_hal_ticks_ms(), hci_cmd_buf[0]); for (int i = 1; i < len; ++i) { printf(":%02x", hci_cmd_buf[i]); } printf("\n"); #endif nimble_hci_uart_tx_strn((void*)bt_hci_cmd_buf, len); } int hal_uart_close(uint32_t port) { return 0; // success } void nimble_uart_process(void) { nimble_hci_uart_rx(hal_uart_rx_cb, hal_uart_rx_arg); } #endif // MICROPY_BLUETOOTH_NIMBLE micropython-1.12/extmod/nimble/nimble/hci_uart.h000066400000000000000000000034261357706137100220120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H #define MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H #include "extmod/nimble/hal/hal_uart.h" // To be implemented by the port. int nimble_hci_uart_configure(uint32_t port); // This will default to MICROPY_HW_BLE_UART_BAUDRATE, but can be updated later. int nimble_hci_uart_set_baudrate(uint32_t baudrate); int nimble_hci_uart_activate(void); void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg); void nimble_hci_uart_tx_strn(const char *str, uint len); #endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H micropython-1.12/extmod/nimble/nimble/nimble_npl_os.h000066400000000000000000000040121357706137100230240ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H #define MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H #include #define BLE_NPL_OS_ALIGNMENT (4) #define BLE_NPL_TIME_FOREVER (0xffffffff) typedef uint32_t ble_npl_time_t; typedef int32_t ble_npl_stime_t; struct ble_npl_event { ble_npl_event_fn *fn; void *arg; struct ble_npl_event *prev; struct ble_npl_event *next; }; struct ble_npl_eventq { struct ble_npl_event *head; struct ble_npl_eventq *nextq; }; struct ble_npl_callout { bool active; uint32_t ticks; struct ble_npl_eventq *evq; struct ble_npl_event ev; struct ble_npl_callout *nextc; }; struct ble_npl_mutex { volatile uint8_t locked; }; struct ble_npl_sem { volatile uint16_t count; }; #endif // MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H micropython-1.12/extmod/nimble/nimble/npl_os.c000066400000000000000000000305421357706137100215000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mphal.h" #include "py/runtime.h" #include "nimble/ble.h" #include "nimble/nimble_npl.h" #define DEBUG_OS_printf(...) //printf(__VA_ARGS__) #define DEBUG_MALLOC_printf(...) //printf(__VA_ARGS__) #define DEBUG_EVENT_printf(...) //printf(__VA_ARGS__) #define DEBUG_MUTEX_printf(...) //printf(__VA_ARGS__) #define DEBUG_SEM_printf(...) //printf(__VA_ARGS__) #define DEBUG_CALLOUT_printf(...) //printf(__VA_ARGS__) #define DEBUG_TIME_printf(...) //printf(__VA_ARGS__) #define DEBUG_CRIT_printf(...) //printf(__VA_ARGS__) bool ble_npl_os_started(void) { DEBUG_OS_printf("ble_npl_os_started\n"); return true; } void *ble_npl_get_current_task_id(void) { DEBUG_OS_printf("ble_npl_get_current_task_id\n"); return NULL; } /******************************************************************************/ // malloc // Maintain a linked list of heap memory that we've passed to Nimble, // discoverable via the bluetooth_nimble_memory root pointer. // MP_STATE_PORT(bluetooth_nimble_memory) is a pointer to [next, prev, data...]. // TODO: This is duplicated from mbedtls. Perhaps make this a generic feature? void *m_malloc_bluetooth(size_t size) { void **ptr = m_malloc0(size + 2 * sizeof(uintptr_t)); if (MP_STATE_PORT(bluetooth_nimble_memory) != NULL) { MP_STATE_PORT(bluetooth_nimble_memory)[0] = ptr; } ptr[0] = NULL; ptr[1] = MP_STATE_PORT(bluetooth_nimble_memory); MP_STATE_PORT(bluetooth_nimble_memory) = ptr; return &ptr[2]; } void m_free_bluetooth(void *ptr_in) { void **ptr = &((void**)ptr_in)[-2]; if (ptr[1] != NULL) { ((void**)ptr[1])[0] = ptr[0]; } if (ptr[0] != NULL) { ((void**)ptr[0])[1] = ptr[1]; } else { MP_STATE_PORT(bluetooth_nimble_memory) = ptr[1]; } m_free(ptr); } // Check if a nimble ptr is tracked. // If it isn't, that means that it's from a previous soft-reset cycle. STATIC bool is_valid_nimble_malloc(void *ptr) { DEBUG_MALLOC_printf("NIMBLE is_valid_nimble_malloc(%p)\n", ptr); void** search = MP_STATE_PORT(bluetooth_nimble_memory); while (search) { if (&search[2] == ptr) { return true; } search = (void**)search[1]; } return false; } void *nimble_malloc(size_t size) { DEBUG_MALLOC_printf("NIMBLE malloc(%u)\n", (uint)size); void* ptr = m_malloc_bluetooth(size); DEBUG_MALLOC_printf(" --> %p\n", ptr); return ptr; } // Only free if it's still a valid pointer. void nimble_free(void *ptr) { DEBUG_MALLOC_printf("NIMBLE free(%p)\n", ptr); if (ptr && is_valid_nimble_malloc(ptr)) { m_free_bluetooth(ptr); } } // Only realloc if it's still a valid pointer. Otherwise just malloc. void *nimble_realloc(void *ptr, size_t size) { // This is only used by ble_gatts.c to grow the queue of pending services to be registered. DEBUG_MALLOC_printf("NIMBLE realloc(%p, %u)\n", ptr, (uint)size); void *ptr2 = nimble_malloc(size); if (ptr && is_valid_nimble_malloc(ptr)) { // If it's a realloc and we still have the old data, then copy it. // This will happen as we add services. memcpy(ptr2, ptr, size); m_free_bluetooth(ptr); } return ptr2; } /******************************************************************************/ // EVENTQ struct ble_npl_eventq *global_eventq = NULL; void os_eventq_run_all(void) { for (struct ble_npl_eventq *evq = global_eventq; evq != NULL; evq = evq->nextq) { while (evq->head != NULL) { struct ble_npl_event *ev = evq->head; evq->head = ev->next; if (ev->next) { ev->next->prev = NULL; ev->next = NULL; } ev->prev = NULL; DEBUG_EVENT_printf("event_run(%p)\n", ev); ev->fn(ev); DEBUG_EVENT_printf("event_run(%p) done\n", ev); } } } void ble_npl_eventq_init(struct ble_npl_eventq *evq) { DEBUG_EVENT_printf("ble_npl_eventq_init(%p)\n", evq); evq->head = NULL; struct ble_npl_eventq **evq2; for (evq2 = &global_eventq; *evq2 != NULL; evq2 = &(*evq2)->nextq) { } *evq2 = evq; evq->nextq = NULL; } void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) { DEBUG_EVENT_printf("ble_npl_eventq_put(%p, %p (%p, %p))\n", evq, ev, ev->fn, ev->arg); ev->next = NULL; if (evq->head == NULL) { evq->head = ev; ev->prev = NULL; } else { struct ble_npl_event *ev2 = evq->head; while (true) { if (ev2 == ev) { DEBUG_EVENT_printf(" --> already in queue\n"); return; } if (ev2->next == NULL) { break; } DEBUG_EVENT_printf(" --> %p\n", ev2->next); ev2 = ev2->next; } ev2->next = ev; ev->prev = ev2; } } void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void *arg) { DEBUG_EVENT_printf("ble_npl_event_init(%p, %p, %p)\n", ev, fn, arg); ev->fn = fn; ev->arg = arg; ev->next = NULL; } void *ble_npl_event_get_arg(struct ble_npl_event *ev) { DEBUG_EVENT_printf("ble_npl_event_get_arg(%p) -> %p\n", ev, ev->arg); return ev->arg; } void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg) { DEBUG_EVENT_printf("ble_npl_event_set_arg(%p, %p)\n", ev, arg); ev->arg = arg; } /******************************************************************************/ // MUTEX ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu) { DEBUG_MUTEX_printf("ble_npl_mutex_init(%p)\n", mu); mu->locked = 0; return BLE_NPL_OK; } ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) { DEBUG_MUTEX_printf("ble_npl_mutex_pend(%p, %u) locked=%u\n", mu, (uint)timeout, (uint)mu->locked); mu->locked = 1; return BLE_NPL_OK; } ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu) { DEBUG_MUTEX_printf("ble_npl_mutex_release(%p) locked=%u\n", mu, (uint)mu->locked); mu->locked = 0; return BLE_NPL_OK; } /******************************************************************************/ // SEM ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) { DEBUG_SEM_printf("ble_npl_sem_init(%p, %u)\n", sem, (uint)tokens); sem->count = tokens; return BLE_NPL_OK; } ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) { DEBUG_SEM_printf("ble_npl_sem_pend(%p, %u) count=%u\n", sem, (uint)timeout, (uint)sem->count); if (sem->count == 0) { uint32_t t0 = mp_hal_ticks_ms(); while (sem->count == 0 && mp_hal_ticks_ms() - t0 < timeout) { extern void nimble_uart_process(void); nimble_uart_process(); if (sem->count != 0) { break; } __WFI(); } if (sem->count == 0) { printf("timeout\n"); return BLE_NPL_TIMEOUT; } DEBUG_SEM_printf("got response in %u ms\n", (int)(mp_hal_ticks_ms() - t0)); } sem->count -= 1; return BLE_NPL_OK; } ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem) { DEBUG_SEM_printf("ble_npl_sem_release(%p)\n", sem); sem->count += 1; return BLE_NPL_OK; } uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem) { DEBUG_SEM_printf("ble_npl_sem_get_count(%p)\n", sem); return sem->count; } /******************************************************************************/ // CALLOUT static struct ble_npl_callout *global_callout = NULL; void os_callout_process(void) { uint32_t tnow = mp_hal_ticks_ms(); for (struct ble_npl_callout *c = global_callout; c != NULL; c = c->nextc) { if (!c->active) { continue; } if ((int32_t)(tnow - c->ticks) >= 0) { DEBUG_CALLOUT_printf("callout_run(%p) tnow=%u ticks=%u evq=%p\n", c, (uint)tnow, (uint)c->ticks, c->evq); c->active = false; if (c->evq) { ble_npl_eventq_put(c->evq, &c->ev); } else { c->ev.fn(&c->ev); } DEBUG_CALLOUT_printf("callout_run(%p) done\n", c); } } } void ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq, ble_npl_event_fn *ev_cb, void *ev_arg) { DEBUG_CALLOUT_printf("ble_npl_callout_init(%p, %p, %p, %p)\n", c, evq, ev_cb, ev_arg); c->active = false; c->ticks = 0; c->evq = evq; ble_npl_event_init(&c->ev, ev_cb, ev_arg); struct ble_npl_callout **c2; for (c2 = &global_callout; *c2 != NULL; c2 = &(*c2)->nextc) { if (c == *c2) { // callout already in linked list so don't link it in again return; } } *c2 = c; c->nextc = NULL; } ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *c, ble_npl_time_t ticks) { DEBUG_CALLOUT_printf("ble_npl_callout_reset(%p, %u) tnow=%u\n", c, (uint)ticks, (uint)mp_hal_ticks_ms()); c->active = true; c->ticks = ble_npl_time_get() + ticks; return BLE_NPL_OK; } void ble_npl_callout_stop(struct ble_npl_callout *c) { DEBUG_CALLOUT_printf("ble_npl_callout_stop(%p)\n", c); c->active = false; } bool ble_npl_callout_is_active(struct ble_npl_callout *c) { DEBUG_CALLOUT_printf("ble_npl_callout_is_active(%p)\n", c); return c->active; } ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *c) { DEBUG_CALLOUT_printf("ble_npl_callout_get_ticks(%p)\n", c); return c->ticks; } ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *c, ble_npl_time_t now) { DEBUG_CALLOUT_printf("ble_npl_callout_remaining_ticks(%p, %u)\n", c, (uint)now); if (c->ticks > now) { return c->ticks - now; } else { return 0; } } void *ble_npl_callout_get_arg(struct ble_npl_callout *c) { DEBUG_CALLOUT_printf("ble_npl_callout_get_arg(%p)\n", c); return ble_npl_event_get_arg(&c->ev); } void ble_npl_callout_set_arg(struct ble_npl_callout *c, void *arg) { DEBUG_CALLOUT_printf("ble_npl_callout_set_arg(%p, %p)\n", c, arg); ble_npl_event_set_arg(&c->ev, arg); } /******************************************************************************/ // TIME uint32_t ble_npl_time_get(void) { DEBUG_TIME_printf("ble_npl_time_get -> %u\n", (uint)mp_hal_ticks_ms()); return mp_hal_ticks_ms(); } ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) { DEBUG_TIME_printf("ble_npl_time_ms_to_ticks(%u)\n", (uint)ms); *out_ticks = ms; return BLE_NPL_OK; } ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms) { DEBUG_TIME_printf("ble_npl_time_ms_to_ticks32(%u)\n", (uint)ms); return ms; } uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) { DEBUG_TIME_printf("ble_npl_time_ticks_to_ms32(%u)\n", (uint)ticks); return ticks; } void ble_npl_time_delay(ble_npl_time_t ticks) { mp_hal_delay_ms(ticks + 1); } /******************************************************************************/ // CRITICAL uint32_t ble_npl_hw_enter_critical(void) { DEBUG_CRIT_printf("ble_npl_hw_enter_critical()\n"); return raise_irq_pri(15); } void ble_npl_hw_exit_critical(uint32_t ctx) { DEBUG_CRIT_printf("ble_npl_hw_exit_critical(%u)\n", (uint)ctx); restore_irq_pri(ctx); } micropython-1.12/extmod/nimble/syscfg/000077500000000000000000000000001357706137100200665ustar00rootroot00000000000000micropython-1.12/extmod/nimble/syscfg/syscfg.h000066400000000000000000000155011357706137100215370ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H #define MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H #include "py/mphal.h" #include "uart.h" void *nimble_malloc(size_t size); void nimble_free(void *ptr); void *nimble_realloc(void *ptr, size_t size); #define malloc(size) nimble_malloc(size) #define free(ptr) nimble_free(ptr) #define realloc(ptr, size) nimble_realloc(ptr, size) int nimble_sprintf(char *str, const char *fmt, ...); #define sprintf(str, fmt, ...) nimble_sprintf(str, fmt, __VA_ARGS__) #define MYNEWT_VAL(x) MYNEWT_VAL_ ## x #define MYNEWT_VAL_LOG_LEVEL (255) /*** compiler/arm-none-eabi-m4 */ #define MYNEWT_VAL_HARDFLOAT (1) /*** kernel/os */ #define MYNEWT_VAL_FLOAT_USER (0) #define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12) #define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292) #define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0) #define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0) #define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) #define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) #define MYNEWT_VAL_OS_CTX_SW_STACK_CHECK (0) #define MYNEWT_VAL_OS_CTX_SW_STACK_GUARD (4) #define MYNEWT_VAL_OS_MAIN_STACK_SIZE (1024) #define MYNEWT_VAL_OS_MAIN_TASK_PRIO (127) #define MYNEWT_VAL_OS_MEMPOOL_CHECK (0) #define MYNEWT_VAL_OS_MEMPOOL_POISON (0) /*** nimble */ #define MYNEWT_VAL_BLE_EXT_ADV (0) #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) #define MYNEWT_VAL_BLE_MAX_CONNECTIONS (4) #define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0) #define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1) #define MYNEWT_VAL_BLE_ROLE_CENTRAL (1) #define MYNEWT_VAL_BLE_ROLE_OBSERVER (1) #define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1) #define MYNEWT_VAL_BLE_WHITELIST (1) /*** nimble/host */ #define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256) #define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1) #define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1) #define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1) #define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64) #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000) #define MYNEWT_VAL_BLE_ATT_SVR_READ (1) #define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1) #define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1) #define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1) #define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1) #define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1) #define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1) #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_INDICATE (1) #define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4) #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8) #define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000) #define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4) #define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL) #define MYNEWT_VAL_BLE_HOST (1) #define MYNEWT_VAL_BLE_HS_DEBUG (0) #define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0) #define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000) #define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2) #define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0) #define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0) #define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1) #define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (0) #define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1) #define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS) #define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000) #define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1) #define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128) #define MYNEWT_VAL_BLE_MONITOR_RTT (0) #define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1) #define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("monitor") #define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256) #define MYNEWT_VAL_BLE_MONITOR_UART (0) #define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000) #define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64) #define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0") #define MYNEWT_VAL_BLE_RPA_TIMEOUT (300) #define MYNEWT_VAL_BLE_SM_BONDING (0) #define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) #define MYNEWT_VAL_BLE_SM_KEYPRESS (0) #define MYNEWT_VAL_BLE_SM_LEGACY (1) #define MYNEWT_VAL_BLE_SM_MAX_PROCS (1) #define MYNEWT_VAL_BLE_SM_MITM (0) #define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0) #define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) #define MYNEWT_VAL_BLE_SM_SC (1) #define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) #define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3) #define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8) /*** nimble/host/services/gap */ #define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0) #define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1) #define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1) #define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("pybd") #define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH (31) #define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1) #define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0) #define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0) #define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0) #define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0) /* Overridden by targets/porting-nimble (defined by nimble/transport) */ #define MYNEWT_VAL_BLE_HCI_TRANSPORT_NIMBLE_BUILTIN (0) #define MYNEWT_VAL_BLE_HCI_TRANSPORT_RAM (0) #define MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET (0) #define MYNEWT_VAL_BLE_HCI_TRANSPORT_UART (1) /*** nimble/transport/uart */ #define MYNEWT_VAL_BLE_ACL_BUF_COUNT (12) #define MYNEWT_VAL_BLE_ACL_BUF_SIZE (255) #define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (12) #define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE (70) #define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (8) #define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (8) /* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */ #define MYNEWT_VAL_BLE_HCI_UART_BAUD (MICROPY_HW_BLE_UART_BAUDRATE) #define MYNEWT_VAL_BLE_HCI_UART_DATA_BITS (8) #define MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL (1) #define MYNEWT_VAL_BLE_HCI_UART_PARITY (HAL_UART_PARITY_NONE) #define MYNEWT_VAL_BLE_HCI_UART_PORT (MICROPY_HW_BLE_UART_ID) #define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1) #endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H micropython-1.12/extmod/re1.5/000077500000000000000000000000001357706137100161545ustar00rootroot00000000000000micropython-1.12/extmod/re1.5/charclass.c000066400000000000000000000015441357706137100202670ustar00rootroot00000000000000#include "re1.5.h" int _re1_5_classmatch(const char *pc, const char *sp) { // pc points to "cnt" byte after opcode int is_positive = (pc[-1] == Class); int cnt = *pc++; while (cnt--) { if (*sp >= *pc && *sp <= pc[1]) return is_positive; pc += 2; } return !is_positive; } int _re1_5_namedclassmatch(const char *pc, const char *sp) { // pc points to name of class int off = (*pc >> 5) & 1; if ((*pc | 0x20) == 'd') { if (!(*sp >= '0' && *sp <= '9')) { off ^= 1; } } else if ((*pc | 0x20) == 's') { if (!(*sp == ' ' || (*sp >= '\t' && *sp <= '\r'))) { off ^= 1; } } else { // w if (!((*sp >= 'A' && *sp <= 'Z') || (*sp >= 'a' && *sp <= 'z') || (*sp >= '0' && *sp <= '9') || *sp == '_')) { off ^= 1; } } return off; } micropython-1.12/extmod/re1.5/compilecode.c000066400000000000000000000134221357706137100206050ustar00rootroot00000000000000// Copyright 2014 Paul Sokolovsky. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "re1.5.h" #define INSERT_CODE(at, num, pc) \ ((code ? memmove(code + at + num, code + at, pc - at) : 0), pc += num) #define REL(at, to) (to - at - 2) #define EMIT(at, byte) (code ? (code[at] = byte) : (at)) #define PC (prog->bytelen) static const char *_compilecode(const char *re, ByteProg *prog, int sizecode) { char *code = sizecode ? NULL : prog->insts; int start = PC; int term = PC; int alt_label = 0; for (; *re && *re != ')'; re++) { switch (*re) { case '\\': re++; if (!*re) return NULL; // Trailing backslash if ((*re | 0x20) == 'd' || (*re | 0x20) == 's' || (*re | 0x20) == 'w') { term = PC; EMIT(PC++, NamedClass); EMIT(PC++, *re); prog->len++; break; } default: term = PC; EMIT(PC++, Char); EMIT(PC++, *re); prog->len++; break; case '.': term = PC; EMIT(PC++, Any); prog->len++; break; case '[': { int cnt; term = PC; re++; if (*re == '^') { EMIT(PC++, ClassNot); re++; } else { EMIT(PC++, Class); } PC++; // Skip # of pair byte prog->len++; for (cnt = 0; *re != ']'; re++, cnt++) { if (*re == '\\') { ++re; } if (!*re) return NULL; EMIT(PC++, *re); if (re[1] == '-' && re[2] != ']') { re += 2; } EMIT(PC++, *re); } EMIT(term + 1, cnt); break; } case '(': { term = PC; int sub = 0; int capture = re[1] != '?' || re[2] != ':'; if (capture) { sub = ++prog->sub; EMIT(PC++, Save); EMIT(PC++, 2 * sub); prog->len++; } else { re += 2; } re = _compilecode(re + 1, prog, sizecode); if (re == NULL || *re != ')') return NULL; // error, or no matching paren if (capture) { EMIT(PC++, Save); EMIT(PC++, 2 * sub + 1); prog->len++; } break; } case '?': if (PC == term) return NULL; // nothing to repeat INSERT_CODE(term, 2, PC); if (re[1] == '?') { EMIT(term, RSplit); re++; } else { EMIT(term, Split); } EMIT(term + 1, REL(term, PC)); prog->len++; term = PC; break; case '*': if (PC == term) return NULL; // nothing to repeat INSERT_CODE(term, 2, PC); EMIT(PC, Jmp); EMIT(PC + 1, REL(PC, term)); PC += 2; if (re[1] == '?') { EMIT(term, RSplit); re++; } else { EMIT(term, Split); } EMIT(term + 1, REL(term, PC)); prog->len += 2; term = PC; break; case '+': if (PC == term) return NULL; // nothing to repeat if (re[1] == '?') { EMIT(PC, Split); re++; } else { EMIT(PC, RSplit); } EMIT(PC + 1, REL(PC, term)); PC += 2; prog->len++; term = PC; break; case '|': if (alt_label) { EMIT(alt_label, REL(alt_label, PC) + 1); } INSERT_CODE(start, 2, PC); EMIT(PC++, Jmp); alt_label = PC++; EMIT(start, Split); EMIT(start + 1, REL(start, PC)); prog->len += 2; term = PC; break; case '^': EMIT(PC++, Bol); prog->len++; term = PC; break; case '$': EMIT(PC++, Eol); prog->len++; term = PC; break; } } if (alt_label) { EMIT(alt_label, REL(alt_label, PC) + 1); } return re; } int re1_5_sizecode(const char *re) { ByteProg dummyprog = { // Save 0, Save 1, Match; more bytes for "search" (vs "match") prefix code .bytelen = 5 + NON_ANCHORED_PREFIX }; if (_compilecode(re, &dummyprog, /*sizecode*/1) == NULL) return -1; return dummyprog.bytelen; } int re1_5_compilecode(ByteProg *prog, const char *re) { prog->len = 0; prog->bytelen = 0; prog->sub = 0; // Add code to implement non-anchored operation ("search"), // for anchored operation ("match"), this code will be just skipped. // TODO: Implement search in much more efficient manner prog->insts[prog->bytelen++] = RSplit; prog->insts[prog->bytelen++] = 3; prog->insts[prog->bytelen++] = Any; prog->insts[prog->bytelen++] = Jmp; prog->insts[prog->bytelen++] = -5; prog->len += 3; prog->insts[prog->bytelen++] = Save; prog->insts[prog->bytelen++] = 0; prog->len++; re = _compilecode(re, prog, /*sizecode*/0); if (re == NULL || *re) return 1; prog->insts[prog->bytelen++] = Save; prog->insts[prog->bytelen++] = 1; prog->len++; prog->insts[prog->bytelen++] = Match; prog->len++; return 0; } #if 0 int main(int argc, char *argv[]) { int pc = 0; ByteProg *code = re1_5_compilecode(argv[1]); re1_5_dumpcode(code); } #endif micropython-1.12/extmod/re1.5/dumpcode.c000066400000000000000000000045551357706137100201310ustar00rootroot00000000000000// Copyright 2014 Paul Sokolovsky. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "re1.5.h" void re1_5_dumpcode(ByteProg *prog) { int pc = 0; char *code = prog->insts; while (pc < prog->bytelen) { printf("%2d: ", pc); switch(code[pc++]) { default: assert(0); // re1_5_fatal("printprog"); case Split: printf("split %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]); pc++; break; case RSplit: printf("rsplit %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]); pc++; break; case Jmp: printf("jmp %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]); pc++; break; case Char: printf("char %c\n", code[pc++]); break; case Any: printf("any\n"); break; case Class: case ClassNot: { int num = code[pc]; printf("class%s %d", (code[pc - 1] == ClassNot ? "not" : ""), num); pc++; while (num--) { printf(" 0x%02x-0x%02x", code[pc], code[pc + 1]); pc += 2; } printf("\n"); break; } case NamedClass: printf("namedclass %c\n", code[pc++]); break; case Match: printf("match\n"); break; case Save: printf("save %d\n", (unsigned char)code[pc++]); break; case Bol: printf("assert bol\n"); break; case Eol: printf("assert eol\n"); break; } } printf("Bytes: %d, insts: %d\n", prog->bytelen, prog->len); } micropython-1.12/extmod/re1.5/re1.5.h000066400000000000000000000053371357706137100171670ustar00rootroot00000000000000// Copyright 2007-2009 Russ Cox. All Rights Reserved. // Copyright 2014 Paul Sokolovsky. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #ifndef _RE1_5_REGEXP__H #define _RE1_5_REGEXP__H #include #include #include #include #include #define nil ((void*)0) #define nelem(x) (sizeof(x)/sizeof((x)[0])) typedef struct Regexp Regexp; typedef struct Prog Prog; typedef struct ByteProg ByteProg; typedef struct Inst Inst; typedef struct Subject Subject; struct Regexp { int type; int n; int ch; Regexp *left; Regexp *right; }; enum /* Regexp.type */ { Alt = 1, Cat, Lit, Dot, Paren, Quest, Star, Plus, }; Regexp *parse(char*); Regexp *reg(int type, Regexp *left, Regexp *right); void printre(Regexp*); #ifndef re1_5_fatal void re1_5_fatal(char*); #endif #ifndef re1_5_stack_chk #define re1_5_stack_chk() #endif void *mal(int); struct Prog { Inst *start; int len; }; struct ByteProg { int bytelen; int len; int sub; char insts[0]; }; struct Inst { int opcode; int c; int n; Inst *x; Inst *y; int gen; // global state, oooh! }; enum /* Inst.opcode */ { // Instructions which consume input bytes (and thus fail if none left) CONSUMERS = 1, Char = CONSUMERS, Any, Class, ClassNot, NamedClass, ASSERTS = 0x50, Bol = ASSERTS, Eol, // Instructions which take relative offset as arg JUMPS = 0x60, Jmp = JUMPS, Split, RSplit, // Other (special) instructions Save = 0x7e, Match = 0x7f, }; #define inst_is_consumer(inst) ((inst) < ASSERTS) #define inst_is_jump(inst) ((inst) & 0x70 == JUMPS) Prog *compile(Regexp*); void printprog(Prog*); extern int gen; enum { MAXSUB = 20 }; typedef struct Sub Sub; struct Sub { int ref; int nsub; const char *sub[MAXSUB]; }; Sub *newsub(int n); Sub *incref(Sub*); Sub *copy(Sub*); Sub *update(Sub*, int, const char*); void decref(Sub*); struct Subject { const char *begin; const char *end; }; #define NON_ANCHORED_PREFIX 5 #define HANDLE_ANCHORED(bytecode, is_anchored) ((is_anchored) ? (bytecode) + NON_ANCHORED_PREFIX : (bytecode)) int re1_5_backtrack(ByteProg*, Subject*, const char**, int, int); int re1_5_pikevm(ByteProg*, Subject*, const char**, int, int); int re1_5_recursiveloopprog(ByteProg*, Subject*, const char**, int, int); int re1_5_recursiveprog(ByteProg*, Subject*, const char**, int, int); int re1_5_thompsonvm(ByteProg*, Subject*, const char**, int, int); int re1_5_sizecode(const char *re); int re1_5_compilecode(ByteProg *prog, const char *re); void re1_5_dumpcode(ByteProg *prog); void cleanmarks(ByteProg *prog); int _re1_5_classmatch(const char *pc, const char *sp); int _re1_5_namedclassmatch(const char *pc, const char *sp); #endif /*_RE1_5_REGEXP__H*/ micropython-1.12/extmod/re1.5/recursiveloop.c000066400000000000000000000034141357706137100212230ustar00rootroot00000000000000// Copyright 2007-2009 Russ Cox. All Rights Reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "re1.5.h" static int recursiveloop(char *pc, const char *sp, Subject *input, const char **subp, int nsubp) { const char *old; int off; re1_5_stack_chk(); for(;;) { if(inst_is_consumer(*pc)) { // If we need to match a character, but there's none left, it's fail if(sp >= input->end) return 0; } switch(*pc++) { case Char: if(*sp != *pc++) return 0; case Any: sp++; continue; case Class: case ClassNot: if (!_re1_5_classmatch(pc, sp)) return 0; pc += *(unsigned char*)pc * 2 + 1; sp++; continue; case NamedClass: if (!_re1_5_namedclassmatch(pc, sp)) return 0; pc++; sp++; continue; case Match: return 1; case Jmp: off = (signed char)*pc++; pc = pc + off; continue; case Split: off = (signed char)*pc++; if(recursiveloop(pc, sp, input, subp, nsubp)) return 1; pc = pc + off; continue; case RSplit: off = (signed char)*pc++; if(recursiveloop(pc + off, sp, input, subp, nsubp)) return 1; continue; case Save: off = (unsigned char)*pc++; if(off >= nsubp) { continue; } old = subp[off]; subp[off] = sp; if(recursiveloop(pc, sp, input, subp, nsubp)) return 1; subp[off] = old; return 0; case Bol: if(sp != input->begin) return 0; continue; case Eol: if(sp != input->end) return 0; continue; } re1_5_fatal("recursiveloop"); } } int re1_5_recursiveloopprog(ByteProg *prog, Subject *input, const char **subp, int nsubp, int is_anchored) { return recursiveloop(HANDLE_ANCHORED(prog->insts, is_anchored), input->begin, input, subp, nsubp); } micropython-1.12/extmod/uos_dupterm.c000066400000000000000000000152631357706137100200430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * Copyright (c) 2017-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpconfig.h" #include "py/runtime.h" #include "py/objtuple.h" #include "py/objarray.h" #include "py/stream.h" #include "extmod/misc.h" #include "lib/utils/interrupt_char.h" #if MICROPY_PY_OS_DUPTERM void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) { mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]); MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL; mp_printf(&mp_plat_print, msg); if (exc != MP_OBJ_NULL) { mp_obj_print_exception(&mp_plat_print, exc); } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_stream_close(term); nlr_pop(); } else { // Ignore any errors during stream closing } } uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags) { uintptr_t poll_flags_out = 0; for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) { mp_obj_t s = MP_STATE_VM(dupterm_objs[idx]); if (s == MP_OBJ_NULL) { continue; } int errcode = 0; mp_uint_t ret = 0; const mp_stream_p_t *stream_p = mp_get_stream(s); #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM if (mp_uos_dupterm_is_builtin_stream(s)) { ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode); } else #endif { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode); nlr_pop(); } else { // Ignore error with ioctl } } if (ret != MP_STREAM_ERROR) { poll_flags_out |= ret; if (poll_flags_out == poll_flags) { // Finish early if all requested flags are set break; } } } return poll_flags_out; } int mp_uos_dupterm_rx_chr(void) { for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) { if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) { continue; } #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM if (mp_uos_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) { byte buf[1]; int errcode = 0; const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx])); mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode); if (errcode == 0 && out_sz != 0) { return buf[0]; } else { continue; } } #endif nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { byte buf[1]; int errcode; const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx])); mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode); if (out_sz == 0) { nlr_pop(); mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL); } else if (out_sz == MP_STREAM_ERROR) { // errcode is valid if (mp_is_nonblocking_error(errcode)) { nlr_pop(); } else { mp_raise_OSError(errcode); } } else { // read 1 byte nlr_pop(); if (buf[0] == mp_interrupt_char) { // Signal keyboard interrupt to be raised as soon as the VM resumes mp_keyboard_interrupt(); return -2; } return buf[0]; } } else { mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val)); } } // No chars available return -1; } void mp_uos_dupterm_tx_strn(const char *str, size_t len) { for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) { if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) { continue; } #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM if (mp_uos_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) { int errcode = 0; const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx])); stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode); continue; } #endif nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE); nlr_pop(); } else { mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val)); } } } STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) { mp_int_t idx = 0; if (n_args == 2) { idx = mp_obj_get_int(args[1]); } if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) { mp_raise_ValueError("invalid dupterm index"); } mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]); if (previous_obj == MP_OBJ_NULL) { previous_obj = mp_const_none; } if (args[0] == mp_const_none) { MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL; } else { mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); MP_STATE_VM(dupterm_objs[idx]) = args[0]; } return previous_obj; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm); #endif micropython-1.12/extmod/utime_mphal.c000066400000000000000000000075301357706137100177770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_UTIME_MP_HAL #include #include "py/obj.h" #include "py/mphal.h" #include "py/smallint.h" #include "py/runtime.h" #include "extmod/utime_mphal.h" STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { #if MICROPY_PY_BUILTINS_FLOAT mp_hal_delay_ms((mp_uint_t)(1000 * mp_obj_get_float(seconds_o))); #else mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o)); #endif return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep); STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) { mp_int_t ms = mp_obj_get_int(arg); if (ms > 0) { mp_hal_delay_ms(ms); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms); STATIC mp_obj_t time_sleep_us(mp_obj_t arg) { mp_int_t us = mp_obj_get_int(arg); if (us > 0) { mp_hal_delay_us(us); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj, time_sleep_us); STATIC mp_obj_t time_ticks_ms(void) { return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj, time_ticks_ms); STATIC mp_obj_t time_ticks_us(void) { return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj, time_ticks_us); STATIC mp_obj_t time_ticks_cpu(void) { return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj, time_ticks_cpu); STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) { // we assume that the arguments come from ticks_xx so are small ints mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in); mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in); // Optimized formula avoiding if conditions. We adjust difference "forward", // wrap it around and adjust back. mp_int_t diff = ((end - start + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)) - MICROPY_PY_UTIME_TICKS_PERIOD / 2; return MP_OBJ_NEW_SMALL_INT(diff); } MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff); STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) { // we assume that first argument come from ticks_xx so is small int mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in); mp_uint_t delta = mp_obj_get_int(delta_in); return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add); #endif // MICROPY_PY_UTIME_MP_HAL micropython-1.12/extmod/utime_mphal.h000066400000000000000000000034601357706137100200020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H #define MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H #include "py/obj.h" MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj); #endif // MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H micropython-1.12/extmod/uzlib/000077500000000000000000000000001357706137100164475ustar00rootroot00000000000000micropython-1.12/extmod/uzlib/adler32.c000066400000000000000000000043031357706137100200470ustar00rootroot00000000000000/* * Adler-32 checksum * * Copyright (c) 2003 by Joergen Ibsen / Jibz * All Rights Reserved * * http://www.ibsensoftware.com/ * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be * held liable for any damages arising from the use of * this software. * * Permission is granted to anyone to use this software * for any purpose, including commercial applications, * and to alter it and redistribute it freely, subject to * the following restrictions: * * 1. The origin of this software must not be * misrepresented; you must not claim that you * wrote the original software. If you use this * software in a product, an acknowledgment in * the product documentation would be appreciated * but is not required. * * 2. Altered source versions must be plainly marked * as such, and must not be misrepresented as * being the original software. * * 3. This notice may not be removed or altered from * any source distribution. */ /* * Adler-32 algorithm taken from the zlib source, which is * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler */ #include "tinf.h" #define A32_BASE 65521 #define A32_NMAX 5552 uint32_t uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum /* 1 */) { const unsigned char *buf = (const unsigned char *)data; unsigned int s1 = prev_sum & 0xffff; unsigned int s2 = prev_sum >> 16; while (length > 0) { int k = length < A32_NMAX ? length : A32_NMAX; int i; for (i = k / 16; i; --i, buf += 16) { s1 += buf[0]; s2 += s1; s1 += buf[1]; s2 += s1; s1 += buf[2]; s2 += s1; s1 += buf[3]; s2 += s1; s1 += buf[4]; s2 += s1; s1 += buf[5]; s2 += s1; s1 += buf[6]; s2 += s1; s1 += buf[7]; s2 += s1; s1 += buf[8]; s2 += s1; s1 += buf[9]; s2 += s1; s1 += buf[10]; s2 += s1; s1 += buf[11]; s2 += s1; s1 += buf[12]; s2 += s1; s1 += buf[13]; s2 += s1; s1 += buf[14]; s2 += s1; s1 += buf[15]; s2 += s1; } for (i = k % 16; i; --i) { s1 += *buf++; s2 += s1; } s1 %= A32_BASE; s2 %= A32_BASE; length -= k; } return (s2 << 16) | s1; } micropython-1.12/extmod/uzlib/crc32.c000066400000000000000000000036401357706137100175320ustar00rootroot00000000000000/* * CRC32 checksum * * Copyright (c) 1998-2003 by Joergen Ibsen / Jibz * All Rights Reserved * * http://www.ibsensoftware.com/ * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be * held liable for any damages arising from the use of * this software. * * Permission is granted to anyone to use this software * for any purpose, including commercial applications, * and to alter it and redistribute it freely, subject to * the following restrictions: * * 1. The origin of this software must not be * misrepresented; you must not claim that you * wrote the original software. If you use this * software in a product, an acknowledgment in * the product documentation would be appreciated * but is not required. * * 2. Altered source versions must be plainly marked * as such, and must not be misrepresented as * being the original software. * * 3. This notice may not be removed or altered from * any source distribution. */ /* * CRC32 algorithm taken from the zlib source, which is * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler */ #include "tinf.h" static const unsigned int tinf_crc32tab[16] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; /* crc is previous value for incremental computation, 0xffffffff initially */ uint32_t uzlib_crc32(const void *data, unsigned int length, uint32_t crc) { const unsigned char *buf = (const unsigned char *)data; unsigned int i; for (i = 0; i < length; ++i) { crc ^= buf[i]; crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); } // return value suitable for passing in next time, for final value invert it return crc/* ^ 0xffffffff*/; } micropython-1.12/extmod/uzlib/defl_static.h000066400000000000000000000027451357706137100211110ustar00rootroot00000000000000/* * Copyright (c) uzlib authors * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be * held liable for any damages arising from the use of * this software. * * Permission is granted to anyone to use this software * for any purpose, including commercial applications, * and to alter it and redistribute it freely, subject to * the following restrictions: * * 1. The origin of this software must not be * misrepresented; you must not claim that you * wrote the original software. If you use this * software in a product, an acknowledgment in * the product documentation would be appreciated * but is not required. * * 2. Altered source versions must be plainly marked * as such, and must not be misrepresented as * being the original software. * * 3. This notice may not be removed or altered from * any source distribution. */ /* This files contains type declaration and prototypes for defl_static.c. They may be altered/distinct from the originals used in PuTTY source code. */ struct Outbuf { unsigned char *outbuf; int outlen, outsize; unsigned long outbits; int noutbits; int comp_disabled; }; void outbits(struct Outbuf *out, unsigned long bits, int nbits); void zlib_start_block(struct Outbuf *ctx); void zlib_finish_block(struct Outbuf *ctx); void zlib_literal(struct Outbuf *ectx, unsigned char c); void zlib_match(struct Outbuf *ectx, int distance, int len); micropython-1.12/extmod/uzlib/tinf.h000066400000000000000000000002431357706137100175570ustar00rootroot00000000000000/* Compatibility header for the original tinf lib/older versions of uzlib. Note: may be removed in the future, please migrate to uzlib.h. */ #include "uzlib.h" micropython-1.12/extmod/uzlib/tinf_compat.h000066400000000000000000000005471357706137100211310ustar00rootroot00000000000000/* This header contains compatibility defines for the original tinf API and uzlib 2.x and below API. These defines are deprecated and going to be removed in the future, so applications should migrate to new uzlib API. */ #define TINF_DATA struct uzlib_uncomp #define destSize dest_size #define destStart dest_start #define readSource source_read_cb micropython-1.12/extmod/uzlib/tinfgzip.c000066400000000000000000000054211357706137100204470ustar00rootroot00000000000000/* * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) * * Copyright (c) 2003 by Joergen Ibsen / Jibz * All Rights Reserved * * http://www.ibsensoftware.com/ * * Copyright (c) 2014-2018 by Paul Sokolovsky * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be * held liable for any damages arising from the use of * this software. * * Permission is granted to anyone to use this software * for any purpose, including commercial applications, * and to alter it and redistribute it freely, subject to * the following restrictions: * * 1. The origin of this software must not be * misrepresented; you must not claim that you * wrote the original software. If you use this * software in a product, an acknowledgment in * the product documentation would be appreciated * but is not required. * * 2. Altered source versions must be plainly marked * as such, and must not be misrepresented as * being the original software. * * 3. This notice may not be removed or altered from * any source distribution. */ #include "tinf.h" #define FTEXT 1 #define FHCRC 2 #define FEXTRA 4 #define FNAME 8 #define FCOMMENT 16 void tinf_skip_bytes(TINF_DATA *d, int num); uint16_t tinf_get_uint16(TINF_DATA *d); void tinf_skip_bytes(TINF_DATA *d, int num) { while (num--) uzlib_get_byte(d); } uint16_t tinf_get_uint16(TINF_DATA *d) { unsigned int v = uzlib_get_byte(d); v = (uzlib_get_byte(d) << 8) | v; return v; } int uzlib_gzip_parse_header(TINF_DATA *d) { unsigned char flg; /* -- check format -- */ /* check id bytes */ if (uzlib_get_byte(d) != 0x1f || uzlib_get_byte(d) != 0x8b) return TINF_DATA_ERROR; /* check method is deflate */ if (uzlib_get_byte(d) != 8) return TINF_DATA_ERROR; /* get flag byte */ flg = uzlib_get_byte(d); /* check that reserved bits are zero */ if (flg & 0xe0) return TINF_DATA_ERROR; /* -- find start of compressed data -- */ /* skip rest of base header of 10 bytes */ tinf_skip_bytes(d, 6); /* skip extra data if present */ if (flg & FEXTRA) { unsigned int xlen = tinf_get_uint16(d); tinf_skip_bytes(d, xlen); } /* skip file name if present */ if (flg & FNAME) { while (uzlib_get_byte(d)); } /* skip file comment if present */ if (flg & FCOMMENT) { while (uzlib_get_byte(d)); } /* check header crc if present */ if (flg & FHCRC) { /*unsigned int hcrc =*/ tinf_get_uint16(d); // TODO: Check! // if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff)) // return TINF_DATA_ERROR; } /* initialize for crc32 checksum */ d->checksum_type = TINF_CHKSUM_CRC; d->checksum = ~0; return TINF_OK; } micropython-1.12/extmod/uzlib/tinflate.c000066400000000000000000000420171357706137100204250ustar00rootroot00000000000000/* * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) * * Copyright (c) 2003 by Joergen Ibsen / Jibz * All Rights Reserved * http://www.ibsensoftware.com/ * * Copyright (c) 2014-2018 by Paul Sokolovsky * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be * held liable for any damages arising from the use of * this software. * * Permission is granted to anyone to use this software * for any purpose, including commercial applications, * and to alter it and redistribute it freely, subject to * the following restrictions: * * 1. The origin of this software must not be * misrepresented; you must not claim that you * wrote the original software. If you use this * software in a product, an acknowledgment in * the product documentation would be appreciated * but is not required. * * 2. Altered source versions must be plainly marked * as such, and must not be misrepresented as * being the original software. * * 3. This notice may not be removed or altered from * any source distribution. */ #include #include "tinf.h" #define UZLIB_DUMP_ARRAY(heading, arr, size) \ { \ printf("%s", heading); \ for (int i = 0; i < size; ++i) { \ printf(" %d", (arr)[i]); \ } \ printf("\n"); \ } uint32_t tinf_get_le_uint32(TINF_DATA *d); uint32_t tinf_get_be_uint32(TINF_DATA *d); /* --------------------------------------------------- * * -- uninitialized global data (static structures) -- * * --------------------------------------------------- */ #ifdef RUNTIME_BITS_TABLES /* extra bits and base tables for length codes */ unsigned char length_bits[30]; unsigned short length_base[30]; /* extra bits and base tables for distance codes */ unsigned char dist_bits[30]; unsigned short dist_base[30]; #else const unsigned char length_bits[30] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 }; const unsigned short length_base[30] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 }; const unsigned char dist_bits[30] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 }; const unsigned short dist_base[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }; #endif /* special ordering of code length codes */ const unsigned char clcidx[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; /* ----------------------- * * -- utility functions -- * * ----------------------- */ #ifdef RUNTIME_BITS_TABLES /* build extra bits and base tables */ static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first) { int i, sum; /* build bits table */ for (i = 0; i < delta; ++i) bits[i] = 0; for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta; /* build base table */ for (sum = first, i = 0; i < 30; ++i) { base[i] = sum; sum += 1 << bits[i]; } } #endif /* build the fixed huffman trees */ static void tinf_build_fixed_trees(TINF_TREE *lt, TINF_TREE *dt) { int i; /* build fixed length tree */ for (i = 0; i < 7; ++i) lt->table[i] = 0; lt->table[7] = 24; lt->table[8] = 152; lt->table[9] = 112; for (i = 0; i < 24; ++i) lt->trans[i] = 256 + i; for (i = 0; i < 144; ++i) lt->trans[24 + i] = i; for (i = 0; i < 8; ++i) lt->trans[24 + 144 + i] = 280 + i; for (i = 0; i < 112; ++i) lt->trans[24 + 144 + 8 + i] = 144 + i; /* build fixed distance tree */ for (i = 0; i < 5; ++i) dt->table[i] = 0; dt->table[5] = 32; for (i = 0; i < 32; ++i) dt->trans[i] = i; } /* given an array of code lengths, build a tree */ static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned int num) { unsigned short offs[16]; unsigned int i, sum; /* clear code length count table */ for (i = 0; i < 16; ++i) t->table[i] = 0; /* scan symbol lengths, and sum code length counts */ for (i = 0; i < num; ++i) t->table[lengths[i]]++; #if UZLIB_CONF_DEBUG_LOG >= 2 UZLIB_DUMP_ARRAY("codelen counts:", t->table, TINF_ARRAY_SIZE(t->table)); #endif /* In the lengths array, 0 means unused code. So, t->table[0] now contains number of unused codes. But table's purpose is to contain # of codes of particular length, and there're 0 codes of length 0. */ t->table[0] = 0; /* compute offset table for distribution sort */ for (sum = 0, i = 0; i < 16; ++i) { offs[i] = sum; sum += t->table[i]; } #if UZLIB_CONF_DEBUG_LOG >= 2 UZLIB_DUMP_ARRAY("codelen offsets:", offs, TINF_ARRAY_SIZE(offs)); #endif /* create code->symbol translation table (symbols sorted by code) */ for (i = 0; i < num; ++i) { if (lengths[i]) t->trans[offs[lengths[i]]++] = i; } } /* ---------------------- * * -- decode functions -- * * ---------------------- */ unsigned char uzlib_get_byte(TINF_DATA *d) { /* If end of source buffer is not reached, return next byte from source buffer. */ if (d->source < d->source_limit) { return *d->source++; } /* Otherwise if there's callback and we haven't seen EOF yet, try to read next byte using it. (Note: the callback can also update ->source and ->source_limit). */ if (d->readSource && !d->eof) { int val = d->readSource(d); if (val >= 0) { return (unsigned char)val; } } /* Otherwise, we hit EOF (either from ->readSource() or from exhaustion of the buffer), and it will be "sticky", i.e. further calls to this function will end up here too. */ d->eof = true; return 0; } uint32_t tinf_get_le_uint32(TINF_DATA *d) { uint32_t val = 0; int i; for (i = 4; i--;) { val = val >> 8 | ((uint32_t)uzlib_get_byte(d)) << 24; } return val; } uint32_t tinf_get_be_uint32(TINF_DATA *d) { uint32_t val = 0; int i; for (i = 4; i--;) { val = val << 8 | uzlib_get_byte(d); } return val; } /* get one bit from source stream */ static int tinf_getbit(TINF_DATA *d) { unsigned int bit; /* check if tag is empty */ if (!d->bitcount--) { /* load next tag */ d->tag = uzlib_get_byte(d); d->bitcount = 7; } /* shift bit out of tag */ bit = d->tag & 0x01; d->tag >>= 1; return bit; } /* read a num bit value from a stream and add base */ static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base) { unsigned int val = 0; /* read num bits */ if (num) { unsigned int limit = 1 << (num); unsigned int mask; for (mask = 1; mask < limit; mask *= 2) if (tinf_getbit(d)) val += mask; } return val + base; } /* given a data stream and a tree, decode a symbol */ static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t) { int sum = 0, cur = 0, len = 0; /* get more bits while code value is above sum */ do { cur = 2*cur + tinf_getbit(d); if (++len == TINF_ARRAY_SIZE(t->table)) { return TINF_DATA_ERROR; } sum += t->table[len]; cur -= t->table[len]; } while (cur >= 0); sum += cur; #if UZLIB_CONF_PARANOID_CHECKS if (sum < 0 || sum >= TINF_ARRAY_SIZE(t->trans)) { return TINF_DATA_ERROR; } #endif return t->trans[sum]; } /* given a data stream, decode dynamic trees from it */ static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) { /* code lengths for 288 literal/len symbols and 32 dist symbols */ unsigned char lengths[288+32]; unsigned int hlit, hdist, hclen, hlimit; unsigned int i, num, length; /* get 5 bits HLIT (257-286) */ hlit = tinf_read_bits(d, 5, 257); /* get 5 bits HDIST (1-32) */ hdist = tinf_read_bits(d, 5, 1); /* get 4 bits HCLEN (4-19) */ hclen = tinf_read_bits(d, 4, 4); for (i = 0; i < 19; ++i) lengths[i] = 0; /* read code lengths for code length alphabet */ for (i = 0; i < hclen; ++i) { /* get 3 bits code length (0-7) */ unsigned int clen = tinf_read_bits(d, 3, 0); lengths[clcidx[i]] = clen; } /* build code length tree, temporarily use length tree */ tinf_build_tree(lt, lengths, 19); /* decode code lengths for the dynamic trees */ hlimit = hlit + hdist; for (num = 0; num < hlimit; ) { int sym = tinf_decode_symbol(d, lt); unsigned char fill_value = 0; int lbits, lbase = 3; /* error decoding */ if (sym < 0) return sym; switch (sym) { case 16: /* copy previous code length 3-6 times (read 2 bits) */ if (num == 0) return TINF_DATA_ERROR; fill_value = lengths[num - 1]; lbits = 2; break; case 17: /* repeat code length 0 for 3-10 times (read 3 bits) */ lbits = 3; break; case 18: /* repeat code length 0 for 11-138 times (read 7 bits) */ lbits = 7; lbase = 11; break; default: /* values 0-15 represent the actual code lengths */ lengths[num++] = sym; /* continue the for loop */ continue; } /* special code length 16-18 are handled here */ length = tinf_read_bits(d, lbits, lbase); if (num + length > hlimit) return TINF_DATA_ERROR; for (; length; --length) { lengths[num++] = fill_value; } } #if UZLIB_CONF_DEBUG_LOG >= 2 printf("lit code lengths (%d):", hlit); UZLIB_DUMP_ARRAY("", lengths, hlit); printf("dist code lengths (%d):", hdist); UZLIB_DUMP_ARRAY("", lengths + hlit, hdist); #endif #if UZLIB_CONF_PARANOID_CHECKS /* Check that there's "end of block" symbol */ if (lengths[256] == 0) { return TINF_DATA_ERROR; } #endif /* build dynamic trees */ tinf_build_tree(lt, lengths, hlit); tinf_build_tree(dt, lengths + hlit, hdist); return TINF_OK; } /* ----------------------------- * * -- block inflate functions -- * * ----------------------------- */ /* given a stream and two trees, inflate next byte of output */ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) { if (d->curlen == 0) { unsigned int offs; int dist; int sym = tinf_decode_symbol(d, lt); //printf("huff sym: %02x\n", sym); if (d->eof) { return TINF_DATA_ERROR; } /* literal byte */ if (sym < 256) { TINF_PUT(d, sym); return TINF_OK; } /* end of block */ if (sym == 256) { return TINF_DONE; } /* substring from sliding dictionary */ sym -= 257; if (sym >= 29) { return TINF_DATA_ERROR; } /* possibly get more bits from length code */ d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]); dist = tinf_decode_symbol(d, dt); if (dist >= 30) { return TINF_DATA_ERROR; } /* possibly get more bits from distance code */ offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]); /* calculate and validate actual LZ offset to use */ if (d->dict_ring) { if (offs > d->dict_size) { return TINF_DICT_ERROR; } /* Note: unlike full-dest-in-memory case below, we don't try to catch offset which points to not yet filled part of the dictionary here. Doing so would require keeping another variable to track "filled in" size of the dictionary. Appearance of such an offset cannot lead to accessing memory outside of the dictionary buffer, and clients which don't want to leak unrelated information, should explicitly initialize dictionary buffer passed to uzlib. */ d->lzOff = d->dict_idx - offs; if (d->lzOff < 0) { d->lzOff += d->dict_size; } } else { /* catch trying to point before the start of dest buffer */ if (offs > d->dest - d->destStart) { return TINF_DATA_ERROR; } d->lzOff = -offs; } } /* copy next byte from dict substring */ if (d->dict_ring) { TINF_PUT(d, d->dict_ring[d->lzOff]); if ((unsigned)++d->lzOff == d->dict_size) { d->lzOff = 0; } } else { d->dest[0] = d->dest[d->lzOff]; d->dest++; } d->curlen--; return TINF_OK; } /* inflate next byte from uncompressed block of data */ static int tinf_inflate_uncompressed_block(TINF_DATA *d) { if (d->curlen == 0) { unsigned int length, invlength; /* get length */ length = uzlib_get_byte(d); length += 256 * uzlib_get_byte(d); /* get one's complement of length */ invlength = uzlib_get_byte(d); invlength += 256 * uzlib_get_byte(d); /* check length */ if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR; /* increment length to properly return TINF_DONE below, without producing data at the same time */ d->curlen = length + 1; /* make sure we start next block on a byte boundary */ d->bitcount = 0; } if (--d->curlen == 0) { return TINF_DONE; } unsigned char c = uzlib_get_byte(d); TINF_PUT(d, c); return TINF_OK; } /* ---------------------- * * -- public functions -- * * ---------------------- */ /* initialize global (static) data */ void uzlib_init(void) { #ifdef RUNTIME_BITS_TABLES /* build extra bits and base tables */ tinf_build_bits_base(length_bits, length_base, 4, 3); tinf_build_bits_base(dist_bits, dist_base, 2, 1); /* fix a special case */ length_bits[28] = 0; length_base[28] = 258; #endif } /* initialize decompression structure */ void uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen) { d->eof = 0; d->bitcount = 0; d->bfinal = 0; d->btype = -1; d->dict_size = dictLen; d->dict_ring = dict; d->dict_idx = 0; d->curlen = 0; } /* inflate next output bytes from compressed stream */ int uzlib_uncompress(TINF_DATA *d) { do { int res; /* start a new block */ if (d->btype == -1) { next_blk: /* read final block flag */ d->bfinal = tinf_getbit(d); /* read block type (2 bits) */ d->btype = tinf_read_bits(d, 2, 0); #if UZLIB_CONF_DEBUG_LOG >= 1 printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal); #endif if (d->btype == 1) { /* build fixed huffman trees */ tinf_build_fixed_trees(&d->ltree, &d->dtree); } else if (d->btype == 2) { /* decode trees from stream */ res = tinf_decode_trees(d, &d->ltree, &d->dtree); if (res != TINF_OK) { return res; } } } /* process current block */ switch (d->btype) { case 0: /* decompress uncompressed block */ res = tinf_inflate_uncompressed_block(d); break; case 1: case 2: /* decompress block with fixed/dynamic huffman trees */ /* trees were decoded previously, so it's the same routine for both */ res = tinf_inflate_block_data(d, &d->ltree, &d->dtree); break; default: return TINF_DATA_ERROR; } if (res == TINF_DONE && !d->bfinal) { /* the block has ended (without producing more data), but we can't return without data, so start procesing next block */ goto next_blk; } if (res != TINF_OK) { return res; } } while (d->dest < d->dest_limit); return TINF_OK; } /* inflate next output bytes from compressed stream, updating checksum, and at the end of stream, verify it */ int uzlib_uncompress_chksum(TINF_DATA *d) { int res; unsigned char *data = d->dest; res = uzlib_uncompress(d); if (res < 0) return res; switch (d->checksum_type) { case TINF_CHKSUM_ADLER: d->checksum = uzlib_adler32(data, d->dest - data, d->checksum); break; case TINF_CHKSUM_CRC: d->checksum = uzlib_crc32(data, d->dest - data, d->checksum); break; } if (res == TINF_DONE) { unsigned int val; switch (d->checksum_type) { case TINF_CHKSUM_ADLER: val = tinf_get_be_uint32(d); if (d->checksum != val) { return TINF_CHKSUM_ERROR; } break; case TINF_CHKSUM_CRC: val = tinf_get_le_uint32(d); if (~d->checksum != val) { return TINF_CHKSUM_ERROR; } // Uncompressed size. TODO: Check val = tinf_get_le_uint32(d); break; } } return res; } micropython-1.12/extmod/uzlib/tinfzlib.c000066400000000000000000000034101357706137100204320ustar00rootroot00000000000000/* * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) * * Copyright (c) 2003 by Joergen Ibsen / Jibz * All Rights Reserved * * http://www.ibsensoftware.com/ * * Copyright (c) 2014-2018 by Paul Sokolovsky * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be * held liable for any damages arising from the use of * this software. * * Permission is granted to anyone to use this software * for any purpose, including commercial applications, * and to alter it and redistribute it freely, subject to * the following restrictions: * * 1. The origin of this software must not be * misrepresented; you must not claim that you * wrote the original software. If you use this * software in a product, an acknowledgment in * the product documentation would be appreciated * but is not required. * * 2. Altered source versions must be plainly marked * as such, and must not be misrepresented as * being the original software. * * 3. This notice may not be removed or altered from * any source distribution. */ #include "tinf.h" int uzlib_zlib_parse_header(TINF_DATA *d) { unsigned char cmf, flg; /* -- get header bytes -- */ cmf = uzlib_get_byte(d); flg = uzlib_get_byte(d); /* -- check format -- */ /* check checksum */ if ((256*cmf + flg) % 31) return TINF_DATA_ERROR; /* check method is deflate */ if ((cmf & 0x0f) != 8) return TINF_DATA_ERROR; /* check window size is valid */ if ((cmf >> 4) > 7) return TINF_DATA_ERROR; /* check there is no preset dictionary */ if (flg & 0x20) return TINF_DATA_ERROR; /* initialize for adler32 checksum */ d->checksum_type = TINF_CHKSUM_ADLER; d->checksum = 1; return cmf >> 4; } micropython-1.12/extmod/uzlib/uzlib.h000066400000000000000000000111751357706137100177520ustar00rootroot00000000000000/* * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) * * Copyright (c) 2003 by Joergen Ibsen / Jibz * All Rights Reserved * http://www.ibsensoftware.com/ * * Copyright (c) 2014-2018 by Paul Sokolovsky * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be * held liable for any damages arising from the use of * this software. * * Permission is granted to anyone to use this software * for any purpose, including commercial applications, * and to alter it and redistribute it freely, subject to * the following restrictions: * * 1. The origin of this software must not be * misrepresented; you must not claim that you * wrote the original software. If you use this * software in a product, an acknowledgment in * the product documentation would be appreciated * but is not required. * * 2. Altered source versions must be plainly marked * as such, and must not be misrepresented as * being the original software. * * 3. This notice may not be removed or altered from * any source distribution. */ #ifndef UZLIB_H_INCLUDED #define UZLIB_H_INCLUDED #include #include #include #include "defl_static.h" #include "uzlib_conf.h" #if UZLIB_CONF_DEBUG_LOG #include #endif /* calling convention */ #ifndef TINFCC #ifdef __WATCOMC__ #define TINFCC __cdecl #else #define TINFCC #endif #endif #ifdef __cplusplus extern "C" { #endif /* ok status, more data produced */ #define TINF_OK 0 /* end of compressed stream reached */ #define TINF_DONE 1 #define TINF_DATA_ERROR (-3) #define TINF_CHKSUM_ERROR (-4) #define TINF_DICT_ERROR (-5) /* checksum types */ #define TINF_CHKSUM_NONE 0 #define TINF_CHKSUM_ADLER 1 #define TINF_CHKSUM_CRC 2 /* helper macros */ #define TINF_ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr))) /* data structures */ typedef struct { unsigned short table[16]; /* table of code length counts */ unsigned short trans[288]; /* code -> symbol translation table */ } TINF_TREE; struct uzlib_uncomp { /* Pointer to the next byte in the input buffer */ const unsigned char *source; /* Pointer to the next byte past the input buffer (source_limit = source + len) */ const unsigned char *source_limit; /* If source_limit == NULL, or source >= source_limit, this function will be used to read next byte from source stream. The function may also return -1 in case of EOF (or irrecoverable error). Note that besides returning the next byte, it may also update source and source_limit fields, thus allowing for buffered operation. */ int (*source_read_cb)(struct uzlib_uncomp *uncomp); unsigned int tag; unsigned int bitcount; /* Destination (output) buffer start */ unsigned char *dest_start; /* Current pointer in dest buffer */ unsigned char *dest; /* Pointer past the end of the dest buffer, similar to source_limit */ unsigned char *dest_limit; /* Accumulating checksum */ unsigned int checksum; char checksum_type; bool eof; int btype; int bfinal; unsigned int curlen; int lzOff; unsigned char *dict_ring; unsigned int dict_size; unsigned int dict_idx; TINF_TREE ltree; /* dynamic length/symbol tree */ TINF_TREE dtree; /* dynamic distance tree */ }; #include "tinf_compat.h" #define TINF_PUT(d, c) \ { \ *d->dest++ = c; \ if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \ } unsigned char TINFCC uzlib_get_byte(TINF_DATA *d); /* Decompression API */ void TINFCC uzlib_init(void); void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen); int TINFCC uzlib_uncompress(TINF_DATA *d); int TINFCC uzlib_uncompress_chksum(TINF_DATA *d); int TINFCC uzlib_zlib_parse_header(TINF_DATA *d); int TINFCC uzlib_gzip_parse_header(TINF_DATA *d); /* Compression API */ typedef const uint8_t *uzlib_hash_entry_t; struct uzlib_comp { struct Outbuf out; uzlib_hash_entry_t *hash_table; unsigned int hash_bits; unsigned int dict_size; }; void TINFCC uzlib_compress(struct uzlib_comp *c, const uint8_t *src, unsigned slen); /* Checksum API */ /* prev_sum is previous value for incremental computation, 1 initially */ uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum); /* crc is previous value for incremental computation, 0xffffffff initially */ uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* UZLIB_H_INCLUDED */ micropython-1.12/extmod/uzlib/uzlib_conf.h000066400000000000000000000010621357706137100207510ustar00rootroot00000000000000/* * uzlib - tiny deflate/inflate library (deflate, gzip, zlib) * * Copyright (c) 2014-2018 by Paul Sokolovsky */ #ifndef UZLIB_CONF_H_INCLUDED #define UZLIB_CONF_H_INCLUDED #ifndef UZLIB_CONF_DEBUG_LOG /* Debug logging level 0, 1, 2, etc. */ #define UZLIB_CONF_DEBUG_LOG 0 #endif #ifndef UZLIB_CONF_PARANOID_CHECKS /* Perform extra checks on the input stream, even if they aren't proven to be strictly required (== lack of them wasn't proven to lead to crashes). */ #define UZLIB_CONF_PARANOID_CHECKS 0 #endif #endif /* UZLIB_CONF_H_INCLUDED */ micropython-1.12/extmod/vfs.c000066400000000000000000000450051357706137100162700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/objstr.h" #include "py/mperrno.h" #include "extmod/vfs.h" #if MICROPY_VFS #if MICROPY_VFS_FAT #include "extmod/vfs_fat.h" #endif #if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2 #include "extmod/vfs_lfs.h" #endif #if MICROPY_VFS_POSIX #include "extmod/vfs_posix.h" #endif // For mp_vfs_proxy_call, the maximum number of additional args that can be passed. // A fixed maximum size is used to avoid the need for a costly variable array. #define PROXY_MAX_ARGS (2) // path is the path to lookup and *path_out holds the path within the VFS // object (starts with / if an absolute path). // Returns MP_VFS_ROOT for root dir (and then path_out is undefined) and // MP_VFS_NONE for path not found. mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out) { if (*path == '/' || MP_STATE_VM(vfs_cur) == MP_VFS_ROOT) { // an absolute path, or the current volume is root, so search root dir bool is_abs = 0; if (*path == '/') { ++path; is_abs = 1; } if (*path == '\0') { // path is "" or "/" so return virtual root return MP_VFS_ROOT; } for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { size_t len = vfs->len - 1; if (len == 0) { *path_out = path - is_abs; return vfs; } if (strncmp(path, vfs->str + 1, len) == 0) { if (path[len] == '/') { *path_out = path + len; return vfs; } else if (path[len] == '\0') { *path_out = "/"; return vfs; } } } // if we get here then there's nothing mounted on / if (is_abs) { // path began with / and was not found return MP_VFS_NONE; } } // a relative path within a mounted device *path_out = path; return MP_STATE_VM(vfs_cur); } // Version of mp_vfs_lookup_path that takes and returns uPy string objects. STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) { const char *path = mp_obj_str_get_str(path_in); const char *p_out; mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &p_out); if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) { *path_out = mp_obj_new_str_of_type(mp_obj_get_type(path_in), (const byte*)p_out, strlen(p_out)); } return vfs; } STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { assert(n_args <= PROXY_MAX_ARGS); if (vfs == MP_VFS_NONE) { // mount point not found mp_raise_OSError(MP_ENODEV); } if (vfs == MP_VFS_ROOT) { // can't do operation on root dir mp_raise_OSError(MP_EPERM); } mp_obj_t meth[2 + PROXY_MAX_ARGS]; mp_load_method(vfs->obj, meth_name, meth); if (args != NULL) { memcpy(meth + 2, args, n_args * sizeof(*args)); } return mp_call_method_n_kw(n_args, 0, meth); } mp_import_stat_t mp_vfs_import_stat(const char *path) { const char *path_out; mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &path_out); if (vfs == MP_VFS_NONE || vfs == MP_VFS_ROOT) { return MP_IMPORT_STAT_NO_EXIST; } // If the mounted object has the VFS protocol, call its import_stat helper const mp_vfs_proto_t *proto = mp_obj_get_type(vfs->obj)->protocol; if (proto != NULL) { return proto->import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out); } // delegate to vfs.stat() method mp_obj_t path_o = mp_obj_new_str(path_out, strlen(path_out)); mp_obj_t stat; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { stat = mp_vfs_proxy_call(vfs, MP_QSTR_stat, 1, &path_o); nlr_pop(); } else { // assume an exception means that the path is not found return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t *items; mp_obj_get_array_fixed_n(stat, 10, &items); mp_int_t st_mode = mp_obj_get_int(items[0]); if (st_mode & MP_S_IFDIR) { return MP_IMPORT_STAT_DIR; } else { return MP_IMPORT_STAT_FILE; } } STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { #if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2 nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t vfs = MP_OBJ_NULL; mp_vfs_blockdev_t blockdev; mp_vfs_blockdev_init(&blockdev, bdev_obj); uint8_t buf[44]; mp_vfs_blockdev_read_ext(&blockdev, 0, 8, sizeof(buf), buf); #if MICROPY_VFS_LFS1 if (memcmp(&buf[32], "littlefs", 8) == 0) { // LFS1 vfs = mp_type_vfs_lfs1.make_new(&mp_type_vfs_lfs1, 1, 0, &bdev_obj); nlr_pop(); return vfs; } #endif #if MICROPY_VFS_LFS2 if (memcmp(&buf[0], "littlefs", 8) == 0) { // LFS2 vfs = mp_type_vfs_lfs2.make_new(&mp_type_vfs_lfs2, 1, 0, &bdev_obj); nlr_pop(); return vfs; } #endif nlr_pop(); } else { // Ignore exception (eg block device doesn't support extended readblocks) } #endif #if MICROPY_VFS_FAT return mp_fat_vfs_type.make_new(&mp_fat_vfs_type, 1, 0, &bdev_obj); #endif return bdev_obj; } mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_readonly, ARG_mkfs }; static const mp_arg_t allowed_args[] = { { MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_false_obj)} }, { MP_QSTR_mkfs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_false_obj)} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the mount point size_t mnt_len; const char *mnt_str = mp_obj_str_get_data(pos_args[1], &mnt_len); // see if we need to auto-detect and create the filesystem mp_obj_t vfs_obj = pos_args[0]; mp_obj_t dest[2]; mp_load_method_maybe(vfs_obj, MP_QSTR_mount, dest); if (dest[0] == MP_OBJ_NULL) { // Input object has no mount method, assume it's a block device and try to // auto-detect the filesystem and create the corresponding VFS entity. vfs_obj = mp_vfs_autodetect(vfs_obj); } // create new object mp_vfs_mount_t *vfs = m_new_obj(mp_vfs_mount_t); vfs->str = mnt_str; vfs->len = mnt_len; vfs->obj = vfs_obj; vfs->next = NULL; // call the underlying object to do any mounting operation mp_vfs_proxy_call(vfs, MP_QSTR_mount, 2, (mp_obj_t*)&args); // check that the destination mount point is unused const char *path_out; mp_vfs_mount_t *existing_mount = mp_vfs_lookup_path(mp_obj_str_get_str(pos_args[1]), &path_out); if (existing_mount != MP_VFS_NONE && existing_mount != MP_VFS_ROOT) { if (vfs->len != 1 && existing_mount->len == 1) { // if root dir is mounted, still allow to mount something within a subdir of root } else { // mount point in use mp_raise_OSError(MP_EPERM); } } // insert the vfs into the mount table mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); while (*vfsp != NULL) { if ((*vfsp)->len == 1) { // make sure anything mounted at the root stays at the end of the list vfs->next = *vfsp; break; } vfsp = &(*vfsp)->next; } *vfsp = vfs; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_mount_obj, 2, mp_vfs_mount); mp_obj_t mp_vfs_umount(mp_obj_t mnt_in) { // remove vfs from the mount table mp_vfs_mount_t *vfs = NULL; size_t mnt_len; const char *mnt_str = NULL; if (mp_obj_is_str(mnt_in)) { mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len); } for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) { if ((mnt_str != NULL && !memcmp(mnt_str, (*vfsp)->str, mnt_len + 1)) || (*vfsp)->obj == mnt_in) { vfs = *vfsp; *vfsp = (*vfsp)->next; break; } } if (vfs == NULL) { mp_raise_OSError(MP_EINVAL); } // if we unmounted the current device then set current to root if (MP_STATE_VM(vfs_cur) == vfs) { MP_STATE_VM(vfs_cur) = MP_VFS_ROOT; } // call the underlying object to do any unmounting operation mp_vfs_proxy_call(vfs, MP_QSTR_umount, 0, NULL); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_umount_obj, mp_vfs_umount); // Note: buffering and encoding args are currently ignored mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_file, ARG_mode, ARG_encoding }; static const mp_arg_t allowed_args[] = { { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} }, { MP_QSTR_buffering, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); #if MICROPY_VFS_POSIX // If the file is an integer then delegate straight to the POSIX handler if (mp_obj_is_small_int(args[ARG_file].u_obj)) { return mp_vfs_posix_file_open(&mp_type_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj); } #endif mp_vfs_mount_t *vfs = lookup_path(args[ARG_file].u_obj, &args[ARG_file].u_obj); return mp_vfs_proxy_call(vfs, MP_QSTR_open, 2, (mp_obj_t*)&args); } MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_open_obj, 0, mp_vfs_open); mp_obj_t mp_vfs_chdir(mp_obj_t path_in) { mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); MP_STATE_VM(vfs_cur) = vfs; if (vfs == MP_VFS_ROOT) { // If we change to the root dir and a VFS is mounted at the root then // we must change that VFS's current dir to the root dir so that any // subsequent relative paths begin at the root of that VFS. for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { if (vfs->len == 1) { mp_obj_t root = MP_OBJ_NEW_QSTR(MP_QSTR__slash_); mp_vfs_proxy_call(vfs, MP_QSTR_chdir, 1, &root); break; } } } else { mp_vfs_proxy_call(vfs, MP_QSTR_chdir, 1, &path_out); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_chdir_obj, mp_vfs_chdir); mp_obj_t mp_vfs_getcwd(void) { if (MP_STATE_VM(vfs_cur) == MP_VFS_ROOT) { return MP_OBJ_NEW_QSTR(MP_QSTR__slash_); } mp_obj_t cwd_o = mp_vfs_proxy_call(MP_STATE_VM(vfs_cur), MP_QSTR_getcwd, 0, NULL); if (MP_STATE_VM(vfs_cur)->len == 1) { // don't prepend "/" for vfs mounted at root return cwd_o; } const char *cwd = mp_obj_str_get_str(cwd_o); vstr_t vstr; vstr_init(&vstr, MP_STATE_VM(vfs_cur)->len + strlen(cwd) + 1); vstr_add_strn(&vstr, MP_STATE_VM(vfs_cur)->str, MP_STATE_VM(vfs_cur)->len); if (!(cwd[0] == '/' && cwd[1] == 0)) { vstr_add_str(&vstr, cwd); } return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd); typedef struct _mp_vfs_ilistdir_it_t { mp_obj_base_t base; mp_fun_1_t iternext; union { mp_vfs_mount_t *vfs; mp_obj_t iter; } cur; bool is_str; bool is_iter; } mp_vfs_ilistdir_it_t; STATIC mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) { mp_vfs_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->is_iter) { // continue delegating to root dir return mp_iternext(self->cur.iter); } else if (self->cur.vfs == NULL) { // finished iterating mount points and no root dir is mounted return MP_OBJ_STOP_ITERATION; } else { // continue iterating mount points mp_vfs_mount_t *vfs = self->cur.vfs; self->cur.vfs = vfs->next; if (vfs->len == 1) { // vfs is mounted at root dir, delegate to it mp_obj_t root = MP_OBJ_NEW_QSTR(MP_QSTR__slash_); self->is_iter = true; self->cur.iter = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &root); return mp_iternext(self->cur.iter); } else { // a mounted directory mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); t->items[0] = mp_obj_new_str_of_type( self->is_str ? &mp_type_str : &mp_type_bytes, (const byte*)vfs->str + 1, vfs->len - 1); t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number return MP_OBJ_FROM_PTR(t); } } } mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args) { mp_obj_t path_in; if (n_args == 1) { path_in = args[0]; } else { path_in = MP_OBJ_NEW_QSTR(MP_QSTR_); } mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); if (vfs == MP_VFS_ROOT) { // list the root directory mp_vfs_ilistdir_it_t *iter = m_new_obj(mp_vfs_ilistdir_it_t); iter->base.type = &mp_type_polymorph_iter; iter->iternext = mp_vfs_ilistdir_it_iternext; iter->cur.vfs = MP_STATE_VM(vfs_mount_table); iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; iter->is_iter = false; return MP_OBJ_FROM_PTR(iter); } return mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &path_out); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_ilistdir_obj, 0, 1, mp_vfs_ilistdir); mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) { mp_obj_t iter = mp_vfs_ilistdir(n_args, args); mp_obj_t dir_list = mp_obj_new_list(0, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL)); } return dir_list; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj, 0, 1, mp_vfs_listdir); mp_obj_t mp_vfs_mkdir(mp_obj_t path_in) { mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); if (vfs == MP_VFS_ROOT || (vfs != MP_VFS_NONE && !strcmp(mp_obj_str_get_str(path_out), "/"))) { mp_raise_OSError(MP_EEXIST); } return mp_vfs_proxy_call(vfs, MP_QSTR_mkdir, 1, &path_out); } MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_mkdir_obj, mp_vfs_mkdir); mp_obj_t mp_vfs_remove(mp_obj_t path_in) { mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); return mp_vfs_proxy_call(vfs, MP_QSTR_remove, 1, &path_out); } MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_remove_obj, mp_vfs_remove); mp_obj_t mp_vfs_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) { mp_obj_t args[2]; mp_vfs_mount_t *old_vfs = lookup_path(old_path_in, &args[0]); mp_vfs_mount_t *new_vfs = lookup_path(new_path_in, &args[1]); if (old_vfs != new_vfs) { // can't rename across filesystems mp_raise_OSError(MP_EPERM); } return mp_vfs_proxy_call(old_vfs, MP_QSTR_rename, 2, args); } MP_DEFINE_CONST_FUN_OBJ_2(mp_vfs_rename_obj, mp_vfs_rename); mp_obj_t mp_vfs_rmdir(mp_obj_t path_in) { mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); return mp_vfs_proxy_call(vfs, MP_QSTR_rmdir, 1, &path_out); } MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_rmdir_obj, mp_vfs_rmdir); mp_obj_t mp_vfs_stat(mp_obj_t path_in) { mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); if (vfs == MP_VFS_ROOT) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); // st_mode for (int i = 1; i <= 9; ++i) { t->items[i] = MP_OBJ_NEW_SMALL_INT(0); // dev, nlink, uid, gid, size, atime, mtime, ctime } return MP_OBJ_FROM_PTR(t); } return mp_vfs_proxy_call(vfs, MP_QSTR_stat, 1, &path_out); } MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_stat_obj, mp_vfs_stat); mp_obj_t mp_vfs_statvfs(mp_obj_t path_in) { mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); if (vfs == MP_VFS_ROOT) { // statvfs called on the root directory, see if there's anything mounted there for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { if (vfs->len == 1) { break; } } // If there's nothing mounted at root then return a mostly-empty tuple if (vfs == NULL) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); // fill in: bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flags for (int i = 0; i <= 8; ++i) { t->items[i] = MP_OBJ_NEW_SMALL_INT(0); } // Put something sensible in f_namemax t->items[9] = MP_OBJ_NEW_SMALL_INT(MICROPY_ALLOC_PATH_MAX); return MP_OBJ_FROM_PTR(t); } // VFS mounted at root so delegate the call to it path_out = MP_OBJ_NEW_QSTR(MP_QSTR__slash_); } return mp_vfs_proxy_call(vfs, MP_QSTR_statvfs, 1, &path_out); } MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_statvfs_obj, mp_vfs_statvfs); #endif // MICROPY_VFS micropython-1.12/extmod/vfs.h000066400000000000000000000121521357706137100162720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_VFS_H #define MICROPY_INCLUDED_EXTMOD_VFS_H #include "py/lexer.h" #include "py/obj.h" // return values of mp_vfs_lookup_path // ROOT is 0 so that the default current directory is the root directory #define MP_VFS_NONE ((mp_vfs_mount_t*)1) #define MP_VFS_ROOT ((mp_vfs_mount_t*)0) // MicroPython's port-standardized versions of stat constants #define MP_S_IFDIR (0x4000) #define MP_S_IFREG (0x8000) // these are the values for mp_vfs_blockdev_t.flags #define MP_BLOCKDEV_FLAG_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func #define MP_BLOCKDEV_FLAG_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount #define MP_BLOCKDEV_FLAG_HAVE_IOCTL (0x0004) // new protocol with ioctl #define MP_BLOCKDEV_FLAG_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it // constants for block protocol ioctl #define MP_BLOCKDEV_IOCTL_INIT (1) #define MP_BLOCKDEV_IOCTL_DEINIT (2) #define MP_BLOCKDEV_IOCTL_SYNC (3) #define MP_BLOCKDEV_IOCTL_BLOCK_COUNT (4) #define MP_BLOCKDEV_IOCTL_BLOCK_SIZE (5) #define MP_BLOCKDEV_IOCTL_BLOCK_ERASE (6) // At the moment the VFS protocol just has import_stat, but could be extended to other methods typedef struct _mp_vfs_proto_t { mp_import_stat_t (*import_stat)(void *self, const char *path); } mp_vfs_proto_t; typedef struct _mp_vfs_blockdev_t { uint16_t flags; size_t block_size; mp_obj_t readblocks[5]; mp_obj_t writeblocks[5]; // new protocol uses just ioctl, old uses sync (optional) and count union { mp_obj_t ioctl[4]; struct { mp_obj_t sync[2]; mp_obj_t count[2]; } old; } u; } mp_vfs_blockdev_t; typedef struct _mp_vfs_mount_t { const char *str; // mount point with leading / size_t len; mp_obj_t obj; struct _mp_vfs_mount_t *next; } mp_vfs_mount_t; void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev); int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf); int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf); int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf); int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, const uint8_t *buf); mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg); mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out); mp_import_stat_t mp_vfs_import_stat(const char *path); mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); mp_obj_t mp_vfs_umount(mp_obj_t mnt_in); mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); mp_obj_t mp_vfs_chdir(mp_obj_t path_in); mp_obj_t mp_vfs_getcwd(void); mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args); mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args); mp_obj_t mp_vfs_mkdir(mp_obj_t path_in); mp_obj_t mp_vfs_remove(mp_obj_t path_in); mp_obj_t mp_vfs_rename(mp_obj_t old_path_in, mp_obj_t new_path_in); mp_obj_t mp_vfs_rmdir(mp_obj_t path_in); mp_obj_t mp_vfs_stat(mp_obj_t path_in); mp_obj_t mp_vfs_statvfs(mp_obj_t path_in); MP_DECLARE_CONST_FUN_OBJ_KW(mp_vfs_mount_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_umount_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_vfs_open_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_chdir_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_ilistdir_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_mkdir_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_remove_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_vfs_rename_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_rmdir_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_stat_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_statvfs_obj); #endif // MICROPY_INCLUDED_EXTMOD_VFS_H micropython-1.12/extmod/vfs_blockdev.c000066400000000000000000000131611357706137100201370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/binary.h" #include "py/objarray.h" #include "py/mperrno.h" #include "extmod/vfs.h" #if MICROPY_VFS void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) { mp_load_method(bdev, MP_QSTR_readblocks, self->readblocks); mp_load_method_maybe(bdev, MP_QSTR_writeblocks, self->writeblocks); mp_load_method_maybe(bdev, MP_QSTR_ioctl, self->u.ioctl); if (self->u.ioctl[0] != MP_OBJ_NULL) { // Device supports new block protocol, so indicate it self->flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL; } else { // No ioctl method, so assume the device uses the old block protocol mp_load_method_maybe(bdev, MP_QSTR_sync, self->u.old.sync); mp_load_method(bdev, MP_QSTR_count, self->u.old.count); } } int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) { if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) { mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)self->readblocks[2]; return f(buf, block_num, num_blocks); } else { mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks * self->block_size, buf}; self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); self->readblocks[3] = MP_OBJ_FROM_PTR(&ar); mp_call_method_n_kw(2, 0, self->readblocks); // TODO handle error return return 0; } } int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf) { mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf}; self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); self->readblocks[3] = MP_OBJ_FROM_PTR(&ar); self->readblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off); mp_obj_t ret = mp_call_method_n_kw(3, 0, self->readblocks); if (ret == mp_const_none) { return 0; } else { return MP_OBJ_SMALL_INT_VALUE(ret); } } int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) { if (self->writeblocks[0] == MP_OBJ_NULL) { // read-only block device return -MP_EROFS; } if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) { mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)self->writeblocks[2]; return f(buf, block_num, num_blocks); } else { mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks * self->block_size, (void*)buf}; self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); mp_call_method_n_kw(2, 0, self->writeblocks); // TODO handle error return return 0; } } int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, const uint8_t *buf) { if (self->writeblocks[0] == MP_OBJ_NULL) { // read-only block device return -MP_EROFS; } mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, (void*)buf}; self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); self->writeblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off); mp_obj_t ret = mp_call_method_n_kw(3, 0, self->writeblocks); if (ret == mp_const_none) { return 0; } else { return MP_OBJ_SMALL_INT_VALUE(ret); } } mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) { if (self->flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) { // New protocol with ioctl self->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(cmd); self->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(arg); return mp_call_method_n_kw(2, 0, self->u.ioctl); } else { // Old protocol with sync and count switch (cmd) { case MP_BLOCKDEV_IOCTL_SYNC: if (self->u.old.sync[0] != MP_OBJ_NULL) { mp_call_method_n_kw(0, 0, self->u.old.sync); } break; case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return mp_call_method_n_kw(0, 0, self->u.old.count); case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: // Old protocol has fixed sector size of 512 bytes break; case MP_BLOCKDEV_IOCTL_INIT: // Old protocol doesn't have init break; } return mp_const_none; } } #endif // MICROPY_VFS micropython-1.12/extmod/vfs_fat.c000066400000000000000000000360361357706137100171260ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_VFS_FAT #if !MICROPY_VFS #error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_VFS" #endif #include #include "py/runtime.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs_fat.h" #include "lib/timeutils/timeutils.h" #if FF_MAX_SS == FF_MIN_SS #define SECSIZE(fs) (FF_MIN_SS) #else #define SECSIZE(fs) ((fs)->ssize) #endif #define mp_obj_fat_vfs_t fs_user_mount_t STATIC mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) { fs_user_mount_t *vfs = vfs_in; FILINFO fno; assert(vfs != NULL); FRESULT res = f_stat(&vfs->fatfs, path, &fno); if (res == FR_OK) { if ((fno.fattrib & AM_DIR) != 0) { return MP_IMPORT_STAT_DIR; } else { return MP_IMPORT_STAT_FILE; } } return MP_IMPORT_STAT_NO_EXIST; } STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); // create new object fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t); vfs->base.type = type; vfs->fatfs.drv = vfs; // Initialise underlying block device vfs->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE mp_vfs_blockdev_init(&vfs->blockdev, args[0]); // mount the block device so the VFS methods can be used FRESULT res = f_mount(&vfs->fatfs); if (res == FR_NO_FILESYSTEM) { // don't error out if no filesystem, to let mkfs()/mount() create one if wanted vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NO_FILESYSTEM; } else if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } return MP_OBJ_FROM_PTR(vfs); } #if _FS_REENTRANT STATIC mp_obj_t fat_vfs_del(mp_obj_t self_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(self_in); // f_umount only needs to be called to release the sync object f_umount(&self->fatfs); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_del_obj, fat_vfs_del); #endif STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) { // create new object fs_user_mount_t *vfs = MP_OBJ_TO_PTR(fat_vfs_make_new(&mp_fat_vfs_type, 1, 0, &bdev_in)); // make the filesystem uint8_t working_buf[FF_MAX_SS]; FRESULT res = f_mkfs(&vfs->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf)); if (res == FR_MKFS_ABORTED) { // Probably doesn't support FAT16 res = f_mkfs(&vfs->fatfs, FM_FAT32, 0, working_buf, sizeof(working_buf)); } if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mkfs_fun_obj)); typedef struct _mp_vfs_fat_ilistdir_it_t { mp_obj_base_t base; mp_fun_1_t iternext; bool is_str; FF_DIR dir; } mp_vfs_fat_ilistdir_it_t; STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); for (;;) { FILINFO fno; FRESULT res = f_readdir(&self->dir, &fno); char *fn = fno.fname; if (res != FR_OK || fn[0] == 0) { // stop on error or end of dir break; } // Note that FatFS already filters . and .., so we don't need to // make 4-tuple with info about this entry mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); if (self->is_str) { t->items[0] = mp_obj_new_str(fn, strlen(fn)); } else { t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn)); } if (fno.fattrib & AM_DIR) { // dir t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); } else { // file t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG); } t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number t->items[3] = mp_obj_new_int_from_uint(fno.fsize); return MP_OBJ_FROM_PTR(t); } // ignore error because we may be closing a second time f_closedir(&self->dir); return MP_OBJ_STOP_ITERATION; } STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]); bool is_str_type = true; const char *path; if (n_args == 2) { if (mp_obj_get_type(args[1]) == &mp_type_bytes) { is_str_type = false; } path = mp_obj_str_get_str(args[1]); } else { path = ""; } // Create a new iterator object to list the dir mp_vfs_fat_ilistdir_it_t *iter = m_new_obj(mp_vfs_fat_ilistdir_it_t); iter->base.type = &mp_type_polymorph_iter; iter->iternext = mp_vfs_fat_ilistdir_it_iternext; iter->is_str = is_str_type; FRESULT res = f_opendir(&self->fatfs, &iter->dir, path); if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } return MP_OBJ_FROM_PTR(iter); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_ilistdir_obj, 1, 2, fat_vfs_ilistdir_func); STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_int_t attr) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); const char *path = mp_obj_str_get_str(path_in); FILINFO fno; FRESULT res = f_stat(&self->fatfs, path, &fno); if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } // check if path is a file or directory if ((fno.fattrib & AM_DIR) == attr) { res = f_unlink(&self->fatfs, path); if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } return mp_const_none; } else { mp_raise_OSError(attr ? MP_ENOTDIR : MP_EISDIR); } } STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) { return fat_vfs_remove_internal(vfs_in, path_in, 0); // 0 == file attribute } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove); STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) { return fat_vfs_remove_internal(vfs_in, path_in, AM_DIR); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir); STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_out) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); const char *old_path = mp_obj_str_get_str(path_in); const char *new_path = mp_obj_str_get_str(path_out); FRESULT res = f_rename(&self->fatfs, old_path, new_path); if (res == FR_EXIST) { // if new_path exists then try removing it (but only if it's a file) fat_vfs_remove_internal(vfs_in, path_out, 0); // 0 == file attribute // try to rename again res = f_rename(&self->fatfs, old_path, new_path); } if (res == FR_OK) { return mp_const_none; } else { mp_raise_OSError(fresult_to_errno_table[res]); } } STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_rename_obj, fat_vfs_rename); STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); const char *path = mp_obj_str_get_str(path_o); FRESULT res = f_mkdir(&self->fatfs, path); if (res == FR_OK) { return mp_const_none; } else { mp_raise_OSError(fresult_to_errno_table[res]); } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir); /// Change current directory. STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); const char *path; path = mp_obj_str_get_str(path_in); FRESULT res = f_chdir(&self->fatfs, path); if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir); /// Get the current directory. STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); char buf[MICROPY_ALLOC_PATH_MAX + 1]; FRESULT res = f_getcwd(&self->fatfs, buf, sizeof(buf)); if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } return mp_obj_new_str(buf, strlen(buf)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd); /// \function stat(path) /// Get the status of a file or directory. STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); const char *path = mp_obj_str_get_str(path_in); FILINFO fno; if (path[0] == 0 || (path[0] == '/' && path[1] == 0)) { // stat root directory fno.fsize = 0; fno.fdate = 0x2821; // Jan 1, 2000 fno.ftime = 0; fno.fattrib = AM_DIR; } else { FRESULT res = f_stat(&self->fatfs, path, &fno); if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); mp_int_t mode = 0; if (fno.fattrib & AM_DIR) { mode |= MP_S_IFDIR; } else { mode |= MP_S_IFREG; } mp_int_t seconds = timeutils_seconds_since_2000( 1980 + ((fno.fdate >> 9) & 0x7f), (fno.fdate >> 5) & 0x0f, fno.fdate & 0x1f, (fno.ftime >> 11) & 0x1f, (fno.ftime >> 5) & 0x3f, 2 * (fno.ftime & 0x1f) ); t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid t->items[6] = mp_obj_new_int_from_uint(fno.fsize); // st_size t->items[7] = MP_OBJ_NEW_SMALL_INT(seconds); // st_atime t->items[8] = MP_OBJ_NEW_SMALL_INT(seconds); // st_mtime t->items[9] = MP_OBJ_NEW_SMALL_INT(seconds); // st_ctime return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat); // Get the status of a VFS. STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); (void)path_in; DWORD nclst; FATFS *fatfs = &self->fatfs; FRESULT res = f_getfree(fatfs, &nclst); if (FR_OK != res) { mp_raise_OSError(fresult_to_errno_table[res]); } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(fatfs->csize * SECSIZE(fatfs)); // f_bsize t->items[1] = t->items[0]; // f_frsize t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2)); // f_blocks t->items[3] = MP_OBJ_NEW_SMALL_INT(nclst); // f_bfree t->items[4] = t->items[3]; // f_bavail t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags t->items[9] = MP_OBJ_NEW_SMALL_INT(FF_MAX_LFN); // f_namemax return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs); STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); // Read-only device indicated by writeblocks[0] == MP_OBJ_NULL. // User can specify read-only device by: // 1. readonly=True keyword argument // 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already) if (mp_obj_is_true(readonly)) { self->blockdev.writeblocks[0] = MP_OBJ_NULL; } // check if we need to make the filesystem FRESULT res = (self->blockdev.flags & MP_BLOCKDEV_FLAG_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK; if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs)) { uint8_t working_buf[FF_MAX_SS]; res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf)); } if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } self->blockdev.flags &= ~MP_BLOCKDEV_FLAG_NO_FILESYSTEM; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_fat_mount_obj, vfs_fat_mount); STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) { (void)self_in; // keep the FAT filesystem mounted internally so the VFS methods can still be used return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { #if _FS_REENTRANT { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fat_vfs_del_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&fat_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&fat_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_fat_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) }, }; STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); STATIC const mp_vfs_proto_t fat_vfs_proto = { .import_stat = fat_vfs_import_stat, }; const mp_obj_type_t mp_fat_vfs_type = { { &mp_type_type }, .name = MP_QSTR_VfsFat, .make_new = fat_vfs_make_new, .protocol = &fat_vfs_proto, .locals_dict = (mp_obj_dict_t*)&fat_vfs_locals_dict, }; #endif // MICROPY_VFS_FAT micropython-1.12/extmod/vfs_fat.h000066400000000000000000000034101357706137100171210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_VFS_FAT_H #define MICROPY_INCLUDED_EXTMOD_VFS_FAT_H #include "py/obj.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" typedef struct _fs_user_mount_t { mp_obj_base_t base; mp_vfs_blockdev_t blockdev; FATFS fatfs; } fs_user_mount_t; extern const byte fresult_to_errno_table[20]; extern const mp_obj_type_t mp_fat_vfs_type; extern const mp_obj_type_t mp_type_vfs_fat_fileio; extern const mp_obj_type_t mp_type_vfs_fat_textio; MP_DECLARE_CONST_FUN_OBJ_3(fat_vfs_open_obj); #endif // MICROPY_INCLUDED_EXTMOD_VFS_FAT_H micropython-1.12/extmod/vfs_fat_diskio.c000066400000000000000000000130241357706137100204600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Original template for this file comes from: * Low level disk I/O module skeleton for FatFs, (C)ChaN, 2013 * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_VFS && MICROPY_VFS_FAT #include #include #include "py/mphal.h" #include "py/runtime.h" #include "py/binary.h" #include "py/objarray.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs_fat.h" typedef void *bdev_t; STATIC fs_user_mount_t *disk_get_device(void *bdev) { return (fs_user_mount_t*)bdev; } /*-----------------------------------------------------------------------*/ /* Read Sector(s) */ /*-----------------------------------------------------------------------*/ DRESULT disk_read ( bdev_t pdrv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to read (1..128) */ ) { fs_user_mount_t *vfs = disk_get_device(pdrv); if (vfs == NULL) { return RES_PARERR; } int ret = mp_vfs_blockdev_read(&vfs->blockdev, sector, count, buff); return ret == 0 ? RES_OK : RES_ERROR; } /*-----------------------------------------------------------------------*/ /* Write Sector(s) */ /*-----------------------------------------------------------------------*/ DRESULT disk_write ( bdev_t pdrv, /* Physical drive nmuber (0..) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to write (1..128) */ ) { fs_user_mount_t *vfs = disk_get_device(pdrv); if (vfs == NULL) { return RES_PARERR; } int ret = mp_vfs_blockdev_write(&vfs->blockdev, sector, count, buff); if (ret == -MP_EROFS) { // read-only block device return RES_WRPRT; } return ret == 0 ? RES_OK : RES_ERROR; } /*-----------------------------------------------------------------------*/ /* Miscellaneous Functions */ /*-----------------------------------------------------------------------*/ DRESULT disk_ioctl ( bdev_t pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { fs_user_mount_t *vfs = disk_get_device(pdrv); if (vfs == NULL) { return RES_PARERR; } // First part: call the relevant method of the underlying block device static const uint8_t op_map[8] = { [CTRL_SYNC] = MP_BLOCKDEV_IOCTL_SYNC, [GET_SECTOR_COUNT] = MP_BLOCKDEV_IOCTL_BLOCK_COUNT, [GET_SECTOR_SIZE] = MP_BLOCKDEV_IOCTL_BLOCK_SIZE, [IOCTL_INIT] = MP_BLOCKDEV_IOCTL_INIT, }; uint8_t bp_op = op_map[cmd & 7]; mp_obj_t ret = mp_const_none; if (bp_op != 0) { ret = mp_vfs_blockdev_ioctl(&vfs->blockdev, bp_op, 0); } // Second part: convert the result for return switch (cmd) { case CTRL_SYNC: return RES_OK; case GET_SECTOR_COUNT: { *((DWORD*)buff) = mp_obj_get_int(ret); return RES_OK; } case GET_SECTOR_SIZE: { if (ret == mp_const_none) { // Default sector size *((WORD*)buff) = 512; } else { *((WORD*)buff) = mp_obj_get_int(ret); } // need to store ssize because we use it in disk_read/disk_write vfs->blockdev.block_size = *((WORD*)buff); return RES_OK; } case GET_BLOCK_SIZE: *((DWORD*)buff) = 1; // erase block size in units of sector size return RES_OK; case IOCTL_INIT: case IOCTL_STATUS: { DSTATUS stat; if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) { // error initialising stat = STA_NOINIT; } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { stat = STA_PROTECT; } else { stat = 0; } *((DSTATUS*)buff) = stat; return RES_OK; } default: return RES_PARERR; } } #endif // MICROPY_VFS && MICROPY_VFS_FAT micropython-1.12/extmod/vfs_fat_file.c000066400000000000000000000236201357706137100201200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_VFS && MICROPY_VFS_FAT #include #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs_fat.h" // this table converts from FRESULT to POSIX errno const byte fresult_to_errno_table[20] = { [FR_OK] = 0, [FR_DISK_ERR] = MP_EIO, [FR_INT_ERR] = MP_EIO, [FR_NOT_READY] = MP_EBUSY, [FR_NO_FILE] = MP_ENOENT, [FR_NO_PATH] = MP_ENOENT, [FR_INVALID_NAME] = MP_EINVAL, [FR_DENIED] = MP_EACCES, [FR_EXIST] = MP_EEXIST, [FR_INVALID_OBJECT] = MP_EINVAL, [FR_WRITE_PROTECTED] = MP_EROFS, [FR_INVALID_DRIVE] = MP_ENODEV, [FR_NOT_ENABLED] = MP_ENODEV, [FR_NO_FILESYSTEM] = MP_ENODEV, [FR_MKFS_ABORTED] = MP_EIO, [FR_TIMEOUT] = MP_EIO, [FR_LOCKED] = MP_EIO, [FR_NOT_ENOUGH_CORE] = MP_ENOMEM, [FR_TOO_MANY_OPEN_FILES] = MP_EMFILE, [FR_INVALID_PARAMETER] = MP_EINVAL, }; typedef struct _pyb_file_obj_t { mp_obj_base_t base; FIL fp; } pyb_file_obj_t; STATIC void file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_printf(print, "", mp_obj_get_type_str(self_in), MP_OBJ_TO_PTR(self_in)); } STATIC mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); UINT sz_out; FRESULT res = f_read(&self->fp, buf, size, &sz_out); if (res != FR_OK) { *errcode = fresult_to_errno_table[res]; return MP_STREAM_ERROR; } return sz_out; } STATIC mp_uint_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); UINT sz_out; FRESULT res = f_write(&self->fp, buf, size, &sz_out); if (res != FR_OK) { *errcode = fresult_to_errno_table[res]; return MP_STREAM_ERROR; } if (sz_out != size) { // The FatFS documentation says that this means disk full. *errcode = MP_ENOSPC; return MP_STREAM_ERROR; } return sz_out; } STATIC mp_obj_t file_obj___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; return mp_stream_close(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(file_obj___exit___obj, 4, 4, file_obj___exit__); STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { pyb_file_obj_t *self = MP_OBJ_TO_PTR(o_in); if (request == MP_STREAM_SEEK) { struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)(uintptr_t)arg; switch (s->whence) { case 0: // SEEK_SET f_lseek(&self->fp, s->offset); break; case 1: // SEEK_CUR f_lseek(&self->fp, f_tell(&self->fp) + s->offset); break; case 2: // SEEK_END f_lseek(&self->fp, f_size(&self->fp) + s->offset); break; } s->offset = f_tell(&self->fp); return 0; } else if (request == MP_STREAM_FLUSH) { FRESULT res = f_sync(&self->fp); if (res != FR_OK) { *errcode = fresult_to_errno_table[res]; return MP_STREAM_ERROR; } return 0; } else if (request == MP_STREAM_CLOSE) { // if fs==NULL then the file is closed and in that case this method is a no-op if (self->fp.obj.fs != NULL) { FRESULT res = f_close(&self->fp); if (res != FR_OK) { *errcode = fresult_to_errno_table[res]; return MP_STREAM_ERROR; } } return 0; } else { *errcode = MP_EINVAL; return MP_STREAM_ERROR; } } // Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO, // but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor STATIC const mp_arg_t file_open_args[] = { { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} }, { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; #define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_arg_val_t *args) { int mode = 0; const char *mode_s = mp_obj_str_get_str(args[1].u_obj); // TODO make sure only one of r, w, x, a, and b, t are specified while (*mode_s) { switch (*mode_s++) { case 'r': mode |= FA_READ; break; case 'w': mode |= FA_WRITE | FA_CREATE_ALWAYS; break; case 'x': mode |= FA_WRITE | FA_CREATE_NEW; break; case 'a': mode |= FA_WRITE | FA_OPEN_ALWAYS; break; case '+': mode |= FA_READ | FA_WRITE; break; #if MICROPY_PY_IO_FILEIO case 'b': type = &mp_type_vfs_fat_fileio; break; #endif case 't': type = &mp_type_vfs_fat_textio; break; } } pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t); o->base.type = type; const char *fname = mp_obj_str_get_str(args[0].u_obj); assert(vfs != NULL); FRESULT res = f_open(&vfs->fatfs, &o->fp, fname, mode); if (res != FR_OK) { m_del_obj(pyb_file_obj_t, o); mp_raise_OSError(fresult_to_errno_table[res]); } // for 'a' mode, we must begin at the end of the file if ((mode & FA_OPEN_ALWAYS) != 0) { f_lseek(&o->fp, f_size(&o->fp)); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t file_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; mp_arg_parse_all_kw_array(n_args, n_kw, args, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals); return file_open(NULL, type, arg_vals); } // TODO gc hook to close the file if not already closed STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) }, }; STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); #if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { .read = file_obj_read, .write = file_obj_write, .ioctl = file_obj_ioctl, }; const mp_obj_type_t mp_type_vfs_fat_fileio = { { &mp_type_type }, .name = MP_QSTR_FileIO, .print = file_obj_print, .make_new = file_obj_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &vfs_fat_fileio_stream_p, .locals_dict = (mp_obj_dict_t*)&vfs_fat_rawfile_locals_dict, }; #endif STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { .read = file_obj_read, .write = file_obj_write, .ioctl = file_obj_ioctl, .is_text = true, }; const mp_obj_type_t mp_type_vfs_fat_textio = { { &mp_type_type }, .name = MP_QSTR_TextIOWrapper, .print = file_obj_print, .make_new = file_obj_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &vfs_fat_textio_stream_p, .locals_dict = (mp_obj_dict_t*)&vfs_fat_rawfile_locals_dict, }; // Factory function for I/O stream classes STATIC mp_obj_t fatfs_builtin_open_self(mp_obj_t self_in, mp_obj_t path, mp_obj_t mode) { // TODO: analyze buffering args and instantiate appropriate type fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; arg_vals[0].u_obj = path; arg_vals[1].u_obj = mode; arg_vals[2].u_obj = mp_const_none; return file_open(self, &mp_type_vfs_fat_textio, arg_vals); } MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fatfs_builtin_open_self); #endif // MICROPY_VFS && MICROPY_VFS_FAT micropython-1.12/extmod/vfs_lfs.c000066400000000000000000000077231357706137100171410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "extmod/vfs.h" #include "extmod/vfs_lfs.h" #if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) enum { LFS_MAKE_ARG_bdev, LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead }; static const mp_arg_t lfs_make_allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_readsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, { MP_QSTR_progsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, { MP_QSTR_lookahead, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, }; #if MICROPY_VFS_LFS1 #include "lib/littlefs/lfs1.h" #define LFS_BUILD_VERSION (1) #define LFSx_MACRO(s) LFS1 ## s #define LFSx_API(s) lfs1_ ## s #define MP_VFS_LFSx(s) mp_vfs_lfs1_ ## s #define MP_OBJ_VFS_LFSx mp_obj_vfs_lfs1_t #define MP_OBJ_VFS_LFSx_FILE mp_obj_vfs_lfs1_file_t #define MP_TYPE_VFS_LFSx mp_type_vfs_lfs1 #define MP_TYPE_VFS_LFSx_(s) mp_type_vfs_lfs1 ## s typedef struct _mp_obj_vfs_lfs1_t { mp_obj_base_t base; mp_vfs_blockdev_t blockdev; vstr_t cur_dir; struct lfs1_config config; lfs1_t lfs; } mp_obj_vfs_lfs1_t; typedef struct _mp_obj_vfs_lfs1_file_t { mp_obj_base_t base; mp_obj_vfs_lfs1_t *vfs; lfs1_file_t file; struct lfs1_file_config cfg; uint8_t file_buffer[0]; } mp_obj_vfs_lfs1_file_t; const char *mp_vfs_lfs1_make_path(mp_obj_vfs_lfs1_t *self, mp_obj_t path_in); mp_obj_t mp_vfs_lfs1_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in); #include "extmod/vfs_lfsx.c" #include "extmod/vfs_lfsx_file.c" #undef LFS_BUILD_VERSION #undef LFSx_MACRO #undef LFSx_API #undef MP_VFS_LFSx #undef MP_OBJ_VFS_LFSx #undef MP_OBJ_VFS_LFSx_FILE #undef MP_TYPE_VFS_LFSx #undef MP_TYPE_VFS_LFSx_ #endif // MICROPY_VFS_LFS1 #if MICROPY_VFS_LFS2 #include "lib/littlefs/lfs2.h" #define LFS_BUILD_VERSION (2) #define LFSx_MACRO(s) LFS2 ## s #define LFSx_API(s) lfs2_ ## s #define MP_VFS_LFSx(s) mp_vfs_lfs2_ ## s #define MP_OBJ_VFS_LFSx mp_obj_vfs_lfs2_t #define MP_OBJ_VFS_LFSx_FILE mp_obj_vfs_lfs2_file_t #define MP_TYPE_VFS_LFSx mp_type_vfs_lfs2 #define MP_TYPE_VFS_LFSx_(s) mp_type_vfs_lfs2 ## s typedef struct _mp_obj_vfs_lfs2_t { mp_obj_base_t base; mp_vfs_blockdev_t blockdev; vstr_t cur_dir; struct lfs2_config config; lfs2_t lfs; } mp_obj_vfs_lfs2_t; typedef struct _mp_obj_vfs_lfs2_file_t { mp_obj_base_t base; mp_obj_vfs_lfs2_t *vfs; lfs2_file_t file; struct lfs2_file_config cfg; uint8_t file_buffer[0]; } mp_obj_vfs_lfs2_file_t; const char *mp_vfs_lfs2_make_path(mp_obj_vfs_lfs2_t *self, mp_obj_t path_in); mp_obj_t mp_vfs_lfs2_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in); #include "extmod/vfs_lfsx.c" #include "extmod/vfs_lfsx_file.c" #endif // MICROPY_VFS_LFS2 #endif // MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) micropython-1.12/extmod/vfs_lfs.h000066400000000000000000000032131357706137100171340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_VFS_LFS_H #define MICROPY_INCLUDED_EXTMOD_VFS_LFS_H #include "py/obj.h" extern const mp_obj_type_t mp_type_vfs_lfs1; extern const mp_obj_type_t mp_type_vfs_lfs1_fileio; extern const mp_obj_type_t mp_type_vfs_lfs1_textio; extern const mp_obj_type_t mp_type_vfs_lfs2; extern const mp_obj_type_t mp_type_vfs_lfs2_fileio; extern const mp_obj_type_t mp_type_vfs_lfs2_textio; #endif // MICROPY_INCLUDED_EXTMOD_VFS_LFS_H micropython-1.12/extmod/vfs_lfsx.c000066400000000000000000000411061357706137100173220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/binary.h" #include "py/objarray.h" #include "py/mperrno.h" #include "extmod/vfs.h" STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API(config) *c, int cmd, int arg, bool must_return_int) { mp_obj_t ret = mp_vfs_blockdev_ioctl(c->context, cmd, arg); int ret_i = 0; if (must_return_int || ret != mp_const_none) { ret_i = mp_obj_get_int(ret); } return ret_i; } STATIC int MP_VFS_LFSx(dev_read)(const struct LFSx_API(config) *c, LFSx_API(block_t) block, LFSx_API(off_t) off, void *buffer, LFSx_API(size_t) size) { return mp_vfs_blockdev_read_ext(c->context, block, off, size, buffer); } STATIC int MP_VFS_LFSx(dev_prog)(const struct LFSx_API(config) *c, LFSx_API(block_t) block, LFSx_API(off_t) off, const void *buffer, LFSx_API(size_t) size) { return mp_vfs_blockdev_write_ext(c->context, block, off, size, buffer); } STATIC int MP_VFS_LFSx(dev_erase)(const struct LFSx_API(config) *c, LFSx_API(block_t) block) { return MP_VFS_LFSx(dev_ioctl)(c, MP_BLOCKDEV_IOCTL_BLOCK_ERASE, block, true); } STATIC int MP_VFS_LFSx(dev_sync)(const struct LFSx_API(config) *c) { return MP_VFS_LFSx(dev_ioctl)(c, MP_BLOCKDEV_IOCTL_SYNC, 0, false); } STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx *self, mp_obj_t bdev, size_t read_size, size_t prog_size, size_t lookahead) { self->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; mp_vfs_blockdev_init(&self->blockdev, bdev); struct LFSx_API(config) *config = &self->config; memset(config, 0, sizeof(*config)); config->context = &self->blockdev; config->read = MP_VFS_LFSx(dev_read); config->prog = MP_VFS_LFSx(dev_prog); config->erase = MP_VFS_LFSx(dev_erase); config->sync = MP_VFS_LFSx(dev_sync); MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_INIT, 1, false); // initialise block device int bs = MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_BLOCK_SIZE, 0, true); // get block size int bc = MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_BLOCK_COUNT, 0, true); // get block count self->blockdev.block_size = bs; config->read_size = read_size; config->prog_size = prog_size; config->block_size = bs; config->block_count = bc; #if LFS_BUILD_VERSION == 1 config->lookahead = lookahead; config->read_buffer = m_new(uint8_t, config->read_size); config->prog_buffer = m_new(uint8_t, config->prog_size); config->lookahead_buffer = m_new(uint8_t, config->lookahead / 8); #else config->block_cycles = 100; config->cache_size = 4 * MAX(read_size, prog_size); config->lookahead_size = lookahead; config->read_buffer = m_new(uint8_t, config->cache_size); config->prog_buffer = m_new(uint8_t, config->cache_size); config->lookahead_buffer = m_new(uint8_t, config->lookahead_size); #endif } const char *MP_VFS_LFSx(make_path)(MP_OBJ_VFS_LFSx *self, mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); if (path[0] != '/') { size_t l = vstr_len(&self->cur_dir); if (l > 0) { vstr_add_str(&self->cur_dir, path); path = vstr_null_terminated_str(&self->cur_dir); self->cur_dir.len = l; } } return path; } STATIC mp_obj_t MP_VFS_LFSx(make_new)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_val_t args[MP_ARRAY_SIZE(lfs_make_allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(lfs_make_allowed_args), lfs_make_allowed_args, args); MP_OBJ_VFS_LFSx *self = m_new0(MP_OBJ_VFS_LFSx, 1); self->base.type = type; vstr_init(&self->cur_dir, 16); vstr_add_byte(&self->cur_dir, '/'); MP_VFS_LFSx(init_config)(self, args[LFS_MAKE_ARG_bdev].u_obj, args[LFS_MAKE_ARG_readsize].u_int, args[LFS_MAKE_ARG_progsize].u_int, args[LFS_MAKE_ARG_lookahead].u_int); int ret = LFSx_API(mount)(&self->lfs, &self->config); if (ret < 0) { mp_raise_OSError(-ret); } return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t MP_VFS_LFSx(mkfs)(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[MP_ARRAY_SIZE(lfs_make_allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(lfs_make_allowed_args), lfs_make_allowed_args, args); MP_OBJ_VFS_LFSx self; MP_VFS_LFSx(init_config)(&self, args[LFS_MAKE_ARG_bdev].u_obj, args[LFS_MAKE_ARG_readsize].u_int, args[LFS_MAKE_ARG_progsize].u_int, args[LFS_MAKE_ARG_lookahead].u_int); int ret = LFSx_API(format)(&self.lfs, &self.config); if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(MP_VFS_LFSx(mkfs_fun_obj), 0, MP_VFS_LFSx(mkfs)); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(MP_VFS_LFSx(mkfs_obj), MP_ROM_PTR(&MP_VFS_LFSx(mkfs_fun_obj))); // Implementation of mp_vfs_lfs_file_open is provided in vfs_lfsx_file.c STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(open_obj), MP_VFS_LFSx(file_open)); typedef struct MP_VFS_LFSx(_ilistdir_it_t) { mp_obj_base_t base; mp_fun_1_t iternext; bool is_str; MP_OBJ_VFS_LFSx *vfs; LFSx_API(dir_t) dir; } MP_VFS_LFSx(ilistdir_it_t); STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { MP_VFS_LFSx(ilistdir_it_t) *self = MP_OBJ_TO_PTR(self_in); struct LFSx_API(info) info; for (;;) { int ret = LFSx_API(dir_read)(&self->vfs->lfs, &self->dir, &info); if (ret == 0) { LFSx_API(dir_close)(&self->vfs->lfs, &self->dir); return MP_OBJ_STOP_ITERATION; } if (!(info.name[0] == '.' && (info.name[1] == '\0' || (info.name[1] == '.' && info.name[2] == '\0')))) { break; } } // make 4-tuple with info about this entry mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); if (self->is_str) { t->items[0] = mp_obj_new_str(info.name, strlen(info.name)); } else { t->items[0] = mp_obj_new_bytes((const byte*)info.name, strlen(info.name)); } t->items[1] = MP_OBJ_NEW_SMALL_INT(info.type == LFSx_MACRO(_TYPE_REG) ? MP_S_IFREG : MP_S_IFDIR); t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number t->items[3] = MP_OBJ_NEW_SMALL_INT(info.size); return MP_OBJ_FROM_PTR(t); } STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(args[0]); bool is_str_type = true; const char *path; if (n_args == 2) { if (mp_obj_get_type(args[1]) == &mp_type_bytes) { is_str_type = false; } path = MP_VFS_LFSx(make_path)(self, args[1]); } else { path = vstr_null_terminated_str(&self->cur_dir); } MP_VFS_LFSx(ilistdir_it_t) *iter = m_new_obj(MP_VFS_LFSx(ilistdir_it_t)); iter->base.type = &mp_type_polymorph_iter; iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext); iter->is_str = is_str_type; iter->vfs = self; int ret = LFSx_API(dir_open)(&self->lfs, &iter->dir, path); if (ret < 0) { mp_raise_OSError(-ret); } return MP_OBJ_FROM_PTR(iter); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(ilistdir_obj), 1, 2, MP_VFS_LFSx(ilistdir_func)); STATIC mp_obj_t MP_VFS_LFSx(remove)(mp_obj_t self_in, mp_obj_t path_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path = MP_VFS_LFSx(make_path)(self, path_in); int ret = LFSx_API(remove)(&self->lfs, path); if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(remove_obj), MP_VFS_LFSx(remove)); STATIC mp_obj_t MP_VFS_LFSx(rmdir)(mp_obj_t self_in, mp_obj_t path_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path = MP_VFS_LFSx(make_path)(self, path_in); int ret = LFSx_API(remove)(&self->lfs, path); if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(rmdir_obj), MP_VFS_LFSx(rmdir)); STATIC mp_obj_t MP_VFS_LFSx(rename)(mp_obj_t self_in, mp_obj_t path_old_in, mp_obj_t path_new_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path_old = MP_VFS_LFSx(make_path)(self, path_old_in); vstr_t path_new; vstr_init(&path_new, vstr_len(&self->cur_dir)); vstr_add_strn(&path_new, vstr_str(&self->cur_dir), vstr_len(&self->cur_dir)); vstr_add_str(&path_new, mp_obj_str_get_str(path_new_in)); int ret = LFSx_API(rename)(&self->lfs, path_old, vstr_null_terminated_str(&path_new)); vstr_clear(&path_new); if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(rename_obj), MP_VFS_LFSx(rename)); STATIC mp_obj_t MP_VFS_LFSx(mkdir)(mp_obj_t self_in, mp_obj_t path_o) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path = MP_VFS_LFSx(make_path)(self, path_o); int ret = LFSx_API(mkdir)(&self->lfs, path); if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(mkdir_obj), MP_VFS_LFSx(mkdir)); STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); // Check path exists const char *path = MP_VFS_LFSx(make_path)(self, path_in); if (path[1] != '\0') { // Not at root, check it exists struct LFSx_API(info) info; int ret = LFSx_API(stat)(&self->lfs, path, &info); if (ret < 0 || info.type != LFSx_MACRO(_TYPE_DIR)) { mp_raise_OSError(-MP_ENOENT); } } // Update cur_dir with new path if (path == vstr_str(&self->cur_dir)) { self->cur_dir.len = strlen(path); } else { vstr_reset(&self->cur_dir); vstr_add_str(&self->cur_dir, path); } // If not at root add trailing / to make it easy to build paths if (vstr_len(&self->cur_dir) != 1) { vstr_add_byte(&self->cur_dir, '/'); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(chdir_obj), MP_VFS_LFSx(chdir)); STATIC mp_obj_t MP_VFS_LFSx(getcwd)(mp_obj_t self_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); if (vstr_len(&self->cur_dir) == 1) { return MP_OBJ_NEW_QSTR(MP_QSTR__slash_); } else { // don't include trailing / return mp_obj_new_str(self->cur_dir.buf, self->cur_dir.len - 1); } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(MP_VFS_LFSx(getcwd_obj), MP_VFS_LFSx(getcwd)); STATIC mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path = mp_obj_str_get_str(path_in); struct LFSx_API(info) info; int ret = LFSx_API(stat)(&self->lfs, path, &info); if (ret < 0) { mp_raise_OSError(-ret); } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(info.type == LFSx_MACRO(_TYPE_REG) ? MP_S_IFREG : MP_S_IFDIR); // st_mode t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid t->items[6] = mp_obj_new_int_from_uint(info.size); // st_size t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // st_atime t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // st_mtime t->items[9] = MP_OBJ_NEW_SMALL_INT(0); // st_ctime return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(stat_obj), MP_VFS_LFSx(stat)); STATIC int LFSx_API(traverse_cb)(void *data, LFSx_API(block_t) bl) { (void)bl; uint32_t *n = (uint32_t*)data; *n += 1; return LFSx_MACRO(_ERR_OK); } STATIC mp_obj_t MP_VFS_LFSx(statvfs)(mp_obj_t self_in, mp_obj_t path_in) { (void)path_in; MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); uint32_t n_used_blocks = 0; #if LFS_BUILD_VERSION == 1 int ret = LFSx_API(traverse)(&self->lfs, LFSx_API(traverse_cb), &n_used_blocks); #else int ret = LFSx_API(fs_traverse)(&self->lfs, LFSx_API(traverse_cb), &n_used_blocks); #endif if (ret < 0) { mp_raise_OSError(-ret); } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(self->lfs.cfg->block_size); // f_bsize t->items[1] = t->items[0]; // f_frsize t->items[2] = MP_OBJ_NEW_SMALL_INT(self->lfs.cfg->block_count); // f_blocks t->items[3] = MP_OBJ_NEW_SMALL_INT(self->lfs.cfg->block_count - n_used_blocks); // f_bfree t->items[4] = t->items[3]; // f_bavail t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags t->items[9] = MP_OBJ_NEW_SMALL_INT(LFSx_MACRO(_NAME_MAX)); // f_namemax return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(statvfs_obj), MP_VFS_LFSx(statvfs)); STATIC mp_obj_t MP_VFS_LFSx(mount)(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { (void)self_in; (void)readonly; (void)mkfs; // already called LFSx_API(mount) in MP_VFS_LFSx(make_new) return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(mount_obj), MP_VFS_LFSx(mount)); STATIC mp_obj_t MP_VFS_LFSx(umount)(mp_obj_t self_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); // LFS unmount never fails LFSx_API(unmount)(&self->lfs); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(MP_VFS_LFSx(umount_obj), MP_VFS_LFSx(umount)); STATIC const mp_rom_map_elem_t MP_VFS_LFSx(locals_dict_table)[] = { { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&MP_VFS_LFSx(mkfs_obj)) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&MP_VFS_LFSx(open_obj)) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&MP_VFS_LFSx(ilistdir_obj)) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&MP_VFS_LFSx(mkdir_obj)) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&MP_VFS_LFSx(rmdir_obj)) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&MP_VFS_LFSx(chdir_obj)) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&MP_VFS_LFSx(getcwd_obj)) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&MP_VFS_LFSx(remove_obj)) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&MP_VFS_LFSx(rename_obj)) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&MP_VFS_LFSx(stat_obj)) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&MP_VFS_LFSx(statvfs_obj)) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&MP_VFS_LFSx(mount_obj)) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&MP_VFS_LFSx(umount_obj)) }, }; STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(locals_dict), MP_VFS_LFSx(locals_dict_table)); STATIC mp_import_stat_t MP_VFS_LFSx(import_stat)(void *self_in, const char *path) { MP_OBJ_VFS_LFSx *self = self_in; struct LFSx_API(info) info; int ret = LFSx_API(stat)(&self->lfs, path, &info); if (ret == 0) { if (info.type == LFSx_MACRO(_TYPE_REG)) { return MP_IMPORT_STAT_FILE; } else { return MP_IMPORT_STAT_DIR; } } return MP_IMPORT_STAT_NO_EXIST; } STATIC const mp_vfs_proto_t MP_VFS_LFSx(proto) = { .import_stat = MP_VFS_LFSx(import_stat), }; const mp_obj_type_t MP_TYPE_VFS_LFSx = { { &mp_type_type }, #if LFS_BUILD_VERSION == 1 .name = MP_QSTR_VfsLfs1, #else .name = MP_QSTR_VfsLfs2, #endif .make_new = MP_VFS_LFSx(make_new), .protocol = &MP_VFS_LFSx(proto), .locals_dict = (mp_obj_dict_t*)&MP_VFS_LFSx(locals_dict), }; micropython-1.12/extmod/vfs_lfsx_file.c000066400000000000000000000205151357706137100203220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "extmod/vfs.h" STATIC void MP_VFS_LFSx(check_open)(MP_OBJ_VFS_LFSx_FILE *self) { if (self->vfs == NULL) { mp_raise_ValueError(NULL); } } STATIC void MP_VFS_LFSx(file_print)(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)self_in; (void)kind; mp_printf(print, "", mp_obj_get_type_str(self_in)); } mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); int flags = 0; const mp_obj_type_t *type = &MP_TYPE_VFS_LFSx_(_textio); const char *mode_str = mp_obj_str_get_str(mode_in); for (; *mode_str; ++mode_str) { int new_flags = 0; switch (*mode_str) { case 'r': new_flags = LFSx_MACRO(_O_RDONLY); break; case 'w': new_flags = LFSx_MACRO(_O_WRONLY) | LFSx_MACRO(_O_CREAT) | LFSx_MACRO(_O_TRUNC); break; case 'x': new_flags = LFSx_MACRO(_O_WRONLY) | LFSx_MACRO(_O_CREAT) | LFSx_MACRO(_O_EXCL); break; case 'a': new_flags = LFSx_MACRO(_O_WRONLY) | LFSx_MACRO(_O_CREAT) | LFSx_MACRO(_O_APPEND); break; case '+': flags |= LFSx_MACRO(_O_RDWR); break; #if MICROPY_PY_IO_FILEIO case 'b': type = &MP_TYPE_VFS_LFSx_(_fileio); break; #endif case 't': type = &MP_TYPE_VFS_LFSx_(_textio); break; } if (new_flags) { if (flags) { mp_raise_ValueError(NULL); } flags = new_flags; } } if (flags == 0) { flags = LFSx_MACRO(_O_RDONLY); } #if LFS_BUILD_VERSION == 1 MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->prog_size); #else MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->cache_size); #endif o->base.type = type; o->vfs = self; #if !MICROPY_GC_CONSERVATIVE_CLEAR memset(&o->file, 0, sizeof(o->file)); memset(&o->cfg, 0, sizeof(o->cfg)); #endif o->cfg.buffer = &o->file_buffer[0]; const char *path = MP_VFS_LFSx(make_path)(self, path_in); int ret = LFSx_API(file_opencfg)(&self->lfs, &o->file, path, flags, &o->cfg); if (ret < 0) { o->vfs = NULL; mp_raise_OSError(-ret); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t MP_VFS_LFSx(file___exit__)(size_t n_args, const mp_obj_t *args) { (void)n_args; return mp_stream_close(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(file___exit___obj), 4, 4, MP_VFS_LFSx(file___exit__)); STATIC mp_uint_t MP_VFS_LFSx(file_read)(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); MP_VFS_LFSx(check_open)(self); LFSx_API(ssize_t) sz = LFSx_API(file_read)(&self->vfs->lfs, &self->file, buf, size); if (sz < 0) { *errcode = -sz; return MP_STREAM_ERROR; } return sz; } STATIC mp_uint_t MP_VFS_LFSx(file_write)(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); MP_VFS_LFSx(check_open)(self); LFSx_API(ssize_t) sz = LFSx_API(file_write)(&self->vfs->lfs, &self->file, buf, size); if (sz < 0) { *errcode = -sz; return MP_STREAM_ERROR; } return sz; } STATIC mp_uint_t MP_VFS_LFSx(file_ioctl)(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); if (request != MP_STREAM_CLOSE) { MP_VFS_LFSx(check_open)(self); } if (request == MP_STREAM_SEEK) { struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)(uintptr_t)arg; int res = LFSx_API(file_seek)(&self->vfs->lfs, &self->file, s->offset, s->whence); if (res < 0) { *errcode = -res; return MP_STREAM_ERROR; } res = LFSx_API(file_tell)(&self->vfs->lfs, &self->file); if (res < 0) { *errcode = -res; return MP_STREAM_ERROR; } s->offset = res; return 0; } else if (request == MP_STREAM_FLUSH) { int res = LFSx_API(file_sync)(&self->vfs->lfs, &self->file); if (res < 0) { *errcode = -res; return MP_STREAM_ERROR; } return 0; } else if (request == MP_STREAM_CLOSE) { if (self->vfs == NULL) { return 0; } int res = LFSx_API(file_close)(&self->vfs->lfs, &self->file); self->vfs = NULL; // indicate a closed file if (res < 0) { *errcode = -res; return MP_STREAM_ERROR; } return 0; } else { *errcode = MP_EINVAL; return MP_STREAM_ERROR; } } STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&MP_VFS_LFSx(file___exit___obj)) }, }; STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table)); #if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = { .read = MP_VFS_LFSx(file_read), .write = MP_VFS_LFSx(file_write), .ioctl = MP_VFS_LFSx(file_ioctl), }; const mp_obj_type_t MP_TYPE_VFS_LFSx_(_fileio) = { { &mp_type_type }, .name = MP_QSTR_FileIO, .print = MP_VFS_LFSx(file_print), .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &MP_VFS_LFSx(fileio_stream_p), .locals_dict = (mp_obj_dict_t*)&MP_VFS_LFSx(file_locals_dict), }; #endif STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { .read = MP_VFS_LFSx(file_read), .write = MP_VFS_LFSx(file_write), .ioctl = MP_VFS_LFSx(file_ioctl), .is_text = true, }; const mp_obj_type_t MP_TYPE_VFS_LFSx_(_textio) = { { &mp_type_type }, .name = MP_QSTR_TextIOWrapper, .print = MP_VFS_LFSx(file_print), .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &MP_VFS_LFSx(textio_stream_p), .locals_dict = (mp_obj_dict_t*)&MP_VFS_LFSx(file_locals_dict), }; micropython-1.12/extmod/vfs_posix.c000066400000000000000000000313521357706137100175120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/vfs.h" #include "extmod/vfs_posix.h" #if MICROPY_VFS_POSIX #include #include #include #include typedef struct _mp_obj_vfs_posix_t { mp_obj_base_t base; vstr_t root; size_t root_len; bool readonly; } mp_obj_vfs_posix_t; STATIC const char *vfs_posix_get_path_str(mp_obj_vfs_posix_t *self, mp_obj_t path) { if (self->root_len == 0) { return mp_obj_str_get_str(path); } else { self->root.len = self->root_len; vstr_add_str(&self->root, mp_obj_str_get_str(path)); return vstr_null_terminated_str(&self->root); } } STATIC mp_obj_t vfs_posix_get_path_obj(mp_obj_vfs_posix_t *self, mp_obj_t path) { if (self->root_len == 0) { return path; } else { self->root.len = self->root_len; vstr_add_str(&self->root, mp_obj_str_get_str(path)); return mp_obj_new_str(self->root.buf, self->root.len); } } STATIC mp_obj_t vfs_posix_fun1_helper(mp_obj_t self_in, mp_obj_t path_in, int (*f)(const char*)) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); int ret = f(vfs_posix_get_path_str(self, path_in)); if (ret != 0) { mp_raise_OSError(errno); } return mp_const_none; } STATIC mp_import_stat_t mp_vfs_posix_import_stat(void *self_in, const char *path) { mp_obj_vfs_posix_t *self = self_in; if (self->root_len != 0) { self->root.len = self->root_len; vstr_add_str(&self->root, path); path = vstr_null_terminated_str(&self->root); } struct stat st; if (stat(path, &st) == 0) { if (S_ISDIR(st.st_mode)) { return MP_IMPORT_STAT_DIR; } else if (S_ISREG(st.st_mode)) { return MP_IMPORT_STAT_FILE; } } return MP_IMPORT_STAT_NO_EXIST; } STATIC mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_vfs_posix_t *vfs = m_new_obj(mp_obj_vfs_posix_t); vfs->base.type = type; vstr_init(&vfs->root, 0); if (n_args == 1) { vstr_add_str(&vfs->root, mp_obj_str_get_str(args[0])); vstr_add_char(&vfs->root, '/'); } vfs->root_len = vfs->root.len; vfs->readonly = false; return MP_OBJ_FROM_PTR(vfs); } STATIC mp_obj_t vfs_posix_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); if (mp_obj_is_true(readonly)) { self->readonly = true; } if (mp_obj_is_true(mkfs)) { mp_raise_OSError(MP_EPERM); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_mount_obj, vfs_posix_mount); STATIC mp_obj_t vfs_posix_umount(mp_obj_t self_in) { (void)self_in; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_umount_obj, vfs_posix_umount); STATIC mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *mode = mp_obj_str_get_str(mode_in); if (self->readonly && (strchr(mode, 'w') != NULL || strchr(mode, 'a') != NULL || strchr(mode, '+') != NULL)) { mp_raise_OSError(MP_EROFS); } if (!mp_obj_is_small_int(path_in)) { path_in = vfs_posix_get_path_obj(self, path_in); } return mp_vfs_posix_file_open(&mp_type_textio, path_in, mode_in); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_open_obj, vfs_posix_open); STATIC mp_obj_t vfs_posix_chdir(mp_obj_t self_in, mp_obj_t path_in) { return vfs_posix_fun1_helper(self_in, path_in, chdir); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_chdir_obj, vfs_posix_chdir); STATIC mp_obj_t vfs_posix_getcwd(mp_obj_t self_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); char buf[MICROPY_ALLOC_PATH_MAX + 1]; const char *ret = getcwd(buf, sizeof(buf)); if (ret == NULL) { mp_raise_OSError(errno); } ret += self->root_len; return mp_obj_new_str(ret, strlen(ret)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd); typedef struct _vfs_posix_ilistdir_it_t { mp_obj_base_t base; mp_fun_1_t iternext; bool is_str; DIR *dir; } vfs_posix_ilistdir_it_t; STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { vfs_posix_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->dir == NULL) { return MP_OBJ_STOP_ITERATION; } for (;;) { struct dirent *dirent = readdir(self->dir); if (dirent == NULL) { closedir(self->dir); self->dir = NULL; return MP_OBJ_STOP_ITERATION; } const char *fn = dirent->d_name; if (fn[0] == '.' && (fn[1] == 0 || fn[1] == '.')) { // skip . and .. continue; } // make 3-tuple with info about this entry mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); if (self->is_str) { t->items[0] = mp_obj_new_str(fn, strlen(fn)); } else { t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn)); } #ifdef _DIRENT_HAVE_D_TYPE #ifdef DTTOIF t->items[1] = MP_OBJ_NEW_SMALL_INT(DTTOIF(dirent->d_type)); #else if (dirent->d_type == DT_DIR) { t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); } else if (dirent->d_type == DT_REG) { t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG); } else { t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type); } #endif #else // DT_UNKNOWN should have 0 value on any reasonable system t->items[1] = MP_OBJ_NEW_SMALL_INT(0); #endif #ifdef _DIRENT_HAVE_D_INO t->items[2] = MP_OBJ_NEW_SMALL_INT(dirent->d_ino); #else t->items[2] = MP_OBJ_NEW_SMALL_INT(0); #endif return MP_OBJ_FROM_PTR(t); } } STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); vfs_posix_ilistdir_it_t *iter = m_new_obj(vfs_posix_ilistdir_it_t); iter->base.type = &mp_type_polymorph_iter; iter->iternext = vfs_posix_ilistdir_it_iternext; iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; const char *path = vfs_posix_get_path_str(self, path_in); if (path[0] == '\0') { path = "."; } iter->dir = opendir(path); if (iter->dir == NULL) { mp_raise_OSError(errno); } return MP_OBJ_FROM_PTR(iter); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_ilistdir_obj, vfs_posix_ilistdir); typedef struct _mp_obj_listdir_t { mp_obj_base_t base; mp_fun_1_t iternext; DIR *dir; } mp_obj_listdir_t; STATIC mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); int ret = mkdir(vfs_posix_get_path_str(self, path_in), 0777); if (ret != 0) { mp_raise_OSError(errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_mkdir_obj, vfs_posix_mkdir); STATIC mp_obj_t vfs_posix_remove(mp_obj_t self_in, mp_obj_t path_in) { return vfs_posix_fun1_helper(self_in, path_in, unlink); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_remove_obj, vfs_posix_remove); STATIC mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_t new_path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *old_path = vfs_posix_get_path_str(self, old_path_in); const char *new_path = vfs_posix_get_path_str(self, new_path_in); int ret = rename(old_path, new_path); if (ret != 0) { mp_raise_OSError(errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_rename_obj, vfs_posix_rename); STATIC mp_obj_t vfs_posix_rmdir(mp_obj_t self_in, mp_obj_t path_in) { return vfs_posix_fun1_helper(self_in, path_in, rmdir); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_rmdir_obj, vfs_posix_rmdir); STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); struct stat sb; int ret = stat(vfs_posix_get_path_str(self, path_in), &sb); if (ret != 0) { mp_raise_OSError(errno); } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.st_mode); t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.st_ino); t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.st_dev); t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.st_nlink); t->items[4] = MP_OBJ_NEW_SMALL_INT(sb.st_uid); t->items[5] = MP_OBJ_NEW_SMALL_INT(sb.st_gid); t->items[6] = MP_OBJ_NEW_SMALL_INT(sb.st_size); t->items[7] = MP_OBJ_NEW_SMALL_INT(sb.st_atime); t->items[8] = MP_OBJ_NEW_SMALL_INT(sb.st_mtime); t->items[9] = MP_OBJ_NEW_SMALL_INT(sb.st_ctime); return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat); #ifdef __ANDROID__ #define USE_STATFS 1 #endif #if USE_STATFS #include #define STRUCT_STATVFS struct statfs #define STATVFS statfs #define F_FAVAIL sb.f_ffree #define F_NAMEMAX sb.f_namelen #define F_FLAG sb.f_flags #else #include #define STRUCT_STATVFS struct statvfs #define STATVFS statvfs #define F_FAVAIL sb.f_favail #define F_NAMEMAX sb.f_namemax #define F_FLAG sb.f_flag #endif STATIC mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); STRUCT_STATVFS sb; const char *path = vfs_posix_get_path_str(self, path_in); int ret = STATVFS(path, &sb); if (ret != 0) { mp_raise_OSError(errno); } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.f_bsize); t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.f_frsize); t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.f_blocks); t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.f_bfree); t->items[4] = MP_OBJ_NEW_SMALL_INT(sb.f_bavail); t->items[5] = MP_OBJ_NEW_SMALL_INT(sb.f_files); t->items[6] = MP_OBJ_NEW_SMALL_INT(sb.f_ffree); t->items[7] = MP_OBJ_NEW_SMALL_INT(F_FAVAIL); t->items[8] = MP_OBJ_NEW_SMALL_INT(F_FLAG); t->items[9] = MP_OBJ_NEW_SMALL_INT(F_NAMEMAX); return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_statvfs_obj, vfs_posix_statvfs); STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_posix_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&vfs_posix_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&vfs_posix_open_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&vfs_posix_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&vfs_posix_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&vfs_posix_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&vfs_posix_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&vfs_posix_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&vfs_posix_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&vfs_posix_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_posix_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_posix_statvfs_obj) }, }; STATIC MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table); STATIC const mp_vfs_proto_t vfs_posix_proto = { .import_stat = mp_vfs_posix_import_stat, }; const mp_obj_type_t mp_type_vfs_posix = { { &mp_type_type }, .name = MP_QSTR_VfsPosix, .make_new = vfs_posix_make_new, .protocol = &vfs_posix_proto, .locals_dict = (mp_obj_dict_t*)&vfs_posix_locals_dict, }; #endif // MICROPY_VFS_POSIX micropython-1.12/extmod/vfs_posix.h000066400000000000000000000031651357706137100175200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H #define MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H #include "py/lexer.h" #include "py/obj.h" extern const mp_obj_type_t mp_type_vfs_posix; extern const mp_obj_type_t mp_type_vfs_posix_fileio; extern const mp_obj_type_t mp_type_vfs_posix_textio; mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in); #endif // MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H micropython-1.12/extmod/vfs_posix_file.c000066400000000000000000000216321357706137100205110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/stream.h" #include "extmod/vfs_posix.h" #if MICROPY_VFS_POSIX #include #ifdef _WIN32 #define fsync _commit #endif typedef struct _mp_obj_vfs_posix_file_t { mp_obj_base_t base; int fd; } mp_obj_vfs_posix_file_t; #ifdef MICROPY_CPYTHON_COMPAT STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { if (o->fd < 0) { mp_raise_msg(&mp_type_ValueError, "I/O operation on closed file"); } } #else #define check_fd_is_open(o) #endif STATIC void vfs_posix_file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", mp_obj_get_type_str(self_in), self->fd); } mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) { mp_obj_vfs_posix_file_t *o = m_new_obj(mp_obj_vfs_posix_file_t); const char *mode_s = mp_obj_str_get_str(mode_in); int mode_rw = 0, mode_x = 0; while (*mode_s) { switch (*mode_s++) { case 'r': mode_rw = O_RDONLY; break; case 'w': mode_rw = O_WRONLY; mode_x = O_CREAT | O_TRUNC; break; case 'a': mode_rw = O_WRONLY; mode_x = O_CREAT | O_APPEND; break; case '+': mode_rw = O_RDWR; break; #if MICROPY_PY_IO_FILEIO // If we don't have io.FileIO, then files are in text mode implicitly case 'b': type = &mp_type_vfs_posix_fileio; break; case 't': type = &mp_type_vfs_posix_textio; break; #endif } } o->base.type = type; mp_obj_t fid = file_in; if (mp_obj_is_small_int(fid)) { o->fd = MP_OBJ_SMALL_INT_VALUE(fid); return MP_OBJ_FROM_PTR(o); } const char *fname = mp_obj_str_get_str(fid); int fd = open(fname, mode_x | mode_rw, 0644); if (fd == -1) { mp_raise_OSError(errno); } o->fd = fd; return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t vfs_posix_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} }, }; mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals); return mp_vfs_posix_file_open(type, arg_vals[0].u_obj, arg_vals[1].u_obj); } STATIC mp_obj_t vfs_posix_file_fileno(mp_obj_t self_in) { mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in); check_fd_is_open(self); return MP_OBJ_NEW_SMALL_INT(self->fd); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_file_fileno_obj, vfs_posix_file_fileno); STATIC mp_obj_t vfs_posix_file___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; return mp_stream_close(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vfs_posix_file___exit___obj, 4, 4, vfs_posix_file___exit__); STATIC mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); mp_int_t r = read(o->fd, buf, size); if (r == -1) { *errcode = errno; return MP_STREAM_ERROR; } return r; } STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); #if MICROPY_PY_OS_DUPTERM if (o->fd <= STDERR_FILENO) { mp_hal_stdout_tx_strn(buf, size); return size; } #endif mp_int_t r = write(o->fd, buf, size); while (r == -1 && errno == EINTR) { if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } r = write(o->fd, buf, size); } if (r == -1) { *errcode = errno; return MP_STREAM_ERROR; } return r; } STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); switch (request) { case MP_STREAM_FLUSH: if (fsync(o->fd) < 0) { *errcode = errno; return MP_STREAM_ERROR; } return 0; case MP_STREAM_SEEK: { struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg; off_t off = lseek(o->fd, s->offset, s->whence); if (off == (off_t)-1) { *errcode = errno; return MP_STREAM_ERROR; } s->offset = off; return 0; } case MP_STREAM_CLOSE: close(o->fd); #ifdef MICROPY_CPYTHON_COMPAT o->fd = -1; #endif return 0; default: *errcode = EINVAL; return MP_STREAM_ERROR; } } STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&vfs_posix_file_fileno_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_posix_file___exit___obj) }, }; STATIC MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table); #if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = { .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, }; const mp_obj_type_t mp_type_vfs_posix_fileio = { { &mp_type_type }, .name = MP_QSTR_FileIO, .print = vfs_posix_file_print, .make_new = vfs_posix_file_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &vfs_posix_fileio_stream_p, .locals_dict = (mp_obj_dict_t*)&vfs_posix_rawfile_locals_dict, }; #endif STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, .is_text = true, }; const mp_obj_type_t mp_type_vfs_posix_textio = { { &mp_type_type }, .name = MP_QSTR_TextIOWrapper, .print = vfs_posix_file_print, .make_new = vfs_posix_file_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &vfs_posix_textio_stream_p, .locals_dict = (mp_obj_dict_t*)&vfs_posix_rawfile_locals_dict, }; const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_textio}, STDIN_FILENO}; const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_textio}, STDOUT_FILENO}; const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_textio}, STDERR_FILENO}; #endif // MICROPY_VFS_POSIX micropython-1.12/extmod/vfs_reader.c000066400000000000000000000057331357706137100176160ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/reader.h" #include "extmod/vfs.h" #if MICROPY_READER_VFS typedef struct _mp_reader_vfs_t { mp_obj_t file; uint16_t len; uint16_t pos; byte buf[24]; } mp_reader_vfs_t; STATIC mp_uint_t mp_reader_vfs_readbyte(void *data) { mp_reader_vfs_t *reader = (mp_reader_vfs_t*)data; if (reader->pos >= reader->len) { if (reader->len < sizeof(reader->buf)) { return MP_READER_EOF; } else { int errcode; reader->len = mp_stream_rw(reader->file, reader->buf, sizeof(reader->buf), &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); if (errcode != 0) { // TODO handle errors properly return MP_READER_EOF; } if (reader->len == 0) { return MP_READER_EOF; } reader->pos = 0; } } return reader->buf[reader->pos++]; } STATIC void mp_reader_vfs_close(void *data) { mp_reader_vfs_t *reader = (mp_reader_vfs_t*)data; mp_stream_close(reader->file); m_del_obj(mp_reader_vfs_t, reader); } void mp_reader_new_file(mp_reader_t *reader, const char *filename) { mp_reader_vfs_t *rf = m_new_obj(mp_reader_vfs_t); mp_obj_t arg = mp_obj_new_str(filename, strlen(filename)); rf->file = mp_vfs_open(1, &arg, (mp_map_t*)&mp_const_empty_map); int errcode; rf->len = mp_stream_rw(rf->file, rf->buf, sizeof(rf->buf), &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); if (errcode != 0) { mp_raise_OSError(errcode); } rf->pos = 0; reader->data = rf; reader->readbyte = mp_reader_vfs_readbyte; reader->close = mp_reader_vfs_close; } #endif // MICROPY_READER_VFS micropython-1.12/extmod/virtpin.c000066400000000000000000000032241357706137100171620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "extmod/virtpin.h" int mp_virtual_pin_read(mp_obj_t pin) { mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin); mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->protocol; return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL); } void mp_virtual_pin_write(mp_obj_t pin, int value) { mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin); mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->protocol; pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL); } micropython-1.12/extmod/virtpin.h000066400000000000000000000035451357706137100171750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_EXTMOD_VIRTPIN_H #define MICROPY_INCLUDED_EXTMOD_VIRTPIN_H #include "py/obj.h" #define MP_PIN_READ (1) #define MP_PIN_WRITE (2) #define MP_PIN_INPUT (3) #define MP_PIN_OUTPUT (4) // Pin protocol typedef struct _mp_pin_p_t { mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode); } mp_pin_p_t; int mp_virtual_pin_read(mp_obj_t pin); void mp_virtual_pin_write(mp_obj_t pin, int value); // If a port exposes a Pin object, it's constructor should be like this mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); #endif // MICROPY_INCLUDED_EXTMOD_VIRTPIN_H micropython-1.12/extmod/webrepl/000077500000000000000000000000001357706137100167625ustar00rootroot00000000000000micropython-1.12/extmod/webrepl/manifest.py000066400000000000000000000001101357706137100211320ustar00rootroot00000000000000freeze('.', ('webrepl.py', 'webrepl_setup.py', 'websocket_helper.py',)) micropython-1.12/extmod/webrepl/webrepl.py000066400000000000000000000042101357706137100207710ustar00rootroot00000000000000# This module should be imported from REPL, not run from command line. import socket import uos import network import uwebsocket import websocket_helper import _webrepl listen_s = None client_s = None def setup_conn(port, accept_handler): global listen_s listen_s = socket.socket() listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ai = socket.getaddrinfo("0.0.0.0", port) addr = ai[0][4] listen_s.bind(addr) listen_s.listen(1) if accept_handler: listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler) for i in (network.AP_IF, network.STA_IF): iface = network.WLAN(i) if iface.active(): print("WebREPL daemon started on ws://%s:%d" % (iface.ifconfig()[0], port)) return listen_s def accept_conn(listen_sock): global client_s cl, remote_addr = listen_sock.accept() prev = uos.dupterm(None) uos.dupterm(prev) if prev: print("\nConcurrent WebREPL connection from", remote_addr, "rejected") cl.close() return print("\nWebREPL connection from:", remote_addr) client_s = cl websocket_helper.server_handshake(cl) ws = uwebsocket.websocket(cl, True) ws = _webrepl._webrepl(ws) cl.setblocking(False) # notify REPL on socket incoming data (ESP32/ESP8266-only) if hasattr(uos, 'dupterm_notify'): cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify) uos.dupterm(ws) def stop(): global listen_s, client_s uos.dupterm(None) if client_s: client_s.close() if listen_s: listen_s.close() def start(port=8266, password=None): stop() if password is None: try: import webrepl_cfg _webrepl.password(webrepl_cfg.PASS) setup_conn(port, accept_conn) print("Started webrepl in normal mode") except: print("WebREPL is not configured, run 'import webrepl_setup'") else: _webrepl.password(password) setup_conn(port, accept_conn) print("Started webrepl in manual override mode") def start_foreground(port=8266): stop() s = setup_conn(port, None) accept_conn(s) micropython-1.12/extmod/webrepl/webrepl_setup.py000066400000000000000000000052741357706137100222240ustar00rootroot00000000000000import sys #import uos as os import os import machine RC = "./boot.py" CONFIG = "./webrepl_cfg.py" def input_choice(prompt, choices): while 1: resp = input(prompt) if resp in choices: return resp def getpass(prompt): return input(prompt) def input_pass(): while 1: passwd1 = getpass("New password (4-9 chars): ") if len(passwd1) < 4 or len(passwd1) > 9: print("Invalid password length") continue passwd2 = getpass("Confirm password: ") if passwd1 == passwd2: return passwd1 print("Passwords do not match") def exists(fname): try: with open(fname): pass return True except OSError: return False def get_daemon_status(): with open(RC) as f: for l in f: if "webrepl" in l: if l.startswith("#"): return False return True return None def change_daemon(action): LINES = ("import webrepl", "webrepl.start()") with open(RC) as old_f, open(RC + ".tmp", "w") as new_f: found = False for l in old_f: for patt in LINES: if patt in l: found = True if action and l.startswith("#"): l = l[1:] elif not action and not l.startswith("#"): l = "#" + l new_f.write(l) if not found: new_f.write("import webrepl\nwebrepl.start()\n") # FatFs rename() is not POSIX compliant, will raise OSError if # dest file exists. os.remove(RC) os.rename(RC + ".tmp", RC) def main(): status = get_daemon_status() print("WebREPL daemon auto-start status:", "enabled" if status else "disabled") print("\nWould you like to (E)nable or (D)isable it running on boot?") print("(Empty line to quit)") resp = input("> ").upper() if resp == "E": if exists(CONFIG): resp2 = input_choice("Would you like to change WebREPL password? (y/n) ", ("y", "n", "")) else: print("To enable WebREPL, you must set password for it") resp2 = "y" if resp2 == "y": passwd = input_pass() with open(CONFIG, "w") as f: f.write("PASS = %r\n" % passwd) if resp not in ("D", "E") or (resp == "D" and not status) or (resp == "E" and status): print("No further action required") sys.exit() change_daemon(resp == "E") print("Changes will be activated after reboot") resp = input_choice("Would you like to reboot now? (y/n) ", ("y", "n", "")) if resp == "y": machine.reset() main() micropython-1.12/extmod/webrepl/websocket_helper.py000066400000000000000000000031301357706137100226560ustar00rootroot00000000000000import sys try: import ubinascii as binascii except: import binascii try: import uhashlib as hashlib except: import hashlib DEBUG = 0 def server_handshake(sock): clr = sock.makefile("rwb", 0) l = clr.readline() #sys.stdout.write(repr(l)) webkey = None while 1: l = clr.readline() if not l: raise OSError("EOF in headers") if l == b"\r\n": break # sys.stdout.write(l) h, v = [x.strip() for x in l.split(b":", 1)] if DEBUG: print((h, v)) if h == b'Sec-WebSocket-Key': webkey = v if not webkey: raise OSError("Not a websocket request") if DEBUG: print("Sec-WebSocket-Key:", webkey, len(webkey)) d = hashlib.sha1(webkey) d.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11") respkey = d.digest() respkey = binascii.b2a_base64(respkey)[:-1] if DEBUG: print("respkey:", respkey) sock.send(b"""\ HTTP/1.1 101 Switching Protocols\r Upgrade: websocket\r Connection: Upgrade\r Sec-WebSocket-Accept: """) sock.send(respkey) sock.send("\r\n\r\n") # Very simplified client handshake, works for MicroPython's # websocket server implementation, but probably not for other # servers. def client_handshake(sock): cl = sock.makefile("rwb", 0) cl.write(b"""\ GET / HTTP/1.1\r Host: echo.websocket.org\r Connection: Upgrade\r Upgrade: websocket\r Sec-WebSocket-Key: foo\r \r """) l = cl.readline() # print(l) while 1: l = cl.readline() if l == b"\r\n": break # sys.stdout.write(l) micropython-1.12/lib/000077500000000000000000000000001357706137100145705ustar00rootroot00000000000000micropython-1.12/lib/README.md000066400000000000000000000002111357706137100160410ustar00rootroot00000000000000This directory contains standard, low-level C libraries with emphasis on being independent and efficient. They can be used by any port. micropython-1.12/lib/asf4/000077500000000000000000000000001357706137100154255ustar00rootroot00000000000000micropython-1.12/lib/axtls/000077500000000000000000000000001357706137100157235ustar00rootroot00000000000000micropython-1.12/lib/berkeley-db-1.xx/000077500000000000000000000000001357706137100175515ustar00rootroot00000000000000micropython-1.12/lib/cmsis/000077500000000000000000000000001357706137100157065ustar00rootroot00000000000000micropython-1.12/lib/cmsis/inc/000077500000000000000000000000001357706137100164575ustar00rootroot00000000000000micropython-1.12/lib/cmsis/inc/cmsis_armcc.h000066400000000000000000000655501357706137100211260ustar00rootroot00000000000000/**************************************************************************//** * @file cmsis_armcc.h * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file * @version V5.0.5 * @date 14. December 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CMSIS_ARMCC_H #define __CMSIS_ARMCC_H #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) #error "Please use Arm Compiler Toolchain V4.0.677 or later!" #endif /* CMSIS compiler control architecture macros */ #if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \ (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) ) #define __ARM_ARCH_6M__ 1 #endif #if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1)) #define __ARM_ARCH_7M__ 1 #endif #if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1)) #define __ARM_ARCH_7EM__ 1 #endif /* __ARM_ARCH_8M_BASE__ not applicable */ /* __ARM_ARCH_8M_MAIN__ not applicable */ /* CMSIS compiler control DSP macros */ #if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) #define __ARM_FEATURE_DSP 1 #endif /* CMSIS compiler specific defines */ #ifndef __ASM #define __ASM __asm #endif #ifndef __INLINE #define __INLINE __inline #endif #ifndef __STATIC_INLINE #define __STATIC_INLINE static __inline #endif #ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE static __forceinline #endif #ifndef __NO_RETURN #define __NO_RETURN __declspec(noreturn) #endif #ifndef __USED #define __USED __attribute__((used)) #endif #ifndef __WEAK #define __WEAK __attribute__((weak)) #endif #ifndef __PACKED #define __PACKED __attribute__((packed)) #endif #ifndef __PACKED_STRUCT #define __PACKED_STRUCT __packed struct #endif #ifndef __PACKED_UNION #define __PACKED_UNION __packed union #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) #endif #ifndef __UNALIGNED_UINT16_WRITE #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val)) #endif #ifndef __UNALIGNED_UINT16_READ #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr))) #endif #ifndef __UNALIGNED_UINT32_WRITE #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val)) #endif #ifndef __UNALIGNED_UINT32_READ #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr))) #endif #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif #ifndef __RESTRICT #define __RESTRICT __restrict #endif /* ########################### Core Function Access ########################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions @{ */ /** \brief Enable IRQ Interrupts \details Enables IRQ interrupts by clearing the I-bit in the CPSR. Can only be executed in Privileged modes. */ /* intrinsic void __enable_irq(); */ /** \brief Disable IRQ Interrupts \details Disables IRQ interrupts by setting the I-bit in the CPSR. Can only be executed in Privileged modes. */ /* intrinsic void __disable_irq(); */ /** \brief Get Control Register \details Returns the content of the Control Register. \return Control Register value */ __STATIC_INLINE uint32_t __get_CONTROL(void) { register uint32_t __regControl __ASM("control"); return(__regControl); } /** \brief Set Control Register \details Writes the given value to the Control Register. \param [in] control Control Register value to set */ __STATIC_INLINE void __set_CONTROL(uint32_t control) { register uint32_t __regControl __ASM("control"); __regControl = control; } /** \brief Get IPSR Register \details Returns the content of the IPSR Register. \return IPSR Register value */ __STATIC_INLINE uint32_t __get_IPSR(void) { register uint32_t __regIPSR __ASM("ipsr"); return(__regIPSR); } /** \brief Get APSR Register \details Returns the content of the APSR Register. \return APSR Register value */ __STATIC_INLINE uint32_t __get_APSR(void) { register uint32_t __regAPSR __ASM("apsr"); return(__regAPSR); } /** \brief Get xPSR Register \details Returns the content of the xPSR Register. \return xPSR Register value */ __STATIC_INLINE uint32_t __get_xPSR(void) { register uint32_t __regXPSR __ASM("xpsr"); return(__regXPSR); } /** \brief Get Process Stack Pointer \details Returns the current value of the Process Stack Pointer (PSP). \return PSP Register value */ __STATIC_INLINE uint32_t __get_PSP(void) { register uint32_t __regProcessStackPointer __ASM("psp"); return(__regProcessStackPointer); } /** \brief Set Process Stack Pointer \details Assigns the given value to the Process Stack Pointer (PSP). \param [in] topOfProcStack Process Stack Pointer value to set */ __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) { register uint32_t __regProcessStackPointer __ASM("psp"); __regProcessStackPointer = topOfProcStack; } /** \brief Get Main Stack Pointer \details Returns the current value of the Main Stack Pointer (MSP). \return MSP Register value */ __STATIC_INLINE uint32_t __get_MSP(void) { register uint32_t __regMainStackPointer __ASM("msp"); return(__regMainStackPointer); } /** \brief Set Main Stack Pointer \details Assigns the given value to the Main Stack Pointer (MSP). \param [in] topOfMainStack Main Stack Pointer value to set */ __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) { register uint32_t __regMainStackPointer __ASM("msp"); __regMainStackPointer = topOfMainStack; } /** \brief Get Priority Mask \details Returns the current state of the priority mask bit from the Priority Mask Register. \return Priority Mask value */ __STATIC_INLINE uint32_t __get_PRIMASK(void) { register uint32_t __regPriMask __ASM("primask"); return(__regPriMask); } /** \brief Set Priority Mask \details Assigns the given value to the Priority Mask Register. \param [in] priMask Priority Mask */ __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) { register uint32_t __regPriMask __ASM("primask"); __regPriMask = (priMask); } #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) /** \brief Enable FIQ \details Enables FIQ interrupts by clearing the F-bit in the CPSR. Can only be executed in Privileged modes. */ #define __enable_fault_irq __enable_fiq /** \brief Disable FIQ \details Disables FIQ interrupts by setting the F-bit in the CPSR. Can only be executed in Privileged modes. */ #define __disable_fault_irq __disable_fiq /** \brief Get Base Priority \details Returns the current value of the Base Priority register. \return Base Priority register value */ __STATIC_INLINE uint32_t __get_BASEPRI(void) { register uint32_t __regBasePri __ASM("basepri"); return(__regBasePri); } /** \brief Set Base Priority \details Assigns the given value to the Base Priority register. \param [in] basePri Base Priority value to set */ __STATIC_INLINE void __set_BASEPRI(uint32_t basePri) { register uint32_t __regBasePri __ASM("basepri"); __regBasePri = (basePri & 0xFFU); } /** \brief Set Base Priority with condition \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, or the new value increases the BASEPRI priority level. \param [in] basePri Base Priority value to set */ __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) { register uint32_t __regBasePriMax __ASM("basepri_max"); __regBasePriMax = (basePri & 0xFFU); } /** \brief Get Fault Mask \details Returns the current value of the Fault Mask register. \return Fault Mask register value */ __STATIC_INLINE uint32_t __get_FAULTMASK(void) { register uint32_t __regFaultMask __ASM("faultmask"); return(__regFaultMask); } /** \brief Set Fault Mask \details Assigns the given value to the Fault Mask register. \param [in] faultMask Fault Mask value to set */ __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) { register uint32_t __regFaultMask __ASM("faultmask"); __regFaultMask = (faultMask & (uint32_t)1U); } #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ /** \brief Get FPSCR \details Returns the current value of the Floating Point Status/Control register. \return Floating Point Status/Control register value */ __STATIC_INLINE uint32_t __get_FPSCR(void) { #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) register uint32_t __regfpscr __ASM("fpscr"); return(__regfpscr); #else return(0U); #endif } /** \brief Set FPSCR \details Assigns the given value to the Floating Point Status/Control register. \param [in] fpscr Floating Point Status/Control value to set */ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) { #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) register uint32_t __regfpscr __ASM("fpscr"); __regfpscr = (fpscr); #else (void)fpscr; #endif } /*@} end of CMSIS_Core_RegAccFunctions */ /* ########################## Core Instruction Access ######################### */ /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface Access to dedicated instructions @{ */ /** \brief No Operation \details No Operation does nothing. This instruction can be used for code alignment purposes. */ #define __NOP __nop /** \brief Wait For Interrupt \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. */ #define __WFI __wfi /** \brief Wait For Event \details Wait For Event is a hint instruction that permits the processor to enter a low-power state until one of a number of events occurs. */ #define __WFE __wfe /** \brief Send Event \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. */ #define __SEV __sev /** \brief Instruction Synchronization Barrier \details Instruction Synchronization Barrier flushes the pipeline in the processor, so that all instructions following the ISB are fetched from cache or memory, after the instruction has been completed. */ #define __ISB() do {\ __schedule_barrier();\ __isb(0xF);\ __schedule_barrier();\ } while (0U) /** \brief Data Synchronization Barrier \details Acts as a special kind of Data Memory Barrier. It completes when all explicit memory accesses before this instruction complete. */ #define __DSB() do {\ __schedule_barrier();\ __dsb(0xF);\ __schedule_barrier();\ } while (0U) /** \brief Data Memory Barrier \details Ensures the apparent order of the explicit memory operations before and after the instruction, without ensuring their completion. */ #define __DMB() do {\ __schedule_barrier();\ __dmb(0xF);\ __schedule_barrier();\ } while (0U) /** \brief Reverse byte order (32 bit) \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. \param [in] value Value to reverse \return Reversed value */ #define __REV __rev /** \brief Reverse byte order (16 bit) \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. \param [in] value Value to reverse \return Reversed value */ #ifndef __NO_EMBEDDED_ASM __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) { rev16 r0, r0 bx lr } #endif /** \brief Reverse byte order (16 bit) \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. \param [in] value Value to reverse \return Reversed value */ #ifndef __NO_EMBEDDED_ASM __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value) { revsh r0, r0 bx lr } #endif /** \brief Rotate Right in unsigned value (32 bit) \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. \param [in] op1 Value to rotate \param [in] op2 Number of Bits to rotate \return Rotated value */ #define __ROR __ror /** \brief Breakpoint \details Causes the processor to enter Debug state. Debug tools can use this to investigate system state when the instruction at a particular address is reached. \param [in] value is ignored by the processor. If required, a debugger can use it to store additional information about the breakpoint. */ #define __BKPT(value) __breakpoint(value) /** \brief Reverse bit order of value \details Reverses the bit order of the given value. \param [in] value Value to reverse \return Reversed value */ #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) #define __RBIT __rbit #else __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) { uint32_t result; uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ result = value; /* r will be reversed bits of v; first get LSB of v */ for (value >>= 1U; value != 0U; value >>= 1U) { result <<= 1U; result |= value & 1U; s--; } result <<= s; /* shift when v's highest bits are zero */ return result; } #endif /** \brief Count leading zeros \details Counts the number of leading zeros of a data value. \param [in] value Value to count the leading zeros \return number of leading zeros in value */ #define __CLZ __clz #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) /** \brief LDR Exclusive (8 bit) \details Executes a exclusive LDR instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) #else #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") #endif /** \brief LDR Exclusive (16 bit) \details Executes a exclusive LDR instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) #else #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") #endif /** \brief LDR Exclusive (32 bit) \details Executes a exclusive LDR instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) #else #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") #endif /** \brief STR Exclusive (8 bit) \details Executes a exclusive STR instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) #define __STREXB(value, ptr) __strex(value, ptr) #else #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") #endif /** \brief STR Exclusive (16 bit) \details Executes a exclusive STR instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) #define __STREXH(value, ptr) __strex(value, ptr) #else #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") #endif /** \brief STR Exclusive (32 bit) \details Executes a exclusive STR instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) #define __STREXW(value, ptr) __strex(value, ptr) #else #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") #endif /** \brief Remove the exclusive lock \details Removes the exclusive lock which is created by LDREX. */ #define __CLREX __clrex /** \brief Signed Saturate \details Saturates a signed value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (1..32) \return Saturated value */ #define __SSAT __ssat /** \brief Unsigned Saturate \details Saturates an unsigned value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (0..31) \return Saturated value */ #define __USAT __usat /** \brief Rotate Right with Extend (32 bit) \details Moves each bit of a bitstring right by one bit. The carry input is shifted in at the left end of the bitstring. \param [in] value Value to rotate \return Rotated value */ #ifndef __NO_EMBEDDED_ASM __attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) { rrx r0, r0 bx lr } #endif /** \brief LDRT Unprivileged (8 bit) \details Executes a Unprivileged LDRT instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ #define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) /** \brief LDRT Unprivileged (16 bit) \details Executes a Unprivileged LDRT instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ #define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) /** \brief LDRT Unprivileged (32 bit) \details Executes a Unprivileged LDRT instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ #define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) /** \brief STRT Unprivileged (8 bit) \details Executes a Unprivileged STRT instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ #define __STRBT(value, ptr) __strt(value, ptr) /** \brief STRT Unprivileged (16 bit) \details Executes a Unprivileged STRT instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ #define __STRHT(value, ptr) __strt(value, ptr) /** \brief STRT Unprivileged (32 bit) \details Executes a Unprivileged STRT instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ #define __STRT(value, ptr) __strt(value, ptr) #else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ /** \brief Signed Saturate \details Saturates a signed value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (1..32) \return Saturated value */ __attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) { if ((sat >= 1U) && (sat <= 32U)) { const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); const int32_t min = -1 - max ; if (val > max) { return max; } else if (val < min) { return min; } } return val; } /** \brief Unsigned Saturate \details Saturates an unsigned value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (0..31) \return Saturated value */ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) { if (sat <= 31U) { const uint32_t max = ((1U << sat) - 1U); if (val > (int32_t)max) { return max; } else if (val < 0) { return 0U; } } return (uint32_t)val; } #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ /* ################### Compiler specific Intrinsics ########################### */ /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics Access to dedicated SIMD instructions @{ */ #if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) #define __SADD8 __sadd8 #define __QADD8 __qadd8 #define __SHADD8 __shadd8 #define __UADD8 __uadd8 #define __UQADD8 __uqadd8 #define __UHADD8 __uhadd8 #define __SSUB8 __ssub8 #define __QSUB8 __qsub8 #define __SHSUB8 __shsub8 #define __USUB8 __usub8 #define __UQSUB8 __uqsub8 #define __UHSUB8 __uhsub8 #define __SADD16 __sadd16 #define __QADD16 __qadd16 #define __SHADD16 __shadd16 #define __UADD16 __uadd16 #define __UQADD16 __uqadd16 #define __UHADD16 __uhadd16 #define __SSUB16 __ssub16 #define __QSUB16 __qsub16 #define __SHSUB16 __shsub16 #define __USUB16 __usub16 #define __UQSUB16 __uqsub16 #define __UHSUB16 __uhsub16 #define __SASX __sasx #define __QASX __qasx #define __SHASX __shasx #define __UASX __uasx #define __UQASX __uqasx #define __UHASX __uhasx #define __SSAX __ssax #define __QSAX __qsax #define __SHSAX __shsax #define __USAX __usax #define __UQSAX __uqsax #define __UHSAX __uhsax #define __USAD8 __usad8 #define __USADA8 __usada8 #define __SSAT16 __ssat16 #define __USAT16 __usat16 #define __UXTB16 __uxtb16 #define __UXTAB16 __uxtab16 #define __SXTB16 __sxtb16 #define __SXTAB16 __sxtab16 #define __SMUAD __smuad #define __SMUADX __smuadx #define __SMLAD __smlad #define __SMLADX __smladx #define __SMLALD __smlald #define __SMLALDX __smlaldx #define __SMUSD __smusd #define __SMUSDX __smusdx #define __SMLSD __smlsd #define __SMLSDX __smlsdx #define __SMLSLD __smlsld #define __SMLSLDX __smlsldx #define __SEL __sel #define __QADD __qadd #define __QSUB __qsub #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) #define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ ((int64_t)(ARG3) << 32U) ) >> 32U)) #endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ /*@} end of group CMSIS_SIMD_intrinsics */ #endif /* __CMSIS_ARMCC_H */ micropython-1.12/lib/cmsis/inc/cmsis_armclang.h000066400000000000000000001303021357706137100216110ustar00rootroot00000000000000/**************************************************************************//** * @file cmsis_armclang.h * @brief CMSIS compiler armclang (Arm Compiler 6) header file * @version V5.1.0 * @date 14. March 2019 ******************************************************************************/ /* * Copyright (c) 2009-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ #ifndef __CMSIS_ARMCLANG_H #define __CMSIS_ARMCLANG_H #pragma clang system_header /* treat file as system include file */ #ifndef __ARM_COMPAT_H #include /* Compatibility header for Arm Compiler 5 intrinsics */ #endif /* CMSIS compiler specific defines */ #ifndef __ASM #define __ASM __asm #endif #ifndef __INLINE #define __INLINE __inline #endif #ifndef __STATIC_INLINE #define __STATIC_INLINE static __inline #endif #ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline #endif #ifndef __NO_RETURN #define __NO_RETURN __attribute__((__noreturn__)) #endif #ifndef __USED #define __USED __attribute__((used)) #endif #ifndef __WEAK #define __WEAK __attribute__((weak)) #endif #ifndef __PACKED #define __PACKED __attribute__((packed, aligned(1))) #endif #ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #endif #ifndef __PACKED_UNION #define __PACKED_UNION union __attribute__((packed, aligned(1))) #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ struct __attribute__((packed)) T_UINT32 { uint32_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #endif #ifndef __UNALIGNED_UINT16_WRITE #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT16_READ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) #endif #ifndef __UNALIGNED_UINT32_WRITE #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT32_READ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) #endif #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif #ifndef __RESTRICT #define __RESTRICT __restrict #endif /* ########################### Core Function Access ########################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions @{ */ /** \brief Enable IRQ Interrupts \details Enables IRQ interrupts by clearing the I-bit in the CPSR. Can only be executed in Privileged modes. */ /* intrinsic void __enable_irq(); see arm_compat.h */ /** \brief Disable IRQ Interrupts \details Disables IRQ interrupts by setting the I-bit in the CPSR. Can only be executed in Privileged modes. */ /* intrinsic void __disable_irq(); see arm_compat.h */ /** \brief Get Control Register \details Returns the content of the Control Register. \return Control Register value */ __STATIC_FORCEINLINE uint32_t __get_CONTROL(void) { uint32_t result; __ASM volatile ("MRS %0, control" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Control Register (non-secure) \details Returns the content of the non-secure Control Register when in secure mode. \return non-secure Control Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) { uint32_t result; __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Control Register \details Writes the given value to the Control Register. \param [in] control Control Register value to set */ __STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) { __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Control Register (non-secure) \details Writes the given value to the non-secure Control Register when in secure state. \param [in] control Control Register value to set */ __STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) { __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); } #endif /** \brief Get IPSR Register \details Returns the content of the IPSR Register. \return IPSR Register value */ __STATIC_FORCEINLINE uint32_t __get_IPSR(void) { uint32_t result; __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); return(result); } /** \brief Get APSR Register \details Returns the content of the APSR Register. \return APSR Register value */ __STATIC_FORCEINLINE uint32_t __get_APSR(void) { uint32_t result; __ASM volatile ("MRS %0, apsr" : "=r" (result) ); return(result); } /** \brief Get xPSR Register \details Returns the content of the xPSR Register. \return xPSR Register value */ __STATIC_FORCEINLINE uint32_t __get_xPSR(void) { uint32_t result; __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); return(result); } /** \brief Get Process Stack Pointer \details Returns the current value of the Process Stack Pointer (PSP). \return PSP Register value */ __STATIC_FORCEINLINE uint32_t __get_PSP(void) { uint32_t result; __ASM volatile ("MRS %0, psp" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Process Stack Pointer (non-secure) \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. \return PSP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Process Stack Pointer \details Assigns the given value to the Process Stack Pointer (PSP). \param [in] topOfProcStack Process Stack Pointer value to set */ __STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) { __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Process Stack Pointer (non-secure) \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. \param [in] topOfProcStack Process Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); } #endif /** \brief Get Main Stack Pointer \details Returns the current value of the Main Stack Pointer (MSP). \return MSP Register value */ __STATIC_FORCEINLINE uint32_t __get_MSP(void) { uint32_t result; __ASM volatile ("MRS %0, msp" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Main Stack Pointer (non-secure) \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. \return MSP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Main Stack Pointer \details Assigns the given value to the Main Stack Pointer (MSP). \param [in] topOfMainStack Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) { __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Main Stack Pointer (non-secure) \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. \param [in] topOfMainStack Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) { __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); } #endif #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Stack Pointer (non-secure) \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. \return SP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); return(result); } /** \brief Set Stack Pointer (non-secure) \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. \param [in] topOfStack Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) { __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); } #endif /** \brief Get Priority Mask \details Returns the current state of the priority mask bit from the Priority Mask Register. \return Priority Mask value */ __STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) { uint32_t result; __ASM volatile ("MRS %0, primask" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Priority Mask (non-secure) \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. \return Priority Mask value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) { uint32_t result; __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Priority Mask \details Assigns the given value to the Priority Mask Register. \param [in] priMask Priority Mask */ __STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) { __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Priority Mask (non-secure) \details Assigns the given value to the non-secure Priority Mask Register when in secure state. \param [in] priMask Priority Mask */ __STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) { __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); } #endif #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Enable FIQ \details Enables FIQ interrupts by clearing the F-bit in the CPSR. Can only be executed in Privileged modes. */ #define __enable_fault_irq __enable_fiq /* see arm_compat.h */ /** \brief Disable FIQ \details Disables FIQ interrupts by setting the F-bit in the CPSR. Can only be executed in Privileged modes. */ #define __disable_fault_irq __disable_fiq /* see arm_compat.h */ /** \brief Get Base Priority \details Returns the current value of the Base Priority register. \return Base Priority register value */ __STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) { uint32_t result; __ASM volatile ("MRS %0, basepri" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Base Priority (non-secure) \details Returns the current value of the non-secure Base Priority register when in secure state. \return Base Priority register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) { uint32_t result; __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Base Priority \details Assigns the given value to the Base Priority register. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Base Priority (non-secure) \details Assigns the given value to the non-secure Base Priority register when in secure state. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) { __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); } #endif /** \brief Set Base Priority with condition \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, or the new value increases the BASEPRI priority level. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) { __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); } /** \brief Get Fault Mask \details Returns the current value of the Fault Mask register. \return Fault Mask register value */ __STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) { uint32_t result; __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Fault Mask (non-secure) \details Returns the current value of the non-secure Fault Mask register when in secure state. \return Fault Mask register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) { uint32_t result; __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Fault Mask \details Assigns the given value to the Fault Mask register. \param [in] faultMask Fault Mask value to set */ __STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) { __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Fault Mask (non-secure) \details Assigns the given value to the non-secure Fault Mask register when in secure state. \param [in] faultMask Fault Mask value to set */ __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) { __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); } #endif #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief Get Process Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always in non-secure mode. \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). \return PSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, psplim" : "=r" (result) ); return result; #endif } #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Process Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always in non-secure mode. \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. \return PSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure PSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); return result; #endif } #endif /** \brief Set Process Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored in non-secure mode. \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI (void)ProcStackPtrLimit; #else __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Process Stack Pointer (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored in non-secure mode. \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure PSPLIM is RAZ/WI (void)ProcStackPtrLimit; #else __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); #endif } #endif /** \brief Get Main Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always. \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). \return MSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, msplim" : "=r" (result) ); return result; #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Main Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always. \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. \return MSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure MSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); return result; #endif } #endif /** \brief Set Main Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored. \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI (void)MainStackPtrLimit; #else __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Main Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored. \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. \param [in] MainStackPtrLimit Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure MSPLIM is RAZ/WI (void)MainStackPtrLimit; #else __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); #endif } #endif #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /** \brief Get FPSCR \details Returns the current value of the Floating Point Status/Control register. \return Floating Point Status/Control register value */ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) #define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr #else #define __get_FPSCR() ((uint32_t)0U) #endif /** \brief Set FPSCR \details Assigns the given value to the Floating Point Status/Control register. \param [in] fpscr Floating Point Status/Control value to set */ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) #define __set_FPSCR __builtin_arm_set_fpscr #else #define __set_FPSCR(x) ((void)(x)) #endif /*@} end of CMSIS_Core_RegAccFunctions */ /* ########################## Core Instruction Access ######################### */ /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface Access to dedicated instructions @{ */ /* Define macros for porting to both thumb1 and thumb2. * For thumb1, use low register (r0-r7), specified by constraint "l" * Otherwise, use general registers, specified by constraint "r" */ #if defined (__thumb__) && !defined (__thumb2__) #define __CMSIS_GCC_OUT_REG(r) "=l" (r) #define __CMSIS_GCC_RW_REG(r) "+l" (r) #define __CMSIS_GCC_USE_REG(r) "l" (r) #else #define __CMSIS_GCC_OUT_REG(r) "=r" (r) #define __CMSIS_GCC_RW_REG(r) "+r" (r) #define __CMSIS_GCC_USE_REG(r) "r" (r) #endif /** \brief No Operation \details No Operation does nothing. This instruction can be used for code alignment purposes. */ #define __NOP __builtin_arm_nop /** \brief Wait For Interrupt \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. */ #define __WFI __builtin_arm_wfi /** \brief Wait For Event \details Wait For Event is a hint instruction that permits the processor to enter a low-power state until one of a number of events occurs. */ #define __WFE __builtin_arm_wfe /** \brief Send Event \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. */ #define __SEV __builtin_arm_sev /** \brief Instruction Synchronization Barrier \details Instruction Synchronization Barrier flushes the pipeline in the processor, so that all instructions following the ISB are fetched from cache or memory, after the instruction has been completed. */ #define __ISB() __builtin_arm_isb(0xF) /** \brief Data Synchronization Barrier \details Acts as a special kind of Data Memory Barrier. It completes when all explicit memory accesses before this instruction complete. */ #define __DSB() __builtin_arm_dsb(0xF) /** \brief Data Memory Barrier \details Ensures the apparent order of the explicit memory operations before and after the instruction, without ensuring their completion. */ #define __DMB() __builtin_arm_dmb(0xF) /** \brief Reverse byte order (32 bit) \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. \param [in] value Value to reverse \return Reversed value */ #define __REV(value) __builtin_bswap32(value) /** \brief Reverse byte order (16 bit) \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. \param [in] value Value to reverse \return Reversed value */ #define __REV16(value) __ROR(__REV(value), 16) /** \brief Reverse byte order (16 bit) \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. \param [in] value Value to reverse \return Reversed value */ #define __REVSH(value) (int16_t)__builtin_bswap16(value) /** \brief Rotate Right in unsigned value (32 bit) \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. \param [in] op1 Value to rotate \param [in] op2 Number of Bits to rotate \return Rotated value */ __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { op2 %= 32U; if (op2 == 0U) { return op1; } return (op1 >> op2) | (op1 << (32U - op2)); } /** \brief Breakpoint \details Causes the processor to enter Debug state. Debug tools can use this to investigate system state when the instruction at a particular address is reached. \param [in] value is ignored by the processor. If required, a debugger can use it to store additional information about the breakpoint. */ #define __BKPT(value) __ASM volatile ("bkpt "#value) /** \brief Reverse bit order of value \details Reverses the bit order of the given value. \param [in] value Value to reverse \return Reversed value */ #define __RBIT __builtin_arm_rbit /** \brief Count leading zeros \details Counts the number of leading zeros of a data value. \param [in] value Value to count the leading zeros \return number of leading zeros in value */ __STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) { /* Even though __builtin_clz produces a CLZ instruction on ARM, formally __builtin_clz(0) is undefined behaviour, so handle this case specially. This guarantees ARM-compatible results if happening to compile on a non-ARM target, and ensures the compiler doesn't decide to activate any optimisations using the logic "value was passed to __builtin_clz, so it is non-zero". ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a single CLZ instruction. */ if (value == 0U) { return 32U; } return __builtin_clz(value); } #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief LDR Exclusive (8 bit) \details Executes a exclusive LDR instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ #define __LDREXB (uint8_t)__builtin_arm_ldrex /** \brief LDR Exclusive (16 bit) \details Executes a exclusive LDR instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ #define __LDREXH (uint16_t)__builtin_arm_ldrex /** \brief LDR Exclusive (32 bit) \details Executes a exclusive LDR instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ #define __LDREXW (uint32_t)__builtin_arm_ldrex /** \brief STR Exclusive (8 bit) \details Executes a exclusive STR instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STREXB (uint32_t)__builtin_arm_strex /** \brief STR Exclusive (16 bit) \details Executes a exclusive STR instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STREXH (uint32_t)__builtin_arm_strex /** \brief STR Exclusive (32 bit) \details Executes a exclusive STR instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STREXW (uint32_t)__builtin_arm_strex /** \brief Remove the exclusive lock \details Removes the exclusive lock which is created by LDREX. */ #define __CLREX __builtin_arm_clrex #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Signed Saturate \details Saturates a signed value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (1..32) \return Saturated value */ #define __SSAT __builtin_arm_ssat /** \brief Unsigned Saturate \details Saturates an unsigned value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (0..31) \return Saturated value */ #define __USAT __builtin_arm_usat /** \brief Rotate Right with Extend (32 bit) \details Moves each bit of a bitstring right by one bit. The carry input is shifted in at the left end of the bitstring. \param [in] value Value to rotate \return Rotated value */ __STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) { uint32_t result; __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return(result); } /** \brief LDRT Unprivileged (8 bit) \details Executes a Unprivileged LDRT instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ __STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) { uint32_t result; __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint8_t) result); /* Add explicit type cast here */ } /** \brief LDRT Unprivileged (16 bit) \details Executes a Unprivileged LDRT instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ __STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) { uint32_t result; __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint16_t) result); /* Add explicit type cast here */ } /** \brief LDRT Unprivileged (32 bit) \details Executes a Unprivileged LDRT instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ __STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) { uint32_t result; __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } /** \brief STRT Unprivileged (8 bit) \details Executes a Unprivileged STRT instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief STRT Unprivileged (16 bit) \details Executes a Unprivileged STRT instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief STRT Unprivileged (32 bit) \details Executes a Unprivileged STRT instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) { __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); } #else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ /** \brief Signed Saturate \details Saturates a signed value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (1..32) \return Saturated value */ __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) { if ((sat >= 1U) && (sat <= 32U)) { const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); const int32_t min = -1 - max ; if (val > max) { return max; } else if (val < min) { return min; } } return val; } /** \brief Unsigned Saturate \details Saturates an unsigned value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (0..31) \return Saturated value */ __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) { if (sat <= 31U) { const uint32_t max = ((1U << sat) - 1U); if (val > (int32_t)max) { return max; } else if (val < 0) { return 0U; } } return (uint32_t)val; } #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief Load-Acquire (8 bit) \details Executes a LDAB instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ __STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) { uint32_t result; __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint8_t) result); } /** \brief Load-Acquire (16 bit) \details Executes a LDAH instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ __STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) { uint32_t result; __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint16_t) result); } /** \brief Load-Acquire (32 bit) \details Executes a LDA instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ __STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) { uint32_t result; __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } /** \brief Store-Release (8 bit) \details Executes a STLB instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Store-Release (16 bit) \details Executes a STLH instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) { __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Store-Release (32 bit) \details Executes a STL instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) { __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Load-Acquire Exclusive (8 bit) \details Executes a LDAB exclusive instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ #define __LDAEXB (uint8_t)__builtin_arm_ldaex /** \brief Load-Acquire Exclusive (16 bit) \details Executes a LDAH exclusive instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ #define __LDAEXH (uint16_t)__builtin_arm_ldaex /** \brief Load-Acquire Exclusive (32 bit) \details Executes a LDA exclusive instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ #define __LDAEX (uint32_t)__builtin_arm_ldaex /** \brief Store-Release Exclusive (8 bit) \details Executes a STLB exclusive instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STLEXB (uint32_t)__builtin_arm_stlex /** \brief Store-Release Exclusive (16 bit) \details Executes a STLH exclusive instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STLEXH (uint32_t)__builtin_arm_stlex /** \brief Store-Release Exclusive (32 bit) \details Executes a STL exclusive instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STLEX (uint32_t)__builtin_arm_stlex #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ /* ################### Compiler specific Intrinsics ########################### */ /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics Access to dedicated SIMD instructions @{ */ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) #define __SADD8 __builtin_arm_sadd8 #define __QADD8 __builtin_arm_qadd8 #define __SHADD8 __builtin_arm_shadd8 #define __UADD8 __builtin_arm_uadd8 #define __UQADD8 __builtin_arm_uqadd8 #define __UHADD8 __builtin_arm_uhadd8 #define __SSUB8 __builtin_arm_ssub8 #define __QSUB8 __builtin_arm_qsub8 #define __SHSUB8 __builtin_arm_shsub8 #define __USUB8 __builtin_arm_usub8 #define __UQSUB8 __builtin_arm_uqsub8 #define __UHSUB8 __builtin_arm_uhsub8 #define __SADD16 __builtin_arm_sadd16 #define __QADD16 __builtin_arm_qadd16 #define __SHADD16 __builtin_arm_shadd16 #define __UADD16 __builtin_arm_uadd16 #define __UQADD16 __builtin_arm_uqadd16 #define __UHADD16 __builtin_arm_uhadd16 #define __SSUB16 __builtin_arm_ssub16 #define __QSUB16 __builtin_arm_qsub16 #define __SHSUB16 __builtin_arm_shsub16 #define __USUB16 __builtin_arm_usub16 #define __UQSUB16 __builtin_arm_uqsub16 #define __UHSUB16 __builtin_arm_uhsub16 #define __SASX __builtin_arm_sasx #define __QASX __builtin_arm_qasx #define __SHASX __builtin_arm_shasx #define __UASX __builtin_arm_uasx #define __UQASX __builtin_arm_uqasx #define __UHASX __builtin_arm_uhasx #define __SSAX __builtin_arm_ssax #define __QSAX __builtin_arm_qsax #define __SHSAX __builtin_arm_shsax #define __USAX __builtin_arm_usax #define __UQSAX __builtin_arm_uqsax #define __UHSAX __builtin_arm_uhsax #define __USAD8 __builtin_arm_usad8 #define __USADA8 __builtin_arm_usada8 #define __SSAT16 __builtin_arm_ssat16 #define __USAT16 __builtin_arm_usat16 #define __UXTB16 __builtin_arm_uxtb16 #define __UXTAB16 __builtin_arm_uxtab16 #define __SXTB16 __builtin_arm_sxtb16 #define __SXTAB16 __builtin_arm_sxtab16 #define __SMUAD __builtin_arm_smuad #define __SMUADX __builtin_arm_smuadx #define __SMLAD __builtin_arm_smlad #define __SMLADX __builtin_arm_smladx #define __SMLALD __builtin_arm_smlald #define __SMLALDX __builtin_arm_smlaldx #define __SMUSD __builtin_arm_smusd #define __SMUSDX __builtin_arm_smusdx #define __SMLSD __builtin_arm_smlsd #define __SMLSDX __builtin_arm_smlsdx #define __SMLSLD __builtin_arm_smlsld #define __SMLSLDX __builtin_arm_smlsldx #define __SEL __builtin_arm_sel #define __QADD __builtin_arm_qadd #define __QSUB __builtin_arm_qsub #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) { int32_t result; __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); return(result); } #endif /* (__ARM_FEATURE_DSP == 1) */ /*@} end of group CMSIS_SIMD_intrinsics */ #endif /* __CMSIS_ARMCLANG_H */ micropython-1.12/lib/cmsis/inc/cmsis_armclang_ltm.h000066400000000000000000001524561357706137100225030ustar00rootroot00000000000000/**************************************************************************//** * @file cmsis_armclang_ltm.h * @brief CMSIS compiler armclang (Arm Compiler 6) header file * @version V1.0.1 * @date 19. March 2019 ******************************************************************************/ /* * Copyright (c) 2018-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ #ifndef __CMSIS_ARMCLANG_H #define __CMSIS_ARMCLANG_H #pragma clang system_header /* treat file as system include file */ #ifndef __ARM_COMPAT_H #include /* Compatibility header for Arm Compiler 5 intrinsics */ #endif /* CMSIS compiler specific defines */ #ifndef __ASM #define __ASM __asm #endif #ifndef __INLINE #define __INLINE __inline #endif #ifndef __STATIC_INLINE #define __STATIC_INLINE static __inline #endif #ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline #endif #ifndef __NO_RETURN #define __NO_RETURN __attribute__((__noreturn__)) #endif #ifndef __USED #define __USED __attribute__((used)) #endif #ifndef __WEAK #define __WEAK __attribute__((weak)) #endif #ifndef __PACKED #define __PACKED __attribute__((packed, aligned(1))) #endif #ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #endif #ifndef __PACKED_UNION #define __PACKED_UNION union __attribute__((packed, aligned(1))) #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ struct __attribute__((packed)) T_UINT32 { uint32_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #endif #ifndef __UNALIGNED_UINT16_WRITE #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT16_READ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) #endif #ifndef __UNALIGNED_UINT32_WRITE #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT32_READ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpacked" /*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) #endif #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif #ifndef __RESTRICT #define __RESTRICT __restrict #endif /* ########################### Core Function Access ########################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions @{ */ /** \brief Enable IRQ Interrupts \details Enables IRQ interrupts by clearing the I-bit in the CPSR. Can only be executed in Privileged modes. */ /* intrinsic void __enable_irq(); see arm_compat.h */ /** \brief Disable IRQ Interrupts \details Disables IRQ interrupts by setting the I-bit in the CPSR. Can only be executed in Privileged modes. */ /* intrinsic void __disable_irq(); see arm_compat.h */ /** \brief Get Control Register \details Returns the content of the Control Register. \return Control Register value */ __STATIC_FORCEINLINE uint32_t __get_CONTROL(void) { uint32_t result; __ASM volatile ("MRS %0, control" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Control Register (non-secure) \details Returns the content of the non-secure Control Register when in secure mode. \return non-secure Control Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) { uint32_t result; __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Control Register \details Writes the given value to the Control Register. \param [in] control Control Register value to set */ __STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) { __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Control Register (non-secure) \details Writes the given value to the non-secure Control Register when in secure state. \param [in] control Control Register value to set */ __STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) { __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); } #endif /** \brief Get IPSR Register \details Returns the content of the IPSR Register. \return IPSR Register value */ __STATIC_FORCEINLINE uint32_t __get_IPSR(void) { uint32_t result; __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); return(result); } /** \brief Get APSR Register \details Returns the content of the APSR Register. \return APSR Register value */ __STATIC_FORCEINLINE uint32_t __get_APSR(void) { uint32_t result; __ASM volatile ("MRS %0, apsr" : "=r" (result) ); return(result); } /** \brief Get xPSR Register \details Returns the content of the xPSR Register. \return xPSR Register value */ __STATIC_FORCEINLINE uint32_t __get_xPSR(void) { uint32_t result; __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); return(result); } /** \brief Get Process Stack Pointer \details Returns the current value of the Process Stack Pointer (PSP). \return PSP Register value */ __STATIC_FORCEINLINE uint32_t __get_PSP(void) { uint32_t result; __ASM volatile ("MRS %0, psp" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Process Stack Pointer (non-secure) \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. \return PSP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Process Stack Pointer \details Assigns the given value to the Process Stack Pointer (PSP). \param [in] topOfProcStack Process Stack Pointer value to set */ __STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) { __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Process Stack Pointer (non-secure) \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. \param [in] topOfProcStack Process Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); } #endif /** \brief Get Main Stack Pointer \details Returns the current value of the Main Stack Pointer (MSP). \return MSP Register value */ __STATIC_FORCEINLINE uint32_t __get_MSP(void) { uint32_t result; __ASM volatile ("MRS %0, msp" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Main Stack Pointer (non-secure) \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. \return MSP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Main Stack Pointer \details Assigns the given value to the Main Stack Pointer (MSP). \param [in] topOfMainStack Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) { __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Main Stack Pointer (non-secure) \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. \param [in] topOfMainStack Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) { __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); } #endif #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Stack Pointer (non-secure) \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. \return SP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); return(result); } /** \brief Set Stack Pointer (non-secure) \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. \param [in] topOfStack Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) { __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); } #endif /** \brief Get Priority Mask \details Returns the current state of the priority mask bit from the Priority Mask Register. \return Priority Mask value */ __STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) { uint32_t result; __ASM volatile ("MRS %0, primask" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Priority Mask (non-secure) \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. \return Priority Mask value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) { uint32_t result; __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Priority Mask \details Assigns the given value to the Priority Mask Register. \param [in] priMask Priority Mask */ __STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) { __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Priority Mask (non-secure) \details Assigns the given value to the non-secure Priority Mask Register when in secure state. \param [in] priMask Priority Mask */ __STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) { __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); } #endif #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Enable FIQ \details Enables FIQ interrupts by clearing the F-bit in the CPSR. Can only be executed in Privileged modes. */ #define __enable_fault_irq __enable_fiq /* see arm_compat.h */ /** \brief Disable FIQ \details Disables FIQ interrupts by setting the F-bit in the CPSR. Can only be executed in Privileged modes. */ #define __disable_fault_irq __disable_fiq /* see arm_compat.h */ /** \brief Get Base Priority \details Returns the current value of the Base Priority register. \return Base Priority register value */ __STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) { uint32_t result; __ASM volatile ("MRS %0, basepri" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Base Priority (non-secure) \details Returns the current value of the non-secure Base Priority register when in secure state. \return Base Priority register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) { uint32_t result; __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Base Priority \details Assigns the given value to the Base Priority register. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Base Priority (non-secure) \details Assigns the given value to the non-secure Base Priority register when in secure state. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) { __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); } #endif /** \brief Set Base Priority with condition \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, or the new value increases the BASEPRI priority level. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) { __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); } /** \brief Get Fault Mask \details Returns the current value of the Fault Mask register. \return Fault Mask register value */ __STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) { uint32_t result; __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Fault Mask (non-secure) \details Returns the current value of the non-secure Fault Mask register when in secure state. \return Fault Mask register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) { uint32_t result; __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Fault Mask \details Assigns the given value to the Fault Mask register. \param [in] faultMask Fault Mask value to set */ __STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) { __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Fault Mask (non-secure) \details Assigns the given value to the non-secure Fault Mask register when in secure state. \param [in] faultMask Fault Mask value to set */ __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) { __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); } #endif #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief Get Process Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always in non-secure mode. \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). \return PSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, psplim" : "=r" (result) ); return result; #endif } #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Process Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always in non-secure mode. \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. \return PSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure PSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); return result; #endif } #endif /** \brief Set Process Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored in non-secure mode. \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI (void)ProcStackPtrLimit; #else __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Process Stack Pointer (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored in non-secure mode. \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure PSPLIM is RAZ/WI (void)ProcStackPtrLimit; #else __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); #endif } #endif /** \brief Get Main Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always. \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). \return MSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, msplim" : "=r" (result) ); return result; #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Main Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always. \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. \return MSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure MSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); return result; #endif } #endif /** \brief Set Main Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored. \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI (void)MainStackPtrLimit; #else __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Main Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored. \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. \param [in] MainStackPtrLimit Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure MSPLIM is RAZ/WI (void)MainStackPtrLimit; #else __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); #endif } #endif #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /** \brief Get FPSCR \details Returns the current value of the Floating Point Status/Control register. \return Floating Point Status/Control register value */ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) #define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr #else #define __get_FPSCR() ((uint32_t)0U) #endif /** \brief Set FPSCR \details Assigns the given value to the Floating Point Status/Control register. \param [in] fpscr Floating Point Status/Control value to set */ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) #define __set_FPSCR __builtin_arm_set_fpscr #else #define __set_FPSCR(x) ((void)(x)) #endif /*@} end of CMSIS_Core_RegAccFunctions */ /* ########################## Core Instruction Access ######################### */ /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface Access to dedicated instructions @{ */ /* Define macros for porting to both thumb1 and thumb2. * For thumb1, use low register (r0-r7), specified by constraint "l" * Otherwise, use general registers, specified by constraint "r" */ #if defined (__thumb__) && !defined (__thumb2__) #define __CMSIS_GCC_OUT_REG(r) "=l" (r) #define __CMSIS_GCC_USE_REG(r) "l" (r) #else #define __CMSIS_GCC_OUT_REG(r) "=r" (r) #define __CMSIS_GCC_USE_REG(r) "r" (r) #endif /** \brief No Operation \details No Operation does nothing. This instruction can be used for code alignment purposes. */ #define __NOP __builtin_arm_nop /** \brief Wait For Interrupt \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. */ #define __WFI __builtin_arm_wfi /** \brief Wait For Event \details Wait For Event is a hint instruction that permits the processor to enter a low-power state until one of a number of events occurs. */ #define __WFE __builtin_arm_wfe /** \brief Send Event \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. */ #define __SEV __builtin_arm_sev /** \brief Instruction Synchronization Barrier \details Instruction Synchronization Barrier flushes the pipeline in the processor, so that all instructions following the ISB are fetched from cache or memory, after the instruction has been completed. */ #define __ISB() __builtin_arm_isb(0xF) /** \brief Data Synchronization Barrier \details Acts as a special kind of Data Memory Barrier. It completes when all explicit memory accesses before this instruction complete. */ #define __DSB() __builtin_arm_dsb(0xF) /** \brief Data Memory Barrier \details Ensures the apparent order of the explicit memory operations before and after the instruction, without ensuring their completion. */ #define __DMB() __builtin_arm_dmb(0xF) /** \brief Reverse byte order (32 bit) \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. \param [in] value Value to reverse \return Reversed value */ #define __REV(value) __builtin_bswap32(value) /** \brief Reverse byte order (16 bit) \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. \param [in] value Value to reverse \return Reversed value */ #define __REV16(value) __ROR(__REV(value), 16) /** \brief Reverse byte order (16 bit) \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. \param [in] value Value to reverse \return Reversed value */ #define __REVSH(value) (int16_t)__builtin_bswap16(value) /** \brief Rotate Right in unsigned value (32 bit) \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. \param [in] op1 Value to rotate \param [in] op2 Number of Bits to rotate \return Rotated value */ __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { op2 %= 32U; if (op2 == 0U) { return op1; } return (op1 >> op2) | (op1 << (32U - op2)); } /** \brief Breakpoint \details Causes the processor to enter Debug state. Debug tools can use this to investigate system state when the instruction at a particular address is reached. \param [in] value is ignored by the processor. If required, a debugger can use it to store additional information about the breakpoint. */ #define __BKPT(value) __ASM volatile ("bkpt "#value) /** \brief Reverse bit order of value \details Reverses the bit order of the given value. \param [in] value Value to reverse \return Reversed value */ #define __RBIT __builtin_arm_rbit /** \brief Count leading zeros \details Counts the number of leading zeros of a data value. \param [in] value Value to count the leading zeros \return number of leading zeros in value */ __STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) { /* Even though __builtin_clz produces a CLZ instruction on ARM, formally __builtin_clz(0) is undefined behaviour, so handle this case specially. This guarantees ARM-compatible results if happening to compile on a non-ARM target, and ensures the compiler doesn't decide to activate any optimisations using the logic "value was passed to __builtin_clz, so it is non-zero". ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a single CLZ instruction. */ if (value == 0U) { return 32U; } return __builtin_clz(value); } #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief LDR Exclusive (8 bit) \details Executes a exclusive LDR instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ #define __LDREXB (uint8_t)__builtin_arm_ldrex /** \brief LDR Exclusive (16 bit) \details Executes a exclusive LDR instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ #define __LDREXH (uint16_t)__builtin_arm_ldrex /** \brief LDR Exclusive (32 bit) \details Executes a exclusive LDR instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ #define __LDREXW (uint32_t)__builtin_arm_ldrex /** \brief STR Exclusive (8 bit) \details Executes a exclusive STR instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STREXB (uint32_t)__builtin_arm_strex /** \brief STR Exclusive (16 bit) \details Executes a exclusive STR instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STREXH (uint32_t)__builtin_arm_strex /** \brief STR Exclusive (32 bit) \details Executes a exclusive STR instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STREXW (uint32_t)__builtin_arm_strex /** \brief Remove the exclusive lock \details Removes the exclusive lock which is created by LDREX. */ #define __CLREX __builtin_arm_clrex #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Signed Saturate \details Saturates a signed value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (1..32) \return Saturated value */ #define __SSAT __builtin_arm_ssat /** \brief Unsigned Saturate \details Saturates an unsigned value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (0..31) \return Saturated value */ #define __USAT __builtin_arm_usat /** \brief Rotate Right with Extend (32 bit) \details Moves each bit of a bitstring right by one bit. The carry input is shifted in at the left end of the bitstring. \param [in] value Value to rotate \return Rotated value */ __STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) { uint32_t result; __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return(result); } /** \brief LDRT Unprivileged (8 bit) \details Executes a Unprivileged LDRT instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ __STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) { uint32_t result; __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint8_t) result); /* Add explicit type cast here */ } /** \brief LDRT Unprivileged (16 bit) \details Executes a Unprivileged LDRT instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ __STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) { uint32_t result; __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint16_t) result); /* Add explicit type cast here */ } /** \brief LDRT Unprivileged (32 bit) \details Executes a Unprivileged LDRT instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ __STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) { uint32_t result; __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } /** \brief STRT Unprivileged (8 bit) \details Executes a Unprivileged STRT instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief STRT Unprivileged (16 bit) \details Executes a Unprivileged STRT instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief STRT Unprivileged (32 bit) \details Executes a Unprivileged STRT instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) { __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); } #else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ /** \brief Signed Saturate \details Saturates a signed value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (1..32) \return Saturated value */ __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) { if ((sat >= 1U) && (sat <= 32U)) { const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); const int32_t min = -1 - max ; if (val > max) { return max; } else if (val < min) { return min; } } return val; } /** \brief Unsigned Saturate \details Saturates an unsigned value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (0..31) \return Saturated value */ __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) { if (sat <= 31U) { const uint32_t max = ((1U << sat) - 1U); if (val > (int32_t)max) { return max; } else if (val < 0) { return 0U; } } return (uint32_t)val; } #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief Load-Acquire (8 bit) \details Executes a LDAB instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ __STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) { uint32_t result; __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint8_t) result); } /** \brief Load-Acquire (16 bit) \details Executes a LDAH instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ __STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) { uint32_t result; __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint16_t) result); } /** \brief Load-Acquire (32 bit) \details Executes a LDA instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ __STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) { uint32_t result; __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } /** \brief Store-Release (8 bit) \details Executes a STLB instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Store-Release (16 bit) \details Executes a STLH instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) { __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Store-Release (32 bit) \details Executes a STL instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) { __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Load-Acquire Exclusive (8 bit) \details Executes a LDAB exclusive instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ #define __LDAEXB (uint8_t)__builtin_arm_ldaex /** \brief Load-Acquire Exclusive (16 bit) \details Executes a LDAH exclusive instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ #define __LDAEXH (uint16_t)__builtin_arm_ldaex /** \brief Load-Acquire Exclusive (32 bit) \details Executes a LDA exclusive instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ #define __LDAEX (uint32_t)__builtin_arm_ldaex /** \brief Store-Release Exclusive (8 bit) \details Executes a STLB exclusive instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STLEXB (uint32_t)__builtin_arm_stlex /** \brief Store-Release Exclusive (16 bit) \details Executes a STLH exclusive instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STLEXH (uint32_t)__builtin_arm_stlex /** \brief Store-Release Exclusive (32 bit) \details Executes a STL exclusive instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ #define __STLEX (uint32_t)__builtin_arm_stlex #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ /* ################### Compiler specific Intrinsics ########################### */ /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics Access to dedicated SIMD instructions @{ */ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) __STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } #define __SSAT16(ARG1,ARG2) \ ({ \ int32_t __RES, __ARG1 = (ARG1); \ __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ __RES; \ }) #define __USAT16(ARG1,ARG2) \ ({ \ uint32_t __RES, __ARG1 = (ARG1); \ __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ __RES; \ }) __STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) { uint32_t result; __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); return(result); } __STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) { uint32_t result; __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); return(result); } __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } __STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; uint64_t w64; } llr; llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); #else /* Big endian */ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); #endif return(llr.w64); } __STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; uint64_t w64; } llr; llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); #else /* Big endian */ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); #endif return(llr.w64); } __STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } __STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; uint64_t w64; } llr; llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); #else /* Big endian */ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); #endif return(llr.w64); } __STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; uint64_t w64; } llr; llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); #else /* Big endian */ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); #endif return(llr.w64); } __STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) { int32_t result; __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) { int32_t result; __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) { int32_t result; __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); return(result); } #endif /* (__ARM_FEATURE_DSP == 1) */ /*@} end of group CMSIS_SIMD_intrinsics */ #endif /* __CMSIS_ARMCLANG_H */ micropython-1.12/lib/cmsis/inc/cmsis_compiler.h000066400000000000000000000212721357706137100216440ustar00rootroot00000000000000/**************************************************************************//** * @file cmsis_compiler.h * @brief CMSIS compiler generic header file * @version V5.1.0 * @date 09. October 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CMSIS_COMPILER_H #define __CMSIS_COMPILER_H #include /* * Arm Compiler 4/5 */ #if defined ( __CC_ARM ) #include "cmsis_armcc.h" /* * Arm Compiler 6.6 LTM (armclang) */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) #include "cmsis_armclang_ltm.h" /* * Arm Compiler above 6.10.1 (armclang) */ #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) #include "cmsis_armclang.h" /* * GNU Compiler */ #elif defined ( __GNUC__ ) #include "cmsis_gcc.h" /* * IAR Compiler */ #elif defined ( __ICCARM__ ) #include /* * TI Arm Compiler */ #elif defined ( __TI_ARM__ ) #include #ifndef __ASM #define __ASM __asm #endif #ifndef __INLINE #define __INLINE inline #endif #ifndef __STATIC_INLINE #define __STATIC_INLINE static inline #endif #ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE __STATIC_INLINE #endif #ifndef __NO_RETURN #define __NO_RETURN __attribute__((noreturn)) #endif #ifndef __USED #define __USED __attribute__((used)) #endif #ifndef __WEAK #define __WEAK __attribute__((weak)) #endif #ifndef __PACKED #define __PACKED __attribute__((packed)) #endif #ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __attribute__((packed)) #endif #ifndef __PACKED_UNION #define __PACKED_UNION union __attribute__((packed)) #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ struct __attribute__((packed)) T_UINT32 { uint32_t v; }; #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #endif #ifndef __UNALIGNED_UINT16_WRITE __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT16_READ __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) #endif #ifndef __UNALIGNED_UINT32_WRITE __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT32_READ __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) #endif #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif #ifndef __RESTRICT #define __RESTRICT __restrict #endif /* * TASKING Compiler */ #elif defined ( __TASKING__ ) /* * The CMSIS functions have been implemented as intrinsics in the compiler. * Please use "carm -?i" to get an up to date list of all intrinsics, * Including the CMSIS ones. */ #ifndef __ASM #define __ASM __asm #endif #ifndef __INLINE #define __INLINE inline #endif #ifndef __STATIC_INLINE #define __STATIC_INLINE static inline #endif #ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE __STATIC_INLINE #endif #ifndef __NO_RETURN #define __NO_RETURN __attribute__((noreturn)) #endif #ifndef __USED #define __USED __attribute__((used)) #endif #ifndef __WEAK #define __WEAK __attribute__((weak)) #endif #ifndef __PACKED #define __PACKED __packed__ #endif #ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __packed__ #endif #ifndef __PACKED_UNION #define __PACKED_UNION union __packed__ #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ struct __packed__ T_UINT32 { uint32_t v; }; #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #endif #ifndef __UNALIGNED_UINT16_WRITE __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT16_READ __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) #endif #ifndef __UNALIGNED_UINT32_WRITE __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT32_READ __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) #endif #ifndef __ALIGNED #define __ALIGNED(x) __align(x) #endif #ifndef __RESTRICT #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. #define __RESTRICT #endif /* * COSMIC Compiler */ #elif defined ( __CSMC__ ) #include #ifndef __ASM #define __ASM _asm #endif #ifndef __INLINE #define __INLINE inline #endif #ifndef __STATIC_INLINE #define __STATIC_INLINE static inline #endif #ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE __STATIC_INLINE #endif #ifndef __NO_RETURN // NO RETURN is automatically detected hence no warning here #define __NO_RETURN #endif #ifndef __USED #warning No compiler specific solution for __USED. __USED is ignored. #define __USED #endif #ifndef __WEAK #define __WEAK __weak #endif #ifndef __PACKED #define __PACKED @packed #endif #ifndef __PACKED_STRUCT #define __PACKED_STRUCT @packed struct #endif #ifndef __PACKED_UNION #define __PACKED_UNION @packed union #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ @packed struct T_UINT32 { uint32_t v; }; #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #endif #ifndef __UNALIGNED_UINT16_WRITE __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT16_READ __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) #endif #ifndef __UNALIGNED_UINT32_WRITE __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT32_READ __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) #endif #ifndef __ALIGNED #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. #define __ALIGNED(x) #endif #ifndef __RESTRICT #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. #define __RESTRICT #endif #else #error Unknown compiler. #endif #endif /* __CMSIS_COMPILER_H */ micropython-1.12/lib/cmsis/inc/cmsis_gcc.h000066400000000000000000001666651357706137100206060ustar00rootroot00000000000000/**************************************************************************//** * @file cmsis_gcc.h * @brief CMSIS compiler GCC header file * @version V5.1.0 * @date 20. December 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CMSIS_GCC_H #define __CMSIS_GCC_H /* ignore some GCC warnings */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wunused-parameter" /* Fallback for __has_builtin */ #ifndef __has_builtin #define __has_builtin(x) (0) #endif /* CMSIS compiler specific defines */ #ifndef __ASM #define __ASM __asm #endif #ifndef __INLINE #define __INLINE inline #endif #ifndef __STATIC_INLINE #define __STATIC_INLINE static inline #endif #ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline #endif #ifndef __NO_RETURN #define __NO_RETURN __attribute__((__noreturn__)) #endif #ifndef __USED #define __USED __attribute__((used)) #endif #ifndef __WEAK #define __WEAK __attribute__((weak)) #endif #ifndef __PACKED #define __PACKED __attribute__((packed, aligned(1))) #endif #ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #endif #ifndef __PACKED_UNION #define __PACKED_UNION union __attribute__((packed, aligned(1))) #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wattributes" struct __attribute__((packed)) T_UINT32 { uint32_t v; }; #pragma GCC diagnostic pop #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #endif #ifndef __UNALIGNED_UINT16_WRITE #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wattributes" __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; #pragma GCC diagnostic pop #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT16_READ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wattributes" __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; #pragma GCC diagnostic pop #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) #endif #ifndef __UNALIGNED_UINT32_WRITE #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wattributes" __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; #pragma GCC diagnostic pop #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) #endif #ifndef __UNALIGNED_UINT32_READ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wattributes" __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; #pragma GCC diagnostic pop #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) #endif #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif #ifndef __RESTRICT #define __RESTRICT __restrict #endif /* ########################### Core Function Access ########################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions @{ */ /** \brief Enable IRQ Interrupts \details Enables IRQ interrupts by clearing the I-bit in the CPSR. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __enable_irq(void) { __ASM volatile ("cpsie i" : : : "memory"); } /** \brief Disable IRQ Interrupts \details Disables IRQ interrupts by setting the I-bit in the CPSR. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __disable_irq(void) { __ASM volatile ("cpsid i" : : : "memory"); } /** \brief Get Control Register \details Returns the content of the Control Register. \return Control Register value */ __STATIC_FORCEINLINE uint32_t __get_CONTROL(void) { uint32_t result; __ASM volatile ("MRS %0, control" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Control Register (non-secure) \details Returns the content of the non-secure Control Register when in secure mode. \return non-secure Control Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) { uint32_t result; __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Control Register \details Writes the given value to the Control Register. \param [in] control Control Register value to set */ __STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) { __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Control Register (non-secure) \details Writes the given value to the non-secure Control Register when in secure state. \param [in] control Control Register value to set */ __STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) { __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); } #endif /** \brief Get IPSR Register \details Returns the content of the IPSR Register. \return IPSR Register value */ __STATIC_FORCEINLINE uint32_t __get_IPSR(void) { uint32_t result; __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); return(result); } /** \brief Get APSR Register \details Returns the content of the APSR Register. \return APSR Register value */ __STATIC_FORCEINLINE uint32_t __get_APSR(void) { uint32_t result; __ASM volatile ("MRS %0, apsr" : "=r" (result) ); return(result); } /** \brief Get xPSR Register \details Returns the content of the xPSR Register. \return xPSR Register value */ __STATIC_FORCEINLINE uint32_t __get_xPSR(void) { uint32_t result; __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); return(result); } /** \brief Get Process Stack Pointer \details Returns the current value of the Process Stack Pointer (PSP). \return PSP Register value */ __STATIC_FORCEINLINE uint32_t __get_PSP(void) { uint32_t result; __ASM volatile ("MRS %0, psp" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Process Stack Pointer (non-secure) \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. \return PSP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Process Stack Pointer \details Assigns the given value to the Process Stack Pointer (PSP). \param [in] topOfProcStack Process Stack Pointer value to set */ __STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) { __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Process Stack Pointer (non-secure) \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. \param [in] topOfProcStack Process Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); } #endif /** \brief Get Main Stack Pointer \details Returns the current value of the Main Stack Pointer (MSP). \return MSP Register value */ __STATIC_FORCEINLINE uint32_t __get_MSP(void) { uint32_t result; __ASM volatile ("MRS %0, msp" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Main Stack Pointer (non-secure) \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. \return MSP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Main Stack Pointer \details Assigns the given value to the Main Stack Pointer (MSP). \param [in] topOfMainStack Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) { __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Main Stack Pointer (non-secure) \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. \param [in] topOfMainStack Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) { __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); } #endif #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Stack Pointer (non-secure) \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. \return SP Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) { uint32_t result; __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); return(result); } /** \brief Set Stack Pointer (non-secure) \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. \param [in] topOfStack Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) { __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); } #endif /** \brief Get Priority Mask \details Returns the current state of the priority mask bit from the Priority Mask Register. \return Priority Mask value */ __STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) { uint32_t result; __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Priority Mask (non-secure) \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. \return Priority Mask value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) { uint32_t result; __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); return(result); } #endif /** \brief Set Priority Mask \details Assigns the given value to the Priority Mask Register. \param [in] priMask Priority Mask */ __STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) { __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Priority Mask (non-secure) \details Assigns the given value to the non-secure Priority Mask Register when in secure state. \param [in] priMask Priority Mask */ __STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) { __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); } #endif #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Enable FIQ \details Enables FIQ interrupts by clearing the F-bit in the CPSR. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __enable_fault_irq(void) { __ASM volatile ("cpsie f" : : : "memory"); } /** \brief Disable FIQ \details Disables FIQ interrupts by setting the F-bit in the CPSR. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __disable_fault_irq(void) { __ASM volatile ("cpsid f" : : : "memory"); } /** \brief Get Base Priority \details Returns the current value of the Base Priority register. \return Base Priority register value */ __STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) { uint32_t result; __ASM volatile ("MRS %0, basepri" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Base Priority (non-secure) \details Returns the current value of the non-secure Base Priority register when in secure state. \return Base Priority register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) { uint32_t result; __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Base Priority \details Assigns the given value to the Base Priority register. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Base Priority (non-secure) \details Assigns the given value to the non-secure Base Priority register when in secure state. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) { __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); } #endif /** \brief Set Base Priority with condition \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, or the new value increases the BASEPRI priority level. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) { __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); } /** \brief Get Fault Mask \details Returns the current value of the Fault Mask register. \return Fault Mask register value */ __STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) { uint32_t result; __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); return(result); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Fault Mask (non-secure) \details Returns the current value of the non-secure Fault Mask register when in secure state. \return Fault Mask register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) { uint32_t result; __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); return(result); } #endif /** \brief Set Fault Mask \details Assigns the given value to the Fault Mask register. \param [in] faultMask Fault Mask value to set */ __STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) { __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Fault Mask (non-secure) \details Assigns the given value to the non-secure Fault Mask register when in secure state. \param [in] faultMask Fault Mask value to set */ __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) { __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); } #endif #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief Get Process Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always in non-secure mode. \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). \return PSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, psplim" : "=r" (result) ); return result; #endif } #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Process Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always. \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. \return PSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure PSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); return result; #endif } #endif /** \brief Set Process Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored in non-secure mode. \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI (void)ProcStackPtrLimit; #else __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Process Stack Pointer (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored. \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure PSPLIM is RAZ/WI (void)ProcStackPtrLimit; #else __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); #endif } #endif /** \brief Get Main Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always in non-secure mode. \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). \return MSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, msplim" : "=r" (result) ); return result; #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Main Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence zero is returned always. \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. \return MSPLIM Register value */ __STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure MSPLIM is RAZ/WI return 0U; #else uint32_t result; __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); return result; #endif } #endif /** \brief Set Main Stack Pointer Limit Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored in non-secure mode. \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set */ __STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI (void)MainStackPtrLimit; #else __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); #endif } #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Main Stack Pointer Limit (non-secure) Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Stack Pointer Limit register hence the write is silently ignored. \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. \param [in] MainStackPtrLimit Main Stack Pointer value to set */ __STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) // without main extensions, the non-secure MSPLIM is RAZ/WI (void)MainStackPtrLimit; #else __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); #endif } #endif #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /** \brief Get FPSCR \details Returns the current value of the Floating Point Status/Control register. \return Floating Point Status/Control register value */ __STATIC_FORCEINLINE uint32_t __get_FPSCR(void) { #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) #if __has_builtin(__builtin_arm_get_fpscr) // Re-enable using built-in when GCC has been fixed // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ return __builtin_arm_get_fpscr(); #else uint32_t result; __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); return(result); #endif #else return(0U); #endif } /** \brief Set FPSCR \details Assigns the given value to the Floating Point Status/Control register. \param [in] fpscr Floating Point Status/Control value to set */ __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) { #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) #if __has_builtin(__builtin_arm_set_fpscr) // Re-enable using built-in when GCC has been fixed // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ __builtin_arm_set_fpscr(fpscr); #else __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); #endif #else (void)fpscr; #endif } /*@} end of CMSIS_Core_RegAccFunctions */ /* ########################## Core Instruction Access ######################### */ /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface Access to dedicated instructions @{ */ /* Define macros for porting to both thumb1 and thumb2. * For thumb1, use low register (r0-r7), specified by constraint "l" * Otherwise, use general registers, specified by constraint "r" */ #if defined (__thumb__) && !defined (__thumb2__) #define __CMSIS_GCC_OUT_REG(r) "=l" (r) #define __CMSIS_GCC_RW_REG(r) "+l" (r) #define __CMSIS_GCC_USE_REG(r) "l" (r) #else #define __CMSIS_GCC_OUT_REG(r) "=r" (r) #define __CMSIS_GCC_RW_REG(r) "+r" (r) #define __CMSIS_GCC_USE_REG(r) "r" (r) #endif /** \brief No Operation \details No Operation does nothing. This instruction can be used for code alignment purposes. */ #define __NOP() __ASM volatile ("nop") /** \brief Wait For Interrupt \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. */ #define __WFI() __ASM volatile ("wfi") /** \brief Wait For Event \details Wait For Event is a hint instruction that permits the processor to enter a low-power state until one of a number of events occurs. */ #define __WFE() __ASM volatile ("wfe") /** \brief Send Event \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. */ #define __SEV() __ASM volatile ("sev") /** \brief Instruction Synchronization Barrier \details Instruction Synchronization Barrier flushes the pipeline in the processor, so that all instructions following the ISB are fetched from cache or memory, after the instruction has been completed. */ __STATIC_FORCEINLINE void __ISB(void) { __ASM volatile ("isb 0xF":::"memory"); } /** \brief Data Synchronization Barrier \details Acts as a special kind of Data Memory Barrier. It completes when all explicit memory accesses before this instruction complete. */ __STATIC_FORCEINLINE void __DSB(void) { __ASM volatile ("dsb 0xF":::"memory"); } /** \brief Data Memory Barrier \details Ensures the apparent order of the explicit memory operations before and after the instruction, without ensuring their completion. */ __STATIC_FORCEINLINE void __DMB(void) { __ASM volatile ("dmb 0xF":::"memory"); } /** \brief Reverse byte order (32 bit) \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. \param [in] value Value to reverse \return Reversed value */ __STATIC_FORCEINLINE uint32_t __REV(uint32_t value) { #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) return __builtin_bswap32(value); #else uint32_t result; __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return result; #endif } /** \brief Reverse byte order (16 bit) \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. \param [in] value Value to reverse \return Reversed value */ __STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) { uint32_t result; __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return result; } /** \brief Reverse byte order (16 bit) \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. \param [in] value Value to reverse \return Reversed value */ __STATIC_FORCEINLINE int16_t __REVSH(int16_t value) { #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) return (int16_t)__builtin_bswap16(value); #else int16_t result; __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return result; #endif } /** \brief Rotate Right in unsigned value (32 bit) \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. \param [in] op1 Value to rotate \param [in] op2 Number of Bits to rotate \return Rotated value */ __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { op2 %= 32U; if (op2 == 0U) { return op1; } return (op1 >> op2) | (op1 << (32U - op2)); } /** \brief Breakpoint \details Causes the processor to enter Debug state. Debug tools can use this to investigate system state when the instruction at a particular address is reached. \param [in] value is ignored by the processor. If required, a debugger can use it to store additional information about the breakpoint. */ #define __BKPT(value) __ASM volatile ("bkpt "#value) /** \brief Reverse bit order of value \details Reverses the bit order of the given value. \param [in] value Value to reverse \return Reversed value */ __STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) { uint32_t result; #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); #else uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ result = value; /* r will be reversed bits of v; first get LSB of v */ for (value >>= 1U; value != 0U; value >>= 1U) { result <<= 1U; result |= value & 1U; s--; } result <<= s; /* shift when v's highest bits are zero */ #endif return result; } /** \brief Count leading zeros \details Counts the number of leading zeros of a data value. \param [in] value Value to count the leading zeros \return number of leading zeros in value */ __STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) { /* Even though __builtin_clz produces a CLZ instruction on ARM, formally __builtin_clz(0) is undefined behaviour, so handle this case specially. This guarantees ARM-compatible results if happening to compile on a non-ARM target, and ensures the compiler doesn't decide to activate any optimisations using the logic "value was passed to __builtin_clz, so it is non-zero". ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a single CLZ instruction. */ if (value == 0U) { return 32U; } return __builtin_clz(value); } #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief LDR Exclusive (8 bit) \details Executes a exclusive LDR instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ __STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) { uint32_t result; #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); #else /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not accepted by assembler. So has to use following less efficient pattern. */ __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); #endif return ((uint8_t) result); /* Add explicit type cast here */ } /** \brief LDR Exclusive (16 bit) \details Executes a exclusive LDR instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ __STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) { uint32_t result; #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); #else /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not accepted by assembler. So has to use following less efficient pattern. */ __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); #endif return ((uint16_t) result); /* Add explicit type cast here */ } /** \brief LDR Exclusive (32 bit) \details Executes a exclusive LDR instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ __STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) { uint32_t result; __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); return(result); } /** \brief STR Exclusive (8 bit) \details Executes a exclusive STR instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ __STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) { uint32_t result; __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); return(result); } /** \brief STR Exclusive (16 bit) \details Executes a exclusive STR instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ __STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) { uint32_t result; __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); return(result); } /** \brief STR Exclusive (32 bit) \details Executes a exclusive STR instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ __STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) { uint32_t result; __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); return(result); } /** \brief Remove the exclusive lock \details Removes the exclusive lock which is created by LDREX. */ __STATIC_FORCEINLINE void __CLREX(void) { __ASM volatile ("clrex" ::: "memory"); } #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Signed Saturate \details Saturates a signed value. \param [in] ARG1 Value to be saturated \param [in] ARG2 Bit position to saturate to (1..32) \return Saturated value */ #define __SSAT(ARG1,ARG2) \ __extension__ \ ({ \ int32_t __RES, __ARG1 = (ARG1); \ __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ __RES; \ }) /** \brief Unsigned Saturate \details Saturates an unsigned value. \param [in] ARG1 Value to be saturated \param [in] ARG2 Bit position to saturate to (0..31) \return Saturated value */ #define __USAT(ARG1,ARG2) \ __extension__ \ ({ \ uint32_t __RES, __ARG1 = (ARG1); \ __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ __RES; \ }) /** \brief Rotate Right with Extend (32 bit) \details Moves each bit of a bitstring right by one bit. The carry input is shifted in at the left end of the bitstring. \param [in] value Value to rotate \return Rotated value */ __STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) { uint32_t result; __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); return(result); } /** \brief LDRT Unprivileged (8 bit) \details Executes a Unprivileged LDRT instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ __STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) { uint32_t result; #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); #else /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not accepted by assembler. So has to use following less efficient pattern. */ __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); #endif return ((uint8_t) result); /* Add explicit type cast here */ } /** \brief LDRT Unprivileged (16 bit) \details Executes a Unprivileged LDRT instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ __STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) { uint32_t result; #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); #else /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not accepted by assembler. So has to use following less efficient pattern. */ __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); #endif return ((uint16_t) result); /* Add explicit type cast here */ } /** \brief LDRT Unprivileged (32 bit) \details Executes a Unprivileged LDRT instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ __STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) { uint32_t result; __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } /** \brief STRT Unprivileged (8 bit) \details Executes a Unprivileged STRT instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief STRT Unprivileged (16 bit) \details Executes a Unprivileged STRT instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief STRT Unprivileged (32 bit) \details Executes a Unprivileged STRT instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) { __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); } #else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ /** \brief Signed Saturate \details Saturates a signed value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (1..32) \return Saturated value */ __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) { if ((sat >= 1U) && (sat <= 32U)) { const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); const int32_t min = -1 - max ; if (val > max) { return max; } else if (val < min) { return min; } } return val; } /** \brief Unsigned Saturate \details Saturates an unsigned value. \param [in] value Value to be saturated \param [in] sat Bit position to saturate to (0..31) \return Saturated value */ __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) { if (sat <= 31U) { const uint32_t max = ((1U << sat) - 1U); if (val > (int32_t)max) { return max; } else if (val < 0) { return 0U; } } return (uint32_t)val; } #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief Load-Acquire (8 bit) \details Executes a LDAB instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ __STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) { uint32_t result; __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint8_t) result); } /** \brief Load-Acquire (16 bit) \details Executes a LDAH instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ __STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) { uint32_t result; __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint16_t) result); } /** \brief Load-Acquire (32 bit) \details Executes a LDA instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ __STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) { uint32_t result; __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } /** \brief Store-Release (8 bit) \details Executes a STLB instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Store-Release (16 bit) \details Executes a STLH instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) { __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Store-Release (32 bit) \details Executes a STL instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location */ __STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) { __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } /** \brief Load-Acquire Exclusive (8 bit) \details Executes a LDAB exclusive instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ __STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) { uint32_t result; __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint8_t) result); } /** \brief Load-Acquire Exclusive (16 bit) \details Executes a LDAH exclusive instruction for 16 bit values. \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ __STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) { uint32_t result; __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); return ((uint16_t) result); } /** \brief Load-Acquire Exclusive (32 bit) \details Executes a LDA exclusive instruction for 32 bit values. \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ __STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) { uint32_t result; __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } /** \brief Store-Release Exclusive (8 bit) \details Executes a STLB exclusive instruction for 8 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ __STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) { uint32_t result; __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); return(result); } /** \brief Store-Release Exclusive (16 bit) \details Executes a STLH exclusive instruction for 16 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ __STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) { uint32_t result; __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); return(result); } /** \brief Store-Release Exclusive (32 bit) \details Executes a STL exclusive instruction for 32 bit values. \param [in] value Value to store \param [in] ptr Pointer to location \return 0 Function succeeded \return 1 Function failed */ __STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) { uint32_t result; __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); return(result); } #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ /* ################### Compiler specific Intrinsics ########################### */ /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics Access to dedicated SIMD instructions @{ */ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) __STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } #define __SSAT16(ARG1,ARG2) \ ({ \ int32_t __RES, __ARG1 = (ARG1); \ __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ __RES; \ }) #define __USAT16(ARG1,ARG2) \ ({ \ uint32_t __RES, __ARG1 = (ARG1); \ __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ __RES; \ }) __STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) { uint32_t result; __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); return(result); } __STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) { uint32_t result; __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); return(result); } __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } __STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; uint64_t w64; } llr; llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); #else /* Big endian */ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); #endif return(llr.w64); } __STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; uint64_t w64; } llr; llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); #else /* Big endian */ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); #endif return(llr.w64); } __STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } __STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); return(result); } __STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; uint64_t w64; } llr; llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); #else /* Big endian */ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); #endif return(llr.w64); } __STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; uint64_t w64; } llr; llr.w64 = acc; #ifndef __ARMEB__ /* Little endian */ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); #else /* Big endian */ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); #endif return(llr.w64); } __STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) { uint32_t result; __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) { int32_t result; __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) { int32_t result; __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return(result); } #if 0 #define __PKHBT(ARG1,ARG2,ARG3) \ ({ \ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ __RES; \ }) #define __PKHTB(ARG1,ARG2,ARG3) \ ({ \ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ if (ARG3 == 0) \ __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ else \ __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ __RES; \ }) #endif #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) { int32_t result; __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); return(result); } #endif /* (__ARM_FEATURE_DSP == 1) */ /*@} end of group CMSIS_SIMD_intrinsics */ #pragma GCC diagnostic pop #endif /* __CMSIS_GCC_H */ micropython-1.12/lib/cmsis/inc/cmsis_iccarm.h000066400000000000000000000657241357706137100213020ustar00rootroot00000000000000/**************************************************************************//** * @file cmsis_iccarm.h * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file * @version V5.0.8 * @date 04. September 2018 ******************************************************************************/ //------------------------------------------------------------------------------ // // Copyright (c) 2017-2018 IAR Systems // // Licensed under the Apache License, Version 2.0 (the "License") // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //------------------------------------------------------------------------------ #ifndef __CMSIS_ICCARM_H__ #define __CMSIS_ICCARM_H__ #ifndef __ICCARM__ #error This file should only be compiled by ICCARM #endif #pragma system_include #define __IAR_FT _Pragma("inline=forced") __intrinsic #if (__VER__ >= 8000000) #define __ICCARM_V8 1 #else #define __ICCARM_V8 0 #endif #ifndef __ALIGNED #if __ICCARM_V8 #define __ALIGNED(x) __attribute__((aligned(x))) #elif (__VER__ >= 7080000) /* Needs IAR language extensions */ #define __ALIGNED(x) __attribute__((aligned(x))) #else #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored. #define __ALIGNED(x) #endif #endif /* Define compiler macros for CPU architecture, used in CMSIS 5. */ #if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__ /* Macros already defined */ #else #if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) #define __ARM_ARCH_8M_MAIN__ 1 #elif defined(__ARM8M_BASELINE__) #define __ARM_ARCH_8M_BASE__ 1 #elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M' #if __ARM_ARCH == 6 #define __ARM_ARCH_6M__ 1 #elif __ARM_ARCH == 7 #if __ARM_FEATURE_DSP #define __ARM_ARCH_7EM__ 1 #else #define __ARM_ARCH_7M__ 1 #endif #endif /* __ARM_ARCH */ #endif /* __ARM_ARCH_PROFILE == 'M' */ #endif /* Alternativ core deduction for older ICCARM's */ #if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \ !defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__) #if defined(__ARM6M__) && (__CORE__ == __ARM6M__) #define __ARM_ARCH_6M__ 1 #elif defined(__ARM7M__) && (__CORE__ == __ARM7M__) #define __ARM_ARCH_7M__ 1 #elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__) #define __ARM_ARCH_7EM__ 1 #elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__) #define __ARM_ARCH_8M_BASE__ 1 #elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__) #define __ARM_ARCH_8M_MAIN__ 1 #elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__) #define __ARM_ARCH_8M_MAIN__ 1 #else #error "Unknown target." #endif #endif #if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1 #define __IAR_M0_FAMILY 1 #elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1 #define __IAR_M0_FAMILY 1 #else #define __IAR_M0_FAMILY 0 #endif #ifndef __ASM #define __ASM __asm #endif #ifndef __INLINE #define __INLINE inline #endif #ifndef __NO_RETURN #if __ICCARM_V8 #define __NO_RETURN __attribute__((__noreturn__)) #else #define __NO_RETURN _Pragma("object_attribute=__noreturn") #endif #endif #ifndef __PACKED #if __ICCARM_V8 #define __PACKED __attribute__((packed, aligned(1))) #else /* Needs IAR language extensions */ #define __PACKED __packed #endif #endif #ifndef __PACKED_STRUCT #if __ICCARM_V8 #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #else /* Needs IAR language extensions */ #define __PACKED_STRUCT __packed struct #endif #endif #ifndef __PACKED_UNION #if __ICCARM_V8 #define __PACKED_UNION union __attribute__((packed, aligned(1))) #else /* Needs IAR language extensions */ #define __PACKED_UNION __packed union #endif #endif #ifndef __RESTRICT #if __ICCARM_V8 #define __RESTRICT __restrict #else /* Needs IAR language extensions */ #define __RESTRICT restrict #endif #endif #ifndef __STATIC_INLINE #define __STATIC_INLINE static inline #endif #ifndef __FORCEINLINE #define __FORCEINLINE _Pragma("inline=forced") #endif #ifndef __STATIC_FORCEINLINE #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE #endif #ifndef __UNALIGNED_UINT16_READ #pragma language=save #pragma language=extended __IAR_FT uint16_t __iar_uint16_read(void const *ptr) { return *(__packed uint16_t*)(ptr); } #pragma language=restore #define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR) #endif #ifndef __UNALIGNED_UINT16_WRITE #pragma language=save #pragma language=extended __IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val) { *(__packed uint16_t*)(ptr) = val;; } #pragma language=restore #define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL) #endif #ifndef __UNALIGNED_UINT32_READ #pragma language=save #pragma language=extended __IAR_FT uint32_t __iar_uint32_read(void const *ptr) { return *(__packed uint32_t*)(ptr); } #pragma language=restore #define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR) #endif #ifndef __UNALIGNED_UINT32_WRITE #pragma language=save #pragma language=extended __IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val) { *(__packed uint32_t*)(ptr) = val;; } #pragma language=restore #define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL) #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ #pragma language=save #pragma language=extended __packed struct __iar_u32 { uint32_t v; }; #pragma language=restore #define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v) #endif #ifndef __USED #if __ICCARM_V8 #define __USED __attribute__((used)) #else #define __USED _Pragma("__root") #endif #endif #ifndef __WEAK #if __ICCARM_V8 #define __WEAK __attribute__((weak)) #else #define __WEAK _Pragma("__weak") #endif #endif #ifndef __ICCARM_INTRINSICS_VERSION__ #define __ICCARM_INTRINSICS_VERSION__ 0 #endif #if __ICCARM_INTRINSICS_VERSION__ == 2 #if defined(__CLZ) #undef __CLZ #endif #if defined(__REVSH) #undef __REVSH #endif #if defined(__RBIT) #undef __RBIT #endif #if defined(__SSAT) #undef __SSAT #endif #if defined(__USAT) #undef __USAT #endif #include "iccarm_builtin.h" #define __disable_fault_irq __iar_builtin_disable_fiq #define __disable_irq __iar_builtin_disable_interrupt #define __enable_fault_irq __iar_builtin_enable_fiq #define __enable_irq __iar_builtin_enable_interrupt #define __arm_rsr __iar_builtin_rsr #define __arm_wsr __iar_builtin_wsr #define __get_APSR() (__arm_rsr("APSR")) #define __get_BASEPRI() (__arm_rsr("BASEPRI")) #define __get_CONTROL() (__arm_rsr("CONTROL")) #define __get_FAULTMASK() (__arm_rsr("FAULTMASK")) #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) #define __get_FPSCR() (__arm_rsr("FPSCR")) #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE))) #else #define __get_FPSCR() ( 0 ) #define __set_FPSCR(VALUE) ((void)VALUE) #endif #define __get_IPSR() (__arm_rsr("IPSR")) #define __get_MSP() (__arm_rsr("MSP")) #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI #define __get_MSPLIM() (0U) #else #define __get_MSPLIM() (__arm_rsr("MSPLIM")) #endif #define __get_PRIMASK() (__arm_rsr("PRIMASK")) #define __get_PSP() (__arm_rsr("PSP")) #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI #define __get_PSPLIM() (0U) #else #define __get_PSPLIM() (__arm_rsr("PSPLIM")) #endif #define __get_xPSR() (__arm_rsr("xPSR")) #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE))) #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE))) #define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE))) #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE))) #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE))) #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI #define __set_MSPLIM(VALUE) ((void)(VALUE)) #else #define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE))) #endif #define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE))) #define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE))) #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI #define __set_PSPLIM(VALUE) ((void)(VALUE)) #else #define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE))) #endif #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS")) #define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE))) #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS")) #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE))) #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS")) #define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE))) #define __TZ_get_SP_NS() (__arm_rsr("SP_NS")) #define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE))) #define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS")) #define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE))) #define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS")) #define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE))) #define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS")) #define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE))) #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI #define __TZ_get_PSPLIM_NS() (0U) #define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE)) #else #define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS")) #define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE))) #endif #define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS")) #define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE))) #define __NOP __iar_builtin_no_operation #define __CLZ __iar_builtin_CLZ #define __CLREX __iar_builtin_CLREX #define __DMB __iar_builtin_DMB #define __DSB __iar_builtin_DSB #define __ISB __iar_builtin_ISB #define __LDREXB __iar_builtin_LDREXB #define __LDREXH __iar_builtin_LDREXH #define __LDREXW __iar_builtin_LDREX #define __RBIT __iar_builtin_RBIT #define __REV __iar_builtin_REV #define __REV16 __iar_builtin_REV16 __IAR_FT int16_t __REVSH(int16_t val) { return (int16_t) __iar_builtin_REVSH(val); } #define __ROR __iar_builtin_ROR #define __RRX __iar_builtin_RRX #define __SEV __iar_builtin_SEV #if !__IAR_M0_FAMILY #define __SSAT __iar_builtin_SSAT #endif #define __STREXB __iar_builtin_STREXB #define __STREXH __iar_builtin_STREXH #define __STREXW __iar_builtin_STREX #if !__IAR_M0_FAMILY #define __USAT __iar_builtin_USAT #endif #define __WFE __iar_builtin_WFE #define __WFI __iar_builtin_WFI #if __ARM_MEDIA__ #define __SADD8 __iar_builtin_SADD8 #define __QADD8 __iar_builtin_QADD8 #define __SHADD8 __iar_builtin_SHADD8 #define __UADD8 __iar_builtin_UADD8 #define __UQADD8 __iar_builtin_UQADD8 #define __UHADD8 __iar_builtin_UHADD8 #define __SSUB8 __iar_builtin_SSUB8 #define __QSUB8 __iar_builtin_QSUB8 #define __SHSUB8 __iar_builtin_SHSUB8 #define __USUB8 __iar_builtin_USUB8 #define __UQSUB8 __iar_builtin_UQSUB8 #define __UHSUB8 __iar_builtin_UHSUB8 #define __SADD16 __iar_builtin_SADD16 #define __QADD16 __iar_builtin_QADD16 #define __SHADD16 __iar_builtin_SHADD16 #define __UADD16 __iar_builtin_UADD16 #define __UQADD16 __iar_builtin_UQADD16 #define __UHADD16 __iar_builtin_UHADD16 #define __SSUB16 __iar_builtin_SSUB16 #define __QSUB16 __iar_builtin_QSUB16 #define __SHSUB16 __iar_builtin_SHSUB16 #define __USUB16 __iar_builtin_USUB16 #define __UQSUB16 __iar_builtin_UQSUB16 #define __UHSUB16 __iar_builtin_UHSUB16 #define __SASX __iar_builtin_SASX #define __QASX __iar_builtin_QASX #define __SHASX __iar_builtin_SHASX #define __UASX __iar_builtin_UASX #define __UQASX __iar_builtin_UQASX #define __UHASX __iar_builtin_UHASX #define __SSAX __iar_builtin_SSAX #define __QSAX __iar_builtin_QSAX #define __SHSAX __iar_builtin_SHSAX #define __USAX __iar_builtin_USAX #define __UQSAX __iar_builtin_UQSAX #define __UHSAX __iar_builtin_UHSAX #define __USAD8 __iar_builtin_USAD8 #define __USADA8 __iar_builtin_USADA8 #define __SSAT16 __iar_builtin_SSAT16 #define __USAT16 __iar_builtin_USAT16 #define __UXTB16 __iar_builtin_UXTB16 #define __UXTAB16 __iar_builtin_UXTAB16 #define __SXTB16 __iar_builtin_SXTB16 #define __SXTAB16 __iar_builtin_SXTAB16 #define __SMUAD __iar_builtin_SMUAD #define __SMUADX __iar_builtin_SMUADX #define __SMMLA __iar_builtin_SMMLA #define __SMLAD __iar_builtin_SMLAD #define __SMLADX __iar_builtin_SMLADX #define __SMLALD __iar_builtin_SMLALD #define __SMLALDX __iar_builtin_SMLALDX #define __SMUSD __iar_builtin_SMUSD #define __SMUSDX __iar_builtin_SMUSDX #define __SMLSD __iar_builtin_SMLSD #define __SMLSDX __iar_builtin_SMLSDX #define __SMLSLD __iar_builtin_SMLSLD #define __SMLSLDX __iar_builtin_SMLSLDX #define __SEL __iar_builtin_SEL #define __QADD __iar_builtin_QADD #define __QSUB __iar_builtin_QSUB #define __PKHBT __iar_builtin_PKHBT #define __PKHTB __iar_builtin_PKHTB #endif #else /* __ICCARM_INTRINSICS_VERSION__ == 2 */ #if __IAR_M0_FAMILY /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ #define __CLZ __cmsis_iar_clz_not_active #define __SSAT __cmsis_iar_ssat_not_active #define __USAT __cmsis_iar_usat_not_active #define __RBIT __cmsis_iar_rbit_not_active #define __get_APSR __cmsis_iar_get_APSR_not_active #endif #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) #define __get_FPSCR __cmsis_iar_get_FPSR_not_active #define __set_FPSCR __cmsis_iar_set_FPSR_not_active #endif #ifdef __INTRINSICS_INCLUDED #error intrinsics.h is already included previously! #endif #include #if __IAR_M0_FAMILY /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ #undef __CLZ #undef __SSAT #undef __USAT #undef __RBIT #undef __get_APSR __STATIC_INLINE uint8_t __CLZ(uint32_t data) { if (data == 0U) { return 32U; } uint32_t count = 0U; uint32_t mask = 0x80000000U; while ((data & mask) == 0U) { count += 1U; mask = mask >> 1U; } return count; } __STATIC_INLINE uint32_t __RBIT(uint32_t v) { uint8_t sc = 31U; uint32_t r = v; for (v >>= 1U; v; v >>= 1U) { r <<= 1U; r |= v & 1U; sc--; } return (r << sc); } __STATIC_INLINE uint32_t __get_APSR(void) { uint32_t res; __asm("MRS %0,APSR" : "=r" (res)); return res; } #endif #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) #undef __get_FPSCR #undef __set_FPSCR #define __get_FPSCR() (0) #define __set_FPSCR(VALUE) ((void)VALUE) #endif #pragma diag_suppress=Pe940 #pragma diag_suppress=Pe177 #define __enable_irq __enable_interrupt #define __disable_irq __disable_interrupt #define __NOP __no_operation #define __get_xPSR __get_PSR #if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0) __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr) { return __LDREX((unsigned long *)ptr); } __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr) { return __STREX(value, (unsigned long *)ptr); } #endif /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ #if (__CORTEX_M >= 0x03) __IAR_FT uint32_t __RRX(uint32_t value) { uint32_t result; __ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc"); return(result); } __IAR_FT void __set_BASEPRI_MAX(uint32_t value) { __asm volatile("MSR BASEPRI_MAX,%0"::"r" (value)); } #define __enable_fault_irq __enable_fiq #define __disable_fault_irq __disable_fiq #endif /* (__CORTEX_M >= 0x03) */ __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2) { return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2)); } #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) __IAR_FT uint32_t __get_MSPLIM(void) { uint32_t res; #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI res = 0U; #else __asm volatile("MRS %0,MSPLIM" : "=r" (res)); #endif return res; } __IAR_FT void __set_MSPLIM(uint32_t value) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure MSPLIM is RAZ/WI (void)value; #else __asm volatile("MSR MSPLIM,%0" :: "r" (value)); #endif } __IAR_FT uint32_t __get_PSPLIM(void) { uint32_t res; #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI res = 0U; #else __asm volatile("MRS %0,PSPLIM" : "=r" (res)); #endif return res; } __IAR_FT void __set_PSPLIM(uint32_t value) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI (void)value; #else __asm volatile("MSR PSPLIM,%0" :: "r" (value)); #endif } __IAR_FT uint32_t __TZ_get_CONTROL_NS(void) { uint32_t res; __asm volatile("MRS %0,CONTROL_NS" : "=r" (res)); return res; } __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value) { __asm volatile("MSR CONTROL_NS,%0" :: "r" (value)); } __IAR_FT uint32_t __TZ_get_PSP_NS(void) { uint32_t res; __asm volatile("MRS %0,PSP_NS" : "=r" (res)); return res; } __IAR_FT void __TZ_set_PSP_NS(uint32_t value) { __asm volatile("MSR PSP_NS,%0" :: "r" (value)); } __IAR_FT uint32_t __TZ_get_MSP_NS(void) { uint32_t res; __asm volatile("MRS %0,MSP_NS" : "=r" (res)); return res; } __IAR_FT void __TZ_set_MSP_NS(uint32_t value) { __asm volatile("MSR MSP_NS,%0" :: "r" (value)); } __IAR_FT uint32_t __TZ_get_SP_NS(void) { uint32_t res; __asm volatile("MRS %0,SP_NS" : "=r" (res)); return res; } __IAR_FT void __TZ_set_SP_NS(uint32_t value) { __asm volatile("MSR SP_NS,%0" :: "r" (value)); } __IAR_FT uint32_t __TZ_get_PRIMASK_NS(void) { uint32_t res; __asm volatile("MRS %0,PRIMASK_NS" : "=r" (res)); return res; } __IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value) { __asm volatile("MSR PRIMASK_NS,%0" :: "r" (value)); } __IAR_FT uint32_t __TZ_get_BASEPRI_NS(void) { uint32_t res; __asm volatile("MRS %0,BASEPRI_NS" : "=r" (res)); return res; } __IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value) { __asm volatile("MSR BASEPRI_NS,%0" :: "r" (value)); } __IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void) { uint32_t res; __asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res)); return res; } __IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value) { __asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value)); } __IAR_FT uint32_t __TZ_get_PSPLIM_NS(void) { uint32_t res; #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI res = 0U; #else __asm volatile("MRS %0,PSPLIM_NS" : "=r" (res)); #endif return res; } __IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value) { #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) // without main extensions, the non-secure PSPLIM is RAZ/WI (void)value; #else __asm volatile("MSR PSPLIM_NS,%0" :: "r" (value)); #endif } __IAR_FT uint32_t __TZ_get_MSPLIM_NS(void) { uint32_t res; __asm volatile("MRS %0,MSPLIM_NS" : "=r" (res)); return res; } __IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value) { __asm volatile("MSR MSPLIM_NS,%0" :: "r" (value)); } #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ #endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */ #define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value)) #if __IAR_M0_FAMILY __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) { if ((sat >= 1U) && (sat <= 32U)) { const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); const int32_t min = -1 - max ; if (val > max) { return max; } else if (val < min) { return min; } } return val; } __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) { if (sat <= 31U) { const uint32_t max = ((1U << sat) - 1U); if (val > (int32_t)max) { return max; } else if (val < 0) { return 0U; } } return (uint32_t)val; } #endif #if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ __IAR_FT uint8_t __LDRBT(volatile uint8_t *addr) { uint32_t res; __ASM("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); return ((uint8_t)res); } __IAR_FT uint16_t __LDRHT(volatile uint16_t *addr) { uint32_t res; __ASM("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); return ((uint16_t)res); } __IAR_FT uint32_t __LDRT(volatile uint32_t *addr) { uint32_t res; __ASM("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); return res; } __IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr) { __ASM("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); } __IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr) { __ASM("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); } __IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr) { __ASM("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory"); } #endif /* (__CORTEX_M >= 0x03) */ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) __IAR_FT uint8_t __LDAB(volatile uint8_t *ptr) { uint32_t res; __ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); return ((uint8_t)res); } __IAR_FT uint16_t __LDAH(volatile uint16_t *ptr) { uint32_t res; __ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); return ((uint16_t)res); } __IAR_FT uint32_t __LDA(volatile uint32_t *ptr) { uint32_t res; __ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); return res; } __IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr) { __ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); } __IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr) { __ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); } __IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr) { __ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); } __IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr) { uint32_t res; __ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); return ((uint8_t)res); } __IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr) { uint32_t res; __ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); return ((uint16_t)res); } __IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr) { uint32_t res; __ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); return res; } __IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) { uint32_t res; __ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); return res; } __IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) { uint32_t res; __ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); return res; } __IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) { uint32_t res; __ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); return res; } #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ #undef __IAR_FT #undef __IAR_M0_FAMILY #undef __ICCARM_V8 #pragma diag_default=Pe940 #pragma diag_default=Pe177 #endif /* __CMSIS_ICCARM_H__ */ micropython-1.12/lib/cmsis/inc/cmsis_version.h000066400000000000000000000032151357706137100215140ustar00rootroot00000000000000/**************************************************************************//** * @file cmsis_version.h * @brief CMSIS Core(M) Version definitions * @version V5.0.2 * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CMSIS_VERSION_H #define __CMSIS_VERSION_H /* CMSIS Version definitions */ #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ #define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */ #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ #endif micropython-1.12/lib/cmsis/inc/core_armv81mml.h000066400000000000000000005114711357706137100214750ustar00rootroot00000000000000/**************************************************************************//** * @file core_armv81mml.h * @brief CMSIS Armv8.1-M Mainline Core Peripheral Access Layer Header File * @version V1.0.0 * @date 15. March 2019 ******************************************************************************/ /* * Copyright (c) 2018-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_ARMV81MML_H_GENERIC #define __CORE_ARMV81MML_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_ARMV81MML @{ */ #include "cmsis_version.h" #define __ARM_ARCH_8M_MAIN__ 1 // patching for now /* CMSIS ARMV81MML definitions */ #define __ARMv81MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __ARMv81MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __ARMv81MML_CMSIS_VERSION ((__ARMv81MML_CMSIS_VERSION_MAIN << 16U) | \ __ARMv81MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (81U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined(__ARM_FEATURE_DSP) #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined(__ARM_FEATURE_DSP) #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined(__ARM_FEATURE_DSP) #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined(__ARM_FEATURE_DSP) #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_ARMV81MML_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_ARMV81MML_H_DEPENDANT #define __CORE_ARMV81MML_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __ARMv81MML_REV #define __ARMv81MML_REV 0x0000U #warning "__ARMv81MML_REV not defined in device header file; using default!" #endif #ifndef __FPU_PRESENT #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __SAUREGION_PRESENT #define __SAUREGION_PRESENT 0U #warning "__SAUREGION_PRESENT not defined in device header file; using default!" #endif #ifndef __DSP_PRESENT #define __DSP_PRESENT 0U #warning "__DSP_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group ARMv81MML */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register - Core SAU Register - Core FPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ #define APSR_Q_Pos 27U /*!< APSR: Q Position */ #define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ #define APSR_GE_Pos 16U /*!< APSR: GE Position */ #define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ #define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ #define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ #define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ #define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ #define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ #define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[16U]; __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[16U]; __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[16U]; __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[16U]; __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[16U]; __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ uint32_t RESERVED5[16U]; __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED6[580U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ #define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ #define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ uint32_t RESERVED3[92U]; __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ uint32_t RESERVED4[15U]; __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ uint32_t RESERVED5[1U]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ uint32_t RESERVED7[6U]; __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ uint32_t RESERVED8[1U]; __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ #define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ #define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ #define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ #define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ #define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ #define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ #define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ #define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ #define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ #define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ #define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ #define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ #define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ #define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ #define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ #define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ #define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ #define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ #define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ #define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ #define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ #define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ #define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ #define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ #define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ #define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ #define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ #define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ #define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ #define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ #define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ #define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ #define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ #define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ #define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ #define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ #define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ #define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ #define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ #define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ #define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ #define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ #define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ #define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ #define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ /* SCB Configurable Fault Status Register Definitions */ #define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ #define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ #define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ #define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ #define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ #define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ #define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ #define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ #define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ #define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ #define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ #define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ #define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ #define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ #define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ #define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ #define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ #define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ #define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ #define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ #define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ #define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ /* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ #define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ #define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ #define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ #define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ #define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ #define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ #define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ #define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ #define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ #define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ #define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ #define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ #define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ #define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ #define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ #define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ #define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ /* SCB Debug Fault Status Register Definitions */ #define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ #define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ #define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ #define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ #define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ #define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ #define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ #define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ #define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ #define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ /* SCB Non-Secure Access Control Register Definitions */ #define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ #define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ #define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ #define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ #define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ #define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ /* SCB Cache Level ID Register Definitions */ #define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ #define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ #define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ #define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ /* SCB Cache Type Register Definitions */ #define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ #define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ #define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ #define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ #define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ #define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ #define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ #define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ #define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ #define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ /* SCB Cache Size ID Register Definitions */ #define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ #define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ #define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ #define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ #define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ #define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ #define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ #define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ #define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ #define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ #define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ #define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ #define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ #define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ /* SCB Cache Size Selection Register Definitions */ #define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ #define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ #define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ #define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ /* SCB Software Triggered Interrupt Register Definitions */ #define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ #define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ /* SCB D-Cache Invalidate by Set-way Register Definitions */ #define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ #define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ #define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ #define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ /* SCB D-Cache Clean by Set-way Register Definitions */ #define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ #define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ #define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ #define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ /* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ #define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ #define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ #define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ #define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ /* Instruction Tightly-Coupled Memory Control Register Definitions */ #define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ #define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ #define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ #define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ #define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ #define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ #define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ #define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ /* Data Tightly-Coupled Memory Control Register Definitions */ #define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ #define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ #define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ #define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ #define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ #define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ #define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ #define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ /* AHBP Control Register Definitions */ #define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ #define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ #define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ #define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ /* L1 Cache Control Register Definitions */ #define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ #define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ #define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ #define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ #define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ #define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ /* AHBS Control Register Definitions */ #define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ #define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ #define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ #define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ #define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ #define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ /* Auxiliary Bus Fault Status Register Definitions */ #define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ #define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ #define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ #define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ #define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ #define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ #define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ #define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ #define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ #define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ #define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ #define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ #define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) \brief Type definitions for the Instrumentation Trace Macrocell (ITM) @{ */ /** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). */ typedef struct { __OM union { __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ uint32_t RESERVED0[864U]; __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ uint32_t RESERVED1[15U]; __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ uint32_t RESERVED3[29U]; __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ uint32_t RESERVED5[1U]; __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ uint32_t RESERVED6[4U]; __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Stimulus Port Register Definitions */ #define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ #define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ #define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ #define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ #define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ #define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ #define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ #define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ #define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ #define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ #define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ #define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ #define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ #define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ #define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ #define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ #define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ #define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ #define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ #define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ #define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ #define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ /* ITM Integration Write Register Definitions */ #define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ #define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ /* ITM Integration Read Register Definitions */ #define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ #define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ /* ITM Integration Mode Control Register Definitions */ #define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ #define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ #define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ #define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ #define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ #define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ /*@}*/ /* end of group CMSIS_ITM */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ uint32_t RESERVED1[1U]; __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ uint32_t RESERVED3[1U]; __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED4[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ uint32_t RESERVED5[1U]; __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED6[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ uint32_t RESERVED7[1U]; __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ uint32_t RESERVED8[1U]; __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ uint32_t RESERVED9[1U]; __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ uint32_t RESERVED10[1U]; __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ uint32_t RESERVED11[1U]; __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ uint32_t RESERVED12[1U]; __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ uint32_t RESERVED13[1U]; __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ uint32_t RESERVED14[1U]; __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ uint32_t RESERVED15[1U]; __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ uint32_t RESERVED16[1U]; __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ uint32_t RESERVED17[1U]; __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ uint32_t RESERVED18[1U]; __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ uint32_t RESERVED19[1U]; __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ uint32_t RESERVED20[1U]; __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ uint32_t RESERVED21[1U]; __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ uint32_t RESERVED22[1U]; __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ uint32_t RESERVED23[1U]; __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ uint32_t RESERVED24[1U]; __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ uint32_t RESERVED25[1U]; __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ uint32_t RESERVED26[1U]; __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ uint32_t RESERVED27[1U]; __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ uint32_t RESERVED28[1U]; __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ uint32_t RESERVED29[1U]; __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ uint32_t RESERVED30[1U]; __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ uint32_t RESERVED31[1U]; __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ uint32_t RESERVED32[934U]; __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ uint32_t RESERVED33[1U]; __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ #define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ #define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ #define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ #define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ #define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ #define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ #define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ #define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ #define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ #define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ #define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ #define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ #define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ #define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ #define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ #define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ #define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ #define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ #define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ #define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ #define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ #define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ #define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ #define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ #define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ #define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ /* DWT CPI Count Register Definitions */ #define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ #define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ /* DWT Exception Overhead Count Register Definitions */ #define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ #define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ /* DWT Sleep Count Register Definitions */ #define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ #define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ /* DWT LSU Count Register Definitions */ #define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ #define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ /* DWT Folded-instruction Count Register Definitions */ #define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ #define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ #define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ #define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ #define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ #define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ uint32_t RESERVED5[39U]; __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ uint32_t RESERVED7[8U]; __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ #define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI TRIGGER Register Definitions */ #define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ #define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ /* TPI Integration ETM Data Register Definitions (FIFO0) */ #define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ #define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ #define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ #define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ #define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ #define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ #define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ #define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ #define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ #define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ #define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ #define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ #define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ #define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ #define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ #define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ #define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ #define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ #define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ #define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ #define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ #define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ #define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ #define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ #define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ #define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ #define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ #define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ #define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ #define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ #define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ #define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ #define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ #define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ #define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ uint32_t RESERVED0[1]; union { __IOM uint32_t MAIR[2]; struct { __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ }; }; } MPU_Type; #define MPU_TYPE_RALIASES 4U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ #define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ #define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ #define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ #define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ #define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ #define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ #define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ /* MPU Region Limit Address Register Definitions */ #define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ #define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ #define MPU_RLAR_PXN_Pos 4U /*!< MPU RLAR: PXN Position */ #define MPU_RLAR_PXN_Msk (0x1UL << MPU_RLAR_PXN_Pos) /*!< MPU RLAR: PXN Mask */ #define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ #define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ #define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ #define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ /* MPU Memory Attribute Indirection Register 0 Definitions */ #define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ #define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ #define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ #define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ #define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ #define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ #define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ #define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ /* MPU Memory Attribute Indirection Register 1 Definitions */ #define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ #define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ #define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ #define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ #define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ #define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ #define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ #define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ /*@} end of group CMSIS_MPU */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \ingroup CMSIS_core_register \defgroup CMSIS_SAU Security Attribution Unit (SAU) \brief Type definitions for the Security Attribution Unit (SAU) @{ */ /** \brief Structure type to access the Security Attribution Unit (SAU). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #else uint32_t RESERVED0[3]; #endif __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ } SAU_Type; /* SAU Control Register Definitions */ #define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ #define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ #define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ #define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ /* SAU Type Register Definitions */ #define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ #define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) /* SAU Region Number Register Definitions */ #define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ #define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ /* SAU Region Base Address Register Definitions */ #define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ #define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ /* SAU Region Limit Address Register Definitions */ #define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ #define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ #define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ #define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ #define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ #define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ #endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ /* Secure Fault Status Register Definitions */ #define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ #define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ #define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ #define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ #define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ #define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ #define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ #define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ #define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ #define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ #define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ #define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ #define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ #define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ #define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ #define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ /*@} end of group CMSIS_SAU */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \ingroup CMSIS_core_register \defgroup CMSIS_FPU Floating Point Unit (FPU) \brief Type definitions for the Floating Point Unit (FPU) @{ */ /** \brief Structure type to access the Floating Point Unit (FPU). */ typedef struct { uint32_t RESERVED0[1U]; __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ #define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ #define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ #define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ #define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ #define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ #define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ #define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ #define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ #define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ #define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ #define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ #define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ #define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ #define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ #define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ #define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ #define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ #define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ #define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ #define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ #define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ #define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ #define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ #define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ #define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ #define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ #define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ #define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ #define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ #define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ #define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ #define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ #define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ #define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ /* Floating-Point Context Address Register Definitions */ #define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ #define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ /* Floating-Point Default Status Control Register Definitions */ #define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ #define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ #define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ #define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ #define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ #define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ #define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ #define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ /* Media and FP Feature Register 0 Definitions */ #define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ #define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ #define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ #define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ #define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ #define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ #define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ #define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ #define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ #define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ #define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ #define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ #define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ #define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ #define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ #define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ /* Media and FP Feature Register 1 Definitions */ #define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ #define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ #define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ #define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ #define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ #define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ #define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ #define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ /*@} end of group CMSIS_FPU */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ uint32_t RESERVED4[1U]; __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ #define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ #define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register Definitions */ #define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ #define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ #define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ #define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ #define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ #define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ #define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ #define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ #define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ #define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ #define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ #define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ #define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ #define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ #define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ #define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ #define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ #define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ #define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ #define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ #define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /* Debug Authentication Control Register Definitions */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ /* Debug Security Control and Status Register Definitions */ #define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ #define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ #define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ #define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ #define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ #define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ #endif #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ #endif #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Debug Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ SCB->AIRCR = reg_value; } /** \brief Get Priority Grouping \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Get Interrupt Target State \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure \return 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Target State \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Clear Interrupt Target State \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t *vectors = (uint32_t *)SCB->VTOR; vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t *vectors = (uint32_t *)SCB->VTOR; return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Set Priority Grouping (non-secure) \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB_NS->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ SCB_NS->AIRCR = reg_value; } /** \brief Get Priority Grouping (non-secure) \details Reads the priority grouping field from the non-secure NVIC when in secure state. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) { return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt (non-secure) \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status (non-secure) \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt (non-secure) \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Pending Interrupt (non-secure) \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt (non-secure) \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt (non-secure) \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt (non-secure) \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority (non-secure) \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every non-secure processor exception. */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority (non-secure) \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv8.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { uint32_t mvfr0; mvfr0 = FPU->MVFR0; if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) { return 2U; /* Double + Single precision FPU */ } else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) { return 1U; /* Single precision FPU */ } else { return 0U; /* No FPU */ } } /*@} end of CMSIS_Core_FpuFunctions */ /* ########################## SAU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SAUFunctions SAU Functions \brief Functions that configure the SAU. @{ */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Enable SAU \details Enables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Enable(void) { SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } /** \brief Disable SAU \details Disables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Disable(void) { SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_SAUFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief System Tick Configuration (non-secure) \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function TZ_SysTick_Config_NS is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ #endif /*@} end of CMSIS_Core_SysTickFunctions */ /* ##################################### Debug In/Output function ########################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_core_DebugFunctions ITM Functions \brief Functions that access the ITM debug interface. @{ */ extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ #define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** \brief ITM Send Character \details Transmits a character via the ITM channel 0, and \li Just returns when no debugger is connected that has booked the output. \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. \param [in] ch Character to transmit. \returns Character to transmit. */ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ { while (ITM->PORT[0U].u32 == 0UL) { __NOP(); } ITM->PORT[0U].u8 = (uint8_t)ch; } return (ch); } /** \brief ITM Receive Character \details Inputs a character via the external variable \ref ITM_RxBuffer. \return Received character. \return -1 No character pending. */ __STATIC_INLINE int32_t ITM_ReceiveChar (void) { int32_t ch = -1; /* no character available */ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { ch = ITM_RxBuffer; ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ } return (ch); } /** \brief ITM Check Character \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. \return 0 No character available. \return 1 Character available. */ __STATIC_INLINE int32_t ITM_CheckChar (void) { if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { return (0); /* no character available */ } else { return (1); /* character available */ } } /*@} end of CMSIS_core_DebugFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_ARMV81MML_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_armv8mbl.h000066400000000000000000002735141357706137100214040ustar00rootroot00000000000000/**************************************************************************//** * @file core_armv8mbl.h * @brief CMSIS Armv8-M Baseline Core Peripheral Access Layer Header File * @version V5.0.8 * @date 12. November 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_ARMV8MBL_H_GENERIC #define __CORE_ARMV8MBL_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_ARMv8MBL @{ */ #include "cmsis_version.h" /* CMSIS definitions */ #define __ARMv8MBL_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __ARMv8MBL_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __ARMv8MBL_CMSIS_VERSION ((__ARMv8MBL_CMSIS_VERSION_MAIN << 16U) | \ __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M ( 2U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all */ #define __FPU_USED 0U #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_ARMV8MBL_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_ARMV8MBL_H_DEPENDANT #define __CORE_ARMV8MBL_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __ARMv8MBL_REV #define __ARMv8MBL_REV 0x0000U #warning "__ARMv8MBL_REV not defined in device header file; using default!" #endif #ifndef __FPU_PRESENT #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __SAUREGION_PRESENT #define __SAUREGION_PRESENT 0U #warning "__SAUREGION_PRESENT not defined in device header file; using default!" #endif #ifndef __VTOR_PRESENT #define __VTOR_PRESENT 0U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 2U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #ifndef __ETM_PRESENT #define __ETM_PRESENT 0U #warning "__ETM_PRESENT not defined in device header file; using default!" #endif #ifndef __MTB_PRESENT #define __MTB_PRESENT 0U #warning "__MTB_PRESENT not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group ARMv8MBL */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register - Core SAU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[16U]; __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[16U]; __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[16U]; __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[16U]; __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[16U]; __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ uint32_t RESERVED5[16U]; __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ #else uint32_t RESERVED0; #endif __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ uint32_t RESERVED1; __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ #define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ #define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ #define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ #define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ #define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ #define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ #endif /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ #define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ #define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ #define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ #define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ #define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ #define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ #define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ #define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ #define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ #define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ #define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ #define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ #define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ #define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ #define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ #define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ #define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ uint32_t RESERVED0[6U]; __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ uint32_t RESERVED1[1U]; __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ uint32_t RESERVED3[1U]; __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED4[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ uint32_t RESERVED5[1U]; __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED6[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ uint32_t RESERVED7[1U]; __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ uint32_t RESERVED8[1U]; __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ uint32_t RESERVED9[1U]; __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ uint32_t RESERVED10[1U]; __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ uint32_t RESERVED11[1U]; __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ uint32_t RESERVED12[1U]; __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ uint32_t RESERVED13[1U]; __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ uint32_t RESERVED14[1U]; __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ uint32_t RESERVED15[1U]; __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ uint32_t RESERVED16[1U]; __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ uint32_t RESERVED17[1U]; __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ uint32_t RESERVED18[1U]; __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ uint32_t RESERVED19[1U]; __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ uint32_t RESERVED20[1U]; __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ uint32_t RESERVED21[1U]; __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ uint32_t RESERVED22[1U]; __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ uint32_t RESERVED23[1U]; __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ uint32_t RESERVED24[1U]; __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ uint32_t RESERVED25[1U]; __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ uint32_t RESERVED26[1U]; __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ uint32_t RESERVED27[1U]; __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ uint32_t RESERVED28[1U]; __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ uint32_t RESERVED29[1U]; __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ uint32_t RESERVED30[1U]; __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ uint32_t RESERVED31[1U]; __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ #define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ #define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ #define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ #define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ uint32_t RESERVED3[809U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */ uint32_t RESERVED4[4U]; __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */ #define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ #define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI Periodic Synchronization Control Register Definitions */ #define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */ #define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */ /* TPI Software Lock Status Register Definitions */ #define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */ #define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */ #define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */ #define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */ #define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */ #define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */ #define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ uint32_t RESERVED0[7U]; union { __IOM uint32_t MAIR[2]; struct { __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ }; }; } MPU_Type; #define MPU_TYPE_RALIASES 1U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ #define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ #define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ #define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ #define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ #define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ #define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ #define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ /* MPU Region Limit Address Register Definitions */ #define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ #define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ #define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ #define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ #define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */ #define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */ /* MPU Memory Attribute Indirection Register 0 Definitions */ #define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ #define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ #define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ #define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ #define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ #define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ #define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ #define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ /* MPU Memory Attribute Indirection Register 1 Definitions */ #define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ #define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ #define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ #define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ #define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ #define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ #define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ #define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ /*@} end of group CMSIS_MPU */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \ingroup CMSIS_core_register \defgroup CMSIS_SAU Security Attribution Unit (SAU) \brief Type definitions for the Security Attribution Unit (SAU) @{ */ /** \brief Structure type to access the Security Attribution Unit (SAU). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #endif } SAU_Type; /* SAU Control Register Definitions */ #define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ #define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ #define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ #define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ /* SAU Type Register Definitions */ #define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ #define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) /* SAU Region Number Register Definitions */ #define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ #define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ /* SAU Region Base Address Register Definitions */ #define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ #define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ /* SAU Region Limit Address Register Definitions */ #define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ #define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ #define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ #define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ #define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ #define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ #endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ /*@} end of group CMSIS_SAU */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ uint32_t RESERVED4[1U]; __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ #define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register */ #define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */ #define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /* Debug Authentication Control Register Definitions */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ /* Debug Security Control and Status Register Definitions */ #define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ #define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ #define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ #define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ #define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ #define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ #endif #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* Special LR values for Secure/Non-Secure call handling and exception handling */ /* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ #define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ /* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ #define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ #define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ #define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ #define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ #define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ #define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ #define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ /* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ #define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ #else #define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ #endif /* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) #define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) #define __NVIC_SetPriorityGrouping(X) (void)(X) #define __NVIC_GetPriorityGrouping() (0U) /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Get Interrupt Target State \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure \return 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Target State \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Clear Interrupt Target State \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. If VTOR is not present address 0 must be mapped to SRAM. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) uint32_t *vectors = (uint32_t *)SCB->VTOR; #else uint32_t *vectors = (uint32_t *)0x0U; #endif vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) uint32_t *vectors = (uint32_t *)SCB->VTOR; #else uint32_t *vectors = (uint32_t *)0x0U; #endif return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk); __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Enable Interrupt (non-secure) \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status (non-secure) \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt (non-secure) \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Pending Interrupt (non-secure) \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt (non-secure) \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt (non-secure) \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt (non-secure) \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority (non-secure) \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every non-secure processor exception. */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority (non-secure) \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv8.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { return 0U; /* No FPU */ } /*@} end of CMSIS_Core_FpuFunctions */ /* ########################## SAU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SAUFunctions SAU Functions \brief Functions that configure the SAU. @{ */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Enable SAU \details Enables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Enable(void) { SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } /** \brief Disable SAU \details Disables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Disable(void) { SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_SAUFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief System Tick Configuration (non-secure) \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function TZ_SysTick_Config_NS is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ #endif /*@} end of CMSIS_Core_SysTickFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_ARMV8MBL_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_armv8mml.h000066400000000000000000004653421357706137100214210ustar00rootroot00000000000000/**************************************************************************//** * @file core_armv8mml.h * @brief CMSIS Armv8-M Mainline Core Peripheral Access Layer Header File * @version V5.1.0 * @date 12. September 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_ARMV8MML_H_GENERIC #define __CORE_ARMV8MML_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_ARMv8MML @{ */ #include "cmsis_version.h" /* CMSIS Armv8MML definitions */ #define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __ARMv8MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __ARMv8MML_CMSIS_VERSION ((__ARMv8MML_CMSIS_VERSION_MAIN << 16U) | \ __ARMv8MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (81U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined(__ARM_FEATURE_DSP) #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined(__ARM_FEATURE_DSP) #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined(__ARM_FEATURE_DSP) #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined(__ARM_FEATURE_DSP) #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_ARMV8MML_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_ARMV8MML_H_DEPENDANT #define __CORE_ARMV8MML_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __ARMv8MML_REV #define __ARMv8MML_REV 0x0000U #warning "__ARMv8MML_REV not defined in device header file; using default!" #endif #ifndef __FPU_PRESENT #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __SAUREGION_PRESENT #define __SAUREGION_PRESENT 0U #warning "__SAUREGION_PRESENT not defined in device header file; using default!" #endif #ifndef __DSP_PRESENT #define __DSP_PRESENT 0U #warning "__DSP_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group ARMv8MML */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register - Core SAU Register - Core FPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ #define APSR_Q_Pos 27U /*!< APSR: Q Position */ #define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ #define APSR_GE_Pos 16U /*!< APSR: GE Position */ #define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ #define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ #define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ #define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ #define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ #define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ #define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[16U]; __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[16U]; __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[16U]; __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[16U]; __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[16U]; __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ uint32_t RESERVED5[16U]; __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED6[580U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ #define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ #define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ uint32_t RESERVED3[92U]; __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ uint32_t RESERVED4[15U]; __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ uint32_t RESERVED5[1U]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ #define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ #define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ #define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ #define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ #define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ #define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ #define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ #define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ #define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ #define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ #define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ #define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ #define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ #define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ #define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ #define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ #define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ #define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ #define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ #define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ #define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ #define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ #define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ #define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ #define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ #define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ #define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ #define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ #define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ #define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ #define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ #define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ #define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ #define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ #define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ #define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ #define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ #define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ #define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ #define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ #define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ #define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ #define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ #define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ #define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ /* SCB Configurable Fault Status Register Definitions */ #define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ #define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ #define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ #define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ #define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ #define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ #define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ #define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ #define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ #define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ #define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ #define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ #define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ #define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ #define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ #define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ #define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ #define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ #define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ #define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ #define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ #define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ /* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ #define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ #define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ #define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ #define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ #define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ #define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ #define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ #define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ #define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ #define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ #define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ #define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ #define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ #define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ #define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ #define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ #define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ /* SCB Debug Fault Status Register Definitions */ #define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ #define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ #define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ #define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ #define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ #define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ #define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ #define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ #define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ #define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ /* SCB Non-Secure Access Control Register Definitions */ #define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ #define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ #define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ #define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ #define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ #define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ /* SCB Cache Level ID Register Definitions */ #define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ #define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ #define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ #define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ /* SCB Cache Type Register Definitions */ #define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ #define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ #define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ #define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ #define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ #define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ #define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ #define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ #define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ #define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ /* SCB Cache Size ID Register Definitions */ #define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ #define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ #define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ #define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ #define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ #define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ #define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ #define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ #define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ #define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ #define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ #define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ #define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ #define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ /* SCB Cache Size Selection Register Definitions */ #define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ #define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ #define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ #define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ /* SCB Software Triggered Interrupt Register Definitions */ #define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ #define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ /* SCB D-Cache Invalidate by Set-way Register Definitions */ #define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ #define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ #define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ #define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ /* SCB D-Cache Clean by Set-way Register Definitions */ #define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ #define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ #define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ #define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ /* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ #define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ #define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ #define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ #define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ #define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) \brief Type definitions for the Instrumentation Trace Macrocell (ITM) @{ */ /** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). */ typedef struct { __OM union { __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ uint32_t RESERVED0[864U]; __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ uint32_t RESERVED1[15U]; __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ uint32_t RESERVED5[1U]; __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ uint32_t RESERVED6[4U]; __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Stimulus Port Register Definitions */ #define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ #define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ #define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ #define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ #define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ #define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ #define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ #define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ #define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ #define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ #define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ #define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ #define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ #define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ #define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ #define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ #define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ #define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ #define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ #define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ #define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ #define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ #define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ #define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ #define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ #define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ /*@}*/ /* end of group CMSIS_ITM */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ uint32_t RESERVED1[1U]; __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ uint32_t RESERVED3[1U]; __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED4[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ uint32_t RESERVED5[1U]; __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED6[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ uint32_t RESERVED7[1U]; __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ uint32_t RESERVED8[1U]; __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ uint32_t RESERVED9[1U]; __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ uint32_t RESERVED10[1U]; __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ uint32_t RESERVED11[1U]; __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ uint32_t RESERVED12[1U]; __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ uint32_t RESERVED13[1U]; __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ uint32_t RESERVED14[1U]; __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ uint32_t RESERVED15[1U]; __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ uint32_t RESERVED16[1U]; __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ uint32_t RESERVED17[1U]; __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ uint32_t RESERVED18[1U]; __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ uint32_t RESERVED19[1U]; __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ uint32_t RESERVED20[1U]; __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ uint32_t RESERVED21[1U]; __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ uint32_t RESERVED22[1U]; __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ uint32_t RESERVED23[1U]; __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ uint32_t RESERVED24[1U]; __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ uint32_t RESERVED25[1U]; __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ uint32_t RESERVED26[1U]; __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ uint32_t RESERVED27[1U]; __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ uint32_t RESERVED28[1U]; __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ uint32_t RESERVED29[1U]; __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ uint32_t RESERVED30[1U]; __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ uint32_t RESERVED31[1U]; __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ uint32_t RESERVED32[934U]; __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ uint32_t RESERVED33[1U]; __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ #define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ #define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ #define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ #define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ #define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ #define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ #define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ #define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ #define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ #define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ #define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ #define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ #define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ #define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ #define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ #define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ #define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ #define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ #define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ #define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ #define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ #define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ #define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ #define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ #define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ #define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ /* DWT CPI Count Register Definitions */ #define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ #define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ /* DWT Exception Overhead Count Register Definitions */ #define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ #define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ /* DWT Sleep Count Register Definitions */ #define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ #define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ /* DWT LSU Count Register Definitions */ #define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ #define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ /* DWT Folded-instruction Count Register Definitions */ #define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ #define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ #define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ #define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ #define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ #define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ uint32_t RESERVED3[809U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */ uint32_t RESERVED4[4U]; __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */ #define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ #define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI Periodic Synchronization Control Register Definitions */ #define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */ #define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */ /* TPI Software Lock Status Register Definitions */ #define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */ #define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */ #define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */ #define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */ #define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */ #define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */ #define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ uint32_t RESERVED0[1]; union { __IOM uint32_t MAIR[2]; struct { __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ }; }; } MPU_Type; #define MPU_TYPE_RALIASES 4U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ #define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ #define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ #define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ #define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ #define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ #define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ #define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ /* MPU Region Limit Address Register Definitions */ #define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ #define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ #define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ #define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ #define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ #define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ /* MPU Memory Attribute Indirection Register 0 Definitions */ #define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ #define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ #define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ #define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ #define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ #define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ #define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ #define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ /* MPU Memory Attribute Indirection Register 1 Definitions */ #define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ #define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ #define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ #define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ #define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ #define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ #define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ #define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ /*@} end of group CMSIS_MPU */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \ingroup CMSIS_core_register \defgroup CMSIS_SAU Security Attribution Unit (SAU) \brief Type definitions for the Security Attribution Unit (SAU) @{ */ /** \brief Structure type to access the Security Attribution Unit (SAU). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #else uint32_t RESERVED0[3]; #endif __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ } SAU_Type; /* SAU Control Register Definitions */ #define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ #define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ #define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ #define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ /* SAU Type Register Definitions */ #define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ #define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) /* SAU Region Number Register Definitions */ #define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ #define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ /* SAU Region Base Address Register Definitions */ #define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ #define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ /* SAU Region Limit Address Register Definitions */ #define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ #define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ #define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ #define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ #define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ #define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ #endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ /* Secure Fault Status Register Definitions */ #define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ #define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ #define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ #define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ #define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ #define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ #define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ #define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ #define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ #define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ #define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ #define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ #define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ #define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ #define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ #define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ /*@} end of group CMSIS_SAU */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \ingroup CMSIS_core_register \defgroup CMSIS_FPU Floating Point Unit (FPU) \brief Type definitions for the Floating Point Unit (FPU) @{ */ /** \brief Structure type to access the Floating Point Unit (FPU). */ typedef struct { uint32_t RESERVED0[1U]; __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ #define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ #define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ #define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ #define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ #define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ #define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ #define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ #define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ #define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ #define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ #define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ #define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ #define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ #define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ #define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ #define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ #define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ #define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ #define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ #define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ #define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ #define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ #define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ #define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ #define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ #define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ #define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ #define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ #define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ #define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ #define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ #define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ #define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ #define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ /* Floating-Point Context Address Register Definitions */ #define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ #define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ /* Floating-Point Default Status Control Register Definitions */ #define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ #define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ #define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ #define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ #define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ #define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ #define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ #define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ /* Media and FP Feature Register 0 Definitions */ #define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ #define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ #define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ #define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ #define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ #define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ #define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ #define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ #define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ #define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ #define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ #define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ #define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ #define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ #define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ #define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ /* Media and FP Feature Register 1 Definitions */ #define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ #define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ #define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ #define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ #define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ #define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ #define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ #define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ /*@} end of group CMSIS_FPU */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ uint32_t RESERVED4[1U]; __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ #define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ #define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register Definitions */ #define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ #define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ #define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ #define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ #define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ #define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ #define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ #define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ #define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ #define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ #define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ #define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ #define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ #define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ #define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ #define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ #define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ #define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ #define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ #define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ #define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /* Debug Authentication Control Register Definitions */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ /* Debug Security Control and Status Register Definitions */ #define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ #define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ #define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ #define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ #define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ #define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ #endif #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ #endif #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Debug Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* Special LR values for Secure/Non-Secure call handling and exception handling */ /* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ #define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ /* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ #define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ #define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ #define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ #define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ #define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ #define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ #define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ /* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ #define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ #else #define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ #endif /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } /** \brief Get Priority Grouping \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Get Interrupt Target State \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure \return 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Target State \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Clear Interrupt Target State \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t *vectors = (uint32_t *)SCB->VTOR; vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t *vectors = (uint32_t *)SCB->VTOR; return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Set Priority Grouping (non-secure) \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB_NS->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB_NS->AIRCR = reg_value; } /** \brief Get Priority Grouping (non-secure) \details Reads the priority grouping field from the non-secure NVIC when in secure state. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) { return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt (non-secure) \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status (non-secure) \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt (non-secure) \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Pending Interrupt (non-secure) \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt (non-secure) \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt (non-secure) \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt (non-secure) \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority (non-secure) \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every non-secure processor exception. */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority (non-secure) \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv8.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { uint32_t mvfr0; mvfr0 = FPU->MVFR0; if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) { return 2U; /* Double + Single precision FPU */ } else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) { return 1U; /* Single precision FPU */ } else { return 0U; /* No FPU */ } } /*@} end of CMSIS_Core_FpuFunctions */ /* ########################## SAU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SAUFunctions SAU Functions \brief Functions that configure the SAU. @{ */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Enable SAU \details Enables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Enable(void) { SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } /** \brief Disable SAU \details Disables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Disable(void) { SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_SAUFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief System Tick Configuration (non-secure) \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function TZ_SysTick_Config_NS is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ #endif /*@} end of CMSIS_Core_SysTickFunctions */ /* ##################################### Debug In/Output function ########################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_core_DebugFunctions ITM Functions \brief Functions that access the ITM debug interface. @{ */ extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ #define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** \brief ITM Send Character \details Transmits a character via the ITM channel 0, and \li Just returns when no debugger is connected that has booked the output. \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. \param [in] ch Character to transmit. \returns Character to transmit. */ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ { while (ITM->PORT[0U].u32 == 0UL) { __NOP(); } ITM->PORT[0U].u8 = (uint8_t)ch; } return (ch); } /** \brief ITM Receive Character \details Inputs a character via the external variable \ref ITM_RxBuffer. \return Received character. \return -1 No character pending. */ __STATIC_INLINE int32_t ITM_ReceiveChar (void) { int32_t ch = -1; /* no character available */ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { ch = ITM_RxBuffer; ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ } return (ch); } /** \brief ITM Check Character \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. \return 0 No character available. \return 1 Character available. */ __STATIC_INLINE int32_t ITM_CheckChar (void) { if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { return (0); /* no character available */ } else { return (1); /* character available */ } } /*@} end of CMSIS_core_DebugFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_ARMV8MML_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm0.h000066400000000000000000001205031357706137100203200ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm0.h * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File * @version V5.0.6 * @date 13. March 2019 ******************************************************************************/ /* * Copyright (c) 2009-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM0_H_GENERIC #define __CORE_CM0_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_M0 @{ */ #include "cmsis_version.h" /* CMSIS CM0 definitions */ #define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM0_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \ __CM0_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (0U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all */ #define __FPU_USED 0U #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM0_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM0_H_DEPENDANT #define __CORE_CM0_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM0_REV #define __CM0_REV 0x0000U #warning "__CM0_REV not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 2U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex_M0 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t _reserved0:1; /*!< bit: 0 Reserved */ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[31U]; __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RESERVED1[31U]; __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[31U]; __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[31U]; uint32_t RESERVED4[64U]; __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ uint32_t RESERVED0; __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ uint32_t RESERVED1; __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. Therefore they are not covered by the Cortex-M0 header file. @{ */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ /*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0 */ #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* The following EXC_RETURN values are saved the LR on exception entry */ #define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ #define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ #define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ /* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) #define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) #define __NVIC_SetPriorityGrouping(X) (void)(X) #define __NVIC_GetPriorityGrouping() (0U) /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. Address 0 must be mapped to SRAM. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t vectors = 0x0U; (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t vectors = 0x0U; return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk); __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { return 0U; /* No FPU */ } /*@} end of CMSIS_Core_FpuFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /*@} end of CMSIS_Core_SysTickFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM0_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm0plus.h000066400000000000000000001403401357706137100212250ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm0plus.h * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File * @version V5.0.7 * @date 13. March 2019 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM0PLUS_H_GENERIC #define __CORE_CM0PLUS_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex-M0+ @{ */ #include "cmsis_version.h" /* CMSIS CM0+ definitions */ #define __CM0PLUS_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM0PLUS_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \ __CM0PLUS_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (0U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all */ #define __FPU_USED 0U #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM0PLUS_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM0PLUS_H_DEPENDANT #define __CORE_CM0PLUS_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM0PLUS_REV #define __CM0PLUS_REV 0x0000U #warning "__CM0PLUS_REV not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __VTOR_PRESENT #define __VTOR_PRESENT 0U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 2U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex-M0+ */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core MPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[31U]; __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RESERVED1[31U]; __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[31U]; __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[31U]; uint32_t RESERVED4[64U]; __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ #else uint32_t RESERVED0; #endif __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ uint32_t RESERVED1; __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) /* SCB Interrupt Control State Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 8U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ #endif /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ } MPU_Type; #define MPU_TYPE_RALIASES 1U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ #define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ #define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ #define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ #define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ #define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ /* MPU Region Attribute and Size Register Definitions */ #define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ #define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ #define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ #define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ #define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ #define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ #define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ #define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ #define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ #define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ #define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ #define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ #define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ #define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ #define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ #define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ #define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ #define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ #define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ #define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ /*@} end of group CMSIS_MPU */ #endif /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. Therefore they are not covered by the Cortex-M0+ header file. @{ */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ /*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0+ */ #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* The following EXC_RETURN values are saved the LR on exception entry */ #define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ #define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ #define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ /* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) #define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) #define __NVIC_SetPriorityGrouping(X) (void)(X) #define __NVIC_GetPriorityGrouping() (0U) /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. If VTOR is not present address 0 must be mapped to SRAM. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) uint32_t vectors = SCB->VTOR; #else uint32_t vectors = 0x0U; #endif (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) uint32_t vectors = SCB->VTOR; #else uint32_t vectors = 0x0U; #endif return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk); __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv7.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { return 0U; /* No FPU */ } /*@} end of CMSIS_Core_FpuFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /*@} end of CMSIS_Core_SysTickFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM0PLUS_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm1.h000066400000000000000000001227571357706137100203360ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm1.h * @brief CMSIS Cortex-M1 Core Peripheral Access Layer Header File * @version V1.0.1 * @date 12. November 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM1_H_GENERIC #define __CORE_CM1_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_M1 @{ */ #include "cmsis_version.h" /* CMSIS CM1 definitions */ #define __CM1_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM1_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM1_CMSIS_VERSION ((__CM1_CMSIS_VERSION_MAIN << 16U) | \ __CM1_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (1U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all */ #define __FPU_USED 0U #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM1_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM1_H_DEPENDANT #define __CORE_CM1_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM1_REV #define __CM1_REV 0x0100U #warning "__CM1_REV not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 2U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex_M1 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t _reserved0:1; /*!< bit: 0 Reserved */ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[31U]; __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[31U]; __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[31U]; __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[31U]; uint32_t RESERVED4[64U]; __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ uint32_t RESERVED0; __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ uint32_t RESERVED1; __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[2U]; __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ } SCnSCB_Type; /* Auxiliary Control Register Definitions */ #define SCnSCB_ACTLR_ITCMUAEN_Pos 4U /*!< ACTLR: Instruction TCM Upper Alias Enable Position */ #define SCnSCB_ACTLR_ITCMUAEN_Msk (1UL << SCnSCB_ACTLR_ITCMUAEN_Pos) /*!< ACTLR: Instruction TCM Upper Alias Enable Mask */ #define SCnSCB_ACTLR_ITCMLAEN_Pos 3U /*!< ACTLR: Instruction TCM Lower Alias Enable Position */ #define SCnSCB_ACTLR_ITCMLAEN_Msk (1UL << SCnSCB_ACTLR_ITCMLAEN_Pos) /*!< ACTLR: Instruction TCM Lower Alias Enable Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Cortex-M1 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. Therefore they are not covered by the Cortex-M1 header file. @{ */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ /*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M1 */ #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* The following EXC_RETURN values are saved the LR on exception entry */ #define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ #define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ #define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ /* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) #define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) #define __NVIC_SetPriorityGrouping(X) (void)(X) #define __NVIC_GetPriorityGrouping() (0U) /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. Address 0 must be mapped to SRAM. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t *vectors = (uint32_t *)0x0U; vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t *vectors = (uint32_t *)0x0U; return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk); __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { return 0U; /* No FPU */ } /*@} end of CMSIS_Core_FpuFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /*@} end of CMSIS_Core_SysTickFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM1_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm23.h000066400000000000000000003103521357706137100204100ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm23.h * @brief CMSIS Cortex-M23 Core Peripheral Access Layer Header File * @version V5.0.8 * @date 12. November 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM23_H_GENERIC #define __CORE_CM23_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_M23 @{ */ #include "cmsis_version.h" /* CMSIS definitions */ #define __CM23_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM23_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM23_CMSIS_VERSION ((__CM23_CMSIS_VERSION_MAIN << 16U) | \ __CM23_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (23U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all */ #define __FPU_USED 0U #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM23_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM23_H_DEPENDANT #define __CORE_CM23_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM23_REV #define __CM23_REV 0x0000U #warning "__CM23_REV not defined in device header file; using default!" #endif #ifndef __FPU_PRESENT #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __SAUREGION_PRESENT #define __SAUREGION_PRESENT 0U #warning "__SAUREGION_PRESENT not defined in device header file; using default!" #endif #ifndef __VTOR_PRESENT #define __VTOR_PRESENT 0U #warning "__VTOR_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 2U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #ifndef __ETM_PRESENT #define __ETM_PRESENT 0U #warning "__ETM_PRESENT not defined in device header file; using default!" #endif #ifndef __MTB_PRESENT #define __MTB_PRESENT 0U #warning "__MTB_PRESENT not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex_M23 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register - Core SAU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[16U]; __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[16U]; __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[16U]; __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[16U]; __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[16U]; __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ uint32_t RESERVED5[16U]; __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ #else uint32_t RESERVED0; #endif __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ uint32_t RESERVED1; __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ #define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ #define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ #define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ #define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ #define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ #define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ #endif /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ #define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ #define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ #define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ #define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ #define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ #define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ #define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ #define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ #define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ #define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ #define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ #define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ #define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ #define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ #define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ #define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ #define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ uint32_t RESERVED0[6U]; __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ uint32_t RESERVED1[1U]; __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ uint32_t RESERVED3[1U]; __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED4[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ uint32_t RESERVED5[1U]; __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED6[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ uint32_t RESERVED7[1U]; __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ uint32_t RESERVED8[1U]; __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ uint32_t RESERVED9[1U]; __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ uint32_t RESERVED10[1U]; __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ uint32_t RESERVED11[1U]; __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ uint32_t RESERVED12[1U]; __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ uint32_t RESERVED13[1U]; __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ uint32_t RESERVED14[1U]; __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ uint32_t RESERVED15[1U]; __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ uint32_t RESERVED16[1U]; __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ uint32_t RESERVED17[1U]; __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ uint32_t RESERVED18[1U]; __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ uint32_t RESERVED19[1U]; __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ uint32_t RESERVED20[1U]; __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ uint32_t RESERVED21[1U]; __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ uint32_t RESERVED22[1U]; __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ uint32_t RESERVED23[1U]; __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ uint32_t RESERVED24[1U]; __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ uint32_t RESERVED25[1U]; __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ uint32_t RESERVED26[1U]; __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ uint32_t RESERVED27[1U]; __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ uint32_t RESERVED28[1U]; __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ uint32_t RESERVED29[1U]; __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ uint32_t RESERVED30[1U]; __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ uint32_t RESERVED31[1U]; __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ #define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ #define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ #define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ #define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ uint32_t RESERVED3[759U]; __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ uint32_t RESERVED4[1U]; __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ uint32_t RESERVED5[39U]; __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ uint32_t RESERVED7[8U]; __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ #define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ #define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI TRIGGER Register Definitions */ #define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ #define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ /* TPI Integration Test FIFO Test Data 0 Register Definitions */ #define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ #define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ #define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ #define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ #define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ #define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ #define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ #define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ #define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ #define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ #define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ #define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ #define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ #define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ /* TPI Integration Test ATB Control Register 2 Register Definitions */ #define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ #define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ #define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ #define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ #define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ #define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ #define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ #define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ /* TPI Integration Test FIFO Test Data 1 Register Definitions */ #define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ #define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ #define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ #define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ #define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ #define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ #define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ #define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ #define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ #define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ #define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ #define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ #define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ #define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ /* TPI Integration Test ATB Control Register 0 Definitions */ #define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ #define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ #define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ #define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ #define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ #define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ #define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ #define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ #define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ #define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ #define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ #define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ uint32_t RESERVED0[7U]; union { __IOM uint32_t MAIR[2]; struct { __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ }; }; } MPU_Type; #define MPU_TYPE_RALIASES 1U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ #define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ #define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ #define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ #define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ #define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ #define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ #define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ /* MPU Region Limit Address Register Definitions */ #define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ #define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ #define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ #define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ #define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */ #define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */ /* MPU Memory Attribute Indirection Register 0 Definitions */ #define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ #define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ #define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ #define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ #define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ #define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ #define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ #define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ /* MPU Memory Attribute Indirection Register 1 Definitions */ #define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ #define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ #define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ #define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ #define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ #define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ #define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ #define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ /*@} end of group CMSIS_MPU */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \ingroup CMSIS_core_register \defgroup CMSIS_SAU Security Attribution Unit (SAU) \brief Type definitions for the Security Attribution Unit (SAU) @{ */ /** \brief Structure type to access the Security Attribution Unit (SAU). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #endif } SAU_Type; /* SAU Control Register Definitions */ #define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ #define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ #define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ #define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ /* SAU Type Register Definitions */ #define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ #define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) /* SAU Region Number Register Definitions */ #define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ #define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ /* SAU Region Base Address Register Definitions */ #define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ #define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ /* SAU Region Limit Address Register Definitions */ #define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ #define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ #define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ #define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ #define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ #define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ #endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ /*@} end of group CMSIS_SAU */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ uint32_t RESERVED4[1U]; __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ #define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register */ #define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */ #define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /* Debug Authentication Control Register Definitions */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ /* Debug Security Control and Status Register Definitions */ #define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ #define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ #define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ #define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ #define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ #define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ #endif #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else /*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for Cortex-M23 */ /*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for Cortex-M23 */ #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* Special LR values for Secure/Non-Secure call handling and exception handling */ /* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ #define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ /* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ #define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ #define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ #define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ #define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ #define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ #define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ #define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ /* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ #define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ #else #define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ #endif /* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) #define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) #define __NVIC_SetPriorityGrouping(X) (void)(X) #define __NVIC_GetPriorityGrouping() (0U) /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Get Interrupt Target State \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure \return 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Target State \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Clear Interrupt Target State \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. If VTOR is not present address 0 must be mapped to SRAM. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) uint32_t *vectors = (uint32_t *)SCB->VTOR; #else uint32_t *vectors = (uint32_t *)0x0U; #endif vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) uint32_t *vectors = (uint32_t *)SCB->VTOR; #else uint32_t *vectors = (uint32_t *)0x0U; #endif return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk); __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Enable Interrupt (non-secure) \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status (non-secure) \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt (non-secure) \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Pending Interrupt (non-secure) \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt (non-secure) \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt (non-secure) \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt (non-secure) \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority (non-secure) \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every non-secure processor exception. */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority (non-secure) \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv8.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { return 0U; /* No FPU */ } /*@} end of CMSIS_Core_FpuFunctions */ /* ########################## SAU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SAUFunctions SAU Functions \brief Functions that configure the SAU. @{ */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Enable SAU \details Enables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Enable(void) { SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } /** \brief Disable SAU \details Disables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Disable(void) { SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_SAUFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief System Tick Configuration (non-secure) \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function TZ_SysTick_Config_NS is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ #endif /*@} end of CMSIS_Core_SysTickFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM23_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm3.h000066400000000000000000003253311357706137100203310ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm3.h * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File * @version V5.1.0 * @date 13. March 2019 ******************************************************************************/ /* * Copyright (c) 2009-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM3_H_GENERIC #define __CORE_CM3_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_M3 @{ */ #include "cmsis_version.h" /* CMSIS CM3 definitions */ #define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (3U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all */ #define __FPU_USED 0U #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM3_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM3_H_DEPENDANT #define __CORE_CM3_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM3_REV #define __CM3_REV 0x0200U #warning "__CM3_REV not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex_M3 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ #define APSR_Q_Pos 27U /*!< APSR: Q Position */ #define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:1; /*!< bit: 9 Reserved */ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit */ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ #define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ #define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ #define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[24U]; __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RESERVED1[24U]; __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[24U]; __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[24U]; __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[56U]; __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED5[644U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ #define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ #define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ uint32_t RESERVED0[5U]; __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ #if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */ #define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ #define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ #else #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ #endif /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ #define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ #define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ #define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ #define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ #define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ #define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ #define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ #define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ #define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ #define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ #define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ #define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ #define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ #define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ #define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ #define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ #define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ #define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ /* SCB Configurable Fault Status Register Definitions */ #define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ #define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ #define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ #define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ #define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ #define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ #define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ #define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ #define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ #define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ #define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ #define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ #define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ #define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ #define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ #define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ #define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ #define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ #define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ /* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ #define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ #define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ #define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ #define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ #define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ #define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ #define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ #define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ #define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ #define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ #define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ #define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ #define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ #define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ #define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ /* SCB Debug Fault Status Register Definitions */ #define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ #define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ #define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ #define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ #define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ #define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ #define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ #define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ #define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ #define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ #if defined (__CM3_REV) && (__CM3_REV >= 0x200U) __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ #else uint32_t RESERVED1[1U]; #endif } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ #define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /* Auxiliary Control Register Definitions */ #if defined (__CM3_REV) && (__CM3_REV >= 0x200U) #define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ #define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ #define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ #define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ #define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ #define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ #define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ #define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ #define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ #define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ #endif /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) \brief Type definitions for the Instrumentation Trace Macrocell (ITM) @{ */ /** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). */ typedef struct { __OM union { __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ uint32_t RESERVED0[864U]; __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ uint32_t RESERVED1[15U]; __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ uint32_t RESERVED5[6U]; __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ #define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ #define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ #define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ #define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ #define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ #define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ #define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ #define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ #define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ #define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ #define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ #define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ #define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ #define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ #define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ #define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ #define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ #define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ #define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ #define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ /*@}*/ /* end of group CMSIS_ITM */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED0[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED1[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ #define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ #define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ #define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ #define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ #define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ #define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ #define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ #define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ #define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ #define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ #define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ #define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ #define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ #define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ #define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ #define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ #define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ #define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ #define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ #define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ #define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ #define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ #define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ #define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ /* DWT CPI Count Register Definitions */ #define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ #define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ /* DWT Exception Overhead Count Register Definitions */ #define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ #define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ /* DWT Sleep Count Register Definitions */ #define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ #define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ /* DWT LSU Count Register Definitions */ #define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ #define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ /* DWT Folded-instruction Count Register Definitions */ #define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ #define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ /* DWT Comparator Mask Register Definitions */ #define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ #define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ #define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ #define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ #define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ #define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ #define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ #define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ #define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ #define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ #define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ #define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ #define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ #define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ uint32_t RESERVED5[39U]; __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ uint32_t RESERVED7[8U]; __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ #define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI TRIGGER Register Definitions */ #define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ #define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ /* TPI Integration ETM Data Register Definitions (FIFO0) */ #define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ #define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ #define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ #define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ #define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ #define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ #define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ #define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ #define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ #define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ #define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ #define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ #define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ #define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ #define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ #define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ #define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ #define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ #define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ #define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ #define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ #define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ #define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ #define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ #define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ #define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ #define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ #define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ #define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ #define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ #define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ #define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ #define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ #define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ #define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ #define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ #define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ #define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; #define MPU_TYPE_RALIASES 4U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ #define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ #define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ #define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ #define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ #define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ /* MPU Region Attribute and Size Register Definitions */ #define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ #define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ #define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ #define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ #define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ #define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ #define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ #define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ #define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ #define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ #define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ #define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ #define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ #define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ #define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ #define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ #define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ #define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ #define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ #define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ /*@} end of group CMSIS_MPU */ #endif /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ #define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register Definitions */ #define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ #define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ #define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ #define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ #define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ #define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ #define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ #define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ #define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ #define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ #define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ #define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ #define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ #define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ #define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ #define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ #define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ #define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ #define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ #define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ #define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Debug Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* The following EXC_RETURN values are saved the LR on exception entry */ #define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ #define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ #define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } /** \brief Get Priority Grouping \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t vectors = (uint32_t )SCB->VTOR; (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t vectors = (uint32_t )SCB->VTOR; return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv7.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { return 0U; /* No FPU */ } /*@} end of CMSIS_Core_FpuFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /*@} end of CMSIS_Core_SysTickFunctions */ /* ##################################### Debug In/Output function ########################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_core_DebugFunctions ITM Functions \brief Functions that access the ITM debug interface. @{ */ extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ #define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** \brief ITM Send Character \details Transmits a character via the ITM channel 0, and \li Just returns when no debugger is connected that has booked the output. \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. \param [in] ch Character to transmit. \returns Character to transmit. */ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ { while (ITM->PORT[0U].u32 == 0UL) { __NOP(); } ITM->PORT[0U].u8 = (uint8_t)ch; } return (ch); } /** \brief ITM Receive Character \details Inputs a character via the external variable \ref ITM_RxBuffer. \return Received character. \return -1 No character pending. */ __STATIC_INLINE int32_t ITM_ReceiveChar (void) { int32_t ch = -1; /* no character available */ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { ch = ITM_RxBuffer; ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ } return (ch); } /** \brief ITM Check Character \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. \return 0 No character available. \return 1 Character available. */ __STATIC_INLINE int32_t ITM_CheckChar (void) { if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { return (0); /* no character available */ } else { return (1); /* character available */ } } /*@} end of CMSIS_core_DebugFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM3_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm33.h000066400000000000000000005022361357706137100204150ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm33.h * @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File * @version V5.1.0 * @date 12. November 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM33_H_GENERIC #define __CORE_CM33_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_M33 @{ */ #include "cmsis_version.h" /* CMSIS CM33 definitions */ #define __CM33_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM33_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM33_CMSIS_VERSION ((__CM33_CMSIS_VERSION_MAIN << 16U) | \ __CM33_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (33U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) #if defined (__TARGET_FPU_VFP) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined (__ARM_FP) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __ICCARM__ ) #if defined (__ARMVFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __TI_ARM__ ) #if defined (__TI_VFP_SUPPORT__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __TASKING__ ) #if defined (__FPU_VFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM33_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM33_H_DEPENDANT #define __CORE_CM33_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM33_REV #define __CM33_REV 0x0000U #warning "__CM33_REV not defined in device header file; using default!" #endif #ifndef __FPU_PRESENT #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __SAUREGION_PRESENT #define __SAUREGION_PRESENT 0U #warning "__SAUREGION_PRESENT not defined in device header file; using default!" #endif #ifndef __DSP_PRESENT #define __DSP_PRESENT 0U #warning "__DSP_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex_M33 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register - Core SAU Register - Core FPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ #define APSR_Q_Pos 27U /*!< APSR: Q Position */ #define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ #define APSR_GE_Pos 16U /*!< APSR: GE Position */ #define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ #define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ #define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ #define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ #define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ #define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ #define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[16U]; __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[16U]; __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[16U]; __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[16U]; __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[16U]; __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ uint32_t RESERVED5[16U]; __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED6[580U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ #define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ #define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ uint32_t RESERVED3[92U]; __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ uint32_t RESERVED4[15U]; __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ uint32_t RESERVED5[1U]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ #define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ #define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ #define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ #define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ #define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ #define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ #define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ #define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ #define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ #define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ #define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ #define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ #define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ #define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ #define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ #define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ #define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ #define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ #define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ #define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ #define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ #define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ #define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ #define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ #define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ #define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ #define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ #define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ #define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ #define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ #define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ #define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ #define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ #define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ #define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ #define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ #define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ #define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ #define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ #define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ #define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ #define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ #define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ #define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ #define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ /* SCB Configurable Fault Status Register Definitions */ #define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ #define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ #define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ #define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ #define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ #define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ #define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ #define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ #define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ #define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ #define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ #define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ #define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ #define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ #define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ #define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ #define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ #define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ #define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ #define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ #define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ #define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ /* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ #define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ #define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ #define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ #define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ #define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ #define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ #define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ #define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ #define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ #define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ #define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ #define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ #define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ #define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ #define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ #define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ #define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ /* SCB Debug Fault Status Register Definitions */ #define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ #define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ #define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ #define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ #define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ #define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ #define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ #define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ #define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ #define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ /* SCB Non-Secure Access Control Register Definitions */ #define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ #define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ #define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ #define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ #define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ #define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ /* SCB Cache Level ID Register Definitions */ #define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ #define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ #define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ #define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ /* SCB Cache Type Register Definitions */ #define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ #define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ #define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ #define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ #define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ #define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ #define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ #define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ #define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ #define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ /* SCB Cache Size ID Register Definitions */ #define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ #define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ #define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ #define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ #define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ #define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ #define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ #define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ #define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ #define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ #define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ #define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ #define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ #define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ /* SCB Cache Size Selection Register Definitions */ #define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ #define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ #define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ #define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ /* SCB Software Triggered Interrupt Register Definitions */ #define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ #define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ /* SCB D-Cache Invalidate by Set-way Register Definitions */ #define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ #define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ #define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ #define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ /* SCB D-Cache Clean by Set-way Register Definitions */ #define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ #define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ #define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ #define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ /* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ #define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ #define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ #define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ #define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ #define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) \brief Type definitions for the Instrumentation Trace Macrocell (ITM) @{ */ /** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). */ typedef struct { __OM union { __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ uint32_t RESERVED0[864U]; __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ uint32_t RESERVED1[15U]; __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ uint32_t RESERVED5[1U]; __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ uint32_t RESERVED6[4U]; __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Stimulus Port Register Definitions */ #define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ #define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ #define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ #define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ #define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ #define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ #define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ #define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ #define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ #define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ #define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ #define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ #define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ #define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ #define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ #define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ #define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ #define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ #define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ #define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ #define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ #define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ #define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ #define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ #define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ #define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ /*@}*/ /* end of group CMSIS_ITM */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ uint32_t RESERVED1[1U]; __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ uint32_t RESERVED3[1U]; __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED4[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ uint32_t RESERVED5[1U]; __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED6[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ uint32_t RESERVED7[1U]; __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ uint32_t RESERVED8[1U]; __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ uint32_t RESERVED9[1U]; __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ uint32_t RESERVED10[1U]; __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ uint32_t RESERVED11[1U]; __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ uint32_t RESERVED12[1U]; __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ uint32_t RESERVED13[1U]; __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ uint32_t RESERVED14[1U]; __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ uint32_t RESERVED15[1U]; __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ uint32_t RESERVED16[1U]; __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ uint32_t RESERVED17[1U]; __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ uint32_t RESERVED18[1U]; __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ uint32_t RESERVED19[1U]; __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ uint32_t RESERVED20[1U]; __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ uint32_t RESERVED21[1U]; __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ uint32_t RESERVED22[1U]; __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ uint32_t RESERVED23[1U]; __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ uint32_t RESERVED24[1U]; __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ uint32_t RESERVED25[1U]; __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ uint32_t RESERVED26[1U]; __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ uint32_t RESERVED27[1U]; __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ uint32_t RESERVED28[1U]; __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ uint32_t RESERVED29[1U]; __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ uint32_t RESERVED30[1U]; __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ uint32_t RESERVED31[1U]; __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ uint32_t RESERVED32[934U]; __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ uint32_t RESERVED33[1U]; __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ #define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ #define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ #define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ #define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ #define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ #define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ #define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ #define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ #define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ #define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ #define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ #define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ #define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ #define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ #define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ #define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ #define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ #define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ #define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ #define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ #define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ #define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ #define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ #define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ #define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ #define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ /* DWT CPI Count Register Definitions */ #define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ #define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ /* DWT Exception Overhead Count Register Definitions */ #define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ #define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ /* DWT Sleep Count Register Definitions */ #define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ #define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ /* DWT LSU Count Register Definitions */ #define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ #define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ /* DWT Folded-instruction Count Register Definitions */ #define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ #define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ #define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ #define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ #define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ #define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ uint32_t RESERVED3[759U]; __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ uint32_t RESERVED4[1U]; __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ uint32_t RESERVED5[39U]; __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ uint32_t RESERVED7[8U]; __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ #define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ #define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI TRIGGER Register Definitions */ #define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ #define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ /* TPI Integration Test FIFO Test Data 0 Register Definitions */ #define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ #define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ #define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ #define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ #define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ #define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ #define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ #define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ #define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ #define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ #define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ #define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ #define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ #define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ /* TPI Integration Test ATB Control Register 2 Register Definitions */ #define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ #define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ #define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ #define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ #define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ #define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ #define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ #define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ /* TPI Integration Test FIFO Test Data 1 Register Definitions */ #define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ #define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ #define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ #define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ #define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ #define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ #define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ #define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ #define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ #define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ #define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ #define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ #define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ #define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ /* TPI Integration Test ATB Control Register 0 Definitions */ #define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ #define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ #define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ #define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ #define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ #define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ #define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ #define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ #define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ #define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ #define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ #define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ uint32_t RESERVED0[1]; union { __IOM uint32_t MAIR[2]; struct { __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ }; }; } MPU_Type; #define MPU_TYPE_RALIASES 4U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ #define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ #define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ #define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ #define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ #define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ #define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ #define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ /* MPU Region Limit Address Register Definitions */ #define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ #define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ #define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ #define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ #define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ #define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ /* MPU Memory Attribute Indirection Register 0 Definitions */ #define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ #define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ #define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ #define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ #define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ #define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ #define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ #define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ /* MPU Memory Attribute Indirection Register 1 Definitions */ #define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ #define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ #define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ #define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ #define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ #define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ #define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ #define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ /*@} end of group CMSIS_MPU */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \ingroup CMSIS_core_register \defgroup CMSIS_SAU Security Attribution Unit (SAU) \brief Type definitions for the Security Attribution Unit (SAU) @{ */ /** \brief Structure type to access the Security Attribution Unit (SAU). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #else uint32_t RESERVED0[3]; #endif __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ } SAU_Type; /* SAU Control Register Definitions */ #define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ #define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ #define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ #define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ /* SAU Type Register Definitions */ #define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ #define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) /* SAU Region Number Register Definitions */ #define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ #define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ /* SAU Region Base Address Register Definitions */ #define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ #define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ /* SAU Region Limit Address Register Definitions */ #define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ #define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ #define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ #define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ #define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ #define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ #endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ /* Secure Fault Status Register Definitions */ #define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ #define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ #define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ #define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ #define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ #define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ #define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ #define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ #define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ #define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ #define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ #define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ #define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ #define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ #define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ #define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ /*@} end of group CMSIS_SAU */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \ingroup CMSIS_core_register \defgroup CMSIS_FPU Floating Point Unit (FPU) \brief Type definitions for the Floating Point Unit (FPU) @{ */ /** \brief Structure type to access the Floating Point Unit (FPU). */ typedef struct { uint32_t RESERVED0[1U]; __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ #define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ #define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ #define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ #define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ #define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ #define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ #define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ #define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ #define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ #define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ #define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ #define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ #define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ #define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ #define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ #define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ #define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ #define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ #define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ #define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ #define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ #define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ #define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ #define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ #define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ #define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ #define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ #define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ #define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ #define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ #define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ #define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ #define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ #define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ /* Floating-Point Context Address Register Definitions */ #define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ #define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ /* Floating-Point Default Status Control Register Definitions */ #define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ #define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ #define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ #define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ #define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ #define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ #define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ #define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ /* Media and FP Feature Register 0 Definitions */ #define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ #define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ #define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ #define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ #define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ #define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ #define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ #define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ #define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ #define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ #define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ #define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ #define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ #define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ #define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ #define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ /* Media and FP Feature Register 1 Definitions */ #define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ #define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ #define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ #define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ #define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ #define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ #define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ #define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ /*@} end of group CMSIS_FPU */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ uint32_t RESERVED4[1U]; __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ #define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ #define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register Definitions */ #define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ #define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ #define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ #define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ #define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ #define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ #define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ #define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ #define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ #define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ #define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ #define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ #define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ #define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ #define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ #define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ #define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ #define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ #define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ #define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ #define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /* Debug Authentication Control Register Definitions */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ /* Debug Security Control and Status Register Definitions */ #define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ #define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ #define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ #define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ #define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ #define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ #endif #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ #endif #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Debug Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* Special LR values for Secure/Non-Secure call handling and exception handling */ /* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ #define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ /* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ #define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ #define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ #define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ #define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ #define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ #define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ #define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ /* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ #define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ #else #define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ #endif /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } /** \brief Get Priority Grouping \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Get Interrupt Target State \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure \return 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Target State \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Clear Interrupt Target State \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t *vectors = (uint32_t *)SCB->VTOR; vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t *vectors = (uint32_t *)SCB->VTOR; return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Set Priority Grouping (non-secure) \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB_NS->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB_NS->AIRCR = reg_value; } /** \brief Get Priority Grouping (non-secure) \details Reads the priority grouping field from the non-secure NVIC when in secure state. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) { return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt (non-secure) \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status (non-secure) \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt (non-secure) \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Pending Interrupt (non-secure) \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt (non-secure) \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt (non-secure) \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt (non-secure) \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority (non-secure) \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every non-secure processor exception. */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority (non-secure) \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv8.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { uint32_t mvfr0; mvfr0 = FPU->MVFR0; if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) { return 2U; /* Double + Single precision FPU */ } else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) { return 1U; /* Single precision FPU */ } else { return 0U; /* No FPU */ } } /*@} end of CMSIS_Core_FpuFunctions */ /* ########################## SAU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SAUFunctions SAU Functions \brief Functions that configure the SAU. @{ */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Enable SAU \details Enables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Enable(void) { SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } /** \brief Disable SAU \details Disables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Disable(void) { SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_SAUFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief System Tick Configuration (non-secure) \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function TZ_SysTick_Config_NS is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ #endif /*@} end of CMSIS_Core_SysTickFunctions */ /* ##################################### Debug In/Output function ########################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_core_DebugFunctions ITM Functions \brief Functions that access the ITM debug interface. @{ */ extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ #define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** \brief ITM Send Character \details Transmits a character via the ITM channel 0, and \li Just returns when no debugger is connected that has booked the output. \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. \param [in] ch Character to transmit. \returns Character to transmit. */ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ { while (ITM->PORT[0U].u32 == 0UL) { __NOP(); } ITM->PORT[0U].u8 = (uint8_t)ch; } return (ch); } /** \brief ITM Receive Character \details Inputs a character via the external variable \ref ITM_RxBuffer. \return Received character. \return -1 No character pending. */ __STATIC_INLINE int32_t ITM_ReceiveChar (void) { int32_t ch = -1; /* no character available */ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { ch = ITM_RxBuffer; ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ } return (ch); } /** \brief ITM Check Character \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. \return 0 No character available. \return 1 Character available. */ __STATIC_INLINE int32_t ITM_CheckChar (void) { if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { return (0); /* no character available */ } else { return (1); /* character available */ } } /*@} end of CMSIS_core_DebugFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM33_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm35p.h000066400000000000000000005022501357706137100205730ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm35p.h * @brief CMSIS Cortex-M35P Core Peripheral Access Layer Header File * @version V1.0.0 * @date 12. November 2018 ******************************************************************************/ /* * Copyright (c) 2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM35P_H_GENERIC #define __CORE_CM35P_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_M35P @{ */ #include "cmsis_version.h" /* CMSIS CM35P definitions */ #define __CM35P_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM35P_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM35P_CMSIS_VERSION ((__CM35P_CMSIS_VERSION_MAIN << 16U) | \ __CM35P_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (35U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) #if defined (__TARGET_FPU_VFP) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined (__ARM_FP) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __ICCARM__ ) #if defined (__ARMVFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) #define __DSP_USED 1U #else #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" #define __DSP_USED 0U #endif #else #define __DSP_USED 0U #endif #elif defined ( __TI_ARM__ ) #if defined (__TI_VFP_SUPPORT__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __TASKING__ ) #if defined (__FPU_VFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM35P_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM35P_H_DEPENDANT #define __CORE_CM35P_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM35P_REV #define __CM35P_REV 0x0000U #warning "__CM35P_REV not defined in device header file; using default!" #endif #ifndef __FPU_PRESENT #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __SAUREGION_PRESENT #define __SAUREGION_PRESENT 0U #warning "__SAUREGION_PRESENT not defined in device header file; using default!" #endif #ifndef __DSP_PRESENT #define __DSP_PRESENT 0U #warning "__DSP_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex_M35P */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register - Core SAU Register - Core FPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ #define APSR_Q_Pos 27U /*!< APSR: Q Position */ #define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ #define APSR_GE_Pos 16U /*!< APSR: GE Position */ #define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ #define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ #define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ #define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ #define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ #define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ #define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[16U]; __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[16U]; __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[16U]; __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[16U]; __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[16U]; __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ uint32_t RESERVED5[16U]; __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED6[580U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ #define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ #define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ uint32_t RESERVED3[92U]; __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ uint32_t RESERVED4[15U]; __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ uint32_t RESERVED5[1U]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ #define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ #define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ #define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ #define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ #define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ #define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ #define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ #define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ #define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ #define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ #define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ #define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ #define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ #define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ #define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ #define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ #define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ #define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ #define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ #define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ #define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ #define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ #define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ #define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ #define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ #define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ #define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ #define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ #define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ #define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ #define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ #define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ #define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ #define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ #define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ #define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ #define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ #define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ #define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ #define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ #define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ #define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ #define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ #define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ #define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ /* SCB Configurable Fault Status Register Definitions */ #define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ #define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ #define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ #define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ #define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ #define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ #define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ #define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ #define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ #define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ #define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ #define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ #define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ #define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ #define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ #define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ #define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ #define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ #define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ #define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ #define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ #define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ /* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ #define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ #define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ #define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ #define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ #define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ #define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ #define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ #define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ #define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ #define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ #define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ #define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ #define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ #define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ #define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ #define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ #define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ /* SCB Debug Fault Status Register Definitions */ #define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ #define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ #define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ #define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ #define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ #define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ #define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ #define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ #define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ #define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ /* SCB Non-Secure Access Control Register Definitions */ #define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ #define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ #define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ #define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ #define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ #define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ /* SCB Cache Level ID Register Definitions */ #define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ #define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ #define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ #define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ /* SCB Cache Type Register Definitions */ #define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ #define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ #define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ #define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ #define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ #define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ #define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ #define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ #define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ #define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ /* SCB Cache Size ID Register Definitions */ #define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ #define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ #define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ #define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ #define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ #define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ #define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ #define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ #define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ #define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ #define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ #define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ #define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ #define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ /* SCB Cache Size Selection Register Definitions */ #define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ #define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ #define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ #define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ /* SCB Software Triggered Interrupt Register Definitions */ #define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ #define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ /* SCB D-Cache Invalidate by Set-way Register Definitions */ #define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ #define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ #define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ #define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ /* SCB D-Cache Clean by Set-way Register Definitions */ #define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ #define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ #define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ #define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ /* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ #define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ #define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ #define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ #define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ #define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) \brief Type definitions for the Instrumentation Trace Macrocell (ITM) @{ */ /** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). */ typedef struct { __OM union { __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ uint32_t RESERVED0[864U]; __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ uint32_t RESERVED1[15U]; __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ uint32_t RESERVED5[1U]; __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ uint32_t RESERVED6[4U]; __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Stimulus Port Register Definitions */ #define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ #define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ #define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ #define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ #define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ #define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ #define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ #define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ #define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ #define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ #define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ #define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ #define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ #define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ #define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ #define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ #define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ #define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ #define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ #define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ #define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ #define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ #define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ #define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ #define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ #define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ /*@}*/ /* end of group CMSIS_ITM */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ uint32_t RESERVED1[1U]; __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ uint32_t RESERVED3[1U]; __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED4[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ uint32_t RESERVED5[1U]; __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED6[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ uint32_t RESERVED7[1U]; __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ uint32_t RESERVED8[1U]; __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ uint32_t RESERVED9[1U]; __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ uint32_t RESERVED10[1U]; __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ uint32_t RESERVED11[1U]; __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ uint32_t RESERVED12[1U]; __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ uint32_t RESERVED13[1U]; __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ uint32_t RESERVED14[1U]; __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ uint32_t RESERVED15[1U]; __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ uint32_t RESERVED16[1U]; __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ uint32_t RESERVED17[1U]; __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ uint32_t RESERVED18[1U]; __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ uint32_t RESERVED19[1U]; __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ uint32_t RESERVED20[1U]; __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ uint32_t RESERVED21[1U]; __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ uint32_t RESERVED22[1U]; __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ uint32_t RESERVED23[1U]; __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ uint32_t RESERVED24[1U]; __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ uint32_t RESERVED25[1U]; __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ uint32_t RESERVED26[1U]; __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ uint32_t RESERVED27[1U]; __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ uint32_t RESERVED28[1U]; __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ uint32_t RESERVED29[1U]; __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ uint32_t RESERVED30[1U]; __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ uint32_t RESERVED31[1U]; __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ uint32_t RESERVED32[934U]; __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ uint32_t RESERVED33[1U]; __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ #define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ #define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ #define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ #define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ #define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ #define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ #define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ #define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ #define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ #define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ #define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ #define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ #define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ #define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ #define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ #define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ #define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ #define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ #define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ #define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ #define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ #define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ #define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ #define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ #define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ #define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ /* DWT CPI Count Register Definitions */ #define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ #define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ /* DWT Exception Overhead Count Register Definitions */ #define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ #define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ /* DWT Sleep Count Register Definitions */ #define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ #define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ /* DWT LSU Count Register Definitions */ #define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ #define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ /* DWT Folded-instruction Count Register Definitions */ #define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ #define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ #define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ #define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ #define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ #define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ uint32_t RESERVED3[759U]; __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ uint32_t RESERVED4[1U]; __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ uint32_t RESERVED5[39U]; __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ uint32_t RESERVED7[8U]; __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ #define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ #define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI TRIGGER Register Definitions */ #define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ #define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ /* TPI Integration Test FIFO Test Data 0 Register Definitions */ #define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ #define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ #define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ #define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ #define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ #define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ #define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ #define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ #define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ #define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ #define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ #define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ #define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ #define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ /* TPI Integration Test ATB Control Register 2 Register Definitions */ #define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ #define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ #define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ #define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ #define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ #define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ #define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ #define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ /* TPI Integration Test FIFO Test Data 1 Register Definitions */ #define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ #define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ #define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ #define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ #define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ #define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ #define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ #define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ #define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ #define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ #define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ #define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ #define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ #define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ /* TPI Integration Test ATB Control Register 0 Definitions */ #define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ #define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ #define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ #define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ #define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ #define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ #define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ #define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ #define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ #define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ #define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ #define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ uint32_t RESERVED0[1]; union { __IOM uint32_t MAIR[2]; struct { __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ }; }; } MPU_Type; #define MPU_TYPE_RALIASES 4U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ #define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ #define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ #define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ #define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ #define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ #define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ #define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ /* MPU Region Limit Address Register Definitions */ #define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ #define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ #define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ #define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ #define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ #define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ /* MPU Memory Attribute Indirection Register 0 Definitions */ #define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ #define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ #define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ #define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ #define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ #define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ #define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ #define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ /* MPU Memory Attribute Indirection Register 1 Definitions */ #define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ #define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ #define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ #define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ #define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ #define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ #define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ #define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ /*@} end of group CMSIS_MPU */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \ingroup CMSIS_core_register \defgroup CMSIS_SAU Security Attribution Unit (SAU) \brief Type definitions for the Security Attribution Unit (SAU) @{ */ /** \brief Structure type to access the Security Attribution Unit (SAU). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ #else uint32_t RESERVED0[3]; #endif __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ } SAU_Type; /* SAU Control Register Definitions */ #define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ #define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ #define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ #define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ /* SAU Type Register Definitions */ #define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ #define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ #if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) /* SAU Region Number Register Definitions */ #define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ #define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ /* SAU Region Base Address Register Definitions */ #define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ #define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ /* SAU Region Limit Address Register Definitions */ #define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ #define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ #define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ #define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ #define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ #define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ #endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ /* Secure Fault Status Register Definitions */ #define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ #define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ #define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ #define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ #define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ #define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ #define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ #define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ #define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ #define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ #define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ #define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ #define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ #define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ #define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ #define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ /*@} end of group CMSIS_SAU */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \ingroup CMSIS_core_register \defgroup CMSIS_FPU Floating Point Unit (FPU) \brief Type definitions for the Floating Point Unit (FPU) @{ */ /** \brief Structure type to access the Floating Point Unit (FPU). */ typedef struct { uint32_t RESERVED0[1U]; __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ #define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ #define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ #define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ #define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ #define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ #define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ #define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ #define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ #define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ #define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ #define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ #define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ #define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ #define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ #define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ #define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ #define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ #define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ #define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ #define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ #define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ #define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ #define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ #define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ #define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ #define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ #define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ #define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ #define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ #define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ #define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ #define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ #define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ #define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ /* Floating-Point Context Address Register Definitions */ #define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ #define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ /* Floating-Point Default Status Control Register Definitions */ #define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ #define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ #define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ #define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ #define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ #define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ #define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ #define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ /* Media and FP Feature Register 0 Definitions */ #define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ #define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ #define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ #define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ #define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ #define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ #define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ #define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ #define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ #define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ #define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ #define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ #define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ #define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ #define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ #define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ /* Media and FP Feature Register 1 Definitions */ #define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ #define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ #define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ #define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ #define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ #define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ #define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ #define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ /*@} end of group CMSIS_FPU */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ uint32_t RESERVED4[1U]; __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ #define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ #define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register Definitions */ #define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ #define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ #define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ #define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ #define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ #define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ #define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ #define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ #define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ #define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ #define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ #define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ #define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ #define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ #define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ #define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ #define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ #define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ #define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ #define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ #define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /* Debug Authentication Control Register Definitions */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ #define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ #define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ #define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ /* Debug Security Control and Status Register Definitions */ #define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ #define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ #define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ #define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ #define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ #define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ #endif #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ #endif #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Debug Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* Special LR values for Secure/Non-Secure call handling and exception handling */ /* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ #define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ /* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ #define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ #define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ #define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ #define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ #define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ #define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ #define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ /* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ #define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ #else #define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ #endif /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } /** \brief Get Priority Grouping \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Get Interrupt Target State \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure \return 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Target State \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Clear Interrupt Target State \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 if interrupt is assigned to Secure 1 if interrupt is assigned to Non Secure \note IRQn must not be negative. */ __STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t *vectors = (uint32_t *)SCB->VTOR; vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t *vectors = (uint32_t *)SCB->VTOR; return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Set Priority Grouping (non-secure) \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB_NS->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB_NS->AIRCR = reg_value; } /** \brief Get Priority Grouping (non-secure) \details Reads the priority grouping field from the non-secure NVIC when in secure state. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) { return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt (non-secure) \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status (non-secure) \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt (non-secure) \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Pending Interrupt (non-secure) \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt (non-secure) \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt (non-secure) \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt (non-secure) \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority (non-secure) \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every non-secure processor exception. */ __STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority (non-secure) \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } #endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv8.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { uint32_t mvfr0; mvfr0 = FPU->MVFR0; if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) { return 2U; /* Double + Single precision FPU */ } else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) { return 1U; /* Single precision FPU */ } else { return 0U; /* No FPU */ } } /*@} end of CMSIS_Core_FpuFunctions */ /* ########################## SAU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SAUFunctions SAU Functions \brief Functions that configure the SAU. @{ */ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief Enable SAU \details Enables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Enable(void) { SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); } /** \brief Disable SAU \details Disables the Security Attribution Unit (SAU). */ __STATIC_INLINE void TZ_SAU_Disable(void) { SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ /*@} end of CMSIS_Core_SAUFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /** \brief System Tick Configuration (non-secure) \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function TZ_SysTick_Config_NS is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ #endif /*@} end of CMSIS_Core_SysTickFunctions */ /* ##################################### Debug In/Output function ########################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_core_DebugFunctions ITM Functions \brief Functions that access the ITM debug interface. @{ */ extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ #define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** \brief ITM Send Character \details Transmits a character via the ITM channel 0, and \li Just returns when no debugger is connected that has booked the output. \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. \param [in] ch Character to transmit. \returns Character to transmit. */ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ { while (ITM->PORT[0U].u32 == 0UL) { __NOP(); } ITM->PORT[0U].u8 = (uint8_t)ch; } return (ch); } /** \brief ITM Receive Character \details Inputs a character via the external variable \ref ITM_RxBuffer. \return Received character. \return -1 No character pending. */ __STATIC_INLINE int32_t ITM_ReceiveChar (void) { int32_t ch = -1; /* no character available */ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { ch = ITM_RxBuffer; ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ } return (ch); } /** \brief ITM Check Character \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. \return 0 No character available. \return 1 Character available. */ __STATIC_INLINE int32_t ITM_CheckChar (void) { if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { return (0); /* no character available */ } else { return (1); /* character available */ } } /*@} end of CMSIS_core_DebugFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM35P_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm4.h000066400000000000000000003536201357706137100203340ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm4.h * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File * @version V5.1.0 * @date 13. March 2019 ******************************************************************************/ /* * Copyright (c) 2009-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM4_H_GENERIC #define __CORE_CM4_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_M4 @{ */ #include "cmsis_version.h" /* CMSIS CM4 definitions */ #define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (4U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM4_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM4_H_DEPENDANT #define __CORE_CM4_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM4_REV #define __CM4_REV 0x0000U #warning "__CM4_REV not defined in device header file; using default!" #endif #ifndef __FPU_PRESENT #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex_M4 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register - Core FPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ #define APSR_Q_Pos 27U /*!< APSR: Q Position */ #define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ #define APSR_GE_Pos 16U /*!< APSR: GE Position */ #define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:1; /*!< bit: 9 Reserved */ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit */ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ #define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ #define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ #define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ #define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ #define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ #define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[24U]; __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RESERVED1[24U]; __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[24U]; __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[24U]; __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[56U]; __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED5[644U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ #define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ #define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ uint32_t RESERVED0[5U]; __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ #define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ #define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ #define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ #define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ #define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ #define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ #define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ #define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ #define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ #define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ #define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ #define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ #define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ #define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ #define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ #define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ #define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ #define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ /* SCB Configurable Fault Status Register Definitions */ #define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ #define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ #define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ #define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ #define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ #define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ #define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ #define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ #define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ #define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ #define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ #define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ #define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ #define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ #define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ #define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ #define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ #define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ #define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ #define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ #define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ #define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ /* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ #define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ #define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ #define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ #define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ #define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ #define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ #define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ #define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ #define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ #define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ #define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ #define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ #define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ #define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ #define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ /* SCB Debug Fault Status Register Definitions */ #define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ #define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ #define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ #define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ #define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ #define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ #define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ #define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ #define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ #define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ #define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /* Auxiliary Control Register Definitions */ #define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ #define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ #define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ #define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ #define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ #define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ #define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ #define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ #define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ #define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) \brief Type definitions for the Instrumentation Trace Macrocell (ITM) @{ */ /** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). */ typedef struct { __OM union { __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ uint32_t RESERVED0[864U]; __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ uint32_t RESERVED1[15U]; __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ uint32_t RESERVED5[6U]; __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ #define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ #define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ #define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ #define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ #define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ #define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ #define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ #define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ #define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ #define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ #define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ #define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ #define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ #define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ #define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ #define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ #define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ #define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ #define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ #define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ /*@}*/ /* end of group CMSIS_ITM */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED0[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED1[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ #define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ #define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ #define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ #define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ #define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ #define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ #define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ #define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ #define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ #define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ #define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ #define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ #define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ #define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ #define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ #define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ #define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ #define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ #define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ #define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ #define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ #define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ #define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ #define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ /* DWT CPI Count Register Definitions */ #define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ #define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ /* DWT Exception Overhead Count Register Definitions */ #define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ #define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ /* DWT Sleep Count Register Definitions */ #define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ #define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ /* DWT LSU Count Register Definitions */ #define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ #define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ /* DWT Folded-instruction Count Register Definitions */ #define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ #define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ /* DWT Comparator Mask Register Definitions */ #define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ #define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ #define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ #define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ #define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ #define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ #define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ #define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ #define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ #define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ #define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ #define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ #define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ #define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ uint32_t RESERVED5[39U]; __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ uint32_t RESERVED7[8U]; __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ #define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI TRIGGER Register Definitions */ #define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ #define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ /* TPI Integration ETM Data Register Definitions (FIFO0) */ #define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ #define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ #define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ #define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ #define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ #define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ #define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ #define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ #define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ #define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ #define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ #define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ #define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ #define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ #define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ #define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ #define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ #define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ #define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ #define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ #define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ #define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ #define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ #define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ #define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ #define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ #define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ #define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ #define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ #define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ #define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ #define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ #define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ #define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ #define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ #define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ #define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ #define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; #define MPU_TYPE_RALIASES 4U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ #define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ #define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ #define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ #define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ #define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ /* MPU Region Attribute and Size Register Definitions */ #define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ #define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ #define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ #define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ #define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ #define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ #define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ #define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ #define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ #define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ #define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ #define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ #define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ #define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ #define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ #define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ #define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ #define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ #define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ #define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ /*@} end of group CMSIS_MPU */ #endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ /** \ingroup CMSIS_core_register \defgroup CMSIS_FPU Floating Point Unit (FPU) \brief Type definitions for the Floating Point Unit (FPU) @{ */ /** \brief Structure type to access the Floating Point Unit (FPU). */ typedef struct { uint32_t RESERVED0[1U]; __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ #define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ #define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ #define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ #define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ #define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ #define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ #define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ #define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ #define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ #define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ #define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ #define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ #define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ #define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ #define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ #define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ #define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ #define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ /* Floating-Point Context Address Register Definitions */ #define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ #define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ /* Floating-Point Default Status Control Register Definitions */ #define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ #define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ #define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ #define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ #define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ #define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ #define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ #define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ /* Media and FP Feature Register 0 Definitions */ #define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ #define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ #define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ #define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ #define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ #define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ #define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ #define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ #define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ #define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ #define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ #define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ #define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ #define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ #define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ #define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ /* Media and FP Feature Register 1 Definitions */ #define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ #define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ #define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ #define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ #define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ #define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ #define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ #define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ /* Media and FP Feature Register 2 Definitions */ #define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ #define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ /*@} end of group CMSIS_FPU */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ #define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register Definitions */ #define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ #define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ #define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ #define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ #define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ #define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ #define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ #define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ #define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ #define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ #define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ #define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ #define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ #define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ #define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ #define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ #define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ #define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ #define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ #define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ #define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Debug Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* The following EXC_RETURN values are saved the LR on exception entry */ #define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ #define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ #define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ #define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ #define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ #define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } /** \brief Get Priority Grouping \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t vectors = (uint32_t )SCB->VTOR; (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t vectors = (uint32_t )SCB->VTOR; return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv7.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { uint32_t mvfr0; mvfr0 = FPU->MVFR0; if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) { return 1U; /* Single precision FPU */ } else { return 0U; /* No FPU */ } } /*@} end of CMSIS_Core_FpuFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /*@} end of CMSIS_Core_SysTickFunctions */ /* ##################################### Debug In/Output function ########################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_core_DebugFunctions ITM Functions \brief Functions that access the ITM debug interface. @{ */ extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ #define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** \brief ITM Send Character \details Transmits a character via the ITM channel 0, and \li Just returns when no debugger is connected that has booked the output. \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. \param [in] ch Character to transmit. \returns Character to transmit. */ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ { while (ITM->PORT[0U].u32 == 0UL) { __NOP(); } ITM->PORT[0U].u8 = (uint8_t)ch; } return (ch); } /** \brief ITM Receive Character \details Inputs a character via the external variable \ref ITM_RxBuffer. \return Received character. \return -1 No character pending. */ __STATIC_INLINE int32_t ITM_ReceiveChar (void) { int32_t ch = -1; /* no character available */ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { ch = ITM_RxBuffer; ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ } return (ch); } /** \brief ITM Check Character \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. \return 0 No character available. \return 1 Character available. */ __STATIC_INLINE int32_t ITM_CheckChar (void) { if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { return (0); /* no character available */ } else { return (1); /* character available */ } } /*@} end of CMSIS_core_DebugFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM4_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_cm7.h000066400000000000000000004405311357706137100203350ustar00rootroot00000000000000/**************************************************************************//** * @file core_cm7.h * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File * @version V5.1.0 * @date 13. March 2019 ******************************************************************************/ /* * Copyright (c) 2009-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_CM7_H_GENERIC #define __CORE_CM7_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup Cortex_M7 @{ */ #include "cmsis_version.h" /* CMSIS CM7 definitions */ #define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (7U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #define __FPU_USED 0U #endif #else #define __FPU_USED 0U #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_CM7_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_CM7_H_DEPENDANT #define __CORE_CM7_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __CM7_REV #define __CM7_REV 0x0000U #warning "__CM7_REV not defined in device header file; using default!" #endif #ifndef __FPU_PRESENT #define __FPU_PRESENT 0U #warning "__FPU_PRESENT not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __ICACHE_PRESENT #define __ICACHE_PRESENT 0U #warning "__ICACHE_PRESENT not defined in device header file; using default!" #endif #ifndef __DCACHE_PRESENT #define __DCACHE_PRESENT 0U #warning "__DCACHE_PRESENT not defined in device header file; using default!" #endif #ifndef __DTCM_PRESENT #define __DTCM_PRESENT 0U #warning "__DTCM_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group Cortex_M7 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register - Core FPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ #define APSR_Q_Pos 27U /*!< APSR: Q Position */ #define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ #define APSR_GE_Pos 16U /*!< APSR: GE Position */ #define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:1; /*!< bit: 9 Reserved */ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit */ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ #define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ #define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ #define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ #define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ #define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ #define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[24U]; __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RESERVED1[24U]; __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[24U]; __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[24U]; __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[56U]; __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED5[644U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ #define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ #define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ uint32_t RESERVED0[1U]; __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ uint32_t RESERVED3[93U]; __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ uint32_t RESERVED4[15U]; __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ uint32_t RESERVED5[1U]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ uint32_t RESERVED7[6U]; __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ uint32_t RESERVED8[1U]; __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ #define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ #define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ #define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ #define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ #define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ #define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ #define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ #define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ #define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ #define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ #define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ #define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ #define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ #define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ #define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ #define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ #define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ #define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ #define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ #define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ #define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ #define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ #define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ #define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ /* SCB Configurable Fault Status Register Definitions */ #define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ #define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ #define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ #define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ #define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ #define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ #define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ #define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ #define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ #define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ #define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ #define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ #define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ #define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ #define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ #define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ #define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ #define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ #define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ #define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ #define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ #define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ #define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ /* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ #define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ #define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ #define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ #define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ #define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ #define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ #define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ #define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ #define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ #define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ #define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ #define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ #define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ #define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ #define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ /* SCB Debug Fault Status Register Definitions */ #define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ #define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ #define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ #define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ #define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ #define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ #define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ #define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ #define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ #define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ /* SCB Cache Level ID Register Definitions */ #define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ #define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ #define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ #define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ /* SCB Cache Type Register Definitions */ #define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ #define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ #define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ #define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ #define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ #define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ #define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ #define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ #define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ #define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ /* SCB Cache Size ID Register Definitions */ #define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ #define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ #define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ #define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ #define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ #define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ #define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ #define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ #define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ #define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ #define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ #define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ #define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ #define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ /* SCB Cache Size Selection Register Definitions */ #define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ #define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ #define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ #define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ /* SCB Software Triggered Interrupt Register Definitions */ #define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ #define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ /* SCB D-Cache Invalidate by Set-way Register Definitions */ #define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ #define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ #define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ #define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ /* SCB D-Cache Clean by Set-way Register Definitions */ #define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ #define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ #define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ #define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ /* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ #define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ #define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ #define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ #define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ /* Instruction Tightly-Coupled Memory Control Register Definitions */ #define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ #define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ #define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ #define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ #define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ #define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ #define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ #define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ /* Data Tightly-Coupled Memory Control Register Definitions */ #define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ #define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ #define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ #define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ #define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ #define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ #define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ #define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ /* AHBP Control Register Definitions */ #define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ #define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ #define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ #define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ /* L1 Cache Control Register Definitions */ #define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ #define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ #define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ #define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ #define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ #define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ /* AHBS Control Register Definitions */ #define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ #define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ #define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ #define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ #define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ #define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ /* Auxiliary Bus Fault Status Register Definitions */ #define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ #define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ #define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ #define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ #define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ #define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ #define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ #define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ #define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ #define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ #define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ #define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ #define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /* Auxiliary Control Register Definitions */ #define SCnSCB_ACTLR_DISDYNADD_Pos 26U /*!< ACTLR: DISDYNADD Position */ #define SCnSCB_ACTLR_DISDYNADD_Msk (1UL << SCnSCB_ACTLR_DISDYNADD_Pos) /*!< ACTLR: DISDYNADD Mask */ #define SCnSCB_ACTLR_DISISSCH1_Pos 21U /*!< ACTLR: DISISSCH1 Position */ #define SCnSCB_ACTLR_DISISSCH1_Msk (0x1FUL << SCnSCB_ACTLR_DISISSCH1_Pos) /*!< ACTLR: DISISSCH1 Mask */ #define SCnSCB_ACTLR_DISDI_Pos 16U /*!< ACTLR: DISDI Position */ #define SCnSCB_ACTLR_DISDI_Msk (0x1FUL << SCnSCB_ACTLR_DISDI_Pos) /*!< ACTLR: DISDI Mask */ #define SCnSCB_ACTLR_DISCRITAXIRUR_Pos 15U /*!< ACTLR: DISCRITAXIRUR Position */ #define SCnSCB_ACTLR_DISCRITAXIRUR_Msk (1UL << SCnSCB_ACTLR_DISCRITAXIRUR_Pos) /*!< ACTLR: DISCRITAXIRUR Mask */ #define SCnSCB_ACTLR_DISBTACALLOC_Pos 14U /*!< ACTLR: DISBTACALLOC Position */ #define SCnSCB_ACTLR_DISBTACALLOC_Msk (1UL << SCnSCB_ACTLR_DISBTACALLOC_Pos) /*!< ACTLR: DISBTACALLOC Mask */ #define SCnSCB_ACTLR_DISBTACREAD_Pos 13U /*!< ACTLR: DISBTACREAD Position */ #define SCnSCB_ACTLR_DISBTACREAD_Msk (1UL << SCnSCB_ACTLR_DISBTACREAD_Pos) /*!< ACTLR: DISBTACREAD Mask */ #define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ #define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ #define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ #define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ #define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ #define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ #define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ #define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ #define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ #define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) \brief Type definitions for the Instrumentation Trace Macrocell (ITM) @{ */ /** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). */ typedef struct { __OM union { __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ uint32_t RESERVED0[864U]; __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ uint32_t RESERVED1[15U]; __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ uint32_t RESERVED5[6U]; __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ #define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ #define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ #define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ #define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ #define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ #define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ #define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ #define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ #define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ #define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ #define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ #define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ #define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ #define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ #define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ #define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ #define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ #define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ #define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ #define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ /*@}*/ /* end of group CMSIS_ITM */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED0[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED1[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ uint32_t RESERVED3[981U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ #define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ #define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ #define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ #define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ #define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ #define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ #define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ #define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ #define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ #define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ #define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ #define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ #define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ #define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ #define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ #define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ #define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ #define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ #define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ #define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ #define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ #define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ #define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ #define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ /* DWT CPI Count Register Definitions */ #define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ #define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ /* DWT Exception Overhead Count Register Definitions */ #define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ #define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ /* DWT Sleep Count Register Definitions */ #define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ #define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ /* DWT LSU Count Register Definitions */ #define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ #define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ /* DWT Folded-instruction Count Register Definitions */ #define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ #define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ /* DWT Comparator Mask Register Definitions */ #define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ #define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ #define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ #define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ #define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ #define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ #define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ #define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ #define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ #define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ #define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ #define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ #define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ #define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ uint32_t RESERVED5[39U]; __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ uint32_t RESERVED7[8U]; __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ #define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI TRIGGER Register Definitions */ #define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ #define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ /* TPI Integration ETM Data Register Definitions (FIFO0) */ #define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ #define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ #define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ #define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ #define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ #define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ #define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ #define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ #define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ #define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ #define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ #define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ #define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ #define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ #define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ #define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ #define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ #define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ #define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ #define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ #define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ #define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ #define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ #define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ #define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ #define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ #define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ #define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ #define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ #define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ #define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ #define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ #define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ #define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ #define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ #define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ #define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ #define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; #define MPU_TYPE_RALIASES 4U /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ #define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ #define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ #define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ #define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ #define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ /* MPU Region Attribute and Size Register Definitions */ #define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ #define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ #define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ #define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ #define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ #define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ #define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ #define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ #define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ #define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ #define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ #define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ #define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ #define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ #define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ #define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ #define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ #define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ #define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ #define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ /*@} end of group CMSIS_MPU */ #endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ /** \ingroup CMSIS_core_register \defgroup CMSIS_FPU Floating Point Unit (FPU) \brief Type definitions for the Floating Point Unit (FPU) @{ */ /** \brief Structure type to access the Floating Point Unit (FPU). */ typedef struct { uint32_t RESERVED0[1U]; __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ #define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ #define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ #define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ #define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ #define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ #define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ #define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ #define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ #define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ #define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ #define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ #define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ #define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ #define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ #define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ #define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ #define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ #define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ /* Floating-Point Context Address Register Definitions */ #define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ #define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ /* Floating-Point Default Status Control Register Definitions */ #define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ #define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ #define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ #define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ #define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ #define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ #define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ #define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ /* Media and FP Feature Register 0 Definitions */ #define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ #define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ #define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ #define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ #define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ #define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ #define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ #define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ #define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ #define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ #define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ #define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ #define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ #define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ #define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ #define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ /* Media and FP Feature Register 1 Definitions */ #define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ #define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ #define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ #define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ #define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ #define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ #define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ #define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ /* Media and FP Feature Register 2 Definitions */ #define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ #define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ /*@} end of group CMSIS_FPU */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ #define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register Definitions */ #define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ #define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ #define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ #define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ #define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ #define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ #define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ #define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ #define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ #define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ #define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ #define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ #define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ #define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ #define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ #define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ #define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ #define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ #define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ #define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ #define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Debug Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* The following EXC_RETURN values are saved the LR on exception entry */ #define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ #define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ #define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ #define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ #define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ #define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } /** \brief Get Priority Grouping \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t vectors = (uint32_t )SCB->VTOR; (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t vectors = (uint32_t )SCB->VTOR; return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## MPU functions #################################### */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #include "mpu_armv7.h" #endif /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { uint32_t mvfr0; mvfr0 = SCB->MVFR0; if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) { return 2U; /* Double + Single precision FPU */ } else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) { return 1U; /* Single precision FPU */ } else { return 0U; /* No FPU */ } } /*@} end of CMSIS_Core_FpuFunctions */ /* ########################## Cache functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_CacheFunctions Cache Functions \brief Functions that configure Instruction and Data cache. @{ */ /* Cache Size ID Register Macros */ #define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) #define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) #define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ /** \brief Enable I-Cache \details Turns on I-Cache */ __STATIC_FORCEINLINE void SCB_EnableICache (void) { #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */ __DSB(); __ISB(); SCB->ICIALLU = 0UL; /* invalidate I-Cache */ __DSB(); __ISB(); SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ __DSB(); __ISB(); #endif } /** \brief Disable I-Cache \details Turns off I-Cache */ __STATIC_FORCEINLINE void SCB_DisableICache (void) { #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) __DSB(); __ISB(); SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ SCB->ICIALLU = 0UL; /* invalidate I-Cache */ __DSB(); __ISB(); #endif } /** \brief Invalidate I-Cache \details Invalidates I-Cache */ __STATIC_FORCEINLINE void SCB_InvalidateICache (void) { #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) __DSB(); __ISB(); SCB->ICIALLU = 0UL; __DSB(); __ISB(); #endif } /** \brief Enable D-Cache \details Turns on D-Cache */ __STATIC_FORCEINLINE void SCB_EnableDCache (void) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */ SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; /* invalidate D-Cache */ sets = (uint32_t)(CCSIDR_SETS(ccsidr)); do { ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); do { SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); #if defined ( __CC_ARM ) __schedule_barrier(); #endif } while (ways-- != 0U); } while(sets-- != 0U); __DSB(); SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ __DSB(); __ISB(); #endif } /** \brief Disable D-Cache \details Turns off D-Cache */ __STATIC_FORCEINLINE void SCB_DisableDCache (void) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ __DSB(); ccsidr = SCB->CCSIDR; /* clean & invalidate D-Cache */ sets = (uint32_t)(CCSIDR_SETS(ccsidr)); do { ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); do { SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); #if defined ( __CC_ARM ) __schedule_barrier(); #endif } while (ways-- != 0U); } while(sets-- != 0U); __DSB(); __ISB(); #endif } /** \brief Invalidate D-Cache \details Invalidates D-Cache */ __STATIC_FORCEINLINE void SCB_InvalidateDCache (void) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; /* invalidate D-Cache */ sets = (uint32_t)(CCSIDR_SETS(ccsidr)); do { ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); do { SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); #if defined ( __CC_ARM ) __schedule_barrier(); #endif } while (ways-- != 0U); } while(sets-- != 0U); __DSB(); __ISB(); #endif } /** \brief Clean D-Cache \details Cleans D-Cache */ __STATIC_FORCEINLINE void SCB_CleanDCache (void) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; /* clean D-Cache */ sets = (uint32_t)(CCSIDR_SETS(ccsidr)); do { ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); do { SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); #if defined ( __CC_ARM ) __schedule_barrier(); #endif } while (ways-- != 0U); } while(sets-- != 0U); __DSB(); __ISB(); #endif } /** \brief Clean & Invalidate D-Cache \details Cleans and Invalidates D-Cache */ __STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; /* clean & invalidate D-Cache */ sets = (uint32_t)(CCSIDR_SETS(ccsidr)); do { ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); do { SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); #if defined ( __CC_ARM ) __schedule_barrier(); #endif } while (ways-- != 0U); } while(sets-- != 0U); __DSB(); __ISB(); #endif } /** \brief D-Cache Invalidate by address \details Invalidates D-Cache for the given address. D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. D-Cache memory blocks which are part of given address + given size are invalidated. \param[in] addr address \param[in] dsize size of memory block (in number of bytes) */ __STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) if ( dsize > 0 ) { int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; __DSB(); do { SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ op_addr += __SCB_DCACHE_LINE_SIZE; op_size -= __SCB_DCACHE_LINE_SIZE; } while ( op_size > 0 ); __DSB(); __ISB(); } #endif } /** \brief D-Cache Clean by address \details Cleans D-Cache for the given address D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity. D-Cache memory blocks which are part of given address + given size are cleaned. \param[in] addr address \param[in] dsize size of memory block (in number of bytes) */ __STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) if ( dsize > 0 ) { int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; __DSB(); do { SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ op_addr += __SCB_DCACHE_LINE_SIZE; op_size -= __SCB_DCACHE_LINE_SIZE; } while ( op_size > 0 ); __DSB(); __ISB(); } #endif } /** \brief D-Cache Clean and Invalidate by address \details Cleans and invalidates D_Cache for the given address D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity. D-Cache memory blocks which are part of given address + given size are cleaned and invalidated. \param[in] addr address (aligned to 32-byte boundary) \param[in] dsize size of memory block (in number of bytes) */ __STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) { #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) if ( dsize > 0 ) { int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; __DSB(); do { SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ op_addr += __SCB_DCACHE_LINE_SIZE; op_size -= __SCB_DCACHE_LINE_SIZE; } while ( op_size > 0 ); __DSB(); __ISB(); } #endif } /*@} end of CMSIS_Core_CacheFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /*@} end of CMSIS_Core_SysTickFunctions */ /* ##################################### Debug In/Output function ########################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_core_DebugFunctions ITM Functions \brief Functions that access the ITM debug interface. @{ */ extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ #define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** \brief ITM Send Character \details Transmits a character via the ITM channel 0, and \li Just returns when no debugger is connected that has booked the output. \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. \param [in] ch Character to transmit. \returns Character to transmit. */ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ { while (ITM->PORT[0U].u32 == 0UL) { __NOP(); } ITM->PORT[0U].u8 = (uint8_t)ch; } return (ch); } /** \brief ITM Receive Character \details Inputs a character via the external variable \ref ITM_RxBuffer. \return Received character. \return -1 No character pending. */ __STATIC_INLINE int32_t ITM_ReceiveChar (void) { int32_t ch = -1; /* no character available */ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { ch = ITM_RxBuffer; ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ } return (ch); } /** \brief ITM Check Character \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. \return 0 No character available. \return 1 Character available. */ __STATIC_INLINE int32_t ITM_CheckChar (void) { if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { return (0); /* no character available */ } else { return (1); /* character available */ } } /*@} end of CMSIS_core_DebugFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_CM7_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_sc000.h000066400000000000000000001322231357706137100204700ustar00rootroot00000000000000/**************************************************************************//** * @file core_sc000.h * @brief CMSIS SC000 Core Peripheral Access Layer Header File * @version V5.0.6 * @date 12. November 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_SC000_H_GENERIC #define __CORE_SC000_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup SC000 @{ */ #include "cmsis_version.h" /* CMSIS SC000 definitions */ #define __SC000_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __SC000_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \ __SC000_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_SC (000U) /*!< Cortex secure core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all */ #define __FPU_USED 0U #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_SC000_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_SC000_H_DEPENDANT #define __CORE_SC000_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __SC000_REV #define __SC000_REV 0x0000U #warning "__SC000_REV not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 2U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group SC000 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core MPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t _reserved0:1; /*!< bit: 0 Reserved */ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[31U]; __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[31U]; __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[31U]; __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[31U]; uint32_t RESERVED4[64U]; __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ } NVIC_Type; /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ uint32_t RESERVED0[1U]; __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ uint32_t RESERVED1[154U]; __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[2U]; __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ } SCnSCB_Type; /* Auxiliary Control Register Definitions */ #define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ #define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ } MPU_Type; /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ #define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ #define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ #define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ #define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ #define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ /* MPU Region Attribute and Size Register Definitions */ #define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ #define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ #define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ #define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ #define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ #define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ #define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ #define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ #define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ #define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ #define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ #define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ #define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ #define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ #define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ #define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ #define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ #define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ #define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ #define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ /*@} end of group CMSIS_MPU */ #endif /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief SC000 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. Therefore they are not covered by the SC000 header file. @{ */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else /*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for SC000 */ /*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for SC000 */ #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ /*#define NVIC_GetActive __NVIC_GetActive not available for SC000 */ #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* The following EXC_RETURN values are saved the LR on exception entry */ #define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ #define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ #define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ /* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) #define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t *vectors = (uint32_t *)SCB->VTOR; vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t *vectors = (uint32_t *)SCB->VTOR; return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk); __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { return 0U; /* No FPU */ } /*@} end of CMSIS_Core_FpuFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /*@} end of CMSIS_Core_SysTickFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_SC000_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/core_sc300.h000066400000000000000000003240771357706137100205050ustar00rootroot00000000000000/**************************************************************************//** * @file core_sc300.h * @brief CMSIS SC300 Core Peripheral Access Layer Header File * @version V5.0.7 * @date 12. November 2018 ******************************************************************************/ /* * Copyright (c) 2009-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef __CORE_SC300_H_GENERIC #define __CORE_SC300_H_GENERIC #include #ifdef __cplusplus extern "C" { #endif /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions CMSIS violates the following MISRA-C:2004 rules: \li Required Rule 8.5, object/function definition in header file.
Function definitions in header files are used to allow 'inlining'. \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
Unions are used for effective representation of core registers. \li Advisory Rule 19.7, Function-like macro defined.
Function-like macros are used to allow more efficient code. */ /******************************************************************************* * CMSIS definitions ******************************************************************************/ /** \ingroup SC3000 @{ */ #include "cmsis_version.h" /* CMSIS SC300 definitions */ #define __SC300_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ #define __SC300_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \ __SC300_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_SC (300U) /*!< Cortex secure core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all */ #define __FPU_USED 0U #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif #endif #include "cmsis_compiler.h" /* CMSIS compiler specific defines */ #ifdef __cplusplus } #endif #endif /* __CORE_SC300_H_GENERIC */ #ifndef __CMSIS_GENERIC #ifndef __CORE_SC300_H_DEPENDANT #define __CORE_SC300_H_DEPENDANT #ifdef __cplusplus extern "C" { #endif /* check device defines and use defaults */ #if defined __CHECK_DEVICE_DEFINES #ifndef __SC300_REV #define __SC300_REV 0x0000U #warning "__SC300_REV not defined in device header file; using default!" #endif #ifndef __MPU_PRESENT #define __MPU_PRESENT 0U #warning "__MPU_PRESENT not defined in device header file; using default!" #endif #ifndef __NVIC_PRIO_BITS #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif #ifndef __Vendor_SysTickConfig #define __Vendor_SysTickConfig 0U #warning "__Vendor_SysTickConfig not defined in device header file; using default!" #endif #endif /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines IO Type Qualifiers are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ /*@} end of group SC300 */ /******************************************************************************* * Register Abstraction Core Register contain: - Core Register - Core NVIC Register - Core SCB Register - Core SysTick Register - Core Debug Register - Core MPU Register ******************************************************************************/ /** \defgroup CMSIS_core_register Defines and Type Definitions \brief Type definitions and defines for Cortex-M processor based devices. */ /** \ingroup CMSIS_core_register \defgroup CMSIS_CORE Status and Control Registers \brief Core Register type definitions. @{ */ /** \brief Union type to access the Application Program Status Register (APSR). */ typedef union { struct { uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } APSR_Type; /* APSR Register Definitions */ #define APSR_N_Pos 31U /*!< APSR: N Position */ #define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ #define APSR_Z_Pos 30U /*!< APSR: Z Position */ #define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ #define APSR_C_Pos 29U /*!< APSR: C Position */ #define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ #define APSR_V_Pos 28U /*!< APSR: V Position */ #define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ #define APSR_Q_Pos 27U /*!< APSR: Q Position */ #define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ /** \brief Union type to access the Interrupt Program Status Register (IPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } IPSR_Type; /* IPSR Register Definitions */ #define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ #define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). */ typedef union { struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ uint32_t _reserved0:1; /*!< bit: 9 Reserved */ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ uint32_t T:1; /*!< bit: 24 Thumb bit */ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ uint32_t N:1; /*!< bit: 31 Negative condition code flag */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } xPSR_Type; /* xPSR Register Definitions */ #define xPSR_N_Pos 31U /*!< xPSR: N Position */ #define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ #define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ #define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ #define xPSR_C_Pos 29U /*!< xPSR: C Position */ #define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ #define xPSR_V_Pos 28U /*!< xPSR: V Position */ #define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ #define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ #define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ #define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ #define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ /** \brief Union type to access the Control Registers (CONTROL). */ typedef union { struct { uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ } b; /*!< Structure used for bit access */ uint32_t w; /*!< Type used for word access */ } CONTROL_Type; /* CONTROL Register Definitions */ #define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ #define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ #define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ #define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ /*@} end of group CMSIS_CORE */ /** \ingroup CMSIS_core_register \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) \brief Type definitions for the NVIC Registers @{ */ /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). */ typedef struct { __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[24U]; __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ uint32_t RSERVED1[24U]; __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[24U]; __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ uint32_t RESERVED3[24U]; __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[56U]; __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED5[644U]; __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ } NVIC_Type; /* Software Triggered Interrupt Register Definitions */ #define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ #define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ /*@} end of group CMSIS_NVIC */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCB System Control Block (SCB) \brief Type definitions for the System Control Block Registers @{ */ /** \brief Structure type to access the System Control Block (SCB). */ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ uint32_t RESERVED0[5U]; __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ uint32_t RESERVED1[129U]; __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ } SCB_Type; /* SCB CPUID Register Definitions */ #define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ #define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ #define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ #define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ #define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ #define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ /* SCB Interrupt Control State Register Definitions */ #define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ #define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ #define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ #define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ #define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ #define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ #define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ #define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ #define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ #define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ #define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ #define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ #define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ /* SCB Application Interrupt and Reset Control Register Definitions */ #define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ #define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ #define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ #define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ #define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ #define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ #define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ /* SCB System Control Register Definitions */ #define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ #define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ #define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ /* SCB Configuration Control Register Definitions */ #define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ #define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ #define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ #define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ #define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ #define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ #define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ #define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ #define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ #define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ /* SCB System Handler Control and State Register Definitions */ #define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ #define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ #define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ #define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ #define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ #define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ #define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ #define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ #define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ #define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ #define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ #define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ #define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ #define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ #define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ #define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ #define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ #define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ #define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ #define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ #define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ #define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ #define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ #define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ #define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ #define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ #define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ /* SCB Configurable Fault Status Register Definitions */ #define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ #define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ #define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ #define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ /* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ #define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ #define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ #define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ #define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ #define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ #define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ #define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ #define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ #define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ /* BusFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ #define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ #define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ #define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ #define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ #define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ #define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ #define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ #define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ #define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ #define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ #define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ /* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ #define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ #define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ #define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ #define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ #define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ #define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ #define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ #define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ #define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ #define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ #define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ #define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ #define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ #define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ #define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ #define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ /* SCB Debug Fault Status Register Definitions */ #define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ #define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ #define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ #define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ #define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ #define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ #define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ #define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ #define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ #define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ /*@} end of group CMSIS_SCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) \brief Type definitions for the System Control and ID Register not in the SCB @{ */ /** \brief Structure type to access the System Control and ID Register not in the SCB. */ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ uint32_t RESERVED1[1U]; } SCnSCB_Type; /* Interrupt Controller Type Register Definitions */ #define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /*@} end of group CMSIS_SCnotSCB */ /** \ingroup CMSIS_core_register \defgroup CMSIS_SysTick System Tick Timer (SysTick) \brief Type definitions for the System Timer Registers. @{ */ /** \brief Structure type to access the System Timer (SysTick). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; /* SysTick Control / Status Register Definitions */ #define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ #define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ #define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ #define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ #define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ /* SysTick Reload Register Definitions */ #define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ /* SysTick Current Register Definitions */ #define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ /* SysTick Calibration Register Definitions */ #define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ #define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ #define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ /*@} end of group CMSIS_SysTick */ /** \ingroup CMSIS_core_register \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) \brief Type definitions for the Instrumentation Trace Macrocell (ITM) @{ */ /** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). */ typedef struct { __OM union { __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ uint32_t RESERVED0[864U]; __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ uint32_t RESERVED1[15U]; __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ uint32_t RESERVED3[29U]; __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ uint32_t RESERVED5[6U]; __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ } ITM_Type; /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ #define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ #define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ #define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ #define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ #define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ #define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ #define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ #define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ #define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ #define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ #define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ #define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ #define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ #define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ #define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ #define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ /* ITM Integration Write Register Definitions */ #define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ #define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ /* ITM Integration Read Register Definitions */ #define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ #define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ /* ITM Integration Mode Control Register Definitions */ #define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ #define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ #define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ #define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ #define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ #define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ /*@}*/ /* end of group CMSIS_ITM */ /** \ingroup CMSIS_core_register \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) \brief Type definitions for the Data Watchpoint and Trace (DWT) @{ */ /** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). */ typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ uint32_t RESERVED0[1U]; __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ uint32_t RESERVED1[1U]; __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ uint32_t RESERVED2[1U]; __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ } DWT_Type; /* DWT Control Register Definitions */ #define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ #define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ #define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ #define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ #define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ #define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ #define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ #define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ #define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ #define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ #define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ #define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ #define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ #define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ #define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ #define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ #define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ #define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ #define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ #define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ #define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ #define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ #define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ #define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ #define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ #define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ #define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ #define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ #define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ #define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ #define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ #define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ #define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ #define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ #define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ #define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ /* DWT CPI Count Register Definitions */ #define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ #define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ /* DWT Exception Overhead Count Register Definitions */ #define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ #define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ /* DWT Sleep Count Register Definitions */ #define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ #define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ /* DWT LSU Count Register Definitions */ #define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ #define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ /* DWT Folded-instruction Count Register Definitions */ #define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ #define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ /* DWT Comparator Mask Register Definitions */ #define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ #define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ /* DWT Comparator Function Register Definitions */ #define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ #define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ #define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ #define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ #define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ #define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ #define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ #define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ #define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ #define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ #define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ #define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ #define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ #define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ #define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ #define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ #define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ #define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ /*@}*/ /* end of group CMSIS_DWT */ /** \ingroup CMSIS_core_register \defgroup CMSIS_TPI Trace Port Interface (TPI) \brief Type definitions for the Trace Port Interface (TPI) @{ */ /** \brief Structure type to access the Trace Port Interface Register (TPI). */ typedef struct { __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ uint32_t RESERVED1[55U]; __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ uint32_t RESERVED2[131U]; __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ uint32_t RESERVED5[39U]; __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ uint32_t RESERVED7[8U]; __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ } TPI_Type; /* TPI Asynchronous Clock Prescaler Register Definitions */ #define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ #define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ /* TPI Selected Pin Protocol Register Definitions */ #define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ #define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ /* TPI Formatter and Flush Status Register Definitions */ #define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ #define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ #define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ #define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ #define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ #define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ #define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ #define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ /* TPI Formatter and Flush Control Register Definitions */ #define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ #define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ #define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ #define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ /* TPI TRIGGER Register Definitions */ #define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ #define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ /* TPI Integration ETM Data Register Definitions (FIFO0) */ #define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ #define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ #define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ #define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ #define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ #define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ #define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ #define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ #define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ #define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ #define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ #define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ #define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ #define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ #define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ #define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ #define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ #define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ #define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ #define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ #define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ #define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ #define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ #define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ #define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ #define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ #define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ #define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ #define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ #define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ #define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ #define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ #define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ #define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ #define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ #define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ #define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ #define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ #define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ #define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ #define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ #define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ #define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ #define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ #define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ #define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ #define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ /*@}*/ /* end of group CMSIS_TPI */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) \brief Type definitions for the Memory Protection Unit (MPU) @{ */ /** \brief Structure type to access the Memory Protection Unit (MPU). */ typedef struct { __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ #define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ #define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ #define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ #define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ /* MPU Control Register Definitions */ #define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ #define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ #define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ #define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ #define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ #define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ /* MPU Region Number Register Definitions */ #define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ #define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ /* MPU Region Base Address Register Definitions */ #define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ #define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ #define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ #define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ #define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ #define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ /* MPU Region Attribute and Size Register Definitions */ #define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ #define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ #define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ #define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ #define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ #define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ #define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ #define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ #define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ #define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ #define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ #define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ #define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ #define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ #define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ #define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ #define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ #define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ #define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ #define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ /*@} end of group CMSIS_MPU */ #endif /** \ingroup CMSIS_core_register \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) \brief Type definitions for the Core Debug Registers @{ */ /** \brief Structure type to access the Core Debug Register (CoreDebug). */ typedef struct { __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ } CoreDebug_Type; /* Debug Halting Control and Status Register Definitions */ #define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ #define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ #define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ #define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ #define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ #define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ #define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ #define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ #define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ #define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ #define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ #define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ #define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ #define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ #define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ #define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ #define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ #define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ #define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ #define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ #define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ #define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ #define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ #define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ /* Debug Core Register Selector Register Definitions */ #define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ #define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ #define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ #define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ /* Debug Exception and Monitor Control Register Definitions */ #define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ #define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ #define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ #define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ #define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ #define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ #define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ #define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ #define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ #define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ #define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ #define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ #define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ #define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ #define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ #define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ #define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ #define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ #define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ #define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ #define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ #define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ #define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ #define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ #define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ #define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ /*@} end of group CMSIS_CoreDebug */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_bitfield Core register bit field macros \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). @{ */ /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ #define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ #define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ /** \ingroup CMSIS_core_register \defgroup CMSIS_core_base Core Definitions \brief Definitions for base addresses, unions, and structures. @{ */ /* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif /*@} */ /******************************************************************************* * Hardware Abstraction Layer Core Function Interface contains: - Core NVIC Functions - Core SysTick Functions - Core Debug Functions - Core Register Access Functions ******************************************************************************/ /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference */ /* ########################## NVIC functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_NVICFunctions NVIC Functions \brief Functions that manage interrupts and exceptions via the NVIC. @{ */ #ifdef CMSIS_NVIC_VIRTUAL #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" #endif #include CMSIS_NVIC_VIRTUAL_HEADER_FILE #else #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping #define NVIC_EnableIRQ __NVIC_EnableIRQ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ #define NVIC_DisableIRQ __NVIC_DisableIRQ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ #define NVIC_GetActive __NVIC_GetActive #define NVIC_SetPriority __NVIC_SetPriority #define NVIC_GetPriority __NVIC_GetPriority #define NVIC_SystemReset __NVIC_SystemReset #endif /* CMSIS_NVIC_VIRTUAL */ #ifdef CMSIS_VECTAB_VIRTUAL #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" #endif #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE #else #define NVIC_SetVector __NVIC_SetVector #define NVIC_GetVector __NVIC_GetVector #endif /* (CMSIS_VECTAB_VIRTUAL) */ #define NVIC_USER_IRQ_OFFSET 16 /* The following EXC_RETURN values are saved the LR on exception entry */ #define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ #define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ #define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ __STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ reg_value = SCB->AIRCR; /* read old register configuration */ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ SCB->AIRCR = reg_value; } /** \brief Get Priority Grouping \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ __STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** \brief Enable Interrupt \details Enables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Interrupt Enable status \details Returns a device specific interrupt enable status from the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt is not enabled. \return 1 Interrupt is enabled. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Disable Interrupt \details Disables a device specific interrupt in the NVIC interrupt controller. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); __DSB(); __ISB(); } } /** \brief Get Pending Interrupt \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Pending Interrupt \details Sets the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Clear Pending Interrupt \details Clears the pending bit of a device specific interrupt in the NVIC pending register. \param [in] IRQn Device specific interrupt number. \note IRQn must not be negative. */ __STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); } } /** \brief Get Active Interrupt \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. \note IRQn must not be negative. */ __STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } else { return(0U); } } /** \brief Set Interrupt Priority \details Sets the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. \note The priority cannot be set for every processor exception. */ __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) >= 0) { NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority \details Reads the priority of a device specific interrupt or a processor exception. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) >= 0) { return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } /** \brief Encode Priority \details Encodes the priority for an interrupt with the given priority group, preemptive priority value, and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Used priority group. \param [in] PreemptPriority Preemptive priority value (starting from 0). \param [in] SubPriority Subpriority value (starting from 0). \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). */ __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } /** \brief Decode Priority \details Decodes an interrupt priority value with a given priority group to preemptive priority value and subpriority value. In case of a conflict between priority grouping and available priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). \param [in] PriorityGroup Used priority group. \param [out] pPreemptPriority Preemptive priority value (starting from 0). \param [out] pSubPriority Subpriority value (starting from 0). */ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); } /** \brief Set Interrupt Vector \details Sets an interrupt vector in SRAM based interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. VTOR must been relocated to SRAM before. \param [in] IRQn Interrupt number \param [in] vector Address of interrupt handler function */ __STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { uint32_t *vectors = (uint32_t *)SCB->VTOR; vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; } /** \brief Get Interrupt Vector \details Reads an interrupt vector from interrupt vector table. The interrupt number can be positive to specify a device specific interrupt, or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Address of interrupt handler function */ __STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) { uint32_t *vectors = (uint32_t *)SCB->VTOR; return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; } /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ __NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ __DSB(); /* Ensure completion of memory access */ for(;;) /* wait until reset */ { __NOP(); } } /*@} end of CMSIS_Core_NVICFunctions */ /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_FpuFunctions FPU Functions \brief Function that provides FPU type. @{ */ /** \brief get FPU type \details returns the FPU type \returns - \b 0: No FPU - \b 1: Single precision FPU - \b 2: Double + Single precision FPU */ __STATIC_INLINE uint32_t SCB_GetFPUType(void) { return 0U; /* No FPU */ } /*@} end of CMSIS_Core_FpuFunctions */ /* ################################## SysTick function ############################################ */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_Core_SysTickFunctions SysTick Functions \brief Functions that configure the System. @{ */ #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included. In this case, the file device.h must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } #endif /*@} end of CMSIS_Core_SysTickFunctions */ /* ##################################### Debug In/Output function ########################################### */ /** \ingroup CMSIS_Core_FunctionInterface \defgroup CMSIS_core_DebugFunctions ITM Functions \brief Functions that access the ITM debug interface. @{ */ extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ #define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** \brief ITM Send Character \details Transmits a character via the ITM channel 0, and \li Just returns when no debugger is connected that has booked the output. \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. \param [in] ch Character to transmit. \returns Character to transmit. */ __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ { while (ITM->PORT[0U].u32 == 0UL) { __NOP(); } ITM->PORT[0U].u8 = (uint8_t)ch; } return (ch); } /** \brief ITM Receive Character \details Inputs a character via the external variable \ref ITM_RxBuffer. \return Received character. \return -1 No character pending. */ __STATIC_INLINE int32_t ITM_ReceiveChar (void) { int32_t ch = -1; /* no character available */ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { ch = ITM_RxBuffer; ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ } return (ch); } /** \brief ITM Check Character \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. \return 0 No character available. \return 1 Character available. */ __STATIC_INLINE int32_t ITM_CheckChar (void) { if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { return (0); /* no character available */ } else { return (1); /* character available */ } } /*@} end of CMSIS_core_DebugFunctions */ #ifdef __cplusplus } #endif #endif /* __CORE_SC300_H_DEPENDANT */ #endif /* __CMSIS_GENERIC */ micropython-1.12/lib/cmsis/inc/mpu_armv7.h000066400000000000000000000266521357706137100205600ustar00rootroot00000000000000/****************************************************************************** * @file mpu_armv7.h * @brief CMSIS MPU API for Armv7-M MPU * @version V5.1.0 * @date 08. March 2019 ******************************************************************************/ /* * Copyright (c) 2017-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef ARM_MPU_ARMV7_H #define ARM_MPU_ARMV7_H #define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes #define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes #define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes #define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes #define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes #define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte #define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes #define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes #define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes #define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes #define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes #define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes #define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes #define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes #define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes #define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte #define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes #define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes #define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes #define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes #define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes #define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes #define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes #define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes #define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes #define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte #define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes #define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes #define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access #define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only #define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only #define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access #define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only #define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access /** MPU Region Base Address Register Value * * \param Region The region to be configured, number 0 to 15. * \param BaseAddress The base address for the region. */ #define ARM_MPU_RBAR(Region, BaseAddress) \ (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ ((Region) & MPU_RBAR_REGION_Msk) | \ (MPU_RBAR_VALID_Msk)) /** * MPU Memory Access Attributes * * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. * \param IsShareable Region is shareable between multiple bus masters. * \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. */ #define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) /** * MPU Region Attribute and Size Register Value * * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. * \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. * \param SubRegionDisable Sub-region disable field. * \param Size Region size of the region to be configured, for example 4K, 8K. */ #define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ (((MPU_RASR_ENABLE_Msk)))) /** * MPU Region Attribute and Size Register Value * * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. * \param IsShareable Region is shareable between multiple bus masters. * \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. * \param SubRegionDisable Sub-region disable field. * \param Size Region size of the region to be configured, for example 4K, 8K. */ #define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) /** * MPU Memory Access Attribute for strongly ordered memory. * - TEX: 000b * - Shareable * - Non-cacheable * - Non-bufferable */ #define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) /** * MPU Memory Access Attribute for device memory. * - TEX: 000b (if shareable) or 010b (if non-shareable) * - Shareable or non-shareable * - Non-cacheable * - Bufferable (if shareable) or non-bufferable (if non-shareable) * * \param IsShareable Configures the device memory as shareable or non-shareable. */ #define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) /** * MPU Memory Access Attribute for normal memory. * - TEX: 1BBb (reflecting outer cacheability rules) * - Shareable or non-shareable * - Cacheable or non-cacheable (reflecting inner cacheability rules) * - Bufferable or non-bufferable (reflecting inner cacheability rules) * * \param OuterCp Configures the outer cache policy. * \param InnerCp Configures the inner cache policy. * \param IsShareable Configures the memory as shareable or non-shareable. */ #define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U)) /** * MPU Memory Access Attribute non-cacheable policy. */ #define ARM_MPU_CACHEP_NOCACHE 0U /** * MPU Memory Access Attribute write-back, write and read allocate policy. */ #define ARM_MPU_CACHEP_WB_WRA 1U /** * MPU Memory Access Attribute write-through, no write allocate policy. */ #define ARM_MPU_CACHEP_WT_NWA 2U /** * MPU Memory Access Attribute write-back, no write allocate policy. */ #define ARM_MPU_CACHEP_WB_NWA 3U /** * Struct for a single MPU Region */ typedef struct { uint32_t RBAR; //!< The region base address register value (RBAR) uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR } ARM_MPU_Region_t; /** Enable the MPU. * \param MPU_Control Default access permissions for unconfigured regions. */ __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) { MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; #ifdef SCB_SHCSR_MEMFAULTENA_Msk SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; #endif __DSB(); __ISB(); } /** Disable the MPU. */ __STATIC_INLINE void ARM_MPU_Disable(void) { __DMB(); #ifdef SCB_SHCSR_MEMFAULTENA_Msk SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; #endif MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; } /** Clear and disable the given MPU region. * \param rnr Region number to be cleared. */ __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) { MPU->RNR = rnr; MPU->RASR = 0U; } /** Configure an MPU region. * \param rbar Value for RBAR register. * \param rsar Value for RSAR register. */ __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) { MPU->RBAR = rbar; MPU->RASR = rasr; } /** Configure the given MPU region. * \param rnr Region number to be configured. * \param rbar Value for RBAR register. * \param rsar Value for RSAR register. */ __STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) { MPU->RNR = rnr; MPU->RBAR = rbar; MPU->RASR = rasr; } /** Memcopy with strictly ordered memory access, e.g. for register targets. * \param dst Destination data is copied to. * \param src Source data is copied from. * \param len Amount of data words to be copied. */ __STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) { uint32_t i; for (i = 0U; i < len; ++i) { dst[i] = src[i]; } } /** Load the given number of MPU regions from a table. * \param table Pointer to the MPU configuration table. * \param cnt Amount of regions to be configured. */ __STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) { const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; while (cnt > MPU_TYPE_RALIASES) { ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); table += MPU_TYPE_RALIASES; cnt -= MPU_TYPE_RALIASES; } ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); } #endif micropython-1.12/lib/cmsis/inc/mpu_armv8.h000066400000000000000000000257671357706137100205670ustar00rootroot00000000000000/****************************************************************************** * @file mpu_armv8.h * @brief CMSIS MPU API for Armv8-M and Armv8.1-M MPU * @version V5.1.0 * @date 08. March 2019 ******************************************************************************/ /* * Copyright (c) 2017-2019 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef ARM_MPU_ARMV8_H #define ARM_MPU_ARMV8_H /** \brief Attribute for device memory (outer only) */ #define ARM_MPU_ATTR_DEVICE ( 0U ) /** \brief Attribute for non-cacheable, normal memory */ #define ARM_MPU_ATTR_NON_CACHEABLE ( 4U ) /** \brief Attribute for normal memory (outer and inner) * \param NT Non-Transient: Set to 1 for non-transient data. * \param WB Write-Back: Set to 1 to use write-back update policy. * \param RA Read Allocation: Set to 1 to use cache allocation on read miss. * \param WA Write Allocation: Set to 1 to use cache allocation on write miss. */ #define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \ (((NT & 1U) << 3U) | ((WB & 1U) << 2U) | ((RA & 1U) << 1U) | (WA & 1U)) /** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */ #define ARM_MPU_ATTR_DEVICE_nGnRnE (0U) /** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */ #define ARM_MPU_ATTR_DEVICE_nGnRE (1U) /** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */ #define ARM_MPU_ATTR_DEVICE_nGRE (2U) /** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */ #define ARM_MPU_ATTR_DEVICE_GRE (3U) /** \brief Memory Attribute * \param O Outer memory attributes * \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes */ #define ARM_MPU_ATTR(O, I) (((O & 0xFU) << 4U) | (((O & 0xFU) != 0U) ? (I & 0xFU) : ((I & 0x3U) << 2U))) /** \brief Normal memory non-shareable */ #define ARM_MPU_SH_NON (0U) /** \brief Normal memory outer shareable */ #define ARM_MPU_SH_OUTER (2U) /** \brief Normal memory inner shareable */ #define ARM_MPU_SH_INNER (3U) /** \brief Memory access permissions * \param RO Read-Only: Set to 1 for read-only memory. * \param NP Non-Privileged: Set to 1 for non-privileged memory. */ #define ARM_MPU_AP_(RO, NP) (((RO & 1U) << 1U) | (NP & 1U)) /** \brief Region Base Address Register value * \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned. * \param SH Defines the Shareability domain for this memory region. * \param RO Read-Only: Set to 1 for a read-only memory region. * \param NP Non-Privileged: Set to 1 for a non-privileged memory region. * \oaram XN eXecute Never: Set to 1 for a non-executable memory region. */ #define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \ ((BASE & MPU_RBAR_BASE_Msk) | \ ((SH << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \ ((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \ ((XN << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk)) /** \brief Region Limit Address Register value * \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. * \param IDX The attribute index to be associated with this memory region. */ #define ARM_MPU_RLAR(LIMIT, IDX) \ ((LIMIT & MPU_RLAR_LIMIT_Msk) | \ ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ (MPU_RLAR_EN_Msk)) #if defined(MPU_RLAR_PXN_Pos) /** \brief Region Limit Address Register with PXN value * \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. * \param PXN Privileged execute never. Defines whether code can be executed from this privileged region. * \param IDX The attribute index to be associated with this memory region. */ #define ARM_MPU_RLAR_PXN(LIMIT, PXN, IDX) \ ((LIMIT & MPU_RLAR_LIMIT_Msk) | \ ((PXN << MPU_RLAR_PXN_Pos) & MPU_RLAR_PXN_Msk) | \ ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ (MPU_RLAR_EN_Msk)) #endif /** * Struct for a single MPU Region */ typedef struct { uint32_t RBAR; /*!< Region Base Address Register value */ uint32_t RLAR; /*!< Region Limit Address Register value */ } ARM_MPU_Region_t; /** Enable the MPU. * \param MPU_Control Default access permissions for unconfigured regions. */ __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) { MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; #ifdef SCB_SHCSR_MEMFAULTENA_Msk SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; #endif __DSB(); __ISB(); } /** Disable the MPU. */ __STATIC_INLINE void ARM_MPU_Disable(void) { __DMB(); #ifdef SCB_SHCSR_MEMFAULTENA_Msk SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; #endif MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; } #ifdef MPU_NS /** Enable the Non-secure MPU. * \param MPU_Control Default access permissions for unconfigured regions. */ __STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control) { MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; #ifdef SCB_SHCSR_MEMFAULTENA_Msk SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; #endif __DSB(); __ISB(); } /** Disable the Non-secure MPU. */ __STATIC_INLINE void ARM_MPU_Disable_NS(void) { __DMB(); #ifdef SCB_SHCSR_MEMFAULTENA_Msk SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; #endif MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk; } #endif /** Set the memory attribute encoding to the given MPU. * \param mpu Pointer to the MPU to be configured. * \param idx The attribute index to be set [0-7] * \param attr The attribute value to be set. */ __STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr) { const uint8_t reg = idx / 4U; const uint32_t pos = ((idx % 4U) * 8U); const uint32_t mask = 0xFFU << pos; if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) { return; // invalid index } mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask)); } /** Set the memory attribute encoding. * \param idx The attribute index to be set [0-7] * \param attr The attribute value to be set. */ __STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr) { ARM_MPU_SetMemAttrEx(MPU, idx, attr); } #ifdef MPU_NS /** Set the memory attribute encoding to the Non-secure MPU. * \param idx The attribute index to be set [0-7] * \param attr The attribute value to be set. */ __STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr) { ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr); } #endif /** Clear and disable the given MPU region of the given MPU. * \param mpu Pointer to MPU to be used. * \param rnr Region number to be cleared. */ __STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr) { mpu->RNR = rnr; mpu->RLAR = 0U; } /** Clear and disable the given MPU region. * \param rnr Region number to be cleared. */ __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) { ARM_MPU_ClrRegionEx(MPU, rnr); } #ifdef MPU_NS /** Clear and disable the given Non-secure MPU region. * \param rnr Region number to be cleared. */ __STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr) { ARM_MPU_ClrRegionEx(MPU_NS, rnr); } #endif /** Configure the given MPU region of the given MPU. * \param mpu Pointer to MPU to be used. * \param rnr Region number to be configured. * \param rbar Value for RBAR register. * \param rlar Value for RLAR register. */ __STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar) { mpu->RNR = rnr; mpu->RBAR = rbar; mpu->RLAR = rlar; } /** Configure the given MPU region. * \param rnr Region number to be configured. * \param rbar Value for RBAR register. * \param rlar Value for RLAR register. */ __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar) { ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar); } #ifdef MPU_NS /** Configure the given Non-secure MPU region. * \param rnr Region number to be configured. * \param rbar Value for RBAR register. * \param rlar Value for RLAR register. */ __STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar) { ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar); } #endif /** Memcopy with strictly ordered memory access, e.g. for register targets. * \param dst Destination data is copied to. * \param src Source data is copied from. * \param len Amount of data words to be copied. */ __STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) { uint32_t i; for (i = 0U; i < len; ++i) { dst[i] = src[i]; } } /** Load the given number of MPU regions from a table to the given MPU. * \param mpu Pointer to the MPU registers to be used. * \param rnr First region number to be configured. * \param table Pointer to the MPU configuration table. * \param cnt Amount of regions to be configured. */ __STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) { const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; if (cnt == 1U) { mpu->RNR = rnr; ARM_MPU_OrderedMemcpy(&(mpu->RBAR), &(table->RBAR), rowWordSize); } else { uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U); uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES; mpu->RNR = rnrBase; while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) { uint32_t c = MPU_TYPE_RALIASES - rnrOffset; ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize); table += c; cnt -= c; rnrOffset = 0U; rnrBase += MPU_TYPE_RALIASES; mpu->RNR = rnrBase; } ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize); } } /** Load the given number of MPU regions from a table. * \param rnr First region number to be configured. * \param table Pointer to the MPU configuration table. * \param cnt Amount of regions to be configured. */ __STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) { ARM_MPU_LoadEx(MPU, rnr, table, cnt); } #ifdef MPU_NS /** Load the given number of MPU regions from a table to the Non-secure MPU. * \param rnr First region number to be configured. * \param table Pointer to the MPU configuration table. * \param cnt Amount of regions to be configured. */ __STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) { ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt); } #endif #endif micropython-1.12/lib/cmsis/inc/tz_context.h000066400000000000000000000051771357706137100210430ustar00rootroot00000000000000/****************************************************************************** * @file tz_context.h * @brief Context Management for Armv8-M TrustZone * @version V1.0.1 * @date 10. January 2018 ******************************************************************************/ /* * Copyright (c) 2017-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if defined ( __ICCARM__ ) #pragma system_include /* treat file as system include file for MISRA check */ #elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif #ifndef TZ_CONTEXT_H #define TZ_CONTEXT_H #include #ifndef TZ_MODULEID_T #define TZ_MODULEID_T /// \details Data type that identifies secure software modules called by a process. typedef uint32_t TZ_ModuleId_t; #endif /// \details TZ Memory ID identifies an allocated memory slot. typedef uint32_t TZ_MemoryId_t; /// Initialize secure context memory system /// \return execution status (1: success, 0: error) uint32_t TZ_InitContextSystem_S (void); /// Allocate context memory for calling secure software modules in TrustZone /// \param[in] module identifies software modules called from non-secure mode /// \return value != 0 id TrustZone memory slot identifier /// \return value 0 no memory available or internal error TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module); /// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S /// \param[in] id TrustZone memory slot identifier /// \return execution status (1: success, 0: error) uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id); /// Load secure context (called on RTOS thread context switch) /// \param[in] id TrustZone memory slot identifier /// \return execution status (1: success, 0: error) uint32_t TZ_LoadContext_S (TZ_MemoryId_t id); /// Store secure context (called on RTOS thread context switch) /// \param[in] id TrustZone memory slot identifier /// \return execution status (1: success, 0: error) uint32_t TZ_StoreContext_S (TZ_MemoryId_t id); #endif // TZ_CONTEXT_H micropython-1.12/lib/embed/000077500000000000000000000000001357706137100156445ustar00rootroot00000000000000micropython-1.12/lib/embed/abort_.c000066400000000000000000000002201357706137100172500ustar00rootroot00000000000000#include NORETURN void abort_(void); NORETURN void abort_(void) { mp_raise_msg(&mp_type_RuntimeError, "abort() called"); } micropython-1.12/lib/libc/000077500000000000000000000000001357706137100155015ustar00rootroot00000000000000micropython-1.12/lib/libc/string0.c000066400000000000000000000142011357706137100172310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #define likely(x) __builtin_expect((x), 1) void *memcpy(void *dst, const void *src, size_t n) { if (likely(!(((uintptr_t)dst) & 3) && !(((uintptr_t)src) & 3))) { // pointers aligned uint32_t *d = dst; const uint32_t *s = src; // copy words first for (size_t i = (n >> 2); i; i--) { *d++ = *s++; } if (n & 2) { // copy half-word *(uint16_t*)d = *(const uint16_t*)s; d = (uint32_t*)((uint16_t*)d + 1); s = (const uint32_t*)((const uint16_t*)s + 1); } if (n & 1) { // copy byte *((uint8_t*)d) = *((const uint8_t*)s); } } else { // unaligned access, copy bytes uint8_t *d = dst; const uint8_t *s = src; for (; n; n--) { *d++ = *s++; } } return dst; } void *memmove(void *dest, const void *src, size_t n) { if (src < dest && (uint8_t*)dest < (const uint8_t*)src + n) { // need to copy backwards uint8_t *d = (uint8_t*)dest + n - 1; const uint8_t *s = (const uint8_t*)src + n - 1; for (; n > 0; n--) { *d-- = *s--; } return dest; } else { // can use normal memcpy return memcpy(dest, src, n); } } void *memset(void *s, int c, size_t n) { if (c == 0 && ((uintptr_t)s & 3) == 0) { // aligned store of 0 uint32_t *s32 = s; for (size_t i = n >> 2; i > 0; i--) { *s32++ = 0; } if (n & 2) { *((uint16_t*)s32) = 0; s32 = (uint32_t*)((uint16_t*)s32 + 1); } if (n & 1) { *((uint8_t*)s32) = 0; } } else { uint8_t *s2 = s; for (; n > 0; n--) { *s2++ = c; } } return s; } int memcmp(const void *s1, const void *s2, size_t n) { const uint8_t *s1_8 = s1; const uint8_t *s2_8 = s2; while (n--) { char c1 = *s1_8++; char c2 = *s2_8++; if (c1 < c2) return -1; else if (c1 > c2) return 1; } return 0; } void *memchr(const void *s, int c, size_t n) { if (n != 0) { const unsigned char *p = s; do { if (*p++ == c) return ((void *)(p - 1)); } while (--n != 0); } return 0; } size_t strlen(const char *str) { int len = 0; for (const char *s = str; *s; s++) { len += 1; } return len; } int strcmp(const char *s1, const char *s2) { while (*s1 && *s2) { char c1 = *s1++; // XXX UTF8 get char, next char char c2 = *s2++; // XXX UTF8 get char, next char if (c1 < c2) return -1; else if (c1 > c2) return 1; } if (*s2) return -1; else if (*s1) return 1; else return 0; } int strncmp(const char *s1, const char *s2, size_t n) { while (*s1 && *s2 && n > 0) { char c1 = *s1++; // XXX UTF8 get char, next char char c2 = *s2++; // XXX UTF8 get char, next char n--; if (c1 < c2) return -1; else if (c1 > c2) return 1; } if (n == 0) return 0; else if (*s2) return -1; else if (*s1) return 1; else return 0; } char *strcpy(char *dest, const char *src) { char *d = dest; while (*src) { *d++ = *src++; } *d = '\0'; return dest; } // needed because gcc optimises strcpy + strcat to this char *stpcpy(char *dest, const char *src) { while (*src) { *dest++ = *src++; } *dest = '\0'; return dest; } char *strcat(char *dest, const char *src) { char *d = dest; while (*d) { d++; } while (*src) { *d++ = *src++; } *d = '\0'; return dest; } // Public Domain implementation of strchr from: // http://en.wikibooks.org/wiki/C_Programming/Strings#The_strchr_function char *strchr(const char *s, int c) { /* Scan s for the character. When this loop is finished, s will either point to the end of the string or the character we were looking for. */ while (*s != '\0' && *s != (char)c) s++; return ((*s == c) ? (char *) s : 0); } // Public Domain implementation of strstr from: // http://en.wikibooks.org/wiki/C_Programming/Strings#The_strstr_function char *strstr(const char *haystack, const char *needle) { size_t needlelen; /* Check for the null needle case. */ if (*needle == '\0') return (char *) haystack; needlelen = strlen(needle); for (; (haystack = strchr(haystack, *needle)) != 0; haystack++) if (strncmp(haystack, needle, needlelen) == 0) return (char *) haystack; return 0; } size_t strspn(const char *s, const char *accept) { const char *ss = s; while (*s && strchr(accept, *s) != NULL) { ++s; } return s - ss; } size_t strcspn(const char *s, const char *reject) { const char *ss = s; while (*s && strchr(reject, *s) == NULL) { ++s; } return s - ss; } micropython-1.12/lib/libffi/000077500000000000000000000000001357706137100160235ustar00rootroot00000000000000micropython-1.12/lib/libm/000077500000000000000000000000001357706137100155135ustar00rootroot00000000000000micropython-1.12/lib/libm/acoshf.c000066400000000000000000000016711357706137100171270ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // acoshf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ #include "libm.h" #if FLT_EVAL_METHOD==2 #undef sqrtf #define sqrtf sqrtl #elif FLT_EVAL_METHOD==1 #undef sqrtf #define sqrtf sqrt #endif /* acosh(x) = log(x + sqrt(x*x-1)) */ float acoshf(float x) { union {float f; uint32_t i;} u = {x}; uint32_t a = u.i & 0x7fffffff; if (a < 0x3f800000+(1<<23)) /* |x| < 2, invalid if x < 1 or nan */ /* up to 2ulp error in [1,1.125] */ return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1))); if (a < 0x3f800000+(12<<23)) /* |x| < 0x1p12 */ return logf(2*x - 1/(x+sqrtf(x*x-1))); /* x >= 0x1p12 */ return logf(x) + 0.693147180559945309417232121458176568f; } micropython-1.12/lib/libm/asinfacosf.c000066400000000000000000000070401357706137100177740ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // asinf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/e_asinf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "libm.h" // dpgeorge: pio2 was double in original implementation of asinf static const float pio2_hi = 1.5707962513e+00, /* 0x3fc90fda */ pio2_lo = 7.5497894159e-08; /* 0x33a22168 */ static const float /* coefficients for R(x^2) */ pS0 = 1.6666586697e-01, pS1 = -4.2743422091e-02, pS2 = -8.6563630030e-03, qS1 = -7.0662963390e-01; static float R(float z) { float_t p, q; p = z*(pS0+z*(pS1+z*pS2)); q = 1.0f+z*qS1; return p/q; } float asinf(float x) { // dpgeorge: s was double in original implementation float s,z; uint32_t hx,ix; GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; if (ix >= 0x3f800000) { /* |x| >= 1 */ if (ix == 0x3f800000) /* |x| == 1 */ return x*pio2_hi + 0x1p-120f; /* asin(+-1) = +-pi/2 with inexact */ return 0/(x-x); /* asin(|x|>1) is NaN */ } if (ix < 0x3f000000) { /* |x| < 0.5 */ /* if 0x1p-126 <= |x| < 0x1p-12, avoid raising underflow */ if (ix < 0x39800000 && ix >= 0x00800000) return x; return x + x*R(x*x); } /* 1 > |x| >= 0.5 */ z = (1 - fabsf(x))*0.5f; s = sqrtf(z); x = pio2_hi - (2*(s+s*R(z)) - pio2_lo); // dpgeorge: use pio2_hi and pio2_lo if (hx >> 31) return -x; return x; } /*****************************************************************************/ /*****************************************************************************/ // acosf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/e_acosf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ float acosf(float x) { float z,w,s,c,df; uint32_t hx,ix; GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; /* |x| >= 1 or nan */ if (ix >= 0x3f800000) { if (ix == 0x3f800000) { if (hx >> 31) return 2*pio2_hi + 0x1p-120f; return 0; } return 0/(x-x); } /* |x| < 0.5 */ if (ix < 0x3f000000) { if (ix <= 0x32800000) /* |x| < 2**-26 */ return pio2_hi + 0x1p-120f; return pio2_hi - (x - (pio2_lo-x*R(x*x))); } /* x < -0.5 */ if (hx >> 31) { z = (1+x)*0.5f; s = sqrtf(z); w = R(z)*s-pio2_lo; return 2*(pio2_hi - (s+w)); } /* x > 0.5 */ z = (1-x)*0.5f; s = sqrtf(z); GET_FLOAT_WORD(hx,s); SET_FLOAT_WORD(df,hx&0xfffff000); c = (z-df*df)/(s+df); w = R(z)*s+c; return 2*(df+w); } micropython-1.12/lib/libm/asinhf.c000066400000000000000000000020511357706137100171250ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // asinhf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ #include "libm.h" /* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */ float asinhf(float x) { union {float f; uint32_t i;} u = {.f = x}; uint32_t i = u.i & 0x7fffffff; unsigned s = u.i >> 31; /* |x| */ u.i = i; x = u.f; if (i >= 0x3f800000 + (12<<23)) { /* |x| >= 0x1p12 or inf or nan */ x = logf(x) + 0.693147180559945309417232121458176568f; } else if (i >= 0x3f800000 + (1<<23)) { /* |x| >= 2 */ x = logf(2*x + 1/(sqrtf(x*x+1)+x)); } else if (i >= 0x3f800000 - (12<<23)) { /* |x| >= 0x1p-12, up to 1.6ulp error in [0.125,0.5] */ x = log1pf(x + x*x/(sqrtf(x*x+1)+1)); } else { /* |x| < 0x1p-12, raise inexact if x!=0 */ FORCE_EVAL(x + 0x1p120f); } return s ? -x : x; } micropython-1.12/lib/libm/atan2f.c000066400000000000000000000050041357706137100170310ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // atan2f from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/e_atan2f.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "libm.h" static const float pi = 3.1415927410e+00, /* 0x40490fdb */ pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */ float atan2f(float y, float x) { float z; uint32_t m,ix,iy; if (isnan(x) || isnan(y)) return x+y; GET_FLOAT_WORD(ix, x); GET_FLOAT_WORD(iy, y); if (ix == 0x3f800000) /* x=1.0 */ return atanf(y); m = ((iy>>31)&1) | ((ix>>30)&2); /* 2*sign(x)+sign(y) */ ix &= 0x7fffffff; iy &= 0x7fffffff; /* when y = 0 */ if (iy == 0) { switch (m) { case 0: case 1: return y; /* atan(+-0,+anything)=+-0 */ case 2: return pi; /* atan(+0,-anything) = pi */ case 3: return -pi; /* atan(-0,-anything) =-pi */ } } /* when x = 0 */ if (ix == 0) return m&1 ? -pi/2 : pi/2; /* when x is INF */ if (ix == 0x7f800000) { if (iy == 0x7f800000) { switch (m) { case 0: return pi/4; /* atan(+INF,+INF) */ case 1: return -pi/4; /* atan(-INF,+INF) */ case 2: return 3*pi/4; /*atan(+INF,-INF)*/ case 3: return -3*pi/4; /*atan(-INF,-INF)*/ } } else { switch (m) { case 0: return 0.0f; /* atan(+...,+INF) */ case 1: return -0.0f; /* atan(-...,+INF) */ case 2: return pi; /* atan(+...,-INF) */ case 3: return -pi; /* atan(-...,-INF) */ } } } /* |y/x| > 0x1p26 */ if (ix+(26<<23) < iy || iy == 0x7f800000) return m&1 ? -pi/2 : pi/2; /* z = atan(|y/x|) with correct underflow */ if ((m&2) && iy+(26<<23) < ix) /*|y/x| < 0x1p-26, x < 0 */ z = 0.0; else z = atanf(fabsf(y/x)); switch (m) { case 0: return z; /* atan(+,+) */ case 1: return -z; /* atan(-,+) */ case 2: return pi - (z-pi_lo); /* atan(+,-) */ default: /* case 3 */ return (z-pi_lo) - pi; /* atan(-,-) */ } } micropython-1.12/lib/libm/atanf.c000066400000000000000000000052401357706137100167510ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // atanf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/s_atanf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "libm.h" static const float atanhi[] = { 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */ 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */ 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */ 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */ }; static const float atanlo[] = { 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */ 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */ 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */ 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */ }; static const float aT[] = { 3.3333328366e-01, -1.9999158382e-01, 1.4253635705e-01, -1.0648017377e-01, 6.1687607318e-02, }; float atanf(float x) { float_t w,s1,s2,z; uint32_t ix,sign; int id; GET_FLOAT_WORD(ix, x); sign = ix>>31; ix &= 0x7fffffff; if (ix >= 0x4c800000) { /* if |x| >= 2**26 */ if (isnan(x)) return x; z = atanhi[3] + 0x1p-120f; return sign ? -z : z; } if (ix < 0x3ee00000) { /* |x| < 0.4375 */ if (ix < 0x39800000) { /* |x| < 2**-12 */ if (ix < 0x00800000) /* raise underflow for subnormal x */ FORCE_EVAL(x*x); return x; } id = -1; } else { x = fabsf(x); if (ix < 0x3f980000) { /* |x| < 1.1875 */ if (ix < 0x3f300000) { /* 7/16 <= |x| < 11/16 */ id = 0; x = (2.0f*x - 1.0f)/(2.0f + x); } else { /* 11/16 <= |x| < 19/16 */ id = 1; x = (x - 1.0f)/(x + 1.0f); } } else { if (ix < 0x401c0000) { /* |x| < 2.4375 */ id = 2; x = (x - 1.5f)/(1.0f + 1.5f*x); } else { /* 2.4375 <= |x| < 2**26 */ id = 3; x = -1.0f/x; } } } /* end of argument reduction */ z = x*x; w = z*z; /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ s1 = z*(aT[0]+w*(aT[2]+w*aT[4])); s2 = w*(aT[1]+w*aT[3]); if (id < 0) return x - x*(s1+s2); z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); return sign ? -z : z; } micropython-1.12/lib/libm/atanhf.c000066400000000000000000000016361357706137100171260ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // atanhf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ #include "libm.h" /* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */ float atanhf(float x) { union {float f; uint32_t i;} u = {.f = x}; unsigned s = u.i >> 31; float_t y; /* |x| */ u.i &= 0x7fffffff; y = u.f; if (u.i < 0x3f800000 - (1<<23)) { if (u.i < 0x3f800000 - (32<<23)) { /* handle underflow */ if (u.i < (1<<23)) FORCE_EVAL((float)(y*y)); } else { /* |x| < 0.5, up to 1.7ulp error */ y = 0.5f*log1pf(2*y + 2*y*y/(1-y)); } } else { /* avoid overflow */ y = 0.5f*log1pf(2*(y/(1-y))); } return s ? -y : y; } micropython-1.12/lib/libm/ef_rem_pio2.c000066400000000000000000000141711357706137100200510ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* ef_rem_pio2.c -- float version of e_rem_pio2.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* __ieee754_rem_pio2f(x,y) * * return the remainder of x rem pi/2 in y[0]+y[1] * use __kernel_rem_pio2f() */ #include "fdlibm.h" /* * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi */ #ifdef __STDC__ static const __int32_t two_over_pi[] = { #else static __int32_t two_over_pi[] = { #endif 0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC, 0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62, 0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63, 0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A, 0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09, 0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29, 0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44, 0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41, 0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C, 0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8, 0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11, 0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF, 0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E, 0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5, 0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92, 0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08, 0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0, 0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3, 0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85, 0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80, 0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA, 0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B, }; /* This array is like the one in e_rem_pio2.c, but the numbers are single precision and the last 8 bits are forced to 0. */ #ifdef __STDC__ static const __int32_t npio2_hw[] = { #else static __int32_t npio2_hw[] = { #endif 0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00, 0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00, 0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100, 0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00, 0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00, 0x4242c700, 0x42490f00 }; /* * invpio2: 24 bits of 2/pi * pio2_1: first 17 bit of pi/2 * pio2_1t: pi/2 - pio2_1 * pio2_2: second 17 bit of pi/2 * pio2_2t: pi/2 - (pio2_1+pio2_2) * pio2_3: third 17 bit of pi/2 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) */ #ifdef __STDC__ static const float #else static float #endif zero = 0.0000000000e+00, /* 0x00000000 */ half = 5.0000000000e-01, /* 0x3f000000 */ two8 = 2.5600000000e+02, /* 0x43800000 */ invpio2 = 6.3661980629e-01, /* 0x3f22f984 */ pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */ pio2_1t = 1.0804334124e-05, /* 0x37354443 */ pio2_2 = 1.0804273188e-05, /* 0x37354400 */ pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */ pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */ pio2_3t = 6.1232342629e-17; /* 0x248d3132 */ #ifdef __STDC__ __int32_t __ieee754_rem_pio2f(float x, float *y) #else __int32_t __ieee754_rem_pio2f(x,y) float x,y[]; #endif { float z,w,t,r,fn; float tx[3]; __int32_t i,j,n,ix,hx; int e0,nx; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */ {y[0] = x; y[1] = 0; return 0;} if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */ if(hx>0) { z = x - pio2_1; if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */ y[0] = z - pio2_1t; y[1] = (z-y[0])-pio2_1t; } else { /* near pi/2, use 24+24+24 bit pi */ z -= pio2_2; y[0] = z - pio2_2t; y[1] = (z-y[0])-pio2_2t; } return 1; } else { /* negative x */ z = x + pio2_1; if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */ y[0] = z + pio2_1t; y[1] = (z-y[0])+pio2_1t; } else { /* near pi/2, use 24+24+24 bit pi */ z += pio2_2; y[0] = z + pio2_2t; y[1] = (z-y[0])+pio2_2t; } return -1; } } if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */ t = fabsf(x); n = (__int32_t) (t*invpio2+half); fn = (float)n; r = t-fn*pio2_1; w = fn*pio2_1t; /* 1st round good to 40 bit */ if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) { y[0] = r-w; /* quick check no cancellation */ } else { __uint32_t high; j = ix>>23; y[0] = r-w; GET_FLOAT_WORD(high,y[0]); i = j-((high>>23)&0xff); if(i>8) { /* 2nd iteration needed, good to 57 */ t = r; w = fn*pio2_2; r = t-w; w = fn*pio2_2t-((t-r)-w); y[0] = r-w; GET_FLOAT_WORD(high,y[0]); i = j-((high>>23)&0xff); if(i>25) { /* 3rd iteration need, 74 bits acc */ t = r; /* will cover all possible cases */ w = fn*pio2_3; r = t-w; w = fn*pio2_3t-((t-r)-w); y[0] = r-w; } } } y[1] = (r-y[0])-w; if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} else return n; } /* * all other (large) arguments */ if(!FLT_UWORD_IS_FINITE(ix)) { y[0]=y[1]=x-x; return 0; } /* set z = scalbn(|x|,ilogb(x)-7) */ e0 = (int)((ix>>23)-134); /* e0 = ilogb(z)-7; */ SET_FLOAT_WORD(z, ix - ((__int32_t)e0<<23)); for(i=0;i<2;i++) { tx[i] = (float)((__int32_t)(z)); z = (z-tx[i])*two8; } tx[2] = z; nx = 3; while(tx[nx-1]==zero) nx--; /* skip zero term */ n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi); if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} return n; } micropython-1.12/lib/libm/ef_sqrt.c000066400000000000000000000045301357706137100173240ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* ef_sqrtf.c -- float version of e_sqrt.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ static const float one = 1.0, tiny=1.0e-30; #else static float one = 1.0, tiny=1.0e-30; #endif // sqrtf is exactly __ieee754_sqrtf when _IEEE_LIBM defined float sqrtf(float x) /* #ifdef __STDC__ float __ieee754_sqrtf(float x) #else float __ieee754_sqrtf(x) float x; #endif */ { float z; __uint32_t r,hx; __int32_t ix,s,q,m,t,i; GET_FLOAT_WORD(ix,x); hx = ix&0x7fffffff; /* take care of Inf and NaN */ if(!FLT_UWORD_IS_FINITE(hx)) return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf sqrt(-inf)=sNaN */ /* take care of zero and -ves */ if(FLT_UWORD_IS_ZERO(hx)) return x;/* sqrt(+-0) = +-0 */ if(ix<0) return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ /* normalize x */ m = (ix>>23); if(FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal x */ for(i=0;(ix&0x00800000L)==0;i++) ix<<=1; m -= i-1; } m -= 127; /* unbias exponent */ ix = (ix&0x007fffffL)|0x00800000L; if(m&1) /* odd m, double x to make it even */ ix += ix; m >>= 1; /* m = [m/2] */ /* generate sqrt(x) bit by bit */ ix += ix; q = s = 0; /* q = sqrt(x) */ r = 0x01000000L; /* r = moving bit from right to left */ while(r!=0) { t = s+r; if(t<=ix) { s = t+r; ix -= t; q += r; } ix += ix; r>>=1; } /* use floating add to find out rounding direction */ if(ix!=0) { z = one-tiny; /* trigger inexact flag */ if (z>=one) { z = one+tiny; if (z>one) q += 2; else q += (q&1); } } ix = (q>>1)+0x3f000000L; ix += (m <<23); SET_FLOAT_WORD(z,ix); return z; } micropython-1.12/lib/libm/erf_lgamma.c000066400000000000000000000172161357706137100177600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* erf_lgamma.c -- float version of er_lgamma.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ #include "fdlibm.h" #define __ieee754_logf logf #ifdef __STDC__ static const float #else static float #endif two23= 8.3886080000e+06, /* 0x4b000000 */ half= 5.0000000000e-01, /* 0x3f000000 */ one = 1.0000000000e+00, /* 0x3f800000 */ pi = 3.1415927410e+00, /* 0x40490fdb */ a0 = 7.7215664089e-02, /* 0x3d9e233f */ a1 = 3.2246702909e-01, /* 0x3ea51a66 */ a2 = 6.7352302372e-02, /* 0x3d89f001 */ a3 = 2.0580807701e-02, /* 0x3ca89915 */ a4 = 7.3855509982e-03, /* 0x3bf2027e */ a5 = 2.8905137442e-03, /* 0x3b3d6ec6 */ a6 = 1.1927076848e-03, /* 0x3a9c54a1 */ a7 = 5.1006977446e-04, /* 0x3a05b634 */ a8 = 2.2086278477e-04, /* 0x39679767 */ a9 = 1.0801156895e-04, /* 0x38e28445 */ a10 = 2.5214456400e-05, /* 0x37d383a2 */ a11 = 4.4864096708e-05, /* 0x383c2c75 */ tc = 1.4616321325e+00, /* 0x3fbb16c3 */ tf = -1.2148628384e-01, /* 0xbdf8cdcd */ /* tt = -(tail of tf) */ tt = 6.6971006518e-09, /* 0x31e61c52 */ t0 = 4.8383611441e-01, /* 0x3ef7b95e */ t1 = -1.4758771658e-01, /* 0xbe17213c */ t2 = 6.4624942839e-02, /* 0x3d845a15 */ t3 = -3.2788541168e-02, /* 0xbd064d47 */ t4 = 1.7970675603e-02, /* 0x3c93373d */ t5 = -1.0314224288e-02, /* 0xbc28fcfe */ t6 = 6.1005386524e-03, /* 0x3bc7e707 */ t7 = -3.6845202558e-03, /* 0xbb7177fe */ t8 = 2.2596477065e-03, /* 0x3b141699 */ t9 = -1.4034647029e-03, /* 0xbab7f476 */ t10 = 8.8108185446e-04, /* 0x3a66f867 */ t11 = -5.3859531181e-04, /* 0xba0d3085 */ t12 = 3.1563205994e-04, /* 0x39a57b6b */ t13 = -3.1275415677e-04, /* 0xb9a3f927 */ t14 = 3.3552918467e-04, /* 0x39afe9f7 */ u0 = -7.7215664089e-02, /* 0xbd9e233f */ u1 = 6.3282704353e-01, /* 0x3f2200f4 */ u2 = 1.4549225569e+00, /* 0x3fba3ae7 */ u3 = 9.7771751881e-01, /* 0x3f7a4bb2 */ u4 = 2.2896373272e-01, /* 0x3e6a7578 */ u5 = 1.3381091878e-02, /* 0x3c5b3c5e */ v1 = 2.4559779167e+00, /* 0x401d2ebe */ v2 = 2.1284897327e+00, /* 0x4008392d */ v3 = 7.6928514242e-01, /* 0x3f44efdf */ v4 = 1.0422264785e-01, /* 0x3dd572af */ v5 = 3.2170924824e-03, /* 0x3b52d5db */ s0 = -7.7215664089e-02, /* 0xbd9e233f */ s1 = 2.1498242021e-01, /* 0x3e5c245a */ s2 = 3.2577878237e-01, /* 0x3ea6cc7a */ s3 = 1.4635047317e-01, /* 0x3e15dce6 */ s4 = 2.6642270386e-02, /* 0x3cda40e4 */ s5 = 1.8402845599e-03, /* 0x3af135b4 */ s6 = 3.1947532989e-05, /* 0x3805ff67 */ r1 = 1.3920053244e+00, /* 0x3fb22d3b */ r2 = 7.2193557024e-01, /* 0x3f38d0c5 */ r3 = 1.7193385959e-01, /* 0x3e300f6e */ r4 = 1.8645919859e-02, /* 0x3c98bf54 */ r5 = 7.7794247773e-04, /* 0x3a4beed6 */ r6 = 7.3266842264e-06, /* 0x36f5d7bd */ w0 = 4.1893854737e-01, /* 0x3ed67f1d */ w1 = 8.3333335817e-02, /* 0x3daaaaab */ w2 = -2.7777778450e-03, /* 0xbb360b61 */ w3 = 7.9365057172e-04, /* 0x3a500cfd */ w4 = -5.9518753551e-04, /* 0xba1c065c */ w5 = 8.3633989561e-04, /* 0x3a5b3dd2 */ w6 = -1.6309292987e-03; /* 0xbad5c4e8 */ #ifdef __STDC__ static const float zero= 0.0000000000e+00; #else static float zero= 0.0000000000e+00; #endif #ifdef __STDC__ static float sin_pif(float x) #else static float sin_pif(x) float x; #endif { float y,z; __int32_t n,ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; if(ix<0x3e800000) return __kernel_sinf(pi*x,zero,0); y = -x; /* x is assume negative */ /* * argument reduction, make sure inexact flag not raised if input * is an integer */ z = floorf(y); if(z!=y) { /* inexact anyway */ y *= (float)0.5; y = (float)2.0*(y - floorf(y)); /* y = |x| mod 2.0 */ n = (__int32_t) (y*(float)4.0); } else { if(ix>=0x4b800000) { y = zero; n = 0; /* y must be even */ } else { if(ix<0x4b000000) z = y+two23; /* exact */ GET_FLOAT_WORD(n,z); n &= 1; y = n; n<<= 2; } } switch (n) { case 0: y = __kernel_sinf(pi*y,zero,0); break; case 1: case 2: y = __kernel_cosf(pi*((float)0.5-y),zero); break; case 3: case 4: y = __kernel_sinf(pi*(one-y),zero,0); break; case 5: case 6: y = -__kernel_cosf(pi*(y-(float)1.5),zero); break; default: y = __kernel_sinf(pi*(y-(float)2.0),zero,0); break; } return -y; } #ifdef __STDC__ float __ieee754_lgammaf_r(float x, int *signgamp) #else float __ieee754_lgammaf_r(x,signgamp) float x; int *signgamp; #endif { float t,y,z,nadj = 0.0,p,p1,p2,p3,q,r,w; __int32_t i,hx,ix; GET_FLOAT_WORD(hx,x); /* purge off +-inf, NaN, +-0, and negative arguments */ *signgamp = 1; ix = hx&0x7fffffff; if(ix>=0x7f800000) return x*x; if(ix==0) return one/zero; if(ix<0x1c800000) { /* |x|<2**-70, return -log(|x|) */ if(hx<0) { *signgamp = -1; return -__ieee754_logf(-x); } else return -__ieee754_logf(x); } if(hx<0) { if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */ return one/zero; t = sin_pif(x); if(t==zero) return one/zero; /* -integer */ nadj = __ieee754_logf(pi/fabsf(t*x)); if(t=0x3f3b4a20) {y = one-x; i= 0;} else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;} else {y = x; i=2;} } else { r = zero; if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */ else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */ else {y=x-one;i=2;} } switch(i) { case 0: z = y*y; p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); p = y*p1+p2; r += (p-(float)0.5*y); break; case 1: z = y*y; w = z*y; p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); p = z*p1-(tt-w*(p2+y*p3)); r += (tf + p); break; case 2: p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); r += (-(float)0.5*y + p1/p2); } } else if(ix<0x41000000) { /* x < 8.0 */ i = (__int32_t)x; t = zero; y = x-(float)i; p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); r = half*y+p/q; z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ switch(i) { case 7: z *= (y+(float)6.0); /* FALLTHRU */ case 6: z *= (y+(float)5.0); /* FALLTHRU */ case 5: z *= (y+(float)4.0); /* FALLTHRU */ case 4: z *= (y+(float)3.0); /* FALLTHRU */ case 3: z *= (y+(float)2.0); /* FALLTHRU */ r += __ieee754_logf(z); break; } /* 8.0 <= x < 2**58 */ } else if (ix < 0x5c800000) { t = __ieee754_logf(x); z = one/x; y = z*z; w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); r = (x-half)*(t-one)+w; } else /* 2**58 <= x <= inf */ r = x*(__ieee754_logf(x)-one); if(hx<0) r = nadj - r; return r; } micropython-1.12/lib/libm/fdlibm.h000066400000000000000000000160361357706137100171270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * This file is adapted from from newlib-nano-2, the newlib/libm/common/fdlib.h, * available from https://github.com/32bitmicro/newlib-nano-2. The main change * is removal of anything to do with double precision. * * Appropriate copyright headers are reproduced below. */ /* @(#)fdlibm.h 5.1 93/09/24 */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include /* Default to XOPEN_MODE. */ #define _XOPEN_MODE /* Most routines need to check whether a float is finite, infinite, or not a number, and many need to know whether the result of an operation will overflow. These conditions depend on whether the largest exponent is used for NaNs & infinities, or whether it's used for finite numbers. The macros below wrap up that kind of information: FLT_UWORD_IS_FINITE(X) True if a positive float with bitmask X is finite. FLT_UWORD_IS_NAN(X) True if a positive float with bitmask X is not a number. FLT_UWORD_IS_INFINITE(X) True if a positive float with bitmask X is +infinity. FLT_UWORD_MAX The bitmask of FLT_MAX. FLT_UWORD_HALF_MAX The bitmask of FLT_MAX/2. FLT_UWORD_EXP_MAX The bitmask of the largest finite exponent (129 if the largest exponent is used for finite numbers, 128 otherwise). FLT_UWORD_LOG_MAX The bitmask of log(FLT_MAX), rounded down. This value is the largest input that can be passed to exp() without producing overflow. FLT_UWORD_LOG_2MAX The bitmask of log(2*FLT_MAX), rounded down. This value is the largest input than can be passed to cosh() without producing overflow. FLT_LARGEST_EXP The largest biased exponent that can be used for finite numbers (255 if the largest exponent is used for finite numbers, 254 otherwise) */ #ifdef _FLT_LARGEST_EXPONENT_IS_NORMAL #define FLT_UWORD_IS_FINITE(x) 1 #define FLT_UWORD_IS_NAN(x) 0 #define FLT_UWORD_IS_INFINITE(x) 0 #define FLT_UWORD_MAX 0x7fffffff #define FLT_UWORD_EXP_MAX 0x43010000 #define FLT_UWORD_LOG_MAX 0x42b2d4fc #define FLT_UWORD_LOG_2MAX 0x42b437e0 #define HUGE ((float)0X1.FFFFFEP128) #else #define FLT_UWORD_IS_FINITE(x) ((x)<0x7f800000L) #define FLT_UWORD_IS_NAN(x) ((x)>0x7f800000L) #define FLT_UWORD_IS_INFINITE(x) ((x)==0x7f800000L) #define FLT_UWORD_MAX 0x7f7fffffL #define FLT_UWORD_EXP_MAX 0x43000000 #define FLT_UWORD_LOG_MAX 0x42b17217 #define FLT_UWORD_LOG_2MAX 0x42b2d4fc #define HUGE ((float)3.40282346638528860e+38) #endif #define FLT_UWORD_HALF_MAX (FLT_UWORD_MAX-(1L<<23)) #define FLT_LARGEST_EXP (FLT_UWORD_MAX>>23) /* Many routines check for zero and subnormal numbers. Such things depend on whether the target supports denormals or not: FLT_UWORD_IS_ZERO(X) True if a positive float with bitmask X is +0. Without denormals, any float with a zero exponent is a +0 representation. With denormals, the only +0 representation is a 0 bitmask. FLT_UWORD_IS_SUBNORMAL(X) True if a non-zero positive float with bitmask X is subnormal. (Routines should check for zeros first.) FLT_UWORD_MIN The bitmask of the smallest float above +0. Call this number REAL_FLT_MIN... FLT_UWORD_EXP_MIN The bitmask of the float representation of REAL_FLT_MIN's exponent. FLT_UWORD_LOG_MIN The bitmask of |log(REAL_FLT_MIN)|, rounding down. FLT_SMALLEST_EXP REAL_FLT_MIN's exponent - EXP_BIAS (1 if denormals are not supported, -22 if they are). */ #ifdef _FLT_NO_DENORMALS #define FLT_UWORD_IS_ZERO(x) ((x)<0x00800000L) #define FLT_UWORD_IS_SUBNORMAL(x) 0 #define FLT_UWORD_MIN 0x00800000 #define FLT_UWORD_EXP_MIN 0x42fc0000 #define FLT_UWORD_LOG_MIN 0x42aeac50 #define FLT_SMALLEST_EXP 1 #else #define FLT_UWORD_IS_ZERO(x) ((x)==0) #define FLT_UWORD_IS_SUBNORMAL(x) ((x)<0x00800000L) #define FLT_UWORD_MIN 0x00000001 #define FLT_UWORD_EXP_MIN 0x43160000 #define FLT_UWORD_LOG_MIN 0x42cff1b5 #define FLT_SMALLEST_EXP -22 #endif #ifdef __STDC__ #undef __P #define __P(p) p #else #define __P(p) () #endif /* * set X_TLOSS = pi*2**52, which is possibly defined in * (one may replace the following line by "#include ") */ #define X_TLOSS 1.41484755040568800000e+16 /* Functions that are not documented, and are not in . */ /* Undocumented float functions. */ #ifdef _SCALB_INT extern float scalbf __P((float, int)); #else extern float scalbf __P((float, float)); #endif extern float significandf __P((float)); /* ieee style elementary float functions */ extern float __ieee754_sqrtf __P((float)); extern float __ieee754_acosf __P((float)); extern float __ieee754_acoshf __P((float)); extern float __ieee754_logf __P((float)); extern float __ieee754_atanhf __P((float)); extern float __ieee754_asinf __P((float)); extern float __ieee754_atan2f __P((float,float)); extern float __ieee754_expf __P((float)); extern float __ieee754_coshf __P((float)); extern float __ieee754_fmodf __P((float,float)); extern float __ieee754_powf __P((float,float)); extern float __ieee754_lgammaf_r __P((float,int *)); extern float __ieee754_gammaf_r __P((float,int *)); extern float __ieee754_log10f __P((float)); extern float __ieee754_sinhf __P((float)); extern float __ieee754_hypotf __P((float,float)); extern float __ieee754_j0f __P((float)); extern float __ieee754_j1f __P((float)); extern float __ieee754_y0f __P((float)); extern float __ieee754_y1f __P((float)); extern float __ieee754_jnf __P((int,float)); extern float __ieee754_ynf __P((int,float)); extern float __ieee754_remainderf __P((float,float)); extern __int32_t __ieee754_rem_pio2f __P((float,float*)); #ifdef _SCALB_INT extern float __ieee754_scalbf __P((float,int)); #else extern float __ieee754_scalbf __P((float,float)); #endif /* float versions of fdlibm kernel functions */ extern float __kernel_sinf __P((float,float,int)); extern float __kernel_cosf __P((float,float)); extern float __kernel_tanf __P((float,float,int)); extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const __int32_t*)); /* A union which permits us to convert between a float and a 32 bit int. */ typedef union { float value; __uint32_t word; } ieee_float_shape_type; /* Get a 32 bit int from a float. */ #define GET_FLOAT_WORD(i,d) \ do { \ ieee_float_shape_type gf_u; \ gf_u.value = (d); \ (i) = gf_u.word; \ } while (0) /* Set a float from a 32 bit int. */ #define SET_FLOAT_WORD(d,i) \ do { \ ieee_float_shape_type sf_u; \ sf_u.word = (i); \ (d) = sf_u.value; \ } while (0) /* Macros to avoid undefined behaviour that can arise if the amount of a shift is exactly equal to the size of the shifted operand. */ #define SAFE_LEFT_SHIFT(op,amt) \ (((amt) < 8 * sizeof(op)) ? ((op) << (amt)) : 0) #define SAFE_RIGHT_SHIFT(op,amt) \ (((amt) < 8 * sizeof(op)) ? ((op) >> (amt)) : 0) micropython-1.12/lib/libm/fmodf.c000066400000000000000000000026311357706137100167540ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // fmodf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ #include "libm.h" float fmodf(float x, float y) { union {float f; uint32_t i;} ux = {x}, uy = {y}; int ex = ux.i>>23 & 0xff; int ey = uy.i>>23 & 0xff; uint32_t sx = ux.i & 0x80000000; uint32_t i; uint32_t uxi = ux.i; if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) return (x*y)/(x*y); if (uxi<<1 <= uy.i<<1) { if (uxi<<1 == uy.i<<1) return 0*x; return x; } /* normalize x and y */ if (!ex) { for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); uxi <<= -ex + 1; } else { uxi &= -1U >> 9; uxi |= 1U << 23; } if (!ey) { for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); uy.i <<= -ey + 1; } else { uy.i &= -1U >> 9; uy.i |= 1U << 23; } /* x mod y */ for (; ex > ey; ex--) { i = uxi - uy.i; if (i >> 31 == 0) { if (i == 0) return 0*x; uxi = i; } uxi <<= 1; } i = uxi - uy.i; if (i >> 31 == 0) { if (i == 0) return 0*x; uxi = i; } for (; uxi>>23 == 0; uxi <<= 1, ex--); /* scale result up */ if (ex > 0) { uxi -= 1U << 23; uxi |= (uint32_t)ex << 23; } else { uxi >>= -ex + 1; } uxi |= sx; ux.i = uxi; return ux.f; } micropython-1.12/lib/libm/kf_cos.c000066400000000000000000000035221357706137100171250ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* kf_cos.c -- float version of k_cos.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ static const float #else static float #endif one = 1.0000000000e+00, /* 0x3f800000 */ C1 = 4.1666667908e-02, /* 0x3d2aaaab */ C2 = -1.3888889225e-03, /* 0xbab60b61 */ C3 = 2.4801587642e-05, /* 0x37d00d01 */ C4 = -2.7557314297e-07, /* 0xb493f27c */ C5 = 2.0875723372e-09, /* 0x310f74f6 */ C6 = -1.1359647598e-11; /* 0xad47d74e */ #ifdef __STDC__ float __kernel_cosf(float x, float y) #else float __kernel_cosf(x, y) float x,y; #endif { float a,hz,z,r,qx; __int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; /* ix = |x|'s high word*/ if(ix<0x32000000) { /* if x < 2**27 */ if(((int)x)==0) return one; /* generate inexact */ } z = x*x; r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); if(ix < 0x3e99999a) /* if |x| < 0.3 */ return one - ((float)0.5*z - (z*r - x*y)); else { if(ix > 0x3f480000) { /* x > 0.78125 */ qx = (float)0.28125; } else { SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */ } hz = (float)0.5*z-qx; a = one-qx; return a - (hz - (z*r-x*y)); } } micropython-1.12/lib/libm/kf_rem_pio2.c000066400000000000000000000125771357706137100200670ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* kf_rem_pio2.c -- float version of k_rem_pio2.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" /* In the float version, the input parameter x contains 8 bit integers, not 24 bit integers. 113 bit precision is not supported. */ #ifdef __STDC__ static const int init_jk[] = {4,7,9}; /* initial value for jk */ #else static int init_jk[] = {4,7,9}; #endif #ifdef __STDC__ static const float PIo2[] = { #else static float PIo2[] = { #endif 1.5703125000e+00, /* 0x3fc90000 */ 4.5776367188e-04, /* 0x39f00000 */ 2.5987625122e-05, /* 0x37da0000 */ 7.5437128544e-08, /* 0x33a20000 */ 6.0026650317e-11, /* 0x2e840000 */ 7.3896444519e-13, /* 0x2b500000 */ 5.3845816694e-15, /* 0x27c20000 */ 5.6378512969e-18, /* 0x22d00000 */ 8.3009228831e-20, /* 0x1fc40000 */ 3.2756352257e-22, /* 0x1bc60000 */ 6.3331015649e-25, /* 0x17440000 */ }; #ifdef __STDC__ static const float #else static float #endif zero = 0.0, one = 1.0, two8 = 2.5600000000e+02, /* 0x43800000 */ twon8 = 3.9062500000e-03; /* 0x3b800000 */ #ifdef __STDC__ int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const __int32_t *ipio2) #else int __kernel_rem_pio2f(x,y,e0,nx,prec,ipio2) float x[], y[]; int e0,nx,prec; __int32_t ipio2[]; #endif { __int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; float z,fw,f[20],fq[20],q[20]; /* initialize jk*/ jk = init_jk[prec]; jp = jk; /* determine jx,jv,q0, note that 3>q0 */ jx = nx-1; jv = (e0-3)/8; if(jv<0) jv=0; q0 = e0-8*(jv+1); /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ j = jv-jx; m = jx+jk; for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j]; /* compute q[0],q[1],...q[jk] */ for (i=0;i<=jk;i++) { for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; } jz = jk; recompute: /* distill q[] into iq[] reversingly */ for(i=0,j=jz,z=q[jz];j>0;i++,j--) { fw = (float)((__int32_t)(twon8* z)); iq[i] = (__int32_t)(z-two8*fw); z = q[j-1]+fw; } /* compute n */ z = scalbnf(z,(int)q0); /* actual value of z */ z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */ n = (__int32_t) z; z -= (float)n; ih = 0; if(q0>0) { /* need iq[jz-1] to determine n */ i = (iq[jz-1]>>(8-q0)); n += i; iq[jz-1] -= i<<(8-q0); ih = iq[jz-1]>>(7-q0); } else if(q0==0) ih = iq[jz-1]>>8; else if(z>=(float)0.5) ih=2; if(ih>0) { /* q > 0.5 */ n += 1; carry = 0; for(i=0;i0) { /* rare case: chance is 1 in 12 */ switch(q0) { case 1: iq[jz-1] &= 0x7f; break; case 2: iq[jz-1] &= 0x3f; break; } } if(ih==2) { z = one - z; if(carry!=0) z -= scalbnf(one,(int)q0); } } /* check if recomputation is needed */ if(z==zero) { j = 0; for (i=jz-1;i>=jk;i--) j |= iq[i]; if(j==0) { /* need recomputation */ for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ f[jx+i] = (float) ipio2[jv+i]; for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; } jz += k; goto recompute; } } /* chop off zero terms */ if(z==(float)0.0) { jz -= 1; q0 -= 8; while(iq[jz]==0) { jz--; q0-=8;} } else { /* break z into 8-bit if necessary */ z = scalbnf(z,-(int)q0); if(z>=two8) { fw = (float)((__int32_t)(twon8*z)); iq[jz] = (__int32_t)(z-two8*fw); jz += 1; q0 += 8; iq[jz] = (__int32_t) fw; } else iq[jz] = (__int32_t) z ; } /* convert integer "bit" chunk to floating-point value */ fw = scalbnf(one,(int)q0); for(i=jz;i>=0;i--) { q[i] = fw*(float)iq[i]; fw*=twon8; } /* compute PIo2[0,...,jp]*q[jz,...,0] */ for(i=jz;i>=0;i--) { for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; fq[jz-i] = fw; } /* compress fq[] into y[] */ switch(prec) { case 0: fw = 0.0; for (i=jz;i>=0;i--) fw += fq[i]; y[0] = (ih==0)? fw: -fw; break; case 1: case 2: fw = 0.0; for (i=jz;i>=0;i--) fw += fq[i]; y[0] = (ih==0)? fw: -fw; fw = fq[0]-fw; for (i=1;i<=jz;i++) fw += fq[i]; y[1] = (ih==0)? fw: -fw; break; case 3: /* painful */ for (i=jz;i>0;i--) { fw = fq[i-1]+fq[i]; fq[i] += fq[i-1]-fw; fq[i-1] = fw; } for (i=jz;i>1;i--) { fw = fq[i-1]+fq[i]; fq[i] += fq[i-1]-fw; fq[i-1] = fw; } for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; if(ih==0) { y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; } else { y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; } } return n&7; } micropython-1.12/lib/libm/kf_sin.c000066400000000000000000000031661357706137100171360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* kf_sin.c -- float version of k_sin.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ static const float #else static float #endif half = 5.0000000000e-01,/* 0x3f000000 */ S1 = -1.6666667163e-01, /* 0xbe2aaaab */ S2 = 8.3333337680e-03, /* 0x3c088889 */ S3 = -1.9841270114e-04, /* 0xb9500d01 */ S4 = 2.7557314297e-06, /* 0x3638ef1b */ S5 = -2.5050759689e-08, /* 0xb2d72f34 */ S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */ #ifdef __STDC__ float __kernel_sinf(float x, float y, int iy) #else float __kernel_sinf(x, y, iy) float x,y; int iy; /* iy=0 if y is zero */ #endif { float z,r,v; __int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; /* high word of x */ if(ix<0x32000000) /* |x| < 2**-27 */ {if((int)x==0) return x;} /* generate inexact */ z = x*x; v = z*x; r = S2+z*(S3+z*(S4+z*(S5+z*S6))); if(iy==0) return x+v*(S1+z*r); else return x-((z*(half*y-v*r)-y)-v*S1); } micropython-1.12/lib/libm/kf_tan.c000066400000000000000000000056141357706137100171270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* kf_tan.c -- float version of k_tan.c * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "libm.h" #ifdef __STDC__ static const float #else static float #endif one = 1.0000000000e+00, /* 0x3f800000 */ pio4 = 7.8539812565e-01, /* 0x3f490fda */ pio4lo= 3.7748947079e-08, /* 0x33222168 */ T[] = { 3.3333334327e-01, /* 0x3eaaaaab */ 1.3333334029e-01, /* 0x3e088889 */ 5.3968254477e-02, /* 0x3d5d0dd1 */ 2.1869488060e-02, /* 0x3cb327a4 */ 8.8632395491e-03, /* 0x3c11371f */ 3.5920790397e-03, /* 0x3b6b6916 */ 1.4562094584e-03, /* 0x3abede48 */ 5.8804126456e-04, /* 0x3a1a26c8 */ 2.4646313977e-04, /* 0x398137b9 */ 7.8179444245e-05, /* 0x38a3f445 */ 7.1407252108e-05, /* 0x3895c07a */ -1.8558637748e-05, /* 0xb79bae5f */ 2.5907305826e-05, /* 0x37d95384 */ }; #ifdef __STDC__ float __kernel_tanf(float x, float y, int iy) #else float __kernel_tanf(x, y, iy) float x,y; int iy; #endif { float z,r,v,w,s; __int32_t ix,hx; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; /* high word of |x| */ if(ix<0x31800000) /* x < 2**-28 */ {if((int)x==0) { /* generate inexact */ if((ix|(iy+1))==0) return one/fabsf(x); else return (iy==1)? x: -one/x; } } if(ix>=0x3f2ca140) { /* |x|>=0.6744 */ if(hx<0) {x = -x; y = -y;} z = pio4-x; w = pio4lo-y; x = z+w; y = 0.0; } z = x*x; w = z*z; /* Break x^5*(T[1]+x^2*T[2]+...) into * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) */ r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11])))); v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12]))))); s = z*x; r = y + z*(s*(r+v)+y); r += T[0]*s; w = x+r; if(ix>=0x3f2ca140) { v = (float)iy; return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r))); } if(iy==1) return w; else { /* if allow error up to 2 ulp, simply return -1.0/(x+r) here */ /* compute -1.0/(x+r) accurately */ float a,t; __int32_t i; z = w; GET_FLOAT_WORD(i,z); SET_FLOAT_WORD(z,i&0xfffff000); v = r-(z - x); /* z+v = r+x */ t = a = -(float)1.0/w; /* a = -1.0/w */ GET_FLOAT_WORD(i,t); SET_FLOAT_WORD(t,i&0xfffff000); s = (float)1.0+t*z; return t+a*(s+t*v); } } micropython-1.12/lib/libm/libm.h000066400000000000000000000041121357706137100166050ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // portions extracted from musl-0.9.15 libm.h /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include #include #define FLT_EVAL_METHOD 0 #define FORCE_EVAL(x) do { \ if (sizeof(x) == sizeof(float)) { \ volatile float __x; \ __x = (x); \ (void)__x; \ } else if (sizeof(x) == sizeof(double)) { \ volatile double __x; \ __x = (x); \ (void)__x; \ } else { \ volatile long double __x; \ __x = (x); \ (void)__x; \ } \ } while(0) /* Get a 32 bit int from a float. */ #define GET_FLOAT_WORD(w,d) \ do { \ union {float f; uint32_t i;} __u; \ __u.f = (d); \ (w) = __u.i; \ } while (0) /* Set a float from a 32 bit int. */ #define SET_FLOAT_WORD(d,w) \ do { \ union {float f; uint32_t i;} __u; \ __u.i = (w); \ (d) = __u.f; \ } while (0) micropython-1.12/lib/libm/log1pf.c000066400000000000000000000044411357706137100170520ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // log1pf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/s_log1pf.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "libm.h" static const float ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ /* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ float log1pf(float x) { union {float f; uint32_t i;} u = {x}; float_t hfsq,f,c,s,z,R,w,t1,t2,dk; uint32_t ix,iu; int k; ix = u.i; k = 1; if (ix < 0x3ed413d0 || ix>>31) { /* 1+x < sqrt(2)+ */ if (ix >= 0xbf800000) { /* x <= -1.0 */ if (x == -1) return x/0.0f; /* log1p(-1)=+inf */ return (x-x)/0.0f; /* log1p(x<-1)=NaN */ } if (ix<<1 < 0x33800000<<1) { /* |x| < 2**-24 */ /* underflow if subnormal */ if ((ix&0x7f800000) == 0) FORCE_EVAL(x*x); return x; } if (ix <= 0xbe95f619) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ k = 0; c = 0; f = x; } } else if (ix >= 0x7f800000) return x; if (k) { u.f = 1 + x; iu = u.i; iu += 0x3f800000 - 0x3f3504f3; k = (int)(iu>>23) - 0x7f; /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ if (k < 25) { c = k >= 2 ? 1-(u.f-x) : x-(u.f-1); c /= u.f; } else c = 0; /* reduce u into [sqrt(2)/2, sqrt(2)] */ iu = (iu&0x007fffff) + 0x3f3504f3; u.i = iu; f = u.f - 1; } s = f/(2.0f + f); z = s*s; w = z*z; t1= w*(Lg2+w*Lg4); t2= z*(Lg1+w*Lg3); R = t2 + t1; hfsq = 0.5f*f*f; dk = k; return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi; } micropython-1.12/lib/libm/math.c000066400000000000000000000535771357706137100166310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "libm.h" typedef float float_t; typedef union { float f; struct { uint32_t m : 23; uint32_t e : 8; uint32_t s : 1; }; } float_s_t; int __signbitf(float f) { float_s_t u = {.f = f}; return u.s; } #ifndef NDEBUG float copysignf(float x, float y) { float_s_t fx={.f = x}; float_s_t fy={.f = y}; // copy sign bit; fx.s = fy.s; return fx.f; } #endif static const float _M_LN10 = 2.30258509299404; // 0x40135d8e float log10f(float x) { return logf(x) / (float)_M_LN10; } float tanhf(float x) { int sign = 0; if (x < 0) { sign = 1; x = -x; } x = expm1f(-2 * x); x = x / (x + 2); return sign ? x : -x; } /*****************************************************************************/ /*****************************************************************************/ // __fpclassifyf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ int __fpclassifyf(float x) { union {float f; uint32_t i;} u = {x}; int e = u.i>>23 & 0xff; if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; if (e==0xff) return u.i<<9 ? FP_NAN : FP_INFINITE; return FP_NORMAL; } /*****************************************************************************/ /*****************************************************************************/ // scalbnf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ float scalbnf(float x, int n) { union {float f; uint32_t i;} u; float_t y = x; if (n > 127) { y *= 0x1p127f; n -= 127; if (n > 127) { y *= 0x1p127f; n -= 127; if (n > 127) n = 127; } } else if (n < -126) { y *= 0x1p-126f; n += 126; if (n < -126) { y *= 0x1p-126f; n += 126; if (n < -126) n = -126; } } u.i = (uint32_t)(0x7f+n)<<23; x = y * u.f; return x; } /*****************************************************************************/ /*****************************************************************************/ // powf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/e_powf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ static const float bp[] = {1.0, 1.5,}, dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */ dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */ two24 = 16777216.0, /* 0x4b800000 */ huge = 1.0e30, tiny = 1.0e-30, /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ L1 = 6.0000002384e-01, /* 0x3f19999a */ L2 = 4.2857143283e-01, /* 0x3edb6db7 */ L3 = 3.3333334327e-01, /* 0x3eaaaaab */ L4 = 2.7272811532e-01, /* 0x3e8ba305 */ L5 = 2.3066075146e-01, /* 0x3e6c3255 */ L6 = 2.0697501302e-01, /* 0x3e53f142 */ P1 = 1.6666667163e-01, /* 0x3e2aaaab */ P2 = -2.7777778450e-03, /* 0xbb360b61 */ P3 = 6.6137559770e-05, /* 0x388ab355 */ P4 = -1.6533901999e-06, /* 0xb5ddea0e */ P5 = 4.1381369442e-08, /* 0x3331bb4c */ lg2 = 6.9314718246e-01, /* 0x3f317218 */ lg2_h = 6.93145752e-01, /* 0x3f317200 */ lg2_l = 1.42860654e-06, /* 0x35bfbe8c */ ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */ cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */ cp_h = 9.6191406250e-01, /* 0x3f764000 =12b cp */ cp_l = -1.1736857402e-04, /* 0xb8f623c6 =tail of cp_h */ ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */ ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/ ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/ float powf(float x, float y) { float z,ax,z_h,z_l,p_h,p_l; float y1,t1,t2,r,s,sn,t,u,v,w; int32_t i,j,k,yisint,n; int32_t hx,hy,ix,iy,is; GET_FLOAT_WORD(hx, x); GET_FLOAT_WORD(hy, y); ix = hx & 0x7fffffff; iy = hy & 0x7fffffff; /* x**0 = 1, even if x is NaN */ if (iy == 0) return 1.0f; /* 1**y = 1, even if y is NaN */ if (hx == 0x3f800000) return 1.0f; /* NaN if either arg is NaN */ if (ix > 0x7f800000 || iy > 0x7f800000) return x + y; /* determine if y is an odd int when x < 0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ yisint = 0; if (hx < 0) { if (iy >= 0x4b800000) yisint = 2; /* even integer y */ else if (iy >= 0x3f800000) { k = (iy>>23) - 0x7f; /* exponent */ j = iy>>(23-k); if ((j<<(23-k)) == iy) yisint = 2 - (j & 1); } } /* special value of y */ if (iy == 0x7f800000) { /* y is +-inf */ if (ix == 0x3f800000) /* (-1)**+-inf is 1 */ return 1.0f; else if (ix > 0x3f800000) /* (|x|>1)**+-inf = inf,0 */ return hy >= 0 ? y : 0.0f; else if (ix != 0) /* (|x|<1)**+-inf = 0,inf if x!=0 */ return hy >= 0 ? 0.0f: -y; } if (iy == 0x3f800000) /* y is +-1 */ return hy >= 0 ? x : 1.0f/x; if (hy == 0x40000000) /* y is 2 */ return x*x; if (hy == 0x3f000000) { /* y is 0.5 */ if (hx >= 0) /* x >= +0 */ return sqrtf(x); } ax = fabsf(x); /* special value of x */ if (ix == 0x7f800000 || ix == 0 || ix == 0x3f800000) { /* x is +-0,+-inf,+-1 */ z = ax; if (hy < 0) /* z = (1/|x|) */ z = 1.0f/z; if (hx < 0) { if (((ix-0x3f800000)|yisint) == 0) { z = (z-z)/(z-z); /* (-1)**non-int is NaN */ } else if (yisint == 1) z = -z; /* (x<0)**odd = -(|x|**odd) */ } return z; } sn = 1.0f; /* sign of result */ if (hx < 0) { if (yisint == 0) /* (x<0)**(non-int) is NaN */ return (x-x)/(x-x); if (yisint == 1) /* (x<0)**(odd int) */ sn = -1.0f; } /* |y| is huge */ if (iy > 0x4d000000) { /* if |y| > 2**27 */ /* over/underflow if x is not close to one */ if (ix < 0x3f7ffff8) return hy < 0 ? sn*huge*huge : sn*tiny*tiny; if (ix > 0x3f800007) return hy > 0 ? sn*huge*huge : sn*tiny*tiny; /* now |1-x| is tiny <= 2**-20, suffice to compute log(x) by x-x^2/2+x^3/3-x^4/4 */ t = ax - 1; /* t has 20 trailing zeros */ w = (t*t)*(0.5f - t*(0.333333333333f - t*0.25f)); u = ivln2_h*t; /* ivln2_h has 16 sig. bits */ v = t*ivln2_l - w*ivln2; t1 = u + v; GET_FLOAT_WORD(is, t1); SET_FLOAT_WORD(t1, is & 0xfffff000); t2 = v - (t1-u); } else { float s2,s_h,s_l,t_h,t_l; n = 0; /* take care subnormal number */ if (ix < 0x00800000) { ax *= two24; n -= 24; GET_FLOAT_WORD(ix, ax); } n += ((ix)>>23) - 0x7f; j = ix & 0x007fffff; /* determine interval */ ix = j | 0x3f800000; /* normalize ix */ if (j <= 0x1cc471) /* |x|>1) & 0xfffff000) | 0x20000000; SET_FLOAT_WORD(t_h, is + 0x00400000 + (k<<21)); t_l = ax - (t_h - bp[k]); s_l = v*((u - s_h*t_h) - s_h*t_l); /* compute log(ax) */ s2 = s*s; r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); r += s_l*(s_h+s); s2 = s_h*s_h; t_h = 3.0f + s2 + r; GET_FLOAT_WORD(is, t_h); SET_FLOAT_WORD(t_h, is & 0xfffff000); t_l = r - ((t_h - 3.0f) - s2); /* u+v = s*(1+...) */ u = s_h*t_h; v = s_l*t_h + t_l*s; /* 2/(3log2)*(s+...) */ p_h = u + v; GET_FLOAT_WORD(is, p_h); SET_FLOAT_WORD(p_h, is & 0xfffff000); p_l = v - (p_h - u); z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ z_l = cp_l*p_h + p_l*cp+dp_l[k]; /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ t = (float)n; t1 = (((z_h + z_l) + dp_h[k]) + t); GET_FLOAT_WORD(is, t1); SET_FLOAT_WORD(t1, is & 0xfffff000); t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); } /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ GET_FLOAT_WORD(is, y); SET_FLOAT_WORD(y1, is & 0xfffff000); p_l = (y-y1)*t1 + y*t2; p_h = y1*t1; z = p_l + p_h; GET_FLOAT_WORD(j, z); if (j > 0x43000000) /* if z > 128 */ return sn*huge*huge; /* overflow */ else if (j == 0x43000000) { /* if z == 128 */ if (p_l + ovt > z - p_h) return sn*huge*huge; /* overflow */ } else if ((j&0x7fffffff) > 0x43160000) /* z < -150 */ // FIXME: check should be (uint32_t)j > 0xc3160000 return sn*tiny*tiny; /* underflow */ else if (j == 0xc3160000) { /* z == -150 */ if (p_l <= z-p_h) return sn*tiny*tiny; /* underflow */ } /* * compute 2**(p_h+p_l) */ i = j & 0x7fffffff; k = (i>>23) - 0x7f; n = 0; if (i > 0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */ n = j + (0x00800000>>(k+1)); k = ((n&0x7fffffff)>>23) - 0x7f; /* new k for n */ SET_FLOAT_WORD(t, n & ~(0x007fffff>>k)); n = ((n&0x007fffff)|0x00800000)>>(23-k); if (j < 0) n = -n; p_h -= t; } t = p_l + p_h; GET_FLOAT_WORD(is, t); SET_FLOAT_WORD(t, is & 0xffff8000); u = t*lg2_h; v = (p_l-(t-p_h))*lg2 + t*lg2_l; z = u + v; w = v - (z - u); t = z*z; t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); r = (z*t1)/(t1-2.0f) - (w+z*w); z = 1.0f - (r - z); GET_FLOAT_WORD(j, z); j += n<<23; if ((j>>23) <= 0) /* subnormal output */ z = scalbnf(z, n); else SET_FLOAT_WORD(z, j); return sn*z; } /*****************************************************************************/ /*****************************************************************************/ // expf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/e_expf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ static const float half[2] = {0.5,-0.5}, ln2hi = 6.9314575195e-1f, /* 0x3f317200 */ ln2lo = 1.4286067653e-6f, /* 0x35bfbe8e */ invln2 = 1.4426950216e+0f, /* 0x3fb8aa3b */ /* * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]: * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74 */ expf_P1 = 1.6666625440e-1f, /* 0xaaaa8f.0p-26 */ expf_P2 = -2.7667332906e-3f; /* -0xb55215.0p-32 */ float expf(float x) { float_t hi, lo, c, xx, y; int k, sign; uint32_t hx; GET_FLOAT_WORD(hx, x); sign = hx >> 31; /* sign bit of x */ hx &= 0x7fffffff; /* high word of |x| */ /* special cases */ if (hx >= 0x42aeac50) { /* if |x| >= -87.33655f or NaN */ if (hx >= 0x42b17218 && !sign) { /* x >= 88.722839f */ /* overflow */ x *= 0x1p127f; return x; } if (sign) { /* underflow */ FORCE_EVAL(-0x1p-149f/x); if (hx >= 0x42cff1b5) /* x <= -103.972084f */ return 0; } } /* argument reduction */ if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ if (hx > 0x3f851592) /* if |x| > 1.5 ln2 */ k = invln2*x + half[sign]; else k = 1 - sign - sign; hi = x - k*ln2hi; /* k*ln2hi is exact here */ lo = k*ln2lo; x = hi - lo; } else if (hx > 0x39000000) { /* |x| > 2**-14 */ k = 0; hi = x; lo = 0; } else { /* raise inexact */ FORCE_EVAL(0x1p127f + x); return 1 + x; } /* x is now in primary range */ xx = x*x; c = x - xx*(expf_P1+xx*expf_P2); y = 1 + (x*c/(2-c) - lo + hi); if (k == 0) return y; return scalbnf(y, k); } /*****************************************************************************/ /*****************************************************************************/ // expm1f from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/s_expm1f.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ static const float o_threshold = 8.8721679688e+01, /* 0x42b17180 */ ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ //invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */ /* * Domain [-0.34568, 0.34568], range ~[-6.694e-10, 6.696e-10]: * |6 / x * (1 + 2 * (1 / (exp(x) - 1) - 1 / x)) - q(x)| < 2**-30.04 * Scaled coefficients: Qn_here = 2**n * Qn_for_q (see s_expm1.c): */ Q1 = -3.3333212137e-2, /* -0x888868.0p-28 */ Q2 = 1.5807170421e-3; /* 0xcf3010.0p-33 */ float expm1f(float x) { float_t y,hi,lo,c,t,e,hxs,hfx,r1,twopk; union {float f; uint32_t i;} u = {x}; uint32_t hx = u.i & 0x7fffffff; int k, sign = u.i >> 31; /* filter out huge and non-finite argument */ if (hx >= 0x4195b844) { /* if |x|>=27*ln2 */ if (hx > 0x7f800000) /* NaN */ return x; if (sign) return -1; if (x > o_threshold) { x *= 0x1p127f; return x; } } /* argument reduction */ if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ if (hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ if (!sign) { hi = x - ln2_hi; lo = ln2_lo; k = 1; } else { hi = x + ln2_hi; lo = -ln2_lo; k = -1; } } else { k = invln2*x + (sign ? -0.5f : 0.5f); t = k; hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ lo = t*ln2_lo; } x = hi-lo; c = (hi-x)-lo; } else if (hx < 0x33000000) { /* when |x|<2**-25, return x */ if (hx < 0x00800000) FORCE_EVAL(x*x); return x; } else k = 0; /* x is now in primary range */ hfx = 0.5f*x; hxs = x*hfx; r1 = 1.0f+hxs*(Q1+hxs*Q2); t = 3.0f - r1*hfx; e = hxs*((r1-t)/(6.0f - x*t)); if (k == 0) /* c is 0 */ return x - (x*e-hxs); e = x*(e-c) - c; e -= hxs; /* exp(x) ~ 2^k (x_reduced - e + 1) */ if (k == -1) return 0.5f*(x-e) - 0.5f; if (k == 1) { if (x < -0.25f) return -2.0f*(e-(x+0.5f)); return 1.0f + 2.0f*(x-e); } u.i = (0x7f+k)<<23; /* 2^k */ twopk = u.f; if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */ y = x - e + 1.0f; if (k == 128) y = y*2.0f*0x1p127f; else y = y*twopk; return y - 1.0f; } u.i = (0x7f-k)<<23; /* 2^-k */ if (k < 23) y = (x-e+(1-u.f))*twopk; else y = (x-(e+u.f)+1)*twopk; return y; } /*****************************************************************************/ /*****************************************************************************/ // __expo2f from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */ static const int k = 235; static const float kln2 = 0x1.45c778p+7f; /* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */ float __expo2f(float x) { float scale; /* note that k is odd and scale*scale overflows */ SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23); /* exp(x - k ln2) * 2**(k-1) */ return expf(x - kln2) * scale * scale; } /*****************************************************************************/ /*****************************************************************************/ // logf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ /* origin: FreeBSD /usr/src/lib/msun/src/e_logf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ static const float /* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ float logf(float x) { union {float f; uint32_t i;} u = {x}; float_t hfsq,f,s,z,R,w,t1,t2,dk; uint32_t ix; int k; ix = u.i; k = 0; if (ix < 0x00800000 || ix>>31) { /* x < 2**-126 */ if (ix<<1 == 0) return -1/(x*x); /* log(+-0)=-inf */ if (ix>>31) return (x-x)/0.0f; /* log(-#) = NaN */ /* subnormal number, scale up x */ k -= 25; x *= 0x1p25f; u.f = x; ix = u.i; } else if (ix >= 0x7f800000) { return x; } else if (ix == 0x3f800000) return 0; /* reduce x into [sqrt(2)/2, sqrt(2)] */ ix += 0x3f800000 - 0x3f3504f3; k += (int)(ix>>23) - 0x7f; ix = (ix&0x007fffff) + 0x3f3504f3; u.i = ix; x = u.f; f = x - 1.0f; s = f/(2.0f + f); z = s*s; w = z*z; t1= w*(Lg2+w*Lg4); t2= z*(Lg1+w*Lg3); R = t2 + t1; hfsq = 0.5f*f*f; dk = k; return s*(hfsq+R) + dk*ln2_lo - hfsq + f + dk*ln2_hi; } /*****************************************************************************/ /*****************************************************************************/ // coshf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ float coshf(float x) { union {float f; uint32_t i;} u = {.f = x}; uint32_t w; float t; /* |x| */ u.i &= 0x7fffffff; x = u.f; w = u.i; /* |x| < log(2) */ if (w < 0x3f317217) { if (w < 0x3f800000 - (12<<23)) { FORCE_EVAL(x + 0x1p120f); return 1; } t = expm1f(x); return 1 + t*t/(2*(1+t)); } /* |x| < log(FLT_MAX) */ if (w < 0x42b17217) { t = expf(x); return 0.5f*(t + 1/t); } /* |x| > log(FLT_MAX) or nan */ t = __expo2f(x); return t; } /*****************************************************************************/ /*****************************************************************************/ // sinhf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ float sinhf(float x) { union {float f; uint32_t i;} u = {.f = x}; uint32_t w; float t, h, absx; h = 0.5; if (u.i >> 31) h = -h; /* |x| */ u.i &= 0x7fffffff; absx = u.f; w = u.i; /* |x| < log(FLT_MAX) */ if (w < 0x42b17217) { t = expm1f(absx); if (w < 0x3f800000) { if (w < 0x3f800000 - (12<<23)) return x; return h*(2*t - t*t/(t+1)); } return h*(t + t/(t+1)); } /* |x| > logf(FLT_MAX) or nan */ t = 2*h*__expo2f(absx); return t; } /*****************************************************************************/ /*****************************************************************************/ // ceilf, floorf and truncf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ float ceilf(float x) { union {float f; uint32_t i;} u = {x}; int e = (int)(u.i >> 23 & 0xff) - 0x7f; uint32_t m; if (e >= 23) return x; if (e >= 0) { m = 0x007fffff >> e; if ((u.i & m) == 0) return x; FORCE_EVAL(x + 0x1p120f); if (u.i >> 31 == 0) u.i += m; u.i &= ~m; } else { FORCE_EVAL(x + 0x1p120f); if (u.i >> 31) u.f = -0.0; else if (u.i << 1) u.f = 1.0; } return u.f; } float floorf(float x) { union {float f; uint32_t i;} u = {x}; int e = (int)(u.i >> 23 & 0xff) - 0x7f; uint32_t m; if (e >= 23) return x; if (e >= 0) { m = 0x007fffff >> e; if ((u.i & m) == 0) return x; FORCE_EVAL(x + 0x1p120f); if (u.i >> 31) u.i += m; u.i &= ~m; } else { FORCE_EVAL(x + 0x1p120f); if (u.i >> 31 == 0) u.i = 0; else if (u.i << 1) u.f = -1.0; } return u.f; } float truncf(float x) { union {float f; uint32_t i;} u = {x}; int e = (int)(u.i >> 23 & 0xff) - 0x7f + 9; uint32_t m; if (e >= 23 + 9) return x; if (e < 9) e = 1; m = -1U >> e; if ((u.i & m) == 0) return x; FORCE_EVAL(x + 0x1p120f); u.i &= ~m; return u.f; } micropython-1.12/lib/libm/nearbyintf.c000066400000000000000000000005411357706137100200200ustar00rootroot00000000000000// adapted from the rintf() function from musl-1.1.16 #include "libm.h" float nearbyintf(float x) { union {float f; uint32_t i;} u = {x}; int e = u.i>>23 & 0xff; int s = u.i>>31; float_t y; if (e >= 0x7f+23) return x; if (s) y = x - 0x1p23f + 0x1p23f; else y = x + 0x1p23f - 0x1p23f; if (y == 0) return s ? -0.0f : 0.0f; return y; } micropython-1.12/lib/libm/roundf.c000066400000000000000000000013721357706137100171570ustar00rootroot00000000000000/*****************************************************************************/ /*****************************************************************************/ // roundf from musl-0.9.15 /*****************************************************************************/ /*****************************************************************************/ #include "libm.h" float roundf(float x) { union {float f; uint32_t i;} u = {x}; int e = u.i >> 23 & 0xff; float_t y; if (e >= 0x7f+23) return x; if (u.i >> 31) x = -x; if (e < 0x7f-1) { FORCE_EVAL(x + 0x1p23f); return 0*u.f; } y = (float)(x + 0x1p23f) - 0x1p23f - x; if (y > 0.5f) y = y + x - 1; else if (y <= -0.5f) y = y + x + 1; else y = y + x; if (u.i >> 31) y = -y; return y; } micropython-1.12/lib/libm/sf_cos.c000066400000000000000000000031131357706137100171310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* sf_cos.c -- float version of s_cos.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ float cosf(float x) #else float cosf(x) float x; #endif { float y[2],z=0.0; __int32_t n,ix; GET_FLOAT_WORD(ix,x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3f490fd8) return __kernel_cosf(x,z); /* cos(Inf or NaN) is NaN */ else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; /* argument reduction needed */ else { n = __ieee754_rem_pio2f(x,y); switch(n&3) { case 0: return __kernel_cosf(y[0],y[1]); case 1: return -__kernel_sinf(y[0],y[1],1); case 2: return -__kernel_cosf(y[0],y[1]); default: return __kernel_sinf(y[0],y[1],1); } } } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double cos(double x) #else double cos(x) double x; #endif { return (double) cosf((float) x); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm/sf_erf.c000066400000000000000000000164761357706137100171410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* sf_erf.c -- float version of s_erf.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #define __ieee754_expf expf #ifdef __v810__ #define const #endif #ifdef __STDC__ static const float #else static float #endif tiny = 1e-30, half= 5.0000000000e-01, /* 0x3F000000 */ one = 1.0000000000e+00, /* 0x3F800000 */ two = 2.0000000000e+00, /* 0x40000000 */ /* c = (subfloat)0.84506291151 */ erx = 8.4506291151e-01, /* 0x3f58560b */ /* * Coefficients for approximation to erf on [0,0.84375] */ efx = 1.2837916613e-01, /* 0x3e0375d4 */ efx8= 1.0270333290e+00, /* 0x3f8375d4 */ pp0 = 1.2837916613e-01, /* 0x3e0375d4 */ pp1 = -3.2504209876e-01, /* 0xbea66beb */ pp2 = -2.8481749818e-02, /* 0xbce9528f */ pp3 = -5.7702702470e-03, /* 0xbbbd1489 */ pp4 = -2.3763017452e-05, /* 0xb7c756b1 */ qq1 = 3.9791721106e-01, /* 0x3ecbbbce */ qq2 = 6.5022252500e-02, /* 0x3d852a63 */ qq3 = 5.0813062117e-03, /* 0x3ba68116 */ qq4 = 1.3249473704e-04, /* 0x390aee49 */ qq5 = -3.9602282413e-06, /* 0xb684e21a */ /* * Coefficients for approximation to erf in [0.84375,1.25] */ pa0 = -2.3621185683e-03, /* 0xbb1acdc6 */ pa1 = 4.1485610604e-01, /* 0x3ed46805 */ pa2 = -3.7220788002e-01, /* 0xbebe9208 */ pa3 = 3.1834661961e-01, /* 0x3ea2fe54 */ pa4 = -1.1089469492e-01, /* 0xbde31cc2 */ pa5 = 3.5478305072e-02, /* 0x3d1151b3 */ pa6 = -2.1663755178e-03, /* 0xbb0df9c0 */ qa1 = 1.0642088205e-01, /* 0x3dd9f331 */ qa2 = 5.4039794207e-01, /* 0x3f0a5785 */ qa3 = 7.1828655899e-02, /* 0x3d931ae7 */ qa4 = 1.2617121637e-01, /* 0x3e013307 */ qa5 = 1.3637083583e-02, /* 0x3c5f6e13 */ qa6 = 1.1984500103e-02, /* 0x3c445aa3 */ /* * Coefficients for approximation to erfc in [1.25,1/0.35] */ ra0 = -9.8649440333e-03, /* 0xbc21a093 */ ra1 = -6.9385856390e-01, /* 0xbf31a0b7 */ ra2 = -1.0558626175e+01, /* 0xc128f022 */ ra3 = -6.2375331879e+01, /* 0xc2798057 */ ra4 = -1.6239666748e+02, /* 0xc322658c */ ra5 = -1.8460508728e+02, /* 0xc3389ae7 */ ra6 = -8.1287437439e+01, /* 0xc2a2932b */ ra7 = -9.8143291473e+00, /* 0xc11d077e */ sa1 = 1.9651271820e+01, /* 0x419d35ce */ sa2 = 1.3765776062e+02, /* 0x4309a863 */ sa3 = 4.3456588745e+02, /* 0x43d9486f */ sa4 = 6.4538726807e+02, /* 0x442158c9 */ sa5 = 4.2900814819e+02, /* 0x43d6810b */ sa6 = 1.0863500214e+02, /* 0x42d9451f */ sa7 = 6.5702495575e+00, /* 0x40d23f7c */ sa8 = -6.0424413532e-02, /* 0xbd777f97 */ /* * Coefficients for approximation to erfc in [1/.35,28] */ rb0 = -9.8649431020e-03, /* 0xbc21a092 */ rb1 = -7.9928326607e-01, /* 0xbf4c9dd4 */ rb2 = -1.7757955551e+01, /* 0xc18e104b */ rb3 = -1.6063638306e+02, /* 0xc320a2ea */ rb4 = -6.3756646729e+02, /* 0xc41f6441 */ rb5 = -1.0250950928e+03, /* 0xc480230b */ rb6 = -4.8351919556e+02, /* 0xc3f1c275 */ sb1 = 3.0338060379e+01, /* 0x41f2b459 */ sb2 = 3.2579251099e+02, /* 0x43a2e571 */ sb3 = 1.5367296143e+03, /* 0x44c01759 */ sb4 = 3.1998581543e+03, /* 0x4547fdbb */ sb5 = 2.5530502930e+03, /* 0x451f90ce */ sb6 = 4.7452853394e+02, /* 0x43ed43a7 */ sb7 = -2.2440952301e+01; /* 0xc1b38712 */ #ifdef __STDC__ float erff(float x) #else float erff(x) float x; #endif { __int32_t hx,ix,i; float R,S,P,Q,s,y,z,r; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(!FLT_UWORD_IS_FINITE(ix)) { /* erf(nan)=nan */ i = ((__uint32_t)hx>>31)<<1; return (float)(1-i)+one/x; /* erf(+-inf)=+-1 */ } if(ix < 0x3f580000) { /* |x|<0.84375 */ if(ix < 0x31800000) { /* |x|<2**-28 */ if (ix < 0x04000000) /*avoid underflow */ return (float)0.125*((float)8.0*x+efx8*x); return x + efx*x; } z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); y = r/s; return x + x*y; } if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ s = fabsf(x)-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); if(hx>=0) return erx + P/Q; else return -erx - P/Q; } if (ix >= 0x40c00000) { /* inf>|x|>=6 */ if(hx>=0) return one-tiny; else return tiny-one; } x = fabsf(x); s = one/(x*x); if(ix< 0x4036DB6E) { /* |x| < 1/0.35 */ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( ra5+s*(ra6+s*ra7)))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( sa5+s*(sa6+s*(sa7+s*sa8))))))); } else { /* |x| >= 1/0.35 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( rb5+s*rb6))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( sb5+s*(sb6+s*sb7)))))); } GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(z,ix&0xfffff000); r = __ieee754_expf(-z*z-(float)0.5625)*__ieee754_expf((z-x)*(z+x)+R/S); if(hx>=0) return one-r/x; else return r/x-one; } #ifdef __STDC__ float erfcf(float x) #else float erfcf(x) float x; #endif { __int32_t hx,ix; float R,S,P,Q,s,y,z,r; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(!FLT_UWORD_IS_FINITE(ix)) { /* erfc(nan)=nan */ /* erfc(+-inf)=0,2 */ return (float)(((__uint32_t)hx>>31)<<1)+one/x; } if(ix < 0x3f580000) { /* |x|<0.84375 */ if(ix < 0x23800000) /* |x|<2**-56 */ return one-x; z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); y = r/s; if(hx < 0x3e800000) { /* x<1/4 */ return one-(x+x*y); } else { r = x*y; r += (x-half); return half - r ; } } if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ s = fabsf(x)-one; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); if(hx>=0) { z = one-erx; return z - P/Q; } else { z = erx+P/Q; return one+z; } } if (ix < 0x41e00000) { /* |x|<28 */ x = fabsf(x); s = one/(x*x); if(ix< 0x4036DB6D) { /* |x| < 1/.35 ~ 2.857143*/ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( ra5+s*(ra6+s*ra7)))))); S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( sa5+s*(sa6+s*(sa7+s*sa8))))))); } else { /* |x| >= 1/.35 ~ 2.857143 */ if(hx<0&&ix>=0x40c00000) return two-tiny;/* x < -6 */ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( rb5+s*rb6))))); S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( sb5+s*(sb6+s*sb7)))))); } GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(z,ix&0xfffff000); r = __ieee754_expf(-z*z-(float)0.5625)* __ieee754_expf((z-x)*(z+x)+R/S); if(hx>0) return r/x; else return two-r/x; } else { if(hx>0) return tiny*tiny; else return two-tiny; } } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double erf(double x) #else double erf(x) double x; #endif { return (double) erff((float) x); } #ifdef __STDC__ double erfc(double x) #else double erfc(x) double x; #endif { return (double) erfcf((float) x); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm/sf_frexp.c000066400000000000000000000031601357706137100174730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* sf_frexp.c -- float version of s_frexp.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ static const float #else static float #endif two25 = 3.3554432000e+07; /* 0x4c000000 */ #ifdef __STDC__ float frexpf(float x, int *eptr) #else float frexpf(x, eptr) float x; int *eptr; #endif { __int32_t hx, ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; *eptr = 0; if(!FLT_UWORD_IS_FINITE(ix)||FLT_UWORD_IS_ZERO(ix)) return x; /* 0,inf,nan */ if (FLT_UWORD_IS_SUBNORMAL(ix)) { /* subnormal */ x *= two25; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; *eptr = -25; } *eptr += (ix>>23)-126; hx = (hx&0x807fffff)|0x3f000000; SET_FLOAT_WORD(x,hx); return x; } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double frexp(double x, int *eptr) #else double frexp(x, eptr) double x; int *eptr; #endif { return (double) frexpf((float) x, eptr); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm/sf_ldexp.c000066400000000000000000000025051357706137100174650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* sf_ldexp.c -- float version of s_ldexp.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" //#include #ifdef __STDC__ float ldexpf(float value, int exp) #else float ldexpf(value, exp) float value; int exp; #endif { if(!isfinite(value)||value==(float)0.0) return value; value = scalbnf(value,exp); //if(!finitef(value)||value==(float)0.0) errno = ERANGE; return value; } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double ldexp(double value, int exp) #else double ldexp(value, exp) double value; int exp; #endif { return (double) ldexpf((float) value, exp); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm/sf_modf.c000066400000000000000000000036511357706137100173010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/common * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* sf_modf.c -- float version of s_modf.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ static const float one = 1.0; #else static float one = 1.0; #endif #ifdef __STDC__ float modff(float x, float *iptr) #else float modff(x, iptr) float x,*iptr; #endif { __int32_t i0,j0; __uint32_t i; GET_FLOAT_WORD(i0,x); j0 = ((i0>>23)&0xff)-0x7f; /* exponent of x */ if(j0<23) { /* integer part in x */ if(j0<0) { /* |x|<1 */ SET_FLOAT_WORD(*iptr,i0&0x80000000); /* *iptr = +-0 */ return x; } else { i = (0x007fffff)>>j0; if((i0&i)==0) { /* x is integral */ __uint32_t ix; *iptr = x; GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */ return x; } else { SET_FLOAT_WORD(*iptr,i0&(~i)); return x - *iptr; } } } else { /* no fraction part */ __uint32_t ix; *iptr = x*one; GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */ return x; } } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double modf(double x, double *iptr) #else double modf(x, iptr) double x,*iptr; #endif { return (double) modff((float) x, (float *) iptr); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm/sf_sin.c000066400000000000000000000031061357706137100171400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* sf_sin.c -- float version of s_sin.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ float sinf(float x) #else float sinf(x) float x; #endif { float y[2],z=0.0; __int32_t n,ix; GET_FLOAT_WORD(ix,x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0); /* sin(Inf or NaN) is NaN */ else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; /* argument reduction needed */ else { n = __ieee754_rem_pio2f(x,y); switch(n&3) { case 0: return __kernel_sinf(y[0],y[1],1); case 1: return __kernel_cosf(y[0],y[1]); case 2: return -__kernel_sinf(y[0],y[1],1); default: return -__kernel_cosf(y[0],y[1]); } } } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double sin(double x) #else double sin(x) double x; #endif { return (double) sinf((float) x); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm/sf_tan.c000066400000000000000000000027371357706137100171420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* sf_tan.c -- float version of s_tan.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #ifdef __STDC__ float tanf(float x) #else float tanf(x) float x; #endif { float y[2],z=0.0; __int32_t n,ix; GET_FLOAT_WORD(ix,x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3f490fda) return __kernel_tanf(x,z,1); /* tan(Inf or NaN) is NaN */ else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; /* NaN */ /* argument reduction needed */ else { n = __ieee754_rem_pio2f(x,y); return __kernel_tanf(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even -1 -- n odd */ } } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double tan(double x) #else double tan(x) double x; #endif { return (double) tanf((float) x); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm/thumb_vfp_sqrtf.c000066400000000000000000000003641357706137100210730ustar00rootroot00000000000000// an implementation of sqrtf for Thumb using hardware VFP instructions #include float sqrtf(float x) { asm volatile ( "vsqrt.f32 %[r], %[x]\n" : [r] "=t" (x) : [x] "t" (x)); return x; } micropython-1.12/lib/libm/wf_lgamma.c000066400000000000000000000044501357706137100176140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* wf_lgamma.c -- float version of w_lgamma.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ #include "fdlibm.h" #define _IEEE_LIBM 1 //#include //#include #ifdef __STDC__ float lgammaf(float x) #else float lgammaf(x) float x; #endif { #ifdef _IEEE_LIBM int sign; return __ieee754_lgammaf_r(x,&sign); #else float y; struct exception exc; y = __ieee754_lgammaf_r(x,&(_REENT_SIGNGAM(_REENT))); if(_LIB_VERSION == _IEEE_) return y; if(!finitef(y)&&finitef(x)) { #ifndef HUGE_VAL #define HUGE_VAL inf double inf = 0.0; SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */ #endif exc.name = "lgammaf"; exc.err = 0; exc.arg1 = exc.arg2 = (double)x; if (_LIB_VERSION == _SVID_) exc.retval = HUGE; else exc.retval = HUGE_VAL; if(floorf(x)==x&&x<=(float)0.0) { /* lgammaf(-integer) */ exc.type = SING; if (_LIB_VERSION == _POSIX_) errno = EDOM; else if (!matherr(&exc)) { errno = EDOM; } } else { /* lgammaf(finite) overflow */ exc.type = OVERFLOW; if (_LIB_VERSION == _POSIX_) errno = ERANGE; else if (!matherr(&exc)) { errno = ERANGE; } } if (exc.err != 0) errno = exc.err; return (float)exc.retval; } else return y; #endif } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double lgamma(double x) #else double lgamma(x) double x; #endif { return (double) lgammaf((float) x); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm/wf_tgamma.c000066400000000000000000000032771357706137100176320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * These math functions are taken from newlib-nano-2, the newlib/libm/math * directory, available from https://github.com/32bitmicro/newlib-nano-2. * * Appropriate copyright headers are reproduced below. */ /* w_gammaf.c -- float version of w_gamma.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "math.h" #include "fdlibm.h" #define _IEEE_LIBM 1 #ifdef __STDC__ float tgammaf(float x) #else float tgammaf(x) float x; #endif { float y; int local_signgam; if (!isfinite(x)) { /* special cases: tgammaf(nan)=nan, tgammaf(inf)=inf, tgammaf(-inf)=nan */ return x + INFINITY; } y = expf(__ieee754_lgammaf_r(x,&local_signgam)); if (local_signgam < 0) y = -y; #ifdef _IEEE_LIBM return y; #else if(_LIB_VERSION == _IEEE_) return y; if(!finitef(y)&&finitef(x)) { if(floorf(x)==x&&x<=(float)0.0) /* tgammaf pole */ return (float)__kernel_standard((double)x,(double)x,141); else /* tgammaf overflow */ return (float)__kernel_standard((double)x,(double)x,140); } return y; #endif } #ifdef _DOUBLE_IS_32BITS #ifdef __STDC__ double tgamma(double x) #else double tgamma(x) double x; #endif { return (double) tgammaf((float) x); } #endif /* defined(_DOUBLE_IS_32BITS) */ micropython-1.12/lib/libm_dbl/000077500000000000000000000000001357706137100163345ustar00rootroot00000000000000micropython-1.12/lib/libm_dbl/README000066400000000000000000000033211357706137100172130ustar00rootroot00000000000000This directory contains source code for the standard double-precision math functions. The files lgamma.c, log10.c and tanh.c are too small to have a meaningful copyright or license. The file copysign.c contains a double version of the float copysignf provided in libm/math.c for use in DEBUG builds where the standard library copy is not available. The rest of the files in this directory are copied from the musl library, v1.1.16, and, unless otherwise stated in the individual file, have the following copyright and MIT license: ---------------------------------------------------------------------- Copyright © 2005-2014 Rich Felker, et al. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------------------- micropython-1.12/lib/libm_dbl/__cos.c000066400000000000000000000055041357706137100175660ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * __cos( x, y ) * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * * Algorithm * 1. Since cos(-x) = cos(x), we need only to consider positive x. * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. * 3. cos(x) is approximated by a polynomial of degree 14 on * [0,pi/4] * 4 14 * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x * where the remez error is * * | 2 4 6 8 10 12 14 | -58 * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 * | | * * 4 6 8 10 12 14 * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then * cos(x) ~ 1 - x*x/2 + r * since cos(x+y) ~ cos(x) - sin(x)*y * ~ cos(x) - x*y, * a correction term is necessary in cos(x) and hence * cos(x+y) = 1 - (x*x/2 - (r - x*y)) * For better accuracy, rearrange to * cos(x+y) ~ w + (tmp + (r-x*y)) * where w = 1 - x*x/2 and tmp is a tiny correction term * (1 - x*x/2 == w + tmp exactly in infinite precision). * The exactness of w + tmp in infinite precision depends on w * and tmp having the same precision as x. If they have extra * precision due to compiler bugs, then the extra precision is * only good provided it is retained in all terms of the final * expression for cos(). Retention happens in all cases tested * under FreeBSD, so don't pessimize things by forcibly clipping * any extra precision in w. */ #include "libm.h" static const double C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ double __cos(double x, double y) { double_t hz,z,r,w; z = x*x; w = z*z; r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)); hz = 0.5*z; w = 1.0-hz; return w + (((1.0-w)-hz) + (z*r-x*y)); } micropython-1.12/lib/libm_dbl/__expo2.c000066400000000000000000000007451357706137100200410ustar00rootroot00000000000000#include "libm.h" /* k is such that k*ln2 has minimal relative error and x - kln2 > log(DBL_MIN) */ static const int k = 2043; static const double kln2 = 0x1.62066151add8bp+10; /* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */ double __expo2(double x) { double scale; /* note that k is odd and scale*scale overflows */ INSERT_WORDS(scale, (uint32_t)(0x3ff + k/2) << 20, 0); /* exp(x - k ln2) * 2**(k-1) */ return exp(x - kln2) * scale * scale; } micropython-1.12/lib/libm_dbl/__fpclassify.c000066400000000000000000000004031357706137100211360ustar00rootroot00000000000000#include #include int __fpclassifyd(double x) { union {double f; uint64_t i;} u = {x}; int e = u.i>>52 & 0x7ff; if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; if (e==0x7ff) return u.i<<12 ? FP_NAN : FP_INFINITE; return FP_NORMAL; } micropython-1.12/lib/libm_dbl/__rem_pio2.c000066400000000000000000000105721357706137100205170ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * * Optimized by Bruce D. Evans. */ /* __rem_pio2(x,y) * * return the remainder of x rem pi/2 in y[0]+y[1] * use __rem_pio2_large() for large x */ #include "libm.h" #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON #endif /* * invpio2: 53 bits of 2/pi * pio2_1: first 33 bit of pi/2 * pio2_1t: pi/2 - pio2_1 * pio2_2: second 33 bit of pi/2 * pio2_2t: pi/2 - (pio2_1+pio2_2) * pio2_3: third 33 bit of pi/2 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) */ static const double toint = 1.5/EPS, invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ /* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ int __rem_pio2(double x, double *y) { union {double f; uint64_t i;} u = {x}; double_t z,w,t,r,fn; double tx[3],ty[2]; uint32_t ix; int sign, n, ex, ey, i; sign = u.i>>63; ix = u.i>>32 & 0x7fffffff; if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ goto medium; /* cancellation -- use medium case */ if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ if (!sign) { z = x - pio2_1; /* one round good to 85 bits */ y[0] = z - pio2_1t; y[1] = (z-y[0]) - pio2_1t; return 1; } else { z = x + pio2_1; y[0] = z + pio2_1t; y[1] = (z-y[0]) + pio2_1t; return -1; } } else { if (!sign) { z = x - 2*pio2_1; y[0] = z - 2*pio2_1t; y[1] = (z-y[0]) - 2*pio2_1t; return 2; } else { z = x + 2*pio2_1; y[0] = z + 2*pio2_1t; y[1] = (z-y[0]) + 2*pio2_1t; return -2; } } } if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ goto medium; if (!sign) { z = x - 3*pio2_1; y[0] = z - 3*pio2_1t; y[1] = (z-y[0]) - 3*pio2_1t; return 3; } else { z = x + 3*pio2_1; y[0] = z + 3*pio2_1t; y[1] = (z-y[0]) + 3*pio2_1t; return -3; } } else { if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ goto medium; if (!sign) { z = x - 4*pio2_1; y[0] = z - 4*pio2_1t; y[1] = (z-y[0]) - 4*pio2_1t; return 4; } else { z = x + 4*pio2_1; y[0] = z + 4*pio2_1t; y[1] = (z-y[0]) + 4*pio2_1t; return -4; } } } if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ medium: /* rint(x/(pi/2)), Assume round-to-nearest. */ fn = (double_t)x*invpio2 + toint - toint; n = (int32_t)fn; r = x - fn*pio2_1; w = fn*pio2_1t; /* 1st round, good to 85 bits */ y[0] = r - w; u.f = y[0]; ey = u.i>>52 & 0x7ff; ex = ix>>20; if (ex - ey > 16) { /* 2nd round, good to 118 bits */ t = r; w = fn*pio2_2; r = t - w; w = fn*pio2_2t - ((t-r)-w); y[0] = r - w; u.f = y[0]; ey = u.i>>52 & 0x7ff; if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */ t = r; w = fn*pio2_3; r = t - w; w = fn*pio2_3t - ((t-r)-w); y[0] = r - w; } } y[1] = (r - y[0]) - w; return n; } /* * all other (large) arguments */ if (ix >= 0x7ff00000) { /* x is inf or NaN */ y[0] = y[1] = x - x; return 0; } /* set z = scalbn(|x|,-ilogb(x)+23) */ u.f = x; u.i &= (uint64_t)-1>>12; u.i |= (uint64_t)(0x3ff + 23)<<52; z = u.f; for (i=0; i < 2; i++) { tx[i] = (double)(int32_t)z; z = (z-tx[i])*0x1p24; } tx[i] = z; /* skip zero terms, first term is non-zero */ while (tx[i] == 0.0) i--; n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1); if (sign) { y[0] = -ty[0]; y[1] = -ty[1]; return -n; } y[0] = ty[0]; y[1] = ty[1]; return n; } micropython-1.12/lib/libm_dbl/__rem_pio2_large.c000066400000000000000000000400301357706137100216610ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* * __rem_pio2_large(x,y,e0,nx,prec) * double x[],y[]; int e0,nx,prec; * * __rem_pio2_large return the last three digits of N with * y = x - N*pi/2 * so that |y| < pi/2. * * The method is to compute the integer (mod 8) and fraction parts of * (2/pi)*x without doing the full multiplication. In general we * skip the part of the product that are known to be a huge integer ( * more accurately, = 0 mod 8 ). Thus the number of operations are * independent of the exponent of the input. * * (2/pi) is represented by an array of 24-bit integers in ipio2[]. * * Input parameters: * x[] The input value (must be positive) is broken into nx * pieces of 24-bit integers in double precision format. * x[i] will be the i-th 24 bit of x. The scaled exponent * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 * match x's up to 24 bits. * * Example of breaking a double positive z into x[0]+x[1]+x[2]: * e0 = ilogb(z)-23 * z = scalbn(z,-e0) * for i = 0,1,2 * x[i] = floor(z) * z = (z-x[i])*2**24 * * * y[] ouput result in an array of double precision numbers. * The dimension of y[] is: * 24-bit precision 1 * 53-bit precision 2 * 64-bit precision 2 * 113-bit precision 3 * The actual value is the sum of them. Thus for 113-bit * precison, one may have to do something like: * * long double t,w,r_head, r_tail; * t = (long double)y[2] + (long double)y[1]; * w = (long double)y[0]; * r_head = t+w; * r_tail = w - (r_head - t); * * e0 The exponent of x[0]. Must be <= 16360 or you need to * expand the ipio2 table. * * nx dimension of x[] * * prec an integer indicating the precision: * 0 24 bits (single) * 1 53 bits (double) * 2 64 bits (extended) * 3 113 bits (quad) * * External function: * double scalbn(), floor(); * * * Here is the description of some local variables: * * jk jk+1 is the initial number of terms of ipio2[] needed * in the computation. The minimum and recommended value * for jk is 3,4,4,6 for single, double, extended, and quad. * jk+1 must be 2 larger than you might expect so that our * recomputation test works. (Up to 24 bits in the integer * part (the 24 bits of it that we compute) and 23 bits in * the fraction part may be lost to cancelation before we * recompute.) * * jz local integer variable indicating the number of * terms of ipio2[] used. * * jx nx - 1 * * jv index for pointing to the suitable ipio2[] for the * computation. In general, we want * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 * is an integer. Thus * e0-3-24*jv >= 0 or (e0-3)/24 >= jv * Hence jv = max(0,(e0-3)/24). * * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. * * q[] double array with integral value, representing the * 24-bits chunk of the product of x and 2/pi. * * q0 the corresponding exponent of q[0]. Note that the * exponent for q[i] would be q0-24*i. * * PIo2[] double precision array, obtained by cutting pi/2 * into 24 bits chunks. * * f[] ipio2[] in floating point * * iq[] integer array by breaking up q[] in 24-bits chunk. * * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] * * ih integer. If >0 it indicates q[] is >= 0.5, hence * it also indicates the *sign* of the result. * */ /* * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "libm.h" static const int init_jk[] = {3,4,4,6}; /* initial value for jk */ /* * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi * * integer array, contains the (24*i)-th to (24*i+23)-th * bit of 2/pi after binary point. The corresponding * floating value is * * ipio2[i] * 2^(-24(i+1)). * * NB: This table must have at least (e0-3)/24 + jk terms. * For quad precision (e0 <= 16360, jk = 6), this is 686. */ static const int32_t ipio2[] = { 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, #if LDBL_MAX_EXP > 1024 0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6, 0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2, 0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35, 0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30, 0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C, 0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4, 0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770, 0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7, 0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19, 0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522, 0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16, 0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6, 0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E, 0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48, 0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3, 0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF, 0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55, 0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612, 0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929, 0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC, 0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B, 0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C, 0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4, 0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB, 0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC, 0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C, 0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F, 0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5, 0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437, 0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B, 0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA, 0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD, 0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3, 0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3, 0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717, 0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F, 0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61, 0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB, 0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51, 0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0, 0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C, 0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6, 0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC, 0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED, 0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328, 0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D, 0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0, 0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B, 0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4, 0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3, 0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F, 0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD, 0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B, 0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4, 0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761, 0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31, 0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30, 0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262, 0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E, 0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1, 0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C, 0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4, 0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08, 0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196, 0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9, 0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4, 0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC, 0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C, 0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0, 0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C, 0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0, 0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC, 0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22, 0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893, 0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7, 0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5, 0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F, 0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4, 0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF, 0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B, 0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2, 0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138, 0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E, 0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569, 0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34, 0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9, 0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D, 0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F, 0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855, 0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569, 0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B, 0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE, 0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41, 0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49, 0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F, 0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110, 0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8, 0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365, 0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A, 0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270, 0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5, 0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616, 0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B, 0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0, #endif }; static const double PIo2[] = { 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ }; int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec) { int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; double z,fw,f[20],fq[20],q[20]; /* initialize jk*/ jk = init_jk[prec]; jp = jk; /* determine jx,jv,q0, note that 3>q0 */ jx = nx-1; jv = (e0-3)/24; if(jv<0) jv=0; q0 = e0-24*(jv+1); /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ j = jv-jx; m = jx+jk; for (i=0; i<=m; i++,j++) f[i] = j<0 ? 0.0 : (double)ipio2[j]; /* compute q[0],q[1],...q[jk] */ for (i=0; i<=jk; i++) { for (j=0,fw=0.0; j<=jx; j++) fw += x[j]*f[jx+i-j]; q[i] = fw; } jz = jk; recompute: /* distill q[] into iq[] reversingly */ for (i=0,j=jz,z=q[jz]; j>0; i++,j--) { fw = (double)(int32_t)(0x1p-24*z); iq[i] = (int32_t)(z - 0x1p24*fw); z = q[j-1]+fw; } /* compute n */ z = scalbn(z,q0); /* actual value of z */ z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ n = (int32_t)z; z -= (double)n; ih = 0; if (q0 > 0) { /* need iq[jz-1] to determine n */ i = iq[jz-1]>>(24-q0); n += i; iq[jz-1] -= i<<(24-q0); ih = iq[jz-1]>>(23-q0); } else if (q0 == 0) ih = iq[jz-1]>>23; else if (z >= 0.5) ih = 2; if (ih > 0) { /* q > 0.5 */ n += 1; carry = 0; for (i=0; i 0) { /* rare case: chance is 1 in 12 */ switch(q0) { case 1: iq[jz-1] &= 0x7fffff; break; case 2: iq[jz-1] &= 0x3fffff; break; } } if (ih == 2) { z = 1.0 - z; if (carry != 0) z -= scalbn(1.0,q0); } } /* check if recomputation is needed */ if (z == 0.0) { j = 0; for (i=jz-1; i>=jk; i--) j |= iq[i]; if (j == 0) { /* need recomputation */ for (k=1; iq[jk-k]==0; k++); /* k = no. of terms needed */ for (i=jz+1; i<=jz+k; i++) { /* add q[jz+1] to q[jz+k] */ f[jx+i] = (double)ipio2[jv+i]; for (j=0,fw=0.0; j<=jx; j++) fw += x[j]*f[jx+i-j]; q[i] = fw; } jz += k; goto recompute; } } /* chop off zero terms */ if (z == 0.0) { jz -= 1; q0 -= 24; while (iq[jz] == 0) { jz--; q0 -= 24; } } else { /* break z into 24-bit if necessary */ z = scalbn(z,-q0); if (z >= 0x1p24) { fw = (double)(int32_t)(0x1p-24*z); iq[jz] = (int32_t)(z - 0x1p24*fw); jz += 1; q0 += 24; iq[jz] = (int32_t)fw; } else iq[jz] = (int32_t)z; } /* convert integer "bit" chunk to floating-point value */ fw = scalbn(1.0,q0); for (i=jz; i>=0; i--) { q[i] = fw*(double)iq[i]; fw *= 0x1p-24; } /* compute PIo2[0,...,jp]*q[jz,...,0] */ for(i=jz; i>=0; i--) { for (fw=0.0,k=0; k<=jp && k<=jz-i; k++) fw += PIo2[k]*q[i+k]; fq[jz-i] = fw; } /* compress fq[] into y[] */ switch(prec) { case 0: fw = 0.0; for (i=jz; i>=0; i--) fw += fq[i]; y[0] = ih==0 ? fw : -fw; break; case 1: case 2: fw = 0.0; for (i=jz; i>=0; i--) fw += fq[i]; // TODO: drop excess precision here once double_t is used fw = (double)fw; y[0] = ih==0 ? fw : -fw; fw = fq[0]-fw; for (i=1; i<=jz; i++) fw += fq[i]; y[1] = ih==0 ? fw : -fw; break; case 3: /* painful */ for (i=jz; i>0; i--) { fw = fq[i-1]+fq[i]; fq[i] += fq[i-1]-fw; fq[i-1] = fw; } for (i=jz; i>1; i--) { fw = fq[i-1]+fq[i]; fq[i] += fq[i-1]-fw; fq[i-1] = fw; } for (fw=0.0,i=jz; i>=2; i--) fw += fq[i]; if (ih==0) { y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; } else { y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; } } return n&7; } micropython-1.12/lib/libm_dbl/__signbit.c000066400000000000000000000001641357706137100204360ustar00rootroot00000000000000#include "libm.h" int __signbitd(double x) { union { double d; uint64_t i; } y = { x }; return y.i>>63; } micropython-1.12/lib/libm_dbl/__sin.c000066400000000000000000000044741357706137100176000ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __sin( x, y, iy) * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). * * Algorithm * 1. Since sin(-x) = -sin(x), we need only to consider positive x. * 2. Callers must return sin(-0) = -0 without calling here since our * odd polynomial is not evaluated in a way that preserves -0. * Callers may do the optimization sin(x) ~ x for tiny x. * 3. sin(x) is approximated by a polynomial of degree 13 on * [0,pi/4] * 3 13 * sin(x) ~ x + S1*x + ... + S6*x * where * * |sin(x) 2 4 6 8 10 12 | -58 * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 * | x | * * 4. sin(x+y) = sin(x) + sin'(x')*y * ~ sin(x) + (1-x*x/2)*y * For better accuracy, let * 3 2 2 2 2 * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) * then 3 2 * sin(x) = x + (S1*x + (x *(r-y/2)+y)) */ #include "libm.h" static const double S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ double __sin(double x, double y, int iy) { double_t z,r,v,w; z = x*x; w = z*z; r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6); v = z*x; if (iy == 0) return x + v*(S1 + z*r); else return x - ((z*(0.5*y - v*r) - y) - v*S1); } micropython-1.12/lib/libm_dbl/__tan.c000066400000000000000000000075731357706137100175740ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/k_tan.c */ /* * ==================================================== * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* __tan( x, y, k ) * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 * Input x is assumed to be bounded by ~pi/4 in magnitude. * Input y is the tail of x. * Input odd indicates whether tan (if odd = 0) or -1/tan (if odd = 1) is returned. * * Algorithm * 1. Since tan(-x) = -tan(x), we need only to consider positive x. * 2. Callers must return tan(-0) = -0 without calling here since our * odd polynomial is not evaluated in a way that preserves -0. * Callers may do the optimization tan(x) ~ x for tiny x. * 3. tan(x) is approximated by a odd polynomial of degree 27 on * [0,0.67434] * 3 27 * tan(x) ~ x + T1*x + ... + T13*x * where * * |tan(x) 2 4 26 | -59.2 * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 * | x | * * Note: tan(x+y) = tan(x) + tan'(x)*y * ~ tan(x) + (1+x*x)*y * Therefore, for better accuracy in computing tan(x+y), let * 3 2 2 2 2 * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) * then * 3 2 * tan(x+y) = x + (T1*x + (x *(r+y)+y)) * * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) */ #include "libm.h" static const double T[] = { 3.33333333333334091986e-01, /* 3FD55555, 55555563 */ 1.33333333333201242699e-01, /* 3FC11111, 1110FE7A */ 5.39682539762260521377e-02, /* 3FABA1BA, 1BB341FE */ 2.18694882948595424599e-02, /* 3F9664F4, 8406D637 */ 8.86323982359930005737e-03, /* 3F8226E3, E96E8493 */ 3.59207910759131235356e-03, /* 3F6D6D22, C9560328 */ 1.45620945432529025516e-03, /* 3F57DBC8, FEE08315 */ 5.88041240820264096874e-04, /* 3F4344D8, F2F26501 */ 2.46463134818469906812e-04, /* 3F3026F7, 1A8D1068 */ 7.81794442939557092300e-05, /* 3F147E88, A03792A6 */ 7.14072491382608190305e-05, /* 3F12B80F, 32F0A7E9 */ -1.85586374855275456654e-05, /* BEF375CB, DB605373 */ 2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */ }, pio4 = 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */ pio4lo = 3.06161699786838301793e-17; /* 3C81A626, 33145C07 */ double __tan(double x, double y, int odd) { double_t z, r, v, w, s, a; double w0, a0; uint32_t hx; int big, sign; GET_HIGH_WORD(hx,x); big = (hx&0x7fffffff) >= 0x3FE59428; /* |x| >= 0.6744 */ if (big) { sign = hx>>31; if (sign) { x = -x; y = -y; } x = (pio4 - x) + (pio4lo - y); y = 0.0; } z = x * x; w = z * z; /* * Break x^5*(T[1]+x^2*T[2]+...) into * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) */ r = T[1] + w*(T[3] + w*(T[5] + w*(T[7] + w*(T[9] + w*T[11])))); v = z*(T[2] + w*(T[4] + w*(T[6] + w*(T[8] + w*(T[10] + w*T[12]))))); s = z * x; r = y + z*(s*(r + v) + y) + s*T[0]; w = x + r; if (big) { s = 1 - 2*odd; v = s - 2.0 * (x + (r - w*w/(w + s))); return sign ? -v : v; } if (!odd) return w; /* -1.0/(x+r) has up to 2ulp error, so compute it accurately */ w0 = w; SET_LOW_WORD(w0, 0); v = r - (w0 - x); /* w0+v = r+x */ a0 = a = -1.0 / w; SET_LOW_WORD(a0, 0); return a0 + a*(1.0 + a0*w0 + a0*v); } micropython-1.12/lib/libm_dbl/acos.c000066400000000000000000000055651357706137100174400ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/e_acos.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* acos(x) * Method : * acos(x) = pi/2 - asin(x) * acos(-x) = pi/2 + asin(x) * For |x|<=0.5 * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) * For x>0.5 * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) * = 2asin(sqrt((1-x)/2)) * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) * = 2f + (2c + 2s*z*R(z)) * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term * for f so that f+c ~ sqrt(z). * For x<-0.5 * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) * * Special cases: * if x is NaN, return x itself; * if |x|>1, return NaN with invalid signal. * * Function needed: sqrt */ #include "libm.h" static const double pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ static double R(double z) { double_t p, q; p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4))); return p/q; } double acos(double x) { double z,w,s,c,df; uint32_t hx,ix; GET_HIGH_WORD(hx, x); ix = hx & 0x7fffffff; /* |x| >= 1 or nan */ if (ix >= 0x3ff00000) { uint32_t lx; GET_LOW_WORD(lx,x); if (((ix-0x3ff00000) | lx) == 0) { /* acos(1)=0, acos(-1)=pi */ if (hx >> 31) return 2*pio2_hi + 0x1p-120f; return 0; } return 0/(x-x); } /* |x| < 0.5 */ if (ix < 0x3fe00000) { if (ix <= 0x3c600000) /* |x| < 2**-57 */ return pio2_hi + 0x1p-120f; return pio2_hi - (x - (pio2_lo-x*R(x*x))); } /* x < -0.5 */ if (hx >> 31) { z = (1.0+x)*0.5; s = sqrt(z); w = R(z)*s-pio2_lo; return 2*(pio2_hi - (s+w)); } /* x > 0.5 */ z = (1.0-x)*0.5; s = sqrt(z); df = s; SET_LOW_WORD(df,0); c = (z-df*df)/(s+df); w = R(z)*s+c; return 2*(df+w); } micropython-1.12/lib/libm_dbl/acosh.c000066400000000000000000000010711357706137100175740ustar00rootroot00000000000000#include "libm.h" #if FLT_EVAL_METHOD==2 #undef sqrt #define sqrt sqrtl #endif /* acosh(x) = log(x + sqrt(x*x-1)) */ double acosh(double x) { union {double f; uint64_t i;} u = {.f = x}; unsigned e = u.i >> 52 & 0x7ff; /* x < 1 domain error is handled in the called functions */ if (e < 0x3ff + 1) /* |x| < 2, up to 2ulp error in [1,1.125] */ return log1p(x-1 + sqrt((x-1)*(x-1)+2*(x-1))); if (e < 0x3ff + 26) /* |x| < 0x1p26 */ return log(2*x - 1/(x+sqrt(x*x-1))); /* |x| >= 0x1p26 or nan */ return log(x) + 0.693147180559945309417232121458176568; } micropython-1.12/lib/libm_dbl/asin.c000066400000000000000000000065141357706137100174400ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/e_asin.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* asin(x) * Method : * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ... * we approximate asin(x) on [0,0.5] by * asin(x) = x + x*x^2*R(x^2) * where * R(x^2) is a rational approximation of (asin(x)-x)/x^3 * and its remez error is bounded by * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75) * * For x in [0.5,1] * asin(x) = pi/2-2*asin(sqrt((1-x)/2)) * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2; * then for x>0.98 * asin(x) = pi/2 - 2*(s+s*z*R(z)) * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) * For x<=0.98, let pio4_hi = pio2_hi/2, then * f = hi part of s; * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) * and * asin(x) = pi/2 - 2*(s+s*z*R(z)) * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) * * Special cases: * if x is NaN, return x itself; * if |x|>1, return NaN with invalid signal. * */ #include "libm.h" static const double pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ /* coefficients for R(x^2) */ pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ static double R(double z) { double_t p, q; p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4))); return p/q; } double asin(double x) { double z,r,s; uint32_t hx,ix; GET_HIGH_WORD(hx, x); ix = hx & 0x7fffffff; /* |x| >= 1 or nan */ if (ix >= 0x3ff00000) { uint32_t lx; GET_LOW_WORD(lx, x); if (((ix-0x3ff00000) | lx) == 0) /* asin(1) = +-pi/2 with inexact */ return x*pio2_hi + 0x1p-120f; return 0/(x-x); } /* |x| < 0.5 */ if (ix < 0x3fe00000) { /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */ if (ix < 0x3e500000 && ix >= 0x00100000) return x; return x + x*R(x*x); } /* 1 > |x| >= 0.5 */ z = (1 - fabs(x))*0.5; s = sqrt(z); r = R(z); if (ix >= 0x3fef3333) { /* if |x| > 0.975 */ x = pio2_hi-(2*(s+s*r)-pio2_lo); } else { double f,c; /* f+c = sqrt(z) */ f = s; SET_LOW_WORD(f,0); c = (z-f*f)/(s+f); x = 0.5*pio2_hi - (2*s*r - (pio2_lo-2*c) - (0.5*pio2_hi-2*f)); } if (hx >> 31) return -x; return x; } micropython-1.12/lib/libm_dbl/asinh.c000066400000000000000000000012711357706137100176030ustar00rootroot00000000000000#include "libm.h" /* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */ double asinh(double x) { union {double f; uint64_t i;} u = {.f = x}; unsigned e = u.i >> 52 & 0x7ff; unsigned s = u.i >> 63; /* |x| */ u.i &= (uint64_t)-1/2; x = u.f; if (e >= 0x3ff + 26) { /* |x| >= 0x1p26 or inf or nan */ x = log(x) + 0.693147180559945309417232121458176568; } else if (e >= 0x3ff + 1) { /* |x| >= 2 */ x = log(2*x + 1/(sqrt(x*x+1)+x)); } else if (e >= 0x3ff - 26) { /* |x| >= 0x1p-26, up to 1.6ulp error in [0.125,0.5] */ x = log1p(x + x*x/(sqrt(x*x+1)+1)); } else { /* |x| < 0x1p-26, raise inexact if x != 0 */ FORCE_EVAL(x + 0x1p120f); } return s ? -x : x; } micropython-1.12/lib/libm_dbl/atan.c000066400000000000000000000075361357706137100174360ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/s_atan.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* atan(x) * Method * 1. Reduce x to positive by atan(x) = -atan(-x). * 2. According to the integer k=4t+0.25 chopped, t=x, the argument * is further reduced to one of the following intervals and the * arctangent of t is evaluated by the corresponding formula: * * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "libm.h" static const double atanhi[] = { 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ }; static const double atanlo[] = { 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ }; static const double aT[] = { 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ }; double atan(double x) { double_t w,s1,s2,z; uint32_t ix,sign; int id; GET_HIGH_WORD(ix, x); sign = ix >> 31; ix &= 0x7fffffff; if (ix >= 0x44100000) { /* if |x| >= 2^66 */ if (isnan(x)) return x; z = atanhi[3] + 0x1p-120f; return sign ? -z : z; } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ if (ix < 0x3e400000) { /* |x| < 2^-27 */ if (ix < 0x00100000) /* raise underflow for subnormal x */ FORCE_EVAL((float)x); return x; } id = -1; } else { x = fabs(x); if (ix < 0x3ff30000) { /* |x| < 1.1875 */ if (ix < 0x3fe60000) { /* 7/16 <= |x| < 11/16 */ id = 0; x = (2.0*x-1.0)/(2.0+x); } else { /* 11/16 <= |x| < 19/16 */ id = 1; x = (x-1.0)/(x+1.0); } } else { if (ix < 0x40038000) { /* |x| < 2.4375 */ id = 2; x = (x-1.5)/(1.0+1.5*x); } else { /* 2.4375 <= |x| < 2^66 */ id = 3; x = -1.0/x; } } } /* end of argument reduction */ z = x*x; w = z*z; /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); if (id < 0) return x - x*(s1+s2); z = atanhi[id] - (x*(s1+s2) - atanlo[id] - x); return sign ? -z : z; } micropython-1.12/lib/libm_dbl/atan2.c000066400000000000000000000063251357706137100175130ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/e_atan2.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== * */ /* atan2(y,x) * Method : * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). * 2. Reduce x to positive by (if x and y are unexceptional): * ARG (x+iy) = arctan(y/x) ... if x > 0, * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, * * Special cases: * * ATAN2((anything), NaN ) is NaN; * ATAN2(NAN , (anything) ) is NaN; * ATAN2(+-0, +(anything but NaN)) is +-0 ; * ATAN2(+-0, -(anything but NaN)) is +-pi ; * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; * ATAN2(+-INF,+INF ) is +-pi/4 ; * ATAN2(+-INF,-INF ) is +-3pi/4; * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "libm.h" static const double pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ double atan2(double y, double x) { double z; uint32_t m,lx,ly,ix,iy; if (isnan(x) || isnan(y)) return x+y; EXTRACT_WORDS(ix, lx, x); EXTRACT_WORDS(iy, ly, y); if (((ix-0x3ff00000) | lx) == 0) /* x = 1.0 */ return atan(y); m = ((iy>>31)&1) | ((ix>>30)&2); /* 2*sign(x)+sign(y) */ ix = ix & 0x7fffffff; iy = iy & 0x7fffffff; /* when y = 0 */ if ((iy|ly) == 0) { switch(m) { case 0: case 1: return y; /* atan(+-0,+anything)=+-0 */ case 2: return pi; /* atan(+0,-anything) = pi */ case 3: return -pi; /* atan(-0,-anything) =-pi */ } } /* when x = 0 */ if ((ix|lx) == 0) return m&1 ? -pi/2 : pi/2; /* when x is INF */ if (ix == 0x7ff00000) { if (iy == 0x7ff00000) { switch(m) { case 0: return pi/4; /* atan(+INF,+INF) */ case 1: return -pi/4; /* atan(-INF,+INF) */ case 2: return 3*pi/4; /* atan(+INF,-INF) */ case 3: return -3*pi/4; /* atan(-INF,-INF) */ } } else { switch(m) { case 0: return 0.0; /* atan(+...,+INF) */ case 1: return -0.0; /* atan(-...,+INF) */ case 2: return pi; /* atan(+...,-INF) */ case 3: return -pi; /* atan(-...,-INF) */ } } } /* |y/x| > 0x1p64 */ if (ix+(64<<20) < iy || iy == 0x7ff00000) return m&1 ? -pi/2 : pi/2; /* z = atan(|y/x|) without spurious underflow */ if ((m&2) && iy+(64<<20) < ix) /* |y/x| < 0x1p-64, x<0 */ z = 0; else z = atan(fabs(y/x)); switch (m) { case 0: return z; /* atan(+,+) */ case 1: return -z; /* atan(-,+) */ case 2: return pi - (z-pi_lo); /* atan(+,-) */ default: /* case 3 */ return (z-pi_lo) - pi; /* atan(-,-) */ } } micropython-1.12/lib/libm_dbl/atanh.c000066400000000000000000000011011357706137100175640ustar00rootroot00000000000000#include "libm.h" /* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */ double atanh(double x) { union {double f; uint64_t i;} u = {.f = x}; unsigned e = u.i >> 52 & 0x7ff; unsigned s = u.i >> 63; double_t y; /* |x| */ u.i &= (uint64_t)-1/2; y = u.f; if (e < 0x3ff - 1) { if (e < 0x3ff - 32) { /* handle underflow */ if (e == 0) FORCE_EVAL((float)y); } else { /* |x| < 0.5, up to 1.7ulp error */ y = 0.5*log1p(2*y + 2*y*y/(1-y)); } } else { /* avoid overflow */ y = 0.5*log1p(2*(y/(1-y))); } return s ? -y : y; } micropython-1.12/lib/libm_dbl/ceil.c000066400000000000000000000012161357706137100174140ustar00rootroot00000000000000#include "libm.h" #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON #endif static const double_t toint = 1/EPS; double ceil(double x) { union {double f; uint64_t i;} u = {x}; int e = u.i >> 52 & 0x7ff; double_t y; if (e >= 0x3ff+52 || x == 0) return x; /* y = int(x) - x, where int(x) is an integer neighbor of x */ if (u.i >> 63) y = x - toint + toint - x; else y = x + toint - toint - x; /* special case because of non-nearest rounding modes */ if (e <= 0x3ff-1) { FORCE_EVAL(y); return u.i >> 63 ? -0.0 : 1; } if (y < 0) return x + y + 1; return x + y; } micropython-1.12/lib/libm_dbl/copysign.c000066400000000000000000000030361357706137100203350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "libm.h" #ifndef NDEBUG typedef union { double d; struct { uint64_t m : 52; uint64_t e : 11; uint64_t s : 1; }; } double_s_t; double copysign(double x, double y) { double_s_t dx={.d = x}; double_s_t dy={.d = y}; // copy sign bit; dx.s = dy.s; return dx.d; } #endif micropython-1.12/lib/libm_dbl/cos.c000066400000000000000000000040771357706137100172740ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/s_cos.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* cos(x) * Return cosine function of x. * * kernel function: * __sin ... sine function on [-pi/4,pi/4] * __cos ... cosine function on [-pi/4,pi/4] * __rem_pio2 ... argument reduction routine * * Method. * Let S,C and T denote the sin, cos and tan respectively on * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 * in [-pi/4 , +pi/4], and let n = k mod 4. * We have * * n sin(x) cos(x) tan(x) * ---------------------------------------------------------- * 0 S C T * 1 C -S -1/T * 2 -S -C T * 3 -C S -1/T * ---------------------------------------------------------- * * Special cases: * Let trig be any of sin, cos, or tan. * trig(+-INF) is NaN, with signals; * trig(NaN) is that NaN; * * Accuracy: * TRIG(x) returns trig(x) nearly rounded */ #include "libm.h" double cos(double x) { double y[2]; uint32_t ix; unsigned n; GET_HIGH_WORD(ix, x); ix &= 0x7fffffff; /* |x| ~< pi/4 */ if (ix <= 0x3fe921fb) { if (ix < 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */ /* raise inexact if x!=0 */ FORCE_EVAL(x + 0x1p120f); return 1.0; } return __cos(x, 0); } /* cos(Inf or NaN) is NaN */ if (ix >= 0x7ff00000) return x-x; /* argument reduction */ n = __rem_pio2(x, y); switch (n&3) { case 0: return __cos(y[0], y[1]); case 1: return -__sin(y[0], y[1], 1); case 2: return -__cos(y[0], y[1]); default: return __sin(y[0], y[1], 1); } } micropython-1.12/lib/libm_dbl/cosh.c000066400000000000000000000013741357706137100174410ustar00rootroot00000000000000#include "libm.h" /* cosh(x) = (exp(x) + 1/exp(x))/2 * = 1 + 0.5*(exp(x)-1)*(exp(x)-1)/exp(x) * = 1 + x*x/2 + o(x^4) */ double cosh(double x) { union {double f; uint64_t i;} u = {.f = x}; uint32_t w; double t; /* |x| */ u.i &= (uint64_t)-1/2; x = u.f; w = u.i >> 32; /* |x| < log(2) */ if (w < 0x3fe62e42) { if (w < 0x3ff00000 - (26<<20)) { /* raise inexact if x!=0 */ FORCE_EVAL(x + 0x1p120f); return 1; } t = expm1(x); return 1 + t*t/(2*(1+t)); } /* |x| < log(DBL_MAX) */ if (w < 0x40862e42) { t = exp(x); /* note: if x>log(0x1p26) then the 1/t is not needed */ return 0.5*(t + 1/t); } /* |x| > log(DBL_MAX) or nan */ /* note: the result is stored to handle overflow */ t = __expo2(x); return t; } micropython-1.12/lib/libm_dbl/erf.c000066400000000000000000000241521357706137100172600ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/s_erf.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* double erf(double x) * double erfc(double x) * x * 2 |\ * erf(x) = --------- | exp(-t*t)dt * sqrt(pi) \| * 0 * * erfc(x) = 1-erf(x) * Note that * erf(-x) = -erf(x) * erfc(-x) = 2 - erfc(x) * * Method: * 1. For |x| in [0, 0.84375] * erf(x) = x + x*R(x^2) * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] * where R = P/Q where P is an odd poly of degree 8 and * Q is an odd poly of degree 10. * -57.90 * | R - (erf(x)-x)/x | <= 2 * * * Remark. The formula is derived by noting * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) * and that * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 * is close to one. The interval is chosen because the fix * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is * near 0.6174), and by some experiment, 0.84375 is chosen to * guarantee the error is less than one ulp for erf. * * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and * c = 0.84506291151 rounded to single (24 bits) * erf(x) = sign(x) * (c + P1(s)/Q1(s)) * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 * 1+(c+P1(s)/Q1(s)) if x < 0 * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 * Remark: here we use the taylor series expansion at x=1. * erf(1+s) = erf(1) + s*Poly(s) * = 0.845.. + P1(s)/Q1(s) * That is, we use rational approximation to approximate * erf(1+s) - (c = (single)0.84506291151) * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] * where * P1(s) = degree 6 poly in s * Q1(s) = degree 6 poly in s * * 3. For x in [1.25,1/0.35(~2.857143)], * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) * erf(x) = 1 - erfc(x) * where * R1(z) = degree 7 poly in z, (z=1/x^2) * S1(z) = degree 8 poly in z * * 4. For x in [1/0.35,28] * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 * erf(x) = sign(x) *(1 - tiny) (raise inexact) * erfc(x) = tiny*tiny (raise underflow) if x > 0 * = 2 - tiny if x<0 * * 7. Special case: * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, * erfc/erf(NaN) is NaN */ #include "libm.h" static const double erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ /* * Coefficients for approximation to erf on [0,0.84375] */ efx8 = 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ /* * Coefficients for approximation to erf in [0.84375,1.25] */ pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ /* * Coefficients for approximation to erfc in [1.25,1/0.35] */ ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ /* * Coefficients for approximation to erfc in [1/.35,28] */ rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ static double erfc1(double x) { double_t s,P,Q; s = fabs(x) - 1; P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); Q = 1+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); return 1 - erx - P/Q; } static double erfc2(uint32_t ix, double x) { double_t s,R,S; double z; if (ix < 0x3ff40000) /* |x| < 1.25 */ return erfc1(x); x = fabs(x); s = 1/(x*x); if (ix < 0x4006db6d) { /* |x| < 1/.35 ~ 2.85714 */ R = ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( ra5+s*(ra6+s*ra7)))))); S = 1.0+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( sa5+s*(sa6+s*(sa7+s*sa8))))))); } else { /* |x| > 1/.35 */ R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( rb5+s*rb6))))); S = 1.0+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( sb5+s*(sb6+s*sb7)))))); } z = x; SET_LOW_WORD(z,0); return exp(-z*z-0.5625)*exp((z-x)*(z+x)+R/S)/x; } double erf(double x) { double r,s,z,y; uint32_t ix; int sign; GET_HIGH_WORD(ix, x); sign = ix>>31; ix &= 0x7fffffff; if (ix >= 0x7ff00000) { /* erf(nan)=nan, erf(+-inf)=+-1 */ return 1-2*sign + 1/x; } if (ix < 0x3feb0000) { /* |x| < 0.84375 */ if (ix < 0x3e300000) { /* |x| < 2**-28 */ /* avoid underflow */ return 0.125*(8*x + efx8*x); } z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); s = 1.0+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); y = r/s; return x + x*y; } if (ix < 0x40180000) /* 0.84375 <= |x| < 6 */ y = 1 - erfc2(ix,x); else y = 1 - 0x1p-1022; return sign ? -y : y; } double erfc(double x) { double r,s,z,y; uint32_t ix; int sign; GET_HIGH_WORD(ix, x); sign = ix>>31; ix &= 0x7fffffff; if (ix >= 0x7ff00000) { /* erfc(nan)=nan, erfc(+-inf)=0,2 */ return 2*sign + 1/x; } if (ix < 0x3feb0000) { /* |x| < 0.84375 */ if (ix < 0x3c700000) /* |x| < 2**-56 */ return 1.0 - x; z = x*x; r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); s = 1.0+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); y = r/s; if (sign || ix < 0x3fd00000) { /* x < 1/4 */ return 1.0 - (x+x*y); } return 0.5 - (x - 0.5 + x*y); } if (ix < 0x403c0000) { /* 0.84375 <= |x| < 28 */ return sign ? 2 - erfc2(ix,x) : erfc2(ix,x); } return sign ? 2 - 0x1p-1022 : 0x1p-1022*0x1p-1022; } micropython-1.12/lib/libm_dbl/exp.c000066400000000000000000000100261357706137100172730ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/e_exp.c */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* exp(x) * Returns the exponential of x. * * Method * 1. Argument reduction: * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. * Given x, find r and integer k such that * * x = k*ln2 + r, |r| <= 0.5*ln2. * * Here r will be represented as r = hi-lo for better * accuracy. * * 2. Approximation of exp(r) by a special rational function on * the interval [0,0.34658]: * Write * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... * We use a special Remez algorithm on [0,0.34658] to generate * a polynomial of degree 5 to approximate R. The maximum error * of this polynomial approximation is bounded by 2**-59. In * other words, * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 * (where z=r*r, and the values of P1 to P5 are listed below) * and * | 5 | -59 * | 2.0+P1*z+...+P5*z - R(z) | <= 2 * | | * The computation of exp(r) thus becomes * 2*r * exp(r) = 1 + ---------- * R(r) - r * r*c(r) * = 1 + r + ----------- (for better accuracy) * 2 - c(r) * where * 2 4 10 * c(r) = r - (P1*r + P2*r + ... + P5*r ). * * 3. Scale back to obtain exp(x): * From step 1, we have * exp(x) = 2^k * exp(r) * * Special cases: * exp(INF) is INF, exp(NaN) is NaN; * exp(-INF) is 0, and * for finite argument, only exp(0)=1 is exact. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Misc. info. * For IEEE double * if x > 709.782712893383973096 then exp(x) overflows * if x < -745.133219101941108420 then exp(x) underflows */ #include "libm.h" static const double half[2] = {0.5,-0.5}, ln2hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ ln2lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ double exp(double x) { double_t hi, lo, c, xx, y; int k, sign; uint32_t hx; GET_HIGH_WORD(hx, x); sign = hx>>31; hx &= 0x7fffffff; /* high word of |x| */ /* special cases */ if (hx >= 0x4086232b) { /* if |x| >= 708.39... */ if (isnan(x)) return x; if (x > 709.782712893383973096) { /* overflow if x!=inf */ x *= 0x1p1023; return x; } if (x < -708.39641853226410622) { /* underflow if x!=-inf */ FORCE_EVAL((float)(-0x1p-149/x)); if (x < -745.13321910194110842) return 0; } } /* argument reduction */ if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ if (hx >= 0x3ff0a2b2) /* if |x| >= 1.5 ln2 */ k = (int)(invln2*x + half[sign]); else k = 1 - sign - sign; hi = x - k*ln2hi; /* k*ln2hi is exact here */ lo = k*ln2lo; x = hi - lo; } else if (hx > 0x3e300000) { /* if |x| > 2**-28 */ k = 0; hi = x; lo = 0; } else { /* inexact if x!=0 */ FORCE_EVAL(0x1p1023 + x); return 1 + x; } /* x is now in primary range */ xx = x*x; c = x - xx*(P1+xx*(P2+xx*(P3+xx*(P4+xx*P5)))); y = 1 + (x*c/(2-c) - lo + hi); if (k == 0) return y; return scalbn(y, k); } micropython-1.12/lib/libm_dbl/expm1.c000066400000000000000000000154641357706137100175440ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/s_expm1.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* expm1(x) * Returns exp(x)-1, the exponential of x minus 1. * * Method * 1. Argument reduction: * Given x, find r and integer k such that * * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 * * Here a correction term c will be computed to compensate * the error in r when rounded to a floating-point number. * * 2. Approximating expm1(r) by a special rational function on * the interval [0,0.34658]: * Since * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... * we define R1(r*r) by * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) * That is, * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... * We use a special Remez algorithm on [0,0.347] to generate * a polynomial of degree 5 in r*r to approximate R1. The * maximum error of this polynomial approximation is bounded * by 2**-61. In other words, * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 * where Q1 = -1.6666666666666567384E-2, * Q2 = 3.9682539681370365873E-4, * Q3 = -9.9206344733435987357E-6, * Q4 = 2.5051361420808517002E-7, * Q5 = -6.2843505682382617102E-9; * z = r*r, * with error bounded by * | 5 | -61 * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 * | | * * expm1(r) = exp(r)-1 is then computed by the following * specific way which minimize the accumulation rounding error: * 2 3 * r r [ 3 - (R1 + R1*r/2) ] * expm1(r) = r + --- + --- * [--------------------] * 2 2 [ 6 - r*(3 - R1*r/2) ] * * To compensate the error in the argument reduction, we use * expm1(r+c) = expm1(r) + c + expm1(r)*c * ~ expm1(r) + c + r*c * Thus c+r*c will be added in as the correction terms for * expm1(r+c). Now rearrange the term to avoid optimization * screw up: * ( 2 2 ) * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) * ( ) * * = r - E * 3. Scale back to obtain expm1(x): * From step 1, we have * expm1(x) = either 2^k*[expm1(r)+1] - 1 * = or 2^k*[expm1(r) + (1-2^-k)] * 4. Implementation notes: * (A). To save one multiplication, we scale the coefficient Qi * to Qi*2^i, and replace z by (x^2)/2. * (B). To achieve maximum accuracy, we compute expm1(x) by * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) * (ii) if k=0, return r-E * (iii) if k=-1, return 0.5*(r-E)-0.5 * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) * else return 1.0+2.0*(r-E); * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else * (vii) return 2^k(1-((E+2^-k)-r)) * * Special cases: * expm1(INF) is INF, expm1(NaN) is NaN; * expm1(-INF) is -1, and * for finite argument, only expm1(0)=0 is exact. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Misc. info. * For IEEE double * if x > 7.09782712893383973096e+02 then expm1(x) overflow * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "libm.h" static const double o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ ln2_hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ /* Scaled Q's: Qn_here = 2**n * Qn_above, for R(2*z) where z = hxs = x*x/2: */ Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ double expm1(double x) { double_t y,hi,lo,c,t,e,hxs,hfx,r1,twopk; union {double f; uint64_t i;} u = {x}; uint32_t hx = u.i>>32 & 0x7fffffff; int k, sign = u.i>>63; /* filter out huge and non-finite argument */ if (hx >= 0x4043687A) { /* if |x|>=56*ln2 */ if (isnan(x)) return x; if (sign) return -1; if (x > o_threshold) { x *= 0x1p1023; return x; } } /* argument reduction */ if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ if (!sign) { hi = x - ln2_hi; lo = ln2_lo; k = 1; } else { hi = x + ln2_hi; lo = -ln2_lo; k = -1; } } else { k = invln2*x + (sign ? -0.5 : 0.5); t = k; hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ lo = t*ln2_lo; } x = hi-lo; c = (hi-x)-lo; } else if (hx < 0x3c900000) { /* |x| < 2**-54, return x */ if (hx < 0x00100000) FORCE_EVAL((float)x); return x; } else k = 0; /* x is now in primary range */ hfx = 0.5*x; hxs = x*hfx; r1 = 1.0+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); t = 3.0-r1*hfx; e = hxs*((r1-t)/(6.0 - x*t)); if (k == 0) /* c is 0 */ return x - (x*e-hxs); e = x*(e-c) - c; e -= hxs; /* exp(x) ~ 2^k (x_reduced - e + 1) */ if (k == -1) return 0.5*(x-e) - 0.5; if (k == 1) { if (x < -0.25) return -2.0*(e-(x+0.5)); return 1.0+2.0*(x-e); } u.i = (uint64_t)(0x3ff + k)<<52; /* 2^k */ twopk = u.f; if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */ y = x - e + 1.0; if (k == 1024) y = y*2.0*0x1p1023; else y = y*twopk; return y - 1.0; } u.i = (uint64_t)(0x3ff - k)<<52; /* 2^-k */ if (k < 20) y = (x-e+(1-u.f))*twopk; else y = (x-(e+u.f)+1)*twopk; return y; } micropython-1.12/lib/libm_dbl/floor.c000066400000000000000000000012151357706137100176200ustar00rootroot00000000000000#include "libm.h" #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON #endif static const double_t toint = 1/EPS; double floor(double x) { union {double f; uint64_t i;} u = {x}; int e = u.i >> 52 & 0x7ff; double_t y; if (e >= 0x3ff+52 || x == 0) return x; /* y = int(x) - x, where int(x) is an integer neighbor of x */ if (u.i >> 63) y = x - toint + toint - x; else y = x + toint - toint - x; /* special case because of non-nearest rounding modes */ if (e <= 0x3ff-1) { FORCE_EVAL(y); return u.i >> 63 ? -1 : 0; } if (y > 0) return x + y - 1; return x + y; } micropython-1.12/lib/libm_dbl/fmod.c000066400000000000000000000023661357706137100174340ustar00rootroot00000000000000#include #include double fmod(double x, double y) { union {double f; uint64_t i;} ux = {x}, uy = {y}; int ex = ux.i>>52 & 0x7ff; int ey = uy.i>>52 & 0x7ff; int sx = ux.i>>63; uint64_t i; /* in the followings uxi should be ux.i, but then gcc wrongly adds */ /* float load/store to inner loops ruining performance and code size */ uint64_t uxi = ux.i; if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) return (x*y)/(x*y); if (uxi<<1 <= uy.i<<1) { if (uxi<<1 == uy.i<<1) return 0*x; return x; } /* normalize x and y */ if (!ex) { for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); uxi <<= -ex + 1; } else { uxi &= -1ULL >> 12; uxi |= 1ULL << 52; } if (!ey) { for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); uy.i <<= -ey + 1; } else { uy.i &= -1ULL >> 12; uy.i |= 1ULL << 52; } /* x mod y */ for (; ex > ey; ex--) { i = uxi - uy.i; if (i >> 63 == 0) { if (i == 0) return 0*x; uxi = i; } uxi <<= 1; } i = uxi - uy.i; if (i >> 63 == 0) { if (i == 0) return 0*x; uxi = i; } for (; uxi>>52 == 0; uxi <<= 1, ex--); /* scale result */ if (ex > 0) { uxi -= 1ULL << 52; uxi |= (uint64_t)ex << 52; } else { uxi >>= -ex + 1; } uxi |= (uint64_t)sx << 63; ux.i = uxi; return ux.f; } micropython-1.12/lib/libm_dbl/frexp.c000066400000000000000000000005661357706137100176330ustar00rootroot00000000000000#include #include double frexp(double x, int *e) { union { double d; uint64_t i; } y = { x }; int ee = y.i>>52 & 0x7ff; if (!ee) { if (x) { x = frexp(x*0x1p64, e); *e -= 64; } else *e = 0; return x; } else if (ee == 0x7ff) { return x; } *e = ee - 0x3fe; y.i &= 0x800fffffffffffffull; y.i |= 0x3fe0000000000000ull; return y.d; } micropython-1.12/lib/libm_dbl/ldexp.c000066400000000000000000000001131357706137100176070ustar00rootroot00000000000000#include double ldexp(double x, int n) { return scalbn(x, n); } micropython-1.12/lib/libm_dbl/lgamma.c000066400000000000000000000002001357706137100177260ustar00rootroot00000000000000#include double __lgamma_r(double, int*); double lgamma(double x) { int sign; return __lgamma_r(x, &sign); } micropython-1.12/lib/libm_dbl/libm.h000066400000000000000000000071631357706137100174370ustar00rootroot00000000000000// Portions of this file are extracted from musl-1.1.16 src/internal/libm.h /* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include #include #define FLT_EVAL_METHOD 0 #define FORCE_EVAL(x) do { \ if (sizeof(x) == sizeof(float)) { \ volatile float __x; \ __x = (x); \ (void)__x; \ } else if (sizeof(x) == sizeof(double)) { \ volatile double __x; \ __x = (x); \ (void)__x; \ } else { \ volatile long double __x; \ __x = (x); \ (void)__x; \ } \ } while(0) /* Get two 32 bit ints from a double. */ #define EXTRACT_WORDS(hi,lo,d) \ do { \ union {double f; uint64_t i;} __u; \ __u.f = (d); \ (hi) = __u.i >> 32; \ (lo) = (uint32_t)__u.i; \ } while (0) /* Get the more significant 32 bit int from a double. */ #define GET_HIGH_WORD(hi,d) \ do { \ union {double f; uint64_t i;} __u; \ __u.f = (d); \ (hi) = __u.i >> 32; \ } while (0) /* Get the less significant 32 bit int from a double. */ #define GET_LOW_WORD(lo,d) \ do { \ union {double f; uint64_t i;} __u; \ __u.f = (d); \ (lo) = (uint32_t)__u.i; \ } while (0) /* Set a double from two 32 bit ints. */ #define INSERT_WORDS(d,hi,lo) \ do { \ union {double f; uint64_t i;} __u; \ __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \ (d) = __u.f; \ } while (0) /* Set the more significant 32 bits of a double from an int. */ #define SET_HIGH_WORD(d,hi) \ do { \ union {double f; uint64_t i;} __u; \ __u.f = (d); \ __u.i &= 0xffffffff; \ __u.i |= (uint64_t)(hi) << 32; \ (d) = __u.f; \ } while (0) /* Set the less significant 32 bits of a double from an int. */ #define SET_LOW_WORD(d,lo) \ do { \ union {double f; uint64_t i;} __u; \ __u.f = (d); \ __u.i &= 0xffffffff00000000ull; \ __u.i |= (uint32_t)(lo); \ (d) = __u.f; \ } while (0) #define DBL_EPSILON 2.22044604925031308085e-16 int __rem_pio2(double, double*); int __rem_pio2_large(double*, double*, int, int, int); double __sin(double, double, int); double __cos(double, double); double __tan(double, double, int); double __expo2(double); micropython-1.12/lib/libm_dbl/log.c000066400000000000000000000076721357706137100172750ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/e_log.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* log(x) * Return the logarithm of x * * Method : * 1. Argument Reduction: find k and f such that * x = 2^k * (1+f), * where sqrt(2)/2 < 1+f < sqrt(2) . * * 2. Approximation of log(1+f). * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) * = 2s + 2/3 s**3 + 2/5 s**5 + ....., * = 2s + s*R * We use a special Remez algorithm on [0,0.1716] to generate * a polynomial of degree 14 to approximate R The maximum error * of this polynomial approximation is bounded by 2**-58.45. In * other words, * 2 4 6 8 10 12 14 * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s * (the values of Lg1 to Lg7 are listed in the program) * and * | 2 14 | -58.45 * | Lg1*s +...+Lg7*s - R(z) | <= 2 * | | * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. * In order to guarantee error in log below 1ulp, we compute log * by * log(1+f) = f - s*(f - R) (if f is not too large) * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) * * 3. Finally, log(x) = k*ln2 + log(1+f). * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) * Here ln2 is split into two floating point number: * ln2_hi + ln2_lo, * where n*ln2_hi is always exact for |n| < 2000. * * Special cases: * log(x) is NaN with signal if x < 0 (including -INF) ; * log(+INF) is +INF; log(0) is -INF with signal; * log(NaN) is that NaN with no signal. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include #include static const double ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ double log(double x) { union {double f; uint64_t i;} u = {x}; double_t hfsq,f,s,z,R,w,t1,t2,dk; uint32_t hx; int k; hx = u.i>>32; k = 0; if (hx < 0x00100000 || hx>>31) { if (u.i<<1 == 0) return -1/(x*x); /* log(+-0)=-inf */ if (hx>>31) return (x-x)/0.0; /* log(-#) = NaN */ /* subnormal number, scale x up */ k -= 54; x *= 0x1p54; u.f = x; hx = u.i>>32; } else if (hx >= 0x7ff00000) { return x; } else if (hx == 0x3ff00000 && u.i<<32 == 0) return 0; /* reduce x into [sqrt(2)/2, sqrt(2)] */ hx += 0x3ff00000 - 0x3fe6a09e; k += (int)(hx>>20) - 0x3ff; hx = (hx&0x000fffff) + 0x3fe6a09e; u.i = (uint64_t)hx<<32 | (u.i&0xffffffff); x = u.f; f = x - 1.0; hfsq = 0.5*f*f; s = f/(2.0+f); z = s*s; w = z*z; t1 = w*(Lg2+w*(Lg4+w*Lg6)); t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); R = t2 + t1; dk = k; return s*(hfsq+R) + dk*ln2_lo - hfsq + f + dk*ln2_hi; } micropython-1.12/lib/libm_dbl/log10.c000066400000000000000000000002051357706137100174170ustar00rootroot00000000000000#include static const double _M_LN10 = 2.302585092994046; double log10(double x) { return log(x) / (double)_M_LN10; } micropython-1.12/lib/libm_dbl/log1p.c000066400000000000000000000074311357706137100175270ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/s_log1p.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* double log1p(double x) * Return the natural logarithm of 1+x. * * Method : * 1. Argument Reduction: find k and f such that * 1+x = 2^k * (1+f), * where sqrt(2)/2 < 1+f < sqrt(2) . * * Note. If k=0, then f=x is exact. However, if k!=0, then f * may not be representable exactly. In that case, a correction * term is need. Let u=1+x rounded. Let c = (1+x)-u, then * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), * and add back the correction term c/u. * (Note: when x > 2**53, one can simply return log(x)) * * 2. Approximation of log(1+f): See log.c * * 3. Finally, log1p(x) = k*ln2 + log(1+f) + c/u. See log.c * * Special cases: * log1p(x) is NaN with signal if x < -1 (including -INF) ; * log1p(+INF) is +INF; log1p(-1) is -INF with signal; * log1p(NaN) is that NaN with no signal. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. * * Note: Assuming log() return accurate answer, the following * algorithm can be used to compute log1p(x) to within a few ULP: * * u = 1+x; * if(u==1.0) return x ; else * return log(u)*(x/(u-1.0)); * * See HP-15C Advanced Functions Handbook, p.193. */ #include "libm.h" static const double ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ double log1p(double x) { union {double f; uint64_t i;} u = {x}; double_t hfsq,f,c,s,z,R,w,t1,t2,dk; uint32_t hx,hu; int k; hx = u.i>>32; k = 1; if (hx < 0x3fda827a || hx>>31) { /* 1+x < sqrt(2)+ */ if (hx >= 0xbff00000) { /* x <= -1.0 */ if (x == -1) return x/0.0; /* log1p(-1) = -inf */ return (x-x)/0.0; /* log1p(x<-1) = NaN */ } if (hx<<1 < 0x3ca00000<<1) { /* |x| < 2**-53 */ /* underflow if subnormal */ if ((hx&0x7ff00000) == 0) FORCE_EVAL((float)x); return x; } if (hx <= 0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ k = 0; c = 0; f = x; } } else if (hx >= 0x7ff00000) return x; if (k) { u.f = 1 + x; hu = u.i>>32; hu += 0x3ff00000 - 0x3fe6a09e; k = (int)(hu>>20) - 0x3ff; /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ if (k < 54) { c = k >= 2 ? 1-(u.f-x) : x-(u.f-1); c /= u.f; } else c = 0; /* reduce u into [sqrt(2)/2, sqrt(2)] */ hu = (hu&0x000fffff) + 0x3fe6a09e; u.i = (uint64_t)hu<<32 | (u.i&0xffffffff); f = u.f - 1; } hfsq = 0.5*f*f; s = f/(2.0+f); z = s*s; w = z*z; t1 = w*(Lg2+w*(Lg4+w*Lg6)); t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); R = t2 + t1; dk = k; return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi; } micropython-1.12/lib/libm_dbl/modf.c000066400000000000000000000010301357706137100174170ustar00rootroot00000000000000#include "libm.h" double modf(double x, double *iptr) { union {double f; uint64_t i;} u = {x}; uint64_t mask; int e = (int)(u.i>>52 & 0x7ff) - 0x3ff; /* no fractional part */ if (e >= 52) { *iptr = x; if (e == 0x400 && u.i<<12 != 0) /* nan */ return x; u.i &= 1ULL<<63; return u.f; } /* no integral part*/ if (e < 0) { u.i &= 1ULL<<63; *iptr = u.f; return x; } mask = -1ULL>>12>>e; if ((u.i & mask) == 0) { *iptr = x; u.i &= 1ULL<<63; return u.f; } u.i &= ~mask; *iptr = u.f; return x - u.f; } micropython-1.12/lib/libm_dbl/nearbyint.c000066400000000000000000000005161357706137100204750ustar00rootroot00000000000000//#include #include /* nearbyint is the same as rint, but it must not raise the inexact exception */ double nearbyint(double x) { #ifdef FE_INEXACT #pragma STDC FENV_ACCESS ON int e; e = fetestexcept(FE_INEXACT); #endif x = rint(x); #ifdef FE_INEXACT if (!e) feclearexcept(FE_INEXACT); #endif return x; } micropython-1.12/lib/libm_dbl/pow.c000066400000000000000000000242171357706137100173130ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/e_pow.c */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* pow(x,y) return x**y * * n * Method: Let x = 2 * (1+f) * 1. Compute and return log2(x) in two pieces: * log2(x) = w1 + w2, * where w1 has 53-24 = 29 bit trailing zeros. * 2. Perform y*log2(x) = n+y' by simulating muti-precision * arithmetic, where |y'|<=0.5. * 3. Return x**y = 2**n*exp(y'*log2) * * Special cases: * 1. (anything) ** 0 is 1 * 2. 1 ** (anything) is 1 * 3. (anything except 1) ** NAN is NAN * 4. NAN ** (anything except 0) is NAN * 5. +-(|x| > 1) ** +INF is +INF * 6. +-(|x| > 1) ** -INF is +0 * 7. +-(|x| < 1) ** +INF is +0 * 8. +-(|x| < 1) ** -INF is +INF * 9. -1 ** +-INF is 1 * 10. +0 ** (+anything except 0, NAN) is +0 * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 * 12. +0 ** (-anything except 0, NAN) is +INF, raise divbyzero * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF, raise divbyzero * 14. -0 ** (+odd integer) is -0 * 15. -0 ** (-odd integer) is -INF, raise divbyzero * 16. +INF ** (+anything except 0,NAN) is +INF * 17. +INF ** (-anything except 0,NAN) is +0 * 18. -INF ** (+odd integer) is -INF * 19. -INF ** (anything) = -0 ** (-anything), (anything except odd integer) * 20. (anything) ** 1 is (anything) * 21. (anything) ** -1 is 1/(anything) * 22. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) * 23. (-anything except 0 and inf) ** (non-integer) is NAN * * Accuracy: * pow(x,y) returns x**y nearly rounded. In particular * pow(integer,integer) * always returns the correct integer provided it is * representable. * * Constants : * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #include "libm.h" static const double bp[] = {1.0, 1.5,}, dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ huge = 1.0e300, tiny = 1.0e-300, /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ ovt = 8.0085662595372944372e-017, /* -(1024-log2(ovfl+.5ulp)) */ cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ double pow(double x, double y) { double z,ax,z_h,z_l,p_h,p_l; double y1,t1,t2,r,s,t,u,v,w; int32_t i,j,k,yisint,n; int32_t hx,hy,ix,iy; uint32_t lx,ly; EXTRACT_WORDS(hx, lx, x); EXTRACT_WORDS(hy, ly, y); ix = hx & 0x7fffffff; iy = hy & 0x7fffffff; /* x**0 = 1, even if x is NaN */ if ((iy|ly) == 0) return 1.0; /* 1**y = 1, even if y is NaN */ if (hx == 0x3ff00000 && lx == 0) return 1.0; /* NaN if either arg is NaN */ if (ix > 0x7ff00000 || (ix == 0x7ff00000 && lx != 0) || iy > 0x7ff00000 || (iy == 0x7ff00000 && ly != 0)) return x + y; /* determine if y is an odd int when x < 0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ yisint = 0; if (hx < 0) { if (iy >= 0x43400000) yisint = 2; /* even integer y */ else if (iy >= 0x3ff00000) { k = (iy>>20) - 0x3ff; /* exponent */ if (k > 20) { uint32_t j = ly>>(52-k); if ((j<<(52-k)) == ly) yisint = 2 - (j&1); } else if (ly == 0) { uint32_t j = iy>>(20-k); if ((j<<(20-k)) == iy) yisint = 2 - (j&1); } } } /* special value of y */ if (ly == 0) { if (iy == 0x7ff00000) { /* y is +-inf */ if (((ix-0x3ff00000)|lx) == 0) /* (-1)**+-inf is 1 */ return 1.0; else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ return hy >= 0 ? y : 0.0; else /* (|x|<1)**+-inf = 0,inf */ return hy >= 0 ? 0.0 : -y; } if (iy == 0x3ff00000) { /* y is +-1 */ if (hy >= 0) return x; y = 1/x; #if FLT_EVAL_METHOD!=0 { union {double f; uint64_t i;} u = {y}; uint64_t i = u.i & -1ULL/2; if (i>>52 == 0 && (i&(i-1))) FORCE_EVAL((float)y); } #endif return y; } if (hy == 0x40000000) /* y is 2 */ return x*x; if (hy == 0x3fe00000) { /* y is 0.5 */ if (hx >= 0) /* x >= +0 */ return sqrt(x); } } ax = fabs(x); /* special value of x */ if (lx == 0) { if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { /* x is +-0,+-inf,+-1 */ z = ax; if (hy < 0) /* z = (1/|x|) */ z = 1.0/z; if (hx < 0) { if (((ix-0x3ff00000)|yisint) == 0) { z = (z-z)/(z-z); /* (-1)**non-int is NaN */ } else if (yisint == 1) z = -z; /* (x<0)**odd = -(|x|**odd) */ } return z; } } s = 1.0; /* sign of result */ if (hx < 0) { if (yisint == 0) /* (x<0)**(non-int) is NaN */ return (x-x)/(x-x); if (yisint == 1) /* (x<0)**(odd int) */ s = -1.0; } /* |y| is huge */ if (iy > 0x41e00000) { /* if |y| > 2**31 */ if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ if (ix <= 0x3fefffff) return hy < 0 ? huge*huge : tiny*tiny; if (ix >= 0x3ff00000) return hy > 0 ? huge*huge : tiny*tiny; } /* over/underflow if x is not close to one */ if (ix < 0x3fefffff) return hy < 0 ? s*huge*huge : s*tiny*tiny; if (ix > 0x3ff00000) return hy > 0 ? s*huge*huge : s*tiny*tiny; /* now |1-x| is tiny <= 2**-20, suffice to compute log(x) by x-x^2/2+x^3/3-x^4/4 */ t = ax - 1.0; /* t has 20 trailing zeros */ w = (t*t)*(0.5 - t*(0.3333333333333333333333-t*0.25)); u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ v = t*ivln2_l - w*ivln2; t1 = u + v; SET_LOW_WORD(t1, 0); t2 = v - (t1-u); } else { double ss,s2,s_h,s_l,t_h,t_l; n = 0; /* take care subnormal number */ if (ix < 0x00100000) { ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); } n += ((ix)>>20) - 0x3ff; j = ix & 0x000fffff; /* determine interval */ ix = j | 0x3ff00000; /* normalize ix */ if (j <= 0x3988E) /* |x|>1)|0x20000000) + 0x00080000 + (k<<18)); t_l = ax - (t_h-bp[k]); s_l = v*((u-s_h*t_h)-s_h*t_l); /* compute log(ax) */ s2 = ss*ss; r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); r += s_l*(s_h+ss); s2 = s_h*s_h; t_h = 3.0 + s2 + r; SET_LOW_WORD(t_h, 0); t_l = r - ((t_h-3.0)-s2); /* u+v = ss*(1+...) */ u = s_h*t_h; v = s_l*t_h + t_l*ss; /* 2/(3log2)*(ss+...) */ p_h = u + v; SET_LOW_WORD(p_h, 0); p_l = v - (p_h-u); z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ z_l = cp_l*p_h+p_l*cp + dp_l[k]; /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ t = (double)n; t1 = ((z_h + z_l) + dp_h[k]) + t; SET_LOW_WORD(t1, 0); t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); } /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ y1 = y; SET_LOW_WORD(y1, 0); p_l = (y-y1)*t1 + y*t2; p_h = y1*t1; z = p_l + p_h; EXTRACT_WORDS(j, i, z); if (j >= 0x40900000) { /* z >= 1024 */ if (((j-0x40900000)|i) != 0) /* if z > 1024 */ return s*huge*huge; /* overflow */ if (p_l + ovt > z - p_h) return s*huge*huge; /* overflow */ } else if ((j&0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ // FIXME: instead of abs(j) use unsigned j if (((j-0xc090cc00)|i) != 0) /* z < -1075 */ return s*tiny*tiny; /* underflow */ if (p_l <= z - p_h) return s*tiny*tiny; /* underflow */ } /* * compute 2**(p_h+p_l) */ i = j & 0x7fffffff; k = (i>>20) - 0x3ff; n = 0; if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ n = j + (0x00100000>>(k+1)); k = ((n&0x7fffffff)>>20) - 0x3ff; /* new k for n */ t = 0.0; SET_HIGH_WORD(t, n & ~(0x000fffff>>k)); n = ((n&0x000fffff)|0x00100000)>>(20-k); if (j < 0) n = -n; p_h -= t; } t = p_l + p_h; SET_LOW_WORD(t, 0); u = t*lg2_h; v = (p_l-(t-p_h))*lg2 + t*lg2_l; z = u + v; w = v - (z-u); t = z*z; t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); r = (z*t1)/(t1-2.0) - (w + z*w); z = 1.0 - (r-z); GET_HIGH_WORD(j, z); j += n<<20; if ((j>>20) <= 0) /* subnormal output */ z = scalbn(z,n); else SET_HIGH_WORD(z, j); return s*z; } micropython-1.12/lib/libm_dbl/rint.c000066400000000000000000000007511357706137100174570ustar00rootroot00000000000000#include #include #include #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON #endif static const double_t toint = 1/EPS; double rint(double x) { union {double f; uint64_t i;} u = {x}; int e = u.i>>52 & 0x7ff; int s = u.i>>63; double_t y; if (e >= 0x3ff+52) return x; if (s) y = x - toint + toint; else y = x + toint - toint; if (y == 0) return s ? -0.0 : 0; return y; } micropython-1.12/lib/libm_dbl/scalbn.c000066400000000000000000000011001357706137100177320ustar00rootroot00000000000000#include #include double scalbn(double x, int n) { union {double f; uint64_t i;} u; double_t y = x; if (n > 1023) { y *= 0x1p1023; n -= 1023; if (n > 1023) { y *= 0x1p1023; n -= 1023; if (n > 1023) n = 1023; } } else if (n < -1022) { /* make sure final n < -53 to avoid double rounding in the subnormal range */ y *= 0x1p-1022 * 0x1p53; n += 1022 - 53; if (n < -1022) { y *= 0x1p-1022 * 0x1p53; n += 1022 - 53; if (n < -1022) n = -1022; } } u.i = (uint64_t)(0x3ff+n)<<52; x = y * u.f; return x; } micropython-1.12/lib/libm_dbl/sin.c000066400000000000000000000042201357706137100172670ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* sin(x) * Return sine function of x. * * kernel function: * __sin ... sine function on [-pi/4,pi/4] * __cos ... cose function on [-pi/4,pi/4] * __rem_pio2 ... argument reduction routine * * Method. * Let S,C and T denote the sin, cos and tan respectively on * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 * in [-pi/4 , +pi/4], and let n = k mod 4. * We have * * n sin(x) cos(x) tan(x) * ---------------------------------------------------------- * 0 S C T * 1 C -S -1/T * 2 -S -C T * 3 -C S -1/T * ---------------------------------------------------------- * * Special cases: * Let trig be any of sin, cos, or tan. * trig(+-INF) is NaN, with signals; * trig(NaN) is that NaN; * * Accuracy: * TRIG(x) returns trig(x) nearly rounded */ #include "libm.h" double sin(double x) { double y[2]; uint32_t ix; unsigned n; /* High word of x. */ GET_HIGH_WORD(ix, x); ix &= 0x7fffffff; /* |x| ~< pi/4 */ if (ix <= 0x3fe921fb) { if (ix < 0x3e500000) { /* |x| < 2**-26 */ /* raise inexact if x != 0 and underflow if subnormal*/ FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f); return x; } return __sin(x, 0.0, 0); } /* sin(Inf or NaN) is NaN */ if (ix >= 0x7ff00000) return x - x; /* argument reduction needed */ n = __rem_pio2(x, y); switch (n&3) { case 0: return __sin(y[0], y[1], 1); case 1: return __cos(y[0], y[1]); case 2: return -__sin(y[0], y[1], 1); default: return -__cos(y[0], y[1]); } } micropython-1.12/lib/libm_dbl/sinh.c000066400000000000000000000015051357706137100174420ustar00rootroot00000000000000#include "libm.h" /* sinh(x) = (exp(x) - 1/exp(x))/2 * = (exp(x)-1 + (exp(x)-1)/exp(x))/2 * = x + x^3/6 + o(x^5) */ double sinh(double x) { union {double f; uint64_t i;} u = {.f = x}; uint32_t w; double t, h, absx; h = 0.5; if (u.i >> 63) h = -h; /* |x| */ u.i &= (uint64_t)-1/2; absx = u.f; w = u.i >> 32; /* |x| < log(DBL_MAX) */ if (w < 0x40862e42) { t = expm1(absx); if (w < 0x3ff00000) { if (w < 0x3ff00000 - (26<<20)) /* note: inexact and underflow are raised by expm1 */ /* note: this branch avoids spurious underflow */ return x; return h*(2*t - t*t/(t+1)); } /* note: |x|>log(0x1p26)+eps could be just h*exp(x) */ return h*(t + t/(t+1)); } /* |x| > log(DBL_MAX) or nan */ /* note: the result is stored to handle overflow */ t = 2*h*__expo2(absx); return t; } micropython-1.12/lib/libm_dbl/sqrt.c000066400000000000000000000124611357706137100174750ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* sqrt(x) * Return correctly rounded sqrt. * ------------------------------------------ * | Use the hardware sqrt if you have one | * ------------------------------------------ * Method: * Bit by bit method using integer arithmetic. (Slow, but portable) * 1. Normalization * Scale x to y in [1,4) with even powers of 2: * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then * sqrt(x) = 2^k * sqrt(y) * 2. Bit by bit computation * Let q = sqrt(y) truncated to i bit after binary point (q = 1), * i 0 * i+1 2 * s = 2*q , and y = 2 * ( y - q ). (1) * i i i i * * To compute q from q , one checks whether * i+1 i * * -(i+1) 2 * (q + 2 ) <= y. (2) * i * -(i+1) * If (2) is false, then q = q ; otherwise q = q + 2 . * i+1 i i+1 i * * With some algebric manipulation, it is not difficult to see * that (2) is equivalent to * -(i+1) * s + 2 <= y (3) * i i * * The advantage of (3) is that s and y can be computed by * i i * the following recurrence formula: * if (3) is false * * s = s , y = y ; (4) * i+1 i i+1 i * * otherwise, * -i -(i+1) * s = s + 2 , y = y - s - 2 (5) * i+1 i i+1 i i * * One may easily use induction to prove (4) and (5). * Note. Since the left hand side of (3) contain only i+2 bits, * it does not necessary to do a full (53-bit) comparison * in (3). * 3. Final rounding * After generating the 53 bits result, we compute one more bit. * Together with the remainder, we can decide whether the * result is exact, bigger than 1/2ulp, or less than 1/2ulp * (it will never equal to 1/2ulp). * The rounding mode can be detected by checking whether * huge + tiny is equal to huge, and whether huge - tiny is * equal to huge for some floating point number "huge" and "tiny". * * Special cases: * sqrt(+-0) = +-0 ... exact * sqrt(inf) = inf * sqrt(-ve) = NaN ... with invalid signal * sqrt(NaN) = NaN ... with invalid signal for signaling NaN */ #include "libm.h" static const double tiny = 1.0e-300; double sqrt(double x) { double z; int32_t sign = (int)0x80000000; int32_t ix0,s0,q,m,t,i; uint32_t r,t1,s1,ix1,q1; EXTRACT_WORDS(ix0, ix1, x); /* take care of Inf and NaN */ if ((ix0&0x7ff00000) == 0x7ff00000) { return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ } /* take care of zero */ if (ix0 <= 0) { if (((ix0&~sign)|ix1) == 0) return x; /* sqrt(+-0) = +-0 */ if (ix0 < 0) return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ } /* normalize x */ m = ix0>>20; if (m == 0) { /* subnormal x */ while (ix0 == 0) { m -= 21; ix0 |= (ix1>>11); ix1 <<= 21; } for (i=0; (ix0&0x00100000) == 0; i++) ix0<<=1; m -= i - 1; ix0 |= ix1>>(32-i); ix1 <<= i; } m -= 1023; /* unbias exponent */ ix0 = (ix0&0x000fffff)|0x00100000; if (m & 1) { /* odd m, double x to make it even */ ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; } m >>= 1; /* m = [m/2] */ /* generate sqrt(x) bit by bit */ ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ r = 0x00200000; /* r = moving bit from right to left */ while (r != 0) { t = s0 + r; if (t <= ix0) { s0 = t + r; ix0 -= t; q += r; } ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; r >>= 1; } r = sign; while (r != 0) { t1 = s1 + r; t = s0; if (t < ix0 || (t == ix0 && t1 <= ix1)) { s1 = t1 + r; if ((t1&sign) == sign && (s1&sign) == 0) s0++; ix0 -= t; if (ix1 < t1) ix0--; ix1 -= t1; q1 += r; } ix0 += ix0 + ((ix1&sign)>>31); ix1 += ix1; r >>= 1; } /* use floating add to find out rounding direction */ if ((ix0|ix1) != 0) { z = 1.0 - tiny; /* raise inexact flag */ if (z >= 1.0) { z = 1.0 + tiny; if (q1 == (uint32_t)0xffffffff) { q1 = 0; q++; } else if (z > 1.0) { if (q1 == (uint32_t)0xfffffffe) q++; q1 += 2; } else q1 += q1 & 1; } } ix0 = (q>>1) + 0x3fe00000; ix1 = q1>>1; if (q&1) ix1 |= sign; ix0 += m << 20; INSERT_WORDS(z, ix0, ix1); return z; } micropython-1.12/lib/libm_dbl/tan.c000066400000000000000000000036551357706137100172730ustar00rootroot00000000000000/* origin: FreeBSD /usr/src/lib/msun/src/s_tan.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* tan(x) * Return tangent function of x. * * kernel function: * __tan ... tangent function on [-pi/4,pi/4] * __rem_pio2 ... argument reduction routine * * Method. * Let S,C and T denote the sin, cos and tan respectively on * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 * in [-pi/4 , +pi/4], and let n = k mod 4. * We have * * n sin(x) cos(x) tan(x) * ---------------------------------------------------------- * 0 S C T * 1 C -S -1/T * 2 -S -C T * 3 -C S -1/T * ---------------------------------------------------------- * * Special cases: * Let trig be any of sin, cos, or tan. * trig(+-INF) is NaN, with signals; * trig(NaN) is that NaN; * * Accuracy: * TRIG(x) returns trig(x) nearly rounded */ #include "libm.h" double tan(double x) { double y[2]; uint32_t ix; unsigned n; GET_HIGH_WORD(ix, x); ix &= 0x7fffffff; /* |x| ~< pi/4 */ if (ix <= 0x3fe921fb) { if (ix < 0x3e400000) { /* |x| < 2**-27 */ /* raise inexact if x!=0 and underflow if subnormal */ FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f); return x; } return __tan(x, 0.0, 0); } /* tan(Inf or NaN) is NaN */ if (ix >= 0x7ff00000) return x - x; /* argument reduction */ n = __rem_pio2(x, y); return __tan(y[0], y[1], n&1); } micropython-1.12/lib/libm_dbl/tanh.c000066400000000000000000000002761357706137100174370ustar00rootroot00000000000000#include double tanh(double x) { int sign = 0; if (x < 0) { sign = 1; x = -x; } x = expm1(-2 * x); x = x / (x + 2); return sign ? x : -x; } micropython-1.12/lib/libm_dbl/tgamma.c000066400000000000000000000125321357706137100177510ustar00rootroot00000000000000/* "A Precision Approximation of the Gamma Function" - Cornelius Lanczos (1964) "Lanczos Implementation of the Gamma Function" - Paul Godfrey (2001) "An Analysis of the Lanczos Gamma Approximation" - Glendon Ralph Pugh (2004) approximation method: (x - 0.5) S(x) Gamma(x) = (x + g - 0.5) * ---------------- exp(x + g - 0.5) with a1 a2 a3 aN S(x) ~= [ a0 + ----- + ----- + ----- + ... + ----- ] x + 1 x + 2 x + 3 x + N with a0, a1, a2, a3,.. aN constants which depend on g. for x < 0 the following reflection formula is used: Gamma(x)*Gamma(-x) = -pi/(x sin(pi x)) most ideas and constants are from boost and python */ #include "libm.h" static const double pi = 3.141592653589793238462643383279502884; /* sin(pi x) with x > 0x1p-100, if sin(pi*x)==0 the sign is arbitrary */ static double sinpi(double x) { int n; /* argument reduction: x = |x| mod 2 */ /* spurious inexact when x is odd int */ x = x * 0.5; x = 2 * (x - floor(x)); /* reduce x into [-.25,.25] */ n = 4 * x; n = (n+1)/2; x -= n * 0.5; x *= pi; switch (n) { default: /* case 4 */ case 0: return __sin(x, 0, 0); case 1: return __cos(x, 0); case 2: return __sin(-x, 0, 0); case 3: return -__cos(x, 0); } } #define N 12 //static const double g = 6.024680040776729583740234375; static const double gmhalf = 5.524680040776729583740234375; static const double Snum[N+1] = { 23531376880.410759688572007674451636754734846804940, 42919803642.649098768957899047001988850926355848959, 35711959237.355668049440185451547166705960488635843, 17921034426.037209699919755754458931112671403265390, 6039542586.3520280050642916443072979210699388420708, 1439720407.3117216736632230727949123939715485786772, 248874557.86205415651146038641322942321632125127801, 31426415.585400194380614231628318205362874684987640, 2876370.6289353724412254090516208496135991145378768, 186056.26539522349504029498971604569928220784236328, 8071.6720023658162106380029022722506138218516325024, 210.82427775157934587250973392071336271166969580291, 2.5066282746310002701649081771338373386264310793408, }; static const double Sden[N+1] = { 0, 39916800, 120543840, 150917976, 105258076, 45995730, 13339535, 2637558, 357423, 32670, 1925, 66, 1, }; /* n! for small integer n */ static const double fact[] = { 1, 1, 2, 6, 24, 120, 720, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0, 479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, 355687428096000.0, 6402373705728000.0, 121645100408832000.0, 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0, }; /* S(x) rational function for positive x */ static double S(double x) { double_t num = 0, den = 0; int i; /* to avoid overflow handle large x differently */ if (x < 8) for (i = N; i >= 0; i--) { num = num * x + Snum[i]; den = den * x + Sden[i]; } else for (i = 0; i <= N; i++) { num = num / x + Snum[i]; den = den / x + Sden[i]; } return num/den; } double tgamma(double x) { union {double f; uint64_t i;} u = {x}; double absx, y; double_t dy, z, r; uint32_t ix = u.i>>32 & 0x7fffffff; int sign = u.i>>63; /* special cases */ if (ix >= 0x7ff00000) /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */ return x + INFINITY; if (ix < (0x3ff-54)<<20) /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */ return 1/x; /* integer arguments */ /* raise inexact when non-integer */ if (x == floor(x)) { if (sign) return 0/0.0; if (x <= sizeof fact/sizeof *fact) return fact[(int)x - 1]; } /* x >= 172: tgamma(x)=inf with overflow */ /* x =< -184: tgamma(x)=+-0 with underflow */ if (ix >= 0x40670000) { /* |x| >= 184 */ if (sign) { FORCE_EVAL((float)(0x1p-126/x)); if (floor(x) * 0.5 == floor(x * 0.5)) return 0; return -0.0; } x *= 0x1p1023; return x; } absx = sign ? -x : x; /* handle the error of x + g - 0.5 */ y = absx + gmhalf; if (absx > gmhalf) { dy = y - absx; dy -= gmhalf; } else { dy = y - gmhalf; dy -= absx; } z = absx - 0.5; r = S(absx) * exp(-y); if (x < 0) { /* reflection formula for negative x */ /* sinpi(absx) is not 0, integers are already handled */ r = -pi / (sinpi(absx) * absx * r); dy = -dy; z = -z; } r += dy * (gmhalf+0.5) * r / y; z = pow(y, 0.5*z); y = r * z * z; return y; } #if 1 double __lgamma_r(double x, int *sign) { double r, absx; *sign = 1; /* special cases */ if (!isfinite(x)) /* lgamma(nan)=nan, lgamma(+-inf)=inf */ return x*x; /* integer arguments */ if (x == floor(x) && x <= 2) { /* n <= 0: lgamma(n)=inf with divbyzero */ /* n == 1,2: lgamma(n)=0 */ if (x <= 0) return 1/0.0; return 0; } absx = fabs(x); /* lgamma(x) ~ -log(|x|) for tiny |x| */ if (absx < 0x1p-54) { *sign = 1 - 2*!!signbit(x); return -log(absx); } /* use tgamma for smaller |x| */ if (absx < 128) { x = tgamma(x); *sign = 1 - 2*!!signbit(x); return log(fabs(x)); } /* second term (log(S)-g) could be more precise here.. */ /* or with stirling: (|x|-0.5)*(log(|x|)-1) + poly(1/|x|) */ r = (absx-0.5)*(log(absx+gmhalf)-1) + (log(S(absx)) - (gmhalf+0.5)); if (x < 0) { /* reflection formula for negative x */ x = sinpi(absx); *sign = 2*!!signbit(x) - 1; r = log(pi/(fabs(x)*absx)) - r; } return r; } //weak_alias(__lgamma_r, lgamma_r); #endif micropython-1.12/lib/libm_dbl/thumb_vfp_sqrt.c000066400000000000000000000003741357706137100215470ustar00rootroot00000000000000// an implementation of sqrt for Thumb using hardware double-precision VFP instructions double sqrt(double x) { double ret; asm volatile ( "vsqrt.f64 %P0, %P1\n" : "=w" (ret) : "w" (x)); return ret; } micropython-1.12/lib/libm_dbl/trunc.c000066400000000000000000000004571357706137100176410ustar00rootroot00000000000000#include "libm.h" double trunc(double x) { union {double f; uint64_t i;} u = {x}; int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12; uint64_t m; if (e >= 52 + 12) return x; if (e < 12) e = 1; m = -1ULL >> e; if ((u.i & m) == 0) return x; FORCE_EVAL(x + 0x1p120f); u.i &= ~m; return u.f; } micropython-1.12/lib/littlefs/000077500000000000000000000000001357706137100164165ustar00rootroot00000000000000micropython-1.12/lib/littlefs/README.md000066400000000000000000000011301357706137100176700ustar00rootroot00000000000000littlefs library ================ The upstream source for the files in this directory is https://github.com/ARMmbed/littlefs To generate the separate files with lfs1 and lfs2 prefixes run the following commands in the top-level directory of the littlefs repository (replace the version tags with the latest/desired ones, and set `$MPY_DIR`): git checkout v1.7.2 python2 ./scripts/prefix.py lfs1 cp lfs1*.[ch] $MPY_DIR/lib/littlefs git reset --hard HEAD git checkout v2.1.3 python2 ./scripts/prefix.py lfs2 cp lfs2*.[ch] $MPY_DIR/lib/littlefs git reset --hard HEAD micropython-1.12/lib/littlefs/lfs1.c000066400000000000000000002144451357706137100174410ustar00rootroot00000000000000/* * The little filesystem * * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #include "lfs1.h" #include "lfs1_util.h" #include /// Caching block device operations /// static int lfs1_cache_read(lfs1_t *lfs1, lfs1_cache_t *rcache, const lfs1_cache_t *pcache, lfs1_block_t block, lfs1_off_t off, void *buffer, lfs1_size_t size) { uint8_t *data = buffer; LFS1_ASSERT(block < lfs1->cfg->block_count); while (size > 0) { if (pcache && block == pcache->block && off >= pcache->off && off < pcache->off + lfs1->cfg->prog_size) { // is already in pcache? lfs1_size_t diff = lfs1_min(size, lfs1->cfg->prog_size - (off-pcache->off)); memcpy(data, &pcache->buffer[off-pcache->off], diff); data += diff; off += diff; size -= diff; continue; } if (block == rcache->block && off >= rcache->off && off < rcache->off + lfs1->cfg->read_size) { // is already in rcache? lfs1_size_t diff = lfs1_min(size, lfs1->cfg->read_size - (off-rcache->off)); memcpy(data, &rcache->buffer[off-rcache->off], diff); data += diff; off += diff; size -= diff; continue; } if (off % lfs1->cfg->read_size == 0 && size >= lfs1->cfg->read_size) { // bypass cache? lfs1_size_t diff = size - (size % lfs1->cfg->read_size); int err = lfs1->cfg->read(lfs1->cfg, block, off, data, diff); if (err) { return err; } data += diff; off += diff; size -= diff; continue; } // load to cache, first condition can no longer fail rcache->block = block; rcache->off = off - (off % lfs1->cfg->read_size); int err = lfs1->cfg->read(lfs1->cfg, rcache->block, rcache->off, rcache->buffer, lfs1->cfg->read_size); if (err) { return err; } } return 0; } static int lfs1_cache_cmp(lfs1_t *lfs1, lfs1_cache_t *rcache, const lfs1_cache_t *pcache, lfs1_block_t block, lfs1_off_t off, const void *buffer, lfs1_size_t size) { const uint8_t *data = buffer; for (lfs1_off_t i = 0; i < size; i++) { uint8_t c; int err = lfs1_cache_read(lfs1, rcache, pcache, block, off+i, &c, 1); if (err) { return err; } if (c != data[i]) { return false; } } return true; } static int lfs1_cache_crc(lfs1_t *lfs1, lfs1_cache_t *rcache, const lfs1_cache_t *pcache, lfs1_block_t block, lfs1_off_t off, lfs1_size_t size, uint32_t *crc) { for (lfs1_off_t i = 0; i < size; i++) { uint8_t c; int err = lfs1_cache_read(lfs1, rcache, pcache, block, off+i, &c, 1); if (err) { return err; } lfs1_crc(crc, &c, 1); } return 0; } static inline void lfs1_cache_drop(lfs1_t *lfs1, lfs1_cache_t *rcache) { // do not zero, cheaper if cache is readonly or only going to be // written with identical data (during relocates) (void)lfs1; rcache->block = 0xffffffff; } static inline void lfs1_cache_zero(lfs1_t *lfs1, lfs1_cache_t *pcache) { // zero to avoid information leak memset(pcache->buffer, 0xff, lfs1->cfg->prog_size); pcache->block = 0xffffffff; } static int lfs1_cache_flush(lfs1_t *lfs1, lfs1_cache_t *pcache, lfs1_cache_t *rcache) { if (pcache->block != 0xffffffff) { int err = lfs1->cfg->prog(lfs1->cfg, pcache->block, pcache->off, pcache->buffer, lfs1->cfg->prog_size); if (err) { return err; } if (rcache) { int res = lfs1_cache_cmp(lfs1, rcache, NULL, pcache->block, pcache->off, pcache->buffer, lfs1->cfg->prog_size); if (res < 0) { return res; } if (!res) { return LFS1_ERR_CORRUPT; } } lfs1_cache_zero(lfs1, pcache); } return 0; } static int lfs1_cache_prog(lfs1_t *lfs1, lfs1_cache_t *pcache, lfs1_cache_t *rcache, lfs1_block_t block, lfs1_off_t off, const void *buffer, lfs1_size_t size) { const uint8_t *data = buffer; LFS1_ASSERT(block < lfs1->cfg->block_count); while (size > 0) { if (block == pcache->block && off >= pcache->off && off < pcache->off + lfs1->cfg->prog_size) { // is already in pcache? lfs1_size_t diff = lfs1_min(size, lfs1->cfg->prog_size - (off-pcache->off)); memcpy(&pcache->buffer[off-pcache->off], data, diff); data += diff; off += diff; size -= diff; if (off % lfs1->cfg->prog_size == 0) { // eagerly flush out pcache if we fill up int err = lfs1_cache_flush(lfs1, pcache, rcache); if (err) { return err; } } continue; } // pcache must have been flushed, either by programming and // entire block or manually flushing the pcache LFS1_ASSERT(pcache->block == 0xffffffff); if (off % lfs1->cfg->prog_size == 0 && size >= lfs1->cfg->prog_size) { // bypass pcache? lfs1_size_t diff = size - (size % lfs1->cfg->prog_size); int err = lfs1->cfg->prog(lfs1->cfg, block, off, data, diff); if (err) { return err; } if (rcache) { int res = lfs1_cache_cmp(lfs1, rcache, NULL, block, off, data, diff); if (res < 0) { return res; } if (!res) { return LFS1_ERR_CORRUPT; } } data += diff; off += diff; size -= diff; continue; } // prepare pcache, first condition can no longer fail pcache->block = block; pcache->off = off - (off % lfs1->cfg->prog_size); } return 0; } /// General lfs1 block device operations /// static int lfs1_bd_read(lfs1_t *lfs1, lfs1_block_t block, lfs1_off_t off, void *buffer, lfs1_size_t size) { // if we ever do more than writes to alternating pairs, // this may need to consider pcache return lfs1_cache_read(lfs1, &lfs1->rcache, NULL, block, off, buffer, size); } static int lfs1_bd_prog(lfs1_t *lfs1, lfs1_block_t block, lfs1_off_t off, const void *buffer, lfs1_size_t size) { return lfs1_cache_prog(lfs1, &lfs1->pcache, NULL, block, off, buffer, size); } static int lfs1_bd_cmp(lfs1_t *lfs1, lfs1_block_t block, lfs1_off_t off, const void *buffer, lfs1_size_t size) { return lfs1_cache_cmp(lfs1, &lfs1->rcache, NULL, block, off, buffer, size); } static int lfs1_bd_crc(lfs1_t *lfs1, lfs1_block_t block, lfs1_off_t off, lfs1_size_t size, uint32_t *crc) { return lfs1_cache_crc(lfs1, &lfs1->rcache, NULL, block, off, size, crc); } static int lfs1_bd_erase(lfs1_t *lfs1, lfs1_block_t block) { return lfs1->cfg->erase(lfs1->cfg, block); } static int lfs1_bd_sync(lfs1_t *lfs1) { lfs1_cache_drop(lfs1, &lfs1->rcache); int err = lfs1_cache_flush(lfs1, &lfs1->pcache, NULL); if (err) { return err; } return lfs1->cfg->sync(lfs1->cfg); } /// Internal operations predeclared here /// int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data); static int lfs1_pred(lfs1_t *lfs1, const lfs1_block_t dir[2], lfs1_dir_t *pdir); static int lfs1_parent(lfs1_t *lfs1, const lfs1_block_t dir[2], lfs1_dir_t *parent, lfs1_entry_t *entry); static int lfs1_moved(lfs1_t *lfs1, const void *e); static int lfs1_relocate(lfs1_t *lfs1, const lfs1_block_t oldpair[2], const lfs1_block_t newpair[2]); int lfs1_deorphan(lfs1_t *lfs1); /// Block allocator /// static int lfs1_alloc_lookahead(void *p, lfs1_block_t block) { lfs1_t *lfs1 = p; lfs1_block_t off = ((block - lfs1->free.off) + lfs1->cfg->block_count) % lfs1->cfg->block_count; if (off < lfs1->free.size) { lfs1->free.buffer[off / 32] |= 1U << (off % 32); } return 0; } static int lfs1_alloc(lfs1_t *lfs1, lfs1_block_t *block) { while (true) { while (lfs1->free.i != lfs1->free.size) { lfs1_block_t off = lfs1->free.i; lfs1->free.i += 1; lfs1->free.ack -= 1; if (!(lfs1->free.buffer[off / 32] & (1U << (off % 32)))) { // found a free block *block = (lfs1->free.off + off) % lfs1->cfg->block_count; // eagerly find next off so an alloc ack can // discredit old lookahead blocks while (lfs1->free.i != lfs1->free.size && (lfs1->free.buffer[lfs1->free.i / 32] & (1U << (lfs1->free.i % 32)))) { lfs1->free.i += 1; lfs1->free.ack -= 1; } return 0; } } // check if we have looked at all blocks since last ack if (lfs1->free.ack == 0) { LFS1_WARN("No more free space %" PRIu32, lfs1->free.i + lfs1->free.off); return LFS1_ERR_NOSPC; } lfs1->free.off = (lfs1->free.off + lfs1->free.size) % lfs1->cfg->block_count; lfs1->free.size = lfs1_min(lfs1->cfg->lookahead, lfs1->free.ack); lfs1->free.i = 0; // find mask of free blocks from tree memset(lfs1->free.buffer, 0, lfs1->cfg->lookahead/8); int err = lfs1_traverse(lfs1, lfs1_alloc_lookahead, lfs1); if (err) { return err; } } } static void lfs1_alloc_ack(lfs1_t *lfs1) { lfs1->free.ack = lfs1->cfg->block_count; } /// Endian swapping functions /// static void lfs1_dir_fromle32(struct lfs1_disk_dir *d) { d->rev = lfs1_fromle32(d->rev); d->size = lfs1_fromle32(d->size); d->tail[0] = lfs1_fromle32(d->tail[0]); d->tail[1] = lfs1_fromle32(d->tail[1]); } static void lfs1_dir_tole32(struct lfs1_disk_dir *d) { d->rev = lfs1_tole32(d->rev); d->size = lfs1_tole32(d->size); d->tail[0] = lfs1_tole32(d->tail[0]); d->tail[1] = lfs1_tole32(d->tail[1]); } static void lfs1_entry_fromle32(struct lfs1_disk_entry *d) { d->u.dir[0] = lfs1_fromle32(d->u.dir[0]); d->u.dir[1] = lfs1_fromle32(d->u.dir[1]); } static void lfs1_entry_tole32(struct lfs1_disk_entry *d) { d->u.dir[0] = lfs1_tole32(d->u.dir[0]); d->u.dir[1] = lfs1_tole32(d->u.dir[1]); } static void lfs1_superblock_fromle32(struct lfs1_disk_superblock *d) { d->root[0] = lfs1_fromle32(d->root[0]); d->root[1] = lfs1_fromle32(d->root[1]); d->block_size = lfs1_fromle32(d->block_size); d->block_count = lfs1_fromle32(d->block_count); d->version = lfs1_fromle32(d->version); } static void lfs1_superblock_tole32(struct lfs1_disk_superblock *d) { d->root[0] = lfs1_tole32(d->root[0]); d->root[1] = lfs1_tole32(d->root[1]); d->block_size = lfs1_tole32(d->block_size); d->block_count = lfs1_tole32(d->block_count); d->version = lfs1_tole32(d->version); } /// Metadata pair and directory operations /// static inline void lfs1_pairswap(lfs1_block_t pair[2]) { lfs1_block_t t = pair[0]; pair[0] = pair[1]; pair[1] = t; } static inline bool lfs1_pairisnull(const lfs1_block_t pair[2]) { return pair[0] == 0xffffffff || pair[1] == 0xffffffff; } static inline int lfs1_paircmp( const lfs1_block_t paira[2], const lfs1_block_t pairb[2]) { return !(paira[0] == pairb[0] || paira[1] == pairb[1] || paira[0] == pairb[1] || paira[1] == pairb[0]); } static inline bool lfs1_pairsync( const lfs1_block_t paira[2], const lfs1_block_t pairb[2]) { return (paira[0] == pairb[0] && paira[1] == pairb[1]) || (paira[0] == pairb[1] && paira[1] == pairb[0]); } static inline lfs1_size_t lfs1_entry_size(const lfs1_entry_t *entry) { return 4 + entry->d.elen + entry->d.alen + entry->d.nlen; } static int lfs1_dir_alloc(lfs1_t *lfs1, lfs1_dir_t *dir) { // allocate pair of dir blocks for (int i = 0; i < 2; i++) { int err = lfs1_alloc(lfs1, &dir->pair[i]); if (err) { return err; } } // rather than clobbering one of the blocks we just pretend // the revision may be valid int err = lfs1_bd_read(lfs1, dir->pair[0], 0, &dir->d.rev, 4); if (err && err != LFS1_ERR_CORRUPT) { return err; } if (err != LFS1_ERR_CORRUPT) { dir->d.rev = lfs1_fromle32(dir->d.rev); } // set defaults dir->d.rev += 1; dir->d.size = sizeof(dir->d)+4; dir->d.tail[0] = 0xffffffff; dir->d.tail[1] = 0xffffffff; dir->off = sizeof(dir->d); // don't write out yet, let caller take care of that return 0; } static int lfs1_dir_fetch(lfs1_t *lfs1, lfs1_dir_t *dir, const lfs1_block_t pair[2]) { // copy out pair, otherwise may be aliasing dir const lfs1_block_t tpair[2] = {pair[0], pair[1]}; bool valid = false; // check both blocks for the most recent revision for (int i = 0; i < 2; i++) { struct lfs1_disk_dir test; int err = lfs1_bd_read(lfs1, tpair[i], 0, &test, sizeof(test)); lfs1_dir_fromle32(&test); if (err) { if (err == LFS1_ERR_CORRUPT) { continue; } return err; } if (valid && lfs1_scmp(test.rev, dir->d.rev) < 0) { continue; } if ((0x7fffffff & test.size) < sizeof(test)+4 || (0x7fffffff & test.size) > lfs1->cfg->block_size) { continue; } uint32_t crc = 0xffffffff; lfs1_dir_tole32(&test); lfs1_crc(&crc, &test, sizeof(test)); lfs1_dir_fromle32(&test); err = lfs1_bd_crc(lfs1, tpair[i], sizeof(test), (0x7fffffff & test.size) - sizeof(test), &crc); if (err) { if (err == LFS1_ERR_CORRUPT) { continue; } return err; } if (crc != 0) { continue; } valid = true; // setup dir in case it's valid dir->pair[0] = tpair[(i+0) % 2]; dir->pair[1] = tpair[(i+1) % 2]; dir->off = sizeof(dir->d); dir->d = test; } if (!valid) { LFS1_ERROR("Corrupted dir pair at %" PRIu32 " %" PRIu32 , tpair[0], tpair[1]); return LFS1_ERR_CORRUPT; } return 0; } struct lfs1_region { lfs1_off_t oldoff; lfs1_size_t oldlen; const void *newdata; lfs1_size_t newlen; }; static int lfs1_dir_commit(lfs1_t *lfs1, lfs1_dir_t *dir, const struct lfs1_region *regions, int count) { // increment revision count dir->d.rev += 1; // keep pairs in order such that pair[0] is most recent lfs1_pairswap(dir->pair); for (int i = 0; i < count; i++) { dir->d.size += regions[i].newlen - regions[i].oldlen; } const lfs1_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; bool relocated = false; while (true) { if (true) { int err = lfs1_bd_erase(lfs1, dir->pair[0]); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } uint32_t crc = 0xffffffff; lfs1_dir_tole32(&dir->d); lfs1_crc(&crc, &dir->d, sizeof(dir->d)); err = lfs1_bd_prog(lfs1, dir->pair[0], 0, &dir->d, sizeof(dir->d)); lfs1_dir_fromle32(&dir->d); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } int i = 0; lfs1_off_t oldoff = sizeof(dir->d); lfs1_off_t newoff = sizeof(dir->d); while (newoff < (0x7fffffff & dir->d.size)-4) { if (i < count && regions[i].oldoff == oldoff) { lfs1_crc(&crc, regions[i].newdata, regions[i].newlen); err = lfs1_bd_prog(lfs1, dir->pair[0], newoff, regions[i].newdata, regions[i].newlen); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } oldoff += regions[i].oldlen; newoff += regions[i].newlen; i += 1; } else { uint8_t data; err = lfs1_bd_read(lfs1, oldpair[1], oldoff, &data, 1); if (err) { return err; } lfs1_crc(&crc, &data, 1); err = lfs1_bd_prog(lfs1, dir->pair[0], newoff, &data, 1); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } oldoff += 1; newoff += 1; } } crc = lfs1_tole32(crc); err = lfs1_bd_prog(lfs1, dir->pair[0], newoff, &crc, 4); crc = lfs1_fromle32(crc); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } err = lfs1_bd_sync(lfs1); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } // successful commit, check checksum to make sure uint32_t ncrc = 0xffffffff; err = lfs1_bd_crc(lfs1, dir->pair[0], 0, (0x7fffffff & dir->d.size)-4, &ncrc); if (err) { return err; } if (ncrc != crc) { goto relocate; } } break; relocate: //commit was corrupted LFS1_DEBUG("Bad block at %" PRIu32, dir->pair[0]); // drop caches and prepare to relocate block relocated = true; lfs1_cache_drop(lfs1, &lfs1->pcache); // can't relocate superblock, filesystem is now frozen if (lfs1_paircmp(oldpair, (const lfs1_block_t[2]){0, 1}) == 0) { LFS1_WARN("Superblock %" PRIu32 " has become unwritable", oldpair[0]); return LFS1_ERR_CORRUPT; } // relocate half of pair int err = lfs1_alloc(lfs1, &dir->pair[0]); if (err) { return err; } } if (relocated) { // update references if we relocated LFS1_DEBUG("Relocating %" PRIu32 " %" PRIu32 " to %" PRIu32 " %" PRIu32, oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); int err = lfs1_relocate(lfs1, oldpair, dir->pair); if (err) { return err; } } // shift over any directories that are affected for (lfs1_dir_t *d = lfs1->dirs; d; d = d->next) { if (lfs1_paircmp(d->pair, dir->pair) == 0) { d->pair[0] = dir->pair[0]; d->pair[1] = dir->pair[1]; } } return 0; } static int lfs1_dir_update(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry, const void *data) { lfs1_entry_tole32(&entry->d); int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){ {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)}, {entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen} }, data ? 2 : 1); lfs1_entry_fromle32(&entry->d); return err; } static int lfs1_dir_append(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry, const void *data) { // check if we fit, if top bit is set we do not and move on while (true) { if (dir->d.size + lfs1_entry_size(entry) <= lfs1->cfg->block_size) { entry->off = dir->d.size - 4; lfs1_entry_tole32(&entry->d); int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){ {entry->off, 0, &entry->d, sizeof(entry->d)}, {entry->off, 0, data, entry->d.nlen} }, 2); lfs1_entry_fromle32(&entry->d); return err; } // we need to allocate a new dir block if (!(0x80000000 & dir->d.size)) { lfs1_dir_t olddir = *dir; int err = lfs1_dir_alloc(lfs1, dir); if (err) { return err; } dir->d.tail[0] = olddir.d.tail[0]; dir->d.tail[1] = olddir.d.tail[1]; entry->off = dir->d.size - 4; lfs1_entry_tole32(&entry->d); err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){ {entry->off, 0, &entry->d, sizeof(entry->d)}, {entry->off, 0, data, entry->d.nlen} }, 2); lfs1_entry_fromle32(&entry->d); if (err) { return err; } olddir.d.size |= 0x80000000; olddir.d.tail[0] = dir->pair[0]; olddir.d.tail[1] = dir->pair[1]; return lfs1_dir_commit(lfs1, &olddir, NULL, 0); } int err = lfs1_dir_fetch(lfs1, dir, dir->d.tail); if (err) { return err; } } } static int lfs1_dir_remove(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry) { // check if we should just drop the directory block if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + lfs1_entry_size(entry)) { lfs1_dir_t pdir; int res = lfs1_pred(lfs1, dir->pair, &pdir); if (res < 0) { return res; } if (pdir.d.size & 0x80000000) { pdir.d.size &= dir->d.size | 0x7fffffff; pdir.d.tail[0] = dir->d.tail[0]; pdir.d.tail[1] = dir->d.tail[1]; return lfs1_dir_commit(lfs1, &pdir, NULL, 0); } } // shift out the entry int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){ {entry->off, lfs1_entry_size(entry), NULL, 0}, }, 1); if (err) { return err; } // shift over any files/directories that are affected for (lfs1_file_t *f = lfs1->files; f; f = f->next) { if (lfs1_paircmp(f->pair, dir->pair) == 0) { if (f->poff == entry->off) { f->pair[0] = 0xffffffff; f->pair[1] = 0xffffffff; } else if (f->poff > entry->off) { f->poff -= lfs1_entry_size(entry); } } } for (lfs1_dir_t *d = lfs1->dirs; d; d = d->next) { if (lfs1_paircmp(d->pair, dir->pair) == 0) { if (d->off > entry->off) { d->off -= lfs1_entry_size(entry); d->pos -= lfs1_entry_size(entry); } } } return 0; } static int lfs1_dir_next(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry) { while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) { if (!(0x80000000 & dir->d.size)) { entry->off = dir->off; return LFS1_ERR_NOENT; } int err = lfs1_dir_fetch(lfs1, dir, dir->d.tail); if (err) { return err; } dir->off = sizeof(dir->d); dir->pos += sizeof(dir->d) + 4; } int err = lfs1_bd_read(lfs1, dir->pair[0], dir->off, &entry->d, sizeof(entry->d)); lfs1_entry_fromle32(&entry->d); if (err) { return err; } entry->off = dir->off; dir->off += lfs1_entry_size(entry); dir->pos += lfs1_entry_size(entry); return 0; } static int lfs1_dir_find(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry, const char **path) { const char *pathname = *path; size_t pathlen; entry->d.type = LFS1_TYPE_DIR; entry->d.elen = sizeof(entry->d) - 4; entry->d.alen = 0; entry->d.nlen = 0; entry->d.u.dir[0] = lfs1->root[0]; entry->d.u.dir[1] = lfs1->root[1]; while (true) { nextname: // skip slashes pathname += strspn(pathname, "/"); pathlen = strcspn(pathname, "/"); // skip '.' and root '..' if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) || (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) { pathname += pathlen; goto nextname; } // skip if matched by '..' in name const char *suffix = pathname + pathlen; size_t sufflen; int depth = 1; while (true) { suffix += strspn(suffix, "/"); sufflen = strcspn(suffix, "/"); if (sufflen == 0) { break; } if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { depth -= 1; if (depth == 0) { pathname = suffix + sufflen; goto nextname; } } else { depth += 1; } suffix += sufflen; } // found path if (pathname[0] == '\0') { return 0; } // update what we've found *path = pathname; // continue on if we hit a directory if (entry->d.type != LFS1_TYPE_DIR) { return LFS1_ERR_NOTDIR; } int err = lfs1_dir_fetch(lfs1, dir, entry->d.u.dir); if (err) { return err; } // find entry matching name while (true) { err = lfs1_dir_next(lfs1, dir, entry); if (err) { return err; } if (((0x7f & entry->d.type) != LFS1_TYPE_REG && (0x7f & entry->d.type) != LFS1_TYPE_DIR) || entry->d.nlen != pathlen) { continue; } int res = lfs1_bd_cmp(lfs1, dir->pair[0], entry->off + 4+entry->d.elen+entry->d.alen, pathname, pathlen); if (res < 0) { return res; } // found match if (res) { break; } } // check that entry has not been moved if (!lfs1->moving && entry->d.type & 0x80) { int moved = lfs1_moved(lfs1, &entry->d.u); if (moved < 0 || moved) { return (moved < 0) ? moved : LFS1_ERR_NOENT; } entry->d.type &= ~0x80; } // to next name pathname += pathlen; } } /// Top level directory operations /// int lfs1_mkdir(lfs1_t *lfs1, const char *path) { // deorphan if we haven't yet, needed at most once after poweron if (!lfs1->deorphaned) { int err = lfs1_deorphan(lfs1); if (err) { return err; } } // fetch parent directory lfs1_dir_t cwd; lfs1_entry_t entry; int err = lfs1_dir_find(lfs1, &cwd, &entry, &path); if (err != LFS1_ERR_NOENT || strchr(path, '/') != NULL) { return err ? err : LFS1_ERR_EXIST; } // build up new directory lfs1_alloc_ack(lfs1); lfs1_dir_t dir; err = lfs1_dir_alloc(lfs1, &dir); if (err) { return err; } dir.d.tail[0] = cwd.d.tail[0]; dir.d.tail[1] = cwd.d.tail[1]; err = lfs1_dir_commit(lfs1, &dir, NULL, 0); if (err) { return err; } entry.d.type = LFS1_TYPE_DIR; entry.d.elen = sizeof(entry.d) - 4; entry.d.alen = 0; entry.d.nlen = strlen(path); entry.d.u.dir[0] = dir.pair[0]; entry.d.u.dir[1] = dir.pair[1]; cwd.d.tail[0] = dir.pair[0]; cwd.d.tail[1] = dir.pair[1]; err = lfs1_dir_append(lfs1, &cwd, &entry, path); if (err) { return err; } lfs1_alloc_ack(lfs1); return 0; } int lfs1_dir_open(lfs1_t *lfs1, lfs1_dir_t *dir, const char *path) { dir->pair[0] = lfs1->root[0]; dir->pair[1] = lfs1->root[1]; lfs1_entry_t entry; int err = lfs1_dir_find(lfs1, dir, &entry, &path); if (err) { return err; } else if (entry.d.type != LFS1_TYPE_DIR) { return LFS1_ERR_NOTDIR; } err = lfs1_dir_fetch(lfs1, dir, entry.d.u.dir); if (err) { return err; } // setup head dir // special offset for '.' and '..' dir->head[0] = dir->pair[0]; dir->head[1] = dir->pair[1]; dir->pos = sizeof(dir->d) - 2; dir->off = sizeof(dir->d); // add to list of directories dir->next = lfs1->dirs; lfs1->dirs = dir; return 0; } int lfs1_dir_close(lfs1_t *lfs1, lfs1_dir_t *dir) { // remove from list of directories for (lfs1_dir_t **p = &lfs1->dirs; *p; p = &(*p)->next) { if (*p == dir) { *p = dir->next; break; } } return 0; } int lfs1_dir_read(lfs1_t *lfs1, lfs1_dir_t *dir, struct lfs1_info *info) { memset(info, 0, sizeof(*info)); // special offset for '.' and '..' if (dir->pos == sizeof(dir->d) - 2) { info->type = LFS1_TYPE_DIR; strcpy(info->name, "."); dir->pos += 1; return 1; } else if (dir->pos == sizeof(dir->d) - 1) { info->type = LFS1_TYPE_DIR; strcpy(info->name, ".."); dir->pos += 1; return 1; } lfs1_entry_t entry; while (true) { int err = lfs1_dir_next(lfs1, dir, &entry); if (err) { return (err == LFS1_ERR_NOENT) ? 0 : err; } if ((0x7f & entry.d.type) != LFS1_TYPE_REG && (0x7f & entry.d.type) != LFS1_TYPE_DIR) { continue; } // check that entry has not been moved if (entry.d.type & 0x80) { int moved = lfs1_moved(lfs1, &entry.d.u); if (moved < 0) { return moved; } if (moved) { continue; } entry.d.type &= ~0x80; } break; } info->type = entry.d.type; if (info->type == LFS1_TYPE_REG) { info->size = entry.d.u.file.size; } int err = lfs1_bd_read(lfs1, dir->pair[0], entry.off + 4+entry.d.elen+entry.d.alen, info->name, entry.d.nlen); if (err) { return err; } return 1; } int lfs1_dir_seek(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_off_t off) { // simply walk from head dir int err = lfs1_dir_rewind(lfs1, dir); if (err) { return err; } dir->pos = off; while (off > (0x7fffffff & dir->d.size)) { off -= 0x7fffffff & dir->d.size; if (!(0x80000000 & dir->d.size)) { return LFS1_ERR_INVAL; } err = lfs1_dir_fetch(lfs1, dir, dir->d.tail); if (err) { return err; } } dir->off = off; return 0; } lfs1_soff_t lfs1_dir_tell(lfs1_t *lfs1, lfs1_dir_t *dir) { (void)lfs1; return dir->pos; } int lfs1_dir_rewind(lfs1_t *lfs1, lfs1_dir_t *dir) { // reload the head dir int err = lfs1_dir_fetch(lfs1, dir, dir->head); if (err) { return err; } dir->pair[0] = dir->head[0]; dir->pair[1] = dir->head[1]; dir->pos = sizeof(dir->d) - 2; dir->off = sizeof(dir->d); return 0; } /// File index list operations /// static int lfs1_ctz_index(lfs1_t *lfs1, lfs1_off_t *off) { lfs1_off_t size = *off; lfs1_off_t b = lfs1->cfg->block_size - 2*4; lfs1_off_t i = size / b; if (i == 0) { return 0; } i = (size - 4*(lfs1_popc(i-1)+2)) / b; *off = size - b*i - 4*lfs1_popc(i); return i; } static int lfs1_ctz_find(lfs1_t *lfs1, lfs1_cache_t *rcache, const lfs1_cache_t *pcache, lfs1_block_t head, lfs1_size_t size, lfs1_size_t pos, lfs1_block_t *block, lfs1_off_t *off) { if (size == 0) { *block = 0xffffffff; *off = 0; return 0; } lfs1_off_t current = lfs1_ctz_index(lfs1, &(lfs1_off_t){size-1}); lfs1_off_t target = lfs1_ctz_index(lfs1, &pos); while (current > target) { lfs1_size_t skip = lfs1_min( lfs1_npw2(current-target+1) - 1, lfs1_ctz(current)); int err = lfs1_cache_read(lfs1, rcache, pcache, head, 4*skip, &head, 4); head = lfs1_fromle32(head); if (err) { return err; } LFS1_ASSERT(head >= 2 && head <= lfs1->cfg->block_count); current -= 1 << skip; } *block = head; *off = pos; return 0; } static int lfs1_ctz_extend(lfs1_t *lfs1, lfs1_cache_t *rcache, lfs1_cache_t *pcache, lfs1_block_t head, lfs1_size_t size, lfs1_block_t *block, lfs1_off_t *off) { while (true) { // go ahead and grab a block lfs1_block_t nblock; int err = lfs1_alloc(lfs1, &nblock); if (err) { return err; } LFS1_ASSERT(nblock >= 2 && nblock <= lfs1->cfg->block_count); if (true) { err = lfs1_bd_erase(lfs1, nblock); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } if (size == 0) { *block = nblock; *off = 0; return 0; } size -= 1; lfs1_off_t index = lfs1_ctz_index(lfs1, &size); size += 1; // just copy out the last block if it is incomplete if (size != lfs1->cfg->block_size) { for (lfs1_off_t i = 0; i < size; i++) { uint8_t data; err = lfs1_cache_read(lfs1, rcache, NULL, head, i, &data, 1); if (err) { return err; } err = lfs1_cache_prog(lfs1, pcache, rcache, nblock, i, &data, 1); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } } *block = nblock; *off = size; return 0; } // append block index += 1; lfs1_size_t skips = lfs1_ctz(index) + 1; for (lfs1_off_t i = 0; i < skips; i++) { head = lfs1_tole32(head); err = lfs1_cache_prog(lfs1, pcache, rcache, nblock, 4*i, &head, 4); head = lfs1_fromle32(head); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } if (i != skips-1) { err = lfs1_cache_read(lfs1, rcache, NULL, head, 4*i, &head, 4); head = lfs1_fromle32(head); if (err) { return err; } } LFS1_ASSERT(head >= 2 && head <= lfs1->cfg->block_count); } *block = nblock; *off = 4*skips; return 0; } relocate: LFS1_DEBUG("Bad block at %" PRIu32, nblock); // just clear cache and try a new block lfs1_cache_drop(lfs1, &lfs1->pcache); } } static int lfs1_ctz_traverse(lfs1_t *lfs1, lfs1_cache_t *rcache, const lfs1_cache_t *pcache, lfs1_block_t head, lfs1_size_t size, int (*cb)(void*, lfs1_block_t), void *data) { if (size == 0) { return 0; } lfs1_off_t index = lfs1_ctz_index(lfs1, &(lfs1_off_t){size-1}); while (true) { int err = cb(data, head); if (err) { return err; } if (index == 0) { return 0; } lfs1_block_t heads[2]; int count = 2 - (index & 1); err = lfs1_cache_read(lfs1, rcache, pcache, head, 0, &heads, count*4); heads[0] = lfs1_fromle32(heads[0]); heads[1] = lfs1_fromle32(heads[1]); if (err) { return err; } for (int i = 0; i < count-1; i++) { err = cb(data, heads[i]); if (err) { return err; } } head = heads[count-1]; index -= count; } } /// Top level file operations /// int lfs1_file_opencfg(lfs1_t *lfs1, lfs1_file_t *file, const char *path, int flags, const struct lfs1_file_config *cfg) { // deorphan if we haven't yet, needed at most once after poweron if ((flags & 3) != LFS1_O_RDONLY && !lfs1->deorphaned) { int err = lfs1_deorphan(lfs1); if (err) { return err; } } // allocate entry for file if it doesn't exist lfs1_dir_t cwd; lfs1_entry_t entry; int err = lfs1_dir_find(lfs1, &cwd, &entry, &path); if (err && (err != LFS1_ERR_NOENT || strchr(path, '/') != NULL)) { return err; } if (err == LFS1_ERR_NOENT) { if (!(flags & LFS1_O_CREAT)) { return LFS1_ERR_NOENT; } // create entry to remember name entry.d.type = LFS1_TYPE_REG; entry.d.elen = sizeof(entry.d) - 4; entry.d.alen = 0; entry.d.nlen = strlen(path); entry.d.u.file.head = 0xffffffff; entry.d.u.file.size = 0; err = lfs1_dir_append(lfs1, &cwd, &entry, path); if (err) { return err; } } else if (entry.d.type == LFS1_TYPE_DIR) { return LFS1_ERR_ISDIR; } else if (flags & LFS1_O_EXCL) { return LFS1_ERR_EXIST; } // setup file struct file->cfg = cfg; file->pair[0] = cwd.pair[0]; file->pair[1] = cwd.pair[1]; file->poff = entry.off; file->head = entry.d.u.file.head; file->size = entry.d.u.file.size; file->flags = flags; file->pos = 0; if (flags & LFS1_O_TRUNC) { if (file->size != 0) { file->flags |= LFS1_F_DIRTY; } file->head = 0xffffffff; file->size = 0; } // allocate buffer if needed file->cache.block = 0xffffffff; if (file->cfg && file->cfg->buffer) { file->cache.buffer = file->cfg->buffer; } else if (lfs1->cfg->file_buffer) { if (lfs1->files) { // already in use return LFS1_ERR_NOMEM; } file->cache.buffer = lfs1->cfg->file_buffer; } else if ((file->flags & 3) == LFS1_O_RDONLY) { file->cache.buffer = lfs1_malloc(lfs1->cfg->read_size); if (!file->cache.buffer) { return LFS1_ERR_NOMEM; } } else { file->cache.buffer = lfs1_malloc(lfs1->cfg->prog_size); if (!file->cache.buffer) { return LFS1_ERR_NOMEM; } } // zero to avoid information leak lfs1_cache_drop(lfs1, &file->cache); if ((file->flags & 3) != LFS1_O_RDONLY) { lfs1_cache_zero(lfs1, &file->cache); } // add to list of files file->next = lfs1->files; lfs1->files = file; return 0; } int lfs1_file_open(lfs1_t *lfs1, lfs1_file_t *file, const char *path, int flags) { return lfs1_file_opencfg(lfs1, file, path, flags, NULL); } int lfs1_file_close(lfs1_t *lfs1, lfs1_file_t *file) { int err = lfs1_file_sync(lfs1, file); // remove from list of files for (lfs1_file_t **p = &lfs1->files; *p; p = &(*p)->next) { if (*p == file) { *p = file->next; break; } } // clean up memory if (!(file->cfg && file->cfg->buffer) && !lfs1->cfg->file_buffer) { lfs1_free(file->cache.buffer); } return err; } static int lfs1_file_relocate(lfs1_t *lfs1, lfs1_file_t *file) { relocate: LFS1_DEBUG("Bad block at %" PRIu32, file->block); // just relocate what exists into new block lfs1_block_t nblock; int err = lfs1_alloc(lfs1, &nblock); if (err) { return err; } err = lfs1_bd_erase(lfs1, nblock); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } // either read from dirty cache or disk for (lfs1_off_t i = 0; i < file->off; i++) { uint8_t data; err = lfs1_cache_read(lfs1, &lfs1->rcache, &file->cache, file->block, i, &data, 1); if (err) { return err; } err = lfs1_cache_prog(lfs1, &lfs1->pcache, &lfs1->rcache, nblock, i, &data, 1); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } } // copy over new state of file memcpy(file->cache.buffer, lfs1->pcache.buffer, lfs1->cfg->prog_size); file->cache.block = lfs1->pcache.block; file->cache.off = lfs1->pcache.off; lfs1_cache_zero(lfs1, &lfs1->pcache); file->block = nblock; return 0; } static int lfs1_file_flush(lfs1_t *lfs1, lfs1_file_t *file) { if (file->flags & LFS1_F_READING) { // just drop read cache lfs1_cache_drop(lfs1, &file->cache); file->flags &= ~LFS1_F_READING; } if (file->flags & LFS1_F_WRITING) { lfs1_off_t pos = file->pos; // copy over anything after current branch lfs1_file_t orig = { .head = file->head, .size = file->size, .flags = LFS1_O_RDONLY, .pos = file->pos, .cache = lfs1->rcache, }; lfs1_cache_drop(lfs1, &lfs1->rcache); while (file->pos < file->size) { // copy over a byte at a time, leave it up to caching // to make this efficient uint8_t data; lfs1_ssize_t res = lfs1_file_read(lfs1, &orig, &data, 1); if (res < 0) { return res; } res = lfs1_file_write(lfs1, file, &data, 1); if (res < 0) { return res; } // keep our reference to the rcache in sync if (lfs1->rcache.block != 0xffffffff) { lfs1_cache_drop(lfs1, &orig.cache); lfs1_cache_drop(lfs1, &lfs1->rcache); } } // write out what we have while (true) { int err = lfs1_cache_flush(lfs1, &file->cache, &lfs1->rcache); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } return err; } break; relocate: err = lfs1_file_relocate(lfs1, file); if (err) { return err; } } // actual file updates file->head = file->block; file->size = file->pos; file->flags &= ~LFS1_F_WRITING; file->flags |= LFS1_F_DIRTY; file->pos = pos; } return 0; } int lfs1_file_sync(lfs1_t *lfs1, lfs1_file_t *file) { int err = lfs1_file_flush(lfs1, file); if (err) { return err; } if ((file->flags & LFS1_F_DIRTY) && !(file->flags & LFS1_F_ERRED) && !lfs1_pairisnull(file->pair)) { // update dir entry lfs1_dir_t cwd; err = lfs1_dir_fetch(lfs1, &cwd, file->pair); if (err) { return err; } lfs1_entry_t entry = {.off = file->poff}; err = lfs1_bd_read(lfs1, cwd.pair[0], entry.off, &entry.d, sizeof(entry.d)); lfs1_entry_fromle32(&entry.d); if (err) { return err; } LFS1_ASSERT(entry.d.type == LFS1_TYPE_REG); entry.d.u.file.head = file->head; entry.d.u.file.size = file->size; err = lfs1_dir_update(lfs1, &cwd, &entry, NULL); if (err) { return err; } file->flags &= ~LFS1_F_DIRTY; } return 0; } lfs1_ssize_t lfs1_file_read(lfs1_t *lfs1, lfs1_file_t *file, void *buffer, lfs1_size_t size) { uint8_t *data = buffer; lfs1_size_t nsize = size; if ((file->flags & 3) == LFS1_O_WRONLY) { return LFS1_ERR_BADF; } if (file->flags & LFS1_F_WRITING) { // flush out any writes int err = lfs1_file_flush(lfs1, file); if (err) { return err; } } if (file->pos >= file->size) { // eof if past end return 0; } size = lfs1_min(size, file->size - file->pos); nsize = size; while (nsize > 0) { // check if we need a new block if (!(file->flags & LFS1_F_READING) || file->off == lfs1->cfg->block_size) { int err = lfs1_ctz_find(lfs1, &file->cache, NULL, file->head, file->size, file->pos, &file->block, &file->off); if (err) { return err; } file->flags |= LFS1_F_READING; } // read as much as we can in current block lfs1_size_t diff = lfs1_min(nsize, lfs1->cfg->block_size - file->off); int err = lfs1_cache_read(lfs1, &file->cache, NULL, file->block, file->off, data, diff); if (err) { return err; } file->pos += diff; file->off += diff; data += diff; nsize -= diff; } return size; } lfs1_ssize_t lfs1_file_write(lfs1_t *lfs1, lfs1_file_t *file, const void *buffer, lfs1_size_t size) { const uint8_t *data = buffer; lfs1_size_t nsize = size; if ((file->flags & 3) == LFS1_O_RDONLY) { return LFS1_ERR_BADF; } if (file->flags & LFS1_F_READING) { // drop any reads int err = lfs1_file_flush(lfs1, file); if (err) { return err; } } if ((file->flags & LFS1_O_APPEND) && file->pos < file->size) { file->pos = file->size; } if (file->pos + size > LFS1_FILE_MAX) { // larger than file limit? return LFS1_ERR_FBIG; } if (!(file->flags & LFS1_F_WRITING) && file->pos > file->size) { // fill with zeros lfs1_off_t pos = file->pos; file->pos = file->size; while (file->pos < pos) { lfs1_ssize_t res = lfs1_file_write(lfs1, file, &(uint8_t){0}, 1); if (res < 0) { return res; } } } while (nsize > 0) { // check if we need a new block if (!(file->flags & LFS1_F_WRITING) || file->off == lfs1->cfg->block_size) { if (!(file->flags & LFS1_F_WRITING) && file->pos > 0) { // find out which block we're extending from int err = lfs1_ctz_find(lfs1, &file->cache, NULL, file->head, file->size, file->pos-1, &file->block, &file->off); if (err) { file->flags |= LFS1_F_ERRED; return err; } // mark cache as dirty since we may have read data into it lfs1_cache_zero(lfs1, &file->cache); } // extend file with new blocks lfs1_alloc_ack(lfs1); int err = lfs1_ctz_extend(lfs1, &lfs1->rcache, &file->cache, file->block, file->pos, &file->block, &file->off); if (err) { file->flags |= LFS1_F_ERRED; return err; } file->flags |= LFS1_F_WRITING; } // program as much as we can in current block lfs1_size_t diff = lfs1_min(nsize, lfs1->cfg->block_size - file->off); while (true) { int err = lfs1_cache_prog(lfs1, &file->cache, &lfs1->rcache, file->block, file->off, data, diff); if (err) { if (err == LFS1_ERR_CORRUPT) { goto relocate; } file->flags |= LFS1_F_ERRED; return err; } break; relocate: err = lfs1_file_relocate(lfs1, file); if (err) { file->flags |= LFS1_F_ERRED; return err; } } file->pos += diff; file->off += diff; data += diff; nsize -= diff; lfs1_alloc_ack(lfs1); } file->flags &= ~LFS1_F_ERRED; return size; } lfs1_soff_t lfs1_file_seek(lfs1_t *lfs1, lfs1_file_t *file, lfs1_soff_t off, int whence) { // write out everything beforehand, may be noop if rdonly int err = lfs1_file_flush(lfs1, file); if (err) { return err; } // find new pos lfs1_soff_t npos = file->pos; if (whence == LFS1_SEEK_SET) { npos = off; } else if (whence == LFS1_SEEK_CUR) { npos = file->pos + off; } else if (whence == LFS1_SEEK_END) { npos = file->size + off; } if (npos < 0 || npos > LFS1_FILE_MAX) { // file position out of range return LFS1_ERR_INVAL; } // update pos file->pos = npos; return npos; } int lfs1_file_truncate(lfs1_t *lfs1, lfs1_file_t *file, lfs1_off_t size) { if ((file->flags & 3) == LFS1_O_RDONLY) { return LFS1_ERR_BADF; } lfs1_off_t oldsize = lfs1_file_size(lfs1, file); if (size < oldsize) { // need to flush since directly changing metadata int err = lfs1_file_flush(lfs1, file); if (err) { return err; } // lookup new head in ctz skip list err = lfs1_ctz_find(lfs1, &file->cache, NULL, file->head, file->size, size, &file->head, &(lfs1_off_t){0}); if (err) { return err; } file->size = size; file->flags |= LFS1_F_DIRTY; } else if (size > oldsize) { lfs1_off_t pos = file->pos; // flush+seek if not already at end if (file->pos != oldsize) { int err = lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_END); if (err < 0) { return err; } } // fill with zeros while (file->pos < size) { lfs1_ssize_t res = lfs1_file_write(lfs1, file, &(uint8_t){0}, 1); if (res < 0) { return res; } } // restore pos int err = lfs1_file_seek(lfs1, file, pos, LFS1_SEEK_SET); if (err < 0) { return err; } } return 0; } lfs1_soff_t lfs1_file_tell(lfs1_t *lfs1, lfs1_file_t *file) { (void)lfs1; return file->pos; } int lfs1_file_rewind(lfs1_t *lfs1, lfs1_file_t *file) { lfs1_soff_t res = lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_SET); if (res < 0) { return res; } return 0; } lfs1_soff_t lfs1_file_size(lfs1_t *lfs1, lfs1_file_t *file) { (void)lfs1; if (file->flags & LFS1_F_WRITING) { return lfs1_max(file->pos, file->size); } else { return file->size; } } /// General fs operations /// int lfs1_stat(lfs1_t *lfs1, const char *path, struct lfs1_info *info) { lfs1_dir_t cwd; lfs1_entry_t entry; int err = lfs1_dir_find(lfs1, &cwd, &entry, &path); if (err) { return err; } memset(info, 0, sizeof(*info)); info->type = entry.d.type; if (info->type == LFS1_TYPE_REG) { info->size = entry.d.u.file.size; } if (lfs1_paircmp(entry.d.u.dir, lfs1->root) == 0) { strcpy(info->name, "/"); } else { err = lfs1_bd_read(lfs1, cwd.pair[0], entry.off + 4+entry.d.elen+entry.d.alen, info->name, entry.d.nlen); if (err) { return err; } } return 0; } int lfs1_remove(lfs1_t *lfs1, const char *path) { // deorphan if we haven't yet, needed at most once after poweron if (!lfs1->deorphaned) { int err = lfs1_deorphan(lfs1); if (err) { return err; } } lfs1_dir_t cwd; lfs1_entry_t entry; int err = lfs1_dir_find(lfs1, &cwd, &entry, &path); if (err) { return err; } lfs1_dir_t dir; if (entry.d.type == LFS1_TYPE_DIR) { // must be empty before removal, checking size // without masking top bit checks for any case where // dir is not empty err = lfs1_dir_fetch(lfs1, &dir, entry.d.u.dir); if (err) { return err; } else if (dir.d.size != sizeof(dir.d)+4) { return LFS1_ERR_NOTEMPTY; } } // remove the entry err = lfs1_dir_remove(lfs1, &cwd, &entry); if (err) { return err; } // if we were a directory, find pred, replace tail if (entry.d.type == LFS1_TYPE_DIR) { int res = lfs1_pred(lfs1, dir.pair, &cwd); if (res < 0) { return res; } LFS1_ASSERT(res); // must have pred cwd.d.tail[0] = dir.d.tail[0]; cwd.d.tail[1] = dir.d.tail[1]; err = lfs1_dir_commit(lfs1, &cwd, NULL, 0); if (err) { return err; } } return 0; } int lfs1_rename(lfs1_t *lfs1, const char *oldpath, const char *newpath) { // deorphan if we haven't yet, needed at most once after poweron if (!lfs1->deorphaned) { int err = lfs1_deorphan(lfs1); if (err) { return err; } } // find old entry lfs1_dir_t oldcwd; lfs1_entry_t oldentry; int err = lfs1_dir_find(lfs1, &oldcwd, &oldentry, &(const char *){oldpath}); if (err) { return err; } // mark as moving oldentry.d.type |= 0x80; err = lfs1_dir_update(lfs1, &oldcwd, &oldentry, NULL); if (err) { return err; } // allocate new entry lfs1_dir_t newcwd; lfs1_entry_t preventry; err = lfs1_dir_find(lfs1, &newcwd, &preventry, &newpath); if (err && (err != LFS1_ERR_NOENT || strchr(newpath, '/') != NULL)) { return err; } // must have same type bool prevexists = (err != LFS1_ERR_NOENT); if (prevexists && preventry.d.type != (0x7f & oldentry.d.type)) { return LFS1_ERR_ISDIR; } lfs1_dir_t dir; if (prevexists && preventry.d.type == LFS1_TYPE_DIR) { // must be empty before removal, checking size // without masking top bit checks for any case where // dir is not empty err = lfs1_dir_fetch(lfs1, &dir, preventry.d.u.dir); if (err) { return err; } else if (dir.d.size != sizeof(dir.d)+4) { return LFS1_ERR_NOTEMPTY; } } // move to new location lfs1_entry_t newentry = preventry; newentry.d = oldentry.d; newentry.d.type &= ~0x80; newentry.d.nlen = strlen(newpath); if (prevexists) { err = lfs1_dir_update(lfs1, &newcwd, &newentry, newpath); if (err) { return err; } } else { err = lfs1_dir_append(lfs1, &newcwd, &newentry, newpath); if (err) { return err; } } // fetch old pair again in case dir block changed lfs1->moving = true; err = lfs1_dir_find(lfs1, &oldcwd, &oldentry, &oldpath); if (err) { return err; } lfs1->moving = false; // remove old entry err = lfs1_dir_remove(lfs1, &oldcwd, &oldentry); if (err) { return err; } // if we were a directory, find pred, replace tail if (prevexists && preventry.d.type == LFS1_TYPE_DIR) { int res = lfs1_pred(lfs1, dir.pair, &newcwd); if (res < 0) { return res; } LFS1_ASSERT(res); // must have pred newcwd.d.tail[0] = dir.d.tail[0]; newcwd.d.tail[1] = dir.d.tail[1]; err = lfs1_dir_commit(lfs1, &newcwd, NULL, 0); if (err) { return err; } } return 0; } /// Filesystem operations /// static void lfs1_deinit(lfs1_t *lfs1) { // free allocated memory if (!lfs1->cfg->read_buffer) { lfs1_free(lfs1->rcache.buffer); } if (!lfs1->cfg->prog_buffer) { lfs1_free(lfs1->pcache.buffer); } if (!lfs1->cfg->lookahead_buffer) { lfs1_free(lfs1->free.buffer); } } static int lfs1_init(lfs1_t *lfs1, const struct lfs1_config *cfg) { lfs1->cfg = cfg; // setup read cache if (lfs1->cfg->read_buffer) { lfs1->rcache.buffer = lfs1->cfg->read_buffer; } else { lfs1->rcache.buffer = lfs1_malloc(lfs1->cfg->read_size); if (!lfs1->rcache.buffer) { goto cleanup; } } // setup program cache if (lfs1->cfg->prog_buffer) { lfs1->pcache.buffer = lfs1->cfg->prog_buffer; } else { lfs1->pcache.buffer = lfs1_malloc(lfs1->cfg->prog_size); if (!lfs1->pcache.buffer) { goto cleanup; } } // zero to avoid information leaks lfs1_cache_zero(lfs1, &lfs1->pcache); lfs1_cache_drop(lfs1, &lfs1->rcache); // setup lookahead, round down to nearest 32-bits LFS1_ASSERT(lfs1->cfg->lookahead % 32 == 0); LFS1_ASSERT(lfs1->cfg->lookahead > 0); if (lfs1->cfg->lookahead_buffer) { lfs1->free.buffer = lfs1->cfg->lookahead_buffer; } else { lfs1->free.buffer = lfs1_malloc(lfs1->cfg->lookahead/8); if (!lfs1->free.buffer) { goto cleanup; } } // check that program and read sizes are multiples of the block size LFS1_ASSERT(lfs1->cfg->prog_size % lfs1->cfg->read_size == 0); LFS1_ASSERT(lfs1->cfg->block_size % lfs1->cfg->prog_size == 0); // check that the block size is large enough to fit ctz pointers LFS1_ASSERT(4*lfs1_npw2(0xffffffff / (lfs1->cfg->block_size-2*4)) <= lfs1->cfg->block_size); // setup default state lfs1->root[0] = 0xffffffff; lfs1->root[1] = 0xffffffff; lfs1->files = NULL; lfs1->dirs = NULL; lfs1->deorphaned = false; lfs1->moving = false; return 0; cleanup: lfs1_deinit(lfs1); return LFS1_ERR_NOMEM; } int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *cfg) { int err = 0; if (true) { err = lfs1_init(lfs1, cfg); if (err) { return err; } // create free lookahead memset(lfs1->free.buffer, 0, lfs1->cfg->lookahead/8); lfs1->free.off = 0; lfs1->free.size = lfs1_min(lfs1->cfg->lookahead, lfs1->cfg->block_count); lfs1->free.i = 0; lfs1_alloc_ack(lfs1); // create superblock dir lfs1_dir_t superdir; err = lfs1_dir_alloc(lfs1, &superdir); if (err) { goto cleanup; } // write root directory lfs1_dir_t root; err = lfs1_dir_alloc(lfs1, &root); if (err) { goto cleanup; } err = lfs1_dir_commit(lfs1, &root, NULL, 0); if (err) { goto cleanup; } lfs1->root[0] = root.pair[0]; lfs1->root[1] = root.pair[1]; // write superblocks lfs1_superblock_t superblock = { .off = sizeof(superdir.d), .d.type = LFS1_TYPE_SUPERBLOCK, .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, .d.nlen = sizeof(superblock.d.magic), .d.version = LFS1_DISK_VERSION, .d.magic = {"littlefs"}, .d.block_size = lfs1->cfg->block_size, .d.block_count = lfs1->cfg->block_count, .d.root = {lfs1->root[0], lfs1->root[1]}, }; superdir.d.tail[0] = root.pair[0]; superdir.d.tail[1] = root.pair[1]; superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4; // write both pairs to be safe lfs1_superblock_tole32(&superblock.d); bool valid = false; for (int i = 0; i < 2; i++) { err = lfs1_dir_commit(lfs1, &superdir, (struct lfs1_region[]){ {sizeof(superdir.d), sizeof(superblock.d), &superblock.d, sizeof(superblock.d)} }, 1); if (err && err != LFS1_ERR_CORRUPT) { goto cleanup; } valid = valid || !err; } if (!valid) { err = LFS1_ERR_CORRUPT; goto cleanup; } // sanity check that fetch works err = lfs1_dir_fetch(lfs1, &superdir, (const lfs1_block_t[2]){0, 1}); if (err) { goto cleanup; } lfs1_alloc_ack(lfs1); } cleanup: lfs1_deinit(lfs1); return err; } int lfs1_mount(lfs1_t *lfs1, const struct lfs1_config *cfg) { int err = 0; if (true) { err = lfs1_init(lfs1, cfg); if (err) { return err; } // setup free lookahead lfs1->free.off = 0; lfs1->free.size = 0; lfs1->free.i = 0; lfs1_alloc_ack(lfs1); // load superblock lfs1_dir_t dir; lfs1_superblock_t superblock; err = lfs1_dir_fetch(lfs1, &dir, (const lfs1_block_t[2]){0, 1}); if (err && err != LFS1_ERR_CORRUPT) { goto cleanup; } if (!err) { err = lfs1_bd_read(lfs1, dir.pair[0], sizeof(dir.d), &superblock.d, sizeof(superblock.d)); lfs1_superblock_fromle32(&superblock.d); if (err) { goto cleanup; } lfs1->root[0] = superblock.d.root[0]; lfs1->root[1] = superblock.d.root[1]; } if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) { LFS1_ERROR("Invalid superblock at %d %d", 0, 1); err = LFS1_ERR_CORRUPT; goto cleanup; } uint16_t major_version = (0xffff & (superblock.d.version >> 16)); uint16_t minor_version = (0xffff & (superblock.d.version >> 0)); if ((major_version != LFS1_DISK_VERSION_MAJOR || minor_version > LFS1_DISK_VERSION_MINOR)) { LFS1_ERROR("Invalid version %d.%d", major_version, minor_version); err = LFS1_ERR_INVAL; goto cleanup; } return 0; } cleanup: lfs1_deinit(lfs1); return err; } int lfs1_unmount(lfs1_t *lfs1) { lfs1_deinit(lfs1); return 0; } /// Littlefs specific operations /// int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data) { if (lfs1_pairisnull(lfs1->root)) { return 0; } // iterate over metadata pairs lfs1_dir_t dir; lfs1_entry_t entry; lfs1_block_t cwd[2] = {0, 1}; while (true) { for (int i = 0; i < 2; i++) { int err = cb(data, cwd[i]); if (err) { return err; } } int err = lfs1_dir_fetch(lfs1, &dir, cwd); if (err) { return err; } // iterate over contents while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { err = lfs1_bd_read(lfs1, dir.pair[0], dir.off, &entry.d, sizeof(entry.d)); lfs1_entry_fromle32(&entry.d); if (err) { return err; } dir.off += lfs1_entry_size(&entry); if ((0x70 & entry.d.type) == (0x70 & LFS1_TYPE_REG)) { err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, NULL, entry.d.u.file.head, entry.d.u.file.size, cb, data); if (err) { return err; } } } cwd[0] = dir.d.tail[0]; cwd[1] = dir.d.tail[1]; if (lfs1_pairisnull(cwd)) { break; } } // iterate over any open files for (lfs1_file_t *f = lfs1->files; f; f = f->next) { if (f->flags & LFS1_F_DIRTY) { int err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, &f->cache, f->head, f->size, cb, data); if (err) { return err; } } if (f->flags & LFS1_F_WRITING) { int err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, &f->cache, f->block, f->pos, cb, data); if (err) { return err; } } } return 0; } static int lfs1_pred(lfs1_t *lfs1, const lfs1_block_t dir[2], lfs1_dir_t *pdir) { if (lfs1_pairisnull(lfs1->root)) { return 0; } // iterate over all directory directory entries int err = lfs1_dir_fetch(lfs1, pdir, (const lfs1_block_t[2]){0, 1}); if (err) { return err; } while (!lfs1_pairisnull(pdir->d.tail)) { if (lfs1_paircmp(pdir->d.tail, dir) == 0) { return true; } err = lfs1_dir_fetch(lfs1, pdir, pdir->d.tail); if (err) { return err; } } return false; } static int lfs1_parent(lfs1_t *lfs1, const lfs1_block_t dir[2], lfs1_dir_t *parent, lfs1_entry_t *entry) { if (lfs1_pairisnull(lfs1->root)) { return 0; } parent->d.tail[0] = 0; parent->d.tail[1] = 1; // iterate over all directory directory entries while (!lfs1_pairisnull(parent->d.tail)) { int err = lfs1_dir_fetch(lfs1, parent, parent->d.tail); if (err) { return err; } while (true) { err = lfs1_dir_next(lfs1, parent, entry); if (err && err != LFS1_ERR_NOENT) { return err; } if (err == LFS1_ERR_NOENT) { break; } if (((0x70 & entry->d.type) == (0x70 & LFS1_TYPE_DIR)) && lfs1_paircmp(entry->d.u.dir, dir) == 0) { return true; } } } return false; } static int lfs1_moved(lfs1_t *lfs1, const void *e) { if (lfs1_pairisnull(lfs1->root)) { return 0; } // skip superblock lfs1_dir_t cwd; int err = lfs1_dir_fetch(lfs1, &cwd, (const lfs1_block_t[2]){0, 1}); if (err) { return err; } // iterate over all directory directory entries lfs1_entry_t entry; while (!lfs1_pairisnull(cwd.d.tail)) { err = lfs1_dir_fetch(lfs1, &cwd, cwd.d.tail); if (err) { return err; } while (true) { err = lfs1_dir_next(lfs1, &cwd, &entry); if (err && err != LFS1_ERR_NOENT) { return err; } if (err == LFS1_ERR_NOENT) { break; } if (!(0x80 & entry.d.type) && memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) { return true; } } } return false; } static int lfs1_relocate(lfs1_t *lfs1, const lfs1_block_t oldpair[2], const lfs1_block_t newpair[2]) { // find parent lfs1_dir_t parent; lfs1_entry_t entry; int res = lfs1_parent(lfs1, oldpair, &parent, &entry); if (res < 0) { return res; } if (res) { // update disk, this creates a desync entry.d.u.dir[0] = newpair[0]; entry.d.u.dir[1] = newpair[1]; int err = lfs1_dir_update(lfs1, &parent, &entry, NULL); if (err) { return err; } // update internal root if (lfs1_paircmp(oldpair, lfs1->root) == 0) { LFS1_DEBUG("Relocating root %" PRIu32 " %" PRIu32, newpair[0], newpair[1]); lfs1->root[0] = newpair[0]; lfs1->root[1] = newpair[1]; } // clean up bad block, which should now be a desync return lfs1_deorphan(lfs1); } // find pred res = lfs1_pred(lfs1, oldpair, &parent); if (res < 0) { return res; } if (res) { // just replace bad pair, no desync can occur parent.d.tail[0] = newpair[0]; parent.d.tail[1] = newpair[1]; return lfs1_dir_commit(lfs1, &parent, NULL, 0); } // couldn't find dir, must be new return 0; } int lfs1_deorphan(lfs1_t *lfs1) { lfs1->deorphaned = true; if (lfs1_pairisnull(lfs1->root)) { return 0; } lfs1_dir_t pdir = {.d.size = 0x80000000}; lfs1_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1}; // iterate over all directory directory entries for (lfs1_size_t i = 0; i < lfs1->cfg->block_count; i++) { if (lfs1_pairisnull(cwd.d.tail)) { return 0; } int err = lfs1_dir_fetch(lfs1, &cwd, cwd.d.tail); if (err) { return err; } // check head blocks for orphans if (!(0x80000000 & pdir.d.size)) { // check if we have a parent lfs1_dir_t parent; lfs1_entry_t entry; int res = lfs1_parent(lfs1, pdir.d.tail, &parent, &entry); if (res < 0) { return res; } if (!res) { // we are an orphan LFS1_DEBUG("Found orphan %" PRIu32 " %" PRIu32, pdir.d.tail[0], pdir.d.tail[1]); pdir.d.tail[0] = cwd.d.tail[0]; pdir.d.tail[1] = cwd.d.tail[1]; err = lfs1_dir_commit(lfs1, &pdir, NULL, 0); if (err) { return err; } return 0; } if (!lfs1_pairsync(entry.d.u.dir, pdir.d.tail)) { // we have desynced LFS1_DEBUG("Found desync %" PRIu32 " %" PRIu32, entry.d.u.dir[0], entry.d.u.dir[1]); pdir.d.tail[0] = entry.d.u.dir[0]; pdir.d.tail[1] = entry.d.u.dir[1]; err = lfs1_dir_commit(lfs1, &pdir, NULL, 0); if (err) { return err; } return 0; } } // check entries for moves lfs1_entry_t entry; while (true) { err = lfs1_dir_next(lfs1, &cwd, &entry); if (err && err != LFS1_ERR_NOENT) { return err; } if (err == LFS1_ERR_NOENT) { break; } // found moved entry if (entry.d.type & 0x80) { int moved = lfs1_moved(lfs1, &entry.d.u); if (moved < 0) { return moved; } if (moved) { LFS1_DEBUG("Found move %" PRIu32 " %" PRIu32, entry.d.u.dir[0], entry.d.u.dir[1]); err = lfs1_dir_remove(lfs1, &cwd, &entry); if (err) { return err; } } else { LFS1_DEBUG("Found partial move %" PRIu32 " %" PRIu32, entry.d.u.dir[0], entry.d.u.dir[1]); entry.d.type &= ~0x80; err = lfs1_dir_update(lfs1, &cwd, &entry, NULL); if (err) { return err; } } } } memcpy(&pdir, &cwd, sizeof(pdir)); } // If we reached here, we have more directory pairs than blocks in the // filesystem... So something must be horribly wrong return LFS1_ERR_CORRUPT; } micropython-1.12/lib/littlefs/lfs1.h000066400000000000000000000367061357706137100174500ustar00rootroot00000000000000/* * The little filesystem * * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LFS1_H #define LFS1_H #include #include #ifdef __cplusplus extern "C" { #endif /// Version info /// // Software library version // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions #define LFS1_VERSION 0x00010007 #define LFS1_VERSION_MAJOR (0xffff & (LFS1_VERSION >> 16)) #define LFS1_VERSION_MINOR (0xffff & (LFS1_VERSION >> 0)) // Version of On-disk data structures // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions #define LFS1_DISK_VERSION 0x00010001 #define LFS1_DISK_VERSION_MAJOR (0xffff & (LFS1_DISK_VERSION >> 16)) #define LFS1_DISK_VERSION_MINOR (0xffff & (LFS1_DISK_VERSION >> 0)) /// Definitions /// // Type definitions typedef uint32_t lfs1_size_t; typedef uint32_t lfs1_off_t; typedef int32_t lfs1_ssize_t; typedef int32_t lfs1_soff_t; typedef uint32_t lfs1_block_t; // Max name size in bytes #ifndef LFS1_NAME_MAX #define LFS1_NAME_MAX 255 #endif // Max file size in bytes #ifndef LFS1_FILE_MAX #define LFS1_FILE_MAX 2147483647 #endif // Possible error codes, these are negative to allow // valid positive return values enum lfs1_error { LFS1_ERR_OK = 0, // No error LFS1_ERR_IO = -5, // Error during device operation LFS1_ERR_CORRUPT = -52, // Corrupted LFS1_ERR_NOENT = -2, // No directory entry LFS1_ERR_EXIST = -17, // Entry already exists LFS1_ERR_NOTDIR = -20, // Entry is not a dir LFS1_ERR_ISDIR = -21, // Entry is a dir LFS1_ERR_NOTEMPTY = -39, // Dir is not empty LFS1_ERR_BADF = -9, // Bad file number LFS1_ERR_FBIG = -27, // File too large LFS1_ERR_INVAL = -22, // Invalid parameter LFS1_ERR_NOSPC = -28, // No space left on device LFS1_ERR_NOMEM = -12, // No more memory available }; // File types enum lfs1_type { LFS1_TYPE_REG = 0x11, LFS1_TYPE_DIR = 0x22, LFS1_TYPE_SUPERBLOCK = 0x2e, }; // File open flags enum lfs1_open_flags { // open flags LFS1_O_RDONLY = 1, // Open a file as read only LFS1_O_WRONLY = 2, // Open a file as write only LFS1_O_RDWR = 3, // Open a file as read and write LFS1_O_CREAT = 0x0100, // Create a file if it does not exist LFS1_O_EXCL = 0x0200, // Fail if a file already exists LFS1_O_TRUNC = 0x0400, // Truncate the existing file to zero size LFS1_O_APPEND = 0x0800, // Move to end of file on every write // internally used flags LFS1_F_DIRTY = 0x10000, // File does not match storage LFS1_F_WRITING = 0x20000, // File has been written since last flush LFS1_F_READING = 0x40000, // File has been read since last flush LFS1_F_ERRED = 0x80000, // An error occured during write }; // File seek flags enum lfs1_whence_flags { LFS1_SEEK_SET = 0, // Seek relative to an absolute position LFS1_SEEK_CUR = 1, // Seek relative to the current file position LFS1_SEEK_END = 2, // Seek relative to the end of the file }; // Configuration provided during initialization of the littlefs struct lfs1_config { // Opaque user provided context that can be used to pass // information to the block device operations void *context; // Read a region in a block. Negative error codes are propogated // to the user. int (*read)(const struct lfs1_config *c, lfs1_block_t block, lfs1_off_t off, void *buffer, lfs1_size_t size); // Program a region in a block. The block must have previously // been erased. Negative error codes are propogated to the user. // May return LFS1_ERR_CORRUPT if the block should be considered bad. int (*prog)(const struct lfs1_config *c, lfs1_block_t block, lfs1_off_t off, const void *buffer, lfs1_size_t size); // Erase a block. A block must be erased before being programmed. // The state of an erased block is undefined. Negative error codes // are propogated to the user. // May return LFS1_ERR_CORRUPT if the block should be considered bad. int (*erase)(const struct lfs1_config *c, lfs1_block_t block); // Sync the state of the underlying block device. Negative error codes // are propogated to the user. int (*sync)(const struct lfs1_config *c); // Minimum size of a block read. This determines the size of read buffers. // This may be larger than the physical read size to improve performance // by caching more of the block device. lfs1_size_t read_size; // Minimum size of a block program. This determines the size of program // buffers. This may be larger than the physical program size to improve // performance by caching more of the block device. // Must be a multiple of the read size. lfs1_size_t prog_size; // Size of an erasable block. This does not impact ram consumption and // may be larger than the physical erase size. However, this should be // kept small as each file currently takes up an entire block. // Must be a multiple of the program size. lfs1_size_t block_size; // Number of erasable blocks on the device. lfs1_size_t block_count; // Number of blocks to lookahead during block allocation. A larger // lookahead reduces the number of passes required to allocate a block. // The lookahead buffer requires only 1 bit per block so it can be quite // large with little ram impact. Should be a multiple of 32. lfs1_size_t lookahead; // Optional, statically allocated read buffer. Must be read sized. void *read_buffer; // Optional, statically allocated program buffer. Must be program sized. void *prog_buffer; // Optional, statically allocated lookahead buffer. Must be 1 bit per // lookahead block. void *lookahead_buffer; // Optional, statically allocated buffer for files. Must be program sized. // If enabled, only one file may be opened at a time. void *file_buffer; }; // Optional configuration provided during lfs1_file_opencfg struct lfs1_file_config { // Optional, statically allocated buffer for files. Must be program sized. // If NULL, malloc will be used by default. void *buffer; }; // File info structure struct lfs1_info { // Type of the file, either LFS1_TYPE_REG or LFS1_TYPE_DIR uint8_t type; // Size of the file, only valid for REG files lfs1_size_t size; // Name of the file stored as a null-terminated string char name[LFS1_NAME_MAX+1]; }; /// littlefs data structures /// typedef struct lfs1_entry { lfs1_off_t off; struct lfs1_disk_entry { uint8_t type; uint8_t elen; uint8_t alen; uint8_t nlen; union { struct { lfs1_block_t head; lfs1_size_t size; } file; lfs1_block_t dir[2]; } u; } d; } lfs1_entry_t; typedef struct lfs1_cache { lfs1_block_t block; lfs1_off_t off; uint8_t *buffer; } lfs1_cache_t; typedef struct lfs1_file { struct lfs1_file *next; lfs1_block_t pair[2]; lfs1_off_t poff; lfs1_block_t head; lfs1_size_t size; const struct lfs1_file_config *cfg; uint32_t flags; lfs1_off_t pos; lfs1_block_t block; lfs1_off_t off; lfs1_cache_t cache; } lfs1_file_t; typedef struct lfs1_dir { struct lfs1_dir *next; lfs1_block_t pair[2]; lfs1_off_t off; lfs1_block_t head[2]; lfs1_off_t pos; struct lfs1_disk_dir { uint32_t rev; lfs1_size_t size; lfs1_block_t tail[2]; } d; } lfs1_dir_t; typedef struct lfs1_superblock { lfs1_off_t off; struct lfs1_disk_superblock { uint8_t type; uint8_t elen; uint8_t alen; uint8_t nlen; lfs1_block_t root[2]; uint32_t block_size; uint32_t block_count; uint32_t version; char magic[8]; } d; } lfs1_superblock_t; typedef struct lfs1_free { lfs1_block_t off; lfs1_block_t size; lfs1_block_t i; lfs1_block_t ack; uint32_t *buffer; } lfs1_free_t; // The littlefs type typedef struct lfs1 { const struct lfs1_config *cfg; lfs1_block_t root[2]; lfs1_file_t *files; lfs1_dir_t *dirs; lfs1_cache_t rcache; lfs1_cache_t pcache; lfs1_free_t free; bool deorphaned; bool moving; } lfs1_t; /// Filesystem functions /// // Format a block device with the littlefs // // Requires a littlefs object and config struct. This clobbers the littlefs // object, and does not leave the filesystem mounted. The config struct must // be zeroed for defaults and backwards compatibility. // // Returns a negative error code on failure. int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *config); // Mounts a littlefs // // Requires a littlefs object and config struct. Multiple filesystems // may be mounted simultaneously with multiple littlefs objects. Both // lfs1 and config must be allocated while mounted. The config struct must // be zeroed for defaults and backwards compatibility. // // Returns a negative error code on failure. int lfs1_mount(lfs1_t *lfs1, const struct lfs1_config *config); // Unmounts a littlefs // // Does nothing besides releasing any allocated resources. // Returns a negative error code on failure. int lfs1_unmount(lfs1_t *lfs1); /// General operations /// // Removes a file or directory // // If removing a directory, the directory must be empty. // Returns a negative error code on failure. int lfs1_remove(lfs1_t *lfs1, const char *path); // Rename or move a file or directory // // If the destination exists, it must match the source in type. // If the destination is a directory, the directory must be empty. // // Returns a negative error code on failure. int lfs1_rename(lfs1_t *lfs1, const char *oldpath, const char *newpath); // Find info about a file or directory // // Fills out the info structure, based on the specified file or directory. // Returns a negative error code on failure. int lfs1_stat(lfs1_t *lfs1, const char *path, struct lfs1_info *info); /// File operations /// // Open a file // // The mode that the file is opened in is determined by the flags, which // are values from the enum lfs1_open_flags that are bitwise-ored together. // // Returns a negative error code on failure. int lfs1_file_open(lfs1_t *lfs1, lfs1_file_t *file, const char *path, int flags); // Open a file with extra configuration // // The mode that the file is opened in is determined by the flags, which // are values from the enum lfs1_open_flags that are bitwise-ored together. // // The config struct provides additional config options per file as described // above. The config struct must be allocated while the file is open, and the // config struct must be zeroed for defaults and backwards compatibility. // // Returns a negative error code on failure. int lfs1_file_opencfg(lfs1_t *lfs1, lfs1_file_t *file, const char *path, int flags, const struct lfs1_file_config *config); // Close a file // // Any pending writes are written out to storage as though // sync had been called and releases any allocated resources. // // Returns a negative error code on failure. int lfs1_file_close(lfs1_t *lfs1, lfs1_file_t *file); // Synchronize a file on storage // // Any pending writes are written out to storage. // Returns a negative error code on failure. int lfs1_file_sync(lfs1_t *lfs1, lfs1_file_t *file); // Read data from file // // Takes a buffer and size indicating where to store the read data. // Returns the number of bytes read, or a negative error code on failure. lfs1_ssize_t lfs1_file_read(lfs1_t *lfs1, lfs1_file_t *file, void *buffer, lfs1_size_t size); // Write data to file // // Takes a buffer and size indicating the data to write. The file will not // actually be updated on the storage until either sync or close is called. // // Returns the number of bytes written, or a negative error code on failure. lfs1_ssize_t lfs1_file_write(lfs1_t *lfs1, lfs1_file_t *file, const void *buffer, lfs1_size_t size); // Change the position of the file // // The change in position is determined by the offset and whence flag. // Returns the old position of the file, or a negative error code on failure. lfs1_soff_t lfs1_file_seek(lfs1_t *lfs1, lfs1_file_t *file, lfs1_soff_t off, int whence); // Truncates the size of the file to the specified size // // Returns a negative error code on failure. int lfs1_file_truncate(lfs1_t *lfs1, lfs1_file_t *file, lfs1_off_t size); // Return the position of the file // // Equivalent to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_CUR) // Returns the position of the file, or a negative error code on failure. lfs1_soff_t lfs1_file_tell(lfs1_t *lfs1, lfs1_file_t *file); // Change the position of the file to the beginning of the file // // Equivalent to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_CUR) // Returns a negative error code on failure. int lfs1_file_rewind(lfs1_t *lfs1, lfs1_file_t *file); // Return the size of the file // // Similar to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_END) // Returns the size of the file, or a negative error code on failure. lfs1_soff_t lfs1_file_size(lfs1_t *lfs1, lfs1_file_t *file); /// Directory operations /// // Create a directory // // Returns a negative error code on failure. int lfs1_mkdir(lfs1_t *lfs1, const char *path); // Open a directory // // Once open a directory can be used with read to iterate over files. // Returns a negative error code on failure. int lfs1_dir_open(lfs1_t *lfs1, lfs1_dir_t *dir, const char *path); // Close a directory // // Releases any allocated resources. // Returns a negative error code on failure. int lfs1_dir_close(lfs1_t *lfs1, lfs1_dir_t *dir); // Read an entry in the directory // // Fills out the info structure, based on the specified file or directory. // Returns a negative error code on failure. int lfs1_dir_read(lfs1_t *lfs1, lfs1_dir_t *dir, struct lfs1_info *info); // Change the position of the directory // // The new off must be a value previous returned from tell and specifies // an absolute offset in the directory seek. // // Returns a negative error code on failure. int lfs1_dir_seek(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_off_t off); // Return the position of the directory // // The returned offset is only meant to be consumed by seek and may not make // sense, but does indicate the current position in the directory iteration. // // Returns the position of the directory, or a negative error code on failure. lfs1_soff_t lfs1_dir_tell(lfs1_t *lfs1, lfs1_dir_t *dir); // Change the position of the directory to the beginning of the directory // // Returns a negative error code on failure. int lfs1_dir_rewind(lfs1_t *lfs1, lfs1_dir_t *dir); /// Miscellaneous littlefs specific operations /// // Traverse through all blocks in use by the filesystem // // The provided callback will be called with each block address that is // currently in use by the filesystem. This can be used to determine which // blocks are in use or how much of the storage is available. // // Returns a negative error code on failure. int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data); // Prunes any recoverable errors that may have occured in the filesystem // // Not needed to be called by user unless an operation is interrupted // but the filesystem is still mounted. This is already called on first // allocation. // // Returns a negative error code on failure. int lfs1_deorphan(lfs1_t *lfs1); #ifdef __cplusplus } /* extern "C" */ #endif #endif micropython-1.12/lib/littlefs/lfs1_util.c000066400000000000000000000015351357706137100204700ustar00rootroot00000000000000/* * lfs1 util functions * * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #include "lfs1_util.h" // Only compile if user does not provide custom config #ifndef LFS1_CONFIG // Software CRC implementation with small lookup table void lfs1_crc(uint32_t *restrict crc, const void *buffer, size_t size) { static const uint32_t rtable[16] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c, }; const uint8_t *data = buffer; for (size_t i = 0; i < size; i++) { *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf]; *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf]; } } #endif micropython-1.12/lib/littlefs/lfs1_util.h000066400000000000000000000117321357706137100204750ustar00rootroot00000000000000/* * lfs1 utility functions * * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LFS1_UTIL_H #define LFS1_UTIL_H // Users can override lfs1_util.h with their own configuration by defining // LFS1_CONFIG as a header file to include (-DLFS1_CONFIG=lfs1_config.h). // // If LFS1_CONFIG is used, none of the default utils will be emitted and must be // provided by the config file. To start I would suggest copying lfs1_util.h and // modifying as needed. #ifdef LFS1_CONFIG #define LFS1_STRINGIZE(x) LFS1_STRINGIZE2(x) #define LFS1_STRINGIZE2(x) #x #include LFS1_STRINGIZE(LFS1_CONFIG) #else // System includes #include #include #include #ifndef LFS1_NO_MALLOC #include #endif #ifndef LFS1_NO_ASSERT #include #endif #if !defined(LFS1_NO_DEBUG) || !defined(LFS1_NO_WARN) || !defined(LFS1_NO_ERROR) #include #endif #ifdef __cplusplus extern "C" { #endif // Macros, may be replaced by system specific wrappers. Arguments to these // macros must not have side-effects as the macros can be removed for a smaller // code footprint // Logging functions #ifndef LFS1_NO_DEBUG #define LFS1_DEBUG(fmt, ...) \ printf("lfs1 debug:%d: " fmt "\n", __LINE__, __VA_ARGS__) #else #define LFS1_DEBUG(fmt, ...) #endif #ifndef LFS1_NO_WARN #define LFS1_WARN(fmt, ...) \ printf("lfs1 warn:%d: " fmt "\n", __LINE__, __VA_ARGS__) #else #define LFS1_WARN(fmt, ...) #endif #ifndef LFS1_NO_ERROR #define LFS1_ERROR(fmt, ...) \ printf("lfs1 error:%d: " fmt "\n", __LINE__, __VA_ARGS__) #else #define LFS1_ERROR(fmt, ...) #endif // Runtime assertions #ifndef LFS1_NO_ASSERT #define LFS1_ASSERT(test) assert(test) #else #define LFS1_ASSERT(test) #endif // Builtin functions, these may be replaced by more efficient // toolchain-specific implementations. LFS1_NO_INTRINSICS falls back to a more // expensive basic C implementation for debugging purposes // Min/max functions for unsigned 32-bit numbers static inline uint32_t lfs1_max(uint32_t a, uint32_t b) { return (a > b) ? a : b; } static inline uint32_t lfs1_min(uint32_t a, uint32_t b) { return (a < b) ? a : b; } // Find the next smallest power of 2 less than or equal to a static inline uint32_t lfs1_npw2(uint32_t a) { #if !defined(LFS1_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) return 32 - __builtin_clz(a-1); #else uint32_t r = 0; uint32_t s; a -= 1; s = (a > 0xffff) << 4; a >>= s; r |= s; s = (a > 0xff ) << 3; a >>= s; r |= s; s = (a > 0xf ) << 2; a >>= s; r |= s; s = (a > 0x3 ) << 1; a >>= s; r |= s; return (r | (a >> 1)) + 1; #endif } // Count the number of trailing binary zeros in a // lfs1_ctz(0) may be undefined static inline uint32_t lfs1_ctz(uint32_t a) { #if !defined(LFS1_NO_INTRINSICS) && defined(__GNUC__) return __builtin_ctz(a); #else return lfs1_npw2((a & -a) + 1) - 1; #endif } // Count the number of binary ones in a static inline uint32_t lfs1_popc(uint32_t a) { #if !defined(LFS1_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) return __builtin_popcount(a); #else a = a - ((a >> 1) & 0x55555555); a = (a & 0x33333333) + ((a >> 2) & 0x33333333); return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; #endif } // Find the sequence comparison of a and b, this is the distance // between a and b ignoring overflow static inline int lfs1_scmp(uint32_t a, uint32_t b) { return (int)(unsigned)(a - b); } // Convert from 32-bit little-endian to native order static inline uint32_t lfs1_fromle32(uint32_t a) { #if !defined(LFS1_NO_INTRINSICS) && ( \ (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) return a; #elif !defined(LFS1_NO_INTRINSICS) && ( \ (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) return __builtin_bswap32(a); #else return (((uint8_t*)&a)[0] << 0) | (((uint8_t*)&a)[1] << 8) | (((uint8_t*)&a)[2] << 16) | (((uint8_t*)&a)[3] << 24); #endif } // Convert to 32-bit little-endian from native order static inline uint32_t lfs1_tole32(uint32_t a) { return lfs1_fromle32(a); } // Calculate CRC-32 with polynomial = 0x04c11db7 void lfs1_crc(uint32_t *crc, const void *buffer, size_t size); // Allocate memory, only used if buffers are not provided to littlefs static inline void *lfs1_malloc(size_t size) { #ifndef LFS1_NO_MALLOC return malloc(size); #else (void)size; return NULL; #endif } // Deallocate memory, only used if buffers are not provided to littlefs static inline void lfs1_free(void *p) { #ifndef LFS1_NO_MALLOC free(p); #else (void)p; #endif } #ifdef __cplusplus } /* extern "C" */ #endif #endif #endif micropython-1.12/lib/littlefs/lfs2.c000066400000000000000000004437331357706137100174460ustar00rootroot00000000000000/* * The little filesystem * * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #include "lfs2.h" #include "lfs2_util.h" #define LFS2_BLOCK_NULL ((lfs2_block_t)-1) #define LFS2_BLOCK_INLINE ((lfs2_block_t)-2) /// Caching block device operations /// static inline void lfs2_cache_drop(lfs2_t *lfs2, lfs2_cache_t *rcache) { // do not zero, cheaper if cache is readonly or only going to be // written with identical data (during relocates) (void)lfs2; rcache->block = LFS2_BLOCK_NULL; } static inline void lfs2_cache_zero(lfs2_t *lfs2, lfs2_cache_t *pcache) { // zero to avoid information leak memset(pcache->buffer, 0xff, lfs2->cfg->cache_size); pcache->block = LFS2_BLOCK_NULL; } static int lfs2_bd_read(lfs2_t *lfs2, const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint, lfs2_block_t block, lfs2_off_t off, void *buffer, lfs2_size_t size) { uint8_t *data = buffer; LFS2_ASSERT(block != LFS2_BLOCK_NULL); if (off+size > lfs2->cfg->block_size) { return LFS2_ERR_CORRUPT; } while (size > 0) { lfs2_size_t diff = size; if (pcache && block == pcache->block && off < pcache->off + pcache->size) { if (off >= pcache->off) { // is already in pcache? diff = lfs2_min(diff, pcache->size - (off-pcache->off)); memcpy(data, &pcache->buffer[off-pcache->off], diff); data += diff; off += diff; size -= diff; continue; } // pcache takes priority diff = lfs2_min(diff, pcache->off-off); } if (block == rcache->block && off < rcache->off + rcache->size) { if (off >= rcache->off) { // is already in rcache? diff = lfs2_min(diff, rcache->size - (off-rcache->off)); memcpy(data, &rcache->buffer[off-rcache->off], diff); data += diff; off += diff; size -= diff; continue; } // rcache takes priority diff = lfs2_min(diff, rcache->off-off); } // load to cache, first condition can no longer fail LFS2_ASSERT(block < lfs2->cfg->block_count); rcache->block = block; rcache->off = lfs2_aligndown(off, lfs2->cfg->read_size); rcache->size = lfs2_min( lfs2_min( lfs2_alignup(off+hint, lfs2->cfg->read_size), lfs2->cfg->block_size) - rcache->off, lfs2->cfg->cache_size); int err = lfs2->cfg->read(lfs2->cfg, rcache->block, rcache->off, rcache->buffer, rcache->size); LFS2_ASSERT(err <= 0); if (err) { return err; } } return 0; } enum { LFS2_CMP_EQ = 0, LFS2_CMP_LT = 1, LFS2_CMP_GT = 2, }; static int lfs2_bd_cmp(lfs2_t *lfs2, const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint, lfs2_block_t block, lfs2_off_t off, const void *buffer, lfs2_size_t size) { const uint8_t *data = buffer; for (lfs2_off_t i = 0; i < size; i++) { uint8_t dat; int err = lfs2_bd_read(lfs2, pcache, rcache, hint-i, block, off+i, &dat, 1); if (err) { return err; } if (dat != data[i]) { return (dat < data[i]) ? LFS2_CMP_LT : LFS2_CMP_GT; } } return LFS2_CMP_EQ; } static int lfs2_bd_flush(lfs2_t *lfs2, lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate) { if (pcache->block != LFS2_BLOCK_NULL && pcache->block != LFS2_BLOCK_INLINE) { LFS2_ASSERT(pcache->block < lfs2->cfg->block_count); lfs2_size_t diff = lfs2_alignup(pcache->size, lfs2->cfg->prog_size); int err = lfs2->cfg->prog(lfs2->cfg, pcache->block, pcache->off, pcache->buffer, diff); LFS2_ASSERT(err <= 0); if (err) { return err; } if (validate) { // check data on disk lfs2_cache_drop(lfs2, rcache); int res = lfs2_bd_cmp(lfs2, NULL, rcache, diff, pcache->block, pcache->off, pcache->buffer, diff); if (res < 0) { return res; } if (res != LFS2_CMP_EQ) { return LFS2_ERR_CORRUPT; } } lfs2_cache_zero(lfs2, pcache); } return 0; } static int lfs2_bd_sync(lfs2_t *lfs2, lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate) { lfs2_cache_drop(lfs2, rcache); int err = lfs2_bd_flush(lfs2, pcache, rcache, validate); if (err) { return err; } err = lfs2->cfg->sync(lfs2->cfg); LFS2_ASSERT(err <= 0); return err; } static int lfs2_bd_prog(lfs2_t *lfs2, lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate, lfs2_block_t block, lfs2_off_t off, const void *buffer, lfs2_size_t size) { const uint8_t *data = buffer; LFS2_ASSERT(block != LFS2_BLOCK_NULL); LFS2_ASSERT(off + size <= lfs2->cfg->block_size); while (size > 0) { if (block == pcache->block && off >= pcache->off && off < pcache->off + lfs2->cfg->cache_size) { // already fits in pcache? lfs2_size_t diff = lfs2_min(size, lfs2->cfg->cache_size - (off-pcache->off)); memcpy(&pcache->buffer[off-pcache->off], data, diff); data += diff; off += diff; size -= diff; pcache->size = lfs2_max(pcache->size, off - pcache->off); if (pcache->size == lfs2->cfg->cache_size) { // eagerly flush out pcache if we fill up int err = lfs2_bd_flush(lfs2, pcache, rcache, validate); if (err) { return err; } } continue; } // pcache must have been flushed, either by programming and // entire block or manually flushing the pcache LFS2_ASSERT(pcache->block == LFS2_BLOCK_NULL); // prepare pcache, first condition can no longer fail pcache->block = block; pcache->off = lfs2_aligndown(off, lfs2->cfg->prog_size); pcache->size = 0; } return 0; } static int lfs2_bd_erase(lfs2_t *lfs2, lfs2_block_t block) { LFS2_ASSERT(block < lfs2->cfg->block_count); int err = lfs2->cfg->erase(lfs2->cfg, block); LFS2_ASSERT(err <= 0); return err; } /// Small type-level utilities /// // operations on block pairs static inline void lfs2_pair_swap(lfs2_block_t pair[2]) { lfs2_block_t t = pair[0]; pair[0] = pair[1]; pair[1] = t; } static inline bool lfs2_pair_isnull(const lfs2_block_t pair[2]) { return pair[0] == LFS2_BLOCK_NULL || pair[1] == LFS2_BLOCK_NULL; } static inline int lfs2_pair_cmp( const lfs2_block_t paira[2], const lfs2_block_t pairb[2]) { return !(paira[0] == pairb[0] || paira[1] == pairb[1] || paira[0] == pairb[1] || paira[1] == pairb[0]); } static inline bool lfs2_pair_sync( const lfs2_block_t paira[2], const lfs2_block_t pairb[2]) { return (paira[0] == pairb[0] && paira[1] == pairb[1]) || (paira[0] == pairb[1] && paira[1] == pairb[0]); } static inline void lfs2_pair_fromle32(lfs2_block_t pair[2]) { pair[0] = lfs2_fromle32(pair[0]); pair[1] = lfs2_fromle32(pair[1]); } static inline void lfs2_pair_tole32(lfs2_block_t pair[2]) { pair[0] = lfs2_tole32(pair[0]); pair[1] = lfs2_tole32(pair[1]); } // operations on 32-bit entry tags typedef uint32_t lfs2_tag_t; typedef int32_t lfs2_stag_t; #define LFS2_MKTAG(type, id, size) \ (((lfs2_tag_t)(type) << 20) | ((lfs2_tag_t)(id) << 10) | (lfs2_tag_t)(size)) static inline bool lfs2_tag_isvalid(lfs2_tag_t tag) { return !(tag & 0x80000000); } static inline bool lfs2_tag_isdelete(lfs2_tag_t tag) { return ((int32_t)(tag << 22) >> 22) == -1; } static inline uint16_t lfs2_tag_type1(lfs2_tag_t tag) { return (tag & 0x70000000) >> 20; } static inline uint16_t lfs2_tag_type3(lfs2_tag_t tag) { return (tag & 0x7ff00000) >> 20; } static inline uint8_t lfs2_tag_chunk(lfs2_tag_t tag) { return (tag & 0x0ff00000) >> 20; } static inline int8_t lfs2_tag_splice(lfs2_tag_t tag) { return (int8_t)lfs2_tag_chunk(tag); } static inline uint16_t lfs2_tag_id(lfs2_tag_t tag) { return (tag & 0x000ffc00) >> 10; } static inline lfs2_size_t lfs2_tag_size(lfs2_tag_t tag) { return tag & 0x000003ff; } static inline lfs2_size_t lfs2_tag_dsize(lfs2_tag_t tag) { return sizeof(tag) + lfs2_tag_size(tag + lfs2_tag_isdelete(tag)); } // operations on attributes in attribute lists struct lfs2_mattr { lfs2_tag_t tag; const void *buffer; }; struct lfs2_diskoff { lfs2_block_t block; lfs2_off_t off; }; #define LFS2_MKATTRS(...) \ (struct lfs2_mattr[]){__VA_ARGS__}, \ sizeof((struct lfs2_mattr[]){__VA_ARGS__}) / sizeof(struct lfs2_mattr) // operations on global state static inline void lfs2_gstate_xor(struct lfs2_gstate *a, const struct lfs2_gstate *b) { for (int i = 0; i < 3; i++) { ((uint32_t*)a)[i] ^= ((const uint32_t*)b)[i]; } } static inline bool lfs2_gstate_iszero(const struct lfs2_gstate *a) { for (int i = 0; i < 3; i++) { if (((uint32_t*)a)[i] != 0) { return false; } } return true; } static inline bool lfs2_gstate_hasorphans(const struct lfs2_gstate *a) { return lfs2_tag_size(a->tag); } static inline uint8_t lfs2_gstate_getorphans(const struct lfs2_gstate *a) { return lfs2_tag_size(a->tag); } static inline bool lfs2_gstate_hasmove(const struct lfs2_gstate *a) { return lfs2_tag_type1(a->tag); } static inline bool lfs2_gstate_hasmovehere(const struct lfs2_gstate *a, const lfs2_block_t *pair) { return lfs2_tag_type1(a->tag) && lfs2_pair_cmp(a->pair, pair) == 0; } static inline void lfs2_gstate_xororphans(struct lfs2_gstate *a, const struct lfs2_gstate *b, bool orphans) { a->tag ^= LFS2_MKTAG(0x800, 0, 0) & (b->tag ^ ((uint32_t)orphans << 31)); } static inline void lfs2_gstate_xormove(struct lfs2_gstate *a, const struct lfs2_gstate *b, uint16_t id, const lfs2_block_t pair[2]) { a->tag ^= LFS2_MKTAG(0x7ff, 0x3ff, 0) & (b->tag ^ ( (id != 0x3ff) ? LFS2_MKTAG(LFS2_TYPE_DELETE, id, 0) : 0)); a->pair[0] ^= b->pair[0] ^ ((id != 0x3ff) ? pair[0] : 0); a->pair[1] ^= b->pair[1] ^ ((id != 0x3ff) ? pair[1] : 0); } static inline void lfs2_gstate_fromle32(struct lfs2_gstate *a) { a->tag = lfs2_fromle32(a->tag); a->pair[0] = lfs2_fromle32(a->pair[0]); a->pair[1] = lfs2_fromle32(a->pair[1]); } static inline void lfs2_gstate_tole32(struct lfs2_gstate *a) { a->tag = lfs2_tole32(a->tag); a->pair[0] = lfs2_tole32(a->pair[0]); a->pair[1] = lfs2_tole32(a->pair[1]); } // other endianness operations static void lfs2_ctz_fromle32(struct lfs2_ctz *ctz) { ctz->head = lfs2_fromle32(ctz->head); ctz->size = lfs2_fromle32(ctz->size); } static void lfs2_ctz_tole32(struct lfs2_ctz *ctz) { ctz->head = lfs2_tole32(ctz->head); ctz->size = lfs2_tole32(ctz->size); } static inline void lfs2_superblock_fromle32(lfs2_superblock_t *superblock) { superblock->version = lfs2_fromle32(superblock->version); superblock->block_size = lfs2_fromle32(superblock->block_size); superblock->block_count = lfs2_fromle32(superblock->block_count); superblock->name_max = lfs2_fromle32(superblock->name_max); superblock->file_max = lfs2_fromle32(superblock->file_max); superblock->attr_max = lfs2_fromle32(superblock->attr_max); } static inline void lfs2_superblock_tole32(lfs2_superblock_t *superblock) { superblock->version = lfs2_tole32(superblock->version); superblock->block_size = lfs2_tole32(superblock->block_size); superblock->block_count = lfs2_tole32(superblock->block_count); superblock->name_max = lfs2_tole32(superblock->name_max); superblock->file_max = lfs2_tole32(superblock->file_max); superblock->attr_max = lfs2_tole32(superblock->attr_max); } /// Internal operations predeclared here /// static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount); static int lfs2_dir_compact(lfs2_t *lfs2, lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount, lfs2_mdir_t *source, uint16_t begin, uint16_t end); static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file); static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file); static void lfs2_fs_preporphans(lfs2_t *lfs2, int8_t orphans); static void lfs2_fs_prepmove(lfs2_t *lfs2, uint16_t id, const lfs2_block_t pair[2]); static int lfs2_fs_pred(lfs2_t *lfs2, const lfs2_block_t dir[2], lfs2_mdir_t *pdir); static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t dir[2], lfs2_mdir_t *parent); static int lfs2_fs_relocate(lfs2_t *lfs2, const lfs2_block_t oldpair[2], lfs2_block_t newpair[2]); static int lfs2_fs_forceconsistency(lfs2_t *lfs2); static int lfs2_deinit(lfs2_t *lfs2); #ifdef LFS2_MIGRATE static int lfs21_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data); #endif /// Block allocator /// static int lfs2_alloc_lookahead(void *p, lfs2_block_t block) { lfs2_t *lfs2 = (lfs2_t*)p; lfs2_block_t off = ((block - lfs2->free.off) + lfs2->cfg->block_count) % lfs2->cfg->block_count; if (off < lfs2->free.size) { lfs2->free.buffer[off / 32] |= 1U << (off % 32); } return 0; } static int lfs2_alloc(lfs2_t *lfs2, lfs2_block_t *block) { while (true) { while (lfs2->free.i != lfs2->free.size) { lfs2_block_t off = lfs2->free.i; lfs2->free.i += 1; lfs2->free.ack -= 1; if (!(lfs2->free.buffer[off / 32] & (1U << (off % 32)))) { // found a free block *block = (lfs2->free.off + off) % lfs2->cfg->block_count; // eagerly find next off so an alloc ack can // discredit old lookahead blocks while (lfs2->free.i != lfs2->free.size && (lfs2->free.buffer[lfs2->free.i / 32] & (1U << (lfs2->free.i % 32)))) { lfs2->free.i += 1; lfs2->free.ack -= 1; } return 0; } } // check if we have looked at all blocks since last ack if (lfs2->free.ack == 0) { LFS2_ERROR("No more free space %"PRIu32, lfs2->free.i + lfs2->free.off); return LFS2_ERR_NOSPC; } lfs2->free.off = (lfs2->free.off + lfs2->free.size) % lfs2->cfg->block_count; lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->free.ack); lfs2->free.i = 0; // find mask of free blocks from tree memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size); int err = lfs2_fs_traverse(lfs2, lfs2_alloc_lookahead, lfs2); if (err) { return err; } } } static void lfs2_alloc_ack(lfs2_t *lfs2) { lfs2->free.ack = lfs2->cfg->block_count; } /// Metadata pair and directory operations /// static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir, lfs2_tag_t gmask, lfs2_tag_t gtag, lfs2_off_t goff, void *gbuffer, lfs2_size_t gsize) { lfs2_off_t off = dir->off; lfs2_tag_t ntag = dir->etag; lfs2_stag_t gdiff = 0; if (lfs2_gstate_hasmovehere(&lfs2->gstate, dir->pair) && lfs2_tag_id(gtag) <= lfs2_tag_id(lfs2->gstate.tag)) { // synthetic moves gdiff -= LFS2_MKTAG(0, 1, 0); } // iterate over dir block backwards (for faster lookups) while (off >= sizeof(lfs2_tag_t) + lfs2_tag_dsize(ntag)) { off -= lfs2_tag_dsize(ntag); lfs2_tag_t tag = ntag; int err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, sizeof(ntag), dir->pair[0], off, &ntag, sizeof(ntag)); if (err) { return err; } ntag = (lfs2_frombe32(ntag) ^ tag) & 0x7fffffff; if (lfs2_tag_id(gmask) != 0 && lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE && lfs2_tag_id(tag) <= lfs2_tag_id(gtag - gdiff)) { if (tag == (LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0) | (LFS2_MKTAG(0, 0x3ff, 0) & (gtag - gdiff)))) { // found where we were created return LFS2_ERR_NOENT; } // move around splices gdiff += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0); } if ((gmask & tag) == (gmask & (gtag - gdiff))) { if (lfs2_tag_isdelete(tag)) { return LFS2_ERR_NOENT; } lfs2_size_t diff = lfs2_min(lfs2_tag_size(tag), gsize); err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, diff, dir->pair[0], off+sizeof(tag)+goff, gbuffer, diff); if (err) { return err; } memset((uint8_t*)gbuffer + diff, 0, gsize - diff); return tag + gdiff; } } return LFS2_ERR_NOENT; } static lfs2_stag_t lfs2_dir_get(lfs2_t *lfs2, const lfs2_mdir_t *dir, lfs2_tag_t gmask, lfs2_tag_t gtag, void *buffer) { return lfs2_dir_getslice(lfs2, dir, gmask, gtag, 0, buffer, lfs2_tag_size(gtag)); } static int lfs2_dir_getread(lfs2_t *lfs2, const lfs2_mdir_t *dir, const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint, lfs2_tag_t gmask, lfs2_tag_t gtag, lfs2_off_t off, void *buffer, lfs2_size_t size) { uint8_t *data = buffer; if (off+size > lfs2->cfg->block_size) { return LFS2_ERR_CORRUPT; } while (size > 0) { lfs2_size_t diff = size; if (pcache && pcache->block == LFS2_BLOCK_INLINE && off < pcache->off + pcache->size) { if (off >= pcache->off) { // is already in pcache? diff = lfs2_min(diff, pcache->size - (off-pcache->off)); memcpy(data, &pcache->buffer[off-pcache->off], diff); data += diff; off += diff; size -= diff; continue; } // pcache takes priority diff = lfs2_min(diff, pcache->off-off); } if (rcache->block == LFS2_BLOCK_INLINE && off < rcache->off + rcache->size) { if (off >= rcache->off) { // is already in rcache? diff = lfs2_min(diff, rcache->size - (off-rcache->off)); memcpy(data, &rcache->buffer[off-rcache->off], diff); data += diff; off += diff; size -= diff; continue; } // rcache takes priority diff = lfs2_min(diff, rcache->off-off); } // load to cache, first condition can no longer fail rcache->block = LFS2_BLOCK_INLINE; rcache->off = lfs2_aligndown(off, lfs2->cfg->read_size); rcache->size = lfs2_min(lfs2_alignup(off+hint, lfs2->cfg->read_size), lfs2->cfg->cache_size); int err = lfs2_dir_getslice(lfs2, dir, gmask, gtag, rcache->off, rcache->buffer, rcache->size); if (err < 0) { return err; } } return 0; } static int lfs2_dir_traverse_filter(void *p, lfs2_tag_t tag, const void *buffer) { lfs2_tag_t *filtertag = p; (void)buffer; // which mask depends on unique bit in tag structure uint32_t mask = (tag & LFS2_MKTAG(0x100, 0, 0)) ? LFS2_MKTAG(0x7ff, 0x3ff, 0) : LFS2_MKTAG(0x700, 0x3ff, 0); // check for redundancy if ((mask & tag) == (mask & *filtertag) || lfs2_tag_isdelete(*filtertag) || (LFS2_MKTAG(0x7ff, 0x3ff, 0) & tag) == ( LFS2_MKTAG(LFS2_TYPE_DELETE, 0, 0) | (LFS2_MKTAG(0, 0x3ff, 0) & *filtertag))) { return true; } // check if we need to adjust for created/deleted tags if (lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE && lfs2_tag_id(tag) <= lfs2_tag_id(*filtertag)) { *filtertag += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0); } return false; } static int lfs2_dir_traverse(lfs2_t *lfs2, const lfs2_mdir_t *dir, lfs2_off_t off, lfs2_tag_t ptag, const struct lfs2_mattr *attrs, int attrcount, bool hasseenmove, lfs2_tag_t tmask, lfs2_tag_t ttag, uint16_t begin, uint16_t end, int16_t diff, int (*cb)(void *data, lfs2_tag_t tag, const void *buffer), void *data) { // iterate over directory and attrs while (true) { lfs2_tag_t tag; const void *buffer; struct lfs2_diskoff disk; if (off+lfs2_tag_dsize(ptag) < dir->off) { off += lfs2_tag_dsize(ptag); int err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, sizeof(tag), dir->pair[0], off, &tag, sizeof(tag)); if (err) { return err; } tag = (lfs2_frombe32(tag) ^ ptag) | 0x80000000; disk.block = dir->pair[0]; disk.off = off+sizeof(lfs2_tag_t); buffer = &disk; ptag = tag; } else if (attrcount > 0) { tag = attrs[0].tag; buffer = attrs[0].buffer; attrs += 1; attrcount -= 1; } else if (!hasseenmove && lfs2_gstate_hasmovehere(&lfs2->gpending, dir->pair)) { // Wait, we have pending move? Handle this here (we need to // or else we risk letting moves fall out of date) tag = lfs2->gpending.tag & LFS2_MKTAG(0x7ff, 0x3ff, 0); buffer = NULL; hasseenmove = true; } else { return 0; } lfs2_tag_t mask = LFS2_MKTAG(0x7ff, 0, 0); if ((mask & tmask & tag) != (mask & tmask & ttag)) { continue; } // do we need to filter? inlining the filtering logic here allows // for some minor optimizations if (lfs2_tag_id(tmask) != 0) { // scan for duplicates and update tag based on creates/deletes int filter = lfs2_dir_traverse(lfs2, dir, off, ptag, attrs, attrcount, hasseenmove, 0, 0, 0, 0, 0, lfs2_dir_traverse_filter, &tag); if (filter < 0) { return filter; } if (filter) { continue; } // in filter range? if (!(lfs2_tag_id(tag) >= begin && lfs2_tag_id(tag) < end)) { continue; } } // handle special cases for mcu-side operations if (lfs2_tag_type3(tag) == LFS2_FROM_NOOP) { // do nothing } else if (lfs2_tag_type3(tag) == LFS2_FROM_MOVE) { uint16_t fromid = lfs2_tag_size(tag); uint16_t toid = lfs2_tag_id(tag); int err = lfs2_dir_traverse(lfs2, buffer, 0, LFS2_BLOCK_NULL, NULL, 0, true, LFS2_MKTAG(0x600, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, 0, 0), fromid, fromid+1, toid-fromid+diff, cb, data); if (err) { return err; } } else if (lfs2_tag_type3(tag) == LFS2_FROM_USERATTRS) { for (unsigned i = 0; i < lfs2_tag_size(tag); i++) { const struct lfs2_attr *a = buffer; int err = cb(data, LFS2_MKTAG(LFS2_TYPE_USERATTR + a[i].type, lfs2_tag_id(tag) + diff, a[i].size), a[i].buffer); if (err) { return err; } } } else { int err = cb(data, tag + LFS2_MKTAG(0, diff, 0), buffer); if (err) { return err; } } } } static lfs2_stag_t lfs2_dir_fetchmatch(lfs2_t *lfs2, lfs2_mdir_t *dir, const lfs2_block_t pair[2], lfs2_tag_t fmask, lfs2_tag_t ftag, uint16_t *id, int (*cb)(void *data, lfs2_tag_t tag, const void *buffer), void *data) { // we can find tag very efficiently during a fetch, since we're already // scanning the entire directory lfs2_stag_t besttag = -1; // find the block with the most recent revision uint32_t revs[2] = {0, 0}; int r = 0; for (int i = 0; i < 2; i++) { int err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, sizeof(revs[i]), pair[i], 0, &revs[i], sizeof(revs[i])); revs[i] = lfs2_fromle32(revs[i]); if (err && err != LFS2_ERR_CORRUPT) { return err; } if (err != LFS2_ERR_CORRUPT && lfs2_scmp(revs[i], revs[(i+1)%2]) > 0) { r = i; } } dir->pair[0] = pair[(r+0)%2]; dir->pair[1] = pair[(r+1)%2]; dir->rev = revs[(r+0)%2]; dir->off = 0; // nonzero = found some commits // now scan tags to fetch the actual dir and find possible match for (int i = 0; i < 2; i++) { lfs2_off_t off = 0; lfs2_tag_t ptag = LFS2_BLOCK_NULL; uint16_t tempcount = 0; lfs2_block_t temptail[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; bool tempsplit = false; lfs2_stag_t tempbesttag = besttag; dir->rev = lfs2_tole32(dir->rev); uint32_t crc = lfs2_crc(LFS2_BLOCK_NULL, &dir->rev, sizeof(dir->rev)); dir->rev = lfs2_fromle32(dir->rev); while (true) { // extract next tag lfs2_tag_t tag; off += lfs2_tag_dsize(ptag); int err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, lfs2->cfg->block_size, dir->pair[0], off, &tag, sizeof(tag)); if (err) { if (err == LFS2_ERR_CORRUPT) { // can't continue? dir->erased = false; break; } return err; } crc = lfs2_crc(crc, &tag, sizeof(tag)); tag = lfs2_frombe32(tag) ^ ptag; // next commit not yet programmed or we're not in valid range if (!lfs2_tag_isvalid(tag) || off + lfs2_tag_dsize(tag) > lfs2->cfg->block_size) { dir->erased = (lfs2_tag_type1(ptag) == LFS2_TYPE_CRC && dir->off % lfs2->cfg->prog_size == 0); break; } ptag = tag; if (lfs2_tag_type1(tag) == LFS2_TYPE_CRC) { // check the crc attr uint32_t dcrc; err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, lfs2->cfg->block_size, dir->pair[0], off+sizeof(tag), &dcrc, sizeof(dcrc)); if (err) { if (err == LFS2_ERR_CORRUPT) { dir->erased = false; break; } return err; } dcrc = lfs2_fromle32(dcrc); if (crc != dcrc) { dir->erased = false; break; } // reset the next bit if we need to ptag ^= (lfs2_tag_t)(lfs2_tag_chunk(tag) & 1U) << 31; // toss our crc into the filesystem seed for // pseudorandom numbers lfs2->seed ^= crc; // update with what's found so far besttag = tempbesttag; dir->off = off + lfs2_tag_dsize(tag); dir->etag = ptag; dir->count = tempcount; dir->tail[0] = temptail[0]; dir->tail[1] = temptail[1]; dir->split = tempsplit; // reset crc crc = LFS2_BLOCK_NULL; continue; } // crc the entry first, hopefully leaving it in the cache for (lfs2_off_t j = sizeof(tag); j < lfs2_tag_dsize(tag); j++) { uint8_t dat; err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, lfs2->cfg->block_size, dir->pair[0], off+j, &dat, 1); if (err) { if (err == LFS2_ERR_CORRUPT) { dir->erased = false; break; } return err; } crc = lfs2_crc(crc, &dat, 1); } // directory modification tags? if (lfs2_tag_type1(tag) == LFS2_TYPE_NAME) { // increase count of files if necessary if (lfs2_tag_id(tag) >= tempcount) { tempcount = lfs2_tag_id(tag) + 1; } } else if (lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE) { tempcount += lfs2_tag_splice(tag); if (tag == (LFS2_MKTAG(LFS2_TYPE_DELETE, 0, 0) | (LFS2_MKTAG(0, 0x3ff, 0) & tempbesttag))) { tempbesttag |= 0x80000000; } else if (tempbesttag != -1 && lfs2_tag_id(tag) <= lfs2_tag_id(tempbesttag)) { tempbesttag += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0); } } else if (lfs2_tag_type1(tag) == LFS2_TYPE_TAIL) { tempsplit = (lfs2_tag_chunk(tag) & 1); err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, lfs2->cfg->block_size, dir->pair[0], off+sizeof(tag), &temptail, 8); if (err) { if (err == LFS2_ERR_CORRUPT) { dir->erased = false; break; } } lfs2_pair_fromle32(temptail); } // found a match for our fetcher? if ((fmask & tag) == (fmask & ftag)) { int res = cb(data, tag, &(struct lfs2_diskoff){ dir->pair[0], off+sizeof(tag)}); if (res < 0) { if (res == LFS2_ERR_CORRUPT) { dir->erased = false; break; } return res; } if (res == LFS2_CMP_EQ) { // found a match tempbesttag = tag; } else if (res == LFS2_CMP_GT && lfs2_tag_id(tag) <= lfs2_tag_id(tempbesttag)) { // found a greater match, keep track to keep things sorted tempbesttag = tag | 0x80000000; } } } // consider what we have good enough if (dir->off > 0) { // synthetic move if (lfs2_gstate_hasmovehere(&lfs2->gstate, dir->pair)) { if (lfs2_tag_id(lfs2->gstate.tag) == lfs2_tag_id(besttag)) { besttag |= 0x80000000; } else if (besttag != -1 && lfs2_tag_id(lfs2->gstate.tag) < lfs2_tag_id(besttag)) { besttag -= LFS2_MKTAG(0, 1, 0); } } // found tag? or found best id? if (id) { *id = lfs2_min(lfs2_tag_id(besttag), dir->count); } if (lfs2_tag_isvalid(besttag)) { return besttag; } else if (lfs2_tag_id(besttag) < dir->count) { return LFS2_ERR_NOENT; } else { return 0; } } // failed, try the other block? lfs2_pair_swap(dir->pair); dir->rev = revs[(r+1)%2]; } LFS2_ERROR("Corrupted dir pair at %"PRIx32" %"PRIx32, dir->pair[0], dir->pair[1]); return LFS2_ERR_CORRUPT; } static int lfs2_dir_fetch(lfs2_t *lfs2, lfs2_mdir_t *dir, const lfs2_block_t pair[2]) { // note, mask=-1, tag=0 can never match a tag since this // pattern has the invalid bit set return (int)lfs2_dir_fetchmatch(lfs2, dir, pair, -1, 0, NULL, NULL, NULL); } static int lfs2_dir_getgstate(lfs2_t *lfs2, const lfs2_mdir_t *dir, struct lfs2_gstate *gstate) { struct lfs2_gstate temp; lfs2_stag_t res = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x7ff, 0, 0), LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0, sizeof(temp)), &temp); if (res < 0 && res != LFS2_ERR_NOENT) { return res; } if (res != LFS2_ERR_NOENT) { // xor together to find resulting gstate lfs2_gstate_fromle32(&temp); lfs2_gstate_xor(gstate, &temp); } return 0; } static int lfs2_dir_getinfo(lfs2_t *lfs2, lfs2_mdir_t *dir, uint16_t id, struct lfs2_info *info) { if (id == 0x3ff) { // special case for root strcpy(info->name, "/"); info->type = LFS2_TYPE_DIR; return 0; } lfs2_stag_t tag = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x780, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_NAME, id, lfs2->name_max+1), info->name); if (tag < 0) { return (int)tag; } info->type = lfs2_tag_type3(tag); struct lfs2_ctz ctz; tag = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x700, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, id, sizeof(ctz)), &ctz); if (tag < 0) { return (int)tag; } lfs2_ctz_fromle32(&ctz); if (lfs2_tag_type3(tag) == LFS2_TYPE_CTZSTRUCT) { info->size = ctz.size; } else if (lfs2_tag_type3(tag) == LFS2_TYPE_INLINESTRUCT) { info->size = lfs2_tag_size(tag); } return 0; } struct lfs2_dir_find_match { lfs2_t *lfs2; const void *name; lfs2_size_t size; }; static int lfs2_dir_find_match(void *data, lfs2_tag_t tag, const void *buffer) { struct lfs2_dir_find_match *name = data; lfs2_t *lfs2 = name->lfs2; const struct lfs2_diskoff *disk = buffer; // compare with disk lfs2_size_t diff = lfs2_min(name->size, lfs2_tag_size(tag)); int res = lfs2_bd_cmp(lfs2, NULL, &lfs2->rcache, diff, disk->block, disk->off, name->name, diff); if (res != LFS2_CMP_EQ) { return res; } // only equal if our size is still the same if (name->size != lfs2_tag_size(tag)) { return (name->size < lfs2_tag_size(tag)) ? LFS2_CMP_LT : LFS2_CMP_GT; } // found a match! return LFS2_CMP_EQ; } static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, const char **path, uint16_t *id) { // we reduce path to a single name if we can find it const char *name = *path; if (id) { *id = 0x3ff; } // default to root dir lfs2_stag_t tag = LFS2_MKTAG(LFS2_TYPE_DIR, 0x3ff, 0); dir->tail[0] = lfs2->root[0]; dir->tail[1] = lfs2->root[1]; while (true) { nextname: // skip slashes name += strspn(name, "/"); lfs2_size_t namelen = strcspn(name, "/"); // skip '.' and root '..' if ((namelen == 1 && memcmp(name, ".", 1) == 0) || (namelen == 2 && memcmp(name, "..", 2) == 0)) { name += namelen; goto nextname; } // skip if matched by '..' in name const char *suffix = name + namelen; lfs2_size_t sufflen; int depth = 1; while (true) { suffix += strspn(suffix, "/"); sufflen = strcspn(suffix, "/"); if (sufflen == 0) { break; } if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { depth -= 1; if (depth == 0) { name = suffix + sufflen; goto nextname; } } else { depth += 1; } suffix += sufflen; } // found path if (name[0] == '\0') { return tag; } // update what we've found so far *path = name; // only continue if we hit a directory if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { return LFS2_ERR_NOTDIR; } // grab the entry data if (lfs2_tag_id(tag) != 0x3ff) { lfs2_stag_t res = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x700, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), dir->tail); if (res < 0) { return res; } lfs2_pair_fromle32(dir->tail); } // find entry matching name while (true) { tag = lfs2_dir_fetchmatch(lfs2, dir, dir->tail, LFS2_MKTAG(0x780, 0, 0), LFS2_MKTAG(LFS2_TYPE_NAME, 0, namelen), // are we last name? (strchr(name, '/') == NULL) ? id : NULL, lfs2_dir_find_match, &(struct lfs2_dir_find_match){ lfs2, name, namelen}); if (tag < 0) { return tag; } if (tag) { break; } if (!dir->split) { return LFS2_ERR_NOENT; } } // to next name name += namelen; } } // commit logic struct lfs2_commit { lfs2_block_t block; lfs2_off_t off; lfs2_tag_t ptag; uint32_t crc; lfs2_off_t begin; lfs2_off_t end; }; static int lfs2_dir_commitprog(lfs2_t *lfs2, struct lfs2_commit *commit, const void *buffer, lfs2_size_t size) { int err = lfs2_bd_prog(lfs2, &lfs2->pcache, &lfs2->rcache, false, commit->block, commit->off , (const uint8_t*)buffer, size); if (err) { return err; } commit->crc = lfs2_crc(commit->crc, buffer, size); commit->off += size; return 0; } static int lfs2_dir_commitattr(lfs2_t *lfs2, struct lfs2_commit *commit, lfs2_tag_t tag, const void *buffer) { // check if we fit lfs2_size_t dsize = lfs2_tag_dsize(tag); if (commit->off + dsize > commit->end) { return LFS2_ERR_NOSPC; } // write out tag lfs2_tag_t ntag = lfs2_tobe32((tag & 0x7fffffff) ^ commit->ptag); int err = lfs2_dir_commitprog(lfs2, commit, &ntag, sizeof(ntag)); if (err) { return err; } if (!(tag & 0x80000000)) { // from memory err = lfs2_dir_commitprog(lfs2, commit, buffer, dsize-sizeof(tag)); if (err) { return err; } } else { // from disk const struct lfs2_diskoff *disk = buffer; for (lfs2_off_t i = 0; i < dsize-sizeof(tag); i++) { // rely on caching to make this efficient uint8_t dat; err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, dsize-sizeof(tag)-i, disk->block, disk->off+i, &dat, 1); if (err) { return err; } err = lfs2_dir_commitprog(lfs2, commit, &dat, 1); if (err) { return err; } } } commit->ptag = tag & 0x7fffffff; return 0; } static int lfs2_dir_commitcrc(lfs2_t *lfs2, struct lfs2_commit *commit) { // align to program units const lfs2_off_t off1 = commit->off + sizeof(lfs2_tag_t); const lfs2_off_t end = lfs2_alignup(off1 + sizeof(uint32_t), lfs2->cfg->prog_size); // create crc tags to fill up remainder of commit, note that // padding is not crcd, which lets fetches skip padding but // makes committing a bit more complicated while (commit->off < end) { lfs2_off_t off = commit->off + sizeof(lfs2_tag_t); lfs2_off_t noff = lfs2_min(end - off, 0x3fe) + off; if (noff < end) { noff = lfs2_min(noff, end - 2*sizeof(uint32_t)); } // read erased state from next program unit lfs2_tag_t tag = LFS2_BLOCK_NULL; int err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, sizeof(tag), commit->block, noff, &tag, sizeof(tag)); if (err && err != LFS2_ERR_CORRUPT) { return err; } // build crc tag bool reset = ~lfs2_frombe32(tag) >> 31; tag = LFS2_MKTAG(LFS2_TYPE_CRC + reset, 0x3ff, noff - off); // write out crc uint32_t footer[2]; footer[0] = lfs2_tobe32(tag ^ commit->ptag); commit->crc = lfs2_crc(commit->crc, &footer[0], sizeof(footer[0])); footer[1] = lfs2_tole32(commit->crc); err = lfs2_bd_prog(lfs2, &lfs2->pcache, &lfs2->rcache, false, commit->block, commit->off, &footer, sizeof(footer)); if (err) { return err; } commit->off += sizeof(tag)+lfs2_tag_size(tag); commit->ptag = tag ^ ((lfs2_tag_t)reset << 31); commit->crc = LFS2_BLOCK_NULL; // reset crc for next "commit" } // flush buffers int err = lfs2_bd_sync(lfs2, &lfs2->pcache, &lfs2->rcache, false); if (err) { return err; } // successful commit, check checksums to make sure lfs2_off_t off = commit->begin; lfs2_off_t noff = off1; while (off < end) { uint32_t crc = LFS2_BLOCK_NULL; for (lfs2_off_t i = off; i < noff+sizeof(uint32_t); i++) { // leave it up to caching to make this efficient uint8_t dat; err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, noff+sizeof(uint32_t)-i, commit->block, i, &dat, 1); if (err) { return err; } crc = lfs2_crc(crc, &dat, 1); } // detected write error? if (crc != 0) { return LFS2_ERR_CORRUPT; } // skip padding off = lfs2_min(end - noff, 0x3fe) + noff; if (off < end) { off = lfs2_min(off, end - 2*sizeof(uint32_t)); } noff = off + sizeof(uint32_t); } return 0; } static int lfs2_dir_alloc(lfs2_t *lfs2, lfs2_mdir_t *dir) { // allocate pair of dir blocks (backwards, so we write block 1 first) for (int i = 0; i < 2; i++) { int err = lfs2_alloc(lfs2, &dir->pair[(i+1)%2]); if (err) { return err; } } // rather than clobbering one of the blocks we just pretend // the revision may be valid int err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, sizeof(dir->rev), dir->pair[0], 0, &dir->rev, sizeof(dir->rev)); dir->rev = lfs2_fromle32(dir->rev); if (err && err != LFS2_ERR_CORRUPT) { return err; } // make sure we don't immediately evict dir->rev += dir->rev & 1; // set defaults dir->off = sizeof(dir->rev); dir->etag = LFS2_BLOCK_NULL; dir->count = 0; dir->tail[0] = LFS2_BLOCK_NULL; dir->tail[1] = LFS2_BLOCK_NULL; dir->erased = false; dir->split = false; // don't write out yet, let caller take care of that return 0; } static int lfs2_dir_drop(lfs2_t *lfs2, lfs2_mdir_t *dir, lfs2_mdir_t *tail) { // steal state int err = lfs2_dir_getgstate(lfs2, tail, &lfs2->gdelta); if (err) { return err; } // steal tail lfs2_pair_tole32(tail->tail); err = lfs2_dir_commit(lfs2, dir, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_TAIL + tail->split, 0x3ff, 8), tail->tail})); lfs2_pair_fromle32(tail->tail); if (err) { return err; } return 0; } static int lfs2_dir_split(lfs2_t *lfs2, lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount, lfs2_mdir_t *source, uint16_t split, uint16_t end) { // create tail directory lfs2_mdir_t tail; int err = lfs2_dir_alloc(lfs2, &tail); if (err) { return err; } tail.split = dir->split; tail.tail[0] = dir->tail[0]; tail.tail[1] = dir->tail[1]; err = lfs2_dir_compact(lfs2, &tail, attrs, attrcount, source, split, end); if (err) { return err; } dir->tail[0] = tail.pair[0]; dir->tail[1] = tail.pair[1]; dir->split = true; // update root if needed if (lfs2_pair_cmp(dir->pair, lfs2->root) == 0 && split == 0) { lfs2->root[0] = tail.pair[0]; lfs2->root[1] = tail.pair[1]; } return 0; } static int lfs2_dir_commit_size(void *p, lfs2_tag_t tag, const void *buffer) { lfs2_size_t *size = p; (void)buffer; *size += lfs2_tag_dsize(tag); return 0; } struct lfs2_dir_commit_commit { lfs2_t *lfs2; struct lfs2_commit *commit; }; static int lfs2_dir_commit_commit(void *p, lfs2_tag_t tag, const void *buffer) { struct lfs2_dir_commit_commit *commit = p; return lfs2_dir_commitattr(commit->lfs2, commit->commit, tag, buffer); } static int lfs2_dir_compact(lfs2_t *lfs2, lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount, lfs2_mdir_t *source, uint16_t begin, uint16_t end) { // save some state in case block is bad const lfs2_block_t oldpair[2] = {dir->pair[1], dir->pair[0]}; bool relocated = false; bool exhausted = false; // should we split? while (end - begin > 1) { // find size lfs2_size_t size = 0; int err = lfs2_dir_traverse(lfs2, source, 0, LFS2_BLOCK_NULL, attrs, attrcount, false, LFS2_MKTAG(0x400, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_NAME, 0, 0), begin, end, -begin, lfs2_dir_commit_size, &size); if (err) { return err; } // space is complicated, we need room for tail, crc, gstate, // cleanup delete, and we cap at half a block to give room // for metadata updates. if (end - begin < 0xff && size <= lfs2_min(lfs2->cfg->block_size - 36, lfs2_alignup(lfs2->cfg->block_size/2, lfs2->cfg->prog_size))) { break; } // can't fit, need to split, we should really be finding the // largest size that fits with a small binary search, but right now // it's not worth the code size uint16_t split = (end - begin) / 2; err = lfs2_dir_split(lfs2, dir, attrs, attrcount, source, begin+split, end); if (err) { // if we fail to split, we may be able to overcompact, unless // we're too big for even the full block, in which case our // only option is to error if (err == LFS2_ERR_NOSPC && size <= lfs2->cfg->block_size - 36) { break; } return err; } end = begin + split; } // increment revision count dir->rev += 1; if (lfs2->cfg->block_cycles > 0 && (dir->rev % (lfs2->cfg->block_cycles+1) == 0)) { if (lfs2_pair_cmp(dir->pair, (const lfs2_block_t[2]){0, 1}) == 0) { // oh no! we're writing too much to the superblock, // should we expand? lfs2_ssize_t res = lfs2_fs_size(lfs2); if (res < 0) { return res; } // do we have extra space? littlefs can't reclaim this space // by itself, so expand cautiously if ((lfs2_size_t)res < lfs2->cfg->block_count/2) { LFS2_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev); int err = lfs2_dir_split(lfs2, dir, attrs, attrcount, source, begin, end); if (err && err != LFS2_ERR_NOSPC) { return err; } // welp, we tried, if we ran out of space there's not much // we can do, we'll error later if we've become frozen if (!err) { end = begin; } } #ifdef LFS2_MIGRATE } else if (lfs2_pair_cmp(dir->pair, lfs2->root) == 0 && lfs2->lfs21) { // we can't relocate our root during migrations, as this would // cause the superblock to get updated, which would clobber v1 #endif } else { // we're writing too much, time to relocate exhausted = true; goto relocate; } } // begin loop to commit compaction to blocks until a compact sticks while (true) { { // There's nothing special about our global delta, so feed it into // our local global delta int err = lfs2_dir_getgstate(lfs2, dir, &lfs2->gdelta); if (err) { return err; } // setup commit state struct lfs2_commit commit = { .block = dir->pair[1], .off = 0, .ptag = LFS2_BLOCK_NULL, .crc = LFS2_BLOCK_NULL, .begin = 0, .end = lfs2->cfg->block_size - 8, }; // erase block to write to err = lfs2_bd_erase(lfs2, dir->pair[1]); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } // write out header dir->rev = lfs2_tole32(dir->rev); err = lfs2_dir_commitprog(lfs2, &commit, &dir->rev, sizeof(dir->rev)); dir->rev = lfs2_fromle32(dir->rev); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } // traverse the directory, this time writing out all unique tags err = lfs2_dir_traverse(lfs2, source, 0, LFS2_BLOCK_NULL, attrs, attrcount, false, LFS2_MKTAG(0x400, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_NAME, 0, 0), begin, end, -begin, lfs2_dir_commit_commit, &(struct lfs2_dir_commit_commit){ lfs2, &commit}); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } // commit tail, which may be new after last size check if (!lfs2_pair_isnull(dir->tail)) { lfs2_pair_tole32(dir->tail); err = lfs2_dir_commitattr(lfs2, &commit, LFS2_MKTAG(LFS2_TYPE_TAIL + dir->split, 0x3ff, 8), dir->tail); lfs2_pair_fromle32(dir->tail); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } } if (!relocated && !lfs2_gstate_iszero(&lfs2->gdelta)) { // commit any globals, unless we're relocating, // in which case our parent will steal our globals lfs2_gstate_tole32(&lfs2->gdelta); err = lfs2_dir_commitattr(lfs2, &commit, LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0x3ff, sizeof(lfs2->gdelta)), &lfs2->gdelta); lfs2_gstate_fromle32(&lfs2->gdelta); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } } err = lfs2_dir_commitcrc(lfs2, &commit); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } // successful compaction, swap dir pair to indicate most recent LFS2_ASSERT(commit.off % lfs2->cfg->prog_size == 0); lfs2_pair_swap(dir->pair); dir->count = end - begin; dir->off = commit.off; dir->etag = commit.ptag; // note we able to have already handled move here if (lfs2_gstate_hasmovehere(&lfs2->gpending, dir->pair)) { lfs2_gstate_xormove(&lfs2->gpending, &lfs2->gpending, 0x3ff, NULL); } } break; relocate: // commit was corrupted, drop caches and prepare to relocate block relocated = true; lfs2_cache_drop(lfs2, &lfs2->pcache); if (!exhausted) { LFS2_DEBUG("Bad block at %"PRIx32, dir->pair[1]); } // can't relocate superblock, filesystem is now frozen if (lfs2_pair_cmp(oldpair, (const lfs2_block_t[2]){0, 1}) == 0) { LFS2_WARN("Superblock %"PRIx32" has become unwritable", oldpair[1]); return LFS2_ERR_NOSPC; } // relocate half of pair int err = lfs2_alloc(lfs2, &dir->pair[1]); if (err && (err != LFS2_ERR_NOSPC && !exhausted)) { return err; } continue; } if (!relocated) { lfs2->gstate = lfs2->gpending; lfs2->gdelta = (struct lfs2_gstate){0}; } else { // update references if we relocated LFS2_DEBUG("Relocating %"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); int err = lfs2_fs_relocate(lfs2, oldpair, dir->pair); if (err) { return err; } } return 0; } static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount) { // check for any inline files that aren't RAM backed and // forcefully evict them, needed for filesystem consistency for (lfs2_file_t *f = (lfs2_file_t*)lfs2->mlist; f; f = f->next) { if (dir != &f->m && lfs2_pair_cmp(f->m.pair, dir->pair) == 0 && f->type == LFS2_TYPE_REG && (f->flags & LFS2_F_INLINE) && f->ctz.size > lfs2->cfg->cache_size) { int err = lfs2_file_outline(lfs2, f); if (err) { return err; } err = lfs2_file_flush(lfs2, f); if (err) { return err; } } } // calculate changes to the directory lfs2_tag_t deletetag = LFS2_BLOCK_NULL; lfs2_tag_t createtag = LFS2_BLOCK_NULL; for (int i = 0; i < attrcount; i++) { if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_CREATE) { createtag = attrs[i].tag; dir->count += 1; } else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE) { deletetag = attrs[i].tag; LFS2_ASSERT(dir->count > 0); dir->count -= 1; } else if (lfs2_tag_type1(attrs[i].tag) == LFS2_TYPE_TAIL) { dir->tail[0] = ((lfs2_block_t*)attrs[i].buffer)[0]; dir->tail[1] = ((lfs2_block_t*)attrs[i].buffer)[1]; dir->split = (lfs2_tag_chunk(attrs[i].tag) & 1); lfs2_pair_fromle32(dir->tail); } } // do we have a pending move? if (lfs2_gstate_hasmovehere(&lfs2->gpending, dir->pair)) { deletetag = lfs2->gpending.tag & LFS2_MKTAG(0x7ff, 0x3ff, 0); LFS2_ASSERT(dir->count > 0); dir->count -= 1; // mark gdelta so we reflect the move we will fix lfs2_gstate_xormove(&lfs2->gdelta, &lfs2->gpending, 0x3ff, NULL); } // should we actually drop the directory block? if (lfs2_tag_isvalid(deletetag) && dir->count == 0) { lfs2_mdir_t pdir; int err = lfs2_fs_pred(lfs2, dir->pair, &pdir); if (err && err != LFS2_ERR_NOENT) { return err; } if (err != LFS2_ERR_NOENT && pdir.split) { return lfs2_dir_drop(lfs2, &pdir, dir); } } if (dir->erased || dir->count >= 0xff) { // try to commit struct lfs2_commit commit = { .block = dir->pair[0], .off = dir->off, .ptag = dir->etag, .crc = LFS2_BLOCK_NULL, .begin = dir->off, .end = lfs2->cfg->block_size - 8, }; // traverse attrs that need to be written out lfs2_pair_tole32(dir->tail); int err = lfs2_dir_traverse(lfs2, dir, dir->off, dir->etag, attrs, attrcount, false, 0, 0, 0, 0, 0, lfs2_dir_commit_commit, &(struct lfs2_dir_commit_commit){ lfs2, &commit}); lfs2_pair_fromle32(dir->tail); if (err) { if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) { goto compact; } return err; } // commit any global diffs if we have any if (!lfs2_gstate_iszero(&lfs2->gdelta)) { err = lfs2_dir_getgstate(lfs2, dir, &lfs2->gdelta); if (err) { return err; } lfs2_gstate_tole32(&lfs2->gdelta); err = lfs2_dir_commitattr(lfs2, &commit, LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0x3ff, sizeof(lfs2->gdelta)), &lfs2->gdelta); lfs2_gstate_fromle32(&lfs2->gdelta); if (err) { if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) { goto compact; } return err; } } // finalize commit with the crc err = lfs2_dir_commitcrc(lfs2, &commit); if (err) { if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) { goto compact; } return err; } // successful commit, update dir LFS2_ASSERT(commit.off % lfs2->cfg->prog_size == 0); dir->off = commit.off; dir->etag = commit.ptag; // note we able to have already handled move here if (lfs2_gstate_hasmovehere(&lfs2->gpending, dir->pair)) { lfs2_gstate_xormove(&lfs2->gpending, &lfs2->gpending, 0x3ff, NULL); } // update gstate lfs2->gstate = lfs2->gpending; lfs2->gdelta = (struct lfs2_gstate){0}; } else { compact: // fall back to compaction lfs2_cache_drop(lfs2, &lfs2->pcache); int err = lfs2_dir_compact(lfs2, dir, attrs, attrcount, dir, 0, dir->count); if (err) { return err; } } // update any directories that are affected lfs2_mdir_t copy = *dir; // two passes, once for things that aren't us, and one // for things that are for (struct lfs2_mlist *d = lfs2->mlist; d; d = d->next) { if (lfs2_pair_cmp(d->m.pair, copy.pair) == 0) { d->m = *dir; if (d->id == lfs2_tag_id(deletetag)) { d->m.pair[0] = LFS2_BLOCK_NULL; d->m.pair[1] = LFS2_BLOCK_NULL; } else if (d->id > lfs2_tag_id(deletetag)) { d->id -= 1; if (d->type == LFS2_TYPE_DIR) { ((lfs2_dir_t*)d)->pos -= 1; } } else if (&d->m != dir && d->id >= lfs2_tag_id(createtag)) { d->id += 1; if (d->type == LFS2_TYPE_DIR) { ((lfs2_dir_t*)d)->pos += 1; } } while (d->id >= d->m.count && d->m.split) { // we split and id is on tail now d->id -= d->m.count; int err = lfs2_dir_fetch(lfs2, &d->m, d->m.tail); if (err) { return err; } } } } return 0; } /// Top level directory operations /// int lfs2_mkdir(lfs2_t *lfs2, const char *path) { LFS2_TRACE("lfs2_mkdir(%p, \"%s\")", (void*)lfs2, path); // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { LFS2_TRACE("lfs2_mkdir -> %d", err); return err; } lfs2_mdir_t cwd; uint16_t id; err = lfs2_dir_find(lfs2, &cwd, &path, &id); if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) { LFS2_TRACE("lfs2_mkdir -> %d", (err < 0) ? err : LFS2_ERR_EXIST); return (err < 0) ? err : LFS2_ERR_EXIST; } // check that name fits lfs2_size_t nlen = strlen(path); if (nlen > lfs2->name_max) { LFS2_TRACE("lfs2_mkdir -> %d", LFS2_ERR_NAMETOOLONG); return LFS2_ERR_NAMETOOLONG; } // build up new directory lfs2_alloc_ack(lfs2); lfs2_mdir_t dir; err = lfs2_dir_alloc(lfs2, &dir); if (err) { LFS2_TRACE("lfs2_mkdir -> %d", err); return err; } // find end of list lfs2_mdir_t pred = cwd; while (pred.split) { err = lfs2_dir_fetch(lfs2, &pred, pred.tail); if (err) { LFS2_TRACE("lfs2_mkdir -> %d", err); return err; } } // setup dir lfs2_pair_tole32(pred.tail); err = lfs2_dir_commit(lfs2, &dir, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), pred.tail})); lfs2_pair_fromle32(pred.tail); if (err) { LFS2_TRACE("lfs2_mkdir -> %d", err); return err; } // current block end of list? if (cwd.split) { // update tails, this creates a desync lfs2_fs_preporphans(lfs2, +1); lfs2_pair_tole32(dir.pair); err = lfs2_dir_commit(lfs2, &pred, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), dir.pair})); lfs2_pair_fromle32(dir.pair); if (err) { LFS2_TRACE("lfs2_mkdir -> %d", err); return err; } lfs2_fs_preporphans(lfs2, -1); } // now insert into our parent block lfs2_pair_tole32(dir.pair); err = lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_CREATE, id, 0), NULL}, {LFS2_MKTAG(LFS2_TYPE_DIR, id, nlen), path}, {LFS2_MKTAG(LFS2_TYPE_DIRSTRUCT, id, 8), dir.pair}, {!cwd.split ? LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8) : LFS2_MKTAG(LFS2_FROM_NOOP, 0, 0), dir.pair})); lfs2_pair_fromle32(dir.pair); if (err) { LFS2_TRACE("lfs2_mkdir -> %d", err); return err; } LFS2_TRACE("lfs2_mkdir -> %d", 0); return 0; } int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { LFS2_TRACE("lfs2_dir_open(%p, %p, \"%s\")", (void*)lfs2, (void*)dir, path); lfs2_stag_t tag = lfs2_dir_find(lfs2, &dir->m, &path, NULL); if (tag < 0) { LFS2_TRACE("lfs2_dir_open -> %d", tag); return tag; } if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { LFS2_TRACE("lfs2_dir_open -> %d", LFS2_ERR_NOTDIR); return LFS2_ERR_NOTDIR; } lfs2_block_t pair[2]; if (lfs2_tag_id(tag) == 0x3ff) { // handle root dir separately pair[0] = lfs2->root[0]; pair[1] = lfs2->root[1]; } else { // get dir pair from parent lfs2_stag_t res = lfs2_dir_get(lfs2, &dir->m, LFS2_MKTAG(0x700, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), pair); if (res < 0) { LFS2_TRACE("lfs2_dir_open -> %d", res); return res; } lfs2_pair_fromle32(pair); } // fetch first pair int err = lfs2_dir_fetch(lfs2, &dir->m, pair); if (err) { LFS2_TRACE("lfs2_dir_open -> %d", err); return err; } // setup entry dir->head[0] = dir->m.pair[0]; dir->head[1] = dir->m.pair[1]; dir->id = 0; dir->pos = 0; // add to list of mdirs dir->type = LFS2_TYPE_DIR; dir->next = (lfs2_dir_t*)lfs2->mlist; lfs2->mlist = (struct lfs2_mlist*)dir; LFS2_TRACE("lfs2_dir_open -> %d", 0); return 0; } int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir) { LFS2_TRACE("lfs2_dir_close(%p, %p)", (void*)lfs2, (void*)dir); // remove from list of mdirs for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) { if (*p == (struct lfs2_mlist*)dir) { *p = (*p)->next; break; } } LFS2_TRACE("lfs2_dir_close -> %d", 0); return 0; } int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) { LFS2_TRACE("lfs2_dir_read(%p, %p, %p)", (void*)lfs2, (void*)dir, (void*)info); memset(info, 0, sizeof(*info)); // special offset for '.' and '..' if (dir->pos == 0) { info->type = LFS2_TYPE_DIR; strcpy(info->name, "."); dir->pos += 1; LFS2_TRACE("lfs2_dir_read -> %d", true); return true; } else if (dir->pos == 1) { info->type = LFS2_TYPE_DIR; strcpy(info->name, ".."); dir->pos += 1; LFS2_TRACE("lfs2_dir_read -> %d", true); return true; } while (true) { if (dir->id == dir->m.count) { if (!dir->m.split) { LFS2_TRACE("lfs2_dir_read -> %d", false); return false; } int err = lfs2_dir_fetch(lfs2, &dir->m, dir->m.tail); if (err) { LFS2_TRACE("lfs2_dir_read -> %d", err); return err; } dir->id = 0; } int err = lfs2_dir_getinfo(lfs2, &dir->m, dir->id, info); if (err && err != LFS2_ERR_NOENT) { LFS2_TRACE("lfs2_dir_read -> %d", err); return err; } dir->id += 1; if (err != LFS2_ERR_NOENT) { break; } } dir->pos += 1; LFS2_TRACE("lfs2_dir_read -> %d", true); return true; } int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { LFS2_TRACE("lfs2_dir_seek(%p, %p, %"PRIu32")", (void*)lfs2, (void*)dir, off); // simply walk from head dir int err = lfs2_dir_rewind(lfs2, dir); if (err) { LFS2_TRACE("lfs2_dir_seek -> %d", err); return err; } // first two for ./.. dir->pos = lfs2_min(2, off); off -= dir->pos; while (off != 0) { dir->id = lfs2_min(dir->m.count, off); dir->pos += dir->id; off -= dir->id; if (dir->id == dir->m.count) { if (!dir->m.split) { LFS2_TRACE("lfs2_dir_seek -> %d", LFS2_ERR_INVAL); return LFS2_ERR_INVAL; } err = lfs2_dir_fetch(lfs2, &dir->m, dir->m.tail); if (err) { LFS2_TRACE("lfs2_dir_seek -> %d", err); return err; } } } LFS2_TRACE("lfs2_dir_seek -> %d", 0); return 0; } lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir) { LFS2_TRACE("lfs2_dir_tell(%p, %p)", (void*)lfs2, (void*)dir); (void)lfs2; LFS2_TRACE("lfs2_dir_tell -> %"PRId32, dir->pos); return dir->pos; } int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir) { LFS2_TRACE("lfs2_dir_rewind(%p, %p)", (void*)lfs2, (void*)dir); // reload the head dir int err = lfs2_dir_fetch(lfs2, &dir->m, dir->head); if (err) { LFS2_TRACE("lfs2_dir_rewind -> %d", err); return err; } dir->m.pair[0] = dir->head[0]; dir->m.pair[1] = dir->head[1]; dir->id = 0; dir->pos = 0; LFS2_TRACE("lfs2_dir_rewind -> %d", 0); return 0; } /// File index list operations /// static int lfs2_ctz_index(lfs2_t *lfs2, lfs2_off_t *off) { lfs2_off_t size = *off; lfs2_off_t b = lfs2->cfg->block_size - 2*4; lfs2_off_t i = size / b; if (i == 0) { return 0; } i = (size - 4*(lfs2_popc(i-1)+2)) / b; *off = size - b*i - 4*lfs2_popc(i); return i; } static int lfs2_ctz_find(lfs2_t *lfs2, const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_block_t head, lfs2_size_t size, lfs2_size_t pos, lfs2_block_t *block, lfs2_off_t *off) { if (size == 0) { *block = LFS2_BLOCK_NULL; *off = 0; return 0; } lfs2_off_t current = lfs2_ctz_index(lfs2, &(lfs2_off_t){size-1}); lfs2_off_t target = lfs2_ctz_index(lfs2, &pos); while (current > target) { lfs2_size_t skip = lfs2_min( lfs2_npw2(current-target+1) - 1, lfs2_ctz(current)); int err = lfs2_bd_read(lfs2, pcache, rcache, sizeof(head), head, 4*skip, &head, sizeof(head)); head = lfs2_fromle32(head); if (err) { return err; } LFS2_ASSERT(head >= 2 && head <= lfs2->cfg->block_count); current -= 1 << skip; } *block = head; *off = pos; return 0; } static int lfs2_ctz_extend(lfs2_t *lfs2, lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_block_t head, lfs2_size_t size, lfs2_block_t *block, lfs2_off_t *off) { while (true) { // go ahead and grab a block lfs2_block_t nblock; int err = lfs2_alloc(lfs2, &nblock); if (err) { return err; } LFS2_ASSERT(nblock >= 2 && nblock <= lfs2->cfg->block_count); { err = lfs2_bd_erase(lfs2, nblock); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } if (size == 0) { *block = nblock; *off = 0; return 0; } size -= 1; lfs2_off_t index = lfs2_ctz_index(lfs2, &size); size += 1; // just copy out the last block if it is incomplete if (size != lfs2->cfg->block_size) { for (lfs2_off_t i = 0; i < size; i++) { uint8_t data; err = lfs2_bd_read(lfs2, NULL, rcache, size-i, head, i, &data, 1); if (err) { return err; } err = lfs2_bd_prog(lfs2, pcache, rcache, true, nblock, i, &data, 1); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } } *block = nblock; *off = size; return 0; } // append block index += 1; lfs2_size_t skips = lfs2_ctz(index) + 1; for (lfs2_off_t i = 0; i < skips; i++) { head = lfs2_tole32(head); err = lfs2_bd_prog(lfs2, pcache, rcache, true, nblock, 4*i, &head, 4); head = lfs2_fromle32(head); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } if (i != skips-1) { err = lfs2_bd_read(lfs2, NULL, rcache, sizeof(head), head, 4*i, &head, sizeof(head)); head = lfs2_fromle32(head); if (err) { return err; } } LFS2_ASSERT(head >= 2 && head <= lfs2->cfg->block_count); } *block = nblock; *off = 4*skips; return 0; } relocate: LFS2_DEBUG("Bad block at %"PRIx32, nblock); // just clear cache and try a new block lfs2_cache_drop(lfs2, pcache); } } static int lfs2_ctz_traverse(lfs2_t *lfs2, const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_block_t head, lfs2_size_t size, int (*cb)(void*, lfs2_block_t), void *data) { if (size == 0) { return 0; } lfs2_off_t index = lfs2_ctz_index(lfs2, &(lfs2_off_t){size-1}); while (true) { int err = cb(data, head); if (err) { return err; } if (index == 0) { return 0; } lfs2_block_t heads[2]; int count = 2 - (index & 1); err = lfs2_bd_read(lfs2, pcache, rcache, count*sizeof(head), head, 0, &heads, count*sizeof(head)); heads[0] = lfs2_fromle32(heads[0]); heads[1] = lfs2_fromle32(heads[1]); if (err) { return err; } for (int i = 0; i < count-1; i++) { err = cb(data, heads[i]); if (err) { return err; } } head = heads[count-1]; index -= count; } } /// Top level file operations /// int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags, const struct lfs2_file_config *cfg) { LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {" ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})", (void*)lfs2, (void*)file, path, flags, (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); // deorphan if we haven't yet, needed at most once after poweron if ((flags & 3) != LFS2_O_RDONLY) { int err = lfs2_fs_forceconsistency(lfs2); if (err) { LFS2_TRACE("lfs2_file_opencfg -> %d", err); return err; } } // setup simple file details int err; file->cfg = cfg; file->flags = flags | LFS2_F_OPENED; file->pos = 0; file->off = 0; file->cache.buffer = NULL; // allocate entry for file if it doesn't exist lfs2_stag_t tag = lfs2_dir_find(lfs2, &file->m, &path, &file->id); if (tag < 0 && !(tag == LFS2_ERR_NOENT && file->id != 0x3ff)) { err = tag; goto cleanup; } // get id, add to list of mdirs to catch update changes file->type = LFS2_TYPE_REG; file->next = (lfs2_file_t*)lfs2->mlist; lfs2->mlist = (struct lfs2_mlist*)file; if (tag == LFS2_ERR_NOENT) { if (!(flags & LFS2_O_CREAT)) { err = LFS2_ERR_NOENT; goto cleanup; } // check that name fits lfs2_size_t nlen = strlen(path); if (nlen > lfs2->name_max) { err = LFS2_ERR_NAMETOOLONG; goto cleanup; } // get next slot and create entry to remember name err = lfs2_dir_commit(lfs2, &file->m, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_CREATE, file->id, 0), NULL}, {LFS2_MKTAG(LFS2_TYPE_REG, file->id, nlen), path}, {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0), NULL})); if (err) { err = LFS2_ERR_NAMETOOLONG; goto cleanup; } tag = LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, 0); } else if (flags & LFS2_O_EXCL) { err = LFS2_ERR_EXIST; goto cleanup; } else if (lfs2_tag_type3(tag) != LFS2_TYPE_REG) { err = LFS2_ERR_ISDIR; goto cleanup; } else if (flags & LFS2_O_TRUNC) { // truncate if requested tag = LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0); file->flags |= LFS2_F_DIRTY; } else { // try to load what's on disk, if it's inlined we'll fix it later tag = lfs2_dir_get(lfs2, &file->m, LFS2_MKTAG(0x700, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, file->id, 8), &file->ctz); if (tag < 0) { err = tag; goto cleanup; } lfs2_ctz_fromle32(&file->ctz); } // fetch attrs for (unsigned i = 0; i < file->cfg->attr_count; i++) { if ((file->flags & 3) != LFS2_O_WRONLY) { lfs2_stag_t res = lfs2_dir_get(lfs2, &file->m, LFS2_MKTAG(0x7ff, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_USERATTR + file->cfg->attrs[i].type, file->id, file->cfg->attrs[i].size), file->cfg->attrs[i].buffer); if (res < 0 && res != LFS2_ERR_NOENT) { err = res; goto cleanup; } } if ((file->flags & 3) != LFS2_O_RDONLY) { if (file->cfg->attrs[i].size > lfs2->attr_max) { err = LFS2_ERR_NOSPC; goto cleanup; } file->flags |= LFS2_F_DIRTY; } } // allocate buffer if needed if (file->cfg->buffer) { file->cache.buffer = file->cfg->buffer; } else { file->cache.buffer = lfs2_malloc(lfs2->cfg->cache_size); if (!file->cache.buffer) { err = LFS2_ERR_NOMEM; goto cleanup; } } // zero to avoid information leak lfs2_cache_zero(lfs2, &file->cache); if (lfs2_tag_type3(tag) == LFS2_TYPE_INLINESTRUCT) { // load inline files file->ctz.head = LFS2_BLOCK_INLINE; file->ctz.size = lfs2_tag_size(tag); file->flags |= LFS2_F_INLINE; file->cache.block = file->ctz.head; file->cache.off = 0; file->cache.size = lfs2->cfg->cache_size; // don't always read (may be new/trunc file) if (file->ctz.size > 0) { lfs2_stag_t res = lfs2_dir_get(lfs2, &file->m, LFS2_MKTAG(0x700, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, file->id, lfs2_min(file->cache.size, 0x3fe)), file->cache.buffer); if (res < 0) { err = res; goto cleanup; } } } LFS2_TRACE("lfs2_file_opencfg -> %d", 0); return 0; cleanup: // clean up lingering resources file->flags |= LFS2_F_ERRED; lfs2_file_close(lfs2, file); LFS2_TRACE("lfs2_file_opencfg -> %d", err); return err; } int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags) { LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)", (void*)lfs2, (void*)file, path, flags); static const struct lfs2_file_config defaults = {0}; int err = lfs2_file_opencfg(lfs2, file, path, flags, &defaults); LFS2_TRACE("lfs2_file_open -> %d", err); return err; } int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_close(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(file->flags & LFS2_F_OPENED); int err = lfs2_file_sync(lfs2, file); // remove from list of mdirs for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) { if (*p == (struct lfs2_mlist*)file) { *p = (*p)->next; break; } } // clean up memory if (!file->cfg->buffer) { lfs2_free(file->cache.buffer); } file->flags &= ~LFS2_F_OPENED; LFS2_TRACE("lfs2_file_close -> %d", err); return err; } static int lfs2_file_relocate(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_ASSERT(file->flags & LFS2_F_OPENED); while (true) { // just relocate what exists into new block lfs2_block_t nblock; int err = lfs2_alloc(lfs2, &nblock); if (err) { return err; } err = lfs2_bd_erase(lfs2, nblock); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } // either read from dirty cache or disk for (lfs2_off_t i = 0; i < file->off; i++) { uint8_t data; if (file->flags & LFS2_F_INLINE) { err = lfs2_dir_getread(lfs2, &file->m, // note we evict inline files before they can be dirty NULL, &file->cache, file->off-i, LFS2_MKTAG(0xfff, 0x1ff, 0), LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0), i, &data, 1); if (err) { return err; } } else { err = lfs2_bd_read(lfs2, &file->cache, &lfs2->rcache, file->off-i, file->block, i, &data, 1); if (err) { return err; } } err = lfs2_bd_prog(lfs2, &lfs2->pcache, &lfs2->rcache, true, nblock, i, &data, 1); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } } // copy over new state of file memcpy(file->cache.buffer, lfs2->pcache.buffer, lfs2->cfg->cache_size); file->cache.block = lfs2->pcache.block; file->cache.off = lfs2->pcache.off; file->cache.size = lfs2->pcache.size; lfs2_cache_zero(lfs2, &lfs2->pcache); file->block = nblock; file->flags |= LFS2_F_WRITING; return 0; relocate: LFS2_DEBUG("Bad block at %"PRIx32, nblock); // just clear cache and try a new block lfs2_cache_drop(lfs2, &lfs2->pcache); } } static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file) { file->off = file->pos; lfs2_alloc_ack(lfs2); int err = lfs2_file_relocate(lfs2, file); if (err) { return err; } file->flags &= ~LFS2_F_INLINE; return 0; } static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_ASSERT(file->flags & LFS2_F_OPENED); if (file->flags & LFS2_F_READING) { if (!(file->flags & LFS2_F_INLINE)) { lfs2_cache_drop(lfs2, &file->cache); } file->flags &= ~LFS2_F_READING; } if (file->flags & LFS2_F_WRITING) { lfs2_off_t pos = file->pos; if (!(file->flags & LFS2_F_INLINE)) { // copy over anything after current branch lfs2_file_t orig = { .ctz.head = file->ctz.head, .ctz.size = file->ctz.size, .flags = LFS2_O_RDONLY | LFS2_F_OPENED, .pos = file->pos, .cache = lfs2->rcache, }; lfs2_cache_drop(lfs2, &lfs2->rcache); while (file->pos < file->ctz.size) { // copy over a byte at a time, leave it up to caching // to make this efficient uint8_t data; lfs2_ssize_t res = lfs2_file_read(lfs2, &orig, &data, 1); if (res < 0) { return res; } res = lfs2_file_write(lfs2, file, &data, 1); if (res < 0) { return res; } // keep our reference to the rcache in sync if (lfs2->rcache.block != LFS2_BLOCK_NULL) { lfs2_cache_drop(lfs2, &orig.cache); lfs2_cache_drop(lfs2, &lfs2->rcache); } } // write out what we have while (true) { int err = lfs2_bd_flush(lfs2, &file->cache, &lfs2->rcache, true); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } return err; } break; relocate: LFS2_DEBUG("Bad block at %"PRIx32, file->block); err = lfs2_file_relocate(lfs2, file); if (err) { return err; } } } else { file->pos = lfs2_max(file->pos, file->ctz.size); } // actual file updates file->ctz.head = file->block; file->ctz.size = file->pos; file->flags &= ~LFS2_F_WRITING; file->flags |= LFS2_F_DIRTY; file->pos = pos; } return 0; } int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_sync(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(file->flags & LFS2_F_OPENED); while (true) { int err = lfs2_file_flush(lfs2, file); if (err) { file->flags |= LFS2_F_ERRED; LFS2_TRACE("lfs2_file_sync -> %d", err); return err; } if ((file->flags & LFS2_F_DIRTY) && !(file->flags & LFS2_F_ERRED) && !lfs2_pair_isnull(file->m.pair)) { // update dir entry uint16_t type; const void *buffer; lfs2_size_t size; struct lfs2_ctz ctz; if (file->flags & LFS2_F_INLINE) { // inline the whole file type = LFS2_TYPE_INLINESTRUCT; buffer = file->cache.buffer; size = file->ctz.size; } else { // update the ctz reference type = LFS2_TYPE_CTZSTRUCT; // copy ctz so alloc will work during a relocate ctz = file->ctz; lfs2_ctz_tole32(&ctz); buffer = &ctz; size = sizeof(ctz); } // commit file data and attributes err = lfs2_dir_commit(lfs2, &file->m, LFS2_MKATTRS( {LFS2_MKTAG(type, file->id, size), buffer}, {LFS2_MKTAG(LFS2_FROM_USERATTRS, file->id, file->cfg->attr_count), file->cfg->attrs})); if (err) { if (err == LFS2_ERR_NOSPC && (file->flags & LFS2_F_INLINE)) { goto relocate; } file->flags |= LFS2_F_ERRED; LFS2_TRACE("lfs2_file_sync -> %d", err); return err; } file->flags &= ~LFS2_F_DIRTY; } LFS2_TRACE("lfs2_file_sync -> %d", 0); return 0; relocate: // inline file doesn't fit anymore err = lfs2_file_outline(lfs2, file); if (err) { file->flags |= LFS2_F_ERRED; LFS2_TRACE("lfs2_file_sync -> %d", err); return err; } } } lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file, void *buffer, lfs2_size_t size) { LFS2_TRACE("lfs2_file_read(%p, %p, %p, %"PRIu32")", (void*)lfs2, (void*)file, buffer, size); LFS2_ASSERT(file->flags & LFS2_F_OPENED); LFS2_ASSERT((file->flags & 3) != LFS2_O_WRONLY); uint8_t *data = buffer; lfs2_size_t nsize = size; if (file->flags & LFS2_F_WRITING) { // flush out any writes int err = lfs2_file_flush(lfs2, file); if (err) { LFS2_TRACE("lfs2_file_read -> %"PRId32, err); return err; } } if (file->pos >= file->ctz.size) { // eof if past end LFS2_TRACE("lfs2_file_read -> %"PRId32, 0); return 0; } size = lfs2_min(size, file->ctz.size - file->pos); nsize = size; while (nsize > 0) { // check if we need a new block if (!(file->flags & LFS2_F_READING) || file->off == lfs2->cfg->block_size) { if (!(file->flags & LFS2_F_INLINE)) { int err = lfs2_ctz_find(lfs2, NULL, &file->cache, file->ctz.head, file->ctz.size, file->pos, &file->block, &file->off); if (err) { LFS2_TRACE("lfs2_file_read -> %"PRId32, err); return err; } } else { file->block = LFS2_BLOCK_INLINE; file->off = file->pos; } file->flags |= LFS2_F_READING; } // read as much as we can in current block lfs2_size_t diff = lfs2_min(nsize, lfs2->cfg->block_size - file->off); if (file->flags & LFS2_F_INLINE) { int err = lfs2_dir_getread(lfs2, &file->m, NULL, &file->cache, lfs2->cfg->block_size, LFS2_MKTAG(0xfff, 0x1ff, 0), LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0), file->off, data, diff); if (err) { LFS2_TRACE("lfs2_file_read -> %"PRId32, err); return err; } } else { int err = lfs2_bd_read(lfs2, NULL, &file->cache, lfs2->cfg->block_size, file->block, file->off, data, diff); if (err) { LFS2_TRACE("lfs2_file_read -> %"PRId32, err); return err; } } file->pos += diff; file->off += diff; data += diff; nsize -= diff; } LFS2_TRACE("lfs2_file_read -> %"PRId32, size); return size; } lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file, const void *buffer, lfs2_size_t size) { LFS2_TRACE("lfs2_file_write(%p, %p, %p, %"PRIu32")", (void*)lfs2, (void*)file, buffer, size); LFS2_ASSERT(file->flags & LFS2_F_OPENED); LFS2_ASSERT((file->flags & 3) != LFS2_O_RDONLY); const uint8_t *data = buffer; lfs2_size_t nsize = size; if (file->flags & LFS2_F_READING) { // drop any reads int err = lfs2_file_flush(lfs2, file); if (err) { LFS2_TRACE("lfs2_file_write -> %"PRId32, err); return err; } } if ((file->flags & LFS2_O_APPEND) && file->pos < file->ctz.size) { file->pos = file->ctz.size; } if (file->pos + size > lfs2->file_max) { // Larger than file limit? LFS2_TRACE("lfs2_file_write -> %"PRId32, LFS2_ERR_FBIG); return LFS2_ERR_FBIG; } if (!(file->flags & LFS2_F_WRITING) && file->pos > file->ctz.size) { // fill with zeros lfs2_off_t pos = file->pos; file->pos = file->ctz.size; while (file->pos < pos) { lfs2_ssize_t res = lfs2_file_write(lfs2, file, &(uint8_t){0}, 1); if (res < 0) { LFS2_TRACE("lfs2_file_write -> %"PRId32, res); return res; } } } if ((file->flags & LFS2_F_INLINE) && lfs2_max(file->pos+nsize, file->ctz.size) > lfs2_min(0x3fe, lfs2_min( lfs2->cfg->cache_size, lfs2->cfg->block_size/8))) { // inline file doesn't fit anymore int err = lfs2_file_outline(lfs2, file); if (err) { file->flags |= LFS2_F_ERRED; LFS2_TRACE("lfs2_file_write -> %"PRId32, err); return err; } } while (nsize > 0) { // check if we need a new block if (!(file->flags & LFS2_F_WRITING) || file->off == lfs2->cfg->block_size) { if (!(file->flags & LFS2_F_INLINE)) { if (!(file->flags & LFS2_F_WRITING) && file->pos > 0) { // find out which block we're extending from int err = lfs2_ctz_find(lfs2, NULL, &file->cache, file->ctz.head, file->ctz.size, file->pos-1, &file->block, &file->off); if (err) { file->flags |= LFS2_F_ERRED; LFS2_TRACE("lfs2_file_write -> %"PRId32, err); return err; } // mark cache as dirty since we may have read data into it lfs2_cache_zero(lfs2, &file->cache); } // extend file with new blocks lfs2_alloc_ack(lfs2); int err = lfs2_ctz_extend(lfs2, &file->cache, &lfs2->rcache, file->block, file->pos, &file->block, &file->off); if (err) { file->flags |= LFS2_F_ERRED; LFS2_TRACE("lfs2_file_write -> %"PRId32, err); return err; } } else { file->block = LFS2_BLOCK_INLINE; file->off = file->pos; } file->flags |= LFS2_F_WRITING; } // program as much as we can in current block lfs2_size_t diff = lfs2_min(nsize, lfs2->cfg->block_size - file->off); while (true) { int err = lfs2_bd_prog(lfs2, &file->cache, &lfs2->rcache, true, file->block, file->off, data, diff); if (err) { if (err == LFS2_ERR_CORRUPT) { goto relocate; } file->flags |= LFS2_F_ERRED; LFS2_TRACE("lfs2_file_write -> %"PRId32, err); return err; } break; relocate: err = lfs2_file_relocate(lfs2, file); if (err) { file->flags |= LFS2_F_ERRED; LFS2_TRACE("lfs2_file_write -> %"PRId32, err); return err; } } file->pos += diff; file->off += diff; data += diff; nsize -= diff; lfs2_alloc_ack(lfs2); } file->flags &= ~LFS2_F_ERRED; LFS2_TRACE("lfs2_file_write -> %"PRId32, size); return size; } lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file, lfs2_soff_t off, int whence) { LFS2_TRACE("lfs2_file_seek(%p, %p, %"PRId32", %d)", (void*)lfs2, (void*)file, off, whence); LFS2_ASSERT(file->flags & LFS2_F_OPENED); // write out everything beforehand, may be noop if rdonly int err = lfs2_file_flush(lfs2, file); if (err) { LFS2_TRACE("lfs2_file_seek -> %"PRId32, err); return err; } // find new pos lfs2_off_t npos = file->pos; if (whence == LFS2_SEEK_SET) { npos = off; } else if (whence == LFS2_SEEK_CUR) { npos = file->pos + off; } else if (whence == LFS2_SEEK_END) { npos = file->ctz.size + off; } if (npos > lfs2->file_max) { // file position out of range LFS2_TRACE("lfs2_file_seek -> %"PRId32, LFS2_ERR_INVAL); return LFS2_ERR_INVAL; } // update pos file->pos = npos; LFS2_TRACE("lfs2_file_seek -> %"PRId32, npos); return npos; } int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) { LFS2_TRACE("lfs2_file_truncate(%p, %p, %"PRIu32")", (void*)lfs2, (void*)file, size); LFS2_ASSERT(file->flags & LFS2_F_OPENED); LFS2_ASSERT((file->flags & 3) != LFS2_O_RDONLY); if (size > LFS2_FILE_MAX) { LFS2_TRACE("lfs2_file_truncate -> %d", LFS2_ERR_INVAL); return LFS2_ERR_INVAL; } lfs2_off_t pos = file->pos; lfs2_off_t oldsize = lfs2_file_size(lfs2, file); if (size < oldsize) { // need to flush since directly changing metadata int err = lfs2_file_flush(lfs2, file); if (err) { LFS2_TRACE("lfs2_file_truncate -> %d", err); return err; } // lookup new head in ctz skip list err = lfs2_ctz_find(lfs2, NULL, &file->cache, file->ctz.head, file->ctz.size, size, &file->block, &file->off); if (err) { LFS2_TRACE("lfs2_file_truncate -> %d", err); return err; } file->ctz.head = file->block; file->ctz.size = size; file->flags |= LFS2_F_DIRTY | LFS2_F_READING; } else if (size > oldsize) { // flush+seek if not already at end if (file->pos != oldsize) { lfs2_soff_t res = lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_END); if (res < 0) { LFS2_TRACE("lfs2_file_truncate -> %d", res); return (int)res; } } // fill with zeros while (file->pos < size) { lfs2_ssize_t res = lfs2_file_write(lfs2, file, &(uint8_t){0}, 1); if (res < 0) { LFS2_TRACE("lfs2_file_truncate -> %d", res); return (int)res; } } } // restore pos lfs2_soff_t res = lfs2_file_seek(lfs2, file, pos, LFS2_SEEK_SET); if (res < 0) { LFS2_TRACE("lfs2_file_truncate -> %d", res); return (int)res; } LFS2_TRACE("lfs2_file_truncate -> %d", 0); return 0; } lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_tell(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(file->flags & LFS2_F_OPENED); (void)lfs2; LFS2_TRACE("lfs2_file_tell -> %"PRId32, file->pos); return file->pos; } int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_rewind(%p, %p)", (void*)lfs2, (void*)file); lfs2_soff_t res = lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_SET); if (res < 0) { LFS2_TRACE("lfs2_file_rewind -> %d", res); return (int)res; } LFS2_TRACE("lfs2_file_rewind -> %d", 0); return 0; } lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_size(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(file->flags & LFS2_F_OPENED); (void)lfs2; if (file->flags & LFS2_F_WRITING) { LFS2_TRACE("lfs2_file_size -> %"PRId32, lfs2_max(file->pos, file->ctz.size)); return lfs2_max(file->pos, file->ctz.size); } else { LFS2_TRACE("lfs2_file_size -> %"PRId32, file->ctz.size); return file->ctz.size; } } /// General fs operations /// int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) { LFS2_TRACE("lfs2_stat(%p, \"%s\", %p)", (void*)lfs2, path, (void*)info); lfs2_mdir_t cwd; lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); if (tag < 0) { LFS2_TRACE("lfs2_stat -> %d", tag); return (int)tag; } int err = lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info); LFS2_TRACE("lfs2_stat -> %d", err); return err; } int lfs2_remove(lfs2_t *lfs2, const char *path) { LFS2_TRACE("lfs2_remove(%p, \"%s\")", (void*)lfs2, path); // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { LFS2_TRACE("lfs2_remove -> %d", err); return err; } lfs2_mdir_t cwd; lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); if (tag < 0 || lfs2_tag_id(tag) == 0x3ff) { LFS2_TRACE("lfs2_remove -> %d", (tag < 0) ? tag : LFS2_ERR_INVAL); return (tag < 0) ? (int)tag : LFS2_ERR_INVAL; } lfs2_mdir_t dir; if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) { // must be empty before removal lfs2_block_t pair[2]; lfs2_stag_t res = lfs2_dir_get(lfs2, &cwd, LFS2_MKTAG(0x700, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), pair); if (res < 0) { LFS2_TRACE("lfs2_remove -> %d", res); return (int)res; } lfs2_pair_fromle32(pair); err = lfs2_dir_fetch(lfs2, &dir, pair); if (err) { LFS2_TRACE("lfs2_remove -> %d", err); return err; } if (dir.count > 0 || dir.split) { LFS2_TRACE("lfs2_remove -> %d", LFS2_ERR_NOTEMPTY); return LFS2_ERR_NOTEMPTY; } // mark fs as orphaned lfs2_fs_preporphans(lfs2, +1); } // delete the entry err = lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_DELETE, lfs2_tag_id(tag), 0), NULL})); if (err) { LFS2_TRACE("lfs2_remove -> %d", err); return err; } if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) { // fix orphan lfs2_fs_preporphans(lfs2, -1); err = lfs2_fs_pred(lfs2, dir.pair, &cwd); if (err) { LFS2_TRACE("lfs2_remove -> %d", err); return err; } err = lfs2_dir_drop(lfs2, &cwd, &dir); if (err) { LFS2_TRACE("lfs2_remove -> %d", err); return err; } } LFS2_TRACE("lfs2_remove -> %d", 0); return 0; } int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) { LFS2_TRACE("lfs2_rename(%p, \"%s\", \"%s\")", (void*)lfs2, oldpath, newpath); // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { LFS2_TRACE("lfs2_rename -> %d", err); return err; } // find old entry lfs2_mdir_t oldcwd; lfs2_stag_t oldtag = lfs2_dir_find(lfs2, &oldcwd, &oldpath, NULL); if (oldtag < 0 || lfs2_tag_id(oldtag) == 0x3ff) { LFS2_TRACE("lfs2_rename -> %d", (oldtag < 0) ? oldtag : LFS2_ERR_INVAL); return (oldtag < 0) ? (int)oldtag : LFS2_ERR_INVAL; } // find new entry lfs2_mdir_t newcwd; uint16_t newid; lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid); if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) && !(prevtag == LFS2_ERR_NOENT && newid != 0x3ff)) { LFS2_TRACE("lfs2_rename -> %d", (prevtag < 0) ? prevtag : LFS2_ERR_INVAL); return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL; } lfs2_mdir_t prevdir; if (prevtag == LFS2_ERR_NOENT) { // check that name fits lfs2_size_t nlen = strlen(newpath); if (nlen > lfs2->name_max) { LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_NAMETOOLONG); return LFS2_ERR_NAMETOOLONG; } } else if (lfs2_tag_type3(prevtag) != lfs2_tag_type3(oldtag)) { LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_ISDIR); return LFS2_ERR_ISDIR; } else if (lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) { // must be empty before removal lfs2_block_t prevpair[2]; lfs2_stag_t res = lfs2_dir_get(lfs2, &newcwd, LFS2_MKTAG(0x700, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, newid, 8), prevpair); if (res < 0) { LFS2_TRACE("lfs2_rename -> %d", res); return (int)res; } lfs2_pair_fromle32(prevpair); // must be empty before removal err = lfs2_dir_fetch(lfs2, &prevdir, prevpair); if (err) { LFS2_TRACE("lfs2_rename -> %d", err); return err; } if (prevdir.count > 0 || prevdir.split) { LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_NOTEMPTY); return LFS2_ERR_NOTEMPTY; } // mark fs as orphaned lfs2_fs_preporphans(lfs2, +1); } // create move to fix later uint16_t newoldtagid = lfs2_tag_id(oldtag); if (lfs2_pair_cmp(oldcwd.pair, newcwd.pair) == 0 && prevtag == LFS2_ERR_NOENT && newid <= newoldtagid) { // there is a small chance we are being renamed in the same directory // to an id less than our old id, the global update to handle this // is a bit messy newoldtagid += 1; } lfs2_fs_prepmove(lfs2, newoldtagid, oldcwd.pair); // move over all attributes err = lfs2_dir_commit(lfs2, &newcwd, LFS2_MKATTRS( {prevtag != LFS2_ERR_NOENT ? LFS2_MKTAG(LFS2_TYPE_DELETE, newid, 0) : LFS2_MKTAG(LFS2_FROM_NOOP, 0, 0), NULL}, {LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0), NULL}, {LFS2_MKTAG(lfs2_tag_type3(oldtag), newid, strlen(newpath)), newpath}, {LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd})); if (err) { LFS2_TRACE("lfs2_rename -> %d", err); return err; } // let commit clean up after move (if we're different! otherwise move // logic already fixed it for us) if (lfs2_pair_cmp(oldcwd.pair, newcwd.pair) != 0) { err = lfs2_dir_commit(lfs2, &oldcwd, NULL, 0); if (err) { LFS2_TRACE("lfs2_rename -> %d", err); return err; } } if (prevtag != LFS2_ERR_NOENT && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) { // fix orphan lfs2_fs_preporphans(lfs2, -1); err = lfs2_fs_pred(lfs2, prevdir.pair, &newcwd); if (err) { LFS2_TRACE("lfs2_rename -> %d", err); return err; } err = lfs2_dir_drop(lfs2, &newcwd, &prevdir); if (err) { LFS2_TRACE("lfs2_rename -> %d", err); return err; } } LFS2_TRACE("lfs2_rename -> %d", 0); return 0; } lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path, uint8_t type, void *buffer, lfs2_size_t size) { LFS2_TRACE("lfs2_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", (void*)lfs2, path, type, buffer, size); lfs2_mdir_t cwd; lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); if (tag < 0) { LFS2_TRACE("lfs2_getattr -> %"PRId32, tag); return tag; } uint16_t id = lfs2_tag_id(tag); if (id == 0x3ff) { // special case for root id = 0; int err = lfs2_dir_fetch(lfs2, &cwd, lfs2->root); if (err) { LFS2_TRACE("lfs2_getattr -> %"PRId32, err); return err; } } tag = lfs2_dir_get(lfs2, &cwd, LFS2_MKTAG(0x7ff, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_USERATTR + type, id, lfs2_min(size, lfs2->attr_max)), buffer); if (tag < 0) { if (tag == LFS2_ERR_NOENT) { LFS2_TRACE("lfs2_getattr -> %"PRId32, LFS2_ERR_NOATTR); return LFS2_ERR_NOATTR; } LFS2_TRACE("lfs2_getattr -> %"PRId32, tag); return tag; } size = lfs2_tag_size(tag); LFS2_TRACE("lfs2_getattr -> %"PRId32, size); return size; } static int lfs2_commitattr(lfs2_t *lfs2, const char *path, uint8_t type, const void *buffer, lfs2_size_t size) { lfs2_mdir_t cwd; lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); if (tag < 0) { return tag; } uint16_t id = lfs2_tag_id(tag); if (id == 0x3ff) { // special case for root id = 0; int err = lfs2_dir_fetch(lfs2, &cwd, lfs2->root); if (err) { return err; } } return lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_USERATTR + type, id, size), buffer})); } int lfs2_setattr(lfs2_t *lfs2, const char *path, uint8_t type, const void *buffer, lfs2_size_t size) { LFS2_TRACE("lfs2_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", (void*)lfs2, path, type, buffer, size); if (size > lfs2->attr_max) { LFS2_TRACE("lfs2_setattr -> %d", LFS2_ERR_NOSPC); return LFS2_ERR_NOSPC; } int err = lfs2_commitattr(lfs2, path, type, buffer, size); LFS2_TRACE("lfs2_setattr -> %d", err); return err; } int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type) { LFS2_TRACE("lfs2_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs2, path, type); int err = lfs2_commitattr(lfs2, path, type, NULL, 0x3ff); LFS2_TRACE("lfs2_removeattr -> %d", err); return err; } /// Filesystem operations /// static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { lfs2->cfg = cfg; int err = 0; // validate that the lfs2-cfg sizes were initiated properly before // performing any arithmetic logics with them LFS2_ASSERT(lfs2->cfg->read_size != 0); LFS2_ASSERT(lfs2->cfg->prog_size != 0); LFS2_ASSERT(lfs2->cfg->cache_size != 0); // check that block size is a multiple of cache size is a multiple // of prog and read sizes LFS2_ASSERT(lfs2->cfg->cache_size % lfs2->cfg->read_size == 0); LFS2_ASSERT(lfs2->cfg->cache_size % lfs2->cfg->prog_size == 0); LFS2_ASSERT(lfs2->cfg->block_size % lfs2->cfg->cache_size == 0); // check that the block size is large enough to fit ctz pointers LFS2_ASSERT(4*lfs2_npw2(LFS2_BLOCK_NULL / (lfs2->cfg->block_size-2*4)) <= lfs2->cfg->block_size); // block_cycles = 0 is no longer supported. // // block_cycles is the number of erase cycles before littlefs evicts // metadata logs as a part of wear leveling. Suggested values are in the // range of 100-1000, or set block_cycles to -1 to disable block-level // wear-leveling. LFS2_ASSERT(lfs2->cfg->block_cycles != 0); // setup read cache if (lfs2->cfg->read_buffer) { lfs2->rcache.buffer = lfs2->cfg->read_buffer; } else { lfs2->rcache.buffer = lfs2_malloc(lfs2->cfg->cache_size); if (!lfs2->rcache.buffer) { err = LFS2_ERR_NOMEM; goto cleanup; } } // setup program cache if (lfs2->cfg->prog_buffer) { lfs2->pcache.buffer = lfs2->cfg->prog_buffer; } else { lfs2->pcache.buffer = lfs2_malloc(lfs2->cfg->cache_size); if (!lfs2->pcache.buffer) { err = LFS2_ERR_NOMEM; goto cleanup; } } // zero to avoid information leaks lfs2_cache_zero(lfs2, &lfs2->rcache); lfs2_cache_zero(lfs2, &lfs2->pcache); // setup lookahead, must be multiple of 64-bits, 32-bit aligned LFS2_ASSERT(lfs2->cfg->lookahead_size > 0); LFS2_ASSERT(lfs2->cfg->lookahead_size % 8 == 0 && (uintptr_t)lfs2->cfg->lookahead_buffer % 4 == 0); if (lfs2->cfg->lookahead_buffer) { lfs2->free.buffer = lfs2->cfg->lookahead_buffer; } else { lfs2->free.buffer = lfs2_malloc(lfs2->cfg->lookahead_size); if (!lfs2->free.buffer) { err = LFS2_ERR_NOMEM; goto cleanup; } } // check that the size limits are sane LFS2_ASSERT(lfs2->cfg->name_max <= LFS2_NAME_MAX); lfs2->name_max = lfs2->cfg->name_max; if (!lfs2->name_max) { lfs2->name_max = LFS2_NAME_MAX; } LFS2_ASSERT(lfs2->cfg->file_max <= LFS2_FILE_MAX); lfs2->file_max = lfs2->cfg->file_max; if (!lfs2->file_max) { lfs2->file_max = LFS2_FILE_MAX; } LFS2_ASSERT(lfs2->cfg->attr_max <= LFS2_ATTR_MAX); lfs2->attr_max = lfs2->cfg->attr_max; if (!lfs2->attr_max) { lfs2->attr_max = LFS2_ATTR_MAX; } // setup default state lfs2->root[0] = LFS2_BLOCK_NULL; lfs2->root[1] = LFS2_BLOCK_NULL; lfs2->mlist = NULL; lfs2->seed = 0; lfs2->gstate = (struct lfs2_gstate){0}; lfs2->gpending = (struct lfs2_gstate){0}; lfs2->gdelta = (struct lfs2_gstate){0}; #ifdef LFS2_MIGRATE lfs2->lfs21 = NULL; #endif return 0; cleanup: lfs2_deinit(lfs2); return err; } static int lfs2_deinit(lfs2_t *lfs2) { // free allocated memory if (!lfs2->cfg->read_buffer) { lfs2_free(lfs2->rcache.buffer); } if (!lfs2->cfg->prog_buffer) { lfs2_free(lfs2->pcache.buffer); } if (!lfs2->cfg->lookahead_buffer) { lfs2_free(lfs2->free.buffer); } return 0; } int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) { LFS2_TRACE("lfs2_format(%p, %p {.context=%p, " ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " ".attr_max=%"PRIu32"})", (void*)lfs2, (void*)cfg, cfg->context, (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); int err = 0; { err = lfs2_init(lfs2, cfg); if (err) { LFS2_TRACE("lfs2_format -> %d", err); return err; } // create free lookahead memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size); lfs2->free.off = 0; lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->cfg->block_count); lfs2->free.i = 0; lfs2_alloc_ack(lfs2); // create root dir lfs2_mdir_t root; err = lfs2_dir_alloc(lfs2, &root); if (err) { goto cleanup; } // write one superblock lfs2_superblock_t superblock = { .version = LFS2_DISK_VERSION, .block_size = lfs2->cfg->block_size, .block_count = lfs2->cfg->block_count, .name_max = lfs2->name_max, .file_max = lfs2->file_max, .attr_max = lfs2->attr_max, }; lfs2_superblock_tole32(&superblock); err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0), NULL}, {LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), "littlefs"}, {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), &superblock})); if (err) { goto cleanup; } // sanity check that fetch works err = lfs2_dir_fetch(lfs2, &root, (const lfs2_block_t[2]){0, 1}); if (err) { goto cleanup; } // force compaction to prevent accidentally mounting any // older version of littlefs that may live on disk root.erased = false; err = lfs2_dir_commit(lfs2, &root, NULL, 0); if (err) { goto cleanup; } } cleanup: lfs2_deinit(lfs2); LFS2_TRACE("lfs2_format -> %d", err); return err; } int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) { LFS2_TRACE("lfs2_mount(%p, %p {.context=%p, " ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " ".attr_max=%"PRIu32"})", (void*)lfs2, (void*)cfg, cfg->context, (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); int err = lfs2_init(lfs2, cfg); if (err) { LFS2_TRACE("lfs2_mount -> %d", err); return err; } // scan directory blocks for superblock and any global updates lfs2_mdir_t dir = {.tail = {0, 1}}; while (!lfs2_pair_isnull(dir.tail)) { // fetch next block in tail list lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, &dir, dir.tail, LFS2_MKTAG(0x7ff, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), NULL, lfs2_dir_find_match, &(struct lfs2_dir_find_match){ lfs2, "littlefs", 8}); if (tag < 0) { err = tag; goto cleanup; } // has superblock? if (tag && !lfs2_tag_isdelete(tag)) { // update root lfs2->root[0] = dir.pair[0]; lfs2->root[1] = dir.pair[1]; // grab superblock lfs2_superblock_t superblock; tag = lfs2_dir_get(lfs2, &dir, LFS2_MKTAG(0x7ff, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), &superblock); if (tag < 0) { err = tag; goto cleanup; } lfs2_superblock_fromle32(&superblock); // check version uint16_t major_version = (0xffff & (superblock.version >> 16)); uint16_t minor_version = (0xffff & (superblock.version >> 0)); if ((major_version != LFS2_DISK_VERSION_MAJOR || minor_version > LFS2_DISK_VERSION_MINOR)) { LFS2_ERROR("Invalid version %"PRIu16".%"PRIu16, major_version, minor_version); err = LFS2_ERR_INVAL; goto cleanup; } // check superblock configuration if (superblock.name_max) { if (superblock.name_max > lfs2->name_max) { LFS2_ERROR("Unsupported name_max (%"PRIu32" > %"PRIu32")", superblock.name_max, lfs2->name_max); err = LFS2_ERR_INVAL; goto cleanup; } lfs2->name_max = superblock.name_max; } if (superblock.file_max) { if (superblock.file_max > lfs2->file_max) { LFS2_ERROR("Unsupported file_max (%"PRIu32" > %"PRIu32")", superblock.file_max, lfs2->file_max); err = LFS2_ERR_INVAL; goto cleanup; } lfs2->file_max = superblock.file_max; } if (superblock.attr_max) { if (superblock.attr_max > lfs2->attr_max) { LFS2_ERROR("Unsupported attr_max (%"PRIu32" > %"PRIu32")", superblock.attr_max, lfs2->attr_max); err = LFS2_ERR_INVAL; goto cleanup; } lfs2->attr_max = superblock.attr_max; } } // has gstate? err = lfs2_dir_getgstate(lfs2, &dir, &lfs2->gpending); if (err) { goto cleanup; } } // found superblock? if (lfs2_pair_isnull(lfs2->root)) { err = LFS2_ERR_INVAL; goto cleanup; } // update littlefs with gstate lfs2->gpending.tag += !lfs2_tag_isvalid(lfs2->gpending.tag); lfs2->gstate = lfs2->gpending; if (lfs2_gstate_hasmove(&lfs2->gstate)) { LFS2_DEBUG("Found move %"PRIx32" %"PRIx32" %"PRIx16, lfs2->gstate.pair[0], lfs2->gstate.pair[1], lfs2_tag_id(lfs2->gstate.tag)); } // setup free lookahead lfs2->free.off = lfs2->seed % lfs2->cfg->block_size; lfs2->free.size = 0; lfs2->free.i = 0; lfs2_alloc_ack(lfs2); LFS2_TRACE("lfs2_mount -> %d", 0); return 0; cleanup: lfs2_unmount(lfs2); LFS2_TRACE("lfs2_mount -> %d", err); return err; } int lfs2_unmount(lfs2_t *lfs2) { LFS2_TRACE("lfs2_unmount(%p)", (void*)lfs2); int err = lfs2_deinit(lfs2); LFS2_TRACE("lfs2_unmount -> %d", err); return err; } /// Filesystem filesystem operations /// int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void *data, lfs2_block_t block), void *data) { LFS2_TRACE("lfs2_fs_traverse(%p, %p, %p)", (void*)lfs2, (void*)(uintptr_t)cb, data); // iterate over metadata pairs lfs2_mdir_t dir = {.tail = {0, 1}}; #ifdef LFS2_MIGRATE // also consider v1 blocks during migration if (lfs2->lfs21) { int err = lfs21_traverse(lfs2, cb, data); if (err) { LFS2_TRACE("lfs2_fs_traverse -> %d", err); return err; } dir.tail[0] = lfs2->root[0]; dir.tail[1] = lfs2->root[1]; } #endif while (!lfs2_pair_isnull(dir.tail)) { for (int i = 0; i < 2; i++) { int err = cb(data, dir.tail[i]); if (err) { LFS2_TRACE("lfs2_fs_traverse -> %d", err); return err; } } // iterate through ids in directory int err = lfs2_dir_fetch(lfs2, &dir, dir.tail); if (err) { LFS2_TRACE("lfs2_fs_traverse -> %d", err); return err; } for (uint16_t id = 0; id < dir.count; id++) { struct lfs2_ctz ctz; lfs2_stag_t tag = lfs2_dir_get(lfs2, &dir, LFS2_MKTAG(0x700, 0x3ff, 0), LFS2_MKTAG(LFS2_TYPE_STRUCT, id, sizeof(ctz)), &ctz); if (tag < 0) { if (tag == LFS2_ERR_NOENT) { continue; } LFS2_TRACE("lfs2_fs_traverse -> %d", tag); return tag; } lfs2_ctz_fromle32(&ctz); if (lfs2_tag_type3(tag) == LFS2_TYPE_CTZSTRUCT) { err = lfs2_ctz_traverse(lfs2, NULL, &lfs2->rcache, ctz.head, ctz.size, cb, data); if (err) { LFS2_TRACE("lfs2_fs_traverse -> %d", err); return err; } } } } // iterate over any open files for (lfs2_file_t *f = (lfs2_file_t*)lfs2->mlist; f; f = f->next) { if (f->type != LFS2_TYPE_REG) { continue; } if ((f->flags & LFS2_F_DIRTY) && !(f->flags & LFS2_F_INLINE)) { int err = lfs2_ctz_traverse(lfs2, &f->cache, &lfs2->rcache, f->ctz.head, f->ctz.size, cb, data); if (err) { LFS2_TRACE("lfs2_fs_traverse -> %d", err); return err; } } if ((f->flags & LFS2_F_WRITING) && !(f->flags & LFS2_F_INLINE)) { int err = lfs2_ctz_traverse(lfs2, &f->cache, &lfs2->rcache, f->block, f->pos, cb, data); if (err) { LFS2_TRACE("lfs2_fs_traverse -> %d", err); return err; } } } LFS2_TRACE("lfs2_fs_traverse -> %d", 0); return 0; } static int lfs2_fs_pred(lfs2_t *lfs2, const lfs2_block_t pair[2], lfs2_mdir_t *pdir) { // iterate over all directory directory entries pdir->tail[0] = 0; pdir->tail[1] = 1; while (!lfs2_pair_isnull(pdir->tail)) { if (lfs2_pair_cmp(pdir->tail, pair) == 0) { return 0; } int err = lfs2_dir_fetch(lfs2, pdir, pdir->tail); if (err) { return err; } } return LFS2_ERR_NOENT; } struct lfs2_fs_parent_match { lfs2_t *lfs2; const lfs2_block_t pair[2]; }; static int lfs2_fs_parent_match(void *data, lfs2_tag_t tag, const void *buffer) { struct lfs2_fs_parent_match *find = data; lfs2_t *lfs2 = find->lfs2; const struct lfs2_diskoff *disk = buffer; (void)tag; lfs2_block_t child[2]; int err = lfs2_bd_read(lfs2, &lfs2->pcache, &lfs2->rcache, lfs2->cfg->block_size, disk->block, disk->off, &child, sizeof(child)); if (err) { return err; } lfs2_pair_fromle32(child); return (lfs2_pair_cmp(child, find->pair) == 0) ? LFS2_CMP_EQ : LFS2_CMP_LT; } static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2], lfs2_mdir_t *parent) { // use fetchmatch with callback to find pairs parent->tail[0] = 0; parent->tail[1] = 1; while (!lfs2_pair_isnull(parent->tail)) { lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, parent, parent->tail, LFS2_MKTAG(0x7ff, 0, 0x3ff), LFS2_MKTAG(LFS2_TYPE_DIRSTRUCT, 0, 8), NULL, lfs2_fs_parent_match, &(struct lfs2_fs_parent_match){ lfs2, {pair[0], pair[1]}}); if (tag && tag != LFS2_ERR_NOENT) { return tag; } } return LFS2_ERR_NOENT; } static int lfs2_fs_relocate(lfs2_t *lfs2, const lfs2_block_t oldpair[2], lfs2_block_t newpair[2]) { // update internal root if (lfs2_pair_cmp(oldpair, lfs2->root) == 0) { LFS2_DEBUG("Relocating root %"PRIx32" %"PRIx32, newpair[0], newpair[1]); lfs2->root[0] = newpair[0]; lfs2->root[1] = newpair[1]; } // update internally tracked dirs for (struct lfs2_mlist *d = lfs2->mlist; d; d = d->next) { if (lfs2_pair_cmp(oldpair, d->m.pair) == 0) { d->m.pair[0] = newpair[0]; d->m.pair[1] = newpair[1]; } } // find parent lfs2_mdir_t parent; lfs2_stag_t tag = lfs2_fs_parent(lfs2, oldpair, &parent); if (tag < 0 && tag != LFS2_ERR_NOENT) { return tag; } if (tag != LFS2_ERR_NOENT) { // update disk, this creates a desync lfs2_fs_preporphans(lfs2, +1); lfs2_pair_tole32(newpair); int err = lfs2_dir_commit(lfs2, &parent, LFS2_MKATTRS({tag, newpair})); lfs2_pair_fromle32(newpair); if (err) { return err; } // next step, clean up orphans lfs2_fs_preporphans(lfs2, -1); } // find pred int err = lfs2_fs_pred(lfs2, oldpair, &parent); if (err && err != LFS2_ERR_NOENT) { return err; } // if we can't find dir, it must be new if (err != LFS2_ERR_NOENT) { // replace bad pair, either we clean up desync, or no desync occured lfs2_pair_tole32(newpair); err = lfs2_dir_commit(lfs2, &parent, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_TAIL + parent.split, 0x3ff, 8), newpair})); lfs2_pair_fromle32(newpair); if (err) { return err; } } return 0; } static void lfs2_fs_preporphans(lfs2_t *lfs2, int8_t orphans) { lfs2->gpending.tag += orphans; lfs2_gstate_xororphans(&lfs2->gdelta, &lfs2->gpending, lfs2_gstate_hasorphans(&lfs2->gpending)); lfs2_gstate_xororphans(&lfs2->gpending, &lfs2->gpending, lfs2_gstate_hasorphans(&lfs2->gpending)); } static void lfs2_fs_prepmove(lfs2_t *lfs2, uint16_t id, const lfs2_block_t pair[2]) { lfs2_gstate_xormove(&lfs2->gdelta, &lfs2->gpending, id, pair); lfs2_gstate_xormove(&lfs2->gpending, &lfs2->gpending, id, pair); } static int lfs2_fs_demove(lfs2_t *lfs2) { if (!lfs2_gstate_hasmove(&lfs2->gstate)) { return 0; } // Fix bad moves LFS2_DEBUG("Fixing move %"PRIx32" %"PRIx32" %"PRIx16, lfs2->gstate.pair[0], lfs2->gstate.pair[1], lfs2_tag_id(lfs2->gstate.tag)); // fetch and delete the moved entry lfs2_mdir_t movedir; int err = lfs2_dir_fetch(lfs2, &movedir, lfs2->gstate.pair); if (err) { return err; } // rely on cancel logic inside commit err = lfs2_dir_commit(lfs2, &movedir, NULL, 0); if (err) { return err; } return 0; } static int lfs2_fs_deorphan(lfs2_t *lfs2) { if (!lfs2_gstate_hasorphans(&lfs2->gstate)) { return 0; } // Fix any orphans lfs2_mdir_t pdir = {.split = true}; lfs2_mdir_t dir = {.tail = {0, 1}}; // iterate over all directory directory entries while (!lfs2_pair_isnull(dir.tail)) { int err = lfs2_dir_fetch(lfs2, &dir, dir.tail); if (err) { return err; } // check head blocks for orphans if (!pdir.split) { // check if we have a parent lfs2_mdir_t parent; lfs2_stag_t tag = lfs2_fs_parent(lfs2, pdir.tail, &parent); if (tag < 0 && tag != LFS2_ERR_NOENT) { return tag; } if (tag == LFS2_ERR_NOENT) { // we are an orphan LFS2_DEBUG("Fixing orphan %"PRIx32" %"PRIx32, pdir.tail[0], pdir.tail[1]); err = lfs2_dir_drop(lfs2, &pdir, &dir); if (err) { return err; } break; } lfs2_block_t pair[2]; lfs2_stag_t res = lfs2_dir_get(lfs2, &parent, LFS2_MKTAG(0x7ff, 0x3ff, 0), tag, pair); if (res < 0) { return res; } lfs2_pair_fromle32(pair); if (!lfs2_pair_sync(pair, pdir.tail)) { // we have desynced LFS2_DEBUG("Fixing half-orphan %"PRIx32" %"PRIx32, pair[0], pair[1]); lfs2_pair_tole32(pair); err = lfs2_dir_commit(lfs2, &pdir, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), pair})); lfs2_pair_fromle32(pair); if (err) { return err; } break; } } memcpy(&pdir, &dir, sizeof(pdir)); } // mark orphans as fixed lfs2_fs_preporphans(lfs2, -lfs2_gstate_getorphans(&lfs2->gstate)); lfs2->gstate = lfs2->gpending; return 0; } static int lfs2_fs_forceconsistency(lfs2_t *lfs2) { int err = lfs2_fs_demove(lfs2); if (err) { return err; } err = lfs2_fs_deorphan(lfs2); if (err) { return err; } return 0; } static int lfs2_fs_size_count(void *p, lfs2_block_t block) { (void)block; lfs2_size_t *size = p; *size += 1; return 0; } lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2) { LFS2_TRACE("lfs2_fs_size(%p)", (void*)lfs2); lfs2_size_t size = 0; int err = lfs2_fs_traverse(lfs2, lfs2_fs_size_count, &size); if (err) { LFS2_TRACE("lfs2_fs_size -> %"PRId32, err); return err; } LFS2_TRACE("lfs2_fs_size -> %"PRId32, err); return size; } #ifdef LFS2_MIGRATE ////// Migration from littelfs v1 below this ////// /// Version info /// // Software library version // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions #define LFS21_VERSION 0x00010007 #define LFS21_VERSION_MAJOR (0xffff & (LFS21_VERSION >> 16)) #define LFS21_VERSION_MINOR (0xffff & (LFS21_VERSION >> 0)) // Version of On-disk data structures // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions #define LFS21_DISK_VERSION 0x00010001 #define LFS21_DISK_VERSION_MAJOR (0xffff & (LFS21_DISK_VERSION >> 16)) #define LFS21_DISK_VERSION_MINOR (0xffff & (LFS21_DISK_VERSION >> 0)) /// v1 Definitions /// // File types enum lfs21_type { LFS21_TYPE_REG = 0x11, LFS21_TYPE_DIR = 0x22, LFS21_TYPE_SUPERBLOCK = 0x2e, }; typedef struct lfs21 { lfs2_block_t root[2]; } lfs21_t; typedef struct lfs21_entry { lfs2_off_t off; struct lfs21_disk_entry { uint8_t type; uint8_t elen; uint8_t alen; uint8_t nlen; union { struct { lfs2_block_t head; lfs2_size_t size; } file; lfs2_block_t dir[2]; } u; } d; } lfs21_entry_t; typedef struct lfs21_dir { struct lfs21_dir *next; lfs2_block_t pair[2]; lfs2_off_t off; lfs2_block_t head[2]; lfs2_off_t pos; struct lfs21_disk_dir { uint32_t rev; lfs2_size_t size; lfs2_block_t tail[2]; } d; } lfs21_dir_t; typedef struct lfs21_superblock { lfs2_off_t off; struct lfs21_disk_superblock { uint8_t type; uint8_t elen; uint8_t alen; uint8_t nlen; lfs2_block_t root[2]; uint32_t block_size; uint32_t block_count; uint32_t version; char magic[8]; } d; } lfs21_superblock_t; /// Low-level wrappers v1->v2 /// static void lfs21_crc(uint32_t *crc, const void *buffer, size_t size) { *crc = lfs2_crc(*crc, buffer, size); } static int lfs21_bd_read(lfs2_t *lfs2, lfs2_block_t block, lfs2_off_t off, void *buffer, lfs2_size_t size) { // if we ever do more than writes to alternating pairs, // this may need to consider pcache return lfs2_bd_read(lfs2, &lfs2->pcache, &lfs2->rcache, size, block, off, buffer, size); } static int lfs21_bd_crc(lfs2_t *lfs2, lfs2_block_t block, lfs2_off_t off, lfs2_size_t size, uint32_t *crc) { for (lfs2_off_t i = 0; i < size; i++) { uint8_t c; int err = lfs21_bd_read(lfs2, block, off+i, &c, 1); if (err) { return err; } lfs21_crc(crc, &c, 1); } return 0; } /// Endian swapping functions /// static void lfs21_dir_fromle32(struct lfs21_disk_dir *d) { d->rev = lfs2_fromle32(d->rev); d->size = lfs2_fromle32(d->size); d->tail[0] = lfs2_fromle32(d->tail[0]); d->tail[1] = lfs2_fromle32(d->tail[1]); } static void lfs21_dir_tole32(struct lfs21_disk_dir *d) { d->rev = lfs2_tole32(d->rev); d->size = lfs2_tole32(d->size); d->tail[0] = lfs2_tole32(d->tail[0]); d->tail[1] = lfs2_tole32(d->tail[1]); } static void lfs21_entry_fromle32(struct lfs21_disk_entry *d) { d->u.dir[0] = lfs2_fromle32(d->u.dir[0]); d->u.dir[1] = lfs2_fromle32(d->u.dir[1]); } static void lfs21_entry_tole32(struct lfs21_disk_entry *d) { d->u.dir[0] = lfs2_tole32(d->u.dir[0]); d->u.dir[1] = lfs2_tole32(d->u.dir[1]); } static void lfs21_superblock_fromle32(struct lfs21_disk_superblock *d) { d->root[0] = lfs2_fromle32(d->root[0]); d->root[1] = lfs2_fromle32(d->root[1]); d->block_size = lfs2_fromle32(d->block_size); d->block_count = lfs2_fromle32(d->block_count); d->version = lfs2_fromle32(d->version); } ///// Metadata pair and directory operations /// static inline lfs2_size_t lfs21_entry_size(const lfs21_entry_t *entry) { return 4 + entry->d.elen + entry->d.alen + entry->d.nlen; } static int lfs21_dir_fetch(lfs2_t *lfs2, lfs21_dir_t *dir, const lfs2_block_t pair[2]) { // copy out pair, otherwise may be aliasing dir const lfs2_block_t tpair[2] = {pair[0], pair[1]}; bool valid = false; // check both blocks for the most recent revision for (int i = 0; i < 2; i++) { struct lfs21_disk_dir test; int err = lfs21_bd_read(lfs2, tpair[i], 0, &test, sizeof(test)); lfs21_dir_fromle32(&test); if (err) { if (err == LFS2_ERR_CORRUPT) { continue; } return err; } if (valid && lfs2_scmp(test.rev, dir->d.rev) < 0) { continue; } if ((0x7fffffff & test.size) < sizeof(test)+4 || (0x7fffffff & test.size) > lfs2->cfg->block_size) { continue; } uint32_t crc = LFS2_BLOCK_NULL; lfs21_dir_tole32(&test); lfs21_crc(&crc, &test, sizeof(test)); lfs21_dir_fromle32(&test); err = lfs21_bd_crc(lfs2, tpair[i], sizeof(test), (0x7fffffff & test.size) - sizeof(test), &crc); if (err) { if (err == LFS2_ERR_CORRUPT) { continue; } return err; } if (crc != 0) { continue; } valid = true; // setup dir in case it's valid dir->pair[0] = tpair[(i+0) % 2]; dir->pair[1] = tpair[(i+1) % 2]; dir->off = sizeof(dir->d); dir->d = test; } if (!valid) { LFS2_ERROR("Corrupted dir pair at %" PRIx32 " %" PRIx32 , tpair[0], tpair[1]); return LFS2_ERR_CORRUPT; } return 0; } static int lfs21_dir_next(lfs2_t *lfs2, lfs21_dir_t *dir, lfs21_entry_t *entry) { while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) { if (!(0x80000000 & dir->d.size)) { entry->off = dir->off; return LFS2_ERR_NOENT; } int err = lfs21_dir_fetch(lfs2, dir, dir->d.tail); if (err) { return err; } dir->off = sizeof(dir->d); dir->pos += sizeof(dir->d) + 4; } int err = lfs21_bd_read(lfs2, dir->pair[0], dir->off, &entry->d, sizeof(entry->d)); lfs21_entry_fromle32(&entry->d); if (err) { return err; } entry->off = dir->off; dir->off += lfs21_entry_size(entry); dir->pos += lfs21_entry_size(entry); return 0; } /// littlefs v1 specific operations /// int lfs21_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data) { if (lfs2_pair_isnull(lfs2->lfs21->root)) { return 0; } // iterate over metadata pairs lfs21_dir_t dir; lfs21_entry_t entry; lfs2_block_t cwd[2] = {0, 1}; while (true) { for (int i = 0; i < 2; i++) { int err = cb(data, cwd[i]); if (err) { return err; } } int err = lfs21_dir_fetch(lfs2, &dir, cwd); if (err) { return err; } // iterate over contents while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { err = lfs21_bd_read(lfs2, dir.pair[0], dir.off, &entry.d, sizeof(entry.d)); lfs21_entry_fromle32(&entry.d); if (err) { return err; } dir.off += lfs21_entry_size(&entry); if ((0x70 & entry.d.type) == (0x70 & LFS21_TYPE_REG)) { err = lfs2_ctz_traverse(lfs2, NULL, &lfs2->rcache, entry.d.u.file.head, entry.d.u.file.size, cb, data); if (err) { return err; } } } // we also need to check if we contain a threaded v2 directory lfs2_mdir_t dir2 = {.split=true, .tail={cwd[0], cwd[1]}}; while (dir2.split) { err = lfs2_dir_fetch(lfs2, &dir2, dir2.tail); if (err) { break; } for (int i = 0; i < 2; i++) { err = cb(data, dir2.pair[i]); if (err) { return err; } } } cwd[0] = dir.d.tail[0]; cwd[1] = dir.d.tail[1]; if (lfs2_pair_isnull(cwd)) { break; } } return 0; } static int lfs21_moved(lfs2_t *lfs2, const void *e) { if (lfs2_pair_isnull(lfs2->lfs21->root)) { return 0; } // skip superblock lfs21_dir_t cwd; int err = lfs21_dir_fetch(lfs2, &cwd, (const lfs2_block_t[2]){0, 1}); if (err) { return err; } // iterate over all directory directory entries lfs21_entry_t entry; while (!lfs2_pair_isnull(cwd.d.tail)) { err = lfs21_dir_fetch(lfs2, &cwd, cwd.d.tail); if (err) { return err; } while (true) { err = lfs21_dir_next(lfs2, &cwd, &entry); if (err && err != LFS2_ERR_NOENT) { return err; } if (err == LFS2_ERR_NOENT) { break; } if (!(0x80 & entry.d.type) && memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) { return true; } } } return false; } /// Filesystem operations /// static int lfs21_mount(lfs2_t *lfs2, struct lfs21 *lfs21, const struct lfs2_config *cfg) { int err = 0; { err = lfs2_init(lfs2, cfg); if (err) { return err; } lfs2->lfs21 = lfs21; lfs2->lfs21->root[0] = LFS2_BLOCK_NULL; lfs2->lfs21->root[1] = LFS2_BLOCK_NULL; // setup free lookahead lfs2->free.off = 0; lfs2->free.size = 0; lfs2->free.i = 0; lfs2_alloc_ack(lfs2); // load superblock lfs21_dir_t dir; lfs21_superblock_t superblock; err = lfs21_dir_fetch(lfs2, &dir, (const lfs2_block_t[2]){0, 1}); if (err && err != LFS2_ERR_CORRUPT) { goto cleanup; } if (!err) { err = lfs21_bd_read(lfs2, dir.pair[0], sizeof(dir.d), &superblock.d, sizeof(superblock.d)); lfs21_superblock_fromle32(&superblock.d); if (err) { goto cleanup; } lfs2->lfs21->root[0] = superblock.d.root[0]; lfs2->lfs21->root[1] = superblock.d.root[1]; } if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) { LFS2_ERROR("Invalid superblock at %d %d", 0, 1); err = LFS2_ERR_CORRUPT; goto cleanup; } uint16_t major_version = (0xffff & (superblock.d.version >> 16)); uint16_t minor_version = (0xffff & (superblock.d.version >> 0)); if ((major_version != LFS21_DISK_VERSION_MAJOR || minor_version > LFS21_DISK_VERSION_MINOR)) { LFS2_ERROR("Invalid version %d.%d", major_version, minor_version); err = LFS2_ERR_INVAL; goto cleanup; } return 0; } cleanup: lfs2_deinit(lfs2); return err; } static int lfs21_unmount(lfs2_t *lfs2) { return lfs2_deinit(lfs2); } /// v1 migration /// int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) { LFS2_TRACE("lfs2_migrate(%p, %p {.context=%p, " ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " ".attr_max=%"PRIu32"})", (void*)lfs2, (void*)cfg, cfg->context, (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); struct lfs21 lfs21; int err = lfs21_mount(lfs2, &lfs21, cfg); if (err) { LFS2_TRACE("lfs2_migrate -> %d", err); return err; } { // iterate through each directory, copying over entries // into new directory lfs21_dir_t dir1; lfs2_mdir_t dir2; dir1.d.tail[0] = lfs2->lfs21->root[0]; dir1.d.tail[1] = lfs2->lfs21->root[1]; while (!lfs2_pair_isnull(dir1.d.tail)) { // iterate old dir err = lfs21_dir_fetch(lfs2, &dir1, dir1.d.tail); if (err) { goto cleanup; } // create new dir and bind as temporary pretend root err = lfs2_dir_alloc(lfs2, &dir2); if (err) { goto cleanup; } dir2.rev = dir1.d.rev; dir1.head[0] = dir1.pair[0]; dir1.head[1] = dir1.pair[1]; lfs2->root[0] = dir2.pair[0]; lfs2->root[1] = dir2.pair[1]; err = lfs2_dir_commit(lfs2, &dir2, NULL, 0); if (err) { goto cleanup; } while (true) { lfs21_entry_t entry1; err = lfs21_dir_next(lfs2, &dir1, &entry1); if (err && err != LFS2_ERR_NOENT) { goto cleanup; } if (err == LFS2_ERR_NOENT) { break; } // check that entry has not been moved if (entry1.d.type & 0x80) { int moved = lfs21_moved(lfs2, &entry1.d.u); if (moved < 0) { err = moved; goto cleanup; } if (moved) { continue; } entry1.d.type &= ~0x80; } // also fetch name char name[LFS2_NAME_MAX+1]; memset(name, 0, sizeof(name)); err = lfs21_bd_read(lfs2, dir1.pair[0], entry1.off + 4+entry1.d.elen+entry1.d.alen, name, entry1.d.nlen); if (err) { goto cleanup; } bool isdir = (entry1.d.type == LFS21_TYPE_DIR); // create entry in new dir err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root); if (err) { goto cleanup; } uint16_t id; err = lfs2_dir_find(lfs2, &dir2, &(const char*){name}, &id); if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) { err = (err < 0) ? err : LFS2_ERR_EXIST; goto cleanup; } lfs21_entry_tole32(&entry1.d); err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_CREATE, id, 0), NULL}, {LFS2_MKTAG( isdir ? LFS2_TYPE_DIR : LFS2_TYPE_REG, id, entry1.d.nlen), name}, {LFS2_MKTAG( isdir ? LFS2_TYPE_DIRSTRUCT : LFS2_TYPE_CTZSTRUCT, id, sizeof(&entry1.d.u)), &entry1.d.u})); lfs21_entry_fromle32(&entry1.d); if (err) { goto cleanup; } } if (!lfs2_pair_isnull(dir1.d.tail)) { // find last block and update tail to thread into fs err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root); if (err) { goto cleanup; } while (dir2.split) { err = lfs2_dir_fetch(lfs2, &dir2, dir2.tail); if (err) { goto cleanup; } } lfs2_pair_tole32(dir2.pair); err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 0), dir1.d.tail})); lfs2_pair_fromle32(dir2.pair); if (err) { goto cleanup; } } // Copy over first block to thread into fs. Unfortunately // if this fails there is not much we can do. LFS2_DEBUG("Migrating %"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, lfs2->root[0], lfs2->root[1], dir1.head[0], dir1.head[1]); err = lfs2_bd_erase(lfs2, dir1.head[1]); if (err) { goto cleanup; } err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root); if (err) { goto cleanup; } for (lfs2_off_t i = 0; i < dir2.off; i++) { uint8_t dat; err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, dir2.off, dir2.pair[0], i, &dat, 1); if (err) { goto cleanup; } err = lfs2_bd_prog(lfs2, &lfs2->pcache, &lfs2->rcache, true, dir1.head[1], i, &dat, 1); if (err) { goto cleanup; } } err = lfs2_bd_flush(lfs2, &lfs2->pcache, &lfs2->rcache, true); if (err) { goto cleanup; } } // Create new superblock. This marks a successful migration! err = lfs21_dir_fetch(lfs2, &dir1, (const lfs2_block_t[2]){0, 1}); if (err) { goto cleanup; } dir2.pair[0] = dir1.pair[0]; dir2.pair[1] = dir1.pair[1]; dir2.rev = dir1.d.rev; dir2.off = sizeof(dir2.rev); dir2.etag = LFS2_BLOCK_NULL; dir2.count = 0; dir2.tail[0] = lfs2->lfs21->root[0]; dir2.tail[1] = lfs2->lfs21->root[1]; dir2.erased = false; dir2.split = true; lfs2_superblock_t superblock = { .version = LFS2_DISK_VERSION, .block_size = lfs2->cfg->block_size, .block_count = lfs2->cfg->block_count, .name_max = lfs2->name_max, .file_max = lfs2->file_max, .attr_max = lfs2->attr_max, }; lfs2_superblock_tole32(&superblock); err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS( {LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0), NULL}, {LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), "littlefs"}, {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), &superblock})); if (err) { goto cleanup; } // sanity check that fetch works err = lfs2_dir_fetch(lfs2, &dir2, (const lfs2_block_t[2]){0, 1}); if (err) { goto cleanup; } // force compaction to prevent accidentally mounting v1 dir2.erased = false; err = lfs2_dir_commit(lfs2, &dir2, NULL, 0); if (err) { goto cleanup; } } cleanup: lfs21_unmount(lfs2); LFS2_TRACE("lfs2_migrate -> %d", err); return err; } #endif micropython-1.12/lib/littlefs/lfs2.h000066400000000000000000000536571357706137100174550ustar00rootroot00000000000000/* * The little filesystem * * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LFS2_H #define LFS2_H #include #include #ifdef __cplusplus extern "C" { #endif /// Version info /// // Software library version // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions #define LFS2_VERSION 0x00020001 #define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16)) #define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0)) // Version of On-disk data structures // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions #define LFS2_DISK_VERSION 0x00020000 #define LFS2_DISK_VERSION_MAJOR (0xffff & (LFS2_DISK_VERSION >> 16)) #define LFS2_DISK_VERSION_MINOR (0xffff & (LFS2_DISK_VERSION >> 0)) /// Definitions /// // Type definitions typedef uint32_t lfs2_size_t; typedef uint32_t lfs2_off_t; typedef int32_t lfs2_ssize_t; typedef int32_t lfs2_soff_t; typedef uint32_t lfs2_block_t; // Maximum name size in bytes, may be redefined to reduce the size of the // info struct. Limited to <= 1022. Stored in superblock and must be // respected by other littlefs drivers. #ifndef LFS2_NAME_MAX #define LFS2_NAME_MAX 255 #endif // Maximum size of a file in bytes, may be redefined to limit to support other // drivers. Limited on disk to <= 4294967296. However, above 2147483647 the // functions lfs2_file_seek, lfs2_file_size, and lfs2_file_tell will return // incorrect values due to using signed integers. Stored in superblock and // must be respected by other littlefs drivers. #ifndef LFS2_FILE_MAX #define LFS2_FILE_MAX 2147483647 #endif // Maximum size of custom attributes in bytes, may be redefined, but there is // no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022. #ifndef LFS2_ATTR_MAX #define LFS2_ATTR_MAX 1022 #endif // Possible error codes, these are negative to allow // valid positive return values enum lfs2_error { LFS2_ERR_OK = 0, // No error LFS2_ERR_IO = -5, // Error during device operation LFS2_ERR_CORRUPT = -84, // Corrupted LFS2_ERR_NOENT = -2, // No directory entry LFS2_ERR_EXIST = -17, // Entry already exists LFS2_ERR_NOTDIR = -20, // Entry is not a dir LFS2_ERR_ISDIR = -21, // Entry is a dir LFS2_ERR_NOTEMPTY = -39, // Dir is not empty LFS2_ERR_BADF = -9, // Bad file number LFS2_ERR_FBIG = -27, // File too large LFS2_ERR_INVAL = -22, // Invalid parameter LFS2_ERR_NOSPC = -28, // No space left on device LFS2_ERR_NOMEM = -12, // No more memory available LFS2_ERR_NOATTR = -61, // No data/attr available LFS2_ERR_NAMETOOLONG = -36, // File name too long }; // File types enum lfs2_type { // file types LFS2_TYPE_REG = 0x001, LFS2_TYPE_DIR = 0x002, // internally used types LFS2_TYPE_SPLICE = 0x400, LFS2_TYPE_NAME = 0x000, LFS2_TYPE_STRUCT = 0x200, LFS2_TYPE_USERATTR = 0x300, LFS2_TYPE_FROM = 0x100, LFS2_TYPE_TAIL = 0x600, LFS2_TYPE_GLOBALS = 0x700, LFS2_TYPE_CRC = 0x500, // internally used type specializations LFS2_TYPE_CREATE = 0x401, LFS2_TYPE_DELETE = 0x4ff, LFS2_TYPE_SUPERBLOCK = 0x0ff, LFS2_TYPE_DIRSTRUCT = 0x200, LFS2_TYPE_CTZSTRUCT = 0x202, LFS2_TYPE_INLINESTRUCT = 0x201, LFS2_TYPE_SOFTTAIL = 0x600, LFS2_TYPE_HARDTAIL = 0x601, LFS2_TYPE_MOVESTATE = 0x7ff, // internal chip sources LFS2_FROM_NOOP = 0x000, LFS2_FROM_MOVE = 0x101, LFS2_FROM_USERATTRS = 0x102, }; // File open flags enum lfs2_open_flags { // open flags LFS2_O_RDONLY = 1, // Open a file as read only LFS2_O_WRONLY = 2, // Open a file as write only LFS2_O_RDWR = 3, // Open a file as read and write LFS2_O_CREAT = 0x0100, // Create a file if it does not exist LFS2_O_EXCL = 0x0200, // Fail if a file already exists LFS2_O_TRUNC = 0x0400, // Truncate the existing file to zero size LFS2_O_APPEND = 0x0800, // Move to end of file on every write // internally used flags LFS2_F_DIRTY = 0x010000, // File does not match storage LFS2_F_WRITING = 0x020000, // File has been written since last flush LFS2_F_READING = 0x040000, // File has been read since last flush LFS2_F_ERRED = 0x080000, // An error occured during write LFS2_F_INLINE = 0x100000, // Currently inlined in directory entry LFS2_F_OPENED = 0x200000, // File has been opened }; // File seek flags enum lfs2_whence_flags { LFS2_SEEK_SET = 0, // Seek relative to an absolute position LFS2_SEEK_CUR = 1, // Seek relative to the current file position LFS2_SEEK_END = 2, // Seek relative to the end of the file }; // Configuration provided during initialization of the littlefs struct lfs2_config { // Opaque user provided context that can be used to pass // information to the block device operations void *context; // Read a region in a block. Negative error codes are propogated // to the user. int (*read)(const struct lfs2_config *c, lfs2_block_t block, lfs2_off_t off, void *buffer, lfs2_size_t size); // Program a region in a block. The block must have previously // been erased. Negative error codes are propogated to the user. // May return LFS2_ERR_CORRUPT if the block should be considered bad. int (*prog)(const struct lfs2_config *c, lfs2_block_t block, lfs2_off_t off, const void *buffer, lfs2_size_t size); // Erase a block. A block must be erased before being programmed. // The state of an erased block is undefined. Negative error codes // are propogated to the user. // May return LFS2_ERR_CORRUPT if the block should be considered bad. int (*erase)(const struct lfs2_config *c, lfs2_block_t block); // Sync the state of the underlying block device. Negative error codes // are propogated to the user. int (*sync)(const struct lfs2_config *c); // Minimum size of a block read. All read operations will be a // multiple of this value. lfs2_size_t read_size; // Minimum size of a block program. All program operations will be a // multiple of this value. lfs2_size_t prog_size; // Size of an erasable block. This does not impact ram consumption and // may be larger than the physical erase size. However, non-inlined files // take up at minimum one block. Must be a multiple of the read // and program sizes. lfs2_size_t block_size; // Number of erasable blocks on the device. lfs2_size_t block_count; // Number of erase cycles before littlefs evicts metadata logs and moves // the metadata to another block. Suggested values are in the // range 100-1000, with large values having better performance at the cost // of less consistent wear distribution. // // Set to -1 to disable block-level wear-leveling. int32_t block_cycles; // Size of block caches. Each cache buffers a portion of a block in RAM. // The littlefs needs a read cache, a program cache, and one additional // cache per file. Larger caches can improve performance by storing more // data and reducing the number of disk accesses. Must be a multiple of // the read and program sizes, and a factor of the block size. lfs2_size_t cache_size; // Size of the lookahead buffer in bytes. A larger lookahead buffer // increases the number of blocks found during an allocation pass. The // lookahead buffer is stored as a compact bitmap, so each byte of RAM // can track 8 blocks. Must be a multiple of 8. lfs2_size_t lookahead_size; // Optional statically allocated read buffer. Must be cache_size. // By default lfs2_malloc is used to allocate this buffer. void *read_buffer; // Optional statically allocated program buffer. Must be cache_size. // By default lfs2_malloc is used to allocate this buffer. void *prog_buffer; // Optional statically allocated lookahead buffer. Must be lookahead_size // and aligned to a 32-bit boundary. By default lfs2_malloc is used to // allocate this buffer. void *lookahead_buffer; // Optional upper limit on length of file names in bytes. No downside for // larger names except the size of the info struct which is controlled by // the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX when zero. Stored in // superblock and must be respected by other littlefs drivers. lfs2_size_t name_max; // Optional upper limit on files in bytes. No downside for larger files // but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX when zero. Stored // in superblock and must be respected by other littlefs drivers. lfs2_size_t file_max; // Optional upper limit on custom attributes in bytes. No downside for // larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to // LFS2_ATTR_MAX when zero. lfs2_size_t attr_max; }; // File info structure struct lfs2_info { // Type of the file, either LFS2_TYPE_REG or LFS2_TYPE_DIR uint8_t type; // Size of the file, only valid for REG files. Limited to 32-bits. lfs2_size_t size; // Name of the file stored as a null-terminated string. Limited to // LFS2_NAME_MAX+1, which can be changed by redefining LFS2_NAME_MAX to // reduce RAM. LFS2_NAME_MAX is stored in superblock and must be // respected by other littlefs drivers. char name[LFS2_NAME_MAX+1]; }; // Custom attribute structure, used to describe custom attributes // committed atomically during file writes. struct lfs2_attr { // 8-bit type of attribute, provided by user and used to // identify the attribute uint8_t type; // Pointer to buffer containing the attribute void *buffer; // Size of attribute in bytes, limited to LFS2_ATTR_MAX lfs2_size_t size; }; // Optional configuration provided during lfs2_file_opencfg struct lfs2_file_config { // Optional statically allocated file buffer. Must be cache_size. // By default lfs2_malloc is used to allocate this buffer. void *buffer; // Optional list of custom attributes related to the file. If the file // is opened with read access, these attributes will be read from disk // during the open call. If the file is opened with write access, the // attributes will be written to disk every file sync or close. This // write occurs atomically with update to the file's contents. // // Custom attributes are uniquely identified by an 8-bit type and limited // to LFS2_ATTR_MAX bytes. When read, if the stored attribute is smaller // than the buffer, it will be padded with zeros. If the stored attribute // is larger, then it will be silently truncated. If the attribute is not // found, it will be created implicitly. struct lfs2_attr *attrs; // Number of custom attributes in the list lfs2_size_t attr_count; }; /// internal littlefs data structures /// typedef struct lfs2_cache { lfs2_block_t block; lfs2_off_t off; lfs2_size_t size; uint8_t *buffer; } lfs2_cache_t; typedef struct lfs2_mdir { lfs2_block_t pair[2]; uint32_t rev; lfs2_off_t off; uint32_t etag; uint16_t count; bool erased; bool split; lfs2_block_t tail[2]; } lfs2_mdir_t; // littlefs directory type typedef struct lfs2_dir { struct lfs2_dir *next; uint16_t id; uint8_t type; lfs2_mdir_t m; lfs2_off_t pos; lfs2_block_t head[2]; } lfs2_dir_t; // littlefs file type typedef struct lfs2_file { struct lfs2_file *next; uint16_t id; uint8_t type; lfs2_mdir_t m; struct lfs2_ctz { lfs2_block_t head; lfs2_size_t size; } ctz; uint32_t flags; lfs2_off_t pos; lfs2_block_t block; lfs2_off_t off; lfs2_cache_t cache; const struct lfs2_file_config *cfg; } lfs2_file_t; typedef struct lfs2_superblock { uint32_t version; lfs2_size_t block_size; lfs2_size_t block_count; lfs2_size_t name_max; lfs2_size_t file_max; lfs2_size_t attr_max; } lfs2_superblock_t; // The littlefs filesystem type typedef struct lfs2 { lfs2_cache_t rcache; lfs2_cache_t pcache; lfs2_block_t root[2]; struct lfs2_mlist { struct lfs2_mlist *next; uint16_t id; uint8_t type; lfs2_mdir_t m; } *mlist; uint32_t seed; struct lfs2_gstate { uint32_t tag; lfs2_block_t pair[2]; } gstate, gpending, gdelta; struct lfs2_free { lfs2_block_t off; lfs2_block_t size; lfs2_block_t i; lfs2_block_t ack; uint32_t *buffer; } free; const struct lfs2_config *cfg; lfs2_size_t name_max; lfs2_size_t file_max; lfs2_size_t attr_max; #ifdef LFS2_MIGRATE struct lfs21 *lfs21; #endif } lfs2_t; /// Filesystem functions /// // Format a block device with the littlefs // // Requires a littlefs object and config struct. This clobbers the littlefs // object, and does not leave the filesystem mounted. The config struct must // be zeroed for defaults and backwards compatibility. // // Returns a negative error code on failure. int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *config); // Mounts a littlefs // // Requires a littlefs object and config struct. Multiple filesystems // may be mounted simultaneously with multiple littlefs objects. Both // lfs2 and config must be allocated while mounted. The config struct must // be zeroed for defaults and backwards compatibility. // // Returns a negative error code on failure. int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *config); // Unmounts a littlefs // // Does nothing besides releasing any allocated resources. // Returns a negative error code on failure. int lfs2_unmount(lfs2_t *lfs2); /// General operations /// // Removes a file or directory // // If removing a directory, the directory must be empty. // Returns a negative error code on failure. int lfs2_remove(lfs2_t *lfs2, const char *path); // Rename or move a file or directory // // If the destination exists, it must match the source in type. // If the destination is a directory, the directory must be empty. // // Returns a negative error code on failure. int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath); // Find info about a file or directory // // Fills out the info structure, based on the specified file or directory. // Returns a negative error code on failure. int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info); // Get a custom attribute // // Custom attributes are uniquely identified by an 8-bit type and limited // to LFS2_ATTR_MAX bytes. When read, if the stored attribute is smaller than // the buffer, it will be padded with zeros. If the stored attribute is larger, // then it will be silently truncated. If no attribute is found, the error // LFS2_ERR_NOATTR is returned and the buffer is filled with zeros. // // Returns the size of the attribute, or a negative error code on failure. // Note, the returned size is the size of the attribute on disk, irrespective // of the size of the buffer. This can be used to dynamically allocate a buffer // or check for existance. lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path, uint8_t type, void *buffer, lfs2_size_t size); // Set custom attributes // // Custom attributes are uniquely identified by an 8-bit type and limited // to LFS2_ATTR_MAX bytes. If an attribute is not found, it will be // implicitly created. // // Returns a negative error code on failure. int lfs2_setattr(lfs2_t *lfs2, const char *path, uint8_t type, const void *buffer, lfs2_size_t size); // Removes a custom attribute // // If an attribute is not found, nothing happens. // // Returns a negative error code on failure. int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type); /// File operations /// // Open a file // // The mode that the file is opened in is determined by the flags, which // are values from the enum lfs2_open_flags that are bitwise-ored together. // // Returns a negative error code on failure. int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags); // Open a file with extra configuration // // The mode that the file is opened in is determined by the flags, which // are values from the enum lfs2_open_flags that are bitwise-ored together. // // The config struct provides additional config options per file as described // above. The config struct must be allocated while the file is open, and the // config struct must be zeroed for defaults and backwards compatibility. // // Returns a negative error code on failure. int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags, const struct lfs2_file_config *config); // Close a file // // Any pending writes are written out to storage as though // sync had been called and releases any allocated resources. // // Returns a negative error code on failure. int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file); // Synchronize a file on storage // // Any pending writes are written out to storage. // Returns a negative error code on failure. int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file); // Read data from file // // Takes a buffer and size indicating where to store the read data. // Returns the number of bytes read, or a negative error code on failure. lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file, void *buffer, lfs2_size_t size); // Write data to file // // Takes a buffer and size indicating the data to write. The file will not // actually be updated on the storage until either sync or close is called. // // Returns the number of bytes written, or a negative error code on failure. lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file, const void *buffer, lfs2_size_t size); // Change the position of the file // // The change in position is determined by the offset and whence flag. // Returns the new position of the file, or a negative error code on failure. lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file, lfs2_soff_t off, int whence); // Truncates the size of the file to the specified size // // Returns a negative error code on failure. int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size); // Return the position of the file // // Equivalent to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_CUR) // Returns the position of the file, or a negative error code on failure. lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file); // Change the position of the file to the beginning of the file // // Equivalent to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_SET) // Returns a negative error code on failure. int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file); // Return the size of the file // // Similar to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_END) // Returns the size of the file, or a negative error code on failure. lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file); /// Directory operations /// // Create a directory // // Returns a negative error code on failure. int lfs2_mkdir(lfs2_t *lfs2, const char *path); // Open a directory // // Once open a directory can be used with read to iterate over files. // Returns a negative error code on failure. int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path); // Close a directory // // Releases any allocated resources. // Returns a negative error code on failure. int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir); // Read an entry in the directory // // Fills out the info structure, based on the specified file or directory. // Returns a positive value on success, 0 at the end of directory, // or a negative error code on failure. int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info); // Change the position of the directory // // The new off must be a value previous returned from tell and specifies // an absolute offset in the directory seek. // // Returns a negative error code on failure. int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off); // Return the position of the directory // // The returned offset is only meant to be consumed by seek and may not make // sense, but does indicate the current position in the directory iteration. // // Returns the position of the directory, or a negative error code on failure. lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir); // Change the position of the directory to the beginning of the directory // // Returns a negative error code on failure. int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir); /// Filesystem-level filesystem operations // Finds the current size of the filesystem // // Note: Result is best effort. If files share COW structures, the returned // size may be larger than the filesystem actually is. // // Returns the number of allocated blocks, or a negative error code on failure. lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2); // Traverse through all blocks in use by the filesystem // // The provided callback will be called with each block address that is // currently in use by the filesystem. This can be used to determine which // blocks are in use or how much of the storage is available. // // Returns a negative error code on failure. int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data); #ifdef LFS2_MIGRATE // Attempts to migrate a previous version of littlefs // // Behaves similarly to the lfs2_format function. Attempts to mount // the previous version of littlefs and update the filesystem so it can be // mounted with the current version of littlefs. // // Requires a littlefs object and config struct. This clobbers the littlefs // object, and does not leave the filesystem mounted. The config struct must // be zeroed for defaults and backwards compatibility. // // Returns a negative error code on failure. int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg); #endif #ifdef __cplusplus } /* extern "C" */ #endif #endif micropython-1.12/lib/littlefs/lfs2_util.c000066400000000000000000000015421357706137100204670ustar00rootroot00000000000000/* * lfs2 util functions * * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #include "lfs2_util.h" // Only compile if user does not provide custom config #ifndef LFS2_CONFIG // Software CRC implementation with small lookup table uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) { static const uint32_t rtable[16] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c, }; const uint8_t *data = buffer; for (size_t i = 0; i < size; i++) { crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf]; crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf]; } return crc; } #endif micropython-1.12/lib/littlefs/lfs2_util.h000066400000000000000000000154461357706137100205040ustar00rootroot00000000000000/* * lfs2 utility functions * * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LFS2_UTIL_H #define LFS2_UTIL_H // Users can override lfs2_util.h with their own configuration by defining // LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h). // // If LFS2_CONFIG is used, none of the default utils will be emitted and must be // provided by the config file. To start, I would suggest copying lfs2_util.h // and modifying as needed. #ifdef LFS2_CONFIG #define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x) #define LFS2_STRINGIZE2(x) #x #include LFS2_STRINGIZE(LFS2_CONFIG) #else // System includes #include #include #include #include #ifndef LFS2_NO_MALLOC #include #endif #ifndef LFS2_NO_ASSERT #include #endif #if !defined(LFS2_NO_DEBUG) || \ !defined(LFS2_NO_WARN) || \ !defined(LFS2_NO_ERROR) || \ defined(LFS2_YES_TRACE) #include #endif #ifdef __cplusplus extern "C" { #endif // Macros, may be replaced by system specific wrappers. Arguments to these // macros must not have side-effects as the macros can be removed for a smaller // code footprint // Logging functions #ifdef LFS2_YES_TRACE #define LFS2_TRACE(fmt, ...) \ printf("lfs2_trace:%d: " fmt "\n", __LINE__, __VA_ARGS__) #else #define LFS2_TRACE(fmt, ...) #endif #ifndef LFS2_NO_DEBUG #define LFS2_DEBUG(fmt, ...) \ printf("lfs2_debug:%d: " fmt "\n", __LINE__, __VA_ARGS__) #else #define LFS2_DEBUG(fmt, ...) #endif #ifndef LFS2_NO_WARN #define LFS2_WARN(fmt, ...) \ printf("lfs2_warn:%d: " fmt "\n", __LINE__, __VA_ARGS__) #else #define LFS2_WARN(fmt, ...) #endif #ifndef LFS2_NO_ERROR #define LFS2_ERROR(fmt, ...) \ printf("lfs2_error:%d: " fmt "\n", __LINE__, __VA_ARGS__) #else #define LFS2_ERROR(fmt, ...) #endif // Runtime assertions #ifndef LFS2_NO_ASSERT #define LFS2_ASSERT(test) assert(test) #else #define LFS2_ASSERT(test) #endif // Builtin functions, these may be replaced by more efficient // toolchain-specific implementations. LFS2_NO_INTRINSICS falls back to a more // expensive basic C implementation for debugging purposes // Min/max functions for unsigned 32-bit numbers static inline uint32_t lfs2_max(uint32_t a, uint32_t b) { return (a > b) ? a : b; } static inline uint32_t lfs2_min(uint32_t a, uint32_t b) { return (a < b) ? a : b; } // Align to nearest multiple of a size static inline uint32_t lfs2_aligndown(uint32_t a, uint32_t alignment) { return a - (a % alignment); } static inline uint32_t lfs2_alignup(uint32_t a, uint32_t alignment) { return lfs2_aligndown(a + alignment-1, alignment); } // Find the next smallest power of 2 less than or equal to a static inline uint32_t lfs2_npw2(uint32_t a) { #if !defined(LFS2_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) return 32 - __builtin_clz(a-1); #else uint32_t r = 0; uint32_t s; a -= 1; s = (a > 0xffff) << 4; a >>= s; r |= s; s = (a > 0xff ) << 3; a >>= s; r |= s; s = (a > 0xf ) << 2; a >>= s; r |= s; s = (a > 0x3 ) << 1; a >>= s; r |= s; return (r | (a >> 1)) + 1; #endif } // Count the number of trailing binary zeros in a // lfs2_ctz(0) may be undefined static inline uint32_t lfs2_ctz(uint32_t a) { #if !defined(LFS2_NO_INTRINSICS) && defined(__GNUC__) return __builtin_ctz(a); #else return lfs2_npw2((a & -a) + 1) - 1; #endif } // Count the number of binary ones in a static inline uint32_t lfs2_popc(uint32_t a) { #if !defined(LFS2_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) return __builtin_popcount(a); #else a = a - ((a >> 1) & 0x55555555); a = (a & 0x33333333) + ((a >> 2) & 0x33333333); return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; #endif } // Find the sequence comparison of a and b, this is the distance // between a and b ignoring overflow static inline int lfs2_scmp(uint32_t a, uint32_t b) { return (int)(unsigned)(a - b); } // Convert between 32-bit little-endian and native order static inline uint32_t lfs2_fromle32(uint32_t a) { #if !defined(LFS2_NO_INTRINSICS) && ( \ (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) return a; #elif !defined(LFS2_NO_INTRINSICS) && ( \ (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) return __builtin_bswap32(a); #else return (((uint8_t*)&a)[0] << 0) | (((uint8_t*)&a)[1] << 8) | (((uint8_t*)&a)[2] << 16) | (((uint8_t*)&a)[3] << 24); #endif } static inline uint32_t lfs2_tole32(uint32_t a) { return lfs2_fromle32(a); } // Convert between 32-bit big-endian and native order static inline uint32_t lfs2_frombe32(uint32_t a) { #if !defined(LFS2_NO_INTRINSICS) && ( \ (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) return __builtin_bswap32(a); #elif !defined(LFS2_NO_INTRINSICS) && ( \ (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) return a; #else return (((uint8_t*)&a)[0] << 24) | (((uint8_t*)&a)[1] << 16) | (((uint8_t*)&a)[2] << 8) | (((uint8_t*)&a)[3] << 0); #endif } static inline uint32_t lfs2_tobe32(uint32_t a) { return lfs2_frombe32(a); } // Calculate CRC-32 with polynomial = 0x04c11db7 uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size); // Allocate memory, only used if buffers are not provided to littlefs // Note, memory must be 64-bit aligned static inline void *lfs2_malloc(size_t size) { #ifndef LFS2_NO_MALLOC return malloc(size); #else (void)size; return NULL; #endif } // Deallocate memory, only used if buffers are not provided to littlefs static inline void lfs2_free(void *p) { #ifndef LFS2_NO_MALLOC free(p); #else (void)p; #endif } #ifdef __cplusplus } /* extern "C" */ #endif #endif #endif micropython-1.12/lib/lwip/000077500000000000000000000000001357706137100155435ustar00rootroot00000000000000micropython-1.12/lib/mbedtls/000077500000000000000000000000001357706137100162225ustar00rootroot00000000000000micropython-1.12/lib/memzip/000077500000000000000000000000001357706137100160715ustar00rootroot00000000000000micropython-1.12/lib/memzip/README.md000066400000000000000000000015501357706137100173510ustar00rootroot00000000000000MEMZIP - a simple readonly file system memzip takes a zip file which is comprised of uncompressed files and and presents it as a filesystem, allowing Python files to be imported. The script make-memzip.py takes a directory name and will create a zip file containing uncompressed files found in the directory. It will then generate a C file which contains the data from the zip file. A typical addition to a makefile would look like: ``` SRC_C += \ lib/memzip/import.c \ lib/memzip/lexermemzip.c \ lib/memzip/memzip.c \ OBJ += $(BUILD)/memzip-files.o MAKE_MEMZIP = ../lib/memzip/make-memzip.py $(BUILD)/memzip-files.o: $(BUILD)/memzip-files.c $(call compile_c) $(BUILD)/memzip-files.c: $(shell find ${MEMZIP_DIR} -type f) @$(ECHO) "Creating $@" $(Q)$(PYTHON) $(MAKE_MEMZIP) --zip-file $(BUILD)/memzip-files.zip --c-file $@ $(MEMZIP_DIR) ``` micropython-1.12/lib/memzip/import.c000066400000000000000000000005151357706137100175500ustar00rootroot00000000000000#include #include "py/lexer.h" #include "memzip.h" mp_import_stat_t mp_import_stat(const char *path) { MEMZIP_FILE_INFO info; if (memzip_stat(path, &info) != MZ_OK) { return MP_IMPORT_STAT_NO_EXIST; } if (info.is_dir) { return MP_IMPORT_STAT_DIR; } return MP_IMPORT_STAT_FILE; } micropython-1.12/lib/memzip/lexermemzip.c000066400000000000000000000006321357706137100205770ustar00rootroot00000000000000#include #include "py/lexer.h" #include "py/runtime.h" #include "py/mperrno.h" #include "memzip.h" mp_lexer_t *mp_lexer_new_from_file(const char *filename) { void *data; size_t len; if (memzip_locate(filename, &data, &len) != MZ_OK) { mp_raise_OSError(MP_ENOENT); } return mp_lexer_new_from_str_len(qstr_from_str(filename), (const char *)data, (mp_uint_t)len, 0); } micropython-1.12/lib/memzip/make-memzip.py000077500000000000000000000047311357706137100206670ustar00rootroot00000000000000#!/usr/bin/env python # # Takes a directory of files and zips them up (as uncompressed files). # This then gets converted into a C data structure which can be read # like a filesystem at runtime. # # This is somewhat like frozen modules in python, but allows arbitrary files # to be used. from __future__ import print_function import argparse import os import subprocess import sys import types def create_zip(zip_filename, zip_dir): abs_zip_filename = os.path.abspath(zip_filename) save_cwd = os.getcwd() os.chdir(zip_dir) if os.path.exists(abs_zip_filename): os.remove(abs_zip_filename) subprocess.check_call(['zip', '-0', '-r', '-D', abs_zip_filename, '.']) os.chdir(save_cwd) def create_c_from_file(c_filename, zip_filename): with open(zip_filename, 'rb') as zip_file: with open(c_filename, 'wb') as c_file: print('#include ', file=c_file) print('', file=c_file) print('const uint8_t memzip_data[] = {', file=c_file) while True: buf = zip_file.read(16) if not buf: break print(' ', end='', file=c_file) for byte in buf: if type(byte) is types.StringType: print(' 0x{:02x},'.format(ord(byte)), end='', file=c_file) else: print(' 0x{:02x},'.format(byte), end='', file=c_file) print('', file=c_file) print('};', file=c_file) def main(): parser = argparse.ArgumentParser( prog='make-memzip.py', usage='%(prog)s [options] [command]', description='Generates a C source memzip file.' ) parser.add_argument( '-z', '--zip-file', dest='zip_filename', help='Specifies the name of the created zip file.', default='memzip_files.zip' ) parser.add_argument( '-c', '--c-file', dest='c_filename', help='Specifies the name of the created C source file.', default='memzip_files.c' ) parser.add_argument( dest='source_dir', default='memzip_files' ) args = parser.parse_args(sys.argv[1:]) print('args.zip_filename =', args.zip_filename) print('args.c_filename =', args.c_filename) print('args.source_dir =', args.source_dir) create_zip(args.zip_filename, args.source_dir) create_c_from_file(args.c_filename, args.zip_filename) if __name__ == "__main__": main() micropython-1.12/lib/memzip/memzip.c000066400000000000000000000061321357706137100175400ustar00rootroot00000000000000#include #include #include #include "py/mpconfig.h" #include "py/misc.h" #include "memzip.h" extern uint8_t memzip_data[]; const MEMZIP_FILE_HDR *memzip_find_file_header(const char *filename) { const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)memzip_data; uint8_t *mem_data; /* Zip file filenames don't have a leading /, so we strip it off */ if (*filename == '/') { filename++; } while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) { const char *file_hdr_filename = (const char *)&file_hdr[1]; mem_data = (uint8_t *)file_hdr_filename; mem_data += file_hdr->filename_len; mem_data += file_hdr->extra_len; if (!strncmp(file_hdr_filename, filename, file_hdr->filename_len)) { /* We found a match */ return file_hdr; } mem_data += file_hdr->uncompressed_size; file_hdr = (const MEMZIP_FILE_HDR *)mem_data; } return NULL; } bool memzip_is_dir(const char *filename) { const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)memzip_data; uint8_t *mem_data; if (strcmp(filename, "/") == 0) { // The root directory is a directory. return true; } // Zip filenames don't have a leading /, so we strip it off if (*filename == '/') { filename++; } size_t filename_len = strlen(filename); while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) { const char *file_hdr_filename = (const char *)&file_hdr[1]; if (filename_len < file_hdr->filename_len && strncmp(file_hdr_filename, filename, filename_len) == 0 && file_hdr_filename[filename_len] == '/') { return true; } mem_data = (uint8_t *)file_hdr_filename; mem_data += file_hdr->filename_len; mem_data += file_hdr->extra_len; mem_data += file_hdr->uncompressed_size; file_hdr = (const MEMZIP_FILE_HDR *)mem_data; } return NULL; } MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len) { const MEMZIP_FILE_HDR *file_hdr = memzip_find_file_header(filename); if (file_hdr == NULL) { return MZ_NO_FILE; } if (file_hdr->compression_method != 0) { return MZ_FILE_COMPRESSED; } uint8_t *mem_data; mem_data = (uint8_t *)&file_hdr[1]; mem_data += file_hdr->filename_len; mem_data += file_hdr->extra_len; *data = mem_data; *len = file_hdr->uncompressed_size; return MZ_OK; } MEMZIP_RESULT memzip_stat(const char *path, MEMZIP_FILE_INFO *info) { const MEMZIP_FILE_HDR *file_hdr = memzip_find_file_header(path); if (file_hdr == NULL) { if (memzip_is_dir(path)) { info->file_size = 0; info->last_mod_date = 0; info->last_mod_time = 0; info->is_dir = 1; return MZ_OK; } return MZ_NO_FILE; } info->file_size = file_hdr->uncompressed_size; info->last_mod_date = file_hdr->last_mod_date; info->last_mod_time = file_hdr->last_mod_time; info->is_dir = 0; return MZ_OK; } micropython-1.12/lib/memzip/memzip.h000066400000000000000000000042411357706137100175440ustar00rootroot00000000000000#pragma pack(push, 1) #define MEMZIP_FILE_HEADER_SIGNATURE 0x04034b50 typedef struct { uint32_t signature; uint16_t version; uint16_t flags; uint16_t compression_method; uint16_t last_mod_time; uint16_t last_mod_date; uint32_t crc32; uint32_t compressed_size; uint32_t uncompressed_size; uint16_t filename_len; uint16_t extra_len; /* char filename[filename_len] */ /* uint8_t extra[extra_len] */ } MEMZIP_FILE_HDR; #define MEMZIP_CENTRAL_DIRECTORY_SIGNATURE 0x02014b50 typedef struct { uint32_t signature; uint16_t version_made_by; uint16_t version_read_with; uint16_t flags; uint16_t compression_method; uint16_t last_mod_time; uint16_t last_mod_date; uint32_t crc32; uint32_t compressed_size; uint32_t uncompressed_size; uint16_t filename_len; uint16_t extra_len; uint16_t disk_num; uint16_t internal_file_attributes; uint32_t external_file_attributes; uint32_t file_header_offset; /* char filename[filename_len] */ /* uint8_t extra[extra_len] */ } MEMZIP_CENTRAL_DIRECTORY_HDR; #define MEMZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE 0x06054b50 typedef struct { uint32_t signature; uint16_t disk_num; uint16_t central_directory_disk; uint16_t num_central_directories_this_disk; uint16_t total_central_directories; uint32_t central_directory_size; uint32_t central_directory_offset; uint16_t comment_len; /* char comment[comment_len] */ } MEMZIP_END_OF_CENTRAL_DIRECTORY; #pragma pack(pop) typedef enum { MZ_OK = 0, /* (0) Succeeded */ MZ_NO_FILE, /* (1) Could not find the file. */ MZ_FILE_COMPRESSED, /* (2) File is compressed (expecting uncompressed) */ } MEMZIP_RESULT; typedef struct { uint32_t file_size; uint16_t last_mod_date; uint16_t last_mod_time; uint8_t is_dir; } MEMZIP_FILE_INFO; MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len); MEMZIP_RESULT memzip_stat(const char *path, MEMZIP_FILE_INFO *info); micropython-1.12/lib/mp-readline/000077500000000000000000000000001357706137100167655ustar00rootroot00000000000000micropython-1.12/lib/mp-readline/readline.c000066400000000000000000000365301357706137100207230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpstate.h" #include "py/repl.h" #include "py/mphal.h" #include "lib/mp-readline/readline.h" #if 0 // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif #define READLINE_HIST_SIZE (MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist))) enum { ESEQ_NONE, ESEQ_ESC, ESEQ_ESC_BRACKET, ESEQ_ESC_BRACKET_DIGIT, ESEQ_ESC_O }; void readline_init0(void) { memset(MP_STATE_PORT(readline_hist), 0, READLINE_HIST_SIZE * sizeof(const char*)); } STATIC char *str_dup_maybe(const char *str) { uint32_t len = strlen(str); char *s2 = m_new_maybe(char, len + 1); if (s2 == NULL) { return NULL; } memcpy(s2, str, len + 1); return s2; } // By default assume terminal which implements VT100 commands... #ifndef MICROPY_HAL_HAS_VT100 #define MICROPY_HAL_HAS_VT100 (1) #endif // ...and provide the implementation using them #if MICROPY_HAL_HAS_VT100 STATIC void mp_hal_move_cursor_back(uint pos) { if (pos <= 4) { // fast path for most common case of 1 step back mp_hal_stdout_tx_strn("\b\b\b\b", pos); } else { char vt100_command[6]; // snprintf needs space for the terminating null character int n = snprintf(&vt100_command[0], sizeof(vt100_command), "\x1b[%u", pos); if (n > 0) { vt100_command[n] = 'D'; // replace null char mp_hal_stdout_tx_strn(vt100_command, n + 1); } } } STATIC void mp_hal_erase_line_from_cursor(uint n_chars_to_erase) { (void)n_chars_to_erase; mp_hal_stdout_tx_strn("\x1b[K", 3); } #endif typedef struct _readline_t { vstr_t *line; size_t orig_line_len; int escape_seq; int hist_cur; size_t cursor_pos; char escape_seq_buf[1]; const char *prompt; } readline_t; STATIC readline_t rl; int readline_process_char(int c) { size_t last_line_len = rl.line->len; int redraw_step_back = 0; bool redraw_from_cursor = false; int redraw_step_forward = 0; if (rl.escape_seq == ESEQ_NONE) { if (CHAR_CTRL_A <= c && c <= CHAR_CTRL_E && vstr_len(rl.line) == rl.orig_line_len) { // control character with empty line return c; } else if (c == CHAR_CTRL_A) { // CTRL-A with non-empty line is go-to-start-of-line goto home_key; #if MICROPY_REPL_EMACS_KEYS } else if (c == CHAR_CTRL_B) { // CTRL-B with non-empty line is go-back-one-char goto left_arrow_key; #endif } else if (c == CHAR_CTRL_C) { // CTRL-C with non-empty line is cancel return c; #if MICROPY_REPL_EMACS_KEYS } else if (c == CHAR_CTRL_D) { // CTRL-D with non-empty line is delete-at-cursor goto delete_key; #endif } else if (c == CHAR_CTRL_E) { // CTRL-E is go-to-end-of-line goto end_key; #if MICROPY_REPL_EMACS_KEYS } else if (c == CHAR_CTRL_F) { // CTRL-F with non-empty line is go-forward-one-char goto right_arrow_key; } else if (c == CHAR_CTRL_K) { // CTRL-K is kill from cursor to end-of-line, inclusive vstr_cut_tail_bytes(rl.line, last_line_len - rl.cursor_pos); // set redraw parameters redraw_from_cursor = true; } else if (c == CHAR_CTRL_N) { // CTRL-N is go to next line in history goto down_arrow_key; } else if (c == CHAR_CTRL_P) { // CTRL-P is go to previous line in history goto up_arrow_key; } else if (c == CHAR_CTRL_U) { // CTRL-U is kill from beginning-of-line up to cursor vstr_cut_out_bytes(rl.line, rl.orig_line_len, rl.cursor_pos - rl.orig_line_len); // set redraw parameters redraw_step_back = rl.cursor_pos - rl.orig_line_len; redraw_from_cursor = true; #endif } else if (c == '\r') { // newline mp_hal_stdout_tx_str("\r\n"); readline_push_history(vstr_null_terminated_str(rl.line) + rl.orig_line_len); return 0; } else if (c == 27) { // escape sequence rl.escape_seq = ESEQ_ESC; } else if (c == 8 || c == 127) { // backspace/delete if (rl.cursor_pos > rl.orig_line_len) { // work out how many chars to backspace #if MICROPY_REPL_AUTO_INDENT int nspace = 0; for (size_t i = rl.orig_line_len; i < rl.cursor_pos; i++) { if (rl.line->buf[i] != ' ') { nspace = 0; break; } nspace += 1; } if (nspace < 4) { nspace = 1; } else { nspace = 4; } #else int nspace = 1; #endif // do the backspace vstr_cut_out_bytes(rl.line, rl.cursor_pos - nspace, nspace); // set redraw parameters redraw_step_back = nspace; redraw_from_cursor = true; } #if MICROPY_HELPER_REPL } else if (c == 9) { // tab magic const char *compl_str; size_t compl_len = mp_repl_autocomplete(rl.line->buf + rl.orig_line_len, rl.cursor_pos - rl.orig_line_len, &mp_plat_print, &compl_str); if (compl_len == 0) { // no match } else if (compl_len == (size_t)(-1)) { // many matches mp_hal_stdout_tx_str(rl.prompt); mp_hal_stdout_tx_strn(rl.line->buf + rl.orig_line_len, rl.cursor_pos - rl.orig_line_len); redraw_from_cursor = true; } else { // one match for (size_t i = 0; i < compl_len; ++i) { vstr_ins_byte(rl.line, rl.cursor_pos + i, *compl_str++); } // set redraw parameters redraw_from_cursor = true; redraw_step_forward = compl_len; } #endif } else if (32 <= c && c <= 126) { // printable character vstr_ins_char(rl.line, rl.cursor_pos, c); // set redraw parameters redraw_from_cursor = true; redraw_step_forward = 1; } } else if (rl.escape_seq == ESEQ_ESC) { switch (c) { case '[': rl.escape_seq = ESEQ_ESC_BRACKET; break; case 'O': rl.escape_seq = ESEQ_ESC_O; break; default: DEBUG_printf("(ESC %d)", c); rl.escape_seq = ESEQ_NONE; } } else if (rl.escape_seq == ESEQ_ESC_BRACKET) { if ('0' <= c && c <= '9') { rl.escape_seq = ESEQ_ESC_BRACKET_DIGIT; rl.escape_seq_buf[0] = c; } else { rl.escape_seq = ESEQ_NONE; if (c == 'A') { #if MICROPY_REPL_EMACS_KEYS up_arrow_key: #endif // up arrow if (rl.hist_cur + 1 < (int)READLINE_HIST_SIZE && MP_STATE_PORT(readline_hist)[rl.hist_cur + 1] != NULL) { // increase hist num rl.hist_cur += 1; // set line to history rl.line->len = rl.orig_line_len; vstr_add_str(rl.line, MP_STATE_PORT(readline_hist)[rl.hist_cur]); // set redraw parameters redraw_step_back = rl.cursor_pos - rl.orig_line_len; redraw_from_cursor = true; redraw_step_forward = rl.line->len - rl.orig_line_len; } } else if (c == 'B') { #if MICROPY_REPL_EMACS_KEYS down_arrow_key: #endif // down arrow if (rl.hist_cur >= 0) { // decrease hist num rl.hist_cur -= 1; // set line to history vstr_cut_tail_bytes(rl.line, rl.line->len - rl.orig_line_len); if (rl.hist_cur >= 0) { vstr_add_str(rl.line, MP_STATE_PORT(readline_hist)[rl.hist_cur]); } // set redraw parameters redraw_step_back = rl.cursor_pos - rl.orig_line_len; redraw_from_cursor = true; redraw_step_forward = rl.line->len - rl.orig_line_len; } } else if (c == 'C') { #if MICROPY_REPL_EMACS_KEYS right_arrow_key: #endif // right arrow if (rl.cursor_pos < rl.line->len) { redraw_step_forward = 1; } } else if (c == 'D') { #if MICROPY_REPL_EMACS_KEYS left_arrow_key: #endif // left arrow if (rl.cursor_pos > rl.orig_line_len) { redraw_step_back = 1; } } else if (c == 'H') { // home goto home_key; } else if (c == 'F') { // end goto end_key; } else { DEBUG_printf("(ESC [ %d)", c); } } } else if (rl.escape_seq == ESEQ_ESC_BRACKET_DIGIT) { if (c == '~') { if (rl.escape_seq_buf[0] == '1' || rl.escape_seq_buf[0] == '7') { home_key: redraw_step_back = rl.cursor_pos - rl.orig_line_len; } else if (rl.escape_seq_buf[0] == '4' || rl.escape_seq_buf[0] == '8') { end_key: redraw_step_forward = rl.line->len - rl.cursor_pos; } else if (rl.escape_seq_buf[0] == '3') { // delete #if MICROPY_REPL_EMACS_KEYS delete_key: #endif if (rl.cursor_pos < rl.line->len) { vstr_cut_out_bytes(rl.line, rl.cursor_pos, 1); redraw_from_cursor = true; } } else { DEBUG_printf("(ESC [ %c %d)", rl.escape_seq_buf[0], c); } } else { DEBUG_printf("(ESC [ %c %d)", rl.escape_seq_buf[0], c); } rl.escape_seq = ESEQ_NONE; } else if (rl.escape_seq == ESEQ_ESC_O) { switch (c) { case 'H': goto home_key; case 'F': goto end_key; default: DEBUG_printf("(ESC O %d)", c); rl.escape_seq = ESEQ_NONE; } } else { rl.escape_seq = ESEQ_NONE; } // redraw command prompt, efficiently if (redraw_step_back > 0) { mp_hal_move_cursor_back(redraw_step_back); rl.cursor_pos -= redraw_step_back; } if (redraw_from_cursor) { if (rl.line->len < last_line_len) { // erase old chars mp_hal_erase_line_from_cursor(last_line_len - rl.cursor_pos); } // draw new chars mp_hal_stdout_tx_strn(rl.line->buf + rl.cursor_pos, rl.line->len - rl.cursor_pos); // move cursor forward if needed (already moved forward by length of line, so move it back) mp_hal_move_cursor_back(rl.line->len - (rl.cursor_pos + redraw_step_forward)); rl.cursor_pos += redraw_step_forward; } else if (redraw_step_forward > 0) { // draw over old chars to move cursor forwards mp_hal_stdout_tx_strn(rl.line->buf + rl.cursor_pos, redraw_step_forward); rl.cursor_pos += redraw_step_forward; } return -1; } #if MICROPY_REPL_AUTO_INDENT STATIC void readline_auto_indent(void) { vstr_t *line = rl.line; if (line->len > 1 && line->buf[line->len - 1] == '\n') { int i; for (i = line->len - 1; i > 0; i--) { if (line->buf[i - 1] == '\n') { break; } } size_t j; for (j = i; j < line->len; j++) { if (line->buf[j] != ' ') { break; } } // i=start of line; j=first non-space if (i > 0 && j + 1 == line->len) { // previous line is not first line and is all spaces for (size_t k = i - 1; k > 0; --k) { if (line->buf[k - 1] == '\n') { // don't auto-indent if last 2 lines are all spaces return; } else if (line->buf[k - 1] != ' ') { // 2nd previous line is not all spaces break; } } } int n = (j - i) / 4; if (line->buf[line->len - 2] == ':') { n += 1; } while (n-- > 0) { vstr_add_strn(line, " ", 4); mp_hal_stdout_tx_strn(" ", 4); rl.cursor_pos += 4; } } } #endif void readline_note_newline(const char *prompt) { rl.orig_line_len = rl.line->len; rl.cursor_pos = rl.orig_line_len; rl.prompt = prompt; mp_hal_stdout_tx_str(prompt); #if MICROPY_REPL_AUTO_INDENT readline_auto_indent(); #endif } void readline_init(vstr_t *line, const char *prompt) { rl.line = line; rl.orig_line_len = line->len; rl.escape_seq = ESEQ_NONE; rl.escape_seq_buf[0] = 0; rl.hist_cur = -1; rl.cursor_pos = rl.orig_line_len; rl.prompt = prompt; mp_hal_stdout_tx_str(prompt); #if MICROPY_REPL_AUTO_INDENT readline_auto_indent(); #endif } int readline(vstr_t *line, const char *prompt) { readline_init(line, prompt); for (;;) { int c = mp_hal_stdin_rx_chr(); int r = readline_process_char(c); if (r >= 0) { return r; } } } void readline_push_history(const char *line) { if (line[0] != '\0' && (MP_STATE_PORT(readline_hist)[0] == NULL || strcmp(MP_STATE_PORT(readline_hist)[0], line) != 0)) { // a line which is not empty and different from the last one // so update the history char *most_recent_hist = str_dup_maybe(line); if (most_recent_hist != NULL) { for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) { MP_STATE_PORT(readline_hist)[i] = MP_STATE_PORT(readline_hist)[i - 1]; } MP_STATE_PORT(readline_hist)[0] = most_recent_hist; } } } micropython-1.12/lib/mp-readline/readline.h000066400000000000000000000035461357706137100207310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_LIB_MP_READLINE_READLINE_H #define MICROPY_INCLUDED_LIB_MP_READLINE_READLINE_H #define CHAR_CTRL_A (1) #define CHAR_CTRL_B (2) #define CHAR_CTRL_C (3) #define CHAR_CTRL_D (4) #define CHAR_CTRL_E (5) #define CHAR_CTRL_F (6) #define CHAR_CTRL_K (11) #define CHAR_CTRL_N (14) #define CHAR_CTRL_P (16) #define CHAR_CTRL_U (21) void readline_init0(void); int readline(vstr_t *line, const char *prompt); void readline_push_history(const char *line); void readline_init(vstr_t *line, const char *prompt); void readline_note_newline(const char *prompt); int readline_process_char(int c); #endif // MICROPY_INCLUDED_LIB_MP_READLINE_READLINE_H micropython-1.12/lib/mynewt-nimble/000077500000000000000000000000001357706137100173575ustar00rootroot00000000000000micropython-1.12/lib/netutils/000077500000000000000000000000001357706137100164375ustar00rootroot00000000000000micropython-1.12/lib/netutils/dhcpserver.c000066400000000000000000000232411357706137100207520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // For DHCP specs see: // https://www.ietf.org/rfc/rfc2131.txt // https://tools.ietf.org/html/rfc2132 -- DHCP Options and BOOTP Vendor Extensions #include #include #include "py/mperrno.h" #include "py/mphal.h" #if MICROPY_PY_LWIP #include "lib/netutils/dhcpserver.h" #include "lwip/udp.h" #define DHCPDISCOVER (1) #define DHCPOFFER (2) #define DHCPREQUEST (3) #define DHCPDECLINE (4) #define DHCPACK (5) #define DHCPNACK (6) #define DHCPRELEASE (7) #define DHCPINFORM (8) #define DHCP_OPT_PAD (0) #define DHCP_OPT_SUBNET_MASK (1) #define DHCP_OPT_ROUTER (3) #define DHCP_OPT_DNS (6) #define DHCP_OPT_HOST_NAME (12) #define DHCP_OPT_REQUESTED_IP (50) #define DHCP_OPT_IP_LEASE_TIME (51) #define DHCP_OPT_MSG_TYPE (53) #define DHCP_OPT_SERVER_ID (54) #define DHCP_OPT_PARAM_REQUEST_LIST (55) #define DHCP_OPT_MAX_MSG_SIZE (57) #define DHCP_OPT_VENDOR_CLASS_ID (60) #define DHCP_OPT_CLIENT_ID (61) #define DHCP_OPT_END (255) #define PORT_DHCP_SERVER (67) #define PORT_DHCP_CLIENT (68) #define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8) #define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds #define MAC_LEN (6) #define MAKE_IP4(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) typedef struct { uint8_t op; // message opcode uint8_t htype; // hardware address type uint8_t hlen; // hardware address length uint8_t hops; uint32_t xid; // transaction id, chosen by client uint16_t secs; // client seconds elapsed uint16_t flags; uint8_t ciaddr[4]; // client IP address uint8_t yiaddr[4]; // your IP address uint8_t siaddr[4]; // next server IP address uint8_t giaddr[4]; // relay agent IP address uint8_t chaddr[16]; // client hardware address uint8_t sname[64]; // server host name uint8_t file[128]; // boot file name uint8_t options[312]; // optional parameters, variable, starts with magic } dhcp_msg_t; static int dhcp_socket_new_dgram(struct udp_pcb **udp, void *cb_data, udp_recv_fn cb_udp_recv) { // family is AF_INET // type is SOCK_DGRAM *udp = udp_new(); if (*udp == NULL) { return -MP_ENOMEM; } // Register callback udp_recv(*udp, cb_udp_recv, (void*)cb_data); return 0; // success } static void dhcp_socket_free(struct udp_pcb **udp) { if (*udp != NULL) { udp_remove(*udp); *udp = NULL; } } static int dhcp_socket_bind(struct udp_pcb **udp, uint32_t ip, uint16_t port) { ip_addr_t addr; IP4_ADDR(&addr, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff); // TODO convert lwIP errors to errno return udp_bind(*udp, &addr, port); } static int dhcp_socket_sendto(struct udp_pcb **udp, const void *buf, size_t len, uint32_t ip, uint16_t port) { if (len > 0xffff) { len = 0xffff; } struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); if (p == NULL) { return -MP_ENOMEM; } memcpy(p->payload, buf, len); ip_addr_t dest; IP4_ADDR(&dest, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff); err_t err = udp_sendto(*udp, p, &dest, port); pbuf_free(p); if (err != ERR_OK) { return err; } return len; } static uint8_t *opt_find(uint8_t *opt, uint8_t cmd) { for (int i = 0; i < 308 && opt[i] != DHCP_OPT_END;) { if (opt[i] == cmd) { return &opt[i]; } i += 2 + opt[i + 1]; } return NULL; } static void opt_write_n(uint8_t **opt, uint8_t cmd, size_t n, void *data) { uint8_t *o = *opt; *o++ = cmd; *o++ = n; memcpy(o, data, n); *opt = o + n; } static void opt_write_u8(uint8_t **opt, uint8_t cmd, uint8_t val) { uint8_t *o = *opt; *o++ = cmd; *o++ = 1; *o++ = val; *opt = o; } static void opt_write_u32(uint8_t **opt, uint8_t cmd, uint32_t val) { uint8_t *o = *opt; *o++ = cmd; *o++ = 4; *o++ = val >> 24; *o++ = val >> 16; *o++ = val >> 8; *o++ = val; *opt = o; } static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *src_addr, u16_t src_port) { dhcp_server_t *d = arg; (void)upcb; (void)src_addr; (void)src_port; // This is around 548 bytes dhcp_msg_t dhcp_msg; #define DHCP_MIN_SIZE (240 + 3) if (p->tot_len < DHCP_MIN_SIZE) { goto ignore_request; } size_t len = pbuf_copy_partial(p, &dhcp_msg, sizeof(dhcp_msg), 0); if (len < DHCP_MIN_SIZE) { goto ignore_request; } dhcp_msg.op = DHCPOFFER; memcpy(&dhcp_msg.yiaddr, &d->ip.addr, 4); uint8_t *opt = (uint8_t*)&dhcp_msg.options; opt += 4; // assume magic cookie: 99, 130, 83, 99 switch (opt[2]) { case DHCPDISCOVER: { int yi = DHCPS_MAX_IP; for (int i = 0; i < DHCPS_MAX_IP; ++i) { if (memcmp(d->lease[i].mac, dhcp_msg.chaddr, MAC_LEN) == 0) { // MAC match, use this IP address yi = i; break; } if (yi == DHCPS_MAX_IP) { // Look for a free IP address if (memcmp(d->lease[i].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) { // IP available yi = i; } uint32_t expiry = d->lease[i].expiry << 16 | 0xffff; if ((int32_t)(expiry - mp_hal_ticks_ms()) < 0) { // IP expired, reuse it memset(d->lease[i].mac, 0, MAC_LEN); yi = i; } } } if (yi == DHCPS_MAX_IP) { // No more IP addresses left goto ignore_request; } dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi; opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPOFFER); break; } case DHCPREQUEST: { uint8_t *o = opt_find(opt, DHCP_OPT_REQUESTED_IP); if (o == NULL) { // Should be NACK goto ignore_request; } if (memcmp(o + 2, &d->ip.addr, 3) != 0) { // Should be NACK goto ignore_request; } uint8_t yi = o[5] - DHCPS_BASE_IP; if (yi >= DHCPS_MAX_IP) { // Should be NACK goto ignore_request; } if (memcmp(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN) == 0) { // MAC match, ok to use this IP address } else if (memcmp(d->lease[yi].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) { // IP unused, ok to use this IP address memcpy(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN); } else { // IP already in use // Should be NACK goto ignore_request; } d->lease[yi].expiry = (mp_hal_ticks_ms() + DEFAULT_LEASE_TIME_S * 1000) >> 16; dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi; opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPACK); printf("DHCPS: client connected: MAC=%02x:%02x:%02x:%02x:%02x:%02x IP=%u.%u.%u.%u\n", dhcp_msg.chaddr[0], dhcp_msg.chaddr[1], dhcp_msg.chaddr[2], dhcp_msg.chaddr[3], dhcp_msg.chaddr[4], dhcp_msg.chaddr[5], dhcp_msg.yiaddr[0], dhcp_msg.yiaddr[1], dhcp_msg.yiaddr[2], dhcp_msg.yiaddr[3]); break; } default: goto ignore_request; } opt_write_n(&opt, DHCP_OPT_SERVER_ID, 4, &d->ip.addr); opt_write_n(&opt, DHCP_OPT_SUBNET_MASK, 4, &d->nm.addr); opt_write_n(&opt, DHCP_OPT_ROUTER, 4, &d->ip.addr); // aka gateway; can have mulitple addresses opt_write_u32(&opt, DHCP_OPT_DNS, DEFAULT_DNS); // can have mulitple addresses opt_write_u32(&opt, DHCP_OPT_IP_LEASE_TIME, DEFAULT_LEASE_TIME_S); *opt++ = DHCP_OPT_END; dhcp_socket_sendto(&d->udp, &dhcp_msg, opt - (uint8_t*)&dhcp_msg, 0xffffffff, PORT_DHCP_CLIENT); ignore_request: pbuf_free(p); } void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm) { ip_addr_copy(d->ip, *ip); ip_addr_copy(d->nm, *nm); memset(d->lease, 0, sizeof(d->lease)); if (dhcp_socket_new_dgram(&d->udp, d, dhcp_server_process) != 0) { return; } dhcp_socket_bind(&d->udp, 0, PORT_DHCP_SERVER); } void dhcp_server_deinit(dhcp_server_t *d) { dhcp_socket_free(&d->udp); } #endif // MICROPY_PY_LWIP micropython-1.12/lib/netutils/dhcpserver.h000066400000000000000000000034601357706137100207600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H #define MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H #include "lwip/ip_addr.h" #define DHCPS_BASE_IP (16) #define DHCPS_MAX_IP (8) typedef struct _dhcp_server_lease_t { uint8_t mac[6]; uint16_t expiry; } dhcp_server_lease_t; typedef struct _dhcp_server_t { ip_addr_t ip; ip_addr_t nm; dhcp_server_lease_t lease[DHCPS_MAX_IP]; struct udp_pcb *udp; } dhcp_server_t; void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm); void dhcp_server_deinit(dhcp_server_t *d); #endif // MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H micropython-1.12/lib/netutils/netutils.c000066400000000000000000000070311357706137100204530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "lib/netutils/netutils.h" // Takes an array with a raw IPv4 address and returns something like '192.168.0.1'. mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian) { char ip_str[16]; mp_uint_t ip_len; if (endian == NETUTILS_LITTLE) { ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]); } else { ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); } return mp_obj_new_str(ip_str, ip_len); } // Takes an array with a raw IP address, and a port, and returns a net-address // tuple such as ('192.168.0.1', 8080). mp_obj_t netutils_format_inet_addr(uint8_t *ip, mp_uint_t port, netutils_endian_t endian) { mp_obj_t tuple[2] = { tuple[0] = netutils_format_ipv4_addr(ip, endian), tuple[1] = mp_obj_new_int(port), }; return mp_obj_new_tuple(2, tuple); } void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian) { size_t addr_len; const char *addr_str = mp_obj_str_get_data(addr_in, &addr_len); if (addr_len == 0) { // special case of no address given memset(out_ip, 0, NETUTILS_IPV4ADDR_BUFSIZE); return; } const char *s = addr_str; const char *s_top = addr_str + addr_len; for (mp_uint_t i = 3 ; ; i--) { mp_uint_t val = 0; for (; s < s_top && *s != '.'; s++) { val = val * 10 + *s - '0'; } if (endian == NETUTILS_LITTLE) { out_ip[i] = val; } else { out_ip[NETUTILS_IPV4ADDR_BUFSIZE - 1 - i] = val; } if (i == 0 && s == s_top) { return; } else if (i > 0 && s < s_top && *s == '.') { s++; } else { mp_raise_ValueError("invalid arguments"); } } } // Takes an address of the form ('192.168.0.1', 8080), returns the port and // puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes). mp_uint_t netutils_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian) { mp_obj_t *addr_items; mp_obj_get_array_fixed_n(addr_in, 2, &addr_items); netutils_parse_ipv4_addr(addr_items[0], out_ip, endian); return mp_obj_get_int(addr_items[1]); } micropython-1.12/lib/netutils/netutils.h000066400000000000000000000047121357706137100204630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_LIB_NETUTILS_NETUTILS_H #define MICROPY_INCLUDED_LIB_NETUTILS_NETUTILS_H #define NETUTILS_IPV4ADDR_BUFSIZE 4 #define NETUTILS_TRACE_IS_TX (0x0001) #define NETUTILS_TRACE_PAYLOAD (0x0002) #define NETUTILS_TRACE_NEWLINE (0x0004) typedef enum _netutils_endian_t { NETUTILS_LITTLE, NETUTILS_BIG, } netutils_endian_t; // Takes an array with a raw IPv4 address and returns something like '192.168.0.1'. mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian); // Takes an array with a raw IP address, and a port, and returns a net-address // tuple such as ('192.168.0.1', 8080). mp_obj_t netutils_format_inet_addr(uint8_t *ip, mp_uint_t port, netutils_endian_t endian); void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian); // Takes an address of the form ('192.168.0.1', 8080), returns the port and // puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes). mp_uint_t netutils_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian); void netutils_ethernet_trace(const mp_print_t *print, size_t len, const uint8_t *buf, unsigned int flags); #endif // MICROPY_INCLUDED_LIB_NETUTILS_NETUTILS_H micropython-1.12/lib/netutils/trace.c000066400000000000000000000145051357706137100177060ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mphal.h" #include "lib/netutils/netutils.h" static uint32_t get_be16(const uint8_t *buf) { return buf[0] << 8 | buf[1]; } static uint32_t get_be32(const uint8_t *buf) { return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; } static void dump_hex_bytes(const mp_print_t *print, size_t len, const uint8_t *buf) { for (size_t i = 0; i < len; ++i) { mp_printf(print, " %02x", buf[i]); } } static const char *ethertype_str(uint16_t type) { // A value between 0x0000 - 0x05dc (inclusive) indicates a length, not type switch (type) { case 0x0800: return "IPv4"; case 0x0806: return "ARP"; case 0x86dd: return "IPv6"; default: return NULL; } } void netutils_ethernet_trace(const mp_print_t *print, size_t len, const uint8_t *buf, unsigned int flags) { mp_printf(print, "[% 8d] ETH%cX len=%u", mp_hal_ticks_ms(), flags & NETUTILS_TRACE_IS_TX ? 'T' : 'R', len); mp_printf(print, " dst=%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); mp_printf(print, " src=%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); const char *ethertype = ethertype_str(buf[12] << 8 | buf[13]); if (ethertype) { mp_printf(print, " type=%s", ethertype); } else { mp_printf(print, " type=0x%04x", buf[12] << 8 | buf[13]); } if (len > 14) { len -= 14; buf += 14; if (buf[-2] == 0x08 && buf[-1] == 0x00 && buf[0] == 0x45) { // IPv4 packet len = get_be16(buf + 2); mp_printf(print, " srcip=%u.%u.%u.%u dstip=%u.%u.%u.%u", buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]); uint8_t prot = buf[9]; buf += 20; len -= 20; if (prot == 6) { // TCP packet uint16_t srcport = get_be16(buf); uint16_t dstport = get_be16(buf + 2); uint32_t seqnum = get_be32(buf + 4); uint32_t acknum = get_be32(buf + 8); uint16_t dataoff_flags = get_be16(buf + 12); uint16_t winsz = get_be16(buf + 14); mp_printf(print, " TCP srcport=%u dstport=%u seqnum=%u acknum=%u dataoff=%u flags=%x winsz=%u", srcport, dstport, (unsigned)seqnum, (unsigned)acknum, dataoff_flags >> 12, dataoff_flags & 0x1ff, winsz); buf += 20; len -= 20; if (dataoff_flags >> 12 > 5) { mp_printf(print, " opts="); size_t opts_len = ((dataoff_flags >> 12) - 5) * 4; dump_hex_bytes(print, opts_len, buf); buf += opts_len; len -= opts_len; } } else if (prot == 17) { // UDP packet uint16_t srcport = get_be16(buf); uint16_t dstport = get_be16(buf + 2); mp_printf(print, " UDP srcport=%u dstport=%u", srcport, dstport); len = get_be16(buf + 4); buf += 8; if ((srcport == 67 && dstport == 68) || (srcport == 68 && dstport == 67)) { // DHCP if (srcport == 67) { mp_printf(print, " DHCPS"); } else { mp_printf(print, " DHCPC"); } dump_hex_bytes(print, 12 + 16 + 16 + 64, buf); size_t n = 12 + 16 + 16 + 64 + 128; len -= n; buf += n; mp_printf(print, " opts:"); switch (buf[6]) { case 1: mp_printf(print, " DISCOVER"); break; case 2: mp_printf(print, " OFFER"); break; case 3: mp_printf(print, " REQUEST"); break; case 4: mp_printf(print, " DECLINE"); break; case 5: mp_printf(print, " ACK"); break; case 6: mp_printf(print, " NACK"); break; case 7: mp_printf(print, " RELEASE"); break; case 8: mp_printf(print, " INFORM"); break; } } } else { // Non-UDP packet mp_printf(print, " prot=%u", prot); } } else if (buf[-2] == 0x86 && buf[-1] == 0xdd && (buf[0] >> 4) == 6) { // IPv6 packet uint32_t h = get_be32(buf); uint16_t l = get_be16(buf + 4); mp_printf(print, " tclass=%u flow=%u len=%u nexthdr=%u hoplimit=%u", (unsigned)((h >> 20) & 0xff), (unsigned)(h & 0xfffff), l, buf[6], buf[7]); mp_printf(print, " srcip="); dump_hex_bytes(print, 16, buf + 8); mp_printf(print, " dstip="); dump_hex_bytes(print, 16, buf + 24); buf += 40; len -= 40; } if (flags & NETUTILS_TRACE_PAYLOAD) { mp_printf(print, " data="); dump_hex_bytes(print, len, buf); } } if (flags & NETUTILS_TRACE_NEWLINE) { mp_printf(print, "\n"); } } micropython-1.12/lib/nrfx/000077500000000000000000000000001357706137100155455ustar00rootroot00000000000000micropython-1.12/lib/oofatfs/000077500000000000000000000000001357706137100162315ustar00rootroot00000000000000micropython-1.12/lib/oofatfs/diskio.h000066400000000000000000000055701357706137100176730ustar00rootroot00000000000000/* This file is part of ooFatFs, a customised version of FatFs * See https://github.com/micropython/oofatfs for details */ /*-----------------------------------------------------------------------/ / Low level disk interface modlue include file (C)ChaN, 2014 / /-----------------------------------------------------------------------*/ #ifndef _DISKIO_DEFINED #define _DISKIO_DEFINED #ifdef __cplusplus extern "C" { #endif /* Status of Disk Functions */ typedef BYTE DSTATUS; /* Results of Disk Functions */ typedef enum { RES_OK = 0, /* 0: Successful */ RES_ERROR, /* 1: R/W Error */ RES_WRPRT, /* 2: Write Protected */ RES_NOTRDY, /* 3: Not Ready */ RES_PARERR /* 4: Invalid Parameter */ } DRESULT; /*---------------------------------------*/ /* Prototypes for disk control functions */ DRESULT disk_read (void *drv, BYTE* buff, DWORD sector, UINT count); DRESULT disk_write (void *drv, const BYTE* buff, DWORD sector, UINT count); DRESULT disk_ioctl (void *drv, BYTE cmd, void* buff); /* Disk Status Bits (DSTATUS) */ #define STA_NOINIT 0x01 /* Drive not initialized */ #define STA_NODISK 0x02 /* No medium in the drive */ #define STA_PROTECT 0x04 /* Write protected */ /* Command code for disk_ioctrl fucntion */ /* Generic command (Used by FatFs) */ #define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ #define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ #define IOCTL_INIT 5 #define IOCTL_STATUS 6 /* Generic command (Not used by FatFs) */ #define CTRL_POWER 5 /* Get/Set power status */ #define CTRL_LOCK 6 /* Lock/Unlock media removal */ #define CTRL_EJECT 7 /* Eject media */ #define CTRL_FORMAT 8 /* Create physical format on the media */ /* MMC/SDC specific ioctl command */ #define MMC_GET_TYPE 10 /* Get card type */ #define MMC_GET_CSD 11 /* Get CSD */ #define MMC_GET_CID 12 /* Get CID */ #define MMC_GET_OCR 13 /* Get OCR */ #define MMC_GET_SDSTAT 14 /* Get SD status */ #define ISDIO_READ 55 /* Read data form SD iSDIO register */ #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ /* ATA/CF specific ioctl command */ #define ATA_GET_REV 20 /* Get F/W revision */ #define ATA_GET_MODEL 21 /* Get model name */ #define ATA_GET_SN 22 /* Get serial number */ #ifdef __cplusplus } #endif #endif micropython-1.12/lib/oofatfs/ff.c000066400000000000000000007470601357706137100170060ustar00rootroot00000000000000/* This file is part of ooFatFs, a customised version of FatFs * See https://github.com/micropython/oofatfs for details */ /*----------------------------------------------------------------------------/ / FatFs - Generic FAT Filesystem Module R0.13c / /-----------------------------------------------------------------------------/ / / Copyright (C) 2018, ChaN, all right reserved. / / FatFs module is an open source software. Redistribution and use of FatFs in / source and binary forms, with or without modification, are permitted provided / that the following condition is met: / / 1. Redistributions of source code must retain the above copyright notice, / this condition and the following disclaimer. / / This software is provided by the copyright holder and contributors "AS IS" / and any warranties related to this software are DISCLAIMED. / The copyright owner or contributors be NOT LIABLE for any damages caused / by use of this software. / /----------------------------------------------------------------------------*/ #include #include "ff.h" /* Declarations of FatFs API */ #include "diskio.h" /* Declarations of device I/O functions */ // DIR has been renamed FF_DIR in the public API so it doesn't clash with POSIX #define DIR FF_DIR /*-------------------------------------------------------------------------- Module Private Definitions ---------------------------------------------------------------------------*/ #if FF_DEFINED != 86604 /* Revision ID */ #error Wrong include file (ff.h). #endif /* Limits and boundaries */ #define MAX_DIR 0x200000 /* Max size of FAT directory */ #define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ #define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */ #define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */ #define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ #define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ /* Character code support macros */ #define IsUpper(c) ((c) >= 'A' && (c) <= 'Z') #define IsLower(c) ((c) >= 'a' && (c) <= 'z') #define IsDigit(c) ((c) >= '0' && (c) <= '9') #define IsSurrogate(c) ((c) >= 0xD800 && (c) <= 0xDFFF) #define IsSurrogateH(c) ((c) >= 0xD800 && (c) <= 0xDBFF) #define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF) /* Additional file access control and file status flags for internal use */ #define FA_SEEKEND 0x20 /* Seek to end of the file on file open */ #define FA_MODIFIED 0x40 /* File has been modified */ #define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */ /* Additional file attribute bits for internal use */ #define AM_VOL 0x08 /* Volume label */ #define AM_LFN 0x0F /* LFN entry */ #define AM_MASK 0x3F /* Mask of defined bits */ /* Name status flags in fn[11] */ #define NSFLAG 11 /* Index of the name status byte */ #define NS_LOSS 0x01 /* Out of 8.3 format */ #define NS_LFN 0x02 /* Force to create LFN entry */ #define NS_LAST 0x04 /* Last segment */ #define NS_BODY 0x08 /* Lower case flag (body) */ #define NS_EXT 0x10 /* Lower case flag (ext) */ #define NS_DOT 0x20 /* Dot entry */ #define NS_NOLFN 0x40 /* Do not find LFN */ #define NS_NONAME 0x80 /* Not followed */ /* exFAT directory entry types */ #define ET_BITMAP 0x81 /* Allocation bitmap */ #define ET_UPCASE 0x82 /* Up-case table */ #define ET_VLABEL 0x83 /* Volume label */ #define ET_FILEDIR 0x85 /* File and directory */ #define ET_STREAM 0xC0 /* Stream extension */ #define ET_FILENAME 0xC1 /* Name extension */ /* FatFs refers the FAT structure as simple byte array instead of structure member / because the C structure is not binary compatible between different platforms */ #define BS_JmpBoot 0 /* x86 jump instruction (3-byte) */ #define BS_OEMName 3 /* OEM name (8-byte) */ #define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */ #define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */ #define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (WORD) */ #define BPB_NumFATs 16 /* Number of FATs (BYTE) */ #define BPB_RootEntCnt 17 /* Size of root directory area for FAT [entry] (WORD) */ #define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ #define BPB_Media 21 /* Media descriptor byte (BYTE) */ #define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ #define BPB_SecPerTrk 24 /* Number of sectors per track for int13h [sector] (WORD) */ #define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ #define BPB_HiddSec 28 /* Volume offset from top of the drive (DWORD) */ #define BPB_TotSec32 32 /* Volume size (32-bit) [sector] (DWORD) */ #define BS_DrvNum 36 /* Physical drive number for int13h (BYTE) */ #define BS_NTres 37 /* WindowsNT error flag (BYTE) */ #define BS_BootSig 38 /* Extended boot signature (BYTE) */ #define BS_VolID 39 /* Volume serial number (DWORD) */ #define BS_VolLab 43 /* Volume label string (8-byte) */ #define BS_FilSysType 54 /* Filesystem type string (8-byte) */ #define BS_BootCode 62 /* Boot code (448-byte) */ #define BS_55AA 510 /* Signature word (WORD) */ #define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ #define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ #define BPB_FSVer32 42 /* FAT32: Filesystem version (WORD) */ #define BPB_RootClus32 44 /* FAT32: Root directory cluster (DWORD) */ #define BPB_FSInfo32 48 /* FAT32: Offset of FSINFO sector (WORD) */ #define BPB_BkBootSec32 50 /* FAT32: Offset of backup boot sector (WORD) */ #define BS_DrvNum32 64 /* FAT32: Physical drive number for int13h (BYTE) */ #define BS_NTres32 65 /* FAT32: Error flag (BYTE) */ #define BS_BootSig32 66 /* FAT32: Extended boot signature (BYTE) */ #define BS_VolID32 67 /* FAT32: Volume serial number (DWORD) */ #define BS_VolLab32 71 /* FAT32: Volume label string (8-byte) */ #define BS_FilSysType32 82 /* FAT32: Filesystem type string (8-byte) */ #define BS_BootCode32 90 /* FAT32: Boot code (420-byte) */ #define BPB_ZeroedEx 11 /* exFAT: MBZ field (53-byte) */ #define BPB_VolOfsEx 64 /* exFAT: Volume offset from top of the drive [sector] (QWORD) */ #define BPB_TotSecEx 72 /* exFAT: Volume size [sector] (QWORD) */ #define BPB_FatOfsEx 80 /* exFAT: FAT offset from top of the volume [sector] (DWORD) */ #define BPB_FatSzEx 84 /* exFAT: FAT size [sector] (DWORD) */ #define BPB_DataOfsEx 88 /* exFAT: Data offset from top of the volume [sector] (DWORD) */ #define BPB_NumClusEx 92 /* exFAT: Number of clusters (DWORD) */ #define BPB_RootClusEx 96 /* exFAT: Root directory start cluster (DWORD) */ #define BPB_VolIDEx 100 /* exFAT: Volume serial number (DWORD) */ #define BPB_FSVerEx 104 /* exFAT: Filesystem version (WORD) */ #define BPB_VolFlagEx 106 /* exFAT: Volume flags (WORD) */ #define BPB_BytsPerSecEx 108 /* exFAT: Log2 of sector size in unit of byte (BYTE) */ #define BPB_SecPerClusEx 109 /* exFAT: Log2 of cluster size in unit of sector (BYTE) */ #define BPB_NumFATsEx 110 /* exFAT: Number of FATs (BYTE) */ #define BPB_DrvNumEx 111 /* exFAT: Physical drive number for int13h (BYTE) */ #define BPB_PercInUseEx 112 /* exFAT: Percent in use (BYTE) */ #define BPB_RsvdEx 113 /* exFAT: Reserved (7-byte) */ #define BS_BootCodeEx 120 /* exFAT: Boot code (390-byte) */ #define DIR_Name 0 /* Short file name (11-byte) */ #define DIR_Attr 11 /* Attribute (BYTE) */ #define DIR_NTres 12 /* Lower case flag (BYTE) */ #define DIR_CrtTime10 13 /* Created time sub-second (BYTE) */ #define DIR_CrtTime 14 /* Created time (DWORD) */ #define DIR_LstAccDate 18 /* Last accessed date (WORD) */ #define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (WORD) */ #define DIR_ModTime 22 /* Modified time (DWORD) */ #define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (WORD) */ #define DIR_FileSize 28 /* File size (DWORD) */ #define LDIR_Ord 0 /* LFN: LFN order and LLE flag (BYTE) */ #define LDIR_Attr 11 /* LFN: LFN attribute (BYTE) */ #define LDIR_Type 12 /* LFN: Entry type (BYTE) */ #define LDIR_Chksum 13 /* LFN: Checksum of the SFN (BYTE) */ #define LDIR_FstClusLO 26 /* LFN: MBZ field (WORD) */ #define XDIR_Type 0 /* exFAT: Type of exFAT directory entry (BYTE) */ #define XDIR_NumLabel 1 /* exFAT: Number of volume label characters (BYTE) */ #define XDIR_Label 2 /* exFAT: Volume label (11-WORD) */ #define XDIR_CaseSum 4 /* exFAT: Sum of case conversion table (DWORD) */ #define XDIR_NumSec 1 /* exFAT: Number of secondary entries (BYTE) */ #define XDIR_SetSum 2 /* exFAT: Sum of the set of directory entries (WORD) */ #define XDIR_Attr 4 /* exFAT: File attribute (WORD) */ #define XDIR_CrtTime 8 /* exFAT: Created time (DWORD) */ #define XDIR_ModTime 12 /* exFAT: Modified time (DWORD) */ #define XDIR_AccTime 16 /* exFAT: Last accessed time (DWORD) */ #define XDIR_CrtTime10 20 /* exFAT: Created time subsecond (BYTE) */ #define XDIR_ModTime10 21 /* exFAT: Modified time subsecond (BYTE) */ #define XDIR_CrtTZ 22 /* exFAT: Created timezone (BYTE) */ #define XDIR_ModTZ 23 /* exFAT: Modified timezone (BYTE) */ #define XDIR_AccTZ 24 /* exFAT: Last accessed timezone (BYTE) */ #define XDIR_GenFlags 33 /* exFAT: General secondary flags (BYTE) */ #define XDIR_NumName 35 /* exFAT: Number of file name characters (BYTE) */ #define XDIR_NameHash 36 /* exFAT: Hash of file name (WORD) */ #define XDIR_ValidFileSize 40 /* exFAT: Valid file size (QWORD) */ #define XDIR_FstClus 52 /* exFAT: First cluster of the file data (DWORD) */ #define XDIR_FileSize 56 /* exFAT: File/Directory size (QWORD) */ #define SZDIRE 32 /* Size of a directory entry */ #define DDEM 0xE5 /* Deleted directory entry mark set to DIR_Name[0] */ #define RDDEM 0x05 /* Replacement of the character collides with DDEM */ #define LLEF 0x40 /* Last long entry flag in LDIR_Ord */ #define FSI_LeadSig 0 /* FAT32 FSI: Leading signature (DWORD) */ #define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ #define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ #define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ #define MBR_Table 446 /* MBR: Offset of partition table in the MBR */ #define SZ_PTE 16 /* MBR: Size of a partition table entry */ #define PTE_Boot 0 /* MBR PTE: Boot indicator */ #define PTE_StHead 1 /* MBR PTE: Start head */ #define PTE_StSec 2 /* MBR PTE: Start sector */ #define PTE_StCyl 3 /* MBR PTE: Start cylinder */ #define PTE_System 4 /* MBR PTE: System ID */ #define PTE_EdHead 5 /* MBR PTE: End head */ #define PTE_EdSec 6 /* MBR PTE: End sector */ #define PTE_EdCyl 7 /* MBR PTE: End cylinder */ #define PTE_StLba 8 /* MBR PTE: Start in LBA */ #define PTE_SizLba 12 /* MBR PTE: Size in LBA */ /* Post process on fatal error in the file operations */ #define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } /* Re-entrancy related */ #if FF_FS_REENTRANT #if FF_USE_LFN == 1 #error Static LFN work area cannot be used at thread-safe configuration #endif #define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } #else #define LEAVE_FF(fs, res) return res #endif /* Definitions of volume - physical location conversion */ #if FF_MULTI_PARTITION #define LD2PT(fs) (fs->part) /* Get partition index */ #else #define LD2PT(fs) 0 /* Find first valid partition or in SFD */ #endif /* Definitions of sector size */ #if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096) #error Wrong sector size configuration #endif #if FF_MAX_SS == FF_MIN_SS #define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */ #else #define SS(fs) ((fs)->ssize) /* Variable sector size */ #endif /* Timestamp */ #if FF_FS_NORTC == 1 #if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31 #error Invalid FF_FS_NORTC settings #endif #define GET_FATTIME() ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16) #else #define GET_FATTIME() get_fattime() #endif /* File lock controls */ #if FF_FS_LOCK != 0 #if FF_FS_READONLY #error FF_FS_LOCK must be 0 at read-only configuration #endif typedef struct { FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ DWORD clu; /* Object ID 2, containing directory (0:root) */ DWORD ofs; /* Object ID 3, offset in the directory */ WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ } FILESEM; #endif /* SBCS up-case tables (\x80-\xFF) */ #define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT720 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT737 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT771 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDC,0xDE,0xDE, \ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF} #define TBL_CT775 {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \ 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT850 {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \ 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \ 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT852 {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \ 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \ 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} #define TBL_CT855 {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \ 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \ 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} #define TBL_CT857 {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \ 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT860 {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \ 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT861 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \ 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT862 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT863 {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \ 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \ 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT864 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT865 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT866 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #define TBL_CT869 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \ 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \ 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \ 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF} /* DBCS code range |----- 1st byte -----| |----------- 2nd byte -----------| */ #define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00} #define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00} #define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE} #define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00} /* Macros for table definitions */ #define MERGE_2STR(a, b) a ## b #define MKCVTBL(hd, cp) MERGE_2STR(hd, cp) /*-------------------------------------------------------------------------- Module Private Work Area ---------------------------------------------------------------------------*/ /* Remark: Variables defined here without initial value shall be guaranteed / zero/null at start-up. If not, the linker option or start-up routine is / not compliance with C standard. */ /*--------------------------------*/ /* File/Volume controls */ /*--------------------------------*/ #if FF_VOLUMES < 1 || FF_VOLUMES > 10 #error Wrong FF_VOLUMES setting #endif static WORD Fsid; /* Filesystem mount ID */ #if FF_FS_LOCK != 0 static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ #endif #if FF_STR_VOLUME_ID #ifdef FF_VOLUME_STRS static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ #endif #endif /*--------------------------------*/ /* LFN/Directory working buffer */ /*--------------------------------*/ #if FF_USE_LFN == 0 /* Non-LFN configuration */ #if FF_FS_EXFAT #error LFN must be enabled when enable exFAT #endif #define DEF_NAMBUF #define INIT_NAMBUF(fs) #define FREE_NAMBUF() #define LEAVE_MKFS(res) return res #else /* LFN configurations */ #if FF_MAX_LFN < 12 || FF_MAX_LFN > 255 #error Wrong setting of FF_MAX_LFN #endif #if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12 #error Wrong setting of FF_LFN_BUF or FF_SFN_BUF #endif #if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3 #error Wrong setting of FF_LFN_UNICODE #endif static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* FAT: Offset of LFN characters in the directory entry */ #define MAXDIRB(nc) ((nc + 44U) / 15 * SZDIRE) /* exFAT: Size of directory entry block scratchpad buffer needed for the name length */ #if FF_USE_LFN == 1 /* LFN enabled with static working buffer */ #if FF_FS_EXFAT static BYTE DirBuf[MAXDIRB(FF_MAX_LFN)]; /* Directory entry block scratchpad buffer */ #endif static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ #define DEF_NAMBUF #define INIT_NAMBUF(fs) #define FREE_NAMBUF() #define LEAVE_MKFS(res) return res #elif FF_USE_LFN == 2 /* LFN enabled with dynamic working buffer on the stack */ #if FF_FS_EXFAT #define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; BYTE dbuf[MAXDIRB(FF_MAX_LFN)]; /* LFN working buffer and directory entry block scratchpad buffer */ #define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; } #define FREE_NAMBUF() #else #define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; /* LFN working buffer */ #define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; } #define FREE_NAMBUF() #endif #define LEAVE_MKFS(res) return res #elif FF_USE_LFN == 3 /* LFN enabled with dynamic working buffer on the heap */ #if FF_FS_EXFAT #define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer and directory entry block scratchpad buffer */ #define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2 + MAXDIRB(FF_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+FF_MAX_LFN+1); } #define FREE_NAMBUF() ff_memfree(lfn) #else #define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer */ #define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } #define FREE_NAMBUF() ff_memfree(lfn) #endif #define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; } #define MAX_MALLOC 0x8000 /* Must be >=FF_MAX_SS */ #else #error Wrong setting of FF_USE_LFN #endif /* FF_USE_LFN == 1 */ #endif /* FF_USE_LFN == 0 */ /*--------------------------------*/ /* Code conversion tables */ /*--------------------------------*/ #if FF_CODE_PAGE == 0 /* Run-time code page configuration */ #define CODEPAGE CodePage static WORD CodePage; /* Current code page */ static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */ static const BYTE Ct437[] = TBL_CT437; static const BYTE Ct720[] = TBL_CT720; static const BYTE Ct737[] = TBL_CT737; static const BYTE Ct771[] = TBL_CT771; static const BYTE Ct775[] = TBL_CT775; static const BYTE Ct850[] = TBL_CT850; static const BYTE Ct852[] = TBL_CT852; static const BYTE Ct855[] = TBL_CT855; static const BYTE Ct857[] = TBL_CT857; static const BYTE Ct860[] = TBL_CT860; static const BYTE Ct861[] = TBL_CT861; static const BYTE Ct862[] = TBL_CT862; static const BYTE Ct863[] = TBL_CT863; static const BYTE Ct864[] = TBL_CT864; static const BYTE Ct865[] = TBL_CT865; static const BYTE Ct866[] = TBL_CT866; static const BYTE Ct869[] = TBL_CT869; static const BYTE Dc932[] = TBL_DC932; static const BYTE Dc936[] = TBL_DC936; static const BYTE Dc949[] = TBL_DC949; static const BYTE Dc950[] = TBL_DC950; #elif FF_CODE_PAGE < 900 /* Static code page configuration (SBCS) */ #define CODEPAGE FF_CODE_PAGE static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE); #else /* Static code page configuration (DBCS) */ #define CODEPAGE FF_CODE_PAGE static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); #endif /*-------------------------------------------------------------------------- Module Private Functions ---------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ /* Load/Store multi-byte word in the FAT structure */ /*-----------------------------------------------------------------------*/ static WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ { WORD rv; rv = ptr[1]; rv = rv << 8 | ptr[0]; return rv; } static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ { DWORD rv; rv = ptr[3]; rv = rv << 8 | ptr[2]; rv = rv << 8 | ptr[1]; rv = rv << 8 | ptr[0]; return rv; } #if FF_FS_EXFAT static QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ { QWORD rv; rv = ptr[7]; rv = rv << 8 | ptr[6]; rv = rv << 8 | ptr[5]; rv = rv << 8 | ptr[4]; rv = rv << 8 | ptr[3]; rv = rv << 8 | ptr[2]; rv = rv << 8 | ptr[1]; rv = rv << 8 | ptr[0]; return rv; } #endif #if !FF_FS_READONLY static void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; } static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; } #if FF_FS_EXFAT static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; } #endif #endif /* !FF_FS_READONLY */ /*-----------------------------------------------------------------------*/ /* String functions */ /*-----------------------------------------------------------------------*/ // These were originally provided by the FatFs library but we use externally // provided versions from C stdlib to (hopefully) reduce code size and use // more efficient versions. #define mem_cpy memcpy #define mem_set memset #define mem_cmp memcmp /* Check if chr is contained in the string */ static int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ { while (*str && *str != chr) str++; return *str; } /* Test if the character is DBC 1st byte */ static int dbc_1st (BYTE c) { #if FF_CODE_PAGE == 0 /* Variable code page */ if (DbcTbl && c >= DbcTbl[0]) { if (c <= DbcTbl[1]) return 1; /* 1st byte range 1 */ if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; /* 1st byte range 2 */ } #elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ if (c >= DbcTbl[0]) { if (c <= DbcTbl[1]) return 1; if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; } #else /* SBCS fixed code page */ if (c != 0) return 0; /* Always false */ #endif return 0; } /* Test if the character is DBC 2nd byte */ static int dbc_2nd (BYTE c) { #if FF_CODE_PAGE == 0 /* Variable code page */ if (DbcTbl && c >= DbcTbl[4]) { if (c <= DbcTbl[5]) return 1; /* 2nd byte range 1 */ if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; /* 2nd byte range 2 */ if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; /* 2nd byte range 3 */ } #elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ if (c >= DbcTbl[4]) { if (c <= DbcTbl[5]) return 1; if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; } #else /* SBCS fixed code page */ if (c != 0) return 0; /* Always false */ #endif return 0; } #if FF_USE_LFN /* Get a character from TCHAR string in defined API encodeing */ static DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */ const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ ) { DWORD uc; const TCHAR *p = *str; #if FF_LFN_UNICODE == 1 /* UTF-16 input */ WCHAR wc; uc = *p++; /* Get a unit */ if (IsSurrogate(uc)) { /* Surrogate? */ wc = *p++; /* Get low surrogate */ if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF; /* Wrong surrogate? */ uc = uc << 16 | wc; } #elif FF_LFN_UNICODE == 2 /* UTF-8 input */ BYTE b; int nf; uc = (BYTE)*p++; /* Get a unit */ if (uc & 0x80) { /* Multiple byte code? */ if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */ uc &= 0x1F; nf = 1; } else { if ((uc & 0xF0) == 0xE0) { /* 3-byte sequence? */ uc &= 0x0F; nf = 2; } else { if ((uc & 0xF8) == 0xF0) { /* 4-byte sequence? */ uc &= 0x07; nf = 3; } else { /* Wrong sequence */ return 0xFFFFFFFF; } } } do { /* Get trailing bytes */ b = (BYTE)*p++; if ((b & 0xC0) != 0x80) return 0xFFFFFFFF; /* Wrong sequence? */ uc = uc << 6 | (b & 0x3F); } while (--nf != 0); if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ } #elif FF_LFN_UNICODE == 3 /* UTF-32 input */ uc = (TCHAR)*p++; /* Get a unit */ if (uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ #else /* ANSI/OEM input */ BYTE b; WCHAR wc; wc = (BYTE)*p++; /* Get a byte */ if (dbc_1st((BYTE)wc)) { /* Is it a DBC 1st byte? */ b = (BYTE)*p++; /* Get 2nd byte */ if (!dbc_2nd(b)) return 0xFFFFFFFF; /* Invalid code? */ wc = (wc << 8) + b; /* Make a DBC */ } if (wc != 0) { wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM ==> Unicode */ if (wc == 0) return 0xFFFFFFFF; /* Invalid code? */ } uc = wc; #endif *str = p; /* Next read pointer */ return uc; } /* Output a TCHAR string in defined API encoding */ static BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ DWORD chr, /* UTF-16 encoded character (Double encoding unit char if >=0x10000) */ TCHAR* buf, /* Output buffer */ UINT szb /* Size of the buffer */ ) { #if FF_LFN_UNICODE == 1 /* UTF-16 output */ WCHAR hs, wc; hs = (WCHAR)(chr >> 16); wc = (WCHAR)chr; if (hs == 0) { /* Single encoding unit? */ if (szb < 1 || IsSurrogate(wc)) return 0; /* Buffer overflow or wrong code? */ *buf = wc; return 1; } if (szb < 2 || !IsSurrogateH(hs) || !IsSurrogateL(wc)) return 0; /* Buffer overflow or wrong surrogate? */ *buf++ = hs; *buf++ = wc; return 2; #elif FF_LFN_UNICODE == 2 /* UTF-8 output */ DWORD hc; if (chr < 0x80) { /* Single byte code? */ if (szb < 1) return 0; /* Buffer overflow? */ *buf = (TCHAR)chr; return 1; } if (chr < 0x800) { /* 2-byte sequence? */ if (szb < 2) return 0; /* Buffer overflow? */ *buf++ = (TCHAR)(0xC0 | (chr >> 6 & 0x1F)); *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); return 2; } if (chr < 0x10000) { /* 3-byte sequence? */ if (szb < 3 || IsSurrogate(chr)) return 0; /* Buffer overflow or wrong code? */ *buf++ = (TCHAR)(0xE0 | (chr >> 12 & 0x0F)); *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); return 3; } /* 4-byte sequence */ if (szb < 4) return 0; /* Buffer overflow? */ hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ chr = (hc | chr) + 0x10000; *buf++ = (TCHAR)(0xF0 | (chr >> 18 & 0x07)); *buf++ = (TCHAR)(0x80 | (chr >> 12 & 0x3F)); *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); return 4; #elif FF_LFN_UNICODE == 3 /* UTF-32 output */ DWORD hc; if (szb < 1) return 0; /* Buffer overflow? */ if (chr >= 0x10000) { /* Out of BMP? */ hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ chr = (hc | chr) + 0x10000; } *buf++ = (TCHAR)chr; return 1; #else /* ANSI/OEM output */ WCHAR wc; wc = ff_uni2oem(chr, CODEPAGE); if (wc >= 0x100) { /* Is this a DBC? */ if (szb < 2) return 0; *buf++ = (char)(wc >> 8); /* Store DBC 1st byte */ *buf++ = (TCHAR)wc; /* Store DBC 2nd byte */ return 2; } if (wc == 0 || szb < 1) return 0; /* Invalid char or buffer overflow? */ *buf++ = (TCHAR)wc; /* Store the character */ return 1; #endif } #endif /* FF_USE_LFN */ #if FF_FS_REENTRANT /*-----------------------------------------------------------------------*/ /* Request/Release grant to access the volume */ /*-----------------------------------------------------------------------*/ static int lock_fs ( /* 1:Ok, 0:timeout */ FATFS* fs /* Filesystem object */ ) { return ff_req_grant(fs->sobj); } static void unlock_fs ( FATFS* fs, /* Filesystem object */ FRESULT res /* Result code to be returned */ ) { if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) { ff_rel_grant(fs->sobj); } } #endif #if FF_FS_LOCK != 0 /*-----------------------------------------------------------------------*/ /* File lock control functions */ /*-----------------------------------------------------------------------*/ static FRESULT chk_lock ( /* Check if the file can be accessed */ DIR* dp, /* Directory object pointing the file to be checked */ int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ ) { UINT i, be; /* Search open object table for the object */ be = 0; for (i = 0; i < FF_FS_LOCK; i++) { if (Files[i].fs) { /* Existing entry */ if (Files[i].fs == dp->obj.fs && /* Check if the object matches with an open object */ Files[i].clu == dp->obj.sclust && Files[i].ofs == dp->dptr) break; } else { /* Blank entry */ be = 1; } } if (i == FF_FS_LOCK) { /* The object has not been opened */ return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK; /* Is there a blank entry for new object? */ } /* The object was opened. Reject any open against writing file and all write mode open */ return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; } static int enq_lock (void) /* Check if an entry is available for a new object */ { UINT i; for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; return (i == FF_FS_LOCK) ? 0 : 1; } static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ DIR* dp, /* Directory object pointing the file to register or increment */ int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ ) { UINT i; for (i = 0; i < FF_FS_LOCK; i++) { /* Find the object */ if (Files[i].fs == dp->obj.fs && Files[i].clu == dp->obj.sclust && Files[i].ofs == dp->dptr) break; } if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */ for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; if (i == FF_FS_LOCK) return 0; /* No free entry to register (int err) */ Files[i].fs = dp->obj.fs; Files[i].clu = dp->obj.sclust; Files[i].ofs = dp->dptr; Files[i].ctr = 0; } if (acc >= 1 && Files[i].ctr) return 0; /* Access violation (int err) */ Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ return i + 1; /* Index number origin from 1 */ } static FRESULT dec_lock ( /* Decrement object open counter */ UINT i /* Semaphore index (1..) */ ) { WORD n; FRESULT res; if (--i < FF_FS_LOCK) { /* Index number origin from 0 */ n = Files[i].ctr; if (n == 0x100) n = 0; /* If write mode open, delete the entry */ if (n > 0) n--; /* Decrement read mode open count */ Files[i].ctr = n; if (n == 0) Files[i].fs = 0; /* Delete the entry if open count gets zero */ res = FR_OK; } else { res = FR_INT_ERR; /* Invalid index nunber */ } return res; } static void clear_lock ( /* Clear lock entries of the volume */ FATFS *fs ) { UINT i; for (i = 0; i < FF_FS_LOCK; i++) { if (Files[i].fs == fs) Files[i].fs = 0; } } #endif /* FF_FS_LOCK != 0 */ /*-----------------------------------------------------------------------*/ /* Move/Flush disk access window in the filesystem object */ /*-----------------------------------------------------------------------*/ #if !FF_FS_READONLY static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs /* Filesystem object */ ) { FRESULT res = FR_OK; if (fs->wflag) { /* Is the disk access window dirty */ if (disk_write(fs->drv, fs->win, fs->winsect, 1) == RES_OK) { /* Write back the window */ fs->wflag = 0; /* Clear window dirty flag */ if (fs->winsect - fs->fatbase < fs->fsize) { /* Is it in the 1st FAT? */ if (fs->n_fats == 2) disk_write(fs->drv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */ } } else { res = FR_DISK_ERR; } } return res; } #endif static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs, /* Filesystem object */ DWORD sector /* Sector number to make appearance in the fs->win[] */ ) { FRESULT res = FR_OK; if (sector != fs->winsect) { /* Window offset changed? */ #if !FF_FS_READONLY res = sync_window(fs); /* Write-back changes */ #endif if (res == FR_OK) { /* Fill sector window with new data */ if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) { sector = 0xFFFFFFFF; /* Invalidate window if read data is not valid */ res = FR_DISK_ERR; } fs->winsect = sector; } } return res; } #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Synchronize filesystem and data on the storage */ /*-----------------------------------------------------------------------*/ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs /* Filesystem object */ ) { FRESULT res; res = sync_window(fs); if (res == FR_OK) { if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */ /* Create FSInfo structure */ mem_set(fs->win, 0, sizeof fs->win); st_word(fs->win + BS_55AA, 0xAA55); st_dword(fs->win + FSI_LeadSig, 0x41615252); st_dword(fs->win + FSI_StrucSig, 0x61417272); st_dword(fs->win + FSI_Free_Count, fs->free_clst); st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); /* Write it into the FSInfo sector */ fs->winsect = fs->volbase + 1; disk_write(fs->drv, fs->win, fs->winsect, 1); fs->fsi_flag = 0; } /* Make sure that no pending write process in the lower layer */ if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; } return res; } #endif /*-----------------------------------------------------------------------*/ /* Get physical sector number from cluster number */ /*-----------------------------------------------------------------------*/ static DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ FATFS* fs, /* Filesystem object */ DWORD clst /* Cluster# to be converted */ ) { clst -= 2; /* Cluster number is origin from 2 */ if (clst >= fs->n_fatent - 2) return 0; /* Is it invalid cluster number? */ return fs->database + fs->csize * clst; /* Start sector number of the cluster */ } /*-----------------------------------------------------------------------*/ /* FAT access - Read value of a FAT entry */ /*-----------------------------------------------------------------------*/ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ FFOBJID* obj, /* Corresponding object */ DWORD clst /* Cluster number to get the value */ ) { UINT wc, bc; DWORD val; FATFS *fs = obj->fs; if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */ val = 1; /* Internal error */ } else { val = 0xFFFFFFFF; /* Default value falls on disk error */ switch (fs->fs_type) { case FS_FAT12 : bc = (UINT)clst; bc += bc / 2; if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; wc = fs->win[bc++ % SS(fs)]; /* Get 1st byte of the entry */ if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; wc |= fs->win[bc % SS(fs)] << 8; /* Merge 2nd byte of the entry */ val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); /* Adjust bit position */ break; case FS_FAT16 : if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; val = ld_word(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */ break; case FS_FAT32 : if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */ break; #if FF_FS_EXFAT case FS_EXFAT : if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) { /* Object except root dir must have valid data length */ DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ if (obj->stat == 2 && cofs <= clen) { /* Is it a contiguous chain? */ val = (cofs == clen) ? 0x7FFFFFFF : clst + 1; /* No data on the FAT, generate the value */ break; } if (obj->stat == 3 && cofs < obj->n_cont) { /* Is it in the 1st fragment? */ val = clst + 1; /* Generate the value */ break; } if (obj->stat != 2) { /* Get value from FAT if FAT chain is valid */ if (obj->n_frag != 0) { /* Is it on the growing edge? */ val = 0x7FFFFFFF; /* Generate EOC */ } else { if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; } break; } } /* go to default */ #endif default: val = 1; /* Internal error */ } } return val; } #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* FAT access - Change value of a FAT entry */ /*-----------------------------------------------------------------------*/ static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ FATFS* fs, /* Corresponding filesystem object */ DWORD clst, /* FAT index number (cluster number) to be changed */ DWORD val /* New value to be set to the entry */ ) { UINT bc; BYTE *p; FRESULT res = FR_INT_ERR; if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */ switch (fs->fs_type) { case FS_FAT12 : bc = (UINT)clst; bc += bc / 2; /* bc: byte offset of the entry */ res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; p = fs->win + bc++ % SS(fs); *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Put 1st byte */ fs->wflag = 1; res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; p = fs->win + bc % SS(fs); *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); /* Put 2nd byte */ fs->wflag = 1; break; case FS_FAT16 : res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); if (res != FR_OK) break; st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */ fs->wflag = 1; break; case FS_FAT32 : #if FF_FS_EXFAT case FS_EXFAT : #endif res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); if (res != FR_OK) break; if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); } st_dword(fs->win + clst * 4 % SS(fs), val); fs->wflag = 1; break; } } return res; } #endif /* !FF_FS_READONLY */ #if FF_FS_EXFAT && !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* exFAT: Accessing FAT and Allocation Bitmap */ /*-----------------------------------------------------------------------*/ /*--------------------------------------*/ /* Find a contiguous free cluster block */ /*--------------------------------------*/ static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ FATFS* fs, /* Filesystem object */ DWORD clst, /* Cluster number to scan from */ DWORD ncl /* Number of contiguous clusters to find (1..) */ ) { BYTE bm, bv; UINT i; DWORD val, scl, ctr; clst -= 2; /* The first bit in the bitmap corresponds to cluster #2 */ if (clst >= fs->n_fatent - 2) clst = 0; scl = val = clst; ctr = 0; for (;;) { if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; i = val / 8 % SS(fs); bm = 1 << (val % 8); do { do { bv = fs->win[i] & bm; bm <<= 1; /* Get bit value */ if (++val >= fs->n_fatent - 2) { /* Next cluster (with wrap-around) */ val = 0; bm = 0; i = SS(fs); } if (bv == 0) { /* Is it a free cluster? */ if (++ctr == ncl) return scl + 2; /* Check if run length is sufficient for required */ } else { scl = val; ctr = 0; /* Encountered a cluster in-use, restart to scan */ } if (val == clst) return 0; /* All cluster scanned? */ } while (bm != 0); bm = 1; } while (++i < SS(fs)); } } /*----------------------------------------*/ /* Set/Clear a block of allocation bitmap */ /*----------------------------------------*/ static FRESULT change_bitmap ( FATFS* fs, /* Filesystem object */ DWORD clst, /* Cluster number to change from */ DWORD ncl, /* Number of clusters to be changed */ int bv /* bit value to be set (0 or 1) */ ) { BYTE bm; UINT i; DWORD sect; clst -= 2; /* The first bit corresponds to cluster #2 */ sect = fs->bitbase + clst / 8 / SS(fs); /* Sector address */ i = clst / 8 % SS(fs); /* Byte offset in the sector */ bm = 1 << (clst % 8); /* Bit mask in the byte */ for (;;) { if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR; do { do { if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR; /* Is the bit expected value? */ fs->win[i] ^= bm; /* Flip the bit */ fs->wflag = 1; if (--ncl == 0) return FR_OK; /* All bits processed? */ } while (bm <<= 1); /* Next bit */ bm = 1; } while (++i < SS(fs)); /* Next byte */ i = 0; } } /*---------------------------------------------*/ /* Fill the first fragment of the FAT chain */ /*---------------------------------------------*/ static FRESULT fill_first_frag ( FFOBJID* obj /* Pointer to the corresponding object */ ) { FRESULT res; DWORD cl, n; if (obj->stat == 3) { /* Has the object been changed 'fragmented' in this session? */ for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) { /* Create cluster chain on the FAT */ res = put_fat(obj->fs, cl, cl + 1); if (res != FR_OK) return res; } obj->stat = 0; /* Change status 'FAT chain is valid' */ } return FR_OK; } /*---------------------------------------------*/ /* Fill the last fragment of the FAT chain */ /*---------------------------------------------*/ static FRESULT fill_last_frag ( FFOBJID* obj, /* Pointer to the corresponding object */ DWORD lcl, /* Last cluster of the fragment */ DWORD term /* Value to set the last FAT entry */ ) { FRESULT res; while (obj->n_frag > 0) { /* Create the chain of last fragment */ res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term); if (res != FR_OK) return res; obj->n_frag--; } return FR_OK; } #endif /* FF_FS_EXFAT && !FF_FS_READONLY */ #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* FAT handling - Remove a cluster chain */ /*-----------------------------------------------------------------------*/ static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ FFOBJID* obj, /* Corresponding object */ DWORD clst, /* Cluster to remove a chain from */ DWORD pclst /* Previous cluster of clst (0 if entire chain) */ ) { FRESULT res = FR_OK; DWORD nxt; FATFS *fs = obj->fs; #if FF_FS_EXFAT || FF_USE_TRIM DWORD scl = clst, ecl = clst; #endif #if FF_USE_TRIM DWORD rt[2]; #endif if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Check if in valid range */ /* Mark the previous cluster 'EOC' on the FAT if it exists */ if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) { res = put_fat(fs, pclst, 0xFFFFFFFF); if (res != FR_OK) return res; } /* Remove the chain */ do { nxt = get_fat(obj, clst); /* Get cluster status */ if (nxt == 0) break; /* Empty cluster? */ if (nxt == 1) return FR_INT_ERR; /* Internal error? */ if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error? */ if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { res = put_fat(fs, clst, 0); /* Mark the cluster 'free' on the FAT */ if (res != FR_OK) return res; } if (fs->free_clst < fs->n_fatent - 2) { /* Update FSINFO */ fs->free_clst++; fs->fsi_flag |= 1; } #if FF_FS_EXFAT || FF_USE_TRIM if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ ecl = nxt; } else { /* End of contiguous cluster block */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */ if (res != FR_OK) return res; } #endif #if FF_USE_TRIM rt[0] = clst2sect(fs, scl); /* Start of data area freed */ rt[1] = clst2sect(fs, ecl) + fs->csize - 1; /* End of data area freed */ disk_ioctl(fs->drv, CTRL_TRIM, rt); /* Inform device the data in the block is no longer needed */ #endif scl = ecl = nxt; } #endif clst = nxt; /* Next cluster */ } while (clst < fs->n_fatent); /* Repeat while not the last link */ #if FF_FS_EXFAT /* Some post processes for chain status */ if (fs->fs_type == FS_EXFAT) { if (pclst == 0) { /* Has the entire chain been removed? */ obj->stat = 0; /* Change the chain status 'initial' */ } else { if (obj->stat == 0) { /* Is it a fragmented chain from the beginning of this session? */ clst = obj->sclust; /* Follow the chain to check if it gets contiguous */ while (clst != pclst) { nxt = get_fat(obj, clst); if (nxt < 2) return FR_INT_ERR; if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; if (nxt != clst + 1) break; /* Not contiguous? */ clst++; } if (clst == pclst) { /* Has the chain got contiguous again? */ obj->stat = 2; /* Change the chain status 'contiguous' */ } } else { if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) { /* Was the chain fragmented in this session and got contiguous again? */ obj->stat = 2; /* Change the chain status 'contiguous' */ } } } } #endif return FR_OK; } /*-----------------------------------------------------------------------*/ /* FAT handling - Stretch a chain or Create a new chain */ /*-----------------------------------------------------------------------*/ static DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ FFOBJID* obj, /* Corresponding object */ DWORD clst /* Cluster# to stretch, 0:Create a new chain */ ) { DWORD cs, ncl, scl; FRESULT res; FATFS *fs = obj->fs; if (clst == 0) { /* Create a new chain */ scl = fs->last_clst; /* Suggested cluster to start to find */ if (scl == 0 || scl >= fs->n_fatent) scl = 1; } else { /* Stretch a chain */ cs = get_fat(obj, clst); /* Check the cluster status */ if (cs < 2) return 1; /* Test for insanity */ if (cs == 0xFFFFFFFF) return cs; /* Test for disk error */ if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ scl = clst; /* Cluster to start to find */ } if (fs->free_clst == 0) return 0; /* No free cluster */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ if (res == FR_INT_ERR) return 1; if (res == FR_DISK_ERR) return 0xFFFFFFFF; if (clst == 0) { /* Is it a new chain? */ obj->stat = 2; /* Set status 'contiguous' */ } else { /* It is a stretched chain */ if (obj->stat == 2 && ncl != scl + 1) { /* Is the chain got fragmented? */ obj->n_cont = scl - obj->sclust; /* Set size of the contiguous part */ obj->stat = 3; /* Change status 'just fragmented' */ } } if (obj->stat != 2) { /* Is the file non-contiguous? */ if (ncl == clst + 1) { /* Is the cluster next to previous one? */ obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2; /* Increment size of last framgent */ } else { /* New fragment */ if (obj->n_frag == 0) obj->n_frag = 1; res = fill_last_frag(obj, clst, ncl); /* Fill last fragment on the FAT and link it to new one */ if (res == FR_OK) obj->n_frag = 1; } } } else #endif { /* On the FAT/FAT32 volume */ ncl = 0; if (scl == clst) { /* Stretching an existing chain? */ ncl = scl + 1; /* Test if next cluster is free */ if (ncl >= fs->n_fatent) ncl = 2; cs = get_fat(obj, ncl); /* Get next cluster status */ if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ if (cs != 0) { /* Not free? */ cs = fs->last_clst; /* Start at suggested cluster if it is valid */ if (cs >= 2 && cs < fs->n_fatent) scl = cs; ncl = 0; } } if (ncl == 0) { /* The new cluster cannot be contiguous and find another fragment */ ncl = scl; /* Start cluster */ for (;;) { ncl++; /* Next cluster */ if (ncl >= fs->n_fatent) { /* Check wrap-around */ ncl = 2; if (ncl > scl) return 0; /* No free cluster found? */ } cs = get_fat(obj, ncl); /* Get the cluster status */ if (cs == 0) break; /* Found a free cluster? */ if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ if (ncl == scl) return 0; /* No free cluster found? */ } } res = put_fat(fs, ncl, 0xFFFFFFFF); /* Mark the new cluster 'EOC' */ if (res == FR_OK && clst != 0) { res = put_fat(fs, clst, ncl); /* Link it from the previous one if needed */ } } if (res == FR_OK) { /* Update FSINFO if function succeeded. */ fs->last_clst = ncl; if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--; fs->fsi_flag |= 1; } else { ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; /* Failed. Generate error status */ } return ncl; /* Return new cluster number or error status */ } #endif /* !FF_FS_READONLY */ #if FF_USE_FASTSEEK /*-----------------------------------------------------------------------*/ /* FAT handling - Convert offset into cluster with link map table */ /*-----------------------------------------------------------------------*/ static DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ FIL* fp, /* Pointer to the file object */ FSIZE_t ofs /* File offset to be converted to cluster# */ ) { DWORD cl, ncl, *tbl; FATFS *fs = fp->obj.fs; tbl = fp->cltbl + 1; /* Top of CLMT */ cl = (DWORD)(ofs / SS(fs) / fs->csize); /* Cluster order from top of the file */ for (;;) { ncl = *tbl++; /* Number of cluters in the fragment */ if (ncl == 0) return 0; /* End of table? (error) */ if (cl < ncl) break; /* In this fragment? */ cl -= ncl; tbl++; /* Next fragment */ } return cl + *tbl; /* Return the cluster number */ } #endif /* FF_USE_FASTSEEK */ /*-----------------------------------------------------------------------*/ /* Directory handling - Fill a cluster with zeros */ /*-----------------------------------------------------------------------*/ #if !FF_FS_READONLY static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ FATFS *fs, /* Filesystem object */ DWORD clst /* Directory table to clear */ ) { DWORD sect; UINT n, szb; BYTE *ibuf; if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */ sect = clst2sect(fs, clst); /* Top of the cluster */ fs->winsect = sect; /* Set window to top of the cluster */ mem_set(fs->win, 0, sizeof fs->win); /* Clear window buffer */ #if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ /* Allocate a temporary buffer */ for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ; if (szb > SS(fs)) { /* Buffer allocated? */ mem_set(ibuf, 0, szb); szb /= SS(fs); /* Bytes -> Sectors */ for (n = 0; n < fs->csize && disk_write(fs->drv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ ff_memfree(ibuf); } else #endif { ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */ for (n = 0; n < fs->csize && disk_write(fs->drv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ } return (n == fs->csize) ? FR_OK : FR_DISK_ERR; } #endif /* !FF_FS_READONLY */ /*-----------------------------------------------------------------------*/ /* Directory handling - Set directory index */ /*-----------------------------------------------------------------------*/ static FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ DIR* dp, /* Pointer to directory object */ DWORD ofs /* Offset of directory table */ ) { DWORD csz, clst; FATFS *fs = dp->obj.fs; if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) { /* Check range of offset and alignment */ return FR_INT_ERR; } dp->dptr = ofs; /* Set current offset */ clst = dp->obj.sclust; /* Table start cluster (0:root) */ if (clst == 0 && fs->fs_type >= FS_FAT32) { /* Replace cluster# 0 with root cluster# */ clst = fs->dirbase; if (FF_FS_EXFAT) dp->obj.stat = 0; /* exFAT: Root dir has an FAT chain */ } if (clst == 0) { /* Static table (root-directory on the FAT volume) */ if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */ dp->sect = fs->dirbase; } else { /* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */ csz = (DWORD)fs->csize * SS(fs); /* Bytes per cluster */ while (ofs >= csz) { /* Follow cluster chain */ clst = get_fat(&dp->obj, clst); /* Get next cluster */ if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Reached to end of table or internal error */ ofs -= csz; } dp->sect = clst2sect(fs, clst); } dp->clust = clst; /* Current cluster# */ if (dp->sect == 0) return FR_INT_ERR; dp->sect += ofs / SS(fs); /* Sector# of the directory entry */ dp->dir = fs->win + (ofs % SS(fs)); /* Pointer to the entry in the win[] */ return FR_OK; } /*-----------------------------------------------------------------------*/ /* Directory handling - Move directory table index next */ /*-----------------------------------------------------------------------*/ static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ DIR* dp, /* Pointer to the directory object */ int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ ) { DWORD ofs, clst; FATFS *fs = dp->obj.fs; ofs = dp->dptr + SZDIRE; /* Next entry */ if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0; /* Disable it if the offset reached the max value */ if (dp->sect == 0) return FR_NO_FILE; /* Report EOT if it has been disabled */ if (ofs % SS(fs) == 0) { /* Sector changed? */ dp->sect++; /* Next sector */ if (dp->clust == 0) { /* Static table */ if (ofs / SZDIRE >= fs->n_rootdir) { /* Report EOT if it reached end of static table */ dp->sect = 0; return FR_NO_FILE; } } else { /* Dynamic table */ if ((ofs / SS(fs) & (fs->csize - 1)) == 0) { /* Cluster changed? */ clst = get_fat(&dp->obj, dp->clust); /* Get next cluster */ if (clst <= 1) return FR_INT_ERR; /* Internal error */ if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ if (clst >= fs->n_fatent) { /* It reached end of dynamic table */ #if !FF_FS_READONLY if (!stretch) { /* If no stretch, report EOT */ dp->sect = 0; return FR_NO_FILE; } clst = create_chain(&dp->obj, dp->clust); /* Allocate a cluster */ if (clst == 0) return FR_DENIED; /* No free cluster */ if (clst == 1) return FR_INT_ERR; /* Internal error */ if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ if (dir_clear(fs, clst) != FR_OK) return FR_DISK_ERR; /* Clean up the stretched table */ if (FF_FS_EXFAT) dp->obj.stat |= 4; /* exFAT: The directory has been stretched */ #else if (!stretch) dp->sect = 0; /* (this line is to suppress compiler warning) */ dp->sect = 0; return FR_NO_FILE; /* Report EOT */ #endif } dp->clust = clst; /* Initialize data for new cluster */ dp->sect = clst2sect(fs, clst); } } } dp->dptr = ofs; /* Current entry */ dp->dir = fs->win + ofs % SS(fs); /* Pointer to the entry in the win[] */ return FR_OK; } #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Directory handling - Reserve a block of directory entries */ /*-----------------------------------------------------------------------*/ static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ DIR* dp, /* Pointer to the directory object */ UINT nent /* Number of contiguous entries to allocate */ ) { FRESULT res; UINT n; FATFS *fs = dp->obj.fs; res = dir_sdi(dp, 0); if (res == FR_OK) { n = 0; do { res = move_window(fs, dp->sect); if (res != FR_OK) break; #if FF_FS_EXFAT if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) { #else if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) { #endif if (++n == nent) break; /* A block of contiguous free entries is found */ } else { n = 0; /* Not a blank entry. Restart to search */ } res = dir_next(dp, 1); } while (res == FR_OK); /* Next entry with table stretch enabled */ } if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ return res; } #endif /* !FF_FS_READONLY */ /*-----------------------------------------------------------------------*/ /* FAT: Directory handling - Load/Store start cluster number */ /*-----------------------------------------------------------------------*/ static DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ FATFS* fs, /* Pointer to the fs object */ const BYTE* dir /* Pointer to the key entry */ ) { DWORD cl; cl = ld_word(dir + DIR_FstClusLO); if (fs->fs_type == FS_FAT32) { cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16; } return cl; } #if !FF_FS_READONLY static void st_clust ( FATFS* fs, /* Pointer to the fs object */ BYTE* dir, /* Pointer to the key entry */ DWORD cl /* Value to be set */ ) { st_word(dir + DIR_FstClusLO, (WORD)cl); if (fs->fs_type == FS_FAT32) { st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16)); } } #endif #if FF_USE_LFN /*--------------------------------------------------------*/ /* FAT-LFN: Compare a part of file name with an LFN entry */ /*--------------------------------------------------------*/ static int cmp_lfn ( /* 1:matched, 0:not matched */ const WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */ BYTE* dir /* Pointer to the directory entry containing the part of LFN */ ) { UINT i, s; WCHAR wc, uc; if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */ i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ if (wc != 0) { if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */ return 0; /* Not matched */ } wc = uc; } else { if (uc != 0xFFFF) return 0; /* Check filler */ } } if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; /* Last segment matched but different length */ return 1; /* The part of LFN matched */ } #if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT /*-----------------------------------------------------*/ /* FAT-LFN: Pick a part of file name from an LFN entry */ /*-----------------------------------------------------*/ static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ WCHAR* lfnbuf, /* Pointer to the LFN working buffer */ BYTE* dir /* Pointer to the LFN entry */ ) { UINT i, s; WCHAR wc, uc; if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO is 0 */ i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Offset in the LFN buffer */ for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ if (wc != 0) { if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ lfnbuf[i++] = wc = uc; /* Store it */ } else { if (uc != 0xFFFF) return 0; /* Check filler */ } } if (dir[LDIR_Ord] & LLEF && wc != 0) { /* Put terminator if it is the last LFN part and not terminated */ if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ lfnbuf[i] = 0; } return 1; /* The part of LFN is valid */ } #endif #if !FF_FS_READONLY /*-----------------------------------------*/ /* FAT-LFN: Create an entry of LFN entries */ /*-----------------------------------------*/ static void put_lfn ( const WCHAR* lfn, /* Pointer to the LFN */ BYTE* dir, /* Pointer to the LFN entry to be created */ BYTE ord, /* LFN order (1-20) */ BYTE sum /* Checksum of the corresponding SFN */ ) { UINT i, s; WCHAR wc; dir[LDIR_Chksum] = sum; /* Set checksum */ dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ dir[LDIR_Type] = 0; st_word(dir + LDIR_FstClusLO, 0); i = (ord - 1) * 13; /* Get offset in the LFN working buffer */ s = wc = 0; do { if (wc != 0xFFFF) wc = lfn[i++]; /* Get an effective character */ st_word(dir + LfnOfs[s], wc); /* Put it */ if (wc == 0) wc = 0xFFFF; /* Padding characters for left locations */ } while (++s < 13); if (wc == 0xFFFF || !lfn[i]) ord |= LLEF; /* Last LFN part is the start of LFN sequence */ dir[LDIR_Ord] = ord; /* Set the LFN order */ } #endif /* !FF_FS_READONLY */ #endif /* FF_USE_LFN */ #if FF_USE_LFN && !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* FAT-LFN: Create a Numbered SFN */ /*-----------------------------------------------------------------------*/ static void gen_numname ( BYTE* dst, /* Pointer to the buffer to store numbered SFN */ const BYTE* src, /* Pointer to SFN */ const WCHAR* lfn, /* Pointer to LFN */ UINT seq /* Sequence number */ ) { BYTE ns[8], c; UINT i, j; WCHAR wc; DWORD sr; mem_cpy(dst, src, 11); if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */ sr = seq; while (*lfn) { /* Create a CRC as hash value */ wc = *lfn++; for (i = 0; i < 16; i++) { sr = (sr << 1) + (wc & 1); wc >>= 1; if (sr & 0x10000) sr ^= 0x11021; } } seq = (UINT)sr; } /* itoa (hexdecimal) */ i = 7; do { c = (BYTE)((seq % 16) + '0'); if (c > '9') c += 7; ns[i--] = c; seq /= 16; } while (seq); ns[i] = '~'; /* Append the number to the SFN body */ for (j = 0; j < i && dst[j] != ' '; j++) { if (dbc_1st(dst[j])) { if (j == i - 1) break; j++; } } do { dst[j++] = (i < 8) ? ns[i++] : ' '; } while (j < 8); } #endif /* FF_USE_LFN && !FF_FS_READONLY */ #if FF_USE_LFN /*-----------------------------------------------------------------------*/ /* FAT-LFN: Calculate checksum of an SFN entry */ /*-----------------------------------------------------------------------*/ static BYTE sum_sfn ( const BYTE* dir /* Pointer to the SFN entry */ ) { BYTE sum = 0; UINT n = 11; do { sum = (sum >> 1) + (sum << 7) + *dir++; } while (--n); return sum; } #endif /* FF_USE_LFN */ #if FF_FS_EXFAT /*-----------------------------------------------------------------------*/ /* exFAT: Checksum */ /*-----------------------------------------------------------------------*/ static WORD xdir_sum ( /* Get checksum of the directoly entry block */ const BYTE* dir /* Directory entry block to be calculated */ ) { UINT i, szblk; WORD sum; szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; /* Number of bytes of the entry block */ for (i = sum = 0; i < szblk; i++) { if (i == XDIR_SetSum) { /* Skip 2-byte sum field */ i++; } else { sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; } } return sum; } static WORD xname_sum ( /* Get check sum (to be used as hash) of the file name */ const WCHAR* name /* File name to be calculated */ ) { WCHAR chr; WORD sum = 0; while ((chr = *name++) != 0) { chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be up-case converted */ sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); } return sum; } #if !FF_FS_READONLY && FF_USE_MKFS static DWORD xsum32 ( /* Returns 32-bit checksum */ BYTE dat, /* Byte to be calculated (byte-by-byte processing) */ DWORD sum /* Previous sum value */ ) { sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; return sum; } #endif #if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 /*------------------------------------------------------*/ /* exFAT: Get object information from a directory block */ /*------------------------------------------------------*/ static void get_xfileinfo ( BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */ FILINFO* fno /* Buffer to store the extracted file information */ ) { WCHAR wc, hs; UINT di, si, nc; /* Get file name from the entry block */ si = SZDIRE * 2; /* 1st C1 entry */ nc = 0; hs = 0; di = 0; while (nc < dirb[XDIR_NumName]) { if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */ if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ wc = ld_word(dirb + si); si += 2; nc++; /* Get a character */ if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ hs = wc; continue; /* Get low surrogate */ } wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */ if (wc == 0) { di = 0; break; } /* Buffer overflow or wrong encoding? */ di += wc; hs = 0; } if (hs != 0) di = 0; /* Broken surrogate pair? */ if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ fno->fname[di] = 0; /* Terminate the name */ fno->altname[0] = 0; /* exFAT does not support SFN */ fno->fattrib = dirb[XDIR_Attr]; /* Attribute */ fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */ fno->ftime = ld_word(dirb + XDIR_ModTime + 0); /* Time */ fno->fdate = ld_word(dirb + XDIR_ModTime + 2); /* Date */ } #endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ /*-----------------------------------*/ /* exFAT: Get a directry entry block */ /*-----------------------------------*/ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ DIR* dp /* Reading direcotry object pointing top of the entry block to load */ ) { FRESULT res; UINT i, sz_ent; BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */ /* Load file-directory entry */ res = move_window(dp->obj.fs, dp->sect); if (res != FR_OK) return res; if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */ mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE); sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE; if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR; /* Load stream-extension entry */ res = dir_next(dp, 0); if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ if (res != FR_OK) return res; res = move_window(dp->obj.fs, dp->sect); if (res != FR_OK) return res; if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */ mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE); if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR; /* Load file-name entries */ i = 2 * SZDIRE; /* Name offset to load */ do { res = dir_next(dp, 0); if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ if (res != FR_OK) return res; res = move_window(dp->obj.fs, dp->sect); if (res != FR_OK) return res; if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR; /* Invalid order */ if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE); } while ((i += SZDIRE) < sz_ent); /* Sanity check (do it for only accessible object) */ if (i <= MAXDIRB(FF_MAX_LFN)) { if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR; } return FR_OK; } /*------------------------------------------------------------------*/ /* exFAT: Initialize object allocation info with loaded entry block */ /*------------------------------------------------------------------*/ static void init_alloc_info ( FATFS* fs, /* Filesystem object */ FFOBJID* obj /* Object allocation information to be initialized */ ) { obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Start cluster */ obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */ obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; /* Allocation status */ obj->n_frag = 0; /* No last fragment info */ } #if !FF_FS_READONLY || FF_FS_RPATH != 0 /*------------------------------------------------*/ /* exFAT: Load the object's directory entry block */ /*------------------------------------------------*/ static FRESULT load_obj_xdir ( DIR* dp, /* Blank directory object to be used to access containing direcotry */ const FFOBJID* obj /* Object with its containing directory information */ ) { FRESULT res; /* Open object containing directory */ dp->obj.fs = obj->fs; dp->obj.sclust = obj->c_scl; dp->obj.stat = (BYTE)obj->c_size; dp->obj.objsize = obj->c_size & 0xFFFFFF00; dp->obj.n_frag = 0; dp->blk_ofs = obj->c_ofs; res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ if (res == FR_OK) { res = load_xdir(dp); /* Load the object's entry block */ } return res; } #endif #if !FF_FS_READONLY /*----------------------------------------*/ /* exFAT: Store the directory entry block */ /*----------------------------------------*/ static FRESULT store_xdir ( DIR* dp /* Pointer to the direcotry object */ ) { FRESULT res; UINT nent; BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */ /* Create set sum */ st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); nent = dirb[XDIR_NumSec] + 1; /* Store the direcotry entry block to the directory */ res = dir_sdi(dp, dp->blk_ofs); while (res == FR_OK) { res = move_window(dp->obj.fs, dp->sect); if (res != FR_OK) break; mem_cpy(dp->dir, dirb, SZDIRE); dp->obj.fs->wflag = 1; if (--nent == 0) break; dirb += SZDIRE; res = dir_next(dp, 0); } return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR; } /*-------------------------------------------*/ /* exFAT: Create a new directory enrty block */ /*-------------------------------------------*/ static void create_xdir ( BYTE* dirb, /* Pointer to the direcotry entry block buffer */ const WCHAR* lfn /* Pointer to the object name */ ) { UINT i; BYTE nc1, nlen; WCHAR wc; /* Create file-directory and stream-extension entry */ mem_set(dirb, 0, 2 * SZDIRE); dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR; dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM; /* Create file-name entries */ i = SZDIRE * 2; /* Top of file_name entries */ nlen = nc1 = 0; wc = 1; do { dirb[i++] = ET_FILENAME; dirb[i++] = 0; do { /* Fill name field */ if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */ st_word(dirb + i, wc); /* Store it */ i += 2; } while (i % SZDIRE != 0); nc1++; } while (lfn[nlen]); /* Fill next entry if any char follows */ dirb[XDIR_NumName] = nlen; /* Set name length */ dirb[XDIR_NumSec] = 1 + nc1; /* Set secondary count (C0 + C1s) */ st_word(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ } #endif /* !FF_FS_READONLY */ #endif /* FF_FS_EXFAT */ #if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT /*-----------------------------------------------------------------------*/ /* Read an object from the directory */ /*-----------------------------------------------------------------------*/ #define DIR_READ_FILE(dp) dir_read(dp, 0) #define DIR_READ_LABEL(dp) dir_read(dp, 1) static FRESULT dir_read ( DIR* dp, /* Pointer to the directory object */ int vol /* Filtered by 0:file/directory or 1:volume label */ ) { FRESULT res = FR_NO_FILE; FATFS *fs = dp->obj.fs; BYTE attr, b; #if FF_USE_LFN BYTE ord = 0xFF, sum = 0xFF; #endif while (dp->sect) { res = move_window(fs, dp->sect); if (res != FR_OK) break; b = dp->dir[DIR_Name]; /* Test for the entry type */ if (b == 0) { res = FR_NO_FILE; break; /* Reached to end of the directory */ } #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ if (FF_USE_LABEL && vol) { if (b == ET_VLABEL) break; /* Volume label entry? */ } else { if (b == ET_FILEDIR) { /* Start of the file entry block? */ dp->blk_ofs = dp->dptr; /* Get location of the block */ res = load_xdir(dp); /* Load the entry block */ if (res == FR_OK) { dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK; /* Get attribute */ } break; } } } else #endif { /* On the FAT/FAT32 volume */ dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ #if FF_USE_LFN /* LFN configuration */ if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ ord = 0xFF; } else { if (attr == AM_LFN) { /* An LFN entry is found */ if (b & LLEF) { /* Is it start of an LFN sequence? */ sum = dp->dir[LDIR_Chksum]; b &= (BYTE)~LLEF; ord = b; dp->blk_ofs = dp->dptr; } /* Check LFN validity and capture it */ ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; } else { /* An SFN entry is found */ if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */ dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */ } break; } } #else /* Non LFN configuration */ if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */ break; } #endif } res = dir_next(dp, 0); /* Next entry */ if (res != FR_OK) break; } if (res != FR_OK) dp->sect = 0; /* Terminate the read operation on error or EOT */ return res; } #endif /* FF_FS_MINIMIZE <= 1 || FF_USE_LABEL || FF_FS_RPATH >= 2 */ /*-----------------------------------------------------------------------*/ /* Directory handling - Find an object in the directory */ /*-----------------------------------------------------------------------*/ static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ DIR* dp /* Pointer to the directory object with the file name */ ) { FRESULT res; FATFS *fs = dp->obj.fs; BYTE c; #if FF_USE_LFN BYTE a, ord, sum; #endif res = dir_sdi(dp, 0); /* Rewind directory object */ if (res != FR_OK) return res; #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ BYTE nc; UINT di, ni; WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */ #if FF_MAX_LFN < 255 if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */ #endif if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare the name */ if ((di % SZDIRE) == 0) di += 2; if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; } if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */ } return res; } #endif /* On the FAT/FAT32 volume */ #if FF_USE_LFN ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ #endif do { res = move_window(fs, dp->sect); if (res != FR_OK) break; c = dp->dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ #if FF_USE_LFN /* LFN configuration */ dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ } else { if (a == AM_LFN) { /* An LFN entry is found */ if (!(dp->fn[NSFLAG] & NS_NOLFN)) { if (c & LLEF) { /* Is it start of LFN sequence? */ sum = dp->dir[LDIR_Chksum]; c &= (BYTE)~LLEF; ord = c; /* LFN start order */ dp->blk_ofs = dp->dptr; /* Start offset of LFN */ } /* Check validity of the LFN entry and compare it with given name */ ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; } } else { /* An SFN entry is found */ if (ord == 0 && sum == sum_sfn(dp->dir)) break; /* LFN matched? */ if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */ ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ } } #else /* Non LFN configuration */ dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK; if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */ #endif res = dir_next(dp, 0); /* Next entry */ } while (res == FR_OK); return res; } #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Register an object to the directory */ /*-----------------------------------------------------------------------*/ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ DIR* dp /* Target directory with object name to be created */ ) { FRESULT res; FATFS *fs = dp->obj.fs; #if FF_USE_LFN /* LFN configuration */ UINT n, nlen, nent; BYTE sn[12], sum; if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */ for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ res = dir_alloc(dp, nent); /* Allocate directory entries */ if (res != FR_OK) return res; dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */ if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */ dp->obj.stat &= ~4; res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */ if (res != FR_OK) return res; res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */ if (res != FR_OK) return res; if (dp->obj.sclust != 0) { /* Is it a sub-directory? */ DIR dj; res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */ if (res != FR_OK) return res; dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */ st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; res = store_xdir(&dj); /* Store the object status */ if (res != FR_OK) return res; } } create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ return FR_OK; } #endif /* On the FAT/FAT32 volume */ mem_cpy(sn, dp->fn, 12); if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ for (n = 1; n < 100; n++) { gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */ res = dir_find(dp); /* Check if the name collides with existing SFN */ if (res != FR_OK) break; } if (n == 100) return FR_DENIED; /* Abort if too many collisions */ if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ dp->fn[NSFLAG] = sn[NSFLAG]; } /* Create an SFN with/without LFNs. */ nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1; /* Number of entries to allocate */ res = dir_alloc(dp, nent); /* Allocate entries */ if (res == FR_OK && --nent) { /* Set LFN entry if needed */ res = dir_sdi(dp, dp->dptr - nent * SZDIRE); if (res == FR_OK) { sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */ do { /* Store LFN entries in bottom first */ res = move_window(fs, dp->sect); if (res != FR_OK) break; put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum); fs->wflag = 1; res = dir_next(dp, 0); /* Next entry */ } while (res == FR_OK && --nent); } } #else /* Non LFN configuration */ res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ #endif /* Set SFN entry */ if (res == FR_OK) { res = move_window(fs, dp->sect); if (res == FR_OK) { mem_set(dp->dir, 0, SZDIRE); /* Clean the entry */ mem_cpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */ #if FF_USE_LFN dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */ #endif fs->wflag = 1; } } return res; } #endif /* !FF_FS_READONLY */ #if !FF_FS_READONLY && FF_FS_MINIMIZE == 0 /*-----------------------------------------------------------------------*/ /* Remove an object from the directory */ /*-----------------------------------------------------------------------*/ static FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ DIR* dp /* Directory object pointing the entry to be removed */ ) { FRESULT res; FATFS *fs = dp->obj.fs; #if FF_USE_LFN /* LFN configuration */ DWORD last = dp->dptr; res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs); /* Goto top of the entry block if LFN is exist */ if (res == FR_OK) { do { res = move_window(fs, dp->sect); if (res != FR_OK) break; if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ dp->dir[XDIR_Type] &= 0x7F; /* Clear the entry InUse flag. */ } else { /* On the FAT/FAT32 volume */ dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'. */ } fs->wflag = 1; if (dp->dptr >= last) break; /* If reached last entry then all entries of the object has been deleted. */ res = dir_next(dp, 0); /* Next entry */ } while (res == FR_OK); if (res == FR_NO_FILE) res = FR_INT_ERR; } #else /* Non LFN configuration */ res = move_window(fs, dp->sect); if (res == FR_OK) { dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'.*/ fs->wflag = 1; } #endif return res; } #endif /* !FF_FS_READONLY && FF_FS_MINIMIZE == 0 */ #if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 /*-----------------------------------------------------------------------*/ /* Get file information from directory entry */ /*-----------------------------------------------------------------------*/ static void get_fileinfo ( DIR* dp, /* Pointer to the directory object */ FILINFO* fno /* Pointer to the file information to be filled */ ) { UINT si, di; #if FF_USE_LFN BYTE lcf; WCHAR wc, hs; FATFS *fs = dp->obj.fs; #else TCHAR c; #endif fno->fname[0] = 0; /* Invaidate file info */ if (dp->sect == 0) return; /* Exit if read pointer has reached end of directory */ #if FF_USE_LFN /* LFN configuration */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ get_xfileinfo(fs->dirbuf, fno); return; } else #endif { /* On the FAT/FAT32 volume */ if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */ si = di = hs = 0; while (fs->lfnbuf[si] != 0) { wc = fs->lfnbuf[si++]; /* Get an LFN character (UTF-16) */ if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ hs = wc; continue; /* Get low surrogate */ } wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in UTF-16 or UTF-8 encoding */ if (wc == 0) { di = 0; break; } /* Invalid char or buffer overflow? */ di += wc; hs = 0; } if (hs != 0) di = 0; /* Broken surrogate pair? */ fno->fname[di] = 0; /* Terminate the LFN (null string means LFN is invalid) */ } } si = di = 0; while (si < 11) { /* Get SFN from SFN entry */ wc = dp->dir[si++]; /* Get a char */ if (wc == ' ') continue; /* Skip padding spaces */ if (wc == RDDEM) wc = DDEM; /* Restore replaced DDEM character */ if (si == 9 && di < FF_SFN_BUF) fno->altname[di++] = '.'; /* Insert a . if extension is exist */ #if FF_LFN_UNICODE >= 1 /* Unicode output */ if (dbc_1st((BYTE)wc) && si != 8 && si != 11 && dbc_2nd(dp->dir[si])) { /* Make a DBC if needed */ wc = wc << 8 | dp->dir[si++]; } wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */ if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */ wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in Unicode */ if (wc == 0) { di = 0; break; } /* Buffer overflow? */ di += wc; #else /* ANSI/OEM output */ fno->altname[di++] = (TCHAR)wc; /* Store it without any conversion */ #endif } fno->altname[di] = 0; /* Terminate the SFN (null string means SFN is invalid) */ if (fno->fname[0] == 0) { /* If LFN is invalid, altname[] needs to be copied to fname[] */ if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */ fno->fname[di++] = '?'; } else { for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */ wc = (WCHAR)fno->altname[si]; if (wc == '.') lcf = NS_EXT; if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20; fno->fname[di] = (TCHAR)wc; } } fno->fname[di] = 0; /* Terminate the LFN */ if (!dp->dir[DIR_NTres]) fno->altname[0] = 0; /* Altname is not needed if neither LFN nor case info is exist. */ } #else /* Non-LFN configuration */ si = di = 0; while (si < 11) { /* Copy name body and extension */ c = (TCHAR)dp->dir[si++]; if (c == ' ') continue; /* Skip padding spaces */ if (c == RDDEM) c = DDEM; /* Restore replaced DDEM character */ if (si == 9) fno->fname[di++] = '.';/* Insert a . if extension is exist */ fno->fname[di++] = c; } fno->fname[di] = 0; #endif fno->fattrib = dp->dir[DIR_Attr]; /* Attribute */ fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */ fno->ftime = ld_word(dp->dir + DIR_ModTime + 0); /* Time */ fno->fdate = ld_word(dp->dir + DIR_ModTime + 2); /* Date */ } #endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ #if FF_USE_FIND && FF_FS_MINIMIZE <= 1 /*-----------------------------------------------------------------------*/ /* Pattern matching */ /*-----------------------------------------------------------------------*/ static DWORD get_achar ( /* Get a character and advances ptr */ const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ ) { DWORD chr; #if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode input */ chr = tchar2uni(ptr); if (chr == 0xFFFFFFFF) chr = 0; /* Wrong UTF encoding is recognized as end of the string */ chr = ff_wtoupper(chr); #else /* ANSI/OEM input */ chr = (BYTE)*(*ptr)++; /* Get a byte */ if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */ #if FF_CODE_PAGE == 0 if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ #elif FF_CODE_PAGE < 900 if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ #endif #if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900 if (dbc_1st((BYTE)chr)) { /* Get DBC 2nd byte if needed */ chr = dbc_2nd((BYTE)**ptr) ? chr << 8 | (BYTE)*(*ptr)++ : 0; } #endif #endif return chr; } static int pattern_matching ( /* 0:not matched, 1:matched */ const TCHAR* pat, /* Matching pattern */ const TCHAR* nam, /* String to be tested */ int skip, /* Number of pre-skip chars (number of ?s) */ int inf /* Infinite search (* specified) */ ) { const TCHAR *pp, *np; DWORD pc, nc; int nm, nx; while (skip--) { /* Pre-skip name chars */ if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */ } if (*pat == 0 && inf) return 1; /* (short circuit) */ do { pp = pat; np = nam; /* Top of pattern and name to match */ for (;;) { if (*pp == '?' || *pp == '*') { /* Wildcard? */ nm = nx = 0; do { /* Analyze the wildcard block */ if (*pp++ == '?') nm++; else nx = 1; } while (*pp == '?' || *pp == '*'); if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */ nc = *np; break; /* Branch mismatched */ } pc = get_achar(&pp); /* Get a pattern char */ nc = get_achar(&np); /* Get a name char */ if (pc != nc) break; /* Branch mismatched? */ if (pc == 0) return 1; /* Branch matched? (matched at end of both strings) */ } get_achar(&nam); /* nam++ */ } while (inf && nc); /* Retry until end of name if infinite search is specified */ return 0; } #endif /* FF_USE_FIND && FF_FS_MINIMIZE <= 1 */ /*-----------------------------------------------------------------------*/ /* Pick a top segment and create the object name in directory form */ /*-----------------------------------------------------------------------*/ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ DIR* dp, /* Pointer to the directory object */ const TCHAR** path /* Pointer to pointer to the segment in the path string */ ) { #if FF_USE_LFN /* LFN configuration */ BYTE b, cf; WCHAR wc, *lfn; DWORD uc; UINT i, ni, si, di; const TCHAR *p; /* Create LFN into LFN working buffer */ p = *path; lfn = dp->obj.fs->lfnbuf; di = 0; for (;;) { uc = tchar2uni(&p); /* Get a character */ if (uc == 0xFFFFFFFF) return FR_INVALID_NAME; /* Invalid code or UTF decode error */ if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16); /* Store high surrogate if needed */ wc = (WCHAR)uc; if (wc < ' ' || wc == '/' || wc == '\\') break; /* Break if end of the path or a separator is found */ if (wc < 0x80 && chk_chr("\"*:<>\?|\x7F", wc)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */ if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */ lfn[di++] = wc; /* Store the Unicode character */ } while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */ *path = p; /* Return pointer to the next segment */ cf = (wc < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ #if FF_FS_RPATH != 0 if ((di == 1 && lfn[di - 1] == '.') || (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */ lfn[di] = 0; for (i = 0; i < 11; i++) { /* Create dot name for SFN entry */ dp->fn[i] = (i < di) ? '.' : ' '; } dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ return FR_OK; } #endif while (di) { /* Snip off trailing spaces and dots if exist */ wc = lfn[di - 1]; if (wc != ' ' && wc != '.') break; di--; } lfn[di] = 0; /* LFN is created into the working buffer */ if (di == 0) return FR_INVALID_NAME; /* Reject null name */ /* Create SFN in directory form */ for (si = 0; lfn[si] == ' '; si++) ; /* Remove leading spaces */ if (si > 0 || lfn[si] == '.') cf |= NS_LOSS | NS_LFN; /* Is there any leading space or dot? */ while (di > 0 && lfn[di - 1] != '.') di--; /* Find last dot (di<=si: no extension) */ mem_set(dp->fn, ' ', 11); i = b = 0; ni = 8; for (;;) { wc = lfn[si++]; /* Get an LFN character */ if (wc == 0) break; /* Break on end of the LFN */ if (wc == ' ' || (wc == '.' && si != di)) { /* Remove embedded spaces and dots */ cf |= NS_LOSS | NS_LFN; continue; } if (i >= ni || si == di) { /* End of field? */ if (ni == 11) { /* Name extension overflow? */ cf |= NS_LOSS | NS_LFN; break; } if (si != di) cf |= NS_LOSS | NS_LFN; /* Name body overflow? */ if (si > di) break; /* No name extension? */ si = di; i = 8; ni = 11; b <<= 2; /* Enter name extension */ continue; } if (wc >= 0x80) { /* Is this a non-ASCII character? */ cf |= NS_LFN; /* LFN entry needs to be created */ #if FF_CODE_PAGE == 0 if (ExCvt) { /* At SBCS */ wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ } else { /* At DBCS */ wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ } #elif FF_CODE_PAGE < 900 /* SBCS cfg */ wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ #else /* DBCS cfg */ wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ #endif } if (wc >= 0x100) { /* Is this a DBC? */ if (i >= ni - 1) { /* Field overflow? */ cf |= NS_LOSS | NS_LFN; i = ni; continue; /* Next field */ } dp->fn[i++] = (BYTE)(wc >> 8); /* Put 1st byte */ } else { /* SBC */ if (wc == 0 || chk_chr("+,;=[]", wc)) { /* Replace illegal characters for SFN if needed */ wc = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ } else { if (IsUpper(wc)) { /* ASCII upper case? */ b |= 2; } if (IsLower(wc)) { /* ASCII lower case? */ b |= 1; wc -= 0x20; } } } dp->fn[i++] = (BYTE)wc; } if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ if (ni == 8) b <<= 2; /* Shift capital flags if no extension */ if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; /* LFN entry needs to be created if composite capitals */ if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */ if (b & 0x01) cf |= NS_EXT; /* NT flag (Extension has small capital letters only) */ if (b & 0x04) cf |= NS_BODY; /* NT flag (Body has small capital letters only) */ } dp->fn[NSFLAG] = cf; /* SFN is created into dp->fn[] */ return FR_OK; #else /* FF_USE_LFN : Non-LFN configuration */ BYTE c, d, *sfn; UINT ni, si, i; const char *p; /* Create file name in directory form */ p = *path; sfn = dp->fn; mem_set(sfn, ' ', 11); si = i = 0; ni = 8; #if FF_FS_RPATH != 0 if (p[si] == '.') { /* Is this a dot entry? */ for (;;) { c = (BYTE)p[si++]; if (c != '.' || si >= 3) break; sfn[i++] = c; } if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; *path = p + si; /* Return pointer to the next segment */ sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */ return FR_OK; } #endif for (;;) { c = (BYTE)p[si++]; /* Get a byte */ if (c <= ' ') break; /* Break if end of the path name */ if (c == '/' || c == '\\') { /* Break if a separator is found */ while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */ break; } if (c == '.' || i >= ni) { /* End of body or field overflow? */ if (ni == 11 || c != '.') return FR_INVALID_NAME; /* Field overflow or invalid dot? */ i = 8; ni = 11; /* Enter file extension field */ continue; } #if FF_CODE_PAGE == 0 if (ExCvt && c >= 0x80) { /* Is SBC extended character? */ c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ } #elif FF_CODE_PAGE < 900 if (c >= 0x80) { /* Is SBC extended character? */ c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ } #endif if (dbc_1st(c)) { /* Check if it is a DBC 1st byte */ d = (BYTE)p[si++]; /* Get 2nd byte */ if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */ sfn[i++] = c; sfn[i++] = d; } else { /* SBC */ if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */ if (IsLower(c)) c -= 0x20; /* To upper */ sfn[i++] = c; } } *path = p + si; /* Return pointer to the next segment */ if (i == 0) return FR_INVALID_NAME; /* Reject nul string */ if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ return FR_OK; #endif /* FF_USE_LFN */ } /*-----------------------------------------------------------------------*/ /* Follow a file path */ /*-----------------------------------------------------------------------*/ static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ DIR* dp, /* Directory object to return last directory and found object */ const TCHAR* path /* Full-path string to find a file or directory */ ) { FRESULT res; BYTE ns; FATFS *fs = dp->obj.fs; #if FF_FS_RPATH != 0 if (*path != '/' && *path != '\\') { /* Without heading separator */ dp->obj.sclust = fs->cdir; /* Start from current directory */ } else #endif { /* With heading separator */ while (*path == '/' || *path == '\\') path++; /* Strip heading separator */ dp->obj.sclust = 0; /* Start from root directory */ } #if FF_FS_EXFAT dp->obj.n_frag = 0; /* Invalidate last fragment counter of the object */ #if FF_FS_RPATH != 0 if (fs->fs_type == FS_EXFAT && dp->obj.sclust) { /* exFAT: Retrieve the sub-directory's status */ DIR dj; dp->obj.c_scl = fs->cdc_scl; dp->obj.c_size = fs->cdc_size; dp->obj.c_ofs = fs->cdc_ofs; res = load_obj_xdir(&dj, &dp->obj); if (res != FR_OK) return res; dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize); dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; } #endif #endif if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */ dp->fn[NSFLAG] = NS_NONAME; res = dir_sdi(dp, 0); } else { /* Follow path */ for (;;) { res = create_name(dp, &path); /* Get a segment name of the path */ if (res != FR_OK) break; res = dir_find(dp); /* Find an object with the segment name */ ns = dp->fn[NSFLAG]; if (res != FR_OK) { /* Failed to find the object */ if (res == FR_NO_FILE) { /* Object is not found */ if (FF_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, stay there */ if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ dp->fn[NSFLAG] = NS_NONAME; res = FR_OK; } else { /* Could not find the object */ if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ } } break; } if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ /* Get into the sub-directory */ if (!(dp->obj.attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */ res = FR_NO_PATH; break; } #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* Save containing directory information for next dir */ dp->obj.c_scl = dp->obj.sclust; dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; dp->obj.c_ofs = dp->blk_ofs; init_alloc_info(fs, &dp->obj); /* Open next directory */ } else #endif { dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs)); /* Open next directory */ } } } return res; } /*-----------------------------------------------------------------------*/ /* Load a sector and check if it is an FAT VBR */ /*-----------------------------------------------------------------------*/ static BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ FATFS* fs, /* Filesystem object */ DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ ) { fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */ if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always here regardless of the sector size) */ #if FF_FS_EXFAT if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* Check if exFAT VBR */ #endif if (fs->win[BS_JmpBoot] == 0xE9 || fs->win[BS_JmpBoot] == 0xEB || fs->win[BS_JmpBoot] == 0xE8) { /* Valid JumpBoot code? */ if (!mem_cmp(fs->win + BS_FilSysType, "FAT", 3)) return 0; /* Is it an FAT VBR? */ if (!mem_cmp(fs->win + BS_FilSysType32, "FAT32", 5)) return 0; /* Is it an FAT32 VBR? */ } return 2; /* Valid BS but not FAT */ } /*-----------------------------------------------------------------------*/ /* Determine logical drive number and mount the volume if needed */ /*-----------------------------------------------------------------------*/ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */ FATFS *fs, /* Pointer to the file system object */ BYTE mode /* !=0: Check write protection for write access */ ) { BYTE fmt, *pt; DSTATUS stat; DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; WORD nrsv; UINT i; #if FF_FS_REENTRANT if (!lock_fs(fs)) return FR_TIMEOUT; /* Lock the volume */ #endif mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ if (fs->fs_type != 0) { /* If the volume has been mounted */ disk_ioctl(fs->drv, IOCTL_STATUS, &stat); if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ return FR_WRITE_PROTECTED; } return FR_OK; /* The filesystem object is valid */ } } /* The filesystem object is not valid. */ /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */ fs->fs_type = 0; /* Clear the filesystem object */ disk_ioctl(fs->drv, IOCTL_INIT, &stat); /* Initialize the physical drive */ if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ } if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */ return FR_WRITE_PROTECTED; } #if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; #endif /* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */ bsect = 0; fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */ if (fmt == 2 || (fmt < 2 && LD2PT(fs) != 0)) { /* Not an FAT-VBR or forced partition number */ for (i = 0; i < 4; i++) { /* Get partition offset */ pt = fs->win + (MBR_Table + i * SZ_PTE); br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0; } i = LD2PT(fs); /* Partition number: 0:auto, 1-4:forced */ if (i != 0) i--; do { /* Find an FAT volume */ bsect = br[i]; fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ } while (LD2PT(fs) == 0 && fmt >= 2 && ++i < 4); } if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ /* An FAT volume is found (bsect). Following code initializes the filesystem object */ #if FF_FS_EXFAT if (fmt == 1) { QWORD maxlba; DWORD so, cv, bcl; for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ return FR_NO_FILESYSTEM; } maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */ if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */ fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */ nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ fs->n_fatent = nclst + 2; /* Boundaries and Limits */ fs->volbase = bsect; fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); /* Get bitmap location and check if it is contiguous (implementation assumption) */ so = i = 0; for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */ if (i == 0) { if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */ if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) return FR_DISK_ERR; so++; } if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */ i = (i + SZDIRE) % SS(fs); /* Next entry */ } bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */ if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM; fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */ for (;;) { /* Check if bitmap is contiguous */ if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR; cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4); if (cv == 0xFFFFFFFF) break; /* Last link? */ if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented? */ } #if !FF_FS_READONLY fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ #endif fmt = FS_EXFAT; /* FAT sub-type */ } else #endif /* FF_FS_EXFAT */ { if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); fs->fsize = fasize; fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ fasize *= fs->n_fats; /* Number of sectors for FAT area */ fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ /* Determine the FAT sub type */ sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */ if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ fmt = 0; if (nclst <= MAX_FAT32) fmt = FS_FAT32; if (nclst <= MAX_FAT16) fmt = FS_FAT16; if (nclst <= MAX_FAT12) fmt = FS_FAT12; if (fmt == 0) return FR_NO_FILESYSTEM; /* Boundaries and Limits */ fs->n_fatent = nclst + 2; /* Number of FAT entries */ fs->volbase = bsect; /* Volume start sector */ fs->fatbase = bsect + nrsv; /* FAT start sector */ fs->database = bsect + sysect; /* Data start sector */ if (fmt == FS_FAT32) { if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ } else { if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); } if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */ #if !FF_FS_READONLY /* Get FSInfo if available */ fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ fs->fsi_flag = 0x80; #if (FF_FS_NOFSINFO & 3) != 3 if (fmt == FS_FAT32 /* Allow to update FSInfo only if BPB_FSInfo32 == 1 */ && ld_word(fs->win + BPB_FSInfo32) == 1 && move_window(fs, bsect + 1) == FR_OK) { fs->fsi_flag = 0; if (ld_word(fs->win + BS_55AA) == 0xAA55 /* Load FSInfo data if available */ && ld_dword(fs->win + FSI_LeadSig) == 0x41615252 && ld_dword(fs->win + FSI_StrucSig) == 0x61417272) { #if (FF_FS_NOFSINFO & 1) == 0 fs->free_clst = ld_dword(fs->win + FSI_Free_Count); #endif #if (FF_FS_NOFSINFO & 2) == 0 fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free); #endif } } #endif /* (FF_FS_NOFSINFO & 3) != 3 */ #endif /* !FF_FS_READONLY */ } fs->fs_type = fmt; /* FAT sub-type */ fs->id = ++Fsid; /* Volume mount ID */ #if FF_USE_LFN == 1 fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ #if FF_FS_EXFAT fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */ #endif #endif #if FF_FS_RPATH != 0 fs->cdir = 0; /* Initialize current directory */ #endif #if FF_FS_LOCK != 0 /* Clear file lock semaphores */ clear_lock(fs); #endif return FR_OK; } /*-----------------------------------------------------------------------*/ /* Check if the file/directory object is valid or not */ /*-----------------------------------------------------------------------*/ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ ) { FRESULT res = FR_INVALID_OBJECT; DSTATUS stat; if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */ #if FF_FS_REENTRANT if (lock_fs(obj->fs)) { /* Obtain the filesystem object */ if (disk_ioctl(obj->fs->drv, IOCTL_STATUS, &stat) == RES_OK && !(stat & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ res = FR_OK; } else { unlock_fs(obj->fs, FR_OK); } } else { res = FR_TIMEOUT; } #else if (disk_ioctl(obj->fs->drv, IOCTL_STATUS, &stat) == RES_OK && !(stat & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ res = FR_OK; } #endif } *rfs = (res == FR_OK) ? obj->fs : 0; /* Corresponding filesystem object */ return res; } /*--------------------------------------------------------------------------- Public Functions (FatFs API) ----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ /* Mount/Unmount a Logical Drive */ /*-----------------------------------------------------------------------*/ FRESULT f_mount ( FATFS* fs /* Pointer to the file system object to mount */ ) { FRESULT res; fs->fs_type = 0; /* Clear new fs object */ #if FF_FS_REENTRANT /* Create sync object for the new volume */ if (!ff_cre_syncobj(fs, &fs->sobj)) return FR_INT_ERR; #endif res = find_volume(fs, 0); /* Force mounted the volume */ LEAVE_FF(fs, res); } FRESULT f_umount ( FATFS* fs /* Pointer to the file system object to unmount */ ) { #if FF_FS_LOCK clear_lock(fs); #endif #if FF_FS_REENTRANT /* Discard sync object of the current volume */ if (!ff_del_syncobj(fs->sobj)) return FR_INT_ERR; #endif fs->fs_type = 0; /* Clear old fs object */ return FR_OK; } /*-----------------------------------------------------------------------*/ /* Open or Create a File */ /*-----------------------------------------------------------------------*/ FRESULT f_open ( FATFS *fs, FIL* fp, /* Pointer to the blank file object */ const TCHAR* path, /* Pointer to the file name */ BYTE mode /* Access mode and file open mode flags */ ) { FRESULT res; DIR dj; #if !FF_FS_READONLY DWORD dw, cl, bcs, clst, sc; FSIZE_t ofs; #endif DEF_NAMBUF if (!fp) return FR_INVALID_OBJECT; /* Get logical drive number */ mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND; res = find_volume(fs, mode); if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); res = follow_path(&dj, path); /* Follow the file path */ #if !FF_FS_READONLY /* Read/Write configuration */ if (res == FR_OK) { if (dj.fn[NSFLAG] & NS_NONAME) { /* Origin directory itself? */ res = FR_INVALID_NAME; } #if FF_FS_LOCK != 0 else { res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */ } #endif } /* Create or Open a file */ if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { if (res != FR_OK) { /* No file, create new */ if (res == FR_NO_FILE) { /* There is no file to open, create a new entry */ #if FF_FS_LOCK != 0 res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; #else res = dir_register(&dj); #endif } mode |= FA_CREATE_ALWAYS; /* File is created */ } else { /* Any object with the same name is already existing */ if (dj.obj.attr & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ res = FR_DENIED; } else { if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */ } } if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate the file if overwrite mode */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* Get current allocation info */ fp->obj.fs = fs; init_alloc_info(fs, &fp->obj); /* Set directory entry block initial state */ mem_set(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */ mem_set(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */ fs->dirbuf[XDIR_Attr] = AM_ARC; st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME()); fs->dirbuf[XDIR_GenFlags] = 1; res = store_xdir(&dj); if (res == FR_OK && fp->obj.sclust != 0) { /* Remove the cluster chain if exist */ res = remove_chain(&fp->obj, fp->obj.sclust, 0); fs->last_clst = fp->obj.sclust - 1; /* Reuse the cluster hole */ } } else #endif { /* Set directory entry initial state */ cl = ld_clust(fs, dj.dir); /* Get current cluster chain */ st_dword(dj.dir + DIR_CrtTime, GET_FATTIME()); /* Set created time */ dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */ st_clust(fs, dj.dir, 0); /* Reset file allocation info */ st_dword(dj.dir + DIR_FileSize, 0); fs->wflag = 1; if (cl != 0) { /* Remove the cluster chain if exist */ dw = fs->winsect; res = remove_chain(&dj.obj, cl, 0); if (res == FR_OK) { res = move_window(fs, dw); fs->last_clst = cl - 1; /* Reuse the cluster hole */ } } } } } else { /* Open an existing file */ if (res == FR_OK) { /* Is the object exsiting? */ if (dj.obj.attr & AM_DIR) { /* File open against a directory */ res = FR_NO_FILE; } else { if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */ res = FR_DENIED; } } } } if (res == FR_OK) { if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED; /* Set file change flag if created or overwritten */ fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ fp->dir_ptr = dj.dir; #if FF_FS_LOCK != 0 fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */ if (fp->obj.lockid == 0) res = FR_INT_ERR; #endif } #else /* R/O configuration */ if (res == FR_OK) { if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it origin directory itself? */ res = FR_INVALID_NAME; } else { if (dj.obj.attr & AM_DIR) { /* Is it a directory? */ res = FR_NO_FILE; } } } #endif if (res == FR_OK) { #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { fp->obj.c_scl = dj.obj.sclust; /* Get containing directory info */ fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; fp->obj.c_ofs = dj.blk_ofs; init_alloc_info(fs, &fp->obj); } else #endif { fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */ fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize); } #if FF_USE_FASTSEEK fp->cltbl = 0; /* Disable fast seek mode */ #endif fp->obj.fs = fs; /* Validate the file object */ fp->obj.id = fs->id; fp->flag = mode; /* Set file access mode */ fp->err = 0; /* Clear error flag */ fp->sect = 0; /* Invalidate current data sector */ fp->fptr = 0; /* Set file pointer top of the file */ #if !FF_FS_READONLY #if !FF_FS_TINY mem_set(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */ #endif if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */ fp->fptr = fp->obj.objsize; /* Offset to seek */ bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */ clst = fp->obj.sclust; /* Follow the cluster chain */ for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) { clst = get_fat(&fp->obj, clst); if (clst <= 1) res = FR_INT_ERR; if (clst == 0xFFFFFFFF) res = FR_DISK_ERR; } fp->clust = clst; if (res == FR_OK && ofs % SS(fs)) { /* Fill sector buffer if not on the sector boundary */ if ((sc = clst2sect(fs, clst)) == 0) { res = FR_INT_ERR; } else { fp->sect = sc + (DWORD)(ofs / SS(fs)); #if !FF_FS_TINY if (disk_read(fs->drv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; #endif } } } #endif } FREE_NAMBUF(); } if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */ LEAVE_FF(fs, res); } /*-----------------------------------------------------------------------*/ /* Read File */ /*-----------------------------------------------------------------------*/ FRESULT f_read ( FIL* fp, /* Pointer to the file object */ void* buff, /* Pointer to data buffer */ UINT btr, /* Number of bytes to read */ UINT* br /* Pointer to number of bytes read */ ) { FRESULT res; FATFS *fs; DWORD clst, sect; FSIZE_t remain; UINT rcnt, cc, csect; BYTE *rbuff = (BYTE*)buff; *br = 0; /* Clear read byte counter */ res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ remain = fp->obj.objsize - fp->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ for ( ; btr; /* Repeat until btr bytes read */ btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ if (csect == 0) { /* On the cluster boundary? */ if (fp->fptr == 0) { /* On the top of the file? */ clst = fp->obj.sclust; /* Follow cluster chain from the origin */ } else { /* Middle or end of the file */ #if FF_USE_FASTSEEK if (fp->cltbl) { clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ } else #endif { clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */ } } if (clst < 2) ABORT(fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); fp->clust = clst; /* Update current cluster */ } sect = clst2sect(fs, fp->clust); /* Get current sector */ if (sect == 0) ABORT(fs, FR_INT_ERR); sect += csect; cc = btr / SS(fs); /* When remaining bytes >= sector size, */ if (cc > 0) { /* Read maximum contiguous sectors directly */ if (csect + cc > fs->csize) { /* Clip at cluster boundary */ cc = fs->csize - csect; } if (disk_read(fs->drv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); #if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if FF_FS_TINY if (fs->wflag && fs->winsect - sect < cc) { mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs)); } #else if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) { mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs)); } #endif #endif rcnt = SS(fs) * cc; /* Number of bytes transferred */ continue; } #if !FF_FS_TINY if (fp->sect != sect) { /* Load data sector if not in cache */ #if !FF_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ } #endif fp->sect = sect; } rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */ #if FF_FS_TINY if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ #else mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ #endif } LEAVE_FF(fs, FR_OK); } #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Write File */ /*-----------------------------------------------------------------------*/ FRESULT f_write ( FIL* fp, /* Pointer to the file object */ const void* buff, /* Pointer to the data to be written */ UINT btw, /* Number of bytes to write */ UINT* bw /* Pointer to number of bytes written */ ) { FRESULT res; FATFS *fs; DWORD clst, sect; UINT wcnt, cc, csect; const BYTE *wbuff = (const BYTE*)buff; *bw = 0; /* Clear write byte counter */ res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); } for ( ; btw; /* Repeat until all data written */ btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) { if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */ if (csect == 0) { /* On the cluster boundary? */ if (fp->fptr == 0) { /* On the top of the file? */ clst = fp->obj.sclust; /* Follow from the origin */ if (clst == 0) { /* If no cluster is allocated, */ clst = create_chain(&fp->obj, 0); /* create a new cluster chain */ } } else { /* On the middle or end of the file */ #if FF_USE_FASTSEEK if (fp->cltbl) { clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ } else #endif { clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */ } } if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ if (clst == 1) ABORT(fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); fp->clust = clst; /* Update current cluster */ if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */ } #if FF_FS_TINY if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ #else if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif sect = clst2sect(fs, fp->clust); /* Get current sector */ if (sect == 0) ABORT(fs, FR_INT_ERR); sect += csect; cc = btw / SS(fs); /* When remaining bytes >= sector size, */ if (cc > 0) { /* Write maximum contiguous sectors directly */ if (csect + cc > fs->csize) { /* Clip at cluster boundary */ cc = fs->csize - csect; } if (disk_write(fs->drv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); #if FF_FS_MINIMIZE <= 2 #if FF_FS_TINY if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs)); fs->wflag = 0; } #else if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); fp->flag &= (BYTE)~FA_DIRTY; } #endif #endif wcnt = SS(fs) * cc; /* Number of bytes transferred */ continue; } #if FF_FS_TINY if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */ if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); fs->winsect = sect; } #else if (fp->sect != sect && /* Fill sector cache with file data */ fp->fptr < fp->obj.objsize && disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) { ABORT(fs, FR_DISK_ERR); } #endif fp->sect = sect; } wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */ #if FF_FS_TINY if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ fs->wflag = 1; #else mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ fp->flag |= FA_DIRTY; #endif } fp->flag |= FA_MODIFIED; /* Set file change flag */ LEAVE_FF(fs, FR_OK); } /*-----------------------------------------------------------------------*/ /* Synchronize the File */ /*-----------------------------------------------------------------------*/ FRESULT f_sync ( FIL* fp /* Pointer to the file object */ ) { FRESULT res; FATFS *fs; DWORD tm; BYTE *dir; res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res == FR_OK) { if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ #if !FF_FS_TINY if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif /* Update the directory entry */ tm = GET_FATTIME(); /* Modified time */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */ if (res == FR_OK) { res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ } if (res == FR_OK) { DIR dj; DEF_NAMBUF INIT_NAMBUF(fs); res = load_obj_xdir(&dj, &fp->obj); /* Load directory entry block */ if (res == FR_OK) { fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */ st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */ fs->dirbuf[XDIR_ModTime10] = 0; st_dword(fs->dirbuf + XDIR_AccTime, 0); res = store_xdir(&dj); /* Restore it to the directory */ if (res == FR_OK) { res = sync_fs(fs); fp->flag &= (BYTE)~FA_MODIFIED; } } FREE_NAMBUF(); } } else #endif { res = move_window(fs, fp->dir_sect); if (res == FR_OK) { dir = fp->dir_ptr; dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */ st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ st_dword(dir + DIR_ModTime, tm); /* Update modified time */ st_word(dir + DIR_LstAccDate, 0); fs->wflag = 1; res = sync_fs(fs); /* Restore it to the directory */ fp->flag &= (BYTE)~FA_MODIFIED; } } } } LEAVE_FF(fs, res); } #endif /* !FF_FS_READONLY */ /*-----------------------------------------------------------------------*/ /* Close File */ /*-----------------------------------------------------------------------*/ FRESULT f_close ( FIL* fp /* Pointer to the file object to be closed */ ) { FRESULT res; FATFS *fs; #if !FF_FS_READONLY res = f_sync(fp); /* Flush cached data */ if (res == FR_OK) #endif { res = validate(&fp->obj, &fs); /* Lock volume */ if (res == FR_OK) { #if FF_FS_LOCK != 0 res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ if (res == FR_OK) fp->obj.fs = 0; /* Invalidate file object */ #else fp->obj.fs = 0; /* Invalidate file object */ #endif #if FF_FS_REENTRANT unlock_fs(fs, FR_OK); /* Unlock volume */ #endif } } return res; } #if FF_FS_RPATH >= 1 /*-----------------------------------------------------------------------*/ /* Change Current Directory or Current Drive, Get Current Directory */ /*-----------------------------------------------------------------------*/ FRESULT f_chdir ( FATFS *fs, const TCHAR* path /* Pointer to the directory path */ ) { #if FF_STR_VOLUME_ID == 2 UINT i; #endif FRESULT res; DIR dj; DEF_NAMBUF /* Get logical drive */ res = find_volume(fs, 0); if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); res = follow_path(&dj, path); /* Follow the path */ if (res == FR_OK) { /* Follow completed */ if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it the start directory itself? */ fs->cdir = dj.obj.sclust; #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { fs->cdc_scl = dj.obj.c_scl; fs->cdc_size = dj.obj.c_size; fs->cdc_ofs = dj.obj.c_ofs; } #endif } else { if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; fs->cdc_ofs = dj.blk_ofs; } else #endif { fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ } } else { res = FR_NO_PATH; /* Reached but a file */ } } } FREE_NAMBUF(); if (res == FR_NO_FILE) res = FR_NO_PATH; #if FF_STR_VOLUME_ID == 2 /* Also current drive is changed at Unix style volume ID */ if (res == FR_OK) { for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */ CurrVol = (BYTE)i; } #endif } LEAVE_FF(fs, res); } #if FF_FS_RPATH >= 2 FRESULT f_getcwd ( FATFS *fs, TCHAR* buff, /* Pointer to the directory path */ UINT len /* Size of buff in unit of TCHAR */ ) { FRESULT res; DIR dj; UINT i, n; DWORD ccl; TCHAR *tp = buff; #if FF_VOLUMES >= 2 UINT vl; #endif #if FF_STR_VOLUME_ID const char *vp; #endif FILINFO fno; DEF_NAMBUF /* Get logical drive */ buff[0] = 0; /* Set null string to get current volume */ res = find_volume(fs, 0); /* Get current volume */ if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); /* Follow parent directories and create the path */ i = len; /* Bottom of buffer (directory stack base) */ if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) */ dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ while ((ccl = dj.obj.sclust) != 0) { /* Repeat while current directory is a sub-directory */ res = dir_sdi(&dj, 1 * SZDIRE); /* Get parent directory */ if (res != FR_OK) break; res = move_window(fs, dj.sect); if (res != FR_OK) break; dj.obj.sclust = ld_clust(fs, dj.dir); /* Goto parent directory */ res = dir_sdi(&dj, 0); if (res != FR_OK) break; do { /* Find the entry links to the child directory */ res = DIR_READ_FILE(&dj); if (res != FR_OK) break; if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */ res = dir_next(&dj, 0); } while (res == FR_OK); if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ if (res != FR_OK) break; get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ for (n = 0; fno.fname[n]; n++) ; /* Name length */ if (i < n + 1) { /* Insufficient space to store the path name? */ res = FR_NOT_ENOUGH_CORE; break; } while (n) buff[--i] = fno.fname[--n]; /* Stack the name */ buff[--i] = '/'; } } if (res == FR_OK) { if (i == len) buff[--i] = '/'; /* Is it the root-directory? */ #if FF_VOLUMES >= 2 /* Put drive prefix */ vl = 0; #if FF_STR_VOLUME_ID >= 1 /* String volume ID */ for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ; if (i >= n + 2) { if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/'; for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ; if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':'; vl++; } #else /* Numeric volume ID */ if (i >= 3) { *tp++ = (TCHAR)'0' + CurrVol; *tp++ = (TCHAR)':'; vl = 2; } #endif if (vl == 0) res = FR_NOT_ENOUGH_CORE; #endif /* Add current directory path */ if (res == FR_OK) { do *tp++ = buff[i++]; while (i < len); /* Copy stacked path string */ } } FREE_NAMBUF(); } *tp = 0; LEAVE_FF(fs, res); } #endif /* FF_FS_RPATH >= 2 */ #endif /* FF_FS_RPATH >= 1 */ #if FF_FS_MINIMIZE <= 2 /*-----------------------------------------------------------------------*/ /* Seek File Read/Write Pointer */ /*-----------------------------------------------------------------------*/ FRESULT f_lseek ( FIL* fp, /* Pointer to the file object */ FSIZE_t ofs /* File pointer from top of file */ ) { FRESULT res; FATFS *fs; DWORD clst, bcs, nsect; FSIZE_t ifptr; #if FF_USE_FASTSEEK DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; #endif res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res == FR_OK) res = (FRESULT)fp->err; #if FF_FS_EXFAT && !FF_FS_READONLY if (res == FR_OK && fs->fs_type == FS_EXFAT) { res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ } #endif if (res != FR_OK) LEAVE_FF(fs, res); #if FF_USE_FASTSEEK if (fp->cltbl) { /* Fast seek */ if (ofs == CREATE_LINKMAP) { /* Create CLMT */ tbl = fp->cltbl; tlen = *tbl++; ulen = 2; /* Given table size and required table size */ cl = fp->obj.sclust; /* Origin of the chain */ if (cl != 0) { do { /* Get a fragment */ tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ do { pcl = cl; ncl++; cl = get_fat(&fp->obj, cl); if (cl <= 1) ABORT(fs, FR_INT_ERR); if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); } while (cl == pcl + 1); if (ulen <= tlen) { /* Store the length and top of the fragment */ *tbl++ = ncl; *tbl++ = tcl; } } while (cl < fs->n_fatent); /* Repeat until end of chain */ } *fp->cltbl = ulen; /* Number of items used */ if (ulen <= tlen) { *tbl = 0; /* Terminate table */ } else { res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ } } else { /* Fast seek */ if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */ fp->fptr = ofs; /* Set file pointer */ if (ofs > 0) { fp->clust = clmt_clust(fp, ofs - 1); dsc = clst2sect(fs, fp->clust); if (dsc == 0) ABORT(fs, FR_INT_ERR); dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1); if (fp->fptr % SS(fs) && dsc != fp->sect) { /* Refill sector cache if needed */ #if !FF_FS_TINY #if !FF_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif if (disk_read(fs->drv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ #endif fp->sect = dsc; } } } } else #endif /* Normal Seek */ { #if FF_FS_EXFAT if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4 GiB - 1 if at FATxx */ #endif if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) { /* In read-only mode, clip offset with the file size */ ofs = fp->obj.objsize; } ifptr = fp->fptr; fp->fptr = nsect = 0; if (ofs > 0) { bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ if (ifptr > 0 && (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */ ofs -= fp->fptr; clst = fp->clust; } else { /* When seek to back cluster, */ clst = fp->obj.sclust; /* start from the first cluster */ #if !FF_FS_READONLY if (clst == 0) { /* If no cluster chain, create a new chain */ clst = create_chain(&fp->obj, 0); if (clst == 1) ABORT(fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); fp->obj.sclust = clst; } #endif fp->clust = clst; } if (clst != 0) { while (ofs > bcs) { /* Cluster following loop */ ofs -= bcs; fp->fptr += bcs; #if !FF_FS_READONLY if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) { /* No FAT chain object needs correct objsize to generate FAT value */ fp->obj.objsize = fp->fptr; fp->flag |= FA_MODIFIED; } clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */ if (clst == 0) { /* Clip file size in case of disk full */ ofs = 0; break; } } else #endif { clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ } if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); fp->clust = clst; } fp->fptr += ofs; if (ofs % SS(fs)) { nsect = clst2sect(fs, clst); /* Current sector */ if (nsect == 0) ABORT(fs, FR_INT_ERR); nsect += (DWORD)(ofs / SS(fs)); } } } if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */ fp->obj.objsize = fp->fptr; fp->flag |= FA_MODIFIED; } if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */ #if !FF_FS_TINY #if !FF_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif if (disk_read(fs->drv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ #endif fp->sect = nsect; } } LEAVE_FF(fs, res); } #if FF_FS_MINIMIZE <= 1 /*-----------------------------------------------------------------------*/ /* Create a Directory Object */ /*-----------------------------------------------------------------------*/ FRESULT f_opendir ( FATFS *fs, DIR* dp, /* Pointer to directory object to create */ const TCHAR* path /* Pointer to the directory path */ ) { FRESULT res; DEF_NAMBUF if (!dp) return FR_INVALID_OBJECT; /* Get logical drive */ res = find_volume(fs, 0); if (res == FR_OK) { dp->obj.fs = fs; INIT_NAMBUF(fs); res = follow_path(dp, path); /* Follow the path to the directory */ if (res == FR_OK) { /* Follow completed */ if (!(dp->fn[NSFLAG] & NS_NONAME)) { /* It is not the origin directory itself */ if (dp->obj.attr & AM_DIR) { /* This object is a sub-directory */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */ dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; dp->obj.c_ofs = dp->blk_ofs; init_alloc_info(fs, &dp->obj); /* Get object allocation info */ } else #endif { dp->obj.sclust = ld_clust(fs, dp->dir); /* Get object allocation info */ } } else { /* This object is a file */ res = FR_NO_PATH; } } if (res == FR_OK) { dp->obj.id = fs->id; res = dir_sdi(dp, 0); /* Rewind directory */ #if FF_FS_LOCK != 0 if (res == FR_OK) { if (dp->obj.sclust != 0) { dp->obj.lockid = inc_lock(dp, 0); /* Lock the sub directory */ if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES; } else { dp->obj.lockid = 0; /* Root directory need not to be locked */ } } #endif } } FREE_NAMBUF(); if (res == FR_NO_FILE) res = FR_NO_PATH; } if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function faild */ LEAVE_FF(fs, res); } /*-----------------------------------------------------------------------*/ /* Close Directory */ /*-----------------------------------------------------------------------*/ FRESULT f_closedir ( DIR *dp /* Pointer to the directory object to be closed */ ) { FRESULT res; FATFS *fs; res = validate(&dp->obj, &fs); /* Check validity of the file object */ if (res == FR_OK) { #if FF_FS_LOCK != 0 if (dp->obj.lockid) res = dec_lock(dp->obj.lockid); /* Decrement sub-directory open counter */ if (res == FR_OK) dp->obj.fs = 0; /* Invalidate directory object */ #else dp->obj.fs = 0; /* Invalidate directory object */ #endif #if FF_FS_REENTRANT unlock_fs(fs, FR_OK); /* Unlock volume */ #endif } return res; } /*-----------------------------------------------------------------------*/ /* Read Directory Entries in Sequence */ /*-----------------------------------------------------------------------*/ FRESULT f_readdir ( DIR* dp, /* Pointer to the open directory object */ FILINFO* fno /* Pointer to file information to return */ ) { FRESULT res; FATFS *fs; DEF_NAMBUF res = validate(&dp->obj, &fs); /* Check validity of the directory object */ if (res == FR_OK) { if (!fno) { res = dir_sdi(dp, 0); /* Rewind the directory object */ } else { INIT_NAMBUF(fs); res = DIR_READ_FILE(dp); /* Read an item */ if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */ if (res == FR_OK) { /* A valid entry is found */ get_fileinfo(dp, fno); /* Get the object information */ res = dir_next(dp, 0); /* Increment index for next */ if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory now */ } FREE_NAMBUF(); } } LEAVE_FF(fs, res); } #if FF_USE_FIND /*-----------------------------------------------------------------------*/ /* Find Next File */ /*-----------------------------------------------------------------------*/ FRESULT f_findnext ( DIR* dp, /* Pointer to the open directory object */ FILINFO* fno /* Pointer to the file information structure */ ) { FRESULT res; for (;;) { res = f_readdir(dp, fno); /* Get a directory item */ if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */ if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */ #if FF_USE_LFN && FF_USE_FIND == 2 if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */ #endif } return res; } /*-----------------------------------------------------------------------*/ /* Find First File */ /*-----------------------------------------------------------------------*/ FRESULT f_findfirst ( DIR* dp, /* Pointer to the blank directory object */ FILINFO* fno, /* Pointer to the file information structure */ const TCHAR* path, /* Pointer to the directory to open */ const TCHAR* pattern /* Pointer to the matching pattern */ ) { FRESULT res; dp->pat = pattern; /* Save pointer to pattern string */ res = f_opendir(dp, path); /* Open the target directory */ if (res == FR_OK) { res = f_findnext(dp, fno); /* Find the first item */ } return res; } #endif /* FF_USE_FIND */ #if FF_FS_MINIMIZE == 0 /*-----------------------------------------------------------------------*/ /* Get File Status */ /*-----------------------------------------------------------------------*/ FRESULT f_stat ( FATFS *fs, const TCHAR* path, /* Pointer to the file path */ FILINFO* fno /* Pointer to file information to return */ ) { FRESULT res; DIR dj; DEF_NAMBUF /* Get logical drive */ res = find_volume(fs, 0); dj.obj.fs = fs; if (res == FR_OK) { INIT_NAMBUF(dj.obj.fs); res = follow_path(&dj, path); /* Follow the file path */ if (res == FR_OK) { /* Follow completed */ if (dj.fn[NSFLAG] & NS_NONAME) { /* It is origin directory */ res = FR_INVALID_NAME; } else { /* Found an object */ if (fno) get_fileinfo(&dj, fno); } } FREE_NAMBUF(); } LEAVE_FF(dj.obj.fs, res); } #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Get Number of Free Clusters */ /*-----------------------------------------------------------------------*/ FRESULT f_getfree ( FATFS *fs, DWORD* nclst /* Pointer to a variable to return number of free clusters */ ) { FRESULT res; DWORD nfree, clst, sect, stat; UINT i; FFOBJID obj; /* Get logical drive */ res = find_volume(fs, 0); if (res == FR_OK) { /* If free_clst is valid, return it without full FAT scan */ if (fs->free_clst <= fs->n_fatent - 2) { *nclst = fs->free_clst; } else { /* Scan FAT to obtain number of free clusters */ nfree = 0; if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */ clst = 2; obj.fs = fs; do { stat = get_fat(&obj, clst); if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } if (stat == 1) { res = FR_INT_ERR; break; } if (stat == 0) nfree++; } while (++clst < fs->n_fatent); } else { #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* exFAT: Scan allocation bitmap */ BYTE bm; UINT b; clst = fs->n_fatent - 2; /* Number of clusters */ sect = fs->bitbase; /* Bitmap sector */ i = 0; /* Offset in the sector */ do { /* Counts numbuer of bits with zero in the bitmap */ if (i == 0) { res = move_window(fs, sect++); if (res != FR_OK) break; } for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) { if (!(bm & 1)) nfree++; bm >>= 1; } i = (i + 1) % SS(fs); } while (clst); } else #endif { /* FAT16/32: Scan WORD/DWORD FAT entries */ clst = fs->n_fatent; /* Number of entries */ sect = fs->fatbase; /* Top of the FAT */ i = 0; /* Offset in the sector */ do { /* Counts numbuer of entries with zero in the FAT */ if (i == 0) { res = move_window(fs, sect++); if (res != FR_OK) break; } if (fs->fs_type == FS_FAT16) { if (ld_word(fs->win + i) == 0) nfree++; i += 2; } else { if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++; i += 4; } i %= SS(fs); } while (--clst); } } *nclst = nfree; /* Return the free clusters */ fs->free_clst = nfree; /* Now free_clst is valid */ fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */ } } LEAVE_FF(fs, res); } /*-----------------------------------------------------------------------*/ /* Truncate File */ /*-----------------------------------------------------------------------*/ FRESULT f_truncate ( FIL* fp /* Pointer to the file object */ ) { FRESULT res; FATFS *fs; DWORD ncl; res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ if (fp->fptr < fp->obj.objsize) { /* Process when fptr is not on the eof */ if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ res = remove_chain(&fp->obj, fp->obj.sclust, 0); fp->obj.sclust = 0; } else { /* When truncate a part of the file, remove remaining clusters */ ncl = get_fat(&fp->obj, fp->clust); res = FR_OK; if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; if (ncl == 1) res = FR_INT_ERR; if (res == FR_OK && ncl < fs->n_fatent) { res = remove_chain(&fp->obj, ncl, fp->clust); } } fp->obj.objsize = fp->fptr; /* Set file size to current read/write point */ fp->flag |= FA_MODIFIED; #if !FF_FS_TINY if (res == FR_OK && (fp->flag & FA_DIRTY)) { if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) { res = FR_DISK_ERR; } else { fp->flag &= (BYTE)~FA_DIRTY; } } #endif if (res != FR_OK) ABORT(fs, res); } LEAVE_FF(fs, res); } /*-----------------------------------------------------------------------*/ /* Delete a File/Directory */ /*-----------------------------------------------------------------------*/ FRESULT f_unlink ( FATFS *fs, const TCHAR* path /* Pointer to the file or directory path */ ) { FRESULT res; DIR dj, sdj; DWORD dclst = 0; #if FF_FS_EXFAT FFOBJID obj; #endif DEF_NAMBUF /* Get logical drive */ res = find_volume(fs, FA_WRITE); if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); res = follow_path(&dj, path); /* Follow the file path */ if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) { res = FR_INVALID_NAME; /* Cannot remove dot entry */ } #if FF_FS_LOCK != 0 if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */ #endif if (res == FR_OK) { /* The object is accessible */ if (dj.fn[NSFLAG] & NS_NONAME) { res = FR_INVALID_NAME; /* Cannot remove the origin directory */ } else { if (dj.obj.attr & AM_RDO) { res = FR_DENIED; /* Cannot remove R/O object */ } } if (res == FR_OK) { #if FF_FS_EXFAT obj.fs = fs; if (fs->fs_type == FS_EXFAT) { init_alloc_info(fs, &obj); dclst = obj.sclust; } else #endif { dclst = ld_clust(fs, dj.dir); } if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory? */ #if FF_FS_RPATH != 0 if (dclst == fs->cdir) { /* Is it the current directory? */ res = FR_DENIED; } else #endif { sdj.obj.fs = fs; /* Open the sub-directory */ sdj.obj.sclust = dclst; #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { sdj.obj.objsize = obj.objsize; sdj.obj.stat = obj.stat; } #endif res = dir_sdi(&sdj, 0); if (res == FR_OK) { res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */ if (res == FR_OK) res = FR_DENIED; /* Not empty? */ if (res == FR_NO_FILE) res = FR_OK; /* Empty? */ } } } } if (res == FR_OK) { res = dir_remove(&dj); /* Remove the directory entry */ if (res == FR_OK && dclst != 0) { /* Remove the cluster chain if exist */ #if FF_FS_EXFAT res = remove_chain(&obj, dclst, 0); #else res = remove_chain(&dj.obj, dclst, 0); #endif } if (res == FR_OK) res = sync_fs(fs); } } FREE_NAMBUF(); } LEAVE_FF(fs, res); } /*-----------------------------------------------------------------------*/ /* Create a Directory */ /*-----------------------------------------------------------------------*/ FRESULT f_mkdir ( FATFS *fs, const TCHAR* path /* Pointer to the directory path */ ) { FRESULT res; DIR dj; FFOBJID sobj; DWORD dcl, pcl, tm; DEF_NAMBUF res = find_volume(fs, FA_WRITE); /* Get logical drive */ if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); res = follow_path(&dj, path); /* Follow the file path */ if (res == FR_OK) res = FR_EXIST; /* Name collision? */ if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */ res = FR_INVALID_NAME; } if (res == FR_NO_FILE) { /* It is clear to create a new directory */ sobj.fs = fs; /* New object id to create a new chain */ dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */ res = FR_OK; if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */ if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */ if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */ tm = GET_FATTIME(); if (res == FR_OK) { res = dir_clear(fs, dcl); /* Clean up the new table */ if (res == FR_OK) { if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */ mem_set(fs->win + DIR_Name, ' ', 11); /* Create "." entry */ fs->win[DIR_Name] = '.'; fs->win[DIR_Attr] = AM_DIR; st_dword(fs->win + DIR_ModTime, tm); st_clust(fs, fs->win, dcl); mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */ fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust; st_clust(fs, fs->win + SZDIRE, pcl); fs->wflag = 1; } res = dir_register(&dj); /* Register the object to the parent directoy */ } } if (res == FR_OK) { #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */ st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */ st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* File size needs to be valid */ st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs)); fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */ fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ res = store_xdir(&dj); } else #endif { st_dword(dj.dir + DIR_ModTime, tm); /* Created time */ st_clust(fs, dj.dir, dcl); /* Table start cluster */ dj.dir[DIR_Attr] = AM_DIR; /* Attribute */ fs->wflag = 1; } if (res == FR_OK) { res = sync_fs(fs); } } else { remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */ } } FREE_NAMBUF(); } LEAVE_FF(fs, res); } /*-----------------------------------------------------------------------*/ /* Rename a File/Directory */ /*-----------------------------------------------------------------------*/ FRESULT f_rename ( FATFS *fs, const TCHAR* path_old, /* Pointer to the object name to be renamed */ const TCHAR* path_new /* Pointer to the new name */ ) { FRESULT res; DIR djo, djn; BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir; DWORD dw; DEF_NAMBUF res = find_volume(fs, FA_WRITE); /* Get logical drive of the old object */ if (res == FR_OK) { djo.obj.fs = fs; INIT_NAMBUF(fs); res = follow_path(&djo, path_old); /* Check old object */ if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */ #if FF_FS_LOCK != 0 if (res == FR_OK) { res = chk_lock(&djo, 2); } #endif if (res == FR_OK) { /* Object to be renamed is found */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* At exFAT volume */ BYTE nf, nn; WORD nh; mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ mem_cpy(&djn, &djo, sizeof djo); res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ if (res == FR_OK) { /* Is new name already in use by any other object? */ res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; } if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ res = dir_register(&djn); /* Register the new entry */ if (res == FR_OK) { nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName]; nh = ld_word(fs->dirbuf + XDIR_NameHash); mem_cpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */ fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn; st_word(fs->dirbuf + XDIR_NameHash, nh); if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ /* Start of critical section where an interruption can cause a cross-link */ res = store_xdir(&djn); } } } else #endif { /* At FAT/FAT32 volume */ mem_cpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */ mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ if (res == FR_OK) { /* Is new name already in use by any other object? */ res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; } if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ res = dir_register(&djn); /* Register the new entry */ if (res == FR_OK) { dir = djn.dir; /* Copy directory entry of the object except name */ mem_cpy(dir + 13, buf + 13, SZDIRE - 13); dir[DIR_Attr] = buf[DIR_Attr]; if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ fs->wflag = 1; if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) { /* Update .. entry in the sub-directory if needed */ dw = clst2sect(fs, ld_clust(fs, dir)); if (dw == 0) { res = FR_INT_ERR; } else { /* Start of critical section where an interruption can cause a cross-link */ res = move_window(fs, dw); dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */ if (res == FR_OK && dir[1] == '.') { st_clust(fs, dir, djn.obj.sclust); fs->wflag = 1; } } } } } } if (res == FR_OK) { res = dir_remove(&djo); /* Remove old entry */ if (res == FR_OK) { res = sync_fs(fs); } } /* End of the critical section */ } FREE_NAMBUF(); } LEAVE_FF(fs, res); } #endif /* !FF_FS_READONLY */ #endif /* FF_FS_MINIMIZE == 0 */ #endif /* FF_FS_MINIMIZE <= 1 */ #endif /* FF_FS_MINIMIZE <= 2 */ #if FF_USE_CHMOD && !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Change Attribute */ /*-----------------------------------------------------------------------*/ FRESULT f_chmod ( FATFS *fs, const TCHAR* path, /* Pointer to the file path */ BYTE attr, /* Attribute bits */ BYTE mask /* Attribute mask to change */ ) { FRESULT res; DIR dj; DEF_NAMBUF res = find_volume(fs, FA_WRITE); /* Get logical drive */ if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); res = follow_path(&dj, path); /* Follow the file path */ if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ if (res == FR_OK) { mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask); /* Apply attribute change */ res = store_xdir(&dj); } else #endif { dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ fs->wflag = 1; } if (res == FR_OK) { res = sync_fs(fs); } } FREE_NAMBUF(); } LEAVE_FF(fs, res); } /*-----------------------------------------------------------------------*/ /* Change Timestamp */ /*-----------------------------------------------------------------------*/ FRESULT f_utime ( FATFS *fs, const TCHAR* path, /* Pointer to the file/directory name */ const FILINFO* fno /* Pointer to the timestamp to be set */ ) { FRESULT res; DIR dj; DEF_NAMBUF res = find_volume(fs, FA_WRITE); /* Get logical drive */ if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); res = follow_path(&dj, path); /* Follow the file path */ if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ if (res == FR_OK) { #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); res = store_xdir(&dj); } else #endif { st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); fs->wflag = 1; } if (res == FR_OK) { res = sync_fs(fs); } } FREE_NAMBUF(); } LEAVE_FF(fs, res); } #endif /* FF_USE_CHMOD && !FF_FS_READONLY */ #if FF_USE_LABEL /*-----------------------------------------------------------------------*/ /* Get Volume Label */ /*-----------------------------------------------------------------------*/ FRESULT f_getlabel ( FATFS *fs, TCHAR* label, /* Buffer to store the volume label */ DWORD* vsn /* Variable to store the volume serial number */ ) { FRESULT res; DIR dj; UINT si, di; WCHAR wc; /* Get logical drive */ res = find_volume(fs, 0); /* Get volume label */ if (res == FR_OK && label) { dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ res = dir_sdi(&dj, 0); if (res == FR_OK) { res = DIR_READ_LABEL(&dj); /* Find a volume label entry */ if (res == FR_OK) { #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { WCHAR hs; for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */ wc = ld_word(dj.dir + XDIR_Label + si * 2); if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */ hs = wc; continue; } wc = put_utf((DWORD)hs << 16 | wc, &label[di], 4); if (wc == 0) { di = 0; break; } di += wc; hs = 0; } if (hs != 0) di = 0; /* Broken surrogate pair? */ label[di] = 0; } else #endif { si = di = 0; /* Extract volume label from AM_VOL entry */ while (si < 11) { wc = dj.dir[si++]; #if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode output */ if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++]; /* Is it a DBC? */ wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */ if (wc != 0) wc = put_utf(wc, &label[di], 4); /* Put it in Unicode */ if (wc == 0) { di = 0; break; } di += wc; #else /* ANSI/OEM output */ label[di++] = (TCHAR)wc; #endif } do { /* Truncate trailing spaces */ label[di] = 0; if (di == 0) break; } while (label[--di] == ' '); } } } if (res == FR_NO_FILE) { /* No label entry and return nul string */ label[0] = 0; res = FR_OK; } } /* Get volume serial number */ if (res == FR_OK && vsn) { res = move_window(fs, fs->volbase); if (res == FR_OK) { switch (fs->fs_type) { case FS_EXFAT: di = BPB_VolIDEx; break; case FS_FAT32: di = BS_VolID32; break; default: di = BS_VolID; } *vsn = ld_dword(fs->win + di); } } LEAVE_FF(fs, res); } #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Set Volume Label */ /*-----------------------------------------------------------------------*/ FRESULT f_setlabel ( FATFS *fs, const TCHAR* label /* Volume label to set with heading logical drive number */ ) { FRESULT res; DIR dj; BYTE dirvn[22]; UINT di; WCHAR wc; static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */ #if FF_USE_LFN DWORD dc; #endif /* Get logical drive */ res = find_volume(fs, FA_WRITE); if (res != FR_OK) LEAVE_FF(fs, res); #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ mem_set(dirvn, 0, 22); di = 0; while ((UINT)*label >= ' ') { /* Create volume label */ dc = tchar2uni(&label); /* Get a Unicode character */ if (dc >= 0x10000) { if (dc == 0xFFFFFFFF || di >= 10) { /* Wrong surrogate or buffer overflow */ dc = 0; } else { st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++; } } if (dc == 0 || chk_chr(badchr + 7, (int)dc) || di >= 11) { /* Check validity of the volume label */ LEAVE_FF(fs, FR_INVALID_NAME); } st_word(dirvn + di * 2, (WCHAR)dc); di++; } } else #endif { /* On the FAT/FAT32 volume */ mem_set(dirvn, ' ', 11); di = 0; while ((UINT)*label >= ' ') { /* Create volume label */ #if FF_USE_LFN dc = tchar2uni(&label); wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0; #else /* ANSI/OEM input */ wc = (BYTE)*label++; if (dbc_1st((BYTE)wc)) wc = dbc_2nd((BYTE)*label) ? wc << 8 | (BYTE)*label++ : 0; if (IsLower(wc)) wc -= 0x20; /* To upper ASCII characters */ #if FF_CODE_PAGE == 0 if (ExCvt && wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ #elif FF_CODE_PAGE < 900 if (wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ #endif #endif if (wc == 0 || chk_chr(badchr + 0, (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */ LEAVE_FF(fs, FR_INVALID_NAME); } if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8); dirvn[di++] = (BYTE)wc; } if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */ while (di && dirvn[di - 1] == ' ') di--; /* Snip trailing spaces */ } /* Set volume label */ dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ res = dir_sdi(&dj, 0); if (res == FR_OK) { res = DIR_READ_LABEL(&dj); /* Get volume label entry */ if (res == FR_OK) { if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */ mem_cpy(dj.dir + XDIR_Label, dirvn, 22); } else { if (di != 0) { mem_cpy(dj.dir, dirvn, 11); /* Change the volume label */ } else { dj.dir[DIR_Name] = DDEM; /* Remove the volume label */ } } fs->wflag = 1; res = sync_fs(fs); } else { /* No volume label entry or an error */ if (res == FR_NO_FILE) { res = FR_OK; if (di != 0) { /* Create a volume label entry */ res = dir_alloc(&dj, 1); /* Allocate an entry */ if (res == FR_OK) { mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */ if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */ dj.dir[XDIR_NumLabel] = (BYTE)di; mem_cpy(dj.dir + XDIR_Label, dirvn, 22); } else { dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ mem_cpy(dj.dir, dirvn, 11); } fs->wflag = 1; res = sync_fs(fs); } } } } } LEAVE_FF(fs, res); } #endif /* !FF_FS_READONLY */ #endif /* FF_USE_LABEL */ #if FF_USE_EXPAND && !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Allocate a Contiguous Blocks to the File */ /*-----------------------------------------------------------------------*/ FRESULT f_expand ( FIL* fp, /* Pointer to the file object */ FSIZE_t fsz, /* File size to be expanded to */ BYTE opt /* Operation mode 0:Find and prepare or 1:Find and allocate */ ) { FRESULT res; FATFS *fs; DWORD n, clst, stcl, scl, ncl, tcl, lclst; res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); #if FF_FS_EXFAT if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ #endif n = (DWORD)fs->csize * SS(fs); /* Cluster size */ tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0); /* Number of clusters required */ stcl = fs->last_clst; lclst = 0; if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2; #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { scl = find_bitmap(fs, stcl, tcl); /* Find a contiguous cluster block */ if (scl == 0) res = FR_DENIED; /* No contiguous cluster block was found */ if (scl == 0xFFFFFFFF) res = FR_DISK_ERR; if (res == FR_OK) { /* A contiguous free area is found */ if (opt) { /* Allocate it now */ res = change_bitmap(fs, scl, tcl, 1); /* Mark the cluster block 'in use' */ lclst = scl + tcl - 1; } else { /* Set it as suggested point for next allocation */ lclst = scl - 1; } } } else #endif { scl = clst = stcl; ncl = 0; for (;;) { /* Find a contiguous cluster block */ n = get_fat(&fp->obj, clst); if (++clst >= fs->n_fatent) clst = 2; if (n == 1) { res = FR_INT_ERR; break; } if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } if (n == 0) { /* Is it a free cluster? */ if (++ncl == tcl) break; /* Break if a contiguous cluster block is found */ } else { scl = clst; ncl = 0; /* Not a free cluster */ } if (clst == stcl) { res = FR_DENIED; break; } /* No contiguous cluster? */ } if (res == FR_OK) { /* A contiguous free area is found */ if (opt) { /* Allocate it now */ for (clst = scl, n = tcl; n; clst++, n--) { /* Create a cluster chain on the FAT */ res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1); if (res != FR_OK) break; lclst = clst; } } else { /* Set it as suggested point for next allocation */ lclst = scl - 1; } } } if (res == FR_OK) { fs->last_clst = lclst; /* Set suggested start cluster to start next */ if (opt) { /* Is it allocated now? */ fp->obj.sclust = scl; /* Update object allocation information */ fp->obj.objsize = fsz; if (FF_FS_EXFAT) fp->obj.stat = 2; /* Set status 'contiguous chain' */ fp->flag |= FA_MODIFIED; if (fs->free_clst <= fs->n_fatent - 2) { /* Update FSINFO */ fs->free_clst -= tcl; fs->fsi_flag |= 1; } } } LEAVE_FF(fs, res); } #endif /* FF_USE_EXPAND && !FF_FS_READONLY */ #if FF_USE_FORWARD /*-----------------------------------------------------------------------*/ /* Forward Data to the Stream Directly */ /*-----------------------------------------------------------------------*/ FRESULT f_forward ( FIL* fp, /* Pointer to the file object */ UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ UINT btf, /* Number of bytes to forward */ UINT* bf /* Pointer to number of bytes forwarded */ ) { FRESULT res; FATFS *fs; DWORD clst, sect; FSIZE_t remain; UINT rcnt, csect; BYTE *dbuf; *bf = 0; /* Clear transfer byte counter */ res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ remain = fp->obj.objsize - fp->fptr; if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream goes busy */ fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ if (csect == 0) { /* On the cluster boundary? */ clst = (fp->fptr == 0) ? /* On the top of the file? */ fp->obj.sclust : get_fat(&fp->obj, fp->clust); if (clst <= 1) ABORT(fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); fp->clust = clst; /* Update current cluster */ } } sect = clst2sect(fs, fp->clust); /* Get current data sector */ if (sect == 0) ABORT(fs, FR_INT_ERR); sect += csect; #if FF_FS_TINY if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window to the file data */ dbuf = fs->win; #else if (fp->sect != sect) { /* Fill sector cache with file data */ #if !FF_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } #endif if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); } dbuf = fp->buf; #endif fp->sect = sect; rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ if (rcnt > btf) rcnt = btf; /* Clip it by btr if needed */ rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt); /* Forward the file data */ if (rcnt == 0) ABORT(fs, FR_INT_ERR); } LEAVE_FF(fs, FR_OK); } #endif /* FF_USE_FORWARD */ #if FF_USE_MKFS && !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Create an FAT/exFAT volume */ /*-----------------------------------------------------------------------*/ FRESULT f_mkfs ( FATFS *fs, BYTE opt, /* Format option */ DWORD au, /* Size of allocation unit (cluster) [byte] */ void* work, /* Pointer to working buffer (null: use heap memory) */ UINT len /* Size of working buffer [byte] */ ) { const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */ const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */ static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */ static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ BYTE fmt, sys, *buf, *pte, part; void *pdrv; WORD ss; /* Sector size */ DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n; DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */ DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */ UINT i; DSTATUS stat; #if FF_USE_TRIM || FF_FS_EXFAT DWORD tbl[3]; #endif /* Check mounted drive and clear work area */ fs->fs_type = 0; /* Clear mounted volume */ pdrv = fs->drv; /* Physical drive */ part = LD2PT(fs); /* Partition (0:create as new, 1-4:get from partition table) */ /* Check physical drive status */ disk_ioctl(pdrv, IOCTL_INIT, &stat); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */ #if FF_MAX_SS != FF_MIN_SS /* Get sector size of the medium if variable sector size cfg. */ if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; #else ss = FF_MAX_SS; #endif if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ au /= ss; /* Cluster size in unit of sector */ /* Get working buffer */ #if FF_USE_LFN == 3 if (!work) { /* Use heap memory for working buffer */ for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && (buf = ff_memalloc(szb_buf)) == 0; szb_buf /= 2) ; sz_buf = szb_buf / ss; /* Size of working buffer (sector) */ } else #endif { buf = (BYTE*)work; /* Working buffer */ sz_buf = len / ss; /* Size of working buffer (sector) */ szb_buf = sz_buf * ss; /* Size of working buffer (byte) */ } if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE; /* Determine where the volume to be located (b_vol, sz_vol) */ if (FF_MULTI_PARTITION && part != 0) { /* Get partition information from partition table in the MBR */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ pte = buf + (MBR_Table + (part - 1) * SZ_PTE); if (pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED); /* No partition? */ b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ } else { /* Create a single-partition in this function */ if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */ if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); sz_vol -= b_vol; /* Volume size */ } if (sz_vol < 22) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=22s (minimum for ss=4096) */ /* Pre-determine the FAT type */ do { if (FF_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */ if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) { /* exFAT only, vol >= 64Ms or au > 128s ? */ fmt = FS_EXFAT; break; } } if (au > 128) LEAVE_MKFS(FR_INVALID_PARAMETER); /* Too large au for FAT/FAT32 */ if (opt & FM_FAT32) { /* FAT32 possible? */ if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */ fmt = FS_FAT32; break; } } if (!(opt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER); /* no-FAT? */ fmt = FS_FAT16; } while (0); #if FF_FS_EXFAT if (fmt == FS_EXFAT) { /* Create an exFAT volume */ DWORD szb_bit, szb_case, sum, nb, cl; WCHAR ch, si; UINT j, st; BYTE b; if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ #if FF_USE_TRIM tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area may be erased */ disk_ioctl(pdrv, CTRL_TRIM, tbl); #endif /* Determine FAT location, data location and number of clusters */ if (au == 0) { /* au auto-selection */ au = 8; if (sz_vol >= 0x80000) au = 64; /* >= 512Ks */ if (sz_vol >= 0x4000000) au = 256; /* >= 64Ms */ } b_fat = b_vol + 32; /* FAT start at offset 32 */ sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */ if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */ if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */ if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */ szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */ /* Create a compressed up-case table */ sect = b_data + au * tbl[0]; /* Table start sector */ sum = 0; /* Table checksum to be stored in the 82 entry */ st = 0; si = 0; i = 0; j = 0; szb_case = 0; do { switch (st) { case 0: ch = (WCHAR)ff_wtoupper(si); /* Get an up-case char */ if (ch != si) { si++; break; /* Store the up-case char if exist */ } for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */ if (j >= 128) { ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */ } st = 1; /* Do not compress short run */ /* go to next case */ case 1: ch = si++; /* Fill the short run */ if (--j == 0) st = 0; break; default: ch = (WCHAR)j; si += (WCHAR)j; /* Number of chars to skip */ st = 0; } sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); i += 2; szb_case += 2; if (si == 0 || i == szb_buf) { /* Write buffered data when buffer full or end of process */ n = (i + ss - 1) / ss; if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); sect += n; i = 0; } } while (si); tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */ tbl[2] = 1; /* Number of root dir clusters */ /* Initialize the allocation bitmap */ sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */ nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */ do { mem_set(buf, 0, szb_buf); for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ; for (b = 1; nb != 0 && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ; n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); sect += n; nsect -= n; } while (nsect); /* Initialize the FAT */ sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */ j = nb = cl = 0; do { mem_set(buf, 0, szb_buf); i = 0; /* Clear work area and reset write index */ if (cl == 0) { /* Set entry 0 and 1 */ st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++; st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++; } do { /* Create chains of bitmap, up-case and root dir */ while (nb != 0 && i < szb_buf) { /* Create a chain */ st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF); i += 4; cl++; nb--; } if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */ } while (nb != 0 && i < szb_buf); n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); sect += n; nsect -= n; } while (nsect); /* Initialize the root directory */ mem_set(buf, 0, szb_buf); buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry */ buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */ st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */ st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */ st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */ st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */ sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */ do { /* Fill root directory sectors */ n = (nsect > sz_buf) ? sz_buf : nsect; if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); mem_set(buf, 0, ss); sect += n; nsect -= n; } while (nsect); /* Create two set of the exFAT VBR blocks */ sect = b_vol; for (n = 0; n < 2; n++) { /* Main record (+0) */ mem_set(buf, 0, ss); mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */ st_dword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ st_dword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ st_dword(buf + BPB_FatOfsEx, b_fat - b_vol); /* FAT offset [sector] */ st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ st_dword(buf + BPB_DataOfsEx, b_data - b_vol); /* Data offset [sector] */ st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */ st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */ st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ buf[BPB_NumFATsEx] = 1; /* Number of FATs */ buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */ st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ for (i = sum = 0; i < ss; i++) { /* VBR checksum */ if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); } if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Extended bootstrap record (+1..+8) */ mem_set(buf, 0, ss); st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ for (j = 1; j < 9; j++) { for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); } /* OEM/Reserved record (+9..+10) */ mem_set(buf, 0, ss); for ( ; j < 11; j++) { for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); } /* Sum record (+11) */ for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); } } else #endif /* FF_FS_EXFAT */ { /* Create an FAT/FAT32 volume */ do { pau = au; /* Pre-determine number of clusters and FAT sub-type */ if (fmt == FS_FAT32) { /* FAT32 volume */ if (pau == 0) { /* au auto-selection */ n = sz_vol / 0x20000; /* Volume size in unit of 128KS */ for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */ } n_clst = sz_vol / pau; /* Number of clusters */ sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */ sz_rsv = 32; /* Number of reserved sectors */ sz_dir = 0; /* No static directory */ if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED); } else { /* FAT volume */ if (pau == 0) { /* au auto-selection */ n = sz_vol / 0x1000; /* Volume size in unit of 4KS */ for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ; /* Get from table */ } n_clst = sz_vol / pau; if (n_clst > MAX_FAT12) { n = n_clst * 2 + 4; /* FAT size [byte] */ } else { fmt = FS_FAT12; n = (n_clst * 3 + 1) / 2 + 3; /* FAT size [byte] */ } sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */ sz_rsv = 1; /* Number of reserved sectors */ sz_dir = (DWORD)n_rootdir * SZDIRE / ss; /* Rootdir size [sector] */ } b_fat = b_vol + sz_rsv; /* FAT base */ b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */ /* Align data base to erase block boundary (for flash memory media) */ n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */ if (fmt == FS_FAT32) { /* FAT32: Move FAT base */ sz_rsv += n; b_fat += n; } else { /* FAT: Expand FAT size */ sz_fat += n / n_fats; } /* Determine number of clusters and final check of validity of the FAT sub-type */ if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume */ n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau; if (fmt == FS_FAT32) { if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32 */ if (au == 0 && (au = pau / 2) != 0) continue; /* Adjust cluster size and retry */ LEAVE_MKFS(FR_MKFS_ABORTED); } } if (fmt == FS_FAT16) { if (n_clst > MAX_FAT16) { /* Too many clusters for FAT16 */ if (au == 0 && (pau * 2) <= 64) { au = pau * 2; continue; /* Adjust cluster size and retry */ } if ((opt & FM_FAT32)) { fmt = FS_FAT32; continue; /* Switch type to FAT32 and retry */ } if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ LEAVE_MKFS(FR_MKFS_ABORTED); } if (n_clst <= MAX_FAT12) { /* Too few clusters for FAT16 */ if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ LEAVE_MKFS(FR_MKFS_ABORTED); } } if (fmt == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters for FAT12 */ /* Ok, it is the valid cluster configuration */ break; } while (1); #if FF_USE_TRIM tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area can be erased */ disk_ioctl(pdrv, CTRL_TRIM, tbl); #endif /* Create FAT VBR */ mem_set(buf, 0, ss); mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */ st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */ if (sz_vol < 0x10000) { st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ } else { st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */ } buf[BPB_Media] = 0xF8; /* Media descriptor byte */ st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ if (fmt == FS_FAT32) { st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig32] = 0x29; /* Extended boot signature */ mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ } else { st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig] = 0x29; /* Extended boot signature */ mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ } st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ /* Create FSINFO record if needed */ if (fmt == FS_FAT32) { disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ mem_set(buf, 0, ss); st_dword(buf + FSI_LeadSig, 0x41615252); st_dword(buf + FSI_StrucSig, 0x61417272); st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ st_word(buf + BS_55AA, 0xAA55); disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ } /* Initialize FAT area */ mem_set(buf, 0, (UINT)szb_buf); sect = b_fat; /* FAT start sector */ for (i = 0; i < n_fats; i++) { /* Initialize FATs each */ if (fmt == FS_FAT32) { st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */ st_dword(buf + 4, 0xFFFFFFFF); /* Entry 1 */ st_dword(buf + 8, 0x0FFFFFFF); /* Entry 2 (root directory) */ } else { st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */ } nsect = sz_fat; /* Number of FAT sectors */ do { /* Fill FAT sectors */ n = (nsect > sz_buf) ? sz_buf : nsect; if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); mem_set(buf, 0, ss); sect += n; nsect -= n; } while (nsect); } /* Initialize root directory (fill with zero) */ nsect = (fmt == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ do { n = (nsect > sz_buf) ? sz_buf : nsect; if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); sect += n; nsect -= n; } while (nsect); } /* Determine system ID in the partition table */ if (FF_FS_EXFAT && fmt == FS_EXFAT) { sys = 0x07; /* HPFS/NTFS/exFAT */ } else { if (fmt == FS_FAT32) { sys = 0x0C; /* FAT32X */ } else { if (sz_vol >= 0x10000) { sys = 0x06; /* FAT12/16 (large) */ } else { sys = (fmt == FS_FAT16) ? 0x04 : 0x01; /* FAT16 : FAT12 */ } } } /* Update partition information */ if (FF_MULTI_PARTITION && part != 0) { /* Created in the existing partition */ /* Update system ID in the partition table */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */ } else { /* Created as a new single partition */ if (!(opt & FM_SFD)) { /* Create partition table if in FDISK format */ mem_set(buf, 0, ss); st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ pte = buf + MBR_Table; /* Create partition table for single partition in the drive */ pte[PTE_Boot] = 0; /* Boot indicator */ pte[PTE_StHead] = 1; /* Start head */ pte[PTE_StSec] = 1; /* Start sector */ pte[PTE_StCyl] = 0; /* Start cylinder */ pte[PTE_System] = sys; /* System type */ n = (b_vol + sz_vol) / (63 * 255); /* (End CHS may be invalid) */ pte[PTE_EdHead] = 254; /* End head */ pte[PTE_EdSec] = (BYTE)(((n >> 2) & 0xC0) | 63); /* End sector */ pte[PTE_EdCyl] = (BYTE)n; /* End cylinder */ st_dword(pte + PTE_StLba, b_vol); /* Start offset in LBA */ st_dword(pte + PTE_SizLba, sz_vol); /* Size in sectors */ if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the MBR */ } } if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); LEAVE_MKFS(FR_OK); } #if FF_MULTI_PARTITION /*-----------------------------------------------------------------------*/ /* Create Partition Table on the Physical Drive */ /*-----------------------------------------------------------------------*/ FRESULT f_fdisk ( void *pdrv, /* Physical drive number */ const DWORD* szt, /* Pointer to the size table for each partitions */ void* work /* Pointer to the working buffer (null: use heap memory) */ ) { UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; DSTATUS stat; DWORD sz_disk, sz_part, s_part; FRESULT res; disk_ioctl(pdrv, IOCTL_INIT, &stat); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; buf = (BYTE*)work; #if FF_USE_LFN == 3 if (!buf) buf = ff_memalloc(FF_MAX_SS); /* Use heap memory for working buffer */ #endif if (!buf) return FR_NOT_ENOUGH_CORE; /* Determine the CHS without any consideration of the drive geometry */ for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; if (n == 256) n--; e_hd = (BYTE)(n - 1); sz_cyl = 63 * n; tot_cyl = sz_disk / sz_cyl; /* Create partition table */ mem_set(buf, 0, FF_MAX_SS); p = buf + MBR_Table; b_cyl = 0; for (i = 0; i < 4; i++, p += SZ_PTE) { p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; /* Number of cylinders */ if (p_cyl == 0) continue; s_part = (DWORD)sz_cyl * b_cyl; sz_part = (DWORD)sz_cyl * p_cyl; if (i == 0) { /* Exclude first track of cylinder 0 */ s_hd = 1; s_part += 63; sz_part -= 63; } else { s_hd = 0; } e_cyl = b_cyl + p_cyl - 1; /* End cylinder */ if (e_cyl >= tot_cyl) LEAVE_MKFS(FR_INVALID_PARAMETER); /* Set partition table */ p[1] = s_hd; /* Start head */ p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1); /* Start sector */ p[3] = (BYTE)b_cyl; /* Start cylinder */ p[4] = 0x07; /* System type (temporary setting) */ p[5] = e_hd; /* End head */ p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | 63); /* End sector */ p[7] = (BYTE)e_cyl; /* End cylinder */ st_dword(p + 8, s_part); /* Start sector in LBA */ st_dword(p + 12, sz_part); /* Number of sectors */ /* Next partition */ b_cyl += p_cyl; } st_word(p, 0xAA55); /* MBR signature (always at offset 510) */ /* Write it to the MBR */ res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; LEAVE_MKFS(res); } #endif /* FF_MULTI_PARTITION */ #endif /* FF_USE_MKFS && !FF_FS_READONLY */ #if FF_CODE_PAGE == 0 /*-----------------------------------------------------------------------*/ /* Set Active Codepage for the Path Name */ /*-----------------------------------------------------------------------*/ FRESULT f_setcp ( WORD cp /* Value to be set as active code page */ ) { static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0}; static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; UINT i; for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ; /* Find the code page */ if (validcp[i] != cp) return FR_INVALID_PARAMETER; /* Not found? */ CodePage = cp; if (cp >= 900) { /* DBCS */ ExCvt = 0; DbcTbl = tables[i]; } else { /* SBCS */ ExCvt = tables[i]; DbcTbl = 0; } return FR_OK; } #endif /* FF_CODE_PAGE == 0 */ micropython-1.12/lib/oofatfs/ff.h000066400000000000000000000401411357706137100167750ustar00rootroot00000000000000/* This file is part of ooFatFs, a customised version of FatFs * See https://github.com/micropython/oofatfs for details */ /*----------------------------------------------------------------------------/ / FatFs - Generic FAT Filesystem module R0.13c / /-----------------------------------------------------------------------------/ / / Copyright (C) 2018, ChaN, all right reserved. / / FatFs module is an open source software. Redistribution and use of FatFs in / source and binary forms, with or without modification, are permitted provided / that the following condition is met: / 1. Redistributions of source code must retain the above copyright notice, / this condition and the following disclaimer. / / This software is provided by the copyright holder and contributors "AS IS" / and any warranties related to this software are DISCLAIMED. / The copyright owner or contributors be NOT LIABLE for any damages caused / by use of this software. / /----------------------------------------------------------------------------*/ #ifndef FF_DEFINED #define FF_DEFINED 86604 /* Revision ID */ #ifdef __cplusplus extern "C" { #endif #include FFCONF_H /* FatFs configuration options */ #if FF_DEFINED != FFCONF_DEF #error Wrong configuration file (ffconf.h). #endif /* Integer types used for FatFs API */ #if defined(_WIN32) /* Main development platform */ #define FF_INTDEF 2 #include typedef unsigned __int64 QWORD; #elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */ #define FF_INTDEF 2 #include typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ typedef unsigned char BYTE; /* char must be 8-bit */ typedef uint16_t WORD; /* 16-bit unsigned integer */ typedef uint16_t WCHAR; /* 16-bit unsigned integer */ typedef uint32_t DWORD; /* 32-bit unsigned integer */ typedef uint64_t QWORD; /* 64-bit unsigned integer */ #else /* Earlier than C99 */ #define FF_INTDEF 1 typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ typedef unsigned char BYTE; /* char must be 8-bit */ typedef unsigned short WORD; /* 16-bit unsigned integer */ typedef unsigned short WCHAR; /* 16-bit unsigned integer */ typedef unsigned long DWORD; /* 32-bit unsigned integer */ #endif /* Definitions of volume management */ #if FF_STR_VOLUME_ID #ifndef FF_VOLUME_STRS extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ #endif #endif /* Type of path name strings on FatFs API */ #ifndef _INC_TCHAR #define _INC_TCHAR #if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */ typedef WCHAR TCHAR; #define _T(x) L ## x #define _TEXT(x) L ## x #elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */ typedef char TCHAR; #define _T(x) u8 ## x #define _TEXT(x) u8 ## x #elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ typedef DWORD TCHAR; #define _T(x) U ## x #define _TEXT(x) U ## x #elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) #error Wrong FF_LFN_UNICODE setting #else /* ANSI/OEM code in SBCS/DBCS */ typedef char TCHAR; #define _T(x) x #define _TEXT(x) x #endif #endif /* Type of file size variables */ #if FF_FS_EXFAT #if FF_INTDEF != 2 #error exFAT feature wants C99 or later #endif typedef QWORD FSIZE_t; #else typedef DWORD FSIZE_t; #endif /* Filesystem object structure (FATFS) */ typedef struct { void *drv; // block device underlying this filesystem #if FF_MULTI_PARTITION /* Multiple partition configuration */ BYTE part; // Partition: 0:Auto detect, 1-4:Forced partition #endif BYTE fs_type; /* Filesystem type (0:not mounted) */ BYTE n_fats; /* Number of FATs (1 or 2) */ BYTE wflag; /* win[] flag (b0:dirty) */ BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ WORD id; /* Volume mount ID */ WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ WORD csize; /* Cluster size [sectors] */ #if FF_MAX_SS != FF_MIN_SS WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ #endif #if FF_USE_LFN WCHAR* lfnbuf; /* LFN working buffer */ #endif #if FF_FS_EXFAT BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ #endif #if FF_FS_REENTRANT FF_SYNC_t sobj; /* Identifier of sync object */ #endif #if !FF_FS_READONLY DWORD last_clst; /* Last allocated cluster */ DWORD free_clst; /* Number of free clusters */ #endif #if FF_FS_RPATH DWORD cdir; /* Current directory start cluster (0:root) */ #if FF_FS_EXFAT DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ #endif #endif DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ DWORD fsize; /* Size of an FAT [sectors] */ DWORD volbase; /* Volume base sector */ DWORD fatbase; /* FAT base sector */ DWORD dirbase; /* Root directory base sector/cluster */ DWORD database; /* Data base sector */ #if FF_FS_EXFAT DWORD bitbase; /* Allocation bitmap base sector */ #endif DWORD winsect; /* Current sector appearing in the win[] */ BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ } FATFS; /* Object ID and allocation information (FFOBJID) */ typedef struct { FATFS* fs; /* Pointer to the hosting volume of this object */ WORD id; /* Hosting volume mount ID */ BYTE attr; /* Object attribute */ BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */ DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ FSIZE_t objsize; /* Object size (valid when sclust != 0) */ #if FF_FS_EXFAT DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ #endif #if FF_FS_LOCK UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ #endif } FFOBJID; /* File object structure (FIL) */ typedef struct { FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ BYTE flag; /* File status flags */ BYTE err; /* Abort flag (error code) */ FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ #if !FF_FS_READONLY DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ #endif #if FF_USE_FASTSEEK DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ #endif #if !FF_FS_TINY BYTE buf[FF_MAX_SS]; /* File private data read/write window */ #endif } FIL; /* Directory object structure (FF_DIR) */ typedef struct { FFOBJID obj; /* Object identifier */ DWORD dptr; /* Current read/write offset */ DWORD clust; /* Current cluster */ DWORD sect; /* Current sector (0:Read operation has terminated) */ BYTE* dir; /* Pointer to the directory item in the win[] */ BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ #if FF_USE_LFN DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ #endif #if FF_USE_FIND const TCHAR* pat; /* Pointer to the name matching pattern */ #endif } FF_DIR; /* File information structure (FILINFO) */ typedef struct { FSIZE_t fsize; /* File size */ WORD fdate; /* Modified date */ WORD ftime; /* Modified time */ BYTE fattrib; /* File attribute */ #if FF_USE_LFN TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */ TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ #else TCHAR fname[12 + 1]; /* File name */ #endif } FILINFO; /* File function return code (FRESULT) */ typedef enum { FR_OK = 0, /* (0) Succeeded */ FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ FR_INT_ERR, /* (2) Assertion failed */ FR_NOT_READY, /* (3) The physical drive cannot work */ FR_NO_FILE, /* (4) Could not find the file */ FR_NO_PATH, /* (5) Could not find the path */ FR_INVALID_NAME, /* (6) The path name format is invalid */ FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ FR_EXIST, /* (8) Access denied due to prohibited access */ FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ FR_NOT_ENABLED, /* (12) The volume has no work area */ FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ } FRESULT; /*--------------------------------------------------------------*/ /* FatFs module application interface */ FRESULT f_open (FATFS *fs, FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ FRESULT f_close (FIL* fp); /* Close an open file object */ FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ FRESULT f_truncate (FIL* fp); /* Truncate the file */ FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ FRESULT f_opendir (FATFS *fs, FF_DIR* dp, const TCHAR* path); /* Open a directory */ FRESULT f_closedir (FF_DIR* dp); /* Close an open directory */ FRESULT f_readdir (FF_DIR* dp, FILINFO* fno); /* Read a directory item */ FRESULT f_findfirst (FF_DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ FRESULT f_findnext (FF_DIR* dp, FILINFO* fno); /* Find next file */ FRESULT f_mkdir (FATFS *fs, const TCHAR* path); /* Create a sub directory */ FRESULT f_unlink (FATFS *fs, const TCHAR* path); /* Delete an existing file or directory */ FRESULT f_rename (FATFS *fs, const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ FRESULT f_stat (FATFS *fs, const TCHAR* path, FILINFO* fno); /* Get file status */ FRESULT f_chmod (FATFS *fs, const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ FRESULT f_utime (FATFS *fs, const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ FRESULT f_chdir (FATFS *fs, const TCHAR* path); /* Change current directory */ FRESULT f_getcwd (FATFS *fs, TCHAR* buff, UINT len); /* Get current directory */ FRESULT f_getfree (FATFS *fs, DWORD* nclst); /* Get number of free clusters on the drive */ FRESULT f_getlabel (FATFS *fs, TCHAR* label, DWORD* vsn); /* Get volume label */ FRESULT f_setlabel (FATFS *fs, const TCHAR* label); /* Set volume label */ FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ FRESULT f_mount (FATFS* fs); /* Mount/Unmount a logical drive */ FRESULT f_umount (FATFS* fs); /* Unmount a logical drive */ FRESULT f_mkfs (FATFS *fs, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ FRESULT f_fdisk (void *pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ FRESULT f_setcp (WORD cp); /* Set current code page */ #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) #define f_error(fp) ((fp)->err) #define f_tell(fp) ((fp)->fptr) #define f_size(fp) ((fp)->obj.objsize) #define f_rewind(fp) f_lseek((fp), 0) #define f_rewinddir(dp) f_readdir((dp), 0) #define f_rmdir(path) f_unlink(path) #define f_unmount(path) f_mount(0, path, 0) #ifndef EOF #define EOF (-1) #endif /*--------------------------------------------------------------*/ /* Additional user defined functions */ /* RTC function */ #if !FF_FS_READONLY && !FF_FS_NORTC DWORD get_fattime (void); #endif /* LFN support functions */ #if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ #endif #if FF_USE_LFN == 3 /* Dynamic memory allocation */ void* ff_memalloc (UINT msize); /* Allocate memory block */ void ff_memfree (void* mblock); /* Free memory block */ #endif /* Sync functions */ #if FF_FS_REENTRANT int ff_cre_syncobj (FATFS *fatfs, FF_SYNC_t* sobj); /* Create a sync object */ int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ #endif /*--------------------------------------------------------------*/ /* Flags and offset address */ /* File access mode and open method flags (3rd argument of f_open) */ #define FA_READ 0x01 #define FA_WRITE 0x02 #define FA_OPEN_EXISTING 0x00 #define FA_CREATE_NEW 0x04 #define FA_CREATE_ALWAYS 0x08 #define FA_OPEN_ALWAYS 0x10 #define FA_OPEN_APPEND 0x30 /* Fast seek controls (2nd argument of f_lseek) */ #define CREATE_LINKMAP ((FSIZE_t)0 - 1) /* Format options (2nd argument of f_mkfs) */ #define FM_FAT 0x01 #define FM_FAT32 0x02 #define FM_EXFAT 0x04 #define FM_ANY 0x07 #define FM_SFD 0x08 /* Filesystem type (FATFS.fs_type) */ #define FS_FAT12 1 #define FS_FAT16 2 #define FS_FAT32 3 #define FS_EXFAT 4 /* File attribute bits for directory entry (FILINFO.fattrib) */ #define AM_RDO 0x01 /* Read only */ #define AM_HID 0x02 /* Hidden */ #define AM_SYS 0x04 /* System */ #define AM_DIR 0x10 /* Directory */ #define AM_ARC 0x20 /* Archive */ #ifdef __cplusplus } #endif #endif /* FF_DEFINED */ micropython-1.12/lib/oofatfs/ffconf.h000066400000000000000000000332341357706137100176500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Original file from: * FatFs - FAT file system module configuration file R0.13c (C)ChaN, 2018 * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" /*---------------------------------------------------------------------------/ / FatFs Functional Configurations /---------------------------------------------------------------------------*/ #define FFCONF_DEF 86604 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations /---------------------------------------------------------------------------*/ #define FF_FS_READONLY 0 /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) / Read-only configuration removes writing API functions, f_write(), f_sync(), / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() / and optional writing functions as well. */ #define FF_FS_MINIMIZE 0 /* This option defines minimization level to remove some basic API functions. / / 0: Basic functions are fully enabled. / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() / are removed. / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. / 3: f_lseek() function is removed in addition to 2. */ #define FF_USE_STRFUNC 0 /* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). / / 0: Disable string functions. / 1: Enable without LF-CRLF conversion. / 2: Enable with LF-CRLF conversion. */ #define FF_USE_FIND 0 /* This option switches filtered directory read functions, f_findfirst() and / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ #define FF_USE_MKFS 1 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ #define FF_USE_FASTSEEK 0 /* This option switches fast seek function. (0:Disable or 1:Enable) */ #define FF_USE_EXPAND 0 /* This option switches f_expand function. (0:Disable or 1:Enable) */ #define FF_USE_CHMOD 1 /* This option switches attribute manipulation functions, f_chmod() and f_utime(). / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ #ifdef MICROPY_FATFS_USE_LABEL #define FF_USE_LABEL (MICROPY_FATFS_USE_LABEL) #else #define FF_USE_LABEL 0 #endif /* This option switches volume label functions, f_getlabel() and f_setlabel(). / (0:Disable or 1:Enable) */ #define FF_USE_FORWARD 0 /* This option switches f_forward() function. (0:Disable or 1:Enable) */ /*---------------------------------------------------------------------------/ / Locale and Namespace Configurations /---------------------------------------------------------------------------*/ #ifdef MICROPY_FATFS_LFN_CODE_PAGE #define FF_CODE_PAGE MICROPY_FATFS_LFN_CODE_PAGE #else #define FF_CODE_PAGE 437 #endif /* This option specifies the OEM code page to be used on the target system. / Incorrect code page setting can cause a file open failure. / / 437 - U.S. / 720 - Arabic / 737 - Greek / 771 - KBL / 775 - Baltic / 850 - Latin 1 / 852 - Latin 2 / 855 - Cyrillic / 857 - Turkish / 860 - Portuguese / 861 - Icelandic / 862 - Hebrew / 863 - Canadian French / 864 - Arabic / 865 - Nordic / 866 - Russian / 869 - Greek 2 / 932 - Japanese (DBCS) / 936 - Simplified Chinese (DBCS) / 949 - Korean (DBCS) / 950 - Traditional Chinese (DBCS) / 0 - Include all code pages above and configured by f_setcp() */ #ifdef MICROPY_FATFS_ENABLE_LFN #define FF_USE_LFN (MICROPY_FATFS_ENABLE_LFN) #else #define FF_USE_LFN 0 #endif #ifdef MICROPY_FATFS_MAX_LFN #define FF_MAX_LFN (MICROPY_FATFS_MAX_LFN) #else #define FF_MAX_LFN 255 #endif /* The FF_USE_LFN switches the support for LFN (long file name). / / 0: Disable LFN. FF_MAX_LFN has no effect. / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. / 2: Enable LFN with dynamic working buffer on the STACK. / 3: Enable LFN with dynamic working buffer on the HEAP. / / To enable the LFN, ffunicode.c needs to be added to the project. The LFN function / requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and / additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. / The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can / be in range of 12 to 255. It is recommended to be set 255 to fully support LFN / specification. / When use stack for the working buffer, take care on stack overflow. When use heap / memory for the working buffer, memory management functions, ff_memalloc() and / ff_memfree() in ffsystem.c, need to be added to the project. */ #define FF_LFN_UNICODE 0 /* This option switches the character encoding on the API when LFN is enabled. / / 0: ANSI/OEM in current CP (TCHAR = char) / 1: Unicode in UTF-16 (TCHAR = WCHAR) / 2: Unicode in UTF-8 (TCHAR = char) / 3: Unicode in UTF-32 (TCHAR = DWORD) / / Also behavior of string I/O functions will be affected by this option. / When LFN is not enabled, this option has no effect. */ #define FF_LFN_BUF 255 #define FF_SFN_BUF 12 /* This set of options defines size of file name members in the FILINFO structure / which is used to read out directory items. These values should be suffcient for / the file names to read. The maximum possible length of the read file name depends / on character encoding. When LFN is not enabled, these options have no effect. */ #define FF_STRF_ENCODE 3 /* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(), / f_putc(), f_puts and f_printf() convert the character encoding in it. / This option selects assumption of character encoding ON THE FILE to be / read/written via those functions. / / 0: ANSI/OEM in current CP / 1: Unicode in UTF-16LE / 2: Unicode in UTF-16BE / 3: Unicode in UTF-8 */ #ifdef MICROPY_FATFS_RPATH #define FF_FS_RPATH (MICROPY_FATFS_RPATH) #else #define FF_FS_RPATH 0 #endif /* This option configures support for relative path. / / 0: Disable relative path and remove related functions. / 1: Enable relative path. f_chdir() and f_chdrive() are available. / 2: f_getcwd() function is available in addition to 1. */ /*---------------------------------------------------------------------------/ / Drive/Volume Configurations /---------------------------------------------------------------------------*/ #define FF_VOLUMES 1 /* Number of volumes (logical drives) to be used. (1-10) */ #define FF_STR_VOLUME_ID 0 #define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each / logical drives. Number of items must not be less than FF_VOLUMES. Valid / characters for the volume ID strings are A-Z, a-z and 0-9, however, they are / compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is / not defined, a user defined volume string table needs to be defined as: / / const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... */ #ifdef MICROPY_FATFS_MULTI_PARTITION #define FF_MULTI_PARTITION (MICROPY_FATFS_MULTI_PARTITION) #else #define FF_MULTI_PARTITION 0 #endif /* This option switches support for multiple volumes on the physical drive. / By default (0), each logical drive number is bound to the same physical drive / number and only an FAT volume found on the physical drive will be mounted. / When this function is enabled (1), each logical drive number can be bound to / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() / funciton will be available. */ #define FF_MIN_SS 512 #ifdef MICROPY_FATFS_MAX_SS #define FF_MAX_SS (MICROPY_FATFS_MAX_SS) #else #define FF_MAX_SS 512 #endif /* This set of options configures the range of sector size to be supported. (512, / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and / harddisk. But a larger value may be required for on-board flash memory and some / type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured / for variable sector size mode and disk_ioctl() function needs to implement / GET_SECTOR_SIZE command. */ #define FF_USE_TRIM 0 /* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) / To enable Trim function, also CTRL_TRIM command should be implemented to the / disk_ioctl() function. */ #define FF_FS_NOFSINFO 0 /* If you need to know correct free space on the FAT32 volume, set bit 0 of this / option, and f_getfree() function at first time after volume mount will force / a full FAT scan. Bit 1 controls the use of last allocated cluster number. / / bit0=0: Use free cluster count in the FSINFO if available. / bit0=1: Do not trust free cluster count in the FSINFO. / bit1=0: Use last allocated cluster number in the FSINFO if available. / bit1=1: Do not trust last allocated cluster number in the FSINFO. */ /*---------------------------------------------------------------------------/ / System Configurations /---------------------------------------------------------------------------*/ #define FF_FS_TINY 1 /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) / At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. / Instead of private sector buffer eliminated from the file object, common sector / buffer in the filesystem object (FATFS) is used for the file data transfer. */ #ifdef MICROPY_FATFS_EXFAT #define FF_FS_EXFAT (MICROPY_FATFS_EXFAT) #else #define FF_FS_EXFAT 0 #endif /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) / To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) / Note that enabling exFAT discards ANSI C (C89) compatibility. */ #ifdef MICROPY_FATFS_NORTC #define FF_FS_NORTC (MICROPY_FATFS_NORTC) #else #define FF_FS_NORTC 0 #endif #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 #define FF_NORTC_YEAR 2018 /* The option FF_FS_NORTC switches timestamp functiton. If the system does not have / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable / the timestamp function. Every object modified by FatFs will have a fixed timestamp / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be / added to the project to read current time form real-time clock. FF_NORTC_MON, / FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. / These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ #define FF_FS_LOCK 0 /* The option FF_FS_LOCK switches file lock function to control duplicated file open / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY / is 1. / / 0: Disable file lock function. To avoid volume corruption, application program / should avoid illegal open, remove and rename to the open objects. / >0: Enable file lock function. The value defines how many files/sub-directories / can be opened simultaneously under file lock control. Note that the file / lock control is independent of re-entrancy. */ #ifdef MICROPY_FATFS_REENTRANT #define FF_FS_REENTRANT (MICROPY_FATFS_REENTRANT) #else #define FF_FS_REENTRANT 0 #endif // milliseconds #ifdef MICROPY_FATFS_TIMEOUT #define FF_FS_TIMEOUT (MICROPY_FATFS_TIMEOUT) #else #define FF_FS_TIMEOUT 1000 #endif #ifdef MICROPY_FATFS_SYNC_T #define FF_SYNC_t MICROPY_FATFS_SYNC_T #else #define FF_SYNC_t HANDLE #endif /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs / module itself. Note that regardless of this option, file access to different / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() / and f_fdisk() function, are always not re-entrant. Only file/directory access / to the same volume is under control of this function. / / 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. / 1: Enable re-entrancy. Also user provided synchronization handlers, / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() / function, must be added to the project. Samples are available in / option/syscall.c. / / The FF_FS_TIMEOUT defines timeout period in unit of time tick. / The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be / included somewhere in the scope of ff.h. */ /*--- End of configuration options ---*/ micropython-1.12/lib/oofatfs/ffunicode.c000066400000000000000000001042201357706137100203360ustar00rootroot00000000000000/*------------------------------------------------------------------------*/ /* Unicode handling functions for FatFs R0.13c */ /*------------------------------------------------------------------------*/ /* This module will occupy a huge memory in the .const section when the / / FatFs is configured for LFN with DBCS. If the system has any Unicode / / utilitiy for the code conversion, this module should be modified to use / / that function to avoid silly memory consumption. / /-------------------------------------------------------------------------*/ /* / Copyright (C) 2018, ChaN, all right reserved. / / FatFs module is an open source software. Redistribution and use of FatFs in / source and binary forms, with or without modification, are permitted provided / that the following condition is met: / / 1. Redistributions of source code must retain the above copyright notice, / this condition and the following disclaimer. / / This software is provided by the copyright holder and contributors "AS IS" / and any warranties related to this software are DISCLAIMED. / The copyright owner or contributors be NOT LIABLE for any damages caused / by use of this software. */ #include "ff.h" #if FF_USE_LFN /* This module will be blanked at non-LFN configuration */ #if FF_DEFINED != 86604 /* Revision ID */ #error Wrong include file (ff.h). #endif #define MERGE2(a, b) a ## b #define CVTBL(tbl, cp) MERGE2(tbl, cp) /*------------------------------------------------------------------------*/ /* Code Conversion Tables */ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0 static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0 static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0 static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0 static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0 static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0 static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0 static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0 static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0 static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0 static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0 static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0 static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0 static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0 static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F, 0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, 0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9, 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1, 0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000 }; #endif #if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0 static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0 static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 }; #endif #if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0 static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384, 0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0 }; #endif /*------------------------------------------------------------------------*/ /* OEM <==> Unicode conversions for static code page configuration */ /* SBCS fixed code page */ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900 WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ DWORD uni, /* UTF-16 encoded character to be converted */ WORD cp /* Code page for the conversion */ ) { WCHAR c = 0; const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); if (uni < 0x80) { /* ASCII? */ c = (WCHAR)uni; } else { /* Non-ASCII */ if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ for (c = 0; c < 0x80 && uni != p[c]; c++) ; c = (c + 0x80) & 0xFF; } } return c; } WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ WCHAR oem, /* OEM code to be converted */ WORD cp /* Code page for the conversion */ ) { WCHAR c = 0; const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); if (oem < 0x80) { /* ASCII? */ c = oem; } else { /* Extended char */ if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ if (oem < 0x100) c = p[oem - 0x80]; } } return c; } #endif /*------------------------------------------------------------------------*/ /* OEM <==> Unicode conversions for static code page configuration */ /* DBCS fixed code page */ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE >= 900 WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ DWORD uni, /* UTF-16 encoded character to be converted */ WORD cp /* Code page for the conversion */ ) { const WCHAR *p; WCHAR c = 0, uc; UINT i = 0, n, li, hi; if (uni < 0x80) { /* ASCII? */ c = (WCHAR)uni; } else { /* Non-ASCII */ if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ uc = (WCHAR)uni; p = CVTBL(uni2oem, FF_CODE_PAGE); hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; li = 0; for (n = 16; n; n--) { i = li + (hi - li) / 2; if (uc == p[i * 2]) break; if (uc > p[i * 2]) { li = i; } else { hi = i; } } if (n != 0) c = p[i * 2 + 1]; } } return c; } WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ WCHAR oem, /* OEM code to be converted */ WORD cp /* Code page for the conversion */ ) { const WCHAR *p; WCHAR c = 0; UINT i = 0, n, li, hi; if (oem < 0x80) { /* ASCII? */ c = oem; } else { /* Extended char */ if (cp == FF_CODE_PAGE) { /* Is it valid code page? */ p = CVTBL(oem2uni, FF_CODE_PAGE); hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1; li = 0; for (n = 16; n; n--) { i = li + (hi - li) / 2; if (oem == p[i * 2]) break; if (oem > p[i * 2]) { li = i; } else { hi = i; } } if (n != 0) c = p[i * 2 + 1]; } } return c; } #endif /*------------------------------------------------------------------------*/ /* OEM <==> Unicode conversions for dynamic code page configuration */ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE == 0 static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0}; static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ DWORD uni, /* UTF-16 encoded character to be converted */ WORD cp /* Code page for the conversion */ ) { const WCHAR *p; WCHAR c = 0, uc; UINT i, n, li, hi; if (uni < 0x80) { /* ASCII? */ c = (WCHAR)uni; } else { /* Non-ASCII */ if (uni < 0x10000) { /* Is it in BMP? */ uc = (WCHAR)uni; p = 0; if (cp < 900) { /* SBCS */ for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */ p = cp_table[i]; if (p) { /* Is it valid code page ? */ for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */ c = (c + 0x80) & 0xFF; } } else { /* DBCS */ switch (cp) { /* Get conversion table */ case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break; case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break; case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break; case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break; } if (p) { /* Is it valid code page? */ li = 0; for (n = 16; n; n--) { /* Find OEM code */ i = li + (hi - li) / 2; if (uc == p[i * 2]) break; if (uc > p[i * 2]) { li = i; } else { hi = i; } } if (n != 0) c = p[i * 2 + 1]; } } } } return c; } WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */ WORD cp /* Code page for the conversion */ ) { const WCHAR *p; WCHAR c = 0; UINT i, n, li, hi; if (oem < 0x80) { /* ASCII? */ c = oem; } else { /* Extended char */ p = 0; if (cp < 900) { /* SBCS */ for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ p = cp_table[i]; if (p) { /* Is it a valid CP ? */ if (oem < 0x100) c = p[oem - 0x80]; } } else { /* DBCS */ switch (cp) { case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break; case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break; case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break; case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break; } if (p) { li = 0; for (n = 16; n; n--) { i = li + (hi - li) / 2; if (oem == p[i * 2]) break; if (oem > p[i * 2]) { li = i; } else { hi = i; } } if (n != 0) c = p[i * 2 + 1]; } } } return c; } #endif /*------------------------------------------------------------------------*/ /* Unicode up-case conversion */ /*------------------------------------------------------------------------*/ DWORD ff_wtoupper ( /* Returns up-converted code point */ DWORD uni /* Unicode code point to be up-converted */ ) { const WORD *p; WORD uc, bc, nc, cmd; static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ /* Basic Latin */ 0x0061,0x031A, /* Latin-1 Supplement */ 0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178, /* Latin Extended-A */ 0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106, /* Latin Extended-B */ 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA, 0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128, 0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A, /* IPA Extensions */ 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7, /* Greek, Coptic */ 0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311, 0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118, 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, /* Cyrillic */ 0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144, /* Armenian */ 0x0561,0x0426, 0x0000 /* EOT */ }; static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */ /* Phonetic Extensions */ 0x1D7D,0x0001,0x2C63, /* Latin Extended Additional */ 0x1E00,0x0196, 0x1EA0,0x015A, /* Greek Extended */ 0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606, 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608, 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, 0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, 0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF3,0x0001,0x1FFC, /* Letterlike Symbols */ 0x214E,0x0001,0x2132, /* Number forms */ 0x2170,0x0210, 0x2184,0x0001,0x2183, /* Enclosed Alphanumerics */ 0x24D0,0x051A, 0x2C30,0x042F, /* Latin Extended-C */ 0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102, /* Coptic */ 0x2C80,0x0164, /* Georgian Supplement */ 0x2D00,0x0826, /* Full-width */ 0xFF41,0x031A, 0x0000 /* EOT */ }; if (uni < 0x10000) { /* Is it in BMP? */ uc = (WORD)uni; p = uc < 0x1000 ? cvt1 : cvt2; for (;;) { bc = *p++; /* Get the block base */ if (bc == 0 || uc < bc) break; /* Not matched? */ nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ if (uc < bc + nc) { /* In the block? */ switch (cmd) { case 0: uc = p[uc - bc]; break; /* Table conversion */ case 1: uc -= (uc - bc) & 1; break; /* Case pairs */ case 2: uc -= 16; break; /* Shift -16 */ case 3: uc -= 32; break; /* Shift -32 */ case 4: uc -= 48; break; /* Shift -48 */ case 5: uc -= 26; break; /* Shift -26 */ case 6: uc += 8; break; /* Shift +8 */ case 7: uc -= 80; break; /* Shift -80 */ case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */ } break; } if (cmd == 0) p += nc; /* Skip table if needed */ } uni = uc; } return uni; } #endif /* #if FF_USE_LFN */ micropython-1.12/lib/stm32lib/000077500000000000000000000000001357706137100162275ustar00rootroot00000000000000micropython-1.12/lib/timeutils/000077500000000000000000000000001357706137100166075ustar00rootroot00000000000000micropython-1.12/lib/timeutils/timeutils.c000066400000000000000000000150021357706137100207700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "lib/timeutils/timeutils.h" // LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately // after Feb 29. We calculate seconds as a signed integer relative to that. // // Our timebase is relative to 2000-01-01. #define LEAPOCH ((31 + 29) * 86400) #define DAYS_PER_400Y (365*400 + 97) #define DAYS_PER_100Y (365*100 + 24) #define DAYS_PER_4Y (365*4 + 1) STATIC const uint16_t days_since_jan1[]= { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; bool timeutils_is_leap_year(mp_uint_t year) { return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; } // month is one based mp_uint_t timeutils_days_in_month(mp_uint_t year, mp_uint_t month) { mp_uint_t mdays = days_since_jan1[month] - days_since_jan1[month - 1]; if (month == 2 && timeutils_is_leap_year(year)) { mdays++; } return mdays; } // compute the day of the year, between 1 and 366 // month should be between 1 and 12, date should start at 1 mp_uint_t timeutils_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) { mp_uint_t yday = days_since_jan1[month - 1] + date; if (month >= 3 && timeutils_is_leap_year(year)) { yday += 1; } return yday; } void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t, timeutils_struct_time_t *tm) { // The following algorithm was adapted from musl's __secs_to_tm and adapted // for differences in MicroPython's timebase. mp_int_t seconds = t - LEAPOCH; mp_int_t days = seconds / 86400; seconds %= 86400; if (seconds < 0) { seconds += 86400; days -= 1; } tm->tm_hour = seconds / 3600; tm->tm_min = seconds / 60 % 60; tm->tm_sec = seconds % 60; mp_int_t wday = (days + 2) % 7; // Mar 1, 2000 was a Wednesday (2) if (wday < 0) { wday += 7; } tm->tm_wday = wday; mp_int_t qc_cycles = days / DAYS_PER_400Y; days %= DAYS_PER_400Y; if (days < 0) { days += DAYS_PER_400Y; qc_cycles--; } mp_int_t c_cycles = days / DAYS_PER_100Y; if (c_cycles == 4) { c_cycles--; } days -= (c_cycles * DAYS_PER_100Y); mp_int_t q_cycles = days / DAYS_PER_4Y; if (q_cycles == 25) { q_cycles--; } days -= q_cycles * DAYS_PER_4Y; mp_int_t years = days / 365; if (years == 4) { years--; } days -= (years * 365); /* We will compute tm_yday at the very end mp_int_t leap = !years && (q_cycles || !c_cycles); tm->tm_yday = days + 31 + 28 + leap; if (tm->tm_yday >= 365 + leap) { tm->tm_yday -= 365 + leap; } tm->tm_yday++; // Make one based */ tm->tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles; // Note: days_in_month[0] corresponds to March STATIC const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29}; mp_int_t month; for (month = 0; days_in_month[month] <= days; month++) { days -= days_in_month[month]; } tm->tm_mon = month + 2; if (tm->tm_mon >= 12) { tm->tm_mon -= 12; tm->tm_year++; } tm->tm_mday = days + 1; // Make one based tm->tm_mon++; // Make one based tm->tm_yday = timeutils_year_day(tm->tm_year, tm->tm_mon, tm->tm_mday); } // returns the number of seconds, as an integer, since 2000-01-01 mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { return second + minute * 60 + hour * 3600 + (timeutils_year_day(year, month, date) - 1 + ((year - 2000 + 3) / 4) // add a day each 4 years starting with 2001 - ((year - 2000 + 99) / 100) // subtract a day each 100 years starting with 2001 + ((year - 2000 + 399) / 400) // add a day each 400 years starting with 2001 ) * 86400 + (year - 2000) * 31536000; } mp_uint_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday, mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { // Normalize the tuple. This allows things like: // // tm_tomorrow = list(time.localtime()) // tm_tomorrow[2] += 1 # Adds 1 to mday // tomorrow = time.mktime(tm_tomorrow) // // And not have to worry about all the weird overflows. // // You can subtract dates/times this way as well. minutes += seconds / 60; if ((seconds = seconds % 60) < 0) { seconds += 60; minutes--; } hours += minutes / 60; if ((minutes = minutes % 60) < 0) { minutes += 60; hours--; } mday += hours / 24; if ((hours = hours % 24) < 0) { hours += 24; mday--; } month--; // make month zero based year += month / 12; if ((month = month % 12) < 0) { month += 12; year--; } month++; // back to one based while (mday < 1) { if (--month == 0) { month = 12; year--; } mday += timeutils_days_in_month(year, month); } while ((mp_uint_t)mday > timeutils_days_in_month(year, month)) { mday -= timeutils_days_in_month(year, month); if (++month == 13) { month = 1; year++; } } return timeutils_seconds_since_2000(year, month, mday, hours, minutes, seconds); } micropython-1.12/lib/timeutils/timeutils.h000066400000000000000000000045061357706137100210040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H #define MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H typedef struct _timeutils_struct_time_t { uint16_t tm_year; // i.e. 2014 uint8_t tm_mon; // 1..12 uint8_t tm_mday; // 1..31 uint8_t tm_hour; // 0..23 uint8_t tm_min; // 0..59 uint8_t tm_sec; // 0..59 uint8_t tm_wday; // 0..6 0 = Monday uint16_t tm_yday; // 1..366 } timeutils_struct_time_t; bool timeutils_is_leap_year(mp_uint_t year); mp_uint_t timeutils_days_in_month(mp_uint_t year, mp_uint_t month); mp_uint_t timeutils_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date); void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t, timeutils_struct_time_t *tm); mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second); mp_uint_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday, mp_int_t hours, mp_int_t minutes, mp_int_t seconds); #endif // MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H micropython-1.12/lib/tinytest/000077500000000000000000000000001357706137100164535ustar00rootroot00000000000000micropython-1.12/lib/tinytest/README000066400000000000000000000012411357706137100173310ustar00rootroot00000000000000Tinytest is a tiny little test framework written in C by Nick Mathewson. It is distributed under the 3-clause BSD license. You can use it in your own programs so long as you follow the license's conditions. It's been tested on Windows, Mac, and many of the free Unixes. It knows how to fork before running certain tests, and it makes text-mode output in a format I like. For info on how to use it, check out tinytest_demo.c. You can get the latest version using Git, by pulling from git://github.com/nmathewson/tinytest.git Patches are welcome. Patches that turn this from tinytest to hugetest will not be applied. If you want a huge test framework, use CUnit. micropython-1.12/lib/tinytest/tinytest.c000066400000000000000000000275511357706137100205140ustar00rootroot00000000000000/* tinytest.c -- Copyright 2009-2012 Nick Mathewson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce 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 the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef TINYTEST_LOCAL #include "tinytest_local.h" #endif #include #include #include #include #ifndef NO_FORKING #ifdef _WIN32 #include #else #include #include #include #endif #if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) #if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070) /* Workaround for a stupid bug in OSX 10.6 */ #define FORK_BREAKS_GCOV #include #endif #endif #endif /* !NO_FORKING */ #ifndef __GNUC__ #define __attribute__(x) #endif #include "tinytest.h" #include "tinytest_macros.h" #define LONGEST_TEST_NAME 16384 static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/ static int n_ok = 0; /**< Number of tests that have passed */ static int n_bad = 0; /**< Number of tests that have failed. */ static int n_skipped = 0; /**< Number of tests that have been skipped. */ static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/ static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */ static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */ const char *verbosity_flag = ""; const struct testlist_alias_t *cfg_aliases=NULL; enum outcome { SKIP=2, OK=1, FAIL=0 }; static enum outcome cur_test_outcome = 0; const char *cur_test_prefix = NULL; /**< prefix of the current test group */ /** Name of the current test, if we haven't logged is yet. Used for --quiet */ const char *cur_test_name = NULL; #ifdef _WIN32 /* Copy of argv[0] for win32. */ static char commandname[MAX_PATH+1]; #endif static void usage(struct testgroup_t *groups, int list_groups) __attribute__((noreturn)); static int process_test_option(struct testgroup_t *groups, const char *test); static enum outcome testcase_run_bare_(const struct testcase_t *testcase) { void *env = NULL; int outcome; if (testcase->setup) { env = testcase->setup->setup_fn(testcase); if (!env) return FAIL; else if (env == (void*)TT_SKIP) return SKIP; } cur_test_outcome = OK; testcase->fn(env); outcome = cur_test_outcome; if (testcase->setup) { if (testcase->setup->cleanup_fn(testcase, env) == 0) outcome = FAIL; } return outcome; } #define MAGIC_EXITCODE 42 #ifndef NO_FORKING static enum outcome testcase_run_forked_(const struct testgroup_t *group, const struct testcase_t *testcase) { #ifdef _WIN32 /* Fork? On Win32? How primitive! We'll do what the smart kids do: we'll invoke our own exe (whose name we recall from the command line) with a command line that tells it to run just the test we want, and this time without forking. (No, threads aren't an option. The whole point of forking is to share no state between tests.) */ int ok; char buffer[LONGEST_TEST_NAME+256]; STARTUPINFOA si; PROCESS_INFORMATION info; DWORD exitcode; if (!in_tinytest_main) { printf("\nERROR. On Windows, testcase_run_forked_ must be" " called from within tinytest_main.\n"); abort(); } if (opt_verbosity>0) printf("[forking] "); snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", commandname, verbosity_flag, group->prefix, testcase->name); memset(&si, 0, sizeof(si)); memset(&info, 0, sizeof(info)); si.cb = sizeof(si); ok = CreateProcessA(commandname, buffer, NULL, NULL, 0, 0, NULL, NULL, &si, &info); if (!ok) { printf("CreateProcess failed!\n"); return 0; } WaitForSingleObject(info.hProcess, INFINITE); GetExitCodeProcess(info.hProcess, &exitcode); CloseHandle(info.hProcess); CloseHandle(info.hThread); if (exitcode == 0) return OK; else if (exitcode == MAGIC_EXITCODE) return SKIP; else return FAIL; #else int outcome_pipe[2]; pid_t pid; (void)group; if (pipe(outcome_pipe)) perror("opening pipe"); if (opt_verbosity>0) printf("[forking] "); pid = fork(); #ifdef FORK_BREAKS_GCOV vproc_transaction_begin(0); #endif if (!pid) { /* child. */ int test_r, write_r; char b[1]; close(outcome_pipe[0]); test_r = testcase_run_bare_(testcase); assert(0<=(int)test_r && (int)test_r<=2); b[0] = "NYS"[test_r]; write_r = (int)write(outcome_pipe[1], b, 1); if (write_r != 1) { perror("write outcome to pipe"); exit(1); } exit(0); return FAIL; /* unreachable */ } else { /* parent */ int status, r; char b[1]; /* Close this now, so that if the other side closes it, * our read fails. */ close(outcome_pipe[1]); r = (int)read(outcome_pipe[0], b, 1); if (r == 0) { printf("[Lost connection!] "); return 0; } else if (r != 1) { perror("read outcome from pipe"); } waitpid(pid, &status, 0); close(outcome_pipe[0]); return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL); } #endif } #endif /* !NO_FORKING */ int testcase_run_one(const struct testgroup_t *group, const struct testcase_t *testcase) { enum outcome outcome; if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) { if (opt_verbosity>0) printf("%s%s: %s\n", group->prefix, testcase->name, (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED"); ++n_skipped; return SKIP; } if (opt_verbosity>0 && !opt_forked) { printf("%s%s: ", group->prefix, testcase->name); } else { if (opt_verbosity==0) printf("."); cur_test_prefix = group->prefix; cur_test_name = testcase->name; } #ifndef NO_FORKING if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) { outcome = testcase_run_forked_(group, testcase); } else { #else { #endif outcome = testcase_run_bare_(testcase); } if (outcome == OK) { ++n_ok; if (opt_verbosity>0 && !opt_forked) puts(opt_verbosity==1?"OK":""); } else if (outcome == SKIP) { ++n_skipped; if (opt_verbosity>0 && !opt_forked) puts("SKIPPED"); } else { ++n_bad; if (!opt_forked) printf("\n [%s FAILED]\n", testcase->name); } if (opt_forked) { exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1)); return 1; /* unreachable */ } else { return (int)outcome; } } int tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag) { int i, j; size_t length = LONGEST_TEST_NAME; char fullname[LONGEST_TEST_NAME]; int found=0; if (strstr(arg, "..")) length = strstr(arg,"..")-arg; for (i=0; groups[i].prefix; ++i) { for (j=0; groups[i].cases[j].name; ++j) { struct testcase_t *testcase = &groups[i].cases[j]; snprintf(fullname, sizeof(fullname), "%s%s", groups[i].prefix, testcase->name); if (!flag) { /* Hack! */ printf(" %s", fullname); if (testcase->flags & TT_OFF_BY_DEFAULT) puts(" (Off by default)"); else if (testcase->flags & TT_SKIP) puts(" (DISABLED)"); else puts(""); } if (!strncmp(fullname, arg, length)) { if (set) testcase->flags |= flag; else testcase->flags &= ~flag; ++found; } } } return found; } static void usage(struct testgroup_t *groups, int list_groups) { puts("Options are: [--verbose|--quiet|--terse] [--no-fork]"); puts(" Specify tests by name, or using a prefix ending with '..'"); puts(" To skip a test, prefix its name with a colon."); puts(" To enable a disabled test, prefix its name with a plus."); puts(" Use --list-tests for a list of tests."); if (list_groups) { puts("Known tests are:"); tinytest_set_flag_(groups, "..", 1, 0); } exit(0); } static int process_test_alias(struct testgroup_t *groups, const char *test) { int i, j, n, r; for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) { if (!strcmp(cfg_aliases[i].name, test)) { n = 0; for (j = 0; cfg_aliases[i].tests[j]; ++j) { r = process_test_option(groups, cfg_aliases[i].tests[j]); if (r<0) return -1; n += r; } return n; } } printf("No such test alias as @%s!",test); return -1; } static int process_test_option(struct testgroup_t *groups, const char *test) { int flag = TT_ENABLED_; int n = 0; if (test[0] == '@') { return process_test_alias(groups, test + 1); } else if (test[0] == ':') { ++test; flag = TT_SKIP; } else if (test[0] == '+') { ++test; ++n; if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) { printf("No such test as %s!\n", test); return -1; } } else { ++n; } if (!tinytest_set_flag_(groups, test, 1, flag)) { printf("No such test as %s!\n", test); return -1; } return n; } void tinytest_set_aliases(const struct testlist_alias_t *aliases) { cfg_aliases = aliases; } int tinytest_main(int c, const char **v, struct testgroup_t *groups) { int i, j, n=0; #ifdef _WIN32 const char *sp = strrchr(v[0], '.'); const char *extension = ""; if (!sp || stricmp(sp, ".exe")) extension = ".exe"; /* Add an exe so CreateProcess will work */ snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension); commandname[MAX_PATH]='\0'; #endif for (i=1; i= 1) printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped); return (n_bad == 0) ? 0 : 1; } int tinytest_get_verbosity_(void) { return opt_verbosity; } void tinytest_set_test_failed_(void) { if (opt_verbosity <= 0 && cur_test_name) { if (opt_verbosity==0) puts(""); printf("%s%s: ", cur_test_prefix, cur_test_name); cur_test_name = NULL; } cur_test_outcome = 0; } void tinytest_set_test_skipped_(void) { if (cur_test_outcome==OK) cur_test_outcome = SKIP; } micropython-1.12/lib/tinytest/tinytest.h000066400000000000000000000101601357706137100205050ustar00rootroot00000000000000/* tinytest.h -- Copyright 2009-2012 Nick Mathewson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce 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 the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TINYTEST_H_INCLUDED_ #define TINYTEST_H_INCLUDED_ /** Flag for a test that needs to run in a subprocess. */ #define TT_FORK (1<<0) /** Runtime flag for a test we've decided to skip. */ #define TT_SKIP (1<<1) /** Internal runtime flag for a test we've decided to run. */ #define TT_ENABLED_ (1<<2) /** Flag for a test that's off by default. */ #define TT_OFF_BY_DEFAULT (1<<3) /** If you add your own flags, make them start at this point. */ #define TT_FIRST_USER_FLAG (1<<4) typedef void (*testcase_fn)(void *); struct testcase_t; /** Functions to initialize/teardown a structure for a testcase. */ struct testcase_setup_t { /** Return a new structure for use by a given testcase. */ void *(*setup_fn)(const struct testcase_t *); /** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */ int (*cleanup_fn)(const struct testcase_t *, void *); }; /** A single test-case that you can run. */ struct testcase_t { const char *name; /**< An identifier for this case. */ testcase_fn fn; /**< The function to run to implement this case. */ unsigned long flags; /**< Bitfield of TT_* flags. */ const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/ void *setup_data; /**< Extra data usable by setup function */ }; #define END_OF_TESTCASES { NULL, NULL, 0, NULL, NULL } /** A group of tests that are selectable together. */ struct testgroup_t { const char *prefix; /**< Prefix to prepend to testnames. */ struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */ }; #define END_OF_GROUPS { NULL, NULL} struct testlist_alias_t { const char *name; const char **tests; }; #define END_OF_ALIASES { NULL, NULL } /** Implementation: called from a test to indicate failure, before logging. */ void tinytest_set_test_failed_(void); /** Implementation: called from a test to indicate that we're skipping. */ void tinytest_set_test_skipped_(void); /** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */ int tinytest_get_verbosity_(void); /** Implementation: Set a flag on tests matching a name; returns number * of tests that matched. */ int tinytest_set_flag_(struct testgroup_t *, const char *, int set, unsigned long); /** Set all tests in 'groups' matching the name 'named' to be skipped. */ #define tinytest_skip(groups, named) \ tinytest_set_flag_(groups, named, 1, TT_SKIP) /** Run a single testcase in a single group. */ int testcase_run_one(const struct testgroup_t *,const struct testcase_t *); void tinytest_set_aliases(const struct testlist_alias_t *aliases); /** Run a set of testcases from an END_OF_GROUPS-terminated array of groups, as selected from the command line. */ int tinytest_main(int argc, const char **argv, struct testgroup_t *groups); #endif micropython-1.12/lib/tinytest/tinytest_macros.h000066400000000000000000000145641357706137100220650ustar00rootroot00000000000000/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce 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 the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TINYTEST_MACROS_H_INCLUDED_ #define TINYTEST_MACROS_H_INCLUDED_ /* Helpers for defining statement-like macros */ #define TT_STMT_BEGIN do { #define TT_STMT_END } while (0) /* Redefine this if your test functions want to abort with something besides * "goto end;" */ #ifndef TT_EXIT_TEST_FUNCTION #define TT_EXIT_TEST_FUNCTION TT_STMT_BEGIN goto end; TT_STMT_END #endif /* Redefine this if you want to note success/failure in some different way. */ #ifndef TT_DECLARE #define TT_DECLARE(prefix, args) \ TT_STMT_BEGIN \ printf("\n %s %s:%d: ",prefix,__FILE__,__LINE__); \ printf args ; \ TT_STMT_END #endif /* Announce a failure. Args are parenthesized printf args. */ #define TT_GRIPE(args) TT_DECLARE("FAIL", args) /* Announce a non-failure if we're verbose. */ #define TT_BLATHER(args) \ TT_STMT_BEGIN \ if (tinytest_get_verbosity_()>1) TT_DECLARE(" OK", args); \ TT_STMT_END #define TT_DIE(args) \ TT_STMT_BEGIN \ tinytest_set_test_failed_(); \ TT_GRIPE(args); \ TT_EXIT_TEST_FUNCTION; \ TT_STMT_END #define TT_FAIL(args) \ TT_STMT_BEGIN \ tinytest_set_test_failed_(); \ TT_GRIPE(args); \ TT_STMT_END /* Fail and abort the current test for the reason in msg */ #define tt_abort_printf(msg) TT_DIE(msg) #define tt_abort_perror(op) TT_DIE(("%s: %s [%d]",(op),strerror(errno), errno)) #define tt_abort_msg(msg) TT_DIE(("%s", msg)) #define tt_abort() TT_DIE(("%s", "(Failed.)")) /* Fail but do not abort the current test for the reason in msg. */ #define tt_failprint_f(msg) TT_FAIL(msg) #define tt_fail_perror(op) TT_FAIL(("%s: %s [%d]",(op),strerror(errno), errno)) #define tt_fail_msg(msg) TT_FAIL(("%s", msg)) #define tt_fail() TT_FAIL(("%s", "(Failed.)")) /* End the current test, and indicate we are skipping it. */ #define tt_skip() \ TT_STMT_BEGIN \ tinytest_set_test_skipped_(); \ TT_EXIT_TEST_FUNCTION; \ TT_STMT_END #define tt_want_(b, msg, fail) \ TT_STMT_BEGIN \ if (!(b)) { \ tinytest_set_test_failed_(); \ TT_GRIPE(("%s",msg)); \ fail; \ } else { \ TT_BLATHER(("%s",msg)); \ } \ TT_STMT_END /* Assert b, but do not stop the test if b fails. Log msg on failure. */ #define tt_want_msg(b, msg) \ tt_want_(b, msg, ); /* Assert b and stop the test if b fails. Log msg on failure. */ #define tt_assert_msg(b, msg) \ tt_want_(b, msg, TT_EXIT_TEST_FUNCTION); /* Assert b, but do not stop the test if b fails. */ #define tt_want(b) tt_want_msg( (b), "want("#b")") /* Assert b, and stop the test if b fails. */ #define tt_assert(b) tt_assert_msg((b), "assert("#b")") #define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \ setup_block,cleanup_block,die_on_fail) \ TT_STMT_BEGIN \ type val1_ = (type)(a); \ type val2_ = (type)(b); \ int tt_status_ = (test); \ if (!tt_status_ || tinytest_get_verbosity_()>1) { \ printf_type print_; \ printf_type print1_; \ printf_type print2_; \ type value_ = val1_; \ setup_block; \ print1_ = print_; \ value_ = val2_; \ setup_block; \ print2_ = print_; \ TT_DECLARE(tt_status_?" OK":"FAIL", \ ("assert(%s): "printf_fmt" vs "printf_fmt, \ str_test, print1_, print2_)); \ print_ = print1_; \ cleanup_block; \ print_ = print2_; \ cleanup_block; \ if (!tt_status_) { \ tinytest_set_test_failed_(); \ die_on_fail ; \ } \ } \ TT_STMT_END #define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail) \ tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \ {print_=value_;},{},die_on_fail) /* Helper: assert that a op b, when cast to type. Format the values with * printf format fmt on failure. */ #define tt_assert_op_type(a,op,b,type,fmt) \ tt_assert_test_type(a,b,#a" "#op" "#b,type,(val1_ op val2_),fmt, \ TT_EXIT_TEST_FUNCTION) #define tt_int_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_), \ "%ld",TT_EXIT_TEST_FUNCTION) #define tt_uint_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ (val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION) #define tt_ptr_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ (val1_ op val2_),"%p",TT_EXIT_TEST_FUNCTION) #define tt_str_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ (strcmp(val1_,val2_) op 0),"<%s>",TT_EXIT_TEST_FUNCTION) #define tt_want_int_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_),"%ld",(void)0) #define tt_want_uint_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ (val1_ op val2_),"%lu",(void)0) #define tt_want_ptr_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ (val1_ op val2_),"%p",(void)0) #define tt_want_str_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ (strcmp(val1_,val2_) op 0),"<%s>",(void)0) #endif micropython-1.12/lib/tinyusb/000077500000000000000000000000001357706137100162655ustar00rootroot00000000000000micropython-1.12/lib/upytesthelper/000077500000000000000000000000001357706137100175055ustar00rootroot00000000000000micropython-1.12/lib/upytesthelper/upytesthelper.c000066400000000000000000000106141357706137100225700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mphal.h" #include "py/gc.h" #include "py/runtime.h" #include "py/compile.h" #include "upytesthelper.h" static const char *test_exp_output; static int test_exp_output_len, test_rem_output_len; static int test_failed; static void *heap_start, *heap_end; void upytest_set_heap(void *start, void *end) { heap_start = start; heap_end = end; } void upytest_set_expected_output(const char *output, unsigned len) { test_exp_output = output; test_exp_output_len = test_rem_output_len = len; test_failed = false; } bool upytest_is_failed(void) { if (test_failed) { return true; } #if 0 if (test_rem_output_len != 0) { printf("remaining len: %d\n", test_rem_output_len); } #endif return test_rem_output_len != 0; } // MP_PLAT_PRINT_STRN() should be redirected to this function. // It will pass-thru any content to mp_hal_stdout_tx_strn_cooked() // (the dfault value of MP_PLAT_PRINT_STRN), but will also match // it to the expected output as set by upytest_set_expected_output(). // If mismatch happens, upytest_is_failed() returns true. void upytest_output(const char *str, mp_uint_t len) { if (!test_failed) { if (len > test_rem_output_len) { test_failed = true; } else { test_failed = memcmp(test_exp_output, str, len); #if 0 if (test_failed) { printf("failed after char %u, within %d chars, res: %d\n", test_exp_output_len - test_rem_output_len, (int)len, test_failed); for (int i = 0; i < len; i++) { if (str[i] != test_exp_output[i]) { printf("%d %02x %02x\n", i, str[i], test_exp_output[i]); } } } #endif test_exp_output += len; test_rem_output_len -= len; } } mp_hal_stdout_tx_strn_cooked(str, len); } void upytest_execute_test(const char *src) { // To provide clean room for each test, interpreter and heap are // reinitialized before running each. gc_init(heap_start, heap_end); mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_init(mp_sys_argv, 0); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); mp_call_function_0(module_fun); nlr_pop(); } else { mp_obj_t exc = (mp_obj_t)nlr.ret_val; if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { // Assume that sys.exit() is called to skip the test. // TODO: That can be always true, we should set up convention to // use specific exit code as skip indicator. tinytest_set_test_skipped_(); goto end; } mp_obj_print_exception(&mp_plat_print, exc); tt_abort_msg("Uncaught exception\n"); } if (upytest_is_failed()) { tinytest_set_test_failed_(); } end: mp_deinit(); } micropython-1.12/lib/upytesthelper/upytesthelper.h000066400000000000000000000031111357706137100225670ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpconfig.h" #include "lib/tinytest/tinytest.h" #include "lib/tinytest/tinytest_macros.h" void upytest_set_heap(void *start, void *end); void upytest_set_expected_output(const char *output, unsigned len); void upytest_execute_test(const char *src); void upytest_output(const char *str, mp_uint_t len); bool upytest_is_failed(void); micropython-1.12/lib/utils/000077500000000000000000000000001357706137100157305ustar00rootroot00000000000000micropython-1.12/lib/utils/gchelper.h000066400000000000000000000027041357706137100176750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_LIB_UTILS_GCHELPER_H #define MICROPY_INCLUDED_LIB_UTILS_GCHELPER_H #include uintptr_t gc_helper_get_sp(void); uintptr_t gc_helper_get_regs_and_sp(uintptr_t *regs); #endif // MICROPY_INCLUDED_LIB_UTILS_GCHELPER_H micropython-1.12/lib/utils/gchelper_m0.s000066400000000000000000000037071357706137100203100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ .syntax unified .cpu cortex-m0 .thumb .section .text .align 2 .global gc_helper_get_regs_and_sp .type gc_helper_get_regs_and_sp, %function @ uint gc_helper_get_regs_and_sp(r0=uint regs[10]) gc_helper_get_regs_and_sp: @ store registers into given array str r4, [r0, #0] str r5, [r0, #4] str r6, [r0, #8] str r7, [r0, #12] mov r1, r8 str r1, [r0, #16] mov r1, r9 str r1, [r0, #20] mov r1, r10 str r1, [r0, #24] mov r1, r11 str r1, [r0, #28] mov r1, r12 str r1, [r0, #32] mov r1, r13 str r1, [r0, #36] @ return the sp mov r0, sp bx lr .size gc_helper_get_regs_and_sp, .-gc_helper_get_regs_and_sp micropython-1.12/lib/utils/gchelper_m3.s000066400000000000000000000041021357706137100203010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ .syntax unified .cpu cortex-m3 .thumb .section .text .align 2 .global gc_helper_get_sp .type gc_helper_get_sp, %function @ uint gc_helper_get_sp(void) gc_helper_get_sp: @ return the sp mov r0, sp bx lr .size gc_helper_get_sp, .-gc_helper_get_sp .global gc_helper_get_regs_and_sp .type gc_helper_get_regs_and_sp, %function @ uint gc_helper_get_regs_and_sp(r0=uint regs[10]) gc_helper_get_regs_and_sp: @ store registers into given array str r4, [r0], #4 str r5, [r0], #4 str r6, [r0], #4 str r7, [r0], #4 str r8, [r0], #4 str r9, [r0], #4 str r10, [r0], #4 str r11, [r0], #4 str r12, [r0], #4 str r13, [r0], #4 @ return the sp mov r0, sp bx lr .size gc_helper_get_regs_and_sp, .-gc_helper_get_regs_and_sp micropython-1.12/lib/utils/interrupt_char.c000066400000000000000000000034201357706137100211240ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/mpstate.h" #if MICROPY_KBD_EXCEPTION int mp_interrupt_char = -1; void mp_hal_set_interrupt_char(int c) { if (c != -1) { mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); } mp_interrupt_char = c; } void mp_keyboard_interrupt(void) { MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); #if MICROPY_ENABLE_SCHEDULER if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } #endif } #endif micropython-1.12/lib/utils/interrupt_char.h000066400000000000000000000027251357706137100211400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H #define MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H extern int mp_interrupt_char; void mp_hal_set_interrupt_char(int c); void mp_keyboard_interrupt(void); #endif // MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H micropython-1.12/lib/utils/mpirq.c000066400000000000000000000114741357706137100172330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * 2018 Tobias Badertscher * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/gc.h" #include "lib/utils/mpirq.h" /****************************************************************************** DECLARE PUBLIC DATA ******************************************************************************/ const mp_arg_t mp_irq_init_args[] = { { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, }; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent) { mp_irq_obj_t *self = m_new0(mp_irq_obj_t, 1); self->base.type = &mp_irq_type; self->methods = (mp_irq_methods_t*)methods; self->parent = parent; self->handler = mp_const_none; self->ishard = false; return self; } void mp_irq_handler(mp_irq_obj_t *self) { if (self->handler != mp_const_none) { if (self->ishard) { // When executing code within a handler we must lock the GC to prevent // any memory allocations. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_1(self->handler, self->parent); nlr_pop(); } else { // Uncaught exception; disable the callback so that it doesn't run again self->methods->trigger(self->parent, 0); self->handler = mp_const_none; printf("Uncaught exception in IRQ callback handler\n"); mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } gc_unlock(); } else { // Schedule call to user function mp_sched_schedule(self->handler, self->parent); } } } /******************************************************************************/ // MicroPython bindings STATIC mp_obj_t mp_irq_flags(mp_obj_t self_in) { mp_irq_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_FLAGS)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags); STATIC mp_obj_t mp_irq_trigger(size_t n_args, const mp_obj_t *args) { mp_irq_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_t ret_obj = mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_TRIGGERS)); if (n_args == 2) { // Set trigger self->methods->trigger(self->parent, mp_obj_get_int(args[1])); } return ret_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_irq_trigger_obj, 1, 2, mp_irq_trigger); STATIC mp_obj_t mp_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 0, false); mp_irq_handler(MP_OBJ_TO_PTR(self_in)); return mp_const_none; } STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_flags), MP_ROM_PTR(&mp_irq_flags_obj) }, { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&mp_irq_trigger_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table); const mp_obj_type_t mp_irq_type = { { &mp_type_type }, .name = MP_QSTR_irq, .call = mp_irq_call, .locals_dict = (mp_obj_dict_t*)&mp_irq_locals_dict, }; micropython-1.12/lib/utils/mpirq.h000066400000000000000000000060321357706137100172320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H #define MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ enum { MP_IRQ_ARG_INIT_handler = 0, MP_IRQ_ARG_INIT_trigger, MP_IRQ_ARG_INIT_hard, MP_IRQ_ARG_INIT_NUM_ARGS, }; /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef mp_obj_t (*mp_irq_init_t)(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); typedef mp_uint_t (*mp_irq_uint_method_one_uint_para_t)(mp_obj_t self, mp_uint_t trigger); typedef mp_uint_t (*mp_irq_int_method_one_para_t)(mp_obj_t self, mp_uint_t info_type); enum { MP_IRQ_INFO_FLAGS, MP_IRQ_INFO_TRIGGERS, MP_IRQ_INFO_CNT }; typedef struct _mp_irq_methods_t { mp_irq_init_t init; mp_irq_uint_method_one_uint_para_t trigger; mp_irq_int_method_one_para_t info; } mp_irq_methods_t; typedef struct _mp_irq_obj_t { mp_obj_base_t base; mp_irq_methods_t *methods; mp_obj_t parent; mp_obj_t handler; bool ishard; } mp_irq_obj_t; /****************************************************************************** DECLARE EXPORTED DATA ******************************************************************************/ extern const mp_arg_t mp_irq_init_args[]; extern const mp_obj_type_t mp_irq_type; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent); void mp_irq_handler(mp_irq_obj_t *self); #endif // MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H micropython-1.12/lib/utils/printf.c000066400000000000000000000100421357706137100173730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #include #include #include #include "py/obj.h" #include "py/mphal.h" #if MICROPY_PY_BUILTINS_FLOAT #include "py/formatfloat.h" #endif #if MICROPY_DEBUG_PRINTERS int DEBUG_printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); int ret = mp_vprintf(MICROPY_DEBUG_PRINTER, fmt, ap); va_end(ap); return ret; } #endif #if MICROPY_USE_INTERNAL_PRINTF #undef putchar // Some stdlibs have a #define for putchar int printf(const char *fmt, ...); int vprintf(const char *fmt, va_list ap); int putchar(int c); int puts(const char *s); int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); int snprintf(char *str, size_t size, const char *fmt, ...); int printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); int ret = mp_vprintf(&mp_plat_print, fmt, ap); va_end(ap); return ret; } int vprintf(const char *fmt, va_list ap) { return mp_vprintf(&mp_plat_print, fmt, ap); } // need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a') int putchar(int c) { char chr = c; mp_hal_stdout_tx_strn_cooked(&chr, 1); return chr; } // need this because gcc optimises printf("string\n") -> puts("string") int puts(const char *s) { mp_hal_stdout_tx_strn_cooked(s, strlen(s)); char chr = '\n'; mp_hal_stdout_tx_strn_cooked(&chr, 1); return 1; } typedef struct _strn_print_env_t { char *cur; size_t remain; } strn_print_env_t; STATIC void strn_print_strn(void *data, const char *str, size_t len) { strn_print_env_t *strn_print_env = data; if (len > strn_print_env->remain) { len = strn_print_env->remain; } memcpy(strn_print_env->cur, str, len); strn_print_env->cur += len; strn_print_env->remain -= len; } #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 9 // uClibc requires this alias to be defined, or there may be link errors // when linkings against it statically. // GCC 9 gives a warning about missing attributes so it's excluded until // uClibc+GCC9 support is needed. int __GI_vsnprintf(char *str, size_t size, const char *fmt, va_list ap) __attribute__((weak, alias ("vsnprintf"))); #endif int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) { strn_print_env_t strn_print_env = {str, size}; mp_print_t print = {&strn_print_env, strn_print_strn}; int len = mp_vprintf(&print, fmt, ap); // add terminating null byte if (size > 0) { if (strn_print_env.remain == 0) { strn_print_env.cur[-1] = 0; } else { strn_print_env.cur[0] = 0; } } return len; } int snprintf(char *str, size_t size, const char *fmt, ...) { va_list ap; va_start(ap, fmt); int ret = vsnprintf(str, size, fmt, ap); va_end(ap); return ret; } #endif //MICROPY_USE_INTERNAL_PRINTF micropython-1.12/lib/utils/pyexec.c000066400000000000000000000465551357706137100174100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" #include "py/gc.h" #include "py/frozenmod.h" #include "py/mphal.h" #if MICROPY_HW_ENABLE_USB #include "irq.h" #include "usb.h" #endif #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" #include "genhdr/mpversion.h" pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; int pyexec_system_exit = 0; STATIC bool repl_display_debugging_info = 0; #define EXEC_FLAG_PRINT_EOF (1) #define EXEC_FLAG_ALLOW_DEBUGGING (2) #define EXEC_FLAG_IS_REPL (4) #define EXEC_FLAG_SOURCE_IS_RAW_CODE (8) #define EXEC_FLAG_SOURCE_IS_VSTR (16) #define EXEC_FLAG_SOURCE_IS_FILENAME (32) // parses, compiles and executes the code in the lexer // frees the lexer before returning // EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output // EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code // EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, int exec_flags) { int ret = 0; uint32_t start = 0; // by default a SystemExit exception returns 0 pyexec_system_exit = 0; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t module_fun; #if MICROPY_MODULE_FROZEN_MPY if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) { // source is a raw_code object, create the function module_fun = mp_make_function_from_raw_code(source, MP_OBJ_NULL, MP_OBJ_NULL); } else #endif { #if MICROPY_ENABLE_COMPILER mp_lexer_t *lex; if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) { const vstr_t *vstr = source; lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0); } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) { lex = mp_lexer_new_from_file(source); } else { lex = (mp_lexer_t*)source; } // source is a lexer, parse and compile the script qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL); #else mp_raise_msg(&mp_type_RuntimeError, "script compilation not supported"); #endif } // execute code mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us start = mp_hal_ticks_ms(); mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt nlr_pop(); ret = 1; if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } } else { // uncaught exception // FIXME it could be that an interrupt happens just before we disable it here mp_hal_set_interrupt_char(-1); // disable interrupt // print EOF after normal output if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } // check for SystemExit if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // at the moment, the value of SystemExit is unused ret = pyexec_system_exit; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); ret = 0; } } // display debugging info if wanted if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { mp_uint_t ticks = mp_hal_ticks_ms() - start; // TODO implement a function that does this properly printf("took " UINT_FMT " ms\n", ticks); // qstr info { size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); printf("qstr:\n n_pool=%u\n n_qstr=%u\n " "n_str_data_bytes=%u\n n_total_bytes=%u\n", (unsigned)n_pool, (unsigned)n_qstr, (unsigned)n_str_data_bytes, (unsigned)n_total_bytes); } #if MICROPY_ENABLE_GC // run collection and print GC info gc_collect(); gc_dump_info(); #endif } if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } return ret; } #if MICROPY_ENABLE_COMPILER #if MICROPY_REPL_EVENT_DRIVEN typedef struct _repl_t { // This structure originally also held current REPL line, // but it was moved to MP_STATE_VM(repl_line) as containing // root pointer. Still keep structure in case more state // will be added later. //vstr_t line; bool cont_line; bool paste_mode; } repl_t; repl_t repl; STATIC int pyexec_raw_repl_process_char(int c); STATIC int pyexec_friendly_repl_process_char(int c); void pyexec_event_repl_init(void) { MP_STATE_VM(repl_line) = vstr_new(32); repl.cont_line = false; repl.paste_mode = false; // no prompt before printing friendly REPL banner or entering raw REPL readline_init(MP_STATE_VM(repl_line), ""); if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { pyexec_raw_repl_process_char(CHAR_CTRL_A); } else { pyexec_friendly_repl_process_char(CHAR_CTRL_B); } } STATIC int pyexec_raw_repl_process_char(int c) { if (c == CHAR_CTRL_A) { // reset raw REPL mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); goto reset; } else if (c == CHAR_CTRL_B) { // change to friendly REPL pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; vstr_reset(MP_STATE_VM(repl_line)); repl.cont_line = false; repl.paste_mode = false; pyexec_friendly_repl_process_char(CHAR_CTRL_B); return 0; } else if (c == CHAR_CTRL_C) { // clear line vstr_reset(MP_STATE_VM(repl_line)); return 0; } else if (c == CHAR_CTRL_D) { // input finished } else { // let through any other raw 8-bit value vstr_add_byte(MP_STATE_VM(repl_line), c); return 0; } // indicate reception of command mp_hal_stdout_tx_str("OK"); if (MP_STATE_VM(repl_line)->len == 0) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(MP_STATE_VM(repl_line)); return PYEXEC_FORCED_EXIT; } int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } reset: vstr_reset(MP_STATE_VM(repl_line)); mp_hal_stdout_tx_str(">"); return 0; } STATIC int pyexec_friendly_repl_process_char(int c) { if (repl.paste_mode) { if (c == CHAR_CTRL_C) { // cancel everything mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (c == CHAR_CTRL_D) { // end of input mp_hal_stdout_tx_str("\r\n"); int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } goto input_restart; } else { // add char to buffer and echo vstr_add_byte(MP_STATE_VM(repl_line), c); if (c == '\r') { mp_hal_stdout_tx_str("\r\n=== "); } else { char buf[1] = {c}; mp_hal_stdout_tx_strn(buf, 1); } return 0; } } int ret = readline_process_char(c); if (!repl.cont_line) { if (ret == CHAR_CTRL_A) { // change to raw REPL pyexec_mode_kind = PYEXEC_MODE_RAW_REPL; mp_hal_stdout_tx_str("\r\n"); pyexec_raw_repl_process_char(CHAR_CTRL_A); return 0; } else if (ret == CHAR_CTRL_B) { // reset friendly REPL mp_hal_stdout_tx_str("\r\n"); mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); #if MICROPY_PY_BUILTINS_HELP mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); #endif goto input_restart; } else if (ret == CHAR_CTRL_C) { // break mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (ret == CHAR_CTRL_D) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(MP_STATE_VM(repl_line)); return PYEXEC_FORCED_EXIT; } else if (ret == CHAR_CTRL_E) { // paste mode mp_hal_stdout_tx_str("\r\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\r\n=== "); vstr_reset(MP_STATE_VM(repl_line)); repl.paste_mode = true; return 0; } if (ret < 0) { return 0; } if (!mp_repl_continue_with_input(vstr_null_terminated_str(MP_STATE_VM(repl_line)))) { goto exec; } vstr_add_byte(MP_STATE_VM(repl_line), '\n'); repl.cont_line = true; readline_note_newline("... "); return 0; } else { if (ret == CHAR_CTRL_C) { // cancel everything mp_hal_stdout_tx_str("\r\n"); repl.cont_line = false; goto input_restart; } else if (ret == CHAR_CTRL_D) { // stop entering compound statement goto exec; } if (ret < 0) { return 0; } if (mp_repl_continue_with_input(vstr_null_terminated_str(MP_STATE_VM(repl_line)))) { vstr_add_byte(MP_STATE_VM(repl_line), '\n'); readline_note_newline("... "); return 0; } exec: ; int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } input_restart: vstr_reset(MP_STATE_VM(repl_line)); repl.cont_line = false; repl.paste_mode = false; readline_init(MP_STATE_VM(repl_line), ">>> "); return 0; } } uint8_t pyexec_repl_active; int pyexec_event_repl_process_char(int c) { pyexec_repl_active = 1; int res; if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { res = pyexec_raw_repl_process_char(c); } else { res = pyexec_friendly_repl_process_char(c); } pyexec_repl_active = 0; return res; } #else // MICROPY_REPL_EVENT_DRIVEN int pyexec_raw_repl(void) { vstr_t line; vstr_init(&line, 32); raw_repl_reset: mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); for (;;) { vstr_reset(&line); mp_hal_stdout_tx_str(">"); for (;;) { int c = mp_hal_stdin_rx_chr(); if (c == CHAR_CTRL_A) { // reset raw REPL goto raw_repl_reset; } else if (c == CHAR_CTRL_B) { // change to friendly REPL mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; return 0; } else if (c == CHAR_CTRL_C) { // clear line vstr_reset(&line); } else if (c == CHAR_CTRL_D) { // input finished break; } else { // let through any other raw 8-bit value vstr_add_byte(&line, c); } } // indicate reception of command mp_hal_stdout_tx_str("OK"); if (line.len == 0) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); return PYEXEC_FORCED_EXIT; } int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } } } int pyexec_friendly_repl(void) { vstr_t line; vstr_init(&line, 32); #if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD // in host mode, we enable the LCD for the repl mp_obj_t lcd_o = mp_call_function_0(mp_load_name(qstr_from_str("LCD"))); mp_call_function_1(mp_load_attr(lcd_o, qstr_from_str("light")), mp_const_true); #endif friendly_repl_reset: mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); #if MICROPY_PY_BUILTINS_HELP mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); #endif // to test ctrl-C /* { uint32_t x[4] = {0x424242, 0xdeaddead, 0x242424, 0xdeadbeef}; for (;;) { nlr_buf_t nlr; printf("pyexec_repl: %p\n", x); mp_hal_set_interrupt_char(CHAR_CTRL_C); if (nlr_push(&nlr) == 0) { for (;;) { } } else { printf("break\n"); } } } */ for (;;) { input_restart: #if MICROPY_HW_ENABLE_USB if (usb_vcp_is_enabled()) { // If the user gets to here and interrupts are disabled then // they'll never see the prompt, traceback etc. The USB REPL needs // interrupts to be enabled or no transfers occur. So we try to // do the user a favor and reenable interrupts. if (query_irq() == IRQ_STATE_DISABLED) { enable_irq(IRQ_STATE_ENABLED); mp_hal_stdout_tx_str("MPY: enabling IRQs\r\n"); } } #endif // If the GC is locked at this point there is no way out except a reset, // so force the GC to be unlocked to help the user debug what went wrong. if (MP_STATE_MEM(gc_lock_depth) != 0) { MP_STATE_MEM(gc_lock_depth) = 0; } vstr_reset(&line); int ret = readline(&line, ">>> "); mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; if (ret == CHAR_CTRL_A) { // change to raw REPL mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_RAW_REPL; return 0; } else if (ret == CHAR_CTRL_B) { // reset friendly REPL mp_hal_stdout_tx_str("\r\n"); goto friendly_repl_reset; } else if (ret == CHAR_CTRL_C) { // break mp_hal_stdout_tx_str("\r\n"); continue; } else if (ret == CHAR_CTRL_D) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); return PYEXEC_FORCED_EXIT; } else if (ret == CHAR_CTRL_E) { // paste mode mp_hal_stdout_tx_str("\r\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\r\n=== "); vstr_reset(&line); for (;;) { char c = mp_hal_stdin_rx_chr(); if (c == CHAR_CTRL_C) { // cancel everything mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (c == CHAR_CTRL_D) { // end of input mp_hal_stdout_tx_str("\r\n"); break; } else { // add char to buffer and echo vstr_add_byte(&line, c); if (c == '\r') { mp_hal_stdout_tx_str("\r\n=== "); } else { mp_hal_stdout_tx_strn(&c, 1); } } } parse_input_kind = MP_PARSE_FILE_INPUT; } else if (vstr_len(&line) == 0) { continue; } else { // got a line with non-zero length, see if it needs continuing while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { vstr_add_byte(&line, '\n'); ret = readline(&line, "... "); if (ret == CHAR_CTRL_C) { // cancel everything mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (ret == CHAR_CTRL_D) { // stop entering compound statement break; } } } ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } } } #endif // MICROPY_REPL_EVENT_DRIVEN #endif // MICROPY_ENABLE_COMPILER int pyexec_file(const char *filename) { return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME); } int pyexec_file_if_exists(const char *filename) { #if MICROPY_MODULE_FROZEN if (mp_frozen_stat(filename) == MP_IMPORT_STAT_FILE) { return pyexec_frozen_module(filename); } #endif if (mp_import_stat(filename) != MP_IMPORT_STAT_FILE) { return 1; // success (no file is the same as an empty file executing without fail) } return pyexec_file(filename); } #if MICROPY_MODULE_FROZEN int pyexec_frozen_module(const char *name) { void *frozen_data; int frozen_type = mp_find_frozen_module(name, strlen(name), &frozen_data); switch (frozen_type) { #if MICROPY_MODULE_FROZEN_STR case MP_FROZEN_STR: return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, 0); #endif #if MICROPY_MODULE_FROZEN_MPY case MP_FROZEN_MPY: return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_RAW_CODE); #endif default: printf("could not find module '%s'\n", name); return false; } } #endif mp_obj_t pyb_set_repl_info(mp_obj_t o_value) { repl_display_debugging_info = mp_obj_get_int(o_value); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj, pyb_set_repl_info); micropython-1.12/lib/utils/pyexec.h000066400000000000000000000043361357706137100174040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H #define MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H #include "py/obj.h" typedef enum { PYEXEC_MODE_RAW_REPL, PYEXEC_MODE_FRIENDLY_REPL, } pyexec_mode_kind_t; extern pyexec_mode_kind_t pyexec_mode_kind; // Set this to the value (eg PYEXEC_FORCED_EXIT) that will be propagated through // the pyexec functions if a SystemExit exception is raised by the running code. // It will reset to 0 at the start of each execution (eg each REPL entry). extern int pyexec_system_exit; #define PYEXEC_FORCED_EXIT (0x100) #define PYEXEC_SWITCH_MODE (0x200) int pyexec_raw_repl(void); int pyexec_friendly_repl(void); int pyexec_file(const char *filename); int pyexec_file_if_exists(const char *filename); int pyexec_frozen_module(const char *name); void pyexec_event_repl_init(void); int pyexec_event_repl_process_char(int c); extern uint8_t pyexec_repl_active; mp_obj_t pyb_set_repl_info(mp_obj_t o_value); MP_DECLARE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj); #endif // MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H micropython-1.12/lib/utils/stdout_helpers.c000066400000000000000000000012431357706137100211400ustar00rootroot00000000000000#include #include #include "py/mpconfig.h" #include "py/mphal.h" /* * Extra stdout functions * These can be either optimized for a particular port, or reference * implementation below can be used. */ // Send "cooked" string of given length, where every occurrence of // LF character is replaced with CR LF. void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { while (len--) { if (*str == '\n') { mp_hal_stdout_tx_strn("\r", 1); } mp_hal_stdout_tx_strn(str++, 1); } } // Send zero-terminated string void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } micropython-1.12/lib/utils/sys_stdio_mphal.c000066400000000000000000000137331357706137100213040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" // TODO make stdin, stdout and stderr writable objects so they can // be changed by Python code. This requires some changes, as these // objects are in a read-only module (py/modsys.c). /******************************************************************************/ // MicroPython bindings #define STDIO_FD_IN (0) #define STDIO_FD_OUT (1) #define STDIO_FD_ERR (2) typedef struct _sys_stdio_obj_t { mp_obj_base_t base; int fd; } sys_stdio_obj_t; #if MICROPY_PY_SYS_STDIO_BUFFER STATIC const sys_stdio_obj_t stdio_buffer_obj; #endif void stdio_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { sys_stdio_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->fd); } STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { sys_stdio_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->fd == STDIO_FD_IN) { for (uint i = 0; i < size; i++) { int c = mp_hal_stdin_rx_chr(); if (c == '\r') { c = '\n'; } ((byte*)buf)[i] = c; } return size; } else { *errcode = MP_EPERM; return MP_STREAM_ERROR; } } STATIC mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { sys_stdio_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->fd == STDIO_FD_OUT || self->fd == STDIO_FD_ERR) { mp_hal_stdout_tx_strn_cooked(buf, size); return size; } else { *errcode = MP_EPERM; return MP_STREAM_ERROR; } } STATIC mp_uint_t stdio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)self_in; if (request == MP_STREAM_POLL) { return mp_hal_stdio_poll(arg); } else { *errcode = MP_EINVAL; return MP_STREAM_ERROR; } } STATIC mp_obj_t stdio_obj___exit__(size_t n_args, const mp_obj_t *args) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stdio_obj___exit___obj, 4, 4, stdio_obj___exit__); // TODO gc hook to close the file if not already closed STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = { #if MICROPY_PY_SYS_STDIO_BUFFER { MP_ROM_QSTR(MP_QSTR_buffer), MP_ROM_PTR(&stdio_buffer_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)}, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&stdio_obj___exit___obj) }, }; STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table); STATIC const mp_stream_p_t stdio_obj_stream_p = { .read = stdio_read, .write = stdio_write, .ioctl = stdio_ioctl, .is_text = true, }; STATIC const mp_obj_type_t stdio_obj_type = { { &mp_type_type }, .name = MP_QSTR_FileIO, // TODO .make_new? .print = stdio_obj_print, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &stdio_obj_stream_p, .locals_dict = (mp_obj_dict_t*)&stdio_locals_dict, }; const sys_stdio_obj_t mp_sys_stdin_obj = {{&stdio_obj_type}, .fd = STDIO_FD_IN}; const sys_stdio_obj_t mp_sys_stdout_obj = {{&stdio_obj_type}, .fd = STDIO_FD_OUT}; const sys_stdio_obj_t mp_sys_stderr_obj = {{&stdio_obj_type}, .fd = STDIO_FD_ERR}; #if MICROPY_PY_SYS_STDIO_BUFFER STATIC mp_uint_t stdio_buffer_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { for (uint i = 0; i < size; i++) { ((byte*)buf)[i] = mp_hal_stdin_rx_chr(); } return size; } STATIC mp_uint_t stdio_buffer_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { mp_hal_stdout_tx_strn(buf, size); return size; } STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = { .read = stdio_buffer_read, .write = stdio_buffer_write, .ioctl = stdio_ioctl, .is_text = false, }; STATIC const mp_obj_type_t stdio_buffer_obj_type = { { &mp_type_type }, .name = MP_QSTR_FileIO, .print = stdio_obj_print, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &stdio_buffer_obj_stream_p, .locals_dict = (mp_obj_dict_t*)&stdio_locals_dict, }; STATIC const sys_stdio_obj_t stdio_buffer_obj = {{&stdio_buffer_obj_type}, .fd = 0}; // fd unused #endif micropython-1.12/logo/000077500000000000000000000000001357706137100147625ustar00rootroot00000000000000micropython-1.12/logo/1bit-logo.png000066400000000000000000000006371357706137100172730ustar00rootroot00000000000000PNG  IHDR00mkPLTEU~bKGDH pHYs  tIME;;>#AtEXtCommentCREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90 EXIDATc`-u)08+SrJ~PbL-?$Ȟo@r)A/'@Fg^R6); _@F26У(Q S]t ̜6Q )/T]84HjIENDB`micropython-1.12/logo/FONT-LICENSE.txt000066400000000000000000000106271357706137100173570ustar00rootroot00000000000000The font used for the MicroPython logo is "Exo", http://www.google.com/fonts/specimen/Exo. Copyright (c) 2013, Natanael Gama (https://plus.google.com/u/0/+NatanaelGama), with Reserved Font Name Exo. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. micropython-1.12/logo/logo.jpg000066400000000000000000002663051357706137100164400ustar00rootroot00000000000000!6ExifMM*bj(1r2i-'-'Adobe Photoshop CS6 (Windows)2013:09:29 21:47:27NN&(. HH Adobe_CMAdobed            " ?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?TI%)$IJI$RI$׳J+;?1[F3'5 lZ You[zGCX0ާ\=OaeNkmW)鴿67Wlm{}_vS Q2=.V5 oł߬=_g _U3+zkͅQuy^kIfNn[r:nn=e豧ƹ{,2IOFI$$I)I$JRI$TI%)$IJI$RI$73ܼUy hNXU?TpUuܬ?jv_OV߬c+ Ѭ@r "kzլ\lkKrfcl{_ut?-%_Dc, TwlO ^Bb;긘8u+zUSxx~b9;gguw~^mMul۫Y9|v]no@ţ w߃ٲVW}s'b199`H{~NF+\jظ;_;M;!)X'J/$HRI$I$$I)TI%)$IJI$R.LD%\X3nUϩ}Y$NG\ǿRSW:Ctz0]}J}Q0kgf|g2c7!m`ᶼ*[[GXC[Un hĝ9\nnzg,{ȗpc1ԋ>/څ vX¶6/KfۣHߺpm?Wr2->lmolZS|1r"!C$(@9I~}S}W6 I$eEUz;H~Ï#SaI$JRI$I$TI%)$IJI$Rn_PX+˦G!5;YI%>_rz`53Wv7XL6\^E}K3+ZJ7a~/Vd^ITE$SuMo]B~5n= =?82񶿧zi }vlwѷ=NYzؾ z,8003ۓq: "uU}4;mL;\'ۻW]f^Scå:R ю"6Y/;7z_j.:ֺ7 3kG~s' ӾGtѝXayIe4N8F_e//_QK)C*hc:4mjI-I$JRI$I$TI%)$IJIV=G ݟh݄{1M:2tv9m6di#iǭ5ke8 yf$b,:OM'՞ӟmӻ:hs'wOέ:_WOMɯ*X}']V貛?cCl鴾#mMwMّ3i92hɫZXs1"uR/ s Q0#;qpO}vS79t? 8mɳ,c:~iӵqT:'K1:r0zƾKoYggz2~b2t^SQ6Ջͣ#37ɳ6?Oa vJ3Y[\vM%mc`rY*0 '@@{X /w²Y}ڽC W~k=E6lp6>S_ߠk]?OԷ^E =3bG[}y}L׶6?ƥ1qwg3O4rb䑮9KsxswDa,'G.Lq\'ޗm]lgjm󿜭*ԯ}Kuw[n;VM`cs5*h.}6^Ҳ_쏴dVN>C't?ޖ>pXiwY?rd9s>8c#.vk\V~LXjgG\Y'evAޛe^/oo3s|/,R/xÇ/x}_}({c}+]z[^ՒNE~YW?O]NwG+aC.`un?v s1ɨƽ?k\/XX+ՋMtQA},n 5,NK>9s\|S#>XNnML;=Sgmy>>g[p\}y5U_UF/]u]K {YԱt{}j1~S-_ 8(ܥQK,z_O1>npG0ȾfhsH-pG뚤I%?T\_ֿЮ ;l5` mk]IOh֏9S`胾^+?g֮,_bA {gǭ}%<$j.;KoӥvMSwu?O3Md;|5==/OMxq1yLe<}"WE4<>uO>u?Qp3u7+ֳ/ck eu7aΜh7a\kբx8۪7U030*ŋvU~+qʭ6Eɧ*ijm%he͋$ pC%dDϚ?ϑ8kFr(w W`uzr732,Ϯ=0b^.+#0fQe/Y~c鲦W[vkU quowR\M߽G_=b1 U\)'.2=-̷Z^'/$2yD2ALgn3 'x/o21};[ /˙oX0ϝ[wR,qPcjavwݳ"۷ޑ)̜16ncFkӂBQ.#I&[7HK4G?W4rhs0OںuWs ls6{+SaAmaw?+f`eud^טkA!{\٘Q2-`Urz?o.nGN+aE݅O0) fbܜ;C8=J2 UuY67aʶks6&I>U\U77ϥ̶FU=T=Ϫ73ֱٳi%<TѺb4 cfz՞^Q}@0VApGwFjfF 9̗w\fl6u 7 L2K72E1c}Od.'&{6[;[ 8 ȶm{#n;?WyK iI?RMd&.u[biڅ&ɲJ/^VΦ\̋2mWel2s]oƧ0zB c`r-~7ʜ7\6kN't}ޣQOY2MȩpdfpC5+\&FN֮(Uͧ ָZ Ac]u=/Eƽ]W.mE ~=w3ճ\=y `CI.?KoV+6NESibY9|f\~~q>q/o}mޱ:v#s[m~`5gӳTa)wFmao&ʨywG߲=ZzӨuUiS;9ߝk#w*UFlk\I~mڞpc81DGx zО/N«,EmmGn\Q?k}x-ܬۋɱ.PvlHK= sALyjٹhyF#Ynr+Xn^qQ]-!f E{ FOog~޳9%qN[,u4nkn{YKvQr$C}tޛ[{p"(tX gQû T͵fSpcOб~nCWu>H5C+(DG>Y^J`tܢù~ѵۘ_=~W:PĮL_UYm.;\Ozzk׏ߋms[qvDYk'Np1w+u^-=Gk~U~]W}oubki9αj$jkſa2ζ]nlmzv*da懳i%nwͶw/Zƣ!nhp,ܞ`;p*󬭭f{>Jy -ka}]:bʳ}v{ uua1Ū=L7 Kr nf~b:cׅS$4uC]oRu5e1cCa Xd})sz?޺n9űÜlȵ)Vi 65542/@]uYם2]ydb oJ?Ү;Z^(F.+*[ՋScEO֝`5뙸]z3~lcY>Wk6{)~:x^j{C=XJxke CA:kV?Ƿ Kzힼ?7g!c[2\b<@Zti/~Rnf]Đ+nihwHWH-sEmgG{g:WZfUu7pβCkݖ}_Oc}Sy~댥26}VښVG=D)בWN~M$Rsw}F~++9}{ ^&:Jw NFgӹ׿opp,Xxn'CÇ{WǾ^]an}N2[,,_a1̇{sVYYNlnڅO]'N;)ضgNp /vEWc.g0j$_T[mM̜ "PoHzu](Y8}e$I%)$IO)fPhotoshop 3.08BIM%8BIM: printOutputPstSboolInteenumInteClrmprintSixteenBitbool printerNameTEXTHP Deskjet 1050 J410 seriesprintProofSetupObjc Proof Setup proofSetupBltnenum builtinProof proofCMYK8BIM;-printOutputOptionsCptnboolClbrboolRgsMboolCrnCboolCntCboolLblsboolNgtvboolEmlDboolIntrboolBckgObjcRGBCRd doub@oGrn doub@oBl doub@oBrdTUntF#RltBld UntF#RltRsltUntF#Pxl@r vectorDataboolPgPsenumPgPsPgPCLeftUntF#RltTop UntF#RltScl UntF#Prc@YcropWhenPrintingboolcropRectBottomlong cropRectLeftlong cropRectRightlong cropRectToplong8BIM,,8BIM&?8BIM x8BIM8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM8BIM8BIM08BIM-8BIM@@8BIM8BIMINN Untitled-5NNnullboundsObjcRct1Top longLeftlongBtomlongNRghtlongNslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlongNRghtlongNurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM ,  Adobe_CMAdobed            " ?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?TI%)$IJI$RI$׳J+;?1[F3'5 lZ You[zGCX0ާ\=OaeNkmW)鴿67Wlm{}_vS Q2=.V5 oł߬=_g _U3+zkͅQuy^kIfNn[r:nn=e豧ƹ{,2IOFI$$I)I$JRI$TI%)$IJI$RI$73ܼUy hNXU?TpUuܬ?jv_OV߬c+ Ѭ@r "kzլ\lkKrfcl{_ut?-%_Dc, TwlO ^Bb;긘8u+zUSxx~b9;gguw~^mMul۫Y9|v]no@ţ w߃ٲVW}s'b199`H{~NF+\jظ;_;M;!)X'J/$HRI$I$$I)TI%)$IJI$R.LD%\X3nUϩ}Y$NG\ǿRSW:Ctz0]}J}Q0kgf|g2c7!m`ᶼ*[[GXC[Un hĝ9\nnzg,{ȗpc1ԋ>/څ vX¶6/KfۣHߺpm?Wr2->lmolZS|1r"!C$(@9I~}S}W6 I$eEUz;H~Ï#SaI$JRI$I$TI%)$IJI$Rn_PX+˦G!5;YI%>_rz`53Wv7XL6\^E}K3+ZJ7a~/Vd^ITE$SuMo]B~5n= =?82񶿧zi }vlwѷ=NYzؾ z,8003ۓq: "uU}4;mL;\'ۻW]f^Scå:R ю"6Y/;7z_j.:ֺ7 3kG~s' ӾGtѝXayIe4N8F_e//_QK)C*hc:4mjI-I$JRI$I$TI%)$IJIV=G ݟh݄{1M:2tv9m6di#iǭ5ke8 yf$b,:OM'՞ӟmӻ:hs'wOέ:_WOMɯ*X}']V貛?cCl鴾#mMwMّ3i92hɫZXs1"uR/ s Q0#;qpO}vS79t? 8mɳ,c:~iӵqT:'K1:r0zƾKoYggz2~b2t^SQ6Ջͣ#37ɳ6?Oa vJ3Y[\vM%mc`rY*0 '@@{X /w²Y}ڽC W~k=E6lp6>S_ߠk]?OԷ^E =3bG[}y}L׶6?ƥ1qwg3O4rb䑮9KsxswDa,'G.Lq\'ޗm]lgjm󿜭*ԯ}Kuw[n;VM`cs5*h.}6^Ҳ_쏴dVN>C't?ޖ>pXiwY?rd9s>8c#.vk\V~LXjgG\Y'evAޛe^/oo3s|/,R/xÇ/x}_}({c}+]z[^ՒNE~YW?O]NwG+aC.`un?v s1ɨƽ?k\/XX+ՋMtQA},n 5,NK>9s\|S#>XNnML;=Sgmy>>g[p\}y5U_UF/]u]K {YԱt{}j1~S-_ 8(ܥQK,z_O1>npG0ȾfhsH-pG뚤I%?T\_ֿЮ ;l5` mk]IOh֏9S`胾^+?g֮,_bA {gǭ}%<$j.;KoӥvMSwu?O3Md;|5==/OMxq1yLe<}"WE4<>uO>u?Qp3u7+ֳ/ck eu7aΜh7a\kբx8۪7U030*ŋvU~+qʭ6Eɧ*ijm%he͋$ pC%dDϚ?ϑ8kFr(w W`uzr732,Ϯ=0b^.+#0fQe/Y~c鲦W[vkU quowR\M߽G_=b1 U\)'.2=-̷Z^'/$2yD2ALgn3 'x/o21};[ /˙oX0ϝ[wR,qPcjavwݳ"۷ޑ)̜16ncFkӂBQ.#I&[7HK4G?W4rhs0OںuWs ls6{+SaAmaw?+f`eud^טkA!{\٘Q2-`Urz?o.nGN+aE݅O0) fbܜ;C8=J2 UuY67aʶks6&I>U\U77ϥ̶FU=T=Ϫ73ֱٳi%<TѺb4 cfz՞^Q}@0VApGwFjfF 9̗w\fl6u 7 L2K72E1c}Od.'&{6[;[ 8 ȶm{#n;?WyK iI?RMd&.u[biڅ&ɲJ/^VΦ\̋2mWel2s]oƧ0zB c`r-~7ʜ7\6kN't}ޣQOY2MȩpdfpC5+\&FN֮(Uͧ ָZ Ac]u=/Eƽ]W.mE ~=w3ճ\=y `CI.?KoV+6NESibY9|f\~~q>q/o}mޱ:v#s[m~`5gӳTa)wFmao&ʨywG߲=ZzӨuUiS;9ߝk#w*UFlk\I~mڞpc81DGx zО/N«,EmmGn\Q?k}x-ܬۋɱ.PvlHK= sALyjٹhyF#Ynr+Xn^qQ]-!f E{ FOog~޳9%qN[,u4nkn{YKvQr$C}tޛ[{p"(tX gQû T͵fSpcOб~nCWu>H5C+(DG>Y^J`tܢù~ѵۘ_=~W:PĮL_UYm.;\Ozzk׏ߋms[qvDYk'Np1w+u^-=Gk~U~]W}oubki9αj$jkſa2ζ]nlmzv*da懳i%nwͶw/Zƣ!nhp,ܞ`;p*󬭭f{>Jy -ka}]:bʳ}v{ uua1Ū=L7 Kr nf~b:cׅS$4uC]oRu5e1cCa Xd})sz?޺n9űÜlȵ)Vi 65542/@]uYם2]ydb oJ?Ү;Z^(F.+*[ՋScEO֝`5뙸]z3~lcY>Wk6{)~:x^j{C=XJxke CA:kV?Ƿ Kzힼ?7g!c[2\b<@Zti/~Rnf]Đ+nihwHWH-sEmgG{g:WZfUu7pβCkݖ}_Oc}Sy~댥26}VښVG=D)בWN~M$Rsw}F~++9}{ ^&:Jw NFgӹ׿opp,Xxn'CÇ{WǾ^]an}N2[,,_a1̇{sVYYNlnڅO]'N;)ضgNp /vEWc.g0j$_T[mM̜ "PoHzu](Y8}e$I%)$IO8BIM!UAdobe PhotoshopAdobe Photoshop CS68BIMhttp://ns.adobe.com/xap/1.0/ 98944087F8FE469D6594BB113080F9D4 EBB818F190EE38A8B4F997671FF447DA xmp.did:D97F7C514529E311A5CAB2D44753AC1B XICC_PROFILE HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km!Adobed@NN      @P!01A"`#3!1"AQ2# @PaB$q3%0brC4& !1AQa"q2B# @PR30br$Cc%`STs& YR% .ئ a"MFtƝgpP00鑏(!MZ>ð2M kS u$:umX f@2Ϯ?5Rͳlg'2O'O]FNJKE%!IvXGe5fzr=?0btј#Ϛ?|zFTw7kj5=3+]GvcKV38S<Vg[]ؿܙ3ZWnY^aykQ/0O` ϫ ޅ=u>Z{螑9/З.9~m:2Ǹþ璬="6fñYɯޱH m<eiWVk >7@Epvw=͎XOw<ګB'!e>#m|;#']NyW3/9굯֥>'8%;sP ,u41|Sxk[S%Yc&㛅'UBgw|ney6Տg{#^>f>wG띡guk-6v69{is!a6L>q|b7buOo5O-q\ns< ٓeOqxr~&B8\O5{o {'{:<5٬O5][Q.5LRkϞum'.jt΋y:}=K_f=ٿMK}˸k-Z}n,oWCq/yO8Zz@<^Жy_^RtmCKOWmlmwrӝӕ[cG`=WxQCOgGWK8S]'-5g< "kM`.xFÍ#LS2dҟX Ym<y `}o [yT|l_XVRq6Յ=o,6#IuRvʜ֜1se8Vıś16kGv.E $v"dzځ_0r}~_N2ua?/)pE˶ң2\?Q}Ny쎱.|6}:=%=,lvԦڮP(\;KJHTe*s-enBd=jw,[x>GSiB40J-5 Mƈt9ۮ9v,eYSdQ1i~Ϝ `tzஒh<64ܒeɖ85;q/G4hZUo KzHL z> NUO,/-TԚKmo0QuaʙqU#>*\[WtJtf2u\Aoe"X( :›ĒيtkAۈYJ zi%IlʹԬq9T:v2X5:*1T+_Ure+ӏE9 フKwc8?8c?c9먬̏(_EQ:7!< 84ܳrGlhٱ5k[&ЊN$/x񏰪VJ0iP$ fb.SX^?8<?*GM[R(ׄ)HY wT5m#CD=k-ϰms C1쳑8Sx2t[_p)+Ur> DUN'y-C l jw##)('5̩Q:!MSa ,1cȬ% [kV;%:Bw~1cg]/dlKu k"DF>?^3Eu  SJgtt䩌(-g _HyGH%7|URlP/N!W8G4#B#O5?_? PlR1V3q..Ya.T.) mRʪ̆J|x߶tR.?ulO6%q ]^pdKRyX݇9BRp/T#.o7VbK|bL ?E$cn,4; b}3BϝkBǃQp|ST+\le] |b qmXW͆e`!Z3܋$oHiÊ%@>_-uQܠwa L(!` wG]_ZN$ZM@Cw%\جVR]442髶?]m{È5)Gu yAzZɪg u zދ& nxv~AIuZ%fX~Fk݄`/!2c>8[zb")`SIa?k,c kc!zJ.?yKZR?y:*JsZwKv~Z3BeIZ(Z9i3*Yv>6<%H1)2ry!> ,`և}I&/-SZ3ӔN%8{ʗUF \CRꀌp*mW̛gq E9͎L +N5J!(~7ZvvuGm[L#Q+JV`4KsgzC)"_XB r%oʙI BpЇ'u.xZ Rhr-ޥQTULrǑ0c k3?S7{VOg+SWKق@Tv!]"7\CҝћQgaYwJ`_lک)Ԣ6M""Dµ.=?qu68i@E %zVC OfR\Ӯf\~ SfFc#O>8,C'=ƭGVVY,އH䛋K]W U-]rM}`ޤmWm^:ҘUKtA^7fU̢3"ѥ5p ~[FyeyW#=װKӋnQ=?U^.n ϬF#1K(ɥsV3̖p`q8>gLRMFSGXx3}k>׵iZ ךUR2쑈d^y*m-(#L-L 5*Ҡ!C3KB39Cs(|)2Y}9= %8TC&c-QZH^]# v[[G7٣ Б V"2SOȗʆeNQI֠FrwHeN褖iX+ T/ pXs8xEci$Ш$8xyCc<1xMyіcr"aTA^kE<äFƵ{6`%᮲2@$8r2}gVj60JqsH2'#8d =^O'Ʌ @ԇ }Yax0!,e_\BD? $!8ȳ1,"2!x;"f'3rqe18YvqaDq3&YIT80sA 0?KόrIXe<8B{3P`FD ^F8ya/ϣ!qzLr# %Y3L3 cᇃ0bA!q g q!0C}#=c+gdy/3"ώx0g9_8\.ye\g1@_V@@Dc""V2c191 dY+%p'y3cL0??Í`JECHg8Cǂ#<c"1c,qYFc90j, 8X9cRϫǤ"G2 Ws& `11s< !ȦGxXϜ}>|cs?f|ssǟ>3ǫgsE sẋ !=bnUl{Fk%Q< b|hG9K9V|1lA"4dQ{j*aZE~*dL6:]UW,MR:IuTeHeW%ɦ?R0sV0U%!SeI% q FRIJG$,!hԴ΍zY]BF=80$Nz ݦ۰mY;&-hz= , a85 Mk1;ږi $〚Fci$OmLHs +J'ڙ&-1V+ۣyOl{`?ar;'uT՜֧Zo^ Mbѫͽeb?cg:1hDh\C㯝VE"v:lCjj:VԑL9 Ys0b^Qux7Z1r-ώ8Ԅ>ԝxlEe$O .9qc9LόT!=y20M"Q ]$g91&qL茌d4Ä0nj_6qs9ǫ>˙8jpQdp̠"(a3X3Z #TGF0Ի11iʉid1{D? mh Ƕzn1 EјX|9^~OȽ^G8^a{T2jgSņ5AOe+VCX-%FcfRIaFʌ U0 pAOi)̌ϫ<ǟq< B /qA7?_ gyy˘Ǐ2r q |>|@X (C8@_ݐ9/18p8=bg9Ǐȳg1XqB dYy?P2n}9s 00|s,s/9?#|&|ώc|zc#09א>sp9yȋy s9lg|s~>ǏscՎ3c=ǜÑE`B?Kchbk6 γ:h>v3wYӷ&:_GH&{uFziGd6G$ cGk;սOػ=뷧-^KPkr5ɴ/j,HjkX3L(o܃Yέ(o_}[}Y}?iϮڭ.H#}YoM]ؽaPbGY&tQ? ؟cumN{gAԫvpV՞ִ}Z}c`'kͭFlt/ߚ^'ֹm_VgkcmqJ5ŗaGp߹gUURЈ䙒ZeٺPeTEVܡcUo0[=q}s֔-.Yz K3˱nt gIm xOAN״(O{3D ukp+d2c2RfUm-GCG_qkRy# 9 N{2/OvTu\R-1 +B=ޝ\ 8C gW-Ir]whkQG, 㬌|lZIӉl qPh-m>Ľ:{õbEigi]dC[$Fcb,NsCW5"!a.jeZP ߕAqOJej[FlG6BuO4_f}kV$\ݽ@@ۮž]}/c4vv7:[u{RavJZ 0tٓN_ EOuMlswF.[WV cJ"/Իan8h~g81gudN[h:w]>uB\X^{Oqn;6rTlOnzRE~2ynٽ[6d=|OQ_{K6.5^zIujw^Uw>!OU@vV-&ꋵujT7j9k0}ݢP]yu̝Db.Ƙ>U.XsL䧽ܪqIp I~Mv=ӊmU=]ri2je~ΣG|;G57KAP#ՓāvY^;hWTXU%^=Q-geXIujZs/ ƶmKU[}:9/a>vnŢwp[VTD~XԖ"NZt^Ϭ^CcTbEB^͆y4ME7vmJ9.29X$z)욦rȫwt~)kT{tWZ~>i5a;-u Md9mA5l+: Йpja =P[uE+FHDƙ/wDF]>YG.o]<*aF\-~gsj(Htx݄Smݖz[(=]lvݙn̳ҵ0inj%dY1Nz#9ӧ Cz#Y:*sWH8[U:@]kl]wpli^YXdGvw9Ɲr6#}W[k[&{7uNLh˚fdF֋mbMi:lj/l]OO?vvY=_OX3N]lOLC#+ xz`lzojM#6MdGܾ_tL\T)fKWp_6jE-קna#hG& c36_^dI,iibƈ;+cQDʞdۉ7}_qmvkN;Q[$Tڱ5Q7a92*%m/()[V.ʵ,1=h;Wl*p" tMN֮3@Q)UZ"-49Af{ZPws[Yz{|N{j!ަnyO@{$=#)OQج_VXbI#pU)njܾ5.N.-8>{4Va v4؟`Й&N7%/btyOoRݛزU+TG N+x=Τ:llV툨zsm)xddoə.:tS3FJ@q:Ouɨvvm%D0Mu8*lԧHa-iқEpһsm$ lmmw-NtkMNwa sAV57/]Ji_)I]#T'pn 巠x%Eb-\;I5c @Oە#h;#$Em_76uc[TW*Bc;:&N3RյoU{zn$Y:8u[8Fieִp鶱?Bt>{Z/aUE~n; v#sBus$1m EI{ ҔE0Mo=#OmgJc.{Vv3HVVj .ώkd[۪ /rlv׸7ivG^q\ԭ}t#KݹC54o?~njQ38 }>lNlvXqtdHt't$bnJp1R+T|Ӵ GJ(GRѶSt$veoi]$׿Tw_{wp\RᚺX׻@Ri9FlFt\H-:au|!:&&[Mlgkڶ'gԒhv/#铨‡H)-W%Tm?aUV&qTa:k 6x[LゔAWQ7UvSutZb:Ueq6ObLC)MqU2Q&Gvs[olR}|L6-^nV;7ŒC%*dʬ{ _[쌰 CƱ--)uOdLR fGIձn\=7Gw$xm`ss%%4&dN2Nsh^8J4 yCԾ}{Ddt/'pnbm li l/ۥk8Ntfu[c]Y V;14>%'s;vK]fu׾i^-veU"c |-=;69)6{+Վ9rvnMkrc /;R:oDQֱ:j^-2 ۗ2)mws7 9NG+*ލ!VoPkF_Xm-|E5M`Rz^|lF]>(T|> :d~pVKQ-}5Egq+u-Y-c>$VJj+aL @39u8W!,nwo`/;#>߽:d3[Šbܺ{>WӾL݋{Ad^vKwuAxjoȡ:uimfX6U\Uoz) uTtX[6õ;ϨmS62*hx#"7|>_h=%B.Ԭp&QDQ1 VE)ʝ:u#[6])6ՊnJ_]W,ZG SP[wضm J66uuECI.պ35sYɂk/uۧc;tE2i&wY7ՠ5kz CXXue%90J^S 5d/Y)~+]BkQwTۺ# mr7oigdXВ7st=[1xuwV*mOm1u;}%)iu3~!,W}3LnΛnnO햼u1se+jgVx IѱM~5Q{ y _ĪڝϪ>Կ1uLJ>`=Xzc)VuGdkgPn.fvj%MƫvR$SZt]S';-InWg}^uA5dP[uOlؓU'Q}&k +fwzMZ}H 8ߧ|>m7I!j2#U&5ʐZz5cYoA HZ[EݞTs[НSr^*[:ު~O]";ƔҫVo@}S/??=ZW3!.q۴?ܐ#Qdq }C1cʥ܅P2 vxe-z'$ApǏ1ŞNŹSZf ƇZ#/Y…@*IvXʵVSPG#4#*VhIxt+LWE4%$埇 =Yeji5Z@MGT~BEaKNK(SEUrߝeDk0 5YmSubޝJniLp bg[~Y*/pG ͍+}++LK*:FgEϺ @J0NYSA5| |fG39` ky{1<)u(0E@G.̾soجLҷwk٨& 1)A='ddTG;VuEUI"J+ŋd'= 8EZdG:qJɥGNT@e֍rzj;۰RDA`5 ǩ^[| %rƲܮD[NTr~\,X=UnN.Dtԧ+s n{%o`0ļ*ݕEAP}<S)Fu :38CW? FDu.7u$gXXdXE(q_T{_Nm[=I #gj(3fQ=q 8 OXυi(waۦSnwHV8$!7sbx>c y7Q%\Ga(RqJ=u<}1sP\ǠN$9_Zp&z= I׈p@e8mf&,sw#.=MK,M+H5H:EJ#fbUnUa)VH卫g]rWؖwT;楍C4B _? /Rl}6J&[i^B|1hH я]wqɮcRF!A h)⹴:i"PTq 8g3W*-(Ur@{c>?-yܾ6@8Ym|28PiH|iLm?}Oٺ v)QRхSrŭE{>m;Ԗ-Yğ .xTW?:mu-y ŵsڤ_5+ fN`\[\$!~p9`PW8{kcw@bo) hxIIITh=QӖiڡT18|LH+@v=YcMhD|i! %_rwEXMp($'!Ķ^r>Y`GZq$ixV~rjw|_E1c%:;efbI0SZ\C+  {h2gO C٭&@ 9 }.'Dw)ƁPq4#¹nmsr1H5SR9^.kkĠO@$`gφ$7@7iXc"u;"yas+zO4!FC27Cu |$!6$vZ:Z)Y$JQ TSF7hnNYe(oeGn6XUZT\O0cR2M <,%$ͷ(-mZ83QQ;GVn|~ }Y dfj=SڧmLFKe+8!R}w(J&½<F&Qbj`C0qc_ߴ7HwQD%DAٞ#VF:@''b~鷺Y={kHYu˧=Uzm@brg5EtMmFjB;TZyQS*d d14^@~ك!W.nʱME~+׈4&,tz.B :;p!ۡP^C&=W3 &=ԗ;2oq]H#Z(5GZ']no,,Tiϼqֶ[n*,@GA ȎoX}YMD{ {6Ί6-۪d" 3XAKV$6V­#psj^y7I;Ij3gBzXmD%X^1m&g+Esiq$4}=Zu:㬯繸2IX q S2;(BNujiԓSo[a5hF2TյrOh*[x=|G$O"5"Ӵ%vji=5eS>żىVA+p+3.H-O;ܪMy$ل3X?o9[t ۓ)" e+ &U",5~UBrP)NƭWmMtˍu;F:U~$:RvaF zB m`hb"*Nugo_<(x$hOtqR+[O*rχn{~jԎ`gLuQ{Hj14B̊CT+.Uoޖzߍ)!IeG$KUU_ ڋTweIٝgαkd IYLu &7FY淒ʵV8v CA]m3nHjdh\GO0V6`ej$NY[{mH LnT򎥻,j@P(49yy,>R;c<(t{*# 0}ݴǢWB˷:@s{16<V0q㘲:`` <']t @7FD 70oQe8j(@^쾓յFT3Kn6cl6ȻET,#T5h[ 38 pD6T(H I.\ rE %hEH5?p\Z\Idbш㹞;ȏ"U˩S:,?R}"ܶX3#Ҁ 1gzgi䕉t%DI^5tҮk;}Y`:RH.J5U&ɣʖ8^~ʭ+R}3[`Hf[dp[yRh,R1Lo6m=Ҁ~mYC9bU@c`O=z'o$8\M", 2X-?_P7)amD,GNovLu-'2e^^mO+o.gHSZ&`]CU q'.\yrW/@hrʄf39cv.'InY2u $l26[Ǔ3 P],+Wf\nJ+Z^߇ը@a8 V"3 $q-5Zz]Vd.eXd-HkɃS .ګZPdҀ;KSaF<0ov '^A:PW7=;P7c-J54h怖\x" mK,]?+ȖkFQ`P0Z3>Aiv)G*{aPsv>:RsYtw 2.l@-&q&u].m6.m$gF ʐTf6v̪W־;N$Vd.dc,-Q_-c##B[Hb~.U=1/Gw[=1!QJDsQY:_1J(}* )4qT]M+R#Z^Ŧ&!榴5AF$StwH=G]0ܯCnQXɕA%DJڈ+Ppѻ5Ѯ|!Lp1Ji. JmyYnvF#K}̕BA!ŁD:|@9aLQw23DbS0#Nc+^8J2t,q[Q#&p3^*yuR9 5 P4-1۞-Zlܯ%B4hWe4E6WH i'XnjKQ b7\=iF;Ƭ"F %*#7LiSbGu1nә~U._رҽ:`Svh=; OcSwy0,ǀ=ya ++QRMf$~:zSgí7k@[}krW*p2/HvYR)xͭד*ܗX|X (C Oo%~;f EtJs+wŦٿmsdM5<41)lmZ<pZG7mzZ$-##.╣JRHRTdTTP#ΠgycQϙkI D\ Pn7 jg2,zY*?lyGtAі&󛀭kveXz{$6B5b.ZbpLhB2F:_m^yRe@i*73FYI=_:F7nݭ!kuR)Č){QN{ |zé-f+5,3X3 qrniU] C#~uڍ}Sҽ◽ojk8Nf*a ۡ e?c]]|6f-,t vFnw;{S6%@H|B!IQ?IeXm%$i4%88:zvgLQE0گDă  E+eœsႬMw, 'g VDN~+O5!ccɟvV\ϊd< f}v:ԚGQ<69k dYu@1` ~d@Ȥ5h*E*}S诨6mpGWXHnQ˥ybItٽha wZKDC2ǍIBA"mA]eqPu>FmRH[ĶKxX=TЌ^W /SXJK焤;бKZ?;uoci;ED\*ƃ=3>J^ʬ6%Ҽ: @=nV rʑGy8n7ܯ uixDKW,X֠џVnNdh!VÎcY9DߺWmOpcdmK18Pg鵳#VU2nǕJgwf~| I-RRɪg]",:e7M.[JD-D3q"0:r8 |\)1x ֣t v4=44x3[or՗=j(H Ze,Moe&XR֎0׍FXCאE4fas"ܐ#*IӨ`MO\mm..b x'Cq ԫ] &"=0&:Aa!ـp[hji+I#:w=i^>\Ljp$~ 15sZH]Cȫ+dA鮞۠ȶ 3C0P&&kU&wU]e"T}?Fsu&fUkZ ( Ef O`hEZ&5$KͿҝ;RI(Eo:3װ,*@; IۀZ2h1JgJߒIffpA xZPv5[I0}xXb-@5 a>8=cr5 RJ,Gt[+#hvTǼxyk|i{6ƒ ȤF3, ;h1ig=Ej57Px}OJ* K3,aMAΤ) leH=GsA!3^cX[ {AS ' p@qS#q$ƭYcQ?N4<8:}uU g&w<'^:ᦎc S;^B&tXkj+F9(݃߄N]QRT"Hs?+j%cf> (Uy5 3mrK$f:̥X#tbj=Ƈ \}i\+ هծ}XKͱ^1IQ$-{q[E@]w֘햨;  G-BNZJ,;*Sr$H^6x`b+&VX˲R}D0e^=Fh+5A^s X>X/ {U}_߀iZS>x*Ep45~LQHEAb=P(2QT fĎj1QƠNP|UXkdž;QZӿ<YZT  qZp|yR,`.ώ4+ZXl1SZy=sƢ~UY_߆DJ<`b}*W G15S݆E Dj/g y`GfNO ib+ՊS`8煡X⬴ShF80Ƙ-ZWNa_gc8ši9f>>u+ k^*[[z=ჩyaeŊVL Oc>j.Xna2<0-k/jeC8pʸaJ1 p¹ϟ,J˜*P8Mq/ǖ5Wn  3=r#^_k:9|ₔbA~f<+OfH`~`)9>,.A0cÑşϏbljRp**gL+ Ҵ?*Ɯq蓖01A^-GΘ}OӽtK,HLDϤjZ^Rc24.})ۍ2~"RGd+c ^K`=€VEqޟf%],u*WT >/I-Q7)omb,TU9RH: ΨDN]da M*:/k i!XYD ̸V/JӐ[[u]U!D)$z6*i+޻*k+XO5TYmCɿG _ y TbH,z.-dx>t 5 Τ b?SNmoUh kYd>.IEu5-2N6_vpKGczxcvs z1O@m4*$ڣQODt0#}N/7 AųK2%N}Fo  vcK-! -Z'QT,+Dզ\!NYB(EuE@#:U -QP5 '!S.cKņ12e-J&KdS>")} 8q xJLFȑ=?:/ wc:zcқ8L/rA!$~b xe;?\j f2V>*Plm#(Ό$ )-GǙ|'M<#'-*$dW*oܯi6V x[:%MsKdU nP/ND9(4ԁS\ 8 n5O v=9nY0@#ZOf'xނ 74&")x븚%PT4xMrK2Mn7QDXKyf2^ɵMw9p!vt/{ z w;U| *=y *[CiR$dx~΀{9ߎmM%D(ni# H7l6*ZnJʣW,y.UFOiD^)u#"`9:Ⱥ"8\ۅAU{>[5 <,hqqvmKr%C{rgP$4}NY~=a/¢al GĤdFLAieo$rT5.ǀUPKrN-HS$^ceR84=ܷݑ#e-E#pꞋ;~ڮ`48X ZiPFe X'/oäfP3Ö`HPIprΧAOt]W `Hf Ж G jhtKMF"E8i )5s\ӡwTqȥA֥NLs8ez6F\ aeXxMҺCal=|ۈsHь–#Ɲ {j9 Cv$P j ܇<~zusLѕ"$.2@fI-o^ joFm-huΊń+Z^!;y#aPU/zס_}4h){d˶q-I͂iW^%=+̩)۱ELIjFm^mZ']ʛAleid+)[=ږé6/6pcUJ4H2 άtEeAgZ΋NJU#BŔ7ִ ߁ "WQȊcdj=C&Y"(MEѐr}jH UW"wc`ʱy*Z~icҽ-cIDRTm+,@Q 6EnX$rș [EDĸB'.rx I徆2a^\lja5[y3x`?Jɷ]lեۦ&2Jл˅[\֗RVdS,C ):WnF,mb W6/ٛM~_ݧNT<ÙRNP yf;@=<;褔( k emS6'n;"-dTdfZTҦEi+iC^$HO.[ ۪•> wyw(XB1s:Si79hcl Q~CI5܎.K39%ejԓƵӠ$⡞RB*<,FtG"EXٽwGKhnjKй: EȄ=q$o? ԫ<-P@rY@(:h ڷc V3g߇# WTytzCiP,T2Bu&Htq++ZhF bx^ r*E,.K`()߭ZHK"Ѹw{=h4le0yd2$ח/c:tm[MdK#@욫<ӞbА9@wc'ݎm,,{^Y%I1.-%; ޙ,"$= W3qj1}A-ռkEYA݈vH`i5 F`vvW, v H\5S1%|GA'fi\ 98SGtqqyq3,V_HuW:hE}C:)!3 r )A9d[ye%d4AL È?}p{}Ss z$n+8'3;( #ٗa6͇-;!GY. Q !hAꯤ_qaֆm.C#֍FH5ΌR[xT4l IxdTnu߸lwP`(%! ,I*4[+ϳeᯐLnU $R HaƇ&)FZ}#쾛tO6AHg+X6-'̰j(d*lXAA?OIsgavг\Go< QyA9+:kL\tQoQ/ @o1u1?a8ܮo |cpP݉: i%&ؿh$S<\9nK1.Pԩj3;uPJLҾcA愯*OzGk[ N,0HdABh9..z\Չ%o4yPvno'un,C ]VNkn)q/KL9g :%)w,K8۬ѷ .6%T䓢9 a!Ȏ@ CRW 71W{}Ko:Ԃ$B*vOepTfr8gg]/G4d vmc01#N$E%=$?V[4Mu 9!$X)QZwؤޥݍ%v%SQ#MYmH6zVO(x5%e19Q }XKCNy4˳3Onx)ĊҡO1c'rt*FuGw:P})tPi2>i~ {qR\Zo2* _fSk}WYA2ie9 _W7kdv.*+-e܏PSZ~hБ(' "R q54[y#J)G@;oLW3D)%v$ c^߯M9wI q n=_zYypZ)s%9i.U5t@tݳm&:7 XWkO;NYF#ڪ.2YQ{z|J}C*ϰӖͳ>_W EG!;|F4 !1WPrhc5ׁ V6~zҬtZFPywDe l7%*.m]gП HG1`M9f)a4q@Q4JߏQWgxm2W.Yȅ{L&Ӽ\m< -2Q?sSqʠ-0p4F,~rQyn_QiJgJ29Zz֭ HȨ!eu5@,ʴ8o5enKtdΣ/"1ԪSyRyc3#? *gd_P8p'q1yց)@eZp Q^y&e hԖ :3ϻM @T:\JW.fD맀m25IEi?P,,nA<$¥b{quӮt&2tkMV >n|k>˩Ω%,H W$jOyX,8(~*xw{0|hi@~՗<ʄr={iqE-l{8RǷ.sc@'zArY EzTPRnx뽞A+-rEjXyG?W2 ^mMvݬHWʼn~wĵwh8} qRj_N 39"#MErR@4ㄺ$3Ŏ{+:'r~LdXX A9T IzS}AU-FY3?Ȓ*ETXulڥBTe0o@MOˉلkU/!}'$g-WM~Ud-M-SH>% ^:#tah2p1sU߽XJY/`VәV[J*$@5P2avg,4.fXۯIv$>[5ɲ$)R>NڕRǵC<zԭ x{F-6 M wEnQ pƨx8-ȘZҜMдYаB#WtbHKJSW:y[z,h(E[`krN? 0iYRM>~DX*6k ýf-Zᑷ #Y9_ RxᑩCUN3~<_-xcCؤMkaltEIz(1N{ =wKs X *|x}ybI4#<`)$ bK G wY;)Oۀ4 A#.lXl#RC=h}@v?sM2#me#S/iݔd`ܙyp0{2in-.чair=I$}ys+݃$Z7,grY|FXxSHdp ~i^~t׃Ҽ<@coAǼ$Vԧ2s8k_Ʃ U$w制/86ƗS $R*J3gʧ:C6U;jS+ƻ85{oǵ)-p 竾(˯2գR; "F s޿%1qe4 @;v!Cfh5o#̶Ds`RKVeQISQٟOw_Ҳ``zM _g[au痂?< D'>5,8-G(f!Nǯ?Mm/,Lm\y`bH _1̟>+J b&Ƈ,+=sj`X'yrl%P`-Jh"TpCVȶNOQd 5Q$wNϑhpFZJ6:Kbu\ɱg\Pd5#8Y=Ɇ=ۚ^XW3l)ƗPxcj sUQTT33{m,c "N_ו3s ۟-ߖϦ"ؚ؆ZGz.kBb*5:N] ~Ou?|$aMEud49vmkU#̡Ik41uqjf($1:cVe|Fw.!MU5w?|R#1J搰jEV:ѳ2YF`x`ᠭ8i/ܮwڼvm~QIy9hP,I5ȣG/5x XcXǏ͠$Q0"k\b]kSܑ2rU8Ip .1sRdoD-ܜ+yyq]/}?oS8^J;Z[EѤ 9=SNzTȇIOѤ\獱*#Gc1cUS2'ořniuN у {T30⸢&v8p`=e>K#f&({]Rc2Y`u/9YW⏐1"#R r^,m6`n=´8#|#<^+: Oׯ>|먏g8ɲ$ۯTë]f**({Zu"<:-VԾ'3Wem ~6{axLn%,_CEM߲#꾎q/$ʸ+1 8̙\BɫK]& ьBCj9hl3`9~]y{%*jh(ZL{"+q-uOddK(R%KصX98WP^:kSkS<އYx#!\7,TK7km+tUe湾b!M\x$ŏ0gdZ'/̳͓7.ޯ.f8C8G'{ƹOPElT> p9jlabXvE4*ũ|}Lc%&\* {F.к: ג~MȨm~%Zəbq F wcѷyMS>O1A"@pY"!GXFgu&WV5-oxG(yec[rsUǁ6KCnAcɬ+EW# J6$ p7sEEOEO(6^-r[ 2cisb"8SbdVSqsֽTܩFGrt{˙|lz1s;Us~^99+kӲ|<7,CeUp0H5VvM܊E/X$(UˆʭbQy 'WsU?"j *j]ֹBFWK芫!mlҵQQΔbV}rqzthXFLˆ?n\6'SOUNGSFjw1dbr/U^KT bH#E)+UQo^ ҹ#P J碪'[Vd%"Ik+n]8/f'i?ODֵ~ĐG'.V5}5D._S!*-fbi{&T?s^E/VVV$$MȈɓ j{j#v _*259U0ϧcӂďb+g㓅GDDz{+ΐeW D=E<}o H1έ|!ZF7:40~<ՒG]( +/bҝ{c&9XD@~$MDSer+k C_!ТGk&SO׭ ^R|ܶga V7*(5`cܢ![!fPO9)qI:Jҿ)E忢Sc\)O Ci܉PUy˽=zdf!VhWvz"'@gpX}Tꞏ^3)DpB+}8wԹ' |G#7L$ucHV??뽤wNw:E!wLjk&~ž;!:a$lW>xZON:$Xykr^7rk]SB+"4Nk\9wڼz}iH`R5Ҽ}V#?TDk\Ǣ:®$ĭU2#8Uj=zΰ2s5W^ ncc;)qWzEoxm ,L.}mpE/cew9b5F?Sӏ[2/v!c_A=>{$ *LQZvַs)@?, CfGxd]P^5{ jIoW Ǝo׆yaȴF3|sϏ6|w0U;UzuJC]ޡz{G}SPDcapJ6jƱ2Reč xAƹޮw ׏^Jg4ؾuYE.4`ǛmIk&5+Ƌl8i\VlߋE+Zj*[yĸ_gE5Ԅ'f4oq Xa(b#~G6{HOHl4X5i}ׄr(iMb{$>!FW{֖ѸME]s]퉁i#u4ltBR98r])(i6cE1[`~*ὼ8dk\ED^w{.6đ&;Ff_UGr~\:WXUgc.KKVdjjzrGͯ{!c{ӻ+|>̷;a\oHTTUzv7immKWZj^\y&={%W9xNOlGe9dV1'y;#=cmdCQk^'|;cYG7e^Ԧ$b6!Ds]*Tkk*'UEy< )Nck !Q {HTQV!TEsz+UΈ(¬Ǵ%M^!VcrWgvVW3\'I<1 ]doO_eUbTkBS;d\ ?"If(Ǚkhզ3jO&C5os{b#m_%!6h"Tfj.ݳ9$8 s?@ʏoPrʎ UZUrz.=<4r0TXUzFj3OF'SNޛ/'̗/h9曐]Y7qQQU' ϧY&a#De=,\XU]&ú-u}=pE DWq[l*NǓ3KSM{Bٙ|7#Dg5LUh[#=k~#wﮇ܁ǩ+`XCqF/I :'cwIMxe^݂,q yG,\JYd1uο|LIEHWk<iwxsYh2V!ƈTG99VnJX{n C4Q4aaWsRAXrYQ/ 텬TTE>lYqZ_4# \54)lb YgH#_Z7,XQsa[ !}*NU^W'Wj>O_u{7-Ҟe"MnF"4wA{e̖򹒬Wc.AqVlhg+00ܯ}$hx+ƪWx܃4^oL\7̚b% @ |ÉV:ꈎk䴯+LNrڟtDPj 9TȊڪ(3-gOb g*qXbsz^rfX5cV@v$scXUtGqrGvsՆw6NL:jq _m*(N1r"*ugh<;ayS:_ P"[dqkkje" Sjo_>r;aIRdA:ߐsv`;DH ~L A7"sauz_d`|2E0okyhf%<QJA?>0ͮ4*: qJk AE cy6:cfI~> cOfu$l+'Sk1yueФkմ$5Qu)5;(6> g3z >3g,!"00mcor EcI-e{ثp6[U:E%_jMa`: {:ϑ7>Gcl;|A\T8QR"B Dww8lApkȬzrP _Dr?o(Ҏ(‹" v&,o7yBPU81)SUL(n|˜+` Iy9aVeb)`:Ck&PC5D {yE^1o,{!ۊ:Qea("NyvQX7V?z$KQ|cbxB_Drrg ֐Ďyz\p!E[cts1ي7/orIAQ/0z*3kIaBȨ[̪Oeæ5["$QWsbb5Uy,l"N1M^ynUcF+ȪmQDDONNƖ%#Xb7_O>kvN+"ET{O) +c5D$ FSTSd[yu$Iri/dN]ege~ԻM}1thPԤwp`BdB>O k+8ۄa[sks RmG)97~ ,?f.ٹ%1=}$zW 6_-] #>>w<&.2n]Q0aT 00/?uzb%KcqץKS[(tV|OiWJX/+3;h/c } rRɲ0V5Yhk$019z7U]=a]"fU0,5@ǨŪg)qK;޽uX Oq^Ƈ!>T8v Ssz/<'GUx=qQk,Ո!Fr*"*G]yTXR1z>ٯ pa"Y8ԊB?DYXd䳭ySh3.@VȘ%C^5UE/rK ^M&i&6V܍"*1C2)Hv0Ks<Ĭ̒kϓ p،OV.ȡ I׬gmSuelO}NǮnE3|_d ",èhk)@!!MDt zvxK}>6Z\2ngl*l"Zαx뻢QZFENUw4lxwg2|N 36ű9VF+3r GSB\$"wξԘ}M)6Fm+~` B4ZboGNZv&Bz; qT%a=NS$؟K$>T,ud]e׃C: b*+_if(Ur ꆈa!c$Uwv@Xa=S^W'>'Lg9q}?E`߾FN%g^ǯX:+IC^z8 =j[ֵ+w ȶ X& UϏR8W*R2[1OufOz6={/J53W/*6"'\d#D"t4k?l^j*/!DO^?TXq($vUs`kV5^֪zqkU]yLAAv1Ecs~ Z}u[q4jvpG4'ksHQS^Sn1ʭDOi>?н>9羚,("$}ܿBі $v 6`y9ʿQ"87cddgw%3xF9u썏Pjpʜ{]Ϫ꾊1C@-cq^dpys/W*"uOk٧Ra\Rb^%%}UFFmbII^OŁ偛e}+3/cm6].eEzD7\DjEN6YԱ]m^DU6lזi`> \?K *$2mMX/rqz͚n5d +2RS6ikHAN-ڞjI4V夂틪ɵXF҈E$Qٜ:Y(漶O`]8iHp17m|p;eaFRh:ZrE(rjQN%$rh|YVs.28yηZG) j-o.Z{|eS-\  _zPH2Ƣ n^T^s2[U#9T6hܜ5y_^zqJ}wȯv|y"kaDP1, k:gƵnc"*+OkSzuGOSҙ KAw9_ EÚo=Ԭ7Aۛ#HRt#{/o+^ ~+ :\:/D:57hZ'=y!quCƐ#Ǭ6_O3HV DwrNi˻_oc""x9&]UY Q4 L0SWDяj!HJ"l=c=OqO'tUU,W g:F+h y3yj=:lGHOq^ɐr cyCt2s8v*K;̟'TlXzu 'ٯ[ j2[И̾F1=ghJz~%:P +klZk0bS7h G`tWbI{^\T!i; D"8QF(u]㿔6Ez8,݆iֽ0j2m*ib DWlV?(\5ג1u"$9&4#J>@8;{W]Mwr,F<yҲ r] Gb+xDF8.`rzͫVtVcM%|Eeo]TCz øE/"^QlOg\dpBŲ_X"DZܮ LC"cuG= p(hsEU!jk _%FI483e6+H'r#ŽG=5G*+Ip^{?.j cZ^Uk=UNʽz(ƹFQEF8,q? O69d!HG;./=`VsP7E2#XkZF>"k}\W_^mhWS*bั;u'|ǭ' _IvP" ]emB8{5r=1hiB][{9B{! "#WE̼֚TYRVA%6zYVQ#Lak Mp0iܨDN\>'`(/KTl+5˶e>Օ=%`%q~󰬁nOugXm^/6 PFus1(XDhܯYv5imF`q}o@,{Yb/GK8$F{+ܨ-Å} A:]N3eK3hp'P.ws!H搈1w)Ro{\VpʝB5!%sּ%ʳÒs{{?OՍ|vߡ| tcX0f4rG h$k']cͯo_Uz0~!Ke͑╙M!Oshk8 {swzSt>@_!P&?6\YLcLT>$حVo S?y{\/5 V?kbJܞ U^8NzZoGy/…[fYb+,.[E\W$c\Z.dy&$Ed r>ArLQMNA/VI5n7W[G1_@kbQJlf [f@:"/ԑ''G]=C!Fu1)ޝ'{Q!peȎR9ԌE8NGx""ׅ;;dvi,bvWyW9(Z7JVXc"K\_ Nxky^:DDhe\ob=]TN˦2;r=LVrǵJ~]tY*/v2{TRFz%c I2 D`g$r"}ª"Y``Pk,mOqh03\pc~Sy^7#8/o"J@Vs#Hw?ް,[!$.y0^Xv{ߌ h#Z//Pc1)*1i򫚨~޾Dc 8j?"/"qҖZb`s{^Z䐈A~ԭojԴT_})Fiߌ?'r"5O- 8VV[T@s1365Im&7סg:*SLwO,}3`chfOj?qV!Pfal&3Y5 aȲ}yk0W]dN@J5,' Q{}yN%QW5#ZOm"pLT#"@ `5ZrOԽ{:2~hӱQֵùOHIsK <ȗ#DWdV}>Mx,{ #cg 꼻T㥄 Z|b@4IF1/pZ>'Lf s@Dx$1NEFnj$r*~DoYvEC* |q^Em^B@_MG-#2g\DbL~DVC{edpO)|S$"iT mTrA=϶T2&J2K&Q"AUk1=ZƢ'*""cəhJ2be(Bc^KXm1Xm"2=Ib5ր~YeEZD-os>s|T¬(W+F uuTV[72]k 4JꁖjA/lb9Fɟ | Cq Ӄd 5M}OȖKd(d DoryD;_𽯭wI2kc-l[D:T*t/?ڣȭțWw/*9k#Sf99.!V()p) {} V;rª~*:M#:\=a&5qWaUk7Ǫa~Drm36>/ Lp ,-`ѽg [nonyKYZ"Ut*G۶j*G"zEUYK"YA>T5 I+ eI->ϻ^؝+ OewgŬk:wu$A WI 3wn/pj{?.ɝEkqRA/(H֑+& ,KYo'7Ef nqYɶqj*`PH}\Θ6ĭfDUWFok'9%ڊ㸪xܝr⽬dפrG=sJ0Jj!Gg:U2hcZ+5/4{a,"J NJUkWsJ82[h0 `Ӿ"6fU誋5Lc7ljc] (Ty>#9]l:ΆF8rUDVw;Ys-*[<_.tdiIiaS 6ě(DEDTbx_=σ{6q\acM;.22:̦#(k82 .ѽąA㕐WMUG6-G"-Z2{|r g}y-ae8S XqrlO|8"*kUZ^'1<|_q{v'm$3 kDzsLN}: }Ccf3*_uK`ݼqܿUOT'kzqd;Q?ӄ%vY1+ qmC&CqA}'%;sFc\U<1`z55;f#W*F߂CXܮ-ƶzy9WkpFY_/2ֽf bAH*rZV'µm͓MXME6EW̶dP τ&H294&, :~8ީ6#/QDsS:4bBϢR0'瑙Q?=tTowQ%ILZdo1*䰳r"9(fIUuY&mVQJυEALsA) fG`9։Ľ+y.̲ Cwf, :?ح,;x$ 0DWխj"*UQHU|JW_MaaGIJgu- %#gAM?"CqY6\PVPdWx{VrsV'XsԸn=; y$9\Pɿw% b=F8-֢Qޫ7ҾnYmy:*°<+HLV]uwEzqUDI^,#p&rF(ib;\v7QUW9\=WU~FM\cKz;I)``X(e@okEEEhAtmq1`17wFZWESA1b<#z8&ӾX6Ub^9xoz v WVWzW9ʪ80N W@;j6˔ɢ{]#Q߼ONv u2ŎyKy-T&ņ&GHa& gW 6o*YGg]K.O.>"ďr=HF}rH3 X[b3D5[Jh,25jzX .X\WYQղR$U&E Fv&9\:b3#AUiڱ $!*™dpZE=͉bSŗ04`WʄI%S{0 DG1r֡޼ (542;%۞cƯbeຢ 0Hl#VY'6&Y BȮq`v xiiBsG(ǿ{xY~ 8vy(3acx)NXT3%I=qSr63DXIt85a7X\ !bk$f́Jss*\OkU1 E1y-IbcOuPF#QH +G:7|Y͔hq; G Tos8y,[% a!֦\?R>P]2x-QNs\TELECr5ŕ$R 7' #~: +WcQȣvka2L(Sc{bNyP"oEWc[1+> *+Q5J{TTN&]q),al8}y_D(ڔ ϗ!( kNF/]ܨ/V^UCtRbP5Ɩ g40&Tba't,WcX-D#,Hk;{TEwXVPqCjW18DW~Z^Kd& k),j\*40בOV9_ө83*qc!+!9yS4̊k*8yDUW/jGڊ˞JHvCq юFs}zJl<1SwSFCoC>1{5>Z\#RGy>; D|Y  FHG`wd~"*:\:=CK_E8a5uh)N{rQ8.ǚɱ)"yajk(خT kchOw #N=QUvx;g"[`^ 9 8AtyP+\e8HG+\NWlʟ7,J8=±rG=s]܈O5C+9ACƢɬ%WP\79fɪ#/ n xp{r=T‚s [e VkQʟuHC\$iв(pN%ר"N%|e(#ٸqԌGw2Y+9̑`a2JH/LGs}=FcX&0Yx*,ꎳ ̭'{H,Px>Cƹ9U1Gds>dːN##~o1}}zu͋`$v#4y=\r窪qܽh5W$E_ڨu&ERzeUe1b=t~^LW,f T4{?ϨX e$%6ה^_`)+‚P W@ԃ60^~JOGǃ=YQшƼdmWJۭj&gwjr}~\FcQwW1F¹x}%}JȱwGzLg{!݅]`I*46"Wi\+舋'PRk \qy4 r5Nh*荊%cjQ2,ylJڛlxA9b±d2#0Pp++rkL*ґj-M][%,!Ԓr  VC_*l;*3T_n3e6 Fj2DAR55XBY8҅+!t* ;ɛB-}\)c#ODH4154#oc8sqNgO$4rU"2TJ(;'ENO␁p\/ UkX-)|Y1[2*xV2+pCI殬{sDI)]aPGyF]W*+]܍D~yj*w=GAh<&jDyND9_hjݬb9֪ ibEy@ 2Cc|5t6CjC8MG'r+#fvSlO3/cLǭJkCe }wuG^a1{9)x՞DZ0>C_UyfKV2-S ;qsVR.kֻB+1||祶@SZ+{a|1,gh{QdfEa"|G Uk+Bli+EYʝz-&vr`Oa-%MuE姴9KDlE+U謇I_,|cY]==C&2,c9J=3uu5OcPn_K/4Hyi))_ZɦjzhjVuz!s=}Vlw%%nە0+du7j,st;zKV9b+­=[h;]>ѥk>\VqCtQB6P$>ЈQm yY+*Vβk`U*Y1>%i*slQ'smtչI^ m4zY(T ,h`柜 Ħl@yp½߭%Fί,(ACFJYROhr郑$V@35#HxVyEsTGȲ1+h9x=3 -\h@+PiLY=G=QyD7f[c32ʹ?ccؼ[\β$Y}B# ;w1M;dcp\:ZF0f5kVIYvEj VE J~%'1\UM4Koh2X+! kr2_Zl U;"Ln4SUc㷺}e`JYHp!0lEQ2 US5?NKWOySP 1"Ktu.rs|VF,w& M|Z L捭?h, F1m;MhZ\GlnYMԗK8Mmf3lpR:d#\>9Kɬ2lske 4U!,~,F i^s\U`5pԷWI~dBǣ`TQj99ZL_>wVBlJ|-=#"aoTkL]f4K(~Y!؋ eZMEH=pmidC 41УWxYW!ʍ{ZV&tP!$B$ě {׷sUȵuQgDaRlXlrȪ` Z6 k1ZEU'-IJcd/HH`DʞgJ*$b2s#-5rb84Z%56XmPԙ>Bt6'yZbP_sLcNtm+#X-aPl3s8nՅ1ES3f~`3fYz1ʐ R>(Wβ.(P-Tߕ_\*AhJ*"Z#Z1kd=frրw+F2f,S"W`3~Y UyϬ-f:i-+dF.'4t(Ua DUjO^vCa74n-cukGƾmpq+4rgX4@ +,wG㹖O6>e_b?.,Y<21[İs%32A3gsG=*.?H10,c '@mp uiڅ?}gr ~Mw "D(6ɾ<ɬ‰eZK:w*R^78'ЊE̥gj͗@֨@6L<h];-r:;ipDzXTWwİt].~Aym՜9uF3y0BÙidbkϖS"`ap%ߺ$Ojv4 {\W&f9V*:̆Ka٪Mhk (HX]W|m.÷*ig| 1ȭ)m)ȴ چ@ȟ\lNbP`Zİ^+hqH]]y^щq&A^cH9R{raM peĒ&4<a=Z9j*qN>J(m0gũ8L5AgjuXlNWiK&)4u2"Esq 5QŃ_aƏA[:-ݞK% );ڣ"֮/7]W vE8A=tvcЌkq_-4T#)2~Mv`7UrK<dUyC-uE"Rh3I.!,mkQ$XU1m<2 Q Q{~X˿k)5C.u׽NV'U&OI-Is?7G|\_km[6]q+ 1)S$u`LǫC$kmfQcҦXU,'-k 6`'LljGaЩpM^hb5> @#C6y3dH!ZE1ͩΫ)fGbqS 5&@lcVG)8=G\{DD3o߶ԸW:%uB^+d>!fTyCF搶seB^ѲAC SDls.XFt14<x=:wvR89%Ҳ朔/2DѱhRl0ݕb lkᜒut{;%!j7+\ 9nM\2>^JN,tj,f`R9!:/+7׎6ϲ2Y>Qyaی1@)vGÒ׹J1pִn=}38/or6$9x(ӹX"VPےfr(Lی~yŗSt31k" 7NlvV{cLRh[)@C6 _v`QJlpuJ}?3\ i`s)\31TljjɜySd2 t1bF9ʪ޾J>qcKdB=H Vc5x,6ᨘ[jـ]iU؎Xn@=,cl񩂮ږkb@2\dpb[70衋 M"XcEN ŊFCx,A!ѣ6Z֢#Q8ONY"4k\׵vDFEQ: Z)3"`9\],zy1ܫ+NY;nJQyOqSD=c+df94g5QZHvl ^FKԸ VߊhTo?tn*58NNM0LYdٕeV`m-@:ck(Lc!F ]\uWr˳dի:Nu9Ҳ+X:#X;ٳO pa)u9_dqrW uw<&Oߓ_% ZJpD5o>+y24+E-R/_'G_u"w~qmicropython-1.12/logo/micropythonpowered-art.png000066400000000000000000000734361357706137100222320ustar00rootroot00000000000000PNG  IHDRh23vIDATx}\Ev]mL&] H,",Y,AB\df2?ԓ7ɗ o湩]~o}ΩSU^C4ҡC tFAm۶}w;M|VQUUzG5!D;J 80Il(Qzx֬Y wNqԨQ$;G}T2Eq eW5\qZ.|\p!āWG[K(QzFA|@ Zj{ p8jS<NƁB% 7h TVVɳs#6Jo(QZFSA z6j̵q zh3W>) c6Jo(Q4:󪫫!8jE Z#"?fFE#op! +VG8 Lp%; +a q*L>P17Jo(t$ $#6a ~ b!1iџ?mm> Wm(Qz:tc4:tM:X{:t M::tЁS(*&eYtWCڋ+駟:tg~~ Ȗ{gOtС3:FS;nb8=c)].>; 6<ϝ; II~:`HAd7CN(9i\eF`0\Jӗq [Uw.Kr:۟I?uoMvݻ<IޖYqa8UEСCgNe|̴4Ks?V]3yÕ&a鬾Uy%3\yˎu[ا \fh=&>Sӷͮ\50ΆTm6CJ_^6n C 8[K̙3Gv֮d1TGy qd-,"mQɇ)#31UXv;y\ Z"Rx "kd' C{ 88YL{+A<߯[t&˲ cB˵/IICV[ **o4,1"p^~i)YIn;\n]h=1*}eO+Ҭ.3G:mi /{РA@g23*7\bzfNHO^o7/ mk E{:;h](|wsنG{*:>%M1 3![d F'5:~U%9_ #|+i_ļ[q:::ʒWFy̗_pVƋ]s^QjEmimu񠑩Fmg~vomj}yC'?}@3{hTEj4zA(>|wAǓ+X`X ]SFyt}7 /HahdRYiPE6ݚCuQLKƈpyݚu:qDSԘ~_ˀ}mĈ',p'OV7;ZJHbcU)O;;w$VJx+W|eiȀLŒ4 3tС3Z~a=gzfϙͲV=tСf,8@ge04́cdC2#´ Yk22T: 5xa f7 RZPC}7n3䛒/.0 C0-0I߀ AHd<O E?3ãL^oÒH(s2X6oӐJsUk 8СCh]==wfV2Yۍ ҙb*,cfr’`t{b DU՝qma{PaQѐ@a >P1z;bMdX֩C)ӋqX^ 1(_}^{-=#o20 III@p$ 8e3#,o5 .glipKu8&O Z3&XS42`*F2=JN_[;}n٪D:tFfimǟؘN#BQݸ~ήNSSSGW_}udr59R# 3tR Cg/~ "3~:3L6!ʇ9zdޙg¨;?_}yDP,b)vE]sg\.C0e 9*QX+XE өYW2] K& DiV0% `abpkȐ!HTh4 z[.'uT!~*owqضm,J[G >hќv%bȎ8snq^d渉CCzz֯۵ne񐡗]~4S&ſޢe{.oGSM^&# 26Q؈,nkevƞf)165ORȮG^;W]:# IqPa~ "KXuuuB$B|.M$5,,Mƒ͝,6'Nj>n-E"A{o9BATYPMgϓ>  9\zA +ڍ,31adTZ0ɮ-Ͼ+:>Y)#H&1􋂼H+VtMdط~4b8CVړ+HX/lΝp 3f̘7oy1du\ t/0tHjTUU%kR#ߧ AALu׋fYa؋X"Ѭh&lV*%Z pyw`M y?FsűiB7]\e/K "(R-vE{5Si˲\/^Ak  LEǒD/@VׯCZ%57%$Ю7Ԧ]lw=|:{Ŭ8$3b捴xϘ=Y=e Cr0|urF"&zzzQrssUO@j@qF=x]`1nؿ?n *`l@nΡ =T^_{sI6"瞋קH0ёynڴI0?H@---&LH( . ˍA+,]z _xhZO?0-'ГA"y/!h~n ؇NDq_|?Z^bWnx <3*а؈2{{X./;7ƔÏ }}ayF׶p^96Pbn6#']7_?gļCS';YNH8@>A /ΗIWJ`:ik ̯=cO(Y*S4A:PySFL+7kh@Ge_r#/={W^~ͥg9ͥ[G;O[$| ̵Dx :Hr ai`ɓ'`V촌"P`jgP/8 *sTh0N8dff 1t#@YWH?B)t`4&0B -hR7v"o(R%t+b@70FQf1P!3fm2Ȋېh+M[,&yT8"BޘY)KnHb̜omY p0/QZY{/#2lGAHrڵ`{R?o 3-Dz /E TCC.匇-]U ,:0H/+x?w}/5~Fq*Fw2{REu{ִ( Ť$9cpexLS@Qf2P.NRnc(cI`%Vd͔9{8TGbSe9 GlA SaN|Εվ1vC^GWfaC5ݲeKHv4H!p5/?͟?~"i&SRՎTK0⟮/&i^;]-Y|(jQZJ1"ceVA Rh11̘)d$+HbxDq eT ]rC[u:;{{ɋ9[ӭj~,lb+f_g((䶚\# DOJzSS}~^Q}}l2u/-GueN&GkGVOv`>L/S2Z`8vup|EJ!Nm!4ٌ/_c9r% WNHpA|uP8 Ԩj0 eáSL[ûg8u >AUq5)k9BX'|xO)HR*}Pc]<_W]~7__xo!Δ7fclu֜}#-T83L&ŤD1R4$J(1cÊ 3q2RYcv2؄M)AUy~ŏm'T7R2B0̩fMZ;Y y0}ͱQ #pO4aNXT]UHg\vU :Cmp%]&Ht-7 `:$x7L0k1U:K CZ=D![(+p8Jp 焛Gw`h@PgHIHT@Dx$- CH tɄul2>ӄ G5>'kI奔^ZCHm4ҁĘշF#Ba~6t"lZ'0=9kfd5 1%Ng9dfk!h9 Dawmï.!+pYƂLNc 6`̰f(`ڈXE%T*fy< 7ggɌ,в!d *mA<+#+e#e$5(Z,77pxW|6oAb\ mDa99Ajoo،#:+Kla˖͛wt+4RzhY՛\cuOBRWqL;;"3B0I ė }~edKa!@x@AkafHo| uZtR/ vM'Ps@P%S/̇f@nkk/xDa ;zacLgP1Ne bZf)qKrgNZi׮#|[ ]ӧd ^65409ʪEvR,L 6SQhERb ńc(: 2|4Ȝy%'/XL:C/hgJKd ## dӼ(EFHb(zh0|A)Ie̬Er L۾j7EE)Ȁ/]޸ЏQW^hc_B ;CѴW` D K{aVT 2AŸ8@;  ҵV |"1h5!kbv@rna"*}gL(iF84GeCC"!@E:P}D:>,A% @䣶a:oyShKWW|Z'W~HP Dee[@|vȐ_ybn$)>Ӏx&"+,?@Sr,cpA_BhbHF`^B m^(B `NR<yem捻}R&[͖?ܬp  zbҢW%HSx $奩{5=-ôdk6VU+ :="1ÈG 9SrrʮiM *sgŸqЮR:/ c(}jwQUNBOK;Ժ?= BpD -T=k q^ ;|:(..VE!@JjૅЪ4iӈ0"^0S\UA:"j>|>zbWQ }(] 8 aJANIG/8Ԥ3̀_|SUQg4a 1ZM?Fţي1摈$cDE9Y`i P(9ÊR tb׀W4xC2:gĂ)PVTHW72 OXF +T%`ZHKK"$&err*J1yꠢ잮E=nM5, xȄB,G##Q̀33< ~)9+OȁC'?}D6HbPfm:_4 ImP '#ҏt2Z8J1#(G0YuҊ]Ch5խ/׵ӜLXsbYRE HA +GajR”MY\t8~,ӧ͍ݖd1KKBgRhJ)H˿ڍ~i~yǾ 0v 881KYKk\VhUƤ|9']x1G ^mҙֲNFu $\Km8Ձyj*/%~? aznFx"GT !h#?>8st7ް[ShJ~$cf[>y>կ#uVĚ<&Rkuck/G/QhQ0**h@H< ɔ!;ee#@Q4TV9Pɦ(FEAB btL֨A4˦$[l*%s:*LV.hB3Rhhnne93;Qcp3f_\`N0$CS >lx~U0aNyXtK<,$uCW8_5S(v4"Ļ};oj_ _A|:Hd| H4/JIKk?y5 UGkահ$ "0}$(P>?)ϥ~&TLަWrDI,Y웯|Ҁ?egϚsRKRy,Y &'u$L†܊JZy ɴU K#a6( 2#lLȫP],涶,]^L1=]Q%l*kI3l7ؐ*YvCH'Ai|Gv_O@L }e[m۽1"jxNdY24h #,"Hp0AO?zGzoOTOxG6ց7):6<쮣're' x! $P[s)3HPi8uˀg ȠjX >z}fv||jgNYmu"zbz`q:9Xrpʜbܽq{#&1[N9%ظ^d-VFݙ9Fs4hh ƔJn}ghZ i x.ou*,LA&YWr2#e,FE"\ 0oxڱdb[J_nf6VRY[d];}Y_q 3+L<%)@B1BlE?j2j?A:wհ\ 䱬uOE. !@Ȁp_V!ěO _ixJRyY.$FZGjO.O\jQgMZ``vb0paV@=Wp+U'~w o%mMň@S28c:2D"!*T'1OY[۝bѩ0C*<Fi6#RᴘVAQlZְB_卟wIkpLzƟtj w'ڄhPI,Xw 0EӴaVon,Co"C'oPf/PD @X **wR 5F;` #," 5 F#b22U<2R724nhC|!> X7-EGHMRB뿙SL %+2 u8jKR<}1~Y߮J\4ƙ@I=@w E{s/=mкQ##JH1p1[è=hd>Q(ލ$uFl ۛZCH%K1Q( DP6p'DHT.0"Bu,{0r㲋F\ ڕ267ԭCYAJJh`7Gs)'LDfh Bf^ 66|ܼcam#fF+yܡ]•샵h lX#4MR p$C> nVSe2 v)+R&HdN!q tI%PܴLI3IA E= qDw< CZWh YI*R-I&kԞBɰC$z`B's0iOѨ*B'!>6WhH{e;m=nɞBv|ٗek&ft)tJK}.l $,I~ف {2t۬BkBT+#L'zXJfO(bY8 ʀVo}9?o=-ⴘbvLY<5J)+܎(9f\҅ Q%޾7tU'=&DwPԬ>}ab7ZWSRnE ^W况K_p eжpXzIa(A% vs/9.?Iu0nJ!pa5\x=H&!Pm@!\R>(uJ3ikj*BM%`dD2ZLqO0,744ب#[hrj"n2tPX@:4uU:WϚ/FM7zkh$ ڣSM;V>{=qd7p/uW|i;m7ԑl6F"ѝUf98E)&#]+WґGf1l7E̲oFZ qtl͛z{pqc}~BJ{7x]B ܶz=3$MtJ,#dv?V f6y(egCV3O ($:۲SܠJRXeZRS(20ݫs1'rV{xD1Ɓw^D%uLR/WSVTA/AG#ю [PUN |_iZcWill3FjIW;ZT:;ҳf{qpGe7ўvD:| .ze2zszj5Omk6t߬kVdjeô7rߝa1}wcw4eqs.CH1H +ӕ×|6 {f8ɍ~F*KEj֘6XڝsNʧn ϣuZ*cE[U.[k|#ꥥ7܍I{ɂVP%k&IJ=Fs7]:;N;)pӅ)sz/plr5PG4R&WGm<}٧]&ڵ۫ (.:mNV24㧱cu;}f5ٝr6 z=m>oc}EFgfr4bD!:S4 ۮcT]#^RGh0TQXsI8S,M9##.& @*L+lS#A5QFJaғOQ=lXuKaYcODط5{ $z|v3FD`lEpVҗ8wи5 &聈h1R)PH*|Mtu\Şv`c&htSesy]W&5PX(2y`C&O1<>K 1`_Oi:u /y55Uk/T:c9w_ۯ ?4( deMsTJvZZFAaХe i6wE#acv:]]Gc4`& 7qU %OB 9ePT- [qTe?U_mNpw|PfQ8d6<ZTR#?>ۣ7&p-fl</]gSKOxCλH*i1,GbE"2!;-b r뛆fg*X o <.(g((I,b7/"5{f E݁Y%pL.MafJɜ,tMUO՘$Q1 c4wu#o1gKl)$ -]˾_381ä4MkUR􉹄ΆO-(oUL Rr0#=몪8xh۵`YmNo3 >aiYIN4~rkKoBs)W G?It(=`Jw\fW_UY2ufɦ+]fQnWWI0`ND"-XJfU l9̿7}~6p Wms7a#FV:ݷ˭fqΞmN{V^" -5X x}Mvۓ\."e5؄tu-"#32盰R:?61!'MEJ^;y+V_JOpN[w黯<$%IѰ#;h9#6,RLbBT%Bxx,r3^m׀XQ-Ϸڿ˥ۯߴEwt676l.g4*C@ɐhTijjn^JyӒ흭K?X zax{Yr/Fުsh ,GZbX>,` 4}3PK(wȤ;â`ՔlἜ(2"`FhQF}uik׾6t`'MU[s/ב}5.9=?)J=$ f:) PvzԬήƃMf9=-9-ٽo_x(5N%b. zܰ&//clșr(m-_#h/KcL6Q4oLi*"^9z|Q=&(, 4l6 mЙeѫ/~km``LT` ,x%նvtE:7Q 7E惝77:xxIgGOYiM^A^vnֶBZhIJq;O)3#9XQ)IRZf:̥tt k;':3BVOA&gl)Ai3B4QdLQQY#C+<)g 2Ȉ%2#KGgGg\v?xվ  z(e4Wl2 'ʊh âBP1Ȣ724)"ź\|f59.=JlR[s"V(tº&c{w59zHzzTǛ+˒cB,A褦='\apV*f*D̰H(2%SQ%[.G$ g0B4c$ cL#VaEpXV3:cF7юڃ5UbL9c EIc=E%q!a\Srd"QA`NgVhѨEyIEsvo'a;cs5;v*)rBg w:m6m" 7V^QYmIA#%5 M/*Tz?z#t%lrKmhE$AR⪻A4+| tn۴rW,{}_L1|S6ۼjnbE9rV^zv!82X$&asrO_pԩ/hpB=˜:}3dI) JUQn<-57妤%'­7%93ܴ!$y\mV)A *_^^޽3\̮Ri!:~ ;RW|σ驎%0Qg3%&kE[aNMZi ]T, QJ ʽ[tHJZZ)tr]~ʷڗ=u}"t+Lkinmny3 4wѩgy30oqRkGKU[䲀l%ΊJBaaI,$YͩC ^p$Ɣ0f*l:K.y'O;dB5IoMdРTvf)Ӑ1Y`ѫ*,1^,sT_91<|UVc`唡˙0_!3=ƿ8x(+1qF[M}#g^t>xcKw㦕,L겛X@gW {Jyxz$S4+V_D.Oʎ=رͯ HѽaK XaX> f_dL((ʤ/tkٯx8榎a/vxmWTP fR|wSNW@f:u<=dP/w͕o; lO:FaVMm7YRǙ t?Qx֛:sکCt#4e^>ذڊwxfOu98]8&zkbВAIRwg^|mahంi2 U~KJ$ӾҶ[kZ;CPh5KaXbb1>1Xr 'XM#ѹgukL>/>{6i+oQYy( YY] bzz:CShaF:t4 ' F:HF8lc `_A}IB* =%#4_L R=i^ڪȲmbsXwL46*'HI2 &p=Pa 4C=(żVL7o[ crpkZSSS/);p@UrN+UW5PȘ yYgP×V,uedS쨯;ؔ>`uw_oXo_SYi}XOI"31yGj[WgCFڰ|Q_͸ is/Xr^Y?L5J; .7$רb:~Z>Ng埵ma M)qslm4!''*LMYyH1 R+z₳/Ι:3 sκKJ2_|'xjۮfIE$Ȕͷz &Qqv4H"WU%p"nIMmC*j2mF. 4'z弁>ișOڼmsKM)'wY4T)FAB,!v}_>ś:f4tڽk -t)+Wi6tUo.r4"-hM:)Nj'@'# ] hNJ@ChZ%q/8L[U_PWqK.$rNf)&2YX)pMIK)mVo]]ؙ\s 79mg^wʢ?y_}dDbR'o[pEv{әwr2e,]USd^`_a!P0nn*+ 'Y nL_W[_ BV+Bf^׿7vCnޖN;=o6VaI QHv۶mE(JPM'zqhh19Цȃ#>C̏h7öXdR$r*/Gbљ6$IbْgLzî[I4W5z{74o?[o sκ;n?`˚rWe͊ҲGw[ob8 72~9]S$fS)j+KrmEC k/x!c`[s'.e=aMBcai#M=`( _~}gwf)۷n;픹|yIpsKkiκo_ "$72r8f=\DS/> O G$dQ9p8Zp~r"'EQ!kg\yn{q(N)$ #*HSx0*[,^Rd)1R_iߡP%}]71AaǟPQOW6euEЯ@vN!fn?ޱ.7^awՒ"_ݯx +8̀/Ɣ4'hڽ@FzNQ~2xwu.aɧtvBQɡRG)WRG>@Tb/d}ՕÐ2lX]sU]]ܹ7>ȿ{|P9;74yXFB="`ٕ0Q***@S|`_~h[u;i2yfpeB!C@՝-<㐧vZ^W:OHoZ i>n:ӵN?eDK!2xL1MqciƖ5U#&ô#aY! L?xTH ȕVnwҝw=lz|'2AT$**Lfl{ߨ;P;8{x!(0=5gyZZ(|T_HIPhVw`Y-Lɠ5tIyK3XQ(DXB1Gz#bi*K&,cw߸?\i<} +jk!ɭן3U'^may$δعs穧 %ٛMⷱ?VK0 q9 T >}PU$tń z@ sT:i?:UAcM19fcyEJTm,fbj;7Mnwp%iaYM՗^}7n=;}sY2e+,:[}e u뻛*-]rw۾vkUPvTT#$gM͵ md.*g::v8`g۷{/lڲy E(4S$(XijD9\iv+?PϷJO_Zo΍i@ά$`oAlI` jǎq~zyy !tuq@@(&M B3 31駟TQ$ E!++ jO@:C~Z'*X) fuVhC9y6Y*VLzejvj磖nAsNogzzB};kf߰j7Ӧ+,ٲmNZ@jHI,wYn4{ѐ6Wnn>-޶vD0?Z;B?sʃ5['<( L1g^jh 9 H%CI$5 e#f `MuWmrrw6[AvW:y[/V@t&[`+8 f`&*x ǃ>Bn۷oGq0L tz*!t Y("s qC1hex+sA @oI3Q:6cTD JIi$2bZa(52ưl3[1z{Wl[wOYm];XMf@—>pM>:Q/㈊#g9uk fS)ZJXE) c(;;CO3mU5N37T2sDz±hǦM`is\rg2ug#FuAK( 8I1M3 z{4Ǻ:#e6W I%a*lW'Hm%%%B/{'NL6ABq8 2`UU+AKP &o2*r-}r-YDvݺuP:Lhen:S5 ,n lW^CX2>. AI#M]1s6 Š.JL 1)!^j: J˛qMϼX^ѧΝ{UWWrdĸ;0͌2&/mM&X2QTs}(ĺ3Dr%P {T|ȳъ. eKv9ϛh?m7i;,2%Y0H01%FS߂dG0bhւ 4;@G rBvyτo,X@ 0urʄ9e˖]}0i@x muuu(/?.0vR/PTXXhZ30%rC)DP zHR!Fk׮ hW]u=(Nkj$bƀב>4J4W, !CLcTDiAVNdZ%aSƗh5ϛs~Ŧo;8p`VPb޸6-`n@ʐ$T;mV6fN,}yd-,;;1%z<%:ު6eNIrgw||=lrt]`ـA| Qtp2Ta(Feq(!Z,wc,8m쳯|Ξ6m7&| ZnѮNY7Ca` m@/S`\It( *8LZ98Ϥc49* MTI+T)xl$|xԇ?A\谈" 1R iUp iA F*$4)imqW岓N/?{:[}-O{|~Ejzx#;{1p:JC~q!2-T-o`N?Or7NsW5L={tٗ4Q<=qd`Oa@ U?e aFwq+=vKۓ t׿8 9-R1&GrJY8nŁTC t iG>&PdJ T 2*a@#FU(kogf2nb],: ?Z3ٙWl6^yefggF *kh jR KIM"Q e@m>Ӄ 2Fa,-WL@O@d `Ȳ,t^7 9,NUUe.,՗bӦM 9L}F#L B&GzA w}gT 9ҀXm0Dr QEq|I83335[^@5jN4"f4 TIjNxYB:h˅B0i#`%Ձ{{ghjgpx540=Fu2Ƶmꣲ{~^|:-bEizVo;j4ڍ鳧|ɲT|B$(l2Zo/yKP%i@~0%|1Y>ԫs΅L2nU0a6`l.(AׯOvqXRKvp%S2HRHp6z0TrhM ќN'H!@B& PɽPneee30V-AXoc!CN?/p^woOkgܷƷS껪>E_ӏ˫&Úݑ{Z;C~ eç4Luzr80& =T+䦪҄@] ՛LA]xrL~MPvcԊp.BG|KDQ"+ t'3go L*_\\4P{'}{w# Eo̘~6B/- S Sd0994xQDYFx鷟Ϟsj*BJ d7̹8 {a 'h P\tE .DqXx1\׀iJ`4Z'[HjQ$0 I@qؽ{ 7DcJҒVF#ďg kBЍcahk{opKhP$10 ` JМg||vI(*085JLaw^qmJ,l0QăHdd$r a4CnXzCwIp t8@|'|H K@jjlSrb ,:"S ӧSŎ "FVĻ9tIYoH͛G<cѯC7xHIӦ܏aYiZVP86 1 ITLd6Cf8j KH9^ohR|c4҃K؞Tddd @vSwDqnfE@R/QOU?VaUX!p :;!;4@g4B@]ݾgu_u)n y3׷t "+˕z>xXHp6H/͞DZr oc츿oQ2_fBuuSFq5,b;.#CQ# K"a ?td *u$B9MR@wcڄΎ›귇:B5| <L#65A.茆`u<߬j1w$thTnj)55gNqQ(tBKY-da(#sƸ&o۾mnm:_s6K\ޠC"V3A酪BL 5Ck 6dK,J 4j&dJJ[oaj-FK/S쌄HPR:t(S]t hpRVEϯ߸dLL۱a <2 'ȭ_|%^2lp7x{0hjmI)NT\Yn1`xu9/m뮓&Lkz}ݠYLF0(Q0BR_|ka,́8EQ@"S%)J*b10o͟?OAA4!&z"@iT6 KA #G U ) I,XMv@BdAA 8"^/t"bPVjl u i-Pqd] YBBX^mtFe Ef|gT77rÜ6xҳrj]SKLm.K݊}0 VԦn}ގ9y,wM~~iӚ'x+ L*Ko74kq0J2ӌOS4>//UAd3(&$qC{A&Eq`{1UO`HNBqpģ!*aOSy d8JFs|aD)R: A+j9@R`'"~$ UR h>]Pw d0EcG H=ѩ1Ν1yN;iû}{yuUkcug9dζ/0z+kw5T_~9RZf^؊G؏O9eVgGuJ2O.t@guX[5JnpTT 1ɑBL콀h$`W5V<WCe @9t'؄ԎdG}JP{퐛9w$ 2\mh  m.[S{ "R;udϘ׺9*޾ /AvtwcUy;``zR}'[4:3`7/N.+X"Azݓ;\NtMq1I(InK"$S%2pG%SpS9A4S÷ U]P%kULTVR]NpSw*!Bu ǩ7= _A>D%4ц㋇+YmͶ{ZØC,4q_vHql._t`q$ENUifpN+\TNqW[|>ߤqcHOVS oya)b{,8&RFXs*N2l|,dXPW㙰!IFV BՁ#+a5ChW>$3/9 P2>eޘq7pN5-OmySO:9X?lqIÊL,kyCގnҒQ3ϡiz鄘TK-{WFf7x`6%&/u6]FѴPUxn* fR tH/TL6zeʬ_ƸPY ~9bD%'P oÑsY<8_argwf38&2LlYΛw61WSozFD0%#@!-Q.W+RwgN7f ?l:rIlÈQC͟%UUAY6(5-' $)"۴icᗍ Cޞs9֣)1b_}l&9 nU(B?8śԳǘay@UM@ bM %jCHI Z<'Դ }]F@цdwr [֨ /~_IC`k3gX {0aneGaGR@758@S+:=dz9l:*2}9ӟ[>CO5d'i@( |6Tr .8yą6K.%!&(Qz5J%j@(qԦ=yB J@nl橍0gAA瞫7Joި?d4ƃ6B[QmmE H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FnIDATxw]WuYsti4]d51B H!y !^KQz(l\pݖe.唽~3YrI.zYk]x<y <x<Oxxz<x</xxz<x</xx<Njx</xx<Njx<^<=x<Ox<^<=x<Oxxz<x<Oxxz<x</xx<Njx</xx<Njx<^<=x<Njx<^<=x<Oxxz<x<Oxxz<x</xx<x</~<֬YwtGk3McPUTye˞4 4yM-ݽᡡuA@kk+;vxo߾tc9Ș ʳ_,^t >x+~,xxz|Yzi[ϫ#ӂ/^T -OxxzVѐ_{xx^xc#՟D()LjH .Br?w1TIEz_COe+_0y%Lj|F5i~ewDX |*w ZZ)܋( ࿁ sybx4A|NnQn{+6Q?V,RMD mO"z^iաctrLkL-4="(:F`ODw0YD2pm8nxLo lv>pfG۷{axx^%M'}G~MuDχ ؑG+G㜹sVqg?gZ`2PQ-턁:xAčbK,aN//ϫ1KztvM:83_ sM' 1!"HY | NjyIb<3gsͷn&^vj&)ADnvA---Zh'<=W."&tN\*sFWe ЗG[5mY/1444x ?v>OE‹/zn ǟ٥KU,UUU=>37bҥ/ #OB Ӏ.t{p["FX7KN6m۶=h:yO & 8!lp{Mt[Z]m{gb^{Yg^{oZy:;CcgmrO1b|1yat .<3yc$$Eh4:Fc:+G㆛n W۷> ˲,ۑ2/`1,{.43{;:`zРj5cёZ}!7*>lko7 $ |Njy*mKE<"2 ,ꫯ.gR$ٹs'}tN׬Ys=ޞ鍸F)"P6?z(0"9yY//ˉ_BeY|8M21׾|#sϣk4X$$I=_|;ZߴyN6[Ks[5"i#">Ї?l؏2Jwo噇{<^<=/ώǎzێ;ӽ4M'@KRW>я'x}BAvW^nʪ'8gh`-[7oå~8ۦ\j76({ƘܧY&A6l\όL87tdR*bxxxpR`~Z`VtuueЇ®] px[DDFL9ٱcmz&  4$I|~1f!ŵȡĘԒu#} gCUST}8(W! ih2jӞvik ZTUON f{w?@Vkjčfrq v_6I8e>*5O#oʆ ߿K/|eD"EU]wLZ:xpoMT,rgpee̘1J Q!\ڟjSfo+ {w…!8%'KFxxz<Lpl˜gw / 0ӧOy{… #U(OpN>XTct߾}O>Yn4Rȯ[.'t"ryA9s8nv=vz}m^x{xxz^Mb"(&,{0c/HxPVQ 1Gkwwwi֭ő+/"e˖sڹPUz{{YbI.9t H&[ƽxx|Un|m_ݽ`ƌ:7=R86e=眡>rTZv)~Yq氯 0Rw׎e\FT*\}ռmoCT(LYzr \t1Eq2!(xxzp\yps^-[7_eYE:hԩ4dkL4Ν;o%@.b>mGFu6:,NJ^/ ./S˥ؗxx j2 '|r1<y`ײbpCS~a߾}lټ`m̟?qc) ,`ɒ%CN9yKV8hkMMarI'''Jv\)"1!Ԋv,KFQ.K.E>vX\gΜɲeFҽ3p& q2Cmiѳ V84;:'PBbQq9ɓͲi0~̜9s9Z1 R0oV-rGBVVҎZP52U݆VG,#?6|)R%GOibNK!0e`YL>k4ۻޱ~L5o``ĉL2)uΣB!7 y%# RDt8Vu7اl5k ,xX^@=k < G#p٠j$**l~\WUNr{Ku&^K2(bܹL4y*1 bDĀB0E"",3e8^&C#)\///aJS9ⳬq6ˎ Fwu[9/`HDw0ȍuT,b! pJ6 syA0cΑm|TD0=j:Ց$GAe> xx^TP5O{vd11;^d}}m۶#YIӔB0NLܽGy'xR̒%KXd 3g$pk(`85f:^&"5ƌݮo {6{}c |NjKz,?fM40˫i|qW~m돵Zm\oZꍰb /qy&=g˖.7\z٥Gwu:JB!S7D{v>!6$F0fTT˗'G֠g2xxzO>;mT8 0ƠV{i32B! SNNc֬YG?>;wXt _ K/{-ikoGUСC b0jGpϮ q*MeISh4z@ȅM3?t<>x^݌( фs_W9R`xos? NIR:A=C- B M⓫Nzlʖ#5mjjca$6mG?o´6[+8A3Z[ZxobٴuL`bczَ (# ׳f:6}?;w~iѓ& L2B1_y]<#m?kߺjۮ}jŀ0-U$ʩ*e˖~ONM6b#mNҶ6ٿ?v_"+XǯlؾEK3g >[c]۷cͺ s」R14uL8npm72T=g^?e,oqL~m'N#O>*3Wg?Y' a0Ys&`h2~G&h sk0B4'(Y*6mjZORqO.9tH֯_O O?oy;Τ. /+7zV<>EJ7Z*0E{^>?c߾o@i]KN?FpI$CJABC0^8_4O;YӶf͙Ⱥ5^s}u '3B  d(CRaKThvxx|%ZY3g>ZvLX,Ro4f ޵ZN6VXd)oy[Q745=]=6ǟhw]~5eb0N#Oys8D$c/_nnaFdgO,IC 5 eMKI'-wMn:4M.\(RiBh,,[~seG?7̆uΛ??pW:TИ|AsΝ/~wߖM[tҥ$AL44Ʊ?h|Pϗ~'Y䪏ol߱<ҏS#Θbe-*ע+Fx\b\yXxgMy (w |+t5* \p{.;vlg۶T*ͼ]&0͇b2'VO}믿"v::O~<5Mu^q3Ç[b_y3eR%`967޽<2N ̭tU5)QDh1 L0ZbhԣYz{K;oQT,7>\s;1C~m >aXk6u*fʣ<[q>Os?UF-e#(c3=>n(?W=oUE@t*P ߸n=s-Sb7c+ϫ f \&~k5? k(]AcH*`+ɀTA f`(vk5\zKںa-Ǯ]ٵk{kQS09$Sh$֭cŊjQe c4!I. 7ވyŀ4œL)#L=4}QI] _/rw+[6\~w_$eV(\( Vi͝ Y]!L?5Tbp(=!d^_6=;iE:+7bӦMw_0E-dR$ !vx!̽^{S? 9c %Qu*A@-U2+0Q(kƄY&wޝ̜1_dxP_+GH;.ʠ9^ b4SafoR)3gy81vňT* gs3`h++vK,,pR/IY3ڛ) =@4#P@Թˀ-0$lݱ}g̼ ؽ~:_',{jxxz<;;srA3e:A (R4h o +@A *Tc%ڟr\0wVUS l3R25;=#ʐ 6,f=)-S"><;`Q[Sn۝/V7$3˖pz-QjʾzGB漈Typ 6o3gκq;kbxxz=ʣuuGK 0 i&CТh$; R(YAЂ%6$BD eHUN(gLø Wj=_ijHcu,ZqMwۚ )é É!X YF,BAGht= ,AeQk[*%IJP<| *ܮHELZ³>>Ph/ϳ<08x [OIQ`Q`8&M4db, 4 DL E q)J"-nMIySqZP$*$ D eA:A b]5 E`t+S8aAW Bda4K5%{<=^<=W [73y#.ٵqΦ-;Gš\fO jH@bE~"\RW$$b<dGUJR93)d"MNH*tMƉż]%V4dD*:GL X L{.!h A 0BM0hIuH艱 o.xЬqUkݾiFVB E0Mr= 5r{=D5[`K1uUF!\ڄ͜ )((6l-sUmCJ:UCc=螞 ң@>P1$OU{Um& ^є@ig&;3MW`ZbzWY4͋uDPXgEĒ5ԢF"u3T&*~(vU%E-£`HZӥqU\أ,-+N Hs@SgNj Gn?ʶ]cGycp6;sI)m)Q.V<-% [QG:[`3Кbkꞧٸ2u؆Bf3"V]$i(ȥgM  â%kWTd,I1` ;tIJ  0|):]?<^<=W!-8]#{q ͆B4\5d0-Tivψ ;-иʼn DgHE1|ęfdCEIRM-BPrO:PsձZPAQ*^3^ETI"EU' L@[Қb2 E =5H2j*Y IjC/+q?fW.ݖzg欀FЖLE|):j ]ZWS L"$H)_Mr@`ʂ͜#PP Ν(/EüGԥ]CuMF!1) :l2&"M-$4$UB,4c a!lom-F]jzQwOg9>rmm݅5Bi\t6hh";8r dPUD RqC);{?b8{jI(u0Zȟ` ͠(~˓{G f\Hxx^M;zSkG0[2E7ۦΕuƺMI \"LsDa.Ɇ֦Z7Dl]5)=l o ,>D6A!)٦L8sA%XefvjA\[uln\U$Nk:,X1Y&@|YP 6XI9-@y/[VhM? Uehh8ٛű'"৫xxzg Q @E¨jnN$Nyt#F3ݝٴE!lhJ7ln ԍs2%g5&ƥ[C $ \D*kmj#DMEښ &a:j^ Yd7C!,!j;rOjYK:_F.~mWo cw] $,$nж:㜋4,H]AE2l"j:ؽ|{fn2pNs!oGebKהּ44Ql0z霵%ݼo?Pyd ^ȈhXr¢u._` #R`,J10 ia3EB @C\6FT'nNV-n1"U 7_jj6/D  Ժ3ܿa,j M0{o>.gxmKu7l-8~eZ򗒀e'r<=GqsJ74֫nj3aͷзm2l0#y/eDEA!L"uUN*aI3jτZZ$ JFH(Ŧ|ջU5ENB2™ x|uNkS["5&`p2:Btޜfڷ{h_x|#ɫX%+[0y;Лo}lLyO+ـZ:*YL @B»@䢙XIA&I-BkT`*97\3 ; )aPέWɾßm \V0?jǙU*k&u1Q<՗Z%CKꩽYyYX.2} ߼A Ģ9A 󊜴4t@NLZ5q{ՔK(-{Rt"!(b0cYH(@ۍuƩ*5FZHwI'=n֨ ly_*/yz^6zsfE`3m^@%V{.93v@u 7:>Eu̶4#`4G-E= BP &nS 3(X%@ZU+P3)$T--s T]|UHeJ‚ہp&%vF /tf/3Nj3Jv[K[n> ]syCd1ud.˩7g޽̟:@3!D吠(Tauj@  AHat s]%B@I/*IK')XLř0 :[4ȪJɄ4/_?n~Tgz8)E.8s/fU9dǝuB{ouB{%^4=/h.[r܏/w+V^Vyp}O|v%Qk0zFCRL!tz / XQҪ)E IjњT0^`ژ={R@?gOR` !ca]*4u [[-?K:,e3s\Q `-ñ@Lc KO>5ꋽ͙C\az[g.{ ~F]x*p2󟹑 -]䓠mhE%uNBlPd"3Ln^%A.ICvm Nb,,T ^ ø>φ@}3_ijDf*_矎ep_m ++[;ir\*S.Ѥd֌>yTCO=x'4 ~嘷-[zzk~Vmj_ʬb ,h%'R61nXjA4\$}WTC4SL`-6((z[WȣUg'oo;dP/V'&uN܎f7;SN8x.:LP{xz-HwoCk A@ ؞|Ng)Hb0kjr g;>’ 2ChM r7,h*MBY@ CUXG ߽m5v  LeCUʘPZ'}p_~/KI@E>d-/J*prL}NX,6fvc|>˙` 4CuvzDH`m 6vHnٗ6NDEoc[P YQP01jݗleMcH"Dtomc Gx<^h6fofPFY*u޾Zz-r&ILOVC@o{?34M󡭼y;N洅- LD C1٠bk5u6#*A,;2BJ`SP{Bkw{£24axtng\V(YwglН [&0mDvxaۙg&Vg?k3lıɬ# X Z ii B8>"yeâ,klJJq0#;*q:\C%VP.c{BpʩnNNjbcr]|9|9zO߲q;*=[Nq&5+mChO*%p]iet6 T Yj[2{It:#YT({1Mc~=}/QV4jU?eWEFz ԉ%^7H%Kp`FG=NaԈŝ#f`sZ$q) (R AJB @Wx;&cZ5uzxxz<ϛvP 0Z gh`A;K&}G` 0$ [fx۴y m_Qƭ_ *Ţ%B*!*$"@,PEB!3&2RCxxz`x(N Y'R⺥B 4J\@08<>|[o3NX|?UNj j)1#͊b"SP(=-cQmMik.`z3%Zj\5j $}Pl(ت%k8!DqVI5N#>-"Dbec>r$}5-LZ*0< bkWQGsYNpEPY%[l]< 8G"]npRP "RhOT-Ċ %N]9U( E( S.[֎/tyy܁ʓׁyWR;`xj UuC@VDž=%I25juz%$+V,X%e a)k|f,}*P((U P0y.d| ƈiSZ8cX\Kغw/g>Twe!tmn୪(xx^G^?\(8sm9s 2b\~w.s$,<fH߲Rg/"_:ckUT!i|-"|6<=k]zюhl@3"Σw=ϚM[ ;E3: ޻o_&>G߾/ĥ^W?cfb;6I!c @16jS?(<\HRV N:[  F.UG$gΘ˯@Ϲi;yE^#..TLn;NG7137֧丳/1*j`&gSW=yRk@ccRpFX y~?mG?6n1lڼ)wh8`f*-{#[vo}$A;uA5Bh@@SBAz)ƨKB gnc0PRԲf[hdq'6n<<>v<<%!ҡ1L#. #&hXXµwЛ~åc,08}Z‘Y68r,,)bh4m+.%wNgڂL;TG| ן7^u @k2yxzpˊ+sQYg lm v|3U⻬꒑+N:}1/[b'`ob?Dv:DAZw{{4چi@B2R8%DӋl?`wEHbD ˆcBJITղs4^g!p.;x[Uum89wBJW16HĀ@f-H@f3B\،+Ef5 >ƫJ@>9|OC@c:_|mhH'ac[hlW Ov0\ojy"?-O9.mHn1Y-}C{]{'/vXx|+N9Yg-dcyv哻7𗋻(jnW 1؂_oPƣPe VGG (o/|q>׽^vgQ ]k.™suݻL)"fΜAOo[6?\qsyK\wCTki>3{ٺe)41Hsj5\1ˇ$42ϙe)%e-o^}]c#o'q+|zQan! "Ò8]3aa HjQuęgb\(!q)xkn5-P߉s& F0lp#cָ>/ן{"{=/+QUԀZ=#TV>֬LWQPB@P$LD(dBewTNYɷӄc6&),c-͛_.Oͷ7^|7]C?~!N;m؊G>oq5:O}Oػk;=;1ް wYgS*Hz7RY B@T nVHrUG!̝Ka5p}~7֬[KGu9C;VOxPMy+!o, jZPkԱk2#bPҟ(@l(P7d( C{k~v?ز R F ԵYw\|1f ϻ'#}ᛨ_mLuM֎X=n*KӰY5Mo+ml9D%u:fc)BYHRE}UzDA)VU"Vlչǧ?i{{?Ďoslնnki5;V/:cpen>yr^v8#}t'ܰ*$U )hL L2TLRE5$8)x}-8]0wP2..M-qBu8'NYL7A( d`2qk@RK 4TBC(la0BJZ"`d}{=*VG:57SwggYv !p mmmKykOϯ&/(Zؽs[n?bi%.n*j\CPS`#ҊW([WC K$Lh hZ-YĂbTՌ~k۸u_ן;qBۗGҜjS0`o΃{0sx{KT(Wsᵯ_NһCEh.nx4X[LZi Ii$8&`bdIUi4$<=\G}*cso<~QK&3wjtΡ$(S02YBJaDRR4"N\)aF+-zSj_\74BB,]6{{usvy7G=//|+'Mb9 wn3ylYJF*M\X48Sd#8En* XZ pzpCP2e{Gk_n?o}u )5?z=Tdʌج 8DОQ(”`2)gֲv͞kSjuBِ Sdo.Fڢt ȇa|1qQwr?ev;.[k;mؼ|F>Py}8#;G_=%m, Zۑ$Xd[XX8A ĩ21 DU ʉb8Ea<1D&P(<#Q]O.ŵo0ThRn [c)B^drjy [beۮ=ѿ~kWݸe`'ΓWT\sTƦkGh8m;/p7*#S +bhRҳBuE6W H=^l9@V06 AD +{c8uV35:]]5fߎB>feVZK  -Qk y*1OTVfYbQCHjg}׉Ok:5x{{nU!c2p'0?ݗ:S/}7A1$D f!o ')'L=>idxek}A2lG#2iBWdȺ-N2=X#{AJY-bn-ewf!hP 0)g 3ߥui&03 T'kon=鸰c-d ET d#kֺ^cP!2BC@jiHʌRLBhfG"~|݊'>8|rݸ͒1U wjl- ‰gTA6YدԆD(Y @5MXZA3ײA1ZX8Yi/B ;сmSsrTa V!N3no5٧3VLy"W>_ŏXuEuIg~S#:Xwз}m`%v.%mnB.xOFXcCNAd h.ݩ=я{4o;ӀbxMXR6`#c@k LoŪk5qE9Ilwm ZQ(X l^0#DJ$nԊd.ĥuGU[ƭCPkvӣ[>?tM𷀝ÆuX0{1Wn*L kWoaze_N:M2br>w'A J$J*dIFA=kN@$&QG@.3u7PPp?bGZh`1R κ{¥˃0BfFR :[)+*U3ͽ37qu/` ~m;[wXgmryX QrUwq@8}|^(6 nTl0X:rA{l; #+pkR6ӯ~_%;oDyD֨êǥi.( c Ut9^y2~'B=)э"( ]d3KnSpT t`Ni.1"$0 U3mWGN}p>qٯ?~;|)3?c !T*ݘo||ir}4T*9L87 7YW~҈PW~=HdJCR`jS;ȰM]i0JKL98)ZJ\%46YC=yS=yϩ<oV*$ !hEe> EBX“ X^) ١MGxL=bKKݗA> |sݙ-uZ!_gM}y;`uOٯr%YVx+৤`]QgOVn^ tbπS4)WQ3"tZI;`k'X 205Q0fXY2$o?mex2{υO_z \2t'YsOpݵxhWl W *<(r ȣQaT`@Ub|:̞vc{]W<XK囶8']= 1bبc .( ֥s UvRHBh|psimӞ<4[ fXŰ¢:BTJN(SL%S18DyV+'qnSnëx@ݻƸg9{/Wie{?. kǹ >pnuJXqyDc)uk8CjSia, Nly F3 IMo5-挚mUJO#j+Wml = >ܰgG{4GӲ*eb;4$7HZ]j,χ$RŖ.^(畼,3TEyOoxWkxl]gٯfjv?[5Tu/Hnj$bQuBz(.T=a("UV-&E<3^w\h59LBWhM#$EܡNpjN"+J clo9>IQЕl ozCcsߣ ![fh}f\OsǘmuGʭ;01VaH{ < M߹E j.rVu9)<[>+gE7n:Q Npe[iB =E'ĂO &WV0cd˷0c~cױ`r1V K-԰7sXv4UC,c+A#f@W-P·?k!۳Ș!:+FGeہ/pSV5(7 Crf}ڶ_}Vi_5VՇuE_/}۷ ̦XxjK"fA)~ii$ 9B7RkP6 `o\`x~EXҚ x5*+B+O{ LB' +mfby3f9Dqx=lX;ϽiWf3fa{ `<=~%[62%)g6AS%/ƚma+t2O:,TP̸ BhA"D+Gl!O3϶9߼ q߃G9x Å&(lQYj W/^PUrϑU+$qxΕ""Kbºs j ixAeYLص\w> GRT9GYTC_}׿ڋs~NܕッWz~@H Q;3S5ޣe‰ރA)ohp:"@ pQX/)q+og ?[7lv'Ac(Rt31dAE@ΰ-/K .> 7w d̡ZAksS$Wҗ}{;¶0; SS]B\mP %kJ= zLI'+ ¤*"s/kCqa%l.`"lN44ìFƆ100^w{7+̳Xe`'WPδi" SxO' i9&Ғ[ BZ^7RRFPjJe)r*G2}u/[nsG,ĵ>{ۯ>xߦ[ Wٽ;X1[#Pi|G40(w*]فƕv2(ar C*l0!L|)mVn[ZJֆ^Oq\O0(:Z qR!j+>n"(pe_~s3gX1xŧ=b=E,8`!s083T)ImZ}$@daVT,0srMs8Ar6k]LVS**P_g2Xf׮tFv/>*j39zP8 AzxANI]Rc>и]Q!XsuGϰDU89$#J6xQ肱cJv]|9O^sߋm Hiv4Dب s]Y-*E ^&SCC%jٹww#ZRˁ-9*B(P,ϤS,6cgx6,pa 6 >;ѻj9Z8:-&98¸V [2BK([1L2`jCJă5Bu(6$%O$Qt2Pbm9c(Ql`@7-n~<ÃSwuU+kTClJjug"Y9pm|[nr۞-:f!Œ*-a[qLEA$lU#1":# o9x(^~g d4 TC>'B4/L:wY Q9L% HTf\Z|8Э eIY\hU [㉢gL--,*D%Fflv$MA𜕆\z >VQf K+h;&0bc1CMǥV7#JNr`5„(p aEUh k'^+.wT6bm1p\)c[Б~$Y E:pJ8* {˲k1x_gU%%j7S8xWV!0_|H ޹7^ӹӓ(^06dH{J:4*t"э(RFupZ]#a+UI]{+CO$ts`5)W@Ą;0laH &{GQ+r;(9/5D6]@pv'/8/;7+yЇQtʵsfL?m^ +KٳQF$(\CX9>u#z" B0$U%ZR7$ {XkT-*.CK*TW]`C3*Tag7 5TGoU襽 6)NmNO~_ 2G`hO>`{QKa7q|0; Me: xc4{fT%tkAU[6^rBy +xC89ԅCSq esEx֚3ŖrP D">xsHj{): zc,p#bp.'M{ 8 ;PXLdKKA*ʸvR؜yʜOpZ+ԣvr%.PaQSX!pZu* FXJ `( %0nUv/b%%X1PTKG# ;" Z0|ZoF@H*.Vl۾U%p{%Pn\5@հc?'k׮괻GMȱGsblYtW'];o{'\v'\vOԊxDٯ?KIQ0bg{Cs9mkwFsX3XOBZ=>v(;$;HAdb˰jR"ヴt-|TE.쇞a 1l=.SsVd1{q~W喳y[ HǕvc,HSKHA0$+XBj3fDP?| v@N7oxLMPT.A!Z#Ry*i?==Q~9{U}ءk nʕ{ .ٯ~_?;OEwH;U)ص#g8z0V9)<_o}]6__~uk?aEzo=mCvpBu4pp:hN;~mᲊ%*isGJ Zl +Ɍ/(>*AjZ|rHP|dBXUkzsÎ;<p8뒋nE&ɈPxTYuN7Fs-s\{ꐦogbV8̂qe`#݈n/H3"<)W 1B)V\IxC)M򒶭{` 6[)A(ob k]`N!T"%|݋V$TdG')T ޴ Ů̄5SҢ/$0b#9.{% doy#@I[#Jpv_^G=znY588 )?ѯ~_'xZoP #pr\ǿ7~m/?_fX+^Z':#g>>O\\Dhg'sxe$/h΅.ʈP4=:aEH˕hbYH*d nA1b FCW,jTTց*n;&;s#v JU(gc*ĵ_io%ʶ[|SLgn>gn>cフޥG$q劳l=]ɏ:#P v0@}?) '1UI0wݤ&(+PBRUKqPC);Lk -^q7Hجi|3_ E5(f(Ӫy(`7Nh@ RQ/8o=+^̈-Yk+@^eCzúN솙?h׬ Wom'lu@%*5gKVaJ>[1̭;jun;'{tOhs%8b^xӳݕQ7,؞Y~ue]OXT Q+ fYffJoWQ"ck|̓RW= $Aao'P(lxE:PUKZcI(E:Y$#j1OX_=3= r]wv90YԇS 9sCϿp#.Ѱ$#B|6g*LI5ҪʜA8UD<6yQ FDxu(ڕ"(fqP=@n@j݀Fq qP"0Y(Zawbj`# J$ +Ijz4 x"oչw } |ss^XOu\w]kߝ0v/ 礀e9vksΧ,Z燇`V~=:5F[6[.{F%6VaՊ*;ud/IǶ˫ ?#&qyQ8=N 4*R!yP05&>QQ z#"Z*a\&k?|y6[ho3H%1!u=4?0 se`ܑ,6Eyd3U.$qIw S@+`ݧ^Cj*Nֈ,ZF(Jc{וЮEGVpryF&xX% 1hNCz 8SA=!Ŏ0Aky Yn0+Pr@eS(_‡{w,23=s=o%Ӟ{'=W_Wkc=+J>󎈠OaL_ MfYgřA_}#ףso3ʹ.? 寮i ~]]8Y9f,a庽w<O7\ZS%B68 2bCeB&=>5aԀM/8i{)_rv9[J ]r:뗑SbΗ^q&$D x_C,b +z{63W Z]*'_^:?/UqD$HYF^ " rZp)dqB.S8T!@AV"aRlU ^`V/*\A=KjXYDFfX=vB!<21!7CJ:6tm{~3_:53wXHX5Kl׉3gN?L(_xocW]uB+O,o=;9~h<3 /fÎfpbS:oxgO8Lv*1|NĆQ%)vdjƝ^a_>?7,҄+n;У1Lt%&9x,"J/X!o~?ڡIfW<=gȮ?tkx//߾vݙvgD<~}w7o_u";o̺gag+,f)I|+g~_{mcT|(wQyvǧx^|NY{Hɳ0+h,":CMP+>P$ wjMFXu ι W&Q4aVS@ =} vIz6_RuLx-k| wrd2_< B$Dr|:ǿy_E ? U0b;ulx޿vh waZ/QyZ8GFN@Ǟ;7⌡COpK >/5,ÀtA6 >0FW SmeO~״%g 2̐-@ ahY*e "A eXZ8mHqP-q-J R1f9 (SC^(Dޓw!RP,(|zv2mcBUl%x vAQ@Tj!,"EM=3UC6CB:<΢[&_(N\zՖezecư)MmC,]"C6r)6YNj27V,W^?W9gᔁ^?R W..Xk9! ǞD` Vꩌ" u0e(^uO,J-! f^] 40qiկ>xOt-ꋟ?^_ڳgƈ^f [zroΉ <(`LsC,VnL\#p_s7_sR8ej>7|!a85l.;Ͳ֭hT3:t-zud0Z=0&: sB‡^)9 JZ{|^0[TK aX 4 .i\n;|j* unXx׏_xο'oN0V_5pL5yV y(%JJp JhhÎO_+} M>0Ek1E CT\ra.p}U~]f*ǧǧ{0^ư*n*WԔ²B.?yn~܅fZG*&!!2!9)؁ILPfc->!JFqi7L1+󀣨j`Ӑ)6.,R ~Xhu! {x ֐E+t!O@'K/?T&H{M#CGR߿lJ"It' <V؂pNvAՒ<ͩFy`]б`)U -g]=x?IgkSlbYEepWjؤ›{V=s|7\v|4팡I_n9m#UꑡZd0)s킇f[T58gH8Ze7/M#6”`%(,qbG+Eѐ* 3A``ANjT ;URLr  |KѓY@_8,Sw_0dYtz{|?dI'_2/@[撒vfhx({Pha <~v_hy ,xY#1W|!Y3P~vpCGG|3ͱyP[ah⭸XCRYey2/_|dGS}|fv 7 $_}&F?Պhq~p5 *A"8%Ue%Zj q;Pa,Gζ\4ܶ׽*-c-mED 4cZ$ij1Om#e2h+%B |zL((|*]!SldQ6bT|)=C.X01aOӢ$(/K;2?3LgĜ֥EȞT%!(6)ZQSHbEy>|r0mA nznzyʕ|{!+{1?1m&')`q .}M9:ۿ N\̈{~ַe,f y\|Z{"٠z=k,kBėl(j-b%Z!JJVv )X᜵sd xXp0J:J][[Ƶ V*4[mlT,5e`,U?Y0Hqy9--i:\6eY1Ve/.fTW"JdY=ms}3\w׽ܿ(\྆x #ςSL!hף9"if,W%O;%@W#=*7"nu|ׇ,V߳}Ǔ8)8+Y<]fx٩pŒG`y ޷sG?yy#{StFwf9679U6D=X0{jh-_> &S`yQ#\̘hXLTq8cpHZ#j[q3k,ˣ\T b-hHw Vڇ#VIXHI:w}ǙlO7+"BXl)-p%_\Yp¸(1euјYGUB9_ O {y@s[Ǭ\ S-x덬X_Qud֞sv֭_wTDu[֣?$xG~75477t۸zunM]!UpJ%@ŇNkJ ڡ`EG蘌B+6#D{'׵|cS|L~ _4& S;Q'ʇɫ9c# @6=d)o|nX#⚛&'^O^Q'>NxыaʊB "IؕL/nNK!#yo)xcK%Ě˕V'N \I;5֞jR9ԢVlt9tQC̐crp˼]2)U85`?dȠ*PDD=,f%¥w9Ϻ8Af< "fQZLUeA`^)Y&A8TA  Q\0a`!VSa[%`xҠS-t|}šk5]~^A~!>㿿Oo/yC8:S~DAc>w+kaaeEDP"W]+)elEqe+aQ,V8T4V(cohC~_?y_G?3g=ϤZiivoyY)(Јb՟l%@ѓLLJ$BKÅ*)p%0p(2>+ ۻB| yfxoxX,dqjEg\<}W_0yđ>PǧKTy217(7x>֭{ {Ub,'#ǁSq\ ?f]E0mєB!bbb.Jh7;-Z948oTjZ6onƹzm-nr?M6C\tztl 6'?@{,޽z]]LK_ʞ_ui(! *)p+GJڋPCikPC)$̅U, 6xAgh0H\ rmXsA[P(32yhK/> ̍wKWGٱs{ټak&Ƨ`; e0\'LTYFXr"+ Iw%1pR3qjcd ,q֍6BWv ]}tf,}/ @߯+")pg+Ұ4J.02P T$P*D#QjG^d.J' JR-cÍ6D=\Ğvm;zzZϻej~{>Mnq8G~t8Z}q-wӹ`G` Nai0GN 6ˠ=9]sU@,dZg #G .(lf@3exc1SY5Þ䜱ʲ=3n0XkdYvSL5dJDNaR嗁a˸FǡMOFϤL &YN$) U1!U:ax$@gxOWYblRj=Vf9kM  ;q ™\US ¿9tq̷?aסIß}XgP&Uf!SIGXiVylPPxe@`A@ѺRm`!;5hT JZ("g č\(x?"k>jĺu5_tǺuX<]7{NR~}흁$#i<6ɺAT ^q%sk i&n £@e [7)|}zd{gv.aBAKs/ =$|Ws M[`m֮kc|K 85͑)@5Y<2ÑT-%ðh뫜wZD\red;(D0`ʄ8U+k q%rrM/0^PT>U<ٵ0 l4(dh^#AYwBGMBd(5'U.(W*5kRq5igIx1AUF=y*psp>ob}S/l~g\>qr#[6O_}oz뻏cOfB#mBv4X%MKFK8@=Ke$"F zTg6y*I"WskՁV 1 =#Tmi25&9yM1b25,4JHqHi"TիsVvr./s@gNNqqxxsp,z)&֐tJ,ڒ > ?ӕst"tX+,5BCŇ >0`Q`x_E%o$y/GT 1TcJew)b3bd$U!&Oocf9%%XT GU{>~opC]9 v@O1=G9bI!(< +AsbTmC`9iHQ I`P(THRJHPJ7wPsыgG"SF^(F=hZ oT{,-p"W[CTkqjw`:5% Q#U0[J5ؘ u{ tP0q)TJpb!Í&аC_@ʮԋ[Jn QVLQ F| _|qrS_}W/YuN?}S]:%mG6F#UVIpD>lX`.$DI-knHduO%(VD N1!R4̸2a)KFZN Ll(" dg*QhCx'KU +Z|W )ت" {&FK8c:̘ʔ[2˄ZStÛT'ʙDS[dži]O-eFWg , *֕)U 9V15;nPPaY:*I^A,ؒO@wʹBJ.Bl+*+\ipmV++( $^MqMap]̻(URM,wɋLm }SP[tY`9P<%/>OxsO\ w^7?[`@`(=p &5H, RTJ?Eȼ-񺡑MY,WfV@Lix @%@݆z:da6jGWȲ! 1RQ¬(I .w@aq<.9dc$t&2zF|!eWUI6RV["HqȖe-AC5G J\8Wb8bJK!Gi zҳбh`+M6J[[vK\uP 0V$tƗ7' 4rG+BI|#V X` nVe0:"X LYHCjU[!+ nÆh*+go+M#a{A? <~wHgyHUo\W<1u)y18cGP&4n;z;/⑄N3g`@{cxXJYZD-h<*H ycR4+p"HdJk8|);#1^I$RzQe%fD5J8Fd @gjiN. ))TK& AuY A9H VvE{ ߹~^`)5V1.D*e#p(4̠PA|ituB% [`xq$2#⥥UA2FUgAW472%V* UiTz$DR֣NRBQnJBc0à*7eUGS+hvg_y!_|h\?K?aٯB/x1fkQd,ˠg9)Шp /Z \m=~a +&yG1)tG`, *)E]AêK)W8 c[tsG'/&txƆC(US"B{ %!6PTl_7)L@1HerWh7HŇ 6a5t֠&Dp5fqCJzm.:{L 74T kz:QVŇS|egqU%.P3az,N Üt M}^%[[c  ^6dJM /G ;U\c i n(8 E4LbU=b0C.$UHp`EH(ɨb {@.ivµeuϪe,,>(HGAO>x@W=/%ZdJhass Bqn.8g36n`WnC+vQ7NXD)x2x< f@;cap}Bf)>X(74|YHB1@&+ޭ·-c2K3د C6(+˃SyvhJ/MYyR tm8 g.+ա>(6a«'j)(Ixg W\c٘qEYHR ԔnDW0,Yq)Q0$)e jU03F`&A ޝ4f(%];%YyI$|e>t6tZ0MN &M1a?X=.jED:ExUV=FrE$nzBA2 f=~3[bp\˖=8T߫.'x{︥__| _D7Z\$/ƹpWSa=wW<;;l5u~{> >p?<9Vb$AZ >PR+,6Lru1D_,tTr\蜼ᬋ񢗬9:DxLbx})|Q文Qf✧{\3$JA07V#!C]K7DXjq:'] :Lx?yn|^fqq^ڡn2\a@Qcsai ܴ^[y𡙂46rYpiX]H pv%Y `Vae x176uaZda)yIDa*gP!)ߟ:N{֮7tvC:"'|FaQD)+{L7 !a![>7̐gR5`Y5Cc6St+GjUfėe^H_)o LiewV`o]PBi/9z!J"بTVb`Uq:H_*XW֖7>r0{UϬW{+H卆Z< Th% LCq]h )ZsD+2јjO-*If∷FN7 8܉6]8g5{'zNXն5hY}k_{o[s>f8~(v(z]f},<p.HN&G~ú;5 9%j<7+Cw:&N6:Jd# Rs_q^G֛ qpǎk?Q/^/OyùFnS|UG4+CޭV$sv%Y3W~)bZS(UEg %i19$[P` D8uo|HSQ\DD`BȄ[S-FGr%0ظ@$XbC!k߷`H_IK32-\F -o-Za94iTfA*Kyry=mr;9),-6X='֞fpPҬ/S(xHwޤ.;AXHL)t,qS"Q 9aSr s͊Fy׻6S uQN&Tiu46:bZ Lz36s3wH-vM!IMS`=8Z6Na!ox+oskoDIý(K-,qE#$5CPw<%Gڢ'`ue^ItuhUщD@9,ڲ[>_hKrac?|@~%7H▛Ң<%H"p),J&q:zE('Q>?#?8&oob9XZ9m]C$ )B_3 @,JY̕={b 7)p@S US r˰fNRXBJa x.0H|m(Ȓfd҂.{)x΀ƩT =) \o?}nKVhҪ[TВ*JUp@Z>0|z==~'[A3%^ E 8}lܔTס,&Z|a};_W\uxf_t<7/nIbvN(eo/U6 >@?wo7][_)_Ji+^ nnNJ3of v (nϮ,&˳e]N@`pYJ"d ǾU4dB0"W gT_4!V~HqՊd`+L(H+F8՜D#2@b=)jDy'h69>eyo>iHX~8dnô5D+[ [n)& [R+xuX_Z2H=݂z A3xk^N"Ղ9Z*rMb7okRM*cԑ%kA,/9TQXL:Bؚ$I'cA7,ɪEdN8 iYx=+H퓴^c>[.33ɲp h{֙[.j>}ܶi,d*xvIӸyiX.|{si|ЎdQ#iL(KeoꁥiÇss= Xb & T|O EL;͉Ãm3pYI-pK\niI=jQx1YM"0ib? I Yq eQj,2$@quM0Xils6-!'YW,k3T RL !YrB*N}=0\T,ϳzܹ}5}]<͖"'$sHdHRPw}A[v~7)k8N_[5)H@3#\RgL*e nE(a(D`,['T]wB-XW1@8Y Jf>Ng`bAK ‘Ix$mN;oL}H#/}0s2.d,{}/g{߂_t,c[i246H(<>޼Xdgo.w__kt:-Ce$%J V2:w[z'Np3/>-0i^鹼EF3Z0 -?S2CaCA\,_3d-M-β6 ~=IUVņՎ(LSnfKcYL_c|c妧,.su˷i/>G$&] 4}0)s'<ϽLŇYxs=~'xc'М%72UrUE=/ CpC ▀eBA#|*17;82XaFX J-T4cj/|b%ɋm._y1n>LoiԡѝQH!3j!87 !do}4%M"&vY ?;.CsX% \Lfϭ[YT4 Bt ɪ4 j  "niN܀ @6,z`ۓ22=8r%'Ϸz_Yrqa B' B߉cxVCF#tNR[_\7s3`?V3&IH2Ԁƕ0u*Z ꫮЃ_`rj>*>%cotp]%/YЊU3vVw_B$i"bKHԀ@T)C,{K/PN]Ahl@B'.؂`1`[Y6$T?k/2g ˇ?jyUM'tV,+-tgmDR*G~JEh[(BIS $6DMnƵ CԐm$ZYnR2NK6Ngçl1\-9n;ePb^ Q!iyH@ZX-H*=]V71`Z҆@c( R#9ɪ'-˱uK5x VmWHۯ\%43Б2@q*Nw>>~r "CrTN*֭1j- KJ2huY:(e6? l'ږwtWKmCpIcAn-JTѓVl#Ln#a,[د,HF.)+A\=Υ,q:;3O޴|Ǟ-Il EyO02!X6R#˙q*RYvNLTa<0Z\(\26 }lt˞ARZwgz)+' 'Ogtb9t4 V)Ѭahu7]x#-4:# 6Jj\.{NF&&x#sχQ J:pŨǬYҬS~f3I.Nw3Ϗ/6ZV42:oyGB~]C{G$ 'yY?#{ &[O56N!]R dPbn.&V X=tL\pu{_AĴh#> :12, @lF*U'Yl%hcr}饗NGVbep`!<صs YϺO~SZLj -FYg,&Q^?#,HٜKw.,7ֈ6Y[L♓G-|<㚫y1>zTv8eeygzd)~!#G}=r\DN&M(u#R<-{ZaH4֡3D X[-N+L &E5I;o7cvc `Z0lM "u6d܅bmT:@+eˎc3HSr|2G!@AA3DWV,L-Imx{/ ͧ@Eȗ< ^{> Jn,Vdp@mexBqvjw[>X0Roj8 #8k ^ʱSW_yMs%e/~ 9QGVT*%zzjk.DI{$I1RcaaG}djכ~tje?\^7DatiB`,Jk<c޽\sU$"vT탌%1'7qq/WV$iMqv:AdpuEW8v,}n>|/vfm:Mjvw{p,/Xꆅ+M!IrzW }eg_Z yN។O4z'1yzfkӴ/EH j!*eʤn%F`c^ Y. К\FQNl1Tyk2:0I4=Ok:C ݠ8`/_&GO;ciuR6rcVՖ?:e:lx*M,)Iޝ&no t ?s00?8u0[ Xn31e<h ] +]Q¿02W##-gdb``c6  3k8ayRQ?~az vr\, 41J_KSϱ3?SX kXk1V#ez< %),--Qӌ,5{i5#Μ;KRf)R | ^=C$đ&KcN/e~瀽K&x~Go2{+.%%8s R6 hkx))%w>ٌ~7f{,G?Z Gaen~ kzB@J+KX8xQ|[LJAH}}-sVv =Rx[RpO/lk!ɈkÏ#07HIwx/T*կ;A(%7຾ 4b2{P5YAZl٣RHRza%]xb>}\X?C뿋Ac'i92RkI6ٽŹ {:F>O*"0ˋk=F #kF#ԧSSE2У$q.wFnG Y]N =!xWSw}-KrKHEL"+r]PRncKF ZΝs/zU^}ۤc 4Gx$)=ek<|8bڒEav3YXl lM(3szXCI˥? ;#P[rWYPIž={h=rYIT3t1s R=r-xw޺BB _΋Փ_@I(C R !:Ӊ !q;!j7& ͉boڵ[1L Dg\{5ٷ_<4kCyNÏw=8ȽWmxO_%%[ `:F8kiw,2SilVrѰc' e /Orwp=f[Q?;>p' '& +7;qwC4 : `B!C ē$}!2P (.pyO%(÷|^~շ32l9ys^(@9 l2+`:1KdY`B(`FX%ȡEˎ=eHPB ­W{*qĖlĩikyFd>34<%WTxe2m҄^,B8o2eɊd1J` B)Νt/W5 VKeғ." 0u@+P9.rUt(01!iL,fs0hGG 途y~'Gq`^[sX>g>ܥbô gΜA[^X prp`e5Ȁ$`M34B$A*zIL>%񕇎2/#=ҒG?񓇊r} ߶KqCm[<i<G0fƛ<2ϾF dtf jt G!&$mGHIR Y-AJ 6&S>;zﺽ_]N,"0@LlWZ·?w{cW=ȑCm,: \YQAo SB m-s={,n KIfV!$q.)J@&Z1r'^'ĆuPe"7v>WT0uT+ᅳGmw{sHzu=;o'/*cccRƗ/S>3Y]w?ni+[4Y{d~û><5hjRE,:7[v}EC`6igtѹJӯ86)C>*gO~Y⟸9Lay~c3Z3;3O<,canDhpQ6h<)8y0BHD-rV@bh`N3c=8j`BNxEՌ;##@'j%6Bdl{?x࿎ So6٥,262uj0јLEfhY^^,//j̀h9{"۽g7Ο $ߵo Ӵ}b2LXw>֒iw7ڷ_oH00Pe׎uw=9l˿SϳrOFZE؈ b@aU5 M,iљ@)1e 3 ^ 'AP(H  J P?ƐYAC_"(xVÒT^fY_G՘L{W_s#d F(C*Ⱦ"3? #}[+OT^RATwZ `VŠ 𛖷Sf)oς7| ]h#X߹YcqruPFV?e^4,t,]y\9: ~`K#,H"?X"}idrɛ3!`dta疘_h'v~#oi5RJڭ}XkRTgM )-ZR a%.^I**NNT' cɌ[_2߽|**?gv}Eٔ6MsnwPa2nJ@6(/pG4EkMe$ILMMcX[[Hm34F)g|U\.A*V^{-qͧ 2P MS7rgZs0W\6Ïǻww V̒dgH6C$)s-D!s lG'Ŭ[d$𽐷j K7_l6S}uo7̃CnG RnYwc$IY,C$I:sk-'N ҼvKe_ر};gϝV,q-cѠX*)Eiͷ}>A$NT //? xirY'&$I ,)f.BXE1x(?wOFR~^ڛ7~۷c5 kW )jL&Yt)VY8r/˫_9 wܠoo.s*f,m9|ïn!wnz ٟ:e/WE&/ \jRhAX)S?:nȟY]M:)AY9mTh/L{[x;_ey/~~C#O?S?>YafZkN>C@)ŭBcT*ڭF)JŐ믿'Ng>b)DC#(!1XH 8l1y#cc4ZMWWXZX$%Xdxt| /Yߟͅ}B H)Q |ƶ1AO%Ȟ~I?x}q&O}zW?V"I|RJ !<}nwB066K 4 2ϸz:===eJ+ IAϣX,!:uq76EhYgYX#]7M0sOQ!M) +e:QDݹx#]6-]:X`۾Pclh a,iTJǰ2j$I]1PJI*`xHm$X(%߷*^~nJuK?H(ՋŤ[h!Dz*A'|јgLJYYYue !_\ v?_/7~㼛.gMtJq#J41~<Ex<7^Cя܏bJϱ©H=<˷Y ʅ*R\ji+B !70Z-Bvznans23;S'rJ"zk lYoJ\T*>|YħkZ S7eai4NBP Ð!|cppyZKFAP>X6}˲(n1(I9rkkM?Nh:閎h2??O)%YKSQtqT*RD1Qe-l߲rJwcf:^Ɔ >hmp+x;x)KSS.KLP">! A!AΊ$T&$ 0$<Νsgrβҥ}MB'ՕW]ooR.X[4:IH̝cMNgcG'Y\nء?~Ǥ<,9ٓ_bMx`CqaJblv4i=,/v6R K܉ÐSgNqbYbĩT=/ Ia%=e l$M?mۙ:?IAV_ڍgD.`=Պ-3)nDZ#dֺNe=wgOs8FkMa1Fvt7q~!T RC=rFI9="+x*Sw)!`d F0 qv"¤Ha8LMs"ǎ#HPRu$Ve,IߠC/_ff昘@KTfj  NE$8s 70$VkZ6Jku3a@OwyGgާbs9o:x"=CuwN/e)Z c aG)E! CJ kkk,,,O ި300@ݩ.~6JqcȮ,qAN>M:QXu`[XΝ9{qy3./<%ZW}`ClǦUP}di4)XauN|<8NYL%U}8ON$MwgZ_IM?6`SzxZ0F(Aզ^322ɓ'Y^^F ã#XkYZ'cY[['zZK=ړ~}ӛ nI?cG#c(Z+ST!c0ZѣGP(0802AP J%s0kiE;vǹRC]&9uS`y yjT n&bb~NɴfhKYhmPv._ *1ٯxz&$l6t\^KHgI($C~ah6d1QP{n *m 6vYhmcFz?jm0Z}?|0cff*/Lg˖-.{TN0Vuuc;\(2:n٦^uْd)^>@,0e}l߾;?/~ÇE4BX)jF}qflogz(FF)= $Nln6iZ&Zy1R|N+#kv̞x\{xDC˷IZH%Pv3d$R fDɑbZUSct)au5C) >]Z! YB(dg ,rq2`lFx\p-[-Ţ(8e !R~ q#RN3ֲ(P?'OR-Q?R91PͫNfX ~`ZM`޽x4jeYjTK.ԉ]υVW r=(ʫ9sI:' dJ*In;JdG\pDJBx1yѠRvz1N06s}V+ɲ 8q AqM`bbPj5cCYHOu(hXY!aR(z|vc XSǘ9R&E j .[33Bu:v:2wzVkc~d-dt"MR(WBXr)%_Y)*$dzZ_q)T 6!ػJ&&]C`R\}hR03 HcѮ>7 Kq(ZCPPWK+^OXYYbbTCb(zҀd&IwHb[avJst$R\gg%N# q!]P(U,S!n{qщNh4h6]922ٳ.\[_K.A)E\WSzbA__ZFz8{<XZqY 哟;g*z߼y2Ա#y8l.``vp/!Z6vDբYo'ɺ%Z󆔒YԪdfeeUj ֻ a62S"߿/'N`%3A# K3 N+_ _%`?[0<\%MS{-z$W]Q5YG:FH!D rw6ANpg;qV3+\B^\&)sPVz]b/k-I>T*>Z@ooH__j@R ,ؑVד']mp^(6 R*A V\\)IJewz+ N1NܹNn'g@Қۨ<cK P`b bŦFB18$0_Bm{^$Qh3,zJS*UtJlۺ 5)g>iv؊R}~F NDFkH⌓'O15=Erv4^v)cڵJI-IJDΙ3gcnG Z>}%]{fdnf̳^_=3aߕu=/>ODk) 8ǶmۨU{^f``Ożb$+^dSse 85y =zGEIZJ%GGJ# TohP( 08۫) Tr2ˍu*ZokdǑL/&HYSh A V$Be>h % DΞ! I3f˕;-jLޡh8?VJ6K"ȣM[J!g:ԛG~*Z[c2' N5 =Â>?W<cRƙ|`5Lg0Xպ`_ڰ,/[`g,bnZ,I;ʌAExfqUvff7$Iz_wr뭷jcllzAZL\\uGJ VcLLle}x-ow$I:{ZPTHӔ$QQoGFռB{Fv`9LmR"bQwٹi9wOs {x k=2k0q%:3pR%>04L\:QȧOH$N F6K&& /)POB B8l'#@%Bz`&0*E LA[Ϧ\LVJ\vCC*]d&/J ghpx~F9dI, B4 ؐ`⑤P(tZ"DnHD ΞYeqq!c;K cQ%2 ~x"inYHqBFJ2ϟg޽Da^H-[+K,/qeu{CHR.*HlT*魲kFGG9p+++IfFg#k [S$q XjMzk50SkeYL B_ +knd~*=eȐd ":"hGე0ڠXC1 x%3@X+1":.$ˮK9 |f*ue6jwljI]Zk?Թ6'[Qr͠'duK:gm8kڱ0O6cT{gZTSYHA-YǢ\+J|[P$ ^43yh"dž[mG+ҳH+@| t`Y:^eΦT+=:DGi}7$|ݻws ͸[\+9{<$IRN?'NZq7c>ȹZm>ծSTVzjVlPTٽ{7B$٬#,!s Te>BZcBClLR>[lg? z<%>O}s֩%IBڝ8-8OEl߱ELZc^{-J f$I#FG 6^RԺE=9QSl0d.v ]JjҤݨb(c* Bu~BJVWNX%N\:=eI i1f-tb7 AkA Ɲ4uӈ,mȖ0`b|/ZVg&n4.ٓŜ%7&UPnx"JJ$ʐi333<(;vzw)4!IE`j*ȉBM;::1E‚OZsr|}505CԪiٳg"q+b ]!Y ͜o8nϓql߾Ç333R.C #I j.`ch'_D( Fpf݆֚vfqm^Af,O%roܞmv {P= g)9z"Ɠ]5151=|Յҧ@cE Պɘf+Z Ƣ[R2])+ h’88Zҋ΅_~_щ,[,݈oi/:5u-Bc"a$qVFh)$І.hƈlw3֢EP+dN6xBiQk|F#| /(Lpr>]%Pw%0JY+Ѣz'ƥ=ԁؐSd6F,uEa"vHyUkt2ٲ|&덣Ox7"۾<`S^ ΋+YK2O%ضu7i!3S[n!˲&ɓ')u&ZfffPlR,i68#ϘΤZV3ZGGXh:rm,-$( 4-U|V299Zr:ɞ灰(e AJ> Aibra 8_ :T%/EIzso]<'~-صsZ[2;8Ҵ[ =̹s}WUe8j?%N:,..rNBTD-+5?DZEJ.S/DJɮ;8u,Zk-s3TUfgTK4M݆RKY݊J261- ѣؿYk4,// ܹsܵťyfIŅ"6Yn 2TG4?pMcr+~cq1>(}}lݺb$u /Yo&x~Kc e$CHi#Ξ?,MLGR!̵l4Eʌ-[abbAt &ꫯk- i QfMF߾V? (BZi1==Rťn&h"STj,//3==MGeZk1i:w)%S(HӔ([TJ<#D"*u(WBC+ߐ`/N /wJIΞM.ʆ7֙ ޅ@lH$qJ>7T##!rFQtRsd'7Si; &,7x#v`rzVB1T,O}ï}/Q~ "S LO81F#p'Tl16N6;W2m`4SGp@YZnd^{b#|IЃYč~_u8GX^y73pu148 _>|ۯ>D防o$q饗>++k;w ""c|?6&XFHO}="Ig%(OP( JL"F@refgy;^2mI\v] IG4ڳg9EBkS(/3m&x~bCzil6Pըj,.uVPqJ1T4m:Fř3gh\u<9ϡX(#SEkg8z0++x2FeT*^tg?۝~z޾i4dYȈcI@E1qyKn{2k܈@jubv#cuHsB70<2k@͂ɀcǏan6VS*F-~ "RNnke ,W1$6%S~DC;~&xj\-%Reݳw[&&X__\*0<8BT#XX\hSgٵki9~c?~rLOOs3J%XXpq7Fni6]B8]q!$F k-xaϞ=288DG>*C:Q+y $ 0?}ڱmJ98tZDqR_)X bAP>|;wx+}R1=?GXU#^300gٻo_P(lڔm&0t ҩxГ ZdYFD Yf/ 7HTP(11cGsCh Ðm[knsoEchZ|$I2VWWQ&,//sbqlRDt(+ D! zDі\(IlBԌ"ϼ3qznG]Wu쒑 d&eqa3 #"ID$eƺ1k%:OU8}]N F5W_G^gllvb a%Z K@JyZrJ,+R 4Mswl>O{drj@piw[0BܺJ)R9)r֭[%)Cc\qh}R(ȴ %P%/(& Zug~a2>>۶p>]^8azzf[(6K>J RxL 7a.L[C k5:͘fzz,3B.uAeÇsTxM7311R(,LƱ#GO| db-Ϻ wuAkoجuA9REOk6(eJmu]GZCGXy<۹(6,av~ٙsCCx ߚDRWU*\ZS* h>5b|K_J)^133ɓ'sy&}}}y۷8sueܹVt"hW%Z9UFSv~{0tFIܑDLTo( ١BOnu`"<FffvZ ↇlu~~fNRzfβJJ\%Ѹ$ZruuUFGGVcj5fffȲY,0hr)?+!~+z?h6N;8s:S ʎ~_,`S2`׮{^m2q⹹9vqzzzFR*E[lo6`RN:}jJ+++ݱ!-Fk{1&Cyz8'`?6:AVs  RJ s)@9(rmw >(N:-0<4̅SYOn#s`pZJ2r1;;Hw#gn8 ӊ=y8T*eZo 1:uk]rllK./~~zzz/g||zgϞgΝ]I'66~GZ'tbA*"SH R$nx>R-;[%3~5ZSSSM/<|ӭ rǗ>Ylh3NV?ï ," |m8qVC'x{Rj'?(Fق l37[?.Tґ@C>@v`a@$1ϕ4vQwپu+R,3ݒu:ut:fWXCL:Օ)ƨVj4-@^e zzNr]߅k ՚L[tP_[jh4-̏PE!, zիx[VEqeTr }sPN/=Wk‘7cwJ@\ -:cT5z=m~i]U ylٲ%qv#8f-[&ȑ#ii0EHb1䵯a* kk RA$IB__b)'Dmg>Fz{{>HnB? nftvvxBOURB2&M5q"I"`XmP+R fM܌87LoYܥ yP(^fcB؜=_"uUǴR)W/dnp=}=~Zi9zSIt zz`eזVdYW\ɓi4aэ4H)ebX^!qXXXE$ķ.zR0TzWn9gs]>/J vR8K$[e;voOvJر4rvduR,H"A$V>߬!899Iv}]F`aymvM!.JE7- &@5gN$G#]}Q,3 }=TU$Iґх{qqJu0 ZBrq**F.Cx2ȒeYL9F٤>W[CbmU*%D{@> Ȕ>5""NE!_,Ogg'it Ǐ{N:E{{h*f"*.n`y={p)c)4E xÛmo>.rRIH #h@X zڵK/@pGL+ ~VwtuwJQv?^W|zϞ}E1/y4]P(#VH|b0h6(T- (/{_(BpirZpKxG1WXl'J#6 ʕ077lj'bb>GWW6Rȷl6TUUi6m\wz 4 NX]ӰmfFh@H E,!fܭ=Q%1U U ]3ɤAKԡgl޼={pAuѸ js@41cgdw?EOF8#`ڎY %SSSHrH SըE$ħZ+"r4ss SfPVhD\.377GVÇ'0q@jĮ) 8i-bUUH:N\pE8щI|xס&"BIn7p&34 F{xQ$ItLz{{Ԫ4]{pyDӻFTje8vl /㸨N qQ:|0{\.)ʢ>i׿>΢&Ӣ8BV.lB}E^qrAPp>Q)JFQTG5 $6M l׿ .XqIWQd; #lOiRZ[| 1*3>>i NxMAWGč`&O cR78B8r7mCTe$LSeMÇG|BZ,K,.G7!>" ,G򚌪ɼoc۶mAog'FSȿHOjhBhI๨W]o(i\ze[\bTT^n犢Okhgݻ.cnM z|8x026KKKȲLgg'ȲIw3 /鑑uAZ׳14!|EammUge$\R"1걑 A Sk̆A@wWlEA)#!|>OJxʫx^9‹ɥSHHEfg9rk*==efs\~ٕ m8$I@.\^Xwyҩl|"Z6M0 9~|@C 033CVP&h4@lU 6oFZF5V_R۲1 S8>jU⬶ B?ZBEu]̔4 >q2Yo9ٵowOUdM'e<"S̝[o&"i 8_Jy5g|ky=%^'N/&dE>=4U]T^#PV&{݅ktvY~}rSAU&s?drRdOK!ql;"\E4M!'etwɈH)|?}BQK`!JJĝw1_s\M8dY{vuĊ҆EȪz|Q)a"ǕW]hN&"(TUL3@QljCOBMT*fYYYamm\B@\e`@ް׳F"VOr9,\(ŀz] Ja /& C!IY}r4~(wHK&oy+\￟RiDZD0Qd*.*t::G{g#W<M|en/=nY}>Jib"7x#wW\~h "hM" Ȣa,H"*! !~{Ӝ,`qnDZ,fnv޾~D> HQuUUQ뎵eRIi 6 QF尶Fo_w˖QOXꄀ($d)<_i&$~nKsT*Eb.r?EϥZ kǡԹ{)i6(m t:N -be:ImZ(eaR^2qdBƍ"At!!ٌNjɮmذj%x!jw }!ă[E3ߍHĎm[L;dB* zs%roi`h&VVÎ[h1.MK9r Dy=t UÅ;n;}r=99{ᦁuÛh<ެPTޒͦKmgjT*aI1 #R4\ܣ봵6ډiaqύyD֕dPUe+.BGEQ8;oc{p]ᅪ~L=%ve )੧z)I=bree;BUUzz*0ef}aYM&& _`89y)0[ھ#2L^LdqqFNZ6+̣ JMF cs927?_z0q}@ba~d~q?o}T0PfE6l`Y>C^ _E!V?&Ө5IhwȢUC*p9r]Q XK_xex|zmC&qł6 245Mö l0^˱cDŽ&h0t=vDV5egds0 bqnEV^q:{ T4ؼqI4H !+%,a$}UUi-+7e_\A&&&8rahX46āl~~jUdTB277 l( I axFnͦ֙8'+x(>r>J4322B4#Ld>-$$4|?P/b+Ĉ˲u$c-T*a訪x{9T_@DoEUzQPX~=RV)˘;,._* N{eYjO=<9Gz%sIt]+9 A E DzB(;|>CӪ +1lӊ.9%J?5J _G>u}5s`dҙ E4w.,S5,,,(]]] # D}h'~]TUsΡlK//rJyfJ'I36>A^z6a(,TU!21]( \.s=p=߄({,..RDX\ܙ gU'c-jǎO0::p<Dzٻw/Ral=D26lg ,bR޽{braS,#j싾ClںD/ ?s^ZZ`iiipfff[r- iL&Źˉ'ץ #3iIl Ŝ5L-M(ؖ8v@QciZv904.V]O1q( ϱ}6vFxE?`)E,E! ZM(8=V֭F%VIɓ )*a"A\~5RYk^\faa{U!5,*#I h4dZ7ԩc[>>g_um4UkL6MH,?&Ðb.*L;N(=GWw/!IB@Uҩ, bLEq[*AZTFBJ⻼ҋx0 ]zQY(d>H!_i4*KЁk7) F&eoy !B_=;C]T*8ОjGy IQdwyX~#3+2Vy-bUehT~LV`xxO%i4ެ09yB"n۷V1~MyaӦϜy%Ib#oMR4t:hZm2 u$nҺ,M+κ@. L àY'jmؖK>& -|IƲ]~953维u#mfCp]Z>TU^h-0D.6mb׮]?@P 2<ށ,[qѣX0?rZCHl 7-:Xs@8'9|E]D#/D|RJ(KZOww/R"K AVZ-hq]Fbaae޵"b'Dz욪`!Itvvr'&xG9|tjݵkR6h4m.>+ u*TU\]q]DZӃ}a$` bm`6wF*Z l߶E7|_mY-j}!BdYJI|gL&ݶV*5|5}Cd?0Ð%NP6; )E ]8O#M @8HÏ>٤ַk֪blLOOihubȥ^N6'Uroo7>CZpIN:$I_[S=}hƩS]_8aH{{XUB׌8} a2dt4*mM cpKggPQG{?6l d&#={$,KLJDooO.PkT`F qq$2pWRFBطA[fٚÇQjUnmyG/1%130D4M4u<ץ T8pBǦ|rr|ǟp7c&ihh~vɧ?TUz2 =jM锗e{1rlˠ*ժXXѤZFGG^W:eel ťGmI8r|p(\ܸe`pȏ[FrLgBTd7_5MyR@N(?FQUer$)eޖC/eB!^i]Plerry<'J7> C=,æQ8bPT*OpЋj8 ut: 769~8,.)C3VӡjUHj5!r'|%ky'KTcPE r9A.a8 nRVWWlDIAVJʷ7o%˱q8 ۷AoGQh) ِe9޳L:ǹGnQTCT& DQV%NFBGBFV¨/I(h4ra:. 8|0 zz)4MԩSmL*%` I!,PƻKq"s[_n^7uV!g4mSӳ1հyG?& *e7W-|0ZMLnKaU]d9LfyɧKh%>[8ɓ'v;|]BFqiτgTa]-><\+ϳD!9$%~MY?4n"syBM69>y7B i.{DUERs+ @6gyE!D_]Oe099IІL:%WYӱ>c*B}Ɨ%Vsq|UUwG>1]=NJQ_G⣿q5{W(2?k&iƯgRemDZ-Ve׽ 8p\ެVҕYf a:A* Bө)*3S:5Hx:r8U18ժΎ׬4^UU ;|<%3_nff',˺%ŶeYL2 HT\'''i6l F2<<\ץޣmD" EJttw0;;褍4eE5 4KXCgg;WgyRA-q"CCCHB:L^333(z `mMd K*rx`vz|!늬ɲ,2 ~9Y8z|>O_?,0dYVh>F4W\q^x!JG}T(4@FB/]@wW}}HrHgGw4@(N߮x`lRoTŴltc300#XZZlhZU Σi遁e+3Y2,A15uE*S*(F.9,A:q$EC_ZM fH 2L IFM*wq7x####BNS敯|%zZZ ˲bYKEjɪZhls.E)VVdEho0il?k-"IjzzӱN8qMQ cc'_~ Gkoxzn'$x&본e˖B*w}~~CȍbsbMSQ1T,V4M* itMۘ(t^8XV#`hضY)Ұ(UWfPj?]8s )Fѣ-YVc뮻X\\EOM:::hoogyyY(vj6A1pFUU(˴g>:::vVK!~4"4sut3ض7э W^q5?Vk8ғ*Ȋ]o`7kn1GRFV$Advn.#ͥ#LTU' }4]k~1ޓ!Zi6,Lӌb^gnn #p U膌)"TŪF&eA{ld2n6|s?}߿} hZMs<퉀8_%76 0LwrwP. 'NoA -01q۶fF%B/V7(_i4h,*βyf$Uۍ{c IL7*g||o[[Я$)CN b lIeLWW.$p\!bO4 "@.+j dMEu֭ ei~U|6$HRHxx6ssE2L@[MG,;2WBT\.k6B/{ P.E)i23D ayy; Ddjj"e2RHz IR"wlTӴ}5N<ŁXZZBdۋd4-tk'OҴ,ftڤoёhW'AdYhR²,oUPE:v^%CUӽI_& IJ]fg)f3JL/rxzK$\%'MVsƳ|IJ" i$Q%tuty(.,׽R=wg ֆa2+ոj6Ro|dIشi X< CS<=[5_Lj$y亰0C?333BZR VEVE=iC \j 'U͓O.aILk_ֻ?|8Ϋ èD٤T*DR"§0M:uF֭Ųe1<ss lܸF" %jfXC \~ٕq9T"H‹/ݻ!"\.CGG||>//R(uZe9pF$qq4E UBg'QWX08@i^ieA$3*Ki긮k4[ۈ,..r}a6G{{;! ٙyRȹ% %hBpzGNJnJrL.cTFZYcWWӆTr5#עJn_>w=j y[FP0Rq?)qJ #5s/{WCJx~H&vmv*5 >·?+14E\XE٤Z2L!xx *Xi ?=z4Q=9o[Ha@&eH1=- Š{/wT*JZmƸ4ۓn2τ\J_S%~[:@[B3446f"lQ^+@ FO~r"k/\DzF ^x. L-[6OɶĞiS  EU1d>lS'DV~DHHL[[͛7sA\K&,3M[Mȼ;t.;l6mR R(Hk,i:it$@OQ(T*aY=]va±Gѭ^yGe"ir43334:Z( O`xtC,-v>pn=e3 ~rIJgh =~y)DTUbfFC)WJ\|dHAL  Eq13ٸ4jMj:~?>BOuyL.Һ\.g>1g n\cjjJ8j.l0K@,8mMԓ5TSq\qTU%kF"q~n?'NG LOO*^{-$aB4S,..2;;9-!]c&9q|rLZ$0(CcO!\_ \/v\׾u>p˭ttd2t-c2ٺ}O<}]<䓜}Q֞"s>{rgʋ/\QUihkkc >s=7z> M #H2$`'E.CPgjbpc6w+`E'OBQDyzieo}lٺl&a?MF;'Ԣ|*]2\eps?@}B|a[l!]<ϣ(EUd?O{200ɓࡇTUd9s&$3糜<< VlIŚk,/===bSRž```U]D04lVL̶-ϡk*-,Bj F{ n"I!W•\vb`$R˩+"Su==1J%*("R)ߏ Z)qT4qkhm|>3:tfIAbdB> A@P_Q 0cia)C͛7ߋi,/ϋl"cR[,/ m^/j:!I| } Cgl|ûAoj C-;xAя*\E.v}چZG999]gMgCq"2u F*Vj52.:eI-2L&RZYEDQQKhBUU!"a66 JKLVk){sN.!l<]۶m : '?0}τ7m0  <#VP: |XXczzJ1 ːNHi¶)\IFR%6lFUM%@1ȡ,H2F}X4+FN&m&˜^ui:Ug89uMƣ&ħ aӃtvv"v8ۑ#GrC^ ]$nʆ 8vaÆpZSٽ{7 ++lݸ /|p (J?BtPяՅ:.r+ORY+8XDU҄~@({0es?o;)ߨ+3:~`l6}E€]O=[E?~`nnn@$8p97fn;O}䊑τ39P5TVT:0T,x|>K`bͥrT*Xw\.3>nٚml[SMb 4AVPtMW<d0Ѭ3l6abXIu,/}KQ/L y~UtuĿShA{h4ݻGtur\ia,dhkkCx8E'e9]_RIqlO&axx0 ٴi3'OP*p]1$Ibppj[BT5^ؿ'~ FbAH Rt7  BLZ.w7o&Gٺmo㳟,;v`6L ERVqABAjEBq^uͫ *?"P!b E ͦ<>-POP2Duά$$3!'襗^Vgg/uuu4ͯGӴ4u,1;;K>c(V&1cY$IrYR,:rdnP;9IR\S MZ7*J2/~EH)b*y-]=npKS7\^uCI.l6~,DRΧiaB';֍R,dn~L&C>gy04o|Bvy.$)W-/O=_SYn=6*ww{n×oQ4\*~ =o]PYȪgI/o>FGGY]]fiiFOӤ~(D!t]k*EV&}4$;\M`5}lb8_M.g}־}{QU蘙dYgŐϺ auǏ6n' ILq˗׭[w8E*g??$z;9 ͛7y]'?2fff$–uː=,$E2G쉖J%\s)iJM^}w_h4g5 %{ڒ̄$x&׼@=rA(aAhaa%Jt.<ϣ`X\F\i*mett۶ahilX?h"4uT9*)h0qIԲ,yYjf;I8jFnݫ{ՆpZI|_g˖-W\A:%P,YZZj5v,0#&''c DQuNz?_W =EY9pE.Bg۷??PTl6;uGbVON$x&e;6ax^zzz066Y]]05VK@?m;lVC]rM ESl[Hi&fBdAST\cvzy T\@:lJpjbs׮])>kn$^ިRVyyVm`[ t֯_njR/bo2Z IQ51t# +Fim Bzme#l6)|f8CttMWW|15D iqu]j#<E;FCE4Ms@,(HhL{Ѯ(ݳw_7O>EZ}^ jNbxwn7(!&oMslNnV<' Z-SjSO=,mkZahFx9rnP.8 |K_4uR)U"-3W^y?oߝ<l83?^{-#ǎn[eY(K_]]eqq)R`ZL8ɩInIɜ&>a,W(QUT }l[U$YGSi Fy\݇ia"DZPe0Q8VυU0UJ E::زiwFwSؾ0"!*>a`YB==|G ePA w*$~jյf,Jmz4YmbjL&m;V+E@"\qՕ?x EvI]3}{wD8~^#F_ߴwuۆ Eٹs'z׻K)2??iQ,I)\G6M\W HEiG*XuHhOLik;+ʻײVk ˦Rg^S)%ҋ袋(twwǥJBdueZ^:FZR0BA( U#Ns٥IQE0 ށAdYvYD{7|bT+kef4Iy`.y C|$9uE5 !beeȍd _j_nz{ӏ[O_y/΄$L߲e3[lV0_/SY:cfqASȒJgw2!j5"}QOM\T* 92<݌WE CCSUZ9z('K5 +~S*z]Qxːs=9TUeǎYd7Y U.KG{;^$c>6lCVuo>,عsg<0ryV&n LWWJ,p8N# |EWk;(n2lkIC@XUe aD~UUa'jD7/s޽ ]g|őKHgt=__c=Ͽ>)˜81aP(^ݻgӦMa劌qM$NS7V2Xlx-JBR a-bY4 ,ˢZҨ[|[enaR![ p}N8^iqwuQw\ajHaeoN z|+m =71i#i Cjϋ{ȍF-[7rЋxO.*w~O~tR5Y--_[no:DViZ-6*j2!>HA$` & 2!>RYɓ)hgіeqС|́G>ÚWm$rOd&];1YHHHg>RuVvIGTX$E}:UHiE 5ͨQ.i4a>Lߺoȣ255EiMgwR PujFQ0W@mK_/'СC>gKw˖-?1K)?tqTIQ U9rNq{wm6-w5l@5UUH~@VRȫTUu|H^T*"*k*=(l0>2fttZ3ytM#=d$d/@S$BY!p,"hg+Coƶ̔(p XYYV@Q;Ew+dٵL6]*W)7eoW7W\֯/}J__ߤy7&DB<yZ8;n˲GM3=iӖ"6QUt:e] b2} i@l $54EiҶ]$fg0t睳ws: ٳީ\|#>~N}|caa'ruYOWW'FCF[/= B:E )W*0u%S֐$SJii q]?i?5̲at) W4e=Oz芌a+:hoo_nq|'WWJWA@z:?mO'˯$x&$ = <}|?xUX_Q$LSؐilMP@T$?,|+HU!QO>]BB 'vG9tw [w۟;x`\x|W?/isOCYO O>)S'67eZ8'}?dRS\fk90 w3ܚKJ'|U?@z7~}>׿5>2q={_K/oYVlnt׳!p]/.VBGe2 ]l897ϩ8y(s926?PhQbc߹MێaYVfyy/ "C[>+z[w_;;;g\y?uKHHgB`Z,:9iYLV4 ͙!rodyi˲(s+^+ ѣGY]-YV3#fX_Pd @:mVږz{& ¢kMEQ|@Aq^˜98#Аts\'4MZ^zg|$$3!g PٺmkiyyyC*Re|>mUUWUUn&Z[l2W̺[ig~R5TZe3ШH2 g 6lئ.OL^ #Iτ|d&<ϋ-baaRt-[|I-[7lYD/_ď~]xN;]UU?7~xfo{ooݯi/&XB<s7O]xᅿ8kk%\ĉȲ̶Yil?83r?b9>¾7G7_ elͷ}짓-D$!獛tem|]&lddNz?}a)a(mOZVkj 9={G 7KH2τwqq FO<{T*ux x?L^gB<~NkwڵKKKI τ&oO18τO~OlPBB@LHHHHHA2mτ$x&$$$$$$3!!!!!! ILHHHHHHHgBBBBBB<τ$x&$$$$$$$3!!!!!! ILHHHHHHgBBBBBB<τ$x&$$$$$$3!!!!!! ILHHHHHHHgBBBBBB<τ$x&$$$$$$3!!!!!!! ILHHHHHHgBBBBBB<τ$x&$$$$$$3!!!!!! ILHHHHHHgBBBBBBB<τ$x&$$$$$$3!!!!!!! ILHHHHHHgBBBBBB<s3w^IENDB`micropython-1.12/logo/upython-with-micro.jpg000066400000000000000000002323761357706137100212670ustar00rootroot00000000000000JFIFHHC   %# , #&')*)-0-(0%()(C   (((((((((((((((((((((((((((((((((((((((((((((((((((" Aä:I;( IL⋲2$Zg%Ƭ@(J XB%W-dw gՓ\ DH]ׅ<41tD&aӌ҈tAIƄD(@]ؚv I&tC(#ԶAM+RV,d(!dc# ,tU2+i93y" !H(Lҍ %t}v{ֈ*:f:5E[9m;y(gm9tܷ[˥2˿9e{~5Yαpg Rh[G i֣cNZMgǹ-ޅf?@js;hW%q  $3XdҽcѲ3I- wSέcXM}ve_:蝆x䟨ß-W> zݳ^oh<^Yr]@v؇I1L` 2P'` jjʱ=?z+JMۙtfϏWϯvV#4w `سlnS,9 `T,p!Q{Byڱ щN&,ˢ"S)r).K:>V_fB\jyӇ)%L2I_S.INyB WNңYu6.RzrqvݕiAc0Fgr# ؛X3U8N.7z^H|?wO|]/d*t>gߢ]_~Z~\rVfx|JeG|1\L8[:^ltK()* ]<|s:VThX';Et%CXV)1(k{,Z2:MenW=mS}GoVY9gGd(I#yRB/ʳ^~l)ߓT~uw7͟qIp@J)dvQ*|6 ax>ӏ{-/gƺ@==nwv?{jB>Cxܛ>'Cs;6~vHnk:* z4 |I]r@J2QD@yAB-iUtX 9eWDZUa(H H֛;5W/ylK)mnS-ku7͌m ͞~sEk| YPU޶gYmtA?eՇiC+Y'!8,QT:5KSfcUӝg2gc9O_I|;____?:fA6#朧?W\NXӉH 2NMȌc Rd%1ftl+(\ޒ1o08sZ}g,.b:8sOjTj u`fBp-nUвؽ'5G=iJ]Y*"*+De]ϛ]e>N~>F{|}6۟99|+cۻa|X=~d{^?fz_a7?;ڡ&`I1xd"P2X3:Dj2 % #tS\,wEo#W6]ٽdAXْAVU9l^gaS^ ѩPf;7uf7>3u=9@8K.8L;'tWgekTy:XOw\t>דg iK>sp>n^{WWݫ}V.\/{~=Fe;Ώ龯F04Tc#Gb$t;hGň"4؀`},{}-p\SzmJI~a^ }f6Gb.\ }w"2:Hgx8$`(d]ZBPVN{+-lwnOGXQ\xt܏9zϞD0dLx:gͲ}w4ӑlz:ls,u{h괉%lh 2+JOIn*Cϳ 4gb\]lW6NۏݯÝԷ53 ׍쎋lT>tzzY迥5 igEQ?#9}Oΰ0XumÞ1<:ňcQ2:*,kE1ta^;sA,R,bx!/~t= }-t-r"J I}P}mƈ4򇭮chٸ/u<m?"\;­?G˩>|7ž>d`>Cꕢʒ@^BS$8BNqJ,@TЭQk1*Q8O^,v$;0̶-A߶Zr祥N^m|,ز}S0[PPV`HT&b9ja5S|ݬ.)k05q:__s<}N5|~Sɬޝx>-i>iOϿAdI^^k9Oc_Og.ͱhrwψwF"ve GQK*ДBdG5.=t"V !%{fO'W}^yt)6xVba%rUUj9~lZjZzѕu2(" bK`L2  #P0$U(#< Ws:UFjhq0sA@(ԯY9ui|-ލgs5|#Bjy, :uvCNI҆ !$ j-:sD(?W,}:>߅qދ,3|^B{^^=h ܏"<٫rtq ; K6!;Ji'R) yG$Bq`J# ;'U aN@e gi(؀,KT5ڤ3qzw]8&4asT"XAJD8ŹVh %2CB"b9H&2*ȏY9YYOy^>sk?cu=zHn<`U)yҹ\ ]iWlfb ^2Na<.f &P jF LzfPQFm"jJ@VXfxMQ@"Vڨ+JÕp$7P$U:JI'$De'DBq$FP?11 2!"#B3AC$04%5&_o|8>:.OV7[ɖbwk5rr[lYbKX,bX7eA>z:S?>!Mݐm9?N$[{}lHa}X.#Ł e?/oo<GR8|7d?x5,dɉVleL_9:Ȗ$9/ؖ.B e,Y2lK~Y8: "o/ή߫<Kv[ɑm,K'Eӑe/g]bX}le,Y37seVoo:שpu.zOu,dɗqqqfJ}ڃDĜH,bX,>2 egۨx=]K#Wgo|<,d6NLn,i-%_tYl[b!`e,bٶmlf|6H^I11otu~>3Y2Vlddu&}}ąbX,,bN6ۦqԸ:OV:r"=SA*`Q{x?Ku"&1Y22su-;_e[ؓ`XXŖd >]>?^qC:k}cr߹!p+. &qQ}PGb9K?ML|f6Y%}}ı%Q e#f[2;%v^F %߫= ]ĘGπx:zudշyd!f`p7j!VAc9caxC"22#YdKrO/Ė.~,`[6X۫{xq'Btd~F fB/t_?DL-5e۵aG}Ƅ b(B>Z`#z&Y2me,Ӛ}u,Fs)TȠXc X Zt݌5ZJ9R5FSk3ڊT|7&/o' 'Cu#svLt/HɌP;x?S+ q;wj 'AfBbBu e,Y2mpe\2 E,W#v1~UHf!SKo&4ɨY)ከOb֘ݧNmW"4ϿR>|2p֗&c+7Mr}`]ornrYgz`rSUx۲݂VhnGժ3(̶ e! O*^ ۱ W;F9;[!Y:bm,f6DlYdHؖζ$B`e"EŖe/q+?қ~Sẛ4uQ~g}*l`AafNɉ̀Z;h'/;?F ̗>賍}Bmrr}vGbGyE;-2Yo~{&q9v;RΝ szZ B=[5 id<+}g}*QݺGRUvV&nK%){2At``me-?"AR^w' .55%fH6>ͦ(pjghL6aZ*h耍)^@}o>i~Hlͨq$ r a l\&WєsMܟ!(b,f?k7Y:"-HY[Xz-^E8N/VPIB n P'I,cyO"7a rh'x^iMZFO^x{_R}@שu7ztu3]Q?O㦧6ڸO?VϥЭ@],!eݑ;&6Y$nSfwiB%tɀjؚuJ8n]vvdwsXle}]VN*VY!^_͝4bٙ*Q )h5ګL#Q9 C>T$i.X w1[89WUb 33t><GR?^ʴ. ۶&f+R>"yeqi_Xh5:*jт`X,bȅae"h; J| x{x?BV \7*IiF[٠3> F?|jNDׁ8XҥDzWeG-k5HaykM%w!Yd"n 1L>QݖLd 2yȥf[oƝ#1,]b|v`D- cl,YqԸo =[q89YI!H~&/dBjl E S;dW ғv{e#Z)%{2D'A7_k߿h*ͺfSgtƚ͡z\Ƿ F.{A+dKr_tl,[bX, `Xٔmѩ]odOM;׫R=zz.5rM4pVYP,#E[pv(%(̒'QFSͻװP]^lbcO#1K.)9dJWڙS+7e:kM+]똔K]NqNu+YI;?UoXR2:|u.#\O=zY=G:ݖLdd4YHe U5(BDZrGB]!5,XcVLM{۟?M)&(Y RIAiCvL08=FGP{zd`f6UC=]G>#u#;F5194"tj9B0_C9{qf[5W$YC)K>{Uińwl B-,e"e#ܨARx|d^z}l?"̑qNNa6Bi:Ae4gP2FGd3'}`n㳋Ҵ]Bg:aMZn YSI/}cXqY4\]B6+#[ɖL%jg:̈́vQڑVM0:^J[r11ynmB5n7jy-XC7Ԏ1,&/gh~ 喌0oگJorv)G2ݬI4ZU^ôo(,jFQBe_u,]0X,02 gl7F},oڽ!KFhժC^z?8Nu%#{3[Ă-C@ +s]Wy?؛toO-c`OgP?^|uٛj&ծW@r5̈ "(含j,&7&6ZݗqvwܛDXy=Wnf-Rz&I?liH` ć\f+5kLaB2e$:֡m8v~ `ӓ1Rt@+Z~NQ./|R`ucm)NRŽz#4m >=F $CH7Ӡݖ쀙f6Ys@ә+Jlnւ(p4 XZmijӳ/~nS|(!KP6ϲM2 'eRU)] 4a9V j@HptۆhMWzd[pjRGNxs*G[e6[VkRۻC@Z??YJCO>bك1e`nvcfCgM,16͖lL_9,nrMe[: X2 ,YlGR:HH`H FSkݷ ș{.X?(̼k]Ȭ2D"Q#4q)],:j0[oԎW`Po3VյXinf7BII#D*M)Ds*[ݕaRX?Q$*(&6qcҶ [}M0< X2̛eۣ{C&z)[aq9 6 z;Sö˕q=P5Qi: :՗Z^UQq2RN+Ml*c+CRȳ8bdQ.?qid`d{iݿ =pe2ʆx6d\>]J[RRzkSU+Sp%kk+0O꘵ajUOE@R|b /fgu^ЌSF0#jañF:9IY00wf٣7Dm,wfCYYrS"6L 0,eIAj9gɵUt_ &eMS"o |[R`Nc܎DJLG `MJ4eY1i$:b#y X&A_h;[,z-:%6Ӎ67 }l`X'l[)8Jq?5heCHs(4WI^^a"aRB5۽d$d?ճ֧%jjB֖Rբ8N:#Ih{GWrr:gXJfdfu֦Ri_f'T"cCτ~ոtjUi )[6W gmH e'-_ wP#Xc\aid' |7-dd6Y͖h1BW$&jwgrZ"UmpN.J32bum;Nci0w^bMGgI%&2^/ɱ[ѻM- !(]=OQԊUqng)?pyOӪQ),~d?8BQDdSٽPݢ;qoo =GR)]jE2*B}/Mf 2uoQڄOK,<6c\ؿ U6CR%䢛-%om,bűm[t>:nLJsP †ƢѪIR9v5k)NNf tۧX&Ы$Yg~Ⱒ{ 1nYx <->pչb@ wn&Y2ɖMlYѓ$XJB}mXqeja gnp#3jF]']0`Us6zK7e8Zr㷯زRIRս=SlV~Ը:z>ש>KNJCBeݹY4?6v=7),(JfBm DN0 ;s~Tl;>ې׮Ed26db+(yB,ꥉ^[3\ |Ur['-b,Yb[}.ԔEKʹhUTm1M4UDSaxd{o3ȥԬ5DO|iUs+RirIJ[11 /XzR?^~Oz/= 5ח=2ʣtZ=-Vvb!p]%h㔡mgfss]bAܑTNGb9cݸ,}Np uɓef55dIӋ>(wGY&>Ԃq8zmOIc}ZՎ%8duY^* H{P)i䆰4~~IOKJ1IMJE]J8", l6eٖ,YF0ѝIdkdQ/fL{N%/e[:?| X2ųb[/ۯ?ٲvN(vs=qWj]o˹+T5i2}Q&B=5 13MnF-6Z e9>:ש"jg|Fekғj²`PXSpDu>0BteKRi;n [o1XQ2Ajr2جjkY??m~-D%脇8T4 64ӿP'MBniah:eZ]t\NWٺ>ݖL2͖k5}%˹6kR"E6LsOoVGyPC Bej0-&+ݔ_'L%V!h~~:5!vCROlHsIJQdqCR 3XlJrvV:չEzc@)yJ悴h=;SuOqx@ZM08ţ=%+r[/l.X XŐm>I{uYm LTvcUSlAMڱ^zwzTp'mfҞbs.^Mjݧ?T Nł"XF(/zzsaO̰Rc#"9hX/o/o3dȉ͓e4̟iMLyOlZMGX9N֧bxAiYC:ġO0U4:hmk5#aoz:K\,6SĞ_^I156kZȘ:SծCX*g' 3յyo\4N"%j+cn"E1[ɑo,f4u-}lX,`L❔egQ]bg!%-8m,i3(sM^.TŊY!mO L3~>ߡ)ݲ[Dr0rfCm첵LVAQFıAr&G'Z:z%\D*̜\Kwz\*tP1VWvQ-Ru-bbX2,S lE~'} JWVY/Zwj4mwAjtNVr-.B4j5yjvI aZrh_?JE?/o+&VxYe(qC؝䩳[g/5Y6c/4v3-~27Ho^0)$`RB!Cxtݚn:q4QNDpp)YLSݠX̌9/VfƝxrZe |èvFrJ hKĽe,f/k5$NjW5c,*X b~8evwx!Ac(ʮnvY̰ʄ'ᝨHqhK.$%o' Y8o =[F*Xw ojCJ;؁~I::G9;A!:'D.X `e,Vt蔪ǵuU Jm4A{ ƏzRfbduqHӜr)*>/9 5جR#nTqP.>qR۲37Y8:S:ɓ,36YrDq8z楪δ%< 0vK\\FnU'lMoM\'FV_l1›6t펌QԒ[Wf,XZ ͌'( f9!Q_ 4TCVY]!b=uH&OV8l7k-_KX!qff|Od6FMme9:-%_tYl;틬V ,N-A}dK[u5E5E$D Jl[#oq:Y=[oE3ϰJ6G?Zrէ;m֞j_$1G^فe^g:4M Njd $a 2tC ~&lH8m ٷ%_dllp2,n"=z:R>:WQMz۴hFhzCI-Z Iq:pԊU?|oLUeշX Gx`:Uwh֊Oݢ>)cS{B1C!z{lgHyj9BkS(->յkMdv?Vn{ȸ:R=zu]GWQ|uut0vhNH>:Rx'mlf6D K'Y:ܑee9\ԮkR'EI6QL1bHB`T  ϭ_Pu.M)iA "Nv_̿l {7WAWAWQԸ㫨G?QtV+dv@e,f2unHrVαB?,V,m RFOߐUhhfm Qf^mD:pWR36}_Uu@\]9=&OљբrCgEG~#㫠u]G!ue,d͐k%/v%]bX<6A㫠(5*նR6Y7x(7ɑzSx¸E^*%;UٔxdfY2~?P7GQq,f6NlYNto_e[:bX2lelzlA{x>|4!10@ AQ"2Pa#q$B34p?t>Dw:~镮Gjr@J؅ T7 rXQ )[etSw(V1jȔv(d]d1Yp|\tˆlOSo+"&nVajtЊoWr }"\fPA?bm½ d7rd;IU`yDnp.arNC#N 7p2èSή~Piv(zv",ʺ"2G2.RB5JEa1E㕈V*儲ї*i9Wv ʞ]NgYSX2{mr`Fb\b:!mqi^58r?cq'|J! 5_լM<3K8 `Aela*Q!G}icT>'ixe%# *˃9[#]CfRES2q˹U1LZ i^4\zۦ;hLO|lq'hg'a18i𪨦l.ˏb#Sb4&JHD#n폲&WUcශa~G1UtB&GeGO¥t xbp ;q?;E-laTsv5bTO9"ѩM[e\n/EBsQڵ`>~'p^B`F[3!1"0@AQ 2#Paq3Bp?,ydsF_dHOIF7DGT7CoThMEbݒBƸogҖ;:uٛ&Uu3u.nюz諶NI$E}YZ ~ t%G{ vf$`^ο&%;}7&5[nkBWNERQJƽK®Fwr =Tï%!ItI:FHy;M*`C&6e5lJ2-n_γxp&E s4\U>}#{Т)]fUpkob< d1ic4鍦1sKd7l[0k{ XU~ _&8%-D(zjUW:uJTUFj\L?}F`uYcHKC='rNb%L(iVE<}FIbNBV̼(rhz"G+Dw/#fFtnkٙh柂MA;YgM"FjcݍѥmHns;Uc:Ŗ8Ɋx^qNIT,R;;M=kϧFUr//tct)Y &}_#J.qb+͏'R3m*,PWK?KXgOy2'q#K}6ґX?xlѣ~9~jMp8Em5IGR*"ʼnݶK,v7r޿˒8R\zedE*|UG3:_4ϖ{lül?B3g:E#/@1! "2AQ0Baq#@R3b$SrCP4c?;?WWebW*+kertoӺwN𮯹eeʬU, Ѻ<#wOP],QrUmwW\ YYYY MWW\˙\QtӺ~L%eeeemWW\V;td2VTW*<`U;;;uۧºYYY[Ys+seoh̻&nP 㟐tn殯eem]5]s#olm&s'FcYJ ͜:*i pU;_pdU\ۗ\fӺwN3VM_Eur}.@qm&5M2jNYUTb7X++jjWW(gd7YudZmRء_n iMkr#iRUY[U2W;d[^\md.)N[^X'! pqÙhT^yW%' '' #ZTVc1ou0.?%,g3L N7LpԨ~+,8e,Sg#r]_Vcw7XUTJgeusWz~Ez)g76@u7F.rema]] "F:עtR6G5&4F-_l=v M"l3(7*&XW q]pr=YG06^-"zmm0W6=%ؘlQ1;*U۷W*emgy>PhLq̬Y U儔(o>Gw(9byX[XŒ\VoX7=~s+g%'RE$2yEd1T,Ǵ]K ;XPBhx3\>E9οb멲7<=5=)vUuu}AuX'-UO28QsgCl@]aSGc/\03Qc£JvxB:.&3? ܋ôRuBfƻD^ |Ma~:G~ܧ=waԬتv XLRw \ecHtpK^#0ypeߢ8Ϫ$ 0X&A|7WYS^ڏFj6BLUdKːauPh*2 x SuTF5Ѻ7FݒB; '҇[)8SzLm/UМiծSZG0SV5,SϤ&c2xH]F]:ҏ\zksq&M\ybQ;KOuRb>tںw `2v iC쟰[ĪK%ciuǺ+r\=UA; W*tYX#pU%b;tn*m%yh$lΫţL[NvNOr06}"`  UG$\'1!?Pj |[gV9NM{3[y#ndDGGЍ\3t]%ɖ|6!}Tx]€uJR,q4u\쭬eowɔ<b$17=J-kTإ8%gD+F7 z'0Nt_ Ӻo-f8f\lg$f1)BxYڵ\ dc7?o>!jrM4[>da,lWLQ\`2+8}ȲqaƵE:8y1uLp',0;vgd"ps |1uuu}++++j.y kXΕZn]}wDf J{ ^:'9HQ`=2+U#0I9)#&|Ni"GsSAp>`peF},N~ 0t}~n/Da2FypNfmrShkDX%`XrE#O*Θi Y,С`4( W HppV{dk]_v٠z殮豿c yWmL h j[5ߒkbqE2MANs5rCT`eAB;0 꺰Gb?u΢.t1pNaP^*D T&>lI\8}To%?E\c,Z4%\m#U*~FQu`wߦ rLR89#@]#z8_] h#Z\ 杈pTm)i73];a։);4Z+SѪŒ{:'JeA b p0w ñ@Sjȴ\MEiF5TbT~ǹDӊ5Ft%tiKh* hƊYb2 ˔n;c8D6M8Fms@Ξ˫+ʬu]\tXtA(GE3cF Õ.G#d]ӻ+ࡄC,UdkJ 3$0 ( ,U-TxGt%9446,30@E HO{t"N Zyi̝#!Pv+*PA[]$pGGI!mjS\zgvdT`#ptxXz_z:ʐ89G.kl \YW@mme%.:硲y=>DoTZwhe 1J!O;YkdjQy8p hI-aŅه5qcik3w[L.~Vg;dimtu0.!g%VCd[C)FYVnI-?:!#F+EZ6SOUrr£! ?3{ kl'U=Jɪ讎Y[YWWWWG? .j"Zs7+&k3h~(7(j)4G[q;6!W(YӺuʽ-;p0PO/UN<ңSkRʺT粄b ZZ]\G@e=ZT٢Xbp2s ;kjW}-cKQ;Sc63dJSd~졿9{,2I6d}JK.ە)юzobFAl ;3u}W5YYr+ ӨnD=5ã8 OٽLK}͘ђSVeS7=ph3҆܆0yBmA9f4'[sOFJ8i}c0,6rdA~."pЏ ` u28'>Gdr3f&}.yɼM-es+FNnU%+3FHes5MB 81p]]yj)^7^[afp Yo͓ė4Ur Ab X#mA_HUJU\,jtM2+Ԭ2PiD=r%TjS_:!TrVeA%2a+'D8prHģX&9W3cѼVq?Ы~س^&7aD9"`踚Y!av73cm=?s/0Y;?D HjUw)6i-w#}@U4ضncV3;&AgTfr9boRJ󉭱m|a9+xދށ2*#2!?7|<úv֙dzdu]]]_)P}Jj`5RA (8p& (%iڦךE@qK# ݏtnЛ{VxÇF;>Czn+xzuYэcQ8ii}|AOQeZ谰%*9#=PA6](^%lcj lq&>0黚o4s|ػReL{/ˍjRdkf9k(;]X2[=*''ցY̋`O^Ryh'PTƠ{o .*;fC*3 ~c}_C.eeemU('b0HO$s75Ef2Y'd|C=n@vYbgl?ҁph \GqOVoD k?t kcO3ÁѷpOt1<}u21KQoV]*[F{/K*&YWd?PXE6)E3NfɎap[m nUٕ35Ӻ|'jvo<vq5Sus1F>Fl 啕. p3Ǵ0׳Mc{ZUk*6om=SqKVDhw_v*po踁gT %6s*G4=FMn*tUEYPlO(Il>sqm:9;mxZ 7G++K=_lQxW,1bfqms,NHbٽN6h-|2W6]6Ŋ8^i@+hӺwNS1Lk\Vi,10D謥qB26P- ?g PnW(xt%AuM 6cer6g꫸ŨSa.)E͎& ʅ@-*cNǁ|ˆ70?lwѡ66ٹ(\nDNڇ?#1囄0Xj3ňu\rw~݊gIU2 OT04vLbX0jK4Wdքg"xWWWuYX#Vu䞙N[phopSa/6 kzG›*-!CS Gx[RiW+8: 'lܣ>WH0uAfɟ[|+$Ea*9cpC(x6EÃclÖLZ4l3$E;m&.t8ދn`p-r!pX2!~+D"$;!W&ɊSZ atUXiVGHY:XBx_r=ThYwNѴ3jhڊ/F<)K F*. XhT[nbU]KzNͲ(&tF"ĸwMk;) NJYBBT{L4S߅BE~:yMt'e;;*l|[' w>grcJsprGl) ./G))@\uOdPȇ5wF ']maDvYaiŚ-Fz!V,3%CԎvVVVYkU\WXsM~#d;aQ!9qo_>=&0K}qh\#QЅAwd9[Fwm H%ճ-[Gꬳ8[wKlE8T`or$ńtXt4#Q~1 1>PsF6>S@Nr~7,ܒ+:ntՂj2_جYn; T e.h3E4}REdM8ud.SVCwvN;_1WwȟH4lLXՖsC@WΣ\ kSX:0o6BF)%YU+"*GԢ9}SWT$nyuMp:>l'Q:{盛##@E.18N5r_0-T)! WUNP ub{ַj-u((W!ELU ,9I~:|QD)l E;tӺu=Ҏ +Gy¥|vϱF"spB#g9r%"f(cK#N1&Nq3tiUYgi%22dvz=Jb?mZݎNE+&Ni?g30*2O s+LW5,:#] [<恛J>)"ة@ 2-r ivTj PտGttӺw2+5ĸJF+)f~yl c7dGPwXM0`w(=< 8=S者م]]RflzLMtoم siWs;3z 5g 9$#vSK#t8lqsaj ?TEr!WG-nS1pٽ>UEn..osLutnѺ7F媚N"vl›Bn)_=ՕٸRI!cYضR}'n*ahePpf@m0]#o:)|bBQxmՕ]]_Q΢;j>MO5lҘ_m!W Si lCiF0Ný{/2_&GSagrF4ի=RG?T}Jm^5Y@"oN4N>F5aњ oqUR=7FtnY : Ѱd#h9eN{/{:+*>pqD!a멯w)KG!褆"Y7V$aG+GNit,wNL1|MrXsYO*1iF"G 鮂Ll97;ԡhH&'{$(NUGP,݄*D}ut7,K[XWWW* Ѻs=Ӷ i 'Jͩ n' .?>W]aQR{tl[GTLFLu(GU2v)2#Q%ktj(Brc{jd1{,+gܠnc9,9Q!VVVN(W6̨\?4aUkWMY#VVHɪi6+i78DESg(i4mCe22GVKH;pGEޚ=Auho@k$$gF慫4.Z,q5bxzSUVVu}E6Yq+f9X+jʨ /0dAt p7KVF6F2!Id)MN[,D6b%OVuL%l"Zd5 Ѻ+++n] ']z9Uի@Rѽ@%} q&Mc_șb4u[HIcL&3eq)Ųܓ$N =Qٜ4͔a1Nj,Ita*D4m"˅^3 zQC(  Ug8^Ib5R*mdv9:z|YY[zfQ:G@L*#.7⥺#qo2T &TL&t*)_f=t^z qUDj])5[7( b>F䡑icjRN:<ЫWܲ)pjPg r[GEY "7GW9byp`h妣fsT:(4.v"{-INauY,a{LG$q8s)XJ.p'baPW@;5}+++#t%P qQepS$iuBg=пnT h]+*FUp3>>&UlU.jpӺwN;?)!1AQa q0@?!7r3͍f~ ᇋd24, I\: uL-4kaЅ-^3'apK!G<,tL?1~cV~~,Hw`IHrBv.v4霁.gPf\yD\LҾ//C`#,#/(H)" v> ?^=??~6K>,M OP؎= wi=G8E c'.j#)o"\P[inx$(>a<" x1G~~6c ~3ro~v'j}rXl7be:&"2N0'i B4B m"Zjşx!s3fF,?f0d`:Xo-{HpŇI$>fajiVKq=a E$u"@A |`>fܗBƬYz%񌯻oFDPh57馗18bamЯ0q+ H":B b%"$ )/9>)'ЖݰNX&NPׇQ0i3?9,9B4VhgP=iy8He=gv7:BR,c\? cf2$Am8Wh *&; rgQWDM g }Y߄gMŝ7$ؒ r-i;< $ p {-&A&g=Ǹ[S#Ӂ5"AK~g <10i:=f H%XFgOFǦH/4Q mV$ BКX6Hg "+mJB6&NMJ ؋!9| *X#h\ H"40ai=70C6*EڇQk,jħ@%rKO^*ް4'-BbCwRнfxN\C9&)o:]z.I1ٹ #KT!xL q4m<c#EVd2>#qVXIR]]!z%2PG fW)%4]ŏ4C)lo? V1 ɣO]bt3Fu I>z{&ӤOS5 4 {2'PL!y/ #%)aS&xi/.BC9oLa.hE~U Tԁ%7vfv aF3)ș%yKc.)l4dA'؎Nj5f&#xPV5$؉>s72a|2,dCP$%gp+G9ְQ J+ׂvox?AB& B!&qal0߀T,jβP/L^4?r$J'c,I(R4-"%2bo/Be%VEBrt(0Q)hDh(2+! L9d5*.v$W#n :<َq6/&PqfM!rݞﳐ&@kp@Љv3NU"Y{aKjo#RB[$SH'77ЮJGkykt#iGBE9l)v nfj'aN[68荬dIBi_Bՙq3-+j'X  q(Q!ɍЪHmq"`8v| z( }Y`m8~ ́[ RCLJl0L;9Ka°P&&"WqWFw#(u(HX HJ9 ?qFAYuzO1$&HI'0$1H"=tAo&E_/Q"i(#aٙlJ(˲JEiSڐÓZ詵* v'X_!',[-a#e@ W֧T\aErܳq Q]7Bir 8g&;%+_#S R^Ô!L2b^-u42Ao[a?}xPo bB`A;3]qd(鸞>:+\fL,W0Y2!idHQx#TA ij*9MB!P;o5)nK>HȂݲ213zw-p$rňC$ƭ&$$= B61)(-©)Dx#BBϢgKބYtC2]izyA![(t}-/bƛ E4DIJ'P/RQ-F}@nkNUIՇT{oCe6ahS%'CV`TIޠ ?&(4BUzeѻر_֏vhtmO.0J"5ap Dc|C'F=}gYaIƖB A Łiя1]Ź<&sHeXe. ,#11^ݘk%[vMDIdq(z(~HV8/F8zL;6y/)@FP2%ԶÃA'"2qlbF+#P|| <0@gl$xP ".P_g Rtc)SgЀ{DO2nD(^[PLX)q{>A;vVme>ymŏ?/ 2 FzYP[ztF$g|ۢ7Mu Yëċ}$dD`uͿ3gLL]*,DHqr?&oAUVӡ9w!y@6~CH o[j1; &GmGien2ʽ#BB,˜MX`#)2#[k䞠n46͐ձ>!G߱$[EO[y]4>6Feƭ?q 'ˣ9?7BI-FB"KvrO;}OVX5z/чY\,1ۢc G$:.VM@>YRS|F?:¨\n̗Rⰻ;K`g++ Hz2Bʤ"rv8HI%A(A J]$bXʎ6Y#]\̂<IHI$^M[ 6%x,TuIрF`E71]`YPڟAQcKGvO,砼!G&Za_=6~)FgCkx NDYXTfZ=ؐ| O#D:@n懡k' , Q[c7DѺJHB9cXYDYN겍S >Vā?!Ruq5ծ7BF'*?Yiaf%NK!0X{X1BE/)⬷-5 T&05 &;}|۩/hZ LEQ7h$(;jK&"^Y:uy6C(giu"IbDL%Vgm ,PAhąv-PтSZJ eIZx?qE%*,7cȂI?x1 oFx',/aM3=CUK݋Z)(rd̂'pC<.b_it9q: r 8C)O ҆i?x t(ۅ,!+jq]$KZm'^NZ:Xk(S@Oǃ9;;\I$p58 iά'"k6$EM!k"o"I$m'? $YRFĄ^؎p*UebX\  + Oc"$#9=b7aղ?FVp<6nU)>6\gڙmlq J#6}ԡXٟT,#Sv >c#$A#B,ln-_H[YҰCW"EvS%Ѳ$wCW$8I!DqKy!n65v|xBu{;(u6z֛jŞaj=์ 3*mk6SVdRLR` 7hBZ dnw Т 2hDNp+p7M ؊lft(cU v[fLL n"rw[%M %ܖGU ŜmA`ОT~r-G.1 n}jmz$Ϝ1bT {/v&`>gF`j .&l|zOd"-'4;jF4D%UNL|ZS =˂cBN= NK#J8TQ0!7N䁋ps/ 8wkdK]S;r:LUiz'Ѯ?ȵJ\/xQ?#IO:9\8hCL~㡖b-Q#X]'Ar#zFR˒?==d*OKU܈8Ls)'~Ǒ0VΔO|bB62K8ikq\.)9 נ>O ϳoy!|S[ %ۨQ31d BBL3.*UyYuc؃<^yX72NW\\As}EĜ;~B\rSn30(׽ ΙB!f^ОDɥb{Q67NEtNS2QcFSf=n$#+?X Ni'c92;2R"h4ީ.2A|'G":'aG9&K]dFuqg-C!ȶb.O9cސBV| ˁ]m) ۰/>8YRaCA*mX"#Ve.:=(Hi4?6V|6iZ=B'{!%t6?Z-6!< "ciihNS14"0l[؋CD\i^Nydl1D,數 Po ӉC&WH.RnskIQ! U=÷I-{poteluɛYp`HdaDe Nb6{rf!+Ƞt#+"GyK!{=$k KkI'V-v4x'f Q֬I#tO!B57#ʩr>0|;X2HR ARavPPj!Ba NID*S*%/T#.N-1.K-DPr-l=2~`"ȩd-l^eaV!V3s?CzkqbbI+C֡O"G=7En9*B}p$$ld10xМ) ;3p|j""~@]ABdI* +Eֈ])S:Ѵ "H׈9bGV0rPvLJ$4r9BD̻*qnD /Bb28:L4֌"4 t;Սd8uB4 PXJ$BdY]"oȩ8l%Iy~ty5v<3 t%NR%zM)C) pNggę(ǡ٩h3ꩶFv%ZDI7"ȇ0?ieQD RTZz)Z=?#Go1qE;0&?ȿ\v K%mCcE L&[J|UI U@*v|60d=<8|9 M„^@LLUh}ͭZ&ȢK9A6I=.)bT%RJҎ̢0]E Bq$+.zȽ /HSP_᧞]hQQk'-2j\"ktCIHc`ez5* 9DڊkvI>IA'rX8HȰؘ~'n#ɒ$?AulTȖkq7,Dc4 Cُ`HjQT~FǮ7zm$VB69JHBKT7[P.a XʣͯTj,-#=)3m0Pi n 3w'ɒ<$ /x"DH0?i3 p׃=ϔY)00Pܢ?|}k J"xܦ_/eB ‰cر1YOl9$5Ҭ)iҥr-2@߲?X>v;Dii&#̘dj֙3=x31KP 1aBxgZ#`VhjWԏ{.[ [BI K.ۊQW e!;"./_:# "BTO Gb~6q7%@Ք~ dNaCfoܒHAKe[f?}Yh5OBÔ%E4}{>cߡѠ|eHz0M]ܥ1r{V| Npm;ܿ{8ԓ)?2IHn0sH+ 32S] %+_jј=8ÑɄW6\Ph\hIcUW+b)) ̹|B w,p>+XӔw! Yk"I l˼lzB0""$4!2[Myke+:Rɇ; nމ [%ݴޕ?CW*2iR7z$ /7}%Mƚgd6;-~xHrI}d 'R(I/"-lo4({!fB7,):7q9_'E;xl0lSݺ|BId r#:'SAIc^/c@I/R7"5U#DZ] q +} _#Kj FL@0~+LOELM୅R]L.4ښ~꜊e j!D\PnXKQ_";ݚIfޘq]2:--v1 'OQls#_GbUBOmzxiHIH2ۊ?!4&$r"g-a%*vH!І<_t(O{C0>q+0цF8Di"B seBXX ZyhmR|!̶?uI5cs.)cR \Og7aQ[CnXCh3+('DX%ԧ}BH橡_?nc=W$ٓ\yXYK-jQR04ƅn} \sl,."<[ W]4o7H d6lٯMĉl!̄4 >SA'PW}.__ 3%pױ}nz79Lq"\ --p熕biLO \GA|Ly\=cQ1"7P^WM> -Ð Ia4lπ`\\l9.DG<ta Cܓ0ꔊ0,\w7WGȾ5n؉𖩾IcSNgzԝ6WTeHDak )$lZ c1.܉ f~9qE ̢گ uԿ;$Ys!{+bm; Ӆ dBo V&%@eShkյP2YJksቋY0f duеkF; ]"C4|DPHIXX%&e -BIJ"$[XFKGTh2., C 5^HaY`]%."C J>Z$B)liKd'omdMz%)YC^DOph" hBJبm}n5R)B%`%3Ví-Hb\x?Q[z.Fd: "@J7i3wx3ŏƴ st,"t)E6)+d6 C ObUTYYr>lE"lRd%:Fm]Tǰ~q+ŎbݎM&({7\ Tʆ  :.R[$9% as!#dPӴ}dTȟ2CxֈJH[ H 'KHpgr$ND21|ˑ;Gr%>?قI/=Q;2H|h66BXuˉ Je,$"6TA{[>(NR}p!YJe_^ =hg2$u 22Haa86|F]&tG!) ʨF ENE6f{Eu-,LP1g >;(Юne"C܀FΘ%[ #,ԄF$EĢ5ucd|A4vD5}/%B%"RMŪ<ZE^ Jnz2$p sR%Aos/QL}WĮi}~BY/qI[ Mŭt[1#| ~7)%҈XTStB Mr '![1*V[,J(()3)6S&z%#_bK\hDcDfbK]ƕճTV y:\Mb08dd)pg8) @6|70!Jg )`-T%ieǫVr'~5,iCC>MiZjO$CA̓MČVaY?A$D-vrPf$Xk[M}࿂*|d"2fm; O mfkvI c0Z<0f?F1P#ܡDO$WBtE* WQJh$'M=#wĒ(RB@KOADG2G\% SlW$ fJ%"L4߁PO}?TdL{vF6YY a' $@b#D= fi4ǔ¨ADny}Rg\{[WesH~ {r9bVS'?_, ) SFB;<1~ &bĠ1ĠM>5yqG;.q>ÕޡFN;j(Cؘ#ZRxF͜*#e* ~{3M_Blo5,sқ^Є3`^mn_MWP_MhS|ϣ$_X;}3mxd<hǃ hkE͌kÝl)6vF xL"`t)(>H94Ȅ]QQ;Oa( KMFkc j,BE1j:a $!/N_y0KYpc@j4-!&2tWiA$P͆Х1a̦*t|Jbv"_g'D Y$aw2ط">lXv i|ApR8 ljJ۽Yb,9艢uX}1?=t4}VID2zY90gw3o أPYz7h-cbC)gcT] Ɖ?S蔺COQBr\[lX$:KBR4n@ҁ(HYpT(Nv{2N@乺IT5IqpiRoc!3Uś(ķ1:KT&aҟ%g5c|wЎy ͬr)ퟤ-w%)ޑ ; +dnR>DP{?% 7),4`>DR*PcW!Q`gd VS%6˲wI+T&"#m9!)6tD[%n6olȽ2+<Ai|߁ !4XrA+xK uCv9BKOE; WٖJ;!Ϸ#*%ҿiz!y=RY_ܷ"ƳކW((h#I|}.t"{~ЁXaЊ<  Itݏ w$Q4\ohjbVa&N]$7I#n=`Jml h*m61}K#%nWuZT,9op;сȕ>LI`Ot@IQ<#J ipt%Pqh$6pZ4=KwtJI_kc,,'D!;Vj>>F*C۳d% ͦ=.L"U΃B=$A!RbTAQ }KٰP :KM6e)¶% qr4PQ:XZ@*IOԟDT^ 4Š/ ' -61.*[# ,I1x Lq| slВdi=goܿ™XmQ-%QM =f-> Ob!,9r I"plЇl}dZ %<1ĭDf#ˡ yX[@m  p8)Z0"[/y}~ Dd5e:aY,O#|,`a`KVe F[r==Gb7su׳@"8tzԌ ,wN!NCEM.Lv\߆-ssz^~f_rNTFR&`-ƕ -xfZ~hCh)By<9ZFWB0?XOC)bϱ/[ tTq7̍z ,d;8AN $ 02MU ,6r͏DDdؘoIXf MF(UB I-/$ƚpxۄt~1,?B (rgjLςꩰy;kWa8ݘxf1hab#zDf\dMǰ!;"H'mz2W+Hx!|dǀ*P >H]HJ |1^?b5 ș=)- sld-~no[upsK.2D̻0VkaTbJncEX?oj>VK\ S9NN((*E*#?WxZɅZ9lB'lnN )^|LcQnF\8 9<3؎;L 1uRrIABZP( rFqO%$PšؐZ"cDVLO+{ij2N)DЍB oL,>"#Q>^"2n0T9eB eT{48Km o%M|-v{,RFECb:"҅"\eAQT/JQ1JmJ^D6lƥ1kc\zVD_C)&{!xܰ.y.Bؤ+gQ@K+GЂ4Jf? &.aա,L3l)RBm6x VT$)P?bDj(|22<?0$NKAΘXL6Ix(zP#) u+ iR|HٿeAԸo ?\[۳lSk\Z?ALgM_04![\mia.lϺf9H% E%X FБa a j1Cf_m5Rle!(F -D1fC$Q"Œ1MSq=Hyf jRsCȬd@ [ v KnݺHe0PGC;d:?8[NV䲔/+px,e[r$/ oD]ť=;_9ez9C /ؘ2x/E[ߊnRH Bs&(peѻ21ӽQ'AMM!"ue%o "IiGbG=:b!B|ͬ]1tb %iؾqHY^Ҙ]ZTJ$\&FQ'0T^2GbujuOXIp1gόZ"]tb~`6}Ve [r$c|-J& S"m\!;Nd\HHDؑN3-pԍ1e8=$V/ !V}ΎDeL!j-Y3I-lI}GrB:If,)Rk\ј'L Ob9F`5=v{rз&D+vۂwn.!J4J,m3f L| |&QhP76rK9Zwv"PZkmj`6~.IC 8M[( "aUzt.5wBc4X PYSA=[Z(JKz뼐3!.C5Q:hpr׃& *< %1M@E9̾k޴BFkxD0" }`L `<3X?WQ_K_mh8d<緪6rC'Y q=熙'` s.S4iR4?J >eۗe+2o,7ۭ"ɽYmEt2qJwGpӛg%8K~Q0{A}B+aQV%@"-#Ts3Kr8tOQ _*o`x ){*!1 0AQ@aqP?9^Zz7W7]<Ơ^q2o0TCR湎[Bܰ*D娃0G^L4V|7º5HQ AGx]b9HЉ{qXGxB^'#%DZ,61k$ԢSp+]JD$1Z\\]"6*.,]kSqP)K`\ 8QbXqf QҸ*:kU*[ߢA) 9!ϙadΜJ+D #R;`1n':Ĩ#u%r$v@YÅ_b|9ĻĥL* އ;~%Cr*j8H3NHD@q1a,4%ID%kSqBDblU1ĩhweY.#Uً`.傥&z9*T`)# fLtĈtHfT?kxj.\0Jﯬ^{Ji2ΦH%Ws+^|w}B a<=KJQ)̻)Yh}b ;37\c[xC4kC}`{?OηO d_?L ׿ijtt'oxӉNRbwQzeQ%E%BHUs\XiTr쳲^0 >_Z!-8{Cw*S/5bewA k'' ^kWP bp=lpK8)3PcQt)~2N1}\/kg _xc~!y]WQ% -f^{Ǿ1|K}<>0"]eC"*5FtZ=e(>1IXJ!$k4БqM)F)v%k ;p늫M5Ps(l웩JQe;3CbrcZK`~ ~&o^N,AOkb*Pҍ6l\ GsF#!4C.MY1&7Evbͱ"J9{KE7y< \hBhJ?%826&x!L6vGJCScNB Q!*QѲLF]%dwuMd8 yyb1롩{xOe>FBѡ &ք5;(<"zgO} q!-m aL%EvB7s'd!m5xJK҅6R\gi lXFDD[J4j*քĈ(( qa^F)+#n:%D!q1BByEr j*'hid pJ5xś+$CI~;V|Zv`=D' fBn n8*Ѥ6!i7)IXCYC!YWu?G*},Z [c>;i>\|iϱՒ=_w`'Qa!XM"pLAa8L]KعD)٭ Y| ɧ(sF3z{f5 Z MDQa'\&~(~]eb j!v!!G59(Ak767ȧ ӡ .҉%ZL䂜)@[|zВ3'DQ'زxO2_+ ,К(16%(Ĩj%*XY}d4%PMwu㕤HKϕgp)ǨFjxIi=W-6O_~q)M5T]&-nolҚ!:JW{wiS{hJO>}΄cY"p B}I>|WoX&jc\~2x"Vbǟ f~G)G[D%p1o{eBad!0*(I al6tL<,'QB*ķX.cjhAyFȚOAfPGT6\YD7*{cf^)7>F\u_')=P`VIt}b/\@2Iz[>'biK^ Xn%2探PZbW%o$ Y0P'QRf*r^x^`*2i_1 kpL*\g.qBb|D1qơ(TT*䛣x;U̾ɾ&P]0'ߞ!WDCn&V#1zXdr"ٚV镐J,jR2%?t_S%j)p'Pc?|lS"9*-@uaG~_02JUě;HJT8aX'YX;ƞO'1TNitDwZc<ʎM2C29-:2큎,c!qqbmc0j38}#gY[; Ѕm~#V߈iPm <3Ş9k5a._%0v{t߹-Zy9`}J8̠Ve uOƪ-kQ#܊솵o19{A~SduxQ"9|7`u;E.+'7c0mnjidyxS~/8r9 {G5OSlP{8()QYAS@Z7?Q& XvjqSXt8'WUķFQ3$j+G$ngTrr$jnný 3ε0ẋ_ܯEP`(7(qQG4RԪ:]&IH(~۔cDsx_P*_ 2{tfDWj e\wXnJB4N+%nz@YSJq+iX&u4z!ps2bcv5M4? EDow+b }g.Թ k̹b"y%Iq(K.銂vw)5f&RUC34mcHa1s!AkFS*:nc=VWem*cG.ug?+ *̢p_Q\mWDX*e(@Le\K_s'ī8DIs&2 "ޠ(U: LYbNb ackHx4]&R>I\fY5sb11D%zHRi0s(rś5XwQψ?0\- >}<(b|Pĥ #*ȣ XܸФai/QI\ߴT̖#=C&~ e%W chvJM4BTИ߻`[Lw B&+z'8?~$*vִ<O6(]x LbMcӆ0C|El>#]zI[M,-#bKL*&K8jk!pD8t>!v&n2!L-7~H;I%_tQ#0@qծE L^3 b&{eKy1(_k:]8%S$fq.ɼn-+qzKR!u AWd)lK8*,1sk:X$h sQWY1x[Tm=˫@qۂT+xu[*&\eZ4H o >ptvޣb 4(˔`Q "^x]@\0 TTUJ `bb^jMp9DV SHr3{ hekSУh` ncn% gDx:YQ*bi7 4bIxDY^eD ģQI45fQDq֏pj芬3$F1bJ8-1`'40 OmQ˙NJ 3D-Ozi` L%:EmIivGc=8RukJ ;&ATY t buRe5>mB*86(h% "ޠ-%Pݙ )t@]ܡo0|f\OS2̣|â;!F( *R|S"\Q13L1Vaes3YGޭG. _jNSQj0b?]2cc<BSiҰD\WgNăPu̲6}BGJAneV)T,KEUGT\.qVO1)*o6Ta9_1c-= ̣Fe 00KF ,G)+/Q:-+1'<DM - hYnܰ9>Ff;o?" prs_1L.',\*${XȃVMljJPfNf<`5:uvIS'GssC#YfUo̯8cA 9Vqr5ET^PpvB5>a10l9e~fܞi@Hj,kW>,}@@`6xo?d)n%64xnTc0R`,Wq KHf=^ \qC,( Ѣl;1$u1+7@̷3<< [V ^j JʁVJЈ0 u !]G$|ʣݚ%kj,yN&Jb07r! ll4e~?fVFQpʈF-3s% blYN ;c(r0MmG,@P.39%䝘:- y j_!19^焓CxQ(=!GeȢ31^>YbZ0D c"]]|3fMx?rg(}R~[YM4Jrq|Ws#ޖhP?`hu RA0xª69q㨀\./ǻ{8I[B*5YN<)T:cWǨ+4GeTG #yh[@l啻A"*Z(U%Sd[Rγ$4+P._%3$q^3!Ti^Y #'.Gd34VZthbM%}Bp CP2qL?Bf ůK1+mƋMUpww(4)qa`z;AkNu'H_/DK9%pRL)tN"g Ԡ.RjPY8OQ>ĸ`-GEds ~*KKLEMnXw5|ÉŵHwj6J+ܳPVs,L2"XɃ/Ll!Z-es>`,/S$x0>EPKA3 pc0M7@2[+8%iŠq(ePSXJ7)pij @),Ub6}DVr.&nb GDTm0#6 ] Ѧۏ"xF15w//%IwB>qԟ`nB= Z;~6X|&֩}X|+N{0C$,E5 b^n gA㦬nfV_j1 L?厡wrd n%xg#L= -T )mB 9b2)q,8jTNY3mn%Kؚ-82BYJ`T"UN)zTQ$C: S*.iM_jR!a+JBTƭ4E/6c)Z[K۔4< ik|OP+$!iYq bTs(yK1Ë*Jc0eE0;a7 YE̓#Ar"U>$tŠlC,yՇH-QI.7`>'-f !!G P#z'6q?oRN{=&:)ܵu+LXPdcjS J)YK%읒ψoqCPԫcAY6{2b,ULF9v}p$P#lk,Y%hgPCED kr(4JPT=FAq7Q!E^Ø.j9[c*(8[&Y07 ,هv=T!-GB=<Űv) .+WSBs;TFPZ DnrBW ,. Ffe\eƏ,{a Mh DؤeM./1"@ TS5G-75r 7ո"ijkQqW7oQ/lـy[̧), 0]KSɨy<ճ Dn3V8 vle w-=iE/p .aJ)h9BzCDpNs.qqD8ѢQB z;hq>7s[ϩw+D%g1(-L8L+ V= w1n;O;}"↢w )-i "\ҙJΦVZu EK.t[[6G3~ w HkTM}^oJn u EXxyW] fT'J'G|3H@O3!Ti U> oFxW2_?(F~#aָrb-zJdw7Ay2Ah8IQ?%_r }<¯J@HqQGSrW~>fd,kEG+T LTΠ5 F Y&f"ڜă'>K3a l>m' Z#ЮcX^cj}!˨{Pds^Bځ^0ۣ>H4s'(lԯ3Q*xVG.-Ʃ@:6=8p!6a=2c11.8c䑰e%keqfSA6/F ˁ /x [Ck(NLXxtsi7:i5.P)̂pDf"ngcɉR09C)eCn7o^ t90\0HL^Z|G:X#!S?+ysd `\Iv4~)W `g1;@}#O$qpN~fNn o/Z]%d8ٰ֚R{1T'Q,rb %NwX&0ZXkib;&C. w +1ZZ^k;d&: | D iV-nH m*&5 p~/Xt\hZ8|JQ *G@6MH'aăQ\A$Қ8cq2ǨbPzpb:*=A~xC;H*ܽb)PeK , 4ܺ:[6a$\2sz6m# Ou>^`xxpV28Ho,$0*BiR g9l{/7; AD% BL2n;[^U:|8SȻn@O'@N=AЏ!v4[>i^#MFܑH]Q(>b},;"CjOa~&k_X-Pcܶ.'&Z)J(!$ciq61Cz",(,*+DwʭחscN#/oTo ~9-v_pkUW29&n`bbO*bPBOnlh.NJL(l*..e U.t 0CPӝK>fHX CqnqܬK/v4: XU?nCz5cuYS U0)c2fapˆF+ /n>ŝt6a3!r1a~C6JCVZ"%#1ir0 d/ .ߜ- &5B,>aFLh|1+Ӑ׫(Ƀ;%XSbmQsbi{CW=g19PaDphdCIU:3'D*|#ΡE9jEGACeGRdP٭^0'QՔ_HJ5(+SԠ EoVDsPp[a~RWnŀ "#ؖYU&[G !pA+'T, Ga=D뇀|frinx6vI ]?8#f刊.,&MqQY+`tJ H@QE*X۽EZ%!D⃸0FD ,tʮr 78%*2%[,ϣluW]>&eӲz.dL "WQj1KV.f:揚C%`u5thb[^|5qFnD"$~22b2i P?Ol# M%1L׸ņM`4ҞcqnMGClv0] H E/QiORXOŻQU`B\gSY puu0sRTA|*+ڍU>i5sey=Axp=y) ,:RLjf9ER1Ҽ 4n:.Q < z WODۯzH'wL4Z+1>qҠlבBKءL 5߸{tf kKIVĪ @Yolü- gK@83ZEUbbaɢɐbMxh2Xr}aciru38x@f3pI L쯹b"VP6\U  3<P[{wb t"qrQԃ~%U82\*AȈ W>8s/uˎHa]ś(tVπfM#,P#YR1 bĤo\e/D!~FʋbS0ZM+20ú*;L;ilw0ٓem%zed^GS ]|;"_@/1*##6K:T΀@3:f?aK*<Ģ حwh6^{QMȰtP*XzF]grTo=IBfQX%aۡIbɳ"h"C e1{ lj ,Գ!:,3* kU 2m9"U}@H.U3l$lA`Ӗ ִ㘱p&NQ.2YwFPGL (FS >..X  勋F`1qMD+˹^¶~"{k"BKZX.+b>MVȘ[e8TdF (&Z@QBxnBNǰ>D{&EU@kKe-7Ijq/G/X8ԧTdF8euU)+1%Xi(ఫ$[K}[C v/WbR "Vz(Ϫk=x}I[d[s~DB(\%%FC;.mvC3[%^11 SZ)/4xy0ԼY.,ż)B2Ƙ>`Qpp%(}/z+َܱ ' Sdq+rDErq#GO8e2N1ɖ AY*OLhXSmtvkCH/<o4`Zf$ĢSXQQ+p67)L*YTPQ?шA&%A ً?=S\`*) 7fn U5ӋP?,1A~HN-rCLֈYfJt]bwYo<#2z;&k?Iю0XӨCĺq9Qq-yjE|3e]_z.W~:m dqtvs`!UbfpP{ ՅܷATf"+[0pyŘ{?c 81s(| lNW~00 *^' <ݳS?T8_?dnķ"F__ LpU5ሑkm0_ҭ3,7ٻ梁eN{\N|!^oQ(s5~\Ǹ30 /s$E`+D ~,jԩ8balqc DMxG-t3)L!7jf1ĭËV+{H><=Le<|jneZ<&Bt\hx]/^bmق#w2D#8;pnB9'3]U8-O#nsR_F )5Pu); y}pKtݦA .7rpX#XԚ SEؿMDvTƥ{B0k0L0jg*'z$!upP?Yܫ銯HY/!YG0Ӣr)uP#2!kqWfюV|SA~m*U@tH).=Q@ tێ}^1V0Eq5iB˭\as[#:o!bQK6Q0J0.h#`8&ebku䞦Pb?Df"Ri#+TY 5l"k@ O02K@ Yw^#pXY|HSu[yCʜBZSA`Q^IfYS.EՅE))r/>?'RE7_:7 iXvVx+gqܫHM(< Ǜ z +< $ͱoޣٝ=@jTd/&exOj`UfGP$09u΅525KEBl6FyFz0s 66zZ )Ysp([JWחɴX[L9R-]i7)8BXbqq)!+ԭ28k%l̰LN̮8rCjכJ/2řT$f8˂ql73lTYdP` <Eߘ̯ T4²YGn2pYK@^ Dijo001nXHp@{67fP=Ĩ\)!b.+c-o츨\@1YT h.q7 sxL3. ˄VN̿R N 0Dls+j/#( @!T!+lyXǛ%ingP\Z`F.n0(%j̡ OLBԎ$;E!`r$?jspiWd}fQEL15P$͚IVS\JYkcAO'F֘YoM$A5ǯ0-tn;?|GfW2ڵh&,Y7V6Y<71C@fp6Rmj^o q}Jp&:zWќkE`K@YRl " ^>%mh)p d|r'1Ac̾0%i`- 6FsYM?[`Ph1<̭ m?r[!æ!hS|8Oayj@/?wQDvrtu,(hZ 8|u2^X+;ong~P 3SL|ACJ<Ƶ4`sxǜF:oh Z]%/6`T ?YqvЁ;J@%{K*vr2Kfja?Уj#[fL0tm/pd\n;p?x $=+p@-*'PhȄ^qMfƪY8n !rʫ>qYa )WmX>ύƷbK%3E'A3b7q WqvPKԇ]E/,<>F362H&Qno VN˿0@:_ģ6jqOd#5fGwi TR{Bb hUUGIsl7 |U*X|L"BY˵`'ׂ=,y`b]_Pl$Dq2Hy#/TpbfdTpRuQ9\:0*P.֖  #KV 0qr }2_k),jՐ^O >` 1? š/T]!I$d[oi߽2*~0]2Ĩ骉U>z*ǖE`ys\;s?dLX5*&=JOȪ'03~Ȍ,fEcs?0DsyLNP 7"LP[mYaM֮!1P :e:GIG:KX:!|T^we p#j=C[Ta^2 YVץBه7TUAef_1.-bm7ܼc02@&%ɹ#bs@<`s3FxNCMa)?1a^IdjzŁq VfoMYcB0]v,@2PMcQ( t z Z@sDwgyE v\.DU K bW `ȝ&H逝/_Q5"O0?[c76 JgLa D ,#ZCI'TgͦjT+ta̱LqNy q}#m]&9&{]iDO {B/p8OĬ=DA]芢>4ddT$}0AZFR$49W(`b^K0|$^f{xnq6eRZ B-*Ǽ.^A. Ӳr=`Ü)گfqi)7ԛˤэJ'pllؼ`\^kL+n 9FwV3$6sr[2[@ *S4ٯ@(j?R̼Cait\Ne+M/jU/Xݴ ShhTrY1+=%. f^eA4#UGt;3|)3z]Bx̸DgKboV%cs՗zT2LFyzf1Z=ـsn~f#QegnQ|s Ή9q4>ᐔztf"[?pw<4s2'@" Lb"DPfOQ<}Q35'[ ]DPKir`;@H{g  j v_ 0A{7 qm`~":6P,^XuJZ f0ˁy}S~//QՋ;:U^qǵm?3gNk ih {8mhK~(ً3h&/Ŭۇ+^l^C<:}%EEj)}Tѫ%97}LX?OP5t"*5Ǹ}g -b9ҚkbefJpçܣ-bl4r`Jf2Ljj]17 OZVП\˳J#@r2A|Ul4صRUa!8麅Y H0L=B@2 ( a0w>x߸c̴b b?PTWTqR~YN|͛#JpOcfrӒ¼L89e^}&؉H sDb#̴19++N`7y }o$7EbU1e|(gU@f W~ev̭sNG0 Ձ :]7 s@nԉ[b25,3_AQ{-GZ-Tb0ڈiP39f?\0fci9cd*kO2lBauZ,}3=S'( a9倱.8" >IJM|jVb㨁LWu'FDúp #>Q(k6Mz@S8 E(tau|Ǹzl5_?t5X9%rËǓjPW"0 %#Wo=]͚گU\cq 'Zh]Q:Cæb-9]uk̢qM~"%ݢ{Vs6 M2 fXD'P_e(1}+B*rJa7n~9HØmz@q;|Cx݊$60tu0(-V"+l3j4; B" #ReU ($7uA0휏1:B+@A#aXx#I@q V.ѵJb190-X3Pp%rxT̴ 6Rֈ KVZΜˆX i񟘣쁓!U+y7VوP+c-㨤!Bݥ-D"!_zK5_ Nk/H{-v۞^bW,ʌf}Q@8Y.`+vӎ/#*3|02shPQ>DBY?|g] =P{VD&Hں֎53 FZJq2M)\p-vvp4JL\ U:&SfPgBd䅚)}]g3 |@!@ ".MM*Z As8;l}p<@C;( fR5~P14;3h>f4 `ADi&UL"Y*X{\xwIMe-f\İ;쎣3p#WZa#kqP퍒E" Jj C/c~;m  n]M{XJ*ʠtnFu *E!;Q# _ q]\ Jf,tP+m~KOw zybWgL 4V}Jb>QXlt*'A ,{8~>yL!- C}XWzs_1@uku7.~{.%Alq1#f*x+@:c4uqSwD.av'(XbQ__0O !UxbѼ" U,(P gCu'ë6]f?r!-ڶTP]n==\d_=1 ETK_qፏ#*TY1sTops]## 3Y>EYRjsc&=ifS%pNR1KS'$^I]G̜-Ԡ:P6@b>(T4šaޏ_XwܦXYkwGb?L 7|ϴh283 K`^J %xӆdik;\E`'yB K'm kC##kwCy EDQqJx2`lI z{ъh_f xTd1zz>-\5 fYAA5S+ <&GUf R7JM\(7SX&5<0k~B565YpRs`~,kw&3C'fNwI6}p#0LHb/M.A- C pf-9j?.*`sr5,]V}!oGŬ2 P@8@T77b>,F+hC B5˩5u̬]r]:Ll~n2(,u{[ g+ n.tPeT@%Y2uem fx"a,XYѢ1&U`4lNxB4{~8#qq4+Xuy3X诔;bUb TШ,f^,s]K*op lFKfW$oPd5y8ӲVR FQ[qF֥,6.߇I[L JBV(5 5 } [+3gXU%eJORǫ2s/S0!QpCa,=@Q &q:RL;C 00r~@#cԡڙc+3T*E(n*δRWO莼B`bVr2֡8&8*3K_p N(t8aĦl4m8]iD !%>UHZWEw/*҅@sd3]W9}Uv(!tv~a lZT%J @ j~=+m4fæ%sQ,Y畝6lzAJg͊pZzf=/ ]?G#F|C^NgJJfG :\YRZ]DD䨗ز.Wnx}}= jNӨْbW}H9!V-&ס{.bFYx49ǹmC'evS;蟒oX:M'"6=i ,筵c6l_{v"VKR3m#Q\7LIh3!p+J҈k@>R7b¦ZlblS8hc[+`mXIbrj ť1YLo%yv=C;1A_!~ ZY .&>ERn v;@@76\Ӽ95X.6b–'1T;۵x2yj[YHIOoz6֣tb>ߠtg,V+%u z LTqԜDziZGt.=-\O`j:ϣ9EGCp;7ol'7-ZT==Xn J DQw;iVr:k] bCNz :`7]DzS Zաm<;%&ծFN{nvD΃ ItI]1lGmmρBGs5 Ek)sF!OGOxLe- YrW}]oIY[%nM:0D TDƑT'ZF%ry_%}QrCO%t\o? 5> :R{BLF|)&+,hgfrw(T>onm~}Gۯ\J(Ǐﷷ; Y$RXLន(&NG1p<xtJXm'ap拾 Ϩtgќ[ɔ¢;X QfɤKsȢ.e^0Rhה!kP-"}?VEm M7~[{.u!TjNQCI$z M$,4)(ǵ$ՙp<-ڜ)ș)N\LHM3Ёhv넨C:E=c{~4qMKd81u؏IU29eOI:3e\8܁snnL)kb!kO3ztw\7/Vu~fe7"xʳ̢;k6o$AONDR^PP XC(s\2櫆"f)Xۀ3¬AI1~_`@={Vx^~lbx_?MY^%SZ)=J^J`&JQ6`h(,Hgك@sb&W_KMA&ɺZ#a;M )3:M1:bhTI?/6mF }r g¡y4u\Tzj91F9>=´S#NQѸ8?'.d`hW<9L6M3EV )~1A;!O5o\,%DzU[X8r?:L&٣̝MpS|KhR{kO67)?1"rR[jT Ո+S짪/jL&톳ug:Uӧ~&8WFO5ZF m_S;f9k_ς=2YB>c-iw>+l羚6gkxaZw4FM~L4(iqRV^ӧf#H .P;}«bl7v ig٘FsN2W.oooPXc1w7ۻkrN w& IW.5Go0gb)I){R4dԒ9lh%h;mVC>:+V --~ " k|B|&nVNM-N!r4e=R,d.6S`\7S.N2G|vEy1nFbFo_ͳO_S6Nk9J>f_wՖ.;@ͻx_jx|xV)<=<<6,?Vjނ65}Ԓ9keX7]\_%>2J;lepEȊJXV̚`kJ9 ^=SeV;q32K9dɑfoPIʎ~MPl8WKJG]ѿEͶ1 3b֜ uVeę c&'f˛lә*bJݹ{Oazz,֔Γ$%hhNNmL>s M)qӥeuPdB+gL99tBU;볤aIU.[#ofUEX-Vl &N|bPj{d/=Ag@%#fP,h{ %D!#aMeQՊo~,.]#kgv)w۳^էp:`xK ,:].hMv`#.<=煀*9`M PhD9R☏dSm74 ?ɟح>@aQ2%O̓0gK~a9d0bë]a?ȱ9LrM˚Sty_=Ŋ@GieE<۰(͋4)ۥ-'!}h2MĿ/V rw%̑W!׼X}p= 'nBzldaEB4FA&9m6/h,)px+m'1Pv^J-։qja. !zgUb۹-:/Zl§M}1$V?Pt?BIᶎ1JJ iByJb~z;bCik0qmXX,A!uZm(s uÏ\\gm& Ib!)Jo7gn$U};~g9c\-Vp*uc)*WR?O=.K %BlVtiNCȋFB77ྷ͟O)?vě\^t@`uQݮ%c&xp?Tԥ?=+NxyP]&y5I鮘Cц?+$sҌ[ݽgd5B#2ד'ylQ0lcyFҧATo'n0zUh1 &C-LCهl1ug -һCL(c:PYv3'gOMi=5nN5 ;f˸۵RKZ"8G|N's,lS&[޵rf1434ĺ޿ռi!TgdlR_MA93f<*3Fkrb{ƪ y~E/h"Vf]-k`)u?H70?ڕQr.PR[O*?o)@k(M㻏K?}~@? ۗ/?}DY{'6{G;73^s֏bGE` t݁X_QZHw;'sgԟʛ57CdasJRzIkҌ'Ae}k.V`mš IxRU*Sn_Hz_Dga!9а[ CZ. Xf)5G%WLjcjy{nqzҦPE똙OWU*p3[~ˌ&&y͸< !b㕟\q:+6m &݅^,_:XrZ!*=w:ت%MЃ)$&y3Bv<=DkceĮJ v(qF.$֨Uz}IX&/L?Wk5ʷa o!Fbp0jZK㫳jI,-9-'frwJ~ۢPwbڬXr"1/PJclVR* h~ 6YsKP1g*ޕf 3/s2]a ~q&?1*V(75۸bt fqlpPd;"R suҧrp;'lͦ'duy3I-qp8'xdqwl+#+ |IYqkʏ!7kg ɩmO `[~rw7@c(Қ\' i-,WPBZcdO`zC;3VN:l Hu8 od( =Esx:Nt}f{JK{1oSc7k~k̋[94z@fMiD~rۮA ?wgE ۏ_Q*诧gE>,]SYݩ @d57ې°U^ * _L!nfhgg*]` swUoJQr{EM?b"Vye^L_VFA5U,qDy$!D4 \W(ݜ3xgӌϖH 6=#m5l.3,eg@|6g9U]m7Z1h{݉!A_2Bov{ӀnL2zwY 2sNvOƋuJ΢lɔ8{;sa) }i`=3N?GwvL*a'Ee-lϦA8|W3YrHx': 1Mreˢa!h}NdVŀot(ZH-:xr$zLgj ӬRZy7-}ҐÊX8cz}Dfʻv:ߢzEœJRbY{pDX3r8#,(0 K1 _8MYXpM\^  Fņ%Tj=?HSq/ď`"";3pC=-pv>=R,DdM{FA U#CM_K ,bO+n؅%G$UP*-Aěe"'CjSYu}^q:~5$\yɂ=H2f䐚`RRwgjfDHlڔzkBzK/ϔnCRskvK.Z_| @6@{0b?MQV͉kUO=WEgYD"h 7&c$vsl+Xt2ɴzh9휑j>3.\ugf Lꥲ\,69]YvH~]xtML=]ƁAVzUOػ@ z傧×j`Qxҗ }Hn%G}ZNOv*YMIa`p>+=`:~2&qa14gs>{Cϵg2҉DU+{6ZG_>83?ܳ>Yhf'є (ѧ2 m"q1X޴|`3+Jřy#}$/xZYM9r RǠX \PSσ~s1j %^)iؼxۙ'DV[y[V f eXi ?{(`/j/A}O .g!Ч㯟͢P8@f"- >_ɅLoQ*_Oχ38%uhtf49bjP fO"k9=X-U4(Env+(3l:M)r<MfQ}GiVL{o sM'ΘEwJHԤ}`8u%keazdq3XoO\MH|vE xxoI)9R_$=7A m3~ޔzR|aޏ3#bZL+\$ f ޥ5g)B}ҜuKx/i,G/ُs=4h5oB W* hKȮ6.Wfoqȸ #Y&W=zM&MTWW*S5պ[D[]R-f~S{e xH!5w-mZlrY8eI::'X&Qv Ra0yg`蚶(ךHR+ ]O*m&[L f#QcbŴn`D>0(Y0,#,ΪoÀ,Z,p7aWBÂ_,Cn*bh{G8 [ؗ11}/o\>h`T}V;0>U'd2=Xhۙ4=#amRE;͗bY,r瞡X? }J],/iml9.HG͛Lzy1eoKٞ8R+5-HrS6Ef$[u ifP{||bfr'.7}P9Z6Iaݜݖ/%_UKU988g1J 8(+]VOP!jd`pR}_hY Q g+aL=7Y'DaĬ|4bF(hWZFctuke V/A0aPJy(g/2eP~4}UA ϿdX%b-u$D56WP!pK!.>Pu0Y TZ~F Ec[p[u@G*m!mC$+Mw{ɒ "zLirP.R\$ԥ}%!g(uWTN-r2\Tu U7.g&>NÌ)P)gއͭӦKcWɚ#inMṾ=ˬy5yɥ \XąxuM95QB'CT̽BLБlDUXyd_ڕnHګ:3YuHAbmLxO2C }~Jv7t_# $GZ_޾Sk5 xJMq/;rdYȯLQhaf7; JE b' zɼWWJ$EyS.7Vڦ]HKJpOpv"5a/ژF&]NIw)N{Nn>*cz8Yjn4mDk3өWKNd( `=9Rdrkldj͗S17w9v}MD~E!/p325,utx]D<d%WZo J̶PPn#8=PR2 D +0W%ҕUa˗ϿŏORV)%񠽻e]lgDz$qKfUA ;}vS<<-ZNݍWZYV9 M_Mˁ!N=JDlSޓu{kUsώ$(qN[UrJj|tf\ur׉3'+zi3QT:Ėr\' 4og^|_DϹqo?)@5=c7qsOպ[y~SaKl+Ja(U=ZlI*Ly0*4{1i&zou=g(f?'[M "N? 'c@fTJ!.'h:|/$)|xgu>շG+ +ىrVUy(P8H~CTQ(BYW)qS XR]0G VyK}Q 5֠Ýc:pfHJD:{^CK"HW2A`Dʅ(̤ԥ߾rJNi2`baM$TrEXg3Eg3' 'JloŌ5Nċ^R2II|r;G RoMPd<)ڠ^׮ DP_}3d#tqIfKEIm>[}! ~#dpD-m$(&&FVqݸߌ]h{v K-k4%ON̘3۟$߁gJzrl!s&g|ih_"Ll#'|&[r&s. 6U}y6ר22-Y-T6)ת$l; 0BR觹vSpFuawȋT@tJG{TH)rKKR=7UЇKL:FDd:{d+HUzh ոȁAh7y0 TPڝajIGiq&CՀDG++'`u4ވz#ʟѾ;:ċ6:jjӭ&cVzKO [/6VRK;tݓE4M >o"%1+ҷ Mo fH N7RId-=sX/4}\϶ԬPƞ?b<|qԠ^Nf0&9ы$o=]ƌ!*ZB+j!@n$}cR*D=_ɯ~@PԸO&,''D&'IYx߈;e&#+ Bȗ=\Nv-mȌzѷԷ\+r3NOK,p`|y_~ʱrݵveMJoOrv wC_*jgGˈ;XIJ5:-NXR~U[8~e٪=sč=K{9$oWym1 e xax8=S[__8L֛eK Kh'~D;"KVk 1_6N-ڜri.vUej}V,^6|VLӛUw`'7#S%%"%? a6t;ÒkJ~ޓbn?jqn7AnSuNoO$ҟ3.̧d&ڪKC"=q3lۙ7dͦe e$4zS}Ӱ7RZ yNXU%# &VjQ=mg4R{zU ]U)wC^*cm)H -@wj=mv֯L Τdsp}g9r-A(,J\Z2?>g'id3Շ(:/uA) ΰUA(,#Xi jjUQŤ8SĊW !8~}¶ջb1y5ݩ=Rl"x@H}G*ɹWb[O`A2R} vխf2%D&PM}R-7I"nC6#2ҘRzh4G=@ϷvXb:̍zi 2Xsk{v\'=6{[[jټ{⩘kq毒].Lw#Y=:阬I*>66iv9–Sa 71>EHG5[k(uF(_4tdGr"?.ƻ5XV-&Ķ g;Peka*7SgY!}YOL k(-Dk^`cE <^IP9K t/f=*oCv/DD+^P) `j9w(!"Bˠ Z#]Œ%sIK2/Diq\)?ܢZPUU]TΓ&cIy-b $v’*JUP }oկI(u)-(+)RQ)5lX>C!`A7~4Ƶ|YI?("esl\bUa}Y19]|\9NVv&>s|q SJV}y>ꋌj?ف*x@TɛfU>v<) 5$}唗se^|SđefC^E8sګٍ{8Um(N{~BP]MR2 @oSfqq/U1m?Kܸ?Xw4 EɓNW{~]9}pך^G뫒8($RY'dh9sL'[/ȍd\KSㅇx5/'5#fфˋN@͝MI١^ϯR?@ݜK5v*I .(Tr)ėyvZ4akg;,t:PJ~.e+g|}gM %FFT4vQ tMWHDHU8nJʀh ö Â#BH<7NÆ-,}V]MVuUAJ_?xVT_`G=%;:R EQSR |Vm{J+3V!'%28q]+KWȍ?nC­(+Qډ΄MO}qf ڂFE$@zff4?!ugDRI\ޤseR5͚Ui56>eݔU1AS1"ؽ ,= /\ȳlWO;kL~n !!81-,kwZڑRPWxvEKsz><3l/sUTФc,+lge63`q#kJ_(՞ʅtK_OlQK^[Ӫg~!nGثu^v3 f:*""5(R_P>`@e4e T1NK^!4 GǗPfAsBVoM=:㺴zS="L.Zw1[$ 4,nMc&mYC-giԸjt"&/j>^{ D}HEf_͋(n5 F̴%ۇ,F)(O$RFł6UE6Ȑ1I?!^ճ 4yH=w[ŽJK:ܦbT7|S{Ն7|ja\^꾢z aBw;Α%r^Czx~A  <-Wϋ>K8(F^i!"⑅AXZ*Ny{ ]4d{_7.lkFe;r2H,,S+E)e y5\]b7uʰIxK I)fhaMp].qD[z-ng*Bn ȐA/RP"MEx8RT G /v(}r&yUjӼ.Oj ko%vUV2bJRaVnj'l+{ecA<l9jGr|'K|; 3@-NODܯ =Q}xw%̠~[yMỲ! 2#x/vJүxX_Ȳ#i^~M1TYg1O>ċAE9N6.Kebև9OyP/KwQDb~AY T, a3y?!tuQV3*=|ҙ(j~ WI&hwkmSEWZbaHj$[V3,}mo4RQ j -ݞew\ DJ{Y6fbvށl&Ze_|~:o 4_ gP&V[pyϱCͦ'w㭤ޭ%qFuݱL#}(9 =c[Xi(IE_f/REt&AMFQ3\sȻwT˶Vj IJEZV0N5RiHkM 9 yx}9PVK vh6r/{10_1+DŻΉ8+ h.å6('j1KBUa?!S 5'3H85S)8 ,uq4K839e+B!?WGNh1a9&a{2NH}/,t_iZ_c_=>$'7S~|t_ $uhbCeY*IoM6"f]rknqb4W~`>TOA)uO+_ԝh_gd2P뚫k XGmmHr `dXR1@bJ!k|f]_p4澿RgzZy3y}N&kͼy DR=yl{{ ~TvPƪ:A |g{GlH䕋M:/^JԏUPHAZD<)WH|b4X}=-1\/I%3;nvvooAUJ_g'c"Q첦oBdߒfz.H8"}pܛ j(`~"5EMŽ9Kx|T|`w=Їwprx|E?O(LR«\.AⰊ*J_/=fS'&Kz }N,6۪JKp$R;@.[RMQ)\k%_AĘAR9U $څ3hYo,kk{a p^R:@x1y=/כwpJ_o^NotgDk:$ǵ*K0 #'%u*(%t(hk+·(|e(1Ki Ͻͭ~)v^ýZؐ#m2$ NJ%h1.'h&K綴ioM5O*ifm7PdcYǿkM=TTLar!qlM M/L{ލg- JQ4v&\ttQKyyޞپ׀ +l`,( / HezlH7كÆI71kQ0Y1bV=2[:{I9# qlƠzLY`5Oi%ޞ];Uh+e89Xdh+,mnQF{ӻO4h" ?E}5/6W+Cdѕ^6uF)H4_u7&YRd|e;@䦹YBz|ܛ5h/+*QޛOl35Mvkknso7rZg}!I/lLIyq:)߼S=90y9.iTTw*zdxüO4B$X 3Y_lC~ |/_t04"(%8|+HƓxԏ;@YD_,;^w~/TP߿`K=ٺp8]2tq_)䋺).b&$[)| :$Tg~v/fƾCdRUtoH)Cz=]^|]AF_Rm.cc5^kG lʰSvuFvb7iF5\;z^Y/=&hގ4F>q0cq7sۧr_]zVA6v#\"Uǣ7)N]o͔6c;eOKe7٭g2Eϴ!Lvˁ"GZl-@aIؗzz("gikjX !h&U#y];D]-- 7Xqy1g)ퟧ˘id7c72?hk Ka/RiX1(|?ެYJ%y[- &qأiI6Ҙd-^ S#3LfnnAb_,6Tݺ/!ЉD St W^6#ST/ EhUUQrp-T2scY.Ī{({QZRm]NsP9ΐsZJH%EV<#Y9EE5÷ޘ䵦jZ~d5*ZK+N5 bб0M 02ʽ5!~{Gx3B"%*C2>S_jϼ؛L2&o呤H*J~C4*9xHe ǧ7!x`<6MwzO6t)o=Q,{ePhx 9 PJ DSYg<G.K'"b<A~L{P|>:؝o| }nz7ʥ{kw^{Õ3חWn"rnyI \jxqx (AЊ`o2ttP>MGeLide K/ߡ&͏%(6x|YE?|m 5BbQ8%{`׉Y̷_3*YSУMVO/rfj༠$J"&(4I[!6]Jj(*DRB<cY{P@@k@}"eύ#|XzHxycp'=^;#9IoCNHEmVJl';!z;ғQWőqr|݇q[??^f)ҙ''{VѱS\ ^S6t'N;>H>5vzFJIWi< xMDWM )$](] ȷ&! i2aE+W,˺,\1"@ǣb<*GDž(PT@Ixg_IkO#(D"(a-aR*\]1L8iJ2Lk%i( e?ɲb;n]wN/vt կnyK\zwFEZa/M9ػiKz-P:et,dV]O F L—4c7oE6uuOq./H"3~t){_OV8_݀9l' 9ٸDh C)!N! 6pY'ֱbIߚH&M"fb!|`v[ ]f^eB470I!ZTkil)/*[qJt;I-XRJ7&[freT@FVn+\<]WK`sֵ^/Y;ZWz˃\;_\{/_O];Z^]E:.n墀 k>z߯2:JjᙞIu*/Ttb:q#Dgc?KBί= p32Ge"xgw$?6ƃC3Q#HQBu%n1^<9"@) ܟ^bb7[Z"'d 鵼HyֶG{37l"xz0hCbgi5M+!MR*4px*Ir>"qP z M Sl؁ⱉ6Z.b7GP^ ""NnrXs}A`lX-q:y֭*|! geUxyeQ֮pؕET&*RեK&eSqIǪN6߮(nǕ# DCo>xo||/_}&Dڛ_-TuR`P+8Ʃp,E-e/e!sq*u]/9To)bR2po3- l;Jec(ֱ'n˲Ti*30s ؟$`!Bu{ $| ^5 y-oeɨsu2faW!:B(*nG,*m{=,m ̳PuKgF|@fF\D c}fClX(./X[אS0Άեil66͆\ IԐ{;ON3dܫLfR @e v#bܳVBؘqޏUn!sI*[,Mt}ѓS 0`17HNQ1 cSR)0 l}Жahu _ke{J 6s͉&7ZFIq {OstnSL]mdVVVE]mw8A+BG!kEy"m% ┴ڒ:Mup9ݿՃ;`0wF~g=q]9)duaxO> /_ك$0:Ádxoy :af2EZ,xvS1dHFe}NEGr#봅JdDI$TygV\ާNĊD=ٱȫ3 c!%2dvS gL~"YZ@%Aq%T@a'D^QzV Wrc>klOPVBAQ޺ɍ$R,ֳҥ$&v EuUBxLu.:zmXDP}|ZhC)d=~ ̛93avi}NXt|]mw.aL$@ӷy,  XQJuAaF)/1pǭB0Lb#SPy@^+:1dge'D]p؃EDGV? Q'S4O GY=æ. ᨼ:zջGC9)&m~rT'Gx[sn{+;hhu<%eI ;Nj,{pw??Ͽ?UWI'-{q Ҭܸ(]Yξv4\ '/{HI:;?ٗ[=q%Jp~H3Q듲w>Ĉ֊A#!SXkEn <6M\M?rȊӴ̒TL-Tq7vp}Sc(eȉO:j gsP;icgie%te%*+ECCW (+2Fƙ5x"8*>rxW^n9$8QJtV{R!xemޣk= .)v-gf]^OEN<0/=kOQno!%ľjwp8㙴sU8%FTPDuN@P%?(Q!Z Zj|< [wgkACݰ#XBP%e-#L^+30ڒ= u?Lu_p!  +_J8 %-x%N7;54KVjWR9AC <3a3UX(+\z^4S HUTNx]c7;wS0Q_"R.4fu/; ' S2[.r?o_}.>wn޿w$uAgaBi.uV;HMVQ/ a:mH#10JG^<%a'/V1 ^t Gc4_ G i+ gunJrx~6y\֕C)fFȑwB7&GUʡJR$ˮn  %U8$Αl}Z "IuȢrۃElHvF%FFU EC*gMPTJW)'OMPW|{Y^I1I]v-ۧC(j׋zcXG$KGXj}E5K:Lv,by^5ߪ=q?S .+c%^Y'nCq~8$4<Ȉl=!( |A%YKTLmZqjd/_.J,AhE#1qe}܏/?7*?[qzJ.JŐS;s,'irR5טߘhdF#'x5zto#r֨[^[>{vY^d+rga! \-&qmcGQ|jDҠJ4zqqQ9ia壆c@keYQ!̝򠩅_@CYbhDvV"ȘY8 .qY\o!6KB&䈡EMN_b=Њ-Hd|VtD$:KWeN2\ v-(Nc瑊xZq?I؋XPU3FӊAip.K`gb ㈨8:Zíw3j#rK +}ShksNZY]EeS0HNGy1p~^=`dJ\3fzJFԻ=e2|I%ژ r2%qP:A6jg?..4+1X͔I\]B5q=X^^[k;$IZV5a'A;dy![^ֺ=q} ^l7ɺӃOO/mn_K?sW= n8דKFbVZؖB_Gn$-=p&+e~?4b-=_$FBFFfƌ?⌺^8ɩ7$G[I6$2Cַcɰ"1xr xHÙ( F YJ"Aqھ*$$!vJ †I"IS$nfՓ`u,ݹA1lbb%EzEӴ E#w%@$#"IePHMQ))TӊVpb"Qh &{@=? T1=L0R@&Sj8;pv{ij{?/(e}3>ϟ/=1peʴ.:qvxlQǍy<_-%+W=^|Տ~u8J{d?f2 eEi'}^2χzvoxؔRfˠ7DKd$l8a%VP''nveۂePpNȆ[k%iXD"օ%6X$n@o7E ,u̼|4 NrBagcFSe~n 3 , A_YE1L2xJ66Nbt0b'<CߎZ{C Kxzn逡* MP66B3N[`cJъˍ4meŗ}:}DfIaJĤc:TN>2WsU%(QܩuA* 6`wL}6X>#˺έ9ߝ[Νy'}N=:ãq]p?3مd-dBj (s\ٕ|?{W⋿z뭗/_zckot0IʺWsYӼg# ,ǘM#Na*R((#)Cve(=bM7)˹83D/!nY4#„O@xow$Tv2]CrR۞93*Ԛ!'z2P&NOm}6wċ.z%Qͤ~xt֞&% fi(ф>99\n02;u I`dDrH=C?TXjǒ~V4q%byafr sPrܭ5٤{M(B"7.K+LaZ%EIܰp瀒 .QBQV1-cÄBQ)c7gRPe.qm Fu!m:鱄G-sJ0Ē!=(veC|<۩wlܾssW}`{sѷ ~lV'bYι_w\g,wWab:~W.^k_߽_ܽyTIrPεتQ U"!N@Z:Ⱦ9mK|0ܙuem XGUܠQʏįm/.-& NL [} [C6wiq'`0qjK/gXnYkz cq~1iy>  ݾ}Adz+ YIhi > >z ('Ka$"Nx.~$l_JM>dCۇM(rB3T )7x*D6c[*-(*hY:*N,_q SH8b f25 %4B8j+aR2C ɀ PDD(>.w8EE؂ri +Où%OC{I,6/mӖ l`%j%$wE9*Zql#j5QV[xfr#/ }fIs8AVPOC4:s6-e2'݃y~ [SQ!&I[,bEM &F*uYc$U*nܣ#~_ݿŷ^,gN=<<[;o}K߸K\{o^+[nsUg~~x'å:L5LT'e=.7r%RzT5{x/_?;^y^z ue|ˑ:IͷKH>jY@EiuɅ|!6ﲔZ%.DC^<^¶KNK`&!qJ8f RYWdžE.nP zNf$H,oe2^U^1sUP/qF86ȊlB`jϺ1q$lY4:J'nN"uϵoXo XYoNFR OXB2V#w^LI=U G%ʶ꠬kXmތ#0 °-!Q ;7a+,( rXnN_?1O2*B`'MSѐЃ86f{@عR!=ɑKnVnDfQ[2H2BCLc%#) qt>J<qUNs|pш'J(qCeUC(u !P)QXoM\nL %?aa[AIzjE]KwM`VVw]~ǯ_[;so̟ptM]1H *$GINn{Q׵ĽL<!"a*£oll˦沌iH|P,!LRy'D=ݏ i$m-QmT/mTC,8?Ik{/]qf3?7ſ//Ǐv^t_[;7'G+k\^y[ꕲ^_nQeQ]YRPG/0v]7kÛ]yC7q7,&-eFNWeAePƸfcyQNTqD^xPC(x"g$ &3ZъV GS9(apxXc.~"ITA$b3BTS|#޸0UCȣ><2bX0[ANQIZ8D/ B2Ab<0ȏGdX+Z0SEaJv :$ifeI.}g%&1}h'm׷ wngҞ腻1=FQZ%#7?խ`D{2G"?9!B!bPT0Ő ˴;y+Z&O)&S].b;=Џ>vaп_%Q48mGۇN k2NSO,:?x:εχ/ݲkag<ڝ/>>oћ/o_otڕ4wyᅫ];P*Kj4od uߟ_[#}(4ޡ(;iZY#Gŭg(Iv(q'v˗ v,+7fg.6 -PFLzuM_sMҼ?W%}=}.: Z9Y &$J 3-. dLǘ7fz:(0C:Aa ʣ=J~DSgE[zϱ"^lP\8t {ݼV]x0RPH|Y@3WN x[yYI>C9#y۳n2zFedN_E̱{l VLRz$|tL^OZ/ZkSnt<1;fa)+sc_.zI—LN?҂#WYsr:o}(H?m1k;un^W uyx)ҥ/O/ztv eVpk($UҮ~\"yWaWtĩD+V;2[X ?Mz5K\9U[KxƓCltj|k6>_\bqtq^ophscgkxYGׯ9?aŷ;>֭'g<˟ھ~59^,¾xryex)W<<>MٿȰ8\e\^:~6Jxw?ѵO]x$yYYYڰcAUeh~S@ӲOÀ|-^e; Ss_2'UV%hKʧp#X⮦-sz[3k} f̕t(5'J`jB,Ir( |ˌ훔 l-gcoL⧓1oyl˺S.vkMۗ>+d4 IJ.al ~+*3*PjV BR똱6tF$4OρQ-q1QEY8*Vu%? SݦAu_-/}pd{_Oի~uϮzNwO_y{s#Ps?Åյs?ijO<_3OΔuoT$qwur_\//o?[7'U \dIM\UԮHVac^.\cH !0:E{ţt,+ʶ<0u a| fqѮR<:Ԉ=~",fvyL {]*C](ͨZ}IBۂޏHL75uz ( 8u(²`W+"(vmP¡v Q3rB hiʚ˩Fhi؈ZhXƄxu;GyzkffBWN|L4[w e lݙµBXl$5 @ EǴCz AP[D.NPȚBE us+"@Q&iMyҒMP(lų`ؿby&!>=CDui4QhSRGu ;ъ%&lvY4㐌(cVcF k\J]Yx>8+z\ͦHY Ckc=0zCxhQب`++`=3{+ʤr2ͯS>ݭڥ_{b`q>;wϮ^8|ܟ|ѽ{wGpSIU?x>;>``\s9եoVũ۷kw._y恫9'O}_=Ŀ8sO:=MNfX&y4Ta^ tu8*%y탷_߽чwl< JV9n F6a{R5,x G =uIe^zBѓx6PFC#xikR S:,E(ieRу6e+qh)!o![QNx!y(lD !niL$&D&ś.'Ա0RX2|_gbH2F@2LhɀFS!EIEOmw#&{"> 9-voG찮ViaOՁlU.-x{x! fn+7T8&"7L0Za#Q&bbC"tVdQJE`8C 3%"/5tqi]ZGɏq;CG-PfV2*~fiM2UQi+a?* OSJV[_qvEyzmq` 8?$B 2J-ȪBQ:RŎ12YAv{1eYtHXЈiL^dhكGcFT>;5h<_sCyWe]Lɸ:tIva<.ZD)dy LU/rݫyo?޾SPWU?I9sz a[<:>|y;\'n'un~4nsg_7~ܫ/K[jay[g|gן?3GrTL\tSxPg ttO?˯w/oq:UwP.UcjClGZVI {$܉BWeG:,sGim YiGt9eI%LΑuBޣN1Z|Ylpg'*?*k( 4|9J)"cf#>J*1STG6P ",iaPdPR"Ci&Z6S˿fuwrc׿Π !CʙAHPŭ3`#*ńT{pu]3"1pe]ވvh{ZvX`V(!3yܐ6w+"M^BGf2h]q˄<%lp12gVVװ2]ZF2 X9hhcHy^{)" M'E^#+pE.Ƨזnlm>h1O/] O?֭W㍫>}Wk/>xW7xe'goO'pҙLeF8OƋJӇۯ>ʿտ~㗾{{p~N%$5/:oi:;WZi11cM,.-[Q~4=Vqǹg, oŃY䣑:&@K Ma u>ۍ?m5YJ%E3k0BrWeԺ*+%ڔ3IX *o=Lu?޸ȧKITٴ%;PpHjBcR67O1ءbG4ؕgR}OŮZhMqC&f!`Nh!YrT^6pCG1^ix]Sdw*%B,p3XL!Jh9]( sS!HS 7? +Im8"=(UT,niI|-1C,y[WZ&lyՖ =z- PQ|WPN@ b g$[?ž돲[qSBiG!q2og+K>-V.#߲䣚U|Q^#ϢOh2wS*qf О)`A(zKc1G(uC;JZ3E^y\qn-i>++sn 3k+)&LJFJ]jia£Nk7]0=gmeau gO=G?S翸zsg'>v;_nݟ?}?ų<::zp>Wl=Hޅ~oəszVd&ER¥ޜBzbVoݸrw_KW{"-?Ҵt{j4%RƬ1hǴD)ʤh ꦢFͩMK5ỈrRV,E%)%)"Kf0[89t5Q($\t[IoD`QGJ!g?\j܅Ҵ)Hu8ְ3 =ҪJE ZI1GʽAPTZ:tksG jY&ӥy ˈ:)*hQ:JRwy\D,N8#aC,j(3xyMd28Y[cr&Ȭ5CVn`3وs@-%O͹ÙQ!֮doib3-st: qtk@h`[g(!:Y\uoub -$!+iMYb唒~|AGv7mp<#&~5Ò #PzN/tU:#E{Nڌ 1JVڿ,k"ȷ֨b%!z}̚VS?uamɠ2nўjwSlau6N%[DP=ăSvz{d]k+Z3ޠ* j*4.ruV<<Xns3Apw`t+z(3Oy/ڼѥAOg,_=w~8<쳗>y7饵3g6.vǟ~>:x񇠚>|kkoܾu~q<~kqahgmqgs11u 2sX=`qUhw/7n_>wO| O..UwzbUic gMS B;iNU]OuTየ].Sf )}XE-$PkQeEf+8c`< crr]JN3h{ب=hʓ-*s_̄Ⱥ$'@)H(S~ҙ3dF3*W%F E燄VS/[ܴ@+/fԝnġ.HKvg=P,/UGjS_ ]Gg !RCuG<6{ W^qTP_kD/Ŷ?jO! . 9"KVt@:*7UJ)5/g(YcK05mCSaЊ9rv'-eozxk&Z&k2Y*,1|i"jM5J)ll 9-0 +!2I6>#vu!v{"8|<ÑC;nnNn+[GJ6%8ybgn6zZ*nlΰga3 WfUW732#Cesh\}>:08p8bo}k97;x !*21L N #:@}/IƄ$_\ߘk S~㥫 +k/[^}VoscPeǻǧ?/?_TGTZf~Oo'Yrxs=]O_lAcdt,]xk)&ZD'}~iv&h]%积=?ކ5B7 jIdLbvP Pi.Q,SZoD6u%61+ܟ6EX\=b.b$ 1ϑDZ_F׃C$ #z r R+u:_aŭuH&7Z;-3;a8u__Mu#q WP*Jzl,uǍGtX!G7VuN;'{3nאָ:;ߏe+"J RV3{v~hol=~τvп/_/5GFaϞzzcrj~OkG`oY o\_i'j*&=n LN  -om9>iE\JAQI7IfƤKIhsL,,݋6o+HWF灊Q]ް}[>(qD ޫҔ0l׹dbTzU;lT%x˷sT<6U\/_3^]ʳN{TXQ "R^4Z>c I~Iz4*ft,t3 Xv;\ *#BuZ~ZwbcP`58` ׮HQvW߼x2n-:><0txGí#IOn]?{SHj}fwG==16ҨMloCcTI >wf41$R|szdⳓ僉3ssWG'CA m21JSȉ E5bd28X&^4bB[ _z~ TւV v~(Rfzqk.BQ>>1N,0FQ @D˾B;U] !Kj( W %Eøm.]?Ԏਲ)OjIxIqOqaU,[Ô4N?g0ӹce%^3.qvCXԎьc MZ5g՛BXc|ߧ#f/պ7l+}>ͤ_ڔ1.$uUߩ8 0J,#;cVpTo` jA>T7\%<aʌ1-ڻ~WI)M%AM4;j}%EVbQh/S]HLjfzT9v"ao @B ֗Bvi9PBf|C*WFjw[D UW ܊HU6QڣK܅%\] ìYa%6m  P ou輓8cתBN0_s Ѳ9ﺇi~q[i7c+R^sxl+Fkex|Jqo1<<46뵗>|ū;7 ppt54=Мff͋Gǻ+wo} tOݯ~(NjSgOW){r2Ab٠7Ud/aft48%C ܂s 2}2 )<3`ΓC[z;k*K)\t&eF`}9Ypb3JQW0 ~ _|"B*0xnGB;ج9tЕ.&n-K'Mnw-l]&qB=qba OY,V!((Dk}JH(oG]aJEͯgQ8be~vSF5> g;ոӤz nw%bey7_؏srdManH켎%x^ qkmkEht7cgV9 /Yq}3ukl-Şpo 1_Zk3CVBžgQ Jkb1"#tc`6<cd!6#alnڱDylѬ73 %<%Ps7XƫL ͱM{W|SmT<)ei2gbCS+4r~* Œh _qB=6(,68wMAYGM%Ն31`=>>!hܺugvz!ەZT::|u`hϾHU맏B骳av"$rð5:=_i@ׯ} KWLJFΎ_>vsĔIR`*~ݺyǐTcE`ǻ'냭ɉёٱcc8<Fϸҍj&x` & :.O_|};3ãzPpI`pNۈp=\kzJbgSc1(85%2q{0)(W$Ohc oueؕp9).h*^u1*EȭSۜeraOGsQLDVCaX3/8I"Boa4v:h~)%o֑ %r(]B 3?2!PLwOeu 1Xq I^VL/jS/ '4p7(u'3(kL,BN C[qy+cc1Qui*aP:aD5W XoA)%j Qks~A/.y;ݒa.Y5ffeW\P xO.A_d4W)_^9L_RH/hu#]!? ڜިS%3h k}{~rcVE8m ΘrC!/"nvZӏ<40H-Q<!sXۊNZ6jJ S.6 uXdV ǰ1Yn7/8.{Ԣ卨 DO[v/gwy잤%saM/[G蹳pD+LGMJiU"#M 6+!CT09&VE#S >7{rv2?֛1ekkScǮ3Zڄ1^&gGh>$)V1:i&=cU SbcʙIiJn]i7'#XkJˆN$ MV׶K [ۛU3sKSWFG R1ђYH +&쌤*F5 WJ%~뒨hPh; #B)>̀v!NmdBiH̆Խvx8pxHv JFIdJ%55xlfHߏ^⦡o:#@aNkRDQM\suw)<~ԻPs~PNUR8>p0:ÜJ< )(aπ=*󉔲R k+9CaAr¸mdnCz] 8Ok2^/}-w>1i];y -Hw66>tZ?06v޹hHPPphF9z ETuJ %yȥ4sjVų.*rn_=",9j*R@^(4m1ė1^]=4->H]H&QuO ;?]ܗ*%I #tZס9#|{{m2:;J@ti:0<28?89!w_'(λqw Md|fٳ_?~rr?yDꁡQbΖӧk> EMP09vJ חi}xŚ؟y2%YW#wMeQUFG FRաw[U5U=hԇ:Q:7>:135;;13:Вia#bDrjPfian7-o(ٝ=0hsϫ<鷿M9^49O7f:!g[=q~x,mQۀ%Šbt9;gsg v MsIZڈsRk0~=x7cY1 }  )\|_ϯ=^d}K)<֢Iwݥ+PٳЃSMŭ{w%\3s^v]  J>_ˡA!߳h5RZ 5]ϓ+yylq19!aJjʤuEڍbѣVyJyUr1[E3q˃?`}TPhΩ&iÆicȍHTN^2<W ݔHhV2rd., ;v|u&2*VČ|VёkWy7 *o_OLN_xʕ;ֳg^~ < ޺zsr~xku% ? 1pml`h~rzɫ_;/ɍ{FD[Q' Eڕ+_71jl>2\W$JT%;1=pOwe H4zppxd+JZRu(aa.&IH!C%(d#C Vjkp}c3SSZ-`TqN(#D,phr4ssW,pA(:Eg"j3BOI/Ĝ Er'ŽMzw~h~wqx"󽪎#1_?sb  0KT sS8~RɊ.TF*{6@R>@ڻS#ΑH&$^K~%Kio#}67IiiD9ɒvpYkhƁAz\Jyn<4xux!\2臷  1(f[R۶Biֿ:Ab(cF&J)ǧTAOn3C[A n5p#ʛynDuqe~WΜ %8v8t,]Yx?Fީtߍm6Oa"B[ŭo+:H2*;*@R_a 5O9? _gqAt|c]FW 8^[񒯸V.'&'ay< LzAY:L]n$Q**cn>ٜt:X эУ`|kקr-(M IJH}~:(INdžۇPithHcCH &DHH#Z#%P/1? 0GΑK)/h B(4Hm.,ƉRR).1.xd uhk# АF"d >KUmEg!,Ek˹aΜskP4aa`8Kfi!msaf}:+T땡g$6څ-*N%}ni_UvOx)Pb+ׇGhE*~ri_??Kb{|"gGw} P=nvݕHTlc㍡?ssõyFR/?ݸ>54yؑ$sQz{p{ʫ$&Zkgf&o5:xB3zz GSW^<ۅ&DKwv676ǦWVVvk6 U#lWݚ5weq}k_}OhOP 5b]ѰrKH%:M44uaNm$3'ՇtȰ'Q?R,kX~r/oStcf8i8czwW;s{="kWhBk"0*CqE)3{D$}={͗uS=29Eɾrqy/h 2 % )̮)GKgk$y #@ t&w?nB,B1p"+WH/PFL$/yfY3]p-?Y j 46(P~}8?[OiOBb> :|N+~(%q}RJbX]m ]QW=<=0/y/,겛-|G@3-9?bdgy+}J4:}VuMϯ9_3흜 iQTIԏ!ˀʀWfD(b-.< ҃C;ᛝ#9t4(uKeɯ~ b_:t0#!peОyny5 l^03BߠD~\9^0b/Ee|k槠K Tm7ΗxH*’uXOV<} t j67֓I2vzbX5 j ͑7+Ͼ]iwǟ_xOꛇl?AoOܽsgjqՕO[ӧG46+Q9:6x]_\]_}@}'"0/_?XXAy7J C?GϿhk88V8puoZuJzʦ;dgs N\]iώ:Tώ]zmphbbڵ+"lw?ūsKcC3s^ XM2)&iRa܆I)M倚.WiӲ@YEa' ?j*dވc?CuW銊.yO\~../,$OsR.O^\ E^)@ *)*]2}.T9u3 e#y +r:|)C)T_ԾM4R! nx꺊UZeEX5*WMn۝.&wJS&\P (T.0<| 0y.x)yIBah1<%5\_Ka\PRű\Q ͤ6]^ȗֺpZijg9).'{[[[xX/`7QT! T]T!hhHM 2+1ƭUל5յ-pcoB7) jV`Jk|AS*WR}Lr'q>r;BRfAqr Є;!8Fz^rB*Np/r9:ݷJ̘Eץ}Q*)Z:GR%d8W!>ȓ_ˁ%^kE;P WCSOe=m OƝϟl^чY7_7gsɓGov?;ᄈ/߼/?244?;2Kl6'fF ӳyGxG!ݳZ̎_2!ku?x WOXIZ#sWícȘ<ߑ2G/,,,O^<{f}#:{a::8;9=3Xaç7[sזoO_ê#JlJqk1^ ahFOB*'a\SJ{n쬭>h0* WNڝYJhٚh ѶT6&r{.Viavsf[>keJSfePg_|r!/v4Lier> rԙ4Y :6<ڜ ϑÀRwx2_ ]?Yr0mkH$Bچl 9ֶO7g PcЛ3TZL+/D/ڴVZsf }r`ct+{\2_OjPEU@ۦ &94TPHNqkpSQZ2>lJw%kEc:Bln3c\ qӯE,D{{q$>gu6}0ЖVTVK2gwaj Ãmb[M賚.ѪVN;D-Kƺ›Ս_?T{FV#` OON^~o:onnh# 2)bva =PέzSP՛ߝyW>XەQZ jDuggo\zovʝ9S8zS a> 2RҷT/w4vαƮ>Yg5] F͒Rqk YW+ӫJh\{mFvv7Pg7q:섚6}W;־L8l:Jzdr7B*16'l;iRreƉ(w 3/0˛)ɗeMjk?oD+c1F ߬FJt@s<=4s.hhzJb$CcC;bE6orF[!uEWB8Yhk--.hYj[fܝ< B탅hOFx,](w!hD+.Tv\paH8A]> ꬃk@ aTA8QvDL >aH+RGG'E|Wh8!hpt0L^؄aHީ.EVwЋR'<ʒ})AzsL6ߖP$GIW EY[[ݾ962{cVEF15*:LR7E($F0>(YܚQ?\` GY XUimf KaOԳ 4>>27_͠|<E4W( m{^/3i0#8c J*kq s~ {I~+|Ѡ%a42^@C~PD_+ҹ8]:-CeV4~|d|a6^Lbt6hR=:-ٯb(EG݃}؏-%5NJɒV# Z#Z BPՉԄ{6Juqy<<(e/ TN]ةs@kWBWbXt4ip?BseϩtƤ،ikk~8l@;'+·x&a9E6ٲK-.|>UW3l ݪftti"TDUk!Tb$Mb=sp0c`8==^+ PUE4`J~sS0#V;{|bhy0o\zg}ַgՊ&46pU*&ڳǏnܺ0;bpBCCӭ቉?tg}ow#T5Pb}֏(5&hw#jMF 4׏>>{OǙ!Ov\4UGUD}h:8y݃[={kKSjM0aIknK1%ъjf]p:]%ʬS%VuI{ c%Qgj_\5@ɦ@vr;s_zf-vFvyƋFB.K9z}"]Q.[keS.,#". r16~.o\9Q̖s h+9+"[cfK+6[]^9=:zG$]*d &t(W+sp*Auhic󹃅=_AqGDZ7!ceޗ:7.5T)BB_|Gw!h>ޗ~?+1QW+p_L00K$}3?w<77X.q܁OS Qdt;k ;~h`ťy yx@5 Kd3"ZGR=[JE4Ahi{eyǏ/..ݼ~^kvXK)bRNx%}W_  7L 0+!ekT9626;:0<6VE}֑$_?|%(exТQq^:e5utqMq^m޼Rn-.&`s˰܁R3N\s7ˋz-HW^^-?5ݔR4qehhq<;(kI_J8yBVyf^eR[?ϋ8k٠[u. :D X;vE4тK+7`ު#CCpN7TV3wNv ;Wȿ&R5᳼[cj,>"s b9w.Q *@ sY~n~QnJ.y}(O?]ļ| |si;LJ'>oDdO߱@ [ed*m.Zw!))]|jLN+B:~i*4MP%-p>cQϮøn9̠<6NiؠawJ JL^~3L'" /]Gj](ɉ?󐐣!k+a(Vz@S߄HO(wviΊݵ yV2.^U :T1qGTzNAbHD }2 S7!C!n ` e4cRRŌ8di4"/ 4M\\%R`g9^f[. wcZm*bOi|@jR8;39Jnlo!r c-e\&&& ZZsKb0A`v)0~V0A,y 3l:qRaX$Nti,%[ (Vd%7ȕ%?1ɛ ۚYY/LNύ)y(U2p{vr|g_~샯?{UO~?{NO>xq?>yM|߫xkxf`brpVpohKywD՗íg_~xƭFuptRD7Fle}ׯ^6 San!RtO>(api1hDq81$$&*䨪aWCjŃ 'X6<9;9C]JtWJ84Y}~`x1O8IJcZDps FPӁ-ap\qʩүVs ^P>sm hSeGiq=f_^W=c0ش"u{B7͜ۦ ! PMH7szvo3N +@ BLؠ=Laa| *Z>eByZ7f*! :*/N.lӾ%YBfNodQNpWIJ;c Ұ!PaT(ej Չd(V?qD+B75Ɣ H<(?%eֈ!cp1؟r2G8^8>NL)LKmһޝOnT]-rlL MMO^}`%q$Q'g)wP/~kxlrʍ;@Qwڎ͝|ѿW곏?B[+;[\̓;ǭY.lp90^ZD>}W>xFam飧+ϗW^`plbrb &oV=͂}r-Bӧ߬m ez@s1 wcu":8{902QmF oxfj"}zrTyNOwTtY:19;UQ 4nrq& FP\oX6A5D$v|jQu !=BX͝$.'~V9, NP!gU)Kx _QwD_v`BiN 2U=/q)q)ExsH W#~Ȍ^]LvX+ƒOެ.oϕV,(\~-(N O;p"xȒ#_{cN! 3]q(ۆMv?i:JxڐTkFVN<`*1 eQhVvvG_n8`NLрVmhp`٘m|Yŋ?_ozzqEWs;ox鋉ə/~{_ً#MzeÏtlmyslrq`$P1Tߏ雰:988;17SVwGD2Ky<6:y|y/WdK#Ƙ'_ns>Ҩ`u$qe˯ݘzRz|z0Vho_*ucv`5g$4'&Z7:l*L"+z|yfn`eL4"ITSY`( +ͥQt9&gy( -Qb9@2q@_8?ЮLto};hs R0ceڹ y&cˆ^e.%!A1K$:;ϸ rat:ϗQa }I?esMpw/*=661;3 ep-׺ںkqfy:2v$!, IʾdW*<w.Us%),_!gyB}R/:}B_Bg\ygSz͆q,Z]]=;mÓ c[DGFaaЍvZOHkE,Br~d}*}epzg&udz:?B RMrh(# еJ%"bC@~u/3` RnGСeDtjp<(pG62tC gW ) {1ݺ=>M(LJ0p0}~a}y{~a IEϷ RCmn8AB)r+B٘WytuVωo90 @(g#IǜBQ]Ou@ѻm4[ß?x~Dɇ?}i'ZcvR*e~|k?{ܯ_v&&kX%??{;{td$:4lwIwO9zzf|x׮-.omBG0/={٬+oDmdzzvQք^yνoWzyMHj ^_X&~!߾>0lx鱒R#Ux'''Y?4  )c-3"0"Hi) YLNM tP)= yLjity8" )/r,Շ؛..eTTFaKä <̨mmqNPF6P1J1T7ſVyz P3`"a1[׎bM)*s #q$qi)/tKJ1xx`8C)Q*IPs5= i LJb݊c{$`6wjcيk8$ 9[O T`SgFbL ZB$_JKKxrV +6adT~?:,_s]atܓ軚pgp g[:?Ƥ8HC G˶U|oVDc I,(q+><>9=9닋 3a[}qwWwTՅwPc%:'TP4e폪ṩH@pOϿdA╅ɩ>S={5bff7|lex|(LP|kO?n-Ge2әqjwgxhǏ e/HUEg{ۛ;j;>aM&$}T_φov::LڭiPmɉfgF-蔎r3lyBK&/QRWT7kԳ6|qP.i /%]f\]b#tQjfW|0P׆|Paf`F#%`Os}wA&mM{ѮxR^s I:wTIB8g8+'N͔O }ɬO،{h7jI>QB!`8i3B`=;ނ=ҍrK?N.(3@~BYLe@m@G! Sk1;]# 7h# V%ahg9h XEB#<ؔ!訇gg?͘C+l;N@bB6;?~ ,hfd`dzr4c%KT@Sr諯&GٙYDxeqaokoz3 CCrj-Ss7ZaqͶXa^i Itؕ{u(Yk vdžGB ^Ե;wZ#=m#u(96u$ƨRshA]"0$olnSśg_.?M999z򛙉7nKك&TV7f\K~jկ^/L9g[J2i_;Dpphpqf܍ɑF0)* A)eawQv`ٝ](U5ÞL1Fmʩp>:Uy[$ORB>JB+=q TtfmǼ^[U;ռhhX^9GwʴP?ΰ.!w^(vz_S2UKQz.=w0 bCYqjrK)TXm(85cv֖_3g,.M~=Jդ 8Դ41ZrAR -'؈ |Gݾ-=Ana xmC)y٤citZ[pJXOCёQ 1Pvq b MVa^@ӜX`hZa:AS|Q%.9. "{Wg`TMgJ=eRoFrc89݌xg{e{X{TBueggh-Bh.SHIB0da*Y>\?8`܁<φy(ks%;Qh}0{`!UɧLBYѩ71ؓA96lⅻFk yfb^o|_I?{olj(Vg0ƵQsTXP%,V?'7^]m͠I6% HjT<˱<$ zzp͙7+0i ~tga.{ۇR8MC]ڽT!7.Qe*7hˈ>t߮uS|X>YYD?J栗p%7%#ʓ saˮ6$Js\~(5d1 v=9:n߽2;9P Nd$GFyle<j%AC(#"ws(7eQuJ؀G)nԛcPl>.UJ4eXA7sh>;KUj5h6~xİ;qLs9.kLKi<)Ws! ؒ;s̑yX=q~ 3+ІWx''c<}@2Q y<88C.x?xpB.ע,.hCl3A01w'GHjb+Wk](<`?X npğM[a,DF*̄a%=_欂!J]yo`pY1:Rr χy6l ν" ?ߺd#ʌ'n˖$ +- CAV"IR Jwd*1l0IJGJbA|ӓa%x^ӟ|=<SFmy?ן2>ޙx_ͽhbOo_7>@pr $/-ͽىfn^Ʊ|)-&&@oR* d/Y}`p?g?\e߾4ghO7_~'@oݺjw$#Jf'F'91=y*P,]LNO5[3Q`u`mydLD80 >GF $4ZVKQ)YM,iXXIf`E 3dk /K3GW_/~us*iȪ D;o. ީ2f iI:R iEπʷ˽E}R9_ՖͼN]wZ~=x'~D+^v\Ato-MsS<@3 NOoE]r_οHPrfjB\<D*AgLbfzXrNjP*C`><њ,PҎXBUMBXdI )S8U9 Qq S&OO)9Fތ[bdT3[QL7S2,F&)1:.ݻ@вk~[W7 6.fzԵX'%8WvYo7ڕ<=<84x<GTh|oVpb;  R+EasЖI }rZǶۜ; |sıcAV8'`eBTEBJJ z 㥫H9 {AVȆ\d*̴| @-K/e ;%5}ڵqm% (Ċ19>"#ګdF0Xֲ-GF8GG`(CR,3:$M{T\fI\86)=L^-.,\y~8)ޏ3*E{ms1v4}wP"(J%պX>I\n\D C(# !Zi"2ѽ4V)-s nPNu--޸sv,ͳWnVcjqDߺ>ߨ7/^~5M`2,OCy?X;<<}z|#'"?'Gg{||я~po tNvpNL?`k5?1YX'xTKnܾuuivffc=ů}j[oz򓭭FRoFf_^=Ѭqe;K7\Vgg-dAz3!weiTDn Vj8mbKЀqqj h91IچjFaES-Sdc˖WYo/-]w0. 8ʈ;h@9 \Hؒg3%%qV/yf!H*,֑U({$"zTOk-K.HeQGu`2}*!V?z2f̛Ѽi nlnS\rl/^"{CK5ق+2 `o'AŧQX6eӧJJ(\.43X蓐`P(4}MZ)ԚhS>p;2a\'[Q6i S>x ek}mq~ .@nx6+k\K)hu;̎ zC%ЖICcfa!%n.֠M0/fIK>u{Jqܭ|cc< |D' WI8l!;8@7a:J.bdM  >ll03FtjC !sXQ양*D94=-/|*`C>ރ[V|5u8; ai4,_9>N^j8̂Cp8E#z'{<߶y_SؕIKNX7`݋ymØ+d{{?L'RʼnL! JLn'Po`xIj!p!{{i(_>z}wn^__C33;*O7V_G̐߹>=5Ҝz곕_f>x޽߼rM"x!Oo[}ν1xMu}ߛXJJ:g63;z;=x_[<8+Xڏ0nLdgk{g?-CkfG':(, F'O#{bdUmļZy W?xu|) ]S9v]`Wk %S@%q6ttډϡtɑLF&f<!o `?TϾ}sӹŅWnM/4jզR) z$1I:\tT"|_MQ仙!G!G~ #ZzONCh8KO^N| EӻΌ~Ęe n٩_9lU<;,sUYF!D8y\z?@urf[9_ѓb Nw- ܯݬjt*A17ΎΎO70)9&<V*JU N U0 Feeo8y% 8%ڤ./ғ.MqM-LB6vjjچ[@Bk`! B) 4v"t9D] J O9:<:9bcvЖ׊ sjAy*.+ICBJC PJv پI2g`/-u!T _t}>c=xx-L9Z.#PqӣI/~f)'򼱉7?6[S'g%55P{ݻCWU¿9??;9oW(6 OJ)hq$9QvC% t,uiSA5Vֱ:XǰۉCndcJ ,DC$\=yB bH&ǠZ 2ɔbeJYwU[VߵI"0g' Nh&xTX>f B`zP3X$!+}+;AS8{,hޢ XC@,ag/"-!W*Д>f }9&k5Z{N@CǒGQX"YāwQU `} [8_֣xq^䄗0Kֺ8ݡd3=Go$ky8eЌGJ7P )XE3t]) Dz-qS*Q2ֽA,bBӳ`hgc򵥅)`UaGo6NV_vskWÁ~[ BJ(W !5:XDVkR_}/${ww~33'ϟ~sr91VytNcECK7~40:BZ]'q~o߽zW4;w)ww^Q:L昳Dj+=x@+xmbfarf!J̃O76w,]{eN#ó}Z~dkSV "9[x!yڕW20zrՇ 97545%%Qgv mwO'# W?^**a]DT05f–҆KmqLV&<]ɬGi.1qK>O~EGk9.a%,"I|%wd\d7mifv[}w^lK㞢5ոA{p By'䦤o`32?LƸA<)=uNzTjn{[V NhI)QFE' +ƫ(QfXi¨d $bһ6F)Er>?G2%R6i7/2p7מ%ìmG†rV(eqBUJi UZK PP>49bTR`_BW-)Ό4,z|dG 7~J!D $.poɋ]UZ ‚p9b/)_uSJ48I1KR4Wq?.ͅ`" nԫp$h1P\r1z;pם[B=l @'|Дl\M )WB"BB#-VV鵩isB؄/rnTTA:ILj]G1rCKB'W82kd&ϋMظ[߼a׉-HdUvK"1I6jtڳۈ%E~eٲpH,&8Lp 7|#IfL~~fiM3~p߻"b&Jwvߕq2uKniiQQ˷@k0Ft]./*LI_ XyV̸?g___xt<+m1jy*s}ςvQVNn]̵"0oGUG]/l>oV8|k/ ¶1Qb!oB6l6-=,^+.//Q:S(Gn[uR23;UsQvejn> uHq*nɉ,x[|;t.P/Be ƫg^™߼ 7`|Nwn;$ h%w0Rz2&NME5?;yiOޭ['LӣC}-ʇ\b[ͮ?z-ʌӉHR{ ;;3K3Ѥ˸sIpHĹ=ũtD@a Cl0wPZGaO 6G z7&'ӼC><} ((5Pc}`]f$oݱlCcLQN cjќ'h[aɞh FGA] @sXza3:nS_l שo:^FO!Q"5j!(ې͜( s$uCh:<*9rƌ 㗓T 3oB;M",(6\'u9D^N#,IWFM2B^D>OhOϊ8"QI0".Yl@hDȂV>LhsSːƐ0šb8KF&+طdM\;X5oyq LeG LD _ %;佟h(ptp< ml {-LGM=J0`n*s衚x_NAjS`Pz3KhX`)s&G41Ix;.5 rT0LGé+ɤ;478.Šl\G6n`(,W'fP72N3xp?Cq% Jq~Abhsǚf.b %<O]pVbLizrݬA/~{w/ %*[ ?|/ l\ui^9;$D͊u?f+S3-w% WVFý A_zc{ 9!M')x׿7_|U[''~0dz^i4K80ppͫS4݋Z0yO~\tt|ᰄ&sLLL n젹wZ$mt` Y2iDd ؓ,{3ׯ-Z^^s;0mdiTw28ѥgb)|(Wg HO9hFqx*|-(|Q(dj鸯BoA#0gXd̯P>qG*t"/~bsJ7SqRǯf`w$ĴI/s(P vI7u"ثWiƠtUDb=~a A#N'" 9q Nȑ(tdrf=NiEVK 3 7}Aa =*=E07Bf]rwP-Pm7`1? M LJcU:`Md Jc.OBz* \ƃ(udfQJ̋W{CBst[maYx2\c#p^{ Z^a7,B!HC$.k"e #^Хž?g!ȿ [V+&%v'PyPZ*k&> [ Z'JST0M%$ZKEe`"1rѹNv@bZ$mpgnb<Tٮcr3N_B|9˱Pp98uGf 0gv9Gj:xߦ(--Ij:فV4FK\sQQ9t0q]V4 hFݽV#4j!Vsxp(}@ ʢ¸0+CK ! A֟Q8^a{Eʄ-ȔMILX(&&ù~0p8f?"P`_ƧE(ퟄC#\coA6>N$Ÿ # YLxoM*CEP!kpjr"0B. pEs`֖l2TH.i4h&J*IprOS^PX]~=xW_1K3>M6^w k#}-'.~|-vIyL3IJ[NEpZ#HtpYM/MRŤJIQclT+JA.  (cR^__ϿW^yz/~?o~W)/h7< , tԷwVNώܝf'&F rWD&Mɉ>xljUqЕ2KpHh:[{/o_:iw>_YV.ƍkR "R, smyND/ʽgG #N(޼Xֺ2*lvdqfyaA rЂK(Ady^Qidf" 3S7oߛ}[|Gwo.37+_>]yqVb&Q!Q;hpzR]i]"R س4\VBz 5 K^Q {C2>_3AݳРj8= Жv"qGv`p2Pr^H#.8# 1>N:XNO[ Țd'qH!(RcS\2D@h`a9Dsн5 }ǰvtL@4ϕ̸#%*hfBA!bj`NEa$#% |'3σTHmH8F~}Sy .Ҍ̌: aܞ.$Nngօ*H 2*k/zYtarǵj`cS.Vj:!b1PCh+3}IWh!IK 2d &lYa&3#1 dS刢x7Va\ü>Hc WD^?T;Xl,Ķ^u:Pz!af1{ ~ۣDaJqF`'\O2Mw|mQe7aF;PͰ'U/l  ` aG80ø2^Â3.h?ќI\#Cۉ)T+x}9+ ،G]ݑ(DǙN#7l a:0lU)%;IJ,U94BUVqX*"Ft>+p6kr6Bt{Y^Ή੓\uЇtSrG;N"H2+kx}8Ꙕ,w'tյ(TRKsb/>31tjfbKk6?9Vv}Kn}TueY)As^*ʌLdvV?_+d\ZӤh'?yRTy*sw~~zt6{l!V~4(g(mCnemęS'l1_̋@׳K˥\n9 ~&ʥ򵹙/waЙ_Jt @ ?YF aP6!є$K087>[ !Pm49=C$`LfHfi'G&leX9=v$s#нH_;L/p(cR &Ø{DY!L%Q7NԌU:T%To#Y.P?<8e.53pq&SXUv^?2L6D9 [%m(szB=x$)_S(:( >x_(&}Ő1.I6.y6K[ >Y# Ē0;V"GsLs"bcNųh Fl?a(Jvv<8C%,S\qEoFd6Ljue&n^ ΄R.#fǘS /qeFˆ"^0٩qKt/Ut#gx Ǟ^CŶ# Up~CH:N*%$! )]EMϪ#GHVA8 ("0qN"( $x(* BP'djra8)w7j3|.r0@o; r#lۇ; ;Vcy,B&b!^x# b).DCMR ] E qOgeZ $f.73`T: \٨ۡWbgkzY)AQTw9j鄑O{mnTs lta(4  _]-5<5@)Cj+68M|\ _1f1-Tt-Ìd4yc6|qB: -`k!SY@n?sz ӎ߿bgg?|enݼqW׾\_O߿{޹uma^Is˝/w6|VDIK:c^x$Qҍw_> oDn; ow?qwb*f^=_yrfNf榖g~@TT$s/O*dDh *<S :7 riƼc!=|O>UAg͎ggG%=@zj~"|MQIT6565)fO._Htͥs/51tB+D9/)`2).'tp^v(TF2޺f6IJr7"Go_L/..-._4طUnl!{eo䘉ĤƚV $ ңc5/a@* +|-7c"+kg EtHsv̰X p#4\v96l`=ЗAJ. $d8DJ $!-Cpaar5`'JԭJL(мBQW_r>a Hinåۏ/mpUtmJ:2)~5<7[gOjP?rzdi-*+HS ؘe&5Roկ~(??߯:ё<Ll"㩱ƹbܽwgDW( ٛkGk@E6>~ BNO%9'^4;Hd$*l׻a@ycdv DR -h2( `rx|.=]e4aWFI[)un߾ۯ߸)jVؼy7tۧ/[;*OA²*ʍy|yNJgT Ne~ߕ\-[pOCF#Q} ZIu #7cSקu7H3NF lycQ%I( 8r^VHG:V3Q ֗k$rN)~T3`⊡yRAw [yb 26ohCK4XCNk`/'$޲Ea8gKoWkE9 B{_"EՌ*$z6}aܨ}Lh]Ą5GDZ6 SDdB.޸N쵄F.E˖4 C:WB0?p75#H#re:![‡3'9ݮpFE*(Tt[IŬZK8H4ęb[e\ Ac)`%ӸuHefL0it %sP\j3hCgFTngT̖ '9+&fS0XjPڬP7FsGe0_8rUsYНQ&4(6_6پoX =(BЅDk*}?! Ќ'UZp}jxN)Y2i#l?Db%EqFQO2JP[ⵟEC@@T^ ~(87U# 3IGM&~vfAMpn\Ltd4ux?CӅ L&T_(lxR#kr)w-k6; ]n%c(L!3#M_ӆ ~G4xMUlgjQVIGY!пq5Oche?%=0A/|U1or+..*X n) )ӳ i+ӊ$(M]JРF!<|rvf}ZzZ9<8;>5}tdggkbl?Oݟ׷[Xڝ??+ p6Oz:Xo<78ǽ|Y36R9ؚ~"?y= 1ڤ{~roFǵBi['zVpz(eoˠ]ѱtпsI:VJsѝ ]7 !6ѹ+1d:20x## V7]{/Wwgd*]"X][[Ig w=:?oCTn֪WwV/FF%dyjF$tH+lNӹ.fFǦ\(D1 QB8u5)M6Z**;K(pÖaszWYtlȀz.gZ᷅7_z2i$5$=-DӺ!!`c X W%S6ɞ{C. jS)&N,ͨZ2{= RXȁE. 8ob^:JG,Êl- aӺ (v8nX[_sm"w@QTߞ#(4&3CEIڅ*u!z2E&Rl1jYMV(,k ystj0%49L73$rNYx-8E1W,|a.xi9%s(}H`6pk t% T ,R /LNV]*Βk]e dOFGodw(6qpRm3tۋƚ1 ^+v0 :ʣ5]:*Mhn%hA,B꼫A֭ҧA+b-U,d~1tAEmYOMjY8jaHՕBkbR֙:5Ч. ,=ڭ#7󋣺6O)$[R-nmw6щijD!$Ծ2HFǮ߾G5Sb_VVAZc\/sǷn\w?ѽ_^e+޾oqQOx(w#y6^<"`dJ7g'yۧ1q:?Z[;;k+l3 ;"&3vr\}rK\T2 uRJGJǎ#c4UhH%#/QgA7NQi!{piY܌70uiDžӳ_~cc~vIrkcwgc?' ۯAl&!D!?ApK҉!47>^6ҁK8Xoj>z99NӞK|?jI~vvnE<|,KT"*MIwX8$"C CsemW*]26EօaoČ2[%e|4ͯw, |k`Dfjpwv9Qg7[oeיִ-&_VfphF66pX)g9Z8+ΠK^/$cl)%Vb!¶TQ(؎ʶQtv_~e1+R0 mSȧR@ 6.wW+B*#*;JFmKS_Ke'*{=d| L&ԃSҍ9}9;)1ĵ9o[z=H|Y Nƿ9I'5T)%tp6J#Ee;*gZK*)"Rc@oeDžI*8 Giw;V~ :D LT}mFϣ9@pX’sDԋNfP 0!2-,c*Vv*W^)1Şs3@* ٍx|Юi5Ѓ7c|Pή3NJ` <4-X=ۘ)iR\GvGIr<]"v"Z(x߀ Ԯfm*|Xv'mw'P;%D<@؞{ D |%ߚ >F$1avZ%bM 8ޝmxTj0B4P@> r.7`lqň&5ɑxVdx+ORQG<[>DBR;,|i0>1 }Ų*(Rj첮 |GJ2599Lx"_-dZ3*l2H5g8z݂?4tk[_|8}O"ơQX>=?zgOfW'Sx(u*k@ym];]; AonkaFKLftl:_Oѷ+_7g#ə10??wcrb. ԛյm!.NώAZ#0I/lU%dۭwjTvun$Z ,;ׯ/~Paۂzx^ON_o}`ZJr?;5yU&#Z"ǩ_=G0zw<*S<6Y([{tlڽ{@b42$Fb䐳ߕ[{GSM# T͵ҕĉ+3`d:yRJQ9 r]&&,148=bVKXdn# |byxDB MKG( ;0oa;$%Kc! @`͈C]D>{+Y^/GD{ }Q6n;(>qd0f5,T%ٶ[L+Ji?eHHXPΰLjL*=F !P+ju$F0藩"T| 0u9Adh ^`/D鹖r\P F=4"aRQ ߺQ (Fu]Ƒa$CEnrL87x]/#O,siܩ cl(r쬽 O[e\'Hl7<,{qYc$4Y~'#e+Z,5$"UL@8"hws@չl>y6/06R5D< XG& i^lbslt_<+ sQSδ5WCSUJFW3J" U[iPMB^=5vq84m:#Et P'B؃՘S2p my5Ӆ-A0 QhW"ax.^ 0A։TڇHqgB! Cp;E0Dg庮QDZ28\һ 3*pe8=8Jz*3^>Xa dO ZM^"s5A]VwS&"!)(4jb(aQ֠Vk\&oɍۥQ3Sd^䦊 "iR4ez[z' Goto߽hk/tHjff<̼ݿw~|ptR}cyӪo^Q-#A]Z]=P>0轛+_,d7lKNQ6^LeKRBU~؁4: [;~V2;; *Ff:OܬΕ :.5JDmp< Ka'㲨Z;o-:_`nF`y䷿/huOHvSono/-->Hx)=F[:,^;ܕ,uy$=D-Q^)FpoNM,P܈t Pf&BM^8Y+X/8F ?.Dpx4ab<;E1R)lLp-A;WiT#,`/q[E{̠/p= 00E`<0sIȴVs} P3q"\6[1A q]r)k)J؃&:Z`yJfq庸>m3 lݫ~\enӋҞ[_D(\gMaT$p111l&t8f֠CoM8anl f`%beF 5<1ZtP0 7rHIB<*Rcnxɬhi pV'`ێIp)IAqS}:F I+p(KxJd١?pV*s68?h0c7JP} 4lРhP Mz" 1m)4j ۱}P5 ƺJ#!.l=] Th:$9ECa0)XYWuF;w.%( ۄR`hҼ^5dAT.:ͫTlaن+_!j 8Xms5i?=sٯC|(l#j磘)f0v||/-.KHUm?/-,՛ָh6~:8?:9eKӷf2T(3p+F&>ѺR ?f&NճF0\'t<"bsnnh,ډB&2LRǴAecsGK)Шr3Dqpmnq&SHq&}8=nwGk/ B wu޹w *1_.ב`h2xYgx3Pԣ k{_KGUg''@o|?_/kE#-O g~q?=LLO.,'{%/ L;饽8{cn>UQ׈[uq+l8rYX葠Ӳ3qo1!0>xb ֜IW Kw뵢:F(v MTiF{xkgxya{ǀ- +O@ȒˊhF_@1]aǵ`aiUײ}̷tm&TBJJURf 6>J"=.Qt4Z&> HgLNڝa˜mTPʣ#Vɧ?I(͛7 UzQxYw`榧&Jη_;ZY931wp|/iUoR,w\Bx8 "^??:ܚF:KHŒx鎻T<Ζ[k7oޅC&hCzFdB*^G!W%a3]k!RG)itR%a'>EJ0 $0@(OӇJ8n[rp;9q!c 3JDH3W̓-`C!k1<ڷ=i}+τ,IFQ44YiOZ-Њ@)%9e2\J&R8fTC[6aq+4Nw {اA_3BЌ8IfחAVrq|a#04zZ#C}c^XAkɆXLrs>|og[Š McCHG&~q8aZ4$D7l72ې}d$F5\ +Q}FDԶ#% !{NΒ ơ1 }Dm!w q<}RE%uMzÙ%XFOj=ltz$X\.ǠD`x$*i  i 8Cw9 łc'g$\N,wagu~: l|8hNh `XT$, *"G? e :[ e81zW N8K( !0wv#FaWp|kdj 5wwmP *;[­SJ ow0XEXp|贃rJ;,bJVd Xm 8ܢ}HIH"G+a3*¨7N;楑L[YcfsKtMI{]!7ӑQC~rz~RɴA8_}o?Fח>6=~?=}{{m?Rjoc+Tt?OWV_E]\̕FgF d'#Ksw\_Xf\nC{:~ܢ`kjQhQ==3>v[;+zT~dsA.7Oݿ<Տ^<^yRN*ŚT=h4:Z!Tn~v~\;9/X1P&9=>VڥJEI Fٛ333"ٜ,3BMip- |W BqX;/W6![\ǥ̨s)qԳaQH|Ry.e,|pPh>aݑxR֚nOgӥqJR*rC?Ra#"MD82\%mm^P?2CrpLhqԄQA)+d^!fJ q0']0, 3'kjj..`M*EԪUhj)G,4BB(0%gX>jvD`D!޲@+&F' ñ,U1i ^ Rf' B,+$y0`W;K2< :>?;mgDՎ0X8lpb0=n! 3mLTv4`-wӯш}),џڈ=K+d THED֘,A<"t;B[CɁVG\()>zcUx$|G7_ףʯ ̹,Hd;F8a!;7oݦ‹ ;uaiEt8jcw3MllJ˷N_WaspGv\Ȥ WL|Q+քDxiءd{(RS0fL0J팥Ƣ)͈BqW(sUcm"%m?33F;\ 9nb Mc{vԲU:wΛ&ZbxShG!}94ML|5(h Om8qTF_\p+WK c({ c>bM @:C]G"3[ X1G:"l I3b\Q RmS}[l #B˗gJhv3鐷ǠƂ "r8 zu,qԈ#|.IIb&7L9:/@~ !.0 @\a!5;)tTf*` oh)8ag+eX8\'rNFЬy"BɎK TtInatYb L~mv<(i\xAH\ox ΐXL{M\aR(qMmESh#q;QSzoֽOKhT ȂiQ, Hj=(Y1o qQR[;J0”@k^hnBL.s=rcϰ-Fl;~S+p:yHE~O]$@yCUJ x.t- ˠ0}oSSyP7p=}7T}⽐xn܆b^n[aXl6U qɔL>G4hLAgxd9a64P굦v> )U4]QUڏ6&kv%ɚy_ hK]¹ g( !*ixrDJE& 9ԫ0`J}#hdpmSLQ0䠦d͍OG'&=?h4x-/ݻw^lc`[̣g{X)ze)Tkpj7nޜ,5bN'1>e']/IJ6ОnTL)ZåN1s%AH=*틽th`b|6R`l6R@ H3`FCm4%Ơ BpT>0L.LtIwv"lB,E:"Zjf-bm('A*Kˉ3 Ixp6~Cƪ/ g;o9Hh9e`Tpܻ,}1G}7.6R !Ҏ02%C |bd W K_C R9PBIP/)R SA]D Nv1:g7:,R" Myc1! t JWǰ29C#*Hi9R. }9:>01jlSq~wȸD(tppԘ0cce: A.0fv>eZ( Q0̴DKeM|#8ߧ4s:nV2yw`JXO>(N߸7zن t:Kf^<_?8;=/f[}{vwƖYǟkF;{)͗"RK:;ljt^y87Q.M$2JPT'w+͓fǩ7vF(LL:PpCf <.N&RMtyb}mͫנxbbeWk։WO+y'e/12;(]ȴ+4OHM/^T1d|ݕ}ĵۅq/bU1Ni}e|wJMx(4]a"˸=p[iŲ2q:놚9Xlͯ0D)JqD3J)<N,8] (WhlDd(f3uYBU~t{$Oj`$Syl=pc:m-> {^F?o!lLC8Js㒖lM(Ш<3Xߕ2w=0 ,"M|Ct-T@cڌgaŶAi=`Um?R7,UT+Dejh" Ql a.0$'S bWiSbS7A݀t9;9k6AUt‡ej}D mԴTL^w@i@.kM pQN38ޥ$V&cǨ@[}*;y3_( u[)aZCMU7#/p CZ CϜ zmjyn:c {WdRL52ڕ\A/ǽN)VfsL2gZUF&͚⺘CJw#P0ơFQ&eVF"1<ReM(rWGyq ::K@Ig g.|0-h\֠FV;4=̟hHlix`31ȘZMha);*V/Ant4H3D`pi6W"¥ RVf1hSO)ig)*]?5n!ɩ3q7w:La|cd3kH f2A/*4џP *wVٍT*c4je`F^MյuRY2omUh?[wo⧝>; 9>=:m0؃83|.c+N?}ַ_~*||Sf$B Y=?99#]_z{woި_?TDat<n=|O'gjD EpN4K]VڑJE_Cy2+0R3c 'nxI#tBř$,1Bk:eP5=3 :0|;)K^RAqwXwP%`  қc/9sk*FF9|cW†X3"'K$ơFpiVO ϱܿ͠"A-48x:Mm,LLic!I.l &Ghϙs04}I)x PwmHBԋP>n^{sDZ6L=g#=incW7 8%jf: @-@_,.N>nƹEA͢cn[<oAfc0m5f51,)=OsmZ{| |Z"~NGV팔&fg\or-~?tjtf{m?y | vy@~ %`zsxvn犹N7*?d(Oz4pxfcm{so yH(L?#Jx4x908jM[?i :7fFw-MLLynoN-mZ\^p![ѭrˍ7݃z~!CH<%6>ͦRIZE!YS^eUJ߁:~1unLd&!2ŝj]|We9՝n$!F&.8=9W7o^vAqj^m^f &Ǐw77;Qf&:K€ ޼~.SP?=kJ'57w'?;IQL1319 h(Ptߣݙ-=6ZRF})%@J35_d`՗. RZ AɸVRIfR(Wr}*#ͫ0S0#Jk<3 yqbqy,KP860Lzx@x f !O @OEl  yCh!óloo" DI X_ ݃5 daAkU K2B1Xk6EW'"eiėWFxPP0 w x ^ƕzu|`jQh/KjTnEzbY+(`J6 ;<9= )]S .wz:| @*zC% }kK)"YWz4BQ ><̘:P3V)T r`A;[2E]CbCp`%"Hnd7 &j\ \ :I,U4n0pvq _?<ΧKq=9aw!X"eVˠ#N@ݹpliekSlw:c6Iy?{n')ggD!<>Drld2Q$a8;ַW*`d=65加(s$nX].e +wgnf.t+hqaW.w BDH)Le'&GsѕZІݞ/; gTJ Z29 w/o wY9#z8^wwW+d#F7N#ׯ+tܭ7$PAC{*գ݉鉑bRm]fmk ԃ7oq`6=ZaGM27yωjRE/ dg'p+JY[Y}F\v֭[ВJ/O%D~{ f=2B5i+6 'MG6 S򆊰Y܈ p:2iW͡Zx<λ]0E !D&cŻaYgץJC?2iC 31#廈O{q^k:xNX_{M; 7D3\bhZXC R "5C{4Ecε@2 kBKaF7o88tB G;*?6]X(Ի:g.[^} B 9Jxdhz/W2tW' rjY!ciD7ЂǑhzg='<ՄD}Ht,ʤ4abU$ERDӳ#84dsoH t391x2 08LFrDbr)B~;"Ze 5khq2l\2 כeZֆA؍ZH1 D1L8%.thepggF#qx:}ľJ`|m-'F/;r}ZgaNq`g2S)a^J&5u ))L 897e FkU!zd(!.P.pҎA.&N:ȡP UE9~ʇs@*b#Z0H 'L`{|B9>@Om, ~ ᳝=v&cݶst{`]y㱛mln>u)Mh5 c|HF#uwtTʦ~l]ӹ._Qo6 6 #zJ sKL:;5eomU鉑]] Vϛ:O joQDj,?vzrQ=9wtNLirí p0.Ԟ#K*NKhӤl`4 Py(6xt2=٧iCeA,kg3Hrid;Q t2aAxߍʪٺ+Y (퍘 \{4)A8;^C~ $wL=Jp0Q,"!ʻm80ҠοH)u<` #\ a6!1|Y&tfuNU)I t:JbB 5h8îa{aOU{q!:IMo@P zkиn?в'''t{⯖y ] aWǦ`c o )pLB)[^gʉ0C) k0ȂƱR meίna!^VP%N7Ĭq,or36|.I]vI#TNB,@d o8VLP;KAaK;C텍Se'm5[-Xa 2bPp=l)1 &Jlqwb#=Y/Rn: iJ,7j:─*w/~w+A̧L$n {>`mky GI/Qkl;ח°nM+;J Nb''SIe0`xmyaj-yO(/^~ZŇxb&A H"zPiۍh!?_O8CӪ7 JTm߾^.% ] 8:otQe@v?Swv^,!1v_% `:>:nٓ'ړ\k"f^RBN2ʍ# 7JB^ Ca `{DDGᚬFqsD)!ـ&,{}}#ؾTNo)=lm<4*bujy)ӆs;Ԫ\]9_,$QW*{<?я߮Z90 v}M!/?{ FfGo\w:TIū?{~) -77lԎ|~vndRU_<>Bv3\ ;k8sLC¬jL.qε9x uڠv|7 m{9IFJ\6-#D2ZM3 E7կ"յm:1Ysd4YLuG.jǕ/?_넛J'ۮ2"[-aףA`NŅLJ"<ȑ,E@wC&63 ~cϟdaBnZ _o+{=0A$&c&ґ0 I=<9]L&@"GmmsN_|&&fXL W϶^rss$<)Q_Ib^esy`!9]QLDIo :5 1 J uzC}G2e\nV3k׮MLNMmJ  DDT2Q``ZER9Ȋ9t|eWJBm/h6`4Tip0GM=V[]ε3;F\B2yi.9̀8lDBA/NcFKL .&|U@#_pQ][:@0s(QvG9X9YL .>kb SrAvfUFuR@<6h0jncTC*azDXudclbt f1b(EVDA1^)$v gFA*8uD SrH$9L3]@Hwҁ1Js2hs~{RߚfS9nRRq~΁_X %VL*!mAAZj_@ѴK!)%msIf,b^ SQMt_# SW&PG͟ xz%P^($=4R0H;t[Os\ g>#m.OQiHM2ó4Kgg?GbիWSJ G}B\֖ߎwoޚ.n|UџON+#۹xu{k߾xj}mtz& nt_2~0F]?ّ,Q$b~vcY>_ X.9;:xHG-@{$(wOrJlL1%`$ahnϙ^HUr41&SEXaǎ!{hdvzG2"R0= 1!PZg>y &¸ %zʑu& KLZσ]b0b|0f[G˵hV) -(<6@ p"|1agrLJYFIwy5J ,"&5-!Iǹ񪂋C}կ`oQdcp eo}Rh%uW"aM yg lƬ=Cq^ t om+5n#:PNt92noȘ\"d4ÚxP?0DOm -Ab ȈN dZ5YsN#%)K$.S'C?7[!-$Q H:ǑŠT"TŴq1 .FQC!)!u=>(¬E+)?ͽ9;B9V4'w9n.&6XT]2~ҽ8=łV?dUCCHpAmTk41j\ yA$Br\ƇGK/Mgsv5@W a=o+-u=_\?e#CwkYhzGG`ȁ՗/HzDzΰL|>Z7Pp199N33kڇEupu*zGA R0qP_K^E,Y*P<#R0NH?x)Q٪\<\4ox 0eFhhww c8(ЄH &S6ȟ9C&>a'4őz 켄/5͸3^?uN9Ʃю͐SaUf,Pn:, ssJ߭~+72&a6z\ۙof{s_^-dikbsXnrsc??<կ>;Pn쫮ݼr7Qtd!Í-/^_$;7n|˷->}__ͰNvqH`L7=w}|jo6wRW#NùUB?>;z5:hI0 S:qѨhڝv._+ *_"u;a0i7.](8^'@u;d FBN6́<5N*ՓSt\T|2rf4zlQ׏|SRDȍӅy' S"0$NE~bJ?T @O>z>쫩ҢEs~xt Q3v"f˗VxyJ03 S*z:()7M>yhN~c"S`VG[%j!Jd3W(-SHMpp&GSiA:k*zV2N=0\yV: ^!`#j4=T PnR rDG:q_g(Oۨ1EMڟXy)3&AQg6=V!F9khxLad 1p?t5]5v}1l!gG }zh3Źg㑋x6ȁE!:_ii߶P+ja}L^I["zS_!Փ"Ӫ:GK|HhB*(><]B ;G#r:"S"ly<}cvluuGg~oѻTʛ_W_VCZ7Nnk#-37Vhs{k+[+[͋3`'w@x{}}_a{T]h˦3U(ݜ_:9ք=W_|L__)ơ!Lfp++߯o][ZuP0yIJ]"˽THPD`D\7mmJB(~W_ru >~2?('Lzn(bOޏHtvӨlH0.,IH ꨉѱ끤^Ϸ8LLk#*0D!*.p>AHl6_ƥv٪, ga`O.!^Lo\T4ǔZn]= cl7,v!obSq=j a롰"vb#^Wx+2j63GPD$( }ۑ |G!T5ijn wۘNiBc) 0B;N+z7tŘ(THAtZf=W썲("6L(~#!}5 9IqHӰz:v)#FЃz`fKéT9/pCx L+Dq@8m#/1wWFQ`1/Ѽ>aKN u 0{ahm^_T7⦅!"3bHyI@jTXT$HY- oSBcz@ld&ǁ1a?M>Jȁe=,9\ab8."6qЃ"L8}3e6>mqLO=`5% "#g-Cy*<usmyD YHDŕLBJ:yENd7Ot! ? ipZ0 \lɔe{-THⒼ{d9R CsEzภN|δrm`7.Mj1ch{N`I%qBF"*0w rӀ3uمmНll[8*\8M:"M,$r;]Q&=W4q@ 8Լ uLS53*P6DQ33;$Ϡt4eV}' ӣ^ŋTlQ6F.# Σn؍H$IRٛ7E4hÃ7wA3ZKF0;98[~md Cc8 %##PӧfW./yte<ERGN(%ҊDVA0Hy"}d)/马px>` b ?/ݽymjQfǗrQ7O6L=;xjq*Aj2!D4Q FbAY9!cͱiHNxӈVOO✸My,1 Br2`6 wG{Y'Gp3OR6(TR1}n]6+ |CX>Ah}y$U8ehߥ2_l)嵦 ÿ'OozPr:c.z_d}z6,udTla"V$חf@H+/eAY_G#8{A(yB$BLta\g+!` r"޻b[+JWL,!Cdj;fa7Nyk=0L[(gg=pyD1c~i胁=\ C QC|3^cv,v@G\S C,[i7 |I)vf2nj^ *GW "mQv+v ^ mSualvIiBJDqAcṔa< Bu Cx\@dffdv֗P:] PxOT[4 SPRHJBD*i: ] V
 BaseType_t xCoRoutineCreate(
                                 crCOROUTINE_CODE pxCoRoutineCode,
                                 UBaseType_t uxPriority,
                                 UBaseType_t uxIndex
                               );
* * Create a new co-routine and add it to the list of co-routines that are * ready to run. * * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine * functions require special syntax - see the co-routine section of the WEB * documentation for more information. * * @param uxPriority The priority with respect to other co-routines at which * the co-routine will run. * * @param uxIndex Used to distinguish between different co-routines that * execute the same function. See the example below and the co-routine section * of the WEB documentation for further information. * * @return pdPASS if the co-routine was successfully created and added to a ready * list, otherwise an error code defined with ProjDefs.h. * * Example usage:
 // Co-routine to be created.
 void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
 {
 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
 // This may not be necessary for const variables.
 static const char cLedToFlash[ 2 ] = { 5, 6 };
 static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };

     // Must start every co-routine with a call to crSTART();
     crSTART( xHandle );

     for( ;; )
     {
         // This co-routine just delays for a fixed period, then toggles
         // an LED.  Two co-routines are created using this function, so
         // the uxIndex parameter is used to tell the co-routine which
         // LED to flash and how int32_t to delay.  This assumes xQueue has
         // already been created.
         vParTestToggleLED( cLedToFlash[ uxIndex ] );
         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
     }

     // Must end every co-routine with a call to crEND();
     crEND();
 }

 // Function that creates two co-routines.
 void vOtherFunction( void )
 {
 uint8_t ucParameterToPass;
 TaskHandle_t xHandle;

     // Create two co-routines at priority 0.  The first is given index 0
     // so (from the code above) toggles LED 5 every 200 ticks.  The second
     // is given index 1 so toggles LED 6 every 400 ticks.
     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
     {
         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
     }
 }
   
* \defgroup xCoRoutineCreate xCoRoutineCreate * \ingroup Tasks */ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ); /** * croutine. h *
 void vCoRoutineSchedule( void );
* * Run a co-routine. * * vCoRoutineSchedule() executes the highest priority co-routine that is able * to run. The co-routine will execute until it either blocks, yields or is * preempted by a task. Co-routines execute cooperatively so one * co-routine cannot be preempted by another, but can be preempted by a task. * * If an application comprises of both tasks and co-routines then * vCoRoutineSchedule should be called from the idle task (in an idle task * hook). * * Example usage:
 // This idle task hook will schedule a co-routine each time it is called.
 // The rest of the idle task will execute between co-routine calls.
 void vApplicationIdleHook( void )
 {
	vCoRoutineSchedule();
 }

 // Alternatively, if you do not require any other part of the idle task to
 // execute, the idle task hook can call vCoRoutineScheduler() within an
 // infinite loop.
 void vApplicationIdleHook( void )
 {
    for( ;; )
    {
        vCoRoutineSchedule();
    }
 }
 
* \defgroup vCoRoutineSchedule vCoRoutineSchedule * \ingroup Tasks */ void vCoRoutineSchedule( void ); /** * croutine. h *
 crSTART( CoRoutineHandle_t xHandle );
* * This macro MUST always be called at the start of a co-routine function. * * Example usage:
 // Co-routine to be created.
 void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
 {
 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
 static int32_t ulAVariable;

     // Must start every co-routine with a call to crSTART();
     crSTART( xHandle );

     for( ;; )
     {
          // Co-routine functionality goes here.
     }

     // Must end every co-routine with a call to crEND();
     crEND();
 }
* \defgroup crSTART crSTART * \ingroup Tasks */ #define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0: /** * croutine. h *
 crEND();
* * This macro MUST always be called at the end of a co-routine function. * * Example usage:
 // Co-routine to be created.
 void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
 {
 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
 static int32_t ulAVariable;

     // Must start every co-routine with a call to crSTART();
     crSTART( xHandle );

     for( ;; )
     {
          // Co-routine functionality goes here.
     }

     // Must end every co-routine with a call to crEND();
     crEND();
 }
* \defgroup crSTART crSTART * \ingroup Tasks */ #define crEND() } /* * These macros are intended for internal use by the co-routine implementation * only. The macros should not be used directly by application writers. */ #define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): #define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): /** * croutine. h *
 crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
* * Delay a co-routine for a fixed period of time. * * crDELAY can only be called from the co-routine function itself - not * from within a function called by the co-routine function. This is because * co-routines do not maintain their own stack. * * @param xHandle The handle of the co-routine to delay. This is the xHandle * parameter of the co-routine function. * * @param xTickToDelay The number of ticks that the co-routine should delay * for. The actual amount of time this equates to is defined by * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS * can be used to convert ticks to milliseconds. * * Example usage:
 // Co-routine to be created.
 void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
 {
 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
 // This may not be necessary for const variables.
 // We are to delay for 200ms.
 static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;

     // Must start every co-routine with a call to crSTART();
     crSTART( xHandle );

     for( ;; )
     {
        // Delay for 200ms.
        crDELAY( xHandle, xDelayTime );

        // Do something here.
     }

     // Must end every co-routine with a call to crEND();
     crEND();
 }
* \defgroup crDELAY crDELAY * \ingroup Tasks */ #define crDELAY( xHandle, xTicksToDelay ) \ if( ( xTicksToDelay ) > 0 ) \ { \ vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ } \ crSET_STATE0( ( xHandle ) ); /** *
 crQUEUE_SEND(
                  CoRoutineHandle_t xHandle,
                  QueueHandle_t pxQueue,
                  void *pvItemToQueue,
                  TickType_t xTicksToWait,
                  BaseType_t *pxResult
             )
* * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. * * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas * xQueueSend() and xQueueReceive() can only be used from tasks. * * crQUEUE_SEND can only be called from the co-routine function itself - not * from within a function called by the co-routine function. This is because * co-routines do not maintain their own stack. * * See the co-routine section of the WEB documentation for information on * passing data between tasks and co-routines and between ISR's and * co-routines. * * @param xHandle The handle of the calling co-routine. This is the xHandle * parameter of the co-routine function. * * @param pxQueue The handle of the queue on which the data will be posted. * The handle is obtained as the return value when the queue is created using * the xQueueCreate() API function. * * @param pvItemToQueue A pointer to the data being posted onto the queue. * The number of bytes of each queued item is specified when the queue is * created. This number of bytes is copied from pvItemToQueue into the queue * itself. * * @param xTickToDelay The number of ticks that the co-routine should block * to wait for space to become available on the queue, should space not be * available immediately. The actual amount of time this equates to is defined * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example * below). * * @param pxResult The variable pointed to by pxResult will be set to pdPASS if * data was successfully posted onto the queue, otherwise it will be set to an * error defined within ProjDefs.h. * * Example usage:
 // Co-routine function that blocks for a fixed period then posts a number onto
 // a queue.
 static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
 {
 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
 static BaseType_t xNumberToPost = 0;
 static BaseType_t xResult;

    // Co-routines must begin with a call to crSTART().
    crSTART( xHandle );

    for( ;; )
    {
        // This assumes the queue has already been created.
        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );

        if( xResult != pdPASS )
        {
            // The message was not posted!
        }

        // Increment the number to be posted onto the queue.
        xNumberToPost++;

        // Delay for 100 ticks.
        crDELAY( xHandle, 100 );
    }

    // Co-routines must end with a call to crEND().
    crEND();
 }
* \defgroup crQUEUE_SEND crQUEUE_SEND * \ingroup Tasks */ #define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ { \ *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ if( *( pxResult ) == errQUEUE_BLOCKED ) \ { \ crSET_STATE0( ( xHandle ) ); \ *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ } \ if( *pxResult == errQUEUE_YIELD ) \ { \ crSET_STATE1( ( xHandle ) ); \ *pxResult = pdPASS; \ } \ } /** * croutine. h *
  crQUEUE_RECEIVE(
                     CoRoutineHandle_t xHandle,
                     QueueHandle_t pxQueue,
                     void *pvBuffer,
                     TickType_t xTicksToWait,
                     BaseType_t *pxResult
                 )
* * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. * * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas * xQueueSend() and xQueueReceive() can only be used from tasks. * * crQUEUE_RECEIVE can only be called from the co-routine function itself - not * from within a function called by the co-routine function. This is because * co-routines do not maintain their own stack. * * See the co-routine section of the WEB documentation for information on * passing data between tasks and co-routines and between ISR's and * co-routines. * * @param xHandle The handle of the calling co-routine. This is the xHandle * parameter of the co-routine function. * * @param pxQueue The handle of the queue from which the data will be received. * The handle is obtained as the return value when the queue is created using * the xQueueCreate() API function. * * @param pvBuffer The buffer into which the received item is to be copied. * The number of bytes of each queued item is specified when the queue is * created. This number of bytes is copied into pvBuffer. * * @param xTickToDelay The number of ticks that the co-routine should block * to wait for data to become available from the queue, should data not be * available immediately. The actual amount of time this equates to is defined * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the * crQUEUE_SEND example). * * @param pxResult The variable pointed to by pxResult will be set to pdPASS if * data was successfully retrieved from the queue, otherwise it will be set to * an error code as defined within ProjDefs.h. * * Example usage:
 // A co-routine receives the number of an LED to flash from a queue.  It
 // blocks on the queue until the number is received.
 static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
 {
 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
 static BaseType_t xResult;
 static UBaseType_t uxLEDToFlash;

    // All co-routines must start with a call to crSTART().
    crSTART( xHandle );

    for( ;; )
    {
        // Wait for data to become available on the queue.
        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );

        if( xResult == pdPASS )
        {
            // We received the LED to flash - flash it!
            vParTestToggleLED( uxLEDToFlash );
        }
    }

    crEND();
 }
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE * \ingroup Tasks */ #define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ { \ *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ if( *( pxResult ) == errQUEUE_BLOCKED ) \ { \ crSET_STATE0( ( xHandle ) ); \ *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ } \ if( *( pxResult ) == errQUEUE_YIELD ) \ { \ crSET_STATE1( ( xHandle ) ); \ *( pxResult ) = pdPASS; \ } \ } /** * croutine. h *
  crQUEUE_SEND_FROM_ISR(
                            QueueHandle_t pxQueue,
                            void *pvItemToQueue,
                            BaseType_t xCoRoutinePreviouslyWoken
                       )
* * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() * functions used by tasks. * * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and * xQueueReceiveFromISR() can only be used to pass data between a task and and * ISR. * * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue * that is being used from within a co-routine. * * See the co-routine section of the WEB documentation for information on * passing data between tasks and co-routines and between ISR's and * co-routines. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto * the same queue multiple times from a single interrupt. The first call * should always pass in pdFALSE. Subsequent calls should pass in * the value returned from the previous call. * * @return pdTRUE if a co-routine was woken by posting onto the queue. This is * used by the ISR to determine if a context switch may be required following * the ISR. * * Example usage:
 // A co-routine that blocks on a queue waiting for characters to be received.
 static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
 {
 char cRxedChar;
 BaseType_t xResult;

     // All co-routines must start with a call to crSTART().
     crSTART( xHandle );

     for( ;; )
     {
         // Wait for data to become available on the queue.  This assumes the
         // queue xCommsRxQueue has already been created!
         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );

         // Was a character received?
         if( xResult == pdPASS )
         {
             // Process the character here.
         }
     }

     // All co-routines must end with a call to crEND().
     crEND();
 }

 // An ISR that uses a queue to send characters received on a serial port to
 // a co-routine.
 void vUART_ISR( void )
 {
 char cRxedChar;
 BaseType_t xCRWokenByPost = pdFALSE;

     // We loop around reading characters until there are none left in the UART.
     while( UART_RX_REG_NOT_EMPTY() )
     {
         // Obtain the character from the UART.
         cRxedChar = UART_RX_REG;

         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
         // the first time around the loop.  If the post causes a co-routine
         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
         // In this manner we can ensure that if more than one co-routine is
         // blocked on the queue only one is woken by this ISR no matter how
         // many characters are posted to the queue.
         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
     }
 }
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR * \ingroup Tasks */ #define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) /** * croutine. h *
  crQUEUE_SEND_FROM_ISR(
                            QueueHandle_t pxQueue,
                            void *pvBuffer,
                            BaseType_t * pxCoRoutineWoken
                       )
* * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() * functions used by tasks. * * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and * xQueueReceiveFromISR() can only be used to pass data between a task and and * ISR. * * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data * from a queue that is being used from within a co-routine (a co-routine * posted to the queue). * * See the co-routine section of the WEB documentation for information on * passing data between tasks and co-routines and between ISR's and * co-routines. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvBuffer A pointer to a buffer into which the received item will be * placed. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from the queue into * pvBuffer. * * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise * *pxCoRoutineWoken will remain unchanged. * * @return pdTRUE an item was successfully received from the queue, otherwise * pdFALSE. * * Example usage:
 // A co-routine that posts a character to a queue then blocks for a fixed
 // period.  The character is incremented each time.
 static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
 {
 // cChar holds its value while this co-routine is blocked and must therefore
 // be declared static.
 static char cCharToTx = 'a';
 BaseType_t xResult;

     // All co-routines must start with a call to crSTART().
     crSTART( xHandle );

     for( ;; )
     {
         // Send the next character to the queue.
         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );

         if( xResult == pdPASS )
         {
             // The character was successfully posted to the queue.
         }
		 else
		 {
			// Could not post the character to the queue.
		 }

         // Enable the UART Tx interrupt to cause an interrupt in this
		 // hypothetical UART.  The interrupt will obtain the character
		 // from the queue and send it.
		 ENABLE_RX_INTERRUPT();

		 // Increment to the next character then block for a fixed period.
		 // cCharToTx will maintain its value across the delay as it is
		 // declared static.
		 cCharToTx++;
		 if( cCharToTx > 'x' )
		 {
			cCharToTx = 'a';
		 }
		 crDELAY( 100 );
     }

     // All co-routines must end with a call to crEND().
     crEND();
 }

 // An ISR that uses a queue to receive characters to send on a UART.
 void vUART_ISR( void )
 {
 char cCharToTx;
 BaseType_t xCRWokenByPost = pdFALSE;

     while( UART_TX_REG_EMPTY() )
     {
         // Are there any characters in the queue waiting to be sent?
		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
		 // is woken by the post - ensuring that only a single co-routine is
		 // woken no matter how many times we go around this loop.
         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
		 {
			 SEND_CHARACTER( cCharToTx );
		 }
     }
 }
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR * \ingroup Tasks */ #define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) /* * This function is intended for internal use by the co-routine macros only. * The macro nature of the co-routine implementation requires that the * prototype appears here. The function should not be used by application * writers. * * Removes the current co-routine from its ready list and places it in the * appropriate delayed list. */ void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ); /* * This function is intended for internal use by the queue implementation only. * The function should not be used by application writers. * * Removes the highest priority co-routine from the event list and places it in * the pending ready list. */ BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ); #ifdef __cplusplus } #endif #endif /* CO_ROUTINE_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/deprecated_definitions.h000066400000000000000000000231671357706137100272140ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef DEPRECATED_DEFINITIONS_H #define DEPRECATED_DEFINITIONS_H /* Each FreeRTOS port has a unique portmacro.h header file. Originally a pre-processor definition was used to ensure the pre-processor found the correct portmacro.h file for the port being used. That scheme was deprecated in favour of setting the compiler's include path such that it found the correct portmacro.h file - removing the need for the constant and allowing the portmacro.h file to be located anywhere in relation to the port being used. The definitions below remain in the code for backward compatibility only. New projects should not use them. */ #ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" typedef void ( __interrupt __far *pxISR )(); #endif #ifdef OPEN_WATCOM_FLASH_LITE_186_PORT #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" typedef void ( __interrupt __far *pxISR )(); #endif #ifdef GCC_MEGA_AVR #include "../portable/GCC/ATMega323/portmacro.h" #endif #ifdef IAR_MEGA_AVR #include "../portable/IAR/ATMega323/portmacro.h" #endif #ifdef MPLAB_PIC24_PORT #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" #endif #ifdef MPLAB_DSPIC_PORT #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" #endif #ifdef MPLAB_PIC18F_PORT #include "../../Source/portable/MPLAB/PIC18F/portmacro.h" #endif #ifdef MPLAB_PIC32MX_PORT #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h" #endif #ifdef _FEDPICC #include "libFreeRTOS/Include/portmacro.h" #endif #ifdef SDCC_CYGNAL #include "../../Source/portable/SDCC/Cygnal/portmacro.h" #endif #ifdef GCC_ARM7 #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" #endif #ifdef GCC_ARM7_ECLIPSE #include "portmacro.h" #endif #ifdef ROWLEY_LPC23xx #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" #endif #ifdef IAR_MSP430 #include "..\..\Source\portable\IAR\MSP430\portmacro.h" #endif #ifdef GCC_MSP430 #include "../../Source/portable/GCC/MSP430F449/portmacro.h" #endif #ifdef ROWLEY_MSP430 #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" #endif #ifdef ARM7_LPC21xx_KEIL_RVDS #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" #endif #ifdef SAM7_GCC #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" #endif #ifdef SAM7_IAR #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" #endif #ifdef SAM9XE_IAR #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" #endif #ifdef LPC2000_IAR #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" #endif #ifdef STR71X_IAR #include "..\..\Source\portable\IAR\STR71x\portmacro.h" #endif #ifdef STR75X_IAR #include "..\..\Source\portable\IAR\STR75x\portmacro.h" #endif #ifdef STR75X_GCC #include "..\..\Source\portable\GCC\STR75x\portmacro.h" #endif #ifdef STR91X_IAR #include "..\..\Source\portable\IAR\STR91x\portmacro.h" #endif #ifdef GCC_H8S #include "../../Source/portable/GCC/H8S2329/portmacro.h" #endif #ifdef GCC_AT91FR40008 #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" #endif #ifdef RVDS_ARMCM3_LM3S102 #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" #endif #ifdef GCC_ARMCM3_LM3S102 #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" #endif #ifdef GCC_ARMCM3 #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" #endif #ifdef IAR_ARM_CM3 #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" #endif #ifdef IAR_ARMCM3_LM #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" #endif #ifdef HCS12_CODE_WARRIOR #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" #endif #ifdef MICROBLAZE_GCC #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" #endif #ifdef TERN_EE #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" #endif #ifdef GCC_HCS12 #include "../../Source/portable/GCC/HCS12/portmacro.h" #endif #ifdef GCC_MCF5235 #include "../../Source/portable/GCC/MCF5235/portmacro.h" #endif #ifdef COLDFIRE_V2_GCC #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" #endif #ifdef COLDFIRE_V2_CODEWARRIOR #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" #endif #ifdef GCC_PPC405 #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" #endif #ifdef GCC_PPC440 #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" #endif #ifdef _16FX_SOFTUNE #include "..\..\Source\portable\Softune\MB96340\portmacro.h" #endif #ifdef BCC_INDUSTRIAL_PC_PORT /* A short file name has to be used in place of the normal FreeRTOSConfig.h when using the Borland compiler. */ #include "frconfig.h" #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" typedef void ( __interrupt __far *pxISR )(); #endif #ifdef BCC_FLASH_LITE_186_PORT /* A short file name has to be used in place of the normal FreeRTOSConfig.h when using the Borland compiler. */ #include "frconfig.h" #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" typedef void ( __interrupt __far *pxISR )(); #endif #ifdef __GNUC__ #ifdef __AVR32_AVR32A__ #include "portmacro.h" #endif #endif #ifdef __ICCAVR32__ #ifdef __CORE__ #if __CORE__ == __AVR32A__ #include "portmacro.h" #endif #endif #endif #ifdef __91467D #include "portmacro.h" #endif #ifdef __96340 #include "portmacro.h" #endif #ifdef __IAR_V850ES_Fx3__ #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_V850ES_Jx3__ #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_V850ES_Jx3_L__ #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_V850ES_Jx2__ #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_V850ES_Hx2__ #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_78K0R_Kx3__ #include "../../Source/portable/IAR/78K0R/portmacro.h" #endif #ifdef __IAR_78K0R_Kx3L__ #include "../../Source/portable/IAR/78K0R/portmacro.h" #endif #endif /* DEPRECATED_DEFINITIONS_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/event_groups.h000066400000000000000000000765251357706137100252470ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef EVENT_GROUPS_H #define EVENT_GROUPS_H #ifndef INC_FREERTOS_H #error "include FreeRTOS.h" must appear in source files before "include event_groups.h" #endif /* FreeRTOS includes. */ #include "timers.h" #ifdef __cplusplus extern "C" { #endif /** * An event group is a collection of bits to which an application can assign a * meaning. For example, an application may create an event group to convey * the status of various CAN bus related events in which bit 0 might mean "A CAN * message has been received and is ready for processing", bit 1 might mean "The * application has queued a message that is ready for sending onto the CAN * network", and bit 2 might mean "It is time to send a SYNC message onto the * CAN network" etc. A task can then test the bit values to see which events * are active, and optionally enter the Blocked state to wait for a specified * bit or a group of specified bits to be active. To continue the CAN bus * example, a CAN controlling task can enter the Blocked state (and therefore * not consume any processing time) until either bit 0, bit 1 or bit 2 are * active, at which time the bit that was actually active would inform the task * which action it had to take (process a received message, send a message, or * send a SYNC). * * The event groups implementation contains intelligence to avoid race * conditions that would otherwise occur were an application to use a simple * variable for the same purpose. This is particularly important with respect * to when a bit within an event group is to be cleared, and when bits have to * be set and then tested atomically - as is the case where event groups are * used to create a synchronisation point between multiple tasks (a * 'rendezvous'). * * \defgroup EventGroup */ /** * event_groups.h * * Type by which event groups are referenced. For example, a call to * xEventGroupCreate() returns an EventGroupHandle_t variable that can then * be used as a parameter to other event group functions. * * \defgroup EventGroupHandle_t EventGroupHandle_t * \ingroup EventGroup */ typedef void * EventGroupHandle_t; /* * The type that holds event bits always matches TickType_t - therefore the * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1, * 32 bits if set to 0. * * \defgroup EventBits_t EventBits_t * \ingroup EventGroup */ typedef TickType_t EventBits_t; /** * event_groups.h *
 EventGroupHandle_t xEventGroupCreate( void );
 
* * Create a new event group. * * Internally, within the FreeRTOS implementation, event groups use a [small] * block of memory, in which the event group's structure is stored. If an event * groups is created using xEventGropuCreate() then the required memory is * automatically dynamically allocated inside the xEventGroupCreate() function. * (see http://www.freertos.org/a00111.html). If an event group is created * using xEventGropuCreateStatic() then the application writer must instead * provide the memory that will get used by the event group. * xEventGroupCreateStatic() therefore allows an event group to be created * without using any dynamic memory allocation. * * Although event groups are not related to ticks, for internal implementation * reasons the number of bits available for use in an event group is dependent * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store * event bits within an event group. * * @return If the event group was created then a handle to the event group is * returned. If there was insufficient FreeRTOS heap available to create the * event group then NULL is returned. See http://www.freertos.org/a00111.html * * Example usage:
	// Declare a variable to hold the created event group.
	EventGroupHandle_t xCreatedEventGroup;

	// Attempt to create the event group.
	xCreatedEventGroup = xEventGroupCreate();

	// Was the event group created successfully?
	if( xCreatedEventGroup == NULL )
	{
		// The event group was not created because there was insufficient
		// FreeRTOS heap available.
	}
	else
	{
		// The event group was created.
	}
   
* \defgroup xEventGroupCreate xEventGroupCreate * \ingroup EventGroup */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION; #endif /** * event_groups.h *
 EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
 
* * Create a new event group. * * Internally, within the FreeRTOS implementation, event groups use a [small] * block of memory, in which the event group's structure is stored. If an event * groups is created using xEventGropuCreate() then the required memory is * automatically dynamically allocated inside the xEventGroupCreate() function. * (see http://www.freertos.org/a00111.html). If an event group is created * using xEventGropuCreateStatic() then the application writer must instead * provide the memory that will get used by the event group. * xEventGroupCreateStatic() therefore allows an event group to be created * without using any dynamic memory allocation. * * Although event groups are not related to ticks, for internal implementation * reasons the number of bits available for use in an event group is dependent * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store * event bits within an event group. * * @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type * StaticEventGroup_t, which will be then be used to hold the event group's data * structures, removing the need for the memory to be allocated dynamically. * * @return If the event group was created then a handle to the event group is * returned. If pxEventGroupBuffer was NULL then NULL is returned. * * Example usage:
	// StaticEventGroup_t is a publicly accessible structure that has the same
	// size and alignment requirements as the real event group structure.  It is
	// provided as a mechanism for applications to know the size of the event
	// group (which is dependent on the architecture and configuration file
	// settings) without breaking the strict data hiding policy by exposing the
	// real event group internals.  This StaticEventGroup_t variable is passed
	// into the xSemaphoreCreateEventGroupStatic() function and is used to store
	// the event group's data structures
	StaticEventGroup_t xEventGroupBuffer;

	// Create the event group without dynamically allocating any memory.
	xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
   
*/ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION; #endif /** * event_groups.h *
	EventBits_t xEventGroupWaitBits( 	EventGroupHandle_t xEventGroup,
										const EventBits_t uxBitsToWaitFor,
										const BaseType_t xClearOnExit,
										const BaseType_t xWaitForAllBits,
										const TickType_t xTicksToWait );
 
* * [Potentially] block to wait for one or more bits to be set within a * previously created event group. * * This function cannot be called from an interrupt. * * @param xEventGroup The event group in which the bits are being tested. The * event group must have previously been created using a call to * xEventGroupCreate(). * * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test * inside the event group. For example, to wait for bit 0 and/or bit 2 set * uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set * uxBitsToWaitFor to 0x07. Etc. * * @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within * uxBitsToWaitFor that are set within the event group will be cleared before * xEventGroupWaitBits() returns if the wait condition was met (if the function * returns for a reason other than a timeout). If xClearOnExit is set to * pdFALSE then the bits set in the event group are not altered when the call to * xEventGroupWaitBits() returns. * * @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor * are set or the specified block time expires. If xWaitForAllBits is set to * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set * in uxBitsToWaitFor is set or the specified block time expires. The block * time is specified by the xTicksToWait parameter. * * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait * for one/all (depending on the xWaitForAllBits value) of the bits specified by * uxBitsToWaitFor to become set. * * @return The value of the event group at the time either the bits being waited * for became set, or the block time expired. Test the return value to know * which bits were set. If xEventGroupWaitBits() returned because its timeout * expired then not all the bits being waited for will be set. If * xEventGroupWaitBits() returned because the bits it was waiting for were set * then the returned value is the event group value before any bits were * automatically cleared in the case that xClearOnExit parameter was set to * pdTRUE. * * Example usage:
   #define BIT_0	( 1 << 0 )
   #define BIT_4	( 1 << 4 )

   void aFunction( EventGroupHandle_t xEventGroup )
   {
   EventBits_t uxBits;
   const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;

		// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
		// the event group.  Clear the bits before exiting.
		uxBits = xEventGroupWaitBits(
					xEventGroup,	// The event group being tested.
					BIT_0 | BIT_4,	// The bits within the event group to wait for.
					pdTRUE,			// BIT_0 and BIT_4 should be cleared before returning.
					pdFALSE,		// Don't wait for both bits, either bit will do.
					xTicksToWait );	// Wait a maximum of 100ms for either bit to be set.

		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
		{
			// xEventGroupWaitBits() returned because both bits were set.
		}
		else if( ( uxBits & BIT_0 ) != 0 )
		{
			// xEventGroupWaitBits() returned because just BIT_0 was set.
		}
		else if( ( uxBits & BIT_4 ) != 0 )
		{
			// xEventGroupWaitBits() returned because just BIT_4 was set.
		}
		else
		{
			// xEventGroupWaitBits() returned because xTicksToWait ticks passed
			// without either BIT_0 or BIT_4 becoming set.
		}
   }
   
* \defgroup xEventGroupWaitBits xEventGroupWaitBits * \ingroup EventGroup */ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * event_groups.h *
	EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
 
* * Clear bits within an event group. This function cannot be called from an * interrupt. * * @param xEventGroup The event group in which the bits are to be cleared. * * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear * in the event group. For example, to clear bit 3 only, set uxBitsToClear to * 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09. * * @return The value of the event group before the specified bits were cleared. * * Example usage:
   #define BIT_0	( 1 << 0 )
   #define BIT_4	( 1 << 4 )

   void aFunction( EventGroupHandle_t xEventGroup )
   {
   EventBits_t uxBits;

		// Clear bit 0 and bit 4 in xEventGroup.
		uxBits = xEventGroupClearBits(
								xEventGroup,	// The event group being updated.
								BIT_0 | BIT_4 );// The bits being cleared.

		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
		{
			// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
			// called.  Both will now be clear (not set).
		}
		else if( ( uxBits & BIT_0 ) != 0 )
		{
			// Bit 0 was set before xEventGroupClearBits() was called.  It will
			// now be clear.
		}
		else if( ( uxBits & BIT_4 ) != 0 )
		{
			// Bit 4 was set before xEventGroupClearBits() was called.  It will
			// now be clear.
		}
		else
		{
			// Neither bit 0 nor bit 4 were set in the first place.
		}
   }
   
* \defgroup xEventGroupClearBits xEventGroupClearBits * \ingroup EventGroup */ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; /** * event_groups.h *
	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
 
* * A version of xEventGroupClearBits() that can be called from an interrupt. * * Setting bits in an event group is not a deterministic operation because there * are an unknown number of tasks that may be waiting for the bit or bits being * set. FreeRTOS does not allow nondeterministic operations to be performed * while interrupts are disabled, so protects event groups that are accessed * from tasks by suspending the scheduler rather than disabling interrupts. As * a result event groups cannot be accessed directly from an interrupt service * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the * timer task to have the clear operation performed in the context of the timer * task. * * @param xEventGroup The event group in which the bits are to be cleared. * * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear. * For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3 * and bit 0 set uxBitsToClear to 0x09. * * @return If the request to execute the function was posted successfully then * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned * if the timer service queue was full. * * Example usage:
   #define BIT_0	( 1 << 0 )
   #define BIT_4	( 1 << 4 )

   // An event group which it is assumed has already been created by a call to
   // xEventGroupCreate().
   EventGroupHandle_t xEventGroup;

   void anInterruptHandler( void )
   {
		// Clear bit 0 and bit 4 in xEventGroup.
		xResult = xEventGroupClearBitsFromISR(
							xEventGroup,	 // The event group being updated.
							BIT_0 | BIT_4 ); // The bits being set.

		if( xResult == pdPASS )
		{
			// The message was posted successfully.
		}
  }
   
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR * \ingroup EventGroup */ #if( configUSE_TRACE_FACILITY == 1 ) BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; #else #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) #endif /** * event_groups.h *
	EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
 
* * Set bits within an event group. * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() * is a version that can be called from an interrupt. * * Setting bits in an event group will automatically unblock tasks that are * blocked waiting for the bits. * * @param xEventGroup The event group in which the bits are to be set. * * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 * and bit 0 set uxBitsToSet to 0x09. * * @return The value of the event group at the time the call to * xEventGroupSetBits() returns. There are two reasons why the returned value * might have the bits specified by the uxBitsToSet parameter cleared. First, * if setting a bit results in a task that was waiting for the bit leaving the * blocked state then it is possible the bit will be cleared automatically * (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any * unblocked (or otherwise Ready state) task that has a priority above that of * the task that called xEventGroupSetBits() will execute and may change the * event group value before the call to xEventGroupSetBits() returns. * * Example usage:
   #define BIT_0	( 1 << 0 )
   #define BIT_4	( 1 << 4 )

   void aFunction( EventGroupHandle_t xEventGroup )
   {
   EventBits_t uxBits;

		// Set bit 0 and bit 4 in xEventGroup.
		uxBits = xEventGroupSetBits(
							xEventGroup,	// The event group being updated.
							BIT_0 | BIT_4 );// The bits being set.

		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
		{
			// Both bit 0 and bit 4 remained set when the function returned.
		}
		else if( ( uxBits & BIT_0 ) != 0 )
		{
			// Bit 0 remained set when the function returned, but bit 4 was
			// cleared.  It might be that bit 4 was cleared automatically as a
			// task that was waiting for bit 4 was removed from the Blocked
			// state.
		}
		else if( ( uxBits & BIT_4 ) != 0 )
		{
			// Bit 4 remained set when the function returned, but bit 0 was
			// cleared.  It might be that bit 0 was cleared automatically as a
			// task that was waiting for bit 0 was removed from the Blocked
			// state.
		}
		else
		{
			// Neither bit 0 nor bit 4 remained set.  It might be that a task
			// was waiting for both of the bits to be set, and the bits were
			// cleared as the task left the Blocked state.
		}
   }
   
* \defgroup xEventGroupSetBits xEventGroupSetBits * \ingroup EventGroup */ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; /** * event_groups.h *
	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
 
* * A version of xEventGroupSetBits() that can be called from an interrupt. * * Setting bits in an event group is not a deterministic operation because there * are an unknown number of tasks that may be waiting for the bit or bits being * set. FreeRTOS does not allow nondeterministic operations to be performed in * interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR() * sends a message to the timer task to have the set operation performed in the * context of the timer task - where a scheduler lock is used in place of a * critical section. * * @param xEventGroup The event group in which the bits are to be set. * * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 * and bit 0 set uxBitsToSet to 0x09. * * @param pxHigherPriorityTaskWoken As mentioned above, calling this function * will result in a message being sent to the timer daemon task. If the * priority of the timer daemon task is higher than the priority of the * currently running task (the task the interrupt interrupted) then * *pxHigherPriorityTaskWoken will be set to pdTRUE by * xEventGroupSetBitsFromISR(), indicating that a context switch should be * requested before the interrupt exits. For that reason * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the * example code below. * * @return If the request to execute the function was posted successfully then * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned * if the timer service queue was full. * * Example usage:
   #define BIT_0	( 1 << 0 )
   #define BIT_4	( 1 << 4 )

   // An event group which it is assumed has already been created by a call to
   // xEventGroupCreate().
   EventGroupHandle_t xEventGroup;

   void anInterruptHandler( void )
   {
   BaseType_t xHigherPriorityTaskWoken, xResult;

		// xHigherPriorityTaskWoken must be initialised to pdFALSE.
		xHigherPriorityTaskWoken = pdFALSE;

		// Set bit 0 and bit 4 in xEventGroup.
		xResult = xEventGroupSetBitsFromISR(
							xEventGroup,	// The event group being updated.
							BIT_0 | BIT_4   // The bits being set.
							&xHigherPriorityTaskWoken );

		// Was the message posted successfully?
		if( xResult == pdPASS )
		{
			// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
			// switch should be requested.  The macro used is port specific and
			// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
			// refer to the documentation page for the port being used.
			portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
		}
  }
   
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR * \ingroup EventGroup */ #if( configUSE_TRACE_FACILITY == 1 ) BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; #else #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) #endif /** * event_groups.h *
	EventBits_t xEventGroupSync(	EventGroupHandle_t xEventGroup,
									const EventBits_t uxBitsToSet,
									const EventBits_t uxBitsToWaitFor,
									TickType_t xTicksToWait );
 
* * Atomically set bits within an event group, then wait for a combination of * bits to be set within the same event group. This functionality is typically * used to synchronise multiple tasks, where each task has to wait for the other * tasks to reach a synchronisation point before proceeding. * * This function cannot be used from an interrupt. * * The function will return before its block time expires if the bits specified * by the uxBitsToWait parameter are set, or become set within that time. In * this case all the bits specified by uxBitsToWait will be automatically * cleared before the function returns. * * @param xEventGroup The event group in which the bits are being tested. The * event group must have previously been created using a call to * xEventGroupCreate(). * * @param uxBitsToSet The bits to set in the event group before determining * if, and possibly waiting for, all the bits specified by the uxBitsToWait * parameter are set. * * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test * inside the event group. For example, to wait for bit 0 and bit 2 set * uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set * uxBitsToWaitFor to 0x07. Etc. * * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait * for all of the bits specified by uxBitsToWaitFor to become set. * * @return The value of the event group at the time either the bits being waited * for became set, or the block time expired. Test the return value to know * which bits were set. If xEventGroupSync() returned because its timeout * expired then not all the bits being waited for will be set. If * xEventGroupSync() returned because all the bits it was waiting for were * set then the returned value is the event group value before any bits were * automatically cleared. * * Example usage:
 // Bits used by the three tasks.
 #define TASK_0_BIT		( 1 << 0 )
 #define TASK_1_BIT		( 1 << 1 )
 #define TASK_2_BIT		( 1 << 2 )

 #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )

 // Use an event group to synchronise three tasks.  It is assumed this event
 // group has already been created elsewhere.
 EventGroupHandle_t xEventBits;

 void vTask0( void *pvParameters )
 {
 EventBits_t uxReturn;
 TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;

	 for( ;; )
	 {
		// Perform task functionality here.

		// Set bit 0 in the event flag to note this task has reached the
		// sync point.  The other two tasks will set the other two bits defined
		// by ALL_SYNC_BITS.  All three tasks have reached the synchronisation
		// point when all the ALL_SYNC_BITS are set.  Wait a maximum of 100ms
		// for this to happen.
		uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );

		if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
		{
			// All three tasks reached the synchronisation point before the call
			// to xEventGroupSync() timed out.
		}
	}
 }

 void vTask1( void *pvParameters )
 {
	 for( ;; )
	 {
		// Perform task functionality here.

		// Set bit 1 in the event flag to note this task has reached the
		// synchronisation point.  The other two tasks will set the other two
		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
		// indefinitely for this to happen.
		xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );

		// xEventGroupSync() was called with an indefinite block time, so
		// this task will only reach here if the syncrhonisation was made by all
		// three tasks, so there is no need to test the return value.
	 }
 }

 void vTask2( void *pvParameters )
 {
	 for( ;; )
	 {
		// Perform task functionality here.

		// Set bit 2 in the event flag to note this task has reached the
		// synchronisation point.  The other two tasks will set the other two
		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
		// indefinitely for this to happen.
		xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );

		// xEventGroupSync() was called with an indefinite block time, so
		// this task will only reach here if the syncrhonisation was made by all
		// three tasks, so there is no need to test the return value.
	}
 }

 
* \defgroup xEventGroupSync xEventGroupSync * \ingroup EventGroup */ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * event_groups.h *
	EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
 
* * Returns the current value of the bits in an event group. This function * cannot be used from an interrupt. * * @param xEventGroup The event group being queried. * * @return The event group bits at the time xEventGroupGetBits() was called. * * \defgroup xEventGroupGetBits xEventGroupGetBits * \ingroup EventGroup */ #define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) /** * event_groups.h *
	EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
 
* * A version of xEventGroupGetBits() that can be called from an ISR. * * @param xEventGroup The event group being queried. * * @return The event group bits at the time xEventGroupGetBitsFromISR() was called. * * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR * \ingroup EventGroup */ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; /** * event_groups.h *
	void xEventGroupDelete( EventGroupHandle_t xEventGroup );
 
* * Delete an event group that was previously created by a call to * xEventGroupCreate(). Tasks that are blocked on the event group will be * unblocked and obtain 0 as the event group's value. * * @param xEventGroup The event group being deleted. */ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; /* For internal use only. */ void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; #if (configUSE_TRACE_FACILITY == 1) UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION; #endif #ifdef __cplusplus } #endif #endif /* EVENT_GROUPS_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/list.h000066400000000000000000000503541357706137100234720ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /* * This is the list implementation used by the scheduler. While it is tailored * heavily for the schedulers needs, it is also available for use by * application code. * * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a * numeric value (xItemValue). Most of the time the lists are sorted in * descending item value order. * * Lists are created already containing one list item. The value of this * item is the maximum possible that can be stored, it is therefore always at * the end of the list and acts as a marker. The list member pxHead always * points to this marker - even though it is at the tail of the list. This * is because the tail contains a wrap back pointer to the true head of * the list. * * In addition to it's value, each list item contains a pointer to the next * item in the list (pxNext), a pointer to the list it is in (pxContainer) * and a pointer to back to the object that contains it. These later two * pointers are included for efficiency of list manipulation. There is * effectively a two way link between the object containing the list item and * the list item itself. * * * \page ListIntroduction List Implementation * \ingroup FreeRTOSIntro */ #ifndef INC_FREERTOS_H #error FreeRTOS.h must be included before list.h #endif #ifndef LIST_H #define LIST_H /* * The list structure members are modified from within interrupts, and therefore * by rights should be declared volatile. However, they are only modified in a * functionally atomic way (within critical sections of with the scheduler * suspended) and are either passed by reference into a function or indexed via * a volatile variable. Therefore, in all use cases tested so far, the volatile * qualifier can be omitted in order to provide a moderate performance * improvement without adversely affecting functional behaviour. The assembly * instructions generated by the IAR, ARM and GCC compilers when the respective * compiler's options were set for maximum optimisation has been inspected and * deemed to be as intended. That said, as compiler technology advances, and * especially if aggressive cross module optimisation is used (a use case that * has not been exercised to any great extend) then it is feasible that the * volatile qualifier will be needed for correct optimisation. It is expected * that a compiler removing essential code because, without the volatile * qualifier on the list structure members and with aggressive cross module * optimisation, the compiler deemed the code unnecessary will result in * complete and obvious failure of the scheduler. If this is ever experienced * then the volatile qualifier can be inserted in the relevant places within the * list structures by simply defining configLIST_VOLATILE to volatile in * FreeRTOSConfig.h (as per the example at the bottom of this comment block). * If configLIST_VOLATILE is not defined then the preprocessor directives below * will simply #define configLIST_VOLATILE away completely. * * To use volatile list structure members then add the following line to * FreeRTOSConfig.h (without the quotes): * "#define configLIST_VOLATILE volatile" */ #ifndef configLIST_VOLATILE #define configLIST_VOLATILE #endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ #ifdef __cplusplus extern "C" { #endif /* Macros that can be used to place known values within the list structures, then check that the known values do not get corrupted during the execution of the application. These may catch the list data structures being overwritten in memory. They will not catch data errors caused by incorrect configuration or use of FreeRTOS.*/ #if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) /* Define the macros to do nothing. */ #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE #define listFIRST_LIST_INTEGRITY_CHECK_VALUE #define listSECOND_LIST_INTEGRITY_CHECK_VALUE #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) #define listTEST_LIST_INTEGRITY( pxList ) #else /* Define macros that add new members into the list structures. */ #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; /* Define macros that set the new structure members to known values. */ #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE /* Define macros that will assert if one of the structure members does not contain its expected value. */ #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) #endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */ /* * Definition of the only type of object that a list can contain. */ struct xLIST_ITEM { listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ }; typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ struct xMINI_LIST_ITEM { listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ configLIST_VOLATILE TickType_t xItemValue; struct xLIST_ITEM * configLIST_VOLATILE pxNext; struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; }; typedef struct xMINI_LIST_ITEM MiniListItem_t; /* * Definition of the type of queue used by the scheduler. */ typedef struct xLIST { listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ configLIST_VOLATILE UBaseType_t uxNumberOfItems; ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ } List_t; /* * Access macro to set the owner of a list item. The owner of a list item * is the object (usually a TCB) that contains the list item. * * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER * \ingroup LinkedList */ #define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) /* * Access macro to get the owner of a list item. The owner of a list item * is the object (usually a TCB) that contains the list item. * * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER * \ingroup LinkedList */ #define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) /* * Access macro to set the value of the list item. In most cases the value is * used to sort the list in descending order. * * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE * \ingroup LinkedList */ #define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) /* * Access macro to retrieve the value of the list item. The value can * represent anything - for example the priority of a task, or the time at * which a task should be unblocked. * * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE * \ingroup LinkedList */ #define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) /* * Access macro to retrieve the value of the list item at the head of a given * list. * * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE * \ingroup LinkedList */ #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) /* * Return the list item at the head of the list. * * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY * \ingroup LinkedList */ #define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) /* * Return the list item at the head of the list. * * \page listGET_NEXT listGET_NEXT * \ingroup LinkedList */ #define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) /* * Return the list item that marks the end of the list * * \page listGET_END_MARKER listGET_END_MARKER * \ingroup LinkedList */ #define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) /* * Access macro to determine if a list contains any items. The macro will * only have the value true if the list is empty. * * \page listLIST_IS_EMPTY listLIST_IS_EMPTY * \ingroup LinkedList */ #define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ) /* * Access macro to return the number of items in the list. */ #define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) /* * Access function to obtain the owner of the next entry in a list. * * The list member pxIndex is used to walk through a list. Calling * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list * and returns that entry's pxOwner parameter. Using multiple calls to this * function it is therefore possible to move through every item contained in * a list. * * The pxOwner parameter of a list item is a pointer to the object that owns * the list item. In the scheduler this is normally a task control block. * The pxOwner parameter effectively creates a two way link between the list * item and its owner. * * @param pxTCB pxTCB is set to the address of the owner of the next list item. * @param pxList The list from which the next item owner is to be returned. * * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY * \ingroup LinkedList */ #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ { \ List_t * const pxConstList = ( pxList ); \ /* Increment the index to the next item and return the item, ensuring */ \ /* we don't return the marker used at the end of the list. */ \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ { \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ } \ ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ } /* * Access function to obtain the owner of the first entry in a list. Lists * are normally sorted in ascending item value order. * * This function returns the pxOwner member of the first item in the list. * The pxOwner parameter of a list item is a pointer to the object that owns * the list item. In the scheduler this is normally a task control block. * The pxOwner parameter effectively creates a two way link between the list * item and its owner. * * @param pxList The list from which the owner of the head item is to be * returned. * * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY * \ingroup LinkedList */ #define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) /* * Check to see if a list item is within a list. The list item maintains a * "container" pointer that points to the list it is in. All this macro does * is check to see if the container and the list match. * * @param pxList The list we want to know if the list item is within. * @param pxListItem The list item we want to know if is in the list. * @return pdTRUE if the list item is in the list, otherwise pdFALSE. */ #define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) /* * Return the list a list item is contained within (referenced from). * * @param pxListItem The list item being queried. * @return A pointer to the List_t object that references the pxListItem */ #define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer ) /* * This provides a crude means of knowing if a list has been initialised, as * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise() * function. */ #define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) /* * Must be called before a list is used! This initialises all the members * of the list structure and inserts the xListEnd item into the list as a * marker to the back of the list. * * @param pxList Pointer to the list being initialised. * * \page vListInitialise vListInitialise * \ingroup LinkedList */ void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION; /* * Must be called before a list item is used. This sets the list container to * null so the item does not think that it is already contained in a list. * * @param pxItem Pointer to the list item being initialised. * * \page vListInitialiseItem vListInitialiseItem * \ingroup LinkedList */ void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION; /* * Insert a list item into a list. The item will be inserted into the list in * a position determined by its item value (descending item value order). * * @param pxList The list into which the item is to be inserted. * * @param pxNewListItem The item that is to be placed in the list. * * \page vListInsert vListInsert * \ingroup LinkedList */ void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; /* * Insert a list item into a list. The item will be inserted in a position * such that it will be the last item within the list returned by multiple * calls to listGET_OWNER_OF_NEXT_ENTRY. * * The list member pxIndex is used to walk through a list. Calling * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list. * Placing an item in a list using vListInsertEnd effectively places the item * in the list position pointed to by pxIndex. This means that every other * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before * the pxIndex parameter again points to the item being inserted. * * @param pxList The list into which the item is to be inserted. * * @param pxNewListItem The list item to be inserted into the list. * * \page vListInsertEnd vListInsertEnd * \ingroup LinkedList */ void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; /* * Remove an item from a list. The list item has a pointer to the list that * it is in, so only the list item need be passed into the function. * * @param uxListRemove The item to be removed. The item will remove itself from * the list pointed to by it's pxContainer parameter. * * @return The number of items that remain in the list after the list item has * been removed. * * \page uxListRemove uxListRemove * \ingroup LinkedList */ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION; #ifdef __cplusplus } #endif #endif micropython-1.12/ports/cc3200/FreeRTOS/Source/include/mpu_prototypes.h000066400000000000000000000275171357706137100256350ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /* * When the MPU is used the standard (non MPU) API functions are mapped to * equivalents that start "MPU_", the prototypes for which are defined in this * header files. This will cause the application code to call the MPU_ version * which wraps the non-MPU version with privilege promoting then demoting code, * so the kernel code always runs will full privileges. */ #ifndef MPU_PROTOTYPES_H #define MPU_PROTOTYPES_H /* MPU versions of tasks.h API function. */ BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ); TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ); BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ); void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ); void MPU_vTaskDelay( const TickType_t xTicksToDelay ); void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ); BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ); UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t xTask ); eTaskState MPU_eTaskGetState( TaskHandle_t xTask ); void MPU_vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ); void MPU_vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ); void MPU_vTaskResume( TaskHandle_t xTaskToResume ); void MPU_vTaskStartScheduler( void ); void MPU_vTaskSuspendAll( void ); BaseType_t MPU_xTaskResumeAll( void ); TickType_t MPU_xTaskGetTickCount( void ); UBaseType_t MPU_uxTaskGetNumberOfTasks( void ); char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ); TaskHandle_t MPU_xTaskGetHandle( const char *pcNameToQuery ); UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ); TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ); void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ); void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ); BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ); TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ); UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ); void MPU_vTaskList( char * pcWriteBuffer ); void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ); BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ); BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ); BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask ); BaseType_t MPU_xTaskIncrementTick( void ); TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ); void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ); void MPU_vTaskMissedYield( void ); BaseType_t MPU_xTaskGetSchedulerState( void ); /* MPU versions of queue.h API function. */ BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ); BaseType_t MPU_xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ); UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ); UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ); void MPU_vQueueDelete( QueueHandle_t xQueue ); QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ); QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ); QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ); QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ); void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ); BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ); BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ); void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ); void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ); const char * MPU_pcQueueGetName( QueueHandle_t xQueue ); QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ); QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ); QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ); BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ); BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ); void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ); UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ); uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ); /* MPU versions of timers.h API function. */ TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ); TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer ); void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ); void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ); TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ); BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ); const char * MPU_pcTimerGetName( TimerHandle_t xTimer ); TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ); TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ); BaseType_t MPU_xTimerCreateTimerTask( void ); BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ); /* MPU versions of event_group.h API function. */ EventGroupHandle_t MPU_xEventGroupCreate( void ); EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ); EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ); EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ); EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ); void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ); UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup ); #endif /* MPU_PROTOTYPES_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/mpu_wrappers.h000066400000000000000000000234611357706137100252420ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef MPU_WRAPPERS_H #define MPU_WRAPPERS_H /* This file redefines API functions to be called through a wrapper macro, but only for ports that are using the MPU. */ #ifdef portUSING_MPU_WRAPPERS /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is included from queue.c or task.c to prevent it from having an effect within those files. */ #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* * Map standard (non MPU) API functions to equivalents that start * "MPU_". This will cause the application code to call the MPU_ * version, which wraps the non-MPU version with privilege promoting * then demoting code, so the kernel code always runs will full * privileges. */ /* Map standard tasks.h API functions to the MPU equivalents. */ #define xTaskCreate MPU_xTaskCreate #define xTaskCreateStatic MPU_xTaskCreateStatic #define xTaskCreateRestricted MPU_xTaskCreateRestricted #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions #define vTaskDelete MPU_vTaskDelete #define vTaskDelay MPU_vTaskDelay #define vTaskDelayUntil MPU_vTaskDelayUntil #define xTaskAbortDelay MPU_xTaskAbortDelay #define uxTaskPriorityGet MPU_uxTaskPriorityGet #define eTaskGetState MPU_eTaskGetState #define vTaskGetInfo MPU_vTaskGetInfo #define vTaskPrioritySet MPU_vTaskPrioritySet #define vTaskSuspend MPU_vTaskSuspend #define vTaskResume MPU_vTaskResume #define vTaskSuspendAll MPU_vTaskSuspendAll #define xTaskResumeAll MPU_xTaskResumeAll #define xTaskGetTickCount MPU_xTaskGetTickCount #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks #define pcTaskGetName MPU_pcTaskGetName #define xTaskGetHandle MPU_xTaskGetHandle #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle #define uxTaskGetSystemState MPU_uxTaskGetSystemState #define vTaskList MPU_vTaskList #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats #define xTaskGenericNotify MPU_xTaskGenericNotify #define xTaskNotifyWait MPU_xTaskNotifyWait #define ulTaskNotifyTake MPU_ulTaskNotifyTake #define xTaskNotifyStateClear MPU_xTaskNotifyStateClear #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState /* Map standard queue.h API functions to the MPU equivalents. */ #define xQueueGenericSend MPU_xQueueGenericSend #define xQueueGenericReceive MPU_xQueueGenericReceive #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable #define vQueueDelete MPU_vQueueDelete #define xQueueCreateMutex MPU_xQueueCreateMutex #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive #define xQueueGenericCreate MPU_xQueueGenericCreate #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic #define xQueueCreateSet MPU_xQueueCreateSet #define xQueueAddToSet MPU_xQueueAddToSet #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet #define xQueueSelectFromSet MPU_xQueueSelectFromSet #define xQueueGenericReset MPU_xQueueGenericReset #if( configQUEUE_REGISTRY_SIZE > 0 ) #define vQueueAddToRegistry MPU_vQueueAddToRegistry #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue #define pcQueueGetName MPU_pcQueueGetName #endif /* Map standard timer.h API functions to the MPU equivalents. */ #define xTimerCreate MPU_xTimerCreate #define xTimerCreateStatic MPU_xTimerCreateStatic #define pvTimerGetTimerID MPU_pvTimerGetTimerID #define vTimerSetTimerID MPU_vTimerSetTimerID #define xTimerIsTimerActive MPU_xTimerIsTimerActive #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall #define pcTimerGetName MPU_pcTimerGetName #define xTimerGetPeriod MPU_xTimerGetPeriod #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime #define xTimerGenericCommand MPU_xTimerGenericCommand /* Map standard event_group.h API functions to the MPU equivalents. */ #define xEventGroupCreate MPU_xEventGroupCreate #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic #define xEventGroupWaitBits MPU_xEventGroupWaitBits #define xEventGroupClearBits MPU_xEventGroupClearBits #define xEventGroupSetBits MPU_xEventGroupSetBits #define xEventGroupSync MPU_xEventGroupSync #define vEventGroupDelete MPU_vEventGroupDelete /* Remove the privileged function macro. */ #define PRIVILEGED_FUNCTION #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ /* Ensure API functions go in the privileged execution section. */ #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ #else /* portUSING_MPU_WRAPPERS */ #define PRIVILEGED_FUNCTION #define PRIVILEGED_DATA #define portUSING_MPU_WRAPPERS 0 #endif /* portUSING_MPU_WRAPPERS */ #endif /* MPU_WRAPPERS_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/portable.h000066400000000000000000000204351357706137100243240ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /*----------------------------------------------------------- * Portable layer API. Each function must be defined for each port. *----------------------------------------------------------*/ #ifndef PORTABLE_H #define PORTABLE_H /* Each FreeRTOS port has a unique portmacro.h header file. Originally a pre-processor definition was used to ensure the pre-processor found the correct portmacro.h file for the port being used. That scheme was deprecated in favour of setting the compiler's include path such that it found the correct portmacro.h file - removing the need for the constant and allowing the portmacro.h file to be located anywhere in relation to the port being used. Purely for reasons of backward compatibility the old method is still valid, but to make it clear that new projects should not use it, support for the port specific constants has been moved into the deprecated_definitions.h header file. */ #include "deprecated_definitions.h" /* If portENTER_CRITICAL is not defined then including deprecated_definitions.h did not result in a portmacro.h header file being included - and it should be included here. In this case the path to the correct portmacro.h header file must be set in the compiler's include path. */ #ifndef portENTER_CRITICAL #include "portmacro.h" #endif #if portBYTE_ALIGNMENT == 32 #define portBYTE_ALIGNMENT_MASK ( 0x001f ) #endif #if portBYTE_ALIGNMENT == 16 #define portBYTE_ALIGNMENT_MASK ( 0x000f ) #endif #if portBYTE_ALIGNMENT == 8 #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) #endif #if portBYTE_ALIGNMENT == 4 #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) #endif #if portBYTE_ALIGNMENT == 2 #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) #endif #if portBYTE_ALIGNMENT == 1 #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) #endif #ifndef portBYTE_ALIGNMENT_MASK #error "Invalid portBYTE_ALIGNMENT definition" #endif #ifndef portNUM_CONFIGURABLE_REGIONS #define portNUM_CONFIGURABLE_REGIONS 1 #endif #ifdef __cplusplus extern "C" { #endif #include "mpu_wrappers.h" /* * Setup the stack of a new task so it is ready to be placed under the * scheduler control. The registers have to be placed on the stack in * the order that the port expects to find them. * */ #if( portUSING_MPU_WRAPPERS == 1 ) StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; #else StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; #endif /* Used by heap_5.c. */ typedef struct HeapRegion { uint8_t *pucStartAddress; size_t xSizeInBytes; } HeapRegion_t; /* * Used to define multiple heap regions for use by heap_5.c. This function * must be called before any calls to pvPortMalloc() - not creating a task, * queue, semaphore, mutex, software timer, event group, etc. will result in * pvPortMalloc being called. * * pxHeapRegions passes in an array of HeapRegion_t structures - each of which * defines a region of memory that can be used as the heap. The array is * terminated by a HeapRegions_t structure that has a size of 0. The region * with the lowest start address must appear first in the array. */ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION; /* * Map to the memory management routines required for the port. */ void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; void vPortFree( void *pv ) PRIVILEGED_FUNCTION; void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; /* * Setup the hardware ready for the scheduler to take control. This generally * sets up a tick interrupt and sets timers for the correct tick frequency. */ BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; /* * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so * the hardware is left in its original condition after the scheduler stops * executing. */ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; /* * The structures and methods of manipulating the MPU are contained within the * port layer. * * Fills the xMPUSettings structure with the memory region information * contained in xRegions. */ #if( portUSING_MPU_WRAPPERS == 1 ) struct xMEMORY_REGION; void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION; #endif #ifdef __cplusplus } #endif #endif /* PORTABLE_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/projdefs.h000066400000000000000000000175271357706137100243400ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef PROJDEFS_H #define PROJDEFS_H /* * Defines the prototype to which task functions must conform. Defined in this * file to ensure the type is known before portable.h is included. */ typedef void (*TaskFunction_t)( void * ); /* Converts a time in milliseconds to a time in ticks. This macro can be overridden by a macro of the same name defined in FreeRTOSConfig.h in case the definition here is not suitable for your application. */ #ifndef pdMS_TO_TICKS #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) ) #endif #define pdFALSE ( ( BaseType_t ) 0 ) #define pdTRUE ( ( BaseType_t ) 1 ) #define pdPASS ( pdTRUE ) #define pdFAIL ( pdFALSE ) #define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) #define errQUEUE_FULL ( ( BaseType_t ) 0 ) /* FreeRTOS error definitions. */ #define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) #define errQUEUE_BLOCKED ( -4 ) #define errQUEUE_YIELD ( -5 ) /* Macros used for basic data corruption checks. */ #ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 #endif #if( configUSE_16_BIT_TICKS == 1 ) #define pdINTEGRITY_CHECK_VALUE 0x5a5a #else #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL #endif /* The following errno values are used by FreeRTOS+ components, not FreeRTOS itself. */ #define pdFREERTOS_ERRNO_NONE 0 /* No errors */ #define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */ #define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */ #define pdFREERTOS_ERRNO_EIO 5 /* I/O error */ #define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */ #define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */ #define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */ #define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */ #define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */ #define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */ #define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */ #define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */ #define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */ #define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */ #define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */ #define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */ #define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */ #define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */ #define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */ #define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */ #define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */ #define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */ #define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */ #define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */ #define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */ #define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ #define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ #define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ #define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ #define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ #define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ #define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */ #define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */ #define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */ #define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */ #define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */ #define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */ #define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */ #define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */ #define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */ /* The following endian values are used by FreeRTOS+ components, not FreeRTOS itself. */ #define pdFREERTOS_LITTLE_ENDIAN 0 #define pdFREERTOS_BIG_ENDIAN 1 #endif /* PROJDEFS_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/queue.h000066400000000000000000002000021357706137100236260ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef QUEUE_H #define QUEUE_H #ifndef INC_FREERTOS_H #error "include FreeRTOS.h" must appear in source files before "include queue.h" #endif #ifdef __cplusplus extern "C" { #endif /** * Type by which queues are referenced. For example, a call to xQueueCreate() * returns an QueueHandle_t variable that can then be used as a parameter to * xQueueSend(), xQueueReceive(), etc. */ typedef void * QueueHandle_t; /** * Type by which queue sets are referenced. For example, a call to * xQueueCreateSet() returns an xQueueSet variable that can then be used as a * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. */ typedef void * QueueSetHandle_t; /** * Queue sets can contain both queues and semaphores, so the * QueueSetMemberHandle_t is defined as a type to be used where a parameter or * return value can be either an QueueHandle_t or an SemaphoreHandle_t. */ typedef void * QueueSetMemberHandle_t; /* For internal use only. */ #define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) #define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) #define queueOVERWRITE ( ( BaseType_t ) 2 ) /* For internal use only. These definitions *must* match those in queue.c. */ #define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) #define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) #define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) #define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) #define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) #define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) /** * queue. h *
 QueueHandle_t xQueueCreate(
							  UBaseType_t uxQueueLength,
							  UBaseType_t uxItemSize
						  );
 * 
* * Creates a new queue instance, and returns a handle by which the new queue * can be referenced. * * Internally, within the FreeRTOS implementation, queues use two blocks of * memory. The first block is used to hold the queue's data structures. The * second block is used to hold items placed into the queue. If a queue is * created using xQueueCreate() then both blocks of memory are automatically * dynamically allocated inside the xQueueCreate() function. (see * http://www.freertos.org/a00111.html). If a queue is created using * xQueueCreateStatic() then the application writer must provide the memory that * will get used by the queue. xQueueCreateStatic() therefore allows a queue to * be created without using any dynamic memory allocation. * * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html * * @param uxQueueLength The maximum number of items that the queue can contain. * * @param uxItemSize The number of bytes each item in the queue will require. * Items are queued by copy, not by reference, so this is the number of bytes * that will be copied for each posted item. Each item on the queue must be * the same size. * * @return If the queue is successfully create then a handle to the newly * created queue is returned. If the queue cannot be created then 0 is * returned. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 };

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
	if( xQueue1 == 0 )
	{
		// Queue was not created and must not be used.
	}

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
	if( xQueue2 == 0 )
	{
		// Queue was not created and must not be used.
	}

	// ... Rest of task code.
 }
 
* \defgroup xQueueCreate xQueueCreate * \ingroup QueueManagement */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) ) #endif /** * queue. h *
 QueueHandle_t xQueueCreateStatic(
							  UBaseType_t uxQueueLength,
							  UBaseType_t uxItemSize,
							  uint8_t *pucQueueStorageBuffer,
							  StaticQueue_t *pxQueueBuffer
						  );
 * 
* * Creates a new queue instance, and returns a handle by which the new queue * can be referenced. * * Internally, within the FreeRTOS implementation, queues use two blocks of * memory. The first block is used to hold the queue's data structures. The * second block is used to hold items placed into the queue. If a queue is * created using xQueueCreate() then both blocks of memory are automatically * dynamically allocated inside the xQueueCreate() function. (see * http://www.freertos.org/a00111.html). If a queue is created using * xQueueCreateStatic() then the application writer must provide the memory that * will get used by the queue. xQueueCreateStatic() therefore allows a queue to * be created without using any dynamic memory allocation. * * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html * * @param uxQueueLength The maximum number of items that the queue can contain. * * @param uxItemSize The number of bytes each item in the queue will require. * Items are queued by copy, not by reference, so this is the number of bytes * that will be copied for each posted item. Each item on the queue must be * the same size. * * @param pucQueueStorageBuffer If uxItemSize is not zero then * pucQueueStorageBuffer must point to a uint8_t array that is at least large * enough to hold the maximum number of items that can be in the queue at any * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is * zero then pucQueueStorageBuffer can be NULL. * * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which * will be used to hold the queue's data structure. * * @return If the queue is created then a handle to the created queue is * returned. If pxQueueBuffer is NULL then NULL is returned. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 };

 #define QUEUE_LENGTH 10
 #define ITEM_SIZE sizeof( uint32_t )

 // xQueueBuffer will hold the queue structure.
 StaticQueue_t xQueueBuffer;

 // ucQueueStorage will hold the items posted to the queue.  Must be at least
 // [(queue length) * ( queue item size)] bytes long.
 uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
							ITEM_SIZE	  // The size of each item in the queue
							&( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
							&xQueueBuffer ); // The buffer that will hold the queue structure.

	// The queue is guaranteed to be created successfully as no dynamic memory
	// allocation is used.  Therefore xQueue1 is now a handle to a valid queue.

	// ... Rest of task code.
 }
 
* \defgroup xQueueCreateStatic xQueueCreateStatic * \ingroup QueueManagement */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * queue. h *
 BaseType_t xQueueSendToToFront(
								   QueueHandle_t	xQueue,
								   const void		*pvItemToQueue,
								   TickType_t		xTicksToWait
							   );
 * 
* * This is a macro that calls xQueueGenericSend(). * * Post an item to the front of a queue. The item is queued by copy, not by * reference. This function must not be called from an interrupt service * routine. See xQueueSendFromISR () for an alternative which may be used * in an ISR. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param xTicksToWait The maximum amount of time the task should block * waiting for space to become available on the queue, should it already * be full. The call will return immediately if this is set to 0 and the * queue is full. The time is defined in tick periods so the constant * portTICK_PERIOD_MS should be used to convert to real time if this is required. * * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 uint32_t ulVar = 10UL;

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );

	// ...

	if( xQueue1 != 0 )
	{
		// Send an uint32_t.  Wait for 10 ticks for space to become
		// available if necessary.
		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
		{
			// Failed to post the message, even after 10 ticks.
		}
	}

	if( xQueue2 != 0 )
	{
		// Send a pointer to a struct AMessage object.  Don't block if the
		// queue is already full.
		pxMessage = & xMessage;
		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
	}

	// ... Rest of task code.
 }
 
* \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ #define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) /** * queue. h *
 BaseType_t xQueueSendToBack(
								   QueueHandle_t	xQueue,
								   const void		*pvItemToQueue,
								   TickType_t		xTicksToWait
							   );
 * 
* * This is a macro that calls xQueueGenericSend(). * * Post an item to the back of a queue. The item is queued by copy, not by * reference. This function must not be called from an interrupt service * routine. See xQueueSendFromISR () for an alternative which may be used * in an ISR. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param xTicksToWait The maximum amount of time the task should block * waiting for space to become available on the queue, should it already * be full. The call will return immediately if this is set to 0 and the queue * is full. The time is defined in tick periods so the constant * portTICK_PERIOD_MS should be used to convert to real time if this is required. * * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 uint32_t ulVar = 10UL;

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );

	// ...

	if( xQueue1 != 0 )
	{
		// Send an uint32_t.  Wait for 10 ticks for space to become
		// available if necessary.
		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
		{
			// Failed to post the message, even after 10 ticks.
		}
	}

	if( xQueue2 != 0 )
	{
		// Send a pointer to a struct AMessage object.  Don't block if the
		// queue is already full.
		pxMessage = & xMessage;
		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
	}

	// ... Rest of task code.
 }
 
* \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ #define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) /** * queue. h *
 BaseType_t xQueueSend(
							  QueueHandle_t xQueue,
							  const void * pvItemToQueue,
							  TickType_t xTicksToWait
						 );
 * 
* * This is a macro that calls xQueueGenericSend(). It is included for * backward compatibility with versions of FreeRTOS.org that did not * include the xQueueSendToFront() and xQueueSendToBack() macros. It is * equivalent to xQueueSendToBack(). * * Post an item on a queue. The item is queued by copy, not by reference. * This function must not be called from an interrupt service routine. * See xQueueSendFromISR () for an alternative which may be used in an ISR. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param xTicksToWait The maximum amount of time the task should block * waiting for space to become available on the queue, should it already * be full. The call will return immediately if this is set to 0 and the * queue is full. The time is defined in tick periods so the constant * portTICK_PERIOD_MS should be used to convert to real time if this is required. * * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 uint32_t ulVar = 10UL;

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );

	// ...

	if( xQueue1 != 0 )
	{
		// Send an uint32_t.  Wait for 10 ticks for space to become
		// available if necessary.
		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
		{
			// Failed to post the message, even after 10 ticks.
		}
	}

	if( xQueue2 != 0 )
	{
		// Send a pointer to a struct AMessage object.  Don't block if the
		// queue is already full.
		pxMessage = & xMessage;
		xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
	}

	// ... Rest of task code.
 }
 
* \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ #define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) /** * queue. h *
 BaseType_t xQueueOverwrite(
							  QueueHandle_t xQueue,
							  const void * pvItemToQueue
						 );
 * 
* * Only for use with queues that have a length of one - so the queue is either * empty or full. * * Post an item on a queue. If the queue is already full then overwrite the * value held in the queue. The item is queued by copy, not by reference. * * This function must not be called from an interrupt service routine. * See xQueueOverwriteFromISR () for an alternative which may be used in an ISR. * * @param xQueue The handle of the queue to which the data is being sent. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and * therefore has the same return values as xQueueSendToFront(). However, pdPASS * is the only value that can be returned because xQueueOverwrite() will write * to the queue even when the queue is already full. * * Example usage:

 void vFunction( void *pvParameters )
 {
 QueueHandle_t xQueue;
 uint32_t ulVarToSend, ulValReceived;

	// Create a queue to hold one uint32_t value.  It is strongly
	// recommended *not* to use xQueueOverwrite() on queues that can
	// contain more than one value, and doing so will trigger an assertion
	// if configASSERT() is defined.
	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );

	// Write the value 10 to the queue using xQueueOverwrite().
	ulVarToSend = 10;
	xQueueOverwrite( xQueue, &ulVarToSend );

	// Peeking the queue should now return 10, but leave the value 10 in
	// the queue.  A block time of zero is used as it is known that the
	// queue holds a value.
	ulValReceived = 0;
	xQueuePeek( xQueue, &ulValReceived, 0 );

	if( ulValReceived != 10 )
	{
		// Error unless the item was removed by a different task.
	}

	// The queue is still full.  Use xQueueOverwrite() to overwrite the
	// value held in the queue with 100.
	ulVarToSend = 100;
	xQueueOverwrite( xQueue, &ulVarToSend );

	// This time read from the queue, leaving the queue empty once more.
	// A block time of 0 is used again.
	xQueueReceive( xQueue, &ulValReceived, 0 );

	// The value read should be the last value written, even though the
	// queue was already full when the value was written.
	if( ulValReceived != 100 )
	{
		// Error!
	}

	// ...
}
 
* \defgroup xQueueOverwrite xQueueOverwrite * \ingroup QueueManagement */ #define xQueueOverwrite( xQueue, pvItemToQueue ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE ) /** * queue. h *
 BaseType_t xQueueGenericSend(
									QueueHandle_t xQueue,
									const void * pvItemToQueue,
									TickType_t xTicksToWait
									BaseType_t xCopyPosition
								);
 * 
* * It is preferred that the macros xQueueSend(), xQueueSendToFront() and * xQueueSendToBack() are used in place of calling this function directly. * * Post an item on a queue. The item is queued by copy, not by reference. * This function must not be called from an interrupt service routine. * See xQueueSendFromISR () for an alternative which may be used in an ISR. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param xTicksToWait The maximum amount of time the task should block * waiting for space to become available on the queue, should it already * be full. The call will return immediately if this is set to 0 and the * queue is full. The time is defined in tick periods so the constant * portTICK_PERIOD_MS should be used to convert to real time if this is required. * * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the * item at the back of the queue, or queueSEND_TO_FRONT to place the item * at the front of the queue (for high priority messages). * * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 uint32_t ulVar = 10UL;

 void vATask( void *pvParameters )
 {
 QueueHandle_t xQueue1, xQueue2;
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 uint32_t values.
	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );

	// ...

	if( xQueue1 != 0 )
	{
		// Send an uint32_t.  Wait for 10 ticks for space to become
		// available if necessary.
		if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS )
		{
			// Failed to post the message, even after 10 ticks.
		}
	}

	if( xQueue2 != 0 )
	{
		// Send a pointer to a struct AMessage object.  Don't block if the
		// queue is already full.
		pxMessage = & xMessage;
		xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK );
	}

	// ... Rest of task code.
 }
 
* \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; /** * queue. h *
 BaseType_t xQueuePeek(
							 QueueHandle_t xQueue,
							 void *pvBuffer,
							 TickType_t xTicksToWait
						 );
* * This is a macro that calls the xQueueGenericReceive() function. * * Receive an item from a queue without removing the item from the queue. * The item is received by copy so a buffer of adequate size must be * provided. The number of bytes copied into the buffer was defined when * the queue was created. * * Successfully received items remain on the queue so will be returned again * by the next call, or a call to xQueueReceive(). * * This macro must not be used in an interrupt service routine. See * xQueuePeekFromISR() for an alternative that can be called from an interrupt * service routine. * * @param xQueue The handle to the queue from which the item is to be * received. * * @param pvBuffer Pointer to the buffer into which the received item will * be copied. * * @param xTicksToWait The maximum amount of time the task should block * waiting for an item to receive should the queue be empty at the time * of the call. The time is defined in tick periods so the constant * portTICK_PERIOD_MS should be used to convert to real time if this is required. * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue * is empty. * * @return pdTRUE if an item was successfully received from the queue, * otherwise pdFALSE. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 QueueHandle_t xQueue;

 // Task to create a queue and post a value.
 void vATask( void *pvParameters )
 {
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
	if( xQueue == 0 )
	{
		// Failed to create the queue.
	}

	// ...

	// Send a pointer to a struct AMessage object.  Don't block if the
	// queue is already full.
	pxMessage = & xMessage;
	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );

	// ... Rest of task code.
 }

 // Task to peek the data from the queue.
 void vADifferentTask( void *pvParameters )
 {
 struct AMessage *pxRxedMessage;

	if( xQueue != 0 )
	{
		// Peek a message on the created queue.  Block for 10 ticks if a
		// message is not immediately available.
		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
		{
			// pcRxedMessage now points to the struct AMessage variable posted
			// by vATask, but the item still remains on the queue.
		}
	}

	// ... Rest of task code.
 }
 
* \defgroup xQueueReceive xQueueReceive * \ingroup QueueManagement */ #define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) /** * queue. h *
 BaseType_t xQueuePeekFromISR(
									QueueHandle_t xQueue,
									void *pvBuffer,
								);
* * A version of xQueuePeek() that can be called from an interrupt service * routine (ISR). * * Receive an item from a queue without removing the item from the queue. * The item is received by copy so a buffer of adequate size must be * provided. The number of bytes copied into the buffer was defined when * the queue was created. * * Successfully received items remain on the queue so will be returned again * by the next call, or a call to xQueueReceive(). * * @param xQueue The handle to the queue from which the item is to be * received. * * @param pvBuffer Pointer to the buffer into which the received item will * be copied. * * @return pdTRUE if an item was successfully received from the queue, * otherwise pdFALSE. * * \defgroup xQueuePeekFromISR xQueuePeekFromISR * \ingroup QueueManagement */ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; /** * queue. h *
 BaseType_t xQueueReceive(
								 QueueHandle_t xQueue,
								 void *pvBuffer,
								 TickType_t xTicksToWait
							);
* * This is a macro that calls the xQueueGenericReceive() function. * * Receive an item from a queue. The item is received by copy so a buffer of * adequate size must be provided. The number of bytes copied into the buffer * was defined when the queue was created. * * Successfully received items are removed from the queue. * * This function must not be used in an interrupt service routine. See * xQueueReceiveFromISR for an alternative that can. * * @param xQueue The handle to the queue from which the item is to be * received. * * @param pvBuffer Pointer to the buffer into which the received item will * be copied. * * @param xTicksToWait The maximum amount of time the task should block * waiting for an item to receive should the queue be empty at the time * of the call. xQueueReceive() will return immediately if xTicksToWait * is zero and the queue is empty. The time is defined in tick periods so the * constant portTICK_PERIOD_MS should be used to convert to real time if this is * required. * * @return pdTRUE if an item was successfully received from the queue, * otherwise pdFALSE. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 QueueHandle_t xQueue;

 // Task to create a queue and post a value.
 void vATask( void *pvParameters )
 {
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
	if( xQueue == 0 )
	{
		// Failed to create the queue.
	}

	// ...

	// Send a pointer to a struct AMessage object.  Don't block if the
	// queue is already full.
	pxMessage = & xMessage;
	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );

	// ... Rest of task code.
 }

 // Task to receive from the queue.
 void vADifferentTask( void *pvParameters )
 {
 struct AMessage *pxRxedMessage;

	if( xQueue != 0 )
	{
		// Receive a message on the created queue.  Block for 10 ticks if a
		// message is not immediately available.
		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
		{
			// pcRxedMessage now points to the struct AMessage variable posted
			// by vATask.
		}
	}

	// ... Rest of task code.
 }
 
* \defgroup xQueueReceive xQueueReceive * \ingroup QueueManagement */ #define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) /** * queue. h *
 BaseType_t xQueueGenericReceive(
									   QueueHandle_t	xQueue,
									   void	*pvBuffer,
									   TickType_t	xTicksToWait
									   BaseType_t	xJustPeek
									);
* * It is preferred that the macro xQueueReceive() be used rather than calling * this function directly. * * Receive an item from a queue. The item is received by copy so a buffer of * adequate size must be provided. The number of bytes copied into the buffer * was defined when the queue was created. * * This function must not be used in an interrupt service routine. See * xQueueReceiveFromISR for an alternative that can. * * @param xQueue The handle to the queue from which the item is to be * received. * * @param pvBuffer Pointer to the buffer into which the received item will * be copied. * * @param xTicksToWait The maximum amount of time the task should block * waiting for an item to receive should the queue be empty at the time * of the call. The time is defined in tick periods so the constant * portTICK_PERIOD_MS should be used to convert to real time if this is required. * xQueueGenericReceive() will return immediately if the queue is empty and * xTicksToWait is 0. * * @param xJustPeek When set to true, the item received from the queue is not * actually removed from the queue - meaning a subsequent call to * xQueueReceive() will return the same item. When set to false, the item * being received from the queue is also removed from the queue. * * @return pdTRUE if an item was successfully received from the queue, * otherwise pdFALSE. * * Example usage:
 struct AMessage
 {
	char ucMessageID;
	char ucData[ 20 ];
 } xMessage;

 QueueHandle_t xQueue;

 // Task to create a queue and post a value.
 void vATask( void *pvParameters )
 {
 struct AMessage *pxMessage;

	// Create a queue capable of containing 10 pointers to AMessage structures.
	// These should be passed by pointer as they contain a lot of data.
	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
	if( xQueue == 0 )
	{
		// Failed to create the queue.
	}

	// ...

	// Send a pointer to a struct AMessage object.  Don't block if the
	// queue is already full.
	pxMessage = & xMessage;
	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );

	// ... Rest of task code.
 }

 // Task to receive from the queue.
 void vADifferentTask( void *pvParameters )
 {
 struct AMessage *pxRxedMessage;

	if( xQueue != 0 )
	{
		// Receive a message on the created queue.  Block for 10 ticks if a
		// message is not immediately available.
		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
		{
			// pcRxedMessage now points to the struct AMessage variable posted
			// by vATask.
		}
	}

	// ... Rest of task code.
 }
 
* \defgroup xQueueReceive xQueueReceive * \ingroup QueueManagement */ BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION; /** * queue. h *
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
* * Return the number of messages stored in a queue. * * @param xQueue A handle to the queue being queried. * * @return The number of messages available in the queue. * * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting * \ingroup QueueManagement */ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h *
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
* * Return the number of free spaces available in a queue. This is equal to the * number of items that can be sent to the queue before the queue becomes full * if no items are removed. * * @param xQueue A handle to the queue being queried. * * @return The number of spaces available in the queue. * * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting * \ingroup QueueManagement */ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h *
void vQueueDelete( QueueHandle_t xQueue );
* * Delete a queue - freeing all the memory allocated for storing of items * placed on the queue. * * @param xQueue A handle to the queue to be deleted. * * \defgroup vQueueDelete vQueueDelete * \ingroup QueueManagement */ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h *
 BaseType_t xQueueSendToFrontFromISR(
										 QueueHandle_t xQueue,
										 const void *pvItemToQueue,
										 BaseType_t *pxHigherPriorityTaskWoken
									  );
 
* * This is a macro that calls xQueueGenericSendFromISR(). * * Post an item to the front of a queue. It is safe to use this macro from * within an interrupt service routine. * * Items are queued by copy not reference so it is preferable to only * queue small items, especially when called from an ISR. In most cases * it would be preferable to store a pointer to the item being queued. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * * @return pdTRUE if the data was successfully sent to the queue, otherwise * errQUEUE_FULL. * * Example usage for buffered IO (where the ISR can obtain more than one value * per call):
 void vBufferISR( void )
 {
 char cIn;
 BaseType_t xHigherPrioritTaskWoken;

	// We have not woken a task at the start of the ISR.
	xHigherPriorityTaskWoken = pdFALSE;

	// Loop until the buffer is empty.
	do
	{
		// Obtain a byte from the buffer.
		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );

		// Post the byte.
		xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );

	} while( portINPUT_BYTE( BUFFER_COUNT ) );

	// Now the buffer is empty we can switch context if necessary.
	if( xHigherPriorityTaskWoken )
	{
		taskYIELD ();
	}
 }
 
* * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement */ #define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) /** * queue. h *
 BaseType_t xQueueSendToBackFromISR(
										 QueueHandle_t xQueue,
										 const void *pvItemToQueue,
										 BaseType_t *pxHigherPriorityTaskWoken
									  );
 
* * This is a macro that calls xQueueGenericSendFromISR(). * * Post an item to the back of a queue. It is safe to use this macro from * within an interrupt service routine. * * Items are queued by copy not reference so it is preferable to only * queue small items, especially when called from an ISR. In most cases * it would be preferable to store a pointer to the item being queued. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * * @return pdTRUE if the data was successfully sent to the queue, otherwise * errQUEUE_FULL. * * Example usage for buffered IO (where the ISR can obtain more than one value * per call):
 void vBufferISR( void )
 {
 char cIn;
 BaseType_t xHigherPriorityTaskWoken;

	// We have not woken a task at the start of the ISR.
	xHigherPriorityTaskWoken = pdFALSE;

	// Loop until the buffer is empty.
	do
	{
		// Obtain a byte from the buffer.
		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );

		// Post the byte.
		xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );

	} while( portINPUT_BYTE( BUFFER_COUNT ) );

	// Now the buffer is empty we can switch context if necessary.
	if( xHigherPriorityTaskWoken )
	{
		taskYIELD ();
	}
 }
 
* * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement */ #define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) /** * queue. h *
 BaseType_t xQueueOverwriteFromISR(
							  QueueHandle_t xQueue,
							  const void * pvItemToQueue,
							  BaseType_t *pxHigherPriorityTaskWoken
						 );
 * 
* * A version of xQueueOverwrite() that can be used in an interrupt service * routine (ISR). * * Only for use with queues that can hold a single item - so the queue is either * empty or full. * * Post an item on a queue. If the queue is already full then overwrite the * value held in the queue. The item is queued by copy, not by reference. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * * @return xQueueOverwriteFromISR() is a macro that calls * xQueueGenericSendFromISR(), and therefore has the same return values as * xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be * returned because xQueueOverwriteFromISR() will write to the queue even when * the queue is already full. * * Example usage:

 QueueHandle_t xQueue;

 void vFunction( void *pvParameters )
 {
 	// Create a queue to hold one uint32_t value.  It is strongly
	// recommended *not* to use xQueueOverwriteFromISR() on queues that can
	// contain more than one value, and doing so will trigger an assertion
	// if configASSERT() is defined.
	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
}

void vAnInterruptHandler( void )
{
// xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint32_t ulVarToSend, ulValReceived;

	// Write the value 10 to the queue using xQueueOverwriteFromISR().
	ulVarToSend = 10;
	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );

	// The queue is full, but calling xQueueOverwriteFromISR() again will still
	// pass because the value held in the queue will be overwritten with the
	// new value.
	ulVarToSend = 100;
	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );

	// Reading from the queue will now return 100.

	// ...

	if( xHigherPrioritytaskWoken == pdTRUE )
	{
		// Writing to the queue caused a task to unblock and the unblocked task
		// has a priority higher than or equal to the priority of the currently
		// executing task (the task this interrupt interrupted).  Perform a context
		// switch so this interrupt returns directly to the unblocked task.
		portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
	}
}
 
* \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR * \ingroup QueueManagement */ #define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE ) /** * queue. h *
 BaseType_t xQueueSendFromISR(
									 QueueHandle_t xQueue,
									 const void *pvItemToQueue,
									 BaseType_t *pxHigherPriorityTaskWoken
								);
 
* * This is a macro that calls xQueueGenericSendFromISR(). It is included * for backward compatibility with versions of FreeRTOS.org that did not * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() * macros. * * Post an item to the back of a queue. It is safe to use this function from * within an interrupt service routine. * * Items are queued by copy not reference so it is preferable to only * queue small items, especially when called from an ISR. In most cases * it would be preferable to store a pointer to the item being queued. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xQueueSendFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * * @return pdTRUE if the data was successfully sent to the queue, otherwise * errQUEUE_FULL. * * Example usage for buffered IO (where the ISR can obtain more than one value * per call):
 void vBufferISR( void )
 {
 char cIn;
 BaseType_t xHigherPriorityTaskWoken;

	// We have not woken a task at the start of the ISR.
	xHigherPriorityTaskWoken = pdFALSE;

	// Loop until the buffer is empty.
	do
	{
		// Obtain a byte from the buffer.
		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );

		// Post the byte.
		xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );

	} while( portINPUT_BYTE( BUFFER_COUNT ) );

	// Now the buffer is empty we can switch context if necessary.
	if( xHigherPriorityTaskWoken )
	{
		// Actual macro used here is port specific.
		portYIELD_FROM_ISR ();
	}
 }
 
* * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement */ #define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) /** * queue. h *
 BaseType_t xQueueGenericSendFromISR(
										   QueueHandle_t		xQueue,
										   const	void	*pvItemToQueue,
										   BaseType_t	*pxHigherPriorityTaskWoken,
										   BaseType_t	xCopyPosition
									   );
 
* * It is preferred that the macros xQueueSendFromISR(), * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place * of calling this function directly. xQueueGiveFromISR() is an * equivalent for use by semaphores that don't actually copy any data. * * Post an item on a queue. It is safe to use this function from within an * interrupt service routine. * * Items are queued by copy not reference so it is preferable to only * queue small items, especially when called from an ISR. In most cases * it would be preferable to store a pointer to the item being queued. * * @param xQueue The handle to the queue on which the item is to be posted. * * @param pvItemToQueue A pointer to the item that is to be placed on the * queue. The size of the items the queue will hold was defined when the * queue was created, so this many bytes will be copied from pvItemToQueue * into the queue storage area. * * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the * item at the back of the queue, or queueSEND_TO_FRONT to place the item * at the front of the queue (for high priority messages). * * @return pdTRUE if the data was successfully sent to the queue, otherwise * errQUEUE_FULL. * * Example usage for buffered IO (where the ISR can obtain more than one value * per call):
 void vBufferISR( void )
 {
 char cIn;
 BaseType_t xHigherPriorityTaskWokenByPost;

	// We have not woken a task at the start of the ISR.
	xHigherPriorityTaskWokenByPost = pdFALSE;

	// Loop until the buffer is empty.
	do
	{
		// Obtain a byte from the buffer.
		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );

		// Post each byte.
		xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );

	} while( portINPUT_BYTE( BUFFER_COUNT ) );

	// Now the buffer is empty we can switch context if necessary.  Note that the
	// name of the yield function required is port specific.
	if( xHigherPriorityTaskWokenByPost )
	{
		taskYIELD_YIELD_FROM_ISR();
	}
 }
 
* * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement */ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /** * queue. h *
 BaseType_t xQueueReceiveFromISR(
									   QueueHandle_t	xQueue,
									   void	*pvBuffer,
									   BaseType_t *pxTaskWoken
								   );
 * 
* * Receive an item from a queue. It is safe to use this function from within an * interrupt service routine. * * @param xQueue The handle to the queue from which the item is to be * received. * * @param pvBuffer Pointer to the buffer into which the received item will * be copied. * * @param pxTaskWoken A task may be blocked waiting for space to become * available on the queue. If xQueueReceiveFromISR causes such a task to * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will * remain unchanged. * * @return pdTRUE if an item was successfully received from the queue, * otherwise pdFALSE. * * Example usage:

 QueueHandle_t xQueue;

 // Function to create a queue and post some values.
 void vAFunction( void *pvParameters )
 {
 char cValueToPost;
 const TickType_t xTicksToWait = ( TickType_t )0xff;

	// Create a queue capable of containing 10 characters.
	xQueue = xQueueCreate( 10, sizeof( char ) );
	if( xQueue == 0 )
	{
		// Failed to create the queue.
	}

	// ...

	// Post some characters that will be used within an ISR.  If the queue
	// is full then this task will block for xTicksToWait ticks.
	cValueToPost = 'a';
	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
	cValueToPost = 'b';
	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );

	// ... keep posting characters ... this task may block when the queue
	// becomes full.

	cValueToPost = 'c';
	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
 }

 // ISR that outputs all the characters received on the queue.
 void vISR_Routine( void )
 {
 BaseType_t xTaskWokenByReceive = pdFALSE;
 char cRxedChar;

	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
	{
		// A character was received.  Output the character now.
		vOutputCharacter( cRxedChar );

		// If removing the character from the queue woke the task that was
		// posting onto the queue cTaskWokenByReceive will have been set to
		// pdTRUE.  No matter how many times this loop iterates only one
		// task will be woken.
	}

	if( cTaskWokenByPost != ( char ) pdFALSE;
	{
		taskYIELD ();
	}
 }
 
* \defgroup xQueueReceiveFromISR xQueueReceiveFromISR * \ingroup QueueManagement */ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /* * Utilities to query queues that are safe to use from an ISR. These utilities * should be used only from witin an ISR, or within a critical section. */ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /* * The functions defined above are for passing data to and from tasks. The * functions below are the equivalents for passing data to and from * co-routines. * * These functions are called from the co-routine macro implementation and * should not be called directly from application code. Instead use the macro * wrappers defined within croutine.h. */ BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ); BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken ); BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ); BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ); /* * For internal use only. Use xSemaphoreCreateMutex(), * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling * these functions directly. */ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION; void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; /* * For internal use only. Use xSemaphoreTakeMutexRecursive() or * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. */ BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION; /* * Reset a queue back to its original empty state. The return value is now * obsolete and is always set to pdPASS. */ #define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) /* * The registry is provided as a means for kernel aware debuggers to * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add * a queue, semaphore or mutex handle to the registry if you want the handle * to be available to a kernel aware debugger. If you are not using a kernel * aware debugger then this function can be ignored. * * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 * within FreeRTOSConfig.h for the registry to be available. Its value * does not effect the number of queues, semaphores and mutexes that can be * created - just the number that the registry can hold. * * @param xQueue The handle of the queue being added to the registry. This * is the handle returned by a call to xQueueCreate(). Semaphore and mutex * handles can also be passed in here. * * @param pcName The name to be associated with the handle. This is the * name that the kernel aware debugger will display. The queue registry only * stores a pointer to the string - so the string must be persistent (global or * preferably in ROM/Flash), not on the stack. */ #if( configQUEUE_REGISTRY_SIZE > 0 ) void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /* * The registry is provided as a means for kernel aware debuggers to * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add * a queue, semaphore or mutex handle to the registry if you want the handle * to be available to a kernel aware debugger, and vQueueUnregisterQueue() to * remove the queue, semaphore or mutex from the register. If you are not using * a kernel aware debugger then this function can be ignored. * * @param xQueue The handle of the queue being removed from the registry. */ #if( configQUEUE_REGISTRY_SIZE > 0 ) void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; #endif /* * The queue registry is provided as a means for kernel aware debuggers to * locate queues, semaphores and mutexes. Call pcQueueGetName() to look * up and return the name of a queue in the queue registry from the queue's * handle. * * @param xQueue The handle of the queue the name of which will be returned. * @return If the queue is in the registry then a pointer to the name of the * queue is returned. If the queue is not in the registry then NULL is * returned. */ #if( configQUEUE_REGISTRY_SIZE > 0 ) const char *pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /* * Generic version of the function used to creaet a queue using dynamic memory * allocation. This is called by other functions and macros that create other * RTOS objects that use the queue structure as their base. */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; #endif /* * Generic version of the function used to creaet a queue using dynamic memory * allocation. This is called by other functions and macros that create other * RTOS objects that use the queue structure as their base. */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; #endif /* * Queue sets provide a mechanism to allow a task to block (pend) on a read * operation from multiple queues or semaphores simultaneously. * * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this * function. * * A queue set must be explicitly created using a call to xQueueCreateSet() * before it can be used. Once created, standard FreeRTOS queues and semaphores * can be added to the set using calls to xQueueAddToSet(). * xQueueSelectFromSet() is then used to determine which, if any, of the queues * or semaphores contained in the set is in a state where a queue read or * semaphore take operation would be successful. * * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html * for reasons why queue sets are very rarely needed in practice as there are * simpler methods of blocking on multiple objects. * * Note 2: Blocking on a queue set that contains a mutex will not cause the * mutex holder to inherit the priority of the blocked task. * * Note 3: An additional 4 bytes of RAM is required for each space in a every * queue added to a queue set. Therefore counting semaphores that have a high * maximum count value should not be added to a queue set. * * Note 4: A receive (in the case of a queue) or take (in the case of a * semaphore) operation must not be performed on a member of a queue set unless * a call to xQueueSelectFromSet() has first returned a handle to that set member. * * @param uxEventQueueLength Queue sets store events that occur on * the queues and semaphores contained in the set. uxEventQueueLength specifies * the maximum number of events that can be queued at once. To be absolutely * certain that events are not lost uxEventQueueLength should be set to the * total sum of the length of the queues added to the set, where binary * semaphores and mutexes have a length of 1, and counting semaphores have a * length set by their maximum count value. Examples: * + If a queue set is to hold a queue of length 5, another queue of length 12, * and a binary semaphore, then uxEventQueueLength should be set to * (5 + 12 + 1), or 18. * + If a queue set is to hold three binary semaphores then uxEventQueueLength * should be set to (1 + 1 + 1 ), or 3. * + If a queue set is to hold a counting semaphore that has a maximum count of * 5, and a counting semaphore that has a maximum count of 3, then * uxEventQueueLength should be set to (5 + 3), or 8. * * @return If the queue set is created successfully then a handle to the created * queue set is returned. Otherwise NULL is returned. */ QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION; /* * Adds a queue or semaphore to a queue set that was previously created by a * call to xQueueCreateSet(). * * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this * function. * * Note 1: A receive (in the case of a queue) or take (in the case of a * semaphore) operation must not be performed on a member of a queue set unless * a call to xQueueSelectFromSet() has first returned a handle to that set member. * * @param xQueueOrSemaphore The handle of the queue or semaphore being added to * the queue set (cast to an QueueSetMemberHandle_t type). * * @param xQueueSet The handle of the queue set to which the queue or semaphore * is being added. * * @return If the queue or semaphore was successfully added to the queue set * then pdPASS is returned. If the queue could not be successfully added to the * queue set because it is already a member of a different queue set then pdFAIL * is returned. */ BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; /* * Removes a queue or semaphore from a queue set. A queue or semaphore can only * be removed from a set if the queue or semaphore is empty. * * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this * function. * * @param xQueueOrSemaphore The handle of the queue or semaphore being removed * from the queue set (cast to an QueueSetMemberHandle_t type). * * @param xQueueSet The handle of the queue set in which the queue or semaphore * is included. * * @return If the queue or semaphore was successfully removed from the queue set * then pdPASS is returned. If the queue was not in the queue set, or the * queue (or semaphore) was not empty, then pdFAIL is returned. */ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; /* * xQueueSelectFromSet() selects from the members of a queue set a queue or * semaphore that either contains data (in the case of a queue) or is available * to take (in the case of a semaphore). xQueueSelectFromSet() effectively * allows a task to block (pend) on a read operation on all the queues and * semaphores in a queue set simultaneously. * * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this * function. * * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html * for reasons why queue sets are very rarely needed in practice as there are * simpler methods of blocking on multiple objects. * * Note 2: Blocking on a queue set that contains a mutex will not cause the * mutex holder to inherit the priority of the blocked task. * * Note 3: A receive (in the case of a queue) or take (in the case of a * semaphore) operation must not be performed on a member of a queue set unless * a call to xQueueSelectFromSet() has first returned a handle to that set member. * * @param xQueueSet The queue set on which the task will (potentially) block. * * @param xTicksToWait The maximum time, in ticks, that the calling task will * remain in the Blocked state (with other tasks executing) to wait for a member * of the queue set to be ready for a successful queue read or semaphore take * operation. * * @return xQueueSelectFromSet() will return the handle of a queue (cast to * a QueueSetMemberHandle_t type) contained in the queue set that contains data, * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained * in the queue set that is available, or NULL if no such queue or semaphore * exists before before the specified block time expires. */ QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /* * A version of xQueueSelectFromSet() that can be used from an ISR. */ QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; /* Not public API functions. */ void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; #ifdef __cplusplus } #endif #endif /* QUEUE_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/semphr.h000066400000000000000000001401231357706137100240070ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef SEMAPHORE_H #define SEMAPHORE_H #ifndef INC_FREERTOS_H #error "include FreeRTOS.h" must appear in source files before "include semphr.h" #endif #include "queue.h" typedef QueueHandle_t SemaphoreHandle_t; #define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) #define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) #define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) /** * semphr. h *
vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
* * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a binary semaphore! * http://www.freertos.org/RTOS-task-notifications.html * * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the * xSemaphoreCreateBinary() function. Note that binary semaphores created using * the vSemaphoreCreateBinary() macro are created in a state such that the * first call to 'take' the semaphore would pass, whereas binary semaphores * created using xSemaphoreCreateBinary() are created in a state such that the * the semaphore must first be 'given' before it can be 'taken'. * * Macro that implements a semaphore by using the existing queue mechanism. * The queue length is 1 as this is a binary semaphore. The data size is 0 * as we don't want to actually store any data - we just want to know if the * queue is empty or full. * * This type of semaphore can be used for pure synchronisation between tasks or * between an interrupt and a task. The semaphore need not be given back once * obtained, so one task/interrupt can continuously 'give' the semaphore while * another continuously 'takes' the semaphore. For this reason this type of * semaphore does not use a priority inheritance mechanism. For an alternative * that does use priority inheritance see xSemaphoreCreateMutex(). * * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. * * Example usage:
 SemaphoreHandle_t xSemaphore = NULL;

 void vATask( void * pvParameters )
 {
    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
    // This is a macro so pass the variable in directly.
    vSemaphoreCreateBinary( xSemaphore );

    if( xSemaphore != NULL )
    {
        // The semaphore was created successfully.
        // The semaphore can now be used.
    }
 }
 
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * \ingroup Semaphores */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define vSemaphoreCreateBinary( xSemaphore ) \ { \ ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ if( ( xSemaphore ) != NULL ) \ { \ ( void ) xSemaphoreGive( ( xSemaphore ) ); \ } \ } #endif /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateBinary( void )
* * Creates a new binary semaphore instance, and returns a handle by which the * new semaphore can be referenced. * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a binary semaphore! * http://www.freertos.org/RTOS-task-notifications.html * * Internally, within the FreeRTOS implementation, binary semaphores use a block * of memory, in which the semaphore structure is stored. If a binary semaphore * is created using xSemaphoreCreateBinary() then the required memory is * automatically dynamically allocated inside the xSemaphoreCreateBinary() * function. (see http://www.freertos.org/a00111.html). If a binary semaphore * is created using xSemaphoreCreateBinaryStatic() then the application writer * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a * binary semaphore to be created without using any dynamic memory allocation. * * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this * xSemaphoreCreateBinary() function. Note that binary semaphores created using * the vSemaphoreCreateBinary() macro are created in a state such that the * first call to 'take' the semaphore would pass, whereas binary semaphores * created using xSemaphoreCreateBinary() are created in a state such that the * the semaphore must first be 'given' before it can be 'taken'. * * This type of semaphore can be used for pure synchronisation between tasks or * between an interrupt and a task. The semaphore need not be given back once * obtained, so one task/interrupt can continuously 'give' the semaphore while * another continuously 'takes' the semaphore. For this reason this type of * semaphore does not use a priority inheritance mechanism. For an alternative * that does use priority inheritance see xSemaphoreCreateMutex(). * * @return Handle to the created semaphore, or NULL if the memory required to * hold the semaphore's data structures could not be allocated. * * Example usage:
 SemaphoreHandle_t xSemaphore = NULL;

 void vATask( void * pvParameters )
 {
    // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
    // This is a macro so pass the variable in directly.
    xSemaphore = xSemaphoreCreateBinary();

    if( xSemaphore != NULL )
    {
        // The semaphore was created successfully.
        // The semaphore can now be used.
    }
 }
 
* \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary * \ingroup Semaphores */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) #endif /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )
* * Creates a new binary semaphore instance, and returns a handle by which the * new semaphore can be referenced. * * NOTE: In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a binary semaphore! * http://www.freertos.org/RTOS-task-notifications.html * * Internally, within the FreeRTOS implementation, binary semaphores use a block * of memory, in which the semaphore structure is stored. If a binary semaphore * is created using xSemaphoreCreateBinary() then the required memory is * automatically dynamically allocated inside the xSemaphoreCreateBinary() * function. (see http://www.freertos.org/a00111.html). If a binary semaphore * is created using xSemaphoreCreateBinaryStatic() then the application writer * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a * binary semaphore to be created without using any dynamic memory allocation. * * This type of semaphore can be used for pure synchronisation between tasks or * between an interrupt and a task. The semaphore need not be given back once * obtained, so one task/interrupt can continuously 'give' the semaphore while * another continuously 'takes' the semaphore. For this reason this type of * semaphore does not use a priority inheritance mechanism. For an alternative * that does use priority inheritance see xSemaphoreCreateMutex(). * * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, * which will then be used to hold the semaphore's data structure, removing the * need for the memory to be allocated dynamically. * * @return If the semaphore is created then a handle to the created semaphore is * returned. If pxSemaphoreBuffer is NULL then NULL is returned. * * Example usage:
 SemaphoreHandle_t xSemaphore = NULL;
 StaticSemaphore_t xSemaphoreBuffer;

 void vATask( void * pvParameters )
 {
    // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
    // The semaphore's data structures will be placed in the xSemaphoreBuffer
    // variable, the address of which is passed into the function.  The
    // function's parameter is not NULL, so the function will not attempt any
    // dynamic memory allocation, and therefore the function will not return
    // return NULL.
    xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );

    // Rest of task code goes here.
 }
 
* \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic * \ingroup Semaphores */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h *
xSemaphoreTake(
 *                   SemaphoreHandle_t xSemaphore,
 *                   TickType_t xBlockTime
 *               )
* * Macro to obtain a semaphore. The semaphore must have previously been * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or * xSemaphoreCreateCounting(). * * @param xSemaphore A handle to the semaphore being taken - obtained when * the semaphore was created. * * @param xBlockTime The time in ticks to wait for the semaphore to become * available. The macro portTICK_PERIOD_MS can be used to convert this to a * real time. A block time of zero can be used to poll the semaphore. A block * time of portMAX_DELAY can be used to block indefinitely (provided * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). * * @return pdTRUE if the semaphore was obtained. pdFALSE * if xBlockTime expired without the semaphore becoming available. * * Example usage:
 SemaphoreHandle_t xSemaphore = NULL;

 // A task that creates a semaphore.
 void vATask( void * pvParameters )
 {
    // Create the semaphore to guard a shared resource.
    xSemaphore = xSemaphoreCreateBinary();
 }

 // A task that uses the semaphore.
 void vAnotherTask( void * pvParameters )
 {
    // ... Do other things.

    if( xSemaphore != NULL )
    {
        // See if we can obtain the semaphore.  If the semaphore is not available
        // wait 10 ticks to see if it becomes free.
        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
        {
            // We were able to obtain the semaphore and can now access the
            // shared resource.

            // ...

            // We have finished accessing the shared resource.  Release the
            // semaphore.
            xSemaphoreGive( xSemaphore );
        }
        else
        {
            // We could not obtain the semaphore and can therefore not access
            // the shared resource safely.
        }
    }
 }
 
* \defgroup xSemaphoreTake xSemaphoreTake * \ingroup Semaphores */ #define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) /** * semphr. h * xSemaphoreTakeRecursive( * SemaphoreHandle_t xMutex, * TickType_t xBlockTime * ) * * Macro to recursively obtain, or 'take', a mutex type semaphore. * The mutex must have previously been created using a call to * xSemaphoreCreateRecursiveMutex(); * * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this * macro to be available. * * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). * * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * doesn't become available again until the owner has called * xSemaphoreGiveRecursive() for each successful 'take' request. For example, * if a task successfully 'takes' the same mutex 5 times then the mutex will * not be available to any other task until it has also 'given' the mutex back * exactly five times. * * @param xMutex A handle to the mutex being obtained. This is the * handle returned by xSemaphoreCreateRecursiveMutex(); * * @param xBlockTime The time in ticks to wait for the semaphore to become * available. The macro portTICK_PERIOD_MS can be used to convert this to a * real time. A block time of zero can be used to poll the semaphore. If * the task already owns the semaphore then xSemaphoreTakeRecursive() will * return immediately no matter what the value of xBlockTime. * * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime * expired without the semaphore becoming available. * * Example usage:
 SemaphoreHandle_t xMutex = NULL;

 // A task that creates a mutex.
 void vATask( void * pvParameters )
 {
    // Create the mutex to guard a shared resource.
    xMutex = xSemaphoreCreateRecursiveMutex();
 }

 // A task that uses the mutex.
 void vAnotherTask( void * pvParameters )
 {
    // ... Do other things.

    if( xMutex != NULL )
    {
        // See if we can obtain the mutex.  If the mutex is not available
        // wait 10 ticks to see if it becomes free.
        if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
        {
            // We were able to obtain the mutex and can now access the
            // shared resource.

            // ...
            // For some reason due to the nature of the code further calls to
			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
			// code these would not be just sequential calls as this would make
			// no sense.  Instead the calls are likely to be buried inside
			// a more complex call structure.
            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );

            // The mutex has now been 'taken' three times, so will not be
			// available to another task until it has also been given back
			// three times.  Again it is unlikely that real code would have
			// these calls sequentially, but instead buried in a more complex
			// call structure.  This is just for illustrative purposes.
            xSemaphoreGiveRecursive( xMutex );
			xSemaphoreGiveRecursive( xMutex );
			xSemaphoreGiveRecursive( xMutex );

			// Now the mutex can be taken by other tasks.
        }
        else
        {
            // We could not obtain the mutex and can therefore not access
            // the shared resource safely.
        }
    }
 }
 
* \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive * \ingroup Semaphores */ #if( configUSE_RECURSIVE_MUTEXES == 1 ) #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) #endif /** * semphr. h *
xSemaphoreGive( SemaphoreHandle_t xSemaphore )
* * Macro to release a semaphore. The semaphore must have previously been * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). * * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for * an alternative which can be used from an ISR. * * This macro must also not be used on semaphores created using * xSemaphoreCreateRecursiveMutex(). * * @param xSemaphore A handle to the semaphore being released. This is the * handle returned when the semaphore was created. * * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. * Semaphores are implemented using queues. An error can occur if there is * no space on the queue to post a message - indicating that the * semaphore was not first obtained correctly. * * Example usage:
 SemaphoreHandle_t xSemaphore = NULL;

 void vATask( void * pvParameters )
 {
    // Create the semaphore to guard a shared resource.
    xSemaphore = vSemaphoreCreateBinary();

    if( xSemaphore != NULL )
    {
        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
        {
            // We would expect this call to fail because we cannot give
            // a semaphore without first "taking" it!
        }

        // Obtain the semaphore - don't block if the semaphore is not
        // immediately available.
        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
        {
            // We now have the semaphore and can access the shared resource.

            // ...

            // We have finished accessing the shared resource so can free the
            // semaphore.
            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
            {
                // We would not expect this call to fail because we must have
                // obtained the semaphore to get here.
            }
        }
    }
 }
 
* \defgroup xSemaphoreGive xSemaphoreGive * \ingroup Semaphores */ #define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) /** * semphr. h *
xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )
* * Macro to recursively release, or 'give', a mutex type semaphore. * The mutex must have previously been created using a call to * xSemaphoreCreateRecursiveMutex(); * * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this * macro to be available. * * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). * * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * doesn't become available again until the owner has called * xSemaphoreGiveRecursive() for each successful 'take' request. For example, * if a task successfully 'takes' the same mutex 5 times then the mutex will * not be available to any other task until it has also 'given' the mutex back * exactly five times. * * @param xMutex A handle to the mutex being released, or 'given'. This is the * handle returned by xSemaphoreCreateMutex(); * * @return pdTRUE if the semaphore was given. * * Example usage:
 SemaphoreHandle_t xMutex = NULL;

 // A task that creates a mutex.
 void vATask( void * pvParameters )
 {
    // Create the mutex to guard a shared resource.
    xMutex = xSemaphoreCreateRecursiveMutex();
 }

 // A task that uses the mutex.
 void vAnotherTask( void * pvParameters )
 {
    // ... Do other things.

    if( xMutex != NULL )
    {
        // See if we can obtain the mutex.  If the mutex is not available
        // wait 10 ticks to see if it becomes free.
        if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
        {
            // We were able to obtain the mutex and can now access the
            // shared resource.

            // ...
            // For some reason due to the nature of the code further calls to
			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
			// code these would not be just sequential calls as this would make
			// no sense.  Instead the calls are likely to be buried inside
			// a more complex call structure.
            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );

            // The mutex has now been 'taken' three times, so will not be
			// available to another task until it has also been given back
			// three times.  Again it is unlikely that real code would have
			// these calls sequentially, it would be more likely that the calls
			// to xSemaphoreGiveRecursive() would be called as a call stack
			// unwound.  This is just for demonstrative purposes.
            xSemaphoreGiveRecursive( xMutex );
			xSemaphoreGiveRecursive( xMutex );
			xSemaphoreGiveRecursive( xMutex );

			// Now the mutex can be taken by other tasks.
        }
        else
        {
            // We could not obtain the mutex and can therefore not access
            // the shared resource safely.
        }
    }
 }
 
* \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive * \ingroup Semaphores */ #if( configUSE_RECURSIVE_MUTEXES == 1 ) #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) #endif /** * semphr. h *
 xSemaphoreGiveFromISR(
                          SemaphoreHandle_t xSemaphore,
                          BaseType_t *pxHigherPriorityTaskWoken
                      )
* * Macro to release a semaphore. The semaphore must have previously been * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting(). * * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) * must not be used with this macro. * * This macro can be used from an ISR. * * @param xSemaphore A handle to the semaphore being released. This is the * handle returned when the semaphore was created. * * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. * * Example usage:
 \#define LONG_TIME 0xffff
 \#define TICKS_TO_WAIT	10
 SemaphoreHandle_t xSemaphore = NULL;

 // Repetitive task.
 void vATask( void * pvParameters )
 {
    for( ;; )
    {
        // We want this task to run every 10 ticks of a timer.  The semaphore
        // was created before this task was started.

        // Block waiting for the semaphore to become available.
        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
        {
            // It is time to execute.

            // ...

            // We have finished our task.  Return to the top of the loop where
            // we will block on the semaphore until it is time to execute
            // again.  Note when using the semaphore for synchronisation with an
			// ISR in this manner there is no need to 'give' the semaphore back.
        }
    }
 }

 // Timer ISR
 void vTimerISR( void * pvParameters )
 {
 static uint8_t ucLocalTickCount = 0;
 static BaseType_t xHigherPriorityTaskWoken;

    // A timer tick has occurred.

    // ... Do other time functions.

    // Is it time for vATask () to run?
	xHigherPriorityTaskWoken = pdFALSE;
    ucLocalTickCount++;
    if( ucLocalTickCount >= TICKS_TO_WAIT )
    {
        // Unblock the task by releasing the semaphore.
        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );

        // Reset the count so we release the semaphore again in 10 ticks time.
        ucLocalTickCount = 0;
    }

    if( xHigherPriorityTaskWoken != pdFALSE )
    {
        // We can force a context switch here.  Context switching from an
        // ISR uses port specific syntax.  Check the demo task for your port
        // to find the syntax required.
    }
 }
 
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR * \ingroup Semaphores */ #define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) /** * semphr. h *
 xSemaphoreTakeFromISR(
                          SemaphoreHandle_t xSemaphore,
                          BaseType_t *pxHigherPriorityTaskWoken
                      )
* * Macro to take a semaphore from an ISR. The semaphore must have * previously been created with a call to xSemaphoreCreateBinary() or * xSemaphoreCreateCounting(). * * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) * must not be used with this macro. * * This macro can be used from an ISR, however taking a semaphore from an ISR * is not a common operation. It is likely to only be useful when taking a * counting semaphore when an interrupt is obtaining an object from a resource * pool (when the semaphore count indicates the number of resources available). * * @param xSemaphore A handle to the semaphore being taken. This is the * handle returned when the semaphore was created. * * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * * @return pdTRUE if the semaphore was successfully taken, otherwise * pdFALSE */ #define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateMutex( void )
* * Creates a new mutex type semaphore instance, and returns a handle by which * the new mutex can be referenced. * * Internally, within the FreeRTOS implementation, mutex semaphores use a block * of memory, in which the mutex structure is stored. If a mutex is created * using xSemaphoreCreateMutex() then the required memory is automatically * dynamically allocated inside the xSemaphoreCreateMutex() function. (see * http://www.freertos.org/a00111.html). If a mutex is created using * xSemaphoreCreateMutexStatic() then the application writer must provided the * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created * without using any dynamic memory allocation. * * Mutexes created using this function can be accessed using the xSemaphoreTake() * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and * xSemaphoreGiveRecursive() macros must not be used. * * This type of semaphore uses a priority inheritance mechanism so a task * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the * semaphore it is no longer required. * * Mutex type semaphores cannot be used from within interrupt service routines. * * See xSemaphoreCreateBinary() for an alternative implementation that can be * used for pure synchronisation (where one task or interrupt always 'gives' the * semaphore and another always 'takes' the semaphore) and from within interrupt * service routines. * * @return If the mutex was successfully created then a handle to the created * semaphore is returned. If there was not enough heap to allocate the mutex * data structures then NULL is returned. * * Example usage:
 SemaphoreHandle_t xSemaphore;

 void vATask( void * pvParameters )
 {
    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
    // This is a macro so pass the variable in directly.
    xSemaphore = xSemaphoreCreateMutex();

    if( xSemaphore != NULL )
    {
        // The semaphore was created successfully.
        // The semaphore can now be used.
    }
 }
 
* \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex * \ingroup Semaphores */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) #endif /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )
* * Creates a new mutex type semaphore instance, and returns a handle by which * the new mutex can be referenced. * * Internally, within the FreeRTOS implementation, mutex semaphores use a block * of memory, in which the mutex structure is stored. If a mutex is created * using xSemaphoreCreateMutex() then the required memory is automatically * dynamically allocated inside the xSemaphoreCreateMutex() function. (see * http://www.freertos.org/a00111.html). If a mutex is created using * xSemaphoreCreateMutexStatic() then the application writer must provided the * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created * without using any dynamic memory allocation. * * Mutexes created using this function can be accessed using the xSemaphoreTake() * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and * xSemaphoreGiveRecursive() macros must not be used. * * This type of semaphore uses a priority inheritance mechanism so a task * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the * semaphore it is no longer required. * * Mutex type semaphores cannot be used from within interrupt service routines. * * See xSemaphoreCreateBinary() for an alternative implementation that can be * used for pure synchronisation (where one task or interrupt always 'gives' the * semaphore and another always 'takes' the semaphore) and from within interrupt * service routines. * * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, * which will be used to hold the mutex's data structure, removing the need for * the memory to be allocated dynamically. * * @return If the mutex was successfully created then a handle to the created * mutex is returned. If pxMutexBuffer was NULL then NULL is returned. * * Example usage:
 SemaphoreHandle_t xSemaphore;
 StaticSemaphore_t xMutexBuffer;

 void vATask( void * pvParameters )
 {
    // A mutex cannot be used before it has been created.  xMutexBuffer is
    // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
    // attempted.
    xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );

    // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
    // so there is no need to check it.
 }
 
* \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic * \ingroup Semaphores */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
* * Creates a new recursive mutex type semaphore instance, and returns a handle * by which the new recursive mutex can be referenced. * * Internally, within the FreeRTOS implementation, recursive mutexs use a block * of memory, in which the mutex structure is stored. If a recursive mutex is * created using xSemaphoreCreateRecursiveMutex() then the required memory is * automatically dynamically allocated inside the * xSemaphoreCreateRecursiveMutex() function. (see * http://www.freertos.org/a00111.html). If a recursive mutex is created using * xSemaphoreCreateRecursiveMutexStatic() then the application writer must * provide the memory that will get used by the mutex. * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to * be created without using any dynamic memory allocation. * * Mutexes created using this macro can be accessed using the * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The * xSemaphoreTake() and xSemaphoreGive() macros must not be used. * * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * doesn't become available again until the owner has called * xSemaphoreGiveRecursive() for each successful 'take' request. For example, * if a task successfully 'takes' the same mutex 5 times then the mutex will * not be available to any other task until it has also 'given' the mutex back * exactly five times. * * This type of semaphore uses a priority inheritance mechanism so a task * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the * semaphore it is no longer required. * * Mutex type semaphores cannot be used from within interrupt service routines. * * See xSemaphoreCreateBinary() for an alternative implementation that can be * used for pure synchronisation (where one task or interrupt always 'gives' the * semaphore and another always 'takes' the semaphore) and from within interrupt * service routines. * * @return xSemaphore Handle to the created mutex semaphore. Should be of type * SemaphoreHandle_t. * * Example usage:
 SemaphoreHandle_t xSemaphore;

 void vATask( void * pvParameters )
 {
    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
    // This is a macro so pass the variable in directly.
    xSemaphore = xSemaphoreCreateRecursiveMutex();

    if( xSemaphore != NULL )
    {
        // The semaphore was created successfully.
        // The semaphore can now be used.
    }
 }
 
* \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex * \ingroup Semaphores */ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) #endif /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )
* * Creates a new recursive mutex type semaphore instance, and returns a handle * by which the new recursive mutex can be referenced. * * Internally, within the FreeRTOS implementation, recursive mutexs use a block * of memory, in which the mutex structure is stored. If a recursive mutex is * created using xSemaphoreCreateRecursiveMutex() then the required memory is * automatically dynamically allocated inside the * xSemaphoreCreateRecursiveMutex() function. (see * http://www.freertos.org/a00111.html). If a recursive mutex is created using * xSemaphoreCreateRecursiveMutexStatic() then the application writer must * provide the memory that will get used by the mutex. * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to * be created without using any dynamic memory allocation. * * Mutexes created using this macro can be accessed using the * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The * xSemaphoreTake() and xSemaphoreGive() macros must not be used. * * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * doesn't become available again until the owner has called * xSemaphoreGiveRecursive() for each successful 'take' request. For example, * if a task successfully 'takes' the same mutex 5 times then the mutex will * not be available to any other task until it has also 'given' the mutex back * exactly five times. * * This type of semaphore uses a priority inheritance mechanism so a task * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the * semaphore it is no longer required. * * Mutex type semaphores cannot be used from within interrupt service routines. * * See xSemaphoreCreateBinary() for an alternative implementation that can be * used for pure synchronisation (where one task or interrupt always 'gives' the * semaphore and another always 'takes' the semaphore) and from within interrupt * service routines. * * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, * which will then be used to hold the recursive mutex's data structure, * removing the need for the memory to be allocated dynamically. * * @return If the recursive mutex was successfully created then a handle to the * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is * returned. * * Example usage:
 SemaphoreHandle_t xSemaphore;
 StaticSemaphore_t xMutexBuffer;

 void vATask( void * pvParameters )
 {
    // A recursive semaphore cannot be used before it is created.  Here a
    // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
    // The address of xMutexBuffer is passed into the function, and will hold
    // the mutexes data structures - so no dynamic memory allocation will be
    // attempted.
    xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );

    // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
    // so there is no need to check it.
 }
 
* \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic * \ingroup Semaphores */ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )
* * Creates a new counting semaphore instance, and returns a handle by which the * new counting semaphore can be referenced. * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a counting semaphore! * http://www.freertos.org/RTOS-task-notifications.html * * Internally, within the FreeRTOS implementation, counting semaphores use a * block of memory, in which the counting semaphore structure is stored. If a * counting semaphore is created using xSemaphoreCreateCounting() then the * required memory is automatically dynamically allocated inside the * xSemaphoreCreateCounting() function. (see * http://www.freertos.org/a00111.html). If a counting semaphore is created * using xSemaphoreCreateCountingStatic() then the application writer can * instead optionally provide the memory that will get used by the counting * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting * semaphore to be created without using any dynamic memory allocation. * * Counting semaphores are typically used for two things: * * 1) Counting events. * * In this usage scenario an event handler will 'give' a semaphore each time * an event occurs (incrementing the semaphore count value), and a handler * task will 'take' a semaphore each time it processes an event * (decrementing the semaphore count value). The count value is therefore * the difference between the number of events that have occurred and the * number that have been processed. In this case it is desirable for the * initial count value to be zero. * * 2) Resource management. * * In this usage scenario the count value indicates the number of resources * available. To obtain control of a resource a task must first obtain a * semaphore - decrementing the semaphore count value. When the count value * reaches zero there are no free resources. When a task finishes with the * resource it 'gives' the semaphore back - incrementing the semaphore count * value. In this case it is desirable for the initial count value to be * equal to the maximum count value, indicating that all resources are free. * * @param uxMaxCount The maximum count value that can be reached. When the * semaphore reaches this value it can no longer be 'given'. * * @param uxInitialCount The count value assigned to the semaphore when it is * created. * * @return Handle to the created semaphore. Null if the semaphore could not be * created. * * Example usage:
 SemaphoreHandle_t xSemaphore;

 void vATask( void * pvParameters )
 {
 SemaphoreHandle_t xSemaphore = NULL;

    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
    // The max value to which the semaphore can count should be 10, and the
    // initial value assigned to the count should be 0.
    xSemaphore = xSemaphoreCreateCounting( 10, 0 );

    if( xSemaphore != NULL )
    {
        // The semaphore was created successfully.
        // The semaphore can now be used.
    }
 }
 
* \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting * \ingroup Semaphores */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) #endif /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )
* * Creates a new counting semaphore instance, and returns a handle by which the * new counting semaphore can be referenced. * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a counting semaphore! * http://www.freertos.org/RTOS-task-notifications.html * * Internally, within the FreeRTOS implementation, counting semaphores use a * block of memory, in which the counting semaphore structure is stored. If a * counting semaphore is created using xSemaphoreCreateCounting() then the * required memory is automatically dynamically allocated inside the * xSemaphoreCreateCounting() function. (see * http://www.freertos.org/a00111.html). If a counting semaphore is created * using xSemaphoreCreateCountingStatic() then the application writer must * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a * counting semaphore to be created without using any dynamic memory allocation. * * Counting semaphores are typically used for two things: * * 1) Counting events. * * In this usage scenario an event handler will 'give' a semaphore each time * an event occurs (incrementing the semaphore count value), and a handler * task will 'take' a semaphore each time it processes an event * (decrementing the semaphore count value). The count value is therefore * the difference between the number of events that have occurred and the * number that have been processed. In this case it is desirable for the * initial count value to be zero. * * 2) Resource management. * * In this usage scenario the count value indicates the number of resources * available. To obtain control of a resource a task must first obtain a * semaphore - decrementing the semaphore count value. When the count value * reaches zero there are no free resources. When a task finishes with the * resource it 'gives' the semaphore back - incrementing the semaphore count * value. In this case it is desirable for the initial count value to be * equal to the maximum count value, indicating that all resources are free. * * @param uxMaxCount The maximum count value that can be reached. When the * semaphore reaches this value it can no longer be 'given'. * * @param uxInitialCount The count value assigned to the semaphore when it is * created. * * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, * which will then be used to hold the semaphore's data structure, removing the * need for the memory to be allocated dynamically. * * @return If the counting semaphore was successfully created then a handle to * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL * then NULL is returned. * * Example usage:
 SemaphoreHandle_t xSemaphore;
 StaticSemaphore_t xSemaphoreBuffer;

 void vATask( void * pvParameters )
 {
 SemaphoreHandle_t xSemaphore = NULL;

    // Counting semaphore cannot be used before they have been created.  Create
    // a counting semaphore using xSemaphoreCreateCountingStatic().  The max
    // value to which the semaphore can count is 10, and the initial value
    // assigned to the count will be 0.  The address of xSemaphoreBuffer is
    // passed in and will be used to hold the semaphore structure, so no dynamic
    // memory allocation will be used.
    xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );

    // No memory allocation was attempted so xSemaphore cannot be NULL, so there
    // is no need to check its value.
 }
 
* \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic * \ingroup Semaphores */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h *
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
* * Delete a semaphore. This function must be used with care. For example, * do not delete a mutex type semaphore if the mutex is held by a task. * * @param xSemaphore A handle to the semaphore to be deleted. * * \defgroup vSemaphoreDelete vSemaphoreDelete * \ingroup Semaphores */ #define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) /** * semphr.h *
TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
* * If xMutex is indeed a mutex type semaphore, return the current mutex holder. * If xMutex is not a mutex type semaphore, or the mutex is available (not held * by a task), return NULL. * * Note: This is a good way of determining if the calling task is the mutex * holder, but not a good way of determining the identity of the mutex holder as * the holder may change between the function exiting and the returned value * being tested. */ #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) /** * semphr.h *
UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
* * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns * its current count value. If the semaphore is a binary semaphore then * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the * semaphore is not available. * */ #define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) #endif /* SEMAPHORE_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/task.h000066400000000000000000002656341357706137100234720ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef INC_TASK_H #define INC_TASK_H #ifndef INC_FREERTOS_H #error "include FreeRTOS.h must appear in source files before include task.h" #endif #include "list.h" #ifdef __cplusplus extern "C" { #endif /*----------------------------------------------------------- * MACROS AND DEFINITIONS *----------------------------------------------------------*/ #define tskKERNEL_VERSION_NUMBER "V9.0.0" #define tskKERNEL_VERSION_MAJOR 9 #define tskKERNEL_VERSION_MINOR 0 #define tskKERNEL_VERSION_BUILD 0 /** * task. h * * Type by which tasks are referenced. For example, a call to xTaskCreate * returns (via a pointer parameter) an TaskHandle_t variable that can then * be used as a parameter to vTaskDelete to delete the task. * * \defgroup TaskHandle_t TaskHandle_t * \ingroup Tasks */ typedef void * TaskHandle_t; /* * Defines the prototype to which the application task hook function must * conform. */ typedef BaseType_t (*TaskHookFunction_t)( void * ); /* Task states returned by eTaskGetState. */ typedef enum { eRunning = 0, /* A task is querying the state of itself, so must be running. */ eReady, /* The task being queried is in a read or pending ready list. */ eBlocked, /* The task being queried is in the Blocked state. */ eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */ eInvalid /* Used as an 'invalid state' value. */ } eTaskState; /* Actions that can be performed when vTaskNotify() is called. */ typedef enum { eNoAction = 0, /* Notify the task without updating its notify value. */ eSetBits, /* Set bits in the task's notification value. */ eIncrement, /* Increment the task's notification value. */ eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ } eNotifyAction; /* * Used internally only. */ typedef struct xTIME_OUT { BaseType_t xOverflowCount; TickType_t xTimeOnEntering; } TimeOut_t; /* * Defines the memory ranges allocated to the task when an MPU is used. */ typedef struct xMEMORY_REGION { void *pvBaseAddress; uint32_t ulLengthInBytes; uint32_t ulParameters; } MemoryRegion_t; /* * Parameters required to create an MPU protected task. */ typedef struct xTASK_PARAMETERS { TaskFunction_t pvTaskCode; const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ uint16_t usStackDepth; void *pvParameters; UBaseType_t uxPriority; StackType_t *puxStackBuffer; MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; } TaskParameters_t; /* Used with the uxTaskGetSystemState() function to return the state of each task in the system. */ typedef struct xTASK_STATUS { TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ UBaseType_t xTaskNumber; /* A number unique to the task. */ eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */ uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ } TaskStatus_t; /* Possible return values for eTaskConfirmSleepModeStatus(). */ typedef enum { eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ } eSleepModeStatus; /** * Defines the priority used by the idle task. This must not be modified. * * \ingroup TaskUtils */ #define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) /** * task. h * * Macro for forcing a context switch. * * \defgroup taskYIELD taskYIELD * \ingroup SchedulerControl */ #define taskYIELD() portYIELD() /** * task. h * * Macro to mark the start of a critical code region. Preemptive context * switches cannot occur when in a critical region. * * NOTE: This may alter the stack (depending on the portable implementation) * so must be used with care! * * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL * \ingroup SchedulerControl */ #define taskENTER_CRITICAL() portENTER_CRITICAL() #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() /** * task. h * * Macro to mark the end of a critical code region. Preemptive context * switches cannot occur when in a critical region. * * NOTE: This may alter the stack (depending on the portable implementation) * so must be used with care! * * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL * \ingroup SchedulerControl */ #define taskEXIT_CRITICAL() portEXIT_CRITICAL() #define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) /** * task. h * * Macro to disable all maskable interrupts. * * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS * \ingroup SchedulerControl */ #define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() /** * task. h * * Macro to enable microcontroller interrupts. * * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS * \ingroup SchedulerControl */ #define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() /* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is 0 to generate more optimal code when configASSERT() is defined as the constant is used in assert() statements. */ #define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) #define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) #define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) /*----------------------------------------------------------- * TASK CREATION API *----------------------------------------------------------*/ /** * task. h *
 BaseType_t xTaskCreate(
							  TaskFunction_t pvTaskCode,
							  const char * const pcName,
							  uint16_t usStackDepth,
							  void *pvParameters,
							  UBaseType_t uxPriority,
							  TaskHandle_t *pvCreatedTask
						  );
* * Create a new task and add it to the list of tasks that are ready to run. * * Internally, within the FreeRTOS implementation, tasks use two blocks of * memory. The first block is used to hold the task's data structures. The * second block is used by the task as its stack. If a task is created using * xTaskCreate() then both blocks of memory are automatically dynamically * allocated inside the xTaskCreate() function. (see * http://www.freertos.org/a00111.html). If a task is created using * xTaskCreateStatic() then the application writer must provide the required * memory. xTaskCreateStatic() therefore allows a task to be created without * using any dynamic memory allocation. * * See xTaskCreateStatic() for a version that does not use any dynamic memory * allocation. * * xTaskCreate() can only be used to create a task that has unrestricted * access to the entire microcontroller memory map. Systems that include MPU * support can alternatively create an MPU constrained task using * xTaskCreateRestricted(). * * @param pvTaskCode Pointer to the task entry function. Tasks * must be implemented to never return (i.e. continuous loop). * * @param pcName A descriptive name for the task. This is mainly used to * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default * is 16. * * @param usStackDepth The size of the task stack specified as the number of * variables the stack can hold - not the number of bytes. For example, if * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes * will be allocated for stack storage. * * @param pvParameters Pointer that will be used as the parameter for the task * being created. * * @param uxPriority The priority at which the task should run. Systems that * include MPU support can optionally create tasks in a privileged (system) * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For * example, to create a privileged task at priority 2 the uxPriority parameter * should be set to ( 2 | portPRIVILEGE_BIT ). * * @param pvCreatedTask Used to pass back a handle by which the created task * can be referenced. * * @return pdPASS if the task was successfully created and added to a ready * list, otherwise an error code defined in the file projdefs.h * * Example usage:
 // Task to be created.
 void vTaskCode( void * pvParameters )
 {
	 for( ;; )
	 {
		 // Task code goes here.
	 }
 }

 // Function that creates a task.
 void vOtherFunction( void )
 {
 static uint8_t ucParameterToPass;
 TaskHandle_t xHandle = NULL;

	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
	 // the new task attempts to access it.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
     configASSERT( xHandle );

	 // Use the handle to delete the task.
     if( xHandle != NULL )
     {
	     vTaskDelete( xHandle );
     }
 }
   
* \defgroup xTaskCreate xTaskCreate * \ingroup Tasks */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /** * task. h *
 TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
								 const char * const pcName,
								 uint32_t ulStackDepth,
								 void *pvParameters,
								 UBaseType_t uxPriority,
								 StackType_t *pxStackBuffer,
								 StaticTask_t *pxTaskBuffer );
* * Create a new task and add it to the list of tasks that are ready to run. * * Internally, within the FreeRTOS implementation, tasks use two blocks of * memory. The first block is used to hold the task's data structures. The * second block is used by the task as its stack. If a task is created using * xTaskCreate() then both blocks of memory are automatically dynamically * allocated inside the xTaskCreate() function. (see * http://www.freertos.org/a00111.html). If a task is created using * xTaskCreateStatic() then the application writer must provide the required * memory. xTaskCreateStatic() therefore allows a task to be created without * using any dynamic memory allocation. * * @param pvTaskCode Pointer to the task entry function. Tasks * must be implemented to never return (i.e. continuous loop). * * @param pcName A descriptive name for the task. This is mainly used to * facilitate debugging. The maximum length of the string is defined by * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. * * @param ulStackDepth The size of the task stack specified as the number of * variables the stack can hold - not the number of bytes. For example, if * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes * will be allocated for stack storage. * * @param pvParameters Pointer that will be used as the parameter for the task * being created. * * @param uxPriority The priority at which the task will run. * * @param pxStackBuffer Must point to a StackType_t array that has at least * ulStackDepth indexes - the array will then be used as the task's stack, * removing the need for the stack to be allocated dynamically. * * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will * then be used to hold the task's data structures, removing the need for the * memory to be allocated dynamically. * * @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will * be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer * are NULL then the task will not be created and * errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned. * * Example usage:

    // Dimensions the buffer that the task being created will use as its stack.
    // NOTE:  This is the number of words the stack will hold, not the number of
    // bytes.  For example, if each stack item is 32-bits, and this is set to 100,
    // then 400 bytes (100 * 32-bits) will be allocated.
    #define STACK_SIZE 200

    // Structure that will hold the TCB of the task being created.
    StaticTask_t xTaskBuffer;

    // Buffer that the task being created will use as its stack.  Note this is
    // an array of StackType_t variables.  The size of StackType_t is dependent on
    // the RTOS port.
    StackType_t xStack[ STACK_SIZE ];

    // Function that implements the task being created.
    void vTaskCode( void * pvParameters )
    {
        // The parameter value is expected to be 1 as 1 is passed in the
        // pvParameters value in the call to xTaskCreateStatic().
        configASSERT( ( uint32_t ) pvParameters == 1UL );

        for( ;; )
        {
            // Task code goes here.
        }
    }

    // Function that creates a task.
    void vOtherFunction( void )
    {
        TaskHandle_t xHandle = NULL;

        // Create the task without using any dynamic memory allocation.
        xHandle = xTaskCreateStatic(
                      vTaskCode,       // Function that implements the task.
                      "NAME",          // Text name for the task.
                      STACK_SIZE,      // Stack size in words, not bytes.
                      ( void * ) 1,    // Parameter passed into the task.
                      tskIDLE_PRIORITY,// Priority at which the task is created.
                      xStack,          // Array to use as the task's stack.
                      &xTaskBuffer );  // Variable to hold the task's data structure.

        // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
        // been created, and xHandle will be the task's handle.  Use the handle
        // to suspend the task.
        vTaskSuspend( xHandle );
    }
   
* \defgroup xTaskCreateStatic xTaskCreateStatic * \ingroup Tasks */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * task. h *
 BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
* * xTaskCreateRestricted() should only be used in systems that include an MPU * implementation. * * Create a new task and add it to the list of tasks that are ready to run. * The function parameters define the memory regions and associated access * permissions allocated to the task. * * @param pxTaskDefinition Pointer to a structure that contains a member * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API * documentation) plus an optional stack buffer and the memory region * definitions. * * @param pxCreatedTask Used to pass back a handle by which the created task * can be referenced. * * @return pdPASS if the task was successfully created and added to a ready * list, otherwise an error code defined in the file projdefs.h * * Example usage:
// Create an TaskParameters_t structure that defines the task to be created.
static const TaskParameters_t xCheckTaskParameters =
{
	vATask,		// pvTaskCode - the function that implements the task.
	"ATask",	// pcName - just a text name for the task to assist debugging.
	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
	NULL,		// pvParameters - passed into the task function as the function parameters.
	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.

	// xRegions - Allocate up to three separate memory regions for access by
	// the task, with appropriate access permissions.  Different processors have
	// different memory alignment requirements - refer to the FreeRTOS documentation
	// for full information.
	{
		// Base address					Length	Parameters
        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
	}
};

int main( void )
{
TaskHandle_t xHandle;

	// Create a task from the const structure defined above.  The task handle
	// is requested (the second parameter is not NULL) but in this case just for
	// demonstration purposes as its not actually used.
	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );

	// Start the scheduler.
	vTaskStartScheduler();

	// Will only get here if there was insufficient memory to create the idle
	// and/or timer task.
	for( ;; );
}
   
* \defgroup xTaskCreateRestricted xTaskCreateRestricted * \ingroup Tasks */ #if( portUSING_MPU_WRAPPERS == 1 ) BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION; #endif /** * task. h *
 void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
* * Memory regions are assigned to a restricted task when the task is created by * a call to xTaskCreateRestricted(). These regions can be redefined using * vTaskAllocateMPURegions(). * * @param xTask The handle of the task being updated. * * @param xRegions A pointer to an MemoryRegion_t structure that contains the * new memory region definitions. * * Example usage:
// Define an array of MemoryRegion_t structures that configures an MPU region
// allowing read/write access for 1024 bytes starting at the beginning of the
// ucOneKByte array.  The other two of the maximum 3 definable regions are
// unused so set to zero.
static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
{
	// Base address		Length		Parameters
	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
	{ 0,				0,			0 },
	{ 0,				0,			0 }
};

void vATask( void *pvParameters )
{
	// This task was created such that it has access to certain regions of
	// memory as defined by the MPU configuration.  At some point it is
	// desired that these MPU regions are replaced with that defined in the
	// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
	// for this purpose.  NULL is used as the task handle to indicate that this
	// function should modify the MPU regions of the calling task.
	vTaskAllocateMPURegions( NULL, xAltRegions );

	// Now the task can continue its function, but from this point on can only
	// access its stack and the ucOneKByte array (unless any other statically
	// defined or shared regions have been declared elsewhere).
}
   
* \defgroup xTaskCreateRestricted xTaskCreateRestricted * \ingroup Tasks */ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskDelete( TaskHandle_t xTask );
* * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. * See the configuration section for more information. * * Remove a task from the RTOS real time kernel's management. The task being * deleted will be removed from all ready, blocked, suspended and event lists. * * NOTE: The idle task is responsible for freeing the kernel allocated * memory from tasks that have been deleted. It is therefore important that * the idle task is not starved of microcontroller processing time if your * application makes any calls to vTaskDelete (). Memory allocated by the * task code is not automatically freed, and should be freed before the task * is deleted. * * See the demo application file death.c for sample code that utilises * vTaskDelete (). * * @param xTask The handle of the task to be deleted. Passing NULL will * cause the calling task to be deleted. * * Example usage:
 void vOtherFunction( void )
 {
 TaskHandle_t xHandle;

	 // Create the task, storing the handle.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

	 // Use the handle to delete the task.
	 vTaskDelete( xHandle );
 }
   
* \defgroup vTaskDelete vTaskDelete * \ingroup Tasks */ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; /*----------------------------------------------------------- * TASK CONTROL API *----------------------------------------------------------*/ /** * task. h *
void vTaskDelay( const TickType_t xTicksToDelay );
* * Delay a task for a given number of ticks. The actual time that the * task remains blocked depends on the tick rate. The constant * portTICK_PERIOD_MS can be used to calculate real time from the tick * rate - with the resolution of one tick period. * * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. * See the configuration section for more information. * * * vTaskDelay() specifies a time at which the task wishes to unblock relative to * the time at which vTaskDelay() is called. For example, specifying a block * period of 100 ticks will cause the task to unblock 100 ticks after * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method * of controlling the frequency of a periodic task as the path taken through the * code, as well as other task and interrupt activity, will effect the frequency * at which vTaskDelay() gets called and therefore the time at which the task * next executes. See vTaskDelayUntil() for an alternative API function designed * to facilitate fixed frequency execution. It does this by specifying an * absolute time (rather than a relative time) at which the calling task should * unblock. * * @param xTicksToDelay The amount of time, in tick periods, that * the calling task should block. * * Example usage: void vTaskFunction( void * pvParameters ) { // Block for 500ms. const TickType_t xDelay = 500 / portTICK_PERIOD_MS; for( ;; ) { // Simply toggle the LED every 500ms, blocking between each toggle. vToggleLED(); vTaskDelay( xDelay ); } } * \defgroup vTaskDelay vTaskDelay * \ingroup TaskCtrl */ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
* * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. * See the configuration section for more information. * * Delay a task until a specified time. This function can be used by periodic * tasks to ensure a constant execution frequency. * * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will * cause a task to block for the specified number of ticks from the time vTaskDelay () is * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed * execution frequency as the time between a task starting to execute and that task * calling vTaskDelay () may not be fixed [the task may take a different path though the * code between calls, or may get interrupted or preempted a different number of times * each time it executes]. * * Whereas vTaskDelay () specifies a wake time relative to the time at which the function * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to * unblock. * * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick * rate - with the resolution of one tick period. * * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the * task was last unblocked. The variable must be initialised with the current time * prior to its first use (see the example below). Following this the variable is * automatically updated within vTaskDelayUntil (). * * @param xTimeIncrement The cycle time period. The task will be unblocked at * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the * same xTimeIncrement parameter value will cause the task to execute with * a fixed interface period. * * Example usage:
 // Perform an action every 10 ticks.
 void vTaskFunction( void * pvParameters )
 {
 TickType_t xLastWakeTime;
 const TickType_t xFrequency = 10;

	 // Initialise the xLastWakeTime variable with the current time.
	 xLastWakeTime = xTaskGetTickCount ();
	 for( ;; )
	 {
		 // Wait for the next cycle.
		 vTaskDelayUntil( &xLastWakeTime, xFrequency );

		 // Perform action here.
	 }
 }
   
* \defgroup vTaskDelayUntil vTaskDelayUntil * \ingroup TaskCtrl */ void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; /** * task. h *
BaseType_t xTaskAbortDelay( TaskHandle_t xTask );
* * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this * function to be available. * * A task will enter the Blocked state when it is waiting for an event. The * event it is waiting for can be a temporal event (waiting for a time), such * as when vTaskDelay() is called, or an event on an object, such as when * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task * that is in the Blocked state is used in a call to xTaskAbortDelay() then the * task will leave the Blocked state, and return from whichever function call * placed the task into the Blocked state. * * @param xTask The handle of the task to remove from the Blocked state. * * @return If the task referenced by xTask was not in the Blocked state then * pdFAIL is returned. Otherwise pdPASS is returned. * * \defgroup xTaskAbortDelay xTaskAbortDelay * \ingroup TaskCtrl */ BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** * task. h *
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
* * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. * See the configuration section for more information. * * Obtain the priority of any task. * * @param xTask Handle of the task to be queried. Passing a NULL * handle results in the priority of the calling task being returned. * * @return The priority of xTask. * * Example usage:
 void vAFunction( void )
 {
 TaskHandle_t xHandle;

	 // Create a task, storing the handle.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

	 // ...

	 // Use the handle to obtain the priority of the created task.
	 // It was created with tskIDLE_PRIORITY, but may have changed
	 // it itself.
	 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
	 {
		 // The task has changed it's priority.
	 }

	 // ...

	 // Is our priority higher than the created task?
	 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
	 {
		 // Our priority (obtained using NULL handle) is higher.
	 }
 }
   
* \defgroup uxTaskPriorityGet uxTaskPriorityGet * \ingroup TaskCtrl */ UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** * task. h *
UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask );
* * A version of uxTaskPriorityGet() that can be used from an ISR. */ UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** * task. h *
eTaskState eTaskGetState( TaskHandle_t xTask );
* * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. * See the configuration section for more information. * * Obtain the state of any task. States are encoded by the eTaskState * enumerated type. * * @param xTask Handle of the task to be queried. * * @return The state of xTask at the time the function was called. Note the * state of the task might change between the function being called, and the * functions return value being tested by the calling task. */ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
* * configUSE_TRACE_FACILITY must be defined as 1 for this function to be * available. See the configuration section for more information. * * Populates a TaskStatus_t structure with information about a task. * * @param xTask Handle of the task being queried. If xTask is NULL then * information will be returned about the calling task. * * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be * filled with information about the task referenced by the handle passed using * the xTask parameter. * * @xGetFreeStackSpace The TaskStatus_t structure contains a member to report * the stack high water mark of the task being queried. Calculating the stack * high water mark takes a relatively long time, and can make the system * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to * allow the high water mark checking to be skipped. The high watermark value * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is * not set to pdFALSE; * * @param eState The TaskStatus_t structure contains a member to report the * state of the task being queried. Obtaining the task state is not as fast as * a simple assignment - so the eState parameter is provided to allow the state * information to be omitted from the TaskStatus_t structure. To obtain state * information then set eState to eInvalid - otherwise the value passed in * eState will be reported as the task state in the TaskStatus_t structure. * * Example usage:
 void vAFunction( void )
 {
 TaskHandle_t xHandle;
 TaskStatus_t xTaskDetails;

    // Obtain the handle of a task from its name.
    xHandle = xTaskGetHandle( "Task_Name" );

    // Check the handle is not NULL.
    configASSERT( xHandle );

    // Use the handle to obtain further information about the task.
    vTaskGetInfo( xHandle,
                  &xTaskDetails,
                  pdTRUE, // Include the high water mark in xTaskDetails.
                  eInvalid ); // Include the task state in xTaskDetails.
 }
   
* \defgroup vTaskGetInfo vTaskGetInfo * \ingroup TaskCtrl */ void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
* * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. * See the configuration section for more information. * * Set the priority of any task. * * A context switch will occur before the function returns if the priority * being set is higher than the currently executing task. * * @param xTask Handle to the task for which the priority is being set. * Passing a NULL handle results in the priority of the calling task being set. * * @param uxNewPriority The priority to which the task will be set. * * Example usage:
 void vAFunction( void )
 {
 TaskHandle_t xHandle;

	 // Create a task, storing the handle.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

	 // ...

	 // Use the handle to raise the priority of the created task.
	 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );

	 // ...

	 // Use a NULL handle to raise our priority to the same value.
	 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
 }
   
* \defgroup vTaskPrioritySet vTaskPrioritySet * \ingroup TaskCtrl */ void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
* * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * See the configuration section for more information. * * Suspend any task. When suspended a task will never get any microcontroller * processing time, no matter what its priority. * * Calls to vTaskSuspend are not accumulative - * i.e. calling vTaskSuspend () twice on the same task still only requires one * call to vTaskResume () to ready the suspended task. * * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL * handle will cause the calling task to be suspended. * * Example usage:
 void vAFunction( void )
 {
 TaskHandle_t xHandle;

	 // Create a task, storing the handle.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

	 // ...

	 // Use the handle to suspend the created task.
	 vTaskSuspend( xHandle );

	 // ...

	 // The created task will not run during this period, unless
	 // another task calls vTaskResume( xHandle ).

	 //...


	 // Suspend ourselves.
	 vTaskSuspend( NULL );

	 // We cannot get here unless another task calls vTaskResume
	 // with our handle as the parameter.
 }
   
* \defgroup vTaskSuspend vTaskSuspend * \ingroup TaskCtrl */ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskResume( TaskHandle_t xTaskToResume );
* * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * See the configuration section for more information. * * Resumes a suspended task. * * A task that has been suspended by one or more calls to vTaskSuspend () * will be made available for running again by a single call to * vTaskResume (). * * @param xTaskToResume Handle to the task being readied. * * Example usage:
 void vAFunction( void )
 {
 TaskHandle_t xHandle;

	 // Create a task, storing the handle.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );

	 // ...

	 // Use the handle to suspend the created task.
	 vTaskSuspend( xHandle );

	 // ...

	 // The created task will not run during this period, unless
	 // another task calls vTaskResume( xHandle ).

	 //...


	 // Resume the suspended task ourselves.
	 vTaskResume( xHandle );

	 // The created task will once again get microcontroller processing
	 // time in accordance with its priority within the system.
 }
   
* \defgroup vTaskResume vTaskResume * \ingroup TaskCtrl */ void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; /** * task. h *
void xTaskResumeFromISR( TaskHandle_t xTaskToResume );
* * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be * available. See the configuration section for more information. * * An implementation of vTaskResume() that can be called from within an ISR. * * A task that has been suspended by one or more calls to vTaskSuspend () * will be made available for running again by a single call to * xTaskResumeFromISR (). * * xTaskResumeFromISR() should not be used to synchronise a task with an * interrupt if there is a chance that the interrupt could arrive prior to the * task being suspended - as this can lead to interrupts being missed. Use of a * semaphore as a synchronisation mechanism would avoid this eventuality. * * @param xTaskToResume Handle to the task being readied. * * @return pdTRUE if resuming the task should result in a context switch, * otherwise pdFALSE. This is used by the ISR to determine if a context switch * may be required following the ISR. * * \defgroup vTaskResumeFromISR vTaskResumeFromISR * \ingroup TaskCtrl */ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; /*----------------------------------------------------------- * SCHEDULER CONTROL *----------------------------------------------------------*/ /** * task. h *
void vTaskStartScheduler( void );
* * Starts the real time kernel tick processing. After calling the kernel * has control over which tasks are executed and when. * * See the demo application file main.c for an example of creating * tasks and starting the kernel. * * Example usage:
 void vAFunction( void )
 {
	 // Create at least one task before starting the kernel.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );

	 // Start the real time kernel with preemption.
	 vTaskStartScheduler ();

	 // Will not get here unless a task calls vTaskEndScheduler ()
 }
   
* * \defgroup vTaskStartScheduler vTaskStartScheduler * \ingroup SchedulerControl */ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskEndScheduler( void );
* * NOTE: At the time of writing only the x86 real mode port, which runs on a PC * in place of DOS, implements this function. * * Stops the real time kernel tick. All created tasks will be automatically * deleted and multitasking (either preemptive or cooperative) will * stop. Execution then resumes from the point where vTaskStartScheduler () * was called, as if vTaskStartScheduler () had just returned. * * See the demo application file main. c in the demo/PC directory for an * example that uses vTaskEndScheduler (). * * vTaskEndScheduler () requires an exit function to be defined within the * portable layer (see vPortEndScheduler () in port. c for the PC port). This * performs hardware specific operations such as stopping the kernel tick. * * vTaskEndScheduler () will cause all of the resources allocated by the * kernel to be freed - but will not free resources allocated by application * tasks. * * Example usage:
 void vTaskCode( void * pvParameters )
 {
	 for( ;; )
	 {
		 // Task code goes here.

		 // At some point we want to end the real time kernel processing
		 // so call ...
		 vTaskEndScheduler ();
	 }
 }

 void vAFunction( void )
 {
	 // Create at least one task before starting the kernel.
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );

	 // Start the real time kernel with preemption.
	 vTaskStartScheduler ();

	 // Will only get here when the vTaskCode () task has called
	 // vTaskEndScheduler ().  When we get here we are back to single task
	 // execution.
 }
   
* * \defgroup vTaskEndScheduler vTaskEndScheduler * \ingroup SchedulerControl */ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskSuspendAll( void );
* * Suspends the scheduler without disabling interrupts. Context switches will * not occur while the scheduler is suspended. * * After calling vTaskSuspendAll () the calling task will continue to execute * without risk of being swapped out until a call to xTaskResumeAll () has been * made. * * API functions that have the potential to cause a context switch (for example, * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler * is suspended. * * Example usage:
 void vTask1( void * pvParameters )
 {
	 for( ;; )
	 {
		 // Task code goes here.

		 // ...

		 // At some point the task wants to perform a long operation during
		 // which it does not want to get swapped out.  It cannot use
		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
		 // operation may cause interrupts to be missed - including the
		 // ticks.

		 // Prevent the real time kernel swapping out the task.
		 vTaskSuspendAll ();

		 // Perform the operation here.  There is no need to use critical
		 // sections as we have all the microcontroller processing time.
		 // During this time interrupts will still operate and the kernel
		 // tick count will be maintained.

		 // ...

		 // The operation is complete.  Restart the kernel.
		 xTaskResumeAll ();
	 }
 }
   
* \defgroup vTaskSuspendAll vTaskSuspendAll * \ingroup SchedulerControl */ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; /** * task. h *
BaseType_t xTaskResumeAll( void );
* * Resumes scheduler activity after it was suspended by a call to * vTaskSuspendAll(). * * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks * that were previously suspended by a call to vTaskSuspend(). * * @return If resuming the scheduler caused a context switch then pdTRUE is * returned, otherwise pdFALSE is returned. * * Example usage:
 void vTask1( void * pvParameters )
 {
	 for( ;; )
	 {
		 // Task code goes here.

		 // ...

		 // At some point the task wants to perform a long operation during
		 // which it does not want to get swapped out.  It cannot use
		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
		 // operation may cause interrupts to be missed - including the
		 // ticks.

		 // Prevent the real time kernel swapping out the task.
		 vTaskSuspendAll ();

		 // Perform the operation here.  There is no need to use critical
		 // sections as we have all the microcontroller processing time.
		 // During this time interrupts will still operate and the real
		 // time kernel tick count will be maintained.

		 // ...

		 // The operation is complete.  Restart the kernel.  We want to force
		 // a context switch - but there is no point if resuming the scheduler
		 // caused a context switch already.
		 if( !xTaskResumeAll () )
		 {
			  taskYIELD ();
		 }
	 }
 }
   
* \defgroup xTaskResumeAll xTaskResumeAll * \ingroup SchedulerControl */ BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; /*----------------------------------------------------------- * TASK UTILITIES *----------------------------------------------------------*/ /** * task. h *
TickType_t xTaskGetTickCount( void );
* * @return The count of ticks since vTaskStartScheduler was called. * * \defgroup xTaskGetTickCount xTaskGetTickCount * \ingroup TaskUtils */ TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; /** * task. h *
TickType_t xTaskGetTickCountFromISR( void );
* * @return The count of ticks since vTaskStartScheduler was called. * * This is a version of xTaskGetTickCount() that is safe to be called from an * ISR - provided that TickType_t is the natural word size of the * microcontroller being used or interrupt nesting is either not supported or * not being used. * * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR * \ingroup TaskUtils */ TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; /** * task. h *
uint16_t uxTaskGetNumberOfTasks( void );
* * @return The number of tasks that the real time kernel is currently managing. * This includes all ready, blocked and suspended tasks. A task that * has been deleted but not yet freed by the idle task will also be * included in the count. * * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks * \ingroup TaskUtils */ UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; /** * task. h *
char *pcTaskGetName( TaskHandle_t xTaskToQuery );
* * @return The text (human readable) name of the task referenced by the handle * xTaskToQuery. A task can query its own name by either passing in its own * handle, or by setting xTaskToQuery to NULL. * * \defgroup pcTaskGetName pcTaskGetName * \ingroup TaskUtils */ char *pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** * task. h *
TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );
* * NOTE: This function takes a relatively long time to complete and should be * used sparingly. * * @return The handle of the task that has the human readable name pcNameToQuery. * NULL is returned if no matching name is found. INCLUDE_xTaskGetHandle * must be set to 1 in FreeRTOSConfig.h for pcTaskGetHandle() to be available. * * \defgroup pcTaskGetHandle pcTaskGetHandle * \ingroup TaskUtils */ TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** * task.h *
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
* * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for * this function to be available. * * Returns the high water mark of the stack associated with xTask. That is, * the minimum free stack space there has been (in words, so on a 32 bit machine * a value of 1 means 4 bytes) since the task started. The smaller the returned * number the closer the task has come to overflowing its stack. * * @param xTask Handle of the task associated with the stack to be checked. * Set xTask to NULL to check the stack of the calling task. * * @return The smallest amount of free stack space there has been (in words, so * actual spaces on the stack rather than bytes) since the task referenced by * xTask was created. */ UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /* When using trace macros it is sometimes necessary to include task.h before FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, so the following two prototypes will cause a compilation error. This can be fixed by simply guarding against the inclusion of these two prototypes unless they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration constant. */ #ifdef configUSE_APPLICATION_TASK_TAG #if configUSE_APPLICATION_TASK_TAG == 1 /** * task.h *
void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
* * Sets pxHookFunction to be the task hook function used by the task xTask. * Passing xTask as NULL has the effect of setting the calling tasks hook * function. */ void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION; /** * task.h *
void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
* * Returns the pxHookFunction value assigned to the task xTask. */ TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ #endif /* ifdef configUSE_APPLICATION_TASK_TAG */ #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) /* Each task contains an array of pointers that is dimensioned by the configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The kernel does not use the pointers itself, so the application writer can use the pointers for any purpose they wish. The following two functions are used to set and query a pointer respectively. */ void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) PRIVILEGED_FUNCTION; void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) PRIVILEGED_FUNCTION; #endif /** * task.h *
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
* * Calls the hook function associated with xTask. Passing xTask as NULL has * the effect of calling the Running tasks (the calling task) hook function. * * pvParameter is passed to the hook function for the task to interpret as it * wants. The return value is the value returned by the task hook function * registered by the user. */ BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) PRIVILEGED_FUNCTION; /** * xTaskGetIdleTaskHandle() is only available if * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. * * Simply returns the handle of the idle task. It is not valid to call * xTaskGetIdleTaskHandle() before the scheduler has been started. */ TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; /** * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for * uxTaskGetSystemState() to be available. * * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in * the system. TaskStatus_t structures contain, among other things, members * for the task handle, task name, task priority, task state, and total amount * of run time consumed by the task. See the TaskStatus_t structure * definition in this file for the full member list. * * NOTE: This function is intended for debugging use only as its use results in * the scheduler remaining suspended for an extended period. * * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. * The array must contain at least one TaskStatus_t structure for each task * that is under the control of the RTOS. The number of tasks under the control * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. * * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray * parameter. The size is specified as the number of indexes in the array, or * the number of TaskStatus_t structures contained in the array, not by the * number of bytes in the array. * * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the * total run time (as defined by the run time stats clock, see * http://www.freertos.org/rtos-run-time-stats.html) since the target booted. * pulTotalRunTime can be set to NULL to omit the total run time information. * * @return The number of TaskStatus_t structures that were populated by * uxTaskGetSystemState(). This should equal the number returned by the * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed * in the uxArraySize parameter was too small. * * Example usage:
    // This example demonstrates how a human readable table of run time stats
	// information is generated from raw data provided by uxTaskGetSystemState().
	// The human readable table is written to pcWriteBuffer
	void vTaskGetRunTimeStats( char *pcWriteBuffer )
	{
	TaskStatus_t *pxTaskStatusArray;
	volatile UBaseType_t uxArraySize, x;
	uint32_t ulTotalRunTime, ulStatsAsPercentage;

		// Make sure the write buffer does not contain a string.
		*pcWriteBuffer = 0x00;

		// Take a snapshot of the number of tasks in case it changes while this
		// function is executing.
		uxArraySize = uxTaskGetNumberOfTasks();

		// Allocate a TaskStatus_t structure for each task.  An array could be
		// allocated statically at compile time.
		pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );

		if( pxTaskStatusArray != NULL )
		{
			// Generate raw status information about each task.
			uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );

			// For percentage calculations.
			ulTotalRunTime /= 100UL;

			// Avoid divide by zero errors.
			if( ulTotalRunTime > 0 )
			{
				// For each populated position in the pxTaskStatusArray array,
				// format the raw data as human readable ASCII data
				for( x = 0; x < uxArraySize; x++ )
				{
					// What percentage of the total run time has the task used?
					// This will always be rounded down to the nearest integer.
					// ulTotalRunTimeDiv100 has already been divided by 100.
					ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;

					if( ulStatsAsPercentage > 0UL )
					{
						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
					}
					else
					{
						// If the percentage is zero here then the task has
						// consumed less than 1% of the total run time.
						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
					}

					pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
				}
			}

			// The array is no longer needed, free the memory it consumes.
			vPortFree( pxTaskStatusArray );
		}
	}
	
*/ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION; /** * task. h *
void vTaskList( char *pcWriteBuffer );
* * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must * both be defined as 1 for this function to be available. See the * configuration section of the FreeRTOS.org website for more information. * * NOTE 1: This function will disable interrupts for its duration. It is * not intended for normal application runtime use but as a debug aid. * * Lists all the current tasks, along with their current state and stack * usage high water mark. * * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or * suspended ('S'). * * PLEASE NOTE: * * This function is provided for convenience only, and is used by many of the * demo applications. Do not consider it to be part of the scheduler. * * vTaskList() calls uxTaskGetSystemState(), then formats part of the * uxTaskGetSystemState() output into a human readable table that displays task * names, states and stack usage. * * vTaskList() has a dependency on the sprintf() C library function that might * bloat the code size, use a lot of stack, and provide different results on * different platforms. An alternative, tiny, third party, and limited * functionality implementation of sprintf() is provided in many of the * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note * printf-stdarg.c does not provide a full snprintf() implementation!). * * It is recommended that production systems call uxTaskGetSystemState() * directly to get access to raw stats data, rather than indirectly through a * call to vTaskList(). * * @param pcWriteBuffer A buffer into which the above mentioned details * will be written, in ASCII form. This buffer is assumed to be large * enough to contain the generated report. Approximately 40 bytes per * task should be sufficient. * * \defgroup vTaskList vTaskList * \ingroup TaskUtils */ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** * task. h *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
* * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS * must both be defined as 1 for this function to be available. The application * must also then provide definitions for * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() * to configure a peripheral timer/counter and return the timers current count * value respectively. The counter should be at least 10 times the frequency of * the tick count. * * NOTE 1: This function will disable interrupts for its duration. It is * not intended for normal application runtime use but as a debug aid. * * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total * accumulated execution time being stored for each task. The resolution * of the accumulated time value depends on the frequency of the timer * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. * Calling vTaskGetRunTimeStats() writes the total execution time of each * task into a buffer, both as an absolute count value and as a percentage * of the total system execution time. * * NOTE 2: * * This function is provided for convenience only, and is used by many of the * demo applications. Do not consider it to be part of the scheduler. * * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the * uxTaskGetSystemState() output into a human readable table that displays the * amount of time each task has spent in the Running state in both absolute and * percentage terms. * * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function * that might bloat the code size, use a lot of stack, and provide different * results on different platforms. An alternative, tiny, third party, and * limited functionality implementation of sprintf() is provided in many of the * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note * printf-stdarg.c does not provide a full snprintf() implementation!). * * It is recommended that production systems call uxTaskGetSystemState() directly * to get access to raw stats data, rather than indirectly through a call to * vTaskGetRunTimeStats(). * * @param pcWriteBuffer A buffer into which the execution times will be * written, in ASCII form. This buffer is assumed to be large enough to * contain the generated report. Approximately 40 bytes per task should * be sufficient. * * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats * \ingroup TaskUtils */ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** * task. h *
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
* * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * function to be available. * * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * "notification value", which is a 32-bit unsigned integer (uint32_t). * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications * are a method of sending an event directly to a task without the need for such * an intermediary object. * * A notification sent to a task can optionally perform an action, such as * update, overwrite or increment the task's notification value. In that way * task notifications can be used to send data to a task, or be used as light * weight and fast binary or counting semaphores. * * A notification sent to a task will remain pending until it is cleared by the * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was * already in the Blocked state to wait for a notification when the notification * arrives then the task will automatically be removed from the Blocked state * (unblocked) and the notification cleared. * * A task can use xTaskNotifyWait() to [optionally] block to wait for a * notification to be pending, or ulTaskNotifyTake() to [optionally] block * to wait for its notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * * @param ulValue Data that can be sent with the notification. How the data is * used depends on the value of the eAction parameter. * * @param eAction Specifies how the notification updates the task's notification * value, if at all. Valid values for eAction are as follows: * * eSetBits - * The task's notification value is bitwise ORed with ulValue. xTaskNofify() * always returns pdPASS in this case. * * eIncrement - * The task's notification value is incremented. ulValue is not used and * xTaskNotify() always returns pdPASS in this case. * * eSetValueWithOverwrite - * The task's notification value is set to the value of ulValue, even if the * task being notified had not yet processed the previous notification (the * task already had a notification pending). xTaskNotify() always returns * pdPASS in this case. * * eSetValueWithoutOverwrite - * If the task being notified did not already have a notification pending then * the task's notification value is set to ulValue and xTaskNotify() will * return pdPASS. If the task being notified already had a notification * pending then no action is performed and pdFAIL is returned. * * eNoAction - * The task receives a notification without its notification value being * updated. ulValue is not used and xTaskNotify() always returns pdPASS in * this case. * * pulPreviousNotificationValue - * Can be used to pass out the subject task's notification value before any * bits are modified by the notify function. * * @return Dependent on the value of eAction. See the description of the * eAction parameter. * * \defgroup xTaskNotify xTaskNotify * \ingroup TaskNotifications */ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; #define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL ) #define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) /** * task. h *
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
* * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * function to be available. * * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * "notification value", which is a 32-bit unsigned integer (uint32_t). * * A version of xTaskNotify() that can be used from an interrupt service routine * (ISR). * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications * are a method of sending an event directly to a task without the need for such * an intermediary object. * * A notification sent to a task can optionally perform an action, such as * update, overwrite or increment the task's notification value. In that way * task notifications can be used to send data to a task, or be used as light * weight and fast binary or counting semaphores. * * A notification sent to a task will remain pending until it is cleared by the * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was * already in the Blocked state to wait for a notification when the notification * arrives then the task will automatically be removed from the Blocked state * (unblocked) and the notification cleared. * * A task can use xTaskNotifyWait() to [optionally] block to wait for a * notification to be pending, or ulTaskNotifyTake() to [optionally] block * to wait for its notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * * @param ulValue Data that can be sent with the notification. How the data is * used depends on the value of the eAction parameter. * * @param eAction Specifies how the notification updates the task's notification * value, if at all. Valid values for eAction are as follows: * * eSetBits - * The task's notification value is bitwise ORed with ulValue. xTaskNofify() * always returns pdPASS in this case. * * eIncrement - * The task's notification value is incremented. ulValue is not used and * xTaskNotify() always returns pdPASS in this case. * * eSetValueWithOverwrite - * The task's notification value is set to the value of ulValue, even if the * task being notified had not yet processed the previous notification (the * task already had a notification pending). xTaskNotify() always returns * pdPASS in this case. * * eSetValueWithoutOverwrite - * If the task being notified did not already have a notification pending then * the task's notification value is set to ulValue and xTaskNotify() will * return pdPASS. If the task being notified already had a notification * pending then no action is performed and pdFAIL is returned. * * eNoAction - * The task receives a notification without its notification value being * updated. ulValue is not used and xTaskNotify() always returns pdPASS in * this case. * * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * task to which the notification was sent to leave the Blocked state, and the * unblocked task has a priority higher than the currently running task. If * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should * be requested before the interrupt is exited. How a context switch is * requested from an ISR is dependent on the port - see the documentation page * for the port in use. * * @return Dependent on the value of eAction. See the description of the * eAction parameter. * * \defgroup xTaskNotify xTaskNotify * \ingroup TaskNotifications */ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; #define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) #define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) /** * task. h *
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
* * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * function to be available. * * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * "notification value", which is a 32-bit unsigned integer (uint32_t). * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications * are a method of sending an event directly to a task without the need for such * an intermediary object. * * A notification sent to a task can optionally perform an action, such as * update, overwrite or increment the task's notification value. In that way * task notifications can be used to send data to a task, or be used as light * weight and fast binary or counting semaphores. * * A notification sent to a task will remain pending until it is cleared by the * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was * already in the Blocked state to wait for a notification when the notification * arrives then the task will automatically be removed from the Blocked state * (unblocked) and the notification cleared. * * A task can use xTaskNotifyWait() to [optionally] block to wait for a * notification to be pending, or ulTaskNotifyTake() to [optionally] block * to wait for its notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. * * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value * will be cleared in the calling task's notification value before the task * checks to see if any notifications are pending, and optionally blocks if no * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have * the effect of resetting the task's notification value to 0. Setting * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. * * @param ulBitsToClearOnExit If a notification is pending or received before * the calling task exits the xTaskNotifyWait() function then the task's * notification value (see the xTaskNotify() API function) is passed out using * the pulNotificationValue parameter. Then any bits that are set in * ulBitsToClearOnExit will be cleared in the task's notification value (note * *pulNotificationValue is set before any bits are cleared). Setting * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL * (if limits.h is not included) will have the effect of resetting the task's * notification value to 0 before the function exits. Setting * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged * when the function exits (in which case the value passed out in * pulNotificationValue will match the task's notification value). * * @param pulNotificationValue Used to pass the task's notification value out * of the function. Note the value passed out will not be effected by the * clearing of any bits caused by ulBitsToClearOnExit being non-zero. * * @param xTicksToWait The maximum amount of time that the task should wait in * the Blocked state for a notification to be received, should a notification * not already be pending when xTaskNotifyWait() was called. The task * will not consume any processing time while it is in the Blocked state. This * is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be * used to convert a time specified in milliseconds to a time specified in * ticks. * * @return If a notification was received (including notifications that were * already pending when xTaskNotifyWait was called) then pdPASS is * returned. Otherwise pdFAIL is returned. * * \defgroup xTaskNotifyWait xTaskNotifyWait * \ingroup TaskNotifications */ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * task. h *
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
* * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro * to be available. * * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * "notification value", which is a 32-bit unsigned integer (uint32_t). * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications * are a method of sending an event directly to a task without the need for such * an intermediary object. * * A notification sent to a task can optionally perform an action, such as * update, overwrite or increment the task's notification value. In that way * task notifications can be used to send data to a task, or be used as light * weight and fast binary or counting semaphores. * * xTaskNotifyGive() is a helper macro intended for use when task notifications * are used as light weight and faster binary or counting semaphore equivalents. * Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function, * the equivalent action that instead uses a task notification is * xTaskNotifyGive(). * * When task notifications are being used as a binary or counting semaphore * equivalent then the task being notified should wait for the notification * using the ulTaskNotificationTake() API function rather than the * xTaskNotifyWait() API function. * * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the * eAction parameter set to eIncrement - so pdPASS is always returned. * * \defgroup xTaskNotifyGive xTaskNotifyGive * \ingroup TaskNotifications */ #define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL ) /** * task. h *
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
 *
 * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro
 * to be available.
 *
 * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
 * "notification value", which is a 32-bit unsigned integer (uint32_t).
 *
 * A version of xTaskNotifyGive() that can be called from an interrupt service
 * routine (ISR).
 *
 * Events can be sent to a task using an intermediary object.  Examples of such
 * objects are queues, semaphores, mutexes and event groups.  Task notifications
 * are a method of sending an event directly to a task without the need for such
 * an intermediary object.
 *
 * A notification sent to a task can optionally perform an action, such as
 * update, overwrite or increment the task's notification value.  In that way
 * task notifications can be used to send data to a task, or be used as light
 * weight and fast binary or counting semaphores.
 *
 * vTaskNotifyGiveFromISR() is intended for use when task notifications are
 * used as light weight and faster binary or counting semaphore equivalents.
 * Actual FreeRTOS semaphores are given from an ISR using the
 * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses
 * a task notification is vTaskNotifyGiveFromISR().
 *
 * When task notifications are being used as a binary or counting semaphore
 * equivalent then the task being notified should wait for the notification
 * using the ulTaskNotificationTake() API function rather than the
 * xTaskNotifyWait() API function.
 *
 * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
 *
 * @param xTaskToNotify The handle of the task being notified.  The handle to a
 * task can be returned from the xTaskCreate() API function used to create the
 * task, and the handle of the currently running task can be obtained by calling
 * xTaskGetCurrentTaskHandle().
 *
 * @param pxHigherPriorityTaskWoken  vTaskNotifyGiveFromISR() will set
 * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
 * task to which the notification was sent to leave the Blocked state, and the
 * unblocked task has a priority higher than the currently running task.  If
 * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch
 * should be requested before the interrupt is exited.  How a context switch is
 * requested from an ISR is dependent on the port - see the documentation page
 * for the port in use.
 *
 * \defgroup xTaskNotifyWait xTaskNotifyWait
 * \ingroup TaskNotifications
 */
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;

/**
 * task. h
 * 
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
* * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * function to be available. * * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * "notification value", which is a 32-bit unsigned integer (uint32_t). * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications * are a method of sending an event directly to a task without the need for such * an intermediary object. * * A notification sent to a task can optionally perform an action, such as * update, overwrite or increment the task's notification value. In that way * task notifications can be used to send data to a task, or be used as light * weight and fast binary or counting semaphores. * * ulTaskNotifyTake() is intended for use when a task notification is used as a * faster and lighter weight binary or counting semaphore alternative. Actual * FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the * equivalent action that instead uses a task notification is * ulTaskNotifyTake(). * * When a task is using its notification value as a binary or counting semaphore * other tasks should send notifications to it using the xTaskNotifyGive() * macro, or xTaskNotify() function with the eAction parameter set to * eIncrement. * * ulTaskNotifyTake() can either clear the task's notification value to * zero on exit, in which case the notification value acts like a binary * semaphore, or decrement the task's notification value on exit, in which case * the notification value acts like a counting semaphore. * * A task can use ulTaskNotifyTake() to [optionally] block to wait for a * the task's notification value to be non-zero. The task does not consume any * CPU time while it is in the Blocked state. * * Where as xTaskNotifyWait() will return when a notification is pending, * ulTaskNotifyTake() will return when the task's notification value is * not zero. * * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. * * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's * notification value is decremented when the function exits. In this way the * notification value acts like a counting semaphore. If xClearCountOnExit is * not pdFALSE then the task's notification value is cleared to zero when the * function exits. In this way the notification value acts like a binary * semaphore. * * @param xTicksToWait The maximum amount of time that the task should wait in * the Blocked state for the task's notification value to be greater than zero, * should the count not already be greater than zero when * ulTaskNotifyTake() was called. The task will not consume any processing * time while it is in the Blocked state. This is specified in kernel ticks, * the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time * specified in milliseconds to a time specified in ticks. * * @return The task's notification count before it is either cleared to zero or * decremented (see the xClearCountOnExit parameter). * * \defgroup ulTaskNotifyTake ulTaskNotifyTake * \ingroup TaskNotifications */ uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * task. h *
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
* * If the notification state of the task referenced by the handle xTask is * eNotified, then set the task's notification state to eNotWaitingNotification. * The task's notification value is not altered. Set xTask to NULL to clear the * notification state of the calling task. * * @return pdTRUE if the task's notification state was set to * eNotWaitingNotification, otherwise pdFALSE. * \defgroup xTaskNotifyStateClear xTaskNotifyStateClear * \ingroup TaskNotifications */ BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); /*----------------------------------------------------------- * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES *----------------------------------------------------------*/ /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. * * Called from the real time kernel tick (either preemptive or cooperative), * this increments the tick count and checks if any tasks that are blocked * for a finite period required removing from a blocked list and placing on * a ready list. If a non-zero value is returned then a context switch is * required because either: * + A task was removed from a blocked list because its timeout had expired, * or * + Time slicing is in use and there is a task of equal priority to the * currently running task. */ BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. * * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. * * Removes the calling task from the ready list and places it both * on the list of tasks waiting for a particular event, and the * list of delayed tasks. The task will be removed from both lists * and replaced on the ready list should either the event occur (and * there be no higher priority tasks waiting on the same event) or * the delay period expires. * * The 'unordered' version replaces the event list item value with the * xItemValue value, and inserts the list item at the end of the list. * * The 'ordered' version uses the existing event list item value (which is the * owning tasks priority) to insert the list item into the event list is task * priority order. * * @param pxEventList The list containing tasks that are blocked waiting * for the event to occur. * * @param xItemValue The item value to use for the event list item when the * event list is not ordered by task priority. * * @param xTicksToWait The maximum amount of time that the task should wait * for the event to occur. This is specified in kernel ticks,the constant * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time * period. */ void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. * * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. * * This function performs nearly the same function as vTaskPlaceOnEventList(). * The difference being that this function does not permit tasks to block * indefinitely, whereas vTaskPlaceOnEventList() does. * */ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. * * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. * * Removes a task from both the specified event list and the list of blocked * tasks, and places it on a ready queue. * * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called * if either an event occurs to unblock a task, or the block timeout period * expires. * * xTaskRemoveFromEventList() is used when the event list is in task priority * order. It removes the list item from the head of the event list as that will * have the highest priority owning task of all the tasks on the event list. * xTaskRemoveFromUnorderedEventList() is used when the event list is not * ordered and the event list items hold something other than the owning tasks * priority. In this case the event list item value is updated to the value * passed in the xItemValue parameter. * * @return pdTRUE if the task being removed has a higher priority than the task * making the call, otherwise pdFALSE. */ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION; BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. * * Sets the pointer to the current TCB to the TCB of the highest priority task * that is ready to run. */ void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; /* * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY * THE EVENT BITS MODULE. */ TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; /* * Return the handle of the calling task. */ TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; /* * Capture the current time status for future reference. */ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; /* * Compare the time status now with that previously captured to see if the * timeout has expired. */ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION; /* * Shortcut used by the queue implementation to prevent unnecessary call to * taskYIELD(); */ void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; /* * Returns the scheduler state as taskSCHEDULER_RUNNING, * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. */ BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; /* * Raises the priority of the mutex holder to that of the calling task should * the mutex holder have a priority less than the calling task. */ void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; /* * Set the priority of a task back to its proper priority in the case that it * inherited a higher priority while it was holding a semaphore. */ BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; /* * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. */ UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /* * Set the uxTaskNumber of the task referenced by the xTask parameter to * uxHandle. */ void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; /* * Only available when configUSE_TICKLESS_IDLE is set to 1. * If tickless mode is being used, or a low power mode is implemented, then * the tick interrupt will not execute during idle periods. When this is the * case, the tick count value maintained by the scheduler needs to be kept up * to date with the actual execution time by being skipped forward by a time * equal to the idle period. */ void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; /* * Only avilable when configUSE_TICKLESS_IDLE is set to 1. * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port * specific sleep function to determine if it is ok to proceed with the sleep, * and if it is ok to proceed, if it is ok to sleep indefinitely. * * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only * called with the scheduler suspended, not from within a critical section. It * is therefore possible for an interrupt to request a context switch between * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being * entered. eTaskConfirmSleepModeStatus() should be called from a short * critical section between the timer being stopped and the sleep mode being * entered to ensure it is ok to proceed into the sleep mode. */ eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; /* * For internal use only. Increment the mutex held count when a mutex is * taken and return the handle of the task that has taken the mutex. */ void *pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; #ifdef __cplusplus } #endif #endif /* INC_TASK_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/timers.h000066400000000000000000001667771357706137100240430ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef TIMERS_H #define TIMERS_H #ifndef INC_FREERTOS_H #error "include FreeRTOS.h must appear in source files before include timers.h" #endif /*lint -e537 This headers are only multiply included if the application code happens to also be including task.h. */ #include "task.h" /*lint +e537 */ #ifdef __cplusplus extern "C" { #endif /*----------------------------------------------------------- * MACROS AND DEFINITIONS *----------------------------------------------------------*/ /* IDs for commands that can be sent/received on the timer queue. These are to be used solely through the macros that make up the public software timer API, as defined below. The commands that are sent from interrupts must use the highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task or interrupt version of the queue send function should be used. */ #define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) #define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) #define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) #define tmrCOMMAND_START ( ( BaseType_t ) 1 ) #define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) #define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) #define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) #define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) #define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) #define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) #define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) #define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) #define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) /** * Type by which software timers are referenced. For example, a call to * xTimerCreate() returns an TimerHandle_t variable that can then be used to * reference the subject timer in calls to other software timer API functions * (for example, xTimerStart(), xTimerReset(), etc.). */ typedef void * TimerHandle_t; /* * Defines the prototype to which timer callback functions must conform. */ typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer ); /* * Defines the prototype to which functions used with the * xTimerPendFunctionCallFromISR() function must conform. */ typedef void (*PendedFunction_t)( void *, uint32_t ); /** * TimerHandle_t xTimerCreate( const char * const pcTimerName, * TickType_t xTimerPeriodInTicks, * UBaseType_t uxAutoReload, * void * pvTimerID, * TimerCallbackFunction_t pxCallbackFunction ); * * Creates a new software timer instance, and returns a handle by which the * created software timer can be referenced. * * Internally, within the FreeRTOS implementation, software timers use a block * of memory, in which the timer data structure is stored. If a software timer * is created using xTimerCreate() then the required memory is automatically * dynamically allocated inside the xTimerCreate() function. (see * http://www.freertos.org/a00111.html). If a software timer is created using * xTimerCreateStatic() then the application writer must provide the memory that * will get used by the software timer. xTimerCreateStatic() therefore allows a * software timer to be created without using any dynamic memory allocation. * * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and * xTimerChangePeriodFromISR() API functions can all be used to transition a * timer into the active state. * * @param pcTimerName A text name that is assigned to the timer. This is done * purely to assist debugging. The kernel itself only ever references a timer * by its handle, and never by its name. * * @param xTimerPeriodInTicks The timer period. The time is defined in tick * periods so the constant portTICK_PERIOD_MS can be used to convert a time that * has been specified in milliseconds. For example, if the timer must expire * after 100 ticks, then xTimerPeriodInTicks should be set to 100. * Alternatively, if the timer must expire after 500ms, then xPeriod can be set * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or * equal to 1000. * * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and * enter the dormant state after it expires. * * @param pvTimerID An identifier that is assigned to the timer being created. * Typically this would be used in the timer callback function to identify which * timer expired when the same callback function is assigned to more than one * timer. * * @param pxCallbackFunction The function to call when the timer expires. * Callback functions must have the prototype defined by TimerCallbackFunction_t, * which is "void vCallbackFunction( TimerHandle_t xTimer );". * * @return If the timer is successfully created then a handle to the newly * created timer is returned. If the timer cannot be created (because either * there is insufficient FreeRTOS heap remaining to allocate the timer * structures, or the timer period was set to 0) then NULL is returned. * * Example usage: * @verbatim * #define NUM_TIMERS 5 * * // An array to hold handles to the created timers. * TimerHandle_t xTimers[ NUM_TIMERS ]; * * // An array to hold a count of the number of times each timer expires. * int32_t lExpireCounters[ NUM_TIMERS ] = { 0 }; * * // Define a callback function that will be used by multiple timer instances. * // The callback function does nothing but count the number of times the * // associated timer expires, and stop the timer once the timer has expired * // 10 times. * void vTimerCallback( TimerHandle_t pxTimer ) * { * int32_t lArrayIndex; * const int32_t xMaxExpiryCountBeforeStopping = 10; * * // Optionally do something if the pxTimer parameter is NULL. * configASSERT( pxTimer ); * * // Which timer expired? * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer ); * * // Increment the number of times that pxTimer has expired. * lExpireCounters[ lArrayIndex ] += 1; * * // If the timer has expired 10 times then stop it from running. * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping ) * { * // Do not use a block time if calling a timer API function from a * // timer callback function, as doing so could cause a deadlock! * xTimerStop( pxTimer, 0 ); * } * } * * void main( void ) * { * int32_t x; * * // Create then start some timers. Starting the timers before the scheduler * // has been started means the timers will start running immediately that * // the scheduler starts. * for( x = 0; x < NUM_TIMERS; x++ ) * { * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. * ( 100 * x ), // The timer period in ticks. * pdTRUE, // The timers will auto-reload themselves when they expire. * ( void * ) x, // Assign each timer a unique id equal to its array index. * vTimerCallback // Each timer calls the same callback when it expires. * ); * * if( xTimers[ x ] == NULL ) * { * // The timer was not created. * } * else * { * // Start the timer. No block time is specified, and even if one was * // it would be ignored because the scheduler has not yet been * // started. * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS ) * { * // The timer could not be set into the Active state. * } * } * } * * // ... * // Create tasks here. * // ... * * // Starting the scheduler will start the timers running as they have already * // been set into the active state. * vTaskStartScheduler(); * * // Should not reach here. * for( ;; ); * } * @endverbatim */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /** * TimerHandle_t xTimerCreateStatic(const char * const pcTimerName, * TickType_t xTimerPeriodInTicks, * UBaseType_t uxAutoReload, * void * pvTimerID, * TimerCallbackFunction_t pxCallbackFunction, * StaticTimer_t *pxTimerBuffer ); * * Creates a new software timer instance, and returns a handle by which the * created software timer can be referenced. * * Internally, within the FreeRTOS implementation, software timers use a block * of memory, in which the timer data structure is stored. If a software timer * is created using xTimerCreate() then the required memory is automatically * dynamically allocated inside the xTimerCreate() function. (see * http://www.freertos.org/a00111.html). If a software timer is created using * xTimerCreateStatic() then the application writer must provide the memory that * will get used by the software timer. xTimerCreateStatic() therefore allows a * software timer to be created without using any dynamic memory allocation. * * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and * xTimerChangePeriodFromISR() API functions can all be used to transition a * timer into the active state. * * @param pcTimerName A text name that is assigned to the timer. This is done * purely to assist debugging. The kernel itself only ever references a timer * by its handle, and never by its name. * * @param xTimerPeriodInTicks The timer period. The time is defined in tick * periods so the constant portTICK_PERIOD_MS can be used to convert a time that * has been specified in milliseconds. For example, if the timer must expire * after 100 ticks, then xTimerPeriodInTicks should be set to 100. * Alternatively, if the timer must expire after 500ms, then xPeriod can be set * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or * equal to 1000. * * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and * enter the dormant state after it expires. * * @param pvTimerID An identifier that is assigned to the timer being created. * Typically this would be used in the timer callback function to identify which * timer expired when the same callback function is assigned to more than one * timer. * * @param pxCallbackFunction The function to call when the timer expires. * Callback functions must have the prototype defined by TimerCallbackFunction_t, * which is "void vCallbackFunction( TimerHandle_t xTimer );". * * @param pxTimerBuffer Must point to a variable of type StaticTimer_t, which * will be then be used to hold the software timer's data structures, removing * the need for the memory to be allocated dynamically. * * @return If the timer is created then a handle to the created timer is * returned. If pxTimerBuffer was NULL then NULL is returned. * * Example usage: * @verbatim * * // The buffer used to hold the software timer's data structure. * static StaticTimer_t xTimerBuffer; * * // A variable that will be incremented by the software timer's callback * // function. * UBaseType_t uxVariableToIncrement = 0; * * // A software timer callback function that increments a variable passed to * // it when the software timer was created. After the 5th increment the * // callback function stops the software timer. * static void prvTimerCallback( TimerHandle_t xExpiredTimer ) * { * UBaseType_t *puxVariableToIncrement; * BaseType_t xReturned; * * // Obtain the address of the variable to increment from the timer ID. * puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer ); * * // Increment the variable to show the timer callback has executed. * ( *puxVariableToIncrement )++; * * // If this callback has executed the required number of times, stop the * // timer. * if( *puxVariableToIncrement == 5 ) * { * // This is called from a timer callback so must not block. * xTimerStop( xExpiredTimer, staticDONT_BLOCK ); * } * } * * * void main( void ) * { * // Create the software time. xTimerCreateStatic() has an extra parameter * // than the normal xTimerCreate() API function. The parameter is a pointer * // to the StaticTimer_t structure that will hold the software timer * // structure. If the parameter is passed as NULL then the structure will be * // allocated dynamically, just as if xTimerCreate() had been called. * xTimer = xTimerCreateStatic( "T1", // Text name for the task. Helps debugging only. Not used by FreeRTOS. * xTimerPeriod, // The period of the timer in ticks. * pdTRUE, // This is an auto-reload timer. * ( void * ) &uxVariableToIncrement, // A variable incremented by the software timer's callback function * prvTimerCallback, // The function to execute when the timer expires. * &xTimerBuffer ); // The buffer that will hold the software timer structure. * * // The scheduler has not started yet so a block time is not used. * xReturned = xTimerStart( xTimer, 0 ); * * // ... * // Create tasks here. * // ... * * // Starting the scheduler will start the timers running as they have already * // been set into the active state. * vTaskStartScheduler(); * * // Should not reach here. * for( ;; ); * } * @endverbatim */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /* configSUPPORT_STATIC_ALLOCATION */ /** * void *pvTimerGetTimerID( TimerHandle_t xTimer ); * * Returns the ID assigned to the timer. * * IDs are assigned to timers using the pvTimerID parameter of the call to * xTimerCreated() that was used to create the timer, and by calling the * vTimerSetTimerID() API function. * * If the same callback function is assigned to multiple timers then the timer * ID can be used as time specific (timer local) storage. * * @param xTimer The timer being queried. * * @return The ID assigned to the timer being queried. * * Example usage: * * See the xTimerCreate() API function example usage scenario. */ void *pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** * void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); * * Sets the ID assigned to the timer. * * IDs are assigned to timers using the pvTimerID parameter of the call to * xTimerCreated() that was used to create the timer. * * If the same callback function is assigned to multiple timers then the timer * ID can be used as time specific (timer local) storage. * * @param xTimer The timer being updated. * * @param pvNewID The ID to assign to the timer. * * Example usage: * * See the xTimerCreate() API function example usage scenario. */ void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION; /** * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); * * Queries a timer to see if it is active or dormant. * * A timer will be dormant if: * 1) It has been created but not started, or * 2) It is an expired one-shot timer that has not been restarted. * * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the * active state. * * @param xTimer The timer being queried. * * @return pdFALSE will be returned if the timer is dormant. A value other than * pdFALSE will be returned if the timer is active. * * Example usage: * @verbatim * // This function assumes xTimer has already been created. * void vAFunction( TimerHandle_t xTimer ) * { * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" * { * // xTimer is active, do something. * } * else * { * // xTimer is not active, do something else. * } * } * @endverbatim */ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * * Simply returns the handle of the timer service/daemon task. It it not valid * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. */ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; /** * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. * * xTimerStart() starts a timer that was previously created using the * xTimerCreate() API function. If the timer had already been started and was * already in the active state, then xTimerStart() has equivalent functionality * to the xTimerReset() API function. * * Starting a timer ensures the timer is in the active state. If the timer * is not stopped, deleted, or reset in the mean time, the callback function * associated with the timer will get called 'n' ticks after xTimerStart() was * called, where 'n' is the timers defined period. * * It is valid to call xTimerStart() before the scheduler has been started, but * when this is done the timer will not actually start until the scheduler is * started, and the timers expiry time will be relative to when the scheduler is * started, not relative to when xTimerStart() was called. * * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart() * to be available. * * @param xTimer The handle of the timer being started/restarted. * * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the start command to be successfully * sent to the timer command queue, should the queue already be full when * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called * before the scheduler is started. * * @return pdFAIL will be returned if the start command could not be sent to * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system, although the * timers expiry time is relative to when xTimerStart() is actually called. The * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY * configuration constant. * * Example usage: * * See the xTimerCreate() API function example usage scenario. * */ #define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) /** * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. * * xTimerStop() stops a timer that was previously started using either of the * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions. * * Stopping a timer ensures the timer is not in the active state. * * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop() * to be available. * * @param xTimer The handle of the timer being stopped. * * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the stop command to be successfully * sent to the timer command queue, should the queue already be full when * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called * before the scheduler is started. * * @return pdFAIL will be returned if the stop command could not be sent to * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system. The timer * service/daemon task priority is set by the configTIMER_TASK_PRIORITY * configuration constant. * * Example usage: * * See the xTimerCreate() API function example usage scenario. * */ #define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) /** * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, * TickType_t xNewPeriod, * TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. * * xTimerChangePeriod() changes the period of a timer that was previously * created using the xTimerCreate() API function. * * xTimerChangePeriod() can be called to change the period of an active or * dormant state timer. * * The configUSE_TIMERS configuration constant must be set to 1 for * xTimerChangePeriod() to be available. * * @param xTimer The handle of the timer that is having its period changed. * * @param xNewPeriod The new period for xTimer. Timer periods are specified in * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time * that has been specified in milliseconds. For example, if the timer must * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, * if the timer must expire after 500ms, then xNewPeriod can be set to * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than * or equal to 1000. * * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the change period command to be * successfully sent to the timer command queue, should the queue already be * full when xTimerChangePeriod() was called. xTicksToWait is ignored if * xTimerChangePeriod() is called before the scheduler is started. * * @return pdFAIL will be returned if the change period command could not be * sent to the timer command queue even after xTicksToWait ticks had passed. * pdPASS will be returned if the command was successfully sent to the timer * command queue. When the command is actually processed will depend on the * priority of the timer service/daemon task relative to other tasks in the * system. The timer service/daemon task priority is set by the * configTIMER_TASK_PRIORITY configuration constant. * * Example usage: * @verbatim * // This function assumes xTimer has already been created. If the timer * // referenced by xTimer is already active when it is called, then the timer * // is deleted. If the timer referenced by xTimer is not active when it is * // called, then the period of the timer is set to 500ms and the timer is * // started. * void vAFunction( TimerHandle_t xTimer ) * { * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" * { * // xTimer is already active - delete it. * xTimerDelete( xTimer ); * } * else * { * // xTimer is not active, change its period to 500ms. This will also * // cause the timer to start. Block for a maximum of 100 ticks if the * // change period command cannot immediately be sent to the timer * // command queue. * if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS ) * { * // The command was successfully sent. * } * else * { * // The command could not be sent, even after waiting for 100 ticks * // to pass. Take appropriate action here. * } * } * } * @endverbatim */ #define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) /** * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. * * xTimerDelete() deletes a timer that was previously created using the * xTimerCreate() API function. * * The configUSE_TIMERS configuration constant must be set to 1 for * xTimerDelete() to be available. * * @param xTimer The handle of the timer being deleted. * * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the delete command to be * successfully sent to the timer command queue, should the queue already be * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete() * is called before the scheduler is started. * * @return pdFAIL will be returned if the delete command could not be sent to * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system. The timer * service/daemon task priority is set by the configTIMER_TASK_PRIORITY * configuration constant. * * Example usage: * * See the xTimerChangePeriod() API function example usage scenario. */ #define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) /** * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. * * xTimerReset() re-starts a timer that was previously created using the * xTimerCreate() API function. If the timer had already been started and was * already in the active state, then xTimerReset() will cause the timer to * re-evaluate its expiry time so that it is relative to when xTimerReset() was * called. If the timer was in the dormant state then xTimerReset() has * equivalent functionality to the xTimerStart() API function. * * Resetting a timer ensures the timer is in the active state. If the timer * is not stopped, deleted, or reset in the mean time, the callback function * associated with the timer will get called 'n' ticks after xTimerReset() was * called, where 'n' is the timers defined period. * * It is valid to call xTimerReset() before the scheduler has been started, but * when this is done the timer will not actually start until the scheduler is * started, and the timers expiry time will be relative to when the scheduler is * started, not relative to when xTimerReset() was called. * * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset() * to be available. * * @param xTimer The handle of the timer being reset/started/restarted. * * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the reset command to be successfully * sent to the timer command queue, should the queue already be full when * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called * before the scheduler is started. * * @return pdFAIL will be returned if the reset command could not be sent to * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system, although the * timers expiry time is relative to when xTimerStart() is actually called. The * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY * configuration constant. * * Example usage: * @verbatim * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass * // without a key being pressed, then the LCD back-light is switched off. In * // this case, the timer is a one-shot timer. * * TimerHandle_t xBacklightTimer = NULL; * * // The callback function assigned to the one-shot timer. In this case the * // parameter is not used. * void vBacklightTimerCallback( TimerHandle_t pxTimer ) * { * // The timer expired, therefore 5 seconds must have passed since a key * // was pressed. Switch off the LCD back-light. * vSetBacklightState( BACKLIGHT_OFF ); * } * * // The key press event handler. * void vKeyPressEventHandler( char cKey ) * { * // Ensure the LCD back-light is on, then reset the timer that is * // responsible for turning the back-light off after 5 seconds of * // key inactivity. Wait 10 ticks for the command to be successfully sent * // if it cannot be sent immediately. * vSetBacklightState( BACKLIGHT_ON ); * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS ) * { * // The reset command was not executed successfully. Take appropriate * // action here. * } * * // Perform the rest of the key processing here. * } * * void main( void ) * { * int32_t x; * * // Create then start the one-shot timer that is responsible for turning * // the back-light off if no keys are pressed within a 5 second period. * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. * ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks. * pdFALSE, // The timer is a one-shot timer. * 0, // The id is not used by the callback so can take any value. * vBacklightTimerCallback // The callback function that switches the LCD back-light off. * ); * * if( xBacklightTimer == NULL ) * { * // The timer was not created. * } * else * { * // Start the timer. No block time is specified, and even if one was * // it would be ignored because the scheduler has not yet been * // started. * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS ) * { * // The timer could not be set into the Active state. * } * } * * // ... * // Create tasks here. * // ... * * // Starting the scheduler will start the timer running as it has already * // been set into the active state. * vTaskStartScheduler(); * * // Should not reach here. * for( ;; ); * } * @endverbatim */ #define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) /** * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, * BaseType_t *pxHigherPriorityTaskWoken ); * * A version of xTimerStart() that can be called from an interrupt service * routine. * * @param xTimer The handle of the timer being started/restarted. * * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most * of its time in the Blocked state, waiting for messages to arrive on the timer * command queue. Calling xTimerStartFromISR() writes a message to the timer * command queue, so has the potential to transition the timer service/daemon * task out of the Blocked state. If calling xTimerStartFromISR() causes the * timer service/daemon task to leave the Blocked state, and the timer service/ * daemon task has a priority equal to or greater than the currently executing * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will * get set to pdTRUE internally within the xTimerStartFromISR() function. If * xTimerStartFromISR() sets this value to pdTRUE then a context switch should * be performed before the interrupt exits. * * @return pdFAIL will be returned if the start command could not be sent to * the timer command queue. pdPASS will be returned if the command was * successfully sent to the timer command queue. When the command is actually * processed will depend on the priority of the timer service/daemon task * relative to other tasks in the system, although the timers expiry time is * relative to when xTimerStartFromISR() is actually called. The timer * service/daemon task priority is set by the configTIMER_TASK_PRIORITY * configuration constant. * * Example usage: * @verbatim * // This scenario assumes xBacklightTimer has already been created. When a * // key is pressed, an LCD back-light is switched on. If 5 seconds pass * // without a key being pressed, then the LCD back-light is switched off. In * // this case, the timer is a one-shot timer, and unlike the example given for * // the xTimerReset() function, the key press event handler is an interrupt * // service routine. * * // The callback function assigned to the one-shot timer. In this case the * // parameter is not used. * void vBacklightTimerCallback( TimerHandle_t pxTimer ) * { * // The timer expired, therefore 5 seconds must have passed since a key * // was pressed. Switch off the LCD back-light. * vSetBacklightState( BACKLIGHT_OFF ); * } * * // The key press interrupt service routine. * void vKeyPressEventInterruptHandler( void ) * { * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * * // Ensure the LCD back-light is on, then restart the timer that is * // responsible for turning the back-light off after 5 seconds of * // key inactivity. This is an interrupt service routine so can only * // call FreeRTOS API functions that end in "FromISR". * vSetBacklightState( BACKLIGHT_ON ); * * // xTimerStartFromISR() or xTimerResetFromISR() could be called here * // as both cause the timer to re-calculate its expiry time. * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was * // declared (in this function). * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) * { * // The start command was not executed successfully. Take appropriate * // action here. * } * * // Perform the rest of the key processing here. * * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch * // should be performed. The syntax required to perform a context switch * // from inside an ISR varies from port to port, and from compiler to * // compiler. Inspect the demos for the port you are using to find the * // actual syntax required. * if( xHigherPriorityTaskWoken != pdFALSE ) * { * // Call the interrupt safe yield function here (actual function * // depends on the FreeRTOS port being used). * } * } * @endverbatim */ #define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) /** * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, * BaseType_t *pxHigherPriorityTaskWoken ); * * A version of xTimerStop() that can be called from an interrupt service * routine. * * @param xTimer The handle of the timer being stopped. * * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most * of its time in the Blocked state, waiting for messages to arrive on the timer * command queue. Calling xTimerStopFromISR() writes a message to the timer * command queue, so has the potential to transition the timer service/daemon * task out of the Blocked state. If calling xTimerStopFromISR() causes the * timer service/daemon task to leave the Blocked state, and the timer service/ * daemon task has a priority equal to or greater than the currently executing * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will * get set to pdTRUE internally within the xTimerStopFromISR() function. If * xTimerStopFromISR() sets this value to pdTRUE then a context switch should * be performed before the interrupt exits. * * @return pdFAIL will be returned if the stop command could not be sent to * the timer command queue. pdPASS will be returned if the command was * successfully sent to the timer command queue. When the command is actually * processed will depend on the priority of the timer service/daemon task * relative to other tasks in the system. The timer service/daemon task * priority is set by the configTIMER_TASK_PRIORITY configuration constant. * * Example usage: * @verbatim * // This scenario assumes xTimer has already been created and started. When * // an interrupt occurs, the timer should be simply stopped. * * // The interrupt service routine that stops the timer. * void vAnExampleInterruptServiceRoutine( void ) * { * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * * // The interrupt has occurred - simply stop the timer. * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined * // (within this function). As this is an interrupt service routine, only * // FreeRTOS API functions that end in "FromISR" can be used. * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) * { * // The stop command was not executed successfully. Take appropriate * // action here. * } * * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch * // should be performed. The syntax required to perform a context switch * // from inside an ISR varies from port to port, and from compiler to * // compiler. Inspect the demos for the port you are using to find the * // actual syntax required. * if( xHigherPriorityTaskWoken != pdFALSE ) * { * // Call the interrupt safe yield function here (actual function * // depends on the FreeRTOS port being used). * } * } * @endverbatim */ #define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) /** * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, * TickType_t xNewPeriod, * BaseType_t *pxHigherPriorityTaskWoken ); * * A version of xTimerChangePeriod() that can be called from an interrupt * service routine. * * @param xTimer The handle of the timer that is having its period changed. * * @param xNewPeriod The new period for xTimer. Timer periods are specified in * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time * that has been specified in milliseconds. For example, if the timer must * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, * if the timer must expire after 500ms, then xNewPeriod can be set to * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than * or equal to 1000. * * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most * of its time in the Blocked state, waiting for messages to arrive on the timer * command queue. Calling xTimerChangePeriodFromISR() writes a message to the * timer command queue, so has the potential to transition the timer service/ * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR() * causes the timer service/daemon task to leave the Blocked state, and the * timer service/daemon task has a priority equal to or greater than the * currently executing task (the task that was interrupted), then * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets * this value to pdTRUE then a context switch should be performed before the * interrupt exits. * * @return pdFAIL will be returned if the command to change the timers period * could not be sent to the timer command queue. pdPASS will be returned if the * command was successfully sent to the timer command queue. When the command * is actually processed will depend on the priority of the timer service/daemon * task relative to other tasks in the system. The timer service/daemon task * priority is set by the configTIMER_TASK_PRIORITY configuration constant. * * Example usage: * @verbatim * // This scenario assumes xTimer has already been created and started. When * // an interrupt occurs, the period of xTimer should be changed to 500ms. * * // The interrupt service routine that changes the period of xTimer. * void vAnExampleInterruptServiceRoutine( void ) * { * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * * // The interrupt has occurred - change the period of xTimer to 500ms. * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined * // (within this function). As this is an interrupt service routine, only * // FreeRTOS API functions that end in "FromISR" can be used. * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) * { * // The command to change the timers period was not executed * // successfully. Take appropriate action here. * } * * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch * // should be performed. The syntax required to perform a context switch * // from inside an ISR varies from port to port, and from compiler to * // compiler. Inspect the demos for the port you are using to find the * // actual syntax required. * if( xHigherPriorityTaskWoken != pdFALSE ) * { * // Call the interrupt safe yield function here (actual function * // depends on the FreeRTOS port being used). * } * } * @endverbatim */ #define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) /** * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, * BaseType_t *pxHigherPriorityTaskWoken ); * * A version of xTimerReset() that can be called from an interrupt service * routine. * * @param xTimer The handle of the timer that is to be started, reset, or * restarted. * * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most * of its time in the Blocked state, waiting for messages to arrive on the timer * command queue. Calling xTimerResetFromISR() writes a message to the timer * command queue, so has the potential to transition the timer service/daemon * task out of the Blocked state. If calling xTimerResetFromISR() causes the * timer service/daemon task to leave the Blocked state, and the timer service/ * daemon task has a priority equal to or greater than the currently executing * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will * get set to pdTRUE internally within the xTimerResetFromISR() function. If * xTimerResetFromISR() sets this value to pdTRUE then a context switch should * be performed before the interrupt exits. * * @return pdFAIL will be returned if the reset command could not be sent to * the timer command queue. pdPASS will be returned if the command was * successfully sent to the timer command queue. When the command is actually * processed will depend on the priority of the timer service/daemon task * relative to other tasks in the system, although the timers expiry time is * relative to when xTimerResetFromISR() is actually called. The timer service/daemon * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. * * Example usage: * @verbatim * // This scenario assumes xBacklightTimer has already been created. When a * // key is pressed, an LCD back-light is switched on. If 5 seconds pass * // without a key being pressed, then the LCD back-light is switched off. In * // this case, the timer is a one-shot timer, and unlike the example given for * // the xTimerReset() function, the key press event handler is an interrupt * // service routine. * * // The callback function assigned to the one-shot timer. In this case the * // parameter is not used. * void vBacklightTimerCallback( TimerHandle_t pxTimer ) * { * // The timer expired, therefore 5 seconds must have passed since a key * // was pressed. Switch off the LCD back-light. * vSetBacklightState( BACKLIGHT_OFF ); * } * * // The key press interrupt service routine. * void vKeyPressEventInterruptHandler( void ) * { * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * * // Ensure the LCD back-light is on, then reset the timer that is * // responsible for turning the back-light off after 5 seconds of * // key inactivity. This is an interrupt service routine so can only * // call FreeRTOS API functions that end in "FromISR". * vSetBacklightState( BACKLIGHT_ON ); * * // xTimerStartFromISR() or xTimerResetFromISR() could be called here * // as both cause the timer to re-calculate its expiry time. * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was * // declared (in this function). * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) * { * // The reset command was not executed successfully. Take appropriate * // action here. * } * * // Perform the rest of the key processing here. * * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch * // should be performed. The syntax required to perform a context switch * // from inside an ISR varies from port to port, and from compiler to * // compiler. Inspect the demos for the port you are using to find the * // actual syntax required. * if( xHigherPriorityTaskWoken != pdFALSE ) * { * // Call the interrupt safe yield function here (actual function * // depends on the FreeRTOS port being used). * } * } * @endverbatim */ #define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) /** * BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, * void *pvParameter1, * uint32_t ulParameter2, * BaseType_t *pxHigherPriorityTaskWoken ); * * * Used from application interrupt service routines to defer the execution of a * function to the RTOS daemon task (the timer service task, hence this function * is implemented in timers.c and is prefixed with 'Timer'). * * Ideally an interrupt service routine (ISR) is kept as short as possible, but * sometimes an ISR either has a lot of processing to do, or needs to perform * processing that is not deterministic. In these cases * xTimerPendFunctionCallFromISR() can be used to defer processing of a function * to the RTOS daemon task. * * A mechanism is provided that allows the interrupt to return directly to the * task that will subsequently execute the pended callback function. This * allows the callback function to execute contiguously in time with the * interrupt - just as if the callback had executed in the interrupt itself. * * @param xFunctionToPend The function to execute from the timer service/ * daemon task. The function must conform to the PendedFunction_t * prototype. * * @param pvParameter1 The value of the callback function's first parameter. * The parameter has a void * type to allow it to be used to pass any type. * For example, unsigned longs can be cast to a void *, or the void * can be * used to point to a structure. * * @param ulParameter2 The value of the callback function's second parameter. * * @param pxHigherPriorityTaskWoken As mentioned above, calling this function * will result in a message being sent to the timer daemon task. If the * priority of the timer daemon task (which is set using * configTIMER_TASK_PRIORITY in FreeRTOSConfig.h) is higher than the priority of * the currently running task (the task the interrupt interrupted) then * *pxHigherPriorityTaskWoken will be set to pdTRUE within * xTimerPendFunctionCallFromISR(), indicating that a context switch should be * requested before the interrupt exits. For that reason * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the * example code below. * * @return pdPASS is returned if the message was successfully sent to the * timer daemon task, otherwise pdFALSE is returned. * * Example usage: * @verbatim * * // The callback function that will execute in the context of the daemon task. * // Note callback functions must all use this same prototype. * void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 ) * { * BaseType_t xInterfaceToService; * * // The interface that requires servicing is passed in the second * // parameter. The first parameter is not used in this case. * xInterfaceToService = ( BaseType_t ) ulParameter2; * * // ...Perform the processing here... * } * * // An ISR that receives data packets from multiple interfaces * void vAnISR( void ) * { * BaseType_t xInterfaceToService, xHigherPriorityTaskWoken; * * // Query the hardware to determine which interface needs processing. * xInterfaceToService = prvCheckInterfaces(); * * // The actual processing is to be deferred to a task. Request the * // vProcessInterface() callback function is executed, passing in the * // number of the interface that needs processing. The interface to * // service is passed in the second parameter. The first parameter is * // not used in this case. * xHigherPriorityTaskWoken = pdFALSE; * xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken ); * * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context * // switch should be requested. The macro used is port specific and will * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to * // the documentation page for the port being used. * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * * } * @endverbatim */ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /** * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, * void *pvParameter1, * uint32_t ulParameter2, * TickType_t xTicksToWait ); * * * Used to defer the execution of a function to the RTOS daemon task (the timer * service task, hence this function is implemented in timers.c and is prefixed * with 'Timer'). * * @param xFunctionToPend The function to execute from the timer service/ * daemon task. The function must conform to the PendedFunction_t * prototype. * * @param pvParameter1 The value of the callback function's first parameter. * The parameter has a void * type to allow it to be used to pass any type. * For example, unsigned longs can be cast to a void *, or the void * can be * used to point to a structure. * * @param ulParameter2 The value of the callback function's second parameter. * * @param xTicksToWait Calling this function will result in a message being * sent to the timer daemon task on a queue. xTicksToWait is the amount of * time the calling task should remain in the Blocked state (so not using any * processing time) for space to become available on the timer queue if the * queue is found to be full. * * @return pdPASS is returned if the message was successfully sent to the * timer daemon task, otherwise pdFALSE is returned. * */ BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * const char * const pcTimerGetName( TimerHandle_t xTimer ); * * Returns the name that was assigned to a timer when the timer was created. * * @param xTimer The handle of the timer being queried. * * @return The name assigned to the timer specified by the xTimer parameter. */ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** * TickType_t xTimerGetPeriod( TimerHandle_t xTimer ); * * Returns the period of a timer. * * @param xTimer The handle of the timer being queried. * * @return The period of the timer in ticks. */ TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** * TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ); * * Returns the time in ticks at which the timer will expire. If this is less * than the current tick count then the expiry time has overflowed from the * current time. * * @param xTimer The handle of the timer being queried. * * @return If the timer is running then the time in ticks at which the timer * will next expire is returned. If the timer is not running then the return * value is undefined. */ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /* * Functions beyond this part are not part of the public API and are intended * for use by the kernel only. */ BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; #ifdef __cplusplus } #endif #endif /* TIMERS_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/list.c000066400000000000000000000250011357706137100220310ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #include #include "FreeRTOS.h" #include "list.h" /*----------------------------------------------------------- * PUBLIC LIST API documented in list.h *----------------------------------------------------------*/ void vListInitialise( List_t * const pxList ) { /* The list structure contains a list item which is used to mark the end of the list. To initialise the list the list end is inserted as the only list entry. */ pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ /* The list end value is the highest possible value in the list to ensure it remains at the end of the list. */ pxList->xListEnd.xItemValue = portMAX_DELAY; /* The list end next and previous pointers point to itself so we know when the list is empty. */ pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->uxNumberOfItems = ( UBaseType_t ) 0U; /* Write known values into the list if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); } /*-----------------------------------------------------------*/ void vListInitialiseItem( ListItem_t * const pxItem ) { /* Make sure the list item is not recorded as being on a list. */ pxItem->pvContainer = NULL; /* Write known values into the list item if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); } /*-----------------------------------------------------------*/ void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) { ListItem_t * const pxIndex = pxList->pxIndex; /* Only effective when configASSERT() is also defined, these tests may catch the list data structures being overwritten in memory. They will not catch data errors caused by incorrect configuration or use of FreeRTOS. */ listTEST_LIST_INTEGRITY( pxList ); listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); /* Insert a new list item into pxList, but rather than sort the list, makes the new list item the last item to be removed by a call to listGET_OWNER_OF_NEXT_ENTRY(). */ pxNewListItem->pxNext = pxIndex; pxNewListItem->pxPrevious = pxIndex->pxPrevious; /* Only used during decision coverage testing. */ mtCOVERAGE_TEST_DELAY(); pxIndex->pxPrevious->pxNext = pxNewListItem; pxIndex->pxPrevious = pxNewListItem; /* Remember which list the item is in. */ pxNewListItem->pvContainer = ( void * ) pxList; ( pxList->uxNumberOfItems )++; } /*-----------------------------------------------------------*/ void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) { ListItem_t *pxIterator; const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; /* Only effective when configASSERT() is also defined, these tests may catch the list data structures being overwritten in memory. They will not catch data errors caused by incorrect configuration or use of FreeRTOS. */ listTEST_LIST_INTEGRITY( pxList ); listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); /* Insert the new list item into the list, sorted in xItemValue order. If the list already contains a list item with the same item value then the new list item should be placed after it. This ensures that TCB's which are stored in ready lists (all of which have the same xItemValue value) get a share of the CPU. However, if the xItemValue is the same as the back marker the iteration loop below will not end. Therefore the value is checked first, and the algorithm slightly modified if necessary. */ if( xValueOfInsertion == portMAX_DELAY ) { pxIterator = pxList->xListEnd.pxPrevious; } else { /* *** NOTE *********************************************************** If you find your application is crashing here then likely causes are listed below. In addition see http://www.freertos.org/FAQHelp.html for more tips, and ensure configASSERT() is defined! http://www.freertos.org/a00110.html#configASSERT 1) Stack overflow - see http://www.freertos.org/Stacks-and-stack-overflow-checking.html 2) Incorrect interrupt priority assignment, especially on Cortex-M parts where numerically high priority values denote low actual interrupt priorities, which can seem counter intuitive. See http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition of configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html 3) Calling an API function from within a critical section or when the scheduler is suspended, or calling an API function that does not end in "FromISR" from an interrupt. 4) Using a queue or semaphore before it has been initialised or before the scheduler has been started (are interrupts firing before vTaskStartScheduler() has been called?). **********************************************************************/ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ { /* There is nothing to do here, just iterating to the wanted insertion position. */ } } pxNewListItem->pxNext = pxIterator->pxNext; pxNewListItem->pxNext->pxPrevious = pxNewListItem; pxNewListItem->pxPrevious = pxIterator; pxIterator->pxNext = pxNewListItem; /* Remember which list the item is in. This allows fast removal of the item later. */ pxNewListItem->pvContainer = ( void * ) pxList; ( pxList->uxNumberOfItems )++; } /*-----------------------------------------------------------*/ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) { /* The list item knows which list it is in. Obtain the list from the list item. */ List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; /* Only used during decision coverage testing. */ mtCOVERAGE_TEST_DELAY(); /* Make sure the index is left pointing to a valid item. */ if( pxList->pxIndex == pxItemToRemove ) { pxList->pxIndex = pxItemToRemove->pxPrevious; } else { mtCOVERAGE_TEST_MARKER(); } pxItemToRemove->pvContainer = NULL; ( pxList->uxNumberOfItems )--; return pxList->uxNumberOfItems; } /*-----------------------------------------------------------*/ micropython-1.12/ports/cc3200/FreeRTOS/Source/portable/000077500000000000000000000000001357706137100225245ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/Source/portable/GCC/000077500000000000000000000000001357706137100231205ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/Source/portable/GCC/ARM_CM3/000077500000000000000000000000001357706137100242015ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c000066400000000000000000000655061357706137100253450ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /*----------------------------------------------------------- * Implementation of functions defined in portable.h for the ARM CM3 port. *----------------------------------------------------------*/ /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" /* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is defined. The value should also ensure backward compatibility. FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ #ifndef configKERNEL_INTERRUPT_PRIORITY #define configKERNEL_INTERRUPT_PRIORITY 255 #endif #ifndef configSYSTICK_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ /* Ensure the SysTick is clocked at the same frequency as the core. */ #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #else /* The way the SysTick is clocked is not modified in case it is not the same as the core. */ #define portNVIC_SYSTICK_CLK_BIT ( 0 ) #endif /* Constants required to manipulate the core. Registers first... */ #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) /* ...then bits in the registers. */ #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) #define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) /* Constants required to check the validity of an interrupt priority. */ #define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) #define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIGROUP_SHIFT ( 8UL ) /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ #define portVECTACTIVE_MASK ( 0xFFUL ) /* Constants required to set up the initial stack. */ #define portINITIAL_XPSR ( 0x01000000UL ) /* The systick is a 24-bit counter. */ #define portMAX_24_BIT_NUMBER ( 0xffffffUL ) /* A fiddle factor to estimate the number of SysTick counts that would have occurred while the SysTick counter is stopped during tickless idle calculations. */ #define portMISSED_COUNTS_FACTOR ( 45UL ) /* For strict compliance with the Cortex-M spec the task start address should have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ #define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) /* Let the user override the pre-loading of the initial LR with the address of prvTaskExitError() in case it messes up unwinding of the stack in the debugger. */ #ifdef configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* Each task maintains its own interrupt status in the critical nesting variable. */ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* * Setup the timer to generate the tick interrupts. The implementation in this * file is weak to allow application writers to change the timer used to * generate the tick interrupt. */ void vPortSetupTimerInterrupt( void ); /* * Exception handlers. */ void xPortPendSVHandler( void ) __attribute__ (( naked )); void xPortSysTickHandler( void ); void vPortSVCHandler( void ) __attribute__ (( naked )); /* * Start first task is a separate function so it can be tested in isolation. */ static void prvPortStartFirstTask( void ) __attribute__ (( naked )); /* * Used to catch tasks that attempt to return from their implementing function. */ static void prvTaskExitError( void ); /*-----------------------------------------------------------*/ /* * The number of SysTick increments that make up one tick period. */ #if configUSE_TICKLESS_IDLE == 1 static uint32_t ulTimerCountsForOneTick = 0; #endif /* configUSE_TICKLESS_IDLE */ /* * The maximum number of tick periods that can be suppressed is limited by the * 24 bit resolution of the SysTick timer. */ #if configUSE_TICKLESS_IDLE == 1 static uint32_t xMaximumPossibleSuppressedTicks = 0; #endif /* configUSE_TICKLESS_IDLE */ /* * Compensate for the CPU cycles that pass while the SysTick is stopped (low * power functionality only. */ #if configUSE_TICKLESS_IDLE == 1 static uint32_t ulStoppedTimerCompensation = 0; #endif /* configUSE_TICKLESS_IDLE */ /* * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ #if ( configASSERT_DEFINED == 1 ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; #endif /* configASSERT_DEFINED */ /*-----------------------------------------------------------*/ /* * See header file for description. */ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { /* Simulate the stack frame as it would be created by a context switch interrupt. */ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ pxTopOfStack--; *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */ pxTopOfStack--; *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ return pxTopOfStack; } /*-----------------------------------------------------------*/ static void prvTaskExitError( void ) { /* A function that implements a task must not exit or attempt to return to its caller as there is nothing to return to. If a task wants to exit it should instead call vTaskDelete( NULL ). Artificially force an assert() to be triggered if configASSERT() is defined, then stop here so application writers can catch the error. */ configASSERT( uxCriticalNesting == ~0UL ); portDISABLE_INTERRUPTS(); for( ;; ); } /*-----------------------------------------------------------*/ void vPortSVCHandler( void ) { __asm volatile ( " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " msr psp, r0 \n" /* Restore the task stack pointer. */ " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" " orr r14, #0xd \n" " bx r14 \n" " \n" " .align 4 \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n" ); } /*-----------------------------------------------------------*/ static void prvPortStartFirstTask( void ) { __asm volatile( " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ " cpsie i \n" /* Globally enable interrupts. */ " cpsie f \n" " dsb \n" " isb \n" " svc 0 \n" /* System call to start first task. */ " nop \n" ); } /*-----------------------------------------------------------*/ /* * See header file for description. */ BaseType_t xPortStartScheduler( void ) { /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); #if( configASSERT_DEFINED == 1 ) { volatile uint32_t ulOriginalPriority; volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API functions can be called. ISR safe functions are those that end in "FromISR". FreeRTOS maintains separate thread and ISR API functions to ensure interrupt entry is as fast and simple as possible. Save the interrupt priority value that is about to be clobbered. */ ulOriginalPriority = *pucFirstUserPriorityRegister; /* Determine the number of priority bits available. First write to all possible bits. */ *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; /* Read the value back to see how many bits stuck. */ ucMaxPriorityValue = *pucFirstUserPriorityRegister; /* Use the same mask on the maximum system call priority. */ ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; /* Calculate the maximum acceptable priority group value for the number of bits read back. */ ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { ulMaxPRIGROUPValue--; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } /* Shift the priority group value back to its position within the AIRCR register. */ ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; /* Restore the clobbered interrupt priority register to its original value. */ *pucFirstUserPriorityRegister = ulOriginalPriority; } #endif /* conifgASSERT_DEFINED */ /* Make PendSV and SysTick the lowest priority interrupts. */ portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; /* Start the first task. */ prvPortStartFirstTask(); /* Should never get here as the tasks will now be executing! Call the task exit error function to prevent compiler warnings about a static function not being called in the case that the application writer overrides this functionality by defining configTASK_RETURN_ADDRESS. */ prvTaskExitError(); /* Should not get here! */ return 0; } /*-----------------------------------------------------------*/ void vPortEndScheduler( void ) { /* Not implemented in ports where there is nothing to return to. Artificially force an assert. */ configASSERT( uxCriticalNesting == 1000UL ); } /*-----------------------------------------------------------*/ void vPortEnterCritical( void ) { portDISABLE_INTERRUPTS(); uxCriticalNesting++; /* This is not the interrupt safe version of the enter critical function so assert() if it is being called from an interrupt context. Only API functions that end in "FromISR" can be used in an interrupt. Only assert if the critical nesting count is 1 to protect against recursive calls if the assert function also uses a critical section. */ if( uxCriticalNesting == 1 ) { configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); } } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { configASSERT( uxCriticalNesting ); uxCriticalNesting--; if( uxCriticalNesting == 0 ) { portENABLE_INTERRUPTS(); } } /*-----------------------------------------------------------*/ void xPortPendSVHandler( void ) { /* This is a naked function. */ __asm volatile ( " mrs r0, psp \n" " isb \n" " \n" " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" " msr basepri, r0 \n" " bl vTaskSwitchContext \n" " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r3, r14} \n" " \n" /* Restore the context, including the critical nesting count. */ " ldr r1, [r3] \n" " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ " msr psp, r0 \n" " isb \n" " bx r14 \n" " \n" " .align 4 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) ); } /*-----------------------------------------------------------*/ void xPortSysTickHandler( void ) { /* The SysTick runs at the lowest interrupt priority, so when this interrupt executes all interrupts must be unmasked. There is therefore no need to save and then restore the interrupt mask value as its value is already known. */ portDISABLE_INTERRUPTS(); { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) { /* A context switch is required. Context switching is performed in the PendSV interrupt. Pend the PendSV interrupt. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } } portENABLE_INTERRUPTS(); } /*-----------------------------------------------------------*/ #if configUSE_TICKLESS_IDLE == 1 __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) { xExpectedIdleTime = xMaximumPossibleSuppressedTicks; } /* Stop the SysTick momentarily. The time the SysTick is stopped for is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; /* Calculate the reload value required to wait xExpectedIdleTime tick periods. -1 is used because this code will execute part way through one of the tick periods. */ ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); if( ulReloadValue > ulStoppedTimerCompensation ) { ulReloadValue -= ulStoppedTimerCompensation; } /* Enter a critical section but don't use the taskENTER_CRITICAL() method as that will mask interrupts that should exit sleep mode. */ __asm volatile( "cpsid i" ); __asm volatile( "dsb" ); __asm volatile( "isb" ); /* If a context switch is pending or a task is waiting for the scheduler to be unsuspended then abandon the low power entry. */ if( eTaskConfirmSleepModeStatus() == eAbortSleep ) { /* Restart from whatever is left in the count register to complete this tick period. */ portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; /* Restart SysTick. */ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Reset the reload register to the value required for normal tick periods. */ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; /* Re-enable interrupts - see comments above the cpsid instruction() above. */ __asm volatile( "cpsie i" ); } else { /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; /* Clear the SysTick count flag and set the count value back to zero. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains its own wait for interrupt or wait for event instruction, and so wfi should not be executed again. However, the original expected idle time variable must remain unmodified, so a copy is taken. */ xModifiableIdleTime = xExpectedIdleTime; configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); if( xModifiableIdleTime > 0 ) { __asm volatile( "dsb" ); __asm volatile( "wfi" ); __asm volatile( "isb" ); } configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); /* Stop SysTick. Again, the time the SysTick is stopped for is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); /* Re-enable interrupts - see comments above the cpsid instruction() above. */ __asm volatile( "cpsie i" ); if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; /* The tick interrupt has already executed, and the SysTick count reloaded with ulReloadValue. Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick period. */ ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); /* Don't allow a tiny value, or values that have somehow underflowed because the post sleep hook did something that took too long. */ if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) { ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); } portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; /* The tick interrupt handler will already have pended the tick processing in the kernel. As the pending tick will be processed as soon as this function exits, the tick value maintained by the tick is stepped forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; } else { /* Something other than the tick interrupt ended the sleep. Work out how long the sleep lasted rounded to complete tick periods (not the ulReload value which accounted for part ticks). */ ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; /* How many complete tick periods passed while the processor was waiting? */ ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; /* The reload value is set to whatever fraction of a single tick period remains. */ portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, then set portNVIC_SYSTICK_LOAD_REG back to its standard value. The critical section is used to ensure the tick interrupt can only execute once in the case that the reload register is near zero. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portENTER_CRITICAL(); { portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; vTaskStepTick( ulCompleteTickPeriods ); portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; } portEXIT_CRITICAL(); } } #endif /* #if configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ /* * Setup the systick timer to generate the tick interrupts at the required * frequency. */ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) { /* Calculate the constants required to configure the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 { ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); } #endif /* configUSE_TICKLESS_IDLE */ /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); } /*-----------------------------------------------------------*/ #if( configASSERT_DEFINED == 1 ) void vPortValidateInterruptPriority( void ) { uint32_t ulCurrentInterrupt; uint8_t ucCurrentPriority; /* Obtain the number of the currently executing interrupt. */ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); /* Is the interrupt number a user defined interrupt? */ if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) { /* Look up the interrupt's priority. */ ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; /* The following assertion will fail if a service routine (ISR) for an interrupt that has been assigned a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API function. ISR safe FreeRTOS API functions must *only* be called from interrupts that have been assigned a priority at or below configMAX_SYSCALL_INTERRUPT_PRIORITY. Numerically low interrupt priority numbers represent logically high interrupt priorities, therefore the priority of the interrupt must be set to a value equal to or numerically *higher* than configMAX_SYSCALL_INTERRUPT_PRIORITY. Interrupts that use the FreeRTOS API must not be left at their default priority of zero as that is the highest possible priority, which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, and therefore also guaranteed to be invalid. FreeRTOS maintains separate thread and ISR API functions to ensure interrupt entry is as fast and simple as possible. The following links provide detailed information: http://www.freertos.org/RTOS-Cortex-M3-M4.html http://www.freertos.org/FAQHelp.html */ configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); } /* Priority grouping: The interrupt controller (NVIC) allows the bits that define each interrupt's priority to be split between bits that define the interrupt's pre-emption priority bits and bits that define the interrupt's sub-priority. For simplicity all bits must be defined to be pre-emption priority bits. The following assertion will fail if this is not the case (if some bits represent a sub-priority). If the application only uses CMSIS libraries for interrupt configuration then the correct setting can be achieved on all Cortex-M devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the scheduler. Note however that some vendor specific peripheral libraries assume a non-zero priority group setting, in which cases using a value of zero will result in unpredicable behaviour. */ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } #endif /* configASSERT_DEFINED */ micropython-1.12/ports/cc3200/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h000066400000000000000000000246761357706137100263770ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef PORTMACRO_H #define PORTMACRO_H #ifdef __cplusplus extern "C" { #endif /*----------------------------------------------------------- * Port specific definitions. * * The settings in this file configure FreeRTOS correctly for the * given hardware and compiler. * * These settings should not be altered. *----------------------------------------------------------- */ /* Type definitions. */ #define portCHAR char #define portFLOAT float #define portDOUBLE double #define portLONG long #define portSHORT short #define portSTACK_TYPE uint32_t #define portBASE_TYPE long typedef portSTACK_TYPE StackType_t; typedef long BaseType_t; typedef unsigned long UBaseType_t; #if( configUSE_16_BIT_TICKS == 1 ) typedef uint16_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffff #else typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #endif /*-----------------------------------------------------------*/ /* Architecture specifics. */ #define portSTACK_GROWTH ( -1 ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portBYTE_ALIGNMENT 8 /*-----------------------------------------------------------*/ /* Scheduler utilities. */ #define portYIELD() \ { \ /* Set a PendSV to request a context switch. */ \ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \ \ /* Barriers are normally not required but do ensure the code is completely \ within the specified behaviour for the architecture. */ \ __asm volatile( "dsb" ); \ __asm volatile( "isb" ); \ } #define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD() #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /* Critical section management. */ extern void vPortEnterCritical( void ); extern void vPortExitCritical( void ); #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x) #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() #define portENABLE_INTERRUPTS() vPortSetBASEPRI(0) #define portENTER_CRITICAL() vPortEnterCritical() #define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. These are not necessary for to use this port. They are defined so the common demo files (which build with all the ports) will build. */ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ /* Tickless idle/low power functionality. */ #ifndef portSUPPRESS_TICKS_AND_SLEEP extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #endif /*-----------------------------------------------------------*/ /* Architecture specific optimisations. */ #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #endif #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 /* Generic helper function. */ __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) { uint8_t ucReturn; __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) ); return ucReturn; } /* Check the configuration. */ #if( configMAX_PRIORITIES > 32 ) #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #endif /* Store/clear the ready priorities in a bit map. */ #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) /*-----------------------------------------------------------*/ #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ /*-----------------------------------------------------------*/ #ifdef configASSERT void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif /* portNOP() is not required by this port. */ #define portNOP() #define portINLINE __inline #ifndef portFORCE_INLINE #define portFORCE_INLINE inline __attribute__(( always_inline)) #endif portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) { uint32_t ulCurrentInterrupt; BaseType_t xReturn; /* Obtain the number of the currently executing interrupt. */ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); if( ulCurrentInterrupt == 0 ) { xReturn = pdFALSE; } else { xReturn = pdTRUE; } return xReturn; } /*-----------------------------------------------------------*/ portFORCE_INLINE static void vPortRaiseBASEPRI( void ) { uint32_t ulNewBASEPRI; __asm volatile ( " mov %0, %1 \n" \ " msr basepri, %0 \n" \ " isb \n" \ " dsb \n" \ :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ); } /*-----------------------------------------------------------*/ portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) { uint32_t ulOriginalBASEPRI, ulNewBASEPRI; __asm volatile ( " mrs %0, basepri \n" \ " mov %1, %2 \n" \ " msr basepri, %1 \n" \ " isb \n" \ " dsb \n" \ :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ); /* This return will not be reached but is necessary to prevent compiler warnings. */ return ulOriginalBASEPRI; } /*-----------------------------------------------------------*/ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) { __asm volatile ( " msr basepri, %0 " :: "r" ( ulNewMaskValue ) ); } /*-----------------------------------------------------------*/ #ifdef __cplusplus } #endif #endif /* PORTMACRO_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/portable/MemMang/000077500000000000000000000000001357706137100240455ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/Source/portable/MemMang/heap_4.c000066400000000000000000000401371357706137100253560ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /* * A sample implementation of pvPortMalloc() and vPortFree() that combines * (coalescences) adjacent memory blocks as they are freed, and in so doing * limits memory fragmentation. * * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the * memory management pages of http://www.FreeRTOS.org for more information. */ #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining all the API functions to use the MPU wrappers. That should only be done when task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #include "FreeRTOS.h" #include "task.h" #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #if( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 #endif /* Block sizes must not get too small. */ #define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) /* Assumes 8bit bytes! */ #define heapBITS_PER_BYTE ( ( size_t ) 8 ) /* Allocate the memory for the heap. */ #if( configAPPLICATION_ALLOCATED_HEAP == 1 ) /* The application writer has already defined the array used for the RTOS heap - probably so it can be placed in a special segment or address. */ extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; #else static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; #endif /* configAPPLICATION_ALLOCATED_HEAP */ /* Define the linked list structure. This is used to link free blocks in order of their memory address. */ typedef struct A_BLOCK_LINK { struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ size_t xBlockSize; /*<< The size of the free block. */ } BlockLink_t; /*-----------------------------------------------------------*/ /* * Inserts a block of memory that is being freed into the correct position in * the list of free memory blocks. The block being freed will be merged with * the block in front it and/or the block behind it if the memory blocks are * adjacent to each other. */ static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); /* * Called automatically to setup the required heap structures the first time * pvPortMalloc() is called. */ static void prvHeapInit( void ); /*-----------------------------------------------------------*/ /* The size of the structure placed at the beginning of each allocated memory block must by correctly byte aligned. */ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); /* Create a couple of list links to mark the start and end of the list. */ static BlockLink_t xStart, *pxEnd = NULL; /* Keeps track of the number of free bytes remaining, but says nothing about fragmentation. */ static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; /* Gets set to the top bit of an size_t type. When this bit in the xBlockSize member of an BlockLink_t structure is set then the block belongs to the application. When the bit is free the block is still part of the free heap space. */ static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ void *pvPortMalloc( size_t xWantedSize ) { BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; void *pvReturn = NULL; vTaskSuspendAll(); { /* If this is the first call to malloc then the heap will require initialisation to setup the list of free blocks. */ if( pxEnd == NULL ) { prvHeapInit(); } else { mtCOVERAGE_TEST_MARKER(); } /* Check the requested block size is not so large that the top bit is set. The top bit of the block size member of the BlockLink_t structure is used to determine who owns the block - the application or the kernel, so it must be free. */ if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) { /* The wanted size is increased so it can contain a BlockLink_t structure in addition to the requested amount of bytes. */ if( xWantedSize > 0 ) { xWantedSize += xHeapStructSize; /* Ensure that blocks are always aligned to the required number of bytes. */ if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until one of adequate size is found. */ pxPreviousBlock = &xStart; pxBlock = xStart.pxNextFreeBlock; while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) { pxPreviousBlock = pxBlock; pxBlock = pxBlock->pxNextFreeBlock; } /* If the end marker was reached then a block of adequate size was not found. */ if( pxBlock != pxEnd ) { /* Return the memory space pointed to - jumping over the BlockLink_t structure at its start. */ pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize ); /* This block is being returned for use so must be taken out of the list of free blocks. */ pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; /* If the block is larger than required it can be split into two. */ if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) { /* This block is to be split into two. Create a new block following the number of bytes requested. The void cast is used to prevent byte alignment warnings from the compiler. */ pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); /* Calculate the sizes of two blocks split from the single block. */ pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; pxBlock->xBlockSize = xWantedSize; /* Insert the new block into the list of free blocks. */ prvInsertBlockIntoFreeList( pxNewBlockLink ); } else { mtCOVERAGE_TEST_MARKER(); } xFreeBytesRemaining -= pxBlock->xBlockSize; if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) { xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; } else { mtCOVERAGE_TEST_MARKER(); } /* The block is being returned - it is allocated and owned by the application and has no "next" block. */ pxBlock->xBlockSize |= xBlockAllocatedBit; pxBlock->pxNextFreeBlock = NULL; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } traceMALLOC( pvReturn, xWantedSize ); } ( void ) xTaskResumeAll(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { extern void vApplicationMallocFailedHook( void ); vApplicationMallocFailedHook(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 ); return pvReturn; } /*-----------------------------------------------------------*/ void vPortFree( void *pv ) { uint8_t *puc = ( uint8_t * ) pv; BlockLink_t *pxLink; if( pv != NULL ) { /* The memory being freed will have an BlockLink_t structure immediately before it. */ puc -= xHeapStructSize; /* This casting is to keep the compiler from issuing warnings. */ pxLink = ( void * ) puc; /* Check the block is actually allocated. */ configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); configASSERT( pxLink->pxNextFreeBlock == NULL ); if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer allocated. */ pxLink->xBlockSize &= ~xBlockAllocatedBit; vTaskSuspendAll(); { /* Add this block to the list of free blocks. */ xFreeBytesRemaining += pxLink->xBlockSize; traceFREE( pv, pxLink->xBlockSize ); prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); } ( void ) xTaskResumeAll(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } } /*-----------------------------------------------------------*/ size_t xPortGetFreeHeapSize( void ) { return xFreeBytesRemaining; } /*-----------------------------------------------------------*/ size_t xPortGetMinimumEverFreeHeapSize( void ) { return xMinimumEverFreeBytesRemaining; } /*-----------------------------------------------------------*/ void vPortInitialiseBlocks( void ) { /* This just exists to keep the linker quiet. */ } /*-----------------------------------------------------------*/ static void prvHeapInit( void ) { BlockLink_t *pxFirstFreeBlock; uint8_t *pucAlignedHeap; size_t uxAddress; size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; /* Ensure the heap starts on a correctly aligned boundary. */ uxAddress = ( size_t ) ucHeap; if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) { uxAddress += ( portBYTE_ALIGNMENT - 1 ); uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); xTotalHeapSize -= uxAddress - ( size_t ) ucHeap; } pucAlignedHeap = ( uint8_t * ) uxAddress; /* xStart is used to hold a pointer to the first item in the list of free blocks. The void cast is used to prevent compiler warnings. */ xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; xStart.xBlockSize = ( size_t ) 0; /* pxEnd is used to mark the end of the list of free blocks and is inserted at the end of the heap space. */ uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize; uxAddress -= xHeapStructSize; uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); pxEnd = ( void * ) uxAddress; pxEnd->xBlockSize = 0; pxEnd->pxNextFreeBlock = NULL; /* To start with there is a single free block that is sized to take up the entire heap space, minus the space taken by pxEnd. */ pxFirstFreeBlock = ( void * ) pucAlignedHeap; pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock; pxFirstFreeBlock->pxNextFreeBlock = pxEnd; /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; /* Work out the position of the top bit in a size_t variable. */ xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) { BlockLink_t *pxIterator; uint8_t *puc; /* Iterate through the list until a block is found that has a higher address than the block being inserted. */ for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) { /* Nothing to do here, just iterate to the right position. */ } /* Do the block being inserted, and the block it is being inserted after make a contiguous block of memory? */ puc = ( uint8_t * ) pxIterator; if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) { pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; pxBlockToInsert = pxIterator; } else { mtCOVERAGE_TEST_MARKER(); } /* Do the block being inserted, and the block it is being inserted before make a contiguous block of memory? */ puc = ( uint8_t * ) pxBlockToInsert; if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) { if( pxIterator->pxNextFreeBlock != pxEnd ) { /* Form one big block from the two blocks. */ pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; } else { pxBlockToInsert->pxNextFreeBlock = pxEnd; } } else { pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; } /* If the block being inserted plugged a gab, so was merged with the block before and the block after, then it's pxNextFreeBlock pointer will have already been set, and should not be set here as that would make it point to itself. */ if( pxIterator != pxBlockToInsert ) { pxIterator->pxNextFreeBlock = pxBlockToInsert; } else { mtCOVERAGE_TEST_MARKER(); } } micropython-1.12/ports/cc3200/FreeRTOS/Source/queue.c000066400000000000000000002364131357706137100222150ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #include #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining all the API functions to use the MPU wrappers. That should only be done when task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #include "FreeRTOS.h" #include "task.h" #include "queue.h" #if ( configUSE_CO_ROUTINES == 1 ) #include "croutine.h" #endif /* Lint e961 and e750 are suppressed as a MISRA exception justified because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the header files above, but not in this file, in order to generate the correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ /* Constants used with the cRxLock and cTxLock structure members. */ #define queueUNLOCKED ( ( int8_t ) -1 ) #define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 ) /* When the Queue_t structure is used to represent a base queue its pcHead and pcTail members are used as pointers into the queue storage area. When the Queue_t structure is used to represent a mutex pcHead and pcTail pointers are not necessary, and the pcHead pointer is set to NULL to indicate that the pcTail pointer actually points to the mutex holder (if any). Map alternative names to the pcHead and pcTail structure members to ensure the readability of the code is maintained despite this dual use of two structure members. An alternative implementation would be to use a union, but use of a union is against the coding standard (although an exception to the standard has been permitted where the dual use also significantly changes the type of the structure member). */ #define pxMutexHolder pcTail #define uxQueueType pcHead #define queueQUEUE_IS_MUTEX NULL /* Semaphores do not actually store or copy data, so have an item size of zero. */ #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) #define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) #if( configUSE_PREEMPTION == 0 ) /* If the cooperative scheduler is being used then a yield should not be performed just because a higher priority task has been woken. */ #define queueYIELD_IF_USING_PREEMPTION() #else #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #endif /* * Definition of the queue used by the scheduler. * Items are queued by copy, not reference. See the following link for the * rationale: http://www.freertos.org/Embedded-RTOS-Queues.html */ typedef struct QueueDefinition { int8_t *pcHead; /*< Points to the beginning of the queue storage area. */ int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */ union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */ { int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ } u; List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */ UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */ #endif #if ( configUSE_QUEUE_SETS == 1 ) struct QueueDefinition *pxQueueSetContainer; #endif #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxQueueNumber; uint8_t ucQueueType; #endif } xQUEUE; /* The old xQUEUE name is maintained above then typedefed to the new Queue_t name below to enable the use of older kernel aware debuggers. */ typedef xQUEUE Queue_t; /*-----------------------------------------------------------*/ /* * The queue registry is just a means for kernel aware debuggers to locate * queue structures. It has no other purpose so is an optional component. */ #if ( configQUEUE_REGISTRY_SIZE > 0 ) /* The type stored within the queue registry array. This allows a name to be assigned to each queue making kernel aware debugging a little more user friendly. */ typedef struct QUEUE_REGISTRY_ITEM { const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ QueueHandle_t xHandle; } xQueueRegistryItem; /* The old xQueueRegistryItem name is maintained above then typedefed to the new xQueueRegistryItem name below to enable the use of older kernel aware debuggers. */ typedef xQueueRegistryItem QueueRegistryItem_t; /* The queue registry is simply an array of QueueRegistryItem_t structures. The pcQueueName member of a structure being NULL is indicative of the array position being vacant. */ PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; #endif /* configQUEUE_REGISTRY_SIZE */ /* * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not * prevent an ISR from adding or removing items to the queue, but does prevent * an ISR from removing tasks from the queue event lists. If an ISR finds a * queue is locked it will instead increment the appropriate queue lock count * to indicate that a task may require unblocking. When the queue in unlocked * these lock counts are inspected, and the appropriate action taken. */ static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; /* * Uses a critical section to determine if there is any data in a queue. * * @return pdTRUE if the queue contains no items, otherwise pdFALSE. */ static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; /* * Uses a critical section to determine if there is any space in a queue. * * @return pdTRUE if there is no space, otherwise pdFALSE; */ static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; /* * Copies an item into the queue, either at the front of the queue or the * back of the queue. */ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION; /* * Copies an item out of a queue. */ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; #if ( configUSE_QUEUE_SETS == 1 ) /* * Checks to see if a queue is a member of a queue set, and if so, notifies * the queue set that the queue contains data. */ static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; #endif /* * Called after a Queue_t structure has been allocated either statically or * dynamically to fill in the structure's members. */ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; /* * Mutexes are a special type of queue. When a mutex is created, first the * queue is created, then prvInitialiseMutex() is called to configure the queue * as a mutex. */ #if( configUSE_MUTEXES == 1 ) static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; #endif /*-----------------------------------------------------------*/ /* * Macro to mark a queue as locked. Locking a queue prevents an ISR from * accessing the queue event lists. */ #define prvLockQueue( pxQueue ) \ taskENTER_CRITICAL(); \ { \ if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ { \ ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \ } \ if( ( pxQueue )->cTxLock == queueUNLOCKED ) \ { \ ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ } \ } \ taskEXIT_CRITICAL() /*-----------------------------------------------------------*/ BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) { Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); taskENTER_CRITICAL(); { pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; pxQueue->pcWriteTo = pxQueue->pcHead; pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize ); pxQueue->cRxLock = queueUNLOCKED; pxQueue->cTxLock = queueUNLOCKED; if( xNewQueue == pdFALSE ) { /* If there are tasks blocked waiting to read from the queue, then the tasks will remain blocked as after this function exits the queue will still be empty. If there are tasks blocked waiting to write to the queue, then one should be unblocked as after this function exits it will be possible to write to it. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { /* Ensure the event queues start in the correct state. */ vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); } } taskEXIT_CRITICAL(); /* A value is returned for calling semantic consistency with previous versions. */ return pdPASS; } /*-----------------------------------------------------------*/ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) { Queue_t *pxNewQueue; configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); /* The StaticQueue_t structure and the queue storage area must be supplied. */ configASSERT( pxStaticQueue != NULL ); /* A queue storage area should be provided if the item size is not 0, and should not be provided if the item size is 0. */ configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ); configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ); #if( configASSERT_DEFINED == 1 ) { /* Sanity check that the size of the structure used to declare a variable of type StaticQueue_t or StaticSemaphore_t equals the size of the real queue and semaphore structures. */ volatile size_t xSize = sizeof( StaticQueue_t ); configASSERT( xSize == sizeof( Queue_t ) ); } #endif /* configASSERT_DEFINED */ /* The address of a statically allocated queue was passed in, use it. The address of a statically allocated storage area was also passed in but is already set. */ pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ if( pxNewQueue != NULL ) { #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) { /* Queues can be allocated wither statically or dynamically, so note this queue was allocated statically in case the queue is later deleted. */ pxNewQueue->ucStaticallyAllocated = pdTRUE; } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); } return pxNewQueue; } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) { Queue_t *pxNewQueue; size_t xQueueSizeInBytes; uint8_t *pucQueueStorage; configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); if( uxItemSize == ( UBaseType_t ) 0 ) { /* There is not going to be a queue storage area. */ xQueueSizeInBytes = ( size_t ) 0; } else { /* Allocate enough space to hold the maximum number of items that can be in the queue at any time. */ xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ } pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); if( pxNewQueue != NULL ) { /* Jump past the queue structure to find the location of the queue storage area. */ pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t ); #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { /* Queues can be created either statically or dynamically, so note this task was created dynamically in case it is later deleted. */ pxNewQueue->ucStaticallyAllocated = pdFALSE; } #endif /* configSUPPORT_STATIC_ALLOCATION */ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); } return pxNewQueue; } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) { /* Remove compiler warnings about unused parameters should configUSE_TRACE_FACILITY not be set to 1. */ ( void ) ucQueueType; if( uxItemSize == ( UBaseType_t ) 0 ) { /* No RAM was allocated for the queue storage area, but PC head cannot be set to NULL because NULL is used as a key to say the queue is used as a mutex. Therefore just set pcHead to point to the queue as a benign value that is known to be within the memory map. */ pxNewQueue->pcHead = ( int8_t * ) pxNewQueue; } else { /* Set the head to the start of the queue storage area. */ pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage; } /* Initialise the queue members as described where the queue type is defined. */ pxNewQueue->uxLength = uxQueueLength; pxNewQueue->uxItemSize = uxItemSize; ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); #if ( configUSE_TRACE_FACILITY == 1 ) { pxNewQueue->ucQueueType = ucQueueType; } #endif /* configUSE_TRACE_FACILITY */ #if( configUSE_QUEUE_SETS == 1 ) { pxNewQueue->pxQueueSetContainer = NULL; } #endif /* configUSE_QUEUE_SETS */ traceQUEUE_CREATE( pxNewQueue ); } /*-----------------------------------------------------------*/ #if( configUSE_MUTEXES == 1 ) static void prvInitialiseMutex( Queue_t *pxNewQueue ) { if( pxNewQueue != NULL ) { /* The queue create function will set all the queue structure members correctly for a generic queue, but this function is creating a mutex. Overwrite those members that need to be set differently - in particular the information required for priority inheritance. */ pxNewQueue->pxMutexHolder = NULL; pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; /* In case this is a recursive mutex. */ pxNewQueue->u.uxRecursiveCallCount = 0; traceCREATE_MUTEX( pxNewQueue ); /* Start with the semaphore in the expected state. */ ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); } else { traceCREATE_MUTEX_FAILED(); } } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) { Queue_t *pxNewQueue; const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); prvInitialiseMutex( pxNewQueue ); return pxNewQueue; } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) { Queue_t *pxNewQueue; const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; /* Prevent compiler warnings about unused parameters if configUSE_TRACE_FACILITY does not equal 1. */ ( void ) ucQueueType; pxNewQueue = ( Queue_t * ) xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType ); prvInitialiseMutex( pxNewQueue ); return pxNewQueue; } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) { void *pxReturn; /* This function is called by xSemaphoreGetMutexHolder(), and should not be called directly. Note: This is a good way of determining if the calling task is the mutex holder, but not a good way of determining the identity of the mutex holder, as the holder may change between the following critical section exiting and the function returning. */ taskENTER_CRITICAL(); { if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) { pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder; } else { pxReturn = NULL; } } taskEXIT_CRITICAL(); return pxReturn; } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ #endif /*-----------------------------------------------------------*/ #if ( configUSE_RECURSIVE_MUTEXES == 1 ) BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) { BaseType_t xReturn; Queue_t * const pxMutex = ( Queue_t * ) xMutex; configASSERT( pxMutex ); /* If this is the task that holds the mutex then pxMutexHolder will not change outside of this task. If this task does not hold the mutex then pxMutexHolder can never coincidentally equal the tasks handle, and as this is the only condition we are interested in it does not matter if pxMutexHolder is accessed simultaneously by another task. Therefore no mutual exclusion is required to test the pxMutexHolder variable. */ if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as TaskHandle_t is a typedef. */ { traceGIVE_MUTEX_RECURSIVE( pxMutex ); /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to the task handle, therefore no underflow check is required. Also, uxRecursiveCallCount is only modified by the mutex holder, and as there can only be one, no mutual exclusion is required to modify the uxRecursiveCallCount member. */ ( pxMutex->u.uxRecursiveCallCount )--; /* Has the recursive call count unwound to 0? */ if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 ) { /* Return the mutex. This will automatically unblock any other task that might be waiting to access the mutex. */ ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); } else { mtCOVERAGE_TEST_MARKER(); } xReturn = pdPASS; } else { /* The mutex cannot be given because the calling task is not the holder. */ xReturn = pdFAIL; traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); } return xReturn; } #endif /* configUSE_RECURSIVE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( configUSE_RECURSIVE_MUTEXES == 1 ) BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) { BaseType_t xReturn; Queue_t * const pxMutex = ( Queue_t * ) xMutex; configASSERT( pxMutex ); /* Comments regarding mutual exclusion as per those within xQueueGiveMutexRecursive(). */ traceTAKE_MUTEX_RECURSIVE( pxMutex ); if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ { ( pxMutex->u.uxRecursiveCallCount )++; xReturn = pdPASS; } else { xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE ); /* pdPASS will only be returned if the mutex was successfully obtained. The calling task may have entered the Blocked state before reaching here. */ if( xReturn != pdFAIL ) { ( pxMutex->u.uxRecursiveCallCount )++; } else { traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); } } return xReturn; } #endif /* configUSE_RECURSIVE_MUTEXES */ /*-----------------------------------------------------------*/ #if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) { QueueHandle_t xHandle; configASSERT( uxMaxCount != 0 ); configASSERT( uxInitialCount <= uxMaxCount ); xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); if( xHandle != NULL ) { ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; traceCREATE_COUNTING_SEMAPHORE(); } else { traceCREATE_COUNTING_SEMAPHORE_FAILED(); } return xHandle; } #endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ /*-----------------------------------------------------------*/ #if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) { QueueHandle_t xHandle; configASSERT( uxMaxCount != 0 ); configASSERT( uxInitialCount <= uxMaxCount ); xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); if( xHandle != NULL ) { ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; traceCREATE_COUNTING_SEMAPHORE(); } else { traceCREATE_COUNTING_SEMAPHORE_FAILED(); } return xHandle; } #endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ /*-----------------------------------------------------------*/ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) { BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; TimeOut_t xTimeOut; Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) { configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); } #endif /* This function relaxes the coding standard somewhat to allow return statements within the function itself. This is done in the interest of execution time efficiency. */ for( ;; ) { taskENTER_CRITICAL(); { /* Is there room on the queue now? The running task must be the highest priority task wanting to access the queue. If the head item in the queue is to be overwritten then it does not matter if the queue is full. */ if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) { traceQUEUE_SEND( pxQueue ); xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); #if ( configUSE_QUEUE_SETS == 1 ) { if( pxQueue->pxQueueSetContainer != NULL ) { if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) { /* The queue is a member of a queue set, and posting to the queue set caused a higher priority task to unblock. A context switch is required. */ queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else { /* If there was a task waiting for data to arrive on the queue then unblock it now. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The unblocked task has a priority higher than our own so yield immediately. Yes it is ok to do this from within the critical section - the kernel takes care of that. */ queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else if( xYieldRequired != pdFALSE ) { /* This path is a special case that will only get executed if the task was holding multiple mutexes and the mutexes were given back in an order that is different to that in which they were taken. */ queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } } #else /* configUSE_QUEUE_SETS */ { /* If there was a task waiting for data to arrive on the queue then unblock it now. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The unblocked task has a priority higher than our own so yield immediately. Yes it is ok to do this from within the critical section - the kernel takes care of that. */ queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else if( xYieldRequired != pdFALSE ) { /* This path is a special case that will only get executed if the task was holding multiple mutexes and the mutexes were given back in an order that is different to that in which they were taken. */ queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_QUEUE_SETS */ taskEXIT_CRITICAL(); return pdPASS; } else { if( xTicksToWait == ( TickType_t ) 0 ) { /* The queue was full and no block time is specified (or the block time has expired) so leave now. */ taskEXIT_CRITICAL(); /* Return to the original privilege level before exiting the function. */ traceQUEUE_SEND_FAILED( pxQueue ); return errQUEUE_FULL; } else if( xEntryTimeSet == pdFALSE ) { /* The queue was full and a block time was specified so configure the timeout structure. */ vTaskSetTimeOutState( &xTimeOut ); xEntryTimeSet = pdTRUE; } else { /* Entry time was already set. */ mtCOVERAGE_TEST_MARKER(); } } } taskEXIT_CRITICAL(); /* Interrupts and other tasks can send to and receive from the queue now the critical section has been exited. */ vTaskSuspendAll(); prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) { if( prvIsQueueFull( pxQueue ) != pdFALSE ) { traceBLOCKING_ON_QUEUE_SEND( pxQueue ); vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); /* Unlocking the queue means queue events can effect the event list. It is possible that interrupts occurring now remove this task from the event list again - but as the scheduler is suspended the task will go onto the pending ready last instead of the actual ready list. */ prvUnlockQueue( pxQueue ); /* Resuming the scheduler will move tasks from the pending ready list into the ready list - so it is feasible that this task is already in a ready list before it yields - in which case the yield will not cause a context switch unless there is also a higher priority task in the pending ready list. */ if( xTaskResumeAll() == pdFALSE ) { portYIELD_WITHIN_API(); } } else { /* Try again. */ prvUnlockQueue( pxQueue ); ( void ) xTaskResumeAll(); } } else { /* The timeout has expired. */ prvUnlockQueue( pxQueue ); ( void ) xTaskResumeAll(); traceQUEUE_SEND_FAILED( pxQueue ); return errQUEUE_FULL; } } } /*-----------------------------------------------------------*/ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) { BaseType_t xReturn; UBaseType_t uxSavedInterruptStatus; Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); /* Similar to xQueueGenericSend, except without blocking if there is no room in the queue. Also don't directly wake a task that was blocked on a queue read, instead return a flag to say whether a context switch is required or not (i.e. has a task with a higher priority than us been woken by this post). */ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) { const int8_t cTxLock = pxQueue->cTxLock; traceQUEUE_SEND_FROM_ISR( pxQueue ); /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a semaphore or mutex. That means prvCopyDataToQueue() cannot result in a task disinheriting a priority and prvCopyDataToQueue() can be called here even though the disinherit function does not check if the scheduler is suspended before accessing the ready lists. */ ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); /* The event list is not altered if the queue is locked. This will be done when the queue is unlocked later. */ if( cTxLock == queueUNLOCKED ) { #if ( configUSE_QUEUE_SETS == 1 ) { if( pxQueue->pxQueueSetContainer != NULL ) { if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) { /* The queue is a member of a queue set, and posting to the queue set caused a higher priority task to unblock. A context switch is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that a context switch is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } } #else /* configUSE_QUEUE_SETS */ { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that a context switch is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_QUEUE_SETS */ } else { /* Increment the lock count so the task that unlocks the queue knows that data was posted while it was locked. */ pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); } xReturn = pdPASS; } else { traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); xReturn = errQUEUE_FULL; } } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) { BaseType_t xReturn; UBaseType_t uxSavedInterruptStatus; Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* Similar to xQueueGenericSendFromISR() but used with semaphores where the item size is 0. Don't directly wake a task that was blocked on a queue read, instead return a flag to say whether a context switch is required or not (i.e. has a task with a higher priority than us been woken by this post). */ configASSERT( pxQueue ); /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() if the item size is not 0. */ configASSERT( pxQueue->uxItemSize == 0 ); /* Normally a mutex would not be given from an interrupt, especially if there is a mutex holder, as priority inheritance makes no sense for an interrupts, only tasks. */ configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) ); /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; /* When the queue is used to implement a semaphore no data is ever moved through the queue but it is still valid to see if the queue 'has space'. */ if( uxMessagesWaiting < pxQueue->uxLength ) { const int8_t cTxLock = pxQueue->cTxLock; traceQUEUE_SEND_FROM_ISR( pxQueue ); /* A task can only have an inherited priority if it is a mutex holder - and if there is a mutex holder then the mutex cannot be given from an ISR. As this is the ISR version of the function it can be assumed there is no mutex holder and no need to determine if priority disinheritance is needed. Simply increase the count of messages (semaphores) available. */ pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1; /* The event list is not altered if the queue is locked. This will be done when the queue is unlocked later. */ if( cTxLock == queueUNLOCKED ) { #if ( configUSE_QUEUE_SETS == 1 ) { if( pxQueue->pxQueueSetContainer != NULL ) { if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) { /* The semaphore is a member of a queue set, and posting to the queue set caused a higher priority task to unblock. A context switch is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that a context switch is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } } #else /* configUSE_QUEUE_SETS */ { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that a context switch is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_QUEUE_SETS */ } else { /* Increment the lock count so the task that unlocks the queue knows that data was posted while it was locked. */ pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); } xReturn = pdPASS; } else { traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); xReturn = errQUEUE_FULL; } } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking ) { BaseType_t xEntryTimeSet = pdFALSE; TimeOut_t xTimeOut; int8_t *pcOriginalReadPosition; Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) { configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); } #endif /* This function relaxes the coding standard somewhat to allow return statements within the function itself. This is done in the interest of execution time efficiency. */ for( ;; ) { taskENTER_CRITICAL(); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; /* Is there data in the queue now? To be running the calling task must be the highest priority task wanting to access the queue. */ if( uxMessagesWaiting > ( UBaseType_t ) 0 ) { /* Remember the read position in case the queue is only being peeked. */ pcOriginalReadPosition = pxQueue->u.pcReadFrom; prvCopyDataFromQueue( pxQueue, pvBuffer ); if( xJustPeeking == pdFALSE ) { traceQUEUE_RECEIVE( pxQueue ); /* Actually removing data, not just peeking. */ pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1; #if ( configUSE_MUTEXES == 1 ) { if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { /* Record the information required to implement priority inheritance should it become necessary. */ pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_MUTEXES */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { traceQUEUE_PEEK( pxQueue ); /* The data is not being removed, so reset the read pointer. */ pxQueue->u.pcReadFrom = pcOriginalReadPosition; /* The data is being left in the queue, so see if there are any other tasks waiting for the data. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority than this task. */ queueYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); return pdPASS; } else { if( xTicksToWait == ( TickType_t ) 0 ) { /* The queue was empty and no block time is specified (or the block time has expired) so leave now. */ taskEXIT_CRITICAL(); traceQUEUE_RECEIVE_FAILED( pxQueue ); return errQUEUE_EMPTY; } else if( xEntryTimeSet == pdFALSE ) { /* The queue was empty and a block time was specified so configure the timeout structure. */ vTaskSetTimeOutState( &xTimeOut ); xEntryTimeSet = pdTRUE; } else { /* Entry time was already set. */ mtCOVERAGE_TEST_MARKER(); } } } taskEXIT_CRITICAL(); /* Interrupts and other tasks can send to and receive from the queue now the critical section has been exited. */ vTaskSuspendAll(); prvLockQueue( pxQueue ); /* Update the timeout state to see if it has expired yet. */ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) { if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); #if ( configUSE_MUTEXES == 1 ) { if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { taskENTER_CRITICAL(); { vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); } taskEXIT_CRITICAL(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); prvUnlockQueue( pxQueue ); if( xTaskResumeAll() == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } else { /* Try again. */ prvUnlockQueue( pxQueue ); ( void ) xTaskResumeAll(); } } else { prvUnlockQueue( pxQueue ); ( void ) xTaskResumeAll(); if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) { traceQUEUE_RECEIVE_FAILED( pxQueue ); return errQUEUE_EMPTY; } else { mtCOVERAGE_TEST_MARKER(); } } } } /*-----------------------------------------------------------*/ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) { BaseType_t xReturn; UBaseType_t uxSavedInterruptStatus; Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; /* Cannot block in an ISR, so check there is data available. */ if( uxMessagesWaiting > ( UBaseType_t ) 0 ) { const int8_t cRxLock = pxQueue->cRxLock; traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); prvCopyDataFromQueue( pxQueue, pvBuffer ); pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1; /* If the queue is locked the event list will not be modified. Instead update the lock count so the task that unlocks the queue will know that an ISR has removed data while the queue was locked. */ if( cRxLock == queueUNLOCKED ) { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { /* The task waiting has a higher priority than us so force a context switch. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { /* Increment the lock count so the task that unlocks the queue knows that data was removed while it was locked. */ pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 ); } xReturn = pdPASS; } else { xReturn = pdFAIL; traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); } } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) { BaseType_t xReturn; UBaseType_t uxSavedInterruptStatus; int8_t *pcOriginalReadPosition; Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { /* Cannot block in an ISR, so check there is data available. */ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) { traceQUEUE_PEEK_FROM_ISR( pxQueue ); /* Remember the read position so it can be reset as nothing is actually being removed from the queue. */ pcOriginalReadPosition = pxQueue->u.pcReadFrom; prvCopyDataFromQueue( pxQueue, pvBuffer ); pxQueue->u.pcReadFrom = pcOriginalReadPosition; xReturn = pdPASS; } else { xReturn = pdFAIL; traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); } } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xReturn; } /*-----------------------------------------------------------*/ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) { UBaseType_t uxReturn; configASSERT( xQueue ); taskENTER_CRITICAL(); { uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; } taskEXIT_CRITICAL(); return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) { UBaseType_t uxReturn; Queue_t *pxQueue; pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); taskENTER_CRITICAL(); { uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; } taskEXIT_CRITICAL(); return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) { UBaseType_t uxReturn; configASSERT( xQueue ); uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ void vQueueDelete( QueueHandle_t xQueue ) { Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); traceQUEUE_DELETE( pxQueue ); #if ( configQUEUE_REGISTRY_SIZE > 0 ) { vQueueUnregisterQueue( pxQueue ); } #endif #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) { /* The queue can only have been allocated dynamically - free it again. */ vPortFree( pxQueue ); } #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) { /* The queue could have been allocated statically or dynamically, so check before attempting to free the memory. */ if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) { vPortFree( pxQueue ); } else { mtCOVERAGE_TEST_MARKER(); } } #else { /* The queue must have been statically allocated, so is not going to be deleted. Avoid compiler warnings about the unused parameter. */ ( void ) pxQueue; } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) { return ( ( Queue_t * ) xQueue )->uxQueueNumber; } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) { ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) { return ( ( Queue_t * ) xQueue )->ucQueueType; } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) { BaseType_t xReturn = pdFALSE; UBaseType_t uxMessagesWaiting; /* This function is called from a critical section. */ uxMessagesWaiting = pxQueue->uxMessagesWaiting; if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) { #if ( configUSE_MUTEXES == 1 ) { if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { /* The mutex is no longer being held. */ xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); pxQueue->pxMutexHolder = NULL; } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_MUTEXES */ } else if( xPosition == queueSEND_TO_BACK ) { ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */ pxQueue->pcWriteTo += pxQueue->uxItemSize; if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ { pxQueue->pcWriteTo = pxQueue->pcHead; } else { mtCOVERAGE_TEST_MARKER(); } } else { ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ pxQueue->u.pcReadFrom -= pxQueue->uxItemSize; if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ { pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); } else { mtCOVERAGE_TEST_MARKER(); } if( xPosition == queueOVERWRITE ) { if( uxMessagesWaiting > ( UBaseType_t ) 0 ) { /* An item is not being added but overwritten, so subtract one from the recorded number of items in the queue so when one is added again below the number of recorded items remains correct. */ --uxMessagesWaiting; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1; return xReturn; } /*-----------------------------------------------------------*/ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) { if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) { pxQueue->u.pcReadFrom += pxQueue->uxItemSize; if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ { pxQueue->u.pcReadFrom = pxQueue->pcHead; } else { mtCOVERAGE_TEST_MARKER(); } ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */ } } /*-----------------------------------------------------------*/ static void prvUnlockQueue( Queue_t * const pxQueue ) { /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ /* The lock counts contains the number of extra data items placed or removed from the queue while the queue was locked. When a queue is locked items can be added or removed, but the event lists cannot be updated. */ taskENTER_CRITICAL(); { int8_t cTxLock = pxQueue->cTxLock; /* See if data was added to the queue while it was locked. */ while( cTxLock > queueLOCKED_UNMODIFIED ) { /* Data was posted while the queue was locked. Are any tasks blocked waiting for data to become available? */ #if ( configUSE_QUEUE_SETS == 1 ) { if( pxQueue->pxQueueSetContainer != NULL ) { if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) { /* The queue is a member of a queue set, and posting to the queue set caused a higher priority task to unblock. A context switch is required. */ vTaskMissedYield(); } else { mtCOVERAGE_TEST_MARKER(); } } else { /* Tasks that are removed from the event list will get added to the pending ready list as the scheduler is still suspended. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that a context switch is required. */ vTaskMissedYield(); } else { mtCOVERAGE_TEST_MARKER(); } } else { break; } } } #else /* configUSE_QUEUE_SETS */ { /* Tasks that are removed from the event list will get added to the pending ready list as the scheduler is still suspended. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority so record that a context switch is required. */ vTaskMissedYield(); } else { mtCOVERAGE_TEST_MARKER(); } } else { break; } } #endif /* configUSE_QUEUE_SETS */ --cTxLock; } pxQueue->cTxLock = queueUNLOCKED; } taskEXIT_CRITICAL(); /* Do the same for the Rx lock. */ taskENTER_CRITICAL(); { int8_t cRxLock = pxQueue->cRxLock; while( cRxLock > queueLOCKED_UNMODIFIED ) { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { vTaskMissedYield(); } else { mtCOVERAGE_TEST_MARKER(); } --cRxLock; } else { break; } } pxQueue->cRxLock = queueUNLOCKED; } taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) { BaseType_t xReturn; taskENTER_CRITICAL(); { if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) { xReturn = pdTRUE; } else { xReturn = pdFALSE; } } taskEXIT_CRITICAL(); return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) { BaseType_t xReturn; configASSERT( xQueue ); if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( UBaseType_t ) 0 ) { xReturn = pdTRUE; } else { xReturn = pdFALSE; } return xReturn; } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ /*-----------------------------------------------------------*/ static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) { BaseType_t xReturn; taskENTER_CRITICAL(); { if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) { xReturn = pdTRUE; } else { xReturn = pdFALSE; } } taskEXIT_CRITICAL(); return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { BaseType_t xReturn; configASSERT( xQueue ); if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( ( Queue_t * ) xQueue )->uxLength ) { xReturn = pdTRUE; } else { xReturn = pdFALSE; } return xReturn; } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ) { BaseType_t xReturn; Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* If the queue is already full we may have to block. A critical section is required to prevent an interrupt removing something from the queue between the check to see if the queue is full and blocking on the queue. */ portDISABLE_INTERRUPTS(); { if( prvIsQueueFull( pxQueue ) != pdFALSE ) { /* The queue is full - do we want to block or just leave without posting? */ if( xTicksToWait > ( TickType_t ) 0 ) { /* As this is called from a coroutine we cannot block directly, but return indicating that we need to block. */ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); portENABLE_INTERRUPTS(); return errQUEUE_BLOCKED; } else { portENABLE_INTERRUPTS(); return errQUEUE_FULL; } } } portENABLE_INTERRUPTS(); portDISABLE_INTERRUPTS(); { if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) { /* There is room in the queue, copy the data into the queue. */ prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); xReturn = pdPASS; /* Were any co-routines waiting for data to become available? */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { /* In this instance the co-routine could be placed directly into the ready list as we are within a critical section. Instead the same pending ready list mechanism is used as if the event were caused from within an interrupt. */ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The co-routine waiting has a higher priority so record that a yield might be appropriate. */ xReturn = errQUEUE_YIELD; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { xReturn = errQUEUE_FULL; } } portENABLE_INTERRUPTS(); return xReturn; } #endif /* configUSE_CO_ROUTINES */ /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ) { BaseType_t xReturn; Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* If the queue is already empty we may have to block. A critical section is required to prevent an interrupt adding something to the queue between the check to see if the queue is empty and blocking on the queue. */ portDISABLE_INTERRUPTS(); { if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) { /* There are no messages in the queue, do we want to block or just leave with nothing? */ if( xTicksToWait > ( TickType_t ) 0 ) { /* As this is a co-routine we cannot block directly, but return indicating that we need to block. */ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); portENABLE_INTERRUPTS(); return errQUEUE_BLOCKED; } else { portENABLE_INTERRUPTS(); return errQUEUE_FULL; } } else { mtCOVERAGE_TEST_MARKER(); } } portENABLE_INTERRUPTS(); portDISABLE_INTERRUPTS(); { if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) { /* Data is available from the queue. */ pxQueue->u.pcReadFrom += pxQueue->uxItemSize; if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) { pxQueue->u.pcReadFrom = pxQueue->pcHead; } else { mtCOVERAGE_TEST_MARKER(); } --( pxQueue->uxMessagesWaiting ); ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); xReturn = pdPASS; /* Were any co-routines waiting for space to become available? */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { /* In this instance the co-routine could be placed directly into the ready list as we are within a critical section. Instead the same pending ready list mechanism is used as if the event were caused from within an interrupt. */ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { xReturn = errQUEUE_YIELD; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { xReturn = pdFAIL; } } portENABLE_INTERRUPTS(); return xReturn; } #endif /* configUSE_CO_ROUTINES */ /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ) { Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* Cannot block within an ISR so if there is no space on the queue then exit without doing anything. */ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) { prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); /* We only want to wake one co-routine per ISR, so check that a co-routine has not already been woken. */ if( xCoRoutinePreviouslyWoken == pdFALSE ) { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { return pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } return xCoRoutinePreviouslyWoken; } #endif /* configUSE_CO_ROUTINES */ /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken ) { BaseType_t xReturn; Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* We cannot block from an ISR, so check there is data available. If not then just leave without doing anything. */ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) { /* Copy the data from the queue. */ pxQueue->u.pcReadFrom += pxQueue->uxItemSize; if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) { pxQueue->u.pcReadFrom = pxQueue->pcHead; } else { mtCOVERAGE_TEST_MARKER(); } --( pxQueue->uxMessagesWaiting ); ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); if( ( *pxCoRoutineWoken ) == pdFALSE ) { if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { *pxCoRoutineWoken = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } xReturn = pdPASS; } else { xReturn = pdFAIL; } return xReturn; } #endif /* configUSE_CO_ROUTINES */ /*-----------------------------------------------------------*/ #if ( configQUEUE_REGISTRY_SIZE > 0 ) void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { UBaseType_t ux; /* See if there is an empty space in the registry. A NULL name denotes a free slot. */ for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) { if( xQueueRegistry[ ux ].pcQueueName == NULL ) { /* Store the information on this queue. */ xQueueRegistry[ ux ].pcQueueName = pcQueueName; xQueueRegistry[ ux ].xHandle = xQueue; traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); break; } else { mtCOVERAGE_TEST_MARKER(); } } } #endif /* configQUEUE_REGISTRY_SIZE */ /*-----------------------------------------------------------*/ #if ( configQUEUE_REGISTRY_SIZE > 0 ) const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { UBaseType_t ux; const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /* Note there is nothing here to protect against another task adding or removing entries from the registry while it is being searched. */ for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) { if( xQueueRegistry[ ux ].xHandle == xQueue ) { pcReturn = xQueueRegistry[ ux ].pcQueueName; break; } else { mtCOVERAGE_TEST_MARKER(); } } return pcReturn; } #endif /* configQUEUE_REGISTRY_SIZE */ /*-----------------------------------------------------------*/ #if ( configQUEUE_REGISTRY_SIZE > 0 ) void vQueueUnregisterQueue( QueueHandle_t xQueue ) { UBaseType_t ux; /* See if the handle of the queue being unregistered in actually in the registry. */ for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) { if( xQueueRegistry[ ux ].xHandle == xQueue ) { /* Set the name to NULL to show that this slot if free again. */ xQueueRegistry[ ux ].pcQueueName = NULL; /* Set the handle to NULL to ensure the same queue handle cannot appear in the registry twice if it is added, removed, then added again. */ xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0; break; } else { mtCOVERAGE_TEST_MARKER(); } } } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ #endif /* configQUEUE_REGISTRY_SIZE */ /*-----------------------------------------------------------*/ #if ( configUSE_TIMERS == 1 ) void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) { Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* This function should not be called by application code hence the 'Restricted' in its name. It is not part of the public API. It is designed for use by kernel code, and has special calling requirements. It can result in vListInsert() being called on a list that can only possibly ever have one item in it, so the list will be fast, but even so it should be called with the scheduler locked and not from a critical section. */ /* Only do anything if there are no messages in the queue. This function will not actually cause the task to block, just place it on a blocked list. It will not block until the scheduler is unlocked - at which time a yield will be performed. If an item is added to the queue while the queue is locked, and the calling task blocks on the queue, then the calling task will be immediately unblocked when the queue is unlocked. */ prvLockQueue( pxQueue ); if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) { /* There is nothing in the queue, block for the specified period. */ vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely ); } else { mtCOVERAGE_TEST_MARKER(); } prvUnlockQueue( pxQueue ); } #endif /* configUSE_TIMERS */ /*-----------------------------------------------------------*/ #if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) { QueueSetHandle_t pxQueue; pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); return pxQueue; } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) { BaseType_t xReturn; taskENTER_CRITICAL(); { if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) { /* Cannot add a queue/semaphore to more than one queue set. */ xReturn = pdFAIL; } else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) { /* Cannot add a queue/semaphore to a queue set if there are already items in the queue/semaphore. */ xReturn = pdFAIL; } else { ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; xReturn = pdPASS; } } taskEXIT_CRITICAL(); return xReturn; } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) { BaseType_t xReturn; Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) { /* The queue was not a member of the set. */ xReturn = pdFAIL; } else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) { /* It is dangerous to remove a queue from a set when the queue is not empty because the queue set will still hold pending events for the queue. */ xReturn = pdFAIL; } else { taskENTER_CRITICAL(); { /* The queue is no longer contained in the set. */ pxQueueOrSemaphore->pxQueueSetContainer = NULL; } taskEXIT_CRITICAL(); xReturn = pdPASS; } return xReturn; } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) { QueueSetMemberHandle_t xReturn = NULL; ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ return xReturn; } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) { QueueSetMemberHandle_t xReturn = NULL; ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ return xReturn; } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) { Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; BaseType_t xReturn = pdFALSE; /* This function must be called form a critical section. */ configASSERT( pxQueueSetContainer ); configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) { const int8_t cTxLock = pxQueueSetContainer->cTxLock; traceQUEUE_SEND( pxQueueSetContainer ); /* The data copied is the handle of the queue that contains data. */ xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); if( cTxLock == queueUNLOCKED ) { if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) { if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority. */ xReturn = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 ); } } else { mtCOVERAGE_TEST_MARKER(); } return xReturn; } #endif /* configUSE_QUEUE_SETS */ micropython-1.12/ports/cc3200/FreeRTOS/Source/tasks.c000066400000000000000000004526611357706137100222230ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /* Standard includes. */ #include #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining all the API functions to use the MPU wrappers. That should only be done when task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* FreeRTOS includes. */ #include "FreeRTOS.h" #include "task.h" #include "timers.h" #include "StackMacros.h" /* Lint e961 and e750 are suppressed as a MISRA exception justified because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the header files above, but not in this file, in order to generate the correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting functions but without including stdio.h here. */ #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) /* At the bottom of this file are two optional functions that can be used to generate human readable text from the raw data generated by the uxTaskGetSystemState() function. Note the formatting functions are provided for convenience only, and are NOT considered part of the kernel. */ #include #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */ #if( configUSE_PREEMPTION == 0 ) /* If the cooperative scheduler is being used then a yield should not be performed just because a higher priority task has been woken. */ #define taskYIELD_IF_USING_PREEMPTION() #else #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #endif /* Values that can be assigned to the ucNotifyState member of the TCB. */ #define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) #define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 ) #define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) /* * The value used to fill the stack of a task when the task is created. This * is used purely for checking the high water mark for tasks. */ #define tskSTACK_FILL_BYTE ( 0xa5U ) /* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using dynamically allocated RAM, in which case when any task is deleted it is known that both the task's stack and TCB need to be freed. Sometimes the FreeRTOSConfig.h settings only allow a task to be created using statically allocated RAM, in which case when any task is deleted it is known that neither the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h settings allow a task to be created using either statically or dynamically allocated RAM, in which case a member of the TCB is used to record whether the stack and/or TCB were allocated statically or dynamically, so when a task is deleted the RAM that was allocated dynamically is freed again and no attempt is made to free the RAM that was allocated statically. tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a task to be created using either statically or dynamically allocated RAM. Note that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with a statically allocated stack and a dynamically allocated TCB. */ #define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) ) #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 ) #define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 ) #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 ) /* * Macros used by vListTask to indicate which state a task is in. */ #define tskBLOCKED_CHAR ( 'B' ) #define tskREADY_CHAR ( 'R' ) #define tskDELETED_CHAR ( 'D' ) #define tskSUSPENDED_CHAR ( 'S' ) /* * Some kernel aware debuggers require the data the debugger needs access to be * global, rather than file scope. */ #ifdef portREMOVE_STATIC_QUALIFIER #define static #endif #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is performed in a generic way that is not optimised to any particular microcontroller architecture. */ /* uxTopReadyPriority holds the priority of the highest priority ready state task. */ #define taskRECORD_READY_PRIORITY( uxPriority ) \ { \ if( ( uxPriority ) > uxTopReadyPriority ) \ { \ uxTopReadyPriority = ( uxPriority ); \ } \ } /* taskRECORD_READY_PRIORITY */ /*-----------------------------------------------------------*/ #define taskSELECT_HIGHEST_PRIORITY_TASK() \ { \ UBaseType_t uxTopPriority = uxTopReadyPriority; \ \ /* Find the highest priority queue that contains ready tasks. */ \ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \ { \ configASSERT( uxTopPriority ); \ --uxTopPriority; \ } \ \ /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ the same priority get an equal share of the processor time. */ \ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ uxTopReadyPriority = uxTopPriority; \ } /* taskSELECT_HIGHEST_PRIORITY_TASK */ /*-----------------------------------------------------------*/ /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as they are only required when a port optimised method of task selection is being used. */ #define taskRESET_READY_PRIORITY( uxPriority ) #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is performed in a way that is tailored to the particular microcontroller architecture being used. */ /* A port optimised version is provided. Call the port defined macros. */ #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) /*-----------------------------------------------------------*/ #define taskSELECT_HIGHEST_PRIORITY_TASK() \ { \ UBaseType_t uxTopPriority; \ \ /* Find the highest priority list that contains ready tasks. */ \ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ } /* taskSELECT_HIGHEST_PRIORITY_TASK() */ /*-----------------------------------------------------------*/ /* A port optimised version is provided, call it only if the TCB being reset is being referenced from a ready list. If it is referenced from a delayed or suspended list then it won't be in a ready list. */ #define taskRESET_READY_PRIORITY( uxPriority ) \ { \ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ { \ portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ } \ } #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ /*-----------------------------------------------------------*/ /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick count overflows. */ #define taskSWITCH_DELAYED_LISTS() \ { \ List_t *pxTemp; \ \ /* The delayed tasks list should be empty when the lists are switched. */ \ configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ \ pxTemp = pxDelayedTaskList; \ pxDelayedTaskList = pxOverflowDelayedTaskList; \ pxOverflowDelayedTaskList = pxTemp; \ xNumOfOverflows++; \ prvResetNextTaskUnblockTime(); \ } /*-----------------------------------------------------------*/ /* * Place the task represented by pxTCB into the appropriate ready list for * the task. It is inserted at the end of the list. */ #define prvAddTaskToReadyList( pxTCB ) \ traceMOVED_TASK_TO_READY_STATE( pxTCB ); \ taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \ tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) /*-----------------------------------------------------------*/ /* * Several functions take an TaskHandle_t parameter that can optionally be NULL, * where NULL is used to indicate that the handle of the currently executing * task should be used in place of the parameter. This macro simply checks to * see if the parameter is NULL and returns a pointer to the appropriate TCB. */ #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) ) /* The item value of the event list item is normally used to hold the priority of the task to which it belongs (coded to allow it to be held in reverse priority order). However, it is occasionally borrowed for other purposes. It is important its value is not updated due to a task priority change while it is being used for another purpose. The following bit definition is used to inform the scheduler that the value should not be changed - in which case it is the responsibility of whichever module is using the value to ensure it gets set back to its original value when it is released. */ #if( configUSE_16_BIT_TICKS == 1 ) #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U #else #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL #endif /* * Task control block. A task control block (TCB) is allocated for each task, * and stores task state information, including a pointer to the task's context * (the task's run time environment, including register values) */ typedef struct tskTaskControlBlock { volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ #if ( portUSING_MPU_WRAPPERS == 1 ) xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ #endif ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ StackType_t *pxStack; /*< Points to the start of the stack. */ char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #if ( portSTACK_GROWTH > 0 ) StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */ #endif #if ( portCRITICAL_NESTING_IN_TCB == 1 ) UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ #endif #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ #endif #if ( configUSE_MUTEXES == 1 ) UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ UBaseType_t uxMutexesHeld; #endif #if ( configUSE_APPLICATION_TASK_TAG == 1 ) TaskHookFunction_t pxTaskTag; #endif #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; #endif #if( configGENERATE_RUN_TIME_STATS == 1 ) uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ #endif #if ( configUSE_NEWLIB_REENTRANT == 1 ) /* Allocate a Newlib reent structure that is specific to this task. Note Newlib support has been included by popular demand, but is not used by the FreeRTOS maintainers themselves. FreeRTOS is not responsible for resulting newlib operation. User must be familiar with newlib and must provide system-wide implementations of the necessary stubs. Be warned that (at the time of writing) the current newlib design implements a system-wide malloc() that must be provided with locks. */ struct _reent xNewLib_reent; #endif #if( configUSE_TASK_NOTIFICATIONS == 1 ) volatile uint32_t ulNotifiedValue; volatile uint8_t ucNotifyState; #endif /* See the comments above the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ #endif #if( INCLUDE_xTaskAbortDelay == 1 ) uint8_t ucDelayAborted; #endif } tskTCB; /* The old tskTCB name is maintained above then typedefed to the new TCB_t name below to enable the use of older kernel aware debuggers. */ typedef tskTCB TCB_t; /*lint -e956 A manual analysis and inspection has been used to determine which static variables must be declared volatile. */ PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; /* Lists for ready and blocked tasks. --------------------*/ PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */ PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ #if( INCLUDE_vTaskDelete == 1 ) PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */ PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U; #endif #if ( INCLUDE_vTaskSuspend == 1 ) PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */ #endif /* Other file private variables. --------------------------------*/ PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U; PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U; PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE; PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U; PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */ PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ /* Context switches are held pending while the scheduler is suspended. Also, interrupts must not manipulate the xStateListItem of a TCB, or any of the lists the xStateListItem can be referenced from, if the scheduler is suspended. If an interrupt needs to unblock a task while the scheduler is suspended then it moves the task's event list item into the xPendingReadyList, ready for the kernel to move the task from the pending ready list into the real ready list when the scheduler is unsuspended. The pending ready list itself can only be accessed from a critical section. */ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE; #if ( configGENERATE_RUN_TIME_STATS == 1 ) PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ #endif /*lint +e956 */ /*-----------------------------------------------------------*/ /* Callback function prototypes. --------------------------*/ #if( configCHECK_FOR_STACK_OVERFLOW > 0 ) extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ); #endif #if( configUSE_TICK_HOOK > 0 ) extern void vApplicationTickHook( void ); #endif #if( configSUPPORT_STATIC_ALLOCATION == 1 ) extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); #endif /* File private functions. --------------------------------*/ /** * Utility task that simply returns pdTRUE if the task referenced by xTask is * currently in the Suspended state, or pdFALSE if the task referenced by xTask * is in any other state. */ #if ( INCLUDE_vTaskSuspend == 1 ) static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #endif /* INCLUDE_vTaskSuspend */ /* * Utility to ready all the lists used by the scheduler. This is called * automatically upon the creation of the first task. */ static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; /* * The idle task, which as all tasks is implemented as a never ending loop. * The idle task is automatically created and added to the ready lists upon * creation of the first user task. * * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific * language extensions. The equivalent prototype for this function is: * * void prvIdleTask( void *pvParameters ); * */ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); /* * Utility to free all memory allocated by the scheduler to hold a TCB, * including the stack pointed to by the TCB. * * This does not free memory allocated by the task itself (i.e. memory * allocated by calls to pvPortMalloc from within the tasks application code). */ #if ( INCLUDE_vTaskDelete == 1 ) static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION; #endif /* * Used only by the idle task. This checks to see if anything has been placed * in the list of tasks waiting to be deleted. If so the task is cleaned up * and its TCB deleted. */ static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; /* * The currently executing task is entering the Blocked state. Add the task to * either the current or the overflow delayed task list. */ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION; /* * Fills an TaskStatus_t structure with information on each task that is * referenced from the pxList list (which may be a ready list, a delayed list, * a suspended list, etc.). * * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM * NORMAL APPLICATION CODE. */ #if ( configUSE_TRACE_FACILITY == 1 ) static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION; #endif /* * Searches pxList for a task with name pcNameToQuery - returning a handle to * the task if it is found, or NULL if the task is not found. */ #if ( INCLUDE_xTaskGetHandle == 1 ) static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION; #endif /* * When a task is created, the stack of the task is filled with a known value. * This function determines the 'high water mark' of the task stack by * determining how much of the stack remains at the original preset value. */ #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION; #endif /* * Return the amount of time, in ticks, that will pass before the kernel will * next move a task from the Blocked state to the Running state. * * This conditional compilation should use inequality to 0, not equality to 1. * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user * defined low power mode implementations require configUSE_TICKLESS_IDLE to be * set to a value other than 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; #endif /* * Set xNextTaskUnblockTime to the time at which the next Blocked state task * will exit the Blocked state. */ static void prvResetNextTaskUnblockTime( void ); #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) /* * Helper function used to pad task names with spaces when printing out * human readable tables of task information. */ static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION; #endif /* * Called after a Task_t structure has been allocated either statically or * dynamically to fill in the structure's members. */ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB, const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /* * Called after a new task has been created and initialised to place the task * under the control of the scheduler. */ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; /*-----------------------------------------------------------*/ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { TCB_t *pxNewTCB; TaskHandle_t xReturn; configASSERT( puxStackBuffer != NULL ); configASSERT( pxTaskBuffer != NULL ); if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) ) { /* The memory used for the task's TCB and stack are passed into this function - use them. */ pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer; #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) { /* Tasks can be created statically or dynamically, so note this task was created statically in case the task is later deleted. */ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL ); prvAddNewTaskToReadyList( pxNewTCB ); } else { xReturn = NULL; } return xReturn; } #endif /* SUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ #if( portUSING_MPU_WRAPPERS == 1 ) BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) { TCB_t *pxNewTCB; BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; configASSERT( pxTaskDefinition->puxStackBuffer ); if( pxTaskDefinition->puxStackBuffer != NULL ) { /* Allocate space for the TCB. Where the memory comes from depends on the implementation of the port malloc function and whether or not static allocation is being used. */ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); if( pxNewTCB != NULL ) { /* Store the stack location in the TCB. */ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; /* Tasks can be created statically or dynamically, so note this task had a statically allocated stack in case it is later deleted. The TCB was allocated dynamically. */ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, pxTaskDefinition->pcName, ( uint32_t ) pxTaskDefinition->usStackDepth, pxTaskDefinition->pvParameters, pxTaskDefinition->uxPriority, pxCreatedTask, pxNewTCB, pxTaskDefinition->xRegions ); prvAddNewTaskToReadyList( pxNewTCB ); xReturn = pdPASS; } } return xReturn; } #endif /* portUSING_MPU_WRAPPERS */ /*-----------------------------------------------------------*/ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { TCB_t *pxNewTCB; BaseType_t xReturn; /* If the stack grows down then allocate the stack then the TCB so the stack does not grow into the TCB. Likewise if the stack grows up then allocate the TCB then the stack. */ #if( portSTACK_GROWTH > 0 ) { /* Allocate space for the TCB. Where the memory comes from depends on the implementation of the port malloc function and whether or not static allocation is being used. */ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); if( pxNewTCB != NULL ) { /* Allocate space for the stack used by the task being created. The base of the stack memory stored in the TCB so the task can be deleted later if required. */ pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ if( pxNewTCB->pxStack == NULL ) { /* Could not allocate the stack. Delete the allocated TCB. */ vPortFree( pxNewTCB ); pxNewTCB = NULL; } } } #else /* portSTACK_GROWTH */ { StackType_t *pxStack; /* Allocate space for the stack used by the task being created. */ pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ if( pxStack != NULL ) { /* Allocate space for the TCB. */ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */ if( pxNewTCB != NULL ) { /* Store the stack location in the TCB. */ pxNewTCB->pxStack = pxStack; } else { /* The stack cannot be used as the TCB was not created. Free it again. */ vPortFree( pxStack ); } } else { pxNewTCB = NULL; } } #endif /* portSTACK_GROWTH */ if( pxNewTCB != NULL ) { #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) { /* Tasks can be created statically or dynamically, so note this task was created dynamically in case it is later deleted. */ pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; } #endif /* configSUPPORT_STATIC_ALLOCATION */ prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL ); prvAddNewTaskToReadyList( pxNewTCB ); xReturn = pdPASS; } else { xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; } return xReturn; } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { StackType_t *pxTopOfStack; UBaseType_t x; #if( portUSING_MPU_WRAPPERS == 1 ) /* Should the task be created in privileged mode? */ BaseType_t xRunPrivileged; if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) { xRunPrivileged = pdTRUE; } else { xRunPrivileged = pdFALSE; } uxPriority &= ~portPRIVILEGE_BIT; #endif /* portUSING_MPU_WRAPPERS == 1 */ /* Avoid dependency on memset() if it is not required. */ #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) { /* Fill the stack with a known value to assist debugging. */ ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) ); } #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */ /* Calculate the top of stack address. This depends on whether the stack grows from high memory to low (as per the 80x86) or vice versa. portSTACK_GROWTH is used to make the result positive or negative as required by the port. */ #if( portSTACK_GROWTH < 0 ) { pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */ /* Check the alignment of the calculated top of stack is correct. */ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); } #else /* portSTACK_GROWTH */ { pxTopOfStack = pxNewTCB->pxStack; /* Check the alignment of the stack buffer is correct. */ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); /* The other extreme of the stack space is required if stack checking is performed. */ pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); } #endif /* portSTACK_GROWTH */ /* Store the task name in the TCB. */ for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) { pxNewTCB->pcTaskName[ x ] = pcName[ x ]; /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than configMAX_TASK_NAME_LEN characters just in case the memory after the string is not accessible (extremely unlikely). */ if( pcName[ x ] == 0x00 ) { break; } else { mtCOVERAGE_TEST_MARKER(); } } /* Ensure the name string is terminated in the case that the string length was greater or equal to configMAX_TASK_NAME_LEN. */ pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; /* This is used as an array index so must ensure it's not too large. First remove the privilege bit if one is present. */ if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) { uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; } else { mtCOVERAGE_TEST_MARKER(); } pxNewTCB->uxPriority = uxPriority; #if ( configUSE_MUTEXES == 1 ) { pxNewTCB->uxBasePriority = uxPriority; pxNewTCB->uxMutexesHeld = 0; } #endif /* configUSE_MUTEXES */ vListInitialiseItem( &( pxNewTCB->xStateListItem ) ); vListInitialiseItem( &( pxNewTCB->xEventListItem ) ); /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get back to the containing TCB from a generic item in a list. */ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB ); /* Event lists are always in priority order. */ listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB ); #if ( portCRITICAL_NESTING_IN_TCB == 1 ) { pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U; } #endif /* portCRITICAL_NESTING_IN_TCB */ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) { pxNewTCB->pxTaskTag = NULL; } #endif /* configUSE_APPLICATION_TASK_TAG */ #if ( configGENERATE_RUN_TIME_STATS == 1 ) { pxNewTCB->ulRunTimeCounter = 0UL; } #endif /* configGENERATE_RUN_TIME_STATS */ #if ( portUSING_MPU_WRAPPERS == 1 ) { vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth ); } #else { /* Avoid compiler warning about unreferenced parameter. */ ( void ) xRegions; } #endif #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) { for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) { pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL; } } #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) { pxNewTCB->ulNotifiedValue = 0; pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; } #endif #if ( configUSE_NEWLIB_REENTRANT == 1 ) { /* Initialise this task's Newlib reent structure. */ _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); } #endif #if( INCLUDE_xTaskAbortDelay == 1 ) { pxNewTCB->ucDelayAborted = pdFALSE; } #endif /* Initialize the TCB stack to look as if the task was already running, but had been interrupted by the scheduler. The return address is set to the start of the task function. Once the stack has been initialised the top of stack variable is updated. */ #if( portUSING_MPU_WRAPPERS == 1 ) { pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); } #else /* portUSING_MPU_WRAPPERS */ { pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); } #endif /* portUSING_MPU_WRAPPERS */ if( ( void * ) pxCreatedTask != NULL ) { /* Pass the handle out in an anonymous way. The handle can be used to change the created task's priority, delete the created task, etc.*/ *pxCreatedTask = ( TaskHandle_t ) pxNewTCB; } else { mtCOVERAGE_TEST_MARKER(); } } /*-----------------------------------------------------------*/ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) { /* Ensure interrupts don't access the task lists while the lists are being updated. */ taskENTER_CRITICAL(); { uxCurrentNumberOfTasks++; if( pxCurrentTCB == NULL ) { /* There are no other tasks, or all the other tasks are in the suspended state - make this the current task. */ pxCurrentTCB = pxNewTCB; if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) { /* This is the first task to be created so do the preliminary initialisation required. We will not recover if this call fails, but we will report the failure. */ prvInitialiseTaskLists(); } else { mtCOVERAGE_TEST_MARKER(); } } else { /* If the scheduler is not already running, make this task the current task if it is the highest priority task to be created so far. */ if( xSchedulerRunning == pdFALSE ) { if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority ) { pxCurrentTCB = pxNewTCB; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } uxTaskNumber++; #if ( configUSE_TRACE_FACILITY == 1 ) { /* Add a counter into the TCB for tracing only. */ pxNewTCB->uxTCBNumber = uxTaskNumber; } #endif /* configUSE_TRACE_FACILITY */ traceTASK_CREATE( pxNewTCB ); prvAddTaskToReadyList( pxNewTCB ); portSETUP_TCB( pxNewTCB ); } taskEXIT_CRITICAL(); if( xSchedulerRunning != pdFALSE ) { /* If the created task is of a higher priority than the current task then it should run now. */ if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority ) { taskYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelete == 1 ) void vTaskDelete( TaskHandle_t xTaskToDelete ) { TCB_t *pxTCB; taskENTER_CRITICAL(); { /* If null is passed in here then it is the calling task that is being deleted. */ pxTCB = prvGetTCBFromHandle( xTaskToDelete ); /* Remove task from the ready list. */ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } else { mtCOVERAGE_TEST_MARKER(); } /* Is the task waiting on an event also? */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); } else { mtCOVERAGE_TEST_MARKER(); } /* Increment the uxTaskNumber also so kernel aware debuggers can detect that the task lists need re-generating. This is done before portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will not return. */ uxTaskNumber++; if( pxTCB == pxCurrentTCB ) { /* A task is deleting itself. This cannot complete within the task itself, as a context switch to another task is required. Place the task in the termination list. The idle task will check the termination list and free up any memory allocated by the scheduler for the TCB and stack of the deleted task. */ vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) ); /* Increment the ucTasksDeleted variable so the idle task knows there is a task that has been deleted and that it should therefore check the xTasksWaitingTermination list. */ ++uxDeletedTasksWaitingCleanUp; /* The pre-delete hook is primarily for the Windows simulator, in which Windows specific clean up operations are performed, after which it is not possible to yield away from this task - hence xYieldPending is used to latch that a context switch is required. */ portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); } else { --uxCurrentNumberOfTasks; prvDeleteTCB( pxTCB ); /* Reset the next expected unblock time in case it referred to the task that has just been deleted. */ prvResetNextTaskUnblockTime(); } traceTASK_DELETE( pxTCB ); } taskEXIT_CRITICAL(); /* Force a reschedule if it is the currently running task that has just been deleted. */ if( xSchedulerRunning != pdFALSE ) { if( pxTCB == pxCurrentTCB ) { configASSERT( uxSchedulerSuspended == 0 ); portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } } #endif /* INCLUDE_vTaskDelete */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelayUntil == 1 ) void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) { TickType_t xTimeToWake; BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; configASSERT( pxPreviousWakeTime ); configASSERT( ( xTimeIncrement > 0U ) ); configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll(); { /* Minor optimisation. The tick count cannot change in this block. */ const TickType_t xConstTickCount = xTickCount; /* Generate the tick time at which the task wants to wake. */ xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; if( xConstTickCount < *pxPreviousWakeTime ) { /* The tick count has overflowed since this function was lasted called. In this case the only time we should ever actually delay is if the wake time has also overflowed, and the wake time is greater than the tick time. When this is the case it is as if neither time had overflowed. */ if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) { xShouldDelay = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { /* The tick time has not overflowed. In this case we will delay if either the wake time has overflowed, and/or the tick time is less than the wake time. */ if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) { xShouldDelay = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } /* Update the wake time ready for the next call. */ *pxPreviousWakeTime = xTimeToWake; if( xShouldDelay != pdFALSE ) { traceTASK_DELAY_UNTIL( xTimeToWake ); /* prvAddCurrentTaskToDelayedList() needs the block time, not the time to wake, so subtract the current tick count. */ prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE ); } else { mtCOVERAGE_TEST_MARKER(); } } xAlreadyYielded = xTaskResumeAll(); /* Force a reschedule if xTaskResumeAll has not already done so, we may have put ourselves to sleep. */ if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* INCLUDE_vTaskDelayUntil */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelay == 1 ) void vTaskDelay( const TickType_t xTicksToDelay ) { BaseType_t xAlreadyYielded = pdFALSE; /* A delay time of zero just forces a reschedule. */ if( xTicksToDelay > ( TickType_t ) 0U ) { configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll(); { traceTASK_DELAY(); /* A task that is removed from the event list while the scheduler is suspended will not get placed in the ready list or removed from the blocked list until the scheduler is resumed. This task cannot be in an event list as it is the currently executing task. */ prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE ); } xAlreadyYielded = xTaskResumeAll(); } else { mtCOVERAGE_TEST_MARKER(); } /* Force a reschedule if xTaskResumeAll has not already done so, we may have put ourselves to sleep. */ if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* INCLUDE_vTaskDelay */ /*-----------------------------------------------------------*/ #if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) ) eTaskState eTaskGetState( TaskHandle_t xTask ) { eTaskState eReturn; List_t *pxStateList; const TCB_t * const pxTCB = ( TCB_t * ) xTask; configASSERT( pxTCB ); if( pxTCB == pxCurrentTCB ) { /* The task calling this function is querying its own state. */ eReturn = eRunning; } else { taskENTER_CRITICAL(); { pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); } taskEXIT_CRITICAL(); if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) ) { /* The task being queried is referenced from one of the Blocked lists. */ eReturn = eBlocked; } #if ( INCLUDE_vTaskSuspend == 1 ) else if( pxStateList == &xSuspendedTaskList ) { /* The task being queried is referenced from the suspended list. Is it genuinely suspended or is it block indefinitely? */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) { eReturn = eSuspended; } else { eReturn = eBlocked; } } #endif #if ( INCLUDE_vTaskDelete == 1 ) else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) ) { /* The task being queried is referenced from the deleted tasks list, or it is not referenced from any lists at all. */ eReturn = eDeleted; } #endif else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */ { /* If the task is not in any other state, it must be in the Ready (including pending ready) state. */ eReturn = eReady; } } return eReturn; } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ #endif /* INCLUDE_eTaskGetState */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskPriorityGet == 1 ) UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) { TCB_t *pxTCB; UBaseType_t uxReturn; taskENTER_CRITICAL(); { /* If null is passed in here then it is the priority of the that called uxTaskPriorityGet() that is being queried. */ pxTCB = prvGetTCBFromHandle( xTask ); uxReturn = pxTCB->uxPriority; } taskEXIT_CRITICAL(); return uxReturn; } #endif /* INCLUDE_uxTaskPriorityGet */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskPriorityGet == 1 ) UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) { TCB_t *pxTCB; UBaseType_t uxReturn, uxSavedInterruptState; /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are keep permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR(); { /* If null is passed in here then it is the priority of the calling task that is being queried. */ pxTCB = prvGetTCBFromHandle( xTask ); uxReturn = pxTCB->uxPriority; } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState ); return uxReturn; } #endif /* INCLUDE_uxTaskPriorityGet */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskPrioritySet == 1 ) void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) { TCB_t *pxTCB; UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry; BaseType_t xYieldRequired = pdFALSE; configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); /* Ensure the new priority is valid. */ if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) { uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; } else { mtCOVERAGE_TEST_MARKER(); } taskENTER_CRITICAL(); { /* If null is passed in here then it is the priority of the calling task that is being changed. */ pxTCB = prvGetTCBFromHandle( xTask ); traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); #if ( configUSE_MUTEXES == 1 ) { uxCurrentBasePriority = pxTCB->uxBasePriority; } #else { uxCurrentBasePriority = pxTCB->uxPriority; } #endif if( uxCurrentBasePriority != uxNewPriority ) { /* The priority change may have readied a task of higher priority than the calling task. */ if( uxNewPriority > uxCurrentBasePriority ) { if( pxTCB != pxCurrentTCB ) { /* The priority of a task other than the currently running task is being raised. Is the priority being raised above that of the running task? */ if( uxNewPriority >= pxCurrentTCB->uxPriority ) { xYieldRequired = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { /* The priority of the running task is being raised, but the running task must already be the highest priority task able to run so no yield is required. */ } } else if( pxTCB == pxCurrentTCB ) { /* Setting the priority of the running task down means there may now be another task of higher priority that is ready to execute. */ xYieldRequired = pdTRUE; } else { /* Setting the priority of any other task down does not require a yield as the running task must be above the new priority of the task being modified. */ } /* Remember the ready list the task might be referenced from before its uxPriority member is changed so the taskRESET_READY_PRIORITY() macro can function correctly. */ uxPriorityUsedOnEntry = pxTCB->uxPriority; #if ( configUSE_MUTEXES == 1 ) { /* Only change the priority being used if the task is not currently using an inherited priority. */ if( pxTCB->uxBasePriority == pxTCB->uxPriority ) { pxTCB->uxPriority = uxNewPriority; } else { mtCOVERAGE_TEST_MARKER(); } /* The base priority gets set whatever. */ pxTCB->uxBasePriority = uxNewPriority; } #else { pxTCB->uxPriority = uxNewPriority; } #endif /* Only reset the event list item value if the value is not being used for anything else. */ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) { listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ } else { mtCOVERAGE_TEST_MARKER(); } /* If the task is in the blocked or suspended list we need do nothing more than change it's priority variable. However, if the task is in a ready list it needs to be removed and placed in the list appropriate to its new priority. */ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) { /* The task is currently in its ready list - remove before adding it to it's new ready list. As we are in a critical section we can do this even if the scheduler is suspended. */ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { /* It is known that the task is in its ready list so there is no need to check again and the port level reset macro can be called directly. */ portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); } else { mtCOVERAGE_TEST_MARKER(); } prvAddTaskToReadyList( pxTCB ); } else { mtCOVERAGE_TEST_MARKER(); } if( xYieldRequired != pdFALSE ) { taskYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } /* Remove compiler warning about unused variables when the port optimised task selection is not being used. */ ( void ) uxPriorityUsedOnEntry; } } taskEXIT_CRITICAL(); } #endif /* INCLUDE_vTaskPrioritySet */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) void vTaskSuspend( TaskHandle_t xTaskToSuspend ) { TCB_t *pxTCB; taskENTER_CRITICAL(); { /* If null is passed in here then it is the running task that is being suspended. */ pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); traceTASK_SUSPEND( pxTCB ); /* Remove task from the ready/delayed list and place in the suspended list. */ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } else { mtCOVERAGE_TEST_MARKER(); } /* Is the task waiting on an event also? */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); } else { mtCOVERAGE_TEST_MARKER(); } vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); } taskEXIT_CRITICAL(); if( xSchedulerRunning != pdFALSE ) { /* Reset the next expected unblock time in case it referred to the task that is now in the Suspended state. */ taskENTER_CRITICAL(); { prvResetNextTaskUnblockTime(); } taskEXIT_CRITICAL(); } else { mtCOVERAGE_TEST_MARKER(); } if( pxTCB == pxCurrentTCB ) { if( xSchedulerRunning != pdFALSE ) { /* The current task has just been suspended. */ configASSERT( uxSchedulerSuspended == 0 ); portYIELD_WITHIN_API(); } else { /* The scheduler is not running, but the task that was pointed to by pxCurrentTCB has just been suspended and pxCurrentTCB must be adjusted to point to a different task. */ if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) { /* No other tasks are ready, so set pxCurrentTCB back to NULL so when the next task is created pxCurrentTCB will be set to point to it no matter what its relative priority is. */ pxCurrentTCB = NULL; } else { vTaskSwitchContext(); } } } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* INCLUDE_vTaskSuspend */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) { BaseType_t xReturn = pdFALSE; const TCB_t * const pxTCB = ( TCB_t * ) xTask; /* Accesses xPendingReadyList so must be called from a critical section. */ /* It does not make sense to check if the calling task is suspended. */ configASSERT( xTask ); /* Is the task being resumed actually in the suspended list? */ if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE ) { /* Has the task already been resumed from within an ISR? */ if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE ) { /* Is it in the suspended list because it is in the Suspended state, or because is is blocked with no timeout? */ if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) { xReturn = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } return xReturn; } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ #endif /* INCLUDE_vTaskSuspend */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) void vTaskResume( TaskHandle_t xTaskToResume ) { TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; /* It does not make sense to resume the calling task. */ configASSERT( xTaskToResume ); /* The parameter cannot be NULL as it is impossible to resume the currently executing task. */ if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) { taskENTER_CRITICAL(); { if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) { traceTASK_RESUME( pxTCB ); /* As we are in a critical section we can access the ready lists even if the scheduler is suspended. */ ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); /* We may have just resumed a higher priority task. */ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) { /* This yield may not cause the task just resumed to run, but will leave the lists in the correct state for the next yield. */ taskYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* INCLUDE_vTaskSuspend */ /*-----------------------------------------------------------*/ #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) { BaseType_t xYieldRequired = pdFALSE; TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; UBaseType_t uxSavedInterruptStatus; configASSERT( xTaskToResume ); /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are keep permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) { traceTASK_RESUME_FROM_ISR( pxTCB ); /* Check the ready lists can be accessed. */ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { /* Ready lists can be accessed so move the task from the suspended list to the ready list directly. */ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) { xYieldRequired = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); } else { /* The delayed or ready lists cannot be accessed so the task is held in the pending ready list until the scheduler is unsuspended. */ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); } } else { mtCOVERAGE_TEST_MARKER(); } } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xYieldRequired; } #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */ /*-----------------------------------------------------------*/ void vTaskStartScheduler( void ) { BaseType_t xReturn; /* Add the idle task at the lowest priority. */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { StaticTask_t *pxIdleTaskTCBBuffer = NULL; StackType_t *pxIdleTaskStackBuffer = NULL; uint32_t ulIdleTaskStackSize; /* The Idle task is created using user provided RAM - obtain the address of the RAM then create the idle task. */ vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize ); xIdleTaskHandle = xTaskCreateStatic( prvIdleTask, "IDLE", ulIdleTaskStackSize, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), pxIdleTaskStackBuffer, pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ if( xIdleTaskHandle != NULL ) { xReturn = pdPASS; } else { xReturn = pdFAIL; } } #else { /* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreate( prvIdleTask, "IDLE", configMINIMAL_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ } #endif /* configSUPPORT_STATIC_ALLOCATION */ #if ( configUSE_TIMERS == 1 ) { if( xReturn == pdPASS ) { xReturn = xTimerCreateTimerTask(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_TIMERS */ if( xReturn == pdPASS ) { /* Interrupts are turned off here, to ensure a tick does not occur before or during the call to xPortStartScheduler(). The stacks of the created tasks contain a status word with interrupts switched on so interrupts will automatically get re-enabled when the first task starts to run. */ portDISABLE_INTERRUPTS(); #if ( configUSE_NEWLIB_REENTRANT == 1 ) { /* Switch Newlib's _impure_ptr variable to point to the _reent structure specific to the task that will run first. */ _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); } #endif /* configUSE_NEWLIB_REENTRANT */ xNextTaskUnblockTime = portMAX_DELAY; xSchedulerRunning = pdTRUE; xTickCount = ( TickType_t ) 0U; /* If configGENERATE_RUN_TIME_STATS is defined then the following macro must be defined to configure the timer/counter used to generate the run time counter time base. */ portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); /* Setting up the timer tick is hardware specific and thus in the portable interface. */ if( xPortStartScheduler() != pdFALSE ) { /* Should not reach here as if the scheduler is running the function will not return. */ } else { /* Should only reach here if a task calls xTaskEndScheduler(). */ } } else { /* This line will only be reached if the kernel could not be started, because there was not enough FreeRTOS heap to create the idle task or the timer task. */ configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ); } /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0, meaning xIdleTaskHandle is not used anywhere else. */ ( void ) xIdleTaskHandle; } /*-----------------------------------------------------------*/ void vTaskEndScheduler( void ) { /* Stop the scheduler interrupts and call the portable scheduler end routine so the original ISRs can be restored if necessary. The port layer must ensure interrupts enable bit is left in the correct state. */ portDISABLE_INTERRUPTS(); xSchedulerRunning = pdFALSE; vPortEndScheduler(); } /*----------------------------------------------------------*/ void vTaskSuspendAll( void ) { /* A critical section is not required as the variable is of type BaseType_t. Please read Richard Barry's reply in the following link to a post in the FreeRTOS support forum before reporting this as a bug! - http://goo.gl/wu4acr */ ++uxSchedulerSuspended; } /*----------------------------------------------------------*/ #if ( configUSE_TICKLESS_IDLE != 0 ) static TickType_t prvGetExpectedIdleTime( void ) { TickType_t xReturn; UBaseType_t uxHigherPriorityReadyTasks = pdFALSE; /* uxHigherPriorityReadyTasks takes care of the case where configUSE_PREEMPTION is 0, so there may be tasks above the idle priority task that are in the Ready state, even though the idle task is running. */ #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) { if( uxTopReadyPriority > tskIDLE_PRIORITY ) { uxHigherPriorityReadyTasks = pdTRUE; } } #else { const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01; /* When port optimised task selection is used the uxTopReadyPriority variable is used as a bit map. If bits other than the least significant bit are set then there are tasks that have a priority above the idle priority that are in the Ready state. This takes care of the case where the co-operative scheduler is in use. */ if( uxTopReadyPriority > uxLeastSignificantBit ) { uxHigherPriorityReadyTasks = pdTRUE; } } #endif if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY ) { xReturn = 0; } else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) { /* There are other idle priority tasks in the ready state. If time slicing is used then the very next tick interrupt must be processed. */ xReturn = 0; } else if( uxHigherPriorityReadyTasks != pdFALSE ) { /* There are tasks in the Ready state that have a priority above the idle priority. This path can only be reached if configUSE_PREEMPTION is 0. */ xReturn = 0; } else { xReturn = xNextTaskUnblockTime - xTickCount; } return xReturn; } #endif /* configUSE_TICKLESS_IDLE */ /*----------------------------------------------------------*/ BaseType_t xTaskResumeAll( void ) { TCB_t *pxTCB = NULL; BaseType_t xAlreadyYielded = pdFALSE; /* If uxSchedulerSuspended is zero then this function does not match a previous call to vTaskSuspendAll(). */ configASSERT( uxSchedulerSuspended ); /* It is possible that an ISR caused a task to be removed from an event list while the scheduler was suspended. If this was the case then the removed task will have been added to the xPendingReadyList. Once the scheduler has been resumed it is safe to move all the pending ready tasks from this list into their appropriate ready list. */ taskENTER_CRITICAL(); { --uxSchedulerSuspended; if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) { /* Move any readied tasks from the pending list into the appropriate ready list. */ while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) { pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); /* If the moved task has a priority higher than the current task then a yield must be performed. */ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) { xYieldPending = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } if( pxTCB != NULL ) { /* A task was unblocked while the scheduler was suspended, which may have prevented the next unblock time from being re-calculated, in which case re-calculate it now. Mainly important for low power tickless implementations, where this can prevent an unnecessary exit from low power state. */ prvResetNextTaskUnblockTime(); } /* If any ticks occurred while the scheduler was suspended then they should be processed now. This ensures the tick count does not slip, and that any delayed tasks are resumed at the correct time. */ { UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */ if( uxPendedCounts > ( UBaseType_t ) 0U ) { do { if( xTaskIncrementTick() != pdFALSE ) { xYieldPending = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } --uxPendedCounts; } while( uxPendedCounts > ( UBaseType_t ) 0U ); uxPendedTicks = 0; } else { mtCOVERAGE_TEST_MARKER(); } } if( xYieldPending != pdFALSE ) { #if( configUSE_PREEMPTION != 0 ) { xAlreadyYielded = pdTRUE; } #endif taskYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); return xAlreadyYielded; } /*-----------------------------------------------------------*/ TickType_t xTaskGetTickCount( void ) { TickType_t xTicks; /* Critical section required if running on a 16 bit processor. */ portTICK_TYPE_ENTER_CRITICAL(); { xTicks = xTickCount; } portTICK_TYPE_EXIT_CRITICAL(); return xTicks; } /*-----------------------------------------------------------*/ TickType_t xTaskGetTickCountFromISR( void ) { TickType_t xReturn; UBaseType_t uxSavedInterruptStatus; /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR(); { xReturn = xTickCount; } portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xReturn; } /*-----------------------------------------------------------*/ UBaseType_t uxTaskGetNumberOfTasks( void ) { /* A critical section is not required because the variables are of type BaseType_t. */ return uxCurrentNumberOfTasks; } /*-----------------------------------------------------------*/ char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { TCB_t *pxTCB; /* If null is passed in here then the name of the calling task is being queried. */ pxTCB = prvGetTCBFromHandle( xTaskToQuery ); configASSERT( pxTCB ); return &( pxTCB->pcTaskName[ 0 ] ); } /*-----------------------------------------------------------*/ #if ( INCLUDE_xTaskGetHandle == 1 ) static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) { TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL; UBaseType_t x; char cNextChar; /* This function is called with the scheduler suspended. */ if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) { listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); do { listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /* Check each character in the name looking for a match or mismatch. */ for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) { cNextChar = pxNextTCB->pcTaskName[ x ]; if( cNextChar != pcNameToQuery[ x ] ) { /* Characters didn't match. */ break; } else if( cNextChar == 0x00 ) { /* Both strings terminated, a match must have been found. */ pxReturn = pxNextTCB; break; } else { mtCOVERAGE_TEST_MARKER(); } } if( pxReturn != NULL ) { /* The handle has been found. */ break; } } while( pxNextTCB != pxFirstTCB ); } else { mtCOVERAGE_TEST_MARKER(); } return pxReturn; } #endif /* INCLUDE_xTaskGetHandle */ /*-----------------------------------------------------------*/ #if ( INCLUDE_xTaskGetHandle == 1 ) TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { UBaseType_t uxQueue = configMAX_PRIORITIES; TCB_t* pxTCB; /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */ configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN ); vTaskSuspendAll(); { /* Search the ready lists. */ do { uxQueue--; pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery ); if( pxTCB != NULL ) { /* Found the handle. */ break; } } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ /* Search the delayed lists. */ if( pxTCB == NULL ) { pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery ); } if( pxTCB == NULL ) { pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery ); } #if ( INCLUDE_vTaskSuspend == 1 ) { if( pxTCB == NULL ) { /* Search the suspended list. */ pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery ); } } #endif #if( INCLUDE_vTaskDelete == 1 ) { if( pxTCB == NULL ) { /* Search the deleted list. */ pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery ); } } #endif } ( void ) xTaskResumeAll(); return ( TaskHandle_t ) pxTCB; } #endif /* INCLUDE_xTaskGetHandle */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) { UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; vTaskSuspendAll(); { /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) { /* Fill in an TaskStatus_t structure with information on each task in the Ready state. */ do { uxQueue--; uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ /* Fill in an TaskStatus_t structure with information on each task in the Blocked state. */ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ); uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ); #if( INCLUDE_vTaskDelete == 1 ) { /* Fill in an TaskStatus_t structure with information on each task that has been deleted but not yet cleaned up. */ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); } #endif #if ( INCLUDE_vTaskSuspend == 1 ) { /* Fill in an TaskStatus_t structure with information on each task in the Suspended state. */ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); } #endif #if ( configGENERATE_RUN_TIME_STATS == 1) { if( pulTotalRunTime != NULL ) { #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); #else *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); #endif } } #else { if( pulTotalRunTime != NULL ) { *pulTotalRunTime = 0; } } #endif } else { mtCOVERAGE_TEST_MARKER(); } } ( void ) xTaskResumeAll(); return uxTask; } #endif /* configUSE_TRACE_FACILITY */ /*----------------------------------------------------------*/ #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) TaskHandle_t xTaskGetIdleTaskHandle( void ) { /* If xTaskGetIdleTaskHandle() is called before the scheduler has been started, then xIdleTaskHandle will be NULL. */ configASSERT( ( xIdleTaskHandle != NULL ) ); return xIdleTaskHandle; } #endif /* INCLUDE_xTaskGetIdleTaskHandle */ /*----------------------------------------------------------*/ /* This conditional compilation should use inequality to 0, not equality to 1. This is to ensure vTaskStepTick() is available when user defined low power mode implementations require configUSE_TICKLESS_IDLE to be set to a value other than 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) void vTaskStepTick( const TickType_t xTicksToJump ) { /* Correct the tick count value after a period during which the tick was suppressed. Note this does *not* call the tick hook function for each stepped tick. */ configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); xTickCount += xTicksToJump; traceINCREASE_TICK_COUNT( xTicksToJump ); } #endif /* configUSE_TICKLESS_IDLE */ /*----------------------------------------------------------*/ #if ( INCLUDE_xTaskAbortDelay == 1 ) BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) { TCB_t *pxTCB = ( TCB_t * ) xTask; BaseType_t xReturn = pdFALSE; configASSERT( pxTCB ); vTaskSuspendAll(); { /* A task can only be prematurely removed from the Blocked state if it is actually in the Blocked state. */ if( eTaskGetState( xTask ) == eBlocked ) { /* Remove the reference to the task from the blocked list. An interrupt won't touch the xStateListItem because the scheduler is suspended. */ ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); /* Is the task waiting on an event also? If so remove it from the event list too. Interrupts can touch the event list item, even though the scheduler is suspended, so a critical section is used. */ taskENTER_CRITICAL(); { if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); pxTCB->ucDelayAborted = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); /* Place the unblocked task into the appropriate ready list. */ prvAddTaskToReadyList( pxTCB ); /* A task being unblocked cannot cause an immediate context switch if preemption is turned off. */ #if ( configUSE_PREEMPTION == 1 ) { /* Preemption is on, but a context switch should only be performed if the unblocked task has a priority that is equal to or higher than the currently executing task. */ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) { /* Pend the yield to be performed when the scheduler is unsuspended. */ xYieldPending = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_PREEMPTION */ } else { mtCOVERAGE_TEST_MARKER(); } } xTaskResumeAll(); return xReturn; } #endif /* INCLUDE_xTaskAbortDelay */ /*----------------------------------------------------------*/ BaseType_t xTaskIncrementTick( void ) { TCB_t * pxTCB; TickType_t xItemValue; BaseType_t xSwitchRequired = pdFALSE; /* Called by the portable layer each time a tick interrupt occurs. Increments the tick then checks to see if the new tick value will cause any tasks to be unblocked. */ traceTASK_INCREMENT_TICK( xTickCount ); if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { /* Minor optimisation. The tick count cannot change in this block. */ const TickType_t xConstTickCount = xTickCount + 1; /* Increment the RTOS tick, switching the delayed and overflowed delayed lists if it wraps to 0. */ xTickCount = xConstTickCount; if( xConstTickCount == ( TickType_t ) 0U ) { taskSWITCH_DELAYED_LISTS(); } else { mtCOVERAGE_TEST_MARKER(); } /* See if this tick has made a timeout expire. Tasks are stored in the queue in the order of their wake time - meaning once one task has been found whose block time has not expired there is no need to look any further down the list. */ if( xConstTickCount >= xNextTaskUnblockTime ) { for( ;; ) { if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) { /* The delayed list is empty. Set xNextTaskUnblockTime to the maximum possible value so it is extremely unlikely that the if( xTickCount >= xNextTaskUnblockTime ) test will pass next time through. */ xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ break; } else { /* The delayed list is not empty, get the value of the item at the head of the delayed list. This is the time at which the task at the head of the delayed list must be removed from the Blocked state. */ pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) ); if( xConstTickCount < xItemValue ) { /* It is not time to unblock this item yet, but the item value is the time at which the task at the head of the blocked list must be removed from the Blocked state - so record the item value in xNextTaskUnblockTime. */ xNextTaskUnblockTime = xItemValue; break; } else { mtCOVERAGE_TEST_MARKER(); } /* It is time to remove the item from the Blocked state. */ ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); /* Is the task waiting on an event also? If so remove it from the event list. */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); } else { mtCOVERAGE_TEST_MARKER(); } /* Place the unblocked task into the appropriate ready list. */ prvAddTaskToReadyList( pxTCB ); /* A task being unblocked cannot cause an immediate context switch if preemption is turned off. */ #if ( configUSE_PREEMPTION == 1 ) { /* Preemption is on, but a context switch should only be performed if the unblocked task has a priority that is equal to or higher than the currently executing task. */ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) { xSwitchRequired = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_PREEMPTION */ } } } /* Tasks of equal priority to the currently running task will share processing time (time slice) if preemption is on, and the application writer has not explicitly turned time slicing off. */ #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) { if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 ) { xSwitchRequired = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ #if ( configUSE_TICK_HOOK == 1 ) { /* Guard against the tick hook being called when the pended tick count is being unwound (when the scheduler is being unlocked). */ if( uxPendedTicks == ( UBaseType_t ) 0U ) { vApplicationTickHook(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_TICK_HOOK */ } else { ++uxPendedTicks; /* The tick hook gets called at regular intervals, even if the scheduler is locked. */ #if ( configUSE_TICK_HOOK == 1 ) { vApplicationTickHook(); } #endif } #if ( configUSE_PREEMPTION == 1 ) { if( xYieldPending != pdFALSE ) { xSwitchRequired = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_PREEMPTION */ return xSwitchRequired; } /*-----------------------------------------------------------*/ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) { TCB_t *xTCB; /* If xTask is NULL then it is the task hook of the calling task that is getting set. */ if( xTask == NULL ) { xTCB = ( TCB_t * ) pxCurrentTCB; } else { xTCB = ( TCB_t * ) xTask; } /* Save the hook function in the TCB. A critical section is required as the value can be accessed from an interrupt. */ taskENTER_CRITICAL(); xTCB->pxTaskTag = pxHookFunction; taskEXIT_CRITICAL(); } #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) { TCB_t *xTCB; TaskHookFunction_t xReturn; /* If xTask is NULL then we are setting our own task hook. */ if( xTask == NULL ) { xTCB = ( TCB_t * ) pxCurrentTCB; } else { xTCB = ( TCB_t * ) xTask; } /* Save the hook function in the TCB. A critical section is required as the value can be accessed from an interrupt. */ taskENTER_CRITICAL(); { xReturn = xTCB->pxTaskTag; } taskEXIT_CRITICAL(); return xReturn; } #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) { TCB_t *xTCB; BaseType_t xReturn; /* If xTask is NULL then we are calling our own task hook. */ if( xTask == NULL ) { xTCB = ( TCB_t * ) pxCurrentTCB; } else { xTCB = ( TCB_t * ) xTask; } if( xTCB->pxTaskTag != NULL ) { xReturn = xTCB->pxTaskTag( pvParameter ); } else { xReturn = pdFAIL; } return xReturn; } #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ void vTaskSwitchContext( void ) { if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) { /* The scheduler is currently suspended - do not allow a context switch. */ xYieldPending = pdTRUE; } else { xYieldPending = pdFALSE; traceTASK_SWITCHED_OUT(); #if ( configGENERATE_RUN_TIME_STATS == 1 ) { #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); #else ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); #endif /* Add the amount of time the task has been running to the accumulated time so far. The time the task started running was stored in ulTaskSwitchedInTime. Note that there is no overflow protection here so count values are only valid until the timer overflows. The guard against negative values is to protect against suspect run time stat counter implementations - which are provided by the application, not the kernel. */ if( ulTotalRunTime > ulTaskSwitchedInTime ) { pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); } else { mtCOVERAGE_TEST_MARKER(); } ulTaskSwitchedInTime = ulTotalRunTime; } #endif /* configGENERATE_RUN_TIME_STATS */ /* Check for stack overflow, if configured. */ taskCHECK_FOR_STACK_OVERFLOW(); /* Select a new task to run using either the generic C or port optimised asm code. */ taskSELECT_HIGHEST_PRIORITY_TASK(); traceTASK_SWITCHED_IN(); #if ( configUSE_NEWLIB_REENTRANT == 1 ) { /* Switch Newlib's _impure_ptr variable to point to the _reent structure specific to this task. */ _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); } #endif /* configUSE_NEWLIB_REENTRANT */ } } /*-----------------------------------------------------------*/ void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) { configASSERT( pxEventList ); /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ /* Place the event list item of the TCB in the appropriate event list. This is placed in the list in priority order so the highest priority task is the first to be woken by the event. The queue that contains the event list is locked, preventing simultaneous access from interrupts. */ vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); } /*-----------------------------------------------------------*/ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) { configASSERT( pxEventList ); /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by the event groups implementation. */ configASSERT( uxSchedulerSuspended != 0 ); /* Store the item value in the event list item. It is safe to access the event list item here as interrupts won't access the event list item of a task that is not in the Blocked state. */ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); /* Place the event list item of the TCB at the end of the appropriate event list. It is safe to access the event list here because it is part of an event group implementation - and interrupts don't access event groups directly (instead they access them indirectly by pending function calls to the task level). */ vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); } /*-----------------------------------------------------------*/ #if( configUSE_TIMERS == 1 ) void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) { configASSERT( pxEventList ); /* This function should not be called by application code hence the 'Restricted' in its name. It is not part of the public API. It is designed for use by kernel code, and has special calling requirements - it should be called with the scheduler suspended. */ /* Place the event list item of the TCB in the appropriate event list. In this case it is assume that this is the only task that is going to be waiting on this event list, so the faster vListInsertEnd() function can be used in place of vListInsert. */ vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); /* If the task should block indefinitely then set the block time to a value that will be recognised as an indefinite delay inside the prvAddCurrentTaskToDelayedList() function. */ if( xWaitIndefinitely != pdFALSE ) { xTicksToWait = portMAX_DELAY; } traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) ); prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely ); } #endif /* configUSE_TIMERS */ /*-----------------------------------------------------------*/ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) { TCB_t *pxUnblockedTCB; BaseType_t xReturn; /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be called from a critical section within an ISR. */ /* The event list is sorted in priority order, so the first in the list can be removed as it is known to be the highest priority. Remove the TCB from the delayed list, and add it to the ready list. If an event is for a queue that is locked then this function will never get called - the lock count on the queue will get modified instead. This means exclusive access to the event list is guaranteed here. This function assumes that a check has already been made to ensure that pxEventList is not empty. */ pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); configASSERT( pxUnblockedTCB ); ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); } else { /* The delayed and ready lists cannot be accessed, so hold this task pending until the scheduler is resumed. */ vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); } if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) { /* Return true if the task removed from the event list has a higher priority than the calling task. This allows the calling task to know if it should force a context switch now. */ xReturn = pdTRUE; /* Mark that a yield is pending in case the user is not using the "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ xYieldPending = pdTRUE; } else { xReturn = pdFALSE; } #if( configUSE_TICKLESS_IDLE != 0 ) { /* If a task is blocked on a kernel object then xNextTaskUnblockTime might be set to the blocked task's time out time. If the task is unblocked for a reason other than a timeout xNextTaskUnblockTime is normally left unchanged, because it is automatically reset to a new value when the tick count equals xNextTaskUnblockTime. However if tickless idling is used it might be more important to enter sleep mode at the earliest possible time - so reset xNextTaskUnblockTime here to ensure it is updated at the earliest possible time. */ prvResetNextTaskUnblockTime(); } #endif return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) { TCB_t *pxUnblockedTCB; BaseType_t xReturn; /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by the event flags implementation. */ configASSERT( uxSchedulerSuspended != pdFALSE ); /* Store the new item value in the event list. */ listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); /* Remove the event list form the event flag. Interrupts do not access event flags. */ pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem ); configASSERT( pxUnblockedTCB ); ( void ) uxListRemove( pxEventListItem ); /* Remove the task from the delayed list and add it to the ready list. The scheduler is suspended so interrupts will not be accessing the ready lists. */ ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) { /* Return true if the task removed from the event list has a higher priority than the calling task. This allows the calling task to know if it should force a context switch now. */ xReturn = pdTRUE; /* Mark that a yield is pending in case the user is not using the "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ xYieldPending = pdTRUE; } else { xReturn = pdFALSE; } return xReturn; } /*-----------------------------------------------------------*/ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) { configASSERT( pxTimeOut ); pxTimeOut->xOverflowCount = xNumOfOverflows; pxTimeOut->xTimeOnEntering = xTickCount; } /*-----------------------------------------------------------*/ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) { BaseType_t xReturn; configASSERT( pxTimeOut ); configASSERT( pxTicksToWait ); taskENTER_CRITICAL(); { /* Minor optimisation. The tick count cannot change in this block. */ const TickType_t xConstTickCount = xTickCount; #if( INCLUDE_xTaskAbortDelay == 1 ) if( pxCurrentTCB->ucDelayAborted != pdFALSE ) { /* The delay was aborted, which is not the same as a time out, but has the same result. */ pxCurrentTCB->ucDelayAborted = pdFALSE; xReturn = pdTRUE; } else #endif #if ( INCLUDE_vTaskSuspend == 1 ) if( *pxTicksToWait == portMAX_DELAY ) { /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is the maximum block time then the task should block indefinitely, and therefore never time out. */ xReturn = pdFALSE; } else #endif if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ { /* The tick count is greater than the time at which vTaskSetTimeout() was called, but has also overflowed since vTaskSetTimeOut() was called. It must have wrapped all the way around and gone past again. This passed since vTaskSetTimeout() was called. */ xReturn = pdTRUE; } else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */ { /* Not a genuine timeout. Adjust parameters for time remaining. */ *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); vTaskSetTimeOutState( pxTimeOut ); xReturn = pdFALSE; } else { xReturn = pdTRUE; } } taskEXIT_CRITICAL(); return xReturn; } /*-----------------------------------------------------------*/ void vTaskMissedYield( void ) { xYieldPending = pdTRUE; } /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) { UBaseType_t uxReturn; TCB_t *pxTCB; if( xTask != NULL ) { pxTCB = ( TCB_t * ) xTask; uxReturn = pxTCB->uxTaskNumber; } else { uxReturn = 0U; } return uxReturn; } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) { TCB_t *pxTCB; if( xTask != NULL ) { pxTCB = ( TCB_t * ) xTask; pxTCB->uxTaskNumber = uxHandle; } } #endif /* configUSE_TRACE_FACILITY */ /* * ----------------------------------------------------------- * The Idle task. * ---------------------------------------------------------- * * The portTASK_FUNCTION() macro is used to allow port/compiler specific * language extensions. The equivalent prototype for this function is: * * void prvIdleTask( void *pvParameters ); * */ static portTASK_FUNCTION( prvIdleTask, pvParameters ) { /* Stop warnings. */ ( void ) pvParameters; /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE SCHEDULER IS STARTED. **/ for( ;; ) { /* See if any tasks have deleted themselves - if so then the idle task is responsible for freeing the deleted task's TCB and stack. */ prvCheckTasksWaitingTermination(); #if ( configUSE_PREEMPTION == 0 ) { /* If we are not using preemption we keep forcing a task switch to see if any other task has become available. If we are using preemption we don't need to do this as any task becoming available will automatically get the processor anyway. */ taskYIELD(); } #endif /* configUSE_PREEMPTION */ #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) { /* When using preemption tasks of equal priority will be timesliced. If a task that is sharing the idle priority is ready to run then the idle task should yield before the end of the timeslice. A critical region is not required here as we are just reading from the list, and an occasional incorrect value will not matter. If the ready list at the idle priority contains more than one task then a task other than the idle task is ready to execute. */ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) { taskYIELD(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ #if ( configUSE_IDLE_HOOK == 1 ) { extern void vApplicationIdleHook( void ); /* Call the user defined function from within the idle task. This allows the application designer to add background functionality without the overhead of a separate task. NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK. */ vApplicationIdleHook(); } #endif /* configUSE_IDLE_HOOK */ /* This conditional compilation should use inequality to 0, not equality to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when user defined low power mode implementations require configUSE_TICKLESS_IDLE to be set to a value other than 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) { TickType_t xExpectedIdleTime; /* It is not desirable to suspend then resume the scheduler on each iteration of the idle task. Therefore, a preliminary test of the expected idle time is performed without the scheduler suspended. The result here is not necessarily valid. */ xExpectedIdleTime = prvGetExpectedIdleTime(); if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { vTaskSuspendAll(); { /* Now the scheduler is suspended, the expected idle time can be sampled again, and this time its value can be used. */ configASSERT( xNextTaskUnblockTime >= xTickCount ); xExpectedIdleTime = prvGetExpectedIdleTime(); if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { traceLOW_POWER_IDLE_BEGIN(); portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); traceLOW_POWER_IDLE_END(); } else { mtCOVERAGE_TEST_MARKER(); } } ( void ) xTaskResumeAll(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_TICKLESS_IDLE */ } } /*-----------------------------------------------------------*/ #if( configUSE_TICKLESS_IDLE != 0 ) eSleepModeStatus eTaskConfirmSleepModeStatus( void ) { /* The idle task exists in addition to the application tasks. */ const UBaseType_t uxNonApplicationTasks = 1; eSleepModeStatus eReturn = eStandardSleep; if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 ) { /* A task was made ready while the scheduler was suspended. */ eReturn = eAbortSleep; } else if( xYieldPending != pdFALSE ) { /* A yield was pended while the scheduler was suspended. */ eReturn = eAbortSleep; } else { /* If all the tasks are in the suspended list (which might mean they have an infinite block time rather than actually being suspended) then it is safe to turn all clocks off and just wait for external interrupts. */ if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) { eReturn = eNoTasksWaitingTimeout; } else { mtCOVERAGE_TEST_MARKER(); } } return eReturn; } #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) { TCB_t *pxTCB; if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) { pxTCB = prvGetTCBFromHandle( xTaskToSet ); pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; } } #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ /*-----------------------------------------------------------*/ #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) { void *pvReturn = NULL; TCB_t *pxTCB; if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) { pxTCB = prvGetTCBFromHandle( xTaskToQuery ); pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; } else { pvReturn = NULL; } return pvReturn; } #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ /*-----------------------------------------------------------*/ #if ( portUSING_MPU_WRAPPERS == 1 ) void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions ) { TCB_t *pxTCB; /* If null is passed in here then we are modifying the MPU settings of the calling task. */ pxTCB = prvGetTCBFromHandle( xTaskToModify ); vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); } #endif /* portUSING_MPU_WRAPPERS */ /*-----------------------------------------------------------*/ static void prvInitialiseTaskLists( void ) { UBaseType_t uxPriority; for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) { vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); } vListInitialise( &xDelayedTaskList1 ); vListInitialise( &xDelayedTaskList2 ); vListInitialise( &xPendingReadyList ); #if ( INCLUDE_vTaskDelete == 1 ) { vListInitialise( &xTasksWaitingTermination ); } #endif /* INCLUDE_vTaskDelete */ #if ( INCLUDE_vTaskSuspend == 1 ) { vListInitialise( &xSuspendedTaskList ); } #endif /* INCLUDE_vTaskSuspend */ /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList using list2. */ pxDelayedTaskList = &xDelayedTaskList1; pxOverflowDelayedTaskList = &xDelayedTaskList2; } /*-----------------------------------------------------------*/ static void prvCheckTasksWaitingTermination( void ) { /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/ #if ( INCLUDE_vTaskDelete == 1 ) { BaseType_t xListIsEmpty; /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called too often in the idle task. */ while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) { vTaskSuspendAll(); { xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); } ( void ) xTaskResumeAll(); if( xListIsEmpty == pdFALSE ) { TCB_t *pxTCB; taskENTER_CRITICAL(); { pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); --uxCurrentNumberOfTasks; --uxDeletedTasksWaitingCleanUp; } taskEXIT_CRITICAL(); prvDeleteTCB( pxTCB ); } else { mtCOVERAGE_TEST_MARKER(); } } } #endif /* INCLUDE_vTaskDelete */ } /*-----------------------------------------------------------*/ #if( configUSE_TRACE_FACILITY == 1 ) void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) { TCB_t *pxTCB; /* xTask is NULL then get the state of the calling task. */ pxTCB = prvGetTCBFromHandle( xTask ); pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB; pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] ); pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority; pxTaskStatus->pxStackBase = pxTCB->pxStack; pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber; #if ( INCLUDE_vTaskSuspend == 1 ) { /* If the task is in the suspended list then there is a chance it is actually just blocked indefinitely - so really it should be reported as being in the Blocked state. */ if( pxTaskStatus->eCurrentState == eSuspended ) { vTaskSuspendAll(); { if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { pxTaskStatus->eCurrentState = eBlocked; } } xTaskResumeAll(); } } #endif /* INCLUDE_vTaskSuspend */ #if ( configUSE_MUTEXES == 1 ) { pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; } #else { pxTaskStatus->uxBasePriority = 0; } #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) { pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter; } #else { pxTaskStatus->ulRunTimeCounter = 0; } #endif /* Obtaining the task state is a little fiddly, so is only done if the value of eState passed into this function is eInvalid - otherwise the state is just set to whatever is passed in. */ if( eState != eInvalid ) { pxTaskStatus->eCurrentState = eState; } else { pxTaskStatus->eCurrentState = eTaskGetState( xTask ); } /* Obtaining the stack space takes some time, so the xGetFreeStackSpace parameter is provided to allow it to be skipped. */ if( xGetFreeStackSpace != pdFALSE ) { #if ( portSTACK_GROWTH > 0 ) { pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); } #else { pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); } #endif } else { pxTaskStatus->usStackHighWaterMark = 0; } } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) { volatile TCB_t *pxNextTCB, *pxFirstTCB; UBaseType_t uxTask = 0; if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) { listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /* Populate an TaskStatus_t structure within the pxTaskStatusArray array for each task that is referenced from pxList. See the definition of TaskStatus_t in task.h for the meaning of each TaskStatus_t structure member. */ do { listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState ); uxTask++; } while( pxNextTCB != pxFirstTCB ); } else { mtCOVERAGE_TEST_MARKER(); } return uxTask; } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) { uint32_t ulCount = 0U; while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE ) { pucStackByte -= portSTACK_GROWTH; ulCount++; } ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */ return ( uint16_t ) ulCount; } #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) { TCB_t *pxTCB; uint8_t *pucEndOfStack; UBaseType_t uxReturn; pxTCB = prvGetTCBFromHandle( xTask ); #if portSTACK_GROWTH < 0 { pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; } #else { pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; } #endif uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); return uxReturn; } #endif /* INCLUDE_uxTaskGetStackHighWaterMark */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelete == 1 ) static void prvDeleteTCB( TCB_t *pxTCB ) { /* This call is required specifically for the TriCore port. It must be above the vPortFree() calls. The call is also used by ports/demos that want to allocate and clean RAM statically. */ portCLEAN_UP_TCB( pxTCB ); /* Free up the memory allocated by the scheduler for the task. It is up to the task to free any memory allocated at the application level. */ #if ( configUSE_NEWLIB_REENTRANT == 1 ) { _reclaim_reent( &( pxTCB->xNewLib_reent ) ); } #endif /* configUSE_NEWLIB_REENTRANT */ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) { /* The task can only have been allocated dynamically - free both the stack and TCB. */ vPortFree( pxTCB->pxStack ); vPortFree( pxTCB ); } #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 ) { /* The task could have been allocated statically or dynamically, so check what was statically allocated before trying to free the memory. */ if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ) { /* Both the stack and TCB were allocated dynamically, so both must be freed. */ vPortFree( pxTCB->pxStack ); vPortFree( pxTCB ); } else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) { /* Only the stack was statically allocated, so the TCB is the only memory that must be freed. */ vPortFree( pxTCB ); } else { /* Neither the stack nor the TCB were allocated dynamically, so nothing needs to be freed. */ configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ) mtCOVERAGE_TEST_MARKER(); } } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } #endif /* INCLUDE_vTaskDelete */ /*-----------------------------------------------------------*/ static void prvResetNextTaskUnblockTime( void ) { TCB_t *pxTCB; if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) { /* The new current delayed list is empty. Set xNextTaskUnblockTime to the maximum possible value so it is extremely unlikely that the if( xTickCount >= xNextTaskUnblockTime ) test will pass until there is an item in the delayed list. */ xNextTaskUnblockTime = portMAX_DELAY; } else { /* The new current delayed list is not empty, get the value of the item at the head of the delayed list. This is the time at which the task at the head of the delayed list should be removed from the Blocked state. */ ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) ); } } /*-----------------------------------------------------------*/ #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) TaskHandle_t xTaskGetCurrentTaskHandle( void ) { TaskHandle_t xReturn; /* A critical section is not required as this is not called from an interrupt and the current TCB will always be the same for any individual execution thread. */ xReturn = pxCurrentTCB; return xReturn; } #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ /*-----------------------------------------------------------*/ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) BaseType_t xTaskGetSchedulerState( void ) { BaseType_t xReturn; if( xSchedulerRunning == pdFALSE ) { xReturn = taskSCHEDULER_NOT_STARTED; } else { if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { xReturn = taskSCHEDULER_RUNNING; } else { xReturn = taskSCHEDULER_SUSPENDED; } } return xReturn; } #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */ /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) { TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; /* If the mutex was given back by an interrupt while the queue was locked then the mutex holder might now be NULL. */ if( pxMutexHolder != NULL ) { /* If the holder of the mutex has a priority below the priority of the task attempting to obtain the mutex then it will temporarily inherit the priority of the task attempting to obtain the mutex. */ if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) { /* Adjust the mutex holder state to account for its new priority. Only reset the event list item value if the value is not being used for anything else. */ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) { listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ } else { mtCOVERAGE_TEST_MARKER(); } /* If the task being modified is in the ready state it will need to be moved into a new list. */ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) { if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } else { mtCOVERAGE_TEST_MARKER(); } /* Inherit the priority before being moved into the new list. */ pxTCB->uxPriority = pxCurrentTCB->uxPriority; prvAddTaskToReadyList( pxTCB ); } else { /* Just inherit the priority. */ pxTCB->uxPriority = pxCurrentTCB->uxPriority; } traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority ); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) { TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; BaseType_t xReturn = pdFALSE; if( pxMutexHolder != NULL ) { /* A task can only have an inherited priority if it holds the mutex. If the mutex is held by a task then it cannot be given from an interrupt, and if a mutex is given by the holding task then it must be the running state task. */ configASSERT( pxTCB == pxCurrentTCB ); configASSERT( pxTCB->uxMutexesHeld ); ( pxTCB->uxMutexesHeld )--; /* Has the holder of the mutex inherited the priority of another task? */ if( pxTCB->uxPriority != pxTCB->uxBasePriority ) { /* Only disinherit if no other mutexes are held. */ if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) { /* A task can only have an inherited priority if it holds the mutex. If the mutex is held by a task then it cannot be given from an interrupt, and if a mutex is given by the holding task then it must be the running state task. Remove the holding task from the ready list. */ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } else { mtCOVERAGE_TEST_MARKER(); } /* Disinherit the priority before adding the task into the new ready list. */ traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); pxTCB->uxPriority = pxTCB->uxBasePriority; /* Reset the event list item value. It cannot be in use for any other purpose if this task is running, and it must be running to give back the mutex. */ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ prvAddTaskToReadyList( pxTCB ); /* Return true to indicate that a context switch is required. This is only actually required in the corner case whereby multiple mutexes were held and the mutexes were given back in an order different to that in which they were taken. If a context switch did not occur when the first mutex was returned, even if a task was waiting on it, then a context switch should occur when the last mutex is returned whether a task is waiting on it or not. */ xReturn = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } return xReturn; } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( portCRITICAL_NESTING_IN_TCB == 1 ) void vTaskEnterCritical( void ) { portDISABLE_INTERRUPTS(); if( xSchedulerRunning != pdFALSE ) { ( pxCurrentTCB->uxCriticalNesting )++; /* This is not the interrupt safe version of the enter critical function so assert() if it is being called from an interrupt context. Only API functions that end in "FromISR" can be used in an interrupt. Only assert if the critical nesting count is 1 to protect against recursive calls if the assert function also uses a critical section. */ if( pxCurrentTCB->uxCriticalNesting == 1 ) { portASSERT_IF_IN_ISR(); } } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* portCRITICAL_NESTING_IN_TCB */ /*-----------------------------------------------------------*/ #if ( portCRITICAL_NESTING_IN_TCB == 1 ) void vTaskExitCritical( void ) { if( xSchedulerRunning != pdFALSE ) { if( pxCurrentTCB->uxCriticalNesting > 0U ) { ( pxCurrentTCB->uxCriticalNesting )--; if( pxCurrentTCB->uxCriticalNesting == 0U ) { portENABLE_INTERRUPTS(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* portCRITICAL_NESTING_IN_TCB */ /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) { size_t x; /* Start by copying the entire string. */ strcpy( pcBuffer, pcTaskName ); /* Pad the end of the string with spaces to ensure columns line up when printed out. */ for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ ) { pcBuffer[ x ] = ' '; } /* Terminate. */ pcBuffer[ x ] = 0x00; /* Return the new end of string. */ return &( pcBuffer[ x ] ); } #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */ /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) void vTaskList( char * pcWriteBuffer ) { TaskStatus_t *pxTaskStatusArray; volatile UBaseType_t uxArraySize, x; char cStatus; /* * PLEASE NOTE: * * This function is provided for convenience only, and is used by many * of the demo applications. Do not consider it to be part of the * scheduler. * * vTaskList() calls uxTaskGetSystemState(), then formats part of the * uxTaskGetSystemState() output into a human readable table that * displays task names, states and stack usage. * * vTaskList() has a dependency on the sprintf() C library function that * might bloat the code size, use a lot of stack, and provide different * results on different platforms. An alternative, tiny, third party, * and limited functionality implementation of sprintf() is provided in * many of the FreeRTOS/Demo sub-directories in a file called * printf-stdarg.c (note printf-stdarg.c does not provide a full * snprintf() implementation!). * * It is recommended that production systems call uxTaskGetSystemState() * directly to get access to raw stats data, rather than indirectly * through a call to vTaskList(). */ /* Make sure the write buffer does not contain a string. */ *pcWriteBuffer = 0x00; /* Take a snapshot of the number of tasks in case it changes while this function is executing. */ uxArraySize = uxCurrentNumberOfTasks; /* Allocate an array index for each task. NOTE! if configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will equate to NULL. */ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); if( pxTaskStatusArray != NULL ) { /* Generate the (binary) data. */ uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL ); /* Create a human readable table from the binary data. */ for( x = 0; x < uxArraySize; x++ ) { switch( pxTaskStatusArray[ x ].eCurrentState ) { case eReady: cStatus = tskREADY_CHAR; break; case eBlocked: cStatus = tskBLOCKED_CHAR; break; case eSuspended: cStatus = tskSUSPENDED_CHAR; break; case eDeleted: cStatus = tskDELETED_CHAR; break; default: /* Should not get here, but it is included to prevent static checking errors. */ cStatus = 0x00; break; } /* Write the task name to the string, padding with spaces so it can be printed in tabular form more easily. */ pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); /* Write the rest of the string. */ sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); pcWriteBuffer += strlen( pcWriteBuffer ); } /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION is 0 then vPortFree() will be #defined to nothing. */ vPortFree( pxTaskStatusArray ); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ /*----------------------------------------------------------*/ #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) void vTaskGetRunTimeStats( char *pcWriteBuffer ) { TaskStatus_t *pxTaskStatusArray; volatile UBaseType_t uxArraySize, x; uint32_t ulTotalTime, ulStatsAsPercentage; #if( configUSE_TRACE_FACILITY != 1 ) { #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). } #endif /* * PLEASE NOTE: * * This function is provided for convenience only, and is used by many * of the demo applications. Do not consider it to be part of the * scheduler. * * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part * of the uxTaskGetSystemState() output into a human readable table that * displays the amount of time each task has spent in the Running state * in both absolute and percentage terms. * * vTaskGetRunTimeStats() has a dependency on the sprintf() C library * function that might bloat the code size, use a lot of stack, and * provide different results on different platforms. An alternative, * tiny, third party, and limited functionality implementation of * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in * a file called printf-stdarg.c (note printf-stdarg.c does not provide * a full snprintf() implementation!). * * It is recommended that production systems call uxTaskGetSystemState() * directly to get access to raw stats data, rather than indirectly * through a call to vTaskGetRunTimeStats(). */ /* Make sure the write buffer does not contain a string. */ *pcWriteBuffer = 0x00; /* Take a snapshot of the number of tasks in case it changes while this function is executing. */ uxArraySize = uxCurrentNumberOfTasks; /* Allocate an array index for each task. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will equate to NULL. */ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); if( pxTaskStatusArray != NULL ) { /* Generate the (binary) data. */ uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime ); /* For percentage calculations. */ ulTotalTime /= 100UL; /* Avoid divide by zero errors. */ if( ulTotalTime > 0 ) { /* Create a human readable table from the binary data. */ for( x = 0; x < uxArraySize; x++ ) { /* What percentage of the total run time has the task used? This will always be rounded down to the nearest integer. ulTotalRunTimeDiv100 has already been divided by 100. */ ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; /* Write the task name to the string, padding with spaces so it can be printed in tabular form more easily. */ pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); if( ulStatsAsPercentage > 0UL ) { #ifdef portLU_PRINTF_SPECIFIER_REQUIRED { sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); } #else { /* sizeof( int ) == sizeof( long ) so a smaller printf() library can be used. */ sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); } #endif } else { /* If the percentage is zero here then the task has consumed less than 1% of the total run time. */ #ifdef portLU_PRINTF_SPECIFIER_REQUIRED { sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); } #else { /* sizeof( int ) == sizeof( long ) so a smaller printf() library can be used. */ sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); } #endif } pcWriteBuffer += strlen( pcWriteBuffer ); } } else { mtCOVERAGE_TEST_MARKER(); } /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION is 0 then vPortFree() will be #defined to nothing. */ vPortFree( pxTaskStatusArray ); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ /*-----------------------------------------------------------*/ TickType_t uxTaskResetEventItemValue( void ) { TickType_t uxReturn; uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) ); /* Reset the event list item to its normal value - so it can be used with queues and semaphores. */ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ return uxReturn; } /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) void *pvTaskIncrementMutexHeldCount( void ) { /* If xSemaphoreCreateMutex() is called before any tasks have been created then pxCurrentTCB will be NULL. */ if( pxCurrentTCB != NULL ) { ( pxCurrentTCB->uxMutexesHeld )++; } return pxCurrentTCB; } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if( configUSE_TASK_NOTIFICATIONS == 1 ) uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) { uint32_t ulReturn; taskENTER_CRITICAL(); { /* Only block if the notification count is not already non-zero. */ if( pxCurrentTCB->ulNotifiedValue == 0UL ) { /* Mark this task as waiting for a notification. */ pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; if( xTicksToWait > ( TickType_t ) 0 ) { prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); traceTASK_NOTIFY_TAKE_BLOCK(); /* All ports are written to allow a yield in a critical section (some will yield immediately, others wait until the critical section exits) - but it is not something that application code should ever do. */ portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); taskENTER_CRITICAL(); { traceTASK_NOTIFY_TAKE(); ulReturn = pxCurrentTCB->ulNotifiedValue; if( ulReturn != 0UL ) { if( xClearCountOnExit != pdFALSE ) { pxCurrentTCB->ulNotifiedValue = 0UL; } else { pxCurrentTCB->ulNotifiedValue = ulReturn - 1; } } else { mtCOVERAGE_TEST_MARKER(); } pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); return ulReturn; } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ #if( configUSE_TASK_NOTIFICATIONS == 1 ) BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) { BaseType_t xReturn; taskENTER_CRITICAL(); { /* Only block if a notification is not already pending. */ if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED ) { /* Clear bits in the task's notification value as bits may get set by the notifying task or interrupt. This can be used to clear the value to zero. */ pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry; /* Mark this task as waiting for a notification. */ pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; if( xTicksToWait > ( TickType_t ) 0 ) { prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); traceTASK_NOTIFY_WAIT_BLOCK(); /* All ports are written to allow a yield in a critical section (some will yield immediately, others wait until the critical section exits) - but it is not something that application code should ever do. */ portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); taskENTER_CRITICAL(); { traceTASK_NOTIFY_WAIT(); if( pulNotificationValue != NULL ) { /* Output the current notification value, which may or may not have changed. */ *pulNotificationValue = pxCurrentTCB->ulNotifiedValue; } /* If ucNotifyValue is set then either the task never entered the blocked state (because a notification was already pending) or the task unblocked because of a notification. Otherwise the task unblocked because of a timeout. */ if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION ) { /* A notification was not received. */ xReturn = pdFALSE; } else { /* A notification was already pending or a notification was received while the task was waiting. */ pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit; xReturn = pdTRUE; } pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); return xReturn; } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ #if( configUSE_TASK_NOTIFICATIONS == 1 ) BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) { TCB_t * pxTCB; BaseType_t xReturn = pdPASS; uint8_t ucOriginalNotifyState; configASSERT( xTaskToNotify ); pxTCB = ( TCB_t * ) xTaskToNotify; taskENTER_CRITICAL(); { if( pulPreviousNotificationValue != NULL ) { *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; } ucOriginalNotifyState = pxTCB->ucNotifyState; pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; switch( eAction ) { case eSetBits : pxTCB->ulNotifiedValue |= ulValue; break; case eIncrement : ( pxTCB->ulNotifiedValue )++; break; case eSetValueWithOverwrite : pxTCB->ulNotifiedValue = ulValue; break; case eSetValueWithoutOverwrite : if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) { pxTCB->ulNotifiedValue = ulValue; } else { /* The value could not be written to the task. */ xReturn = pdFAIL; } break; case eNoAction: /* The task is being notified without its notify value being updated. */ break; } traceTASK_NOTIFY(); /* If the task is in the blocked state specifically to wait for a notification then unblock it now. */ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); #if( configUSE_TICKLESS_IDLE != 0 ) { /* If a task is blocked waiting for a notification then xNextTaskUnblockTime might be set to the blocked task's time out time. If the task is unblocked for a reason other than a timeout xNextTaskUnblockTime is normally left unchanged, because it will automatically get reset to a new value when the tick count equals xNextTaskUnblockTime. However if tickless idling is used it might be more important to enter sleep mode at the earliest possible time - so reset xNextTaskUnblockTime here to ensure it is updated at the earliest possible time. */ prvResetNextTaskUnblockTime(); } #endif if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) { /* The notified task has a priority above the currently executing task so a yield is required. */ taskYIELD_IF_USING_PREEMPTION(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); return xReturn; } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ #if( configUSE_TASK_NOTIFICATIONS == 1 ) BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) { TCB_t * pxTCB; uint8_t ucOriginalNotifyState; BaseType_t xReturn = pdPASS; UBaseType_t uxSavedInterruptStatus; configASSERT( xTaskToNotify ); /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are keep permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); pxTCB = ( TCB_t * ) xTaskToNotify; uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { if( pulPreviousNotificationValue != NULL ) { *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; } ucOriginalNotifyState = pxTCB->ucNotifyState; pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; switch( eAction ) { case eSetBits : pxTCB->ulNotifiedValue |= ulValue; break; case eIncrement : ( pxTCB->ulNotifiedValue )++; break; case eSetValueWithOverwrite : pxTCB->ulNotifiedValue = ulValue; break; case eSetValueWithoutOverwrite : if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) { pxTCB->ulNotifiedValue = ulValue; } else { /* The value could not be written to the task. */ xReturn = pdFAIL; } break; case eNoAction : /* The task is being notified without its notify value being updated. */ break; } traceTASK_NOTIFY_FROM_ISR(); /* If the task is in the blocked state specifically to wait for a notification then unblock it now. */ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); } else { /* The delayed and ready lists cannot be accessed, so hold this task pending until the scheduler is resumed. */ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); } if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) { /* The notified task has a priority above the currently executing task so a yield is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { /* Mark that a yield is pending in case the user is not using the "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ xYieldPending = pdTRUE; } } else { mtCOVERAGE_TEST_MARKER(); } } } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xReturn; } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ #if( configUSE_TASK_NOTIFICATIONS == 1 ) void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) { TCB_t * pxTCB; uint8_t ucOriginalNotifyState; UBaseType_t uxSavedInterruptStatus; configASSERT( xTaskToNotify ); /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are above the maximum system call priority are keep permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts that have been assigned a priority at or (logically) below the maximum system call interrupt priority. FreeRTOS maintains a separate interrupt safe API to ensure interrupt entry is as fast and as simple as possible. More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); pxTCB = ( TCB_t * ) xTaskToNotify; uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { ucOriginalNotifyState = pxTCB->ucNotifyState; pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; /* 'Giving' is equivalent to incrementing a count in a counting semaphore. */ ( pxTCB->ulNotifiedValue )++; traceTASK_NOTIFY_GIVE_FROM_ISR(); /* If the task is in the blocked state specifically to wait for a notification then unblock it now. */ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); } else { /* The delayed and ready lists cannot be accessed, so hold this task pending until the scheduler is resumed. */ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); } if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) { /* The notified task has a priority above the currently executing task so a yield is required. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } else { /* Mark that a yield is pending in case the user is not using the "xHigherPriorityTaskWoken" parameter in an ISR safe FreeRTOS function. */ xYieldPending = pdTRUE; } } else { mtCOVERAGE_TEST_MARKER(); } } } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ #if( configUSE_TASK_NOTIFICATIONS == 1 ) BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ) { TCB_t *pxTCB; BaseType_t xReturn; /* If null is passed in here then it is the calling task that is having its notification state cleared. */ pxTCB = prvGetTCBFromHandle( xTask ); taskENTER_CRITICAL(); { if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ) { pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; xReturn = pdPASS; } else { xReturn = pdFAIL; } } taskEXIT_CRITICAL(); return xReturn; } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) { TickType_t xTimeToWake; const TickType_t xConstTickCount = xTickCount; #if( INCLUDE_xTaskAbortDelay == 1 ) { /* About to enter a delayed list, so ensure the ucDelayAborted flag is reset to pdFALSE so it can be detected as having been set to pdTRUE when the task leaves the Blocked state. */ pxCurrentTCB->ucDelayAborted = pdFALSE; } #endif /* Remove the task from the ready list before adding it to the blocked list as the same list item is used for both lists. */ if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { /* The current task must be in a ready list, so there is no need to check, and the port reset macro can be called directly. */ portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); } else { mtCOVERAGE_TEST_MARKER(); } #if ( INCLUDE_vTaskSuspend == 1 ) { if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) ) { /* Add the task to the suspended task list instead of a delayed task list to ensure it is not woken by a timing event. It will block indefinitely. */ vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) ); } else { /* Calculate the time at which the task should be woken if the event does not occur. This may overflow but this doesn't matter, the kernel will manage it correctly. */ xTimeToWake = xConstTickCount + xTicksToWait; /* The list item will be inserted in wake time order. */ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); if( xTimeToWake < xConstTickCount ) { /* Wake time has overflowed. Place this item in the overflow list. */ vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); } else { /* The wake time has not overflowed, so the current block list is used. */ vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); /* If the task entering the blocked state was placed at the head of the list of blocked tasks then xNextTaskUnblockTime needs to be updated too. */ if( xTimeToWake < xNextTaskUnblockTime ) { xNextTaskUnblockTime = xTimeToWake; } else { mtCOVERAGE_TEST_MARKER(); } } } } #else /* INCLUDE_vTaskSuspend */ { /* Calculate the time at which the task should be woken if the event does not occur. This may overflow but this doesn't matter, the kernel will manage it correctly. */ xTimeToWake = xConstTickCount + xTicksToWait; /* The list item will be inserted in wake time order. */ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); if( xTimeToWake < xConstTickCount ) { /* Wake time has overflowed. Place this item in the overflow list. */ vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); } else { /* The wake time has not overflowed, so the current block list is used. */ vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); /* If the task entering the blocked state was placed at the head of the list of blocked tasks then xNextTaskUnblockTime needs to be updated too. */ if( xTimeToWake < xNextTaskUnblockTime ) { xNextTaskUnblockTime = xTimeToWake; } else { mtCOVERAGE_TEST_MARKER(); } } /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */ ( void ) xCanBlockIndefinitely; } #endif /* INCLUDE_vTaskSuspend */ } #ifdef FREERTOS_MODULE_TEST #include "tasks_test_access_functions.h" #endif micropython-1.12/ports/cc3200/FreeRTOS/Source/timers.c000066400000000000000000001161271357706137100223730ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /* Standard includes. */ #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining all the API functions to use the MPU wrappers. That should only be done when task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "timers.h" #if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 ) #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. #endif /* Lint e961 and e750 are suppressed as a MISRA exception justified because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the header files above, but not in this file, in order to generate the correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ /* This entire source file will be skipped if the application is not configured to include software timer functionality. This #if is closed at the very bottom of this file. If you want to include software timer functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ #if ( configUSE_TIMERS == 1 ) /* Misc definitions. */ #define tmrNO_DELAY ( TickType_t ) 0U /* The definition of the timers themselves. */ typedef struct tmrTimerControl { const char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */ void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */ #if( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */ #endif #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created statically so no attempt is made to free the memory again if the timer is later deleted. */ #endif } xTIMER; /* The old xTIMER name is maintained above then typedefed to the new Timer_t name below to enable the use of older kernel aware debuggers. */ typedef xTIMER Timer_t; /* The definition of messages that can be sent and received on the timer queue. Two types of message can be queued - messages that manipulate a software timer, and messages that request the execution of a non-timer related callback. The two message types are defined in two separate structures, xTimerParametersType and xCallbackParametersType respectively. */ typedef struct tmrTimerParameters { TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ Timer_t * pxTimer; /*<< The timer to which the command will be applied. */ } TimerParameter_t; typedef struct tmrCallbackParameters { PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */ void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */ uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */ } CallbackParameters_t; /* The structure that contains the two message types, along with an identifier that is used to determine which message type is valid. */ typedef struct tmrTimerQueueMessage { BaseType_t xMessageID; /*<< The command being sent to the timer service task. */ union { TimerParameter_t xTimerParameters; /* Don't include xCallbackParameters if it is not going to be used as it makes the structure (and therefore the timer queue) larger. */ #if ( INCLUDE_xTimerPendFunctionCall == 1 ) CallbackParameters_t xCallbackParameters; #endif /* INCLUDE_xTimerPendFunctionCall */ } u; } DaemonTaskMessage_t; /*lint -e956 A manual analysis and inspection has been used to determine which static variables must be declared volatile. */ /* The list in which active timers are stored. Timers are referenced in expire time order, with the nearest expiry time at the front of the list. Only the timer service task is allowed to access these lists. */ PRIVILEGED_DATA static List_t xActiveTimerList1; PRIVILEGED_DATA static List_t xActiveTimerList2; PRIVILEGED_DATA static List_t *pxCurrentTimerList; PRIVILEGED_DATA static List_t *pxOverflowTimerList; /* A queue that is used to send commands to the timer service task. */ PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; /*lint +e956 */ /*-----------------------------------------------------------*/ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) /* If static allocation is supported then the application must provide the following callback function - which enables the application to optionally provide the memory that will be used by the timer task as the task's stack and TCB. */ extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ); #endif /* * Initialise the infrastructure used by the timer service task if it has not * been initialised already. */ static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; /* * The timer service task (daemon). Timer functionality is controlled by this * task. Other tasks communicate with the timer service task using the * xTimerQueue queue. */ static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; /* * Called by the timer service task to interpret and process a command it * received on the timer queue. */ static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; /* * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, * depending on if the expire time causes a timer counter overflow. */ static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION; /* * An active timer has reached its expire time. Reload the timer if it is an * auto reload timer, then call its callback. */ static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION; /* * The tick count has overflowed. Switch the timer lists after ensuring the * current timer list does not still reference some timers. */ static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION; /* * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE * if a tick count overflow occurred since prvSampleTimeNow() was last called. */ static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; /* * If the timer list contains any active timers then return the expire time of * the timer that will expire first and set *pxListWasEmpty to false. If the * timer list does not contain any timers then return 0 and set *pxListWasEmpty * to pdTRUE. */ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION; /* * If a timer has expired, process it. Otherwise, block the timer service task * until either a timer does expire or a command is received. */ static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION; /* * Called after a Timer_t structure has been allocated either statically or * dynamically to fill in the structure's members. */ static void prvInitialiseNewTimer( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /*-----------------------------------------------------------*/ BaseType_t xTimerCreateTimerTask( void ) { BaseType_t xReturn = pdFAIL; /* This function is called when the scheduler is started if configUSE_TIMERS is set to 1. Check that the infrastructure used by the timer service task has been created/initialised. If timers have already been created then the initialisation will already have been performed. */ prvCheckForValidListAndQueue(); if( xTimerQueue != NULL ) { #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { StaticTask_t *pxTimerTaskTCBBuffer = NULL; StackType_t *pxTimerTaskStackBuffer = NULL; uint32_t ulTimerTaskStackSize; vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize ); xTimerTaskHandle = xTaskCreateStatic( prvTimerTask, "Tmr Svc", ulTimerTaskStackSize, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, pxTimerTaskStackBuffer, pxTimerTaskTCBBuffer ); if( xTimerTaskHandle != NULL ) { xReturn = pdPASS; } } #else { xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle ); } #endif /* configSUPPORT_STATIC_ALLOCATION */ } else { mtCOVERAGE_TEST_MARKER(); } configASSERT( xReturn ); return xReturn; } /*-----------------------------------------------------------*/ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { Timer_t *pxNewTimer; pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); if( pxNewTimer != NULL ) { prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { /* Timers can be created statically or dynamically, so note this timer was created dynamically in case the timer is later deleted. */ pxNewTimer->ucStaticallyAllocated = pdFALSE; } #endif /* configSUPPORT_STATIC_ALLOCATION */ } return pxNewTimer; } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { Timer_t *pxNewTimer; #if( configASSERT_DEFINED == 1 ) { /* Sanity check that the size of the structure used to declare a variable of type StaticTimer_t equals the size of the real timer structures. */ volatile size_t xSize = sizeof( StaticTimer_t ); configASSERT( xSize == sizeof( Timer_t ) ); } #endif /* configASSERT_DEFINED */ /* A pointer to a StaticTimer_t structure MUST be provided, use it. */ configASSERT( pxTimerBuffer ); pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ if( pxNewTimer != NULL ) { prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) { /* Timers can be created statically or dynamically so note this timer was created statically in case it is later deleted. */ pxNewTimer->ucStaticallyAllocated = pdTRUE; } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } return pxNewTimer; } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ static void prvInitialiseNewTimer( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { /* 0 is not a valid value for xTimerPeriodInTicks. */ configASSERT( ( xTimerPeriodInTicks > 0 ) ); if( pxNewTimer != NULL ) { /* Ensure the infrastructure used by the timer service task has been created/initialised. */ prvCheckForValidListAndQueue(); /* Initialise the timer structure members using the function parameters. */ pxNewTimer->pcTimerName = pcTimerName; pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; pxNewTimer->uxAutoReload = uxAutoReload; pxNewTimer->pvTimerID = pvTimerID; pxNewTimer->pxCallbackFunction = pxCallbackFunction; vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); traceTIMER_CREATE( pxNewTimer ); } } /*-----------------------------------------------------------*/ BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) { BaseType_t xReturn = pdFAIL; DaemonTaskMessage_t xMessage; configASSERT( xTimer ); /* Send a message to the timer service task to perform a particular action on a particular timer definition. */ if( xTimerQueue != NULL ) { /* Send a command to the timer service task to start the xTimer timer. */ xMessage.xMessageID = xCommandID; xMessage.u.xTimerParameters.xMessageValue = xOptionalValue; xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer; if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) { if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) { xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); } else { xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); } } else { xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); } traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); } else { mtCOVERAGE_TEST_MARKER(); } return xReturn; } /*-----------------------------------------------------------*/ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) { /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been started, then xTimerTaskHandle will be NULL. */ configASSERT( ( xTimerTaskHandle != NULL ) ); return xTimerTaskHandle; } /*-----------------------------------------------------------*/ TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) { Timer_t *pxTimer = ( Timer_t * ) xTimer; configASSERT( xTimer ); return pxTimer->xTimerPeriodInTicks; } /*-----------------------------------------------------------*/ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) { Timer_t * pxTimer = ( Timer_t * ) xTimer; TickType_t xReturn; configASSERT( xTimer ); xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) ); return xReturn; } /*-----------------------------------------------------------*/ const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { Timer_t *pxTimer = ( Timer_t * ) xTimer; configASSERT( xTimer ); return pxTimer->pcTimerName; } /*-----------------------------------------------------------*/ static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) { BaseType_t xResult; Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /* Remove the timer from the list of active timers. A check has already been performed to ensure the list is not empty. */ ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); traceTIMER_EXPIRED( pxTimer ); /* If the timer is an auto reload timer then calculate the next expiry time and re-insert the timer in the list of active timers. */ if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) { /* The timer is inserted into a list using a time relative to anything other than the current time. It will therefore be inserted into the correct list relative to the time this task thinks it is now. */ if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE ) { /* The timer expired before it was added to the active timer list. Reload it now. */ xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); configASSERT( xResult ); ( void ) xResult; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } /* Call the timer callback. */ pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); } /*-----------------------------------------------------------*/ static void prvTimerTask( void *pvParameters ) { TickType_t xNextExpireTime; BaseType_t xListWasEmpty; /* Just to avoid compiler warnings. */ ( void ) pvParameters; #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 ) { extern void vApplicationDaemonTaskStartupHook( void ); /* Allow the application writer to execute some code in the context of this task at the point the task starts executing. This is useful if the application includes initialisation code that would benefit from executing after the scheduler has been started. */ vApplicationDaemonTaskStartupHook(); } #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */ for( ;; ) { /* Query the timers list to see if it contains any timers, and if so, obtain the time at which the next timer will expire. */ xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); /* If a timer has expired, process it. Otherwise, block this task until either a timer does expire, or a command is received. */ prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); /* Empty the command queue. */ prvProcessReceivedCommands(); } } /*-----------------------------------------------------------*/ static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) { TickType_t xTimeNow; BaseType_t xTimerListsWereSwitched; vTaskSuspendAll(); { /* Obtain the time now to make an assessment as to whether the timer has expired or not. If obtaining the time causes the lists to switch then don't process this timer as any timers that remained in the list when the lists were switched will have been processed within the prvSampleTimeNow() function. */ xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); if( xTimerListsWereSwitched == pdFALSE ) { /* The tick count has not overflowed, has the timer expired? */ if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) { ( void ) xTaskResumeAll(); prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); } else { /* The tick count has not overflowed, and the next expire time has not been reached yet. This task should therefore block to wait for the next expire time or a command to be received - whichever comes first. The following line cannot be reached unless xNextExpireTime > xTimeNow, except in the case when the current timer list is empty. */ if( xListWasEmpty != pdFALSE ) { /* The current timer list is empty - is the overflow list also empty? */ xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList ); } vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty ); if( xTaskResumeAll() == pdFALSE ) { /* Yield to wait for either a command to arrive, or the block time to expire. If a command arrived between the critical section being exited and this yield then the yield will not cause the task to block. */ portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } } else { ( void ) xTaskResumeAll(); } } } /*-----------------------------------------------------------*/ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) { TickType_t xNextExpireTime; /* Timers are listed in expiry time order, with the head of the list referencing the task that will expire first. Obtain the time at which the timer with the nearest expiry time will expire. If there are no active timers then just set the next expire time to 0. That will cause this task to unblock when the tick count overflows, at which point the timer lists will be switched and the next expiry time can be re-assessed. */ *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); if( *pxListWasEmpty == pdFALSE ) { xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); } else { /* Ensure the task unblocks when the tick count rolls over. */ xNextExpireTime = ( TickType_t ) 0U; } return xNextExpireTime; } /*-----------------------------------------------------------*/ static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) { TickType_t xTimeNow; PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ xTimeNow = xTaskGetTickCount(); if( xTimeNow < xLastTime ) { prvSwitchTimerLists(); *pxTimerListsWereSwitched = pdTRUE; } else { *pxTimerListsWereSwitched = pdFALSE; } xLastTime = xTimeNow; return xTimeNow; } /*-----------------------------------------------------------*/ static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) { BaseType_t xProcessTimerNow = pdFALSE; listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); if( xNextExpiryTime <= xTimeNow ) { /* Has the expiry time elapsed between the command to start/reset a timer was issued, and the time the command was processed? */ if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ { /* The time between a command being issued and the command being processed actually exceeds the timers period. */ xProcessTimerNow = pdTRUE; } else { vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); } } else { if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) { /* If, since the command was issued, the tick count has overflowed but the expiry time has not, then the timer must have already passed its expiry time and should be processed immediately. */ xProcessTimerNow = pdTRUE; } else { vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); } } return xProcessTimerNow; } /*-----------------------------------------------------------*/ static void prvProcessReceivedCommands( void ) { DaemonTaskMessage_t xMessage; Timer_t *pxTimer; BaseType_t xTimerListsWereSwitched, xResult; TickType_t xTimeNow; while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ { #if ( INCLUDE_xTimerPendFunctionCall == 1 ) { /* Negative commands are pended function calls rather than timer commands. */ if( xMessage.xMessageID < ( BaseType_t ) 0 ) { const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); /* The timer uses the xCallbackParameters member to request a callback be executed. Check the callback is not NULL. */ configASSERT( pxCallback ); /* Call the function. */ pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* INCLUDE_xTimerPendFunctionCall */ /* Commands that are positive are timer commands rather than pended function calls. */ if( xMessage.xMessageID >= ( BaseType_t ) 0 ) { /* The messages uses the xTimerParameters member to work on a software timer. */ pxTimer = xMessage.u.xTimerParameters.pxTimer; if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) { /* The timer is in a list, remove it. */ ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); } else { mtCOVERAGE_TEST_MARKER(); } traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue ); /* In this case the xTimerListsWereSwitched parameter is not used, but it must be present in the function call. prvSampleTimeNow() must be called after the message is received from xTimerQueue so there is no possibility of a higher priority task adding a message to the message queue with a time that is ahead of the timer daemon task (because it pre-empted the timer daemon task after the xTimeNow value was set). */ xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); switch( xMessage.xMessageID ) { case tmrCOMMAND_START : case tmrCOMMAND_START_FROM_ISR : case tmrCOMMAND_RESET : case tmrCOMMAND_RESET_FROM_ISR : case tmrCOMMAND_START_DONT_TRACE : /* Start or restart a timer. */ if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE ) { /* The timer expired before it was added to the active timer list. Process it now. */ pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); traceTIMER_EXPIRED( pxTimer ); if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) { xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); configASSERT( xResult ); ( void ) xResult; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } break; case tmrCOMMAND_STOP : case tmrCOMMAND_STOP_FROM_ISR : /* The timer has already been removed from the active list. There is nothing to do here. */ break; case tmrCOMMAND_CHANGE_PERIOD : case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR : pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue; configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); /* The new period does not really have a reference, and can be longer or shorter than the old one. The command time is therefore set to the current time, and as the period cannot be zero the next expiry time can only be in the future, meaning (unlike for the xTimerStart() case above) there is no fail case that needs to be handled here. */ ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); break; case tmrCOMMAND_DELETE : /* The timer has already been removed from the active list, just free up the memory if the memory was dynamically allocated. */ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) { /* The timer can only have been allocated dynamically - free it again. */ vPortFree( pxTimer ); } #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) { /* The timer could have been allocated statically or dynamically, so check before attempting to free the memory. */ if( pxTimer->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) { vPortFree( pxTimer ); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ break; default : /* Don't expect to get here. */ break; } } } } /*-----------------------------------------------------------*/ static void prvSwitchTimerLists( void ) { TickType_t xNextExpireTime, xReloadTime; List_t *pxTemp; Timer_t *pxTimer; BaseType_t xResult; /* The tick count has overflowed. The timer lists must be switched. If there are any timers still referenced from the current timer list then they must have expired and should be processed before the lists are switched. */ while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) { xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); /* Remove the timer from the list. */ pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); traceTIMER_EXPIRED( pxTimer ); /* Execute its callback, then send a command to restart the timer if it is an auto-reload timer. It cannot be restarted here as the lists have not yet been switched. */ pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) { /* Calculate the reload value, and if the reload value results in the timer going into the same timer list then it has already expired and the timer should be re-inserted into the current list so it is processed again within this loop. Otherwise a command should be sent to restart the timer to ensure it is only inserted into a list after the lists have been swapped. */ xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); if( xReloadTime > xNextExpireTime ) { listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); } else { xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); configASSERT( xResult ); ( void ) xResult; } } else { mtCOVERAGE_TEST_MARKER(); } } pxTemp = pxCurrentTimerList; pxCurrentTimerList = pxOverflowTimerList; pxOverflowTimerList = pxTemp; } /*-----------------------------------------------------------*/ static void prvCheckForValidListAndQueue( void ) { /* Check that the list from which active timers are referenced, and the queue used to communicate with the timer service, have been initialised. */ taskENTER_CRITICAL(); { if( xTimerQueue == NULL ) { vListInitialise( &xActiveTimerList1 ); vListInitialise( &xActiveTimerList2 ); pxCurrentTimerList = &xActiveTimerList1; pxOverflowTimerList = &xActiveTimerList2; #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { /* The timer queue is allocated statically in case configSUPPORT_DYNAMIC_ALLOCATION is 0. */ static StaticQueue_t xStaticTimerQueue; static uint8_t ucStaticTimerQueueStorage[ configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue ); } #else { xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) ); } #endif #if ( configQUEUE_REGISTRY_SIZE > 0 ) { if( xTimerQueue != NULL ) { vQueueAddToRegistry( xTimerQueue, "TmrQ" ); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configQUEUE_REGISTRY_SIZE */ } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) { BaseType_t xTimerIsInActiveList; Timer_t *pxTimer = ( Timer_t * ) xTimer; configASSERT( xTimer ); /* Is the timer in the list of active timers? */ taskENTER_CRITICAL(); { /* Checking to see if it is in the NULL list in effect checks to see if it is referenced from either the current or the overflow timer lists in one go, but the logic has to be reversed, hence the '!'. */ xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); } taskEXIT_CRITICAL(); return xTimerIsInActiveList; } /*lint !e818 Can't be pointer to const due to the typedef. */ /*-----------------------------------------------------------*/ void *pvTimerGetTimerID( const TimerHandle_t xTimer ) { Timer_t * const pxTimer = ( Timer_t * ) xTimer; void *pvReturn; configASSERT( xTimer ); taskENTER_CRITICAL(); { pvReturn = pxTimer->pvTimerID; } taskEXIT_CRITICAL(); return pvReturn; } /*-----------------------------------------------------------*/ void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) { Timer_t * const pxTimer = ( Timer_t * ) xTimer; configASSERT( xTimer ); taskENTER_CRITICAL(); { pxTimer->pvTimerID = pvNewID; } taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ #if( INCLUDE_xTimerPendFunctionCall == 1 ) BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) { DaemonTaskMessage_t xMessage; BaseType_t xReturn; /* Complete the message with the function parameters and post it to the daemon task. */ xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); return xReturn; } #endif /* INCLUDE_xTimerPendFunctionCall */ /*-----------------------------------------------------------*/ #if( INCLUDE_xTimerPendFunctionCall == 1 ) BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) { DaemonTaskMessage_t xMessage; BaseType_t xReturn; /* This function can only be called after a timer has been created or after the scheduler has been started because, until then, the timer queue does not exist. */ configASSERT( xTimerQueue ); /* Complete the message with the function parameters and post it to the daemon task. */ xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); return xReturn; } #endif /* INCLUDE_xTimerPendFunctionCall */ /*-----------------------------------------------------------*/ /* This entire source file will be skipped if the application is not configured to include software timer functionality. If you want to include software timer functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ #endif /* configUSE_TIMERS == 1 */ micropython-1.12/ports/cc3200/Makefile000066400000000000000000000036221357706137100175260ustar00rootroot00000000000000# Select the board to build for: if not given on the command line, # then default to WIPY BOARD ?= WIPY ifeq ($(wildcard boards/$(BOARD)/.),) $(error Invalid BOARD specified) endif # Make 'release' the default build type BTYPE ?= release # Port for flashing firmware PORT ?= /dev/ttyUSB1 # If the build directory is not given, make it reflect the board name. BUILD ?= build/$(BOARD)/$(BTYPE) include ../../py/mkenv.mk -include ../../localconfig.mk CROSS_COMPILE ?= arm-none-eabi- CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion CFLAGS = -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access CFLAGS += -Iboards/$(BOARD) CFLAGS += $(CFLAGS_MOD) LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map FLASH_SIZE_WIPY = 2M FLASH_SIZE_LAUNCHXL = 1M ifeq ($(BTARGET), application) # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h # include MicroPython make definitions include $(TOP)/py/py.mk include application.mk else ifeq ($(BTARGET), bootloader) include bootmgr/bootloader.mk else $(error Invalid BTARGET specified) endif endif # always include MicroPython make rules include $(TOP)/py/mkrules.mk erase: cc3200tool -p $(PORT) format_flash --size $(FLASH_SIZE_$(BOARD)) deploy: cc3200tool -p $(PORT) \ write_file bootmgr/build/$(BOARD)/$(BTYPE)/bootloader.bin /sys/mcuimg.bin \ write_file build/$(BOARD)/$(BTYPE)/mcuimg.bin /sys/factimg.bin # Files *.ucf and *ucf.signed.bin come from CC3200SDK-SERVICEPACK # package from http://www.ti.com/tool/cc3200sdk servicepack: cc3200tool -p $(PORT) \ write_file --file-size=0x20000 --signature ota_1.0.1.6-2.7.0.0.ucf.signed.bin \ ota_1.0.1.6-2.7.0.0.ucf /sys/servicepack.ucf micropython-1.12/ports/cc3200/README.md000066400000000000000000000154741357706137100173550ustar00rootroot00000000000000MicroPython port to CC3200 WiFi SoC =================================== This is a MicroPython port to Texas Instruments CC3200 WiFi SoC (ARM Cortex-M4 architecture). This port supports 2 boards: WiPy and TI CC3200-LAUNCHXL. ## Build Instructions for the CC3200 Currently the CC3200 port of MicroPython builds under Linux and OSX, but not under Windows. The toolchain required for the build can be found at . In order to flash the image to the CC3200 you will need the [cc3200tool](https://github.com/ALLTERCO/cc3200tool). An alternative is to use CCS_Uniflash tool from TI, which works only under Windows, and all support is provided by TI itself. Building the bootloader: ``` make BTARGET=bootloader BTYPE=release BOARD=LAUNCHXL ``` Building the "release" image: ``` make BTARGET=application BTYPE=release BOARD=LAUNCHXL ``` To build an image suitable for debugging: In order to debug the port specific code, optimizations need to be disabled on the port file (check the Makefile for specific details). You can use CCS from TI. Use the CC3200.ccxml file supplied with this distribution for the debuuger configuration. ``` make BTARGET=application BTYPE=debug BOARD=LAUNCHXL ``` ## Flashing the CC3200-LAUNCHXL Note that WiPy comes factory programmed with a default version of MicroPython, it cannot be programmed via serial, and can be upgraded only with OTA (see below). - Make sure that you have built both the *bootloader* and the *application* in **release** mode. - Make sure the SOP2 jumper is in position. - Make sure you Linux system recognized the board and created `ttyUSB*` devices (see below for configuration of `ftdi_sio` driver). - Run "make erase" and immediately press Reset button on the device. - Wait few seconds. - Run "make deploy" and immediately press Reset button on the device. - You are recommended to install the latest vendor WiFi firmware servicepack from http://www.ti.com/tool/cc3200sdk. Download CC3200SDK-SERVICEPACK package, install it, and locate `ota_*.ucf` and `ota_*.ucf.signed.bin` files. Copy them to the port's directory and run "make servicepack", with immediate press of Reset button. - Remove the SOP2 jumper and reset the board. Flashing process using TI Uniflash: - Open CCS_Uniflash and connect to the board (by default on port 22). - Format the serial flash (select 1MB size in case of the CC3200-LAUNCHXL, 2MB in case of the WiPy, leave the rest unchecked). - Mark the following files for erasing: `/cert/ca.pem`, `/cert/client.pem`, `/cert/private.key` and `/tmp/pac.bin`. - Add a new file with the name of /sys/mcuimg.bin, and select the URL to point to cc3200\bootmgr\build\\bootloader.bin. - Add another file with the name of /sys/factimg.bin, and select the URL to point to cc3200\build\\mcuimg.bin. - Click "Program" to apply all changes. - Flash the latest service pack (servicepack_1.0.0.10.0.bin) using the "Service Pack Update" button. - Close CCS_Uniflash, remove the SOP2 jumper and reset the board. ## Playing with MicroPython and the CC3200: Once the software is running, you have two options to access the MicroPython REPL: - Through telnet. * Connect to the network created by the board (as boots up in AP mode), **ssid = "wipy-wlan", key = "www.wipy.io"**. * You can also reinitialize the WLAN in station mode and connect to another AP, or in AP mode but with a different ssid and/or key. * Use your favourite telnet client with the following settings: **host = 192.168.1.1, port = 23.** * Log in with **user = "micro" and password = "python"** - Through UART (serial). * This is enabled by default in the standard configuration, for UART0 (speed 115200). * For CC3200-LAUNCHXL, you will need to configure Linux `ftdi_sio` driver as described in the [blog post](http://www.achanceofbrainshowers.com/blog/tech/2014/8/19/cc3200-development-under-linux/). After that, connecting a board will create two `/dev/ttyUSB*` devices, a serial console is available on the 2nd one (usually `/dev/ttyUSB1`). * WiPy doesn't have onboard USB-UART converter, so you will need an external one, connected to GPIO01 (Tx) and GPIO02 (Rx). * Usage of UART port for REPL is controlled by MICROPY_STDIO_UART setting (and is done at the high level, using a suitable call to `os.dupterm()` function in boot.py, so you can override it at runtime regardless of MICROPY_STDIO_UART setting). The board has a small file system of 192K (WiPy) or 64K (Launchpad) located in the serial flash connected to the CC3200. SD cards are also supported, you can connect any SD card and configure the pinout using the SD class API. ## Uploading scripts: To upload your MicroPython scripts to the FTP server, open your FTP client of choice and connect to: **ftp://192.168.1.1, user = "micro", password = "python"** Tested FTP clients are: FileZilla, FireFTP, FireFox, IE and Chrome. Other clients should work as well, but you may need to configure them to use a single connection (this should be the default for any compliant FTP client). ## Upgrading the firmware Over The Air (OTA) OTA software updates can be performed through the builtin FTP server. After building a new `mcuimg.bin` in release mode, upload it to: `/flash/sys/mcuimg.bin`. It will take around 6s (The TI SimpleLink file system is quite slow because every file is mirrored for safety). You won't see the file being stored inside `/flash/sys/` because it's actually saved bypassing FatFS, but rest assured that the file was successfully transferred, and it has been signed with a MD5 checksum to verify its integrity. Now, reset the MCU by pressing the switch on the board, or by typing: ```python import machine machine.reset() ``` There's a script which automates this process from the host side: - Make sure the board is running and connected to the same network as the computer. ```bash make BTARGET=application BTYPE=release BOARD=LAUNCHXL WIPY_IP=192.168.1.1 WIPY_USER=micro WIPY_PWD=python deploy-ota ``` If `WIPY_IP`, `WIPY_USER` or `WIPY_PWD` are omitted the default values (the ones shown above) will be used. ## Notes and known issues ## Regarding old revisions of the CC3200-LAUNCHXL First silicon (pre-release) revisions of the CC3200 had issues with the ram blocks, and MicroPython cannot run there. Make sure to use a **v4.1 (or higher) LAUNCHXL board** when trying this port, otherwise it won't work. ### Note regarding FileZilla Do not use the quick connect button, instead, open the site manager and create a new configuration. In the "General" tab make sure that encryption is set to: "Only use plain FTP (insecure)". In the Transfer Settings tab limit the max number of connections to one, otherwise FileZilla will try to open a second command connection when retrieving and saving files, and for simplicity and to reduce code size, only one command and one data connections are possible. micropython-1.12/ports/cc3200/application.lds000066400000000000000000000057351357706137100211040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ __stack_size__ = 2K; /* interrupts are handled within this stack */ __min_heap_size__ = 8K; MEMORY { SRAMB (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 0x0003C000 } ENTRY(ResetISR) SECTIONS { /* place the FreeRTOS heap (the MicroPython stack will live here) */ .rtos_heap (NOLOAD) : { . = ALIGN(8); *(.rtos_heap*) . = ALIGN(8); } > SRAMB .text : { _text = .; KEEP(*(.intvecs)) *(.text*) *(.rodata*) *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(8); } > SRAM .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; _etext = .; } > SRAM .data : { . = ALIGN(8); _data = .; *(.data*) . = ALIGN(8); _edata = .; } > SRAM .bss : { . = ALIGN(8); _bss = .; *(.bss*) *(COMMON) . = ALIGN(8); _ebss = .; } > SRAM /* place here functions that are only called during boot up, */ /* that way, we can re-use this area for the MicroPython heap */ .boot : { . = ALIGN(8); _boot = .; *(.boot*) . = ALIGN(8); _eboot = .; } > SRAM /* allocate the MicroPython heap */ .heap : { . = ALIGN(8); _heap = .; . = . + __min_heap_size__; . = . + (ORIGIN(SRAM) + LENGTH(SRAM) - __stack_size__ - ABSOLUTE(.)); . = ALIGN(8); _eheap = .; } > SRAM /* allocate the main stack */ .stack ORIGIN(SRAM) + LENGTH(SRAM) - __stack_size__ : { . = ALIGN(8); _stack = .; . = . + __stack_size__; . = ALIGN(8); _estack = .; } > SRAM } micropython-1.12/ports/cc3200/application.mk000066400000000000000000000124301357706137100207170ustar00rootroot00000000000000APP_INC = -I. APP_INC += -I$(TOP) APP_INC += -Ifatfs/src APP_INC += -Ifatfs/src/drivers APP_INC += -IFreeRTOS APP_INC += -IFreeRTOS/Source/include APP_INC += -IFreeRTOS/Source/portable/GCC/ARM_CM3 APP_INC += -Iftp APP_INC += -Ihal APP_INC += -Ihal/inc APP_INC += -Imisc APP_INC += -Imods APP_INC += -I$(TOP)/drivers/cc3100/inc APP_INC += -Isimplelink APP_INC += -Isimplelink/oslib APP_INC += -Itelnet APP_INC += -Iutil APP_INC += -Ibootmgr APP_INC += -I$(BUILD) APP_INC += -I$(BUILD)/genhdr APP_INC += -I$(TOP)/ports/stm32 APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS APP_FATFS_SRC_C = $(addprefix fatfs/src/,\ drivers/sflash_diskio.c \ drivers/sd_diskio.c \ ) APP_RTOS_SRC_C = $(addprefix FreeRTOS/Source/,\ croutine.c \ event_groups.c \ list.c \ queue.c \ tasks.c \ timers.c \ portable/GCC/ARM_CM3/port.c \ portable/MemMang/heap_4.c \ ) APP_FTP_SRC_C = $(addprefix ftp/,\ ftp.c \ updater.c \ ) APP_HAL_SRC_C = $(addprefix hal/,\ adc.c \ aes.c \ cc3200_hal.c \ cpu.c \ crc.c \ des.c \ gpio.c \ i2c.c \ i2s.c \ interrupt.c \ pin.c \ prcm.c \ sdhost.c \ shamd5.c \ spi.c \ startup_gcc.c \ systick.c \ timer.c \ uart.c \ utils.c \ wdt.c \ ) APP_MISC_SRC_C = $(addprefix misc/,\ antenna.c \ FreeRTOSHooks.c \ help.c \ mpirq.c \ mperror.c \ mpexception.c \ ) APP_MODS_SRC_C = $(addprefix mods/,\ modmachine.c \ modnetwork.c \ modubinascii.c \ moduos.c \ modusocket.c \ modussl.c \ modutime.c \ modwipy.c \ modwlan.c \ pybadc.c \ pybpin.c \ pybi2c.c \ pybrtc.c \ pybflash.c \ pybsd.c \ pybsleep.c \ pybspi.c \ pybtimer.c \ pybuart.c \ pybwdt.c \ ) APP_CC3100_SRC_C = $(addprefix drivers/cc3100/src/,\ device.c \ driver.c \ flowcont.c \ fs.c \ netapp.c \ netcfg.c \ socket.c \ wlan.c \ ) APP_SL_SRC_C = $(addprefix simplelink/,\ oslib/osi_freertos.c \ cc_pal.c \ ) APP_TELNET_SRC_C = $(addprefix telnet/,\ telnet.c \ ) APP_UTIL_SRC_C = $(addprefix util/,\ cryptohash.c \ fifo.c \ gccollect.c \ random.c \ socketfifo.c \ ) APP_UTIL_SRC_S = $(addprefix util/,\ sleeprestore.s \ ) APP_MAIN_SRC_C = \ main.c \ mptask.c \ mpthreadport.c \ serverstask.c \ fatfs_port.c \ APP_LIB_SRC_C = $(addprefix lib/,\ oofatfs/ff.c \ oofatfs/ffunicode.c \ libc/string0.c \ mp-readline/readline.c \ netutils/netutils.c \ timeutils/timeutils.c \ utils/pyexec.c \ utils/interrupt_char.c \ utils/sys_stdio_mphal.c \ ) APP_STM_SRC_C = $(addprefix ports/stm32/,\ bufhelper.c \ irq.c \ ) OBJ = $(PY_O) $(addprefix $(BUILD)/, $(APP_FATFS_SRC_C:.c=.o) $(APP_RTOS_SRC_C:.c=.o) $(APP_FTP_SRC_C:.c=.o) $(APP_HAL_SRC_C:.c=.o) $(APP_MISC_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(APP_MODS_SRC_C:.c=.o) $(APP_CC3100_SRC_C:.c=.o) $(APP_SL_SRC_C:.c=.o) $(APP_TELNET_SRC_C:.c=.o) $(APP_UTIL_SRC_C:.c=.o) $(APP_UTIL_SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o)) OBJ += $(BUILD)/lib/utils/gchelper_m3.o OBJ += $(BUILD)/pins.o # List of sources for qstr extraction SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += # Add the linker script LINKER_SCRIPT = application.lds LDFLAGS += -T $(LINKER_SCRIPT) # Add the application specific CFLAGS CFLAGS += $(APP_CPPDEFINES) $(APP_INC) # Disable strict aliasing for the simplelink driver $(BUILD)/drivers/cc3100/src/driver.o: CFLAGS += -fno-strict-aliasing # Check if we would like to debug the port code ifeq ($(BTYPE), release) CFLAGS += -DNDEBUG else ifeq ($(BTYPE), debug) CFLAGS += -DNDEBUG else $(error Invalid BTYPE specified) endif endif SHELL = bash APP_SIGN = appsign.sh UPDATE_WIPY ?= tools/update-wipy.py WIPY_IP ?= '192.168.1.1' WIPY_USER ?= 'micro' WIPY_PWD ?= 'python' all: $(BUILD)/mcuimg.bin .PHONY: deploy-ota deploy-ota: $(BUILD)/mcuimg.bin $(ECHO) "Writing $< to the board" $(Q)$(PYTHON) $(UPDATE_WIPY) --verify --ip $(WIPY_IP) --user $(WIPY_USER) --password $(WIPY_PWD) --file $< $(BUILD)/application.axf: $(OBJ) $(LINKER_SCRIPT) $(ECHO) "LINK $@" $(Q)$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS) $(Q)$(SIZE) $@ $(BUILD)/application.bin: $(BUILD)/application.axf $(ECHO) "Create $@" $(Q)$(OBJCOPY) -O binary $< $@ $(BUILD)/mcuimg.bin: $(BUILD)/application.bin $(ECHO) "Create $@" $(Q)$(SHELL) $(APP_SIGN) $(BUILD) MAKE_PINS = boards/make-pins.py BOARD_PINS = boards/$(BOARD)/pins.csv AF_FILE = boards/cc3200_af.csv PREFIX_FILE = boards/cc3200_prefix.c GEN_PINS_SRC = $(BUILD)/pins.c GEN_PINS_HDR = $(HEADER_BUILD)/pins.h GEN_PINS_QSTR = $(BUILD)/pins_qstr.h # Making OBJ use an order-only dependency on the generated pins.h file # has the side effect of making the pins.h file before we actually compile # any of the objects. The normal dependency generation will deal with the # case when pins.h is modified. But when it doesn't exist, we don't know # which source files might need it. $(OBJ): | $(GEN_PINS_HDR) # Call make-pins.py to generate both pins_gen.c and pins.h $(GEN_PINS_SRC) $(GEN_PINS_HDR) $(GEN_PINS_QSTR): $(BOARD_PINS) $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD) $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) > $(GEN_PINS_SRC) $(BUILD)/pins.o: $(BUILD)/pins.c $(call compile_c) micropython-1.12/ports/cc3200/appsign.sh000066400000000000000000000011151357706137100200560ustar00rootroot00000000000000#!/bin/bash if [ "$#" -ne 1 ]; then echo "Usage: appsign.sh *build dir*" exit 1 fi # Build location BUILD=$1 # Generate the MD5 hash # md5 on Darwin, md5sum on Unix if [ `uname -s` = "Darwin" ]; then echo -n `md5 -q $BUILD/application.bin` > __md5hash.bin else echo -n `md5sum --binary $BUILD/application.bin | awk '{ print $1 }'` > __md5hash.bin fi # Concatenate it with the application binary cat $BUILD/application.bin __md5hash.bin > $BUILD/mcuimg.bin RET=$? # Remove the tmp files rm -f __md5hash.bin # Remove the unsigned binary rm -f $BUILD/application.bin exit $RET micropython-1.12/ports/cc3200/boards/000077500000000000000000000000001357706137100173355ustar00rootroot00000000000000micropython-1.12/ports/cc3200/boards/LAUNCHXL/000077500000000000000000000000001357706137100205535ustar00rootroot00000000000000micropython-1.12/ports/cc3200/boards/LAUNCHXL/mpconfigboard.h000066400000000000000000000042621357706137100235420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define LAUNCHXL #define MICROPY_HW_BOARD_NAME "LaunchPad" #define MICROPY_HW_MCU_NAME "CC3200" #define MICROPY_HW_ANTENNA_DIVERSITY (0) #define MICROPY_STDIO_UART 1 #define MICROPY_STDIO_UART_BAUD 115200 #define MICROPY_SYS_LED_PRCM PRCM_GPIOA1 #define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA2 #define MICROPY_SYS_LED_PORT GPIOA1_BASE #define MICROPY_SAFE_BOOT_PORT GPIOA2_BASE #define MICROPY_SYS_LED_GPIO pin_GP9 #define MICROPY_SYS_LED_PIN_NUM PIN_64 // GP9 #define MICROPY_SAFE_BOOT_PIN_NUM PIN_15 // GP22 #define MICROPY_SYS_LED_PORT_PIN GPIO_PIN_1 #define MICROPY_SAFE_BOOT_PORT_PIN GPIO_PIN_6 #define MICROPY_PORT_SFLASH_BLOCK_COUNT 32 micropython-1.12/ports/cc3200/boards/LAUNCHXL/pins.csv000066400000000000000000000002521357706137100222400ustar00rootroot00000000000000P12,58 P13,4 P14,3 P15,61 P16,59 P17,5 P18,62 P19,1 P110,2 P33,57 P34,60 P37,63 P38,53 P39,64 P310,50 P49,16 P410,17 P22,18 P23,8 P24,45 P26,7 P27,6 P28,21 P29,55 P210,15micropython-1.12/ports/cc3200/boards/WIPY/000077500000000000000000000000001357706137100201255ustar00rootroot00000000000000micropython-1.12/ports/cc3200/boards/WIPY/mpconfigboard.h000066400000000000000000000042631357706137100231150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define WIPY #define MICROPY_HW_BOARD_NAME "WiPy" #define MICROPY_HW_MCU_NAME "CC3200" #define MICROPY_HW_ANTENNA_DIVERSITY (1) #define MICROPY_STDIO_UART 1 #define MICROPY_STDIO_UART_BAUD 115200 #define MICROPY_SYS_LED_PRCM PRCM_GPIOA3 #define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3 #define MICROPY_SYS_LED_PORT GPIOA3_BASE #define MICROPY_SAFE_BOOT_PORT GPIOA3_BASE #define MICROPY_SYS_LED_GPIO pin_GP25 #define MICROPY_SYS_LED_PIN_NUM PIN_21 // GP25 (SOP2) #define MICROPY_SAFE_BOOT_PIN_NUM PIN_18 // GP28 #define MICROPY_SYS_LED_PORT_PIN GPIO_PIN_1 #define MICROPY_SAFE_BOOT_PORT_PIN GPIO_PIN_4 #define MICROPY_PORT_SFLASH_BLOCK_COUNT 96 micropython-1.12/ports/cc3200/boards/WIPY/pins.csv000066400000000000000000000003111357706137100216060ustar00rootroot00000000000000L2,GP2 L3,GP1 L4,GP23 L5,GP24 L6,GP11 L7,GP12 L8,GP13 L9,GP14 L10,GP15 L11,GP16 L12,GP17 L13,GP22 L14,GP28 R4,GP10 R5,GP9 R6,GP8 R7,GP7 R8,GP6 R9,GP30 R10,GP31 R11,GP3 R12,GP0 R13,GP4 R14,GP5 HBL,GP25 micropython-1.12/ports/cc3200/boards/cc3200_af.csv000066400000000000000000000071741357706137100214230ustar00rootroot00000000000000Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,ADC 1,GP10,GP10,GP10,I2C0_SCL,,TIM3_PWM,,,SD0_CLK,UART1_TX,,,,,TIM0_CC,,,, 2,GP11,GP11,GP11,I2C0_SDA,,TIM3_PWM,pXCLK(XVCLK),,SD0_CMD,UART1_RX,,,,,TIM1_CC,I2S0_FS,,, 3,GP12,GP12,GP12,,,I2S0_CLK,pVS(VSYNC),I2C0_SCL,,UART0_TX,,,,,TIM1_CC,,,, 4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C0_SDA,,UART0_RX,,,,,TIM2_CC,,,, 5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),I2C0_SCL,,SPI0_CLK,,,,,TIM2_CC,,,, 6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C0_SDA,,SPI0_MISO,SD0_DAT0,,,,,TIM3_CC,,, 7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,SPI0_MOSI,SD0_CLK,,,,,TIM3_CC,,, 8,GP17,GP17,GP17,,,,pDATA11(CAM_D7),UART1_RX,,SPI0_CS0,SD0_CMD,,,,,,,, 9,VDD_DIG1,VDD_DIG1,VDD_DIG1,,,,,,,,,,,,,,,, 10,VIN_IO1,VIN_IO1,VIN_IO1,,,,,,,,,,,,,,,, 11,FLASH_SPI_CLK,FLASH_SPI_CLK,FLASH_SPI_CLK,,,,,,,,,,,,,,,, 12,FLASH_SPI_DOUT,FLASH_SPI_DOUT,FLASH_SPI_DOUT,,,,,,,,,,,,,,,, 13,FLASH_SPI_DIN,FLASH_SPI_DIN,FLASH_SPI_DIN,,,,,,,,,,,,,,,, 14,FLASH_SPI_CS,FLASH_SPI_CS,FLASH_SPI_CS,,,,,,,,,,,,,,,, 15,GP22,GP22,GP22,,,,,TIM2_CC,,I2S0_FS,,,,,,,,, 16,GP23,TDI,GP23,TDI,UART1_TX,,,,,,,I2C0_SCL,,,,,,, 17,GP24,TDO,GP24,TDO,UART1_RX,,TIM3_CC,TIM0_PWM,I2S0_FS,,,I2C0_SDA,,,,,,, 18,GP28,GP28,GP28,,,,,,,,,,,,,,,, 19,TCK,TCK,,TCK,,,,,,,TIM1_PWM,,,,,,,, 20,GP29,TMS,GP29,TMS,,,,,,,,,,,,,,, 21,GP25,SOP2,GP25,,I2S0_FS,,,,,,,TIM1_PWM,,,,,,, 22,WLAN_XTAL_N,WLAN_XTAL_N,WLAN_XTAL_N,,,,,,,,,,,,,,,, 23,WLAN_XTAL_P,WLAN_XTAL_P,WLAN_XTAL_P,,,,,,,,,,,,,,,, 24,VDD_PLL,VDD_PLL,VDD_PLL,,,,,,,,,,,,,,,, 25,LDO_IN2,LDO_IN2,LDO_IN2,,,,,,,,,,,,,,,, 26,NC,NC,NC,,,,,,,,,,,,,,,, 27,NC,NC,NC,,,,,,,,,,,,,,,, 28,NC,NC,NC,,,,,,,,,,,,,,,, 29,ANTSEL1,ANTSEL1,ANTSEL1,,,,,,,,,,,,,,,, 30,ANTSEL2,ANTSEL2,ANTSEL2,,,,,,,,,,,,,,,, 31,RF_BG,RF_BG,RF_BG,,,,,,,,,,,,,,,, 32,nRESET,nRESET,nRESET,,,,,,,,,,,,,,,, 33,VDD_PA_IN,VDD_PA_IN,VDD_PA_IN,,,,,,,,,,,,,,,, 34,SOP1,SOP1,SOP1,,,,,,,,,,,,,,,, 35,SOP0,SOP0,SOP0,,,,,,,,,,,,,,,, 36,LDO_IN1,LDO_IN1,LDO_IN1,,,,,,,,,,,,,,,, 37,VIN_DCDC_ANA,VIN_DCDC_ANA,VIN_DCDC_ANA,,,,,,,,,,,,,,,, 38,DCDC_ANA_SW,DCDC_ANA_SW,DCDC_ANA_SW,,,,,,,,,,,,,,,, 39,VIN_DCDC_PA,VIN_DCDC_ PA,VIN_DCDC_PA,,,,,,,,,,,,,,,, 40,DCDC_PA_SW_P,DCDC_PA_SW_P,DCDC_PA_SW_P,,,,,,,,,,,,,,,, 41,DCDC_PA_SW_N,DCDC_PA_SW_N,DCDC_PA_SW_N,,,,,,,,,,,,,,,, 42,DCDC_PA_OUT,DCDC_PA_O UT,DCDC_PA_O UT,,,,,,,,,,,,,,,, 43,DCDC_DIG_SW,DCDC_DIG_ SW,DCDC_DIG_ SW,,,,,,,,,,,,,,,, 44,VIN_DCDC_DIG,VIN_DCDC_ DIG,VIN_DCDC_ DIG,,,,,,,,,,,,,,,, 45,GP31,DCDC_ANA2_SW_P,GP31,,UART1_RX,,,,I2S0_DAT0,SPI0_CLK,,UART0_RX,,,I2S0_FS,,,, 46,DCDC_ANA2_SW_N,DCDC_ANA2_SW_N,DCDC_ANA2_SW_N,,,,,,,,,,,,,,,, 47,VDD_ANA2,VDD_ANA2,VDD_ANA2,,,,,,,,,,,,,,,, 48,VDD_ANA1,VDD_ANA1,VDD_ANA1,,,,,,,,,,,,,,,, 49,VDD_RAM,VDD_RAM,VDD_RAM,,,,,,,,,,,,,,,, 50,GP0,GP0,GP0,,,UART0_RTS,I2S0_DAT0,,I2S0_DAT1,TIM0_CC,,SPI0_CS0,UART1_RTS,,UART0_CTS,,,, 51,RTC_XTAL_P,RTC_XTAL_P,RTC_XTAL_P,,,,,,,,,,,,,,,, 52,RTC_XTAL_N,RTC_XTAL_N,GP32,,I2S0_CLK,,I2S0_DAT0,,UART0_RTS,,SPI0_MOSI,,,,,,,, 53,GP30,GP30,GP30,,I2S0_CLK,I2S0_FS,TIM2_CC,,,SPI0_MISO,,UART0_TX,,,,,,, 54,VIN_IO2,VIN_IO2,VIN_IO2,,,,,,,,,,,,,,,, 55,GP1,GP1,GP1,,,UART0_TX,pCLK (PIXCLK),,UART1_TX,TIM0_CC,,,,,,,,, 56,VDD_DIG2,VDD_DIG2,VDD_DIG2,,,,,,,,,,,,,,,, 57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,TIM1_CC,,,,,,,,,ADC0_CH0 58,GP3,GP3,GP3,,,,pDATA7(CAM_D3),,UART1_TX,,,,,,,,,,ADC0_CH1 59,GP4,GP4,GP4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC0_CH2 60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,I2S0_DAT1,TIM2_CC,,,,,,,,,ADC0_CH3 61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,TIM3_CC,,,,,,,,, 62,GP7,GP7,GP7,,,UART1_RTS,,,,,,,UART0_RTS,UART0_TX,,I2S0_CLK,,, 63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC,,,, 64,GP9,GP9,GP9,,,TIM2_PWM,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC,,,, 65,GND_TAB,GND_TAB,GND_TAB,,,,,,,,,,,,,,,, micropython-1.12/ports/cc3200/boards/cc3200_prefix.c000066400000000000000000000045031357706137100217520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // cc3200_prefix.c becomes the initial portion of the generated pins file. #include #include #include "py/mpconfig.h" #include "py/obj.h" #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "pin.h" #include "gpio.h" #include "pybpin.h" #define AF(af_name, af_idx, af_fn, af_unit, af_type) \ { \ .name = MP_QSTR_ ## af_name, \ .idx = (af_idx), \ .fn = PIN_FN_ ## af_fn, \ .unit = (af_unit), \ .type = PIN_TYPE_ ## af_fn ## _ ## af_type, \ } #define PIN(p_pin_name, p_port, p_bit, p_pin_num, p_af_list, p_num_afs) \ { \ { &pin_type }, \ .name = MP_QSTR_ ## p_pin_name, \ .port = PORT_A ## p_port, \ .af_list = (p_af_list), \ .pull = PIN_TYPE_STD, \ .bit = (p_bit), \ .pin_num = (p_pin_num), \ .af = PIN_MODE_0, \ .strength = PIN_STRENGTH_4MA, \ .mode = GPIO_DIR_MODE_IN, \ .num_afs = (p_num_afs), \ .value = 0, \ .used = false, \ .irq_trigger = 0, \ .irq_flags = 0, \ } micropython-1.12/ports/cc3200/boards/make-pins.py000066400000000000000000000201041357706137100215700ustar00rootroot00000000000000#!/usr/bin/env python """Generates the pins file for the CC3200.""" from __future__ import print_function import argparse import sys import csv SUPPORTED_AFS = { 'UART': ('TX', 'RX', 'RTS', 'CTS'), 'SPI': ('CLK', 'MOSI', 'MISO', 'CS0'), #'I2S': ('CLK', 'FS', 'DAT0', 'DAT1'), 'I2C': ('SDA', 'SCL'), 'TIM': ('PWM'), 'SD': ('CLK', 'CMD', 'DAT0'), 'ADC': ('CH0', 'CH1', 'CH2', 'CH3') } def parse_port_pin(name_str): """Parses a string and returns a (port, gpio_bit) tuple.""" if len(name_str) < 3: raise ValueError("Expecting pin name to be at least 3 characters") if name_str[:2] != 'GP': raise ValueError("Expecting pin name to start with GP") if not name_str[2:].isdigit(): raise ValueError("Expecting numeric GPIO number") port = int(int(name_str[2:]) / 8) gpio_bit = 1 << int(int(name_str[2:]) % 8) return (port, gpio_bit) class AF: """Holds the description of an alternate function""" def __init__(self, name, idx, fn, unit, type): self.name = name self.idx = idx if self.idx > 15: self.idx = -1 self.fn = fn self.unit = unit self.type = type def print(self): print (' AF({:16s}, {:4d}, {:8s}, {:4d}, {:8s}), // {}'.format(self.name, self.idx, self.fn, self.unit, self.type, self.name)) class Pin: """Holds the information associated with a pin.""" def __init__(self, name, port, gpio_bit, pin_num): self.name = name self.port = port self.gpio_bit = gpio_bit self.pin_num = pin_num self.board_pin = False self.afs = [] def add_af(self, af): self.afs.append(af) def print(self): print('// {}'.format(self.name)) if len(self.afs): print('const pin_af_t pin_{}_af[] = {{'.format(self.name)) for af in self.afs: af.print() print('};') print('pin_obj_t pin_{:4s} = PIN({:6s}, {:1d}, {:3d}, {:2d}, pin_{}_af, {});\n'.format( self.name, self.name, self.port, self.gpio_bit, self.pin_num, self.name, len(self.afs))) else: print('pin_obj_t pin_{:4s} = PIN({:6s}, {:1d}, {:3d}, {:2d}, NULL, 0);\n'.format( self.name, self.name, self.port, self.gpio_bit, self.pin_num)) def print_header(self, hdr_file): hdr_file.write('extern pin_obj_t pin_{:s};\n'.format(self.name)) class Pins: def __init__(self): self.board_pins = [] # list of pin objects def find_pin(self, port, gpio_bit): for pin in self.board_pins: if pin.port == port and pin.gpio_bit == gpio_bit: return pin def find_pin_by_num(self, pin_num): for pin in self.board_pins: if pin.pin_num == pin_num: return pin def find_pin_by_name(self, name): for pin in self.board_pins: if pin.name == name: return pin def parse_af_file(self, filename, pin_col, pinname_col, af_start_col): with open(filename, 'r') as csvfile: rows = csv.reader(csvfile) for row in rows: try: (port_num, gpio_bit) = parse_port_pin(row[pinname_col]) except: continue if not row[pin_col].isdigit(): raise ValueError("Invalid pin number {:s} in row {:s}".format(row[pin_col]), row) # Pin numbers must start from 0 when used with the TI API pin_num = int(row[pin_col]) - 1; pin = Pin(row[pinname_col], port_num, gpio_bit, pin_num) self.board_pins.append(pin) af_idx = 0 for af in row[af_start_col:]: af_splitted = af.split('_') fn_name = af_splitted[0].rstrip('0123456789') if fn_name in SUPPORTED_AFS: type_name = af_splitted[1] if type_name in SUPPORTED_AFS[fn_name]: unit_idx = af_splitted[0][-1] pin.add_af(AF(af, af_idx, fn_name, int(unit_idx), type_name)) af_idx += 1 def parse_board_file(self, filename, cpu_pin_col): with open(filename, 'r') as csvfile: rows = csv.reader(csvfile) for row in rows: # Pin numbers must start from 0 when used with the TI API if row[cpu_pin_col].isdigit(): pin = self.find_pin_by_num(int(row[cpu_pin_col]) - 1) else: pin = self.find_pin_by_name(row[cpu_pin_col]) if pin: pin.board_pin = True def print_named(self, label, pins): print('') print('STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label)) for pin in pins: if pin.board_pin: print(' {{ MP_ROM_QSTR(MP_QSTR_{:6s}), MP_ROM_PTR(&pin_{:6s}) }},'.format(pin.name, pin.name)) print('};') print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label)); def print(self): for pin in self.board_pins: if pin.board_pin: pin.print() self.print_named('board', self.board_pins) print('') def print_header(self, hdr_filename): with open(hdr_filename, 'wt') as hdr_file: for pin in self.board_pins: if pin.board_pin: pin.print_header(hdr_file) def print_qstr(self, qstr_filename): with open(qstr_filename, 'wt') as qstr_file: pin_qstr_set = set([]) af_qstr_set = set([]) for pin in self.board_pins: if pin.board_pin: pin_qstr_set |= set([pin.name]) for af in pin.afs: af_qstr_set |= set([af.name]) print('// Board pins', file=qstr_file) for qstr in sorted(pin_qstr_set): print('Q({})'.format(qstr), file=qstr_file) print('\n// Pin AFs', file=qstr_file) for qstr in sorted(af_qstr_set): print('Q({})'.format(qstr), file=qstr_file) def main(): parser = argparse.ArgumentParser( prog="make-pins.py", usage="%(prog)s [options] [command]", description="Generate board specific pin file" ) parser.add_argument( "-a", "--af", dest="af_filename", help="Specifies the alternate function file for the chip", default="cc3200_af.csv" ) parser.add_argument( "-b", "--board", dest="board_filename", help="Specifies the board file", ) parser.add_argument( "-p", "--prefix", dest="prefix_filename", help="Specifies beginning portion of generated pins file", default="cc3200_prefix.c" ) parser.add_argument( "-q", "--qstr", dest="qstr_filename", help="Specifies name of generated qstr header file", default="build/pins_qstr.h" ) parser.add_argument( "-r", "--hdr", dest="hdr_filename", help="Specifies name of generated pin header file", default="build/pins.h" ) args = parser.parse_args(sys.argv[1:]) pins = Pins() print('// This file was automatically generated by make-pins.py') print('//') if args.af_filename: print('// --af {:s}'.format(args.af_filename)) pins.parse_af_file(args.af_filename, 0, 1, 3) if args.board_filename: print('// --board {:s}'.format(args.board_filename)) pins.parse_board_file(args.board_filename, 1) if args.prefix_filename: print('// --prefix {:s}'.format(args.prefix_filename)) print('') with open(args.prefix_filename, 'r') as prefix_file: print(prefix_file.read()) pins.print() pins.print_qstr(args.qstr_filename) pins.print_header(args.hdr_filename) if __name__ == "__main__": main() micropython-1.12/ports/cc3200/bootmgr/000077500000000000000000000000001357706137100175345ustar00rootroot00000000000000micropython-1.12/ports/cc3200/bootmgr/bootgen.sh000066400000000000000000000017131357706137100215270ustar00rootroot00000000000000#!/bin/bash if [ "$#" -ne 1 ]; then echo "Usage: bootgen.sh *build dir*" exit 1 fi BUILD=$1 # Re-locator Path RELOCATOR=bootmgr/relocator # Build location BOOTMGR=${BUILD} # Check for re-locator binary if [ ! -f $RELOCATOR/relocator.bin ]; then echo "Error : Relocator Not found!" exit 1 else echo "Relocator found..." fi # Check for boot manager binary if [ ! -f $BOOTMGR/bootmgr.bin ]; then echo "Error : Boot Manager Not found!" exit 1 else echo "Boot Manager found..." fi # echo echo "Generating bootloader..." # Generate an all 0 bin file dd if=/dev/zero of=__tmp.bin ibs=1 count=256 conv=notrunc >/dev/null 2>&1 # Generate a 0 padded version of the relocator dd if=$RELOCATOR/relocator.bin of=__tmp.bin ibs=1 conv=notrunc >/dev/null 2>&1 # Concatenate the re-locator and the boot-manager cat __tmp.bin $BOOTMGR/bootmgr.bin > $BOOTMGR/bootloader.bin # Remove the tmp files rm -f __tmp.bin # Remove bootmgr.bin rm -f $BOOTMGR/bootmgr.bin micropython-1.12/ports/cc3200/bootmgr/bootloader.mk000066400000000000000000000056311357706137100222240ustar00rootroot00000000000000BUILD = bootmgr/build/$(BOARD)/$(BTYPE) BOOT_INC = -Ibootmgr BOOT_INC += -Ibootmgr/sl BOOT_INC += -Ihal BOOT_INC += -Ihal/inc BOOT_INC += -I$(TOP)/drivers/cc3100/inc BOOT_INC += -Imisc BOOT_INC += -Imods BOOT_INC += -Isimplelink BOOT_INC += -Isimplelink/oslib BOOT_INC += -Iutil BOOT_INC += -I$(TOP) BOOT_INC += -I. BOOT_INC += -I$(BUILD) BOOT_CPPDEFINES = -Dgcc -DBOOTLOADER -DTARGET_IS_CC3200 -DSL_TINY BOOT_HAL_SRC_C = $(addprefix hal/,\ cpu.c \ interrupt.c \ gpio.c \ pin.c \ prcm.c \ shamd5.c \ spi.c \ startup_gcc.c \ systick.c \ utils.c \ ) BOOT_CC3100_SRC_C = $(addprefix drivers/cc3100/,\ src/device.c \ src/driver.c \ src/flowcont.c \ src/fs.c \ src/netapp.c \ src/netcfg.c \ src/nonos.c \ src/socket.c \ src/spawn.c \ src/wlan.c \ ) BOOT_MISC_SRC_C = $(addprefix misc/,\ antenna.c \ mperror.c \ ) BOOT_SL_SRC_C = $(addprefix simplelink/,\ cc_pal.c \ ) BOOT_UTIL_SRC_C = $(addprefix util/,\ cryptohash.c \ ) BOOT_MAIN_SRC_C = \ bootmgr/main.c BOOT_MAIN_SRC_S = \ bootmgr/runapp.s BOOT_PY_SRC_C = $(addprefix py/,\ mpprint.c \ ) BOOT_LIB_SRC_C = $(addprefix lib/,\ libc/string0.c \ utils/printf.c \ ) OBJ = $(addprefix $(BUILD)/, $(BOOT_HAL_SRC_C:.c=.o) $(BOOT_SL_SRC_C:.c=.o) $(BOOT_CC3100_SRC_C:.c=.o) $(BOOT_UTIL_SRC_C:.c=.o) $(BOOT_MISC_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(BOOT_MAIN_SRC_C:.c=.o) $(BOOT_MAIN_SRC_S:.s=.o) $(BOOT_PY_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(BOOT_LIB_SRC_C:.c=.o)) # Add the linker script LINKER_SCRIPT = bootmgr/bootmgr.lds LDFLAGS += -T $(LINKER_SCRIPT) # Add the bootloader specific CFLAGS CFLAGS += $(BOOT_CPPDEFINES) $(BOOT_INC) # Disable strict aliasing for the simplelink driver $(BUILD)/drivers/cc3100/src/driver.o: CFLAGS += -fno-strict-aliasing # Check if we would like to debug the port code ifeq ($(BTYPE), release) # Optimize everything and define the NDEBUG flag CFLAGS += -Os -DNDEBUG else ifeq ($(BTYPE), debug) # Define the DEBUG flag CFLAGS += -DDEBUG=DEBUG # Optimize the stable sources only $(BUILD)/hal/%.o: CFLAGS += -Os $(BUILD)/misc/%.o: CFLAGS += -Os $(BUILD)/simplelink/%.o: CFLAGS += -Os $(BUILD)/drivers/cc3100/%.o: CFLAGS += -Os $(BUILD)/py/%.o: CFLAGS += -Os $(BUILD)/ports/stm32/%.o: CFLAGS += -Os else $(error Invalid BTYPE specified) endif endif SHELL = bash BOOT_GEN = bootmgr/bootgen.sh HEADER_BUILD = $(BUILD)/genhdr all: $(BUILD)/bootloader.bin $(BUILD)/bootmgr.axf: $(OBJ) $(LINKER_SCRIPT) $(ECHO) "LINK $@" $(Q)$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS) $(Q)$(SIZE) $@ $(BUILD)/bootmgr.bin: $(BUILD)/bootmgr.axf $(ECHO) "Create $@" $(Q)$(OBJCOPY) -O binary $< $@ $(BUILD)/bootloader.bin: $(BUILD)/bootmgr.bin $(ECHO) "Create $@" $(Q)$(SHELL) $(BOOT_GEN) $(BUILD) # Create an empty "qstrdefs.generated.h" needed by py/mkrules.mk $(HEADER_BUILD)/qstrdefs.generated.h: | $(HEADER_BUILD) touch $@ # Create an empty "mpversion.h" needed by py/mkrules.mk $(HEADER_BUILD)/mpversion.h: | $(HEADER_BUILD) touch $@ micropython-1.12/ports/cc3200/bootmgr/bootmgr.h000066400000000000000000000052741357706137100213660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_BOOTMGR_BOOTMGR_H #define MICROPY_INCLUDED_CC3200_BOOTMGR_BOOTMGR_H //**************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //**************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // User image tokens //***************************************************************************** #define FACTORY_IMG_TOKEN 0x5555AAAA #define UPDATE_IMG_TOKEN 0xAA5555AA #define USER_BOOT_INFO_TOKEN 0xA5A55A5A //***************************************************************************** // Macros //***************************************************************************** #define APP_IMG_SRAM_OFFSET 0x20004000 #define DEVICE_IS_CC3101RS 0x18 #define DEVICE_IS_CC3101S 0x1B //***************************************************************************** // Function prototype //***************************************************************************** extern void Run(unsigned long); //**************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //**************************************************************************** #ifdef __cplusplus } #endif #endif // MICROPY_INCLUDED_CC3200_BOOTMGR_BOOTMGR_H micropython-1.12/ports/cc3200/bootmgr/bootmgr.lds000066400000000000000000000040501357706137100217100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ __stack_size__ = 1024; MEMORY { SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 } ENTRY(ResetISR) SECTIONS { .text : { _text = .; KEEP(*(.intvecs)) *(.boot*) *(.text*) *(.rodata*) *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(8); } > SRAM .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; _etext = .; } > SRAM .data : { _data = .; *(.data*) . = ALIGN (8); _edata = .; } > SRAM .bss : { _bss = .; *(.bss*) *(COMMON) _ebss = .; } > SRAM .stack ORIGIN(SRAM) + LENGTH(SRAM) - __stack_size__ : { . = ALIGN(8); _stack = .; . = . + __stack_size__; . = ALIGN(8); _estack = .; } > SRAM } micropython-1.12/ports/cc3200/bootmgr/flc.h000066400000000000000000000071671357706137100204640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_BOOTMGR_FLC_H #define MICROPY_INCLUDED_CC3200_BOOTMGR_FLC_H /****************************************************************************** If building with a C++ compiler, make all of the definitions in this header have a C binding. *******************************************************************************/ #ifdef __cplusplus extern "C" { #endif /****************************************************************************** Image file names *******************************************************************************/ #define IMG_BOOT_INFO "/sys/bootinfo.bin" #define IMG_FACTORY "/sys/factimg.bin" #define IMG_UPDATE1 "/sys/updtimg1.bin" #define IMG_UPDATE2 "/sys/updtimg2.bin" #define IMG_PREFIX "/sys/updtimg" #define IMG_SRVPACK "/sys/servicepack.ucf" #define SRVPACK_SIGN "/sys/servicepack.sig" #define CA_FILE "/cert/ca.pem" #define CERT_FILE "/cert/cert.pem" #define KEY_FILE "/cert/private.key" /****************************************************************************** Special file sizes *******************************************************************************/ #define IMG_SIZE (192 * 1024) /* 16KB are reserved for the bootloader and at least 48KB for the heap*/ #define SRVPACK_SIZE (16 * 1024) #define SIGN_SIZE (2 * 1024) #define CA_KEY_SIZE (4 * 1024) /****************************************************************************** Active Image *******************************************************************************/ #define IMG_ACT_FACTORY 0 #define IMG_ACT_UPDATE1 1 #define IMG_ACT_UPDATE2 2 #define IMG_STATUS_CHECK 0 #define IMG_STATUS_READY 1 /****************************************************************************** Boot Info structure *******************************************************************************/ typedef struct _sBootInfo_t { _u8 ActiveImg; _u8 Status; _u8 PrevImg; _u8 : 8; } sBootInfo_t; /****************************************************************************** Mark the end of the C bindings section for C++ compilers. *******************************************************************************/ #ifdef __cplusplus } #endif #endif // MICROPY_INCLUDED_CC3200_BOOTMGR_FLC_H micropython-1.12/ports/cc3200/bootmgr/main.c000066400000000000000000000375621357706137100206410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpconfig.h" #include "hw_ints.h" #include "hw_types.h" #include "hw_gpio.h" #include "hw_memmap.h" #include "hw_gprcm.h" #include "hw_common_reg.h" #include "pin.h" #include "gpio.h" #include "rom_map.h" #include "prcm.h" #include "simplelink.h" #include "interrupt.h" #include "gpio.h" #include "flc.h" #include "bootmgr.h" #include "shamd5.h" #include "cryptohash.h" #include "utils.h" #include "cc3200_hal.h" #include "debug.h" #include "mperror.h" #include "antenna.h" //***************************************************************************** // Local Constants //***************************************************************************** #define SL_STOP_TIMEOUT 35 #define BOOTMGR_HASH_ALGO SHAMD5_ALGO_MD5 #define BOOTMGR_HASH_SIZE 32 #define BOOTMGR_BUFF_SIZE 512 #define BOOTMGR_WAIT_SAFE_MODE_0_MS 500 #define BOOTMGR_WAIT_SAFE_MODE_1_MS 3000 #define BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS 500 #define BOOTMGR_WAIT_SAFE_MODE_2_MS 3000 #define BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS 250 #define BOOTMGR_WAIT_SAFE_MODE_3_MS 1500 #define BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS 100 //***************************************************************************** // Exported functions declarations //***************************************************************************** extern void bootmgr_run_app (_u32 base); //***************************************************************************** // Local functions declarations //***************************************************************************** static void bootmgr_board_init (void); static bool bootmgr_verify (_u8 *image); static void bootmgr_load_and_execute (_u8 *image); static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait); static bool safe_boot_request_start (uint32_t wait_time); static void wait_for_safe_boot (sBootInfo_t *psBootInfo); static void bootmgr_image_loader (sBootInfo_t *psBootInfo); //***************************************************************************** // Private data //***************************************************************************** static _u8 bootmgr_file_buf[BOOTMGR_BUFF_SIZE]; static _u8 bootmgr_hash_buf[BOOTMGR_HASH_SIZE + 1]; //***************************************************************************** // Vector Table //***************************************************************************** extern void (* const g_pfnVectors[])(void); //***************************************************************************** // WLAN Event handler callback hookup function //***************************************************************************** void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) { } //***************************************************************************** // HTTP Server callback hookup function //***************************************************************************** void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent, SlHttpServerResponse_t *pHttpResponse) { } //***************************************************************************** // Net APP Event callback hookup function //***************************************************************************** void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent) { } //***************************************************************************** // General Event callback hookup function //***************************************************************************** void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent) { } //***************************************************************************** // Socket Event callback hookup function //***************************************************************************** void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) { } //***************************************************************************** //! Board Initialization & Configuration //***************************************************************************** static void bootmgr_board_init(void) { // set the vector table base MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]); // enable processor interrupts MAP_IntMasterEnable(); MAP_IntEnable(FAULT_SYSTICK); // mandatory MCU initialization PRCMCC3200MCUInit(); // clear all the special bits, since we can't trust their content after reset // except for the WDT reset one!! PRCMClearSpecialBit(PRCM_SAFE_BOOT_BIT); PRCMClearSpecialBit(PRCM_FIRST_BOOT_BIT); // check the reset after clearing the special bits mperror_bootloader_check_reset_cause(); #if MICROPY_HW_ANTENNA_DIVERSITY // configure the antenna selection pins antenna_init0(); #endif // enable the data hashing engine CRYPTOHASH_Init(); // init the system led and the system switch mperror_init0(); } //***************************************************************************** //! Verifies the integrity of the new application binary //***************************************************************************** static bool bootmgr_verify (_u8 *image) { SlFsFileInfo_t FsFileInfo; _u32 reqlen, offset = 0; _i32 fHandle; // open the file for reading if (0 == sl_FsOpen(image, FS_MODE_OPEN_READ, NULL, &fHandle)) { // get the file size sl_FsGetInfo(image, 0, &FsFileInfo); if (FsFileInfo.FileLen > BOOTMGR_HASH_SIZE) { FsFileInfo.FileLen -= BOOTMGR_HASH_SIZE; CRYPTOHASH_SHAMD5Start(BOOTMGR_HASH_ALGO, FsFileInfo.FileLen); do { if ((FsFileInfo.FileLen - offset) > BOOTMGR_BUFF_SIZE) { reqlen = BOOTMGR_BUFF_SIZE; } else { reqlen = FsFileInfo.FileLen - offset; } offset += sl_FsRead(fHandle, offset, bootmgr_file_buf, reqlen); CRYPTOHASH_SHAMD5Update(bootmgr_file_buf, reqlen); } while (offset < FsFileInfo.FileLen); CRYPTOHASH_SHAMD5Read (bootmgr_file_buf); // convert the resulting hash to hex for (_u32 i = 0; i < (BOOTMGR_HASH_SIZE / 2); i++) { snprintf ((char *)&bootmgr_hash_buf[(i * 2)], 3, "%02x", bootmgr_file_buf[i]); } // read the hash from the file and close it sl_FsRead(fHandle, offset, bootmgr_file_buf, BOOTMGR_HASH_SIZE); sl_FsClose (fHandle, NULL, NULL, 0); bootmgr_file_buf[BOOTMGR_HASH_SIZE] = '\0'; // compare both hashes if (!strcmp((const char *)bootmgr_hash_buf, (const char *)bootmgr_file_buf)) { // it's a match return true; } } // close the file sl_FsClose(fHandle, NULL, NULL, 0); } return false; } //***************************************************************************** //! Loads the application from sFlash and executes //***************************************************************************** static void bootmgr_load_and_execute (_u8 *image) { SlFsFileInfo_t pFsFileInfo; _i32 fhandle; // open the application binary if (!sl_FsOpen(image, FS_MODE_OPEN_READ, NULL, &fhandle)) { // get the file size if (!sl_FsGetInfo(image, 0, &pFsFileInfo)) { // read the application into SRAM if (pFsFileInfo.FileLen == sl_FsRead(fhandle, 0, (unsigned char *)APP_IMG_SRAM_OFFSET, pFsFileInfo.FileLen)) { // close the file sl_FsClose(fhandle, 0, 0, 0); // stop the network services sl_Stop(SL_STOP_TIMEOUT); // execute the application bootmgr_run_app(APP_IMG_SRAM_OFFSET); } } } } //***************************************************************************** //! Wait while the safe mode pin is being held high and blink the system led //! with the specified period //***************************************************************************** static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait) { _u32 count; for (count = 0; (force_wait || MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) && ((period * count) < wait_time); count++) { // toogle the led MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN)); UtilsDelay(UTILS_DELAY_US_TO_COUNT(period * 1000)); } return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false; } static bool safe_boot_request_start (uint32_t wait_time) { if (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) { UtilsDelay(UTILS_DELAY_US_TO_COUNT(wait_time * 1000)); } return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false; } //***************************************************************************** //! Check for the safe mode pin //***************************************************************************** static void wait_for_safe_boot (sBootInfo_t *psBootInfo) { if (safe_boot_request_start(BOOTMGR_WAIT_SAFE_MODE_0_MS)) { if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_1_MS, BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS, false)) { // go back one step in time psBootInfo->ActiveImg = psBootInfo->PrevImg; if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_2_MS, BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS, false)) { // go back directly to the factory image psBootInfo->ActiveImg = IMG_ACT_FACTORY; wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_3_MS, BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS, true); } } // turn off the system led MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0); // request a safe boot to the application PRCMSetSpecialBit(PRCM_SAFE_BOOT_BIT); } // deinit the safe boot pin mperror_deinit_sfe_pin(); } //***************************************************************************** //! Load the proper image based on the information from the boot info //! and launch it. //***************************************************************************** static void bootmgr_image_loader(sBootInfo_t *psBootInfo) { _i32 fhandle; _u8 *image; // search for the active image switch (psBootInfo->ActiveImg) { case IMG_ACT_UPDATE1: image = (unsigned char *)IMG_UPDATE1; break; case IMG_ACT_UPDATE2: image = (unsigned char *)IMG_UPDATE2; break; default: image = (unsigned char *)IMG_FACTORY; break; } // do we have a new image that needs to be verified? if ((psBootInfo->ActiveImg != IMG_ACT_FACTORY) && (psBootInfo->Status == IMG_STATUS_CHECK)) { if (!bootmgr_verify(image)) { // verification failed, delete the broken file sl_FsDel(image, 0); // switch to the previous image psBootInfo->ActiveImg = psBootInfo->PrevImg; psBootInfo->PrevImg = IMG_ACT_FACTORY; } // in any case, change the status to "READY" psBootInfo->Status = IMG_STATUS_READY; // write the new boot info if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle)) { sl_FsWrite(fhandle, 0, (unsigned char *)psBootInfo, sizeof(sBootInfo_t)); // close the file sl_FsClose(fhandle, 0, 0, 0); } } // this one might modify the boot info hence it MUST be called after // bootmgr_verify! (so that the changes are not saved to flash) wait_for_safe_boot(psBootInfo); // select the active image again, since it might have changed switch (psBootInfo->ActiveImg) { case IMG_ACT_UPDATE1: image = (unsigned char *)IMG_UPDATE1; break; case IMG_ACT_UPDATE2: image = (unsigned char *)IMG_UPDATE2; break; default: image = (unsigned char *)IMG_FACTORY; break; } bootmgr_load_and_execute(image); } //***************************************************************************** //! Main function //***************************************************************************** int main (void) { sBootInfo_t sBootInfo = { .ActiveImg = IMG_ACT_FACTORY, .Status = IMG_STATUS_READY, .PrevImg = IMG_ACT_FACTORY }; bool bootapp = false; _i32 fhandle; // board setup bootmgr_board_init(); // start simplelink since we need it to access the sflash sl_Start(0, 0, 0); // if a boot info file is found, load it, else, create a new one with the default boot info if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) { if (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) { bootapp = true; } sl_FsClose(fhandle, 0, 0, 0); } // boot info file not present, it means that this is the first boot after being programmed if (!bootapp) { // create a new boot info file _u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ; if (!sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)), BootInfoCreateFlag), NULL, &fhandle)) { // write the default boot info. if (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) { bootapp = true; } sl_FsClose(fhandle, 0, 0, 0); } // signal the first boot to the application PRCMSetSpecialBit(PRCM_FIRST_BOOT_BIT); } if (bootapp) { // load and execute the image based on the boot info bootmgr_image_loader(&sBootInfo); } // stop simplelink sl_Stop(SL_STOP_TIMEOUT); // if we've reached this point, then it means that a fatal error has occurred and the // application could not be loaded, so, loop forever and signal the crash to the user while (true) { // keep the bld on MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN); __asm volatile(" dsb \n" " isb \n" " wfi \n"); } } //***************************************************************************** //! The following stub function is needed to link mp_vprintf //***************************************************************************** #include "py/qstr.h" const byte *qstr_data(qstr q, size_t *len) { *len = 0; return NULL; } micropython-1.12/ports/cc3200/bootmgr/relocator/000077500000000000000000000000001357706137100215265ustar00rootroot00000000000000micropython-1.12/ports/cc3200/bootmgr/relocator/relocator.bin000066400000000000000000000002701357706137100242110ustar00rootroot00000000000000@ @ hGpGOP4ObQ;@;RQ;@;Q;@;Q;@;OPA (FF FF pGF8FI &FFFFmicropython-1.12/ports/cc3200/bootmgr/runapp.s000066400000000000000000000005271357706137100212310ustar00rootroot00000000000000 .syntax unified .cpu cortex-m4 .thumb .text .align 2 @ void bootmgr_run_app(_u32 base) .global bootmgr_run_app .thumb .thumb_func .type bootmgr_run_app, %function bootmgr_run_app: @ set the SP ldr sp, [r0] add r0, r0, #4 @ jump to the entry code ldr r1, [r0] bx r1 micropython-1.12/ports/cc3200/bootmgr/sl/000077500000000000000000000000001357706137100201525ustar00rootroot00000000000000micropython-1.12/ports/cc3200/bootmgr/sl/user.h000066400000000000000000000716551357706137100213170ustar00rootroot00000000000000/* * user.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __USER_H__ #define __USER_H__ #ifdef __cplusplus extern "C" { #endif /*! ****************************************************************************** \defgroup porting_user_include Porting - User Include Files This section IS NOT REQUIRED in case user provided primitives are handled in makefiles or project configurations (IDE) PORTING ACTION: - Include all required header files for the definition of: -# Transport layer library API (e.g. SPI, UART) -# OS primitives definitions (e.g. Task spawn, Semaphores) -# Memory management primitives (e.g. alloc, free) ****************************************************************************** */ #include #include "cc_pal.h" /*! \def MAX_CONCURRENT_ACTIONS \brief Defines the maximum number of concurrent action in the system Min:1 , Max: 32 Actions which has async events as return, can be \sa \note In case there are not enough resources for the actions needed in the system, error is received: POOL_IS_EMPTY one option is to increase MAX_CONCURRENT_ACTIONS (improves performance but results in memory consumption) Other option is to call the API later (decrease performance) \warning In case of setting to one, recommend to use non-blocking recv\recvfrom to allow multiple socket recv */ #define MAX_CONCURRENT_ACTIONS 10 /*! \def CPU_FREQ_IN_MHZ \brief Defines CPU frequency for Host side, for better accuracy of busy loops, if any \sa \note \warning If not set the default CPU frequency is set to 200MHz This option will be deprecated in future release */ #define CPU_FREQ_IN_MHZ 80 /*! ****************************************************************************** \defgroup porting_capabilities Porting - Capabilities Set This section IS NOT REQUIRED in case one of the following pre defined capabilities set is in use: - SL_TINY - SL_SMALL - SL_FULL PORTING ACTION: - Define one of the pre-defined capabilities set or uncomment the relevant definitions below to select the required capabilities @{ ******************************************************************************* */ /*! \def SL_INC_ARG_CHECK \brief Defines whether the SimpleLink driver perform argument check or not When defined, the SimpleLink driver perform argument check on function call. Removing this define could reduce some code size and improve slightly the performances but may impact in unpredictable behavior in case of invalid arguments \sa \note belongs to \ref proting_sec \warning Removing argument check may cause unpredictable behavior in case of invalid arguments. In this case the user is responsible to argument validity (for example all handlers must not be NULL) */ #define SL_INC_ARG_CHECK /*! \def SL_INC_STD_BSD_API_NAMING \brief Defines whether SimpleLink driver should expose standard BSD APIs or not When defined, the SimpleLink driver in addtion to its alternative BSD APIs expose also standard BSD APIs. Stadrad BSD API includs the following functions: socket , close , accept , bind , listen , connect , select , setsockopt , getsockopt , recv , recvfrom , write , send , sendto , gethostbyname \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_STD_BSD_API_NAMING /*! \brief Defines whether to include extended API in SimpleLink driver or not When defined, the SimpleLink driver will include also all exteded API of the included packages \sa ext_api \note belongs to \ref porting_sec \warning */ #define SL_INC_EXT_API /*! \brief Defines whether to include WLAN package in SimpleLink driver or not When defined, the SimpleLink driver will include also the WLAN package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_WLAN_PKG /*! \brief Defines whether to include SOCKET package in SimpleLink driver or not When defined, the SimpleLink driver will include also the SOCKET package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_SOCKET_PKG /*! \brief Defines whether to include NET_APP package in SimpleLink driver or not When defined, the SimpleLink driver will include also the NET_APP package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_NET_APP_PKG /*! \brief Defines whether to include NET_CFG package in SimpleLink driver or not When defined, the SimpleLink driver will include also the NET_CFG package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_NET_CFG_PKG /*! \brief Defines whether to include NVMEM package in SimpleLink driver or not When defined, the SimpleLink driver will include also the NVMEM package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_NVMEM_PKG /*! \brief Defines whether to include socket server side APIs in SimpleLink driver or not When defined, the SimpleLink driver will include also socket server side APIs \sa server_side \note \warning */ #define SL_INC_SOCK_SERVER_SIDE_API /*! \brief Defines whether to include socket client side APIs in SimpleLink driver or not When defined, the SimpleLink driver will include also socket client side APIs \sa client_side \note belongs to \ref porting_sec \warning */ #define SL_INC_SOCK_CLIENT_SIDE_API /*! \brief Defines whether to include socket receive APIs in SimpleLink driver or not When defined, the SimpleLink driver will include also socket receive side APIs \sa recv_api \note belongs to \ref porting_sec \warning */ #define SL_INC_SOCK_RECV_API /*! \brief Defines whether to include socket send APIs in SimpleLink driver or not When defined, the SimpleLink driver will include also socket send side APIs \sa send_api \note belongs to \ref porting_sec \warning */ #define SL_INC_SOCK_SEND_API /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup ported_enable_device Ported on CC32XX - Device Enable/Disable The enable/disable API provide mechanism to enable/disable the network processor PORTING ACTION: - None @{ ****************************************************************************** */ /*! \brief Preamble to the enabling the Network Processor. Placeholder to implement any pre-process operations before enabling networking operations. \sa sl_DeviceEnable \note belongs to \ref ported_sec */ #ifdef DEBUG #define sl_DeviceEnablePreamble() NwpPowerOnPreamble() #else #define sl_DeviceEnablePreamble() #endif /*! \brief Enable the Network Processor \sa sl_DeviceDisable \note belongs to \ref ported_sec */ #define sl_DeviceEnable() NwpPowerOn() /*! \brief Disable the Network Processor \sa sl_DeviceEnable \note belongs to \ref ported_sec */ #define sl_DeviceDisable() NwpPowerOff() /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup ported_interface Ported on CC32XX - Communication Interface The simple link device can work with different communication channels (e.g. spi/uart). Texas Instruments provides single driver that can work with all these types. This section bind between the physical communication interface channel and the SimpleLink driver \note Correct and efficient implementation of this driver is critical for the performances of the SimpleLink device on this platform. PORTING ACTION: - None @{ ****************************************************************************** */ #define _SlFd_t Fd_t /*! \brief Opens an interface communication port to be used for communicating with a SimpleLink device Given an interface name and option flags, this function opens the communication port and creates a file descriptor. This file descriptor is used afterwards to read and write data from and to this specific communication channel. The speed, clock polarity, clock phase, chip select and all other specific attributes of the channel are all should be set to hardcoded in this function. \param ifName - points to the interface name/path. The interface name is an optional attributes that the simple link driver receives on opening the driver (sl_Start). In systems that the spi channel is not implemented as part of the os device drivers, this parameter could be NULL. \param flags - optional flags parameters for future use \return upon successful completion, the function shall open the channel and return a non-negative integer representing the file descriptor. Otherwise, -1 shall be returned \sa sl_IfClose , sl_IfRead , sl_IfWrite \note The prototype of the function is as follow: Fd_t xxx_IfOpen(char* pIfName , unsigned long flags); \note belongs to \ref ported_sec \warning */ #define sl_IfOpen spi_Open /*! \brief Closes an opened interface communication port \param fd - file descriptor of opened communication channel \return upon successful completion, the function shall return 0. Otherwise, -1 shall be returned \sa sl_IfOpen , sl_IfRead , sl_IfWrite \note The prototype of the function is as follow: int xxx_IfClose(Fd_t Fd); \note belongs to \ref ported_sec \warning */ #define sl_IfClose spi_Close /*! \brief Attempts to read up to len bytes from an opened communication channel into a buffer starting at pBuff. \param fd - file descriptor of an opened communication channel \param pBuff - pointer to the first location of a buffer that contains enough space for all expected data \param len - number of bytes to read from the communication channel \return upon successful completion, the function shall return the number of read bytes. Otherwise, 0 shall be returned \sa sl_IfClose , sl_IfOpen , sl_IfWrite \note The prototype of the function is as follow: int xxx_IfRead(Fd_t Fd , char* pBuff , int Len); \note belongs to \ref ported_sec \warning */ #define sl_IfRead spi_Read /*! \brief attempts to write up to len bytes to the SPI channel \param fd - file descriptor of an opened communication channel \param pBuff - pointer to the first location of a buffer that contains the data to send over the communication channel \param len - number of bytes to write to the communication channel \return upon successful completion, the function shall return the number of sent bytes. therwise, 0 shall be returned \sa sl_IfClose , sl_IfOpen , sl_IfRead \note This function could be implemented as zero copy and return only upon successful completion of writing the whole buffer, but in cases that memory allocation is not too tight, the function could copy the data to internal buffer, return back and complete the write in parallel to other activities as long as the other SPI activities would be blocked until the entire buffer write would be completed The prototype of the function is as follow: int xxx_IfWrite(Fd_t Fd , char* pBuff , int Len); \note belongs to \ref ported_sec \warning */ #define sl_IfWrite spi_Write /*! \brief register an interrupt handler routine for the host IRQ \param InterruptHdl - pointer to interrupt handler routine \param pValue - pointer to a memory structure that is passed to the interrupt handler. \return upon successful registration, the function shall return 0. Otherwise, -1 shall be returned \sa \note If there is already registered interrupt handler, the function should overwrite the old handler with the new one \note If the handler is a null pointer, the function should un-register the interrupt handler, and the interrupts can be disabled. \note belongs to \ref ported_sec \warning */ #define sl_IfRegIntHdlr(InterruptHdl , pValue) NwpRegisterInterruptHandler(InterruptHdl , pValue) /*! \brief Masks the Host IRQ \sa sl_IfUnMaskIntHdlr \note belongs to \ref ported_sec \warning */ #define sl_IfMaskIntHdlr() NwpMaskInterrupt() /*! \brief Unmasks the Host IRQ \sa sl_IfMaskIntHdlr \note belongs to \ref ported_sec \warning */ #define sl_IfUnMaskIntHdlr() NwpUnMaskInterrupt() /*! \brief Write Handers for statistics debug on write \param interface handler - pointer to interrupt handler routine \return no return value \sa \note An optional hooks for monitoring before and after write info \note belongs to \ref ported_sec \warning */ /* #define SL_START_WRITE_STAT */ /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup ported_os Ported on CC32XX - Operating System The simple link driver can run on multi-threaded environment as well as non-os environment (mail loop) This section IS NOT REQUIRED in case you are working on non-os environment. If you choose to work in multi-threaded environment under any operating system you will have to provide some basic adaptation routines to allow the driver to protect access to resources from different threads (locking object) and to allow synchronization between threads (sync objects). PORTING ACTION: -# Uncomment SL_PLATFORM_MULTI_THREADED define -# Bind locking object routines -# Bind synchronization object routines -# Optional - Bind spawn thread routine @{ ****************************************************************************** */ /* #define SL_PLATFORM_MULTI_THREADED */ #ifdef SL_PLATFORM_MULTI_THREADED #include "osi.h" /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define SL_OS_RET_CODE_OK ((int)OSI_OK) /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define SL_OS_WAIT_FOREVER ((OsiTime_t)OSI_WAIT_FOREVER) /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define SL_OS_NO_WAIT ((OsiTime_t)OSI_NO_WAIT) /*! \brief type definition for a time value \note On each porting or platform the type could be whatever is needed - integer, pointer to structure etc. \note belongs to \ref ported_sec */ #define _SlTime_t OsiTime_t /*! \brief type definition for a sync object container Sync object is object used to synchronize between two threads or thread and interrupt handler. One thread is waiting on the object and the other thread send a signal, which then release the waiting thread. The signal must be able to be sent from interrupt context. This object is generally implemented by binary semaphore or events. \note On each porting or platform the type could be whatever is needed - integer, structure etc. \note belongs to \ref ported_sec */ typedef OsiSyncObj_t _SlSyncObj_t; /*! \brief This function creates a sync object The sync object is used for synchronization between diffrent thread or ISR and a thread. \param pSyncObj - pointer to the sync object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_SyncObjCreate(pSyncObj,pName) osi_SyncObjCreate(pSyncObj) /*! \brief This function deletes a sync object \param pSyncObj - pointer to the sync object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_SyncObjDelete(pSyncObj) osi_SyncObjDelete(pSyncObj) /*! \brief This function generates a sync signal for the object. All suspended threads waiting on this sync object are resumed \param pSyncObj - pointer to the sync object control block \return upon successful signaling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function could be called from ISR context \warning */ #define sl_SyncObjSignal(pSyncObj) osi_SyncObjSignal(pSyncObj) /*! \brief This function generates a sync signal for the object from Interrupt This is for RTOS that should signal from IRQ using a dedicated API \param pSyncObj - pointer to the sync object control block \return upon successful signaling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function could be called from ISR context \warning */ #define sl_SyncObjSignalFromIRQ(pSyncObj) osi_SyncObjSignalFromISR(pSyncObj) /*! \brief This function waits for a sync signal of the specific sync object \param pSyncObj - pointer to the sync object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the sync signal Currently, the simple link driver uses only two values: - OSI_WAIT_FOREVER - OSI_NO_WAIT \return upon successful reception of the signal within the timeout window return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_SyncObjWait(pSyncObj,Timeout) osi_SyncObjWait(pSyncObj,Timeout) /*! \brief type definition for a locking object container Locking object are used to protect a resource from mutual accesses of two or more threads. The locking object should suppurt reentrant locks by a signal thread. This object is generally implemented by mutex semaphore \note On each porting or platform the type could be whatever is needed - integer, structure etc. \note belongs to \ref ported_sec */ typedef OsiLockObj_t _SlLockObj_t; /*! \brief This function creates a locking object. The locking object is used for protecting a shared resources between different threads. \param pLockObj - pointer to the locking object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_LockObjCreate(pLockObj,pName) osi_LockObjCreate(pLockObj) /*! \brief This function deletes a locking object. \param pLockObj - pointer to the locking object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_LockObjDelete(pLockObj) osi_LockObjDelete(pLockObj) /*! \brief This function locks a locking object. All other threads that call this function before this thread calls the osi_LockObjUnlock would be suspended \param pLockObj - pointer to the locking object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the locking object Currently, the simple link driver uses only two values: - OSI_WAIT_FOREVER - OSI_NO_WAIT \return upon successful reception of the locking object the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_LockObjLock(pLockObj,Timeout) osi_LockObjLock(pLockObj,Timeout) /*! \brief This function unlock a locking object. \param pLockObj - pointer to the locking object control block \return upon successful unlocking the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_LockObjUnlock(pLockObj) osi_LockObjUnlock(pLockObj) #endif /*! \brief This function call the pEntry callback from a different context \param pEntry - pointer to the entry callback function \param pValue - pointer to any type of memory structure that would be passed to pEntry callback from the execution thread. \param flags - execution flags - reserved for future usage \return upon successful registration of the spawn the function should return 0 (the function is not blocked till the end of the execution of the function and could be returned before the execution is actually completed) Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ //#define SL_PLATFORM_EXTERNAL_SPAWN #ifdef SL_PLATFORM_EXTERNAL_SPAWN #define sl_Spawn(pEntry,pValue,flags) osi_Spawn(pEntry,pValue,flags) #endif /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup porting_mem_mgm Porting - Memory Management This section declare in which memory management model the SimpleLink driver will run: -# Static -# Dynamic This section IS NOT REQUIRED in case Static model is selected. The default memory model is Static PORTING ACTION: - If dynamic model is selected, define the alloc and free functions. @{ ***************************************************************************** */ /*! \brief Defines whether the SimpleLink driver is working in dynamic memory model or not When defined, the SimpleLink driver use dynamic allocations if dynamic allocation is selected malloc and free functions must be retrieved \sa \note belongs to \ref porting_sec \warning */ #define SL_MEMORY_MGMT_DYNAMIC 1 #define SL_MEMORY_MGMT_STATIC 0 #define SL_MEMORY_MGMT SL_MEMORY_MGMT_STATIC #ifdef SL_MEMORY_MGMT_DYNAMIC #ifdef SL_PLATFORM_MULTI_THREADED /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define sl_Malloc(Size) mem_Malloc(Size) /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define sl_Free(pMem) mem_Free(pMem) #else #include /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define sl_Malloc(Size) malloc(Size) /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define sl_Free(pMem) free(pMem) #endif #endif /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup porting_events Porting - Event Handlers This section includes the asynchronous event handlers routines PORTING ACTION: -Uncomment the required handler and define your routine as the value of this handler @{ ****************************************************************************** */ /*! \brief \sa \note belongs to \ref porting_sec \warning */ #define sl_GeneralEvtHdlr SimpleLinkGeneralEventHandler /*! \brief An event handler for WLAN connection or disconnection indication This event handles async WLAN events. Possible events are: SL_WLAN_CONNECT_EVENT - indicates WLAN is connected SL_WLAN_DISCONNECT_EVENT - indicates WLAN is disconnected \sa \note belongs to \ref porting_sec \warning */ #define sl_WlanEvtHdlr SimpleLinkWlanEventHandler /*! \brief An event handler for IP address asynchronous event. Usually accepted after new WLAN connection. This event handles networking events. Possible events are: SL_NETAPP_IPV4_ACQUIRED - IP address was acquired (DHCP or Static) \sa \note belongs to \ref porting_sec \warning */ #define sl_NetAppEvtHdlr SimpleLinkNetAppEventHandler /*! \brief A callback for HTTP server events. Possible events are: SL_NETAPP_HTTPGETTOKENVALUE - NWP requests to get the value of a specific token SL_NETAPP_HTTPPOSTTOKENVALUE - NWP post to the host a new value for a specific token \param pServerEvent - Contains the relevant event information (SL_NETAPP_HTTPGETTOKENVALUE or SL_NETAPP_HTTPPOSTTOKENVALUE) \param pServerResponse - Should be filled by the user with the relevant response information (i.e SL_NETAPP_HTTPSETTOKENVALUE as a response to SL_NETAPP_HTTPGETTOKENVALUE event) \sa \note belongs to \ref porting_sec \warning */ #define sl_HttpServerCallback SimpleLinkHttpServerCallback /*! \brief \sa \note belongs to \ref porting_sec \warning */ #define sl_SockEvtHdlr SimpleLinkSockEventHandler #define _SL_USER_TYPES #define _u8 unsigned char #define _i8 signed char #define _u16 unsigned short #define _i16 signed short #define _u32 unsigned int #define _i32 signed int #define _volatile volatile #define _const const /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif // __cplusplus #endif // __USER_H__ micropython-1.12/ports/cc3200/fatfs/000077500000000000000000000000001357706137100171665ustar00rootroot00000000000000micropython-1.12/ports/cc3200/fatfs/src/000077500000000000000000000000001357706137100177555ustar00rootroot00000000000000micropython-1.12/ports/cc3200/fatfs/src/drivers/000077500000000000000000000000001357706137100214335ustar00rootroot00000000000000micropython-1.12/ports/cc3200/fatfs/src/drivers/sd_diskio.c000066400000000000000000000350541357706137100235560ustar00rootroot00000000000000//***************************************************************************** // sd_diskio.c // // Low level SD Card access hookup for FatFS // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #include #include "py/mpconfig.h" #include "py/mphal.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "hw_types.h" #include "hw_memmap.h" #include "hw_ints.h" #include "rom_map.h" #include "sd_diskio.h" #include "sdhost.h" #include "pin.h" #include "prcm.h" #include "stdcmd.h" #include "utils.h" //***************************************************************************** // Macros //***************************************************************************** #define DISKIO_RETRY_TIMEOUT 0xFFFFFFFF #define CARD_TYPE_UNKNOWN 0 #define CARD_TYPE_MMC 1 #define CARD_TYPE_SDCARD 2 #define CARD_CAP_CLASS_SDSC 0 #define CARD_CAP_CLASS_SDHC 1 #define CARD_VERSION_1 0 #define CARD_VERSION_2 1 //***************************************************************************** // Disk Info for attached disk //***************************************************************************** DiskInfo_t sd_disk_info = {CARD_TYPE_UNKNOWN, CARD_VERSION_1, CARD_CAP_CLASS_SDSC, 0, 0, STA_NOINIT, 0}; //***************************************************************************** // //! Send Command to card //! //! \param ulCmd is the command to be send //! \paran ulArg is the command argument //! //! This function sends command to attached card and check the response status //! if any. //! //! \return Returns 0 on success, 1 otherwise // //***************************************************************************** static unsigned int CardSendCmd (unsigned int ulCmd, unsigned int ulArg) { unsigned long ulStatus; // Clear the interrupt status MAP_SDHostIntClear(SDHOST_BASE,0xFFFFFFFF); // Send command MAP_SDHostCmdSend(SDHOST_BASE,ulCmd,ulArg); // Wait for command complete or error do { ulStatus = MAP_SDHostIntStatus(SDHOST_BASE); ulStatus = (ulStatus & (SDHOST_INT_CC | SDHOST_INT_ERRI)); } while (!ulStatus); // Check error status if (ulStatus & SDHOST_INT_ERRI) { // Reset the command line MAP_SDHostCmdReset(SDHOST_BASE); return 1; } else { return 0; } } //***************************************************************************** // //! Get the capacity of specified card //! //! \param ulRCA is the Relative Card Address (RCA) //! //! This function gets the capacity of card addressed by \e ulRCA paramaeter. //! //! \return Returns 0 on success, 1 otherwise. // //***************************************************************************** static unsigned int CardCapacityGet(DiskInfo_t *psDiskInfo) { unsigned long ulRet; unsigned long ulResp[4]; unsigned long ulBlockSize; unsigned long ulBlockCount; unsigned long ulCSizeMult; unsigned long ulCSize; // Read the CSD register ulRet = CardSendCmd(CMD_SEND_CSD, (psDiskInfo->usRCA << 16)); if(ulRet == 0) { // Read the response MAP_SDHostRespGet(SDHOST_BASE,ulResp); // 136 bit CSD register is read into an array of 4 words. // ulResp[0] = CSD[31:0] // ulResp[1] = CSD[63:32] // ulResp[2] = CSD[95:64] // ulResp[3] = CSD[127:96] if(ulResp[3] >> 30) { ulBlockSize = SD_SECTOR_SIZE * 1024; ulBlockCount = (ulResp[1] >> 16 | ((ulResp[2] & 0x3F) << 16)) + 1; } else { ulBlockSize = 1 << ((ulResp[2] >> 16) & 0xF); ulCSizeMult = ((ulResp[1] >> 15) & 0x7); ulCSize = ((ulResp[1] >> 30) | (ulResp[2] & 0x3FF) << 2); ulBlockCount = (ulCSize + 1) * (1 << (ulCSizeMult + 2)); } // Calculate the card capacity in bytes psDiskInfo->ulBlockSize = ulBlockSize; psDiskInfo->ulNofBlock = ulBlockCount; } return ulRet; } //***************************************************************************** // //! Select a card for reading or writing //! //! \param Card is the pointer to card attribute structure. //! //! This function selects a card for reading or writing using its RCA from //! \e Card parameter. //! //! \return Returns 0 success, 1 otherwise. // //***************************************************************************** static unsigned int CardSelect (DiskInfo_t *sDiskInfo) { unsigned long ulRCA; unsigned long ulRet; ulRCA = sDiskInfo->usRCA; // Send select command with card's RCA. ulRet = CardSendCmd(CMD_SELECT_CARD, (ulRCA << 16)); if (ulRet == 0) { while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC)); } // Delay 250ms for the card to become ready mp_hal_delay_ms(250); return ulRet; } //***************************************************************************** // //! Initializes physical drive //! //! This function initializes the physical drive //! //! \return Returns 0 on succeeded. //***************************************************************************** DSTATUS sd_disk_init (void) { unsigned long ulRet; unsigned long ulResp[4]; if (sd_disk_info.bStatus != 0) { sd_disk_info.bStatus = STA_NODISK; // Send std GO IDLE command if (CardSendCmd(CMD_GO_IDLE_STATE, 0) == 0) { // Get interface operating condition for the card ulRet = CardSendCmd(CMD_SEND_IF_COND,0x000001A5); MAP_SDHostRespGet(SDHOST_BASE,ulResp); // It's a SD ver 2.0 or higher card if (ulRet == 0 && ((ulResp[0] & 0xFF) == 0xA5)) { // Version 1 card do not respond to this command sd_disk_info.ulVersion = CARD_VERSION_2; sd_disk_info.ucCardType = CARD_TYPE_SDCARD; // Wait for card to become ready. do { // Send ACMD41 CardSendCmd(CMD_APP_CMD, 0); ulRet = CardSendCmd(CMD_SD_SEND_OP_COND, 0x40E00000); // Response contains 32-bit OCR register MAP_SDHostRespGet(SDHOST_BASE, ulResp); } while (((ulResp[0] >> 31) == 0)); if (ulResp[0] & (1UL<<30)) { sd_disk_info.ulCapClass = CARD_CAP_CLASS_SDHC; } sd_disk_info.bStatus = 0; } //It's a MMC or SD 1.x card else { // Wait for card to become ready. do { CardSendCmd(CMD_APP_CMD, 0); ulRet = CardSendCmd(CMD_SD_SEND_OP_COND,0x00E00000); if (ulRet == 0) { // Response contains 32-bit OCR register MAP_SDHostRespGet(SDHOST_BASE, ulResp); } } while (((ulRet == 0) && (ulResp[0] >> 31) == 0)); if (ulRet == 0) { sd_disk_info.ucCardType = CARD_TYPE_SDCARD; sd_disk_info.bStatus = 0; } else { if (CardSendCmd(CMD_SEND_OP_COND, 0) == 0) { // MMC not supported by the controller sd_disk_info.ucCardType = CARD_TYPE_MMC; } } } } // Get the RCA of the attached card if (sd_disk_info.bStatus == 0) { ulRet = CardSendCmd(CMD_ALL_SEND_CID, 0); if (ulRet == 0) { CardSendCmd(CMD_SEND_REL_ADDR,0); MAP_SDHostRespGet(SDHOST_BASE, ulResp); // Fill in the RCA sd_disk_info.usRCA = (ulResp[0] >> 16); // Get tha card capacity CardCapacityGet(&sd_disk_info); } // Select the card. ulRet = CardSelect(&sd_disk_info); if (ulRet == 0) { sd_disk_info.bStatus = 0; } } } return sd_disk_info.bStatus; } //***************************************************************************** // //! De-initializes the physical drive //! //! This function de-initializes the physical drive //***************************************************************************** void sd_disk_deinit (void) { sd_disk_info.ucCardType = CARD_TYPE_UNKNOWN; sd_disk_info.ulVersion = CARD_VERSION_1; sd_disk_info.ulCapClass = CARD_CAP_CLASS_SDSC; sd_disk_info.ulNofBlock = 0; sd_disk_info.ulBlockSize = 0; sd_disk_info.bStatus = STA_NOINIT; sd_disk_info.usRCA = 0; } //***************************************************************************** // //! Reads sector(s) from the disk drive. //! //! //! This function reads specified number of sectors from the drive //! //! \return Returns RES_OK on success. // //***************************************************************************** DRESULT sd_disk_read (BYTE* pBuffer, DWORD ulSectorNumber, UINT SectorCount) { DRESULT Res = RES_ERROR; unsigned long ulSize; if (SectorCount > 0) { // Return if disk not initialized if (sd_disk_info.bStatus & STA_NOINIT) { return RES_NOTRDY; } // SDSC uses linear address, SDHC uses block address if (sd_disk_info.ulCapClass == CARD_CAP_CLASS_SDSC) { ulSectorNumber = ulSectorNumber * SD_SECTOR_SIZE; } // Set the block count MAP_SDHostBlockCountSet(SDHOST_BASE, SectorCount); // Compute the number of words ulSize = (SD_SECTOR_SIZE * SectorCount) / 4; // Check if 1 block or multi block transfer if (SectorCount == 1) { // Send single block read command if (CardSendCmd(CMD_READ_SINGLE_BLK, ulSectorNumber) == 0) { // Read the block of data while (ulSize--) { MAP_SDHostDataRead(SDHOST_BASE, (unsigned long *)pBuffer); pBuffer += 4; } Res = RES_OK; } } else { // Send multi block read command if (CardSendCmd(CMD_READ_MULTI_BLK, ulSectorNumber) == 0) { // Read the data while (ulSize--) { MAP_SDHostDataRead(SDHOST_BASE, (unsigned long *)pBuffer); pBuffer += 4; } CardSendCmd(CMD_STOP_TRANS, 0); while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC)); Res = RES_OK; } } } return Res; } //***************************************************************************** // //! Wrties sector(s) to the disk drive. //! //! //! This function writes specified number of sectors to the drive //! //! \return Returns RES_OK on success. // //***************************************************************************** DRESULT sd_disk_write (const BYTE* pBuffer, DWORD ulSectorNumber, UINT SectorCount) { DRESULT Res = RES_ERROR; unsigned long ulSize; if (SectorCount > 0) { // Return if disk not initialized if (sd_disk_info.bStatus & STA_NOINIT) { return RES_NOTRDY; } // SDSC uses linear address, SDHC uses block address if (sd_disk_info.ulCapClass == CARD_CAP_CLASS_SDSC) { ulSectorNumber = ulSectorNumber * SD_SECTOR_SIZE; } // Set the block count MAP_SDHostBlockCountSet(SDHOST_BASE, SectorCount); // Compute the number of words ulSize = (SD_SECTOR_SIZE * SectorCount) / 4; // Check if 1 block or multi block transfer if (SectorCount == 1) { // Send single block write command if (CardSendCmd(CMD_WRITE_SINGLE_BLK, ulSectorNumber) == 0) { // Write the data while (ulSize--) { MAP_SDHostDataWrite (SDHOST_BASE, (*(unsigned long *)pBuffer)); pBuffer += 4; } // Wait for data transfer complete while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC)); Res = RES_OK; } } else { // Set the card write block count if (sd_disk_info.ucCardType == CARD_TYPE_SDCARD) { CardSendCmd(CMD_APP_CMD,sd_disk_info.usRCA << 16); CardSendCmd(CMD_SET_BLK_CNT, SectorCount); } // Send multi block write command if (CardSendCmd(CMD_WRITE_MULTI_BLK, ulSectorNumber) == 0) { // Write the data buffer while (ulSize--) { MAP_SDHostDataWrite(SDHOST_BASE, (*(unsigned long *)pBuffer)); pBuffer += 4; } // Wait for transfer complete while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC)); CardSendCmd(CMD_STOP_TRANS, 0); while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC)); Res = RES_OK; } } } return Res; } micropython-1.12/ports/cc3200/fatfs/src/drivers/sd_diskio.h000066400000000000000000000014161357706137100235560ustar00rootroot00000000000000#ifndef SD_DISKIO_H_ #define SD_DISKIO_H_ #define SD_SECTOR_SIZE 512 //***************************************************************************** // Disk Info Structure definition //***************************************************************************** typedef struct { unsigned char ucCardType; unsigned int ulVersion; unsigned int ulCapClass; unsigned int ulNofBlock; unsigned int ulBlockSize; DSTATUS bStatus; unsigned short usRCA; }DiskInfo_t; extern DiskInfo_t sd_disk_info; DSTATUS sd_disk_init (void); void sd_disk_deinit (void); DRESULT sd_disk_read (BYTE* pBuffer, DWORD ulSectorNumber, UINT bSectorCount); DRESULT sd_disk_write (const BYTE* pBuffer, DWORD ulSectorNumber, UINT bSectorCount); #endif /* SD_DISKIO_H_ */ micropython-1.12/ports/cc3200/fatfs/src/drivers/sflash_diskio.c000066400000000000000000000133651357706137100244310ustar00rootroot00000000000000#include #include #include #include "py/mpconfig.h" #include "py/obj.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "simplelink.h" #include "sflash_diskio.h" #include "debug.h" #include "modnetwork.h" #include "modwlan.h" #define SFLASH_TIMEOUT_MAX_MS 5500 #define SFLASH_WAIT_TIME_MS 5 static _u8 sflash_block_name[] = "__NNN__.fsb"; static _u8 *sflash_block_cache; static bool sflash_init_done = false; static bool sflash_cache_is_dirty; static uint32_t sflash_ublock; static uint32_t sflash_prblock; static void print_block_name (_u32 ublock) { char _sblock[4]; snprintf (_sblock, sizeof(_sblock), "%03u", ublock); memcpy (&sflash_block_name[2], _sblock, 3); } static bool sflash_access (_u32 mode, _i32 (* sl_FsFunction)(_i32 FileHdl, _u32 Offset, _u8* pData, _u32 Len)) { _i32 fileHandle; bool retval = false; // wlan must be enabled in order to access the serial flash sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); if (0 == sl_FsOpen(sflash_block_name, mode, NULL, &fileHandle)) { if (SFLASH_BLOCK_SIZE == sl_FsFunction (fileHandle, 0, sflash_block_cache, SFLASH_BLOCK_SIZE)) { retval = true; } sl_FsClose (fileHandle, NULL, NULL, 0); } sl_LockObjUnlock (&wlan_LockObj); return retval; } DRESULT sflash_disk_init (void) { _i32 fileHandle; SlFsFileInfo_t FsFileInfo; if (!sflash_init_done) { // Allocate space for the block cache ASSERT ((sflash_block_cache = mem_Malloc(SFLASH_BLOCK_SIZE)) != NULL); sflash_init_done = true; sflash_prblock = UINT32_MAX; sflash_cache_is_dirty = false; // In order too speed up booting, check the last block, if exists, then // it means that the file system has been already created print_block_name (SFLASH_BLOCK_COUNT - 1); sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); if (!sl_FsGetInfo(sflash_block_name, 0, &FsFileInfo)) { sl_LockObjUnlock (&wlan_LockObj); return RES_OK; } sl_LockObjUnlock (&wlan_LockObj); // Proceed to format the memory for (int i = 0; i < SFLASH_BLOCK_COUNT; i++) { print_block_name (i); sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); // Create the block file if it doesn't exist if (sl_FsGetInfo(sflash_block_name, 0, &FsFileInfo) != 0) { if (!sl_FsOpen(sflash_block_name, FS_MODE_OPEN_CREATE(SFLASH_BLOCK_SIZE, 0), NULL, &fileHandle)) { sl_FsClose(fileHandle, NULL, NULL, 0); sl_LockObjUnlock (&wlan_LockObj); memset(sflash_block_cache, 0xFF, SFLASH_BLOCK_SIZE); if (!sflash_access(FS_MODE_OPEN_WRITE, sl_FsWrite)) { return RES_ERROR; } } else { // Unexpected failure while creating the file sl_LockObjUnlock (&wlan_LockObj); return RES_ERROR; } } sl_LockObjUnlock (&wlan_LockObj); } } return RES_OK; } DRESULT sflash_disk_status(void) { if (!sflash_init_done) { return STA_NOINIT; } return RES_OK; } DRESULT sflash_disk_read(BYTE *buff, DWORD sector, UINT count) { uint32_t secindex; if (!sflash_init_done) { return STA_NOINIT; } if ((sector + count > SFLASH_SECTOR_COUNT) || (count == 0)) { return RES_PARERR; } for (int i = 0; i < count; i++) { secindex = (sector + i) % SFLASH_SECTORS_PER_BLOCK; sflash_ublock = (sector + i) / SFLASH_SECTORS_PER_BLOCK; // See if it's time to read a new block if (sflash_prblock != sflash_ublock) { if (sflash_disk_flush() != RES_OK) { return RES_ERROR; } sflash_prblock = sflash_ublock; print_block_name (sflash_ublock); if (!sflash_access(FS_MODE_OPEN_READ, sl_FsRead)) { return RES_ERROR; } } // Copy the requested sector from the block cache memcpy (buff, &sflash_block_cache[(secindex * SFLASH_SECTOR_SIZE)], SFLASH_SECTOR_SIZE); buff += SFLASH_SECTOR_SIZE; } return RES_OK; } DRESULT sflash_disk_write(const BYTE *buff, DWORD sector, UINT count) { uint32_t secindex; int32_t index = 0; if (!sflash_init_done) { return STA_NOINIT; } if ((sector + count > SFLASH_SECTOR_COUNT) || (count == 0)) { sflash_disk_flush(); return RES_PARERR; } do { secindex = (sector + index) % SFLASH_SECTORS_PER_BLOCK; sflash_ublock = (sector + index) / SFLASH_SECTORS_PER_BLOCK; // Check if it's a different block than last time if (sflash_prblock != sflash_ublock) { if (sflash_disk_flush() != RES_OK) { return RES_ERROR; } sflash_prblock = sflash_ublock; print_block_name (sflash_ublock); // Read the block into the cache if (!sflash_access(FS_MODE_OPEN_READ, sl_FsRead)) { return RES_ERROR; } } // Copy the input sector to the block cache memcpy (&sflash_block_cache[(secindex * SFLASH_SECTOR_SIZE)], buff, SFLASH_SECTOR_SIZE); buff += SFLASH_SECTOR_SIZE; sflash_cache_is_dirty = true; } while (++index < count); return RES_OK; } DRESULT sflash_disk_flush (void) { // Write back the cache if it's dirty if (sflash_cache_is_dirty) { if (!sflash_access(FS_MODE_OPEN_WRITE, sl_FsWrite)) { return RES_ERROR; } sflash_cache_is_dirty = false; } return RES_OK; } micropython-1.12/ports/cc3200/fatfs/src/drivers/sflash_diskio.h000066400000000000000000000012031357706137100244220ustar00rootroot00000000000000#ifndef SFLASH_DISKIO_H_ #define SFLASH_DISKIO_H_ #define SFLASH_BLOCK_SIZE 2048 #define SFLASH_BLOCK_COUNT MICROPY_PORT_SFLASH_BLOCK_COUNT #define SFLASH_SECTOR_SIZE 512 #define SFLASH_SECTOR_COUNT ((SFLASH_BLOCK_SIZE * SFLASH_BLOCK_COUNT) / SFLASH_SECTOR_SIZE) #define SFLASH_SECTORS_PER_BLOCK (SFLASH_BLOCK_SIZE / SFLASH_SECTOR_SIZE) DRESULT sflash_disk_init(void); DRESULT sflash_disk_status(void); DRESULT sflash_disk_read(BYTE *buff, DWORD sector, UINT count); DRESULT sflash_disk_write(const BYTE *buff, DWORD sector, UINT count); DRESULT sflash_disk_flush(void); #endif /* SFLASH_DISKIO_H_ */ micropython-1.12/ports/cc3200/fatfs/src/drivers/stdcmd.h000066400000000000000000000062171357706137100230700ustar00rootroot00000000000000//***************************************************************************** // stdcmd.h // // Defines standard SD Card commands for CC3200 SDHOST module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __STDCMD_H__ #define __STDCMD_H__ //***************************************************************************** // Standard MMC/SD Card Commands //***************************************************************************** #define CMD_GO_IDLE_STATE SDHOST_CMD_0 #define CMD_SEND_IF_COND SDHOST_CMD_8|SDHOST_RESP_LEN_48 #define CMD_SEND_CSD SDHOST_CMD_9|SDHOST_RESP_LEN_136 #define CMD_APP_CMD SDHOST_CMD_55|SDHOST_RESP_LEN_48 #define CMD_SD_SEND_OP_COND SDHOST_CMD_41|SDHOST_RESP_LEN_48 #define CMD_SEND_OP_COND SDHOST_CMD_1|SDHOST_RESP_LEN_48 #define CMD_READ_SINGLE_BLK SDHOST_CMD_17|SDHOST_RD_CMD|SDHOST_RESP_LEN_48 #define CMD_READ_MULTI_BLK SDHOST_CMD_18|SDHOST_RD_CMD|SDHOST_RESP_LEN_48|SDHOST_MULTI_BLK #define CMD_WRITE_SINGLE_BLK SDHOST_CMD_24|SDHOST_WR_CMD|SDHOST_RESP_LEN_48 #define CMD_WRITE_MULTI_BLK SDHOST_CMD_25|SDHOST_WR_CMD|SDHOST_RESP_LEN_48|SDHOST_MULTI_BLK #define CMD_SELECT_CARD SDHOST_CMD_7|SDHOST_RESP_LEN_48B #define CMD_DESELECT_CARD SDHOST_CMD_7 #define CMD_STOP_TRANS SDHOST_CMD_12|SDHOST_RESP_LEN_48B #define CMD_SET_BLK_CNT SDHOST_CMD_23|SDHOST_RESP_LEN_48 #define CMD_ALL_SEND_CID SDHOST_CMD_2|SDHOST_RESP_LEN_136 #define CMD_SEND_REL_ADDR SDHOST_CMD_3|SDHOST_RESP_LEN_48 #endif //__STDCMD_H__ micropython-1.12/ports/cc3200/fatfs_port.c000066400000000000000000000055371357706137100204100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * Parts of this file are (C)ChaN, 2014, from FatFs option/syscall.c * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "lib/timeutils/timeutils.h" #include "mods/pybrtc.h" #if FF_FS_REENTRANT // Create a Synchronization Object // This function is called in f_mount() function to create a new // synchronization object, such as semaphore and mutex. // A return of 0 indicates failure, and then f_mount() fails with FR_INT_ERR. int ff_cre_syncobj(FATFS *fatfs, FF_SYNC_t *sobj) { vSemaphoreCreateBinary((*sobj)); return (int)(*sobj != NULL); } // Delete a Synchronization Object // This function is called in f_mount() function to delete a synchronization // object that created with ff_cre_syncobj function. // A return of 0 indicates failure, and then f_mount() fails with FR_INT_ERR. int ff_del_syncobj(FF_SYNC_t sobj) { vSemaphoreDelete(sobj); return 1; } // Request Grant to Access the Volume // This function is called on entering file functions to lock the volume. // When a 0 is returned, the file function fails with FR_TIMEOUT. int ff_req_grant(FF_SYNC_t sobj) { return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); } // Release Grant to Access the Volume // This function is called on leaving file functions to unlock the volume. void ff_rel_grant(FF_SYNC_t sobj) { xSemaphoreGive(sobj); } #endif DWORD get_fattime(void) { timeutils_struct_time_t tm; timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm); return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) | ((tm.tm_mday) << 16) | ((tm.tm_hour) << 11) | ((tm.tm_min) << 5) | (tm.tm_sec >> 1); } micropython-1.12/ports/cc3200/ftp/000077500000000000000000000000001357706137100166545ustar00rootroot00000000000000micropython-1.12/ports/cc3200/ftp/ftp.c000066400000000000000000001175741357706137100176300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "prcm.h" #include "pybrtc.h" #include "ftp.h" #include "simplelink.h" #include "modnetwork.h" #include "modwlan.h" #include "modusocket.h" #include "debug.h" #include "serverstask.h" #include "fifo.h" #include "socketfifo.h" #include "updater.h" #include "moduos.h" /****************************************************************************** DEFINE PRIVATE CONSTANTS ******************************************************************************/ #define FTP_CMD_PORT 21 #define FTP_ACTIVE_DATA_PORT 20 #define FTP_PASIVE_DATA_PORT 2024 #define FTP_BUFFER_SIZE 512 #define FTP_TX_RETRIES_MAX 25 #define FTP_CMD_SIZE_MAX 6 #define FTP_CMD_CLIENTS_MAX 1 #define FTP_DATA_CLIENTS_MAX 1 #define FTP_MAX_PARAM_SIZE (MICROPY_ALLOC_PATH_MAX + 1) #define FTP_UNIX_TIME_20000101 946684800 #define FTP_UNIX_TIME_20150101 1420070400 #define FTP_UNIX_SECONDS_180_DAYS 15552000 #define FTP_DATA_TIMEOUT_MS 5000 // 5 seconds #define FTP_SOCKETFIFO_ELEMENTS_MAX 4 #define FTP_CYCLE_TIME_MS (SERVERS_CYCLE_TIME_MS * 2) /****************************************************************************** DEFINE PRIVATE TYPES ******************************************************************************/ typedef enum { E_FTP_RESULT_OK = 0, E_FTP_RESULT_CONTINUE, E_FTP_RESULT_FAILED } ftp_result_t; typedef enum { E_FTP_STE_DISABLED = 0, E_FTP_STE_START, E_FTP_STE_READY, E_FTP_STE_END_TRANSFER, E_FTP_STE_CONTINUE_LISTING, E_FTP_STE_CONTINUE_FILE_TX, E_FTP_STE_CONTINUE_FILE_RX } ftp_state_t; typedef enum { E_FTP_STE_SUB_DISCONNECTED = 0, E_FTP_STE_SUB_LISTEN_FOR_DATA, E_FTP_STE_SUB_DATA_CONNECTED } ftp_substate_t; typedef struct { bool uservalid : 1; bool passvalid : 1; } ftp_loggin_t; typedef enum { E_FTP_NOTHING_OPEN = 0, E_FTP_FILE_OPEN, E_FTP_DIR_OPEN } ftp_e_open_t; typedef enum { E_FTP_CLOSE_NONE = 0, E_FTP_CLOSE_DATA, E_FTP_CLOSE_CMD_AND_DATA, } ftp_e_closesocket_t; typedef struct { uint8_t *dBuffer; uint32_t ctimeout; union { FF_DIR dp; FIL fp; }; int16_t lc_sd; int16_t ld_sd; int16_t c_sd; int16_t d_sd; int16_t dtimeout; uint16_t volcount; uint8_t state; uint8_t substate; uint8_t txRetries; uint8_t logginRetries; ftp_loggin_t loggin; uint8_t e_open; bool closechild; bool enabled; bool special_file; bool listroot; } ftp_data_t; typedef struct { char * cmd; } ftp_cmd_t; typedef struct { char * month; } ftp_month_t; typedef enum { E_FTP_CMD_NOT_SUPPORTED = -1, E_FTP_CMD_FEAT = 0, E_FTP_CMD_SYST, E_FTP_CMD_CDUP, E_FTP_CMD_CWD, E_FTP_CMD_PWD, E_FTP_CMD_XPWD, E_FTP_CMD_SIZE, E_FTP_CMD_MDTM, E_FTP_CMD_TYPE, E_FTP_CMD_USER, E_FTP_CMD_PASS, E_FTP_CMD_PASV, E_FTP_CMD_LIST, E_FTP_CMD_RETR, E_FTP_CMD_STOR, E_FTP_CMD_DELE, E_FTP_CMD_RMD, E_FTP_CMD_MKD, E_FTP_CMD_RNFR, E_FTP_CMD_RNTO, E_FTP_CMD_NOOP, E_FTP_CMD_QUIT, E_FTP_NUM_FTP_CMDS } ftp_cmd_index_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ static ftp_data_t ftp_data; static char *ftp_path; static char *ftp_scratch_buffer; static char *ftp_cmd_buffer; static const ftp_cmd_t ftp_cmd_table[] = { { "FEAT" }, { "SYST" }, { "CDUP" }, { "CWD" }, { "PWD" }, { "XPWD" }, { "SIZE" }, { "MDTM" }, { "TYPE" }, { "USER" }, { "PASS" }, { "PASV" }, { "LIST" }, { "RETR" }, { "STOR" }, { "DELE" }, { "RMD" }, { "MKD" }, { "RNFR" }, { "RNTO" }, { "NOOP" }, { "QUIT" } }; static const ftp_month_t ftp_month[] = { { "Jan" }, { "Feb" }, { "Mar" }, { "Apr" }, { "May" }, { "Jun" }, { "Jul" }, { "Ago" }, { "Sep" }, { "Oct" }, { "Nov" }, { "Dec" } }; static SocketFifoElement_t ftp_fifoelements[FTP_SOCKETFIFO_ELEMENTS_MAX]; static FIFO_t ftp_socketfifo; /****************************************************************************** DEFINE VFS WRAPPER FUNCTIONS ******************************************************************************/ // These wrapper functions are used so that the FTP server can access the // mounted FATFS devices directly without going through the costly mp_vfs_XXX // functions. The latter may raise exceptions and we would then need to wrap // all calls in an nlr handler. The wrapper functions below assume that there // are only FATFS filesystems mounted. STATIC FATFS *lookup_path(const TCHAR **path) { mp_vfs_mount_t *fs = mp_vfs_lookup_path(*path, path); if (fs == MP_VFS_NONE || fs == MP_VFS_ROOT) { return NULL; } // here we assume that the mounted device is FATFS return &((fs_user_mount_t*)MP_OBJ_TO_PTR(fs->obj))->fatfs; } STATIC FRESULT f_open_helper(FIL *fp, const TCHAR *path, BYTE mode) { FATFS *fs = lookup_path(&path); if (fs == NULL) { return FR_NO_PATH; } return f_open(fs, fp, path, mode); } STATIC FRESULT f_opendir_helper(FF_DIR *dp, const TCHAR *path) { FATFS *fs = lookup_path(&path); if (fs == NULL) { return FR_NO_PATH; } return f_opendir(fs, dp, path); } STATIC FRESULT f_stat_helper(const TCHAR *path, FILINFO *fno) { FATFS *fs = lookup_path(&path); if (fs == NULL) { return FR_NO_PATH; } return f_stat(fs, path, fno); } STATIC FRESULT f_mkdir_helper(const TCHAR *path) { FATFS *fs = lookup_path(&path); if (fs == NULL) { return FR_NO_PATH; } return f_mkdir(fs, path); } STATIC FRESULT f_unlink_helper(const TCHAR *path) { FATFS *fs = lookup_path(&path); if (fs == NULL) { return FR_NO_PATH; } return f_unlink(fs, path); } STATIC FRESULT f_rename_helper(const TCHAR *path_old, const TCHAR *path_new) { FATFS *fs_old = lookup_path(&path_old); if (fs_old == NULL) { return FR_NO_PATH; } FATFS *fs_new = lookup_path(&path_new); if (fs_new == NULL) { return FR_NO_PATH; } if (fs_old != fs_new) { return FR_NO_PATH; } return f_rename(fs_new, path_old, path_new); } /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ static void ftp_wait_for_enabled (void); static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog); static ftp_result_t ftp_wait_for_connection (_i16 l_sd, _i16 *n_sd); static ftp_result_t ftp_send_non_blocking (_i16 sd, void *data, _i16 Len); static void ftp_send_reply (_u16 status, char *message); static void ftp_send_data (_u32 datasize); static void ftp_send_from_fifo (void); static ftp_result_t ftp_recv_non_blocking (_i16 sd, void *buff, _i16 Maxlen, _i32 *rxLen); static void ftp_process_cmd (void); static void ftp_close_files (void); static void ftp_close_filesystem_on_error (void); static void ftp_close_cmd_data (void); static ftp_cmd_index_t ftp_pop_command (char **str); static void ftp_pop_param (char **str, char *param); static int ftp_print_eplf_item (char *dest, uint32_t destsize, FILINFO *fno); static int ftp_print_eplf_drive (char *dest, uint32_t destsize, const char *name); static bool ftp_open_file (const char *path, int mode); static ftp_result_t ftp_read_file (char *filebuf, uint32_t desiredsize, uint32_t *actualsize); static ftp_result_t ftp_write_file (char *filebuf, uint32_t size); static ftp_result_t ftp_open_dir_for_listing (const char *path); static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *listsize); static void ftp_open_child (char *pwd, char *dir); static void ftp_close_child (char *pwd); static void ftp_return_to_previous_path (char *pwd, char *dir); /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void ftp_init (void) { // Allocate memory for the data buffer, and the file system structs (from the RTOS heap) ASSERT ((ftp_data.dBuffer = mem_Malloc(FTP_BUFFER_SIZE)) != NULL); ASSERT ((ftp_path = mem_Malloc(FTP_MAX_PARAM_SIZE)) != NULL); ASSERT ((ftp_scratch_buffer = mem_Malloc(FTP_MAX_PARAM_SIZE)) != NULL); ASSERT ((ftp_cmd_buffer = mem_Malloc(FTP_MAX_PARAM_SIZE + FTP_CMD_SIZE_MAX)) != NULL); SOCKETFIFO_Init (&ftp_socketfifo, (void *)ftp_fifoelements, FTP_SOCKETFIFO_ELEMENTS_MAX); ftp_data.c_sd = -1; ftp_data.d_sd = -1; ftp_data.lc_sd = -1; ftp_data.ld_sd = -1; ftp_data.e_open = E_FTP_NOTHING_OPEN; ftp_data.state = E_FTP_STE_DISABLED; ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; ftp_data.special_file = false; ftp_data.volcount = 0; } void ftp_run (void) { switch (ftp_data.state) { case E_FTP_STE_DISABLED: ftp_wait_for_enabled(); break; case E_FTP_STE_START: if (wlan_is_connected() && ftp_create_listening_socket(&ftp_data.lc_sd, FTP_CMD_PORT, FTP_CMD_CLIENTS_MAX - 1)) { ftp_data.state = E_FTP_STE_READY; } break; case E_FTP_STE_READY: if (ftp_data.c_sd < 0 && ftp_data.substate == E_FTP_STE_SUB_DISCONNECTED) { if (E_FTP_RESULT_OK == ftp_wait_for_connection(ftp_data.lc_sd, &ftp_data.c_sd)) { ftp_data.txRetries = 0; ftp_data.logginRetries = 0; ftp_data.ctimeout = 0; ftp_data.loggin.uservalid = false; ftp_data.loggin.passvalid = false; strcpy (ftp_path, "/"); ftp_send_reply (220, "MicroPython FTP Server"); break; } } if (SOCKETFIFO_IsEmpty()) { if (ftp_data.c_sd > 0 && ftp_data.substate != E_FTP_STE_SUB_LISTEN_FOR_DATA) { ftp_process_cmd(); if (ftp_data.state != E_FTP_STE_READY) { break; } } } break; case E_FTP_STE_END_TRANSFER: break; case E_FTP_STE_CONTINUE_LISTING: // go on with listing only if the transmit buffer is empty if (SOCKETFIFO_IsEmpty()) { uint32_t listsize; ftp_list_dir((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, &listsize); if (listsize > 0) { ftp_send_data(listsize); } else { ftp_send_reply(226, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; } ftp_data.ctimeout = 0; } break; case E_FTP_STE_CONTINUE_FILE_TX: // read the next block from the file only if the previous one has been sent if (SOCKETFIFO_IsEmpty()) { uint32_t readsize; ftp_result_t result; ftp_data.ctimeout = 0; result = ftp_read_file ((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, &readsize); if (result == E_FTP_RESULT_FAILED) { ftp_send_reply(451, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; } else { if (readsize > 0) { ftp_send_data(readsize); } if (result == E_FTP_RESULT_OK) { ftp_send_reply(226, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; } } } break; case E_FTP_STE_CONTINUE_FILE_RX: if (SOCKETFIFO_IsEmpty()) { _i32 len; ftp_result_t result; if (E_FTP_RESULT_OK == (result = ftp_recv_non_blocking(ftp_data.d_sd, ftp_data.dBuffer, FTP_BUFFER_SIZE, &len))) { ftp_data.dtimeout = 0; ftp_data.ctimeout = 0; // its a software update if (ftp_data.special_file) { if (updater_write(ftp_data.dBuffer, len)) { break; } } // user file being received else if (E_FTP_RESULT_OK == ftp_write_file ((char *)ftp_data.dBuffer, len)) { break; } ftp_send_reply(451, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; } else if (result == E_FTP_RESULT_CONTINUE) { if (ftp_data.dtimeout++ > FTP_DATA_TIMEOUT_MS / FTP_CYCLE_TIME_MS) { ftp_close_files(); ftp_send_reply(426, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; } } else { if (ftp_data.special_file) { ftp_data.special_file = false; updater_finnish(); } ftp_close_files(); ftp_send_reply(226, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; } } break; default: break; } switch (ftp_data.substate) { case E_FTP_STE_SUB_DISCONNECTED: break; case E_FTP_STE_SUB_LISTEN_FOR_DATA: if (E_FTP_RESULT_OK == ftp_wait_for_connection(ftp_data.ld_sd, &ftp_data.d_sd)) { ftp_data.dtimeout = 0; ftp_data.substate = E_FTP_STE_SUB_DATA_CONNECTED; } else if (ftp_data.dtimeout++ > FTP_DATA_TIMEOUT_MS / FTP_CYCLE_TIME_MS) { ftp_data.dtimeout = 0; // close the listening socket servers_close_socket(&ftp_data.ld_sd); ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; } break; case E_FTP_STE_SUB_DATA_CONNECTED: if (ftp_data.state == E_FTP_STE_READY && ftp_data.dtimeout++ > FTP_DATA_TIMEOUT_MS / FTP_CYCLE_TIME_MS) { // close the listening and the data socket servers_close_socket(&ftp_data.ld_sd); servers_close_socket(&ftp_data.d_sd); ftp_close_filesystem_on_error (); ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; } break; default: break; } // send data pending in the queue ftp_send_from_fifo(); // check the state of the data sockets if (ftp_data.d_sd < 0 && (ftp_data.state > E_FTP_STE_READY)) { ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; ftp_data.state = E_FTP_STE_READY; } } void ftp_enable (void) { ftp_data.enabled = true; } void ftp_disable (void) { ftp_reset(); ftp_data.enabled = false; ftp_data.state = E_FTP_STE_DISABLED; } void ftp_reset (void) { // close all connections and start all over again servers_close_socket(&ftp_data.lc_sd); servers_close_socket(&ftp_data.ld_sd); ftp_close_cmd_data(); ftp_data.state = E_FTP_STE_START; ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; ftp_data.volcount = 0; SOCKETFIFO_Flush(); } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ static void ftp_wait_for_enabled (void) { // Check if the telnet service has been enabled if (ftp_data.enabled) { ftp_data.state = E_FTP_STE_START; } } static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) { SlSockNonblocking_t nonBlockingOption; SlSockAddrIn_t sServerAddress; _i16 _sd; _i16 result; // Open a socket for ftp data listen ASSERT ((*sd = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_IP)) > 0); _sd = *sd; if (_sd > 0) { // add the new socket to the network administration modusocket_socket_add(_sd, false); // Enable non-blocking mode nonBlockingOption.NonblockingEnabled = 1; ASSERT ((result = sl_SetSockOpt(_sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK); // Bind the socket to a port number sServerAddress.sin_family = SL_AF_INET; sServerAddress.sin_addr.s_addr = SL_INADDR_ANY; sServerAddress.sin_port = sl_Htons(port); ASSERT ((result |= sl_Bind(_sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK); // Start listening ASSERT ((result |= sl_Listen (_sd, backlog)) == SL_SOC_OK); if (result == SL_SOC_OK) { return true; } servers_close_socket(sd); } return false; } static ftp_result_t ftp_wait_for_connection (_i16 l_sd, _i16 *n_sd) { SlSockAddrIn_t sClientAddress; SlSocklen_t in_addrSize; // accepts a connection from a TCP client, if there is any, otherwise returns SL_EAGAIN *n_sd = sl_Accept(l_sd, (SlSockAddr_t *)&sClientAddress, (SlSocklen_t *)&in_addrSize); _i16 _sd = *n_sd; if (_sd == SL_EAGAIN) { return E_FTP_RESULT_CONTINUE; } else if (_sd < 0) { // error ftp_reset(); return E_FTP_RESULT_FAILED; } // add the new socket to the network administration modusocket_socket_add(_sd, false); // client connected, so go on return E_FTP_RESULT_OK; } static ftp_result_t ftp_send_non_blocking (_i16 sd, void *data, _i16 Len) { int16_t result = sl_Send(sd, data, Len, 0); if (result > 0) { ftp_data.txRetries = 0; return E_FTP_RESULT_OK; } else if ((FTP_TX_RETRIES_MAX >= ++ftp_data.txRetries) && (result == SL_EAGAIN)) { return E_FTP_RESULT_CONTINUE; } else { // error ftp_reset(); return E_FTP_RESULT_FAILED; } } static void ftp_send_reply (_u16 status, char *message) { SocketFifoElement_t fifoelement; if (!message) { message = ""; } snprintf((char *)ftp_cmd_buffer, 4, "%u", status); strcat ((char *)ftp_cmd_buffer, " "); strcat ((char *)ftp_cmd_buffer, message); strcat ((char *)ftp_cmd_buffer, "\r\n"); fifoelement.sd = &ftp_data.c_sd; fifoelement.datasize = strlen((char *)ftp_cmd_buffer); fifoelement.data = mem_Malloc(fifoelement.datasize); if (status == 221) { fifoelement.closesockets = E_FTP_CLOSE_CMD_AND_DATA; } else if (status == 426 || status == 451 || status == 550) { fifoelement.closesockets = E_FTP_CLOSE_DATA; } else { fifoelement.closesockets = E_FTP_CLOSE_NONE; } fifoelement.freedata = true; if (fifoelement.data) { memcpy (fifoelement.data, ftp_cmd_buffer, fifoelement.datasize); if (!SOCKETFIFO_Push (&fifoelement)) { mem_Free(fifoelement.data); } } } static void ftp_send_data (_u32 datasize) { SocketFifoElement_t fifoelement; fifoelement.data = ftp_data.dBuffer; fifoelement.datasize = datasize; fifoelement.sd = &ftp_data.d_sd; fifoelement.closesockets = E_FTP_CLOSE_NONE; fifoelement.freedata = false; SOCKETFIFO_Push (&fifoelement); } static void ftp_send_from_fifo (void) { SocketFifoElement_t fifoelement; if (SOCKETFIFO_Peek (&fifoelement)) { _i16 _sd = *fifoelement.sd; if (_sd > 0) { if (E_FTP_RESULT_OK == ftp_send_non_blocking (_sd, fifoelement.data, fifoelement.datasize)) { SOCKETFIFO_Pop (&fifoelement); if (fifoelement.closesockets != E_FTP_CLOSE_NONE) { servers_close_socket(&ftp_data.d_sd); if (fifoelement.closesockets == E_FTP_CLOSE_CMD_AND_DATA) { servers_close_socket(&ftp_data.ld_sd); // this one is the command socket servers_close_socket(fifoelement.sd); ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; } ftp_close_filesystem_on_error(); } if (fifoelement.freedata) { mem_Free(fifoelement.data); } } } // socket closed, remove from the queue else { SOCKETFIFO_Pop (&fifoelement); if (fifoelement.freedata) { mem_Free(fifoelement.data); } } } else if (ftp_data.state == E_FTP_STE_END_TRANSFER && (ftp_data.d_sd > 0)) { // close the listening and the data sockets servers_close_socket(&ftp_data.ld_sd); servers_close_socket(&ftp_data.d_sd); if (ftp_data.special_file) { ftp_data.special_file = false; } } } static ftp_result_t ftp_recv_non_blocking (_i16 sd, void *buff, _i16 Maxlen, _i32 *rxLen) { *rxLen = sl_Recv(sd, buff, Maxlen, 0); if (*rxLen > 0) { return E_FTP_RESULT_OK; } else if (*rxLen != SL_EAGAIN) { // error return E_FTP_RESULT_FAILED; } return E_FTP_RESULT_CONTINUE; } static void ftp_get_param_and_open_child (char **bufptr) { ftp_pop_param (bufptr, ftp_scratch_buffer); ftp_open_child (ftp_path, ftp_scratch_buffer); ftp_data.closechild = true; } static void ftp_process_cmd (void) { _i32 len; char *bufptr = (char *)ftp_cmd_buffer; ftp_result_t result; FRESULT fres; FILINFO fno; ftp_data.closechild = false; // also use the reply buffer to receive new commands if (E_FTP_RESULT_OK == (result = ftp_recv_non_blocking(ftp_data.c_sd, ftp_cmd_buffer, FTP_MAX_PARAM_SIZE + FTP_CMD_SIZE_MAX, &len))) { // bufptr is moved as commands are being popped ftp_cmd_index_t cmd = ftp_pop_command(&bufptr); if (!ftp_data.loggin.passvalid && (cmd != E_FTP_CMD_USER && cmd != E_FTP_CMD_PASS && cmd != E_FTP_CMD_QUIT)) { ftp_send_reply(332, NULL); return; } switch (cmd) { case E_FTP_CMD_FEAT: ftp_send_reply(211, "no-features"); break; case E_FTP_CMD_SYST: ftp_send_reply(215, "UNIX Type: L8"); break; case E_FTP_CMD_CDUP: ftp_close_child(ftp_path); ftp_send_reply(250, NULL); break; case E_FTP_CMD_CWD: { fres = FR_NO_PATH; ftp_pop_param (&bufptr, ftp_scratch_buffer); ftp_open_child (ftp_path, ftp_scratch_buffer); if ((ftp_path[0] == '/' && ftp_path[1] == '\0') || ((fres = f_opendir_helper (&ftp_data.dp, ftp_path)) == FR_OK)) { if (fres == FR_OK) { f_closedir(&ftp_data.dp); } ftp_send_reply(250, NULL); } else { ftp_close_child (ftp_path); ftp_send_reply(550, NULL); } } break; case E_FTP_CMD_PWD: case E_FTP_CMD_XPWD: ftp_send_reply(257, ftp_path); break; case E_FTP_CMD_SIZE: { ftp_get_param_and_open_child (&bufptr); if (FR_OK == f_stat_helper(ftp_path, &fno)) { // send the size snprintf((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, "%u", (_u32)fno.fsize); ftp_send_reply(213, (char *)ftp_data.dBuffer); } else { ftp_send_reply(550, NULL); } } break; case E_FTP_CMD_MDTM: ftp_get_param_and_open_child (&bufptr); if (FR_OK == f_stat_helper(ftp_path, &fno)) { // send the last modified time snprintf((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, "%u%02u%02u%02u%02u%02u", 1980 + ((fno.fdate >> 9) & 0x7f), (fno.fdate >> 5) & 0x0f, fno.fdate & 0x1f, (fno.ftime >> 11) & 0x1f, (fno.ftime >> 5) & 0x3f, 2 * (fno.ftime & 0x1f)); ftp_send_reply(213, (char *)ftp_data.dBuffer); } else { ftp_send_reply(550, NULL); } break; case E_FTP_CMD_TYPE: ftp_send_reply(200, NULL); break; case E_FTP_CMD_USER: ftp_pop_param (&bufptr, ftp_scratch_buffer); if (!memcmp(ftp_scratch_buffer, servers_user, MAX(strlen(ftp_scratch_buffer), strlen(servers_user)))) { ftp_data.loggin.uservalid = true && (strlen(servers_user) == strlen(ftp_scratch_buffer)); } ftp_send_reply(331, NULL); break; case E_FTP_CMD_PASS: ftp_pop_param (&bufptr, ftp_scratch_buffer); if (!memcmp(ftp_scratch_buffer, servers_pass, MAX(strlen(ftp_scratch_buffer), strlen(servers_pass))) && ftp_data.loggin.uservalid) { ftp_data.loggin.passvalid = true && (strlen(servers_pass) == strlen(ftp_scratch_buffer)); if (ftp_data.loggin.passvalid) { ftp_send_reply(230, NULL); break; } } ftp_send_reply(530, NULL); break; case E_FTP_CMD_PASV: { // some servers (e.g. google chrome) send PASV several times very quickly servers_close_socket(&ftp_data.d_sd); ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; bool socketcreated = true; if (ftp_data.ld_sd < 0) { socketcreated = ftp_create_listening_socket(&ftp_data.ld_sd, FTP_PASIVE_DATA_PORT, FTP_DATA_CLIENTS_MAX - 1); } if (socketcreated) { uint32_t ip; uint8_t *pip = (uint8_t *)&ip; ftp_data.dtimeout = 0; wlan_get_ip(&ip); snprintf((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, "(%u,%u,%u,%u,%u,%u)", pip[3], pip[2], pip[1], pip[0], (FTP_PASIVE_DATA_PORT >> 8), (FTP_PASIVE_DATA_PORT & 0xFF)); ftp_data.substate = E_FTP_STE_SUB_LISTEN_FOR_DATA; ftp_send_reply(227, (char *)ftp_data.dBuffer); } else { ftp_send_reply(425, NULL); } } break; case E_FTP_CMD_LIST: if (ftp_open_dir_for_listing(ftp_path) == E_FTP_RESULT_CONTINUE) { ftp_data.state = E_FTP_STE_CONTINUE_LISTING; ftp_send_reply(150, NULL); } else { ftp_send_reply(550, NULL); } break; case E_FTP_CMD_RETR: ftp_get_param_and_open_child (&bufptr); if (ftp_open_file (ftp_path, FA_READ)) { ftp_data.state = E_FTP_STE_CONTINUE_FILE_TX; ftp_send_reply(150, NULL); } else { ftp_data.state = E_FTP_STE_END_TRANSFER; ftp_send_reply(550, NULL); } break; case E_FTP_CMD_STOR: ftp_get_param_and_open_child (&bufptr); // first check if a software update is being requested if (updater_check_path (ftp_path)) { if (updater_start()) { ftp_data.special_file = true; ftp_data.state = E_FTP_STE_CONTINUE_FILE_RX; ftp_send_reply(150, NULL); } else { // to unlock the updater updater_finnish(); ftp_data.state = E_FTP_STE_END_TRANSFER; ftp_send_reply(550, NULL); } } else { if (ftp_open_file (ftp_path, FA_WRITE | FA_CREATE_ALWAYS)) { ftp_data.state = E_FTP_STE_CONTINUE_FILE_RX; ftp_send_reply(150, NULL); } else { ftp_data.state = E_FTP_STE_END_TRANSFER; ftp_send_reply(550, NULL); } } break; case E_FTP_CMD_DELE: case E_FTP_CMD_RMD: ftp_get_param_and_open_child (&bufptr); if (FR_OK == f_unlink_helper(ftp_path)) { ftp_send_reply(250, NULL); } else { ftp_send_reply(550, NULL); } break; case E_FTP_CMD_MKD: ftp_get_param_and_open_child (&bufptr); if (FR_OK == f_mkdir_helper(ftp_path)) { ftp_send_reply(250, NULL); } else { ftp_send_reply(550, NULL); } break; case E_FTP_CMD_RNFR: ftp_get_param_and_open_child (&bufptr); if (FR_OK == f_stat_helper(ftp_path, &fno)) { ftp_send_reply(350, NULL); // save the current path strcpy ((char *)ftp_data.dBuffer, ftp_path); } else { ftp_send_reply(550, NULL); } break; case E_FTP_CMD_RNTO: ftp_get_param_and_open_child (&bufptr); // old path was saved in the data buffer if (FR_OK == (fres = f_rename_helper((char *)ftp_data.dBuffer, ftp_path))) { ftp_send_reply(250, NULL); } else { ftp_send_reply(550, NULL); } break; case E_FTP_CMD_NOOP: ftp_send_reply(200, NULL); break; case E_FTP_CMD_QUIT: ftp_send_reply(221, NULL); break; default: // command not implemented ftp_send_reply(502, NULL); break; } if (ftp_data.closechild) { ftp_return_to_previous_path(ftp_path, ftp_scratch_buffer); } } else if (result == E_FTP_RESULT_CONTINUE) { if (ftp_data.ctimeout++ > (servers_get_timeout() / FTP_CYCLE_TIME_MS)) { ftp_send_reply(221, NULL); } } else { ftp_close_cmd_data (); } } static void ftp_close_files (void) { if (ftp_data.e_open == E_FTP_FILE_OPEN) { f_close(&ftp_data.fp); } else if (ftp_data.e_open == E_FTP_DIR_OPEN) { f_closedir(&ftp_data.dp); } ftp_data.e_open = E_FTP_NOTHING_OPEN; } static void ftp_close_filesystem_on_error (void) { ftp_close_files(); if (ftp_data.special_file) { updater_finnish (); ftp_data.special_file = false; } } static void ftp_close_cmd_data (void) { servers_close_socket(&ftp_data.c_sd); servers_close_socket(&ftp_data.d_sd); ftp_close_filesystem_on_error (); } static void stoupper (char *str) { while (str && *str != '\0') { *str = (char)unichar_toupper((int)(*str)); str++; } } static ftp_cmd_index_t ftp_pop_command (char **str) { char _cmd[FTP_CMD_SIZE_MAX]; ftp_pop_param (str, _cmd); stoupper (_cmd); for (ftp_cmd_index_t i = 0; i < E_FTP_NUM_FTP_CMDS; i++) { if (!strcmp (_cmd, ftp_cmd_table[i].cmd)) { // move one step further to skip the space (*str)++; return i; } } return E_FTP_CMD_NOT_SUPPORTED; } static void ftp_pop_param (char **str, char *param) { while (**str != ' ' && **str != '\r' && **str != '\n' && **str != '\0') { *param++ = **str; (*str)++; } *param = '\0'; } static int ftp_print_eplf_item (char *dest, uint32_t destsize, FILINFO *fno) { char *type = (fno->fattrib & AM_DIR) ? "d" : "-"; uint32_t tseconds; uint mindex = (((fno->fdate >> 5) & 0x0f) > 0) ? (((fno->fdate >> 5) & 0x0f) - 1) : 0; uint day = ((fno->fdate & 0x1f) > 0) ? (fno->fdate & 0x1f) : 1; uint fseconds = timeutils_seconds_since_2000(1980 + ((fno->fdate >> 9) & 0x7f), (fno->fdate >> 5) & 0x0f, fno->fdate & 0x1f, (fno->ftime >> 11) & 0x1f, (fno->ftime >> 5) & 0x3f, 2 * (fno->ftime & 0x1f)); tseconds = pyb_rtc_get_seconds(); if (FTP_UNIX_SECONDS_180_DAYS < tseconds - fseconds) { return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %5u %s\r\n", type, (_u32)fno->fsize, ftp_month[mindex].month, day, 1980 + ((fno->fdate >> 9) & 0x7f), fno->fname); } else { return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %02u:%02u %s\r\n", type, (_u32)fno->fsize, ftp_month[mindex].month, day, (fno->ftime >> 11) & 0x1f, (fno->ftime >> 5) & 0x3f, fno->fname); } } static int ftp_print_eplf_drive (char *dest, uint32_t destsize, const char *name) { timeutils_struct_time_t tm; uint32_t tseconds; char *type = "d"; timeutils_seconds_since_2000_to_struct_time((FTP_UNIX_TIME_20150101 - FTP_UNIX_TIME_20000101), &tm); tseconds = pyb_rtc_get_seconds(); if (FTP_UNIX_SECONDS_180_DAYS < tseconds - (FTP_UNIX_TIME_20150101 - FTP_UNIX_TIME_20000101)) { return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %5u %s\r\n", type, 0, ftp_month[(tm.tm_mon - 1)].month, tm.tm_mday, tm.tm_year, name); } else { return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %02u:%02u %s\r\n", type, 0, ftp_month[(tm.tm_mon - 1)].month, tm.tm_mday, tm.tm_hour, tm.tm_min, name); } } static bool ftp_open_file (const char *path, int mode) { FRESULT res = f_open_helper(&ftp_data.fp, path, mode); if (res != FR_OK) { return false; } ftp_data.e_open = E_FTP_FILE_OPEN; return true; } static ftp_result_t ftp_read_file (char *filebuf, uint32_t desiredsize, uint32_t *actualsize) { ftp_result_t result = E_FTP_RESULT_CONTINUE; FRESULT res = f_read(&ftp_data.fp, filebuf, desiredsize, (UINT *)actualsize); if (res != FR_OK) { ftp_close_files(); result = E_FTP_RESULT_FAILED; *actualsize = 0; } else if (*actualsize < desiredsize) { ftp_close_files(); result = E_FTP_RESULT_OK; } return result; } static ftp_result_t ftp_write_file (char *filebuf, uint32_t size) { ftp_result_t result = E_FTP_RESULT_FAILED; uint32_t actualsize; FRESULT res = f_write(&ftp_data.fp, filebuf, size, (UINT *)&actualsize); if ((actualsize == size) && (FR_OK == res)) { result = E_FTP_RESULT_OK; } else { ftp_close_files(); } return result; } static ftp_result_t ftp_open_dir_for_listing (const char *path) { // "hack" to detect the root directory if (path[0] == '/' && path[1] == '\0') { ftp_data.listroot = true; } else { FRESULT res; res = f_opendir_helper(&ftp_data.dp, path); /* Open the directory */ if (res != FR_OK) { return E_FTP_RESULT_FAILED; } ftp_data.e_open = E_FTP_DIR_OPEN; ftp_data.listroot = false; } return E_FTP_RESULT_CONTINUE; } static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *listsize) { uint next = 0; uint listcount = 0; FRESULT res; ftp_result_t result = E_FTP_RESULT_CONTINUE; FILINFO fno; #if _USE_LFN // read up to 2 directory items while (listcount < 2) { #else // read up to 4 directory items while (listcount < 4) { #endif if (ftp_data.listroot) { // root directory "hack" mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); int i = ftp_data.volcount; while (vfs != NULL && i != 0) { vfs = vfs->next; i -= 1; } if (vfs == NULL) { if (!next) { // no volume found this time, we are done ftp_data.volcount = 0; } break; } else { next += ftp_print_eplf_drive((list + next), (maxlistsize - next), vfs->str + 1); } ftp_data.volcount++; } else { // a "normal" directory res = f_readdir(&ftp_data.dp, &fno); /* Read a directory item */ if (res != FR_OK || fno.fname[0] == 0) { result = E_FTP_RESULT_OK; break; /* Break on error or end of dp */ } if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */ if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */ // add the entry to the list next += ftp_print_eplf_item((list + next), (maxlistsize - next), &fno); } listcount++; } if (result == E_FTP_RESULT_OK) { ftp_close_files(); } *listsize = next; return result; } static void ftp_open_child (char *pwd, char *dir) { if (dir[0] == '/') { strcpy (pwd, dir); } else { if (strlen(pwd) > 1) { strcat (pwd, "/"); } strcat (pwd, dir); } uint len = strlen(pwd); if ((len > 1) && (pwd[len - 1] == '/')) { pwd[len - 1] = '\0'; } } static void ftp_close_child (char *pwd) { uint len = strlen(pwd); while (len && (pwd[len] != '/')) { len--; } if (len == 0) { strcpy (pwd, "/"); } else { pwd[len] = '\0'; } } static void ftp_return_to_previous_path (char *pwd, char *dir) { uint newlen = strlen(pwd) - strlen(dir); if ((newlen > 2) && (pwd[newlen - 1] == '/')) { pwd[newlen - 1] = '\0'; } else { if (newlen == 0) { strcpy (pwd, "/"); } else { pwd[newlen] = '\0'; } } } micropython-1.12/ports/cc3200/ftp/ftp.h000066400000000000000000000032341357706137100176200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_FTP_FTP_H #define MICROPY_INCLUDED_CC3200_FTP_FTP_H /****************************************************************************** DECLARE EXPORTED FUNCTIONS ******************************************************************************/ extern void ftp_init (void); extern void ftp_run (void); extern void ftp_enable (void); extern void ftp_disable (void); extern void ftp_reset (void); #endif // MICROPY_INCLUDED_CC3200_FTP_FTP_H micropython-1.12/ports/cc3200/ftp/updater.c000066400000000000000000000175061357706137100204750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpconfig.h" #include "py/obj.h" #include "simplelink.h" #include "flc.h" #include "updater.h" #include "shamd5.h" #include "modnetwork.h" #include "modwlan.h" #include "debug.h" #include "osi.h" /****************************************************************************** DEFINE PRIVATE CONSTANTS ******************************************************************************/ #define UPDATER_IMG_PATH "/flash/sys/mcuimg.bin" #define UPDATER_SRVPACK_PATH "/flash/sys/servicepack.ucf" #define UPDATER_SIGN_PATH "/flash/sys/servicepack.sig" #define UPDATER_CA_PATH "/flash/cert/ca.pem" #define UPDATER_CERT_PATH "/flash/cert/cert.pem" #define UPDATER_KEY_PATH "/flash/cert/private.key" /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef struct { char *path; _i32 fhandle; _u32 fsize; _u32 foffset; } updater_data_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ static updater_data_t updater_data = { .path = NULL, .fhandle = -1, .fsize = 0, .foffset = 0 }; static OsiLockObj_t updater_LockObj; static sBootInfo_t sBootInfo; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ __attribute__ ((section (".boot"))) void updater_pre_init (void) { // create the updater lock ASSERT(OSI_OK == sl_LockObjCreate(&updater_LockObj, "UpdaterLock")); } bool updater_check_path (void *path) { sl_LockObjLock (&updater_LockObj, SL_OS_WAIT_FOREVER); if (!strcmp(UPDATER_IMG_PATH, path)) { updater_data.fsize = IMG_SIZE; updater_data.path = IMG_UPDATE1; // the launchxl doesn't have enough flash space for 2 user update images #ifdef WIPY // check which one should be the next active image _i32 fhandle; if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) { ASSERT (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))); sl_FsClose(fhandle, 0, 0, 0); // if we still have an image pending for verification, keep overwriting it if ((sBootInfo.Status == IMG_STATUS_CHECK && sBootInfo.ActiveImg == IMG_ACT_UPDATE2) || (sBootInfo.ActiveImg == IMG_ACT_UPDATE1 && sBootInfo.Status != IMG_STATUS_CHECK)) { updater_data.path = IMG_UPDATE2; } } #endif } else if (!strcmp(UPDATER_SRVPACK_PATH, path)) { updater_data.path = IMG_SRVPACK; updater_data.fsize = SRVPACK_SIZE; } else if (!strcmp(UPDATER_SIGN_PATH, path)) { updater_data.path = SRVPACK_SIGN; updater_data.fsize = SIGN_SIZE; } else if (!strcmp(UPDATER_CA_PATH, path)) { updater_data.path = CA_FILE; updater_data.fsize = CA_KEY_SIZE; } else if (!strcmp(UPDATER_CERT_PATH, path)) { updater_data.path = CERT_FILE; updater_data.fsize = CA_KEY_SIZE; } else if (!strcmp(UPDATER_KEY_PATH, path)) { updater_data.path = KEY_FILE; updater_data.fsize = CA_KEY_SIZE; } else { sl_LockObjUnlock (&updater_LockObj); return false; } return true; } bool updater_start (void) { _u32 AccessModeAndMaxSize = FS_MODE_OPEN_WRITE; SlFsFileInfo_t FsFileInfo; bool result = false; sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); if (0 != sl_FsGetInfo((_u8 *)updater_data.path, 0, &FsFileInfo)) { // file doesn't exist, create it AccessModeAndMaxSize = FS_MODE_OPEN_CREATE(updater_data.fsize, 0); } if (!sl_FsOpen((_u8 *)updater_data.path, AccessModeAndMaxSize, NULL, &updater_data.fhandle)) { updater_data.foffset = 0; result = true; } sl_LockObjUnlock (&wlan_LockObj); return result; } bool updater_write (uint8_t *buf, uint32_t len) { bool result = false; sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); if (len == sl_FsWrite(updater_data.fhandle, updater_data.foffset, buf, len)) { updater_data.foffset += len; result = true; } sl_LockObjUnlock (&wlan_LockObj); return result; } void updater_finnish (void) { _i32 fhandle; if (updater_data.fhandle > 0) { sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); // close the file being updated sl_FsClose(updater_data.fhandle, NULL, NULL, 0); #ifdef WIPY // if we still have an image pending for verification, leave the boot info as it is if (!strncmp(IMG_PREFIX, updater_data.path, strlen(IMG_PREFIX)) && sBootInfo.Status != IMG_STATUS_CHECK) { #else if (!strncmp(IMG_PREFIX, updater_data.path, strlen(IMG_PREFIX))) { #endif #ifdef DEBUG if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) { ASSERT (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))); sl_FsClose(fhandle, 0, 0, 0); #endif // open the boot info file for writing ASSERT (sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle) == 0); #ifdef DEBUG } else { // the boot info file doesn't exist yet _u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ; ASSERT (sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)), BootInfoCreateFlag), NULL, &fhandle) == 0); } #endif // save the new boot info #ifdef WIPY sBootInfo.PrevImg = sBootInfo.ActiveImg; if (sBootInfo.ActiveImg == IMG_ACT_UPDATE1) { sBootInfo.ActiveImg = IMG_ACT_UPDATE2; } else { sBootInfo.ActiveImg = IMG_ACT_UPDATE1; } // the launchxl doesn't have enough flash space for 2 user updates #else sBootInfo.PrevImg = IMG_ACT_FACTORY; sBootInfo.ActiveImg = IMG_ACT_UPDATE1; #endif sBootInfo.Status = IMG_STATUS_CHECK; ASSERT (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))); sl_FsClose(fhandle, 0, 0, 0); } sl_LockObjUnlock (&wlan_LockObj); updater_data.fhandle = -1; } sl_LockObjUnlock (&updater_LockObj); } micropython-1.12/ports/cc3200/ftp/updater.h000066400000000000000000000031441357706137100204730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_FTP_UPDATER_H #define MICROPY_INCLUDED_CC3200_FTP_UPDATER_H extern void updater_pre_init (void); extern bool updater_check_path (void *path); extern bool updater_start (void); extern bool updater_write (uint8_t *buf, uint32_t len); extern void updater_finnish (void); extern bool updater_verify (uint8_t *rbuff, uint8_t *hasbuff); #endif // MICROPY_INCLUDED_CC3200_FTP_UPDATER_H micropython-1.12/ports/cc3200/hal/000077500000000000000000000000001357706137100166275ustar00rootroot00000000000000micropython-1.12/ports/cc3200/hal/adc.c000066400000000000000000000501331357706137100175240ustar00rootroot00000000000000//***************************************************************************** // // adc.c // // Driver for the ADC module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup ADC_Analog_to_Digital_Converter_api //! @{ // //***************************************************************************** #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "inc/hw_ints.h" #include "inc/hw_adc.h" #include "inc/hw_apps_config.h" #include "interrupt.h" #include "adc.h" //***************************************************************************** // //! Enables the ADC //! //! \param ulBase is the base address of the ADC //! //! This function sets the ADC global enable //! //! \return None. // //***************************************************************************** void ADCEnable(unsigned long ulBase) { // // Set the global enable bit in the control register. // HWREG(ulBase + ADC_O_ADC_CTRL) |= 0x1; } //***************************************************************************** // //! Disable the ADC //! //! \param ulBase is the base address of the ADC //! //! This function clears the ADC global enable //! //! \return None. // //***************************************************************************** void ADCDisable(unsigned long ulBase) { // // Clear the global enable bit in the control register. // HWREG(ulBase + ADC_O_ADC_CTRL) &= ~0x1 ; } //***************************************************************************** // //! Enables specified ADC channel //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels //! //! This function enables specified ADC channel and configures the //! pin as analog pin. //! //! \return None. // //***************************************************************************** void ADCChannelEnable(unsigned long ulBase, unsigned long ulChannel) { unsigned long ulCh; ulCh = (ulChannel == ADC_CH_0)? 0x02 : (ulChannel == ADC_CH_1)? 0x04 : (ulChannel == ADC_CH_2)? 0x08 : 0x10; HWREG(ulBase + ADC_O_ADC_CH_ENABLE) |= ulCh; } //***************************************************************************** // //! Disables specified ADC channel //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channelsber //! //! This function disables specified ADC channel. //! //! \return None. // //***************************************************************************** void ADCChannelDisable(unsigned long ulBase, unsigned long ulChannel) { unsigned long ulCh; ulCh = (ulChannel == ADC_CH_0)? 0x02 : (ulChannel == ADC_CH_1)? 0x04 : (ulChannel == ADC_CH_2)? 0x08 : 0x10; HWREG(ulBase + ADC_O_ADC_CH_ENABLE) &= ~ulCh; } //***************************************************************************** // //! Enables and registers ADC interrupt handler for specified channel //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels //! \param pfnHandler is a pointer to the function to be called when the //! ADC channel interrupt occurs. //! //! This function enables and registers ADC interrupt handler for specified //! channel. Individual interrupt for each channel should be enabled using //! \sa ADCIntEnable(). It is the interrupt handler's responsibility to clear //! the interrupt source. //! //! The parameter \e ulChannel should be one of the following //! //! - \b ADC_CH_0 for channel 0 //! - \b ADC_CH_1 for channel 1 //! - \b ADC_CH_2 for channel 2 //! - \b ADC_CH_3 for channel 3 //! //! \return None. // //***************************************************************************** void ADCIntRegister(unsigned long ulBase, unsigned long ulChannel, void (*pfnHandler)(void)) { unsigned long ulIntNo; // // Get the interrupt number associted with the specified channel // ulIntNo = (ulChannel == ADC_CH_0)? INT_ADCCH0 : (ulChannel == ADC_CH_1)? INT_ADCCH1 : (ulChannel == ADC_CH_2)? INT_ADCCH2 : INT_ADCCH3; // // Register the interrupt handler // IntRegister(ulIntNo,pfnHandler); // // Enable ADC interrupt // IntEnable(ulIntNo); } //***************************************************************************** // //! Disables and unregisters ADC interrupt handler for specified channel //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels //! //! This function disables and unregisters ADC interrupt handler for specified //! channel. This function also masks off the interrupt in the interrupt //! controller so that the interrupt handler no longer is called. //! //! The parameter \e ulChannel should be one of the following //! //! - \b ADC_CH_0 for channel 0 //! - \b ADC_CH_1 for channel 1 //! - \b ADC_CH_2 for channel 2 //! - \b ADC_CH_3 for channel 3 //! //! \return None. // //***************************************************************************** void ADCIntUnregister(unsigned long ulBase, unsigned long ulChannel) { unsigned long ulIntNo; // // Get the interrupt number associted with the specified channel // ulIntNo = (ulChannel == ADC_CH_0)? INT_ADCCH0 : (ulChannel == ADC_CH_1)? INT_ADCCH1 : (ulChannel == ADC_CH_2)? INT_ADCCH2 : INT_ADCCH3; // // Disable ADC interrupt // IntDisable(ulIntNo); // // Unregister the interrupt handler // IntUnregister(ulIntNo); } //***************************************************************************** // //! Enables individual interrupt sources for specified channel //! //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated ADC interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The parameter \e ulChannel should be one of the following //! //! - \b ADC_CH_0 for channel 0 //! - \b ADC_CH_1 for channel 1 //! - \b ADC_CH_2 for channel 2 //! - \b ADC_CH_3 for channel 3 //! //! The \e ulIntFlags parameter is the logical OR of any of the following: //! - \b ADC_DMA_DONE for DMA done //! - \b ADC_FIFO_OVERFLOW for FIFO over flow //! - \b ADC_FIFO_UNDERFLOW for FIFO under flow //! - \b ADC_FIFO_EMPTY for FIFO empty //! - \b ADC_FIFO_FULL for FIFO full //! //! \return None. // //***************************************************************************** void ADCIntEnable(unsigned long ulBase, unsigned long ulChannel, unsigned long ulIntFlags) { unsigned long ulOffset; unsigned long ulDmaMsk; // // Enable DMA Done interrupt // if(ulIntFlags & ADC_DMA_DONE) { ulDmaMsk = (ulChannel == ADC_CH_0)?0x00001000: (ulChannel == ADC_CH_1)?0x00002000: (ulChannel == ADC_CH_2)?0x00004000:0x00008000; HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk; } ulIntFlags = ulIntFlags & 0x0F; // // Get the interrupt enable register offset for specified channel // ulOffset = ADC_O_adc_ch0_irq_en + ulChannel; // // Unmask the specified interrupts // HWREG(ulBase + ulOffset) |= (ulIntFlags & 0xf); } //***************************************************************************** // //! Disables individual interrupt sources for specified channel //! //! //! \param ulBase is the base address of the ADC. //! \param ulChannel is one of the valid ADC channels //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function disables the indicated ADC interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The parameters\e ulIntFlags and \e ulChannel should be as explained in //! ADCIntEnable(). //! //! \return None. // //***************************************************************************** void ADCIntDisable(unsigned long ulBase, unsigned long ulChannel, unsigned long ulIntFlags) { unsigned long ulOffset; unsigned long ulDmaMsk; // // Disable DMA Done interrupt // if(ulIntFlags & ADC_DMA_DONE) { ulDmaMsk = (ulChannel == ADC_CH_0)?0x00001000: (ulChannel == ADC_CH_1)?0x00002000: (ulChannel == ADC_CH_2)?0x00004000:0x00008000; HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk; } // // Get the interrupt enable register offset for specified channel // ulOffset = ADC_O_adc_ch0_irq_en + ulChannel; // // Unmask the specified interrupts // HWREG(ulBase + ulOffset) &= ~ulIntFlags; } //***************************************************************************** // //! Gets the current channel interrupt status //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels //! //! This function returns the interrupt status of the specified ADC channel. //! //! The parameter \e ulChannel should be as explained in \sa ADCIntEnable(). //! //! \return Return the ADC channel interrupt status, enumerated as a bit //! field of values described in ADCIntEnable() // //***************************************************************************** unsigned long ADCIntStatus(unsigned long ulBase, unsigned long ulChannel) { unsigned long ulOffset; unsigned long ulDmaMsk; unsigned long ulIntStatus; // // Get DMA Done interrupt status // ulDmaMsk = (ulChannel == ADC_CH_0)?0x00001000: (ulChannel == ADC_CH_1)?0x00002000: (ulChannel == ADC_CH_2)?0x00004000:0x00008000; ulIntStatus = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED)& ulDmaMsk; // // Get the interrupt enable register offset for specified channel // ulOffset = ADC_O_adc_ch0_irq_status + ulChannel; // // Read ADC interrupt status // ulIntStatus |= HWREG(ulBase + ulOffset) & 0xf; // // Return the current interrupt status // return(ulIntStatus); } //***************************************************************************** // //! Clears the current channel interrupt sources //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels //! \param ulIntFlags is the bit mask of the interrupt sources to be cleared. //! //! This function clears individual interrupt source for the specified //! ADC channel. //! //! The parameter \e ulChannel should be as explained in \sa ADCIntEnable(). //! //! \return None. // //***************************************************************************** void ADCIntClear(unsigned long ulBase, unsigned long ulChannel, unsigned long ulIntFlags) { unsigned long ulOffset; unsigned long ulDmaMsk; // // Clear DMA Done interrupt // if(ulIntFlags & ADC_DMA_DONE) { ulDmaMsk = (ulChannel == ADC_CH_0)?0x00001000: (ulChannel == ADC_CH_1)?0x00002000: (ulChannel == ADC_CH_2)?0x00004000:0x00008000; HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk; } // // Get the interrupt enable register offset for specified channel // ulOffset = ADC_O_adc_ch0_irq_status + ulChannel; // // Clear the specified interrupts // HWREG(ulBase + ulOffset) = (ulIntFlags & ~(ADC_DMA_DONE)); } //***************************************************************************** // //! Enables the ADC DMA operation for specified channel //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels //! //! This function enables the DMA operation for specified ADC channel //! //! The parameter \e ulChannel should be one of the following //! //! - \b ADC_CH_0 for channel 0 //! - \b ADC_CH_1 for channel 1 //! - \b ADC_CH_2 for channel 2 //! - \b ADC_CH_3 for channel 3 //! //! \return None. // //***************************************************************************** void ADCDMAEnable(unsigned long ulBase, unsigned long ulChannel) { unsigned long ulBitMask; // // Get the bit mask for enabling DMA for specified channel // ulBitMask = (ulChannel == ADC_CH_0)?0x01: (ulChannel == ADC_CH_1)?0x04: (ulChannel == ADC_CH_2)?0x10:0x40; // // Enable DMA request for the specified channel // HWREG(ulBase + ADC_O_adc_dma_mode_en) |= ulBitMask; } //***************************************************************************** // //! Disables the ADC DMA operation for specified channel //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels //! //! This function disables the DMA operation for specified ADC channel //! //! The parameter \e ulChannel should be one of the following //! //! - \b ADC_CH_0 for channel 0 //! - \b ADC_CH_1 for channel 1 //! - \b ADC_CH_2 for channel 2 //! - \b ADC_CH_3 for channel 3 //! //! \return None. // //***************************************************************************** void ADCDMADisable(unsigned long ulBase, unsigned long ulChannel) { unsigned long ulBitMask; // // Get the bit mask for disabling DMA for specified channel // ulBitMask = (ulChannel == ADC_CH_0)?0x01: (ulChannel == ADC_CH_1)?0x04: (ulChannel == ADC_CH_2)?0x10:0x40; // // Disable DMA request for the specified channel // HWREG(ulBase + ADC_O_adc_dma_mode_en) &= ~ulBitMask; } //***************************************************************************** // //! Configures the ADC internal timer //! //! \param ulBase is the base address of the ADC //! \param ulValue is wrap arround value of the timer //! //! This function Configures the ADC internal timer. The ADC timer is a 17 bit //! used to timestamp the ADC data samples internally. //! User can read the timestamp along with the sample from the FIFO register(s). //! Each sample in the FIFO contains 14 bit actual data and 18 bit timestamp //! //! The parameter \e ulValue can take any value between 0 - 2^17 //! //! \returns None. // //***************************************************************************** void ADCTimerConfig(unsigned long ulBase, unsigned long ulValue) { unsigned long ulReg; // // Read the currrent config // ulReg = HWREG(ulBase + ADC_O_adc_timer_configuration); // // Mask and set timer count field // ulReg = ((ulReg & ~0x1FFFF) | (ulValue & 0x1FFFF)); // // Set the timer count value // HWREG(ulBase + ADC_O_adc_timer_configuration) = ulReg; } //***************************************************************************** // //! Resets ADC internal timer //! //! \param ulBase is the base address of the ADC //! //! This function resets 17-bit ADC internal timer //! //! \returns None. // //***************************************************************************** void ADCTimerReset(unsigned long ulBase) { // // Reset the timer // HWREG(ulBase + ADC_O_adc_timer_configuration) |= (1 << 24); } //***************************************************************************** // //! Enables ADC internal timer //! //! \param ulBase is the base address of the ADC //! //! This function enables 17-bit ADC internal timer //! //! \returns None. // //***************************************************************************** void ADCTimerEnable(unsigned long ulBase) { // // Enable the timer // HWREG(ulBase + ADC_O_adc_timer_configuration) |= (1 << 25); } //***************************************************************************** // //! Disables ADC internal timer //! //! \param ulBase is the base address of the ADC //! //! This function disables 17-bit ADC internal timer //! //! \returns None. // //***************************************************************************** void ADCTimerDisable(unsigned long ulBase) { // // Disable the timer // HWREG(ulBase + ADC_O_adc_timer_configuration) &= ~(1 << 25); } //***************************************************************************** // //! Gets the current value of ADC internal timer //! //! \param ulBase is the base address of the ADC //! //! This function the current value of 17-bit ADC internal timer //! //! \returns Return the current value of ADC internal timer. // //***************************************************************************** unsigned long ADCTimerValueGet(unsigned long ulBase) { return(HWREG(ulBase + ADC_O_adc_timer_current_count)); } //***************************************************************************** // //! Gets the current FIFO level for specified ADC channel //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels. //! //! This function returns the current FIFO level for specified ADC channel. //! //! The parameter \e ulChannel should be one of the following //! //! - \b ADC_CH_0 for channel 0 //! - \b ADC_CH_1 for channel 1 //! - \b ADC_CH_2 for channel 2 //! - \b ADC_CH_3 for channel 3 //! //! \returns Return the current FIFO level for specified channel // //***************************************************************************** unsigned char ADCFIFOLvlGet(unsigned long ulBase, unsigned long ulChannel) { unsigned long ulOffset; // // Get the fifo level register offset for specified channel // ulOffset = ADC_O_adc_ch0_fifo_lvl + ulChannel; // // Return FIFO level // return(HWREG(ulBase + ulOffset) & 0x7); } //***************************************************************************** // //! Reads FIFO for specified ADC channel //! //! \param ulBase is the base address of the ADC //! \param ulChannel is one of the valid ADC channels. //! //! This function returns one data sample from the channel fifo as specified by //! \e ulChannel parameter. //! //! The parameter \e ulChannel should be one of the following //! //! - \b ADC_CH_0 for channel 0 //! - \b ADC_CH_1 for channel 1 //! - \b ADC_CH_2 for channel 2 //! - \b ADC_CH_3 for channel 3 //! //! \returns Return one data sample from the channel fifo. // //***************************************************************************** unsigned long ADCFIFORead(unsigned long ulBase, unsigned long ulChannel) { unsigned long ulOffset; // // Get the fifo register offset for specified channel // ulOffset = ADC_O_channel0FIFODATA + ulChannel; // // Return FIFO level // return(HWREG(ulBase + ulOffset)); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/adc.h000066400000000000000000000116551357706137100175370ustar00rootroot00000000000000//***************************************************************************** // // adc.h // // Defines and Macros for the ADC. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __ADC_H__ #define __ADC_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // Values that can be passed to APIs as ulChannel parameter //***************************************************************************** #define ADC_CH_0 0x00000000 #define ADC_CH_1 0x00000008 #define ADC_CH_2 0x00000010 #define ADC_CH_3 0x00000018 //***************************************************************************** // // Values that can be passed to ADCIntEnable(), ADCIntDisable() // and ADCIntClear() as ulIntFlags, and returned from ADCIntStatus() // //***************************************************************************** #define ADC_DMA_DONE 0x00000010 #define ADC_FIFO_OVERFLOW 0x00000008 #define ADC_FIFO_UNDERFLOW 0x00000004 #define ADC_FIFO_EMPTY 0x00000002 #define ADC_FIFO_FULL 0x00000001 //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void ADCEnable(unsigned long ulBase); extern void ADCDisable(unsigned long ulBase); extern void ADCChannelEnable(unsigned long ulBase,unsigned long ulChannel); extern void ADCChannelDisable(unsigned long ulBase,unsigned long ulChannel); extern void ADCIntRegister(unsigned long ulBase, unsigned long ulChannel, void (*pfnHandler)(void)); extern void ADCIntUnregister(unsigned long ulBase, unsigned long ulChannel); extern void ADCIntEnable(unsigned long ulBase, unsigned long ulChannel, unsigned long ulIntFlags); extern void ADCIntDisable(unsigned long ulBase, unsigned long ulChannel, unsigned long ulIntFlags); extern unsigned long ADCIntStatus(unsigned long ulBase,unsigned long ulChannel); extern void ADCIntClear(unsigned long ulBase, unsigned long ulChannel, unsigned long ulIntFlags); extern void ADCDMAEnable(unsigned long ulBase, unsigned long ulChannel); extern void ADCDMADisable(unsigned long ulBase, unsigned long ulChannel); extern void ADCTimerConfig(unsigned long ulBase, unsigned long ulValue); extern void ADCTimerEnable(unsigned long ulBase); extern void ADCTimerDisable(unsigned long ulBase); extern void ADCTimerReset(unsigned long ulBase); extern unsigned long ADCTimerValueGet(unsigned long ulBase); extern unsigned char ADCFIFOLvlGet(unsigned long ulBase, unsigned long ulChannel); extern unsigned long ADCFIFORead(unsigned long ulBase, unsigned long ulChannel); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __ADC_H__ micropython-1.12/ports/cc3200/hal/aes.c000066400000000000000000001325521357706137100175530ustar00rootroot00000000000000//***************************************************************************** // // aes.c // // Driver for the AES module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup AES_Advanced_Encryption_Standard_api //! @{ // //***************************************************************************** #include #include #include "inc/hw_aes.h" #include "inc/hw_dthe.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_nvic.h" #include "inc/hw_types.h" #include "aes.h" #include "debug.h" #include "interrupt.h" #define AES_BLOCK_SIZE_IN_BYTES 16 //***************************************************************************** // //! Configures the AES module. //! //! \param ui32Base is the base address of the AES module. //! \param ui32Config is the configuration of the AES module. //! //! This function configures the AES module based on the specified parameters. //! It does not change any DMA- or interrupt-related parameters. //! //! The ui32Config parameter is a bit-wise OR of a number of configuration //! flags. The valid flags are grouped based on their function. //! //! The direction of the operation is specified with only of following flags: //! //! - \b AES_CFG_DIR_ENCRYPT - Encryption mode //! - \b AES_CFG_DIR_DECRYPT - Decryption mode //! //! The key size is specified with only one of the following flags: //! //! - \b AES_CFG_KEY_SIZE_128BIT - Key size of 128 bits //! - \b AES_CFG_KEY_SIZE_192BIT - Key size of 192 bits //! - \b AES_CFG_KEY_SIZE_256BIT - Key size of 256 bits //! //! The mode of operation is specified with only one of the following flags. //! //! - \b AES_CFG_MODE_ECB - Electronic codebook mode //! - \b AES_CFG_MODE_CBC - Cipher-block chaining mode //! - \b AES_CFG_MODE_CFB - Cipher feedback mode //! - \b AES_CFG_MODE_CTR - Counter mode //! - \b AES_CFG_MODE_ICM - Integer counter mode //! - \b AES_CFG_MODE_XTS - Ciphertext stealing mode //! - \b AES_CFG_MODE_XTS_TWEAKJL - XEX-based tweaked-codebook mode with //! ciphertext stealing with previous/intermediate tweak value and j loaded //! - \b AES_CFG_MODE_XTS_K2IJL - XEX-based tweaked-codebook mode with //! ciphertext stealing with key2, i and j loaded //! - \b AES_CFG_MODE_XTS_K2ILJ0 - XEX-based tweaked-codebook mode with //! ciphertext stealing with key2 and i loaded, j = 0 //! - \b AES_CFG_MODE_F8 - F8 mode //! - \b AES_CFG_MODE_F9 - F9 mode //! - \b AES_CFG_MODE_CBCMAC - Cipher block chaining message authentication //! code mode //! - \b AES_CFG_MODE_GCM - Galois/counter mode //! - \b AES_CFG_MODE_GCM_HLY0ZERO - Galois/counter mode with GHASH with H //! loaded and Y0-encrypted forced to zero //! - \b AES_CFG_MODE_GCM_HLY0CALC - Galois/counter mode with GHASH with H //! loaded and Y0-encrypted calculated internally //! - \b AES_CFG_MODE_GCM_HY0CALC - Galois/Counter mode with autonomous GHASH //! (both H and Y0-encrypted calculated internally) //! - \b AES_CFG_MODE_CCM - Counter with CBC-MAC mode //! //! The following defines are used to specify the counter width. It is only //! required to be defined when using CTR, CCM, or GCM modes, only one of the //! following defines must be used to specify the counter width length: //! //! - \b AES_CFG_CTR_WIDTH_32 - Counter is 32 bits //! - \b AES_CFG_CTR_WIDTH_64 - Counter is 64 bits //! - \b AES_CFG_CTR_WIDTH_96 - Counter is 96 bits //! - \b AES_CFG_CTR_WIDTH_128 - Counter is 128 bits //! //! Only one of the following defines must be used to specify the length field //! for CCM operations (L): //! //! - \b AES_CFG_CCM_L_2 - 2 bytes //! - \b AES_CFG_CCM_L_4 - 4 bytes //! - \b AES_CFG_CCM_L_8 - 8 bytes //! //! Only one of the following defines must be used to specify the length of the //! authentication field for CCM operations (M) through the \e ui32Config //! argument in the AESConfigSet() function: //! //! - \b AES_CFG_CCM_M_4 - 4 bytes //! - \b AES_CFG_CCM_M_6 - 6 bytes //! - \b AES_CFG_CCM_M_8 - 8 bytes //! - \b AES_CFG_CCM_M_10 - 10 bytes //! - \b AES_CFG_CCM_M_12 - 12 bytes //! - \b AES_CFG_CCM_M_14 - 14 bytes //! - \b AES_CFG_CCM_M_16 - 16 bytes //! //! \return None. // //***************************************************************************** void AESConfigSet(uint32_t ui32Base, uint32_t ui32Config) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); ASSERT((ui32Config & AES_CFG_DIR_ENCRYPT) || (ui32Config & AES_CFG_DIR_DECRYPT)); ASSERT((ui32Config & AES_CFG_KEY_SIZE_128BIT) || (ui32Config & AES_CFG_KEY_SIZE_192BIT) || (ui32Config & AES_CFG_KEY_SIZE_256BIT)); ASSERT((ui32Config & AES_CFG_MODE_ECB) || (ui32Config & AES_CFG_MODE_CBC) || (ui32Config & AES_CFG_MODE_CTR) || (ui32Config & AES_CFG_MODE_ICM) || (ui32Config & AES_CFG_MODE_CFB) || (ui32Config & AES_CFG_MODE_XTS_TWEAKJL) || (ui32Config & AES_CFG_MODE_XTS_K2IJL) || (ui32Config & AES_CFG_MODE_XTS_K2ILJ0) || (ui32Config & AES_CFG_MODE_F8) || (ui32Config & AES_CFG_MODE_F9) || (ui32Config & AES_CFG_MODE_CTR) || (ui32Config & AES_CFG_MODE_CBCMAC) || (ui32Config & AES_CFG_MODE_GCM_HLY0ZERO) || (ui32Config & AES_CFG_MODE_GCM_HLY0CALC) || (ui32Config & AES_CFG_MODE_GCM_HY0CALC) || (ui32Config & AES_CFG_MODE_CCM)); ASSERT(((ui32Config & AES_CFG_MODE_CTR) || (ui32Config & AES_CFG_MODE_GCM_HLY0ZERO) || (ui32Config & AES_CFG_MODE_GCM_HLY0CALC) || (ui32Config & AES_CFG_MODE_GCM_HY0CALC) || (ui32Config & AES_CFG_MODE_CCM)) && ((ui32Config & AES_CFG_CTR_WIDTH_32) || (ui32Config & AES_CFG_CTR_WIDTH_64) || (ui32Config & AES_CFG_CTR_WIDTH_96) || (ui32Config & AES_CFG_CTR_WIDTH_128))); ASSERT((ui32Config & AES_CFG_MODE_CCM) && ((ui32Config & AES_CFG_CCM_L_2) || (ui32Config & AES_CFG_CCM_L_4) || (ui32Config & AES_CFG_CCM_L_8)) && ((ui32Config & AES_CFG_CCM_M_4) || (ui32Config & AES_CFG_CCM_M_6) || (ui32Config & AES_CFG_CCM_M_8) || (ui32Config & AES_CFG_CCM_M_10) || (ui32Config & AES_CFG_CCM_M_12) || (ui32Config & AES_CFG_CCM_M_14) || (ui32Config & AES_CFG_CCM_M_16))); // // Backup the save context field before updating the register. // if(HWREG(ui32Base + AES_O_CTRL) & AES_CTRL_SAVE_CONTEXT) { ui32Config |= AES_CTRL_SAVE_CONTEXT; } // // Write the CTRL register with the new value // HWREG(ui32Base + AES_O_CTRL) = ui32Config; } //***************************************************************************** // //! Writes the key 1 configuration registers, which are used for encryption or //! decryption. //! //! \param ui32Base is the base address for the AES module. //! \param pui8Key is an array of bytes, containing the key to be //! configured. The least significant word in the 0th index. //! \param ui32Keysize is the size of the key, which must be one of the //! following values: \b AES_CFG_KEY_SIZE_128, \b AES_CFG_KEY_SIZE_192, or //! \b AES_CFG_KEY_SIZE_256. //! //! This function writes key 1 configuration registers based on the key //! size. This function is used in all modes. //! //! \return None. // //***************************************************************************** void AESKey1Set(uint32_t ui32Base, uint8_t *pui8Key, uint32_t ui32Keysize) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); ASSERT((ui32Keysize == AES_CFG_KEY_SIZE_128BIT) || (ui32Keysize == AES_CFG_KEY_SIZE_192BIT) || (ui32Keysize == AES_CFG_KEY_SIZE_256BIT)); // // With all key sizes, the first 4 words are written. // HWREG(ui32Base + AES_O_KEY1_0) = * ((uint32_t *)(pui8Key + 0)); HWREG(ui32Base + AES_O_KEY1_1) = * ((uint32_t *)(pui8Key + 4)); HWREG(ui32Base + AES_O_KEY1_2) = * ((uint32_t *)(pui8Key + 8)); HWREG(ui32Base + AES_O_KEY1_3) = * ((uint32_t *)(pui8Key + 12)); // // The key is 192 or 256 bits. Write the next 2 words. // if(ui32Keysize != AES_CFG_KEY_SIZE_128BIT) { HWREG(ui32Base + AES_O_KEY1_4) = * ((uint32_t *)(pui8Key + 16)); HWREG(ui32Base + AES_O_KEY1_5) = * ((uint32_t *)(pui8Key + 20)); } // // The key is 256 bits. Write the last 2 words. // if(ui32Keysize == AES_CFG_KEY_SIZE_256BIT) { HWREG(ui32Base + AES_O_KEY1_6) = * ((uint32_t *)(pui8Key + 24)); HWREG(ui32Base + AES_O_KEY1_7) = * ((uint32_t *)(pui8Key + 28)); } } //***************************************************************************** // //! Writes the key 2 configuration registers, which are used for encryption or //! decryption. //! //! \param ui32Base is the base address for the AES module. //! \param pui8Key is an array of bytes, containing the key to be //! configured. The least significant word in the 0th index. //! \param ui32Keysize is the size of the key, which must be one of the //! following values: \b AES_CFG_KEY_SIZE_128, \b AES_CFG_KEY_SIZE_192, or //! \b AES_CFG_KEY_SIZE_256. //! //! This function writes the key 2 configuration registers based on the key //! size. This function is used in the F8, F9, XTS, CCM, and CBC-MAC modes. //! //! \return None. // //***************************************************************************** void AESKey2Set(uint32_t ui32Base, uint8_t *pui8Key, uint32_t ui32Keysize) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); ASSERT((ui32Keysize == AES_CFG_KEY_SIZE_128BIT) || (ui32Keysize == AES_CFG_KEY_SIZE_192BIT) || (ui32Keysize == AES_CFG_KEY_SIZE_256BIT)); // // With all key sizes, the first 4 words are written. // HWREG(ui32Base + AES_O_KEY2_0) = * ((uint32_t *)(pui8Key + 0)); HWREG(ui32Base + AES_O_KEY2_1) = * ((uint32_t *)(pui8Key + 4)); HWREG(ui32Base + AES_O_KEY2_2) = * ((uint32_t *)(pui8Key + 8)); HWREG(ui32Base + AES_O_KEY2_3) = * ((uint32_t *)(pui8Key + 12)); // // The key is 192 or 256 bits. Write the next 2 words. // if(ui32Keysize != AES_CFG_KEY_SIZE_128BIT) { HWREG(ui32Base + AES_O_KEY2_4) = * ((uint32_t *)(pui8Key + 16)); HWREG(ui32Base + AES_O_KEY2_5) = * ((uint32_t *)(pui8Key + 20)); } // // The key is 256 bits. Write the last 2 words. // if(ui32Keysize == AES_CFG_KEY_SIZE_256BIT) { HWREG(ui32Base + AES_O_KEY2_6) = * ((uint32_t *)(pui8Key + 24)); HWREG(ui32Base + AES_O_KEY2_7) = * ((uint32_t *)(pui8Key + 28)); } } //***************************************************************************** // //! Writes key 3 configuration registers, which are used for encryption or //! decryption. //! //! \param ui32Base is the base address for the AES module. //! \param pui8Key is a pointer to an array bytes, containing //! the key to be configured. The least significant word is in the 0th index. //! //! This function writes the key 2 configuration registers with key 3 data //! used in CBC-MAC and F8 modes. This key is always 128 bits. //! //! \return None. // //***************************************************************************** void AESKey3Set(uint32_t ui32Base, uint8_t *pui8Key) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Write the key into the upper 4 key registers // HWREG(ui32Base + AES_O_KEY2_4) = * ((uint32_t *)(pui8Key + 0)); HWREG(ui32Base + AES_O_KEY2_5) = * ((uint32_t *)(pui8Key + 4)); HWREG(ui32Base + AES_O_KEY2_6) = * ((uint32_t *)(pui8Key + 8)); HWREG(ui32Base + AES_O_KEY2_7) = * ((uint32_t *)(pui8Key + 12)); } //***************************************************************************** // //! Writes the Initial Vector (IV) register, needed in some of the AES Modes. //! //! \param ui32Base is the base address of the AES module. //! \param pui8IVdata is an array of 16 bytes (128 bits), containing the IV //! value to be configured. The least significant word is in the 0th index. //! //! This functions writes the initial vector registers in the AES module. //! //! \return None. // //***************************************************************************** void AESIVSet(uint32_t ui32Base, uint8_t *pui8IVdata) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Write the initial vector registers. // HWREG(ui32Base + AES_O_IV_IN_0) = *((uint32_t *)(pui8IVdata+0)); HWREG(ui32Base + AES_O_IV_IN_1) = *((uint32_t *)(pui8IVdata+4)); HWREG(ui32Base + AES_O_IV_IN_2) = *((uint32_t *)(pui8IVdata+8)); HWREG(ui32Base + AES_O_IV_IN_3) = *((uint32_t *)(pui8IVdata+12)); } //***************************************************************************** // //! Reads the Initial Vector (IV) register, needed in some of the AES Modes. //! //! \param ui32Base is the base address of the AES module. //! \param pui8IVdata is pointer to an array of 16 bytes. //! //! This functions reads the initial vector registers in the AES module. //! //! \return None. // //***************************************************************************** void AESIVGet(uint32_t ui32Base, uint8_t *pui8IVdata) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Write the initial vector registers. // *((uint32_t *)(pui8IVdata+ 0)) = HWREG(ui32Base + AES_O_IV_IN_0); *((uint32_t *)(pui8IVdata+ 4)) = HWREG(ui32Base + AES_O_IV_IN_1); *((uint32_t *)(pui8IVdata+ 8)) = HWREG(ui32Base + AES_O_IV_IN_2); *((uint32_t *)(pui8IVdata+12)) = HWREG(ui32Base + AES_O_IV_IN_3); } //***************************************************************************** // //! Saves the tag registers to a user-defined location. //! //! \param ui32Base is the base address of the AES module. //! \param pui8TagData is pointer to the location that stores the tag data. //! //! This function stores the tag data for use authenticated encryption and //! decryption operations. //! //! \return None. // //***************************************************************************** void AESTagRead(uint32_t ui32Base, uint8_t *pui8TagData) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Read the tag data. // *((uint32_t *)(pui8TagData+0)) = HWREG((ui32Base + AES_O_TAG_OUT_0)); *((uint32_t *)(pui8TagData+4)) = HWREG((ui32Base + AES_O_TAG_OUT_1)); *((uint32_t *)(pui8TagData+8)) = HWREG((ui32Base + AES_O_TAG_OUT_2)); *((uint32_t *)(pui8TagData+12)) = HWREG((ui32Base + AES_O_TAG_OUT_3)); } //***************************************************************************** // //! Used to set the write crypto data length in the AES module. //! //! \param ui32Base is the base address of the AES module. //! \param ui64Length is the crypto data length in bytes. //! //! This function stores the cryptographic data length in blocks for all modes. //! Data lengths up to (2^61 - 1) bytes are allowed. For GCM, any value up //! to (2^36 - 2) bytes are allowed because a 32-bit block counter is used. For //! basic modes (ECB/CBC/CTR/ICM/CFB128), zero can be programmed into the //! length field, indicating that the length is infinite. //! //! When this function is called, the engine is triggered to start using //! this context. //! //! \note This length does not include the authentication-only data used in //! some modes. Use the AESAuthLengthSet() function to specify the //! authentication data length. //! //! \return None // //***************************************************************************** void AESDataLengthSet(uint32_t ui32Base, uint64_t ui64Length) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Write the length register by shifting the 64-bit ui64Length. // HWREG(ui32Base + AES_O_C_LENGTH_0) = (uint32_t)(ui64Length); HWREG(ui32Base + AES_O_C_LENGTH_1) = (uint32_t)(ui64Length >> 32); } //***************************************************************************** // //! Sets the optional additional authentication data (AAD) length. //! //! \param ui32Base is the base address of the AES module. //! \param ui32Length is the length in bytes. //! //! This function is only used to write the authentication data length in the //! combined modes (GCM or CCM) and XTS mode. Supported AAD lengths for CCM //! are from 0 to (2^16 - 28) bytes. For GCM, any value up to (2^32 - 1) can //! be used. For XTS mode, this register is used to load j. Loading of j is //! only required if j != 0. j represents the sequential number of the 128-bit //! blocks inside the data unit. Consequently, j must be multiplied by 16 //! when passed to this function, thereby placing the block number in //! bits [31:4] of the register. //! //! When this function is called, the engine is triggered to start using //! this context for GCM and CCM. //! //! \return None // //***************************************************************************** void AESAuthDataLengthSet(uint32_t ui32Base, uint32_t ui32Length) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Write the length into the register. // HWREG(ui32Base + AES_O_AUTH_LENGTH) = ui32Length; } //***************************************************************************** // //! Reads plaintext/ciphertext from data registers without blocking. //! This api writes data in blocks //! //! \param ui32Base is the base address of the AES module. //! \param pui8Dest is a pointer to an array of words of data. //! \param ui8Length the length can be from 1 to 16 //! //! This function reads a block of either plaintext or ciphertext out of the //! AES module. If the output data is not ready, the function returns //! false. If the read completed successfully, the function returns true. //! A block is 16 bytes or 4 words. //! //! \return true or false. // //***************************************************************************** bool AESDataReadNonBlocking(uint32_t ui32Base, uint8_t *pui8Dest, uint8_t ui8Length) { volatile uint32_t pui32Dest[4]; uint8_t ui8BytCnt; uint8_t *pui8DestTemp; // // Check the arguments. // ASSERT(ui32Base == AES_BASE); if((ui8Length == 0)||(ui8Length>16)) { return(false); } // // Check if the output is ready before reading the data. If it not ready, // return false. // if((AES_CTRL_OUTPUT_READY & (HWREG(ui32Base + AES_O_CTRL))) == 0) { return(false); } // // Read a block of data from the data registers // pui32Dest[0] = HWREG(ui32Base + AES_O_DATA_IN_3); pui32Dest[1] = HWREG(ui32Base + AES_O_DATA_IN_2); pui32Dest[2] = HWREG(ui32Base + AES_O_DATA_IN_1); pui32Dest[3] = HWREG(ui32Base + AES_O_DATA_IN_0); // //Copy the data to a block memory // pui8DestTemp = (uint8_t *)pui32Dest; for(ui8BytCnt = 0; ui8BytCnt < ui8Length ; ui8BytCnt++) { *(pui8Dest+ui8BytCnt) = *(pui8DestTemp+ui8BytCnt); } // // Read successful, return true. // return(true); } //***************************************************************************** // //! Reads plaintext/ciphertext from data registers with blocking. //! This api writes data in blocks //! //! \param ui32Base is the base address of the AES module. //! \param pui8Dest is a pointer to an array of words. //! \param ui8Length is the length of data in bytes to be read. //! ui8Length can be from 1 to 16 //! //! This function reads a block of either plaintext or ciphertext out of the //! AES module. If the output is not ready, the function waits until it //! is ready. A block is 16 bytes or 4 words. //! //! \return None. // //***************************************************************************** void AESDataRead(uint32_t ui32Base, uint8_t *pui8Dest, uint8_t ui8Length) { volatile uint32_t pui32Dest[4]; uint8_t ui8BytCnt; uint8_t *pui8DestTemp; // // Check the arguments. // ASSERT(ui32Base == AES_BASE); if((ui8Length == 0)||(ui8Length>16)) { return; } // // Wait for the output to be ready before reading the data. // while((AES_CTRL_OUTPUT_READY & (HWREG(ui32Base + AES_O_CTRL))) == 0) { } // // Read a block of data from the data registers // pui32Dest[0] = HWREG(ui32Base + AES_O_DATA_IN_3); pui32Dest[1] = HWREG(ui32Base + AES_O_DATA_IN_2); pui32Dest[2] = HWREG(ui32Base + AES_O_DATA_IN_1); pui32Dest[3] = HWREG(ui32Base + AES_O_DATA_IN_0); // //Copy the data to a block memory // pui8DestTemp = (uint8_t *)pui32Dest; for(ui8BytCnt = 0; ui8BytCnt < ui8Length ; ui8BytCnt++) { *(pui8Dest+ui8BytCnt) = *(pui8DestTemp+ui8BytCnt); } return; } //***************************************************************************** // //! Writes plaintext/ciphertext to data registers without blocking. //! //! \param ui32Base is the base address of the AES module. //! \param pui8Src is a pointer to an array of words of data. //! \param ui8Length the length can be from 1 to 16 //! //! This function writes a block of either plaintext or ciphertext into the //! AES module. If the input is not ready, the function returns false //! If the write completed successfully, the function returns true. //! //! \return True or false. // //***************************************************************************** bool AESDataWriteNonBlocking(uint32_t ui32Base, uint8_t *pui8Src, uint8_t ui8Length) { volatile uint32_t pui32Src[4]={0,0,0,0}; uint8_t ui8BytCnt; uint8_t *pui8SrcTemp; // // Check the arguments. // ASSERT(ui32Base == AES_BASE); if((ui8Length == 0)||(ui8Length>16)) { return(false); } // // Check if the input is ready. If not, then return false. // if(!(AES_CTRL_INPUT_READY & (HWREG(ui32Base + AES_O_CTRL)))) { return(false); } // //Copy the data to a block memory // pui8SrcTemp = (uint8_t *)pui32Src; for(ui8BytCnt = 0; ui8BytCnt < ui8Length ; ui8BytCnt++) { *(pui8SrcTemp+ui8BytCnt) = *(pui8Src+ui8BytCnt); } // // Write a block of data into the data registers. // HWREG(ui32Base + AES_O_DATA_IN_3) = pui32Src[0]; HWREG(ui32Base + AES_O_DATA_IN_2) = pui32Src[1]; HWREG(ui32Base + AES_O_DATA_IN_1) = pui32Src[2]; HWREG(ui32Base + AES_O_DATA_IN_0) = pui32Src[3]; // // Write successful, return true. // return(true); } //***************************************************************************** // //! Writes plaintext/ciphertext to data registers with blocking. //! //! \param ui32Base is the base address of the AES module. //! \param pui8Src is a pointer to an array of bytes. //! \param ui8Length the length can be from 1 to 16 //! //! This function writes a block of either plaintext or ciphertext into the //! AES module. If the input is not ready, the function waits until it is //! ready before performing the write. //! //! \return None. // //***************************************************************************** void AESDataWrite(uint32_t ui32Base, uint8_t *pui8Src, uint8_t ui8Length) { volatile uint32_t pui32Src[4]={0,0,0,0}; uint8_t ui8BytCnt; uint8_t *pui8SrcTemp; // // Check the arguments. // ASSERT(ui32Base == AES_BASE); if((ui8Length == 0)||(ui8Length>16)) { return; } // // Wait for input ready. // while((AES_CTRL_INPUT_READY & (HWREG(ui32Base + AES_O_CTRL))) == 0) { } // //Copy the data to a block memory // pui8SrcTemp = (uint8_t *)pui32Src; for(ui8BytCnt = 0; ui8BytCnt < ui8Length ; ui8BytCnt++) { *(pui8SrcTemp+ui8BytCnt) = *(pui8Src+ui8BytCnt); } // // Write a block of data into the data registers. // HWREG(ui32Base + AES_O_DATA_IN_3) = pui32Src[0]; HWREG(ui32Base + AES_O_DATA_IN_2) = pui32Src[1]; HWREG(ui32Base + AES_O_DATA_IN_1) = pui32Src[2]; HWREG(ui32Base + AES_O_DATA_IN_0) = pui32Src[3]; } //***************************************************************************** // //! Used to process(transform) blocks of data, either encrypt or decrypt it. //! //! \param ui32Base is the base address of the AES module. //! \param pui8Src is a pointer to the memory location where the input data //! is stored. //! \param pui8Dest is a pointer to the memory location output is written. //! \param ui32Length is the length of the cryptographic data in bytes. //! //! This function iterates the encryption or decryption mechanism number over //! the data length. Before calling this function, ensure that the AES //! module is properly configured the key, data size, mode, etc. Only ECB, //! CBC, CTR, ICM, CFB, XTS and F8 operating modes should be used. The data //! is processed in 4-word (16-byte) blocks. //! //! \note This function only supports values of \e ui32Length less than 2^32, //! because the memory size is restricted to between 0 to 2^32 bytes. //! //! \return Returns true if data was processed successfully. Returns false //! if data processing failed. // //***************************************************************************** bool AESDataProcess(uint32_t ui32Base, uint8_t *pui8Src, uint8_t *pui8Dest, uint32_t ui32Length) { uint32_t ui32Count, ui32BlkCount, ui32ByteCount; // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Write the length register first, which triggers the engine to start // using this context. // AESDataLengthSet(AES_BASE, (uint64_t) ui32Length); // // Now loop until the blocks are written. // ui32BlkCount = ui32Length/16; for(ui32Count = 0; ui32Count < ui32BlkCount; ui32Count += 1) { // // Write the data registers. // AESDataWrite(ui32Base, pui8Src + (ui32Count*16) ,16); // // Read the data registers. // AESDataRead(ui32Base, pui8Dest + (ui32Count*16) ,16); } // //Now handle the residue bytes // ui32ByteCount = ui32Length%16; if(ui32ByteCount) { // // Write the data registers. // AESDataWrite(ui32Base, pui8Src + (16*ui32BlkCount) ,ui32ByteCount); // // Read the data registers. // AESDataRead(ui32Base, pui8Dest + (16*ui32BlkCount) ,ui32ByteCount); } // // Return true to indicate successful completion of the function. // return(true); } //***************************************************************************** // //! Used to generate message authentication code (MAC) using CBC-MAC and F9 mode. //! //! \param ui32Base is the base address of the AES module. //! \param pui8Src is a pointer to the memory location where the input data //! is stored. //! \param ui32Length is the length of the cryptographic data in bytes. //! \param pui8Tag is a pointer to a 4-word array where the hash tag is //! written. //! //! This function processes data to produce a hash tag that can be used tor //! authentication. Before calling this function, ensure that the AES //! module is properly configured the key, data size, mode, etc. Only //! CBC-MAC and F9 modes should be used. //! //! \return Returns true if data was processed successfully. Returns false //! if data processing failed. // //***************************************************************************** bool AESDataMAC(uint32_t ui32Base, uint8_t *pui8Src, uint32_t ui32Length, uint8_t *pui8Tag) { uint32_t ui32Count, ui32BlkCount, ui32ByteCount; // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Write the length register first, which triggers the engine to start // using this context. // AESDataLengthSet(AES_BASE, (uint64_t) ui32Length); // // Write the data registers. // // // Now loop until the blocks are written. // ui32BlkCount = ui32Length/16; for(ui32Count = 0; ui32Count < ui32BlkCount; ui32Count += 1) { // // Write the data registers. // AESDataWrite(ui32Base, pui8Src + ui32Count*16 ,16); } // //Now handle the residue bytes // ui32ByteCount = ui32Length%16; if(ui32ByteCount) { // // Write the data registers. // AESDataWrite(ui32Base, pui8Src + (ui32Count*ui32BlkCount) ,ui32ByteCount); } // // Wait for the context data regsiters to be ready. // while((AES_CTRL_SVCTXTRDY & (HWREG(AES_BASE + AES_O_CTRL))) == 0) { } // // Read the hash tag value. // AESTagRead(AES_BASE, pui8Tag); // // Return true to indicate successful completion of the function. // return(true); } //***************************************************************************** // //! Used for Authenticated encryption (AE) of the data. Processes and authenticates blocks of data, //! either encrypt the data or decrypt the data. //! //! \param ui32Base is the base address of the AES module. //! \param pui8Src is a pointer to the memory location where the input data //! is stored. The data must be padded to the 16-byte boundary. //! \param pui8Dest is a pointer to the memory location output is written. //! The space for written data must be rounded up to the 16-byte boundary. //! \param ui32Length is the length of the cryptographic data in bytes. //! \param pui8AuthSrc is a pointer to the memory location where the //! additional authentication data is stored. The data must be padded to the //! 16-byte boundary. //! \param ui32AuthLength is the length of the additional authentication //! data in bytes. //! \param pui8Tag is a pointer to a 4-word array where the hash tag is //! written. //! //! This function encrypts or decrypts blocks of data in addition to //! authentication data. A hash tag is also produced. Before calling this //! function, ensure that the AES module is properly configured the key, //! data size, mode, etc. Only CCM and GCM modes should be used. //! //! \return Returns true if data was processed successfully. Returns false //! if data processing failed. // //***************************************************************************** bool AESDataProcessAE(uint32_t ui32Base, uint8_t *pui8Src, uint8_t *pui8Dest, uint32_t ui32Length, uint8_t *pui8AuthSrc, uint32_t ui32AuthLength, uint8_t *pui8Tag) { uint32_t ui32Count; // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Set the data length. // AESDataLengthSet(AES_BASE, (uint64_t) ui32Length); // // Set the additional authentication data length. // AESAuthDataLengthSet(AES_BASE, ui32AuthLength); // // Now loop until the authentication data blocks are written. // for(ui32Count = 0; ui32Count < ui32AuthLength; ui32Count += 16) { // // Write the data registers. // AESDataWrite(ui32Base, pui8AuthSrc + (ui32Count),16); } // // Now loop until the data blocks are written. // for(ui32Count = 0; ui32Count < ui32Length; ui32Count += 16) { // // Write the data registers. // AESDataWrite(ui32Base, pui8Src + (ui32Count),16); // // // Read the data registers. // AESDataRead(ui32Base, pui8Dest + (ui32Count),16); } // // Wait for the context data regsiters to be ready. // while((AES_CTRL_SVCTXTRDY & (HWREG(AES_BASE + AES_O_CTRL))) == 0) { } // // Read the hash tag value. // AESTagRead(AES_BASE, pui8Tag); // // Return true to indicate successful completion of the function. // return(true); } //***************************************************************************** // //! Returns the current AES module interrupt status. //! //! \param ui32Base is the base address of the AES module. //! \param bMasked is \b false if the raw interrupt status is required and //! \b true if the masked interrupt status is required. //! //! \return Returns a bit mask of the interrupt sources, which is a logical OR //! of any of the following: //! //! - \b AES_INT_CONTEXT_IN - Context interrupt //! - \b AES_INT_CONTEXT_OUT - Authentication tag (and IV) interrupt. //! - \b AES_INT_DATA_IN - Data input interrupt //! - \b AES_INT_DATA_OUT - Data output interrupt //! - \b AES_INT_DMA_CONTEXT_IN - Context DMA done interrupt //! - \b AES_INT_DMA_CONTEXT_OUT - Authentication tag (and IV) DMA done //! interrupt //! - \b AES_INT_DMA_DATA_IN - Data input DMA done interrupt //! - \b AES_INT_DMA_DATA_OUT - Data output DMA done interrupt // //***************************************************************************** uint32_t AESIntStatus(uint32_t ui32Base, bool bMasked) { uint32_t ui32Temp; uint32_t ui32IrqEnable; // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Read the IRQ status register and return the value. // if(bMasked) { ui32Temp = HWREG(DTHE_BASE + DTHE_O_AES_MIS); ui32IrqEnable = HWREG(ui32Base + AES_O_IRQENABLE); return((HWREG(ui32Base + AES_O_IRQSTATUS) & ui32IrqEnable) | ((ui32Temp & 0x0000000F) << 16)); } else { ui32Temp = HWREG(DTHE_BASE + DTHE_O_AES_RIS); return(HWREG(ui32Base + AES_O_IRQSTATUS) | ((ui32Temp & 0x0000000F) << 16)); } } //***************************************************************************** // //! Enables AES module interrupts. //! //! \param ui32Base is the base address of the AES module. //! \param ui32IntFlags is a bit mask of the interrupt sources to enable. //! //! This function enables the interrupts in the AES module. The \e ui32IntFlags //! parameter is the logical OR of any of the following: //! //! - \b AES_INT_CONTEXT_IN - Context interrupt //! - \b AES_INT_CONTEXT_OUT - Authentication tag (and IV) interrupt //! - \b AES_INT_DATA_IN - Data input interrupt //! - \b AES_INT_DATA_OUT - Data output interrupt //! - \b AES_INT_DMA_CONTEXT_IN - Context DMA done interrupt //! - \b AES_INT_DMA_CONTEXT_OUT - Authentication tag (and IV) DMA done //! interrupt //! - \b AES_INT_DMA_DATA_IN - Data input DMA done interrupt //! - \b AES_INT_DMA_DATA_OUT - Data output DMA done interrupt //! //! \note Interrupts that have been previously been enabled are not disabled //! when this function is called. //! //! \return None. // //***************************************************************************** void AESIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); ASSERT((ui32IntFlags == AES_INT_CONTEXT_IN) || (ui32IntFlags == AES_INT_CONTEXT_OUT) || (ui32IntFlags == AES_INT_DATA_IN) || (ui32IntFlags == AES_INT_DATA_OUT) || (ui32IntFlags == AES_INT_DMA_CONTEXT_IN) || (ui32IntFlags == AES_INT_DMA_CONTEXT_OUT) || (ui32IntFlags == AES_INT_DMA_DATA_IN) || (ui32IntFlags == AES_INT_DMA_DATA_OUT)); // // Set the flags. // HWREG(DTHE_BASE + DTHE_O_AES_IM) &= ~((ui32IntFlags & 0x000F0000) >> 16); HWREG(ui32Base + AES_O_IRQENABLE) |= ui32IntFlags & 0x0000ffff; } //***************************************************************************** // //! Disables AES module interrupts. //! //! \param ui32Base is the base address of the AES module. //! \param ui32IntFlags is a bit mask of the interrupt sources to disable. //! //! This function disables the interrupt sources in the AES module. The //! \e ui32IntFlags parameter is the logical OR of any of the following: //! //! - \b AES_INT_CONTEXT_IN - Context interrupt //! - \b AES_INT_CONTEXT_OUT - Authentication tag (and IV) interrupt //! - \b AES_INT_DATA_IN - Data input interrupt //! - \b AES_INT_DATA_OUT - Data output interrupt //! - \b AES_INT_DMA_CONTEXT_IN - Context DMA done interrupt //! - \b AES_INT_DMA_CONTEXT_OUT - Authentication tag (and IV) DMA done //! interrupt //! - \b AES_INT_DMA_DATA_IN - Data input DMA done interrupt //! - \b AES_INT_DMA_DATA_OUT - Data output DMA done interrupt //! //! \note The DMA done interrupts are the only interrupts that can be cleared. //! The remaining interrupts can be disabled instead using AESIntDisable(). //! //! \return None. // //***************************************************************************** void AESIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); ASSERT((ui32IntFlags == AES_INT_CONTEXT_IN) || (ui32IntFlags == AES_INT_CONTEXT_OUT) || (ui32IntFlags == AES_INT_DATA_IN) || (ui32IntFlags == AES_INT_DATA_OUT) || (ui32IntFlags == AES_INT_DMA_CONTEXT_IN) || (ui32IntFlags == AES_INT_DMA_CONTEXT_OUT) || (ui32IntFlags == AES_INT_DMA_DATA_IN) || (ui32IntFlags == AES_INT_DMA_DATA_OUT)); // // Clear the flags. // HWREG(DTHE_BASE + DTHE_O_AES_IM) |= ((ui32IntFlags & 0x000F0000) >> 16); HWREG(ui32Base + AES_O_IRQENABLE) &= ~(ui32IntFlags & 0x0000ffff); } //***************************************************************************** // //! Clears AES module interrupts. //! //! \param ui32Base is the base address of the AES module. //! \param ui32IntFlags is a bit mask of the interrupt sources to disable. //! //! This function clears the interrupt sources in the AES module. The //! \e ui32IntFlags parameter is the logical OR of any of the following: //! //! - \b AES_INT_DMA_CONTEXT_IN - Context DMA done interrupt //! - \b AES_INT_DMA_CONTEXT_OUT - Authentication tag (and IV) DMA done //! interrupt //! - \b AES_INT_DMA_DATA_IN - Data input DMA done interrupt //! - \b AES_INT_DMA_DATA_OUT - Data output DMA done interrupt //! //! \note Only the DMA done interrupts can be cleared. The remaining //! interrupts should be disabled with AESIntDisable(). //! //! \return None. // //***************************************************************************** void AESIntClear(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); ASSERT((ui32IntFlags == AES_INT_DMA_CONTEXT_IN) || (ui32IntFlags == AES_INT_DMA_CONTEXT_OUT) || (ui32IntFlags == AES_INT_DMA_DATA_IN) || (ui32IntFlags == AES_INT_DMA_DATA_OUT)); HWREG(DTHE_BASE + DTHE_O_AES_IC) = ((ui32IntFlags >> 16) & 0x0000000F); } //***************************************************************************** // //! Registers an interrupt handler for the AES module. //! //! \param ui32Base is the base address of the AES module. //! \param pfnHandler is a pointer to the function to be called when the //! enabled AES interrupts occur. //! //! This function registers the interrupt handler in the interrupt vector //! table, and enables AES interrupts on the interrupt controller; specific AES //! interrupt sources must be enabled using AESIntEnable(). The interrupt //! handler being registered must clear the source of the interrupt using //! AESIntClear(). //! //! If the application is using a static interrupt vector table stored in //! flash, then it is not necessary to register the interrupt handler this way. //! Instead, IntEnable() is used to enable AES interrupts on the //! interrupt controller. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void AESIntRegister(uint32_t ui32Base, void(*pfnHandler)(void)) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Register the interrupt handler. // IntRegister(INT_AES, pfnHandler); // // Enable the interrupt // IntEnable(INT_AES); } //***************************************************************************** // //! Unregisters an interrupt handler for the AES module. //! //! \param ui32Base is the base address of the AES module. //! //! This function unregisters the previously registered interrupt handler and //! disables the interrupt in the interrupt controller. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void AESIntUnregister(uint32_t ui32Base) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); // // Disable the interrupt. // IntDisable(INT_AES); // // Unregister the interrupt handler. // IntUnregister(INT_AES); } //***************************************************************************** // //! Enables uDMA requests for the AES module. //! //! \param ui32Base is the base address of the AES module. //! \param ui32Flags is a bit mask of the uDMA requests to be enabled. //! //! This function enables the uDMA request sources in the AES module. //! The \e ui32Flags parameter is the logical OR of any of the following: //! //! - \b AES_DMA_DATA_IN //! - \b AES_DMA_DATA_OUT //! - \b AES_DMA_CONTEXT_IN //! - \b AES_DMA_CONTEXT_OUT //! //! \return None. // //***************************************************************************** void AESDMAEnable(uint32_t ui32Base, uint32_t ui32Flags) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); ASSERT((ui32Flags == AES_DMA_DATA_IN) || (ui32Flags == AES_DMA_DATA_OUT) || (ui32Flags == AES_DMA_CONTEXT_IN) || (ui32Flags == AES_DMA_CONTEXT_OUT)); // // Set the flags in the current register value. // HWREG(ui32Base + AES_O_SYSCONFIG) |= ui32Flags; } //***************************************************************************** // //! Disables uDMA requests for the AES module. //! //! \param ui32Base is the base address of the AES module. //! \param ui32Flags is a bit mask of the uDMA requests to be disabled. //! //! This function disables the uDMA request sources in the AES module. //! The \e ui32Flags parameter is the logical OR of any of the //! following: //! //! - \b AES_DMA_DATA_IN //! - \b AES_DMA_DATA_OUT //! - \b AES_DMA_CONTEXT_IN //! - \b AES_DMA_CONTEXT_OUT //! //! \return None. // //***************************************************************************** void AESDMADisable(uint32_t ui32Base, uint32_t ui32Flags) { // // Check the arguments. // ASSERT(ui32Base == AES_BASE); ASSERT((ui32Flags == AES_DMA_DATA_IN) || (ui32Flags == AES_DMA_DATA_OUT) || (ui32Flags == AES_DMA_CONTEXT_IN) || (ui32Flags == AES_DMA_CONTEXT_OUT)); // // Clear the flags in the current register value. // HWREG(ui32Base + AES_O_SYSCONFIG) &= ~ui32Flags; } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/aes.h000066400000000000000000000233741357706137100175610ustar00rootroot00000000000000//***************************************************************************** // // aes.h // // Defines and Macros for the AES module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __DRIVERLIB_AES_H__ #define __DRIVERLIB_AES_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // The following defines are used to specify the operation direction in the // ui32Config argument in the AESConfig function. Only one is permitted. // //***************************************************************************** #define AES_CFG_DIR_ENCRYPT 0x00000004 #define AES_CFG_DIR_DECRYPT 0x00000000 //***************************************************************************** // // The following defines are used to specify the key size in the ui32Config // argument in the AESConfig function. Only one is permitted. // //***************************************************************************** #define AES_CFG_KEY_SIZE_128BIT 0x00000008 #define AES_CFG_KEY_SIZE_192BIT 0x00000010 #define AES_CFG_KEY_SIZE_256BIT 0x00000018 //***************************************************************************** // // The following defines are used to specify the mode of operation in the // ui32Config argument in the AESConfig function. Only one is permitted. // //***************************************************************************** #define AES_CFG_MODE_M 0x2007fe60 #define AES_CFG_MODE_ECB 0x00000000 #define AES_CFG_MODE_CBC 0x00000020 #define AES_CFG_MODE_CTR 0x00000040 #define AES_CFG_MODE_ICM 0x00000200 #define AES_CFG_MODE_CFB 0x00000400 #define AES_CFG_MODE_XTS_TWEAKJL \ 0x00000800 #define AES_CFG_MODE_XTS_K2IJL \ 0x00001000 #define AES_CFG_MODE_XTS_K2ILJ0 \ 0x00001800 #define AES_CFG_MODE_F8 0x00002000 #define AES_CFG_MODE_F9 0x20004000 #define AES_CFG_MODE_CBCMAC 0x20008000 #define AES_CFG_MODE_GCM_HLY0ZERO \ 0x20010040 #define AES_CFG_MODE_GCM_HLY0CALC \ 0x20020040 #define AES_CFG_MODE_GCM_HY0CALC \ 0x20030040 #define AES_CFG_MODE_CCM 0x20040040 //***************************************************************************** // // The following defines are used to specify the counter width in the // ui32Config argument in the AESConfig function. It is only required to // be defined when using CTR, CCM, or GCM modes. Only one length is permitted. // //***************************************************************************** #define AES_CFG_CTR_WIDTH_32 0x00000000 #define AES_CFG_CTR_WIDTH_64 0x00000080 #define AES_CFG_CTR_WIDTH_96 0x00000100 #define AES_CFG_CTR_WIDTH_128 0x00000180 //***************************************************************************** // // The following defines are used to define the width of the length field for // CCM operation through the ui32Config argument in the AESConfig function. // This value is also known as L. Only one is permitted. // //***************************************************************************** #define AES_CFG_CCM_L_2 0x00080000 #define AES_CFG_CCM_L_4 0x00180000 #define AES_CFG_CCM_L_8 0x00380000 //***************************************************************************** // // The following defines are used to define the length of the authentication // field for CCM operations through the ui32Config argument in the AESConfig // function. This value is also known as M. Only one is permitted. // //***************************************************************************** #define AES_CFG_CCM_M_4 0x00400000 #define AES_CFG_CCM_M_6 0x00800000 #define AES_CFG_CCM_M_8 0x00c00000 #define AES_CFG_CCM_M_10 0x01000000 #define AES_CFG_CCM_M_12 0x01400000 #define AES_CFG_CCM_M_14 0x01800000 #define AES_CFG_CCM_M_16 0x01c00000 //***************************************************************************** // // Interrupt flags for use with the AESIntEnable, AESIntDisable, and // AESIntStatus functions. // //***************************************************************************** #define AES_INT_CONTEXT_IN 0x00000001 #define AES_INT_CONTEXT_OUT 0x00000008 #define AES_INT_DATA_IN 0x00000002 #define AES_INT_DATA_OUT 0x00000004 #define AES_INT_DMA_CONTEXT_IN 0x00010000 #define AES_INT_DMA_CONTEXT_OUT 0x00020000 #define AES_INT_DMA_DATA_IN 0x00040000 #define AES_INT_DMA_DATA_OUT 0x00080000 //***************************************************************************** // // Defines used when enabling and disabling DMA requests in the // AESEnableDMA and AESDisableDMA functions. // //***************************************************************************** #define AES_DMA_DATA_IN 0x00000040 #define AES_DMA_DATA_OUT 0x00000020 #define AES_DMA_CONTEXT_IN 0x00000080 #define AES_DMA_CONTEXT_OUT 0x00000100 //***************************************************************************** // // Function prototypes. // //***************************************************************************** extern void AESConfigSet(uint32_t ui32Base, uint32_t ui32Config); extern void AESKey1Set(uint32_t ui32Base, uint8_t *pui8Key, uint32_t ui32Keysize); extern void AESKey2Set(uint32_t ui32Base, uint8_t *pui8Key, uint32_t ui32Keysize); extern void AESKey3Set(uint32_t ui32Base, uint8_t *pui8Key); extern void AESIVSet(uint32_t ui32Base, uint8_t *pui8IVdata); extern void AESIVGet(uint32_t ui32Base, uint8_t *pui8IVdata); extern void AESTagRead(uint32_t ui32Base, uint8_t *pui8TagData); extern void AESDataLengthSet(uint32_t ui32Base, uint64_t ui64Length); extern void AESAuthDataLengthSet(uint32_t ui32Base, uint32_t ui32Length); extern bool AESDataReadNonBlocking(uint32_t ui32Base, uint8_t *pui8Dest, uint8_t ui8Length); extern void AESDataRead(uint32_t ui32Base, uint8_t *pui8Dest, uint8_t ui8Length); extern bool AESDataWriteNonBlocking(uint32_t ui32Base, uint8_t *pui8Src, uint8_t ui8Length); extern void AESDataWrite(uint32_t ui32Base, uint8_t *pui8Src, uint8_t ui8Length); extern bool AESDataProcess(uint32_t ui32Base, uint8_t *pui8Src, uint8_t *pui8Dest, uint32_t ui32Length); extern bool AESDataMAC(uint32_t ui32Base, uint8_t *pui8Src, uint32_t ui32Length, uint8_t *pui8Tag); extern bool AESDataProcessAE(uint32_t ui32Base, uint8_t *pui8Src, uint8_t *pui8Dest, uint32_t ui32Length, uint8_t *pui8AuthSrc, uint32_t ui32AuthLength, uint8_t *pui8Tag); extern uint32_t AESIntStatus(uint32_t ui32Base, bool bMasked); extern void AESIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags); extern void AESIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags); extern void AESIntClear(uint32_t ui32Base, uint32_t ui32IntFlags); extern void AESIntRegister(uint32_t ui32Base, void(*pfnHandler)(void)); extern void AESIntUnregister(uint32_t ui32Base); extern void AESDMAEnable(uint32_t ui32Base, uint32_t ui32Flags); extern void AESDMADisable(uint32_t ui32Base, uint32_t ui32Flags); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __DRIVERLIB_AES_H__ micropython-1.12/ports/cc3200/hal/cc3200_asm.h000066400000000000000000000060411357706137100205330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef CC3200_ASM_H_ #define CC3200_ASM_H_ // We have inlined IRQ functions for efficiency (they are generally // 1 machine instruction). // // Note on IRQ state: you should not need to know the specific // value of the state variable, but rather just pass the return // value from disable_irq back to enable_irq. If you really need // to know the machine-specific values, see irq.h. #ifndef __disable_irq #define __disable_irq() __asm__ volatile ("cpsid i"); #endif #ifndef DEBUG __attribute__(( always_inline )) static inline void __WFI(void) { __asm volatile (" dsb \n" " isb \n" " wfi \n"); } #else // For some reason the debugger gets disconnected when entering any of the sleep modes __attribute__(( always_inline )) static inline void __WFI(void) { __asm volatile (" dsb \n" " isb \n"); } #endif __attribute__(( always_inline )) static inline uint32_t __get_PRIMASK(void) { uint32_t result; __asm volatile ("mrs %0, primask" : "=r" (result)); return(result); } __attribute__(( always_inline )) static inline void __set_PRIMASK(uint32_t priMask) { __asm volatile ("msr primask, %0" : : "r" (priMask) : "memory"); } __attribute__(( always_inline )) static inline uint32_t __get_BASEPRI(void) { uint32_t result; __asm volatile ("mrs %0, basepri" : "=r" (result)); return(result); } __attribute__(( always_inline )) static inline void __set_BASEPRI(uint32_t value) { __asm volatile ("msr basepri, %0" : : "r" (value) : "memory"); } __attribute__(( always_inline )) static inline void enable_irq(mp_uint_t state) { __set_PRIMASK(state); } __attribute__(( always_inline )) static inline mp_uint_t disable_irq(void) { mp_uint_t state = __get_PRIMASK(); __disable_irq(); return state; } #endif /* CC3200_ASM_H_ */ micropython-1.12/ports/cc3200/hal/cc3200_hal.c000066400000000000000000000163011357706137100205120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /****************************************************************************** IMPORTS ******************************************************************************/ #include #include #include #include "py/mphal.h" #include "py/runtime.h" #include "py/objstr.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "hw_memmap.h" #include "rom_map.h" #include "interrupt.h" #include "systick.h" #include "prcm.h" #include "pin.h" #include "mpexception.h" #include "telnet.h" #include "pybuart.h" #include "utils.h" #include "irq.h" #include "moduos.h" #ifdef USE_FREERTOS #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #endif /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ #ifndef USE_FREERTOS static void hal_TickInit (void); #endif /****************************************************************************** DECLARE LOCAL DATA ******************************************************************************/ static volatile uint32_t HAL_tickCount; /****************************************************************************** DECLARE IMPORTED DATA ******************************************************************************/ extern void (* const g_pfnVectors[256])(void); /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ __attribute__ ((section (".boot"))) void HAL_SystemInit (void) { MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]); // in the case of a release image, these steps are already performed by // the bootloader so we can skip it and gain some code space #ifdef DEBUG MAP_IntMasterEnable(); PRCMCC3200MCUInit(); #endif #ifndef USE_FREERTOS hal_TickInit(); #endif } void HAL_SystemDeInit (void) { } void HAL_IncrementTick(void) { HAL_tickCount++; } mp_uint_t mp_hal_ticks_ms(void) { return HAL_tickCount; } // The SysTick timer counts down at HAL_FCPU_HZ, so we can use that knowledge // to grab a microsecond counter. mp_uint_t mp_hal_ticks_us(void) { mp_uint_t irq_state = disable_irq(); uint32_t counter = SysTickValueGet(); uint32_t milliseconds = mp_hal_ticks_ms(); enable_irq(irq_state); uint32_t load = SysTickPeriodGet(); counter = load - counter; // Convert from decrementing to incrementing return (milliseconds * 1000) + ((counter * 1000) / load); } void mp_hal_delay_ms(mp_uint_t delay) { // only if we are not within interrupt context and interrupts are enabled if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) { MP_THREAD_GIL_EXIT(); #ifdef USE_FREERTOS vTaskDelay (delay / portTICK_PERIOD_MS); #else uint32_t start = HAL_tickCount; // wraparound of tick is taken care of by 2's complement arithmetic. while (HAL_tickCount - start < delay) { // enter sleep mode, waiting for (at least) the SysTick interrupt. __WFI(); } #endif MP_THREAD_GIL_ENTER(); } else { for (int ms = 0; ms < delay; ms++) { UtilsDelay(UTILS_DELAY_US_TO_COUNT(1000)); } } } void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } void mp_hal_stdout_tx_strn(const char *str, size_t len) { if (MP_STATE_PORT(os_term_dup_obj)) { if (mp_obj_is_type(MP_STATE_PORT(os_term_dup_obj)->stream_o, &pyb_uart_type)) { uart_tx_strn(MP_STATE_PORT(os_term_dup_obj)->stream_o, str, len); } else { MP_STATE_PORT(os_term_dup_obj)->write[2] = mp_obj_new_str_of_type(&mp_type_str, (const byte *)str, len); mp_call_method_n_kw(1, 0, MP_STATE_PORT(os_term_dup_obj)->write); } } // and also to telnet telnet_tx_strn(str, len); } void mp_hal_stdout_tx_strn_cooked (const char *str, size_t len) { int32_t nslen = 0; const char *_str = str; for (int i = 0; i < len; i++) { if (str[i] == '\n') { mp_hal_stdout_tx_strn(_str, nslen); mp_hal_stdout_tx_strn("\r\n", 2); _str += nslen + 1; nslen = 0; } else { nslen++; } } if (_str < str + len) { mp_hal_stdout_tx_strn(_str, nslen); } } int mp_hal_stdin_rx_chr(void) { for ( ;; ) { // read telnet first if (telnet_rx_any()) { return telnet_rx_char(); } else if (MP_STATE_PORT(os_term_dup_obj)) { // then the stdio_dup if (mp_obj_is_type(MP_STATE_PORT(os_term_dup_obj)->stream_o, &pyb_uart_type)) { if (uart_rx_any(MP_STATE_PORT(os_term_dup_obj)->stream_o)) { return uart_rx_char(MP_STATE_PORT(os_term_dup_obj)->stream_o); } } else { MP_STATE_PORT(os_term_dup_obj)->read[2] = mp_obj_new_int(1); mp_obj_t data = mp_call_method_n_kw(1, 0, MP_STATE_PORT(os_term_dup_obj)->read); // data len is > 0 if (mp_obj_is_true(data)) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); return ((int *)(bufinfo.buf))[0]; } } } mp_hal_delay_ms(1); } } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ #ifndef USE_FREERTOS static void hal_TickInit (void) { HAL_tickCount = 0; MAP_SysTickIntRegister(HAL_IncrementTick); MAP_IntEnable(FAULT_SYSTICK); MAP_SysTickIntEnable(); MAP_SysTickPeriodSet(HAL_FCPU_HZ / HAL_SYSTICK_PERIOD_US); // Force a reload of the SysTick counter register HWREG(NVIC_ST_CURRENT) = 0; MAP_SysTickEnable(); } #endif micropython-1.12/ports/cc3200/hal/cc3200_hal.h000066400000000000000000000057051357706137100205250ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "hal/utils.h" #include "hal/systick.h" /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define HAL_FCPU_MHZ 80U #define HAL_FCPU_HZ (1000000U * HAL_FCPU_MHZ) #define HAL_SYSTICK_PERIOD_US 1000U #define UTILS_DELAY_US_TO_COUNT(us) (((us) * HAL_FCPU_MHZ) / 6) #define HAL_NVIC_INT_CTRL_REG (*((volatile uint32_t *) 0xE000ED04 ) ) #define HAL_VECTACTIVE_MASK (0x1FUL) /****************************************************************************** DEFINE TYPES ******************************************************************************/ /****************************************************************************** DEFINE FUNCTION-LIKE MACROS ******************************************************************************/ #define HAL_INTRODUCE_SYNC_BARRIER() { \ __asm(" dsb \n" \ " isb \n"); \ } /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ extern void HAL_SystemInit (void); extern void HAL_SystemDeInit (void); extern void HAL_IncrementTick(void); extern void mp_hal_set_interrupt_char (int c); #define mp_hal_stdio_poll(poll_flags) (0) // not implemented #define mp_hal_delay_us(usec) UtilsDelay(UTILS_DELAY_US_TO_COUNT(usec)) #define mp_hal_ticks_cpu() (SysTickPeriodGet() - SysTickValueGet()) micropython-1.12/ports/cc3200/hal/cpu.c000066400000000000000000000256251357706137100175740ustar00rootroot00000000000000//***************************************************************************** // // cpu.c // // Instruction wrappers for special CPU instructions needed by the // drivers. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #include "cpu.h" //***************************************************************************** // // Wrapper function for the CPSID instruction. Returns the state of PRIMASK // on entry. // //***************************************************************************** #if defined(gcc) unsigned long __attribute__((naked)) CPUcpsid(void) { unsigned long ulRet; // // Read PRIMASK and disable interrupts. // __asm(" mrs r0, PRIMASK\n" " cpsid i\n" " dsb \n" " isb \n" " bx lr\n" : "=r" (ulRet)); // // The return is handled in the inline assembly, but the compiler will // still complain if there is not an explicit return here (despite the fact // that this does not result in any code being produced because of the // naked attribute). // return(ulRet); } #endif #if defined(ewarm) unsigned long CPUcpsid(void) { // // Read PRIMASK and disable interrupts. // __asm(" mrs r0, PRIMASK\n" " cpsid i\n" " dsb \n" " isb \n"); // // "Warning[Pe940]: missing return statement at end of non-void function" // is suppressed here to avoid putting a "bx lr" in the inline assembly // above and a superfluous return statement here. // #pragma diag_suppress=Pe940 } #pragma diag_default=Pe940 #endif #if defined(ccs) unsigned long CPUcpsid(void) { // // Read PRIMASK and disable interrupts. // __asm(" mrs r0, PRIMASK\n" " cpsid i\n" " dsb \n" " isb \n" " bx lr\n"); // // The following keeps the compiler happy, because it wants to see a // return value from this function. It will generate code to return // a zero. However, the real return is the "bx lr" above, so the // return(0) is never executed and the function returns with the value // you expect in R0. // return(0); } #endif //***************************************************************************** // // Wrapper function returning the state of PRIMASK (indicating whether // interrupts are enabled or disabled). // //***************************************************************************** #if defined(gcc) unsigned long __attribute__((naked)) CPUprimask(void) { unsigned long ulRet; // // Read PRIMASK and disable interrupts. // __asm(" mrs r0, PRIMASK\n" " bx lr\n" : "=r" (ulRet)); // // The return is handled in the inline assembly, but the compiler will // still complain if there is not an explicit return here (despite the fact // that this does not result in any code being produced because of the // naked attribute). // return(ulRet); } #endif #if defined(ewarm) unsigned long CPUprimask(void) { // // Read PRIMASK and disable interrupts. // __asm(" mrs r0, PRIMASK\n"); // // "Warning[Pe940]: missing return statement at end of non-void function" // is suppressed here to avoid putting a "bx lr" in the inline assembly // above and a superfluous return statement here. // #pragma diag_suppress=Pe940 } #pragma diag_default=Pe940 #endif #if defined(ccs) unsigned long CPUprimask(void) { // // Read PRIMASK and disable interrupts. // __asm(" mrs r0, PRIMASK\n" " bx lr\n"); // // The following keeps the compiler happy, because it wants to see a // return value from this function. It will generate code to return // a zero. However, the real return is the "bx lr" above, so the // return(0) is never executed and the function returns with the value // you expect in R0. // return(0); } #endif //***************************************************************************** // // Wrapper function for the CPSIE instruction. Returns the state of PRIMASK // on entry. // //***************************************************************************** #if defined(gcc) unsigned long __attribute__((naked)) CPUcpsie(void) { unsigned long ulRet; // // Read PRIMASK and enable interrupts. // __asm(" mrs r0, PRIMASK\n" " cpsie i\n" " dsb \n" " isb \n" " bx lr\n" : "=r" (ulRet)); // // The return is handled in the inline assembly, but the compiler will // still complain if there is not an explicit return here (despite the fact // that this does not result in any code being produced because of the // naked attribute). // return(ulRet); } #endif #if defined(ewarm) unsigned long CPUcpsie(void) { // // Read PRIMASK and enable interrupts. // __asm(" mrs r0, PRIMASK\n" " cpsie i\n" " dsb \n" " isb \n"); // // "Warning[Pe940]: missing return statement at end of non-void function" // is suppressed here to avoid putting a "bx lr" in the inline assembly // above and a superfluous return statement here. // #pragma diag_suppress=Pe940 } #pragma diag_default=Pe940 #endif #if defined(ccs) unsigned long CPUcpsie(void) { // // Read PRIMASK and enable interrupts. // __asm(" mrs r0, PRIMASK\n" " cpsie i\n" " dsb \n" " isb \n" " bx lr\n"); // // The following keeps the compiler happy, because it wants to see a // return value from this function. It will generate code to return // a zero. However, the real return is the "bx lr" above, so the // return(0) is never executed and the function returns with the value // you expect in R0. // return(0); } #endif //***************************************************************************** // // Wrapper function for the WFI instruction. // //***************************************************************************** #if defined(gcc) void __attribute__((naked)) CPUwfi(void) { // // Wait for the next interrupt. // __asm(" dsb \n" " isb \n" " wfi \n" " bx lr\n"); } #endif #if defined(ewarm) void CPUwfi(void) { // // Wait for the next interrupt. // __asm(" dsb \n" " isb \n" " wfi \n"); } #endif #if defined(ccs) void CPUwfi(void) { // // Wait for the next interrupt. // __asm(" dsb \n" " isb \n" " wfi \n"); } #endif //***************************************************************************** // // Wrapper function for writing the BASEPRI register. // //***************************************************************************** #if defined(gcc) void __attribute__((naked)) CPUbasepriSet(unsigned long ulNewBasepri) { // // Set the BASEPRI register // __asm(" msr BASEPRI, r0\n" " dsb \n" " isb \n" " bx lr\n"); } #endif #if defined(ewarm) void CPUbasepriSet(unsigned long ulNewBasepri) { // // Set the BASEPRI register // __asm(" msr BASEPRI, r0\n" " dsb \n" " isb \n"); } #endif #if defined(ccs) void CPUbasepriSet(unsigned long ulNewBasepri) { // // Set the BASEPRI register // __asm(" msr BASEPRI, r0\n" " dsb \n" " isb \n"); } #endif //***************************************************************************** // // Wrapper function for reading the BASEPRI register. // //***************************************************************************** #if defined(gcc) unsigned long __attribute__((naked)) CPUbasepriGet(void) { unsigned long ulRet; // // Read BASEPRI // __asm(" mrs r0, BASEPRI\n" " bx lr\n" : "=r" (ulRet)); // // The return is handled in the inline assembly, but the compiler will // still complain if there is not an explicit return here (despite the fact // that this does not result in any code being produced because of the // naked attribute). // return(ulRet); } #endif #if defined(ewarm) unsigned long CPUbasepriGet(void) { // // Read BASEPRI // __asm(" mrs r0, BASEPRI\n"); // // "Warning[Pe940]: missing return statement at end of non-void function" // is suppressed here to avoid putting a "bx lr" in the inline assembly // above and a superfluous return statement here. // #pragma diag_suppress=Pe940 } #pragma diag_default=Pe940 #endif #if defined(ccs) unsigned long CPUbasepriGet(void) { // // Read BASEPRI // __asm(" mrs r0, BASEPRI\n" " bx lr\n"); // // The following keeps the compiler happy, because it wants to see a // return value from this function. It will generate code to return // a zero. However, the real return is the "bx lr" above, so the // return(0) is never executed and the function returns with the value // you expect in R0. // return(0); } #endif micropython-1.12/ports/cc3200/hal/cpu.h000066400000000000000000000055311357706137100175730ustar00rootroot00000000000000//***************************************************************************** // // cpu.h // // Prototypes for the CPU instruction wrapper functions. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __CPU_H__ #define __CPU_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // Prototypes. // //***************************************************************************** extern unsigned long CPUcpsid(void); extern unsigned long CPUcpsie(void); extern unsigned long CPUprimask(void); extern void CPUwfi(void); extern unsigned long CPUbasepriGet(void); extern void CPUbasepriSet(unsigned long ulNewBasepri); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __CPU_H__ micropython-1.12/ports/cc3200/hal/crc.c000066400000000000000000000237301357706137100175470ustar00rootroot00000000000000//***************************************************************************** // // crc.c // // Driver for the CRC module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup CRC_Cyclic_Redundancy_Check_api //! @{ // //***************************************************************************** #include #include #include "inc/hw_dthe.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "crc.h" #include "debug.h" //***************************************************************************** // //! Set the configuration of CRC functionality with the EC module. //! //! \param ui32Base is the base address of the EC module. //! \param ui32CRCConfig is the configuration of the CRC engine. //! //! This function configures the operation of the CRC engine within the EC //! module. The configuration is specified with the \e ui32CRCConfig argument. //! It is the logical OR of any of the following options: //! //! CRC Initialization Value //! - \b EC_CRC_CFG_INIT_SEED - Initialize with seed value //! - \b EC_CRC_CFG_INIT_0 - Initialize to all '0s' //! - \b EC_CRC_CFG_INIT_1 - Initialize to all '1s' //! //! Input Data Size //! - \b EC_CRC_CFG_SIZE_8BIT - Input data size of 8 bits //! - \b EC_CRC_CFG_SIZE_32BIT - Input data size of 32 bits //! //! Post Process Reverse/Inverse //! - \b EC_CRC_CFG_RESINV - Result inverse enable //! - \b EC_CRC_CFG_OBR - Output reverse enable //! //! Input Bit Reverse //! - \b EC_CRC_CFG_IBR - Bit reverse enable //! //! Endian Control //! - \b EC_CRC_CFG_ENDIAN_SBHW - Swap byte in half-word //! - \b EC_CRC_CFG_ENDIAN_SHW - Swap half-word //! //! Operation Type //! - \b EC_CRC_CFG_TYPE_P8005 - Polynomial 0x8005 //! - \b EC_CRC_CFG_TYPE_P1021 - Polynomial 0x1021 //! - \b EC_CRC_CFG_TYPE_P4C11DB7 - Polynomial 0x4C11DB7 //! - \b EC_CRC_CFG_TYPE_P1EDC6F41 - Polynomial 0x1EDC6F41 //! - \b EC_CRC_CFG_TYPE_TCPCHKSUM - TCP checksum //! //! \return None. // //***************************************************************************** void CRCConfigSet(uint32_t ui32Base, uint32_t ui32CRCConfig) { // // Check the arguments. // ASSERT(ui32Base == DTHE_BASE); ASSERT((ui32CRCConfig & CRC_CFG_INIT_SEED) || (ui32CRCConfig & CRC_CFG_INIT_0) || (ui32CRCConfig & CRC_CFG_INIT_1) || (ui32CRCConfig & CRC_CFG_SIZE_8BIT) || (ui32CRCConfig & CRC_CFG_SIZE_32BIT) || (ui32CRCConfig & CRC_CFG_RESINV) || (ui32CRCConfig & CRC_CFG_OBR) || (ui32CRCConfig & CRC_CFG_IBR) || (ui32CRCConfig & CRC_CFG_ENDIAN_SBHW) || (ui32CRCConfig & CRC_CFG_ENDIAN_SHW) || (ui32CRCConfig & CRC_CFG_TYPE_P8005) || (ui32CRCConfig & CRC_CFG_TYPE_P1021) || (ui32CRCConfig & CRC_CFG_TYPE_P4C11DB7) || (ui32CRCConfig & CRC_CFG_TYPE_P1EDC6F41) || (ui32CRCConfig & CRC_CFG_TYPE_TCPCHKSUM)); // // Write the control register with the configuration. // HWREG(ui32Base + DTHE_O_CRC_CTRL) = ui32CRCConfig; } //***************************************************************************** // //! Write the seed value for CRC operations in the EC module. //! //! \param ui32Base is the base address of the EC module. //! \param ui32Seed is the seed value. //! //! This function writes the seed value for use with CRC operations in the //! EC module. This value is the start value for CRC operations. If this //! value is not written, then the residual seed from the previous operation //! is used as the starting value. //! //! \note The seed must be written only if \b EC_CRC_CFG_INIT_SEED is //! set with the CRCConfigSet() function. // //***************************************************************************** void CRCSeedSet(uint32_t ui32Base, uint32_t ui32Seed) { // // Check the arguments. // ASSERT(ui32Base == DTHE_BASE); // // Write the seed value to the seed register. // HWREG(ui32Base + DTHE_O_CRC_SEED) = ui32Seed; } //***************************************************************************** // //! Write data into the EC module for CRC operations. //! //! \param ui32Base is the base address of the EC module. //! \param ui32Data is the data to be written. //! //! This function writes either 8 or 32 bits of data into the EC module for //! CRC operations. The distinction between 8 and 32 bits of data is made //! when the \b EC_CRC_CFG_SIZE_8BIT or \b EC_CRC_CFG_SIZE_32BIT flag //! is set using the CRCConfigSet() function. //! //! When writing 8 bits of data, ensure the data is in the least signficant //! byte position. The remaining bytes should be written with zero. For //! example, when writing 0xAB, \e ui32Data should be 0x000000AB. //! //! \return None // //***************************************************************************** void CRCDataWrite(uint32_t ui32Base, uint32_t ui32Data) { // // Check the arguments. // ASSERT(ui32Base == DTHE_BASE); // // Write the data // HWREG(DTHE_BASE + DTHE_O_CRC_DIN) = ui32Data; } //***************************************************************************** // //! Reads the result of a CRC operation in the EC module. //! //! \param ui32Base is the base address of the EC module. //! //! This function reads either the unmodified CRC result or the post //! processed CRC result from the EC module. The post-processing options //! are selectable through \b EC_CRC_CFG_RESINV and \b EC_CRC_CFG_OBR //! parameters in the CRCConfigSet() function. //! //! \return The CRC result. // //***************************************************************************** uint32_t CRCResultRead(uint32_t ui32Base) { // // Check the arguments. // ASSERT(ui32Base == DTHE_BASE); // // return value. // return(HWREG(DTHE_BASE + DTHE_O_CRC_RSLT_PP)); } //***************************************************************************** // //! Process data to generate a CRC with the EC module. //! //! \param ui32Base is the base address of the EC module. //! \param puiDataIn is a pointer to an array of data that is processed. //! \param ui32DataLength is the number of data items that are processed //! to produce the CRC. //! \param ui32Config the config parameter to determine the CRC mode //! //! This function processes an array of data to produce a CRC result. //! This function takes the CRC mode as the parameter. //! //! The data in the array pointed to be \e pui32DataIn is either an array //! of bytes or an array or words depending on the selection of the input //! data size options \b EC_CRC_CFG_SIZE_8BIT and //! \b EC_CRC_CFG_SIZE_32BIT. //! //! This function returns either the unmodified CRC result or the //! post- processed CRC result from the EC module. The post-processing //! options are selectable through \b EC_CRC_CFG_RESINV and //! \b EC_CRC_CFG_OBR parameters. //! //! \return The CRC result. // //***************************************************************************** uint32_t CRCDataProcess(uint32_t ui32Base, void *puiDataIn, uint32_t ui32DataLength, uint32_t ui32Config) { uint8_t *pui8DataIn; uint32_t *pui32DataIn; // // Check the arguments. // ASSERT(ui32Base == DTHE_BASE); // // See if the CRC is operating in 8-bit or 32-bit mode. // if(ui32Config & DTHE_CRC_CTRL_SIZE) { // // The CRC is operating in 8-bit mode, so create an 8-bit pointer to // the data. // pui8DataIn = (uint8_t *)puiDataIn; // // Loop through the input data. // while(ui32DataLength--) { // // Write the next data byte. // HWREG(ui32Base + DTHE_O_CRC_DIN) = *pui8DataIn++; } } else { // // The CRC is operating in 32-bit mode, so loop through the input data. // pui32DataIn = (uint32_t *)puiDataIn; while(ui32DataLength--) { // // Write the next data word. // HWREG(ui32Base + DTHE_O_CRC_DIN) = *pui32DataIn++; } } // // Return the result. // return(CRCResultRead(ui32Base)); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/crc.h000066400000000000000000000103361357706137100175520ustar00rootroot00000000000000//***************************************************************************** // // crc.h // // Defines and Macros for CRC module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __DRIVERLIB_CRC_H__ #define __DRIVERLIB_CRC_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // The following defines are used in the ui32Config argument of the // ECConfig function. // //***************************************************************************** #define CRC_CFG_INIT_SEED 0x00000000 // Initialize with seed #define CRC_CFG_INIT_0 0x00004000 // Initialize to all '0s' #define CRC_CFG_INIT_1 0x00006000 // Initialize to all '1s' #define CRC_CFG_SIZE_8BIT 0x00001000 // Input Data Size #define CRC_CFG_SIZE_32BIT 0x00000000 // Input Data Size #define CRC_CFG_RESINV 0x00000200 // Result Inverse Enable #define CRC_CFG_OBR 0x00000100 // Output Reverse Enable #define CRC_CFG_IBR 0x00000080 // Bit reverse enable #define CRC_CFG_ENDIAN_SBHW 0x00000000 // Swap byte in half-word #define CRC_CFG_ENDIAN_SHW 0x00000010 // Swap half-word #define CRC_CFG_TYPE_P8005 0x00000000 // Polynomial 0x8005 #define CRC_CFG_TYPE_P1021 0x00000001 // Polynomial 0x1021 #define CRC_CFG_TYPE_P4C11DB7 0x00000002 // Polynomial 0x4C11DB7 #define CRC_CFG_TYPE_P1EDC6F41 0x00000003 // Polynomial 0x1EDC6F41 #define CRC_CFG_TYPE_TCPCHKSUM 0x00000008 // TCP checksum //***************************************************************************** // // Function prototypes. // //***************************************************************************** extern void CRCConfigSet(uint32_t ui32Base, uint32_t ui32CRCConfig); extern uint32_t CRCDataProcess(uint32_t ui32Base, void *puiDataIn, uint32_t ui32DataLength, uint32_t ui32Config); extern void CRCDataWrite(uint32_t ui32Base, uint32_t ui32Data); extern uint32_t CRCResultRead(uint32_t ui32Base); extern void CRCSeedSet(uint32_t ui32Base, uint32_t ui32Seed); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __DRIVERLIB_CRC_H__ micropython-1.12/ports/cc3200/hal/debug.h000066400000000000000000000051641357706137100200740ustar00rootroot00000000000000//***************************************************************************** // // debug.h // // Macros for assisting debug of the driver library. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __DEBUG_H__ #define __DEBUG_H__ #include "assert.h" //***************************************************************************** // // Prototype for the function that is called when an invalid argument is passed // to an API. This is only used when doing a DEBUG build. // //***************************************************************************** //***************************************************************************** // // The ASSERT macro, which does the actual assertion checking. Typically, this // will be for procedure arguments. // //***************************************************************************** #if defined(DEBUG) && !defined(BOOTLOADER) #define ASSERT(expr) assert(expr) #else #define ASSERT(expr) (void)(expr) #endif #endif // __DEBUG_H__ micropython-1.12/ports/cc3200/hal/des.c000066400000000000000000000656101357706137100175560ustar00rootroot00000000000000//***************************************************************************** // // des.c // // Driver for the DES data transformation. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup DES_Data_Encryption_Standard_api //! @{ // //***************************************************************************** #include #include #include "inc/hw_des.h" #include "inc/hw_dthe.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "debug.h" #include "des.h" #include "interrupt.h" //***************************************************************************** // //! Configures the DES module for operation. //! //! \param ui32Base is the base address of the DES module. //! \param ui32Config is the configuration of the DES module. //! //! This function configures the DES module for operation. //! //! The \e ui32Config parameter is a bit-wise OR of a number of configuration //! flags. The valid flags are grouped below based on their function. //! //! The direction of the operation is specified with one of the following two //! flags. Only one is permitted. //! //! - \b DES_CFG_DIR_ENCRYPT - Encryption //! - \b DES_CFG_DIR_DECRYPT - Decryption //! //! The operational mode of the DES engine is specified with one of the //! following flags. Only one is permitted. //! //! - \b DES_CFG_MODE_ECB - Electronic Codebook Mode //! - \b DES_CFG_MODE_CBC - Cipher-Block Chaining Mode //! - \b DES_CFG_MODE_CFB - Cipher Feedback Mode //! //! The selection of single DES or triple DES is specified with one of the //! following two flags. Only one is permitted. //! //! - \b DES_CFG_SINGLE - Single DES //! - \b DES_CFG_TRIPLE - Triple DES //! //! \return None. // //***************************************************************************** void DESConfigSet(uint32_t ui32Base, uint32_t ui32Config) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); // // Backup the save context field. // ui32Config |= (HWREG(ui32Base + DES_O_CTRL) & DES_CTRL_CONTEXT); // // Write the control register. // HWREG(ui32Base + DES_O_CTRL) = ui32Config; } //***************************************************************************** // //! Sets the key used for DES operations. //! //! \param ui32Base is the base address of the DES module. //! \param pui8Key is a pointer to an array that holds the key //! //! This function sets the key used for DES operations. //! //! \e pui8Key should be 64 bits long (2 words) if single DES is being used or //! 192 bits (6 words) if triple DES is being used. //! //! \return None. // //***************************************************************************** void DESKeySet(uint32_t ui32Base, uint8_t *pui8Key) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); // // Write the first part of the key. // HWREG(ui32Base + DES_O_KEY1_L) = * ((uint32_t *)(pui8Key + 0)); HWREG(ui32Base + DES_O_KEY1_H) = * ((uint32_t *)(pui8Key + 4)); // // If we are performing triple DES, then write the key registers for // the second and third rounds. // if(HWREG(ui32Base + DES_O_CTRL) & DES_CFG_TRIPLE) { HWREG(ui32Base + DES_O_KEY2_L) = * ((uint32_t *)(pui8Key + 8)); HWREG(ui32Base + DES_O_KEY2_H) = * ((uint32_t *)(pui8Key + 12)); HWREG(ui32Base + DES_O_KEY3_L) = * ((uint32_t *)(pui8Key + 16)); HWREG(ui32Base + DES_O_KEY3_H) = * ((uint32_t *)(pui8Key + 20)); } } //***************************************************************************** // //! Sets the initialization vector in the DES module. //! //! \param ui32Base is the base address of the DES module. //! \param pui8IVdata is a pointer to an array of 64 bits (2 words) of data to //! be written into the initialization vectors registers. //! //! This function sets the initialization vector in the DES module. It returns //! true if the registers were successfully written. If the context registers //! cannot be written at the time the function was called, then false is //! returned. //! //! \return True or false. // //***************************************************************************** bool DESIVSet(uint32_t ui32Base, uint8_t *pui8IVdata) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); // // Check to see if context registers can be overwritten. If not, return // false. // if((HWREG(ui32Base + DES_O_CTRL) & DES_CTRL_CONTEXT) == 0) { return(false); } // // Write the initialization vector registers. // HWREG(ui32Base + DES_O_IV_L) = *((uint32_t *) (pui8IVdata + 0)); HWREG(ui32Base + DES_O_IV_H) = *((uint32_t *) (pui8IVdata + 4)); // // Return true to indicate the write was successful. // return(true); } //***************************************************************************** // //! Sets the crytographic data length in the DES module. //! //! \param ui32Base is the base address of the DES module. //! \param ui32Length is the length of the data in bytes. //! //! This function writes the cryptographic data length into the DES module. //! When this register is written, the engine is triggersed to start using //! this context. //! //! \note Data lengths up to (2^32 - 1) bytes are allowed. //! //! \return None. // //***************************************************************************** void DESDataLengthSet(uint32_t ui32Base, uint32_t ui32Length) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); // // Write the length register. // HWREG(ui32Base + DES_O_LENGTH) = ui32Length; } //***************************************************************************** // //! Reads plaintext/ciphertext from data registers without blocking //! //! \param ui32Base is the base address of the DES module. //! \param pui8Dest is a pointer to an array of 2 words. //! \param ui8Length the length can be from 1 to 8 //! //! This function returns true if the data was ready when the function was //! called. If the data was not ready, false is returned. //! //! \return True or false. // //***************************************************************************** bool DESDataReadNonBlocking(uint32_t ui32Base, uint8_t *pui8Dest, uint8_t ui8Length) { volatile uint32_t pui32Dest[2]; uint8_t ui8BytCnt; uint8_t *pui8DestTemp; // // Check the arguments. // ASSERT(ui32Base == DES_BASE); if((ui8Length == 0)||(ui8Length>8)) { return(false); } // // Check to see if the data is ready to be read. // if((DES_CTRL_OUTPUT_READY & (HWREG(ui32Base + DES_O_CTRL))) == 0) { return(false); } // // Read two words of data from the data registers. // pui32Dest[0] = HWREG(DES_BASE + DES_O_DATA_L); pui32Dest[1] = HWREG(DES_BASE + DES_O_DATA_H); // //Copy the data to a block memory // pui8DestTemp = (uint8_t *)pui32Dest; for(ui8BytCnt = 0; ui8BytCnt < ui8Length ; ui8BytCnt++) { *(pui8Dest+ui8BytCnt) = *(pui8DestTemp+ui8BytCnt); } // // Return true to indicate a successful write. // return(true); } //***************************************************************************** // //! Reads plaintext/ciphertext from data registers with blocking. //! //! \param ui32Base is the base address of the DES module. //! \param pui8Dest is a pointer to an array of bytes. //! \param ui8Length the length can be from 1 to 8 //! //! This function waits until the DES module is finished and encrypted or //! decrypted data is ready. The output data is then stored in the pui8Dest //! array. //! //! \return None // //***************************************************************************** void DESDataRead(uint32_t ui32Base, uint8_t *pui8Dest, uint8_t ui8Length) { volatile uint32_t pui32Dest[2]; uint8_t ui8BytCnt; uint8_t *pui8DestTemp; // // Check the arguments. // ASSERT(ui32Base == DES_BASE); if((ui8Length == 0)||(ui8Length>8)) { return; } // // Wait for data output to be ready. // while((HWREG(ui32Base + DES_O_CTRL) & DES_CTRL_OUTPUT_READY) == 0) { } // // Read two words of data from the data registers. // pui32Dest[0] = HWREG(DES_BASE + DES_O_DATA_L); pui32Dest[1] = HWREG(DES_BASE + DES_O_DATA_H); // //Copy the data to a block memory // pui8DestTemp = (uint8_t *)pui32Dest; for(ui8BytCnt = 0; ui8BytCnt < ui8Length ; ui8BytCnt++) { *(pui8Dest+ui8BytCnt) = *(pui8DestTemp+ui8BytCnt); } } //***************************************************************************** // //! Writes plaintext/ciphertext to data registers without blocking //! //! \param ui32Base is the base address of the DES module. //! \param pui8Src is a pointer to an array of 2 words. //! \param ui8Length the length can be from 1 to 8 //! //! This function returns false if the DES module is not ready to accept //! data. It returns true if the data was written successfully. //! //! \return true or false. // //***************************************************************************** bool DESDataWriteNonBlocking(uint32_t ui32Base, uint8_t *pui8Src, uint8_t ui8Length) { volatile uint32_t pui32Src[2]={0,0}; uint8_t ui8BytCnt; uint8_t *pui8SrcTemp; // // Check the arguments. // ASSERT(ui32Base == DES_BASE); if((ui8Length == 0)||(ui8Length>8)) { return(false); } // // Check if the DES module is ready to encrypt or decrypt data. If it // is not, return false. // if(!(DES_CTRL_INPUT_READY & (HWREG(ui32Base + DES_O_CTRL)))) { return(false); } // // Copy the data to a block memory // pui8SrcTemp = (uint8_t *)pui32Src; for(ui8BytCnt = 0; ui8BytCnt < ui8Length ; ui8BytCnt++) { *(pui8SrcTemp+ui8BytCnt) = *(pui8Src+ui8BytCnt); } // // Write the data. // HWREG(DES_BASE + DES_O_DATA_L) = pui32Src[0]; HWREG(DES_BASE + DES_O_DATA_H) = pui32Src[1]; // // Return true to indicate a successful write. // return(true); } //***************************************************************************** // //! Writes plaintext/ciphertext to data registers without blocking //! //! \param ui32Base is the base address of the DES module. //! \param pui8Src is a pointer to an array of bytes. //! \param ui8Length the length can be from 1 to 8 //! //! This function waits until the DES module is ready before writing the //! data contained in the pui8Src array. //! //! \return None. // //***************************************************************************** void DESDataWrite(uint32_t ui32Base, uint8_t *pui8Src, uint8_t ui8Length) { volatile uint32_t pui32Src[2]={0,0}; uint8_t ui8BytCnt; uint8_t *pui8SrcTemp; // // Check the arguments. // ASSERT(ui32Base == DES_BASE); if((ui8Length == 0)||(ui8Length>8)) { return; } // // Wait for the input ready bit to go high. // while(((HWREG(ui32Base + DES_O_CTRL) & DES_CTRL_INPUT_READY)) == 0) { } // //Copy the data to a block memory // pui8SrcTemp = (uint8_t *)pui32Src; for(ui8BytCnt = 0; ui8BytCnt < ui8Length ; ui8BytCnt++) { *(pui8SrcTemp+ui8BytCnt) = *(pui8Src+ui8BytCnt); } // // Write the data. // HWREG(DES_BASE + DES_O_DATA_L) = pui32Src[0]; HWREG(DES_BASE + DES_O_DATA_H) = pui32Src[1]; } //***************************************************************************** // //! Processes blocks of data through the DES module. //! //! \param ui32Base is the base address of the DES module. //! \param pui8Src is a pointer to an array of words that contains the //! source data for processing. //! \param pui8Dest is a pointer to an array of words consisting of the //! processed data. //! \param ui32Length is the length of the cryptographic data in bytes. //! It must be a multiple of eight. //! //! This function takes the data contained in the pui8Src array and processes //! it using the DES engine. The resulting data is stored in the //! pui8Dest array. The function blocks until all of the data has been //! processed. If processing is successful, the function returns true. //! //! \note This functions assumes that the DES module has been configured, //! and initialization values and keys have been written. //! //! \return true or false. // //***************************************************************************** bool DESDataProcess(uint32_t ui32Base, uint8_t *pui8Src, uint8_t *pui8Dest, uint32_t ui32Length) { uint32_t ui32Count, ui32BlkCount, ui32ByteCount; // // Check the arguments. // ASSERT(ui32Base == DES_BASE); ASSERT((ui32Length % 8) == 0); // // Write the length register first. This triggers the engine to start // using this context. // HWREG(ui32Base + DES_O_LENGTH) = ui32Length; // // Now loop until the blocks are written. // ui32BlkCount = ui32Length/8; for(ui32Count = 0; ui32Count > 16); HWREG(ui32Base + DES_O_IRQENABLE) |= ui32IntFlags & 0x0000ffff; } //***************************************************************************** // //! Disables interrupts in the DES module. //! //! \param ui32Base is the base address of the DES module. //! \param ui32IntFlags is a bit mask of the interrupts to be disabled. //! //! This function disables interrupt sources in the DES module. //! \e ui32IntFlags should be a logical OR of one or more of the following //! values: //! //! - \b DES_INT_CONTEXT_IN - Context interrupt //! - \b DES_INT_DATA_IN - Data input interrupt //! - \b DES_INT_DATA_OUT - Data output interrupt //! - \b DES_INT_DMA_CONTEXT_IN - Context DMA done interrupt //! - \b DES_INT_DMA_DATA_IN - Data input DMA done interrupt //! - \b DES_INT_DMA_DATA_OUT - Data output DMA done interrupt //! //! \return None. // //***************************************************************************** void DESIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); ASSERT((ui32IntFlags & DES_INT_CONTEXT_IN) || (ui32IntFlags & DES_INT_DATA_IN) || (ui32IntFlags & DES_INT_DATA_OUT) || (ui32IntFlags & DES_INT_DMA_CONTEXT_IN) || (ui32IntFlags & DES_INT_DMA_DATA_IN) || (ui32IntFlags & DES_INT_DMA_DATA_OUT)); // // Clear the interrupts from the flags. // HWREG(DTHE_BASE + DTHE_O_AES_IM) |= ((ui32IntFlags & 0x00070000) >> 16); HWREG(ui32Base + DES_O_IRQENABLE) &= ~(ui32IntFlags & 0x0000ffff); } //***************************************************************************** // //! Clears interrupts in the DES module. //! //! \param ui32Base is the base address of the DES module. //! \param ui32IntFlags is a bit mask of the interrupts to be disabled. //! //! This function disables interrupt sources in the DES module. //! \e ui32IntFlags should be a logical OR of one or more of the following //! values: //! //! - \b DES_INT_DMA_CONTEXT_IN - Context interrupt //! - \b DES_INT_DMA_DATA_IN - Data input interrupt //! - \b DES_INT_DMA_DATA_OUT - Data output interrupt //! //! \note The DMA done interrupts are the only interrupts that can be cleared. //! The remaining interrupts can be disabled instead using DESIntDisable(). //! //! \return None. // //***************************************************************************** void DESIntClear(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); ASSERT((ui32IntFlags & DES_INT_DMA_CONTEXT_IN) || (ui32IntFlags & DES_INT_DMA_DATA_IN) || (ui32IntFlags & DES_INT_DMA_DATA_OUT)); HWREG(DTHE_BASE + DTHE_O_DES_IC) = ((ui32IntFlags & 0x00070000) >> 16); } //***************************************************************************** // //! Registers an interrupt handler for the DES module. //! //! \param ui32Base is the base address of the DES module. //! \param pfnHandler is a pointer to the function to be called when the //! enabled DES interrupts occur. //! //! This function registers the interrupt handler in the interrupt vector //! table, and enables DES interrupts on the interrupt controller; specific DES //! interrupt sources must be enabled using DESIntEnable(). The interrupt //! handler being registered must clear the source of the interrupt using //! DESIntClear(). //! //! If the application is using a static interrupt vector table stored in //! flash, then it is not necessary to register the interrupt handler this way. //! Instead, IntEnable() should be used to enable DES interrupts on the //! interrupt controller. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void DESIntRegister(uint32_t ui32Base, void(*pfnHandler)(void)) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); // // Register the interrupt handler. // IntRegister(INT_DES, pfnHandler); // // Enable the interrupt. // IntEnable(INT_DES); } //***************************************************************************** // //! Unregisters an interrupt handler for the DES module. //! //! \param ui32Base is the base address of the DES module. //! //! This function unregisters the previously registered interrupt handler and //! disables the interrupt in the interrupt controller. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void DESIntUnregister(uint32_t ui32Base) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); // // Disable the interrupt. // IntDisable(INT_DES); // // Unregister the interrupt handler. // IntUnregister(INT_DES); } //***************************************************************************** // //! Enables DMA request sources in the DES module. //! //! \param ui32Base is the base address of the DES module. //! \param ui32Flags is a bit mask of the DMA requests to be enabled. //! //! This function enables DMA request sources in the DES module. The //! \e ui32Flags parameter should be the logical OR of any of the following: //! //! - \b DES_DMA_CONTEXT_IN - Context In //! - \b DES_DMA_DATA_OUT - Data Out //! - \b DES_DMA_DATA_IN - Data In //! //! \return None. // //***************************************************************************** void DESDMAEnable(uint32_t ui32Base, uint32_t ui32Flags) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); ASSERT((ui32Flags & DES_DMA_CONTEXT_IN) || (ui32Flags & DES_DMA_DATA_OUT) || (ui32Flags & DES_DMA_DATA_IN)); // // Set the data in and data out DMA request enable bits. // HWREG(ui32Base + DES_O_SYSCONFIG) |= ui32Flags; } //***************************************************************************** // //! Disables DMA request sources in the DES module. //! //! \param ui32Base is the base address of the DES module. //! \param ui32Flags is a bit mask of the DMA requests to be disabled. //! //! This function disables DMA request sources in the DES module. The //! \e ui32Flags parameter should be the logical OR of any of the following: //! //! - \b DES_DMA_CONTEXT_IN - Context In //! - \b DES_DMA_DATA_OUT - Data Out //! - \b DES_DMA_DATA_IN - Data In //! //! \return None. // //***************************************************************************** void DESDMADisable(uint32_t ui32Base, uint32_t ui32Flags) { // // Check the arguments. // ASSERT(ui32Base == DES_BASE); ASSERT((ui32Flags & DES_DMA_CONTEXT_IN) || (ui32Flags & DES_DMA_DATA_OUT) || (ui32Flags & DES_DMA_DATA_IN)); // // Disable the DMA sources. // HWREG(ui32Base + DES_O_SYSCONFIG) &= ~ui32Flags; } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/des.h000066400000000000000000000141571357706137100175630ustar00rootroot00000000000000//***************************************************************************** // // des.h // // Defines and Macros for the DES module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __DRIVERLIB_DES_H__ #define __DRIVERLIB_DES_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // The following defines are used to specify the direction with the // ui32Config argument in the DESConfig() function. Only one is permitted. // //***************************************************************************** #define DES_CFG_DIR_DECRYPT 0x00000000 #define DES_CFG_DIR_ENCRYPT 0x00000004 //***************************************************************************** // // The following defines are used to specify the operational with the // ui32Config argument in the DESConfig() function. Only one is permitted. // //***************************************************************************** #define DES_CFG_MODE_ECB 0x00000000 #define DES_CFG_MODE_CBC 0x00000010 #define DES_CFG_MODE_CFB 0x00000020 //***************************************************************************** // // The following defines are used to select between single DES and triple DES // with the ui32Config argument in the DESConfig() function. Only one is // permitted. // //***************************************************************************** #define DES_CFG_SINGLE 0x00000000 #define DES_CFG_TRIPLE 0x00000008 //***************************************************************************** // // The following defines are used with the DESIntEnable(), DESIntDisable() and // DESIntStatus() functions. // //***************************************************************************** #define DES_INT_CONTEXT_IN 0x00000001 #define DES_INT_DATA_IN 0x00000002 #define DES_INT_DATA_OUT 0x00000004 #define DES_INT_DMA_CONTEXT_IN 0x00010000 #define DES_INT_DMA_DATA_IN 0x00020000 #define DES_INT_DMA_DATA_OUT 0x00040000 //***************************************************************************** // // The following defines are used with the DESEnableDMA() and DESDisableDMA() // functions. // //***************************************************************************** #define DES_DMA_CONTEXT_IN 0x00000080 #define DES_DMA_DATA_OUT 0x00000040 #define DES_DMA_DATA_IN 0x00000020 //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void DESConfigSet(uint32_t ui32Base, uint32_t ui32Config); extern void DESDataRead(uint32_t ui32Base, uint8_t *pui8Dest, uint8_t ui8Length); extern bool DESDataReadNonBlocking(uint32_t ui32Base, uint8_t *pui8Dest, uint8_t ui8Length); extern bool DESDataProcess(uint32_t ui32Base, uint8_t *pui8Src, uint8_t *pui8Dest, uint32_t ui32Length); extern void DESDataWrite(uint32_t ui32Base, uint8_t *pui8Src, uint8_t ui8Length); extern bool DESDataWriteNonBlocking(uint32_t ui32Base, uint8_t *pui8Src, uint8_t ui8Length); extern void DESDMADisable(uint32_t ui32Base, uint32_t ui32Flags); extern void DESDMAEnable(uint32_t ui32Base, uint32_t ui32Flags); extern void DESIntClear(uint32_t ui32Base, uint32_t ui32IntFlags); extern void DESIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags); extern void DESIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags); extern void DESIntRegister(uint32_t ui32Base, void(*pfnHandler)(void)); extern uint32_t DESIntStatus(uint32_t ui32Base, bool bMasked); extern void DESIntUnregister(uint32_t ui32Base); extern bool DESIVSet(uint32_t ui32Base, uint8_t *pui8IVdata); extern void DESKeySet(uint32_t ui32Base, uint8_t *pui8Key); extern void DESDataLengthSet(uint32_t ui32Base, uint32_t ui32Length); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __DRIVERLIB_DES_H__ micropython-1.12/ports/cc3200/hal/fault_registers.h000066400000000000000000000043761357706137100222140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef FAULT_REGISTERS_H_ #define FAULT_REGISTERS_H_ typedef struct { uint32_t IERR :1; uint32_t DERR :1; uint32_t :1; uint32_t MUSTKE :1; uint32_t MSTKE :1; uint32_t MLSPERR :1; uint32_t :1; uint32_t MMARV :1; uint32_t IBUS :1; uint32_t PRECISE :1; uint32_t IMPRE :1; uint32_t BUSTKE :1; uint32_t BSTKE :1; uint32_t BLSPERR :1; uint32_t :1; uint32_t BFARV :1; uint32_t UNDEF :1; uint32_t INVSTAT :1; uint32_t INVCP :1; uint32_t NOCP :1; uint32_t :4; uint32_t UNALIGN :1; uint32_t DIVO0 :1; uint32_t :6; }_CFSR_t; typedef struct { uint32_t DBG :1; uint32_t FORCED :1; uint32_t :28; uint32_t VECT :1; uint32_t :1; }_HFSR_t; #endif /* FAULT_REGISTERS_H_ */ micropython-1.12/ports/cc3200/hal/gpio.c000066400000000000000000000540311357706137100177340ustar00rootroot00000000000000//***************************************************************************** // // gpio.c // // Driver for the GPIO module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup GPIO_General_Purpose_InputOutput_api //! @{ // //***************************************************************************** #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_common_reg.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" //***************************************************************************** // //! \internal //! Checks a GPIO base address. //! //! \param ulPort is the base address of the GPIO port. //! //! This function determines if a GPIO port base address is valid. //! //! \return Returns \b true if the base address is valid and \b false //! otherwise. // //***************************************************************************** #if defined(DEBUG) && !defined(BOOTLOADER) static tBoolean GPIOBaseValid(unsigned long ulPort) { return((ulPort == GPIOA0_BASE) || (ulPort == GPIOA1_BASE) || (ulPort == GPIOA2_BASE) || (ulPort == GPIOA3_BASE) || (ulPort == GPIOA4_BASE)); } #else #define GPIOBaseValid(ulPort) (ulPort) #endif //***************************************************************************** // //! \internal //! Gets the GPIO interrupt number. //! //! \param ulPort is the base address of the GPIO port. //! //! Given a GPIO base address, returns the corresponding interrupt number. //! //! \return Returns a GPIO interrupt number, or -1 if \e ulPort is invalid. // //***************************************************************************** static long GPIOGetIntNumber(unsigned long ulPort) { unsigned int ulInt; // // Determine the GPIO interrupt number for the given module. // switch(ulPort) { case GPIOA0_BASE: { ulInt = INT_GPIOA0; break; } case GPIOA1_BASE: { ulInt = INT_GPIOA1; break; } case GPIOA2_BASE: { ulInt = INT_GPIOA2; break; } case GPIOA3_BASE: { ulInt = INT_GPIOA3; break; } default: { return(-1); } } // // Return GPIO interrupt number. // return(ulInt); } //***************************************************************************** // //! Sets the direction and mode of the specified pin(s). //! //! \param ulPort is the base address of the GPIO port //! \param ucPins is the bit-packed representation of the pin(s). //! \param ulPinIO is the pin direction and/or mode. //! //! This function will set the specified pin(s) on the selected GPIO port //! as either an input or output under software control, or it will set the //! pin to be under hardware control. //! //! The parameter \e ulPinIO is an enumerated data type that can be one of //! the following values: //! //! - \b GPIO_DIR_MODE_IN //! - \b GPIO_DIR_MODE_OUT //! //! where \b GPIO_DIR_MODE_IN specifies that the pin will be programmed as //! a software controlled input, \b GPIO_DIR_MODE_OUT specifies that the pin //! will be programmed as a software controlled output. //! //! The pin(s) are specified using a bit-packed byte, where each bit that is //! set identifies the pin to be accessed, and where bit 0 of the byte //! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on. //! //! \note GPIOPadConfigSet() must also be used to configure the corresponding //! pad(s) in order for them to propagate the signal to/from the GPIO. //! //! \return None. // //***************************************************************************** void GPIODirModeSet(unsigned long ulPort, unsigned char ucPins, unsigned long ulPinIO) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); ASSERT((ulPinIO == GPIO_DIR_MODE_IN) || (ulPinIO == GPIO_DIR_MODE_OUT)); // // Set the pin direction and mode. // HWREG(ulPort + GPIO_O_GPIO_DIR) = ((ulPinIO & 1) ? (HWREG(ulPort + GPIO_O_GPIO_DIR) | ucPins) : (HWREG(ulPort + GPIO_O_GPIO_DIR) & ~(ucPins))); } //***************************************************************************** // //! Gets the direction and mode of a pin. //! //! \param ulPort is the base address of the GPIO port. //! \param ucPin is the pin number. //! //! This function gets the direction and control mode for a specified pin on //! the selected GPIO port. The pin can be configured as either an input or //! output under software control, or it can be under hardware control. The //! type of control and direction are returned as an enumerated data type. //! //! \return Returns one of the enumerated data types described for //! GPIODirModeSet(). // //***************************************************************************** unsigned long GPIODirModeGet(unsigned long ulPort, unsigned char ucPin) { unsigned long ulDir; // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Return the pin direction // ulDir = HWREG(ulPort + GPIO_O_GPIO_DIR); return(((ulDir & ucPin) ? 1 : 0)); } //***************************************************************************** // //! Sets the interrupt type for the specified pin(s). //! //! \param ulPort is the base address of the GPIO port. //! \param ucPins is the bit-packed representation of the pin(s). //! \param ulIntType specifies the type of interrupt trigger mechanism. //! //! This function sets up the various interrupt trigger mechanisms for the //! specified pin(s) on the selected GPIO port. //! //! The parameter \e ulIntType is an enumerated data type that can be one of //! the following values: //! //! - \b GPIO_FALLING_EDGE //! - \b GPIO_RISING_EDGE //! - \b GPIO_BOTH_EDGES //! - \b GPIO_LOW_LEVEL //! - \b GPIO_HIGH_LEVEL //! //! The pin(s) are specified using a bit-packed byte, where each bit that is //! set identifies the pin to be accessed, and where bit 0 of the byte //! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on. //! //! \note In order to avoid any spurious interrupts, the user must //! ensure that the GPIO inputs remain stable for the duration of //! this function. //! //! \return None. // //***************************************************************************** void GPIOIntTypeSet(unsigned long ulPort, unsigned char ucPins, unsigned long ulIntType) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); ASSERT((ulIntType == GPIO_FALLING_EDGE) || (ulIntType == GPIO_RISING_EDGE) || (ulIntType == GPIO_BOTH_EDGES) || (ulIntType == GPIO_LOW_LEVEL) || (ulIntType == GPIO_HIGH_LEVEL)); // // Set the pin interrupt type. // HWREG(ulPort + GPIO_O_GPIO_IBE) = ((ulIntType & 1) ? (HWREG(ulPort + GPIO_O_GPIO_IBE) | ucPins) : (HWREG(ulPort + GPIO_O_GPIO_IBE) & ~(ucPins))); HWREG(ulPort + GPIO_O_GPIO_IS) = ((ulIntType & 2) ? (HWREG(ulPort + GPIO_O_GPIO_IS) | ucPins) : (HWREG(ulPort + GPIO_O_GPIO_IS) & ~(ucPins))); HWREG(ulPort + GPIO_O_GPIO_IEV) = ((ulIntType & 4) ? (HWREG(ulPort + GPIO_O_GPIO_IEV) | ucPins) : (HWREG(ulPort + GPIO_O_GPIO_IEV) & ~(ucPins))); } //***************************************************************************** // //! Gets the interrupt type for a pin. //! //! \param ulPort is the base address of the GPIO port. //! \param ucPin is the pin number. //! //! This function gets the interrupt type for a specified pin on the selected //! GPIO port. The pin can be configured as a falling edge, rising edge, or //! both edge detected interrupt, or it can be configured as a low level or //! high level detected interrupt. The type of interrupt detection mechanism //! is returned as an enumerated data type. //! //! \return Returns one of the enumerated data types described for //! GPIOIntTypeSet(). // //***************************************************************************** unsigned long GPIOIntTypeGet(unsigned long ulPort, unsigned char ucPin) { unsigned long ulIBE, ulIS, ulIEV; // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Return the pin interrupt type. // ulIBE = HWREG(ulPort + GPIO_O_GPIO_IBE); ulIS = HWREG(ulPort + GPIO_O_GPIO_IS); ulIEV = HWREG(ulPort + GPIO_O_GPIO_IEV); return(((ulIBE & ucPin) ? 1 : 0) | ((ulIS & ucPin) ? 2 : 0) | ((ulIEV & ucPin) ? 4 : 0)); } //***************************************************************************** // //! Enables the specified GPIO interrupts. //! //! \param ulPort is the base address of the GPIO port. //! \param ulIntFlags is the bit mask of the interrupt sources to enable. //! //! This function enables the indicated GPIO interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter is the logical OR of any of the following: //! //! - \b GPIO_INT_DMA - interrupt due to GPIO triggered DMA Done //! - \b GPIO_INT_PIN_0 - interrupt due to activity on Pin 0. //! - \b GPIO_INT_PIN_1 - interrupt due to activity on Pin 1. //! - \b GPIO_INT_PIN_2 - interrupt due to activity on Pin 2. //! - \b GPIO_INT_PIN_3 - interrupt due to activity on Pin 3. //! - \b GPIO_INT_PIN_4 - interrupt due to activity on Pin 4. //! - \b GPIO_INT_PIN_5 - interrupt due to activity on Pin 5. //! - \b GPIO_INT_PIN_6 - interrupt due to activity on Pin 6. //! - \b GPIO_INT_PIN_7 - interrupt due to activity on Pin 7. //! //! \return None. // //***************************************************************************** void GPIOIntEnable(unsigned long ulPort, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Enable the interrupts. // HWREG(ulPort + GPIO_O_GPIO_IM) |= ulIntFlags; } //***************************************************************************** // //! Disables the specified GPIO interrupts. //! //! \param ulPort is the base address of the GPIO port. //! \param ulIntFlags is the bit mask of the interrupt sources to disable. //! //! This function disables the indicated GPIO interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter is the logical OR of any of the following: //! //! - \b GPIO_INT_DMA - interrupt due to GPIO triggered DMA Done //! - \b GPIO_INT_PIN_0 - interrupt due to activity on Pin 0. //! - \b GPIO_INT_PIN_1 - interrupt due to activity on Pin 1. //! - \b GPIO_INT_PIN_2 - interrupt due to activity on Pin 2. //! - \b GPIO_INT_PIN_3 - interrupt due to activity on Pin 3. //! - \b GPIO_INT_PIN_4 - interrupt due to activity on Pin 4. //! - \b GPIO_INT_PIN_5 - interrupt due to activity on Pin 5. //! - \b GPIO_INT_PIN_6 - interrupt due to activity on Pin 6. //! - \b GPIO_INT_PIN_7 - interrupt due to activity on Pin 7. //! //! \return None. // //***************************************************************************** void GPIOIntDisable(unsigned long ulPort, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Disable the interrupts. // HWREG(ulPort + GPIO_O_GPIO_IM) &= ~(ulIntFlags); } //***************************************************************************** // //! Gets interrupt status for the specified GPIO port. //! //! \param ulPort is the base address of the GPIO port. //! \param bMasked specifies whether masked or raw interrupt status is //! returned. //! //! If \e bMasked is set as \b true, then the masked interrupt status is //! returned; otherwise, the raw interrupt status will be returned. //! //! \return Returns the current interrupt status, enumerated as a bit field of //! values described in GPIOIntEnable(). // //***************************************************************************** long GPIOIntStatus(unsigned long ulPort, tBoolean bMasked) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Return the interrupt status. // if(bMasked) { return(HWREG(ulPort + GPIO_O_GPIO_MIS)); } else { return(HWREG(ulPort + GPIO_O_GPIO_RIS)); } } //***************************************************************************** // //! Clears the interrupt for the specified pin(s). //! //! \param ulPort is the base address of the GPIO port. //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared. //! //! Clears the interrupt for the specified pin(s). //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to GPIOIntEnable(). //! //! //! \return None. // //***************************************************************************** void GPIOIntClear(unsigned long ulPort, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Clear the interrupts. // HWREG(ulPort + GPIO_O_GPIO_ICR) = ulIntFlags; } //***************************************************************************** // //! Registers an interrupt handler for a GPIO port. //! //! \param ulPort is the base address of the GPIO port. //! \param pfnIntHandler is a pointer to the GPIO port interrupt handling //! function. //! //! This function will ensure that the interrupt handler specified by //! \e pfnIntHandler is called when an interrupt is detected from the selected //! GPIO port. This function will also enable the corresponding GPIO interrupt //! in the interrupt controller; individual pin interrupts and interrupt //! sources must be enabled with GPIOIntEnable(). //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void GPIOIntRegister(unsigned long ulPort, void (*pfnIntHandler)(void)) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Get the interrupt number associated with the specified GPIO. // ulPort = GPIOGetIntNumber(ulPort); // // Register the interrupt handler. // IntRegister(ulPort, pfnIntHandler); // // Enable the GPIO interrupt. // IntEnable(ulPort); } //***************************************************************************** // //! Removes an interrupt handler for a GPIO port. //! //! \param ulPort is the base address of the GPIO port. //! //! This function will unregister the interrupt handler for the specified //! GPIO port. This function will also disable the corresponding //! GPIO port interrupt in the interrupt controller; individual GPIO interrupts //! and interrupt sources must be disabled with GPIOIntDisable(). //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void GPIOIntUnregister(unsigned long ulPort) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Get the interrupt number associated with the specified GPIO. // ulPort = GPIOGetIntNumber(ulPort); // // Disable the GPIO interrupt. // IntDisable(ulPort); // // Unregister the interrupt handler. // IntUnregister(ulPort); } //***************************************************************************** // //! Reads the values present of the specified pin(s). //! //! \param ulPort is the base address of the GPIO port. //! \param ucPins is the bit-packed representation of the pin(s). //! //! The values at the specified pin(s) are read, as specified by \e ucPins. //! Values are returned for both input and output pin(s), and the value //! for pin(s) that are not specified by \e ucPins are set to 0. //! //! The pin(s) are specified using a bit-packed byte, where each bit that is //! set identifies the pin to be accessed, and where bit 0 of the byte //! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on. //! //! \return Returns a bit-packed byte providing the state of the specified //! pin, where bit 0 of the byte represents GPIO port pin 0, bit 1 represents //! GPIO port pin 1, and so on. Any bit that is not specified by \e ucPins //! is returned as a 0. Bits 31:8 should be ignored. // //***************************************************************************** long GPIOPinRead(unsigned long ulPort, unsigned char ucPins) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Return the pin value(s). // return(HWREG(ulPort + (GPIO_O_GPIO_DATA + (ucPins << 2)))); } //***************************************************************************** // //! Writes a value to the specified pin(s). //! //! \param ulPort is the base address of the GPIO port. //! \param ucPins is the bit-packed representation of the pin(s). //! \param ucVal is the value to write to the pin(s). //! //! Writes the corresponding bit values to the output pin(s) specified by //! \e ucPins. Writing to a pin configured as an input pin has no effect. //! //! The pin(s) are specified using a bit-packed byte, where each bit that is //! set identifies the pin to be accessed, and where bit 0 of the byte //! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on. //! //! \return None. // //***************************************************************************** void GPIOPinWrite(unsigned long ulPort, unsigned char ucPins, unsigned char ucVal) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Write the pins. // HWREG(ulPort + (GPIO_O_GPIO_DATA + (ucPins << 2))) = ucVal; } //***************************************************************************** // //! Enables a GPIO port as a trigger to start a DMA transaction. //! //! \param ulPort is the base address of the GPIO port. //! //! This function enables a GPIO port to be used as a trigger to start a uDMA //! transaction. The GPIO pin will still generate interrupts if the interrupt is //! enabled for the selected pin. //! //! \return None. // //***************************************************************************** void GPIODMATriggerEnable(unsigned long ulPort) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Set the pin as a DMA trigger. // if(ulPort == GPIOA0_BASE) { HWREG(COMMON_REG_BASE + COMMON_REG_O_APPS_GPIO_TRIG_EN) |= 0x1; } else if(ulPort == GPIOA1_BASE) { HWREG(COMMON_REG_BASE + COMMON_REG_O_APPS_GPIO_TRIG_EN) |= 0x2; } else if(ulPort == GPIOA2_BASE) { HWREG(COMMON_REG_BASE + COMMON_REG_O_APPS_GPIO_TRIG_EN) |= 0x4; } else if(ulPort == GPIOA3_BASE) { HWREG(COMMON_REG_BASE + COMMON_REG_O_APPS_GPIO_TRIG_EN) |= 0x8; } } //***************************************************************************** // //! Disables a GPIO port as a trigger to start a DMA transaction. //! //! \param ulPort is the base address of the GPIO port. //! //! This function disables a GPIO port to be used as a trigger to start a uDMA //! transaction. This function can be used to disable this feature if it was //! enabled via a call to GPIODMATriggerEnable(). //! //! \return None. // //***************************************************************************** void GPIODMATriggerDisable(unsigned long ulPort) { // // Check the arguments. // ASSERT(GPIOBaseValid(ulPort)); // // Set the pin as a DMA trigger. // if(ulPort == GPIOA0_BASE) { HWREG(COMMON_REG_BASE + COMMON_REG_O_APPS_GPIO_TRIG_EN) &= ~0x1; } else if(ulPort == GPIOA1_BASE) { HWREG(COMMON_REG_BASE + COMMON_REG_O_APPS_GPIO_TRIG_EN) &= ~0x2; } else if(ulPort == GPIOA2_BASE) { HWREG(COMMON_REG_BASE + COMMON_REG_O_APPS_GPIO_TRIG_EN) &= ~0x4; } else if(ulPort == GPIOA3_BASE) { HWREG(COMMON_REG_BASE + COMMON_REG_O_APPS_GPIO_TRIG_EN) &= ~0x8; } } // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/gpio.h000066400000000000000000000141731357706137100177440ustar00rootroot00000000000000//***************************************************************************** // // gpio.h // // Defines and Macros for GPIO API. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __GPIO_H__ #define __GPIO_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // The following values define the bit field for the ucPins argument to several // of the APIs. // //***************************************************************************** #define GPIO_PIN_0 0x00000001 // GPIO pin 0 #define GPIO_PIN_1 0x00000002 // GPIO pin 1 #define GPIO_PIN_2 0x00000004 // GPIO pin 2 #define GPIO_PIN_3 0x00000008 // GPIO pin 3 #define GPIO_PIN_4 0x00000010 // GPIO pin 4 #define GPIO_PIN_5 0x00000020 // GPIO pin 5 #define GPIO_PIN_6 0x00000040 // GPIO pin 6 #define GPIO_PIN_7 0x00000080 // GPIO pin 7 //***************************************************************************** // // Values that can be passed to GPIODirModeSet as the ulPinIO parameter, and // returned from GPIODirModeGet. // //***************************************************************************** #define GPIO_DIR_MODE_IN 0x00000000 // Pin is a GPIO input #define GPIO_DIR_MODE_OUT 0x00000001 // Pin is a GPIO output //***************************************************************************** // // Values that can be passed to GPIOIntTypeSet as the ulIntType parameter, and // returned from GPIOIntTypeGet. // //***************************************************************************** #define GPIO_FALLING_EDGE 0x00000000 // Interrupt on falling edge #define GPIO_RISING_EDGE 0x00000004 // Interrupt on rising edge #define GPIO_BOTH_EDGES 0x00000001 // Interrupt on both edges #define GPIO_LOW_LEVEL 0x00000002 // Interrupt on low level #define GPIO_HIGH_LEVEL 0x00000006 // Interrupt on high level //***************************************************************************** // // Values that can be passed to GPIOIntEnable() and GPIOIntDisable() functions // in the ulIntFlags parameter. // //***************************************************************************** #define GPIO_INT_DMA 0x00000100 #define GPIO_INT_PIN_0 0x00000001 #define GPIO_INT_PIN_1 0x00000002 #define GPIO_INT_PIN_2 0x00000004 #define GPIO_INT_PIN_3 0x00000008 #define GPIO_INT_PIN_4 0x00000010 #define GPIO_INT_PIN_5 0x00000020 #define GPIO_INT_PIN_6 0x00000040 #define GPIO_INT_PIN_7 0x00000080 //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** extern void GPIODirModeSet(unsigned long ulPort, unsigned char ucPins, unsigned long ulPinIO); extern unsigned long GPIODirModeGet(unsigned long ulPort, unsigned char ucPin); extern void GPIOIntTypeSet(unsigned long ulPort, unsigned char ucPins, unsigned long ulIntType); extern void GPIODMATriggerEnable(unsigned long ulPort); extern void GPIODMATriggerDisable(unsigned long ulPort); extern unsigned long GPIOIntTypeGet(unsigned long ulPort, unsigned char ucPin); extern void GPIOIntEnable(unsigned long ulPort, unsigned long ulIntFlags); extern void GPIOIntDisable(unsigned long ulPort, unsigned long ulIntFlags); extern long GPIOIntStatus(unsigned long ulPort, tBoolean bMasked); extern void GPIOIntClear(unsigned long ulPort, unsigned long ulIntFlags); extern void GPIOIntRegister(unsigned long ulPort, void (*pfnIntHandler)(void)); extern void GPIOIntUnregister(unsigned long ulPort); extern long GPIOPinRead(unsigned long ulPort, unsigned char ucPins); extern void GPIOPinWrite(unsigned long ulPort, unsigned char ucPins, unsigned char ucVal); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __GPIO_H__ micropython-1.12/ports/cc3200/hal/i2c.c000066400000000000000000001707411357706137100174620ustar00rootroot00000000000000//***************************************************************************** // // i2c.c // // Driver for Inter-IC (I2C) bus block. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup I2C_api //! @{ // //***************************************************************************** #include #include #include "inc/hw_i2c.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "debug.h" #include "i2c.h" #include "interrupt.h" //***************************************************************************** // // A mapping of I2C base address to interrupt number. // //***************************************************************************** static const uint32_t g_ppui32I2CIntMap[][2] = { { I2CA0_BASE, INT_I2CA0}, }; static const int_fast8_t g_i8I2CIntMapRows = sizeof(g_ppui32I2CIntMap) / sizeof(g_ppui32I2CIntMap[0]); //***************************************************************************** // //! \internal //! Checks an I2C base address. //! //! \param ui32Base is the base address of the I2C module. //! //! This function determines if a I2C module base address is valid. //! //! \return Returns \b true if the base address is valid and \b false //! otherwise. // //***************************************************************************** #ifdef DEBUG static bool _I2CBaseValid(uint32_t ui32Base) { return((ui32Base == I2CA0_BASE)); } #else #define _I2CBaseValid(ui32Base) (ui32Base) #endif //***************************************************************************** // //! \internal //! Gets the I2C interrupt number. //! //! \param ui32Base is the base address of the I2C Master module. //! //! Given a I2C base address, this function returns the corresponding //! interrupt number. //! //! \return Returns an I2C interrupt number, or 0 if \e ui32Base is invalid. // //***************************************************************************** static uint32_t _I2CIntNumberGet(uint32_t ui32Base) { int_fast8_t i8Idx, i8Rows; const uint32_t (*ppui32I2CIntMap)[2]; // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); ppui32I2CIntMap = g_ppui32I2CIntMap; i8Rows = g_i8I2CIntMapRows; // // Loop through the table that maps I2C base addresses to interrupt // numbers. // for(i8Idx = 0; i8Idx < i8Rows; i8Idx++) { // // See if this base address matches. // if(ppui32I2CIntMap[i8Idx][0] == ui32Base) { // // Return the corresponding interrupt number. // return(ppui32I2CIntMap[i8Idx][1]); } } // // The base address could not be found, so return an error. // return(0); } //***************************************************************************** // //! Initializes the I2C Master block. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui32I2CClk is the rate of the clock supplied to the I2C module. //! \param bFast set up for fast data transfers. //! //! This function initializes operation of the I2C Master block by configuring //! the bus speed for the master and enabling the I2C Master block. //! //! If the parameter \e bFast is \b true, then the master block is set up to //! transfer data at 400 Kbps; otherwise, it is set up to transfer data at //! 100 Kbps. If Fast Mode Plus (1 Mbps) is desired, software should manually //! write the I2CMTPR after calling this function. For High Speed (3.4 Mbps) //! mode, a specific command is used to switch to the faster clocks after the //! initial communication with the slave is done at either 100 Kbps or //! 400 Kbps. //! //! The peripheral clock is the same as the processor clock. This value is //! returned by SysCtlClockGet(), or it can be explicitly hard coded if it is //! constant and known (to save the code/execution overhead of a call to //! SysCtlClockGet()). //! //! \return None. // //***************************************************************************** void I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32SCLFreq) { uint32_t ui32TPR; // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Must enable the device before doing anything else. // I2CMasterEnable(ui32Base); // // Compute the clock divider that achieves the fastest speed less than or // equal to the desired speed. The numerator is biased to favor a larger // clock divider so that the resulting clock is always less than or equal // to the desired clock, never greater. // ui32TPR = ((80000000 + (2 * 10 * ui32SCLFreq) - 1) / (2 * 10 * ui32SCLFreq)) - 1; HWREG(ui32Base + I2C_O_MTPR) = ui32TPR; // // Check to see if this I2C peripheral is High-Speed enabled. If yes, also // choose the fastest speed that is less than or equal to 3.4 Mbps. // if(HWREG(ui32Base + I2C_O_PP) & I2C_PP_HS) { ui32TPR = ((80000000 + (2 * 3 * 3400000) - 1) / (2 * 3 * 3400000)) - 1; HWREG(ui32Base + I2C_O_MTPR) = I2C_MTPR_HS | ui32TPR; } } //***************************************************************************** // //! Initializes the I2C Slave block. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param ui8SlaveAddr 7-bit slave address //! //! This function initializes operation of the I2C Slave block by configuring //! the slave address and enabling the I2C Slave block. //! //! The parameter \e ui8SlaveAddr is the value that is compared against the //! slave address sent by an I2C master. //! //! \return None. // //***************************************************************************** void I2CSlaveInit(uint32_t ui32Base, uint8_t ui8SlaveAddr) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); ASSERT(!(ui8SlaveAddr & 0x80)); // // Must enable the device before doing anything else. // I2CSlaveEnable(ui32Base); // // Set up the slave address. // HWREG(ui32Base + I2C_O_SOAR) = ui8SlaveAddr; } //***************************************************************************** // //! Sets the I2C slave address. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param ui8AddrNum determines which slave address is set. //! \param ui8SlaveAddr is the 7-bit slave address //! //! This function writes the specified slave address. The \e ui32AddrNum field //! dictates which slave address is configured. For example, a value of 0 //! configures the primary address and a value of 1 configures the secondary. //! //! //! \return None. // //***************************************************************************** void I2CSlaveAddressSet(uint32_t ui32Base, uint8_t ui8AddrNum, uint8_t ui8SlaveAddr) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); ASSERT(!(ui8AddrNum > 1)); ASSERT(!(ui8SlaveAddr & 0x80)); // // Determine which slave address is being set. // switch(ui8AddrNum) { // // Set up the primary slave address. // case 0: { HWREG(ui32Base + I2C_O_SOAR) = ui8SlaveAddr; break; } // // Set up and enable the secondary slave address. // case 1: { HWREG(ui32Base + I2C_O_SOAR2) = I2C_SOAR2_OAR2EN | ui8SlaveAddr; break; } } } //***************************************************************************** // //! Enables the I2C Master block. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function enables operation of the I2C Master block. //! //! \return None. // //***************************************************************************** void I2CMasterEnable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Enable the master block. // HWREG(ui32Base + I2C_O_MCR) |= I2C_MCR_MFE; } //***************************************************************************** // //! Enables the I2C Slave block. //! //! \param ui32Base is the base address of the I2C Slave module. //! //! This fucntion enables operation of the I2C Slave block. //! //! \return None. // //***************************************************************************** void I2CSlaveEnable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Enable the clock to the slave block. // HWREG(ui32Base + I2C_O_MCR) |= I2C_MCR_SFE; // // Enable the slave. // HWREG(ui32Base + I2C_O_SCSR) = I2C_SCSR_DA; } //***************************************************************************** // //! Disables the I2C master block. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function disables operation of the I2C master block. //! //! \return None. // //***************************************************************************** void I2CMasterDisable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Disable the master block. // HWREG(ui32Base + I2C_O_MCR) &= ~(I2C_MCR_MFE); } //***************************************************************************** // //! Disables the I2C slave block. //! //! \param ui32Base is the base address of the I2C Slave module. //! //! This function disables operation of the I2C slave block. //! //! \return None. // //***************************************************************************** void I2CSlaveDisable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Disable the slave. // HWREG(ui32Base + I2C_O_SCSR) = 0; // // Disable the clock to the slave block. // HWREG(ui32Base + I2C_O_MCR) &= ~(I2C_MCR_SFE); } //***************************************************************************** // //! Registers an interrupt handler for the I2C module. //! //! \param ui32Base is the base address of the I2C Master module. //! \param pfnHandler is a pointer to the function to be called when the //! I2C interrupt occurs. //! //! This function sets the handler to be called when an I2C interrupt occurs. //! This function enables the global interrupt in the interrupt controller; //! specific I2C interrupts must be enabled via I2CMasterIntEnable() and //! I2CSlaveIntEnable(). If necessary, it is the interrupt handler's //! responsibility to clear the interrupt source via I2CMasterIntClear() and //! I2CSlaveIntClear(). //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void I2CIntRegister(uint32_t ui32Base, void (*pfnHandler)(void)) { uint32_t ui32Int; // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Determine the interrupt number based on the I2C port. // ui32Int = _I2CIntNumberGet(ui32Base); ASSERT(ui32Int != 0); // // Register the interrupt handler, returning an error if an error occurs. // IntRegister(ui32Int, pfnHandler); // // Enable the I2C interrupt. // IntEnable(ui32Int); } //***************************************************************************** // //! Unregisters an interrupt handler for the I2C module. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function clears the handler to be called when an I2C interrupt //! occurs. This function also masks off the interrupt in the interrupt r //! controller so that the interrupt handler no longer is called. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void I2CIntUnregister(uint32_t ui32Base) { uint32_t ui32Int; // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Determine the interrupt number based on the I2C port. // ui32Int = _I2CIntNumberGet(ui32Base); ASSERT(ui32Int != 0); // // Disable the interrupt. // IntDisable(ui32Int); // // Unregister the interrupt handler. // IntUnregister(ui32Int); } //***************************************************************************** // //! Enables the I2C Master interrupt. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function enables the I2C Master interrupt source. //! //! \return None. // //***************************************************************************** void I2CMasterIntEnable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Enable the master interrupt. // HWREG(ui32Base + I2C_O_MIMR) = 1; } //***************************************************************************** // //! Enables individual I2C Master interrupt sources. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui32IntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated I2C Master interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ui32IntFlags parameter is the logical OR of any of the following: //! //! - \b I2C_MASTER_INT_RX_FIFO_FULL - RX FIFO Full interrupt //! - \b I2C_MASTER_INT_TX_FIFO_EMPTY - TX FIFO Empty interrupt //! - \b I2C_MASTER_INT_RX_FIFO_REQ - RX FIFO Request interrupt //! - \b I2C_MASTER_INT_TX_FIFO_REQ - TX FIFO Request interrupt //! - \b I2C_MASTER_INT_ARB_LOST - Arbitration Lost interrupt //! - \b I2C_MASTER_INT_STOP - Stop Condition interrupt //! - \b I2C_MASTER_INT_START - Start Condition interrupt //! - \b I2C_MASTER_INT_NACK - Address/Data NACK interrupt //! - \b I2C_MASTER_INT_TX_DMA_DONE - TX DMA Complete interrupt //! - \b I2C_MASTER_INT_RX_DMA_DONE - RX DMA Complete interrupt //! - \b I2C_MASTER_INT_TIMEOUT - Clock Timeout interrupt //! - \b I2C_MASTER_INT_DATA - Data interrupt //! //! //! \return None. // //***************************************************************************** void I2CMasterIntEnableEx(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Enable the master interrupt. // HWREG(ui32Base + I2C_O_MIMR) |= ui32IntFlags; } //***************************************************************************** // //! Enables the I2C Slave interrupt. //! //! \param ui32Base is the base address of the I2C Slave module. //! //! This function enables the I2C Slave interrupt source. //! //! \return None. // //***************************************************************************** void I2CSlaveIntEnable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Enable the slave interrupt. // HWREG(ui32Base + I2C_O_SIMR) |= I2C_SLAVE_INT_DATA; } //***************************************************************************** // //! Enables individual I2C Slave interrupt sources. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param ui32IntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated I2C Slave interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ui32IntFlags parameter is the logical OR of any of the following: //! //! - \b I2C_SLAVE_INT_RX_FIFO_FULL - RX FIFO Full interrupt //! - \b I2C_SLAVE_INT_TX_FIFO_EMPTY - TX FIFO Empty interrupt //! - \b I2C_SLAVE_INT_RX_FIFO_REQ - RX FIFO Request interrupt //! - \b I2C_SLAVE_INT_TX_FIFO_REQ - TX FIFO Request interrupt //! - \b I2C_SLAVE_INT_TX_DMA_DONE - TX DMA Complete interrupt //! - \b I2C_SLAVE_INT_RX_DMA_DONE - RX DMA Complete interrupt //! - \b I2C_SLAVE_INT_STOP - Stop condition detected interrupt //! - \b I2C_SLAVE_INT_START - Start condition detected interrupt //! - \b I2C_SLAVE_INT_DATA - Data interrupt //! //! //! \return None. // //***************************************************************************** void I2CSlaveIntEnableEx(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Enable the slave interrupt. // HWREG(ui32Base + I2C_O_SIMR) |= ui32IntFlags; } //***************************************************************************** // //! Disables the I2C Master interrupt. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function disables the I2C Master interrupt source. //! //! \return None. // //***************************************************************************** void I2CMasterIntDisable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Disable the master interrupt. // HWREG(ui32Base + I2C_O_MIMR) = 0; } //***************************************************************************** // //! Disables individual I2C Master interrupt sources. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui32IntFlags is the bit mask of the interrupt sources to be //! disabled. //! //! This function disables the indicated I2C Master interrupt sources. Only //! the sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ui32IntFlags parameter has the same definition as the //! \e ui32IntFlags parameter to I2CMasterIntEnableEx(). //! //! \return None. // //***************************************************************************** void I2CMasterIntDisableEx(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Disable the master interrupt. // HWREG(ui32Base + I2C_O_MIMR) &= ~ui32IntFlags; } //***************************************************************************** // //! Disables the I2C Slave interrupt. //! //! \param ui32Base is the base address of the I2C Slave module. //! //! This function disables the I2C Slave interrupt source. //! //! \return None. // //***************************************************************************** void I2CSlaveIntDisable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Disable the slave interrupt. // HWREG(ui32Base + I2C_O_SIMR) &= ~I2C_SLAVE_INT_DATA; } //***************************************************************************** // //! Disables individual I2C Slave interrupt sources. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param ui32IntFlags is the bit mask of the interrupt sources to be //! disabled. //! //! This function disables the indicated I2C Slave interrupt sources. Only //! the sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ui32IntFlags parameter has the same definition as the //! \e ui32IntFlags parameter to I2CSlaveIntEnableEx(). //! //! \return None. // //***************************************************************************** void I2CSlaveIntDisableEx(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Disable the slave interrupt. // HWREG(ui32Base + I2C_O_SIMR) &= ~ui32IntFlags; } //***************************************************************************** // //! Gets the current I2C Master interrupt status. //! //! \param ui32Base is the base address of the I2C Master module. //! \param bMasked is false if the raw interrupt status is requested and //! true if the masked interrupt status is requested. //! //! This function returns the interrupt status for the I2C Master module. //! Either the raw interrupt status or the status of interrupts that are //! allowed to reflect to the processor can be returned. //! //! \return The current interrupt status, returned as \b true if active //! or \b false if not active. // //***************************************************************************** bool I2CMasterIntStatus(uint32_t ui32Base, bool bMasked) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return either the interrupt status or the raw interrupt status as // requested. // if(bMasked) { return((HWREG(ui32Base + I2C_O_MMIS)) ? true : false); } else { return((HWREG(ui32Base + I2C_O_MRIS)) ? true : false); } } //***************************************************************************** // //! Gets the current I2C Master interrupt status. //! //! \param ui32Base is the base address of the I2C Master module. //! \param bMasked is false if the raw interrupt status is requested and //! true if the masked interrupt status is requested. //! //! This function returns the interrupt status for the I2C Master module. //! Either the raw interrupt status or the status of interrupts that are //! allowed to reflect to the processor can be returned. //! //! \return Returns the current interrupt status, enumerated as a bit field of //! values described in I2CMasterIntEnableEx(). // //***************************************************************************** uint32_t I2CMasterIntStatusEx(uint32_t ui32Base, bool bMasked) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return either the interrupt status or the raw interrupt status as // requested. // if(bMasked) { return(HWREG(ui32Base + I2C_O_MMIS)); } else { return(HWREG(ui32Base + I2C_O_MRIS)); } } //***************************************************************************** // //! Gets the current I2C Slave interrupt status. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param bMasked is false if the raw interrupt status is requested and //! true if the masked interrupt status is requested. //! //! This function returns the interrupt status for the I2C Slave module. //! Either the raw interrupt status or the status of interrupts that are //! allowed to reflect to the processor can be returned. //! //! \return The current interrupt status, returned as \b true if active //! or \b false if not active. // //***************************************************************************** bool I2CSlaveIntStatus(uint32_t ui32Base, bool bMasked) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return either the interrupt status or the raw interrupt status as // requested. // if(bMasked) { return((HWREG(ui32Base + I2C_O_SMIS)) ? true : false); } else { return((HWREG(ui32Base + I2C_O_SRIS)) ? true : false); } } //***************************************************************************** // //! Gets the current I2C Slave interrupt status. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param bMasked is false if the raw interrupt status is requested and //! true if the masked interrupt status is requested. //! //! This function returns the interrupt status for the I2C Slave module. //! Either the raw interrupt status or the status of interrupts that are //! allowed to reflect to the processor can be returned. //! //! \return Returns the current interrupt status, enumerated as a bit field of //! values described in I2CSlaveIntEnableEx(). // //***************************************************************************** uint32_t I2CSlaveIntStatusEx(uint32_t ui32Base, bool bMasked) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return either the interrupt status or the raw interrupt status as // requested. // if(bMasked) { return(HWREG(ui32Base + I2C_O_SMIS)); } else { return(HWREG(ui32Base + I2C_O_SRIS)); } } //***************************************************************************** // //! Clears I2C Master interrupt sources. //! //! \param ui32Base is the base address of the I2C Master module. //! //! The I2C Master interrupt source is cleared, so that it no longer //! asserts. This function must be called in the interrupt handler to keep the //! interrupt from being triggered again immediately upon exit. //! //! \note Because there is a write buffer in the Cortex-M processor, it may //! take several clock cycles before the interrupt source is actually cleared. //! Therefore, it is recommended that the interrupt source be cleared early in //! the interrupt handler (as opposed to the very last action) to avoid //! returning from the interrupt handler before the interrupt source is //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). //! //! \return None. // //***************************************************************************** void I2CMasterIntClear(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Clear the I2C master interrupt source. // HWREG(ui32Base + I2C_O_MICR) = I2C_MICR_IC; // // Workaround for I2C master interrupt clear errata for some // devices. For later devices, this write is ignored and therefore // harmless (other than the slight performance hit). // HWREG(ui32Base + I2C_O_MMIS) = I2C_MICR_IC; } //***************************************************************************** // //! Clears I2C Master interrupt sources. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui32IntFlags is a bit mask of the interrupt sources to be cleared. //! //! The specified I2C Master interrupt sources are cleared, so that they no //! longer assert. This function must be called in the interrupt handler to //! keep the interrupt from being triggered again immediately upon exit. //! //! The \e ui32IntFlags parameter has the same definition as the //! \e ui32IntFlags parameter to I2CMasterIntEnableEx(). //! //! \note Because there is a write buffer in the Cortex-M processor, it may //! take several clock cycles before the interrupt source is actually cleared. //! Therefore, it is recommended that the interrupt source be cleared early in //! the interrupt handler (as opposed to the very last action) to avoid //! returning from the interrupt handler before the interrupt source is //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). //! //! \return None. // //***************************************************************************** void I2CMasterIntClearEx(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Clear the I2C master interrupt source. // HWREG(ui32Base + I2C_O_MICR) = ui32IntFlags; } //***************************************************************************** // //! Clears I2C Slave interrupt sources. //! //! \param ui32Base is the base address of the I2C Slave module. //! //! The I2C Slave interrupt source is cleared, so that it no longer asserts. //! This function must be called in the interrupt handler to keep the interrupt //! from being triggered again immediately upon exit. //! //! \note Because there is a write buffer in the Cortex-M processor, it may //! take several clock cycles before the interrupt source is actually cleared. //! Therefore, it is recommended that the interrupt source be cleared early in //! the interrupt handler (as opposed to the very last action) to avoid //! returning from the interrupt handler before the interrupt source is //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). //! //! \return None. // //***************************************************************************** void I2CSlaveIntClear(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Clear the I2C slave interrupt source. // HWREG(ui32Base + I2C_O_SICR) = I2C_SICR_DATAIC; } //***************************************************************************** // //! Clears I2C Slave interrupt sources. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param ui32IntFlags is a bit mask of the interrupt sources to be cleared. //! //! The specified I2C Slave interrupt sources are cleared, so that they no //! longer assert. This function must be called in the interrupt handler to //! keep the interrupt from being triggered again immediately upon exit. //! //! The \e ui32IntFlags parameter has the same definition as the //! \e ui32IntFlags parameter to I2CSlaveIntEnableEx(). //! //! \note Because there is a write buffer in the Cortex-M processor, it may //! take several clock cycles before the interrupt source is actually cleared. //! Therefore, it is recommended that the interrupt source be cleared early in //! the interrupt handler (as opposed to the very last action) to avoid //! returning from the interrupt handler before the interrupt source is //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). //! //! \return None. // //***************************************************************************** void I2CSlaveIntClearEx(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Clear the I2C slave interrupt source. // HWREG(ui32Base + I2C_O_SICR) = ui32IntFlags; } //***************************************************************************** // //! Sets the address that the I2C Master places on the bus. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui8SlaveAddr 7-bit slave address //! \param bReceive flag indicating the type of communication with the slave //! //! This function configures the address that the I2C Master places on the //! bus when initiating a transaction. When the \e bReceive parameter is set //! to \b true, the address indicates that the I2C Master is initiating a //! read from the slave; otherwise the address indicates that the I2C //! Master is initiating a write to the slave. //! //! \return None. // //***************************************************************************** void I2CMasterSlaveAddrSet(uint32_t ui32Base, uint8_t ui8SlaveAddr, bool bReceive) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); ASSERT(!(ui8SlaveAddr & 0x80)); // // Set the address of the slave with which the master will communicate. // HWREG(ui32Base + I2C_O_MSA) = (ui8SlaveAddr << 1) | bReceive; } //***************************************************************************** // //! Reads the state of the SDA and SCL pins. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function returns the state of the I2C bus by providing the real time //! values of the SDA and SCL pins. //! //! //! \return Returns the state of the bus with SDA in bit position 1 and SCL in //! bit position 0. // //***************************************************************************** uint32_t I2CMasterLineStateGet(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return the line state. // return(HWREG(ui32Base + I2C_O_MBMON)); } //***************************************************************************** // //! Indicates whether or not the I2C Master is busy. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function returns an indication of whether or not the I2C Master is //! busy transmitting or receiving data. //! //! \return Returns \b true if the I2C Master is busy; otherwise, returns //! \b false. // //***************************************************************************** bool I2CMasterBusy(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return the busy status. // if(HWREG(ui32Base + I2C_O_MCS) & I2C_MCS_BUSY) { return(true); } else { return(false); } } //***************************************************************************** // //! Indicates whether or not the I2C bus is busy. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function returns an indication of whether or not the I2C bus is busy. //! This function can be used in a multi-master environment to determine if //! another master is currently using the bus. //! //! \return Returns \b true if the I2C bus is busy; otherwise, returns //! \b false. // //***************************************************************************** bool I2CMasterBusBusy(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return the bus busy status. // if(HWREG(ui32Base + I2C_O_MCS) & I2C_MCS_BUSBSY) { return(true); } else { return(false); } } //***************************************************************************** // //! Controls the state of the I2C Master module. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui32Cmd command to be issued to the I2C Master module. //! //! This function is used to control the state of the Master module send and //! receive operations. The \e ui8Cmd parameter can be one of the following //! values: //! //! - \b I2C_MASTER_CMD_SINGLE_SEND //! - \b I2C_MASTER_CMD_SINGLE_RECEIVE //! - \b I2C_MASTER_CMD_BURST_SEND_START //! - \b I2C_MASTER_CMD_BURST_SEND_CONT //! - \b I2C_MASTER_CMD_BURST_SEND_FINISH //! - \b I2C_MASTER_CMD_BURST_SEND_ERROR_STOP //! - \b I2C_MASTER_CMD_BURST_RECEIVE_START //! - \b I2C_MASTER_CMD_BURST_RECEIVE_CONT //! - \b I2C_MASTER_CMD_BURST_RECEIVE_FINISH //! - \b I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP //! - \b I2C_MASTER_CMD_QUICK_COMMAND //! - \b I2C_MASTER_CMD_HS_MASTER_CODE_SEND //! - \b I2C_MASTER_CMD_FIFO_SINGLE_SEND //! - \b I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE //! - \b I2C_MASTER_CMD_FIFO_BURST_SEND_START //! - \b I2C_MASTER_CMD_FIFO_BURST_SEND_CONT //! - \b I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH //! - \b I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP //! - \b I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START //! - \b I2C_MASTER_CMD_FIFO_BURST_RECEIVE_CONT //! - \b I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH //! - \b I2C_MASTER_CMD_FIFO_BURST_RECEIVE_ERROR_STOP //! //! //! \return None. // //***************************************************************************** void I2CMasterControl(uint32_t ui32Base, uint32_t ui32Cmd) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); ASSERT((ui32Cmd == I2C_MASTER_CMD_SINGLE_SEND) || (ui32Cmd == I2C_MASTER_CMD_SINGLE_RECEIVE) || (ui32Cmd == I2C_MASTER_CMD_BURST_SEND_START) || (ui32Cmd == I2C_MASTER_CMD_BURST_SEND_CONT) || (ui32Cmd == I2C_MASTER_CMD_BURST_SEND_FINISH) || (ui32Cmd == I2C_MASTER_CMD_BURST_SEND_ERROR_STOP) || (ui32Cmd == I2C_MASTER_CMD_BURST_RECEIVE_START) || (ui32Cmd == I2C_MASTER_CMD_BURST_RECEIVE_CONT) || (ui32Cmd == I2C_MASTER_CMD_BURST_RECEIVE_FINISH) || (ui32Cmd == I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP) || (ui32Cmd == I2C_MASTER_CMD_QUICK_COMMAND) || (ui32Cmd == I2C_MASTER_CMD_FIFO_SINGLE_SEND) || (ui32Cmd == I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE) || (ui32Cmd == I2C_MASTER_CMD_FIFO_BURST_SEND_START) || (ui32Cmd == I2C_MASTER_CMD_FIFO_BURST_SEND_CONT) || (ui32Cmd == I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH) || (ui32Cmd == I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP) || (ui32Cmd == I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START) || (ui32Cmd == I2C_MASTER_CMD_FIFO_BURST_RECEIVE_CONT) || (ui32Cmd == I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH) || (ui32Cmd == I2C_MASTER_CMD_FIFO_BURST_RECEIVE_ERROR_STOP) || (ui32Cmd == I2C_MASTER_CMD_HS_MASTER_CODE_SEND)); // // Send the command. // HWREG(ui32Base + I2C_O_MCS) = ui32Cmd; } //***************************************************************************** // //! Gets the error status of the I2C Master module. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function is used to obtain the error status of the Master module send //! and receive operations. //! //! \return Returns the error status, as one of \b I2C_MASTER_ERR_NONE, //! \b I2C_MASTER_ERR_ADDR_ACK, \b I2C_MASTER_ERR_DATA_ACK, or //! \b I2C_MASTER_ERR_ARB_LOST. // //***************************************************************************** uint32_t I2CMasterErr(uint32_t ui32Base) { uint32_t ui32Err; // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Get the raw error state // ui32Err = HWREG(ui32Base + I2C_O_MCS); // // If the I2C master is busy, then all the other bit are invalid, and // don't have an error to report. // if(ui32Err & I2C_MCS_BUSY) { return(I2C_MASTER_ERR_NONE); } // // Check for errors. // if(ui32Err & (I2C_MCS_ERROR | I2C_MCS_ARBLST)) { return(ui32Err & (I2C_MCS_ARBLST | I2C_MCS_ACK | I2C_MCS_ADRACK)); } else { return(I2C_MASTER_ERR_NONE); } } //***************************************************************************** // //! Transmits a byte from the I2C Master. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui8Data data to be transmitted from the I2C Master. //! //! This function places the supplied data into I2C Master Data Register. //! //! \return None. // //***************************************************************************** void I2CMasterDataPut(uint32_t ui32Base, uint8_t ui8Data) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Write the byte. // HWREG(ui32Base + I2C_O_MDR) = ui8Data; } //***************************************************************************** // //! Receives a byte that has been sent to the I2C Master. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function reads a byte of data from the I2C Master Data Register. //! //! \return Returns the byte received from by the I2C Master, cast as an //! uint32_t. // //***************************************************************************** uint32_t I2CMasterDataGet(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Read a byte. // return(HWREG(ui32Base + I2C_O_MDR)); } //***************************************************************************** // //! Sets the Master clock timeout value. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui32Value is the number of I2C clocks before the timeout is //! asserted. //! //! This function enables and configures the clock low timeout feature in the //! I2C peripheral. This feature is implemented as a 12-bit counter, with the //! upper 8-bits being programmable. For example, to program a timeout of 20ms //! with a 100kHz SCL frequency, \e ui32Value would be 0x7d. //! //! //! \return None. // //***************************************************************************** void I2CMasterTimeoutSet(uint32_t ui32Base, uint32_t ui32Value) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Write the timeout value. // HWREG(ui32Base + I2C_O_MCLKOCNT) = ui32Value; } //***************************************************************************** // //! Configures ACK override behavior of the I2C Slave. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param bEnable enables or disables ACK override. //! //! This function enables or disables ACK override, allowing the user //! application to drive the value on SDA during the ACK cycle. //! //! //! \return None. // //***************************************************************************** void I2CSlaveACKOverride(uint32_t ui32Base, bool bEnable) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Enable or disable based on bEnable. // if(bEnable) { HWREG(ui32Base + I2C_O_SACKCTL) |= I2C_SACKCTL_ACKOEN; } else { HWREG(ui32Base + I2C_O_SACKCTL) &= ~I2C_SACKCTL_ACKOEN; } } //***************************************************************************** // //! Writes the ACK value. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param bACK chooses whether to ACK (true) or NACK (false) the transfer. //! //! This function puts the desired ACK value on SDA during the ACK cycle. The //! value written is only valid when ACK override is enabled using //! I2CSlaveACKOverride(). //! //! \return None. // //***************************************************************************** void I2CSlaveACKValueSet(uint32_t ui32Base, bool bACK) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // ACK or NACK based on the value of bACK. // if(bACK) { HWREG(ui32Base + I2C_O_SACKCTL) &= ~I2C_SACKCTL_ACKOVAL; } else { HWREG(ui32Base + I2C_O_SACKCTL) |= I2C_SACKCTL_ACKOVAL; } } //***************************************************************************** // //! Gets the I2C Slave module status //! //! \param ui32Base is the base address of the I2C Slave module. //! //! This function returns the action requested from a master, if any. //! Possible values are: //! //! - \b I2C_SLAVE_ACT_NONE //! - \b I2C_SLAVE_ACT_RREQ //! - \b I2C_SLAVE_ACT_TREQ //! - \b I2C_SLAVE_ACT_RREQ_FBR //! - \b I2C_SLAVE_ACT_OWN2SEL //! - \b I2C_SLAVE_ACT_QCMD //! - \b I2C_SLAVE_ACT_QCMD_DATA //! //! \note Not all devices support the second I2C slave's own address //! or the quick command function. Please consult the device data sheet to //! determine if these features are supported. //! //! \return Returns \b I2C_SLAVE_ACT_NONE to indicate that no action has been //! requested of the I2C Slave module, \b I2C_SLAVE_ACT_RREQ to indicate that //! an I2C master has sent data to the I2C Slave module, \b I2C_SLAVE_ACT_TREQ //! to indicate that an I2C master has requested that the I2C Slave module send //! data, \b I2C_SLAVE_ACT_RREQ_FBR to indicate that an I2C master has sent //! data to the I2C slave and the first byte following the slave's own address //! has been received, \b I2C_SLAVE_ACT_OWN2SEL to indicate that the second I2C //! slave address was matched, \b I2C_SLAVE_ACT_QCMD to indicate that a quick //! command was received, and \b I2C_SLAVE_ACT_QCMD_DATA to indicate that the //! data bit was set when the quick command was received. // //***************************************************************************** uint32_t I2CSlaveStatus(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return the slave status. // return(HWREG(ui32Base + I2C_O_SCSR)); } //***************************************************************************** // //! Transmits a byte from the I2C Slave. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param ui8Data is the data to be transmitted from the I2C Slave //! //! This function places the supplied data into I2C Slave Data Register. //! //! \return None. // //***************************************************************************** void I2CSlaveDataPut(uint32_t ui32Base, uint8_t ui8Data) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Write the byte. // HWREG(ui32Base + I2C_O_SDR) = ui8Data; } //***************************************************************************** // //! Receives a byte that has been sent to the I2C Slave. //! //! \param ui32Base is the base address of the I2C Slave module. //! //! This function reads a byte of data from the I2C Slave Data Register. //! //! \return Returns the byte received from by the I2C Slave, cast as an //! uint32_t. // //***************************************************************************** uint32_t I2CSlaveDataGet(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Read a byte. // return(HWREG(ui32Base + I2C_O_SDR)); } //***************************************************************************** // //! Configures the I2C transmit (TX) FIFO. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! \param ui32Config is the configuration of the FIFO using specified macros. //! //! This configures the I2C peripheral's transmit FIFO. The transmit FIFO can //! be used by the master or slave, but not both. The following macros are //! used to configure the TX FIFO behavior for master or slave, with or without //! DMA: //! //! \b I2C_FIFO_CFG_TX_MASTER, \b I2C_FIFO_CFG_TX_SLAVE, //! \b I2C_FIFO_CFG_TX_MASTER_DMA, \b I2C_FIFO_CFG_TX_SLAVE_DMA //! //! To select the trigger level, one of the following macros should be used: //! //! \b I2C_FIFO_CFG_TX_TRIG_1, \b I2C_FIFO_CFG_TX_TRIG_2, //! \b I2C_FIFO_CFG_TX_TRIG_3, \b I2C_FIFO_CFG_TX_TRIG_4, //! \b I2C_FIFO_CFG_TX_TRIG_5, \b I2C_FIFO_CFG_TX_TRIG_6, //! \b I2C_FIFO_CFG_TX_TRIG_7, \b I2C_FIFO_CFG_TX_TRIG_8 //! //! //! \return None. // //***************************************************************************** void I2CTxFIFOConfigSet(uint32_t ui32Base, uint32_t ui32Config) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Clear transmit configuration data. // HWREG(ui32Base + I2C_O_FIFOCTL) &= 0xffff0000; // // Store new transmit configuration data. // HWREG(ui32Base + I2C_O_FIFOCTL) |= ui32Config; } //***************************************************************************** // //! Flushes the transmit (TX) FIFO. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! //! This function flushes the I2C transmit FIFO. //! //! //! \return None. // //***************************************************************************** void I2CTxFIFOFlush(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Flush the TX FIFO. // HWREG(ui32Base + I2C_O_FIFOCTL) |= I2C_FIFOCTL_TXFLUSH; } //***************************************************************************** // //! Configures the I2C receive (RX) FIFO. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! \param ui32Config is the configuration of the FIFO using specified macros. //! //! This configures the I2C peripheral's receive FIFO. The receive FIFO can be //! used by the master or slave, but not both. The following macros are used //! to configure the RX FIFO behavior for master or slave, with or without DMA: //! //! \b I2C_FIFO_CFG_RX_MASTER, \b I2C_FIFO_CFG_RX_SLAVE, //! \b I2C_FIFO_CFG_RX_MASTER_DMA, \b I2C_FIFO_CFG_RX_SLAVE_DMA //! //! To select the trigger level, one of the following macros should be used: //! //! \b I2C_FIFO_CFG_RX_TRIG_1, \b I2C_FIFO_CFG_RX_TRIG_2, //! \b I2C_FIFO_CFG_RX_TRIG_3, \b I2C_FIFO_CFG_RX_TRIG_4, //! \b I2C_FIFO_CFG_RX_TRIG_5, \b I2C_FIFO_CFG_RX_TRIG_6, //! \b I2C_FIFO_CFG_RX_TRIG_7, \b I2C_FIFO_CFG_RX_TRIG_8 //! //! //! \return None. // //***************************************************************************** void I2CRxFIFOConfigSet(uint32_t ui32Base, uint32_t ui32Config) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Clear receive configuration data. // HWREG(ui32Base + I2C_O_FIFOCTL) &= 0x0000ffff; // // Store new receive configuration data. // HWREG(ui32Base + I2C_O_FIFOCTL) |= ui32Config; } //***************************************************************************** // //! Flushes the receive (RX) FIFO. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! //! This function flushes the I2C receive FIFO. //! //! \return None. // //***************************************************************************** void I2CRxFIFOFlush(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Flush the TX FIFO. // HWREG(ui32Base + I2C_O_FIFOCTL) |= I2C_FIFOCTL_RXFLUSH; } //***************************************************************************** // //! Gets the current FIFO status. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! //! This function retrieves the status for both the transmit (TX) and receive //! (RX) FIFOs. The trigger level for the transmit FIFO is set using //! I2CTxFIFOConfigSet() and for the receive FIFO using I2CTxFIFOConfigSet(). //! //! \return Returns the FIFO status, enumerated as a bit field containing //! \b I2C_FIFO_RX_BELOW_TRIG_LEVEL, \b I2C_FIFO_RX_FULL, \b I2C_FIFO_RX_EMPTY, //! \b I2C_FIFO_TX_BELOW_TRIG_LEVEL, \b I2C_FIFO_TX_FULL, and //! \b I2C_FIFO_TX_EMPTY. // //***************************************************************************** uint32_t I2CFIFOStatus(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Return the contents of the FIFO status register. // return(HWREG(ui32Base + I2C_O_FIFOSTATUS)); } //***************************************************************************** // //! Writes a data byte to the I2C transmit FIFO. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! \param ui8Data is the data to be placed into the transmit FIFO. //! //! This function adds a byte of data to the I2C transmit FIFO. If there is //! no space available in the FIFO, this function waits for space to become //! available before returning. //! //! \return None. // //***************************************************************************** void I2CFIFODataPut(uint32_t ui32Base, uint8_t ui8Data) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Wait until there is space. // while(HWREG(ui32Base + I2C_O_FIFOSTATUS) & I2C_FIFOSTATUS_TXFF) { } // // Place data into the FIFO. // HWREG(ui32Base + I2C_O_FIFODATA) = ui8Data; } //***************************************************************************** // //! Writes a data byte to the I2C transmit FIFO. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! \param ui8Data is the data to be placed into the transmit FIFO. //! //! This function adds a byte of data to the I2C transmit FIFO. If there is //! no space available in the FIFO, this function returns a zero. //! //! \return The number of elements added to the I2C transmit FIFO. // //***************************************************************************** uint32_t I2CFIFODataPutNonBlocking(uint32_t ui32Base, uint8_t ui8Data) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // If FIFO is full, return zero. // if(HWREG(ui32Base + I2C_O_FIFOSTATUS) & I2C_FIFOSTATUS_TXFF) { return(0); } else { HWREG(ui32Base + I2C_O_FIFODATA) = ui8Data; return(1); } } //***************************************************************************** // //! Reads a byte from the I2C receive FIFO. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! //! This function reads a byte of data from I2C receive FIFO and places it in //! the location specified by the \e pui8Data parameter. If there is no data //! available, this function waits until data is received before returning. //! //! \return The data byte. // //***************************************************************************** uint32_t I2CFIFODataGet(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Wait until there is data to read. // while(HWREG(ui32Base + I2C_O_FIFOSTATUS) & I2C_FIFOSTATUS_RXFE) { } // // Read a byte. // return(HWREG(ui32Base + I2C_O_FIFODATA)); } //***************************************************************************** // //! Reads a byte from the I2C receive FIFO. //! //! \param ui32Base is the base address of the I2C Master or Slave module. //! \param pui8Data is a pointer where the read data is stored. //! //! This function reads a byte of data from I2C receive FIFO and places it in //! the location specified by the \e pui8Data parameter. If there is no data //! available, this functions returns 0. //! //! \return The number of elements read from the I2C receive FIFO. // //***************************************************************************** uint32_t I2CFIFODataGetNonBlocking(uint32_t ui32Base, uint8_t *pui8Data) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // If nothing in the FIFO, return zero. // if(HWREG(ui32Base + I2C_O_FIFOSTATUS) & I2C_FIFOSTATUS_RXFE) { return(0); } else { *pui8Data = HWREG(ui32Base + I2C_O_FIFODATA); return(1); } } //***************************************************************************** // //! Set the burst length for a I2C master FIFO operation. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui8Length is the length of the burst transfer. //! //! This function configures the burst length for a I2C Master FIFO operation. //! The burst field is limited to 8 bits or 256 bytes. The burst length //! applies to a single I2CMCS BURST operation meaning that it specifies the //! burst length for only the current operation (can be TX or RX). Each burst //! operation must configure the burst length prior to writing the BURST bit //! in the I2CMCS using I2CMasterControl(). //! //! \return None. // //***************************************************************************** void I2CMasterBurstLengthSet(uint32_t ui32Base, uint8_t ui8Length) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base) && (ui8Length < 255)); // // Set the burst length. // HWREG(ui32Base + I2C_O_MBLEN) = ui8Length; } //***************************************************************************** // //! Returns the current value of the burst transfer counter. //! //! \param ui32Base is the base address of the I2C Master module. //! //! This function returns the current value of the burst transfer counter that //! is used by the FIFO mechanism. Software can use this value to determine //! how many bytes remain in a transfer, or where in the transfer the burst //! operation was if an error has occurred. //! //! \return None. // //***************************************************************************** uint32_t I2CMasterBurstCountGet(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Get burst count. // return(HWREG(ui32Base + I2C_O_MBCNT)); } //***************************************************************************** // //! Configures the I2C Master glitch filter. //! //! \param ui32Base is the base address of the I2C Master module. //! \param ui32Config is the glitch filter configuration. //! //! This function configures the I2C Master glitch filter. The value passed in //! to \e ui32Config determines the sampling range of the glitch filter, which //! is configurable between 1 and 32 system clock cycles. The default //! configuration of the glitch filter is 0 system clock cycles, which means //! that it's disabled. //! //! The \e ui32Config field should be any of the following values: //! //! - \b I2C_MASTER_GLITCH_FILTER_DISABLED //! - \b I2C_MASTER_GLITCH_FILTER_1 //! - \b I2C_MASTER_GLITCH_FILTER_2 //! - \b I2C_MASTER_GLITCH_FILTER_3 //! - \b I2C_MASTER_GLITCH_FILTER_4 //! - \b I2C_MASTER_GLITCH_FILTER_8 //! - \b I2C_MASTER_GLITCH_FILTER_16 //! - \b I2C_MASTER_GLITCH_FILTER_32 //! //! \return None. // //***************************************************************************** void I2CMasterGlitchFilterConfigSet(uint32_t ui32Base, uint32_t ui32Config) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Configure the glitch filter field of MTPR. // HWREG(ui32Base + I2C_O_MTPR) |= ui32Config; } //***************************************************************************** // //! Enables FIFO usage for the I2C Slave module. //! //! \param ui32Base is the base address of the I2C Slave module. //! \param ui32Config is the desired FIFO configuration of the I2C Slave. //! //! This function configures the I2C Slave module to use the FIFO(s). This //! function should be used in combination with I2CTxFIFOConfigSet() and/or //! I2CRxFIFOConfigSet(), which configure the FIFO trigger level and tell //! the FIFO hardware whether to interact with the I2C Master or Slave. The //! application appropriate combination of \b I2C_SLAVE_TX_FIFO_ENABLE and //! \b I2C_SLAVE_RX_FIFO_ENABLE should be passed in to the \e ui32Config //! field. //! //! The Slave I2CSCSR register is write-only, so any call to I2CSlaveEnable(), //! I2CSlaveDisable or I2CSlaveFIFOEnable() overwrites the slave configuration. //! Therefore, application software should call I2CSlaveEnable() followed by //! I2CSlaveFIFOEnable() with the desired FIFO configuration. //! //! \return None. // //***************************************************************************** void I2CSlaveFIFOEnable(uint32_t ui32Base, uint32_t ui32Config) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Enable the FIFOs for the slave. // HWREG(ui32Base + I2C_O_SCSR) = ui32Config | I2C_SCSR_DA; } //***************************************************************************** // //! Disable FIFO usage for the I2C Slave module. //! //! \param ui32Base is the base address of the I2C Slave module. //! //! This function disables the FIFOs for the I2C Slave. After calling this //! this function, the FIFOs are disabled, but the Slave remains active. //! //! \return None. // //***************************************************************************** void I2CSlaveFIFODisable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(_I2CBaseValid(ui32Base)); // // Disable slave FIFOs. // HWREG(ui32Base + I2C_O_SCSR) = I2C_SCSR_DA; } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/i2c.h000066400000000000000000000433111357706137100174570ustar00rootroot00000000000000//***************************************************************************** // // i2c.h // // Prototypes for the I2C Driver. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __DRIVERLIB_I2C_H__ #define __DRIVERLIB_I2C_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // Defines for the API. // //***************************************************************************** //***************************************************************************** // // Interrupt defines. // //***************************************************************************** #define I2C_INT_MASTER 0x00000001 #define I2C_INT_SLAVE 0x00000002 //***************************************************************************** // // I2C Master commands. // //***************************************************************************** #define I2C_MASTER_CMD_SINGLE_SEND \ 0x00000007 #define I2C_MASTER_CMD_SINGLE_RECEIVE \ 0x00000007 #define I2C_MASTER_CMD_BURST_SEND_START \ 0x00000003 #define I2C_MASTER_CMD_BURST_SEND_CONT \ 0x00000001 #define I2C_MASTER_CMD_BURST_SEND_FINISH \ 0x00000005 #define I2C_MASTER_CMD_BURST_SEND_STOP \ 0x00000004 #define I2C_MASTER_CMD_BURST_SEND_ERROR_STOP \ 0x00000004 #define I2C_MASTER_CMD_BURST_RECEIVE_START \ 0x0000000b #define I2C_MASTER_CMD_BURST_RECEIVE_CONT \ 0x00000009 #define I2C_MASTER_CMD_BURST_RECEIVE_FINISH \ 0x00000005 #define I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP \ 0x00000004 #define I2C_MASTER_CMD_QUICK_COMMAND \ 0x00000027 #define I2C_MASTER_CMD_HS_MASTER_CODE_SEND \ 0x00000013 #define I2C_MASTER_CMD_FIFO_SINGLE_SEND \ 0x00000046 #define I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE \ 0x00000046 #define I2C_MASTER_CMD_FIFO_BURST_SEND_START \ 0x00000042 #define I2C_MASTER_CMD_FIFO_BURST_SEND_CONT \ 0x00000040 #define I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH \ 0x00000044 #define I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP \ 0x00000004 #define I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START \ 0x0000004a #define I2C_MASTER_CMD_FIFO_BURST_RECEIVE_CONT \ 0x00000048 #define I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH \ 0x00000044 #define I2C_MASTER_CMD_FIFO_BURST_RECEIVE_ERROR_STOP \ 0x00000004 //***************************************************************************** // // I2C Master glitch filter configuration. // //***************************************************************************** #define I2C_MASTER_GLITCH_FILTER_DISABLED \ 0 #define I2C_MASTER_GLITCH_FILTER_1 \ 0x00010000 #define I2C_MASTER_GLITCH_FILTER_2 \ 0x00020000 #define I2C_MASTER_GLITCH_FILTER_3 \ 0x00030000 #define I2C_MASTER_GLITCH_FILTER_4 \ 0x00040000 #define I2C_MASTER_GLITCH_FILTER_8 \ 0x00050000 #define I2C_MASTER_GLITCH_FILTER_16 \ 0x00060000 #define I2C_MASTER_GLITCH_FILTER_32 \ 0x00070000 //***************************************************************************** // // I2C Master error status. // //***************************************************************************** #define I2C_MASTER_ERR_NONE 0 #define I2C_MASTER_ERR_ADDR_ACK 0x00000004 #define I2C_MASTER_ERR_DATA_ACK 0x00000008 #define I2C_MASTER_ERR_ARB_LOST 0x00000010 #define I2C_MASTER_ERR_CLK_TOUT 0x00000080 //***************************************************************************** // // I2C Slave action requests // //***************************************************************************** #define I2C_SLAVE_ACT_NONE 0 #define I2C_SLAVE_ACT_RREQ 0x00000001 // Master has sent data #define I2C_SLAVE_ACT_TREQ 0x00000002 // Master has requested data #define I2C_SLAVE_ACT_RREQ_FBR 0x00000005 // Master has sent first byte #define I2C_SLAVE_ACT_OWN2SEL 0x00000008 // Master requested secondary slave #define I2C_SLAVE_ACT_QCMD 0x00000010 // Master has sent a Quick Command #define I2C_SLAVE_ACT_QCMD_DATA 0x00000020 // Master Quick Command value //***************************************************************************** // // Miscellaneous I2C driver definitions. // //***************************************************************************** #define I2C_MASTER_MAX_RETRIES 1000 // Number of retries //***************************************************************************** // // I2C Master interrupts. // //***************************************************************************** #define I2C_MASTER_INT_RX_FIFO_FULL \ 0x00000800 // RX FIFO Full Interrupt #define I2C_MASTER_INT_TX_FIFO_EMPTY \ 0x00000400 // TX FIFO Empty Interrupt #define I2C_MASTER_INT_RX_FIFO_REQ \ 0x00000200 // RX FIFO Request Interrupt #define I2C_MASTER_INT_TX_FIFO_REQ \ 0x00000100 // TX FIFO Request Interrupt #define I2C_MASTER_INT_ARB_LOST \ 0x00000080 // Arb Lost Interrupt #define I2C_MASTER_INT_STOP 0x00000040 // Stop Condition Interrupt #define I2C_MASTER_INT_START 0x00000020 // Start Condition Interrupt #define I2C_MASTER_INT_NACK 0x00000010 // Addr/Data NACK Interrupt #define I2C_MASTER_INT_TX_DMA_DONE \ 0x00000008 // TX DMA Complete Interrupt #define I2C_MASTER_INT_RX_DMA_DONE \ 0x00000004 // RX DMA Complete Interrupt #define I2C_MASTER_INT_TIMEOUT 0x00000002 // Clock Timeout Interrupt #define I2C_MASTER_INT_DATA 0x00000001 // Data Interrupt //***************************************************************************** // // I2C Slave interrupts. // //***************************************************************************** #define I2C_SLAVE_INT_RX_FIFO_FULL \ 0x00000100 // RX FIFO Full Interrupt #define I2C_SLAVE_INT_TX_FIFO_EMPTY \ 0x00000080 // TX FIFO Empty Interrupt #define I2C_SLAVE_INT_RX_FIFO_REQ \ 0x00000040 // RX FIFO Request Interrupt #define I2C_SLAVE_INT_TX_FIFO_REQ \ 0x00000020 // TX FIFO Request Interrupt #define I2C_SLAVE_INT_TX_DMA_DONE \ 0x00000010 // TX DMA Complete Interrupt #define I2C_SLAVE_INT_RX_DMA_DONE \ 0x00000008 // RX DMA Complete Interrupt #define I2C_SLAVE_INT_STOP 0x00000004 // Stop Condition Interrupt #define I2C_SLAVE_INT_START 0x00000002 // Start Condition Interrupt #define I2C_SLAVE_INT_DATA 0x00000001 // Data Interrupt //***************************************************************************** // // I2C Slave FIFO configuration macros. // //***************************************************************************** #define I2C_SLAVE_TX_FIFO_ENABLE \ 0x00000002 #define I2C_SLAVE_RX_FIFO_ENABLE \ 0x00000004 //***************************************************************************** // // I2C FIFO configuration macros. // //***************************************************************************** #define I2C_FIFO_CFG_TX_MASTER 0x00000000 #define I2C_FIFO_CFG_TX_SLAVE 0x00008000 #define I2C_FIFO_CFG_RX_MASTER 0x00000000 #define I2C_FIFO_CFG_RX_SLAVE 0x80000000 #define I2C_FIFO_CFG_TX_MASTER_DMA \ 0x00002000 #define I2C_FIFO_CFG_TX_SLAVE_DMA \ 0x0000a000 #define I2C_FIFO_CFG_RX_MASTER_DMA \ 0x20000000 #define I2C_FIFO_CFG_RX_SLAVE_DMA \ 0xa0000000 #define I2C_FIFO_CFG_TX_NO_TRIG 0x00000000 #define I2C_FIFO_CFG_TX_TRIG_1 0x00000001 #define I2C_FIFO_CFG_TX_TRIG_2 0x00000002 #define I2C_FIFO_CFG_TX_TRIG_3 0x00000003 #define I2C_FIFO_CFG_TX_TRIG_4 0x00000004 #define I2C_FIFO_CFG_TX_TRIG_5 0x00000005 #define I2C_FIFO_CFG_TX_TRIG_6 0x00000006 #define I2C_FIFO_CFG_TX_TRIG_7 0x00000007 #define I2C_FIFO_CFG_TX_TRIG_8 0x00000008 #define I2C_FIFO_CFG_RX_NO_TRIG 0x00000000 #define I2C_FIFO_CFG_RX_TRIG_1 0x00010000 #define I2C_FIFO_CFG_RX_TRIG_2 0x00020000 #define I2C_FIFO_CFG_RX_TRIG_3 0x00030000 #define I2C_FIFO_CFG_RX_TRIG_4 0x00040000 #define I2C_FIFO_CFG_RX_TRIG_5 0x00050000 #define I2C_FIFO_CFG_RX_TRIG_6 0x00060000 #define I2C_FIFO_CFG_RX_TRIG_7 0x00070000 #define I2C_FIFO_CFG_RX_TRIG_8 0x00080000 //***************************************************************************** // // I2C FIFO status. // //***************************************************************************** #define I2C_FIFO_RX_BELOW_TRIG_LEVEL \ 0x00040000 #define I2C_FIFO_RX_FULL 0x00020000 #define I2C_FIFO_RX_EMPTY 0x00010000 #define I2C_FIFO_TX_BELOW_TRIG_LEVEL \ 0x00000004 #define I2C_FIFO_TX_FULL 0x00000002 #define I2C_FIFO_TX_EMPTY 0x00000001 //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** extern void I2CIntRegister(uint32_t ui32Base, void(pfnHandler)(void)); extern void I2CIntUnregister(uint32_t ui32Base); extern void I2CTxFIFOConfigSet(uint32_t ui32Base, uint32_t ui32Config); extern void I2CTxFIFOFlush(uint32_t ui32Base); extern void I2CRxFIFOConfigSet(uint32_t ui32Base, uint32_t ui32Config); extern void I2CRxFIFOFlush(uint32_t ui32Base); extern uint32_t I2CFIFOStatus(uint32_t ui32Base); extern void I2CFIFODataPut(uint32_t ui32Base, uint8_t ui8Data); extern uint32_t I2CFIFODataPutNonBlocking(uint32_t ui32Base, uint8_t ui8Data); extern uint32_t I2CFIFODataGet(uint32_t ui32Base); extern uint32_t I2CFIFODataGetNonBlocking(uint32_t ui32Base, uint8_t *pui8Data); extern void I2CMasterBurstLengthSet(uint32_t ui32Base, uint8_t ui8Length); extern uint32_t I2CMasterBurstCountGet(uint32_t ui32Base); extern void I2CMasterGlitchFilterConfigSet(uint32_t ui32Base, uint32_t ui32Config); extern void I2CSlaveFIFOEnable(uint32_t ui32Base, uint32_t ui32Config); extern void I2CSlaveFIFODisable(uint32_t ui32Base); extern bool I2CMasterBusBusy(uint32_t ui32Base); extern bool I2CMasterBusy(uint32_t ui32Base); extern void I2CMasterControl(uint32_t ui32Base, uint32_t ui32Cmd); extern uint32_t I2CMasterDataGet(uint32_t ui32Base); extern void I2CMasterDataPut(uint32_t ui32Base, uint8_t ui8Data); extern void I2CMasterDisable(uint32_t ui32Base); extern void I2CMasterEnable(uint32_t ui32Base); extern uint32_t I2CMasterErr(uint32_t ui32Base); extern void I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32SCLFreq); extern void I2CMasterIntClear(uint32_t ui32Base); extern void I2CMasterIntDisable(uint32_t ui32Base); extern void I2CMasterIntEnable(uint32_t ui32Base); extern bool I2CMasterIntStatus(uint32_t ui32Base, bool bMasked); extern void I2CMasterIntEnableEx(uint32_t ui32Base, uint32_t ui32IntFlags); extern void I2CMasterIntDisableEx(uint32_t ui32Base, uint32_t ui32IntFlags); extern uint32_t I2CMasterIntStatusEx(uint32_t ui32Base, bool bMasked); extern void I2CMasterIntClearEx(uint32_t ui32Base, uint32_t ui32IntFlags); extern void I2CMasterTimeoutSet(uint32_t ui32Base, uint32_t ui32Value); extern void I2CSlaveACKOverride(uint32_t ui32Base, bool bEnable); extern void I2CSlaveACKValueSet(uint32_t ui32Base, bool bACK); extern uint32_t I2CMasterLineStateGet(uint32_t ui32Base); extern void I2CMasterSlaveAddrSet(uint32_t ui32Base, uint8_t ui8SlaveAddr, bool bReceive); extern uint32_t I2CSlaveDataGet(uint32_t ui32Base); extern void I2CSlaveDataPut(uint32_t ui32Base, uint8_t ui8Data); extern void I2CSlaveDisable(uint32_t ui32Base); extern void I2CSlaveEnable(uint32_t ui32Base); extern void I2CSlaveInit(uint32_t ui32Base, uint8_t ui8SlaveAddr); extern void I2CSlaveAddressSet(uint32_t ui32Base, uint8_t ui8AddrNum, uint8_t ui8SlaveAddr); extern void I2CSlaveIntClear(uint32_t ui32Base); extern void I2CSlaveIntDisable(uint32_t ui32Base); extern void I2CSlaveIntEnable(uint32_t ui32Base); extern void I2CSlaveIntClearEx(uint32_t ui32Base, uint32_t ui32IntFlags); extern void I2CSlaveIntDisableEx(uint32_t ui32Base, uint32_t ui32IntFlags); extern void I2CSlaveIntEnableEx(uint32_t ui32Base, uint32_t ui32IntFlags); extern bool I2CSlaveIntStatus(uint32_t ui32Base, bool bMasked); extern uint32_t I2CSlaveIntStatusEx(uint32_t ui32Base, bool bMasked); extern uint32_t I2CSlaveStatus(uint32_t ui32Base); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __DRIVERLIB_I2C_H__ micropython-1.12/ports/cc3200/hal/i2s.c000066400000000000000000000676151357706137100175070ustar00rootroot00000000000000//***************************************************************************** // // i2s.c // // Driver for the I2S interface. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup I2S_api //! @{ // //***************************************************************************** #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_mcasp.h" #include "inc/hw_apps_config.h" #include "interrupt.h" #include "i2s.h" //***************************************************************************** // Macros //***************************************************************************** #define MCASP_GBL_RCLK 0x00000001 #define MCASP_GBL_RHCLK 0x00000002 #define MCASP_GBL_RSER 0x00000004 #define MCASP_GBL_RSM 0x00000008 #define MCASP_GBL_RFSYNC 0x00000010 #define MCASP_GBL_XCLK 0x00000100 #define MCASP_GBL_XHCLK 0x00000200 #define MCASP_GBL_XSER 0x00000400 #define MCASP_GBL_XSM 0x00000800 #define MCASP_GBL_XFSYNC 0x00001000 //***************************************************************************** // //! \internal //! Releases the specifed submodule out of reset. //! //! \param ulBase is the base address of the I2S module. //! \param ulFlag is one of the valid sub module. //! //! This function Releases the specifed submodule out of reset. //! //! \return None. // //***************************************************************************** static void I2SGBLEnable(unsigned long ulBase, unsigned long ulFlag) { unsigned long ulReg; // // Read global control register // ulReg = HWREG(ulBase + MCASP_O_GBLCTL); // // Remove the sub modules reset as specified by ulFlag parameter // ulReg |= ulFlag; // // Write the configuration // HWREG(ulBase + MCASP_O_GBLCTL) = ulReg; // // Wait for write completeion // while(HWREG(ulBase + MCASP_O_GBLCTL) != ulReg) { } } //***************************************************************************** // //! Enables transmit and/or receive. //! //! \param ulBase is the base address of the I2S module. //! \param ulMode is one of the valid modes. //! //! This function enables the I2S module in specified mode. The parameter //! \e ulMode should be one of the following //! //! -\b I2S_MODE_TX_ONLY //! -\b I2S_MODE_TX_RX_SYNC //! //! \return None. // //***************************************************************************** void I2SEnable(unsigned long ulBase, unsigned long ulMode) { // // FSYNC and Bit clock are output only in master mode // if( HWREG(ulBase + MCASP_O_ACLKXCTL) & 0x20) { // // Set FSYNC anc BitClk as output // HWREG(ulBase + MCASP_O_PDIR) |= 0x14000000; } if(ulMode & 0x2) { // // Remove Rx HCLK reset // I2SGBLEnable(ulBase, MCASP_GBL_RHCLK); // // Remove Rx XCLK reset // I2SGBLEnable(ulBase, MCASP_GBL_RCLK); // // Enable Rx SERDES(s) // I2SGBLEnable(ulBase, MCASP_GBL_RSER); // // Enable Rx state machine // I2SGBLEnable(ulBase, MCASP_GBL_RSM); // // Enable FSync generator // I2SGBLEnable(ulBase, MCASP_GBL_RFSYNC); } // // Remove Tx HCLK reset // I2SGBLEnable(ulBase, MCASP_GBL_XHCLK); // // Remove Tx XCLK reset // I2SGBLEnable(ulBase, MCASP_GBL_XCLK); if(ulMode & 0x1) { // // Enable Tx SERDES(s) // I2SGBLEnable(ulBase, MCASP_GBL_XSER); // // Enable Tx state machine // I2SGBLEnable(ulBase, MCASP_GBL_XSM); } // // Enable FSync generator // I2SGBLEnable(ulBase, MCASP_GBL_XFSYNC); } //***************************************************************************** // //! Disables transmit and/or receive. //! //! \param ulBase is the base address of the I2S module. //! //! This function disables transmit and/or receive from I2S module. //! //! \return None. // //***************************************************************************** void I2SDisable(unsigned long ulBase) { // // Reset all sub modules // HWREG(ulBase + MCASP_O_GBLCTL) = 0; // // Wait for write to complete // while( HWREG(ulBase + MCASP_O_GBLCTL) != 0) { } } //***************************************************************************** // //! Waits to send data over the specified data line //! //! \param ulBase is the base address of the I2S module. //! \param ulDataLine is one of the valid data lines. //! \param ulData is the data to be transmitted. //! //! This function sends the \e ucData to the transmit register for the //! specified data line. If there is no space available, this //! function waits until there is space available before returning. //! //! \return None. // //***************************************************************************** void I2SDataPut(unsigned long ulBase, unsigned long ulDataLine, unsigned long ulData) { // // Compute register the offeset // ulDataLine = (ulDataLine-1) << 2; // // Wait for free space in fifo // while(!( HWREG(ulBase + MCASP_O_TXSTAT) & MCASP_TXSTAT_XDATA)) { } // // Write Data into the FIFO // HWREG(ulBase + MCASP_O_TXBUF0 + ulDataLine) = ulData; } //***************************************************************************** // //! Sends data over the specified data line //! //! \param ulBase is the base address of the I2S module. //! \param ulDataLine is one of the valid data lines. //! \param ulData is the data to be transmitted. //! //! This function writes the \e ucData to the transmit register for //! the specified data line. This function does not block, so if there is no //! space available, then \b -1 is returned, and the application must retry the //! function later. //! //! \return Returns 0 on success, -1 otherwise. // //***************************************************************************** long I2SDataPutNonBlocking(unsigned long ulBase, unsigned long ulDataLine, unsigned long ulData) { // // Compute register the offeset // ulDataLine = (ulDataLine-1) << 2; // // Send Data if fifo has free space // if( HWREG(ulBase + MCASP_O_TXSTAT) & MCASP_TXSTAT_XDATA) { // // Write data into the FIFO // HWREG(ulBase + MCASP_O_TXBUF0 + ulDataLine) = ulData; return 0; } // // FIFO is full // return(-1); } //***************************************************************************** // //! Waits for data from the specified data line. //! //! \param ulBase is the base address of the I2S module. //! \param ulDataLine is one of the valid data lines. //! \param pulData is pointer to receive data variable. //! //! This function gets data from the receive register for the specified //! data line. If there are no data available, this function waits until a //! receive before returning. //! //! \return None. // //***************************************************************************** void I2SDataGet(unsigned long ulBase, unsigned long ulDataLine, unsigned long *pulData) { // // Compute register the offeset // ulDataLine = (ulDataLine-1) << 2; // // Wait for atleat on word in FIFO // while(!(HWREG(ulBase + MCASP_O_RXSTAT) & MCASP_RXSTAT_RDATA)) { } // // Read the Data // *pulData = HWREG(ulBase + MCASP_O_RXBUF0 + ulDataLine); } //***************************************************************************** // //! Receives data from the specified data line. //! //! \param ulBase is the base address of the I2S module. //! \param ulDataLine is one of the valid data lines. //! \param pulData is pointer to receive data variable. //! //! This function gets data from the receive register for the specified //! data line. //! //! //! \return Returns 0 on success, -1 otherwise. // //***************************************************************************** long I2SDataGetNonBlocking(unsigned long ulBase, unsigned long ulDataLine, unsigned long *pulData) { // // Compute register the offeset // ulDataLine = (ulDataLine-1) << 2; // // Check if data is available in FIFO // if(HWREG(ulBase + MCASP_O_RXSTAT) & MCASP_RXSTAT_RDATA) { // // Read the Data // *pulData = HWREG(ulBase + MCASP_O_RXBUF0 + ulDataLine); return 0; } // // FIFO is empty // return -1; } //***************************************************************************** // //! Sets the configuration of the I2S module. //! //! \param ulBase is the base address of the I2S module. //! \param ulI2SClk is the rate of the clock supplied to the I2S module. //! \param ulBitClk is the desired bit rate. //! \param ulConfig is the data format. //! //! This function configures the I2S for operation in the specified data //! format. The bit rate is provided in the \e ulBitClk parameter and the data //! format in the \e ulConfig parameter. //! //! The \e ulConfig parameter is the logical OR of three values: the slot size //! the data read/write port select, Master or Slave mode //! //! Follwoing selects the Master-Slave mode //! -\b I2S_MODE_MASTER //! -\b I2S_MODE_SLAVE //! //! Following selects the slot size: //! -\b I2S_SLOT_SIZE_24 //! -\b I2S_SLOT_SIZE_16 //! //! Following selects the data read/write port: //! -\b I2S_PORT_DMA //! -\b I2S_PORT_CPU //! //! \return None. // //***************************************************************************** void I2SConfigSetExpClk(unsigned long ulBase, unsigned long ulI2SClk, unsigned long ulBitClk, unsigned long ulConfig) { unsigned long ulHClkDiv; unsigned long ulClkDiv; unsigned long ulSlotSize; unsigned long ulBitMask; // // Calculate clock dividers // ulHClkDiv = ((ulI2SClk/ulBitClk)-1); ulClkDiv = 0; // // Check if HCLK divider is overflowing // if(ulHClkDiv > 0xFFF) { ulHClkDiv = 0xFFF; // // Calculate clock divider // ulClkDiv = ((ulI2SClk/(ulBitClk * (ulHClkDiv + 1))) & 0x1F); } // // // ulClkDiv = ((ulConfig & I2S_MODE_SLAVE )?0x80:0xA0|ulClkDiv); HWREG(ulBase + MCASP_O_ACLKXCTL) = ulClkDiv; HWREG(ulBase + MCASP_O_AHCLKXCTL) = (0x8000|ulHClkDiv); // // Write the Tx format register // HWREG(ulBase + MCASP_O_TXFMT) = (0x18000 | (ulConfig & 0x7FFF)); // // Write the Rx format register // HWREG(ulBase + MCASP_O_RXFMT) = (0x18000 | ((ulConfig >> 16) &0x7FFF)); // // Check if in master mode // if( ulConfig & I2S_MODE_SLAVE) { // // Configure Tx FSync generator in I2S mode // HWREG(ulBase + MCASP_O_TXFMCTL) = 0x111; // // Configure Rx FSync generator in I2S mode // HWREG(ulBase + MCASP_O_RXFMCTL) = 0x111; } else { // // Configure Tx FSync generator in I2S mode // HWREG(ulBase + MCASP_O_TXFMCTL) = 0x113; // // Configure Rx FSync generator in I2S mode // HWREG(ulBase + MCASP_O_RXFMCTL) = 0x113; } // // Compute Slot Size // ulSlotSize = ((((ulConfig & 0xFF) >> 4) + 1) * 2); // // Creat the bit mask // ulBitMask = (0xFFFFFFFF >> (32 - ulSlotSize)); // // Set Tx bit valid mask // HWREG(ulBase + MCASP_O_TXMASK) = ulBitMask; // // Set Rx bit valid mask // HWREG(ulBase + MCASP_O_RXMASK) = ulBitMask; // // Set Tx slot valid mask // HWREG(ulBase + MCASP_O_TXTDM) = 0x3; // // Set Rx slot valid mask // HWREG(ulBase + MCASP_O_RXTDM) = 0x3; } //***************************************************************************** // //! Configure and enable transmit FIFO. //! //! \param ulBase is the base address of the I2S module. //! \param ulTxLevel is the transmit FIFO DMA request level. //! \param ulWordsPerTransfer is the nuber of words transferred from the FIFO. //! //! This function configures and enable I2S transmit FIFO. //! //! The parameter \e ulTxLevel sets the level at which transmit DMA requests //! are generated. This should be non-zero integer multiple of number of //! serializers enabled as transmitters //! //! The parameter \e ulWordsPerTransfer sets the number of words that are //! transferred from the transmit FIFO to the data line(s). This value must //! equal the number of serializers used as transmitters. //! //! \return None. // //***************************************************************************** void I2STxFIFOEnable(unsigned long ulBase, unsigned long ulTxLevel, unsigned long ulWordsPerTransfer) { // // Set transmit FIFO configuration and // enable it // HWREG(ulBase + MCASP_0_WFIFOCTL) = ((1 <<16) | ((ulTxLevel & 0xFF) << 8) | (ulWordsPerTransfer & 0x1F)); } //***************************************************************************** // //! Disables transmit FIFO. //! //! \param ulBase is the base address of the I2S module. //! //! This function disables the I2S transmit FIFO. //! //! \return None. // //***************************************************************************** void I2STxFIFODisable(unsigned long ulBase) { // // Disable transmit FIFO. // HWREG(ulBase + MCASP_0_WFIFOCTL) = 0; } //***************************************************************************** // //! Configure and enable receive FIFO. //! //! \param ulBase is the base address of the I2S module. //! \param ulRxLevel is the receive FIFO DMA request level. //! \param ulWordsPerTransfer is the nuber of words transferred from the FIFO. //! //! This function configures and enable I2S receive FIFO. //! //! The parameter \e ulRxLevel sets the level at which receive DMA requests //! are generated. This should be non-zero integer multiple of number of //! serializers enabled as receivers. //! //! The parameter \e ulWordsPerTransfer sets the number of words that are //! transferred to the receive FIFO from the data line(s). This value must //! equal the number of serializers used as receivers. //! //! \return None. // //***************************************************************************** void I2SRxFIFOEnable(unsigned long ulBase, unsigned long ulRxLevel, unsigned long ulWordsPerTransfer) { // // Set FIFO configuration // HWREG(ulBase + MCASP_0_RFIFOCTL) = ( (1 <<16) | ((ulRxLevel & 0xFF) << 8) | (ulWordsPerTransfer & 0x1F)); } //***************************************************************************** // //! Disables receive FIFO. //! //! \param ulBase is the base address of the I2S module. //! //! This function disables the I2S receive FIFO. //! //! \return None. // //***************************************************************************** void I2SRxFIFODisable(unsigned long ulBase) { // // Disable receive FIFO. // HWREG(ulBase + MCASP_0_RFIFOCTL) = 0; } //***************************************************************************** // //! Get the transmit FIFO status. //! //! \param ulBase is the base address of the I2S module. //! //! This function gets the number of 32-bit words currently in the transmit //! FIFO. //! //! \return Returns transmit FIFO status. // //***************************************************************************** unsigned long I2STxFIFOStatusGet(unsigned long ulBase) { // // Return transmit FIFO level // return HWREG(ulBase + MCASP_0_WFIFOSTS); } //***************************************************************************** // //! Get the receive FIFO status. //! //! \param ulBase is the base address of the I2S module. //! //! This function gets the number of 32-bit words currently in the receive //! FIFO. //! //! \return Returns receive FIFO status. // //***************************************************************************** unsigned long I2SRxFIFOStatusGet(unsigned long ulBase) { // // Return receive FIFO level // return HWREG(ulBase + MCASP_0_RFIFOSTS); } //***************************************************************************** // //! Configure the serializer in specified mode. //! //! \param ulBase is the base address of the I2S module. //! \param ulDataLine is the data line (serilizer) to be configured. //! \param ulSerMode is the required serializer mode. //! \param ulInActState sets the inactive state of the data line. //! //! This function configure and enable the serializer associated with the given //! data line in specified mode. //! //! The paramenter \e ulDataLine selects to data line to be configured and //! can be one of the following: //! -\b I2S_DATA_LINE_0 //! -\b I2S_DATA_LINE_1 //! //! The parameter \e ulSerMode can be one of the following: //! -\b I2S_SER_MODE_TX //! -\b I2S_SER_MODE_RX //! -\b I2S_SER_MODE_DISABLE //! //! The parameter \e ulInActState can be one of the following //! -\b I2S_INACT_TRI_STATE //! -\b I2S_INACT_LOW_LEVEL //! -\b I2S_INACT_LOW_HIGH //! //! \return Returns receive FIFO status. // //***************************************************************************** void I2SSerializerConfig(unsigned long ulBase, unsigned long ulDataLine, unsigned long ulSerMode, unsigned long ulInActState) { if( ulSerMode == I2S_SER_MODE_TX) { // // Set the data line in output mode // HWREG(ulBase + MCASP_O_PDIR) |= ulDataLine; } else { // // Set the data line in input mode // HWREG(ulBase + MCASP_O_PDIR) &= ~ulDataLine; } // // Set the serializer configuration. // HWREG(ulBase + MCASP_O_XRSRCTL0 + ((ulDataLine-1) << 2)) = (ulSerMode | ulInActState); } //***************************************************************************** // //! Enables individual I2S interrupt sources. //! //! \param ulBase is the base address of the I2S module. //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated I2S interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter is the logical OR of any of the following: //! //! -\b I2S_INT_XUNDRN //! -\b I2S_INT_XSYNCERR //! -\b I2S_INT_XLAST //! -\b I2S_INT_XDATA //! -\b I2S_INT_XSTAFRM //! -\b I2S_INT_XDMA //! -\b I2S_INT_ROVRN //! -\b I2S_INT_RSYNCERR //! -\b I2S_INT_RLAST //! -\b I2S_INT_RDATA //! -\b I2S_INT_RSTAFRM //! -\b I2S_INT_RDMA //! //! \return None. // //***************************************************************************** void I2SIntEnable(unsigned long ulBase, unsigned long ulIntFlags) { // // Enable DMA done interrupts // HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR ) |= ((ulIntFlags &0xC0000000) >> 20); // // Enable specific Tx Interrupts // HWREG(ulBase + MCASP_O_EVTCTLX) |= (ulIntFlags & 0xFF); // // Enable specific Rx Interrupts // HWREG(ulBase + MCASP_O_EVTCTLR) |= ((ulIntFlags >> 16) & 0xFF); } //***************************************************************************** // //! Disables individual I2S interrupt sources. //! //! \param ulBase is the base address of the I2S module. //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled. //! //! This function disables the indicated I2S interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to I2SIntEnable(). //! //! \return None. // //***************************************************************************** void I2SIntDisable(unsigned long ulBase, unsigned long ulIntFlags) { // // Disable DMA done interrupts // HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) |= ((ulIntFlags &0xC0000000) >> 20); // // Disable specific Tx Interrupts // HWREG(ulBase + MCASP_O_EVTCTLX) &= ~(ulIntFlags & 0xFF); // // Disable specific Rx Interrupts // HWREG(ulBase + MCASP_O_EVTCTLR) &= ~((ulIntFlags >> 16) & 0xFF); } //***************************************************************************** // //! Gets the current interrupt status. //! //! \param ulBase is the base address of the I2S module. //! //! This function returns the raw interrupt status for I2S enumerated //! as a bit field of values: //! -\b I2S_STS_XERR //! -\b I2S_STS_XDMAERR //! -\b I2S_STS_XSTAFRM //! -\b I2S_STS_XDATA //! -\b I2S_STS_XLAST //! -\b I2S_STS_XSYNCERR //! -\b I2S_STS_XUNDRN //! -\b I2S_STS_XDMA //! -\b I2S_STS_RERR //! -\b I2S_STS_RDMAERR //! -\b I2S_STS_RSTAFRM //! -\b I2S_STS_RDATA //! -\b I2S_STS_RLAST //! -\b I2S_STS_RSYNCERR //! -\b I2S_STS_ROVERN //! -\b I2S_STS_RDMA //! //! \return Returns the current interrupt status, enumerated as a bit field of //! values described above. // //***************************************************************************** unsigned long I2SIntStatus(unsigned long ulBase) { unsigned long ulStatus; // // Get DMA interrupt status // ulStatus = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_RAW) << 20; ulStatus &= 0xC0000000; // // Read Tx Interrupt status // ulStatus |= HWREG(ulBase + MCASP_O_TXSTAT); // // Read Rx Interrupt status // ulStatus |= HWREG(ulBase + MCASP_O_RXSTAT) << 16; // // Return the status // return ulStatus; } //***************************************************************************** // //! Clears I2S interrupt sources. //! //! \param ulBase is the base address of the I2S module. //! \param ulStatFlags is a bit mask of the interrupt sources to be cleared. //! //! The specified I2S interrupt sources are cleared, so that they no longer //! assert. This function must be called in the interrupt handler to keep the //! interrupt from being recognized again immediately upon exit. //! //! The \e ulIntFlags parameter is the logical OR of any of the value //! describe in I2SIntStatus(). //! //! \return None. // //***************************************************************************** void I2SIntClear(unsigned long ulBase, unsigned long ulStatFlags) { // // Clear DMA done interrupts // HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) |= ((ulStatFlags &0xC0000000) >> 20); // // Clear Tx Interrupt // HWREG(ulBase + MCASP_O_TXSTAT) = ulStatFlags & 0x1FF ; // // Clear Rx Interrupt // HWREG(ulBase + MCASP_O_RXSTAT) = (ulStatFlags >> 16) & 0x1FF; } //***************************************************************************** // //! Registers an interrupt handler for a I2S interrupt. //! //! \param ulBase is the base address of the I2S module. //! \param pfnHandler is a pointer to the function to be called when the //! I2S interrupt occurs. //! //! This function does the actual registering of the interrupt handler. This //! function enables the global interrupt in the interrupt controller; specific //! I2S interrupts must be enabled via I2SIntEnable(). It is the interrupt //! handler's responsibility to clear the interrupt source. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void I2SIntRegister(unsigned long ulBase, void (*pfnHandler)(void)) { // // Register the interrupt handler // IntRegister(INT_I2S,pfnHandler); // // Enable the interrupt // IntEnable(INT_I2S); } //***************************************************************************** // //! Unregisters an interrupt handler for a I2S interrupt. //! //! \param ulBase is the base address of the I2S module. //! //! This function does the actual unregistering of the interrupt handler. It //! clears the handler to be called when a I2S interrupt occurs. This //! function also masks off the interrupt in the interrupt controller so that //! the interrupt handler no longer is called. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void I2SIntUnregister(unsigned long ulBase) { // // Disable interrupt // IntDisable(INT_I2S); // // Unregister the handler // IntUnregister(INT_I2S); } //***************************************************************************** // //! Set the active slots for Trasmitter //! //! \param ulBase is the base address of the I2S module. //! \param ulActSlot is the bit-mask of activ slots //! //! This function sets the active slots for the transmitter. By default both //! the slots are active. The parameter \e ulActSlot is logical OR follwoing //! values: //! -\b I2S_ACT_SLOT_EVEN //! -\b I2S_ACT_SLOT_ODD //! //! \return None. // //***************************************************************************** void I2STxActiveSlotSet(unsigned long ulBase, unsigned long ulActSlot) { HWREG(ulBase + MCASP_O_TXTDM) = ulActSlot; } //***************************************************************************** // //! Set the active slots for Receiver //! //! \param ulBase is the base address of the I2S module. //! \param ulActSlot is the bit-mask of activ slots //! //! This function sets the active slots for the receiver. By default both //! the slots are active. The parameter \e ulActSlot is logical OR follwoing //! values: //! -\b I2S_ACT_SLOT_EVEN //! -\b I2S_ACT_SLOT_ODD //! //! \return None. // //***************************************************************************** void I2SRxActiveSlotSet(unsigned long ulBase, unsigned long ulActSlot) { HWREG(ulBase + MCASP_O_RXTDM) = ulActSlot; } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/i2s.h000066400000000000000000000215101357706137100174740ustar00rootroot00000000000000//***************************************************************************** // // i2s.h // // Defines and Macros for the I2S. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __I2S_H__ #define __I2S_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // I2S DMA ports. // //***************************************************************************** #define I2S_TX_DMA_PORT 0x4401E200 #define I2S_RX_DMA_PORT 0x4401E280 //***************************************************************************** // // Values that can be passed to I2SConfigSetExpClk() as the ulConfig parameter. // //***************************************************************************** #define I2S_SLOT_SIZE_8 0x00300032 #define I2S_SLOT_SIZE_16 0x00700074 #define I2S_SLOT_SIZE_24 0x00B000B6 #define I2S_PORT_CPU 0x00080008 #define I2S_PORT_DMA 0x00000000 #define I2S_MODE_MASTER 0x00000000 #define I2S_MODE_SLAVE 0x00008000 //***************************************************************************** // // Values that can be passed as ulDataLine parameter. // //***************************************************************************** #define I2S_DATA_LINE_0 0x00000001 #define I2S_DATA_LINE_1 0x00000002 //***************************************************************************** // // Values that can be passed to I2SSerializerConfig() as the ulSerMode // parameter. // //***************************************************************************** #define I2S_SER_MODE_TX 0x00000001 #define I2S_SER_MODE_RX 0x00000002 #define I2S_SER_MODE_DISABLE 0x00000000 //***************************************************************************** // // Values that can be passed to I2SSerializerConfig() as the ulInActState // parameter. // //***************************************************************************** #define I2S_INACT_TRI_STATE 0x00000000 #define I2S_INACT_LOW_LEVEL 0x00000008 #define I2S_INACT_HIGH_LEVEL 0x0000000C //***************************************************************************** // // Values that can be passed to I2SIntEnable() and I2SIntDisable() as the // ulIntFlags parameter. // //***************************************************************************** #define I2S_INT_XUNDRN 0x00000001 #define I2S_INT_XSYNCERR 0x00000002 #define I2S_INT_XLAST 0x00000010 #define I2S_INT_XDATA 0x00000020 #define I2S_INT_XSTAFRM 0x00000080 #define I2S_INT_XDMA 0x80000000 #define I2S_INT_ROVRN 0x00010000 #define I2S_INT_RSYNCERR 0x00020000 #define I2S_INT_RLAST 0x00100000 #define I2S_INT_RDATA 0x00200000 #define I2S_INT_RSTAFRM 0x00800000 #define I2S_INT_RDMA 0x40000000 //***************************************************************************** // // Values that can be passed to I2SRxActiveSlotSet() and I2STxActiveSlotSet // //***************************************************************************** #define I2S_ACT_SLOT_EVEN 0x00000001 #define I2S_ACT_SLOT_ODD 0x00000002 //***************************************************************************** // // Values that can be passed to I2SIntClear() as the // ulIntFlags parameter and returned from I2SIntStatus(). // //***************************************************************************** #define I2S_STS_XERR 0x00000100 #define I2S_STS_XDMAERR 0x00000080 #define I2S_STS_XSTAFRM 0x00000040 #define I2S_STS_XDATA 0x00000020 #define I2S_STS_XLAST 0x00000010 #define I2S_STS_XSYNCERR 0x00000002 #define I2S_STS_XUNDRN 0x00000001 #define I2S_STS_XDMA 0x80000000 #define I2S_STS_RERR 0x01000000 #define I2S_STS_RDMAERR 0x00800000 #define I2S_STS_RSTAFRM 0x00400000 #define I2S_STS_RDATA 0x00200000 #define I2S_STS_RLAST 0x00100000 #define I2S_STS_RSYNCERR 0x00020000 #define I2S_STS_ROVERN 0x00010000 #define I2S_STS_RDMA 0x40000000 //***************************************************************************** // // Values that can be passed to I2SEnable() as the ulMode parameter. // //***************************************************************************** #define I2S_MODE_TX_ONLY 0x00000001 #define I2S_MODE_TX_RX_SYNC 0x00000003 //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void I2SEnable(unsigned long ulBase, unsigned long ulMode); extern void I2SDisable(unsigned long ulBase); extern void I2SDataPut(unsigned long ulBase, unsigned long ulDataLine, unsigned long ulData); extern long I2SDataPutNonBlocking(unsigned long ulBase, unsigned long ulDataLine, unsigned long ulData); extern void I2SDataGet(unsigned long ulBase, unsigned long ulDataLine, unsigned long *pulData); extern long I2SDataGetNonBlocking(unsigned long ulBase, unsigned long ulDataLine, unsigned long *pulData); extern void I2SConfigSetExpClk(unsigned long ulBase, unsigned long ulI2SClk, unsigned long ulBitClk, unsigned long ulConfig); extern void I2STxFIFOEnable(unsigned long ulBase, unsigned long ulTxLevel, unsigned long ulWordsPerTransfer); extern void I2STxFIFODisable(unsigned long ulBase); extern void I2SRxFIFOEnable(unsigned long ulBase, unsigned long ulRxLevel, unsigned long ulWordsPerTransfer); extern void I2SRxFIFODisable(unsigned long ulBase); extern unsigned long I2STxFIFOStatusGet(unsigned long ulBase); extern unsigned long I2SRxFIFOStatusGet(unsigned long ulBase); extern void I2SSerializerConfig(unsigned long ulBase, unsigned long ulDataLine, unsigned long ulSerMode, unsigned long ulInActState); extern void I2SIntEnable(unsigned long ulBase, unsigned long ulIntFlags); extern void I2SIntDisable(unsigned long ulBase, unsigned long ulIntFlags); extern unsigned long I2SIntStatus(unsigned long ulBase); extern void I2SIntClear(unsigned long ulBase, unsigned long ulIntFlags); extern void I2SIntRegister(unsigned long ulBase, void (*pfnHandler)(void)); extern void I2SIntUnregister(unsigned long ulBase); extern void I2STxActiveSlotSet(unsigned long ulBase, unsigned long ulActSlot); extern void I2SRxActiveSlotSet(unsigned long ulBase, unsigned long ulActSlot); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif //__I2S_H__ micropython-1.12/ports/cc3200/hal/inc/000077500000000000000000000000001357706137100174005ustar00rootroot00000000000000micropython-1.12/ports/cc3200/hal/inc/asmdefs.h000066400000000000000000000153071357706137100212010ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // // asmdefs.h - Macros to allow assembly code be portable among toolchains. // //***************************************************************************** #ifndef __ASMDEFS_H__ #define __ASMDEFS_H__ //***************************************************************************** // // The defines required for code_red. // //***************************************************************************** #ifdef codered // // The assembly code preamble required to put the assembler into the correct // configuration. // .syntax unified .thumb // // Section headers. // #define __LIBRARY__ @ #define __TEXT__ .text #define __DATA__ .data #define __BSS__ .bss #define __TEXT_NOROOT__ .text // // Assembler nmenonics. // #define __ALIGN__ .balign 4 #define __END__ .end #define __EXPORT__ .globl #define __IMPORT__ .extern #define __LABEL__ : #define __STR__ .ascii #define __THUMB_LABEL__ .thumb_func #define __WORD__ .word #define __INLINE_DATA__ #endif // codered //***************************************************************************** // // The defines required for EW-ARM. // //***************************************************************************** #ifdef ewarm // // Section headers. // #define __LIBRARY__ module #define __TEXT__ rseg CODE:CODE(2) #define __DATA__ rseg DATA:DATA(2) #define __BSS__ rseg DATA:DATA(2) #define __TEXT_NOROOT__ rseg CODE:CODE:NOROOT(2) // // Assembler nmenonics. // #define __ALIGN__ alignrom 2 #define __END__ end #define __EXPORT__ export #define __IMPORT__ import #define __LABEL__ #define __STR__ dcb #define __THUMB_LABEL__ thumb #define __WORD__ dcd #define __INLINE_DATA__ data #endif // ewarm //***************************************************************************** // // The defines required for GCC. // //***************************************************************************** #if defined(gcc) // // The assembly code preamble required to put the assembler into the correct // configuration. // .syntax unified .thumb // // Section headers. // #define __LIBRARY__ @ #define __TEXT__ .text #define __DATA__ .data #define __BSS__ .bss #define __TEXT_NOROOT__ .text // // Assembler nmenonics. // #define __ALIGN__ .balign 4 #define __END__ .end #define __EXPORT__ .globl #define __IMPORT__ .extern #define __LABEL__ : #define __STR__ .ascii #define __THUMB_LABEL__ .thumb_func #define __WORD__ .word #define __INLINE_DATA__ #endif // gcc //***************************************************************************** // // The defines required for RV-MDK. // //***************************************************************************** #ifdef rvmdk // // The assembly code preamble required to put the assembler into the correct // configuration. // thumb require8 preserve8 // // Section headers. // #define __LIBRARY__ ; #define __TEXT__ area ||.text||, code, readonly, align=2 #define __DATA__ area ||.data||, data, align=2 #define __BSS__ area ||.bss||, noinit, align=2 #define __TEXT_NOROOT__ area ||.text||, code, readonly, align=2 // // Assembler nmenonics. // #define __ALIGN__ align 4 #define __END__ end #define __EXPORT__ export #define __IMPORT__ import #define __LABEL__ #define __STR__ dcb #define __THUMB_LABEL__ #define __WORD__ dcd #define __INLINE_DATA__ #endif // rvmdk //***************************************************************************** // // The defines required for Sourcery G++. // //***************************************************************************** #if defined(sourcerygxx) // // The assembly code preamble required to put the assembler into the correct // configuration. // .syntax unified .thumb // // Section headers. // #define __LIBRARY__ @ #define __TEXT__ .text #define __DATA__ .data #define __BSS__ .bss #define __TEXT_NOROOT__ .text // // Assembler nmenonics. // #define __ALIGN__ .balign 4 #define __END__ .end #define __EXPORT__ .globl #define __IMPORT__ .extern #define __LABEL__ : #define __STR__ .ascii #define __THUMB_LABEL__ .thumb_func #define __WORD__ .word #define __INLINE_DATA__ #endif // sourcerygxx #endif // __ASMDEF_H__ micropython-1.12/ports/cc3200/hal/inc/hw_adc.h000066400000000000000000001406201357706137100210010ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_ADC_H__ #define __HW_ADC_H__ //***************************************************************************** // // The following are defines for the ADC register offsets. // //***************************************************************************** #define ADC_O_ADC_CTRL 0x00000000 // ADC control register. #define ADC_O_adc_ch0_gain 0x00000004 // Channel 0 gain setting #define ADC_O_adc_ch1_gain 0x00000008 // Channel 1 gain setting #define ADC_O_adc_ch2_gain 0x0000000C // Channel 2 gain setting #define ADC_O_adc_ch3_gain 0x00000010 // Channel 3 gain setting #define ADC_O_adc_ch4_gain 0x00000014 // Channel 4 gain setting #define ADC_O_adc_ch5_gain 0x00000018 // Channel 5 gain setting #define ADC_O_adc_ch6_gain 0x0000001C // Channel 6 gain setting #define ADC_O_adc_ch7_gain 0x00000020 // Channel 7 gain setting #define ADC_O_adc_ch0_irq_en 0x00000024 // Channel 0 interrupt enable // register #define ADC_O_adc_ch1_irq_en 0x00000028 // Channel 1 interrupt enable // register #define ADC_O_adc_ch2_irq_en 0x0000002C // Channel 2 interrupt enable // register #define ADC_O_adc_ch3_irq_en 0x00000030 // Channel 3 interrupt enable // register #define ADC_O_adc_ch4_irq_en 0x00000034 // Channel 4 interrupt enable // register #define ADC_O_adc_ch5_irq_en 0x00000038 // Channel 5 interrupt enable // register #define ADC_O_adc_ch6_irq_en 0x0000003C // Channel 6 interrupt enable // register #define ADC_O_adc_ch7_irq_en 0x00000040 // Channel 7 interrupt enable // register #define ADC_O_adc_ch0_irq_status \ 0x00000044 // Channel 0 interrupt status // register #define ADC_O_adc_ch1_irq_status \ 0x00000048 // Channel 1 interrupt status // register #define ADC_O_adc_ch2_irq_status \ 0x0000004C #define ADC_O_adc_ch3_irq_status \ 0x00000050 // Channel 3 interrupt status // register #define ADC_O_adc_ch4_irq_status \ 0x00000054 // Channel 4 interrupt status // register #define ADC_O_adc_ch5_irq_status \ 0x00000058 #define ADC_O_adc_ch6_irq_status \ 0x0000005C // Channel 6 interrupt status // register #define ADC_O_adc_ch7_irq_status \ 0x00000060 // Channel 7 interrupt status // register #define ADC_O_adc_dma_mode_en 0x00000064 // DMA mode enable register #define ADC_O_adc_timer_configuration \ 0x00000068 // ADC timer configuration register #define ADC_O_adc_timer_current_count \ 0x00000070 // ADC timer current count register #define ADC_O_channel0FIFODATA 0x00000074 // CH0 FIFO DATA register #define ADC_O_channel1FIFODATA 0x00000078 // CH1 FIFO DATA register #define ADC_O_channel2FIFODATA 0x0000007C // CH2 FIFO DATA register #define ADC_O_channel3FIFODATA 0x00000080 // CH3 FIFO DATA register #define ADC_O_channel4FIFODATA 0x00000084 // CH4 FIFO DATA register #define ADC_O_channel5FIFODATA 0x00000088 // CH5 FIFO DATA register #define ADC_O_channel6FIFODATA 0x0000008C // CH6 FIFO DATA register #define ADC_O_channel7FIFODATA 0x00000090 // CH7 FIFO DATA register #define ADC_O_adc_ch0_fifo_lvl 0x00000094 // channel 0 FIFO Level register #define ADC_O_adc_ch1_fifo_lvl 0x00000098 // Channel 1 interrupt status // register #define ADC_O_adc_ch2_fifo_lvl 0x0000009C #define ADC_O_adc_ch3_fifo_lvl 0x000000A0 // Channel 3 interrupt status // register #define ADC_O_adc_ch4_fifo_lvl 0x000000A4 // Channel 4 interrupt status // register #define ADC_O_adc_ch5_fifo_lvl 0x000000A8 #define ADC_O_adc_ch6_fifo_lvl 0x000000AC // Channel 6 interrupt status // register #define ADC_O_adc_ch7_fifo_lvl 0x000000B0 // Channel 7 interrupt status // register #define ADC_O_ADC_CH_ENABLE 0x000000B8 //****************************************************************************** // // The following are defines for the bit fields in the ADC_O_ADC_CTRL register. // //****************************************************************************** #define ADC_ADC_CTRL_adc_cap_scale \ 0x00000020 // ADC CAP SCALE. #define ADC_ADC_CTRL_adc_buf_bypass \ 0x00000010 // ADC ANA CIO buffer bypass. // Signal is modelled in ANA TOP. // When '1': ADC buffer is bypassed. #define ADC_ADC_CTRL_adc_buf_en 0x00000008 // ADC ANA buffer enable. When 1: // ADC buffer is enabled. #define ADC_ADC_CTRL_adc_core_en \ 0x00000004 // ANA ADC core en. This signal act // as glbal enable to ADC CIO. When // 1: ADC core is enabled. #define ADC_ADC_CTRL_adc_soft_reset \ 0x00000002 // ADC soft reset. When '1' : reset // ADC internal logic. #define ADC_ADC_CTRL_adc_en 0x00000001 // ADC global enable. When set ADC // module is enabled //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch0_gain register. // //****************************************************************************** #define ADC_adc_ch0_gain_adc_channel0_gain_M \ 0x00000003 // gain setting for ADC channel 0. // when "00": 1x when "01: 2x when // "10":3x when "11" 4x #define ADC_adc_ch0_gain_adc_channel0_gain_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch1_gain register. // //****************************************************************************** #define ADC_adc_ch1_gain_adc_channel1_gain_M \ 0x00000003 // gain setting for ADC channel 1. // when "00": 1x when "01: 2x when // "10":3x when "11" 4x #define ADC_adc_ch1_gain_adc_channel1_gain_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch2_gain register. // //****************************************************************************** #define ADC_adc_ch2_gain_adc_channel2_gain_M \ 0x00000003 // gain setting for ADC channel 2. // when "00": 1x when "01: 2x when // "10":3x when "11" 4x #define ADC_adc_ch2_gain_adc_channel2_gain_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch3_gain register. // //****************************************************************************** #define ADC_adc_ch3_gain_adc_channel3_gain_M \ 0x00000003 // gain setting for ADC channel 3. // when "00": 1x when "01: 2x when // "10":3x when "11" 4x #define ADC_adc_ch3_gain_adc_channel3_gain_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch4_gain register. // //****************************************************************************** #define ADC_adc_ch4_gain_adc_channel4_gain_M \ 0x00000003 // gain setting for ADC channel 4 // when "00": 1x when "01: 2x when // "10":3x when "11" 4x #define ADC_adc_ch4_gain_adc_channel4_gain_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch5_gain register. // //****************************************************************************** #define ADC_adc_ch5_gain_adc_channel5_gain_M \ 0x00000003 // gain setting for ADC channel 5. // when "00": 1x when "01: 2x when // "10":3x when "11" 4x #define ADC_adc_ch5_gain_adc_channel5_gain_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch6_gain register. // //****************************************************************************** #define ADC_adc_ch6_gain_adc_channel6_gain_M \ 0x00000003 // gain setting for ADC channel 6 // when "00": 1x when "01: 2x when // "10":3x when "11" 4x #define ADC_adc_ch6_gain_adc_channel6_gain_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch7_gain register. // //****************************************************************************** #define ADC_adc_ch7_gain_adc_channel7_gain_M \ 0x00000003 // gain setting for ADC channel 7. // when "00": 1x when "01: 2x when // "10":3x when "11" 4x #define ADC_adc_ch7_gain_adc_channel7_gain_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch0_irq_en register. // //****************************************************************************** #define ADC_adc_ch0_irq_en_adc_channel0_irq_en_M \ 0x0000000F // interrupt enable register for // per ADC channel bit 3: when '1' // -> enable FIFO overflow interrupt // bit 2: when '1' -> enable FIFO // underflow interrupt bit 1: when // "1' -> enable FIFO empty // interrupt bit 0: when "1" -> // enable FIFO full interrupt #define ADC_adc_ch0_irq_en_adc_channel0_irq_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch1_irq_en register. // //****************************************************************************** #define ADC_adc_ch1_irq_en_adc_channel1_irq_en_M \ 0x0000000F // interrupt enable register for // per ADC channel bit 3: when '1' // -> enable FIFO overflow interrupt // bit 2: when '1' -> enable FIFO // underflow interrupt bit 1: when // "1' -> enable FIFO empty // interrupt bit 0: when "1" -> // enable FIFO full interrupt #define ADC_adc_ch1_irq_en_adc_channel1_irq_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch2_irq_en register. // //****************************************************************************** #define ADC_adc_ch2_irq_en_adc_channel2_irq_en_M \ 0x0000000F // interrupt enable register for // per ADC channel bit 3: when '1' // -> enable FIFO overflow interrupt // bit 2: when '1' -> enable FIFO // underflow interrupt bit 1: when // "1' -> enable FIFO empty // interrupt bit 0: when "1" -> // enable FIFO full interrupt #define ADC_adc_ch2_irq_en_adc_channel2_irq_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch3_irq_en register. // //****************************************************************************** #define ADC_adc_ch3_irq_en_adc_channel3_irq_en_M \ 0x0000000F // interrupt enable register for // per ADC channel bit 3: when '1' // -> enable FIFO overflow interrupt // bit 2: when '1' -> enable FIFO // underflow interrupt bit 1: when // "1' -> enable FIFO empty // interrupt bit 0: when "1" -> // enable FIFO full interrupt #define ADC_adc_ch3_irq_en_adc_channel3_irq_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch4_irq_en register. // //****************************************************************************** #define ADC_adc_ch4_irq_en_adc_channel4_irq_en_M \ 0x0000000F // interrupt enable register for // per ADC channel bit 3: when '1' // -> enable FIFO overflow interrupt // bit 2: when '1' -> enable FIFO // underflow interrupt bit 1: when // "1' -> enable FIFO empty // interrupt bit 0: when "1" -> // enable FIFO full interrupt #define ADC_adc_ch4_irq_en_adc_channel4_irq_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch5_irq_en register. // //****************************************************************************** #define ADC_adc_ch5_irq_en_adc_channel5_irq_en_M \ 0x0000000F // interrupt enable register for // per ADC channel bit 3: when '1' // -> enable FIFO overflow interrupt // bit 2: when '1' -> enable FIFO // underflow interrupt bit 1: when // "1' -> enable FIFO empty // interrupt bit 0: when "1" -> // enable FIFO full interrupt #define ADC_adc_ch5_irq_en_adc_channel5_irq_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch6_irq_en register. // //****************************************************************************** #define ADC_adc_ch6_irq_en_adc_channel6_irq_en_M \ 0x0000000F // interrupt enable register for // per ADC channel bit 3: when '1' // -> enable FIFO overflow interrupt // bit 2: when '1' -> enable FIFO // underflow interrupt bit 1: when // "1' -> enable FIFO empty // interrupt bit 0: when "1" -> // enable FIFO full interrupt #define ADC_adc_ch6_irq_en_adc_channel6_irq_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch7_irq_en register. // //****************************************************************************** #define ADC_adc_ch7_irq_en_adc_channel7_irq_en_M \ 0x0000000F // interrupt enable register for // per ADC channel bit 3: when '1' // -> enable FIFO overflow interrupt // bit 2: when '1' -> enable FIFO // underflow interrupt bit 1: when // "1' -> enable FIFO empty // interrupt bit 0: when "1" -> // enable FIFO full interrupt #define ADC_adc_ch7_irq_en_adc_channel7_irq_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch0_irq_status register. // //****************************************************************************** #define ADC_adc_ch0_irq_status_adc_channel0_irq_status_M \ 0x0000000F // interrupt status register for // per ADC channel. Interrupt status // can be cleared on write. bit 3: // when value '1' is written -> // would clear FIFO overflow // interrupt status in the next // cycle. if same interrupt is set // in the same cycle then interurpt // would be set and clear command // will be ignored. bit 2: when // value '1' is written -> would // clear FIFO underflow interrupt // status in the next cycle. bit 1: // when value '1' is written -> // would clear FIFO empty interrupt // status in the next cycle. bit 0: // when value '1' is written -> // would clear FIFO full interrupt // status in the next cycle. #define ADC_adc_ch0_irq_status_adc_channel0_irq_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch1_irq_status register. // //****************************************************************************** #define ADC_adc_ch1_irq_status_adc_channel1_irq_status_M \ 0x0000000F // interrupt status register for // per ADC channel. Interrupt status // can be cleared on write. bit 3: // when value '1' is written -> // would clear FIFO overflow // interrupt status in the next // cycle. if same interrupt is set // in the same cycle then interurpt // would be set and clear command // will be ignored. bit 2: when // value '1' is written -> would // clear FIFO underflow interrupt // status in the next cycle. bit 1: // when value '1' is written -> // would clear FIFO empty interrupt // status in the next cycle. bit 0: // when value '1' is written -> // would clear FIFO full interrupt // status in the next cycle. #define ADC_adc_ch1_irq_status_adc_channel1_irq_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch2_irq_status register. // //****************************************************************************** #define ADC_adc_ch2_irq_status_adc_channel2_irq_status_M \ 0x0000000F // interrupt status register for // per ADC channel. Interrupt status // can be cleared on write. bit 3: // when value '1' is written -> // would clear FIFO overflow // interrupt status in the next // cycle. if same interrupt is set // in the same cycle then interurpt // would be set and clear command // will be ignored. bit 2: when // value '1' is written -> would // clear FIFO underflow interrupt // status in the next cycle. bit 1: // when value '1' is written -> // would clear FIFO empty interrupt // status in the next cycle. bit 0: // when value '1' is written -> // would clear FIFO full interrupt // status in the next cycle. #define ADC_adc_ch2_irq_status_adc_channel2_irq_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch3_irq_status register. // //****************************************************************************** #define ADC_adc_ch3_irq_status_adc_channel3_irq_status_M \ 0x0000000F // interrupt status register for // per ADC channel. Interrupt status // can be cleared on write. bit 3: // when value '1' is written -> // would clear FIFO overflow // interrupt status in the next // cycle. if same interrupt is set // in the same cycle then interurpt // would be set and clear command // will be ignored. bit 2: when // value '1' is written -> would // clear FIFO underflow interrupt // status in the next cycle. bit 1: // when value '1' is written -> // would clear FIFO empty interrupt // status in the next cycle. bit 0: // when value '1' is written -> // would clear FIFO full interrupt // status in the next cycle. #define ADC_adc_ch3_irq_status_adc_channel3_irq_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch4_irq_status register. // //****************************************************************************** #define ADC_adc_ch4_irq_status_adc_channel4_irq_status_M \ 0x0000000F // interrupt status register for // per ADC channel. Interrupt status // can be cleared on write. bit 3: // when value '1' is written -> // would clear FIFO overflow // interrupt status in the next // cycle. if same interrupt is set // in the same cycle then interurpt // would be set and clear command // will be ignored. bit 2: when // value '1' is written -> would // clear FIFO underflow interrupt // status in the next cycle. bit 1: // when value '1' is written -> // would clear FIFO empty interrupt // status in the next cycle. bit 0: // when value '1' is written -> // would clear FIFO full interrupt // status in the next cycle. #define ADC_adc_ch4_irq_status_adc_channel4_irq_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch5_irq_status register. // //****************************************************************************** #define ADC_adc_ch5_irq_status_adc_channel5_irq_status_M \ 0x0000000F // interrupt status register for // per ADC channel. Interrupt status // can be cleared on write. bit 3: // when value '1' is written -> // would clear FIFO overflow // interrupt status in the next // cycle. if same interrupt is set // in the same cycle then interurpt // would be set and clear command // will be ignored. bit 2: when // value '1' is written -> would // clear FIFO underflow interrupt // status in the next cycle. bit 1: // when value '1' is written -> // would clear FIFO empty interrupt // status in the next cycle. bit 0: // when value '1' is written -> // would clear FIFO full interrupt // status in the next cycle. #define ADC_adc_ch5_irq_status_adc_channel5_irq_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch6_irq_status register. // //****************************************************************************** #define ADC_adc_ch6_irq_status_adc_channel6_irq_status_M \ 0x0000000F // interrupt status register for // per ADC channel. Interrupt status // can be cleared on write. bit 3: // when value '1' is written -> // would clear FIFO overflow // interrupt status in the next // cycle. if same interrupt is set // in the same cycle then interurpt // would be set and clear command // will be ignored. bit 2: when // value '1' is written -> would // clear FIFO underflow interrupt // status in the next cycle. bit 1: // when value '1' is written -> // would clear FIFO empty interrupt // status in the next cycle. bit 0: // when value '1' is written -> // would clear FIFO full interrupt // status in the next cycle. #define ADC_adc_ch6_irq_status_adc_channel6_irq_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch7_irq_status register. // //****************************************************************************** #define ADC_adc_ch7_irq_status_adc_channel7_irq_status_M \ 0x0000000F // interrupt status register for // per ADC channel. Interrupt status // can be cleared on write. bit 3: // when value '1' is written -> // would clear FIFO overflow // interrupt status in the next // cycle. if same interrupt is set // in the same cycle then interurpt // would be set and clear command // will be ignored. bit 2: when // value '1' is written -> would // clear FIFO underflow interrupt // status in the next cycle. bit 1: // when value '1' is written -> // would clear FIFO empty interrupt // status in the next cycle. bit 0: // when value '1' is written -> // would clear FIFO full interrupt // status in the next cycle. #define ADC_adc_ch7_irq_status_adc_channel7_irq_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_dma_mode_en register. // //****************************************************************************** #define ADC_adc_dma_mode_en_DMA_MODEenable_M \ 0x000000FF // this register enable DMA mode. // when '1' respective ADC channel // is enabled for DMA. When '0' only // interrupt mode is enabled. Bit 0: // channel 0 DMA mode enable. Bit 1: // channel 1 DMA mode enable. Bit 2: // channel 2 DMA mode enable. Bit 3: // channel 3 DMA mode enable. bit 4: // channel 4 DMA mode enable. bit 5: // channel 5 DMA mode enable. bit 6: // channel 6 DMA mode enable. bit 7: // channel 7 DMA mode enable. #define ADC_adc_dma_mode_en_DMA_MODEenable_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_timer_configuration register. // //****************************************************************************** #define ADC_adc_timer_configuration_timeren \ 0x02000000 // when '1' timer is enabled. #define ADC_adc_timer_configuration_timerreset \ 0x01000000 // when '1' reset timer. #define ADC_adc_timer_configuration_timercount_M \ 0x00FFFFFF // Timer count configuration. 17 // bit counter is supported. Other // MSB's are redundent. #define ADC_adc_timer_configuration_timercount_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_timer_current_count register. // //****************************************************************************** #define ADC_adc_timer_current_count_timercurrentcount_M \ 0x0001FFFF // Timer count configuration #define ADC_adc_timer_current_count_timercurrentcount_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_channel0FIFODATA register. // //****************************************************************************** #define ADC_channel0FIFODATA_FIFO_RD_DATA_M \ 0xFFFFFFFF // read to this register would // return ADC data along with time // stamp information in following // format: bits [13:0] : ADC sample // bits [31:14]: : time stamp per // ADC sample #define ADC_channel0FIFODATA_FIFO_RD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_channel1FIFODATA register. // //****************************************************************************** #define ADC_channel1FIFODATA_FIFO_RD_DATA_M \ 0xFFFFFFFF // read to this register would // return ADC data along with time // stamp information in following // format: bits [13:0] : ADC sample // bits [31:14]: : time stamp per // ADC sample #define ADC_channel1FIFODATA_FIFO_RD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_channel2FIFODATA register. // //****************************************************************************** #define ADC_channel2FIFODATA_FIFO_RD_DATA_M \ 0xFFFFFFFF // read to this register would // return ADC data along with time // stamp information in following // format: bits [13:0] : ADC sample // bits [31:14]: : time stamp per // ADC sample #define ADC_channel2FIFODATA_FIFO_RD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_channel3FIFODATA register. // //****************************************************************************** #define ADC_channel3FIFODATA_FIFO_RD_DATA_M \ 0xFFFFFFFF // read to this register would // return ADC data along with time // stamp information in following // format: bits [13:0] : ADC sample // bits [31:14]: : time stamp per // ADC sample #define ADC_channel3FIFODATA_FIFO_RD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_channel4FIFODATA register. // //****************************************************************************** #define ADC_channel4FIFODATA_FIFO_RD_DATA_M \ 0xFFFFFFFF // read to this register would // return ADC data along with time // stamp information in following // format: bits [13:0] : ADC sample // bits [31:14]: : time stamp per // ADC sample #define ADC_channel4FIFODATA_FIFO_RD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_channel5FIFODATA register. // //****************************************************************************** #define ADC_channel5FIFODATA_FIFO_RD_DATA_M \ 0xFFFFFFFF // read to this register would // return ADC data along with time // stamp information in following // format: bits [13:0] : ADC sample // bits [31:14]: : time stamp per // ADC sample #define ADC_channel5FIFODATA_FIFO_RD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_channel6FIFODATA register. // //****************************************************************************** #define ADC_channel6FIFODATA_FIFO_RD_DATA_M \ 0xFFFFFFFF // read to this register would // return ADC data along with time // stamp information in following // format: bits [13:0] : ADC sample // bits [31:14]: : time stamp per // ADC sample #define ADC_channel6FIFODATA_FIFO_RD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_channel7FIFODATA register. // //****************************************************************************** #define ADC_channel7FIFODATA_FIFO_RD_DATA_M \ 0xFFFFFFFF // read to this register would // return ADC data along with time // stamp information in following // format: bits [13:0] : ADC sample // bits [31:14]: : time stamp per // ADC sample #define ADC_channel7FIFODATA_FIFO_RD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch0_fifo_lvl register. // //****************************************************************************** #define ADC_adc_ch0_fifo_lvl_adc_channel0_fifo_lvl_M \ 0x00000007 // This register shows current FIFO // level. FIFO is 4 word wide. // Possible supported levels are : // 0x0 to 0x3 #define ADC_adc_ch0_fifo_lvl_adc_channel0_fifo_lvl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch1_fifo_lvl register. // //****************************************************************************** #define ADC_adc_ch1_fifo_lvl_adc_channel1_fifo_lvl_M \ 0x00000007 // This register shows current FIFO // level. FIFO is 4 word wide. // Possible supported levels are : // 0x0 to 0x3 #define ADC_adc_ch1_fifo_lvl_adc_channel1_fifo_lvl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch2_fifo_lvl register. // //****************************************************************************** #define ADC_adc_ch2_fifo_lvl_adc_channel2_fifo_lvl_M \ 0x00000007 // This register shows current FIFO // level. FIFO is 4 word wide. // Possible supported levels are : // 0x0 to 0x3 #define ADC_adc_ch2_fifo_lvl_adc_channel2_fifo_lvl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch3_fifo_lvl register. // //****************************************************************************** #define ADC_adc_ch3_fifo_lvl_adc_channel3_fifo_lvl_M \ 0x00000007 // This register shows current FIFO // level. FIFO is 4 word wide. // Possible supported levels are : // 0x0 to 0x3 #define ADC_adc_ch3_fifo_lvl_adc_channel3_fifo_lvl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch4_fifo_lvl register. // //****************************************************************************** #define ADC_adc_ch4_fifo_lvl_adc_channel4_fifo_lvl_M \ 0x00000007 // This register shows current FIFO // level. FIFO is 4 word wide. // Possible supported levels are : // 0x0 to 0x3 #define ADC_adc_ch4_fifo_lvl_adc_channel4_fifo_lvl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch5_fifo_lvl register. // //****************************************************************************** #define ADC_adc_ch5_fifo_lvl_adc_channel5_fifo_lvl_M \ 0x00000007 // This register shows current FIFO // level. FIFO is 4 word wide. // Possible supported levels are : // 0x0 to 0x3 #define ADC_adc_ch5_fifo_lvl_adc_channel5_fifo_lvl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch6_fifo_lvl register. // //****************************************************************************** #define ADC_adc_ch6_fifo_lvl_adc_channel6_fifo_lvl_M \ 0x00000007 // This register shows current FIFO // level. FIFO is 4 word wide. // Possible supported levels are : // 0x0 to 0x3 #define ADC_adc_ch6_fifo_lvl_adc_channel6_fifo_lvl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // ADC_O_adc_ch7_fifo_lvl register. // //****************************************************************************** #define ADC_adc_ch7_fifo_lvl_adc_channel7_fifo_lvl_M \ 0x00000007 // This register shows current FIFO // level. FIFO is 4 word wide. // Possible supported levels are : // 0x0 to 0x3 #define ADC_adc_ch7_fifo_lvl_adc_channel7_fifo_lvl_S 0 #endif // __HW_ADC_H__ micropython-1.12/ports/cc3200/hal/inc/hw_aes.h000066400000000000000000001403111357706137100210170ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_AES_H__ #define __HW_AES_H__ //***************************************************************************** // // The following are defines for the AES_P register offsets. // //***************************************************************************** #define AES_O_KEY2_6 0x00000000 // XTS second key / CBC-MAC third // key #define AES_O_KEY2_7 0x00000004 // XTS second key (MSW for 256-bit // key) / CBC-MAC third key (MSW) #define AES_O_KEY2_4 0x00000008 // XTS / CCM second key / CBC-MAC // third key (LSW) #define AES_O_KEY2_5 0x0000000C // XTS second key (MSW for 192-bit // key) / CBC-MAC third key #define AES_O_KEY2_2 0x00000010 // XTS / CCM / CBC-MAC second key / // Hash Key input #define AES_O_KEY2_3 0x00000014 // XTS second key (MSW for 128-bit // key) + CCM/CBC-MAC second key // (MSW) / Hash Key input (MSW) #define AES_O_KEY2_0 0x00000018 // XTS / CCM / CBC-MAC second key // (LSW) / Hash Key input (LSW) #define AES_O_KEY2_1 0x0000001C // XTS / CCM / CBC-MAC second key / // Hash Key input #define AES_O_KEY1_6 0x00000020 // Key (LSW for 256-bit key) #define AES_O_KEY1_7 0x00000024 // Key (MSW for 256-bit key) #define AES_O_KEY1_4 0x00000028 // Key (LSW for 192-bit key) #define AES_O_KEY1_5 0x0000002C // Key (MSW for 192-bit key) #define AES_O_KEY1_2 0x00000030 // Key #define AES_O_KEY1_3 0x00000034 // Key (MSW for 128-bit key) #define AES_O_KEY1_0 0x00000038 // Key (LSW for 128-bit key) #define AES_O_KEY1_1 0x0000003C // Key #define AES_O_IV_IN_0 0x00000040 // Initialization Vector input // (LSW) #define AES_O_IV_IN_1 0x00000044 // Initialization vector input #define AES_O_IV_IN_2 0x00000048 // Initialization vector input #define AES_O_IV_IN_3 0x0000004C // Initialization Vector input // (MSW) #define AES_O_CTRL 0x00000050 // register determines the mode of // operation of the AES Engine #define AES_O_C_LENGTH_0 0x00000054 // Crypto data length registers // (LSW and MSW) store the // cryptographic data length in // bytes for all modes. Once // processing with this context is // started@@ this length decrements // to zero. Data lengths up to (2^61 // – 1) bytes are allowed. For GCM@@ // any value up to 2^36 - 32 bytes // can be used. This is because a // 32-bit counter mode is used; the // maximum number of 128-bit blocks // is 2^32 – 2@@ resulting in a // maximum number of bytes of 2^36 - // 32. A write to this register // triggers the engine to start // using this context. This is valid // for all modes except GCM and CCM. // Note that for the combined // modes@@ this length does not // include the authentication only // data; the authentication length // is specified in the // AES_AUTH_LENGTH register below. // All modes must have a length > 0. // For the combined modes@@ it is // allowed to have one of the // lengths equal to zero. For the // basic encryption modes // (ECB/CBC/CTR/ICM/CFB128) it is // allowed to program zero to the // length field; in that case the // length is assumed infinite. All // data must be byte (8-bit) // aligned; bit aligned data streams // are not supported by the AES // Engine. For a Host read // operation@@ these registers // return all-zeroes. #define AES_O_C_LENGTH_1 0x00000058 // Crypto data length registers // (LSW and MSW) store the // cryptographic data length in // bytes for all modes. Once // processing with this context is // started@@ this length decrements // to zero. Data lengths up to (2^61 // – 1) bytes are allowed. For GCM@@ // any value up to 2^36 - 32 bytes // can be used. This is because a // 32-bit counter mode is used; the // maximum number of 128-bit blocks // is 2^32 – 2@@ resulting in a // maximum number of bytes of 2^36 - // 32. A write to this register // triggers the engine to start // using this context. This is valid // for all modes except GCM and CCM. // Note that for the combined // modes@@ this length does not // include the authentication only // data; the authentication length // is specified in the // AES_AUTH_LENGTH register below. // All modes must have a length > 0. // For the combined modes@@ it is // allowed to have one of the // lengths equal to zero. For the // basic encryption modes // (ECB/CBC/CTR/ICM/CFB128) it is // allowed to program zero to the // length field; in that case the // length is assumed infinite. All // data must be byte (8-bit) // aligned; bit aligned data streams // are not supported by the AES // Engine. For a Host read // operation@@ these registers // return all-zeroes. #define AES_O_AUTH_LENGTH 0x0000005C // AAD data length. The // authentication length register // store the authentication data // length in bytes for combined // modes only (GCM or CCM) Supported // AAD-lengths for CCM are from 0 to // (2^16 - 2^8) bytes. For GCM any // value up to (2^32 - 1) bytes can // be used. Once processing with // this context is started@@ this // length decrements to zero. A // write to this register triggers // the engine to start using this // context for GCM and CCM. For XTS // this register is optionally used // to load ‘j’. Loading of ‘j’ is // only required if ‘j’ != 0. ‘j’ is // a 28-bit value and must be // written to bits [31-4] of this // register. ‘j’ represents the // sequential number of the 128-bit // block inside the data unit. For // the first block in a unit@@ this // value is zero. It is not required // to provide a ‘j’ for each new // data block within a unit. Note // that it is possible to start with // a ‘j’ unequal to zero; refer to // Table 4 for more details. For a // Host read operation@@ these // registers return all-zeroes. #define AES_O_DATA_IN_0 0x00000060 // Data register to read and write // plaintext/ciphertext (MSW) #define AES_O_DATA_IN_1 0x00000064 // Data register to read and write // plaintext/ciphertext #define AES_O_DATA_IN_2 0x00000068 // Data register to read and write // plaintext/ciphertext #define AES_O_DATA_IN_3 0x0000006C // Data register to read and write // plaintext/ciphertext (LSW) #define AES_O_TAG_OUT_0 0x00000070 #define AES_O_TAG_OUT_1 0x00000074 #define AES_O_TAG_OUT_2 0x00000078 #define AES_O_TAG_OUT_3 0x0000007C #define AES_O_REVISION 0x00000080 // Register AES_REVISION #define AES_O_SYSCONFIG 0x00000084 // Register AES_SYSCONFIG.This // register configures the DMA // signals and controls the IDLE and // reset logic #define AES_O_SYSSTATUS 0x00000088 #define AES_O_IRQSTATUS 0x0000008C // This register indicates the // interrupt status. If one of the // interrupt bits is set the // interrupt output will be asserted #define AES_O_IRQENABLE 0x00000090 // This register contains an enable // bit for each unique interrupt // generated by the module. It // matches the layout of // AES_IRQSTATUS register. An // interrupt is enabled when the bit // in this register is set to ‘1’. // An interrupt that is enabled is // propagated to the SINTREQUEST_x // output. All interrupts need to be // enabled explicitly by writing // this register. //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY2_6 register. // //****************************************************************************** #define AES_KEY2_6_KEY_M 0xFFFFFFFF // key data #define AES_KEY2_6_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY2_7 register. // //****************************************************************************** #define AES_KEY2_7_KEY_M 0xFFFFFFFF // key data #define AES_KEY2_7_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY2_4 register. // //****************************************************************************** #define AES_KEY2_4_KEY_M 0xFFFFFFFF // key data #define AES_KEY2_4_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY2_5 register. // //****************************************************************************** #define AES_KEY2_5_KEY_M 0xFFFFFFFF // key data #define AES_KEY2_5_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY2_2 register. // //****************************************************************************** #define AES_KEY2_2_KEY_M 0xFFFFFFFF // key data #define AES_KEY2_2_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY2_3 register. // //****************************************************************************** #define AES_KEY2_3_KEY_M 0xFFFFFFFF // key data #define AES_KEY2_3_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY2_0 register. // //****************************************************************************** #define AES_KEY2_0_KEY_M 0xFFFFFFFF // key data #define AES_KEY2_0_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY2_1 register. // //****************************************************************************** #define AES_KEY2_1_KEY_M 0xFFFFFFFF // key data #define AES_KEY2_1_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY1_6 register. // //****************************************************************************** #define AES_KEY1_6_KEY_M 0xFFFFFFFF // key data #define AES_KEY1_6_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY1_7 register. // //****************************************************************************** #define AES_KEY1_7_KEY_M 0xFFFFFFFF // key data #define AES_KEY1_7_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY1_4 register. // //****************************************************************************** #define AES_KEY1_4_KEY_M 0xFFFFFFFF // key data #define AES_KEY1_4_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY1_5 register. // //****************************************************************************** #define AES_KEY1_5_KEY_M 0xFFFFFFFF // key data #define AES_KEY1_5_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY1_2 register. // //****************************************************************************** #define AES_KEY1_2_KEY_M 0xFFFFFFFF // key data #define AES_KEY1_2_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY1_3 register. // //****************************************************************************** #define AES_KEY1_3_KEY_M 0xFFFFFFFF // key data #define AES_KEY1_3_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY1_0 register. // //****************************************************************************** #define AES_KEY1_0_KEY_M 0xFFFFFFFF // key data #define AES_KEY1_0_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_KEY1_1 register. // //****************************************************************************** #define AES_KEY1_1_KEY_M 0xFFFFFFFF // key data #define AES_KEY1_1_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_IV_IN_0 register. // //****************************************************************************** #define AES_IV_IN_0_DATA_M 0xFFFFFFFF // IV data #define AES_IV_IN_0_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_IV_IN_1 register. // //****************************************************************************** #define AES_IV_IN_1_DATA_M 0xFFFFFFFF // IV data #define AES_IV_IN_1_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_IV_IN_2 register. // //****************************************************************************** #define AES_IV_IN_2_DATA_M 0xFFFFFFFF // IV data #define AES_IV_IN_2_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_IV_IN_3 register. // //****************************************************************************** #define AES_IV_IN_3_DATA_M 0xFFFFFFFF // IV data #define AES_IV_IN_3_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_CTRL register. // //****************************************************************************** #define AES_CTRL_CONTEXT_READY \ 0x80000000 // If ‘1’@@ this read-only status // bit indicates that the context // data registers can be overwritten // and the host is permitted to // write the next context. #define AES_CTRL_SVCTXTRDY \ 0x40000000 // If ‘1’@@ this read-only status // bit indicates that an AES // authentication TAG and/or IV // block(s) is/are available for the // host to retrieve. This bit is // only asserted if the // ‘save_context’ bit is set to ‘1’. // The bit is mutual exclusive with // the ‘context_ready’ bit. #define AES_CTRL_SAVE_CONTEXT 0x20000000 // This bit is used to indicate // that an authentication TAG or // result IV needs to be stored as a // result context. If this bit is // set@@ context output DMA and/or // interrupt will be asserted if the // operation is finished and related // signals are enabled. #define AES_CTRL_CCM_M 0x01C00000 // Defines “M” that indicated the // length of the authentication // field for CCM operations; the // authentication field length // equals two times (the value of // CCM-M plus one). Note that the // AES Engine always returns a // 128-bit authentication field@@ of // which the M least significant // bytes are valid. All values are // supported. #define AES_CTRL_CCM_S 22 #define AES_CTRL_CCM_L_M 0x00380000 // Defines “L” that indicated the // width of the length field for CCM // operations; the length field in // bytes equals the value of CMM-L // plus one. Supported values for L // are (programmed value): 2 (1)@@ 4 // (3) and 8 (7). #define AES_CTRL_CCM_L_S 19 #define AES_CTRL_CCM 0x00040000 // AES-CCM is selected@@ this is a // combined mode@@ using AES for // both authentication and // encryption. No additional mode // selection is required. 0 Other // mode selected 1 ccm mode selected #define AES_CTRL_GCM_M 0x00030000 // AES-GCM mode is selected.this is // a combined mode@@ using the // Galois field multiplier GF(2^128) // for authentication and AES-CTR // mode for encryption@@ the bits // specify the GCM mode. 0x0 No // operation 0x1 GHASH with H loaded // and Y0-encrypted forced to zero // 0x2 GHASH with H loaded and // Y0-encrypted calculated // internally 0x3 Autonomous GHASH // (both H and Y0-encrypted // calculated internally) #define AES_CTRL_GCM_S 16 #define AES_CTRL_CBCMAC 0x00008000 // AES-CBC MAC is selected@@ the // Direction bit must be set to ‘1’ // for this mode. 0 Other mode // selected 1 cbcmac mode selected #define AES_CTRL_F9 0x00004000 // AES f9 mode is selected@@ the // AES key size must be set to // 128-bit for this mode. 0 Other // mode selected 1 f9 selected #define AES_CTRL_F8 0x00002000 // AES f8 mode is selected@@ the // AES key size must be set to // 128-bit for this mode. 0 Other // mode selected 1 f8 selected #define AES_CTRL_XTS_M 0x00001800 // AES-XTS operation is selected; // the bits specify the XTS mode.01 // = Previous/intermediate tweak // value and ‘j’ loaded (value is // loaded via IV@@ j is loaded via // the AAD length register) 0x0 No // operation 0x1 // Previous/intermediate tweak value // and ‘j’ loaded (value is loaded // via IV@@ j is loaded via the AAD // length register) 0x2 Key2@@ i and // j loaded (i is loaded via IV@@ j // is loaded via the AAD length // register) 0x3 Key2 and i loaded@@ // j=0 (i is loaded via IV) #define AES_CTRL_XTS_S 11 #define AES_CTRL_CFB 0x00000400 // full block AES cipher feedback // mode (CFB128) is selected. 0 // other mode selected 1 cfb // selected #define AES_CTRL_ICM 0x00000200 // AES integer counter mode (ICM) // is selected@@ this is a counter // mode with a 16-bit wide counter. // 0 Other mode selected. 1 ICM mode // selected #define AES_CTRL_CTR_WIDTH_M 0x00000180 // Specifies the counter width for // AES-CTR mode 0x0 Counter is 32 // bits 0x1 Counter is 64 bits 0x2 // Counter is 128 bits 0x3 Counter // is 192 bits #define AES_CTRL_CTR_WIDTH_S 7 #define AES_CTRL_CTR 0x00000040 // Tthis bit must also be set for // GCM and CCM@@ when // encryption/decryption is // required. 0 Other mode selected 1 // Counter mode #define AES_CTRL_MODE 0x00000020 // ecb/cbc mode 0 ecb mode 1 cbc // mode #define AES_CTRL_KEY_SIZE_M 0x00000018 // key size 0x0 reserved 0x1 Key is // 128 bits. 0x2 Key is 192 bits 0x3 // Key is 256 #define AES_CTRL_KEY_SIZE_S 3 #define AES_CTRL_DIRECTION 0x00000004 // If set to ‘1’ an encrypt // operation is performed. If set to // ‘0’ a decrypt operation is // performed. Read 0 decryption is // selected Read 1 Encryption is // selected #define AES_CTRL_INPUT_READY 0x00000002 // If ‘1’@@ this read-only status // bit indicates that the 16-byte // input buffer is empty@@ and the // host is permitted to write the // next block of data. #define AES_CTRL_OUTPUT_READY 0x00000001 // If ‘1’@@ this read-only status // bit indicates that an AES output // block is available for the host // to retrieve. //****************************************************************************** // // The following are defines for the bit fields in the // AES_O_C_LENGTH_0 register. // //****************************************************************************** //****************************************************************************** // // The following are defines for the bit fields in the // AES_O_C_LENGTH_1 register. // //****************************************************************************** #define AES_C_LENGTH_1_LENGTH_M \ 0x1FFFFFFF // Data length (MSW) length // registers (LSW and MSW) store the // cryptographic data length in // bytes for all modes. Once // processing with this context is // started@@ this length decrements // to zero. Data lengths up to (2^61 // – 1) bytes are allowed. For GCM@@ // any value up to 2^36 - 32 bytes // can be used. This is because a // 32-bit counter mode is used; the // maximum number of 128-bit blocks // is 2^32 – 2@@ resulting in a // maximum number of bytes of 2^36 - // 32. A write to this register // triggers the engine to start // using this context. This is valid // for all modes except GCM and CCM. // Note that for the combined // modes@@ this length does not // include the authentication only // data; the authentication length // is specified in the // AES_AUTH_LENGTH register below. // All modes must have a length > 0. // For the combined modes@@ it is // allowed to have one of the // lengths equal to zero. For the // basic encryption modes // (ECB/CBC/CTR/ICM/CFB128) it is // allowed to program zero to the // length field; in that case the // length is assumed infinite. All // data must be byte (8-bit) // aligned; bit aligned data streams // are not supported by the AES // Engine. For a Host read // operation@@ these registers // return all-zeroes. #define AES_C_LENGTH_1_LENGTH_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // AES_O_AUTH_LENGTH register. // //****************************************************************************** #define AES_AUTH_LENGTH_AUTH_M \ 0xFFFFFFFF // data #define AES_AUTH_LENGTH_AUTH_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_DATA_IN_0 register. // //****************************************************************************** #define AES_DATA_IN_0_DATA_M 0xFFFFFFFF // Data to encrypt/decrypt #define AES_DATA_IN_0_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_DATA_IN_1 register. // //****************************************************************************** #define AES_DATA_IN_1_DATA_M 0xFFFFFFFF // Data to encrypt/decrypt #define AES_DATA_IN_1_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_DATA_IN_2 register. // //****************************************************************************** #define AES_DATA_IN_2_DATA_M 0xFFFFFFFF // Data to encrypt/decrypt #define AES_DATA_IN_2_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_DATA_IN_3 register. // //****************************************************************************** #define AES_DATA_IN_3_DATA_M 0xFFFFFFFF // Data to encrypt/decrypt #define AES_DATA_IN_3_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_TAG_OUT_0 register. // //****************************************************************************** #define AES_TAG_OUT_0_HASH_M 0xFFFFFFFF // Hash result (MSW) #define AES_TAG_OUT_0_HASH_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_TAG_OUT_1 register. // //****************************************************************************** #define AES_TAG_OUT_1_HASH_M 0xFFFFFFFF // Hash result (MSW) #define AES_TAG_OUT_1_HASH_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_TAG_OUT_2 register. // //****************************************************************************** #define AES_TAG_OUT_2_HASH_M 0xFFFFFFFF // Hash result (MSW) #define AES_TAG_OUT_2_HASH_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_TAG_OUT_3 register. // //****************************************************************************** #define AES_TAG_OUT_3_HASH_M 0xFFFFFFFF // Hash result (LSW) #define AES_TAG_OUT_3_HASH_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_REVISION register. // //****************************************************************************** #define AES_REVISION_SCHEME_M 0xC0000000 #define AES_REVISION_SCHEME_S 30 #define AES_REVISION_FUNC_M 0x0FFF0000 // Function indicates a software // compatible module family. If // there is no level of software // compatibility a new Func number // (and hence REVISION) should be // assigned. #define AES_REVISION_FUNC_S 16 #define AES_REVISION_R_RTL_M 0x0000F800 // RTL Version (R)@@ maintained by // IP design owner. RTL follows a // numbering such as X.Y.R.Z which // are explained in this table. R // changes ONLY when: (1) PDS // uploads occur which may have been // due to spec changes (2) Bug fixes // occur (3) Resets to '0' when X or // Y changes. Design team has an // internal 'Z' (customer invisible) // number which increments on every // drop that happens due to DV and // RTL updates. Z resets to 0 when R // increments. #define AES_REVISION_R_RTL_S 11 #define AES_REVISION_X_MAJOR_M \ 0x00000700 // Major Revision (X)@@ maintained // by IP specification owner. X // changes ONLY when: (1) There is a // major feature addition. An // example would be adding Master // Mode to Utopia Level2. The Func // field (or Class/Type in old PID // format) will remain the same. X // does NOT change due to: (1) Bug // fixes (2) Change in feature // parameters. #define AES_REVISION_X_MAJOR_S 8 #define AES_REVISION_CUSTOM_M 0x000000C0 #define AES_REVISION_CUSTOM_S 6 #define AES_REVISION_Y_MINOR_M \ 0x0000003F // Minor Revision (Y)@@ maintained // by IP specification owner. Y // changes ONLY when: (1) Features // are scaled (up or down). // Flexibility exists in that this // feature scalability may either be // represented in the Y change or a // specific register in the IP that // indicates which features are // exactly available. (2) When // feature creeps from Is-Not list // to Is list. But this may not be // the case once it sees silicon; in // which case X will change. Y does // NOT change due to: (1) Bug fixes // (2) Typos or clarifications (3) // major functional/feature // change/addition/deletion. Instead // these changes may be reflected // via R@@ S@@ X as applicable. Spec // owner maintains a // customer-invisible number 'S' // which changes due to: (1) // Typos/clarifications (2) Bug // documentation. Note that this bug // is not due to a spec change but // due to implementation. // Nevertheless@@ the spec tracks // the IP bugs. An RTL release (say // for silicon PG1.1) that occurs // due to bug fix should document // the corresponding spec number // (X.Y.S) in its release notes. #define AES_REVISION_Y_MINOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_SYSCONFIG register. // //****************************************************************************** #define AES_SYSCONFIG_MACONTEXT_OUT_ON_DATA_OUT \ 0x00000200 // If set to '1' the two context // out requests // (dma_req_context_out_en@@ Bit [8] // above@@ and context_out interrupt // enable@@ Bit [3] of AES_IRQENABLE // register) are mapped on the // corresponding data output request // bit. In this case@@ the original // ‘context out’ bit values are // ignored. #define AES_SYSCONFIG_DMA_REQ_CONTEXT_OUT_EN \ 0x00000100 // If set to ‘1’@@ the DMA context // output request is enabled (for // context data out@@ e.g. TAG for // authentication modes). 0 Dma // disabled 1 Dma enabled #define AES_SYSCONFIG_DMA_REQ_CONTEXT_IN_EN \ 0x00000080 // If set to ‘1’@@ the DMA context // request is enabled. 0 Dma // disabled 1 Dma enabled #define AES_SYSCONFIG_DMA_REQ_DATA_OUT_EN \ 0x00000040 // If set to ‘1’@@ the DMA output // request is enabled. 0 Dma // disabled 1 Dma enabled #define AES_SYSCONFIG_DMA_REQ_DATA_IN_EN \ 0x00000020 // If set to ‘1’@@ the DMA input // request is enabled. 0 Dma // disabled 1 Dma enabled //****************************************************************************** // // The following are defines for the bit fields in the AES_O_SYSSTATUS register. // //****************************************************************************** #define AES_SYSSTATUS_RESETDONE \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the AES_O_IRQSTATUS register. // //****************************************************************************** #define AES_IRQSTATUS_CONTEXT_OUT \ 0x00000008 // This bit indicates // authentication tag (and IV) // interrupt(s) is/are active and // triggers the interrupt output. #define AES_IRQSTATUS_DATA_OUT \ 0x00000004 // This bit indicates data output // interrupt is active and triggers // the interrupt output. #define AES_IRQSTATUS_DATA_IN 0x00000002 // This bit indicates data input // interrupt is active and triggers // the interrupt output. #define AES_IRQSTATUS_CONTEX_IN \ 0x00000001 // This bit indicates context // interrupt is active and triggers // the interrupt output. //****************************************************************************** // // The following are defines for the bit fields in the AES_O_IRQENABLE register. // //****************************************************************************** #define AES_IRQENABLE_CONTEXT_OUT \ 0x00000008 // This bit indicates // authentication tag (and IV) // interrupt(s) is/are active and // triggers the interrupt output. #define AES_IRQENABLE_DATA_OUT \ 0x00000004 // This bit indicates data output // interrupt is active and triggers // the interrupt output. #define AES_IRQENABLE_DATA_IN 0x00000002 // This bit indicates data input // interrupt is active and triggers // the interrupt output. #define AES_IRQENABLE_CONTEX_IN \ 0x00000001 // This bit indicates context // interrupt is active and triggers // the interrupt output. #endif // __HW_AES_H__ micropython-1.12/ports/cc3200/hal/inc/hw_apps_config.h000066400000000000000000001214001357706137100225350ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_APPS_CONFIG_H__ #define __HW_APPS_CONFIG_H__ //***************************************************************************** // // The following are defines for the APPS_CONFIG register offsets. // //***************************************************************************** #define APPS_CONFIG_O_PATCH_TRAP_ADDR_REG \ 0x00000000 // Patch trap address Register // array #define APPS_CONFIG_O_PATCH_TRAP_EN_REG \ 0x00000078 #define APPS_CONFIG_O_FAULT_STATUS_REG \ 0x0000007C #define APPS_CONFIG_O_MEMSS_WR_ERR_CLR_REG \ 0x00000080 #define APPS_CONFIG_O_MEMSS_WR_ERR_ADDR_REG \ 0x00000084 #define APPS_CONFIG_O_DMA_DONE_INT_MASK \ 0x0000008C #define APPS_CONFIG_O_DMA_DONE_INT_MASK_SET \ 0x00000090 #define APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR \ 0x00000094 #define APPS_CONFIG_O_DMA_DONE_INT_STS_CLR \ 0x00000098 #define APPS_CONFIG_O_DMA_DONE_INT_ACK \ 0x0000009C #define APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED \ 0x000000A0 #define APPS_CONFIG_O_DMA_DONE_INT_STS_RAW \ 0x000000A4 #define APPS_CONFIG_O_FAULT_STATUS_CLR_REG \ 0x000000A8 #define APPS_CONFIG_O_RESERVD_REG_0 \ 0x000000AC #define APPS_CONFIG_O_GPT_TRIG_SEL \ 0x000000B0 #define APPS_CONFIG_O_TOP_DIE_SPARE_DIN_REG \ 0x000000B4 #define APPS_CONFIG_O_TOP_DIE_SPARE_DOUT_REG \ 0x000000B8 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_PATCH_TRAP_ADDR_REG register. // //****************************************************************************** #define APPS_CONFIG_PATCH_TRAP_ADDR_REG_PATCH_TRAP_ADDR_M \ 0xFFFFFFFF // When PATCH_TRAP_EN[n] is set bus // fault is generated for the // address // PATCH_TRAP_ADDR_REG[n][31:0] from // Idcode bus. The exception routine // should take care to jump to the // location where the patch // correspond to this address is // kept. #define APPS_CONFIG_PATCH_TRAP_ADDR_REG_PATCH_TRAP_ADDR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_PATCH_TRAP_EN_REG register. // //****************************************************************************** #define APPS_CONFIG_PATCH_TRAP_EN_REG_PATCH_TRAP_EN_M \ 0x3FFFFFFF // When PATCH_TRAP_EN[n] is set bus // fault is generated for the // address PATCH_TRAP_ADD[n][31:0] // from Idcode bus. The exception // routine should take care to jump // to the location where the patch // correspond to this address is // kept. #define APPS_CONFIG_PATCH_TRAP_EN_REG_PATCH_TRAP_EN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_FAULT_STATUS_REG register. // //****************************************************************************** #define APPS_CONFIG_FAULT_STATUS_REG_PATCH_ERR_INDEX_M \ 0x0000003E // This field shows because of // which patch trap address the // bus_fault is generated. If the // PATCH_ERR bit is set, then it // means the bus fault is generated // because of // PATCH_TRAP_ADDR_REG[2^PATCH_ERR_INDEX] #define APPS_CONFIG_FAULT_STATUS_REG_PATCH_ERR_INDEX_S 1 #define APPS_CONFIG_FAULT_STATUS_REG_PATCH_ERR \ 0x00000001 // This bit is set when there is a // bus fault because of patched // address access to the Apps boot // rom. Write 0 to clear this // register. //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_MEMSS_WR_ERR_CLR_REG register. // //****************************************************************************** #define APPS_CONFIG_MEMSS_WR_ERR_CLR_REG_MEMSS_WR_ERR_CLR \ 0x00000001 // This bit is set when there is a // an error in memss write access. // And the address causing this // error is captured in // MEMSS_ERR_ADDR_REG. To capture // the next error address one have // to clear this bit. //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_MEMSS_WR_ERR_ADDR_REG register. // //****************************************************************************** //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_DMA_DONE_INT_MASK register. // //****************************************************************************** #define APPS_CONFIG_DMA_DONE_INT_MASK_ADC_WR_DMA_DONE_INT_MASK_M \ 0x0000F000 // 1= disable corresponding // interrupt;0 = interrupt enabled // bit 14: ADC channel 7 interrupt // enable/disable bit 13: ADC // channel 5 interrupt // enable/disable bit 12: ADC // channel 3 interrupt // enable/disable bit 11: ADC // channel 1 interrupt // enable/disable #define APPS_CONFIG_DMA_DONE_INT_MASK_ADC_WR_DMA_DONE_INT_MASK_S 12 #define APPS_CONFIG_DMA_DONE_INT_MASK_MCASP_WR_DMA_DONE_INT_MASK \ 0x00000800 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_MCASP_RD_DMA_DONE_INT_MASK \ 0x00000400 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_CAM_FIFO_EMPTY_DMA_DONE_INT_MASK \ 0x00000200 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_CAM_THRESHHOLD_DMA_DONE_INT_MASK \ 0x00000100 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_SHSPI_WR_DMA_DONE_INT_MASK \ 0x00000080 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_SHSPI_RD_DMA_DONE_INT_MASK \ 0x00000040 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_HOSTSPI_WR_DMA_DONE_INT_MASK \ 0x00000020 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_HOSTSPI_RD_DMA_DONE_INT_MASK \ 0x00000010 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_APPS_SPI_WR_DMA_DONE_INT_MASK \ 0x00000008 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_APPS_SPI_RD_DMA_DONE_INT_MASK \ 0x00000004 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_SDIOM_WR_DMA_DONE_INT_MASK \ 0x00000002 // 1= disable corresponding // interrupt;0 = interrupt enabled #define APPS_CONFIG_DMA_DONE_INT_MASK_SDIOM_RD_DMA_DONE_INT_MASK \ 0x00000001 // 1= disable corresponding // interrupt;0 = interrupt enabled //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_DMA_DONE_INT_MASK_SET register. // //****************************************************************************** #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_ADC_WR_DMA_DONE_INT_MASK_SET_M \ 0x0000F000 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect bit 14: ADC channel 7 DMA // Done IRQ bit 13: ADC channel 5 // DMA Done IRQ bit 12: ADC channel // 3 DMA Done IRQ bit 11: ADC // channel 1 DMA Done IRQ #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_ADC_WR_DMA_DONE_INT_MASK_SET_S 12 #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_MCASP_WR_DMA_DONE_INT_MASK_SET \ 0x00000800 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_MCASP_RD_DMA_DONE_INT_MASK_SET \ 0x00000400 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_CAM_FIFO_EMPTY_DMA_DONE_INT_MASK_SET \ 0x00000200 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_CAM_THRESHHOLD_DMA_DONE_INT_MASK_SET \ 0x00000100 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_SHSPI_WR_DMA_DONE_INT_MASK_SET \ 0x00000080 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_SHSPI_RD_DMA_DONE_INT_MASK_SET \ 0x00000040 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_HOSTSPI_WR_DMA_DONE_INT_MASK_SET \ 0x00000020 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_HOSTSPI_RD_DMA_DONE_INT_MASK_SET \ 0x00000010 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_APPS_SPI_WR_DMA_DONE_INT_MASK_SET \ 0x00000008 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_APPS_SPI_RD_DMA_DONE_INT_MASK_SET \ 0x00000004 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_SDIOM_WR_DMA_DONE_INT_MASK_SET \ 0x00000002 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_SET_SDIOM_RD_DMA_DONE_INT_MASK_SET \ 0x00000001 // write 1 to set mask of the // corresponding DMA DONE IRQ;0 = no // effect //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR register. // //****************************************************************************** #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_ADC_WR_DMA_DONE_INT_MASK_CLR_M \ 0x0000F000 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect bit 14: ADC channel 7 DMA // Done IRQ mask bit 13: ADC channel // 5 DMA Done IRQ mask bit 12: ADC // channel 3 DMA Done IRQ mask bit // 11: ADC channel 1 DMA Done IRQ // mask #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_ADC_WR_DMA_DONE_INT_MASK_CLR_S 12 #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_MACASP_WR_DMA_DONE_INT_MASK_CLR \ 0x00000800 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_MCASP_RD_DMA_DONE_INT_MASK_CLR \ 0x00000400 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_CAM_FIFO_EMPTY_DMA_DONE_INT_MASK_CLR \ 0x00000200 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_CAM_THRESHHOLD_DMA_DONE_INT_MASK_CLR \ 0x00000100 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_SHSPI_WR_DMA_DONE_INT_MASK_CLR \ 0x00000080 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_SHSPI_RD_DMA_DONE_INT_MASK_CLR \ 0x00000040 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_HOSTSPI_WR_DMA_DONE_INT_MASK_CLR \ 0x00000020 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_HOSTSPI_RD_DMA_DONE_INT_MASK_CLR \ 0x00000010 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_APPS_SPI_WR_DMA_DONE_INT_MASK_CLR \ 0x00000008 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_APPS_SPI_RD_DMA_DONE_INT_MASK_CLR \ 0x00000004 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_SDIOM_WR_DMA_DONE_INT_MASK_CLR \ 0x00000002 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect #define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_SDIOM_RD_DMA_DONE_INT_MASK_CLR \ 0x00000001 // write 1 to clear mask of the // corresponding DMA DONE IRQ;0 = no // effect //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_DMA_DONE_INT_STS_CLR register. // //****************************************************************************** #define APPS_CONFIG_DMA_DONE_INT_STS_CLR_DMA_INT_STS_CLR_M \ 0xFFFFFFFF // write 1 or 0 to clear all // DMA_DONE interrupt; #define APPS_CONFIG_DMA_DONE_INT_STS_CLR_DMA_INT_STS_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_DMA_DONE_INT_ACK register. // //****************************************************************************** #define APPS_CONFIG_DMA_DONE_INT_ACK_ADC_WR_DMA_DONE_INT_ACK_M \ 0x0000F000 // write 1 to clear corresponding // interrupt; 0 = no effect; bit 14: // ADC channel 7 DMA Done IRQ bit // 13: ADC channel 5 DMA Done IRQ // bit 12: ADC channel 3 DMA Done // IRQ bit 11: ADC channel 1 DMA // Done IRQ #define APPS_CONFIG_DMA_DONE_INT_ACK_ADC_WR_DMA_DONE_INT_ACK_S 12 #define APPS_CONFIG_DMA_DONE_INT_ACK_MCASP_WR_DMA_DONE_INT_ACK \ 0x00000800 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_MCASP_RD_DMA_DONE_INT_ACK \ 0x00000400 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_CAM_FIFO_EMPTY_DMA_DONE_INT_ACK \ 0x00000200 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_CAM_THRESHHOLD_DMA_DONE_INT_ACK \ 0x00000100 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_SHSPI_WR_DMA_DONE_INT_ACK \ 0x00000080 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_SHSPI_RD_DMA_DONE_INT_ACK \ 0x00000040 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_HOSTSPI_WR_DMA_DONE_INT_ACK \ 0x00000020 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_HOSTSPI_RD_DMA_DONE_INT_ACK \ 0x00000010 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_APPS_SPI_WR_DMA_DONE_INT_ACK \ 0x00000008 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_APPS_SPI_RD_DMA_DONE_INT_ACK \ 0x00000004 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_SDIOM_WR_DMA_DONE_INT_ACK \ 0x00000002 // write 1 to clear corresponding // interrupt; 0 = no effect; #define APPS_CONFIG_DMA_DONE_INT_ACK_SDIOM_RD_DMA_DONE_INT_ACK \ 0x00000001 // write 1 to clear corresponding // interrupt; 0 = no effect; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED register. // //****************************************************************************** #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_ADC_WR_DMA_DONE_INT_STS_MASKED_M \ 0x0000F000 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask bit 14: ADC // channel 7 DMA Done IRQ bit 13: // ADC channel 5 DMA Done IRQ bit // 12: ADC channel 3 DMA Done IRQ // bit 11: ADC channel 1 DMA Done // IRQ #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_ADC_WR_DMA_DONE_INT_STS_MASKED_S 12 #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_MCASP_WR_DMA_DONE_INT_STS_MASKED \ 0x00000800 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_MCASP_RD_DMA_DONE_INT_STS_MASKED \ 0x00000400 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_CAM_FIFO_EMPTY_DMA_DONE_INT_STS_MASKED \ 0x00000200 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_CAM_THRESHHOLD_DMA_DONE_INT_STS_MASKED \ 0x00000100 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_SHSPI_WR_DMA_DONE_INT_STS_MASKED \ 0x00000080 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_SHSPI_RD_DMA_DONE_INT_STS_MASKED \ 0x00000040 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_HOSTSPI_WR_DMA_DONE_INT_STS_MASKED \ 0x00000020 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_HOSTSPI_RD_DMA_DONE_INT_STS_MASKED \ 0x00000010 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_APPS_SPI_WR_DMA_DONE_INT_STS_MASKED \ 0x00000008 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_APPS_SPI_RD_DMA_DONE_INT_STS_MASKED \ 0x00000004 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_SDIOM_WR_DMA_DONE_INT_STS_MASKED \ 0x00000002 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask #define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_SDIOM_RD_DMA_DONE_INT_STS_MASKED \ 0x00000001 // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by DMA_DONE_INT mask //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_DMA_DONE_INT_STS_RAW register. // //****************************************************************************** #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_ADC_WR_DMA_DONE_INT_STS_RAW_M \ 0x0000F000 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive bit 14: ADC channel 7 // DMA Done IRQ bit 13: ADC channel // 5 DMA Done IRQ bit 12: ADC // channel 3 DMA Done IRQ bit 11: // ADC channel 1 DMA Done IRQ #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_ADC_WR_DMA_DONE_INT_STS_RAW_S 12 #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_MCASP_WR_DMA_DONE_INT_STS_RAW \ 0x00000800 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_MCASP_RD_DMA_DONE_INT_STS_RAW \ 0x00000400 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_CAM_EPMTY_FIFO_DMA_DONE_INT_STS_RAW \ 0x00000200 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_CAM_THRESHHOLD_DMA_DONE_INT_STS_RAW \ 0x00000100 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_SHSPI_WR_DMA_DONE_INT_STS_RAW \ 0x00000080 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_SHSPI_RD_DMA_DONE_INT_STS_RAW \ 0x00000040 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_HOSTSPI_WR_DMA_DONE_INT_STS_RAW \ 0x00000020 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_HOSTSPI_RD_DMA_DONE_INT_STS_RAW \ 0x00000010 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_APPS_SPI_WR_DMA_DONE_INT_STS_RAW \ 0x00000008 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_APPS_SPI_RD_DMA_DONE_INT_STS_RAW \ 0x00000004 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_SDIOM_WR_DMA_DONE_INT_STS_RAW \ 0x00000002 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define APPS_CONFIG_DMA_DONE_INT_STS_RAW_SDIOM_RD_DMA_DONE_INT_STS_RAW \ 0x00000001 // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_FAULT_STATUS_CLR_REG register. // //****************************************************************************** #define APPS_CONFIG_FAULT_STATUS_CLR_REG_PATCH_ERR_CLR \ 0x00000001 // Write 1 to clear the LSB of // FAULT_STATUS_REG //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_RESERVD_REG_0 register. // //****************************************************************************** //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_GPT_TRIG_SEL register. // //****************************************************************************** #define APPS_CONFIG_GPT_TRIG_SEL_GPT_TRIG_SEL_M \ 0x000000FF // This bit is implemented for GPT // trigger mode select. GPT IP // support 2 modes: RTC mode and // external trigger. When this bit // is set to logic '1': enable // external trigger mode for APPS // GPT CP0 and CP1 pin. bit 0: when // set '1' enable external GPT // trigger 0 on GPIO0 CP0 pin else // RTC mode is selected. bit 1: when // set '1' enable external GPT // trigger 1 on GPIO0 CP1 pin else // RTC mode is selected. bit 2: when // set '1' enable external GPT // trigger 2 on GPIO1 CP0 pin else // RTC mode is selected. bit 3: when // set '1' enable external GPT // trigger 3 on GPIO1 CP1 pin else // RTC mode is selected. bit 4: when // set '1' enable external GPT // trigger 4 on GPIO2 CP0 pin else // RTC mode is selected. bit 5: when // set '1' enable external GPT // trigger 5 on GPIO2 CP1 pin else // RTC mode is selected. bit 6: when // set '1' enable external GPT // trigger 6 on GPIO3 CP0 pin else // RTC mode is selected. bit 7: when // set '1' enable external GPT // trigger 7 on GPIO3 CP1 pin else // RTC mode is selected. #define APPS_CONFIG_GPT_TRIG_SEL_GPT_TRIG_SEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_TOP_DIE_SPARE_DIN_REG register. // //****************************************************************************** #define APPS_CONFIG_TOP_DIE_SPARE_DIN_REG_D2D_SPARE_DIN_M \ 0x00000007 // Capture data from d2d_spare pads #define APPS_CONFIG_TOP_DIE_SPARE_DIN_REG_D2D_SPARE_DIN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_CONFIG_O_TOP_DIE_SPARE_DOUT_REG register. // //****************************************************************************** #define APPS_CONFIG_TOP_DIE_SPARE_DOUT_REG_D2D_SPARE_DOUT_M \ 0x00000007 // Send data to d2d_spare pads - // eventually this will get // registered in top die #define APPS_CONFIG_TOP_DIE_SPARE_DOUT_REG_D2D_SPARE_DOUT_S 0 #endif // __HW_APPS_CONFIG_H__ micropython-1.12/ports/cc3200/hal/inc/hw_apps_rcm.h000066400000000000000000002111421357706137100220540ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_APPS_RCM_H__ #define __HW_APPS_RCM_H__ //***************************************************************************** // // The following are defines for the APPS_RCM register offsets. // //***************************************************************************** #define APPS_RCM_O_CAMERA_CLK_GEN \ 0x00000000 #define APPS_RCM_O_CAMERA_CLK_GATING \ 0x00000004 #define APPS_RCM_O_CAMERA_SOFT_RESET \ 0x00000008 #define APPS_RCM_O_MCASP_CLK_GATING \ 0x00000014 #define APPS_RCM_O_MCASP_SOFT_RESET \ 0x00000018 #define APPS_RCM_O_MMCHS_CLK_GEN \ 0x00000020 #define APPS_RCM_O_MMCHS_CLK_GATING \ 0x00000024 #define APPS_RCM_O_MMCHS_SOFT_RESET \ 0x00000028 #define APPS_RCM_O_MCSPI_A1_CLK_GEN \ 0x0000002C #define APPS_RCM_O_MCSPI_A1_CLK_GATING \ 0x00000030 #define APPS_RCM_O_MCSPI_A1_SOFT_RESET \ 0x00000034 #define APPS_RCM_O_MCSPI_A2_CLK_GEN \ 0x00000038 #define APPS_RCM_O_MCSPI_A2_CLK_GATING \ 0x00000040 #define APPS_RCM_O_MCSPI_A2_SOFT_RESET \ 0x00000044 #define APPS_RCM_O_UDMA_A_CLK_GATING \ 0x00000048 #define APPS_RCM_O_UDMA_A_SOFT_RESET \ 0x0000004C #define APPS_RCM_O_GPIO_A_CLK_GATING \ 0x00000050 #define APPS_RCM_O_GPIO_A_SOFT_RESET \ 0x00000054 #define APPS_RCM_O_GPIO_B_CLK_GATING \ 0x00000058 #define APPS_RCM_O_GPIO_B_SOFT_RESET \ 0x0000005C #define APPS_RCM_O_GPIO_C_CLK_GATING \ 0x00000060 #define APPS_RCM_O_GPIO_C_SOFT_RESET \ 0x00000064 #define APPS_RCM_O_GPIO_D_CLK_GATING \ 0x00000068 #define APPS_RCM_O_GPIO_D_SOFT_RESET \ 0x0000006C #define APPS_RCM_O_GPIO_E_CLK_GATING \ 0x00000070 #define APPS_RCM_O_GPIO_E_SOFT_RESET \ 0x00000074 #define APPS_RCM_O_WDOG_A_CLK_GATING \ 0x00000078 #define APPS_RCM_O_WDOG_A_SOFT_RESET \ 0x0000007C #define APPS_RCM_O_UART_A0_CLK_GATING \ 0x00000080 #define APPS_RCM_O_UART_A0_SOFT_RESET \ 0x00000084 #define APPS_RCM_O_UART_A1_CLK_GATING \ 0x00000088 #define APPS_RCM_O_UART_A1_SOFT_RESET \ 0x0000008C #define APPS_RCM_O_GPT_A0_CLK_GATING \ 0x00000090 #define APPS_RCM_O_GPT_A0_SOFT_RESET \ 0x00000094 #define APPS_RCM_O_GPT_A1_CLK_GATING \ 0x00000098 #define APPS_RCM_O_GPT_A1_SOFT_RESET \ 0x0000009C #define APPS_RCM_O_GPT_A2_CLK_GATING \ 0x000000A0 #define APPS_RCM_O_GPT_A2_SOFT_RESET \ 0x000000A4 #define APPS_RCM_O_GPT_A3_CLK_GATING \ 0x000000A8 #define APPS_RCM_O_GPT_A3_SOFT_RESET \ 0x000000AC #define APPS_RCM_O_MCASP_FRAC_CLK_CONFIG0 \ 0x000000B0 #define APPS_RCM_O_MCASP_FRAC_CLK_CONFIG1 \ 0x000000B4 #define APPS_RCM_O_CRYPTO_CLK_GATING \ 0x000000B8 #define APPS_RCM_O_CRYPTO_SOFT_RESET \ 0x000000BC #define APPS_RCM_O_MCSPI_S0_CLK_GATING \ 0x000000C8 #define APPS_RCM_O_MCSPI_S0_SOFT_RESET \ 0x000000CC #define APPS_RCM_O_MCSPI_S0_CLKDIV_CFG \ 0x000000D0 #define APPS_RCM_O_I2C_CLK_GATING \ 0x000000D8 #define APPS_RCM_O_I2C_SOFT_RESET \ 0x000000DC #define APPS_RCM_O_APPS_LPDS_REQ \ 0x000000E4 #define APPS_RCM_O_APPS_TURBO_REQ \ 0x000000EC #define APPS_RCM_O_APPS_DSLP_WAKE_CONFIG \ 0x00000108 #define APPS_RCM_O_APPS_DSLP_WAKE_TIMER_CFG \ 0x0000010C #define APPS_RCM_O_APPS_RCM_SLP_WAKE_ENABLE \ 0x00000110 #define APPS_RCM_O_APPS_SLP_WAKETIMER_CFG \ 0x00000114 #define APPS_RCM_O_APPS_TO_NWP_WAKE_REQUEST \ 0x00000118 #define APPS_RCM_O_APPS_RCM_INTERRUPT_STATUS \ 0x00000120 #define APPS_RCM_O_APPS_RCM_INTERRUPT_ENABLE \ 0x00000124 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_CAMERA_CLK_GEN register. // //****************************************************************************** #define APPS_RCM_CAMERA_CLK_GEN_CAMERA_PLLCKDIV_OFF_TIME_M \ 0x00000700 // Configuration of OFF-TIME for // dividing PLL clk (240 MHz) in // generation of Camera func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_CAMERA_CLK_GEN_CAMERA_PLLCKDIV_OFF_TIME_S 8 #define APPS_RCM_CAMERA_CLK_GEN_NU1_M \ 0x000000F8 #define APPS_RCM_CAMERA_CLK_GEN_NU1_S 3 #define APPS_RCM_CAMERA_CLK_GEN_CAMERA_PLLCKDIV_ON_TIME_M \ 0x00000007 // Configuration of ON-TIME for // dividing PLL clk (240 MHz) in // generation of Camera func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_CAMERA_CLK_GEN_CAMERA_PLLCKDIV_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_CAMERA_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_CAMERA_CLK_GATING_NU1_M \ 0x00FE0000 #define APPS_RCM_CAMERA_CLK_GATING_NU1_S 17 #define APPS_RCM_CAMERA_CLK_GATING_CAMERA_DSLP_CLK_ENABLE \ 0x00010000 // 0 - Disable camera clk during // deep-sleep mode #define APPS_RCM_CAMERA_CLK_GATING_NU2_M \ 0x0000FE00 #define APPS_RCM_CAMERA_CLK_GATING_NU2_S 9 #define APPS_RCM_CAMERA_CLK_GATING_CAMERA_SLP_CLK_ENABLE \ 0x00000100 // 1- Enable camera clk during // sleep mode ; 0- Disable camera // clk during sleep mode #define APPS_RCM_CAMERA_CLK_GATING_NU3_M \ 0x000000FE #define APPS_RCM_CAMERA_CLK_GATING_NU3_S 1 #define APPS_RCM_CAMERA_CLK_GATING_CAMERA_RUN_CLK_ENABLE \ 0x00000001 // 1- Enable camera clk during run // mode ; 0- Disable camera clk // during run mode //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_CAMERA_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_CAMERA_SOFT_RESET_CAMERA_ENABLED_STATUS \ 0x00000002 // 1 - Camera clocks/resets are // enabled ; 0 - Camera // clocks/resets are disabled #define APPS_RCM_CAMERA_SOFT_RESET_CAMERA_SOFT_RESET \ 0x00000001 // 1 - Assert reset for Camera-core // ; 0 - De-assert reset for // Camera-core //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCASP_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_MCASP_CLK_GATING_NU1_M \ 0x00FE0000 #define APPS_RCM_MCASP_CLK_GATING_NU1_S 17 #define APPS_RCM_MCASP_CLK_GATING_MCASP_DSLP_CLK_ENABLE \ 0x00010000 // 0 - Disable MCASP clk during // deep-sleep mode #define APPS_RCM_MCASP_CLK_GATING_NU2_M \ 0x0000FE00 #define APPS_RCM_MCASP_CLK_GATING_NU2_S 9 #define APPS_RCM_MCASP_CLK_GATING_MCASP_SLP_CLK_ENABLE \ 0x00000100 // 1- Enable MCASP clk during sleep // mode ; 0- Disable MCASP clk // during sleep mode #define APPS_RCM_MCASP_CLK_GATING_NU3_M \ 0x000000FE #define APPS_RCM_MCASP_CLK_GATING_NU3_S 1 #define APPS_RCM_MCASP_CLK_GATING_MCASP_RUN_CLK_ENABLE \ 0x00000001 // 1- Enable MCASP clk during run // mode ; 0- Disable MCASP clk // during run mode //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCASP_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_MCASP_SOFT_RESET_MCASP_ENABLED_STATUS \ 0x00000002 // 1 - MCASP Clocks/resets are // enabled ; 0 - MCASP Clocks/resets // are disabled #define APPS_RCM_MCASP_SOFT_RESET_MCASP_SOFT_RESET \ 0x00000001 // 1 - Assert reset for MCASP-core // ; 0 - De-assert reset for // MCASP-core //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MMCHS_CLK_GEN register. // //****************************************************************************** #define APPS_RCM_MMCHS_CLK_GEN_MMCHS_PLLCKDIV_OFF_TIME_M \ 0x00000700 // Configuration of OFF-TIME for // dividing PLL clk (240 MHz) in // generation of MMCHS func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_MMCHS_CLK_GEN_MMCHS_PLLCKDIV_OFF_TIME_S 8 #define APPS_RCM_MMCHS_CLK_GEN_NU1_M \ 0x000000F8 #define APPS_RCM_MMCHS_CLK_GEN_NU1_S 3 #define APPS_RCM_MMCHS_CLK_GEN_MMCHS_PLLCKDIV_ON_TIME_M \ 0x00000007 // Configuration of ON-TIME for // dividing PLL clk (240 MHz) in // generation of MMCHS func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_MMCHS_CLK_GEN_MMCHS_PLLCKDIV_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MMCHS_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_MMCHS_CLK_GATING_NU1_M \ 0x00FE0000 #define APPS_RCM_MMCHS_CLK_GATING_NU1_S 17 #define APPS_RCM_MMCHS_CLK_GATING_MMCHS_DSLP_CLK_ENABLE \ 0x00010000 // 0 - Disable MMCHS clk during // deep-sleep mode #define APPS_RCM_MMCHS_CLK_GATING_NU2_M \ 0x0000FE00 #define APPS_RCM_MMCHS_CLK_GATING_NU2_S 9 #define APPS_RCM_MMCHS_CLK_GATING_MMCHS_SLP_CLK_ENABLE \ 0x00000100 // 1- Enable MMCHS clk during sleep // mode ; 0- Disable MMCHS clk // during sleep mode #define APPS_RCM_MMCHS_CLK_GATING_NU3_M \ 0x000000FE #define APPS_RCM_MMCHS_CLK_GATING_NU3_S 1 #define APPS_RCM_MMCHS_CLK_GATING_MMCHS_RUN_CLK_ENABLE \ 0x00000001 // 1- Enable MMCHS clk during run // mode ; 0- Disable MMCHS clk // during run mode //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MMCHS_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_MMCHS_SOFT_RESET_MMCHS_ENABLED_STATUS \ 0x00000002 // 1 - MMCHS Clocks/resets are // enabled ; 0 - MMCHS Clocks/resets // are disabled #define APPS_RCM_MMCHS_SOFT_RESET_MMCHS_SOFT_RESET \ 0x00000001 // 1 - Assert reset for MMCHS-core // ; 0 - De-assert reset for // MMCHS-core //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_A1_CLK_GEN register. // //****************************************************************************** #define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_BAUD_CLK_SEL \ 0x00010000 // 0 - XTAL clk is used as baud clk // for MCSPI_A1 ; 1 - PLL divclk is // used as baud clk for MCSPI_A1. #define APPS_RCM_MCSPI_A1_CLK_GEN_NU1_M \ 0x0000F800 #define APPS_RCM_MCSPI_A1_CLK_GEN_NU1_S 11 #define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_PLLCLKDIV_OFF_TIME_M \ 0x00000700 // Configuration of OFF-TIME for // dividing PLL clk (240 MHz) in // generation of MCSPI_A1 func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_PLLCLKDIV_OFF_TIME_S 8 #define APPS_RCM_MCSPI_A1_CLK_GEN_NU2_M \ 0x000000F8 #define APPS_RCM_MCSPI_A1_CLK_GEN_NU2_S 3 #define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_PLLCLKDIV_ON_TIME_M \ 0x00000007 // Configuration of ON-TIME for // dividing PLL clk (240 MHz) in // generation of MCSPI_A1 func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_PLLCLKDIV_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_A1_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_MCSPI_A1_CLK_GATING_NU1_M \ 0x00FE0000 #define APPS_RCM_MCSPI_A1_CLK_GATING_NU1_S 17 #define APPS_RCM_MCSPI_A1_CLK_GATING_MCSPI_A1_DSLP_CLK_ENABLE \ 0x00010000 // 0 - Disable MCSPI_A1 clk during // deep-sleep mode #define APPS_RCM_MCSPI_A1_CLK_GATING_NU2_M \ 0x0000FE00 #define APPS_RCM_MCSPI_A1_CLK_GATING_NU2_S 9 #define APPS_RCM_MCSPI_A1_CLK_GATING_MCSPI_A1_SLP_CLK_ENABLE \ 0x00000100 // 1- Enable MCSPI_A1 clk during // sleep mode ; 0- Disable MCSPI_A1 // clk during sleep mode #define APPS_RCM_MCSPI_A1_CLK_GATING_NU3_M \ 0x000000FE #define APPS_RCM_MCSPI_A1_CLK_GATING_NU3_S 1 #define APPS_RCM_MCSPI_A1_CLK_GATING_MCSPI_A1_RUN_CLK_ENABLE \ 0x00000001 // 1- Enable MCSPI_A1 clk during // run mode ; 0- Disable MCSPI_A1 // clk during run mode //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_A1_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_MCSPI_A1_SOFT_RESET_MCSPI_A1_ENABLED_STATUS \ 0x00000002 // 1 - MCSPI_A1 Clocks/Resets are // enabled ; 0 - MCSPI_A1 // Clocks/Resets are disabled #define APPS_RCM_MCSPI_A1_SOFT_RESET_MCSPI_A1_SOFT_RESET \ 0x00000001 // 1 - Assert reset for // MCSPI_A1-core ; 0 - De-assert // reset for MCSPI_A1-core //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_A2_CLK_GEN register. // //****************************************************************************** #define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_BAUD_CLK_SEL \ 0x00010000 // 0 - XTAL clk is used as baud-clk // for MCSPI_A2 ; 1 - PLL divclk is // used as baud-clk for MCSPI_A2 #define APPS_RCM_MCSPI_A2_CLK_GEN_NU1_M \ 0x0000F800 #define APPS_RCM_MCSPI_A2_CLK_GEN_NU1_S 11 #define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_PLLCKDIV_OFF_TIME_M \ 0x00000700 // Configuration of OFF-TIME for // dividing PLL clk (240 MHz) in // generation of MCSPI_A2 func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_PLLCKDIV_OFF_TIME_S 8 #define APPS_RCM_MCSPI_A2_CLK_GEN_NU2_M \ 0x000000F8 #define APPS_RCM_MCSPI_A2_CLK_GEN_NU2_S 3 #define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_PLLCKDIV_ON_TIME_M \ 0x00000007 // Configuration of OFF-TIME for // dividing PLL clk (240 MHz) in // generation of MCSPI_A2 func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_PLLCKDIV_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_A2_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_MCSPI_A2_CLK_GATING_NU1_M \ 0x00FE0000 #define APPS_RCM_MCSPI_A2_CLK_GATING_NU1_S 17 #define APPS_RCM_MCSPI_A2_CLK_GATING_MCSPI_A2_DSLP_CLK_ENABLE \ 0x00010000 // 0 - Disable MCSPI_A2 clk during // deep-sleep mode #define APPS_RCM_MCSPI_A2_CLK_GATING_NU2_M \ 0x0000FE00 #define APPS_RCM_MCSPI_A2_CLK_GATING_NU2_S 9 #define APPS_RCM_MCSPI_A2_CLK_GATING_MCSPI_A2_SLP_CLK_ENABLE \ 0x00000100 // 1- Enable MCSPI_A2 clk during // sleep mode ; 0- Disable MCSPI_A2 // clk during sleep mode #define APPS_RCM_MCSPI_A2_CLK_GATING_NU3_M \ 0x000000FE #define APPS_RCM_MCSPI_A2_CLK_GATING_NU3_S 1 #define APPS_RCM_MCSPI_A2_CLK_GATING_MCSPI_A2_RUN_CLK_ENABLE \ 0x00000001 // 1- Enable MCSPI_A2 clk during // run mode ; 0- Disable MCSPI_A2 // clk during run mode //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_A2_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_MCSPI_A2_SOFT_RESET_MCSPI_A2_ENABLED_STATUS \ 0x00000002 // 1 - MCSPI_A2 Clocks/Resets are // enabled ; 0 - MCSPI_A2 // Clocks/Resets are disabled #define APPS_RCM_MCSPI_A2_SOFT_RESET_MCSPI_A2_SOFT_RESET \ 0x00000001 // 1 - Assert reset for // MCSPI_A2-core ; 0 - De-assert // reset for MCSPI_A2-core //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_UDMA_A_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_UDMA_A_CLK_GATING_UDMA_A_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable UDMA_A clk during // deep-sleep mode 0 - Disable // UDMA_A clk during deep-sleep mode // ; #define APPS_RCM_UDMA_A_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_UDMA_A_CLK_GATING_NU1_S 9 #define APPS_RCM_UDMA_A_CLK_GATING_UDMA_A_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable UDMA_A clk during // sleep mode 0 - Disable UDMA_A clk // during sleep mode ; #define APPS_RCM_UDMA_A_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_UDMA_A_CLK_GATING_NU2_S 1 #define APPS_RCM_UDMA_A_CLK_GATING_UDMA_A_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable UDMA_A clk during run // mode 0 - Disable UDMA_A clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_UDMA_A_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_UDMA_A_SOFT_RESET_UDMA_A_ENABLED_STATUS \ 0x00000002 // 1 - UDMA_A Clocks/Resets are // enabled ; 0 - UDMA_A // Clocks/Resets are disabled #define APPS_RCM_UDMA_A_SOFT_RESET_UDMA_A_SOFT_RESET \ 0x00000001 // 1 - Assert reset for DMA_A ; 0 - // De-assert reset for DMA_A //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_A_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPIO_A_CLK_GATING_GPIO_A_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable GPIO_A clk during // deep-sleep mode 0 - Disable // GPIO_A clk during deep-sleep mode // ; #define APPS_RCM_GPIO_A_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPIO_A_CLK_GATING_NU1_S 9 #define APPS_RCM_GPIO_A_CLK_GATING_GPIO_A_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable GPIO_A clk during // sleep mode 0 - Disable GPIO_A clk // during sleep mode ; #define APPS_RCM_GPIO_A_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPIO_A_CLK_GATING_NU2_S 1 #define APPS_RCM_GPIO_A_CLK_GATING_GPIO_A_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable GPIO_A clk during run // mode 0 - Disable GPIO_A clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_A_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPIO_A_SOFT_RESET_GPIO_A_ENABLED_STATUS \ 0x00000002 // 1 - GPIO_A Clocks/Resets are // enabled ; 0 - GPIO_A // Clocks/Resets are disabled #define APPS_RCM_GPIO_A_SOFT_RESET_GPIO_A_SOFT_RESET \ 0x00000001 // 1 - Assert reset for GPIO_A ; 0 // - De-assert reset for GPIO_A //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_B_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPIO_B_CLK_GATING_GPIO_B_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable GPIO_B clk during // deep-sleep mode 0 - Disable // GPIO_B clk during deep-sleep mode // ; #define APPS_RCM_GPIO_B_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPIO_B_CLK_GATING_NU1_S 9 #define APPS_RCM_GPIO_B_CLK_GATING_GPIO_B_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable GPIO_B clk during // sleep mode 0 - Disable GPIO_B clk // during sleep mode ; #define APPS_RCM_GPIO_B_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPIO_B_CLK_GATING_NU2_S 1 #define APPS_RCM_GPIO_B_CLK_GATING_GPIO_B_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable GPIO_B clk during run // mode 0 - Disable GPIO_B clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_B_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPIO_B_SOFT_RESET_GPIO_B_ENABLED_STATUS \ 0x00000002 // 1 - GPIO_B Clocks/Resets are // enabled ; 0 - GPIO_B // Clocks/Resets are disabled #define APPS_RCM_GPIO_B_SOFT_RESET_GPIO_B_SOFT_RESET \ 0x00000001 // 1 - Assert reset for GPIO_B ; 0 // - De-assert reset for GPIO_B //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_C_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPIO_C_CLK_GATING_GPIO_C_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable GPIO_C clk during // deep-sleep mode 0 - Disable // GPIO_C clk during deep-sleep mode // ; #define APPS_RCM_GPIO_C_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPIO_C_CLK_GATING_NU1_S 9 #define APPS_RCM_GPIO_C_CLK_GATING_GPIO_C_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable GPIO_C clk during // sleep mode 0 - Disable GPIO_C clk // during sleep mode ; #define APPS_RCM_GPIO_C_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPIO_C_CLK_GATING_NU2_S 1 #define APPS_RCM_GPIO_C_CLK_GATING_GPIO_C_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable GPIO_C clk during run // mode 0 - Disable GPIO_C clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_C_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPIO_C_SOFT_RESET_GPIO_C_ENABLED_STATUS \ 0x00000002 // 1 - GPIO_C Clocks/Resets are // enabled ; 0 - GPIO_C // Clocks/Resets are disabled #define APPS_RCM_GPIO_C_SOFT_RESET_GPIO_C_SOFT_RESET \ 0x00000001 // 1 - Assert reset for GPIO_C ; 0 // - De-assert reset for GPIO_C //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_D_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPIO_D_CLK_GATING_GPIO_D_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable GPIO_D clk during // deep-sleep mode 0 - Disable // GPIO_D clk during deep-sleep mode // ; #define APPS_RCM_GPIO_D_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPIO_D_CLK_GATING_NU1_S 9 #define APPS_RCM_GPIO_D_CLK_GATING_GPIO_D_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable GPIO_D clk during // sleep mode 0 - Disable GPIO_D clk // during sleep mode ; #define APPS_RCM_GPIO_D_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPIO_D_CLK_GATING_NU2_S 1 #define APPS_RCM_GPIO_D_CLK_GATING_GPIO_D_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable GPIO_D clk during run // mode 0 - Disable GPIO_D clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_D_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPIO_D_SOFT_RESET_GPIO_D_ENABLED_STATUS \ 0x00000002 // 1 - GPIO_D Clocks/Resets are // enabled ; 0 - GPIO_D // Clocks/Resets are disabled #define APPS_RCM_GPIO_D_SOFT_RESET_GPIO_D_SOFT_RESET \ 0x00000001 // 1 - Assert reset for GPIO_D ; 0 // - De-assert reset for GPIO_D //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_E_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPIO_E_CLK_GATING_GPIO_E_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable GPIO_E clk during // deep-sleep mode 0 - Disable // GPIO_E clk during deep-sleep mode // ; #define APPS_RCM_GPIO_E_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPIO_E_CLK_GATING_NU1_S 9 #define APPS_RCM_GPIO_E_CLK_GATING_GPIO_E_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable GPIO_E clk during // sleep mode 0 - Disable GPIO_E clk // during sleep mode ; #define APPS_RCM_GPIO_E_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPIO_E_CLK_GATING_NU2_S 1 #define APPS_RCM_GPIO_E_CLK_GATING_GPIO_E_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable GPIO_E clk during run // mode 0 - Disable GPIO_E clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPIO_E_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPIO_E_SOFT_RESET_GPIO_E_ENABLED_STATUS \ 0x00000002 // 1 - GPIO_E Clocks/Resets are // enabled ; 0 - GPIO_E // Clocks/Resets are disabled #define APPS_RCM_GPIO_E_SOFT_RESET_GPIO_E_SOFT_RESET \ 0x00000001 // 1 - Assert reset for GPIO_E ; 0 // - De-assert reset for GPIO_E //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_WDOG_A_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_BAUD_CLK_SEL_M \ 0x03000000 // "00" - Sysclk ; "01" - REF_CLK // (38.4 MHz) ; "10/11" - Slow_clk #define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_BAUD_CLK_SEL_S 24 #define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable WDOG_A clk during // deep-sleep mode 0 - Disable // WDOG_A clk during deep-sleep mode // ; #define APPS_RCM_WDOG_A_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_WDOG_A_CLK_GATING_NU1_S 9 #define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable WDOG_A clk during // sleep mode 0 - Disable WDOG_A clk // during sleep mode ; #define APPS_RCM_WDOG_A_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_WDOG_A_CLK_GATING_NU2_S 1 #define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable WDOG_A clk during run // mode 0 - Disable WDOG_A clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_WDOG_A_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_WDOG_A_SOFT_RESET_WDOG_A_ENABLED_STATUS \ 0x00000002 // 1 - WDOG_A Clocks/Resets are // enabled ; 0 - WDOG_A // Clocks/Resets are disabled #define APPS_RCM_WDOG_A_SOFT_RESET_WDOG_A_SOFT_RESET \ 0x00000001 // 1 - Assert reset for WDOG_A ; 0 // - De-assert reset for WDOG_A //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_UART_A0_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_UART_A0_CLK_GATING_UART_A0_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable UART_A0 clk during // deep-sleep mode 0 - Disable // UART_A0 clk during deep-sleep // mode ; #define APPS_RCM_UART_A0_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_UART_A0_CLK_GATING_NU1_S 9 #define APPS_RCM_UART_A0_CLK_GATING_UART_A0_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable UART_A0 clk during // sleep mode 0 - Disable UART_A0 // clk during sleep mode ; #define APPS_RCM_UART_A0_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_UART_A0_CLK_GATING_NU2_S 1 #define APPS_RCM_UART_A0_CLK_GATING_UART_A0_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable UART_A0 clk during // run mode 0 - Disable UART_A0 clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_UART_A0_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_UART_A0_SOFT_RESET_UART_A0_ENABLED_STATUS \ 0x00000002 // 1 - UART_A0 Clocks/Resets are // enabled ; 0 - UART_A0 // Clocks/Resets are disabled #define APPS_RCM_UART_A0_SOFT_RESET_UART_A0_SOFT_RESET \ 0x00000001 // 1 - Assert reset for UART_A0 ; 0 // - De-assert reset for UART_A0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_UART_A1_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_UART_A1_CLK_GATING_UART_A1_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable UART_A1 clk during // deep-sleep mode 0 - Disable // UART_A1 clk during deep-sleep // mode ; #define APPS_RCM_UART_A1_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_UART_A1_CLK_GATING_NU1_S 9 #define APPS_RCM_UART_A1_CLK_GATING_UART_A1_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable UART_A1 clk during // sleep mode 0 - Disable UART_A1 // clk during sleep mode ; #define APPS_RCM_UART_A1_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_UART_A1_CLK_GATING_NU2_S 1 #define APPS_RCM_UART_A1_CLK_GATING_UART_A1_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable UART_A1 clk during // run mode 0 - Disable UART_A1 clk // during run mode ; //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_UART_A1_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_UART_A1_SOFT_RESET_UART_A1_ENABLED_STATUS \ 0x00000002 // 1 - UART_A1 Clocks/Resets are // enabled ; 0 - UART_A1 // Clocks/Resets are disabled #define APPS_RCM_UART_A1_SOFT_RESET_UART_A1_SOFT_RESET \ 0x00000001 // 1 - Assert the soft reset for // UART_A1 ; 0 - De-assert the soft // reset for UART_A1 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPT_A0_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPT_A0_CLK_GATING_GPT_A0_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable the GPT_A0 clock // during deep-sleep ; 0 - Disable // the GPT_A0 clock during // deep-sleep #define APPS_RCM_GPT_A0_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPT_A0_CLK_GATING_NU1_S 9 #define APPS_RCM_GPT_A0_CLK_GATING_GPT_A0_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable the GPT_A0 clock // during sleep ; 0 - Disable the // GPT_A0 clock during sleep #define APPS_RCM_GPT_A0_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPT_A0_CLK_GATING_NU2_S 1 #define APPS_RCM_GPT_A0_CLK_GATING_GPT_A0_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable the GPT_A0 clock // during run ; 0 - Disable the // GPT_A0 clock during run //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPT_A0_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPT_A0_SOFT_RESET_GPT_A0_ENABLED_STATUS \ 0x00000002 // 1 - GPT_A0 clocks/resets are // enabled ; 0 - GPT_A0 // clocks/resets are disabled #define APPS_RCM_GPT_A0_SOFT_RESET_GPT_A0_SOFT_RESET \ 0x00000001 // 1 - Assert the soft reset for // GPT_A0 ; 0 - De-assert the soft // reset for GPT_A0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPT_A1_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPT_A1_CLK_GATING_GPT_A1_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable the GPT_A1 clock // during deep-sleep ; 0 - Disable // the GPT_A1 clock during // deep-sleep #define APPS_RCM_GPT_A1_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPT_A1_CLK_GATING_NU1_S 9 #define APPS_RCM_GPT_A1_CLK_GATING_GPT_A1_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable the GPT_A1 clock // during sleep ; 0 - Disable the // GPT_A1 clock during sleep #define APPS_RCM_GPT_A1_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPT_A1_CLK_GATING_NU2_S 1 #define APPS_RCM_GPT_A1_CLK_GATING_GPT_A1_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable the GPT_A1 clock // during run ; 0 - Disable the // GPT_A1 clock during run //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPT_A1_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPT_A1_SOFT_RESET_GPT_A1_ENABLED_STATUS \ 0x00000002 // 1 - GPT_A1 clocks/resets are // enabled ; 0 - GPT_A1 // clocks/resets are disabled #define APPS_RCM_GPT_A1_SOFT_RESET_GPT_A1_SOFT_RESET \ 0x00000001 // 1 - Assert the soft reset for // GPT_A1 ; 0 - De-assert the soft // reset for GPT_A1 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPT_A2_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPT_A2_CLK_GATING_GPT_A2_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable the GPT_A2 clock // during deep-sleep ; 0 - Disable // the GPT_A2 clock during // deep-sleep #define APPS_RCM_GPT_A2_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPT_A2_CLK_GATING_NU1_S 9 #define APPS_RCM_GPT_A2_CLK_GATING_GPT_A2_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable the GPT_A2 clock // during sleep ; 0 - Disable the // GPT_A2 clock during sleep #define APPS_RCM_GPT_A2_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPT_A2_CLK_GATING_NU2_S 1 #define APPS_RCM_GPT_A2_CLK_GATING_GPT_A2_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable the GPT_A2 clock // during run ; 0 - Disable the // GPT_A2 clock during run //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPT_A2_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPT_A2_SOFT_RESET_GPT_A2_ENABLED_STATUS \ 0x00000002 // 1 - GPT_A2 clocks/resets are // enabled ; 0 - GPT_A2 // clocks/resets are disabled #define APPS_RCM_GPT_A2_SOFT_RESET_GPT_A2_SOFT_RESET \ 0x00000001 // 1 - Assert the soft reset for // GPT_A2 ; 0 - De-assert the soft // reset for GPT_A2 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPT_A3_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_GPT_A3_CLK_GATING_GPT_A3_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable the GPT_A3 clock // during deep-sleep ; 0 - Disable // the GPT_A3 clock during // deep-sleep #define APPS_RCM_GPT_A3_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_GPT_A3_CLK_GATING_NU1_S 9 #define APPS_RCM_GPT_A3_CLK_GATING_GPT_A3_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable the GPT_A3 clock // during sleep ; 0 - Disable the // GPT_A3 clock during sleep #define APPS_RCM_GPT_A3_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_GPT_A3_CLK_GATING_NU2_S 1 #define APPS_RCM_GPT_A3_CLK_GATING_GPT_A3_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable the GPT_A3 clock // during run ; 0 - Disable the // GPT_A3 clock during run //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_GPT_A3_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_GPT_A3_SOFT_RESET_GPT_A3_ENABLED_STATUS \ 0x00000002 // 1 - GPT_A3 Clocks/resets are // enabled ; 0 - GPT_A3 // Clocks/resets are disabled #define APPS_RCM_GPT_A3_SOFT_RESET_GPT_A3_SOFT_RESET \ 0x00000001 // 1 - Assert the soft reset for // GPT_A3 ; 0 - De-assert the soft // reset for GPT_A3 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCASP_FRAC_CLK_CONFIG0 register. // //****************************************************************************** #define APPS_RCM_MCASP_FRAC_CLK_CONFIG0_MCASP_FRAC_DIV_DIVISOR_M \ 0x03FF0000 #define APPS_RCM_MCASP_FRAC_CLK_CONFIG0_MCASP_FRAC_DIV_DIVISOR_S 16 #define APPS_RCM_MCASP_FRAC_CLK_CONFIG0_MCASP_FRAC_DIV_FRACTION_M \ 0x0000FFFF #define APPS_RCM_MCASP_FRAC_CLK_CONFIG0_MCASP_FRAC_DIV_FRACTION_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCASP_FRAC_CLK_CONFIG1 register. // //****************************************************************************** #define APPS_RCM_MCASP_FRAC_CLK_CONFIG1_MCASP_FRAC_DIV_SOFT_RESET \ 0x00010000 // 1 - Assert the reset for MCASP // Frac-clk div; 0 - Donot assert // the reset for MCASP frac clk-div #define APPS_RCM_MCASP_FRAC_CLK_CONFIG1_MCASP_FRAC_DIV_PERIOD_M \ 0x000003FF #define APPS_RCM_MCASP_FRAC_CLK_CONFIG1_MCASP_FRAC_DIV_PERIOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_CRYPTO_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_CRYPTO_CLK_GATING_CRYPTO_DSLP_CLK_ENABLE \ 0x00010000 // 0 - Disable the Crypto clock // during deep-sleep #define APPS_RCM_CRYPTO_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_CRYPTO_CLK_GATING_NU1_S 9 #define APPS_RCM_CRYPTO_CLK_GATING_CRYPTO_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable the Crypto clock // during sleep ; 0 - Disable the // Crypto clock during sleep #define APPS_RCM_CRYPTO_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_CRYPTO_CLK_GATING_NU2_S 1 #define APPS_RCM_CRYPTO_CLK_GATING_CRYPTO_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable the Crypto clock // during run ; 0 - Disable the // Crypto clock during run //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_CRYPTO_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_CRYPTO_SOFT_RESET_CRYPTO_ENABLED_STATUS \ 0x00000002 // 1 - Crypto clocks/resets are // enabled ; 0 - Crypto // clocks/resets are disabled #define APPS_RCM_CRYPTO_SOFT_RESET_CRYPTO_SOFT_RESET \ 0x00000001 // 1 - Assert the soft reset for // Crypto ; 0 - De-assert the soft // reset for Crypto //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_S0_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_MCSPI_S0_CLK_GATING_MCSPI_S0_DSLP_CLK_ENABLE \ 0x00010000 // 0 - Disable the MCSPI_S0 clock // during deep-sleep #define APPS_RCM_MCSPI_S0_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_MCSPI_S0_CLK_GATING_NU1_S 9 #define APPS_RCM_MCSPI_S0_CLK_GATING_MCSPI_S0_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable the MCSPI_S0 clock // during sleep ; 0 - Disable the // MCSPI_S0 clock during sleep #define APPS_RCM_MCSPI_S0_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_MCSPI_S0_CLK_GATING_NU2_S 1 #define APPS_RCM_MCSPI_S0_CLK_GATING_MCSPI_S0_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable the MCSPI_S0 clock // during run ; 0 - Disable the // MCSPI_S0 clock during run //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_S0_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_MCSPI_S0_SOFT_RESET_MCSPI_S0_ENABLED_STATUS \ 0x00000002 // 1 - MCSPI_S0 Clocks/Resets are // enabled ; 0 - MCSPI_S0 // Clocks/resets are disabled #define APPS_RCM_MCSPI_S0_SOFT_RESET_MCSPI_S0_SOFT_RESET \ 0x00000001 // 1 - Assert the soft reset for // MCSPI_S0 ; 0 - De-assert the soft // reset for MCSPI_S0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_MCSPI_S0_CLKDIV_CFG register. // //****************************************************************************** #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_BAUD_CLK_SEL \ 0x00010000 // 0 - XTAL clk is used as baud-clk // for MCSPI_S0 ; 1 - PLL divclk is // used as buad-clk for MCSPI_S0 #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_NU1_M \ 0x0000F800 #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_NU1_S 11 #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_PLLCLKDIV_OFF_TIME_M \ 0x00000700 // Configuration of OFF-TIME for // dividing PLL clk (240 MHz) in // generation of MCSPI_S0 func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_PLLCLKDIV_OFF_TIME_S 8 #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_NU2_M \ 0x000000F8 #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_NU2_S 3 #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_PLLCLKDIV_ON_TIME_M \ 0x00000007 // Configuration of ON-TIME for // dividing PLL clk (240 MHz) in // generation of MCSPI_S0 func-clk : // "000" - 1 "001" - 2 "010" - 3 // "011" - 4 "100" - 5 "101" - 6 // "110" - 7 "111" - 8 #define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_PLLCLKDIV_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_I2C_CLK_GATING register. // //****************************************************************************** #define APPS_RCM_I2C_CLK_GATING_I2C_DSLP_CLK_ENABLE \ 0x00010000 // 1 - Enable the I2C Clock during // deep-sleep 0 - Disable the I2C // clock during deep-sleep #define APPS_RCM_I2C_CLK_GATING_NU1_M \ 0x0000FE00 #define APPS_RCM_I2C_CLK_GATING_NU1_S 9 #define APPS_RCM_I2C_CLK_GATING_I2C_SLP_CLK_ENABLE \ 0x00000100 // 1 - Enable the I2C clock during // sleep ; 0 - Disable the I2C clock // during sleep #define APPS_RCM_I2C_CLK_GATING_NU2_M \ 0x000000FE #define APPS_RCM_I2C_CLK_GATING_NU2_S 1 #define APPS_RCM_I2C_CLK_GATING_I2C_RUN_CLK_ENABLE \ 0x00000001 // 1 - Enable the I2C clock during // run ; 0 - Disable the I2C clock // during run //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_I2C_SOFT_RESET register. // //****************************************************************************** #define APPS_RCM_I2C_SOFT_RESET_I2C_ENABLED_STATUS \ 0x00000002 // 1 - I2C Clocks/Resets are // enabled ; 0 - I2C clocks/resets // are disabled #define APPS_RCM_I2C_SOFT_RESET_I2C_SOFT_RESET \ 0x00000001 // 1 - Assert the soft reset for // Shared-I2C ; 0 - De-assert the // soft reset for Shared-I2C //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_APPS_LPDS_REQ register. // //****************************************************************************** #define APPS_RCM_APPS_LPDS_REQ_APPS_LPDS_REQ \ 0x00000001 // 1 - Request for LPDS //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_APPS_TURBO_REQ register. // //****************************************************************************** #define APPS_RCM_APPS_TURBO_REQ_APPS_TURBO_REQ \ 0x00000001 // 1 - Request for TURBO //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_APPS_DSLP_WAKE_CONFIG register. // //****************************************************************************** #define APPS_RCM_APPS_DSLP_WAKE_CONFIG_DSLP_WAKE_FROM_NWP_ENABLE \ 0x00000002 // 1 - Enable the NWP to wake APPS // from deep-sleep ; 0 - Disable NWP // to wake APPS from deep-sleep #define APPS_RCM_APPS_DSLP_WAKE_CONFIG_DSLP_WAKE_TIMER_ENABLE \ 0x00000001 // 1 - Enable deep-sleep wake timer // in APPS RCM for deep-sleep; 0 - // Disable deep-sleep wake timer in // APPS RCM //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_APPS_DSLP_WAKE_TIMER_CFG register. // //****************************************************************************** #define APPS_RCM_APPS_DSLP_WAKE_TIMER_CFG_DSLP_WAKE_TIMER_OPP_CFG_M \ 0xFFFF0000 // Configuration (in slow_clks) // which says when to request for // OPP during deep-sleep exit #define APPS_RCM_APPS_DSLP_WAKE_TIMER_CFG_DSLP_WAKE_TIMER_OPP_CFG_S 16 #define APPS_RCM_APPS_DSLP_WAKE_TIMER_CFG_DSLP_WAKE_TIMER_WAKE_CFG_M \ 0x0000FFFF // Configuration (in slow_clks) // which says when to request for // WAKE during deep-sleep exit #define APPS_RCM_APPS_DSLP_WAKE_TIMER_CFG_DSLP_WAKE_TIMER_WAKE_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_APPS_RCM_SLP_WAKE_ENABLE register. // //****************************************************************************** #define APPS_RCM_APPS_RCM_SLP_WAKE_ENABLE_SLP_WAKE_FROM_NWP_ENABLE \ 0x00000002 // 1- Enable the sleep wakeup due // to NWP request. 0- Disable the // sleep wakeup due to NWP request #define APPS_RCM_APPS_RCM_SLP_WAKE_ENABLE_SLP_WAKE_TIMER_ENABLE \ 0x00000001 // 1- Enable the sleep wakeup due // to sleep-timer; 0-Disable the // sleep wakeup due to sleep-timer //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_APPS_SLP_WAKETIMER_CFG register. // //****************************************************************************** #define APPS_RCM_APPS_SLP_WAKETIMER_CFG_SLP_WAKE_TIMER_CFG_M \ 0xFFFFFFFF // Configuration (number of // sysclks-80MHz) for the Sleep // wakeup timer #define APPS_RCM_APPS_SLP_WAKETIMER_CFG_SLP_WAKE_TIMER_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_APPS_TO_NWP_WAKE_REQUEST register. // //****************************************************************************** #define APPS_RCM_APPS_TO_NWP_WAKE_REQUEST_APPS_TO_NWP_WAKEUP_REQUEST \ 0x00000001 // When 1 => APPS generated a wake // request to NWP (When NWP is in // any of its low-power modes : // SLP/DSLP/LPDS) //****************************************************************************** // // The following are defines for the bit fields in the // APPS_RCM_O_APPS_RCM_INTERRUPT_STATUS register. // //****************************************************************************** #define APPS_RCM_APPS_RCM_INTERRUPT_STATUS_apps_deep_sleep_timer_wake \ 0x00000008 // 1 - Indicates that deep-sleep // timer expiry had caused the // wakeup from deep-sleep #define APPS_RCM_APPS_RCM_INTERRUPT_STATUS_apps_sleep_timer_wake \ 0x00000004 // 1 - Indicates that sleep timer // expiry had caused the wakeup from // sleep #define APPS_RCM_APPS_RCM_INTERRUPT_STATUS_apps_deep_sleep_wake_from_nwp \ 0x00000002 // 1 - Indicates that NWP had // caused the wakeup from deep-sleep #define APPS_RCM_APPS_RCM_INTERRUPT_STATUS_apps_sleep_wake_from_nwp \ 0x00000001 // 1 - Indicates that NWP had // caused the wakeup from Sleep #endif // __HW_APPS_RCM_H__ micropython-1.12/ports/cc3200/hal/inc/hw_camera.h000066400000000000000000000714611357706137100215100ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_CAMERA_H__ #define __HW_CAMERA_H__ //***************************************************************************** // // The following are defines for the CAMERA register offsets. // //***************************************************************************** #define CAMERA_O_CC_REVISION 0x00000000 // This register contains the IP // revision code ( Parallel Mode) #define CAMERA_O_CC_SYSCONFIG 0x00000010 // This register controls the // various parameters of the OCP // interface (CCP and Parallel Mode) #define CAMERA_O_CC_SYSSTATUS 0x00000014 // This register provides status // information about the module // excluding the interrupt status // information (CCP and Parallel // Mode) #define CAMERA_O_CC_IRQSTATUS 0x00000018 // The interrupt status regroups // all the status of the module // internal events that can generate // an interrupt (CCP & Parallel // Mode) #define CAMERA_O_CC_IRQENABLE 0x0000001C // The interrupt enable register // allows to enable/disable the // module internal sources of // interrupt on an event-by-event // basis (CCP & Parallel Mode) #define CAMERA_O_CC_CTRL 0x00000040 // This register controls the // various parameters of the Camera // Core block (CCP & Parallel Mode) #define CAMERA_O_CC_CTRL_DMA 0x00000044 // This register controls the DMA // interface of the Camera Core // block (CCP & Parallel Mode) #define CAMERA_O_CC_CTRL_XCLK 0x00000048 // This register control the value // of the clock divisor used to // generate the external clock // (Parallel Mode) #define CAMERA_O_CC_FIFO_DATA 0x0000004C // This register allows to write to // the FIFO and read from the FIFO // (CCP & Parallel Mode) #define CAMERA_O_CC_TEST 0x00000050 // This register shows the status // of some important variables of // the camera core module (CCP & // Parallel Mode) #define CAMERA_O_CC_GEN_PAR 0x00000054 // This register shows the values // of the generic parameters of the // module //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_REVISION register. // //****************************************************************************** #define CAMERA_CC_REVISION_REV_M \ 0x000000FF // IP revision [7:4] Major revision // [3:0] Minor revision Examples: // 0x10 for 1.0 0x21 for 2.1 #define CAMERA_CC_REVISION_REV_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_SYSCONFIG register. // //****************************************************************************** #define CAMERA_CC_SYSCONFIG_S_IDLE_MODE_M \ 0x00000018 // Slave interface power management // req/ack control """00"" // Force-idle. An idle request is // acknoledged unconditionally" // """01"" No-idle. An idle request // is never acknowledged" """10"" // reserved (Smart-idle not // implemented)" #define CAMERA_CC_SYSCONFIG_S_IDLE_MODE_S 3 #define CAMERA_CC_SYSCONFIG_SOFT_RESET \ 0x00000002 // Software reset. Set this bit to // 1 to trigger a module reset. The // bit is automatically reset by the // hardware. During reset it always // returns 0. 0 Normal mode 1 The // module is reset #define CAMERA_CC_SYSCONFIG_AUTO_IDLE \ 0x00000001 // Internal OCP clock gating // strategy 0 OCP clock is // free-running 1 Automatic OCP // clock gating strategy is applied // based on the OCP interface // activity //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_SYSSTATUS register. // //****************************************************************************** #define CAMERA_CC_SYSSTATUS_RESET_DONE2 \ 0x00000001 // Internal Reset Monitoring 0 // Internal module reset is on-going // 1 Reset completed //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_IRQSTATUS register. // //****************************************************************************** #define CAMERA_CC_IRQSTATUS_FS_IRQ \ 0x00080000 // Frame Start has occurred 0 Event // false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset #define CAMERA_CC_IRQSTATUS_LE_IRQ \ 0x00040000 // Line End has occurred 0 Event // false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset #define CAMERA_CC_IRQSTATUS_LS_IRQ \ 0x00020000 // Line Start has occurred 0 Event // false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset #define CAMERA_CC_IRQSTATUS_FE_IRQ \ 0x00010000 // Frame End has occurred 0 Event // false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset #define CAMERA_CC_IRQSTATUS_FSP_ERR_IRQ \ 0x00000800 // FSP code error 0 Event false "1 // Event is true (""pending"")" 0 // Event status bit unchanged 1 // Event status bit is reset #define CAMERA_CC_IRQSTATUS_FW_ERR_IRQ \ 0x00000400 // Frame Height Error 0 Event false // "1 Event is true (""pending"")" 0 // Event status bit unchanged 1 // Event status bit is reset #define CAMERA_CC_IRQSTATUS_FSC_ERR_IRQ \ 0x00000200 // False Synchronization Code 0 // Event false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset #define CAMERA_CC_IRQSTATUS_SSC_ERR_IRQ \ 0x00000100 // Shifted Synchronization Code 0 // Event false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset #define CAMERA_CC_IRQSTATUS_FIFO_NONEMPTY_IRQ \ 0x00000010 // FIFO is not empty 0 Event false // "1 Event is true (""pending"")" 0 // Event status bit unchanged 1 // Event status bit is reset #define CAMERA_CC_IRQSTATUS_FIFO_FULL_IRQ \ 0x00000008 // FIFO is full 0 Event false "1 // Event is true (""pending"")" 0 // Event status bit unchanged 1 // Event status bit is reset #define CAMERA_CC_IRQSTATUS_FIFO_THR_IRQ \ 0x00000004 // FIFO threshold has been reached // 0 Event false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset #define CAMERA_CC_IRQSTATUS_FIFO_OF_IRQ \ 0x00000002 // FIFO overflow has occurred 0 // Event false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset #define CAMERA_CC_IRQSTATUS_FIFO_UF_IRQ \ 0x00000001 // FIFO underflow has occurred 0 // Event false "1 Event is true // (""pending"")" 0 Event status bit // unchanged 1 Event status bit is // reset //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_IRQENABLE register. // //****************************************************************************** #define CAMERA_CC_IRQENABLE_FS_IRQ_EN \ 0x00080000 // Frame Start Interrupt Enable 0 // Event is masked 1 Event generates // an interrupt when it occurs #define CAMERA_CC_IRQENABLE_LE_IRQ_EN \ 0x00040000 // Line End Interrupt Enable 0 // Event is masked 1 Event generates // an interrupt when it occurs #define CAMERA_CC_IRQENABLE_LS_IRQ_EN \ 0x00020000 // Line Start Interrupt Enable 0 // Event is masked 1 Event generates // an interrupt when it occurs #define CAMERA_CC_IRQENABLE_FE_IRQ_EN \ 0x00010000 // Frame End Interrupt Enable 0 // Event is masked 1 Event generates // an interrupt when it occurs #define CAMERA_CC_IRQENABLE_FSP_IRQ_EN \ 0x00000800 // FSP code Interrupt Enable 0 // Event is masked 1 Event generates // an interrupt when it occurs #define CAMERA_CC_IRQENABLE_FW_ERR_IRQ_EN \ 0x00000400 // Frame Height Error Interrupt // Enable 0 Event is masked 1 Event // generates an interrupt when it // occurs #define CAMERA_CC_IRQENABLE_FSC_ERR_IRQ_EN \ 0x00000200 // False Synchronization Code // Interrupt Enable 0 Event is // masked 1 Event generates an // interrupt when it occurs #define CAMERA_CC_IRQENABLE_SSC_ERR_IRQ_EN \ 0x00000100 // False Synchronization Code // Interrupt Enable 0 Event is // masked 1 Event generates an // interrupt when it occurs #define CAMERA_CC_IRQENABLE_FIFO_NONEMPTY_IRQ_EN \ 0x00000010 // FIFO Threshold Interrupt Enable // 0 Event is masked 1 Event // generates an interrupt when it // occurs #define CAMERA_CC_IRQENABLE_FIFO_FULL_IRQ_EN \ 0x00000008 // FIFO Threshold Interrupt Enable // 0 Event is masked 1 Event // generates an interrupt when it // occurs #define CAMERA_CC_IRQENABLE_FIFO_THR_IRQ_EN \ 0x00000004 // FIFO Threshold Interrupt Enable // 0 Event is masked 1 Event // generates an interrupt when it // occurs #define CAMERA_CC_IRQENABLE_FIFO_OF_IRQ_EN \ 0x00000002 // FIFO Overflow Interrupt Enable 0 // Event is masked 1 Event generates // an interrupt when it occurs #define CAMERA_CC_IRQENABLE_FIFO_UF_IRQ_EN \ 0x00000001 // FIFO Underflow Interrupt Enable // 0 Event is masked 1 Event // generates an interrupt when it // occurs //****************************************************************************** // // The following are defines for the bit fields in the CAMERA_O_CC_CTRL register. // //****************************************************************************** #define CAMERA_CC_CTRL_CC_IF_SYNCHRO \ 0x00080000 // Synchronize all camera sensor // inputs This must be set during // the configuration phase before // CC_EN set to '1'. This can be // used in very high frequency to // avoid dependancy to the IO // timings. 0 No synchro (most of // applications) 1 Synchro enabled // (should never be required) #define CAMERA_CC_CTRL_CC_RST 0x00040000 // Resets all the internal finite // states machines of the camera // core module - by writing a 1 to // this bit. must be applied when // CC_EN = 0 Reads returns 0 #define CAMERA_CC_CTRL_CC_FRAME_TRIG \ 0x00020000 // Set the modality in which CC_EN // works when a disabling of the // sensor camera core is wanted "If // CC_FRAME_TRIG = 1 by writing // ""0"" to CC_EN" the module is // disabled at the end of the frame // "If CC_FRAME_TRIG = 0 by writing // ""0"" to CC_EN" the module is // disabled immediately #define CAMERA_CC_CTRL_CC_EN 0x00010000 // Enables the sensor interface of // the camera core module "By // writing ""1"" to this field the // module is enabled." "By writing // ""0"" to this field the module is // disabled at" the end of the frame // if CC_FRAM_TRIG =1 and is // disabled immediately if // CC_FRAM_TRIG = 0 #define CAMERA_CC_CTRL_NOBT_SYNCHRO \ 0x00002000 // Enables to start at the // beginning of the frame or not in // NoBT 0 Acquisition starts when // Vertical synchro is high 1 // Acquisition starts when Vertical // synchro goes from low to high // (beginning of the frame) - // Recommended. #define CAMERA_CC_CTRL_BT_CORRECT \ 0x00001000 // Enables the correction within // the sync codes in BT mode 0 // correction is not enabled 1 // correction is enabled #define CAMERA_CC_CTRL_PAR_ORDERCAM \ 0x00000800 // Enables swap between image-data // in parallel mode 0 swap is not // enabled 1 swap is enabled #define CAMERA_CC_CTRL_PAR_CLK_POL \ 0x00000400 // Inverts the clock coming from // the sensor in parallel mode 0 // clock not inverted - data sampled // on rising edge 1 clock inverted - // data sampled on falling edge #define CAMERA_CC_CTRL_NOBT_HS_POL \ 0x00000200 // Sets the polarity of the // synchronization signals in NOBT // parallel mode 0 CAM_P_HS is // active high 1 CAM_P_HS is active // low #define CAMERA_CC_CTRL_NOBT_VS_POL \ 0x00000100 // Sets the polarity of the // synchronization signals in NOBT // parallel mode 0 CAM_P_VS is // active high 1 CAM_P_VS is active // low #define CAMERA_CC_CTRL_PAR_MODE_M \ 0x0000000E // Sets the Protocol Mode of the // Camera Core module in parallel // mode (when CCP_MODE = 0) """000"" // Parallel NOBT 8-bit" """001"" // Parallel NOBT 10-bit" """010"" // Parallel NOBT 12-bit" """011"" // reserved" """100"" Parallet BT // 8-bit" """101"" Parallel BT // 10-bit" """110"" reserved" // """111"" FIFO test mode. Refer to // Table 12 - FIFO Write and Read // access" #define CAMERA_CC_CTRL_PAR_MODE_S 1 #define CAMERA_CC_CTRL_CCP_MODE 0x00000001 // Set the Camera Core in CCP mode // 0 CCP mode disabled 1 CCP mode // enabled //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_CTRL_DMA register. // //****************************************************************************** #define CAMERA_CC_CTRL_DMA_DMA_EN \ 0x00000100 // Sets the number of dma request // lines 0 DMA interface disabled // The DMA request line stays // inactive 1 DMA interface enabled // The DMA request line is // operational #define CAMERA_CC_CTRL_DMA_FIFO_THRESHOLD_M \ 0x0000007F // Sets the threshold of the FIFO // the assertion of the dmarequest // line takes place when the // threshold is reached. // """0000000"" threshold set to 1" // """0000001"" threshold set to 2" // … """1111111"" threshold set to // 128" #define CAMERA_CC_CTRL_DMA_FIFO_THRESHOLD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_CTRL_XCLK register. // //****************************************************************************** #define CAMERA_CC_CTRL_XCLK_XCLK_DIV_M \ 0x0000001F // Sets the clock divisor value for // CAM_XCLK generation. based on // CAM_MCK (value of CAM_MCLK is // 96MHz) """00000"" CAM_XCLK Stable // Low Level" Divider not enabled // """00001"" CAM_XCLK Stable High // Level" Divider not enabled from 2 // to 30 CAM_XCLK = CAM_MCLK / // XCLK_DIV """11111"" Bypass - // CAM_XCLK = CAM_MCLK" #define CAMERA_CC_CTRL_XCLK_XCLK_DIV_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_FIFO_DATA register. // //****************************************************************************** #define CAMERA_CC_FIFO_DATA_FIFO_DATA_M \ 0xFFFFFFFF // Writes the 32-bit word into the // FIFO Reads the 32-bit word from // the FIFO #define CAMERA_CC_FIFO_DATA_FIFO_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the CAMERA_O_CC_TEST register. // //****************************************************************************** #define CAMERA_CC_TEST_FIFO_RD_POINTER_M \ 0xFF000000 // FIFO READ Pointer This field // shows the value of the FIFO read // pointer Expected value ranges // from 0 to 127 #define CAMERA_CC_TEST_FIFO_RD_POINTER_S 24 #define CAMERA_CC_TEST_FIFO_WR_POINTER_M \ 0x00FF0000 // FIFO WRITE pointer This field // shows the value of the FIFO write // pointer Expected value ranges // from 0 to 127 #define CAMERA_CC_TEST_FIFO_WR_POINTER_S 16 #define CAMERA_CC_TEST_FIFO_LEVEL_M \ 0x0000FF00 // FIFO level (how many 32-bit // words the FIFO contains) This // field shows the value of the FIFO // level and can assume values from // 0 to 128 #define CAMERA_CC_TEST_FIFO_LEVEL_S 8 #define CAMERA_CC_TEST_FIFO_LEVEL_PEAK_M \ 0x000000FF // FIFO level peak This field shows // the max value of the FIFO level // and can assume values from 0 to // 128 #define CAMERA_CC_TEST_FIFO_LEVEL_PEAK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // CAMERA_O_CC_GEN_PAR register. // //****************************************************************************** #define CAMERA_CC_GEN_PAR_CC_FIFO_DEPTH_M \ 0x00000007 // Camera Core FIFO DEPTH generic // parameter #define CAMERA_CC_GEN_PAR_CC_FIFO_DEPTH_S 0 #endif // __HW_CAMERA_H__ micropython-1.12/ports/cc3200/hal/inc/hw_common_reg.h000066400000000000000000001702061357706137100224020ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_COMMON_REG_H__ #define __HW_COMMON_REG_H__ //***************************************************************************** // // The following are defines for the COMMON_REG register offsets. // //***************************************************************************** #define COMMON_REG_O_I2C_Properties_Register \ 0x00000000 #define COMMON_REG_O_SPI_Properties_Register \ 0x00000004 #define COMMON_REG_O_APPS_sh_resource_Interrupt_enable \ 0x0000000C #define COMMON_REG_O_APPS_sh_resource_Interrupt_status \ 0x00000010 #define COMMON_REG_O_NWP_sh_resource_Interrupt_enable \ 0x00000014 #define COMMON_REG_O_NWP_sh_resource_Interrupt_status \ 0x00000018 #define COMMON_REG_O_Flash_ctrl_reg \ 0x0000001C #define COMMON_REG_O_Bus_matrix_M0_segment_access_config \ 0x00000024 #define COMMON_REG_O_Bus_matrix_M1_segment_access_config \ 0x00000028 #define COMMON_REG_O_Bus_matrix_M2_segment_access_config \ 0x0000002C #define COMMON_REG_O_Bus_matrix_M3_segment_access_config \ 0x00000030 #define COMMON_REG_O_Bus_matrix_M4_segment_access_config \ 0x00000034 #define COMMON_REG_O_Bus_matrix_M5_segment_access_config \ 0x00000038 #define COMMON_REG_O_GPIO_properties_register \ 0x0000003C #define COMMON_REG_O_APPS_NW_SEMAPHORE1 \ 0x00000040 #define COMMON_REG_O_APPS_NW_SEMAPHORE2 \ 0x00000044 #define COMMON_REG_O_APPS_NW_SEMAPHORE3 \ 0x00000048 #define COMMON_REG_O_APPS_NW_SEMAPHORE4 \ 0x0000004C #define COMMON_REG_O_APPS_NW_SEMAPHORE5 \ 0x00000050 #define COMMON_REG_O_APPS_NW_SEMAPHORE6 \ 0x00000054 #define COMMON_REG_O_APPS_NW_SEMAPHORE7 \ 0x00000058 #define COMMON_REG_O_APPS_NW_SEMAPHORE8 \ 0x0000005C #define COMMON_REG_O_APPS_NW_SEMAPHORE9 \ 0x00000060 #define COMMON_REG_O_APPS_NW_SEMAPHORE10 \ 0x00000064 #define COMMON_REG_O_APPS_NW_SEMAPHORE11 \ 0x00000068 #define COMMON_REG_O_APPS_NW_SEMAPHORE12 \ 0x0000006C #define COMMON_REG_O_APPS_SEMAPPHORE_PEND \ 0x00000070 #define COMMON_REG_O_NW_SEMAPPHORE_PEND \ 0x00000074 #define COMMON_REG_O_SEMAPHORE_STATUS \ 0x00000078 #define COMMON_REG_O_IDMEM_TIM_Update \ 0x0000007C #define COMMON_REG_O_FPGA_ROM_WR_EN \ 0x00000080 #define COMMON_REG_O_NW_INT_MASK \ 0x00000084 #define COMMON_REG_O_NW_INT_MASK_SET \ 0x00000088 #define COMMON_REG_O_NW_INT_MASK_CLR \ 0x0000008C #define COMMON_REG_O_NW_INT_STS_CLR \ 0x00000090 #define COMMON_REG_O_NW_INT_ACK 0x00000094 #define COMMON_REG_O_NW_INT_TRIG \ 0x00000098 #define COMMON_REG_O_NW_INT_STS_MASKED \ 0x0000009C #define COMMON_REG_O_NW_INT_STS_RAW \ 0x000000A0 #define COMMON_REG_O_APPS_INT_MASK \ 0x000000A4 #define COMMON_REG_O_APPS_INT_MASK_SET \ 0x000000A8 #define COMMON_REG_O_APPS_INT_MASK_CLR \ 0x000000AC #define COMMON_REG_O_APPS_INT_STS_CLR \ 0x000000B0 #define COMMON_REG_O_APPS_INT_ACK \ 0x000000B4 #define COMMON_REG_O_APPS_INT_TRIG \ 0x000000B8 #define COMMON_REG_O_APPS_INT_STS_MASKED \ 0x000000BC #define COMMON_REG_O_APPS_INT_STS_RAW \ 0x000000C0 #define COMMON_REG_O_IDMEM_TIM_Updated \ 0x000000C4 #define COMMON_REG_O_APPS_GPIO_TRIG_EN \ 0x000000C8 #define COMMON_REG_O_EMU_DEBUG_REG \ 0x000000CC #define COMMON_REG_O_SEMAPHORE_STATUS2 \ 0x000000D0 #define COMMON_REG_O_SEMAPHORE_PREV_OWNER1 \ 0x000000D4 #define COMMON_REG_O_SEMAPHORE_PREV_OWNER2 \ 0x000000D8 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_I2C_Properties_Register register. // //****************************************************************************** #define COMMON_REG_I2C_Properties_Register_I2C_Properties_Register_M \ 0x00000003 // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_I2C_Properties_Register_I2C_Properties_Register_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_SPI_Properties_Register register. // //****************************************************************************** #define COMMON_REG_SPI_Properties_Register_SPI_Properties_Register_M \ 0x00000003 // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_SPI_Properties_Register_SPI_Properties_Register_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_sh_resource_Interrupt_enable register. // //****************************************************************************** #define COMMON_REG_APPS_sh_resource_Interrupt_enable_APPS_sh_resource_Interrupt_enable_M \ 0x0000000F // Interrupt enable APPS bit 0 -> // when '1' enable I2C interrupt bit // 1 -> when '1' enable SPI // interrupt bit 3 -> // when '1' enable GPIO interrupt #define COMMON_REG_APPS_sh_resource_Interrupt_enable_APPS_sh_resource_Interrupt_enable_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_sh_resource_Interrupt_status register. // //****************************************************************************** #define COMMON_REG_APPS_sh_resource_Interrupt_status_APPS_sh_resource_Interrupt_status_M \ 0x0000000F // Interrupt enable APPS bit 0 -> // when '1' enable I2C interrupt bit // 1 -> when '1' enable SPI // interrupt bit 3 -> // when '1' enable GPIO interrupt #define COMMON_REG_APPS_sh_resource_Interrupt_status_APPS_sh_resource_Interrupt_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NWP_sh_resource_Interrupt_enable register. // //****************************************************************************** #define COMMON_REG_NWP_sh_resource_Interrupt_enable_NWP_sh_resource_Interrupt_enable_M \ 0x0000000F // Interrupt enable NWP bit 0 -> // when '1' enable I2C interrupt bit // 1 -> when '1' enable SPI // interrupt bit 3 -> // when '1' enable GPIO interrupt #define COMMON_REG_NWP_sh_resource_Interrupt_enable_NWP_sh_resource_Interrupt_enable_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NWP_sh_resource_Interrupt_status register. // //****************************************************************************** #define COMMON_REG_NWP_sh_resource_Interrupt_status_NWP_sh_resource_Interrupt_status_M \ 0x0000000F // Interrupt enable NWP bit 0 -> // when '1' enable I2C interrupt bit // 1 -> when '1' enable SPI // interrupt bit 3 -> // when '1' enable GPIO interrupt #define COMMON_REG_NWP_sh_resource_Interrupt_status_NWP_sh_resource_Interrupt_status_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_Flash_ctrl_reg register. // //****************************************************************************** #define COMMON_REG_Flash_ctrl_reg_Flash_ctrl_reg_M \ 0x00000003 // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_Flash_ctrl_reg_Flash_ctrl_reg_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_Bus_matrix_M0_segment_access_config register. // //****************************************************************************** #define COMMON_REG_Bus_matrix_M0_segment_access_config_Bus_matrix_M0_segment_access_config_M \ 0x0003FFFF // Master 0 control word matrix to // each segment. Tieoff. Bit value 1 // indicates segment is accesable. #define COMMON_REG_Bus_matrix_M0_segment_access_config_Bus_matrix_M0_segment_access_config_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_Bus_matrix_M1_segment_access_config register. // //****************************************************************************** #define COMMON_REG_Bus_matrix_M1_segment_access_config_Bus_matrix_M1_segment_access_config_M \ 0x0003FFFF // Master 1 control word matrix to // each segment. Tieoff. Bit value 1 // indicates segment is accesable. #define COMMON_REG_Bus_matrix_M1_segment_access_config_Bus_matrix_M1_segment_access_config_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_Bus_matrix_M2_segment_access_config register. // //****************************************************************************** #define COMMON_REG_Bus_matrix_M2_segment_access_config_Bus_matrix_M2_segment_access_config_M \ 0x0003FFFF // Master 2 control word matrix to // each segment. Tieoff. Bit value 1 // indicates segment is accesable. #define COMMON_REG_Bus_matrix_M2_segment_access_config_Bus_matrix_M2_segment_access_config_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_Bus_matrix_M3_segment_access_config register. // //****************************************************************************** #define COMMON_REG_Bus_matrix_M3_segment_access_config_Bus_matrix_M3_segment_access_config_M \ 0x0003FFFF // Master 3 control word matrix to // each segment. Tieoff. Bit value 1 // indicates segment is accesable. #define COMMON_REG_Bus_matrix_M3_segment_access_config_Bus_matrix_M3_segment_access_config_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_Bus_matrix_M4_segment_access_config register. // //****************************************************************************** #define COMMON_REG_Bus_matrix_M4_segment_access_config_Bus_matrix_M4_segment_access_config_M \ 0x0003FFFF // Master 4 control word matrix to // each segment. Tieoff. Bit value 1 // indicates segment is accesable. #define COMMON_REG_Bus_matrix_M4_segment_access_config_Bus_matrix_M4_segment_access_config_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_Bus_matrix_M5_segment_access_config register. // //****************************************************************************** #define COMMON_REG_Bus_matrix_M5_segment_access_config_Bus_matrix_M5_segment_access_config_M \ 0x0003FFFF // Master 5 control word matrix to // each segment. Tieoff. Bit value 1 // indicates segment is accesable. #define COMMON_REG_Bus_matrix_M5_segment_access_config_Bus_matrix_M5_segment_access_config_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_GPIO_properties_register register. // //****************************************************************************** #define COMMON_REG_GPIO_properties_register_GPIO_properties_register_M \ 0x000003FF // Shared GPIO configuration // register. Bit [1:0] to configure // GPIO0 Bit [3:2] to configure // GPIO1 Bit [5:4] to configure // GPIO2 Bit [7:6] to configure // GPIO3 Bit [9:8] to configure // GPIO4 each GPIO can be // individully selected. When “00” // GPIO is free resource. When “01” // GPIO is APPS resource. When “10” // GPIO is NWP resource. Writing 11 // doesnt have any affect, i.e. If // one write only relevant gpio // semaphore and other bits are 1s, // it'll not disturb the other // semaphore bits. For example : Say // If NW wants to take control of // gpio-1, one should write // 10'b11_1111_1011 and if one wants // to release it write // 10'b11_1111_0011. #define COMMON_REG_GPIO_properties_register_GPIO_properties_register_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE1 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE1_APPS_NW_SEMAPHORE1_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE1_APPS_NW_SEMAPHORE1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE2 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE2_APPS_NW_SEMAPHORE2_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE2_APPS_NW_SEMAPHORE2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE3 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE3_APPS_NW_SEMAPHORE3_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE3_APPS_NW_SEMAPHORE3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE4 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE4_APPS_NW_SEMAPHORE4_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE4_APPS_NW_SEMAPHORE4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE5 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE5_APPS_NW_SEMAPHORE5_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE5_APPS_NW_SEMAPHORE5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE6 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE6_APPS_NW_SEMAPHORE6_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE6_APPS_NW_SEMAPHORE6_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE7 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE7_APPS_NW_SEMAPHORE7_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE7_APPS_NW_SEMAPHORE7_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE8 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE8_APPS_NW_SEMAPHORE8_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE8_APPS_NW_SEMAPHORE8_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE9 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE9_APPS_NW_SEMAPHORE9_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE9_APPS_NW_SEMAPHORE9_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE10 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE10_APPS_NW_SEMAPHORE10_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE10_APPS_NW_SEMAPHORE10_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE11 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE11_APPS_NW_SEMAPHORE11_M \ 0xFFFFFFFF // • Each semaphore register is of // 2 bit. • When this register is // set to 2’b01 – Apps have access // and when set to 2’b10 – NW have // access. • Ideally both the master // can modify any of this 2 bit, but // assumption apps will write only // 2’b01 or 2’b00 to this register // and nw will write only 2’b10 or // 2’b00. • Implementation is when // any of the bit of this register // is set, only next write // allowedvis 2’b00 – Again // assumption is one master will not // write 2’b00 if other is already // holding the semaphore. #define COMMON_REG_APPS_NW_SEMAPHORE11_APPS_NW_SEMAPHORE11_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_NW_SEMAPHORE12 register. // //****************************************************************************** #define COMMON_REG_APPS_NW_SEMAPHORE12_APPS_NW_SEMAPHORE12_M \ 0xFFFFFFFF // APPS NW semaphore register - not // reflected in status. #define COMMON_REG_APPS_NW_SEMAPHORE12_APPS_NW_SEMAPHORE12_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_SEMAPPHORE_PEND register. // //****************************************************************************** #define COMMON_REG_APPS_SEMAPPHORE_PEND_APPS_SEMAPPHORE_PEND_M \ 0xFFFFFFFF // APPS SEMAPOHORE STATUS #define COMMON_REG_APPS_SEMAPPHORE_PEND_APPS_SEMAPPHORE_PEND_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_SEMAPPHORE_PEND register. // //****************************************************************************** #define COMMON_REG_NW_SEMAPPHORE_PEND_NW_SEMAPPHORE_PEND_M \ 0xFFFFFFFF // NW SEMAPHORE STATUS #define COMMON_REG_NW_SEMAPPHORE_PEND_NW_SEMAPPHORE_PEND_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_SEMAPHORE_STATUS register. // //****************************************************************************** #define COMMON_REG_SEMAPHORE_STATUS_SEMAPHORE_STATUS_M \ 0xFFFFFFFF // SEMAPHORE STATUS 9:8 :semaphore // status of flash_control 7:6 // :semaphore status of // gpio_properties 5:4 // :semaphore status of // spi_propertie 1:0 :semaphore // status of i2c_propertie #define COMMON_REG_SEMAPHORE_STATUS_SEMAPHORE_STATUS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_IDMEM_TIM_Update register. // //****************************************************************************** //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_FPGA_ROM_WR_EN register. // //****************************************************************************** #define COMMON_REG_FPGA_ROM_WR_EN_FPGA_ROM_WR_EN \ 0x00000001 // when '1' enables Write into // IDMEM CORE ROM, APPS ROM, NWP ROM //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_INT_MASK register. // //****************************************************************************** #define COMMON_REG_NW_INT_MASK_NW_INT_MASK_M \ 0xFFFFFFFF // 1= disable corresponding // interrupt;0 = interrupt enabled #define COMMON_REG_NW_INT_MASK_NW_INT_MASK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_INT_MASK_SET register. // //****************************************************************************** #define COMMON_REG_NW_INT_MASK_SET_NW_INT_MASK_SET_M \ 0xFFFFFFFF // write 1 to set corresponding bit // in NW_INT_MASK;0 = no effect #define COMMON_REG_NW_INT_MASK_SET_NW_INT_MASK_SET_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_INT_MASK_CLR register. // //****************************************************************************** #define COMMON_REG_NW_INT_MASK_CLR_NW_INT_MASK_CLR_M \ 0xFFFFFFFF // write 1 to clear corresponding // bit in NW_INT_MASK;0 = no effect #define COMMON_REG_NW_INT_MASK_CLR_NW_INT_MASK_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_INT_STS_CLR register. // //****************************************************************************** #define COMMON_REG_NW_INT_STS_CLR_NW_INT_STS_CLR_M \ 0xFFFFFFFF // write 1 to clear corresponding // interrupt; 0 = no effect; // interrupt is not lost if coincide // with write operation #define COMMON_REG_NW_INT_STS_CLR_NW_INT_STS_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_INT_ACK register. // //****************************************************************************** #define COMMON_REG_NW_INT_ACK_NW_INT_ACK_M \ 0xFFFFFFFF // write 1 to clear corresponding // interrupt;0 = no effect #define COMMON_REG_NW_INT_ACK_NW_INT_ACK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_INT_TRIG register. // //****************************************************************************** #define COMMON_REG_NW_INT_TRIG_NW_INT_TRIG_M \ 0xFFFFFFFF // Writing a 1 to a bit in this // register causes the the Host CPU // if enabled (not masked). This // register is self-clearing. // Writing 0 has no effect #define COMMON_REG_NW_INT_TRIG_NW_INT_TRIG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_INT_STS_MASKED register. // //****************************************************************************** #define COMMON_REG_NW_INT_STS_MASKED_NW_INT_STS_MASKED_M \ 0xFFFFFFFF // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by NW_INT mask #define COMMON_REG_NW_INT_STS_MASKED_NW_INT_STS_MASKED_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_NW_INT_STS_RAW register. // //****************************************************************************** #define COMMON_REG_NW_INT_STS_RAW_NW_INT_STS_RAW_M \ 0xFFFFFFFF // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define COMMON_REG_NW_INT_STS_RAW_NW_INT_STS_RAW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_INT_MASK register. // //****************************************************************************** #define COMMON_REG_APPS_INT_MASK_APPS_INT_MASK_M \ 0xFFFFFFFF // 1= disable corresponding // interrupt;0 = interrupt enabled #define COMMON_REG_APPS_INT_MASK_APPS_INT_MASK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_INT_MASK_SET register. // //****************************************************************************** #define COMMON_REG_APPS_INT_MASK_SET_APPS_INT_MASK_SET_M \ 0xFFFFFFFF // write 1 to set corresponding bit // in APPS_INT_MASK;0 = no effect #define COMMON_REG_APPS_INT_MASK_SET_APPS_INT_MASK_SET_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_INT_MASK_CLR register. // //****************************************************************************** #define COMMON_REG_APPS_INT_MASK_CLR_APPS_INT_MASK_CLR_M \ 0xFFFFFFFF // write 1 to clear corresponding // bit in APPS_INT_MASK;0 = no // effect #define COMMON_REG_APPS_INT_MASK_CLR_APPS_INT_MASK_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_INT_STS_CLR register. // //****************************************************************************** #define COMMON_REG_APPS_INT_STS_CLR_APPS_INT_STS_CLR_M \ 0xFFFFFFFF // write 1 to clear corresponding // interrupt; 0 = no effect; // interrupt is not lost if coincide // with write operation #define COMMON_REG_APPS_INT_STS_CLR_APPS_INT_STS_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_INT_ACK register. // //****************************************************************************** #define COMMON_REG_APPS_INT_ACK_APPS_INT_ACK_M \ 0xFFFFFFFF // write 1 to clear corresponding // interrupt;0 = no effect #define COMMON_REG_APPS_INT_ACK_APPS_INT_ACK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_INT_TRIG register. // //****************************************************************************** #define COMMON_REG_APPS_INT_TRIG_APPS_INT_TRIG_M \ 0xFFFFFFFF // Writing a 1 to a bit in this // register causes the the Host CPU // if enabled (not masked). This // register is self-clearing. // Writing 0 has no effect #define COMMON_REG_APPS_INT_TRIG_APPS_INT_TRIG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_INT_STS_MASKED register. // //****************************************************************************** #define COMMON_REG_APPS_INT_STS_MASKED_APPS_INT_STS_MASKED_M \ 0xFFFFFFFF // 1= corresponding interrupt is // active and not masked. read is // non-destructive;0 = corresponding // interrupt is inactive or masked // by APPS_INT mask #define COMMON_REG_APPS_INT_STS_MASKED_APPS_INT_STS_MASKED_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_INT_STS_RAW register. // //****************************************************************************** #define COMMON_REG_APPS_INT_STS_RAW_APPS_INT_STS_RAW_M \ 0xFFFFFFFF // 1= corresponding interrupt is // active. read is non-destructive;0 // = corresponding interrupt is // inactive #define COMMON_REG_APPS_INT_STS_RAW_APPS_INT_STS_RAW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_IDMEM_TIM_Updated register. // //****************************************************************************** #define COMMON_REG_IDMEM_TIM_Updated_TIM_UPDATED \ 0x00000001 // toggle in this signal // indicatesIDMEM_TIM_UPDATE // register mentioned above is // updated. //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_APPS_GPIO_TRIG_EN register. // //****************************************************************************** #define COMMON_REG_APPS_GPIO_TRIG_EN_APPS_GPIO_TRIG_EN_M \ 0x0000001F // APPS GPIO Trigger EN control. // Bit 0: when '1' enable GPIO 0 // trigger. This bit enables trigger // for all GPIO 0 pins (GPIO 0 to // GPIO7). Bit 1: when '1' enable // GPIO 1 trigger. This bit enables // trigger for all GPIO 1 pins ( // GPIO8 to GPIO15). Bit 2: when '1' // enable GPIO 2 trigger. This bit // enables trigger for all GPIO 2 // pins (GPIO16 to GPIO23). Bit 3: // when '1' enable GPIO 3 trigger. // This bit enables trigger for all // GPIO 3 pins (GPIO24 to GPIO31). // Bit 4: when '1' enable GPIO 4 // trigger. This bit enables trigger // for all GPIO 4 pins.(GPIO32 to // GPIO39) #define COMMON_REG_APPS_GPIO_TRIG_EN_APPS_GPIO_TRIG_EN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_EMU_DEBUG_REG register. // //****************************************************************************** #define COMMON_REG_EMU_DEBUG_REG_EMU_DEBUG_REG_M \ 0xFFFFFFFF // 0 th bit used for stalling APPS // DMA and 1st bit is used for // stalling NWP DMA for debug // purpose. Other bits are unused. #define COMMON_REG_EMU_DEBUG_REG_EMU_DEBUG_REG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_SEMAPHORE_STATUS2 register. // //****************************************************************************** #define COMMON_REG_SEMAPHORE_STATUS2_SEMPAPHORE_STATUS2_M \ 0x00FFFFFF // SEMAPHORE STATUS 23:22 // :semaphore status of // apps_nw_semaphore11 21:20 // :semaphore status of // apps_nw_semaphore11 19:18 // :semaphore status of // apps_nw_semaphore10 17:16 // :semaphore status of // apps_nw_semaphore9 15:14 // :semaphore status of // apps_nw_semaphore8 13:12 // :semaphore status of // apps_nw_semaphore7 11:10 // :semaphore status of // apps_nw_semaphore6 9:8 :semaphore // status of apps_nw_semaphore5 7:6 // :semaphore status of // apps_nw_semaphore4 5:4 :semaphore // status of apps_nw_semaphore3 3:2 // :semaphore status of // apps_nw_semaphore2 1:0 :semaphore // status of apps_nw_semaphore1 #define COMMON_REG_SEMAPHORE_STATUS2_SEMPAPHORE_STATUS2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_SEMAPHORE_PREV_OWNER1 register. // //****************************************************************************** #define COMMON_REG_SEMAPHORE_PREV_OWNER1_SEMAPHORE_PREV_OWNER1_M \ 0x0003FFFF // 1:0 : prvious owner of // i2c_properties_reg[1:0] 3:2 : // prvious owner of // spi_properties_reg[1:0] 5:4 : // prvious owner of // gpio_properties_reg[1:0] 9:8 : // prvious owner of // gpio_properties_reg[3:2] 11:10 : // prvious owner of // gpio_properties_reg[5:4] 13:12 : // prvious owner of // gpio_properties_reg[7:6] 15:14 : // prvious owner of // gpio_properties_reg[9:8] 17:16 : // prvious owner of // flash_control_reg[1:0] #define COMMON_REG_SEMAPHORE_PREV_OWNER1_SEMAPHORE_PREV_OWNER1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // COMMON_REG_O_SEMAPHORE_PREV_OWNER2 register. // //****************************************************************************** #define COMMON_REG_SEMAPHORE_PREV_OWNER2_SEMAPHORE_PREV_OWNER2_M \ 0x00FFFFFF // 1:0 : previous owner of // apps_nw_semaphore1_reg[1:0] 3:2 : // previous owner of // apps_nw_semaphore2_reg[1:0] 5:4 : // previous owner of // apps_nw_semaphore3_reg[1:0] 7:6 : // previous owner of // apps_nw_semaphore4_reg[1:0] 9:8 : // previous owner of // apps_nw_semaphore5_reg[1:0] 11:10 // : previous owner of // apps_nw_semaphore6_reg[1:0] 13:12 // : previous owner of // apps_nw_semaphore7_reg[1:0] 15:14 // : previous owner of // apps_nw_semaphore8_reg[1:0] 17:16 // : previous owner of // apps_nw_semaphore9_reg[1:0] 19:18 // : previous owner of // apps_nw_semaphore10_reg[1:0] // 21:20 : previous owner of // apps_nw_semaphore11_reg[1:0] // 23:22 : previous owner of // apps_nw_semaphore12_reg[1:0] #define COMMON_REG_SEMAPHORE_PREV_OWNER2_SEMAPHORE_PREV_OWNER2_S 0 #endif // __HW_COMMON_REG_H__ micropython-1.12/ports/cc3200/hal/inc/hw_des.h000066400000000000000000000453721357706137100210350ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_DES_H__ #define __HW_DES_H__ //***************************************************************************** // // The following are defines for the DES_P register offsets. // //***************************************************************************** #define DES_O_KEY3_L 0x00000000 // KEY3 (LSW) for 192-bit key #define DES_O_KEY3_H 0x00000004 // KEY3 (MSW) for 192-bit key #define DES_O_KEY2_L 0x00000008 // KEY2 (LSW) for 192-bit key #define DES_O_KEY2_H 0x0000000C // KEY2 (MSW) for 192-bit key #define DES_O_KEY1_L 0x00000010 // KEY1 (LSW) for 128-bit // key/192-bit key #define DES_O_KEY1_H 0x00000014 // KEY1 (LSW) for 128-bit // key/192-bit key #define DES_O_IV_L 0x00000018 // Initialization vector LSW #define DES_O_IV_H 0x0000001C // Initialization vector MSW #define DES_O_CTRL 0x00000020 #define DES_O_LENGTH 0x00000024 // Indicates the cryptographic data // length in bytes for all modes. // Once processing is started with // this context this length // decrements to zero. Data lengths // up to (2^32 – 1) bytes are // allowed. A write to this register // triggers the engine to start // using this context. For a Host // read operation these registers // return all-zeroes. #define DES_O_DATA_L 0x00000028 // Data register(LSW) to read/write // encrypted/decrypted data. #define DES_O_DATA_H 0x0000002C // Data register(MSW) to read/write // encrypted/decrypted data. #define DES_O_REVISION 0x00000030 #define DES_O_SYSCONFIG 0x00000034 #define DES_O_SYSSTATUS 0x00000038 #define DES_O_IRQSTATUS 0x0000003C // This register indicates the // interrupt status. If one of the // interrupt bits is set the // interrupt output will be asserted #define DES_O_IRQENABLE 0x00000040 // This register contains an enable // bit for each unique interrupt // generated by the module. It // matches the layout of // DES_IRQSTATUS register. An // interrupt is enabled when the bit // in this register is set to 1 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_KEY3_L register. // //****************************************************************************** #define DES_KEY3_L_KEY3_L_M 0xFFFFFFFF // data for key3 #define DES_KEY3_L_KEY3_L_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_KEY3_H register. // //****************************************************************************** #define DES_KEY3_H_KEY3_H_M 0xFFFFFFFF // data for key3 #define DES_KEY3_H_KEY3_H_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_KEY2_L register. // //****************************************************************************** #define DES_KEY2_L_KEY2_L_M 0xFFFFFFFF // data for key2 #define DES_KEY2_L_KEY2_L_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_KEY2_H register. // //****************************************************************************** #define DES_KEY2_H_KEY2_H_M 0xFFFFFFFF // data for key2 #define DES_KEY2_H_KEY2_H_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_KEY1_L register. // //****************************************************************************** #define DES_KEY1_L_KEY1_L_M 0xFFFFFFFF // data for key1 #define DES_KEY1_L_KEY1_L_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_KEY1_H register. // //****************************************************************************** #define DES_KEY1_H_KEY1_H_M 0xFFFFFFFF // data for key1 #define DES_KEY1_H_KEY1_H_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_IV_L register. // //****************************************************************************** #define DES_IV_L_IV_L_M 0xFFFFFFFF // initialization vector for CBC // CFB modes #define DES_IV_L_IV_L_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_IV_H register. // //****************************************************************************** #define DES_IV_H_IV_H_M 0xFFFFFFFF // initialization vector for CBC // CFB modes #define DES_IV_H_IV_H_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_CTRL register. // //****************************************************************************** #define DES_CTRL_CONTEXT 0x80000000 // If ‘1’ this read-only status bit // indicates that the context data // registers can be overwritten and // the host is permitted to write // the next context. #define DES_CTRL_MODE_M 0x00000030 // Select CBC ECB or CFB mode 0x0 // ecb mode 0x1 cbc mode 0x2 cfb // mode 0x3 reserved #define DES_CTRL_MODE_S 4 #define DES_CTRL_TDES 0x00000008 // Select DES or triple DES // encryption/decryption. 0 des mode // 1 tdes mode #define DES_CTRL_DIRECTION 0x00000004 // select encryption/decryption 0 // decryption is selected 1 // Encryption is selected #define DES_CTRL_INPUT_READY 0x00000002 // When '1' ready to // encrypt/decrypt data #define DES_CTRL_OUTPUT_READY 0x00000001 // When '1' Data // decrypted/encrypted ready //****************************************************************************** // // The following are defines for the bit fields in the DES_O_LENGTH register. // //****************************************************************************** #define DES_LENGTH_LENGTH_M 0xFFFFFFFF #define DES_LENGTH_LENGTH_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_DATA_L register. // //****************************************************************************** #define DES_DATA_L_DATA_L_M 0xFFFFFFFF // data for encryption/decryption #define DES_DATA_L_DATA_L_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_DATA_H register. // //****************************************************************************** #define DES_DATA_H_DATA_H_M 0xFFFFFFFF // data for encryption/decryption #define DES_DATA_H_DATA_H_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_REVISION register. // //****************************************************************************** #define DES_REVISION_SCHEME_M 0xC0000000 #define DES_REVISION_SCHEME_S 30 #define DES_REVISION_FUNC_M 0x0FFF0000 // Function indicates a software // compatible module family. If // there is no level of software // compatibility a new Func number // (and hence REVISION) should be // assigned. #define DES_REVISION_FUNC_S 16 #define DES_REVISION_R_RTL_M 0x0000F800 // RTL Version (R) maintained by IP // design owner. RTL follows a // numbering such as X.Y.R.Z which // are explained in this table. R // changes ONLY when: (1) PDS // uploads occur which may have been // due to spec changes (2) Bug fixes // occur (3) Resets to '0' when X or // Y changes. Design team has an // internal 'Z' (customer invisible) // number which increments on every // drop that happens due to DV and // RTL updates. Z resets to 0 when R // increments. #define DES_REVISION_R_RTL_S 11 #define DES_REVISION_X_MAJOR_M \ 0x00000700 // Major Revision (X) maintained by // IP specification owner. X changes // ONLY when: (1) There is a major // feature addition. An example // would be adding Master Mode to // Utopia Level2. The Func field (or // Class/Type in old PID format) // will remain the same. X does NOT // change due to: (1) Bug fixes (2) // Change in feature parameters. #define DES_REVISION_X_MAJOR_S 8 #define DES_REVISION_CUSTOM_M 0x000000C0 #define DES_REVISION_CUSTOM_S 6 #define DES_REVISION_Y_MINOR_M \ 0x0000003F // Minor Revision (Y) maintained by // IP specification owner. Y changes // ONLY when: (1) Features are // scaled (up or down). Flexibility // exists in that this feature // scalability may either be // represented in the Y change or a // specific register in the IP that // indicates which features are // exactly available. (2) When // feature creeps from Is-Not list // to Is list. But this may not be // the case once it sees silicon; in // which case X will change. Y does // NOT change due to: (1) Bug fixes // (2) Typos or clarifications (3) // major functional/feature // change/addition/deletion. Instead // these changes may be reflected // via R S X as applicable. Spec // owner maintains a // customer-invisible number 'S' // which changes due to: (1) // Typos/clarifications (2) Bug // documentation. Note that this bug // is not due to a spec change but // due to implementation. // Nevertheless the spec tracks the // IP bugs. An RTL release (say for // silicon PG1.1) that occurs due to // bug fix should document the // corresponding spec number (X.Y.S) // in its release notes. #define DES_REVISION_Y_MINOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_SYSCONFIG register. // //****************************************************************************** #define DES_SYSCONFIG_DMA_REQ_CONTEXT_IN_EN \ 0x00000080 // If set to ‘1’ the DMA context // request is enabled. 0 Dma // disabled 1 Dma enabled #define DES_SYSCONFIG_DMA_REQ_DATA_OUT_EN \ 0x00000040 // If set to ‘1’ the DMA output // request is enabled. 0 Dma // disabled 1 Dma enabled #define DES_SYSCONFIG_DMA_REQ_DATA_IN_EN \ 0x00000020 // If set to ‘1’ the DMA input // request is enabled. 0 Dma // disabled 1 Dma enabled //****************************************************************************** // // The following are defines for the bit fields in the DES_O_SYSSTATUS register. // //****************************************************************************** #define DES_SYSSTATUS_RESETDONE \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the DES_O_IRQSTATUS register. // //****************************************************************************** #define DES_IRQSTATUS_DATA_OUT \ 0x00000004 // This bit indicates data output // interrupt is active and triggers // the interrupt output. #define DES_IRQSTATUS_DATA_IN 0x00000002 // This bit indicates data input // interrupt is active and triggers // the interrupt output. #define DES_IRQSTATUS_CONTEX_IN \ 0x00000001 // This bit indicates context // interrupt is active and triggers // the interrupt output. //****************************************************************************** // // The following are defines for the bit fields in the DES_O_IRQENABLE register. // //****************************************************************************** #define DES_IRQENABLE_M_DATA_OUT \ 0x00000004 // If this bit is set to ‘1’ the // secure data output interrupt is // enabled. #define DES_IRQENABLE_M_DATA_IN \ 0x00000002 // If this bit is set to ‘1’ the // secure data input interrupt is // enabled. #define DES_IRQENABLE_M_CONTEX_IN \ 0x00000001 // If this bit is set to ‘1’ the // secure context interrupt is // enabled. #endif // __HW_DES_H__ micropython-1.12/ports/cc3200/hal/inc/hw_dthe.h000066400000000000000000000501731357706137100212010ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** #ifndef __HW_DTHE_H__ #define __HW_DTHE_H__ //***************************************************************************** // // The following are defines for the DTHE register offsets. // //***************************************************************************** #define DTHE_O_SHA_IM 0x00000810 #define DTHE_O_SHA_RIS 0x00000814 #define DTHE_O_SHA_MIS 0x00000818 #define DTHE_O_SHA_IC 0x0000081C #define DTHE_O_AES_IM 0x00000820 #define DTHE_O_AES_RIS 0x00000824 #define DTHE_O_AES_MIS 0x00000828 #define DTHE_O_AES_IC 0x0000082C #define DTHE_O_DES_IM 0x00000830 #define DTHE_O_DES_RIS 0x00000834 #define DTHE_O_DES_MIS 0x00000838 #define DTHE_O_DES_IC 0x0000083C #define DTHE_O_EIP_CGCFG 0x00000A00 #define DTHE_O_EIP_CGREQ 0x00000A04 #define DTHE_O_CRC_CTRL 0x00000C00 #define DTHE_O_CRC_SEED 0x00000C10 #define DTHE_O_CRC_DIN 0x00000C14 #define DTHE_O_CRC_RSLT_PP 0x00000C18 #define DTHE_O_RAND_KEY0 0x00000F00 #define DTHE_O_RAND_KEY1 0x00000F04 #define DTHE_O_RAND_KEY2 0x00000F08 #define DTHE_O_RAND_KEY3 0x00000F0C //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_SHAMD5_IMST register. // //****************************************************************************** #define DTHE_SHAMD5_IMST_DIN 0x00000004 // Data in: this interrupt is // raised when DMA writes last word // of input data to internal FIFO of // the engine #define DTHE_SHAMD5_IMST_COUT 0x00000002 // Context out: this interrupt is // raised when DMA complets the // output context movement from // internal register #define DTHE_SHAMD5_IMST_CIN 0x00000001 // context in: this interrupt is // raised when DMA complets Context // write to internal register //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_SHAMD5_IRIS register. // //****************************************************************************** #define DTHE_SHAMD5_IRIS_DIN 0x00000004 // input Data movement is done #define DTHE_SHAMD5_IRIS_COUT 0x00000002 // Context output is done #define DTHE_SHAMD5_IRIS_CIN 0x00000001 // context input is done //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_SHAMD5_IMIS register. // //****************************************************************************** #define DTHE_SHAMD5_IMIS_DIN 0x00000004 // input Data movement is done #define DTHE_SHAMD5_IMIS_COUT 0x00000002 // Context output is done #define DTHE_SHAMD5_IMIS_CIN 0x00000001 // context input is done //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_SHAMD5_ICIS register. // //****************************************************************************** #define DTHE_SHAMD5_ICIS_DIN 0x00000004 // Clear “input Data movement done” // flag #define DTHE_SHAMD5_ICIS_COUT 0x00000002 // Clear “Context output done” flag #define DTHE_SHAMD5_ICIS_CIN 0x00000001 // Clear “context input done” flag //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_AES_IMST register. // //****************************************************************************** #define DTHE_AES_IMST_DOUT 0x00000008 // Data out: this interrupt is // raised when DMA finishes writing // last word of the process result #define DTHE_AES_IMST_DIN 0x00000004 // Data in: this interrupt is // raised when DMA writes last word // of input data to internal FIFO of // the engine #define DTHE_AES_IMST_COUT 0x00000002 // Context out: this interrupt is // raised when DMA complets the // output context movement from // internal register #define DTHE_AES_IMST_CIN 0x00000001 // context in: this interrupt is // raised when DMA complets Context // write to internal register //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_AES_IRIS register. // //****************************************************************************** #define DTHE_AES_IRIS_DOUT 0x00000008 // Output Data movement is done #define DTHE_AES_IRIS_DIN 0x00000004 // input Data movement is done #define DTHE_AES_IRIS_COUT 0x00000002 // Context output is done #define DTHE_AES_IRIS_CIN 0x00000001 // context input is done //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_AES_IMIS register. // //****************************************************************************** #define DTHE_AES_IMIS_DOUT 0x00000008 // Output Data movement is done #define DTHE_AES_IMIS_DIN 0x00000004 // input Data movement is done #define DTHE_AES_IMIS_COUT 0x00000002 // Context output is done #define DTHE_AES_IMIS_CIN 0x00000001 // context input is done //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_AES_ICIS register. // //****************************************************************************** #define DTHE_AES_ICIS_DOUT 0x00000008 // Clear “output Data movement // done” flag #define DTHE_AES_ICIS_DIN 0x00000004 // Clear “input Data movement done” // flag #define DTHE_AES_ICIS_COUT 0x00000002 // Clear “Context output done” flag #define DTHE_AES_ICIS_CIN 0x00000001 // Clear “context input done” flag //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_DES_IMST register. // //****************************************************************************** #define DTHE_DES_IMST_DOUT 0x00000008 // Data out: this interrupt is // raised when DMA finishes writing // last word of the process result #define DTHE_DES_IMST_DIN 0x00000004 // Data in: this interrupt is // raised when DMA writes last word // of input data to internal FIFO of // the engine #define DTHE_DES_IMST_CIN 0x00000001 // context in: this interrupt is // raised when DMA complets Context // write to internal register //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_DES_IRIS register. // //****************************************************************************** #define DTHE_DES_IRIS_DOUT 0x00000008 // Output Data movement is done #define DTHE_DES_IRIS_DIN 0x00000004 // input Data movement is done #define DTHE_DES_IRIS_CIN 0x00000001 // context input is done //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_DES_IMIS register. // //****************************************************************************** #define DTHE_DES_IMIS_DOUT 0x00000008 // Output Data movement is done #define DTHE_DES_IMIS_DIN 0x00000004 // input Data movement is done #define DTHE_DES_IMIS_CIN 0x00000001 // context input is done //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_DES_ICIS register. // //****************************************************************************** #define DTHE_DES_ICIS_DOUT 0x00000008 // Clear “output Data movement // done” flag #define DTHE_DES_ICIS_DIN 0x00000004 // Clear “input Data movement done” // flag #define DTHE_DES_ICIS_CIN 0x00000001 // Clear "context input done” flag //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_EIP_CGCFG register. // //****************************************************************************** #define DTHE_EIP_CGCFG_EIP29_CFG \ 0x00000010 // Clock gating protocol setting // for EIP29T. 0 – Follow direct // protocol 1 – Follow idle_req/ack // protocol. #define DTHE_EIP_CGCFG_EIP75_CFG \ 0x00000008 // Clock gating protocol setting // for EIP75T. 0 – Follow direct // protocol 1 – Follow idle_req/ack // protocol. #define DTHE_EIP_CGCFG_EIP16_CFG \ 0x00000004 // Clock gating protocol setting // for DES. 0 – Follow direct // protocol 1 – Follow idle_req/ack // protocol. #define DTHE_EIP_CGCFG_EIP36_CFG \ 0x00000002 // Clock gating protocol setting // for AES. 0 – Follow direct // protocol 1 – Follow idle_req/ack // protocol. #define DTHE_EIP_CGCFG_EIP57_CFG \ 0x00000001 // Clock gating protocol setting // for SHAMD5. 0 – Follow direct // protocol 1 – Follow idle_req/ack // protocol. //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_EIP_CGREQ register. // //****************************************************************************** #define DTHE_EIP_CGREQ_Key_M 0xF0000000 // When “0x5” write “1” to lower // bits [4:0] will set the bit. // Write “0” will be ignored When // “0x2” write “1” to lower bit // [4:0] will clear the bit. Write // “0” will be ignored for other key // value, regular read write // operation #define DTHE_EIP_CGREQ_Key_S 28 #define DTHE_EIP_CGREQ_EIP29_REQ \ 0x00000010 // 0 – request clock gating 1 – // request to un-gate the clock. #define DTHE_EIP_CGREQ_EIP75_REQ \ 0x00000008 // 0 – request clock gating 1 – // request to un-gate the clock. #define DTHE_EIP_CGREQ_EIP16_REQ \ 0x00000004 // 0 – request clock gating 1 – // request to un-gate the clock. #define DTHE_EIP_CGREQ_EIP36_REQ \ 0x00000002 // 0 – request clock gating 1 – // request to un-gate the clock. #define DTHE_EIP_CGREQ_EIP57_REQ \ 0x00000001 // 0 – request clock gating 1 – // request to un-gate the clock. //****************************************************************************** // // The following are defines for the bit fields in the DTHE_O_CRC_CTRL register. // //****************************************************************************** #define DTHE_CRC_CTRL_INIT_M 0x00006000 // Initialize the CRC 00 – use SEED // register context as starting // value 10 – all “zero” 11 – all // “one” This is self clearing. With // first write to data register this // value clears to zero and remain // zero for rest of the operation // unless written again #define DTHE_CRC_CTRL_INIT_S 13 #define DTHE_CRC_CTRL_SIZE 0x00001000 // Input data size 0 – 32 bit 1 – 8 // bit #define DTHE_CRC_CTRL_OINV 0x00000200 // Inverse the bits of result // before storing to CRC_RSLT_PP0 #define DTHE_CRC_CTRL_OBR 0x00000100 // Bit reverse the output result // byte before storing to // CRC_RSLT_PP0. applicable for all // bytes in word #define DTHE_CRC_CTRL_IBR 0x00000080 // Bit reverse the input byte. For // all bytes in word #define DTHE_CRC_CTRL_ENDIAN_M \ 0x00000030 // Endian control [0] – swap byte // in half-word [1] – swap half word #define DTHE_CRC_CTRL_ENDIAN_S 4 #define DTHE_CRC_CTRL_TYPE_M 0x0000000F // Type of operation 0000 – // polynomial 0x8005 0001 – // polynomial 0x1021 0010 – // polynomial 0x4C11DB7 0011 – // polynomial 0x1EDC6F41 1000 – TCP // checksum TYPE in DTHE_S_CRC_CTRL // & DTHE_S_CRC_CTRL should be // exclusive #define DTHE_CRC_CTRL_TYPE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DTHE_O_CRC_SEED register. // //****************************************************************************** #define DTHE_CRC_SEED_SEED_M 0xFFFFFFFF // Starting seed of CRC and // checksum operation. Please see // CTRL register for more detail. // This resister also holds the // latest result of CRC or checksum // operation #define DTHE_CRC_SEED_SEED_S 0 //****************************************************************************** // // The following are defines for the bit fields in the DTHE_O_CRC_DIN register. // //****************************************************************************** #define DTHE_CRC_DIN_DATA_IN_M \ 0xFFFFFFFF // Input data for CRC or checksum // operation #define DTHE_CRC_DIN_DATA_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_CRC_RSLT_PP register. // //****************************************************************************** #define DTHE_CRC_RSLT_PP_RSLT_PP_M \ 0xFFFFFFFF // Input data for CRC or checksum // operation #define DTHE_CRC_RSLT_PP_RSLT_PP_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_RAND_KEY0 register. // //****************************************************************************** #define DTHE_RAND_KEY0_KEY_M 0xFFFFFFFF // Device Specific Randon key // [31:0] #define DTHE_RAND_KEY0_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_RAND_KEY1 register. // //****************************************************************************** #define DTHE_RAND_KEY1_KEY_M 0xFFFFFFFF // Device Specific Randon key // [63:32] #define DTHE_RAND_KEY1_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_RAND_KEY2 register. // //****************************************************************************** #define DTHE_RAND_KEY2_KEY_M 0xFFFFFFFF // Device Specific Randon key // [95:34] #define DTHE_RAND_KEY2_KEY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // DTHE_O_RAND_KEY3 register. // //****************************************************************************** #define DTHE_RAND_KEY3_KEY_M 0xFFFFFFFF // Device Specific Randon key // [127:96] #define DTHE_RAND_KEY3_KEY_S 0 #endif // __HW_DTHE_H__ micropython-1.12/ports/cc3200/hal/inc/hw_flash_ctrl.h000066400000000000000000003742031357706137100224010ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_FLASH_CTRL_H__ #define __HW_FLASH_CTRL_H__ //***************************************************************************** // // The following are defines for the FLASH_CTRL register offsets. // //***************************************************************************** #define FLASH_CTRL_O_FMA 0x00000000 // Flash Memory Address (FMA) // offset 0x000 During a write // operation this register contains // a 4-byte-aligned address and // specifies where the data is // written. During erase operations // this register contains a 1 // KB-aligned CPU byte address and // specifies which block is erased. // Note that the alignment // requirements must be met by // software or the results of the // operation are unpredictable. #define FLASH_CTRL_O_FMD 0x00000004 // Flash Memory Data (FMD) offset // 0x004 This register contains the // data to be written during the // programming cycle or read during // the read cycle. Note that the // contents of this register are // undefined for a read access of an // execute-only block. This register // is not used during erase cycles. #define FLASH_CTRL_O_FMC 0x00000008 // Flash Memory Control (FMC) // offset 0x008 When this register // is written the Flash memory // controller initiates the // appropriate access cycle for the // location specified by the Flash // Memory Address (FMA) register . // If the access is a write access // the data contained in the Flash // Memory Data (FMD) register is // written to the specified address. // This register must be the final // register written and initiates // the memory operation. The four // control bits in the lower byte of // this register are used to // initiate memory operations. #define FLASH_CTRL_O_FCRIS 0x0000000C // Flash Controller Raw Interrupt // Status (FCRIS) offset 0x00C This // register indicates that the Flash // memory controller has an // interrupt condition. An interrupt // is sent to the interrupt // controller only if the // corresponding FCIM register bit // is set. #define FLASH_CTRL_O_FCIM 0x00000010 // Flash Controller Interrupt Mask // (FCIM) offset 0x010 This register // controls whether the Flash memory // controller generates interrupts // to the controller. #define FLASH_CTRL_O_FCMISC 0x00000014 // Flash Controller Masked // Interrupt Status and Clear // (FCMISC) offset 0x014 This // register provides two functions. // First it reports the cause of an // interrupt by indicating which // interrupt source or sources are // signalling the interrupt. Second // it serves as the method to clear // the interrupt reporting. #define FLASH_CTRL_O_FMC2 0x00000020 // Flash Memory Control 2 (FMC2) // offset 0x020 When this register // is written the Flash memory // controller initiates the // appropriate access cycle for the // location specified by the Flash // Memory Address (FMA) register . // If the access is a write access // the data contained in the Flash // Write Buffer (FWB) registers is // written. This register must be // the final register written as it // initiates the memory operation. #define FLASH_CTRL_O_FWBVAL 0x00000030 // Flash Write Buffer Valid // (FWBVAL) offset 0x030 This // register provides a bitwise // status of which FWBn registers // have been written by the // processor since the last write of // the Flash memory write buffer. // The entries with a 1 are written // on the next write of the Flash // memory write buffer. This // register is cleared after the // write operation by hardware. A // protection violation on the write // operation also clears this // status. Software can program the // same 32 words to various Flash // memory locations by setting the // FWB[n] bits after they are // cleared by the write operation. // The next write operation then // uses the same data as the // previous one. In addition if a // FWBn register change should not // be written to Flash memory // software can clear the // corresponding FWB[n] bit to // preserve the existing data when // the next write operation occurs. #define FLASH_CTRL_O_FWB1 0x00000100 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB2 0x00000104 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB3 0x00000108 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB4 0x0000010C // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB5 0x00000110 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB6 0x00000114 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB7 0x00000118 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB8 0x0000011C // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB9 0x00000120 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB10 0x00000124 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB11 0x00000128 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB12 0x0000012C // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB13 0x00000130 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB14 0x00000134 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB15 0x00000138 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB16 0x0000013C // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB17 0x00000140 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB18 0x00000144 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB19 0x00000148 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB20 0x0000014C // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB21 0x00000150 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB22 0x00000154 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB23 0x00000158 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB24 0x0000015C // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB25 0x00000160 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB26 0x00000164 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB27 0x00000168 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB28 0x0000016C // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB29 0x00000170 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB30 0x00000174 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB31 0x00000178 // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FWB32 0x0000017C // Flash Write Buffer n (FWBn) // offset 0x100 - 0x17C These 32 // registers hold the contents of // the data to be written into the // Flash memory on a buffered Flash // memory write operation. The // offset selects one of the 32-bit // registers. Only FWBn registers // that have been updated since the // preceding buffered Flash memory // write operation are written into // the Flash memory so it is not // necessary to write the entire // bank of registers in order to // write 1 or 2 words. The FWBn // registers are written into the // Flash memory with the FWB0 // register corresponding to the // address contained in FMA. FWB1 is // written to the address FMA+0x4 // etc. Note that only data bits // that are 0 result in the Flash // memory being modified. A data bit // that is 1 leaves the content of // the Flash memory bit at its // previous value. #define FLASH_CTRL_O_FSIZE 0x00000FC0 // Flash Size (FSIZE) offset 0xFC0 // This register indicates the size // of the on-chip Flash memory. // Important: This register should // be used to determine the size of // the Flash memory that is // implemented on this // microcontroller. However to // support legacy software the DC0 // register is available. A read of // the DC0 register correctly // identifies legacy memory sizes. // Software must use the FSIZE // register for memory sizes that // are not listed in the DC0 // register description. #define FLASH_CTRL_O_SSIZE 0x00000FC4 // SRAM Size (SSIZE) offset 0xFC4 // This register indicates the size // of the on-chip SRAM. Important: // This register should be used to // determine the size of the SRAM // that is implemented on this // microcontroller. However to // support legacy software the DC0 // register is available. A read of // the DC0 register correctly // identifies legacy memory sizes. // Software must use the SSIZE // register for memory sizes that // are not listed in the DC0 // register description. //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FMA register. // //****************************************************************************** #define FLASH_CTRL_FMA_OFFSET_M 0x0003FFFF // Address Offset Address offset in // Flash memory where operation is // performed except for nonvolatile // registers #define FLASH_CTRL_FMA_OFFSET_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FMD register. // //****************************************************************************** #define FLASH_CTRL_FMD_DATA_M 0xFFFFFFFF // Data Value Data value for write // operation. #define FLASH_CTRL_FMD_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FMC register. // //****************************************************************************** #define FLASH_CTRL_FMC_WRKEY_M 0xFFFF0000 // Flash Memory Write Key This // field contains a write key which // is used to minimize the incidence // of accidental Flash memory // writes. The value 0xA442 must be // written into this field for a // Flash memory write to occur. // Writes to the FMC register // without this WRKEY value are // ignored. A read of this field // returns the value 0. #define FLASH_CTRL_FMC_WRKEY_S 16 #define FLASH_CTRL_FMC_COMT 0x00000008 // Commit Register Value This bit // is used to commit writes to // Flash-memory-resident registers // and to monitor the progress of // that process. Value Description 1 // Set this bit to commit (write) // the register value to a // Flash-memory-resident register. // When read a 1 indicates that the // previous commit access is not // complete. 0 A write of 0 has no // effect on the state of this bit. // When read a 0 indicates that the // previous commit access is // complete. #define FLASH_CTRL_FMC_MERASE1 0x00000004 // Mass Erase Flash Memory This bit // is used to mass erase the Flash // main memory and to monitor the // progress of that process. Value // Description 1 Set this bit to // erase the Flash main memory. When // read a 1 indicates that the // previous mass erase access is not // complete. 0 A write of 0 has no // effect on the state of this bit. // When read a 0 indicates that the // previous mass erase access is // complete. #define FLASH_CTRL_FMC_ERASE 0x00000002 // Erase a Page of Flash Memory // This bit is used to erase a page // of Flash memory and to monitor // the progress of that process. // Value Description 1 Set this bit // to erase the Flash memory page // specified by the contents of the // FMA register. When read a 1 // indicates that the previous page // erase access is not complete. 0 A // write of 0 has no effect on the // state of this bit. When read a 0 // indicates that the previous page // erase access is complete. #define FLASH_CTRL_FMC_WRITE 0x00000001 // Write a Word into Flash Memory // This bit is used to write a word // into Flash memory and to monitor // the progress of that process. // Value Description 1 Set this bit // to write the data stored in the // FMD register into the Flash // memory location specified by the // contents of the FMA register. // When read a 1 indicates that the // write update access is not // complete. 0 A write of 0 has no // effect on the state of this bit. // When read a 0 indicates that the // previous write update access is // complete. //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FCRIS register. // //****************************************************************************** #define FLASH_CTRL_FCRIS_PROGRIS \ 0x00002000 // Program Verify Error Raw // Interrupt Status Value // Description 1 An interrupt is // pending because the verify of a // PROGRAM operation failed. 0 An // interrupt has not occurred. This // bit is cleared by writing a 1 to // the PROGMISC bit in the FCMISC // register. #define FLASH_CTRL_FCRIS_ERRIS 0x00000800 // Erase Verify Error Raw Interrupt // Status Value Description 1 An // interrupt is pending because the // verify of an ERASE operation // failed. 0 An interrupt has not // occurred. This bit is cleared by // writing a 1 to the ERMISC bit in // the FCMISC register. #define FLASH_CTRL_FCRIS_INVDRIS \ 0x00000400 // Invalid Data Raw Interrupt // Status Value Description 1 An // interrupt is pending because a // bit that was previously // programmed as a 0 is now being // requested to be programmed as a // 1. 0 An interrupt has not // occurred. This bit is cleared by // writing a 1 to the INVMISC bit in // the FCMISC register. #define FLASH_CTRL_FCRIS_VOLTRIS \ 0x00000200 // Pump Voltage Raw Interrupt // Status Value Description 1 An // interrupt is pending because the // regulated voltage of the pump // went out of spec during the Flash // operation and the operation was // terminated. 0 An interrupt has // not occurred. This bit is cleared // by writing a 1 to the VOLTMISC // bit in the FCMISC register. #define FLASH_CTRL_FCRIS_ERIS 0x00000004 // EEPROM Raw Interrupt Status This // bit provides status EEPROM // operation. Value Description 1 An // EEPROM interrupt has occurred. 0 // An EEPROM interrupt has not // occurred. This bit is cleared by // writing a 1 to the EMISC bit in // the FCMISC register. #define FLASH_CTRL_FCRIS_PRIS 0x00000002 // Programming Raw Interrupt Status // This bit provides status on // programming cycles which are // write or erase actions generated // through the FMC or FMC2 register // bits (see page 537 and page 549). // Value Description 1 The // programming or erase cycle has // completed. 0 The programming or // erase cycle has not completed. // This status is sent to the // interrupt controller when the // PMASK bit in the FCIM register is // set. This bit is cleared by // writing a 1 to the PMISC bit in // the FCMISC register. #define FLASH_CTRL_FCRIS_ARIS 0x00000001 // Access Raw Interrupt Status // Value Description 1 A program or // erase action was attempted on a // block of Flash memory that // contradicts the protection policy // for that block as set in the // FMPPEn registers. 0 No access has // tried to improperly program or // erase the Flash memory. This // status is sent to the interrupt // controller when the AMASK bit in // the FCIM register is set. This // bit is cleared by writing a 1 to // the AMISC bit in the FCMISC // register. //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FCIM register. // //****************************************************************************** #define FLASH_CTRL_FCIM_ILLMASK 0x00004000 // Illegal Address Interrupt Mask // Value Description 1 An interrupt // is sent to the interrupt // controller when the ILLARIS bit // is set. 0 The ILLARIS interrupt // is suppressed and not sent to the // interrupt controller. #define FLASH_CTRL_FCIM_PROGMASK \ 0x00002000 // PROGVER Interrupt Mask Value // Description 1 An interrupt is // sent to the interrupt controller // when the PROGRIS bit is set. 0 // The PROGRIS interrupt is // suppressed and not sent to the // interrupt controller. #define FLASH_CTRL_FCIM_PREMASK 0x00001000 // PREVER Interrupt Mask Value // Description 1 An interrupt is // sent to the interrupt controller // when the PRERIS bit is set. 0 The // PRERIS interrupt is suppressed // and not sent to the interrupt // controller. #define FLASH_CTRL_FCIM_ERMASK 0x00000800 // ERVER Interrupt Mask Value // Description 1 An interrupt is // sent to the interrupt controller // when the ERRIS bit is set. 0 The // ERRIS interrupt is suppressed and // not sent to the interrupt // controller. #define FLASH_CTRL_FCIM_INVDMASK \ 0x00000400 // Invalid Data Interrupt Mask // Value Description 1 An interrupt // is sent to the interrupt // controller when the INVDRIS bit // is set. 0 The INVDRIS interrupt // is suppressed and not sent to the // interrupt controller. #define FLASH_CTRL_FCIM_VOLTMASK \ 0x00000200 // VOLT Interrupt Mask Value // Description 1 An interrupt is // sent to the interrupt controller // when the VOLTRIS bit is set. 0 // The VOLTRIS interrupt is // suppressed and not sent to the // interrupt controller. #define FLASH_CTRL_FCIM_LOCKMASK \ 0x00000100 // LOCK Interrupt Mask Value // Description 1 An interrupt is // sent to the interrupt controller // when the LOCKRIS bit is set. 0 // The LOCKRIS interrupt is // suppressed and not sent to the // interrupt controller. #define FLASH_CTRL_FCIM_EMASK 0x00000004 // EEPROM Interrupt Mask Value // Description 1 An interrupt is // sent to the interrupt controller // when the ERIS bit is set. 0 The // ERIS interrupt is suppressed and // not sent to the interrupt // controller. #define FLASH_CTRL_FCIM_PMASK 0x00000002 // Programming Interrupt Mask This // bit controls the reporting of the // programming raw interrupt status // to the interrupt controller. // Value Description 1 An interrupt // is sent to the interrupt // controller when the PRIS bit is // set. 0 The PRIS interrupt is // suppressed and not sent to the // interrupt controller. #define FLASH_CTRL_FCIM_AMASK 0x00000001 // Access Interrupt Mask This bit // controls the reporting of the // access raw interrupt status to // the interrupt controller. Value // Description 1 An interrupt is // sent to the interrupt controller // when the ARIS bit is set. 0 The // ARIS interrupt is suppressed and // not sent to the interrupt // controller. //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FCMISC register. // //****************************************************************************** #define FLASH_CTRL_FCMISC_ILLMISC \ 0x00004000 // Illegal Address Masked Interrupt // Status and Clear Value // Description 1 When read a 1 // indicates that an unmasked // interrupt was signaled. Writing a // 1 to this bit clears ILLAMISC and // also the ILLARIS bit in the FCRIS // register (see page 540). 0 When // read a 0 indicates that an // interrupt has not occurred. A // write of 0 has no effect on the // state of this bit. #define FLASH_CTRL_FCMISC_PROGMISC \ 0x00002000 // PROGVER Masked Interrupt Status // and Clear Value Description 1 // When read a 1 indicates that an // unmasked interrupt was signaled. // Writing a 1 to this bit clears // PROGMISC and also the PROGRIS bit // in the FCRIS register (see page // 540). 0 When read a 0 indicates // that an interrupt has not // occurred. A write of 0 has no // effect on the state of this bit. #define FLASH_CTRL_FCMISC_PREMISC \ 0x00001000 // PREVER Masked Interrupt Status // and Clear Value Description 1 // When read a 1 indicates that an // unmasked interrupt was signaled. // Writing a 1 to this bit clears // PREMISC and also the PRERIS bit // in the FCRIS register . 0 When // read a 0 indicates that an // interrupt has not occurred. A // write of 0 has no effect on the // state of this bit. #define FLASH_CTRL_FCMISC_ERMISC \ 0x00000800 // ERVER Masked Interrupt Status // and Clear Value Description 1 // When read a 1 indicates that an // unmasked interrupt was signaled. // Writing a 1 to this bit clears // ERMISC and also the ERRIS bit in // the FCRIS register 0 When read a // 0 indicates that an interrupt has // not occurred. A write of 0 has no // effect on the state of this bit. #define FLASH_CTRL_FCMISC_INVDMISC \ 0x00000400 // Invalid Data Masked Interrupt // Status and Clear Value // Description 1 When read a 1 // indicates that an unmasked // interrupt was signaled. Writing a // 1 to this bit clears INVDMISC and // also the INVDRIS bit in the FCRIS // register (see page 540). 0 When // read a 0 indicates that an // interrupt has not occurred. A // write of 0 has no effect on the // state of this bit. #define FLASH_CTRL_FCMISC_VOLTMISC \ 0x00000200 // VOLT Masked Interrupt Status and // Clear Value Description 1 When // read a 1 indicates that an // unmasked interrupt was signaled. // Writing a 1 to this bit clears // VOLTMISC and also the VOLTRIS bit // in the FCRIS register (see page // 540). 0 When read a 0 indicates // that an interrupt has not // occurred. A write of 0 has no // effect on the state of this bit. #define FLASH_CTRL_FCMISC_LOCKMISC \ 0x00000100 // LOCK Masked Interrupt Status and // Clear Value Description 1 When // read a 1 indicates that an // unmasked interrupt was signaled. // Writing a 1 to this bit clears // LOCKMISC and also the LOCKRIS bit // in the FCRIS register (see page // 540). 0 When read a 0 indicates // that an interrupt has not // occurred. A write of 0 has no // effect on the state of this bit. #define FLASH_CTRL_FCMISC_EMISC 0x00000004 // EEPROM Masked Interrupt Status // and Clear Value Description 1 // When read a 1 indicates that an // unmasked interrupt was signaled. // Writing a 1 to this bit clears // EMISC and also the ERIS bit in // the FCRIS register 0 When read a // 0 indicates that an interrupt has // not occurred. A write of 0 has no // effect on the state of this bit. #define FLASH_CTRL_FCMISC_PMISC 0x00000002 // Programming Masked Interrupt // Status and Clear Value // Description 1 When read a 1 // indicates that an unmasked // interrupt was signaled because a // programming cycle completed. // Writing a 1 to this bit clears // PMISC and also the PRIS bit in // the FCRIS register 0 When read a // 0 indicates that a programming // cycle complete interrupt has not // occurred. A write of 0 has no // effect on the state of this bit. #define FLASH_CTRL_FCMISC_AMISC 0x00000001 // Access Masked Interrupt Status // and Clear Value Description 1 // When read a 1 indicates that an // unmasked interrupt was signaled // because a program or erase action // was attempted on a block of Flash // memory that contradicts the // protection policy for that block // as set in the FMPPEn registers. // Writing a 1 to this bit clears // AMISC and also the ARIS bit in // the FCRIS register 0 When read a // 0 indicates that no improper // accesses have occurred. A write // of 0 has no effect on the state // of this bit. //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FMC2 register. // //****************************************************************************** #define FLASH_CTRL_FMC2_WRKEY_M 0xFFFF0000 // Flash Memory Write Key This // field contains a write key which // is used to minimize the incidence // of accidental Flash memory // writes. The value 0xA442 must be // written into this field for a // write to occur. Writes to the // FMC2 register without this WRKEY // value are ignored. A read of this // field returns the value 0. #define FLASH_CTRL_FMC2_WRKEY_S 16 #define FLASH_CTRL_FMC2_WRBUF 0x00000001 // Buffered Flash Memory Write This // bit is used to start a buffered // write to Flash memory. Value // Description 1 Set this bit to // write the data stored in the FWBn // registers to the location // specified by the contents of the // FMA register. When read a 1 // indicates that the previous // buffered Flash memory write // access is not complete. 0 A write // of 0 has no effect on the state // of this bit. When read a 0 // indicates that the previous // buffered Flash memory write // access is complete. //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWBVAL register. // //****************************************************************************** #define FLASH_CTRL_FWBVAL_FWBN_M \ 0xFFFFFFFF // Flash Memory Write Buffer Value // Description 1 The corresponding // FWBn register has been updated // since the last buffer write // operation and is ready to be // written to Flash memory. 0 The // corresponding FWBn register has // no new data to be written. Bit 0 // corresponds to FWB0 offset 0x100 // and bit 31 corresponds to FWB31 // offset 0x13C. #define FLASH_CTRL_FWBVAL_FWBN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB1 register. // //****************************************************************************** #define FLASH_CTRL_FWB1_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB1_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB2 register. // //****************************************************************************** #define FLASH_CTRL_FWB2_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB2_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB3 register. // //****************************************************************************** #define FLASH_CTRL_FWB3_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB3_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB4 register. // //****************************************************************************** #define FLASH_CTRL_FWB4_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB4_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB5 register. // //****************************************************************************** #define FLASH_CTRL_FWB5_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB5_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB6 register. // //****************************************************************************** #define FLASH_CTRL_FWB6_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB6_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB7 register. // //****************************************************************************** #define FLASH_CTRL_FWB7_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB7_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB8 register. // //****************************************************************************** #define FLASH_CTRL_FWB8_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB8_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the FLASH_CTRL_O_FWB9 register. // //****************************************************************************** #define FLASH_CTRL_FWB9_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB9_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB10 register. // //****************************************************************************** #define FLASH_CTRL_FWB10_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB10_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB11 register. // //****************************************************************************** #define FLASH_CTRL_FWB11_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB11_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB12 register. // //****************************************************************************** #define FLASH_CTRL_FWB12_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB12_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB13 register. // //****************************************************************************** #define FLASH_CTRL_FWB13_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB13_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB14 register. // //****************************************************************************** #define FLASH_CTRL_FWB14_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB14_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB15 register. // //****************************************************************************** #define FLASH_CTRL_FWB15_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB15_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB16 register. // //****************************************************************************** #define FLASH_CTRL_FWB16_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB16_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB17 register. // //****************************************************************************** #define FLASH_CTRL_FWB17_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB17_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB18 register. // //****************************************************************************** #define FLASH_CTRL_FWB18_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB18_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB19 register. // //****************************************************************************** #define FLASH_CTRL_FWB19_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB19_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB20 register. // //****************************************************************************** #define FLASH_CTRL_FWB20_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB20_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB21 register. // //****************************************************************************** #define FLASH_CTRL_FWB21_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB21_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB22 register. // //****************************************************************************** #define FLASH_CTRL_FWB22_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB22_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB23 register. // //****************************************************************************** #define FLASH_CTRL_FWB23_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB23_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB24 register. // //****************************************************************************** #define FLASH_CTRL_FWB24_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB24_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB25 register. // //****************************************************************************** #define FLASH_CTRL_FWB25_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB25_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB26 register. // //****************************************************************************** #define FLASH_CTRL_FWB26_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB26_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB27 register. // //****************************************************************************** #define FLASH_CTRL_FWB27_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB27_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB28 register. // //****************************************************************************** #define FLASH_CTRL_FWB28_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB28_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB29 register. // //****************************************************************************** #define FLASH_CTRL_FWB29_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB29_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB30 register. // //****************************************************************************** #define FLASH_CTRL_FWB30_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB30_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB31 register. // //****************************************************************************** #define FLASH_CTRL_FWB31_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB31_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FWB32 register. // //****************************************************************************** #define FLASH_CTRL_FWB32_DATA_M 0xFFFFFFFF // Data Data to be written into the // Flash memory. #define FLASH_CTRL_FWB32_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_FSIZE register. // //****************************************************************************** #define FLASH_CTRL_FSIZE_SIZE_M 0x0000FFFF // Flash Size Indicates the size of // the on-chip Flash memory. Value // Description 0x0003 8 KB of Flash // 0x0007 16 KB of Flash 0x000F 32 // KB of Flash 0x001F 64 KB of Flash // 0x002F 96 KB of Flash 0x003F 128 // KB of Flash 0x005F 192 KB of // Flash 0x007F 256 KB of Flash #define FLASH_CTRL_FSIZE_SIZE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // FLASH_CTRL_O_SSIZE register. // //****************************************************************************** #define FLASH_CTRL_SSIZE_SRAM_SIZE_M \ 0x0000FFFF // SRAM Size Indicates the size of // the on-chip SRAM. Value // Description 0x0007 2 KB of SRAM // 0x000F 4 KB of SRAM 0x0017 6 KB // of SRAM 0x001F 8 KB of SRAM // 0x002F 12 KB of SRAM 0x003F 16 KB // of SRAM 0x004F 20 KB of SRAM // 0x005F 24 KB of SRAM 0x007F 32 KB // of SRAM #define FLASH_CTRL_SSIZE_SRAM_SIZE_S 0 #define FLASH_CTRL_FMC_WRKEY 0xA4420000 // FLASH write key #define FLASH_CTRL_FMC2_WRKEY 0xA4420000 // FLASH write key #define FLASH_CTRL_O_FWBN FLASH_CTRL_O_FWB1 #define FLASH_ERASE_SIZE 0x00000400 #define FLASH_PROTECT_SIZE 0x00000800 #define FLASH_FMP_BLOCK_0 0x00000001 // Enable for block 0 #define FLASH_FMPRE0 0x400FE200 // Flash Memory Protection Read // Enable 0 #define FLASH_FMPRE1 0x400FE204 // Flash Memory Protection Read // Enable 1 #define FLASH_FMPRE2 0x400FE208 // Flash Memory Protection Read // Enable 2 #define FLASH_FMPRE3 0x400FE20C // Flash Memory Protection Read // Enable 3 #define FLASH_FMPRE4 0x400FE210 // Flash Memory Protection Read // Enable 4 #define FLASH_FMPRE5 0x400FE214 // Flash Memory Protection Read // Enable 5 #define FLASH_FMPRE6 0x400FE218 // Flash Memory Protection Read // Enable 6 #define FLASH_FMPRE7 0x400FE21C // Flash Memory Protection Read // Enable 7 #define FLASH_FMPRE8 0x400FE220 // Flash Memory Protection Read // Enable 8 #define FLASH_FMPRE9 0x400FE224 // Flash Memory Protection Read // Enable 9 #define FLASH_FMPRE10 0x400FE228 // Flash Memory Protection Read // Enable 10 #define FLASH_FMPRE11 0x400FE22C // Flash Memory Protection Read // Enable 11 #define FLASH_FMPRE12 0x400FE230 // Flash Memory Protection Read // Enable 12 #define FLASH_FMPRE13 0x400FE234 // Flash Memory Protection Read // Enable 13 #define FLASH_FMPRE14 0x400FE238 // Flash Memory Protection Read // Enable 14 #define FLASH_FMPRE15 0x400FE23C // Flash Memory Protection Read // Enable 15 #define FLASH_FMPPE0 0x400FE400 // Flash Memory Protection Program // Enable 0 #define FLASH_FMPPE1 0x400FE404 // Flash Memory Protection Program // Enable 1 #define FLASH_FMPPE2 0x400FE408 // Flash Memory Protection Program // Enable 2 #define FLASH_FMPPE3 0x400FE40C // Flash Memory Protection Program // Enable 3 #define FLASH_FMPPE4 0x400FE410 // Flash Memory Protection Program // Enable 4 #define FLASH_FMPPE5 0x400FE414 // Flash Memory Protection Program // Enable 5 #define FLASH_FMPPE6 0x400FE418 // Flash Memory Protection Program // Enable 6 #define FLASH_FMPPE7 0x400FE41C // Flash Memory Protection Program // Enable 7 #define FLASH_FMPPE8 0x400FE420 // Flash Memory Protection Program // Enable 8 #define FLASH_FMPPE9 0x400FE424 // Flash Memory Protection Program // Enable 9 #define FLASH_FMPPE10 0x400FE428 // Flash Memory Protection Program // Enable 10 #define FLASH_FMPPE11 0x400FE42C // Flash Memory Protection Program // Enable 11 #define FLASH_FMPPE12 0x400FE430 // Flash Memory Protection Program // Enable 12 #define FLASH_FMPPE13 0x400FE434 // Flash Memory Protection Program // Enable 13 #define FLASH_FMPPE14 0x400FE438 // Flash Memory Protection Program // Enable 14 #define FLASH_FMPPE15 0x400FE43C // Flash Memory Protection Program // Enable 15 #define FLASH_USECRL 0x400FE140 // USec Reload #define FLASH_CTRL_ERASE_SIZE 0x00000400 #endif // __HW_FLASH_CTRL_H__ micropython-1.12/ports/cc3200/hal/inc/hw_gpio.h000066400000000000000000002640751357706137100212230ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_GPIO_H__ #define __HW_GPIO_H__ //***************************************************************************** // // The following are defines for the GPIO register offsets. // //***************************************************************************** #define GPIO_O_GPIO_DATA 0x00000000 // 0x4000 5000 0x4000 6000 0x4000 // 7000 0x4002 4000 GPIO Data // (GPIODATA)@@ offset 0x000 The // GPIODATA register is the data // register. In software control // mode@@ values written in the // GPIODATA register are transferred // onto the GPIO port pins if the // respective pins have been // configured as outputs through the // GPIO Direction (GPIODIR) register // (see page 653). In order to write // to GPIODATA@@ the corresponding // bits in the mask@@ resulting from // the address bus bits [9:2]@@ must // be set. Otherwise@@ the bit // values remain unchanged by the // write. Similarly@@ the values // read from this register are // determined for each bit by the // mask bit derived from the address // used to access the data // register@@ bits [9:2]. Bits that // are set in the address mask cause // the corresponding bits in // GPIODATA to be read@@ and bits // that are clear in the address // mask cause the corresponding bits // in GPIODATA to be read as 0@@ // regardless of their value. A read // from GPIODATA returns the last // bit value written if the // respective pins are configured as // outputs@@ or it returns the value // on the corresponding input pin // when these are configured as // inputs. All bits are cleared by a // reset. #define GPIO_O_GPIO_DIR 0x00000400 // 0x4000 5400 0x4000 6400 0x4000 // 7400 0x4002 4400 GPIO Direction // (GPIODIR)@@ offset 0x400 The // GPIODIR register is the data // direction register. Setting a bit // in the GPIODIR register // configures the corresponding pin // to be an output@@ while clearing // a bit configures the // corresponding pin to be an input. // All bits are cleared by a reset@@ // meaning all GPIO pins are inputs // by default. #define GPIO_O_GPIO_IS 0x00000404 // 0x4000 5404 0x4000 6404 0x4000 // 7404 0x4002 4404 GPIO Interrupt // Sense (GPIOIS)@@ offset 0x404 The // GPIOIS register is the interrupt // sense register. Setting a bit in // the GPIOIS register configures // the corresponding pin to detect // levels@@ while clearing a bit // configures the corresponding pin // to detect edges. All bits are // cleared by a reset. #define GPIO_O_GPIO_IBE 0x00000408 // 0x4000 5408 0x4000 6408 0x4000 // 7408 0x4002 4408 GPIO Interrupt // Both Edges (GPIOIBE)@@ offset // 0x408 The GPIOIBE register allows // both edges to cause interrupts. // When the corresponding bit in the // GPIO Interrupt Sense (GPIOIS) // register is set to detect edges@@ // setting a bit in the GPIOIBE // register configures the // corresponding pin to detect both // rising and falling edges@@ // regardless of the corresponding // bit in the GPIO Interrupt Event // (GPIOIEV) register . Clearing a // bit configures the pin to be // controlled by the GPIOIEV // register. All bits are cleared by // a reset. #define GPIO_O_GPIO_IEV 0x0000040C // 0x4000 540C 0x4000 640C 0x4000 // 740C 0x4002 440C GPIO Interrupt // Event (GPIOIEV)@@ offset 0x40C // The GPIOIEV register is the // interrupt event register. Setting // a bit in the GPIOIEV register // configures the corresponding pin // to detect rising edges or high // levels@@ depending on the // corresponding bit value in the // GPIO Interrupt Sense (GPIOIS) // register . Clearing a bit // configures the pin to detect // falling edges or low levels@@ // depending on the corresponding // bit value in the GPIOIS register. // All bits are cleared by a reset. #define GPIO_O_GPIO_IM 0x00000410 // 0x4000 5410 0x4000 6410 0x4000 // 7410 0x4002 4410 GPIO Interrupt // Mask (GPIOIM)@@ offset 0x410 The // GPIOIM register is the interrupt // mask register. Setting a bit in // the GPIOIM register allows // interrupts that are generated by // the corresponding pin to be sent // to the interrupt controller on // the combined interrupt signal. // Clearing a bit prevents an // interrupt on the corresponding // pin from being sent to the // interrupt controller. All bits // are cleared by a reset. #define GPIO_O_GPIO_RIS 0x00000414 // 0x4000 5414 0x4000 6414 0x4000 // 7414 0x4002 4414 GPIO Raw // Interrupt Status (GPIORIS)@@ // offset 0x414 The GPIORIS register // is the raw interrupt status // register. A bit in this register // is set when an interrupt // condition occurs on the // corresponding GPIO pin. If the // corresponding bit in the GPIO // Interrupt Mask (GPIOIM) register // is set@@ the interrupt is sent to // the interrupt controller. Bits // read as zero indicate that // corresponding input pins have not // initiated an interrupt. A bit in // this register can be cleared by // writing a 1 to the corresponding // bit in the GPIO Interrupt Clear // (GPIOICR) register. #define GPIO_O_GPIO_MIS 0x00000418 // 0x4000 5418 0x4000 6418 0x4000 // 7418 0x4002 4418 GPIO Masked // Interrupt Status (GPIOMIS)@@ // offset 0x418 The GPIOMIS register // is the masked interrupt status // register. If a bit is set in this // register@@ the corresponding // interrupt has triggered an // interrupt to the interrupt // controller. If a bit is clear@@ // either no interrupt has been // generated@@ or the interrupt is // masked. If no port pin@@ other // than the one that is being used // as an ADC trigger@@ is being used // to generate interrupts@@ the // appropriate Interrupt Set Enable // (ENn) register can disable the // interrupts for the port@@ and the // ADC interrupt can be used to read // back the converted data. // Otherwise@@ the port interrupt // handler must ignore and clear // interrupts on the port pin and // wait for the ADC interrupt@@ or // the ADC interrupt must be // disabled in the EN0 register and // the port interrupt handler must // poll the ADC registers until the // conversion is completed. If no // port pin@@ other than the one // that is being used as an ADC // trigger@@ is being used to // generate interrupts@@ the // appropriate Interrupt Set Enable // (ENn) register can disable the // interrupts for the port@@ and the // ADC interrupt can be used to read // back the converted data. // Otherwise@@ the port interrupt // handler must ignore and clear // interrupts on the port pin and // wait for the ADC interrupt@@ or // the ADC interrupt must be // disabled in the EN0 register and // the port interrupt handler must // poll the ADC registers until the // conversion is completed. Note // that if the Port B GPIOADCCTL // register is cleared@@ PB4 can // still be used as an external // trigger for the ADC. This is a // legacy mode which allows code // written for previous Stellaris // devices to operate on this // microcontroller. GPIOMIS is the // state of the interrupt after // masking. #define GPIO_O_GPIO_ICR 0x0000041C // 0x4000 541C 0x4000 641C 0x4000 // 741C 0x4002 441C GPIO Interrupt // Clear (GPIOICR)@@ offset 0x41C // The GPIOICR register is the // interrupt clear register. Writing // a 1 to a bit in this register // clears the corresponding // interrupt bit in the GPIORIS and // GPIOMIS registers. Writing a 0 // has no effect. #define GPIO_O_GPIO_AFSEL 0x00000420 // 0x4000 5420 0x4000 6420 0x4000 // 7420 0x4002 4420 GPIO Alternate // Function Select (GPIOAFSEL)@@ // offset 0x420 The GPIOAFSEL // register is the mode control // select register. If a bit is // clear@@ the pin is used as a GPIO // and is controlled by the GPIO // registers. Setting a bit in this // register configures the // corresponding GPIO line to be // controlled by an associated // peripheral. Several possible // peripheral functions are // multiplexed on each GPIO. The // GPIO Port Control (GPIOPCTL) // register is used to select one of // the possible functions. #define GPIO_O_GPIO_DR2R 0x00000500 // 0x4000 5500 0x4000 6500 0x4000 // 7500 0x4002 4500 GPIO 2-mA Drive // Select (GPIODR2R)@@ offset 0x500 // The GPIODR2R register is the 2-mA // drive control register. Each GPIO // signal in the port can be // individually configured without // affecting the other pads. When // setting the DRV2 bit for a GPIO // signal@@ the corresponding DRV4 // bit in the GPIODR4R register and // DRV8 bit in the GPIODR8R register // are automatically cleared by // hardware. By default@@ all GPIO // pins have 2-mA drive. #define GPIO_O_GPIO_DR4R 0x00000504 // 0x4000 5504 0x4000 6504 0x4000 // 7504 0x4002 4504 GPIO 4-mA Drive // Select (GPIODR4R)@@ offset 0x504 // The GPIODR4R register is the 4-mA // drive control register. Each GPIO // signal in the port can be // individually configured without // affecting the other pads. When // setting the DRV4 bit for a GPIO // signal@@ the corresponding DRV2 // bit in the GPIODR2R register and // DRV8 bit in the GPIODR8R register // are automatically cleared by // hardware. #define GPIO_O_GPIO_DR8R 0x00000508 // 0x4000 5508 0x4000 6508 0x4000 // 7508 0x4002 4508 GPIO 8-mA Drive // Select (GPIODR8R)@@ offset 0x508 // The GPIODR8R register is the 8-mA // drive control register. Each GPIO // signal in the port can be // individually configured without // affecting the other pads. When // setting the DRV8 bit for a GPIO // signal@@ the corresponding DRV2 // bit in the GPIODR2R register and // DRV4 bit in the GPIODR4R register // are automatically cleared by // hardware. The 8-mA setting is // also used for high-current // operation. Note: There is no // configuration difference between // 8-mA and high-current operation. // The additional current capacity // results from a shift in the // VOH/VOL levels. #define GPIO_O_GPIO_ODR 0x0000050C // 0x4000 550C 0x4000 650C 0x4000 // 750C 0x4002 450C GPIO Open Drain // Select (GPIOODR)@@ offset 0x50C // The GPIOODR register is the open // drain control register. Setting a // bit in this register enables the // open-drain configuration of the // corresponding GPIO pad. When // open-drain mode is enabled@@ the // corresponding bit should also be // set in the GPIO Digital Input // Enable (GPIODEN) register . // Corresponding bits in the drive // strength and slew rate control // registers (GPIODR2R@@ GPIODR4R@@ // GPIODR8R@@ and GPIOSLR) can be // set to achieve the desired rise // and fall times. The GPIO acts as // an open-drain input if the // corresponding bit in the GPIODIR // register is cleared. If open // drain is selected while the GPIO // is configured as an input@@ the // GPIO will remain an input and the // open-drain selection has no // effect until the GPIO is changed // to an output. When using the I2C // module@@ in addition to // configuring the pin to open // drain@@ the GPIO Alternate // Function Select (GPIOAFSEL) // register bits for the I2C clock // and data pins should be set #define GPIO_O_GPIO_PUR 0x00000510 // 0x4000 5510 0x4000 6510 0x4000 // 7510 0x4002 4510 GPIO Pull-Up // Select (GPIOPUR)@@ offset 0x510 // The GPIOPUR register is the // pull-up control register. When a // bit is set@@ a weak pull-up // resistor on the corresponding // GPIO signal is enabled. Setting a // bit in GPIOPUR automatically // clears the corresponding bit in // the GPIO Pull-Down Select // (GPIOPDR) register . Write access // to this register is protected // with the GPIOCR register. Bits in // GPIOCR that are cleared prevent // writes to the equivalent bit in // this register. #define GPIO_O_GPIO_PDR 0x00000514 // 0x4000 5514 0x4000 6514 0x4000 // 7514 0x4002 4514 GPIO Pull-Down // Select (GPIOPDR)@@ offset 0x514 // The GPIOPDR register is the // pull-down control register. When // a bit is set@@ a weak pull-down // resistor on the corresponding // GPIO signal is enabled. Setting a // bit in GPIOPDR automatically // clears the corresponding bit in // the GPIO Pull-Up Select (GPIOPUR) // register #define GPIO_O_GPIO_SLR 0x00000518 // 0x4000 5518 0x4000 6518 0x4000 // 7518 0x4002 4518 The GPIOSLR // register is the slew rate control // register. Slew rate control is // only available when using the // 8-mA drive strength option via // the GPIO 8-mA Drive Select // (GPIODR8R) register #define GPIO_O_GPIO_DEN 0x0000051C // 0x4000 551C 0x4000 651C 0x4000 // 751C 0x4002 451C GPIO Digital // Enable (GPIODEN)@@ offset 0x51C // Note: Pins configured as digital // inputs are Schmitt-triggered. The // GPIODEN register is the digital // enable register. By default@@ all // GPIO signals except those listed // below are configured out of reset // to be undriven (tristate). Their // digital function is disabled; // they do not drive a logic value // on the pin and they do not allow // the pin voltage into the GPIO // receiver. To use the pin as a // digital input or output (either // GPIO or alternate function)@@ the // corresponding GPIODEN bit must be // set. #define GPIO_O_GPIO_LOCK 0x00000520 // 0x4000 5520 0x4000 6520 0x4000 // 7520 0x4002 4520 GPIO Lock // (GPIOLOCK)@@ offset 0x520 The // GPIOLOCK register enables write // access to the GPIOCR register . // Writing 0x4C4F.434B to the // GPIOLOCK register unlocks the // GPIOCR register. Writing any // other value to the GPIOLOCK // register re-enables the locked // state. Reading the GPIOLOCK // register returns the lock status // rather than the 32-bit value that // was previously written. // Therefore@@ when write accesses // are disabled@@ or locked@@ // reading the GPIOLOCK register // returns 0x0000.0001. When write // accesses are enabled@@ or // unlocked@@ reading the GPIOLOCK // register returns 0x0000.0000. #define GPIO_O_GPIO_CR 0x00000524 // 0x4000 5524 0x4000 6524 0x4000 // 7524 0x4002 4524 GPIO Commit // (GPIOCR)@@ offset 0x524 The // GPIOCR register is the commit // register. The value of the GPIOCR // register determines which bits of // the GPIOAFSEL@@ GPIOPUR@@ // GPIOPDR@@ and GPIODEN registers // are committed when a write to // these registers is performed. If // a bit in the GPIOCR register is // cleared@@ the data being written // to the corresponding bit in the // GPIOAFSEL@@ GPIOPUR@@ GPIOPDR@@ // or GPIODEN registers cannot be // committed and retains its // previous value. If a bit in the // GPIOCR register is set@@ the data // being written to the // corresponding bit of the // GPIOAFSEL@@ GPIOPUR@@ GPIOPDR@@ // or GPIODEN registers is committed // to the register and reflects the // new value. The contents of the // GPIOCR register can only be // modified if the status in the // GPIOLOCK register is unlocked. // Writes to the GPIOCR register are // ignored if the status in the // GPIOLOCK register is locked. #define GPIO_O_GPIO_AMSEL 0x00000528 // 0x4000 5528 0x4000 6528 0x4000 // 7528 0x4002 4528 The GPIOAMSEL // register controls isolation // circuits to the analog side of a // unified I/O pad. Because the // GPIOs may be driven by a 5-V // source and affect analog // operation@@ analog circuitry // requires isolation from the pins // when they are not used in their // analog function. Each bit of this // register controls the isolation // circuitry for the corresponding // GPIO signal. #define GPIO_O_GPIO_PCTL 0x0000052C // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) 0x4000 552C // 0x4000 652C 0x4000 752C 0x4002 // 452C GPIO Port Control // (GPIOPCTL)@@ offset 0x52C The // GPIOPCTL register is used in // conjunction with the GPIOAFSEL // register and selects the specific // peripheral signal for each GPIO // pin when using the alternate // function mode. Most bits in the // GPIOAFSEL register are cleared on // reset@@ therefore most GPIO pins // are configured as GPIOs by // default. When a bit is set in the // GPIOAFSEL register@@ the // corresponding GPIO signal is // controlled by an associated // peripheral. The GPIOPCTL register // selects one out of a set of // peripheral functions for each // GPIO@@ providing additional // flexibility in signal definition. #define GPIO_O_GPIO_ADCCTL 0x00000530 // This register is not used in // cc3xx. ADC trigger via GPIO is // not supported. 0x4000 5530 0x4000 // 6530 0x4000 7530 0x4002 4530 GPIO // ADC Control (GPIOADCCTL)@@ offset // 0x530 This register is used to // configure a GPIO pin as a source // for the ADC trigger. Note that if // the Port B GPIOADCCTL register is // cleared@@ PB4 can still be used // as an external trigger for the // ADC. This is a legacy mode which // allows code written for previous // Stellaris devices to operate on // this microcontroller. #define GPIO_O_GPIO_DMACTL 0x00000534 // 0x4000 5534 0x4000 6534 0x4000 // 7534 0x4002 4534 GPIO DMA Control // (GPIODMACTL)@@ offset 0x534 This // register is used to configure a // GPIO pin as a source for the ?DMA // trigger. #define GPIO_O_GPIO_SI 0x00000538 // 0x4000 5538 0x4000 6538 0x4000 // 7538 0x4002 4538 GPIO Select // Interrupt (GPIOSI)@@ offset 0x538 // This register is used to enable // individual interrupts for each // pin. Note: This register is only // available on Port P and Port Q. #define GPIO_O_GPIO_PERIPHID4 0x00000FD0 // 0x4000 5FD0 0x4000 6FD0 0x4000 // 7FD0 0x4002 4FD0 GPIO Peripheral // Identification 4 // (GPIOPeriphID4)@@ offset 0xFD0 // The GPIOPeriphID4@@ // GPIOPeriphID5@@ GPIOPeriphID6@@ // and GPIOPeriphID7 registers can // conceptually be treated as one // 32-bit register; each register // contains eight bits of the 32-bit // register@@ used by software to // identify the peripheral. #define GPIO_O_GPIO_PERIPHID5 0x00000FD4 // 0x4000 5FD4 0x4000 6FD4 0x4000 // 7FD4 0x4002 4FD4 GPIO Peripheral // Identification 5 // (GPIOPeriphID5)@@ offset 0xFD4 // The GPIOPeriphID4@@ // GPIOPeriphID5@@ GPIOPeriphID6@@ // and GPIOPeriphID7 registers can // conceptually be treated as one // 32-bit register; each register // contains eight bits of the 32-bit // register@@ used by software to // identify the peripheral. #define GPIO_O_GPIO_PERIPHID6 0x00000FD8 // 0x4000 5FD8 0x4000 6FD8 0x4000 // 7FD8 0x4002 4FD8 GPIO Peripheral // Identification 6 // (GPIOPeriphID6)@@ offset 0xFD8 // The GPIOPeriphID4@@ // GPIOPeriphID5@@ GPIOPeriphID6@@ // and GPIOPeriphID7 registers can // conceptually be treated as one // 32-bit register; each register // contains eight bits of the 32-bit // register@@ used by software to // identify the peripheral. #define GPIO_O_GPIO_PERIPHID7 0x00000FDC // 0x4000 5FDC 0x4000 6FDC 0x4000 // 7FDC 0x4002 4FDC GPIO Peripheral // Identification 7 // (GPIOPeriphID7)@@ offset 0xFDC // The GPIOPeriphID4@@ // GPIOPeriphID5@@ GPIOPeriphID6@@ // and GPIOPeriphID7 registers can // conceptually be treated as one // 32-bit register; each register // contains eight bits of the 32-bit // register@@ used by software to // identify the peripheral. #define GPIO_O_GPIO_PERIPHID0 0x00000FE0 // 0x4000 5FE0 0x4000 6FE0 0x4000 // 7FE0 0x4002 4FE0 GPIO Peripheral // Identification 0 // (GPIOPeriphID0)@@ offset 0xFE0 // The GPIOPeriphID0@@ // GPIOPeriphID1@@ GPIOPeriphID2@@ // and GPIOPeriphID3 registers can // conceptually be treated as one // 32-bit register; each register // contains eight bits of the 32-bit // register@@ used by software to // identify the peripheral. #define GPIO_O_GPIO_PERIPHID1 0x00000FE4 // 0x4000 5FE4 0x4000 6FE4 0x4000 // 7FE4 0x4002 4FE4 GPIO Peripheral // Identification 1 // (GPIOPeriphID1)@@ offset 0xFE4 // The GPIOPeriphID0@@ // GPIOPeriphID1@@ GPIOPeriphID2@@ // and GPIOPeriphID3 registers can // conceptually be treated as one // 32-bit register; each register // contains eight bits of the 32-bit // register@@ used by software to // identify the peripheral. #define GPIO_O_GPIO_PERIPHID2 0x00000FE8 // 0x4000 5FE8 0x4000 6FE8 0x4000 // 7FE8 0x4002 4FE8 GPIO Peripheral // Identification 2 // (GPIOPeriphID2)@@ offset 0xFE8 // The GPIOPeriphID0@@ // GPIOPeriphID1@@ GPIOPeriphID2@@ // and GPIOPeriphID3 registers can // conceptually be treated as one // 32-bit register; each register // contains eight bits of the 32-bit // register@@ used by software to // identify the peripheral. #define GPIO_O_GPIO_PERIPHID3 0x00000FEC // 0x4000 5FEC 0x4000 6FEC 0x4000 // 7FEC 0x4002 4FEC GPIO Peripheral // Identification 3 // (GPIOPeriphID3)@@ offset 0xFEC // The GPIOPeriphID0@@ // GPIOPeriphID1@@ GPIOPeriphID2@@ // and GPIOPeriphID3 registers can // conceptually be treated as one // 32-bit register; each register // contains eight bits of the 32-bit // register@@ used by software to // identify the peripheral. #define GPIO_O_GPIO_PCELLID0 0x00000FF0 // 0x4000 5FF0 0x4000 6FF0 0x4000 // 7FF0 0x4002 4FF0 GPIO PrimeCell // Identification 0 (GPIOPCellID0)@@ // offset 0xFF0 The GPIOPCellID0@@ // GPIOPCellID1@@ GPIOPCellID2@@ and // GPIOPCellID3 registers are four // 8-bit wide registers@@ that can // conceptually be treated as one // 32-bit register. The register is // used as a standard // cross-peripheral identification // system. #define GPIO_O_GPIO_PCELLID1 0x00000FF4 // 0x4000 5FF4 0x4000 6FF4 0x4000 // 7FF4 0x4002 4FF4 GPIO PrimeCell // Identification 1 (GPIOPCellID1)@@ // offset 0xFF4 The GPIOPCellID0@@ // GPIOPCellID1@@ GPIOPCellID2@@ and // GPIOPCellID3 registers are four // 8-bit wide registers@@ that can // conceptually be treated as one // 32-bit register. The register is // used as a standard // cross-peripheral identification // system. #define GPIO_O_GPIO_PCELLID2 0x00000FF8 // 0x4000 5FF8 0x4000 6FF8 0x4000 // 7FF8 0x4002 4FF8 GPIO PrimeCell // Identification 2 (GPIOPCellID2)@@ // offset 0xFF8 The GPIOPCellID0@@ // GPIOPCellID1@@ GPIOPCellID2@@ and // GPIOPCellID3 registers are four // 8-bit wide registers@@ that can // conceptually be treated as one // 32-bit register. The register is // used as a standard // cross-peripheral identification // system. #define GPIO_O_GPIO_PCELLID3 0x00000FFC // 0x4000 5FFC 0x4000 6FFC 0x4000 // 7FFC 0x4002 4FFC GPIO PrimeCell // Identification 3 (GPIOPCellID3)@@ // offset 0xFFC The GPIOPCellID0@@ // GPIOPCellID1@@ GPIOPCellID2@@ and // GPIOPCellID3 registers are four // 8-bit wide registers@@ that can // conceptually be treated as one // 32-bit register. The register is // used as a standard // cross-peripheral identification // system.0xb1 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_DATA register. // //****************************************************************************** #define GPIO_GPIO_DATA_DATA_M 0x000000FF // GPIO Data This register is // virtually mapped to 256 locations // in the address space. To // facilitate the reading and // writing of data to these // registers by independent // drivers@@ the data read from and // written to the registers are // masked by the eight address lines // [9:2]. Reads from this register // return its current state. Writes // to this register only affect bits // that are not masked by ADDR[9:2] // and are configured as outputs. #define GPIO_GPIO_DATA_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_DIR register. // //****************************************************************************** #define GPIO_GPIO_DIR_DIR_M 0x000000FF // GPIO Data Direction Value // Description 0 Corresponding pin // is an input. 1 Corresponding pins // is an output. #define GPIO_GPIO_DIR_DIR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_IS register. // //****************************************************************************** #define GPIO_GPIO_IS_IS_M 0x000000FF // GPIO Interrupt Sense Value // Description 0 The edge on the // corresponding pin is detected // (edge-sensitive). 1 The level on // the corresponding pin is detected // (level-sensitive). #define GPIO_GPIO_IS_IS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_IBE register. // //****************************************************************************** #define GPIO_GPIO_IBE_IBE_M 0x000000FF // GPIO Interrupt Both Edges Value // Description 0 Interrupt // generation is controlled by the // GPIO Interrupt Event (GPIOIEV) // register. 1 Both edges on the // corresponding pin trigger an // interrupt. #define GPIO_GPIO_IBE_IBE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_IEV register. // //****************************************************************************** #define GPIO_GPIO_IEV_IEV_M 0x000000FF // GPIO Interrupt Event Value // Description 1 A falling edge or a // Low level on the corresponding // pin triggers an interrupt. 0 A // rising edge or a High level on // the corresponding pin triggers an // interrupt. #define GPIO_GPIO_IEV_IEV_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_IM register. // //****************************************************************************** #define GPIO_GPIO_IM_IME_M 0x000000FF // GPIO Interrupt Mask Enable Value // Description 0 The interrupt from // the corresponding pin is masked. // 1 The interrupt from the // corresponding pin is sent to the // interrupt controller. #define GPIO_GPIO_IM_IME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_RIS register. // //****************************************************************************** #define GPIO_GPIO_RIS_RIS_M 0x000000FF // GPIO Interrupt Raw Status Value // Description 1 An interrupt // condition has occurred on the // corresponding pin. 0 interrupt // condition has not occurred on the // corresponding pin. A bit is // cleared by writing a 1 to the // corresponding bit in the GPIOICR // register. #define GPIO_GPIO_RIS_RIS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_MIS register. // //****************************************************************************** #define GPIO_GPIO_MIS_MIS_M 0x000000FF // GPIO Masked Interrupt Status // Value Description 1 An interrupt // condition on the corresponding // pin has triggered an interrupt to // the interrupt controller. 0 An // interrupt condition on the // corresponding pin is masked or // has not occurred. A bit is // cleared by writing a 1 to the // corresponding bit in the GPIOICR // register. #define GPIO_GPIO_MIS_MIS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_ICR register. // //****************************************************************************** #define GPIO_GPIO_ICR_IC_M 0x000000FF // GPIO Interrupt Clear Value // Description 1 The corresponding // interrupt is cleared. 0 The // corresponding interrupt is // unaffected. #define GPIO_GPIO_ICR_IC_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_AFSEL register. // //****************************************************************************** //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_DR2R register. // //****************************************************************************** #define GPIO_GPIO_DR2R_DRV2_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Output Pad // 2-mA Drive Enable Value // Description 1 The corresponding // GPIO pin has 2-mA drive. The // drive for the corresponding GPIO // pin is controlled by the GPIODR4R // or GPIODR8R register. 0 Setting a // bit in either the GPIODR4 // register or the GPIODR8 register // clears the corresponding 2-mA // enable bit. The change is // effective on the second clock // cycle after the write if // accessing GPIO via the APB memory // aperture. If using AHB access@@ // the change is effective on the // next clock cycle. #define GPIO_GPIO_DR2R_DRV2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_DR4R register. // //****************************************************************************** #define GPIO_GPIO_DR4R_DRV4_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Output Pad // 4-mA Drive Enable Value // Description 1 The corresponding // GPIO pin has 4-mA drive. The // drive for the corresponding GPIO // pin is controlled by the GPIODR2R // or GPIODR8R register. 0 Setting a // bit in either the GPIODR2 // register or the GPIODR8 register // clears the corresponding 4-mA // enable bit. The change is // effective on the second clock // cycle after the write if // accessing GPIO via the APB memory // aperture. If using AHB access@@ // the change is effective on the // next clock cycle. #define GPIO_GPIO_DR4R_DRV4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_DR8R register. // //****************************************************************************** #define GPIO_GPIO_DR8R_DRV8_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Output Pad // 8-mA Drive Enable Value // Description 1 The corresponding // GPIO pin has 8-mA drive. The // drive for the corresponding GPIO // pin is controlled by the GPIODR2R // or GPIODR4R register. 0 Setting a // bit in either the GPIODR2 // register or the GPIODR4 register // clears the corresponding 8-mA // enable bit. The change is // effective on the second clock // cycle after the write if // accessing GPIO via the APB memory // aperture. If using AHB access@@ // the change is effective on the // next clock cycle. #define GPIO_GPIO_DR8R_DRV8_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_ODR register. // //****************************************************************************** #define GPIO_GPIO_ODR_ODE_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Output Pad // Open Drain Enable Value // Description 1 The corresponding // pin is configured as open drain. // 0 The corresponding pin is not // configured as open drain. #define GPIO_GPIO_ODR_ODE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_PUR register. // //****************************************************************************** #define GPIO_GPIO_PUR_PUE_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Pad Weak // Pull-Up Enable Value Description // 1 The corresponding pin has a // weak pull-up resistor. 0 The // corresponding pin is not // affected. Setting a bit in the // GPIOPDR register clears the // corresponding bit in the GPIOPUR // register. The change is effective // on the second clock cycle after // the write if accessing GPIO via // the APB memory aperture. If using // AHB access@@ the change is // effective on the next clock // cycle. #define GPIO_GPIO_PUR_PUE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_PDR register. // //****************************************************************************** #define GPIO_GPIO_PDR_PDE_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Pad Weak // Pull-Down Enable Value // Description 1 The corresponding // pin has a weak pull-down // resistor. 0 The corresponding pin // is not affected. Setting a bit in // the GPIOPUR register clears the // corresponding bit in the GPIOPDR // register. The change is effective // on the second clock cycle after // the write if accessing GPIO via // the APB memory aperture. If using // AHB access@@ the change is // effective on the next clock // cycle. #define GPIO_GPIO_PDR_PDE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_SLR register. // //****************************************************************************** #define GPIO_GPIO_SLR_SRL_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Slew Rate // Limit Enable (8-mA drive only) // Value Description 1 Slew rate // control is enabled for the // corresponding pin. 0 Slew rate // control is disabled for the // corresponding pin. #define GPIO_GPIO_SLR_SRL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_DEN register. // //****************************************************************************** #define GPIO_GPIO_DEN_DEN_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Digital Enable // Value Description 0 The digital // functions for the corresponding // pin are disabled. 1 The digital // functions for the corresponding // pin are enabled. #define GPIO_GPIO_DEN_DEN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_LOCK register. // //****************************************************************************** #define GPIO_GPIO_LOCK_LOCK_M 0xFFFFFFFF // This register is not used in // cc3xx. GPIO Lock A write of the // value 0x4C4F.434B unlocks the // GPIO Commit (GPIOCR) register for // write access.A write of any other // value or a write to the GPIOCR // register reapplies the lock@@ // preventing any register updates. // A read of this register returns // the following values: Value // Description 0x1 The GPIOCR // register is locked and may not be // modified. 0x0 The GPIOCR register // is unlocked and may be modified. #define GPIO_GPIO_LOCK_LOCK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_CR register. // //****************************************************************************** #define GPIO_GPIO_CR_CR_M 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) GPIO Commit // Value Description The // corresponding GPIOAFSEL@@ // GPIOPUR@@ GPIOPDR@@ or GPIODEN // bits can be written. 1 The // corresponding GPIOAFSEL@@ // GPIOPUR@@ GPIOPDR@@ or GPIODEN // bits cannot be written. 0 Note: // The default register type for the // GPIOCR register is RO for all // GPIO pins with the exception of // the NMI pin and the four JTAG/SWD // pins (PD7@@ PF0@@ and PC[3:0]). // These six pins are the only GPIOs // that are protected by the GPIOCR // register. Because of this@@ the // register type for GPIO Port D7@@ // GPIO Port F0@@ and GPIO Port // C[3:0] is R/W. The default reset // value for the GPIOCR register is // 0x0000.00FF for all GPIO pins@@ // with the exception of the NMI pin // and the four JTAG/SWD pins (PD7@@ // PF0@@ and PC[3:0]). To ensure // that the JTAG port is not // accidentally programmed as GPIO // pins@@ the PC[3:0] pins default // to non-committable. Similarly@@ // to ensure that the NMI pin is not // accidentally programmed as a GPIO // pin@@ the PD7 and PF0 pins // default to non-committable. // Because of this@@ the default // reset value of GPIOCR for GPIO // Port C is 0x0000.00F0@@ for GPIO // Port D is 0x0000.007F@@ and for // GPIO Port F is 0x0000.00FE. #define GPIO_GPIO_CR_CR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_AMSEL register. // //****************************************************************************** #define GPIO_GPIO_AMSEL_GPIO_AMSEL_M \ 0x000000FF // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) GPIO Analog // Mode Select Value Description 1 // The analog function of the pin is // enabled@@ the isolation is // disabled@@ and the pin is capable // of analog functions. 0 The analog // function of the pin is disabled@@ // the isolation is enabled@@ and // the pin is capable of digital // functions as specified by the // other GPIO configuration // registers. Note: This register // and bits are only valid for GPIO // signals that share analog // function through a unified I/O // pad. The reset state of this // register is 0 for all signals. #define GPIO_GPIO_AMSEL_GPIO_AMSEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_PCTL register. // //****************************************************************************** #define GPIO_GPIO_PCTL_PMC7_M 0xF0000000 // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Port Mux // Control 7 This field controls the // configuration for GPIO pin 7. #define GPIO_GPIO_PCTL_PMC7_S 28 #define GPIO_GPIO_PCTL_PMC6_M 0x0F000000 // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Port Mux // Control 6 This field controls the // configuration for GPIO pin 6. #define GPIO_GPIO_PCTL_PMC6_S 24 #define GPIO_GPIO_PCTL_PMC5_M 0x00F00000 // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Port Mux // Control 5 This field controls the // configuration for GPIO pin 5. #define GPIO_GPIO_PCTL_PMC5_S 20 #define GPIO_GPIO_PCTL_PMC4_M 0x000F0000 // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Port Mux // Control 4 This field controls the // configuration for GPIO pin 4. #define GPIO_GPIO_PCTL_PMC4_S 16 #define GPIO_GPIO_PCTL_PMC3_M 0x0000F000 // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Port Mux // Control 43 This field controls // the configuration for GPIO pin 3. #define GPIO_GPIO_PCTL_PMC3_S 12 #define GPIO_GPIO_PCTL_PMC1_M 0x00000F00 // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Port Mux // Control 1 This field controls the // configuration for GPIO pin 1. #define GPIO_GPIO_PCTL_PMC1_S 8 #define GPIO_GPIO_PCTL_PMC2_M 0x000000F0 // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Port Mux // Control 2 This field controls the // configuration for GPIO pin 2. #define GPIO_GPIO_PCTL_PMC2_S 4 #define GPIO_GPIO_PCTL_PMC0_M 0x0000000F // This register is not used in // cc3xx. equivalant register exsist // outside GPIO IP (refer // PAD*_config register in the // shared comn space) Port Mux // Control 0 This field controls the // configuration for GPIO pin 0. #define GPIO_GPIO_PCTL_PMC0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_ADCCTL register. // //****************************************************************************** #define GPIO_GPIO_ADCCTL_ADCEN_M \ 0x000000FF // This register is not used in // cc3xx. ADC trigger via GPIO is // not supported. ADC Trigger Enable // Value Description 1 The // corresponding pin is used to // trigger the ADC. 0 The // corresponding pin is not used to // trigger the ADC. #define GPIO_GPIO_ADCCTL_ADCEN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_DMACTL register. // //****************************************************************************** #define GPIO_GPIO_DMACTL_DMAEN_M \ 0x000000FF // This register is not used in the // cc3xx. Alternate register to // support this feature is coded in // the APPS_NWP_CMN space. refer // register as offset 0x400F70D8 // ?DMA Trigger Enable Value // Description 1 The corresponding // pin is used to trigger the ?DMA. // 0 The corresponding pin is not // used to trigger the ?DMA. #define GPIO_GPIO_DMACTL_DMAEN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPIO_O_GPIO_SI register. // //****************************************************************************** #define GPIO_GPIO_SI_SUM 0x00000001 // Summary Interrupt Value // Description 1 Each pin has its // own interrupt vector. 0 All port // pin interrupts are OR'ed together // to produce a summary interrupt. //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PERIPHID4 register. // //****************************************************************************** #define GPIO_GPIO_PERIPHID4_PID4_M \ 0x000000FF // This register is not used in // CC3XX. GPIO Peripheral ID // Register [7:0] #define GPIO_GPIO_PERIPHID4_PID4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PERIPHID5 register. // //****************************************************************************** #define GPIO_GPIO_PERIPHID5_PID5_M \ 0x000000FF // This register is not used in // CC3XX. GPIO Peripheral ID // Register [15:8] #define GPIO_GPIO_PERIPHID5_PID5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PERIPHID6 register. // //****************************************************************************** #define GPIO_GPIO_PERIPHID6_PID6_M \ 0x000000FF // This register is not used in // CC3XX. GPIO Peripheral ID // Register [23:16] #define GPIO_GPIO_PERIPHID6_PID6_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PERIPHID7 register. // //****************************************************************************** #define GPIO_GPIO_PERIPHID7_PID7_M \ 0x000000FF // This register is not used in // CC3XX. GPIO Peripheral ID // Register [31:24] #define GPIO_GPIO_PERIPHID7_PID7_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PERIPHID0 register. // //****************************************************************************** #define GPIO_GPIO_PERIPHID0_PID0_M \ 0x000000FF // This register is not used in // CC3XX. GPIO Peripheral ID // Register [7:0] Can be used by // software to identify the presence // of this peripheral. #define GPIO_GPIO_PERIPHID0_PID0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PERIPHID1 register. // //****************************************************************************** #define GPIO_GPIO_PERIPHID1_PID1_M \ 0x000000FF // GPIO Peripheral ID Register // [15:8] Can be used by software to // identify the presence of this // peripheral. #define GPIO_GPIO_PERIPHID1_PID1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PERIPHID2 register. // //****************************************************************************** #define GPIO_GPIO_PERIPHID2_PID2_M \ 0x000000FF // This register is not used in // CC3XX.v GPIO Peripheral ID // Register [23:16] Can be used by // software to identify the presence // of this peripheral. #define GPIO_GPIO_PERIPHID2_PID2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PERIPHID3 register. // //****************************************************************************** #define GPIO_GPIO_PERIPHID3_PID3_M \ 0x000000FF // This register is not used in // CC3XX. GPIO Peripheral ID // Register [31:24] Can be used by // software to identify the presence // of this peripheral. #define GPIO_GPIO_PERIPHID3_PID3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PCELLID0 register. // //****************************************************************************** #define GPIO_GPIO_PCELLID0_CID0_M \ 0x000000FF // This register is not used in // CC3XX. GPIO PrimeCell ID Register // [7:0] Provides software a // standard cross-peripheral // identification system. #define GPIO_GPIO_PCELLID0_CID0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PCELLID1 register. // //****************************************************************************** #define GPIO_GPIO_PCELLID1_CID1_M \ 0x000000FF // This register is not used in // CC3XX. GPIO PrimeCell ID Register // [15:8] Provides software a // standard cross-peripheral // identification system. #define GPIO_GPIO_PCELLID1_CID1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PCELLID2 register. // //****************************************************************************** #define GPIO_GPIO_PCELLID2_CID2_M \ 0x000000FF // This register is not used in // CC3XX. GPIO PrimeCell ID Register // [23:16] Provides software a // standard cross-peripheral // identification system. #define GPIO_GPIO_PCELLID2_CID2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPIO_O_GPIO_PCELLID3 register. // //****************************************************************************** #define GPIO_GPIO_PCELLID3_CID3_M \ 0x000000FF // This register is not used in // CC3XX. GPIO PrimeCell ID Register // [31:24] Provides software a // standard cross-peripheral // identification system. #define GPIO_GPIO_PCELLID3_CID3_S 0 #endif // __HW_GPIO_H__ micropython-1.12/ports/cc3200/hal/inc/hw_gprcm.h000066400000000000000000005056571357706137100214010ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_GPRCM_H__ #define __HW_GPRCM_H__ //***************************************************************************** // // The following are defines for the GPRCM register offsets. // //***************************************************************************** #define GPRCM_O_APPS_SOFT_RESET 0x00000000 #define GPRCM_O_APPS_LPDS_WAKEUP_CFG \ 0x00000004 #define GPRCM_O_APPS_LPDS_WAKEUP_SRC \ 0x00000008 #define GPRCM_O_APPS_RESET_CAUSE \ 0x0000000C #define GPRCM_O_APPS_LPDS_WAKETIME_OPP_CFG \ 0x00000010 #define GPRCM_O_APPS_SRAM_DSLP_CFG \ 0x00000018 #define GPRCM_O_APPS_SRAM_LPDS_CFG \ 0x0000001C #define GPRCM_O_APPS_LPDS_WAKETIME_WAKE_CFG \ 0x00000020 #define GPRCM_O_TOP_DIE_ENABLE 0x00000100 #define GPRCM_O_TOP_DIE_ENABLE_PARAMETERS \ 0x00000104 #define GPRCM_O_MCU_GLOBAL_SOFT_RESET \ 0x00000108 #define GPRCM_O_ADC_CLK_CONFIG 0x0000010C #define GPRCM_O_APPS_GPIO_WAKE_CONF \ 0x00000110 #define GPRCM_O_EN_NWP_BOOT_WO_DEVINIT \ 0x00000114 #define GPRCM_O_MEM_HCLK_DIV_CFG \ 0x00000118 #define GPRCM_O_MEM_SYSCLK_DIV_CFG \ 0x0000011C #define GPRCM_O_APLLMCS_LOCK_TIME_CONF \ 0x00000120 #define GPRCM_O_NWP_SOFT_RESET 0x00000400 #define GPRCM_O_NWP_LPDS_WAKEUP_CFG \ 0x00000404 #define GPRCM_O_NWP_LPDS_WAKEUP_SRC \ 0x00000408 #define GPRCM_O_NWP_RESET_CAUSE 0x0000040C #define GPRCM_O_NWP_LPDS_WAKETIME_OPP_CFG \ 0x00000410 #define GPRCM_O_NWP_SRAM_DSLP_CFG \ 0x00000418 #define GPRCM_O_NWP_SRAM_LPDS_CFG \ 0x0000041C #define GPRCM_O_NWP_LPDS_WAKETIME_WAKE_CFG \ 0x00000420 #define GPRCM_O_NWP_AUTONMS_SPI_MASTER_SEL \ 0x00000424 #define GPRCM_O_NWP_AUTONMS_SPI_IDLE_REQ \ 0x00000428 #define GPRCM_O_WLAN_TO_NWP_WAKE_REQUEST \ 0x0000042C #define GPRCM_O_NWP_TO_WLAN_WAKE_REQUEST \ 0x00000430 #define GPRCM_O_NWP_GPIO_WAKE_CONF \ 0x00000434 #define GPRCM_O_GPRCM_EFUSE_READ_REG12 \ 0x00000438 #define GPRCM_O_GPRCM_DIEID_READ_REG5 \ 0x00000448 #define GPRCM_O_GPRCM_DIEID_READ_REG6 \ 0x0000044C #define GPRCM_O_REF_FSM_CFG0 0x00000800 #define GPRCM_O_REF_FSM_CFG1 0x00000804 #define GPRCM_O_APLLMCS_WLAN_CONFIG0_40 \ 0x00000808 #define GPRCM_O_APLLMCS_WLAN_CONFIG1_40 \ 0x0000080C #define GPRCM_O_APLLMCS_WLAN_CONFIG0_26 \ 0x00000810 #define GPRCM_O_APLLMCS_WLAN_CONFIG1_26 \ 0x00000814 #define GPRCM_O_APLLMCS_WLAN_OVERRIDES \ 0x00000818 #define GPRCM_O_APLLMCS_MCU_RUN_CONFIG0_38P4 \ 0x0000081C #define GPRCM_O_APLLMCS_MCU_RUN_CONFIG1_38P4 \ 0x00000820 #define GPRCM_O_APLLMCS_MCU_RUN_CONFIG0_26 \ 0x00000824 #define GPRCM_O_APLLMCS_MCU_RUN_CONFIG1_26 \ 0x00000828 #define GPRCM_O_SPARE_RW0 0x0000082C #define GPRCM_O_SPARE_RW1 0x00000830 #define GPRCM_O_APLLMCS_MCU_OVERRIDES \ 0x00000834 #define GPRCM_O_SYSCLK_SWITCH_STATUS \ 0x00000838 #define GPRCM_O_REF_LDO_CONTROLS \ 0x0000083C #define GPRCM_O_REF_RTRIM_CONTROL \ 0x00000840 #define GPRCM_O_REF_SLICER_CONTROLS0 \ 0x00000844 #define GPRCM_O_REF_SLICER_CONTROLS1 \ 0x00000848 #define GPRCM_O_REF_ANA_BGAP_CONTROLS0 \ 0x0000084C #define GPRCM_O_REF_ANA_BGAP_CONTROLS1 \ 0x00000850 #define GPRCM_O_REF_ANA_SPARE_CONTROLS0 \ 0x00000854 #define GPRCM_O_REF_ANA_SPARE_CONTROLS1 \ 0x00000858 #define GPRCM_O_MEMSS_PSCON_OVERRIDES0 \ 0x0000085C #define GPRCM_O_MEMSS_PSCON_OVERRIDES1 \ 0x00000860 #define GPRCM_O_PLL_REF_LOCK_OVERRIDES \ 0x00000864 #define GPRCM_O_MCU_PSCON_DEBUG 0x00000868 #define GPRCM_O_MEMSS_PWR_PS 0x0000086C #define GPRCM_O_REF_FSM_DEBUG 0x00000870 #define GPRCM_O_MEM_SYS_OPP_REQ_OVERRIDE \ 0x00000874 #define GPRCM_O_MEM_TESTCTRL_PD_OPP_CONFIG \ 0x00000878 #define GPRCM_O_MEM_WL_FAST_CLK_REQ_OVERRIDES \ 0x0000087C #define GPRCM_O_MEM_MCU_PD_MODE_REQ_OVERRIDES \ 0x00000880 #define GPRCM_O_MEM_MCSPI_SRAM_OFF_REQ_OVERRIDES \ 0x00000884 #define GPRCM_O_MEM_WLAN_APLLMCS_OVERRIDES \ 0x00000888 #define GPRCM_O_MEM_REF_FSM_CFG2 \ 0x0000088C #define GPRCM_O_TESTCTRL_POWER_CTRL \ 0x00000C10 #define GPRCM_O_SSDIO_POWER_CTRL \ 0x00000C14 #define GPRCM_O_MCSPI_N1_POWER_CTRL \ 0x00000C18 #define GPRCM_O_WELP_POWER_CTRL 0x00000C1C #define GPRCM_O_WL_SDIO_POWER_CTRL \ 0x00000C20 #define GPRCM_O_WLAN_SRAM_ACTIVE_PWR_CFG \ 0x00000C24 #define GPRCM_O_WLAN_SRAM_SLEEP_PWR_CFG \ 0x00000C28 #define GPRCM_O_APPS_SECURE_INIT_DONE \ 0x00000C30 #define GPRCM_O_APPS_DEV_MODE_INIT_DONE \ 0x00000C34 #define GPRCM_O_EN_APPS_REBOOT 0x00000C38 #define GPRCM_O_MEM_APPS_PERIPH_PRESENT \ 0x00000C3C #define GPRCM_O_MEM_NWP_PERIPH_PRESENT \ 0x00000C40 #define GPRCM_O_MEM_SHARED_PERIPH_PRESENT \ 0x00000C44 #define GPRCM_O_NWP_PWR_STATE 0x00000C48 #define GPRCM_O_APPS_PWR_STATE 0x00000C4C #define GPRCM_O_MCU_PWR_STATE 0x00000C50 #define GPRCM_O_WTOP_PM_PS 0x00000C54 #define GPRCM_O_WTOP_PD_RESETZ_OVERRIDE_REG \ 0x00000C58 #define GPRCM_O_WELP_PD_RESETZ_OVERRIDE_REG \ 0x00000C5C #define GPRCM_O_WL_SDIO_PD_RESETZ_OVERRIDE_REG \ 0x00000C60 #define GPRCM_O_SSDIO_PD_RESETZ_OVERRIDE_REG \ 0x00000C64 #define GPRCM_O_MCSPI_N1_PD_RESETZ_OVERRIDE_REG \ 0x00000C68 #define GPRCM_O_TESTCTRL_PD_RESETZ_OVERRIDE_REG \ 0x00000C6C #define GPRCM_O_MCU_PD_RESETZ_OVERRIDE_REG \ 0x00000C70 #define GPRCM_O_GPRCM_EFUSE_READ_REG0 \ 0x00000C78 #define GPRCM_O_GPRCM_EFUSE_READ_REG1 \ 0x00000C7C #define GPRCM_O_GPRCM_EFUSE_READ_REG2 \ 0x00000C80 #define GPRCM_O_GPRCM_EFUSE_READ_REG3 \ 0x00000C84 #define GPRCM_O_WTOP_MEM_RET_CFG \ 0x00000C88 #define GPRCM_O_COEX_CLK_SWALLOW_CFG0 \ 0x00000C8C #define GPRCM_O_COEX_CLK_SWALLOW_CFG1 \ 0x00000C90 #define GPRCM_O_COEX_CLK_SWALLOW_CFG2 \ 0x00000C94 #define GPRCM_O_COEX_CLK_SWALLOW_ENABLE \ 0x00000C98 #define GPRCM_O_DCDC_CLK_GEN_CONFIG \ 0x00000C9C #define GPRCM_O_GPRCM_EFUSE_READ_REG4 \ 0x00000CA0 #define GPRCM_O_GPRCM_EFUSE_READ_REG5 \ 0x00000CA4 #define GPRCM_O_GPRCM_EFUSE_READ_REG6 \ 0x00000CA8 #define GPRCM_O_GPRCM_EFUSE_READ_REG7 \ 0x00000CAC #define GPRCM_O_GPRCM_EFUSE_READ_REG8 \ 0x00000CB0 #define GPRCM_O_GPRCM_EFUSE_READ_REG9 \ 0x00000CB4 #define GPRCM_O_GPRCM_EFUSE_READ_REG10 \ 0x00000CB8 #define GPRCM_O_GPRCM_EFUSE_READ_REG11 \ 0x00000CBC #define GPRCM_O_GPRCM_DIEID_READ_REG0 \ 0x00000CC0 #define GPRCM_O_GPRCM_DIEID_READ_REG1 \ 0x00000CC4 #define GPRCM_O_GPRCM_DIEID_READ_REG2 \ 0x00000CC8 #define GPRCM_O_GPRCM_DIEID_READ_REG3 \ 0x00000CCC #define GPRCM_O_GPRCM_DIEID_READ_REG4 \ 0x00000CD0 #define GPRCM_O_APPS_SS_OVERRIDES \ 0x00000CD4 #define GPRCM_O_NWP_SS_OVERRIDES \ 0x00000CD8 #define GPRCM_O_SHARED_SS_OVERRIDES \ 0x00000CDC #define GPRCM_O_IDMEM_CORE_RST_OVERRIDES \ 0x00000CE0 #define GPRCM_O_TOP_DIE_FSM_OVERRIDES \ 0x00000CE4 #define GPRCM_O_MCU_PSCON_OVERRIDES \ 0x00000CE8 #define GPRCM_O_WTOP_PSCON_OVERRIDES \ 0x00000CEC #define GPRCM_O_WELP_PSCON_OVERRIDES \ 0x00000CF0 #define GPRCM_O_WL_SDIO_PSCON_OVERRIDES \ 0x00000CF4 #define GPRCM_O_MCSPI_PSCON_OVERRIDES \ 0x00000CF8 #define GPRCM_O_SSDIO_PSCON_OVERRIDES \ 0x00000CFC //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_SOFT_RESET register. // //****************************************************************************** #define GPRCM_APPS_SOFT_RESET_APPS_SOFT_RESET1 \ 0x00000002 // Soft-reset1 for APPS : Cortex // sysrstn is asserted and in // addition to that the associated // APPS Peripherals are also reset. // This is an auto-clear bit. #define GPRCM_APPS_SOFT_RESET_APPS_SOFT_RESET0 \ 0x00000001 // Soft-reset0 for APPS : Only // sys-resetn for Cortex will be // asserted. This is an auto-clear // bit. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_LPDS_WAKEUP_CFG register. // //****************************************************************************** #define GPRCM_APPS_LPDS_WAKEUP_CFG_APPS_LPDS_WAKEUP_CFG_M \ 0x000000FF // Mask for LPDS Wakeup interrupt : // [7] - Host IRQ from NWP [6] - // NWP_LPDS_Wake_irq (TRUE_LPDS) [5] // - NWP Wake-request to APPS [4] - // GPIO [3:1] - Reserved [0] - LPDS // Wakeup-timer #define GPRCM_APPS_LPDS_WAKEUP_CFG_APPS_LPDS_WAKEUP_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_LPDS_WAKEUP_SRC register. // //****************************************************************************** #define GPRCM_APPS_LPDS_WAKEUP_SRC_APPS_LPDS_WAKEUP_SRC_M \ 0x000000FF // Indicates the cause for wakeup // from LPDS : [7] - Host IRQ from // NWP [6] - NWP_LPDS_Wake_irq // (TRUE_LPDS) [5] - NWP // Wake-request to APPS [4] - GPIO // [3:1] - Reserved [0] - LPDS // Wakeup-timer #define GPRCM_APPS_LPDS_WAKEUP_SRC_APPS_LPDS_WAKEUP_SRC_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_RESET_CAUSE register. // //****************************************************************************** #define GPRCM_APPS_RESET_CAUSE_APPS_RESET_CAUSE_M \ 0x000000FF // Indicates the reset cause for // APPS : "0000" - Wake from HIB/OFF // mode; "0001" - Wake from LPDS ; // "0010" - Reserved ; "0011" - // Soft-reset0 (Only APPS // Cortex-sysrstn is asserted); // "0100" - Soft-reset1 (APPS // Cortex-sysrstn and APPS // peripherals are reset); "0101" - // WDOG0 (APPS Cortex-sysrstn and // APPS peripherals are reset); // "0110" - MCU Soft-reset (APPS + // NWP Cortex-sysrstn + Peripherals // are reset); "0111" - Secure Init // done (Indication that reset has // happened after DevInit); "1000" - // Dev Mode Patch Init done (During // development mode, patch // downloading and Cortex // re-vectoring is completed) #define GPRCM_APPS_RESET_CAUSE_APPS_RESET_CAUSE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_LPDS_WAKETIME_OPP_CFG register. // //****************************************************************************** #define GPRCM_APPS_LPDS_WAKETIME_OPP_CFG_APPS_LPDS_WAKETIME_OPP_CFG_M \ 0xFFFFFFFF // OPP Request Configuration // (Number of slow-clk cycles) for // LPDS Wake-timer : This // configuration implies the RTC // time-stamp, which must be few // slow-clks prior to // APPS_LPDS_WAKETIME_WAKE_CFG, such // that by the time actual wakeup is // given, OPP is already switched to // ACTIVE (RUN). #define GPRCM_APPS_LPDS_WAKETIME_OPP_CFG_APPS_LPDS_WAKETIME_OPP_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_SRAM_DSLP_CFG register. // //****************************************************************************** #define GPRCM_APPS_SRAM_DSLP_CFG_APPS_SRAM_DSLP_CFG_M \ 0x000FFFFF // Configuration of APPS Memories // during Deep-sleep : 0 - SRAMs are // OFF ; 1 - SRAMs are Retained. // APPS SRAM Cluster information : // [0] - 1st column in MEMSS // (Applicable only when owned by // APPS); [1] - 2nd column in MEMSS // (Applicable only when owned by // APPS); [2] - 3rd column in MEMSS // (Applicable only when owned by // APPS) ; [3] - 4th column in MEMSS // (Applicable only when owned by // APPS) ; [16] - MCU-PD - Apps // cluster 0 (TBD); [19:18] - // Reserved. #define GPRCM_APPS_SRAM_DSLP_CFG_APPS_SRAM_DSLP_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_SRAM_LPDS_CFG register. // //****************************************************************************** #define GPRCM_APPS_SRAM_LPDS_CFG_APPS_SRAM_LPDS_CFG_M \ 0x000FFFFF // Configuration of APPS Memories // during LPDS : 0 - SRAMs are OFF ; // 1 - SRAMs are Retained. APPS SRAM // Cluster information : [0] - 1st // column in MEMSS (Applicable only // when owned by APPS); [1] - 2nd // column in MEMSS (Applicable only // when owned by APPS); [2] - 3rd // column in MEMSS (Applicable only // when owned by APPS) ; [3] - 4th // column in MEMSS (Applicable only // when owned by APPS) ; [16] - // MCU-PD - Apps cluster 0 (TBD); // [19:18] - Reserved. #define GPRCM_APPS_SRAM_LPDS_CFG_APPS_SRAM_LPDS_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_LPDS_WAKETIME_WAKE_CFG register. // //****************************************************************************** #define GPRCM_APPS_LPDS_WAKETIME_WAKE_CFG_APPS_LPDS_WAKETIME_WAKE_CFG_M \ 0xFFFFFFFF // Configuration (in no of // slow_clks) which says when the // actual wakeup request for // removing the PD-reset be given. #define GPRCM_APPS_LPDS_WAKETIME_WAKE_CFG_APPS_LPDS_WAKETIME_WAKE_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_TOP_DIE_ENABLE register. // //****************************************************************************** #define GPRCM_TOP_DIE_ENABLE_FLASH_BUSY \ 0x00001000 #define GPRCM_TOP_DIE_ENABLE_TOP_DIE_PWR_PS_M \ 0x00000F00 #define GPRCM_TOP_DIE_ENABLE_TOP_DIE_PWR_PS_S 8 #define GPRCM_TOP_DIE_ENABLE_TOP_DIE_ENABLE_STATUS \ 0x00000002 // 1 - Top-die is enabled ; #define GPRCM_TOP_DIE_ENABLE_TOP_DIE_ENABLE \ 0x00000001 // 1 - Enable the top-die ; 0 - // Disable the top-die //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_TOP_DIE_ENABLE_PARAMETERS register. // //****************************************************************************** #define GPRCM_TOP_DIE_ENABLE_PARAMETERS_FLASH_3P3_RSTN2D2D_POR_RSTN_M \ 0xF0000000 // Configuration (in slow_clks) for // number of clks between // Flash-3p3-rstn to D2D POR Resetn. #define GPRCM_TOP_DIE_ENABLE_PARAMETERS_FLASH_3P3_RSTN2D2D_POR_RSTN_S 28 #define GPRCM_TOP_DIE_ENABLE_PARAMETERS_TOP_DIE_SW_EN2TOP_DIE_FLASH_3P3_RSTN_M \ 0x00FF0000 // Configuration (in slow_clks) for // number of clks between Top-die // Switch-Enable and Top-die Flash // 3p3 Reset removal #define GPRCM_TOP_DIE_ENABLE_PARAMETERS_TOP_DIE_SW_EN2TOP_DIE_FLASH_3P3_RSTN_S 16 #define GPRCM_TOP_DIE_ENABLE_PARAMETERS_TOP_DIE_POR_RSTN2BOTT_DIE_FMC_RSTN_M \ 0x000000FF // Configuration (in slow_clks) for // number of clks between D2D POR // Reset removal and bottom die FMC // reset removal #define GPRCM_TOP_DIE_ENABLE_PARAMETERS_TOP_DIE_POR_RSTN2BOTT_DIE_FMC_RSTN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MCU_GLOBAL_SOFT_RESET register. // //****************************************************************************** #define GPRCM_MCU_GLOBAL_SOFT_RESET_MCU_GLOBAL_SOFT_RESET \ 0x00000001 // 1 - Assert the global reset for // MCU (APPS + NWP) ; Asserts both // Cortex sysrstn and its // peripherals 0 - Deassert the // global reset for MCU (APPS + NWP) // ; Asserts both Cortex sysrstn and // its peripherals Note : Reset for // shared peripherals is not // affected here. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_ADC_CLK_CONFIG register. // //****************************************************************************** #define GPRCM_ADC_CLK_CONFIG_ADC_CLKGEN_OFF_TIME_M \ 0x000007C0 // Configuration (in number of 38.4 // MHz clks) for the OFF-Time in // generation of ADC_CLK #define GPRCM_ADC_CLK_CONFIG_ADC_CLKGEN_OFF_TIME_S 6 #define GPRCM_ADC_CLK_CONFIG_ADC_CLKGEN_ON_TIME_M \ 0x0000003E // Configuration (in number of 38.4 // MHz clks) for the ON-Time in // generation of ADC_CLK #define GPRCM_ADC_CLK_CONFIG_ADC_CLKGEN_ON_TIME_S 1 #define GPRCM_ADC_CLK_CONFIG_ADC_CLK_ENABLE \ 0x00000001 // 1 - Enable the ADC_CLK ; 0 - // Disable the ADC_CLK //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_GPIO_WAKE_CONF register. // //****************************************************************************** #define GPRCM_APPS_GPIO_WAKE_CONF_APPS_GPIO_WAKE_CONF_M \ 0x00000003 // "00" - Wake on Level0 on // selected GPIO pin (GPIO is // selected inside the HIB3p3 // module); "01" - Wakeup on // fall-edge of GPIO pin. #define GPRCM_APPS_GPIO_WAKE_CONF_APPS_GPIO_WAKE_CONF_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_EN_NWP_BOOT_WO_DEVINIT register. // //****************************************************************************** #define GPRCM_EN_NWP_BOOT_WO_DEVINIT_reserved_M \ 0xFFFFFFFE #define GPRCM_EN_NWP_BOOT_WO_DEVINIT_reserved_S 1 #define GPRCM_EN_NWP_BOOT_WO_DEVINIT_mem_en_nwp_boot_wo_devinit \ 0x00000001 // 1 - Override the secure-mode // done for booting up NWP (Wakeup // NWP on its event independent of // CM4 state) ; 0 - Donot override // the secure-mode done for NWP boot // (NWP must be enabled by CM4 only) //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_HCLK_DIV_CFG register. // //****************************************************************************** #define GPRCM_MEM_HCLK_DIV_CFG_mem_hclk_div_cfg_M \ 0x00000007 // Division configuration for // HCLKDIVOUT : "000" - Divide by 1 // ; "001" - Divide by 2 ; "010" - // Divide by 3 ; "011" - Divide by 4 // ; "100" - Divide by 5 ; "101" - // Divide by 6 ; "110" - Divide by 7 // ; "111" - Divide by 8 #define GPRCM_MEM_HCLK_DIV_CFG_mem_hclk_div_cfg_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_SYSCLK_DIV_CFG register. // //****************************************************************************** #define GPRCM_MEM_SYSCLK_DIV_CFG_mem_sysclk_div_off_time_M \ 0x00000038 #define GPRCM_MEM_SYSCLK_DIV_CFG_mem_sysclk_div_off_time_S 3 #define GPRCM_MEM_SYSCLK_DIV_CFG_mem_sysclk_div_on_time_M \ 0x00000007 #define GPRCM_MEM_SYSCLK_DIV_CFG_mem_sysclk_div_on_time_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_LOCK_TIME_CONF register. // //****************************************************************************** #define GPRCM_APLLMCS_LOCK_TIME_CONF_mem_apllmcs_wlan_lock_time_M \ 0x0000FF00 #define GPRCM_APLLMCS_LOCK_TIME_CONF_mem_apllmcs_wlan_lock_time_S 8 #define GPRCM_APLLMCS_LOCK_TIME_CONF_mem_apllmcs_mcu_lock_time_M \ 0x000000FF #define GPRCM_APLLMCS_LOCK_TIME_CONF_mem_apllmcs_mcu_lock_time_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_SOFT_RESET register. // //****************************************************************************** #define GPRCM_NWP_SOFT_RESET_NWP_SOFT_RESET1 \ 0x00000002 // Soft-reset1 for NWP - Cortex // sysrstn and NWP associated // peripherals are - This is an // auto-clr bit. #define GPRCM_NWP_SOFT_RESET_NWP_SOFT_RESET0 \ 0x00000001 // Soft-reset0 for NWP - Only // Cortex-sysrstn is asserted - This // is an auto-clear bit. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_LPDS_WAKEUP_CFG register. // //****************************************************************************** #define GPRCM_NWP_LPDS_WAKEUP_CFG_NWP_LPDS_WAKEUP_CFG_M \ 0x000000FF // Mask for LPDS Wakeup interrupt : // 7 - WLAN Host Interrupt ; 6 - // WLAN to NWP Wake request ; 5 - // APPS to NWP Wake request; 4 - // GPIO Wakeup ; 3 - Autonomous UART // Wakeup ; 2 - SSDIO Wakeup ; 1 - // Autonomous SPI Wakeup ; 0 - LPDS // Wakeup-timer #define GPRCM_NWP_LPDS_WAKEUP_CFG_NWP_LPDS_WAKEUP_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_LPDS_WAKEUP_SRC register. // //****************************************************************************** #define GPRCM_NWP_LPDS_WAKEUP_SRC_NWP_LPDS_WAKEUP_SRC_M \ 0x000000FF // Indicates the cause for NWP // LPDS-Wakeup : 7 - WLAN Host // Interrupt ; 6 - WLAN to NWP Wake // request ; 5 - APPS to NWP Wake // request; 4 - GPIO Wakeup ; 3 - // Autonomous UART Wakeup ; 2 - // SSDIO Wakeup ; 1 - Autonomous SPI // Wakeup ; 0 - LPDS Wakeup-timer #define GPRCM_NWP_LPDS_WAKEUP_SRC_NWP_LPDS_WAKEUP_SRC_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_RESET_CAUSE register. // //****************************************************************************** #define GPRCM_NWP_RESET_CAUSE_NWP_RESET_CAUSE_M \ 0x000000FF // Indicates the reset cause for // NWP : "0000" - Wake from HIB/OFF // mode; "0001" - Wake from LPDS ; // "0010" - Reserved ; "0011" - // Soft-reset0 (Only NWP // Cortex-sysrstn is asserted); // "0100" - Soft-reset1 (NWP // Cortex-sysrstn and NWP // peripherals are reset); "0101" - // WDOG0 (NWP Cortex-sysrstn and NWP // peripherals are reset); "0110" - // MCU Soft-reset (APPS + NWP // Cortex-sysrstn + Peripherals are // reset); "0111" - SSDIO Function2 // reset (Only Cortex-sysrstn is // asserted) ; "1000" - Reset due to // WDOG of APPS (NWP Cortex-sysrstn // and NWP peripherals are reset); #define GPRCM_NWP_RESET_CAUSE_NWP_RESET_CAUSE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_LPDS_WAKETIME_OPP_CFG register. // //****************************************************************************** #define GPRCM_NWP_LPDS_WAKETIME_OPP_CFG_NWP_LPDS_WAKETIME_OPP_CFG_M \ 0xFFFFFFFF // OPP Request Configuration // (Number of slow-clk cycles) for // LPDS Wake-timer #define GPRCM_NWP_LPDS_WAKETIME_OPP_CFG_NWP_LPDS_WAKETIME_OPP_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_SRAM_DSLP_CFG register. // //****************************************************************************** #define GPRCM_NWP_SRAM_DSLP_CFG_NWP_SRAM_DSLP_CFG_M \ 0x000FFFFF // Configuration of NWP Memories // during DSLP : 0 - SRAMs are OFF ; // 1 - SRAMs are Retained. NWP SRAM // Cluster information : [2] - 3rd // column in MEMSS (Applicable only // when owned by NWP) ; [3] - 4th // column in MEMSS (Applicable only // when owned by NWP) ; [4] - 5th // column in MEMSS (Applicable only // when owned by NWP) ; [5] - 6th // column in MEMSS (Applicable only // when owned by NWP) ; [6] - 7th // column in MEMSS (Applicable only // when owned by NWP) ; [7] - 8th // column in MEMSS (Applicable only // when owned by NWP) ; [8] - 9th // column in MEMSS (Applicable only // when owned by NWP) ; [9] - 10th // column in MEMSS (Applicable only // when owned by NWP) ; [10] - 11th // column in MEMSS (Applicable only // when owned by NWP) ; [11] - 12th // column in MEMSS (Applicable only // when owned by NWP) ; [12] - 13th // column in MEMSS (Applicable only // when owned by NWP) ; [13] - 14th // column in MEMSS (Applicable only // when owned by NWP) ; [14] - 15th // column in MEMSS (Applicable only // when owned by NWP) ; [19:18] - // Reserved. #define GPRCM_NWP_SRAM_DSLP_CFG_NWP_SRAM_DSLP_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_SRAM_LPDS_CFG register. // //****************************************************************************** #define GPRCM_NWP_SRAM_LPDS_CFG_NWP_SRAM_LPDS_CFG_M \ 0x000FFFFF // Configuration of NWP Memories // during LPDS : 0 - SRAMs are OFF ; // 1 - SRAMs are Retained. NWP SRAM // Cluster information : [2] - 3rd // column in MEMSS (Applicable only // when owned by NWP) ; [3] - 4th // column in MEMSS (Applicable only // when owned by NWP) ; [4] - 5th // column in MEMSS (Applicable only // when owned by NWP) ; [5] - 6th // column in MEMSS (Applicable only // when owned by NWP) ; [6] - 7th // column in MEMSS (Applicable only // when owned by NWP) ; [7] - 8th // column in MEMSS (Applicable only // when owned by NWP) ; [8] - 9th // column in MEMSS (Applicable only // when owned by NWP) ; [9] - 10th // column in MEMSS (Applicable only // when owned by NWP) ; [10] - 11th // column in MEMSS (Applicable only // when owned by NWP) ; [11] - 12th // column in MEMSS (Applicable only // when owned by NWP) ; [12] - 13th // column in MEMSS (Applicable only // when owned by NWP) ; [13] - 14th // column in MEMSS (Applicable only // when owned by NWP) ; [14] - 15th // column in MEMSS (Applicable only // when owned by NWP) ; [19:18] - // Reserved. #define GPRCM_NWP_SRAM_LPDS_CFG_NWP_SRAM_LPDS_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_LPDS_WAKETIME_WAKE_CFG register. // //****************************************************************************** #define GPRCM_NWP_LPDS_WAKETIME_WAKE_CFG_NWP_LPDS_WAKETIME_WAKE_CFG_M \ 0xFFFFFFFF // Wake time configuration (no of // slow clks) for NWP wake from // LPDS. #define GPRCM_NWP_LPDS_WAKETIME_WAKE_CFG_NWP_LPDS_WAKETIME_WAKE_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_AUTONMS_SPI_MASTER_SEL register. // //****************************************************************************** #define GPRCM_NWP_AUTONMS_SPI_MASTER_SEL_F_M \ 0xFFFE0000 #define GPRCM_NWP_AUTONMS_SPI_MASTER_SEL_F_S 17 #define GPRCM_NWP_AUTONMS_SPI_MASTER_SEL_MEM_AUTONMS_SPI_MASTER_SEL \ 0x00010000 // 0 - APPS is selected as host for // Autonms SPI ; 1 - External host // is selected as host for Autonms // SPI //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_AUTONMS_SPI_IDLE_REQ register. // //****************************************************************************** #define GPRCM_NWP_AUTONMS_SPI_IDLE_REQ_NWP_AUTONMS_SPI_IDLE_WAKEUP \ 0x00010000 #define GPRCM_NWP_AUTONMS_SPI_IDLE_REQ_NWP_AUTONMS_SPI_IDLE_ACK \ 0x00000002 // When 1 => IDLE-mode is // acknowledged by the SPI-IP. (This // is for MCSPI_N1) #define GPRCM_NWP_AUTONMS_SPI_IDLE_REQ_NWP_AUTONMS_SPI_IDLE_REQ \ 0x00000001 // When 1 => Request for IDLE-mode // for autonomous SPI. (This is for // MCSPI_N1) //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WLAN_TO_NWP_WAKE_REQUEST register. // //****************************************************************************** #define GPRCM_WLAN_TO_NWP_WAKE_REQUEST_WLAN_TO_NWP_WAKE_REQUEST \ 0x00000001 // 1 - Request for waking up NWP // from any of its low-power modes // (SLP/DSLP/LPDS) //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_TO_WLAN_WAKE_REQUEST register. // //****************************************************************************** #define GPRCM_NWP_TO_WLAN_WAKE_REQUEST_NWP_TO_WLAN_WAKE_REQUEST \ 0x00000001 // 1 - Request for wakinp up WLAN // from its ELP Mode (This gets // triggered to ELP-logic of WLAN) //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_GPIO_WAKE_CONF register. // //****************************************************************************** #define GPRCM_NWP_GPIO_WAKE_CONF_NWP_GPIO_WAKE_CONF_M \ 0x00000003 // "00" - Wakeup on level0 of the // selected GPIO (GPIO gets selected // inside HIB3P3-module); "01" - // Wakeup on fall-edge of selected // GPIO. #define GPRCM_NWP_GPIO_WAKE_CONF_NWP_GPIO_WAKE_CONF_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG12 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG12_FUSEFARM_ROW_32_MSW_M \ 0x0000FFFF // This corrsponds to ROW_32 // [31:16] of the FUSEFARM. SPARE #define GPRCM_GPRCM_EFUSE_READ_REG12_FUSEFARM_ROW_32_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_DIEID_READ_REG5 register. // //****************************************************************************** #define GPRCM_GPRCM_DIEID_READ_REG5_FUSEFARM_ROW_10_M \ 0xFFFFFFFF // Corresponds to ROW10 of FUSEFARM // : [5:0] - ADC OFFSET ; [13:6] - // TEMP_SENSE ; [14:14] - DFT_GSG ; // [15:15] - FMC_DISABLE ; [31:16] - // WLAN_MAC ID #define GPRCM_GPRCM_DIEID_READ_REG5_FUSEFARM_ROW_10_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_DIEID_READ_REG6 register. // //****************************************************************************** #define GPRCM_GPRCM_DIEID_READ_REG6_FUSEFARM_ROW_11_M \ 0xFFFFFFFF // Corresponds to ROW11 of FUSEFARM // : [31:0] : WLAN MAC ID #define GPRCM_GPRCM_DIEID_READ_REG6_FUSEFARM_ROW_11_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_FSM_CFG0 register. // //****************************************************************************** #define GPRCM_REF_FSM_CFG0_BGAP_SETTLING_TIME_M \ 0x00FF0000 // ANA-BGAP Settling time (In // number of slow_clks) #define GPRCM_REF_FSM_CFG0_BGAP_SETTLING_TIME_S 16 #define GPRCM_REF_FSM_CFG0_FREF_LDO_SETTLING_TIME_M \ 0x0000FF00 // Slicer LDO settling time (In // number of slow clks) #define GPRCM_REF_FSM_CFG0_FREF_LDO_SETTLING_TIME_S 8 #define GPRCM_REF_FSM_CFG0_DIG_BUF_SETTLING_TIME_M \ 0x000000FF // Dig-buffer settling time (In // number of slow clks) #define GPRCM_REF_FSM_CFG0_DIG_BUF_SETTLING_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_FSM_CFG1 register. // //****************************************************************************** #define GPRCM_REF_FSM_CFG1_XTAL_SETTLING_TIME_M \ 0xFF000000 // XTAL settling time (In number of // slow clks) #define GPRCM_REF_FSM_CFG1_XTAL_SETTLING_TIME_S 24 #define GPRCM_REF_FSM_CFG1_SLICER_LV_SETTLING_TIME_M \ 0x00FF0000 // LV Slicer settling time #define GPRCM_REF_FSM_CFG1_SLICER_LV_SETTLING_TIME_S 16 #define GPRCM_REF_FSM_CFG1_SLICER_HV_PD_SETTLING_TIME_M \ 0x0000FF00 // HV Slicer Pull-down settling // time #define GPRCM_REF_FSM_CFG1_SLICER_HV_PD_SETTLING_TIME_S 8 #define GPRCM_REF_FSM_CFG1_SLICER_HV_SETTLING_TIME_M \ 0x000000FF // HV Slicer settling time #define GPRCM_REF_FSM_CFG1_SLICER_HV_SETTLING_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_WLAN_CONFIG0_40 register. // //****************************************************************************** #define GPRCM_APLLMCS_WLAN_CONFIG0_40_APLLMCS_WLAN_N_40_M \ 0x00007F00 // Configuration for WLAN APLLMCS - // N[6:0], if the XTAL frequency is // 40 MHz (Selected by efuse) #define GPRCM_APLLMCS_WLAN_CONFIG0_40_APLLMCS_WLAN_N_40_S 8 #define GPRCM_APLLMCS_WLAN_CONFIG0_40_APLLMCS_WLAN_M_40_M \ 0x000000FF // Configuration for WLAN APLLMCS - // M[7:0], if the XTAL frequency is // 40 MHz (Selected by efuse) #define GPRCM_APLLMCS_WLAN_CONFIG0_40_APLLMCS_WLAN_M_40_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_WLAN_CONFIG1_40 register. // //****************************************************************************** #define GPRCM_APLLMCS_WLAN_CONFIG1_40_APLLMCS_HISPEED_40 \ 0x00000010 // Configuration for WLAN APLLMCS - // if the XTAL frequency if 40 MHz // (Selected by Efuse) #define GPRCM_APLLMCS_WLAN_CONFIG1_40_APLLMCS_SEL96_40 \ 0x00000008 // Configuration for WLAN APLLMCS - // Sel96, if the XTAL frequency is // 40 MHz (Selected by Efuse) #define GPRCM_APLLMCS_WLAN_CONFIG1_40_APLLMCS_SELINPFREQ_40_M \ 0x00000007 // Configuration for WLAN APLLMCS - // Selinpfreq, if the XTAL frequency // is 40 MHz (Selected by Efuse) #define GPRCM_APLLMCS_WLAN_CONFIG1_40_APLLMCS_SELINPFREQ_40_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_WLAN_CONFIG0_26 register. // //****************************************************************************** #define GPRCM_APLLMCS_WLAN_CONFIG0_26_APLLMCS_WLAN_N_26_M \ 0x00007F00 // Configuration for WLAN APLLMCS - // N[6:0], if the XTAL frequency is // 26 MHz (Selected by efuse) #define GPRCM_APLLMCS_WLAN_CONFIG0_26_APLLMCS_WLAN_N_26_S 8 #define GPRCM_APLLMCS_WLAN_CONFIG0_26_APLLMCS_WLAN_M_26_M \ 0x000000FF // Configuration for WLAN APLLMCS - // M[7:0], if the XTAL frequency is // 26 MHz (Selected by efuse) #define GPRCM_APLLMCS_WLAN_CONFIG0_26_APLLMCS_WLAN_M_26_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_WLAN_CONFIG1_26 register. // //****************************************************************************** #define GPRCM_APLLMCS_WLAN_CONFIG1_26_APLLMCS_HISPEED_26 \ 0x00000010 // Configuration for WLAN APLLMCS - // if the XTAL frequency if 26 MHz // (Selected by Efuse) #define GPRCM_APLLMCS_WLAN_CONFIG1_26_APLLMCS_SEL96_26 \ 0x00000008 // Configuration for WLAN APLLMCS - // Sel96, if the XTAL frequency is // 26 MHz (Selected by Efuse) #define GPRCM_APLLMCS_WLAN_CONFIG1_26_APLLMCS_SELINPFREQ_26_M \ 0x00000007 // Configuration for WLAN APLLMCS - // Selinpfreq, if the XTAL frequency // is 26 MHz (Selected by Efuse) #define GPRCM_APLLMCS_WLAN_CONFIG1_26_APLLMCS_SELINPFREQ_26_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_WLAN_OVERRIDES register. // //****************************************************************************** #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_POSTDIV_OVERRIDE_CTRL \ 0x00080000 #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_POSTDIV_OVERRIDE_M \ 0x00070000 #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_POSTDIV_OVERRIDE_S 16 #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_SPARE_M \ 0x00000700 #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_SPARE_S 8 #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_M_8_OVERRIDE_CTRL \ 0x00000020 // Override control for // WLAN_APLLMCS_M[8]. When set to1, // M[8] will be selected by bit [3]. // (Else controlled from WTOP) #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_M_8_OVERRIDE \ 0x00000010 // Override for WLAN_APLLMCS_M[8]. // Applicable only when bit [4] is // set to 1. (Else controlled from // WTOP) #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_N_7_8_OVERRIDE_CTRL \ 0x00000004 // Override control for // WLAN_APLLMCS_N[8:7]. When set // to1, N[8:7] will be selected by // bits [2:1]. (Else controlled from // WTOP) #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_N_7_8_OVERRIDE_M \ 0x00000003 // Override value for // WLAN_APLLMCS_N[8:7] bits. // Applicable only when bit [1] is // set to 1. (Else controlled from // WTOP) #define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_N_7_8_OVERRIDE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_MCU_RUN_CONFIG0_38P4 register. // //****************************************************************************** #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_POSTDIV_M \ 0x38000000 #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_POSTDIV_S 27 #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_SPARE_M \ 0x07000000 #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_SPARE_S 24 #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_N_38P4_M \ 0x007F0000 // Configuration for MCU-APLLMCS : // N during RUN mode. Selected if // the XTAL frequency is 38.4 MHz // (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_N_38P4_S 16 #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_M_38P4_M \ 0x0000FF00 // Configuration for MCU-APLLMCS : // M during RUN mode. Selected if // the XTAL frequency is 38.4 MHz // (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_M_38P4_S 8 #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_M_8_38P4 \ 0x00000010 // Configuration for MCU-APLLMCS : // M[8] during RUN mode. Selected if // the XTAL frequency is 38.4 MHz // (From Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_N_7_8_38P4_M \ 0x00000003 // Configuration for MCU-APLLMCS : // N[8:7] during RUN mode. Selected // if the XTAL frequency is 38.4 MHz // (From Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_N_7_8_38P4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_MCU_RUN_CONFIG1_38P4 register. // //****************************************************************************** #define GPRCM_APLLMCS_MCU_RUN_CONFIG1_38P4_APLLMCS_MCU_RUN_HISPEED_38P4 \ 0x00000010 // Configuration for MCU-APLLMCS : // HISPEED during RUN mode. Selected // if the XTAL frequency is 38.4 MHz // (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG1_38P4_APLLMCS_MCU_RUN_SEL96_38P4 \ 0x00000008 // Configuration for MCU-APLLMCS : // SEL96 during RUN mode. Selected // if the XTAL frequency is 38.4 MHz // (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG1_38P4_APLLMCS_MCU_RUN_SELINPFREQ_38P4_M \ 0x00000007 // Configuration for MCU-APLLMCS : // SELINPFREQ during RUN mode. // Selected if the XTAL frequency is // 38.4 MHz (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG1_38P4_APLLMCS_MCU_RUN_SELINPFREQ_38P4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_MCU_RUN_CONFIG0_26 register. // //****************************************************************************** #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_N_26_M \ 0x007F0000 // Configuration for MCU-APLLMCS : // N during RUN mode. Selected if // the XTAL frequency is 26 MHz // (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_N_26_S 16 #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_M_26_M \ 0x0000FF00 // Configuration for MCU-APLLMCS : // M during RUN mode. Selected if // the XTAL frequency is 26 MHz // (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_M_26_S 8 #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_M_8_26 \ 0x00000010 // Configuration for MCU-APLLMCS : // M[8] during RUN mode. Selected if // the XTAL frequency is 26 MHz // (From Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_N_7_8_26_M \ 0x00000003 // Configuration for MCU-APLLMCS : // N[8:7] during RUN mode. Selected // if the XTAL frequency is 26 MHz // (From Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_N_7_8_26_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_MCU_RUN_CONFIG1_26 register. // //****************************************************************************** #define GPRCM_APLLMCS_MCU_RUN_CONFIG1_26_APLLMCS_MCU_RUN_HISPEED_26 \ 0x00000010 // Configuration for MCU-APLLMCS : // HISPEED during RUN mode. Selected // if the XTAL frequency is 26 MHz // (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG1_26_APLLMCS_MCU_RUN_SEL96_26 \ 0x00000008 // Configuration for MCU-APLLMCS : // SEL96 during RUN mode. Selected // if the XTAL frequency is 26 MHz // (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG1_26_APLLMCS_MCU_RUN_SELINPFREQ_26_M \ 0x00000007 // Configuration for MCU-APLLMCS : // SELINPFREQ during RUN mode. // Selected if the XTAL frequency is // 26 MHz (from Efuse) #define GPRCM_APLLMCS_MCU_RUN_CONFIG1_26_APLLMCS_MCU_RUN_SELINPFREQ_26_S 0 //****************************************************************************** // // The following are defines for the bit fields in the GPRCM_O_SPARE_RW0 register. // //****************************************************************************** //****************************************************************************** // // The following are defines for the bit fields in the GPRCM_O_SPARE_RW1 register. // //****************************************************************************** //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APLLMCS_MCU_OVERRIDES register. // //****************************************************************************** #define GPRCM_APLLMCS_MCU_OVERRIDES_APLLMCS_MCU_LOCK \ 0x00000400 // 1 - APLLMCS_MCU is locked ; 0 - // APLLMCS_MCU is not locked #define GPRCM_APLLMCS_MCU_OVERRIDES_APLLMCS_MCU_ENABLE_OVERRIDE \ 0x00000200 // Override for APLLMCS_MCU Enable. // Applicable if bit [8] is set #define GPRCM_APLLMCS_MCU_OVERRIDES_APLLMCS_MCU_ENABLE_OVERRIDE_CTRL \ 0x00000100 // 1 - Enable for APLLMCS_MCU comes // from bit [9]. 0 - Enable for // APLLMCS_MCU comes from FSM. #define GPRCM_APLLMCS_MCU_OVERRIDES_SYSCLK_SRC_OVERRIDE_M \ 0x00000006 // Override for sysclk src // (applicable only if bit [0] is // set to 1. "00"- SLOW_CLK "01"- // XTAL_CLK "10"- PLL_CLK #define GPRCM_APLLMCS_MCU_OVERRIDES_SYSCLK_SRC_OVERRIDE_S 1 #define GPRCM_APLLMCS_MCU_OVERRIDES_SYSCLK_SRC_OVERRIDE_CTRL \ 0x00000001 // 1 - Sysclk src is selected from // bits [2:1] of this register. 0 - // Sysclk src is selected from FSM //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_SYSCLK_SWITCH_STATUS register. // //****************************************************************************** #define GPRCM_SYSCLK_SWITCH_STATUS_SYSCLK_SWITCH_STATUS \ 0x00000001 // 1 - Sysclk switching is // complete. 0 - Sysclk switching is // in progress. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_LDO_CONTROLS register. // //****************************************************************************** #define GPRCM_REF_LDO_CONTROLS_REF_LDO_ENABLE_OVERRIDE_CTRL \ 0x00010000 // 1 - Enable for REF_LDO comes // from bit [0] of this register ; 0 // - Enable for REF_LDO comes from // the FSM. Note : Final REF_LDO_EN // reaches on the port // TOP_PM_REG2[0] of gprcm. #define GPRCM_REF_LDO_CONTROLS_REF_SPARE_CONTROL_M \ 0x0000C000 // Spare bits for REF_CTRL_FSM. // Reaches directly on port // TOP_PM_REG2[15:14] of gprcm. #define GPRCM_REF_LDO_CONTROLS_REF_SPARE_CONTROL_S 14 #define GPRCM_REF_LDO_CONTROLS_REF_TLOAD_ENABLE_M \ 0x00003800 // REF TLOAD Enable. Reaches // directly on port // TOP_PM_REG2[13:11] of gprcm. #define GPRCM_REF_LDO_CONTROLS_REF_TLOAD_ENABLE_S 11 #define GPRCM_REF_LDO_CONTROLS_REF_LDO_TMUX_CONTROL_M \ 0x00000700 // REF_LDO Test-mux control. // Reaches directly on port // TOP_PM_REG2[10:8] of gprcm. #define GPRCM_REF_LDO_CONTROLS_REF_LDO_TMUX_CONTROL_S 8 #define GPRCM_REF_LDO_CONTROLS_REF_BW_CONTROL_M \ 0x000000C0 // REF BW Control. Reaches directly // on port TOP_PM_REG2[7:6] of // gprcm. #define GPRCM_REF_LDO_CONTROLS_REF_BW_CONTROL_S 6 #define GPRCM_REF_LDO_CONTROLS_REF_VTRIM_CONTROL_M \ 0x0000003C // REF VTRIM Control. Reaches // directly on port TOP_PM_REG2[5:2] // of gprcm. #define GPRCM_REF_LDO_CONTROLS_REF_VTRIM_CONTROL_S 2 #define GPRCM_REF_LDO_CONTROLS_REF_LDO_BYPASS_ENABLE \ 0x00000002 // REF LDO Bypass Enable. Reaches // directly on port TOP_PM_REG2[1] // of gprcm. #define GPRCM_REF_LDO_CONTROLS_REF_LDO_ENABLE \ 0x00000001 // Override for REF_LDO Enable. // Applicable only if bit [16] of // this register is set. Note : // Final REF_LDO_EN reaches on the // port TOP_PM_REG2[0] of gprcm. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_RTRIM_CONTROL register. // //****************************************************************************** #define GPRCM_REF_RTRIM_CONTROL_TOP_PM_REG0_5_4_M \ 0x18000000 // This is [5:4] bits of // TOP_PM_REG0 #define GPRCM_REF_RTRIM_CONTROL_TOP_PM_REG0_5_4_S 27 #define GPRCM_REF_RTRIM_CONTROL_TOP_CLKM_REG0_15_5_M \ 0x07FF0000 // This is [15:5] bits of // TOP_CLKM_REG0 #define GPRCM_REF_RTRIM_CONTROL_TOP_CLKM_REG0_15_5_S 16 #define GPRCM_REF_RTRIM_CONTROL_REF_CLKM_RTRIM_OVERRIDE_CTRL \ 0x00000100 // 1 - CLKM_RTRIM comes for // bits[4:0] of this register. 0 - // CLKM_RTRIM comes from Efuse // (after efuse_done = 1). #define GPRCM_REF_RTRIM_CONTROL_REF_CLKM_RTRIM_M \ 0x0000001F // CLKM_TRIM Override. Applicable // when efuse_done = 0 or bit[8] is // set to 1. #define GPRCM_REF_RTRIM_CONTROL_REF_CLKM_RTRIM_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_SLICER_CONTROLS0 register. // //****************************************************************************** #define GPRCM_REF_SLICER_CONTROLS0_CLK_EN_WLAN_LOWV_OVERRIDE_CTRL \ 0x00200000 // 1 - EN_DIG_BUF_TOP comes from // bit [14] of this register. 0 - // EN_DIG_BUF_TOP comes from the // FSM. Note : Final EN_DIG_BUF_WLAN // reaches on TOP_CLKM_REG1_IN[14] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_CLK_EN_TOP_LOWV_OVERRIDE_CTRL \ 0x00100000 // 1 - EN_DIG_BUF_TOP comes from // bit [15] of this register. 0 - // EN_DIG_BUF_TOP comes from the // FSM. Note : Final EN_DIG_BUF_TOP // reaches on TOP_CLKM_REG1_IN[15] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_EN_XTAL_OVERRIDE_CTRL \ 0x00080000 // 1 - EN_XTAL comes from bit [3] // of this register. 0 - EN_XTAL // comes from FSM. Note : Final // XTAL_EN reaches on // TOP_CLKM_REG1_IN[3] of gprcm. #define GPRCM_REF_SLICER_CONTROLS0_EN_SLI_HV_OVERRIDE_CTRL \ 0x00040000 // 1 - Enable HV Slicer comes from // bit [2] of this register. 0 - // Enable HV Slicer comes from FSM. // Note : Final HV_SLICER_EN reaches // on port TOP_CLKM_REG1_IN[1] of // gprcm. #define GPRCM_REF_SLICER_CONTROLS0_EN_SLI_LV_OVERRIDE_CTRL \ 0x00020000 // 1 - Enable LV Slicer comes from // bit[1] of this register. 0 - // Enable LV Slicer comes from FSM. // Note : final LV_SLICER_EN reaches // on port TOP_CLKM_REG1_IN[2] of // gprcm. #define GPRCM_REF_SLICER_CONTROLS0_EN_SLI_HV_PDN_OVERRIDE_CTRL \ 0x00010000 // 1 - Enable HV Pull-down comes // from bit[0] of this register. 0 - // Enable HV Pull-down comes from // FSM. Note : Final HV_PULL_DOWN // reaches on port // TOP_CLKM_REG1_IN[0] of gprcm. #define GPRCM_REF_SLICER_CONTROLS0_CLK_EN_TOP_LOWV \ 0x00008000 // Override for EN_DIG_BUF_TOP. // Applicable if bit[20] is set to // 1. Note : Final EN_DIG_BUF_TOP // reaches on TOP_CLKM_REG1_IN[15] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_CLK_EN_WLAN_LOWV \ 0x00004000 // Override for EN_DIG_BUF_WLAN. // Applicable if bit[19] is set to // 1. Note : Final EN_DIG_BUF_WLAN // reaches on TOP_CLKM_REG1_IN[14] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_CLKOUT_FLIP_EN \ 0x00002000 // CLKOUT Flip Enable. Reaches on // bit[13] of TOP_CLKM_REG1_IN[13] // port of gprcm. #define GPRCM_REF_SLICER_CONTROLS0_EN_DIV2_WLAN_CLK \ 0x00001000 // Enable divide2 in WLAN Clk-path. // Reaches on TOP_CLKM_REG1_IN[12] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_EN_DIV3_WLAN_CLK \ 0x00000800 // Enable divide3 in WLAN Clk-path. // Reaches on TOP_CLKM_REG1_IN[11] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_EN_DIV4_WLAN_CLK \ 0x00000400 // Enable divide4 in WLAN Clk-path. // Reaches on TOP_CLKM_REG1_IN[10] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_CM_TMUX_SEL_LOWV_M \ 0x000003C0 // CM Test-mux select. Reaches on // TOP_CLMM_REG1_IN[9:6] port of // gprcm #define GPRCM_REF_SLICER_CONTROLS0_CM_TMUX_SEL_LOWV_S 6 #define GPRCM_REF_SLICER_CONTROLS0_SLICER_SPARE0_M \ 0x00000030 // Slicer spare0 control. Reaches // on TOP_CLKM_REG1_IN[5:4] port of // gprcm #define GPRCM_REF_SLICER_CONTROLS0_SLICER_SPARE0_S 4 #define GPRCM_REF_SLICER_CONTROLS0_EN_XTAL \ 0x00000008 // Enable XTAL override. Reaches on // TOP_CLKM_REG1_IN[3] port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_EN_SLICER_HV \ 0x00000004 // Enable HV Slicer override. // Reaches on TOP_CLKM_REG1_IN[1] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_EN_SLICER_LV \ 0x00000002 // Enable LV Slicer override. // Reaches on TOP_CLKM_REG1_IN[2] // port of gprcm #define GPRCM_REF_SLICER_CONTROLS0_EN_SLICER_HV_PDN \ 0x00000001 // Enable HV Pull-down override. // Reaches on TOP_CLKM_REG1_IN[0] // port of gprcm //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_SLICER_CONTROLS1 register. // //****************************************************************************** #define GPRCM_REF_SLICER_CONTROLS1_SLICER_SPARE1_M \ 0x0000FC00 // Slicer spare1. Reaches on port // TOP_CLKM_REG2_IN[15:10] of gprcm. #define GPRCM_REF_SLICER_CONTROLS1_SLICER_SPARE1_S 10 #define GPRCM_REF_SLICER_CONTROLS1_XOSC_TRIM_M \ 0x000003F0 // XOSC Trim. Reaches on port // TOP_CLKM_REG2_IN[9:4] of gprcm #define GPRCM_REF_SLICER_CONTROLS1_XOSC_TRIM_S 4 #define GPRCM_REF_SLICER_CONTROLS1_SLICER_ITRIM_CHANGE_TOGGLE \ 0x00000008 // Slicer ITRIM Toggle. Reaches on // port TOP_CLKM_REG2_IN[3] of // gprcm. #define GPRCM_REF_SLICER_CONTROLS1_SLICER_LV_TRIM_M \ 0x00000007 // LV Slicer trim. Reaches on port // TOP_CLKM_REG2_IN[2:0] of gprcm. #define GPRCM_REF_SLICER_CONTROLS1_SLICER_LV_TRIM_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_ANA_BGAP_CONTROLS0 register. // //****************************************************************************** #define GPRCM_REF_ANA_BGAP_CONTROLS0_reserved_M \ 0xFF800000 #define GPRCM_REF_ANA_BGAP_CONTROLS0_reserved_S 23 #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_mag_trim_override_ctrl \ 0x00400000 // 1 - REF_MAG_TRIM comes from // bit[4:0] of register // REF_ANA_BGAP_CONTROLS1 [Addr : // 0x0850]; 0 - REF_MAG_TRIM comes // from efuse (After efc_done = 1). // Note : Final REF_MAG_TRIM reaches // on port TOP_PM_REG1[4:0] of gprcm #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_trim_override_ctrl \ 0x00200000 // 1 - REF_V2I_TRIM comes from // bit[9:6] of this register ; 0 - // REF_V2I_TRIM comes from efuse // (After efc_done = 1). Note : // Final REF_V2I_TRIM reaches on // port TOP_PM_REG0[9:6] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_temp_trim_override_ctrl \ 0x00100000 // 1 - REF_TEMP_TRIM comes from // bit[15:10] of this register ; 0 - // REF_TEMP_TRIM comes from efuse // (After efc_done = 1). Note : // Final REF_TEMP_TRIM reaches on // port TOP_PM_REG0[15:10] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_startup_en_override_ctrl \ 0x00080000 // 1 - REF_STARTUP_EN comes from // bit [3] of this register ; 0 - // REF_STARTUP_EN comes from FSM. // Note : Final REF_STARTUP_EN // reaches on port TOP_PM_REG0[3] of // gprcm #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_en_override_ctrl \ 0x00040000 // 1 - REF_V2I_EN comes from bit // [2] of this register ; 0 - // REF_V2I_EN comes from FSM. Note : // Final REF_V2I_EN reaches on port // TOP_PM_REG0[2] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_fc_en_override_ctrl \ 0x00020000 // 1 - REF_FC_EN comes from bit [1] // of this register ; 0 - REF_FC_EN // comes from FSM. Note : Final // REF_FC_EN reaches on port // TOP_PM_REG0[1] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_bgap_en_override_ctrl \ 0x00010000 // 1 - REF_BGAP_EN comes from bit // [0] of this register ; 0 - // REF_BGAP_EN comes from FSM. Note // : Final REF_BGAP_EN reaches on // port TOP_PM_REG0[0] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_temp_trim_M \ 0x0000FC00 // REF_TEMP_TRIM override. // Applicable when bit [20] of this // register set to 1. (or efc_done = // 0) Note : Final REF_TEMP_TRIM // reaches on port // TOP_PM_REG0[15:10] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_temp_trim_S 10 #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_trim_M \ 0x000003C0 // REF_V2I_TRIM Override. // Applicable when bit [21] of this // register set to 1 . (of efc_done // = 0) Note : Final REF_V2I_TRIM // reaches on port TOP_PM_REG0[9:6] // of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_trim_S 6 #define GPRCM_REF_ANA_BGAP_CONTROLS0_NU1_M \ 0x00000030 #define GPRCM_REF_ANA_BGAP_CONTROLS0_NU1_S 4 #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_startup_en \ 0x00000008 // REF_STARTUP_EN override. // Applicable when bit [19] of this // register is set to 1. Note : // Final REF_STARTUP_EN reaches on // port TOP_PM_REG0[3] of gprcm #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_en \ 0x00000004 // REF_V2I_EN override. Applicable // when bit [21] of this register is // set to 1. Note : Final REF_V2I_EN // reaches on port TOP_PM_REG0[2] of // gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_fc_en \ 0x00000002 // REF_FC_EN override. Applicable // when bit [17] of this register is // set to 1. Note : Final REF_FC_EN // reaches on port TOP_PM_REG0[1] of // gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_bgap_en \ 0x00000001 // REF_BGAP_EN override. Applicable // when bit [16] of this register // set to 1. Note : Final // REF_BGAP_EN reaches on port // TOP_PM_REG0[0] of gprcm. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_ANA_BGAP_CONTROLS1 register. // //****************************************************************************** #define GPRCM_REF_ANA_BGAP_CONTROLS1_reserved_M \ 0xFFFF0000 #define GPRCM_REF_ANA_BGAP_CONTROLS1_reserved_S 16 #define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_bg_spare_M \ 0x0000C000 // REF_BGAP_SPARE. Reaches on port // TOP_PM_REG1[15:14] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_bg_spare_S 14 #define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_bgap_tmux_ctrl_M \ 0x00003E00 // REF_BGAP_TMUX_CTRL. Reaches on // port TOP_PM_REG1[13:9] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_bgap_tmux_ctrl_S 9 #define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_filt_trim_M \ 0x000001E0 // REF_FILT_TRIM. Reaches on port // TOP_PM_REG1[8:5] of gprcm. #define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_filt_trim_S 5 #define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_mag_trim_M \ 0x0000001F // REF_MAG_TRIM Override. // Applicable when bit[22] of // REF_ANA_BGAP_CONTROLS0 [0x084C] // set to 1 (of efc_done = 0). Note // : Final REF_MAG_TRIM reaches on // port TOP_PM_REG1[4:0] of gprcm #define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_mag_trim_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_ANA_SPARE_CONTROLS0 register. // //****************************************************************************** #define GPRCM_REF_ANA_SPARE_CONTROLS0_reserved_M \ 0xFFFF0000 #define GPRCM_REF_ANA_SPARE_CONTROLS0_reserved_S 16 #define GPRCM_REF_ANA_SPARE_CONTROLS0_mem_top_pm_reg3_M \ 0x0000FFFF // Spare control. Reaches on // TOP_PM_REG3 [15:0] of gprcm. #define GPRCM_REF_ANA_SPARE_CONTROLS0_mem_top_pm_reg3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_ANA_SPARE_CONTROLS1 register. // //****************************************************************************** #define GPRCM_REF_ANA_SPARE_CONTROLS1_mem_top_clkm_reg3_M \ 0xFFFF0000 // Spare control. Reaches on // TOP_CLKM_REG3 [15:0] of gprcm. #define GPRCM_REF_ANA_SPARE_CONTROLS1_mem_top_clkm_reg3_S 16 #define GPRCM_REF_ANA_SPARE_CONTROLS1_mem_top_clkm_reg4_M \ 0x0000FFFF // Spare control. Reaches on // TOP_CLKM_REG4 [15:0] of gprcm. #define GPRCM_REF_ANA_SPARE_CONTROLS1_mem_top_clkm_reg4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEMSS_PSCON_OVERRIDES0 register. // //****************************************************************************** #define GPRCM_MEMSS_PSCON_OVERRIDES0_mem_memss_pscon_mem_off_override_M \ 0xFFFF0000 #define GPRCM_MEMSS_PSCON_OVERRIDES0_mem_memss_pscon_mem_off_override_S 16 #define GPRCM_MEMSS_PSCON_OVERRIDES0_mem_memss_pscon_mem_retain_override_M \ 0x0000FFFF #define GPRCM_MEMSS_PSCON_OVERRIDES0_mem_memss_pscon_mem_retain_override_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEMSS_PSCON_OVERRIDES1 register. // //****************************************************************************** #define GPRCM_MEMSS_PSCON_OVERRIDES1_reserved_M \ 0xFFFFFFC0 #define GPRCM_MEMSS_PSCON_OVERRIDES1_reserved_S 6 #define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_mem_update_override_ctrl \ 0x00000020 #define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_mem_update_override \ 0x00000010 #define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_sleep_override_ctrl \ 0x00000008 #define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_sleep_override \ 0x00000004 #define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_mem_off_override_ctrl \ 0x00000002 #define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memms_pscon_mem_retain_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_PLL_REF_LOCK_OVERRIDES register. // //****************************************************************************** #define GPRCM_PLL_REF_LOCK_OVERRIDES_reserved_M \ 0xFFFFFFF8 #define GPRCM_PLL_REF_LOCK_OVERRIDES_reserved_S 3 #define GPRCM_PLL_REF_LOCK_OVERRIDES_mem_mcu_apllmcs_lock_override \ 0x00000004 #define GPRCM_PLL_REF_LOCK_OVERRIDES_mem_wlan_apllmcs_lock_override \ 0x00000002 #define GPRCM_PLL_REF_LOCK_OVERRIDES_mem_ref_clk_valid_override \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MCU_PSCON_DEBUG register. // //****************************************************************************** #define GPRCM_MCU_PSCON_DEBUG_reserved_M \ 0xFFFFFFC0 #define GPRCM_MCU_PSCON_DEBUG_reserved_S 6 #define GPRCM_MCU_PSCON_DEBUG_mcu_pscon_rtc_ps_M \ 0x00000038 // MCU_PSCON_RTC_ON = "0000"; // MCU_PSCON_RTC_OFF = "0001"; // MCU_PSCON_RTC_RET = "0010"; // MCU_PSCON_RTC_OFF_TO_ON = "0011"; // MCU_PSCON_RTC_RET_TO_ON = "0100"; // MCU_PSCON_RTC_ON_TO_RET = "0101"; // MCU_PSCON_RTC_ON_TO_OFF = "0110"; // MCU_PSCON_RTC_RET_TO_ON_WAIT_OPP // = "0111"; // MCU_PSCON_RTC_OFF_TO_ON_WAIT_OPP // = "1000"; #define GPRCM_MCU_PSCON_DEBUG_mcu_pscon_rtc_ps_S 3 #define GPRCM_MCU_PSCON_DEBUG_mcu_pscon_sys_ps_M \ 0x00000007 #define GPRCM_MCU_PSCON_DEBUG_mcu_pscon_sys_ps_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEMSS_PWR_PS register. // //****************************************************************************** #define GPRCM_MEMSS_PWR_PS_reserved_M \ 0xFFFFFFF8 #define GPRCM_MEMSS_PWR_PS_reserved_S 3 #define GPRCM_MEMSS_PWR_PS_pwr_ps_memss_M \ 0x00000007 // MEMSS_PM_SLEEP = "000"; // MEMSS_PM_WAIT_OPP = "010"; // MEMSS_PM_ACTIVE = "011"; // MEMSS_PM_SLEEP_TO_ACTIVE = "100"; // MEMSS_PM_ACTIVE_TO_SLEEP = "101"; #define GPRCM_MEMSS_PWR_PS_pwr_ps_memss_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_REF_FSM_DEBUG register. // //****************************************************************************** #define GPRCM_REF_FSM_DEBUG_reserved_M \ 0xFFFFFFC0 #define GPRCM_REF_FSM_DEBUG_reserved_S 6 #define GPRCM_REF_FSM_DEBUG_fref_mode_M \ 0x00000030 // 01 - HV Mode ; 10 - LV Mode ; 11 // - XTAL Mode #define GPRCM_REF_FSM_DEBUG_fref_mode_S 4 #define GPRCM_REF_FSM_DEBUG_ref_fsm_ps_M \ 0x0000000F // constant FREF_CLK_OFF = "00000"; // constant FREF_EN_BGAP = "00001"; // constant FREF_EN_LDO = "00010"; // constant FREF_EN_SLI_HV = // "00011"; constant // FREF_EN_SLI_HV_PD = "00100"; // constant FREF_EN_DIG_BUF = // "00101"; constant FREF_EN_OSC = // "00110"; constant FREF_EN_SLI_LV // = "00111"; constant // FREF_EN_CLK_REQ = "01000"; // constant FREF_CLK_VALID = // "01001"; constant FREF_MODE_DET0 // = "01010"; constant // FREF_MODE_DET1 = "01011"; // constant FREF_MODE_DET2 = // "10010"; constant FREF_MODE_DET3 // = "10011"; constant FREF_VALID = // "01100"; constant FREF_VALID0 = // "01101"; constant FREF_VALID1 = // "01110"; constant FREF_VALID2 = // "01111"; constant // FREF_WAIT_EXT_TCXO0 = "10000"; // constant FREF_WAIT_EXT_TCXO1 = // "10001"; #define GPRCM_REF_FSM_DEBUG_ref_fsm_ps_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_SYS_OPP_REQ_OVERRIDE register. // //****************************************************************************** #define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_reserved_M \ 0xFFFFFFE0 #define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_reserved_S 5 #define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_mem_sys_opp_req_override_ctrl \ 0x00000010 // 1 - Override the sytem-opp // request to ANATOP using bit0 of // this register #define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_mem_sys_opp_req_override_M \ 0x0000000F // "0001" - RUN ; "0010" - DSLP ; // "0100" - LPDS ; Others - NA #define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_mem_sys_opp_req_override_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_TESTCTRL_PD_OPP_CONFIG register. // //****************************************************************************** #define GPRCM_MEM_TESTCTRL_PD_OPP_CONFIG_reserved_M \ 0xFFFFFFFE #define GPRCM_MEM_TESTCTRL_PD_OPP_CONFIG_reserved_S 1 #define GPRCM_MEM_TESTCTRL_PD_OPP_CONFIG_mem_sleep_opp_enter_with_testpd_on \ 0x00000001 // 1 - Enable sleep-opp (DSLP/LPDS) // entry even if Test-Pd is kept ON // ; 0 - Donot enable sleep-opp // (DSLP/LPDS) entry with Test-Pd // ON. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_WL_FAST_CLK_REQ_OVERRIDES register. // //****************************************************************************** #define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_reserved_M \ 0xFFFFFFF8 #define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_reserved_S 3 #define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_mem_wl_fast_clk_req_override_ctrl \ 0x00000004 // NA #define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_mem_wl_fast_clk_req_override \ 0x00000002 // NA #define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_mem_wl_sleep_with_clk_req_override \ 0x00000001 // NA //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_MCU_PD_MODE_REQ_OVERRIDES register. // //****************************************************************************** #define GPRCM_MEM_MCU_PD_MODE_REQ_OVERRIDES_mem_mcu_pd_mode_req_override_ctrl \ 0x00000004 // 1 - Override the MCU-PD power // modes using bits [1] & [0] ; #define GPRCM_MEM_MCU_PD_MODE_REQ_OVERRIDES_mem_mcu_pd_pwrdn_req_override \ 0x00000002 // 1 - Request for power-down of // MCU-PD ; #define GPRCM_MEM_MCU_PD_MODE_REQ_OVERRIDES_mem_mcu_pd_ret_req_override \ 0x00000001 // 1 - Request for retention mode // of MCU-PD. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_MCSPI_SRAM_OFF_REQ_OVERRIDES register. // //****************************************************************************** #define GPRCM_MEM_MCSPI_SRAM_OFF_REQ_OVERRIDES_mem_mcspi_sram_off_req_override_ctrl \ 0x00000002 // 1- Override the MCSPI // (Autonomous SPI) memory state // using bit [0] #define GPRCM_MEM_MCSPI_SRAM_OFF_REQ_OVERRIDES_mem_mcspi_sram_off_req_override \ 0x00000001 // 1 - Request for power-down of // Autonomous SPI 8k memory ; 0 - // Donot request power-down of // Autonomous SPI 8k Memory //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_WLAN_APLLMCS_OVERRIDES register. // //****************************************************************************** #define GPRCM_MEM_WLAN_APLLMCS_OVERRIDES_wlan_apllmcs_lock \ 0x00000100 #define GPRCM_MEM_WLAN_APLLMCS_OVERRIDES_mem_wlan_apllmcs_enable_override \ 0x00000002 #define GPRCM_MEM_WLAN_APLLMCS_OVERRIDES_mem_wlan_apllmcs_enable_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_REF_FSM_CFG2 register. // //****************************************************************************** #define GPRCM_MEM_REF_FSM_CFG2_MEM_FC_DEASSERT_DELAY_M \ 0x00380000 // Number of RTC clocks for keeping // the FC_EN asserted high #define GPRCM_MEM_REF_FSM_CFG2_MEM_FC_DEASSERT_DELAY_S 19 #define GPRCM_MEM_REF_FSM_CFG2_MEM_STARTUP_DEASSERT_DELAY_M \ 0x00070000 // Number of RTC clocks for keeping // the STARTUP_EN asserted high #define GPRCM_MEM_REF_FSM_CFG2_MEM_STARTUP_DEASSERT_DELAY_S 16 #define GPRCM_MEM_REF_FSM_CFG2_MEM_EXT_TCXO_SETTLING_TIME_M \ 0x0000FFFF // Number of RTC clocks for waiting // for clock to settle. #define GPRCM_MEM_REF_FSM_CFG2_MEM_EXT_TCXO_SETTLING_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_TESTCTRL_POWER_CTRL register. // //****************************************************************************** #define GPRCM_TESTCTRL_POWER_CTRL_TESTCTRL_PD_STATUS_M \ 0x00000006 #define GPRCM_TESTCTRL_POWER_CTRL_TESTCTRL_PD_STATUS_S 1 #define GPRCM_TESTCTRL_POWER_CTRL_TESTCTRL_PD_ENABLE \ 0x00000001 // 0 - Disable the TestCtrl-pd ; 1 // - Enable the TestCtrl-pd. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_SSDIO_POWER_CTRL register. // //****************************************************************************** #define GPRCM_SSDIO_POWER_CTRL_SSDIO_PD_STATUS_M \ 0x00000006 // 1 - SSDIO-PD is ON ; 0 - // SSDIO-PD is OFF #define GPRCM_SSDIO_POWER_CTRL_SSDIO_PD_STATUS_S 1 #define GPRCM_SSDIO_POWER_CTRL_SSDIO_PD_ENABLE \ 0x00000001 // 0 - Disable the SSDIO-pd ; 1 - // Enable the SSDIO-pd. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MCSPI_N1_POWER_CTRL register. // //****************************************************************************** #define GPRCM_MCSPI_N1_POWER_CTRL_MCSPI_N1_PD_STATUS_M \ 0x00000006 // 1 - MCSPI_N1-PD is ON ; 0 - // MCSPI_N1-PD if OFF #define GPRCM_MCSPI_N1_POWER_CTRL_MCSPI_N1_PD_STATUS_S 1 #define GPRCM_MCSPI_N1_POWER_CTRL_MCSPI_N1_PD_ENABLE \ 0x00000001 // 0 - Disable the MCSPI_N1-pd ; 1 // - Enable the MCSPI_N1-pd. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WELP_POWER_CTRL register. // //****************************************************************************** #define GPRCM_WELP_POWER_CTRL_WTOP_PD_STATUS_M \ 0x00001C00 #define GPRCM_WELP_POWER_CTRL_WTOP_PD_STATUS_S 10 #define GPRCM_WELP_POWER_CTRL_WTOP_PD_REQ_OVERRIDE \ 0x00000200 #define GPRCM_WELP_POWER_CTRL_WTOP_PD_REQ_OVERRIDE_CTRL \ 0x00000100 #define GPRCM_WELP_POWER_CTRL_WELP_PD_STATUS_M \ 0x00000006 #define GPRCM_WELP_POWER_CTRL_WELP_PD_STATUS_S 1 #define GPRCM_WELP_POWER_CTRL_WELP_PD_ENABLE \ 0x00000001 // 0 - Disable the WELP-pd ; 1 - // Enable the WELP-pd. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WL_SDIO_POWER_CTRL register. // //****************************************************************************** #define GPRCM_WL_SDIO_POWER_CTRL_WL_SDIO_PD_STATUS_M \ 0x00000006 #define GPRCM_WL_SDIO_POWER_CTRL_WL_SDIO_PD_STATUS_S 1 #define GPRCM_WL_SDIO_POWER_CTRL_WL_SDIO_PD_ENABLE \ 0x00000001 // 0 - Disable the WL_SDIO-pd ; 1 - // Enable the WL_SDIO-pd. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WLAN_SRAM_ACTIVE_PWR_CFG register. // //****************************************************************************** #define GPRCM_WLAN_SRAM_ACTIVE_PWR_CFG_WLAN_SRAM_ACTIVE_PWR_CFG_M \ 0x00FFFFFF // SRAM (WTOP+DRP) state during // Active-mode : 1 - SRAMs are ON ; // 0 - SRAMs are OFF. Cluster // information : [0] - 1st column of // MEMSS (Applicable only when owned // by WTOP/PHY) [1] - 2nd column of // MEMSS (Applicable only when owned // by WTOP/PHY) ; [2] - 3rd column // of MEMSS (Applicable only when // owned by WTOP/PHY) ; [3] - 4th // column of MEMSS (Applicable only // when owned by WTOP/PHY) ; [4] - // 5th column of MEMSS (Applicable // only when owned by WTOP/PHY) ; // [5] - 6th column of MEMSS // (Applicable only when owned by // WTOP/PHY) ; [6] - 7th column of // MEMSS (Applicable only when owned // by WTOP/PHY) ; [7] - 8th column // of MEMSS (Applicable only when // owned by WTOP/PHY) ; [8] - 9th // column of MEMSS (Applicable only // when owned by WTOP/PHY) ; [9] - // 10th column of MEMSS (Applicable // only when owned by WTOP/PHY) ; // [10] - 11th column of MEMSS // (Applicable only when owned by // WTOP/PHY) ; [11] - 12th column of // MEMSS (Applicable only when owned // by WTOP/PHY) ; [12] - 13th column // of MEMSS (Applicable only when // owned by WTOP/PHY) ; [13] - 14th // column of MEMSS (Applicable only // when owned by WTOP/PHY) ; [14] - // 15th column of MEMSS (Applicable // only when owned by WTOP/PHY) ; // [15] - 16th column of MEMSS // (Applicable only when owned by // WTOP/PHY) ; [23:16] - Internal to // WTOP Cluster #define GPRCM_WLAN_SRAM_ACTIVE_PWR_CFG_WLAN_SRAM_ACTIVE_PWR_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WLAN_SRAM_SLEEP_PWR_CFG register. // //****************************************************************************** #define GPRCM_WLAN_SRAM_SLEEP_PWR_CFG_WLAN_SRAM_SLEEP_PWR_CFG_M \ 0x00FFFFFF // SRAM (WTOP+DRP) state during // Sleep-mode : 1 - SRAMs are RET ; // 0 - SRAMs are OFF. Cluster // information : [0] - 1st column of // MEMSS (Applicable only when owned // by WTOP/PHY) [1] - 2nd column of // MEMSS (Applicable only when owned // by WTOP/PHY) ; [2] - 3rd column // of MEMSS (Applicable only when // owned by WTOP/PHY) ; [3] - 4th // column of MEMSS (Applicable only // when owned by WTOP/PHY) ; [4] - // 5th column of MEMSS (Applicable // only when owned by WTOP/PHY) ; // [5] - 6th column of MEMSS // (Applicable only when owned by // WTOP/PHY) ; [6] - 7th column of // MEMSS (Applicable only when owned // by WTOP/PHY) ; [7] - 8th column // of MEMSS (Applicable only when // owned by WTOP/PHY) ; [8] - 9th // column of MEMSS (Applicable only // when owned by WTOP/PHY) ; [9] - // 10th column of MEMSS (Applicable // only when owned by WTOP/PHY) ; // [10] - 11th column of MEMSS // (Applicable only when owned by // WTOP/PHY) ; [11] - 12th column of // MEMSS (Applicable only when owned // by WTOP/PHY) ; [12] - 13th column // of MEMSS (Applicable only when // owned by WTOP/PHY) ; [13] - 14th // column of MEMSS (Applicable only // when owned by WTOP/PHY) ; [14] - // 15th column of MEMSS (Applicable // only when owned by WTOP/PHY) ; // [15] - 16th column of MEMSS // (Applicable only when owned by // WTOP/PHY) ; [23:16] - Internal to // WTOP Cluster #define GPRCM_WLAN_SRAM_SLEEP_PWR_CFG_WLAN_SRAM_SLEEP_PWR_CFG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_SECURE_INIT_DONE register. // //****************************************************************************** #define GPRCM_APPS_SECURE_INIT_DONE_SECURE_INIT_DONE_STATUS \ 0x00000002 // 1-Secure mode init is done ; // 0-Secure mode init is not done #define GPRCM_APPS_SECURE_INIT_DONE_APPS_SECURE_INIT_DONE \ 0x00000001 // Must be programmed 1 in order to // say that secure-mode device init // is done //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_DEV_MODE_INIT_DONE register. // //****************************************************************************** #define GPRCM_APPS_DEV_MODE_INIT_DONE_APPS_DEV_MODE_INIT_DONE \ 0x00000001 // 1 - Patch download and other // initializations are done (before // removing APPS resetn) for // development mode (#3) . 0 - // Development mode (#3) init is not // done yet //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_EN_APPS_REBOOT register. // //****************************************************************************** #define GPRCM_EN_APPS_REBOOT_EN_APPS_REBOOT \ 0x00000001 // 1 - When 1, disable the reboot // of APPS after DevInit is // completed. In this case, APPS // will permanantly help in reset. 0 // - When 0, enable the reboot of // APPS after DevInit is completed. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_APPS_PERIPH_PRESENT register. // //****************************************************************************** #define GPRCM_MEM_APPS_PERIPH_PRESENT_WLAN_GEM_PP \ 0x00010000 // 1 - Enable ; 0 - Disable #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_AES_PP \ 0x00008000 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_DES_PP \ 0x00004000 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_SHA_PP \ 0x00002000 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_CAMERA_PP \ 0x00001000 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_MMCHS_PP \ 0x00000800 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_MCASP_PP \ 0x00000400 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_MCSPI_A1_PP \ 0x00000200 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_MCSPI_A2_PP \ 0x00000100 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_UDMA_PP \ 0x00000080 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_WDOG_PP \ 0x00000040 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_UART_A0_PP \ 0x00000020 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_UART_A1_PP \ 0x00000010 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_GPT_A0_PP \ 0x00000008 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_GPT_A1_PP \ 0x00000004 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_GPT_A2_PP \ 0x00000002 #define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_GPT_A3_PP \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_NWP_PERIPH_PRESENT register. // //****************************************************************************** #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_ASYNC_BRIDGE_PP \ 0x00000200 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_MCSPI_N2_PP \ 0x00000100 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_GPT_N0_PP \ 0x00000080 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_GPT_N1_PP \ 0x00000040 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_WDOG_PP \ 0x00000020 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_UDMA_PP \ 0x00000010 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_UART_N0_PP \ 0x00000008 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_UART_N1_PP \ 0x00000004 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_SSDIO_PP \ 0x00000002 #define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_MCSPI_N1_PP \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MEM_SHARED_PERIPH_PRESENT register. // //****************************************************************************** #define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_MCSPI_PP \ 0x00000040 #define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_I2C_PP \ 0x00000020 #define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_A_PP \ 0x00000010 #define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_B_PP \ 0x00000008 #define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_C_PP \ 0x00000004 #define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_D_PP \ 0x00000002 #define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_E_PP \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_PWR_STATE register. // //****************************************************************************** #define GPRCM_NWP_PWR_STATE_NWP_PWR_STATE_PS_M \ 0x00000F00 // "0000"- PORZ :- NWP is yet to be // enabled by APPS during powerup // (from HIB/OFF) ; "0011"- ACTIVE // :- NWP is enabled, clocks and // resets to NWP-SubSystem are // enabled ; "0010"- LPDS :- NWP is // in LPDS-mode ; Clocks and reset // to NWP-SubSystem are gated ; // "0101"- WAIT_FOR_OPP :- NWP is in // transition from LPDS to ACTIVE, // where it is waiting for OPP to be // stable ; "1000"- // WAKE_TIMER_OPP_REQ :- NWP is in // transition from LPDS, where the // wakeup cause is LPDS_Wake timer // OTHERS : NA #define GPRCM_NWP_PWR_STATE_NWP_PWR_STATE_PS_S 8 #define GPRCM_NWP_PWR_STATE_NWP_RCM_PS_M \ 0x00000007 // "000" - NWP_RUN : NWP is in RUN // state (default) - Applicable only // when NWP_PWR_STATE_PS = ACTIVE ; // "001" - NWP_SLP : NWP is in SLEEP // state (default) - Applicable only // when NWP_PWR_STATE_PS = ACTIVE ; // "010" - NWP_DSLP : NWP is in // Deep-Sleep state (default) - // Applicable only when // NWP_PWR_STATE_PS = ACTIVE ; "011" // - WAIT_FOR_ACTIVE : NWP is in // transition from Deep-sleep to // Run, where it is waiting for OPP // to be stable ; "100" - // WAIT_FOR_DSLP_TIMER_WAKE_REQ : // NWP is in transition from // Deep-sleep to Run, where the // wakeup cause is deep-sleep // wake-timer #define GPRCM_NWP_PWR_STATE_NWP_RCM_PS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_PWR_STATE register. // //****************************************************************************** #define GPRCM_APPS_PWR_STATE_APPS_PWR_STATE_PS_M \ 0x00000F00 // "0000"- PORZ :- APPS is waiting // for PLL_clock during powerup // (from HIB/OFF) ; "0011"- ACTIVE // :- APPS is enabled, clocks and // resets to APPS-SubSystem are // enabled ; APPS might be either in // Secure or Un-secure mode during // this state. "1001" - // SECURE_MODE_LPDS :- While in // ACTIVE (Secure-mode), APPS had to // program the DevInit_done bit at // the end, after which it enters // into this state, where the reset // to APPS will be asserted. From // this state APPS might either // re-boot itself or enter into LPDS // depending upon whether the device // is 3200 or 3100. "0010"- LPDS :- // APPS is in LPDS-mode ; Clocks and // reset to APPS-SubSystem are gated // ; "0101"- WAIT_FOR_OPP :- APPS is // in transition from LPDS to // ACTIVE, where it is waiting for // OPP to be stable ; "1000" - // WAKE_TIMER_OPP_REQ : APPS is in // transition from LPDS, where the // wakeup cause is LPDS_Wake timer ; // "1010" - WAIT_FOR_PATCH_INIT : // APPS enters into this state // during development-mode #3 (SOP = // 3), where it is waiting for patch // download to complete and 0x4 hack // is programmed. OTHERS : NA #define GPRCM_APPS_PWR_STATE_APPS_PWR_STATE_PS_S 8 #define GPRCM_APPS_PWR_STATE_APPS_RCM_PS_M \ 0x00000007 // "000" - APPS_RUN : APPS is in // RUN state (default) - Applicable // only when APPS_PWR_STATE_PS = // ACTIVE ; "001" - APPS_SLP : APPS // is in SLEEP state (default) - // Applicable only when // APPS_PWR_STATE_PS = ACTIVE ; // "010" - APPS_DSLP : APPS is in // Deep-Sleep state (default) - // Applicable only when // APPS_PWR_STATE_PS = ACTIVE ; // "011" - WAIT_FOR_ACTIVE : APPS is // in transition from Deep-sleep to // Run, where it is waiting for OPP // to be stable ; "100" - // WAIT_FOR_DSLP_TIMER_WAKE_REQ : // APPS is in transition from // Deep-sleep to Run, where the // wakeup cause is deep-sleep // wake-timer #define GPRCM_APPS_PWR_STATE_APPS_RCM_PS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MCU_PWR_STATE register. // //****************************************************************************** #define GPRCM_MCU_PWR_STATE_MCU_OPP_PS_M \ 0x0000001F // TBD #define GPRCM_MCU_PWR_STATE_MCU_OPP_PS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WTOP_PM_PS register. // //****************************************************************************** #define GPRCM_WTOP_PM_PS_WTOP_PM_PS_M \ 0x00000007 // "011" - WTOP_PM_ACTIVE (Default) // :- WTOP_Pd is in ACTIVE mode; // "100" - WTOP_PM_ACTIVE_TO_SLEEP // :- WTOP_Pd is in transition from // ACTIVE to SLEEP ; "000" - // WTOP_PM_SLEEP : WTOP-Pd is in // Sleep-state ; "100" - // WTOP_PM_SLEEP_TO_ACTIVE : WTOP_Pd // is in transition from SLEEP to // ACTIVE ; "000" - // WTOP_PM_WAIT_FOR_OPP : Wait for // OPP to be stable ; #define GPRCM_WTOP_PM_PS_WTOP_PM_PS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WTOP_PD_RESETZ_OVERRIDE_REG register. // //****************************************************************************** #define GPRCM_WTOP_PD_RESETZ_OVERRIDE_REG_WTOP_PD_RESETZ_OVERRIDE_CTRL \ 0x00000100 // Override control for WTOP PD // Resetz. When set to 1, // WTOP_Resetz will be controlled by // bit [0] #define GPRCM_WTOP_PD_RESETZ_OVERRIDE_REG_WTOP_PD_RESETZ_OVERRIDE \ 0x00000001 // Override for WTOP PD Resetz. // Applicable only when bit[8] is // set to 1 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WELP_PD_RESETZ_OVERRIDE_REG register. // //****************************************************************************** #define GPRCM_WELP_PD_RESETZ_OVERRIDE_REG_WELP_PD_RESETZ_OVERRIDE_CTRL \ 0x00000100 // Override control for WELP PD // Resetz. When set to 1, // WELP_Resetz will be controlled by // bit [0] #define GPRCM_WELP_PD_RESETZ_OVERRIDE_REG_WELP_PD_RESETZ_OVERRIDE \ 0x00000001 // Override for WELP PD Resetz. // Applicable only when bit[8] is // set to 1 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WL_SDIO_PD_RESETZ_OVERRIDE_REG register. // //****************************************************************************** #define GPRCM_WL_SDIO_PD_RESETZ_OVERRIDE_REG_WL_SDIO_PD_RESETZ_OVERRIDE_CTRL \ 0x00000100 // Override control for WL_SDIO // Resetz. When set to 1, // WL_SDIO_Resetz will be controlled // by bit [0] #define GPRCM_WL_SDIO_PD_RESETZ_OVERRIDE_REG_WL_SDIO_PD_RESETZ_OVERRIDE \ 0x00000001 // Override for WL_SDIO Resetz. // Applicable only when bit[8] is // set to 1 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_SSDIO_PD_RESETZ_OVERRIDE_REG register. // //****************************************************************************** #define GPRCM_SSDIO_PD_RESETZ_OVERRIDE_REG_SSDIO_PD_RESETZ_OVERRIDE_CTRL \ 0x00000100 // Override control for SSDIO // Resetz. When set to 1, // SSDIO_Resetz will be controlled // by bit [0] #define GPRCM_SSDIO_PD_RESETZ_OVERRIDE_REG_SSDIO_PD_RESETZ_OVERRIDE \ 0x00000001 // Override for SSDIO Resetz. // Applicable only when bit[8] is // set to 1 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MCSPI_N1_PD_RESETZ_OVERRIDE_REG register. // //****************************************************************************** #define GPRCM_MCSPI_N1_PD_RESETZ_OVERRIDE_REG_MCSPI_N1_PD_RESETZ_OVERRIDE_CTRL \ 0x00000100 // Override control for MCSPI_N1 // Resetz. When set to 1, // MCSPI_N1_Resetz will be // controlled by bit [0] #define GPRCM_MCSPI_N1_PD_RESETZ_OVERRIDE_REG_MCSPI_N1_PD_RESETZ_OVERRIDE \ 0x00000001 // Override for MCSPI_N1 Resetz. // Applicable only when bit[8] is // set to 1 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_TESTCTRL_PD_RESETZ_OVERRIDE_REG register. // //****************************************************************************** #define GPRCM_TESTCTRL_PD_RESETZ_OVERRIDE_REG_TESTCTRL_PD_RESETZ_OVERRIDE_CTRL \ 0x00000100 // Override control for TESTCTRL-PD // Resetz. When set to 1, // TESTCTRL_Resetz will be // controlled by bit [0] #define GPRCM_TESTCTRL_PD_RESETZ_OVERRIDE_REG_TESTCTRL_PD_RESETZ_OVERRIDE \ 0x00000001 // Override for TESTCTRL Resetz. // Applicable only when bit[8] is // set to 1 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MCU_PD_RESETZ_OVERRIDE_REG register. // //****************************************************************************** #define GPRCM_MCU_PD_RESETZ_OVERRIDE_REG_MCU_PD_RESETZ_OVERRIDE_CTRL \ 0x00000100 // Override control for MCU-PD // Resetz. When set to 1, MCU_Resetz // will be controlled by bit [0] #define GPRCM_MCU_PD_RESETZ_OVERRIDE_REG_MCU_PD_RESETZ_OVERRIDE \ 0x00000001 // Override for MCU Resetz. // Applicable only when bit[8] is // set to 1 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG0 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG0_FUSEFARM_ROW_14_M \ 0xFFFFFFFF // This is ROW_14 [31:0] of // FUSEFARM. [0:0] : XTAL_IS_26MHZ // [5:1] : TOP_CLKM_RTRIM[4:0] // [10:6] : ANA_BGAP_MAG_TRIM[4:0] // [16:11] : ANA_BGAP_TEMP_TRIM[5:0] // [20:17] : ANA_BGAP_V2I_TRIM[3:0] // [25:22] : PROCESS INDICATOR // [26:26] : Reserved [31:27] : // FUSEROM Version #define GPRCM_GPRCM_EFUSE_READ_REG0_FUSEFARM_ROW_14_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG1 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG1_FUSEFARM_ROW_15_LSW_M \ 0x0000FFFF // This is ROW_15[15:0] of FUSEFARM // 1. NWP Peripheral Present bits // [15:8] NWP_GPT_N0_PP [15:15] // NWP_GPT_N1_PP [14:14] NWP_WDOG_PP // [13:13] NWP_UDMA_PP [12:12] // NWP_UART_N0_PP [11:11] // NWP_UART_N1_PP [10:10] // NWP_SSDIO_PP [9:9] // NWP_MCSPI_N1_PP [8:8] 2. Shared // Peripheral Present bits [7:0] // SHARED SPI PP [6:6] // SHARED I2C PP [5:5] SHARED // GPIO-A PP [4:4] SHARED GPIO-B PP // [3:3] SHARED GPIO-C PP [2:2] // SHARED GPIO-D PP [1:1] SHARED // GPIO-E PP [0:0] #define GPRCM_GPRCM_EFUSE_READ_REG1_FUSEFARM_ROW_15_LSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG2 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG2_FUSEFARM_ROW_16_LSW_ROW_15_MSW_M \ 0xFFFFFFFF // This is ROW_16[15:0] & // ROW_15[31:16] of FUSEFARM. // [31:21] - Reserved [20:16] - // CHIP_ID [15:15] - SSBD SOP // Control [14:14] - SSBD TAP // Control [13:2] - APPS Peripheral // Present bits : APPS_CAMERA_PP // [13:13] APPS_MMCHS_PP [12:12] // APPS_MCASP_PP [11:11] // APPS_MCSPI_A1_PP [10:10] // APPS_MCSPI_A2_PP [9:9] // APPS_UDMA_PP [8:8] APPS_WDOG_PP // [7:7] APPS_UART_A0_PP [6:6] // APPS_UART_A1_PP [5:5] // APPS_GPT_A0_PP [4:4] // APPS_GPT_A1_PP [3:3] // APPS_GPT_A2_PP [2:2] // APPS_GPT_A3_PP [1:1] [0:0] - NWP // Peripheral present bits // NWP_ACSPI_PP [0:0] #define GPRCM_GPRCM_EFUSE_READ_REG2_FUSEFARM_ROW_16_LSW_ROW_15_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG3 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG3_FUSEFARM_ROW_17_LSW_ROW_16_MSW_M \ 0xFFFFFFFF // This is ROW_17[15:0] & // ROW_16[31:16] of FUSEFARM : // [31:16] - TEST_TAP_KEY(15:0) // [15:0] - Reserved #define GPRCM_GPRCM_EFUSE_READ_REG3_FUSEFARM_ROW_17_LSW_ROW_16_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WTOP_MEM_RET_CFG register. // //****************************************************************************** #define GPRCM_WTOP_MEM_RET_CFG_WTOP_MEM_RET_CFG \ 0x00000001 // 1 - Soft-compile memories in // WTOP can be turned-off during // WTOP-sleep mode ; 0 - // Soft-compile memories in WTOP // must be kept on during WTOP-sleep // mode. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_COEX_CLK_SWALLOW_CFG0 register. // //****************************************************************************** #define GPRCM_COEX_CLK_SWALLOW_CFG0_Q_FACTOR_M \ 0x007FFFFF // TBD #define GPRCM_COEX_CLK_SWALLOW_CFG0_Q_FACTOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_COEX_CLK_SWALLOW_CFG1 register. // //****************************************************************************** #define GPRCM_COEX_CLK_SWALLOW_CFG1_P_FACTOR_M \ 0x000FFFFF // TBD #define GPRCM_COEX_CLK_SWALLOW_CFG1_P_FACTOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_COEX_CLK_SWALLOW_CFG2 register. // //****************************************************************************** #define GPRCM_COEX_CLK_SWALLOW_CFG2_CONSECUTIVE_SWALLOW_M \ 0x00000018 #define GPRCM_COEX_CLK_SWALLOW_CFG2_CONSECUTIVE_SWALLOW_S 3 #define GPRCM_COEX_CLK_SWALLOW_CFG2_PRBS_GAIN \ 0x00000004 #define GPRCM_COEX_CLK_SWALLOW_CFG2_PRBS_ENABLE \ 0x00000002 #define GPRCM_COEX_CLK_SWALLOW_CFG2_SWALLOW_ENABLE \ 0x00000001 // TBD //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_COEX_CLK_SWALLOW_ENABLE register. // //****************************************************************************** #define GPRCM_COEX_CLK_SWALLOW_ENABLE_COEX_CLK_SWALLOW_ENABLE \ 0x00000001 // 1 - Enable switching of sysclk // to Coex-clk path ; 0 - Disable // switching of sysclk to Coex-clk // path. //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_DCDC_CLK_GEN_CONFIG register. // //****************************************************************************** #define GPRCM_DCDC_CLK_GEN_CONFIG_DCDC_CLK_ENABLE \ 0x00000001 // 1 - Enable the clock for DCDC // (PWM-mode) ; 0 - Disable the // clock for DCDC (PWM-mode) //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG4 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG4_FUSEFARM_ROW_17_MSW_M \ 0x0000FFFF // This corresponds to // ROW_17[31:16] of the FUSEFARM : // [15:0] : TEST_TAP_KEY(31:16) #define GPRCM_GPRCM_EFUSE_READ_REG4_FUSEFARM_ROW_17_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG5 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG5_FUSEFARM_ROW_18_M \ 0xFFFFFFFF // Corresponds to ROW_18 of // FUSEFARM. [29:0] - // MEMSS_COLUMN_SEL_LSW ; [30:30] - // WLAN GEM DISABLE ; [31:31] - // SERIAL WIRE JTAG SELECT #define GPRCM_GPRCM_EFUSE_READ_REG5_FUSEFARM_ROW_18_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG6 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG6_FUSEFARM_ROW_19_LSW_M \ 0x0000FFFF // Corresponds to ROW_19[15:0] of // FUSEFARM. [15:0] : // MEMSS_COLUMN_SEL_MSW #define GPRCM_GPRCM_EFUSE_READ_REG6_FUSEFARM_ROW_19_LSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG7 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG7_FUSEFARM_ROW_20_LSW_ROW_19_MSW_M \ 0xFFFFFFFF // Corresponds to ROW_20[15:0] & // ROW_19[31:16] of FUSEFARM. // FLASH_REGION0 #define GPRCM_GPRCM_EFUSE_READ_REG7_FUSEFARM_ROW_20_LSW_ROW_19_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG8 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG8_FUSEFARM_ROW_21_LSW_ROW_20_MSW_M \ 0xFFFFFFFF // Corresponds to ROW_21[15:0] & // ROW_20[31:16] of FUSEFARM. // FLASH_REGION1 #define GPRCM_GPRCM_EFUSE_READ_REG8_FUSEFARM_ROW_21_LSW_ROW_20_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG9 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG9_FUSEFARM_ROW_22_LSW_ROW_21_MSW_M \ 0xFFFFFFFF // Corresponds to ROW_22[15:0] & // ROW_21[31:16] of FUSEFARM. // FLASH_REGION2 #define GPRCM_GPRCM_EFUSE_READ_REG9_FUSEFARM_ROW_22_LSW_ROW_21_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG10 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG10_FUSEFARM_ROW_23_LSW_ROW_22_MSW_M \ 0xFFFFFFFF // Corresponds to ROW_23[15:0] & // ROW_22[31:16] of FUSEFARM. // FLASH_REGION3 #define GPRCM_GPRCM_EFUSE_READ_REG10_FUSEFARM_ROW_23_LSW_ROW_22_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_EFUSE_READ_REG11 register. // //****************************************************************************** #define GPRCM_GPRCM_EFUSE_READ_REG11_FUSEFARM_ROW_24_LSW_ROW_23_MSW_M \ 0xFFFFFFFF // Corresponds to ROW_24[15:0] & // ROW_23[31:16] of FUSEFARM. // FLASH_DESCRIPTOR #define GPRCM_GPRCM_EFUSE_READ_REG11_FUSEFARM_ROW_24_LSW_ROW_23_MSW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_DIEID_READ_REG0 register. // //****************************************************************************** #define GPRCM_GPRCM_DIEID_READ_REG0_FUSEFARM_191_160_M \ 0xFFFFFFFF // Corresponds to bits [191:160] of // the FUSEFARM. This is ROW_5 of // FUSEFARM [191:160] : [31:0] : // DIE_ID0 [31:0] : DEVX [11:0] DEVY // [23:12] DEVWAF [29:24] DEV_SPARE // [31:30] #define GPRCM_GPRCM_DIEID_READ_REG0_FUSEFARM_191_160_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_DIEID_READ_REG1 register. // //****************************************************************************** #define GPRCM_GPRCM_DIEID_READ_REG1_FUSEFARM_223_192_M \ 0xFFFFFFFF // Corresponds to bits [223:192] of // the FUSEFARM. This is ROW_6 of // FUSEFARM :- DEVLOT [23:0] DEVFAB // [28:24] DEVFABBE [31:29] #define GPRCM_GPRCM_DIEID_READ_REG1_FUSEFARM_223_192_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_DIEID_READ_REG2 register. // //****************************************************************************** #define GPRCM_GPRCM_DIEID_READ_REG2_FUSEFARM_255_224_M \ 0xFFFFFFFF // Corresponds to bits [255:224] of // the FUSEFARM. This is ROW_7 of // FUSEFARM:- DEVDESREV[4:0] // Memrepair[5:5] MakeDefined[16:6] // CHECKSUM[30:17] Reserved : // [31:31] #define GPRCM_GPRCM_DIEID_READ_REG2_FUSEFARM_255_224_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_DIEID_READ_REG3 register. // //****************************************************************************** #define GPRCM_GPRCM_DIEID_READ_REG3_FUSEFARM_287_256_M \ 0xFFFFFFFF // Corresponds to bits [287:256] of // the FUSEFARM. This is ROW_8 of // FUSEFARM :- DIEID0 - DEVREG // [31:0] #define GPRCM_GPRCM_DIEID_READ_REG3_FUSEFARM_287_256_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_GPRCM_DIEID_READ_REG4 register. // //****************************************************************************** #define GPRCM_GPRCM_DIEID_READ_REG4_FUSEFARM_319_288_M \ 0xFFFFFFFF // Corresponds to bits [319:288] of // the FUSEFARM. This is ROW_9 of // FUSEFARM :- [7:0] - VBATMON ; // [13:8] - BUFF_OFFSET ; [15:15] - // DFT_GXG ; [14:14] - DFT_GLX ; // [19:16] - PHY ROM Version ; // [23:20] - MAC ROM Version ; // [27:24] - NWP ROM Version ; // [31:28] - APPS ROM Version #define GPRCM_GPRCM_DIEID_READ_REG4_FUSEFARM_319_288_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_APPS_SS_OVERRIDES register. // //****************************************************************************** #define GPRCM_APPS_SS_OVERRIDES_reserved_M \ 0xFFFFFC00 #define GPRCM_APPS_SS_OVERRIDES_reserved_S 10 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_refclk_gating_override \ 0x00000200 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_refclk_gating_override_ctrl \ 0x00000100 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_pllclk_gating_override \ 0x00000080 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_pllclk_gating_override_ctrl \ 0x00000040 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_por_rstn_override \ 0x00000020 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_sysrstn_override \ 0x00000010 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_sysclk_gating_override \ 0x00000008 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_por_rstn_override_ctrl \ 0x00000004 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_sysrstn_override_ctrl \ 0x00000002 #define GPRCM_APPS_SS_OVERRIDES_mem_apps_sysclk_gating_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_NWP_SS_OVERRIDES register. // //****************************************************************************** #define GPRCM_NWP_SS_OVERRIDES_reserved_M \ 0xFFFFFC00 #define GPRCM_NWP_SS_OVERRIDES_reserved_S 10 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_refclk_gating_override \ 0x00000200 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_refclk_gating_override_ctrl \ 0x00000100 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_pllclk_gating_override \ 0x00000080 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_pllclk_gating_override_ctrl \ 0x00000040 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_por_rstn_override \ 0x00000020 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_sysrstn_override \ 0x00000010 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_sysclk_gating_override \ 0x00000008 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_por_rstn_override_ctrl \ 0x00000004 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_sysrstn_override_ctrl \ 0x00000002 #define GPRCM_NWP_SS_OVERRIDES_mem_nwp_sysclk_gating_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_SHARED_SS_OVERRIDES register. // //****************************************************************************** #define GPRCM_SHARED_SS_OVERRIDES_reserved_M \ 0xFFFFFF00 #define GPRCM_SHARED_SS_OVERRIDES_reserved_S 8 #define GPRCM_SHARED_SS_OVERRIDES_mem_shared_pllclk_gating_override_ctrl \ 0x00000080 #define GPRCM_SHARED_SS_OVERRIDES_mem_shared_pllclk_gating_override \ 0x00000040 #define GPRCM_SHARED_SS_OVERRIDES_mem_shared_refclk_gating_override_ctrl \ 0x00000020 #define GPRCM_SHARED_SS_OVERRIDES_mem_shared_refclk_gating_override \ 0x00000010 #define GPRCM_SHARED_SS_OVERRIDES_mem_shared_rstn_override \ 0x00000008 #define GPRCM_SHARED_SS_OVERRIDES_mem_shared_sysclk_gating_override \ 0x00000004 #define GPRCM_SHARED_SS_OVERRIDES_mem_shared_rstn_override_ctrl \ 0x00000002 #define GPRCM_SHARED_SS_OVERRIDES_mem_shared_sysclk_gating_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_IDMEM_CORE_RST_OVERRIDES register. // //****************************************************************************** #define GPRCM_IDMEM_CORE_RST_OVERRIDES_reserved_M \ 0xFFFFFF00 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_reserved_S 8 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_sysrstn_override \ 0x00000080 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_fmc_rstn_override \ 0x00000040 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_SPARE_RW1 \ 0x00000020 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_piosc_gating_override \ 0x00000010 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_sysrstn_override_ctrl \ 0x00000008 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_fmc_rstn_override_ctrl \ 0x00000004 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_SPARE_RW0 \ 0x00000002 #define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_piosc_gating_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_TOP_DIE_FSM_OVERRIDES register. // //****************************************************************************** #define GPRCM_TOP_DIE_FSM_OVERRIDES_reserved_M \ 0xFFFFF000 #define GPRCM_TOP_DIE_FSM_OVERRIDES_reserved_S 12 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_pwr_switch_pgoodin_override_ctrl \ 0x00000800 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_pwr_switch_pgoodin_override \ 0x00000400 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_hclk_gating_override \ 0x00000200 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_piosc_gating_override \ 0x00000100 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_rstn_override \ 0x00000080 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_pwr_switch_ponin_override \ 0x00000040 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_flash_ready_override \ 0x00000020 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_hclk_gating_override_ctrl \ 0x00000010 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_piosc_gating_override_ctrl \ 0x00000008 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_rstn_override_ctrl \ 0x00000004 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_pwr_switch_ponin_override_ctrl \ 0x00000002 #define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_flash_ready_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MCU_PSCON_OVERRIDES register. // //****************************************************************************** #define GPRCM_MCU_PSCON_OVERRIDES_reserved_M \ 0xFFF00000 #define GPRCM_MCU_PSCON_OVERRIDES_reserved_S 20 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_sleep_override_ctrl \ 0x00080000 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_update_override_ctrl \ 0x00040000 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_off_override_ctrl \ 0x00020000 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_retain_override_ctrl \ 0x00010000 #define GPRCM_MCU_PSCON_OVERRIDES_NU1_M \ 0x0000FC00 #define GPRCM_MCU_PSCON_OVERRIDES_NU1_S 10 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_sleep_override \ 0x00000200 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_update_override \ 0x00000100 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_off_override_M \ 0x000000F0 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_off_override_S 4 #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_retain_override_M \ 0x0000000F #define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_retain_override_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WTOP_PSCON_OVERRIDES register. // //****************************************************************************** #define GPRCM_WTOP_PSCON_OVERRIDES_reserved_M \ 0xFFC00000 #define GPRCM_WTOP_PSCON_OVERRIDES_reserved_S 22 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_sleep_override_ctrl \ 0x00200000 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_update_override_ctrl \ 0x00100000 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_off_override_ctrl \ 0x00080000 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_retain_override_ctrl \ 0x00040000 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_sleep_override \ 0x00020000 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_update_override \ 0x00010000 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_off_override_M \ 0x0000FF00 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_off_override_S 8 #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_retain_override_M \ 0x000000FF #define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_retain_override_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WELP_PSCON_OVERRIDES register. // //****************************************************************************** #define GPRCM_WELP_PSCON_OVERRIDES_reserved_M \ 0xFFFFFFFC #define GPRCM_WELP_PSCON_OVERRIDES_reserved_S 2 #define GPRCM_WELP_PSCON_OVERRIDES_mem_welp_pscon_sleep_override_ctrl \ 0x00000002 #define GPRCM_WELP_PSCON_OVERRIDES_mem_welp_pscon_sleep_override \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_WL_SDIO_PSCON_OVERRIDES register. // //****************************************************************************** #define GPRCM_WL_SDIO_PSCON_OVERRIDES_reserved_M \ 0xFFFFFFFC #define GPRCM_WL_SDIO_PSCON_OVERRIDES_reserved_S 2 #define GPRCM_WL_SDIO_PSCON_OVERRIDES_mem_wl_sdio_pscon_sleep_override_ctrl \ 0x00000002 #define GPRCM_WL_SDIO_PSCON_OVERRIDES_mem_wl_sdio_pscon_sleep_override \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_MCSPI_PSCON_OVERRIDES register. // //****************************************************************************** #define GPRCM_MCSPI_PSCON_OVERRIDES_reserved_M \ 0xFFFFFF00 #define GPRCM_MCSPI_PSCON_OVERRIDES_reserved_S 8 #define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_retain_override_ctrl \ 0x00000080 #define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_off_override_ctrl \ 0x00000040 #define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_retain_override \ 0x00000020 #define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_off_override \ 0x00000010 #define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_update_override_ctrl \ 0x00000008 #define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_update_override \ 0x00000004 #define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_sleep_override_ctrl \ 0x00000002 #define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_sleep_override \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // GPRCM_O_SSDIO_PSCON_OVERRIDES register. // //****************************************************************************** #define GPRCM_SSDIO_PSCON_OVERRIDES_reserved_M \ 0xFFFFFFFC #define GPRCM_SSDIO_PSCON_OVERRIDES_reserved_S 2 #define GPRCM_SSDIO_PSCON_OVERRIDES_mem_ssdio_pscon_sleep_override_ctrl \ 0x00000002 #define GPRCM_SSDIO_PSCON_OVERRIDES_mem_ssdio_pscon_sleep_override \ 0x00000001 #endif // __HW_GPRCM_H__ micropython-1.12/ports/cc3200/hal/inc/hw_hib1p2.h000066400000000000000000002201661357706137100213430ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_HIB1P2_H__ #define __HW_HIB1P2_H__ //***************************************************************************** // // The following are defines for the HIB1P2 register offsets. // //***************************************************************************** #define HIB1P2_O_SRAM_SKA_LDO_PARAMETERS0 \ 0x00000000 #define HIB1P2_O_SRAM_SKA_LDO_PARAMETERS1 \ 0x00000004 #define HIB1P2_O_DIG_DCDC_PARAMETERS0 \ 0x00000008 #define HIB1P2_O_DIG_DCDC_PARAMETERS1 \ 0x0000000C #define HIB1P2_O_DIG_DCDC_PARAMETERS2 \ 0x00000010 #define HIB1P2_O_DIG_DCDC_PARAMETERS3 \ 0x00000014 #define HIB1P2_O_DIG_DCDC_PARAMETERS4 \ 0x00000018 #define HIB1P2_O_DIG_DCDC_PARAMETERS5 \ 0x0000001C #define HIB1P2_O_DIG_DCDC_PARAMETERS6 \ 0x00000020 #define HIB1P2_O_ANA_DCDC_PARAMETERS0 \ 0x00000024 #define HIB1P2_O_ANA_DCDC_PARAMETERS1 \ 0x00000028 #define HIB1P2_O_ANA_DCDC_PARAMETERS16 \ 0x00000064 #define HIB1P2_O_ANA_DCDC_PARAMETERS17 \ 0x00000068 #define HIB1P2_O_ANA_DCDC_PARAMETERS18 \ 0x0000006C #define HIB1P2_O_ANA_DCDC_PARAMETERS19 \ 0x00000070 #define HIB1P2_O_FLASH_DCDC_PARAMETERS0 \ 0x00000074 #define HIB1P2_O_FLASH_DCDC_PARAMETERS1 \ 0x00000078 #define HIB1P2_O_FLASH_DCDC_PARAMETERS2 \ 0x0000007C #define HIB1P2_O_FLASH_DCDC_PARAMETERS3 \ 0x00000080 #define HIB1P2_O_FLASH_DCDC_PARAMETERS4 \ 0x00000084 #define HIB1P2_O_FLASH_DCDC_PARAMETERS5 \ 0x00000088 #define HIB1P2_O_FLASH_DCDC_PARAMETERS6 \ 0x0000008C #define HIB1P2_O_PMBIST_PARAMETERS0 \ 0x00000094 #define HIB1P2_O_PMBIST_PARAMETERS1 \ 0x00000098 #define HIB1P2_O_PMBIST_PARAMETERS2 \ 0x0000009C #define HIB1P2_O_PMBIST_PARAMETERS3 \ 0x000000A0 #define HIB1P2_O_FLASH_DCDC_PARAMETERS8 \ 0x000000A4 #define HIB1P2_O_ANA_DCDC_PARAMETERS_OVERRIDE \ 0x000000A8 #define HIB1P2_O_FLASH_DCDC_PARAMETERS_OVERRIDE \ 0x000000AC #define HIB1P2_O_DIG_DCDC_VTRIM_CFG \ 0x000000B0 #define HIB1P2_O_DIG_DCDC_FSM_PARAMETERS \ 0x000000B4 #define HIB1P2_O_ANA_DCDC_FSM_PARAMETERS \ 0x000000B8 #define HIB1P2_O_SRAM_SKA_LDO_FSM_PARAMETERS \ 0x000000BC #define HIB1P2_O_BGAP_DUTY_CYCLING_EXIT_CFG \ 0x000000C0 #define HIB1P2_O_CM_OSC_16M_CONFIG \ 0x000000C4 #define HIB1P2_O_SOP_SENSE_VALUE \ 0x000000C8 #define HIB1P2_O_HIB_RTC_TIMER_LSW_1P2 \ 0x000000CC #define HIB1P2_O_HIB_RTC_TIMER_MSW_1P2 \ 0x000000D0 #define HIB1P2_O_HIB1P2_BGAP_TRIM_OVERRIDES \ 0x000000D4 #define HIB1P2_O_HIB1P2_EFUSE_READ_REG0 \ 0x000000D8 #define HIB1P2_O_HIB1P2_EFUSE_READ_REG1 \ 0x000000DC #define HIB1P2_O_HIB1P2_POR_TEST_CTRL \ 0x000000E0 #define HIB1P2_O_HIB_TIMER_SYNC_CALIB_CFG0 \ 0x000000E4 #define HIB1P2_O_HIB_TIMER_SYNC_CALIB_CFG1 \ 0x000000E8 #define HIB1P2_O_HIB_TIMER_SYNC_CFG2 \ 0x000000EC #define HIB1P2_O_HIB_TIMER_SYNC_TSF_ADJ_VAL \ 0x000000F0 #define HIB1P2_O_HIB_TIMER_RTC_GTS_TIMESTAMP_LSW \ 0x000000F4 #define HIB1P2_O_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW \ 0x000000F8 #define HIB1P2_O_HIB_TIMER_RTC_WUP_TIMESTAMP_LSW \ 0x000000FC #define HIB1P2_O_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW \ 0x00000100 #define HIB1P2_O_HIB_TIMER_SYNC_WAKE_OFFSET_ERR \ 0x00000104 #define HIB1P2_O_HIB_TIMER_SYNC_TSF_CURR_VAL_LSW \ 0x00000108 #define HIB1P2_O_HIB_TIMER_SYNC_TSF_CURR_VAL_MSW \ 0x0000010C #define HIB1P2_O_CM_SPARE 0x00000110 #define HIB1P2_O_PORPOL_SPARE 0x00000114 #define HIB1P2_O_MEM_DIG_DCDC_CLK_CONFIG \ 0x00000118 #define HIB1P2_O_MEM_ANA_DCDC_CLK_CONFIG \ 0x0000011C #define HIB1P2_O_MEM_FLASH_DCDC_CLK_CONFIG \ 0x00000120 #define HIB1P2_O_MEM_PA_DCDC_CLK_CONFIG \ 0x00000124 #define HIB1P2_O_MEM_SLDO_VNWA_OVERRIDE \ 0x00000128 #define HIB1P2_O_MEM_BGAP_DUTY_CYCLING_ENABLE_OVERRIDE \ 0x0000012C #define HIB1P2_O_MEM_HIB_FSM_DEBUG \ 0x00000130 #define HIB1P2_O_MEM_SLDO_VNWA_SW_CTRL \ 0x00000134 #define HIB1P2_O_MEM_SLDO_WEAK_PROCESS \ 0x00000138 #define HIB1P2_O_MEM_PA_DCDC_OV_UV_STATUS \ 0x0000013C #define HIB1P2_O_MEM_CM_TEST_MODE \ 0x00000140 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_SRAM_SKA_LDO_PARAMETERS0 register. // //****************************************************************************** #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_sc_itrim_lowv_M \ 0xC0000000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_sc_itrim_lowv_S 30 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_iq_trim_lowv_M \ 0x30000000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_iq_trim_lowv_S 28 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_sc_prot_lowv \ 0x08000000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_lowv_override \ 0x04000000 // FSM Override value for SLDO_EN : // Applicable only when bit [4] of // this register is set to 1. #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_low_pwr_lowv \ 0x02000000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_int_cap_sel_lowv \ 0x01000000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_vtrim_lowv_M \ 0x00FC0000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_vtrim_lowv_S 18 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_spare_lowv_M \ 0x0003FF00 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_spare_lowv_S 8 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_skaldo_en_lowv_override \ 0x00000080 // FSM Override value for // SKA_LDO_EN : Applicable only when // bit [3] of this register is set // to 1. #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_skaldo_en_cap_ref_lowv \ 0x00000040 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_skaldo_en_resdiv_ref_lowv \ 0x00000020 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_lowv_fsm_override_ctrl \ 0x00000010 // When 1, bit[26] of this register // will be used as SLDO_EN #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_skaldo_en_lowv_fsm_override_ctrl \ 0x00000008 // When 1, bit[26] of this register // will be used as SKA_LDO_EN #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_NA1_M \ 0x00000007 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_NA1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_SRAM_SKA_LDO_PARAMETERS1 register. // //****************************************************************************** #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_ctrl_lowv_M \ 0xFFC00000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_ctrl_lowv_S 22 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_vtrim_lowv_M \ 0x003F0000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_vtrim_lowv_S 16 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_sldo_en_tload_lowv \ 0x00008000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_en_tload_lowv \ 0x00004000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_cap_sw_en_lowv \ 0x00002000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_en_hib_lowv \ 0x00001000 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_en_vref_buf_lowv \ 0x00000800 #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_NA2_M \ 0x000007FF #define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_NA2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_PARAMETERS0 register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_lowv_override \ 0x80000000 // Override value for DCDC_DIG_EN : // Applicable only when bit [31] of // DIG_DCDC_PARAMETERS1 [0x000C] is // set to 1. Else from FSM #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_delayed_en_lowv \ 0x40000000 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_subreg_1p8v_lowv_override \ 0x20000000 // Override value for // DCDC_DIG_EN_SUBREG_1P8V : // Applicable only when bit [30] of // DIG_DCDC_PARAMETERS1 [0x000C] is // set to 1. Else from FSM #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_subreg_1p2v_lowv_override \ 0x10000000 // Override value for // DCDC_DIG_EN_SUBREG_1P2V : // Applicable only when bit [29] of // DIG_DCDC_PARAMETERS1 [0x000C] is // set to 1. Else from FSM #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_slp_mode_lowv_override \ 0x08000000 // Override value for // DCDC_DIG_SLP_EN : Applicable only // when bit [28] of // DIG_DCDC_PARAMETERS1 [0x000C] is // set to 1. Else from FSM #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_ldo_mode_lowv \ 0x04000000 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_nfet_rds_mode_lowv \ 0x02000000 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_pfet_rds_mode_lowv \ 0x01000000 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_ext_smps_override_mode_lowv \ 0x00800000 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_clk_in_lowv_enable \ 0x00400000 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_vtrim_lowv_override_M \ 0x003F0000 // Override value for // DCDC_DIG_VTRIM : Applicable only // when bit [27] of // DIG_DCDC_PARAMETERS1 [0x000C] is // set to 1. #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_vtrim_lowv_override_S 16 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_pfm_ripple_trim_lowv_M \ 0x0000C000 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_pfm_ripple_trim_lowv_S 14 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_iq_ctrl_lowv_M \ 0x00003000 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_iq_ctrl_lowv_S 12 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_cl_non_ov_lowv \ 0x00000800 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_non_ov_ctrl_lowv_M \ 0x00000780 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_non_ov_ctrl_lowv_S 7 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_slp_drv_dly_sel_lowv_M \ 0x00000078 #define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_slp_drv_dly_sel_lowv_S 3 #define HIB1P2_DIG_DCDC_PARAMETERS0_NA3_M \ 0x00000007 #define HIB1P2_DIG_DCDC_PARAMETERS0_NA3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_PARAMETERS1 register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_en_lowv_fsm_override_ctrl \ 0x80000000 #define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_en_subreg_1p8v_fsm_override_ctrl \ 0x40000000 #define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_en_subreg_1p2v_fsm_override_ctrl \ 0x20000000 #define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_en_slp_mode_lowv_fsm_override_ctrl \ 0x10000000 #define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_vtrim_fsm_override_ctrl \ 0x08000000 #define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_cot_mode_en_lowv_fsm_override_ctrl \ 0x04000000 #define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_ilim_trim_lowv_efc_override_ctrl \ 0x02000000 #define HIB1P2_DIG_DCDC_PARAMETERS1_NA4_M \ 0x01FFFFFF #define HIB1P2_DIG_DCDC_PARAMETERS1_NA4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_PARAMETERS2 register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pfet_sel_lowv_M \ 0xF0000000 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pfet_sel_lowv_S 28 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_nfet_sel_lowv_M \ 0x0F000000 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_nfet_sel_lowv_S 24 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pdrv_stagger_ctrl_lowv_M \ 0x00C00000 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pdrv_stagger_ctrl_lowv_S 22 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ndrv_stagger_ctrl_lowv_M \ 0x00300000 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ndrv_stagger_ctrl_lowv_S 20 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pdrv_str_sel_lowv_M \ 0x000F0000 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pdrv_str_sel_lowv_S 16 #define HIB1P2_DIG_DCDC_PARAMETERS2_NA5 \ 0x00008000 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ndrv_str_sel_lowv_M \ 0x00007800 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ndrv_str_sel_lowv_S 11 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_en_shootthru_ctrl_lowv \ 0x00000400 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ton_trim_lowv_M \ 0x000003FC #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ton_trim_lowv_S 2 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_swcap_res_hf_clk_lowv \ 0x00000002 #define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_cot_mode_en_lowv_override \ 0x00000001 // Override value for // DCDC_DIG_COT_EN : Applicable only // when bit[26] of // DIG_DCDC_PARAMETERS1 [0x000C] is // set to 1. //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_PARAMETERS3 register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_PARAMETERS3_NA6 \ 0x80000000 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_cot_ctrl_lowv_M \ 0x7F800000 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_cot_ctrl_lowv_S 23 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ilim_lowv \ 0x00400000 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ilim_hib_lowv \ 0x00200000 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ilim_trim_lowv_override_M \ 0x001FE000 // Override value for // DCDC_DIG_ILIM_TRIM : Applicable // only when bit [25] of // DIG_DCDC_PARAMETERS1 [0x000C] is // set to 1 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ilim_trim_lowv_override_S 13 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ilim_mask_dly_sel_lowv_M \ 0x00001800 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ilim_mask_dly_sel_lowv_S 11 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ncomp_lowv \ 0x00000400 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ncomp_hib_lowv \ 0x00000200 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ncomp_trim_lowv_M \ 0x000001F0 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ncomp_trim_lowv_S 4 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ncomp_mask_dly_sel_lowv_M \ 0x0000000C #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ncomp_mask_dly_sel_lowv_S 2 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_uv_prot_lowv \ 0x00000002 #define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ov_prot_lowv \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_PARAMETERS4 register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_PARAMETERS4_dcdc_dig_uv_prot_out_lowv \ 0x80000000 #define HIB1P2_DIG_DCDC_PARAMETERS4_dcdc_dig_ov_prot_out_lowv \ 0x40000000 #define HIB1P2_DIG_DCDC_PARAMETERS4_mem_dcdc_dig_en_tmux_lowv \ 0x20000000 #define HIB1P2_DIG_DCDC_PARAMETERS4_NA7_M \ 0x1FFFFFFF #define HIB1P2_DIG_DCDC_PARAMETERS4_NA7_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_PARAMETERS5 register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_PARAMETERS5_mem_dcdc_dig_tmux_ctrl_lowv_M \ 0xFFFFFFFF #define HIB1P2_DIG_DCDC_PARAMETERS5_mem_dcdc_dig_tmux_ctrl_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_PARAMETERS6 register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_PARAMETERS6_mem_dcdc_dig_spare_lowv_M \ 0xFFFFFFFF #define HIB1P2_DIG_DCDC_PARAMETERS6_mem_dcdc_dig_spare_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_ANA_DCDC_PARAMETERS0 register. // //****************************************************************************** #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_lowv_override \ 0x80000000 // Override for ANA DCDC EN #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_delayed_en_lowv \ 0x40000000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_subreg_1p8v_lowv \ 0x20000000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_subreg_1p2v_lowv \ 0x10000000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_pwm_mode_lowv_override \ 0x08000000 // Override for ANA DCDC PWM #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_slp_mode_lowv_override \ 0x04000000 // Override for ANA DCDC SLP #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_ldo_mode_lowv \ 0x02000000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_pfet_rds_mode_lowv \ 0x01000000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_nfet_rds_mode_lowv \ 0x00800000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_ext_smps_override_mode_lowv \ 0x00400000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_clk_in_lowv_enable \ 0x00200000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_vtrim_lowv_M \ 0x001E0000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_vtrim_lowv_S 17 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_pfm_ripple_trim_lowv_M \ 0x00018000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_pfm_ripple_trim_lowv_S 15 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_iq_ctrl_lowv_M \ 0x00006000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_iq_ctrl_lowv_S 13 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_cl_non_ov_lowv \ 0x00001000 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_non_ov_ctrl_lowv_M \ 0x00000F00 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_non_ov_ctrl_lowv_S 8 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_slp_drv_dly_sel_lowv_M \ 0x000000F0 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_slp_drv_dly_sel_lowv_S 4 #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_pfet_sel_lowv_M \ 0x0000000F #define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_pfet_sel_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_ANA_DCDC_PARAMETERS1 register. // //****************************************************************************** #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_nfet_sel_lowv_M \ 0xF0000000 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_nfet_sel_lowv_S 28 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_pdrv_stagger_ctrl_lowv_M \ 0x0C000000 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_pdrv_stagger_ctrl_lowv_S 26 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ndrv_stagger_ctrl_lowv_M \ 0x03000000 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ndrv_stagger_ctrl_lowv_S 24 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_pdrv_str_sel_lowv_M \ 0x00F00000 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_pdrv_str_sel_lowv_S 20 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ndrv_str_sel_lowv_M \ 0x000F0000 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ndrv_str_sel_lowv_S 16 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_en_rtrim_lowv \ 0x00008000 // (Earlier SHOOTTHRU CTRL) #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_apwm_en_lowv \ 0x00004000 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ramp_hgt_lowv_M \ 0x00003E00 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ramp_hgt_lowv_S 9 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_en_anti_glitch_lowv \ 0x00000100 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_en_hi_clamp_lowv \ 0x00000080 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_hi_clamp_trim_lowv_M \ 0x00000060 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_hi_clamp_trim_lowv_S 5 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_en_lo_clamp_lowv \ 0x00000010 #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_lo_clamp_trim_lowv_M \ 0x0000000C #define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_lo_clamp_trim_lowv_S 2 #define HIB1P2_ANA_DCDC_PARAMETERS1_NA8_M \ 0x00000003 #define HIB1P2_ANA_DCDC_PARAMETERS1_NA8_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_ANA_DCDC_PARAMETERS16 register. // //****************************************************************************** #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ilim_lowv \ 0x00200000 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ilim_hib_lowv \ 0x00100000 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ilim_trim_lowv_override_M \ 0x000FF000 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ilim_trim_lowv_override_S 12 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ilim_mask_dly_sel_lowv_M \ 0x00000C00 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ilim_mask_dly_sel_lowv_S 10 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ncomp_lowv \ 0x00000200 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ncomp_hib_lowv \ 0x00000100 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ncomp_trim_lowv_M \ 0x000000F8 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ncomp_trim_lowv_S 3 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ncomp_mask_dly_sel_lowv_M \ 0x00000006 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ncomp_mask_dly_sel_lowv_S 1 #define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ov_prot_lowv \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_ANA_DCDC_PARAMETERS17 register. // //****************************************************************************** #define HIB1P2_ANA_DCDC_PARAMETERS17_dcdc_ana_ov_prot_out_lowv \ 0x80000000 #define HIB1P2_ANA_DCDC_PARAMETERS17_mem_dcdc_ana_en_tmux_lowv \ 0x40000000 #define HIB1P2_ANA_DCDC_PARAMETERS17_NA17_M \ 0x3FFFFFFF #define HIB1P2_ANA_DCDC_PARAMETERS17_NA17_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_ANA_DCDC_PARAMETERS18 register. // //****************************************************************************** #define HIB1P2_ANA_DCDC_PARAMETERS18_mem_dcdc_ana_tmux_ctrl_lowv_M \ 0xFFFFFFFF #define HIB1P2_ANA_DCDC_PARAMETERS18_mem_dcdc_ana_tmux_ctrl_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_ANA_DCDC_PARAMETERS19 register. // //****************************************************************************** #define HIB1P2_ANA_DCDC_PARAMETERS19_mem_dcdc_ana_spare_lowv_M \ 0xFFFFFFFF #define HIB1P2_ANA_DCDC_PARAMETERS19_mem_dcdc_ana_spare_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS0 register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_lowv \ 0x80000000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_delayed_en_lowv \ 0x40000000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_clk_in_lowv_enable \ 0x20000000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_iq_ctrl_lowv_M \ 0x18000000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_iq_ctrl_lowv_S 27 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_buck_mode_lowv \ 0x04000000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_boost_mode_lowv \ 0x02000000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_buck_boost_mode_lowv \ 0x01000000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_bb_alt_cycles_lowv \ 0x00800000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_cl_non_ov_lowv \ 0x00400000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_non_ov_ctrl_lowv_M \ 0x003C0000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_non_ov_ctrl_lowv_S 18 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_drv_lowv \ 0x00020000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_pwm_mode_lowv \ 0x00010000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_pfm_comp_lowv \ 0x00008000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_slp_mode_lowv \ 0x00004000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_n1fet_rds_mode_lowv \ 0x00002000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_n2fet_rds_mode_lowv \ 0x00001000 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_p1fet_rds_mode_lowv \ 0x00000800 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_p2fet_rds_mode_lowv \ 0x00000400 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_ext_smps_mode_override_lowv \ 0x00000200 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_p1fet_sel_lowv_M \ 0x000001E0 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_p1fet_sel_lowv_S 5 #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_n1fet_sel_lowv_M \ 0x0000001E #define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_n1fet_sel_lowv_S 1 #define HIB1P2_FLASH_DCDC_PARAMETERS0_NA18 \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS1 register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2fet_sel_lowv_M \ 0xF0000000 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2fet_sel_lowv_S 28 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2fet_sel_lowv_M \ 0x0F000000 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2fet_sel_lowv_S 24 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p1drv_str_sel_lowv_M \ 0x00F00000 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p1drv_str_sel_lowv_S 20 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n1drv_str_sel_lowv_M \ 0x000F0000 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n1drv_str_sel_lowv_S 16 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2drv_str_sel_lowv_M \ 0x0000F000 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2drv_str_sel_lowv_S 12 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2drv_str_sel_lowv_M \ 0x00000F00 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2drv_str_sel_lowv_S 8 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p1fet_non_ov_lowv_M \ 0x000000C0 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p1fet_non_ov_lowv_S 6 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n1fet_non_ov_lowv_M \ 0x00000030 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n1fet_non_ov_lowv_S 4 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2fet_non_ov_lowv_M \ 0x0000000C #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2fet_non_ov_lowv_S 2 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2fet_non_ov_lowv_M \ 0x00000003 #define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2fet_non_ov_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS2 register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_p1fet_stagger_lowv_M \ 0xC0000000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_p1fet_stagger_lowv_S 30 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_n1fet_stagger_lowv_M \ 0x30000000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_n1fet_stagger_lowv_S 28 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_p2fet_stagger_lowv_M \ 0x0C000000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_p2fet_stagger_lowv_S 26 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_n2fet_stagger_lowv_M \ 0x03000000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_n2fet_stagger_lowv_S 24 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_shoot_thru_ctrl_lowv \ 0x00800000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_en_ncomp_lowv \ 0x00400000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_en_ncomp_hib_lowv \ 0x00200000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ncomp_trim_lowv_M \ 0x001F0000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ncomp_trim_lowv_S 16 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ncomp_mask_dly_trim_lowv_M \ 0x0000F000 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ncomp_mask_dly_trim_lowv_S 12 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_en_ilim_lowv \ 0x00000800 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_en_ilim_hib_lowv \ 0x00000400 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ilim_trim_lowv_override_M \ 0x000003FC #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ilim_trim_lowv_override_S 2 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ilim_mask_dly_sel_lowv_M \ 0x00000003 #define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ilim_mask_dly_sel_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS3 register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_anti_glitch_lowv \ 0x80000000 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_hi_clamp_lowv \ 0x40000000 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_lo_clamp_lowv \ 0x20000000 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_ramp_hgt_lowv_M \ 0x1F000000 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_ramp_hgt_lowv_S 24 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vclamph_trim_lowv_M \ 0x00E00000 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vclamph_trim_lowv_S 21 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vclampl_trim_lowv_M \ 0x001C0000 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vclampl_trim_lowv_S 18 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vtrim_lowv_M \ 0x0003C000 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vtrim_lowv_S 14 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_pfm_ripple_trim_lowv_M \ 0x00003C00 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_pfm_ripple_trim_lowv_S 10 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_slp_drv_dly_sel_lowv_M \ 0x00000300 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_slp_drv_dly_sel_lowv_S 8 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_ov_prot_lowv \ 0x00000080 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_uv_prot_lowv \ 0x00000040 #define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_tmux_lowv \ 0x00000020 #define HIB1P2_FLASH_DCDC_PARAMETERS3_NA19_M \ 0x0000001F #define HIB1P2_FLASH_DCDC_PARAMETERS3_NA19_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS4 register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS4_mem_dcdc_flash_tmux_ctrl_lowv_M \ 0xFFFFFFFF #define HIB1P2_FLASH_DCDC_PARAMETERS4_mem_dcdc_flash_tmux_ctrl_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS5 register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS5_mem_dcdc_flash_spare_lowv_M \ 0xFFFFFFFF #define HIB1P2_FLASH_DCDC_PARAMETERS5_mem_dcdc_flash_spare_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS6 register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS6_dcdc_flash_ov_prot_out_lowv \ 0x80000000 #define HIB1P2_FLASH_DCDC_PARAMETERS6_dcdc_flash_uv_prot_out_lowv \ 0x40000000 #define HIB1P2_FLASH_DCDC_PARAMETERS6_NA20_M \ 0x3FFFFFFF #define HIB1P2_FLASH_DCDC_PARAMETERS6_NA20_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_PMBIST_PARAMETERS0 register. // //****************************************************************************** #define HIB1P2_PMBIST_PARAMETERS0_mem_pm_bist_en_lowv \ 0x80000000 #define HIB1P2_PMBIST_PARAMETERS0_mem_pm_bist_ctrl_lowv_M \ 0x7FFFF800 #define HIB1P2_PMBIST_PARAMETERS0_mem_pm_bist_ctrl_lowv_S 11 #define HIB1P2_PMBIST_PARAMETERS0_NA21_M \ 0x000007FF #define HIB1P2_PMBIST_PARAMETERS0_NA21_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_PMBIST_PARAMETERS1 register. // //****************************************************************************** #define HIB1P2_PMBIST_PARAMETERS1_mem_pm_bist_spare_lowv_M \ 0xFFFF0000 #define HIB1P2_PMBIST_PARAMETERS1_mem_pm_bist_spare_lowv_S 16 #define HIB1P2_PMBIST_PARAMETERS1_mem_pmtest_en_lowv \ 0x00008000 #define HIB1P2_PMBIST_PARAMETERS1_NA22_M \ 0x00007FFF #define HIB1P2_PMBIST_PARAMETERS1_NA22_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_PMBIST_PARAMETERS2 register. // //****************************************************************************** #define HIB1P2_PMBIST_PARAMETERS2_mem_pmtest_tmux_ctrl_lowv_M \ 0xFFFFFFFF #define HIB1P2_PMBIST_PARAMETERS2_mem_pmtest_tmux_ctrl_lowv_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_PMBIST_PARAMETERS3 register. // //****************************************************************************** #define HIB1P2_PMBIST_PARAMETERS3_mem_pmtest_spare_lowv_M \ 0xFFFF0000 #define HIB1P2_PMBIST_PARAMETERS3_mem_pmtest_spare_lowv_S 16 #define HIB1P2_PMBIST_PARAMETERS3_mem_pmtest_load_trim_lowv_M \ 0x0000E000 #define HIB1P2_PMBIST_PARAMETERS3_mem_pmtest_load_trim_lowv_S 13 #define HIB1P2_PMBIST_PARAMETERS3_mem_rnwell_calib_en_lowv \ 0x00001000 #define HIB1P2_PMBIST_PARAMETERS3_NA23_M \ 0x00000FFF #define HIB1P2_PMBIST_PARAMETERS3_NA23_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS8 register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_en_flash_sup_comp_lowv \ 0x80000000 #define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_flash_high_sup_trim_lowv_M \ 0x7C000000 #define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_flash_high_sup_trim_lowv_S 26 #define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_flash_low_sup_trim_lowv_M \ 0x03E00000 #define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_flash_low_sup_trim_lowv_S 21 #define HIB1P2_FLASH_DCDC_PARAMETERS8_NA24_M \ 0x001FFFFF #define HIB1P2_FLASH_DCDC_PARAMETERS8_NA24_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_ANA_DCDC_PARAMETERS_OVERRIDE register. // //****************************************************************************** #define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_reserved_M \ 0xFFFFFFC0 #define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_reserved_S 6 #define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_subreg_1p2v_lowv_override_ctrl \ 0x00000020 #define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_subreg_1p8v_lowv_override_ctrl \ 0x00000010 #define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_ilim_trim_lowv_efc_override_ctrl \ 0x00000008 #define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_slp_mode_lowv_fsm_override_ctrl \ 0x00000004 #define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_pwm_mode_lowv_fsm_override_ctrl \ 0x00000002 #define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_lowv_fsm_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_FLASH_DCDC_PARAMETERS_OVERRIDE register. // //****************************************************************************** #define HIB1P2_FLASH_DCDC_PARAMETERS_OVERRIDE_reserved_M \ 0xFFFFFFFC #define HIB1P2_FLASH_DCDC_PARAMETERS_OVERRIDE_reserved_S 2 #define HIB1P2_FLASH_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_flash_en_lowv_override_ctrl \ 0x00000002 #define HIB1P2_FLASH_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_flash_ilim_trim_lowv_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_VTRIM_CFG register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_VTRIM_CFG_reserved_M \ 0xFF000000 #define HIB1P2_DIG_DCDC_VTRIM_CFG_reserved_S 24 #define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_run_vtrim_M \ 0x00FC0000 #define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_run_vtrim_S 18 #define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_dslp_vtrim_M \ 0x0003F000 #define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_dslp_vtrim_S 12 #define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_lpds_vtrim_M \ 0x00000FC0 #define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_lpds_vtrim_S 6 #define HIB1P2_DIG_DCDC_VTRIM_CFG_Spare_RW_M \ 0x0000003F #define HIB1P2_DIG_DCDC_VTRIM_CFG_Spare_RW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_DIG_DCDC_FSM_PARAMETERS register. // //****************************************************************************** #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_reserved_M \ 0xFFFF8000 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_reserved_S 15 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_enter_cot_to_vtrim_M \ 0x00007000 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_enter_cot_to_vtrim_S 12 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_enter_vtrim_to_sleep_M \ 0x00000E00 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_enter_vtrim_to_sleep_S 9 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_sleep_to_vtrim_M \ 0x000001C0 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_sleep_to_vtrim_S 6 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_vtrim_to_cot_M \ 0x00000038 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_vtrim_to_cot_S 3 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_cot_to_run_M \ 0x00000007 #define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_cot_to_run_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_ANA_DCDC_FSM_PARAMETERS register. // //****************************************************************************** #define HIB1P2_ANA_DCDC_FSM_PARAMETERS_reserved_M \ 0xFFFFFFF8 #define HIB1P2_ANA_DCDC_FSM_PARAMETERS_reserved_S 3 #define HIB1P2_ANA_DCDC_FSM_PARAMETERS_mem_dcdc_ana_dslp_exit_sleep_to_run_M \ 0x00000007 #define HIB1P2_ANA_DCDC_FSM_PARAMETERS_mem_dcdc_ana_dslp_exit_sleep_to_run_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_SRAM_SKA_LDO_FSM_PARAMETERS register. // //****************************************************************************** #define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_reserved_M \ 0xFFFFFFC0 #define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_reserved_S 6 #define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_mem_ska_ldo_en_to_sram_ldo_dis_M \ 0x00000038 #define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_mem_ska_ldo_en_to_sram_ldo_dis_S 3 #define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_mem_sram_ldo_en_to_ska_ldo_dis_M \ 0x00000007 #define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_mem_sram_ldo_en_to_ska_ldo_dis_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_BGAP_DUTY_CYCLING_EXIT_CFG register. // //****************************************************************************** #define HIB1P2_BGAP_DUTY_CYCLING_EXIT_CFG_reserved_M \ 0xFFFFFFF8 #define HIB1P2_BGAP_DUTY_CYCLING_EXIT_CFG_reserved_S 3 #define HIB1P2_BGAP_DUTY_CYCLING_EXIT_CFG_mem_bgap_duty_cycling_exit_time_M \ 0x00000007 #define HIB1P2_BGAP_DUTY_CYCLING_EXIT_CFG_mem_bgap_duty_cycling_exit_time_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_CM_OSC_16M_CONFIG register. // //****************************************************************************** #define HIB1P2_CM_OSC_16M_CONFIG_reserved_M \ 0xFFFC0000 #define HIB1P2_CM_OSC_16M_CONFIG_reserved_S 18 #define HIB1P2_CM_OSC_16M_CONFIG_cm_clk_good_16m \ 0x00020000 #define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_en_osc_16m \ 0x00010000 #define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_16m_trim_M \ 0x0000FC00 #define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_16m_trim_S 10 #define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_16m_spare_M \ 0x000003F0 #define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_16m_spare_S 4 #define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_en_sli_16m \ 0x00000008 #define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_sli_16m_trim_M \ 0x00000007 #define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_sli_16m_trim_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_SOP_SENSE_VALUE register. // //****************************************************************************** #define HIB1P2_SOP_SENSE_VALUE_reserved_M \ 0xFFFFFF00 #define HIB1P2_SOP_SENSE_VALUE_reserved_S 8 #define HIB1P2_SOP_SENSE_VALUE_sop_sense_value_M \ 0x000000FF #define HIB1P2_SOP_SENSE_VALUE_sop_sense_value_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_RTC_TIMER_LSW_1P2 register. // //****************************************************************************** #define HIB1P2_HIB_RTC_TIMER_LSW_1P2_hib_rtc_timer_lsw_M \ 0xFFFFFFFF #define HIB1P2_HIB_RTC_TIMER_LSW_1P2_hib_rtc_timer_lsw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_RTC_TIMER_MSW_1P2 register. // //****************************************************************************** #define HIB1P2_HIB_RTC_TIMER_MSW_1P2_hib_rtc_timer_msw_M \ 0x0000FFFF #define HIB1P2_HIB_RTC_TIMER_MSW_1P2_hib_rtc_timer_msw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB1P2_BGAP_TRIM_OVERRIDES register. // //****************************************************************************** #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_reserved_M \ 0xFF800000 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_reserved_S 23 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_mag_trim_override_ctrl \ 0x00400000 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_mag_trim_override_M \ 0x003FC000 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_mag_trim_override_S 14 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_temp_trim_override_ctrl \ 0x00002000 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_temp_trim_override_M \ 0x00001FC0 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_temp_trim_override_S 6 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_rtrim_override_ctrl \ 0x00000020 #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_rtrim_override_M \ 0x0000001F #define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_rtrim_override_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB1P2_EFUSE_READ_REG0 register. // //****************************************************************************** #define HIB1P2_HIB1P2_EFUSE_READ_REG0_FUSEFARM_ROW_12_M \ 0xFFFFFFFF // Corresponds to ROW_12 of // FUSEFARM. [7:0] : // DCDC_DIG_ILIM_TRIM_LOWV(7:0) // [15:8] : // DCDC_ANA_ILIM_TRIM_LOWV(7:0) // [23:16] : // DCDC_FLASH_ILIM_TRIM_LOWV(7:0) // [24:24] : DTHE SHA DISABLE // [25:25] : DTHE DES DISABLE // [26:26] : DTHE AES DISABLE // [31:27] : HD_BG_RTRIM (4:0) #define HIB1P2_HIB1P2_EFUSE_READ_REG0_FUSEFARM_ROW_12_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB1P2_EFUSE_READ_REG1 register. // //****************************************************************************** #define HIB1P2_HIB1P2_EFUSE_READ_REG1_FUSEFARM_ROW_13_M \ 0xFFFFFFFF // Corresponds to ROW_13 of the // FUSEFARM. [7:0] : HD_BG_MAG_TRIM // (7:0) [14:8] : HD_BG_TEMP_TRIM // (6:0) [15:15] : GREYOUT ENABLE // DUTY CYCLING [31:16] : // Reserved/Checksum #define HIB1P2_HIB1P2_EFUSE_READ_REG1_FUSEFARM_ROW_13_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB1P2_POR_TEST_CTRL register. // //****************************************************************************** #define HIB1P2_HIB1P2_POR_TEST_CTRL_reserved_M \ 0xFFFFFF00 #define HIB1P2_HIB1P2_POR_TEST_CTRL_reserved_S 8 #define HIB1P2_HIB1P2_POR_TEST_CTRL_mem_prcm_por_test_ctrl_M \ 0x000000FF #define HIB1P2_HIB1P2_POR_TEST_CTRL_mem_prcm_por_test_ctrl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_SYNC_CALIB_CFG0 register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_reserved_M \ 0xFFFF0000 #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_reserved_S 16 #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_mem_cfg_calib_time_M \ 0x0000FF00 #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_mem_cfg_calib_time_S 8 #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_NU1_M \ 0x000000FE #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_NU1_S 1 #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_mem_cfg_calib_start \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_SYNC_CALIB_CFG1 register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG1_reserved_M \ 0xFFF00000 #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG1_reserved_S 20 #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG1_fast_calib_count_M \ 0x000FFFFF #define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG1_fast_calib_count_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_SYNC_CFG2 register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_SYNC_CFG2_reserved_M \ 0xFFFFFE00 #define HIB1P2_HIB_TIMER_SYNC_CFG2_reserved_S 9 #define HIB1P2_HIB_TIMER_SYNC_CFG2_mem_cfg_hib_unload \ 0x00000100 #define HIB1P2_HIB_TIMER_SYNC_CFG2_NU1_M \ 0x000000FC #define HIB1P2_HIB_TIMER_SYNC_CFG2_NU1_S 2 #define HIB1P2_HIB_TIMER_SYNC_CFG2_mem_cfg_tsf_adj \ 0x00000002 #define HIB1P2_HIB_TIMER_SYNC_CFG2_mem_cfg_update_tsf \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_SYNC_TSF_ADJ_VAL register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_SYNC_TSF_ADJ_VAL_mem_tsf_adj_val_M \ 0xFFFFFFFF #define HIB1P2_HIB_TIMER_SYNC_TSF_ADJ_VAL_mem_tsf_adj_val_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_RTC_GTS_TIMESTAMP_LSW register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_LSW_rtc_gts_timestamp_lsw_M \ 0xFFFFFFFF #define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_LSW_rtc_gts_timestamp_lsw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW_reserved_M \ 0xFFFF0000 #define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW_reserved_S 16 #define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW_rtc_gts_timestamp_msw_M \ 0x0000FFFF #define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW_rtc_gts_timestamp_msw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_RTC_WUP_TIMESTAMP_LSW register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_LSW_rtc_wup_timestamp_lsw_M \ 0xFFFFFFFF #define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_LSW_rtc_wup_timestamp_lsw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW_reserved_M \ 0xFFFF0000 #define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW_reserved_S 16 #define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW_rtc_wup_timestamp_msw_M \ 0x0000FFFF #define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW_rtc_wup_timestamp_msw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_SYNC_WAKE_OFFSET_ERR register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_SYNC_WAKE_OFFSET_ERR_reserved_M \ 0xFFFFF000 #define HIB1P2_HIB_TIMER_SYNC_WAKE_OFFSET_ERR_reserved_S 12 #define HIB1P2_HIB_TIMER_SYNC_WAKE_OFFSET_ERR_wup_offset_error_M \ 0x00000FFF #define HIB1P2_HIB_TIMER_SYNC_WAKE_OFFSET_ERR_wup_offset_error_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_SYNC_TSF_CURR_VAL_LSW register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_SYNC_TSF_CURR_VAL_LSW_tsf_curr_val_lsw_M \ 0xFFFFFFFF #define HIB1P2_HIB_TIMER_SYNC_TSF_CURR_VAL_LSW_tsf_curr_val_lsw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_HIB_TIMER_SYNC_TSF_CURR_VAL_MSW register. // //****************************************************************************** #define HIB1P2_HIB_TIMER_SYNC_TSF_CURR_VAL_MSW_tsf_curr_val_msw_M \ 0xFFFFFFFF #define HIB1P2_HIB_TIMER_SYNC_TSF_CURR_VAL_MSW_tsf_curr_val_msw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the HIB1P2_O_CM_SPARE register. // //****************************************************************************** #define HIB1P2_CM_SPARE_CM_SPARE_OUT_M \ 0xFF000000 #define HIB1P2_CM_SPARE_CM_SPARE_OUT_S 24 #define HIB1P2_CM_SPARE_MEM_CM_TEST_CTRL_M \ 0x00FF0000 #define HIB1P2_CM_SPARE_MEM_CM_TEST_CTRL_S 16 #define HIB1P2_CM_SPARE_MEM_CM_SPARE_M \ 0x0000FFFF #define HIB1P2_CM_SPARE_MEM_CM_SPARE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_PORPOL_SPARE register. // //****************************************************************************** #define HIB1P2_PORPOL_SPARE_MEM_PORPOL_SPARE_M \ 0xFFFFFFFF #define HIB1P2_PORPOL_SPARE_MEM_PORPOL_SPARE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_DIG_DCDC_CLK_CONFIG register. // //****************************************************************************** #define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_ENABLE \ 0x00000100 #define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_PLLGEN_OFF_TIME_M \ 0x000000F0 #define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_PLLGEN_OFF_TIME_S 4 #define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_PLLGEN_ON_TIME_M \ 0x0000000F #define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_PLLGEN_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_ANA_DCDC_CLK_CONFIG register. // //****************************************************************************** #define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_ENABLE \ 0x00000100 #define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_PLLGEN_OFF_TIME_M \ 0x000000F0 #define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_PLLGEN_OFF_TIME_S 4 #define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_PLLGEN_ON_TIME_M \ 0x0000000F #define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_PLLGEN_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_FLASH_DCDC_CLK_CONFIG register. // //****************************************************************************** #define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_ENABLE \ 0x00000100 #define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_PLLGEN_OFF_TIME_M \ 0x000000F0 #define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_PLLGEN_OFF_TIME_S 4 #define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_PLLGEN_ON_TIME_M \ 0x0000000F #define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_PLLGEN_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_PA_DCDC_CLK_CONFIG register. // //****************************************************************************** #define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_ENABLE \ 0x00000100 #define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_PLLGEN_OFF_TIME_M \ 0x000000F0 #define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_PLLGEN_OFF_TIME_S 4 #define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_PLLGEN_ON_TIME_M \ 0x0000000F #define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_PLLGEN_ON_TIME_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_SLDO_VNWA_OVERRIDE register. // //****************************************************************************** #define HIB1P2_MEM_SLDO_VNWA_OVERRIDE_MEM_SLDO_EN_TOP_VNWA_OVERRIDE_CTRL \ 0x00000002 #define HIB1P2_MEM_SLDO_VNWA_OVERRIDE_MEM_SLDO_EN_TOP_VNWA_OVERRIDE \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_BGAP_DUTY_CYCLING_ENABLE_OVERRIDE register. // //****************************************************************************** #define HIB1P2_MEM_BGAP_DUTY_CYCLING_ENABLE_OVERRIDE_MEM_BGAP_DUTY_CYCLING_OVERRIDE_CTRL \ 0x00000002 #define HIB1P2_MEM_BGAP_DUTY_CYCLING_ENABLE_OVERRIDE_MEM_BGAP_DUTY_CYCLING_OVERRIDE \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_HIB_FSM_DEBUG register. // //****************************************************************************** #define HIB1P2_MEM_HIB_FSM_DEBUG_SRAM_PS_M \ 0x00000700 #define HIB1P2_MEM_HIB_FSM_DEBUG_SRAM_PS_S 8 #define HIB1P2_MEM_HIB_FSM_DEBUG_ANA_DCDC_PS_M \ 0x000000F0 #define HIB1P2_MEM_HIB_FSM_DEBUG_ANA_DCDC_PS_S 4 #define HIB1P2_MEM_HIB_FSM_DEBUG_DIG_DCDC_PS_M \ 0x0000000F #define HIB1P2_MEM_HIB_FSM_DEBUG_DIG_DCDC_PS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_SLDO_VNWA_SW_CTRL register. // //****************************************************************************** #define HIB1P2_MEM_SLDO_VNWA_SW_CTRL_MEM_SLDO_VNWA_SW_CTRL_M \ 0x000FFFFF #define HIB1P2_MEM_SLDO_VNWA_SW_CTRL_MEM_SLDO_VNWA_SW_CTRL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_SLDO_WEAK_PROCESS register. // //****************************************************************************** #define HIB1P2_MEM_SLDO_WEAK_PROCESS_MEM_SLDO_WEAK_PROCESS \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_PA_DCDC_OV_UV_STATUS register. // //****************************************************************************** #define HIB1P2_MEM_PA_DCDC_OV_UV_STATUS_dcdc_pa_ov_prot_out_lowv \ 0x00000002 //****************************************************************************** // // The following are defines for the bit fields in the // HIB1P2_O_MEM_CM_TEST_MODE register. // //****************************************************************************** #define HIB1P2_MEM_CM_TEST_MODE_mem_cm_test_mode \ 0x00000001 #endif // __HW_HIB1P2_H__ micropython-1.12/ports/cc3200/hal/inc/hw_hib3p3.h000066400000000000000000001502641357706137100213470ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_HIB3P3_H__ #define __HW_HIB3P3_H__ //***************************************************************************** // // The following are defines for the HIB3P3 register offsets. // //***************************************************************************** #define HIB3P3_O_MEM_HIB_REQ 0x00000000 #define HIB3P3_O_MEM_HIB_RTC_TIMER_ENABLE \ 0x00000004 #define HIB3P3_O_MEM_HIB_RTC_TIMER_RESET \ 0x00000008 #define HIB3P3_O_MEM_HIB_RTC_TIMER_READ \ 0x0000000C #define HIB3P3_O_MEM_HIB_RTC_TIMER_LSW \ 0x00000010 #define HIB3P3_O_MEM_HIB_RTC_TIMER_MSW \ 0x00000014 #define HIB3P3_O_MEM_HIB_RTC_WAKE_EN \ 0x00000018 #define HIB3P3_O_MEM_HIB_RTC_WAKE_LSW_CONF \ 0x0000001C #define HIB3P3_O_MEM_HIB_RTC_WAKE_MSW_CONF \ 0x00000020 #define HIB3P3_O_MEM_INT_OSC_CONF \ 0x0000002C #define HIB3P3_O_MEM_XTAL_OSC_CONF \ 0x00000034 #define HIB3P3_O_MEM_BGAP_PARAMETERS0 \ 0x00000038 #define HIB3P3_O_MEM_BGAP_PARAMETERS1 \ 0x0000003C #define HIB3P3_O_MEM_HIB_DETECTION_STATUS \ 0x00000040 #define HIB3P3_O_MEM_HIB_MISC_CONTROLS \ 0x00000044 #define HIB3P3_O_MEM_HIB_CONFIG 0x00000050 #define HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE \ 0x00000054 #define HIB3P3_O_MEM_HIB_RTC_IRQ_LSW_CONF \ 0x00000058 #define HIB3P3_O_MEM_HIB_RTC_IRQ_MSW_CONF \ 0x0000005C #define HIB3P3_O_MEM_HIB_UART_CONF \ 0x00000400 #define HIB3P3_O_MEM_GPIO_WAKE_EN \ 0x00000404 #define HIB3P3_O_MEM_GPIO_WAKE_CONF \ 0x00000408 #define HIB3P3_O_MEM_PAD_OEN_RET33_CONF \ 0x0000040C #define HIB3P3_O_MEM_UART_RTS_OEN_RET33_CONF \ 0x00000410 #define HIB3P3_O_MEM_JTAG_CONF 0x00000414 #define HIB3P3_O_MEM_HIB_REG0 0x00000418 #define HIB3P3_O_MEM_HIB_REG1 0x0000041C #define HIB3P3_O_MEM_HIB_REG2 0x00000420 #define HIB3P3_O_MEM_HIB_REG3 0x00000424 #define HIB3P3_O_MEM_HIB_SEQUENCER_CFG0 \ 0x0000045C #define HIB3P3_O_MEM_HIB_SEQUENCER_CFG1 \ 0x00000460 #define HIB3P3_O_MEM_HIB_MISC_CONFIG \ 0x00000464 #define HIB3P3_O_MEM_HIB_WAKE_STATUS \ 0x00000468 #define HIB3P3_O_MEM_HIB_LPDS_GPIO_SEL \ 0x0000046C #define HIB3P3_O_MEM_HIB_SEQUENCER_CFG2 \ 0x00000470 #define HIB3P3_O_HIBANA_SPARE_LOWV \ 0x00000474 #define HIB3P3_O_HIB_TMUX_CTRL 0x00000478 #define HIB3P3_O_HIB_1P2_1P8_LDO_TRIM \ 0x0000047C #define HIB3P3_O_HIB_COMP_TRIM 0x00000480 #define HIB3P3_O_HIB_EN_TS 0x00000484 #define HIB3P3_O_HIB_1P8V_DET_EN \ 0x00000488 #define HIB3P3_O_HIB_VBAT_MON_EN \ 0x0000048C #define HIB3P3_O_HIB_NHIB_ENABLE \ 0x00000490 #define HIB3P3_O_HIB_UART_RTS_SW_ENABLE \ 0x00000494 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_REQ register. // //****************************************************************************** #define HIB3P3_MEM_HIB_REQ_reserved_M \ 0xFFFFFE00 #define HIB3P3_MEM_HIB_REQ_reserved_S 9 #define HIB3P3_MEM_HIB_REQ_NU1_M \ 0x000001FC #define HIB3P3_MEM_HIB_REQ_NU1_S 2 #define HIB3P3_MEM_HIB_REQ_mem_hib_clk_disable \ 0x00000002 // 1 - Specifies that the Hiberante // mode is without clocks ; 0 - // Specified that the Hibernate mode // is with clocks This register will // be reset during Hibernate // -WO-Clks mode (but not during // Hibernate-W-Clks mode). #define HIB3P3_MEM_HIB_REQ_mem_hib_req \ 0x00000001 // 1 - Request for hibernate mode // (This is an auto-clear bit) ; 0 - // Donot request for hibernate mode // This register will be reset // during Hibernate -WO-Clks mode // (but not during Hibernate-W-Clks // mode). //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_TIMER_ENABLE register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_TIMER_ENABLE_reserved_M \ 0xFFFFFFFE #define HIB3P3_MEM_HIB_RTC_TIMER_ENABLE_reserved_S 1 #define HIB3P3_MEM_HIB_RTC_TIMER_ENABLE_mem_hib_rtc_timer_enable \ 0x00000001 // 1 - Enable the RTC timer to // start running ; 0 - Keep the RTC // timer disabled This register will // be reset during Hibernate // -WO-Clks mode (but not during // Hibernate-W-Clks mode). //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_TIMER_RESET register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_TIMER_RESET_reserved_M \ 0xFFFFFFFE #define HIB3P3_MEM_HIB_RTC_TIMER_RESET_reserved_S 1 #define HIB3P3_MEM_HIB_RTC_TIMER_RESET_mem_hib_rtc_timer_reset \ 0x00000001 // 1 - Reset the RTC timer ; 0 - // Donot reset the RTC timer. This // is an auto-clear bit. This // register will be reset during // Hibernate -WO-Clks mode (but not // during Hibernate-W-Clks mode). //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_TIMER_READ register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_TIMER_READ_reserved_M \ 0xFFFFFFFE #define HIB3P3_MEM_HIB_RTC_TIMER_READ_reserved_S 1 #define HIB3P3_MEM_HIB_RTC_TIMER_READ_mem_hib_rtc_timer_read \ 0x00000001 // 1 - Latch the running RTC timer // into local registers. After // programming this bit to 1, the // F/w can read the latched RTC // timer values from // MEM_HIB_RTC_TIMER_LSW and // MEM_HIB_RTC_TIMER_MSW. Before the // F/w (APPS or NWP) wants to read // the RTC-Timer, it has to program // this bit to 1, then only read the // MSW and LSW values. This is an // auto-clear bit. This register // will be reset during Hibernate // -WO-Clks mode (but not during // Hibernate-W-Clks mode). //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_TIMER_LSW register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_TIMER_LSW_hib_rtc_timer_lsw_M \ 0xFFFFFFFF // Lower 32b value of the latched // RTC-Timer. #define HIB3P3_MEM_HIB_RTC_TIMER_LSW_hib_rtc_timer_lsw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_TIMER_MSW register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_TIMER_MSW_reserved_M \ 0xFFFF0000 #define HIB3P3_MEM_HIB_RTC_TIMER_MSW_reserved_S 16 #define HIB3P3_MEM_HIB_RTC_TIMER_MSW_hib_rtc_timer_msw_M \ 0x0000FFFF // Upper 32b value of the latched // RTC-Timer. #define HIB3P3_MEM_HIB_RTC_TIMER_MSW_hib_rtc_timer_msw_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_WAKE_EN register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_WAKE_EN_reserved_M \ 0xFFFFFFFE #define HIB3P3_MEM_HIB_RTC_WAKE_EN_reserved_S 1 #define HIB3P3_MEM_HIB_RTC_WAKE_EN_mem_hib_rtc_wake_en \ 0x00000001 // 1 - Enable the RTC timer based // wakeup during Hibernate mode ; 0 // - Disable the RTC timer based // wakeup during Hibernate mode This // register will be reset during // Hibernate-WO-Clks mode (but not // during Hibernate-W-Clks mode). //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_WAKE_LSW_CONF register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_WAKE_LSW_CONF_mem_hib_rtc_wake_lsw_conf_M \ 0xFFFFFFFF // Configuration for RTC-Timer // Wakeup (Lower 32b word) #define HIB3P3_MEM_HIB_RTC_WAKE_LSW_CONF_mem_hib_rtc_wake_lsw_conf_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_WAKE_MSW_CONF register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_WAKE_MSW_CONF_reserved_M \ 0xFFFF0000 #define HIB3P3_MEM_HIB_RTC_WAKE_MSW_CONF_reserved_S 16 #define HIB3P3_MEM_HIB_RTC_WAKE_MSW_CONF_mem_hib_rtc_wake_msw_conf_M \ 0x0000FFFF // Configuration for RTC-Timer // Wakeup (Upper 16b word) #define HIB3P3_MEM_HIB_RTC_WAKE_MSW_CONF_mem_hib_rtc_wake_msw_conf_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_INT_OSC_CONF register. // //****************************************************************************** #define HIB3P3_MEM_INT_OSC_CONF_reserved_M \ 0xFFFF0000 #define HIB3P3_MEM_INT_OSC_CONF_reserved_S 16 #define HIB3P3_MEM_INT_OSC_CONF_cm_clk_good_32k_int \ 0x00008000 // 1 - Internal 32kHz Oscillator is // valid ; 0 - Internal 32k // oscillator clk is not valid #define HIB3P3_MEM_INT_OSC_CONF_mem_cm_intosc_32k_spare_M \ 0x00007E00 #define HIB3P3_MEM_INT_OSC_CONF_mem_cm_intosc_32k_spare_S 9 #define HIB3P3_MEM_INT_OSC_CONF_mem_cm_en_intosc_32k_override_ctrl \ 0x00000100 // When 1, the INT_32K_OSC_EN comes // from bit [0] of this register, // else comes from the FSM. This // register will be reset during // Hibernate-WO-Clks mode (but not // during Hibernate-W-Clks mode) #define HIB3P3_MEM_INT_OSC_CONF_NU1 \ 0x00000080 #define HIB3P3_MEM_INT_OSC_CONF_mem_cm_intosc_32k_trim_M \ 0x0000007E #define HIB3P3_MEM_INT_OSC_CONF_mem_cm_intosc_32k_trim_S 1 #define HIB3P3_MEM_INT_OSC_CONF_mem_cm_en_intosc_32k \ 0x00000001 // Override value for INT_OSC_EN. // Applicable only when bit [3] of // this register is set to 1. //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_XTAL_OSC_CONF register. // //****************************************************************************** #define HIB3P3_MEM_XTAL_OSC_CONF_reserved_M \ 0xFFF00000 #define HIB3P3_MEM_XTAL_OSC_CONF_reserved_S 20 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_sli_32k_override_ctrl \ 0x00080000 // When 1, the SLICER_EN comes from // bit [10] of this register, else // comes from the FSM. #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_xtal_32k_override_ctrl \ 0x00040000 // When 1, the XTAL_EN comes from // bit [0] of this register, else // comes from the FSM. #define HIB3P3_MEM_XTAL_OSC_CONF_cm_clk_good_xtal \ 0x00020000 // 1 - XTAL Clk is good ; 0 - XTAL // Clk is yet to be valid. #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_xtal_trim_M \ 0x0001F800 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_xtal_trim_S 11 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_sli_32k \ 0x00000400 // SLICER_EN Override value : // Applicable only when bit [19] of // this register is set to 1. #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_sli_32k_trim_M \ 0x00000380 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_sli_32k_trim_S 7 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_fref_32k_slicer_itrim_M \ 0x00000070 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_fref_32k_slicer_itrim_S 4 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_fref_32k_slicer \ 0x00000008 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_input_sense_M \ 0x00000006 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_input_sense_S 1 #define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_xtal_32k \ 0x00000001 // XTAL_EN Override value : // Applicable only when bit [18] of // this register is set to 1. //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_BGAP_PARAMETERS0 register. // //****************************************************************************** #define HIB3P3_MEM_BGAP_PARAMETERS0_reserved_M \ 0xFFF80000 #define HIB3P3_MEM_BGAP_PARAMETERS0_reserved_S 19 #define HIB3P3_MEM_BGAP_PARAMETERS0_mem_en_seq \ 0x00040000 #define HIB3P3_MEM_BGAP_PARAMETERS0_mem_vbok4bg_comp_trim_M \ 0x0001C000 #define HIB3P3_MEM_BGAP_PARAMETERS0_mem_vbok4bg_comp_trim_S 14 #define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_en_vbat_ok_4bg \ 0x00001000 #define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_en_vbok4bg_comp \ 0x00000800 #define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_en_vbok4bg_comp_ref \ 0x00000400 #define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_spare_M \ 0x000003FF #define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_spare_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_BGAP_PARAMETERS1 register. // //****************************************************************************** #define HIB3P3_MEM_BGAP_PARAMETERS1_reserved_M \ 0xE0000000 #define HIB3P3_MEM_BGAP_PARAMETERS1_reserved_S 29 #define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_act_iref_itrim_M \ 0x1F000000 #define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_act_iref_itrim_S 24 #define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_en_act_iref \ 0x00000008 #define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_en_v2i \ 0x00000004 #define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_en_cap_sw \ 0x00000002 #define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_en \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_DETECTION_STATUS register. // //****************************************************************************** #define HIB3P3_MEM_HIB_DETECTION_STATUS_reserved_M \ 0xFFFFFF80 #define HIB3P3_MEM_HIB_DETECTION_STATUS_reserved_S 7 #define HIB3P3_MEM_HIB_DETECTION_STATUS_hib_forced_ana_status \ 0x00000040 // 1 - 1.8 V supply forced mode. #define HIB3P3_MEM_HIB_DETECTION_STATUS_hib_forced_flash_status \ 0x00000004 // 1 - 3.3 V supply forced mode for // Flash supply #define HIB3P3_MEM_HIB_DETECTION_STATUS_hib_ext_clk_det_out_status \ 0x00000002 // 1 - Forced clock mode #define HIB3P3_MEM_HIB_DETECTION_STATUS_hib_xtal_det_out_status \ 0x00000001 // 1 - XTAL clock mode //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_MISC_CONTROLS register. // //****************************************************************************** #define HIB3P3_MEM_HIB_MISC_CONTROLS_reserved_M \ 0xFFFFF800 #define HIB3P3_MEM_HIB_MISC_CONTROLS_reserved_S 11 #define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_en_pok_por_comp \ 0x00000400 #define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_en_pok_por_comp_ref \ 0x00000200 #define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_pok_por_comp_trim_M \ 0x000001C0 #define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_pok_por_comp_trim_S 6 #define HIB3P3_MEM_HIB_MISC_CONTROLS_NU1 \ 0x00000020 #define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_flash_det_en \ 0x00000010 #define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_en_tmux \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_CONFIG register. // //****************************************************************************** #define HIB3P3_MEM_HIB_CONFIG_TOP_MUX_CTRL_SOP_SPIO_M \ 0xFF000000 #define HIB3P3_MEM_HIB_CONFIG_TOP_MUX_CTRL_SOP_SPIO_S 24 #define HIB3P3_MEM_HIB_CONFIG_EN_ANA_DIG_SHARED3 \ 0x00080000 // 1 - Enable VDD_FLASH_INDP_PAD // for digital path (SHARED4) ; 0 - // Disable VDD_FLASH_INDP_PAD for // digital path (SHARED4) ; Before // programming this bit to 1, ensure // that the device is in FORCED 3.3 // supply Mode, which can be // inferred from the register : // MEM_HIB_DETECTION_STATUS : 0x0040 #define HIB3P3_MEM_HIB_CONFIG_EN_ANA_DIG_SHARED2 \ 0x00040000 // 1 - Enable the // VDD_FB_GPIO_MUX_PAD for digital // path (SHARED3) ; 0 - Disable the // VDD_FB_GPIO_MUX_PAD for digital // path (SHARED3) ; This pin can be // used only in modes other than // SOP("111") #define HIB3P3_MEM_HIB_CONFIG_EN_ANA_DIG_SHARED1 \ 0x00020000 // 1 - Enable the PM_TEST_PAD for // digital GPIO path (SHARED2) ; 0 - // Disable the PM_TEST_PAD for // digital GPIO path (SHARED2) This // pin can be used for digital only // in modes other then SOP-111 #define HIB3P3_MEM_HIB_CONFIG_EN_ANA_DIG_SHARED0 \ 0x00010000 // 1 - Enable the XTAL_N pin // digital GPIO path (SHARED1); 0 - // Disable the XTAL_N pin digital // GPIO path (SHARED1). Before // programming this bit to 1, ensure // that the device is in FORCED CLK // Mode, which can inferred from the // register : // MEM_HIB_DETECTION_STATUS : // 0x0040. #define HIB3P3_MEM_HIB_CONFIG_mem_hib_xtal_enable \ 0x00000100 // 1 - Enable the XTAL Clock ; 0 - // Donot enable the XTAL Clock. This // bit has to be programmed to 1 (by // APPS Devinit F/w), during exit // from OFF or Hib_wo_clks modes, // after checking if the slow_clk // mode is XTAL_CLK mode. Once // enabled the XTAL will be disabled // only after entering HIB_WO_CLKS // mode. This register will be reset // during Hibernate -WO-Clks mode // (but not during Hibernate-W-Clks // mode). //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_IRQ_ENABLE_HIB_RTC_IRQ_ENABLE \ 0x00000001 // 1 - Enable the HIB RTC - IRQ ; 0 // - Disable the HIB RTC - IRQ //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_IRQ_LSW_CONF register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_IRQ_LSW_CONF_HIB_RTC_IRQ_LSW_CONF_M \ 0xFFFFFFFF // Configuration for LSW of the // RTC-Timestamp at which interrupt // need to be generated #define HIB3P3_MEM_HIB_RTC_IRQ_LSW_CONF_HIB_RTC_IRQ_LSW_CONF_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_RTC_IRQ_MSW_CONF register. // //****************************************************************************** #define HIB3P3_MEM_HIB_RTC_IRQ_MSW_CONF_HIB_RTC_IRQ_MSW_CONF_M \ 0x0000FFFF // Configuration for MSW of thr // RTC-Timestamp at which the // interrupt need to be generated #define HIB3P3_MEM_HIB_RTC_IRQ_MSW_CONF_HIB_RTC_IRQ_MSW_CONF_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_UART_CONF register. // //****************************************************************************** #define HIB3P3_MEM_HIB_UART_CONF_reserved_M \ 0xFFFFFFFE #define HIB3P3_MEM_HIB_UART_CONF_reserved_S 1 #define HIB3P3_MEM_HIB_UART_CONF_mem_hib_uart_wake_en \ 0x00000001 // 1 - Enable the UART-Autonomous // mode wakeup during Hibernate mode // ; This is an auto-clear bit, once // programmed to 1, it will latched // into an internal register which // remain asserted until the // Hib-wakeup is initiated. //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_GPIO_WAKE_EN register. // //****************************************************************************** #define HIB3P3_MEM_GPIO_WAKE_EN_reserved_M \ 0xFFFFFF00 #define HIB3P3_MEM_GPIO_WAKE_EN_reserved_S 8 #define HIB3P3_MEM_GPIO_WAKE_EN_mem_gpio_wake_en_M \ 0x000000FF // 1 - Enable the GPIO-Autonomous // mode wakeup during Hibernate mode // ; This is an auto-clear bit, once // programmed to 1, it will latched // into an internal register which // remain asserted until the // Hib-wakeup is initiated. #define HIB3P3_MEM_GPIO_WAKE_EN_mem_gpio_wake_en_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_GPIO_WAKE_CONF register. // //****************************************************************************** #define HIB3P3_MEM_GPIO_WAKE_CONF_reserved_M \ 0xFFFF0000 #define HIB3P3_MEM_GPIO_WAKE_CONF_reserved_S 16 #define HIB3P3_MEM_GPIO_WAKE_CONF_mem_gpio_wake_conf_M \ 0x0000FFFF // Configuration to say whether the // GPIO wakeup has to happen on // Level0 or falling-edge for the // given group. “00” – Level0 “01” – // Level1 “10”- Fall-edge “11”- // Rise-edge [1:0] – Conf for GPIO0 // [3:2] – Conf for GPIO1 [5:4] – // Conf for GPIO2 [7:6] – Conf for // GPIO3 [9:8] – Conf for GPIO4 // [11:10] – Conf for GPIO5 [13:12] // – Conf for GPIO6 #define HIB3P3_MEM_GPIO_WAKE_CONF_mem_gpio_wake_conf_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_PAD_OEN_RET33_CONF register. // //****************************************************************************** #define HIB3P3_MEM_PAD_OEN_RET33_CONF_mem_pad_oen_ret33_override_ctrl \ 0x00000004 // 1 - Override the OEN33 and RET33 // controls of GPIOs during // SOP-Bootdebug mode ; 0 - Donot // override the OEN33 and RET33 // controls of GPIOs during // SOP-Bootdebug mode #define HIB3P3_MEM_PAD_OEN_RET33_CONF_PAD_OEN33_CONF \ 0x00000002 #define HIB3P3_MEM_PAD_OEN_RET33_CONF_PAD_RET33_CONF \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_UART_RTS_OEN_RET33_CONF register. // //****************************************************************************** #define HIB3P3_MEM_UART_RTS_OEN_RET33_CONF_mem_uart_nrts_oen_ret33_override_ctrl \ 0x00000004 // 1 - Override the OEN33 and RET33 // controls of UART NRTS GPIO during // SOP-Bootdebug mode ; 0 - Donot // override the OEN33 and RET33 // controls of UART NRTS GPIO during // SOP-Bootdebug mode #define HIB3P3_MEM_UART_RTS_OEN_RET33_CONF_PAD_UART_RTS_OEN33_CONF \ 0x00000002 #define HIB3P3_MEM_UART_RTS_OEN_RET33_CONF_PAD_UART_RTS_RET33_CONF \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_JTAG_CONF register. // //****************************************************************************** #define HIB3P3_MEM_JTAG_CONF_mem_jtag1_oen_ret33_override_ctrl \ 0x00000200 #define HIB3P3_MEM_JTAG_CONF_mem_jtag0_oen_ret33_override_ctrl \ 0x00000100 #define HIB3P3_MEM_JTAG_CONF_PAD_JTAG1_RTS_OEN33_CONF \ 0x00000008 #define HIB3P3_MEM_JTAG_CONF_PAD_JTAG1_RTS_RET33_CONF \ 0x00000004 #define HIB3P3_MEM_JTAG_CONF_PAD_JTAG0_RTS_OEN33_CONF \ 0x00000002 #define HIB3P3_MEM_JTAG_CONF_PAD_JTAG0_RTS_RET33_CONF \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_REG0 register. // //****************************************************************************** #define HIB3P3_MEM_HIB_REG0_mem_hib_reg0_M \ 0xFFFFFFFF #define HIB3P3_MEM_HIB_REG0_mem_hib_reg0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_REG1 register. // //****************************************************************************** #define HIB3P3_MEM_HIB_REG1_mem_hib_reg1_M \ 0xFFFFFFFF #define HIB3P3_MEM_HIB_REG1_mem_hib_reg1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_REG2 register. // //****************************************************************************** #define HIB3P3_MEM_HIB_REG2_mem_hib_reg2_M \ 0xFFFFFFFF #define HIB3P3_MEM_HIB_REG2_mem_hib_reg2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_REG3 register. // //****************************************************************************** #define HIB3P3_MEM_HIB_REG3_mem_hib_reg3_M \ 0xFFFFFFFF #define HIB3P3_MEM_HIB_REG3_mem_hib_reg3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_SEQUENCER_CFG0 register. // //****************************************************************************** #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev0_to_ev1_time_M \ 0xFFFF0000 // Configuration for the number of // slow-clks between de-assertion of // EN_BG_3P3V to assertion of // EN_BG_3P3V #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev0_to_ev1_time_S 16 #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_NU1 \ 0x00008000 #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev3_to_ev4_time_M \ 0x00006000 // Configuration for the number of // slow-clks between assertion of // EN_COMP_3P3V and assertion of // EN_COMP_LATCH_3P3V #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev3_to_ev4_time_S 13 #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev2_to_ev3_time_M \ 0x00001800 // Configuration for the number of // slow-clks between assertion of // (EN_CAP_SW_3P3V,EN_COMP_REF) and // assertion of (EN_COMP_3P3V) #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev2_to_ev3_time_S 11 #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev1_to_ev2_time_M \ 0x00000600 // Configuration for the number of // slow-clks between assertion of // (EN_BG_3P3V) and assertion of // (EN_CAP_SW_3P3V, // EN_COMP_REF_3P3V) #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev1_to_ev2_time_S 9 #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_crude_ref_comp \ 0x00000100 #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_vbok4bg_ref_override_ctrl \ 0x00000080 // 1 - EN_VBOK4BG_REF comes from // bit[10] of the register // MEM_BGAP_PARAMETERS0 [0x0038]. 0 // - EN_VBOK4BG_REF comes directly // from the Hib-Sequencer. #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_vbok4bg_comp_override_ctrl \ 0x00000040 // 1 - EN_VBOK4BG comes from // bit[11] of the register // MEM_BGAP_PARAMETERS0 [0x0038]. 0 // - EN_VBOK4BG comes directly from // the Hib-Sequencer. #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_v2i_override_ctrl \ 0x00000020 // 1 - EN_V2I comes from bit[2] of // the register MEM_BGAP_PARAMETERS1 // [0x003C]. 0 - EN_V2I comes // directly from the Hib-Sequencer. #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_por_comp_ref_override_ctrl \ 0x00000010 // 1 - EN_POR_COMP_REF comes from // bit[9] of the register // MEM_HIB_MISC_CONTROLS [0x0044]. 0 // - EN_POR_COMP_REF comes directly // from the Hib-Sequencer. #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_por_comp_override_ctrl \ 0x00000008 // 1 - EN_POR_COMP comes from // bit[10] of the register // MEM_HIB_MISC_CONTROLS [0x044]. 0 // - EN_POR_COMP comes directly from // the Hib-Sequencer. #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_cap_sw_override_ctrl \ 0x00000004 // 1 - EN_CAP_SW comes from bit[1] // of the register // MEM_BGAP_PARAMETERS1 [0x003C]. 0 // - EN_CAP_SW comes directly from // Hib-Sequencer. #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bg_override_ctrl \ 0x00000002 // 1 - EN_BGAP comes from bit[0] of // the register MEM_BGAP_PARAMETERS1 // [0x003C]. 0 - EN_BGAP comes // directly from Hib-Sequencer. #define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_act_iref_override_ctrl \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_SEQUENCER_CFG1 register. // //****************************************************************************** #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_reserved_M \ 0xFFFF0000 #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_reserved_S 16 #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_ev5_to_ev6_time_M \ 0x0000C000 // Configuration for number of // slow-clks between de-assertion of // EN_COMP_LATCH and assertion of #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_ev5_to_ev6_time_S 14 #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev1_to_ev2_time_M \ 0x00003000 // Configuration for number of // slow-clks between assertion of // EN_COMP_REF to assertion of // EN_COMP during HIB-Exit #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev1_to_ev2_time_S 12 #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev0_to_ev1_time_M \ 0x00000C00 // TBD #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev0_to_ev1_time_S 10 #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev0_to_active_M \ 0x00000300 // Configuration in number of // slow-clks between assertion of // (EN_BGAP_3P3V, EN_CAP_SW_3P3V, // EN_ACT_IREF_3P3V, EN_COMP_REF) to // assertion of EN_COMP_3P3V #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev0_to_active_S 8 #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_active_to_bdc_ev1_to_bdc_ev0_time_M \ 0x000000C0 // Configuration in number of // slow-clks between de-assertion of // (EN_COMP_3P3V, EN_COMP_REF_3P3V, // EN_ACT_IREF_3P3V, EN_CAP_SW_3P3V) // to deassertion of EN_BGAP_3P3V. #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_active_to_bdc_ev1_to_bdc_ev0_time_S 6 #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_NU1_M \ 0x0000003F #define HIB3P3_MEM_HIB_SEQUENCER_CFG1_NU1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_MISC_CONFIG register. // //****************************************************************************** #define HIB3P3_MEM_HIB_MISC_CONFIG_mem_en_pll_untrim_current \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_WAKE_STATUS register. // //****************************************************************************** #define HIB3P3_MEM_HIB_WAKE_STATUS_hib_wake_src_M \ 0x0000001E // "0100" - GPIO ; "0010" - RTC ; // "0001" - UART Others - Reserved #define HIB3P3_MEM_HIB_WAKE_STATUS_hib_wake_src_S 1 #define HIB3P3_MEM_HIB_WAKE_STATUS_hib_wake_status \ 0x00000001 // 1 - Wake from Hibernate ; 0 - // Wake from OFF //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_LPDS_GPIO_SEL register. // //****************************************************************************** #define HIB3P3_MEM_HIB_LPDS_GPIO_SEL_HIB_LPDS_GPIO_SEL_M \ 0x00000007 #define HIB3P3_MEM_HIB_LPDS_GPIO_SEL_HIB_LPDS_GPIO_SEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_MEM_HIB_SEQUENCER_CFG2 register. // //****************************************************************************** #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_reserved_M \ 0xFFFFF800 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_reserved_S 11 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_active_to_bdc_ev0_to_active_to_bdc_ev1_time_M \ 0x00000600 // Deassertion of EN_COMP_LATCH_3P3 // to deassertion of (EN_COMP_3P3, // EN_COMP_REF_3P3, EN_ACT_IREF_3P3, // EN_CAP_SW_3P3) #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_active_to_bdc_ev0_to_active_to_bdc_ev1_time_S 9 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_ev4_to_ev5_time_M \ 0x000001C0 // Assertion of EN_COMP_LATCH_3P3 // to deassertion of // EN_COMP_LATCH_3P3 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_ev4_to_ev5_time_S 6 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_ev6_to_ev7_time_M \ 0x00000030 // Deassertion of (EN_CAP_SW_3P3, // EN_COMP_REF_3P3, EN_COMP_3P3, // EN_COMP_OUT_LATCH_3P3) to // deassertion of EN_BGAP_3P3 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_ev6_to_ev7_time_S 4 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_to_active_ev1_to_ev2_time_M \ 0x0000000C // Assertion of EN_COMP_3P3 to // assertion of EN_COMPOUT_LATCH_3P3 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_to_active_ev1_to_ev2_time_S 2 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_hib_to_active_ev2_to_ev3_time_M \ 0x00000003 // Assertion of EN_COMP_3P3 to // assertion of EN_COMPOUT_LATCH_3P3 #define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_hib_to_active_ev2_to_ev3_time_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIBANA_SPARE_LOWV register. // //****************************************************************************** #define HIB3P3_HIBANA_SPARE_LOWV_mem_hibana_spare1_M \ 0xFFC00000 #define HIB3P3_HIBANA_SPARE_LOWV_mem_hibana_spare1_S 22 #define HIB3P3_HIBANA_SPARE_LOWV_mem_hibana_spare0_M \ 0x0001FFFF #define HIB3P3_HIBANA_SPARE_LOWV_mem_hibana_spare0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIB_TMUX_CTRL register. // //****************************************************************************** #define HIB3P3_HIB_TMUX_CTRL_reserved_M \ 0xFFFFFC00 #define HIB3P3_HIB_TMUX_CTRL_reserved_S 10 #define HIB3P3_HIB_TMUX_CTRL_mem_hd_tmux_cntrl_M \ 0x000003FF #define HIB3P3_HIB_TMUX_CTRL_mem_hd_tmux_cntrl_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIB_1P2_1P8_LDO_TRIM register. // //****************************************************************************** #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_reserved_M \ 0xFFFFF000 #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_reserved_S 12 #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p2_ldo_en_override_ctrl \ 0x00000800 #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p8_ldo_en_override_ctrl \ 0x00000400 #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p2_ldo_en_override \ 0x00000200 #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p8_ldo_en_override \ 0x00000100 #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p2_ldo_vtrim_M \ 0x000000F0 #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p2_ldo_vtrim_S 4 #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p8_ldo_vtrim_M \ 0x0000000F #define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p8_ldo_vtrim_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIB_COMP_TRIM register. // //****************************************************************************** #define HIB3P3_HIB_COMP_TRIM_reserved_M \ 0xFFFFFFF8 #define HIB3P3_HIB_COMP_TRIM_reserved_S 3 #define HIB3P3_HIB_COMP_TRIM_mem_hd_comp_trim_M \ 0x00000007 #define HIB3P3_HIB_COMP_TRIM_mem_hd_comp_trim_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIB_EN_TS register. // //****************************************************************************** #define HIB3P3_HIB_EN_TS_reserved_M \ 0xFFFFFFFE #define HIB3P3_HIB_EN_TS_reserved_S 1 #define HIB3P3_HIB_EN_TS_mem_hd_en_ts \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIB_1P8V_DET_EN register. // //****************************************************************************** #define HIB3P3_HIB_1P8V_DET_EN_reserved_M \ 0xFFFFFFFE #define HIB3P3_HIB_1P8V_DET_EN_reserved_S 1 #define HIB3P3_HIB_1P8V_DET_EN_mem_hib_1p8v_det_en \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIB_VBAT_MON_EN register. // //****************************************************************************** #define HIB3P3_HIB_VBAT_MON_EN_reserved_M \ 0xFFFFFFFC #define HIB3P3_HIB_VBAT_MON_EN_reserved_S 2 #define HIB3P3_HIB_VBAT_MON_EN_mem_hib_vbat_mon_del_en \ 0x00000002 #define HIB3P3_HIB_VBAT_MON_EN_mem_hib_vbat_mon_en \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIB_NHIB_ENABLE register. // //****************************************************************************** #define HIB3P3_HIB_NHIB_ENABLE_mem_hib_nhib_enable \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // HIB3P3_O_HIB_UART_RTS_SW_ENABLE register. // //****************************************************************************** #define HIB3P3_HIB_UART_RTS_SW_ENABLE_mem_hib_uart_rts_sw_enable \ 0x00000001 #endif // __HW_HIB3P3_H__ micropython-1.12/ports/cc3200/hal/inc/hw_i2c.h000066400000000000000000000650151357706137100207330ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_I2C_H__ #define __HW_I2C_H__ //***************************************************************************** // // The following are defines for the I2C register offsets. // //***************************************************************************** #define I2C_O_MSA 0x00000000 #define I2C_O_MCS 0x00000004 #define I2C_O_MDR 0x00000008 #define I2C_O_MTPR 0x0000000C #define I2C_O_MIMR 0x00000010 #define I2C_O_MRIS 0x00000014 #define I2C_O_MMIS 0x00000018 #define I2C_O_MICR 0x0000001C #define I2C_O_MCR 0x00000020 #define I2C_O_MCLKOCNT 0x00000024 #define I2C_O_MBMON 0x0000002C #define I2C_O_MBLEN 0x00000030 #define I2C_O_MBCNT 0x00000034 #define I2C_O_SOAR 0x00000800 #define I2C_O_SCSR 0x00000804 #define I2C_O_SDR 0x00000808 #define I2C_O_SIMR 0x0000080C #define I2C_O_SRIS 0x00000810 #define I2C_O_SMIS 0x00000814 #define I2C_O_SICR 0x00000818 #define I2C_O_SOAR2 0x0000081C #define I2C_O_SACKCTL 0x00000820 #define I2C_O_FIFODATA 0x00000F00 #define I2C_O_FIFOCTL 0x00000F04 #define I2C_O_FIFOSTATUS 0x00000F08 #define I2C_O_OBSMUXSEL0 0x00000F80 #define I2C_O_OBSMUXSEL1 0x00000F84 #define I2C_O_MUXROUTE 0x00000F88 #define I2C_O_PV 0x00000FB0 #define I2C_O_PP 0x00000FC0 #define I2C_O_PC 0x00000FC4 #define I2C_O_CC 0x00000FC8 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MSA register. // //****************************************************************************** #define I2C_MSA_SA_M 0x000000FE // I2C Slave Address #define I2C_MSA_SA_S 1 #define I2C_MSA_RS 0x00000001 // Receive not send //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MCS register. // //****************************************************************************** #define I2C_MCS_ACTDMARX 0x80000000 // DMA RX Active Status #define I2C_MCS_ACTDMATX 0x40000000 // DMA TX Active Status #define I2C_MCS_CLKTO 0x00000080 // Clock Timeout Error #define I2C_MCS_BUSBSY 0x00000040 // Bus Busy #define I2C_MCS_IDLE 0x00000020 // I2C Idle #define I2C_MCS_ARBLST 0x00000010 // Arbitration Lost #define I2C_MCS_ACK 0x00000008 // Data Acknowledge Enable #define I2C_MCS_ADRACK 0x00000004 // Acknowledge Address #define I2C_MCS_ERROR 0x00000002 // Error #define I2C_MCS_BUSY 0x00000001 // I2C Busy //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MDR register. // //****************************************************************************** #define I2C_MDR_DATA_M 0x000000FF // Data Transferred #define I2C_MDR_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MTPR register. // //****************************************************************************** #define I2C_MTPR_HS 0x00000080 // High-Speed Enable #define I2C_MTPR_TPR_M 0x0000007F // SCL Clock Period #define I2C_MTPR_TPR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MIMR register. // //****************************************************************************** #define I2C_MIMR_RXFFIM 0x00000800 // Receive FIFO Full Interrupt Mask #define I2C_MIMR_TXFEIM 0x00000400 // Transmit FIFO Empty Interrupt // Mask #define I2C_MIMR_RXIM 0x00000200 // Receive FIFO Request Interrupt // Mask #define I2C_MIMR_TXIM 0x00000100 // Transmit FIFO Request Interrupt // Mask #define I2C_MIMR_ARBLOSTIM 0x00000080 // Arbitration Lost Interrupt Mask #define I2C_MIMR_STOPIM 0x00000040 // STOP Detection Interrupt Mask #define I2C_MIMR_STARTIM 0x00000020 // START Detection Interrupt Mask #define I2C_MIMR_NACKIM 0x00000010 // Address/Data NACK Interrupt Mask #define I2C_MIMR_DMATXIM 0x00000008 // Transmit DMA Interrupt Mask #define I2C_MIMR_DMARXIM 0x00000004 // Receive DMA Interrupt Mask #define I2C_MIMR_CLKIM 0x00000002 // Clock Timeout Interrupt Mask #define I2C_MIMR_IM 0x00000001 // Master Interrupt Mask //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MRIS register. // //****************************************************************************** #define I2C_MRIS_RXFFRIS 0x00000800 // Receive FIFO Full Raw Interrupt // Status #define I2C_MRIS_TXFERIS 0x00000400 // Transmit FIFO Empty Raw // Interrupt Status #define I2C_MRIS_RXRIS 0x00000200 // Receive FIFO Request Raw // Interrupt Status #define I2C_MRIS_TXRIS 0x00000100 // Transmit Request Raw Interrupt // Status #define I2C_MRIS_ARBLOSTRIS 0x00000080 // Arbitration Lost Raw Interrupt // Status #define I2C_MRIS_STOPRIS 0x00000040 // STOP Detection Raw Interrupt // Status #define I2C_MRIS_STARTRIS 0x00000020 // START Detection Raw Interrupt // Status #define I2C_MRIS_NACKRIS 0x00000010 // Address/Data NACK Raw Interrupt // Status #define I2C_MRIS_DMATXRIS 0x00000008 // Transmit DMA Raw Interrupt // Status #define I2C_MRIS_DMARXRIS 0x00000004 // Receive DMA Raw Interrupt Status #define I2C_MRIS_CLKRIS 0x00000002 // Clock Timeout Raw Interrupt // Status #define I2C_MRIS_RIS 0x00000001 // Master Raw Interrupt Status //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MMIS register. // //****************************************************************************** #define I2C_MMIS_RXFFMIS 0x00000800 // Receive FIFO Full Interrupt Mask #define I2C_MMIS_TXFEMIS 0x00000400 // Transmit FIFO Empty Interrupt // Mask #define I2C_MMIS_RXMIS 0x00000200 // Receive FIFO Request Interrupt // Mask #define I2C_MMIS_TXMIS 0x00000100 // Transmit Request Interrupt Mask #define I2C_MMIS_ARBLOSTMIS 0x00000080 // Arbitration Lost Interrupt Mask #define I2C_MMIS_STOPMIS 0x00000040 // STOP Detection Interrupt Mask #define I2C_MMIS_STARTMIS 0x00000020 // START Detection Interrupt Mask #define I2C_MMIS_NACKMIS 0x00000010 // Address/Data NACK Interrupt Mask #define I2C_MMIS_DMATXMIS 0x00000008 // Transmit DMA Interrupt Status #define I2C_MMIS_DMARXMIS 0x00000004 // Receive DMA Interrupt Status #define I2C_MMIS_CLKMIS 0x00000002 // Clock Timeout Masked Interrupt // Status #define I2C_MMIS_MIS 0x00000001 // Masked Interrupt Status //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MICR register. // //****************************************************************************** #define I2C_MICR_RXFFIC 0x00000800 // Receive FIFO Full Interrupt // Clear #define I2C_MICR_TXFEIC 0x00000400 // Transmit FIFO Empty Interrupt // Clear #define I2C_MICR_RXIC 0x00000200 // Receive FIFO Request Interrupt // Clear #define I2C_MICR_TXIC 0x00000100 // Transmit FIFO Request Interrupt // Clear #define I2C_MICR_ARBLOSTIC 0x00000080 // Arbitration Lost Interrupt Clear #define I2C_MICR_STOPIC 0x00000040 // STOP Detection Interrupt Clear #define I2C_MICR_STARTIC 0x00000020 // START Detection Interrupt Clear #define I2C_MICR_NACKIC 0x00000010 // Address/Data NACK Interrupt // Clear #define I2C_MICR_DMATXIC 0x00000008 // Transmit DMA Interrupt Clear #define I2C_MICR_DMARXIC 0x00000004 // Receive DMA Interrupt Clear #define I2C_MICR_CLKIC 0x00000002 // Clock Timeout Interrupt Clear #define I2C_MICR_IC 0x00000001 // Master Interrupt Clear //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MCR register. // //****************************************************************************** #define I2C_MCR_MMD 0x00000040 // Multi-master Disable #define I2C_MCR_SFE 0x00000020 // I2C Slave Function Enable #define I2C_MCR_MFE 0x00000010 // I2C Master Function Enable #define I2C_MCR_LPBK 0x00000001 // I2C Loopback //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MCLKOCNT register. // //****************************************************************************** #define I2C_MCLKOCNT_CNTL_M 0x000000FF // I2C Master Count #define I2C_MCLKOCNT_CNTL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MBMON register. // //****************************************************************************** #define I2C_MBMON_SDA 0x00000002 // I2C SDA Status #define I2C_MBMON_SCL 0x00000001 // I2C SCL Status //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MBLEN register. // //****************************************************************************** #define I2C_MBLEN_CNTL_M 0x000000FF // I2C Burst Length #define I2C_MBLEN_CNTL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MBCNT register. // //****************************************************************************** #define I2C_MBCNT_CNTL_M 0x000000FF // I2C Master Burst Count #define I2C_MBCNT_CNTL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SOAR register. // //****************************************************************************** #define I2C_SOAR_OAR_M 0x0000007F // I2C Slave Own Address #define I2C_SOAR_OAR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SCSR register. // //****************************************************************************** #define I2C_SCSR_ACTDMARX 0x80000000 // DMA RX Active Status #define I2C_SCSR_ACTDMATX 0x40000000 // DMA TX Active Status #define I2C_SCSR_QCMDRW 0x00000020 // Quick Command Read / Write #define I2C_SCSR_QCMDST 0x00000010 // Quick Command Status #define I2C_SCSR_OAR2SEL 0x00000008 // OAR2 Address Matched #define I2C_SCSR_FBR 0x00000004 // First Byte Received #define I2C_SCSR_TREQ 0x00000002 // Transmit Request #define I2C_SCSR_DA 0x00000001 // Device Active //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SDR register. // //****************************************************************************** #define I2C_SDR_DATA_M 0x000000FF // Data for Transfer #define I2C_SDR_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SIMR register. // //****************************************************************************** #define I2C_SIMR_IM 0x00000100 // Interrupt Mask #define I2C_SIMR_TXFEIM 0x00000080 // Transmit FIFO Empty Interrupt // Mask #define I2C_SIMR_RXIM 0x00000040 // Receive FIFO Request Interrupt // Mask #define I2C_SIMR_TXIM 0x00000020 // Transmit FIFO Request Interrupt // Mask #define I2C_SIMR_DMATXIM 0x00000010 // Transmit DMA Interrupt Mask #define I2C_SIMR_DMARXIM 0x00000008 // Receive DMA Interrupt Mask #define I2C_SIMR_STOPIM 0x00000004 // Stop Condition Interrupt Mask #define I2C_SIMR_STARTIM 0x00000002 // Start Condition Interrupt Mask #define I2C_SIMR_DATAIM 0x00000001 // Data Interrupt Mask //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SRIS register. // //****************************************************************************** #define I2C_SRIS_RIS 0x00000100 // Raw Interrupt Status #define I2C_SRIS_TXFERIS 0x00000080 // Transmit FIFO Empty Raw // Interrupt Status #define I2C_SRIS_RXRIS 0x00000040 // Receive FIFO Request Raw // Interrupt Status #define I2C_SRIS_TXRIS 0x00000020 // Transmit Request Raw Interrupt // Status #define I2C_SRIS_DMATXRIS 0x00000010 // Transmit DMA Raw Interrupt // Status #define I2C_SRIS_DMARXRIS 0x00000008 // Receive DMA Raw Interrupt Status #define I2C_SRIS_STOPRIS 0x00000004 // Stop Condition Raw Interrupt // Status #define I2C_SRIS_STARTRIS 0x00000002 // Start Condition Raw Interrupt // Status #define I2C_SRIS_DATARIS 0x00000001 // Data Raw Interrupt Status //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SMIS register. // //****************************************************************************** #define I2C_SMIS_RXFFMIS 0x00000100 // Receive FIFO Full Interrupt Mask #define I2C_SMIS_TXFEMIS 0x00000080 // Transmit FIFO Empty Interrupt // Mask #define I2C_SMIS_RXMIS 0x00000040 // Receive FIFO Request Interrupt // Mask #define I2C_SMIS_TXMIS 0x00000020 // Transmit FIFO Request Interrupt // Mask #define I2C_SMIS_DMATXMIS 0x00000010 // Transmit DMA Masked Interrupt // Status #define I2C_SMIS_DMARXMIS 0x00000008 // Receive DMA Masked Interrupt // Status #define I2C_SMIS_STOPMIS 0x00000004 // Stop Condition Masked Interrupt // Status #define I2C_SMIS_STARTMIS 0x00000002 // Start Condition Masked Interrupt // Status #define I2C_SMIS_DATAMIS 0x00000001 // Data Masked Interrupt Status //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SICR register. // //****************************************************************************** #define I2C_SICR_RXFFIC 0x00000100 // Receive FIFO Full Interrupt Mask #define I2C_SICR_TXFEIC 0x00000080 // Transmit FIFO Empty Interrupt // Mask #define I2C_SICR_RXIC 0x00000040 // Receive Request Interrupt Mask #define I2C_SICR_TXIC 0x00000020 // Transmit Request Interrupt Mask #define I2C_SICR_DMATXIC 0x00000010 // Transmit DMA Interrupt Clear #define I2C_SICR_DMARXIC 0x00000008 // Receive DMA Interrupt Clear #define I2C_SICR_STOPIC 0x00000004 // Stop Condition Interrupt Clear #define I2C_SICR_STARTIC 0x00000002 // Start Condition Interrupt Clear #define I2C_SICR_DATAIC 0x00000001 // Data Interrupt Clear //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SOAR2 register. // //****************************************************************************** #define I2C_SOAR2_OAR2EN 0x00000080 // I2C Slave Own Address 2 Enable #define I2C_SOAR2_OAR2_M 0x0000007F // I2C Slave Own Address 2 #define I2C_SOAR2_OAR2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_SACKCTL register. // //****************************************************************************** #define I2C_SACKCTL_ACKOVAL 0x00000002 // I2C Slave ACK Override Value #define I2C_SACKCTL_ACKOEN 0x00000001 // I2C Slave ACK Override Enable //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_FIFODATA register. // //****************************************************************************** #define I2C_FIFODATA_DATA_M 0x000000FF // I2C FIFO Data Byte #define I2C_FIFODATA_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_FIFOCTL register. // //****************************************************************************** #define I2C_FIFOCTL_RXASGNMT 0x80000000 // RX Control Assignment #define I2C_FIFOCTL_RXFLUSH 0x40000000 // RX FIFO Flush #define I2C_FIFOCTL_DMARXENA 0x20000000 // DMA RX Channel Enable #define I2C_FIFOCTL_RXTRIG_M 0x00070000 // RX FIFO Trigger #define I2C_FIFOCTL_RXTRIG_S 16 #define I2C_FIFOCTL_TXASGNMT 0x00008000 // TX Control Assignment #define I2C_FIFOCTL_TXFLUSH 0x00004000 // TX FIFO Flush #define I2C_FIFOCTL_DMATXENA 0x00002000 // DMA TX Channel Enable #define I2C_FIFOCTL_TXTRIG_M 0x00000007 // TX FIFO Trigger #define I2C_FIFOCTL_TXTRIG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_FIFOSTATUS register. // //****************************************************************************** #define I2C_FIFOSTATUS_RXABVTRIG \ 0x00040000 // RX FIFO Above Trigger Level #define I2C_FIFOSTATUS_RXFF 0x00020000 // RX FIFO Full #define I2C_FIFOSTATUS_RXFE 0x00010000 // RX FIFO Empty #define I2C_FIFOSTATUS_TXBLWTRIG \ 0x00000004 // TX FIFO Below Trigger Level #define I2C_FIFOSTATUS_TXFF 0x00000002 // TX FIFO Full #define I2C_FIFOSTATUS_TXFE 0x00000001 // TX FIFO Empty //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_OBSMUXSEL0 register. // //****************************************************************************** #define I2C_OBSMUXSEL0_LN3_M 0x07000000 // Observation Mux Lane 3 #define I2C_OBSMUXSEL0_LN3_S 24 #define I2C_OBSMUXSEL0_LN2_M 0x00070000 // Observation Mux Lane 2 #define I2C_OBSMUXSEL0_LN2_S 16 #define I2C_OBSMUXSEL0_LN1_M 0x00000700 // Observation Mux Lane 1 #define I2C_OBSMUXSEL0_LN1_S 8 #define I2C_OBSMUXSEL0_LN0_M 0x00000007 // Observation Mux Lane 0 #define I2C_OBSMUXSEL0_LN0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_OBSMUXSEL1 register. // //****************************************************************************** #define I2C_OBSMUXSEL1_LN7_M 0x07000000 // Observation Mux Lane 7 #define I2C_OBSMUXSEL1_LN7_S 24 #define I2C_OBSMUXSEL1_LN6_M 0x00070000 // Observation Mux Lane 6 #define I2C_OBSMUXSEL1_LN6_S 16 #define I2C_OBSMUXSEL1_LN5_M 0x00000700 // Observation Mux Lane 5 #define I2C_OBSMUXSEL1_LN5_S 8 #define I2C_OBSMUXSEL1_LN4_M 0x00000007 // Observation Mux Lane 4 #define I2C_OBSMUXSEL1_LN4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_MUXROUTE register. // //****************************************************************************** #define I2C_MUXROUTE_LN7ROUTE_M \ 0x70000000 // Lane 7 output is routed to the // lane pointed to by the offset in // this bit field #define I2C_MUXROUTE_LN7ROUTE_S 28 #define I2C_MUXROUTE_LN6ROUTE_M \ 0x07000000 // Lane 6 output is routed to the // lane pointed to by the offset in // this bit field #define I2C_MUXROUTE_LN6ROUTE_S 24 #define I2C_MUXROUTE_LN5ROUTE_M \ 0x00700000 // Lane 5 output is routed to the // lane pointed to by the offset in // this bit field #define I2C_MUXROUTE_LN5ROUTE_S 20 #define I2C_MUXROUTE_LN4ROUTE_M \ 0x00070000 // Lane 4 output is routed to the // lane pointed to by the offset in // this bit field #define I2C_MUXROUTE_LN4ROUTE_S 16 #define I2C_MUXROUTE_LN3ROUTE_M \ 0x00007000 // Lane 3 output is routed to the // lane pointed to by the offset in // this bit field #define I2C_MUXROUTE_LN3ROUTE_S 12 #define I2C_MUXROUTE_LN2ROUTE_M \ 0x00000700 // Lane 2 output is routed to the // lane pointed to by the offset in // this bit field #define I2C_MUXROUTE_LN2ROUTE_S 8 #define I2C_MUXROUTE_LN1ROUTE_M \ 0x00000070 // Lane 1 output is routed to the // lane pointed to by the offset in // this bit field #define I2C_MUXROUTE_LN1ROUTE_S 4 #define I2C_MUXROUTE_LN0ROUTE_M \ 0x00000007 // Lane 0 output is routed to the // lane pointed to by the offset in // this bit field #define I2C_MUXROUTE_LN0ROUTE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_PV register. // //****************************************************************************** #define I2C_PV_MAJOR_M 0x0000FF00 // Major Revision #define I2C_PV_MAJOR_S 8 #define I2C_PV_MINOR_M 0x000000FF // Minor Revision #define I2C_PV_MINOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_PP register. // //****************************************************************************** #define I2C_PP_HS 0x00000001 // High-Speed Capable //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_PC register. // //****************************************************************************** #define I2C_PC_HS 0x00000001 // High-Speed Capable //****************************************************************************** // // The following are defines for the bit fields in the I2C_O_CC register. // //****************************************************************************** #endif // __HW_I2C_H__ micropython-1.12/ports/cc3200/hal/inc/hw_ints.h000066400000000000000000000131731357706137100212310ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // // hw_ints.h - Macros that define the interrupt assignment on CC3200. // //***************************************************************************** #ifndef __HW_INTS_H__ #define __HW_INTS_H__ //***************************************************************************** // // The following are defines for the fault assignments. // //***************************************************************************** #define FAULT_NMI 2 // NMI fault #define FAULT_HARD 3 // Hard fault #define FAULT_MPU 4 // MPU fault #define FAULT_BUS 5 // Bus fault #define FAULT_USAGE 6 // Usage fault #define FAULT_SVCALL 11 // SVCall #define FAULT_DEBUG 12 // Debug monitor #define FAULT_PENDSV 14 // PendSV #define FAULT_SYSTICK 15 // System Tick //***************************************************************************** // // The following are defines for the interrupt assignments. // //***************************************************************************** #define INT_GPIOA0 16 // GPIO Port S0 #define INT_GPIOA1 17 // GPIO Port S1 #define INT_GPIOA2 18 // GPIO Port S2 #define INT_GPIOA3 19 // GPIO Port S3 #define INT_UARTA0 21 // UART0 Rx and Tx #define INT_UARTA1 22 // UART1 Rx and Tx #define INT_I2CA0 24 // I2C controller #define INT_ADCCH0 30 // ADC Sequence 0 #define INT_ADCCH1 31 // ADC Sequence 1 #define INT_ADCCH2 32 // ADC Sequence 2 #define INT_ADCCH3 33 // ADC Sequence 3 #define INT_WDT 34 // Watchdog Timer0 #define INT_TIMERA0A 35 // Timer 0 subtimer A #define INT_TIMERA0B 36 // Timer 0 subtimer B #define INT_TIMERA1A 37 // Timer 1 subtimer A #define INT_TIMERA1B 38 // Timer 1 subtimer B #define INT_TIMERA2A 39 // Timer 2 subtimer A #define INT_TIMERA2B 40 // Timer 2 subtimer B #define INT_FLASH 45 // FLASH Control #define INT_TIMERA3A 51 // Timer 3 subtimer A #define INT_TIMERA3B 52 // Timer 3 subtimer B #define INT_UDMA 62 // uDMA controller #define INT_UDMAERR 63 // uDMA Error #define INT_SHA 164 // SHA #define INT_AES 167 // AES #define INT_DES 169 // DES #define INT_MMCHS 175 // SDIO #define INT_I2S 177 // McAPS #define INT_CAMERA 179 // Camera #define INT_NWPIC 187 // Interprocessor communication #define INT_PRCM 188 // Power, Reset and Clock Module #define INT_SSPI 191 // Shared SPI #define INT_GSPI 192 // Generic SPI #define INT_LSPI 193 // Link SPI //***************************************************************************** // // The following are defines for the total number of interrupts. // //***************************************************************************** #define NUM_INTERRUPTS 195 //The above number plus 2? //***************************************************************************** // // The following are defines for the total number of priority levels. // //***************************************************************************** #define NUM_PRIORITY 8 #define NUM_PRIORITY_BITS 3 #endif // __HW_INTS_H__ micropython-1.12/ports/cc3200/hal/inc/hw_mcasp.h000066400000000000000000002605511357706137100213630ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_MCASP_H__ #define __HW_MCASP_H__ //***************************************************************************** // // The following are defines for the MCASP register offsets. // //***************************************************************************** #define MCASP_O_PID 0x00000000 #define MCASP_O_ESYSCONFIG 0x00000004 // Power Idle SYSCONFIG register. #define MCASP_O_PFUNC 0x00000010 #define MCASP_O_PDIR 0x00000014 #define MCASP_O_PDOUT 0x00000018 #define MCASP_O_PDSET 0x0000001C // The pin data set register // (PDSET) is an alias of the pin // data output register (PDOUT) for // writes only. Writing a 1 to the // PDSET bit sets the corresponding // bit in PDOUT and if PFUNC = 1 // (GPIO function) and PDIR = 1 // (output) drives a logic high on // the pin. #define MCASP_O_PDIN 0x0000001C // The pin data input register // (PDIN) holds the I/O pin state of // each of the McASP pins. PDIN // allows the actual value of the // pin to be read regardless of the // state of PFUNC and PDIR. #define MCASP_O_PDCLR 0x00000020 // The pin data clear register // (PDCLR) is an alias of the pin // data output register (PDOUT) for // writes only. Writing a 1 to the // PDCLR bit clears the // corresponding bit in PDOUT and if // PFUNC = 1 (GPIO function) and // PDIR = 1 (output) drives a logic // low on the pin. #define MCASP_O_TLGC 0x00000030 // for IODFT #define MCASP_O_TLMR 0x00000034 // for IODFT #define MCASP_O_TLEC 0x00000038 // for IODFT #define MCASP_O_GBLCTL 0x00000044 #define MCASP_O_AMUTE 0x00000048 #define MCASP_O_LBCTL 0x0000004C #define MCASP_O_TXDITCTL 0x00000050 #define MCASP_O_GBLCTLR 0x00000060 #define MCASP_O_RXMASK 0x00000064 #define MCASP_O_RXFMT 0x00000068 #define MCASP_O_RXFMCTL 0x0000006C #define MCASP_O_ACLKRCTL 0x00000070 #define MCASP_O_AHCLKRCTL 0x00000074 #define MCASP_O_RXTDM 0x00000078 #define MCASP_O_EVTCTLR 0x0000007C #define MCASP_O_RXSTAT 0x00000080 #define MCASP_O_RXTDMSLOT 0x00000084 #define MCASP_O_RXCLKCHK 0x00000088 #define MCASP_O_REVTCTL 0x0000008C #define MCASP_O_GBLCTLX 0x000000A0 #define MCASP_O_TXMASK 0x000000A4 #define MCASP_O_TXFMT 0x000000A8 #define MCASP_O_TXFMCTL 0x000000AC #define MCASP_O_ACLKXCTL 0x000000B0 #define MCASP_O_AHCLKXCTL 0x000000B4 #define MCASP_O_TXTDM 0x000000B8 #define MCASP_O_EVTCTLX 0x000000BC #define MCASP_O_TXSTAT 0x000000C0 #define MCASP_O_TXTDMSLOT 0x000000C4 #define MCASP_O_TXCLKCHK 0x000000C8 #define MCASP_O_XEVTCTL 0x000000CC #define MCASP_O_CLKADJEN 0x000000D0 #define MCASP_O_DITCSRA0 0x00000100 #define MCASP_O_DITCSRA1 0x00000104 #define MCASP_O_DITCSRA2 0x00000108 #define MCASP_O_DITCSRA3 0x0000010C #define MCASP_O_DITCSRA4 0x00000110 #define MCASP_O_DITCSRA5 0x00000114 #define MCASP_O_DITCSRB0 0x00000118 #define MCASP_O_DITCSRB1 0x0000011C #define MCASP_O_DITCSRB2 0x00000120 #define MCASP_O_DITCSRB3 0x00000124 #define MCASP_O_DITCSRB4 0x00000128 #define MCASP_O_DITCSRB5 0x0000012C #define MCASP_O_DITUDRA0 0x00000130 #define MCASP_O_DITUDRA1 0x00000134 #define MCASP_O_DITUDRA2 0x00000138 #define MCASP_O_DITUDRA3 0x0000013C #define MCASP_O_DITUDRA4 0x00000140 #define MCASP_O_DITUDRA5 0x00000144 #define MCASP_O_DITUDRB0 0x00000148 #define MCASP_O_DITUDRB1 0x0000014C #define MCASP_O_DITUDRB2 0x00000150 #define MCASP_O_DITUDRB3 0x00000154 #define MCASP_O_DITUDRB4 0x00000158 #define MCASP_O_DITUDRB5 0x0000015C #define MCASP_O_XRSRCTL0 0x00000180 #define MCASP_O_XRSRCTL1 0x00000184 #define MCASP_O_XRSRCTL2 0x00000188 #define MCASP_O_XRSRCTL3 0x0000018C #define MCASP_O_XRSRCTL4 0x00000190 #define MCASP_O_XRSRCTL5 0x00000194 #define MCASP_O_XRSRCTL6 0x00000198 #define MCASP_O_XRSRCTL7 0x0000019C #define MCASP_O_XRSRCTL8 0x000001A0 #define MCASP_O_XRSRCTL9 0x000001A4 #define MCASP_O_XRSRCTL10 0x000001A8 #define MCASP_O_XRSRCTL11 0x000001AC #define MCASP_O_XRSRCTL12 0x000001B0 #define MCASP_O_XRSRCTL13 0x000001B4 #define MCASP_O_XRSRCTL14 0x000001B8 #define MCASP_O_XRSRCTL15 0x000001BC #define MCASP_O_TXBUF0 0x00000200 #define MCASP_O_TXBUF1 0x00000204 #define MCASP_O_TXBUF2 0x00000208 #define MCASP_O_TXBUF3 0x0000020C #define MCASP_O_TXBUF4 0x00000210 #define MCASP_O_TXBUF5 0x00000214 #define MCASP_O_TXBUF6 0x00000218 #define MCASP_O_TXBUF7 0x0000021C #define MCASP_O_TXBUF8 0x00000220 #define MCASP_O_TXBUF9 0x00000224 #define MCASP_O_TXBUF10 0x00000228 #define MCASP_O_TXBUF11 0x0000022C #define MCASP_O_TXBUF12 0x00000230 #define MCASP_O_TXBUF13 0x00000234 #define MCASP_O_TXBUF14 0x00000238 #define MCASP_O_TXBUF15 0x0000023C #define MCASP_O_RXBUF0 0x00000280 #define MCASP_O_RXBUF1 0x00000284 #define MCASP_O_RXBUF2 0x00000288 #define MCASP_O_RXBUF3 0x0000028C #define MCASP_O_RXBUF4 0x00000290 #define MCASP_O_RXBUF5 0x00000294 #define MCASP_O_RXBUF6 0x00000298 #define MCASP_O_RXBUF7 0x0000029C #define MCASP_O_RXBUF8 0x000002A0 #define MCASP_O_RXBUF9 0x000002A4 #define MCASP_O_RXBUF10 0x000002A8 #define MCASP_O_RXBUF11 0x000002AC #define MCASP_O_RXBUF12 0x000002B0 #define MCASP_O_RXBUF13 0x000002B4 #define MCASP_O_RXBUF14 0x000002B8 #define MCASP_O_RXBUF15 0x000002BC #define MCASP_0_WFIFOCTL 0x00001000 #define MCASP_0_WFIFOSTS 0x00001004 #define MCASP_0_RFIFOCTL 0x00001008 #define MCASP_0_RFIFOSTS 0x0000100C //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_PID register. // //****************************************************************************** #define MCASP_PID_SCHEME_M 0xC0000000 #define MCASP_PID_SCHEME_S 30 #define MCASP_PID_RESV_M 0x30000000 #define MCASP_PID_RESV_S 28 #define MCASP_PID_FUNCTION_M 0x0FFF0000 // McASP #define MCASP_PID_FUNCTION_S 16 #define MCASP_PID_RTL_M 0x0000F800 #define MCASP_PID_RTL_S 11 #define MCASP_PID_REVMAJOR_M 0x00000700 #define MCASP_PID_REVMAJOR_S 8 #define MCASP_PID_CUSTOM_M 0x000000C0 // non-custom #define MCASP_PID_CUSTOM_S 6 #define MCASP_PID_REVMINOR_M 0x0000003F #define MCASP_PID_REVMINOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // MCASP_O_ESYSCONFIG register. // //****************************************************************************** #define MCASP_ESYSCONFIG_RSV_M 0xFFFFFFC0 // Reserved as per PDR 3.5 #define MCASP_ESYSCONFIG_RSV_S 6 #define MCASP_ESYSCONFIG_OTHER_M \ 0x0000003C // Reserved for future expansion #define MCASP_ESYSCONFIG_OTHER_S 2 #define MCASP_ESYSCONFIG_IDLE_MODE_M \ 0x00000003 // Idle Mode #define MCASP_ESYSCONFIG_IDLE_MODE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_PFUNC register. // //****************************************************************************** #define MCASP_PFUNC_AFSR 0x80000000 // AFSR PFUNC 31 0 1 #define MCASP_PFUNC_AHCLKR 0x40000000 // AHCLKR PFUNC 30 0 1 #define MCASP_PFUNC_ACLKR 0x20000000 // ACLKR PFUNC 29 0 1 #define MCASP_PFUNC_AFSX 0x10000000 // AFSX PFUNC 28 0 1 #define MCASP_PFUNC_AHCLKX 0x08000000 // AHCLKX PFUNC 27 0 1 #define MCASP_PFUNC_ACLKX 0x04000000 // ACLKX PFUNC 26 0 1 #define MCASP_PFUNC_AMUTE 0x02000000 // AMUTE PFUNC 25 0 1 #define MCASP_PFUNC_RESV1_M 0x01FF0000 // Reserved #define MCASP_PFUNC_RESV1_S 16 #define MCASP_PFUNC_AXR15 0x00008000 // AXR PFUNC BIT 15 0 1 #define MCASP_PFUNC_AXR14 0x00004000 // AXR PFUNC BIT 14 0 1 #define MCASP_PFUNC_AXR13 0x00002000 // AXR PFUNC BIT 13 0 1 #define MCASP_PFUNC_AXR12 0x00001000 // AXR PFUNC BIT 12 0 1 #define MCASP_PFUNC_AXR11 0x00000800 // AXR PFUNC BIT 11 0 1 #define MCASP_PFUNC_AXR10 0x00000400 // AXR PFUNC BIT 10 0 1 #define MCASP_PFUNC_AXR9 0x00000200 // AXR PFUNC BIT 9 0 1 #define MCASP_PFUNC_AXR8 0x00000100 // AXR PFUNC BIT 8 0 1 #define MCASP_PFUNC_AXR7 0x00000080 // AXR PFUNC BIT 7 0 1 #define MCASP_PFUNC_AXR6 0x00000040 // AXR PFUNC BIT 6 0 1 #define MCASP_PFUNC_AXR5 0x00000020 // AXR PFUNC BIT 5 0 1 #define MCASP_PFUNC_AXR4 0x00000010 // AXR PFUNC BIT 4 0 1 #define MCASP_PFUNC_AXR3 0x00000008 // AXR PFUNC BIT 3 0 1 #define MCASP_PFUNC_AXR2 0x00000004 // AXR PFUNC BIT 2 0 1 #define MCASP_PFUNC_AXR1 0x00000002 // AXR PFUNC BIT 1 0 1 #define MCASP_PFUNC_AXR0 0x00000001 // AXR PFUNC BIT 0 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_PDIR register. // //****************************************************************************** #define MCASP_PDIR_AFSR 0x80000000 // AFSR PDIR 31 0 1 #define MCASP_PDIR_AHCLKR 0x40000000 // AHCLKR PDIR 30 0 1 #define MCASP_PDIR_ACLKR 0x20000000 // ACLKR PDIR 29 0 1 #define MCASP_PDIR_AFSX 0x10000000 // AFSX PDIR 28 0 1 #define MCASP_PDIR_AHCLKX 0x08000000 // AHCLKX PDIR 27 0 1 #define MCASP_PDIR_ACLKX 0x04000000 // ACLKX PDIR 26 0 1 #define MCASP_PDIR_AMUTE 0x02000000 // AMUTE PDIR 25 0 1 #define MCASP_PDIR_RESV_M 0x01FF0000 // Reserved #define MCASP_PDIR_RESV_S 16 #define MCASP_PDIR_AXR15 0x00008000 // AXR PDIR BIT 15 0 1 #define MCASP_PDIR_AXR14 0x00004000 // AXR PDIR BIT 14 0 1 #define MCASP_PDIR_AXR13 0x00002000 // AXR PDIR BIT 13 0 1 #define MCASP_PDIR_AXR12 0x00001000 // AXR PDIR BIT 12 0 1 #define MCASP_PDIR_AXR11 0x00000800 // AXR PDIR BIT 11 0 1 #define MCASP_PDIR_AXR10 0x00000400 // AXR PDIR BIT 10 0 1 #define MCASP_PDIR_AXR9 0x00000200 // AXR PDIR BIT 9 0 1 #define MCASP_PDIR_AXR8 0x00000100 // AXR PDIR BIT 8 0 1 #define MCASP_PDIR_AXR7 0x00000080 // AXR PDIR BIT 7 0 1 #define MCASP_PDIR_AXR6 0x00000040 // AXR PDIR BIT 6 0 1 #define MCASP_PDIR_AXR5 0x00000020 // AXR PDIR BIT 5 0 1 #define MCASP_PDIR_AXR4 0x00000010 // AXR PDIR BIT 4 0 1 #define MCASP_PDIR_AXR3 0x00000008 // AXR PDIR BIT 3 0 1 #define MCASP_PDIR_AXR2 0x00000004 // AXR PDIR BIT 2 0 1 #define MCASP_PDIR_AXR1 0x00000002 // AXR PDIR BIT 1 0 1 #define MCASP_PDIR_AXR0 0x00000001 // AXR PDIR BIT 0 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_PDOUT register. // //****************************************************************************** #define MCASP_PDOUT_AFSR 0x80000000 // AFSR PDOUT 31 0 1 #define MCASP_PDOUT_AHCLKR 0x40000000 // AHCLKR PDOUT 30 0 1 #define MCASP_PDOUT_ACLKR 0x20000000 // ACLKR PDOUT 29 0 1 #define MCASP_PDOUT_AFSX 0x10000000 // AFSX PDOUT 28 0 1 #define MCASP_PDOUT_AHCLKX 0x08000000 // AHCLKX PDOUT 27 0 1 #define MCASP_PDOUT_ACLKX 0x04000000 // ACLKX PDOUT 26 0 1 #define MCASP_PDOUT_AMUTE 0x02000000 // AMUTE PDOUT 25 0 1 #define MCASP_PDOUT_RESV_M 0x01FF0000 // Reserved #define MCASP_PDOUT_RESV_S 16 #define MCASP_PDOUT_AXR15 0x00008000 // AXR PDOUT BIT 15 0 1 #define MCASP_PDOUT_AXR14 0x00004000 // AXR PDOUT BIT 14 0 1 #define MCASP_PDOUT_AXR13 0x00002000 // AXR PDOUT BIT 13 0 1 #define MCASP_PDOUT_AXR12 0x00001000 // AXR PDOUT BIT 12 0 1 #define MCASP_PDOUT_AXR11 0x00000800 // AXR PDOUT BIT 11 0 1 #define MCASP_PDOUT_AXR10 0x00000400 // AXR PDOUT BIT 10 0 1 #define MCASP_PDOUT_AXR9 0x00000200 // AXR PDOUT BIT 9 0 1 #define MCASP_PDOUT_AXR8 0x00000100 // AXR PDOUT BIT 8 0 1 #define MCASP_PDOUT_AXR7 0x00000080 // AXR PDOUT BIT 7 0 1 #define MCASP_PDOUT_AXR6 0x00000040 // AXR PDOUT BIT 6 0 1 #define MCASP_PDOUT_AXR5 0x00000020 // AXR PDOUT BIT 5 0 1 #define MCASP_PDOUT_AXR4 0x00000010 // AXR PDOUT BIT 4 0 1 #define MCASP_PDOUT_AXR3 0x00000008 // AXR PDOUT BIT 3 0 1 #define MCASP_PDOUT_AXR2 0x00000004 // AXR PDOUT BIT 2 0 1 #define MCASP_PDOUT_AXR1 0x00000002 // AXR PDOUT BIT 1 0 1 #define MCASP_PDOUT_AXR0 0x00000001 // AXR PDOUT BIT 0 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_PDSET register. // //****************************************************************************** #define MCASP_PDSET_AFSR 0x80000000 #define MCASP_PDSET_AHCLKR 0x40000000 #define MCASP_PDSET_ACLKR 0x20000000 #define MCASP_PDSET_AFSX 0x10000000 #define MCASP_PDSET_AHCLKX 0x08000000 #define MCASP_PDSET_ACLKX 0x04000000 #define MCASP_PDSET_AMUTE 0x02000000 #define MCASP_PDSET_RESV_M 0x01FF0000 // Reserved #define MCASP_PDSET_RESV_S 16 #define MCASP_PDSET_AXR15 0x00008000 #define MCASP_PDSET_AXR14 0x00004000 #define MCASP_PDSET_AXR13 0x00002000 #define MCASP_PDSET_AXR12 0x00001000 #define MCASP_PDSET_AXR11 0x00000800 #define MCASP_PDSET_AXR10 0x00000400 #define MCASP_PDSET_AXR9 0x00000200 #define MCASP_PDSET_AXR8 0x00000100 #define MCASP_PDSET_AXR7 0x00000080 #define MCASP_PDSET_AXR6 0x00000040 #define MCASP_PDSET_AXR5 0x00000020 #define MCASP_PDSET_AXR4 0x00000010 #define MCASP_PDSET_AXR3 0x00000008 #define MCASP_PDSET_AXR2 0x00000004 #define MCASP_PDSET_AXR1 0x00000002 #define MCASP_PDSET_AXR0 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_PDIN register. // //****************************************************************************** #define MCASP_PDIN_AFSR 0x80000000 #define MCASP_PDIN_AHCLKR 0x40000000 #define MCASP_PDIN_ACLKR 0x20000000 #define MCASP_PDIN_AFSX 0x10000000 #define MCASP_PDIN_AHCLKX 0x08000000 #define MCASP_PDIN_ACLKX 0x04000000 #define MCASP_PDIN_AMUTE 0x02000000 #define MCASP_PDIN_RESV_M 0x01FF0000 // Reserved #define MCASP_PDIN_RESV_S 16 #define MCASP_PDIN_AXR15 0x00008000 #define MCASP_PDIN_AXR14 0x00004000 #define MCASP_PDIN_AXR13 0x00002000 #define MCASP_PDIN_AXR12 0x00001000 #define MCASP_PDIN_AXR11 0x00000800 #define MCASP_PDIN_AXR10 0x00000400 #define MCASP_PDIN_AXR9 0x00000200 #define MCASP_PDIN_AXR8 0x00000100 #define MCASP_PDIN_AXR7 0x00000080 #define MCASP_PDIN_AXR6 0x00000040 #define MCASP_PDIN_AXR5 0x00000020 #define MCASP_PDIN_AXR4 0x00000010 #define MCASP_PDIN_AXR3 0x00000008 #define MCASP_PDIN_AXR2 0x00000004 #define MCASP_PDIN_AXR1 0x00000002 #define MCASP_PDIN_AXR0 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_PDCLR register. // //****************************************************************************** #define MCASP_PDCLR_AFSR 0x80000000 // AFSR PDCLR 31 0 1 #define MCASP_PDCLR_AHCLKR 0x40000000 // AHCLKR PDCLR 30 0 1 #define MCASP_PDCLR_ACLKR 0x20000000 // ACLKR PDCLR 29 0 1 #define MCASP_PDCLR_AFSX 0x10000000 // AFSX PDCLR 28 0 1 #define MCASP_PDCLR_AHCLKX 0x08000000 // AHCLKX PDCLR 27 0 1 #define MCASP_PDCLR_ACLKX 0x04000000 // ACLKX PDCLR 26 0 1 #define MCASP_PDCLR_AMUTE 0x02000000 // AMUTE PDCLR 25 0 1 #define MCASP_PDCLR_RESV_M 0x01FF0000 // Reserved #define MCASP_PDCLR_RESV_S 16 #define MCASP_PDCLR_AXR15 0x00008000 // AXR PDCLR BIT 15 0 1 #define MCASP_PDCLR_AXR14 0x00004000 // AXR PDCLR BIT 14 0 1 #define MCASP_PDCLR_AXR13 0x00002000 // AXR PDCLR BIT 13 0 1 #define MCASP_PDCLR_AXR12 0x00001000 // AXR PDCLR BIT 12 0 1 #define MCASP_PDCLR_AXR11 0x00000800 // AXR PDCLR BIT 11 0 1 #define MCASP_PDCLR_AXR10 0x00000400 // AXR PDCLR BIT 10 0 1 #define MCASP_PDCLR_AXR9 0x00000200 // AXR PDCLR BIT 9 0 1 #define MCASP_PDCLR_AXR8 0x00000100 // AXR PDCLR BIT 8 0 1 #define MCASP_PDCLR_AXR7 0x00000080 // AXR PDCLR BIT 7 0 1 #define MCASP_PDCLR_AXR6 0x00000040 // AXR PDCLR BIT 6 0 1 #define MCASP_PDCLR_AXR5 0x00000020 // AXR PDCLR BIT 5 0 1 #define MCASP_PDCLR_AXR4 0x00000010 // AXR PDCLR BIT 4 0 1 #define MCASP_PDCLR_AXR3 0x00000008 // AXR PDCLR BIT 3 0 1 #define MCASP_PDCLR_AXR2 0x00000004 // AXR PDCLR BIT 2 0 1 #define MCASP_PDCLR_AXR1 0x00000002 // AXR PDCLR BIT 1 0 1 #define MCASP_PDCLR_AXR0 0x00000001 // AXR PDCLR BIT 0 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TLGC register. // //****************************************************************************** #define MCASP_TLGC_RESV_M 0xFFFF0000 // Reserved #define MCASP_TLGC_RESV_S 16 #define MCASP_TLGC_MT_M 0x0000C000 // MISR on/off trigger command 0x0 // 0x1 0x2 0x3 #define MCASP_TLGC_MT_S 14 #define MCASP_TLGC_RESV1_M 0x00003E00 // Reserved #define MCASP_TLGC_RESV1_S 9 #define MCASP_TLGC_MMS 0x00000100 // Source of MISR input 0 1 #define MCASP_TLGC_ESEL 0x00000080 // Output enable select 0 1 #define MCASP_TLGC_TOEN 0x00000040 // Test output enable control. 0 1 #define MCASP_TLGC_MC_M 0x00000030 // States of MISR 0x0 0x1 0x2 0x3 #define MCASP_TLGC_MC_S 4 #define MCASP_TLGC_PC_M 0x0000000E // Pattern code 0x0 0x1 0x2 0x3 0x4 // 0x5 0x6 0x7 #define MCASP_TLGC_PC_S 1 #define MCASP_TLGC_TM 0x00000001 // Tie high; do not write to this // bit 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TLMR register. // //****************************************************************************** #define MCASP_TLMR_TLMR_M 0xFFFFFFFF // Contains test result signature. #define MCASP_TLMR_TLMR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TLEC register. // //****************************************************************************** #define MCASP_TLEC_TLEC_M 0xFFFFFFFF // Contains number of cycles during // which MISR sig will be // accumulated. #define MCASP_TLEC_TLEC_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_GBLCTL register. // //****************************************************************************** #define MCASP_GBLCTL_XFRST 0x00001000 // Frame sync generator reset 0 1 #define MCASP_GBLCTL_XSMRST 0x00000800 // XMT state machine reset 0 1 #define MCASP_GBLCTL_XSRCLR 0x00000400 // XMT serializer clear 0 1 #define MCASP_GBLCTL_XHCLKRST 0x00000200 // XMT High Freq. clk Divider 0 1 #define MCASP_GBLCTL_XCLKRST 0x00000100 // XMT clock divder reset 0 1 #define MCASP_GBLCTL_RFRST 0x00000010 // Frame sync generator reset 0 1 #define MCASP_GBLCTL_RSMRST 0x00000008 // RCV state machine reset 0 1 #define MCASP_GBLCTL_RSRCLR 0x00000004 // RCV serializer clear 0 1 #define MCASP_GBLCTL_RHCLKRST 0x00000002 // RCV High Freq. clk Divider 0 1 #define MCASP_GBLCTL_RCLKRST 0x00000001 // RCV clock divder reset 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_AMUTE register. // //****************************************************************************** #define MCASP_AMUTE_XDMAERR 0x00001000 // MUTETXDMAERR occur 0 1 #define MCASP_AMUTE_RDMAERR 0x00000800 // MUTERXDMAERR occur 0 1 #define MCASP_AMUTE_XCKFAIL 0x00000400 // XMT bad clock 0 1 #define MCASP_AMUTE_RCKFAIL 0x00000200 // RCV bad clock 0 1 #define MCASP_AMUTE_XSYNCERR 0x00000100 // XMT unexpected FS 0 1 #define MCASP_AMUTE_RSYNCERR 0x00000080 // RCV unexpected FS 0 1 #define MCASP_AMUTE_XUNDRN 0x00000040 // XMT underrun occurs 0 1 #define MCASP_AMUTE_ROVRN 0x00000020 // RCV overun occurs 0 1 #define MCASP_AMUTE_INSTAT 0x00000010 #define MCASP_AMUTE_INEN 0x00000008 // drive AMUTE active on mute in // active 0 1 #define MCASP_AMUTE_INPOL 0x00000004 // Mute input polarity 0 1 #define MCASP_AMUTE_MUTEN_M 0x00000003 // AMUTE pin enable 0x0 0x1 0x2 #define MCASP_AMUTE_MUTEN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_LBCTL register. // //****************************************************************************** #define MCASP_LBCTL_IOLBEN 0x00000010 // IO loopback enable 0 1 #define MCASP_LBCTL_MODE_M 0x0000000C // Loop back clock source generator // 0x0 0x1 0x2 0x3 #define MCASP_LBCTL_MODE_S 2 #define MCASP_LBCTL_ORD 0x00000002 // Loopback order 0 1 #define MCASP_LBCTL_DLBEN 0x00000001 // Loop back mode 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXDITCTL register. // //****************************************************************************** #define MCASP_TXDITCTL_VB 0x00000008 // Valib bit for odd TDM 0 1 #define MCASP_TXDITCTL_VA 0x00000004 // Valib bit for even TDM 0 1 #define MCASP_TXDITCTL_DITEN 0x00000001 // XMT DIT Mode Enable 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_GBLCTLR register. // //****************************************************************************** #define MCASP_GBLCTLR_XFRST 0x00001000 #define MCASP_GBLCTLR_XSMRST 0x00000800 #define MCASP_GBLCTLR_XSRCLR 0x00000400 #define MCASP_GBLCTLR_XHCLKRST 0x00000200 #define MCASP_GBLCTLR_XCLKRST 0x00000100 #define MCASP_GBLCTLR_RFRST 0x00000010 // Frame sync generator reset 0 1 #define MCASP_GBLCTLR_RSMRST 0x00000008 // RCV state machine reset 0 1 #define MCASP_GBLCTLR_RSRCLR 0x00000004 // RCV serializer clear 0 1 #define MCASP_GBLCTLR_RHCLKRST 0x00000002 // RCV High Freq. clk Divider 0 1 #define MCASP_GBLCTLR_RCLKRST 0x00000001 // RCV clock divder reset 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXMASK register. // //****************************************************************************** #define MCASP_RXMASK_RMASK31 0x80000000 // RMASK BIT 31 0 1 #define MCASP_RXMASK_RMASK30 0x40000000 // RMASK BIT 30 0 1 #define MCASP_RXMASK_RMASK29 0x20000000 // RMASK BIT 29 0 1 #define MCASP_RXMASK_RMASK28 0x10000000 // RMASK BIT 28 0 1 #define MCASP_RXMASK_RMASK27 0x08000000 // RMASK BIT 27 0 1 #define MCASP_RXMASK_RMASK26 0x04000000 // RMASK BIT 26 0 1 #define MCASP_RXMASK_RMASK25 0x02000000 // RMASK BIT 25 0 1 #define MCASP_RXMASK_RMASK24 0x01000000 // RMASK BIT 24 0 1 #define MCASP_RXMASK_RMASK23 0x00800000 // RMASK BIT 23 0 1 #define MCASP_RXMASK_RMASK22 0x00400000 // RMASK BIT 22 0 1 #define MCASP_RXMASK_RMASK21 0x00200000 // RMASK BIT 21 0 1 #define MCASP_RXMASK_RMASK20 0x00100000 // RMASK BIT 20 0 1 #define MCASP_RXMASK_RMASK19 0x00080000 // RMASK BIT 19 0 1 #define MCASP_RXMASK_RMASK18 0x00040000 // RMASK BIT 18 0 1 #define MCASP_RXMASK_RMASK17 0x00020000 // RMASK BIT 17 0 1 #define MCASP_RXMASK_RMASK16 0x00010000 // RMASK BIT 16 0 1 #define MCASP_RXMASK_RMASK15 0x00008000 // RMASK BIT 15 0 1 #define MCASP_RXMASK_RMASK14 0x00004000 // RMASK BIT 14 0 1 #define MCASP_RXMASK_RMASK13 0x00002000 // RMASK BIT 13 0 1 #define MCASP_RXMASK_RMASK12 0x00001000 // RMASK BIT 12 0 1 #define MCASP_RXMASK_RMASK11 0x00000800 // RMASK BIT 11 0 1 #define MCASP_RXMASK_RMASK10 0x00000400 // RMASK BIT 10 0 1 #define MCASP_RXMASK_RMASK9 0x00000200 // RMASK BIT 9 0 1 #define MCASP_RXMASK_RMASK8 0x00000100 // RMASK BIT 8 0 1 #define MCASP_RXMASK_RMASK7 0x00000080 // RMASK BIT 7 0 1 #define MCASP_RXMASK_RMASK6 0x00000040 // RMASK BIT 6 0 1 #define MCASP_RXMASK_RMASK5 0x00000020 // RMASK BIT 5 0 1 #define MCASP_RXMASK_RMASK4 0x00000010 // RMASK BIT 4 0 1 #define MCASP_RXMASK_RMASK3 0x00000008 // RMASK BIT 3 0 1 #define MCASP_RXMASK_RMASK2 0x00000004 // RMASK BIT 2 0 1 #define MCASP_RXMASK_RMASK1 0x00000002 // RMASK BIT 1 0 1 #define MCASP_RXMASK_RMASK0 0x00000001 // RMASK BIT 0 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXFMT register. // //****************************************************************************** #define MCASP_RXFMT_RDATDLY_M 0x00030000 // RCV Frame sync delay 0x0 0 Bit // delay 0x1 1 Bit delay 0x2 2 Bit // delay #define MCASP_RXFMT_RDATDLY_S 16 #define MCASP_RXFMT_RRVRS 0x00008000 // RCV serial stream bit order 0 1 #define MCASP_RXFMT_RPAD_M 0x00006000 // Pad value 0x0 0x1 0x2 #define MCASP_RXFMT_RPAD_S 13 #define MCASP_RXFMT_RPBIT_M 0x00001F00 // Pad bit position #define MCASP_RXFMT_RPBIT_S 8 #define MCASP_RXFMT_RSSZ_M 0x000000F0 // RCV slot Size 0x0 0x1 0x2 0x3 // 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB // 0xC 0xD 0xE 0xF #define MCASP_RXFMT_RSSZ_S 4 #define MCASP_RXFMT_RBUSEL 0x00000008 // Write to RBUF using CPU/DMA 0 // DMA port access 1 CPU port Access #define MCASP_RXFMT_RROT_M 0x00000007 // Right Rotate Value 0x0 0x1 0x2 // 0x3 0x4 0x5 0x6 0x7 #define MCASP_RXFMT_RROT_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXFMCTL register. // //****************************************************************************** #define MCASP_RXFMCTL_RMOD_M 0x0000FF80 // RCV Frame sync mode #define MCASP_RXFMCTL_RMOD_S 7 #define MCASP_RXFMCTL_FRWID 0x00000010 // RCV Frame sync Duration 0 1 #define MCASP_RXFMCTL_FSRM 0x00000002 // RCV frame sync External 0 1 #define MCASP_RXFMCTL_FSRP 0x00000001 // RCV Frame sync Polarity 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_ACLKRCTL register. // //****************************************************************************** #define MCASP_ACLKRCTL_BUSY 0x00100000 #define MCASP_ACLKRCTL_DIVBUSY 0x00080000 #define MCASP_ACLKRCTL_ADJBUSY 0x00040000 #define MCASP_ACLKRCTL_CLKRADJ_M \ 0x00030000 #define MCASP_ACLKRCTL_CLKRADJ_S 16 #define MCASP_ACLKRCTL_CLKRP 0x00000080 // RCV Clock Polarity 0 1 #define MCASP_ACLKRCTL_CLKRM 0x00000020 // RCV clock source 0 1 #define MCASP_ACLKRCTL_CLKRDIV_M \ 0x0000001F // RCV clock devide ratio #define MCASP_ACLKRCTL_CLKRDIV_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_AHCLKRCTL register. // //****************************************************************************** #define MCASP_AHCLKRCTL_BUSY 0x00100000 #define MCASP_AHCLKRCTL_DIVBUSY 0x00080000 #define MCASP_AHCLKRCTL_ADJBUSY 0x00040000 #define MCASP_AHCLKRCTL_HCLKRADJ_M \ 0x00030000 #define MCASP_AHCLKRCTL_HCLKRADJ_S 16 #define MCASP_AHCLKRCTL_HCLKRM 0x00008000 // High Freq. RCV clock Source 0 1 #define MCASP_AHCLKRCTL_HCLKRP 0x00004000 // High Freq. clock Polarity Before // diviser 0 1 #define MCASP_AHCLKRCTL_HCLKRDIV_M \ 0x00000FFF // RCV clock Divide Ratio #define MCASP_AHCLKRCTL_HCLKRDIV_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXTDM register. // //****************************************************************************** #define MCASP_RXTDM_RTDMS31 0x80000000 // RCV mode during TDM time slot 31 // 0 1 #define MCASP_RXTDM_RTDMS30 0x40000000 // RCV mode during TDM time slot 30 // 0 1 #define MCASP_RXTDM_RTDMS29 0x20000000 // RCV mode during TDM time slot 29 // 0 1 #define MCASP_RXTDM_RTDMS28 0x10000000 // RCV mode during TDM time slot 28 // 0 1 #define MCASP_RXTDM_RTDMS27 0x08000000 // RCV mode during TDM time slot 27 // 0 1 #define MCASP_RXTDM_RTDMS26 0x04000000 // RCV mode during TDM time slot 26 // 0 1 #define MCASP_RXTDM_RTDMS25 0x02000000 // RCV mode during TDM time slot 25 // 0 1 #define MCASP_RXTDM_RTDMS24 0x01000000 // RCV mode during TDM time slot 24 // 0 1 #define MCASP_RXTDM_RTDMS23 0x00800000 // RCV mode during TDM time slot 23 // 0 1 #define MCASP_RXTDM_RTDMS22 0x00400000 // RCV mode during TDM time slot 22 // 0 1 #define MCASP_RXTDM_RTDMS21 0x00200000 // RCV mode during TDM time slot 21 // 0 1 #define MCASP_RXTDM_RTDMS20 0x00100000 // RCV mode during TDM time slot 20 // 0 1 #define MCASP_RXTDM_RTDMS19 0x00080000 // RCV mode during TDM time slot 19 // 0 1 #define MCASP_RXTDM_RTDMS18 0x00040000 // RCV mode during TDM time slot 18 // 0 1 #define MCASP_RXTDM_RTDMS17 0x00020000 // RCV mode during TDM time slot 17 // 0 1 #define MCASP_RXTDM_RTDMS16 0x00010000 // RCV mode during TDM time slot 16 // 0 1 #define MCASP_RXTDM_RTDMS15 0x00008000 // RCV mode during TDM time slot 15 // 0 1 #define MCASP_RXTDM_RTDMS14 0x00004000 // RCV mode during TDM time slot 14 // 0 1 #define MCASP_RXTDM_RTDMS13 0x00002000 // RCV mode during TDM time slot 13 // 0 1 #define MCASP_RXTDM_RTDMS12 0x00001000 // RCV mode during TDM time slot 12 // 0 1 #define MCASP_RXTDM_RTDMS11 0x00000800 // RCV mode during TDM time slot 11 // 0 1 #define MCASP_RXTDM_RTDMS10 0x00000400 // RCV mode during TDM time slot 10 // 0 1 #define MCASP_RXTDM_RTDMS9 0x00000200 // RCV mode during TDM time slot 9 // 0 1 #define MCASP_RXTDM_RTDMS8 0x00000100 // RCV mode during TDM time slot 8 // 0 1 #define MCASP_RXTDM_RTDMS7 0x00000080 // RCV mode during TDM time slot 7 // 0 1 #define MCASP_RXTDM_RTDMS6 0x00000040 // RCV mode during TDM time slot 6 // 0 1 #define MCASP_RXTDM_RTDMS5 0x00000020 // RCV mode during TDM time slot 5 // 0 1 #define MCASP_RXTDM_RTDMS4 0x00000010 // RCV mode during TDM time slot 4 // 0 1 #define MCASP_RXTDM_RTDMS3 0x00000008 // RCV mode during TDM time slot 3 // 0 1 #define MCASP_RXTDM_RTDMS2 0x00000004 // RCV mode during TDM time slot 2 // 0 1 #define MCASP_RXTDM_RTDMS1 0x00000002 // RCV mode during TDM time slot 1 // 0 1 #define MCASP_RXTDM_RTDMS0 0x00000001 // RCV mode during TDM time slot 0 // 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_EVTCTLR register. // //****************************************************************************** #define MCASP_EVTCTLR_RSTAFRM 0x00000080 // RCV Start of Frame Interrupt 0 1 #define MCASP_EVTCTLR_RDATA 0x00000020 // RCV Data Interrupt 0 1 #define MCASP_EVTCTLR_RLAST 0x00000010 // RCV Last Slot Interrupt 0 1 #define MCASP_EVTCTLR_RDMAERR 0x00000008 // RCV DMA Bus Error 0 1 #define MCASP_EVTCTLR_RCKFAIL 0x00000004 // Bad Clock Interrupt 0 1 #define MCASP_EVTCTLR_RSYNCERR 0x00000002 // RCV Unexpected FSR Interrupt 0 1 #define MCASP_EVTCTLR_ROVRN 0x00000001 // RCV Underrun Flag 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXSTAT register. // //****************************************************************************** #define MCASP_RXSTAT_RERR 0x00000100 // RCV Error 0 1 #define MCASP_RXSTAT_RDMAERR 0x00000080 // RCV DMA bus error 0 1 #define MCASP_RXSTAT_RSTAFRM 0x00000040 // Start of Frame-RCV 0 1 #define MCASP_RXSTAT_RDATA 0x00000020 // Data Ready Flag 0 1 #define MCASP_RXSTAT_RLAST 0x00000010 // Last Slot Interrupt Flag 0 1 #define MCASP_RXSTAT_RTDMSLOT 0x00000008 // EvenOdd Slot 0 1 #define MCASP_RXSTAT_RCKFAIL 0x00000004 // Bad Transmit Flag 0 1 #define MCASP_RXSTAT_RSYNCERR 0x00000002 // Unexpected RCV Frame sync flag 0 // 1 #define MCASP_RXSTAT_ROVRN 0x00000001 // RCV Underrun Flag 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXTDMSLOT register. // //****************************************************************************** #define MCASP_RXTDMSLOT_RSLOTCNT_M \ 0x000003FF // Current RCV time slot count #define MCASP_RXTDMSLOT_RSLOTCNT_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXCLKCHK register. // //****************************************************************************** #define MCASP_RXCLKCHK_RCNT_M 0xFF000000 // RCV clock count value #define MCASP_RXCLKCHK_RCNT_S 24 #define MCASP_RXCLKCHK_RMAX_M 0x00FF0000 // RCV clock maximum boundary #define MCASP_RXCLKCHK_RMAX_S 16 #define MCASP_RXCLKCHK_RMIN_M 0x0000FF00 // RCV clock minimum boundary #define MCASP_RXCLKCHK_RMIN_S 8 #define MCASP_RXCLKCHK_RPS_M 0x0000000F // RCV clock check prescaler 0x0 // 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 #define MCASP_RXCLKCHK_RPS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_REVTCTL register. // //****************************************************************************** #define MCASP_REVTCTL_RDATDMA 0x00000001 // RCV data DMA request 0 Enable // DMA Transfer 1 Disable DMA // Transfer //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_GBLCTLX register. // //****************************************************************************** #define MCASP_GBLCTLX_XFRST 0x00001000 // Frame sync generator reset 0 1 #define MCASP_GBLCTLX_XSMRST 0x00000800 // XMT state machine reset 0 1 #define MCASP_GBLCTLX_XSRCLR 0x00000400 // XMT serializer clear 0 1 #define MCASP_GBLCTLX_XHCLKRST 0x00000200 // XMT High Freq. clk Divider 0 1 #define MCASP_GBLCTLX_XCLKRST 0x00000100 // XMT clock divder reset 0 1 #define MCASP_GBLCTLX_RFRST 0x00000010 #define MCASP_GBLCTLX_RSMRST 0x00000008 #define MCASP_GBLCTLX_RSRCLKR 0x00000004 #define MCASP_GBLCTLX_RHCLKRST 0x00000002 #define MCASP_GBLCTLX_RCLKRST 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXMASK register. // //****************************************************************************** #define MCASP_TXMASK_XMASK31 0x80000000 // XMASK BIT 31 0 1 #define MCASP_TXMASK_XMASK30 0x40000000 // XMASK BIT 30 0 1 #define MCASP_TXMASK_XMASK29 0x20000000 // XMASK BIT 29 0 1 #define MCASP_TXMASK_XMASK28 0x10000000 // XMASK BIT 28 0 1 #define MCASP_TXMASK_XMASK27 0x08000000 // XMASK BIT 27 0 1 #define MCASP_TXMASK_XMASK26 0x04000000 // XMASK BIT 26 0 1 #define MCASP_TXMASK_XMASK25 0x02000000 // XMASK BIT 25 0 1 #define MCASP_TXMASK_XMASK24 0x01000000 // XMASK BIT 24 0 1 #define MCASP_TXMASK_XMASK23 0x00800000 // XMASK BIT 23 0 1 #define MCASP_TXMASK_XMASK22 0x00400000 // XMASK BIT 22 0 1 #define MCASP_TXMASK_XMASK21 0x00200000 // XMASK BIT 21 0 1 #define MCASP_TXMASK_XMASK20 0x00100000 // XMASK BIT 20 0 1 #define MCASP_TXMASK_XMASK19 0x00080000 // XMASK BIT 19 0 1 #define MCASP_TXMASK_XMASK18 0x00040000 // XMASK BIT 18 0 1 #define MCASP_TXMASK_XMASK17 0x00020000 // XMASK BIT 17 0 1 #define MCASP_TXMASK_XMASK16 0x00010000 // XMASK BIT 16 0 1 #define MCASP_TXMASK_XMASK15 0x00008000 // XMASK BIT 15 0 1 #define MCASP_TXMASK_XMASK14 0x00004000 // XMASK BIT 14 0 1 #define MCASP_TXMASK_XMASK13 0x00002000 // XMASK BIT 13 0 1 #define MCASP_TXMASK_XMASK12 0x00001000 // XMASK BIT 12 0 1 #define MCASP_TXMASK_XMASK11 0x00000800 // XMASK BIT 11 0 1 #define MCASP_TXMASK_XMASK10 0x00000400 // XMASK BIT 10 0 1 #define MCASP_TXMASK_XMASK9 0x00000200 // XMASK BIT 9 0 1 #define MCASP_TXMASK_XMASK8 0x00000100 // XMASK BIT 8 0 1 #define MCASP_TXMASK_XMASK7 0x00000080 // XMASK BIT 7 0 1 #define MCASP_TXMASK_XMASK6 0x00000040 // XMASK BIT 6 0 1 #define MCASP_TXMASK_XMASK5 0x00000020 // XMASK BIT 5 0 1 #define MCASP_TXMASK_XMASK4 0x00000010 // XMASK BIT 4 0 1 #define MCASP_TXMASK_XMASK3 0x00000008 // XMASK BIT 3 0 1 #define MCASP_TXMASK_XMASK2 0x00000004 // XMASK BIT 2 0 1 #define MCASP_TXMASK_XMASK1 0x00000002 // XMASK BIT 1 0 1 #define MCASP_TXMASK_XMASK0 0x00000001 // XMASK BIT 0 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXFMT register. // //****************************************************************************** #define MCASP_TXFMT_XDATDLY_M 0x00030000 // XMT Frame sync delay 0x0 0 Bit // delay 0x1 1 Bit delay 0x2 2 Bit // delay #define MCASP_TXFMT_XDATDLY_S 16 #define MCASP_TXFMT_XRVRS 0x00008000 // XMT serial stream bit order 0 1 #define MCASP_TXFMT_XPAD_M 0x00006000 // Pad value 0x0 0x1 0x2 #define MCASP_TXFMT_XPAD_S 13 #define MCASP_TXFMT_XPBIT_M 0x00001F00 // Pad bit position #define MCASP_TXFMT_XPBIT_S 8 #define MCASP_TXFMT_XSSZ_M 0x000000F0 // XMT slot Size 0x0 0x1 0x2 0x3 // 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB // 0xC 0xD 0xE 0xF #define MCASP_TXFMT_XSSZ_S 4 #define MCASP_TXFMT_XBUSEL 0x00000008 // Write to XBUF using CPU/DMA 0 // DMA port access 1 CPU port Access #define MCASP_TXFMT_XROT_M 0x00000007 // Right Rotate Value 0x0 0x1 0x2 // 0x3 0x4 0x5 0x6 0x7 #define MCASP_TXFMT_XROT_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXFMCTL register. // //****************************************************************************** #define MCASP_TXFMCTL_XMOD_M 0x0000FF80 // XMT Frame sync mode #define MCASP_TXFMCTL_XMOD_S 7 #define MCASP_TXFMCTL_FXWID 0x00000010 // XMT Frame sync Duration 0 1 #define MCASP_TXFMCTL_FSXM 0x00000002 // XMT frame sync External 0 1 #define MCASP_TXFMCTL_FSXP 0x00000001 // XMT Frame sync Polarity 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_ACLKXCTL register. // //****************************************************************************** #define MCASP_ACLKXCTL_BUSY 0x00100000 #define MCASP_ACLKXCTL_DIVBUSY 0x00080000 #define MCASP_ACLKXCTL_ADJBUSY 0x00040000 #define MCASP_ACLKXCTL_CLKXADJ_M \ 0x00030000 #define MCASP_ACLKXCTL_CLKXADJ_S 16 #define MCASP_ACLKXCTL_CLKXP 0x00000080 // XMT Clock Polarity 0 1 #define MCASP_ACLKXCTL_ASYNC 0x00000040 // XMT/RCV operation sync /Async 0 // 1 #define MCASP_ACLKXCTL_CLKXM 0x00000020 // XMT clock source 0 1 #define MCASP_ACLKXCTL_CLKXDIV_M \ 0x0000001F // XMT clock devide ratio #define MCASP_ACLKXCTL_CLKXDIV_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_AHCLKXCTL register. // //****************************************************************************** #define MCASP_AHCLKXCTL_BUSY 0x00100000 #define MCASP_AHCLKXCTL_DIVBUSY 0x00080000 #define MCASP_AHCLKXCTL_ADJBUSY 0x00040000 #define MCASP_AHCLKXCTL_HCLKXADJ_M \ 0x00030000 #define MCASP_AHCLKXCTL_HCLKXADJ_S 16 #define MCASP_AHCLKXCTL_HCLKXM 0x00008000 // High Freq. XMT clock Source 0 1 #define MCASP_AHCLKXCTL_HCLKXP 0x00004000 // High Freq. clock Polarity Before // diviser 0 1 #define MCASP_AHCLKXCTL_HCLKXDIV_M \ 0x00000FFF // XMT clock Divide Ratio #define MCASP_AHCLKXCTL_HCLKXDIV_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXTDM register. // //****************************************************************************** #define MCASP_TXTDM_XTDMS31 0x80000000 // XMT mode during TDM time slot 31 // 0 1 #define MCASP_TXTDM_XTDMS30 0x40000000 // XMT mode during TDM time slot 30 // 0 1 #define MCASP_TXTDM_XTDMS29 0x20000000 // XMT mode during TDM time slot 29 // 0 1 #define MCASP_TXTDM_XTDMS28 0x10000000 // XMT mode during TDM time slot 28 // 0 1 #define MCASP_TXTDM_XTDMS27 0x08000000 // XMT mode during TDM time slot 27 // 0 1 #define MCASP_TXTDM_XTDMS26 0x04000000 // XMT mode during TDM time slot 26 // 0 1 #define MCASP_TXTDM_XTDMS25 0x02000000 // XMT mode during TDM time slot 25 // 0 1 #define MCASP_TXTDM_XTDMS24 0x01000000 // XMT mode during TDM time slot 24 // 0 1 #define MCASP_TXTDM_XTDMS23 0x00800000 // XMT mode during TDM time slot 23 // 0 1 #define MCASP_TXTDM_XTDMS22 0x00400000 // XMT mode during TDM time slot 22 // 0 1 #define MCASP_TXTDM_XTDMS21 0x00200000 // XMT mode during TDM time slot 21 // 0 1 #define MCASP_TXTDM_XTDMS20 0x00100000 // XMT mode during TDM time slot 20 // 0 1 #define MCASP_TXTDM_XTDMS19 0x00080000 // XMT mode during TDM time slot 19 // 0 1 #define MCASP_TXTDM_XTDMS18 0x00040000 // XMT mode during TDM time slot 18 // 0 1 #define MCASP_TXTDM_XTDMS17 0x00020000 // XMT mode during TDM time slot 17 // 0 1 #define MCASP_TXTDM_XTDMS16 0x00010000 // XMT mode during TDM time slot 16 // 0 1 #define MCASP_TXTDM_XTDMS15 0x00008000 // XMT mode during TDM time slot 15 // 0 1 #define MCASP_TXTDM_XTDMS14 0x00004000 // XMT mode during TDM time slot 14 // 0 1 #define MCASP_TXTDM_XTDMS13 0x00002000 // XMT mode during TDM time slot 13 // 0 1 #define MCASP_TXTDM_XTDMS12 0x00001000 // XMT mode during TDM time slot 12 // 0 1 #define MCASP_TXTDM_XTDMS11 0x00000800 // XMT mode during TDM time slot 11 // 0 1 #define MCASP_TXTDM_XTDMS10 0x00000400 // XMT mode during TDM time slot 10 // 0 1 #define MCASP_TXTDM_XTDMS9 0x00000200 // XMT mode during TDM time slot 9 // 0 1 #define MCASP_TXTDM_XTDMS8 0x00000100 // XMT mode during TDM time slot 8 // 0 1 #define MCASP_TXTDM_XTDMS7 0x00000080 // XMT mode during TDM time slot 7 // 0 1 #define MCASP_TXTDM_XTDMS6 0x00000040 // XMT mode during TDM time slot 6 // 0 1 #define MCASP_TXTDM_XTDMS5 0x00000020 // XMT mode during TDM time slot 5 // 0 1 #define MCASP_TXTDM_XTDMS4 0x00000010 // XMT mode during TDM time slot 4 // 0 1 #define MCASP_TXTDM_XTDMS3 0x00000008 // XMT mode during TDM time slot 3 // 0 1 #define MCASP_TXTDM_XTDMS2 0x00000004 // XMT mode during TDM time slot 2 // 0 1 #define MCASP_TXTDM_XTDMS1 0x00000002 // XMT mode during TDM time slot 1 // 0 1 #define MCASP_TXTDM_XTDMS0 0x00000001 // XMT mode during TDM time slot 0 // 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_EVTCTLX register. // //****************************************************************************** #define MCASP_EVTCTLX_XSTAFRM 0x00000080 // XMT Start of Frame Interrupt 0 1 #define MCASP_EVTCTLX_XDATA 0x00000020 // XMT Data Interrupt 0 1 #define MCASP_EVTCTLX_XLAST 0x00000010 // XMT Last Slot Interrupt 0 1 #define MCASP_EVTCTLX_XDMAERR 0x00000008 // XMT DMA Bus Error 0 1 #define MCASP_EVTCTLX_XCKFAIL 0x00000004 // Bad Clock Interrupt 0 1 #define MCASP_EVTCTLX_XSYNCERR 0x00000002 // XMT Unexpected FSR Interrupt 0 1 #define MCASP_EVTCTLX_XUNDRN 0x00000001 // XMT Underrun Interrupt 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXSTAT register. // //****************************************************************************** #define MCASP_TXSTAT_XERR 0x00000100 // XMT Error 0 1 #define MCASP_TXSTAT_XDMAERR 0x00000080 // XMT DMA bus error 0 1 #define MCASP_TXSTAT_XSTAFRM 0x00000040 // Start of Frame-XMT 0 1 #define MCASP_TXSTAT_XDATA 0x00000020 // Data Ready Flag 0 1 #define MCASP_TXSTAT_XLAST 0x00000010 // Last Slot Interrupt Flag 0 1 #define MCASP_TXSTAT_XTDMSLOT 0x00000008 // EvenOdd Slot 0 1 #define MCASP_TXSTAT_XCKFAIL 0x00000004 // Bad Transmit Flag 0 1 #define MCASP_TXSTAT_XSYNCERR 0x00000002 // Unexpected XMT Frame sync flag 0 // 1 #define MCASP_TXSTAT_XUNDRN 0x00000001 // XMT Underrun Flag 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXTDMSLOT register. // //****************************************************************************** #define MCASP_TXTDMSLOT_XSLOTCNT_M \ 0x000003FF // Current XMT time slot count // during reset the value of this // register is 0b0101111111 (0x17f) // and after reset 0 #define MCASP_TXTDMSLOT_XSLOTCNT_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXCLKCHK register. // //****************************************************************************** #define MCASP_TXCLKCHK_XCNT_M 0xFF000000 // XMT clock count value #define MCASP_TXCLKCHK_XCNT_S 24 #define MCASP_TXCLKCHK_XMAX_M 0x00FF0000 // XMT clock maximum boundary #define MCASP_TXCLKCHK_XMAX_S 16 #define MCASP_TXCLKCHK_XMIN_M 0x0000FF00 // XMT clock minimum boundary #define MCASP_TXCLKCHK_XMIN_S 8 #define MCASP_TXCLKCHK_RESV 0x00000080 // Reserved #define MCASP_TXCLKCHK_XPS_M 0x0000000F // XMT clock check prescaler 0x0 // 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 #define MCASP_TXCLKCHK_XPS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XEVTCTL register. // //****************************************************************************** #define MCASP_XEVTCTL_XDATDMA 0x00000001 // XMT data DMA request 0 Enable // DMA Transfer 1 Disable DMA // Transfer //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_CLKADJEN register. // //****************************************************************************** #define MCASP_CLKADJEN_ENABLE 0x00000001 // One-shot clock adjust enable 0 1 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRA0 register. // //****************************************************************************** #define MCASP_DITCSRA0_DITCSRA0_M \ 0xFFFFFFFF // Left (Even TDM slot ) Channel // status #define MCASP_DITCSRA0_DITCSRA0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRA1 register. // //****************************************************************************** #define MCASP_DITCSRA1_DITCSRA1_M \ 0xFFFFFFFF // Left (Even TDM slot ) Channel // status #define MCASP_DITCSRA1_DITCSRA1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRA2 register. // //****************************************************************************** #define MCASP_DITCSRA2_DITCSRA2_M \ 0xFFFFFFFF // Left (Even TDM slot ) Channel // status Register #define MCASP_DITCSRA2_DITCSRA2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRA3 register. // //****************************************************************************** #define MCASP_DITCSRA3_DITCSRA3_M \ 0xFFFFFFFF // Left (Even TDM slot ) Channel // status Register #define MCASP_DITCSRA3_DITCSRA3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRA4 register. // //****************************************************************************** #define MCASP_DITCSRA4_DITCSRA4_M \ 0xFFFFFFFF // Left (Even TDM slot ) Channel // status #define MCASP_DITCSRA4_DITCSRA4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRA5 register. // //****************************************************************************** #define MCASP_DITCSRA5_DITCSRA5_M \ 0xFFFFFFFF // Left (Even TDM slot ) Channel // status #define MCASP_DITCSRA5_DITCSRA5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRB0 register. // //****************************************************************************** #define MCASP_DITCSRB0_DITCSRB0_M \ 0xFFFFFFFF // Right (odd TDM slot ) Channel // status #define MCASP_DITCSRB0_DITCSRB0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRB1 register. // //****************************************************************************** #define MCASP_DITCSRB1_DITCSRB1_M \ 0xFFFFFFFF // Right (odd TDM slot ) Channel // status #define MCASP_DITCSRB1_DITCSRB1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRB2 register. // //****************************************************************************** #define MCASP_DITCSRB2_DITCSRB2_M \ 0xFFFFFFFF // Right (odd TDM slot ) Channel // status #define MCASP_DITCSRB2_DITCSRB2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRB3 register. // //****************************************************************************** #define MCASP_DITCSRB3_DITCSRB3_M \ 0xFFFFFFFF // Right (odd TDM slot ) Channel // status #define MCASP_DITCSRB3_DITCSRB3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRB4 register. // //****************************************************************************** #define MCASP_DITCSRB4_DITCSRB4_M \ 0xFFFFFFFF // Right (odd TDM slot ) Channel // status #define MCASP_DITCSRB4_DITCSRB4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITCSRB5 register. // //****************************************************************************** #define MCASP_DITCSRB5_DITCSRB5_M \ 0xFFFFFFFF // Right (odd TDM slot ) Channel // status #define MCASP_DITCSRB5_DITCSRB5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRA0 register. // //****************************************************************************** #define MCASP_DITUDRA0_DITUDRA0_M \ 0xFFFFFFFF // Left (Even TDM slot ) User Data #define MCASP_DITUDRA0_DITUDRA0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRA1 register. // //****************************************************************************** #define MCASP_DITUDRA1_DITUDRA1_M \ 0xFFFFFFFF // Left (Even TDM slot ) User Data #define MCASP_DITUDRA1_DITUDRA1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRA2 register. // //****************************************************************************** #define MCASP_DITUDRA2_DITUDRA2_M \ 0xFFFFFFFF // Left (Even TDM slot ) User Data #define MCASP_DITUDRA2_DITUDRA2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRA3 register. // //****************************************************************************** #define MCASP_DITUDRA3_DITUDRA3_M \ 0xFFFFFFFF // Left (Even TDM slot ) User Data #define MCASP_DITUDRA3_DITUDRA3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRA4 register. // //****************************************************************************** #define MCASP_DITUDRA4_DITUDRA4_M \ 0xFFFFFFFF // Left (Even TDM slot ) User Data #define MCASP_DITUDRA4_DITUDRA4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRA5 register. // //****************************************************************************** #define MCASP_DITUDRA5_DITUDRA5_M \ 0xFFFFFFFF // Left (Even TDM slot ) User Data #define MCASP_DITUDRA5_DITUDRA5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRB0 register. // //****************************************************************************** #define MCASP_DITUDRB0_DITUDRB0_M \ 0xFFFFFFFF // Right (odd TDM slot ) User Data #define MCASP_DITUDRB0_DITUDRB0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRB1 register. // //****************************************************************************** #define MCASP_DITUDRB1_DITUDRB1_M \ 0xFFFFFFFF // Right (odd TDM slot ) User Data #define MCASP_DITUDRB1_DITUDRB1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRB2 register. // //****************************************************************************** #define MCASP_DITUDRB2_DITUDRB2_M \ 0xFFFFFFFF // Right (odd TDM slot ) User Data #define MCASP_DITUDRB2_DITUDRB2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRB3 register. // //****************************************************************************** #define MCASP_DITUDRB3_DITUDRB3_M \ 0xFFFFFFFF // Right (odd TDM slot ) User Data #define MCASP_DITUDRB3_DITUDRB3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRB4 register. // //****************************************************************************** #define MCASP_DITUDRB4_DITUDRB4_M \ 0xFFFFFFFF // Right (odd TDM slot ) User Data #define MCASP_DITUDRB4_DITUDRB4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_DITUDRB5 register. // //****************************************************************************** #define MCASP_DITUDRB5_DITUDRB5_M \ 0xFFFFFFFF // Right (odd TDM slot ) User Data #define MCASP_DITUDRB5_DITUDRB5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL0 register. // //****************************************************************************** #define MCASP_XRSRCTL0_RRDY 0x00000020 #define MCASP_XRSRCTL0_XRDY 0x00000010 #define MCASP_XRSRCTL0_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL0_DISMOD_S 2 #define MCASP_XRSRCTL0_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL0_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL1 register. // //****************************************************************************** #define MCASP_XRSRCTL1_RRDY 0x00000020 #define MCASP_XRSRCTL1_XRDY 0x00000010 #define MCASP_XRSRCTL1_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL1_DISMOD_S 2 #define MCASP_XRSRCTL1_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL1_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL2 register. // //****************************************************************************** #define MCASP_XRSRCTL2_RRDY 0x00000020 #define MCASP_XRSRCTL2_XRDY 0x00000010 #define MCASP_XRSRCTL2_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL2_DISMOD_S 2 #define MCASP_XRSRCTL2_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL2_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL3 register. // //****************************************************************************** #define MCASP_XRSRCTL3_RRDY 0x00000020 #define MCASP_XRSRCTL3_XRDY 0x00000010 #define MCASP_XRSRCTL3_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL3_DISMOD_S 2 #define MCASP_XRSRCTL3_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL3_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL4 register. // //****************************************************************************** #define MCASP_XRSRCTL4_RRDY 0x00000020 #define MCASP_XRSRCTL4_XRDY 0x00000010 #define MCASP_XRSRCTL4_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL4_DISMOD_S 2 #define MCASP_XRSRCTL4_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL4_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL5 register. // //****************************************************************************** #define MCASP_XRSRCTL5_RRDY 0x00000020 #define MCASP_XRSRCTL5_XRDY 0x00000010 #define MCASP_XRSRCTL5_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL5_DISMOD_S 2 #define MCASP_XRSRCTL5_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL5_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL6 register. // //****************************************************************************** #define MCASP_XRSRCTL6_RRDY 0x00000020 #define MCASP_XRSRCTL6_XRDY 0x00000010 #define MCASP_XRSRCTL6_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL6_DISMOD_S 2 #define MCASP_XRSRCTL6_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL6_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL7 register. // //****************************************************************************** #define MCASP_XRSRCTL7_RRDY 0x00000020 #define MCASP_XRSRCTL7_XRDY 0x00000010 #define MCASP_XRSRCTL7_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL7_DISMOD_S 2 #define MCASP_XRSRCTL7_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL7_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL8 register. // //****************************************************************************** #define MCASP_XRSRCTL8_RRDY 0x00000020 #define MCASP_XRSRCTL8_XRDY 0x00000010 #define MCASP_XRSRCTL8_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL8_DISMOD_S 2 #define MCASP_XRSRCTL8_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL8_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL9 register. // //****************************************************************************** #define MCASP_XRSRCTL9_RRDY 0x00000020 #define MCASP_XRSRCTL9_XRDY 0x00000010 #define MCASP_XRSRCTL9_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL9_DISMOD_S 2 #define MCASP_XRSRCTL9_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL9_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL10 register. // //****************************************************************************** #define MCASP_XRSRCTL10_RRDY 0x00000020 #define MCASP_XRSRCTL10_XRDY 0x00000010 #define MCASP_XRSRCTL10_DISMOD_M \ 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL10_DISMOD_S 2 #define MCASP_XRSRCTL10_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL10_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL11 register. // //****************************************************************************** #define MCASP_XRSRCTL11_RRDY 0x00000020 #define MCASP_XRSRCTL11_XRDY 0x00000010 #define MCASP_XRSRCTL11_DISMOD_M \ 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL11_DISMOD_S 2 #define MCASP_XRSRCTL11_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL11_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL12 register. // //****************************************************************************** #define MCASP_XRSRCTL12_RRDY 0x00000020 #define MCASP_XRSRCTL12_XRDY 0x00000010 #define MCASP_XRSRCTL12_DISMOD_M \ 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL12_DISMOD_S 2 #define MCASP_XRSRCTL12_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL12_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL13 register. // //****************************************************************************** #define MCASP_XRSRCTL13_RRDY 0x00000020 #define MCASP_XRSRCTL13_XRDY 0x00000010 #define MCASP_XRSRCTL13_DISMOD_M \ 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL13_DISMOD_S 2 #define MCASP_XRSRCTL13_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL13_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL14 register. // //****************************************************************************** #define MCASP_XRSRCTL14_RRDY 0x00000020 #define MCASP_XRSRCTL14_XRDY 0x00000010 #define MCASP_XRSRCTL14_DISMOD_M \ 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL14_DISMOD_S 2 #define MCASP_XRSRCTL14_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL14_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_XRSRCTL15 register. // //****************************************************************************** #define MCASP_XRSRCTL15_RRDY 0x00000020 #define MCASP_XRSRCTL15_XRDY 0x00000010 #define MCASP_XRSRCTL15_DISMOD_M \ 0x0000000C // Serializer drive state 0x0 Tri // state 0x1 Reserved 0x2 Drive pin // low 0x3 Drive pin high #define MCASP_XRSRCTL15_DISMOD_S 2 #define MCASP_XRSRCTL15_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive // mode 0x1 Transmit mode 0x2 // Receive mode #define MCASP_XRSRCTL15_SRMOD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF0 register. // //****************************************************************************** #define MCASP_TXBUF0_XBUF0_M 0xFFFFFFFF // Transmit Buffer 0 #define MCASP_TXBUF0_XBUF0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF1 register. // //****************************************************************************** #define MCASP_TXBUF1_XBUF1_M 0xFFFFFFFF // Transmit Buffer 1 #define MCASP_TXBUF1_XBUF1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF2 register. // //****************************************************************************** #define MCASP_TXBUF2_XBUF2_M 0xFFFFFFFF // Transmit Buffer 2 #define MCASP_TXBUF2_XBUF2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF3 register. // //****************************************************************************** #define MCASP_TXBUF3_XBUF3_M 0xFFFFFFFF // Transmit Buffer 3 #define MCASP_TXBUF3_XBUF3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF4 register. // //****************************************************************************** #define MCASP_TXBUF4_XBUF4_M 0xFFFFFFFF // Transmit Buffer 4 #define MCASP_TXBUF4_XBUF4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF5 register. // //****************************************************************************** #define MCASP_TXBUF5_XBUF5_M 0xFFFFFFFF // Transmit Buffer 5 #define MCASP_TXBUF5_XBUF5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF6 register. // //****************************************************************************** #define MCASP_TXBUF6_XBUF6_M 0xFFFFFFFF // Transmit Buffer 6 #define MCASP_TXBUF6_XBUF6_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF7 register. // //****************************************************************************** #define MCASP_TXBUF7_XBUF7_M 0xFFFFFFFF // Transmit Buffer 7 #define MCASP_TXBUF7_XBUF7_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF8 register. // //****************************************************************************** #define MCASP_TXBUF8_XBUF8_M 0xFFFFFFFF // Transmit Buffer 8 #define MCASP_TXBUF8_XBUF8_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF9 register. // //****************************************************************************** #define MCASP_TXBUF9_XBUF9_M 0xFFFFFFFF // Transmit Buffer 9 #define MCASP_TXBUF9_XBUF9_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF10 register. // //****************************************************************************** #define MCASP_TXBUF10_XBUF10_M 0xFFFFFFFF // Transmit Buffer 10 #define MCASP_TXBUF10_XBUF10_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF11 register. // //****************************************************************************** #define MCASP_TXBUF11_XBUF11_M 0xFFFFFFFF // Transmit Buffer 11 #define MCASP_TXBUF11_XBUF11_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF12 register. // //****************************************************************************** #define MCASP_TXBUF12_XBUF12_M 0xFFFFFFFF // Transmit Buffer 12 #define MCASP_TXBUF12_XBUF12_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF13 register. // //****************************************************************************** #define MCASP_TXBUF13_XBUF13_M 0xFFFFFFFF // Transmit Buffer 13 #define MCASP_TXBUF13_XBUF13_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF14 register. // //****************************************************************************** #define MCASP_TXBUF14_XBUF14_M 0xFFFFFFFF // Transmit Buffer 14 #define MCASP_TXBUF14_XBUF14_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_TXBUF15 register. // //****************************************************************************** #define MCASP_TXBUF15_XBUF15_M 0xFFFFFFFF // Transmit Buffer 15 #define MCASP_TXBUF15_XBUF15_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF0 register. // //****************************************************************************** #define MCASP_RXBUF0_RBUF0_M 0xFFFFFFFF // Receive Buffer 0 #define MCASP_RXBUF0_RBUF0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF1 register. // //****************************************************************************** #define MCASP_RXBUF1_RBUF1_M 0xFFFFFFFF // Receive Buffer 1 #define MCASP_RXBUF1_RBUF1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF2 register. // //****************************************************************************** #define MCASP_RXBUF2_RBUF2_M 0xFFFFFFFF // Receive Buffer 2 #define MCASP_RXBUF2_RBUF2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF3 register. // //****************************************************************************** #define MCASP_RXBUF3_RBUF3_M 0xFFFFFFFF // Receive Buffer 3 #define MCASP_RXBUF3_RBUF3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF4 register. // //****************************************************************************** #define MCASP_RXBUF4_RBUF4_M 0xFFFFFFFF // Receive Buffer 4 #define MCASP_RXBUF4_RBUF4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF5 register. // //****************************************************************************** #define MCASP_RXBUF5_RBUF5_M 0xFFFFFFFF // Receive Buffer 5 #define MCASP_RXBUF5_RBUF5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF6 register. // //****************************************************************************** #define MCASP_RXBUF6_RBUF6_M 0xFFFFFFFF // Receive Buffer 6 #define MCASP_RXBUF6_RBUF6_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF7 register. // //****************************************************************************** #define MCASP_RXBUF7_RBUF7_M 0xFFFFFFFF // Receive Buffer 7 #define MCASP_RXBUF7_RBUF7_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF8 register. // //****************************************************************************** #define MCASP_RXBUF8_RBUF8_M 0xFFFFFFFF // Receive Buffer 8 #define MCASP_RXBUF8_RBUF8_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF9 register. // //****************************************************************************** #define MCASP_RXBUF9_RBUF9_M 0xFFFFFFFF // Receive Buffer 9 #define MCASP_RXBUF9_RBUF9_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF10 register. // //****************************************************************************** #define MCASP_RXBUF10_RBUF10_M 0xFFFFFFFF // Receive Buffer 10 #define MCASP_RXBUF10_RBUF10_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF11 register. // //****************************************************************************** #define MCASP_RXBUF11_RBUF11_M 0xFFFFFFFF // Receive Buffer 11 #define MCASP_RXBUF11_RBUF11_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF12 register. // //****************************************************************************** #define MCASP_RXBUF12_RBUF12_M 0xFFFFFFFF // Receive Buffer 12 #define MCASP_RXBUF12_RBUF12_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF13 register. // //****************************************************************************** #define MCASP_RXBUF13_RBUF13_M 0xFFFFFFFF // Receive Buffer 13 #define MCASP_RXBUF13_RBUF13_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF14 register. // //****************************************************************************** #define MCASP_RXBUF14_RBUF14_M 0xFFFFFFFF // Receive Buffer 14 #define MCASP_RXBUF14_RBUF14_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCASP_O_RXBUF15 register. // //****************************************************************************** #define MCASP_RXBUF15_RBUF15_M 0xFFFFFFFF // Receive Buffer 15 #define MCASP_RXBUF15_RBUF15_S 0 #endif // __HW_MCASP_H__ micropython-1.12/ports/cc3200/hal/inc/hw_mcspi.h000066400000000000000000003476111357706137100213760ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_MCSPI_H__ #define __HW_MCSPI_H__ //***************************************************************************** // // The following are defines for the MCSPI register offsets. // //***************************************************************************** #define MCSPI_O_HL_REV 0x00000000 // IP Revision Identifier (X.Y.R) // Used by software to track // features bugs and compatibility #define MCSPI_O_HL_HWINFO 0x00000004 // Information about the IP // module's hardware configuration // i.e. typically the module's HDL // generics (if any). Actual field // format and encoding is up to the // module's designer to decide. #define MCSPI_O_HL_SYSCONFIG 0x00000010 // 0x4402 1010 0x4402 2010 Clock // management configuration #define MCSPI_O_REVISION 0x00000100 // 0x4402 1100 0x4402 2100 This // register contains the hard coded // RTL revision number. #define MCSPI_O_SYSCONFIG 0x00000110 // 0x4402 1110 0x4402 2110 This // register allows controlling // various parameters of the OCP // interface. #define MCSPI_O_SYSSTATUS 0x00000114 // 0x4402 1114 0x4402 2114 This // register provides status // information about the module // excluding the interrupt status // information #define MCSPI_O_IRQSTATUS 0x00000118 // 0x4402 1118 0x4402 2118 The // interrupt status regroups all the // status of the module internal // events that can generate an // interrupt #define MCSPI_O_IRQENABLE 0x0000011C // 0x4402 111C 0x4402 211C This // register allows to enable/disable // the module internal sources of // interrupt on an event-by-event // basis. #define MCSPI_O_WAKEUPENABLE 0x00000120 // 0x4402 1120 0x4402 2120 The // wakeup enable register allows to // enable/disable the module // internal sources of wakeup on // event-by-event basis. #define MCSPI_O_SYST 0x00000124 // 0x4402 1124 0x4402 2124 This // register is used to check the // correctness of the system // interconnect either internally to // peripheral bus or externally to // device IO pads when the module is // configured in system test // (SYSTEST) mode. #define MCSPI_O_MODULCTRL 0x00000128 // 0x4402 1128 0x4402 2128 This // register is dedicated to the // configuration of the serial port // interface. #define MCSPI_O_CH0CONF 0x0000012C // 0x4402 112C 0x4402 212C This // register is dedicated to the // configuration of the channel 0 #define MCSPI_O_CH0STAT 0x00000130 // 0x4402 1130 0x4402 2130 This // register provides status // information about transmitter and // receiver registers of channel 0 #define MCSPI_O_CH0CTRL 0x00000134 // 0x4402 1134 0x4402 2134 This // register is dedicated to enable // the channel 0 #define MCSPI_O_TX0 0x00000138 // 0x4402 1138 0x4402 2138 This // register contains a single SPI // word to transmit on the serial // link what ever SPI word length // is. #define MCSPI_O_RX0 0x0000013C // 0x4402 113C 0x4402 213C This // register contains a single SPI // word received through the serial // link what ever SPI word length // is. #define MCSPI_O_CH1CONF 0x00000140 // 0x4402 1140 0x4402 2140 This // register is dedicated to the // configuration of the channel. #define MCSPI_O_CH1STAT 0x00000144 // 0x4402 1144 0x4402 2144 This // register provides status // information about transmitter and // receiver registers of channel 1 #define MCSPI_O_CH1CTRL 0x00000148 // 0x4402 1148 0x4402 2148 This // register is dedicated to enable // the channel 1 #define MCSPI_O_TX1 0x0000014C // 0x4402 114C 0x4402 214C This // register contains a single SPI // word to transmit on the serial // link what ever SPI word length // is. #define MCSPI_O_RX1 0x00000150 // 0x4402 1150 0x4402 2150 This // register contains a single SPI // word received through the serial // link what ever SPI word length // is. #define MCSPI_O_CH2CONF 0x00000154 // 0x4402 1154 0x4402 2154 This // register is dedicated to the // configuration of the channel 2 #define MCSPI_O_CH2STAT 0x00000158 // 0x4402 1158 0x4402 2158 This // register provides status // information about transmitter and // receiver registers of channel 2 #define MCSPI_O_CH2CTRL 0x0000015C // 0x4402 115C 0x4402 215C This // register is dedicated to enable // the channel 2 #define MCSPI_O_TX2 0x00000160 // 0x4402 1160 0x4402 2160 This // register contains a single SPI // word to transmit on the serial // link what ever SPI word length // is. #define MCSPI_O_RX2 0x00000164 // 0x4402 1164 0x4402 2164 This // register contains a single SPI // word received through the serial // link what ever SPI word length // is. #define MCSPI_O_CH3CONF 0x00000168 // 0x4402 1168 0x4402 2168 This // register is dedicated to the // configuration of the channel 3 #define MCSPI_O_CH3STAT 0x0000016C // 0x4402 116C 0x4402 216C This // register provides status // information about transmitter and // receiver registers of channel 3 #define MCSPI_O_CH3CTRL 0x00000170 // 0x4402 1170 0x4402 2170 This // register is dedicated to enable // the channel 3 #define MCSPI_O_TX3 0x00000174 // 0x4402 1174 0x4402 2174 This // register contains a single SPI // word to transmit on the serial // link what ever SPI word length // is. #define MCSPI_O_RX3 0x00000178 // 0x4402 1178 0x4402 2178 This // register contains a single SPI // word received through the serial // link what ever SPI word length // is. #define MCSPI_O_XFERLEVEL 0x0000017C // 0x4402 117C 0x4402 217C This // register provides transfer levels // needed while using FIFO buffer // during transfer. #define MCSPI_O_DAFTX 0x00000180 // 0x4402 1180 0x4402 2180 This // register contains the SPI words // to transmit on the serial link // when FIFO used and DMA address is // aligned on 256 bit.This register // is an image of one of MCSPI_TX(i) // register corresponding to the // channel which have its FIFO // enabled. #define MCSPI_O_DAFRX 0x000001A0 // 0x4402 11A0 0x4402 21A0 This // register contains the SPI words // to received on the serial link // when FIFO used and DMA address is // aligned on 256 bit.This register // is an image of one of MCSPI_RX(i) // register corresponding to the // channel which have its FIFO // enabled. //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_HL_REV register. // //****************************************************************************** #define MCSPI_HL_REV_SCHEME_M 0xC0000000 #define MCSPI_HL_REV_SCHEME_S 30 #define MCSPI_HL_REV_RSVD_M 0x30000000 // Reserved These bits are // initialized to zero and writes to // them are ignored. #define MCSPI_HL_REV_RSVD_S 28 #define MCSPI_HL_REV_FUNC_M 0x0FFF0000 // Function indicates a software // compatible module family. If // there is no level of software // compatibility a new Func number // (and hence REVISION) should be // assigned. #define MCSPI_HL_REV_FUNC_S 16 #define MCSPI_HL_REV_R_RTL_M 0x0000F800 // RTL Version (R) maintained by IP // design owner. RTL follows a // numbering such as X.Y.R.Z which // are explained in this table. R // changes ONLY when: (1) PDS // uploads occur which may have been // due to spec changes (2) Bug fixes // occur (3) Resets to '0' when X or // Y changes. Design team has an // internal 'Z' (customer invisible) // number which increments on every // drop that happens due to DV and // RTL updates. Z resets to 0 when R // increments. #define MCSPI_HL_REV_R_RTL_S 11 #define MCSPI_HL_REV_X_MAJOR_M 0x00000700 // Major Revision (X) maintained by // IP specification owner. X changes // ONLY when: (1) There is a major // feature addition. An example // would be adding Master Mode to // Utopia Level2. The Func field (or // Class/Type in old PID format) // will remain the same. X does NOT // change due to: (1) Bug fixes (2) // Change in feature parameters. #define MCSPI_HL_REV_X_MAJOR_S 8 #define MCSPI_HL_REV_CUSTOM_M 0x000000C0 #define MCSPI_HL_REV_CUSTOM_S 6 #define MCSPI_HL_REV_Y_MINOR_M 0x0000003F // Minor Revision (Y) maintained by // IP specification owner. Y changes // ONLY when: (1) Features are // scaled (up or down). Flexibility // exists in that this feature // scalability may either be // represented in the Y change or a // specific register in the IP that // indicates which features are // exactly available. (2) When // feature creeps from Is-Not list // to Is list. But this may not be // the case once it sees silicon; in // which case X will change. Y does // NOT change due to: (1) Bug fixes // (2) Typos or clarifications (3) // major functional/feature // change/addition/deletion. Instead // these changes may be reflected // via R S X as applicable. Spec // owner maintains a // customer-invisible number 'S' // which changes due to: (1) // Typos/clarifications (2) Bug // documentation. Note that this bug // is not due to a spec change but // due to implementation. // Nevertheless the spec tracks the // IP bugs. An RTL release (say for // silicon PG1.1) that occurs due to // bug fix should document the // corresponding spec number (X.Y.S) // in its release notes. #define MCSPI_HL_REV_Y_MINOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_HL_HWINFO register. // //****************************************************************************** #define MCSPI_HL_HWINFO_RETMODE 0x00000040 #define MCSPI_HL_HWINFO_FFNBYTE_M \ 0x0000003E #define MCSPI_HL_HWINFO_FFNBYTE_S 1 #define MCSPI_HL_HWINFO_USEFIFO 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // MCSPI_O_HL_SYSCONFIG register. // //****************************************************************************** #define MCSPI_HL_SYSCONFIG_IDLEMODE_M \ 0x0000000C // Configuration of the local // target state management mode. By // definition target can handle // read/write transaction as long as // it is out of IDLE state. 0x0 // Force-idle mode: local target's // idle state follows (acknowledges) // the system's idle requests // unconditionally i.e. regardless // of the IP module's internal // requirements.Backup mode for // debug only. 0x1 No-idle mode: // local target never enters idle // state.Backup mode for debug only. // 0x2 Smart-idle mode: local // target's idle state eventually // follows (acknowledges) the // system's idle requests depending // on the IP module's internal // requirements.IP module shall not // generate (IRQ- or // DMA-request-related) wakeup // events. 0x3 "Smart-idle // wakeup-capable mode: local // target's idle state eventually // follows (acknowledges) the // system's idle requests depending // on the IP module's internal // requirements.IP module may // generate (IRQ- or // DMA-request-related) wakeup // events when in idle state.Mode is // only relevant if the appropriate // IP module ""swakeup"" output(s) // is (are) implemented." #define MCSPI_HL_SYSCONFIG_IDLEMODE_S 2 #define MCSPI_HL_SYSCONFIG_FREEEMU \ 0x00000002 // Sensitivity to emulation (debug) // suspend input signal. 0 IP module // is sensitive to emulation suspend // 1 IP module is not sensitive to // emulation suspend #define MCSPI_HL_SYSCONFIG_SOFTRESET \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_REVISION register. // //****************************************************************************** #define MCSPI_REVISION_REV_M 0x000000FF // IP revision [7:4] Major revision // [3:0] Minor revision Examples: // 0x10 for 1.0 0x21 for 2.1 #define MCSPI_REVISION_REV_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_SYSCONFIG register. // //****************************************************************************** #define MCSPI_SYSCONFIG_CLOCKACTIVITY_M \ 0x00000300 // Clocks activity during wake up // mode period 0x0 OCP and // Functional clocks may be switched // off. 0x1 OCP clock is maintained. // Functional clock may be // switched-off. 0x2 Functional // clock is maintained. OCP clock // may be switched-off. 0x3 OCP and // Functional clocks are maintained. #define MCSPI_SYSCONFIG_CLOCKACTIVITY_S 8 #define MCSPI_SYSCONFIG_SIDLEMODE_M \ 0x00000018 // Power management 0x0 If an idle // request is detected the McSPI // acknowledges it unconditionally // and goes in Inactive mode. // Interrupt DMA requests and wake // up lines are unconditionally // de-asserted and the module wakeup // capability is deactivated even if // the bit // MCSPI_SYSCONFIG[EnaWakeUp] is // set. 0x1 If an idle request is // detected the request is ignored // and the module does not switch to // wake up mode and keeps on // behaving normally. 0x2 If an idle // request is detected the module // will switch to idle mode based on // its internal activity. The wake // up capability cannot be used. 0x3 // If an idle request is detected // the module will switch to idle // mode based on its internal // activity and the wake up // capability can be used if the bit // MCSPI_SYSCONFIG[EnaWakeUp] is // set. #define MCSPI_SYSCONFIG_SIDLEMODE_S 3 #define MCSPI_SYSCONFIG_ENAWAKEUP \ 0x00000004 // WakeUp feature control 0 WakeUp // capability is disabled 1 WakeUp // capability is enabled #define MCSPI_SYSCONFIG_SOFTRESET \ 0x00000002 // Software reset. During reads it // always returns 0. 0 (write) // Normal mode 1 (write) Set this // bit to 1 to trigger a module // reset.The bit is automatically // reset by the hardware. #define MCSPI_SYSCONFIG_AUTOIDLE \ 0x00000001 // Internal OCP Clock gating // strategy 0 OCP clock is // free-running 1 Automatic OCP // clock gating strategy is applied // based on the OCP interface // activity //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_SYSSTATUS register. // //****************************************************************************** #define MCSPI_SYSSTATUS_RESETDONE \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_IRQSTATUS register. // //****************************************************************************** #define MCSPI_IRQSTATUS_EOW 0x00020000 #define MCSPI_IRQSTATUS_WKS 0x00010000 #define MCSPI_IRQSTATUS_RX3_FULL \ 0x00004000 #define MCSPI_IRQSTATUS_TX3_UNDERFLOW \ 0x00002000 #define MCSPI_IRQSTATUS_TX3_EMPTY \ 0x00001000 #define MCSPI_IRQSTATUS_RX2_FULL \ 0x00000400 #define MCSPI_IRQSTATUS_TX2_UNDERFLOW \ 0x00000200 #define MCSPI_IRQSTATUS_TX2_EMPTY \ 0x00000100 #define MCSPI_IRQSTATUS_RX1_FULL \ 0x00000040 #define MCSPI_IRQSTATUS_TX1_UNDERFLOW \ 0x00000020 #define MCSPI_IRQSTATUS_TX1_EMPTY \ 0x00000010 #define MCSPI_IRQSTATUS_RX0_OVERFLOW \ 0x00000008 #define MCSPI_IRQSTATUS_RX0_FULL \ 0x00000004 #define MCSPI_IRQSTATUS_TX0_UNDERFLOW \ 0x00000002 #define MCSPI_IRQSTATUS_TX0_EMPTY \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_IRQENABLE register. // //****************************************************************************** #define MCSPI_IRQENABLE_EOW_ENABLE \ 0x00020000 // End of Word count Interrupt // Enable. 0 Interrupt disabled 1 // Interrupt enabled #define MCSPI_IRQENABLE_WKE 0x00010000 // Wake Up event interrupt Enable // in slave mode when an active // control signal is detected on the // SPIEN line programmed in the // field MCSPI_CH0CONF[SPIENSLV] 0 // Interrupt disabled 1 Interrupt // enabled #define MCSPI_IRQENABLE_RX3_FULL_ENABLE \ 0x00004000 // Receiver register Full Interrupt // Enable. Ch 3 0 Interrupt disabled // 1 Interrupt enabled #define MCSPI_IRQENABLE_TX3_UNDERFLOW_ENABLE \ 0x00002000 // Transmitter register Underflow // Interrupt Enable. Ch 3 0 // Interrupt disabled 1 Interrupt // enabled #define MCSPI_IRQENABLE_TX3_EMPTY_ENABLE \ 0x00001000 // Transmitter register Empty // Interrupt Enable. Ch3 0 Interrupt // disabled 1 Interrupt enabled #define MCSPI_IRQENABLE_RX2_FULL_ENABLE \ 0x00000400 // Receiver register Full Interrupt // Enable. Ch 2 0 Interrupt disabled // 1 Interrupt enabled #define MCSPI_IRQENABLE_TX2_UNDERFLOW_ENABLE \ 0x00000200 // Transmitter register Underflow // Interrupt Enable. Ch 2 0 // Interrupt disabled 1 Interrupt // enabled #define MCSPI_IRQENABLE_TX2_EMPTY_ENABLE \ 0x00000100 // Transmitter register Empty // Interrupt Enable. Ch 2 0 // Interrupt disabled 1 Interrupt // enabled #define MCSPI_IRQENABLE_RX1_FULL_ENABLE \ 0x00000040 // Receiver register Full Interrupt // Enable. Ch 1 0 Interrupt disabled // 1 Interrupt enabled #define MCSPI_IRQENABLE_TX1_UNDERFLOW_ENABLE \ 0x00000020 // Transmitter register Underflow // Interrupt Enable. Ch 1 0 // Interrupt disabled 1 Interrupt // enabled #define MCSPI_IRQENABLE_TX1_EMPTY_ENABLE \ 0x00000010 // Transmitter register Empty // Interrupt Enable. Ch 1 0 // Interrupt disabled 1 Interrupt // enabled #define MCSPI_IRQENABLE_RX0_OVERFLOW_ENABLE \ 0x00000008 // Receiver register Overflow // Interrupt Enable. Ch 0 0 // Interrupt disabled 1 Interrupt // enabled #define MCSPI_IRQENABLE_RX0_FULL_ENABLE \ 0x00000004 // Receiver register Full Interrupt // Enable. Ch 0 0 Interrupt disabled // 1 Interrupt enabled #define MCSPI_IRQENABLE_TX0_UNDERFLOW_ENABLE \ 0x00000002 // Transmitter register Underflow // Interrupt Enable. Ch 0 0 // Interrupt disabled 1 Interrupt // enabled #define MCSPI_IRQENABLE_TX0_EMPTY_ENABLE \ 0x00000001 // Transmitter register Empty // Interrupt Enable. Ch 0 0 // Interrupt disabled 1 Interrupt // enabled //****************************************************************************** // // The following are defines for the bit fields in the // MCSPI_O_WAKEUPENABLE register. // //****************************************************************************** #define MCSPI_WAKEUPENABLE_WKEN 0x00000001 // WakeUp functionality in slave // mode when an active control // signal is detected on the SPIEN // line programmed in the field // MCSPI_CH0CONF[SPIENSLV] 0 The // event is not allowed to wakeup // the system even if the global // control bit // MCSPI_SYSCONF[EnaWakeUp] is set. // 1 The event is allowed to wakeup // the system if the global control // bit MCSPI_SYSCONF[EnaWakeUp] is // set. //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_SYST register. // //****************************************************************************** #define MCSPI_SYST_SSB 0x00000800 // Set status bit 0 No action. // Writing 0 does not clear already // set status bits; This bit must be // cleared prior attempting to clear // a status bit of the // register. 1 // Force to 1 all status bits of // MCSPI_IRQSTATUS register. Writing // 1 into this bit sets to 1 all // status bits contained in the // register. #define MCSPI_SYST_SPIENDIR 0x00000400 // Set the direction of the // SPIEN[3:0] lines and SPICLK line // 0 output (as in master mode) 1 // input (as in slave mode) #define MCSPI_SYST_SPIDATDIR1 0x00000200 // Set the direction of the // SPIDAT[1] 0 output 1 input #define MCSPI_SYST_SPIDATDIR0 0x00000100 // Set the direction of the // SPIDAT[0] 0 output 1 input #define MCSPI_SYST_WAKD 0x00000080 // SWAKEUP output (signal data // value of internal signal to // system). The signal is driven // high or low according to the // value written into this register // bit. 0 The pin is driven low. 1 // The pin is driven high. #define MCSPI_SYST_SPICLK 0x00000040 // SPICLK line (signal data value) // If MCSPI_SYST[SPIENDIR] = 1 // (input mode direction) this bit // returns the value on the CLKSPI // line (high or low) and a write // into this bit has no effect. If // MCSPI_SYST[SPIENDIR] = 0 (output // mode direction) the CLKSPI line // is driven high or low according // to the value written into this // register. #define MCSPI_SYST_SPIDAT_1 0x00000020 // SPIDAT[1] line (signal data // value) If MCSPI_SYST[SPIDATDIR1] // = 0 (output mode direction) the // SPIDAT[1] line is driven high or // low according to the value // written into this register. If // MCSPI_SYST[SPIDATDIR1] = 1 (input // mode direction) this bit returns // the value on the SPIDAT[1] line // (high or low) and a write into // this bit has no effect. #define MCSPI_SYST_SPIDAT_0 0x00000010 // SPIDAT[0] line (signal data // value) If MCSPI_SYST[SPIDATDIR0] // = 0 (output mode direction) the // SPIDAT[0] line is driven high or // low according to the value // written into this register. If // MCSPI_SYST[SPIDATDIR0] = 1 (input // mode direction) this bit returns // the value on the SPIDAT[0] line // (high or low) and a write into // this bit has no effect. #define MCSPI_SYST_SPIEN_3 0x00000008 // SPIEN[3] line (signal data // value) If MCSPI_SYST[SPIENDIR] = // 0 (output mode direction) the // SPIENT[3] line is driven high or // low according to the value // written into this register. If // MCSPI_SYST[SPIENDIR] = 1 (input // mode direction) this bit returns // the value on the SPIEN[3] line // (high or low) and a write into // this bit has no effect. #define MCSPI_SYST_SPIEN_2 0x00000004 // SPIEN[2] line (signal data // value) If MCSPI_SYST[SPIENDIR] = // 0 (output mode direction) the // SPIENT[2] line is driven high or // low according to the value // written into this register. If // MCSPI_SYST[SPIENDIR] = 1 (input // mode direction) this bit returns // the value on the SPIEN[2] line // (high or low) and a write into // this bit has no effect. #define MCSPI_SYST_SPIEN_1 0x00000002 // SPIEN[1] line (signal data // value) If MCSPI_SYST[SPIENDIR] = // 0 (output mode direction) the // SPIENT[1] line is driven high or // low according to the value // written into this register. If // MCSPI_SYST[SPIENDIR] = 1 (input // mode direction) this bit returns // the value on the SPIEN[1] line // (high or low) and a write into // this bit has no effect. #define MCSPI_SYST_SPIEN_0 0x00000001 // SPIEN[0] line (signal data // value) If MCSPI_SYST[SPIENDIR] = // 0 (output mode direction) the // SPIENT[0] line is driven high or // low according to the value // written into this register. If // MCSPI_SYST[SPIENDIR] = 1 (input // mode direction) this bit returns // the value on the SPIEN[0] line // (high or low) and a write into // this bit has no effect. //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_MODULCTRL register. // //****************************************************************************** #define MCSPI_MODULCTRL_FDAA 0x00000100 // FIFO DMA Address 256-bit aligned // This register is used when a FIFO // is managed by the module and DMA // connected to the controller // provides only 256 bit aligned // address. If this bit is set the // enabled channel which uses the // FIFO has its datas managed // through MCSPI_DAFTX and // MCSPI_DAFRX registers instead of // MCSPI_TX(i) and MCSPI_RX(i) // registers. 0 FIFO data managed by // MCSPI_TX(i) and MCSPI_RX(i) // registers. 1 FIFO data managed by // MCSPI_DAFTX and MCSPI_DAFRX // registers. #define MCSPI_MODULCTRL_MOA 0x00000080 // Multiple word ocp access: This // register can only be used when a // channel is enabled using a FIFO. // It allows the system to perform // multiple SPI word access for a // single 32-bit OCP word access. // This is possible for WL < 16. 0 // Multiple word access disabled 1 // Multiple word access enabled with // FIFO #define MCSPI_MODULCTRL_INITDLY_M \ 0x00000070 // Initial spi delay for first // transfer: This register is an // option only available in SINGLE // master mode The controller waits // for a delay to transmit the first // spi word after channel enabled // and corresponding TX register // filled. This Delay is based on // SPI output frequency clock No // clock output provided to the // boundary and chip select is not // active in 4 pin mode within this // period. 0x0 No delay for first // spi transfer. 0x1 The controller // wait 4 spi bus clock 0x2 The // controller wait 8 spi bus clock // 0x3 The controller wait 16 spi // bus clock 0x4 The controller wait // 32 spi bus clock #define MCSPI_MODULCTRL_INITDLY_S 4 #define MCSPI_MODULCTRL_SYSTEM_TEST \ 0x00000008 // Enables the system test mode 0 // Functional mode 1 System test // mode (SYSTEST) #define MCSPI_MODULCTRL_MS 0x00000004 // Master/ Slave 0 Master - The // module generates the SPICLK and // SPIEN[3:0] 1 Slave - The module // receives the SPICLK and // SPIEN[3:0] #define MCSPI_MODULCTRL_PIN34 0x00000002 // Pin mode selection: This // register is used to configure the // SPI pin mode in master or slave // mode. If asserted the controller // only use SIMOSOMI and SPICLK // clock pin for spi transfers. 0 // SPIEN is used as a chip select. 1 // SPIEN is not used.In this mode // all related option to chip select // have no meaning. #define MCSPI_MODULCTRL_SINGLE 0x00000001 // Single channel / Multi Channel // (master mode only) 0 More than // one channel will be used in // master mode. 1 Only one channel // will be used in master mode. This // bit must be set in Force SPIEN // mode. //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH0CONF register. // //****************************************************************************** #define MCSPI_CH0CONF_CLKG 0x20000000 // Clock divider granularity This // register defines the granularity // of channel clock divider: power // of two or one clock cycle // granularity. When this bit is set // the register MCSPI_CHCTRL[EXTCLK] // must be configured to reach a // maximum of 4096 clock divider // ratio. Then The clock divider // ratio is a concatenation of // MCSPI_CHCONF[CLKD] and // MCSPI_CHCTRL[EXTCLK] values 0 // Clock granularity of power of two // 1 One clock cycle ganularity #define MCSPI_CH0CONF_FFER 0x10000000 // FIFO enabled for receive:Only // one channel can have this bit // field set. 0 The buffer is not // used to receive data. 1 The // buffer is used to receive data. #define MCSPI_CH0CONF_FFEW 0x08000000 // FIFO enabled for Transmit:Only // one channel can have this bit // field set. 0 The buffer is not // used to transmit data. 1 The // buffer is used to transmit data. #define MCSPI_CH0CONF_TCS0_M 0x06000000 // Chip Select Time Control This // 2-bits field defines the number // of interface clock cycles between // CS toggling and first or last // edge of SPI clock. 0x0 0.5 clock // cycle 0x1 1.5 clock cycle 0x2 2.5 // clock cycle 0x3 3.5 clock cycle #define MCSPI_CH0CONF_TCS0_S 25 #define MCSPI_CH0CONF_SBPOL 0x01000000 // Start bit polarity 0 Start bit // polarity is held to 0 during SPI // transfer. 1 Start bit polarity is // held to 1 during SPI transfer. #define MCSPI_CH0CONF_SBE 0x00800000 // Start bit enable for SPI // transfer 0 Default SPI transfer // length as specified by WL bit // field 1 Start bit D/CX added // before SPI transfer polarity is // defined by MCSPI_CH0CONF[SBPOL] #define MCSPI_CH0CONF_SPIENSLV_M \ 0x00600000 // Channel 0 only and slave mode // only: SPI slave select signal // detection. Reserved bits for // other cases. 0x0 Detection // enabled only on SPIEN[0] 0x1 // Detection enabled only on // SPIEN[1] 0x2 Detection enabled // only on SPIEN[2] 0x3 Detection // enabled only on SPIEN[3] #define MCSPI_CH0CONF_SPIENSLV_S 21 #define MCSPI_CH0CONF_FORCE 0x00100000 // Manual SPIEN assertion to keep // SPIEN active between SPI words. // (single channel master mode only) // 0 Writing 0 into this bit drives // low the SPIEN line when // MCSPI_CHCONF(i)[EPOL]=0 and // drives it high when // MCSPI_CHCONF(i)[EPOL]=1. 1 // Writing 1 into this bit drives // high the SPIEN line when // MCSPI_CHCONF(i)[EPOL]=0 and // drives it low when // MCSPI_CHCONF(i)[EPOL]=1 #define MCSPI_CH0CONF_TURBO 0x00080000 // Turbo mode 0 Turbo is // deactivated (recommended for // single SPI word transfer) 1 Turbo // is activated to maximize the // throughput for multi SPI words // transfer. #define MCSPI_CH0CONF_IS 0x00040000 // Input Select 0 Data Line0 // (SPIDAT[0]) selected for // reception. 1 Data Line1 // (SPIDAT[1]) selected for // reception #define MCSPI_CH0CONF_DPE1 0x00020000 // Transmission Enable for data // line 1 (SPIDATAGZEN[1]) 0 Data // Line1 (SPIDAT[1]) selected for // transmission 1 No transmission on // Data Line1 (SPIDAT[1]) #define MCSPI_CH0CONF_DPE0 0x00010000 // Transmission Enable for data // line 0 (SPIDATAGZEN[0]) 0 Data // Line0 (SPIDAT[0]) selected for // transmission 1 No transmission on // Data Line0 (SPIDAT[0]) #define MCSPI_CH0CONF_DMAR 0x00008000 // DMA Read request The DMA Read // request line is asserted when the // channel is enabled and a new data // is available in the receive // register of the channel. The DMA // Read request line is deasserted // on read completion of the receive // register of the channel. 0 DMA // Read Request disabled 1 DMA Read // Request enabled #define MCSPI_CH0CONF_DMAW 0x00004000 // DMA Write request. The DMA Write // request line is asserted when The // channel is enabled and the // transmitter register of the // channel is empty. The DMA Write // request line is deasserted on // load completion of the // transmitter register of the // channel. 0 DMA Write Request // disabled 1 DMA Write Request // enabled #define MCSPI_CH0CONF_TRM_M 0x00003000 // Transmit/Receive modes 0x0 // Transmit and Receive mode 0x1 // Receive only mode 0x2 Transmit // only mode 0x3 Reserved #define MCSPI_CH0CONF_TRM_S 12 #define MCSPI_CH0CONF_WL_M 0x00000F80 // SPI word length 0x00 Reserved // 0x01 Reserved 0x02 Reserved 0x03 // The SPI word is 4-bits long 0x04 // The SPI word is 5-bits long 0x05 // The SPI word is 6-bits long 0x06 // The SPI word is 7-bits long 0x07 // The SPI word is 8-bits long 0x08 // The SPI word is 9-bits long 0x09 // The SPI word is 10-bits long 0x0A // The SPI word is 11-bits long 0x0B // The SPI word is 12-bits long 0x0C // The SPI word is 13-bits long 0x0D // The SPI word is 14-bits long 0x0E // The SPI word is 15-bits long 0x0F // The SPI word is 16-bits long 0x10 // The SPI word is 17-bits long 0x11 // The SPI word is 18-bits long 0x12 // The SPI word is 19-bits long 0x13 // The SPI word is 20-bits long 0x14 // The SPI word is 21-bits long 0x15 // The SPI word is 22-bits long 0x16 // The SPI word is 23-bits long 0x17 // The SPI word is 24-bits long 0x18 // The SPI word is 25-bits long 0x19 // The SPI word is 26-bits long 0x1A // The SPI word is 27-bits long 0x1B // The SPI word is 28-bits long 0x1C // The SPI word is 29-bits long 0x1D // The SPI word is 30-bits long 0x1E // The SPI word is 31-bits long 0x1F // The SPI word is 32-bits long #define MCSPI_CH0CONF_WL_S 7 #define MCSPI_CH0CONF_EPOL 0x00000040 // SPIEN polarity 0 SPIEN is held // high during the active state. 1 // SPIEN is held low during the // active state. #define MCSPI_CH0CONF_CLKD_M 0x0000003C // Frequency divider for SPICLK. // (only when the module is a Master // SPI device). A programmable clock // divider divides the SPI reference // clock (CLKSPIREF) with a 4-bit // value and results in a new clock // SPICLK available to shift-in and // shift-out data. By default the // clock divider ratio has a power // of two granularity when // MCSPI_CHCONF[CLKG] is cleared // Otherwise this register is the 4 // LSB bit of a 12-bit register // concatenated with clock divider // extension MCSPI_CHCTRL[EXTCLK] // register.The value description // below defines the clock ratio // when MCSPI_CHCONF[CLKG] is set to // 0. 0x0 1 0x1 2 0x2 4 0x3 8 0x4 16 // 0x5 32 0x6 64 0x7 128 0x8 256 0x9 // 512 0xA 1024 0xB 2048 0xC 4096 // 0xD 8192 0xE 16384 0xF 32768 #define MCSPI_CH0CONF_CLKD_S 2 #define MCSPI_CH0CONF_POL 0x00000002 // SPICLK polarity 0 SPICLK is held // high during the active state 1 // SPICLK is held low during the // active state #define MCSPI_CH0CONF_PHA 0x00000001 // SPICLK phase 0 Data are latched // on odd numbered edges of SPICLK. // 1 Data are latched on even // numbered edges of SPICLK. //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH0STAT register. // //****************************************************************************** #define MCSPI_CH0STAT_RXFFF 0x00000040 #define MCSPI_CH0STAT_RXFFE 0x00000020 #define MCSPI_CH0STAT_TXFFF 0x00000010 #define MCSPI_CH0STAT_TXFFE 0x00000008 #define MCSPI_CH0STAT_EOT 0x00000004 #define MCSPI_CH0STAT_TXS 0x00000002 #define MCSPI_CH0STAT_RXS 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH0CTRL register. // //****************************************************************************** #define MCSPI_CH0CTRL_EXTCLK_M 0x0000FF00 // Clock ratio extension: This // register is used to concatenate // with MCSPI_CHCONF[CLKD] register // for clock ratio only when // granularity is one clock cycle // (MCSPI_CHCONF[CLKG] set to 1). // Then the max value reached is // 4096 clock divider ratio. 0x00 // Clock ratio is CLKD + 1 0x01 // Clock ratio is CLKD + 1 + 16 0xFF // Clock ratio is CLKD + 1 + 4080 #define MCSPI_CH0CTRL_EXTCLK_S 8 #define MCSPI_CH0CTRL_EN 0x00000001 // Channel Enable 0 "Channel ""i"" // is not active" 1 "Channel ""i"" // is active" //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_TX0 register. // //****************************************************************************** #define MCSPI_TX0_TDATA_M 0xFFFFFFFF // Channel 0 Data to transmit #define MCSPI_TX0_TDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_RX0 register. // //****************************************************************************** #define MCSPI_RX0_RDATA_M 0xFFFFFFFF // Channel 0 Received Data #define MCSPI_RX0_RDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH1CONF register. // //****************************************************************************** #define MCSPI_CH1CONF_CLKG 0x20000000 // Clock divider granularity This // register defines the granularity // of channel clock divider: power // of two or one clock cycle // granularity. When this bit is set // the register MCSPI_CHCTRL[EXTCLK] // must be configured to reach a // maximum of 4096 clock divider // ratio. Then The clock divider // ratio is a concatenation of // MCSPI_CHCONF[CLKD] and // MCSPI_CHCTRL[EXTCLK] values 0 // Clock granularity of power of two // 1 One clock cycle ganularity #define MCSPI_CH1CONF_FFER 0x10000000 // FIFO enabled for receive:Only // one channel can have this bit // field set. 0 The buffer is not // used to receive data. 1 The // buffer is used to receive data. #define MCSPI_CH1CONF_FFEW 0x08000000 // FIFO enabled for Transmit:Only // one channel can have this bit // field set. 0 The buffer is not // used to transmit data. 1 The // buffer is used to transmit data. #define MCSPI_CH1CONF_TCS1_M 0x06000000 // Chip Select Time Control This // 2-bits field defines the number // of interface clock cycles between // CS toggling and first or last // edge of SPI clock. 0x0 0.5 clock // cycle 0x1 1.5 clock cycle 0x2 2.5 // clock cycle 0x3 3.5 clock cycle #define MCSPI_CH1CONF_TCS1_S 25 #define MCSPI_CH1CONF_SBPOL 0x01000000 // Start bit polarity 0 Start bit // polarity is held to 0 during SPI // transfer. 1 Start bit polarity is // held to 1 during SPI transfer. #define MCSPI_CH1CONF_SBE 0x00800000 // Start bit enable for SPI // transfer 0 Default SPI transfer // length as specified by WL bit // field 1 Start bit D/CX added // before SPI transfer polarity is // defined by MCSPI_CH1CONF[SBPOL] #define MCSPI_CH1CONF_FORCE 0x00100000 // Manual SPIEN assertion to keep // SPIEN active between SPI words. // (single channel master mode only) // 0 Writing 0 into this bit drives // low the SPIEN line when // MCSPI_CHCONF(i)[EPOL]=0 and // drives it high when // MCSPI_CHCONF(i)[EPOL]=1. 1 // Writing 1 into this bit drives // high the SPIEN line when // MCSPI_CHCONF(i)[EPOL]=0 and // drives it low when // MCSPI_CHCONF(i)[EPOL]=1 #define MCSPI_CH1CONF_TURBO 0x00080000 // Turbo mode 0 Turbo is // deactivated (recommended for // single SPI word transfer) 1 Turbo // is activated to maximize the // throughput for multi SPI words // transfer. #define MCSPI_CH1CONF_IS 0x00040000 // Input Select 0 Data Line0 // (SPIDAT[0]) selected for // reception. 1 Data Line1 // (SPIDAT[1]) selected for // reception #define MCSPI_CH1CONF_DPE1 0x00020000 // Transmission Enable for data // line 1 (SPIDATAGZEN[1]) 0 Data // Line1 (SPIDAT[1]) selected for // transmission 1 No transmission on // Data Line1 (SPIDAT[1]) #define MCSPI_CH1CONF_DPE0 0x00010000 // Transmission Enable for data // line 0 (SPIDATAGZEN[0]) 0 Data // Line0 (SPIDAT[0]) selected for // transmission 1 No transmission on // Data Line0 (SPIDAT[0]) #define MCSPI_CH1CONF_DMAR 0x00008000 // DMA Read request The DMA Read // request line is asserted when the // channel is enabled and a new data // is available in the receive // register of the channel. The DMA // Read request line is deasserted // on read completion of the receive // register of the channel. 0 DMA // Read Request disabled 1 DMA Read // Request enabled #define MCSPI_CH1CONF_DMAW 0x00004000 // DMA Write request. The DMA Write // request line is asserted when The // channel is enabled and the // transmitter register of the // channel is empty. The DMA Write // request line is deasserted on // load completion of the // transmitter register of the // channel. 0 DMA Write Request // disabled 1 DMA Write Request // enabled #define MCSPI_CH1CONF_TRM_M 0x00003000 // Transmit/Receive modes 0x0 // Transmit and Receive mode 0x1 // Receive only mode 0x2 Transmit // only mode 0x3 Reserved #define MCSPI_CH1CONF_TRM_S 12 #define MCSPI_CH1CONF_WL_M 0x00000F80 // SPI word length 0x00 Reserved // 0x01 Reserved 0x02 Reserved 0x03 // The SPI word is 4-bits long 0x04 // The SPI word is 5-bits long 0x05 // The SPI word is 6-bits long 0x06 // The SPI word is 7-bits long 0x07 // The SPI word is 8-bits long 0x08 // The SPI word is 9-bits long 0x09 // The SPI word is 10-bits long 0x0A // The SPI word is 11-bits long 0x0B // The SPI word is 12-bits long 0x0C // The SPI word is 13-bits long 0x0D // The SPI word is 14-bits long 0x0E // The SPI word is 15-bits long 0x0F // The SPI word is 16-bits long 0x10 // The SPI word is 17-bits long 0x11 // The SPI word is 18-bits long 0x12 // The SPI word is 19-bits long 0x13 // The SPI word is 20-bits long 0x14 // The SPI word is 21-bits long 0x15 // The SPI word is 22-bits long 0x16 // The SPI word is 23-bits long 0x17 // The SPI word is 24-bits long 0x18 // The SPI word is 25-bits long 0x19 // The SPI word is 26-bits long 0x1A // The SPI word is 27-bits long 0x1B // The SPI word is 28-bits long 0x1C // The SPI word is 29-bits long 0x1D // The SPI word is 30-bits long 0x1E // The SPI word is 31-bits long 0x1F // The SPI word is 32-bits long #define MCSPI_CH1CONF_WL_S 7 #define MCSPI_CH1CONF_EPOL 0x00000040 // SPIEN polarity 0 SPIEN is held // high during the active state. 1 // SPIEN is held low during the // active state. #define MCSPI_CH1CONF_CLKD_M 0x0000003C // Frequency divider for SPICLK. // (only when the module is a Master // SPI device). A programmable clock // divider divides the SPI reference // clock (CLKSPIREF) with a 4-bit // value and results in a new clock // SPICLK available to shift-in and // shift-out data. By default the // clock divider ratio has a power // of two granularity when // MCSPI_CHCONF[CLKG] is cleared // Otherwise this register is the 4 // LSB bit of a 12-bit register // concatenated with clock divider // extension MCSPI_CHCTRL[EXTCLK] // register.The value description // below defines the clock ratio // when MCSPI_CHCONF[CLKG] is set to // 0. 0x0 1 0x1 2 0x2 4 0x3 8 0x4 16 // 0x5 32 0x6 64 0x7 128 0x8 256 0x9 // 512 0xA 1024 0xB 2048 0xC 4096 // 0xD 8192 0xE 16384 0xF 32768 #define MCSPI_CH1CONF_CLKD_S 2 #define MCSPI_CH1CONF_POL 0x00000002 // SPICLK polarity 0 SPICLK is held // high during the active state 1 // SPICLK is held low during the // active state #define MCSPI_CH1CONF_PHA 0x00000001 // SPICLK phase 0 Data are latched // on odd numbered edges of SPICLK. // 1 Data are latched on even // numbered edges of SPICLK. //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH1STAT register. // //****************************************************************************** #define MCSPI_CH1STAT_RXFFF 0x00000040 #define MCSPI_CH1STAT_RXFFE 0x00000020 #define MCSPI_CH1STAT_TXFFF 0x00000010 #define MCSPI_CH1STAT_TXFFE 0x00000008 #define MCSPI_CH1STAT_EOT 0x00000004 #define MCSPI_CH1STAT_TXS 0x00000002 #define MCSPI_CH1STAT_RXS 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH1CTRL register. // //****************************************************************************** #define MCSPI_CH1CTRL_EXTCLK_M 0x0000FF00 // Clock ratio extension: This // register is used to concatenate // with MCSPI_CHCONF[CLKD] register // for clock ratio only when // granularity is one clock cycle // (MCSPI_CHCONF[CLKG] set to 1). // Then the max value reached is // 4096 clock divider ratio. 0x00 // Clock ratio is CLKD + 1 0x01 // Clock ratio is CLKD + 1 + 16 0xFF // Clock ratio is CLKD + 1 + 4080 #define MCSPI_CH1CTRL_EXTCLK_S 8 #define MCSPI_CH1CTRL_EN 0x00000001 // Channel Enable 0 "Channel ""i"" // is not active" 1 "Channel ""i"" // is active" //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_TX1 register. // //****************************************************************************** #define MCSPI_TX1_TDATA_M 0xFFFFFFFF // Channel 1 Data to transmit #define MCSPI_TX1_TDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_RX1 register. // //****************************************************************************** #define MCSPI_RX1_RDATA_M 0xFFFFFFFF // Channel 1 Received Data #define MCSPI_RX1_RDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH2CONF register. // //****************************************************************************** #define MCSPI_CH2CONF_CLKG 0x20000000 // Clock divider granularity This // register defines the granularity // of channel clock divider: power // of two or one clock cycle // granularity. When this bit is set // the register MCSPI_CHCTRL[EXTCLK] // must be configured to reach a // maximum of 4096 clock divider // ratio. Then The clock divider // ratio is a concatenation of // MCSPI_CHCONF[CLKD] and // MCSPI_CHCTRL[EXTCLK] values 0 // Clock granularity of power of two // 1 One clock cycle ganularity #define MCSPI_CH2CONF_FFER 0x10000000 // FIFO enabled for receive:Only // one channel can have this bit // field set. 0 The buffer is not // used to receive data. 1 The // buffer is used to receive data. #define MCSPI_CH2CONF_FFEW 0x08000000 // FIFO enabled for Transmit:Only // one channel can have this bit // field set. 0 The buffer is not // used to transmit data. 1 The // buffer is used to transmit data. #define MCSPI_CH2CONF_TCS2_M 0x06000000 // Chip Select Time Control This // 2-bits field defines the number // of interface clock cycles between // CS toggling and first or last // edge of SPI clock. 0x0 0.5 clock // cycle 0x1 1.5 clock cycle 0x2 2.5 // clock cycle 0x3 3.5 clock cycle #define MCSPI_CH2CONF_TCS2_S 25 #define MCSPI_CH2CONF_SBPOL 0x01000000 // Start bit polarity 0 Start bit // polarity is held to 0 during SPI // transfer. 1 Start bit polarity is // held to 1 during SPI transfer. #define MCSPI_CH2CONF_SBE 0x00800000 // Start bit enable for SPI // transfer 0 Default SPI transfer // length as specified by WL bit // field 1 Start bit D/CX added // before SPI transfer polarity is // defined by MCSPI_CH2CONF[SBPOL] #define MCSPI_CH2CONF_FORCE 0x00100000 // Manual SPIEN assertion to keep // SPIEN active between SPI words. // (single channel master mode only) // 0 Writing 0 into this bit drives // low the SPIEN line when // MCSPI_CHCONF(i)[EPOL]=0 and // drives it high when // MCSPI_CHCONF(i)[EPOL]=1. 1 // Writing 1 into this bit drives // high the SPIEN line when // MCSPI_CHCONF(i)[EPOL]=0 and // drives it low when // MCSPI_CHCONF(i)[EPOL]=1 #define MCSPI_CH2CONF_TURBO 0x00080000 // Turbo mode 0 Turbo is // deactivated (recommended for // single SPI word transfer) 1 Turbo // is activated to maximize the // throughput for multi SPI words // transfer. #define MCSPI_CH2CONF_IS 0x00040000 // Input Select 0 Data Line0 // (SPIDAT[0]) selected for // reception. 1 Data Line1 // (SPIDAT[1]) selected for // reception #define MCSPI_CH2CONF_DPE1 0x00020000 // Transmission Enable for data // line 1 (SPIDATAGZEN[1]) 0 Data // Line1 (SPIDAT[1]) selected for // transmission 1 No transmission on // Data Line1 (SPIDAT[1]) #define MCSPI_CH2CONF_DPE0 0x00010000 // Transmission Enable for data // line 0 (SPIDATAGZEN[0]) 0 Data // Line0 (SPIDAT[0]) selected for // transmission 1 No transmission on // Data Line0 (SPIDAT[0]) #define MCSPI_CH2CONF_DMAR 0x00008000 // DMA Read request The DMA Read // request line is asserted when the // channel is enabled and a new data // is available in the receive // register of the channel. The DMA // Read request line is deasserted // on read completion of the receive // register of the channel. 0 DMA // Read Request disabled 1 DMA Read // Request enabled #define MCSPI_CH2CONF_DMAW 0x00004000 // DMA Write request. The DMA Write // request line is asserted when The // channel is enabled and the // transmitter register of the // channel is empty. The DMA Write // request line is deasserted on // load completion of the // transmitter register of the // channel. 0 DMA Write Request // disabled 1 DMA Write Request // enabled #define MCSPI_CH2CONF_TRM_M 0x00003000 // Transmit/Receive modes 0x0 // Transmit and Receive mode 0x1 // Receive only mode 0x2 Transmit // only mode 0x3 Reserved #define MCSPI_CH2CONF_TRM_S 12 #define MCSPI_CH2CONF_WL_M 0x00000F80 // SPI word length 0x00 Reserved // 0x01 Reserved 0x02 Reserved 0x03 // The SPI word is 4-bits long 0x04 // The SPI word is 5-bits long 0x05 // The SPI word is 6-bits long 0x06 // The SPI word is 7-bits long 0x07 // The SPI word is 8-bits long 0x08 // The SPI word is 9-bits long 0x09 // The SPI word is 10-bits long 0x0A // The SPI word is 11-bits long 0x0B // The SPI word is 12-bits long 0x0C // The SPI word is 13-bits long 0x0D // The SPI word is 14-bits long 0x0E // The SPI word is 15-bits long 0x0F // The SPI word is 16-bits long 0x10 // The SPI word is 17-bits long 0x11 // The SPI word is 18-bits long 0x12 // The SPI word is 19-bits long 0x13 // The SPI word is 20-bits long 0x14 // The SPI word is 21-bits long 0x15 // The SPI word is 22-bits long 0x16 // The SPI word is 23-bits long 0x17 // The SPI word is 24-bits long 0x18 // The SPI word is 25-bits long 0x19 // The SPI word is 26-bits long 0x1A // The SPI word is 27-bits long 0x1B // The SPI word is 28-bits long 0x1C // The SPI word is 29-bits long 0x1D // The SPI word is 30-bits long 0x1E // The SPI word is 31-bits long 0x1F // The SPI word is 32-bits long #define MCSPI_CH2CONF_WL_S 7 #define MCSPI_CH2CONF_EPOL 0x00000040 // SPIEN polarity 0 SPIEN is held // high during the active state. 1 // SPIEN is held low during the // active state. #define MCSPI_CH2CONF_CLKD_M 0x0000003C // Frequency divider for SPICLK. // (only when the module is a Master // SPI device). A programmable clock // divider divides the SPI reference // clock (CLKSPIREF) with a 4-bit // value and results in a new clock // SPICLK available to shift-in and // shift-out data. By default the // clock divider ratio has a power // of two granularity when // MCSPI_CHCONF[CLKG] is cleared // Otherwise this register is the 4 // LSB bit of a 12-bit register // concatenated with clock divider // extension MCSPI_CHCTRL[EXTCLK] // register.The value description // below defines the clock ratio // when MCSPI_CHCONF[CLKG] is set to // 0. 0x0 1 0x1 2 0x2 4 0x3 8 0x4 16 // 0x5 32 0x6 64 0x7 128 0x8 256 0x9 // 512 0xA 1024 0xB 2048 0xC 4096 // 0xD 8192 0xE 16384 0xF 32768 #define MCSPI_CH2CONF_CLKD_S 2 #define MCSPI_CH2CONF_POL 0x00000002 // SPICLK polarity 0 SPICLK is held // high during the active state 1 // SPICLK is held low during the // active state #define MCSPI_CH2CONF_PHA 0x00000001 // SPICLK phase 0 Data are latched // on odd numbered edges of SPICLK. // 1 Data are latched on even // numbered edges of SPICLK. //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH2STAT register. // //****************************************************************************** #define MCSPI_CH2STAT_RXFFF 0x00000040 #define MCSPI_CH2STAT_RXFFE 0x00000020 #define MCSPI_CH2STAT_TXFFF 0x00000010 #define MCSPI_CH2STAT_TXFFE 0x00000008 #define MCSPI_CH2STAT_EOT 0x00000004 #define MCSPI_CH2STAT_TXS 0x00000002 #define MCSPI_CH2STAT_RXS 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH2CTRL register. // //****************************************************************************** #define MCSPI_CH2CTRL_EXTCLK_M 0x0000FF00 // Clock ratio extension: This // register is used to concatenate // with MCSPI_CHCONF[CLKD] register // for clock ratio only when // granularity is one clock cycle // (MCSPI_CHCONF[CLKG] set to 1). // Then the max value reached is // 4096 clock divider ratio. 0x00 // Clock ratio is CLKD + 1 0x01 // Clock ratio is CLKD + 1 + 16 0xFF // Clock ratio is CLKD + 1 + 4080 #define MCSPI_CH2CTRL_EXTCLK_S 8 #define MCSPI_CH2CTRL_EN 0x00000001 // Channel Enable 0 "Channel ""i"" // is not active" 1 "Channel ""i"" // is active" //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_TX2 register. // //****************************************************************************** #define MCSPI_TX2_TDATA_M 0xFFFFFFFF // Channel 2 Data to transmit #define MCSPI_TX2_TDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_RX2 register. // //****************************************************************************** #define MCSPI_RX2_RDATA_M 0xFFFFFFFF // Channel 2 Received Data #define MCSPI_RX2_RDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH3CONF register. // //****************************************************************************** #define MCSPI_CH3CONF_CLKG 0x20000000 // Clock divider granularity This // register defines the granularity // of channel clock divider: power // of two or one clock cycle // granularity. When this bit is set // the register MCSPI_CHCTRL[EXTCLK] // must be configured to reach a // maximum of 4096 clock divider // ratio. Then The clock divider // ratio is a concatenation of // MCSPI_CHCONF[CLKD] and // MCSPI_CHCTRL[EXTCLK] values 0 // Clock granularity of power of two // 1 One clock cycle ganularity #define MCSPI_CH3CONF_FFER 0x10000000 // FIFO enabled for receive:Only // one channel can have this bit // field set. 0 The buffer is not // used to receive data. 1 The // buffer is used to receive data. #define MCSPI_CH3CONF_FFEW 0x08000000 // FIFO enabled for Transmit:Only // one channel can have this bit // field set. 0 The buffer is not // used to transmit data. 1 The // buffer is used to transmit data. #define MCSPI_CH3CONF_TCS3_M 0x06000000 // Chip Select Time Control This // 2-bits field defines the number // of interface clock cycles between // CS toggling and first or last // edge of SPI clock. 0x0 0.5 clock // cycle 0x1 1.5 clock cycle 0x2 2.5 // clock cycle 0x3 3.5 clock cycle #define MCSPI_CH3CONF_TCS3_S 25 #define MCSPI_CH3CONF_SBPOL 0x01000000 // Start bit polarity 0 Start bit // polarity is held to 0 during SPI // transfer. 1 Start bit polarity is // held to 1 during SPI transfer. #define MCSPI_CH3CONF_SBE 0x00800000 // Start bit enable for SPI // transfer 0 Default SPI transfer // length as specified by WL bit // field 1 Start bit D/CX added // before SPI transfer polarity is // defined by MCSPI_CH3CONF[SBPOL] #define MCSPI_CH3CONF_FORCE 0x00100000 // Manual SPIEN assertion to keep // SPIEN active between SPI words. // (single channel master mode only) // 0 Writing 0 into this bit drives // low the SPIEN line when // MCSPI_CHCONF(i)[EPOL]=0 and // drives it high when // MCSPI_CHCONF(i)[EPOL]=1. 1 // Writing 1 into this bit drives // high the SPIEN line when // MCSPI_CHCONF(i)[EPOL]=0 and // drives it low when // MCSPI_CHCONF(i)[EPOL]=1 #define MCSPI_CH3CONF_TURBO 0x00080000 // Turbo mode 0 Turbo is // deactivated (recommended for // single SPI word transfer) 1 Turbo // is activated to maximize the // throughput for multi SPI words // transfer. #define MCSPI_CH3CONF_IS 0x00040000 // Input Select 0 Data Line0 // (SPIDAT[0]) selected for // reception. 1 Data Line1 // (SPIDAT[1]) selected for // reception #define MCSPI_CH3CONF_DPE1 0x00020000 // Transmission Enable for data // line 1 (SPIDATAGZEN[1]) 0 Data // Line1 (SPIDAT[1]) selected for // transmission 1 No transmission on // Data Line1 (SPIDAT[1]) #define MCSPI_CH3CONF_DPE0 0x00010000 // Transmission Enable for data // line 0 (SPIDATAGZEN[0]) 0 Data // Line0 (SPIDAT[0]) selected for // transmission 1 No transmission on // Data Line0 (SPIDAT[0]) #define MCSPI_CH3CONF_DMAR 0x00008000 // DMA Read request The DMA Read // request line is asserted when the // channel is enabled and a new data // is available in the receive // register of the channel. The DMA // Read request line is deasserted // on read completion of the receive // register of the channel. 0 DMA // Read Request disabled 1 DMA Read // Request enabled #define MCSPI_CH3CONF_DMAW 0x00004000 // DMA Write request. The DMA Write // request line is asserted when The // channel is enabled and the // transmitter register of the // channel is empty. The DMA Write // request line is deasserted on // load completion of the // transmitter register of the // channel. 0 DMA Write Request // disabled 1 DMA Write Request // enabled #define MCSPI_CH3CONF_TRM_M 0x00003000 // Transmit/Receive modes 0x0 // Transmit and Receive mode 0x1 // Receive only mode 0x2 Transmit // only mode 0x3 Reserved #define MCSPI_CH3CONF_TRM_S 12 #define MCSPI_CH3CONF_WL_M 0x00000F80 // SPI word length 0x00 Reserved // 0x01 Reserved 0x02 Reserved 0x03 // The SPI word is 4-bits long 0x04 // The SPI word is 5-bits long 0x05 // The SPI word is 6-bits long 0x06 // The SPI word is 7-bits long 0x07 // The SPI word is 8-bits long 0x08 // The SPI word is 9-bits long 0x09 // The SPI word is 10-bits long 0x0A // The SPI word is 11-bits long 0x0B // The SPI word is 12-bits long 0x0C // The SPI word is 13-bits long 0x0D // The SPI word is 14-bits long 0x0E // The SPI word is 15-bits long 0x0F // The SPI word is 16-bits long 0x10 // The SPI word is 17-bits long 0x11 // The SPI word is 18-bits long 0x12 // The SPI word is 19-bits long 0x13 // The SPI word is 20-bits long 0x14 // The SPI word is 21-bits long 0x15 // The SPI word is 22-bits long 0x16 // The SPI word is 23-bits long 0x17 // The SPI word is 24-bits long 0x18 // The SPI word is 25-bits long 0x19 // The SPI word is 26-bits long 0x1A // The SPI word is 27-bits long 0x1B // The SPI word is 28-bits long 0x1C // The SPI word is 29-bits long 0x1D // The SPI word is 30-bits long 0x1E // The SPI word is 31-bits long 0x1F // The SPI word is 32-bits long #define MCSPI_CH3CONF_WL_S 7 #define MCSPI_CH3CONF_EPOL 0x00000040 // SPIEN polarity 0 SPIEN is held // high during the active state. 1 // SPIEN is held low during the // active state. #define MCSPI_CH3CONF_CLKD_M 0x0000003C // Frequency divider for SPICLK. // (only when the module is a Master // SPI device). A programmable clock // divider divides the SPI reference // clock (CLKSPIREF) with a 4-bit // value and results in a new clock // SPICLK available to shift-in and // shift-out data. By default the // clock divider ratio has a power // of two granularity when // MCSPI_CHCONF[CLKG] is cleared // Otherwise this register is the 4 // LSB bit of a 12-bit register // concatenated with clock divider // extension MCSPI_CHCTRL[EXTCLK] // register.The value description // below defines the clock ratio // when MCSPI_CHCONF[CLKG] is set to // 0. 0x0 1 0x1 2 0x2 4 0x3 8 0x4 16 // 0x5 32 0x6 64 0x7 128 0x8 256 0x9 // 512 0xA 1024 0xB 2048 0xC 4096 // 0xD 8192 0xE 16384 0xF 32768 #define MCSPI_CH3CONF_CLKD_S 2 #define MCSPI_CH3CONF_POL 0x00000002 // SPICLK polarity 0 SPICLK is held // high during the active state 1 // SPICLK is held low during the // active state #define MCSPI_CH3CONF_PHA 0x00000001 // SPICLK phase 0 Data are latched // on odd numbered edges of SPICLK. // 1 Data are latched on even // numbered edges of SPICLK. //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH3STAT register. // //****************************************************************************** #define MCSPI_CH3STAT_RXFFF 0x00000040 #define MCSPI_CH3STAT_RXFFE 0x00000020 #define MCSPI_CH3STAT_TXFFF 0x00000010 #define MCSPI_CH3STAT_TXFFE 0x00000008 #define MCSPI_CH3STAT_EOT 0x00000004 #define MCSPI_CH3STAT_TXS 0x00000002 #define MCSPI_CH3STAT_RXS 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_CH3CTRL register. // //****************************************************************************** #define MCSPI_CH3CTRL_EXTCLK_M 0x0000FF00 // Clock ratio extension: This // register is used to concatenate // with MCSPI_CHCONF[CLKD] register // for clock ratio only when // granularity is one clock cycle // (MCSPI_CHCONF[CLKG] set to 1). // Then the max value reached is // 4096 clock divider ratio. 0x00 // Clock ratio is CLKD + 1 0x01 // Clock ratio is CLKD + 1 + 16 0xFF // Clock ratio is CLKD + 1 + 4080 #define MCSPI_CH3CTRL_EXTCLK_S 8 #define MCSPI_CH3CTRL_EN 0x00000001 // Channel Enable 0 "Channel ""i"" // is not active" 1 "Channel ""i"" // is active" //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_TX3 register. // //****************************************************************************** #define MCSPI_TX3_TDATA_M 0xFFFFFFFF // Channel 3 Data to transmit #define MCSPI_TX3_TDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_RX3 register. // //****************************************************************************** #define MCSPI_RX3_RDATA_M 0xFFFFFFFF // Channel 3 Received Data #define MCSPI_RX3_RDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_XFERLEVEL register. // //****************************************************************************** #define MCSPI_XFERLEVEL_WCNT_M 0xFFFF0000 // Spi word counterThis register // holds the programmable value of // number of SPI word to be // transferred on channel which is // using the FIFO buffer.When // transfer had started a read back // in this register returns the // current SPI word transfer index. // 0x0000 Counter not used 0x0001 // one word 0xFFFE 65534 spi word // 0xFFFF 65535 spi word #define MCSPI_XFERLEVEL_WCNT_S 16 #define MCSPI_XFERLEVEL_AFL_M 0x0000FF00 // Buffer Almost Full This register // holds the programmable almost // full level value used to // determine almost full buffer // condition. If the user wants an // interrupt or a DMA read request // to be issued during a receive // operation when the data buffer // holds at least n bytes then the // buffer MCSPI_MODULCTRL[AFL] must // be set with n-1.The size of this // register is defined by the // generic parameter FFNBYTE. 0x00 // one byte 0x01 2 bytes 0xFE // 255bytes 0xFF 256bytes #define MCSPI_XFERLEVEL_AFL_S 8 #define MCSPI_XFERLEVEL_AEL_M 0x000000FF // Buffer Almost EmptyThis register // holds the programmable almost // empty level value used to // determine almost empty buffer // condition. If the user wants an // interrupt or a DMA write request // to be issued during a transmit // operation when the data buffer is // able to receive n bytes then the // buffer MCSPI_MODULCTRL[AEL] must // be set with n-1. 0x00 one byte // 0x01 2 bytes 0xFE 255 bytes 0xFF // 256bytes #define MCSPI_XFERLEVEL_AEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_DAFTX register. // //****************************************************************************** #define MCSPI_DAFTX_DAFTDATA_M 0xFFFFFFFF // FIFO Data to transmit with DMA // 256 bit aligned address. "This // Register is only is used when // MCSPI_MODULCTRL[FDAA] is set to // ""1"" and only one of the // MCSPI_CH(i)CONF[FFEW] of enabled // channels is set. If these // conditions are not respected any // access to this register return a // null value." #define MCSPI_DAFTX_DAFTDATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MCSPI_O_DAFRX register. // //****************************************************************************** #define MCSPI_DAFRX_DAFRDATA_M 0xFFFFFFFF // FIFO Data to transmit with DMA // 256 bit aligned address. "This // Register is only is used when // MCSPI_MODULCTRL[FDAA] is set to // ""1"" and only one of the // MCSPI_CH(i)CONF[FFEW] of enabled // channels is set. If these // conditions are not respected any // access to this register return a // null value." #define MCSPI_DAFRX_DAFRDATA_S 0 #endif // __HW_MCSPI_H__ micropython-1.12/ports/cc3200/hal/inc/hw_memmap.h000066400000000000000000000072341357706137100215310ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_MEMMAP_H__ #define __HW_MEMMAP_H__ //***************************************************************************** // // The following are defines for the base address of the memories and // peripherals on the slave_1 interface. // //***************************************************************************** #define FLASH_BASE 0x01000000 #define SRAM_BASE 0x20000000 #define WDT_BASE 0x40000000 #define GPIOA0_BASE 0x40004000 #define GPIOA1_BASE 0x40005000 #define GPIOA2_BASE 0x40006000 #define GPIOA3_BASE 0x40007000 #define GPIOA4_BASE 0x40024000 #define UARTA0_BASE 0x4000C000 #define UARTA1_BASE 0x4000D000 #define I2CA0_BASE 0x40020000 #define TIMERA0_BASE 0x40030000 #define TIMERA1_BASE 0x40031000 #define TIMERA2_BASE 0x40032000 #define TIMERA3_BASE 0x40033000 #define STACKDIE_CTRL_BASE 0x400F5000 #define COMMON_REG_BASE 0x400F7000 #define FLASH_CONTROL_BASE 0x400FD000 #define SYSTEM_CONTROL_BASE 0x400FE000 #define UDMA_BASE 0x400FF000 #define SDHOST_BASE 0x44010000 #define CAMERA_BASE 0x44018000 #define I2S_BASE 0x4401C000 #define SSPI_BASE 0x44020000 #define GSPI_BASE 0x44021000 #define LSPI_BASE 0x44022000 #define ARCM_BASE 0x44025000 #define APPS_CONFIG_BASE 0x44026000 #define GPRCM_BASE 0x4402D000 #define OCP_SHARED_BASE 0x4402E000 #define ADC_BASE 0x4402E800 #define HIB1P2_BASE 0x4402F000 #define HIB3P3_BASE 0x4402F800 #define DTHE_BASE 0x44030000 #define SHAMD5_BASE 0x44035000 #define AES_BASE 0x44037000 #define DES_BASE 0x44039000 #endif // __HW_MEMMAP_H__ micropython-1.12/ports/cc3200/hal/inc/hw_mmchs.h000066400000000000000000004055241357706137100213700ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_MMCHS_H__ #define __HW_MMCHS_H__ //***************************************************************************** // // The following are defines for the MMCHS register offsets. // //***************************************************************************** #define MMCHS_O_HL_REV 0x00000000 // IP Revision Identifier (X.Y.R) // Used by software to track // features bugs and compatibility #define MMCHS_O_HL_HWINFO 0x00000004 // Information about the IP // module's hardware configuration // i.e. typically the module's HDL // generics (if any). Actual field // format and encoding is up to the // module's designer to decide. #define MMCHS_O_HL_SYSCONFIG 0x00000010 // Clock management configuration #define MMCHS_O_SYSCONFIG 0x00000110 // System Configuration Register // This register allows controlling // various parameters of the OCP // interface. #define MMCHS_O_SYSSTATUS 0x00000114 // System Status Register This // register provides status // information about the module // excluding the interrupt status // information #define MMCHS_O_CSRE 0x00000124 // Card status response error This // register enables the host // controller to detect card status // errors of response type R1 R1b // for all cards and of R5 R5b and // R6 response for cards types SD or // SDIO. When a bit MMCHS_CSRE[i] is // set to 1 if the corresponding bit // at the same position in the // response MMCHS_RSP0[i] is set to // 1 the host controller indicates a // card error (MMCHS_STAT[CERR]) // interrupt status to avoid the // host driver reading the response // register (MMCHS_RSP0). Note: No // automatic card error detection // for autoCMD12 is implemented; the // host system has to check // autoCMD12 response register // (MMCHS_RESP76) for possible card // errors. #define MMCHS_O_SYSTEST 0x00000128 // System Test register This // register is used to control the // signals that connect to I/O pins // when the module is configured in // system test (SYSTEST) mode for // boundary connectivity // verification. Note: In SYSTEST // mode a write into MMCHS_CMD // register will not start a // transfer. The buffer behaves as a // stack accessible only by the // local host (push and pop // operations). In this mode the // Transfer Block Size // (MMCHS_BLK[BLEN]) and the Blocks // count for current transfer // (MMCHS_BLK[NBLK]) are needed to // generate a Buffer write ready // interrupt (MMCHS_STAT[BWR]) or a // Buffer read ready interrupt // (MMCHS_STAT[BRR]) and DMA // requests if enabled. #define MMCHS_O_CON 0x0000012C // Configuration register This // register is used: - to select the // functional mode or the SYSTEST // mode for any card. - to send an // initialization sequence to any // card. - to enable the detection // on DAT[1] of a card interrupt for // SDIO cards only. and also to // configure : - specific data and // command transfers for MMC cards // only. - the parameters related to // the card detect and write protect // input signals. #define MMCHS_O_PWCNT 0x00000130 // Power counter register This // register is used to program a mmc // counter to delay command // transfers after activating the // PAD power this value depends on // PAD characteristics and voltage. #define MMCHS_O_BLK 0x00000204 // Transfer Length Configuration // register MMCHS_BLK[BLEN] is the // block size register. // MMCHS_BLK[NBLK] is the block // count register. This register // shall be used for any card. #define MMCHS_O_ARG 0x00000208 // Command argument Register This // register contains command // argument specified as bit 39-8 of // Command-Format These registers // must be initialized prior to // sending the command itself to the // card (write action into the // register MMCHS_CMD register). // Only exception is for a command // index specifying stuff bits in // arguments making a write // unnecessary. #define MMCHS_O_CMD 0x0000020C // Command and transfer mode // register MMCHS_CMD[31:16] = the // command register MMCHS_CMD[15:0] // = the transfer mode. This // register configures the data and // command transfers. A write into // the most significant byte send // the command. A write into // MMCHS_CMD[15:0] registers during // data transfer has no effect. This // register shall be used for any // card. Note: In SYSTEST mode a // write into MMCHS_CMD register // will not start a transfer. #define MMCHS_O_RSP10 0x00000210 // Command response[31:0] Register // This 32-bit register holds bits // positions [31:0] of command // response type // R1/R1b/R2/R3/R4/R5/R5b/R6 #define MMCHS_O_RSP32 0x00000214 // Command response[63:32] Register // This 32-bit register holds bits // positions [63:32] of command // response type R2 #define MMCHS_O_RSP54 0x00000218 // Command response[95:64] Register // This 32-bit register holds bits // positions [95:64] of command // response type R2 #define MMCHS_O_RSP76 0x0000021C // Command response[127:96] // Register This 32-bit register // holds bits positions [127:96] of // command response type R2 #define MMCHS_O_DATA 0x00000220 // Data Register This register is // the 32-bit entry point of the // buffer for read or write data // transfers. The buffer size is // 32bits x256(1024 bytes). Bytes // within a word are stored and read // in little endian format. This // buffer can be used as two 512 // byte buffers to transfer data // efficiently without reducing the // throughput. Sequential and // contiguous access is necessary to // increment the pointer correctly. // Random or skipped access is not // allowed. In little endian if the // local host accesses this register // byte-wise or 16bit-wise the least // significant byte (bits [7:0]) // must always be written/read // first. The update of the buffer // address is done on the most // significant byte write for full // 32-bit DATA register or on the // most significant byte of the last // word of block transfer. Example // 1: Byte or 16-bit access // Mbyteen[3:0]=0001 (1-byte) => // Mbyteen[3:0]=0010 (1-byte) => // Mbyteen[3:0]=1100 (2-bytes) OK // Mbyteen[3:0]=0001 (1-byte) => // Mbyteen[3:0]=0010 (1-byte) => // Mbyteen[3:0]=0100 (1-byte) OK // Mbyteen[3:0]=0001 (1-byte) => // Mbyteen[3:0]=0010 (1-byte) => // Mbyteen[3:0]=1000 (1-byte) Bad #define MMCHS_O_PSTATE 0x00000224 // Present state register The Host // can get status of the Host // Controller from this 32-bit read // only register. #define MMCHS_O_HCTL 0x00000228 // Control register This register // defines the host controls to set // power wakeup and transfer // parameters. MMCHS_HCTL[31:24] = // Wakeup control MMCHS_HCTL[23:16] // = Block gap control // MMCHS_HCTL[15:8] = Power control // MMCHS_HCTL[7:0] = Host control #define MMCHS_O_SYSCTL 0x0000022C // SD system control register This // register defines the system // controls to set software resets // clock frequency management and // data timeout. MMCHS_SYSCTL[31:24] // = Software resets // MMCHS_SYSCTL[23:16] = Timeout // control MMCHS_SYSCTL[15:0] = // Clock control #define MMCHS_O_STAT 0x00000230 // Interrupt status register The // interrupt status regroups all the // status of the module internal // events that can generate an // interrupt. MMCHS_STAT[31:16] = // Error Interrupt Status // MMCHS_STAT[15:0] = Normal // Interrupt Status #define MMCHS_O_IE 0x00000234 // Interrupt SD enable register // This register allows to // enable/disable the module to set // status bits on an event-by-event // basis. MMCHS_IE[31:16] = Error // Interrupt Status Enable // MMCHS_IE[15:0] = Normal Interrupt // Status Enable #define MMCHS_O_ISE 0x00000238 // Interrupt signal enable register // This register allows to // enable/disable the module // internal sources of status on an // event-by-event basis. // MMCHS_ISE[31:16] = Error // Interrupt Signal Enable // MMCHS_ISE[15:0] = Normal // Interrupt Signal Enable #define MMCHS_O_AC12 0x0000023C // Auto CMD12 Error Status Register // The host driver may determine // which of the errors cases related // to Auto CMD12 has occurred by // checking this MMCHS_AC12 register // when an Auto CMD12 Error // interrupt occurs. This register // is valid only when Auto CMD12 is // enabled (MMCHS_CMD[ACEN]) and // Auto CMD12Error (MMCHS_STAT[ACE]) // is set to 1. Note: These bits are // automatically reset when starting // a new adtc command with data. #define MMCHS_O_CAPA 0x00000240 // Capabilities register This // register lists the capabilities // of the MMC/SD/SDIO host // controller. #define MMCHS_O_CUR_CAPA 0x00000248 // Maximum current capabilities // Register This register indicates // the maximum current capability // for each voltage. The value is // meaningful if the voltage support // is set in the capabilities // register (MMCHS_CAPA). // Initialization of this register // (via a write access to this // register) depends on the system // capabilities. The host driver // shall not modify this register // after the initilaization. This // register is only reinitialized by // a hard reset (via RESETN signal) #define MMCHS_O_FE 0x00000250 // Force Event Register for Error // Interrupt status The force Event // Register is not a physically // implemented register. Rather it // is an address at which the Error // Interrupt Status register can be // written. The effect of a write to // this address will be reflected in // the Error Interrupt Status // Register if corresponding bit of // the Error Interrupt Status Enable // Register is set. #define MMCHS_O_ADMAES 0x00000254 // ADMA Error Status Register When // ADMA Error Interrupt is occurred // the ADMA Error States field in // this register holds the ADMA // state and the ADMA System Address // Register holds the address around // the error descriptor. For // recovering the error the Host // Driver requires the ADMA state to // identify the error descriptor // address as follows: ST_STOP: // Previous location set in the ADMA // System Address register is the // error descriptor address ST_FDS: // Current location set in the ADMA // System Address register is the // error descriptor address ST_CADR: // This sate is never set because do // not generate ADMA error in this // state. ST_TFR: Previous location // set in the ADMA System Address // register is the error descriptor // address In case of write // operation the Host Driver should // use ACMD22 to get the number of // written block rather than using // this information since unwritten // data may exist in the Host // Controller. The Host Controller // generates the ADMA Error // Interrupt when it detects invalid // descriptor data (Valid=0) at the // ST_FDS state. In this case ADMA // Error State indicates that an // error occurs at ST_FDS state. The // Host Driver may find that the // Valid bit is not set in the error // descriptor. #define MMCHS_O_ADMASAL 0x00000258 // ADMA System address Low bits #define MMCHS_O_REV 0x000002FC // Versions Register This register // contains the hard coded RTL // vendor revision number the // version number of SD // specification compliancy and a // slot status bit. MMCHS_REV[31:16] // = Host controller version // MMCHS_REV[15:0] = Slot Interrupt // Status //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_HL_REV register. // //****************************************************************************** #define MMCHS_HL_REV_SCHEME_M 0xC0000000 #define MMCHS_HL_REV_SCHEME_S 30 #define MMCHS_HL_REV_FUNC_M 0x0FFF0000 // Function indicates a software // compatible module family. If // there is no level of software // compatibility a new Func number // (and hence REVISION) should be // assigned. #define MMCHS_HL_REV_FUNC_S 16 #define MMCHS_HL_REV_R_RTL_M 0x0000F800 // RTL Version (R) maintained by IP // design owner. RTL follows a // numbering such as X.Y.R.Z which // are explained in this table. R // changes ONLY when: (1) PDS // uploads occur which may have been // due to spec changes (2) Bug fixes // occur (3) Resets to '0' when X or // Y changes. Design team has an // internal 'Z' (customer invisible) // number which increments on every // drop that happens due to DV and // RTL updates. Z resets to 0 when R // increments. #define MMCHS_HL_REV_R_RTL_S 11 #define MMCHS_HL_REV_X_MAJOR_M 0x00000700 // Major Revision (X) maintained by // IP specification owner. X changes // ONLY when: (1) There is a major // feature addition. An example // would be adding Master Mode to // Utopia Level2. The Func field (or // Class/Type in old PID format) // will remain the same. X does NOT // change due to: (1) Bug fixes (2) // Change in feature parameters. #define MMCHS_HL_REV_X_MAJOR_S 8 #define MMCHS_HL_REV_CUSTOM_M 0x000000C0 #define MMCHS_HL_REV_CUSTOM_S 6 #define MMCHS_HL_REV_Y_MINOR_M 0x0000003F // Minor Revision (Y) maintained by // IP specification owner. Y changes // ONLY when: (1) Features are // scaled (up or down). Flexibility // exists in that this feature // scalability may either be // represented in the Y change or a // specific register in the IP that // indicates which features are // exactly available. (2) When // feature creeps from Is-Not list // to Is list. But this may not be // the case once it sees silicon; in // which case X will change. Y does // NOT change due to: (1) Bug fixes // (2) Typos or clarifications (3) // major functional/feature // change/addition/deletion. Instead // these changes may be reflected // via R S X as applicable. Spec // owner maintains a // customer-invisible number 'S' // which changes due to: (1) // Typos/clarifications (2) Bug // documentation. Note that this bug // is not due to a spec change but // due to implementation. // Nevertheless the spec tracks the // IP bugs. An RTL release (say for // silicon PG1.1) that occurs due to // bug fix should document the // corresponding spec number (X.Y.S) // in its release notes. #define MMCHS_HL_REV_Y_MINOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_HL_HWINFO register. // //****************************************************************************** #define MMCHS_HL_HWINFO_RETMODE 0x00000040 #define MMCHS_HL_HWINFO_MEM_SIZE_M \ 0x0000003C #define MMCHS_HL_HWINFO_MEM_SIZE_S 2 #define MMCHS_HL_HWINFO_MERGE_MEM \ 0x00000002 #define MMCHS_HL_HWINFO_MADMA_EN \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the // MMCHS_O_HL_SYSCONFIG register. // //****************************************************************************** #define MMCHS_HL_SYSCONFIG_STANDBYMODE_M \ 0x00000030 // Configuration of the local // initiator state management mode. // By definition initiator may // generate read/write transaction // as long as it is out of STANDBY // state. 0x0 Force-standby mode: // local initiator is // unconditionally placed in standby // state.Backup mode for debug only. // 0x1 No-standby mode: local // initiator is unconditionally // placed out of standby // state.Backup mode for debug only. // 0x2 Smart-standby mode: local // initiator standby status depends // on local conditions i.e. the // module's functional requirement // from the initiator.IP module // shall not generate // (initiator-related) wakeup // events. 0x3 "Smart-Standby // wakeup-capable mode: local // initiator standby status depends // on local conditions i.e. the // module's functional requirement // from the initiator. IP module may // generate (master-related) wakeup // events when in standby state.Mode // is only relevant if the // appropriate IP module ""mwakeup"" // output is implemented." #define MMCHS_HL_SYSCONFIG_STANDBYMODE_S 4 #define MMCHS_HL_SYSCONFIG_IDLEMODE_M \ 0x0000000C // Configuration of the local // target state management mode. By // definition target can handle // read/write transaction as long as // it is out of IDLE state. 0x0 // Force-idle mode: local target's // idle state follows (acknowledges) // the system's idle requests // unconditionally i.e. regardless // of the IP module's internal // requirements.Backup mode for // debug only. 0x1 No-idle mode: // local target never enters idle // state.Backup mode for debug only. // 0x2 Smart-idle mode: local // target's idle state eventually // follows (acknowledges) the // system's idle requests depending // on the IP module's internal // requirements.IP module shall not // generate (IRQ- or // DMA-request-related) wakeup // events. 0x3 "Smart-idle // wakeup-capable mode: local // target's idle state eventually // follows (acknowledges) the // system's idle requests depending // on the IP module's internal // requirements.IP module may // generate (IRQ- or // DMA-request-related) wakeup // events when in idle state.Mode is // only relevant if the appropriate // IP module ""swakeup"" output(s) // is (are) implemented." #define MMCHS_HL_SYSCONFIG_IDLEMODE_S 2 #define MMCHS_HL_SYSCONFIG_FREEEMU \ 0x00000002 // Sensitivity to emulation (debug) // suspend input signal. // Functionality NOT implemented in // MMCHS. 0 IP module is sensitive // to emulation suspend 1 IP module // is not sensitive to emulation // suspend #define MMCHS_HL_SYSCONFIG_SOFTRESET \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_SYSCONFIG register. // //****************************************************************************** #define MMCHS_SYSCONFIG_STANDBYMODE_M \ 0x00003000 // Master interface power // Management standby/wait control. // The bit field is only useful when // generic parameter MADMA_EN // (Master ADMA enable) is set as // active otherwise it is a read // only register read a '0'. 0x0 // Force-standby. Mstandby is forced // unconditionnaly. 0x1 No-standby. // Mstandby is never asserted. 0x2 // Smart-standby mode: local // initiator standby status depends // on local conditions i.e. the // module's functional requirement // from the initiator.IP module // shall not generate // (initiator-related) wakeup // events. 0x3 Smart-Standby // wakeup-capable mode: "local // initiator standby status depends // on local conditions i.e. the // module's functional requirement // from the initiator. IP module may // generate (master-related) wakeup // events when in standby state.Mode // is only relevant if the // appropriate IP module ""mwakeup"" // output is implemented." #define MMCHS_SYSCONFIG_STANDBYMODE_S 12 #define MMCHS_SYSCONFIG_CLOCKACTIVITY_M \ 0x00000300 // Clocks activity during wake up // mode period. Bit8: OCP interface // clock Bit9: Functional clock 0x0 // OCP and Functional clock may be // switched off. 0x1 OCP clock is // maintained. Functional clock may // be switched-off. 0x2 Functional // clock is maintained. OCP clock // may be switched-off. 0x3 OCP and // Functional clocks are maintained. #define MMCHS_SYSCONFIG_CLOCKACTIVITY_S 8 #define MMCHS_SYSCONFIG_SIDLEMODE_M \ 0x00000018 // Power management 0x0 If an idle // request is detected the MMCHS // acknowledges it unconditionally // and goes in Inactive mode. // Interrupt and DMA requests are // unconditionally de-asserted. 0x1 // If an idle request is detected // the request is ignored and the // module keeps on behaving // normally. 0x2 Smart-idle mode: // local target's idle state // eventually follows (acknowledges) // the system's idle requests // depending on the IP module's // internal requirements.IP module // shall not generate (IRQ- or // DMA-request-related) wakeup // events. 0x3 Smart-idle // wakeup-capable mode: "local // target's idle state eventually // follows (acknowledges) the // system's idle requests depending // on the IP module's internal // requirements.IP module may // generate (IRQ- or // DMA-request-related) wakeup // events when in idle state.Mode is // only relevant if the appropriate // IP module ""swakeup"" output(s) // is (are) implemented." #define MMCHS_SYSCONFIG_SIDLEMODE_S 3 #define MMCHS_SYSCONFIG_ENAWAKEUP \ 0x00000004 // Wakeup feature control 0 Wakeup // capability is disabled 1 Wakeup // capability is enabled #define MMCHS_SYSCONFIG_SOFTRESET \ 0x00000002 #define MMCHS_SYSCONFIG_AUTOIDLE \ 0x00000001 // Internal Clock gating strategy 0 // Clocks are free-running 1 // Automatic clock gating strategy // is applied based on the OCP and // MMC interface activity //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_SYSSTATUS register. // //****************************************************************************** #define MMCHS_SYSSTATUS_RESETDONE \ 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_CSRE register. // //****************************************************************************** #define MMCHS_CSRE_CSRE_M 0xFFFFFFFF // Card status response error #define MMCHS_CSRE_CSRE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_SYSTEST register. // //****************************************************************************** #define MMCHS_SYSTEST_OBI 0x00010000 #define MMCHS_SYSTEST_SDCD 0x00008000 #define MMCHS_SYSTEST_SDWP 0x00004000 #define MMCHS_SYSTEST_WAKD 0x00002000 #define MMCHS_SYSTEST_SSB 0x00001000 #define MMCHS_SYSTEST_D7D 0x00000800 #define MMCHS_SYSTEST_D6D 0x00000400 #define MMCHS_SYSTEST_D5D 0x00000200 #define MMCHS_SYSTEST_D4D 0x00000100 #define MMCHS_SYSTEST_D3D 0x00000080 #define MMCHS_SYSTEST_D2D 0x00000040 #define MMCHS_SYSTEST_D1D 0x00000020 #define MMCHS_SYSTEST_D0D 0x00000010 #define MMCHS_SYSTEST_DDIR 0x00000008 #define MMCHS_SYSTEST_CDAT 0x00000004 #define MMCHS_SYSTEST_CDIR 0x00000002 #define MMCHS_SYSTEST_MCKD 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_CON register. // //****************************************************************************** #define MMCHS_CON_SDMA_LNE 0x00200000 // Slave DMA Level/Edge Request: // The waveform of the DMA request // can be configured either edge // sensitive with early de-assertion // on first access to MMCHS_DATA // register or late de-assertion // request remains active until last // allowed data written into // MMCHS_DATA. 0 Slave DMA edge // sensitive Early DMA de-assertion // 1 Slave DMA level sensitive Late // DMA de-assertion #define MMCHS_CON_DMA_MNS 0x00100000 // DMA Master or Slave selection: // When this bit is set and the // controller is configured to use // the DMA Ocp master interface is // used to get datas from system // using ADMA2 procedure (direct // access to the memory).This option // is only available if generic // parameter MADMA_EN is asserted to // '1'. 0 The controller is slave on // data transfers with system. 1 The // controller is master on data // exchange with system controller // must be configured as using DMA. #define MMCHS_CON_DDR 0x00080000 // Dual Data Rate mode: When this // register is set the controller // uses both clock edge to emit or // receive data. Odd bytes are // transmitted on falling edges and // even bytes are transmitted on // rise edges. It only applies on // Data bytes and CRC Start end bits // and CRC status are kept full // cycle. This bit field is only // meaningful and active for even // clock divider ratio of // MMCHS_SYSCTL[CLKD] it is // insensitive to MMCHS_HCTL[HSPE] // setting. 0 Standard mode : data // are transmitted on a single edge // depending on MMCHS_HCTRL[HSPE]. 1 // Data Bytes and CRC are // transmitted on both edge. #define MMCHS_CON_BOOT_CF0 0x00040000 #define MMCHS_CON_BOOT_ACK 0x00020000 // Book acknowledge received: When // this bit is set the controller // should receive a boot status on // DAT0 line after next command // issued. If no status is received // a data timeout will be generated. // 0 No acknowledge to be received 1 // A boot status will be received on // DAT0 line after issuing a // command. #define MMCHS_CON_CLKEXTFREE 0x00010000 // External clock free running: // This register is used to maintain // card clock out of transfer // transaction to enable slave // module for example to generate a // synchronous interrupt on DAT[1]. // The Clock will be maintain only // if MMCHS_SYSCTL[CEN] is set. 0 // External card clock is cut off // outside active transaction // period. 1 External card clock is // maintain even out of active // transaction period only if // MMCHS_SYSCTL[CEN] is set. #define MMCHS_CON_PADEN 0x00008000 // Control Power for MMC Lines: // This register is only useful when // MMC PADs contain power saving // mechanism to minimize its leakage // power. It works as a GPIO that // directly control the ACTIVE pin // of PADs. Excepted for DAT[1] the // signal is also combine outside // the module with the dedicated // power control MMCHS_CON[CTPL] // bit. 0 ADPIDLE module pin is not // forced it is automatically // generated by the MMC fsms. 1 // ADPIDLE module pin is forced to // active state. #define MMCHS_CON_OBIE 0x00004000 // Out-of-Band Interrupt Enable MMC // cards only: This bit enables the // detection of Out-of-Band // Interrupt on MMCOBI input pin. // The usage of the Out-of-Band // signal (OBI) is optional and // depends on the system // integration. 0 Out-of-Band // interrupt detection disabled 1 // Out-of-Band interrupt detection // enabled #define MMCHS_CON_OBIP 0x00002000 // Out-of-Band Interrupt Polarity // MMC cards only: This bit selects // the active level of the // out-of-band interrupt coming from // MMC cards. The usage of the // Out-of-Band signal (OBI) is // optional and depends on the // system integration. 0 active high // level 1 active low level #define MMCHS_CON_CEATA 0x00001000 // CE-ATA control mode MMC cards // compliant with CE-ATA:By default // this bit is set to 0. It is use // to indicate that next commands // are considered as specific CE-ATA // commands that potentially use // 'command completion' features. 0 // Standard MMC/SD/SDIO mode. 1 // CE-ATA mode next commands are // considered as CE-ATA commands. #define MMCHS_CON_CTPL 0x00000800 // Control Power for DAT[1] line // MMC and SD cards: By default this // bit is set to 0 and the host // controller automatically disables // all the input buffers outside of // a transaction to minimize the // leakage current. SDIO cards: When // this bit is set to 1 the host // controller automatically disables // all the input buffers except the // buffer of DAT[1] outside of a // transaction in order to detect // asynchronous card interrupt on // DAT[1] line and minimize the // leakage current of the buffers. 0 // Disable all the input buffers // outside of a transaction. 1 // Disable all the input buffers // except the buffer of DAT[1] // outside of a transaction. #define MMCHS_CON_DVAL_M 0x00000600 // Debounce filter value All cards // This register is used to define a // debounce period to filter the // card detect input signal (SDCD). // The usage of the card detect // input signal (SDCD) is optional // and depends on the system // integration and the type of the // connector housing that // accommodates the card. 0x0 33 us // debounce period 0x1 231 us // debounce period 0x2 1 ms debounce // period 0x3 84 ms debounce period #define MMCHS_CON_DVAL_S 9 #define MMCHS_CON_WPP 0x00000100 // Write protect polarity For SD // and SDIO cards only This bit // selects the active level of the // write protect input signal // (SDWP). The usage of the write // protect input signal (SDWP) is // optional and depends on the // system integration and the type // of the connector housing that // accommodates the card. 0 active // high level 1 active low level #define MMCHS_CON_CDP 0x00000080 // Card detect polarity All cards // This bit selects the active level // of the card detect input signal // (SDCD). The usage of the card // detect input signal (SDCD) is // optional and depends on the // system integration and the type // of the connector housing that // accommodates the card. 0 active // high level 1 active low level #define MMCHS_CON_MIT 0x00000040 // MMC interrupt command Only for // MMC cards. This bit must be set // to 1 when the next write access // to the command register // (MMCHS_CMD) is for writing a MMC // interrupt command (CMD40) // requiring the command timeout // detection to be disabled for the // command response. 0 Command // timeout enabled 1 Command timeout // disabled #define MMCHS_CON_DW8 0x00000020 // 8-bit mode MMC select For // SD/SDIO cards this bit must be // set to 0. For MMC card this bit // must be set following a valid // SWITCH command (CMD6) with the // correct value and extend CSD // index written in the argument. // Prior to this command the MMC // card configuration register (CSD // and EXT_CSD) must be verified for // compliancy with MMC standard // specification 4.x (see section // 3.6). 0 1-bit or 4-bit Data width // (DAT[0] used MMC SD cards) 1 // 8-bit Data width (DAT[7:0] used // MMC cards) #define MMCHS_CON_MODE 0x00000010 // Mode select All cards These bits // select between Functional mode // and SYSTEST mode. 0 Functional // mode. Transfers to the // MMC/SD/SDIO cards follow the card // protocol. MMC clock is enabled. // MMC/SD transfers are operated // under the control of the CMD // register. 1 SYSTEST mode The // signal pins are configured as // general-purpose input/output and // the 1024-byte buffer is // configured as a stack memory // accessible only by the local host // or system DMA. The pins retain // their default type (input output // or in-out). SYSTEST mode is // operated under the control of the // SYSTEST register. #define MMCHS_CON_STR 0x00000008 // Stream command Only for MMC // cards. This bit must be set to 1 // only for the stream data // transfers (read or write) of the // adtc commands. Stream read is a // class 1 command (CMD11: // READ_DAT_UNTIL_STOP). Stream // write is a class 3 command // (CMD20: WRITE_DAT_UNTIL_STOP). 0 // Block oriented data transfer 1 // Stream oriented data transfer #define MMCHS_CON_HR 0x00000004 // Broadcast host response Only for // MMC cards. This register is used // to force the host to generate a // 48-bit response for bc command // type. "It can be used to // terminate the interrupt mode by // generating a CMD40 response by // the core (see section 4.3 // ""Interrupt Mode"" in the MMC [1] // specification). In order to have // the host response to be generated // in open drain mode the register // MMCHS_CON[OD] must be set to 1." // When MMCHS_CON[CEATA] is set to 1 // and MMCHS_ARG set to 0x00000000 // when writing 0x00000000 into // MMCHS_CMD register the host // controller performs a 'command // completion signal disable' token // i.e. CMD line held to '0' during // 47 cycles followed by a 1. 0 The // host does not generate a 48-bit // response instead of a command. 1 // The host generates a 48-bit // response instead of a command or // a command completion signal // disable token. #define MMCHS_CON_INIT 0x00000002 // Send initialization stream All // cards. When this bit is set to 1 // and the card is idle an // initialization sequence is sent // to the card. "An initialization // sequence consists of setting the // CMD line to 1 during 80 clock // cycles. The initialisation // sequence is mandatory - but it is // not required to do it through // this bit - this bit makes it // easier. Clock divider // (MMCHS_SYSCTL[CLKD]) should be // set to ensure that 80 clock // periods are greater than 1ms. // (see section 9.3 ""Power-Up"" in // the MMC card specification [1] or // section 6.4 in the SD card // specification [2])." Note: in // this mode there is no command // sent to the card and no response // is expected 0 The host does not // send an initialization sequence. // 1 The host sends an // initialization sequence. #define MMCHS_CON_OD 0x00000001 // Card open drain mode. Only for // MMC cards. This bit must be set // to 1 for MMC card commands 1 2 3 // and 40 and if the MMC card bus is // operating in open-drain mode // during the response phase to the // command sent. Typically during // card identification mode when the // card is either in idle ready or // ident state. It is also necessary // to set this bit to 1 for a // broadcast host response (see // Broadcast host response register // MMCHS_CON[HR]) 0 No Open Drain 1 // Open Drain or Broadcast host // response //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_PWCNT register. // //****************************************************************************** #define MMCHS_PWCNT_PWRCNT_M 0x0000FFFF // Power counter register. This // register is used to introduce a // delay between the PAD ACTIVE pin // assertion and the command issued. // 0x0000 No additional delay added // 0x0001 TCF delay (card clock // period) 0x0002 TCF x 2 delay // (card clock period) 0xFFFE TCF x // 65534 delay (card clock period) // 0xFFFF TCF x 65535 delay (card // clock period) #define MMCHS_PWCNT_PWRCNT_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_BLK register. // //****************************************************************************** #define MMCHS_BLK_NBLK_M 0xFFFF0000 // Blocks count for current // transfer This register is enabled // when Block count Enable // (MMCHS_CMD[BCE]) is set to 1 and // is valid only for multiple block // transfers. Setting the block // count to 0 results no data blocks // being transferred. Note: The host // controller decrements the block // count after each block transfer // and stops when the count reaches // zero. This register can be // accessed only if no transaction // is executing (i.e after a // transaction has stopped). Read // operations during transfers may // return an invalid value and write // operation will be ignored. In // suspend context the number of // blocks yet to be transferred can // be determined by reading this // register. When restoring transfer // context prior to issuing a Resume // command The local host shall // restore the previously saved // block count. 0x0000 Stop count // 0x0001 1 block 0x0002 2 blocks // 0xFFFF 65535 blocks #define MMCHS_BLK_NBLK_S 16 #define MMCHS_BLK_BLEN_M 0x00000FFF // Transfer Block Size. This // register specifies the block size // for block data transfers. Read // operations during transfers may // return an invalid value and write // operations are ignored. When a // CMD12 command is issued to stop // the transfer a read of the BLEN // field after transfer completion // (MMCHS_STAT[TC] set to 1) will // not return the true byte number // of data length while the stop // occurs but the value written in // this register before transfer is // launched. 0x000 No data transfer // 0x001 1 byte block length 0x002 2 // bytes block length 0x003 3 bytes // block length 0x1FF 511 bytes // block length 0x200 512 bytes // block length 0x7FF 2047 bytes // block length 0x800 2048 bytes // block length #define MMCHS_BLK_BLEN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_ARG register. // //****************************************************************************** #define MMCHS_ARG_ARG_M 0xFFFFFFFF // Command argument bits [31:0] #define MMCHS_ARG_ARG_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_CMD register. // //****************************************************************************** #define MMCHS_CMD_INDX_M 0x3F000000 // Command index Binary encoded // value from 0 to 63 specifying the // command number send to card 0x00 // CMD0 or ACMD0 0x01 CMD1 or ACMD1 // 0x02 CMD2 or ACMD2 0x03 CMD3 or // ACMD3 0x04 CMD4 or ACMD4 0x05 // CMD5 or ACMD5 0x06 CMD6 or ACMD6 // 0x07 CMD7 or ACMD7 0x08 CMD8 or // ACMD8 0x09 CMD9 or ACMD9 0x0A // CMD10 or ACMD10 0x0B CMD11 or // ACMD11 0x0C CMD12 or ACMD12 0x0D // CMD13 or ACMD13 0x0E CMD14 or // ACMD14 0x0F CMD15 or ACMD15 0x10 // CMD16 or ACMD16 0x11 CMD17 or // ACMD17 0x12 CMD18 or ACMD18 0x13 // CMD19 or ACMD19 0x14 CMD20 or // ACMD20 0x15 CMD21 or ACMD21 0x16 // CMD22 or ACMD22 0x17 CMD23 or // ACMD23 0x18 CMD24 or ACMD24 0x19 // CMD25 or ACMD25 0x1A CMD26 or // ACMD26 0x1B CMD27 or ACMD27 0x1C // CMD28 or ACMD28 0x1D CMD29 or // ACMD29 0x1E CMD30 or ACMD30 0x1F // CMD31 or ACMD31 0x20 CMD32 or // ACMD32 0x21 CMD33 or ACMD33 0x22 // CMD34 or ACMD34 0x23 CMD35 or // ACMD35 0x24 CMD36 or ACMD36 0x25 // CMD37 or ACMD37 0x26 CMD38 or // ACMD38 0x27 CMD39 or ACMD39 0x28 // CMD40 or ACMD40 0x29 CMD41 or // ACMD41 0x2A CMD42 or ACMD42 0x2B // CMD43 or ACMD43 0x2C CMD44 or // ACMD44 0x2D CMD45 or ACMD45 0x2E // CMD46 or ACMD46 0x2F CMD47 or // ACMD47 0x30 CMD48 or ACMD48 0x31 // CMD49 or ACMD49 0x32 CMD50 or // ACMD50 0x33 CMD51 or ACMD51 0x34 // CMD52 or ACMD52 0x35 CMD53 or // ACMD53 0x36 CMD54 or ACMD54 0x37 // CMD55 or ACMD55 0x38 CMD56 or // ACMD56 0x39 CMD57 or ACMD57 0x3A // CMD58 or ACMD58 0x3B CMD59 or // ACMD59 0x3C CMD60 or ACMD60 0x3D // CMD61 or ACMD61 0x3E CMD62 or // ACMD62 0x3F CMD63 or ACMD63 #define MMCHS_CMD_INDX_S 24 #define MMCHS_CMD_CMD_TYPE_M 0x00C00000 // Command type This register // specifies three types of special // command: Suspend Resume and // Abort. These bits shall be set to // 00b for all other commands. 0x0 // Others Commands 0x1 "CMD52 for // writing ""Bus Suspend"" in CCCR" // 0x2 "CMD52 for writing ""Function // Select"" in CCCR" 0x3 "Abort // command CMD12 CMD52 for writing // "" I/O Abort"" in CCCR" #define MMCHS_CMD_CMD_TYPE_S 22 #define MMCHS_CMD_DP 0x00200000 // Data present select This // register indicates that data is // present and DAT line shall be // used. It must be set to 0 in the // following conditions: - command // using only CMD line - command // with no data transfer but using // busy signal on DAT[0] - Resume // command 0 Command with no data // transfer 1 Command with data // transfer #define MMCHS_CMD_CICE 0x00100000 // Command Index check enable This // bit must be set to 1 to enable // index check on command response // to compare the index field in the // response against the index of the // command. If the index is not the // same in the response as in the // command it is reported as a // command index error // (MMCHS_STAT[CIE] set to1) Note: // The register CICE cannot be // configured for an Auto CMD12 then // index check is automatically // checked when this command is // issued. 0 Index check disable 1 // Index check enable #define MMCHS_CMD_CCCE 0x00080000 // Command CRC check enable This // bit must be set to 1 to enable // CRC7 check on command response to // protect the response against // transmission errors on the bus. // If an error is detected it is // reported as a command CRC error // (MMCHS_STAT[CCRC] set to 1). // Note: The register CCCE cannot be // configured for an Auto CMD12 and // then CRC check is automatically // checked when this command is // issued. 0 CRC7 check disable 1 // CRC7 check enable #define MMCHS_CMD_RSP_TYPE_M 0x00030000 // Response type This bits defines // the response type of the command // 0x0 No response 0x1 Response // Length 136 bits 0x2 Response // Length 48 bits 0x3 Response // Length 48 bits with busy after // response #define MMCHS_CMD_RSP_TYPE_S 16 #define MMCHS_CMD_MSBS 0x00000020 // Multi/Single block select This // bit must be set to 1 for data // transfer in case of multi block // command. For any others command // this bit shall be set to 0. 0 // Single block. If this bit is 0 it // is not necessary to set the // register MMCHS_BLK[NBLK]. 1 Multi // block. When Block Count is // disabled (MMCHS_CMD[BCE] is set // to 0) in Multiple block transfers // (MMCHS_CMD[MSBS] is set to 1) the // module can perform infinite // transfer. #define MMCHS_CMD_DDIR 0x00000010 // Data transfer Direction Select // This bit defines either data // transfer will be a read or a // write. 0 Data Write (host to // card) 1 Data Read (card to host) #define MMCHS_CMD_ACEN 0x00000004 // Auto CMD12 Enable SD card only. // When this bit is set to 1 the // host controller issues a CMD12 // automatically after the transfer // completion of the last block. The // Host Driver shall not set this // bit to issue commands that do not // require CMD12 to stop data // transfer. In particular secure // commands do not require CMD12. 0 // Auto CMD12 disable 1 Auto CMD12 // enable or CCS detection enabled. #define MMCHS_CMD_BCE 0x00000002 // Block Count Enable Multiple // block transfers only. This bit is // used to enable the block count // register (MMCHS_BLK[NBLK]). When // Block Count is disabled // (MMCHS_CMD[BCE] is set to 0) in // Multiple block transfers // (MMCHS_CMD[MSBS] is set to 1) the // module can perform infinite // transfer. 0 Block count disabled // for infinite transfer. 1 Block // count enabled for multiple block // transfer with known number of // blocks #define MMCHS_CMD_DE 0x00000001 // DMA Enable This bit is used to // enable DMA mode for host data // access. 0 DMA mode disable 1 DMA // mode enable //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_RSP10 register. // //****************************************************************************** #define MMCHS_RSP10_RSP1_M 0xFFFF0000 // Command Response [31:16] #define MMCHS_RSP10_RSP1_S 16 #define MMCHS_RSP10_RSP0_M 0x0000FFFF // Command Response [15:0] #define MMCHS_RSP10_RSP0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_RSP32 register. // //****************************************************************************** #define MMCHS_RSP32_RSP3_M 0xFFFF0000 // Command Response [63:48] #define MMCHS_RSP32_RSP3_S 16 #define MMCHS_RSP32_RSP2_M 0x0000FFFF // Command Response [47:32] #define MMCHS_RSP32_RSP2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_RSP54 register. // //****************************************************************************** #define MMCHS_RSP54_RSP5_M 0xFFFF0000 // Command Response [95:80] #define MMCHS_RSP54_RSP5_S 16 #define MMCHS_RSP54_RSP4_M 0x0000FFFF // Command Response [79:64] #define MMCHS_RSP54_RSP4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_RSP76 register. // //****************************************************************************** #define MMCHS_RSP76_RSP7_M 0xFFFF0000 // Command Response [127:112] #define MMCHS_RSP76_RSP7_S 16 #define MMCHS_RSP76_RSP6_M 0x0000FFFF // Command Response [111:96] #define MMCHS_RSP76_RSP6_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_DATA register. // //****************************************************************************** #define MMCHS_DATA_DATA_M 0xFFFFFFFF // Data Register [31:0] In // functional mode (MMCHS_CON[MODE] // set to the default value 0) A // read access to this register is // allowed only when the buffer read // enable status is set to 1 // (MMCHS_PSTATE[BRE]) otherwise a // bad access (MMCHS_STAT[BADA]) is // signaled. A write access to this // register is allowed only when the // buffer write enable status is set // to 1(MMCHS_STATE[BWE]) otherwise // a bad access (MMCHS_STAT[BADA]) // is signaled and the data is not // written. #define MMCHS_DATA_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_PSTATE register. // //****************************************************************************** #define MMCHS_PSTATE_CLEV 0x01000000 #define MMCHS_PSTATE_DLEV_M 0x00F00000 // DAT[3:0] line signal level // DAT[3] => bit 23 DAT[2] => bit 22 // DAT[1] => bit 21 DAT[0] => bit 20 // This status is used to check DAT // line level to recover from errors // and for debugging. This is // especially useful in detecting // the busy signal level from // DAT[0]. The value of these // registers after reset depends on // the DAT lines level at that time. #define MMCHS_PSTATE_DLEV_S 20 #define MMCHS_PSTATE_WP 0x00080000 #define MMCHS_PSTATE_CDPL 0x00040000 #define MMCHS_PSTATE_CSS 0x00020000 #define MMCHS_PSTATE_CINS 0x00010000 #define MMCHS_PSTATE_BRE 0x00000800 #define MMCHS_PSTATE_BWE 0x00000400 #define MMCHS_PSTATE_RTA 0x00000200 #define MMCHS_PSTATE_WTA 0x00000100 #define MMCHS_PSTATE_DLA 0x00000004 #define MMCHS_PSTATE_DATI 0x00000002 #define MMCHS_PSTATE_CMDI 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_HCTL register. // //****************************************************************************** #define MMCHS_HCTL_OBWE 0x08000000 // Wakeup event enable for // 'Out-of-Band' Interrupt. This bit // enables wakeup events for // 'Out-of-Band' assertion. Wakeup // is generated if the wakeup // feature is enabled // (MMCHS_SYSCONFIG[ENAWAKEUP]). The // write to this register is ignored // when MMCHS_CON[OBIE] is not set. // 0 Disable wakeup on 'Out-of-Band' // Interrupt 1 Enable wakeup on // 'Out-of-Band' Interrupt #define MMCHS_HCTL_REM 0x04000000 // Wakeup event enable on SD card // removal This bit enables wakeup // events for card removal // assertion. Wakeup is generated if // the wakeup feature is enabled // (MMCHS_SYSCONFIG[ENAWAKEUP]). 0 // Disable wakeup on card removal 1 // Enable wakeup on card removal #define MMCHS_HCTL_INS 0x02000000 // Wakeup event enable on SD card // insertion This bit enables wakeup // events for card insertion // assertion. Wakeup is generated if // the wakeup feature is enabled // (MMCHS_SYSCONFIG[ENAWAKEUP]). 0 // Disable wakeup on card insertion // 1 Enable wakeup on card insertion #define MMCHS_HCTL_IWE 0x01000000 // Wakeup event enable on SD card // interrupt This bit enables wakeup // events for card interrupt // assertion. Wakeup is generated if // the wakeup feature is enabled // (MMCHS_SYSCONFIG[ENAWAKEUP]). 0 // Disable wakeup on card interrupt // 1 Enable wakeup on card interrupt #define MMCHS_HCTL_IBG 0x00080000 // Interrupt block at gap This bit // is valid only in 4-bit mode of // SDIO card to enable interrupt // detection in the interrupt cycle // at block gap for a multiple block // transfer. For MMC cards and for // SD card this bit should be set to // 0. 0 Disable interrupt detection // at the block gap in 4-bit mode 1 // Enable interrupt detection at the // block gap in 4-bit mode #define MMCHS_HCTL_RWC 0x00040000 // Read wait control The read wait // function is optional only for // SDIO cards. If the card supports // read wait this bit must be // enabled then requesting a stop at // block gap (MMCHS_HCTL[SBGR]) // generates a read wait period // after the current end of block. // Be careful if read wait is not // supported it may cause a conflict // on DAT line. 0 Disable Read Wait // Control. Suspend/Resume cannot be // supported. 1 Enable Read Wait // Control #define MMCHS_HCTL_CR 0x00020000 // Continue request This bit is // used to restart a transaction // that was stopped by requesting a // stop at block gap // (MMCHS_HCTL[SBGR]). Set this bit // to 1 restarts the transfer. The // bit is automatically set to 0 by // the host controller when transfer // has restarted i.e DAT line is // active (MMCHS_PSTATE[DLA]) or // transferring data // (MMCHS_PSTATE[WTA]). The Stop at // block gap request must be // disabled (MMCHS_HCTL[SBGR]=0) // before setting this bit. 0 No // affect 1 transfer restart #define MMCHS_HCTL_SBGR 0x00010000 // Stop at block gap request This // bit is used to stop executing a // transaction at the next block // gap. The transfer can restart // with a continue request // (MMHS_HCTL[CR]) or during a // suspend/resume sequence. In case // of read transfer the card must // support read wait control. In // case of write transfer the host // driver shall set this bit after // all block data written. Until the // transfer completion // (MMCHS_STAT[TC] set to 1) the // host driver shall leave this bit // set to 1. If this bit is set the // local host shall not write to the // data register (MMCHS_DATA). 0 // Transfer mode 1 Stop at block gap #define MMCHS_HCTL_SDVS_M 0x00000E00 // SD bus voltage select All cards. // The host driver should set to // these bits to select the voltage // level for the card according to // the voltage supported by the // system (MMCHS_CAPA[VS18VS30VS33]) // before starting a transfer. 0x5 // 1.8V (Typical) 0x6 3.0V (Typical) // 0x7 3.3V (Typical) #define MMCHS_HCTL_SDVS_S 9 #define MMCHS_HCTL_SDBP 0x00000100 // SD bus power Before setting this // bit the host driver shall select // the SD bus voltage // (MMCHS_HCTL[SDVS]). If the host // controller detects the No card // state this bit is automatically // set to 0. If the module is power // off a write in the command // register (MMCHS_CMD) will not // start the transfer. A write to // this bit has no effect if the // selected SD bus voltage // MMCHS_HCTL[SDVS] is not supported // according to capability register // (MMCHS_CAPA[VS*]). 0 Power off 1 // Power on #define MMCHS_HCTL_CDSS 0x00000080 // Card Detect Signal Selection // This bit selects source for the // card detection.When the source // for the card detection is // switched the interrupt should be // disabled during the switching // period by clearing the Interrupt // Status/Signal Enable register in // order to mask unexpected // interrupt being caused by the // glitch. The Interrupt // Status/Signal Enable should be // disabled during over the period // of debouncing. 0 SDCD# is // selected (for normal use) 1 The // Card Detect Test Level is // selected (for test purpose) #define MMCHS_HCTL_CDTL 0x00000040 // Card Detect Test Level: This bit // is enabled while the Card Detect // Signal Selection is set to 1 and // it indicates card inserted or // not. 0 No Card 1 Card Inserted #define MMCHS_HCTL_DMAS_M 0x00000018 // DMA Select Mode: One of // supported DMA modes can be // selected. The host driver shall // check support of DMA modes by // referring the Capabilities // register. Use of selected DMA is // determined by DMA Enable of the // Transfer Mode register. This // register is only meaningful when // MADMA_EN is set to 1. When // MADMA_EN is set to 0 the bit // field is read only and returned // value is 0. 0x0 Reserved 0x1 // Reserved 0x2 32-bit Address ADMA2 // is selected 0x3 Reserved #define MMCHS_HCTL_DMAS_S 3 #define MMCHS_HCTL_HSPE 0x00000004 // High Speed Enable: Before // setting this bit the Host Driver // shall check the High Speed // Support in the Capabilities // register. If this bit is set to 0 // (default) the Host Controller // outputs CMD line and DAT lines at // the falling edge of the SD Clock. // If this bit is set to 1 the Host // Controller outputs CMD line and // DAT lines at the rising edge of // the SD Clock.This bit shall not // be set when dual data rate mode // is activated in MMCHS_CON[DDR]. 0 // Normal speed mode 1 High speed // mode #define MMCHS_HCTL_DTW 0x00000002 // Data transfer width For MMC card // this bit must be set following a // valid SWITCH command (CMD6) with // the correct value and extend CSD // index written in the argument. // Prior to this command the MMC // card configuration register (CSD // and EXT_CSD) must be verified for // compliance with MMC standard // specification 4.x (see section // 3.6). This register has no effect // when the MMC 8-bit mode is // selected (register MMCHS_CON[DW8] // set to1 ) For SD/SDIO cards this // bit must be set following a valid // SET_BUS_WIDTH command (ACMD6) // with the value written in bit 1 // of the argument. Prior to this // command the SD card configuration // register (SCR) must be verified // for the supported bus width by // the SD card. 0 1-bit Data width // (DAT[0] used) 1 4-bit Data width // (DAT[3:0] used) //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_SYSCTL register. // //****************************************************************************** #define MMCHS_SYSCTL_SRD 0x04000000 // Software reset for DAT line This // bit is set to 1 for reset and // released to 0 when completed. DAT // finite state machine in both // clock domain are also reset. Here // below are the registers cleared // by MMCHS_SYSCTL[SRD]: #VALUE! - // MMCHS_PSTATE: BRE BWE RTA WTA DLA // and DATI - MMCHS_HCTL: SBGR and // CR - MMCHS_STAT: BRR BWR BGE and // TC OCP and MMC buffer data // management is reinitialized. 0 // Reset completed 1 Software reset // for DAT line #define MMCHS_SYSCTL_SRC 0x02000000 // Software reset for CMD line This // bit is set to 1 for reset and // released to 0 when completed. CMD // finite state machine in both // clock domain are also reset. Here // below the registers cleared by // MMCHS_SYSCTL[SRC]: - // MMCHS_PSTATE: CMDI - MMCHS_STAT: // CC OCP and MMC command status // management is reinitialized. 0 // Reset completed 1 Software reset // for CMD line #define MMCHS_SYSCTL_SRA 0x01000000 // Software reset for all This bit // is set to 1 for reset and // released to 0 when completed. // This reset affects the entire // host controller except for the // card detection circuit and // capabilities registers. 0 Reset // completed 1 Software reset for // all the design #define MMCHS_SYSCTL_DTO_M 0x000F0000 // Data timeout counter value and // busy timeout. This value // determines the interval by which // DAT lines timeouts are detected. // The host driver needs to set this // bitfield based on - the maximum // read access time (NAC) (Refer to // the SD Specification Part1 // Physical Layer) - the data read // access time values (TAAC and // NSAC) in the card specific data // register (CSD) of the card - the // timeout clock base frequency // (MMCHS_CAPA[TCF]). If the card // does not respond within the // specified number of cycles a data // timeout error occurs // (MMCHS_STA[DTO]). The // MMCHS_SYSCTL[DTO] register is // also used to check busy duration // to generate busy timeout for // commands with busy response or // for busy programming during a // write command. Timeout on CRC // status is generated if no CRC // token is present after a block // write. 0x0 TCF x 2^13 0x1 TCF x // 2^14 0xE TCF x 2^27 0xF Reserved #define MMCHS_SYSCTL_DTO_S 16 #define MMCHS_SYSCTL_CLKD_M 0x0000FFC0 // Clock frequency select These // bits define the ratio between a // reference clock frequency (system // dependant) and the output clock // frequency on the CLK pin of // either the memory card (MMC SD or // SDIO). 0x000 Clock Ref bypass // 0x001 Clock Ref bypass 0x002 // Clock Ref / 2 0x003 Clock Ref / 3 // 0x3FF Clock Ref / 1023 #define MMCHS_SYSCTL_CLKD_S 6 #define MMCHS_SYSCTL_CEN 0x00000004 // Clock enable This bit controls // if the clock is provided to the // card or not. 0 The clock is not // provided to the card . Clock // frequency can be changed . 1 The // clock is provided to the card and // can be automatically gated when // MMCHS_SYSCONFIG[AUTOIDLE] is set // to 1 (default value) . The host // driver shall wait to set this bit // to 1 until the Internal clock is // stable (MMCHS_SYSCTL[ICS]). #define MMCHS_SYSCTL_ICS 0x00000002 #define MMCHS_SYSCTL_ICE 0x00000001 // Internal clock enable This // register controls the internal // clock activity. In very low power // state the internal clock is // stopped. Note: The activity of // the debounce clock (used for // wakeup events) and the OCP clock // (used for reads and writes to the // module register map) are not // affected by this register. 0 The // internal clock is stopped (very // low power state). 1 The internal // clock oscillates and can be // automatically gated when // MMCHS_SYSCONFIG[AUTOIDLE] is set // to 1 (default value) . //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_STAT register. // //****************************************************************************** #define MMCHS_STAT_BADA 0x20000000 #define MMCHS_STAT_CERR 0x10000000 #define MMCHS_STAT_ADMAE 0x02000000 #define MMCHS_STAT_ACE 0x01000000 #define MMCHS_STAT_DEB 0x00400000 #define MMCHS_STAT_DCRC 0x00200000 #define MMCHS_STAT_DTO 0x00100000 #define MMCHS_STAT_CIE 0x00080000 #define MMCHS_STAT_CEB 0x00040000 #define MMCHS_STAT_CCRC 0x00020000 #define MMCHS_STAT_CTO 0x00010000 #define MMCHS_STAT_ERRI 0x00008000 #define MMCHS_STAT_BSR 0x00000400 #define MMCHS_STAT_OBI 0x00000200 #define MMCHS_STAT_CIRQ 0x00000100 #define MMCHS_STAT_CREM 0x00000080 #define MMCHS_STAT_CINS 0x00000040 #define MMCHS_STAT_BRR 0x00000020 #define MMCHS_STAT_BWR 0x00000010 #define MMCHS_STAT_DMA 0x00000008 #define MMCHS_STAT_BGE 0x00000004 #define MMCHS_STAT_TC 0x00000002 #define MMCHS_STAT_CC 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_IE register. // //****************************************************************************** #define MMCHS_IE_BADA_ENABLE 0x20000000 // Bad access to data space // Interrupt Enable 0 Masked 1 // Enabled #define MMCHS_IE_CERR_ENABLE 0x10000000 // Card error interrupt Enable 0 // Masked 1 Enabled #define MMCHS_IE_ADMAE_ENABLE 0x02000000 // ADMA error Interrupt Enable 0 // Masked 1 Enabled #define MMCHS_IE_ACE_ENABLE 0x01000000 // Auto CMD12 error Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_DEB_ENABLE 0x00400000 // Data end bit error Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_DCRC_ENABLE 0x00200000 // Data CRC error Interrupt Enable // 0 Masked 1 Enabled #define MMCHS_IE_DTO_ENABLE 0x00100000 // Data timeout error Interrupt // Enable 0 The data timeout // detection is deactivated. The // host controller provides the // clock to the card until the card // sends the data or the transfer is // aborted. 1 The data timeout // detection is enabled. #define MMCHS_IE_CIE_ENABLE 0x00080000 // Command index error Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_CEB_ENABLE 0x00040000 // Command end bit error Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_CCRC_ENABLE 0x00020000 // Command CRC error Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_CTO_ENABLE 0x00010000 // Command timeout error Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_NULL 0x00008000 // Fixed to 0 The host driver shall // control error interrupts using // the Error Interrupt Signal Enable // register. Writes to this bit are // ignored #define MMCHS_IE_BSR_ENABLE 0x00000400 // Boot status interrupt Enable A // write to this register when // MMCHS_CON[BOOT_ACK] is set to 0x0 // is ignored. 0 Masked 1 Enabled #define MMCHS_IE_OBI_ENABLE 0x00000200 // Out-of-Band interrupt Enable A // write to this register when // MMCHS_CON[OBIE] is set to '0' is // ignored. 0 Masked 1 Enabled #define MMCHS_IE_CIRQ_ENABLE 0x00000100 // Card interrupt Enable A clear of // this bit also clears the // corresponding status bit. During // 1-bit mode if the interrupt // routine doesn't remove the source // of a card interrupt in the SDIO // card the status bit is reasserted // when this bit is set to 1. 0 // Masked 1 Enabled #define MMCHS_IE_CREM_ENABLE 0x00000080 // Card removal Interrupt Enable 0 // Masked 1 Enabled #define MMCHS_IE_CINS_ENABLE 0x00000040 // Card insertion Interrupt Enable // 0 Masked 1 Enabled #define MMCHS_IE_BRR_ENABLE 0x00000020 // Buffer Read Ready Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_BWR_ENABLE 0x00000010 // Buffer Write Ready Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_DMA_ENABLE 0x00000008 // DMA interrupt Enable 0 Masked 1 // Enabled #define MMCHS_IE_BGE_ENABLE 0x00000004 // Block Gap Event Interrupt Enable // 0 Masked 1 Enabled #define MMCHS_IE_TC_ENABLE 0x00000002 // Transfer completed Interrupt // Enable 0 Masked 1 Enabled #define MMCHS_IE_CC_ENABLE 0x00000001 // Command completed Interrupt // Enable 0 Masked 1 Enabled //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_ISE register. // //****************************************************************************** #define MMCHS_ISE_BADA_SIGEN 0x20000000 // Bad access to data space signal // status Enable 0 Masked 1 Enabled #define MMCHS_ISE_CERR_SIGEN 0x10000000 // Card error interrupt signal // status Enable 0 Masked 1 Enabled #define MMCHS_ISE_ADMAE_SIGEN 0x02000000 // ADMA error signal status Enable // 0 Masked 1 Enabled #define MMCHS_ISE_ACE_SIGEN 0x01000000 // Auto CMD12 error signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_DEB_SIGEN 0x00400000 // Data end bit error signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_DCRC_SIGEN 0x00200000 // Data CRC error signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_DTO_SIGEN 0x00100000 // Data timeout error signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_CIE_SIGEN 0x00080000 // Command index error signal // status Enable 0 Masked 1 Enabled #define MMCHS_ISE_CEB_SIGEN 0x00040000 // Command end bit error signal // status Enable 0 Masked 1 Enabled #define MMCHS_ISE_CCRC_SIGEN 0x00020000 // Command CRC error signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_CTO_SIGEN 0x00010000 // Command timeout error signal // status Enable 0 Masked 1 Enabled #define MMCHS_ISE_NULL 0x00008000 // Fixed to 0 The host driver shall // control error interrupts using // the Error Interrupt Signal Enable // register. Writes to this bit are // ignored #define MMCHS_ISE_BSR_SIGEN 0x00000400 // Boot status signal status // EnableA write to this register // when MMCHS_CON[BOOT_ACK] is set // to 0x0 is ignored. 0 Masked 1 // Enabled #define MMCHS_ISE_OBI_SIGEN 0x00000200 // Out-Of-Band Interrupt signal // status Enable A write to this // register when MMCHS_CON[OBIE] is // set to '0' is ignored. 0 Masked 1 // Enabled #define MMCHS_ISE_CIRQ_SIGEN 0x00000100 // Card interrupt signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_CREM_SIGEN 0x00000080 // Card removal signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_CINS_SIGEN 0x00000040 // Card insertion signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_BRR_SIGEN 0x00000020 // Buffer Read Ready signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_BWR_SIGEN 0x00000010 // Buffer Write Ready signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_DMA_SIGEN 0x00000008 // DMA interrupt Signal status // enable 0 Masked 1 Enabled #define MMCHS_ISE_BGE_SIGEN 0x00000004 // Black Gap Event signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_TC_SIGEN 0x00000002 // Transfer completed signal status // Enable 0 Masked 1 Enabled #define MMCHS_ISE_CC_SIGEN 0x00000001 // Command completed signal status // Enable 0 Masked 1 Enabled //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_AC12 register. // //****************************************************************************** #define MMCHS_AC12_CNI 0x00000080 #define MMCHS_AC12_ACIE 0x00000010 #define MMCHS_AC12_ACEB 0x00000008 #define MMCHS_AC12_ACCE 0x00000004 #define MMCHS_AC12_ACTO 0x00000002 #define MMCHS_AC12_ACNE 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_CAPA register. // //****************************************************************************** #define MMCHS_CAPA_BIT64 0x10000000 #define MMCHS_CAPA_VS18 0x04000000 #define MMCHS_CAPA_VS30 0x02000000 #define MMCHS_CAPA_VS33 0x01000000 #define MMCHS_CAPA_SRS 0x00800000 #define MMCHS_CAPA_DS 0x00400000 #define MMCHS_CAPA_HSS 0x00200000 #define MMCHS_CAPA_AD2S 0x00080000 #define MMCHS_CAPA_MBL_M 0x00030000 #define MMCHS_CAPA_MBL_S 16 #define MMCHS_CAPA_BCF_M 0x00003F00 #define MMCHS_CAPA_BCF_S 8 #define MMCHS_CAPA_TCU 0x00000080 #define MMCHS_CAPA_TCF_M 0x0000003F #define MMCHS_CAPA_TCF_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_CUR_CAPA register. // //****************************************************************************** #define MMCHS_CUR_CAPA_CUR_1V8_M \ 0x00FF0000 #define MMCHS_CUR_CAPA_CUR_1V8_S 16 #define MMCHS_CUR_CAPA_CUR_3V0_M \ 0x0000FF00 #define MMCHS_CUR_CAPA_CUR_3V0_S 8 #define MMCHS_CUR_CAPA_CUR_3V3_M \ 0x000000FF #define MMCHS_CUR_CAPA_CUR_3V3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_FE register. // //****************************************************************************** #define MMCHS_FE_FE_BADA 0x20000000 #define MMCHS_FE_FE_CERR 0x10000000 #define MMCHS_FE_FE_ADMAE 0x02000000 #define MMCHS_FE_FE_ACE 0x01000000 #define MMCHS_FE_FE_DEB 0x00400000 #define MMCHS_FE_FE_DCRC 0x00200000 #define MMCHS_FE_FE_DTO 0x00100000 #define MMCHS_FE_FE_CIE 0x00080000 #define MMCHS_FE_FE_CEB 0x00040000 #define MMCHS_FE_FE_CCRC 0x00020000 #define MMCHS_FE_FE_CTO 0x00010000 #define MMCHS_FE_FE_CNI 0x00000080 #define MMCHS_FE_FE_ACIE 0x00000010 #define MMCHS_FE_FE_ACEB 0x00000008 #define MMCHS_FE_FE_ACCE 0x00000004 #define MMCHS_FE_FE_ACTO 0x00000002 #define MMCHS_FE_FE_ACNE 0x00000001 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_ADMAES register. // //****************************************************************************** #define MMCHS_ADMAES_LME 0x00000004 // ADMA Length Mismatch Error: (1) // While Block Count Enable being // set the total data length // specified by the Descriptor table // is different from that specified // by the Block Count and Block // Length. (2) Total data length can // not be divided by the block // length. 0 No Error 1 Error #define MMCHS_ADMAES_AES_M 0x00000003 // ADMA Error State his field // indicates the state of ADMA when // error is occurred during ADMA // data transfer. "This field never // indicates ""10"" because ADMA // never stops in this state." 0x0 // ST_STOP (Stop DMA)Contents of // SYS_SDR register 0x1 ST_STOP // (Stop DMA)Points the error // descriptor 0x2 Never set this // state(Not used) 0x3 ST_TFR // (Transfer Data)Points the next of // the error descriptor #define MMCHS_ADMAES_AES_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_ADMASAL register. // //****************************************************************************** #define MMCHS_ADMASAL_ADMA_A32B_M \ 0xFFFFFFFF // ADMA System address 32 bits.This // register holds byte address of // executing command of the // Descriptor table. 32-bit Address // Descriptor uses lower 32-bit of // this register. At the start of // ADMA the Host Driver shall set // start address of the Descriptor // table. The ADMA increments this // register address which points to // next line when every fetching a // Descriptor line. When the ADMA // Error Interrupt is generated this // register shall hold valid // Descriptor address depending on // the ADMA state. The Host Driver // shall program Descriptor Table on // 32-bit boundary and set 32-bit // boundary address to this // register. ADMA2 ignores lower // 2-bit of this register and // assumes it to be 00b. #define MMCHS_ADMASAL_ADMA_A32B_S 0 //****************************************************************************** // // The following are defines for the bit fields in the MMCHS_O_REV register. // //****************************************************************************** #define MMCHS_REV_VREV_M 0xFF000000 // Vendor Version Number: IP // revision [7:4] Major revision // [3:0] Minor revision Examples: // 0x10 for 1.0 0x21 for 2.1 #define MMCHS_REV_VREV_S 24 #define MMCHS_REV_SREV_M 0x00FF0000 #define MMCHS_REV_SREV_S 16 #define MMCHS_REV_SIS 0x00000001 // Slot Interrupt Status This // status bit indicates the inverted // state of interrupt signal for the // module. By a power on reset or by // setting a software reset for all // (MMCHS_HCTL[SRA]) the interrupt // signal shall be de-asserted and // this status shall read 0. #endif // __HW_MMCHS_H__ micropython-1.12/ports/cc3200/hal/inc/hw_nvic.h000066400000000000000000002570361357706137100212230ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // // hw_nvic.h - Macros used when accessing the NVIC hardware. // //***************************************************************************** #ifndef __HW_NVIC_H__ #define __HW_NVIC_H__ //***************************************************************************** // // The following are defines for the NVIC register addresses. // //***************************************************************************** #define NVIC_INT_TYPE 0xE000E004 // Interrupt Controller Type Reg #define NVIC_ACTLR 0xE000E008 // Auxiliary Control #define NVIC_ST_CTRL 0xE000E010 // SysTick Control and Status // Register #define NVIC_ST_RELOAD 0xE000E014 // SysTick Reload Value Register #define NVIC_ST_CURRENT 0xE000E018 // SysTick Current Value Register #define NVIC_ST_CAL 0xE000E01C // SysTick Calibration Value Reg #define NVIC_EN0 0xE000E100 // Interrupt 0-31 Set Enable #define NVIC_EN1 0xE000E104 // Interrupt 32-54 Set Enable #define NVIC_EN2 0xE000E108 // Interrupt 64-95 Set Enable #define NVIC_EN3 0xE000E10C // Interrupt 96-127 Set Enable #define NVIC_EN4 0xE000E110 // Interrupt 128-131 Set Enable #define NVIC_EN5 0xE000E114 // Interrupt 160-191 Set Enable #define NVIC_DIS0 0xE000E180 // Interrupt 0-31 Clear Enable #define NVIC_DIS1 0xE000E184 // Interrupt 32-54 Clear Enable #define NVIC_DIS2 0xE000E188 // Interrupt 64-95 Clear Enable #define NVIC_DIS3 0xE000E18C // Interrupt 96-127 Clear Enable #define NVIC_DIS4 0xE000E190 // Interrupt 128-131 Clear Enable #define NVIC_DIS5 0xE000E194 // Interrupt 160-191 Clear Enable #define NVIC_PEND0 0xE000E200 // Interrupt 0-31 Set Pending #define NVIC_PEND1 0xE000E204 // Interrupt 32-54 Set Pending #define NVIC_PEND2 0xE000E208 // Interrupt 64-95 Set Pending #define NVIC_PEND3 0xE000E20C // Interrupt 96-127 Set Pending #define NVIC_PEND4 0xE000E210 // Interrupt 128-131 Set Pending #define NVIC_PEND5 0xE000E214 // Interrupt 160-191 Set Pending #define NVIC_UNPEND0 0xE000E280 // Interrupt 0-31 Clear Pending #define NVIC_UNPEND1 0xE000E284 // Interrupt 32-54 Clear Pending #define NVIC_UNPEND2 0xE000E288 // Interrupt 64-95 Clear Pending #define NVIC_UNPEND3 0xE000E28C // Interrupt 96-127 Clear Pending #define NVIC_UNPEND4 0xE000E290 // Interrupt 128-131 Clear Pending #define NVIC_UNPEND5 0xE000E294 // Interrupt 160-191 Clear Pending #define NVIC_ACTIVE0 0xE000E300 // Interrupt 0-31 Active Bit #define NVIC_ACTIVE1 0xE000E304 // Interrupt 32-54 Active Bit #define NVIC_ACTIVE2 0xE000E308 // Interrupt 64-95 Active Bit #define NVIC_ACTIVE3 0xE000E30C // Interrupt 96-127 Active Bit #define NVIC_ACTIVE4 0xE000E310 // Interrupt 128-131 Active Bit #define NVIC_ACTIVE5 0xE000E314 // Interrupt 160-191 Active Bit #define NVIC_PRI0 0xE000E400 // Interrupt 0-3 Priority #define NVIC_PRI1 0xE000E404 // Interrupt 4-7 Priority #define NVIC_PRI2 0xE000E408 // Interrupt 8-11 Priority #define NVIC_PRI3 0xE000E40C // Interrupt 12-15 Priority #define NVIC_PRI4 0xE000E410 // Interrupt 16-19 Priority #define NVIC_PRI5 0xE000E414 // Interrupt 20-23 Priority #define NVIC_PRI6 0xE000E418 // Interrupt 24-27 Priority #define NVIC_PRI7 0xE000E41C // Interrupt 28-31 Priority #define NVIC_PRI8 0xE000E420 // Interrupt 32-35 Priority #define NVIC_PRI9 0xE000E424 // Interrupt 36-39 Priority #define NVIC_PRI10 0xE000E428 // Interrupt 40-43 Priority #define NVIC_PRI11 0xE000E42C // Interrupt 44-47 Priority #define NVIC_PRI12 0xE000E430 // Interrupt 48-51 Priority #define NVIC_PRI13 0xE000E434 // Interrupt 52-53 Priority #define NVIC_PRI14 0xE000E438 // Interrupt 56-59 Priority #define NVIC_PRI15 0xE000E43C // Interrupt 60-63 Priority #define NVIC_PRI16 0xE000E440 // Interrupt 64-67 Priority #define NVIC_PRI17 0xE000E444 // Interrupt 68-71 Priority #define NVIC_PRI18 0xE000E448 // Interrupt 72-75 Priority #define NVIC_PRI19 0xE000E44C // Interrupt 76-79 Priority #define NVIC_PRI20 0xE000E450 // Interrupt 80-83 Priority #define NVIC_PRI21 0xE000E454 // Interrupt 84-87 Priority #define NVIC_PRI22 0xE000E458 // Interrupt 88-91 Priority #define NVIC_PRI23 0xE000E45C // Interrupt 92-95 Priority #define NVIC_PRI24 0xE000E460 // Interrupt 96-99 Priority #define NVIC_PRI25 0xE000E464 // Interrupt 100-103 Priority #define NVIC_PRI26 0xE000E468 // Interrupt 104-107 Priority #define NVIC_PRI27 0xE000E46C // Interrupt 108-111 Priority #define NVIC_PRI28 0xE000E470 // Interrupt 112-115 Priority #define NVIC_PRI29 0xE000E474 // Interrupt 116-119 Priority #define NVIC_PRI30 0xE000E478 // Interrupt 120-123 Priority #define NVIC_PRI31 0xE000E47C // Interrupt 124-127 Priority #define NVIC_PRI32 0xE000E480 // Interrupt 128-131 Priority #define NVIC_PRI33 0xE000E484 // Interrupt 132-135 Priority #define NVIC_PRI34 0xE000E488 // Interrupt 136-139 Priority #define NVIC_PRI35 0xE000E48C // Interrupt 140-143 Priority #define NVIC_PRI36 0xE000E490 // Interrupt 144-147 Priority #define NVIC_PRI37 0xE000E494 // Interrupt 148-151 Priority #define NVIC_PRI38 0xE000E498 // Interrupt 152-155 Priority #define NVIC_PRI39 0xE000E49C // Interrupt 156-159 Priority #define NVIC_PRI40 0xE000E4A0 // Interrupt 160-163 Priority #define NVIC_PRI41 0xE000E4A4 // Interrupt 164-167 Priority #define NVIC_PRI42 0xE000E4A8 // Interrupt 168-171 Priority #define NVIC_PRI43 0xE000E4AC // Interrupt 172-175 Priority #define NVIC_PRI44 0xE000E4B0 // Interrupt 176-179 Priority #define NVIC_PRI45 0xE000E4B4 // Interrupt 180-183 Priority #define NVIC_PRI46 0xE000E4B8 // Interrupt 184-187 Priority #define NVIC_PRI47 0xE000E4BC // Interrupt 188-191 Priority #define NVIC_PRI48 0xE000E4C0 // Interrupt 192-195 Priority #define NVIC_CPUID 0xE000ED00 // CPU ID Base #define NVIC_INT_CTRL 0xE000ED04 // Interrupt Control and State #define NVIC_VTABLE 0xE000ED08 // Vector Table Offset #define NVIC_APINT 0xE000ED0C // Application Interrupt and Reset // Control #define NVIC_SYS_CTRL 0xE000ED10 // System Control #define NVIC_CFG_CTRL 0xE000ED14 // Configuration and Control #define NVIC_SYS_PRI1 0xE000ED18 // System Handler Priority 1 #define NVIC_SYS_PRI2 0xE000ED1C // System Handler Priority 2 #define NVIC_SYS_PRI3 0xE000ED20 // System Handler Priority 3 #define NVIC_SYS_HND_CTRL 0xE000ED24 // System Handler Control and State #define NVIC_FAULT_STAT 0xE000ED28 // Configurable Fault Status #define NVIC_HFAULT_STAT 0xE000ED2C // Hard Fault Status #define NVIC_DEBUG_STAT 0xE000ED30 // Debug Status Register #define NVIC_MM_ADDR 0xE000ED34 // Memory Management Fault Address #define NVIC_FAULT_ADDR 0xE000ED38 // Bus Fault Address #define NVIC_MPU_TYPE 0xE000ED90 // MPU Type #define NVIC_MPU_CTRL 0xE000ED94 // MPU Control #define NVIC_MPU_NUMBER 0xE000ED98 // MPU Region Number #define NVIC_MPU_BASE 0xE000ED9C // MPU Region Base Address #define NVIC_MPU_ATTR 0xE000EDA0 // MPU Region Attribute and Size #define NVIC_MPU_BASE1 0xE000EDA4 // MPU Region Base Address Alias 1 #define NVIC_MPU_ATTR1 0xE000EDA8 // MPU Region Attribute and Size // Alias 1 #define NVIC_MPU_BASE2 0xE000EDAC // MPU Region Base Address Alias 2 #define NVIC_MPU_ATTR2 0xE000EDB0 // MPU Region Attribute and Size // Alias 2 #define NVIC_MPU_BASE3 0xE000EDB4 // MPU Region Base Address Alias 3 #define NVIC_MPU_ATTR3 0xE000EDB8 // MPU Region Attribute and Size // Alias 3 #define NVIC_DBG_CTRL 0xE000EDF0 // Debug Control and Status Reg #define NVIC_DBG_XFER 0xE000EDF4 // Debug Core Reg. Transfer Select #define NVIC_DBG_DATA 0xE000EDF8 // Debug Core Register Data #define NVIC_DBG_INT 0xE000EDFC // Debug Reset Interrupt Control #define NVIC_SW_TRIG 0xE000EF00 // Software Trigger Interrupt //***************************************************************************** // // The following are defines for the bit fields in the NVIC_INT_TYPE register. // //***************************************************************************** #define NVIC_INT_TYPE_LINES_M 0x0000001F // Number of interrupt lines (x32) #define NVIC_INT_TYPE_LINES_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ACTLR register. // //***************************************************************************** #define NVIC_ACTLR_DISFOLD 0x00000004 // Disable IT Folding #define NVIC_ACTLR_DISWBUF 0x00000002 // Disable Write Buffer #define NVIC_ACTLR_DISMCYC 0x00000001 // Disable Interrupts of Multiple // Cycle Instructions //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ST_CTRL register. // //***************************************************************************** #define NVIC_ST_CTRL_COUNT 0x00010000 // Count Flag #define NVIC_ST_CTRL_CLK_SRC 0x00000004 // Clock Source #define NVIC_ST_CTRL_INTEN 0x00000002 // Interrupt Enable #define NVIC_ST_CTRL_ENABLE 0x00000001 // Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ST_RELOAD register. // //***************************************************************************** #define NVIC_ST_RELOAD_M 0x00FFFFFF // Reload Value #define NVIC_ST_RELOAD_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ST_CURRENT // register. // //***************************************************************************** #define NVIC_ST_CURRENT_M 0x00FFFFFF // Current Value #define NVIC_ST_CURRENT_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ST_CAL register. // //***************************************************************************** #define NVIC_ST_CAL_NOREF 0x80000000 // No reference clock #define NVIC_ST_CAL_SKEW 0x40000000 // Clock skew #define NVIC_ST_CAL_ONEMS_M 0x00FFFFFF // 1ms reference value #define NVIC_ST_CAL_ONEMS_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_EN0 register. // //***************************************************************************** #define NVIC_EN0_INT_M 0xFFFFFFFF // Interrupt Enable #define NVIC_EN0_INT0 0x00000001 // Interrupt 0 enable #define NVIC_EN0_INT1 0x00000002 // Interrupt 1 enable #define NVIC_EN0_INT2 0x00000004 // Interrupt 2 enable #define NVIC_EN0_INT3 0x00000008 // Interrupt 3 enable #define NVIC_EN0_INT4 0x00000010 // Interrupt 4 enable #define NVIC_EN0_INT5 0x00000020 // Interrupt 5 enable #define NVIC_EN0_INT6 0x00000040 // Interrupt 6 enable #define NVIC_EN0_INT7 0x00000080 // Interrupt 7 enable #define NVIC_EN0_INT8 0x00000100 // Interrupt 8 enable #define NVIC_EN0_INT9 0x00000200 // Interrupt 9 enable #define NVIC_EN0_INT10 0x00000400 // Interrupt 10 enable #define NVIC_EN0_INT11 0x00000800 // Interrupt 11 enable #define NVIC_EN0_INT12 0x00001000 // Interrupt 12 enable #define NVIC_EN0_INT13 0x00002000 // Interrupt 13 enable #define NVIC_EN0_INT14 0x00004000 // Interrupt 14 enable #define NVIC_EN0_INT15 0x00008000 // Interrupt 15 enable #define NVIC_EN0_INT16 0x00010000 // Interrupt 16 enable #define NVIC_EN0_INT17 0x00020000 // Interrupt 17 enable #define NVIC_EN0_INT18 0x00040000 // Interrupt 18 enable #define NVIC_EN0_INT19 0x00080000 // Interrupt 19 enable #define NVIC_EN0_INT20 0x00100000 // Interrupt 20 enable #define NVIC_EN0_INT21 0x00200000 // Interrupt 21 enable #define NVIC_EN0_INT22 0x00400000 // Interrupt 22 enable #define NVIC_EN0_INT23 0x00800000 // Interrupt 23 enable #define NVIC_EN0_INT24 0x01000000 // Interrupt 24 enable #define NVIC_EN0_INT25 0x02000000 // Interrupt 25 enable #define NVIC_EN0_INT26 0x04000000 // Interrupt 26 enable #define NVIC_EN0_INT27 0x08000000 // Interrupt 27 enable #define NVIC_EN0_INT28 0x10000000 // Interrupt 28 enable #define NVIC_EN0_INT29 0x20000000 // Interrupt 29 enable #define NVIC_EN0_INT30 0x40000000 // Interrupt 30 enable #define NVIC_EN0_INT31 0x80000000 // Interrupt 31 enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_EN1 register. // //***************************************************************************** #define NVIC_EN1_INT_M 0x007FFFFF // Interrupt Enable #undef NVIC_EN1_INT_M #define NVIC_EN1_INT_M 0xFFFFFFFF // Interrupt Enable #define NVIC_EN1_INT32 0x00000001 // Interrupt 32 enable #define NVIC_EN1_INT33 0x00000002 // Interrupt 33 enable #define NVIC_EN1_INT34 0x00000004 // Interrupt 34 enable #define NVIC_EN1_INT35 0x00000008 // Interrupt 35 enable #define NVIC_EN1_INT36 0x00000010 // Interrupt 36 enable #define NVIC_EN1_INT37 0x00000020 // Interrupt 37 enable #define NVIC_EN1_INT38 0x00000040 // Interrupt 38 enable #define NVIC_EN1_INT39 0x00000080 // Interrupt 39 enable #define NVIC_EN1_INT40 0x00000100 // Interrupt 40 enable #define NVIC_EN1_INT41 0x00000200 // Interrupt 41 enable #define NVIC_EN1_INT42 0x00000400 // Interrupt 42 enable #define NVIC_EN1_INT43 0x00000800 // Interrupt 43 enable #define NVIC_EN1_INT44 0x00001000 // Interrupt 44 enable #define NVIC_EN1_INT45 0x00002000 // Interrupt 45 enable #define NVIC_EN1_INT46 0x00004000 // Interrupt 46 enable #define NVIC_EN1_INT47 0x00008000 // Interrupt 47 enable #define NVIC_EN1_INT48 0x00010000 // Interrupt 48 enable #define NVIC_EN1_INT49 0x00020000 // Interrupt 49 enable #define NVIC_EN1_INT50 0x00040000 // Interrupt 50 enable #define NVIC_EN1_INT51 0x00080000 // Interrupt 51 enable #define NVIC_EN1_INT52 0x00100000 // Interrupt 52 enable #define NVIC_EN1_INT53 0x00200000 // Interrupt 53 enable #define NVIC_EN1_INT54 0x00400000 // Interrupt 54 enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_EN2 register. // //***************************************************************************** #define NVIC_EN2_INT_M 0xFFFFFFFF // Interrupt Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_EN3 register. // //***************************************************************************** #define NVIC_EN3_INT_M 0xFFFFFFFF // Interrupt Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_EN4 register. // //***************************************************************************** #define NVIC_EN4_INT_M 0x0000000F // Interrupt Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DIS0 register. // //***************************************************************************** #define NVIC_DIS0_INT_M 0xFFFFFFFF // Interrupt Disable #define NVIC_DIS0_INT0 0x00000001 // Interrupt 0 disable #define NVIC_DIS0_INT1 0x00000002 // Interrupt 1 disable #define NVIC_DIS0_INT2 0x00000004 // Interrupt 2 disable #define NVIC_DIS0_INT3 0x00000008 // Interrupt 3 disable #define NVIC_DIS0_INT4 0x00000010 // Interrupt 4 disable #define NVIC_DIS0_INT5 0x00000020 // Interrupt 5 disable #define NVIC_DIS0_INT6 0x00000040 // Interrupt 6 disable #define NVIC_DIS0_INT7 0x00000080 // Interrupt 7 disable #define NVIC_DIS0_INT8 0x00000100 // Interrupt 8 disable #define NVIC_DIS0_INT9 0x00000200 // Interrupt 9 disable #define NVIC_DIS0_INT10 0x00000400 // Interrupt 10 disable #define NVIC_DIS0_INT11 0x00000800 // Interrupt 11 disable #define NVIC_DIS0_INT12 0x00001000 // Interrupt 12 disable #define NVIC_DIS0_INT13 0x00002000 // Interrupt 13 disable #define NVIC_DIS0_INT14 0x00004000 // Interrupt 14 disable #define NVIC_DIS0_INT15 0x00008000 // Interrupt 15 disable #define NVIC_DIS0_INT16 0x00010000 // Interrupt 16 disable #define NVIC_DIS0_INT17 0x00020000 // Interrupt 17 disable #define NVIC_DIS0_INT18 0x00040000 // Interrupt 18 disable #define NVIC_DIS0_INT19 0x00080000 // Interrupt 19 disable #define NVIC_DIS0_INT20 0x00100000 // Interrupt 20 disable #define NVIC_DIS0_INT21 0x00200000 // Interrupt 21 disable #define NVIC_DIS0_INT22 0x00400000 // Interrupt 22 disable #define NVIC_DIS0_INT23 0x00800000 // Interrupt 23 disable #define NVIC_DIS0_INT24 0x01000000 // Interrupt 24 disable #define NVIC_DIS0_INT25 0x02000000 // Interrupt 25 disable #define NVIC_DIS0_INT26 0x04000000 // Interrupt 26 disable #define NVIC_DIS0_INT27 0x08000000 // Interrupt 27 disable #define NVIC_DIS0_INT28 0x10000000 // Interrupt 28 disable #define NVIC_DIS0_INT29 0x20000000 // Interrupt 29 disable #define NVIC_DIS0_INT30 0x40000000 // Interrupt 30 disable #define NVIC_DIS0_INT31 0x80000000 // Interrupt 31 disable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DIS1 register. // //***************************************************************************** #define NVIC_DIS1_INT_M 0x00FFFFFF // Interrupt Disable #undef NVIC_DIS1_INT_M #define NVIC_DIS1_INT_M 0xFFFFFFFF // Interrupt Disable #define NVIC_DIS1_INT32 0x00000001 // Interrupt 32 disable #define NVIC_DIS1_INT33 0x00000002 // Interrupt 33 disable #define NVIC_DIS1_INT34 0x00000004 // Interrupt 34 disable #define NVIC_DIS1_INT35 0x00000008 // Interrupt 35 disable #define NVIC_DIS1_INT36 0x00000010 // Interrupt 36 disable #define NVIC_DIS1_INT37 0x00000020 // Interrupt 37 disable #define NVIC_DIS1_INT38 0x00000040 // Interrupt 38 disable #define NVIC_DIS1_INT39 0x00000080 // Interrupt 39 disable #define NVIC_DIS1_INT40 0x00000100 // Interrupt 40 disable #define NVIC_DIS1_INT41 0x00000200 // Interrupt 41 disable #define NVIC_DIS1_INT42 0x00000400 // Interrupt 42 disable #define NVIC_DIS1_INT43 0x00000800 // Interrupt 43 disable #define NVIC_DIS1_INT44 0x00001000 // Interrupt 44 disable #define NVIC_DIS1_INT45 0x00002000 // Interrupt 45 disable #define NVIC_DIS1_INT46 0x00004000 // Interrupt 46 disable #define NVIC_DIS1_INT47 0x00008000 // Interrupt 47 disable #define NVIC_DIS1_INT48 0x00010000 // Interrupt 48 disable #define NVIC_DIS1_INT49 0x00020000 // Interrupt 49 disable #define NVIC_DIS1_INT50 0x00040000 // Interrupt 50 disable #define NVIC_DIS1_INT51 0x00080000 // Interrupt 51 disable #define NVIC_DIS1_INT52 0x00100000 // Interrupt 52 disable #define NVIC_DIS1_INT53 0x00200000 // Interrupt 53 disable #define NVIC_DIS1_INT54 0x00400000 // Interrupt 54 disable #define NVIC_DIS1_INT55 0x00800000 // Interrupt 55 disable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DIS2 register. // //***************************************************************************** #define NVIC_DIS2_INT_M 0xFFFFFFFF // Interrupt Disable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DIS3 register. // //***************************************************************************** #define NVIC_DIS3_INT_M 0xFFFFFFFF // Interrupt Disable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DIS4 register. // //***************************************************************************** #define NVIC_DIS4_INT_M 0x0000000F // Interrupt Disable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PEND0 register. // //***************************************************************************** #define NVIC_PEND0_INT_M 0xFFFFFFFF // Interrupt Set Pending #define NVIC_PEND0_INT0 0x00000001 // Interrupt 0 pend #define NVIC_PEND0_INT1 0x00000002 // Interrupt 1 pend #define NVIC_PEND0_INT2 0x00000004 // Interrupt 2 pend #define NVIC_PEND0_INT3 0x00000008 // Interrupt 3 pend #define NVIC_PEND0_INT4 0x00000010 // Interrupt 4 pend #define NVIC_PEND0_INT5 0x00000020 // Interrupt 5 pend #define NVIC_PEND0_INT6 0x00000040 // Interrupt 6 pend #define NVIC_PEND0_INT7 0x00000080 // Interrupt 7 pend #define NVIC_PEND0_INT8 0x00000100 // Interrupt 8 pend #define NVIC_PEND0_INT9 0x00000200 // Interrupt 9 pend #define NVIC_PEND0_INT10 0x00000400 // Interrupt 10 pend #define NVIC_PEND0_INT11 0x00000800 // Interrupt 11 pend #define NVIC_PEND0_INT12 0x00001000 // Interrupt 12 pend #define NVIC_PEND0_INT13 0x00002000 // Interrupt 13 pend #define NVIC_PEND0_INT14 0x00004000 // Interrupt 14 pend #define NVIC_PEND0_INT15 0x00008000 // Interrupt 15 pend #define NVIC_PEND0_INT16 0x00010000 // Interrupt 16 pend #define NVIC_PEND0_INT17 0x00020000 // Interrupt 17 pend #define NVIC_PEND0_INT18 0x00040000 // Interrupt 18 pend #define NVIC_PEND0_INT19 0x00080000 // Interrupt 19 pend #define NVIC_PEND0_INT20 0x00100000 // Interrupt 20 pend #define NVIC_PEND0_INT21 0x00200000 // Interrupt 21 pend #define NVIC_PEND0_INT22 0x00400000 // Interrupt 22 pend #define NVIC_PEND0_INT23 0x00800000 // Interrupt 23 pend #define NVIC_PEND0_INT24 0x01000000 // Interrupt 24 pend #define NVIC_PEND0_INT25 0x02000000 // Interrupt 25 pend #define NVIC_PEND0_INT26 0x04000000 // Interrupt 26 pend #define NVIC_PEND0_INT27 0x08000000 // Interrupt 27 pend #define NVIC_PEND0_INT28 0x10000000 // Interrupt 28 pend #define NVIC_PEND0_INT29 0x20000000 // Interrupt 29 pend #define NVIC_PEND0_INT30 0x40000000 // Interrupt 30 pend #define NVIC_PEND0_INT31 0x80000000 // Interrupt 31 pend //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PEND1 register. // //***************************************************************************** #define NVIC_PEND1_INT_M 0x00FFFFFF // Interrupt Set Pending #undef NVIC_PEND1_INT_M #define NVIC_PEND1_INT_M 0xFFFFFFFF // Interrupt Set Pending #define NVIC_PEND1_INT32 0x00000001 // Interrupt 32 pend #define NVIC_PEND1_INT33 0x00000002 // Interrupt 33 pend #define NVIC_PEND1_INT34 0x00000004 // Interrupt 34 pend #define NVIC_PEND1_INT35 0x00000008 // Interrupt 35 pend #define NVIC_PEND1_INT36 0x00000010 // Interrupt 36 pend #define NVIC_PEND1_INT37 0x00000020 // Interrupt 37 pend #define NVIC_PEND1_INT38 0x00000040 // Interrupt 38 pend #define NVIC_PEND1_INT39 0x00000080 // Interrupt 39 pend #define NVIC_PEND1_INT40 0x00000100 // Interrupt 40 pend #define NVIC_PEND1_INT41 0x00000200 // Interrupt 41 pend #define NVIC_PEND1_INT42 0x00000400 // Interrupt 42 pend #define NVIC_PEND1_INT43 0x00000800 // Interrupt 43 pend #define NVIC_PEND1_INT44 0x00001000 // Interrupt 44 pend #define NVIC_PEND1_INT45 0x00002000 // Interrupt 45 pend #define NVIC_PEND1_INT46 0x00004000 // Interrupt 46 pend #define NVIC_PEND1_INT47 0x00008000 // Interrupt 47 pend #define NVIC_PEND1_INT48 0x00010000 // Interrupt 48 pend #define NVIC_PEND1_INT49 0x00020000 // Interrupt 49 pend #define NVIC_PEND1_INT50 0x00040000 // Interrupt 50 pend #define NVIC_PEND1_INT51 0x00080000 // Interrupt 51 pend #define NVIC_PEND1_INT52 0x00100000 // Interrupt 52 pend #define NVIC_PEND1_INT53 0x00200000 // Interrupt 53 pend #define NVIC_PEND1_INT54 0x00400000 // Interrupt 54 pend #define NVIC_PEND1_INT55 0x00800000 // Interrupt 55 pend //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PEND2 register. // //***************************************************************************** #define NVIC_PEND2_INT_M 0xFFFFFFFF // Interrupt Set Pending //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PEND3 register. // //***************************************************************************** #define NVIC_PEND3_INT_M 0xFFFFFFFF // Interrupt Set Pending //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PEND4 register. // //***************************************************************************** #define NVIC_PEND4_INT_M 0x0000000F // Interrupt Set Pending //***************************************************************************** // // The following are defines for the bit fields in the NVIC_UNPEND0 register. // //***************************************************************************** #define NVIC_UNPEND0_INT_M 0xFFFFFFFF // Interrupt Clear Pending #define NVIC_UNPEND0_INT0 0x00000001 // Interrupt 0 unpend #define NVIC_UNPEND0_INT1 0x00000002 // Interrupt 1 unpend #define NVIC_UNPEND0_INT2 0x00000004 // Interrupt 2 unpend #define NVIC_UNPEND0_INT3 0x00000008 // Interrupt 3 unpend #define NVIC_UNPEND0_INT4 0x00000010 // Interrupt 4 unpend #define NVIC_UNPEND0_INT5 0x00000020 // Interrupt 5 unpend #define NVIC_UNPEND0_INT6 0x00000040 // Interrupt 6 unpend #define NVIC_UNPEND0_INT7 0x00000080 // Interrupt 7 unpend #define NVIC_UNPEND0_INT8 0x00000100 // Interrupt 8 unpend #define NVIC_UNPEND0_INT9 0x00000200 // Interrupt 9 unpend #define NVIC_UNPEND0_INT10 0x00000400 // Interrupt 10 unpend #define NVIC_UNPEND0_INT11 0x00000800 // Interrupt 11 unpend #define NVIC_UNPEND0_INT12 0x00001000 // Interrupt 12 unpend #define NVIC_UNPEND0_INT13 0x00002000 // Interrupt 13 unpend #define NVIC_UNPEND0_INT14 0x00004000 // Interrupt 14 unpend #define NVIC_UNPEND0_INT15 0x00008000 // Interrupt 15 unpend #define NVIC_UNPEND0_INT16 0x00010000 // Interrupt 16 unpend #define NVIC_UNPEND0_INT17 0x00020000 // Interrupt 17 unpend #define NVIC_UNPEND0_INT18 0x00040000 // Interrupt 18 unpend #define NVIC_UNPEND0_INT19 0x00080000 // Interrupt 19 unpend #define NVIC_UNPEND0_INT20 0x00100000 // Interrupt 20 unpend #define NVIC_UNPEND0_INT21 0x00200000 // Interrupt 21 unpend #define NVIC_UNPEND0_INT22 0x00400000 // Interrupt 22 unpend #define NVIC_UNPEND0_INT23 0x00800000 // Interrupt 23 unpend #define NVIC_UNPEND0_INT24 0x01000000 // Interrupt 24 unpend #define NVIC_UNPEND0_INT25 0x02000000 // Interrupt 25 unpend #define NVIC_UNPEND0_INT26 0x04000000 // Interrupt 26 unpend #define NVIC_UNPEND0_INT27 0x08000000 // Interrupt 27 unpend #define NVIC_UNPEND0_INT28 0x10000000 // Interrupt 28 unpend #define NVIC_UNPEND0_INT29 0x20000000 // Interrupt 29 unpend #define NVIC_UNPEND0_INT30 0x40000000 // Interrupt 30 unpend #define NVIC_UNPEND0_INT31 0x80000000 // Interrupt 31 unpend //***************************************************************************** // // The following are defines for the bit fields in the NVIC_UNPEND1 register. // //***************************************************************************** #define NVIC_UNPEND1_INT_M 0x00FFFFFF // Interrupt Clear Pending #undef NVIC_UNPEND1_INT_M #define NVIC_UNPEND1_INT_M 0xFFFFFFFF // Interrupt Clear Pending #define NVIC_UNPEND1_INT32 0x00000001 // Interrupt 32 unpend #define NVIC_UNPEND1_INT33 0x00000002 // Interrupt 33 unpend #define NVIC_UNPEND1_INT34 0x00000004 // Interrupt 34 unpend #define NVIC_UNPEND1_INT35 0x00000008 // Interrupt 35 unpend #define NVIC_UNPEND1_INT36 0x00000010 // Interrupt 36 unpend #define NVIC_UNPEND1_INT37 0x00000020 // Interrupt 37 unpend #define NVIC_UNPEND1_INT38 0x00000040 // Interrupt 38 unpend #define NVIC_UNPEND1_INT39 0x00000080 // Interrupt 39 unpend #define NVIC_UNPEND1_INT40 0x00000100 // Interrupt 40 unpend #define NVIC_UNPEND1_INT41 0x00000200 // Interrupt 41 unpend #define NVIC_UNPEND1_INT42 0x00000400 // Interrupt 42 unpend #define NVIC_UNPEND1_INT43 0x00000800 // Interrupt 43 unpend #define NVIC_UNPEND1_INT44 0x00001000 // Interrupt 44 unpend #define NVIC_UNPEND1_INT45 0x00002000 // Interrupt 45 unpend #define NVIC_UNPEND1_INT46 0x00004000 // Interrupt 46 unpend #define NVIC_UNPEND1_INT47 0x00008000 // Interrupt 47 unpend #define NVIC_UNPEND1_INT48 0x00010000 // Interrupt 48 unpend #define NVIC_UNPEND1_INT49 0x00020000 // Interrupt 49 unpend #define NVIC_UNPEND1_INT50 0x00040000 // Interrupt 50 unpend #define NVIC_UNPEND1_INT51 0x00080000 // Interrupt 51 unpend #define NVIC_UNPEND1_INT52 0x00100000 // Interrupt 52 unpend #define NVIC_UNPEND1_INT53 0x00200000 // Interrupt 53 unpend #define NVIC_UNPEND1_INT54 0x00400000 // Interrupt 54 unpend #define NVIC_UNPEND1_INT55 0x00800000 // Interrupt 55 unpend //***************************************************************************** // // The following are defines for the bit fields in the NVIC_UNPEND2 register. // //***************************************************************************** #define NVIC_UNPEND2_INT_M 0xFFFFFFFF // Interrupt Clear Pending //***************************************************************************** // // The following are defines for the bit fields in the NVIC_UNPEND3 register. // //***************************************************************************** #define NVIC_UNPEND3_INT_M 0xFFFFFFFF // Interrupt Clear Pending //***************************************************************************** // // The following are defines for the bit fields in the NVIC_UNPEND4 register. // //***************************************************************************** #define NVIC_UNPEND4_INT_M 0x0000000F // Interrupt Clear Pending //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ACTIVE0 register. // //***************************************************************************** #define NVIC_ACTIVE0_INT_M 0xFFFFFFFF // Interrupt Active #define NVIC_ACTIVE0_INT0 0x00000001 // Interrupt 0 active #define NVIC_ACTIVE0_INT1 0x00000002 // Interrupt 1 active #define NVIC_ACTIVE0_INT2 0x00000004 // Interrupt 2 active #define NVIC_ACTIVE0_INT3 0x00000008 // Interrupt 3 active #define NVIC_ACTIVE0_INT4 0x00000010 // Interrupt 4 active #define NVIC_ACTIVE0_INT5 0x00000020 // Interrupt 5 active #define NVIC_ACTIVE0_INT6 0x00000040 // Interrupt 6 active #define NVIC_ACTIVE0_INT7 0x00000080 // Interrupt 7 active #define NVIC_ACTIVE0_INT8 0x00000100 // Interrupt 8 active #define NVIC_ACTIVE0_INT9 0x00000200 // Interrupt 9 active #define NVIC_ACTIVE0_INT10 0x00000400 // Interrupt 10 active #define NVIC_ACTIVE0_INT11 0x00000800 // Interrupt 11 active #define NVIC_ACTIVE0_INT12 0x00001000 // Interrupt 12 active #define NVIC_ACTIVE0_INT13 0x00002000 // Interrupt 13 active #define NVIC_ACTIVE0_INT14 0x00004000 // Interrupt 14 active #define NVIC_ACTIVE0_INT15 0x00008000 // Interrupt 15 active #define NVIC_ACTIVE0_INT16 0x00010000 // Interrupt 16 active #define NVIC_ACTIVE0_INT17 0x00020000 // Interrupt 17 active #define NVIC_ACTIVE0_INT18 0x00040000 // Interrupt 18 active #define NVIC_ACTIVE0_INT19 0x00080000 // Interrupt 19 active #define NVIC_ACTIVE0_INT20 0x00100000 // Interrupt 20 active #define NVIC_ACTIVE0_INT21 0x00200000 // Interrupt 21 active #define NVIC_ACTIVE0_INT22 0x00400000 // Interrupt 22 active #define NVIC_ACTIVE0_INT23 0x00800000 // Interrupt 23 active #define NVIC_ACTIVE0_INT24 0x01000000 // Interrupt 24 active #define NVIC_ACTIVE0_INT25 0x02000000 // Interrupt 25 active #define NVIC_ACTIVE0_INT26 0x04000000 // Interrupt 26 active #define NVIC_ACTIVE0_INT27 0x08000000 // Interrupt 27 active #define NVIC_ACTIVE0_INT28 0x10000000 // Interrupt 28 active #define NVIC_ACTIVE0_INT29 0x20000000 // Interrupt 29 active #define NVIC_ACTIVE0_INT30 0x40000000 // Interrupt 30 active #define NVIC_ACTIVE0_INT31 0x80000000 // Interrupt 31 active //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ACTIVE1 register. // //***************************************************************************** #define NVIC_ACTIVE1_INT_M 0x00FFFFFF // Interrupt Active #undef NVIC_ACTIVE1_INT_M #define NVIC_ACTIVE1_INT_M 0xFFFFFFFF // Interrupt Active #define NVIC_ACTIVE1_INT32 0x00000001 // Interrupt 32 active #define NVIC_ACTIVE1_INT33 0x00000002 // Interrupt 33 active #define NVIC_ACTIVE1_INT34 0x00000004 // Interrupt 34 active #define NVIC_ACTIVE1_INT35 0x00000008 // Interrupt 35 active #define NVIC_ACTIVE1_INT36 0x00000010 // Interrupt 36 active #define NVIC_ACTIVE1_INT37 0x00000020 // Interrupt 37 active #define NVIC_ACTIVE1_INT38 0x00000040 // Interrupt 38 active #define NVIC_ACTIVE1_INT39 0x00000080 // Interrupt 39 active #define NVIC_ACTIVE1_INT40 0x00000100 // Interrupt 40 active #define NVIC_ACTIVE1_INT41 0x00000200 // Interrupt 41 active #define NVIC_ACTIVE1_INT42 0x00000400 // Interrupt 42 active #define NVIC_ACTIVE1_INT43 0x00000800 // Interrupt 43 active #define NVIC_ACTIVE1_INT44 0x00001000 // Interrupt 44 active #define NVIC_ACTIVE1_INT45 0x00002000 // Interrupt 45 active #define NVIC_ACTIVE1_INT46 0x00004000 // Interrupt 46 active #define NVIC_ACTIVE1_INT47 0x00008000 // Interrupt 47 active #define NVIC_ACTIVE1_INT48 0x00010000 // Interrupt 48 active #define NVIC_ACTIVE1_INT49 0x00020000 // Interrupt 49 active #define NVIC_ACTIVE1_INT50 0x00040000 // Interrupt 50 active #define NVIC_ACTIVE1_INT51 0x00080000 // Interrupt 51 active #define NVIC_ACTIVE1_INT52 0x00100000 // Interrupt 52 active #define NVIC_ACTIVE1_INT53 0x00200000 // Interrupt 53 active #define NVIC_ACTIVE1_INT54 0x00400000 // Interrupt 54 active #define NVIC_ACTIVE1_INT55 0x00800000 // Interrupt 55 active //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ACTIVE2 register. // //***************************************************************************** #define NVIC_ACTIVE2_INT_M 0xFFFFFFFF // Interrupt Active //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ACTIVE3 register. // //***************************************************************************** #define NVIC_ACTIVE3_INT_M 0xFFFFFFFF // Interrupt Active //***************************************************************************** // // The following are defines for the bit fields in the NVIC_ACTIVE4 register. // //***************************************************************************** #define NVIC_ACTIVE4_INT_M 0x0000000F // Interrupt Active //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI0 register. // //***************************************************************************** #define NVIC_PRI0_INT3_M 0xE0000000 // Interrupt 3 Priority Mask #define NVIC_PRI0_INT2_M 0x00E00000 // Interrupt 2 Priority Mask #define NVIC_PRI0_INT1_M 0x0000E000 // Interrupt 1 Priority Mask #define NVIC_PRI0_INT0_M 0x000000E0 // Interrupt 0 Priority Mask #define NVIC_PRI0_INT3_S 29 #define NVIC_PRI0_INT2_S 21 #define NVIC_PRI0_INT1_S 13 #define NVIC_PRI0_INT0_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI1 register. // //***************************************************************************** #define NVIC_PRI1_INT7_M 0xE0000000 // Interrupt 7 Priority Mask #define NVIC_PRI1_INT6_M 0x00E00000 // Interrupt 6 Priority Mask #define NVIC_PRI1_INT5_M 0x0000E000 // Interrupt 5 Priority Mask #define NVIC_PRI1_INT4_M 0x000000E0 // Interrupt 4 Priority Mask #define NVIC_PRI1_INT7_S 29 #define NVIC_PRI1_INT6_S 21 #define NVIC_PRI1_INT5_S 13 #define NVIC_PRI1_INT4_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI2 register. // //***************************************************************************** #define NVIC_PRI2_INT11_M 0xE0000000 // Interrupt 11 Priority Mask #define NVIC_PRI2_INT10_M 0x00E00000 // Interrupt 10 Priority Mask #define NVIC_PRI2_INT9_M 0x0000E000 // Interrupt 9 Priority Mask #define NVIC_PRI2_INT8_M 0x000000E0 // Interrupt 8 Priority Mask #define NVIC_PRI2_INT11_S 29 #define NVIC_PRI2_INT10_S 21 #define NVIC_PRI2_INT9_S 13 #define NVIC_PRI2_INT8_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI3 register. // //***************************************************************************** #define NVIC_PRI3_INT15_M 0xE0000000 // Interrupt 15 Priority Mask #define NVIC_PRI3_INT14_M 0x00E00000 // Interrupt 14 Priority Mask #define NVIC_PRI3_INT13_M 0x0000E000 // Interrupt 13 Priority Mask #define NVIC_PRI3_INT12_M 0x000000E0 // Interrupt 12 Priority Mask #define NVIC_PRI3_INT15_S 29 #define NVIC_PRI3_INT14_S 21 #define NVIC_PRI3_INT13_S 13 #define NVIC_PRI3_INT12_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI4 register. // //***************************************************************************** #define NVIC_PRI4_INT19_M 0xE0000000 // Interrupt 19 Priority Mask #define NVIC_PRI4_INT18_M 0x00E00000 // Interrupt 18 Priority Mask #define NVIC_PRI4_INT17_M 0x0000E000 // Interrupt 17 Priority Mask #define NVIC_PRI4_INT16_M 0x000000E0 // Interrupt 16 Priority Mask #define NVIC_PRI4_INT19_S 29 #define NVIC_PRI4_INT18_S 21 #define NVIC_PRI4_INT17_S 13 #define NVIC_PRI4_INT16_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI5 register. // //***************************************************************************** #define NVIC_PRI5_INT23_M 0xE0000000 // Interrupt 23 Priority Mask #define NVIC_PRI5_INT22_M 0x00E00000 // Interrupt 22 Priority Mask #define NVIC_PRI5_INT21_M 0x0000E000 // Interrupt 21 Priority Mask #define NVIC_PRI5_INT20_M 0x000000E0 // Interrupt 20 Priority Mask #define NVIC_PRI5_INT23_S 29 #define NVIC_PRI5_INT22_S 21 #define NVIC_PRI5_INT21_S 13 #define NVIC_PRI5_INT20_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI6 register. // //***************************************************************************** #define NVIC_PRI6_INT27_M 0xE0000000 // Interrupt 27 Priority Mask #define NVIC_PRI6_INT26_M 0x00E00000 // Interrupt 26 Priority Mask #define NVIC_PRI6_INT25_M 0x0000E000 // Interrupt 25 Priority Mask #define NVIC_PRI6_INT24_M 0x000000E0 // Interrupt 24 Priority Mask #define NVIC_PRI6_INT27_S 29 #define NVIC_PRI6_INT26_S 21 #define NVIC_PRI6_INT25_S 13 #define NVIC_PRI6_INT24_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI7 register. // //***************************************************************************** #define NVIC_PRI7_INT31_M 0xE0000000 // Interrupt 31 Priority Mask #define NVIC_PRI7_INT30_M 0x00E00000 // Interrupt 30 Priority Mask #define NVIC_PRI7_INT29_M 0x0000E000 // Interrupt 29 Priority Mask #define NVIC_PRI7_INT28_M 0x000000E0 // Interrupt 28 Priority Mask #define NVIC_PRI7_INT31_S 29 #define NVIC_PRI7_INT30_S 21 #define NVIC_PRI7_INT29_S 13 #define NVIC_PRI7_INT28_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI8 register. // //***************************************************************************** #define NVIC_PRI8_INT35_M 0xE0000000 // Interrupt 35 Priority Mask #define NVIC_PRI8_INT34_M 0x00E00000 // Interrupt 34 Priority Mask #define NVIC_PRI8_INT33_M 0x0000E000 // Interrupt 33 Priority Mask #define NVIC_PRI8_INT32_M 0x000000E0 // Interrupt 32 Priority Mask #define NVIC_PRI8_INT35_S 29 #define NVIC_PRI8_INT34_S 21 #define NVIC_PRI8_INT33_S 13 #define NVIC_PRI8_INT32_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI9 register. // //***************************************************************************** #define NVIC_PRI9_INT39_M 0xE0000000 // Interrupt 39 Priority Mask #define NVIC_PRI9_INT38_M 0x00E00000 // Interrupt 38 Priority Mask #define NVIC_PRI9_INT37_M 0x0000E000 // Interrupt 37 Priority Mask #define NVIC_PRI9_INT36_M 0x000000E0 // Interrupt 36 Priority Mask #define NVIC_PRI9_INT39_S 29 #define NVIC_PRI9_INT38_S 21 #define NVIC_PRI9_INT37_S 13 #define NVIC_PRI9_INT36_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI10 register. // //***************************************************************************** #define NVIC_PRI10_INT43_M 0xE0000000 // Interrupt 43 Priority Mask #define NVIC_PRI10_INT42_M 0x00E00000 // Interrupt 42 Priority Mask #define NVIC_PRI10_INT41_M 0x0000E000 // Interrupt 41 Priority Mask #define NVIC_PRI10_INT40_M 0x000000E0 // Interrupt 40 Priority Mask #define NVIC_PRI10_INT43_S 29 #define NVIC_PRI10_INT42_S 21 #define NVIC_PRI10_INT41_S 13 #define NVIC_PRI10_INT40_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI11 register. // //***************************************************************************** #define NVIC_PRI11_INT47_M 0xE0000000 // Interrupt 47 Priority Mask #define NVIC_PRI11_INT46_M 0x00E00000 // Interrupt 46 Priority Mask #define NVIC_PRI11_INT45_M 0x0000E000 // Interrupt 45 Priority Mask #define NVIC_PRI11_INT44_M 0x000000E0 // Interrupt 44 Priority Mask #define NVIC_PRI11_INT47_S 29 #define NVIC_PRI11_INT46_S 21 #define NVIC_PRI11_INT45_S 13 #define NVIC_PRI11_INT44_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI12 register. // //***************************************************************************** #define NVIC_PRI12_INT51_M 0xE0000000 // Interrupt 51 Priority Mask #define NVIC_PRI12_INT50_M 0x00E00000 // Interrupt 50 Priority Mask #define NVIC_PRI12_INT49_M 0x0000E000 // Interrupt 49 Priority Mask #define NVIC_PRI12_INT48_M 0x000000E0 // Interrupt 48 Priority Mask #define NVIC_PRI12_INT51_S 29 #define NVIC_PRI12_INT50_S 21 #define NVIC_PRI12_INT49_S 13 #define NVIC_PRI12_INT48_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI13 register. // //***************************************************************************** #define NVIC_PRI13_INT55_M 0xE0000000 // Interrupt 55 Priority Mask #define NVIC_PRI13_INT54_M 0x00E00000 // Interrupt 54 Priority Mask #define NVIC_PRI13_INT53_M 0x0000E000 // Interrupt 53 Priority Mask #define NVIC_PRI13_INT52_M 0x000000E0 // Interrupt 52 Priority Mask #define NVIC_PRI13_INT55_S 29 #define NVIC_PRI13_INT54_S 21 #define NVIC_PRI13_INT53_S 13 #define NVIC_PRI13_INT52_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI14 register. // //***************************************************************************** #define NVIC_PRI14_INTD_M 0xE0000000 // Interrupt 59 Priority Mask #define NVIC_PRI14_INTC_M 0x00E00000 // Interrupt 58 Priority Mask #define NVIC_PRI14_INTB_M 0x0000E000 // Interrupt 57 Priority Mask #define NVIC_PRI14_INTA_M 0x000000E0 // Interrupt 56 Priority Mask #define NVIC_PRI14_INTD_S 29 #define NVIC_PRI14_INTC_S 21 #define NVIC_PRI14_INTB_S 13 #define NVIC_PRI14_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI15 register. // //***************************************************************************** #define NVIC_PRI15_INTD_M 0xE0000000 // Interrupt 63 Priority Mask #define NVIC_PRI15_INTC_M 0x00E00000 // Interrupt 62 Priority Mask #define NVIC_PRI15_INTB_M 0x0000E000 // Interrupt 61 Priority Mask #define NVIC_PRI15_INTA_M 0x000000E0 // Interrupt 60 Priority Mask #define NVIC_PRI15_INTD_S 29 #define NVIC_PRI15_INTC_S 21 #define NVIC_PRI15_INTB_S 13 #define NVIC_PRI15_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI16 register. // //***************************************************************************** #define NVIC_PRI16_INTD_M 0xE0000000 // Interrupt 67 Priority Mask #define NVIC_PRI16_INTC_M 0x00E00000 // Interrupt 66 Priority Mask #define NVIC_PRI16_INTB_M 0x0000E000 // Interrupt 65 Priority Mask #define NVIC_PRI16_INTA_M 0x000000E0 // Interrupt 64 Priority Mask #define NVIC_PRI16_INTD_S 29 #define NVIC_PRI16_INTC_S 21 #define NVIC_PRI16_INTB_S 13 #define NVIC_PRI16_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI17 register. // //***************************************************************************** #define NVIC_PRI17_INTD_M 0xE0000000 // Interrupt 71 Priority Mask #define NVIC_PRI17_INTC_M 0x00E00000 // Interrupt 70 Priority Mask #define NVIC_PRI17_INTB_M 0x0000E000 // Interrupt 69 Priority Mask #define NVIC_PRI17_INTA_M 0x000000E0 // Interrupt 68 Priority Mask #define NVIC_PRI17_INTD_S 29 #define NVIC_PRI17_INTC_S 21 #define NVIC_PRI17_INTB_S 13 #define NVIC_PRI17_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI18 register. // //***************************************************************************** #define NVIC_PRI18_INTD_M 0xE0000000 // Interrupt 75 Priority Mask #define NVIC_PRI18_INTC_M 0x00E00000 // Interrupt 74 Priority Mask #define NVIC_PRI18_INTB_M 0x0000E000 // Interrupt 73 Priority Mask #define NVIC_PRI18_INTA_M 0x000000E0 // Interrupt 72 Priority Mask #define NVIC_PRI18_INTD_S 29 #define NVIC_PRI18_INTC_S 21 #define NVIC_PRI18_INTB_S 13 #define NVIC_PRI18_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI19 register. // //***************************************************************************** #define NVIC_PRI19_INTD_M 0xE0000000 // Interrupt 79 Priority Mask #define NVIC_PRI19_INTC_M 0x00E00000 // Interrupt 78 Priority Mask #define NVIC_PRI19_INTB_M 0x0000E000 // Interrupt 77 Priority Mask #define NVIC_PRI19_INTA_M 0x000000E0 // Interrupt 76 Priority Mask #define NVIC_PRI19_INTD_S 29 #define NVIC_PRI19_INTC_S 21 #define NVIC_PRI19_INTB_S 13 #define NVIC_PRI19_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI20 register. // //***************************************************************************** #define NVIC_PRI20_INTD_M 0xE0000000 // Interrupt 83 Priority Mask #define NVIC_PRI20_INTC_M 0x00E00000 // Interrupt 82 Priority Mask #define NVIC_PRI20_INTB_M 0x0000E000 // Interrupt 81 Priority Mask #define NVIC_PRI20_INTA_M 0x000000E0 // Interrupt 80 Priority Mask #define NVIC_PRI20_INTD_S 29 #define NVIC_PRI20_INTC_S 21 #define NVIC_PRI20_INTB_S 13 #define NVIC_PRI20_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI21 register. // //***************************************************************************** #define NVIC_PRI21_INTD_M 0xE0000000 // Interrupt 87 Priority Mask #define NVIC_PRI21_INTC_M 0x00E00000 // Interrupt 86 Priority Mask #define NVIC_PRI21_INTB_M 0x0000E000 // Interrupt 85 Priority Mask #define NVIC_PRI21_INTA_M 0x000000E0 // Interrupt 84 Priority Mask #define NVIC_PRI21_INTD_S 29 #define NVIC_PRI21_INTC_S 21 #define NVIC_PRI21_INTB_S 13 #define NVIC_PRI21_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI22 register. // //***************************************************************************** #define NVIC_PRI22_INTD_M 0xE0000000 // Interrupt 91 Priority Mask #define NVIC_PRI22_INTC_M 0x00E00000 // Interrupt 90 Priority Mask #define NVIC_PRI22_INTB_M 0x0000E000 // Interrupt 89 Priority Mask #define NVIC_PRI22_INTA_M 0x000000E0 // Interrupt 88 Priority Mask #define NVIC_PRI22_INTD_S 29 #define NVIC_PRI22_INTC_S 21 #define NVIC_PRI22_INTB_S 13 #define NVIC_PRI22_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI23 register. // //***************************************************************************** #define NVIC_PRI23_INTD_M 0xE0000000 // Interrupt 95 Priority Mask #define NVIC_PRI23_INTC_M 0x00E00000 // Interrupt 94 Priority Mask #define NVIC_PRI23_INTB_M 0x0000E000 // Interrupt 93 Priority Mask #define NVIC_PRI23_INTA_M 0x000000E0 // Interrupt 92 Priority Mask #define NVIC_PRI23_INTD_S 29 #define NVIC_PRI23_INTC_S 21 #define NVIC_PRI23_INTB_S 13 #define NVIC_PRI23_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI24 register. // //***************************************************************************** #define NVIC_PRI24_INTD_M 0xE0000000 // Interrupt 99 Priority Mask #define NVIC_PRI24_INTC_M 0x00E00000 // Interrupt 98 Priority Mask #define NVIC_PRI24_INTB_M 0x0000E000 // Interrupt 97 Priority Mask #define NVIC_PRI24_INTA_M 0x000000E0 // Interrupt 96 Priority Mask #define NVIC_PRI24_INTD_S 29 #define NVIC_PRI24_INTC_S 21 #define NVIC_PRI24_INTB_S 13 #define NVIC_PRI24_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI25 register. // //***************************************************************************** #define NVIC_PRI25_INTD_M 0xE0000000 // Interrupt 103 Priority Mask #define NVIC_PRI25_INTC_M 0x00E00000 // Interrupt 102 Priority Mask #define NVIC_PRI25_INTB_M 0x0000E000 // Interrupt 101 Priority Mask #define NVIC_PRI25_INTA_M 0x000000E0 // Interrupt 100 Priority Mask #define NVIC_PRI25_INTD_S 29 #define NVIC_PRI25_INTC_S 21 #define NVIC_PRI25_INTB_S 13 #define NVIC_PRI25_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI26 register. // //***************************************************************************** #define NVIC_PRI26_INTD_M 0xE0000000 // Interrupt 107 Priority Mask #define NVIC_PRI26_INTC_M 0x00E00000 // Interrupt 106 Priority Mask #define NVIC_PRI26_INTB_M 0x0000E000 // Interrupt 105 Priority Mask #define NVIC_PRI26_INTA_M 0x000000E0 // Interrupt 104 Priority Mask #define NVIC_PRI26_INTD_S 29 #define NVIC_PRI26_INTC_S 21 #define NVIC_PRI26_INTB_S 13 #define NVIC_PRI26_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI27 register. // //***************************************************************************** #define NVIC_PRI27_INTD_M 0xE0000000 // Interrupt 111 Priority Mask #define NVIC_PRI27_INTC_M 0x00E00000 // Interrupt 110 Priority Mask #define NVIC_PRI27_INTB_M 0x0000E000 // Interrupt 109 Priority Mask #define NVIC_PRI27_INTA_M 0x000000E0 // Interrupt 108 Priority Mask #define NVIC_PRI27_INTD_S 29 #define NVIC_PRI27_INTC_S 21 #define NVIC_PRI27_INTB_S 13 #define NVIC_PRI27_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI28 register. // //***************************************************************************** #define NVIC_PRI28_INTD_M 0xE0000000 // Interrupt 115 Priority Mask #define NVIC_PRI28_INTC_M 0x00E00000 // Interrupt 114 Priority Mask #define NVIC_PRI28_INTB_M 0x0000E000 // Interrupt 113 Priority Mask #define NVIC_PRI28_INTA_M 0x000000E0 // Interrupt 112 Priority Mask #define NVIC_PRI28_INTD_S 29 #define NVIC_PRI28_INTC_S 21 #define NVIC_PRI28_INTB_S 13 #define NVIC_PRI28_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI29 register. // //***************************************************************************** #define NVIC_PRI29_INTD_M 0xE0000000 // Interrupt 119 Priority Mask #define NVIC_PRI29_INTC_M 0x00E00000 // Interrupt 118 Priority Mask #define NVIC_PRI29_INTB_M 0x0000E000 // Interrupt 117 Priority Mask #define NVIC_PRI29_INTA_M 0x000000E0 // Interrupt 116 Priority Mask #define NVIC_PRI29_INTD_S 29 #define NVIC_PRI29_INTC_S 21 #define NVIC_PRI29_INTB_S 13 #define NVIC_PRI29_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI30 register. // //***************************************************************************** #define NVIC_PRI30_INTD_M 0xE0000000 // Interrupt 123 Priority Mask #define NVIC_PRI30_INTC_M 0x00E00000 // Interrupt 122 Priority Mask #define NVIC_PRI30_INTB_M 0x0000E000 // Interrupt 121 Priority Mask #define NVIC_PRI30_INTA_M 0x000000E0 // Interrupt 120 Priority Mask #define NVIC_PRI30_INTD_S 29 #define NVIC_PRI30_INTC_S 21 #define NVIC_PRI30_INTB_S 13 #define NVIC_PRI30_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI31 register. // //***************************************************************************** #define NVIC_PRI31_INTD_M 0xE0000000 // Interrupt 127 Priority Mask #define NVIC_PRI31_INTC_M 0x00E00000 // Interrupt 126 Priority Mask #define NVIC_PRI31_INTB_M 0x0000E000 // Interrupt 125 Priority Mask #define NVIC_PRI31_INTA_M 0x000000E0 // Interrupt 124 Priority Mask #define NVIC_PRI31_INTD_S 29 #define NVIC_PRI31_INTC_S 21 #define NVIC_PRI31_INTB_S 13 #define NVIC_PRI31_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_PRI32 register. // //***************************************************************************** #define NVIC_PRI32_INTD_M 0xE0000000 // Interrupt 131 Priority Mask #define NVIC_PRI32_INTC_M 0x00E00000 // Interrupt 130 Priority Mask #define NVIC_PRI32_INTB_M 0x0000E000 // Interrupt 129 Priority Mask #define NVIC_PRI32_INTA_M 0x000000E0 // Interrupt 128 Priority Mask #define NVIC_PRI32_INTD_S 29 #define NVIC_PRI32_INTC_S 21 #define NVIC_PRI32_INTB_S 13 #define NVIC_PRI32_INTA_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_CPUID register. // //***************************************************************************** #define NVIC_CPUID_IMP_M 0xFF000000 // Implementer Code #define NVIC_CPUID_IMP_ARM 0x41000000 // ARM #define NVIC_CPUID_VAR_M 0x00F00000 // Variant Number #define NVIC_CPUID_CON_M 0x000F0000 // Constant #define NVIC_CPUID_PARTNO_M 0x0000FFF0 // Part Number #define NVIC_CPUID_PARTNO_CM3 0x0000C230 // Cortex-M3 processor #define NVIC_CPUID_PARTNO_CM4 0x0000C240 // Cortex-M4 processor #define NVIC_CPUID_REV_M 0x0000000F // Revision Number //***************************************************************************** // // The following are defines for the bit fields in the NVIC_INT_CTRL register. // //***************************************************************************** #define NVIC_INT_CTRL_NMI_SET 0x80000000 // NMI Set Pending #define NVIC_INT_CTRL_PEND_SV 0x10000000 // PendSV Set Pending #define NVIC_INT_CTRL_UNPEND_SV 0x08000000 // PendSV Clear Pending #define NVIC_INT_CTRL_PENDSTSET 0x04000000 // SysTick Set Pending #define NVIC_INT_CTRL_PENDSTCLR 0x02000000 // SysTick Clear Pending #define NVIC_INT_CTRL_ISR_PRE 0x00800000 // Debug Interrupt Handling #define NVIC_INT_CTRL_ISR_PEND 0x00400000 // Interrupt Pending #define NVIC_INT_CTRL_VEC_PEN_M 0x0007F000 // Interrupt Pending Vector Number #undef NVIC_INT_CTRL_VEC_PEN_M #define NVIC_INT_CTRL_VEC_PEN_M 0x000FF000 // Interrupt Pending Vector Number #define NVIC_INT_CTRL_VEC_PEN_NMI \ 0x00002000 // NMI #define NVIC_INT_CTRL_VEC_PEN_HARD \ 0x00003000 // Hard fault #define NVIC_INT_CTRL_VEC_PEN_MEM \ 0x00004000 // Memory management fault #define NVIC_INT_CTRL_VEC_PEN_BUS \ 0x00005000 // Bus fault #define NVIC_INT_CTRL_VEC_PEN_USG \ 0x00006000 // Usage fault #define NVIC_INT_CTRL_VEC_PEN_SVC \ 0x0000B000 // SVCall #define NVIC_INT_CTRL_VEC_PEN_PNDSV \ 0x0000E000 // PendSV #define NVIC_INT_CTRL_VEC_PEN_TICK \ 0x0000F000 // SysTick #define NVIC_INT_CTRL_RET_BASE 0x00000800 // Return to Base #define NVIC_INT_CTRL_VEC_ACT_M 0x0000007F // Interrupt Pending Vector Number #undef NVIC_INT_CTRL_VEC_ACT_M #define NVIC_INT_CTRL_VEC_ACT_M 0x000000FF // Interrupt Pending Vector Number #define NVIC_INT_CTRL_VEC_PEN_S 12 #define NVIC_INT_CTRL_VEC_ACT_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_VTABLE register. // //***************************************************************************** #define NVIC_VTABLE_BASE 0x20000000 // Vector Table Base #define NVIC_VTABLE_OFFSET_M 0x1FFFFE00 // Vector Table Offset #undef NVIC_VTABLE_OFFSET_M #define NVIC_VTABLE_OFFSET_M 0x1FFFFC00 // Vector Table Offset #define NVIC_VTABLE_OFFSET_S 9 #undef NVIC_VTABLE_OFFSET_S #define NVIC_VTABLE_OFFSET_S 10 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_APINT register. // //***************************************************************************** #define NVIC_APINT_VECTKEY_M 0xFFFF0000 // Register Key #define NVIC_APINT_VECTKEY 0x05FA0000 // Vector key #define NVIC_APINT_ENDIANESS 0x00008000 // Data Endianess #define NVIC_APINT_PRIGROUP_M 0x00000700 // Interrupt Priority Grouping #define NVIC_APINT_PRIGROUP_7_1 0x00000000 // Priority group 7.1 split #define NVIC_APINT_PRIGROUP_6_2 0x00000100 // Priority group 6.2 split #define NVIC_APINT_PRIGROUP_5_3 0x00000200 // Priority group 5.3 split #define NVIC_APINT_PRIGROUP_4_4 0x00000300 // Priority group 4.4 split #define NVIC_APINT_PRIGROUP_3_5 0x00000400 // Priority group 3.5 split #define NVIC_APINT_PRIGROUP_2_6 0x00000500 // Priority group 2.6 split #define NVIC_APINT_PRIGROUP_1_7 0x00000600 // Priority group 1.7 split #define NVIC_APINT_PRIGROUP_0_8 0x00000700 // Priority group 0.8 split #define NVIC_APINT_SYSRESETREQ 0x00000004 // System Reset Request #define NVIC_APINT_VECT_CLR_ACT 0x00000002 // Clear Active NMI / Fault #define NVIC_APINT_VECT_RESET 0x00000001 // System Reset //***************************************************************************** // // The following are defines for the bit fields in the NVIC_SYS_CTRL register. // //***************************************************************************** #define NVIC_SYS_CTRL_SEVONPEND 0x00000010 // Wake Up on Pending #define NVIC_SYS_CTRL_SLEEPDEEP 0x00000004 // Deep Sleep Enable #define NVIC_SYS_CTRL_SLEEPEXIT 0x00000002 // Sleep on ISR Exit //***************************************************************************** // // The following are defines for the bit fields in the NVIC_CFG_CTRL register. // //***************************************************************************** #define NVIC_CFG_CTRL_STKALIGN 0x00000200 // Stack Alignment on Exception // Entry #define NVIC_CFG_CTRL_BFHFNMIGN 0x00000100 // Ignore Bus Fault in NMI and // Fault #define NVIC_CFG_CTRL_DIV0 0x00000010 // Trap on Divide by 0 #define NVIC_CFG_CTRL_UNALIGNED 0x00000008 // Trap on Unaligned Access #define NVIC_CFG_CTRL_MAIN_PEND 0x00000002 // Allow Main Interrupt Trigger #define NVIC_CFG_CTRL_BASE_THR 0x00000001 // Thread State Control //***************************************************************************** // // The following are defines for the bit fields in the NVIC_SYS_PRI1 register. // //***************************************************************************** #define NVIC_SYS_PRI1_USAGE_M 0x00E00000 // Usage Fault Priority #define NVIC_SYS_PRI1_BUS_M 0x0000E000 // Bus Fault Priority #define NVIC_SYS_PRI1_MEM_M 0x000000E0 // Memory Management Fault Priority #define NVIC_SYS_PRI1_USAGE_S 21 #define NVIC_SYS_PRI1_BUS_S 13 #define NVIC_SYS_PRI1_MEM_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_SYS_PRI2 register. // //***************************************************************************** #define NVIC_SYS_PRI2_SVC_M 0xE0000000 // SVCall Priority #define NVIC_SYS_PRI2_SVC_S 29 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_SYS_PRI3 register. // //***************************************************************************** #define NVIC_SYS_PRI3_TICK_M 0xE0000000 // SysTick Exception Priority #define NVIC_SYS_PRI3_PENDSV_M 0x00E00000 // PendSV Priority #define NVIC_SYS_PRI3_DEBUG_M 0x000000E0 // Debug Priority #define NVIC_SYS_PRI3_TICK_S 29 #define NVIC_SYS_PRI3_PENDSV_S 21 #define NVIC_SYS_PRI3_DEBUG_S 5 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_SYS_HND_CTRL // register. // //***************************************************************************** #define NVIC_SYS_HND_CTRL_USAGE 0x00040000 // Usage Fault Enable #define NVIC_SYS_HND_CTRL_BUS 0x00020000 // Bus Fault Enable #define NVIC_SYS_HND_CTRL_MEM 0x00010000 // Memory Management Fault Enable #define NVIC_SYS_HND_CTRL_SVC 0x00008000 // SVC Call Pending #define NVIC_SYS_HND_CTRL_BUSP 0x00004000 // Bus Fault Pending #define NVIC_SYS_HND_CTRL_MEMP 0x00002000 // Memory Management Fault Pending #define NVIC_SYS_HND_CTRL_USAGEP \ 0x00001000 // Usage Fault Pending #define NVIC_SYS_HND_CTRL_TICK 0x00000800 // SysTick Exception Active #define NVIC_SYS_HND_CTRL_PNDSV 0x00000400 // PendSV Exception Active #define NVIC_SYS_HND_CTRL_MON 0x00000100 // Debug Monitor Active #define NVIC_SYS_HND_CTRL_SVCA 0x00000080 // SVC Call Active #define NVIC_SYS_HND_CTRL_USGA 0x00000008 // Usage Fault Active #define NVIC_SYS_HND_CTRL_BUSA 0x00000002 // Bus Fault Active #define NVIC_SYS_HND_CTRL_MEMA 0x00000001 // Memory Management Fault Active //***************************************************************************** // // The following are defines for the bit fields in the NVIC_FAULT_STAT // register. // //***************************************************************************** #define NVIC_FAULT_STAT_DIV0 0x02000000 // Divide-by-Zero Usage Fault #define NVIC_FAULT_STAT_UNALIGN 0x01000000 // Unaligned Access Usage Fault #define NVIC_FAULT_STAT_NOCP 0x00080000 // No Coprocessor Usage Fault #define NVIC_FAULT_STAT_INVPC 0x00040000 // Invalid PC Load Usage Fault #define NVIC_FAULT_STAT_INVSTAT 0x00020000 // Invalid State Usage Fault #define NVIC_FAULT_STAT_UNDEF 0x00010000 // Undefined Instruction Usage // Fault #define NVIC_FAULT_STAT_BFARV 0x00008000 // Bus Fault Address Register Valid #define NVIC_FAULT_STAT_BLSPERR 0x00002000 // Bus Fault on Floating-Point Lazy // State Preservation #define NVIC_FAULT_STAT_BSTKE 0x00001000 // Stack Bus Fault #define NVIC_FAULT_STAT_BUSTKE 0x00000800 // Unstack Bus Fault #define NVIC_FAULT_STAT_IMPRE 0x00000400 // Imprecise Data Bus Error #define NVIC_FAULT_STAT_PRECISE 0x00000200 // Precise Data Bus Error #define NVIC_FAULT_STAT_IBUS 0x00000100 // Instruction Bus Error #define NVIC_FAULT_STAT_MMARV 0x00000080 // Memory Management Fault Address // Register Valid #define NVIC_FAULT_STAT_MLSPERR 0x00000020 // Memory Management Fault on // Floating-Point Lazy State // Preservation #define NVIC_FAULT_STAT_MSTKE 0x00000010 // Stack Access Violation #define NVIC_FAULT_STAT_MUSTKE 0x00000008 // Unstack Access Violation #define NVIC_FAULT_STAT_DERR 0x00000002 // Data Access Violation #define NVIC_FAULT_STAT_IERR 0x00000001 // Instruction Access Violation //***************************************************************************** // // The following are defines for the bit fields in the NVIC_HFAULT_STAT // register. // //***************************************************************************** #define NVIC_HFAULT_STAT_DBG 0x80000000 // Debug Event #define NVIC_HFAULT_STAT_FORCED 0x40000000 // Forced Hard Fault #define NVIC_HFAULT_STAT_VECT 0x00000002 // Vector Table Read Fault //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DEBUG_STAT // register. // //***************************************************************************** #define NVIC_DEBUG_STAT_EXTRNL 0x00000010 // EDBGRQ asserted #define NVIC_DEBUG_STAT_VCATCH 0x00000008 // Vector catch #define NVIC_DEBUG_STAT_DWTTRAP 0x00000004 // DWT match #define NVIC_DEBUG_STAT_BKPT 0x00000002 // Breakpoint instruction #define NVIC_DEBUG_STAT_HALTED 0x00000001 // Halt request //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MM_ADDR register. // //***************************************************************************** #define NVIC_MM_ADDR_M 0xFFFFFFFF // Fault Address #define NVIC_MM_ADDR_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_FAULT_ADDR // register. // //***************************************************************************** #define NVIC_FAULT_ADDR_M 0xFFFFFFFF // Fault Address #define NVIC_FAULT_ADDR_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_TYPE register. // //***************************************************************************** #define NVIC_MPU_TYPE_IREGION_M 0x00FF0000 // Number of I Regions #define NVIC_MPU_TYPE_DREGION_M 0x0000FF00 // Number of D Regions #define NVIC_MPU_TYPE_SEPARATE 0x00000001 // Separate or Unified MPU #define NVIC_MPU_TYPE_IREGION_S 16 #define NVIC_MPU_TYPE_DREGION_S 8 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_CTRL register. // //***************************************************************************** #define NVIC_MPU_CTRL_PRIVDEFEN 0x00000004 // MPU Default Region #define NVIC_MPU_CTRL_HFNMIENA 0x00000002 // MPU Enabled During Faults #define NVIC_MPU_CTRL_ENABLE 0x00000001 // MPU Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_NUMBER // register. // //***************************************************************************** #define NVIC_MPU_NUMBER_M 0x00000007 // MPU Region to Access #define NVIC_MPU_NUMBER_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_BASE register. // //***************************************************************************** #define NVIC_MPU_BASE_ADDR_M 0xFFFFFFE0 // Base Address Mask #define NVIC_MPU_BASE_VALID 0x00000010 // Region Number Valid #define NVIC_MPU_BASE_REGION_M 0x00000007 // Region Number #define NVIC_MPU_BASE_ADDR_S 5 #define NVIC_MPU_BASE_REGION_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_ATTR register. // //***************************************************************************** #define NVIC_MPU_ATTR_M 0xFFFF0000 // Attributes #define NVIC_MPU_ATTR_XN 0x10000000 // Instruction Access Disable #define NVIC_MPU_ATTR_AP_M 0x07000000 // Access Privilege #define NVIC_MPU_ATTR_AP_NO_NO 0x00000000 // prv: no access, usr: no access #define NVIC_MPU_ATTR_AP_RW_NO 0x01000000 // prv: rw, usr: none #define NVIC_MPU_ATTR_AP_RW_RO 0x02000000 // prv: rw, usr: read-only #define NVIC_MPU_ATTR_AP_RW_RW 0x03000000 // prv: rw, usr: rw #define NVIC_MPU_ATTR_AP_RO_NO 0x05000000 // prv: ro, usr: none #define NVIC_MPU_ATTR_AP_RO_RO 0x06000000 // prv: ro, usr: ro #define NVIC_MPU_ATTR_TEX_M 0x00380000 // Type Extension Mask #define NVIC_MPU_ATTR_SHAREABLE 0x00040000 // Shareable #define NVIC_MPU_ATTR_CACHEABLE 0x00020000 // Cacheable #define NVIC_MPU_ATTR_BUFFRABLE 0x00010000 // Bufferable #define NVIC_MPU_ATTR_SRD_M 0x0000FF00 // Subregion Disable Bits #define NVIC_MPU_ATTR_SRD_0 0x00000100 // Sub-region 0 disable #define NVIC_MPU_ATTR_SRD_1 0x00000200 // Sub-region 1 disable #define NVIC_MPU_ATTR_SRD_2 0x00000400 // Sub-region 2 disable #define NVIC_MPU_ATTR_SRD_3 0x00000800 // Sub-region 3 disable #define NVIC_MPU_ATTR_SRD_4 0x00001000 // Sub-region 4 disable #define NVIC_MPU_ATTR_SRD_5 0x00002000 // Sub-region 5 disable #define NVIC_MPU_ATTR_SRD_6 0x00004000 // Sub-region 6 disable #define NVIC_MPU_ATTR_SRD_7 0x00008000 // Sub-region 7 disable #define NVIC_MPU_ATTR_SIZE_M 0x0000003E // Region Size Mask #define NVIC_MPU_ATTR_SIZE_32B 0x00000008 // Region size 32 bytes #define NVIC_MPU_ATTR_SIZE_64B 0x0000000A // Region size 64 bytes #define NVIC_MPU_ATTR_SIZE_128B 0x0000000C // Region size 128 bytes #define NVIC_MPU_ATTR_SIZE_256B 0x0000000E // Region size 256 bytes #define NVIC_MPU_ATTR_SIZE_512B 0x00000010 // Region size 512 bytes #define NVIC_MPU_ATTR_SIZE_1K 0x00000012 // Region size 1 Kbytes #define NVIC_MPU_ATTR_SIZE_2K 0x00000014 // Region size 2 Kbytes #define NVIC_MPU_ATTR_SIZE_4K 0x00000016 // Region size 4 Kbytes #define NVIC_MPU_ATTR_SIZE_8K 0x00000018 // Region size 8 Kbytes #define NVIC_MPU_ATTR_SIZE_16K 0x0000001A // Region size 16 Kbytes #define NVIC_MPU_ATTR_SIZE_32K 0x0000001C // Region size 32 Kbytes #define NVIC_MPU_ATTR_SIZE_64K 0x0000001E // Region size 64 Kbytes #define NVIC_MPU_ATTR_SIZE_128K 0x00000020 // Region size 128 Kbytes #define NVIC_MPU_ATTR_SIZE_256K 0x00000022 // Region size 256 Kbytes #define NVIC_MPU_ATTR_SIZE_512K 0x00000024 // Region size 512 Kbytes #define NVIC_MPU_ATTR_SIZE_1M 0x00000026 // Region size 1 Mbytes #define NVIC_MPU_ATTR_SIZE_2M 0x00000028 // Region size 2 Mbytes #define NVIC_MPU_ATTR_SIZE_4M 0x0000002A // Region size 4 Mbytes #define NVIC_MPU_ATTR_SIZE_8M 0x0000002C // Region size 8 Mbytes #define NVIC_MPU_ATTR_SIZE_16M 0x0000002E // Region size 16 Mbytes #define NVIC_MPU_ATTR_SIZE_32M 0x00000030 // Region size 32 Mbytes #define NVIC_MPU_ATTR_SIZE_64M 0x00000032 // Region size 64 Mbytes #define NVIC_MPU_ATTR_SIZE_128M 0x00000034 // Region size 128 Mbytes #define NVIC_MPU_ATTR_SIZE_256M 0x00000036 // Region size 256 Mbytes #define NVIC_MPU_ATTR_SIZE_512M 0x00000038 // Region size 512 Mbytes #define NVIC_MPU_ATTR_SIZE_1G 0x0000003A // Region size 1 Gbytes #define NVIC_MPU_ATTR_SIZE_2G 0x0000003C // Region size 2 Gbytes #define NVIC_MPU_ATTR_SIZE_4G 0x0000003E // Region size 4 Gbytes #define NVIC_MPU_ATTR_ENABLE 0x00000001 // Region Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_BASE1 register. // //***************************************************************************** #define NVIC_MPU_BASE1_ADDR_M 0xFFFFFFE0 // Base Address Mask #define NVIC_MPU_BASE1_VALID 0x00000010 // Region Number Valid #define NVIC_MPU_BASE1_REGION_M 0x00000007 // Region Number #define NVIC_MPU_BASE1_ADDR_S 5 #define NVIC_MPU_BASE1_REGION_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_ATTR1 register. // //***************************************************************************** #define NVIC_MPU_ATTR1_XN 0x10000000 // Instruction Access Disable #define NVIC_MPU_ATTR1_AP_M 0x07000000 // Access Privilege #define NVIC_MPU_ATTR1_TEX_M 0x00380000 // Type Extension Mask #define NVIC_MPU_ATTR1_SHAREABLE \ 0x00040000 // Shareable #define NVIC_MPU_ATTR1_CACHEABLE \ 0x00020000 // Cacheable #define NVIC_MPU_ATTR1_BUFFRABLE \ 0x00010000 // Bufferable #define NVIC_MPU_ATTR1_SRD_M 0x0000FF00 // Subregion Disable Bits #define NVIC_MPU_ATTR1_SIZE_M 0x0000003E // Region Size Mask #define NVIC_MPU_ATTR1_ENABLE 0x00000001 // Region Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_BASE2 register. // //***************************************************************************** #define NVIC_MPU_BASE2_ADDR_M 0xFFFFFFE0 // Base Address Mask #define NVIC_MPU_BASE2_VALID 0x00000010 // Region Number Valid #define NVIC_MPU_BASE2_REGION_M 0x00000007 // Region Number #define NVIC_MPU_BASE2_ADDR_S 5 #define NVIC_MPU_BASE2_REGION_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_ATTR2 register. // //***************************************************************************** #define NVIC_MPU_ATTR2_XN 0x10000000 // Instruction Access Disable #define NVIC_MPU_ATTR2_AP_M 0x07000000 // Access Privilege #define NVIC_MPU_ATTR2_TEX_M 0x00380000 // Type Extension Mask #define NVIC_MPU_ATTR2_SHAREABLE \ 0x00040000 // Shareable #define NVIC_MPU_ATTR2_CACHEABLE \ 0x00020000 // Cacheable #define NVIC_MPU_ATTR2_BUFFRABLE \ 0x00010000 // Bufferable #define NVIC_MPU_ATTR2_SRD_M 0x0000FF00 // Subregion Disable Bits #define NVIC_MPU_ATTR2_SIZE_M 0x0000003E // Region Size Mask #define NVIC_MPU_ATTR2_ENABLE 0x00000001 // Region Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_BASE3 register. // //***************************************************************************** #define NVIC_MPU_BASE3_ADDR_M 0xFFFFFFE0 // Base Address Mask #define NVIC_MPU_BASE3_VALID 0x00000010 // Region Number Valid #define NVIC_MPU_BASE3_REGION_M 0x00000007 // Region Number #define NVIC_MPU_BASE3_ADDR_S 5 #define NVIC_MPU_BASE3_REGION_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_MPU_ATTR3 register. // //***************************************************************************** #define NVIC_MPU_ATTR3_XN 0x10000000 // Instruction Access Disable #define NVIC_MPU_ATTR3_AP_M 0x07000000 // Access Privilege #define NVIC_MPU_ATTR3_TEX_M 0x00380000 // Type Extension Mask #define NVIC_MPU_ATTR3_SHAREABLE \ 0x00040000 // Shareable #define NVIC_MPU_ATTR3_CACHEABLE \ 0x00020000 // Cacheable #define NVIC_MPU_ATTR3_BUFFRABLE \ 0x00010000 // Bufferable #define NVIC_MPU_ATTR3_SRD_M 0x0000FF00 // Subregion Disable Bits #define NVIC_MPU_ATTR3_SIZE_M 0x0000003E // Region Size Mask #define NVIC_MPU_ATTR3_ENABLE 0x00000001 // Region Enable //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DBG_CTRL register. // //***************************************************************************** #define NVIC_DBG_CTRL_DBGKEY_M 0xFFFF0000 // Debug key mask #define NVIC_DBG_CTRL_DBGKEY 0xA05F0000 // Debug key #define NVIC_DBG_CTRL_S_RESET_ST \ 0x02000000 // Core has reset since last read #define NVIC_DBG_CTRL_S_RETIRE_ST \ 0x01000000 // Core has executed insruction // since last read #define NVIC_DBG_CTRL_S_LOCKUP 0x00080000 // Core is locked up #define NVIC_DBG_CTRL_S_SLEEP 0x00040000 // Core is sleeping #define NVIC_DBG_CTRL_S_HALT 0x00020000 // Core status on halt #define NVIC_DBG_CTRL_S_REGRDY 0x00010000 // Register read/write available #define NVIC_DBG_CTRL_C_SNAPSTALL \ 0x00000020 // Breaks a stalled load/store #define NVIC_DBG_CTRL_C_MASKINT 0x00000008 // Mask interrupts when stepping #define NVIC_DBG_CTRL_C_STEP 0x00000004 // Step the core #define NVIC_DBG_CTRL_C_HALT 0x00000002 // Halt the core #define NVIC_DBG_CTRL_C_DEBUGEN 0x00000001 // Enable debug //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DBG_XFER register. // //***************************************************************************** #define NVIC_DBG_XFER_REG_WNR 0x00010000 // Write or not read #define NVIC_DBG_XFER_REG_SEL_M 0x0000001F // Register #define NVIC_DBG_XFER_REG_R0 0x00000000 // Register R0 #define NVIC_DBG_XFER_REG_R1 0x00000001 // Register R1 #define NVIC_DBG_XFER_REG_R2 0x00000002 // Register R2 #define NVIC_DBG_XFER_REG_R3 0x00000003 // Register R3 #define NVIC_DBG_XFER_REG_R4 0x00000004 // Register R4 #define NVIC_DBG_XFER_REG_R5 0x00000005 // Register R5 #define NVIC_DBG_XFER_REG_R6 0x00000006 // Register R6 #define NVIC_DBG_XFER_REG_R7 0x00000007 // Register R7 #define NVIC_DBG_XFER_REG_R8 0x00000008 // Register R8 #define NVIC_DBG_XFER_REG_R9 0x00000009 // Register R9 #define NVIC_DBG_XFER_REG_R10 0x0000000A // Register R10 #define NVIC_DBG_XFER_REG_R11 0x0000000B // Register R11 #define NVIC_DBG_XFER_REG_R12 0x0000000C // Register R12 #define NVIC_DBG_XFER_REG_R13 0x0000000D // Register R13 #define NVIC_DBG_XFER_REG_R14 0x0000000E // Register R14 #define NVIC_DBG_XFER_REG_R15 0x0000000F // Register R15 #define NVIC_DBG_XFER_REG_FLAGS 0x00000010 // xPSR/Flags register #define NVIC_DBG_XFER_REG_MSP 0x00000011 // Main SP #define NVIC_DBG_XFER_REG_PSP 0x00000012 // Process SP #define NVIC_DBG_XFER_REG_DSP 0x00000013 // Deep SP #define NVIC_DBG_XFER_REG_CFBP 0x00000014 // Control/Fault/BasePri/PriMask //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DBG_DATA register. // //***************************************************************************** #define NVIC_DBG_DATA_M 0xFFFFFFFF // Data temporary cache #define NVIC_DBG_DATA_S 0 //***************************************************************************** // // The following are defines for the bit fields in the NVIC_DBG_INT register. // //***************************************************************************** #define NVIC_DBG_INT_HARDERR 0x00000400 // Debug trap on hard fault #define NVIC_DBG_INT_INTERR 0x00000200 // Debug trap on interrupt errors #define NVIC_DBG_INT_BUSERR 0x00000100 // Debug trap on bus error #define NVIC_DBG_INT_STATERR 0x00000080 // Debug trap on usage fault state #define NVIC_DBG_INT_CHKERR 0x00000040 // Debug trap on usage fault check #define NVIC_DBG_INT_NOCPERR 0x00000020 // Debug trap on coprocessor error #define NVIC_DBG_INT_MMERR 0x00000010 // Debug trap on mem manage fault #define NVIC_DBG_INT_RESET 0x00000008 // Core reset status #define NVIC_DBG_INT_RSTPENDCLR 0x00000004 // Clear pending core reset #define NVIC_DBG_INT_RSTPENDING 0x00000002 // Core reset is pending #define NVIC_DBG_INT_RSTVCATCH 0x00000001 // Reset vector catch //***************************************************************************** // // The following are defines for the bit fields in the NVIC_SW_TRIG register. // //***************************************************************************** #define NVIC_SW_TRIG_INTID_M 0x0000003F // Interrupt ID #undef NVIC_SW_TRIG_INTID_M #define NVIC_SW_TRIG_INTID_M 0x000000FF // Interrupt ID #define NVIC_SW_TRIG_INTID_S 0 #endif // __HW_NVIC_H__ micropython-1.12/ports/cc3200/hal/inc/hw_ocp_shared.h000066400000000000000000006565131357706137100223760ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_OCP_SHARED_H__ #define __HW_OCP_SHARED_H__ //***************************************************************************** // // The following are defines for the OCP_SHARED register offsets. // //***************************************************************************** #define OCP_SHARED_O_SEMAPHORE1 0x00000000 #define OCP_SHARED_O_SEMAPHORE2 0x00000004 #define OCP_SHARED_O_SEMAPHORE3 0x00000008 #define OCP_SHARED_O_SEMAPHORE4 0x0000000C #define OCP_SHARED_O_SEMAPHORE5 0x00000010 #define OCP_SHARED_O_SEMAPHORE6 0x00000014 #define OCP_SHARED_O_SEMAPHORE7 0x00000018 #define OCP_SHARED_O_SEMAPHORE8 0x0000001C #define OCP_SHARED_O_SEMAPHORE9 0x00000020 #define OCP_SHARED_O_SEMAPHORE10 \ 0x00000024 #define OCP_SHARED_O_SEMAPHORE11 \ 0x00000028 #define OCP_SHARED_O_SEMAPHORE12 \ 0x0000002C #define OCP_SHARED_O_IC_LOCKER_ID \ 0x00000030 #define OCP_SHARED_O_MCU_SEMAPHORE_PEND \ 0x00000034 #define OCP_SHARED_O_WL_SEMAPHORE_PEND \ 0x00000038 #define OCP_SHARED_O_PLATFORM_DETECTION_RD_ONLY \ 0x0000003C #define OCP_SHARED_O_SEMAPHORES_STATUS_RD_ONLY \ 0x00000040 #define OCP_SHARED_O_CC3XX_CONFIG_CTRL \ 0x00000044 #define OCP_SHARED_O_CC3XX_SHARED_MEM_SEL_LSB \ 0x00000048 #define OCP_SHARED_O_CC3XX_SHARED_MEM_SEL_MSB \ 0x0000004C #define OCP_SHARED_O_WLAN_ELP_WAKE_EN \ 0x00000050 #define OCP_SHARED_O_DEVINIT_ROM_START_ADDR \ 0x00000054 #define OCP_SHARED_O_DEVINIT_ROM_END_ADDR \ 0x00000058 #define OCP_SHARED_O_SSBD_SEED 0x0000005C #define OCP_SHARED_O_SSBD_CHK 0x00000060 #define OCP_SHARED_O_SSBD_POLY_SEL \ 0x00000064 #define OCP_SHARED_O_SPARE_REG_0 \ 0x00000068 #define OCP_SHARED_O_SPARE_REG_1 \ 0x0000006C #define OCP_SHARED_O_SPARE_REG_2 \ 0x00000070 #define OCP_SHARED_O_SPARE_REG_3 \ 0x00000074 #define OCP_SHARED_O_GPIO_PAD_CONFIG_0 \ 0x000000A0 #define OCP_SHARED_O_GPIO_PAD_CONFIG_1 \ 0x000000A4 #define OCP_SHARED_O_GPIO_PAD_CONFIG_2 \ 0x000000A8 #define OCP_SHARED_O_GPIO_PAD_CONFIG_3 \ 0x000000AC #define OCP_SHARED_O_GPIO_PAD_CONFIG_4 \ 0x000000B0 #define OCP_SHARED_O_GPIO_PAD_CONFIG_5 \ 0x000000B4 #define OCP_SHARED_O_GPIO_PAD_CONFIG_6 \ 0x000000B8 #define OCP_SHARED_O_GPIO_PAD_CONFIG_7 \ 0x000000BC #define OCP_SHARED_O_GPIO_PAD_CONFIG_8 \ 0x000000C0 #define OCP_SHARED_O_GPIO_PAD_CONFIG_9 \ 0x000000C4 #define OCP_SHARED_O_GPIO_PAD_CONFIG_10 \ 0x000000C8 #define OCP_SHARED_O_GPIO_PAD_CONFIG_11 \ 0x000000CC #define OCP_SHARED_O_GPIO_PAD_CONFIG_12 \ 0x000000D0 #define OCP_SHARED_O_GPIO_PAD_CONFIG_13 \ 0x000000D4 #define OCP_SHARED_O_GPIO_PAD_CONFIG_14 \ 0x000000D8 #define OCP_SHARED_O_GPIO_PAD_CONFIG_15 \ 0x000000DC #define OCP_SHARED_O_GPIO_PAD_CONFIG_16 \ 0x000000E0 #define OCP_SHARED_O_GPIO_PAD_CONFIG_17 \ 0x000000E4 #define OCP_SHARED_O_GPIO_PAD_CONFIG_18 \ 0x000000E8 #define OCP_SHARED_O_GPIO_PAD_CONFIG_19 \ 0x000000EC #define OCP_SHARED_O_GPIO_PAD_CONFIG_20 \ 0x000000F0 #define OCP_SHARED_O_GPIO_PAD_CONFIG_21 \ 0x000000F4 #define OCP_SHARED_O_GPIO_PAD_CONFIG_22 \ 0x000000F8 #define OCP_SHARED_O_GPIO_PAD_CONFIG_23 \ 0x000000FC #define OCP_SHARED_O_GPIO_PAD_CONFIG_24 \ 0x00000100 #define OCP_SHARED_O_GPIO_PAD_CONFIG_25 \ 0x00000104 #define OCP_SHARED_O_GPIO_PAD_CONFIG_26 \ 0x00000108 #define OCP_SHARED_O_GPIO_PAD_CONFIG_27 \ 0x0000010C #define OCP_SHARED_O_GPIO_PAD_CONFIG_28 \ 0x00000110 #define OCP_SHARED_O_GPIO_PAD_CONFIG_29 \ 0x00000114 #define OCP_SHARED_O_GPIO_PAD_CONFIG_30 \ 0x00000118 #define OCP_SHARED_O_GPIO_PAD_CONFIG_31 \ 0x0000011C #define OCP_SHARED_O_GPIO_PAD_CONFIG_32 \ 0x00000120 #define OCP_SHARED_O_GPIO_PAD_CONFIG_33 \ 0x00000124 #define OCP_SHARED_O_GPIO_PAD_CONFIG_34 \ 0x00000128 #define OCP_SHARED_O_GPIO_PAD_CONFIG_35 \ 0x0000012C #define OCP_SHARED_O_GPIO_PAD_CONFIG_36 \ 0x00000130 #define OCP_SHARED_O_GPIO_PAD_CONFIG_37 \ 0x00000134 #define OCP_SHARED_O_GPIO_PAD_CONFIG_38 \ 0x00000138 #define OCP_SHARED_O_GPIO_PAD_CONFIG_39 \ 0x0000013C #define OCP_SHARED_O_GPIO_PAD_CONFIG_40 \ 0x00000140 #define OCP_SHARED_O_GPIO_PAD_CMN_CONFIG \ 0x00000144 // This register provide control to // GPIO_CC3XXV1 IO PAD. Common // control signals to all bottom Die // IO's are controlled via this. #define OCP_SHARED_O_D2D_DEV_PAD_CMN_CONFIG \ 0x00000148 #define OCP_SHARED_O_D2D_TOSTACK_PAD_CONF \ 0x0000014C #define OCP_SHARED_O_D2D_MISC_PAD_CONF \ 0x00000150 #define OCP_SHARED_O_SOP_CONF_OVERRIDE \ 0x00000154 #define OCP_SHARED_O_CC3XX_DEBUGSS_STATUS \ 0x00000158 #define OCP_SHARED_O_CC3XX_DEBUGMUX_SEL \ 0x0000015C #define OCP_SHARED_O_ALT_PC_VAL_NW \ 0x00000160 #define OCP_SHARED_O_ALT_PC_VAL_APPS \ 0x00000164 #define OCP_SHARED_O_SPARE_REG_4 \ 0x00000168 #define OCP_SHARED_O_SPARE_REG_5 \ 0x0000016C #define OCP_SHARED_O_SH_SPI_CS_MASK \ 0x00000170 #define OCP_SHARED_O_CC3XX_DEVICE_TYPE \ 0x00000174 #define OCP_SHARED_O_MEM_TOPMUXCTRL_IFORCE \ 0x00000178 #define OCP_SHARED_O_CC3XX_DEV_PACKAGE_DETECT \ 0x0000017C #define OCP_SHARED_O_AUTONMS_SPICLK_SEL \ 0x00000180 #define OCP_SHARED_O_CC3XX_DEV_PADCONF \ 0x00000184 #define OCP_SHARED_O_SPARE_REG_8 \ 0x00000188 #define OCP_SHARED_O_SPARE_REG_6 \ 0x0000018C #define OCP_SHARED_O_SPARE_REG_7 \ 0x00000190 #define OCP_SHARED_O_APPS_WLAN_ORBIT \ 0x00000194 #define OCP_SHARED_O_APPS_WLAN_SCRATCH_PAD \ 0x00000198 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE1 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE1_MEM_SEMAPHORE1_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE1_MEM_SEMAPHORE1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE2 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE2_MEM_SEMAPHORE2_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE2_MEM_SEMAPHORE2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE3 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE3_MEM_SEMAPHORE3_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE3_MEM_SEMAPHORE3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE4 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE4_MEM_SEMAPHORE4_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE4_MEM_SEMAPHORE4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE5 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE5_MEM_SEMAPHORE5_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE5_MEM_SEMAPHORE5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE6 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE6_MEM_SEMAPHORE6_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE6_MEM_SEMAPHORE6_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE7 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE7_MEM_SEMAPHORE7_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE7_MEM_SEMAPHORE7_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE8 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE8_MEM_SEMAPHORE8_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE8_MEM_SEMAPHORE8_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE9 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE9_MEM_SEMAPHORE9_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE9_MEM_SEMAPHORE9_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE10 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE10_MEM_SEMAPHORE10_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE10_MEM_SEMAPHORE10_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE11 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE11_MEM_SEMAPHORE11_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE11_MEM_SEMAPHORE11_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORE12 register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORE12_MEM_SEMAPHORE12_M \ 0x00000003 // General Purpose Semaphore for SW // Usage. If any of the 2 bits of a // given register is set to 1, it // means that the semaphore is // locked by one of the masters. // Each bit represents a master IP // as follows: {WLAN,NWP}. The JTAG // cannot capture the semaphore but // it can release it. As a master IP // reads the semaphore, it will be // caputed and the masters // correlating bit will be set to 1 // (set upon read). As any IP writes // to this address (independent of // the written data) the semaphore // will be set to 2'b00. #define OCP_SHARED_SEMAPHORE12_MEM_SEMAPHORE12_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_IC_LOCKER_ID register. // //****************************************************************************** #define OCP_SHARED_IC_LOCKER_ID_MEM_IC_LOCKER_ID_M \ 0x00000007 // This register is used for // allowing only one master OCP to // perform write transactions to the // OCP slaves. Each bit represents // an IP in the following format: { // JTAG,WLAN, NWP mcu}. As any of // the bits is set to one, the // correlating IP is preventing the // other IP's from performing write // transactions to the slaves. As // the Inter Connect is locked, the // only the locking IP can write to // the register and by that // releasing the lock. 3'b000 => IC // is not locked. 3'b001 => IC is // locked by NWP mcu. 3'b010 => IC // is locked by WLAN. 3'b100 => IC // is locked by JTAG. #define OCP_SHARED_IC_LOCKER_ID_MEM_IC_LOCKER_ID_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_MCU_SEMAPHORE_PEND register. // //****************************************************************************** #define OCP_SHARED_MCU_SEMAPHORE_PEND_MEM_MCU_SEMAPHORE_PEND_M \ 0x0000FFFF // This register specifies the // semaphore for which the NWP mcu // is waiting to be released. It is // set to the serial number of a // given locked semaphore after it // was read by the NWP mcu. Only // [11:0] is used. #define OCP_SHARED_MCU_SEMAPHORE_PEND_MEM_MCU_SEMAPHORE_PEND_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_WL_SEMAPHORE_PEND register. // //****************************************************************************** #define OCP_SHARED_WL_SEMAPHORE_PEND_MEM_WL_SEMAPHORE_PEND_M \ 0x0000FFFF // This register specifies the // semaphore for which the WLAN is // waiting to be released. It is set // to the serial number of a given // locked semaphore after it was // read by the WLAN. Only [11:0] is // used. #define OCP_SHARED_WL_SEMAPHORE_PEND_MEM_WL_SEMAPHORE_PEND_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_PLATFORM_DETECTION_RD_ONLY register. // //****************************************************************************** #define OCP_SHARED_PLATFORM_DETECTION_RD_ONLY_PLATFORM_DETECTION_M \ 0x0000FFFF // This information serves the IPs // for knowing in which platform are // they integrated at: 0 = CC31XX. #define OCP_SHARED_PLATFORM_DETECTION_RD_ONLY_PLATFORM_DETECTION_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SEMAPHORES_STATUS_RD_ONLY register. // //****************************************************************************** #define OCP_SHARED_SEMAPHORES_STATUS_RD_ONLY_SEMAPHORES_STATUS_M \ 0x00000FFF // Captured/released semaphores // status for the 12 semaphores. // Each bit of the 12 bits // represents a semaphore. 0 => // Semaphore Free. 1 => Semaphore // Captured. #define OCP_SHARED_SEMAPHORES_STATUS_RD_ONLY_SEMAPHORES_STATUS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_CC3XX_CONFIG_CTRL register. // //****************************************************************************** #define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_IC_TO_EN \ 0x00000010 // This bit is used to enable // timeout mechanism for top_ocp_ic // (for debug puropse). When 1 value // , in case any ocp slave doesn't // give sresponse within 16 cylcles // top_ic will give error response // itself to avoid bus hange. #define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_ALT_PC_EN_APPS \ 0x00000008 // 1 bit should be accessible only // in devinit. This will enable 0x4 // hack for apps processor #define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_ALT_PC_EN_NW \ 0x00000004 // 1 bit, should be accessible only // in devinit. This will enable 0x4 // hack for nw processor #define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_EXTEND_NW_ROM \ 0x00000002 // When set NW can take over apps // rom and flash via IDCODE bus. // Apps will able to access this // register only during devinit and // reset value should be 0. #define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_WLAN_HOST_INTF_SEL \ 0x00000001 // When this bit is set to 0 WPSI // host interface wil be selected, // when this bit is set to 1 , WLAN // host async bridge will be // selected. //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_CC3XX_SHARED_MEM_SEL_LSB register. // //****************************************************************************** #define OCP_SHARED_CC3XX_SHARED_MEM_SEL_LSB_MEM_SHARED_MEM_SEL_LSB_M \ 0x3FFFFFFF // This register provides memss RAM // column configuration for column 0 // to 9. 3 bits are allocated per // column. This register is required // to be configured before starting // RAM access. Changing register // setting while code is running // will result into unpredictable // memory behaviour. Register is // supported to configured ones // after core is booted up. 3 bit // encoding per column is as // follows: when 000 : WLAN, 001: // NWP, 010: APPS, 011: PHY, 100: // OCLA column 0 select: bit [2:0] // :when 000 -> WLAN,001 -> NWP,010 // -> APPS, 011 -> PHY, 100 -> OCLA // column 1 select: bit [5:3] // :column 2 select: bit [8 : 6]: // column 3 select : bit [11: 9] // column 4 select : bit [14:12] // column 5 select : bit [17:15] // column 6 select : bit [20:18] // column 7 select : bit [23:21] // column 8 select : bit [26:24] // column 9 select : bit [29:27] // column 10 select #define OCP_SHARED_CC3XX_SHARED_MEM_SEL_LSB_MEM_SHARED_MEM_SEL_LSB_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_CC3XX_SHARED_MEM_SEL_MSB register. // //****************************************************************************** #define OCP_SHARED_CC3XX_SHARED_MEM_SEL_MSB_MEM_SHARED_MEM_SEL_MSB_M \ 0x00000FFF // This register provides memss RAM // column configuration for column // 10 to 15. 3 bits are allocated // per column. This register is // required to be configured before // starting RAM access. Changing // register setting while code is // running will result into // unpredictable memory behaviour. // Register is supported to // configured ones after core is // booted up. 3 bit encoding per // column is as follows: when 000 : // WLAN, 001: NWP, 010: APPS, 011: // PHY, 100: OCLA column 11 select : // bit [2:0] column 12 select : bit // [5:3] column 13 select : bit [8 : // 6] column 14 select : #define OCP_SHARED_CC3XX_SHARED_MEM_SEL_MSB_MEM_SHARED_MEM_SEL_MSB_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_WLAN_ELP_WAKE_EN register. // //****************************************************************************** #define OCP_SHARED_WLAN_ELP_WAKE_EN_MEM_WLAN_ELP_WAKE_EN \ 0x00000001 // when '1' : signal will enabled // ELP power doamin when '0': ELP is // not powered up. //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_DEVINIT_ROM_START_ADDR register. // //****************************************************************************** #define OCP_SHARED_DEVINIT_ROM_START_ADDR_MEM_DEVINIT_ROM_START_ADDR_M \ 0xFFFFFFFF // 32 bit, Writable only during // devinit, and whole 32 bit should // be output of the config register // module. This register is not used // , similar register availble in // GPRCM space. #define OCP_SHARED_DEVINIT_ROM_START_ADDR_MEM_DEVINIT_ROM_START_ADDR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_DEVINIT_ROM_END_ADDR register. // //****************************************************************************** #define OCP_SHARED_DEVINIT_ROM_END_ADDR_MEM_DEVINIT_ROM_END_ADDR_M \ 0xFFFFFFFF // 32 bit, Writable only during // devinit, and whole 32 bit should // be output of the config register // module. #define OCP_SHARED_DEVINIT_ROM_END_ADDR_MEM_DEVINIT_ROM_END_ADDR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SSBD_SEED register. // //****************************************************************************** #define OCP_SHARED_SSBD_SEED_MEM_SSBD_SEED_M \ 0xFFFFFFFF // 32 bit, Writable only during // devinit, and whole 32 bit should // be output of the config register // module. #define OCP_SHARED_SSBD_SEED_MEM_SSBD_SEED_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SSBD_CHK register. // //****************************************************************************** #define OCP_SHARED_SSBD_CHK_MEM_SSBD_CHK_M \ 0xFFFFFFFF // 32 bit, Writable only during // devinit, and whole 32 bit should // be output of the config register // module. #define OCP_SHARED_SSBD_CHK_MEM_SSBD_CHK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SSBD_POLY_SEL register. // //****************************************************************************** #define OCP_SHARED_SSBD_POLY_SEL_MEM_SSBD_POLY_SEL_M \ 0x00000003 // 2 bit, Writable only during // devinit, and whole 2 bit should // be output of the config register // module. #define OCP_SHARED_SSBD_POLY_SEL_MEM_SSBD_POLY_SEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SPARE_REG_0 register. // //****************************************************************************** #define OCP_SHARED_SPARE_REG_0_MEM_SPARE_REG_0_M \ 0xFFFFFFFF // Devinit code should look for // whether corresponding fuse is // blown and if blown write to the // 11th bit of this register to // disable flshtst interface #define OCP_SHARED_SPARE_REG_0_MEM_SPARE_REG_0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SPARE_REG_1 register. // //****************************************************************************** #define OCP_SHARED_SPARE_REG_1_MEM_SPARE_REG_1_M \ 0xFFFFFFFF // NWP Software register #define OCP_SHARED_SPARE_REG_1_MEM_SPARE_REG_1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SPARE_REG_2 register. // //****************************************************************************** #define OCP_SHARED_SPARE_REG_2_MEM_SPARE_REG_2_M \ 0xFFFFFFFF // NWP Software register #define OCP_SHARED_SPARE_REG_2_MEM_SPARE_REG_2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SPARE_REG_3 register. // //****************************************************************************** #define OCP_SHARED_SPARE_REG_3_MEM_SPARE_REG_3_M \ 0xFFFFFFFF // APPS Software register #define OCP_SHARED_SPARE_REG_3_MEM_SPARE_REG_3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_0 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_0_MEM_GPIO_PAD_CONFIG_0_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." "For example in // case of I2C Value gets latched at // rising edge of RET33.""" """ 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_0_MEM_GPIO_PAD_CONFIG_0_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_1 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_1_MEM_GPIO_PAD_CONFIG_1_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_1_MEM_GPIO_PAD_CONFIG_1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_2 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_2_MEM_GPIO_PAD_CONFIG_2_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_2_MEM_GPIO_PAD_CONFIG_2_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_3 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_3_MEM_GPIO_PAD_CONFIG_3_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_3_MEM_GPIO_PAD_CONFIG_3_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_4 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_4_MEM_GPIO_PAD_CONFIG_4_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_4_MEM_GPIO_PAD_CONFIG_4_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_5 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_5_MEM_GPIO_PAD_CONFIG_5_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_5_MEM_GPIO_PAD_CONFIG_5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_6 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_6_MEM_GPIO_PAD_CONFIG_6_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_6_MEM_GPIO_PAD_CONFIG_6_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_7 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_7_MEM_GPIO_PAD_CONFIG_7_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_7_MEM_GPIO_PAD_CONFIG_7_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_8 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_8_MEM_GPIO_PAD_CONFIG_8_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_8_MEM_GPIO_PAD_CONFIG_8_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_9 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_9_MEM_GPIO_PAD_CONFIG_9_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_9_MEM_GPIO_PAD_CONFIG_9_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_10 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_10_MEM_GPIO_PAD_CONFIG_10_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_10_MEM_GPIO_PAD_CONFIG_10_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_11 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_11_MEM_GPIO_PAD_CONFIG_11_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_11_MEM_GPIO_PAD_CONFIG_11_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_12 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_12_MEM_GPIO_PAD_CONFIG_12_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_12_MEM_GPIO_PAD_CONFIG_12_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_13 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_13_MEM_GPIO_PAD_CONFIG_13_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_13_MEM_GPIO_PAD_CONFIG_13_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_14 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_14_MEM_GPIO_PAD_CONFIG_14_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_14_MEM_GPIO_PAD_CONFIG_14_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_15 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_15_MEM_GPIO_PAD_CONFIG_15_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_15_MEM_GPIO_PAD_CONFIG_15_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_16 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_16_MEM_GPIO_PAD_CONFIG_16_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_16_MEM_GPIO_PAD_CONFIG_16_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_17 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_17_MEM_GPIO_PAD_CONFIG_17_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_17_MEM_GPIO_PAD_CONFIG_17_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_18 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_18_MEM_GPIO_PAD_CONFIG_18_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_18_MEM_GPIO_PAD_CONFIG_18_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_19 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_19_MEM_GPIO_PAD_CONFIG_19_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_19_MEM_GPIO_PAD_CONFIG_19_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_20 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_20_MEM_GPIO_PAD_CONFIG_20_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_20_MEM_GPIO_PAD_CONFIG_20_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_21 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_21_MEM_GPIO_PAD_CONFIG_21_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_21_MEM_GPIO_PAD_CONFIG_21_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_22 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_22_MEM_GPIO_PAD_CONFIG_22_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_22_MEM_GPIO_PAD_CONFIG_22_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_23 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_23_MEM_GPIO_PAD_CONFIG_23_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_23_MEM_GPIO_PAD_CONFIG_23_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_24 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_24_MEM_GPIO_PAD_CONFIG_24_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_24_MEM_GPIO_PAD_CONFIG_24_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_25 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_25_MEM_GPIO_PAD_CONFIG_25_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_25_MEM_GPIO_PAD_CONFIG_25_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_26 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_26_MEM_GPIO_PAD_CONFIG_26_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_26_MEM_GPIO_PAD_CONFIG_26_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_27 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_27_MEM_GPIO_PAD_CONFIG_27_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_27_MEM_GPIO_PAD_CONFIG_27_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_28 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_28_MEM_GPIO_PAD_CONFIG_28_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_28_MEM_GPIO_PAD_CONFIG_28_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_29 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_29_MEM_GPIO_PAD_CONFIG_29_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_29_MEM_GPIO_PAD_CONFIG_29_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_30 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_30_MEM_GPIO_PAD_CONFIG_30_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_30_MEM_GPIO_PAD_CONFIG_30_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_31 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_31_MEM_GPIO_PAD_CONFIG_31_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_31_MEM_GPIO_PAD_CONFIG_31_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_32 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_32_MEM_GPIO_PAD_CONFIG_32_M \ 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." it can be used // for I2C type of peripherals. 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_32_MEM_GPIO_PAD_CONFIG_32_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_33 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_33_MEM_GPIO_PAD_CONFIG_33_M \ 0x0000003F // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 5 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. IODEN and I8MAEN // is diesabled for all development // IO's. These signals are tied to // logic level '0'. common control // is implemented for I2MAEN, // I4MAEN, WKPU, WKPD control . // refer dev_pad_cmn_config register // bits. #define OCP_SHARED_GPIO_PAD_CONFIG_33_MEM_GPIO_PAD_CONFIG_33_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_34 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_34_MEM_GPIO_PAD_CONFIG_34_M \ 0x0000003F // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 5 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. IODEN and I8MAEN // is diesabled for all development // IO's. These signals are tied to // logic level '0'. common control // is implemented for I2MAEN, // I4MAEN, WKPU, WKPD control . // refer dev_pad_cmn_config register // bits. #define OCP_SHARED_GPIO_PAD_CONFIG_34_MEM_GPIO_PAD_CONFIG_34_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_35 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_35_MEM_GPIO_PAD_CONFIG_35_M \ 0x0000003F // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 5 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. IODEN and I8MAEN // is diesabled for all development // IO's. These signals are tied to // logic level '0'. common control // is implemented for I2MAEN, // I4MAEN, WKPU, WKPD control . // refer dev_pad_cmn_config register // bits. #define OCP_SHARED_GPIO_PAD_CONFIG_35_MEM_GPIO_PAD_CONFIG_35_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_36 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_36_MEM_GPIO_PAD_CONFIG_36_M \ 0x0000003F // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 5 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. IODEN and I8MAEN // is diesabled for all development // IO's. These signals are tied to // logic level '0'. common control // is implemented for I2MAEN, // I4MAEN, WKPU, WKPD control . // refer dev_pad_cmn_config register // bits. #define OCP_SHARED_GPIO_PAD_CONFIG_36_MEM_GPIO_PAD_CONFIG_36_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_37 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_37_MEM_GPIO_PAD_CONFIG_37_M \ 0x0000003F // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 5 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. IODEN and I8MAEN // is diesabled for all development // IO's. These signals are tied to // logic level '0'. common control // is implemented for I2MAEN, // I4MAEN, WKPU, WKPD control . // refer dev_pad_cmn_config register // bits. #define OCP_SHARED_GPIO_PAD_CONFIG_37_MEM_GPIO_PAD_CONFIG_37_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_38 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_38_MEM_GPIO_PAD_CONFIG_38_M \ 0x0000003F // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 5 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. IODEN and I8MAEN // is diesabled for all development // IO's. These signals are tied to // logic level '0'. common control // is implemented for I2MAEN, // I4MAEN, WKPU, WKPD control . // refer dev_pad_cmn_config register // bits. #define OCP_SHARED_GPIO_PAD_CONFIG_38_MEM_GPIO_PAD_CONFIG_38_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_39 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_39_MEM_GPIO_PAD_CONFIG_39_M \ 0x0000003F // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 5 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. IODEN and I8MAEN // is diesabled for all development // IO's. These signals are tied to // logic level '0'. common control // is implemented for I2MAEN, // I4MAEN, WKPU, WKPD control . // refer dev_pad_cmn_config register // bits. #define OCP_SHARED_GPIO_PAD_CONFIG_39_MEM_GPIO_PAD_CONFIG_39_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CONFIG_40 register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CONFIG_40_MEM_GPIO_PAD_CONFIG_40_M \ 0x0007FFFF // GPIO 0 register: "Bit 0 - 3 is // used for PAD IO mode selection. // io_register={ "" 0 => // """"CONFMODE[0]"""""" "" 1 => // """"CONFMODE[1]"""""" "" 2 => // """"CONFMODE[2]"""""" "" 3 => // """"CONFMODE[3]"""" 4 => // """"IODEN"""" --> When level ‘1’ // this disables the PMOS xtors of // the output stages making them // open-drain type." "For example in // case of I2C Value gets latched at // rising edge of RET33.""" """ 5 => // """"I2MAEN"""" --> Level ‘1’ // enables the approx 2mA output // stage""" """ 6 => """"I4MAEN"""" // --> Level ‘1’ enables the approx // 4mA output stage""" """ 7 => // """"I8MAEN"""" --> Level ‘1’ // enables the approx 8mA output // stage. Note: any drive strength // between 2mA and 14mA can be // obtained with combination of 2mA // 4mA and 8mA.""" """ 8 => // """"IWKPUEN"""" --> 10uA pull up // (weak strength)""" """ 9 => // """"IWKPDEN"""" --> 10uA pull // down (weak strength)""" """ 10 => // """"IOE_N"""" --> output enable // value. level ‘0’ enables the IDO // to PAD path. Else PAD is // tristated (except for the PU/PD // which are independent)." "Value // gets latched at rising edge of // RET33""" """ 11 =>"""" // IOE_N_OV"""" --> output enable // overirde. when bit is set to // logic '1' IOE_N (bit 4) value // will control IO IOE_N signal else // IOE_N is control via selected HW // logic. strong PULL UP and PULL // Down control is disabled for all // IO's. both controls are tied to // logic level '0'. #define OCP_SHARED_GPIO_PAD_CONFIG_40_MEM_GPIO_PAD_CONFIG_40_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_GPIO_PAD_CMN_CONFIG register. // //****************************************************************************** #define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_D2D_ISO_A_EN \ 0x00000080 // when '1' enable ISO A control to // D2D Pads else ISO is disabled. // For these PADS to be functional // this signals should be set 0. #define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_D2D_ISO_Y_EN \ 0x00000040 // when '1' enable ISO Y control to // D2D Pads else ISO is disabled. // For these PADS to be functional // this signals should be set 0. #define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_JTAG_IDIEN \ 0x00000020 // If level ‘1’ enables the PAD to // ODI path for JTAG PADS [PAD 23, // 24, 28, 29]. Else ODI is pulled // ‘Low’ regardless of PAD level." // "Value gets latched at rising // edge of RET33.""" """ #define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_HYSTVAL_M \ 0x00000018 // 00’: hysteriris = 10% of VDDS // (difference between upper and // lower threshold of the schmit // trigger) ‘01’: hysteriris = 20% // of VDDS (difference between upper // and lower threshold of the schmit // trigger) ‘10’: hysteriris = 30% // of VDDS (difference between upper // and lower threshold of the schmit // trigger) ‘11’: hysteriris = 40% // of VDDS (difference between upper // and lower threshold of the schmit // trigger)" """ #define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_HYSTVAL_S 3 #define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_HYSTEN \ 0x00000004 // If logic ‘0’ there is no // hysteresis. Set to ‘1’ to enable // hysteresis. Leave the choice to // customers""" #define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_IBIASEN \ 0x00000002 // Normal functional operation set // this to logic ‘1’ to increase the // speed of the o/p buffer at the // cost of 0.2uA static current // consumption per IO. During IDDQ // test and during Hibernate this // would be forced to logic ‘0’. // Value is not latched at rising // edge of RET33."" #define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_IDIEN \ 0x00000001 // If level ‘1’ enables the PAD to // ODI path. Else ODI is pulled // ‘Low’ regardless of PAD level." // "Value gets latched at rising // edge of RET33.""" """ //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_D2D_DEV_PAD_CMN_CONFIG register. // //****************************************************************************** #define OCP_SHARED_D2D_DEV_PAD_CMN_CONFIG_MEM_DEV_PAD_CMN_CONF_M \ 0x0000003F // this register implements common // IO control to all devement mode // PADs; these PADs are DEV_PAD33 to // DEV_PAD39. Bit [1:0] : Drive // strength control. These 2 bits // are connected to DEV PAD drive // strength control. possible drive // stregnths are 2MA, 4MA and 6 MA // for the these IO's. bit 0: when // set to logic value '1' enable 2MA // drive strength for DEVPAD01 to 07 // bit 1: when set to logic value // '1' enable 4MA drive strength for // DEVPAD01 to 07. bit[3:2] : WK // PULL UP and PULL down control. // These 2 bits provide IWKPUEN and // IWKPDEN control for all DEV IO's. // bit 2: when set to logic value // '1' enable WKPU to DEVPAD01 to 07 // bit 3: when set to logic value // '1' enable WKPD to DEVPAD01 to // 07. bit 4: WK PULL control for // DEV_PKG_DETECT pin. when '1' // pullup enabled else it is // disable. bit 5: when set to logic // value '1' enable 8MA drive // strength for DEVPAD01 to 07. #define OCP_SHARED_D2D_DEV_PAD_CMN_CONFIG_MEM_DEV_PAD_CMN_CONF_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_D2D_TOSTACK_PAD_CONF register. // //****************************************************************************** #define OCP_SHARED_D2D_TOSTACK_PAD_CONF_MEM_D2D_TOSTACK_PAD_CONF_M \ 0x1FFFFFFF // OEN/OEN2X control. When 0 : Act // as input buffer else output // buffer with drive strength 2. // this register control OEN2X pin // of D2D TOSTACK PAD: OEN1X and // OEN2X decoding is as follows: // "when ""00"" :" "when ""01"" : // dirve strength is '1' and output // buffer enabled." "when ""10"" : // drive strength is 2 and output // buffer is disabled." "when ""11"" // : dirve strength is '3' and // output buffer enabled." #define OCP_SHARED_D2D_TOSTACK_PAD_CONF_MEM_D2D_TOSTACK_PAD_CONF_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_D2D_MISC_PAD_CONF register. // //****************************************************************************** #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_POR_RESET_N \ 0x00000200 // This register provide OEN2X // control to D2D PADS OEN/OEN2X // control. When 0 : Act as input // buffer else output buffer with // drive strength 2. #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_RESET_N \ 0x00000100 // OEN/OEN2X control. When 0 : Act // as input buffer else output // buffer with drive strength 2. #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_HCLK \ 0x00000080 // OEN/OEN2X control. When 0 : Act // as input buffer else output // buffer with drive strength 2. #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_JTAG_TCK \ 0x00000040 // OEN/OEN2X control. When 0 : Act // as input buffer else output // buffer with drive strength 2. #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_JTAG_TMS \ 0x00000020 // OEN/OEN2X control. When 0 : Act // as input buffer else output // buffer with drive strength 2. #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_JTAG_TDI \ 0x00000010 // OEN/OEN2X control. When 0 : Act // as input buffer else output // buffer with drive strength 2. #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_PIOSC \ 0x00000008 // OEN/OEN2X control. When 0 : Act // as input buffer else output // buffer with drive strength 2. #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_SPARE_M \ 0x00000007 // D2D SPARE PAD OEN/OEN2X control. // When 0: Act as input buffer else // output buffer with drive strength // 2. #define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_SPARE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SOP_CONF_OVERRIDE register. // //****************************************************************************** #define OCP_SHARED_SOP_CONF_OVERRIDE_MEM_SOP_CONF_OVERRIDE \ 0x00000001 // when '1' : signal will ovberride // SoP setting of JTAG PADS. when // '0': SoP setting will control // JTAG PADs [ TDI, TDO, TMS, TCK] //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_CC3XX_DEBUGSS_STATUS register. // //****************************************************************************** #define OCP_SHARED_CC3XX_DEBUGSS_STATUS_APPS_MCU_JTAGNSW \ 0x00000020 // This register contains debug // subsystem status bits From APPS // MCU status bit to indicates // whether serial wire or 4 pins // jtag select. #define OCP_SHARED_CC3XX_DEBUGSS_STATUS_CJTAG_BYPASS_STATUS \ 0x00000010 // cjtag bypass bit select #define OCP_SHARED_CC3XX_DEBUGSS_STATUS_SW_INTERFACE_SEL_STATUS \ 0x00000008 // serial wire interface bit select #define OCP_SHARED_CC3XX_DEBUGSS_STATUS_APPS_TAP_ENABLE_STATUS \ 0x00000004 // apps tap enable status #define OCP_SHARED_CC3XX_DEBUGSS_STATUS_TAPS_ENABLE_STATUS \ 0x00000002 // tap enable status #define OCP_SHARED_CC3XX_DEBUGSS_STATUS_SSBD_UNLOCK \ 0x00000001 // ssbd unlock status //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_CC3XX_DEBUGMUX_SEL register. // //****************************************************************************** #define OCP_SHARED_CC3XX_DEBUGMUX_SEL_MEM_CC3XX_DEBUGMUX_SEL_M \ 0x0000FFFF // debug mux select register. Upper // 8 bits are used for debug module // selection. Lower 8 bit [7:0] used // inside debug module for selecting // module specific signals. // Bits[15:8: when set x"00" : GPRCM // debug bus. When "o1" : SDIO debug // debug bus when x"02" : // autonoumous SPI when x"03" : // TOPIC when x"04": memss when // x"25": mcu debug bus : APPS debug // when x"45": mcu debug bus : NWP // debug when x"65": mcu debug bus : // AHB2VBUS debug when x"85": mcu // debug bus : VBUS2HAB debug when // x"95": mcu debug bus : RCM debug // when x"A5": mcu debug bus : // crypto debug when x"06": WLAN // debug bus when x"07": debugss bus // when x"08": ADC debug when x"09": // SDIO PHY debug bus then "others" // : no debug is selected #define OCP_SHARED_CC3XX_DEBUGMUX_SEL_MEM_CC3XX_DEBUGMUX_SEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_ALT_PC_VAL_NW register. // //****************************************************************************** #define OCP_SHARED_ALT_PC_VAL_NW_MEM_ALT_PC_VAL_NW_M \ 0xFFFFFFFF // 32 bit. Program counter value // for 0x4 address when Alt_pc_en_nw // is set. #define OCP_SHARED_ALT_PC_VAL_NW_MEM_ALT_PC_VAL_NW_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_ALT_PC_VAL_APPS register. // //****************************************************************************** #define OCP_SHARED_ALT_PC_VAL_APPS_MEM_ALT_PC_VAL_APPS_M \ 0xFFFFFFFF // 32 bit. Program counter value // for 0x4 address when // Alt_pc_en_apps is set #define OCP_SHARED_ALT_PC_VAL_APPS_MEM_ALT_PC_VAL_APPS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SPARE_REG_4 register. // //****************************************************************************** #define OCP_SHARED_SPARE_REG_4_MEM_SPARE_REG_4_M \ 0xFFFFFFFE // HW register #define OCP_SHARED_SPARE_REG_4_MEM_SPARE_REG_4_S 1 #define OCP_SHARED_SPARE_REG_4_INVERT_D2D_INTERFACE \ 0x00000001 // Data to the top die launched at // negative edge instead of positive // edge. //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SPARE_REG_5 register. // //****************************************************************************** #define OCP_SHARED_SPARE_REG_5_MEM_SPARE_REG_5_M \ 0xFFFFFFFF // HW register #define OCP_SHARED_SPARE_REG_5_MEM_SPARE_REG_5_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SH_SPI_CS_MASK register. // //****************************************************************************** #define OCP_SHARED_SH_SPI_CS_MASK_MEM_SH_SPI_CS_MASK_M \ 0x0000000F // ( chip select 0 is unmasked // after reset. When ‘1’ : CS is // unmasked or else masked. Valid // configurations are 1000, 0100, // 0010 or 0001. Any other setting // can lead to unpredictable // behavior. #define OCP_SHARED_SH_SPI_CS_MASK_MEM_SH_SPI_CS_MASK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_CC3XX_DEVICE_TYPE register. // //****************************************************************************** #define OCP_SHARED_CC3XX_DEVICE_TYPE_DEVICE_TYPE_reserved_M \ 0x00000060 // reserved bits tied off "00". #define OCP_SHARED_CC3XX_DEVICE_TYPE_DEVICE_TYPE_reserved_S 5 #define OCP_SHARED_CC3XX_DEVICE_TYPE_DEVICE_TYPE_M \ 0x0000001F // CC3XX Device type information. #define OCP_SHARED_CC3XX_DEVICE_TYPE_DEVICE_TYPE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_MEM_TOPMUXCTRL_IFORCE register. // //****************************************************************************** #define OCP_SHARED_MEM_TOPMUXCTRL_IFORCE_MEM_TOPMUXCTRL_IFORCE1_M \ 0x000000F0 // [4] 1: switch between // WLAN_I2C_SCL and // TOP_GPIO_PORT4_I2C closes 0: // switch opens [5] 1: switch // between WLAN_I2C_SCL and // TOP_VSENSE_PORT closes 0: switch // opens [6] 1: switch between // WLAN_I2C_SCL and WLAN_ANA_TP4 // closes 0: switch opens [7] // Reserved #define OCP_SHARED_MEM_TOPMUXCTRL_IFORCE_MEM_TOPMUXCTRL_IFORCE1_S 4 #define OCP_SHARED_MEM_TOPMUXCTRL_IFORCE_MEM_TOPMUXCTRL_IFORCE_M \ 0x0000000F // [0] 1: switch between // WLAN_I2C_SDA and // TOP_GPIO_PORT3_I2C closes 0: // switch opens [1] 1: switch // between WLAN_I2C_SDA and // TOP_IFORCE_PORT closes 0: switch // opens [2] 1: switch between // WLAN_I2C_SDA and WLAN_ANA_TP3 // closes 0: switch opens [3] // Reserved #define OCP_SHARED_MEM_TOPMUXCTRL_IFORCE_MEM_TOPMUXCTRL_IFORCE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_CC3XX_DEV_PACKAGE_DETECT register. // //****************************************************************************** #define OCP_SHARED_CC3XX_DEV_PACKAGE_DETECT_DEV_PKG_DETECT \ 0x00000001 // when '0' indicates package type // is development. //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_AUTONMS_SPICLK_SEL register. // //****************************************************************************** #define OCP_SHARED_AUTONMS_SPICLK_SEL_MEM_AUTONOMOUS_BYPASS \ 0x00000002 // This bit is used to bypass MCPSI // autonomous mode .if this bit is 1 // autonomous MCSPI logic will be // bypassed and it will act as link // SPI #define OCP_SHARED_AUTONMS_SPICLK_SEL_MEM_AUTONMS_SPICLK_SEL \ 0x00000001 // This bit is used in SPI // Autonomous mode to switch clock // from system clock to SPI clk that // is coming from PAD. When value 1 // PAD SPI clk is used as system // clock in LPDS mode by SPI as well // as autonomous wrapper logic. //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_CC3XX_DEV_PADCONF register. // //****************************************************************************** #define OCP_SHARED_CC3XX_DEV_PADCONF_MEM_CC3XX_DEV_PADCONF_M \ 0x0000FFFF #define OCP_SHARED_CC3XX_DEV_PADCONF_MEM_CC3XX_DEV_PADCONF_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_IDMEM_TIM_UPDATE register. // //****************************************************************************** #define OCP_SHARED_IDMEM_TIM_UPDATE_MEM_IDMEM_TIM_UPDATE_M \ 0xFFFFFFFF #define OCP_SHARED_IDMEM_TIM_UPDATE_MEM_IDMEM_TIM_UPDATE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SPARE_REG_6 register. // //****************************************************************************** #define OCP_SHARED_SPARE_REG_6_MEM_SPARE_REG_6_M \ 0xFFFFFFFF // NWP Software register #define OCP_SHARED_SPARE_REG_6_MEM_SPARE_REG_6_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_SPARE_REG_7 register. // //****************************************************************************** #define OCP_SHARED_SPARE_REG_7_MEM_SPARE_REG_7_M \ 0xFFFFFFFF // NWP Software register #define OCP_SHARED_SPARE_REG_7_MEM_SPARE_REG_7_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_APPS_WLAN_ORBIT register. // //****************************************************************************** #define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_spare_M \ 0xFFFFFC00 // Spare bit #define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_spare_S 10 #define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_status \ 0x00000200 // A rising edge on this bit // indicates that the test case // passes. This bit would be brought // out on the pin interface during // ORBIT. #define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_exec \ 0x00000100 // This register bit is writable by // the FW and when set to 1 it // indicates the start of a test // execution. A failing edge on this // bit indicates that the test // execution is complete. This bit // would be brought out on the pin // interface during ORBIT. #define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_id_M \ 0x000000FC // Implies the test case ID that // needs to run. #define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_id_S 2 #define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_halt_proc \ 0x00000002 // This bit is used to trigger the // execution of test cases within // the (ROM based) IP. #define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_mode \ 0x00000001 // When this bit is 1 it implies // ORBIT mode of operation and the // (ROM based) IP start the // execution from a test case // perspective //****************************************************************************** // // The following are defines for the bit fields in the // OCP_SHARED_O_APPS_WLAN_SCRATCH_PAD register. // //****************************************************************************** #define OCP_SHARED_APPS_WLAN_SCRATCH_PAD_MEM_APPS_WLAN_SCRATCH_PAD_M \ 0xFFFFFFFF // scratch pad register. #define OCP_SHARED_APPS_WLAN_SCRATCH_PAD_MEM_APPS_WLAN_SCRATCH_PAD_S 0 #endif // __HW_OCP_SHARED_H__ micropython-1.12/ports/cc3200/hal/inc/hw_shamd5.h000066400000000000000000001741211357706137100214360ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_SHAMD5_H__ #define __HW_SHAMD5_H__ //***************************************************************************** // // The following are defines for the SHAMD5_P register offsets. // //***************************************************************************** #define SHAMD5_O_ODIGEST_A 0x00000000 // WRITE: Outer Digest [127:96] for // MD5 [159:128] for SHA-1 [255:224] // for SHA-2 / HMAC Key [31:0] for // HMAC key proc READ: Outer Digest // [127:96] for MD5 [159:128] for // SHA-1 [255:224] for SHA-2 #define SHAMD5_O_ODIGEST_B 0x00000004 // WRITE: Outer Digest [95:64] for // MD5 [127:96] for SHA-1 [223:192] // for SHA-2 / HMAC Key [63:32] for // HMAC key proc READ: Outer Digest // [95:64] for MD5 [127:96] for // SHA-1 [223:192] for SHA-2 #define SHAMD5_O_ODIGEST_C 0x00000008 // WRITE: Outer Digest [63:32] for // MD5 [95:64] for SHA-1 [191:160] // for SHA-2 / HMAC Key [95:64] for // HMAC key proc READ: Outer Digest // [63:32] for MD5 [95:64] for SHA-1 // [191:160] for SHA-2 #define SHAMD5_O_ODIGEST_D 0x0000000C // WRITE: Outer Digest [31:0] for // MD5 [63:31] for SHA-1 [159:128] // for SHA-2 / HMAC Key [127:96] for // HMAC key proc READ: Outer Digest // [31:0] for MD5 [63:32] for SHA-1 // [159:128] for SHA-2 #define SHAMD5_O_ODIGEST_E 0x00000010 // WRITE: Outer Digest [31:0] for // SHA-1 [127:96] for SHA-2 / HMAC // Key [159:128] for HMAC key proc // READ: Outer Digest [31:0] for // SHA-1 [127:96] for SHA-2 #define SHAMD5_O_ODIGEST_F 0x00000014 // WRITE: Outer Digest [95:64] for // SHA-2 / HMAC Key [191:160] for // HMAC key proc READ: Outer Digest // [95:64] for SHA-2 #define SHAMD5_O_ODIGEST_G 0x00000018 // WRITE: Outer Digest [63:32] for // SHA-2 / HMAC Key [223:192] for // HMAC key proc READ: Outer Digest // [63:32] for SHA-2 #define SHAMD5_O_ODIGEST_H 0x0000001C // WRITE: Outer Digest [31:0] for // SHA-2 / HMAC Key [255:224] for // HMAC key proc READ: Outer Digest // [31:0] for SHA-2 #define SHAMD5_O_IDIGEST_A 0x00000020 // WRITE: Inner / Initial Digest // [127:96] for MD5 [159:128] for // SHA-1 [255:224] for SHA-2 / HMAC // Key [287:256] for HMAC key proc // READ: Intermediate / Inner Digest // [127:96] for MD5 [159:128] for // SHA-1 [255:224] for SHA-2 / // Result Digest/MAC [127:96] for // MD5 [159:128] for SHA-1 [223:192] // for SHA-2 224 [255:224] for SHA-2 // 256 #define SHAMD5_O_IDIGEST_B 0x00000024 // WRITE: Inner / Initial Digest // [95:64] for MD5 [127:96] for // SHA-1 [223:192] for SHA-2 / HMAC // Key [319:288] for HMAC key proc // READ: Intermediate / Inner Digest // [95:64] for MD5 [127:96] for // SHA-1 [223:192] for SHA-2 / // Result Digest/MAC [95:64] for MD5 // [127:96] for SHA-1 [191:160] for // SHA-2 224 [223:192] for SHA-2 256 #define SHAMD5_O_IDIGEST_C 0x00000028 // WRITE: Inner / Initial Digest // [63:32] for MD5 [95:64] for SHA-1 // [191:160] for SHA- 2 / HMAC Key // [351:320] for HMAC key proc READ: // Intermediate / Inner Digest // [63:32] for MD5 [95:64] for SHA-1 // [191:160] for SHA-2 / Result // Digest/MAC [63:32] for MD5 // [95:64] for SHA-1 [159:128] for // SHA-2 224 [191:160] for SHA-2 256 #define SHAMD5_O_IDIGEST_D 0x0000002C // WRITE: Inner / Initial Digest // [31:0] for MD5 [63:32] for SHA-1 // [159:128] for SHA-2 / HMAC Key // [383:352] for HMAC key proc READ: // Intermediate / Inner Digest // [31:0] for MD5 [63:32] for SHA-1 // [159:128] for SHA-2 / Result // Digest/MAC [31:0] for MD5 [63:32] // for SHA-1 [127:96] for SHA-2 224 // [159:128] for SHA-2 256 #define SHAMD5_O_IDIGEST_E 0x00000030 // WRITE: Inner / Initial Digest // [31:0] for SHA-1 [127:96] for // SHA-2 / HMAC Key [415:384] for // HMAC key proc READ: Intermediate // / Inner Digest [31:0] for SHA-1 // [127:96] for SHA-2 / Result // Digest/MAC [31:0] for SHA-1 // [95:64] for SHA-2 224 [127:96] // for SHA-2 256 #define SHAMD5_O_IDIGEST_F 0x00000034 // WRITE: Inner / Initial Digest // [95:64] for SHA-2 / HMAC Key // [447:416] for HMAC key proc READ: // Intermediate / Inner Digest // [95:64] for SHA-2 / Result // Digest/MAC [63:32] for SHA-2 224 // [95:64] for SHA-2 256 #define SHAMD5_O_IDIGEST_G 0x00000038 // WRITE: Inner / Initial Digest // [63:32] for SHA-2 / HMAC Key // [479:448] for HMAC key proc READ: // Intermediate / Inner Digest // [63:32] for SHA-2 / Result // Digest/MAC [31:0] for SHA-2 224 // [63:32] for SHA-2 256 #define SHAMD5_O_IDIGEST_H 0x0000003C // WRITE: Inner / Initial Digest // [31:0] for SHA-2 / HMAC Key // [511:480] for HMAC key proc READ: // Intermediate / Inner Digest // [31:0] for SHA-2 / Result // Digest/MAC [31:0] for SHA-2 256 #define SHAMD5_O_DIGEST_COUNT 0x00000040 // WRITE: Initial Digest Count // ([31:6] only [5:0] assumed 0) // READ: Result / IntermediateDigest // Count The initial digest byte // count for hash/HMAC continue // operations (HMAC Key Processing = // 0 and Use Algorithm Constants = // 0) on the Secure World must be // written to this register prior to // starting the operation by writing // to S_HASH_MODE. When either HMAC // Key Processing is 1 or Use // Algorithm Constants is 1 this // register does not need to be // written it will be overwritten // with 64 (1 hash block of key XOR // ipad) or 0 respectively // automatically. When starting a // HMAC operation from pre-computes // (HMAC Key Processing is 0) then // the value 64 must be written here // to compensate for the appended // key XOR ipad block. Note that the // value written should always be a // 64 byte multiple the lower 6 bits // written are ignored. The updated // digest byte count (initial digest // byte count + bytes processed) can // be read from this register when // the status register indicates // that the operation is done or // suspended due to a context switch // request or when a Secure World // context out DMA is requested. In // Advanced DMA mode when not // suspended with a partial result // reading the SHAMD5_DIGEST_COUNT // register triggers the Hash/HMAC // Engine to start the next context // input DMA. Therefore reading the // SHAMD5_DIGEST_COUNT register // should always be the last // context-read action if not // suspended with a partial result // (i.e. PartHashReady interrupt not // pending). #define SHAMD5_O_MODE 0x00000044 // Register SHAMD5_MODE #define SHAMD5_O_LENGTH 0x00000048 // WRITE: Block Length / Remaining // Byte Count (bytes) READ: // Remaining Byte Count. The value // programmed MUST be a 64-byte // multiple if Close Hash is set to // 0. This register is also the // trigger to start processing: once // this register is written the core // will commence requesting input // data via DMA or IRQ (if // programmed length > 0) and start // processing. The remaining byte // count for the active operation // can be read from this register // when the interrupt status // register indicates that the // operation is suspended due to a // context switch request. #define SHAMD5_O_DATA0_IN 0x00000080 // Data input message 0 #define SHAMD5_O_DATA1_IN 0x00000084 // Data input message 1 #define SHAMD5_O_DATA2_IN 0x00000088 // Data input message 2 #define SHAMD5_O_DATA3_IN 0x0000008C // Data input message 3 #define SHAMD5_O_DATA4_IN 0x00000090 // Data input message 4 #define SHAMD5_O_DATA5_IN 0x00000094 // Data input message 5 #define SHAMD5_O_DATA6_IN 0x00000098 // Data input message 6 #define SHAMD5_O_DATA7_IN 0x0000009C // Data input message 7 #define SHAMD5_O_DATA8_IN 0x000000A0 // Data input message 8 #define SHAMD5_O_DATA9_IN 0x000000A4 // Data input message 9 #define SHAMD5_O_DATA10_IN 0x000000A8 // Data input message 10 #define SHAMD5_O_DATA11_IN 0x000000AC // Data input message 11 #define SHAMD5_O_DATA12_IN 0x000000B0 // Data input message 12 #define SHAMD5_O_DATA13_IN 0x000000B4 // Data input message 13 #define SHAMD5_O_DATA14_IN 0x000000B8 // Data input message 14 #define SHAMD5_O_DATA15_IN 0x000000BC // Data input message 15 #define SHAMD5_O_REVISION 0x00000100 // Register SHAMD5_REV #define SHAMD5_O_SYSCONFIG 0x00000110 // Register SHAMD5_SYSCONFIG #define SHAMD5_O_SYSSTATUS 0x00000114 // Register SHAMD5_SYSSTATUS #define SHAMD5_O_IRQSTATUS 0x00000118 // Register SHAMD5_IRQSTATUS #define SHAMD5_O_IRQENABLE 0x0000011C // Register SHAMD5_IRQENABLE. The // SHAMD5_IRQENABLE register contains // an enable bit for each unique // interrupt for the public side. An // interrupt is enabled when both // the global enable in // SHAMD5_SYSCONFIG (PIT_en) and the // bit in this register are both set // to 1. An interrupt that is // enabled is propagated to the // SINTREQUEST_P output. Please note // that the dedicated partial hash // output (SINTREQUEST_PART_P) is // not affected by this register it // is only affected by the global // enable SHAMD5_SYSCONFIG (PIT_en). #define SHAMD5_O_HASH512_ODIGEST_A \ 0x00000200 #define SHAMD5_O_HASH512_ODIGEST_B \ 0x00000204 #define SHAMD5_O_HASH512_ODIGEST_C \ 0x00000208 #define SHAMD5_O_HASH512_ODIGEST_D \ 0x0000020C #define SHAMD5_O_HASH512_ODIGEST_E \ 0x00000210 #define SHAMD5_O_HASH512_ODIGEST_F \ 0x00000214 #define SHAMD5_O_HASH512_ODIGEST_G \ 0x00000218 #define SHAMD5_O_HASH512_ODIGEST_H \ 0x0000021C #define SHAMD5_O_HASH512_ODIGEST_I \ 0x00000220 #define SHAMD5_O_HASH512_ODIGEST_J \ 0x00000224 #define SHAMD5_O_HASH512_ODIGEST_K \ 0x00000228 #define SHAMD5_O_HASH512_ODIGEST_L \ 0x0000022C #define SHAMD5_O_HASH512_ODIGEST_M \ 0x00000230 #define SHAMD5_O_HASH512_ODIGEST_N \ 0x00000234 #define SHAMD5_O_HASH512_ODIGEST_O \ 0x00000238 #define SHAMD5_O_HASH512_ODIGEST_P \ 0x0000023C #define SHAMD5_O_HASH512_IDIGEST_A \ 0x00000240 #define SHAMD5_O_HASH512_IDIGEST_B \ 0x00000244 #define SHAMD5_O_HASH512_IDIGEST_C \ 0x00000248 #define SHAMD5_O_HASH512_IDIGEST_D \ 0x0000024C #define SHAMD5_O_HASH512_IDIGEST_E \ 0x00000250 #define SHAMD5_O_HASH512_IDIGEST_F \ 0x00000254 #define SHAMD5_O_HASH512_IDIGEST_G \ 0x00000258 #define SHAMD5_O_HASH512_IDIGEST_H \ 0x0000025C #define SHAMD5_O_HASH512_IDIGEST_I \ 0x00000260 #define SHAMD5_O_HASH512_IDIGEST_J \ 0x00000264 #define SHAMD5_O_HASH512_IDIGEST_K \ 0x00000268 #define SHAMD5_O_HASH512_IDIGEST_L \ 0x0000026C #define SHAMD5_O_HASH512_IDIGEST_M \ 0x00000270 #define SHAMD5_O_HASH512_IDIGEST_N \ 0x00000274 #define SHAMD5_O_HASH512_IDIGEST_O \ 0x00000278 #define SHAMD5_O_HASH512_IDIGEST_P \ 0x0000027C #define SHAMD5_O_HASH512_DIGEST_COUNT \ 0x00000280 #define SHAMD5_O_HASH512_MODE 0x00000284 #define SHAMD5_O_HASH512_LENGTH 0x00000288 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_ODIGEST_A register. // //****************************************************************************** #define SHAMD5_ODIGEST_A_DATA_M 0xFFFFFFFF // data #define SHAMD5_ODIGEST_A_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_ODIGEST_B register. // //****************************************************************************** #define SHAMD5_ODIGEST_B_DATA_M 0xFFFFFFFF // data #define SHAMD5_ODIGEST_B_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_ODIGEST_C register. // //****************************************************************************** #define SHAMD5_ODIGEST_C_DATA_M 0xFFFFFFFF // data #define SHAMD5_ODIGEST_C_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_ODIGEST_D register. // //****************************************************************************** #define SHAMD5_ODIGEST_D_DATA_M 0xFFFFFFFF // data #define SHAMD5_ODIGEST_D_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_ODIGEST_E register. // //****************************************************************************** #define SHAMD5_ODIGEST_E_DATA_M 0xFFFFFFFF // data #define SHAMD5_ODIGEST_E_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_ODIGEST_F register. // //****************************************************************************** #define SHAMD5_ODIGEST_F_DATA_M 0xFFFFFFFF // data #define SHAMD5_ODIGEST_F_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_ODIGEST_G register. // //****************************************************************************** #define SHAMD5_ODIGEST_G_DATA_M 0xFFFFFFFF // data #define SHAMD5_ODIGEST_G_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_ODIGEST_H register. // //****************************************************************************** #define SHAMD5_ODIGEST_H_DATA_M 0xFFFFFFFF // data #define SHAMD5_ODIGEST_H_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IDIGEST_A register. // //****************************************************************************** #define SHAMD5_IDIGEST_A_DATA_M 0xFFFFFFFF // data #define SHAMD5_IDIGEST_A_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IDIGEST_B register. // //****************************************************************************** #define SHAMD5_IDIGEST_B_DATA_M 0xFFFFFFFF // data #define SHAMD5_IDIGEST_B_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IDIGEST_C register. // //****************************************************************************** #define SHAMD5_IDIGEST_C_DATA_M 0xFFFFFFFF // data #define SHAMD5_IDIGEST_C_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IDIGEST_D register. // //****************************************************************************** #define SHAMD5_IDIGEST_D_DATA_M 0xFFFFFFFF // data #define SHAMD5_IDIGEST_D_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IDIGEST_E register. // //****************************************************************************** #define SHAMD5_IDIGEST_E_DATA_M 0xFFFFFFFF // data #define SHAMD5_IDIGEST_E_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IDIGEST_F register. // //****************************************************************************** #define SHAMD5_IDIGEST_F_DATA_M 0xFFFFFFFF // data #define SHAMD5_IDIGEST_F_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IDIGEST_G register. // //****************************************************************************** #define SHAMD5_IDIGEST_G_DATA_M 0xFFFFFFFF // data #define SHAMD5_IDIGEST_G_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IDIGEST_H register. // //****************************************************************************** #define SHAMD5_IDIGEST_H_DATA_M 0xFFFFFFFF // data #define SHAMD5_IDIGEST_H_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_DIGEST_COUNT register. // //****************************************************************************** #define SHAMD5_DIGEST_COUNT_DATA_M \ 0xFFFFFFFF // data #define SHAMD5_DIGEST_COUNT_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_MODE register. // //****************************************************************************** #define SHAMD5_MODE_HMAC_OUTER_HASH \ 0x00000080 // The HMAC Outer Hash is performed // on the hash digest when the inner // hash hash finished (block length // exhausted and final hash // performed if close_hash is 1). // This bit should normally be set // together with close_hash to // finish the inner hash first or // Block Length should be zero (HMAC // continue with the just outer hash // to be done). Auto cleared // internally when outer hash // performed. 0 No operation 1 hmac // processing #define SHAMD5_MODE_HMAC_KEY_PROC \ 0x00000020 // Performs HMAC key processing on // the 512 bit HMAC key loaded into // the SHAMD5_IDIGEST_{A to H} and // SHAMD5_ODIGEST_{A to H} register // block. Once HMAC key processing // is finished this bit is // automatically cleared and the // resulting Inner and Outer digest // is available from // SHAMD5_IDIGEST_{A to H} and // SHAMD5_ODIGEST_{A to H} // respectively after which regular // hash processing (using // SHAMD5_IDIGEST_{A to H} as initial // digest) will commence until the // Block Length is exhausted. 0 No // operation. 1 Hmac processing. #define SHAMD5_MODE_CLOSE_HASH 0x00000010 // Performs the padding the // hash/HMAC will be 'closed' at the // end of the block as per // MD5/SHA-1/SHA-2 specification // (i.e. appropriate padding is // added) or no padding is done // allowing the hash to be continued // later. However if the hash/HMAC // is not closed then the Block // Length MUST be a multiple of 64 // bytes to ensure correct // operation. Auto cleared // internally when hash closed. 0 No // padding hash computation can be // contimued. 1 Last packet will be // padded. #define SHAMD5_MODE_ALGO_CONSTANT \ 0x00000008 // The initial digest register will // be overwritten with the algorithm // constants for the selected // algorithm when hashing and the // initial digest count register // will be reset to 0. This will // start a normal hash operation. // When continuing an existing hash // or when performing an HMAC // operation this register must be // set to 0 and the // intermediate/inner digest or HMAC // key and digest count need to be // written to the context input // registers prior to writing // SHAMD5_MODE. Auto cleared // internally after first block // processed. 0 Use pre-calculated // digest (from an other operation) // 1 Use constants of the selected // algo. #define SHAMD5_MODE_ALGO_M 0x00000006 // These bits select the hash // algorithm to be used for // processing: 0x0 md5_128 algorithm // 0x1 sha1_160 algorithm 0x2 // sha2_224 algorithm 0x3 sha2_256 // algorithm #define SHAMD5_MODE_ALGO_S 1 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_LENGTH register. // //****************************************************************************** #define SHAMD5_LENGTH_DATA_M 0xFFFFFFFF // data #define SHAMD5_LENGTH_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA0_IN register. // //****************************************************************************** #define SHAMD5_DATA0_IN_DATA0_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA0_IN_DATA0_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA1_IN register. // //****************************************************************************** #define SHAMD5_DATA1_IN_DATA1_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA1_IN_DATA1_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA2_IN register. // //****************************************************************************** #define SHAMD5_DATA2_IN_DATA2_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA2_IN_DATA2_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA3_IN register. // //****************************************************************************** #define SHAMD5_DATA3_IN_DATA3_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA3_IN_DATA3_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA4_IN register. // //****************************************************************************** #define SHAMD5_DATA4_IN_DATA4_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA4_IN_DATA4_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA5_IN register. // //****************************************************************************** #define SHAMD5_DATA5_IN_DATA5_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA5_IN_DATA5_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA6_IN register. // //****************************************************************************** #define SHAMD5_DATA6_IN_DATA6_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA6_IN_DATA6_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA7_IN register. // //****************************************************************************** #define SHAMD5_DATA7_IN_DATA7_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA7_IN_DATA7_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA8_IN register. // //****************************************************************************** #define SHAMD5_DATA8_IN_DATA8_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA8_IN_DATA8_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA9_IN register. // //****************************************************************************** #define SHAMD5_DATA9_IN_DATA9_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA9_IN_DATA9_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA10_IN register. // //****************************************************************************** #define SHAMD5_DATA10_IN_DATA10_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA10_IN_DATA10_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA11_IN register. // //****************************************************************************** #define SHAMD5_DATA11_IN_DATA11_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA11_IN_DATA11_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA12_IN register. // //****************************************************************************** #define SHAMD5_DATA12_IN_DATA12_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA12_IN_DATA12_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA13_IN register. // //****************************************************************************** #define SHAMD5_DATA13_IN_DATA13_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA13_IN_DATA13_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA14_IN register. // //****************************************************************************** #define SHAMD5_DATA14_IN_DATA14_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA14_IN_DATA14_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_DATA15_IN register. // //****************************************************************************** #define SHAMD5_DATA15_IN_DATA15_IN_M \ 0xFFFFFFFF // data #define SHAMD5_DATA15_IN_DATA15_IN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_REVISION register. // //****************************************************************************** #define SHAMD5_REVISION_SCHEME_M 0xC0000000 #define SHAMD5_REVISION_SCHEME_S 30 #define SHAMD5_REVISION_FUNC_M 0x0FFF0000 // Function indicates a software // compatible module family. If // there is no level of software // compatibility a new Func number // (and hence REVISION) should be // assigned. #define SHAMD5_REVISION_FUNC_S 16 #define SHAMD5_REVISION_R_RTL_M 0x0000F800 // RTL Version (R) maintained by IP // design owner. RTL follows a // numbering such as X.Y.R.Z which // are explained in this table. R // changes ONLY when: (1) PDS // uploads occur which may have been // due to spec changes (2) Bug fixes // occur (3) Resets to '0' when X or // Y changes. Design team has an // internal 'Z' (customer invisible) // number which increments on every // drop that happens due to DV and // RTL updates. Z resets to 0 when R // increments. #define SHAMD5_REVISION_R_RTL_S 11 #define SHAMD5_REVISION_X_MAJOR_M \ 0x00000700 // Major Revision (X) maintained by // IP specification owner. X changes // ONLY when: (1) There is a major // feature addition. An example // would be adding Master Mode to // Utopia Level2. The Func field (or // Class/Type in old PID format) // will remain the same. X does NOT // change due to: (1) Bug fixes (2) // Change in feature parameters. #define SHAMD5_REVISION_X_MAJOR_S 8 #define SHAMD5_REVISION_CUSTOM_M 0x000000C0 #define SHAMD5_REVISION_CUSTOM_S 6 #define SHAMD5_REVISION_Y_MINOR_M \ 0x0000003F // Minor Revision (Y) maintained by // IP specification owner. Y changes // ONLY when: (1) Features are // scaled (up or down). Flexibility // exists in that this feature // scalability may either be // represented in the Y change or a // specific register in the IP that // indicates which features are // exactly available. (2) When // feature creeps from Is-Not list // to Is list. But this may not be // the case once it sees silicon; in // which case X will change. Y does // NOT change due to: (1) Bug fixes // (2) Typos or clarifications (3) // major functional/feature // change/addition/deletion. Instead // these changes may be reflected // via R S X as applicable. Spec // owner maintains a // customer-invisible number 'S' // which changes due to: (1) // Typos/clarifications (2) Bug // documentation. Note that this bug // is not due to a spec change but // due to implementation. // Nevertheless the spec tracks the // IP bugs. An RTL release (say for // silicon PG1.1) that occurs due to // bug fix should document the // corresponding spec number (X.Y.S) // in its release notes. #define SHAMD5_REVISION_Y_MINOR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_SYSCONFIG register. // //****************************************************************************** #define SHAMD5_SYSCONFIG_PADVANCED \ 0x00000080 // If set to 1 Advanced mode is // enabled for the Secure World. If // set to 0 Legacy mode is enabled // for the Secure World. #define SHAMD5_SYSCONFIG_PCONT_SWT \ 0x00000040 // Finish all pending data and // context DMA input requests (but // will not assert any new requests) // finish processing all data in the // module and provide a saved // context (partial hash result // updated digest count remaining // length updated mode information // where applicable) for the last // operation that was interrupted so // that it can be resumed later. #define SHAMD5_SYSCONFIG_PDMA_EN 0x00000008 #define SHAMD5_SYSCONFIG_PIT_EN 0x00000004 //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_SYSSTATUS register. // //****************************************************************************** #define SHAMD5_SYSSTATUS_RESETDONE \ 0x00000001 // data //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IRQSTATUS register. // //****************************************************************************** #define SHAMD5_IRQSTATUS_CONTEXT_READY \ 0x00000008 // indicates that the secure side // context input registers are // available for a new context for // the next packet to be processed. #define SHAMD5_IRQSTATUS_PARTHASH_READY \ 0x00000004 // After a secure side context // switch request this bit will read // as 1 indicating that the saved // context is available from the // secure side context output // registers. Note that if the // context switch request coincides // with a final hash (when hashing) // or an outer hash (when doing // HMAC) that PartHashReady will not // become active but a regular // Output Ready will occur instead // (indicating that the result is // final and therefore no // continuation is required). #define SHAMD5_IRQSTATUS_INPUT_READY \ 0x00000002 // indicates that the secure side // data FIFO is ready to receive the // next 64 byte data block. #define SHAMD5_IRQSTATUS_OUTPUT_READY \ 0x00000001 // Indicates that a (partial) // result or saved context is // available from the secure side // context output registers. //****************************************************************************** // // The following are defines for the bit fields in the SHAMD5_O_IRQENABLE register. // //****************************************************************************** #define SHAMD5_IRQENABLE_M_CONTEXT_READY \ 0x00000008 // mask for context ready #define SHAMD5_IRQENABLE_M_PARTHASH_READY \ 0x00000004 // mask for partial hash #define SHAMD5_IRQENABLE_M_INPUT_READY \ 0x00000002 // mask for input_ready #define SHAMD5_IRQENABLE_M_OUTPUT_READY \ 0x00000001 // mask for output_ready //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_A register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_A_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_A_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_B register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_B_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_B_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_C register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_C_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_C_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_D register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_D_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_D_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_E register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_E_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_E_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_F register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_F_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_F_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_G register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_G_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_G_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_H register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_H_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_H_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_I register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_I_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_I_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_J register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_J_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_J_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_K register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_K_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_K_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_L register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_L_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_L_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_M register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_M_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_M_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_N register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_N_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_N_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_O register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_O_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_O_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_ODIGEST_P register. // //****************************************************************************** #define SHAMD5_HASH512_ODIGEST_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_ODIGEST_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_A register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_A_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_A_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_B register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_B_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_B_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_C register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_C_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_C_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_D register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_D_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_D_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_E register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_E_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_E_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_F register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_F_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_F_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_G register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_G_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_G_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_H register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_H_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_H_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_I register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_I_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_I_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_J register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_J_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_J_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_K register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_K_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_K_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_L register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_L_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_L_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_M register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_M_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_M_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_N register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_N_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_N_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_O register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_O_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_O_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_IDIGEST_P register. // //****************************************************************************** #define SHAMD5_HASH512_IDIGEST_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_IDIGEST_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_DIGEST_COUNT register. // //****************************************************************************** #define SHAMD5_HASH512_DIGEST_COUNT_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_DIGEST_COUNT_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_MODE register. // //****************************************************************************** #define SHAMD5_HASH512_MODE_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_MODE_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // SHAMD5_O_HASH512_LENGTH register. // //****************************************************************************** #define SHAMD5_HASH512_LENGTH_DATA_M \ 0xFFFFFFFF #define SHAMD5_HASH512_LENGTH_DATA_S 0 #endif // __HW_SHAMD5_H__ micropython-1.12/ports/cc3200/hal/inc/hw_stack_die_ctrl.h000066400000000000000000001211611357706137100232230ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_STACK_DIE_CTRL_H__ #define __HW_STACK_DIE_CTRL_H__ //***************************************************************************** // // The following are defines for the STACK_DIE_CTRL register offsets. // //***************************************************************************** #define STACK_DIE_CTRL_O_STK_UP_RESET \ 0x00000000 // Can be written only by Base // Processor. Writing to this // register will reset the stack // processor reset will be // de-asserted upon clearing this // register. #define STACK_DIE_CTRL_O_SR_MASTER_PRIORITY \ 0x00000004 // This register defines who among // base processor and stack // processor have highest priority // for Sram Access. Can be written // only by Base Processor. #define STACK_DIE_CTRL_O_STK_SR_ACC_CTL_BK2 \ 0x00000008 // In Spinlock mode this Register // defines who among base processor // and stack processor have access // to Sram Bank2 right now. In // Handshake mode this Register // defines who among base processor // and stack processor have access // to Sram Bank2 and Bank3 right // now. Its Clear only register and // is set by hardware. Lower bit can // be cleared only by Base Processor // and Upper bit Cleared only by the // Stack processor. #define STACK_DIE_CTRL_O_BASE_UP_ACC_REQ_BK2 \ 0x0000000C // In Spinlock mode whenever Base // processor wants the access to // Sram Bank2 it should request for // it by writing into this register. // It'll get interrupt whenever it // is granted. In Handshake mode // this bit will be set by Stack // processor. Its a set only bit and // is cleared by HW when the request // is granted. #define STACK_DIE_CTRL_O_STK_UP_ACC_REQ_BK2 \ 0x00000010 // In Spinlock mode Whenever Stack // processor wants the access to // Sram Bank2 it should request for // it by writing into this register. // It'll get interrupt whenever it // is granted. In Handshake mode // this bit will be set by the Base // processor. Its a set only bit and // is cleared by HW when the request // is granted. #define STACK_DIE_CTRL_O_STK_SR_ACC_CTL_BK3 \ 0x00000014 // Register defines who among base // processor and stack processor // have access to Sram Bank3 right // now. Its Clear only register and // is set by hardware. Lower bit can // be cleared only by Base Processor // and Upper bit Cleared only by the // Stack processor. #define STACK_DIE_CTRL_O_BASE_UP_ACC_REQ_BK3 \ 0x00000018 // In Spinlock mode whenever Base // processor wants the access to // Sram Bank3 it should request for // it by writing into this register. // It'll get interrupt whenever it // is granted. In Handshake mode // this bit will be set by Stack // processor. Its a set only bit and // is cleared by HW when the request // is granted. #define STACK_DIE_CTRL_O_STK_UP_ACC_REQ_BK3 \ 0x0000001C // In Spinlock mode Whenever Stack // processor wants the access to // Sram Bank3 it should request for // it by writing into this register. // It'll get interrupt whenever it // is granted. In Handshake mode // this bit will be set by the Base // processor. Its a set only bit and // is cleared by HW when the request // is granted. #define STACK_DIE_CTRL_O_RDSM_CFG_CPU \ 0x00000020 // Read State Machine timing // configuration register. Generally // Bit 4 and 3 will be identical. // For stacked die always 43 are 0 // and 6:5 == 1 for 120Mhz. #define STACK_DIE_CTRL_O_RDSM_CFG_EE \ 0x00000024 // Read State Machine timing // configuration register. Generally // Bit 4 and 3 will be identical. // For stacked die always 43 are 0 // and 6:5 == 1 for 120Mhz. #define STACK_DIE_CTRL_O_BASE_UP_IRQ_LOG \ 0x00000028 // Reading this register Base // procesor will able to know the // reason for the interrupt. This is // clear only register - set by HW // upon an interrupt to Base // processor and can be cleared only // by BASE processor. #define STACK_DIE_CTRL_O_STK_UP_IRQ_LOG \ 0x0000002C // Reading this register Stack // procesor will able to know the // reason for the interrupt. This is // clear only register - set by HW // upon an interrupt to Stack // processor and can be cleared only // by Stack processor. #define STACK_DIE_CTRL_O_STK_CLK_EN \ 0x00000030 // Can be written only by base // processor. Controls the enable // pin of the cgcs for the clocks // going to CM3 dft ctrl block and // Sram. #define STACK_DIE_CTRL_O_SPIN_LOCK_MODE \ 0x00000034 // Can be written only by the base // processor. Decides the ram // sharing mode :: handshake or // Spinlock mode. #define STACK_DIE_CTRL_O_BUS_FAULT_ADDR \ 0x00000038 // Stores the last bus fault // address. #define STACK_DIE_CTRL_O_BUS_FAULT_CLR \ 0x0000003C // write only registers on read // returns 0.W Write 1 to clear the // bust fault to store the new bus // fault address #define STACK_DIE_CTRL_O_RESET_CAUSE \ 0x00000040 // Reset cause value captured from // the ICR_CLKRST block. #define STACK_DIE_CTRL_O_WDOG_TIMER_EVENT \ 0x00000044 // Watchdog timer event value // captured from the ICR_CLKRST // block #define STACK_DIE_CTRL_O_DMA_REQ \ 0x00000048 // To send Dma Request to bottom // die. #define STACK_DIE_CTRL_O_SRAM_JUMP_OFFSET_ADDR \ 0x0000004C // Address offset within SRAM to // which CM3 should jump after // reset. #define STACK_DIE_CTRL_O_SW_REG1 \ 0x00000050 // These are sw registers for // topdie processor and bottom die // processor to communicate. Both // can set and read these registers. // In case of write clash bottom // die's processor wins and top die // processor access is ignored. #define STACK_DIE_CTRL_O_SW_REG2 \ 0x00000054 // These are sw registers for // topdie processor and bottom die // processor to communicate. Both // can set and read these registers. // In case of write clash bottom // die's processor wins and top die // processor access is ignored. #define STACK_DIE_CTRL_O_FMC_SLEEP_CTL \ 0x00000058 // By posting the request Flash can // be put into low-power mode // (Sleep) without powering down the // Flash. Earlier (in Garnet) this // was fully h/w controlled and the // control for this was coming from // SysCtl while entering into Cortex // Deep-sleep mode. But for our // device the D2D i/f doesnt support // this. The Firmware has to program // the register in the top-die for // entering into this mode and wait // for an interrupt. #define STACK_DIE_CTRL_O_MISC_CTL \ 0x0000005C // Miscellanious control register. #define STACK_DIE_CTRL_O_SW_DFT_CTL \ 0x000000FC // DFT control and status bits #define STACK_DIE_CTRL_O_PADN_CTL_0 \ 0x00000100 // Mainly for For controlling the // pads OEN pins. There are total 60 // pads and hence 60 control registe // i.e n value varies from 0 to 59. // Here is the mapping for the // pad_ctl register number and the // functionality : 0 D2DPAD_DMAREQ1 // 1 D2DPAD_DMAREQ0 2 // D2DPAD_INT2BASE 3 D2DPAD_PIOSC 4 // D2DPAD_RST_N 5 D2DPAD_POR_RST_N 6 // D2DPAD_HCLK 7 D2DPAD_JTAG_TDO 8 // D2DPAD_JTAG_TCK 9 D2DPAD_JTAG_TMS // 10 D2DPAD_JTAG_TDI 11-27 // D2DPAD_FROMSTACK[D2D_FROMSTACK_SIZE // -1:0] 28-56 D2DPAD_TOSTACK // [D2D_TOSTACK_SIZE -1:0] 57-59 // D2DPAD_SPARE [D2D_SPARE_PAD_SIZE // -1:0] 0:00 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_STK_UP_RESET register. // //****************************************************************************** #define STACK_DIE_CTRL_STK_UP_RESET_UP_RESET \ 0x00000001 // 1 :Assert Reset 0 : Deassert the // Reset //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_SR_MASTER_PRIORITY register. // //****************************************************************************** #define STACK_DIE_CTRL_SR_MASTER_PRIORITY_PRIORITY_M \ 0x00000003 // 00 : Equal Priority 01 : Stack // Processor have priority 10 : Base // Processor have priority 11 : // Unused #define STACK_DIE_CTRL_SR_MASTER_PRIORITY_PRIORITY_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_STK_SR_ACC_CTL_BK2 register. // //****************************************************************************** #define STACK_DIE_CTRL_STK_SR_ACC_CTL_BK2_STK_UP_ACCSS \ 0x00000002 // Stack Processor should clear it // when it is done with the sram // bank usage. Set by HW It is set // when Stack Processor is granted // the access to this bank #define STACK_DIE_CTRL_STK_SR_ACC_CTL_BK2_BASE_UP_ACCSS \ 0x00000001 // Base Processor should clear it // when it is done wth the sram // usage. Set by HW It is set when // Base Processor is granted the // access to this bank //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_BASE_UP_ACC_REQ_BK2 register. // //****************************************************************************** #define STACK_DIE_CTRL_BASE_UP_ACC_REQ_BK2_ACCSS_REQ \ 0x00000001 // Base Processor will set when // Sram access is needed in Spin // Lock mode. In Handshake mode // Stack Processor will set to // inform Base Processor that it is // done with the processing of data // in SRAM and is now ready to use // by the base processor. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_STK_UP_ACC_REQ_BK2 register. // //****************************************************************************** #define STACK_DIE_CTRL_STK_UP_ACC_REQ_BK2_ACCSS_REQ \ 0x00000001 // Stack Processor will set when // Sram access is needed in Spin // Lock mode. In Handshake mode Base // Processor will set to inform // Stack Processor to start // processing the data in the Ram. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_STK_SR_ACC_CTL_BK3 register. // //****************************************************************************** #define STACK_DIE_CTRL_STK_SR_ACC_CTL_BK3_STK_UP_ACCSS \ 0x00000002 // Stack Processor should clear it // when it is done with the sram // bank usage. Set by HW It is set // when Stack Processor is granted // the access to this bank. #define STACK_DIE_CTRL_STK_SR_ACC_CTL_BK3_BASE_UP_ACCSS \ 0x00000001 // Base Processor should clear it // when it is done wth the sram // usage. Set by HW it is set when // Base Processor is granted the // access to this bank. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_BASE_UP_ACC_REQ_BK3 register. // //****************************************************************************** #define STACK_DIE_CTRL_BASE_UP_ACC_REQ_BK3_ACCSS_REQ \ 0x00000001 // Base Processor will set when // Sram access is needed in Spin // Lock mode. Not used in handshake // mode. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_STK_UP_ACC_REQ_BK3 register. // //****************************************************************************** #define STACK_DIE_CTRL_STK_UP_ACC_REQ_BK3_ACCSS_REQ \ 0x00000001 // Stack Processor will set when // Sram access is needed in Spin // Lock mode. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_RDSM_CFG_CPU register. // //****************************************************************************** #define STACK_DIE_CTRL_RDSM_CFG_CPU_FLCLK_PULSE_WIDTH_M \ 0x000000C0 // Bank Clock Hi Time 00 : HCLK // pulse 01 : 1 cycle of HCLK 10 : // 1.5 cycles of HCLK 11 : 2 cycles // of HCLK #define STACK_DIE_CTRL_RDSM_CFG_CPU_FLCLK_PULSE_WIDTH_S 6 #define STACK_DIE_CTRL_RDSM_CFG_CPU_FLCLK_SENSE \ 0x00000020 // FLCLK 0 : indicates flash clock // rise aligns on HCLK rise 1 : // indicates flash clock rise aligns // on HCLK fall #define STACK_DIE_CTRL_RDSM_CFG_CPU_PIPELINE_FLDATA \ 0x00000010 // 0 : Always register flash rdata // before sending to CPU 1 : Drive // Flash rdata directly out on MISS // (Both ICODE / DCODE) #define STACK_DIE_CTRL_RDSM_CFG_CPU_READ_WAIT_STATE_M \ 0x0000000F // Number of wait states inserted #define STACK_DIE_CTRL_RDSM_CFG_CPU_READ_WAIT_STATE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_RDSM_CFG_EE register. // //****************************************************************************** #define STACK_DIE_CTRL_RDSM_CFG_EE_FLCLK_PULSE_WIDTH_M \ 0x000000C0 // Bank Clock Hi Time 00 : HCLK // pulse 01 : 1 cycle of HCLK 10 : // 1.5 cycles of HCLK 11 : 2 cycles // of HCLK #define STACK_DIE_CTRL_RDSM_CFG_EE_FLCLK_PULSE_WIDTH_S 6 #define STACK_DIE_CTRL_RDSM_CFG_EE_FLCLK_SENSE \ 0x00000020 // FLCLK 0 : indicates flash clock // rise aligns on HCLK rise 1 : // indicates flash clock rise aligns // on HCLK fall #define STACK_DIE_CTRL_RDSM_CFG_EE_PIPELINE_FLDATA \ 0x00000010 // 0 : Always register flash rdata // before sending to CPU 1 : Drive // Flash rdata directly out on MISS // (Both ICODE / DCODE) #define STACK_DIE_CTRL_RDSM_CFG_EE_READ_WAIT_STATE_M \ 0x0000000F // Number of wait states inserted #define STACK_DIE_CTRL_RDSM_CFG_EE_READ_WAIT_STATE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_BASE_UP_IRQ_LOG register. // //****************************************************************************** #define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_BK3_REL \ 0x00000010 // Set when Relinquish Interrupt // sent to Base processor for Bank3. #define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_BK2_RELEASE \ 0x00000008 // Set when Relinquish Interrupt // sent to Base processor for Bank2. #define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_BK3_GRANT \ 0x00000004 // Set when Bank3 is granted to // Base processor. #define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_BK2_GRANT \ 0x00000002 // Set when Bank2 is granted to // BAse processor. #define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_INVAL_ACCSS \ 0x00000001 // Set when there Base processor do // an Invalid access to Sram. Ex : // Accessing the bank which is not // granted for BAse processor. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_STK_UP_IRQ_LOG register. // //****************************************************************************** #define STACK_DIE_CTRL_STK_UP_IRQ_LOG_SR_BK3_REL \ 0x00000008 // Set when Relinquish Interrupt // sent to Stack processor for // Bank3. #define STACK_DIE_CTRL_STK_UP_IRQ_LOG_SR_BK2_REL \ 0x00000004 // Set when Relinquish Interrupt // sent to Stack processor for // Bank2. #define STACK_DIE_CTRL_STK_UP_IRQ_LOG_SR_BK3_GRANT \ 0x00000002 // Set when Bank3 is granted to // Stack processor. #define STACK_DIE_CTRL_STK_UP_IRQ_LOG_SR_BK2_GRANT \ 0x00000001 // Set when Bank2 is granted to // Stack processor. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_STK_CLK_EN register. // //****************************************************************************** #define STACK_DIE_CTRL_STK_CLK_EN_SR_CLK \ 0x00000004 // Enable the clock going to sram. #define STACK_DIE_CTRL_STK_CLK_EN_DFT_CTRL_CLK \ 0x00000002 // Enable the clock going to dft // control block #define STACK_DIE_CTRL_STK_CLK_EN_STK_UP_CLK \ 0x00000001 // Enable the clock going to Cm3 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_SPIN_LOCK_MODE register. // //****************************************************************************** #define STACK_DIE_CTRL_SPIN_LOCK_MODE_MODE \ 0x00000001 // 0 : Handshake Mode 1 : Spinlock // mode. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_BUS_FAULT_ADDR register. // //****************************************************************************** #define STACK_DIE_CTRL_BUS_FAULT_ADDR_ADDRESS_M \ 0xFFFFFFFF // Fault Address #define STACK_DIE_CTRL_BUS_FAULT_ADDR_ADDRESS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_BUS_FAULT_CLR register. // //****************************************************************************** #define STACK_DIE_CTRL_BUS_FAULT_CLR_CLEAR \ 0x00000001 // When set it'll clear the bust // fault address register to store // the new bus fault address //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_RESET_CAUSE register. // //****************************************************************************** #define STACK_DIE_CTRL_RESET_CAUSE_RST_CAUSE_M \ 0xFFFFFFFF #define STACK_DIE_CTRL_RESET_CAUSE_RST_CAUSE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_WDOG_TIMER_EVENT register. // //****************************************************************************** #define STACK_DIE_CTRL_WDOG_TIMER_EVENT_WDOG_TMR_EVNT_M \ 0xFFFFFFFF #define STACK_DIE_CTRL_WDOG_TIMER_EVENT_WDOG_TMR_EVNT_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_DMA_REQ register. // //****************************************************************************** #define STACK_DIE_CTRL_DMA_REQ_DMAREQ1 \ 0x00000002 // Generate DMAREQ1 on setting this // bit. #define STACK_DIE_CTRL_DMA_REQ_DMAREQ0 \ 0x00000001 // Generate DMAREQ0 on setting this // bit. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_SRAM_JUMP_OFFSET_ADDR register. // //****************************************************************************** #define STACK_DIE_CTRL_SRAM_JUMP_OFFSET_ADDR_ADDR_M \ 0xFFFFFFFF #define STACK_DIE_CTRL_SRAM_JUMP_OFFSET_ADDR_ADDR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_SW_REG1 register. // //****************************************************************************** #define STACK_DIE_CTRL_SW_REG1_NEWBITFIELD1_M \ 0xFFFFFFFF #define STACK_DIE_CTRL_SW_REG1_NEWBITFIELD1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_SW_REG2 register. // //****************************************************************************** #define STACK_DIE_CTRL_SW_REG2_NEWBITFIELD1_M \ 0xFFFFFFFF #define STACK_DIE_CTRL_SW_REG2_NEWBITFIELD1_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_FMC_SLEEP_CTL register. // //****************************************************************************** #define STACK_DIE_CTRL_FMC_SLEEP_CTL_FMC_LPM_ACK \ 0x00000002 // captures the status of of // fmc_lpm_ack #define STACK_DIE_CTRL_FMC_SLEEP_CTL_FMC_LPM_REQ \ 0x00000001 // When set assert // iflpe2fmc_lpm_req to FMC. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_MISC_CTL register. // //****************************************************************************** #define STACK_DIE_CTRL_MISC_CTL_WDOG_RESET \ 0x00000080 // 1 : will reset the async wdog // timer runing on piosc clock #define STACK_DIE_CTRL_MISC_CTL_FW_IRQ2 \ 0x00000020 // Setting this Will send to // interttupt to CM3 #define STACK_DIE_CTRL_MISC_CTL_FW_IRQ1 \ 0x00000010 // Setting this Will send to // interttupt to CM3 #define STACK_DIE_CTRL_MISC_CTL_FW_IRQ0 \ 0x00000008 // Setting this Will send to // interttupt to CM3 #define STACK_DIE_CTRL_MISC_CTL_FLB_TEST_MUX_CTL_BK3 \ 0x00000004 // While testing Flash Setting this // bit will Control the // CE/STR/AIN/CLKIN going to flash // banks 12 and 3. 0 : Control // signals coming from FMC for Bank // 3 goes to Bank3 1 : Control // signals coming from FMC for Bank // 0 goes to Bank2 #define STACK_DIE_CTRL_MISC_CTL_FLB_TEST_MUX_CTL_BK2 \ 0x00000002 // While testing Flash Setting this // bit will Control the // CE/STR/AIN/CLKIN going to flash // banks 12 and 3. 0 : Control // signals coming from FMC for Bank // 2 goes to Bank2 1 : Control // signals coming from FMC for Bank // 0 goes to Bank2 #define STACK_DIE_CTRL_MISC_CTL_FLB_TEST_MUX_CTL_BK1 \ 0x00000001 // While testing Flash Setting this // bit will Control the // CE/STR/AIN/CLKIN going to flash // banks 12 and 3. 0 : Control // signals coming from FMC for Bank // 1 goes to Bank1 1 : Control // signals coming from FMC for Bank // 0 goes to Bank1 //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_SW_DFT_CTL register. // //****************************************************************************** #define STACK_DIE_CTRL_SW_DFT_CTL_FL_CTRL_OWNS \ 0x20000000 // when set to '1' all flash // control signals switch over to // CM3 control when '0' it is under // the D2D interface control #define STACK_DIE_CTRL_SW_DFT_CTL_SWIF_CPU_READ \ 0x10000000 // 1 indicates in SWIF mode the // control signals to flash are from // FMC CPU read controls the clock // and address. that is one can give // address via FMC and read through // IDMEM. #define STACK_DIE_CTRL_SW_DFT_CTL_CPU_DONE \ 0x00800000 // 'CPU Done' bit for PBIST. Write // '1' to indicate test done. #define STACK_DIE_CTRL_SW_DFT_CTL_CPU_FAIL \ 0x00400000 // 'CPU Fail' bit for PBIST. Write // '1' to indicate test failed. #define STACK_DIE_CTRL_SW_DFT_CTL_FLBK4_OWNS \ 0x00001000 // when set to '1' flash bank 4 // (EEPROM) is owned by the CM3for // reads over DCODE bus. When '0' // access control given to D2D // interface. #define STACK_DIE_CTRL_SW_DFT_CTL_FLBK3_OWNS \ 0x00000800 // when set to '1' flash bank 3 is // owned by the CM3for reads over // DCODE bus. When '0' access // control given to D2D interface. #define STACK_DIE_CTRL_SW_DFT_CTL_FLBK2_OWNS \ 0x00000400 // when set to '1' flash bank 2 is // owned by the CM3for reads over // DCODE bus. When '0' access // control given to D2D interface. #define STACK_DIE_CTRL_SW_DFT_CTL_FLBK1_OWNS \ 0x00000200 // when set to '1' flash bank 1 is // owned by the CM3for reads over // DCODE bus. When '0' access // control given to D2D interface. #define STACK_DIE_CTRL_SW_DFT_CTL_FLBK0_OWNS \ 0x00000100 // when set to '1' flash bank 0 is // owned by the CM3 for reads over // DCODE bus. When '0' access // control given to D2D interface. //****************************************************************************** // // The following are defines for the bit fields in the // STACK_DIE_CTRL_O_PADN_CTL_0 register. // //****************************************************************************** #define STACK_DIE_CTRL_PADN_CTL_0_SPARE_PAD_DOUT \ 0x00000008 // This bit is valid for only the // spare pads ie for n=57 to 59. // value to drive at the output of // the pad #define STACK_DIE_CTRL_PADN_CTL_0_SPARE_PAD_DIN \ 0x00000004 // This bit is valid for only the // spare pads ie for n=57 to 59. // captures the 'Y' pin of the pad // which is the data being driven // into the die #define STACK_DIE_CTRL_PADN_CTL_0_OEN2X \ 0x00000002 // OEN2X control when '1' enables // the output with 1x. Total drive // strength is decided bu oen1x // setting + oen2x setting. #define STACK_DIE_CTRL_PADN_CTL_0_OEN1X \ 0x00000001 // OEN1X control when '1' enables // the output with 1x . Total drive // strength is decided bu oen1x // setting + oen2x setting. #endif // __HW_STACK_DIE_CTRL_H__ micropython-1.12/ports/cc3200/hal/inc/hw_timer.h000066400000000000000000001167021357706137100213760ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // // hw_timer.h - Defines and macros used when accessing the timer. // //***************************************************************************** //##### INTERNAL BEGIN ##### // // This is an auto-generated file. Do not edit by hand. // Created by version 6779 of DriverLib. // //##### INTERNAL END ##### #ifndef __HW_TIMER_H__ #define __HW_TIMER_H__ //***************************************************************************** // // The following are defines for the Timer register offsets. // //***************************************************************************** #define TIMER_O_CFG 0x00000000 // GPTM Configuration #define TIMER_O_TAMR 0x00000004 // GPTM Timer A Mode #define TIMER_O_TBMR 0x00000008 // GPTM Timer B Mode #define TIMER_O_CTL 0x0000000C // GPTM Control //##### GARNET BEGIN ##### #define TIMER_O_SYNC 0x00000010 // GPTM Synchronize //##### GARNET END ##### #define TIMER_O_IMR 0x00000018 // GPTM Interrupt Mask #define TIMER_O_RIS 0x0000001C // GPTM Raw Interrupt Status #define TIMER_O_MIS 0x00000020 // GPTM Masked Interrupt Status #define TIMER_O_ICR 0x00000024 // GPTM Interrupt Clear #define TIMER_O_TAILR 0x00000028 // GPTM Timer A Interval Load #define TIMER_O_TBILR 0x0000002C // GPTM Timer B Interval Load #define TIMER_O_TAMATCHR 0x00000030 // GPTM Timer A Match #define TIMER_O_TBMATCHR 0x00000034 // GPTM Timer B Match #define TIMER_O_TAPR 0x00000038 // GPTM Timer A Prescale #define TIMER_O_TBPR 0x0000003C // GPTM Timer B Prescale #define TIMER_O_TAPMR 0x00000040 // GPTM TimerA Prescale Match #define TIMER_O_TBPMR 0x00000044 // GPTM TimerB Prescale Match #define TIMER_O_TAR 0x00000048 // GPTM Timer A #define TIMER_O_TBR 0x0000004C // GPTM Timer B #define TIMER_O_TAV 0x00000050 // GPTM Timer A Value #define TIMER_O_TBV 0x00000054 // GPTM Timer B Value #define TIMER_O_RTCPD 0x00000058 // GPTM RTC Predivide #define TIMER_O_TAPS 0x0000005C // GPTM Timer A Prescale Snapshot #define TIMER_O_TBPS 0x00000060 // GPTM Timer B Prescale Snapshot #define TIMER_O_TAPV 0x00000064 // GPTM Timer A Prescale Value #define TIMER_O_TBPV 0x00000068 // GPTM Timer B Prescale Value #define TIMER_O_DMAEV 0x0000006C // GPTM DMA Event #define TIMER_O_PP 0x00000FC0 // GPTM Peripheral Properties //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_CFG register. // //***************************************************************************** #define TIMER_CFG_M 0x00000007 // GPTM Configuration #define TIMER_CFG_32_BIT_TIMER 0x00000000 // 32-bit timer configuration #define TIMER_CFG_32_BIT_RTC 0x00000001 // 32-bit real-time clock (RTC) // counter configuration #define TIMER_CFG_16_BIT 0x00000004 // 16-bit timer configuration. The // function is controlled by bits // 1:0 of GPTMTAMR and GPTMTBMR //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAMR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TAMR_TAPLO 0x00000800 // GPTM Timer A PWM Legacy // Operation #define TIMER_TAMR_TAMRSU 0x00000400 // GPTM Timer A Match Register // Update #define TIMER_TAMR_TAPWMIE 0x00000200 // GPTM Timer A PWM Interrupt // Enable #define TIMER_TAMR_TAILD 0x00000100 // GPTM Timer A Interval Load Write //##### GARNET END ##### #define TIMER_TAMR_TASNAPS 0x00000080 // GPTM Timer A Snap-Shot Mode #define TIMER_TAMR_TAWOT 0x00000040 // GPTM Timer A Wait-on-Trigger #define TIMER_TAMR_TAMIE 0x00000020 // GPTM Timer A Match Interrupt // Enable #define TIMER_TAMR_TACDIR 0x00000010 // GPTM Timer A Count Direction #define TIMER_TAMR_TAAMS 0x00000008 // GPTM Timer A Alternate Mode // Select #define TIMER_TAMR_TACMR 0x00000004 // GPTM Timer A Capture Mode #define TIMER_TAMR_TAMR_M 0x00000003 // GPTM Timer A Mode #define TIMER_TAMR_TAMR_1_SHOT 0x00000001 // One-Shot Timer mode #define TIMER_TAMR_TAMR_PERIOD 0x00000002 // Periodic Timer mode #define TIMER_TAMR_TAMR_CAP 0x00000003 // Capture mode //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBMR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TBMR_TBPLO 0x00000800 // GPTM Timer B PWM Legacy // Operation #define TIMER_TBMR_TBMRSU 0x00000400 // GPTM Timer B Match Register // Update #define TIMER_TBMR_TBPWMIE 0x00000200 // GPTM Timer B PWM Interrupt // Enable #define TIMER_TBMR_TBILD 0x00000100 // GPTM Timer B Interval Load Write //##### GARNET END ##### #define TIMER_TBMR_TBSNAPS 0x00000080 // GPTM Timer B Snap-Shot Mode #define TIMER_TBMR_TBWOT 0x00000040 // GPTM Timer B Wait-on-Trigger #define TIMER_TBMR_TBMIE 0x00000020 // GPTM Timer B Match Interrupt // Enable #define TIMER_TBMR_TBCDIR 0x00000010 // GPTM Timer B Count Direction #define TIMER_TBMR_TBAMS 0x00000008 // GPTM Timer B Alternate Mode // Select #define TIMER_TBMR_TBCMR 0x00000004 // GPTM Timer B Capture Mode #define TIMER_TBMR_TBMR_M 0x00000003 // GPTM Timer B Mode #define TIMER_TBMR_TBMR_1_SHOT 0x00000001 // One-Shot Timer mode #define TIMER_TBMR_TBMR_PERIOD 0x00000002 // Periodic Timer mode #define TIMER_TBMR_TBMR_CAP 0x00000003 // Capture mode //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_CTL register. // //***************************************************************************** #define TIMER_CTL_TBPWML 0x00004000 // GPTM Timer B PWM Output Level #define TIMER_CTL_TBOTE 0x00002000 // GPTM Timer B Output Trigger // Enable #define TIMER_CTL_TBEVENT_M 0x00000C00 // GPTM Timer B Event Mode #define TIMER_CTL_TBEVENT_POS 0x00000000 // Positive edge #define TIMER_CTL_TBEVENT_NEG 0x00000400 // Negative edge #define TIMER_CTL_TBEVENT_BOTH 0x00000C00 // Both edges #define TIMER_CTL_TBSTALL 0x00000200 // GPTM Timer B Stall Enable #define TIMER_CTL_TBEN 0x00000100 // GPTM Timer B Enable #define TIMER_CTL_TAPWML 0x00000040 // GPTM Timer A PWM Output Level #define TIMER_CTL_TAOTE 0x00000020 // GPTM Timer A Output Trigger // Enable #define TIMER_CTL_RTCEN 0x00000010 // GPTM RTC Enable #define TIMER_CTL_TAEVENT_M 0x0000000C // GPTM Timer A Event Mode #define TIMER_CTL_TAEVENT_POS 0x00000000 // Positive edge #define TIMER_CTL_TAEVENT_NEG 0x00000004 // Negative edge #define TIMER_CTL_TAEVENT_BOTH 0x0000000C // Both edges #define TIMER_CTL_TASTALL 0x00000002 // GPTM Timer A Stall Enable #define TIMER_CTL_TAEN 0x00000001 // GPTM Timer A Enable //##### GARNET BEGIN ##### //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_SYNC register. // //***************************************************************************** #define TIMER_SYNC_SYNC11_M 0x00C00000 // Synchronize GPTM Timer 11 #define TIMER_SYNC_SYNC11_TA 0x00400000 // A timeout event for Timer A of // GPTM11 is triggered #define TIMER_SYNC_SYNC11_TB 0x00800000 // A timeout event for Timer B of // GPTM11 is triggered #define TIMER_SYNC_SYNC11_TATB 0x00C00000 // A timeout event for both Timer A // and Timer B of GPTM11 is // triggered #define TIMER_SYNC_SYNC10_M 0x00300000 // Synchronize GPTM Timer 10 #define TIMER_SYNC_SYNC10_TA 0x00100000 // A timeout event for Timer A of // GPTM10 is triggered #define TIMER_SYNC_SYNC10_TB 0x00200000 // A timeout event for Timer B of // GPTM10 is triggered #define TIMER_SYNC_SYNC10_TATB 0x00300000 // A timeout event for both Timer A // and Timer B of GPTM10 is // triggered #define TIMER_SYNC_SYNC9_M 0x000C0000 // Synchronize GPTM Timer 9 #define TIMER_SYNC_SYNC9_TA 0x00040000 // A timeout event for Timer A of // GPTM9 is triggered #define TIMER_SYNC_SYNC9_TB 0x00080000 // A timeout event for Timer B of // GPTM9 is triggered #define TIMER_SYNC_SYNC9_TATB 0x000C0000 // A timeout event for both Timer A // and Timer B of GPTM9 is // triggered #define TIMER_SYNC_SYNC8_M 0x00030000 // Synchronize GPTM Timer 8 #define TIMER_SYNC_SYNC8_TA 0x00010000 // A timeout event for Timer A of // GPTM8 is triggered #define TIMER_SYNC_SYNC8_TB 0x00020000 // A timeout event for Timer B of // GPTM8 is triggered #define TIMER_SYNC_SYNC8_TATB 0x00030000 // A timeout event for both Timer A // and Timer B of GPTM8 is // triggered #define TIMER_SYNC_SYNC7_M 0x0000C000 // Synchronize GPTM Timer 7 #define TIMER_SYNC_SYNC7_TA 0x00004000 // A timeout event for Timer A of // GPTM7 is triggered #define TIMER_SYNC_SYNC7_TB 0x00008000 // A timeout event for Timer B of // GPTM7 is triggered #define TIMER_SYNC_SYNC7_TATB 0x0000C000 // A timeout event for both Timer A // and Timer B of GPTM7 is // triggered #define TIMER_SYNC_SYNC6_M 0x00003000 // Synchronize GPTM Timer 6 #define TIMER_SYNC_SYNC6_TA 0x00001000 // A timeout event for Timer A of // GPTM6 is triggered #define TIMER_SYNC_SYNC6_TB 0x00002000 // A timeout event for Timer B of // GPTM6 is triggered #define TIMER_SYNC_SYNC6_TATB 0x00003000 // A timeout event for both Timer A // and Timer B of GPTM6 is // triggered #define TIMER_SYNC_SYNC5_M 0x00000C00 // Synchronize GPTM Timer 5 #define TIMER_SYNC_SYNC5_TA 0x00000400 // A timeout event for Timer A of // GPTM5 is triggered #define TIMER_SYNC_SYNC5_TB 0x00000800 // A timeout event for Timer B of // GPTM5 is triggered #define TIMER_SYNC_SYNC5_TATB 0x00000C00 // A timeout event for both Timer A // and Timer B of GPTM5 is // triggered #define TIMER_SYNC_SYNC4_M 0x00000300 // Synchronize GPTM Timer 4 #define TIMER_SYNC_SYNC4_TA 0x00000100 // A timeout event for Timer A of // GPTM4 is triggered #define TIMER_SYNC_SYNC4_TB 0x00000200 // A timeout event for Timer B of // GPTM4 is triggered #define TIMER_SYNC_SYNC4_TATB 0x00000300 // A timeout event for both Timer A // and Timer B of GPTM4 is // triggered #define TIMER_SYNC_SYNC3_M 0x000000C0 // Synchronize GPTM Timer 3 #define TIMER_SYNC_SYNC3_TA 0x00000040 // A timeout event for Timer A of // GPTM3 is triggered #define TIMER_SYNC_SYNC3_TB 0x00000080 // A timeout event for Timer B of // GPTM3 is triggered #define TIMER_SYNC_SYNC3_TATB 0x000000C0 // A timeout event for both Timer A // and Timer B of GPTM3 is // triggered #define TIMER_SYNC_SYNC2_M 0x00000030 // Synchronize GPTM Timer 2 #define TIMER_SYNC_SYNC2_TA 0x00000010 // A timeout event for Timer A of // GPTM2 is triggered #define TIMER_SYNC_SYNC2_TB 0x00000020 // A timeout event for Timer B of // GPTM2 is triggered #define TIMER_SYNC_SYNC2_TATB 0x00000030 // A timeout event for both Timer A // and Timer B of GPTM2 is // triggered #define TIMER_SYNC_SYNC1_M 0x0000000C // Synchronize GPTM Timer 1 #define TIMER_SYNC_SYNC1_TA 0x00000004 // A timeout event for Timer A of // GPTM1 is triggered #define TIMER_SYNC_SYNC1_TB 0x00000008 // A timeout event for Timer B of // GPTM1 is triggered #define TIMER_SYNC_SYNC1_TATB 0x0000000C // A timeout event for both Timer A // and Timer B of GPTM1 is // triggered #define TIMER_SYNC_SYNC0_M 0x00000003 // Synchronize GPTM Timer 0 #define TIMER_SYNC_SYNC0_TA 0x00000001 // A timeout event for Timer A of // GPTM0 is triggered #define TIMER_SYNC_SYNC0_TB 0x00000002 // A timeout event for Timer B of // GPTM0 is triggered #define TIMER_SYNC_SYNC0_TATB 0x00000003 // A timeout event for both Timer A // and Timer B of GPTM0 is // triggered //##### GARNET END ##### //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_IMR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_IMR_WUEIM 0x00010000 // 32/64-Bit GPTM Write Update // Error Interrupt Mask //##### GARNET END ##### #define TIMER_IMR_TBMIM 0x00000800 // GPTM Timer B Mode Match // Interrupt Mask #define TIMER_IMR_CBEIM 0x00000400 // GPTM Capture B Event Interrupt // Mask #define TIMER_IMR_CBMIM 0x00000200 // GPTM Capture B Match Interrupt // Mask #define TIMER_IMR_TBTOIM 0x00000100 // GPTM Timer B Time-Out Interrupt // Mask #define TIMER_IMR_TAMIM 0x00000010 // GPTM Timer A Mode Match // Interrupt Mask #define TIMER_IMR_RTCIM 0x00000008 // GPTM RTC Interrupt Mask #define TIMER_IMR_CAEIM 0x00000004 // GPTM Capture A Event Interrupt // Mask #define TIMER_IMR_CAMIM 0x00000002 // GPTM Capture A Match Interrupt // Mask #define TIMER_IMR_TATOIM 0x00000001 // GPTM Timer A Time-Out Interrupt // Mask //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_RIS register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_RIS_WUERIS 0x00010000 // 32/64-Bit GPTM Write Update // Error Raw Interrupt Status //##### GARNET END ##### #define TIMER_RIS_TBMRIS 0x00000800 // GPTM Timer B Mode Match Raw // Interrupt #define TIMER_RIS_CBERIS 0x00000400 // GPTM Capture B Event Raw // Interrupt #define TIMER_RIS_CBMRIS 0x00000200 // GPTM Capture B Match Raw // Interrupt #define TIMER_RIS_TBTORIS 0x00000100 // GPTM Timer B Time-Out Raw // Interrupt #define TIMER_RIS_TAMRIS 0x00000010 // GPTM Timer A Mode Match Raw // Interrupt #define TIMER_RIS_RTCRIS 0x00000008 // GPTM RTC Raw Interrupt #define TIMER_RIS_CAERIS 0x00000004 // GPTM Capture A Event Raw // Interrupt #define TIMER_RIS_CAMRIS 0x00000002 // GPTM Capture A Match Raw // Interrupt #define TIMER_RIS_TATORIS 0x00000001 // GPTM Timer A Time-Out Raw // Interrupt //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_MIS register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_MIS_WUEMIS 0x00010000 // 32/64-Bit GPTM Write Update // Error Masked Interrupt Status //##### GARNET END ##### #define TIMER_MIS_TBMMIS 0x00000800 // GPTM Timer B Mode Match Masked // Interrupt #define TIMER_MIS_CBEMIS 0x00000400 // GPTM Capture B Event Masked // Interrupt #define TIMER_MIS_CBMMIS 0x00000200 // GPTM Capture B Match Masked // Interrupt #define TIMER_MIS_TBTOMIS 0x00000100 // GPTM Timer B Time-Out Masked // Interrupt #define TIMER_MIS_TAMMIS 0x00000010 // GPTM Timer A Mode Match Masked // Interrupt #define TIMER_MIS_RTCMIS 0x00000008 // GPTM RTC Masked Interrupt #define TIMER_MIS_CAEMIS 0x00000004 // GPTM Capture A Event Masked // Interrupt #define TIMER_MIS_CAMMIS 0x00000002 // GPTM Capture A Match Masked // Interrupt #define TIMER_MIS_TATOMIS 0x00000001 // GPTM Timer A Time-Out Masked // Interrupt //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_ICR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_ICR_WUECINT 0x00010000 // 32/64-Bit GPTM Write Update // Error Interrupt Clear //##### GARNET END ##### #define TIMER_ICR_TBMCINT 0x00000800 // GPTM Timer B Mode Match // Interrupt Clear #define TIMER_ICR_CBECINT 0x00000400 // GPTM Capture B Event Interrupt // Clear #define TIMER_ICR_CBMCINT 0x00000200 // GPTM Capture B Match Interrupt // Clear #define TIMER_ICR_TBTOCINT 0x00000100 // GPTM Timer B Time-Out Interrupt // Clear #define TIMER_ICR_TAMCINT 0x00000010 // GPTM Timer A Mode Match // Interrupt Clear #define TIMER_ICR_RTCCINT 0x00000008 // GPTM RTC Interrupt Clear #define TIMER_ICR_CAECINT 0x00000004 // GPTM Capture A Event Interrupt // Clear #define TIMER_ICR_CAMCINT 0x00000002 // GPTM Capture A Match Interrupt // Clear #define TIMER_ICR_TATOCINT 0x00000001 // GPTM Timer A Time-Out Raw // Interrupt //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAILR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TAILR_M 0xFFFFFFFF // GPTM Timer A Interval Load // Register //##### GARNET END ##### #define TIMER_TAILR_TAILRH_M 0xFFFF0000 // GPTM Timer A Interval Load // Register High #define TIMER_TAILR_TAILRL_M 0x0000FFFF // GPTM Timer A Interval Load // Register Low #define TIMER_TAILR_TAILRH_S 16 #define TIMER_TAILR_TAILRL_S 0 //##### GARNET BEGIN ##### #define TIMER_TAILR_S 0 //##### GARNET END ##### //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBILR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TBILR_M 0xFFFFFFFF // GPTM Timer B Interval Load // Register //##### GARNET END ##### #define TIMER_TBILR_TBILRL_M 0x0000FFFF // GPTM Timer B Interval Load // Register #define TIMER_TBILR_TBILRL_S 0 //##### GARNET BEGIN ##### #define TIMER_TBILR_S 0 //##### GARNET END ##### //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAMATCHR // register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TAMATCHR_TAMR_M 0xFFFFFFFF // GPTM Timer A Match Register //##### GARNET END ##### #define TIMER_TAMATCHR_TAMRH_M 0xFFFF0000 // GPTM Timer A Match Register High #define TIMER_TAMATCHR_TAMRL_M 0x0000FFFF // GPTM Timer A Match Register Low #define TIMER_TAMATCHR_TAMRH_S 16 #define TIMER_TAMATCHR_TAMRL_S 0 //##### GARNET BEGIN ##### #define TIMER_TAMATCHR_TAMR_S 0 //##### GARNET END ##### //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBMATCHR // register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TBMATCHR_TBMR_M 0xFFFFFFFF // GPTM Timer B Match Register //##### GARNET END ##### #define TIMER_TBMATCHR_TBMRL_M 0x0000FFFF // GPTM Timer B Match Register Low //##### GARNET BEGIN ##### #define TIMER_TBMATCHR_TBMR_S 0 //##### GARNET END ##### #define TIMER_TBMATCHR_TBMRL_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAPR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TAPR_TAPSRH_M 0x0000FF00 // GPTM Timer A Prescale High Byte //##### GARNET END ##### #define TIMER_TAPR_TAPSR_M 0x000000FF // GPTM Timer A Prescale //##### GARNET BEGIN ##### #define TIMER_TAPR_TAPSRH_S 8 //##### GARNET END ##### #define TIMER_TAPR_TAPSR_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBPR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TBPR_TBPSRH_M 0x0000FF00 // GPTM Timer B Prescale High Byte //##### GARNET END ##### #define TIMER_TBPR_TBPSR_M 0x000000FF // GPTM Timer B Prescale //##### GARNET BEGIN ##### #define TIMER_TBPR_TBPSRH_S 8 //##### GARNET END ##### #define TIMER_TBPR_TBPSR_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAPMR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TAPMR_TAPSMRH_M 0x0000FF00 // GPTM Timer A Prescale Match High // Byte //##### GARNET END ##### #define TIMER_TAPMR_TAPSMR_M 0x000000FF // GPTM TimerA Prescale Match //##### GARNET BEGIN ##### #define TIMER_TAPMR_TAPSMRH_S 8 //##### GARNET END ##### #define TIMER_TAPMR_TAPSMR_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBPMR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TBPMR_TBPSMRH_M 0x0000FF00 // GPTM Timer B Prescale Match High // Byte //##### GARNET END ##### #define TIMER_TBPMR_TBPSMR_M 0x000000FF // GPTM TimerB Prescale Match //##### GARNET BEGIN ##### #define TIMER_TBPMR_TBPSMRH_S 8 //##### GARNET END ##### #define TIMER_TBPMR_TBPSMR_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TAR_M 0xFFFFFFFF // GPTM Timer A Register //##### GARNET END ##### #define TIMER_TAR_TARH_M 0xFFFF0000 // GPTM Timer A Register High #define TIMER_TAR_TARL_M 0x0000FFFF // GPTM Timer A Register Low #define TIMER_TAR_TARH_S 16 #define TIMER_TAR_TARL_S 0 //##### GARNET BEGIN ##### #define TIMER_TAR_S 0 //##### GARNET END ##### //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBR register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TBR_M 0xFFFFFFFF // GPTM Timer B Register //##### GARNET END ##### #define TIMER_TBR_TBRL_M 0x00FFFFFF // GPTM Timer B #define TIMER_TBR_TBRL_S 0 //##### GARNET BEGIN ##### #define TIMER_TBR_S 0 //##### GARNET END ##### //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAV register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TAV_M 0xFFFFFFFF // GPTM Timer A Value //##### GARNET END ##### #define TIMER_TAV_TAVH_M 0xFFFF0000 // GPTM Timer A Value High #define TIMER_TAV_TAVL_M 0x0000FFFF // GPTM Timer A Register Low #define TIMER_TAV_TAVH_S 16 #define TIMER_TAV_TAVL_S 0 //##### GARNET BEGIN ##### #define TIMER_TAV_S 0 //##### GARNET END ##### //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBV register. // //***************************************************************************** //##### GARNET BEGIN ##### #define TIMER_TBV_M 0xFFFFFFFF // GPTM Timer B Value //##### GARNET END ##### #define TIMER_TBV_TBVL_M 0x0000FFFF // GPTM Timer B Register #define TIMER_TBV_TBVL_S 0 //##### GARNET BEGIN ##### #define TIMER_TBV_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_RTCPD register. // //***************************************************************************** #define TIMER_RTCPD_RTCPD_M 0x0000FFFF // RTC Predivide Counter Value #define TIMER_RTCPD_RTCPD_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAPS register. // //***************************************************************************** #define TIMER_TAPS_PSS_M 0x0000FFFF // GPTM Timer A Prescaler Snapshot #define TIMER_TAPS_PSS_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBPS register. // //***************************************************************************** #define TIMER_TBPS_PSS_M 0x0000FFFF // GPTM Timer A Prescaler Value #define TIMER_TBPS_PSS_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TAPV register. // //***************************************************************************** #define TIMER_TAPV_PSV_M 0x0000FFFF // GPTM Timer A Prescaler Value #define TIMER_TAPV_PSV_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_TBPV register. // //***************************************************************************** #define TIMER_TBPV_PSV_M 0x0000FFFF // GPTM Timer B Prescaler Value #define TIMER_TBPV_PSV_S 0 //***************************************************************************** // // The following are defines for the bit fields in the TIMER_O_PP register. // //***************************************************************************** #define TIMER_PP_SYNCCNT 0x00000020 // Synchronize Start #define TIMER_PP_CHAIN 0x00000010 // Chain with Other Timers #define TIMER_PP_SIZE_M 0x0000000F // Count Size #define TIMER_PP_SIZE__0 0x00000000 // Timer A and Timer B counters are // 16 bits each with an 8-bit // prescale counter #define TIMER_PP_SIZE__1 0x00000001 // Timer A and Timer B counters are // 32 bits each with an 16-bit // prescale counter //##### GARNET END ##### //***************************************************************************** // // The following definitions are deprecated. // //***************************************************************************** #ifndef DEPRECATED //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_O_CFG // register. // //***************************************************************************** #define TIMER_CFG_CFG_MSK 0x00000007 // Configuration options mask //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_O_CTL // register. // //***************************************************************************** #define TIMER_CTL_TBEVENT_MSK 0x00000C00 // TimerB event mode mask #define TIMER_CTL_TAEVENT_MSK 0x0000000C // TimerA event mode mask //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_O_RIS // register. // //***************************************************************************** #define TIMER_RIS_CBEMIS 0x00000400 // CaptureB event masked int status #define TIMER_RIS_CBMMIS 0x00000200 // CaptureB match masked int status #define TIMER_RIS_TBTOMIS 0x00000100 // TimerB time out masked int stat #define TIMER_RIS_RTCMIS 0x00000008 // RTC masked int status #define TIMER_RIS_CAEMIS 0x00000004 // CaptureA event masked int status #define TIMER_RIS_CAMMIS 0x00000002 // CaptureA match masked int status #define TIMER_RIS_TATOMIS 0x00000001 // TimerA time out masked int stat //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_O_TAILR // register. // //***************************************************************************** #define TIMER_TAILR_TAILRH 0xFFFF0000 // TimerB load val in 32 bit mode #define TIMER_TAILR_TAILRL 0x0000FFFF // TimerA interval load value //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_O_TBILR // register. // //***************************************************************************** #define TIMER_TBILR_TBILRL 0x0000FFFF // TimerB interval load value //***************************************************************************** // // The following are deprecated defines for the bit fields in the // TIMER_O_TAMATCHR register. // //***************************************************************************** #define TIMER_TAMATCHR_TAMRH 0xFFFF0000 // TimerB match val in 32 bit mode #define TIMER_TAMATCHR_TAMRL 0x0000FFFF // TimerA match value //***************************************************************************** // // The following are deprecated defines for the bit fields in the // TIMER_O_TBMATCHR register. // //***************************************************************************** #define TIMER_TBMATCHR_TBMRL 0x0000FFFF // TimerB match load value //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_O_TAR // register. // //***************************************************************************** #define TIMER_TAR_TARH 0xFFFF0000 // TimerB val in 32 bit mode #define TIMER_TAR_TARL 0x0000FFFF // TimerA value //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_O_TBR // register. // //***************************************************************************** #define TIMER_TBR_TBRL 0x0000FFFF // TimerB value //***************************************************************************** // // The following are deprecated defines for the reset values of the timer // registers. // //***************************************************************************** #define TIMER_RV_TAILR 0xFFFFFFFF // TimerA interval load reg RV #define TIMER_RV_TAR 0xFFFFFFFF // TimerA register RV #define TIMER_RV_TAMATCHR 0xFFFFFFFF // TimerA match register RV #define TIMER_RV_TBILR 0x0000FFFF // TimerB interval load reg RV #define TIMER_RV_TBMATCHR 0x0000FFFF // TimerB match register RV #define TIMER_RV_TBR 0x0000FFFF // TimerB register RV #define TIMER_RV_TAPR 0x00000000 // TimerA prescale register RV #define TIMER_RV_CFG 0x00000000 // Configuration register RV #define TIMER_RV_TBPMR 0x00000000 // TimerB prescale match regi RV #define TIMER_RV_TAPMR 0x00000000 // TimerA prescale match reg RV #define TIMER_RV_CTL 0x00000000 // Control register RV #define TIMER_RV_ICR 0x00000000 // Interrupt clear register RV #define TIMER_RV_TBMR 0x00000000 // TimerB mode register RV #define TIMER_RV_MIS 0x00000000 // Masked interrupt status reg RV #define TIMER_RV_RIS 0x00000000 // Interrupt status register RV #define TIMER_RV_TBPR 0x00000000 // TimerB prescale register RV #define TIMER_RV_IMR 0x00000000 // Interrupt mask register RV #define TIMER_RV_TAMR 0x00000000 // TimerA mode register RV //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_TnMR // register. // //***************************************************************************** #define TIMER_TNMR_TNAMS 0x00000008 // Alternate mode select #define TIMER_TNMR_TNCMR 0x00000004 // Capture mode - count or time #define TIMER_TNMR_TNTMR_MSK 0x00000003 // Timer mode mask #define TIMER_TNMR_TNTMR_1_SHOT 0x00000001 // Mode - one shot #define TIMER_TNMR_TNTMR_PERIOD 0x00000002 // Mode - periodic #define TIMER_TNMR_TNTMR_CAP 0x00000003 // Mode - capture //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_TnPR // register. // //***************************************************************************** #define TIMER_TNPR_TNPSR 0x000000FF // TimerN prescale value //***************************************************************************** // // The following are deprecated defines for the bit fields in the TIMER_TnPMR // register. // //***************************************************************************** #define TIMER_TNPMR_TNPSMR 0x000000FF // TimerN prescale match value #endif #endif // __HW_TIMER_H__ micropython-1.12/ports/cc3200/hal/inc/hw_types.h000066400000000000000000000066471357706137100214300ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_TYPES_H__ #define __HW_TYPES_H__ //***************************************************************************** // // Define a boolean type, and values for true and false. // //***************************************************************************** typedef unsigned char tBoolean; #ifndef true #define true 1 #endif #ifndef false #define false 0 #endif //***************************************************************************** // // Macros for hardware access, both direct and via the bit-band region. // //***************************************************************************** #define HWREG(x) \ (*((volatile unsigned long *)(x))) #define HWREGH(x) \ (*((volatile unsigned short *)(x))) #define HWREGB(x) \ (*((volatile unsigned char *)(x))) #define HWREGBITW(x, b) \ HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) #define HWREGBITH(x, b) \ HWREGH(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) #define HWREGBITB(x, b) \ HWREGB(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) #endif // __HW_TYPES_H__ micropython-1.12/ports/cc3200/hal/inc/hw_uart.h000066400000000000000000000556151357706137100212360ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_UART_H__ #define __HW_UART_H__ //***************************************************************************** // // The following are defines for the UART register offsets. // //***************************************************************************** #define UART_O_DR 0x00000000 #define UART_O_RSR 0x00000004 #define UART_O_ECR 0x00000004 #define UART_O_FR 0x00000018 #define UART_O_ILPR 0x00000020 #define UART_O_IBRD 0x00000024 #define UART_O_FBRD 0x00000028 #define UART_O_LCRH 0x0000002C #define UART_O_CTL 0x00000030 #define UART_O_IFLS 0x00000034 #define UART_O_IM 0x00000038 #define UART_O_RIS 0x0000003C #define UART_O_MIS 0x00000040 #define UART_O_ICR 0x00000044 #define UART_O_DMACTL 0x00000048 #define UART_O_LCTL 0x00000090 #define UART_O_LSS 0x00000094 #define UART_O_LTIM 0x00000098 #define UART_O_9BITADDR 0x000000A4 #define UART_O_9BITAMASK 0x000000A8 #define UART_O_PP 0x00000FC0 #define UART_O_CC 0x00000FC8 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_DR register. // //****************************************************************************** #define UART_DR_OE 0x00000800 // UART Overrun Error #define UART_DR_BE 0x00000400 // UART Break Error #define UART_DR_PE 0x00000200 // UART Parity Error #define UART_DR_FE 0x00000100 // UART Framing Error #define UART_DR_DATA_M 0x000000FF // Data Transmitted or Received #define UART_DR_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_RSR register. // //****************************************************************************** #define UART_RSR_OE 0x00000008 // UART Overrun Error #define UART_RSR_BE 0x00000004 // UART Break Error #define UART_RSR_PE 0x00000002 // UART Parity Error #define UART_RSR_FE 0x00000001 // UART Framing Error //****************************************************************************** // // The following are defines for the bit fields in the UART_O_ECR register. // //****************************************************************************** #define UART_ECR_DATA_M 0x000000FF // Error Clear #define UART_ECR_DATA_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_FR register. // //****************************************************************************** #define UART_FR_RI 0x00000100 // Ring Indicator #define UART_FR_TXFE 0x00000080 // UART Transmit FIFO Empty #define UART_FR_RXFF 0x00000040 // UART Receive FIFO Full #define UART_FR_TXFF 0x00000020 // UART Transmit FIFO Full #define UART_FR_RXFE 0x00000010 // UART Receive FIFO Empty #define UART_FR_BUSY 0x00000008 // UART Busy #define UART_FR_DCD 0x00000004 // Data Carrier Detect #define UART_FR_DSR 0x00000002 // Data Set Ready #define UART_FR_CTS 0x00000001 // Clear To Send //****************************************************************************** // // The following are defines for the bit fields in the UART_O_ILPR register. // //****************************************************************************** #define UART_ILPR_ILPDVSR_M 0x000000FF // IrDA Low-Power Divisor #define UART_ILPR_ILPDVSR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_IBRD register. // //****************************************************************************** #define UART_IBRD_DIVINT_M 0x0000FFFF // Integer Baud-Rate Divisor #define UART_IBRD_DIVINT_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_FBRD register. // //****************************************************************************** #define UART_FBRD_DIVFRAC_M 0x0000003F // Fractional Baud-Rate Divisor #define UART_FBRD_DIVFRAC_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_LCRH register. // //****************************************************************************** #define UART_LCRH_SPS 0x00000080 // UART Stick Parity Select #define UART_LCRH_WLEN_M 0x00000060 // UART Word Length 0x00000000 : // UART_LCRH_WLEN_5 : 5 bits // (default) 0x00000020 : // UART_LCRH_WLEN_6 : 6 bits // 0x00000040 : UART_LCRH_WLEN_7 : 7 // bits 0x00000060 : // UART_LCRH_WLEN_8 : 8 bits #define UART_LCRH_WLEN_S 5 #define UART_LCRH_FEN 0x00000010 // UART Enable FIFOs #define UART_LCRH_STP2 0x00000008 // UART Two Stop Bits Select #define UART_LCRH_EPS 0x00000004 // UART Even Parity Select #define UART_LCRH_PEN 0x00000002 // UART Parity Enable #define UART_LCRH_BRK 0x00000001 // UART Send Break #define UART_LCRH_WLEN_M 0x00000060 // UART Word Length #define UART_LCRH_WLEN_5 0x00000000 // 5 bits (default) #define UART_LCRH_WLEN_6 0x00000020 // 6 bits #define UART_LCRH_WLEN_7 0x00000040 // 7 bits #define UART_LCRH_WLEN_8 0x00000060 // 8 bits //****************************************************************************** // // The following are defines for the bit fields in the UART_O_CTL register. // //****************************************************************************** #define UART_CTL_CTSEN 0x00008000 // Enable Clear To Send #define UART_CTL_RTSEN 0x00004000 // Enable Request to Send #define UART_CTL_RI 0x00002000 // Ring Indicator #define UART_CTL_DCD 0x00001000 // Data Carrier Detect #define UART_CTL_RTS 0x00000800 // Request to Send #define UART_CTL_DTR 0x00000400 // Data Terminal Ready #define UART_CTL_RXE 0x00000200 // UART Receive Enable #define UART_CTL_TXE 0x00000100 // UART Transmit Enable #define UART_CTL_LBE 0x00000080 // UART Loop Back Enable #define UART_CTL_LIN 0x00000040 // LIN Mode Enable #define UART_CTL_HSE 0x00000020 // High-Speed Enable #define UART_CTL_EOT 0x00000010 // End of Transmission #define UART_CTL_SMART 0x00000008 // ISO 7816 Smart Card Support #define UART_CTL_SIRLP 0x00000004 // UART SIR Low-Power Mode #define UART_CTL_SIREN 0x00000002 // UART SIR Enable #define UART_CTL_UARTEN 0x00000001 // UART Enable //****************************************************************************** // // The following are defines for the bit fields in the UART_O_IFLS register. // //****************************************************************************** #define UART_IFLS_RX_M 0x00000038 // UART Receive Interrupt FIFO // Level Select #define UART_IFLS_RX_S 3 #define UART_IFLS_TX_M 0x00000007 // UART Transmit Interrupt FIFO // Level Select #define UART_IFLS_TX_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_IM register. // //****************************************************************************** #define UART_IM_DMATXIM 0x00020000 // Transmit DMA Interrupt Mask #define UART_IM_DMARXIM 0x00010000 // Receive DMA Interrupt Mask #define UART_IM_LME5IM 0x00008000 // LIN Mode Edge 5 Interrupt Mask #define UART_IM_LME1IM 0x00004000 // LIN Mode Edge 1 Interrupt Mask #define UART_IM_LMSBIM 0x00002000 // LIN Mode Sync Break Interrupt // Mask #define UART_IM_9BITIM 0x00001000 // 9-Bit Mode Interrupt Mask #define UART_IM_EOTIM 0x00000800 // End of Transmission Interrupt // Mask #define UART_IM_OEIM 0x00000400 // UART Overrun Error Interrupt // Mask #define UART_IM_BEIM 0x00000200 // UART Break Error Interrupt Mask #define UART_IM_PEIM 0x00000100 // UART Parity Error Interrupt Mask #define UART_IM_FEIM 0x00000080 // UART Framing Error Interrupt // Mask #define UART_IM_RTIM 0x00000040 // UART Receive Time-Out Interrupt // Mask #define UART_IM_TXIM 0x00000020 // UART Transmit Interrupt Mask #define UART_IM_RXIM 0x00000010 // UART Receive Interrupt Mask #define UART_IM_DSRMIM 0x00000008 // UART Data Set Ready Modem // Interrupt Mask #define UART_IM_DCDMIM 0x00000004 // UART Data Carrier Detect Modem // Interrupt Mask #define UART_IM_CTSMIM 0x00000002 // UART Clear to Send Modem // Interrupt Mask #define UART_IM_RIMIM 0x00000001 // UART Ring Indicator Modem // Interrupt Mask //****************************************************************************** // // The following are defines for the bit fields in the UART_O_RIS register. // //****************************************************************************** #define UART_RIS_DMATXRIS 0x00020000 // Transmit DMA Raw Interrupt // Status #define UART_RIS_DMARXRIS 0x00010000 // Receive DMA Raw Interrupt Status #define UART_RIS_LME5RIS 0x00008000 // LIN Mode Edge 5 Raw Interrupt // Status #define UART_RIS_LME1RIS 0x00004000 // LIN Mode Edge 1 Raw Interrupt // Status #define UART_RIS_LMSBRIS 0x00002000 // LIN Mode Sync Break Raw // Interrupt Status #define UART_RIS_9BITRIS 0x00001000 // 9-Bit Mode Raw Interrupt Status #define UART_RIS_EOTRIS 0x00000800 // End of Transmission Raw // Interrupt Status #define UART_RIS_OERIS 0x00000400 // UART Overrun Error Raw Interrupt // Status #define UART_RIS_BERIS 0x00000200 // UART Break Error Raw Interrupt // Status #define UART_RIS_PERIS 0x00000100 // UART Parity Error Raw Interrupt // Status #define UART_RIS_FERIS 0x00000080 // UART Framing Error Raw Interrupt // Status #define UART_RIS_RTRIS 0x00000040 // UART Receive Time-Out Raw // Interrupt Status #define UART_RIS_TXRIS 0x00000020 // UART Transmit Raw Interrupt // Status #define UART_RIS_RXRIS 0x00000010 // UART Receive Raw Interrupt // Status #define UART_RIS_DSRRIS 0x00000008 // UART Data Set Ready Modem Raw // Interrupt Status #define UART_RIS_DCDRIS 0x00000004 // UART Data Carrier Detect Modem // Raw Interrupt Status #define UART_RIS_CTSRIS 0x00000002 // UART Clear to Send Modem Raw // Interrupt Status #define UART_RIS_RIRIS 0x00000001 // UART Ring Indicator Modem Raw // Interrupt Status //****************************************************************************** // // The following are defines for the bit fields in the UART_O_MIS register. // //****************************************************************************** #define UART_MIS_DMATXMIS 0x00020000 // Transmit DMA Masked Interrupt // Status #define UART_MIS_DMARXMIS 0x00010000 // Receive DMA Masked Interrupt // Status #define UART_MIS_LME5MIS 0x00008000 // LIN Mode Edge 5 Masked Interrupt // Status #define UART_MIS_LME1MIS 0x00004000 // LIN Mode Edge 1 Masked Interrupt // Status #define UART_MIS_LMSBMIS 0x00002000 // LIN Mode Sync Break Masked // Interrupt Status #define UART_MIS_9BITMIS 0x00001000 // 9-Bit Mode Masked Interrupt // Status #define UART_MIS_EOTMIS 0x00000800 // End of Transmission Masked // Interrupt Status #define UART_MIS_OEMIS 0x00000400 // UART Overrun Error Masked // Interrupt Status #define UART_MIS_BEMIS 0x00000200 // UART Break Error Masked // Interrupt Status #define UART_MIS_PEMIS 0x00000100 // UART Parity Error Masked // Interrupt Status #define UART_MIS_FEMIS 0x00000080 // UART Framing Error Masked // Interrupt Status #define UART_MIS_RTMIS 0x00000040 // UART Receive Time-Out Masked // Interrupt Status #define UART_MIS_TXMIS 0x00000020 // UART Transmit Masked Interrupt // Status #define UART_MIS_RXMIS 0x00000010 // UART Receive Masked Interrupt // Status #define UART_MIS_DSRMIS 0x00000008 // UART Data Set Ready Modem Masked // Interrupt Status #define UART_MIS_DCDMIS 0x00000004 // UART Data Carrier Detect Modem // Masked Interrupt Status #define UART_MIS_CTSMIS 0x00000002 // UART Clear to Send Modem Masked // Interrupt Status #define UART_MIS_RIMIS 0x00000001 // UART Ring Indicator Modem Masked // Interrupt Status //****************************************************************************** // // The following are defines for the bit fields in the UART_O_ICR register. // //****************************************************************************** #define UART_ICR_DMATXIC 0x00020000 // Transmit DMA Interrupt Clear #define UART_ICR_DMARXIC 0x00010000 // Receive DMA Interrupt Clear #define UART_ICR_LME5MIC 0x00008000 // LIN Mode Edge 5 Interrupt Clear #define UART_ICR_LME1MIC 0x00004000 // LIN Mode Edge 1 Interrupt Clear #define UART_ICR_LMSBMIC 0x00002000 // LIN Mode Sync Break Interrupt // Clear #define UART_ICR_9BITIC 0x00001000 // 9-Bit Mode Interrupt Clear #define UART_ICR_EOTIC 0x00000800 // End of Transmission Interrupt // Clear #define UART_ICR_OEIC 0x00000400 // Overrun Error Interrupt Clear #define UART_ICR_BEIC 0x00000200 // Break Error Interrupt Clear #define UART_ICR_PEIC 0x00000100 // Parity Error Interrupt Clear #define UART_ICR_FEIC 0x00000080 // Framing Error Interrupt Clear #define UART_ICR_RTIC 0x00000040 // Receive Time-Out Interrupt Clear #define UART_ICR_TXIC 0x00000020 // Transmit Interrupt Clear #define UART_ICR_RXIC 0x00000010 // Receive Interrupt Clear #define UART_ICR_DSRMIC 0x00000008 // UART Data Set Ready Modem // Interrupt Clear #define UART_ICR_DCDMIC 0x00000004 // UART Data Carrier Detect Modem // Interrupt Clear #define UART_ICR_CTSMIC 0x00000002 // UART Clear to Send Modem // Interrupt Clear #define UART_ICR_RIMIC 0x00000001 // UART Ring Indicator Modem // Interrupt Clear //****************************************************************************** // // The following are defines for the bit fields in the UART_O_DMACTL register. // //****************************************************************************** #define UART_DMACTL_DMAERR 0x00000004 // DMA on Error #define UART_DMACTL_TXDMAE 0x00000002 // Transmit DMA Enable #define UART_DMACTL_RXDMAE 0x00000001 // Receive DMA Enable //****************************************************************************** // // The following are defines for the bit fields in the UART_O_LCTL register. // //****************************************************************************** #define UART_LCTL_BLEN_M 0x00000030 // Sync Break Length 0x00000000 : // UART_LCTL_BLEN_13T : Sync break // length is 13T bits (default) // 0x00000010 : UART_LCTL_BLEN_14T : // Sync break length is 14T bits // 0x00000020 : UART_LCTL_BLEN_15T : // Sync break length is 15T bits // 0x00000030 : UART_LCTL_BLEN_16T : // Sync break length is 16T bits #define UART_LCTL_BLEN_S 4 #define UART_LCTL_MASTER 0x00000001 // LIN Master Enable //****************************************************************************** // // The following are defines for the bit fields in the UART_O_LSS register. // //****************************************************************************** #define UART_LSS_TSS_M 0x0000FFFF // Timer Snap Shot #define UART_LSS_TSS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_LTIM register. // //****************************************************************************** #define UART_LTIM_TIMER_M 0x0000FFFF // Timer Value #define UART_LTIM_TIMER_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // UART_O_9BITADDR register. // //****************************************************************************** #define UART_9BITADDR_9BITEN \ 0x00008000 // Enable 9-Bit Mode #define UART_9BITADDR_ADDR_M \ 0x000000FF // Self Address for 9-Bit Mode #define UART_9BITADDR_ADDR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // UART_O_9BITAMASK register. // //****************************************************************************** #define UART_9BITAMASK_RANGE_M \ 0x0000FF00 // Self Address Range for 9-Bit // Mode #define UART_9BITAMASK_RANGE_S 8 #define UART_9BITAMASK_MASK_M \ 0x000000FF // Self Address Mask for 9-Bit Mode #define UART_9BITAMASK_MASK_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UART_O_PP register. // //****************************************************************************** #define UART_PP_MSE 0x00000008 // Modem Support Extended #define UART_PP_MS 0x00000004 // Modem Support #define UART_PP_NB 0x00000002 // 9-Bit Support #define UART_PP_SC 0x00000001 // Smart Card Support //****************************************************************************** // // The following are defines for the bit fields in the UART_O_CC register. // //****************************************************************************** #define UART_CC_CS_M 0x0000000F // UART Baud Clock Source // 0x00000005 : UART_CC_CS_PIOSC : // PIOSC 0x00000000 : // UART_CC_CS_SYSCLK : The system // clock (default) #define UART_CC_CS_S 0 #endif // __HW_UART_H__ micropython-1.12/ports/cc3200/hal/inc/hw_udma.h000066400000000000000000000407021357706137100212000ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_UDMA_H__ #define __HW_UDMA_H__ //***************************************************************************** // // The following are defines for the UDMA register offsets. // //***************************************************************************** #define UDMA_O_STAT 0x00000000 #define UDMA_O_CFG 0x00000004 #define UDMA_O_CTLBASE 0x00000008 #define UDMA_O_ALTBASE 0x0000000C #define UDMA_O_WAITSTAT 0x00000010 #define UDMA_O_SWREQ 0x00000014 #define UDMA_O_USEBURSTSET 0x00000018 #define UDMA_O_USEBURSTCLR 0x0000001C #define UDMA_O_REQMASKSET 0x00000020 #define UDMA_O_REQMASKCLR 0x00000024 #define UDMA_O_ENASET 0x00000028 #define UDMA_O_ENACLR 0x0000002C #define UDMA_O_ALTSET 0x00000030 #define UDMA_O_ALTCLR 0x00000034 #define UDMA_O_PRIOSET 0x00000038 #define UDMA_O_PRIOCLR 0x0000003C #define UDMA_O_ERRCLR 0x0000004C #define UDMA_O_CHASGN 0x00000500 #define UDMA_O_CHIS 0x00000504 #define UDMA_O_CHMAP0 0x00000510 #define UDMA_O_CHMAP1 0x00000514 #define UDMA_O_CHMAP2 0x00000518 #define UDMA_O_CHMAP3 0x0000051C #define UDMA_O_PV 0x00000FB0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_STAT register. // //****************************************************************************** #define UDMA_STAT_DMACHANS_M 0x001F0000 // Available uDMA Channels Minus 1 #define UDMA_STAT_DMACHANS_S 16 #define UDMA_STAT_STATE_M 0x000000F0 // Control State Machine Status // 0x00000090 : UDMA_STAT_STATE_DONE // : Done 0x00000000 : // UDMA_STAT_STATE_IDLE : Idle // 0x00000010 : // UDMA_STAT_STATE_RD_CTRL : Reading // channel controller data // 0x00000030 : // UDMA_STAT_STATE_RD_DSTENDP : // Reading destination end pointer // 0x00000040 : // UDMA_STAT_STATE_RD_SRCDAT : // Reading source data 0x00000020 : // UDMA_STAT_STATE_RD_SRCENDP : // Reading source end pointer // 0x00000080 : // UDMA_STAT_STATE_STALL : Stalled // 0x000000A0 : // UDMA_STAT_STATE_UNDEF : Undefined // 0x00000060 : UDMA_STAT_STATE_WAIT // : Waiting for uDMA request to // clear 0x00000070 : // UDMA_STAT_STATE_WR_CTRL : Writing // channel controller data // 0x00000050 : // UDMA_STAT_STATE_WR_DSTDAT : // Writing destination data #define UDMA_STAT_STATE_S 4 #define UDMA_STAT_MASTEN 0x00000001 // Master Enable Status //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_CFG register. // //****************************************************************************** #define UDMA_CFG_MASTEN 0x00000001 // Controller Master Enable //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_CTLBASE register. // //****************************************************************************** #define UDMA_CTLBASE_ADDR_M 0xFFFFFC00 // Channel Control Base Address #define UDMA_CTLBASE_ADDR_S 10 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_ALTBASE register. // //****************************************************************************** #define UDMA_ALTBASE_ADDR_M 0xFFFFFFFF // Alternate Channel Address // Pointer #define UDMA_ALTBASE_ADDR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_WAITSTAT register. // //****************************************************************************** #define UDMA_WAITSTAT_WAITREQ_M \ 0xFFFFFFFF // Channel [n] Wait Status #define UDMA_WAITSTAT_WAITREQ_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_SWREQ register. // //****************************************************************************** #define UDMA_SWREQ_M 0xFFFFFFFF // Channel [n] Software Request #define UDMA_SWREQ_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // UDMA_O_USEBURSTSET register. // //****************************************************************************** #define UDMA_USEBURSTSET_SET_M \ 0xFFFFFFFF // Channel [n] Useburst Set #define UDMA_USEBURSTSET_SET_S 0 //****************************************************************************** // // The following are defines for the bit fields in the // UDMA_O_USEBURSTCLR register. // //****************************************************************************** #define UDMA_USEBURSTCLR_CLR_M \ 0xFFFFFFFF // Channel [n] Useburst Clear #define UDMA_USEBURSTCLR_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_REQMASKSET register. // //****************************************************************************** #define UDMA_REQMASKSET_SET_M 0xFFFFFFFF // Channel [n] Request Mask Set #define UDMA_REQMASKSET_SET_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_REQMASKCLR register. // //****************************************************************************** #define UDMA_REQMASKCLR_CLR_M 0xFFFFFFFF // Channel [n] Request Mask Clear #define UDMA_REQMASKCLR_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_ENASET register. // //****************************************************************************** #define UDMA_ENASET_CHENSET_M 0xFFFFFFFF // Channel [n] Enable Set #define UDMA_ENASET_CHENSET_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_ENACLR register. // //****************************************************************************** #define UDMA_ENACLR_CLR_M 0xFFFFFFFF // Clear Channel [n] Enable Clear #define UDMA_ENACLR_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_ALTSET register. // //****************************************************************************** #define UDMA_ALTSET_SET_M 0xFFFFFFFF // Channel [n] Alternate Set #define UDMA_ALTSET_SET_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_ALTCLR register. // //****************************************************************************** #define UDMA_ALTCLR_CLR_M 0xFFFFFFFF // Channel [n] Alternate Clear #define UDMA_ALTCLR_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_PRIOSET register. // //****************************************************************************** #define UDMA_PRIOSET_SET_M 0xFFFFFFFF // Channel [n] Priority Set #define UDMA_PRIOSET_SET_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_PRIOCLR register. // //****************************************************************************** #define UDMA_PRIOCLR_CLR_M 0xFFFFFFFF // Channel [n] Priority Clear #define UDMA_PRIOCLR_CLR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_ERRCLR register. // //****************************************************************************** #define UDMA_ERRCLR_ERRCLR 0x00000001 // uDMA Bus Error Status //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_CHASGN register. // //****************************************************************************** #define UDMA_CHASGN_M 0xFFFFFFFF // Channel [n] Assignment Select #define UDMA_CHASGN_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_CHIS register. // //****************************************************************************** #define UDMA_CHIS_M 0xFFFFFFFF // Channel [n] Interrupt Status #define UDMA_CHIS_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_CHMAP0 register. // //****************************************************************************** #define UDMA_CHMAP0_CH7SEL_M 0xF0000000 // uDMA Channel 7 Source Select #define UDMA_CHMAP0_CH7SEL_S 28 #define UDMA_CHMAP0_CH6SEL_M 0x0F000000 // uDMA Channel 6 Source Select #define UDMA_CHMAP0_CH6SEL_S 24 #define UDMA_CHMAP0_CH5SEL_M 0x00F00000 // uDMA Channel 5 Source Select #define UDMA_CHMAP0_CH5SEL_S 20 #define UDMA_CHMAP0_CH4SEL_M 0x000F0000 // uDMA Channel 4 Source Select #define UDMA_CHMAP0_CH4SEL_S 16 #define UDMA_CHMAP0_CH3SEL_M 0x0000F000 // uDMA Channel 3 Source Select #define UDMA_CHMAP0_CH3SEL_S 12 #define UDMA_CHMAP0_CH2SEL_M 0x00000F00 // uDMA Channel 2 Source Select #define UDMA_CHMAP0_CH2SEL_S 8 #define UDMA_CHMAP0_CH1SEL_M 0x000000F0 // uDMA Channel 1 Source Select #define UDMA_CHMAP0_CH1SEL_S 4 #define UDMA_CHMAP0_CH0SEL_M 0x0000000F // uDMA Channel 0 Source Select #define UDMA_CHMAP0_CH0SEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_CHMAP1 register. // //****************************************************************************** #define UDMA_CHMAP1_CH15SEL_M 0xF0000000 // uDMA Channel 15 Source Select #define UDMA_CHMAP1_CH15SEL_S 28 #define UDMA_CHMAP1_CH14SEL_M 0x0F000000 // uDMA Channel 14 Source Select #define UDMA_CHMAP1_CH14SEL_S 24 #define UDMA_CHMAP1_CH13SEL_M 0x00F00000 // uDMA Channel 13 Source Select #define UDMA_CHMAP1_CH13SEL_S 20 #define UDMA_CHMAP1_CH12SEL_M 0x000F0000 // uDMA Channel 12 Source Select #define UDMA_CHMAP1_CH12SEL_S 16 #define UDMA_CHMAP1_CH11SEL_M 0x0000F000 // uDMA Channel 11 Source Select #define UDMA_CHMAP1_CH11SEL_S 12 #define UDMA_CHMAP1_CH10SEL_M 0x00000F00 // uDMA Channel 10 Source Select #define UDMA_CHMAP1_CH10SEL_S 8 #define UDMA_CHMAP1_CH9SEL_M 0x000000F0 // uDMA Channel 9 Source Select #define UDMA_CHMAP1_CH9SEL_S 4 #define UDMA_CHMAP1_CH8SEL_M 0x0000000F // uDMA Channel 8 Source Select #define UDMA_CHMAP1_CH8SEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_CHMAP2 register. // //****************************************************************************** #define UDMA_CHMAP2_CH23SEL_M 0xF0000000 // uDMA Channel 23 Source Select #define UDMA_CHMAP2_CH23SEL_S 28 #define UDMA_CHMAP2_CH22SEL_M 0x0F000000 // uDMA Channel 22 Source Select #define UDMA_CHMAP2_CH22SEL_S 24 #define UDMA_CHMAP2_CH21SEL_M 0x00F00000 // uDMA Channel 21 Source Select #define UDMA_CHMAP2_CH21SEL_S 20 #define UDMA_CHMAP2_CH20SEL_M 0x000F0000 // uDMA Channel 20 Source Select #define UDMA_CHMAP2_CH20SEL_S 16 #define UDMA_CHMAP2_CH19SEL_M 0x0000F000 // uDMA Channel 19 Source Select #define UDMA_CHMAP2_CH19SEL_S 12 #define UDMA_CHMAP2_CH18SEL_M 0x00000F00 // uDMA Channel 18 Source Select #define UDMA_CHMAP2_CH18SEL_S 8 #define UDMA_CHMAP2_CH17SEL_M 0x000000F0 // uDMA Channel 17 Source Select #define UDMA_CHMAP2_CH17SEL_S 4 #define UDMA_CHMAP2_CH16SEL_M 0x0000000F // uDMA Channel 16 Source Select #define UDMA_CHMAP2_CH16SEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_CHMAP3 register. // //****************************************************************************** #define UDMA_CHMAP3_CH31SEL_M 0xF0000000 // uDMA Channel 31 Source Select #define UDMA_CHMAP3_CH31SEL_S 28 #define UDMA_CHMAP3_CH30SEL_M 0x0F000000 // uDMA Channel 30 Source Select #define UDMA_CHMAP3_CH30SEL_S 24 #define UDMA_CHMAP3_CH29SEL_M 0x00F00000 // uDMA Channel 29 Source Select #define UDMA_CHMAP3_CH29SEL_S 20 #define UDMA_CHMAP3_CH28SEL_M 0x000F0000 // uDMA Channel 28 Source Select #define UDMA_CHMAP3_CH28SEL_S 16 #define UDMA_CHMAP3_CH27SEL_M 0x0000F000 // uDMA Channel 27 Source Select #define UDMA_CHMAP3_CH27SEL_S 12 #define UDMA_CHMAP3_CH26SEL_M 0x00000F00 // uDMA Channel 26 Source Select #define UDMA_CHMAP3_CH26SEL_S 8 #define UDMA_CHMAP3_CH25SEL_M 0x000000F0 // uDMA Channel 25 Source Select #define UDMA_CHMAP3_CH25SEL_S 4 #define UDMA_CHMAP3_CH24SEL_M 0x0000000F // uDMA Channel 24 Source Select #define UDMA_CHMAP3_CH24SEL_S 0 //****************************************************************************** // // The following are defines for the bit fields in the UDMA_O_PV register. // //****************************************************************************** #define UDMA_PV_MAJOR_M 0x0000FF00 // Major Revision #define UDMA_PV_MAJOR_S 8 #define UDMA_PV_MINOR_M 0x000000FF // Minor Revision #define UDMA_PV_MINOR_S 0 #endif // __HW_UDMA_H__ micropython-1.12/ports/cc3200/hal/inc/hw_wdt.h000066400000000000000000000137711357706137100210560ustar00rootroot00000000000000//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __HW_WDT_H__ #define __HW_WDT_H__ //***************************************************************************** // // The following are defines for the WDT register offsets. // //***************************************************************************** #define WDT_O_LOAD 0x00000000 #define WDT_O_VALUE 0x00000004 #define WDT_O_CTL 0x00000008 #define WDT_O_ICR 0x0000000C #define WDT_O_RIS 0x00000010 #define WDT_O_MIS 0x00000014 #define WDT_O_TEST 0x00000418 #define WDT_O_LOCK 0x00000C00 //****************************************************************************** // // The following are defines for the bit fields in the WDT_O_LOAD register. // //****************************************************************************** #define WDT_LOAD_M 0xFFFFFFFF // Watchdog Load Value #define WDT_LOAD_S 0 //****************************************************************************** // // The following are defines for the bit fields in the WDT_O_VALUE register. // //****************************************************************************** #define WDT_VALUE_M 0xFFFFFFFF // Watchdog Value #define WDT_VALUE_S 0 //****************************************************************************** // // The following are defines for the bit fields in the WDT_O_CTL register. // //****************************************************************************** #define WDT_CTL_WRC 0x80000000 // Write Complete #define WDT_CTL_INTTYPE 0x00000004 // Watchdog Interrupt Type #define WDT_CTL_RESEN 0x00000002 // Watchdog Reset Enable. This bit // is not used in cc3xx, WDOG shall // always generate RESET to system // irrespective of this bit setting. #define WDT_CTL_INTEN 0x00000001 // Watchdog Interrupt Enable //****************************************************************************** // // The following are defines for the bit fields in the WDT_O_ICR register. // //****************************************************************************** #define WDT_ICR_M 0xFFFFFFFF // Watchdog Interrupt Clear #define WDT_ICR_S 0 //****************************************************************************** // // The following are defines for the bit fields in the WDT_O_RIS register. // //****************************************************************************** #define WDT_RIS_WDTRIS 0x00000001 // Watchdog Raw Interrupt Status //****************************************************************************** // // The following are defines for the bit fields in the WDT_O_MIS register. // //****************************************************************************** #define WDT_MIS_WDTMIS 0x00000001 // Watchdog Masked Interrupt Status //****************************************************************************** // // The following are defines for the bit fields in the WDT_O_TEST register. // //****************************************************************************** #define WDT_TEST_STALL_EN_M 0x00000C00 // Watchdog stall enable #define WDT_TEST_STALL_EN_S 10 #define WDT_TEST_STALL 0x00000100 // Watchdog Stall Enable //****************************************************************************** // // The following are defines for the bit fields in the WDT_O_LOCK register. // //****************************************************************************** #define WDT_LOCK_M 0xFFFFFFFF // Watchdog Lock #define WDT_LOCK_S 0 #define WDT_LOCK_UNLOCKED 0x00000000 // Unlocked #define WDT_LOCK_LOCKED 0x00000001 // Locked #define WDT_LOCK_UNLOCK 0x1ACCE551 // Unlocks the watchdog timer //***************************************************************************** // // The following are defines for the bit fields in the WDT_ISR, WDT_RIS, and // WDT_MIS registers. // //***************************************************************************** #define WDT_INT_TIMEOUT 0x00000001 // Watchdog timer expired #endif // __HW_WDT_H__ micropython-1.12/ports/cc3200/hal/interrupt.c000066400000000000000000000602221357706137100210310ustar00rootroot00000000000000//***************************************************************************** // // interrupt.c // // Driver for the NVIC Interrupt Controller. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup interrupt_api //! @{ // //***************************************************************************** #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_types.h" #include "cpu.h" #include "debug.h" #include "interrupt.h" //***************************************************************************** // // This is a mapping between priority grouping encodings and the number of // preemption priority bits. // //***************************************************************************** static const unsigned long g_pulPriority[] = { NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6, NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4, NVIC_APINT_PRIGROUP_5_3, NVIC_APINT_PRIGROUP_6_2, NVIC_APINT_PRIGROUP_7_1 }; //***************************************************************************** // // This is a mapping between interrupt number and the register that contains // the priority encoding for that interrupt. // //***************************************************************************** static const unsigned long g_pulRegs[] = { 0, NVIC_SYS_PRI1, NVIC_SYS_PRI2, NVIC_SYS_PRI3, NVIC_PRI0, NVIC_PRI1, NVIC_PRI2, NVIC_PRI3, NVIC_PRI4, NVIC_PRI5, NVIC_PRI6, NVIC_PRI7, NVIC_PRI8, NVIC_PRI9, NVIC_PRI10, NVIC_PRI11, NVIC_PRI12, NVIC_PRI13, NVIC_PRI14, NVIC_PRI15, NVIC_PRI16, NVIC_PRI17, NVIC_PRI18, NVIC_PRI19, NVIC_PRI20, NVIC_PRI21, NVIC_PRI22, NVIC_PRI23, NVIC_PRI24, NVIC_PRI25, NVIC_PRI26, NVIC_PRI27, NVIC_PRI28, NVIC_PRI29, NVIC_PRI30, NVIC_PRI31, NVIC_PRI32, NVIC_PRI33, NVIC_PRI34, NVIC_PRI35, NVIC_PRI36, NVIC_PRI37, NVIC_PRI38, NVIC_PRI39, NVIC_PRI40, NVIC_PRI41, NVIC_PRI42, NVIC_PRI43, NVIC_PRI44, NVIC_PRI45, NVIC_PRI46, NVIC_PRI47, NVIC_PRI48 }; //***************************************************************************** // // This is a mapping between interrupt number (for the peripheral interrupts // only) and the register that contains the interrupt enable for that // interrupt. // //***************************************************************************** static const unsigned long g_pulEnRegs[] = { NVIC_EN0, NVIC_EN1, NVIC_EN2, NVIC_EN3, NVIC_EN4, NVIC_EN5 }; //***************************************************************************** // // This is a mapping between interrupt number (for the peripheral interrupts // only) and the register that contains the interrupt disable for that // interrupt. // //***************************************************************************** static const unsigned long g_pulDisRegs[] = { NVIC_DIS0, NVIC_DIS1, NVIC_DIS2, NVIC_DIS3, NVIC_DIS4, NVIC_DIS5 }; //***************************************************************************** // // This is a mapping between interrupt number (for the peripheral interrupts // only) and the register that contains the interrupt pend for that interrupt. // //***************************************************************************** static const unsigned long g_pulPendRegs[] = { NVIC_PEND0, NVIC_PEND1, NVIC_PEND2, NVIC_PEND3, NVIC_PEND4, NVIC_PEND5 }; //***************************************************************************** // // This is a mapping between interrupt number (for the peripheral interrupts // only) and the register that contains the interrupt unpend for that // interrupt. // //***************************************************************************** static const unsigned long g_pulUnpendRegs[] = { NVIC_UNPEND0, NVIC_UNPEND1, NVIC_UNPEND2, NVIC_UNPEND3, NVIC_UNPEND4, NVIC_UNPEND5 }; //***************************************************************************** // //! \internal //! The default interrupt handler. //! //! This is the default interrupt handler for all interrupts. It simply loops //! forever so that the system state is preserved for observation by a //! debugger. Since interrupts should be disabled before unregistering the //! corresponding handler, this should never be called. //! //! \return None. // //***************************************************************************** static void IntDefaultHandler(void) { // // Go into an infinite loop. // while(1) { } } //***************************************************************************** // //! Enables the processor interrupt. //! //! Allows the processor to respond to interrupts. This does not affect the //! set of interrupts enabled in the interrupt controller; it just gates the //! single interrupt from the controller to the processor. //! //! \note Previously, this function had no return value. As such, it was //! possible to include interrupt.h and call this function without //! having included hw_types.h. Now that the return is a //! tBoolean, a compiler error will occur in this case. The solution //! is to include hw_types.h before including interrupt.h. //! //! \return Returns \b true if interrupts were disabled when the function was //! called or \b false if they were initially enabled. // //***************************************************************************** tBoolean IntMasterEnable(void) { // // Enable processor interrupts. // return(CPUcpsie()); } //***************************************************************************** // //! Disables the processor interrupt. //! //! Prevents the processor from receiving interrupts. This does not affect the //! set of interrupts enabled in the interrupt controller; it just gates the //! single interrupt from the controller to the processor. //! //! \note Previously, this function had no return value. As such, it was //! possible to include interrupt.h and call this function without //! having included hw_types.h. Now that the return is a //! tBoolean, a compiler error will occur in this case. The solution //! is to include hw_types.h before including interrupt.h. //! //! \return Returns \b true if interrupts were already disabled when the //! function was called or \b false if they were initially enabled. // //***************************************************************************** tBoolean IntMasterDisable(void) { // // Disable processor interrupts. // return(CPUcpsid()); } //***************************************************************************** // //! Sets the NVIC VTable base. //! //! \param ulVtableBase specifies the new base address of VTable //! //! This function is used to specify a new base address for the VTable. //! This function must be called before using IntRegister() for registering //! any interrupt handler. //! //! //! \return None. // //***************************************************************************** void IntVTableBaseSet(unsigned long ulVtableBase) { HWREG(NVIC_VTABLE) = ulVtableBase; } //***************************************************************************** // //! Registers a function to be called when an interrupt occurs. //! //! \param ulInterrupt specifies the interrupt in question. //! \param pfnHandler is a pointer to the function to be called. //! //! This function is used to specify the handler function to be called when the //! given interrupt is asserted to the processor. When the interrupt occurs, //! if it is enabled (via IntEnable()), the handler function will be called in //! interrupt context. Since the handler function can preempt other code, care //! must be taken to protect memory or peripherals that are accessed by the //! handler and other non-handler code. //! //! //! \return None. // //***************************************************************************** void IntRegister(unsigned long ulInterrupt, void (*pfnHandler)(void)) { unsigned long *ulNvicTbl; // // Check the arguments. // ASSERT(ulInterrupt < NUM_INTERRUPTS); ulNvicTbl = (unsigned long *)HWREG(NVIC_VTABLE); ulNvicTbl[ulInterrupt]= (unsigned long)pfnHandler; } //***************************************************************************** // //! Unregisters the function to be called when an interrupt occurs. //! //! \param ulInterrupt specifies the interrupt in question. //! //! This function is used to indicate that no handler should be called when the //! given interrupt is asserted to the processor. The interrupt source will be //! automatically disabled (via IntDisable()) if necessary. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void IntUnregister(unsigned long ulInterrupt) { unsigned long *ulNvicTbl; // // Check the arguments. // ASSERT(ulInterrupt < NUM_INTERRUPTS); ulNvicTbl = (unsigned long *)HWREG(NVIC_VTABLE); ulNvicTbl[ulInterrupt]= (unsigned long)IntDefaultHandler; } //***************************************************************************** // //! Sets the priority grouping of the interrupt controller. //! //! \param ulBits specifies the number of bits of preemptable priority. //! //! This function specifies the split between preemptable priority levels and //! subpriority levels in the interrupt priority specification. The range of //! the grouping values are dependent upon the hardware implementation; on //! the CC3200 , three bits are available for hardware interrupt //! prioritization and therefore priority grouping values of three through //! seven have the same effect. //! //! \return None. // //***************************************************************************** void IntPriorityGroupingSet(unsigned long ulBits) { // // Check the arguments. // ASSERT(ulBits < NUM_PRIORITY); // // Set the priority grouping. // HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | g_pulPriority[ulBits]; } //***************************************************************************** // //! Gets the priority grouping of the interrupt controller. //! //! This function returns the split between preemptable priority levels and //! subpriority levels in the interrupt priority specification. //! //! \return The number of bits of preemptable priority. // //***************************************************************************** unsigned long IntPriorityGroupingGet(void) { unsigned long ulLoop, ulValue; // // Read the priority grouping. // ulValue = HWREG(NVIC_APINT) & NVIC_APINT_PRIGROUP_M; // // Loop through the priority grouping values. // for(ulLoop = 0; ulLoop < NUM_PRIORITY; ulLoop++) { // // Stop looping if this value matches. // if(ulValue == g_pulPriority[ulLoop]) { break; } } // // Return the number of priority bits. // return(ulLoop); } //***************************************************************************** // //! Sets the priority of an interrupt. //! //! \param ulInterrupt specifies the interrupt in question. //! \param ucPriority specifies the priority of the interrupt. //! //! This function is used to set the priority of an interrupt. When multiple //! interrupts are asserted simultaneously, the ones with the highest priority //! are processed before the lower priority interrupts. Smaller numbers //! correspond to higher interrupt priorities; priority 0 is the highest //! interrupt priority. //! //! The hardware priority mechanism will only look at the upper N bits of the //! priority level (where N is 3), so any prioritization must be performed in //! those bits. The remaining bits can be used to sub-prioritize the interrupt //! sources, and may be used by the hardware priority mechanism on a future //! part. This arrangement allows priorities to migrate to different NVIC //! implementations without changing the gross prioritization of the //! interrupts. //! //! The parameter \e ucPriority can be any one of the following //! -\b INT_PRIORITY_LVL_0 //! -\b INT_PRIORITY_LVL_1 //! -\b INT_PRIORITY_LVL_2 //! -\b INT_PRIORITY_LVL_3 //! -\b INT_PRIORITY_LVL_4 //! -\b INT_PRIORITY_LVL_5 //! -\b INT_PRIORITY_LVL_6 //! -\b INT_PRIORITY_LVL_7 //! //! \return None. // //***************************************************************************** void IntPrioritySet(unsigned long ulInterrupt, unsigned char ucPriority) { unsigned long ulTemp; // // Check the arguments. // ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS)); // // Set the interrupt priority. // ulTemp = HWREG(g_pulRegs[ulInterrupt >> 2]); ulTemp &= ~(0xFF << (8 * (ulInterrupt & 3))); ulTemp |= ucPriority << (8 * (ulInterrupt & 3)); HWREG(g_pulRegs[ulInterrupt >> 2]) = ulTemp; } //***************************************************************************** // //! Gets the priority of an interrupt. //! //! \param ulInterrupt specifies the interrupt in question. //! //! This function gets the priority of an interrupt. See IntPrioritySet() for //! a definition of the priority value. //! //! \return Returns the interrupt priority, or -1 if an invalid interrupt was //! specified. // //***************************************************************************** long IntPriorityGet(unsigned long ulInterrupt) { // // Check the arguments. // ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS)); // // Return the interrupt priority. // return((HWREG(g_pulRegs[ulInterrupt >> 2]) >> (8 * (ulInterrupt & 3))) & 0xFF); } //***************************************************************************** // //! Enables an interrupt. //! //! \param ulInterrupt specifies the interrupt to be enabled. //! //! The specified interrupt is enabled in the interrupt controller. Other //! enables for the interrupt (such as at the peripheral level) are unaffected //! by this function. //! //! \return None. // //***************************************************************************** void IntEnable(unsigned long ulInterrupt) { // // Check the arguments. // ASSERT(ulInterrupt < NUM_INTERRUPTS); // // Determine the interrupt to enable. // if(ulInterrupt == FAULT_MPU) { // // Enable the MemManage interrupt. // HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_MEM; __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt == FAULT_BUS) { // // Enable the bus fault interrupt. // HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_BUS; __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt == FAULT_USAGE) { // // Enable the usage fault interrupt. // HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_USAGE; __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt == FAULT_SYSTICK) { // // Enable the System Tick interrupt. // HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN; __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt >= 16) { // // Enable the general interrupt. // HWREG(g_pulEnRegs[(ulInterrupt - 16) / 32]) = 1 << ((ulInterrupt - 16) & 31); __asm(" dsb "); __asm(" isb "); } } //***************************************************************************** // //! Disables an interrupt. //! //! \param ulInterrupt specifies the interrupt to be disabled. //! //! The specified interrupt is disabled in the interrupt controller. Other //! enables for the interrupt (such as at the peripheral level) are unaffected //! by this function. //! //! \return None. // //***************************************************************************** void IntDisable(unsigned long ulInterrupt) { // // Check the arguments. // ASSERT(ulInterrupt < NUM_INTERRUPTS); // // Determine the interrupt to disable. // if(ulInterrupt == FAULT_MPU) { // // Disable the MemManage interrupt. // HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_MEM); __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt == FAULT_BUS) { // // Disable the bus fault interrupt. // HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_BUS); __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt == FAULT_USAGE) { // // Disable the usage fault interrupt. // HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_USAGE); __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt == FAULT_SYSTICK) { // // Disable the System Tick interrupt. // HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN); __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt >= 16) { // // Disable the general interrupt. // HWREG(g_pulDisRegs[(ulInterrupt - 16) / 32]) = 1 << ((ulInterrupt - 16) & 31); __asm(" dsb "); __asm(" isb "); } } //***************************************************************************** // //! Pends an interrupt. //! //! \param ulInterrupt specifies the interrupt to be pended. //! //! The specified interrupt is pended in the interrupt controller. This will //! cause the interrupt controller to execute the corresponding interrupt //! handler at the next available time, based on the current interrupt state //! priorities. For example, if called by a higher priority interrupt handler, //! the specified interrupt handler will not be called until after the current //! interrupt handler has completed execution. The interrupt must have been //! enabled for it to be called. //! //! \return None. // //***************************************************************************** void IntPendSet(unsigned long ulInterrupt) { // // Check the arguments. // ASSERT(ulInterrupt < NUM_INTERRUPTS); // // Determine the interrupt to pend. // if(ulInterrupt == FAULT_NMI) { // // Pend the NMI interrupt. // HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_NMI_SET; __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt == FAULT_PENDSV) { // // Pend the PendSV interrupt. // HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PEND_SV; __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt == FAULT_SYSTICK) { // // Pend the SysTick interrupt. // HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTSET; __asm(" dsb "); __asm(" isb "); } else if(ulInterrupt >= 16) { // // Pend the general interrupt. // HWREG(g_pulPendRegs[(ulInterrupt - 16) / 32]) = 1 << ((ulInterrupt - 16) & 31); __asm(" dsb "); __asm(" isb "); } } //***************************************************************************** // //! Unpends an interrupt. //! //! \param ulInterrupt specifies the interrupt to be unpended. //! //! The specified interrupt is unpended in the interrupt controller. This will //! cause any previously generated interrupts that have not been handled yet //! (due to higher priority interrupts or the interrupt no having been enabled //! yet) to be discarded. //! //! \return None. // //***************************************************************************** void IntPendClear(unsigned long ulInterrupt) { // // Check the arguments. // ASSERT(ulInterrupt < NUM_INTERRUPTS); // // Determine the interrupt to unpend. // if(ulInterrupt == FAULT_PENDSV) { // // Unpend the PendSV interrupt. // HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_UNPEND_SV; } else if(ulInterrupt == FAULT_SYSTICK) { // // Unpend the SysTick interrupt. // HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTCLR; } else if(ulInterrupt >= 16) { // // Unpend the general interrupt. // HWREG(g_pulUnpendRegs[(ulInterrupt - 16) / 32]) = 1 << ((ulInterrupt - 16) & 31); } } //***************************************************************************** // //! Sets the priority masking level //! //! \param ulPriorityMask is the priority level that will be masked. //! //! This function sets the interrupt priority masking level so that all //! interrupts at the specified or lesser priority level is masked. This //! can be used to globally disable a set of interrupts with priority below //! a predetermined threshold. A value of 0 disables priority //! masking. //! //! Smaller numbers correspond to higher interrupt priorities. So for example //! a priority level mask of 4 will allow interrupts of priority level 0-3, //! and interrupts with a numerical priority of 4 and greater will be blocked. //! //! The hardware priority mechanism will only look at the upper N bits of the //! priority level (where N is 3), so any //! prioritization must be performed in those bits. //! //! \return None. // //***************************************************************************** void IntPriorityMaskSet(unsigned long ulPriorityMask) { CPUbasepriSet(ulPriorityMask); } //***************************************************************************** // //! Gets the priority masking level //! //! This function gets the current setting of the interrupt priority masking //! level. The value returned is the priority level such that all interrupts //! of that and lesser priority are masked. A value of 0 means that priority //! masking is disabled. //! //! Smaller numbers correspond to higher interrupt priorities. So for example //! a priority level mask of 4 will allow interrupts of priority level 0-3, //! and interrupts with a numerical priority of 4 and greater will be blocked. //! //! The hardware priority mechanism will only look at the upper N bits of the //! priority level (where N is 3), so any //! prioritization must be performed in those bits. //! //! \return Returns the value of the interrupt priority level mask. // //***************************************************************************** unsigned long IntPriorityMaskGet(void) { return(CPUbasepriGet()); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/interrupt.h000066400000000000000000000113371357706137100210410ustar00rootroot00000000000000//***************************************************************************** // // interrupt.h // // Prototypes for the NVIC Interrupt Controller Driver. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __INTERRUPT_H__ #define __INTERRUPT_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // A union that describes the entries of the vector table. The union is needed // since the first entry is the stack pointer and the remainder are function // pointers. // //***************************************************************************** typedef union { void (*pfnHandler)(void); unsigned long ulPtr; } uVectorEntry; //***************************************************************************** // // Macro to generate an interrupt priority mask based on the number of bits // of priority supported by the hardware. // //***************************************************************************** #define INT_PRIORITY_MASK ((0xFF << (8 - NUM_PRIORITY_BITS)) & 0xFF) //***************************************************************************** // Interrupt priority levels //***************************************************************************** #define INT_PRIORITY_LVL_0 0x00 #define INT_PRIORITY_LVL_1 0x20 #define INT_PRIORITY_LVL_2 0x40 #define INT_PRIORITY_LVL_3 0x60 #define INT_PRIORITY_LVL_4 0x80 #define INT_PRIORITY_LVL_5 0xA0 #define INT_PRIORITY_LVL_6 0xC0 #define INT_PRIORITY_LVL_7 0xE0 //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** extern tBoolean IntMasterEnable(void); extern tBoolean IntMasterDisable(void); extern void IntVTableBaseSet(unsigned long ulVtableBase); extern void IntRegister(unsigned long ulInterrupt, void (*pfnHandler)(void)); extern void IntUnregister(unsigned long ulInterrupt); extern void IntPriorityGroupingSet(unsigned long ulBits); extern unsigned long IntPriorityGroupingGet(void); extern void IntPrioritySet(unsigned long ulInterrupt, unsigned char ucPriority); extern long IntPriorityGet(unsigned long ulInterrupt); extern void IntEnable(unsigned long ulInterrupt); extern void IntDisable(unsigned long ulInterrupt); extern void IntPendSet(unsigned long ulInterrupt); extern void IntPendClear(unsigned long ulInterrupt); extern void IntPriorityMaskSet(unsigned long ulPriorityMask); extern unsigned long IntPriorityMaskGet(void); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __INTERRUPT_H__ micropython-1.12/ports/cc3200/hal/pin.c000066400000000000000000000440201357706137100175610ustar00rootroot00000000000000//***************************************************************************** // // pin.c // // Mapping of peripherals to pins. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup pin_api //! @{ // //***************************************************************************** #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "inc/hw_ocp_shared.h" #include "pin.h" //***************************************************************************** // PIN to PAD matrix //***************************************************************************** static const unsigned long g_ulPinToPadMap[64] = { 10,11,12,13,14,15,16,17,255,255,18, 19,20,21,22,23,24,40,28,29,25,255, 255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255, 31,255,255,255,255,0,255,32,30,255,1, 255,2,3,4,5,6,7,8,9 }; //***************************************************************************** // //! Configures pin mux for the specified pin. //! //! \param ulPin is a valid pin. //! \param ulPinMode is one of the valid mode //! //! This function configures the pin mux that selects the peripheral function //! associated with a particular SOC pin. Only one peripheral function at a //! time can be associated with a pin, and each peripheral function should //! only be associated with a single pin at a time. //! //! \return none // //***************************************************************************** void PinModeSet(unsigned long ulPin,unsigned long ulPinMode) { unsigned long ulPad; // // Get the corresponding Pad // ulPad = g_ulPinToPadMap[ulPin & 0x3F]; // // Calculate the register address // ulPad = ((ulPad << 2) + PAD_CONFIG_BASE); // // Set the mode. // HWREG(ulPad) = (((HWREG(ulPad) & ~PAD_MODE_MASK) | ulPinMode) & ~(3<<10)); } //***************************************************************************** // //! Gets current pin mux configuration of specified pin. //! //! \param ulPin is a valid pin. //! //! This function get the current configuration of the pin mux. //! //! \return Returns current pin mode if \e ulPin is valid, 0xFF otherwise. // //***************************************************************************** unsigned long PinModeGet(unsigned long ulPin) { unsigned long ulPad; // // Get the corresponding Pad // ulPad = g_ulPinToPadMap[ulPin & 0x3F]; // // Calculate the register address // ulPad = ((ulPad << 2) + PAD_CONFIG_BASE) ; // // return the mode. // return (HWREG(ulPad) & PAD_MODE_MASK); } //***************************************************************************** // //! Sets the direction of the specified pin(s). //! //! \param ulPin is one of the valid pin. //! \param ulPinIO is the pin direction and/or mode. //! //! This function configures the specified pin(s) as either input only or //! output only or it configures the pin to be under hardware control. //! //! The parameter \e ulPinIO is an enumerated data type that can be one of //! the following values: //! //! - \b PIN_DIR_MODE_IN //! - \b PIN_DIR_MODE_OUT //! - \b PIN_DIR_MODE_HW //! //! where \b PIN_DIR_MODE_IN specifies that the pin is programmed as a //! input only, \b PIN_DIR_MODE_OUT specifies that the pin is //! programmed output only, and \b PIN_DIR_MODE_HW specifies that the pin is //! placed under hardware control. //! //! //! \return None. // //***************************************************************************** void PinDirModeSet(unsigned long ulPin, unsigned long ulPinIO) { unsigned long ulPad; // // Get the corresponding Pad // ulPad = g_ulPinToPadMap[ulPin & 0x3F]; // // Calculate the register address // ulPad = ((ulPad << 2) + PAD_CONFIG_BASE); // // Set the direction // HWREG(ulPad) = ((HWREG(ulPad) & ~0xC00) | ulPinIO); } //***************************************************************************** // //! Gets the direction of a pin. //! //! \param ulPin is one of the valid pin. //! //! This function gets the direction and control mode for a specified pin on //! the selected GPIO port. The pin can be configured as either an input only //! or output only, or it can be under hardware control. The type of control //! and direction are returned as an enumerated data type. //! //! \return Returns one of the enumerated data types described for //! GPIODirModeSet(). // //***************************************************************************** unsigned long PinDirModeGet(unsigned long ulPin) { unsigned long ulPad; // // Get the corresponding Pad // ulPad = g_ulPinToPadMap[ulPin & 0x3F]; // // Calculate the register address // ulPad = ((ulPad << 2) + PAD_CONFIG_BASE); // // Return the direction // return ((HWREG(ulPad) & 0xC00)); } //***************************************************************************** // //! Gets Pin output drive strength and Type //! //! \param ulPin is one of the valid pin //! \param pulPinStrength is pointer to storage for output drive strength //! \param pulPinType is pinter to storage for pin type //! //! This function gets the pin type and output drive strength for the pin //! specified by \e ulPin parameter. Parameters \e pulPinStrength and //! \e pulPinType corresponds to the values used in PinConfigSet(). //! //! //! \return None. // //***************************************************************************** void PinConfigGet(unsigned long ulPin,unsigned long *pulPinStrength, unsigned long *pulPinType) { unsigned long ulPad; // // Get the corresponding Pad // ulPad = g_ulPinToPadMap[ulPin & 0x3F]; // // Calculate the register address // ulPad = ((ulPad << 2) + PAD_CONFIG_BASE); // // Get the type // *pulPinType = (HWREG(ulPad) & PAD_TYPE_MASK); // // Get the output drive strength // *pulPinStrength = (HWREG(ulPad) & PAD_STRENGTH_MASK); } //***************************************************************************** // //! Configure Pin output drive strength and Type //! //! \param ulPin is one of the valid pin //! \param ulPinStrength is logical OR of valid output drive strengths. //! \param ulPinType is one of the valid pin type. //! //! This function sets the pin type and strength for the pin specified by //! \e ulPin parameter. //! //! The parameter \e ulPinStrength should be one of the following //! - \b PIN_STRENGTH_2MA //! - \b PIN_STRENGTH_4MA //! - \b PIN_STRENGTH_6MA //! //! //! The parameter \e ulPinType should be one of the following //! For standard type //! //! - \b PIN_TYPE_STD //! - \b PIN_TYPE_STD_PU //! - \b PIN_TYPE_STD_PD //! //! And for Open drain type //! //! - \b PIN_TYPE_OD //! - \b PIN_TYPE_OD_PU //! - \b PIN_TYPE_OD_PD //! //! \return None. // //***************************************************************************** void PinConfigSet(unsigned long ulPin,unsigned long ulPinStrength, unsigned long ulPinType) { unsigned long ulPad; // // Get the corresponding Pad // ulPad = g_ulPinToPadMap[ulPin & 0x3F]; // // Write the register // if(ulPinType == PIN_TYPE_ANALOG) { // // Isolate the input // HWREG(0x4402E144) |= ((0x80 << ulPad) & (0x1E << 8)); // // Calculate the register address // ulPad = ((ulPad << 2) + PAD_CONFIG_BASE); // // Isolate the output // HWREG(ulPad) = 0xC00; } else { // // Enable the input // HWREG(0x4402E144) &= ~((0x80 << ulPad) & (0x1E << 8)); // // Calculate the register address // ulPad = ((ulPad << 2) + PAD_CONFIG_BASE); // // Write the configuration // HWREG(ulPad) = ((HWREG(ulPad) & ~(PAD_STRENGTH_MASK | PAD_TYPE_MASK)) | (ulPinStrength | ulPinType )); } } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by UART peripheral //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! //! The UART pins must be properly configured for the peripheral to //! function correctly. This function provides a typical configuration for //! those pin(s); other configurations may work as well depending upon the //! board setup (for example, using the on-chip pull-ups). //! //! //! \note This function cannot be used to turn any pin into a UART pin; it //! only sets the pin mode and configures it for proper UART operation. //! //! //! \return None. // //***************************************************************************** void PinTypeUART(unsigned long ulPin,unsigned long ulPinMode) { // // Set the pin to specified mode // PinModeSet(ulPin,ulPinMode); // // Set the pin for standard operation // PinConfigSet(ulPin,PIN_STRENGTH_2MA,PIN_TYPE_STD); } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by I2C peripheral //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! //! The I2C pins must be properly configured for the peripheral to //! function correctly. This function provides a typical configuration for //! the pin. //! //! //! \note This function cannot be used to turn any pin into a I2C pin; it //! only sets the pin mode and configures it for proper I2C operation. //! //! //! \return None. // //***************************************************************************** void PinTypeI2C(unsigned long ulPin,unsigned long ulPinMode) { // // Set the pin to specified mode // PinModeSet(ulPin,ulPinMode); // // Set the pin for open-drain operation with a weak pull-up. // PinConfigSet(ulPin,PIN_STRENGTH_2MA,PIN_TYPE_OD_PU); } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by SPI peripheral //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! //! The SPI pins must be properly configured for the peripheral to //! function correctly. This function provides a typical configuration for //! those pin. //! //! //! \note This function cannot be used to turn any pin into a SPI pin; it //! only sets the pin mode and configures it for proper SPI operation. //! //! //! \return None. // //***************************************************************************** void PinTypeSPI(unsigned long ulPin,unsigned long ulPinMode) { // // Set the pin to specified mode // PinModeSet(ulPin,ulPinMode); // // Set the pin for standard operation // PinConfigSet(ulPin,PIN_STRENGTH_2MA|PIN_STRENGTH_4MA,PIN_TYPE_STD); } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by I2S peripheral //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! //! The I2S pins must be properly configured for the peripheral to //! function correctly. This function provides a typical configuration for //! those pin. //! //! //! \note This function cannot be used to turn any pin into a I2S pin; it //! only sets the pin mode and configures it for proper I2S operation. //! //! \return None. // //***************************************************************************** void PinTypeI2S(unsigned long ulPin,unsigned long ulPinMode) { // // Set the pin to specified mode // PinModeSet(ulPin,ulPinMode); // // Set the pin for standard operation // PinConfigSet(ulPin,PIN_STRENGTH_2MA|PIN_STRENGTH_4MA,PIN_TYPE_STD); } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by Timer peripheral //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! //! The timer PWM pins must be properly configured for the Timer peripheral to //! function correctly. This function provides a typical configuration for //! those pin; other configurations may work as well depending upon the //! board setup (for example, using the on-chip pull-ups). //! //! //! \note This function cannot be used to turn any pin into a timer PWM pin; it //! only sets the pin mode and configures it for proper timer PWM operation. //! //! \return None. // //***************************************************************************** void PinTypeTimer(unsigned long ulPin,unsigned long ulPinMode) { // // Set the pin to specified mode // PinModeSet(ulPin,ulPinMode); // // Set the pin for standard operation // PinConfigSet(ulPin,PIN_STRENGTH_2MA|PIN_STRENGTH_4MA,PIN_TYPE_STD); } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by Camera peripheral //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! //! The Camera pins must be properly configured for the peripheral to //! function correctly. This function provides a typical configuration for //! those pin. //! //! //! \note This function cannot be used to turn any pin into a Camera pin; it //! only sets the pin mode and configures it for proper Camera operation. //! //! \return None. // //***************************************************************************** void PinTypeCamera(unsigned long ulPin,unsigned long ulPinMode) { // // Set the pin to specified mode // PinModeSet(ulPin,ulPinMode); // // Set the pin for standard operation // PinConfigSet(ulPin,PIN_STRENGTH_2MA|PIN_STRENGTH_4MA,PIN_TYPE_STD); } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by GPIO peripheral //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! \param bOpenDrain is one to decide either OpenDrain or STD //! //! The GPIO pins must be properly configured for the peripheral to //! function correctly. This function provides a typical configuration for //! those pin. //! //! //! \return None. // //***************************************************************************** void PinTypeGPIO(unsigned long ulPin,unsigned long ulPinMode,tBoolean bOpenDrain) { // // Set the pin for standard push-pull operation. // if(bOpenDrain) { PinConfigSet(ulPin, PIN_STRENGTH_2MA, PIN_TYPE_OD); } else { PinConfigSet(ulPin, PIN_STRENGTH_2MA, PIN_TYPE_STD); } // // Set the pin to specified mode // PinModeSet(ulPin, ulPinMode); } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by ADC //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! //! The ADC pins must be properly configured for the peripheral to //! function correctly. This function provides a typical configuration for //! those pin. //! //! //! \note This function cannot be used to turn any pin into a ADC pin; it //! only sets the pin mode and configures it for proper ADC operation. //! //! \return None. // //***************************************************************************** void PinTypeADC(unsigned long ulPin,unsigned long ulPinMode) { // // Configure the Pin // PinConfigSet(ulPin,PIN_STRENGTH_2MA,PIN_TYPE_ANALOG); } //***************************************************************************** // //! Sets the pin mode and configures the pin for use by SD Host peripheral //! //! \param ulPin is one of the valid pin. //! \param ulPinMode is one of the valid pin mode. //! //! The MMC pins must be properly configured for the peripheral to //! function correctly. This function provides a typical configuration for //! those pin. //! //! //! \note This function cannot be used to turn any pin into a SD Host pin; it //! only sets the pin mode and configures it for proper SD Host operation. //! //! \return None. // //***************************************************************************** void PinTypeSDHost(unsigned long ulPin,unsigned long ulPinMode) { // // Set pin mode // PinModeSet(ulPin,ulPinMode); // // Configure the Pin // PinConfigSet(ulPin,PIN_STRENGTH_2MA,PIN_TYPE_STD); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/pin.h000066400000000000000000000157061357706137100175770ustar00rootroot00000000000000//***************************************************************************** // // pin.h // // Defines and Macros for the pin mux module // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __PIN_H__ #define __PIN_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // Macros Defining Pins //***************************************************************************** #define PIN_01 0x00000000 #define PIN_02 0x00000001 #define PIN_03 0x00000002 #define PIN_04 0x00000003 #define PIN_05 0x00000004 #define PIN_06 0x00000005 #define PIN_07 0x00000006 #define PIN_08 0x00000007 #define PIN_11 0x0000000A #define PIN_12 0x0000000B #define PIN_13 0x0000000C #define PIN_14 0x0000000D #define PIN_15 0x0000000E #define PIN_16 0x0000000F #define PIN_17 0x00000010 #define PIN_18 0x00000011 #define PIN_19 0x00000012 #define PIN_20 0x00000013 #define PIN_21 0x00000014 #define PIN_45 0x0000002C #define PIN_46 0x0000002D #define PIN_47 0x0000002E #define PIN_48 0x0000002F #define PIN_49 0x00000030 #define PIN_50 0x00000031 #define PIN_52 0x00000033 #define PIN_53 0x00000034 #define PIN_55 0x00000036 #define PIN_56 0x00000037 #define PIN_57 0x00000038 #define PIN_58 0x00000039 #define PIN_59 0x0000003A #define PIN_60 0x0000003B #define PIN_61 0x0000003C #define PIN_62 0x0000003D #define PIN_63 0x0000003E #define PIN_64 0x0000003F //***************************************************************************** // Macros that can be used with PinConfigSet(), PinTypeGet(), PinStrengthGet() //***************************************************************************** #define PIN_MODE_0 0x00000000 #define PIN_MODE_1 0x00000001 #define PIN_MODE_2 0x00000002 #define PIN_MODE_3 0x00000003 #define PIN_MODE_4 0x00000004 #define PIN_MODE_5 0x00000005 #define PIN_MODE_6 0x00000006 #define PIN_MODE_7 0x00000007 #define PIN_MODE_8 0x00000008 #define PIN_MODE_9 0x00000009 #define PIN_MODE_10 0x0000000A #define PIN_MODE_11 0x0000000B #define PIN_MODE_12 0x0000000C #define PIN_MODE_13 0x0000000D #define PIN_MODE_14 0x0000000E #define PIN_MODE_15 0x0000000F // Note : PIN_MODE_255 is a dummy define for pinmux utility code generation // PIN_MODE_255 should never be used in any user code. #define PIN_MODE_255 0x000000FF //***************************************************************************** // Macros that can be used with PinDirModeSet() and returned from // PinDirModeGet(). //***************************************************************************** #define PIN_DIR_MODE_IN 0x00000C00 // Pin is input #define PIN_DIR_MODE_OUT 0x00000800 // Pin is output #define PIN_DIR_MODE_HW 0x00000000 // Pin is peripheral function //***************************************************************************** // Macros that can be used with PinConfigSet() //***************************************************************************** #define PIN_STRENGTH_2MA 0x00000020 #define PIN_STRENGTH_4MA 0x00000040 #define PIN_STRENGTH_6MA 0x00000060 #define PIN_TYPE_STD 0x00000000 #define PIN_TYPE_STD_PU 0x00000100 #define PIN_TYPE_STD_PD 0x00000200 #define PIN_TYPE_OD 0x00000010 #define PIN_TYPE_OD_PU 0x00000110 #define PIN_TYPE_OD_PD 0x00000210 #define PIN_TYPE_ANALOG 0x10000000 //***************************************************************************** // Macros for mode and type //***************************************************************************** #define PAD_MODE_MASK 0x0000000F #define PAD_STRENGTH_MASK 0x000000E0 #define PAD_TYPE_MASK 0x00000310 #define PAD_CONFIG_BASE ((OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)) //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void PinModeSet(unsigned long ulPin, unsigned long ulPinMode); extern void PinDirModeSet(unsigned long ulPin, unsigned long ulPinIO); extern unsigned long PinDirModeGet(unsigned long ulPin); extern unsigned long PinModeGet(unsigned long ulPin); extern void PinConfigGet(unsigned long ulPin,unsigned long *pulPinStrength, unsigned long *pulPinType); extern void PinConfigSet(unsigned long ulPin,unsigned long ulPinStrength, unsigned long ulPinType); extern void PinTypeUART(unsigned long ulPin,unsigned long ulPinMode); extern void PinTypeI2C(unsigned long ulPin,unsigned long ulPinMode); extern void PinTypeSPI(unsigned long ulPin,unsigned long ulPinMode); extern void PinTypeI2S(unsigned long ulPin,unsigned long ulPinMode); extern void PinTypeTimer(unsigned long ulPin,unsigned long ulPinMode); extern void PinTypeCamera(unsigned long ulPin,unsigned long ulPinMode); extern void PinTypeGPIO(unsigned long ulPin,unsigned long ulPinMode, tBoolean bOpenDrain); extern void PinTypeADC(unsigned long ulPin,unsigned long ulPinMode); extern void PinTypeSDHost(unsigned long ulPin,unsigned long ulPinMode); #ifdef __cplusplus } #endif #endif //__PIN_H__ micropython-1.12/ports/cc3200/hal/prcm.c000066400000000000000000001660571357706137100177530ustar00rootroot00000000000000//***************************************************************************** // // prcm.c // // Driver for the Power, Reset and Clock Module (PRCM) // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup PRCM_Power_Reset_Clock_Module_api //! @{ // //***************************************************************************** #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_apps_rcm.h" #include "inc/hw_gprcm.h" #include "inc/hw_hib1p2.h" #include "inc/hw_hib3p3.h" #include "prcm.h" #include "interrupt.h" #include "cpu.h" #include "utils.h" #include "rom_map.h" //***************************************************************************** // Macro definition //***************************************************************************** #define PRCM_SOFT_RESET 0x00000001 #define PRCM_ENABLE_STATUS 0x00000002 #define SYS_CLK 80000000 #define XTAL_CLK 40000000 //***************************************************************************** // CC3200 does not have a true RTC capability. However, API(s) in this file // provide an effective mechanism to support RTC feature in the device. // // The implementation to support RTC has been kept very simple. A set of // HIB Memory Registers in conjunction with Slow Clock Counter are used // to render RTC information to users. Core principle of design involves // two steps (a) establish an association between user provided wall-clock // and slow clock counter. (b) store reference value of this associattion // in HIB Registers. This reference value and SCC value are then combined // to create real-world calendar time. // // Across HIB cycles, value stored in HIB Registers is retained and slow // clock counter continues to tick, thereby, this arragement is relevant // and valid as long as device has a (tickle) battery power. // // Further, provision also has been made to set an alarm. When it RTC value // matches that of set for alarm, an interrupt is generated. // // HIB MEM REG0 and REG1 are reserved for TI. // // If RTC feature is not used, then HIB REG2 & REG3 are available to user. // // Lower half of REG0 is used for TI HW ECO. //***************************************************************************** #define RTC_U64MSEC_MK(u32Secs, u16Msec) (((unsigned long long)u32Secs << 10)|\ (u16Msec & 0x3FF)) #define RTC_SECS_IN_U64MSEC(u64Msec) ((unsigned long)(u64Msec >> 10)) #define RTC_MSEC_IN_U64MSEC(u64Msec) ((unsigned short)(u64Msec & 0x3FF)) #define RTC_MSEC_U32_REG_ADDR (HIB3P3_BASE + HIB3P3_O_MEM_HIB_REG2) #define RTC_SECS_U32_REG_ADDR (HIB3P3_BASE + HIB3P3_O_MEM_HIB_REG3) //***************************************************************************** // Register Access and Updates // // Tick of SCC has a resolution of 32768Hz, meaning 1 sec is equal to 32768 // clock ticks. Ideal way of getting time in millisecond will involve floating // point arithmetic (division by 32.768). To avoid this, we simply divide it by // 32, which will give a range from 0 -1023(instead of 0-999). To use this // output correctly we have to take care of this inaccuracy externally. // following wrapper can be used to convert the value from cycles to // millisecond: // // CYCLES_U16MS(cycles) ((cycles * 1000) / 1024), // // Similarly, before setting the value, it must be first converted (from ms to // cycles). // // U16MS_CYCLES(msec) ((msec * 1024) / 1000) // // Note: There is a precision loss of 1 ms with the above scheme. // // #define SCC_U64MSEC_GET() (RTCFastDomainCounterGet() >> 5) #define SCC_U64MSEC_MATCH_SET(u64Msec) (MAP_PRCMSlowClkCtrMatchSet(u64Msec << 5)) #define SCC_U64MSEC_MATCH_GET() (MAP_PRCMSlowClkCtrMatchGet() >> 5) //***************************************************************************** // // Bit: 31 is used to indicate use of RTC. If set as '1', RTC feature is used. // Bit: 30 is used to indicate that a safe boot should be performed. // bit: 29 is used to indicate that the last reset was caused by the WDT. // bit: 28 is used to indicate that the board is booting for the first time after being programmed in factory. // Bits: 27 and 26 are unused. // Bits: 25 to 16 are used to save millisecond part of RTC reference. // Bits: 15 to 0 are being used for HW Changes / ECO. // //***************************************************************************** //***************************************************************************** // Set RTC USE Bit //***************************************************************************** static void RTCUseSet(void) { unsigned int uiRegValue; uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) | (1 << 31); PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue); } //***************************************************************************** // Clear RTC USE Bit //***************************************************************************** static void RTCUseClear(void) { unsigned int uiRegValue; uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(1 << 31)); PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue); } //***************************************************************************** // Checks if RTC-USE bit is set //***************************************************************************** static tBoolean IsRTCUsed(void) { return (MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (1 << 31)) ? true : false; } //***************************************************************************** // Read 16-bit mSecs //***************************************************************************** static unsigned short RTCU32MSecRegRead(void) { return ((MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) >> 16) & 0x03FF); } //***************************************************************************** // Write 16-bit mSecs //***************************************************************************** static void RTCU32MSecRegWrite(unsigned int u32Msec) { unsigned int uiRegValue; // read the whole register and clear the msec bits uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(0x03FF << 16)); // write the msec bits only MAP_PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue | ((u32Msec & 0x03FF) << 16)); } //***************************************************************************** // Read 32-bit Secs //***************************************************************************** static unsigned long RTCU32SecRegRead(void) { return (MAP_PRCMHIBRegRead(RTC_SECS_U32_REG_ADDR)); } //***************************************************************************** // Write 32-bit Secs //***************************************************************************** static void RTCU32SecRegWrite(unsigned long u32Msec) { MAP_PRCMHIBRegWrite(RTC_SECS_U32_REG_ADDR, u32Msec); } //***************************************************************************** // Fast function to get the most accurate RTC counter value //***************************************************************************** static unsigned long long RTCFastDomainCounterGet (void) { #define BRK_IF_RTC_CTRS_ALIGN(c2, c1) if (c2 - c1 <= 1) { \ itr++; \ break; \ } unsigned long long rtc_count1, rtc_count2, rtc_count3; unsigned int itr; do { rtc_count1 = PRCMSlowClkCtrFastGet(); rtc_count2 = PRCMSlowClkCtrFastGet(); rtc_count3 = PRCMSlowClkCtrFastGet(); itr = 0; BRK_IF_RTC_CTRS_ALIGN(rtc_count2, rtc_count1); BRK_IF_RTC_CTRS_ALIGN(rtc_count3, rtc_count2); BRK_IF_RTC_CTRS_ALIGN(rtc_count3, rtc_count1); // Consistent values in two consecutive reads implies a correct // value of the counter. Do note, the counter does not give the // calendar time but a hardware that ticks upwards continuously. // The 48-bit counter operates at 32,768 HZ. } while (true); return (1 == itr) ? rtc_count2 : rtc_count3; } //***************************************************************************** // Macros //***************************************************************************** #define IS_RTC_USED() IsRTCUsed() #define RTC_USE_SET() RTCUseSet() #define RTC_USE_CLR() RTCUseClear() #define RTC_U32MSEC_REG_RD() RTCU32MSecRegRead() #define RTC_U32MSEC_REG_WR(u32Msec) RTCU32MSecRegWrite(u32Msec) #define RTC_U32SECS_REG_RD() RTCU32SecRegRead() #define RTC_U32SECS_REG_WR(u32Secs) RTCU32SecRegWrite(u32Secs) #define SELECT_SCC_U42BITS(u64Msec) (u64Msec & 0x3ffffffffff) //***************************************************************************** // Global Peripheral clock and rest Registers //***************************************************************************** static const PRCM_PeriphRegs_t PRCM_PeriphRegsList[] = { {APPS_RCM_O_CAMERA_CLK_GATING, APPS_RCM_O_CAMERA_SOFT_RESET }, {APPS_RCM_O_MCASP_CLK_GATING, APPS_RCM_O_MCASP_SOFT_RESET }, {APPS_RCM_O_MMCHS_CLK_GATING, APPS_RCM_O_MMCHS_SOFT_RESET }, {APPS_RCM_O_MCSPI_A1_CLK_GATING, APPS_RCM_O_MCSPI_A1_SOFT_RESET }, {APPS_RCM_O_MCSPI_A2_CLK_GATING, APPS_RCM_O_MCSPI_A2_SOFT_RESET }, {APPS_RCM_O_UDMA_A_CLK_GATING, APPS_RCM_O_UDMA_A_SOFT_RESET }, {APPS_RCM_O_GPIO_A_CLK_GATING, APPS_RCM_O_GPIO_A_SOFT_RESET }, {APPS_RCM_O_GPIO_B_CLK_GATING, APPS_RCM_O_GPIO_B_SOFT_RESET }, {APPS_RCM_O_GPIO_C_CLK_GATING, APPS_RCM_O_GPIO_C_SOFT_RESET }, {APPS_RCM_O_GPIO_D_CLK_GATING, APPS_RCM_O_GPIO_D_SOFT_RESET }, {APPS_RCM_O_GPIO_E_CLK_GATING, APPS_RCM_O_GPIO_E_SOFT_RESET }, {APPS_RCM_O_WDOG_A_CLK_GATING, APPS_RCM_O_WDOG_A_SOFT_RESET }, {APPS_RCM_O_UART_A0_CLK_GATING, APPS_RCM_O_UART_A0_SOFT_RESET }, {APPS_RCM_O_UART_A1_CLK_GATING, APPS_RCM_O_UART_A1_SOFT_RESET }, {APPS_RCM_O_GPT_A0_CLK_GATING , APPS_RCM_O_GPT_A0_SOFT_RESET }, {APPS_RCM_O_GPT_A1_CLK_GATING, APPS_RCM_O_GPT_A1_SOFT_RESET }, {APPS_RCM_O_GPT_A2_CLK_GATING, APPS_RCM_O_GPT_A2_SOFT_RESET }, {APPS_RCM_O_GPT_A3_CLK_GATING, APPS_RCM_O_GPT_A3_SOFT_RESET }, {APPS_RCM_O_CRYPTO_CLK_GATING, APPS_RCM_O_CRYPTO_SOFT_RESET }, {APPS_RCM_O_MCSPI_S0_CLK_GATING, APPS_RCM_O_MCSPI_S0_SOFT_RESET }, {APPS_RCM_O_I2C_CLK_GATING, APPS_RCM_O_I2C_SOFT_RESET } }; //***************************************************************************** // //! Set a special bit //! //! \return None. // //***************************************************************************** void PRCMSetSpecialBit(unsigned char bit) { unsigned int uiRegValue; uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) | (1 << bit); PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue); } //***************************************************************************** // //! Clear a special bit //! //! \return None. // //***************************************************************************** void PRCMClearSpecialBit(unsigned char bit) { unsigned int uiRegValue; uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(1 << bit)); PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue); } //***************************************************************************** // //! Read a special bit //! //! \return Value of the bit // //***************************************************************************** tBoolean PRCMGetSpecialBit(unsigned char bit) { tBoolean value = (MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (1 << bit)) ? true : false; // special bits must be cleared immediatelly after reading PRCMClearSpecialBit(bit); return value; } //***************************************************************************** // //! Performs a software reset of a SOC //! //! This function performs a software reset of a SOC //! //! \return None. // //***************************************************************************** void PRCMSOCReset(void) { // // Reset MCU // HWREG(GPRCM_BASE+ GPRCM_O_MCU_GLOBAL_SOFT_RESET) |= 0x1; } //***************************************************************************** // //! Performs a software reset of a MCU and associated peripherals //! //! \param bIncludeSubsystem is \b true to reset associated peripherals. //! //! This function performs a software reset of a MCU and associated peripherals. //! To reset the associated peripheral, the parameter \e bIncludeSubsystem //! should be set to \b true. //! //! \return None. // //***************************************************************************** void PRCMMCUReset(tBoolean bIncludeSubsystem) { if(bIncludeSubsystem) { // // Reset Apps processor and associated peripheral // HWREG(GPRCM_BASE+ GPRCM_O_APPS_SOFT_RESET) = 0x2; } else { // // Reset Apps processor only // HWREG(GPRCM_BASE+ GPRCM_O_APPS_SOFT_RESET) = 0x1; } } //***************************************************************************** // //! Gets the reason for a reset. //! //! This function returns the reason(s) for a reset. The reset reason are:- //! -\b PRCM_POWER_ON - Device is powering up. //! -\b PRCM_LPDS_EXIT - Device is exiting from LPDS. //! -\b PRCM_CORE_RESET - Device is exiting soft core only reset //! -\b PRCM_MCU_RESET - Device is exiting soft subsystem reset. //! -\b PRCM_WDT_RESET - Device was reset by watchdog. //! -\b PRCM_SOC_RESET - Device is exting SOC reset. //! -\b PRCM_HIB_EXIT - Device is exiting hibernate. //! //! \return Returns one of the cause defined above. // //***************************************************************************** unsigned long PRCMSysResetCauseGet(void) { unsigned long ulWakeupStatus; // // Read the Reset status // ulWakeupStatus = (HWREG(GPRCM_BASE+ GPRCM_O_APPS_RESET_CAUSE) & 0xFF); // // For hibernate do additional chaeck. // if(ulWakeupStatus == PRCM_POWER_ON) { if(MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_WAKE_STATUS) & 0x1) { ulWakeupStatus = PRCM_HIB_EXIT; } } // // Return status. // return ulWakeupStatus; } //***************************************************************************** // //! Enable clock(s) to peripheral. //! //! \param ulPeripheral is one of the valid peripherals //! \param ulClkFlags are bitmask of clock(s) to be enabled. //! //! This function enables the clock for the specified peripheral. Peripherals //! are by default clock gated (disabled) and generates a bus fault if //! accessed. //! //! The parameter \e ulClkFlags can be logical OR of the following: //! -\b PRCM_RUN_MODE_CLK - Ungates clock to the peripheral //! -\b PRCM_SLP_MODE_CLK - Keeps the clocks ungated in sleep. //! -\b PRCM_DSLP_MODE_CLK - Keeps the clock ungated in deepsleep. //! //! \return None. // //***************************************************************************** void PRCMPeripheralClkEnable(unsigned long ulPeripheral, unsigned long ulClkFlags) { // // Enable the specified peripheral clocks, Nothing to be done for PRCM_ADC // as it is a dummy define for pinmux utility code generation // if(ulPeripheral != PRCM_ADC) { HWREG(ARCM_BASE + PRCM_PeriphRegsList[ulPeripheral].ulClkReg) |= ulClkFlags; } // // Set the default clock for camera // if(ulPeripheral == PRCM_CAMERA) { HWREG(ARCM_BASE + APPS_RCM_O_CAMERA_CLK_GEN) = 0x0404; } } //***************************************************************************** // //! Disables clock(s) to peripheral. //! //! \param ulPeripheral is one of the valid peripherals //! \param ulClkFlags are bitmask of clock(s) to be enabled. //! //! This function disable the clock for the specified peripheral. Peripherals //! are by default clock gated (disabled) and generated a bus fault if //! accessed. //! //! The parameter \e ulClkFlags can be logical OR bit fields as defined in //! PRCMEnablePeripheral(). //! //! \return None. // //***************************************************************************** void PRCMPeripheralClkDisable(unsigned long ulPeripheral, unsigned long ulClkFlags) { // // Disable the specified peripheral clocks // HWREG(ARCM_BASE + PRCM_PeriphRegsList[ulPeripheral].ulClkReg) &= ~ulClkFlags; } //***************************************************************************** // //! Gets the input clock for the specified peripheral. //! //! \param ulPeripheral is one of the valid peripherals. //! //! This function gets the input clock for the specified peripheral. //! //! The parameter \e ulPeripheral has the same definition as that in //! PRCMPeripheralClkEnable(); //! //! \return Returns input clock frequency for specified peripheral. // //***************************************************************************** unsigned long PRCMPeripheralClockGet(unsigned long ulPeripheral) { unsigned long ulClockFreq; unsigned long ulHiPulseDiv; unsigned long ulLoPulseDiv; // // Get the clock based on specified peripheral. // if(((ulPeripheral == PRCM_SSPI) | (ulPeripheral == PRCM_LSPI) | (ulPeripheral == PRCM_GSPI))) { return XTAL_CLK; } else if(ulPeripheral == PRCM_CAMERA) { ulHiPulseDiv = ((HWREG(ARCM_BASE + APPS_RCM_O_CAMERA_CLK_GEN) >> 8) & 0x07); ulLoPulseDiv = (HWREG(ARCM_BASE + APPS_RCM_O_CAMERA_CLK_GEN)& 0xFF); } else if(ulPeripheral == PRCM_SDHOST) { ulHiPulseDiv = ((HWREG(ARCM_BASE + APPS_RCM_O_MMCHS_CLK_GEN) >> 8) & 0x07); ulLoPulseDiv = (HWREG(ARCM_BASE + APPS_RCM_O_MMCHS_CLK_GEN)& 0xFF); } else { return SYS_CLK; } // // Compute the clock freq. from the divider value // ulClockFreq = (240000000/((ulHiPulseDiv + 1) + (ulLoPulseDiv + 1))); // // Return the clock rate. // return ulClockFreq; } //***************************************************************************** // //! Performs a software reset of a peripheral. //! //! \param ulPeripheral is one of the valid peripheral. //! //! This assert or deassert reset to the specified peripheral based of the //! \e bAssert parameter. //! //! \return None. // //***************************************************************************** void PRCMPeripheralReset(unsigned long ulPeripheral) { volatile unsigned long ulDelay; if( ulPeripheral != PRCM_DTHE) { // // Assert the reset // HWREG(ARCM_BASE + PRCM_PeriphRegsList[ulPeripheral].ulRstReg) |= PRCM_SOFT_RESET; // // Delay for a little bit. // for(ulDelay = 0; ulDelay < 16; ulDelay++) { } // // Deassert the reset // HWREG(ARCM_BASE+PRCM_PeriphRegsList[ulPeripheral].ulRstReg) &= ~PRCM_SOFT_RESET; } } //***************************************************************************** // //! Determines if a peripheral is ready. //! //! \param ulPeripheral is one of the valid modules //! //! This function determines if a particular peripheral is ready to be //! accessed. The peripheral may be in a non-ready state if it is not enabled, //! is being held in reset, or is in the process of becoming ready after being //! enabled or taken out of reset. //! //! \return Returns \b true if the peripheral is ready, \b false otherwise. // //***************************************************************************** tBoolean PRCMPeripheralStatusGet(unsigned long ulPeripheral) { unsigned long ReadyBit; // // Read the ready bit status // ReadyBit = HWREG(ARCM_BASE + PRCM_PeriphRegsList[ulPeripheral].ulRstReg); ReadyBit = ReadyBit & PRCM_ENABLE_STATUS; if (ReadyBit) { // // Module is ready // return(true); } else { // // Module is not ready // return(false); } } //***************************************************************************** // //! Configure I2S fracactional divider //! //! \param ulI2CClkFreq is the required input clock for McAPS module //! //! This function configures I2S fractional divider. By default this //! divider is set to output 24 Mhz clock to I2S module. //! //! The minimum frequency that can be obtained by configuring this divider is //! //! (240000KHz/1023.99) = 234.377 KHz //! //! \return None. // //***************************************************************************** void PRCMI2SClockFreqSet(unsigned long ulI2CClkFreq) { unsigned long long ullDiv; unsigned short usInteger; unsigned short usFrac; ullDiv = (((unsigned long long)240000000 * 65536)/ulI2CClkFreq); usInteger = (ullDiv/65536); usFrac = (ullDiv%65536); HWREG(ARCM_BASE + APPS_RCM_O_MCASP_FRAC_CLK_CONFIG0) = ((usInteger & 0x3FF) << 16 | usFrac); } //***************************************************************************** // //! Sets the LPDS exit PC and SP restore vlaues. //! //! \param ulStackPtr is the SP restore value. //! \param ulProgCntr is the PC restore value //! //! This function sets the LPDS exit PC and SP restore vlaues. Setting //! \e ulProgCntr to a non-zero value, forces bootloader to jump to that //! address with Stack Pointer initialized to \e ulStackPtr on LPDS exit, //! otherwise the application's vector table entries are used. //! //! \return None. // //***************************************************************************** void PRCMLPDSRestoreInfoSet(unsigned long ulStackPtr, unsigned long ulProgCntr) { // // Set The SP Value // HWREG(0x4402E18C) = ulStackPtr; // // Set The PC Value // HWREG(0x4402E190) = ulProgCntr; } //***************************************************************************** // //! Puts the system into Low Power Deel Sleep (LPDS) power mode. //! //! This function puts the system into Low Power Deel Sleep (LPDS) power mode. //! A call to this function never returns and the execution starts from Reset. //! \sa PRCMLPDSRestoreInfoSet(). //! //! \return None. //! //! \note The Test Power Domain is shutdown whenever the system //! enters LPDS (by default). In order to avoid this and allow for //! connecting back the debugger after waking up from LPDS, //! the macro KEEP_TESTPD_ALIVE has to be defined while building the library. //! This is recommended for development purposes only as it adds to //! the current consumption of the system. //! // //***************************************************************************** void PRCMLPDSEnter(void) { #ifndef DEBUG // // Disable TestPD // HWREG(0x4402E168) |= (1<<9); #endif // // Set bandgap duty cycle to 1 // HWREG(HIB1P2_BASE + HIB1P2_O_BGAP_DUTY_CYCLING_EXIT_CFG) = 0x1; // // Request LPDS // HWREG(ARCM_BASE + APPS_RCM_O_APPS_LPDS_REQ) = APPS_RCM_APPS_LPDS_REQ_APPS_LPDS_REQ; __asm(" nop\n" " nop\n" " nop\n" " nop\n"); } //***************************************************************************** // //! Enable the individual LPDS wakeup source(s). //! //! \param ulLpdsWakeupSrc is logical OR of wakeup sources. //! //! This function enable the individual LPDS wakeup source(s) and following //! three wakeup sources (\e ulLpdsWakeupSrc ) are supported by the device. //! -\b PRCM_LPDS_HOST_IRQ //! -\b PRCM_LPDS_GPIO //! -\b PRCM_LPDS_TIMER //! //! \return None. // //***************************************************************************** void PRCMLPDSWakeupSourceEnable(unsigned long ulLpdsWakeupSrc) { unsigned long ulRegVal; // // Read the current wakup sources // ulRegVal = HWREG(GPRCM_BASE+ GPRCM_O_APPS_LPDS_WAKEUP_CFG); // // Enable individual wakeup source // ulRegVal = ((ulRegVal | ulLpdsWakeupSrc) & 0x91); // // Set the configuration in the register // HWREG(GPRCM_BASE+ GPRCM_O_APPS_LPDS_WAKEUP_CFG) = ulRegVal; } //***************************************************************************** // //! Disable the individual LPDS wakeup source(s). //! //! \param ulLpdsWakeupSrc is logical OR of wakeup sources. //! //! This function enable the individual LPDS wakeup source(s) and following //! three wake up sources (\e ulLpdsWakeupSrc ) are supported by the device. //! -\b PRCM_LPDS_HOST_IRQ //! -\b PRCM_LPDS_GPIO //! -\b PRCM_LPDS_TIMER //! //! \return None. // //***************************************************************************** void PRCMLPDSWakeupSourceDisable(unsigned long ulLpdsWakeupSrc) { HWREG(GPRCM_BASE+ GPRCM_O_APPS_LPDS_WAKEUP_CFG) &= ~ulLpdsWakeupSrc; } //***************************************************************************** // //! Get LPDS wakeup cause //! //! This function gets LPDS wakeup caouse //! //! \return Returns values enumerated as described in //! PRCMLPDSWakeupSourceEnable(). // //***************************************************************************** unsigned long PRCMLPDSWakeupCauseGet(void) { return (HWREG(GPRCM_BASE+ GPRCM_O_APPS_LPDS_WAKEUP_SRC)); } //***************************************************************************** // //! Sets LPDS wakeup Timer //! //! \param ulTicks is number of 32.768 KHz clocks //! //! This function sets internal LPDS wakeup timer running at 32.768 KHz. The //! timer is only configured if the parameter \e ulTicks is in valid range i.e. //! from 21 to 2^32. //! //! \return Returns \b true on success, \b false otherwise. // //***************************************************************************** void PRCMLPDSIntervalSet(unsigned long ulTicks) { // // Check sleep is atleast for 21 cycles // If not set the sleep time to 21 cycles // if( ulTicks < 21) { ulTicks = 21; } HWREG(GPRCM_BASE + GPRCM_O_APPS_LPDS_WAKETIME_WAKE_CFG) = ulTicks; HWREG(GPRCM_BASE + GPRCM_O_APPS_LPDS_WAKETIME_OPP_CFG) = ulTicks-20; } //***************************************************************************** // //! Selects the GPIO for LPDS wakeup //! //! \param ulGPIOPin is one of the valid GPIO fro LPDS wakeup. //! \param ulType is the wakeup trigger type. //! //! This function setects the wakeup GPIO for LPDS wakeup and can be //! used to select one out of 7 pre-defined GPIO(s). //! //! The parameter \e ulLpdsGPIOSel should be one of the following:- //! -\b PRCM_LPDS_GPIO2 //! -\b PRCM_LPDS_GPIO4 //! -\b PRCM_LPDS_GPIO13 //! -\b PRCM_LPDS_GPIO17 //! -\b PRCM_LPDS_GPIO11 //! -\b PRCM_LPDS_GPIO24 //! -\b PRCM_LPDS_GPIO26 //! //! The parameter \e ulType sets the trigger type and can be one of the //! following: //! - \b PRCM_LPDS_LOW_LEVEL //! - \b PRCM_LPDS_HIGH_LEVEL //! - \b PRCM_LPDS_FALL_EDGE //! - \b PRCM_LPDS_RISE_EDGE //! //! \return None. // //***************************************************************************** void PRCMLPDSWakeUpGPIOSelect(unsigned long ulGPIOPin, unsigned long ulType) { // // Set the wakeup GPIO // MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_LPDS_GPIO_SEL, ulGPIOPin); // // Set the trigger type. // HWREG(GPRCM_BASE + GPRCM_O_APPS_GPIO_WAKE_CONF) = (ulType & 0x3); } //***************************************************************************** // //! Puts the system into Sleep. //! //! This function puts the system into sleep power mode. System exits the power //! state on any one of the available interrupt. On exit from sleep mode the //! function returns to the calling function with all the processor core //! registers retained. //! //! \return None. // //***************************************************************************** void PRCMSleepEnter(void) { // // Request Sleep // CPUwfi(); } //***************************************************************************** // //! Puts the system into Deep Sleep power mode. //! //! This function puts the system into Deep Sleep power mode. System exits the //! power state on any one of the available interrupt. On exit from deep //! sleep the function returns to the calling function with all the processor //! core registers retained. //! //! \return None. // //***************************************************************************** void PRCMDeepSleepEnter(void) { // // Set bandgap duty cycle to 1 // HWREG(HIB1P2_BASE + HIB1P2_O_BGAP_DUTY_CYCLING_EXIT_CFG) = 0x1; // // Enable DSLP in cortex // HWREG(0xE000ED10)|=1<<2; // // Request Deep Sleep // CPUwfi(); // // Disable DSLP in cortex before // returning to the caller // HWREG(0xE000ED10) &= ~(1<<2); } //***************************************************************************** // //! Enable SRAM column retention during Deep Sleep and/or LPDS Power mode(s) //! //! \param ulSramColSel is bit mask of valid SRAM columns. //! \param ulModeFlags is the bit mask of power modes. //! //! This functions enables the SRAM retention. The device supports configurable //! SRAM column retention in Low Power Deep Sleep (LPDS) and Deep Sleep power //! modes. Each column is of 64 KB size. //! //! The parameter \e ulSramColSel should be logical OR of the following:- //! -\b PRCM_SRAM_COL_1 //! -\b PRCM_SRAM_COL_2 //! -\b PRCM_SRAM_COL_3 //! -\b PRCM_SRAM_COL_4 //! //! The parameter \e ulModeFlags selects the power modes and sholud be logical //! OR of one or more of the following //! -\b PRCM_SRAM_DSLP_RET //! -\b PRCM_SRAM_LPDS_RET //! //! \return None. // //**************************************************************************** void PRCMSRAMRetentionEnable(unsigned long ulSramColSel, unsigned long ulModeFlags) { if(ulModeFlags & PRCM_SRAM_DSLP_RET) { // // Configure deep sleep SRAM retention register // HWREG(GPRCM_BASE+ GPRCM_O_APPS_SRAM_DSLP_CFG) = (ulSramColSel & 0xF); } if(ulModeFlags & PRCM_SRAM_LPDS_RET) { // // Configure LPDS SRAM retention register // HWREG(GPRCM_BASE+ GPRCM_O_APPS_SRAM_LPDS_CFG) = (ulSramColSel & 0xF); } } //***************************************************************************** // //! Disable SRAM column retention during Deep Sleep and/or LPDS Power mode(s). //! //! \param ulSramColSel is bit mask of valid SRAM columns. //! \param ulFlags is the bit mask of power modes. //! //! This functions disable the SRAM retention. The device supports configurable //! SRAM column retention in Low Power Deep Sleep (LPDS) and Deep Sleep power //! modes. Each column is of 64 KB size. //! //! The parameter \e ulSramColSel should be logical OR of the following:- //! -\b PRCM_SRAM_COL_1 //! -\b PRCM_SRAM_COL_2 //! -\b PRCM_SRAM_COL_3 //! -\b PRCM_SRAM_COL_4 //! //! The parameter \e ulFlags selects the power modes and sholud be logical OR //! of one or more of the following //! -\b PRCM_SRAM_DSLP_RET //! -\b PRCM_SRAM_LPDS_RET //! //! \return None. // //**************************************************************************** void PRCMSRAMRetentionDisable(unsigned long ulSramColSel, unsigned long ulFlags) { if(ulFlags & PRCM_SRAM_DSLP_RET) { // // Configure deep sleep SRAM retention register // HWREG(GPRCM_BASE+ GPRCM_O_APPS_SRAM_DSLP_CFG) &= ~(ulSramColSel & 0xF); } if(ulFlags & PRCM_SRAM_LPDS_RET) { // // Configure LPDS SRAM retention register // HWREG(GPRCM_BASE+ GPRCM_O_APPS_SRAM_LPDS_CFG) &= ~(ulSramColSel & 0xF); } } //***************************************************************************** // //! Enables individual HIB wakeup source(s). //! //! \param ulHIBWakupSrc is logical OR of valid HIB wakeup sources. //! //! This function enables individual HIB wakeup source(s). The paramter //! \e ulHIBWakupSrc is the bit mask of HIB wakeup sources and should be //! logical OR of one or more of the follwoing :- //! -\b PRCM_HIB_SLOW_CLK_CTR //! -\b PRCM_HIB_GPIO2 //! -\b PRCM_HIB_GPIO4 //! -\b PRCM_HIB_GPIO13 //! -\b PRCM_HIB_GPIO17 //! -\b PRCM_HIB_GPIO11 //! -\b PRCM_HIB_GPIO24 //! -\b PRCM_HIB_GPIO26 //! //! \return None. // //***************************************************************************** void PRCMHibernateWakeupSourceEnable(unsigned long ulHIBWakupSrc) { unsigned long ulRegValue; // // Read the RTC register // ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_EN); // // Enable the RTC as wakeup source if specified // ulRegValue |= (ulHIBWakupSrc & 0x1); // // Enable HIB wakeup sources // MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_EN,ulRegValue); // // REad the GPIO wakeup configuration register // ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_EN); // // Enable the specified GPIOs a wakeup sources // ulRegValue |= ((ulHIBWakupSrc>>16)&0xFF); // // Write the new register configuration // MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_EN,ulRegValue); } //***************************************************************************** // //! Disable individual HIB wakeup source(s). //! //! \param ulHIBWakupSrc is logical OR of valid HIB wakeup sources. //! //! This function disable individual HIB wakeup source(s). The paramter //! \e ulHIBWakupSrc is same as bit fileds defined in //! PRCMEnableHibernateWakeupSource() //! //! \return None. // //***************************************************************************** void PRCMHibernateWakeupSourceDisable(unsigned long ulHIBWakupSrc) { unsigned long ulRegValue; // // Read the RTC register // ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_EN); // // Disable the RTC as wakeup source if specified // ulRegValue &= ~(ulHIBWakupSrc & 0x1); // // Disable HIB wakeup sources // MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_EN,ulRegValue); // // Read the GPIO wakeup configuration register // ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_EN); // // Enable the specified GPIOs a wakeup sources // ulRegValue &= ~((ulHIBWakupSrc>>16)&0xFF); // // Write the new register configuration // MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_GPIO_WAKE_EN,ulRegValue); } //***************************************************************************** // //! Get hibernate wakeup cause //! //! This function gets the hibernate wakeup cause. //! //! \return Returns \b PRCM_HIB_WAKEUP_CAUSE_SLOW_CLOCK or //! \b PRCM_HIB_WAKEUP_CAUSE_GPIO // //***************************************************************************** unsigned long PRCMHibernateWakeupCauseGet(void) { return ((MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_WAKE_STATUS)>>1)&0xF); } //***************************************************************************** // //! Sets Hibernate wakeup Timer //! //! \param ullTicks is number of 32.768 KHz clocks //! //! This function sets internal hibernate wakeup timer running at 32.768 KHz. //! //! \return Returns \b true on success, \b false otherwise. // //***************************************************************************** void PRCMHibernateIntervalSet(unsigned long long ullTicks) { unsigned long long ullRTCVal; // // Latch the RTC vlaue // MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_TIMER_READ ,0x1); // // Read latched values as 2 32-bit vlaues // ullRTCVal = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_TIMER_MSW); ullRTCVal = ullRTCVal << 32; ullRTCVal |= MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_TIMER_LSW); // // Add the interval // ullRTCVal = ullRTCVal + ullTicks; // // Set RTC match value // MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_LSW_CONF, (unsigned long)(ullRTCVal)); MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_RTC_WAKE_MSW_CONF, (unsigned long)(ullRTCVal>>32)); } //***************************************************************************** // //! Selects the GPIO(s) for hibernate wakeup //! //! \param ulGPIOBitMap is the bit-map of valid hibernate wakeup GPIO. //! \param ulType is the wakeup trigger type. //! //! This function setects the wakeup GPIO for hibernate and can be //! used to select any combination of 7 pre-defined GPIO(s). //! //! This function enables individual HIB wakeup source(s). The paramter //! \e ulGPIOBitMap should be one of the follwoing :- //! -\b PRCM_HIB_GPIO2 //! -\b PRCM_HIB_GPIO4 //! -\b PRCM_HIB_GPIO13 //! -\b PRCM_HIB_GPIO17 //! -\b PRCM_HIB_GPIO11 //! -\b PRCM_HIB_GPIO24 //! -\b PRCM_HIB_GPIO26 //! //! The parameter \e ulType sets the trigger type and can be one of the //! following: //! - \b PRCM_HIB_LOW_LEVEL //! - \b PRCM_HIB_HIGH_LEVEL //! - \b PRCM_HIB_FALL_EDGE //! - \b PRCM_HIB_RISE_EDGE //! //! \return None. // //***************************************************************************** void PRCMHibernateWakeUpGPIOSelect(unsigned long ulGPIOBitMap, unsigned long ulType) { unsigned char ucLoop; unsigned long ulRegValue; // // Shift the bits to extract the GPIO selection // ulGPIOBitMap >>= 16; // // Set the configuration for each GPIO // for(ucLoop=0; ucLoop < 7; ucLoop++) { if(ulGPIOBitMap & (1<>32)); } //***************************************************************************** // //! Gets slow clock counter match value. //! //! This function gets the match value for slow clock counter. This is use //! to interrupt the processor when RTC counts to the specified value. //! //! \return None. // //***************************************************************************** unsigned long long PRCMSlowClkCtrMatchGet(void) { unsigned long long ullValue; // // Get RTC match value // ullValue = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_MSW_CONF); ullValue = ullValue<<32; ullValue |= MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_LSW_CONF); // // Return the value // return ullValue; } //***************************************************************************** // //! Write to On-Chip Retention (OCR) register. //! //! This function writes to On-Chip retention register. The device supports two //! 4-byte OCR register which are retained across all power mode. //! //! The parameter \e ucIndex is an index of the OCR and can be \b 0 or \b 1. //! //! \return None. // //***************************************************************************** void PRCMOCRRegisterWrite(unsigned char ucIndex, unsigned long ulRegValue) { MAP_PRCMHIBRegWrite(HIB3P3_BASE+HIB3P3_O_MEM_HIB_REG2+(ucIndex << 2),ulRegValue); } //***************************************************************************** // //! Read from On-Chip Retention (OCR) register. //! //! This function reads from On-Chip retention register. The device supports two //! 4-byte OCR register which are retained across all power mode. //! //! The parameter \e ucIndex is an index of the OCR and can be \b 0 or \b 1. //! //! \return None. // //***************************************************************************** unsigned long PRCMOCRRegisterRead(unsigned char ucIndex) { // // Return the read value. // return MAP_PRCMHIBRegRead(HIB3P3_BASE+HIB3P3_O_MEM_HIB_REG2 + (ucIndex << 2)); } //***************************************************************************** // //! Registers an interrupt handler for the PRCM. //! //! \param pfnHandler is a pointer to the function to be called when the //! interrupt is activated. //! //! This function does the actual registering of the interrupt handler. This //! function enables the global interrupt in the interrupt controller; //! //! \return None. // //***************************************************************************** void PRCMIntRegister(void (*pfnHandler)(void)) { // // Register the interrupt handler. // IntRegister(INT_PRCM, pfnHandler); // // Enable the PRCM interrupt. // IntEnable(INT_PRCM); } //***************************************************************************** // //! Unregisters an interrupt handler for the PRCM. //! //! This function does the actual unregistering of the interrupt handler. It //! clears the handler to be called when a PRCM interrupt occurs. This //! function also masks off the interrupt in the interrupt controller so that //! the interrupt handler no longer is called. //! //! \return None. // //***************************************************************************** void PRCMIntUnregister(void) { // // Enable the UART interrupt. // IntDisable(INT_PRCM); // // Register the interrupt handler. // IntUnregister(INT_PRCM); } //***************************************************************************** // //! Enables individual PRCM interrupt sources. //! //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated ARCM interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter is the logical OR of any of the following: //! -\b PRCM_INT_SLOW_CLK_CTR //! // //***************************************************************************** void PRCMIntEnable(unsigned long ulIntFlags) { unsigned long ulRegValue; if(ulIntFlags & PRCM_INT_SLOW_CLK_CTR ) { // // Enable PRCM interrupt // HWREG(ARCM_BASE + APPS_RCM_O_APPS_RCM_INTERRUPT_ENABLE) |= 0x4; // // Enable RTC interrupt // ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE); ulRegValue |= 0x1; MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE, ulRegValue); } } //***************************************************************************** // //! Disables individual PRCM interrupt sources. //! //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled. //! //! This function disables the indicated ARCM interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to PRCMEnableInterrupt(). //! //! \return None. // //***************************************************************************** void PRCMIntDisable(unsigned long ulIntFlags) { unsigned long ulRegValue; if(ulIntFlags & PRCM_INT_SLOW_CLK_CTR ) { // // Disable PRCM interrupt // HWREG(ARCM_BASE + APPS_RCM_O_APPS_RCM_INTERRUPT_ENABLE) &= ~0x4; // // Disable RTC interrupt // ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE); ulRegValue &= ~0x1; MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE, ulRegValue); } } //***************************************************************************** // //! Gets the current interrupt status. //! //! This function returns the PRCM interrupt status of interrupts that are //! allowed to reflect to the processor. The interrupts are cleared on read. //! //! \return Returns the current interrupt status. // //***************************************************************************** unsigned long PRCMIntStatus(void) { return HWREG(ARCM_BASE + APPS_RCM_O_APPS_RCM_INTERRUPT_STATUS); } //***************************************************************************** // //! Mark the function of RTC as being used //! //! This function marks in HW that feature to maintain calendar time in device //! is being used. //! //! Specifically, this feature reserves user's HIB Register-1 accessed through //! PRCMOCRRegisterWrite(1) for internal work / purpose, therefore, the stated //! register is not available to user. Also, users must not excercise the Slow //! Clock Counter API(s), if RTC has been set for use. //! //! \return None. // //***************************************************************************** void PRCMRTCInUseSet(void) { RTC_USE_SET(); return; } //***************************************************************************** // //! Clear the function of RTC as being used //! //! \return None. // //***************************************************************************** void PRCMRTCInUseClear(void) { RTC_USE_CLR(); return; } //***************************************************************************** // //! Ascertain whether function of RTC is being used //! //! This function indicates whether function of RTC is being used on the device //! or not. //! //! This routine should be utilized by the application software, when returning //! from low-power, to confirm that RTC has been put to use and may not need to //! set the value of the RTC. //! //! The RTC feature, if set or marked, can be only reset either through reboot //! or power cycle. //! //! \return None. // //***************************************************************************** tBoolean PRCMRTCInUseGet(void) { return IS_RTC_USED()? true : false; } //***************************************************************************** // //! Set the calendar time in the device. //! //! \param ulSecs refers to the seconds part of the calendar time //! \param usMsec refers to the fractional (ms) part of the second //! //! This function sets the specified calendar time in the device. The calendar //! time is outlined in terms of seconds and milliseconds. However, the device //! makes no assumption about the origin or reference of the calendar time. //! //! The device uses the indicated calendar value to update and maintain the //! wall-clock time across active and low power states. //! //! The function PRCMRTCInUseSet() must be invoked prior to use of this feature. //! //! \return None. // //***************************************************************************** void PRCMRTCSet(unsigned long ulSecs, unsigned short usMsec) { unsigned long long ullMsec = 0; if(IS_RTC_USED()) { ullMsec = RTC_U64MSEC_MK(ulSecs, usMsec) - SCC_U64MSEC_GET(); RTC_U32SECS_REG_WR(RTC_SECS_IN_U64MSEC(ullMsec)); RTC_U32MSEC_REG_WR(RTC_MSEC_IN_U64MSEC(ullMsec)); } return; } //***************************************************************************** // //! Get the instantaneous calendar time from the device. //! //! \param ulSecs refers to the seconds part of the calendar time //! \param usMsec refers to the fractional (ms) part of the second //! //! This function fetches the instantaneous value of the ticking calendar time //! from the device. The calendar time is outlined in terms of seconds and //! milliseconds. //! //! The device provides the calendar value that has been maintained across //! active and low power states. //! //! The function PRCMRTCSet() must have been invoked once to set a reference. //! //! \return None. // //***************************************************************************** void PRCMRTCGet(unsigned long *ulSecs, unsigned short *usMsec) { unsigned long long ullMsec = 0; if(IS_RTC_USED()) { ullMsec = RTC_U64MSEC_MK(RTC_U32SECS_REG_RD(), RTC_U32MSEC_REG_RD()); ullMsec += SCC_U64MSEC_GET(); } *ulSecs = RTC_SECS_IN_U64MSEC(ullMsec); *usMsec = RTC_MSEC_IN_U64MSEC(ullMsec); return; } //***************************************************************************** // //! Set a calendar time alarm. //! //! \param ulSecs refers to the seconds part of the calendar time //! \param usMsec refers to the fractional (ms) part of the second //! //! This function sets an wall-clock alarm in the device to be reported for a //! futuristic calendar time. The calendar time is outlined in terms of seconds //! and milliseconds. //! //! The device provides uses the calendar value that has been maintained across //! active and low power states to report attainment of alarm time. //! //! The function PRCMRTCSet() must have been invoked once to set a reference. //! //! \return None. // //***************************************************************************** void PRCMRTCMatchSet(unsigned long ulSecs, unsigned short usMsec) { unsigned long long ullMsec = 0; if(IS_RTC_USED()) { ullMsec = RTC_U64MSEC_MK(ulSecs, usMsec); ullMsec -= RTC_U64MSEC_MK(RTC_U32SECS_REG_RD(), RTC_U32MSEC_REG_RD()); SCC_U64MSEC_MATCH_SET(SELECT_SCC_U42BITS(ullMsec)); } return; } //***************************************************************************** // //! Get a previously set calendar time alarm. //! //! \param ulSecs refers to the seconds part of the calendar time //! \param usMsec refers to the fractional (ms) part of the second //! //! This function fetches from the device a wall-clock alarm that would have //! been previously set in the device. The calendar time is outlined in terms //! of seconds and milliseconds. //! //! If no alarm was set in the past, then this function would fetch a random //! information. //! //! The function PRCMRTCMatchSet() must have been invoked once to set an alarm. //! //! \return None. // //***************************************************************************** void PRCMRTCMatchGet(unsigned long *ulSecs, unsigned short *usMsec) { unsigned long long ullMsec = 0; if(IS_RTC_USED()) { ullMsec = SCC_U64MSEC_MATCH_GET(); ullMsec += RTC_U64MSEC_MK(RTC_U32SECS_REG_RD(), RTC_U32MSEC_REG_RD()); } *ulSecs = RTC_SECS_IN_U64MSEC(ullMsec); *usMsec = RTC_MSEC_IN_U64MSEC(ullMsec); return; } //***************************************************************************** // //! MCU Initialization Routine //! //! This function sets mandatory configurations for the MCU //! //! \return None // //***************************************************************************** void PRCMCC3200MCUInit(void) { unsigned long ulRegValue; // // DIG DCDC LPDS ECO Enable // HWREG(0x4402F064) |= 0x800000; // // Enable hibernate ECO for PG 1.32 devices only. With this ECO enabled, // any hibernate wakeup source will be kept masked until the device enters // hibernate completely (analog + digital) // ulRegValue = MAP_PRCMHIBRegRead(HIB3P3_BASE + HIB3P3_O_MEM_HIB_REG0); MAP_PRCMHIBRegWrite(HIB3P3_BASE + HIB3P3_O_MEM_HIB_REG0, ulRegValue | (1<<4)); // // Handling the clock switching (for 1.32 only) // HWREG(0x4402E16C) |= 0x3C; // // Enable uDMA // MAP_PRCMPeripheralClkEnable(PRCM_UDMA,PRCM_RUN_MODE_CLK); // // Reset uDMA // MAP_PRCMPeripheralReset(PRCM_UDMA); // // Disable uDMA // MAP_PRCMPeripheralClkDisable(PRCM_UDMA,PRCM_RUN_MODE_CLK); // // Enable RTC // if(MAP_PRCMSysResetCauseGet()== PRCM_POWER_ON) { MAP_PRCMHIBRegWrite(0x4402F804,0x1); } // // SWD mode // if (((HWREG(0x4402F0C8) & 0xFF) == 0x2)) { HWREG(0x4402E110) = ((HWREG(0x4402E110) & ~0xC0F) | 0x2); HWREG(0x4402E114) = ((HWREG(0x4402E110) & ~0xC0F) | 0x2); } // // Override JTAG mux // HWREG(0x4402E184) |= 0x2; // // Change UART pins(55,57) mode to PIN_MODE_0 if they are in PIN_MODE_1 // if ((HWREG(0x4402E0A4) & 0xF) == 0x1) { HWREG(0x4402E0A4) = ((HWREG(0x4402E0A4) & ~0xF)); } if ((HWREG(0x4402E0A8) & 0xF) == 0x1) { HWREG(0x4402E0A8) = ((HWREG(0x4402E0A8) & ~0xF)); } // // DIG DCDC VOUT trim settings based on PROCESS INDICATOR // if (((HWREG(0x4402DC78) >> 22) & 0xF) == 0xE) { HWREG(0x4402F0B0) = ((HWREG(0x4402F0B0) & ~(0x00FC0000))|(0x32 << 18)); } else { HWREG(0x4402F0B0) = ((HWREG(0x4402F0B0) & ~(0x00FC0000))|(0x29 << 18)); } // // Enable SOFT RESTART in case of DIG DCDC collapse // HWREG(0x4402FC74) &= ~(0x10000000); // // Disable the sleep for ANA DCDC // HWREG(0x4402F0A8) |= 0x00000004 ; } //***************************************************************************** // //! Reads 32-bit value from register at specified address //! //! \param ulRegAddr is the address of register to be read. //! //! This function reads 32-bit value from the register as specified by //! \e ulRegAddr. //! //! \return Return the value of the register. // //***************************************************************************** unsigned long PRCMHIBRegRead(unsigned long ulRegAddr) { unsigned long ulValue; // // Read the Reg value // ulValue = HWREG(ulRegAddr); // // Wait for 200 uSec // UtilsDelay((80*200)/3); // // Return the value // return ulValue; } //***************************************************************************** // //! Writes 32-bit value to register at specified address //! //! \param ulRegAddr is the address of register to be read. //! \param ulValue is the 32-bit value to be written. //! //! This function writes 32-bit value passed as \e ulValue to the register as //! specified by \e ulRegAddr //! //! \return None // //***************************************************************************** void PRCMHIBRegWrite(unsigned long ulRegAddr, unsigned long ulValue) { // // Read the Reg value // HWREG(ulRegAddr) = ulValue; // // Wait for 200 uSec // UtilsDelay((80*200)/3); } //***************************************************************************** // //! \param ulDivider is clock frequency divider value //! \param ulWidth is the width of the high pulse //! //! This function sets the input frequency for camera module. //! //! The frequency is calculated as follows: //! //! f_out = 240MHz/ulDivider; //! //! The parameter \e ulWidth sets the width of the high pulse. //! //! For e.g.: //! //! ulDivider = 4; //! ulWidth = 2; //! //! f_out = 30 MHz and 50% duty cycle //! //! And, //! //! ulDivider = 4; //! ulWidth = 1; //! //! f_out = 30 MHz and 25% duty cycle //! //! \return 0 on success, 1 on error // //***************************************************************************** unsigned long PRCMCameraFreqSet(unsigned char ulDivider, unsigned char ulWidth) { if(ulDivider > ulWidth && ulWidth != 0 ) { // // Set the hifh pulse width // HWREG(ARCM_BASE + APPS_RCM_O_CAMERA_CLK_GEN) = (((ulWidth & 0x07) -1) << 8); // // Set the low pulse width // HWREG(ARCM_BASE + APPS_RCM_O_CAMERA_CLK_GEN) = ((ulDivider - ulWidth - 1) & 0x07); // // Return success // return 0; } // // Success; // return 1; } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/prcm.h000066400000000000000000000315631357706137100177510ustar00rootroot00000000000000//***************************************************************************** // // prcm.h // // Prototypes for the PRCM control driver. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __PRCM_H__ #define __PRCM_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // Peripheral clock and reset control registers // //***************************************************************************** typedef struct _PRCM_PeripheralRegs_ { unsigned char ulClkReg; unsigned char ulRstReg; }PRCM_PeriphRegs_t; //***************************************************************************** // Values that can be passed to PRCMPeripheralEnable() and // PRCMPeripheralDisable() //***************************************************************************** #define PRCM_RUN_MODE_CLK 0x00000001 #define PRCM_SLP_MODE_CLK 0x00000100 #define PRCM_DSLP_MODE_CLK 0x00010000 //***************************************************************************** // Values that can be passed to PRCMSRAMRetentionEnable() and // PRCMSRAMRetentionDisable() as ulSramColSel. //***************************************************************************** #define PRCM_SRAM_COL_1 0x00000001 #define PRCM_SRAM_COL_2 0x00000002 #define PRCM_SRAM_COL_3 0x00000004 #define PRCM_SRAM_COL_4 0x00000008 //***************************************************************************** // Values that can be passed to PRCMSRAMRetentionEnable() and // PRCMSRAMRetentionDisable() as ulModeFlags. //***************************************************************************** #define PRCM_SRAM_DSLP_RET 0x00000001 #define PRCM_SRAM_LPDS_RET 0x00000002 //***************************************************************************** // Values that can be passed to PRCMLPDSWakeupSourceEnable(), // PRCMLPDSWakeupCauseGet() and PRCMLPDSWakeupSourceDisable(). //***************************************************************************** #define PRCM_LPDS_HOST_IRQ 0x00000080 #define PRCM_LPDS_GPIO 0x00000010 #define PRCM_LPDS_TIMER 0x00000001 //***************************************************************************** // Values that can be passed to PRCMLPDSWakeUpGPIOSelect() as Type //***************************************************************************** #define PRCM_LPDS_LOW_LEVEL 0x00000002 #define PRCM_LPDS_HIGH_LEVEL 0x00000000 #define PRCM_LPDS_FALL_EDGE 0x00000001 #define PRCM_LPDS_RISE_EDGE 0x00000003 //***************************************************************************** // Values that can be passed to PRCMLPDSWakeUpGPIOSelect() //***************************************************************************** #define PRCM_LPDS_GPIO2 0x00000000 #define PRCM_LPDS_GPIO4 0x00000001 #define PRCM_LPDS_GPIO13 0x00000002 #define PRCM_LPDS_GPIO17 0x00000003 #define PRCM_LPDS_GPIO11 0x00000004 #define PRCM_LPDS_GPIO24 0x00000005 #define PRCM_LPDS_GPIO26 0x00000006 //***************************************************************************** // Values that can be passed to PRCMHibernateWakeupSourceEnable(), // PRCMHibernateWakeupSourceDisable(). //***************************************************************************** #define PRCM_HIB_SLOW_CLK_CTR 0x00000001 //***************************************************************************** // Values that can be passed to PRCMHibernateWakeUpGPIOSelect() as ulType //***************************************************************************** #define PRCM_HIB_LOW_LEVEL 0x00000000 #define PRCM_HIB_HIGH_LEVEL 0x00000001 #define PRCM_HIB_FALL_EDGE 0x00000002 #define PRCM_HIB_RISE_EDGE 0x00000003 //***************************************************************************** // Values that can be passed to PRCMHibernateWakeupSourceEnable(), // PRCMHibernateWakeupSourceDisable(), PRCMHibernateWakeUpGPIOSelect() //***************************************************************************** #define PRCM_HIB_GPIO2 0x00010000 #define PRCM_HIB_GPIO4 0x00020000 #define PRCM_HIB_GPIO13 0x00040000 #define PRCM_HIB_GPIO17 0x00080000 #define PRCM_HIB_GPIO11 0x00100000 #define PRCM_HIB_GPIO24 0x00200000 #define PRCM_HIB_GPIO26 0x00400000 //***************************************************************************** // Values that will be returned from PRCMSysResetCauseGet(). //***************************************************************************** #define PRCM_POWER_ON 0x00000000 #define PRCM_LPDS_EXIT 0x00000001 #define PRCM_CORE_RESET 0x00000003 #define PRCM_MCU_RESET 0x00000004 #define PRCM_WDT_RESET 0x00000005 #define PRCM_SOC_RESET 0x00000006 #define PRCM_HIB_EXIT 0x00000007 //***************************************************************************** // Values that can be passed to PRCMHibernateWakeupCauseGet(). //***************************************************************************** #define PRCM_HIB_WAKEUP_CAUSE_SLOW_CLOCK 0x00000002 #define PRCM_HIB_WAKEUP_CAUSE_GPIO 0x00000004 //***************************************************************************** // Values that can be passed to PRCMIntEnable //***************************************************************************** #define PRCM_INT_SLOW_CLK_CTR 0x00004000 //***************************************************************************** // Values that can be passed to PRCMPeripheralClkEnable(), // PRCMPeripheralClkDisable(), PRCMPeripheralReset() //***************************************************************************** #define PRCM_CAMERA 0x00000000 #define PRCM_I2S 0x00000001 #define PRCM_SDHOST 0x00000002 #define PRCM_GSPI 0x00000003 #define PRCM_LSPI 0x00000004 #define PRCM_UDMA 0x00000005 #define PRCM_GPIOA0 0x00000006 #define PRCM_GPIOA1 0x00000007 #define PRCM_GPIOA2 0x00000008 #define PRCM_GPIOA3 0x00000009 #define PRCM_GPIOA4 0x0000000A #define PRCM_WDT 0x0000000B #define PRCM_UARTA0 0x0000000C #define PRCM_UARTA1 0x0000000D #define PRCM_TIMERA0 0x0000000E #define PRCM_TIMERA1 0x0000000F #define PRCM_TIMERA2 0x00000010 #define PRCM_TIMERA3 0x00000011 #define PRCM_DTHE 0x00000012 #define PRCM_SSPI 0x00000013 #define PRCM_I2CA0 0x00000014 // Note : PRCM_ADC is a dummy define for pinmux utility code generation // PRCM_ADC should never be used in any user code. #define PRCM_ADC 0x000000FF //***************************************************************************** // User bits in the PRCM persistent registers //***************************************************************************** #define PRCM_SAFE_BOOT_BIT 30 #define PRCM_WDT_RESET_BIT 29 #define PRCM_FIRST_BOOT_BIT 28 //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void PRCMSetSpecialBit(unsigned char bit); extern void PRCMClearSpecialBit(unsigned char bit); extern tBoolean PRCMGetSpecialBit(unsigned char bit); extern void PRCMSOCReset(void); extern void PRCMMCUReset(tBoolean bIncludeSubsystem); extern unsigned long PRCMSysResetCauseGet(void); extern void PRCMPeripheralClkEnable(unsigned long ulPeripheral, unsigned long ulClkFlags); extern void PRCMPeripheralClkDisable(unsigned long ulPeripheral, unsigned long ulClkFlags); extern void PRCMPeripheralReset(unsigned long ulPeripheral); extern tBoolean PRCMPeripheralStatusGet(unsigned long ulPeripheral); extern void PRCMI2SClockFreqSet(unsigned long ulI2CClkFreq); extern unsigned long PRCMPeripheralClockGet(unsigned long ulPeripheral); extern void PRCMSleepEnter(void); extern void PRCMDeepSleepEnter(void); extern void PRCMSRAMRetentionEnable(unsigned long ulSramColSel, unsigned long ulFlags); extern void PRCMSRAMRetentionDisable(unsigned long ulSramColSel, unsigned long ulFlags); extern void PRCMLPDSRestoreInfoSet(unsigned long ulRestoreSP, unsigned long ulRestorePC); extern void PRCMLPDSEnter(void); extern void PRCMLPDSIntervalSet(unsigned long ulTicks); extern void PRCMLPDSWakeupSourceEnable(unsigned long ulLpdsWakeupSrc); extern unsigned long PRCMLPDSWakeupCauseGet(void); extern void PRCMLPDSWakeUpGPIOSelect(unsigned long ulGPIOPin, unsigned long ulType); extern void PRCMLPDSWakeupSourceDisable(unsigned long ulLpdsWakeupSrc); extern void PRCMHibernateEnter(void); extern void PRCMHibernateWakeupSourceEnable(unsigned long ulHIBWakupSrc); extern unsigned long PRCMHibernateWakeupCauseGet(void); extern void PRCMHibernateWakeUpGPIOSelect(unsigned long ulMultiGPIOBitMap, unsigned long ulType); extern void PRCMHibernateWakeupSourceDisable(unsigned long ulHIBWakupSrc); extern void PRCMHibernateIntervalSet(unsigned long long ullTicks); extern unsigned long long PRCMSlowClkCtrGet(void); extern unsigned long long PRCMSlowClkCtrFastGet(void); extern void PRCMSlowClkCtrMatchSet(unsigned long long ullTicks); extern unsigned long long PRCMSlowClkCtrMatchGet(void); extern void PRCMOCRRegisterWrite(unsigned char ucIndex, unsigned long ulRegValue); extern unsigned long PRCMOCRRegisterRead(unsigned char ucIndex); extern void PRCMIntRegister(void (*pfnHandler)(void)); extern void PRCMIntUnregister(void); extern void PRCMIntEnable(unsigned long ulIntFlags); extern void PRCMIntDisable(unsigned long ulIntFlags); extern unsigned long PRCMIntStatus(void); extern void PRCMRTCInUseSet(void); extern void PRCMRTCInUseClear(void); extern tBoolean PRCMRTCInUseGet(void); extern void PRCMRTCSet(unsigned long ulSecs, unsigned short usMsec); extern void PRCMRTCGet(unsigned long *ulSecs, unsigned short *usMsec); extern void PRCMRTCMatchSet(unsigned long ulSecs, unsigned short usMsec); extern void PRCMRTCMatchGet(unsigned long *ulSecs, unsigned short *usMsec); extern void PRCMCC3200MCUInit(void); extern unsigned long PRCMHIBRegRead(unsigned long ulRegAddr); extern void PRCMHIBRegWrite(unsigned long ulRegAddr, unsigned long ulValue); extern unsigned long PRCMCameraFreqSet(unsigned char ulDivider, unsigned char ulWidth); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __PRCM_H__ micropython-1.12/ports/cc3200/hal/rom.h000066400000000000000000003302031357706137100175760ustar00rootroot00000000000000//***************************************************************************** // // rom.h // // Macros to facilitate calling functions in the ROM. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // // THIS IS AN AUTO-GENERATED FILE. DO NOT EDIT BY HAND. // //***************************************************************************** #ifndef __ROM_H__ #define __ROM_H__ //***************************************************************************** // // Pointers to the main API tables. // //***************************************************************************** #define ROM_APITABLE ((unsigned long *)0x0000040C) #define ROM_VERSION (ROM_APITABLE[0]) #define ROM_UARTTABLE ((unsigned long *)(ROM_APITABLE[1])) #define ROM_TIMERTABLE ((unsigned long *)(ROM_APITABLE[2])) #define ROM_WATCHDOGTABLE ((unsigned long *)(ROM_APITABLE[3])) #define ROM_INTERRUPTTABLE ((unsigned long *)(ROM_APITABLE[4])) #define ROM_UDMATABLE ((unsigned long *)(ROM_APITABLE[5])) #define ROM_PRCMTABLE ((unsigned long *)(ROM_APITABLE[6])) #define ROM_I2CTABLE ((unsigned long *)(ROM_APITABLE[7])) #define ROM_SPITABLE ((unsigned long *)(ROM_APITABLE[8])) #define ROM_CAMERATABLE ((unsigned long *)(ROM_APITABLE[9])) #define ROM_FLASHTABLE ((unsigned long *)(ROM_APITABLE[10])) #define ROM_PINTABLE ((unsigned long *)(ROM_APITABLE[11])) #define ROM_SYSTICKTABLE ((unsigned long *)(ROM_APITABLE[12])) #define ROM_UTILSTABLE ((unsigned long *)(ROM_APITABLE[13])) #define ROM_I2STABLE ((unsigned long *)(ROM_APITABLE[14])) #define ROM_HWSPINLOCKTABLE ((unsigned long *)(ROM_APITABLE[15])) #define ROM_GPIOTABLE ((unsigned long *)(ROM_APITABLE[16])) #define ROM_AESTABLE ((unsigned long *)(ROM_APITABLE[17])) #define ROM_DESTABLE ((unsigned long *)(ROM_APITABLE[18])) #define ROM_SHAMD5TABLE ((unsigned long *)(ROM_APITABLE[19])) #define ROM_CRCTABLE ((unsigned long *)(ROM_APITABLE[20])) #define ROM_SDHOSTTABLE ((unsigned long *)(ROM_APITABLE[21])) #define ROM_ADCTABLE ((unsigned long *)(ROM_APITABLE[22])) //***************************************************************************** // // Macros for calling ROM functions in the Interrupt API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_IntEnable \ ((void (*)(unsigned long ulInterrupt))ROM_INTERRUPTTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntMasterEnable \ ((tBoolean (*)(void))ROM_INTERRUPTTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntMasterDisable \ ((tBoolean (*)(void))ROM_INTERRUPTTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntDisable \ ((void (*)(unsigned long ulInterrupt))ROM_INTERRUPTTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntPriorityGroupingSet \ ((void (*)(unsigned long ulBits))ROM_INTERRUPTTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntPriorityGroupingGet \ ((unsigned long (*)(void))ROM_INTERRUPTTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntPrioritySet \ ((void (*)(unsigned long ulInterrupt, \ unsigned char ucPriority))ROM_INTERRUPTTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntPriorityGet \ ((long (*)(unsigned long ulInterrupt))ROM_INTERRUPTTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntPendSet \ ((void (*)(unsigned long ulInterrupt))ROM_INTERRUPTTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntPendClear \ ((void (*)(unsigned long ulInterrupt))ROM_INTERRUPTTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntPriorityMaskSet \ ((void (*)(unsigned long ulPriorityMask))ROM_INTERRUPTTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntPriorityMaskGet \ ((unsigned long (*)(void))ROM_INTERRUPTTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntRegister \ ((void (*)(unsigned long ulInterrupt, \ void (*pfnHandler)(void)))ROM_INTERRUPTTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntUnregister \ ((void (*)(unsigned long ulInterrupt))ROM_INTERRUPTTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_IntVTableBaseSet \ ((void (*)(unsigned long ulVtableBase))ROM_INTERRUPTTABLE[14]) #endif //***************************************************************************** // // Macros for calling ROM functions in the Timer API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_TimerEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer))ROM_TIMERTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer))ROM_TIMERTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerConfigure \ ((void (*)(unsigned long ulBase, \ unsigned long ulConfig))ROM_TIMERTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerControlLevel \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer, \ tBoolean bInvert))ROM_TIMERTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerControlEvent \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer, \ unsigned long ulEvent))ROM_TIMERTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerControlStall \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer, \ tBoolean bStall))ROM_TIMERTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerPrescaleSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer, \ unsigned long ulValue))ROM_TIMERTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerPrescaleGet \ ((unsigned long (*)(unsigned long ulBase, \ unsigned long ulTimer))ROM_TIMERTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerPrescaleMatchSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer, \ unsigned long ulValue))ROM_TIMERTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerPrescaleMatchGet \ ((unsigned long (*)(unsigned long ulBase, \ unsigned long ulTimer))ROM_TIMERTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerLoadSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer, \ unsigned long ulValue))ROM_TIMERTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerLoadGet \ ((unsigned long (*)(unsigned long ulBase, \ unsigned long ulTimer))ROM_TIMERTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerValueGet \ ((unsigned long (*)(unsigned long ulBase, \ unsigned long ulTimer))ROM_TIMERTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerMatchSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer, \ unsigned long ulValue))ROM_TIMERTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerMatchGet \ ((unsigned long (*)(unsigned long ulBase, \ unsigned long ulTimer))ROM_TIMERTABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerIntRegister \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer, \ void (*pfnHandler)(void)))ROM_TIMERTABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerIntUnregister \ ((void (*)(unsigned long ulBase, \ unsigned long ulTimer))ROM_TIMERTABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerIntEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_TIMERTABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerIntDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_TIMERTABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerIntStatus \ ((unsigned long (*)(unsigned long ulBase, \ tBoolean bMasked))ROM_TIMERTABLE[19]) #endif #if defined(TARGET_IS_CC3200) #define ROM_TimerIntClear \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_TIMERTABLE[20]) #endif //***************************************************************************** // // Macros for calling ROM functions in the UART API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_UARTParityModeSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulParity))ROM_UARTTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTParityModeGet \ ((unsigned long (*)(unsigned long ulBase))ROM_UARTTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTFIFOLevelSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulTxLevel, \ unsigned long ulRxLevel))ROM_UARTTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTFIFOLevelGet \ ((void (*)(unsigned long ulBase, \ unsigned long *pulTxLevel, \ unsigned long *pulRxLevel))ROM_UARTTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTConfigSetExpClk \ ((void (*)(unsigned long ulBase, \ unsigned long ulUARTClk, \ unsigned long ulBaud, \ unsigned long ulConfig))ROM_UARTTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTConfigGetExpClk \ ((void (*)(unsigned long ulBase, \ unsigned long ulUARTClk, \ unsigned long *pulBaud, \ unsigned long *pulConfig))ROM_UARTTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTEnable \ ((void (*)(unsigned long ulBase))ROM_UARTTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTDisable \ ((void (*)(unsigned long ulBase))ROM_UARTTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTFIFOEnable \ ((void (*)(unsigned long ulBase))ROM_UARTTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTFIFODisable \ ((void (*)(unsigned long ulBase))ROM_UARTTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTCharsAvail \ ((tBoolean (*)(unsigned long ulBase))ROM_UARTTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTSpaceAvail \ ((tBoolean (*)(unsigned long ulBase))ROM_UARTTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTCharGetNonBlocking \ ((long (*)(unsigned long ulBase))ROM_UARTTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTCharGet \ ((long (*)(unsigned long ulBase))ROM_UARTTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTCharPutNonBlocking \ ((tBoolean (*)(unsigned long ulBase, \ unsigned char ucData))ROM_UARTTABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTCharPut \ ((void (*)(unsigned long ulBase, \ unsigned char ucData))ROM_UARTTABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTBreakCtl \ ((void (*)(unsigned long ulBase, \ tBoolean bBreakState))ROM_UARTTABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTBusy \ ((tBoolean (*)(unsigned long ulBase))ROM_UARTTABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTIntRegister \ ((void (*)(unsigned long ulBase, \ void(*pfnHandler)(void)))ROM_UARTTABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTIntUnregister \ ((void (*)(unsigned long ulBase))ROM_UARTTABLE[19]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTIntEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_UARTTABLE[20]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTIntDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_UARTTABLE[21]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTIntStatus \ ((unsigned long (*)(unsigned long ulBase, \ tBoolean bMasked))ROM_UARTTABLE[22]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTIntClear \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_UARTTABLE[23]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTDMAEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulDMAFlags))ROM_UARTTABLE[24]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTDMADisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulDMAFlags))ROM_UARTTABLE[25]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTRxErrorGet \ ((unsigned long (*)(unsigned long ulBase))ROM_UARTTABLE[26]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTRxErrorClear \ ((void (*)(unsigned long ulBase))ROM_UARTTABLE[27]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTModemControlSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulControl))ROM_UARTTABLE[28]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTModemControlClear \ ((void (*)(unsigned long ulBase, \ unsigned long ulControl))ROM_UARTTABLE[29]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTModemControlGet \ ((unsigned long (*)(unsigned long ulBase))ROM_UARTTABLE[30]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTModemStatusGet \ ((unsigned long (*)(unsigned long ulBase))ROM_UARTTABLE[31]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTFlowControlSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulMode))ROM_UARTTABLE[32]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTFlowControlGet \ ((unsigned long (*)(unsigned long ulBase))ROM_UARTTABLE[33]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTTxIntModeSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulMode))ROM_UARTTABLE[34]) #endif #if defined(TARGET_IS_CC3200) #define ROM_UARTTxIntModeGet \ ((unsigned long (*)(unsigned long ulBase))ROM_UARTTABLE[35]) #endif //***************************************************************************** // // Macros for calling ROM functions in the uDMA API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelTransferSet \ ((void (*)(unsigned long ulChannelStructIndex, \ unsigned long ulMode, \ void *pvSrcAddr, \ void *pvDstAddr, \ unsigned long ulTransferSize))ROM_UDMATABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAEnable \ ((void (*)(void))ROM_UDMATABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMADisable \ ((void (*)(void))ROM_UDMATABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAErrorStatusGet \ ((unsigned long (*)(void))ROM_UDMATABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAErrorStatusClear \ ((void (*)(void))ROM_UDMATABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelEnable \ ((void (*)(unsigned long ulChannelNum))ROM_UDMATABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelDisable \ ((void (*)(unsigned long ulChannelNum))ROM_UDMATABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelIsEnabled \ ((tBoolean (*)(unsigned long ulChannelNum))ROM_UDMATABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAControlBaseSet \ ((void (*)(void *pControlTable))ROM_UDMATABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAControlBaseGet \ ((void * (*)(void))ROM_UDMATABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelRequest \ ((void (*)(unsigned long ulChannelNum))ROM_UDMATABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelAttributeEnable \ ((void (*)(unsigned long ulChannelNum, \ unsigned long ulAttr))ROM_UDMATABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelAttributeDisable \ ((void (*)(unsigned long ulChannelNum, \ unsigned long ulAttr))ROM_UDMATABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelAttributeGet \ ((unsigned long (*)(unsigned long ulChannelNum))ROM_UDMATABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelControlSet \ ((void (*)(unsigned long ulChannelStructIndex, \ unsigned long ulControl))ROM_UDMATABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelSizeGet \ ((unsigned long (*)(unsigned long ulChannelStructIndex))ROM_UDMATABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelModeGet \ ((unsigned long (*)(unsigned long ulChannelStructIndex))ROM_UDMATABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAIntStatus \ ((unsigned long (*)(void))ROM_UDMATABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAIntClear \ ((void (*)(unsigned long ulChanMask))ROM_UDMATABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAControlAlternateBaseGet \ ((void * (*)(void))ROM_UDMATABLE[19]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelScatterGatherSet \ ((void (*)(unsigned long ulChannelNum, \ unsigned ulTaskCount, \ void *pvTaskList, \ unsigned long ulIsPeriphSG))ROM_UDMATABLE[20]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAChannelAssign \ ((void (*)(unsigned long ulMapping))ROM_UDMATABLE[21]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAIntRegister \ ((void (*)(unsigned long ulIntChannel, \ void (*pfnHandler)(void)))ROM_UDMATABLE[22]) #endif #if defined(TARGET_IS_CC3200) #define ROM_uDMAIntUnregister \ ((void (*)(unsigned long ulIntChannel))ROM_UDMATABLE[23]) #endif //***************************************************************************** // // Macros for calling ROM functions in the Watchdog API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_WatchdogIntClear \ ((void (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogRunning \ ((tBoolean (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogEnable \ ((void (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogLock \ ((void (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogUnlock \ ((void (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogLockState \ ((tBoolean (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogReloadSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulLoadVal))ROM_WATCHDOGTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogReloadGet \ ((unsigned long (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogValueGet \ ((unsigned long (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogIntStatus \ ((unsigned long (*)(unsigned long ulBase, \ tBoolean bMasked))ROM_WATCHDOGTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogStallEnable \ ((void (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogStallDisable \ ((void (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogIntRegister \ ((void (*)(unsigned long ulBase, \ void(*pfnHandler)(void)))ROM_WATCHDOGTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_WatchdogIntUnregister \ ((void (*)(unsigned long ulBase))ROM_WATCHDOGTABLE[14]) #endif //***************************************************************************** // // Macros for calling ROM functions in the I2C API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_I2CIntRegister \ ((void (*)(uint32_t ui32Base, \ void(pfnHandler)(void)))ROM_I2CTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CIntUnregister \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CTxFIFOConfigSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Config))ROM_I2CTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CTxFIFOFlush \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CRxFIFOConfigSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Config))ROM_I2CTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CRxFIFOFlush \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CFIFOStatus \ ((uint32_t (*)(uint32_t ui32Base))ROM_I2CTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CFIFODataPut \ ((void (*)(uint32_t ui32Base, \ uint8_t ui8Data))ROM_I2CTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CFIFODataPutNonBlocking \ ((uint32_t (*)(uint32_t ui32Base, \ uint8_t ui8Data))ROM_I2CTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CFIFODataGet \ ((uint32_t (*)(uint32_t ui32Base))ROM_I2CTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CFIFODataGetNonBlocking \ ((uint32_t (*)(uint32_t ui32Base, \ uint8_t *pui8Data))ROM_I2CTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterBurstLengthSet \ ((void (*)(uint32_t ui32Base, \ uint8_t ui8Length))ROM_I2CTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterBurstCountGet \ ((uint32_t (*)(uint32_t ui32Base))ROM_I2CTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterGlitchFilterConfigSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Config))ROM_I2CTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveFIFOEnable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Config))ROM_I2CTABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveFIFODisable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterBusBusy \ ((bool (*)(uint32_t ui32Base))ROM_I2CTABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterBusy \ ((bool (*)(uint32_t ui32Base))ROM_I2CTABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterControl \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Cmd))ROM_I2CTABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterDataGet \ ((uint32_t (*)(uint32_t ui32Base))ROM_I2CTABLE[19]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterDataPut \ ((void (*)(uint32_t ui32Base, \ uint8_t ui8Data))ROM_I2CTABLE[20]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterDisable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[21]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterEnable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[22]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterErr \ ((uint32_t (*)(uint32_t ui32Base))ROM_I2CTABLE[23]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterIntClear \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[24]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterIntDisable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[25]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterIntEnable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[26]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterIntStatus \ ((bool (*)(uint32_t ui32Base, \ bool bMasked))ROM_I2CTABLE[27]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterIntEnableEx \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_I2CTABLE[28]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterIntDisableEx \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_I2CTABLE[29]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterIntStatusEx \ ((uint32_t (*)(uint32_t ui32Base, \ bool bMasked))ROM_I2CTABLE[30]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterIntClearEx \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_I2CTABLE[31]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterTimeoutSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Value))ROM_I2CTABLE[32]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveACKOverride \ ((void (*)(uint32_t ui32Base, \ bool bEnable))ROM_I2CTABLE[33]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveACKValueSet \ ((void (*)(uint32_t ui32Base, \ bool bACK))ROM_I2CTABLE[34]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterLineStateGet \ ((uint32_t (*)(uint32_t ui32Base))ROM_I2CTABLE[35]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterSlaveAddrSet \ ((void (*)(uint32_t ui32Base, \ uint8_t ui8SlaveAddr, \ bool bReceive))ROM_I2CTABLE[36]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveDataGet \ ((uint32_t (*)(uint32_t ui32Base))ROM_I2CTABLE[37]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveDataPut \ ((void (*)(uint32_t ui32Base, \ uint8_t ui8Data))ROM_I2CTABLE[38]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveDisable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[39]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveEnable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[40]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveInit \ ((void (*)(uint32_t ui32Base, \ uint8_t ui8SlaveAddr))ROM_I2CTABLE[41]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveAddressSet \ ((void (*)(uint32_t ui32Base, \ uint8_t ui8AddrNum, \ uint8_t ui8SlaveAddr))ROM_I2CTABLE[42]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveIntClear \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[43]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveIntDisable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[44]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveIntEnable \ ((void (*)(uint32_t ui32Base))ROM_I2CTABLE[45]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveIntClearEx \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_I2CTABLE[46]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveIntDisableEx \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_I2CTABLE[47]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveIntEnableEx \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_I2CTABLE[48]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveIntStatus \ ((bool (*)(uint32_t ui32Base, \ bool bMasked))ROM_I2CTABLE[49]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveIntStatusEx \ ((uint32_t (*)(uint32_t ui32Base, \ bool bMasked))ROM_I2CTABLE[50]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CSlaveStatus \ ((uint32_t (*)(uint32_t ui32Base))ROM_I2CTABLE[51]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2CMasterInitExpClk \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32I2CClk, \ bool bFast))ROM_I2CTABLE[52]) #endif //***************************************************************************** // // Macros for calling ROM functions in the SPI API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_SPIEnable \ ((void (*)(unsigned long ulBase))ROM_SPITABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIDisable \ ((void (*)(unsigned long ulBase))ROM_SPITABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIReset \ ((void (*)(unsigned long ulBase))ROM_SPITABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIConfigSetExpClk \ ((void (*)(unsigned long ulBase, \ unsigned long ulSPIClk, \ unsigned long ulBitRate, \ unsigned long ulMode, \ unsigned long ulSubMode, \ unsigned long ulConfig))ROM_SPITABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIDataGetNonBlocking \ ((long (*)(unsigned long ulBase, \ unsigned long * pulData))ROM_SPITABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIDataGet \ ((void (*)(unsigned long ulBase, \ unsigned long *pulData))ROM_SPITABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIDataPutNonBlocking \ ((long (*)(unsigned long ulBase, \ unsigned long ulData))ROM_SPITABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIDataPut \ ((void (*)(unsigned long ulBase, \ unsigned long ulData))ROM_SPITABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIFIFOEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulFlags))ROM_SPITABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIFIFODisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulFlags))ROM_SPITABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIFIFOLevelSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulTxLevel, \ unsigned long ulRxLevel))ROM_SPITABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIFIFOLevelGet \ ((void (*)(unsigned long ulBase, \ unsigned long *pulTxLevel, \ unsigned long *pulRxLevel))ROM_SPITABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIWordCountSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulWordCount))ROM_SPITABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIIntRegister \ ((void (*)(unsigned long ulBase, \ void(*pfnHandler)(void)))ROM_SPITABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIIntUnregister \ ((void (*)(unsigned long ulBase))ROM_SPITABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIIntEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_SPITABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIIntDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_SPITABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIIntStatus \ ((unsigned long (*)(unsigned long ulBase, \ tBoolean bMasked))ROM_SPITABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIIntClear \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_SPITABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIDmaEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulFlags))ROM_SPITABLE[19]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPIDmaDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulFlags))ROM_SPITABLE[20]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPICSEnable \ ((void (*)(unsigned long ulBase))ROM_SPITABLE[21]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPICSDisable \ ((void (*)(unsigned long ulBase))ROM_SPITABLE[22]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SPITransfer \ ((long (*)(unsigned long ulBase, \ unsigned char *ucDout, \ unsigned char *ucDin, \ unsigned long ulSize, \ unsigned long ulFlags))ROM_SPITABLE[23]) #endif //***************************************************************************** // // Macros for calling ROM functions in the CAM API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_CameraReset \ ((void (*)(unsigned long ulBase))ROM_CAMERATABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraParamsConfig \ ((void (*)(unsigned long ulBase, \ unsigned long ulHSPol, \ unsigned long ulVSPol, \ unsigned long ulFlags))ROM_CAMERATABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraXClkConfig \ ((void (*)(unsigned long ulBase, \ unsigned long ulCamClkIn, \ unsigned long ulXClk))ROM_CAMERATABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraXClkSet \ ((void (*)(unsigned long ulBase, \ unsigned char bXClkFlags))ROM_CAMERATABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraDMAEnable \ ((void (*)(unsigned long ulBase))ROM_CAMERATABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraDMADisable \ ((void (*)(unsigned long ulBase))ROM_CAMERATABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraThresholdSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulThreshold))ROM_CAMERATABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraIntRegister \ ((void (*)(unsigned long ulBase, \ void (*pfnHandler)(void)))ROM_CAMERATABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraIntUnregister \ ((void (*)(unsigned long ulBase))ROM_CAMERATABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraIntEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_CAMERATABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraIntDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_CAMERATABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraIntStatus \ ((unsigned long (*)(unsigned long ulBase))ROM_CAMERATABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraIntClear \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_CAMERATABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraCaptureStop \ ((void (*)(unsigned long ulBase, \ tBoolean bImmediate))ROM_CAMERATABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraCaptureStart \ ((void (*)(unsigned long ulBase))ROM_CAMERATABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CameraBufferRead \ ((void (*)(unsigned long ulBase, \ unsigned long *pBuffer, \ unsigned char ucSize))ROM_CAMERATABLE[15]) #endif //***************************************************************************** // // Macros for calling ROM functions in the FLASH API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_FlashDisable \ ((void (*)(void))ROM_FLASHTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashErase \ ((long (*)(unsigned long ulAddress))ROM_FLASHTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashMassErase \ ((long (*)(void))ROM_FLASHTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashMassEraseNonBlocking \ ((void (*)(void))ROM_FLASHTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashEraseNonBlocking \ ((void (*)(unsigned long ulAddress))ROM_FLASHTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashProgram \ ((long (*)(unsigned long *pulData, \ unsigned long ulAddress, \ unsigned long ulCount))ROM_FLASHTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashProgramNonBlocking \ ((long (*)(unsigned long *pulData, \ unsigned long ulAddress, \ unsigned long ulCount))ROM_FLASHTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashIntRegister \ ((void (*)(void (*pfnHandler)(void)))ROM_FLASHTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashIntUnregister \ ((void (*)(void))ROM_FLASHTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashIntEnable \ ((void (*)(unsigned long ulIntFlags))ROM_FLASHTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashIntDisable \ ((void (*)(unsigned long ulIntFlags))ROM_FLASHTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashIntStatus \ ((unsigned long (*)(tBoolean bMasked))ROM_FLASHTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashIntClear \ ((void (*)(unsigned long ulIntFlags))ROM_FLASHTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_FlashProtectGet \ ((tFlashProtection (*)(unsigned long ulAddress))ROM_FLASHTABLE[13]) #endif //***************************************************************************** // // Macros for calling ROM functions in the Pin API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_PinModeSet \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinDirModeSet \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinIO))ROM_PINTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinDirModeGet \ ((unsigned long (*)(unsigned long ulPin))ROM_PINTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinModeGet \ ((unsigned long (*)(unsigned long ulPin))ROM_PINTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinConfigGet \ ((void (*)(unsigned long ulPin, \ unsigned long *pulPinStrength, \ unsigned long *pulPinType))ROM_PINTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinConfigSet \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinStrength, \ unsigned long ulPinType))ROM_PINTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeUART \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeI2C \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeSPI \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeI2S \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeTimer \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeCamera \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeGPIO \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode, \ tBoolean bOpenDrain))ROM_PINTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeADC \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PinTypeSDHost \ ((void (*)(unsigned long ulPin, \ unsigned long ulPinMode))ROM_PINTABLE[14]) #endif //***************************************************************************** // // Macros for calling ROM functions in the SYSTICK API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_SysTickEnable \ ((void (*)(void))ROM_SYSTICKTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SysTickDisable \ ((void (*)(void))ROM_SYSTICKTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SysTickIntRegister \ ((void (*)(void (*pfnHandler)(void)))ROM_SYSTICKTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SysTickIntUnregister \ ((void (*)(void))ROM_SYSTICKTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SysTickIntEnable \ ((void (*)(void))ROM_SYSTICKTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SysTickIntDisable \ ((void (*)(void))ROM_SYSTICKTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SysTickPeriodSet \ ((void (*)(unsigned long ulPeriod))ROM_SYSTICKTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SysTickPeriodGet \ ((unsigned long (*)(void))ROM_SYSTICKTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SysTickValueGet \ ((unsigned long (*)(void))ROM_SYSTICKTABLE[8]) #endif //***************************************************************************** // // Macros for calling ROM functions in the UTILS API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_UtilsDelay \ ((void (*)(unsigned long ulCount))ROM_UTILSTABLE[0]) #endif //***************************************************************************** // // Macros for calling ROM functions in the I2S API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_I2SEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulMode))ROM_I2STABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SDisable \ ((void (*)(unsigned long ulBase))ROM_I2STABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SDataPut \ ((void (*)(unsigned long ulBase, \ unsigned long ulDataLine, \ unsigned long ulData))ROM_I2STABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SDataPutNonBlocking \ ((long (*)(unsigned long ulBase, \ unsigned long ulDataLine, \ unsigned long ulData))ROM_I2STABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SDataGet \ ((void (*)(unsigned long ulBase, \ unsigned long ulDataLine, \ unsigned long *pulData))ROM_I2STABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SDataGetNonBlocking \ ((long (*)(unsigned long ulBase, \ unsigned long ulDataLine, \ unsigned long *pulData))ROM_I2STABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SConfigSetExpClk \ ((void (*)(unsigned long ulBase, \ unsigned long ulI2SClk, \ unsigned long ulBitClk, \ unsigned long ulConfig))ROM_I2STABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2STxFIFOEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulTxLevel, \ unsigned long ulWordsPerTransfer))ROM_I2STABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2STxFIFODisable \ ((void (*)(unsigned long ulBase))ROM_I2STABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SRxFIFOEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulRxLevel, \ unsigned long ulWordsPerTransfer))ROM_I2STABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SRxFIFODisable \ ((void (*)(unsigned long ulBase))ROM_I2STABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2STxFIFOStatusGet \ ((unsigned long (*)(unsigned long ulBase))ROM_I2STABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SRxFIFOStatusGet \ ((unsigned long (*)(unsigned long ulBase))ROM_I2STABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SSerializerConfig \ ((void (*)(unsigned long ulBase, \ unsigned long ulDataLine, \ unsigned long ulSerMode, \ unsigned long ulInActState))ROM_I2STABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SIntEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_I2STABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SIntDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_I2STABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SIntStatus \ ((unsigned long (*)(unsigned long ulBase))ROM_I2STABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SIntClear \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_I2STABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SIntRegister \ ((void (*)(unsigned long ulBase, \ void (*pfnHandler)(void)))ROM_I2STABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_I2SIntUnregister \ ((void (*)(unsigned long ulBase))ROM_I2STABLE[19]) #endif //***************************************************************************** // // Macros for calling ROM functions in the GPIO API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_GPIODirModeSet \ ((void (*)(unsigned long ulPort, \ unsigned char ucPins, \ unsigned long ulPinIO))ROM_GPIOTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIODirModeGet \ ((unsigned long (*)(unsigned long ulPort, \ unsigned char ucPin))ROM_GPIOTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOIntTypeSet \ ((void (*)(unsigned long ulPort, \ unsigned char ucPins, \ unsigned long ulIntType))ROM_GPIOTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIODMATriggerEnable \ ((void (*)(unsigned long ulPort))ROM_GPIOTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIODMATriggerDisable \ ((void (*)(unsigned long ulPort))ROM_GPIOTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOIntTypeGet \ ((unsigned long (*)(unsigned long ulPort, \ unsigned char ucPin))ROM_GPIOTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOIntEnable \ ((void (*)(unsigned long ulPort, \ unsigned long ulIntFlags))ROM_GPIOTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOIntDisable \ ((void (*)(unsigned long ulPort, \ unsigned long ulIntFlags))ROM_GPIOTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOIntStatus \ ((long (*)(unsigned long ulPort, \ tBoolean bMasked))ROM_GPIOTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOIntClear \ ((void (*)(unsigned long ulPort, \ unsigned long ulIntFlags))ROM_GPIOTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOIntRegister \ ((void (*)(unsigned long ulPort, \ void (*pfnIntHandler)(void)))ROM_GPIOTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOIntUnregister \ ((void (*)(unsigned long ulPort))ROM_GPIOTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOPinRead \ ((long (*)(unsigned long ulPort, \ unsigned char ucPins))ROM_GPIOTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_GPIOPinWrite \ ((void (*)(unsigned long ulPort, \ unsigned char ucPins, \ unsigned char ucVal))ROM_GPIOTABLE[13]) #endif //***************************************************************************** // // Macros for calling ROM functions in the AES API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_AESConfigSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Config))ROM_AESTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESKey1Set \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Key, \ uint32_t ui32Keysize))ROM_AESTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESKey2Set \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Key, \ uint32_t ui32Keysize))ROM_AESTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESKey3Set \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Key))ROM_AESTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESIVSet \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8IVdata))ROM_AESTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESTagRead \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8TagData))ROM_AESTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDataLengthSet \ ((void (*)(uint32_t ui32Base, \ uint64_t ui64Length))ROM_AESTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESAuthDataLengthSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Length))ROM_AESTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDataReadNonBlocking \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Dest, \ uint8_t ui8Length))ROM_AESTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDataRead \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Dest, \ uint8_t ui8Length))ROM_AESTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDataWriteNonBlocking \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Src, \ uint8_t ui8Length))ROM_AESTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDataWrite \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Src, \ uint8_t ui8Length))ROM_AESTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDataProcess \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Src, \ uint8_t *pui8Dest, \ uint32_t ui32Length))ROM_AESTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDataMAC \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Src, \ uint32_t ui32Length, \ uint8_t *pui8Tag))ROM_AESTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDataProcessAE \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Src, \ uint8_t *pui8Dest, \ uint32_t ui32Length, \ uint8_t *pui8AuthSrc, \ uint32_t ui32AuthLength, \ uint8_t *pui8Tag))ROM_AESTABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESIntStatus \ ((uint32_t (*)(uint32_t ui32Base, \ bool bMasked))ROM_AESTABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESIntEnable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_AESTABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESIntDisable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_AESTABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESIntClear \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_AESTABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESIntRegister \ ((void (*)(uint32_t ui32Base, \ void(*pfnHandler)(void)))ROM_AESTABLE[19]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESIntUnregister \ ((void (*)(uint32_t ui32Base))ROM_AESTABLE[20]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDMAEnable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Flags))ROM_AESTABLE[21]) #endif #if defined(TARGET_IS_CC3200) #define ROM_AESDMADisable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Flags))ROM_AESTABLE[22]) #endif //***************************************************************************** // // Macros for calling ROM functions in the DES API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_DESConfigSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Config))ROM_DESTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESDataRead \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Dest, \ uint8_t ui8Length))ROM_DESTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESDataReadNonBlocking \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Dest, \ uint8_t ui8Length))ROM_DESTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESDataProcess \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Src, \ uint8_t *pui8Dest, \ uint32_t ui32Length))ROM_DESTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESDataWrite \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Src, \ uint8_t ui8Length))ROM_DESTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESDataWriteNonBlocking \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Src, \ uint8_t ui8Length))ROM_DESTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESDMADisable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Flags))ROM_DESTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESDMAEnable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Flags))ROM_DESTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESIntClear \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_DESTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESIntDisable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_DESTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESIntEnable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_DESTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESIntRegister \ ((void (*)(uint32_t ui32Base, \ void(*pfnHandler)(void)))ROM_DESTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESIntStatus \ ((uint32_t (*)(uint32_t ui32Base, \ bool bMasked))ROM_DESTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESIntUnregister \ ((void (*)(uint32_t ui32Base))ROM_DESTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESIVSet \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8IVdata))ROM_DESTABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESKeySet \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Key))ROM_DESTABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_DESDataLengthSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Length))ROM_DESTABLE[16]) #endif //***************************************************************************** // // Macros for calling ROM functions in the SHAMD5 API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5ConfigSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Mode))ROM_SHAMD5TABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5DataProcess \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8DataSrc, \ uint32_t ui32DataLength, \ uint8_t *pui8HashResult))ROM_SHAMD5TABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5DataWrite \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Src))ROM_SHAMD5TABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5DataWriteNonBlocking \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8Src))ROM_SHAMD5TABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5DMADisable \ ((void (*)(uint32_t ui32Base))ROM_SHAMD5TABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5DMAEnable \ ((void (*)(uint32_t ui32Base))ROM_SHAMD5TABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5DataLengthSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Length))ROM_SHAMD5TABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5HMACKeySet \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Src))ROM_SHAMD5TABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5HMACPPKeyGenerate \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Key, \ uint8_t *pui8PPKey))ROM_SHAMD5TABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5HMACPPKeySet \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Src))ROM_SHAMD5TABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5HMACProcess \ ((bool (*)(uint32_t ui32Base, \ uint8_t *pui8DataSrc, \ uint32_t ui32DataLength, \ uint8_t *pui8HashResult))ROM_SHAMD5TABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5IntClear \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_SHAMD5TABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5IntDisable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_SHAMD5TABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5IntEnable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32IntFlags))ROM_SHAMD5TABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5IntRegister \ ((void (*)(uint32_t ui32Base, \ void(*pfnHandler)(void)))ROM_SHAMD5TABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5IntStatus \ ((uint32_t (*)(uint32_t ui32Base, \ bool bMasked))ROM_SHAMD5TABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5IntUnregister \ ((void (*)(uint32_t ui32Base))ROM_SHAMD5TABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SHAMD5ResultRead \ ((void (*)(uint32_t ui32Base, \ uint8_t *pui8Dest))ROM_SHAMD5TABLE[17]) #endif //***************************************************************************** // // Macros for calling ROM functions in the CRC API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_CRCConfigSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32CRCConfig))ROM_CRCTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CRCDataProcess \ ((uint32_t (*)(uint32_t ui32Base, \ void *puiDataIn, \ uint32_t ui32DataLength, \ uint32_t ui32Config))ROM_CRCTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CRCDataWrite \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Data))ROM_CRCTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CRCResultRead \ ((uint32_t (*)(uint32_t ui32Base))ROM_CRCTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_CRCSeedSet \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32Seed))ROM_CRCTABLE[4]) #endif //***************************************************************************** // // Macros for calling ROM functions in the SDHOST API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_SDHostCmdReset \ ((void (*)(unsigned long ulBase))ROM_SDHOSTTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostInit \ ((void (*)(unsigned long ulBase))ROM_SDHOSTTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostCmdSend \ ((long (*)(unsigned long ulBase, \ unsigned long ulCmd, \ unsigned ulArg))ROM_SDHOSTTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostIntRegister \ ((void (*)(unsigned long ulBase, \ void (*pfnHandler)(void)))ROM_SDHOSTTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostIntUnregister \ ((void (*)(unsigned long ulBase))ROM_SDHOSTTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostIntEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_SDHOSTTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostIntDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_SDHOSTTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostIntStatus \ ((unsigned long (*)(unsigned long ulBase))ROM_SDHOSTTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostIntClear \ ((void (*)(unsigned long ulBase, \ unsigned long ulIntFlags))ROM_SDHOSTTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostRespStatus \ ((unsigned long (*)(unsigned long ulBase))ROM_SDHOSTTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostRespGet \ ((void (*)(unsigned long ulBase, \ unsigned long ulRespnse[4]))ROM_SDHOSTTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostBlockSizeSet \ ((void (*)(unsigned long ulBase, \ unsigned short ulBlkSize))ROM_SDHOSTTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostBlockCountSet \ ((void (*)(unsigned long ulBase, \ unsigned short ulBlkCount))ROM_SDHOSTTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostDataNonBlockingWrite \ ((tBoolean (*)(unsigned long ulBase, \ unsigned long ulData))ROM_SDHOSTTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostDataNonBlockingRead \ ((tBoolean (*)(unsigned long ulBase, \ unsigned long *pulData))ROM_SDHOSTTABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostDataWrite \ ((void (*)(unsigned long ulBase, \ unsigned long ulData))ROM_SDHOSTTABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostDataRead \ ((void (*)(unsigned long ulBase, \ unsigned long *ulData))ROM_SDHOSTTABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_SDHostSetExpClk \ ((void (*)(unsigned long ulBase, \ unsigned long ulSDHostClk, \ unsigned long ulCardClk))ROM_SDHOSTTABLE[17]) #endif //***************************************************************************** // // Macros for calling ROM functions in the PRCM API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_PRCMMCUReset \ ((void (*)(tBoolean bIncludeSubsystem))ROM_PRCMTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMSysResetCauseGet \ ((unsigned long (*)(void))ROM_PRCMTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMPeripheralClkEnable \ ((void (*)(unsigned long ulPeripheral, \ unsigned long ulClkFlags))ROM_PRCMTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMPeripheralClkDisable \ ((void (*)(unsigned long ulPeripheral, \ unsigned long ulClkFlags))ROM_PRCMTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMPeripheralReset \ ((void (*)(unsigned long ulPeripheral))ROM_PRCMTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMPeripheralStatusGet \ ((tBoolean (*)(unsigned long ulPeripheral))ROM_PRCMTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMI2SClockFreqSet \ ((void (*)(unsigned long ulI2CClkFreq))ROM_PRCMTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMPeripheralClockGet \ ((unsigned long (*)(unsigned long ulPeripheral))ROM_PRCMTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMSleepEnter \ ((void (*)(void))ROM_PRCMTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMDeepSleepEnter \ ((void (*)(void))ROM_PRCMTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMSRAMRetentionEnable \ ((void (*)(unsigned long ulSramColSel, \ unsigned long ulFlags))ROM_PRCMTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMSRAMRetentionDisable \ ((void (*)(unsigned long ulSramColSel, \ unsigned long ulFlags))ROM_PRCMTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMLPDSEnter \ ((void (*)(void))ROM_PRCMTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMLPDSIntervalSet \ ((void (*)(unsigned long ulTicks))ROM_PRCMTABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMLPDSWakeupSourceEnable \ ((void (*)(unsigned long ulLpdsWakeupSrc))ROM_PRCMTABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMLPDSWakeupCauseGet \ ((unsigned long (*)(void))ROM_PRCMTABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMLPDSWakeUpGPIOSelect \ ((void (*)(unsigned long ulGPIOPin, \ unsigned long ulType))ROM_PRCMTABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMLPDSWakeupSourceDisable \ ((void (*)(unsigned long ulLpdsWakeupSrc))ROM_PRCMTABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMHibernateEnter \ ((void (*)(void))ROM_PRCMTABLE[19]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMHibernateWakeupSourceEnable \ ((void (*)(unsigned long ulHIBWakupSrc))ROM_PRCMTABLE[20]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMHibernateWakeupCauseGet \ ((unsigned long (*)(void))ROM_PRCMTABLE[21]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMHibernateWakeUpGPIOSelect \ ((void (*)(unsigned long ulMultiGPIOBitMap, \ unsigned long ulType))ROM_PRCMTABLE[22]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMHibernateWakeupSourceDisable \ ((void (*)(unsigned long ulHIBWakupSrc))ROM_PRCMTABLE[23]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMHibernateIntervalSet \ ((void (*)(unsigned long long ullTicks))ROM_PRCMTABLE[24]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMSlowClkCtrGet \ ((unsigned long long (*)(void))ROM_PRCMTABLE[25]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMSlowClkCtrMatchSet \ ((void (*)(unsigned long long ullTicks))ROM_PRCMTABLE[26]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMSlowClkCtrMatchGet \ ((unsigned long long (*)(void))ROM_PRCMTABLE[27]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMOCRRegisterWrite \ ((void (*)(unsigned char ucIndex, \ unsigned long ulRegValue))ROM_PRCMTABLE[28]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMOCRRegisterRead \ ((unsigned long (*)(unsigned char ucIndex))ROM_PRCMTABLE[29]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMIntRegister \ ((void (*)(void (*pfnHandler)(void)))ROM_PRCMTABLE[30]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMIntUnregister \ ((void (*)(void))ROM_PRCMTABLE[31]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMIntEnable \ ((void (*)(unsigned long ulIntFlags))ROM_PRCMTABLE[32]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMIntDisable \ ((void (*)(unsigned long ulIntFlags))ROM_PRCMTABLE[33]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMIntStatus \ ((unsigned long (*)(void))ROM_PRCMTABLE[34]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMRTCInUseSet \ ((void (*)(void))ROM_PRCMTABLE[35]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMRTCInUseGet \ ((tBoolean (*)(void))ROM_PRCMTABLE[36]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMRTCSet \ ((void (*)(unsigned long ulSecs, \ unsigned short usMsec))ROM_PRCMTABLE[37]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMRTCGet \ ((void (*)(unsigned long *ulSecs, \ unsigned short *usMsec))ROM_PRCMTABLE[38]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMRTCMatchSet \ ((void (*)(unsigned long ulSecs, \ unsigned short usMsec))ROM_PRCMTABLE[39]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMRTCMatchGet \ ((void (*)(unsigned long *ulSecs, \ unsigned short *usMsec))ROM_PRCMTABLE[40]) #endif #if defined(TARGET_IS_CC3200) #define ROM_PRCMLPDSRestoreInfoSet \ ((void (*)(unsigned long ulRestoreSP, \ unsigned long ulRestorePC))ROM_PRCMTABLE[41]) #endif //***************************************************************************** // // Macros for calling ROM functions in the HWSPINLOCK API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_HwSpinLockAcquire \ ((void (*)(uint32_t ui32LockID))ROM_HWSPINLOCKTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_HwSpinLockTryAcquire \ ((int32_t (*)(uint32_t ui32LockID, \ uint32_t ui32Retry))ROM_HWSPINLOCKTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_HwSpinLockRelease \ ((void (*)(uint32_t ui32LockID))ROM_HWSPINLOCKTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_HwSpinLockTest \ ((uint32_t (*)(uint32_t ui32LockID, \ bool bCurrentStatus))ROM_HWSPINLOCKTABLE[3]) #endif //***************************************************************************** // // Macros for calling ROM functions in the ADC API. // //***************************************************************************** #if defined(TARGET_IS_CC3200) #define ROM_ADCEnable \ ((void (*)(unsigned long ulBase))ROM_ADCTABLE[0]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCDisable \ ((void (*)(unsigned long ulBase))ROM_ADCTABLE[1]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCChannelEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[2]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCChannelDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[3]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCIntRegister \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel, \ void (*pfnHandler)(void)))ROM_ADCTABLE[4]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCIntUnregister \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[5]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCIntEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel, \ unsigned long ulIntFlags))ROM_ADCTABLE[6]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCIntDisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel, \ unsigned long ulIntFlags))ROM_ADCTABLE[7]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCIntStatus \ ((unsigned long (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[8]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCIntClear \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel, \ unsigned long ulIntFlags))ROM_ADCTABLE[9]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCDMAEnable \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[10]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCDMADisable \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[11]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCChannelGainSet \ ((void (*)(unsigned long ulBase, \ unsigned long ulChannel, \ unsigned char ucGain))ROM_ADCTABLE[12]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCChannleGainGet \ ((unsigned char (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[13]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCTimerConfig \ ((void (*)(unsigned long ulBase, \ unsigned long ulValue))ROM_ADCTABLE[14]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCTimerEnable \ ((void (*)(unsigned long ulBase))ROM_ADCTABLE[15]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCTimerDisable \ ((void (*)(unsigned long ulBase))ROM_ADCTABLE[16]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCTimerReset \ ((void (*)(unsigned long ulBase))ROM_ADCTABLE[17]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCTimerValueGet \ ((unsigned long (*)(unsigned long ulBase))ROM_ADCTABLE[18]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCFIFOLvlGet \ ((unsigned char (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[19]) #endif #if defined(TARGET_IS_CC3200) #define ROM_ADCFIFORead \ ((unsigned long (*)(unsigned long ulBase, \ unsigned long ulChannel))ROM_ADCTABLE[20]) #endif #endif // __ROM_H__ micropython-1.12/ports/cc3200/hal/rom_map.h000066400000000000000000002167421357706137100204460ustar00rootroot00000000000000//***************************************************************************** // // rom_map.h // // Macros to facilitate calling functions in the ROM when they are // available and in flash otherwise. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // // THIS IS AN AUTO-GENERATED FILE. DO NOT EDIT BY HAND. // //***************************************************************************** #ifndef __ROM_MAP_H__ #define __ROM_MAP_H__ #ifndef DEBUG #include "rom.h" #endif #include "rom_patch.h" //***************************************************************************** // // Macros for the Interrupt API. // //***************************************************************************** #ifdef ROM_IntEnable #define MAP_IntEnable \ ROM_IntEnable #else #define MAP_IntEnable \ IntEnable #endif #ifdef ROM_IntMasterEnable #define MAP_IntMasterEnable \ ROM_IntMasterEnable #else #define MAP_IntMasterEnable \ IntMasterEnable #endif #ifdef ROM_IntMasterDisable #define MAP_IntMasterDisable \ ROM_IntMasterDisable #else #define MAP_IntMasterDisable \ IntMasterDisable #endif #ifdef ROM_IntDisable #define MAP_IntDisable \ ROM_IntDisable #else #define MAP_IntDisable \ IntDisable #endif #ifdef ROM_IntPriorityGroupingSet #define MAP_IntPriorityGroupingSet \ ROM_IntPriorityGroupingSet #else #define MAP_IntPriorityGroupingSet \ IntPriorityGroupingSet #endif #ifdef ROM_IntPriorityGroupingGet #define MAP_IntPriorityGroupingGet \ ROM_IntPriorityGroupingGet #else #define MAP_IntPriorityGroupingGet \ IntPriorityGroupingGet #endif #ifdef ROM_IntPrioritySet #define MAP_IntPrioritySet \ ROM_IntPrioritySet #else #define MAP_IntPrioritySet \ IntPrioritySet #endif #ifdef ROM_IntPriorityGet #define MAP_IntPriorityGet \ ROM_IntPriorityGet #else #define MAP_IntPriorityGet \ IntPriorityGet #endif #ifdef ROM_IntPendSet #define MAP_IntPendSet \ ROM_IntPendSet #else #define MAP_IntPendSet \ IntPendSet #endif #ifdef ROM_IntPendClear #define MAP_IntPendClear \ ROM_IntPendClear #else #define MAP_IntPendClear \ IntPendClear #endif #ifdef ROM_IntPriorityMaskSet #define MAP_IntPriorityMaskSet \ ROM_IntPriorityMaskSet #else #define MAP_IntPriorityMaskSet \ IntPriorityMaskSet #endif #ifdef ROM_IntPriorityMaskGet #define MAP_IntPriorityMaskGet \ ROM_IntPriorityMaskGet #else #define MAP_IntPriorityMaskGet \ IntPriorityMaskGet #endif #ifdef ROM_IntRegister #define MAP_IntRegister \ ROM_IntRegister #else #define MAP_IntRegister \ IntRegister #endif #ifdef ROM_IntUnregister #define MAP_IntUnregister \ ROM_IntUnregister #else #define MAP_IntUnregister \ IntUnregister #endif #ifdef ROM_IntVTableBaseSet #define MAP_IntVTableBaseSet \ ROM_IntVTableBaseSet #else #define MAP_IntVTableBaseSet \ IntVTableBaseSet #endif //***************************************************************************** // // Macros for the Timer API. // //***************************************************************************** #ifdef ROM_TimerEnable #define MAP_TimerEnable \ ROM_TimerEnable #else #define MAP_TimerEnable \ TimerEnable #endif #ifdef ROM_TimerDisable #define MAP_TimerDisable \ ROM_TimerDisable #else #define MAP_TimerDisable \ TimerDisable #endif #ifdef ROM_TimerConfigure #define MAP_TimerConfigure \ ROM_TimerConfigure #else #define MAP_TimerConfigure \ TimerConfigure #endif #ifdef ROM_TimerControlLevel #define MAP_TimerControlLevel \ ROM_TimerControlLevel #else #define MAP_TimerControlLevel \ TimerControlLevel #endif #ifdef ROM_TimerControlEvent #define MAP_TimerControlEvent \ ROM_TimerControlEvent #else #define MAP_TimerControlEvent \ TimerControlEvent #endif #ifdef ROM_TimerControlStall #define MAP_TimerControlStall \ ROM_TimerControlStall #else #define MAP_TimerControlStall \ TimerControlStall #endif #ifdef ROM_TimerPrescaleSet #define MAP_TimerPrescaleSet \ ROM_TimerPrescaleSet #else #define MAP_TimerPrescaleSet \ TimerPrescaleSet #endif #ifdef ROM_TimerPrescaleGet #define MAP_TimerPrescaleGet \ ROM_TimerPrescaleGet #else #define MAP_TimerPrescaleGet \ TimerPrescaleGet #endif #ifdef ROM_TimerPrescaleMatchSet #define MAP_TimerPrescaleMatchSet \ ROM_TimerPrescaleMatchSet #else #define MAP_TimerPrescaleMatchSet \ TimerPrescaleMatchSet #endif #ifdef ROM_TimerPrescaleMatchGet #define MAP_TimerPrescaleMatchGet \ ROM_TimerPrescaleMatchGet #else #define MAP_TimerPrescaleMatchGet \ TimerPrescaleMatchGet #endif #ifdef ROM_TimerLoadSet #define MAP_TimerLoadSet \ ROM_TimerLoadSet #else #define MAP_TimerLoadSet \ TimerLoadSet #endif #ifdef ROM_TimerLoadGet #define MAP_TimerLoadGet \ ROM_TimerLoadGet #else #define MAP_TimerLoadGet \ TimerLoadGet #endif #ifdef ROM_TimerValueGet #define MAP_TimerValueGet \ ROM_TimerValueGet #else #define MAP_TimerValueGet \ TimerValueGet #endif #ifdef ROM_TimerMatchSet #define MAP_TimerMatchSet \ ROM_TimerMatchSet #else #define MAP_TimerMatchSet \ TimerMatchSet #endif #ifdef ROM_TimerMatchGet #define MAP_TimerMatchGet \ ROM_TimerMatchGet #else #define MAP_TimerMatchGet \ TimerMatchGet #endif #ifdef ROM_TimerIntRegister #define MAP_TimerIntRegister \ ROM_TimerIntRegister #else #define MAP_TimerIntRegister \ TimerIntRegister #endif #ifdef ROM_TimerIntUnregister #define MAP_TimerIntUnregister \ ROM_TimerIntUnregister #else #define MAP_TimerIntUnregister \ TimerIntUnregister #endif #ifdef ROM_TimerIntEnable #define MAP_TimerIntEnable \ ROM_TimerIntEnable #else #define MAP_TimerIntEnable \ TimerIntEnable #endif #ifdef ROM_TimerIntDisable #define MAP_TimerIntDisable \ ROM_TimerIntDisable #else #define MAP_TimerIntDisable \ TimerIntDisable #endif #ifdef ROM_TimerIntStatus #define MAP_TimerIntStatus \ ROM_TimerIntStatus #else #define MAP_TimerIntStatus \ TimerIntStatus #endif #ifdef ROM_TimerIntClear #define MAP_TimerIntClear \ ROM_TimerIntClear #else #define MAP_TimerIntClear \ TimerIntClear #endif #ifdef ROM_TimerDMAEventSet #define MAP_TimerDMAEventSet \ ROM_TimerDMAEventSet #else #define MAP_TimerDMAEventSet \ TimerDMAEventSet #endif #ifdef ROM_TimerDMAEventGet #define MAP_TimerDMAEventGet \ ROM_TimerDMAEventGet #else #define MAP_TimerDMAEventGet \ TimerDMAEventGet #endif //***************************************************************************** // // Macros for the UART API. // //***************************************************************************** #ifdef ROM_UARTParityModeSet #define MAP_UARTParityModeSet \ ROM_UARTParityModeSet #else #define MAP_UARTParityModeSet \ UARTParityModeSet #endif #ifdef ROM_UARTParityModeGet #define MAP_UARTParityModeGet \ ROM_UARTParityModeGet #else #define MAP_UARTParityModeGet \ UARTParityModeGet #endif #ifdef ROM_UARTFIFOLevelSet #define MAP_UARTFIFOLevelSet \ ROM_UARTFIFOLevelSet #else #define MAP_UARTFIFOLevelSet \ UARTFIFOLevelSet #endif #ifdef ROM_UARTFIFOLevelGet #define MAP_UARTFIFOLevelGet \ ROM_UARTFIFOLevelGet #else #define MAP_UARTFIFOLevelGet \ UARTFIFOLevelGet #endif #ifdef ROM_UARTConfigSetExpClk #define MAP_UARTConfigSetExpClk \ ROM_UARTConfigSetExpClk #else #define MAP_UARTConfigSetExpClk \ UARTConfigSetExpClk #endif #ifdef ROM_UARTConfigGetExpClk #define MAP_UARTConfigGetExpClk \ ROM_UARTConfigGetExpClk #else #define MAP_UARTConfigGetExpClk \ UARTConfigGetExpClk #endif #ifdef ROM_UARTEnable #define MAP_UARTEnable \ ROM_UARTEnable #else #define MAP_UARTEnable \ UARTEnable #endif #ifdef ROM_UARTDisable #define MAP_UARTDisable \ ROM_UARTDisable #else #define MAP_UARTDisable \ UARTDisable #endif #ifdef ROM_UARTFIFOEnable #define MAP_UARTFIFOEnable \ ROM_UARTFIFOEnable #else #define MAP_UARTFIFOEnable \ UARTFIFOEnable #endif #ifdef ROM_UARTFIFODisable #define MAP_UARTFIFODisable \ ROM_UARTFIFODisable #else #define MAP_UARTFIFODisable \ UARTFIFODisable #endif #ifdef ROM_UARTCharsAvail #define MAP_UARTCharsAvail \ ROM_UARTCharsAvail #else #define MAP_UARTCharsAvail \ UARTCharsAvail #endif #ifdef ROM_UARTSpaceAvail #define MAP_UARTSpaceAvail \ ROM_UARTSpaceAvail #else #define MAP_UARTSpaceAvail \ UARTSpaceAvail #endif #ifdef ROM_UARTCharGetNonBlocking #define MAP_UARTCharGetNonBlocking \ ROM_UARTCharGetNonBlocking #else #define MAP_UARTCharGetNonBlocking \ UARTCharGetNonBlocking #endif #ifdef ROM_UARTCharGet #define MAP_UARTCharGet \ ROM_UARTCharGet #else #define MAP_UARTCharGet \ UARTCharGet #endif #ifdef ROM_UARTCharPutNonBlocking #define MAP_UARTCharPutNonBlocking \ ROM_UARTCharPutNonBlocking #else #define MAP_UARTCharPutNonBlocking \ UARTCharPutNonBlocking #endif #ifdef ROM_UARTCharPut #define MAP_UARTCharPut \ ROM_UARTCharPut #else #define MAP_UARTCharPut \ UARTCharPut #endif #ifdef ROM_UARTBreakCtl #define MAP_UARTBreakCtl \ ROM_UARTBreakCtl #else #define MAP_UARTBreakCtl \ UARTBreakCtl #endif #ifdef ROM_UARTBusy #define MAP_UARTBusy \ ROM_UARTBusy #else #define MAP_UARTBusy \ UARTBusy #endif #ifdef ROM_UARTIntRegister #define MAP_UARTIntRegister \ ROM_UARTIntRegister #else #define MAP_UARTIntRegister \ UARTIntRegister #endif #ifdef ROM_UARTIntUnregister #define MAP_UARTIntUnregister \ ROM_UARTIntUnregister #else #define MAP_UARTIntUnregister \ UARTIntUnregister #endif #ifdef ROM_UARTIntEnable #define MAP_UARTIntEnable \ ROM_UARTIntEnable #else #define MAP_UARTIntEnable \ UARTIntEnable #endif #ifdef ROM_UARTIntDisable #define MAP_UARTIntDisable \ ROM_UARTIntDisable #else #define MAP_UARTIntDisable \ UARTIntDisable #endif #ifdef ROM_UARTIntStatus #define MAP_UARTIntStatus \ ROM_UARTIntStatus #else #define MAP_UARTIntStatus \ UARTIntStatus #endif #ifdef ROM_UARTIntClear #define MAP_UARTIntClear \ ROM_UARTIntClear #else #define MAP_UARTIntClear \ UARTIntClear #endif #ifdef ROM_UARTDMAEnable #define MAP_UARTDMAEnable \ ROM_UARTDMAEnable #else #define MAP_UARTDMAEnable \ UARTDMAEnable #endif #ifdef ROM_UARTDMADisable #define MAP_UARTDMADisable \ ROM_UARTDMADisable #else #define MAP_UARTDMADisable \ UARTDMADisable #endif #ifdef ROM_UARTRxErrorGet #define MAP_UARTRxErrorGet \ ROM_UARTRxErrorGet #else #define MAP_UARTRxErrorGet \ UARTRxErrorGet #endif #ifdef ROM_UARTRxErrorClear #define MAP_UARTRxErrorClear \ ROM_UARTRxErrorClear #else #define MAP_UARTRxErrorClear \ UARTRxErrorClear #endif #ifdef ROM_UARTModemControlSet #define MAP_UARTModemControlSet \ ROM_UARTModemControlSet #else #define MAP_UARTModemControlSet \ UARTModemControlSet #endif #ifdef ROM_UARTModemControlClear #define MAP_UARTModemControlClear \ ROM_UARTModemControlClear #else #define MAP_UARTModemControlClear \ UARTModemControlClear #endif #ifdef ROM_UARTModemControlGet #define MAP_UARTModemControlGet \ ROM_UARTModemControlGet #else #define MAP_UARTModemControlGet \ UARTModemControlGet #endif #ifdef ROM_UARTModemStatusGet #define MAP_UARTModemStatusGet \ ROM_UARTModemStatusGet #else #define MAP_UARTModemStatusGet \ UARTModemStatusGet #endif #ifdef ROM_UARTFlowControlSet #define MAP_UARTFlowControlSet \ ROM_UARTFlowControlSet #else #define MAP_UARTFlowControlSet \ UARTFlowControlSet #endif #ifdef ROM_UARTFlowControlGet #define MAP_UARTFlowControlGet \ ROM_UARTFlowControlGet #else #define MAP_UARTFlowControlGet \ UARTFlowControlGet #endif #ifdef ROM_UARTTxIntModeSet #define MAP_UARTTxIntModeSet \ ROM_UARTTxIntModeSet #else #define MAP_UARTTxIntModeSet \ UARTTxIntModeSet #endif #ifdef ROM_UARTTxIntModeGet #define MAP_UARTTxIntModeGet \ ROM_UARTTxIntModeGet #else #define MAP_UARTTxIntModeGet \ UARTTxIntModeGet #endif //***************************************************************************** // // Macros for the uDMA API. // //***************************************************************************** #ifdef ROM_uDMAChannelTransferSet #define MAP_uDMAChannelTransferSet \ ROM_uDMAChannelTransferSet #else #define MAP_uDMAChannelTransferSet \ uDMAChannelTransferSet #endif #ifdef ROM_uDMAEnable #define MAP_uDMAEnable \ ROM_uDMAEnable #else #define MAP_uDMAEnable \ uDMAEnable #endif #ifdef ROM_uDMADisable #define MAP_uDMADisable \ ROM_uDMADisable #else #define MAP_uDMADisable \ uDMADisable #endif #ifdef ROM_uDMAErrorStatusGet #define MAP_uDMAErrorStatusGet \ ROM_uDMAErrorStatusGet #else #define MAP_uDMAErrorStatusGet \ uDMAErrorStatusGet #endif #ifdef ROM_uDMAErrorStatusClear #define MAP_uDMAErrorStatusClear \ ROM_uDMAErrorStatusClear #else #define MAP_uDMAErrorStatusClear \ uDMAErrorStatusClear #endif #ifdef ROM_uDMAChannelEnable #define MAP_uDMAChannelEnable \ ROM_uDMAChannelEnable #else #define MAP_uDMAChannelEnable \ uDMAChannelEnable #endif #ifdef ROM_uDMAChannelDisable #define MAP_uDMAChannelDisable \ ROM_uDMAChannelDisable #else #define MAP_uDMAChannelDisable \ uDMAChannelDisable #endif #ifdef ROM_uDMAChannelIsEnabled #define MAP_uDMAChannelIsEnabled \ ROM_uDMAChannelIsEnabled #else #define MAP_uDMAChannelIsEnabled \ uDMAChannelIsEnabled #endif #ifdef ROM_uDMAControlBaseSet #define MAP_uDMAControlBaseSet \ ROM_uDMAControlBaseSet #else #define MAP_uDMAControlBaseSet \ uDMAControlBaseSet #endif #ifdef ROM_uDMAControlBaseGet #define MAP_uDMAControlBaseGet \ ROM_uDMAControlBaseGet #else #define MAP_uDMAControlBaseGet \ uDMAControlBaseGet #endif #ifdef ROM_uDMAChannelRequest #define MAP_uDMAChannelRequest \ ROM_uDMAChannelRequest #else #define MAP_uDMAChannelRequest \ uDMAChannelRequest #endif #ifdef ROM_uDMAChannelAttributeEnable #define MAP_uDMAChannelAttributeEnable \ ROM_uDMAChannelAttributeEnable #else #define MAP_uDMAChannelAttributeEnable \ uDMAChannelAttributeEnable #endif #ifdef ROM_uDMAChannelAttributeDisable #define MAP_uDMAChannelAttributeDisable \ ROM_uDMAChannelAttributeDisable #else #define MAP_uDMAChannelAttributeDisable \ uDMAChannelAttributeDisable #endif #ifdef ROM_uDMAChannelAttributeGet #define MAP_uDMAChannelAttributeGet \ ROM_uDMAChannelAttributeGet #else #define MAP_uDMAChannelAttributeGet \ uDMAChannelAttributeGet #endif #ifdef ROM_uDMAChannelControlSet #define MAP_uDMAChannelControlSet \ ROM_uDMAChannelControlSet #else #define MAP_uDMAChannelControlSet \ uDMAChannelControlSet #endif #ifdef ROM_uDMAChannelSizeGet #define MAP_uDMAChannelSizeGet \ ROM_uDMAChannelSizeGet #else #define MAP_uDMAChannelSizeGet \ uDMAChannelSizeGet #endif #ifdef ROM_uDMAChannelModeGet #define MAP_uDMAChannelModeGet \ ROM_uDMAChannelModeGet #else #define MAP_uDMAChannelModeGet \ uDMAChannelModeGet #endif #ifdef ROM_uDMAIntStatus #define MAP_uDMAIntStatus \ ROM_uDMAIntStatus #else #define MAP_uDMAIntStatus \ uDMAIntStatus #endif #ifdef ROM_uDMAIntClear #define MAP_uDMAIntClear \ ROM_uDMAIntClear #else #define MAP_uDMAIntClear \ uDMAIntClear #endif #ifdef ROM_uDMAControlAlternateBaseGet #define MAP_uDMAControlAlternateBaseGet \ ROM_uDMAControlAlternateBaseGet #else #define MAP_uDMAControlAlternateBaseGet \ uDMAControlAlternateBaseGet #endif #ifdef ROM_uDMAChannelScatterGatherSet #define MAP_uDMAChannelScatterGatherSet \ ROM_uDMAChannelScatterGatherSet #else #define MAP_uDMAChannelScatterGatherSet \ uDMAChannelScatterGatherSet #endif #ifdef ROM_uDMAChannelAssign #define MAP_uDMAChannelAssign \ ROM_uDMAChannelAssign #else #define MAP_uDMAChannelAssign \ uDMAChannelAssign #endif #ifdef ROM_uDMAIntRegister #define MAP_uDMAIntRegister \ ROM_uDMAIntRegister #else #define MAP_uDMAIntRegister \ uDMAIntRegister #endif #ifdef ROM_uDMAIntUnregister #define MAP_uDMAIntUnregister \ ROM_uDMAIntUnregister #else #define MAP_uDMAIntUnregister \ uDMAIntUnregister #endif //***************************************************************************** // // Macros for the Watchdog API. // //***************************************************************************** #ifdef ROM_WatchdogIntClear #define MAP_WatchdogIntClear \ ROM_WatchdogIntClear #else #define MAP_WatchdogIntClear \ WatchdogIntClear #endif #ifdef ROM_WatchdogRunning #define MAP_WatchdogRunning \ ROM_WatchdogRunning #else #define MAP_WatchdogRunning \ WatchdogRunning #endif #ifdef ROM_WatchdogEnable #define MAP_WatchdogEnable \ ROM_WatchdogEnable #else #define MAP_WatchdogEnable \ WatchdogEnable #endif #ifdef ROM_WatchdogLock #define MAP_WatchdogLock \ ROM_WatchdogLock #else #define MAP_WatchdogLock \ WatchdogLock #endif #ifdef ROM_WatchdogUnlock #define MAP_WatchdogUnlock \ ROM_WatchdogUnlock #else #define MAP_WatchdogUnlock \ WatchdogUnlock #endif #ifdef ROM_WatchdogLockState #define MAP_WatchdogLockState \ ROM_WatchdogLockState #else #define MAP_WatchdogLockState \ WatchdogLockState #endif #ifdef ROM_WatchdogReloadSet #define MAP_WatchdogReloadSet \ ROM_WatchdogReloadSet #else #define MAP_WatchdogReloadSet \ WatchdogReloadSet #endif #ifdef ROM_WatchdogReloadGet #define MAP_WatchdogReloadGet \ ROM_WatchdogReloadGet #else #define MAP_WatchdogReloadGet \ WatchdogReloadGet #endif #ifdef ROM_WatchdogValueGet #define MAP_WatchdogValueGet \ ROM_WatchdogValueGet #else #define MAP_WatchdogValueGet \ WatchdogValueGet #endif #ifdef ROM_WatchdogIntStatus #define MAP_WatchdogIntStatus \ ROM_WatchdogIntStatus #else #define MAP_WatchdogIntStatus \ WatchdogIntStatus #endif #ifdef ROM_WatchdogStallEnable #define MAP_WatchdogStallEnable \ ROM_WatchdogStallEnable #else #define MAP_WatchdogStallEnable \ WatchdogStallEnable #endif #ifdef ROM_WatchdogStallDisable #define MAP_WatchdogStallDisable \ ROM_WatchdogStallDisable #else #define MAP_WatchdogStallDisable \ WatchdogStallDisable #endif #ifdef ROM_WatchdogIntRegister #define MAP_WatchdogIntRegister \ ROM_WatchdogIntRegister #else #define MAP_WatchdogIntRegister \ WatchdogIntRegister #endif #ifdef ROM_WatchdogIntUnregister #define MAP_WatchdogIntUnregister \ ROM_WatchdogIntUnregister #else #define MAP_WatchdogIntUnregister \ WatchdogIntUnregister #endif //***************************************************************************** // // Macros for the I2C API. // //***************************************************************************** #ifdef ROM_I2CIntRegister #define MAP_I2CIntRegister \ ROM_I2CIntRegister #else #define MAP_I2CIntRegister \ I2CIntRegister #endif #ifdef ROM_I2CIntUnregister #define MAP_I2CIntUnregister \ ROM_I2CIntUnregister #else #define MAP_I2CIntUnregister \ I2CIntUnregister #endif #ifdef ROM_I2CTxFIFOConfigSet #define MAP_I2CTxFIFOConfigSet \ ROM_I2CTxFIFOConfigSet #else #define MAP_I2CTxFIFOConfigSet \ I2CTxFIFOConfigSet #endif #ifdef ROM_I2CTxFIFOFlush #define MAP_I2CTxFIFOFlush \ ROM_I2CTxFIFOFlush #else #define MAP_I2CTxFIFOFlush \ I2CTxFIFOFlush #endif #ifdef ROM_I2CRxFIFOConfigSet #define MAP_I2CRxFIFOConfigSet \ ROM_I2CRxFIFOConfigSet #else #define MAP_I2CRxFIFOConfigSet \ I2CRxFIFOConfigSet #endif #ifdef ROM_I2CRxFIFOFlush #define MAP_I2CRxFIFOFlush \ ROM_I2CRxFIFOFlush #else #define MAP_I2CRxFIFOFlush \ I2CRxFIFOFlush #endif #ifdef ROM_I2CFIFOStatus #define MAP_I2CFIFOStatus \ ROM_I2CFIFOStatus #else #define MAP_I2CFIFOStatus \ I2CFIFOStatus #endif #ifdef ROM_I2CFIFODataPut #define MAP_I2CFIFODataPut \ ROM_I2CFIFODataPut #else #define MAP_I2CFIFODataPut \ I2CFIFODataPut #endif #ifdef ROM_I2CFIFODataPutNonBlocking #define MAP_I2CFIFODataPutNonBlocking \ ROM_I2CFIFODataPutNonBlocking #else #define MAP_I2CFIFODataPutNonBlocking \ I2CFIFODataPutNonBlocking #endif #ifdef ROM_I2CFIFODataGet #define MAP_I2CFIFODataGet \ ROM_I2CFIFODataGet #else #define MAP_I2CFIFODataGet \ I2CFIFODataGet #endif #ifdef ROM_I2CFIFODataGetNonBlocking #define MAP_I2CFIFODataGetNonBlocking \ ROM_I2CFIFODataGetNonBlocking #else #define MAP_I2CFIFODataGetNonBlocking \ I2CFIFODataGetNonBlocking #endif #ifdef ROM_I2CMasterBurstLengthSet #define MAP_I2CMasterBurstLengthSet \ ROM_I2CMasterBurstLengthSet #else #define MAP_I2CMasterBurstLengthSet \ I2CMasterBurstLengthSet #endif #ifdef ROM_I2CMasterBurstCountGet #define MAP_I2CMasterBurstCountGet \ ROM_I2CMasterBurstCountGet #else #define MAP_I2CMasterBurstCountGet \ I2CMasterBurstCountGet #endif #ifdef ROM_I2CMasterGlitchFilterConfigSet #define MAP_I2CMasterGlitchFilterConfigSet \ ROM_I2CMasterGlitchFilterConfigSet #else #define MAP_I2CMasterGlitchFilterConfigSet \ I2CMasterGlitchFilterConfigSet #endif #ifdef ROM_I2CSlaveFIFOEnable #define MAP_I2CSlaveFIFOEnable \ ROM_I2CSlaveFIFOEnable #else #define MAP_I2CSlaveFIFOEnable \ I2CSlaveFIFOEnable #endif #ifdef ROM_I2CSlaveFIFODisable #define MAP_I2CSlaveFIFODisable \ ROM_I2CSlaveFIFODisable #else #define MAP_I2CSlaveFIFODisable \ I2CSlaveFIFODisable #endif #ifdef ROM_I2CMasterBusBusy #define MAP_I2CMasterBusBusy \ ROM_I2CMasterBusBusy #else #define MAP_I2CMasterBusBusy \ I2CMasterBusBusy #endif #ifdef ROM_I2CMasterBusy #define MAP_I2CMasterBusy \ ROM_I2CMasterBusy #else #define MAP_I2CMasterBusy \ I2CMasterBusy #endif #ifdef ROM_I2CMasterControl #define MAP_I2CMasterControl \ ROM_I2CMasterControl #else #define MAP_I2CMasterControl \ I2CMasterControl #endif #ifdef ROM_I2CMasterDataGet #define MAP_I2CMasterDataGet \ ROM_I2CMasterDataGet #else #define MAP_I2CMasterDataGet \ I2CMasterDataGet #endif #ifdef ROM_I2CMasterDataPut #define MAP_I2CMasterDataPut \ ROM_I2CMasterDataPut #else #define MAP_I2CMasterDataPut \ I2CMasterDataPut #endif #ifdef ROM_I2CMasterDisable #define MAP_I2CMasterDisable \ ROM_I2CMasterDisable #else #define MAP_I2CMasterDisable \ I2CMasterDisable #endif #ifdef ROM_I2CMasterEnable #define MAP_I2CMasterEnable \ ROM_I2CMasterEnable #else #define MAP_I2CMasterEnable \ I2CMasterEnable #endif #ifdef ROM_I2CMasterErr #define MAP_I2CMasterErr \ ROM_I2CMasterErr #else #define MAP_I2CMasterErr \ I2CMasterErr #endif #ifdef ROM_I2CMasterIntClear #define MAP_I2CMasterIntClear \ ROM_I2CMasterIntClear #else #define MAP_I2CMasterIntClear \ I2CMasterIntClear #endif #ifdef ROM_I2CMasterIntDisable #define MAP_I2CMasterIntDisable \ ROM_I2CMasterIntDisable #else #define MAP_I2CMasterIntDisable \ I2CMasterIntDisable #endif #ifdef ROM_I2CMasterIntEnable #define MAP_I2CMasterIntEnable \ ROM_I2CMasterIntEnable #else #define MAP_I2CMasterIntEnable \ I2CMasterIntEnable #endif #ifdef ROM_I2CMasterIntStatus #define MAP_I2CMasterIntStatus \ ROM_I2CMasterIntStatus #else #define MAP_I2CMasterIntStatus \ I2CMasterIntStatus #endif #ifdef ROM_I2CMasterIntEnableEx #define MAP_I2CMasterIntEnableEx \ ROM_I2CMasterIntEnableEx #else #define MAP_I2CMasterIntEnableEx \ I2CMasterIntEnableEx #endif #ifdef ROM_I2CMasterIntDisableEx #define MAP_I2CMasterIntDisableEx \ ROM_I2CMasterIntDisableEx #else #define MAP_I2CMasterIntDisableEx \ I2CMasterIntDisableEx #endif #ifdef ROM_I2CMasterIntStatusEx #define MAP_I2CMasterIntStatusEx \ ROM_I2CMasterIntStatusEx #else #define MAP_I2CMasterIntStatusEx \ I2CMasterIntStatusEx #endif #ifdef ROM_I2CMasterIntClearEx #define MAP_I2CMasterIntClearEx \ ROM_I2CMasterIntClearEx #else #define MAP_I2CMasterIntClearEx \ I2CMasterIntClearEx #endif #ifdef ROM_I2CMasterTimeoutSet #define MAP_I2CMasterTimeoutSet \ ROM_I2CMasterTimeoutSet #else #define MAP_I2CMasterTimeoutSet \ I2CMasterTimeoutSet #endif #ifdef ROM_I2CSlaveACKOverride #define MAP_I2CSlaveACKOverride \ ROM_I2CSlaveACKOverride #else #define MAP_I2CSlaveACKOverride \ I2CSlaveACKOverride #endif #ifdef ROM_I2CSlaveACKValueSet #define MAP_I2CSlaveACKValueSet \ ROM_I2CSlaveACKValueSet #else #define MAP_I2CSlaveACKValueSet \ I2CSlaveACKValueSet #endif #ifdef ROM_I2CMasterLineStateGet #define MAP_I2CMasterLineStateGet \ ROM_I2CMasterLineStateGet #else #define MAP_I2CMasterLineStateGet \ I2CMasterLineStateGet #endif #ifdef ROM_I2CMasterSlaveAddrSet #define MAP_I2CMasterSlaveAddrSet \ ROM_I2CMasterSlaveAddrSet #else #define MAP_I2CMasterSlaveAddrSet \ I2CMasterSlaveAddrSet #endif #ifdef ROM_I2CSlaveDataGet #define MAP_I2CSlaveDataGet \ ROM_I2CSlaveDataGet #else #define MAP_I2CSlaveDataGet \ I2CSlaveDataGet #endif #ifdef ROM_I2CSlaveDataPut #define MAP_I2CSlaveDataPut \ ROM_I2CSlaveDataPut #else #define MAP_I2CSlaveDataPut \ I2CSlaveDataPut #endif #ifdef ROM_I2CSlaveDisable #define MAP_I2CSlaveDisable \ ROM_I2CSlaveDisable #else #define MAP_I2CSlaveDisable \ I2CSlaveDisable #endif #ifdef ROM_I2CSlaveEnable #define MAP_I2CSlaveEnable \ ROM_I2CSlaveEnable #else #define MAP_I2CSlaveEnable \ I2CSlaveEnable #endif #ifdef ROM_I2CSlaveInit #define MAP_I2CSlaveInit \ ROM_I2CSlaveInit #else #define MAP_I2CSlaveInit \ I2CSlaveInit #endif #ifdef ROM_I2CSlaveAddressSet #define MAP_I2CSlaveAddressSet \ ROM_I2CSlaveAddressSet #else #define MAP_I2CSlaveAddressSet \ I2CSlaveAddressSet #endif #ifdef ROM_I2CSlaveIntClear #define MAP_I2CSlaveIntClear \ ROM_I2CSlaveIntClear #else #define MAP_I2CSlaveIntClear \ I2CSlaveIntClear #endif #ifdef ROM_I2CSlaveIntDisable #define MAP_I2CSlaveIntDisable \ ROM_I2CSlaveIntDisable #else #define MAP_I2CSlaveIntDisable \ I2CSlaveIntDisable #endif #ifdef ROM_I2CSlaveIntEnable #define MAP_I2CSlaveIntEnable \ ROM_I2CSlaveIntEnable #else #define MAP_I2CSlaveIntEnable \ I2CSlaveIntEnable #endif #ifdef ROM_I2CSlaveIntClearEx #define MAP_I2CSlaveIntClearEx \ ROM_I2CSlaveIntClearEx #else #define MAP_I2CSlaveIntClearEx \ I2CSlaveIntClearEx #endif #ifdef ROM_I2CSlaveIntDisableEx #define MAP_I2CSlaveIntDisableEx \ ROM_I2CSlaveIntDisableEx #else #define MAP_I2CSlaveIntDisableEx \ I2CSlaveIntDisableEx #endif #ifdef ROM_I2CSlaveIntEnableEx #define MAP_I2CSlaveIntEnableEx \ ROM_I2CSlaveIntEnableEx #else #define MAP_I2CSlaveIntEnableEx \ I2CSlaveIntEnableEx #endif #ifdef ROM_I2CSlaveIntStatus #define MAP_I2CSlaveIntStatus \ ROM_I2CSlaveIntStatus #else #define MAP_I2CSlaveIntStatus \ I2CSlaveIntStatus #endif #ifdef ROM_I2CSlaveIntStatusEx #define MAP_I2CSlaveIntStatusEx \ ROM_I2CSlaveIntStatusEx #else #define MAP_I2CSlaveIntStatusEx \ I2CSlaveIntStatusEx #endif #ifdef ROM_I2CSlaveStatus #define MAP_I2CSlaveStatus \ ROM_I2CSlaveStatus #else #define MAP_I2CSlaveStatus \ I2CSlaveStatus #endif #ifdef ROM_I2CMasterInitExpClk #define MAP_I2CMasterInitExpClk \ ROM_I2CMasterInitExpClk #else #define MAP_I2CMasterInitExpClk \ I2CMasterInitExpClk #endif //***************************************************************************** // // Macros for the SPI API. // //***************************************************************************** #ifdef ROM_SPIEnable #define MAP_SPIEnable \ ROM_SPIEnable #else #define MAP_SPIEnable \ SPIEnable #endif #ifdef ROM_SPIDisable #define MAP_SPIDisable \ ROM_SPIDisable #else #define MAP_SPIDisable \ SPIDisable #endif #ifdef ROM_SPIReset #define MAP_SPIReset \ ROM_SPIReset #else #define MAP_SPIReset \ SPIReset #endif #ifdef ROM_SPIConfigSetExpClk #define MAP_SPIConfigSetExpClk \ ROM_SPIConfigSetExpClk #else #define MAP_SPIConfigSetExpClk \ SPIConfigSetExpClk #endif #ifdef ROM_SPIDataGetNonBlocking #define MAP_SPIDataGetNonBlocking \ ROM_SPIDataGetNonBlocking #else #define MAP_SPIDataGetNonBlocking \ SPIDataGetNonBlocking #endif #ifdef ROM_SPIDataGet #define MAP_SPIDataGet \ ROM_SPIDataGet #else #define MAP_SPIDataGet \ SPIDataGet #endif #ifdef ROM_SPIDataPutNonBlocking #define MAP_SPIDataPutNonBlocking \ ROM_SPIDataPutNonBlocking #else #define MAP_SPIDataPutNonBlocking \ SPIDataPutNonBlocking #endif #ifdef ROM_SPIDataPut #define MAP_SPIDataPut \ ROM_SPIDataPut #else #define MAP_SPIDataPut \ SPIDataPut #endif #ifdef ROM_SPIFIFOEnable #define MAP_SPIFIFOEnable \ ROM_SPIFIFOEnable #else #define MAP_SPIFIFOEnable \ SPIFIFOEnable #endif #ifdef ROM_SPIFIFODisable #define MAP_SPIFIFODisable \ ROM_SPIFIFODisable #else #define MAP_SPIFIFODisable \ SPIFIFODisable #endif #ifdef ROM_SPIFIFOLevelSet #define MAP_SPIFIFOLevelSet \ ROM_SPIFIFOLevelSet #else #define MAP_SPIFIFOLevelSet \ SPIFIFOLevelSet #endif #ifdef ROM_SPIFIFOLevelGet #define MAP_SPIFIFOLevelGet \ ROM_SPIFIFOLevelGet #else #define MAP_SPIFIFOLevelGet \ SPIFIFOLevelGet #endif #ifdef ROM_SPIWordCountSet #define MAP_SPIWordCountSet \ ROM_SPIWordCountSet #else #define MAP_SPIWordCountSet \ SPIWordCountSet #endif #ifdef ROM_SPIIntRegister #define MAP_SPIIntRegister \ ROM_SPIIntRegister #else #define MAP_SPIIntRegister \ SPIIntRegister #endif #ifdef ROM_SPIIntUnregister #define MAP_SPIIntUnregister \ ROM_SPIIntUnregister #else #define MAP_SPIIntUnregister \ SPIIntUnregister #endif #ifdef ROM_SPIIntEnable #define MAP_SPIIntEnable \ ROM_SPIIntEnable #else #define MAP_SPIIntEnable \ SPIIntEnable #endif #ifdef ROM_SPIIntDisable #define MAP_SPIIntDisable \ ROM_SPIIntDisable #else #define MAP_SPIIntDisable \ SPIIntDisable #endif #ifdef ROM_SPIIntStatus #define MAP_SPIIntStatus \ ROM_SPIIntStatus #else #define MAP_SPIIntStatus \ SPIIntStatus #endif #ifdef ROM_SPIIntClear #define MAP_SPIIntClear \ ROM_SPIIntClear #else #define MAP_SPIIntClear \ SPIIntClear #endif #ifdef ROM_SPIDmaEnable #define MAP_SPIDmaEnable \ ROM_SPIDmaEnable #else #define MAP_SPIDmaEnable \ SPIDmaEnable #endif #ifdef ROM_SPIDmaDisable #define MAP_SPIDmaDisable \ ROM_SPIDmaDisable #else #define MAP_SPIDmaDisable \ SPIDmaDisable #endif #ifdef ROM_SPICSEnable #define MAP_SPICSEnable \ ROM_SPICSEnable #else #define MAP_SPICSEnable \ SPICSEnable #endif #ifdef ROM_SPICSDisable #define MAP_SPICSDisable \ ROM_SPICSDisable #else #define MAP_SPICSDisable \ SPICSDisable #endif #ifdef ROM_SPITransfer #define MAP_SPITransfer \ ROM_SPITransfer #else #define MAP_SPITransfer \ SPITransfer #endif //***************************************************************************** // // Macros for the CAM API. // //***************************************************************************** #ifdef ROM_CameraReset #define MAP_CameraReset \ ROM_CameraReset #else #define MAP_CameraReset \ CameraReset #endif #ifdef ROM_CameraParamsConfig #define MAP_CameraParamsConfig \ ROM_CameraParamsConfig #else #define MAP_CameraParamsConfig \ CameraParamsConfig #endif #ifdef ROM_CameraXClkConfig #define MAP_CameraXClkConfig \ ROM_CameraXClkConfig #else #define MAP_CameraXClkConfig \ CameraXClkConfig #endif #ifdef ROM_CameraXClkSet #define MAP_CameraXClkSet \ ROM_CameraXClkSet #else #define MAP_CameraXClkSet \ CameraXClkSet #endif #ifdef ROM_CameraDMAEnable #define MAP_CameraDMAEnable \ ROM_CameraDMAEnable #else #define MAP_CameraDMAEnable \ CameraDMAEnable #endif #ifdef ROM_CameraDMADisable #define MAP_CameraDMADisable \ ROM_CameraDMADisable #else #define MAP_CameraDMADisable \ CameraDMADisable #endif #ifdef ROM_CameraThresholdSet #define MAP_CameraThresholdSet \ ROM_CameraThresholdSet #else #define MAP_CameraThresholdSet \ CameraThresholdSet #endif #ifdef ROM_CameraIntRegister #define MAP_CameraIntRegister \ ROM_CameraIntRegister #else #define MAP_CameraIntRegister \ CameraIntRegister #endif #ifdef ROM_CameraIntUnregister #define MAP_CameraIntUnregister \ ROM_CameraIntUnregister #else #define MAP_CameraIntUnregister \ CameraIntUnregister #endif #ifdef ROM_CameraIntEnable #define MAP_CameraIntEnable \ ROM_CameraIntEnable #else #define MAP_CameraIntEnable \ CameraIntEnable #endif #ifdef ROM_CameraIntDisable #define MAP_CameraIntDisable \ ROM_CameraIntDisable #else #define MAP_CameraIntDisable \ CameraIntDisable #endif #ifdef ROM_CameraIntStatus #define MAP_CameraIntStatus \ ROM_CameraIntStatus #else #define MAP_CameraIntStatus \ CameraIntStatus #endif #ifdef ROM_CameraIntClear #define MAP_CameraIntClear \ ROM_CameraIntClear #else #define MAP_CameraIntClear \ CameraIntClear #endif #ifdef ROM_CameraCaptureStop #define MAP_CameraCaptureStop \ ROM_CameraCaptureStop #else #define MAP_CameraCaptureStop \ CameraCaptureStop #endif #ifdef ROM_CameraCaptureStart #define MAP_CameraCaptureStart \ ROM_CameraCaptureStart #else #define MAP_CameraCaptureStart \ CameraCaptureStart #endif #ifdef ROM_CameraBufferRead #define MAP_CameraBufferRead \ ROM_CameraBufferRead #else #define MAP_CameraBufferRead \ CameraBufferRead #endif //***************************************************************************** // // Macros for the FLASH API. // //***************************************************************************** #ifdef ROM_FlashDisable #define MAP_FlashDisable \ ROM_FlashDisable #else #define MAP_FlashDisable \ FlashDisable #endif #ifdef ROM_FlashErase #define MAP_FlashErase \ ROM_FlashErase #else #define MAP_FlashErase \ FlashErase #endif #ifdef ROM_FlashMassErase #define MAP_FlashMassErase \ ROM_FlashMassErase #else #define MAP_FlashMassErase \ FlashMassErase #endif #ifdef ROM_FlashMassEraseNonBlocking #define MAP_FlashMassEraseNonBlocking \ ROM_FlashMassEraseNonBlocking #else #define MAP_FlashMassEraseNonBlocking \ FlashMassEraseNonBlocking #endif #ifdef ROM_FlashEraseNonBlocking #define MAP_FlashEraseNonBlocking \ ROM_FlashEraseNonBlocking #else #define MAP_FlashEraseNonBlocking \ FlashEraseNonBlocking #endif #ifdef ROM_FlashProgram #define MAP_FlashProgram \ ROM_FlashProgram #else #define MAP_FlashProgram \ FlashProgram #endif #ifdef ROM_FlashProgramNonBlocking #define MAP_FlashProgramNonBlocking \ ROM_FlashProgramNonBlocking #else #define MAP_FlashProgramNonBlocking \ FlashProgramNonBlocking #endif #ifdef ROM_FlashIntRegister #define MAP_FlashIntRegister \ ROM_FlashIntRegister #else #define MAP_FlashIntRegister \ FlashIntRegister #endif #ifdef ROM_FlashIntUnregister #define MAP_FlashIntUnregister \ ROM_FlashIntUnregister #else #define MAP_FlashIntUnregister \ FlashIntUnregister #endif #ifdef ROM_FlashIntEnable #define MAP_FlashIntEnable \ ROM_FlashIntEnable #else #define MAP_FlashIntEnable \ FlashIntEnable #endif #ifdef ROM_FlashIntDisable #define MAP_FlashIntDisable \ ROM_FlashIntDisable #else #define MAP_FlashIntDisable \ FlashIntDisable #endif #ifdef ROM_FlashIntStatus #define MAP_FlashIntStatus \ ROM_FlashIntStatus #else #define MAP_FlashIntStatus \ FlashIntStatus #endif #ifdef ROM_FlashIntClear #define MAP_FlashIntClear \ ROM_FlashIntClear #else #define MAP_FlashIntClear \ FlashIntClear #endif #ifdef ROM_FlashProtectGet #define MAP_FlashProtectGet \ ROM_FlashProtectGet #else #define MAP_FlashProtectGet \ FlashProtectGet #endif //***************************************************************************** // // Macros for the Pin API. // //***************************************************************************** #ifdef ROM_PinModeSet #define MAP_PinModeSet \ ROM_PinModeSet #else #define MAP_PinModeSet \ PinModeSet #endif #ifdef ROM_PinDirModeSet #define MAP_PinDirModeSet \ ROM_PinDirModeSet #else #define MAP_PinDirModeSet \ PinDirModeSet #endif #ifdef ROM_PinDirModeGet #define MAP_PinDirModeGet \ ROM_PinDirModeGet #else #define MAP_PinDirModeGet \ PinDirModeGet #endif #ifdef ROM_PinModeGet #define MAP_PinModeGet \ ROM_PinModeGet #else #define MAP_PinModeGet \ PinModeGet #endif #ifdef ROM_PinConfigGet #define MAP_PinConfigGet \ ROM_PinConfigGet #else #define MAP_PinConfigGet \ PinConfigGet #endif #ifdef ROM_PinConfigSet #define MAP_PinConfigSet \ ROM_PinConfigSet #else #define MAP_PinConfigSet \ PinConfigSet #endif #ifdef ROM_PinTypeUART #define MAP_PinTypeUART \ ROM_PinTypeUART #else #define MAP_PinTypeUART \ PinTypeUART #endif #ifdef ROM_PinTypeI2C #define MAP_PinTypeI2C \ ROM_PinTypeI2C #else #define MAP_PinTypeI2C \ PinTypeI2C #endif #ifdef ROM_PinTypeSPI #define MAP_PinTypeSPI \ ROM_PinTypeSPI #else #define MAP_PinTypeSPI \ PinTypeSPI #endif #ifdef ROM_PinTypeI2S #define MAP_PinTypeI2S \ ROM_PinTypeI2S #else #define MAP_PinTypeI2S \ PinTypeI2S #endif #ifdef ROM_PinTypeTimer #define MAP_PinTypeTimer \ ROM_PinTypeTimer #else #define MAP_PinTypeTimer \ PinTypeTimer #endif #ifdef ROM_PinTypeCamera #define MAP_PinTypeCamera \ ROM_PinTypeCamera #else #define MAP_PinTypeCamera \ PinTypeCamera #endif #ifdef ROM_PinTypeGPIO #define MAP_PinTypeGPIO \ ROM_PinTypeGPIO #else #define MAP_PinTypeGPIO \ PinTypeGPIO #endif #ifdef ROM_PinTypeADC #define MAP_PinTypeADC \ ROM_PinTypeADC #else #define MAP_PinTypeADC \ PinTypeADC #endif #ifdef ROM_PinTypeSDHost #define MAP_PinTypeSDHost \ ROM_PinTypeSDHost #else #define MAP_PinTypeSDHost \ PinTypeSDHost #endif //***************************************************************************** // // Macros for the SYSTICK API. // //***************************************************************************** #ifdef ROM_SysTickEnable #define MAP_SysTickEnable \ ROM_SysTickEnable #else #define MAP_SysTickEnable \ SysTickEnable #endif #ifdef ROM_SysTickDisable #define MAP_SysTickDisable \ ROM_SysTickDisable #else #define MAP_SysTickDisable \ SysTickDisable #endif #ifdef ROM_SysTickIntRegister #define MAP_SysTickIntRegister \ ROM_SysTickIntRegister #else #define MAP_SysTickIntRegister \ SysTickIntRegister #endif #ifdef ROM_SysTickIntUnregister #define MAP_SysTickIntUnregister \ ROM_SysTickIntUnregister #else #define MAP_SysTickIntUnregister \ SysTickIntUnregister #endif #ifdef ROM_SysTickIntEnable #define MAP_SysTickIntEnable \ ROM_SysTickIntEnable #else #define MAP_SysTickIntEnable \ SysTickIntEnable #endif #ifdef ROM_SysTickIntDisable #define MAP_SysTickIntDisable \ ROM_SysTickIntDisable #else #define MAP_SysTickIntDisable \ SysTickIntDisable #endif #ifdef ROM_SysTickPeriodSet #define MAP_SysTickPeriodSet \ ROM_SysTickPeriodSet #else #define MAP_SysTickPeriodSet \ SysTickPeriodSet #endif #ifdef ROM_SysTickPeriodGet #define MAP_SysTickPeriodGet \ ROM_SysTickPeriodGet #else #define MAP_SysTickPeriodGet \ SysTickPeriodGet #endif #ifdef ROM_SysTickValueGet #define MAP_SysTickValueGet \ ROM_SysTickValueGet #else #define MAP_SysTickValueGet \ SysTickValueGet #endif //***************************************************************************** // // Macros for the UTILS API. // //***************************************************************************** #ifdef ROM_UtilsDelay #define MAP_UtilsDelay \ ROM_UtilsDelay #else #define MAP_UtilsDelay \ UtilsDelay #endif //***************************************************************************** // // Macros for the I2S API. // //***************************************************************************** #ifdef ROM_I2SEnable #define MAP_I2SEnable \ ROM_I2SEnable #else #define MAP_I2SEnable \ I2SEnable #endif #ifdef ROM_I2SDisable #define MAP_I2SDisable \ ROM_I2SDisable #else #define MAP_I2SDisable \ I2SDisable #endif #ifdef ROM_I2SDataPut #define MAP_I2SDataPut \ ROM_I2SDataPut #else #define MAP_I2SDataPut \ I2SDataPut #endif #ifdef ROM_I2SDataPutNonBlocking #define MAP_I2SDataPutNonBlocking \ ROM_I2SDataPutNonBlocking #else #define MAP_I2SDataPutNonBlocking \ I2SDataPutNonBlocking #endif #ifdef ROM_I2SDataGet #define MAP_I2SDataGet \ ROM_I2SDataGet #else #define MAP_I2SDataGet \ I2SDataGet #endif #ifdef ROM_I2SDataGetNonBlocking #define MAP_I2SDataGetNonBlocking \ ROM_I2SDataGetNonBlocking #else #define MAP_I2SDataGetNonBlocking \ I2SDataGetNonBlocking #endif #ifdef ROM_I2SConfigSetExpClk #define MAP_I2SConfigSetExpClk \ ROM_I2SConfigSetExpClk #else #define MAP_I2SConfigSetExpClk \ I2SConfigSetExpClk #endif #ifdef ROM_I2STxFIFOEnable #define MAP_I2STxFIFOEnable \ ROM_I2STxFIFOEnable #else #define MAP_I2STxFIFOEnable \ I2STxFIFOEnable #endif #ifdef ROM_I2STxFIFODisable #define MAP_I2STxFIFODisable \ ROM_I2STxFIFODisable #else #define MAP_I2STxFIFODisable \ I2STxFIFODisable #endif #ifdef ROM_I2SRxFIFOEnable #define MAP_I2SRxFIFOEnable \ ROM_I2SRxFIFOEnable #else #define MAP_I2SRxFIFOEnable \ I2SRxFIFOEnable #endif #ifdef ROM_I2SRxFIFODisable #define MAP_I2SRxFIFODisable \ ROM_I2SRxFIFODisable #else #define MAP_I2SRxFIFODisable \ I2SRxFIFODisable #endif #ifdef ROM_I2STxFIFOStatusGet #define MAP_I2STxFIFOStatusGet \ ROM_I2STxFIFOStatusGet #else #define MAP_I2STxFIFOStatusGet \ I2STxFIFOStatusGet #endif #ifdef ROM_I2SRxFIFOStatusGet #define MAP_I2SRxFIFOStatusGet \ ROM_I2SRxFIFOStatusGet #else #define MAP_I2SRxFIFOStatusGet \ I2SRxFIFOStatusGet #endif #ifdef ROM_I2SSerializerConfig #define MAP_I2SSerializerConfig \ ROM_I2SSerializerConfig #else #define MAP_I2SSerializerConfig \ I2SSerializerConfig #endif #ifdef ROM_I2SIntEnable #define MAP_I2SIntEnable \ ROM_I2SIntEnable #else #define MAP_I2SIntEnable \ I2SIntEnable #endif #ifdef ROM_I2SIntDisable #define MAP_I2SIntDisable \ ROM_I2SIntDisable #else #define MAP_I2SIntDisable \ I2SIntDisable #endif #ifdef ROM_I2SIntStatus #define MAP_I2SIntStatus \ ROM_I2SIntStatus #else #define MAP_I2SIntStatus \ I2SIntStatus #endif #ifdef ROM_I2SIntClear #define MAP_I2SIntClear \ ROM_I2SIntClear #else #define MAP_I2SIntClear \ I2SIntClear #endif #ifdef ROM_I2SIntRegister #define MAP_I2SIntRegister \ ROM_I2SIntRegister #else #define MAP_I2SIntRegister \ I2SIntRegister #endif #ifdef ROM_I2SIntUnregister #define MAP_I2SIntUnregister \ ROM_I2SIntUnregister #else #define MAP_I2SIntUnregister \ I2SIntUnregister #endif //***************************************************************************** // // Macros for the GPIO API. // //***************************************************************************** #ifdef ROM_GPIODirModeSet #define MAP_GPIODirModeSet \ ROM_GPIODirModeSet #else #define MAP_GPIODirModeSet \ GPIODirModeSet #endif #ifdef ROM_GPIODirModeGet #define MAP_GPIODirModeGet \ ROM_GPIODirModeGet #else #define MAP_GPIODirModeGet \ GPIODirModeGet #endif #ifdef ROM_GPIOIntTypeSet #define MAP_GPIOIntTypeSet \ ROM_GPIOIntTypeSet #else #define MAP_GPIOIntTypeSet \ GPIOIntTypeSet #endif #ifdef ROM_GPIODMATriggerEnable #define MAP_GPIODMATriggerEnable \ ROM_GPIODMATriggerEnable #else #define MAP_GPIODMATriggerEnable \ GPIODMATriggerEnable #endif #ifdef ROM_GPIODMATriggerDisable #define MAP_GPIODMATriggerDisable \ ROM_GPIODMATriggerDisable #else #define MAP_GPIODMATriggerDisable \ GPIODMATriggerDisable #endif #ifdef ROM_GPIOIntTypeGet #define MAP_GPIOIntTypeGet \ ROM_GPIOIntTypeGet #else #define MAP_GPIOIntTypeGet \ GPIOIntTypeGet #endif #ifdef ROM_GPIOIntEnable #define MAP_GPIOIntEnable \ ROM_GPIOIntEnable #else #define MAP_GPIOIntEnable \ GPIOIntEnable #endif #ifdef ROM_GPIOIntDisable #define MAP_GPIOIntDisable \ ROM_GPIOIntDisable #else #define MAP_GPIOIntDisable \ GPIOIntDisable #endif #ifdef ROM_GPIOIntStatus #define MAP_GPIOIntStatus \ ROM_GPIOIntStatus #else #define MAP_GPIOIntStatus \ GPIOIntStatus #endif #ifdef ROM_GPIOIntClear #define MAP_GPIOIntClear \ ROM_GPIOIntClear #else #define MAP_GPIOIntClear \ GPIOIntClear #endif #ifdef ROM_GPIOIntRegister #define MAP_GPIOIntRegister \ ROM_GPIOIntRegister #else #define MAP_GPIOIntRegister \ GPIOIntRegister #endif #ifdef ROM_GPIOIntUnregister #define MAP_GPIOIntUnregister \ ROM_GPIOIntUnregister #else #define MAP_GPIOIntUnregister \ GPIOIntUnregister #endif #ifdef ROM_GPIOPinRead #define MAP_GPIOPinRead \ ROM_GPIOPinRead #else #define MAP_GPIOPinRead \ GPIOPinRead #endif #ifdef ROM_GPIOPinWrite #define MAP_GPIOPinWrite \ ROM_GPIOPinWrite #else #define MAP_GPIOPinWrite \ GPIOPinWrite #endif //***************************************************************************** // // Macros for the AES API. // //***************************************************************************** #ifdef ROM_AESConfigSet #define MAP_AESConfigSet \ ROM_AESConfigSet #else #define MAP_AESConfigSet \ AESConfigSet #endif #ifdef ROM_AESKey1Set #define MAP_AESKey1Set \ ROM_AESKey1Set #else #define MAP_AESKey1Set \ AESKey1Set #endif #ifdef ROM_AESKey2Set #define MAP_AESKey2Set \ ROM_AESKey2Set #else #define MAP_AESKey2Set \ AESKey2Set #endif #ifdef ROM_AESKey3Set #define MAP_AESKey3Set \ ROM_AESKey3Set #else #define MAP_AESKey3Set \ AESKey3Set #endif #ifdef ROM_AESIVSet #define MAP_AESIVSet \ ROM_AESIVSet #else #define MAP_AESIVSet \ AESIVSet #endif #ifdef ROM_AESTagRead #define MAP_AESTagRead \ ROM_AESTagRead #else #define MAP_AESTagRead \ AESTagRead #endif #ifdef ROM_AESDataLengthSet #define MAP_AESDataLengthSet \ ROM_AESDataLengthSet #else #define MAP_AESDataLengthSet \ AESDataLengthSet #endif #ifdef ROM_AESAuthDataLengthSet #define MAP_AESAuthDataLengthSet \ ROM_AESAuthDataLengthSet #else #define MAP_AESAuthDataLengthSet \ AESAuthDataLengthSet #endif #ifdef ROM_AESDataReadNonBlocking #define MAP_AESDataReadNonBlocking \ ROM_AESDataReadNonBlocking #else #define MAP_AESDataReadNonBlocking \ AESDataReadNonBlocking #endif #ifdef ROM_AESDataRead #define MAP_AESDataRead \ ROM_AESDataRead #else #define MAP_AESDataRead \ AESDataRead #endif #ifdef ROM_AESDataWriteNonBlocking #define MAP_AESDataWriteNonBlocking \ ROM_AESDataWriteNonBlocking #else #define MAP_AESDataWriteNonBlocking \ AESDataWriteNonBlocking #endif #ifdef ROM_AESDataWrite #define MAP_AESDataWrite \ ROM_AESDataWrite #else #define MAP_AESDataWrite \ AESDataWrite #endif #ifdef ROM_AESDataProcess #define MAP_AESDataProcess \ ROM_AESDataProcess #else #define MAP_AESDataProcess \ AESDataProcess #endif #ifdef ROM_AESDataMAC #define MAP_AESDataMAC \ ROM_AESDataMAC #else #define MAP_AESDataMAC \ AESDataMAC #endif #ifdef ROM_AESDataProcessAE #define MAP_AESDataProcessAE \ ROM_AESDataProcessAE #else #define MAP_AESDataProcessAE \ AESDataProcessAE #endif #ifdef ROM_AESIntStatus #define MAP_AESIntStatus \ ROM_AESIntStatus #else #define MAP_AESIntStatus \ AESIntStatus #endif #ifdef ROM_AESIntEnable #define MAP_AESIntEnable \ ROM_AESIntEnable #else #define MAP_AESIntEnable \ AESIntEnable #endif #ifdef ROM_AESIntDisable #define MAP_AESIntDisable \ ROM_AESIntDisable #else #define MAP_AESIntDisable \ AESIntDisable #endif #ifdef ROM_AESIntClear #define MAP_AESIntClear \ ROM_AESIntClear #else #define MAP_AESIntClear \ AESIntClear #endif #ifdef ROM_AESIntRegister #define MAP_AESIntRegister \ ROM_AESIntRegister #else #define MAP_AESIntRegister \ AESIntRegister #endif #ifdef ROM_AESIntUnregister #define MAP_AESIntUnregister \ ROM_AESIntUnregister #else #define MAP_AESIntUnregister \ AESIntUnregister #endif #ifdef ROM_AESDMAEnable #define MAP_AESDMAEnable \ ROM_AESDMAEnable #else #define MAP_AESDMAEnable \ AESDMAEnable #endif #ifdef ROM_AESDMADisable #define MAP_AESDMADisable \ ROM_AESDMADisable #else #define MAP_AESDMADisable \ AESDMADisable #endif //***************************************************************************** // // Macros for the DES API. // //***************************************************************************** #ifdef ROM_DESConfigSet #define MAP_DESConfigSet \ ROM_DESConfigSet #else #define MAP_DESConfigSet \ DESConfigSet #endif #ifdef ROM_DESDataRead #define MAP_DESDataRead \ ROM_DESDataRead #else #define MAP_DESDataRead \ DESDataRead #endif #ifdef ROM_DESDataReadNonBlocking #define MAP_DESDataReadNonBlocking \ ROM_DESDataReadNonBlocking #else #define MAP_DESDataReadNonBlocking \ DESDataReadNonBlocking #endif #ifdef ROM_DESDataProcess #define MAP_DESDataProcess \ ROM_DESDataProcess #else #define MAP_DESDataProcess \ DESDataProcess #endif #ifdef ROM_DESDataWrite #define MAP_DESDataWrite \ ROM_DESDataWrite #else #define MAP_DESDataWrite \ DESDataWrite #endif #ifdef ROM_DESDataWriteNonBlocking #define MAP_DESDataWriteNonBlocking \ ROM_DESDataWriteNonBlocking #else #define MAP_DESDataWriteNonBlocking \ DESDataWriteNonBlocking #endif #ifdef ROM_DESDMADisable #define MAP_DESDMADisable \ ROM_DESDMADisable #else #define MAP_DESDMADisable \ DESDMADisable #endif #ifdef ROM_DESDMAEnable #define MAP_DESDMAEnable \ ROM_DESDMAEnable #else #define MAP_DESDMAEnable \ DESDMAEnable #endif #ifdef ROM_DESIntClear #define MAP_DESIntClear \ ROM_DESIntClear #else #define MAP_DESIntClear \ DESIntClear #endif #ifdef ROM_DESIntDisable #define MAP_DESIntDisable \ ROM_DESIntDisable #else #define MAP_DESIntDisable \ DESIntDisable #endif #ifdef ROM_DESIntEnable #define MAP_DESIntEnable \ ROM_DESIntEnable #else #define MAP_DESIntEnable \ DESIntEnable #endif #ifdef ROM_DESIntRegister #define MAP_DESIntRegister \ ROM_DESIntRegister #else #define MAP_DESIntRegister \ DESIntRegister #endif #ifdef ROM_DESIntStatus #define MAP_DESIntStatus \ ROM_DESIntStatus #else #define MAP_DESIntStatus \ DESIntStatus #endif #ifdef ROM_DESIntUnregister #define MAP_DESIntUnregister \ ROM_DESIntUnregister #else #define MAP_DESIntUnregister \ DESIntUnregister #endif #ifdef ROM_DESIVSet #define MAP_DESIVSet \ ROM_DESIVSet #else #define MAP_DESIVSet \ DESIVSet #endif #ifdef ROM_DESKeySet #define MAP_DESKeySet \ ROM_DESKeySet #else #define MAP_DESKeySet \ DESKeySet #endif #ifdef ROM_DESDataLengthSet #define MAP_DESDataLengthSet \ ROM_DESDataLengthSet #else #define MAP_DESDataLengthSet \ DESDataLengthSet #endif //***************************************************************************** // // Macros for the SHAMD5 API. // //***************************************************************************** #ifdef ROM_SHAMD5ConfigSet #define MAP_SHAMD5ConfigSet \ ROM_SHAMD5ConfigSet #else #define MAP_SHAMD5ConfigSet \ SHAMD5ConfigSet #endif #ifdef ROM_SHAMD5DataProcess #define MAP_SHAMD5DataProcess \ ROM_SHAMD5DataProcess #else #define MAP_SHAMD5DataProcess \ SHAMD5DataProcess #endif #ifdef ROM_SHAMD5DataWrite #define MAP_SHAMD5DataWrite \ ROM_SHAMD5DataWrite #else #define MAP_SHAMD5DataWrite \ SHAMD5DataWrite #endif #ifdef ROM_SHAMD5DataWriteNonBlocking #define MAP_SHAMD5DataWriteNonBlocking \ ROM_SHAMD5DataWriteNonBlocking #else #define MAP_SHAMD5DataWriteNonBlocking \ SHAMD5DataWriteNonBlocking #endif #ifdef ROM_SHAMD5DMADisable #define MAP_SHAMD5DMADisable \ ROM_SHAMD5DMADisable #else #define MAP_SHAMD5DMADisable \ SHAMD5DMADisable #endif #ifdef ROM_SHAMD5DMAEnable #define MAP_SHAMD5DMAEnable \ ROM_SHAMD5DMAEnable #else #define MAP_SHAMD5DMAEnable \ SHAMD5DMAEnable #endif #ifdef ROM_SHAMD5DataLengthSet #define MAP_SHAMD5DataLengthSet \ ROM_SHAMD5DataLengthSet #else #define MAP_SHAMD5DataLengthSet \ SHAMD5DataLengthSet #endif #ifdef ROM_SHAMD5HMACKeySet #define MAP_SHAMD5HMACKeySet \ ROM_SHAMD5HMACKeySet #else #define MAP_SHAMD5HMACKeySet \ SHAMD5HMACKeySet #endif #ifdef ROM_SHAMD5HMACPPKeyGenerate #define MAP_SHAMD5HMACPPKeyGenerate \ ROM_SHAMD5HMACPPKeyGenerate #else #define MAP_SHAMD5HMACPPKeyGenerate \ SHAMD5HMACPPKeyGenerate #endif #ifdef ROM_SHAMD5HMACPPKeySet #define MAP_SHAMD5HMACPPKeySet \ ROM_SHAMD5HMACPPKeySet #else #define MAP_SHAMD5HMACPPKeySet \ SHAMD5HMACPPKeySet #endif #ifdef ROM_SHAMD5HMACProcess #define MAP_SHAMD5HMACProcess \ ROM_SHAMD5HMACProcess #else #define MAP_SHAMD5HMACProcess \ SHAMD5HMACProcess #endif #ifdef ROM_SHAMD5IntClear #define MAP_SHAMD5IntClear \ ROM_SHAMD5IntClear #else #define MAP_SHAMD5IntClear \ SHAMD5IntClear #endif #ifdef ROM_SHAMD5IntDisable #define MAP_SHAMD5IntDisable \ ROM_SHAMD5IntDisable #else #define MAP_SHAMD5IntDisable \ SHAMD5IntDisable #endif #ifdef ROM_SHAMD5IntEnable #define MAP_SHAMD5IntEnable \ ROM_SHAMD5IntEnable #else #define MAP_SHAMD5IntEnable \ SHAMD5IntEnable #endif #ifdef ROM_SHAMD5IntRegister #define MAP_SHAMD5IntRegister \ ROM_SHAMD5IntRegister #else #define MAP_SHAMD5IntRegister \ SHAMD5IntRegister #endif #ifdef ROM_SHAMD5IntStatus #define MAP_SHAMD5IntStatus \ ROM_SHAMD5IntStatus #else #define MAP_SHAMD5IntStatus \ SHAMD5IntStatus #endif #ifdef ROM_SHAMD5IntUnregister #define MAP_SHAMD5IntUnregister \ ROM_SHAMD5IntUnregister #else #define MAP_SHAMD5IntUnregister \ SHAMD5IntUnregister #endif #ifdef ROM_SHAMD5ResultRead #define MAP_SHAMD5ResultRead \ ROM_SHAMD5ResultRead #else #define MAP_SHAMD5ResultRead \ SHAMD5ResultRead #endif //***************************************************************************** // // Macros for the CRC API. // //***************************************************************************** #ifdef ROM_CRCConfigSet #define MAP_CRCConfigSet \ ROM_CRCConfigSet #else #define MAP_CRCConfigSet \ CRCConfigSet #endif #ifdef ROM_CRCDataProcess #define MAP_CRCDataProcess \ ROM_CRCDataProcess #else #define MAP_CRCDataProcess \ CRCDataProcess #endif #ifdef ROM_CRCDataWrite #define MAP_CRCDataWrite \ ROM_CRCDataWrite #else #define MAP_CRCDataWrite \ CRCDataWrite #endif #ifdef ROM_CRCResultRead #define MAP_CRCResultRead \ ROM_CRCResultRead #else #define MAP_CRCResultRead \ CRCResultRead #endif #ifdef ROM_CRCSeedSet #define MAP_CRCSeedSet \ ROM_CRCSeedSet #else #define MAP_CRCSeedSet \ CRCSeedSet #endif //***************************************************************************** // // Macros for the SDHOST API. // //***************************************************************************** #ifdef ROM_SDHostCmdReset #define MAP_SDHostCmdReset \ ROM_SDHostCmdReset #else #define MAP_SDHostCmdReset \ SDHostCmdReset #endif #ifdef ROM_SDHostInit #define MAP_SDHostInit \ ROM_SDHostInit #else #define MAP_SDHostInit \ SDHostInit #endif #ifdef ROM_SDHostCmdSend #define MAP_SDHostCmdSend \ ROM_SDHostCmdSend #else #define MAP_SDHostCmdSend \ SDHostCmdSend #endif #ifdef ROM_SDHostIntRegister #define MAP_SDHostIntRegister \ ROM_SDHostIntRegister #else #define MAP_SDHostIntRegister \ SDHostIntRegister #endif #ifdef ROM_SDHostIntUnregister #define MAP_SDHostIntUnregister \ ROM_SDHostIntUnregister #else #define MAP_SDHostIntUnregister \ SDHostIntUnregister #endif #ifdef ROM_SDHostIntEnable #define MAP_SDHostIntEnable \ ROM_SDHostIntEnable #else #define MAP_SDHostIntEnable \ SDHostIntEnable #endif #ifdef ROM_SDHostIntDisable #define MAP_SDHostIntDisable \ ROM_SDHostIntDisable #else #define MAP_SDHostIntDisable \ SDHostIntDisable #endif #ifdef ROM_SDHostIntStatus #define MAP_SDHostIntStatus \ ROM_SDHostIntStatus #else #define MAP_SDHostIntStatus \ SDHostIntStatus #endif #ifdef ROM_SDHostIntClear #define MAP_SDHostIntClear \ ROM_SDHostIntClear #else #define MAP_SDHostIntClear \ SDHostIntClear #endif #ifdef ROM_SDHostRespStatus #define MAP_SDHostRespStatus \ ROM_SDHostRespStatus #else #define MAP_SDHostRespStatus \ SDHostRespStatus #endif #ifdef ROM_SDHostRespGet #define MAP_SDHostRespGet \ ROM_SDHostRespGet #else #define MAP_SDHostRespGet \ SDHostRespGet #endif #ifdef ROM_SDHostBlockSizeSet #define MAP_SDHostBlockSizeSet \ ROM_SDHostBlockSizeSet #else #define MAP_SDHostBlockSizeSet \ SDHostBlockSizeSet #endif #ifdef ROM_SDHostBlockCountSet #define MAP_SDHostBlockCountSet \ ROM_SDHostBlockCountSet #else #define MAP_SDHostBlockCountSet \ SDHostBlockCountSet #endif #ifdef ROM_SDHostDataNonBlockingWrite #define MAP_SDHostDataNonBlockingWrite \ ROM_SDHostDataNonBlockingWrite #else #define MAP_SDHostDataNonBlockingWrite \ SDHostDataNonBlockingWrite #endif #ifdef ROM_SDHostDataNonBlockingRead #define MAP_SDHostDataNonBlockingRead \ ROM_SDHostDataNonBlockingRead #else #define MAP_SDHostDataNonBlockingRead \ SDHostDataNonBlockingRead #endif #ifdef ROM_SDHostDataWrite #define MAP_SDHostDataWrite \ ROM_SDHostDataWrite #else #define MAP_SDHostDataWrite \ SDHostDataWrite #endif #ifdef ROM_SDHostDataRead #define MAP_SDHostDataRead \ ROM_SDHostDataRead #else #define MAP_SDHostDataRead \ SDHostDataRead #endif #ifdef ROM_SDHostSetExpClk #define MAP_SDHostSetExpClk \ ROM_SDHostSetExpClk #else #define MAP_SDHostSetExpClk \ SDHostSetExpClk #endif //***************************************************************************** // // Macros for the PRCM API. // //***************************************************************************** #ifdef ROM_PRCMMCUReset #define MAP_PRCMMCUReset \ ROM_PRCMMCUReset #else #define MAP_PRCMMCUReset \ PRCMMCUReset #endif #ifdef ROM_PRCMSysResetCauseGet #define MAP_PRCMSysResetCauseGet \ ROM_PRCMSysResetCauseGet #else #define MAP_PRCMSysResetCauseGet \ PRCMSysResetCauseGet #endif #ifdef ROM_PRCMPeripheralClkEnable #define MAP_PRCMPeripheralClkEnable \ ROM_PRCMPeripheralClkEnable #else #define MAP_PRCMPeripheralClkEnable \ PRCMPeripheralClkEnable #endif #ifdef ROM_PRCMPeripheralClkDisable #define MAP_PRCMPeripheralClkDisable \ ROM_PRCMPeripheralClkDisable #else #define MAP_PRCMPeripheralClkDisable \ PRCMPeripheralClkDisable #endif #ifdef ROM_PRCMPeripheralReset #define MAP_PRCMPeripheralReset \ ROM_PRCMPeripheralReset #else #define MAP_PRCMPeripheralReset \ PRCMPeripheralReset #endif #ifdef ROM_PRCMPeripheralStatusGet #define MAP_PRCMPeripheralStatusGet \ ROM_PRCMPeripheralStatusGet #else #define MAP_PRCMPeripheralStatusGet \ PRCMPeripheralStatusGet #endif #ifdef ROM_PRCMI2SClockFreqSet #define MAP_PRCMI2SClockFreqSet \ ROM_PRCMI2SClockFreqSet #else #define MAP_PRCMI2SClockFreqSet \ PRCMI2SClockFreqSet #endif #ifdef ROM_PRCMPeripheralClockGet #define MAP_PRCMPeripheralClockGet \ ROM_PRCMPeripheralClockGet #else #define MAP_PRCMPeripheralClockGet \ PRCMPeripheralClockGet #endif #ifdef ROM_PRCMSleepEnter #define MAP_PRCMSleepEnter \ ROM_PRCMSleepEnter #else #define MAP_PRCMSleepEnter \ PRCMSleepEnter #endif #ifdef ROM_PRCMDeepSleepEnter #define MAP_PRCMDeepSleepEnter \ ROM_PRCMDeepSleepEnter #else #define MAP_PRCMDeepSleepEnter \ PRCMDeepSleepEnter #endif #ifdef ROM_PRCMSRAMRetentionEnable #define MAP_PRCMSRAMRetentionEnable \ ROM_PRCMSRAMRetentionEnable #else #define MAP_PRCMSRAMRetentionEnable \ PRCMSRAMRetentionEnable #endif #ifdef ROM_PRCMSRAMRetentionDisable #define MAP_PRCMSRAMRetentionDisable \ ROM_PRCMSRAMRetentionDisable #else #define MAP_PRCMSRAMRetentionDisable \ PRCMSRAMRetentionDisable #endif #ifdef ROM_PRCMLPDSEnter #define MAP_PRCMLPDSEnter \ ROM_PRCMLPDSEnter #else #define MAP_PRCMLPDSEnter \ PRCMLPDSEnter #endif #ifdef ROM_PRCMLPDSIntervalSet #define MAP_PRCMLPDSIntervalSet \ ROM_PRCMLPDSIntervalSet #else #define MAP_PRCMLPDSIntervalSet \ PRCMLPDSIntervalSet #endif #ifdef ROM_PRCMLPDSWakeupSourceEnable #define MAP_PRCMLPDSWakeupSourceEnable \ ROM_PRCMLPDSWakeupSourceEnable #else #define MAP_PRCMLPDSWakeupSourceEnable \ PRCMLPDSWakeupSourceEnable #endif #ifdef ROM_PRCMLPDSWakeupCauseGet #define MAP_PRCMLPDSWakeupCauseGet \ ROM_PRCMLPDSWakeupCauseGet #else #define MAP_PRCMLPDSWakeupCauseGet \ PRCMLPDSWakeupCauseGet #endif #ifdef ROM_PRCMLPDSWakeUpGPIOSelect #define MAP_PRCMLPDSWakeUpGPIOSelect \ ROM_PRCMLPDSWakeUpGPIOSelect #else #define MAP_PRCMLPDSWakeUpGPIOSelect \ PRCMLPDSWakeUpGPIOSelect #endif #ifdef ROM_PRCMLPDSWakeupSourceDisable #define MAP_PRCMLPDSWakeupSourceDisable \ ROM_PRCMLPDSWakeupSourceDisable #else #define MAP_PRCMLPDSWakeupSourceDisable \ PRCMLPDSWakeupSourceDisable #endif #ifdef ROM_PRCMHibernateEnter #define MAP_PRCMHibernateEnter \ ROM_PRCMHibernateEnter #else #define MAP_PRCMHibernateEnter \ PRCMHibernateEnter #endif #ifdef ROM_PRCMHibernateWakeupSourceEnable #define MAP_PRCMHibernateWakeupSourceEnable \ ROM_PRCMHibernateWakeupSourceEnable #else #define MAP_PRCMHibernateWakeupSourceEnable \ PRCMHibernateWakeupSourceEnable #endif #ifdef ROM_PRCMHibernateWakeupCauseGet #define MAP_PRCMHibernateWakeupCauseGet \ ROM_PRCMHibernateWakeupCauseGet #else #define MAP_PRCMHibernateWakeupCauseGet \ PRCMHibernateWakeupCauseGet #endif #ifdef ROM_PRCMHibernateWakeUpGPIOSelect #define MAP_PRCMHibernateWakeUpGPIOSelect \ ROM_PRCMHibernateWakeUpGPIOSelect #else #define MAP_PRCMHibernateWakeUpGPIOSelect \ PRCMHibernateWakeUpGPIOSelect #endif #ifdef ROM_PRCMHibernateWakeupSourceDisable #define MAP_PRCMHibernateWakeupSourceDisable \ ROM_PRCMHibernateWakeupSourceDisable #else #define MAP_PRCMHibernateWakeupSourceDisable \ PRCMHibernateWakeupSourceDisable #endif #ifdef ROM_PRCMHibernateIntervalSet #define MAP_PRCMHibernateIntervalSet \ ROM_PRCMHibernateIntervalSet #else #define MAP_PRCMHibernateIntervalSet \ PRCMHibernateIntervalSet #endif #ifdef ROM_PRCMSlowClkCtrGet #define MAP_PRCMSlowClkCtrGet \ ROM_PRCMSlowClkCtrGet #else #define MAP_PRCMSlowClkCtrGet \ PRCMSlowClkCtrGet #endif #ifdef ROM_PRCMSlowClkCtrMatchSet #define MAP_PRCMSlowClkCtrMatchSet \ ROM_PRCMSlowClkCtrMatchSet #else #define MAP_PRCMSlowClkCtrMatchSet \ PRCMSlowClkCtrMatchSet #endif #ifdef ROM_PRCMSlowClkCtrMatchGet #define MAP_PRCMSlowClkCtrMatchGet \ ROM_PRCMSlowClkCtrMatchGet #else #define MAP_PRCMSlowClkCtrMatchGet \ PRCMSlowClkCtrMatchGet #endif #ifdef ROM_PRCMOCRRegisterWrite #define MAP_PRCMOCRRegisterWrite \ ROM_PRCMOCRRegisterWrite #else #define MAP_PRCMOCRRegisterWrite \ PRCMOCRRegisterWrite #endif #ifdef ROM_PRCMOCRRegisterRead #define MAP_PRCMOCRRegisterRead \ ROM_PRCMOCRRegisterRead #else #define MAP_PRCMOCRRegisterRead \ PRCMOCRRegisterRead #endif #ifdef ROM_PRCMIntRegister #define MAP_PRCMIntRegister \ ROM_PRCMIntRegister #else #define MAP_PRCMIntRegister \ PRCMIntRegister #endif #ifdef ROM_PRCMIntUnregister #define MAP_PRCMIntUnregister \ ROM_PRCMIntUnregister #else #define MAP_PRCMIntUnregister \ PRCMIntUnregister #endif #ifdef ROM_PRCMIntEnable #define MAP_PRCMIntEnable \ ROM_PRCMIntEnable #else #define MAP_PRCMIntEnable \ PRCMIntEnable #endif #ifdef ROM_PRCMIntDisable #define MAP_PRCMIntDisable \ ROM_PRCMIntDisable #else #define MAP_PRCMIntDisable \ PRCMIntDisable #endif #ifdef ROM_PRCMIntStatus #define MAP_PRCMIntStatus \ ROM_PRCMIntStatus #else #define MAP_PRCMIntStatus \ PRCMIntStatus #endif #ifdef ROM_PRCMRTCInUseSet #define MAP_PRCMRTCInUseSet \ ROM_PRCMRTCInUseSet #else #define MAP_PRCMRTCInUseSet \ PRCMRTCInUseSet #endif #ifdef ROM_PRCMRTCInUseGet #define MAP_PRCMRTCInUseGet \ ROM_PRCMRTCInUseGet #else #define MAP_PRCMRTCInUseGet \ PRCMRTCInUseGet #endif #ifdef ROM_PRCMRTCSet #define MAP_PRCMRTCSet \ ROM_PRCMRTCSet #else #define MAP_PRCMRTCSet \ PRCMRTCSet #endif #ifdef ROM_PRCMRTCGet #define MAP_PRCMRTCGet \ ROM_PRCMRTCGet #else #define MAP_PRCMRTCGet \ PRCMRTCGet #endif #ifdef ROM_PRCMRTCMatchSet #define MAP_PRCMRTCMatchSet \ ROM_PRCMRTCMatchSet #else #define MAP_PRCMRTCMatchSet \ PRCMRTCMatchSet #endif #ifdef ROM_PRCMRTCMatchGet #define MAP_PRCMRTCMatchGet \ ROM_PRCMRTCMatchGet #else #define MAP_PRCMRTCMatchGet \ PRCMRTCMatchGet #endif #ifdef ROM_PRCMLPDSRestoreInfoSet #define MAP_PRCMLPDSRestoreInfoSet \ ROM_PRCMLPDSRestoreInfoSet #else #define MAP_PRCMLPDSRestoreInfoSet \ PRCMLPDSRestoreInfoSet #endif #ifdef ROM_PRCMHIBRegRead #define MAP_PRCMHIBRegRead \ ROM_PRCMHIBRegRead #else #define MAP_PRCMHIBRegRead \ PRCMHIBRegRead #endif #ifdef ROM_PRCMHIBRegWrite #define MAP_PRCMHIBRegWrite \ ROM_PRCMHIBRegWrite #else #define MAP_PRCMHIBRegWrite \ PRCMHIBRegWrite #endif //***************************************************************************** // // Macros for the HWSPINLOCK API. // //***************************************************************************** #ifdef ROM_HwSpinLockAcquire #define MAP_HwSpinLockAcquire \ ROM_HwSpinLockAcquire #else #define MAP_HwSpinLockAcquire \ HwSpinLockAcquire #endif #ifdef ROM_HwSpinLockTryAcquire #define MAP_HwSpinLockTryAcquire \ ROM_HwSpinLockTryAcquire #else #define MAP_HwSpinLockTryAcquire \ HwSpinLockTryAcquire #endif #ifdef ROM_HwSpinLockRelease #define MAP_HwSpinLockRelease \ ROM_HwSpinLockRelease #else #define MAP_HwSpinLockRelease \ HwSpinLockRelease #endif #ifdef ROM_HwSpinLockTest #define MAP_HwSpinLockTest \ ROM_HwSpinLockTest #else #define MAP_HwSpinLockTest \ HwSpinLockTest #endif //***************************************************************************** // // Macros for the ADC API. // //***************************************************************************** #ifdef ROM_ADCEnable #define MAP_ADCEnable \ ROM_ADCEnable #else #define MAP_ADCEnable \ ADCEnable #endif #ifdef ROM_ADCDisable #define MAP_ADCDisable \ ROM_ADCDisable #else #define MAP_ADCDisable \ ADCDisable #endif #ifdef ROM_ADCChannelEnable #define MAP_ADCChannelEnable \ ROM_ADCChannelEnable #else #define MAP_ADCChannelEnable \ ADCChannelEnable #endif #ifdef ROM_ADCChannelDisable #define MAP_ADCChannelDisable \ ROM_ADCChannelDisable #else #define MAP_ADCChannelDisable \ ADCChannelDisable #endif #ifdef ROM_ADCIntRegister #define MAP_ADCIntRegister \ ROM_ADCIntRegister #else #define MAP_ADCIntRegister \ ADCIntRegister #endif #ifdef ROM_ADCIntUnregister #define MAP_ADCIntUnregister \ ROM_ADCIntUnregister #else #define MAP_ADCIntUnregister \ ADCIntUnregister #endif #ifdef ROM_ADCIntEnable #define MAP_ADCIntEnable \ ROM_ADCIntEnable #else #define MAP_ADCIntEnable \ ADCIntEnable #endif #ifdef ROM_ADCIntDisable #define MAP_ADCIntDisable \ ROM_ADCIntDisable #else #define MAP_ADCIntDisable \ ADCIntDisable #endif #ifdef ROM_ADCIntStatus #define MAP_ADCIntStatus \ ROM_ADCIntStatus #else #define MAP_ADCIntStatus \ ADCIntStatus #endif #ifdef ROM_ADCIntClear #define MAP_ADCIntClear \ ROM_ADCIntClear #else #define MAP_ADCIntClear \ ADCIntClear #endif #ifdef ROM_ADCDMAEnable #define MAP_ADCDMAEnable \ ROM_ADCDMAEnable #else #define MAP_ADCDMAEnable \ ADCDMAEnable #endif #ifdef ROM_ADCDMADisable #define MAP_ADCDMADisable \ ROM_ADCDMADisable #else #define MAP_ADCDMADisable \ ADCDMADisable #endif #ifdef ROM_ADCChannelGainSet #define MAP_ADCChannelGainSet \ ROM_ADCChannelGainSet #else #define MAP_ADCChannelGainSet \ ADCChannelGainSet #endif #ifdef ROM_ADCChannleGainGet #define MAP_ADCChannleGainGet \ ROM_ADCChannleGainGet #else #define MAP_ADCChannleGainGet \ ADCChannleGainGet #endif #ifdef ROM_ADCTimerConfig #define MAP_ADCTimerConfig \ ROM_ADCTimerConfig #else #define MAP_ADCTimerConfig \ ADCTimerConfig #endif #ifdef ROM_ADCTimerEnable #define MAP_ADCTimerEnable \ ROM_ADCTimerEnable #else #define MAP_ADCTimerEnable \ ADCTimerEnable #endif #ifdef ROM_ADCTimerDisable #define MAP_ADCTimerDisable \ ROM_ADCTimerDisable #else #define MAP_ADCTimerDisable \ ADCTimerDisable #endif #ifdef ROM_ADCTimerReset #define MAP_ADCTimerReset \ ROM_ADCTimerReset #else #define MAP_ADCTimerReset \ ADCTimerReset #endif #ifdef ROM_ADCTimerValueGet #define MAP_ADCTimerValueGet \ ROM_ADCTimerValueGet #else #define MAP_ADCTimerValueGet \ ADCTimerValueGet #endif #ifdef ROM_ADCFIFOLvlGet #define MAP_ADCFIFOLvlGet \ ROM_ADCFIFOLvlGet #else #define MAP_ADCFIFOLvlGet \ ADCFIFOLvlGet #endif #ifdef ROM_ADCFIFORead #define MAP_ADCFIFORead \ ROM_ADCFIFORead #else #define MAP_ADCFIFORead \ ADCFIFORead #endif #endif // __ROM_MAP_H__ micropython-1.12/ports/cc3200/hal/rom_patch.h000066400000000000000000000072471357706137100207660ustar00rootroot00000000000000//***************************************************************************** // // rom_patch.h // // Macros to facilitate patching driverlib API's in the ROM. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // // List of API's in the ROM that need to be patched. // For e.g. to patch ROM_UARTCharPut add the line #undef ROM_UARTCharPut //***************************************************************************** #undef ROM_ADCIntClear #undef ROM_IntEnable #undef ROM_IntDisable #undef ROM_IntPendSet #undef ROM_SDHostCardErrorMaskSet #undef ROM_SDHostCardErrorMaskGet #undef ROM_TimerConfigure #undef ROM_TimerDMAEventSet #undef ROM_TimerDMAEventGet #undef ROM_SDHostDataNonBlockingWrite #undef ROM_SDHostDataWrite #undef ROM_SDHostDataRead #undef ROM_SDHostDataNonBlockingRead #undef ROM_PRCMSysResetCauseGet #undef ROM_PRCMPeripheralClkEnable #undef ROM_PRCMLPDSWakeUpGPIOSelect #undef ROM_PRCMHibernateWakeupSourceEnable #undef ROM_PRCMHibernateWakeupSourceDisable #undef ROM_PRCMHibernateWakeupCauseGet #undef ROM_PRCMHibernateIntervalSet #undef ROM_PRCMHibernateWakeUpGPIOSelect #undef ROM_PRCMHibernateEnter #undef ROM_PRCMSlowClkCtrGet #undef ROM_PRCMSlowClkCtrMatchSet #undef ROM_PRCMSlowClkCtrMatchGet #undef ROM_PRCMOCRRegisterWrite #undef ROM_PRCMOCRRegisterRead #undef ROM_PRCMIntEnable #undef ROM_PRCMIntDisable #undef ROM_PRCMRTCInUseSet #undef ROM_PRCMRTCInUseGet #undef ROM_PRCMRTCSet #undef ROM_PRCMRTCGet #undef ROM_PRCMRTCMatchSet #undef ROM_PRCMRTCMatchGet #undef ROM_PRCMPeripheralClkDisable #undef ROM_PRCMPeripheralReset #undef ROM_PRCMPeripheralStatusGet #undef ROM_SPIConfigSetExpClk #undef ROM_GPIODirModeGet #undef ROM_GPIOIntTypeGet #undef ROM_I2CMasterInitExpClk #undef ROM_AESDataProcess #undef ROM_DESDataProcess #undef ROM_I2SEnable #undef ROM_I2SConfigSetExpClk #undef ROM_PinConfigSet #undef ROM_PRCMLPDSEnter #undef ROM_PRCMCC3200MCUInit #undef ROM_SDHostIntStatus #undef ROM_SDHostBlockCountSet #undef ROM_UARTModemControlSet #undef ROM_UARTModemControlClear micropython-1.12/ports/cc3200/hal/sdhost.c000066400000000000000000000516471357706137100203140ustar00rootroot00000000000000//***************************************************************************** // // sdhost.c // // Driver for the SD Host (SDHost) Interface // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup Secure_Digital_Host_api //! @{ // //***************************************************************************** #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "inc/hw_mmchs.h" #include "inc/hw_ints.h" #include "inc/hw_apps_config.h" #include "interrupt.h" #include "sdhost.h" //***************************************************************************** // //! Configures SDHost module. //! //! \param ulBase is the base address of SDHost module. //! //! This function configures the SDHost module, enabling internal sub-modules. //! //! \return None. // //***************************************************************************** void SDHostInit(unsigned long ulBase) { // // Assert module reset // HWREG(ulBase + MMCHS_O_SYSCONFIG) = 0x2; // // Wait for soft reset to complete // while( !(HWREG(ulBase + MMCHS_O_SYSCONFIG) & 0x1) ) { } // // Assert internal reset // HWREG(ulBase + MMCHS_O_SYSCTL) |= (1 << 24); // // Wait for Reset to complete // while( (HWREG(ulBase + MMCHS_O_SYSCTL) & (0x1 << 24)) ) { } // // Set capability register, 1.8 and 3.0 V // HWREG(ulBase + MMCHS_O_CAPA) = (0x7 <<24); // // Select bus voltage, 3.0 V // HWREG(ulBase + MMCHS_O_HCTL) |= 0x7 << 9; // // Power up the bus // HWREG(ulBase + MMCHS_O_HCTL) |= 1 << 8; // // Wait for power on // while( !(HWREG(ulBase + MMCHS_O_HCTL) & (1<<8)) ) { } HWREG(ulBase + MMCHS_O_CON) |= 1 << 21; // // Un-mask all events // HWREG(ulBase + MMCHS_O_IE) = 0xFFFFFFFF; } //***************************************************************************** // //! Resets SDHost command line //! //! \param ulBase is the base address of SDHost module. //! //! This function assers a soft reset for the command line //! //! \return None. // //***************************************************************************** void SDHostCmdReset(unsigned long ulBase) { HWREG(ulBase + MMCHS_O_SYSCTL) |= 1 << 25; while( (HWREG(ulBase + MMCHS_O_SYSCTL) & (1 << 25)) ) { } } //***************************************************************************** // //! Sends command over SDHost interface //! //! \param ulBase is the base address of SDHost module. //! \param ulCmd is the command to send. //! \param ulArg is the argument for the command. //! //! This function send command to the attached card over the SDHost interface. //! //! The \e ulCmd parameter can be one of \b SDHOST_CMD_0 to \b SDHOST_CMD_63. //! It can be logically ORed with one or more of the following: //! - \b SDHOST_MULTI_BLK for multi-block transfer //! - \b SDHOST_WR_CMD if command is followed by write data //! - \b SDHOST_RD_CMD if command is followed by read data //! - \b SDHOST_DMA_EN if SDHost need to generate DMA request. //! - \b SDHOST_RESP_LEN_136 if 136 bit response is expected //! - \b SDHOST_RESP_LEN_48 if 48 bit response is expected //! - \b SDHOST_RESP_LEN_48B if 48 bit response with busy bit is expected //! //! The parameter \e ulArg is the argument for the command //! //! \return Returns 0 on success, -1 otherwise. // //***************************************************************************** long SDHostCmdSend(unsigned long ulBase, unsigned long ulCmd, unsigned ulArg) { // // Set Data Timeout // HWREG(ulBase + MMCHS_O_SYSCTL) |= 0x000E0000; // // Check for cmd inhabit // if( (HWREG(ulBase + MMCHS_O_PSTATE) & 0x1)) { return -1; } // // Set the argument // HWREG(ulBase + MMCHS_O_ARG) = ulArg; // // Send the command // HWREG(ulBase + MMCHS_O_CMD) = ulCmd; return 0; } //***************************************************************************** // //! Writes a data word into the SDHost write buffer. //! //! \param ulBase is the base address of SDHost module. //! \param ulData is data word to be transfered. //! //! This function writes a single data word into the SDHost write buffer. The //! function returns \b true if there was a space available in the buffer else //! returns \b false. //! //! \return Return \b true on success, \b false otherwise. // //***************************************************************************** tBoolean SDHostDataNonBlockingWrite(unsigned long ulBase, unsigned long ulData) { // // See if there is a space in the write buffer // if( (HWREG(ulBase + MMCHS_O_PSTATE) & (1<<10)) ) { // // Write the data into the buffer // HWREG(ulBase + MMCHS_O_DATA) = ulData; // // Success. // return(true); } else { // // No free sapce, failure. // return(false); } } //***************************************************************************** // //! Waits to write a data word into the SDHost write buffer. //! //! \param ulBase is the base address of SDHost module. //! \param ulData is data word to be transfered. //! //! This function writes \e ulData into the SDHost write buffer. If there is no //! space in the write buffer this function waits until there is a space //! available before returning. //! //! \return None. // //***************************************************************************** void SDHostDataWrite(unsigned long ulBase, unsigned long ulData) { // // Wait until space is available // while( !(HWREG(ulBase + MMCHS_O_PSTATE) & (1<<10)) ) { } // // Write the data // HWREG(ulBase + MMCHS_O_DATA) = ulData; } //***************************************************************************** // //! Waits for a data word from the SDHost read buffer //! //! \param ulBase is the base address of SDHost module. //! \param pulData is pointer to read data variable. //! //! This function reads a single data word from the SDHost read buffer. If there //! is no data available in the buffer the function will wait until a data //! word is received before returning. //! //! \return None. // //***************************************************************************** void SDHostDataRead(unsigned long ulBase, unsigned long *pulData) { // // Wait until data is available // while( !(HWREG(ulBase + MMCHS_O_PSTATE) & (1<<11)) ) { } // // Read the data // *pulData = HWREG(ulBase + MMCHS_O_DATA); } //***************************************************************************** // //! Reads single data word from the SDHost read buffer //! //! \param ulBase is the base address of SDHost module. //! \param pulData is pointer to read data variable. //! //! This function reads a data word from the SDHost read buffer. The //! function returns \b true if there was data available in to buffer else //! returns \b false. //! //! \return Return \b true on success, \b false otherwise. // //***************************************************************************** tBoolean SDHostDataNonBlockingRead(unsigned long ulBase, unsigned long *pulData) { // // See if there is any data in the read buffer. // if( (HWREG(ulBase + MMCHS_O_PSTATE) & (1<11)) ) { // // Read the data word. // *pulData = HWREG(ulBase + MMCHS_O_DATA); // // Success // return(true); } else { // // No data available, failure. // return(false); } } //***************************************************************************** // //! Registers the interrupt handler for SDHost interrupt //! //! \param ulBase is the base address of SDHost module //! \param pfnHandler is a pointer to the function to be called when the //! SDHost interrupt occurs. //! //! This function does the actual registering of the interrupt handler. This //! function enables the global interrupt in the interrupt controller; specific //! SDHost interrupts must be enabled via SDHostIntEnable(). It is the //! interrupt handler's responsibility to clear the interrupt source. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void SDHostIntRegister(unsigned long ulBase, void (*pfnHandler)(void)) { // // Register the interrupt handler. // IntRegister(INT_MMCHS, pfnHandler); // // Enable the SDHost interrupt. // IntEnable(INT_MMCHS); } //***************************************************************************** // //! Unregisters the interrupt handler for SDHost interrupt //! //! \param ulBase is the base address of SDHost module //! //! This function does the actual unregistering of the interrupt handler. It //! clears the handler to be called when a SDHost interrupt occurs. This //! function also masks off the interrupt in the interrupt controller so that //! the interrupt handler no longer is called. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void SDHostIntUnregister(unsigned long ulBase) { // // Disable the SDHost interrupt. // IntDisable(INT_MMCHS); // // Unregister the interrupt handler. // IntUnregister(INT_MMCHS); } //***************************************************************************** // //! Enable individual interrupt source for the specified SDHost //! //! \param ulBase is the base address of SDHost module. //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated SDHost interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter is the logical OR of any of the following: //! - \b SDHOST_INT_CC Command Complete interrupt //! - \b SDHOST_INT_TC Transfer Complete interrupt //! - \b SDHOST_INT_BWR Buffer Write Ready interrupt //! - \b SDHOST_INT_BRR Buffer Read Ready interrupt //! - \b SDHOST_INT_ERRI Error interrupt //! - \b SDHOST_INT_CTO Command Timeout error interrupt //! - \b SDHOST_INT_CEB Command End Bit error interrupt //! - \b SDHOST_INT_DTO Data Timeout error interrupt //! - \b SDHOST_INT_DCRC Data CRC error interrupt //! - \b SDHOST_INT_DEB Data End Bit error //! - \b SDHOST_INT_CERR Cart Status Error interrupt //! - \b SDHOST_INT_BADA Bad Data error interrupt //! - \b SDHOST_INT_DMARD Read DMA done interrupt //! - \b SDHOST_INT_DMAWR Write DMA done interrupt //! //! Note that SDHOST_INT_ERRI can only be used with \sa SDHostIntStatus() //! and is internally logical OR of all error status bits. Setting this bit //! alone as \e ulIntFlags doesn't generates any interrupt. //! //! \return None. // //***************************************************************************** void SDHostIntEnable(unsigned long ulBase,unsigned long ulIntFlags) { // // Enable DMA done interrupts // HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = (ulIntFlags >> 30); // // Enable the individual interrupt sources // HWREG(ulBase + MMCHS_O_ISE) |= (ulIntFlags & 0x3FFFFFFF); } //***************************************************************************** // //! Enable individual interrupt source for the specified SDHost //! //! \param ulBase is the base address of SDHost module. //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled. //! //! This function disables the indicated SDHost interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to SDHostIntEnable(). //! //! \return None. // //***************************************************************************** void SDHostIntDisable(unsigned long ulBase,unsigned long ulIntFlags) { // // Disable DMA done interrupts // HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = (ulIntFlags >> 30); // // Disable the individual interrupt sources // HWREG(ulBase + MMCHS_O_ISE) &= ~(ulIntFlags & 0x3FFFFFFF); } //***************************************************************************** // //! Gets the current interrupt status. //! //! \param ulBase is the base address of SDHost module. //! //! This function returns the interrupt status for the specified SDHost. //! //! \return Returns the current interrupt status, enumerated as a bit field of //! values described in SDHostIntEnable(). // //***************************************************************************** unsigned long SDHostIntStatus(unsigned long ulBase) { unsigned long ulIntStatus; // // Get DMA done interrupt status // ulIntStatus = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_RAW); ulIntStatus = (ulIntStatus << 30); // // Return the status of individual interrupt sources // ulIntStatus |= (HWREG(ulBase + MMCHS_O_STAT) & 0x3FFFFFFF); return(ulIntStatus); } //***************************************************************************** // //! Clears the individual interrupt sources. //! //! \param ulBase is the base address of SDHost module. //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared. //! //! The specified SDHost interrupt sources are cleared, so that they no longer //! assert. This function must be called in the interrupt handler to keep the //! interrupt from being recognized again immediately upon exit. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to SDHostIntEnable(). //! //! \return None. // //***************************************************************************** void SDHostIntClear(unsigned long ulBase,unsigned long ulIntFlags) { // // Clear DMA done interrupts // HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = (ulIntFlags >> 30); // // Clear the individual interrupt sources // HWREG(ulBase + MMCHS_O_STAT) = (ulIntFlags & 0x3FFFFFFF); } //***************************************************************************** // //! Sets the card status error mask. //! //! \param ulBase is the base address of SDHost module //! \param ulErrMask is the bit mask of card status errors to be enabled //! //! This function sets the card status error mask for response type R1, R1b, //! R5, R5b and R6 response. The parameter \e ulErrMask is the bit mask of card //! status errors to be enabled, if the corresponding bits in the 'card status' //! field of a respose are set then the host controller indicates a card error //! interrupt status. Only bits referenced as type E (error) in status field in //! the response can set a card status error. //! //! \return None // //***************************************************************************** void SDHostCardErrorMaskSet(unsigned long ulBase, unsigned long ulErrMask) { // // Set the card status error mask // HWREG(ulBase + MMCHS_O_CSRE) = ulErrMask; } //***************************************************************************** // //! Gets the card status error mask. //! //! \param ulBase is the base address of SDHost module //! //! This function gets the card status error mask for response type R1, R1b, //! R5, R5b and R6 response. //! //! \return Returns the current card status error. // //***************************************************************************** unsigned long SDHostCardErrorMaskGet(unsigned long ulBase) { // // Return the card status error mask // return(HWREG(ulBase + MMCHS_O_CSRE)); } //***************************************************************************** // //! Sets the SD Card clock. //! //! \param ulBase is the base address of SDHost module //! \param ulSDHostClk is the rate of clock supplied to SDHost module //! \param ulCardClk is the required SD interface clock //! //! This function configures the SDHost interface to supply the specified clock //! to the connected card. //! //! \return None. // //***************************************************************************** void SDHostSetExpClk(unsigned long ulBase, unsigned long ulSDHostClk, unsigned long ulCardClk) { unsigned long ulDiv; // // Disable card clock // HWREG(ulBase + MMCHS_O_SYSCTL) &= ~0x4; // // Enable internal clock // HWREG(ulBase + MMCHS_O_SYSCTL) |= 0x1; ulDiv = ((ulSDHostClk/ulCardClk) & 0x3FF); // // Set clock divider, // HWREG(ulBase + MMCHS_O_SYSCTL) = ((HWREG(ulBase + MMCHS_O_SYSCTL) & ~0x0000FFC0)| (ulDiv) << 6); // // Wait for clock to stablize // while( !(HWREG(ulBase + MMCHS_O_SYSCTL) & 0x2) ) { } // // Enable card clock // HWREG(ulBase + MMCHS_O_SYSCTL) |= 0x4; } //***************************************************************************** // //! Get the response for the last command. //! //! \param ulBase is the base address of SDHost module //! \param ulRespnse is 128-bit response. //! //! This function gets the response from the SD card for the last command //! send. //! //! \return None. // //***************************************************************************** void SDHostRespGet(unsigned long ulBase, unsigned long ulRespnse[4]) { // // Read the responses. // ulRespnse[0] = HWREG(ulBase + MMCHS_O_RSP10); ulRespnse[1] = HWREG(ulBase + MMCHS_O_RSP32); ulRespnse[2] = HWREG(ulBase + MMCHS_O_RSP54); ulRespnse[3] = HWREG(ulBase + MMCHS_O_RSP76); } //***************************************************************************** // //! Set the block size for data transfer //! //! \param ulBase is the base address of SDHost module //! \param ulBlkSize is the transfer block size in bytes //! //! This function sets the block size the data transfer. //! //! The parameter \e ulBlkSize is size of each data block in bytes. //! This should be in range 0 - 2^10. //! //! \return None. // //***************************************************************************** void SDHostBlockSizeSet(unsigned long ulBase, unsigned short ulBlkSize) { // // Set the block size // HWREG(ulBase + MMCHS_O_BLK) = ((HWREG(ulBase + MMCHS_O_BLK) & 0x00000FFF)| (ulBlkSize & 0xFFF)); } //***************************************************************************** // //! Set the block size and count for data transfer //! //! \param ulBase is the base address of SDHost module //! \param ulBlkCount is the number of blocks //! //! This function sets block count for the data transfer. This needs to be set //! for each block transfer. \sa SDHostBlockSizeSet() //! //! \return None. // //***************************************************************************** void SDHostBlockCountSet(unsigned long ulBase, unsigned short ulBlkCount) { unsigned long ulRegVal; // // Read the current value // ulRegVal = HWREG(ulBase + MMCHS_O_BLK); // // Set the number of blocks // HWREG(ulBase + MMCHS_O_BLK) = ((ulRegVal & 0x0000FFFF)| (ulBlkCount << 16)); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/sdhost.h000066400000000000000000000203761357706137100203140ustar00rootroot00000000000000//***************************************************************************** // // sdhost.h // // Defines and Macros for the SDHost. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __SDHOST_H__ #define __SDHOST_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" //{ #endif //***************************************************************************** // Values that can be passed to SDHostRespGet(). //***************************************************************************** #define SDHOST_RESP_10 0x00000003 #define SDHOST_RESP_32 0x00000002 #define SDHOST_RESP_54 0x00000001 #define SDHOST_RESP_76 0x00000000 //***************************************************************************** // Values that can be passed to SDHostIntEnable(), SDHostIntDisable(), // SDHostIntClear() ,and returned from SDHostIntStatus(). //***************************************************************************** #define SDHOST_INT_CC 0x00000001 #define SDHOST_INT_TC 0x00000002 #define SDHOST_INT_BWR 0x00000010 #define SDHOST_INT_BRR 0x00000020 #define SDHOST_INT_ERRI 0x00008000 #define SDHOST_INT_CTO 0x00010000 #define SDHOST_INT_CEB 0x00040000 #define SDHOST_INT_DTO 0x00100000 #define SDHOST_INT_DCRC 0x00200000 #define SDHOST_INT_DEB 0x00400000 #define SDHOST_INT_CERR 0x10000000 #define SDHOST_INT_BADA 0x20000000 #define SDHOST_INT_DMARD 0x40000000 #define SDHOST_INT_DMAWR 0x80000000 //***************************************************************************** // Values that can be passed to SDHostCmdSend(). //***************************************************************************** #define SDHOST_CMD_0 0x00000000 #define SDHOST_CMD_1 0x01000000 #define SDHOST_CMD_2 0x02000000 #define SDHOST_CMD_3 0x03000000 #define SDHOST_CMD_4 0x04000000 #define SDHOST_CMD_5 0x05000000 #define SDHOST_CMD_6 0x06000000 #define SDHOST_CMD_7 0x07000000 #define SDHOST_CMD_8 0x08000000 #define SDHOST_CMD_9 0x09000000 #define SDHOST_CMD_10 0x0A000000 #define SDHOST_CMD_11 0x0B000000 #define SDHOST_CMD_12 0x0C000000 #define SDHOST_CMD_13 0x0D000000 #define SDHOST_CMD_14 0x0E000000 #define SDHOST_CMD_15 0x0F000000 #define SDHOST_CMD_16 0x10000000 #define SDHOST_CMD_17 0x11000000 #define SDHOST_CMD_18 0x12000000 #define SDHOST_CMD_19 0x13000000 #define SDHOST_CMD_20 0x14000000 #define SDHOST_CMD_21 0x15000000 #define SDHOST_CMD_22 0x16000000 #define SDHOST_CMD_23 0x17000000 #define SDHOST_CMD_24 0x18000000 #define SDHOST_CMD_25 0x19000000 #define SDHOST_CMD_26 0x1A000000 #define SDHOST_CMD_27 0x1B000000 #define SDHOST_CMD_28 0x1C000000 #define SDHOST_CMD_29 0x1D000000 #define SDHOST_CMD_30 0x1E000000 #define SDHOST_CMD_31 0x1F000000 #define SDHOST_CMD_32 0x20000000 #define SDHOST_CMD_33 0x21000000 #define SDHOST_CMD_34 0x22000000 #define SDHOST_CMD_35 0x23000000 #define SDHOST_CMD_36 0x24000000 #define SDHOST_CMD_37 0x25000000 #define SDHOST_CMD_38 0x26000000 #define SDHOST_CMD_39 0x27000000 #define SDHOST_CMD_40 0x28000000 #define SDHOST_CMD_41 0x29000000 #define SDHOST_CMD_42 0x2A000000 #define SDHOST_CMD_43 0x2B000000 #define SDHOST_CMD_44 0x2C000000 #define SDHOST_CMD_45 0x2D000000 #define SDHOST_CMD_46 0x2E000000 #define SDHOST_CMD_47 0x2F000000 #define SDHOST_CMD_48 0x30000000 #define SDHOST_CMD_49 0x31000000 #define SDHOST_CMD_50 0x32000000 #define SDHOST_CMD_51 0x33000000 #define SDHOST_CMD_52 0x34000000 #define SDHOST_CMD_53 0x35000000 #define SDHOST_CMD_54 0x36000000 #define SDHOST_CMD_55 0x37000000 #define SDHOST_CMD_56 0x38000000 #define SDHOST_CMD_57 0x39000000 #define SDHOST_CMD_58 0x3A000000 #define SDHOST_CMD_59 0x3B000000 #define SDHOST_CMD_60 0x3C000000 #define SDHOST_CMD_61 0x3D000000 #define SDHOST_CMD_62 0x3E000000 #define SDHOST_CMD_63 0x3F000000 //***************************************************************************** // Values that can be logically ORed with ulCmd parameter for SDHostCmdSend(). //***************************************************************************** #define SDHOST_MULTI_BLK 0x00000022 #define SDHOST_DMA_EN 0x00000001 #define SDHOST_WR_CMD 0x00200000 #define SDHOST_RD_CMD 0x00200010 #define SDHOST_RESP_LEN_136 0x00010000 #define SDHOST_RESP_LEN_48 0x00020000 #define SDHOST_RESP_LEN_48B 0x00030000 //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void SDHostCmdReset(unsigned long ulBase); extern void SDHostInit(unsigned long ulBase); extern long SDHostCmdSend(unsigned long ulBase,unsigned long ulCmd, unsigned ulArg); extern void SDHostIntRegister(unsigned long ulBase, void (*pfnHandler)(void)); extern void SDHostIntUnregister(unsigned long ulBase); extern void SDHostIntEnable(unsigned long ulBase,unsigned long ulIntFlags); extern void SDHostIntDisable(unsigned long ulBase,unsigned long ulIntFlags); extern unsigned long SDHostIntStatus(unsigned long ulBase); extern void SDHostIntClear(unsigned long ulBase,unsigned long ulIntFlags); extern void SDHostCardErrorMaskSet(unsigned long ulBase, unsigned long ulErrMask); extern unsigned long SDHostCardErrorMaskGet(unsigned long ulBase); extern void SDHostSetExpClk(unsigned long ulBase, unsigned long ulSDHostClk, unsigned long ulCardClk); extern void SDHostRespGet(unsigned long ulBase, unsigned long ulRespnse[4]); extern void SDHostBlockSizeSet(unsigned long ulBase, unsigned short ulBlkSize); extern void SDHostBlockCountSet(unsigned long ulBase, unsigned short ulBlkCount); extern tBoolean SDHostDataNonBlockingWrite(unsigned long ulBase, unsigned long ulData); extern tBoolean SDHostDataNonBlockingRead(unsigned long ulBase, unsigned long *pulData); extern void SDHostDataWrite(unsigned long ulBase, unsigned long ulData); extern void SDHostDataRead(unsigned long ulBase, unsigned long *ulData); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus //} #endif #endif // __SDHOST_H__ micropython-1.12/ports/cc3200/hal/shamd5.c000066400000000000000000000777161357706137100201760ustar00rootroot00000000000000//***************************************************************************** // // shamd5.c // // Driver for the SHA/MD5 module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup SHA_Secure_Hash_Algorithm_api //! @{ // //***************************************************************************** #include #include #include "inc/hw_dthe.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_nvic.h" #include "inc/hw_shamd5.h" #include "inc/hw_types.h" #include "debug.h" #include "interrupt.h" #include "shamd5.h" #include "rom_map.h" #define SHAMD5_MODE_ALGO_MD5 0x00000000 // MD5 #define SHAMD5_MODE_ALGO_SHA1 0x00000002 // SHA-1 #define SHAMD5_MODE_ALGO_SHA224 0x00000004 // SHA-224 #define SHAMD5_MODE_ALGO_SHA256 0x00000006 // SHA-256 //***************************************************************************** // //! Enables the uDMA requests in the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! //! This function configures the DMA options of the SHA/MD5 module. //! //! \return None // //***************************************************************************** void SHAMD5DMAEnable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Write the new configuration into the register. // HWREG(ui32Base + SHAMD5_O_SYSCONFIG) |= SHAMD5_SYSCONFIG_PADVANCED | SHAMD5_SYSCONFIG_PDMA_EN; } //***************************************************************************** // //! Disables the uDMA requests in the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! //! This function configures the DMA options of the SHA/MD5 module. //! //! \return None // //***************************************************************************** void SHAMD5DMADisable(uint32_t ui32Base) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Write the new configuration into the register. // HWREG(ui32Base + SHAMD5_O_SYSCONFIG) &= ~(SHAMD5_SYSCONFIG_PADVANCED | SHAMD5_SYSCONFIG_PDMA_EN); } //***************************************************************************** // //! Get the interrupt status of the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param bMasked is \b false if the raw interrupt status is required and //! \b true if the masked interrupt status is required. //! //! This function returns the current value of the IRQSTATUS register. The //! value will be a logical OR of the following: //! //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready. //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after //! a context switch. //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data. //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready. //! //! \return Interrupt status // //***************************************************************************** uint32_t SHAMD5IntStatus(uint32_t ui32Base, bool bMasked) { uint32_t ui32Temp; uint32_t ui32IrqEnable; // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Return the value of the IRQSTATUS register. // if(bMasked) { ui32Temp = HWREG(DTHE_BASE + DTHE_O_SHA_MIS); ui32IrqEnable = HWREG(ui32Base + SHAMD5_O_IRQENABLE); return((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & ui32IrqEnable) | (ui32Temp & 0x00000007) << 16); } else { ui32Temp = HWREG(DTHE_BASE + DTHE_O_SHA_RIS); return(HWREG(ui32Base + SHAMD5_O_IRQSTATUS) | (ui32Temp & 0x00000007) << 16); } } //***************************************************************************** // //! Enable interrupt sources in the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param ui32IntFlags contains desired interrupts to enable. //! //! This function enables interrupt sources in the SHA/MD5 module. //! ui32IntFlags must be a logical OR of one or more of the following //! values: //! //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready. //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after //! a context switch. //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data. //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready. //! //! \return None. // //***************************************************************************** void SHAMD5IntEnable(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) || (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) || (ui32IntFlags == SHAMD5_INT_INPUT_READY) || (ui32IntFlags == SHAMD5_INT_OUTPUT_READY)); // // Enable the interrupt sources. // HWREG(DTHE_BASE + DTHE_O_SHA_IM) &= ~((ui32IntFlags & 0x00070000) >> 16); HWREG(ui32Base + SHAMD5_O_IRQENABLE) |= ui32IntFlags & 0x0000ffff; // // Enable all interrupts. // HWREG(ui32Base + SHAMD5_O_SYSCONFIG) |= SHAMD5_SYSCONFIG_PIT_EN; } //***************************************************************************** // //! Disable interrupt sources in the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param ui32IntFlags contains desired interrupts to disable. //! //! \e ui32IntFlags must be a logical OR of one or more of the following //! values: //! //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready. //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after //! a context switch. //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data. //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready. //! //! \return None. // //***************************************************************************** void SHAMD5IntDisable(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) || (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) || (ui32IntFlags == SHAMD5_INT_INPUT_READY) || (ui32IntFlags == SHAMD5_INT_OUTPUT_READY)); // // Clear the corresponding flags disabling the interrupt sources. // HWREG(DTHE_BASE + DTHE_O_SHA_IM) |= ((ui32IntFlags & 0x00070000) >> 16); HWREG(ui32Base + SHAMD5_O_IRQENABLE) &= ~(ui32IntFlags & 0x0000ffff); // // If there are no interrupts enabled, then disable all interrupts. // if(HWREG(ui32Base + SHAMD5_O_IRQENABLE) == 0x0) { HWREG(ui32Base + SHAMD5_O_SYSCONFIG) &= ~SHAMD5_SYSCONFIG_PIT_EN; } } //***************************************************************************** // //! Clears interrupt sources in the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param ui32IntFlags contains desired interrupts to disable. //! //! \e ui32IntFlags must be a logical OR of one or more of the following //! values: //! //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready. //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after //! a context switch. //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data. //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready. //! //! \return None. // //***************************************************************************** void SHAMD5IntClear(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) || (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) || (ui32IntFlags == SHAMD5_INT_INPUT_READY) || (ui32IntFlags == SHAMD5_INT_OUTPUT_READY)); // // Clear the corresponding flags disabling the interrupt sources. // HWREG(DTHE_BASE + DTHE_O_SHA_IC) = ((ui32IntFlags & 0x00070000) >> 16); } //***************************************************************************** // //! Registers an interrupt handler for the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param pfnHandler is a pointer to the function to be called when the //! enabled SHA/MD5 interrupts occur. //! //! This function registers the interrupt handler in the interrupt vector //! table, and enables SHA/MD5 interrupts on the interrupt controller; //! specific SHA/MD5 interrupt sources must be enabled using //! SHAMD5IntEnable(). The interrupt handler being registered must clear //! the source of the interrupt using SHAMD5IntClear(). //! //! If the application is using a static interrupt vector table stored in //! flash, then it is not necessary to register the interrupt handler this way. //! Instead, IntEnable() should be used to enable SHA/MD5 interrupts on the //! interrupt controller. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void SHAMD5IntRegister(uint32_t ui32Base, void(*pfnHandler)(void)) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Register the interrupt handler. // IntRegister(INT_SHA, pfnHandler); // // Enable the interrupt // IntEnable(INT_SHA); } //***************************************************************************** // //! Unregisters an interrupt handler for the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! //! This function unregisters the previously registered interrupt handler and //! disables the interrupt in the interrupt controller. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void SHAMD5IntUnregister(uint32_t ui32Base) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Disable the interrupt. // IntDisable(INT_SHA); // // Unregister the interrupt handler. // IntUnregister(INT_SHA); } //***************************************************************************** // //! Write the hash length to the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param ui32Length is the hash length in bytes. //! //! This function writes the length of the hash data of the current operation //! to the SHA/MD5 module. The value must be a multiple of 64 if the close //! hash is not set in the mode register. //! //! \note When this register is written, hash processing is triggered. //! //! \return None. // //***************************************************************************** void SHAMD5DataLengthSet(uint32_t ui32Base, uint32_t ui32Length) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Set the LENGTH register and start processing. // HWREG(ui32Base + SHAMD5_O_LENGTH) = ui32Length; } //***************************************************************************** // //! Writes the mode in the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param ui32Mode is the mode of the SHA/MD5 module. //! //! This function writes the mode register configuring the SHA/MD5 module. //! //! The ui32Mode paramerter is a bit-wise OR of values: //! //! - \b SHAMD5_ALGO_MD5 - Regular hash with MD5 //! - \b SHAMD5_ALGO_SHA1 - Regular hash with SHA-1 //! - \b SHAMD5_ALGO_SHA224 - Regular hash with SHA-224 //! - \b SHAMD5_ALGO_SHA256 - Regular hash with SHA-256 //! - \b SHAMD5_ALGO_HMAC_MD5 - HMAC with MD5 //! - \b SHAMD5_ALGO_HMAC_SHA1 - HMAC with SHA-1 //! - \b SHAMD5_ALGO_HMAC_SHA224 - HMAC with SHA-224 //! - \b SHAMD5_ALGO_HMAC_SHA256 - HMAC with SHA-256 //! //! \return None // //***************************************************************************** void SHAMD5ConfigSet(uint32_t ui32Base, uint32_t ui32Mode) { // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); ASSERT((ui32Mode == SHAMD5_ALGO_MD5) || (ui32Mode == SHAMD5_ALGO_SHA1) || (ui32Mode == SHAMD5_ALGO_SHA224) || (ui32Mode == SHAMD5_ALGO_SHA256) || (ui32Mode == SHAMD5_ALGO_HMAC_MD5) || (ui32Mode == SHAMD5_ALGO_HMAC_SHA1) || (ui32Mode == SHAMD5_ALGO_HMAC_SHA224) || (ui32Mode == SHAMD5_ALGO_HMAC_SHA256)); // // Write the value in the MODE register. // HWREG(ui32Base + SHAMD5_O_MODE) = ui32Mode; } //***************************************************************************** // //! Perform a non-blocking write of 16 words of data to the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param pui8Src is the pointer to the 16-word array of data that will be //! written. //! //! This function writes 16 words of data into the data register. //! //! \return This function returns true if the write completed successfully. //! It returns false if the module was not ready. // //***************************************************************************** bool SHAMD5DataWriteNonBlocking(uint32_t ui32Base, uint8_t *pui8Src) { uint32_t ui8Counter; // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Check that the SHA/MD5 module is ready for data. If not, return false. // if((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_INPUT_READY) == 0) { return(false); } // // Write the 16 words of data. // for(ui8Counter = 0; ui8Counter < 64; ui8Counter += 4) { HWREG(ui32Base + SHAMD5_O_DATA0_IN + ui8Counter) = *((uint32_t *)(pui8Src + ui8Counter)); } // // Return true as a sign of successfully completing the function. // return(true); } //***************************************************************************** // //! Perform a blocking write of 64 bytes of data to the SHA/MD5 module. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param pui8Src is the pointer to the 64-byte array of data that will be //! written. //! //! This function does not return until the module is ready to accept data and //! the data has been written. //! //! \return None. // //***************************************************************************** void SHAMD5DataWrite(uint32_t ui32Base, uint8_t *pui8Src) { uint8_t ui8Counter; // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Wait for the module to be ready to accept data. // while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_INPUT_READY) == 0) { } // // Write the 64 bytes of data. // for(ui8Counter = 0; ui8Counter < 64; ui8Counter += 4) { HWREG(ui32Base + SHAMD5_O_DATA0_IN + ui8Counter) = *((uint32_t *) (pui8Src + ui8Counter)); } } //***************************************************************************** // //! Reads the result of a hashing operation. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param pui8Dest is the pointer to the byte array of data that will be //! written. //! //! This function does not return until the module is ready to accept data and //! the data has been written. //! ----------------------------------------- //! | Algorithm | Number of Words in Result | //! ----------------------------------------- //! | MD5 | 16 Bytes (128 bits) | //! | SHA-1 | 20 Bytes (160 bits) | //! | SHA-224 | 28 Bytes (224 bits) | //! | SHA-256 | 32 Bytes (256 bits) | //! ----------------------------------------- //! //! \return None. // //***************************************************************************** void SHAMD5ResultRead(uint32_t ui32Base, uint8_t *pui8Dest) { uint32_t ui32Idx, ui32Count; // // Check the arguments. // ASSERT(ui32Base == SHAMD5_BASE); // // Determine the number of bytes in the result, based on the hash type. // switch(HWREG(ui32Base + SHAMD5_O_MODE) & SHAMD5_MODE_ALGO_M) { // // The MD5 hash is being used. // case SHAMD5_MODE_ALGO_MD5: { // // There are 16 bytes in the MD5 hash. // ui32Count = 16; // // Done. // break; } // // The SHA-1 hash is being used. // case SHAMD5_MODE_ALGO_SHA1: { // // There are 20 bytes in the SHA-1 hash. // ui32Count = 20; // // Done. // break; } // // The SHA-224 hash is being used. // case SHAMD5_MODE_ALGO_SHA224: { // // There are 28 bytes in the SHA-224 hash. // ui32Count = 28; // // Done. // break; } // // The SHA-256 hash is being used. // case SHAMD5_MODE_ALGO_SHA256: { // // There are 32 bytes in the SHA-256 hash. // ui32Count = 32; // // Done. // break; } // // The hash type is not recognized. // default: { // // Return without reading a result since the hardware appears to be // misconfigured. // return; } } // // Read the hash result. // for(ui32Idx = 0; ui32Idx < ui32Count; ui32Idx += 4) { *((uint32_t *)(pui8Dest+ui32Idx)) = HWREG(ui32Base + SHAMD5_O_IDIGEST_A + ui32Idx); } } //***************************************************************************** // //! Writes multiple words of data into the SHA/MD5 data registers. //! //! \param ui32Base is the base address of the SHA/MD5 module. //! \param pui8DataSrc is a pointer to an array of data to be written. //! \param ui32DataLength is the length of the data to be written in bytes. //! //! This function writes a variable number of words into the SHA/MD5 data //! registers. The function waits for each block of data to be processed //! before another is written. //! //! \note This function is used by SHAMD5HashCompute(), SHAMD5HMACWithKPP(), //! and SHAMD5HMACNoKPP() to process data. //! //! \return None. // //***************************************************************************** void SHAMD5DataWriteMultiple(uint8_t *pui8DataSrc, uint32_t ui32DataLength) { uint32_t ui32Idx, ui32Count, ui32Lastword, ui32TempData = 0; uint8_t * ui8TempData; // // Calculate the number of blocks of data. // ui32Count = ui32DataLength / 64; // // Loop through all the blocks and write them into the data registers // making sure to block additional operations until we can write the // next 16 words. // for (ui32Idx = 0; ui32Idx < ui32Count; ui32Idx++) { // // Write the block of data. // MAP_SHAMD5DataWrite(SHAMD5_BASE, pui8DataSrc); // // Increment the pointer to next block of data. // pui8DataSrc += 64; } // // Calculate the remaining bytes of data that don't make up a full block. // ui32Count = ui32DataLength % 64; // // If there are bytes that do not make up a whole block, then // write them separately. // if(ui32Count) { // // Wait until the engine has finished processing the previous block. // while ((HWREG(SHAMD5_BASE + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_INPUT_READY) == 0); // // Loop through the remaining words. // ui32Count = ui32Count / 4; for (ui32Idx = 0; ui32Idx < ui32Count; ui32Idx ++) { // // Write the word into the data register. // HWREG(SHAMD5_BASE + SHAMD5_O_DATA0_IN + (ui32Idx * 4)) =* ( (uint32_t *) pui8DataSrc); pui8DataSrc +=4; } // // Loop through the remaining bytes // ui32Count = ui32DataLength % 4; ui8TempData = (uint8_t *) &ui32TempData; if(ui32Count) { ui32Lastword = 0; if(ui32Idx) { ui32Lastword = (ui32Idx-1) *4; } for(ui32Idx=0 ; ui32Idx //! Polarity Phase Sub-Mode //! 0 0 0 //! 0 1 1 //! 1 0 2 //! 1 1 3 //!
//! //! Required sub mode can be select by setting \e ulSubMode parameter to one //! of the following //! - \b SPI_SUB_MODE_0 //! - \b SPI_SUB_MODE_1 //! - \b SPI_SUB_MODE_2 //! - \b SPI_SUB_MODE_3 //! //! The parameter \e ulConfig is logical OR of five values: the word length, //! active level for chip select, software or hardware controled chip select, //! 3 or 4 pin mode and turbo mode. //! mode. //! //! SPI support 8, 16 and 32 bit word lengths defined by:- //! - \b SPI_WL_8 //! - \b SPI_WL_16 //! - \b SPI_WL_32 //! //! Active state of Chip Select can be defined by:- //! - \b SPI_CS_ACTIVELOW //! - \b SPI_CS_ACTIVEHIGH //! //! SPI chip select can be configured to be controlled either by hardware or //! software:- //! - \b SPI_SW_CS //! - \b SPI_HW_CS //! //! The module can work in 3 or 4 pin mode defined by:- //! - \b SPI_3PIN_MODE //! - \b SPI_4PIN_MODE //! //! Turbo mode can be set on or turned off using:- //! - \b SPI_TURBO_MODE_ON //! - \b SPI_TURBO_MODE_OFF //! //! \return None. // //***************************************************************************** void SPIConfigSetExpClk(unsigned long ulBase,unsigned long ulSPIClk, unsigned long ulBitRate, unsigned long ulMode, unsigned long ulSubMode, unsigned long ulConfig) { unsigned long ulRegData; unsigned long ulDivider; // // Read MODULCTRL register // ulRegData = HWREG(ulBase + MCSPI_O_MODULCTRL); // // Set Master mode with h/w chip select // ulRegData &= ~(MCSPI_MODULCTRL_MS | MCSPI_MODULCTRL_SINGLE); // // Enable software control Chip Select, Init delay // and 3-pin mode // ulRegData |= (((ulConfig >> 24) | ulMode) & 0xFF); // // Write the configuration // HWREG(ulBase + MCSPI_O_MODULCTRL) = ulRegData; // // Set IS, DPE0, DPE1 based on master or slave mode // if(ulMode == SPI_MODE_MASTER) { ulRegData = 0x1 << 16; } else { ulRegData = 0x6 << 16; } // // set clock divider granularity to 1 cycle // ulRegData |= MCSPI_CH0CONF_CLKG; // // Get the divider value // ulDivider = ((ulSPIClk/ulBitRate) - 1); // // The least significant four bits of the divider is used to configure // CLKD in MCSPI_CHCONF next eight least significant bits are used to // configure the EXTCLK in MCSPI_CHCTRL // ulRegData |= ((ulDivider & 0x0000000F) << 2); HWREG(ulBase + MCSPI_O_CH0CTRL) = ((ulDivider & 0x00000FF0) << 4); // // Set the protocol, CS polarity, word length // and turbo mode // ulRegData = ((ulRegData | ulSubMode) | (ulConfig & 0x0008FFFF)); // // Write back the CONF register // HWREG(ulBase + MCSPI_O_CH0CONF) = ulRegData; } //***************************************************************************** // //! Receives a word from the specified port. //! //! \param ulBase is the base address of the SPI module. //! \param pulData is pointer to receive data variable. //! //! This function gets a SPI word from the receive FIFO for the specified //! port. //! //! \return Returns the number of elements read from the receive FIFO. // //***************************************************************************** long SPIDataGetNonBlocking(unsigned long ulBase, unsigned long *pulData) { unsigned long ulRegVal; // // Read register status register // ulRegVal = HWREG(ulBase + MCSPI_O_CH0STAT); // // Check is data is available // if(ulRegVal & MCSPI_CH0STAT_RXS) { *pulData = HWREG(ulBase + MCSPI_O_RX0); return(1); } return(0); } //***************************************************************************** // //! Waits for the word to be received on the specified port. //! //! \param ulBase is the base address of the SPI module. //! \param pulData is pointer to receive data variable. //! //! This function gets a SPI word from the receive FIFO for the specified //! port. If there is no word available, this function waits until a //! word is received before returning. //! //! \return Returns the word read from the specified port, cast as an //! \e unsigned long. // //***************************************************************************** void SPIDataGet(unsigned long ulBase, unsigned long *pulData) { // // Wait for Rx data // while(!(HWREG(ulBase + MCSPI_O_CH0STAT) & MCSPI_CH0STAT_RXS)) { } // // Read the value // *pulData = HWREG(ulBase + MCSPI_O_RX0); } //***************************************************************************** // //! Transmits a word on the specified port. //! //! \param ulBase is the base address of the SPI module //! \param ulData is data to be transmitted. //! //! This function transmits a SPI word on the transmit FIFO for the specified //! port. //! //! \return Returns the number of elements written to the transmit FIFO. //! //***************************************************************************** long SPIDataPutNonBlocking(unsigned long ulBase, unsigned long ulData) { unsigned long ulRegVal; // // Read status register // ulRegVal = HWREG(ulBase + MCSPI_O_CH0STAT); // // Write value into Tx register/FIFO // if space is available // if(ulRegVal & MCSPI_CH0STAT_TXS) { HWREG(ulBase + MCSPI_O_TX0) = ulData; return(1); } return(0); } //***************************************************************************** // //! Waits until the word is transmitted on the specified port. //! //! \param ulBase is the base address of the SPI module //! \param ulData is data to be transmitted. //! //! This function transmits a SPI word on the transmit FIFO for the specified //! port. This function waits until the space is available on transmit FIFO //! //! \return None //! //***************************************************************************** void SPIDataPut(unsigned long ulBase, unsigned long ulData) { // // Wait for space in FIFO // while(!(HWREG(ulBase + MCSPI_O_CH0STAT)&MCSPI_CH0STAT_TXS)) { } // // Write the data // HWREG(ulBase + MCSPI_O_TX0) = ulData; } //***************************************************************************** // //! Enables the transmit and/or receive FIFOs. //! //! \param ulBase is the base address of the SPI module //! \param ulFlags selects the FIFO(s) to be enabled //! //! This function enables the transmit and/or receive FIFOs as specified by //! \e ulFlags. //! The parameter \e ulFlags shoulde be logical OR of one or more of the //! following: //! - \b SPI_TX_FIFO //! - \b SPI_RX_FIFO //! //! \return None. // //***************************************************************************** void SPIFIFOEnable(unsigned long ulBase, unsigned long ulFlags) { // // Set FIFO enable bits. // HWREG(ulBase + MCSPI_O_CH0CONF) |= ulFlags; } //***************************************************************************** // //! Disables the transmit and/or receive FIFOs. //! //! \param ulBase is the base address of the SPI module //! \param ulFlags selects the FIFO(s) to be enabled //! //! This function disables transmit and/or receive FIFOs. as specified by //! \e ulFlags. //! The parameter \e ulFlags shoulde be logical OR of one or more of the //! following: //! - \b SPI_TX_FIFO //! - \b SPI_RX_FIFO //! //! \return None. // //***************************************************************************** void SPIFIFODisable(unsigned long ulBase, unsigned long ulFlags) { // // Reset FIFO Enable bits. // HWREG(ulBase + MCSPI_O_CH0CONF) &= ~(ulFlags); } //***************************************************************************** // //! Sets the FIFO level at which DMA requests or interrupts are generated. //! //! \param ulBase is the base address of the SPI module //! \param ulTxLevel is the Almost Empty Level for transmit FIFO. //! \param ulRxLevel is the Almost Full Level for the receive FIFO. //! //! This function Sets the FIFO level at which DMA requests or interrupts //! are generated. //! //! \return None. // //***************************************************************************** void SPIFIFOLevelSet(unsigned long ulBase, unsigned long ulTxLevel, unsigned long ulRxLevel) { unsigned long ulRegVal; // // Read the current configuration // ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL); // // Mask and set new FIFO thresholds. // ulRegVal = ((ulRegVal & 0xFFFF0000) | (((ulRxLevel-1) << 8) | (ulTxLevel-1))); // // Set the transmit and receive FIFO thresholds. // HWREG(ulBase + MCSPI_O_XFERLEVEL) = ulRegVal; } //***************************************************************************** // //! Gets the FIFO level at which DMA requests or interrupts are generated. //! //! \param ulBase is the base address of the SPI module //! \param pulTxLevel is a pointer to storage for the transmit FIFO level //! \param pulRxLevel is a pointer to storage for the receive FIFO level //! //! This function gets the FIFO level at which DMA requests or interrupts //! are generated. //! //! \return None. // //***************************************************************************** void SPIFIFOLevelGet(unsigned long ulBase, unsigned long *pulTxLevel, unsigned long *pulRxLevel) { unsigned long ulRegVal; // // Read the current configuration // ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL); *pulTxLevel = (ulRegVal & 0xFF); *pulRxLevel = ((ulRegVal >> 8) & 0xFF); } //***************************************************************************** // //! Sets the word count. //! //! \param ulBase is the base address of the SPI module //! \param ulWordCount is number of SPI words to be transmitted. //! //! This function sets the word count, which is the number of SPI word to //! be transferred on channel when using the FIFO buffer. //! //! \return None. // //***************************************************************************** void SPIWordCountSet(unsigned long ulBase, unsigned long ulWordCount) { unsigned long ulRegVal; // // Read the current configuration // ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL); // // Mask and set the word count // HWREG(ulBase + MCSPI_O_XFERLEVEL) = ((ulRegVal & 0x0000FFFF)| (ulWordCount & 0xFFFF) << 16); } //***************************************************************************** // //! Registers an interrupt handler for a SPI interrupt. //! //! \param ulBase is the base address of the SPI module //! \param pfnHandler is a pointer to the function to be called when the //! SPI interrupt occurs. //! //! This function does the actual registering of the interrupt handler. This //! function enables the global interrupt in the interrupt controller; specific //! SPI interrupts must be enabled via SPIIntEnable(). It is the interrupt //! handler's responsibility to clear the interrupt source. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void SPIIntRegister(unsigned long ulBase, void(*pfnHandler)(void)) { unsigned long ulInt; // // Determine the interrupt number based on the SPI module // ulInt = SPIIntNumberGet(ulBase); // // Register the interrupt handler. // IntRegister(ulInt, pfnHandler); // // Enable the SPI interrupt. // IntEnable(ulInt); } //***************************************************************************** // //! Unregisters an interrupt handler for a SPI interrupt. //! //! \param ulBase is the base address of the SPI module //! //! This function does the actual unregistering of the interrupt handler. It //! clears the handler to be called when a SPI interrupt occurs. This //! function also masks off the interrupt in the interrupt controller so that //! the interrupt handler no longer is called. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void SPIIntUnregister(unsigned long ulBase) { unsigned long ulInt; // // Determine the interrupt number based on the SPI module // ulInt = SPIIntNumberGet(ulBase); // // Disable the interrupt. // IntDisable(ulInt); // // Unregister the interrupt handler. // IntUnregister(ulInt); } //***************************************************************************** // //! Enables individual SPI interrupt sources. //! //! \param ulBase is the base address of the SPI module //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated SPI interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter is the logical OR of any of the following: //! //! - \b SPI_INT_DMATX //! - \b SPI_INT_DMARX //! - \b SPI_INT_EOW //! - \b SPI_INT_RX_OVRFLOW //! - \b SPI_INT_RX_FULL //! - \b SPI_INT_TX_UDRFLOW //! - \b SPI_INT_TX_EMPTY //! //! \return None. // //***************************************************************************** void SPIIntEnable(unsigned long ulBase, unsigned long ulIntFlags) { unsigned long ulDmaMsk; // // Enable DMA Tx Interrupt // if(ulIntFlags & SPI_INT_DMATX) { ulDmaMsk = SPIDmaMaskGet(ulBase); HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk; } // // Enable DMA Rx Interrupt // if(ulIntFlags & SPI_INT_DMARX) { ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1); HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk; } // // Enable the specific Interrupts // HWREG(ulBase + MCSPI_O_IRQENABLE) |= (ulIntFlags & 0x0003000F); } //***************************************************************************** // //! Disables individual SPI interrupt sources. //! //! \param ulBase is the base address of the SPI module //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled. //! //! This function disables the indicated SPI interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to SPIIntEnable(). //! //! \return None. // //***************************************************************************** void SPIIntDisable(unsigned long ulBase, unsigned long ulIntFlags) { unsigned long ulDmaMsk; // // Disable DMA Tx Interrupt // if(ulIntFlags & SPI_INT_DMATX) { ulDmaMsk = SPIDmaMaskGet(ulBase); HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk; } // // Disable DMA Tx Interrupt // if(ulIntFlags & SPI_INT_DMARX) { ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1); HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk; } // // Disable the specific Interrupts // HWREG(ulBase + MCSPI_O_IRQENABLE) &= ~(ulIntFlags & 0x0003000F); } //***************************************************************************** // //! Gets the current interrupt status. //! //! \param ulBase is the base address of the SPI module //! \param bMasked is \b false if the raw interrupt status is required and //! \b true if the masked interrupt status is required. //! //! This function returns the interrupt status for the specified SPI. //! The status of interrupts that are allowed to reflect to the processor can //! be returned. //! //! \return Returns the current interrupt status, enumerated as a bit field of //! values described in SPIIntEnable(). // //***************************************************************************** unsigned long SPIIntStatus(unsigned long ulBase, tBoolean bMasked) { unsigned long ulIntStat; unsigned long ulIntFlag; unsigned long ulDmaMsk; // // Get SPI interrupt status // ulIntFlag = HWREG(ulBase + MCSPI_O_IRQSTATUS) & 0x0003000F; if(bMasked) { ulIntFlag &= HWREG(ulBase + MCSPI_O_IRQENABLE); } // // Get the interrupt bit // ulDmaMsk = SPIDmaMaskGet(ulBase); // // Get the DMA interrupt status // if(bMasked) { ulIntStat = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED); } else { ulIntStat = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_RAW); } // // Get SPI Tx DMA done status // if(ulIntStat & ulDmaMsk) { ulIntFlag |= SPI_INT_DMATX; } // // Get SPI Rx DMA done status // if(ulIntStat & (ulDmaMsk >> 1)) { ulIntFlag |= SPI_INT_DMARX; } // // Return status // return(ulIntFlag); } //***************************************************************************** // //! Clears SPI interrupt sources. //! //! \param ulBase is the base address of the SPI module //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared. //! //! The specified SPI interrupt sources are cleared, so that they no longer //! assert. This function must be called in the interrupt handler to keep the //! interrupt from being recognized again immediately upon exit. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to SPIIntEnable(). //! //! \return None. // //***************************************************************************** void SPIIntClear(unsigned long ulBase, unsigned long ulIntFlags) { unsigned long ulDmaMsk; // // Disable DMA Tx Interrupt // if(ulIntFlags & SPI_INT_DMATX) { ulDmaMsk = SPIDmaMaskGet(ulBase); HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk; } // // Disable DMA Tx Interrupt // if(ulIntFlags & SPI_INT_DMARX) { ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1); HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk; } // // Clear Interrupts // HWREG(ulBase + MCSPI_O_IRQSTATUS) = (ulIntFlags & 0x0003000F); } //***************************************************************************** // //! Enables the chip select in software controlled mode //! //! \param ulBase is the base address of the SPI module. //! //! This function enables the Chip select in software controlled mode. The //! active state of CS will depend on the configuration done via //! \sa SPIConfigExpClkSet(). //! //! \return None. // //***************************************************************************** void SPICSEnable(unsigned long ulBase) { // // Set Chip Select enable bit. // HWREG( ulBase+MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE; } //***************************************************************************** // //! Disables the chip select in software controlled mode //! //! \param ulBase is the base address of the SPI module. //! //! This function disables the Chip select in software controlled mode. The //! active state of CS will depend on the configuration done via //! sa SPIConfigSetExpClk(). //! //! \return None. // //***************************************************************************** void SPICSDisable(unsigned long ulBase) { // // Reset Chip Select enable bit. // HWREG( ulBase+MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE; } //***************************************************************************** // //! Send/Receive data buffer over SPI channel //! //! \param ulBase is the base address of SPI module //! \param ucDout is the pointer to Tx data buffer or 0. //! \param ucDin is pointer to Rx data buffer or 0 //! \param ulCount is the size of data in bytes. //! \param ulFlags controlls chip select toggling. //! //! This function transfers \e ulCount bytes of data over SPI channel. Since //! the API sends a SPI word at a time \e ulCount should be a multiple of //! word length set using SPIConfigSetExpClk(). //! //! If the \e ucDout parameter is set to 0, the function will send 0xFF over //! the SPI MOSI line. //! //! If the \e ucDin parameter is set to 0, the function will ignore data on SPI //! MISO line. //! //! The parameter \e ulFlags is logical OR of one or more of the following //! //! - \b SPI_CS_ENABLE if CS needs to be enabled at start of transfer. //! - \b SPI_CS_DISABLE if CS need to be disabled at the end of transfer. //! //! This function will not return until data has been transmitted //! //! \return Returns 0 on success, -1 otherwise. // //***************************************************************************** long SPITransfer(unsigned long ulBase, unsigned char *ucDout, unsigned char *ucDin, unsigned long ulCount, unsigned long ulFlags) { unsigned long ulWordLength; long lRet; // // Get the word length // ulWordLength = (HWREG(ulBase + MCSPI_O_CH0CONF) & MCSPI_CH0CONF_WL_M); // // Check for word length. // if( !((ulWordLength == SPI_WL_8) || (ulWordLength == SPI_WL_16) || (ulWordLength == SPI_WL_32)) ) { return -1; } if( ulWordLength == SPI_WL_8 ) { // // Do byte transfer // lRet = SPITransfer8(ulBase,ucDout,ucDin,ulCount,ulFlags); } else if( ulWordLength == SPI_WL_16 ) { // // Do half-word transfer // lRet = SPITransfer16(ulBase,(unsigned short *)ucDout, (unsigned short *)ucDin,ulCount,ulFlags); } else { // // Do word transfer // lRet = SPITransfer32(ulBase,(unsigned long *)ucDout, (unsigned long *)ucDin,ulCount,ulFlags); } // // return // return lRet; } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/spi.h000066400000000000000000000165501357706137100176020ustar00rootroot00000000000000//***************************************************************************** // // spi.h // // Defines and Macros for the SPI. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __SPI_H__ #define __SPI_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // Values that can be passed to SPIConfigSetExpClk() as ulMode parameter //***************************************************************************** #define SPI_MODE_MASTER 0x00000000 #define SPI_MODE_SLAVE 0x00000004 //***************************************************************************** // Values that can be passed to SPIConfigSetExpClk() as ulSubMode parameter //***************************************************************************** #define SPI_SUB_MODE_0 0x00000000 #define SPI_SUB_MODE_1 0x00000001 #define SPI_SUB_MODE_2 0x00000002 #define SPI_SUB_MODE_3 0x00000003 //***************************************************************************** // Values that can be passed to SPIConfigSetExpClk() as ulConfigFlags parameter //***************************************************************************** #define SPI_SW_CTRL_CS 0x01000000 #define SPI_HW_CTRL_CS 0x00000000 #define SPI_3PIN_MODE 0x02000000 #define SPI_4PIN_MODE 0x00000000 #define SPI_TURBO_ON 0x00080000 #define SPI_TURBO_OFF 0x00000000 #define SPI_CS_ACTIVEHIGH 0x00000000 #define SPI_CS_ACTIVELOW 0x00000040 #define SPI_WL_8 0x00000380 #define SPI_WL_16 0x00000780 #define SPI_WL_32 0x00000F80 //***************************************************************************** // Values that can be passed to SPIFIFOEnable() and SPIFIFODisable() //***************************************************************************** #define SPI_TX_FIFO 0x08000000 #define SPI_RX_FIFO 0x10000000 //***************************************************************************** // Values that can be passed to SPIDMAEnable() and SPIDMADisable() //***************************************************************************** #define SPI_RX_DMA 0x00008000 #define SPI_TX_DMA 0x00004000 //***************************************************************************** // Values that can be passed to SPIIntEnable(), SPIIntDiasble(), // SPIIntClear() or returned from SPIStatus() //***************************************************************************** #define SPI_INT_DMATX 0x20000000 #define SPI_INT_DMARX 0x10000000 #define SPI_INT_EOW 0x00020000 #define SPI_INT_WKS 0x00010000 #define SPI_INT_RX_OVRFLOW 0x00000008 #define SPI_INT_RX_FULL 0x00000004 #define SPI_INT_TX_UDRFLOW 0x00000002 #define SPI_INT_TX_EMPTY 0x00000001 //***************************************************************************** // Values that can be passed to SPITransfer() //***************************************************************************** #define SPI_CS_ENABLE 0x00000001 #define SPI_CS_DISABLE 0x00000002 //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void SPIEnable(unsigned long ulBase); extern void SPIDisable(unsigned long ulBase); extern void SPIReset(unsigned long ulBase); extern void SPIConfigSetExpClk(unsigned long ulBase,unsigned long ulSPIClk, unsigned long ulBitRate, unsigned long ulMode, unsigned long ulSubMode, unsigned long ulConfig); extern long SPIDataGetNonBlocking(unsigned long ulBase, unsigned long * pulData); extern void SPIDataGet(unsigned long ulBase, unsigned long *pulData); extern long SPIDataPutNonBlocking(unsigned long ulBase, unsigned long ulData); extern void SPIDataPut(unsigned long ulBase, unsigned long ulData); extern void SPIFIFOEnable(unsigned long ulBase, unsigned long ulFlags); extern void SPIFIFODisable(unsigned long ulBase, unsigned long ulFlags); extern void SPIFIFOLevelSet(unsigned long ulBase, unsigned long ulTxLevel, unsigned long ulRxLevel); extern void SPIFIFOLevelGet(unsigned long ulBase, unsigned long *pulTxLevel, unsigned long *pulRxLevel); extern void SPIWordCountSet(unsigned long ulBase, unsigned long ulWordCount); extern void SPIIntRegister(unsigned long ulBase, void(*pfnHandler)(void)); extern void SPIIntUnregister(unsigned long ulBase); extern void SPIIntEnable(unsigned long ulBase, unsigned long ulIntFlags); extern void SPIIntDisable(unsigned long ulBase, unsigned long ulIntFlags); extern unsigned long SPIIntStatus(unsigned long ulBase, tBoolean bMasked); extern void SPIIntClear(unsigned long ulBase, unsigned long ulIntFlags); extern void SPIDmaEnable(unsigned long ulBase, unsigned long ulFlags); extern void SPIDmaDisable(unsigned long ulBase, unsigned long ulFlags); extern void SPICSEnable(unsigned long ulBase); extern void SPICSDisable(unsigned long ulBase); extern long SPITransfer(unsigned long ulBase, unsigned char *ucDout, unsigned char *ucDin, unsigned long ulSize, unsigned long ulFlags); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __SPI_H__ micropython-1.12/ports/cc3200/hal/startup_gcc.c000066400000000000000000000371201357706137100213140ustar00rootroot00000000000000//***************************************************************************** // startup_gcc.c // // Startup code for use with GCC. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #include #include "inc/hw_nvic.h" #include "inc/hw_types.h" #include "fault_registers.h" //***************************************************************************** // // The following are constructs created by the linker, indicating where the // the "data" and "bss" segments reside in memory. The initializers for the // for the "data" segment resides immediately following the "text" segment. // //***************************************************************************** extern uint32_t _data; extern uint32_t _edata; extern uint32_t _bss; extern uint32_t _ebss; extern uint32_t _estack; //***************************************************************************** // // Forward declaration of the default fault handlers. // //***************************************************************************** #ifndef BOOTLOADER __attribute__ ((section (".boot"))) #endif void ResetISR(void); #ifdef DEBUG static void NmiSR(void) __attribute__( ( naked ) ); static void FaultISR( void ) __attribute__( ( naked ) ); void HardFault_HandlerC(uint32_t *pulFaultStackAddress); static void BusFaultHandler(void) __attribute__( ( naked ) ); #endif static void IntDefaultHandler(void) __attribute__( ( naked ) ); //***************************************************************************** // // External declaration for the freeRTOS handlers // //***************************************************************************** #ifdef USE_FREERTOS extern void vPortSVCHandler(void); extern void xPortPendSVHandler(void); extern void xPortSysTickHandler(void); #endif //***************************************************************************** // // The entry point for the application. // //***************************************************************************** extern int main(void); //***************************************************************************** // // The vector table. Note that the proper constructs must be placed on this to // ensure that it ends up at physical address 0x0000.0000. // //***************************************************************************** __attribute__ ((section(".intvecs"))) void (* const g_pfnVectors[256])(void) = { (void (*)(void))((uint32_t)&_estack), // The initial stack pointer ResetISR, // The reset handler #ifdef DEBUG NmiSR, // The NMI handler FaultISR, // The hard fault handler #else IntDefaultHandler, // The NMI handler IntDefaultHandler, // The hard fault handler #endif IntDefaultHandler, // The MPU fault handler #ifdef DEBUG BusFaultHandler, // The bus fault handler #else IntDefaultHandler, // The bus fault handler #endif IntDefaultHandler, // The usage fault handler 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved #ifdef USE_FREERTOS vPortSVCHandler, // SVCall handler #else IntDefaultHandler, // SVCall handler #endif IntDefaultHandler, // Debug monitor handler 0, // Reserved #ifdef USE_FREERTOS xPortPendSVHandler, // The PendSV handler xPortSysTickHandler, // The SysTick handler #else IntDefaultHandler, // The PendSV handler IntDefaultHandler, // The SysTick handler #endif IntDefaultHandler, // GPIO Port A IntDefaultHandler, // GPIO Port B IntDefaultHandler, // GPIO Port C IntDefaultHandler, // GPIO Port D 0, // Reserved IntDefaultHandler, // UART0 Rx and Tx IntDefaultHandler, // UART1 Rx and Tx 0, // Reserved IntDefaultHandler, // I2C0 Master and Slave 0,0,0,0,0, // Reserved IntDefaultHandler, // ADC Channel 0 IntDefaultHandler, // ADC Channel 1 IntDefaultHandler, // ADC Channel 2 IntDefaultHandler, // ADC Channel 3 IntDefaultHandler, // Watchdog Timer IntDefaultHandler, // Timer 0 subtimer A IntDefaultHandler, // Timer 0 subtimer B IntDefaultHandler, // Timer 1 subtimer A IntDefaultHandler, // Timer 1 subtimer B IntDefaultHandler, // Timer 2 subtimer A IntDefaultHandler, // Timer 2 subtimer B 0,0,0,0, // Reserved IntDefaultHandler, // Flash 0,0,0,0,0, // Reserved IntDefaultHandler, // Timer 3 subtimer A IntDefaultHandler, // Timer 3 subtimer B 0,0,0,0,0,0,0,0,0, // Reserved IntDefaultHandler, // uDMA Software Transfer IntDefaultHandler, // uDMA Error 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved IntDefaultHandler, // SHA 0,0, // Reserved IntDefaultHandler, // AES 0, // Reserved IntDefaultHandler, // DES 0,0,0,0,0, // Reserved IntDefaultHandler, // SDHost 0, // Reserved IntDefaultHandler, // I2S 0, // Reserved IntDefaultHandler, // Camera 0,0,0,0,0,0,0, // Reserved IntDefaultHandler, // NWP to APPS Interrupt IntDefaultHandler, // Power, Reset and Clock module 0,0, // Reserved IntDefaultHandler, // Shared SPI IntDefaultHandler, // Generic SPI IntDefaultHandler, // Link SPI 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0,0,0,0,0,0,0,0,0, // Reserved 0,0 // Reserved }; //***************************************************************************** // // This is the code that gets called when the processor first starts execution // following a reset event. Only the absolutely necessary set is performed, // after which the application supplied entry() routine is called. Any fancy // actions (such as making decisions based on the reset cause register, and // resetting the bits in that register) are left solely in the hands of the // application. // //***************************************************************************** void ResetISR(void) { #if defined(DEBUG) && !defined(BOOTLOADER) { // // Fill the main stack with a known value so that // we can measure the main stack high water mark // __asm volatile ( "ldr r0, =_stack \n" "ldr r1, =_estack \n" "mov r2, #0x55555555 \n" ".thumb_func \n" "fill_loop: \n" "cmp r0, r1 \n" "it lt \n" "strlt r2, [r0], #4 \n" "blt fill_loop \n" ); } #endif { // Get the initial stack pointer location from the vector table // and write this value to the msp register __asm volatile ( "ldr r0, =_text \n" "ldr r0, [r0] \n" "msr msp, r0 \n" ); } { // // Zero fill the bss segment. // __asm volatile ( "ldr r0, =_bss \n" "ldr r1, =_ebss \n" "mov r2, #0 \n" ".thumb_func \n" "zero_loop: \n" "cmp r0, r1 \n" "it lt \n" "strlt r2, [r0], #4 \n" "blt zero_loop \n" ); } { // // Call the application's entry point. // main(); } } #ifdef DEBUG //***************************************************************************** // // This is the code that gets called when the processor receives a NMI. This // simply enters an infinite loop, preserving the system state for examination // by a debugger. // //***************************************************************************** static void NmiSR(void) { // Break into the debugger __asm volatile ("bkpt #0 \n"); // // Enter an infinite loop. // for ( ; ; ) { } } //***************************************************************************** // // This is the code that gets called when the processor receives a hard fault // interrupt. This simply enters an infinite loop, preserving the system state // for examination by a debugger. // //***************************************************************************** static void FaultISR(void) { /* * Get the appropriate stack pointer, depending on our mode, * and use it as the parameter to the C handler. This function * will never return */ __asm volatile ( "movs r0, #4 \n" "mov r1, lr \n" "tst r0, r1 \n" "beq _msp \n" "mrs r0, psp \n" "b HardFault_HandlerC \n" "_msp: \n" "mrs r0, msp \n" "b HardFault_HandlerC \n" ) ; } //*********************************************************************************** // HardFaultHandler_C: // This is called from the FaultISR with a pointer the Fault stack // as the parameter. We can then read the values from the stack and place them // into local variables for ease of reading. // We then read the various Fault Status and Address Registers to help decode // cause of the fault. // The function ends with a BKPT instruction to force control back into the debugger //*********************************************************************************** void HardFault_HandlerC(uint32_t *pulFaultStackAddress) { volatile uint32_t r0 ; volatile uint32_t r1 ; volatile uint32_t r2 ; volatile uint32_t r3 ; volatile uint32_t r12 ; volatile uint32_t lr ; volatile uint32_t pc ; volatile uint32_t psr ; volatile _CFSR_t _CFSR ; volatile _HFSR_t _HFSR ; volatile uint32_t _BFAR ; r0 = pulFaultStackAddress[0]; r1 = pulFaultStackAddress[1]; r2 = pulFaultStackAddress[2]; r3 = pulFaultStackAddress[3]; r12 = pulFaultStackAddress[4]; lr = pulFaultStackAddress[5]; pc = pulFaultStackAddress[6]; psr = pulFaultStackAddress[7]; // Configurable Fault Status Register // Consists of MMSR, BFSR and UFSR _CFSR = (*((volatile _CFSR_t *)(0xE000ED28))); // Hard Fault Status Register _HFSR = (*((volatile _HFSR_t *)(0xE000ED2C))); // Bus Fault Address Register _BFAR = (*((volatile uint32_t *)(0xE000ED38))); // Break into the debugger __asm volatile ("bkpt #0 \n"); for ( ; ; ) { // Keep the compiler happy (void)r0, (void)r1, (void)r2, (void)r3, (void)r12, (void)lr, (void)pc, (void)psr; (void)_CFSR, (void)_HFSR, (void)_BFAR; } } //***************************************************************************** // // This is the code that gets called when the processor receives an unexpected // interrupt. This simply enters an infinite loop, preserving the system state // for examination by a debugger. // //***************************************************************************** static void BusFaultHandler(void) { // Break into the debugger __asm volatile ("bkpt #0 \n"); // // Enter an infinite loop. // for ( ; ; ) { } } #endif //***************************************************************************** // // This is the code that gets called when the processor receives an unexpected // interrupt. This simply enters an infinite loop, preserving the system state // for examination by a debugger. // //***************************************************************************** static void IntDefaultHandler(void) { #ifdef DEBUG // Break into the debugger __asm volatile ("bkpt #0 \n"); #endif // // Enter an infinite loop. // for ( ; ; ) { } } micropython-1.12/ports/cc3200/hal/systick.c000066400000000000000000000210611357706137100204640ustar00rootroot00000000000000//***************************************************************************** // // systick.c // // Driver for the SysTick timer in NVIC. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup systick_api //! @{ // //***************************************************************************** #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_types.h" #include "debug.h" #include "interrupt.h" #include "systick.h" //***************************************************************************** // //! Enables the SysTick counter. //! //! This function starts the SysTick counter. If an interrupt handler has been //! registered, it is called when the SysTick counter rolls over. //! //! \note Calling this function causes the SysTick counter to (re)commence //! counting from its current value. The counter is not automatically reloaded //! with the period as specified in a previous call to SysTickPeriodSet(). If //! an immediate reload is required, the \b NVIC_ST_CURRENT register must be //! written to force the reload. Any write to this register clears the SysTick //! counter to 0 and causes a reload with the supplied period on the next //! clock. //! //! \return None. // //***************************************************************************** void SysTickEnable(void) { // // Enable SysTick. // HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_ENABLE; } //***************************************************************************** // //! Disables the SysTick counter. //! //! This function stops the SysTick counter. If an interrupt handler has been //! registered, it is not called until SysTick is restarted. //! //! \return None. // //***************************************************************************** void SysTickDisable(void) { // // Disable SysTick. // HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_ENABLE); } //***************************************************************************** // //! Registers an interrupt handler for the SysTick interrupt. //! //! \param pfnHandler is a pointer to the function to be called when the //! SysTick interrupt occurs. //! //! This function registers the handler to be called when a SysTick interrupt //! occurs. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void SysTickIntRegister(void (*pfnHandler)(void)) { // // Register the interrupt handler, returning an error if an error occurs. // IntRegister(FAULT_SYSTICK, pfnHandler); // // Enable the SysTick interrupt. // HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN; } //***************************************************************************** // //! Unregisters the interrupt handler for the SysTick interrupt. //! //! This function unregisters the handler to be called when a SysTick interrupt //! occurs. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void SysTickIntUnregister(void) { // // Disable the SysTick interrupt. // HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN); // // Unregister the interrupt handler. // IntUnregister(FAULT_SYSTICK); } //***************************************************************************** // //! Enables the SysTick interrupt. //! //! This function enables the SysTick interrupt, allowing it to be //! reflected to the processor. //! //! \note The SysTick interrupt handler is not required to clear the SysTick //! interrupt source because it is cleared automatically by the NVIC when the //! interrupt handler is called. //! //! \return None. // //***************************************************************************** void SysTickIntEnable(void) { // // Enable the SysTick interrupt. // HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN; } //***************************************************************************** // //! Disables the SysTick interrupt. //! //! This function disables the SysTick interrupt, preventing it from being //! reflected to the processor. //! //! \return None. // //***************************************************************************** void SysTickIntDisable(void) { // // Disable the SysTick interrupt. // HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN); } //***************************************************************************** // //! Sets the period of the SysTick counter. //! //! \param ulPeriod is the number of clock ticks in each period of the SysTick //! counter and must be between 1 and 16,777,216, inclusive. //! //! This function sets the rate at which the SysTick counter wraps, which //! equates to the number of processor clocks between interrupts. //! //! \note Calling this function does not cause the SysTick counter to reload //! immediately. If an immediate reload is required, the \b NVIC_ST_CURRENT //! register must be written. Any write to this register clears the SysTick //! counter to 0 and causes a reload with the \e ulPeriod supplied here on //! the next clock after SysTick is enabled. //! //! \return None. // //***************************************************************************** void SysTickPeriodSet(unsigned long ulPeriod) { // // Check the arguments. // ASSERT((ulPeriod > 0) && (ulPeriod <= 16777216)); // // Set the period of the SysTick counter. // HWREG(NVIC_ST_RELOAD) = ulPeriod - 1; } //***************************************************************************** // //! Gets the period of the SysTick counter. //! //! This function returns the rate at which the SysTick counter wraps, which //! equates to the number of processor clocks between interrupts. //! //! \return Returns the period of the SysTick counter. // //***************************************************************************** unsigned long SysTickPeriodGet(void) { // // Return the period of the SysTick counter. // return(HWREG(NVIC_ST_RELOAD) + 1); } //***************************************************************************** // //! Gets the current value of the SysTick counter. //! //! This function returns the current value of the SysTick counter, which is //! a value between the period - 1 and zero, inclusive. //! //! \return Returns the current value of the SysTick counter. // //***************************************************************************** unsigned long SysTickValueGet(void) { // // Return the current value of the SysTick counter. // return(HWREG(NVIC_ST_CURRENT)); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/systick.h000066400000000000000000000057641357706137100205050ustar00rootroot00000000000000//***************************************************************************** // // systick.h // // Prototypes for the SysTick driver. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __SYSTICK_H__ #define __SYSTICK_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** extern void SysTickEnable(void); extern void SysTickDisable(void); extern void SysTickIntRegister(void (*pfnHandler)(void)); extern void SysTickIntUnregister(void); extern void SysTickIntEnable(void); extern void SysTickIntDisable(void); extern void SysTickPeriodSet(unsigned long ulPeriod); extern unsigned long SysTickPeriodGet(void); extern unsigned long SysTickValueGet(void); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __SYSTICK_H__ micropython-1.12/ports/cc3200/hal/timer.c000066400000000000000000001066001357706137100201160ustar00rootroot00000000000000//***************************************************************************** // // timer.c // // Driver for the timer module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup GPT_General_Purpose_Timer_api //! @{ // //***************************************************************************** #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_timer.h" #include "inc/hw_types.h" #include "debug.h" #include "interrupt.h" #include "timer.h" //***************************************************************************** // //! \internal //! Checks a timer base address. //! //! \param ulBase is the base address of the timer module. //! //! This function determines if a timer module base address is valid. //! //! \return Returns \b true if the base address is valid and \b false //! otherwise. // //***************************************************************************** #ifdef DEBUG static tBoolean TimerBaseValid(unsigned long ulBase) { return((ulBase == TIMERA0_BASE) || (ulBase == TIMERA1_BASE) || (ulBase == TIMERA2_BASE) || (ulBase == TIMERA3_BASE)); } #else #define TimerBaseValid(ulBase) (ulBase) #endif //***************************************************************************** // //! Enables the timer(s). //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to enable; must be one of \b TIMER_A, //! \b TIMER_B, or \b TIMER_BOTH. //! //! This function enables operation of the timer module. The timer must be //! configured before it is enabled. //! //! \return None. // //***************************************************************************** void TimerEnable(unsigned long ulBase, unsigned long ulTimer) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Enable the timer(s) module. // HWREG(ulBase + TIMER_O_CTL) |= ulTimer & (TIMER_CTL_TAEN | TIMER_CTL_TBEN); } //***************************************************************************** // //! Disables the timer(s). //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to disable; must be one of //! \b TIMER_A, \b TIMER_B, or \b TIMER_BOTH. //! //! This function disables operation of the timer module. //! //! \return None. // //***************************************************************************** void TimerDisable(unsigned long ulBase, unsigned long ulTimer) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Disable the timer module. // HWREG(ulBase + TIMER_O_CTL) &= ~(ulTimer & (TIMER_CTL_TAEN | TIMER_CTL_TBEN)); } //***************************************************************************** // //! Configures the timer(s). //! //! \param ulBase is the base address of the timer module. //! \param ulConfig is the configuration for the timer. //! //! This function configures the operating mode of the timer(s). The timer //! module is disabled before being configured, and is left in the disabled //! state. The 16/32-bit timer is comprised of two 16-bit timers that can //! operate independently or be concatenated to form a 32-bit timer. //! //! The configuration is specified in \e ulConfig as one of the following //! values: //! //! - \b TIMER_CFG_ONE_SHOT - Full-width one-shot timer //! - \b TIMER_CFG_ONE_SHOT_UP - Full-width one-shot timer that counts up //! instead of down (not available on all parts) //! - \b TIMER_CFG_PERIODIC - Full-width periodic timer //! - \b TIMER_CFG_PERIODIC_UP - Full-width periodic timer that counts up //! instead of down (not available on all parts) //! - \b TIMER_CFG_SPLIT_PAIR - Two half-width timers //! //! When configured for a pair of half-width timers, each timer is separately //! configured. The first timer is configured by setting \e ulConfig to //! the result of a logical OR operation between one of the following values //! and \e ulConfig: //! //! - \b TIMER_CFG_A_ONE_SHOT - Half-width one-shot timer //! - \b TIMER_CFG_A_ONE_SHOT_UP - Half-width one-shot timer that counts up //! instead of down (not available on all parts) //! - \b TIMER_CFG_A_PERIODIC - Half-width periodic timer //! - \b TIMER_CFG_A_PERIODIC_UP - Half-width periodic timer that counts up //! instead of down (not available on all parts) //! - \b TIMER_CFG_A_CAP_COUNT - Half-width edge count capture //! - \b TIMER_CFG_A_CAP_TIME - Half-width edge time capture //! - \b TIMER_CFG_A_PWM - Half-width PWM output //! //! Similarly, the second timer is configured by setting \e ulConfig to //! the result of a logical OR operation between one of the corresponding //! \b TIMER_CFG_B_* values and \e ulConfig. //! //! \return None. // //***************************************************************************** void TimerConfigure(unsigned long ulBase, unsigned long ulConfig) { ASSERT((ulConfig == TIMER_CFG_ONE_SHOT) || (ulConfig == TIMER_CFG_ONE_SHOT_UP) || (ulConfig == TIMER_CFG_PERIODIC) || (ulConfig == TIMER_CFG_PERIODIC_UP) || ((ulConfig & 0xff000000) == TIMER_CFG_SPLIT_PAIR)); ASSERT(((ulConfig & 0xff000000) != TIMER_CFG_SPLIT_PAIR) || ((((ulConfig & 0x000000ff) == TIMER_CFG_A_ONE_SHOT) || ((ulConfig & 0x000000ff) == TIMER_CFG_A_ONE_SHOT_UP) || ((ulConfig & 0x000000ff) == TIMER_CFG_A_PERIODIC) || ((ulConfig & 0x000000ff) == TIMER_CFG_A_PERIODIC_UP) || ((ulConfig & 0x000000ff) == TIMER_CFG_A_CAP_COUNT) || ((ulConfig & 0x000000ff) == TIMER_CFG_A_CAP_TIME) || ((ulConfig & 0x000000ff) == TIMER_CFG_A_PWM)) && (((ulConfig & 0x0000ff00) == TIMER_CFG_B_ONE_SHOT) || ((ulConfig & 0x0000ff00) == TIMER_CFG_B_ONE_SHOT_UP) || ((ulConfig & 0x0000ff00) == TIMER_CFG_B_PERIODIC) || ((ulConfig & 0x0000ff00) == TIMER_CFG_B_PERIODIC_UP) || ((ulConfig & 0x0000ff00) == TIMER_CFG_B_CAP_COUNT) || ((ulConfig & 0x0000ff00) == TIMER_CFG_B_CAP_TIME) || ((ulConfig & 0x0000ff00) == TIMER_CFG_B_PWM)))); // // Enable CCP to IO path // HWREG(0x440260B0) = 0xFF; // // Disable the timers. // HWREG(ulBase + TIMER_O_CTL) &= ~(TIMER_CTL_TAEN | TIMER_CTL_TBEN); // // Set the global timer configuration. // HWREG(ulBase + TIMER_O_CFG) = ulConfig >> 24; // // Set the configuration of the A and B timers. Note that the B timer // configuration is ignored by the hardware in 32-bit modes. // HWREG(ulBase + TIMER_O_TAMR) = ulConfig & 255; HWREG(ulBase + TIMER_O_TBMR) = (ulConfig >> 8) & 255; } //***************************************************************************** // //! Controls the output level. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to adjust; must be one of \b TIMER_A, //! \b TIMER_B, or \b TIMER_BOTH. //! \param bInvert specifies the output level. //! //! This function sets the PWM output level for the specified timer. If the //! \e bInvert parameter is \b true, then the timer's output is made active //! low; otherwise, it is made active high. //! //! \return None. // //***************************************************************************** void TimerControlLevel(unsigned long ulBase, unsigned long ulTimer, tBoolean bInvert) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Set the output levels as requested. // ulTimer &= TIMER_CTL_TAPWML | TIMER_CTL_TBPWML; HWREG(ulBase + TIMER_O_CTL) = (bInvert ? (HWREG(ulBase + TIMER_O_CTL) | ulTimer) : (HWREG(ulBase + TIMER_O_CTL) & ~(ulTimer))); } //***************************************************************************** // //! Controls the event type. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to be adjusted; must be one of //! \b TIMER_A, \b TIMER_B, or \b TIMER_BOTH. //! \param ulEvent specifies the type of event; must be one of //! \b TIMER_EVENT_POS_EDGE, \b TIMER_EVENT_NEG_EDGE, or //! \b TIMER_EVENT_BOTH_EDGES. //! //! This function sets the signal edge(s) that triggers the timer when in //! capture mode. //! //! \return None. // //***************************************************************************** void TimerControlEvent(unsigned long ulBase, unsigned long ulTimer, unsigned long ulEvent) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Set the event type. // ulEvent &= ulTimer & (TIMER_CTL_TAEVENT_M | TIMER_CTL_TBEVENT_M); HWREG(ulBase + TIMER_O_CTL) = ((HWREG(ulBase + TIMER_O_CTL) & ~(TIMER_CTL_TAEVENT_M | TIMER_CTL_TBEVENT_M)) | ulEvent); } //***************************************************************************** // //! Controls the stall handling. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to be adjusted; must be one of //! \b TIMER_A, \b TIMER_B, or \b TIMER_BOTH. //! \param bStall specifies the response to a stall signal. //! //! This function controls the stall response for the specified timer. If the //! \e bStall parameter is \b true, then the timer stops counting if the //! processor enters debug mode; otherwise the timer keeps running while in //! debug mode. //! //! \return None. // //***************************************************************************** void TimerControlStall(unsigned long ulBase, unsigned long ulTimer, tBoolean bStall) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Set the stall mode. // ulTimer &= TIMER_CTL_TASTALL | TIMER_CTL_TBSTALL; HWREG(ulBase + TIMER_O_CTL) = (bStall ? (HWREG(ulBase + TIMER_O_CTL) | ulTimer) : (HWREG(ulBase + TIMER_O_CTL) & ~(ulTimer))); } //***************************************************************************** // //! Set the timer prescale value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to adjust; must be one of \b TIMER_A, //! \b TIMER_B, or \b TIMER_BOTH. //! \param ulValue is the timer prescale value which must be between 0 and 255 //! (inclusive) for 16/32-bit timers. //! //! This function sets the value of the input clock prescaler. The prescaler //! is only operational when in half-width mode and is used to extend the range //! of the half-width timer modes. //! //! \return None. // //***************************************************************************** void TimerPrescaleSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); ASSERT(ulValue < 256); // // Set the timer A prescaler if requested. // if(ulTimer & TIMER_A) { HWREG(ulBase + TIMER_O_TAPR) = ulValue; } // // Set the timer B prescaler if requested. // if(ulTimer & TIMER_B) { HWREG(ulBase + TIMER_O_TBPR) = ulValue; } } //***************************************************************************** // //! Get the timer prescale value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer; must be one of \b TIMER_A or //! \b TIMER_B. //! //! This function gets the value of the input clock prescaler. The prescaler //! is only operational when in half-width mode and is used to extend the range //! of the half-width timer modes. //! //! \return The value of the timer prescaler. // //***************************************************************************** unsigned long TimerPrescaleGet(unsigned long ulBase, unsigned long ulTimer) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Return the appropriate prescale value. // return((ulTimer == TIMER_A) ? HWREG(ulBase + TIMER_O_TAPR) : HWREG(ulBase + TIMER_O_TBPR)); } //***************************************************************************** // //! Set the timer prescale match value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to adjust; must be one of \b TIMER_A, //! \b TIMER_B, or \b TIMER_BOTH. //! \param ulValue is the timer prescale match value which must be between 0 //! and 255 (inclusive) for 16/32-bit timers. //! //! This function sets the value of the input clock prescaler match value. //! When in a half-width mode that uses the counter match and the prescaler, //! the prescale match effectively extends the range of the match. //! //! \note The availability of the prescaler match varies with the //! part and timer mode in use. Please consult the datasheet for the part you //! are using to determine whether this support is available. //! //! \return None. // //***************************************************************************** void TimerPrescaleMatchSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); ASSERT(ulValue < 256); // // Set the timer A prescale match if requested. // if(ulTimer & TIMER_A) { HWREG(ulBase + TIMER_O_TAPMR) = ulValue; } // // Set the timer B prescale match if requested. // if(ulTimer & TIMER_B) { HWREG(ulBase + TIMER_O_TBPMR) = ulValue; } } //***************************************************************************** // //! Get the timer prescale match value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer; must be one of \b TIMER_A or //! \b TIMER_B. //! //! This function gets the value of the input clock prescaler match value. //! When in a half-width mode that uses the counter match and prescaler, the //! prescale match effectively extends the range of the match. //! //! \note The availability of the prescaler match varies with the //! part and timer mode in use. Please consult the datasheet for the part you //! are using to determine whether this support is available. //! //! \return The value of the timer prescale match. // //***************************************************************************** unsigned long TimerPrescaleMatchGet(unsigned long ulBase, unsigned long ulTimer) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Return the appropriate prescale match value. // return((ulTimer == TIMER_A) ? HWREG(ulBase + TIMER_O_TAPMR) : HWREG(ulBase + TIMER_O_TBPMR)); } //***************************************************************************** // //! Sets the timer load value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to adjust; must be one of \b TIMER_A, //! \b TIMER_B, or \b TIMER_BOTH. Only \b TIMER_A should be used when the //! timer is configured for full-width operation. //! \param ulValue is the load value. //! //! This function sets the timer load value; if the timer is running then the //! value is immediately loaded into the timer. //! //! \note This function can be used for both full- and half-width modes of //! 16/32-bit timers. //! //! \return None. // //***************************************************************************** void TimerLoadSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Set the timer A load value if requested. // if(ulTimer & TIMER_A) { HWREG(ulBase + TIMER_O_TAILR) = ulValue; } // // Set the timer B load value if requested. // if(ulTimer & TIMER_B) { HWREG(ulBase + TIMER_O_TBILR) = ulValue; } } //***************************************************************************** // //! Gets the timer load value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer; must be one of \b TIMER_A or //! \b TIMER_B. Only \b TIMER_A should be used when the timer is configured //! for full-width operation. //! //! This function gets the currently programmed interval load value for the //! specified timer. //! //! \note This function can be used for both full- and half-width modes of //! 16/32-bit timers. //! //! \return Returns the load value for the timer. // //***************************************************************************** unsigned long TimerLoadGet(unsigned long ulBase, unsigned long ulTimer) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B)); // // Return the appropriate load value. // return((ulTimer == TIMER_A) ? HWREG(ulBase + TIMER_O_TAILR) : HWREG(ulBase + TIMER_O_TBILR)); } //***************************************************************************** // //! Gets the current timer value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer; must be one of \b TIMER_A or //! \b TIMER_B. Only \b TIMER_A should be used when the timer is configured //! for 32-bit operation. //! //! This function reads the current value of the specified timer. //! //! \return Returns the current value of the timer. // //***************************************************************************** unsigned long TimerValueGet(unsigned long ulBase, unsigned long ulTimer) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B)); // // Return the appropriate timer value. // return((ulTimer == TIMER_A) ? HWREG(ulBase + TIMER_O_TAR) : HWREG(ulBase + TIMER_O_TBR)); } //***************************************************************************** // //! Sets the current timer value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer; must be one of \b TIMER_A or //! \b TIMER_B. Only \b TIMER_A should be used when the timer is configured //! for 32-bit operation. //! \param ulValue is the new value of the timer to be set. //! //! This function sets the current value of the specified timer. //! //! \return None. // //***************************************************************************** void TimerValueSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B)); // // Set the appropriate timer value. // if( (ulTimer == TIMER_A) ) { HWREG(ulBase + TIMER_O_TAV) = ulValue; } else { HWREG(ulBase + TIMER_O_TBV) = ulValue; } } //***************************************************************************** // //! Sets the timer match value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s) to adjust; must be one of \b TIMER_A, //! \b TIMER_B, or \b TIMER_BOTH. Only \b TIMER_A should be used when the //! timer is configured for 32-bit operation. //! \param ulValue is the match value. //! //! This function sets the match value for a timer. This is used in capture //! count mode to determine when to interrupt the processor and in PWM mode to //! determine the duty cycle of the output signal. //! //! \return None. // //***************************************************************************** void TimerMatchSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Set the timer A match value if requested. // if(ulTimer & TIMER_A) { HWREG(ulBase + TIMER_O_TAMATCHR) = ulValue; } // // Set the timer B match value if requested. // if(ulTimer & TIMER_B) { HWREG(ulBase + TIMER_O_TBMATCHR) = ulValue; } } //***************************************************************************** // //! Gets the timer match value. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer; must be one of \b TIMER_A or //! \b TIMER_B. Only \b TIMER_A should be used when the timer is configured //! for 32-bit operation. //! //! This function gets the match value for the specified timer. //! //! \return Returns the match value for the timer. // //******************************************************************************** unsigned long TimerMatchGet(unsigned long ulBase, unsigned long ulTimer) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B)); // // Return the appropriate match value. // return((ulTimer == TIMER_A) ? HWREG(ulBase + TIMER_O_TAMATCHR) : HWREG(ulBase + TIMER_O_TBMATCHR)); } //***************************************************************************** // //! Registers an interrupt handler for the timer interrupt. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s); must be one of \b TIMER_A, //! \b TIMER_B, or \b TIMER_BOTH. //! \param pfnHandler is a pointer to the function to be called when the timer //! interrupt occurs. //! //! This function sets the handler to be called when a timer interrupt occurs. //! In addition, this function enables the global interrupt in the interrupt //! controller; specific timer interrupts must be enabled via TimerIntEnable(). //! It is the interrupt handler's responsibility to clear the interrupt source //! via TimerIntClear(). //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void TimerIntRegister(unsigned long ulBase, unsigned long ulTimer, void (*pfnHandler)(void)) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); ulBase = ((ulBase == TIMERA0_BASE) ? INT_TIMERA0A : ((ulBase == TIMERA1_BASE) ? INT_TIMERA1A : ((ulBase == TIMERA2_BASE) ? INT_TIMERA2A : INT_TIMERA3A))); // // Register an interrupt handler for timer A if requested. // if(ulTimer & TIMER_A) { // // Register the interrupt handler. // IntRegister(ulBase, pfnHandler); // // Enable the interrupt. // IntEnable(ulBase); } // // Register an interrupt handler for timer B if requested. // if(ulTimer & TIMER_B) { // // Register the interrupt handler. // IntRegister(ulBase + 1, pfnHandler); // // Enable the interrupt. // IntEnable(ulBase + 1); } } //***************************************************************************** // //! Unregisters an interrupt handler for the timer interrupt. //! //! \param ulBase is the base address of the timer module. //! \param ulTimer specifies the timer(s); must be one of \b TIMER_A, //! \b TIMER_B, or \b TIMER_BOTH. //! //! This function clears the handler to be called when a timer interrupt //! occurs. This function also masks off the interrupt in the interrupt //! controller so that the interrupt handler no longer is called. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void TimerIntUnregister(unsigned long ulBase, unsigned long ulTimer) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); ASSERT((ulTimer == TIMER_A) || (ulTimer == TIMER_B) || (ulTimer == TIMER_BOTH)); // // Get the interrupt number for this timer module. // ulBase = ((ulBase == TIMERA0_BASE) ? INT_TIMERA0A : ((ulBase == TIMERA1_BASE) ? INT_TIMERA1A : ((ulBase == TIMERA2_BASE) ? INT_TIMERA2A : INT_TIMERA3A))); // // Unregister the interrupt handler for timer A if requested. // if(ulTimer & TIMER_A) { // // Disable the interrupt. // IntDisable(ulBase); // // Unregister the interrupt handler. // IntUnregister(ulBase); } // // Unregister the interrupt handler for timer B if requested. // if(ulTimer & TIMER_B) { // // Disable the interrupt. // IntDisable(ulBase + 1); // // Unregister the interrupt handler. // IntUnregister(ulBase + 1); } } //***************************************************************************** // //! Enables individual timer interrupt sources. //! //! \param ulBase is the base address of the timer module. //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled. //! //! Enables the indicated timer interrupt sources. Only the sources that are //! enabled can be reflected to the processor interrupt; disabled sources have //! no effect on the processor. //! //! The \e ulIntFlags parameter must be the logical OR of any combination of //! the following: //! //! - \b TIMER_CAPB_EVENT - Capture B event interrupt //! - \b TIMER_CAPB_MATCH - Capture B match interrupt //! - \b TIMER_TIMB_TIMEOUT - Timer B timeout interrupt //! - \b TIMER_CAPA_EVENT - Capture A event interrupt //! - \b TIMER_CAPA_MATCH - Capture A match interrupt //! - \b TIMER_TIMA_TIMEOUT - Timer A timeout interrupt //! //! \return None. // //***************************************************************************** void TimerIntEnable(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); // // Enable the specified interrupts. // HWREG(ulBase + TIMER_O_IMR) |= ulIntFlags; } //***************************************************************************** // //! Disables individual timer interrupt sources. //! //! \param ulBase is the base address of the timer module. //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled. //! //! Disables the indicated timer interrupt sources. Only the sources that are //! enabled can be reflected to the processor interrupt; disabled sources have //! no effect on the processor. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to TimerIntEnable(). //! //! \return None. // //***************************************************************************** void TimerIntDisable(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); // // Disable the specified interrupts. // HWREG(ulBase + TIMER_O_IMR) &= ~(ulIntFlags); } //***************************************************************************** // //! Gets the current interrupt status. //! //! \param ulBase is the base address of the timer module. //! \param bMasked is false if the raw interrupt status is required and true if //! the masked interrupt status is required. //! //! This function returns the interrupt status for the timer module. Either //! the raw interrupt status or the status of interrupts that are allowed to //! reflect to the processor can be returned. //! //! \return The current interrupt status, enumerated as a bit field of //! values described in TimerIntEnable(). // //***************************************************************************** unsigned long TimerIntStatus(unsigned long ulBase, tBoolean bMasked) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); // // Return either the interrupt status or the raw interrupt status as // requested. // return(bMasked ? HWREG(ulBase + TIMER_O_MIS) : HWREG(ulBase + TIMER_O_RIS)); } //***************************************************************************** // //! Clears timer interrupt sources. //! //! \param ulBase is the base address of the timer module. //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared. //! //! The specified timer interrupt sources are cleared, so that they no longer //! assert. This function must be called in the interrupt handler to keep the //! interrupt from being triggered again immediately upon exit. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to TimerIntEnable(). //! //! \note Because there is a write buffer in the Cortex-M3 processor, it may //! take several clock cycles before the interrupt source is actually cleared. //! Therefore, it is recommended that the interrupt source be cleared early in //! the interrupt handler (as opposed to the very last action) to avoid //! returning from the interrupt handler before the interrupt source is //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). //! //! \return None. // //***************************************************************************** void TimerIntClear(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); // // Clear the requested interrupt sources. // HWREG(ulBase + TIMER_O_ICR) = ulIntFlags; } //***************************************************************************** // //! Enables the events that can trigger a DMA request. //! //! \param ulBase is the base address of the timer module. //! \param ulDMAEvent is a bit mask of the events that can trigger DMA. //! //! This function enables the timer events that can trigger the start of a DMA //! sequence. The DMA trigger events are specified in the \e ui32DMAEvent //! parameter by passing in the logical OR of the following values: //! //! - \b TIMER_DMA_MODEMATCH_B - The mode match DMA trigger for timer B is //! enabled. //! - \b TIMER_DMA_CAPEVENT_B - The capture event DMA trigger for timer B is //! enabled. //! - \b TIMER_DMA_CAPMATCH_B - The capture match DMA trigger for timer B is //! enabled. //! - \b TIMER_DMA_TIMEOUT_B - The timeout DMA trigger for timer B is enabled. //! - \b TIMER_DMA_MODEMATCH_A - The mode match DMA trigger for timer A is //! enabled. //! - \b TIMER_DMA_CAPEVENT_A - The capture event DMA trigger for timer A is //! enabled. //! - \b TIMER_DMA_CAPMATCH_A - The capture match DMA trigger for timer A is //! enabled. //! - \b TIMER_DMA_TIMEOUT_A - The timeout DMA trigger for timer A is enabled. //! //! \return None. // //***************************************************************************** void TimerDMAEventSet(unsigned long ulBase, unsigned long ulDMAEvent) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); // // Set the DMA triggers. // HWREG(ulBase + TIMER_O_DMAEV) = ulDMAEvent; } //***************************************************************************** // //! Returns the events that can trigger a DMA request. //! //! \param ulBase is the base address of the timer module. //! //! This function returns the timer events that can trigger the start of a DMA //! sequence. The DMA trigger events are the logical OR of the following //! values: //! //! - \b TIMER_DMA_MODEMATCH_B - Enables the mode match DMA trigger for timer //! B. //! - \b TIMER_DMA_CAPEVENT_B - Enables the capture event DMA trigger for //! timer B. //! - \b TIMER_DMA_CAPMATCH_B - Enables the capture match DMA trigger for //! timer B. //! - \b TIMER_DMA_TIMEOUT_B - Enables the timeout DMA trigger for timer B. //! - \b TIMER_DMA_MODEMATCH_A - Enables the mode match DMA trigger for timer //! A. //! - \b TIMER_DMA_CAPEVENT_A - Enables the capture event DMA trigger for //! timer A. //! - \b TIMER_DMA_CAPMATCH_A - Enables the capture match DMA trigger for //! timer A. //! - \b TIMER_DMA_TIMEOUT_A - Enables the timeout DMA trigger for timer A. //! //! \return The timer events that trigger the uDMA. // //***************************************************************************** unsigned long TimerDMAEventGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(TimerBaseValid(ulBase)); // // Return the current DMA triggers. // return(HWREG(ulBase + TIMER_O_DMAEV)); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/timer.h000066400000000000000000000242631357706137100201270ustar00rootroot00000000000000//***************************************************************************** // // timer.h // // Prototypes for the timer module // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __TIMER_H__ #define __TIMER_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // Values that can be passed to TimerConfigure as the ulConfig parameter. // //***************************************************************************** #define TIMER_CFG_ONE_SHOT 0x00000021 // Full-width one-shot timer #define TIMER_CFG_ONE_SHOT_UP 0x00000031 // Full-width one-shot up-count // timer #define TIMER_CFG_PERIODIC 0x00000022 // Full-width periodic timer #define TIMER_CFG_PERIODIC_UP 0x00000032 // Full-width periodic up-count // timer #define TIMER_CFG_SPLIT_PAIR 0x04000000 // Two half-width timers #define TIMER_CFG_A_ONE_SHOT 0x00000021 // Timer A one-shot timer #define TIMER_CFG_A_ONE_SHOT_UP 0x00000031 // Timer A one-shot up-count timer #define TIMER_CFG_A_PERIODIC 0x00000022 // Timer A periodic timer #define TIMER_CFG_A_PERIODIC_UP 0x00000032 // Timer A periodic up-count timer #define TIMER_CFG_A_CAP_COUNT 0x00000003 // Timer A event counter #define TIMER_CFG_A_CAP_COUNT_UP 0x00000013 // Timer A event up-counter #define TIMER_CFG_A_CAP_TIME 0x00000007 // Timer A event timer #define TIMER_CFG_A_CAP_TIME_UP 0x00000017 // Timer A event up-count timer #define TIMER_CFG_A_PWM 0x0000000A // Timer A PWM output #define TIMER_CFG_B_ONE_SHOT 0x00002100 // Timer B one-shot timer #define TIMER_CFG_B_ONE_SHOT_UP 0x00003100 // Timer B one-shot up-count timer #define TIMER_CFG_B_PERIODIC 0x00002200 // Timer B periodic timer #define TIMER_CFG_B_PERIODIC_UP 0x00003200 // Timer B periodic up-count timer #define TIMER_CFG_B_CAP_COUNT 0x00000300 // Timer B event counter #define TIMER_CFG_B_CAP_COUNT_UP 0x00001300 // Timer B event up-counter #define TIMER_CFG_B_CAP_TIME 0x00000700 // Timer B event timer #define TIMER_CFG_B_CAP_TIME_UP 0x00001700 // Timer B event up-count timer #define TIMER_CFG_B_PWM 0x00000A00 // Timer B PWM output //***************************************************************************** // // Values that can be passed to TimerIntEnable, TimerIntDisable, and // TimerIntClear as the ulIntFlags parameter, and returned from TimerIntStatus. // //***************************************************************************** #define TIMER_TIMB_DMA 0x00002000 // TimerB DMA Done interrupt #define TIMER_TIMB_MATCH 0x00000800 // TimerB match interrupt #define TIMER_CAPB_EVENT 0x00000400 // CaptureB event interrupt #define TIMER_CAPB_MATCH 0x00000200 // CaptureB match interrupt #define TIMER_TIMB_TIMEOUT 0x00000100 // TimerB time out interrupt #define TIMER_TIMA_DMA 0x00000020 // TimerA DMA Done interrupt #define TIMER_TIMA_MATCH 0x00000010 // TimerA match interrupt #define TIMER_CAPA_EVENT 0x00000004 // CaptureA event interrupt #define TIMER_CAPA_MATCH 0x00000002 // CaptureA match interrupt #define TIMER_TIMA_TIMEOUT 0x00000001 // TimerA time out interrupt //***************************************************************************** // // Values that can be passed to TimerControlEvent as the ulEvent parameter. // //***************************************************************************** #define TIMER_EVENT_POS_EDGE 0x00000000 // Count positive edges #define TIMER_EVENT_NEG_EDGE 0x00000404 // Count negative edges #define TIMER_EVENT_BOTH_EDGES 0x00000C0C // Count both edges //***************************************************************************** // // Values that can be passed to most of the timer APIs as the ulTimer // parameter. // //***************************************************************************** #define TIMER_A 0x000000ff // Timer A #define TIMER_B 0x0000ff00 // Timer B #define TIMER_BOTH 0x0000ffff // Timer Both //***************************************************************************** // // Values that can be passed to TimerSynchronize as the ulTimers parameter. // //***************************************************************************** #define TIMER_0A_SYNC 0x00000001 // Synchronize Timer 0A #define TIMER_0B_SYNC 0x00000002 // Synchronize Timer 0B #define TIMER_1A_SYNC 0x00000004 // Synchronize Timer 1A #define TIMER_1B_SYNC 0x00000008 // Synchronize Timer 1B #define TIMER_2A_SYNC 0x00000010 // Synchronize Timer 2A #define TIMER_2B_SYNC 0x00000020 // Synchronize Timer 2B #define TIMER_3A_SYNC 0x00000040 // Synchronize Timer 3A #define TIMER_3B_SYNC 0x00000080 // Synchronize Timer 3B //***************************************************************************** // // Values that can be passed to TimerDMAEventSet() or returned from // TimerDMAEventGet(). // //***************************************************************************** #define TIMER_DMA_MODEMATCH_B 0x00000800 #define TIMER_DMA_CAPEVENT_B 0x00000400 #define TIMER_DMA_CAPMATCH_B 0x00000200 #define TIMER_DMA_TIMEOUT_B 0x00000100 #define TIMER_DMA_MODEMATCH_A 0x00000010 #define TIMER_DMA_CAPEVENT_A 0x00000004 #define TIMER_DMA_CAPMATCH_A 0x00000002 #define TIMER_DMA_TIMEOUT_A 0x00000001 //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** extern void TimerEnable(unsigned long ulBase, unsigned long ulTimer); extern void TimerDisable(unsigned long ulBase, unsigned long ulTimer); extern void TimerConfigure(unsigned long ulBase, unsigned long ulConfig); extern void TimerControlLevel(unsigned long ulBase, unsigned long ulTimer, tBoolean bInvert); extern void TimerControlEvent(unsigned long ulBase, unsigned long ulTimer, unsigned long ulEvent); extern void TimerControlStall(unsigned long ulBase, unsigned long ulTimer, tBoolean bStall); extern void TimerPrescaleSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue); extern unsigned long TimerPrescaleGet(unsigned long ulBase, unsigned long ulTimer); extern void TimerPrescaleMatchSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue); extern unsigned long TimerPrescaleMatchGet(unsigned long ulBase, unsigned long ulTimer); extern void TimerLoadSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue); extern unsigned long TimerLoadGet(unsigned long ulBase, unsigned long ulTimer); extern unsigned long TimerValueGet(unsigned long ulBase, unsigned long ulTimer); extern void TimerValueSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue); extern void TimerMatchSet(unsigned long ulBase, unsigned long ulTimer, unsigned long ulValue); extern unsigned long TimerMatchGet(unsigned long ulBase, unsigned long ulTimer); extern void TimerIntRegister(unsigned long ulBase, unsigned long ulTimer, void (*pfnHandler)(void)); extern void TimerIntUnregister(unsigned long ulBase, unsigned long ulTimer); extern void TimerIntEnable(unsigned long ulBase, unsigned long ulIntFlags); extern void TimerIntDisable(unsigned long ulBase, unsigned long ulIntFlags); extern unsigned long TimerIntStatus(unsigned long ulBase, tBoolean bMasked); extern void TimerIntClear(unsigned long ulBase, unsigned long ulIntFlags); extern void TimerDMAEventSet(unsigned long ulBase, unsigned long ulDMAEvent); extern unsigned long TimerDMAEventGet(unsigned long ulBase); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __TIMER_H__ micropython-1.12/ports/cc3200/hal/uart.c000066400000000000000000001342261357706137100177560ustar00rootroot00000000000000//***************************************************************************** // // uart.c // // Driver for the UART. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup UART_api //! @{ // //***************************************************************************** #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_uart.h" #include "debug.h" #include "interrupt.h" #include "uart.h" //***************************************************************************** // // A mapping of UART base address to interupt number. // //***************************************************************************** static const unsigned long g_ppulUARTIntMap[][2] = { { UARTA0_BASE, INT_UARTA0 }, { UARTA1_BASE, INT_UARTA1 }, }; //***************************************************************************** // //! \internal //! Checks a UART base address. //! //! \param ulBase is the base address of the UART port. //! //! This function determines if a UART port base address is valid. //! //! \return Returns \b true if the base address is valid and \b false //! otherwise. // //***************************************************************************** #ifdef DEBUG static tBoolean UARTBaseValid(unsigned long ulBase) { return((ulBase == UARTA0_BASE) || (ulBase == UARTA1_BASE)); } #else #define UARTBaseValid(ulBase) (ulBase) #endif //***************************************************************************** // //! \internal //! Gets the UART interrupt number. //! //! \param ulBase is the base address of the UART port. //! //! Given a UART base address, returns the corresponding interrupt number. //! //! \return Returns a UART interrupt number, or -1 if \e ulBase is invalid. // //***************************************************************************** static long UARTIntNumberGet(unsigned long ulBase) { unsigned long ulIdx; // // Loop through the table that maps UART base addresses to interrupt // numbers. // for(ulIdx = 0; ulIdx < (sizeof(g_ppulUARTIntMap) / sizeof(g_ppulUARTIntMap[0])); ulIdx++) { // // See if this base address matches. // if(g_ppulUARTIntMap[ulIdx][0] == ulBase) { // // Return the corresponding interrupt number. // return(g_ppulUARTIntMap[ulIdx][1]); } } // // The base address could not be found, so return an error. // return(-1); } //***************************************************************************** // //! Sets the type of parity. //! //! \param ulBase is the base address of the UART port. //! \param ulParity specifies the type of parity to use. //! //! This function sets the type of parity to use for transmitting and expect //! when receiving. The \e ulParity parameter must be one of //! \b UART_CONFIG_PAR_NONE, \b UART_CONFIG_PAR_EVEN, \b UART_CONFIG_PAR_ODD, //! \b UART_CONFIG_PAR_ONE, or \b UART_CONFIG_PAR_ZERO. The last two allow //! direct control of the parity bit; it is always either one or zero based on //! the mode. //! //! \return None. // //***************************************************************************** void UARTParityModeSet(unsigned long ulBase, unsigned long ulParity) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); ASSERT((ulParity == UART_CONFIG_PAR_NONE) || (ulParity == UART_CONFIG_PAR_EVEN) || (ulParity == UART_CONFIG_PAR_ODD) || (ulParity == UART_CONFIG_PAR_ONE) || (ulParity == UART_CONFIG_PAR_ZERO)); // // Set the parity mode. // HWREG(ulBase + UART_O_LCRH) = ((HWREG(ulBase + UART_O_LCRH) & ~(UART_LCRH_SPS | UART_LCRH_EPS | UART_LCRH_PEN)) | ulParity); } //***************************************************************************** // //! Gets the type of parity currently being used. //! //! \param ulBase is the base address of the UART port. //! //! This function gets the type of parity used for transmitting data and //! expected when receiving data. //! //! \return Returns the current parity settings, specified as one of //! \b UART_CONFIG_PAR_NONE, \b UART_CONFIG_PAR_EVEN, \b UART_CONFIG_PAR_ODD, //! \b UART_CONFIG_PAR_ONE, or \b UART_CONFIG_PAR_ZERO. // //***************************************************************************** unsigned long UARTParityModeGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Return the current parity setting. // return(HWREG(ulBase + UART_O_LCRH) & (UART_LCRH_SPS | UART_LCRH_EPS | UART_LCRH_PEN)); } //***************************************************************************** // //! Sets the FIFO level at which interrupts are generated. //! //! \param ulBase is the base address of the UART port. //! \param ulTxLevel is the transmit FIFO interrupt level, specified as one of //! \b UART_FIFO_TX1_8, \b UART_FIFO_TX2_8, \b UART_FIFO_TX4_8, //! \b UART_FIFO_TX6_8, or \b UART_FIFO_TX7_8. //! \param ulRxLevel is the receive FIFO interrupt level, specified as one of //! \b UART_FIFO_RX1_8, \b UART_FIFO_RX2_8, \b UART_FIFO_RX4_8, //! \b UART_FIFO_RX6_8, or \b UART_FIFO_RX7_8. //! //! This function sets the FIFO level at which transmit and receive interrupts //! are generated. //! //! \return None. // //***************************************************************************** void UARTFIFOLevelSet(unsigned long ulBase, unsigned long ulTxLevel, unsigned long ulRxLevel) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); ASSERT((ulTxLevel == UART_FIFO_TX1_8) || (ulTxLevel == UART_FIFO_TX2_8) || (ulTxLevel == UART_FIFO_TX4_8) || (ulTxLevel == UART_FIFO_TX6_8) || (ulTxLevel == UART_FIFO_TX7_8)); ASSERT((ulRxLevel == UART_FIFO_RX1_8) || (ulRxLevel == UART_FIFO_RX2_8) || (ulRxLevel == UART_FIFO_RX4_8) || (ulRxLevel == UART_FIFO_RX6_8) || (ulRxLevel == UART_FIFO_RX7_8)); // // Set the FIFO interrupt levels. // HWREG(ulBase + UART_O_IFLS) = ulTxLevel | ulRxLevel; } //***************************************************************************** // //! Gets the FIFO level at which interrupts are generated. //! //! \param ulBase is the base address of the UART port. //! \param pulTxLevel is a pointer to storage for the transmit FIFO level, //! returned as one of \b UART_FIFO_TX1_8, \b UART_FIFO_TX2_8, //! \b UART_FIFO_TX4_8, \b UART_FIFO_TX6_8, or \b UART_FIFO_TX7_8. //! \param pulRxLevel is a pointer to storage for the receive FIFO level, //! returned as one of \b UART_FIFO_RX1_8, \b UART_FIFO_RX2_8, //! \b UART_FIFO_RX4_8, \b UART_FIFO_RX6_8, or \b UART_FIFO_RX7_8. //! //! This function gets the FIFO level at which transmit and receive interrupts //! are generated. //! //! \return None. // //***************************************************************************** void UARTFIFOLevelGet(unsigned long ulBase, unsigned long *pulTxLevel, unsigned long *pulRxLevel) { unsigned long ulTemp; // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Read the FIFO level register. // ulTemp = HWREG(ulBase + UART_O_IFLS); // // Extract the transmit and receive FIFO levels. // *pulTxLevel = ulTemp & UART_IFLS_TX_M; *pulRxLevel = ulTemp & UART_IFLS_RX_M; } //***************************************************************************** // //! Sets the configuration of a UART. //! //! \param ulBase is the base address of the UART port. //! \param ulUARTClk is the rate of the clock supplied to the UART module. //! \param ulBaud is the desired baud rate. //! \param ulConfig is the data format for the port (number of data bits, //! number of stop bits, and parity). //! //! This function configures the UART for operation in the specified data //! format. The baud rate is provided in the \e ulBaud parameter and the data //! format in the \e ulConfig parameter. //! //! The \e ulConfig parameter is the logical OR of three values: the number of //! data bits, the number of stop bits, and the parity. \b UART_CONFIG_WLEN_8, //! \b UART_CONFIG_WLEN_7, \b UART_CONFIG_WLEN_6, and \b UART_CONFIG_WLEN_5 //! select from eight to five data bits per byte (respectively). //! \b UART_CONFIG_STOP_ONE and \b UART_CONFIG_STOP_TWO select one or two stop //! bits (respectively). \b UART_CONFIG_PAR_NONE, \b UART_CONFIG_PAR_EVEN, //! \b UART_CONFIG_PAR_ODD, \b UART_CONFIG_PAR_ONE, and \b UART_CONFIG_PAR_ZERO //! select the parity mode (no parity bit, even parity bit, odd parity bit, //! parity bit always one, and parity bit always zero, respectively). //! //! The peripheral clock is the same as the processor clock. The frequency of //! the system clock is the value returned by SysCtlClockGet(), or it can be //! explicitly hard coded if it is constant and known (to save the //! code/execution overhead of a call to SysCtlClockGet()). //! //! //! \return None. // //***************************************************************************** void UARTConfigSetExpClk(unsigned long ulBase, unsigned long ulUARTClk, unsigned long ulBaud, unsigned long ulConfig) { unsigned long ulDiv; // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); ASSERT(ulBaud != 0); // // Stop the UART. // UARTDisable(ulBase); // // Is the required baud rate greater than the maximum rate supported // without the use of high speed mode? // if((ulBaud * 16) > ulUARTClk) { // // Enable high speed mode. // HWREG(ulBase + UART_O_CTL) |= UART_CTL_HSE; // // Half the supplied baud rate to compensate for enabling high speed // mode. This allows the following code to be common to both cases. // ulBaud /= 2; } else { // // Disable high speed mode. // HWREG(ulBase + UART_O_CTL) &= ~(UART_CTL_HSE); } // // Compute the fractional baud rate divider. // ulDiv = (((ulUARTClk * 8) / ulBaud) + 1) / 2; // // Set the baud rate. // HWREG(ulBase + UART_O_IBRD) = ulDiv / 64; HWREG(ulBase + UART_O_FBRD) = ulDiv % 64; // // Set parity, data length, and number of stop bits. // HWREG(ulBase + UART_O_LCRH) = ulConfig; // // Clear the flags register. // HWREG(ulBase + UART_O_FR) = 0; // // Start the UART. // UARTEnable(ulBase); } //***************************************************************************** // //! Gets the current configuration of a UART. //! //! \param ulBase is the base address of the UART port. //! \param ulUARTClk is the rate of the clock supplied to the UART module. //! \param pulBaud is a pointer to storage for the baud rate. //! \param pulConfig is a pointer to storage for the data format. //! //! The baud rate and data format for the UART is determined, given an //! explicitly provided peripheral clock (hence the ExpClk suffix). The //! returned baud rate is the actual baud rate; it may not be the exact baud //! rate requested or an ``official'' baud rate. The data format returned in //! \e pulConfig is enumerated the same as the \e ulConfig parameter of //! UARTConfigSetExpClk(). //! //! The peripheral clock is the same as the processor clock. The frequency of //! the system clock is the value returned by SysCtlClockGet(), or it can be //! explicitly hard coded if it is constant and known (to save the //! code/execution overhead of a call to SysCtlClockGet()). //! //! //! \return None. // //***************************************************************************** void UARTConfigGetExpClk(unsigned long ulBase, unsigned long ulUARTClk, unsigned long *pulBaud, unsigned long *pulConfig) { unsigned long ulInt, ulFrac; // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Compute the baud rate. // ulInt = HWREG(ulBase + UART_O_IBRD); ulFrac = HWREG(ulBase + UART_O_FBRD); *pulBaud = (ulUARTClk * 4) / ((64 * ulInt) + ulFrac); // // See if high speed mode enabled. // if(HWREG(ulBase + UART_O_CTL) & UART_CTL_HSE) { // // High speed mode is enabled so the actual baud rate is actually // double what was just calculated. // *pulBaud *= 2; } // // Get the parity, data length, and number of stop bits. // *pulConfig = (HWREG(ulBase + UART_O_LCRH) & (UART_LCRH_SPS | UART_LCRH_WLEN_M | UART_LCRH_STP2 | UART_LCRH_EPS | UART_LCRH_PEN)); } //***************************************************************************** // //! Enables transmitting and receiving. //! //! \param ulBase is the base address of the UART port. //! //! This function sets the UARTEN, TXE, and RXE bits, and enables the transmit //! and receive FIFOs. //! //! \return None. // //***************************************************************************** void UARTEnable(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Enable the FIFO. // HWREG(ulBase + UART_O_LCRH) |= UART_LCRH_FEN; // // Enable RX, TX, and the UART. // HWREG(ulBase + UART_O_CTL) |= (UART_CTL_UARTEN | UART_CTL_TXE | UART_CTL_RXE); } //***************************************************************************** // //! Disables transmitting and receiving. //! //! \param ulBase is the base address of the UART port. //! //! This function clears the UARTEN, TXE, and RXE bits, waits for the end of //! transmission of the current character, and flushes the transmit FIFO. //! //! \return None. // //***************************************************************************** void UARTDisable(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Wait for end of TX. // while(HWREG(ulBase + UART_O_FR) & UART_FR_BUSY) { } // // Disable the FIFO. // HWREG(ulBase + UART_O_LCRH) &= ~(UART_LCRH_FEN); // // Disable the UART. // HWREG(ulBase + UART_O_CTL) &= ~(UART_CTL_UARTEN | UART_CTL_TXE | UART_CTL_RXE); } //***************************************************************************** // //! Enables the transmit and receive FIFOs. //! //! \param ulBase is the base address of the UART port. //! //! This functions enables the transmit and receive FIFOs in the UART. //! //! \return None. // //***************************************************************************** void UARTFIFOEnable(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Enable the FIFO. // HWREG(ulBase + UART_O_LCRH) |= UART_LCRH_FEN; } //***************************************************************************** // //! Disables the transmit and receive FIFOs. //! //! \param ulBase is the base address of the UART port. //! //! This functions disables the transmit and receive FIFOs in the UART. //! //! \return None. // //***************************************************************************** void UARTFIFODisable(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Disable the FIFO. // HWREG(ulBase + UART_O_LCRH) &= ~(UART_LCRH_FEN); } //***************************************************************************** // //! Sets the states of the RTS modem control signals. //! //! \param ulBase is the base address of the UART port. //! \param ulControl is a bit-mapped flag indicating which modem control bits //! should be set. //! //! This function sets the states of the RTS modem handshake outputs //! from the UART. //! //! The \e ulControl parameter is the logical OR of any of the following: //! //! - \b UART_OUTPUT_RTS - The Modem Control RTS signal //! //! \note The availability of hardware modem handshake signals varies with the //! part and UART in use. Please consult the datasheet for the part //! you are using to determine whether this support is available. //! //! \return None. // //***************************************************************************** void UARTModemControlSet(unsigned long ulBase, unsigned long ulControl) { unsigned long ulTemp; // // Check the arguments. // ASSERT(ulBase == UARTA1_BASE); ASSERT((ulControl & ~(UART_OUTPUT_RTS)) == 0); // // Set the appropriate modem control output bits. // ulTemp = HWREG(ulBase + UART_O_CTL); ulTemp |= (ulControl & (UART_OUTPUT_RTS)); HWREG(ulBase + UART_O_CTL) = ulTemp; } //***************************************************************************** // //! Clears the states of the RTS modem control signals. //! //! \param ulBase is the base address of the UART port. //! \param ulControl is a bit-mapped flag indicating which modem control bits //! should be set. //! //! This function clears the states of the RTS modem handshake outputs //! from the UART. //! //! The \e ulControl parameter is the logical OR of any of the following: //! //! - \b UART_OUTPUT_RTS - The Modem Control RTS signal //! //! \note The availability of hardware modem handshake signals varies with the //! part and UART in use. Please consult the datasheet for the part //! you are using to determine whether this support is available. //! //! \return None. // //***************************************************************************** void UARTModemControlClear(unsigned long ulBase, unsigned long ulControl) { unsigned long ulTemp; // // Check the arguments. // ASSERT(ulBase == UARTA1_BASE); ASSERT((ulControl & ~(UART_OUTPUT_RTS)) == 0); // // Set the appropriate modem control output bits. // ulTemp = HWREG(ulBase + UART_O_CTL); ulTemp &= ~(ulControl & (UART_OUTPUT_RTS)); HWREG(ulBase + UART_O_CTL) = ulTemp; } //***************************************************************************** // //! Gets the states of the RTS modem control signals. //! //! \param ulBase is the base address of the UART port. //! //! This function returns the current states of each of the UART modem //! control signal, RTS. //! //! \note The availability of hardware modem handshake signals varies with the //! part and UART in use. Please consult the datasheet for the part //! you are using to determine whether this support is available. //! //! \return Returns the states of the handshake output signal. // //***************************************************************************** unsigned long UARTModemControlGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == UARTA1_BASE); return(HWREG(ulBase + UART_O_CTL) & (UART_OUTPUT_RTS)); } //***************************************************************************** // //! Gets the states of the CTS modem status signal. //! //! \param ulBase is the base address of the UART port. //! //! This function returns the current states of the UART modem status signal, //! CTS. //! //! \note The availability of hardware modem handshake signals varies with the //! part and UART in use. Please consult the datasheet for the part //! you are using to determine whether this support is available. //! //! \return Returns the states of the handshake output signal // //***************************************************************************** unsigned long UARTModemStatusGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == UARTA1_BASE); return(HWREG(ulBase + UART_O_FR) & (UART_INPUT_CTS)); } //***************************************************************************** // //! Sets the UART hardware flow control mode to be used. //! //! \param ulBase is the base address of the UART port. //! \param ulMode indicates the flow control modes to be used. This parameter //! is a logical OR combination of values \b UART_FLOWCONTROL_TX and //! \b UART_FLOWCONTROL_RX to enable hardware transmit (CTS) and receive (RTS) //! flow control or \b UART_FLOWCONTROL_NONE to disable hardware flow control. //! //! This function sets the required hardware flow control modes. If \e ulMode //! contains flag \b UART_FLOWCONTROL_TX, data is only transmitted if the //! incoming CTS signal is asserted. If \e ulMode contains flag //! \b UART_FLOWCONTROL_RX, the RTS output is controlled by the hardware and is //! asserted only when there is space available in the receive FIFO. If no //! hardware flow control is required, \b UART_FLOWCONTROL_NONE should be //! passed. //! //! \note The availability of hardware flow control varies with the //! part and UART in use. Please consult the datasheet for the part you are //! using to determine whether this support is available. //! //! \return None. // //***************************************************************************** void UARTFlowControlSet(unsigned long ulBase, unsigned long ulMode) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); ASSERT((ulMode & ~(UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX)) == 0); // // Set the flow control mode as requested. // HWREG(ulBase + UART_O_CTL) = ((HWREG(ulBase + UART_O_CTL) & ~(UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX)) | ulMode); } //***************************************************************************** // //! Returns the UART hardware flow control mode currently in use. //! //! \param ulBase is the base address of the UART port. //! //! This function returns the current hardware flow control mode. //! //! \note The availability of hardware flow control varies with the //! part and UART in use. Please consult the datasheet for the part you are //! using to determine whether this support is available. //! //! \return Returns the current flow control mode in use. This is a //! logical OR combination of values \b UART_FLOWCONTROL_TX if transmit //! (CTS) flow control is enabled and \b UART_FLOWCONTROL_RX if receive (RTS) //! flow control is in use. If hardware flow control is disabled, //! \b UART_FLOWCONTROL_NONE is returned. // //***************************************************************************** unsigned long UARTFlowControlGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); return(HWREG(ulBase + UART_O_CTL) & (UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX)); } //***************************************************************************** // //! Sets the operating mode for the UART transmit interrupt. //! //! \param ulBase is the base address of the UART port. //! \param ulMode is the operating mode for the transmit interrupt. It may be //! \b UART_TXINT_MODE_EOT to trigger interrupts when the transmitter is idle //! or \b UART_TXINT_MODE_FIFO to trigger based on the current transmit FIFO //! level. //! //! This function allows the mode of the UART transmit interrupt to be set. By //! default, the transmit interrupt is asserted when the FIFO level falls past //! a threshold set via a call to UARTFIFOLevelSet(). Alternatively, if this //! function is called with \e ulMode set to \b UART_TXINT_MODE_EOT, the //! transmit interrupt is asserted once the transmitter is completely idle - //! the transmit FIFO is empty and all bits, including any stop bits, have //! cleared the transmitter. //! //! \note The availability of end-of-transmission mode varies with the //! part in use. Please consult the datasheet for the part you are //! using to determine whether this support is available. //! //! \return None. // //***************************************************************************** void UARTTxIntModeSet(unsigned long ulBase, unsigned long ulMode) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); ASSERT((ulMode == UART_TXINT_MODE_EOT) || (ulMode == UART_TXINT_MODE_FIFO)); // // Set or clear the EOT bit of the UART control register as appropriate. // HWREG(ulBase + UART_O_CTL) = ((HWREG(ulBase + UART_O_CTL) & ~(UART_TXINT_MODE_EOT | UART_TXINT_MODE_FIFO)) | ulMode); } //***************************************************************************** // //! Returns the current operating mode for the UART transmit interrupt. //! //! \param ulBase is the base address of the UART port. //! //! This function returns the current operating mode for the UART transmit //! interrupt. The return value is \b UART_TXINT_MODE_EOT if the transmit //! interrupt is currently set to be asserted once the transmitter is //! completely idle - the transmit FIFO is empty and all bits, including any //! stop bits, have cleared the transmitter. The return value is //! \b UART_TXINT_MODE_FIFO if the interrupt is set to be asserted based upon //! the level of the transmit FIFO. //! //! \note The availability of end-of-transmission mode varies with the //! part in use. Please consult the datasheet for the part you are //! using to determine whether this support is available. //! //! \return Returns \b UART_TXINT_MODE_FIFO or \b UART_TXINT_MODE_EOT. // //***************************************************************************** unsigned long UARTTxIntModeGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Return the current transmit interrupt mode. // return(HWREG(ulBase + UART_O_CTL) & (UART_TXINT_MODE_EOT | UART_TXINT_MODE_FIFO)); } //***************************************************************************** // //! Determines if there are any characters in the receive FIFO. //! //! \param ulBase is the base address of the UART port. //! //! This function returns a flag indicating whether or not there is data //! available in the receive FIFO. //! //! \return Returns \b true if there is data in the receive FIFO or \b false //! if there is no data in the receive FIFO. // //***************************************************************************** tBoolean UARTCharsAvail(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Return the availability of characters. // return((HWREG(ulBase + UART_O_FR) & UART_FR_RXFE) ? false : true); } //***************************************************************************** // //! Determines if there is any space in the transmit FIFO. //! //! \param ulBase is the base address of the UART port. //! //! This function returns a flag indicating whether or not there is space //! available in the transmit FIFO. //! //! \return Returns \b true if there is space available in the transmit FIFO //! or \b false if there is no space available in the transmit FIFO. // //***************************************************************************** tBoolean UARTSpaceAvail(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Return the availability of space. // return((HWREG(ulBase + UART_O_FR) & UART_FR_TXFF) ? false : true); } //***************************************************************************** // //! Receives a character from the specified port. //! //! \param ulBase is the base address of the UART port. //! //! This function gets a character from the receive FIFO for the specified //! port. //! //! //! \return Returns the character read from the specified port, cast as a //! \e long. A \b -1 is returned if there are no characters present in the //! receive FIFO. The UARTCharsAvail() function should be called before //! attempting to call this function. // //***************************************************************************** long UARTCharGetNonBlocking(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // See if there are any characters in the receive FIFO. // if(!(HWREG(ulBase + UART_O_FR) & UART_FR_RXFE)) { // // Read and return the next character. // return(HWREG(ulBase + UART_O_DR)); } else { // // There are no characters, so return a failure. // return(-1); } } //***************************************************************************** // //! Waits for a character from the specified port. //! //! \param ulBase is the base address of the UART port. //! //! This function gets a character from the receive FIFO for the specified //! port. If there are no characters available, this function waits until a //! character is received before returning. //! //! \return Returns the character read from the specified port, cast as a //! \e long. // //***************************************************************************** long UARTCharGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Wait until a char is available. // while(HWREG(ulBase + UART_O_FR) & UART_FR_RXFE) { } // // Now get the char. // return(HWREG(ulBase + UART_O_DR)); } //***************************************************************************** // //! Sends a character to the specified port. //! //! \param ulBase is the base address of the UART port. //! \param ucData is the character to be transmitted. //! //! This function writes the character \e ucData to the transmit FIFO for the //! specified port. This function does not block, so if there is no space //! available, then a \b false is returned, and the application must retry the //! function later. //! //! \return Returns \b true if the character was successfully placed in the //! transmit FIFO or \b false if there was no space available in the transmit //! FIFO. // //***************************************************************************** tBoolean UARTCharPutNonBlocking(unsigned long ulBase, unsigned char ucData) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // See if there is space in the transmit FIFO. // if(!(HWREG(ulBase + UART_O_FR) & UART_FR_TXFF)) { // // Write this character to the transmit FIFO. // HWREG(ulBase + UART_O_DR) = ucData; // // Success. // return(true); } else { // // There is no space in the transmit FIFO, so return a failure. // return(false); } } //***************************************************************************** // //! Waits to send a character from the specified port. //! //! \param ulBase is the base address of the UART port. //! \param ucData is the character to be transmitted. //! //! This function sends the character \e ucData to the transmit FIFO for the //! specified port. If there is no space available in the transmit FIFO, this //! function waits until there is space available before returning. //! //! \return None. // //***************************************************************************** void UARTCharPut(unsigned long ulBase, unsigned char ucData) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Wait until space is available. // while(HWREG(ulBase + UART_O_FR) & UART_FR_TXFF) { } // // Send the char. // HWREG(ulBase + UART_O_DR) = ucData; } //***************************************************************************** // //! Causes a BREAK to be sent. //! //! \param ulBase is the base address of the UART port. //! \param bBreakState controls the output level. //! //! Calling this function with \e bBreakState set to \b true asserts a break //! condition on the UART. Calling this function with \e bBreakState set to //! \b false removes the break condition. For proper transmission of a break //! command, the break must be asserted for at least two complete frames. //! //! \return None. // //***************************************************************************** void UARTBreakCtl(unsigned long ulBase, tBoolean bBreakState) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Set the break condition as requested. // HWREG(ulBase + UART_O_LCRH) = (bBreakState ? (HWREG(ulBase + UART_O_LCRH) | UART_LCRH_BRK) : (HWREG(ulBase + UART_O_LCRH) & ~(UART_LCRH_BRK))); } //***************************************************************************** // //! Determines whether the UART transmitter is busy or not. //! //! \param ulBase is the base address of the UART port. //! //! Allows the caller to determine whether all transmitted bytes have cleared //! the transmitter hardware. If \b false is returned, the transmit FIFO is //! empty and all bits of the last transmitted character, including all stop //! bits, have left the hardware shift register. //! //! \return Returns \b true if the UART is transmitting or \b false if all //! transmissions are complete. // //***************************************************************************** tBoolean UARTBusy(unsigned long ulBase) { // // Check the argument. // ASSERT(UARTBaseValid(ulBase)); // // Determine if the UART is busy. // return((HWREG(ulBase + UART_O_FR) & UART_FR_BUSY) ? true : false); } //***************************************************************************** // //! Registers an interrupt handler for a UART interrupt. //! //! \param ulBase is the base address of the UART port. //! \param pfnHandler is a pointer to the function to be called when the //! UART interrupt occurs. //! //! This function does the actual registering of the interrupt handler. This //! function enables the global interrupt in the interrupt controller; specific //! UART interrupts must be enabled via UARTIntEnable(). It is the interrupt //! handler's responsibility to clear the interrupt source. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void UARTIntRegister(unsigned long ulBase, void (*pfnHandler)(void)) { unsigned long ulInt; // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Determine the interrupt number based on the UART port. // ulInt = UARTIntNumberGet(ulBase); // // Register the interrupt handler. // IntRegister(ulInt, pfnHandler); // // Enable the UART interrupt. // IntEnable(ulInt); } //***************************************************************************** // //! Unregisters an interrupt handler for a UART interrupt. //! //! \param ulBase is the base address of the UART port. //! //! This function does the actual unregistering of the interrupt handler. It //! clears the handler to be called when a UART interrupt occurs. This //! function also masks off the interrupt in the interrupt controller so that //! the interrupt handler no longer is called. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void UARTIntUnregister(unsigned long ulBase) { unsigned long ulInt; // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Determine the interrupt number based on the UART port. // ulInt = UARTIntNumberGet(ulBase); // // Disable the interrupt. // IntDisable(ulInt); // // Unregister the interrupt handler. // IntUnregister(ulInt); } //***************************************************************************** // //! Enables individual UART interrupt sources. //! //! \param ulBase is the base address of the UART port. //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated UART interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter is the logical OR of any of the following: //! //! - \b UART_INT_OE - Overrun Error interrupt //! - \b UART_INT_BE - Break Error interrupt //! - \b UART_INT_PE - Parity Error interrupt //! - \b UART_INT_FE - Framing Error interrupt //! - \b UART_INT_RT - Receive Timeout interrupt //! - \b UART_INT_TX - Transmit interrupt //! - \b UART_INT_RX - Receive interrupt //! - \b UART_INT_CTS - CTS interrupt //! //! \return None. // //***************************************************************************** void UARTIntEnable(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Enable the specified interrupts. // HWREG(ulBase + UART_O_IM) |= ulIntFlags; } //***************************************************************************** // //! Disables individual UART interrupt sources. //! //! \param ulBase is the base address of the UART port. //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled. //! //! This function disables the indicated UART interrupt sources. Only the //! sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to UARTIntEnable(). //! //! \return None. // //***************************************************************************** void UARTIntDisable(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Disable the specified interrupts. // HWREG(ulBase + UART_O_IM) &= ~(ulIntFlags); } //***************************************************************************** // //! Gets the current interrupt status. //! //! \param ulBase is the base address of the UART port. //! \param bMasked is \b false if the raw interrupt status is required and //! \b true if the masked interrupt status is required. //! //! This function returns the interrupt status for the specified UART. Either //! the raw interrupt status or the status of interrupts that are allowed to //! reflect to the processor can be returned. //! //! \return Returns the current interrupt status, enumerated as a bit field of //! values described in UARTIntEnable(). // //***************************************************************************** unsigned long UARTIntStatus(unsigned long ulBase, tBoolean bMasked) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Return either the interrupt status or the raw interrupt status as // requested. // if(bMasked) { return(HWREG(ulBase + UART_O_MIS)); } else { return(HWREG(ulBase + UART_O_RIS)); } } //***************************************************************************** // //! Clears UART interrupt sources. //! //! \param ulBase is the base address of the UART port. //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared. //! //! The specified UART interrupt sources are cleared, so that they no longer //! assert. This function must be called in the interrupt handler to keep the //! interrupt from being recognized again immediately upon exit. //! //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags //! parameter to UARTIntEnable(). //! //! \note Because there is a write buffer in the Cortex-M3 processor, it may //! take several clock cycles before the interrupt source is actually cleared. //! Therefore, it is recommended that the interrupt source be cleared early in //! the interrupt handler (as opposed to the very last action) to avoid //! returning from the interrupt handler before the interrupt source is //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). //! //! \return None. // //***************************************************************************** void UARTIntClear(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Clear the requested interrupt sources. // HWREG(ulBase + UART_O_ICR) = ulIntFlags; } //***************************************************************************** // //! Enable UART DMA operation. //! //! \param ulBase is the base address of the UART port. //! \param ulDMAFlags is a bit mask of the DMA features to enable. //! //! The specified UART DMA features are enabled. The UART can be //! configured to use DMA for transmit or receive, and to disable //! receive if an error occurs. The \e ulDMAFlags parameter is the //! logical OR of any of the following values: //! //! - UART_DMA_RX - enable DMA for receive //! - UART_DMA_TX - enable DMA for transmit //! - UART_DMA_ERR_RXSTOP - disable DMA receive on UART error //! //! \note The uDMA controller must also be set up before DMA can be used //! with the UART. //! //! \return None. // //***************************************************************************** void UARTDMAEnable(unsigned long ulBase, unsigned long ulDMAFlags) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Set the requested bits in the UART DMA control register. // HWREG(ulBase + UART_O_DMACTL) |= ulDMAFlags; } //***************************************************************************** // //! Disable UART DMA operation. //! //! \param ulBase is the base address of the UART port. //! \param ulDMAFlags is a bit mask of the DMA features to disable. //! //! This function is used to disable UART DMA features that were enabled //! by UARTDMAEnable(). The specified UART DMA features are disabled. The //! \e ulDMAFlags parameter is the logical OR of any of the following values: //! //! - UART_DMA_RX - disable DMA for receive //! - UART_DMA_TX - disable DMA for transmit //! - UART_DMA_ERR_RXSTOP - do not disable DMA receive on UART error //! //! \return None. // //***************************************************************************** void UARTDMADisable(unsigned long ulBase, unsigned long ulDMAFlags) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Clear the requested bits in the UART DMA control register. // HWREG(ulBase + UART_O_DMACTL) &= ~ulDMAFlags; } //***************************************************************************** // //! Gets current receiver errors. //! //! \param ulBase is the base address of the UART port. //! //! This function returns the current state of each of the 4 receiver error //! sources. The returned errors are equivalent to the four error bits //! returned via the previous call to UARTCharGet() or UARTCharGetNonBlocking() //! with the exception that the overrun error is set immediately the overrun //! occurs rather than when a character is next read. //! //! \return Returns a logical OR combination of the receiver error flags, //! \b UART_RXERROR_FRAMING, \b UART_RXERROR_PARITY, \b UART_RXERROR_BREAK //! and \b UART_RXERROR_OVERRUN. // //***************************************************************************** unsigned long UARTRxErrorGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Return the current value of the receive status register. // return(HWREG(ulBase + UART_O_RSR) & 0x0000000F); } //***************************************************************************** // //! Clears all reported receiver errors. //! //! \param ulBase is the base address of the UART port. //! //! This function is used to clear all receiver error conditions reported via //! UARTRxErrorGet(). If using the overrun, framing error, parity error or //! break interrupts, this function must be called after clearing the interrupt //! to ensure that later errors of the same type trigger another interrupt. //! //! \return None. // //***************************************************************************** void UARTRxErrorClear(unsigned long ulBase) { // // Check the arguments. // ASSERT(UARTBaseValid(ulBase)); // // Any write to the Error Clear Register will clear all bits which are // currently set. // HWREG(ulBase + UART_O_ECR) = 0; } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/uart.h000066400000000000000000000263371357706137100177660ustar00rootroot00000000000000//***************************************************************************** // // uart.h // // Defines and Macros for the UART. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __UART_H__ #define __UART_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // Values that can be passed to UARTIntEnable, UARTIntDisable, and UARTIntClear // as the ulIntFlags parameter, and returned from UARTIntStatus. // //***************************************************************************** #define UART_INT_DMATX 0x20000 // DMA Tx Done interrupt Mask #define UART_INT_DMARX 0x10000 // DMA Rx Done interrupt Mask #define UART_INT_EOT 0x800 // End of transfer interrupt Mask #define UART_INT_OE 0x400 // Overrun Error Interrupt Mask #define UART_INT_BE 0x200 // Break Error Interrupt Mask #define UART_INT_PE 0x100 // Parity Error Interrupt Mask #define UART_INT_FE 0x080 // Framing Error Interrupt Mask #define UART_INT_RT 0x040 // Receive Timeout Interrupt Mask #define UART_INT_TX 0x020 // Transmit Interrupt Mask #define UART_INT_RX 0x010 // Receive Interrupt Mask #define UART_INT_CTS 0x002 // CTS Modem Interrupt Mask //***************************************************************************** // // Values that can be passed to UARTConfigSetExpClk as the ulConfig parameter // and returned by UARTConfigGetExpClk in the pulConfig parameter. // Additionally, the UART_CONFIG_PAR_* subset can be passed to // UARTParityModeSet as the ulParity parameter, and are returned by // UARTParityModeGet. // //***************************************************************************** #define UART_CONFIG_WLEN_MASK 0x00000060 // Mask for extracting word length #define UART_CONFIG_WLEN_8 0x00000060 // 8 bit data #define UART_CONFIG_WLEN_7 0x00000040 // 7 bit data #define UART_CONFIG_WLEN_6 0x00000020 // 6 bit data #define UART_CONFIG_WLEN_5 0x00000000 // 5 bit data #define UART_CONFIG_STOP_MASK 0x00000008 // Mask for extracting stop bits #define UART_CONFIG_STOP_ONE 0x00000000 // One stop bit #define UART_CONFIG_STOP_TWO 0x00000008 // Two stop bits #define UART_CONFIG_PAR_MASK 0x00000086 // Mask for extracting parity #define UART_CONFIG_PAR_NONE 0x00000000 // No parity #define UART_CONFIG_PAR_EVEN 0x00000006 // Even parity #define UART_CONFIG_PAR_ODD 0x00000002 // Odd parity #define UART_CONFIG_PAR_ONE 0x00000082 // Parity bit is one #define UART_CONFIG_PAR_ZERO 0x00000086 // Parity bit is zero //***************************************************************************** // // Values that can be passed to UARTFIFOLevelSet as the ulTxLevel parameter and // returned by UARTFIFOLevelGet in the pulTxLevel. // //***************************************************************************** #define UART_FIFO_TX1_8 0x00000000 // Transmit interrupt at 1/8 Full #define UART_FIFO_TX2_8 0x00000001 // Transmit interrupt at 1/4 Full #define UART_FIFO_TX4_8 0x00000002 // Transmit interrupt at 1/2 Full #define UART_FIFO_TX6_8 0x00000003 // Transmit interrupt at 3/4 Full #define UART_FIFO_TX7_8 0x00000004 // Transmit interrupt at 7/8 Full //***************************************************************************** // // Values that can be passed to UARTFIFOLevelSet as the ulRxLevel parameter and // returned by UARTFIFOLevelGet in the pulRxLevel. // //***************************************************************************** #define UART_FIFO_RX1_8 0x00000000 // Receive interrupt at 1/8 Full #define UART_FIFO_RX2_8 0x00000008 // Receive interrupt at 1/4 Full #define UART_FIFO_RX4_8 0x00000010 // Receive interrupt at 1/2 Full #define UART_FIFO_RX6_8 0x00000018 // Receive interrupt at 3/4 Full #define UART_FIFO_RX7_8 0x00000020 // Receive interrupt at 7/8 Full //***************************************************************************** // // Values that can be passed to UARTDMAEnable() and UARTDMADisable(). // //***************************************************************************** #define UART_DMA_ERR_RXSTOP 0x00000004 // Stop DMA receive if UART error #define UART_DMA_TX 0x00000002 // Enable DMA for transmit #define UART_DMA_RX 0x00000001 // Enable DMA for receive //***************************************************************************** // // Values returned from UARTRxErrorGet(). // //***************************************************************************** #define UART_RXERROR_OVERRUN 0x00000008 #define UART_RXERROR_BREAK 0x00000004 #define UART_RXERROR_PARITY 0x00000002 #define UART_RXERROR_FRAMING 0x00000001 //***************************************************************************** // // Values that can be passed to UARTModemControlSet()and UARTModemControlClear() // or returned from UARTModemControlGet(). // //***************************************************************************** #define UART_OUTPUT_RTS 0x00000800 //***************************************************************************** // // Values that can be returned from UARTModemStatusGet(). // //***************************************************************************** #define UART_INPUT_CTS 0x00000001 //***************************************************************************** // // Values that can be passed to UARTFlowControl() or returned from // UARTFlowControlGet(). // //***************************************************************************** #define UART_FLOWCONTROL_TX 0x00008000 #define UART_FLOWCONTROL_RX 0x00004000 #define UART_FLOWCONTROL_NONE 0x00000000 //***************************************************************************** // // Values that can be passed to UARTTxIntModeSet() or returned from // UARTTxIntModeGet(). // //***************************************************************************** #define UART_TXINT_MODE_FIFO 0x00000000 #define UART_TXINT_MODE_EOT 0x00000010 //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void UARTParityModeSet(unsigned long ulBase, unsigned long ulParity); extern unsigned long UARTParityModeGet(unsigned long ulBase); extern void UARTFIFOLevelSet(unsigned long ulBase, unsigned long ulTxLevel, unsigned long ulRxLevel); extern void UARTFIFOLevelGet(unsigned long ulBase, unsigned long *pulTxLevel, unsigned long *pulRxLevel); extern void UARTConfigSetExpClk(unsigned long ulBase, unsigned long ulUARTClk, unsigned long ulBaud, unsigned long ulConfig); extern void UARTConfigGetExpClk(unsigned long ulBase, unsigned long ulUARTClk, unsigned long *pulBaud, unsigned long *pulConfig); extern void UARTEnable(unsigned long ulBase); extern void UARTDisable(unsigned long ulBase); extern void UARTFIFOEnable(unsigned long ulBase); extern void UARTFIFODisable(unsigned long ulBase); extern tBoolean UARTCharsAvail(unsigned long ulBase); extern tBoolean UARTSpaceAvail(unsigned long ulBase); extern long UARTCharGetNonBlocking(unsigned long ulBase); extern long UARTCharGet(unsigned long ulBase); extern tBoolean UARTCharPutNonBlocking(unsigned long ulBase, unsigned char ucData); extern void UARTCharPut(unsigned long ulBase, unsigned char ucData); extern void UARTBreakCtl(unsigned long ulBase, tBoolean bBreakState); extern tBoolean UARTBusy(unsigned long ulBase); extern void UARTIntRegister(unsigned long ulBase, void(*pfnHandler)(void)); extern void UARTIntUnregister(unsigned long ulBase); extern void UARTIntEnable(unsigned long ulBase, unsigned long ulIntFlags); extern void UARTIntDisable(unsigned long ulBase, unsigned long ulIntFlags); extern unsigned long UARTIntStatus(unsigned long ulBase, tBoolean bMasked); extern void UARTIntClear(unsigned long ulBase, unsigned long ulIntFlags); extern void UARTDMAEnable(unsigned long ulBase, unsigned long ulDMAFlags); extern void UARTDMADisable(unsigned long ulBase, unsigned long ulDMAFlags); extern unsigned long UARTRxErrorGet(unsigned long ulBase); extern void UARTRxErrorClear(unsigned long ulBase); extern void UARTModemControlSet(unsigned long ulBase, unsigned long ulControl); extern void UARTModemControlClear(unsigned long ulBase, unsigned long ulControl); extern unsigned long UARTModemControlGet(unsigned long ulBase); extern unsigned long UARTModemStatusGet(unsigned long ulBase); extern void UARTFlowControlSet(unsigned long ulBase, unsigned long ulMode); extern unsigned long UARTFlowControlGet(unsigned long ulBase); extern void UARTTxIntModeSet(unsigned long ulBase, unsigned long ulMode); extern unsigned long UARTTxIntModeGet(unsigned long ulBase); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __UART_H__ micropython-1.12/ports/cc3200/hal/utils.c000066400000000000000000000070331357706137100201360ustar00rootroot00000000000000//***************************************************************************** // // utils.c // // Utility APIs // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup Utils_api //! @{ // //***************************************************************************** #include "utils.h" //***************************************************************************** // //! Provides a small delay. //! //! \param ulCount is the number of delay loop iterations to perform. //! //! This function provides a means of generating a constant length delay. It //! is written in assembly to keep the delay consistent across tool chains, //! avoiding the need to tune the delay based on the tool chain in use. //! //! The loop takes 3 cycles/loop. //! //! \return None. // //***************************************************************************** #if defined(ewarm) || defined(DOXYGEN) void UtilsDelay(unsigned long ulCount) { __asm(" subs r0, #1\n" " bne.n UtilsDelay\n"); } #endif #if defined(gcc) void __attribute__((naked)) UtilsDelay(unsigned long ulCount) { __asm(" subs r0, #1\n" " bne UtilsDelay\n" " bx lr"); } #endif // // For CCS implement this function in pure assembly. This prevents the TI // compiler from doing funny things with the optimizer. // #if defined(ccs) __asm(" .sect \".text:UtilsDelay\"\n" " .clink\n" " .thumbfunc UtilsDelay\n" " .thumb\n" " .global UtilsDelay\n" "UtilsDelay:\n" " subs r0, #1\n" " bne.n UtilsDelay\n" " bx lr\n"); #endif //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/utils.h000066400000000000000000000052411357706137100201420ustar00rootroot00000000000000//***************************************************************************** // // utils.h // // Prototypes and macros for utility APIs // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __UTILS_H__ #define __UTILS_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // API Function prototypes // //***************************************************************************** extern void UtilsDelay(unsigned long ulCount); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif //__UTILS_H__ micropython-1.12/ports/cc3200/hal/wdt.c000066400000000000000000000353461357706137100176040ustar00rootroot00000000000000//***************************************************************************** // // wdt.c // // Driver for the Watchdog Timer Module. // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup WDT_Watchdog_Timer_api //! @{ // //***************************************************************************** #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_wdt.h" #include "debug.h" #include "interrupt.h" #include "wdt.h" //***************************************************************************** // //! Determines if the watchdog timer is enabled. //! //! \param ulBase is the base address of the watchdog timer module. //! //! This will check to see if the watchdog timer is enabled. //! //! \return Returns \b true if the watchdog timer is enabled, and \b false //! if it is not. // //***************************************************************************** tBoolean WatchdogRunning(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // See if the watchdog timer module is enabled, and return. // return(HWREG(ulBase + WDT_O_CTL) & WDT_CTL_INTEN); } //***************************************************************************** // //! Enables the watchdog timer. //! //! \param ulBase is the base address of the watchdog timer module. //! //! This will enable the watchdog timer counter and interrupt. //! //! \note This function will have no effect if the watchdog timer has //! been locked. //! //! \sa WatchdogLock(), WatchdogUnlock() //! //! \return None. // //***************************************************************************** void WatchdogEnable(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Enable the watchdog timer module. // HWREG(ulBase + WDT_O_CTL) |= WDT_CTL_INTEN; } //***************************************************************************** // //! Enables the watchdog timer lock mechanism. //! //! \param ulBase is the base address of the watchdog timer module. //! //! Locks out write access to the watchdog timer configuration registers. //! //! \return None. // //***************************************************************************** void WatchdogLock(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Lock out watchdog register writes. Writing anything to the WDT_O_LOCK // register causes the lock to go into effect. // HWREG(ulBase + WDT_O_LOCK) = WDT_LOCK_LOCKED; } //***************************************************************************** // //! Disables the watchdog timer lock mechanism. //! //! \param ulBase is the base address of the watchdog timer module. //! //! Enables write access to the watchdog timer configuration registers. //! //! \return None. // //***************************************************************************** void WatchdogUnlock(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Unlock watchdog register writes. // HWREG(ulBase + WDT_O_LOCK) = WDT_LOCK_UNLOCK; } //***************************************************************************** // //! Gets the state of the watchdog timer lock mechanism. //! //! \param ulBase is the base address of the watchdog timer module. //! //! Returns the lock state of the watchdog timer registers. //! //! \return Returns \b true if the watchdog timer registers are locked, and //! \b false if they are not locked. // //***************************************************************************** tBoolean WatchdogLockState(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Get the lock state. // return((HWREG(ulBase + WDT_O_LOCK) == WDT_LOCK_LOCKED) ? true : false); } //***************************************************************************** // //! Sets the watchdog timer reload value. //! //! \param ulBase is the base address of the watchdog timer module. //! \param ulLoadVal is the load value for the watchdog timer. //! //! This function sets the value to load into the watchdog timer when the count //! reaches zero for the first time; if the watchdog timer is running when this //! function is called, then the value will be immediately loaded into the //! watchdog timer counter. If the \e ulLoadVal parameter is 0, then an //! interrupt is immediately generated. //! //! \note This function will have no effect if the watchdog timer has //! been locked. //! //! \sa WatchdogLock(), WatchdogUnlock(), WatchdogReloadGet() //! //! \return None. // //***************************************************************************** void WatchdogReloadSet(unsigned long ulBase, unsigned long ulLoadVal) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Set the load register. // HWREG(ulBase + WDT_O_LOAD) = ulLoadVal; } //***************************************************************************** // //! Gets the watchdog timer reload value. //! //! \param ulBase is the base address of the watchdog timer module. //! //! This function gets the value that is loaded into the watchdog timer when //! the count reaches zero for the first time. //! //! \sa WatchdogReloadSet() //! //! \return None. // //***************************************************************************** unsigned long WatchdogReloadGet(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Get the load register. // return(HWREG(ulBase + WDT_O_LOAD)); } //***************************************************************************** // //! Gets the current watchdog timer value. //! //! \param ulBase is the base address of the watchdog timer module. //! //! This function reads the current value of the watchdog timer. //! //! \return Returns the current value of the watchdog timer. // //***************************************************************************** unsigned long WatchdogValueGet(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Get the current watchdog timer register value. // return(HWREG(ulBase + WDT_O_VALUE)); } //***************************************************************************** // //! Registers an interrupt handler for watchdog timer interrupt. //! //! \param ulBase is the base address of the watchdog timer module. //! \param pfnHandler is a pointer to the function to be called when the //! watchdog timer interrupt occurs. //! //! This function does the actual registering of the interrupt handler. This //! will enable the global interrupt in the interrupt controller; the watchdog //! timer interrupt must be enabled via WatchdogEnable(). It is the interrupt //! handler's responsibility to clear the interrupt source via //! WatchdogIntClear(). //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \note This function will only register the standard watchdog interrupt //! handler. To register the NMI watchdog handler, use IntRegister() //! to register the handler for the \b FAULT_NMI interrupt. //! //! \return None. // //***************************************************************************** void WatchdogIntRegister(unsigned long ulBase, void (*pfnHandler)(void)) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Register the interrupt handler and // Enable the watchdog timer interrupt. // IntRegister(INT_WDT, pfnHandler); IntEnable(INT_WDT); } //***************************************************************************** // //! Unregisters an interrupt handler for the watchdog timer interrupt. //! //! \param ulBase is the base address of the watchdog timer module. //! //! This function does the actual unregistering of the interrupt handler. This //! function will clear the handler to be called when a watchdog timer //! interrupt occurs. This will also mask off the interrupt in the interrupt //! controller so that the interrupt handler no longer is called. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \note This function will only unregister the standard watchdog interrupt //! handler. To unregister the NMI watchdog handler, use IntUnregister() //! to unregister the handler for the \b FAULT_NMI interrupt. //! //! \return None. // //***************************************************************************** void WatchdogIntUnregister(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Disable the interrupt IntDisable(INT_WDT); // // Unregister the interrupt handler. // IntUnregister(INT_WDT); } //***************************************************************************** // //! Gets the current watchdog timer interrupt status. //! //! \param ulBase is the base address of the watchdog timer module. //! \param bMasked is \b false if the raw interrupt status is required and //! \b true if the masked interrupt status is required. //! //! This returns the interrupt status for the watchdog timer module. Either //! the raw interrupt status or the status of interrupt that is allowed to //! reflect to the processor can be returned. //! //! \return Returns the current interrupt status, where a 1 indicates that the //! watchdog interrupt is active, and a 0 indicates that it is not active. // //***************************************************************************** unsigned long WatchdogIntStatus(unsigned long ulBase, tBoolean bMasked) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Return either the interrupt status or the raw interrupt status as // requested. // if(bMasked) { return(HWREG(ulBase + WDT_O_MIS)); } else { return(HWREG(ulBase + WDT_O_RIS)); } } //***************************************************************************** // //! Clears the watchdog timer interrupt. //! //! \param ulBase is the base address of the watchdog timer module. //! //! The watchdog timer interrupt source is cleared, so that it no longer //! asserts. //! //! \note Because there is a write buffer in the Cortex-M3 processor, it may //! take several clock cycles before the interrupt source is actually cleared. //! Therefore, it is recommended that the interrupt source be cleared early in //! the interrupt handler (as opposed to the very last action) to avoid //! returning from the interrupt handler before the interrupt source is //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (because the interrupt controller still sees //! the interrupt source asserted). //! //! \return None. // //***************************************************************************** void WatchdogIntClear(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Clear the interrupt source. // HWREG(ulBase + WDT_O_ICR) = WDT_INT_TIMEOUT; } //***************************************************************************** // //! Enables stalling of the watchdog timer during debug events. //! //! \param ulBase is the base address of the watchdog timer module. //! //! This function allows the watchdog timer to stop counting when the processor //! is stopped by the debugger. By doing so, the watchdog is prevented from //! expiring (typically almost immediately from a human time perspective) and //! resetting the system (if reset is enabled). The watchdog will instead //! expired after the appropriate number of processor cycles have been executed //! while debugging (or at the appropriate time after the processor has been //! restarted). //! //! \return None. // //***************************************************************************** void WatchdogStallEnable(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Enable timer stalling. // HWREG(ulBase + WDT_O_TEST) |= WDT_TEST_STALL; } //***************************************************************************** // //! Disables stalling of the watchdog timer during debug events. //! //! \param ulBase is the base address of the watchdog timer module. //! //! This function disables the debug mode stall of the watchdog timer. By //! doing so, the watchdog timer continues to count regardless of the processor //! debug state. //! //! \return None. // //***************************************************************************** void WatchdogStallDisable(unsigned long ulBase) { // // Check the arguments. // ASSERT((ulBase == WDT_BASE)); // // Disable timer stalling. // HWREG(ulBase + WDT_O_TEST) &= ~(WDT_TEST_STALL); } //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** micropython-1.12/ports/cc3200/hal/wdt.h000066400000000000000000000066761357706137100176150ustar00rootroot00000000000000//***************************************************************************** // // wdt.h - Prototypes for the Watchdog Timer API // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __WATCHDOG_H__ #define __WATCHDOG_H__ //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** extern tBoolean WatchdogRunning(unsigned long ulBase); extern void WatchdogEnable(unsigned long ulBase); extern void WatchdogLock(unsigned long ulBase); extern void WatchdogUnlock(unsigned long ulBase); extern tBoolean WatchdogLockState(unsigned long ulBase); extern void WatchdogReloadSet(unsigned long ulBase, unsigned long ulLoadVal); extern unsigned long WatchdogReloadGet(unsigned long ulBase); extern unsigned long WatchdogValueGet(unsigned long ulBase); extern void WatchdogIntRegister(unsigned long ulBase, void(*pfnHandler)(void)); extern void WatchdogIntUnregister(unsigned long ulBase); extern unsigned long WatchdogIntStatus(unsigned long ulBase, tBoolean bMasked); extern void WatchdogIntClear(unsigned long ulBase); extern void WatchdogStallEnable(unsigned long ulBase); extern void WatchdogStallDisable(unsigned long ulBase); //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // __WATCHDOG_H__ micropython-1.12/ports/cc3200/main.c000066400000000000000000000101141357706137100171500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpconfig.h" #include "py/mphal.h" #include "mptask.h" #include "simplelink.h" #include "pybwdt.h" #include "debug.h" #include "antenna.h" #include "mperror.h" #include "task.h" /****************************************************************************** DECLARE PRIVATE CONSTANTS ******************************************************************************/ /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ // This is the static memory (TCB and stack) for the idle task static StaticTask_t xIdleTaskTCB __attribute__ ((section (".rtos_heap"))); static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE] __attribute__ ((section (".rtos_heap"))) __attribute__((aligned (8))); /****************************************************************************** DECLARE PUBLIC DATA ******************************************************************************/ #ifdef DEBUG OsiTaskHandle mpTaskHandle; #endif // This is the FreeRTOS heap, defined here so we can put it in a special segment uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ((section (".rtos_heap"))) __attribute__((aligned (8))); // This is the static memory (TCB and stack) for the main MicroPython task StaticTask_t mpTaskTCB __attribute__ ((section (".rtos_heap"))); StackType_t mpTaskStack[MICROPY_TASK_STACK_LEN] __attribute__ ((section (".rtos_heap"))) __attribute__((aligned (8))); /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ __attribute__ ((section (".boot"))) int main (void) { // Initialize the clocks and the interrupt system HAL_SystemInit(); #if MICROPY_HW_ANTENNA_DIVERSITY // configure the antenna selection pins antenna_init0(); #endif // Init the watchdog pybwdt_init0(); #ifndef DEBUG OsiTaskHandle mpTaskHandle; #endif mpTaskHandle = xTaskCreateStatic(TASK_MicroPython, "MicroPy", MICROPY_TASK_STACK_LEN, NULL, MICROPY_TASK_PRIORITY, mpTaskStack, &mpTaskTCB); ASSERT(mpTaskHandle != NULL); osi_start(); for ( ; ; ); } // We need this when configSUPPORT_STATIC_ALLOCATION is enabled void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) { *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; *ppxIdleTaskStackBuffer = uxIdleTaskStack; *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } micropython-1.12/ports/cc3200/misc/000077500000000000000000000000001357706137100170165ustar00rootroot00000000000000micropython-1.12/ports/cc3200/misc/FreeRTOSHooks.c000066400000000000000000000060271357706137100215640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpconfig.h" #include "py/mphal.h" #include "py/obj.h" #include "inc/hw_memmap.h" #include "pybuart.h" #include "osi.h" #include "mperror.h" //***************************************************************************** // //! \brief Application defined idle task hook //! //! \param none //! //! \return none //! //***************************************************************************** void vApplicationIdleHook (void) { // signal that we are alive and kicking mperror_heartbeat_signal(); // gate the processor's clock to save power __WFI(); } //***************************************************************************** // //! \brief Application defined malloc failed hook //! //! \param none //! //! \return none //! //***************************************************************************** void vApplicationMallocFailedHook (void) { #ifdef DEBUG // break into the debugger __asm volatile ("bkpt #0 \n"); #endif __fatal_error("FreeRTOS malloc failed!"); } //***************************************************************************** // //! \brief Application defined stack overflow hook //! //! \param none //! //! \return none //! //***************************************************************************** void vApplicationStackOverflowHook (OsiTaskHandle *pxTask, signed char *pcTaskName) { #ifdef DEBUG // Break into the debugger __asm volatile ("bkpt #0 \n"); #endif __fatal_error("Stack overflow!"); } //***************************************************************************** // //! \brief Application defined tick hook //! //! \param none //! //! \return none //! //***************************************************************************** void vApplicationTickHook (void) { HAL_IncrementTick(); } micropython-1.12/ports/cc3200/misc/antenna.c000066400000000000000000000101461357706137100206100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "mpconfigboard.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "pin.h" #include "prcm.h" #include "gpio.h" #include "antenna.h" #if MICROPY_HW_ANTENNA_DIVERSITY /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define REG_PAD_CONFIG_26 (0x4402E108) #define REG_PAD_CONFIG_27 (0x4402E10C) /****************************************************************************** DEFINE PRIVATE DATA ******************************************************************************/ static antenna_type_t antenna_type_selected = ANTENNA_TYPE_INTERNAL; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void antenna_init0(void) { // enable the peripheral clock and set the gpio direction for // both antenna 1 and antenna 2 pins MAP_PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); MAP_GPIODirModeSet(GPIOA3_BASE, 0x0C, GPIO_DIR_MODE_OUT); // configure antenna 1 pin type and strength HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~(PAD_STRENGTH_MASK | PAD_TYPE_MASK)) | (0x00000020 | 0x00000000)); // set the mode HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~PAD_MODE_MASK) | 0x00000000) & ~(3 << 10); // set the direction HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~0xC00) | 0x00000800); // configure antenna 2 pin type and strength HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~(PAD_STRENGTH_MASK | PAD_TYPE_MASK)) | (0x00000020 | 0x00000000)); // set the mode HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~PAD_MODE_MASK) | 0x00000000) & ~(3 << 10); // set the direction HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~0xC00) | 0x00000800); // select the currently active antenna antenna_select(antenna_type_selected); } void antenna_select (antenna_type_t _antenna) { if (_antenna == ANTENNA_TYPE_INTERNAL) { MAP_GPIOPinWrite(GPIOA3_BASE, 0x0C, 0x04); // also configure the pull-up and pull-down accordingly HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~PAD_TYPE_MASK)) | PIN_TYPE_STD_PU; HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~PAD_TYPE_MASK)) | PIN_TYPE_STD_PD; } else { MAP_GPIOPinWrite(GPIOA3_BASE, 0x0C, 0x08); // also configure the pull-up and pull-down accordingly HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~PAD_TYPE_MASK)) | PIN_TYPE_STD_PD; HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~PAD_TYPE_MASK)) | PIN_TYPE_STD_PU; } antenna_type_selected = _antenna; } #endif micropython-1.12/ports/cc3200/misc/antenna.h000066400000000000000000000030171357706137100206140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MISC_ANTENNA_H #define MICROPY_INCLUDED_CC3200_MISC_ANTENNA_H typedef enum { ANTENNA_TYPE_INTERNAL = 0, ANTENNA_TYPE_EXTERNAL } antenna_type_t; extern void antenna_init0 (void); extern void antenna_select (antenna_type_t antenna_type); #endif // MICROPY_INCLUDED_CC3200_MISC_ANTENNA_H micropython-1.12/ports/cc3200/misc/help.c000066400000000000000000000030041357706137100201070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" const char cc3200_help_text[] = "Welcome to MicroPython!\n" "For online help please visit http://micropython.org/help/.\n" "For further help on a specific object, type help(obj)\n"; micropython-1.12/ports/cc3200/misc/mperror.c000066400000000000000000000170661357706137100206620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" #include "py/mphal.h" #include "hw_ints.h" #include "hw_types.h" #include "hw_gpio.h" #include "hw_memmap.h" #include "hw_gprcm.h" #include "hw_common_reg.h" #include "pin.h" #include "gpio.h" #ifndef BOOTLOADER #include "pybpin.h" #include "pins.h" #endif #include "rom_map.h" #include "prcm.h" #include "pybuart.h" #include "utils.h" #include "mperror.h" /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define MPERROR_TOOGLE_MS (50) #define MPERROR_SIGNAL_ERROR_MS (1200) #define MPERROR_HEARTBEAT_ON_MS (80) #define MPERROR_HEARTBEAT_OFF_MS (3920) /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ struct mperror_heart_beat { uint32_t off_time; uint32_t on_time; bool beating; bool enabled; bool do_disable; } mperror_heart_beat = {.off_time = 0, .on_time = 0, .beating = false, .enabled = false, .do_disable = false}; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void mperror_init0 (void) { #ifdef BOOTLOADER // enable the system led and the safe boot pin peripheral clocks MAP_PRCMPeripheralClkEnable(MICROPY_SYS_LED_PRCM, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); MAP_PRCMPeripheralClkEnable(MICROPY_SAFE_BOOT_PRCM, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // configure the safe boot pin MAP_PinTypeGPIO(MICROPY_SAFE_BOOT_PIN_NUM, PIN_MODE_0, false); MAP_PinConfigSet(MICROPY_SAFE_BOOT_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD_PD); MAP_GPIODirModeSet(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN, GPIO_DIR_MODE_IN); // configure the bld MAP_PinTypeGPIO(MICROPY_SYS_LED_PIN_NUM, PIN_MODE_0, false); MAP_PinConfigSet(MICROPY_SYS_LED_PIN_NUM, PIN_STRENGTH_6MA, PIN_TYPE_STD); MAP_GPIODirModeSet(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, GPIO_DIR_MODE_OUT); #else // configure the system led pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, 0, PIN_STRENGTH_6MA); #endif mperror_heart_beat.enabled = true; mperror_heartbeat_switch_off(); } void mperror_bootloader_check_reset_cause (void) { // if we are recovering from a WDT reset, trigger // a hibernate cycle for a clean boot if (MAP_PRCMSysResetCauseGet() == PRCM_WDT_RESET) { HWREG(0x400F70B8) = 1; UtilsDelay(800000/5); HWREG(0x400F70B0) = 1; UtilsDelay(800000/5); HWREG(0x4402E16C) |= 0x2; UtilsDelay(800); HWREG(0x4402F024) &= 0xF7FFFFFF; // since the reset cause will be changed, we must store the right reason // so that the application knows it when booting for the next time PRCMSetSpecialBit(PRCM_WDT_RESET_BIT); MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR); // set the sleep interval to 10ms MAP_PRCMHibernateIntervalSet(330); MAP_PRCMHibernateEnter(); } } void mperror_deinit_sfe_pin (void) { // disable the pull-down MAP_PinConfigSet(MICROPY_SAFE_BOOT_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD); } void mperror_signal_error (void) { uint32_t count = 0; while ((MPERROR_TOOGLE_MS * count++) < MPERROR_SIGNAL_ERROR_MS) { // toogle the led MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN)); UtilsDelay(UTILS_DELAY_US_TO_COUNT(MPERROR_TOOGLE_MS * 1000)); } } void mperror_heartbeat_switch_off (void) { if (mperror_heart_beat.enabled) { mperror_heart_beat.on_time = 0; mperror_heart_beat.off_time = 0; MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0); } } void mperror_heartbeat_signal (void) { if (mperror_heart_beat.do_disable) { mperror_heart_beat.do_disable = false; } else if (mperror_heart_beat.enabled) { if (!mperror_heart_beat.beating) { if ((mperror_heart_beat.on_time = mp_hal_ticks_ms()) - mperror_heart_beat.off_time > MPERROR_HEARTBEAT_OFF_MS) { MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN); mperror_heart_beat.beating = true; } } else { if ((mperror_heart_beat.off_time = mp_hal_ticks_ms()) - mperror_heart_beat.on_time > MPERROR_HEARTBEAT_ON_MS) { MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0); mperror_heart_beat.beating = false; } } } } void NORETURN __fatal_error(const char *msg) { #ifdef DEBUG if (msg != NULL) { // wait for 20ms UtilsDelay(UTILS_DELAY_US_TO_COUNT(20000)); mp_hal_stdout_tx_str("\r\nFATAL ERROR:"); mp_hal_stdout_tx_str(msg); mp_hal_stdout_tx_str("\r\n"); } #endif // signal the crash with the system led MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN); for ( ;; ) {__WFI();} } void __assert_func(const char *file, int line, const char *func, const char *expr) { (void) func; printf("Assertion failed: %s, file %s, line %d\n", expr, file, line); __fatal_error(NULL); } void nlr_jump_fail(void *val) { #ifdef DEBUG char msg[64]; snprintf(msg, sizeof(msg), "uncaught exception %p\n", val); __fatal_error(msg); #else __fatal_error(NULL); #endif } void mperror_enable_heartbeat (bool enable) { if (enable) { #ifndef BOOTLOADER // configure the led again pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, 0, PIN_STRENGTH_6MA); #endif mperror_heart_beat.enabled = true; mperror_heart_beat.do_disable = false; mperror_heartbeat_switch_off(); } else { mperror_heart_beat.do_disable = true; mperror_heart_beat.enabled = false; } } bool mperror_is_heartbeat_enabled (void) { return mperror_heart_beat.enabled; } micropython-1.12/ports/cc3200/misc/mperror.h000066400000000000000000000033651357706137100206640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MISC_MPERROR_H #define MICROPY_INCLUDED_CC3200_MISC_MPERROR_H extern void NORETURN __fatal_error(const char *msg); void mperror_init0 (void); void mperror_bootloader_check_reset_cause (void); void mperror_deinit_sfe_pin (void); void mperror_signal_error (void); void mperror_heartbeat_switch_off (void); void mperror_heartbeat_signal (void); void mperror_enable_heartbeat (bool enable); bool mperror_is_heartbeat_enabled (void); #endif // MICROPY_INCLUDED_CC3200_MISC_MPERROR_H micropython-1.12/ports/cc3200/misc/mpexception.c000066400000000000000000000033451357706137100215220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "mpexception.h" /****************************************************************************** DECLARE EXPORTED DATA ******************************************************************************/ const char mpexception_value_invalid_arguments[] = "invalid argument(s) value"; const char mpexception_num_type_invalid_arguments[] = "invalid argument(s) num/type"; const char mpexception_uncaught[] = "uncaught exception"; micropython-1.12/ports/cc3200/misc/mpexception.h000066400000000000000000000030601357706137100215210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MISC_MPEXCEPTION_H #define MICROPY_INCLUDED_CC3200_MISC_MPEXCEPTION_H extern const char mpexception_value_invalid_arguments[]; extern const char mpexception_num_type_invalid_arguments[]; extern const char mpexception_uncaught[]; #endif // MICROPY_INCLUDED_CC3200_MISC_MPEXCEPTION_H micropython-1.12/ports/cc3200/misc/mpirq.c000066400000000000000000000171041357706137100203150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" #include "py/gc.h" #include "inc/hw_types.h" #include "interrupt.h" #include "pybsleep.h" #include "mpexception.h" #include "mperror.h" #include "mpirq.h" /****************************************************************************** DECLARE PUBLIC DATA ******************************************************************************/ const mp_arg_t mp_irq_init_args[] = { { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_priority, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, // the lowest priority { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC uint8_t mp_irq_priorities[] = { INT_PRIORITY_LVL_7, INT_PRIORITY_LVL_6, INT_PRIORITY_LVL_5, INT_PRIORITY_LVL_4, INT_PRIORITY_LVL_3, INT_PRIORITY_LVL_2, INT_PRIORITY_LVL_1 }; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void mp_irq_init0 (void) { // initialize the callback objects list mp_obj_list_init(&MP_STATE_PORT(mp_irq_obj_list), 0); } mp_obj_t mp_irq_new (mp_obj_t parent, mp_obj_t handler, const mp_irq_methods_t *methods) { mp_irq_obj_t *self = m_new_obj(mp_irq_obj_t); self->base.type = &mp_irq_type; self->handler = handler; self->parent = parent; self->methods = (mp_irq_methods_t *)methods; self->isenabled = true; // remove it in case it was already registered mp_irq_remove(parent); mp_obj_list_append(&MP_STATE_PORT(mp_irq_obj_list), self); return self; } mp_irq_obj_t *mp_irq_find (mp_obj_t parent) { for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) { mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i])); if (callback_obj->parent == parent) { return callback_obj; } } return NULL; } void mp_irq_wake_all (void) { // re-enable all active callback objects one by one for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) { mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i])); if (callback_obj->isenabled) { callback_obj->methods->enable(callback_obj->parent); } } } void mp_irq_disable_all (void) { // re-enable all active callback objects one by one for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) { mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i])); callback_obj->methods->disable(callback_obj->parent); } } void mp_irq_remove (const mp_obj_t parent) { mp_irq_obj_t *callback_obj; if ((callback_obj = mp_irq_find(parent))) { mp_obj_list_remove(&MP_STATE_PORT(mp_irq_obj_list), callback_obj); } } uint mp_irq_translate_priority (uint priority) { if (priority < 1 || priority > MP_ARRAY_SIZE(mp_irq_priorities)) { mp_raise_ValueError(mpexception_value_invalid_arguments); } return mp_irq_priorities[priority - 1]; } void mp_irq_handler (mp_obj_t self_in) { mp_irq_obj_t *self = self_in; if (self && self->handler != mp_const_none) { // when executing code within a handler we must lock the GC to prevent // any memory allocations. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_1(self->handler, self->parent); nlr_pop(); } else { // uncaught exception; disable the callback so that it doesn't run again self->methods->disable (self->parent); self->handler = mp_const_none; // signal the error using the heart beat led and // by printing a message printf("Uncaught exception in callback handler\n"); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); mperror_signal_error(); } gc_unlock(); } } /******************************************************************************/ // MicroPython bindings STATIC mp_obj_t mp_irq_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_irq_obj_t *self = pos_args[0]; // this is a bit of a hack, but it let us reuse the callback_create method from our parent ((mp_obj_t *)pos_args)[0] = self->parent; self->methods->init (n_args, pos_args, kw_args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_irq_init_obj, 1, mp_irq_init); STATIC mp_obj_t mp_irq_enable (mp_obj_t self_in) { mp_irq_obj_t *self = self_in; self->methods->enable(self->parent); self->isenabled = true; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_enable_obj, mp_irq_enable); STATIC mp_obj_t mp_irq_disable (mp_obj_t self_in) { mp_irq_obj_t *self = self_in; self->methods->disable(self->parent); self->isenabled = false; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_disable_obj, mp_irq_disable); STATIC mp_obj_t mp_irq_flags (mp_obj_t self_in) { mp_irq_obj_t *self = self_in; return mp_obj_new_int(self->methods->flags(self->parent)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags); STATIC mp_obj_t mp_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 0, false); mp_irq_handler (self_in); return mp_const_none; } STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&mp_irq_init_obj) }, { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&mp_irq_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&mp_irq_disable_obj) }, { MP_ROM_QSTR(MP_QSTR_flags), MP_ROM_PTR(&mp_irq_flags_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table); const mp_obj_type_t mp_irq_type = { { &mp_type_type }, .name = MP_QSTR_irq, .call = mp_irq_call, .locals_dict = (mp_obj_t)&mp_irq_locals_dict, }; micropython-1.12/ports/cc3200/misc/mpirq.h000066400000000000000000000060231357706137100203200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MISC_MPIRQ_H #define MICROPY_INCLUDED_CC3200_MISC_MPIRQ_H /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define mp_irq_INIT_NUM_ARGS 4 /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef mp_obj_t (*mp_irq_init_t) (size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); typedef void (*mp_irq_void_method_t) (mp_obj_t self); typedef int (*mp_irq_int_method_t) (mp_obj_t self); typedef struct { mp_irq_init_t init; mp_irq_void_method_t enable; mp_irq_void_method_t disable; mp_irq_int_method_t flags; } mp_irq_methods_t; typedef struct { mp_obj_base_t base; mp_obj_t parent; mp_obj_t handler; mp_irq_methods_t *methods; bool isenabled; } mp_irq_obj_t; /****************************************************************************** DECLARE EXPORTED DATA ******************************************************************************/ extern const mp_arg_t mp_irq_init_args[]; extern const mp_obj_type_t mp_irq_type; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ void mp_irq_init0 (void); mp_obj_t mp_irq_new (mp_obj_t parent, mp_obj_t handler, const mp_irq_methods_t *methods); mp_irq_obj_t *mp_irq_find (mp_obj_t parent); void mp_irq_wake_all (void); void mp_irq_disable_all (void); void mp_irq_remove (const mp_obj_t parent); void mp_irq_handler (mp_obj_t self_in); uint mp_irq_translate_priority (uint priority); #endif // MICROPY_INCLUDED_CC3200_MISC_MPIRQ_H micropython-1.12/ports/cc3200/mods/000077500000000000000000000000001357706137100170255ustar00rootroot00000000000000micropython-1.12/ports/cc3200/mods/modmachine.c000066400000000000000000000206641357706137100213050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/mphal.h" #include "irq.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_uart.h" #include "rom_map.h" #include "prcm.h" #include "pybuart.h" #include "pybpin.h" #include "pybrtc.h" #include "simplelink.h" #include "modnetwork.h" #include "modwlan.h" #include "moduos.h" #include "FreeRTOS.h" #include "portable.h" #include "task.h" #include "mpexception.h" #include "random.h" #include "pybadc.h" #include "pybi2c.h" #include "pybsd.h" #include "pybwdt.h" #include "pybsleep.h" #include "pybspi.h" #include "pybtimer.h" #include "utils.h" #include "gccollect.h" #ifdef DEBUG extern OsiTaskHandle mpTaskHandle; extern OsiTaskHandle svTaskHandle; extern OsiTaskHandle xSimpleLinkSpawnTaskHndl; #endif /// \module machine - functions related to the SoC /// /******************************************************************************/ // MicroPython bindings; STATIC mp_obj_t machine_reset(void) { // disable wlan wlan_stop(SL_STOP_TIMEOUT_LONG); // reset the cpu and it's peripherals MAP_PRCMMCUReset(true); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); #ifdef DEBUG STATIC mp_obj_t machine_info(uint n_args, const mp_obj_t *args) { // FreeRTOS info { printf("---------------------------------------------\n"); printf("FreeRTOS\n"); printf("---------------------------------------------\n"); printf("Total heap: %u\n", configTOTAL_HEAP_SIZE); printf("Free heap: %u\n", xPortGetFreeHeapSize()); printf("MpTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark((TaskHandle_t)mpTaskHandle)); printf("ServersTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark((TaskHandle_t)svTaskHandle)); printf("SlTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark(xSimpleLinkSpawnTaskHndl)); printf("IdleTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark(xTaskGetIdleTaskHandle())); uint32_t *pstack = (uint32_t *)&_stack; while (*pstack == 0x55555555) { pstack++; } printf("MAIN min free stack: %u\n", pstack - ((uint32_t *)&_stack)); printf("---------------------------------------------\n"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info); #endif STATIC mp_obj_t machine_freq(void) { return mp_obj_new_int(HAL_FCPU_HZ); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq); STATIC mp_obj_t machine_unique_id(void) { uint8_t mac[SL_BSSID_LENGTH]; wlan_get_mac (mac); return mp_obj_new_bytes(mac, SL_BSSID_LENGTH); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id); STATIC mp_obj_t machine_main(mp_obj_t main) { if (mp_obj_is_str(main)) { MP_STATE_PORT(machine_config_main) = main; } else { mp_raise_ValueError(mpexception_value_invalid_arguments); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(machine_main_obj, machine_main); STATIC mp_obj_t machine_idle(void) { __WFI(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle); STATIC mp_obj_t machine_lightsleep(void) { pyb_sleep_sleep(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_lightsleep_obj, machine_lightsleep); STATIC mp_obj_t machine_deepsleep (void) { pyb_sleep_deepsleep(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep); STATIC mp_obj_t machine_reset_cause (void) { return mp_obj_new_int(pyb_sleep_get_reset_cause()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); STATIC mp_obj_t machine_wake_reason (void) { return mp_obj_new_int(pyb_sleep_get_wake_reason()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_wake_reason_obj, machine_wake_reason); STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, #ifdef DEBUG { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_main), MP_ROM_PTR(&machine_main_obj) }, { MP_ROM_QSTR(MP_QSTR_rng), MP_ROM_PTR(&machine_rng_get_obj) }, { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_wake_reason), MP_ROM_PTR(&machine_wake_reason_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&pyb_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&pyb_wdt_type) }, { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sd_type) }, // class constants { MP_ROM_QSTR(MP_QSTR_IDLE), MP_ROM_INT(PYB_PWR_MODE_ACTIVE) }, { MP_ROM_QSTR(MP_QSTR_SLEEP), MP_ROM_INT(PYB_PWR_MODE_LPDS) }, { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(PYB_PWR_MODE_HIBERNATE) }, { MP_ROM_QSTR(MP_QSTR_POWER_ON), MP_ROM_INT(PYB_SLP_PWRON_RESET) }, // legacy constant { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(PYB_SLP_PWRON_RESET) }, { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(PYB_SLP_HARD_RESET) }, { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(PYB_SLP_WDT_RESET) }, { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(PYB_SLP_HIB_RESET) }, { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(PYB_SLP_SOFT_RESET) }, { MP_ROM_QSTR(MP_QSTR_WLAN_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_WLAN) }, { MP_ROM_QSTR(MP_QSTR_PIN_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_GPIO) }, { MP_ROM_QSTR(MP_QSTR_RTC_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_RTC) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t machine_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; micropython-1.12/ports/cc3200/mods/modnetwork.c000066400000000000000000000151451357706137100213700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "modnetwork.h" #include "mpexception.h" #include "serverstask.h" #include "simplelink.h" /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef struct { mp_obj_base_t base; } network_server_obj_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC network_server_obj_t network_server_obj; STATIC const mp_obj_type_t network_server_type; /// \module network - network configuration /// /// This module provides network drivers and server configuration. void mod_network_init0(void) { } #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) STATIC mp_obj_t network_server_init_helper(mp_obj_t self, const mp_arg_val_t *args) { const char *user = SERVERS_DEF_USER; const char *pass = SERVERS_DEF_PASS; if (args[0].u_obj != MP_OBJ_NULL) { mp_obj_t *login; mp_obj_get_array_fixed_n(args[0].u_obj, 2, &login); user = mp_obj_str_get_str(login[0]); pass = mp_obj_str_get_str(login[1]); } uint32_t timeout = SERVERS_DEF_TIMEOUT_MS / 1000; if (args[1].u_obj != MP_OBJ_NULL) { timeout = mp_obj_get_int(args[1].u_obj); } // configure the new login servers_set_login ((char *)user, (char *)pass); // configure the timeout servers_set_timeout(timeout * 1000); // start the servers servers_start(); return mp_const_none; } STATIC const mp_arg_t network_server_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_login, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); mp_arg_val_t args[MP_ARRAY_SIZE(network_server_args)]; mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), network_server_args, args); // check the server id if (args[0].u_obj != MP_OBJ_NULL) { if (mp_obj_get_int(args[0].u_obj) != 0) { mp_raise_OSError(MP_ENODEV); } } // setup the object and initialize it network_server_obj_t *self = &network_server_obj; self->base.type = &network_server_type; network_server_init_helper(self, &args[1]); return (mp_obj_t)self; } STATIC mp_obj_t network_server_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(network_server_args) - 1]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &network_server_args[1], args); return network_server_init_helper(pos_args[0], args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_server_init_obj, 1, network_server_init); // timeout value given in seconds STATIC mp_obj_t network_server_timeout(size_t n_args, const mp_obj_t *args) { if (n_args > 1) { uint32_t timeout = mp_obj_get_int(args[1]); servers_set_timeout(timeout * 1000); return mp_const_none; } else { // get return mp_obj_new_int(servers_get_timeout() / 1000); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_server_timeout_obj, 1, 2, network_server_timeout); STATIC mp_obj_t network_server_running(mp_obj_t self_in) { // get return mp_obj_new_bool(servers_are_enabled()); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_server_running_obj, network_server_running); STATIC mp_obj_t network_server_deinit(mp_obj_t self_in) { // simply stop the servers servers_stop(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_server_deinit_obj, network_server_deinit); #endif STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_wlan) }, #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) { MP_ROM_QSTR(MP_QSTR_Server), MP_ROM_PTR(&network_server_type) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); const mp_obj_module_t mp_module_network = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_network_globals, }; #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) STATIC const mp_rom_map_elem_t network_server_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_server_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_server_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&network_server_timeout_obj) }, { MP_ROM_QSTR(MP_QSTR_isrunning), MP_ROM_PTR(&network_server_running_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_server_locals_dict, network_server_locals_dict_table); STATIC const mp_obj_type_t network_server_type = { { &mp_type_type }, .name = MP_QSTR_Server, .make_new = network_server_make_new, .locals_dict = (mp_obj_t)&network_server_locals_dict, }; #endif micropython-1.12/ports/cc3200/mods/modnetwork.h000066400000000000000000000056311357706137100213740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_MODNETWORK_H #define MICROPY_INCLUDED_CC3200_MODS_MODNETWORK_H /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define MOD_NETWORK_IPV4ADDR_BUF_SIZE (4) /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef struct _mod_network_nic_type_t { mp_obj_type_t base; } mod_network_nic_type_t; typedef struct _mod_network_socket_base_t { union { struct { // this order is important so that fileno gets > 0 once // the socket descriptor is assigned after being created. uint8_t domain; int8_t fileno; uint8_t type; uint8_t proto; } u_param; int16_t sd; }; uint32_t timeout_ms; // 0 for no timeout bool cert_req; } mod_network_socket_base_t; typedef struct _mod_network_socket_obj_t { mp_obj_base_t base; mod_network_socket_base_t sock_base; } mod_network_socket_obj_t; /****************************************************************************** EXPORTED DATA ******************************************************************************/ extern const mod_network_nic_type_t mod_network_nic_type_wlan; /****************************************************************************** DECLARE FUNCTIONS ******************************************************************************/ void mod_network_init0(void); #endif // MICROPY_INCLUDED_CC3200_MODS_MODNETWORK_H micropython-1.12/ports/cc3200/mods/modubinascii.c000066400000000000000000000046071357706137100216460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/binary.h" #include "extmod/modubinascii.h" #include "modubinascii.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_dthe.h" #include "hw_memmap.h" #include "rom_map.h" #include "prcm.h" #include "crc.h" #include "cryptohash.h" #include "mpexception.h" /******************************************************************************/ // MicroPython bindings STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubinascii) }, { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&mod_binascii_hexlify_obj) }, { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) }, { MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) }, { MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table); const mp_obj_module_t mp_module_ubinascii = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_binascii_globals, }; micropython-1.12/ports/cc3200/mods/modubinascii.h000066400000000000000000000025501357706137100216460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_MODUBINASCII_H #define MICROPY_INCLUDED_CC3200_MODS_MODUBINASCII_H #endif // MICROPY_INCLUDED_CC3200_MODS_MODUBINASCII_H micropython-1.12/ports/cc3200/mods/moduhashlib.c000066400000000000000000000162261357706137100214770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpconfig.h" #include MICROPY_HAL_H #include "py/runtime.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_shamd5.h" #include "inc/hw_dthe.h" #include "hw_memmap.h" #include "rom_map.h" #include "prcm.h" #include "shamd5.h" #include "cryptohash.h" #include "mpexception.h" /****************************************************************************** DEFINE PRIVATE TYPES ******************************************************************************/ typedef struct _mp_obj_hash_t { mp_obj_base_t base; uint8_t *buffer; uint32_t b_size; uint32_t c_size; uint8_t algo; uint8_t h_size; bool fixedlen; bool digested; uint8_t hash[32]; } mp_obj_hash_t; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest); STATIC mp_obj_t hash_read (mp_obj_t self_in); /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest) { mp_obj_hash_t *self = self_in; mp_buffer_info_t bufinfo; if (data) { mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); } if (digest) { CRYPTOHASH_SHAMD5Start (self->algo, self->b_size); } if (self->c_size < self->b_size || !data || !self->fixedlen) { if (digest || self->fixedlen) { // no data means we want to process our internal buffer CRYPTOHASH_SHAMD5Update (data ? bufinfo.buf : self->buffer, data ? bufinfo.len : self->b_size); self->c_size += data ? bufinfo.len : 0; } else { self->buffer = m_renew(byte, self->buffer, self->b_size, self->b_size + bufinfo.len); mp_seq_copy((byte*)self->buffer + self->b_size, bufinfo.buf, bufinfo.len, byte); self->b_size += bufinfo.len; self->digested = false; } } else { mp_raise_OSError(MP_EPERM); } } STATIC mp_obj_t hash_read (mp_obj_t self_in) { mp_obj_hash_t *self = self_in; if (!self->fixedlen) { if (!self->digested) { hash_update_internal(self, MP_OBJ_NULL, true); } } else if (self->c_size < self->b_size) { // it's a fixed len block which is still incomplete mp_raise_OSError(MP_EPERM); } if (!self->digested) { CRYPTOHASH_SHAMD5Read ((uint8_t *)self->hash); self->digested = true; } return mp_obj_new_bytes(self->hash, self->h_size); } /******************************************************************************/ // MicroPython bindings /// \classmethod \constructor([data[, block_size]]) /// initial data must be given if block_size wants to be passed STATIC mp_obj_t hash_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 2, false); mp_obj_hash_t *self = m_new0(mp_obj_hash_t, 1); self->base.type = type_in; if (self->base.type->name == MP_QSTR_sha1) { self->algo = SHAMD5_ALGO_SHA1; self->h_size = 20; } else /* if (self->base.type->name == MP_QSTR_sha256) */ { self->algo = SHAMD5_ALGO_SHA256; self->h_size = 32; } /* else { self->algo = SHAMD5_ALGO_MD5; self->h_size = 32; } */ if (n_args) { // CPython extension to avoid buffering the data before digesting it // Note: care must be taken to provide all intermediate blocks as multiple // of four bytes, otherwise the resulting hash will be incorrect. // the final block can be of any length if (n_args > 1) { // block size given, we will feed the data directly into the hash engine self->fixedlen = true; self->b_size = mp_obj_get_int(args[1]); hash_update_internal(self, args[0], true); } else { hash_update_internal(self, args[0], false); } } return self; } STATIC mp_obj_t hash_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = self_in; hash_update_internal(self, arg, false); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(hash_update_obj, hash_update); STATIC mp_obj_t hash_digest(mp_obj_t self_in) { return hash_read(self_in); } MP_DEFINE_CONST_FUN_OBJ_1(hash_digest_obj, hash_digest); STATIC const mp_rom_map_elem_t hash_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hash_update_obj) }, { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hash_digest_obj) }, }; STATIC MP_DEFINE_CONST_DICT(hash_locals_dict, hash_locals_dict_table); //STATIC const mp_obj_type_t md5_type = { // { &mp_type_type }, // .name = MP_QSTR_md5, // .make_new = hash_make_new, // .locals_dict = (mp_obj_t)&hash_locals_dict, //}; STATIC const mp_obj_type_t sha1_type = { { &mp_type_type }, .name = MP_QSTR_sha1, .make_new = hash_make_new, .locals_dict = (mp_obj_t)&hash_locals_dict, }; STATIC const mp_obj_type_t sha256_type = { { &mp_type_type }, .name = MP_QSTR_sha256, .make_new = hash_make_new, .locals_dict = (mp_obj_t)&hash_locals_dict, }; STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uhashlib) }, //{ MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&md5_type) }, { MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&sha1_type) }, { MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&sha256_type) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table); const mp_obj_module_t mp_module_uhashlib = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_hashlib_globals, }; micropython-1.12/ports/cc3200/mods/moduos.c000066400000000000000000000157541357706137100205130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objtuple.h" #include "py/objstr.h" #include "py/runtime.h" #include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "genhdr/mpversion.h" #include "moduos.h" #include "sflash_diskio.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "random.h" #include "mpexception.h" #include "version.h" #include "pybsd.h" #include "pybuart.h" /// \module os - basic "operating system" services /// /// The `os` module contains functions for filesystem access and `urandom`. /// /// The filesystem has `/` as the root directory, and the available physical /// drives are accessible from here. They are currently: /// /// /flash -- the serial flash filesystem /// /// On boot up, the current directory is `/flash`. /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC os_term_dup_obj_t os_term_dup_obj; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void osmount_unmount_all (void) { //TODO /* for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) { os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i])); unmount(mount_obj); } */ } /******************************************************************************/ // MicroPython bindings // STATIC const qstr os_uname_info_fields[] = { MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine }; STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, WIPY_SW_VERSION_NUMBER); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); STATIC MP_DEFINE_ATTRTUPLE( os_uname_info_obj, os_uname_info_fields, 5, (mp_obj_t)&os_uname_info_sysname_obj, (mp_obj_t)&os_uname_info_nodename_obj, (mp_obj_t)&os_uname_info_release_obj, (mp_obj_t)&os_uname_info_version_obj, (mp_obj_t)&os_uname_info_machine_obj ); STATIC mp_obj_t os_uname(void) { return (mp_obj_t)&os_uname_info_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); STATIC mp_obj_t os_sync(void) { sflash_disk_flush(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync); STATIC mp_obj_t os_urandom(mp_obj_t num) { mp_int_t n = mp_obj_get_int(num); vstr_t vstr; vstr_init_len(&vstr, n); for (int i = 0; i < n; i++) { vstr.buf[i] = rng_get(); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); STATIC mp_obj_t os_dupterm(uint n_args, const mp_obj_t *args) { if (n_args == 0) { if (MP_STATE_PORT(os_term_dup_obj) == MP_OBJ_NULL) { return mp_const_none; } else { return MP_STATE_PORT(os_term_dup_obj)->stream_o; } } else { mp_obj_t stream_o = args[0]; if (stream_o == mp_const_none) { MP_STATE_PORT(os_term_dup_obj) = MP_OBJ_NULL; } else { if (!mp_obj_is_type(stream_o, &pyb_uart_type)) { // must be a stream-like object providing at least read and write methods mp_load_method(stream_o, MP_QSTR_read, os_term_dup_obj.read); mp_load_method(stream_o, MP_QSTR_write, os_term_dup_obj.write); } os_term_dup_obj.stream_o = stream_o; MP_STATE_PORT(os_term_dup_obj) = &os_term_dup_obj; } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_dupterm_obj, 0, 1, os_dupterm); STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&os_sync_obj) }, { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, // MicroPython additions // removed: mkfs // renamed: unmount -> umount { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&os_dupterm_obj) }, }; STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); const mp_obj_module_t mp_module_uos = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&os_module_globals, }; micropython-1.12/ports/cc3200/mods/moduos.h000066400000000000000000000036501357706137100205100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_MODUOS_H #define MICROPY_INCLUDED_CC3200_MODS_MODUOS_H #include "py/obj.h" /****************************************************************************** DEFINE PUBLIC TYPES ******************************************************************************/ typedef struct _os_term_dup_obj_t { mp_obj_t stream_o; mp_obj_t read[3]; mp_obj_t write[3]; } os_term_dup_obj_t; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ void osmount_unmount_all (void); #endif // MICROPY_INCLUDED_CC3200_MODS_MODUOS_H micropython-1.12/ports/cc3200/mods/modusocket.c000066400000000000000000000701051357706137100213510ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "simplelink.h" #include "py/mpconfig.h" #include "py/obj.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" #include "lib/netutils/netutils.h" #include "modnetwork.h" #include "modusocket.h" #include "mpexception.h" /******************************************************************************/ // The following set of macros and functions provide a glue between the CC3100 // simplelink layer and the functions/methods provided by the usocket module. // They were historically in a separate file because usocket was designed to // work with multiple NICs, and the wlan_XXX functions just provided one // particular NIC implementation (that of the CC3100). But the CC3200 port only // supports a single NIC (being the CC3100) so it's unnecessary and inefficient // to provide an intermediate wrapper layer. Hence the wlan_XXX functions // are provided below as static functions so they can be inlined directly by // the corresponding usocket calls. #define WLAN_MAX_RX_SIZE 16000 #define WLAN_MAX_TX_SIZE 1476 #define MAKE_SOCKADDR(addr, ip, port) SlSockAddr_t addr; \ addr.sa_family = SL_AF_INET; \ addr.sa_data[0] = port >> 8; \ addr.sa_data[1] = port; \ addr.sa_data[2] = ip[3]; \ addr.sa_data[3] = ip[2]; \ addr.sa_data[4] = ip[1]; \ addr.sa_data[5] = ip[0]; #define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \ ip[0] = addr.sa_data[5]; \ ip[1] = addr.sa_data[4]; \ ip[2] = addr.sa_data[3]; \ ip[3] = addr.sa_data[2]; #define SOCKET_TIMEOUT_QUANTA_MS (20) STATIC int convert_sl_errno(int sl_errno) { return -sl_errno; } // This function is left as non-static so it's not inlined. int check_timedout(mod_network_socket_obj_t *s, int ret, uint32_t *timeout_ms, int *_errno) { if (*timeout_ms == 0 || ret != SL_EAGAIN) { if (s->sock_base.timeout_ms > 0 && ret == SL_EAGAIN) { *_errno = MP_ETIMEDOUT; } else { *_errno = convert_sl_errno(ret); } return -1; } mp_hal_delay_ms(SOCKET_TIMEOUT_QUANTA_MS); if (*timeout_ms < SOCKET_TIMEOUT_QUANTA_MS) { *timeout_ms = 0; } else { *timeout_ms -= SOCKET_TIMEOUT_QUANTA_MS; } return 0; } STATIC int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { uint32_t ip; int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family); out_ip[0] = ip; out_ip[1] = ip >> 8; out_ip[2] = ip >> 16; out_ip[3] = ip >> 24; return result; } STATIC int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) { int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto); if (sd < 0) { *_errno = sd; return -1; } s->sock_base.sd = sd; return 0; } STATIC void wlan_socket_close(mod_network_socket_obj_t *s) { // this is to prevent the finalizer to close a socket that failed when being created if (s->sock_base.sd >= 0) { modusocket_socket_delete(s->sock_base.sd); sl_Close(s->sock_base.sd); s->sock_base.sd = -1; } } STATIC int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr)); if (ret != 0) { *_errno = ret; return -1; } return 0; } STATIC int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) { int ret = sl_Listen(s->sock_base.sd, backlog); if (ret != 0) { *_errno = ret; return -1; } return 0; } STATIC int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) { // accept incoming connection int16_t sd; SlSockAddr_t addr; SlSocklen_t addr_len = sizeof(addr); uint32_t timeout_ms = s->sock_base.timeout_ms; for (;;) { sd = sl_Accept(s->sock_base.sd, &addr, &addr_len); if (sd >= 0) { // save the socket descriptor s2->sock_base.sd = sd; // return ip and port UNPACK_SOCKADDR(addr, ip, *port); return 0; } if (check_timedout(s, sd, &timeout_ms, _errno)) { return -1; } } } STATIC int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) uint32_t timeout_ms = s->sock_base.timeout_ms; // For a non-blocking connect the CC3100 will return SL_EALREADY while the // connection is in progress. for (;;) { int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr)); if (ret == 0) { return 0; } // Check if we are in non-blocking mode and the connection is in progress if (s->sock_base.timeout_ms == 0 && ret == SL_EALREADY) { // To match BSD we return EINPROGRESS here *_errno = MP_EINPROGRESS; return -1; } // We are in blocking mode, so if the connection isn't in progress then error out if (ret != SL_EALREADY) { *_errno = convert_sl_errno(ret); return -1; } if (check_timedout(s, SL_EAGAIN, &timeout_ms, _errno)) { return -1; } } } STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) { if (len == 0) { return 0; } uint32_t timeout_ms = s->sock_base.timeout_ms; for (;;) { int ret = sl_Send(s->sock_base.sd, (const void *)buf, len, 0); if (ret > 0) { return ret; } if (check_timedout(s, ret, &timeout_ms, _errno)) { return -1; } } } STATIC int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) { uint32_t timeout_ms = s->sock_base.timeout_ms; for (;;) { int ret = sl_Recv(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0); if (ret >= 0) { return ret; } if (check_timedout(s, ret, &timeout_ms, _errno)) { return -1; } } } STATIC int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) uint32_t timeout_ms = s->sock_base.timeout_ms; for (;;) { int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (SlSockAddr_t*)&addr, sizeof(addr)); if (ret >= 0) { return ret; } if (check_timedout(s, ret, &timeout_ms, _errno)) { return -1; } } } STATIC int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { SlSockAddr_t addr; SlSocklen_t addr_len = sizeof(addr); uint32_t timeout_ms = s->sock_base.timeout_ms; for (;;) { int ret = sl_RecvFrom(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len); if (ret >= 0) { UNPACK_SOCKADDR(addr, ip, *port); return ret; } if (check_timedout(s, ret, &timeout_ms, _errno)) { return -1; } } } STATIC int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen); if (ret < 0) { *_errno = ret; return -1; } return 0; } STATIC int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) { SlSockNonblocking_t option; if (timeout_s == 0 || timeout_s == -1) { if (timeout_s == 0) { // set non-blocking mode option.NonblockingEnabled = 1; } else { // set blocking mode option.NonblockingEnabled = 0; } timeout_s = 0; } else { // synthesize timeout via non-blocking behaviour with a loop option.NonblockingEnabled = 1; } int ret = sl_SetSockOpt(s->sock_base.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &option, sizeof(option)); if (ret != 0) { *_errno = convert_sl_errno(ret); return -1; } s->sock_base.timeout_ms = timeout_s * 1000; return 0; } STATIC int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) { mp_int_t ret; if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; int32_t sd = s->sock_base.sd; // init fds SlFdSet_t rfds, wfds, xfds; SL_FD_ZERO(&rfds); SL_FD_ZERO(&wfds); SL_FD_ZERO(&xfds); // set fds if needed if (flags & MP_STREAM_POLL_RD) { SL_FD_SET(sd, &rfds); } if (flags & MP_STREAM_POLL_WR) { SL_FD_SET(sd, &wfds); } if (flags & MP_STREAM_POLL_HUP) { SL_FD_SET(sd, &xfds); } // call simplelink's select with minimum timeout SlTimeval_t tv; tv.tv_sec = 0; tv.tv_usec = 1; int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv); // check for errors if (nfds == -1) { *_errno = nfds; return -1; } // check return of select if (SL_FD_ISSET(sd, &rfds)) { ret |= MP_STREAM_POLL_RD; } if (SL_FD_ISSET(sd, &wfds)) { ret |= MP_STREAM_POLL_WR; } if (SL_FD_ISSET(sd, &xfds)) { ret |= MP_STREAM_POLL_HUP; } } else if (request == MP_STREAM_CLOSE) { wlan_socket_close(s); ret = 0; } else { *_errno = MP_EINVAL; ret = MP_STREAM_ERROR; } return ret; } /****************************************************************************** DEFINE PRIVATE CONSTANTS ******************************************************************************/ #define MOD_NETWORK_MAX_SOCKETS 10 /****************************************************************************** DEFINE PRIVATE TYPES ******************************************************************************/ typedef struct { int16_t sd; bool user; } modusocket_sock_t; /****************************************************************************** DEFINE PRIVATE DATA ******************************************************************************/ STATIC const mp_obj_type_t socket_type; STATIC OsiLockObj_t modusocket_LockObj; STATIC modusocket_sock_t modusocket_sockets[MOD_NETWORK_MAX_SOCKETS] = {{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}}; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ __attribute__ ((section (".boot"))) void modusocket_pre_init (void) { // create the wlan lock ASSERT(OSI_OK == sl_LockObjCreate(&modusocket_LockObj, "SockLock")); sl_LockObjUnlock (&modusocket_LockObj); } void modusocket_socket_add (int16_t sd, bool user) { sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { if (modusocket_sockets[i].sd < 0) { modusocket_sockets[i].sd = sd; modusocket_sockets[i].user = user; break; } } sl_LockObjUnlock (&modusocket_LockObj); } void modusocket_socket_delete (int16_t sd) { sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { if (modusocket_sockets[i].sd == sd) { modusocket_sockets[i].sd = -1; break; } } sl_LockObjUnlock (&modusocket_LockObj); } void modusocket_enter_sleep (void) { SlFdSet_t socketset; int16_t maxfd = 0; for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { int16_t sd; if ((sd = modusocket_sockets[i].sd) >= 0) { SL_FD_SET(sd, &socketset); maxfd = (maxfd > sd) ? maxfd : sd; } } if (maxfd > 0) { // wait for any of the sockets to become ready... sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL); } } void modusocket_close_all_user_sockets (void) { sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { if (modusocket_sockets[i].sd >= 0 && modusocket_sockets[i].user) { sl_Close(modusocket_sockets[i].sd); modusocket_sockets[i].sd = -1; } } sl_LockObjUnlock (&modusocket_LockObj); } /******************************************************************************/ // socket class // constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None) STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 4, false); // create socket object mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t); s->base.type = (mp_obj_t)&socket_type; s->sock_base.u_param.domain = SL_AF_INET; s->sock_base.u_param.type = SL_SOCK_STREAM; s->sock_base.u_param.proto = SL_IPPROTO_TCP; s->sock_base.u_param.fileno = -1; s->sock_base.timeout_ms = 0; s->sock_base.cert_req = false; if (n_args > 0) { s->sock_base.u_param.domain = mp_obj_get_int(args[0]); if (n_args > 1) { s->sock_base.u_param.type = mp_obj_get_int(args[1]); if (n_args > 2) { s->sock_base.u_param.proto = mp_obj_get_int(args[2]); if (n_args > 3) { s->sock_base.u_param.fileno = mp_obj_get_int(args[3]); } } } } // create the socket int _errno; if (wlan_socket_socket(s, &_errno) != 0) { mp_raise_OSError(-_errno); } // add the socket to the list modusocket_socket_add(s->sock_base.sd, true); return s; } // method socket.bind(address) STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { mod_network_socket_obj_t *self = self_in; // get address uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); // call the NIC to bind the socket int _errno = 0; if (wlan_socket_bind(self, ip, port, &_errno) != 0) { mp_raise_OSError(-_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); // method socket.listen([backlog]) STATIC mp_obj_t socket_listen(size_t n_args, const mp_obj_t *args) { mod_network_socket_obj_t *self = args[0]; int32_t backlog = 0; if (n_args > 1) { backlog = mp_obj_get_int(args[1]); backlog = (backlog < 0) ? 0 : backlog; } int _errno; if (wlan_socket_listen(self, backlog, &_errno) != 0) { mp_raise_OSError(-_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen); // method socket.accept() STATIC mp_obj_t socket_accept(mp_obj_t self_in) { mod_network_socket_obj_t *self = self_in; // create new socket object mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); // the new socket inherits all properties from its parent memcpy (socket2, self, sizeof(mod_network_socket_obj_t)); // accept the incoming connection uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; mp_uint_t port = 0; int _errno = 0; if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) { mp_raise_OSError(_errno); } // add the socket to the list modusocket_socket_add(socket2->sock_base.sd, true); // make the return value mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = socket2; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); return client; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); // method socket.connect(address) STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { mod_network_socket_obj_t *self = self_in; // get address uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); // connect the socket int _errno; if (wlan_socket_connect(self, ip, port, &_errno) != 0) { if (!self->sock_base.cert_req && _errno == SL_ESECSNOVERIFY) { return mp_const_none; } mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); // method socket.send(bytes) STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { mod_network_socket_obj_t *self = self_in; mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); int _errno; mp_int_t ret = wlan_socket_send(self, bufinfo.buf, bufinfo.len, &_errno); if (ret < 0) { mp_raise_OSError(_errno); } return mp_obj_new_int_from_uint(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); // method socket.recv(bufsize) STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = self_in; mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); int _errno; mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno); if (ret < 0) { mp_raise_OSError(_errno); } if (ret == 0) { return mp_const_empty_bytes; } vstr.len = ret; vstr.buf[vstr.len] = '\0'; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); // method socket.sendto(bytes, address) STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { mod_network_socket_obj_t *self = self_in; // get the data mp_buffer_info_t bufinfo; mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); // get address uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); // call the nic to sendto int _errno = 0; mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); if (ret < 0) { mp_raise_OSError(_errno); } return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); // method socket.recvfrom(bufsize) STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = self_in; vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(len_in)); byte ip[4]; mp_uint_t port = 0; int _errno = 0; mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); if (ret < 0) { mp_raise_OSError(_errno); } mp_obj_t tuple[2]; if (ret == 0) { tuple[0] = mp_const_empty_bytes; } else { vstr.len = ret; vstr.buf[vstr.len] = '\0'; tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom); // method socket.setsockopt(level, optname, value) STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { mod_network_socket_obj_t *self = args[0]; mp_int_t level = mp_obj_get_int(args[1]); mp_int_t opt = mp_obj_get_int(args[2]); const void *optval; mp_uint_t optlen; mp_int_t val; if (mp_obj_is_integer(args[3])) { val = mp_obj_get_int_truncated(args[3]); optval = &val; optlen = sizeof(val); } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); optval = bufinfo.buf; optlen = bufinfo.len; } int _errno; if (wlan_socket_setsockopt(self, level, opt, optval, optlen, &_errno) != 0) { mp_raise_OSError(-_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); // method socket.settimeout(value) // timeout=0 means non-blocking // timeout=None means blocking // otherwise, timeout is in seconds STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { mod_network_socket_obj_t *self = self_in; mp_uint_t timeout; if (timeout_in == mp_const_none) { timeout = -1; } else { timeout = mp_obj_get_int(timeout_in); } int _errno = 0; if (wlan_socket_settimeout(self, timeout, &_errno) != 0) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); // method socket.setblocking(flag) STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { if (mp_obj_is_true(blocking)) { return socket_settimeout(self_in, mp_const_none); } else { return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0)); } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { (void)n_args; return args[0]; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 6, socket_makefile); STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, { MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&socket_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) }, // stream methods { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read1_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, }; MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { mod_network_socket_obj_t *self = self_in; mp_int_t ret = wlan_socket_recv(self, buf, size, errcode); if (ret < 0) { // we need to ignore the socket closed error here because a read() without params // only returns when the socket is closed by the other end if (*errcode != -SL_ESECCLOSED) { ret = MP_STREAM_ERROR; } else { ret = 0; } } return ret; } STATIC mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { mod_network_socket_obj_t *self = self_in; mp_int_t ret = wlan_socket_send(self, buf, size, errcode); if (ret < 0) { ret = MP_STREAM_ERROR; } return ret; } STATIC mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { mod_network_socket_obj_t *self = self_in; return wlan_socket_ioctl(self, request, arg, errcode); } const mp_stream_p_t socket_stream_p = { .read = socket_read, .write = socket_write, .ioctl = socket_ioctl, .is_text = false, }; STATIC const mp_obj_type_t socket_type = { { &mp_type_type }, .name = MP_QSTR_socket, .make_new = socket_make_new, .protocol = &socket_stream_p, .locals_dict = (mp_obj_t)&socket_locals_dict, }; /******************************************************************************/ // usocket module // function usocket.getaddrinfo(host, port) /// \function getaddrinfo(host, port) STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { size_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); // ipv4 only uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; int32_t result = wlan_gethostbyname(host, hlen, out_ip, SL_AF_INET); if (result < 0) { mp_raise_OSError(-result); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SL_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SL_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE); return mp_obj_new_list(1, (mp_obj_t*)&tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo); STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_usocket_getaddrinfo_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(SL_AF_INET) }, { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SL_SOCK_STREAM) }, { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SL_SOCK_DGRAM) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_SEC), MP_ROM_INT(SL_SEC_SOCKET) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(SL_IPPROTO_TCP) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(SL_IPPROTO_UDP) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); const mp_obj_module_t mp_module_usocket = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, }; micropython-1.12/ports/cc3200/mods/modusocket.h000066400000000000000000000033141357706137100213540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H #define MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H #include "py/stream.h" extern const mp_obj_dict_t socket_locals_dict; extern const mp_stream_p_t socket_stream_p; extern void modusocket_pre_init (void); extern void modusocket_socket_add (int16_t sd, bool user); extern void modusocket_socket_delete (int16_t sd); extern void modusocket_enter_sleep (void); extern void modusocket_close_all_user_sockets (void); #endif // MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H micropython-1.12/ports/cc3200/mods/modussl.c000066400000000000000000000157661357706137100206760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "simplelink.h" #include "py/mpconfig.h" #include "py/obj.h" #include "py/objstr.h" #include "py/runtime.h" #include "modnetwork.h" #include "modusocket.h" #include "mpexception.h" /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define SSL_CERT_NONE (0) #define SSL_CERT_OPTIONAL (1) #define SSL_CERT_REQUIRED (2) /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef struct _mp_obj_ssl_socket_t { mp_obj_base_t base; mod_network_socket_base_t sock_base; mp_obj_t o_sock; } mp_obj_ssl_socket_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC const mp_obj_type_t ssl_socket_type; /******************************************************************************/ // MicroPython bindings; SSL class // ssl sockets inherit from normal socket, so we take its // locals and stream methods STATIC const mp_obj_type_t ssl_socket_type = { { &mp_type_type }, .name = MP_QSTR_ussl, .getiter = NULL, .iternext = NULL, .protocol = &socket_stream_p, .locals_dict = (mp_obj_t)&socket_locals_dict, }; STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t allowed_args[] = { { MP_QSTR_sock, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_keyfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} }, { MP_QSTR_ssl_version, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SL_SO_SEC_METHOD_TLSV1} }, { MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // parse arguments mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // check if ca validation is required if (args[4].u_int != SSL_CERT_NONE && args[6].u_obj == mp_const_none) { goto arg_error; } // retrieve the file paths (with an 6 byte offset in order to strip it from the '/flash' prefix) const char *keyfile = (args[1].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[1].u_obj)[6]); const char *certfile = (args[2].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[2].u_obj)[6]); const char *cafile = (args[6].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ? NULL : &(mp_obj_str_get_str(args[6].u_obj)[6]); // server side requires both certfile and keyfile if (args[3].u_bool && (!keyfile || !certfile)) { goto arg_error; } _i16 _errno; _i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd; // set the requested SSL method _u8 method = args[5].u_int; if ((_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method))) < 0) { goto socket_error; } if (keyfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, keyfile, strlen(keyfile))) < 0) { goto socket_error; } if (certfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, certfile, strlen(certfile))) < 0) { goto socket_error; } if (cafile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME, cafile, strlen(cafile))) < 0) { goto socket_error; } // create the ssl socket mp_obj_ssl_socket_t *ssl_sock = m_new_obj(mp_obj_ssl_socket_t); // ssl sockets inherit all properties from the original socket memcpy (&ssl_sock->sock_base, &((mod_network_socket_obj_t *)args[0].u_obj)->sock_base, sizeof(mod_network_socket_base_t)); ssl_sock->base.type = &ssl_socket_type; ssl_sock->sock_base.cert_req = (args[4].u_int == SSL_CERT_REQUIRED) ? true : false; ssl_sock->o_sock = args[0].u_obj; return ssl_sock; socket_error: mp_raise_OSError(_errno); arg_error: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 0, mod_ssl_wrap_socket); STATIC const mp_rom_map_elem_t mp_module_ussl_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) }, { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) }, // class exceptions { MP_ROM_QSTR(MP_QSTR_SSLError), MP_ROM_PTR(&mp_type_OSError) }, // class constants { MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(SSL_CERT_NONE) }, { MP_ROM_QSTR(MP_QSTR_CERT_OPTIONAL), MP_ROM_INT(SSL_CERT_OPTIONAL) }, { MP_ROM_QSTR(MP_QSTR_CERT_REQUIRED), MP_ROM_INT(SSL_CERT_REQUIRED) }, { MP_ROM_QSTR(MP_QSTR_PROTOCOL_SSLv3), MP_ROM_INT(SL_SO_SEC_METHOD_SSLV3) }, { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1) }, { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1_1), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1_1) }, { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1_2), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1_2) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_ussl_globals, mp_module_ussl_globals_table); const mp_obj_module_t mp_module_ussl = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_ussl_globals, }; micropython-1.12/ports/cc3200/mods/modutime.c000066400000000000000000000140211357706137100210120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpconfig.h" #include "py/runtime.h" #include "py/obj.h" #include "py/smallint.h" #include "py/mphal.h" #include "lib/timeutils/timeutils.h" #include "extmod/utime_mphal.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "prcm.h" #include "systick.h" #include "pybrtc.h" #include "mpexception.h" #include "utils.h" /// \module time - time related functions /// /// The `time` module provides functions for getting the current time and date, /// and for sleeping. /******************************************************************************/ // MicroPython bindings /// \function localtime([secs]) /// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which /// contains: (year, month, mday, hour, minute, second, weekday, yearday) /// If secs is not provided or None, then the current time from the RTC is used. /// year includes the century (for example 2015) /// month is 1-12 /// mday is 1-31 /// hour is 0-23 /// minute is 0-59 /// second is 0-59 /// weekday is 0-6 for Mon-Sun. /// yearday is 1-366 STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { if (n_args == 0 || args[0] == mp_const_none) { timeutils_struct_time_t tm; // get the seconds from the RTC timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm); mp_obj_t tuple[8] = { mp_obj_new_int(tm.tm_year), mp_obj_new_int(tm.tm_mon), mp_obj_new_int(tm.tm_mday), mp_obj_new_int(tm.tm_hour), mp_obj_new_int(tm.tm_min), mp_obj_new_int(tm.tm_sec), mp_obj_new_int(tm.tm_wday), mp_obj_new_int(tm.tm_yday) }; return mp_obj_new_tuple(8, tuple); } else { mp_int_t seconds = mp_obj_get_int(args[0]); timeutils_struct_time_t tm; timeutils_seconds_since_2000_to_struct_time(seconds, &tm); mp_obj_t tuple[8] = { tuple[0] = mp_obj_new_int(tm.tm_year), tuple[1] = mp_obj_new_int(tm.tm_mon), tuple[2] = mp_obj_new_int(tm.tm_mday), tuple[3] = mp_obj_new_int(tm.tm_hour), tuple[4] = mp_obj_new_int(tm.tm_min), tuple[5] = mp_obj_new_int(tm.tm_sec), tuple[6] = mp_obj_new_int(tm.tm_wday), tuple[7] = mp_obj_new_int(tm.tm_yday), }; return mp_obj_new_tuple(8, tuple); } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime); STATIC mp_obj_t time_mktime(mp_obj_t tuple) { size_t len; mp_obj_t *elem; mp_obj_get_array(tuple, &len, &elem); // localtime generates a tuple of len 8. CPython uses 9, so we accept both. if (len < 8 || len > 9) { mp_raise_TypeError(mpexception_num_type_invalid_arguments); } return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); } MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); STATIC mp_obj_t time_time(void) { return mp_obj_new_int(pyb_rtc_get_seconds()); } MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { int32_t sleep_s = mp_obj_get_int(seconds_o); if (sleep_s > 0) { mp_hal_delay_ms(sleep_s * 1000); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep); STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) }, { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) }, { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&time_sleep_obj) }, // MicroPython additions { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t mp_module_utime = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; micropython-1.12/ports/cc3200/mods/modwipy.c000066400000000000000000000017341357706137100206660ustar00rootroot00000000000000#include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" #include "mperror.h" /******************************************************************************/ // MicroPython bindings STATIC mp_obj_t mod_wipy_heartbeat(size_t n_args, const mp_obj_t *args) { if (n_args) { mperror_enable_heartbeat (mp_obj_is_true(args[0])); return mp_const_none; } else { return mp_obj_new_bool(mperror_is_heartbeat_enabled()); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_wipy_heartbeat_obj, 0, 1, mod_wipy_heartbeat); STATIC const mp_rom_map_elem_t wipy_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wipy) }, { MP_ROM_QSTR(MP_QSTR_heartbeat), MP_ROM_PTR(&mod_wipy_heartbeat_obj) }, }; STATIC MP_DEFINE_CONST_DICT(wipy_module_globals, wipy_module_globals_table); const mp_obj_module_t wipy_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&wipy_module_globals, }; micropython-1.12/ports/cc3200/mods/modwlan.c000066400000000000000000001372001357706137100206350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "simplelink.h" #include "py/mpconfig.h" #include "py/obj.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" #include "lib/timeutils/timeutils.h" #include "lib/netutils/netutils.h" #include "modnetwork.h" #include "modusocket.h" #include "modwlan.h" #include "pybrtc.h" #include "debug.h" #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) #include "serverstask.h" #endif #include "mpexception.h" #include "mpirq.h" #include "pybsleep.h" #include "antenna.h" /****************************************************************************** DEFINE TYPES ******************************************************************************/ // Status bits - These are used to set/reset the corresponding bits in a given variable typedef enum{ STATUS_BIT_NWP_INIT = 0, // If this bit is set: Network Processor is // powered up STATUS_BIT_CONNECTION, // If this bit is set: the device is connected to // the AP or client is connected to device (AP) STATUS_BIT_IP_LEASED, // If this bit is set: the device has leased IP to // any connected client STATUS_BIT_IP_ACQUIRED, // If this bit is set: the device has acquired an IP STATUS_BIT_SMARTCONFIG_START, // If this bit is set: the SmartConfiguration // process is started from SmartConfig app STATUS_BIT_P2P_DEV_FOUND, // If this bit is set: the device (P2P mode) // found any p2p-device in scan STATUS_BIT_P2P_REQ_RECEIVED, // If this bit is set: the device (P2P mode) // found any p2p-negotiation request STATUS_BIT_CONNECTION_FAILED, // If this bit is set: the device(P2P mode) // connection to client(or reverse way) is failed STATUS_BIT_PING_DONE // If this bit is set: the device has completed // the ping operation } e_StatusBits; /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define CLR_STATUS_BIT_ALL(status) (status = 0) #define SET_STATUS_BIT(status, bit) (status |= ( 1 << (bit))) #define CLR_STATUS_BIT(status, bit) (status &= ~(1 << (bit))) #define GET_STATUS_BIT(status, bit) (0 != (status & (1 << (bit)))) #define IS_NW_PROCSR_ON(status) GET_STATUS_BIT(status, STATUS_BIT_NWP_INIT) #define IS_CONNECTED(status) GET_STATUS_BIT(status, STATUS_BIT_CONNECTION) #define IS_IP_LEASED(status) GET_STATUS_BIT(status, STATUS_BIT_IP_LEASED) #define IS_IP_ACQUIRED(status) GET_STATUS_BIT(status, STATUS_BIT_IP_ACQUIRED) #define IS_SMART_CFG_START(status) GET_STATUS_BIT(status, STATUS_BIT_SMARTCONFIG_START) #define IS_P2P_DEV_FOUND(status) GET_STATUS_BIT(status, STATUS_BIT_P2P_DEV_FOUND) #define IS_P2P_REQ_RCVD(status) GET_STATUS_BIT(status, STATUS_BIT_P2P_REQ_RECEIVED) #define IS_CONNECT_FAILED(status) GET_STATUS_BIT(status, STATUS_BIT_CONNECTION_FAILED) #define IS_PING_DONE(status) GET_STATUS_BIT(status, STATUS_BIT_PING_DONE) #define MODWLAN_SL_SCAN_ENABLE 1 #define MODWLAN_SL_SCAN_DISABLE 0 #define MODWLAN_SL_MAX_NETWORKS 20 #define MODWLAN_MAX_NETWORKS 20 #define MODWLAN_SCAN_PERIOD_S 3600 // 1 hour #define MODWLAN_WAIT_FOR_SCAN_MS 1050 #define MODWLAN_CONNECTION_WAIT_MS 2 #define ASSERT_ON_ERROR(x) ASSERT((x) >= 0) /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC wlan_obj_t wlan_obj = { .mode = -1, .status = 0, .ip = 0, .auth = MICROPY_PORT_WLAN_AP_SECURITY, .channel = MICROPY_PORT_WLAN_AP_CHANNEL, .ssid = MICROPY_PORT_WLAN_AP_SSID, .key = MICROPY_PORT_WLAN_AP_KEY, .mac = {0}, //.ssid_o = {0}, //.bssid = {0}, #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) .servers_enabled = false, #endif }; STATIC const mp_irq_methods_t wlan_irq_methods; /****************************************************************************** DECLARE PUBLIC DATA ******************************************************************************/ #ifdef SL_PLATFORM_MULTI_THREADED OsiLockObj_t wlan_LockObj; #endif /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void wlan_clear_data (void); STATIC void wlan_reenable (SlWlanMode_t mode); STATIC void wlan_servers_start (void); STATIC void wlan_servers_stop (void); STATIC void wlan_reset (void); STATIC void wlan_validate_mode (uint mode); STATIC void wlan_set_mode (uint mode); STATIC void wlan_validate_ssid_len (uint32_t len); STATIC void wlan_set_ssid (const char *ssid, uint8_t len, bool add_mac); STATIC void wlan_validate_security (uint8_t auth, const char *key, uint8_t len); STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len); STATIC void wlan_validate_channel (uint8_t channel); STATIC void wlan_set_channel (uint8_t channel); #if MICROPY_HW_ANTENNA_DIVERSITY STATIC void wlan_validate_antenna (uint8_t antenna); STATIC void wlan_set_antenna (uint8_t antenna); #endif STATIC void wlan_sl_disconnect (void); STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec, const char* key, uint32_t key_len, int32_t timeout); STATIC void wlan_get_sl_mac (void); STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out); STATIC void wlan_lpds_irq_enable (mp_obj_t self_in); STATIC void wlan_lpds_irq_disable (mp_obj_t self_in); STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid); //***************************************************************************** // //! \brief The Function Handles WLAN Events //! //! \param[in] pWlanEvent - Pointer to WLAN Event Info //! //! \return None //! //***************************************************************************** void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) { if (!pWlanEvent) { return; } switch(pWlanEvent->Event) { case SL_WLAN_CONNECT_EVENT: { //slWlanConnectAsyncResponse_t *pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected; // copy the new connection data //memcpy(wlan_obj.bssid, pEventData->bssid, SL_BSSID_LENGTH); //memcpy(wlan_obj.ssid_o, pEventData->ssid_name, pEventData->ssid_len); //wlan_obj.ssid_o[pEventData->ssid_len] = '\0'; SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) // we must reset the servers in case that the last connection // was lost without any notification being received servers_reset(); #endif } break; case SL_WLAN_DISCONNECT_EVENT: CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED); #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) servers_reset(); servers_wlan_cycle_power(); #endif break; case SL_WLAN_STA_CONNECTED_EVENT: { //slPeerInfoAsyncResponse_t *pEventData = &pWlanEvent->EventData.APModeStaConnected; // get the mac address and name of the connected device //memcpy(wlan_obj.bssid, pEventData->mac, SL_BSSID_LENGTH); //memcpy(wlan_obj.ssid_o, pEventData->go_peer_device_name, pEventData->go_peer_device_name_len); //wlan_obj.ssid_o[pEventData->go_peer_device_name_len] = '\0'; SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) // we must reset the servers in case that the last connection // was lost without any notification being received servers_reset(); #endif } break; case SL_WLAN_STA_DISCONNECTED_EVENT: CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) servers_reset(); servers_wlan_cycle_power(); #endif break; case SL_WLAN_P2P_DEV_FOUND_EVENT: // TODO break; case SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT: // TODO break; case SL_WLAN_CONNECTION_FAILED_EVENT: // TODO break; default: break; } } //***************************************************************************** // //! \brief This function handles network events such as IP acquisition, IP //! leased, IP released etc. //! //! \param[in] pNetAppEvent - Pointer to NetApp Event Info //! //! \return None //! //***************************************************************************** void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent) { if(!pNetAppEvent) { return; } switch(pNetAppEvent->Event) { case SL_NETAPP_IPV4_IPACQUIRED_EVENT: { SlIpV4AcquiredAsync_t *pEventData = NULL; SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED); // Ip Acquired Event Data pEventData = &pNetAppEvent->EventData.ipAcquiredV4; // Get the ip wlan_obj.ip = pEventData->ip; } break; case SL_NETAPP_IPV6_IPACQUIRED_EVENT: break; case SL_NETAPP_IP_LEASED_EVENT: break; case SL_NETAPP_IP_RELEASED_EVENT: break; default: break; } } //***************************************************************************** // //! \brief This function handles HTTP server events //! //! \param[in] pServerEvent - Contains the relevant event information //! \param[in] pServerResponse - Should be filled by the user with the //! relevant response information //! //! \return None //! //**************************************************************************** void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent, SlHttpServerResponse_t *pHttpResponse) { if (!pHttpEvent) { return; } switch (pHttpEvent->Event) { case SL_NETAPP_HTTPGETTOKENVALUE_EVENT: break; case SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT: break; default: break; } } //***************************************************************************** // //! \brief This function handles General Events //! //! \param[in] pDevEvent - Pointer to General Event Info //! //! \return None //! //***************************************************************************** void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent) { if (!pDevEvent) { return; } } //***************************************************************************** // //! This function handles socket events indication //! //! \param[in] pSock - Pointer to Socket Event Info //! //! \return None //! //***************************************************************************** void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) { if (!pSock) { return; } switch( pSock->Event ) { case SL_SOCKET_TX_FAILED_EVENT: switch( pSock->socketAsyncEvent.SockTxFailData.status) { case SL_ECLOSE: break; default: break; } break; case SL_SOCKET_ASYNC_EVENT: switch(pSock->socketAsyncEvent.SockAsyncData.type) { case SSL_ACCEPT: break; case RX_FRAGMENTATION_TOO_BIG: break; case OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED: break; default: break; } break; default: break; } } //***************************************************************************** // SimpleLink Asynchronous Event Handlers -- End //***************************************************************************** __attribute__ ((section (".boot"))) void wlan_pre_init (void) { // create the wlan lock #ifdef SL_PLATFORM_MULTI_THREADED ASSERT(OSI_OK == sl_LockObjCreate(&wlan_LockObj, "WlanLock")); #endif } void wlan_first_start (void) { if (wlan_obj.mode < 0) { CLR_STATUS_BIT_ALL(wlan_obj.status); wlan_obj.mode = sl_Start(0, 0, 0); #ifdef SL_PLATFORM_MULTI_THREADED sl_LockObjUnlock (&wlan_LockObj); #endif } // get the mac address wlan_get_sl_mac(); } void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth, const char *key, uint8_t key_len, uint8_t channel, uint8_t antenna, bool add_mac) { // stop the servers wlan_servers_stop(); // do a basic start wlan_first_start(); // close any active connections wlan_sl_disconnect(); // Remove all profiles ASSERT_ON_ERROR(sl_WlanProfileDel(0xFF)); // Enable the DHCP client uint8_t value = 1; ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE, 1, 1, &value)); // Set PM policy to normal ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_PM, SL_NORMAL_POLICY, NULL, 0)); // Unregister mDNS services ASSERT_ON_ERROR(sl_NetAppMDNSUnRegisterService(0, 0)); // Stop the internal HTTP server sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); // Remove all 64 filters (8 * 8) _WlanRxFilterOperationCommandBuff_t RxFilterIdMask; memset ((void *)&RxFilterIdMask, 0 ,sizeof(RxFilterIdMask)); memset(RxFilterIdMask.FilterIdMask, 0xFF, 8); ASSERT_ON_ERROR(sl_WlanRxFilterSet(SL_REMOVE_RX_FILTER, (_u8 *)&RxFilterIdMask, sizeof(_WlanRxFilterOperationCommandBuff_t))); #if MICROPY_HW_ANTENNA_DIVERSITY // set the antenna type wlan_set_antenna (antenna); #endif // switch to the requested mode wlan_set_mode(mode); // stop and start again (we need to in the propper mode from now on) wlan_reenable(mode); // Set Tx power level for station or AP mode // Number between 0-15, as dB offset from max power - 0 will set max power uint8_t ucPower = 0; if (mode == ROLE_AP) { ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_AP_TX_POWER, sizeof(ucPower), (unsigned char *)&ucPower)); // configure all parameters wlan_set_ssid (ssid, ssid_len, add_mac); wlan_set_security (auth, key, key_len); wlan_set_channel (channel); // set the country _u8* country = (_u8*)"EU"; ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, country)); SlNetCfgIpV4Args_t ipV4; ipV4.ipV4 = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 IP address ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 Default gateway address ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 DNS server address ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); SlNetAppDhcpServerBasicOpt_t dhcpParams; dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address dhcpParams.ipv4_addr_start = SL_IPV4_VAL(192,168,1,2); // first IP Address for allocation. dhcpParams.ipv4_addr_last = SL_IPV4_VAL(192,168,1,254); // last IP Address for allocation. ASSERT_ON_ERROR(sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID)); // Stop DHCP server before settings ASSERT_ON_ERROR(sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // Start DHCP server with new settings // stop and start again wlan_reenable(mode); } else { // STA and P2P modes ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, sizeof(ucPower), (unsigned char *)&ucPower)); // set connection policy to Auto + Fast (tries to connect to the last connected AP) ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 1, 0, 0, 0), NULL, 0)); } // set current time and date (needed to validate certificates) wlan_set_current_time (pyb_rtc_get_seconds()); // start the servers before returning wlan_servers_start(); } void wlan_update(void) { #ifndef SL_PLATFORM_MULTI_THREADED _SlTaskEntry(); #endif } void wlan_stop (uint32_t timeout) { wlan_servers_stop(); #ifdef SL_PLATFORM_MULTI_THREADED sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); #endif sl_Stop(timeout); wlan_clear_data(); wlan_obj.mode = -1; } void wlan_get_mac (uint8_t *macAddress) { if (macAddress) { memcpy (macAddress, wlan_obj.mac, SL_MAC_ADDR_LEN); } } void wlan_get_ip (uint32_t *ip) { if (ip) { *ip = IS_IP_ACQUIRED(wlan_obj.status) ? wlan_obj.ip : 0; } } bool wlan_is_connected (void) { return (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION) && (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED) || wlan_obj.mode != ROLE_STA)); } void wlan_set_current_time (uint32_t seconds_since_2000) { timeutils_struct_time_t tm; timeutils_seconds_since_2000_to_struct_time(seconds_since_2000, &tm); SlDateTime_t sl_datetime = {0}; sl_datetime.sl_tm_day = tm.tm_mday; sl_datetime.sl_tm_mon = tm.tm_mon; sl_datetime.sl_tm_year = tm.tm_year; sl_datetime.sl_tm_hour = tm.tm_hour; sl_datetime.sl_tm_min = tm.tm_min; sl_datetime.sl_tm_sec = tm.tm_sec; sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, sizeof(SlDateTime_t), (_u8 *)(&sl_datetime)); } void wlan_off_on (void) { // no need to lock the WLAN object on every API call since the servers and the MicroPtyhon // task have the same priority wlan_reenable(wlan_obj.mode); } //***************************************************************************** // DEFINE STATIC FUNCTIONS //***************************************************************************** STATIC void wlan_clear_data (void) { CLR_STATUS_BIT_ALL(wlan_obj.status); wlan_obj.ip = 0; //memset(wlan_obj.ssid_o, 0, sizeof(wlan_obj.ssid)); //memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid)); } STATIC void wlan_reenable (SlWlanMode_t mode) { // stop and start again #ifdef SL_PLATFORM_MULTI_THREADED sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); #endif sl_Stop(SL_STOP_TIMEOUT); wlan_clear_data(); wlan_obj.mode = sl_Start(0, 0, 0); #ifdef SL_PLATFORM_MULTI_THREADED sl_LockObjUnlock (&wlan_LockObj); #endif ASSERT (wlan_obj.mode == mode); } STATIC void wlan_servers_start (void) { #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) // start the servers if they were enabled before if (wlan_obj.servers_enabled) { servers_start(); } #endif } STATIC void wlan_servers_stop (void) { #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) // Stop all other processes using the wlan engine if ((wlan_obj.servers_enabled = servers_are_enabled())) { servers_stop(); } #endif } STATIC void wlan_reset (void) { wlan_servers_stop(); wlan_reenable (wlan_obj.mode); wlan_servers_start(); } STATIC void wlan_validate_mode (uint mode) { if (mode != ROLE_STA && mode != ROLE_AP) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void wlan_set_mode (uint mode) { wlan_obj.mode = mode; ASSERT_ON_ERROR(sl_WlanSetMode(mode)); } STATIC void wlan_validate_ssid_len (uint32_t len) { if (len > MODWLAN_SSID_LEN_MAX) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void wlan_set_ssid (const char *ssid, uint8_t len, bool add_mac) { if (ssid != NULL) { // save the ssid memcpy(&wlan_obj.ssid, ssid, len); // append the last 2 bytes of the MAC address, since the use of this functionality is under our control // we can assume that the lenght of the ssid is less than (32 - 5) if (add_mac) { snprintf((char *)&wlan_obj.ssid[len], sizeof(wlan_obj.ssid) - len, "-%02x%02x", wlan_obj.mac[4], wlan_obj.mac[5]); len += 5; } wlan_obj.ssid[len] = '\0'; ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID, len, (unsigned char *)wlan_obj.ssid)); } } STATIC void wlan_validate_security (uint8_t auth, const char *key, uint8_t len) { if (auth != SL_SEC_TYPE_WEP && auth != SL_SEC_TYPE_WPA_WPA2) { goto invalid_args; } if (auth == SL_SEC_TYPE_WEP) { for (mp_uint_t i = strlen(key); i > 0; i--) { if (!unichar_isxdigit(*key++)) { goto invalid_args; } } } return; invalid_args: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) { wlan_obj.auth = auth; ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SECURITY_TYPE, sizeof(uint8_t), &auth)); if (key != NULL) { memcpy(&wlan_obj.key, key, len); wlan_obj.key[len] = '\0'; if (auth == SL_SEC_TYPE_WEP) { _u8 wep_key[32]; wlan_wep_key_unhexlify(key, (char *)&wep_key); key = (const char *)&wep_key; len /= 2; } ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, len, (unsigned char *)key)); } else { wlan_obj.key[0] = '\0'; } } STATIC void wlan_validate_channel (uint8_t channel) { if (channel < 1 || channel > 11) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void wlan_set_channel (uint8_t channel) { wlan_obj.channel = channel; ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_CHANNEL, 1, &channel)); } #if MICROPY_HW_ANTENNA_DIVERSITY STATIC void wlan_validate_antenna (uint8_t antenna) { if (antenna != ANTENNA_TYPE_INTERNAL && antenna != ANTENNA_TYPE_EXTERNAL) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void wlan_set_antenna (uint8_t antenna) { wlan_obj.antenna = antenna; antenna_select(antenna); } #endif STATIC void wlan_sl_disconnect (void) { // Device in station-mode. Disconnect previous connection if any // The function returns 0 if 'Disconnected done', negative number if already // disconnected Wait for 'disconnection' event if 0 is returned, Ignore // other return-codes if (0 == sl_WlanDisconnect()) { while (IS_CONNECTED(wlan_obj.status)) { mp_hal_delay_ms(MODWLAN_CONNECTION_WAIT_MS); wlan_update(); } } } STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec, const char* key, uint32_t key_len, int32_t timeout) { SlSecParams_t secParams; secParams.Key = (_i8*)key; secParams.KeyLen = ((key != NULL) ? key_len : 0); secParams.Type = sec; // first close any active connections wlan_sl_disconnect(); if (!sl_WlanConnect((_i8*)ssid, ssid_len, (_u8*)bssid, &secParams, NULL)) { // wait for the WLAN Event uint32_t waitForConnectionMs = 0; while (timeout && !IS_CONNECTED(wlan_obj.status)) { mp_hal_delay_ms(MODWLAN_CONNECTION_WAIT_MS); waitForConnectionMs += MODWLAN_CONNECTION_WAIT_MS; if (timeout > 0 && waitForConnectionMs > timeout) { return MODWLAN_ERROR_TIMEOUT; } wlan_update(); } return MODWLAN_OK; } return MODWLAN_ERROR_INVALID_PARAMS; } STATIC void wlan_get_sl_mac (void) { // Get the MAC address uint8_t macAddrLen = SL_MAC_ADDR_LEN; sl_NetCfgGet(SL_MAC_ADDRESS_GET, NULL, &macAddrLen, wlan_obj.mac); } STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out) { byte hex_byte = 0; for (mp_uint_t i = strlen(key); i > 0 ; i--) { hex_byte += unichar_xdigit_value(*key++); if (i & 1) { hex_byte <<= 4; } else { *key_out++ = hex_byte; hex_byte = 0; } } } STATIC void wlan_lpds_irq_enable (mp_obj_t self_in) { wlan_obj_t *self = self_in; self->irq_enabled = true; } STATIC void wlan_lpds_irq_disable (mp_obj_t self_in) { wlan_obj_t *self = self_in; self->irq_enabled = false; } STATIC int wlan_irq_flags (mp_obj_t self_in) { wlan_obj_t *self = self_in; return self->irq_flags; } STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid) { for (int i = 0; i < nets->len; i++) { // index 1 in the list is the bssid mp_obj_str_t *_bssid = (mp_obj_str_t *)((mp_obj_tuple_t *)nets->items[i])->items[1]; if (!memcmp (_bssid->data, bssid, SL_BSSID_LENGTH)) { return false; } } return true; } /******************************************************************************/ // MicroPython bindings; WLAN class /// \class WLAN - WiFi driver STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) { // get the mode int8_t mode = args[0].u_int; wlan_validate_mode(mode); // get the ssid size_t ssid_len = 0; const char *ssid = NULL; if (args[1].u_obj != NULL) { ssid = mp_obj_str_get_data(args[1].u_obj, &ssid_len); wlan_validate_ssid_len(ssid_len); } // get the auth config uint8_t auth = SL_SEC_TYPE_OPEN; size_t key_len = 0; const char *key = NULL; if (args[2].u_obj != mp_const_none) { mp_obj_t *sec; mp_obj_get_array_fixed_n(args[2].u_obj, 2, &sec); auth = mp_obj_get_int(sec[0]); key = mp_obj_str_get_data(sec[1], &key_len); wlan_validate_security(auth, key, key_len); } // get the channel uint8_t channel = args[3].u_int; wlan_validate_channel(channel); // get the antenna type uint8_t antenna = 0; #if MICROPY_HW_ANTENNA_DIVERSITY antenna = args[4].u_int; wlan_validate_antenna(antenna); #endif // initialize the wlan subsystem wlan_sl_init(mode, (const char *)ssid, ssid_len, auth, (const char *)key, key_len, channel, antenna, false); return mp_const_none; } STATIC const mp_arg_t wlan_init_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_mode, MP_ARG_INT, {.u_int = ROLE_STA} }, { MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, #if MICROPY_HW_ANTENNA_DIVERSITY { MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} }, #endif }; STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); mp_arg_val_t args[MP_ARRAY_SIZE(wlan_init_args)]; mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), wlan_init_args, args); // setup the object wlan_obj_t *self = &wlan_obj; self->base.type = (mp_obj_t)&mod_network_nic_type_wlan; // give it to the sleep module pyb_sleep_set_wlan_obj(self); if (n_args > 1 || n_kw > 0) { // check the peripheral id if (args[0].u_int != 0) { mp_raise_OSError(MP_ENODEV); } // start the peripheral wlan_init_helper(self, &args[1]); } return (mp_obj_t)self; } STATIC mp_obj_t wlan_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(wlan_init_args) - 1]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &wlan_init_args[1], args); return wlan_init_helper(pos_args[0], args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_init_obj, 1, wlan_init); STATIC mp_obj_t wlan_scan(mp_obj_t self_in) { STATIC const qstr wlan_scan_info_fields[] = { MP_QSTR_ssid, MP_QSTR_bssid, MP_QSTR_sec, MP_QSTR_channel, MP_QSTR_rssi }; // check for correct wlan mode if (wlan_obj.mode == ROLE_AP) { mp_raise_OSError(MP_EPERM); } Sl_WlanNetworkEntry_t wlanEntry; mp_obj_t nets = mp_obj_new_list(0, NULL); uint8_t _index = 0; // trigger a new network scan uint32_t scanSeconds = MODWLAN_SCAN_PERIOD_S; ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_SCAN , MODWLAN_SL_SCAN_ENABLE, (_u8 *)&scanSeconds, sizeof(scanSeconds))); // wait for the scan to complete mp_hal_delay_ms(MODWLAN_WAIT_FOR_SCAN_MS); do { if (sl_WlanGetNetworkList(_index++, 1, &wlanEntry) <= 0) { break; } // we must skip any duplicated results if (!wlan_scan_result_is_unique(nets, wlanEntry.bssid)) { continue; } mp_obj_t tuple[5]; tuple[0] = mp_obj_new_str((const char *)wlanEntry.ssid, wlanEntry.ssid_len); tuple[1] = mp_obj_new_bytes((const byte *)wlanEntry.bssid, SL_BSSID_LENGTH); // 'normalize' the security type if (wlanEntry.sec_type > 2) { wlanEntry.sec_type = 2; } tuple[2] = mp_obj_new_int(wlanEntry.sec_type); tuple[3] = mp_const_none; tuple[4] = mp_obj_new_int(wlanEntry.rssi); // add the network to the list mp_obj_list_append(nets, mp_obj_new_attrtuple(wlan_scan_info_fields, 5, tuple)); } while (_index < MODWLAN_SL_MAX_NETWORKS); return nets; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_scan_obj, wlan_scan); STATIC mp_obj_t wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t allowed_args[] = { { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_auth, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // check for the correct wlan mode if (wlan_obj.mode == ROLE_AP) { mp_raise_OSError(MP_EPERM); } // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the ssid size_t ssid_len; const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len); wlan_validate_ssid_len(ssid_len); // get the auth config uint8_t auth = SL_SEC_TYPE_OPEN; size_t key_len = 0; const char *key = NULL; if (args[1].u_obj != mp_const_none) { mp_obj_t *sec; mp_obj_get_array_fixed_n(args[1].u_obj, 2, &sec); auth = mp_obj_get_int(sec[0]); key = mp_obj_str_get_data(sec[1], &key_len); wlan_validate_security(auth, key, key_len); // convert the wep key if needed if (auth == SL_SEC_TYPE_WEP) { _u8 wep_key[32]; wlan_wep_key_unhexlify(key, (char *)&wep_key); key = (const char *)&wep_key; key_len /= 2; } } // get the bssid const char *bssid = NULL; if (args[2].u_obj != mp_const_none) { bssid = mp_obj_str_get_str(args[2].u_obj); } // get the timeout int32_t timeout = -1; if (args[3].u_obj != mp_const_none) { timeout = mp_obj_get_int(args[3].u_obj); } // connect to the requested access point modwlan_Status_t status; status = wlan_do_connect (ssid, ssid_len, bssid, auth, key, key_len, timeout); if (status == MODWLAN_ERROR_TIMEOUT) { mp_raise_OSError(MP_ETIMEDOUT); } else if (status == MODWLAN_ERROR_INVALID_PARAMS) { mp_raise_ValueError(mpexception_value_invalid_arguments); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_connect_obj, 1, wlan_connect); STATIC mp_obj_t wlan_disconnect(mp_obj_t self_in) { wlan_sl_disconnect(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_disconnect_obj, wlan_disconnect); STATIC mp_obj_t wlan_isconnected(mp_obj_t self_in) { return wlan_is_connected() ? mp_const_true : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_isconnected_obj, wlan_isconnected); STATIC mp_obj_t wlan_ifconfig(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t wlan_ifconfig_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_config, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(wlan_ifconfig_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), wlan_ifconfig_args, args); // check the interface id if (args[0].u_int != 0) { mp_raise_OSError(MP_EPERM); } // get the configuration if (args[1].u_obj == MP_OBJ_NULL) { // get unsigned char len = sizeof(SlNetCfgIpV4Args_t); unsigned char dhcpIsOn; SlNetCfgIpV4Args_t ipV4; sl_NetCfgGet(SL_IPV4_STA_P2P_CL_GET_INFO, &dhcpIsOn, &len, (uint8_t *)&ipV4); mp_obj_t ifconfig[4] = { netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4, NETUTILS_LITTLE), netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4Mask, NETUTILS_LITTLE), netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4Gateway, NETUTILS_LITTLE), netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4DnsServer, NETUTILS_LITTLE) }; return mp_obj_new_tuple(4, ifconfig); } else { // set the configuration if (mp_obj_is_type(args[1].u_obj, &mp_type_tuple)) { // set a static ip mp_obj_t *items; mp_obj_get_array_fixed_n(args[1].u_obj, 4, &items); SlNetCfgIpV4Args_t ipV4; netutils_parse_ipv4_addr(items[0], (uint8_t *)&ipV4.ipV4, NETUTILS_LITTLE); netutils_parse_ipv4_addr(items[1], (uint8_t *)&ipV4.ipV4Mask, NETUTILS_LITTLE); netutils_parse_ipv4_addr(items[2], (uint8_t *)&ipV4.ipV4Gateway, NETUTILS_LITTLE); netutils_parse_ipv4_addr(items[3], (uint8_t *)&ipV4.ipV4DnsServer, NETUTILS_LITTLE); if (wlan_obj.mode == ROLE_AP) { ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); SlNetAppDhcpServerBasicOpt_t dhcpParams; dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address dhcpParams.ipv4_addr_start = ipV4.ipV4 + 1; // first IP Address for allocation. dhcpParams.ipv4_addr_last = (ipV4.ipV4 & 0xFFFFFF00) + 254; // last IP Address for allocation. ASSERT_ON_ERROR(sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID)); // stop DHCP server before settings ASSERT_ON_ERROR(sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // start DHCP server with new settings } else { ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_STA_P2P_CL_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); } } else { // check for the correct string const char *mode = mp_obj_str_get_str(args[1].u_obj); if (strcmp("dhcp", mode)) { mp_raise_ValueError(mpexception_value_invalid_arguments); } // only if we are not in AP mode if (wlan_obj.mode != ROLE_AP) { _u8 val = 1; sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, 1, &val); } } // config values have changed, so reset wlan_reset(); // set current time and date (needed to validate certificates) wlan_set_current_time (pyb_rtc_get_seconds()); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_ifconfig_obj, 1, wlan_ifconfig); STATIC mp_obj_t wlan_mode(size_t n_args, const mp_obj_t *args) { wlan_obj_t *self = args[0]; if (n_args == 1) { return mp_obj_new_int(self->mode); } else { uint mode = mp_obj_get_int(args[1]); wlan_validate_mode(mode); wlan_set_mode(mode); wlan_reset(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_mode_obj, 1, 2, wlan_mode); STATIC mp_obj_t wlan_ssid(size_t n_args, const mp_obj_t *args) { wlan_obj_t *self = args[0]; if (n_args == 1) { return mp_obj_new_str((const char *)self->ssid, strlen((const char *)self->ssid)); } else { size_t len; const char *ssid = mp_obj_str_get_data(args[1], &len); wlan_validate_ssid_len(len); wlan_set_ssid(ssid, len, false); wlan_reset(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_ssid_obj, 1, 2, wlan_ssid); STATIC mp_obj_t wlan_auth(size_t n_args, const mp_obj_t *args) { wlan_obj_t *self = args[0]; if (n_args == 1) { if (self->auth == SL_SEC_TYPE_OPEN) { return mp_const_none; } else { mp_obj_t security[2]; security[0] = mp_obj_new_int(self->auth); security[1] = mp_obj_new_str((const char *)self->key, strlen((const char *)self->key)); return mp_obj_new_tuple(2, security); } } else { // get the auth config uint8_t auth = SL_SEC_TYPE_OPEN; size_t key_len = 0; const char *key = NULL; if (args[1] != mp_const_none) { mp_obj_t *sec; mp_obj_get_array_fixed_n(args[1], 2, &sec); auth = mp_obj_get_int(sec[0]); key = mp_obj_str_get_data(sec[1], &key_len); wlan_validate_security(auth, key, key_len); } wlan_set_security(auth, key, key_len); wlan_reset(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_auth_obj, 1, 2, wlan_auth); STATIC mp_obj_t wlan_channel(size_t n_args, const mp_obj_t *args) { wlan_obj_t *self = args[0]; if (n_args == 1) { return mp_obj_new_int(self->channel); } else { uint8_t channel = mp_obj_get_int(args[1]); wlan_validate_channel(channel); wlan_set_channel(channel); wlan_reset(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_channel_obj, 1, 2, wlan_channel); STATIC mp_obj_t wlan_antenna(size_t n_args, const mp_obj_t *args) { wlan_obj_t *self = args[0]; if (n_args == 1) { return mp_obj_new_int(self->antenna); } else { #if MICROPY_HW_ANTENNA_DIVERSITY uint8_t antenna = mp_obj_get_int(args[1]); wlan_validate_antenna(antenna); wlan_set_antenna(antenna); #endif return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_antenna_obj, 1, 2, wlan_antenna); STATIC mp_obj_t wlan_mac(size_t n_args, const mp_obj_t *args) { wlan_obj_t *self = args[0]; if (n_args == 1) { return mp_obj_new_bytes((const byte *)self->mac, SL_BSSID_LENGTH); } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); if (bufinfo.len != 6) { mp_raise_ValueError(mpexception_value_invalid_arguments); } memcpy(self->mac, bufinfo.buf, SL_MAC_ADDR_LEN); sl_NetCfgSet(SL_MAC_ADDRESS_SET, 1, SL_MAC_ADDR_LEN, (_u8 *)self->mac); wlan_reset(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_mac_obj, 1, 2, wlan_mac); STATIC mp_obj_t wlan_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); wlan_obj_t *self = pos_args[0]; // check the trigger, only one type is supported if (mp_obj_get_int(args[0].u_obj) != MODWLAN_WIFI_EVENT_ANY) { goto invalid_args; } // check the power mode if (mp_obj_get_int(args[3].u_obj) != PYB_PWR_MODE_LPDS) { goto invalid_args; } // create the callback mp_obj_t _irq = mp_irq_new (self, args[2].u_obj, &wlan_irq_methods); self->irq_obj = _irq; // enable the irq just before leaving wlan_lpds_irq_enable(self); return _irq; invalid_args: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq); //STATIC mp_obj_t wlan_connections (mp_obj_t self_in) { // mp_obj_t device[2]; // mp_obj_t connections = mp_obj_new_list(0, NULL); // // if (wlan_is_connected()) { // device[0] = mp_obj_new_str((const char *)wlan_obj.ssid_o, strlen((const char *)wlan_obj.ssid_o)); // device[1] = mp_obj_new_bytes((const byte *)wlan_obj.bssid, SL_BSSID_LENGTH); // // add the device to the list // mp_obj_list_append(connections, mp_obj_new_tuple(MP_ARRAY_SIZE(device), device)); // } // return connections; //} //STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_connections_obj, wlan_connections); //STATIC mp_obj_t wlan_urn (uint n_args, const mp_obj_t *args) { // char urn[MAX_DEVICE_URN_LEN]; // uint8_t len = MAX_DEVICE_URN_LEN; // // // an URN is given, so set it // if (n_args == 2) { // const char *p = mp_obj_str_get_str(args[1]); // uint8_t len = strlen(p); // // // the call to sl_NetAppSet corrupts the input string URN=args[1], so we copy into a local buffer // if (len > MAX_DEVICE_URN_LEN) { // mp_raise_ValueError(mpexception_value_invalid_arguments); // } // strcpy(urn, p); // // if (sl_NetAppSet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, len, (unsigned char *)urn) < 0) { // mp_raise_OSError(MP_EIO); // } // } // else { // // get the URN // if (sl_NetAppGet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, &len, (uint8_t *)urn) < 0) { // mp_raise_OSError(MP_EIO); // } // return mp_obj_new_str(urn, (len - 1)); // } // // return mp_const_none; //} //STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_urn_obj, 1, 2, wlan_urn); STATIC mp_obj_t wlan_print_ver(void) { SlVersionFull ver; byte config_opt = SL_DEVICE_GENERAL_VERSION; byte config_len = sizeof(ver); sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &config_opt, &config_len, (byte*)&ver); printf("NWP: %d.%d.%d.%d\n", (int)ver.NwpVersion[0], (int)ver.NwpVersion[1], (int)ver.NwpVersion[2], (int)ver.NwpVersion[3]); printf("MAC: %d.%d.%d.%d\n", (int)ver.ChipFwAndPhyVersion.FwVersion[0], (int)ver.ChipFwAndPhyVersion.FwVersion[1], (int)ver.ChipFwAndPhyVersion.FwVersion[2], (int)ver.ChipFwAndPhyVersion.FwVersion[3]); printf("PHY: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.PhyVersion[0], ver.ChipFwAndPhyVersion.PhyVersion[1], ver.ChipFwAndPhyVersion.PhyVersion[2], ver.ChipFwAndPhyVersion.PhyVersion[3]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(wlan_print_ver_fun_obj, wlan_print_ver); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(wlan_print_ver_obj, MP_ROM_PTR(&wlan_print_ver_fun_obj)); STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&wlan_init_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&wlan_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&wlan_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&wlan_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wlan_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wlan_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&wlan_mode_obj) }, { MP_ROM_QSTR(MP_QSTR_ssid), MP_ROM_PTR(&wlan_ssid_obj) }, { MP_ROM_QSTR(MP_QSTR_auth), MP_ROM_PTR(&wlan_auth_obj) }, { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wlan_channel_obj) }, { MP_ROM_QSTR(MP_QSTR_antenna), MP_ROM_PTR(&wlan_antenna_obj) }, { MP_ROM_QSTR(MP_QSTR_mac), MP_ROM_PTR(&wlan_mac_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&wlan_irq_obj) }, //{ MP_ROM_QSTR(MP_QSTR_connections), MP_ROM_PTR(&wlan_connections_obj) }, //{ MP_ROM_QSTR(MP_QSTR_urn), MP_ROM_PTR(&wlan_urn_obj) }, { MP_ROM_QSTR(MP_QSTR_print_ver), MP_ROM_PTR(&wlan_print_ver_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_STA), MP_ROM_INT(ROLE_STA) }, { MP_ROM_QSTR(MP_QSTR_AP), MP_ROM_INT(ROLE_AP) }, { MP_ROM_QSTR(MP_QSTR_WEP), MP_ROM_INT(SL_SEC_TYPE_WEP) }, { MP_ROM_QSTR(MP_QSTR_WPA), MP_ROM_INT(SL_SEC_TYPE_WPA_WPA2) }, { MP_ROM_QSTR(MP_QSTR_WPA2), MP_ROM_INT(SL_SEC_TYPE_WPA_WPA2) }, #if MICROPY_HW_ANTENNA_DIVERSITY { MP_ROM_QSTR(MP_QSTR_INT_ANT), MP_ROM_INT(ANTENNA_TYPE_INTERNAL) }, { MP_ROM_QSTR(MP_QSTR_EXT_ANT), MP_ROM_INT(ANTENNA_TYPE_EXTERNAL) }, #endif { MP_ROM_QSTR(MP_QSTR_ANY_EVENT), MP_ROM_INT(MODWLAN_WIFI_EVENT_ANY) }, }; STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table); const mod_network_nic_type_t mod_network_nic_type_wlan = { .base = { { &mp_type_type }, .name = MP_QSTR_WLAN, .make_new = wlan_make_new, .locals_dict = (mp_obj_t)&wlan_locals_dict, }, }; STATIC const mp_irq_methods_t wlan_irq_methods = { .init = wlan_irq, .enable = wlan_lpds_irq_enable, .disable = wlan_lpds_irq_disable, .flags = wlan_irq_flags, }; micropython-1.12/ports/cc3200/mods/modwlan.h000066400000000000000000000075611357706137100206500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H #define MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define SIMPLELINK_SPAWN_TASK_PRIORITY 3 #define SIMPLELINK_TASK_STACK_SIZE 2048 #define SL_STOP_TIMEOUT 35 #define SL_STOP_TIMEOUT_LONG 575 #define MODWLAN_WIFI_EVENT_ANY 0x01 #define MODWLAN_SSID_LEN_MAX 32 /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef enum { MODWLAN_OK = 0, MODWLAN_ERROR_INVALID_PARAMS = -1, MODWLAN_ERROR_TIMEOUT = -2, MODWLAN_ERROR_UNKNOWN = -3, } modwlan_Status_t; typedef struct _wlan_obj_t { mp_obj_base_t base; mp_obj_t irq_obj; uint32_t status; uint32_t ip; int8_t mode; uint8_t auth; uint8_t channel; uint8_t antenna; // my own ssid, key and mac uint8_t ssid[(MODWLAN_SSID_LEN_MAX + 1)]; uint8_t key[65]; uint8_t mac[SL_MAC_ADDR_LEN]; // the sssid (or name) and mac of the other device uint8_t ssid_o[33]; uint8_t bssid[6]; uint8_t irq_flags; bool irq_enabled; #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) bool servers_enabled; #endif } wlan_obj_t; /****************************************************************************** DECLARE PUBLIC DATA ******************************************************************************/ extern _SlLockObj_t wlan_LockObj; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ extern void wlan_pre_init (void); extern void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth, const char *key, uint8_t key_len, uint8_t channel, uint8_t antenna, bool add_mac); extern void wlan_first_start (void); extern void wlan_update(void); extern void wlan_stop (uint32_t timeout); extern void wlan_get_mac (uint8_t *macAddress); extern void wlan_get_ip (uint32_t *ip); extern bool wlan_is_connected (void); extern void wlan_set_current_time (uint32_t seconds_since_2000); extern void wlan_off_on (void); #endif // MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H micropython-1.12/ports/cc3200/mods/pybadc.c000066400000000000000000000261611357706137100204410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/binary.h" #include "py/gc.h" #include "py/mperrno.h" #include "bufhelper.h" #include "inc/hw_types.h" #include "inc/hw_adc.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "interrupt.h" #include "pin.h" #include "gpio.h" #include "prcm.h" #include "adc.h" #include "pybadc.h" #include "pybpin.h" #include "pybsleep.h" #include "pins.h" #include "mpexception.h" /****************************************************************************** DECLARE CONSTANTS ******************************************************************************/ #define PYB_ADC_NUM_CHANNELS 4 /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef struct { mp_obj_base_t base; bool enabled; } pyb_adc_obj_t; typedef struct { mp_obj_base_t base; pin_obj_t *pin; byte channel; byte id; bool enabled; } pyb_adc_channel_obj_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC pyb_adc_channel_obj_t pyb_adc_channel_obj[PYB_ADC_NUM_CHANNELS] = { {.pin = &pin_GP2, .channel = ADC_CH_0, .id = 0, .enabled = false}, {.pin = &pin_GP3, .channel = ADC_CH_1, .id = 1, .enabled = false}, {.pin = &pin_GP4, .channel = ADC_CH_2, .id = 2, .enabled = false}, {.pin = &pin_GP5, .channel = ADC_CH_3, .id = 3, .enabled = false} }; STATIC pyb_adc_obj_t pyb_adc_obj = {.enabled = false}; STATIC const mp_obj_type_t pyb_adc_channel_type; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC mp_obj_t adc_channel_deinit(mp_obj_t self_in); /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ STATIC void pyb_adc_init (pyb_adc_obj_t *self) { // enable and configure the timer MAP_ADCTimerConfig(ADC_BASE, (1 << 17) - 1); MAP_ADCTimerEnable(ADC_BASE); // enable the ADC peripheral MAP_ADCEnable(ADC_BASE); self->enabled = true; } STATIC void pyb_adc_check_init(void) { // not initialized if (!pyb_adc_obj.enabled) { mp_raise_OSError(MP_EPERM); } } STATIC void pyb_adc_channel_init (pyb_adc_channel_obj_t *self) { // the ADC block must be enabled first pyb_adc_check_init(); // configure the pin in analog mode pin_config (self->pin, -1, PIN_TYPE_ANALOG, PIN_TYPE_STD, -1, PIN_STRENGTH_2MA); // enable the ADC channel MAP_ADCChannelEnable(ADC_BASE, self->channel); self->enabled = true; } STATIC void pyb_adc_deinit_all_channels (void) { for (int i = 0; i < PYB_ADC_NUM_CHANNELS; i++) { adc_channel_deinit(&pyb_adc_channel_obj[i]); } } /******************************************************************************/ /* MicroPython bindings : adc object */ STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_adc_obj_t *self = self_in; if (self->enabled) { mp_printf(print, "ADC(0, bits=12)"); } else { mp_printf(print, "ADC(0)"); } } STATIC const mp_arg_t pyb_adc_init_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 12} }, }; STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_init_args)]; mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_adc_init_args, args); // check the peripheral id if (args[0].u_int != 0) { mp_raise_OSError(MP_ENODEV); } // check the number of bits if (args[1].u_int != 12) { mp_raise_ValueError(mpexception_value_invalid_arguments); } // setup the object pyb_adc_obj_t *self = &pyb_adc_obj; self->base.type = &pyb_adc_type; // initialize and register with the sleep module pyb_adc_init(self); pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pyb_adc_init); return self; } STATIC mp_obj_t adc_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_init_args) - 1]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_adc_init_args[1], args); // check the number of bits if (args[0].u_int != 12) { mp_raise_ValueError(mpexception_value_invalid_arguments); } pyb_adc_init(pos_args[0]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adc_init_obj, 1, adc_init); STATIC mp_obj_t adc_deinit(mp_obj_t self_in) { pyb_adc_obj_t *self = self_in; // first deinit all channels pyb_adc_deinit_all_channels(); MAP_ADCDisable(ADC_BASE); self->enabled = false; // unregister it with the sleep module pyb_sleep_remove ((const mp_obj_t)self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_deinit_obj, adc_deinit); STATIC mp_obj_t adc_channel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t pyb_adc_channel_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_channel_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_adc_channel_args, args); uint ch_id; if (args[0].u_obj != MP_OBJ_NULL) { ch_id = mp_obj_get_int(args[0].u_obj); if (ch_id >= PYB_ADC_NUM_CHANNELS) { mp_raise_ValueError(mpexception_value_invalid_arguments); } else if (args[1].u_obj != mp_const_none) { uint pin_ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0); if (ch_id != pin_ch_id) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } } else { ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0); } // setup the object pyb_adc_channel_obj_t *self = &pyb_adc_channel_obj[ch_id]; self->base.type = &pyb_adc_channel_type; pyb_adc_channel_init (self); // register it with the sleep module pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pyb_adc_channel_init); return self; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adc_channel_obj, 1, adc_channel); STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&adc_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&adc_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&adc_channel_obj) }, }; STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table); const mp_obj_type_t pyb_adc_type = { { &mp_type_type }, .name = MP_QSTR_ADC, .print = adc_print, .make_new = adc_make_new, .locals_dict = (mp_obj_t)&adc_locals_dict, }; STATIC void adc_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_adc_channel_obj_t *self = self_in; if (self->enabled) { mp_printf(print, "ADCChannel(%u, pin=%q)", self->id, self->pin->name); } else { mp_printf(print, "ADCChannel(%u)", self->id); } } STATIC mp_obj_t adc_channel_init(mp_obj_t self_in) { pyb_adc_channel_obj_t *self = self_in; // re-enable it pyb_adc_channel_init(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_init_obj, adc_channel_init); STATIC mp_obj_t adc_channel_deinit(mp_obj_t self_in) { pyb_adc_channel_obj_t *self = self_in; MAP_ADCChannelDisable(ADC_BASE, self->channel); // unregister it with the sleep module pyb_sleep_remove ((const mp_obj_t)self); self->enabled = false; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_deinit_obj, adc_channel_deinit); STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) { pyb_adc_channel_obj_t *self = self_in; uint32_t value; // the channel must be enabled if (!self->enabled) { mp_raise_OSError(MP_EPERM); } // wait until a new value is available while (!MAP_ADCFIFOLvlGet(ADC_BASE, self->channel)); // read the sample value = MAP_ADCFIFORead(ADC_BASE, self->channel); // the 12 bit sampled value is stored in bits [13:2] return MP_OBJ_NEW_SMALL_INT((value & 0x3FFF) >> 2); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_value_obj, adc_channel_value); STATIC mp_obj_t adc_channel_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 0, false); return adc_channel_value (self_in); } STATIC const mp_rom_map_elem_t adc_channel_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&adc_channel_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&adc_channel_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&adc_channel_value_obj) }, }; STATIC MP_DEFINE_CONST_DICT(adc_channel_locals_dict, adc_channel_locals_dict_table); STATIC const mp_obj_type_t pyb_adc_channel_type = { { &mp_type_type }, .name = MP_QSTR_ADCChannel, .print = adc_channel_print, .call = adc_channel_call, .locals_dict = (mp_obj_t)&adc_channel_locals_dict, }; micropython-1.12/ports/cc3200/mods/pybadc.h000066400000000000000000000026531357706137100204460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBADC_H #define MICROPY_INCLUDED_CC3200_MODS_PYBADC_H extern const mp_obj_type_t pyb_adc_type; #endif // MICROPY_INCLUDED_CC3200_MODS_PYBADC_H micropython-1.12/ports/cc3200/mods/pybflash.c000066400000000000000000000115031357706137100210010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ //#include //#include #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs_fat.h" #include "fatfs/src/drivers/sflash_diskio.h" #include "mods/pybflash.h" /******************************************************************************/ // MicroPython bindings to expose the internal flash as an object with the // block protocol. // there is a singleton Flash object STATIC const mp_obj_base_t pyb_flash_obj = {&pyb_flash_type}; STATIC mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); // return singleton object return (mp_obj_t)&pyb_flash_obj; } STATIC mp_obj_t pyb_flash_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); DRESULT res = sflash_disk_read(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SFLASH_SECTOR_SIZE); return MP_OBJ_NEW_SMALL_INT(res != RES_OK); // return of 0 means success } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_readblocks_obj, pyb_flash_readblocks); STATIC mp_obj_t pyb_flash_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); DRESULT res = sflash_disk_write(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SFLASH_SECTOR_SIZE); return MP_OBJ_NEW_SMALL_INT(res != RES_OK); // return of 0 means success } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_writeblocks_obj, pyb_flash_writeblocks); STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(sflash_disk_init() != RES_OK); case MP_BLOCKDEV_IOCTL_DEINIT: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0); case MP_BLOCKDEV_IOCTL_SYNC: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0); case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(SFLASH_SECTOR_COUNT); case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(SFLASH_SECTOR_SIZE); default: return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_ioctl_obj, pyb_flash_ioctl); STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&pyb_flash_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&pyb_flash_writeblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&pyb_flash_ioctl_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table); const mp_obj_type_t pyb_flash_type = { { &mp_type_type }, .name = MP_QSTR_Flash, .make_new = pyb_flash_make_new, .locals_dict = (mp_obj_t)&pyb_flash_locals_dict, }; void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; vfs->blockdev.readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj; vfs->blockdev.readblocks[1] = (mp_obj_t)&pyb_flash_obj; vfs->blockdev.readblocks[2] = (mp_obj_t)sflash_disk_read; // native version vfs->blockdev.writeblocks[0] = (mp_obj_t)&pyb_flash_writeblocks_obj; vfs->blockdev.writeblocks[1] = (mp_obj_t)&pyb_flash_obj; vfs->blockdev.writeblocks[2] = (mp_obj_t)sflash_disk_write; // native version vfs->blockdev.u.ioctl[0] = (mp_obj_t)&pyb_flash_ioctl_obj; vfs->blockdev.u.ioctl[1] = (mp_obj_t)&pyb_flash_obj; } micropython-1.12/ports/cc3200/mods/pybflash.h000066400000000000000000000027151357706137100210130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBFLASH_H #define MICROPY_INCLUDED_CC3200_MODS_PYBFLASH_H #include "py/obj.h" extern const mp_obj_type_t pyb_flash_type; void pyb_flash_init_vfs(fs_user_mount_t *vfs); #endif // MICROPY_INCLUDED_CC3200_MODS_PYBFLASH_H micropython-1.12/ports/cc3200/mods/pybi2c.c000066400000000000000000000475711357706137100203770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "bufhelper.h" #include "inc/hw_types.h" #include "inc/hw_i2c.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "pin.h" #include "prcm.h" #include "i2c.h" #include "pybi2c.h" #include "mpexception.h" #include "pybsleep.h" #include "utils.h" #include "pybpin.h" #include "pins.h" /// \moduleref pyb /// \class I2C - a two-wire serial protocol typedef struct _pyb_i2c_obj_t { mp_obj_base_t base; uint baudrate; } pyb_i2c_obj_t; /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define PYBI2C_MIN_BAUD_RATE_HZ (50000) #define PYBI2C_MAX_BAUD_RATE_HZ (400000) #define PYBI2C_TRANSC_TIMEOUT_MS (20) #define PYBI2C_TRANSAC_WAIT_DELAY_US (10) #define PYBI2C_TIMEOUT_TO_COUNT(to_us, baud) (((baud) * to_us) / 16000000) #define RET_IF_ERR(Func) { \ if (!Func) { \ return false; \ } \ } /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC pyb_i2c_obj_t pyb_i2c_obj = {.baudrate = 0}; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC bool pyb_i2c_write(byte addr, byte *data, uint len, bool stop); /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ // only master mode is available for the moment STATIC void i2c_init (pyb_i2c_obj_t *self) { // Enable the I2C Peripheral MAP_PRCMPeripheralClkEnable(PRCM_I2CA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); MAP_PRCMPeripheralReset(PRCM_I2CA0); // Configure I2C module with the specified baudrate MAP_I2CMasterInitExpClk(I2CA0_BASE, self->baudrate); } STATIC bool pyb_i2c_transaction(uint cmd) { // Convert the timeout to microseconds int32_t timeout = PYBI2C_TRANSC_TIMEOUT_MS * 1000; // Sanity check, t_timeout must be between 1 and 255 uint t_timeout = MIN(PYBI2C_TIMEOUT_TO_COUNT(timeout, pyb_i2c_obj.baudrate), 255); // Clear all interrupts MAP_I2CMasterIntClearEx(I2CA0_BASE, MAP_I2CMasterIntStatusEx(I2CA0_BASE, false)); // Set the time-out in terms of clock cycles. Not to be used with breakpoints. MAP_I2CMasterTimeoutSet(I2CA0_BASE, t_timeout); // Initiate the transfer. MAP_I2CMasterControl(I2CA0_BASE, cmd); // Wait until the current byte has been transferred. // Poll on the raw interrupt status. while ((MAP_I2CMasterIntStatusEx(I2CA0_BASE, false) & (I2C_MASTER_INT_DATA | I2C_MASTER_INT_TIMEOUT)) == 0) { if (timeout < 0) { // the peripheral is not responding, so stop return false; } // wait for a few microseconds UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBI2C_TRANSAC_WAIT_DELAY_US)); timeout -= PYBI2C_TRANSAC_WAIT_DELAY_US; } // Check for any errors in the transfer if (MAP_I2CMasterErr(I2CA0_BASE) != I2C_MASTER_ERR_NONE) { switch(cmd) { case I2C_MASTER_CMD_BURST_SEND_START: case I2C_MASTER_CMD_BURST_SEND_CONT: case I2C_MASTER_CMD_BURST_SEND_STOP: MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP); break; case I2C_MASTER_CMD_BURST_RECEIVE_START: case I2C_MASTER_CMD_BURST_RECEIVE_CONT: case I2C_MASTER_CMD_BURST_RECEIVE_FINISH: MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP); break; default: break; } return false; } return true; } STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) { // not initialized if (!self->baudrate) { mp_raise_OSError(MP_EPERM); } } STATIC bool pyb_i2c_scan_device(byte devAddr) { bool ret = false; // Set the I2C slave address MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true); // Initiate the transfer. if (pyb_i2c_transaction(I2C_MASTER_CMD_SINGLE_RECEIVE)) { ret = true; } // Send the stop bit to cancel the read transaction MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP); if (!ret) { uint8_t data = 0; if (pyb_i2c_write(devAddr, &data, sizeof(data), true)) { ret = true; } } return ret; } STATIC bool pyb_i2c_mem_addr_write (byte addr, byte *mem_addr, uint mem_addr_len) { // Set I2C codec slave address MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, false); // Write the first byte to the controller. MAP_I2CMasterDataPut(I2CA0_BASE, *mem_addr++); // Initiate the transfer. RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_START)); // Loop until the completion of transfer or error while (--mem_addr_len) { // Write the next byte of data MAP_I2CMasterDataPut(I2CA0_BASE, *mem_addr++); // Transact over I2C to send the next byte RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT)); } return true; } STATIC bool pyb_i2c_mem_write (byte addr, byte *mem_addr, uint mem_addr_len, byte *data, uint data_len) { if (pyb_i2c_mem_addr_write (addr, mem_addr, mem_addr_len)) { // Loop until the completion of transfer or error while (data_len--) { // Write the next byte of data MAP_I2CMasterDataPut(I2CA0_BASE, *data++); // Transact over I2C to send the byte RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT)); } // send the stop bit RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_STOP)); return true; } return false; } STATIC bool pyb_i2c_write(byte addr, byte *data, uint len, bool stop) { // Set I2C codec slave address MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, false); // Write the first byte to the controller. MAP_I2CMasterDataPut(I2CA0_BASE, *data++); // Initiate the transfer. RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_START)); // Loop until the completion of transfer or error while (--len) { // Write the next byte of data MAP_I2CMasterDataPut(I2CA0_BASE, *data++); // Transact over I2C to send the byte RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT)); } // If a stop bit is to be sent, do it. if (stop) { RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_STOP)); } return true; } STATIC bool pyb_i2c_read(byte addr, byte *data, uint len) { // Initiate a burst or single receive sequence uint cmd = --len > 0 ? I2C_MASTER_CMD_BURST_RECEIVE_START : I2C_MASTER_CMD_SINGLE_RECEIVE; // Set I2C codec slave address MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, true); // Initiate the transfer. RET_IF_ERR(pyb_i2c_transaction(cmd)); // Loop until the completion of reception or error while (len) { // Receive the byte over I2C *data++ = MAP_I2CMasterDataGet(I2CA0_BASE); if (--len) { // Continue with reception RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_RECEIVE_CONT)); } else { // Complete the last reception RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_RECEIVE_FINISH)); } } // Receive the last byte over I2C *data = MAP_I2CMasterDataGet(I2CA0_BASE); return true; } STATIC void pyb_i2c_read_into (mp_arg_val_t *args, vstr_t *vstr) { pyb_i2c_check_init(&pyb_i2c_obj); // get the buffer to receive into pyb_buf_get_for_recv(args[1].u_obj, vstr); // receive the data if (!pyb_i2c_read(args[0].u_int, (byte *)vstr->buf, vstr->len)) { mp_raise_OSError(MP_EIO); } } STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) { pyb_i2c_check_init(&pyb_i2c_obj); // get the buffer to receive into pyb_buf_get_for_recv(args[2].u_obj, vstr); // get the addresses mp_uint_t i2c_addr = args[0].u_int; mp_uint_t mem_addr = args[1].u_int; // determine the width of mem_addr (1 or 2 bytes) mp_uint_t mem_addr_size = args[3].u_int >> 3; // write the register address to be read from if (pyb_i2c_mem_addr_write (i2c_addr, (byte *)&mem_addr, mem_addr_size)) { // Read the specified length of data if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) { mp_raise_OSError(MP_EIO); } } else { mp_raise_OSError(MP_EIO); } } /******************************************************************************/ /* MicroPython bindings */ /******************************************************************************/ STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_i2c_obj_t *self = self_in; if (self->baudrate > 0) { mp_printf(print, "I2C(0, baudrate=%u)", self->baudrate); } else { mp_print_str(print, "I2C(0)"); } } STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_scl, ARG_sda, ARG_freq }; static const mp_arg_t allowed_args[] = { { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // make sure the baudrate is between the valid range self->baudrate = MIN(MAX(args[ARG_freq].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ); // assign the pins mp_obj_t pins[2] = {&pin_GP13, &pin_GP23}; // default (SDA, SCL) pins if (args[ARG_scl].u_obj != MP_OBJ_NULL) { pins[1] = args[ARG_scl].u_obj; } if (args[ARG_sda].u_obj != MP_OBJ_NULL) { pins[0] = args[ARG_sda].u_obj; } pin_assign_pins_af(pins, 2, PIN_TYPE_STD_PU, PIN_FN_I2C, 0); // init the I2C bus i2c_init(self); // register it with the sleep module pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)i2c_init); return mp_const_none; } STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // check the id argument, if given if (n_args > 0) { if (all_args[0] != MP_OBJ_NEW_SMALL_INT(0)) { mp_raise_OSError(MP_ENODEV); } --n_args; ++all_args; } // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); // setup the object pyb_i2c_obj_t *self = &pyb_i2c_obj; self->base.type = &pyb_i2c_type; // start the peripheral pyb_i2c_init_helper(self, n_args, all_args, &kw_args); return (mp_obj_t)self; } STATIC mp_obj_t pyb_i2c_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { return pyb_i2c_init_helper(pos_args[0], n_args - 1, pos_args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init); STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) { // disable the peripheral MAP_I2CMasterDisable(I2CA0_BASE); MAP_PRCMPeripheralClkDisable(PRCM_I2CA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // invalidate the baudrate pyb_i2c_obj.baudrate = 0; // unregister it with the sleep module pyb_sleep_remove ((const mp_obj_t)self_in); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit); STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) { pyb_i2c_check_init(&pyb_i2c_obj); mp_obj_t list = mp_obj_new_list(0, NULL); for (uint addr = 0x08; addr <= 0x77; addr++) { for (int i = 0; i < 3; i++) { if (pyb_i2c_scan_device(addr)) { mp_obj_list_append(list, mp_obj_new_int(addr)); break; } } } return list; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_scan_obj, pyb_i2c_scan); STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t pyb_i2c_readfrom_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_args, args); vstr_t vstr; pyb_i2c_read_into(args, &vstr); // return the received data return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 3, pyb_i2c_readfrom); STATIC mp_obj_t pyb_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t pyb_i2c_readfrom_into_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_into_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_into_args, args); vstr_t vstr; pyb_i2c_read_into(args, &vstr); // return the number of bytes received return mp_obj_new_int(vstr.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_into_obj, 1, pyb_i2c_readfrom_into); STATIC mp_obj_t pyb_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t pyb_i2c_writeto_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_writeto_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_writeto_args, args); pyb_i2c_check_init(&pyb_i2c_obj); // get the buffer to send from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(args[1].u_obj, &bufinfo, data); // send the data if (!pyb_i2c_write(args[0].u_int, bufinfo.buf, bufinfo.len, args[2].u_bool)) { mp_raise_OSError(MP_EIO); } // return the number of bytes written return mp_obj_new_int(bufinfo.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_obj, 1, pyb_i2c_writeto); STATIC mp_obj_t pyb_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t pyb_i2c_readfrom_mem_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_mem_args, args); vstr_t vstr; pyb_i2c_readmem_into (args, &vstr); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_obj, 1, pyb_i2c_readfrom_mem); STATIC const mp_arg_t pyb_i2c_readfrom_mem_into_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, }; STATIC mp_obj_t pyb_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_mem_into_args, args); // get the buffer to read into vstr_t vstr; pyb_i2c_readmem_into (args, &vstr); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_into_obj, 1, pyb_i2c_readfrom_mem_into); STATIC mp_obj_t pyb_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args), pyb_i2c_readfrom_mem_into_args, args); pyb_i2c_check_init(&pyb_i2c_obj); // get the buffer to write from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(args[2].u_obj, &bufinfo, data); // get the addresses mp_uint_t i2c_addr = args[0].u_int; mp_uint_t mem_addr = args[1].u_int; // determine the width of mem_addr (1 or 2 bytes) mp_uint_t mem_addr_size = args[3].u_int >> 3; // write the register address to write to. if (pyb_i2c_mem_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len)) { return mp_const_none; } mp_raise_OSError(MP_EIO); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_mem_obj, 1, pyb_i2c_writeto_mem); STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_i2c_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_i2c_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&pyb_i2c_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&pyb_i2c_readfrom_obj) }, { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&pyb_i2c_readfrom_into_obj) }, { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&pyb_i2c_writeto_obj) }, { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&pyb_i2c_readfrom_mem_obj) }, { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&pyb_i2c_readfrom_mem_into_obj) }, { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&pyb_i2c_writeto_mem_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table); const mp_obj_type_t pyb_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, .print = pyb_i2c_print, .make_new = pyb_i2c_make_new, .locals_dict = (mp_obj_t)&pyb_i2c_locals_dict, }; micropython-1.12/ports/cc3200/mods/pybi2c.h000066400000000000000000000026531357706137100203740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBI2C_H #define MICROPY_INCLUDED_CC3200_MODS_PYBI2C_H extern const mp_obj_type_t pyb_i2c_type; #endif // MICROPY_INCLUDED_CC3200_MODS_PYBI2C_H micropython-1.12/ports/cc3200/mods/pybpin.c000066400000000000000000001024241357706137100204750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/gc.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "pin.h" #include "prcm.h" #include "gpio.h" #include "interrupt.h" #include "pybpin.h" #include "mpirq.h" #include "pins.h" #include "pybsleep.h" #include "mpexception.h" #include "mperror.h" /// \moduleref pyb /// \class Pin - control I/O pins /// /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name); STATIC pin_obj_t *pin_find_pin_by_port_bit (const mp_obj_dict_t *named_pins, uint port, uint bit); STATIC int8_t pin_obj_find_af (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type); STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type); STATIC void pin_deassign (pin_obj_t* pin); STATIC void pin_obj_configure (const pin_obj_t *self); STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t *self, uint *wake_pin, uint *idx); STATIC void pin_irq_enable (mp_obj_t self_in); STATIC void pin_irq_disable (mp_obj_t self_in); STATIC void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority); STATIC void pin_validate_mode (uint mode); STATIC void pin_validate_pull (uint pull); STATIC void pin_validate_drive (uint strength); STATIC void pin_validate_af(const pin_obj_t* pin, int8_t idx, uint8_t *fn, uint8_t *unit, uint8_t *type); STATIC uint8_t pin_get_value(const pin_obj_t* self); STATIC void GPIOA0IntHandler (void); STATIC void GPIOA1IntHandler (void); STATIC void GPIOA2IntHandler (void); STATIC void GPIOA3IntHandler (void); STATIC void EXTI_Handler(uint port); /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define PYBPIN_NUM_WAKE_PINS (6) #define PYBPIN_WAKES_NOT (-1) #define GPIO_DIR_MODE_ALT 0x00000002 // Pin is NOT controlled by the PGIO module #define GPIO_DIR_MODE_ALT_OD 0x00000003 // Pin is NOT controlled by the PGIO module and is in open drain mode #define PYB_PIN_FALLING_EDGE 0x01 #define PYB_PIN_RISING_EDGE 0x02 #define PYB_PIN_LOW_LEVEL 0x04 #define PYB_PIN_HIGH_LEVEL 0x08 /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef struct { bool active; int8_t lpds; int8_t hib; } pybpin_wake_pin_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC const mp_irq_methods_t pin_irq_methods; STATIC pybpin_wake_pin_t pybpin_wake_pin[PYBPIN_NUM_WAKE_PINS] = { {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT} } ; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void pin_init0(void) { // this initalization also reconfigures the JTAG/SWD pins #ifndef DEBUG // assign all pins to the GPIO module so that peripherals can be connected to any // pins without conflicts after a soft reset const mp_map_t *named_map = &pin_board_pins_locals_dict.map; for (uint i = 0; i < named_map->used - 1; i++) { pin_obj_t * pin = (pin_obj_t *)named_map->table[i].value; pin_deassign (pin); } #endif } // C API used to convert a user-supplied pin name into an ordinal pin number. pin_obj_t *pin_find(mp_obj_t user_obj) { pin_obj_t *pin_obj; // if a pin was provided, use it if (mp_obj_is_type(user_obj, &pin_type)) { pin_obj = user_obj; return pin_obj; } // otherwise see if the pin name matches a cpu pin pin_obj = pin_find_named_pin(&pin_board_pins_locals_dict, user_obj); if (pin_obj) { return pin_obj; } mp_raise_ValueError(mpexception_value_invalid_arguments); } void pin_config (pin_obj_t *self, int af, uint mode, uint pull, int value, uint strength) { self->mode = mode, self->pull = pull, self->strength = strength; // if af is -1, then we want to keep it as it is if (af != -1) { self->af = af; } // if value is -1, then we want to keep it as it is if (value != -1) { self->value = value; } // mark the pin as used self->used = true; pin_obj_configure ((const pin_obj_t *)self); // register it with the sleep module pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pin_obj_configure); } void pin_assign_pins_af (mp_obj_t *pins, uint32_t n_pins, uint32_t pull, uint32_t fn, uint32_t unit) { for (int i = 0; i < n_pins; i++) { pin_free_af_from_pins(fn, unit, i); if (pins[i] != mp_const_none) { pin_obj_t *pin = pin_find(pins[i]); pin_config (pin, pin_find_af_index(pin, fn, unit, i), 0, pull, -1, PIN_STRENGTH_2MA); } } } uint8_t pin_find_peripheral_unit (const mp_obj_t pin, uint8_t fn, uint8_t type) { pin_obj_t *pin_o = pin_find(pin); for (int i = 0; i < pin_o->num_afs; i++) { if (pin_o->af_list[i].fn == fn && pin_o->af_list[i].type == type) { return pin_o->af_list[i].unit; } } mp_raise_ValueError(mpexception_value_invalid_arguments); } uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit) { pin_obj_t *pin_o = pin_find(pin); for (int i = 0; i < pin_o->num_afs; i++) { if (pin_o->af_list[i].fn == fn && pin_o->af_list[i].unit == unit) { return pin_o->af_list[i].type; } } mp_raise_ValueError(mpexception_value_invalid_arguments); } int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) { int8_t af = pin_obj_find_af(pin, fn, unit, type); if (af < 0) { mp_raise_ValueError(mpexception_value_invalid_arguments); } return af; } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ STATIC pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { const mp_map_t *named_map = &named_pins->map; mp_map_elem_t *named_elem = mp_map_lookup((mp_map_t*)named_map, name, MP_MAP_LOOKUP); if (named_elem != NULL && named_elem->value != NULL) { return named_elem->value; } return NULL; } STATIC pin_obj_t *pin_find_pin_by_port_bit (const mp_obj_dict_t *named_pins, uint port, uint bit) { const mp_map_t *named_map = &named_pins->map; for (uint i = 0; i < named_map->used; i++) { if ((((pin_obj_t *)named_map->table[i].value)->port == port) && (((pin_obj_t *)named_map->table[i].value)->bit == bit)) { return named_map->table[i].value; } } return NULL; } STATIC int8_t pin_obj_find_af (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) { for (int i = 0; i < pin->num_afs; i++) { if (pin->af_list[i].fn == fn && pin->af_list[i].unit == unit && pin->af_list[i].type == type) { return pin->af_list[i].idx; } } return -1; } STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type) { const mp_map_t *named_map = &pin_board_pins_locals_dict.map; for (uint i = 0; i < named_map->used - 1; i++) { pin_obj_t * pin = (pin_obj_t *)named_map->table[i].value; // af is different than GPIO if (pin->af > PIN_MODE_0) { // check if the pin supports the target af int af = pin_obj_find_af(pin, fn, unit, type); if (af > 0 && af == pin->af) { // the pin supports the target af, de-assign it pin_deassign (pin); } } } } STATIC void pin_deassign (pin_obj_t* pin) { pin_config (pin, PIN_MODE_0, GPIO_DIR_MODE_IN, PIN_TYPE_STD, -1, PIN_STRENGTH_4MA); pin->used = false; } STATIC void pin_obj_configure (const pin_obj_t *self) { uint32_t type; if (self->mode == PIN_TYPE_ANALOG) { type = PIN_TYPE_ANALOG; } else { type = self->pull; uint32_t direction = self->mode; if (direction == PIN_TYPE_OD || direction == GPIO_DIR_MODE_ALT_OD) { direction = GPIO_DIR_MODE_OUT; type |= PIN_TYPE_OD; } if (self->mode != GPIO_DIR_MODE_ALT && self->mode != GPIO_DIR_MODE_ALT_OD) { // enable the peripheral clock for the GPIO port of this pin switch (self->port) { case PORT_A0: MAP_PRCMPeripheralClkEnable(PRCM_GPIOA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); break; case PORT_A1: MAP_PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); break; case PORT_A2: MAP_PRCMPeripheralClkEnable(PRCM_GPIOA2, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); break; case PORT_A3: MAP_PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); break; default: break; } // configure the direction MAP_GPIODirModeSet(self->port, self->bit, direction); // set the pin value if (self->value) { MAP_GPIOPinWrite(self->port, self->bit, self->bit); } else { MAP_GPIOPinWrite(self->port, self->bit, 0); } } // now set the alternate function MAP_PinModeSet (self->pin_num, self->af); } MAP_PinConfigSet(self->pin_num, self->strength, type); } STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t *self, uint *hib_pin, uint *idx) { // pin_num is actually : (package_pin - 1) switch (self->pin_num) { case 56: // GP2 *hib_pin = PRCM_HIB_GPIO2; *idx = 0; break; case 58: // GP4 *hib_pin = PRCM_HIB_GPIO4; *idx = 1; break; case 3: // GP13 *hib_pin = PRCM_HIB_GPIO13; *idx = 2; break; case 7: // GP17 *hib_pin = PRCM_HIB_GPIO17; *idx = 3; break; case 1: // GP11 *hib_pin = PRCM_HIB_GPIO11; *idx = 4; break; case 16: // GP24 *hib_pin = PRCM_HIB_GPIO24; *idx = 5; break; default: *idx = 0xFF; break; } } STATIC void pin_irq_enable (mp_obj_t self_in) { const pin_obj_t *self = self_in; uint hib_pin, idx; pin_get_hibernate_pin_and_idx (self, &hib_pin, &idx); if (idx < PYBPIN_NUM_WAKE_PINS) { if (pybpin_wake_pin[idx].lpds != PYBPIN_WAKES_NOT) { // enable GPIO as a wake source during LPDS MAP_PRCMLPDSWakeUpGPIOSelect(idx, pybpin_wake_pin[idx].lpds); MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_GPIO); } if (pybpin_wake_pin[idx].hib != PYBPIN_WAKES_NOT) { // enable GPIO as a wake source during hibernate MAP_PRCMHibernateWakeUpGPIOSelect(hib_pin, pybpin_wake_pin[idx].hib); MAP_PRCMHibernateWakeupSourceEnable(hib_pin); } else { MAP_PRCMHibernateWakeupSourceDisable(hib_pin); } } // if idx is invalid, the pin supports active interrupts for sure if (idx >= PYBPIN_NUM_WAKE_PINS || pybpin_wake_pin[idx].active) { MAP_GPIOIntClear(self->port, self->bit); MAP_GPIOIntEnable(self->port, self->bit); } // in case it was enabled before else if (idx < PYBPIN_NUM_WAKE_PINS && !pybpin_wake_pin[idx].active) { MAP_GPIOIntDisable(self->port, self->bit); } } STATIC void pin_irq_disable (mp_obj_t self_in) { const pin_obj_t *self = self_in; uint hib_pin, idx; pin_get_hibernate_pin_and_idx (self, &hib_pin, &idx); if (idx < PYBPIN_NUM_WAKE_PINS) { if (pybpin_wake_pin[idx].lpds != PYBPIN_WAKES_NOT) { // disable GPIO as a wake source during LPDS MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO); } if (pybpin_wake_pin[idx].hib != PYBPIN_WAKES_NOT) { // disable GPIO as a wake source during hibernate MAP_PRCMHibernateWakeupSourceDisable(hib_pin); } } // not need to check for the active flag, it's safe to disable it anyway MAP_GPIOIntDisable(self->port, self->bit); } STATIC int pin_irq_flags (mp_obj_t self_in) { const pin_obj_t *self = self_in; return self->irq_flags; } STATIC void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority) { void *handler; uint32_t intnum; // configure the interrupt type MAP_GPIOIntTypeSet(self->port, self->bit, intmode); switch (self->port) { case GPIOA0_BASE: handler = GPIOA0IntHandler; intnum = INT_GPIOA0; break; case GPIOA1_BASE: handler = GPIOA1IntHandler; intnum = INT_GPIOA1; break; case GPIOA2_BASE: handler = GPIOA2IntHandler; intnum = INT_GPIOA2; break; case GPIOA3_BASE: default: handler = GPIOA3IntHandler; intnum = INT_GPIOA3; break; } MAP_GPIOIntRegister(self->port, handler); // set the interrupt to the lowest priority, to make sure that // no other ISRs will be preemted by this one MAP_IntPrioritySet(intnum, priority); } STATIC void pin_validate_mode (uint mode) { if (mode != GPIO_DIR_MODE_IN && mode != GPIO_DIR_MODE_OUT && mode != PIN_TYPE_OD && mode != GPIO_DIR_MODE_ALT && mode != GPIO_DIR_MODE_ALT_OD) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void pin_validate_pull (uint pull) { if (pull != PIN_TYPE_STD && pull != PIN_TYPE_STD_PU && pull != PIN_TYPE_STD_PD) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void pin_validate_drive(uint strength) { if (strength != PIN_STRENGTH_2MA && strength != PIN_STRENGTH_4MA && strength != PIN_STRENGTH_6MA) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void pin_validate_af(const pin_obj_t* pin, int8_t idx, uint8_t *fn, uint8_t *unit, uint8_t *type) { for (int i = 0; i < pin->num_afs; i++) { if (pin->af_list[i].idx == idx) { *fn = pin->af_list[i].fn; *unit = pin->af_list[i].unit; *type = pin->af_list[i].type; return; } } mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC uint8_t pin_get_value (const pin_obj_t* self) { uint32_t value; bool setdir = false; if (self->mode == PIN_TYPE_OD || self->mode == GPIO_DIR_MODE_ALT_OD) { setdir = true; // configure the direction to IN for a moment in order to read the pin value MAP_GPIODirModeSet(self->port, self->bit, GPIO_DIR_MODE_IN); } // now get the value value = MAP_GPIOPinRead(self->port, self->bit); if (setdir) { // set the direction back to output MAP_GPIODirModeSet(self->port, self->bit, GPIO_DIR_MODE_OUT); if (self->value) { MAP_GPIOPinWrite(self->port, self->bit, self->bit); } else { MAP_GPIOPinWrite(self->port, self->bit, 0); } } // return it return value ? 1 : 0; } STATIC void GPIOA0IntHandler (void) { EXTI_Handler(GPIOA0_BASE); } STATIC void GPIOA1IntHandler (void) { EXTI_Handler(GPIOA1_BASE); } STATIC void GPIOA2IntHandler (void) { EXTI_Handler(GPIOA2_BASE); } STATIC void GPIOA3IntHandler (void) { EXTI_Handler(GPIOA3_BASE); } // common interrupt handler STATIC void EXTI_Handler(uint port) { uint32_t bits = MAP_GPIOIntStatus(port, true); MAP_GPIOIntClear(port, bits); // might be that we have more than one pin interrupt pending // therefore we must loop through all of the 8 possible bits for (int i = 0; i < 8; i++) { uint32_t bit = (1 << i); if (bit & bits) { pin_obj_t *self = (pin_obj_t *)pin_find_pin_by_port_bit(&pin_board_pins_locals_dict, port, bit); if (self->irq_trigger == (PYB_PIN_FALLING_EDGE | PYB_PIN_RISING_EDGE)) { // read the pin value (hoping that the pin level has remained stable) self->irq_flags = MAP_GPIOPinRead(self->port, self->bit) ? PYB_PIN_RISING_EDGE : PYB_PIN_FALLING_EDGE; } else { // same as the triggers self->irq_flags = self->irq_trigger; } mp_irq_handler(mp_irq_find(self)); // always clear the flags after leaving the user handler self->irq_flags = 0; } } } /******************************************************************************/ // MicroPython bindings STATIC const mp_arg_t pin_init_args[] = { { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PIN_STRENGTH_4MA} }, { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; #define pin_INIT_NUM_ARGS MP_ARRAY_SIZE(pin_init_args) STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[pin_INIT_NUM_ARGS]; mp_arg_parse_all(n_args, pos_args, kw_args, pin_INIT_NUM_ARGS, pin_init_args, args); // get the io mode uint mode; // default is input if (args[0].u_obj == MP_OBJ_NULL) { mode = GPIO_DIR_MODE_IN; } else { mode = mp_obj_get_int(args[0].u_obj); pin_validate_mode (mode); } // get the pull type uint pull; if (args[1].u_obj == mp_const_none) { pull = PIN_TYPE_STD; } else { pull = mp_obj_get_int(args[1].u_obj); pin_validate_pull (pull); } // get the value int value = -1; if (args[2].u_obj != MP_OBJ_NULL) { if (mp_obj_is_true(args[2].u_obj)) { value = 1; } else { value = 0; } } // get the strenght uint strength = args[3].u_int; pin_validate_drive(strength); // get the alternate function int af = args[4].u_int; if (mode != GPIO_DIR_MODE_ALT && mode != GPIO_DIR_MODE_ALT_OD) { if (af == -1) { af = 0; } else { goto invalid_args; } } else if (af < -1 || af > 15) { goto invalid_args; } // check for a valid af and then free it from any other pins if (af > PIN_MODE_0) { uint8_t fn, unit, type; pin_validate_af (self, af, &fn, &unit, &type); pin_free_af_from_pins(fn, unit, type); } pin_config (self, af, mode, pull, value, strength); return mp_const_none; invalid_args: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pin_obj_t *self = self_in; uint32_t pull = self->pull; uint32_t drive = self->strength; // pin name mp_printf(print, "Pin('%q'", self->name); // pin mode qstr mode_qst; uint32_t mode = self->mode; if (mode == GPIO_DIR_MODE_IN) { mode_qst = MP_QSTR_IN; } else if (mode == GPIO_DIR_MODE_OUT) { mode_qst = MP_QSTR_OUT; } else if (mode == GPIO_DIR_MODE_ALT) { mode_qst = MP_QSTR_ALT; } else if (mode == GPIO_DIR_MODE_ALT_OD) { mode_qst = MP_QSTR_ALT_OPEN_DRAIN; } else { mode_qst = MP_QSTR_OPEN_DRAIN; } mp_printf(print, ", mode=Pin.%q", mode_qst); // pin pull qstr pull_qst; if (pull == PIN_TYPE_STD) { mp_printf(print, ", pull=%q", MP_QSTR_None); } else { if (pull == PIN_TYPE_STD_PU) { pull_qst = MP_QSTR_PULL_UP; } else { pull_qst = MP_QSTR_PULL_DOWN; } mp_printf(print, ", pull=Pin.%q", pull_qst); } // pin drive qstr drv_qst; if (drive == PIN_STRENGTH_2MA) { drv_qst = MP_QSTR_LOW_POWER; } else if (drive == PIN_STRENGTH_4MA) { drv_qst = MP_QSTR_MED_POWER; } else { drv_qst = MP_QSTR_HIGH_POWER; } mp_printf(print, ", drive=Pin.%q", drv_qst); // pin af int alt = (self->af == 0) ? -1 : self->af; mp_printf(print, ", alt=%d)", alt); } STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // Run an argument through the mapper and return the result. pin_obj_t *pin = (pin_obj_t *)pin_find(args[0]); mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); return (mp_obj_t)pin; } STATIC mp_obj_t pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); } MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init); STATIC mp_obj_t pin_value(size_t n_args, const mp_obj_t *args) { pin_obj_t *self = args[0]; if (n_args == 1) { // get the value return MP_OBJ_NEW_SMALL_INT(pin_get_value(self)); } else { // set the pin value if (mp_obj_is_true(args[1])) { self->value = 1; MAP_GPIOPinWrite(self->port, self->bit, self->bit); } else { self->value = 0; MAP_GPIOPinWrite(self->port, self->bit, 0); } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value); STATIC mp_obj_t pin_id(mp_obj_t self_in) { pin_obj_t *self = self_in; return MP_OBJ_NEW_QSTR(self->name); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_id_obj, pin_id); STATIC mp_obj_t pin_mode(size_t n_args, const mp_obj_t *args) { pin_obj_t *self = args[0]; if (n_args == 1) { return mp_obj_new_int(self->mode); } else { uint32_t mode = mp_obj_get_int(args[1]); pin_validate_mode (mode); self->mode = mode; pin_obj_configure(self); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_mode_obj, 1, 2, pin_mode); STATIC mp_obj_t pin_pull(size_t n_args, const mp_obj_t *args) { pin_obj_t *self = args[0]; if (n_args == 1) { if (self->pull == PIN_TYPE_STD) { return mp_const_none; } return mp_obj_new_int(self->pull); } else { uint32_t pull; if (args[1] == mp_const_none) { pull = PIN_TYPE_STD; } else { pull = mp_obj_get_int(args[1]); pin_validate_pull (pull); } self->pull = pull; pin_obj_configure(self); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_pull_obj, 1, 2, pin_pull); STATIC mp_obj_t pin_drive(size_t n_args, const mp_obj_t *args) { pin_obj_t *self = args[0]; if (n_args == 1) { return mp_obj_new_int(self->strength); } else { uint32_t strength = mp_obj_get_int(args[1]); pin_validate_drive (strength); self->strength = strength; pin_obj_configure(self); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_drive_obj, 1, 2, pin_drive); STATIC mp_obj_t pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_t _args[2] = {self_in, *args}; return pin_value (n_args + 1, _args); } STATIC mp_obj_t pin_alt_list(mp_obj_t self_in) { pin_obj_t *self = self_in; mp_obj_t af[2]; mp_obj_t afs = mp_obj_new_list(0, NULL); for (int i = 0; i < self->num_afs; i++) { af[0] = MP_OBJ_NEW_QSTR(self->af_list[i].name); af[1] = mp_obj_new_int(self->af_list[i].idx); mp_obj_list_append(afs, mp_obj_new_tuple(MP_ARRAY_SIZE(af), af)); } return afs; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_alt_list_obj, pin_alt_list); /// \method irq(trigger, priority, handler, wake) STATIC mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); pin_obj_t *self = pos_args[0]; // convert the priority to the correct value uint priority = mp_irq_translate_priority (args[1].u_int); // verify and translate the interrupt mode uint mp_trigger = mp_obj_get_int(args[0].u_obj); uint trigger; if (mp_trigger == (PYB_PIN_FALLING_EDGE | PYB_PIN_RISING_EDGE)) { trigger = GPIO_BOTH_EDGES; } else { switch (mp_trigger) { case PYB_PIN_FALLING_EDGE: trigger = GPIO_FALLING_EDGE; break; case PYB_PIN_RISING_EDGE: trigger = GPIO_RISING_EDGE; break; case PYB_PIN_LOW_LEVEL: trigger = GPIO_LOW_LEVEL; break; case PYB_PIN_HIGH_LEVEL: trigger = GPIO_HIGH_LEVEL; break; default: goto invalid_args; } } uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj); if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) { goto invalid_args; } // get the wake info from this pin uint hib_pin, idx; pin_get_hibernate_pin_and_idx ((const pin_obj_t *)self, &hib_pin, &idx); if (pwrmode & PYB_PWR_MODE_LPDS) { if (idx >= PYBPIN_NUM_WAKE_PINS) { goto invalid_args; } // wake modes are different in LDPS uint wake_mode; switch (trigger) { case GPIO_FALLING_EDGE: wake_mode = PRCM_LPDS_FALL_EDGE; break; case GPIO_RISING_EDGE: wake_mode = PRCM_LPDS_RISE_EDGE; break; case GPIO_LOW_LEVEL: wake_mode = PRCM_LPDS_LOW_LEVEL; break; case GPIO_HIGH_LEVEL: wake_mode = PRCM_LPDS_HIGH_LEVEL; break; default: goto invalid_args; break; } // first clear the lpds value from all wake-able pins for (uint i = 0; i < PYBPIN_NUM_WAKE_PINS; i++) { pybpin_wake_pin[i].lpds = PYBPIN_WAKES_NOT; } // enable this pin as a wake-up source during LPDS pybpin_wake_pin[idx].lpds = wake_mode; } else if (idx < PYBPIN_NUM_WAKE_PINS) { // this pin was the previous LPDS wake source, so disable it completely if (pybpin_wake_pin[idx].lpds != PYBPIN_WAKES_NOT) { MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO); } pybpin_wake_pin[idx].lpds = PYBPIN_WAKES_NOT; } if (pwrmode & PYB_PWR_MODE_HIBERNATE) { if (idx >= PYBPIN_NUM_WAKE_PINS) { goto invalid_args; } // wake modes are different in hibernate uint wake_mode; switch (trigger) { case GPIO_FALLING_EDGE: wake_mode = PRCM_HIB_FALL_EDGE; break; case GPIO_RISING_EDGE: wake_mode = PRCM_HIB_RISE_EDGE; break; case GPIO_LOW_LEVEL: wake_mode = PRCM_HIB_LOW_LEVEL; break; case GPIO_HIGH_LEVEL: wake_mode = PRCM_HIB_HIGH_LEVEL; break; default: goto invalid_args; break; } // enable this pin as wake-up source during hibernate pybpin_wake_pin[idx].hib = wake_mode; } else if (idx < PYBPIN_NUM_WAKE_PINS) { pybpin_wake_pin[idx].hib = PYBPIN_WAKES_NOT; } // we need to update the callback atomically, so we disable the // interrupt before we update anything. pin_irq_disable(self); if (pwrmode & PYB_PWR_MODE_ACTIVE) { // register the interrupt pin_extint_register((pin_obj_t *)self, trigger, priority); if (idx < PYBPIN_NUM_WAKE_PINS) { pybpin_wake_pin[idx].active = true; } } else if (idx < PYBPIN_NUM_WAKE_PINS) { pybpin_wake_pin[idx].active = false; } // all checks have passed, we can create the irq object mp_obj_t _irq = mp_irq_new (self, args[2].u_obj, &pin_irq_methods); if (pwrmode & PYB_PWR_MODE_LPDS) { pyb_sleep_set_gpio_lpds_callback (_irq); } // save the mp_trigge for later self->irq_trigger = mp_trigger; // enable the interrupt just before leaving pin_irq_enable(self); return _irq; invalid_args: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_irq_obj, 1, pin_irq); STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pin_init_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_id), MP_ROM_PTR(&pin_id_obj) }, { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&pin_mode_obj) }, { MP_ROM_QSTR(MP_QSTR_pull), MP_ROM_PTR(&pin_pull_obj) }, { MP_ROM_QSTR(MP_QSTR_drive), MP_ROM_PTR(&pin_drive_obj) }, { MP_ROM_QSTR(MP_QSTR_alt_list), MP_ROM_PTR(&pin_alt_list_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pin_irq_obj) }, // class attributes { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) }, // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_DIR_MODE_IN) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_DIR_MODE_OUT) }, { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(PIN_TYPE_OD) }, { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_DIR_MODE_ALT) }, { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(GPIO_DIR_MODE_ALT_OD) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(PIN_TYPE_STD_PU) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(PIN_TYPE_STD_PD) }, { MP_ROM_QSTR(MP_QSTR_LOW_POWER), MP_ROM_INT(PIN_STRENGTH_2MA) }, { MP_ROM_QSTR(MP_QSTR_MED_POWER), MP_ROM_INT(PIN_STRENGTH_4MA) }, { MP_ROM_QSTR(MP_QSTR_HIGH_POWER), MP_ROM_INT(PIN_STRENGTH_6MA) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(PYB_PIN_FALLING_EDGE) }, { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(PYB_PIN_RISING_EDGE) }, { MP_ROM_QSTR(MP_QSTR_IRQ_LOW_LEVEL), MP_ROM_INT(PYB_PIN_LOW_LEVEL) }, { MP_ROM_QSTR(MP_QSTR_IRQ_HIGH_LEVEL), MP_ROM_INT(PYB_PIN_HIGH_LEVEL) }, }; STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table); const mp_obj_type_t pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, .print = pin_print, .make_new = pin_make_new, .call = pin_call, .locals_dict = (mp_obj_t)&pin_locals_dict, }; STATIC const mp_irq_methods_t pin_irq_methods = { .init = pin_irq, .enable = pin_irq_enable, .disable = pin_irq_disable, .flags = pin_irq_flags, }; STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pin_named_pins_obj_t *self = self_in; mp_printf(print, "", self->name); } const mp_obj_type_t pin_board_pins_obj_type = { { &mp_type_type }, .name = MP_QSTR_board, .print = pin_named_pins_obj_print, .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict, }; micropython-1.12/ports/cc3200/mods/pybpin.h000066400000000000000000000073061357706137100205050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBPIN_H #define MICROPY_INCLUDED_CC3200_MODS_PYBPIN_H enum { PORT_A0 = GPIOA0_BASE, PORT_A1 = GPIOA1_BASE, PORT_A2 = GPIOA2_BASE, PORT_A3 = GPIOA3_BASE, }; enum { PIN_FN_UART = 0, PIN_FN_SPI, PIN_FN_I2S, PIN_FN_I2C, PIN_FN_TIM, PIN_FN_SD, PIN_FN_ADC, }; enum { PIN_TYPE_UART_TX = 0, PIN_TYPE_UART_RX, PIN_TYPE_UART_RTS, PIN_TYPE_UART_CTS, }; enum { PIN_TYPE_SPI_CLK = 0, PIN_TYPE_SPI_MOSI, PIN_TYPE_SPI_MISO, PIN_TYPE_SPI_CS0, }; enum { PIN_TYPE_I2S_CLK = 0, PIN_TYPE_I2S_FS, PIN_TYPE_I2S_DAT0, PIN_TYPE_I2S_DAT1, }; enum { PIN_TYPE_I2C_SDA = 0, PIN_TYPE_I2C_SCL, }; enum { PIN_TYPE_TIM_PWM = 0, }; enum { PIN_TYPE_SD_CLK = 0, PIN_TYPE_SD_CMD, PIN_TYPE_SD_DAT0, }; enum { PIN_TYPE_ADC_CH0 = 0, PIN_TYPE_ADC_CH1, PIN_TYPE_ADC_CH2, PIN_TYPE_ADC_CH3, }; typedef struct { qstr name; int8_t idx; uint8_t fn; uint8_t unit; uint8_t type; } pin_af_t; typedef struct { const mp_obj_base_t base; const qstr name; const uint32_t port; const pin_af_t *af_list; uint16_t pull; const uint8_t bit; const uint8_t pin_num; int8_t af; uint8_t strength; uint8_t mode; // this is now a combination of type and mode const uint8_t num_afs; // 255 AFs uint8_t value; uint8_t used; uint8_t irq_trigger; uint8_t irq_flags; } pin_obj_t; extern const mp_obj_type_t pin_type; typedef struct { const char *name; const pin_obj_t *pin; } pin_named_pin_t; typedef struct { mp_obj_base_t base; qstr name; const pin_named_pin_t *named_pins; } pin_named_pins_obj_t; extern const mp_obj_type_t pin_board_pins_obj_type; extern const mp_obj_dict_t pin_board_pins_locals_dict; void pin_init0(void); void pin_config(pin_obj_t *self, int af, uint mode, uint type, int value, uint strength); pin_obj_t *pin_find(mp_obj_t user_obj); void pin_assign_pins_af (mp_obj_t *pins, uint32_t n_pins, uint32_t pull, uint32_t fn, uint32_t unit); uint8_t pin_find_peripheral_unit (const mp_obj_t pin, uint8_t fn, uint8_t type); uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit); int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type);; #endif // MICROPY_INCLUDED_CC3200_MODS_PYBPIN_H micropython-1.12/ports/cc3200/mods/pybrtc.c000066400000000000000000000413011357706137100204730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" #include "py/mperrno.h" #include "lib/timeutils/timeutils.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "prcm.h" #include "pybrtc.h" #include "mpirq.h" #include "pybsleep.h" #include "simplelink.h" #include "modnetwork.h" #include "modwlan.h" #include "mpexception.h" /// \moduleref pyb /// \class RTC - real time clock /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC const mp_irq_methods_t pyb_rtc_irq_methods; STATIC pyb_rtc_obj_t pyb_rtc_obj; /****************************************************************************** FUNCTION-LIKE MACROS ******************************************************************************/ #define RTC_U16MS_CYCLES(msec) ((msec * 1024) / 1000) #define RTC_CYCLES_U16MS(cycles) ((cycles * 1000) / 1024) /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void pyb_rtc_set_time (uint32_t secs, uint16_t msecs); STATIC uint32_t pyb_rtc_reset (void); STATIC void pyb_rtc_disable_interupt (void); STATIC void pyb_rtc_irq_enable (mp_obj_t self_in); STATIC void pyb_rtc_irq_disable (mp_obj_t self_in); STATIC int pyb_rtc_irq_flags (mp_obj_t self_in); STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds); STATIC mp_obj_t pyb_rtc_datetime(mp_obj_t self, const mp_obj_t datetime); STATIC void pyb_rtc_set_alarm (pyb_rtc_obj_t *self, uint32_t seconds, uint16_t mseconds); STATIC void rtc_msec_add(uint16_t msecs_1, uint32_t *secs, uint16_t *msecs_2); /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ __attribute__ ((section (".boot"))) void pyb_rtc_pre_init(void) { // only if comming out of a power-on reset if (MAP_PRCMSysResetCauseGet() == PRCM_POWER_ON) { // Mark the RTC in use first MAP_PRCMRTCInUseSet(); // reset the time and date pyb_rtc_reset(); } } void pyb_rtc_get_time (uint32_t *secs, uint16_t *msecs) { uint16_t cycles; MAP_PRCMRTCGet (secs, &cycles); *msecs = RTC_CYCLES_U16MS(cycles); } uint32_t pyb_rtc_get_seconds (void) { uint32_t seconds; uint16_t mseconds; pyb_rtc_get_time(&seconds, &mseconds); return seconds; } void pyb_rtc_calc_future_time (uint32_t a_mseconds, uint32_t *f_seconds, uint16_t *f_mseconds) { uint32_t c_seconds; uint16_t c_mseconds; // get the current time pyb_rtc_get_time(&c_seconds, &c_mseconds); // calculate the future seconds *f_seconds = c_seconds + (a_mseconds / 1000); // calculate the "remaining" future mseconds *f_mseconds = a_mseconds % 1000; // add the current milliseconds rtc_msec_add (c_mseconds, f_seconds, f_mseconds); } void pyb_rtc_repeat_alarm (pyb_rtc_obj_t *self) { if (self->repeat) { uint32_t f_seconds, c_seconds; uint16_t f_mseconds, c_mseconds; pyb_rtc_get_time(&c_seconds, &c_mseconds); // substract the time elapsed between waking up and setting up the alarm again int32_t wake_ms = ((c_seconds * 1000) + c_mseconds) - ((self->alarm_time_s * 1000) + self->alarm_time_ms); int32_t next_alarm = self->alarm_ms - wake_ms; next_alarm = next_alarm > 0 ? next_alarm : PYB_RTC_MIN_ALARM_TIME_MS; pyb_rtc_calc_future_time (next_alarm, &f_seconds, &f_mseconds); // now configure the alarm pyb_rtc_set_alarm (self, f_seconds, f_mseconds); } } void pyb_rtc_disable_alarm (void) { pyb_rtc_obj.alarmset = false; pyb_rtc_disable_interupt(); } /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void pyb_rtc_set_time (uint32_t secs, uint16_t msecs) { // add the RTC access time rtc_msec_add(RTC_ACCESS_TIME_MSEC, &secs, &msecs); // convert from mseconds to cycles msecs = RTC_U16MS_CYCLES(msecs); // now set the time MAP_PRCMRTCSet(secs, msecs); } STATIC uint32_t pyb_rtc_reset (void) { // fresh reset; configure the RTC Calendar // set the date to 1st Jan 2015 // set the time to 00:00:00 uint32_t seconds = timeutils_seconds_since_2000(2015, 1, 1, 0, 0, 0); // disable any running alarm pyb_rtc_disable_alarm(); // Now set the RTC calendar time pyb_rtc_set_time(seconds, 0); return seconds; } STATIC void pyb_rtc_disable_interupt (void) { uint primsk = disable_irq(); MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR); (void)MAP_PRCMIntStatus(); enable_irq(primsk); } STATIC void pyb_rtc_irq_enable (mp_obj_t self_in) { pyb_rtc_obj_t *self = self_in; // we always need interrupts if repeat is enabled if ((self->pwrmode & PYB_PWR_MODE_ACTIVE) || self->repeat) { MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR); } else { // just in case it was already enabled before MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR); } self->irq_enabled = true; } STATIC void pyb_rtc_irq_disable (mp_obj_t self_in) { pyb_rtc_obj_t *self = self_in; self->irq_enabled = false; if (!self->repeat) { // we always need interrupts if repeat is enabled pyb_rtc_disable_interupt(); } } STATIC int pyb_rtc_irq_flags (mp_obj_t self_in) { pyb_rtc_obj_t *self = self_in; return self->irq_flags; } STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds) { timeutils_struct_time_t tm; uint32_t useconds; // set date and time mp_obj_t *items; size_t len; mp_obj_get_array(datetime, &len, &items); // verify the tuple if (len < 3 || len > 8) { mp_raise_ValueError(mpexception_value_invalid_arguments); } tm.tm_year = mp_obj_get_int(items[0]); tm.tm_mon = mp_obj_get_int(items[1]); tm.tm_mday = mp_obj_get_int(items[2]); if (len < 7) { useconds = 0; } else { useconds = mp_obj_get_int(items[6]); } if (len < 6) { tm.tm_sec = 0; } else { tm.tm_sec = mp_obj_get_int(items[5]); } if (len < 5) { tm.tm_min = 0; } else { tm.tm_min = mp_obj_get_int(items[4]); } if (len < 4) { tm.tm_hour = 0; } else { tm.tm_hour = mp_obj_get_int(items[3]); } *seconds = timeutils_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); return useconds; } /// The 8-tuple has the same format as CPython's datetime object: /// /// (year, month, day, hours, minutes, seconds, milliseconds, tzinfo=None) /// STATIC mp_obj_t pyb_rtc_datetime(mp_obj_t self_in, const mp_obj_t datetime) { uint32_t seconds; uint32_t useconds; if (datetime != MP_OBJ_NULL) { useconds = pyb_rtc_datetime_s_us(datetime, &seconds); pyb_rtc_set_time (seconds, useconds / 1000); } else { seconds = pyb_rtc_reset(); } // set WLAN time and date, this is needed to verify certificates wlan_set_current_time(seconds); return mp_const_none; } STATIC void pyb_rtc_set_alarm (pyb_rtc_obj_t *self, uint32_t seconds, uint16_t mseconds) { // disable the interrupt before updating anything if (self->irq_enabled) { MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR); } // set the match value MAP_PRCMRTCMatchSet(seconds, RTC_U16MS_CYCLES(mseconds)); self->alarmset = true; self->alarm_time_s = seconds; self->alarm_time_ms = mseconds; // enabled the interrupts again if applicable if (self->irq_enabled || self->repeat) { MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR); } } STATIC void rtc_msec_add (uint16_t msecs_1, uint32_t *secs, uint16_t *msecs_2) { if (msecs_1 + *msecs_2 >= 1000) { // larger than one second *msecs_2 = (msecs_1 + *msecs_2) - 1000; *secs += 1; // carry flag } else { // simply add the mseconds *msecs_2 = msecs_1 + *msecs_2; } } /******************************************************************************/ // MicroPython bindings STATIC const mp_arg_t pyb_rtc_init_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_datetime, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); mp_arg_val_t args[MP_ARRAY_SIZE(pyb_rtc_init_args)]; mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_rtc_init_args, args); // check the peripheral id if (args[0].u_int != 0) { mp_raise_OSError(MP_ENODEV); } // setup the object pyb_rtc_obj_t *self = &pyb_rtc_obj; self->base.type = &pyb_rtc_type; // set the time and date pyb_rtc_datetime((mp_obj_t)&pyb_rtc_obj, args[1].u_obj); // pass it to the sleep module pyb_sleep_set_rtc_obj (self); // return constant object return (mp_obj_t)&pyb_rtc_obj; } STATIC mp_obj_t pyb_rtc_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_rtc_init_args) - 1]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_rtc_init_args[1], args); return pyb_rtc_datetime(pos_args[0], args[0].u_obj); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_init_obj, 1, pyb_rtc_init); STATIC mp_obj_t pyb_rtc_now (mp_obj_t self_in) { timeutils_struct_time_t tm; uint32_t seconds; uint16_t mseconds; // get the time from the RTC pyb_rtc_get_time(&seconds, &mseconds); timeutils_seconds_since_2000_to_struct_time(seconds, &tm); mp_obj_t tuple[8] = { mp_obj_new_int(tm.tm_year), mp_obj_new_int(tm.tm_mon), mp_obj_new_int(tm.tm_mday), mp_obj_new_int(tm.tm_hour), mp_obj_new_int(tm.tm_min), mp_obj_new_int(tm.tm_sec), mp_obj_new_int(mseconds * 1000), mp_const_none }; return mp_obj_new_tuple(8, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_now_obj, pyb_rtc_now); STATIC mp_obj_t pyb_rtc_deinit (mp_obj_t self_in) { pyb_rtc_reset(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_deinit_obj, pyb_rtc_deinit); STATIC mp_obj_t pyb_rtc_alarm(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_time, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_repeat, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; // parse args pyb_rtc_obj_t *self = pos_args[0]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args); // check the alarm id if (args[0].u_int != 0) { mp_raise_OSError(MP_ENODEV); } uint32_t f_seconds; uint16_t f_mseconds; bool repeat = args[2].u_bool; if (mp_obj_is_type(args[1].u_obj, &mp_type_tuple)) { // datetime tuple given // repeat cannot be used with a datetime tuple if (repeat) { mp_raise_ValueError(mpexception_value_invalid_arguments); } f_mseconds = pyb_rtc_datetime_s_us (args[1].u_obj, &f_seconds) / 1000; } else { // then it must be an integer self->alarm_ms = mp_obj_get_int(args[1].u_obj); pyb_rtc_calc_future_time (self->alarm_ms, &f_seconds, &f_mseconds); } // store the repepat flag self->repeat = repeat; // now configure the alarm pyb_rtc_set_alarm (self, f_seconds, f_mseconds); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_alarm_obj, 1, pyb_rtc_alarm); STATIC mp_obj_t pyb_rtc_alarm_left(size_t n_args, const mp_obj_t *args) { pyb_rtc_obj_t *self = args[0]; int32_t ms_left; uint32_t c_seconds; uint16_t c_mseconds; // only alarm id 0 is available if (n_args > 1 && mp_obj_get_int(args[1]) != 0) { mp_raise_OSError(MP_ENODEV); } // get the current time pyb_rtc_get_time(&c_seconds, &c_mseconds); // calculate the ms left ms_left = ((self->alarm_time_s * 1000) + self->alarm_time_ms) - ((c_seconds * 1000) + c_mseconds); if (!self->alarmset || ms_left < 0) { ms_left = 0; } return mp_obj_new_int(ms_left); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc_alarm_left); STATIC mp_obj_t pyb_rtc_alarm_cancel(size_t n_args, const mp_obj_t *args) { // only alarm id 0 is available if (n_args > 1 && mp_obj_get_int(args[1]) != 0) { mp_raise_OSError(MP_ENODEV); } // disable the alarm pyb_rtc_disable_alarm(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_cancel_obj, 1, 2, pyb_rtc_alarm_cancel); /// \method irq(trigger, priority, handler, wake) STATIC mp_obj_t pyb_rtc_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); pyb_rtc_obj_t *self = pos_args[0]; // save the power mode data for later uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj); if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) { goto invalid_args; } // check the trigger if (mp_obj_get_int(args[0].u_obj) == PYB_RTC_ALARM0) { self->pwrmode = pwrmode; pyb_rtc_irq_enable((mp_obj_t)self); } else { goto invalid_args; } // the interrupt priority is ignored since it's already set to to highest level by the sleep module // to make sure that the wakeup irqs are always called first when resuming from sleep // create the callback mp_obj_t _irq = mp_irq_new ((mp_obj_t)self, args[2].u_obj, &pyb_rtc_irq_methods); self->irq_obj = _irq; return _irq; invalid_args: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq); STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_rtc_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_rtc_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_now), MP_ROM_PTR(&pyb_rtc_now_obj) }, { MP_ROM_QSTR(MP_QSTR_alarm), MP_ROM_PTR(&pyb_rtc_alarm_obj) }, { MP_ROM_QSTR(MP_QSTR_alarm_left), MP_ROM_PTR(&pyb_rtc_alarm_left_obj) }, { MP_ROM_QSTR(MP_QSTR_alarm_cancel), MP_ROM_PTR(&pyb_rtc_alarm_cancel_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_rtc_irq_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_ALARM0), MP_ROM_INT(PYB_RTC_ALARM0) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table); const mp_obj_type_t pyb_rtc_type = { { &mp_type_type }, .name = MP_QSTR_RTC, .make_new = pyb_rtc_make_new, .locals_dict = (mp_obj_t)&pyb_rtc_locals_dict, }; STATIC const mp_irq_methods_t pyb_rtc_irq_methods = { .init = pyb_rtc_irq, .enable = pyb_rtc_irq_enable, .disable = pyb_rtc_irq_disable, .flags = pyb_rtc_irq_flags }; micropython-1.12/ports/cc3200/mods/pybrtc.h000066400000000000000000000043231357706137100205030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBRTC_H #define MICROPY_INCLUDED_CC3200_MODS_PYBRTC_H // RTC triggers #define PYB_RTC_ALARM0 (0x01) #define RTC_ACCESS_TIME_MSEC (5) #define PYB_RTC_MIN_ALARM_TIME_MS (RTC_ACCESS_TIME_MSEC * 2) typedef struct _pyb_rtc_obj_t { mp_obj_base_t base; mp_obj_t irq_obj; uint32_t irq_flags; uint32_t alarm_ms; uint32_t alarm_time_s; uint16_t alarm_time_ms; byte pwrmode; bool alarmset; bool repeat; bool irq_enabled; } pyb_rtc_obj_t; extern const mp_obj_type_t pyb_rtc_type; extern void pyb_rtc_pre_init(void); extern void pyb_rtc_get_time (uint32_t *secs, uint16_t *msecs); extern uint32_t pyb_rtc_get_seconds (void); extern void pyb_rtc_calc_future_time (uint32_t a_mseconds, uint32_t *f_seconds, uint16_t *f_mseconds); extern void pyb_rtc_repeat_alarm (pyb_rtc_obj_t *self); extern void pyb_rtc_disable_alarm (void); #endif // MICROPY_INCLUDED_CC3200_MODS_PYBRTC_H micropython-1.12/ports/cc3200/mods/pybsd.c000066400000000000000000000210631357706137100203140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs_fat.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "pin.h" #include "prcm.h" #include "gpio.h" #include "sdhost.h" #include "sd_diskio.h" #include "pybsd.h" #include "mpexception.h" #include "pybsleep.h" #include "pybpin.h" #include "pins.h" /****************************************************************************** DEFINE PRIVATE CONSTANTS ******************************************************************************/ #define PYBSD_FREQUENCY_HZ 15000000 // 15MHz /****************************************************************************** DECLARE PUBLIC DATA ******************************************************************************/ pybsd_obj_t pybsd_obj; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC const mp_obj_t pyb_sd_def_pin[3] = {&pin_GP10, &pin_GP11, &pin_GP15}; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void pyb_sd_hw_init (pybsd_obj_t *self); STATIC mp_obj_t pyb_sd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t pyb_sd_deinit (mp_obj_t self_in); /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ /// Initalizes the sd card hardware driver STATIC void pyb_sd_hw_init (pybsd_obj_t *self) { if (self->pin_clk) { // Configure the clock pin as output only MAP_PinDirModeSet(((pin_obj_t *)(self->pin_clk))->pin_num, PIN_DIR_MODE_OUT); } // Enable SD peripheral clock MAP_PRCMPeripheralClkEnable(PRCM_SDHOST, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // Reset MMCHS MAP_PRCMPeripheralReset(PRCM_SDHOST); // Initialize MMCHS MAP_SDHostInit(SDHOST_BASE); // Configure the card clock MAP_SDHostSetExpClk(SDHOST_BASE, MAP_PRCMPeripheralClockGet(PRCM_SDHOST), PYBSD_FREQUENCY_HZ); // Set card rd/wr block len MAP_SDHostBlockSizeSet(SDHOST_BASE, SD_SECTOR_SIZE); self->enabled = true; } STATIC mp_obj_t pyb_sd_init_helper (pybsd_obj_t *self, const mp_arg_val_t *args) { // assign the pins mp_obj_t pins_o = args[0].u_obj; if (pins_o != mp_const_none) { mp_obj_t *pins; if (pins_o == MP_OBJ_NULL) { // use the default pins pins = (mp_obj_t *)pyb_sd_def_pin; } else { mp_obj_get_array_fixed_n(pins_o, MP_ARRAY_SIZE(pyb_sd_def_pin), &pins); } pin_assign_pins_af (pins, MP_ARRAY_SIZE(pyb_sd_def_pin), PIN_TYPE_STD_PU, PIN_FN_SD, 0); // save the pins clock self->pin_clk = pin_find(pins[0]); } pyb_sd_hw_init (self); if (sd_disk_init() != 0) { mp_raise_OSError(MP_EIO); } // register it with the sleep module pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pyb_sd_hw_init); return mp_const_none; } /******************************************************************************/ // MicroPython bindings // STATIC const mp_arg_t pyb_sd_init_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; STATIC mp_obj_t pyb_sd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); mp_arg_val_t args[MP_ARRAY_SIZE(pyb_sd_init_args)]; mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_sd_init_args, args); // check the peripheral id if (args[0].u_int != 0) { mp_raise_OSError(MP_ENODEV); } // setup and initialize the object mp_obj_t self = &pybsd_obj; pybsd_obj.base.type = &pyb_sd_type; pyb_sd_init_helper (self, &args[1]); return self; } STATIC mp_obj_t pyb_sd_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_sd_init_args) - 1]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_sd_init_args[1], args); return pyb_sd_init_helper(pos_args[0], args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_sd_init_obj, 1, pyb_sd_init); STATIC mp_obj_t pyb_sd_deinit (mp_obj_t self_in) { pybsd_obj_t *self = self_in; // disable the peripheral self->enabled = false; MAP_PRCMPeripheralClkDisable(PRCM_SDHOST, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // de-initialze the sd card at diskio level sd_disk_deinit(); // unregister it from the sleep module pyb_sleep_remove (self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sd_deinit_obj, pyb_sd_deinit); STATIC mp_obj_t pyb_sd_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); DRESULT res = sd_disk_read(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SD_SECTOR_SIZE); return MP_OBJ_NEW_SMALL_INT(res != RES_OK); // return of 0 means success } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sd_readblocks_obj, pyb_sd_readblocks); STATIC mp_obj_t pyb_sd_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); DRESULT res = sd_disk_write(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SD_SECTOR_SIZE); return MP_OBJ_NEW_SMALL_INT(res != RES_OK); // return of 0 means success } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sd_writeblocks_obj, pyb_sd_writeblocks); STATIC mp_obj_t pyb_sd_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: case MP_BLOCKDEV_IOCTL_DEINIT: case MP_BLOCKDEV_IOCTL_SYNC: // nothing to do return MP_OBJ_NEW_SMALL_INT(0); // success case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(sd_disk_info.ulNofBlock * (sd_disk_info.ulBlockSize / 512)); case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(SD_SECTOR_SIZE); default: // unknown command return MP_OBJ_NEW_SMALL_INT(-1); // error } } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sd_ioctl_obj, pyb_sd_ioctl); STATIC const mp_rom_map_elem_t pyb_sd_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_sd_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_sd_deinit_obj) }, // block device protocol { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&pyb_sd_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&pyb_sd_writeblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&pyb_sd_ioctl_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_sd_locals_dict, pyb_sd_locals_dict_table); const mp_obj_type_t pyb_sd_type = { { &mp_type_type }, .name = MP_QSTR_SD, .make_new = pyb_sd_make_new, .locals_dict = (mp_obj_t)&pyb_sd_locals_dict, }; micropython-1.12/ports/cc3200/mods/pybsd.h000066400000000000000000000035651357706137100203300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBSD_H #define MICROPY_INCLUDED_CC3200_MODS_PYBSD_H /****************************************************************************** DEFINE PUBLIC TYPES ******************************************************************************/ typedef struct { mp_obj_base_t base; mp_obj_t pin_clk; bool enabled; } pybsd_obj_t; /****************************************************************************** DECLARE EXPORTED DATA ******************************************************************************/ extern pybsd_obj_t pybsd_obj; extern const mp_obj_type_t pyb_sd_type; #endif // MICROPY_INCLUDED_CC3200_MODS_PYBSD_H micropython-1.12/ports/cc3200/mods/pybsleep.c000066400000000000000000000572021357706137100210220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_common_reg.h" #include "inc/hw_memmap.h" #include "cc3200_asm.h" #include "rom_map.h" #include "interrupt.h" #include "systick.h" #include "prcm.h" #include "spi.h" #include "pin.h" #include "pybsleep.h" #include "mpirq.h" #include "pybpin.h" #include "simplelink.h" #include "modnetwork.h" #include "modwlan.h" #include "osi.h" #include "debug.h" #include "mpexception.h" #include "mperror.h" #include "sleeprestore.h" #include "serverstask.h" #include "antenna.h" #include "cryptohash.h" #include "pybrtc.h" /****************************************************************************** DECLARE PRIVATE CONSTANTS ******************************************************************************/ #define SPIFLASH_INSTR_READ_STATUS (0x05) #define SPIFLASH_INSTR_DEEP_POWER_DOWN (0xB9) #define SPIFLASH_STATUS_BUSY (0x01) #define LPDS_UP_TIME (425) // 13 msec #define LPDS_DOWN_TIME (98) // 3 msec #define USER_OFFSET (131) // 4 smec #define WAKEUP_TIME_LPDS (LPDS_UP_TIME + LPDS_DOWN_TIME + USER_OFFSET) // 20 msec #define WAKEUP_TIME_HIB (32768) // 1 s #define FORCED_TIMER_INTERRUPT_MS (PYB_RTC_MIN_ALARM_TIME_MS) #define FAILED_SLEEP_DELAY_MS (FORCED_TIMER_INTERRUPT_MS * 3) /****************************************************************************** DECLARE PRIVATE TYPES ******************************************************************************/ // storage memory for Cortex M4 registers typedef struct { uint32_t msp; uint32_t psp; uint32_t psr; uint32_t primask; uint32_t faultmask; uint32_t basepri; uint32_t control; } arm_cm4_core_regs_t; // storage memory for the NVIC registers typedef struct { uint32_t vector_table; // Vector Table Offset uint32_t aux_ctrl; // Auxiliary control register uint32_t int_ctrl_state; // Interrupt Control and State uint32_t app_int; // Application Interrupt Reset control uint32_t sys_ctrl; // System control uint32_t config_ctrl; // Configuration control uint32_t sys_pri_1; // System Handler Priority 1 uint32_t sys_pri_2; // System Handler Priority 2 uint32_t sys_pri_3; // System Handler Priority 3 uint32_t sys_hcrs; // System Handler control and state register uint32_t systick_ctrl; // SysTick Control Status uint32_t systick_reload; // SysTick Reload uint32_t systick_calib; // SysTick Calibration uint32_t int_en[6]; // Interrupt set enable uint32_t int_priority[49]; // Interrupt priority } nvic_reg_store_t; typedef struct { mp_obj_base_t base; mp_obj_t obj; WakeUpCB_t wakeup; } pyb_sleep_obj_t; typedef struct { mp_obj_t gpio_lpds_wake_cb; wlan_obj_t *wlan_obj; pyb_rtc_obj_t *rtc_obj; } pybsleep_data_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC nvic_reg_store_t *nvic_reg_store; STATIC pybsleep_data_t pybsleep_data = {NULL, NULL, NULL}; volatile arm_cm4_core_regs_t vault_arm_registers; STATIC pybsleep_reset_cause_t pybsleep_reset_cause = PYB_SLP_PWRON_RESET; STATIC pybsleep_wake_reason_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON; STATIC const mp_obj_type_t pyb_sleep_type = { { &mp_type_type }, .name = MP_QSTR_sleep, }; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC pyb_sleep_obj_t *pyb_sleep_find (mp_obj_t obj); STATIC void pyb_sleep_flash_powerdown (void); STATIC NORETURN void pyb_sleep_suspend_enter (void); void pyb_sleep_suspend_exit (void); STATIC void pyb_sleep_obj_wakeup (void); STATIC void PRCMInterruptHandler (void); STATIC void pyb_sleep_iopark (bool hibernate); STATIC bool setup_timer_lpds_wake (void); STATIC bool setup_timer_hibernate_wake (void); /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ __attribute__ ((section (".boot"))) void pyb_sleep_pre_init (void) { // allocate memory for nvic registers vault ASSERT ((nvic_reg_store = mem_Malloc(sizeof(nvic_reg_store_t))) != NULL); } void pyb_sleep_init0 (void) { // initialize the sleep objects list mp_obj_list_init(&MP_STATE_PORT(pyb_sleep_obj_list), 0); // register and enable the PRCM interrupt osi_InterruptRegister(INT_PRCM, (P_OSI_INTR_ENTRY)PRCMInterruptHandler, INT_PRIORITY_LVL_1); // disable all LPDS and hibernate wake up sources (WLAN is disabed/enabled before entering LDPS mode) MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO); MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER); MAP_PRCMHibernateWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR | PRCM_HIB_GPIO2 | PRCM_HIB_GPIO4 | PRCM_HIB_GPIO13 | PRCM_HIB_GPIO17 | PRCM_HIB_GPIO11 | PRCM_HIB_GPIO24 | PRCM_HIB_GPIO26); // check the reset casue (if it's soft reset, leave it as it is) if (pybsleep_reset_cause != PYB_SLP_SOFT_RESET) { switch (MAP_PRCMSysResetCauseGet()) { case PRCM_POWER_ON: pybsleep_reset_cause = PYB_SLP_PWRON_RESET; break; case PRCM_CORE_RESET: case PRCM_MCU_RESET: case PRCM_SOC_RESET: pybsleep_reset_cause = PYB_SLP_HARD_RESET; break; case PRCM_WDT_RESET: pybsleep_reset_cause = PYB_SLP_WDT_RESET; break; case PRCM_HIB_EXIT: if (PRCMGetSpecialBit(PRCM_WDT_RESET_BIT)) { pybsleep_reset_cause = PYB_SLP_WDT_RESET; } else { pybsleep_reset_cause = PYB_SLP_HIB_RESET; // set the correct wake reason switch (MAP_PRCMHibernateWakeupCauseGet()) { case PRCM_HIB_WAKEUP_CAUSE_SLOW_CLOCK: pybsleep_wake_reason = PYB_SLP_WAKED_BY_RTC; // TODO repeat the alarm break; case PRCM_HIB_WAKEUP_CAUSE_GPIO: pybsleep_wake_reason = PYB_SLP_WAKED_BY_GPIO; break; default: break; } } break; default: break; } } } void pyb_sleep_signal_soft_reset (void) { pybsleep_reset_cause = PYB_SLP_SOFT_RESET; } void pyb_sleep_add (const mp_obj_t obj, WakeUpCB_t wakeup) { pyb_sleep_obj_t *sleep_obj = m_new_obj(pyb_sleep_obj_t); sleep_obj->base.type = &pyb_sleep_type; sleep_obj->obj = obj; sleep_obj->wakeup = wakeup; // remove it in case it was already registered pyb_sleep_remove (obj); mp_obj_list_append(&MP_STATE_PORT(pyb_sleep_obj_list), sleep_obj); } void pyb_sleep_remove (const mp_obj_t obj) { pyb_sleep_obj_t *sleep_obj; if ((sleep_obj = pyb_sleep_find(obj))) { mp_obj_list_remove(&MP_STATE_PORT(pyb_sleep_obj_list), sleep_obj); } } void pyb_sleep_set_gpio_lpds_callback (mp_obj_t cb_obj) { pybsleep_data.gpio_lpds_wake_cb = cb_obj; } void pyb_sleep_set_wlan_obj (mp_obj_t wlan_obj) { pybsleep_data.wlan_obj = (wlan_obj_t *)wlan_obj; } void pyb_sleep_set_rtc_obj (mp_obj_t rtc_obj) { pybsleep_data.rtc_obj = (pyb_rtc_obj_t *)rtc_obj; } void pyb_sleep_sleep (void) { nlr_buf_t nlr; // check if we should enable timer wake-up if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_LPDS)) { if (!setup_timer_lpds_wake()) { // lpds entering is not possible, wait for the forced interrupt and return mp_hal_delay_ms(FAILED_SLEEP_DELAY_MS); return; } } else { // disable the timer as wake source MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER); } // do we need network wake-up? if (pybsleep_data.wlan_obj->irq_enabled) { MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_HOST_IRQ); server_sleep_sockets(); } else { MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_HOST_IRQ); } // entering and exiting suspended mode must be an atomic operation // therefore interrupts need to be disabled uint primsk = disable_irq(); if (nlr_push(&nlr) == 0) { pyb_sleep_suspend_enter(); nlr_pop(); } // an exception is always raised when exiting suspend mode enable_irq(primsk); } void pyb_sleep_deepsleep (void) { // check if we should enable timer wake-up if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_HIBERNATE)) { if (!setup_timer_hibernate_wake()) { // hibernating is not possible, wait for the forced interrupt and return mp_hal_delay_ms(FAILED_SLEEP_DELAY_MS); return; } } else { // disable the timer as hibernate wake source MAP_PRCMLPDSWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR); } wlan_stop(SL_STOP_TIMEOUT); pyb_sleep_flash_powerdown(); // must be done just before entering hibernate mode pyb_sleep_iopark(true); MAP_PRCMHibernateEnter(); } pybsleep_reset_cause_t pyb_sleep_get_reset_cause (void) { return pybsleep_reset_cause; } pybsleep_wake_reason_t pyb_sleep_get_wake_reason (void) { return pybsleep_wake_reason; } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ STATIC pyb_sleep_obj_t *pyb_sleep_find (mp_obj_t obj) { for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_sleep_obj_list).len; i++) { // search for the object and then remove it pyb_sleep_obj_t *sleep_obj = ((pyb_sleep_obj_t *)(MP_STATE_PORT(pyb_sleep_obj_list).items[i])); if (sleep_obj->obj == obj) { return sleep_obj; } } return NULL; } STATIC void pyb_sleep_flash_powerdown (void) { uint32_t status; // Enable clock for SSPI module MAP_PRCMPeripheralClkEnable(PRCM_SSPI, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // Reset SSPI at PRCM level and wait for reset to complete MAP_PRCMPeripheralReset(PRCM_SSPI); while(!MAP_PRCMPeripheralStatusGet(PRCM_SSPI)); // Reset SSPI at module level MAP_SPIReset(SSPI_BASE); // Configure SSPI module MAP_SPIConfigSetExpClk (SSPI_BASE, PRCMPeripheralClockGet(PRCM_SSPI), 20000000, SPI_MODE_MASTER,SPI_SUB_MODE_0, (SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVELOW | SPI_WL_8)); // Enable SSPI module MAP_SPIEnable(SSPI_BASE); // Enable chip select for the spi flash. MAP_SPICSEnable(SSPI_BASE); // Wait for the spi flash do { // Send the status register read instruction and read back a dummy byte. MAP_SPIDataPut(SSPI_BASE, SPIFLASH_INSTR_READ_STATUS); MAP_SPIDataGet(SSPI_BASE, &status); // Write a dummy byte then read back the actual status. MAP_SPIDataPut(SSPI_BASE, 0xFF); MAP_SPIDataGet(SSPI_BASE, &status); } while ((status & 0xFF) == SPIFLASH_STATUS_BUSY); // Disable chip select for the spi flash. MAP_SPICSDisable(SSPI_BASE); // Start another CS enable sequence for Power down command. MAP_SPICSEnable(SSPI_BASE); // Send Deep Power Down command to spi flash MAP_SPIDataPut(SSPI_BASE, SPIFLASH_INSTR_DEEP_POWER_DOWN); // Disable chip select for the spi flash. MAP_SPICSDisable(SSPI_BASE); } STATIC NORETURN void pyb_sleep_suspend_enter (void) { // enable full RAM retention MAP_PRCMSRAMRetentionEnable(PRCM_SRAM_COL_1 | PRCM_SRAM_COL_2 | PRCM_SRAM_COL_3 | PRCM_SRAM_COL_4, PRCM_SRAM_LPDS_RET); // save the NVIC control registers nvic_reg_store->vector_table = HWREG(NVIC_VTABLE); nvic_reg_store->aux_ctrl = HWREG(NVIC_ACTLR); nvic_reg_store->int_ctrl_state = HWREG(NVIC_INT_CTRL); nvic_reg_store->app_int = HWREG(NVIC_APINT); nvic_reg_store->sys_ctrl = HWREG(NVIC_SYS_CTRL); nvic_reg_store->config_ctrl = HWREG(NVIC_CFG_CTRL); nvic_reg_store->sys_pri_1 = HWREG(NVIC_SYS_PRI1); nvic_reg_store->sys_pri_2 = HWREG(NVIC_SYS_PRI2); nvic_reg_store->sys_pri_3 = HWREG(NVIC_SYS_PRI3); nvic_reg_store->sys_hcrs = HWREG(NVIC_SYS_HND_CTRL); // save the systick registers nvic_reg_store->systick_ctrl = HWREG(NVIC_ST_CTRL); nvic_reg_store->systick_reload = HWREG(NVIC_ST_RELOAD); nvic_reg_store->systick_calib = HWREG(NVIC_ST_CAL); // save the interrupt enable registers uint32_t *base_reg_addr = (uint32_t *)NVIC_EN0; for(int32_t i = 0; i < (sizeof(nvic_reg_store->int_en) / 4); i++) { nvic_reg_store->int_en[i] = base_reg_addr[i]; } // save the interrupt priority registers base_reg_addr = (uint32_t *)NVIC_PRI0; for(int32_t i = 0; i < (sizeof(nvic_reg_store->int_priority) / 4); i++) { nvic_reg_store->int_priority[i] = base_reg_addr[i]; } // switch off the heartbeat led (this makes sure it will blink as soon as we wake up) mperror_heartbeat_switch_off(); // park the gpio pins pyb_sleep_iopark(false); // store the cpu registers sleep_store(); // save the restore info and enter LPDS MAP_PRCMLPDSRestoreInfoSet(vault_arm_registers.psp, (uint32_t)sleep_restore); MAP_PRCMLPDSEnter(); // let the cpu fade away... for ( ; ; ); } void pyb_sleep_suspend_exit (void) { // take the I2C semaphore uint32_t reg = HWREG(COMMON_REG_BASE + COMMON_REG_O_I2C_Properties_Register); reg = (reg & ~0x3) | 0x1; HWREG(COMMON_REG_BASE + COMMON_REG_O_I2C_Properties_Register) = reg; // take the GPIO semaphore reg = HWREG(COMMON_REG_BASE + COMMON_REG_O_GPIO_properties_register); reg = (reg & ~0x3FF) | 0x155; HWREG(COMMON_REG_BASE + COMMON_REG_O_GPIO_properties_register) = reg; // restore de NVIC control registers HWREG(NVIC_VTABLE) = nvic_reg_store->vector_table; HWREG(NVIC_ACTLR) = nvic_reg_store->aux_ctrl; HWREG(NVIC_INT_CTRL) = nvic_reg_store->int_ctrl_state; HWREG(NVIC_APINT) = nvic_reg_store->app_int; HWREG(NVIC_SYS_CTRL) = nvic_reg_store->sys_ctrl; HWREG(NVIC_CFG_CTRL) = nvic_reg_store->config_ctrl; HWREG(NVIC_SYS_PRI1) = nvic_reg_store->sys_pri_1; HWREG(NVIC_SYS_PRI2) = nvic_reg_store->sys_pri_2; HWREG(NVIC_SYS_PRI3) = nvic_reg_store->sys_pri_3; HWREG(NVIC_SYS_HND_CTRL) = nvic_reg_store->sys_hcrs; // restore the systick register HWREG(NVIC_ST_CTRL) = nvic_reg_store->systick_ctrl; HWREG(NVIC_ST_RELOAD) = nvic_reg_store->systick_reload; HWREG(NVIC_ST_CAL) = nvic_reg_store->systick_calib; // restore the interrupt priority registers uint32_t *base_reg_addr = (uint32_t *)NVIC_PRI0; for (uint32_t i = 0; i < (sizeof(nvic_reg_store->int_priority) / 4); i++) { base_reg_addr[i] = nvic_reg_store->int_priority[i]; } // restore the interrupt enable registers base_reg_addr = (uint32_t *)NVIC_EN0; for(uint32_t i = 0; i < (sizeof(nvic_reg_store->int_en) / 4); i++) { base_reg_addr[i] = nvic_reg_store->int_en[i]; } HAL_INTRODUCE_SYNC_BARRIER(); // ungate the clock to the shared spi bus MAP_PRCMPeripheralClkEnable(PRCM_SSPI, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); #if MICROPY_HW_ANTENNA_DIVERSITY // re-configure the antenna selection pins antenna_init0(); #endif // reinitialize simplelink's interface sl_IfOpen (NULL, 0); // restore the configuration of all active peripherals pyb_sleep_obj_wakeup(); // reconfigure all the previously enabled interrupts mp_irq_wake_all(); // we need to init the crypto hash engine again //CRYPTOHASH_Init(); // trigger a sw interrupt MAP_IntPendSet(INT_PRCM); // force an exception to go back to the point where suspend mode was entered nlr_raise(mp_obj_new_exception(&mp_type_SystemExit)); } STATIC void PRCMInterruptHandler (void) { // reading the interrupt status automatically clears the interrupt if (PRCM_INT_SLOW_CLK_CTR == MAP_PRCMIntStatus()) { // reconfigure it again (if repeat is true) pyb_rtc_repeat_alarm (pybsleep_data.rtc_obj); pybsleep_data.rtc_obj->irq_flags = PYB_RTC_ALARM0; // need to check if irq's are enabled from the user point of view if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_ACTIVE)) { mp_irq_handler(pybsleep_data.rtc_obj->irq_obj); } pybsleep_data.rtc_obj->irq_flags = 0; } else { // interrupt has been triggered while waking up from LPDS switch (MAP_PRCMLPDSWakeupCauseGet()) { case PRCM_LPDS_HOST_IRQ: pybsleep_data.wlan_obj->irq_flags = MODWLAN_WIFI_EVENT_ANY; mp_irq_handler(pybsleep_data.wlan_obj->irq_obj); pybsleep_wake_reason = PYB_SLP_WAKED_BY_WLAN; pybsleep_data.wlan_obj->irq_flags = 0; break; case PRCM_LPDS_GPIO: mp_irq_handler(pybsleep_data.gpio_lpds_wake_cb); pybsleep_wake_reason = PYB_SLP_WAKED_BY_GPIO; break; case PRCM_LPDS_TIMER: // reconfigure it again if repeat is true pyb_rtc_repeat_alarm (pybsleep_data.rtc_obj); pybsleep_data.rtc_obj->irq_flags = PYB_RTC_ALARM0; // next one clears the wake cause flag MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER); mp_irq_handler(pybsleep_data.rtc_obj->irq_obj); pybsleep_data.rtc_obj->irq_flags = 0; pybsleep_wake_reason = PYB_SLP_WAKED_BY_RTC; break; default: break; } } } STATIC void pyb_sleep_obj_wakeup (void) { for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_sleep_obj_list).len; i++) { pyb_sleep_obj_t *sleep_obj = ((pyb_sleep_obj_t *)MP_STATE_PORT(pyb_sleep_obj_list).items[i]); sleep_obj->wakeup(sleep_obj->obj); } } STATIC void pyb_sleep_iopark (bool hibernate) { const mp_map_t *named_map = &pin_board_pins_locals_dict.map; for (uint i = 0; i < named_map->used; i++) { pin_obj_t * pin = (pin_obj_t *)named_map->table[i].value; switch (pin->pin_num) { #ifdef DEBUG // skip the JTAG pins case PIN_16: case PIN_17: case PIN_19: case PIN_20: break; #endif default: // enable a weak pull-up if the pin is unused if (!pin->used) { MAP_PinConfigSet(pin->pin_num, pin->strength, PIN_TYPE_STD_PU); } if (hibernate) { // make it an input MAP_PinDirModeSet(pin->pin_num, PIN_DIR_MODE_IN); } break; } } // park the sflash pins HWREG(0x4402E0E8) &= ~(0x3 << 8); HWREG(0x4402E0E8) |= (0x2 << 8); HWREG(0x4402E0EC) &= ~(0x3 << 8); HWREG(0x4402E0EC) |= (0x2 << 8); HWREG(0x4402E0F0) &= ~(0x3 << 8); HWREG(0x4402E0F0) |= (0x2 << 8); HWREG(0x4402E0F4) &= ~(0x3 << 8); HWREG(0x4402E0F4) |= (0x1 << 8); // if the board has antenna diversity, only park the antenna // selection pins when going into hibernation #if MICROPY_HW_ANTENNA_DIVERSITY if (hibernate) { #endif // park the antenna selection pins // (tri-stated with pull down enabled) HWREG(0x4402E108) = 0x00000E61; HWREG(0x4402E10C) = 0x00000E61; #if MICROPY_HW_ANTENNA_DIVERSITY } else { // park the antenna selection pins // (tri-stated without changing the pull up/down resistors) HWREG(0x4402E108) &= ~0x000000FF; HWREG(0x4402E108) |= 0x00000C61; HWREG(0x4402E10C) &= ~0x000000FF; HWREG(0x4402E10C) |= 0x00000C61; } #endif } STATIC bool setup_timer_lpds_wake (void) { uint64_t t_match, t_curr; int64_t t_remaining; // get the time remaining for the RTC timer to expire t_match = MAP_PRCMSlowClkCtrMatchGet(); t_curr = MAP_PRCMSlowClkCtrGet(); // get the time remaining in terms of slow clocks t_remaining = (t_match - t_curr); if (t_remaining > WAKEUP_TIME_LPDS) { // subtract the time it takes to wakeup from lpds t_remaining -= WAKEUP_TIME_LPDS; t_remaining = (t_remaining > 0xFFFFFFFF) ? 0xFFFFFFFF: t_remaining; // setup the LPDS wake time MAP_PRCMLPDSIntervalSet((uint32_t)t_remaining); // enable the wake source MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER); return true; } // disable the timer as wake source MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER); uint32_t f_seconds; uint16_t f_mseconds; // setup a timer interrupt immediately pyb_rtc_calc_future_time (FORCED_TIMER_INTERRUPT_MS, &f_seconds, &f_mseconds); MAP_PRCMRTCMatchSet(f_seconds, f_mseconds); // LPDS wake by timer was not possible, force an interrupt in active mode instead MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR); return false; } STATIC bool setup_timer_hibernate_wake (void) { uint64_t t_match, t_curr; int64_t t_remaining; // get the time remaining for the RTC timer to expire t_match = MAP_PRCMSlowClkCtrMatchGet(); t_curr = MAP_PRCMSlowClkCtrGet(); // get the time remaining in terms of slow clocks t_remaining = (t_match - t_curr); if (t_remaining > WAKEUP_TIME_HIB) { // subtract the time it takes for wakeup from hibernate t_remaining -= WAKEUP_TIME_HIB; // setup the LPDS wake time MAP_PRCMHibernateIntervalSet((uint32_t)t_remaining); // enable the wake source MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR); return true; } // disable the timer as wake source MAP_PRCMLPDSWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR); uint32_t f_seconds; uint16_t f_mseconds; // setup a timer interrupt immediately pyb_rtc_calc_future_time (FORCED_TIMER_INTERRUPT_MS, &f_seconds, &f_mseconds); MAP_PRCMRTCMatchSet(f_seconds, f_mseconds); // LPDS wake by timer was not possible, force an interrupt in active mode instead MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR); return false; } micropython-1.12/ports/cc3200/mods/pybsleep.h000066400000000000000000000056321357706137100210270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBSLEEP_H #define MICROPY_INCLUDED_CC3200_MODS_PYBSLEEP_H /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define PYB_PWR_MODE_ACTIVE (0x01) #define PYB_PWR_MODE_LPDS (0x02) #define PYB_PWR_MODE_HIBERNATE (0x04) /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef enum { PYB_SLP_PWRON_RESET = 0, PYB_SLP_HARD_RESET, PYB_SLP_WDT_RESET, PYB_SLP_HIB_RESET, PYB_SLP_SOFT_RESET } pybsleep_reset_cause_t; typedef enum { PYB_SLP_WAKED_PWRON = 0, PYB_SLP_WAKED_BY_WLAN, PYB_SLP_WAKED_BY_GPIO, PYB_SLP_WAKED_BY_RTC } pybsleep_wake_reason_t; typedef void (*WakeUpCB_t)(const mp_obj_t self); /****************************************************************************** DECLARE FUNCTIONS ******************************************************************************/ void pyb_sleep_pre_init (void); void pyb_sleep_init0 (void); void pyb_sleep_signal_soft_reset (void); void pyb_sleep_add (const mp_obj_t obj, WakeUpCB_t wakeup); void pyb_sleep_remove (const mp_obj_t obj); void pyb_sleep_set_gpio_lpds_callback (mp_obj_t cb_obj); void pyb_sleep_set_wlan_obj (mp_obj_t wlan_obj); void pyb_sleep_set_rtc_obj (mp_obj_t rtc_obj); void pyb_sleep_sleep (void); void pyb_sleep_deepsleep (void); pybsleep_reset_cause_t pyb_sleep_get_reset_cause (void); pybsleep_wake_reason_t pyb_sleep_get_wake_reason (void); #endif // MICROPY_INCLUDED_CC3200_MODS_PYBSLEEP_H micropython-1.12/ports/cc3200/mods/pybspi.c000066400000000000000000000322131357706137100205000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mperrno.h" #include "bufhelper.h" #include "inc/hw_types.h" #include "inc/hw_mcspi.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "pin.h" #include "prcm.h" #include "spi.h" #include "pybspi.h" #include "mpexception.h" #include "pybsleep.h" #include "pybpin.h" #include "pins.h" /// \moduleref pyb /// \class SPI - a master-driven serial protocol /****************************************************************************** DEFINE TYPES ******************************************************************************/ typedef struct _pyb_spi_obj_t { mp_obj_base_t base; uint baudrate; uint config; byte polarity; byte phase; byte submode; byte wlen; } pyb_spi_obj_t; /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define PYBSPI_FIRST_BIT_MSB 0 /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC pyb_spi_obj_t pyb_spi_obj = {.baudrate = 0}; STATIC const mp_obj_t pyb_spi_def_pin[3] = {&pin_GP14, &pin_GP16, &pin_GP30}; /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ // only master mode is available for the moment STATIC void pybspi_init (const pyb_spi_obj_t *self) { // enable the peripheral clock MAP_PRCMPeripheralClkEnable(PRCM_GSPI, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); MAP_PRCMPeripheralReset(PRCM_GSPI); MAP_SPIReset(GSPI_BASE); // configure the interface (only master mode supported) MAP_SPIConfigSetExpClk (GSPI_BASE, MAP_PRCMPeripheralClockGet(PRCM_GSPI), self->baudrate, SPI_MODE_MASTER, self->submode, self->config); // enable the interface MAP_SPIEnable(GSPI_BASE); } STATIC void pybspi_tx (pyb_spi_obj_t *self, const void *data) { uint32_t txdata; switch (self->wlen) { case 1: txdata = (uint8_t)(*(char *)data); break; case 2: txdata = (uint16_t)(*(uint16_t *)data); break; case 4: txdata = (uint32_t)(*(uint32_t *)data); break; default: return; } MAP_SPIDataPut (GSPI_BASE, txdata); } STATIC void pybspi_rx (pyb_spi_obj_t *self, void *data) { uint32_t rxdata; MAP_SPIDataGet (GSPI_BASE, &rxdata); if (data) { switch (self->wlen) { case 1: *(char *)data = rxdata; break; case 2: *(uint16_t *)data = rxdata; break; case 4: *(uint32_t *)data = rxdata; break; default: return; } } } STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len, uint32_t *txchar) { if (!self->baudrate) { mp_raise_OSError(MP_EPERM); } // send and receive the data MAP_SPICSEnable(GSPI_BASE); for (int i = 0; i < len; i += self->wlen) { pybspi_tx(self, txdata ? (const void *)&txdata[i] : txchar); pybspi_rx(self, rxdata ? (void *)&rxdata[i] : NULL); } MAP_SPICSDisable(GSPI_BASE); } /******************************************************************************/ /* MicroPython bindings */ /******************************************************************************/ STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_spi_obj_t *self = self_in; if (self->baudrate > 0) { mp_printf(print, "SPI(0, baudrate=%u, bits=%u, polarity=%u, phase=%u, firstbit=SPI.MSB)", self->baudrate, (self->wlen * 8), self->polarity, self->phase); } else { mp_print_str(print, "SPI(0)"); } } STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, const mp_arg_val_t *args) { uint bits; switch (args[1].u_int) { case 8: bits = SPI_WL_8; break; case 16: bits = SPI_WL_16; break; case 32: bits = SPI_WL_32; break; default: goto invalid_args; break; } uint polarity = args[2].u_int; uint phase = args[3].u_int; if (polarity > 1 || phase > 1) { goto invalid_args; } uint firstbit = args[4].u_int; if (firstbit != PYBSPI_FIRST_BIT_MSB) { goto invalid_args; } // build the configuration self->baudrate = args[0].u_int; self->wlen = args[1].u_int >> 3; self->config = bits | SPI_CS_ACTIVELOW | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF; self->polarity = polarity; self->phase = phase; self->submode = (polarity << 1) | phase; // assign the pins mp_obj_t pins_o = args[5].u_obj; if (pins_o != mp_const_none) { mp_obj_t *pins; if (pins_o == MP_OBJ_NULL) { // use the default pins pins = (mp_obj_t *)pyb_spi_def_pin; } else { mp_obj_get_array_fixed_n(pins_o, 3, &pins); } pin_assign_pins_af (pins, 3, PIN_TYPE_STD_PU, PIN_FN_SPI, 0); } // init the bus pybspi_init((const pyb_spi_obj_t *)self); // register it with the sleep module pyb_sleep_add((const mp_obj_t)self, (WakeUpCB_t)pybspi_init); return mp_const_none; invalid_args: mp_raise_ValueError(mpexception_value_invalid_arguments); } static const mp_arg_t pyb_spi_init_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, // 1MHz { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_FIRST_BIT_MSB} }, { MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); mp_arg_val_t args[MP_ARRAY_SIZE(pyb_spi_init_args)]; mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_spi_init_args, args); // check the peripheral id if (args[0].u_int != 0) { mp_raise_OSError(MP_ENODEV); } // setup the object pyb_spi_obj_t *self = &pyb_spi_obj; self->base.type = &pyb_spi_type; // start the peripheral pyb_spi_init_helper(self, &args[1]); return self; } STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_spi_init_args) - 1]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_spi_init_args[1], args); return pyb_spi_init_helper(pos_args[0], args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init); /// \method deinit() /// Turn off the spi bus. STATIC mp_obj_t pyb_spi_deinit(mp_obj_t self_in) { // disable the peripheral MAP_SPIDisable(GSPI_BASE); MAP_PRCMPeripheralClkDisable(PRCM_GSPI, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // invalidate the baudrate pyb_spi_obj.baudrate = 0; // unregister it with the sleep module pyb_sleep_remove((const mp_obj_t)self_in); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_spi_deinit_obj, pyb_spi_deinit); STATIC mp_obj_t pyb_spi_write (mp_obj_t self_in, mp_obj_t buf) { // parse args pyb_spi_obj_t *self = self_in; // get the buffer to send from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(buf, &bufinfo, data); // just send pybspi_transfer(self, (const char *)bufinfo.buf, NULL, bufinfo.len, NULL); // return the number of bytes written return mp_obj_new_int(bufinfo.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write); STATIC mp_obj_t pyb_spi_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_write, MP_ARG_INT, {.u_int = 0x00} }, }; // parse args pyb_spi_obj_t *self = pos_args[0]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args); // get the buffer to receive into vstr_t vstr; pyb_buf_get_for_recv(args[0].u_obj, &vstr); // just receive uint32_t write = args[1].u_int; pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write); // return the received data return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read); STATIC mp_obj_t pyb_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_write, MP_ARG_INT, {.u_int = 0x00} }, }; // parse args pyb_spi_obj_t *self = pos_args[0]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args); // get the buffer to receive into vstr_t vstr; pyb_buf_get_for_recv(args[0].u_obj, &vstr); // just receive uint32_t write = args[1].u_int; pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write); // return the number of bytes received return mp_obj_new_int(vstr.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_readinto_obj, 1, pyb_spi_readinto); STATIC mp_obj_t pyb_spi_write_readinto (mp_obj_t self, mp_obj_t writebuf, mp_obj_t readbuf) { // get buffers to write from/read to mp_buffer_info_t bufinfo_write; uint8_t data_send[1]; mp_buffer_info_t bufinfo_read; if (writebuf == readbuf) { // same object for writing and reading, it must be a r/w buffer mp_get_buffer_raise(writebuf, &bufinfo_write, MP_BUFFER_RW); bufinfo_read = bufinfo_write; } else { // get the buffer to write from pyb_buf_get_for_send(writebuf, &bufinfo_write, data_send); // get the read buffer mp_get_buffer_raise(readbuf, &bufinfo_read, MP_BUFFER_WRITE); if (bufinfo_read.len != bufinfo_write.len) { mp_raise_ValueError(mpexception_value_invalid_arguments); } } // send and receive pybspi_transfer(self, (const char *)bufinfo_write.buf, bufinfo_read.buf, bufinfo_write.len, NULL); // return the number of transferred bytes return mp_obj_new_int(bufinfo_write.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_spi_write_readinto_obj, pyb_spi_write_readinto); STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_spi_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_spi_write_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_spi_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&pyb_spi_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&pyb_spi_write_readinto_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(PYBSPI_FIRST_BIT_MSB) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table); const mp_obj_type_t pyb_spi_type = { { &mp_type_type }, .name = MP_QSTR_SPI, .print = pyb_spi_print, .make_new = pyb_spi_make_new, .locals_dict = (mp_obj_t)&pyb_spi_locals_dict, }; micropython-1.12/ports/cc3200/mods/pybspi.h000066400000000000000000000026531357706137100205120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBSPI_H #define MICROPY_INCLUDED_CC3200_MODS_PYBSPI_H extern const mp_obj_type_t pyb_spi_type; #endif // MICROPY_INCLUDED_CC3200_MODS_PYBSPI_H micropython-1.12/ports/cc3200/mods/pybtimer.c000066400000000000000000000656071357706137100210420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/gc.h" #include "py/mperrno.h" #include "py/mphal.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_timer.h" #include "rom_map.h" #include "interrupt.h" #include "prcm.h" #include "timer.h" #include "pin.h" #include "pybtimer.h" #include "pybpin.h" #include "pins.h" #include "mpirq.h" #include "pybsleep.h" #include "mpexception.h" /// \moduleref pyb /// \class Timer - generate periodic events, count events, and create PWM signals. /// /// Each timer consists of a counter that counts up at a certain rate. The rate /// at which it counts is the peripheral clock frequency (in Hz) divided by the /// timer prescaler. When the counter reaches the timer period it triggers an /// event, and the counter resets back to zero. By using the irq method, /// the timer event can call a Python function. /****************************************************************************** DECLARE PRIVATE CONSTANTS ******************************************************************************/ #define PYBTIMER_NUM_TIMERS (4) #define PYBTIMER_POLARITY_POS (0x01) #define PYBTIMER_POLARITY_NEG (0x02) #define PYBTIMER_TIMEOUT_TRIGGER (0x01) #define PYBTIMER_MATCH_TRIGGER (0x02) #define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ /****************************************************************************** DEFINE PRIVATE TYPES ******************************************************************************/ typedef struct _pyb_timer_obj_t { mp_obj_base_t base; uint32_t timer; uint32_t config; uint16_t irq_trigger; uint16_t irq_flags; uint8_t peripheral; uint8_t id; } pyb_timer_obj_t; typedef struct _pyb_timer_channel_obj_t { mp_obj_base_t base; struct _pyb_timer_obj_t *timer; uint32_t frequency; uint32_t period; uint16_t channel; uint16_t duty_cycle; uint8_t polarity; } pyb_timer_channel_obj_t; /****************************************************************************** DEFINE PRIVATE DATA ******************************************************************************/ STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods; STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_BASE, .peripheral = PRCM_TIMERA0}, {.timer = TIMERA1_BASE, .peripheral = PRCM_TIMERA1}, {.timer = TIMERA2_BASE, .peripheral = PRCM_TIMERA2}, {.timer = TIMERA3_BASE, .peripheral = PRCM_TIMERA3}}; STATIC const mp_obj_type_t pyb_timer_channel_type; STATIC const mp_obj_t pyb_timer_pwm_pin[8] = {&pin_GP24, MP_OBJ_NULL, &pin_GP25, MP_OBJ_NULL, MP_OBJ_NULL, &pin_GP9, &pin_GP10, &pin_GP11}; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC mp_obj_t pyb_timer_channel_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC void timer_disable (pyb_timer_obj_t *tim); STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch); STATIC void TIMER0AIntHandler(void); STATIC void TIMER0BIntHandler(void); STATIC void TIMER1AIntHandler(void); STATIC void TIMER1BIntHandler(void); STATIC void TIMER2AIntHandler(void); STATIC void TIMER2BIntHandler(void); STATIC void TIMER3AIntHandler(void); STATIC void TIMER3BIntHandler(void); /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void timer_init0 (void) { mp_obj_list_init(&MP_STATE_PORT(pyb_timer_channel_obj_list), 0); } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void pyb_timer_channel_irq_enable (mp_obj_t self_in) { pyb_timer_channel_obj_t *self = self_in; MAP_TimerIntClear(self->timer->timer, self->timer->irq_trigger & self->channel); MAP_TimerIntEnable(self->timer->timer, self->timer->irq_trigger & self->channel); } STATIC void pyb_timer_channel_irq_disable (mp_obj_t self_in) { pyb_timer_channel_obj_t *self = self_in; MAP_TimerIntDisable(self->timer->timer, self->timer->irq_trigger & self->channel); } STATIC int pyb_timer_channel_irq_flags (mp_obj_t self_in) { pyb_timer_channel_obj_t *self = self_in; return self->timer->irq_flags; } STATIC pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) { for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_timer_channel_obj_list).len; i++) { pyb_timer_channel_obj_t *ch = ((pyb_timer_channel_obj_t *)(MP_STATE_PORT(pyb_timer_channel_obj_list).items[i])); // any 32-bit timer must be matched by any of its 16-bit versions if (ch->timer->timer == timer && ((ch->channel & TIMER_A) == channel_n || (ch->channel & TIMER_B) == channel_n)) { return ch; } } return MP_OBJ_NULL; } STATIC void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) { pyb_timer_channel_obj_t *channel; if ((channel = pyb_timer_channel_find(ch->timer->timer, ch->channel))) { mp_obj_list_remove(&MP_STATE_PORT(pyb_timer_channel_obj_list), channel); // unregister it with the sleep module pyb_sleep_remove((const mp_obj_t)channel); } } STATIC void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) { // remove it in case it already exists pyb_timer_channel_remove(ch); mp_obj_list_append(&MP_STATE_PORT(pyb_timer_channel_obj_list), ch); // register it with the sleep module pyb_sleep_add((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init); } STATIC void timer_disable (pyb_timer_obj_t *tim) { // disable all timers and it's interrupts MAP_TimerDisable(tim->timer, TIMER_A | TIMER_B); MAP_TimerIntDisable(tim->timer, tim->irq_trigger); MAP_TimerIntClear(tim->timer, tim->irq_trigger); pyb_timer_channel_obj_t *ch; // disable its channels if ((ch = pyb_timer_channel_find (tim->timer, TIMER_A))) { pyb_sleep_remove(ch); } if ((ch = pyb_timer_channel_find (tim->timer, TIMER_B))) { pyb_sleep_remove(ch); } MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); } // computes prescaler period and match value so timer triggers at freq-Hz STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t *ch, uint32_t *period_out, uint32_t *match_out) { uint32_t maxcount = (ch->channel == (TIMER_A | TIMER_B)) ? 0xFFFFFFFF : 0xFFFF; uint32_t prescaler; uint32_t period_c = (ch->frequency > 0) ? PYBTIMER_SRC_FREQ_HZ / ch->frequency : ((PYBTIMER_SRC_FREQ_HZ / 1000000) * ch->period); period_c = MAX(1, period_c) - 1; if (period_c == 0) { goto error; } prescaler = period_c >> 16; // The prescaler is an extension of the timer counter *period_out = period_c; if (prescaler > 0xFF && maxcount == 0xFFFF) { goto error; } // check limit values for the duty cycle if (ch->duty_cycle == 0) { *match_out = period_c - 1; } else { if (period_c > 0xFFFF) { uint32_t match = (period_c * 100) / 10000; *match_out = period_c - ((match * ch->duty_cycle) / 100); } else { *match_out = period_c - ((period_c * ch->duty_cycle) / 10000); } } return prescaler; error: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC void timer_init (pyb_timer_obj_t *tim) { MAP_PRCMPeripheralClkEnable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); MAP_PRCMPeripheralReset(tim->peripheral); MAP_TimerConfigure(tim->timer, tim->config); } STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch) { // calculate the period, the prescaler and the match value uint32_t period_c; uint32_t match; uint32_t prescaler = compute_prescaler_period_and_match_value(ch, &period_c, &match); // set the prescaler MAP_TimerPrescaleSet(ch->timer->timer, ch->channel, (prescaler < 0xFF) ? prescaler : 0); // set the load value MAP_TimerLoadSet(ch->timer->timer, ch->channel, period_c); // configure the pwm if we are in such mode if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) { // invert the timer output if required MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false); // set the match value (which is simply the duty cycle translated to ticks) MAP_TimerMatchSet(ch->timer->timer, ch->channel, match); MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16); } #ifdef DEBUG // stall the timer when the processor is halted while debugging MAP_TimerControlStall(ch->timer->timer, ch->channel, true); #endif // now enable the timer channel MAP_TimerEnable(ch->timer->timer, ch->channel); } /******************************************************************************/ /* MicroPython bindings */ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_timer_obj_t *tim = self_in; uint32_t mode = tim->config & 0xFF; // timer mode qstr mode_qst = MP_QSTR_PWM; switch(mode) { case TIMER_CFG_A_ONE_SHOT_UP: mode_qst = MP_QSTR_ONE_SHOT; break; case TIMER_CFG_A_PERIODIC_UP: mode_qst = MP_QSTR_PERIODIC; break; default: break; } mp_printf(print, "Timer(%u, mode=Timer.%q)", tim->id, mode_qst); } STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // check the mode uint32_t _mode = args[0].u_int; if (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP && _mode != TIMER_CFG_A_PWM) { goto error; } // check the width if (args[1].u_int != 16 && args[1].u_int != 32) { goto error; } bool is16bit = (args[1].u_int == 16); if (!is16bit && _mode == TIMER_CFG_A_PWM) { // 32-bit mode is only available when in free running modes goto error; } tim->config = is16bit ? ((_mode | (_mode << 8)) | TIMER_CFG_SPLIT_PAIR) : _mode; timer_init(tim); // register it with the sleep module pyb_sleep_add ((const mp_obj_t)tim, (WakeUpCB_t)timer_init); return mp_const_none; error: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // create a new Timer object int32_t timer_idx = mp_obj_get_int(args[0]); if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) { mp_raise_OSError(MP_ENODEV); } pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx]; tim->base.type = &pyb_timer_type; tim->id = timer_idx; if (n_args > 1 || n_kw > 0) { // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_timer_init_helper(tim, n_args - 1, args + 1, &kw_args); } return (mp_obj_t)tim; } STATIC mp_obj_t pyb_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_timer_init_helper(args[0], n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init); STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) { pyb_timer_obj_t *self = self_in; timer_disable(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit); STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBTIMER_POLARITY_POS} }, { MP_QSTR_duty_cycle, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; pyb_timer_obj_t *tim = pos_args[0]; mp_int_t channel_n = mp_obj_get_int(pos_args[1]); // verify that the timer has been already initialized if (!tim->config) { mp_raise_OSError(MP_EPERM); } if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) { // invalid channel goto error; } if (channel_n == (TIMER_A | TIMER_B) && (tim->config & TIMER_CFG_SPLIT_PAIR)) { // 32-bit channel selected when the timer is in 16-bit mode goto error; } // if only the channel number is given return the previously // allocated channel (or None if no previous channel) if (n_args == 2 && kw_args->used == 0) { pyb_timer_channel_obj_t *ch; if ((ch = pyb_timer_channel_find(tim->timer, channel_n))) { return ch; } return mp_const_none; } // parse the arguments mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // throw an exception if both frequency and period are given if (args[0].u_int != 0 && args[1].u_int != 0) { goto error; } // check that at least one of them has a valid value if (args[0].u_int <= 0 && args[1].u_int <= 0) { goto error; } // check that the polarity is not 'both' in pwm mode if ((tim->config & TIMER_A) == TIMER_CFG_A_PWM && args[2].u_int == (PYBTIMER_POLARITY_POS | PYBTIMER_POLARITY_NEG)) { goto error; } // allocate a new timer channel pyb_timer_channel_obj_t *ch = m_new_obj(pyb_timer_channel_obj_t); ch->base.type = &pyb_timer_channel_type; ch->timer = tim; ch->channel = channel_n; // get the frequency the polarity and the duty cycle ch->frequency = args[0].u_int; ch->period = args[1].u_int; ch->polarity = args[2].u_int; ch->duty_cycle = MIN(10000, MAX(0, args[3].u_int)); timer_channel_init(ch); // assign the pin if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) { uint32_t ch_idx = (ch->channel == TIMER_A) ? 0 : 1; // use the default pin if available mp_obj_t pin_o = (mp_obj_t)pyb_timer_pwm_pin[(ch->timer->id * 2) + ch_idx]; if (pin_o != MP_OBJ_NULL) { pin_obj_t *pin = pin_find(pin_o); pin_config (pin, pin_find_af_index(pin, PIN_FN_TIM, ch->timer->id, PIN_TYPE_TIM_PWM), 0, PIN_TYPE_STD, -1, PIN_STRENGTH_4MA); } } // add the timer to the list pyb_timer_channel_add(ch); return ch; error: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel); STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_timer_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_timer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&pyb_timer_channel_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_A), MP_ROM_INT(TIMER_A) }, { MP_ROM_QSTR(MP_QSTR_B), MP_ROM_INT(TIMER_B) }, { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_CFG_A_ONE_SHOT_UP) }, { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_CFG_A_PERIODIC_UP) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_INT(TIMER_CFG_A_PWM) }, { MP_ROM_QSTR(MP_QSTR_POSITIVE), MP_ROM_INT(PYBTIMER_POLARITY_POS) }, { MP_ROM_QSTR(MP_QSTR_NEGATIVE), MP_ROM_INT(PYBTIMER_POLARITY_NEG) }, { MP_ROM_QSTR(MP_QSTR_TIMEOUT), MP_ROM_INT(PYBTIMER_TIMEOUT_TRIGGER) }, { MP_ROM_QSTR(MP_QSTR_MATCH), MP_ROM_INT(PYBTIMER_MATCH_TRIGGER) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table); const mp_obj_type_t pyb_timer_type = { { &mp_type_type }, .name = MP_QSTR_Timer, .print = pyb_timer_print, .make_new = pyb_timer_make_new, .locals_dict = (mp_obj_t)&pyb_timer_locals_dict, }; STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = { .init = pyb_timer_channel_irq, .enable = pyb_timer_channel_irq_enable, .disable = pyb_timer_channel_irq_disable, .flags = pyb_timer_channel_irq_flags, }; STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) { pyb_timer_channel_obj_t *self; uint32_t status; if ((self = pyb_timer_channel_find(timer, channel))) { status = MAP_TimerIntStatus(self->timer->timer, true) & self->channel; MAP_TimerIntClear(self->timer->timer, status); mp_irq_handler(mp_irq_find(self)); } } STATIC void TIMER0AIntHandler(void) { TIMERGenericIntHandler(TIMERA0_BASE, TIMER_A); } STATIC void TIMER0BIntHandler(void) { TIMERGenericIntHandler(TIMERA0_BASE, TIMER_B); } STATIC void TIMER1AIntHandler(void) { TIMERGenericIntHandler(TIMERA1_BASE, TIMER_A); } STATIC void TIMER1BIntHandler(void) { TIMERGenericIntHandler(TIMERA1_BASE, TIMER_B); } STATIC void TIMER2AIntHandler(void) { TIMERGenericIntHandler(TIMERA2_BASE, TIMER_A); } STATIC void TIMER2BIntHandler(void) { TIMERGenericIntHandler(TIMERA2_BASE, TIMER_B); } STATIC void TIMER3AIntHandler(void) { TIMERGenericIntHandler(TIMERA3_BASE, TIMER_A); } STATIC void TIMER3BIntHandler(void) { TIMERGenericIntHandler(TIMERA3_BASE, TIMER_B); } STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_timer_channel_obj_t *ch = self_in; char *ch_id = "AB"; // timer channel if (ch->channel == TIMER_A) { ch_id = "A"; } else if (ch->channel == TIMER_B) { ch_id = "B"; } mp_printf(print, "timer.channel(Timer.%s, %q=%u", ch_id, MP_QSTR_freq, ch->frequency); uint32_t mode = ch->timer->config & 0xFF; if (mode == TIMER_CFG_A_PWM) { mp_printf(print, ", %q=Timer.", MP_QSTR_polarity); switch (ch->polarity) { case PYBTIMER_POLARITY_POS: mp_printf(print, "POSITIVE"); break; case PYBTIMER_POLARITY_NEG: mp_printf(print, "NEGATIVE"); break; default: mp_printf(print, "BOTH"); break; } mp_printf(print, ", %q=%u.%02u", MP_QSTR_duty_cycle, ch->duty_cycle / 100, ch->duty_cycle % 100); } mp_printf(print, ")"); } STATIC mp_obj_t pyb_timer_channel_freq(size_t n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *ch = args[0]; if (n_args == 1) { // get return mp_obj_new_int(ch->frequency); } else { // set int32_t _frequency = mp_obj_get_int(args[1]); if (_frequency <= 0) { mp_raise_ValueError(mpexception_value_invalid_arguments); } ch->frequency = _frequency; ch->period = 1000000 / _frequency; timer_channel_init(ch); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_freq_obj, 1, 2, pyb_timer_channel_freq); STATIC mp_obj_t pyb_timer_channel_period(size_t n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *ch = args[0]; if (n_args == 1) { // get return mp_obj_new_int(ch->period); } else { // set int32_t _period = mp_obj_get_int(args[1]); if (_period <= 0) { mp_raise_ValueError(mpexception_value_invalid_arguments); } ch->period = _period; ch->frequency = 1000000 / _period; timer_channel_init(ch); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_period_obj, 1, 2, pyb_timer_channel_period); STATIC mp_obj_t pyb_timer_channel_duty_cycle(size_t n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *ch = args[0]; if (n_args == 1) { // get return mp_obj_new_int(ch->duty_cycle); } else { // duty cycle must be converted from percentage to ticks // calculate the period, the prescaler and the match value uint32_t period_c; uint32_t match; ch->duty_cycle = MIN(10000, MAX(0, mp_obj_get_int(args[1]))); compute_prescaler_period_and_match_value(ch, &period_c, &match); if (n_args == 3) { // set the new polarity if requested ch->polarity = mp_obj_get_int(args[2]); MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false); } MAP_TimerMatchSet(ch->timer->timer, ch->channel, match); MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle); STATIC mp_obj_t pyb_timer_channel_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); pyb_timer_channel_obj_t *ch = pos_args[0]; // convert the priority to the correct value uint priority = mp_irq_translate_priority (args[1].u_int); // validate the power mode uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj); if (pwrmode != PYB_PWR_MODE_ACTIVE) { goto invalid_args; } // get the trigger uint trigger = mp_obj_get_int(args[0].u_obj); // disable the callback first pyb_timer_channel_irq_disable(ch); uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0; uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A); switch (_config) { case TIMER_CFG_A_ONE_SHOT_UP: case TIMER_CFG_A_PERIODIC_UP: ch->timer->irq_trigger |= TIMER_TIMA_TIMEOUT << shift; if (trigger != PYBTIMER_TIMEOUT_TRIGGER) { goto invalid_args; } break; case TIMER_CFG_A_PWM: // special case for the PWM match interrupt ch->timer->irq_trigger |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH; if (trigger != PYBTIMER_MATCH_TRIGGER) { goto invalid_args; } break; default: break; } // special case for a 32-bit timer if (ch->channel == (TIMER_A | TIMER_B)) { ch->timer->irq_trigger |= (ch->timer->irq_trigger << 8); } void (*pfnHandler)(void); uint32_t intregister; switch (ch->timer->timer) { case TIMERA0_BASE: if (ch->channel == TIMER_B) { pfnHandler = &TIMER0BIntHandler; intregister = INT_TIMERA0B; } else { pfnHandler = &TIMER0AIntHandler; intregister = INT_TIMERA0A; } break; case TIMERA1_BASE: if (ch->channel == TIMER_B) { pfnHandler = &TIMER1BIntHandler; intregister = INT_TIMERA1B; } else { pfnHandler = &TIMER1AIntHandler; intregister = INT_TIMERA1A; } break; case TIMERA2_BASE: if (ch->channel == TIMER_B) { pfnHandler = &TIMER2BIntHandler; intregister = INT_TIMERA2B; } else { pfnHandler = &TIMER2AIntHandler; intregister = INT_TIMERA2A; } break; default: if (ch->channel == TIMER_B) { pfnHandler = &TIMER3BIntHandler; intregister = INT_TIMERA3B; } else { pfnHandler = &TIMER3AIntHandler; intregister = INT_TIMERA3A; } break; } // register the interrupt and configure the priority MAP_IntPrioritySet(intregister, priority); MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler); // create the callback mp_obj_t _irq = mp_irq_new (ch, args[2].u_obj, &pyb_timer_channel_irq_methods); // enable the callback before returning pyb_timer_channel_irq_enable(ch); return _irq; invalid_args: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_irq_obj, 1, pyb_timer_channel_irq); STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_timer_channel_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&pyb_timer_channel_period_obj) }, { MP_ROM_QSTR(MP_QSTR_duty_cycle), MP_ROM_PTR(&pyb_timer_channel_duty_cycle_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_timer_channel_irq_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table); STATIC const mp_obj_type_t pyb_timer_channel_type = { { &mp_type_type }, .name = MP_QSTR_TimerChannel, .print = pyb_timer_channel_print, .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict, }; micropython-1.12/ports/cc3200/mods/pybtimer.h000066400000000000000000000035001357706137100210270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBTIMER_H #define MICROPY_INCLUDED_CC3200_MODS_PYBTIMER_H /****************************************************************************** DECLARE EXPORTED DATA ******************************************************************************/ extern const mp_obj_type_t pyb_timer_type; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ void timer_init0 (void); #endif // MICROPY_INCLUDED_CC3200_MODS_PYBTIMER_H micropython-1.12/ports/cc3200/mods/pybuart.c000066400000000000000000000565261357706137100206750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/objlist.h" #include "py/stream.h" #include "py/mphal.h" #include "lib/utils/interrupt_char.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_uart.h" #include "rom_map.h" #include "interrupt.h" #include "prcm.h" #include "uart.h" #include "pybuart.h" #include "mpirq.h" #include "pybsleep.h" #include "mpexception.h" #include "osi.h" #include "utils.h" #include "pin.h" #include "pybpin.h" #include "pins.h" #include "moduos.h" /// \moduleref pyb /// \class UART - duplex serial communication bus /****************************************************************************** DEFINE CONSTANTS *******-***********************************************************************/ #define PYBUART_FRAME_TIME_US(baud) ((11 * 1000000) / baud) #define PYBUART_2_FRAMES_TIME_US(baud) (PYBUART_FRAME_TIME_US(baud) * 2) #define PYBUART_RX_TIMEOUT_US(baud) (PYBUART_2_FRAMES_TIME_US(baud) * 8) // we need at least characters in the FIFO #define PYBUART_TX_WAIT_US(baud) ((PYBUART_FRAME_TIME_US(baud)) + 1) #define PYBUART_TX_MAX_TIMEOUT_MS (5) #define PYBUART_RX_BUFFER_LEN (256) // interrupt triggers #define UART_TRIGGER_RX_ANY (0x01) #define UART_TRIGGER_RX_HALF (0x02) #define UART_TRIGGER_RX_FULL (0x04) #define UART_TRIGGER_TX_DONE (0x08) /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void uart_init (pyb_uart_obj_t *self); STATIC bool uart_rx_wait (pyb_uart_obj_t *self); STATIC void uart_check_init(pyb_uart_obj_t *self); STATIC mp_obj_t uart_irq_new (pyb_uart_obj_t *self, byte trigger, mp_int_t priority, mp_obj_t handler); STATIC void UARTGenericIntHandler(uint32_t uart_id); STATIC void UART0IntHandler(void); STATIC void UART1IntHandler(void); STATIC void uart_irq_enable (mp_obj_t self_in); STATIC void uart_irq_disable (mp_obj_t self_in); /****************************************************************************** DEFINE PRIVATE TYPES ******************************************************************************/ struct _pyb_uart_obj_t { mp_obj_base_t base; pyb_uart_id_t uart_id; uint reg; uint baudrate; uint config; uint flowcontrol; byte *read_buf; // read buffer pointer volatile uint16_t read_buf_head; // indexes first empty slot uint16_t read_buf_tail; // indexes first full slot (not full if equals head) byte peripheral; byte irq_trigger; bool irq_enabled; byte irq_flags; }; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS] = { {.reg = UARTA0_BASE, .baudrate = 0, .read_buf = NULL, .peripheral = PRCM_UARTA0}, {.reg = UARTA1_BASE, .baudrate = 0, .read_buf = NULL, .peripheral = PRCM_UARTA1} }; STATIC const mp_irq_methods_t uart_irq_methods; STATIC const mp_obj_t pyb_uart_def_pin[PYB_NUM_UARTS][2] = { {&pin_GP1, &pin_GP2}, {&pin_GP3, &pin_GP4} }; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void uart_init0 (void) { // save references of the UART objects, to prevent the read buffers from being trashed by the gc MP_STATE_PORT(pyb_uart_objs)[0] = &pyb_uart_obj[0]; MP_STATE_PORT(pyb_uart_objs)[1] = &pyb_uart_obj[1]; } uint32_t uart_rx_any(pyb_uart_obj_t *self) { if (self->read_buf_tail != self->read_buf_head) { // buffering via irq return (self->read_buf_head > self->read_buf_tail) ? self->read_buf_head - self->read_buf_tail : PYBUART_RX_BUFFER_LEN - self->read_buf_tail + self->read_buf_head; } return MAP_UARTCharsAvail(self->reg) ? 1 : 0; } int uart_rx_char(pyb_uart_obj_t *self) { if (self->read_buf_tail != self->read_buf_head) { // buffering via irq int data = self->read_buf[self->read_buf_tail]; self->read_buf_tail = (self->read_buf_tail + 1) % PYBUART_RX_BUFFER_LEN; return data; } else { // no buffering return MAP_UARTCharGetNonBlocking(self->reg); } } bool uart_tx_char(pyb_uart_obj_t *self, int c) { uint32_t timeout = 0; while (!MAP_UARTCharPutNonBlocking(self->reg, c)) { if (timeout++ > ((PYBUART_TX_MAX_TIMEOUT_MS * 1000) / PYBUART_TX_WAIT_US(self->baudrate))) { return false; } UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_TX_WAIT_US(self->baudrate))); } return true; } bool uart_tx_strn(pyb_uart_obj_t *self, const char *str, uint len) { for (const char *top = str + len; str < top; str++) { if (!uart_tx_char(self, *str)) { return false; } } return true; } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ // assumes init parameters have been set up correctly STATIC void uart_init (pyb_uart_obj_t *self) { // Enable the peripheral clock MAP_PRCMPeripheralClkEnable(self->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // Reset the uart MAP_PRCMPeripheralReset(self->peripheral); // re-allocate the read buffer after resetting the uart (which automatically disables any irqs) self->read_buf_head = 0; self->read_buf_tail = 0; self->read_buf = MP_OBJ_NULL; // free the read buffer before allocating again self->read_buf = m_new(byte, PYBUART_RX_BUFFER_LEN); // Initialize the UART MAP_UARTConfigSetExpClk(self->reg, MAP_PRCMPeripheralClockGet(self->peripheral), self->baudrate, self->config); // Enable the FIFO MAP_UARTFIFOEnable(self->reg); // Configure the FIFO interrupt levels MAP_UARTFIFOLevelSet(self->reg, UART_FIFO_TX4_8, UART_FIFO_RX4_8); // Configure the flow control mode UARTFlowControlSet(self->reg, self->flowcontrol); } // Waits at most timeout microseconds for at least 1 char to become ready for // reading (from buf or for direct reading). // Returns true if something available, false if not. STATIC bool uart_rx_wait (pyb_uart_obj_t *self) { int timeout = PYBUART_RX_TIMEOUT_US(self->baudrate); for ( ; ; ) { if (uart_rx_any(self)) { return true; // we have at least 1 char ready for reading } if (timeout > 0) { UtilsDelay(UTILS_DELAY_US_TO_COUNT(1)); timeout--; } else { return false; } } } STATIC mp_obj_t uart_irq_new (pyb_uart_obj_t *self, byte trigger, mp_int_t priority, mp_obj_t handler) { // disable the uart interrupts before updating anything uart_irq_disable (self); if (self->uart_id == PYB_UART_0) { MAP_IntPrioritySet(INT_UARTA0, priority); MAP_UARTIntRegister(self->reg, UART0IntHandler); } else { MAP_IntPrioritySet(INT_UARTA1, priority); MAP_UARTIntRegister(self->reg, UART1IntHandler); } // create the callback mp_obj_t _irq = mp_irq_new ((mp_obj_t)self, handler, &uart_irq_methods); // enable the interrupts now self->irq_trigger = trigger; uart_irq_enable (self); return _irq; } STATIC void UARTGenericIntHandler(uint32_t uart_id) { pyb_uart_obj_t *self; uint32_t status; self = &pyb_uart_obj[uart_id]; status = MAP_UARTIntStatus(self->reg, true); // receive interrupt if (status & (UART_INT_RX | UART_INT_RT)) { // set the flags self->irq_flags = UART_TRIGGER_RX_ANY; MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT); while (UARTCharsAvail(self->reg)) { int data = MAP_UARTCharGetNonBlocking(self->reg); if (MP_STATE_PORT(os_term_dup_obj) && MP_STATE_PORT(os_term_dup_obj)->stream_o == self && data == mp_interrupt_char) { // raise an exception when interrupts are finished mp_keyboard_interrupt(); } else { // there's always a read buffer available uint16_t next_head = (self->read_buf_head + 1) % PYBUART_RX_BUFFER_LEN; if (next_head != self->read_buf_tail) { // only store data if room in buf self->read_buf[self->read_buf_head] = data; self->read_buf_head = next_head; } } } } // check the flags to see if the user handler should be called if ((self->irq_trigger & self->irq_flags) && self->irq_enabled) { // call the user defined handler mp_irq_handler(mp_irq_find(self)); } // clear the flags self->irq_flags = 0; } STATIC void uart_check_init(pyb_uart_obj_t *self) { // not initialized if (!self->baudrate) { mp_raise_OSError(MP_EPERM); } } STATIC void UART0IntHandler(void) { UARTGenericIntHandler(0); } STATIC void UART1IntHandler(void) { UARTGenericIntHandler(1); } STATIC void uart_irq_enable (mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; // check for any of the rx interrupt types if (self->irq_trigger & (UART_TRIGGER_RX_ANY | UART_TRIGGER_RX_HALF | UART_TRIGGER_RX_FULL)) { MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT); MAP_UARTIntEnable(self->reg, UART_INT_RX | UART_INT_RT); } self->irq_enabled = true; } STATIC void uart_irq_disable (mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; self->irq_enabled = false; } STATIC int uart_irq_flags (mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; return self->irq_flags; } /******************************************************************************/ /* MicroPython bindings */ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = self_in; if (self->baudrate > 0) { mp_printf(print, "UART(%u, baudrate=%u, bits=", self->uart_id, self->baudrate); switch (self->config & UART_CONFIG_WLEN_MASK) { case UART_CONFIG_WLEN_5: mp_print_str(print, "5"); break; case UART_CONFIG_WLEN_6: mp_print_str(print, "6"); break; case UART_CONFIG_WLEN_7: mp_print_str(print, "7"); break; case UART_CONFIG_WLEN_8: mp_print_str(print, "8"); break; default: break; } if ((self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_NONE) { mp_print_str(print, ", parity=None"); } else { mp_printf(print, ", parity=UART.%q", (self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? MP_QSTR_EVEN : MP_QSTR_ODD); } mp_printf(print, ", stop=%u)", (self->config & UART_CONFIG_STOP_MASK) == UART_CONFIG_STOP_ONE ? 1 : 2); } else { mp_printf(print, "UART(%u)", self->uart_id); } } STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *args) { // get the baudrate if (args[0].u_int <= 0) { goto error; } uint baudrate = args[0].u_int; uint config; switch (args[1].u_int) { case 5: config = UART_CONFIG_WLEN_5; break; case 6: config = UART_CONFIG_WLEN_6; break; case 7: config = UART_CONFIG_WLEN_7; break; case 8: config = UART_CONFIG_WLEN_8; break; default: goto error; break; } // parity if (args[2].u_obj == mp_const_none) { config |= UART_CONFIG_PAR_NONE; } else { uint parity = mp_obj_get_int(args[2].u_obj); if (parity == 0) { config |= UART_CONFIG_PAR_EVEN; } else if (parity == 1) { config |= UART_CONFIG_PAR_ODD; } else { goto error; } } // stop bits config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO); // assign the pins mp_obj_t pins_o = args[4].u_obj; uint flowcontrol = UART_FLOWCONTROL_NONE; if (pins_o != mp_const_none) { mp_obj_t *pins; size_t n_pins = 2; if (pins_o == MP_OBJ_NULL) { // use the default pins pins = (mp_obj_t *)pyb_uart_def_pin[self->uart_id]; } else { mp_obj_get_array(pins_o, &n_pins, &pins); if (n_pins != 2 && n_pins != 4) { goto error; } if (n_pins == 4) { if (pins[PIN_TYPE_UART_RTS] != mp_const_none && pins[PIN_TYPE_UART_RX] == mp_const_none) { goto error; // RTS pin given in TX only mode } else if (pins[PIN_TYPE_UART_CTS] != mp_const_none && pins[PIN_TYPE_UART_TX] == mp_const_none) { goto error; // CTS pin given in RX only mode } else { if (pins[PIN_TYPE_UART_RTS] != mp_const_none) { flowcontrol |= UART_FLOWCONTROL_RX; } if (pins[PIN_TYPE_UART_CTS] != mp_const_none) { flowcontrol |= UART_FLOWCONTROL_TX; } } } } pin_assign_pins_af (pins, n_pins, PIN_TYPE_STD_PU, PIN_FN_UART, self->uart_id); } self->baudrate = baudrate; self->config = config; self->flowcontrol = flowcontrol; // initialize and enable the uart uart_init (self); // register it with the sleep module pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)uart_init); // enable the callback uart_irq_new (self, UART_TRIGGER_RX_ANY, INT_PRIORITY_LVL_3, mp_const_none); // disable the irq (from the user point of view) uart_irq_disable(self); return mp_const_none; error: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC const mp_arg_t pyb_uart_init_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 9600} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); mp_arg_val_t args[MP_ARRAY_SIZE(pyb_uart_init_args)]; mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_uart_init_args, args); // work out the uart id uint uart_id; if (args[0].u_obj == MP_OBJ_NULL) { if (args[5].u_obj != MP_OBJ_NULL) { mp_obj_t *pins; size_t n_pins = 2; mp_obj_get_array(args[5].u_obj, &n_pins, &pins); // check the Tx pin (or the Rx if Tx is None) if (pins[0] == mp_const_none) { uart_id = pin_find_peripheral_unit(pins[1], PIN_FN_UART, PIN_TYPE_UART_RX); } else { uart_id = pin_find_peripheral_unit(pins[0], PIN_FN_UART, PIN_TYPE_UART_TX); } } else { // default id uart_id = 0; } } else { uart_id = mp_obj_get_int(args[0].u_obj); } if (uart_id > PYB_UART_1) { mp_raise_OSError(MP_ENODEV); } // get the correct uart instance pyb_uart_obj_t *self = &pyb_uart_obj[uart_id]; self->base.type = &pyb_uart_type; self->uart_id = uart_id; // start the peripheral pyb_uart_init_helper(self, &args[1]); return self; } STATIC mp_obj_t pyb_uart_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_uart_init_args) - 1]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_uart_init_args[1], args); return pyb_uart_init_helper(pos_args[0], args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; // unregister it with the sleep module pyb_sleep_remove (self); // invalidate the baudrate self->baudrate = 0; // free the read buffer m_del(byte, self->read_buf, PYBUART_RX_BUFFER_LEN); MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT); MAP_UARTDisable(self->reg); MAP_PRCMPeripheralClkDisable(self->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit); STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; uart_check_init(self); return mp_obj_new_int(uart_rx_any(self)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any); STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; uart_check_init(self); // send a break signal for at least 2 complete frames MAP_UARTBreakCtl(self->reg, true); UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_2_FRAMES_TIME_US(self->baudrate))); MAP_UARTBreakCtl(self->reg, false); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak); /// \method irq(trigger, priority, handler, wake) STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); // check if any parameters were passed pyb_uart_obj_t *self = pos_args[0]; uart_check_init(self); // convert the priority to the correct value uint priority = mp_irq_translate_priority (args[1].u_int); // check the power mode uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj); if (PYB_PWR_MODE_ACTIVE != pwrmode) { goto invalid_args; } // check the trigger uint trigger = mp_obj_get_int(args[0].u_obj); if (!trigger || trigger > (UART_TRIGGER_RX_ANY | UART_TRIGGER_RX_HALF | UART_TRIGGER_RX_FULL | UART_TRIGGER_TX_DONE)) { goto invalid_args; } // register a new callback return uart_irq_new (self, trigger, priority, args[2].u_obj); invalid_args: mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq); STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) }, { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_uart_irq_obj) }, /// \method read([nbytes]) { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, /// \method readline() { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, /// \method readinto(buf[, nbytes]) { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, /// \method write(buf) { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_RX_ANY), MP_ROM_INT(UART_TRIGGER_RX_ANY) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { pyb_uart_obj_t *self = self_in; byte *buf = buf_in; uart_check_init(self); // make sure we want at least 1 char if (size == 0) { return 0; } // wait for first char to become available if (!uart_rx_wait(self)) { // return MP_EAGAIN error to indicate non-blocking (then read() method returns None) *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } // read the data byte *orig_buf = buf; for ( ; ; ) { *buf++ = uart_rx_char(self); if (--size == 0 || !uart_rx_wait(self)) { // return number of bytes read return buf - orig_buf; } } } STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { pyb_uart_obj_t *self = self_in; const char *buf = buf_in; uart_check_init(self); // write the data if (!uart_tx_strn(self, buf, size)) { mp_raise_OSError(MP_EIO); } return size; } STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { pyb_uart_obj_t *self = self_in; mp_uint_t ret; uart_check_init(self); if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; if ((flags & MP_STREAM_POLL_RD) && uart_rx_any(self)) { ret |= MP_STREAM_POLL_RD; } if ((flags & MP_STREAM_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) { ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; } return ret; } STATIC const mp_stream_p_t uart_stream_p = { .read = pyb_uart_read, .write = pyb_uart_write, .ioctl = pyb_uart_ioctl, .is_text = false, }; STATIC const mp_irq_methods_t uart_irq_methods = { .init = pyb_uart_irq, .enable = uart_irq_enable, .disable = uart_irq_disable, .flags = uart_irq_flags }; const mp_obj_type_t pyb_uart_type = { { &mp_type_type }, .name = MP_QSTR_UART, .print = pyb_uart_print, .make_new = pyb_uart_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &uart_stream_p, .locals_dict = (mp_obj_t)&pyb_uart_locals_dict, }; micropython-1.12/ports/cc3200/mods/pybuart.h000066400000000000000000000034611357706137100206700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBUART_H #define MICROPY_INCLUDED_CC3200_MODS_PYBUART_H typedef enum { PYB_UART_0 = 0, PYB_UART_1 = 1, PYB_NUM_UARTS } pyb_uart_id_t; typedef struct _pyb_uart_obj_t pyb_uart_obj_t; extern const mp_obj_type_t pyb_uart_type; void uart_init0(void); uint32_t uart_rx_any(pyb_uart_obj_t *uart_obj); int uart_rx_char(pyb_uart_obj_t *uart_obj); bool uart_tx_char(pyb_uart_obj_t *self, int c); bool uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); #endif // MICROPY_INCLUDED_CC3200_MODS_PYBUART_H micropython-1.12/ports/cc3200/mods/pybwdt.c000066400000000000000000000131111357706137100204770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "wdt.h" #include "prcm.h" #include "utils.h" #include "pybwdt.h" #include "mpexception.h" #include "mperror.h" /****************************************************************************** DECLARE CONSTANTS ******************************************************************************/ #define PYBWDT_MILLISECONDS_TO_TICKS(ms) ((80000000 / 1000) * (ms)) #define PYBWDT_MIN_TIMEOUT_MS (1000) /****************************************************************************** DECLARE TYPES ******************************************************************************/ typedef struct { mp_obj_base_t base; bool servers; bool servers_sleeping; bool simplelink; bool running; } pyb_wdt_obj_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC pyb_wdt_obj_t pyb_wdt_obj = {.servers = false, .servers_sleeping = false, .simplelink = false, .running = false}; /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ // must be called in main.c just after initializing the hal __attribute__ ((section (".boot"))) void pybwdt_init0 (void) { } void pybwdt_srv_alive (void) { pyb_wdt_obj.servers = true; } void pybwdt_srv_sleeping (bool state) { pyb_wdt_obj.servers_sleeping = state; } void pybwdt_sl_alive (void) { pyb_wdt_obj.simplelink = true; } /******************************************************************************/ // MicroPython bindings STATIC const mp_arg_t pyb_wdt_init_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} }, // 5 s }; STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // check the arguments mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); mp_arg_val_t args[MP_ARRAY_SIZE(pyb_wdt_init_args)]; mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_wdt_init_args, args); if (args[0].u_obj != mp_const_none && mp_obj_get_int(args[0].u_obj) > 0) { mp_raise_OSError(MP_ENODEV); } uint timeout_ms = args[1].u_int; if (timeout_ms < PYBWDT_MIN_TIMEOUT_MS) { mp_raise_ValueError(mpexception_value_invalid_arguments); } if (pyb_wdt_obj.running) { mp_raise_OSError(MP_EPERM); } // Enable the WDT peripheral clock MAP_PRCMPeripheralClkEnable(PRCM_WDT, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // Unlock to be able to configure the registers MAP_WatchdogUnlock(WDT_BASE); #ifdef DEBUG // make the WDT stall when the debugger stops on a breakpoint MAP_WatchdogStallEnable (WDT_BASE); #endif // set the watchdog timer reload value // the WDT trigger a system reset after the second timeout // so, divide by 2 the timeout value received MAP_WatchdogReloadSet(WDT_BASE, PYBWDT_MILLISECONDS_TO_TICKS(timeout_ms / 2)); // start the timer. Once it's started, it cannot be disabled. MAP_WatchdogEnable(WDT_BASE); pyb_wdt_obj.base.type = &pyb_wdt_type; pyb_wdt_obj.running = true; return (mp_obj_t)&pyb_wdt_obj; } STATIC mp_obj_t pyb_wdt_feed(mp_obj_t self_in) { pyb_wdt_obj_t *self = self_in; if ((self->servers || self->servers_sleeping) && self->simplelink && self->running) { self->servers = false; self->simplelink = false; MAP_WatchdogIntClear(WDT_BASE); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_wdt_feed_obj, pyb_wdt_feed); STATIC const mp_rom_map_elem_t pybwdt_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&pyb_wdt_feed_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pybwdt_locals_dict, pybwdt_locals_dict_table); const mp_obj_type_t pyb_wdt_type = { { &mp_type_type }, .name = MP_QSTR_WDT, .make_new = pyb_wdt_make_new, .locals_dict = (mp_obj_t)&pybwdt_locals_dict, }; micropython-1.12/ports/cc3200/mods/pybwdt.h000066400000000000000000000030201357706137100205020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MODS_PYBWDT_H #define MICROPY_INCLUDED_CC3200_MODS_PYBWDT_H #include "py/obj.h" extern const mp_obj_type_t pyb_wdt_type; void pybwdt_init0 (void); void pybwdt_srv_alive (void); void pybwdt_srv_sleeping (bool state); void pybwdt_sl_alive (void); #endif // MICROPY_INCLUDED_CC3200_MODS_PYBWDT_H micropython-1.12/ports/cc3200/mpconfigport.h000066400000000000000000000246031357706137100207500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #ifndef BOOTLOADER #include "FreeRTOS.h" #include "semphr.h" #endif // options to control how MicroPython is built #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t #define MICROPY_ALLOC_PATH_MAX (128) #define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_CONST_LITERAL (0) #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #define MICROPY_STACK_CHECK (0) #define MICROPY_HELPER_REPL (1) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #define MICROPY_READER_VFS (1) #ifndef DEBUG // we need ram on the launchxl while debugging #define MICROPY_CPYTHON_COMPAT (1) #else #define MICROPY_CPYTHON_COMPAT (0) #endif #define MICROPY_QSTR_BYTES_IN_HASH (1) // fatfs configuration used in ffconf.h #define MICROPY_FATFS_ENABLE_LFN (2) #define MICROPY_FATFS_MAX_LFN (MICROPY_ALLOC_PATH_MAX) #define MICROPY_FATFS_LFN_CODE_PAGE 437 // 1=SFN/ANSI 437=LFN/U.S.(OEM) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_REENTRANT (1) #define MICROPY_FATFS_TIMEOUT (2500) #define MICROPY_FATFS_SYNC_T SemaphoreHandle_t #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_VFS (1) #define MICROPY_VFS_FAT (1) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT cc3200_help_text #ifndef DEBUG #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_EXECFILE (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #else #define MICROPY_PY_BUILTINS_STR_UNICODE (0) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_EXECFILE (0) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) #endif #define MICROPY_PY_MICROPYTHON_MEM_INFO (0) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (1) #define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UERRNO_ERRORCODE (0) #define MICROPY_PY_THREAD (1) #define MICROPY_PY_THREAD_GIL (1) #define MICROPY_PY_UBINASCII (0) #define MICROPY_PY_UCTYPES (0) #define MICROPY_PY_UZLIB (0) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_UHEAPQ (0) #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) #define MICROPY_KBD_EXCEPTION (1) // We define our own list of errno constants to include in uerrno module #define MICROPY_PY_UERRNO_LIST \ X(EPERM) \ X(EIO) \ X(ENODEV) \ X(EINVAL) \ X(ETIMEDOUT) \ // TODO these should be generic, not bound to fatfs #define mp_type_fileio mp_type_vfs_fat_fileio #define mp_type_textio mp_type_vfs_fat_textio // use vfs's functions for import stat and builtin open #define mp_import_stat mp_vfs_import_stat #define mp_builtin_open mp_vfs_open #define mp_builtin_open_obj mp_vfs_open_obj // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, \ // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t machine_module; extern const struct _mp_obj_module_t wipy_module; extern const struct _mp_obj_module_t mp_module_ure; extern const struct _mp_obj_module_t mp_module_ujson; extern const struct _mp_obj_module_t mp_module_uos; extern const struct _mp_obj_module_t mp_module_utime; extern const struct _mp_obj_module_t mp_module_uselect; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_network; extern const struct _mp_obj_module_t mp_module_ubinascii; extern const struct _mp_obj_module_t mp_module_ussl; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_wipy), MP_ROM_PTR(&wipy_module) }, \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ { MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) }, \ { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) }, \ { MP_ROM_QSTR(MP_QSTR_network), MP_ROM_PTR(&mp_module_network) }, \ { MP_ROM_QSTR(MP_QSTR_ubinascii), MP_ROM_PTR(&mp_module_ubinascii) }, \ { MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) }, \ // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&machine_module) }, \ // vm state and root pointers for the gc #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ mp_obj_t mp_const_user_interrupt; \ mp_obj_t machine_config_main; \ mp_obj_list_t pyb_sleep_obj_list; \ mp_obj_list_t mp_irq_obj_list; \ mp_obj_list_t pyb_timer_channel_obj_list; \ struct _pyb_uart_obj_t *pyb_uart_objs[2]; \ struct _os_term_dup_obj_t *os_term_dup_obj; \ // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) #define MP_SSIZE_MAX (0x7FFFFFFF) #define UINT_FMT "%u" #define INT_FMT "%d" typedef int32_t mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) #define MICROPY_EVENT_POLL_HOOK __WFI(); // assembly functions to handle critical sections, interrupt // disabling/enabling and sleep mode enter/exit #include "cc3200_asm.h" // We need to provide a declaration/definition of alloca() #include // Include board specific configuration #include "mpconfigboard.h" #define MICROPY_MPHALPORT_H "cc3200_hal.h" #define MICROPY_PORT_HAS_TELNET (1) #define MICROPY_PORT_HAS_FTP (1) #define MICROPY_PY_SYS_PLATFORM "WiPy" #define MICROPY_PORT_WLAN_AP_SSID "wipy-wlan" #define MICROPY_PORT_WLAN_AP_KEY "www.wipy.io" #define MICROPY_PORT_WLAN_AP_SECURITY SL_SEC_TYPE_WPA_WPA2 #define MICROPY_PORT_WLAN_AP_CHANNEL 5 micropython-1.12/ports/cc3200/mptask.c000066400000000000000000000314501357706137100175310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpconfig.h" #include "py/stackctrl.h" #include "py/obj.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" #include "lib/mp-readline/readline.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "pin.h" #include "prcm.h" #include "interrupt.h" #include "pybuart.h" #include "pybpin.h" #include "pybrtc.h" #include "lib/utils/pyexec.h" #include "lib/utils/gchelper.h" #include "gccollect.h" #include "mperror.h" #include "simplelink.h" #include "modnetwork.h" #include "modusocket.h" #include "modwlan.h" #include "serverstask.h" #include "telnet.h" #include "debug.h" #include "sflash_diskio.h" #include "random.h" #include "pybi2c.h" #include "pins.h" #include "mods/pybflash.h" #include "pybsleep.h" #include "pybtimer.h" #include "cryptohash.h" #include "mpirq.h" #include "updater.h" #include "moduos.h" #include "antenna.h" #include "task.h" /****************************************************************************** DECLARE PRIVATE CONSTANTS ******************************************************************************/ /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void mptask_pre_init (void); STATIC void mptask_init_sflash_filesystem (void); STATIC void mptask_enter_ap_mode (void); STATIC void mptask_create_main_py (void); /****************************************************************************** DECLARE PUBLIC DATA ******************************************************************************/ #ifdef DEBUG OsiTaskHandle svTaskHandle; #endif /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ static fs_user_mount_t *sflash_vfs_fat; static const char fresh_main_py[] = "# main.py -- put your code here!\r\n"; static const char fresh_boot_py[] = "# boot.py -- run on boot-up\r\n" "# can run arbitrary Python, but best to keep it minimal\r\n" #if MICROPY_STDIO_UART "import os, machine\r\n" "os.dupterm(machine.UART(0, " MP_STRINGIFY(MICROPY_STDIO_UART_BAUD) "))\r\n" #endif ; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ void TASK_MicroPython (void *pvParameters) { // get the top of the stack to initialize the garbage collector uint32_t sp = gc_helper_get_sp(); bool safeboot = false; mptask_pre_init(); #ifndef DEBUG safeboot = PRCMGetSpecialBit(PRCM_SAFE_BOOT_BIT); #endif soft_reset: // Thread init #if MICROPY_PY_THREAD mp_thread_init(); #endif // initialise the stack pointer for the main thread (must be done after mp_thread_init) mp_stack_set_top((void*)sp); // GC init gc_init(&_boot, &_eheap); // MicroPython init mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_init(mp_sys_argv, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) // execute all basic initializations mp_irq_init0(); pyb_sleep_init0(); pin_init0(); mperror_init0(); uart_init0(); timer_init0(); readline_init0(); mod_network_init0(); rng_init0(); pybsleep_reset_cause_t rstcause = pyb_sleep_get_reset_cause(); if (rstcause < PYB_SLP_SOFT_RESET) { if (rstcause == PYB_SLP_HIB_RESET) { // when waking up from hibernate we just want // to enable simplelink and leave it as is wlan_first_start(); } else { // only if not comming out of hibernate or a soft reset mptask_enter_ap_mode(); } // enable telnet and ftp servers_start(); } // initialize the serial flash file system mptask_init_sflash_filesystem(); // append the flash paths to the system path mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash_slash_lib)); // reset config variables; they should be set by boot.py MP_STATE_PORT(machine_config_main) = MP_OBJ_NULL; if (!safeboot) { // run boot.py int ret = pyexec_file_if_exists("boot.py"); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } if (!ret) { // flash the system led mperror_signal_error(); } } // now we initialise sub-systems that need configuration from boot.py, // or whose initialisation can be safely deferred until after running // boot.py. // at this point everything is fully configured and initialised. if (!safeboot) { // run the main script from the current directory. if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { const char *main_py; if (MP_STATE_PORT(machine_config_main) == MP_OBJ_NULL) { main_py = "main.py"; } else { main_py = mp_obj_str_get_str(MP_STATE_PORT(machine_config_main)); } int ret = pyexec_file_if_exists(main_py); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } if (!ret) { // flash the system led mperror_signal_error(); } } } // main script is finished, so now go into REPL mode. // the REPL mode can change, or it can request a soft reset. for ( ; ; ) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } soft_reset_exit: // soft reset pyb_sleep_signal_soft_reset(); mp_printf(&mp_plat_print, "MPY: soft reboot\n"); // disable all callbacks to avoid undefined behaviour // when coming out of a soft reset mp_irq_disable_all(); // cancel the RTC alarm which might be running independent of the irq state pyb_rtc_disable_alarm(); // flush the serial flash buffer sflash_disk_flush(); // clean-up the user socket space modusocket_close_all_user_sockets(); // unmount all user file systems osmount_unmount_all(); // wait for pending transactions to complete mp_hal_delay_ms(20); goto soft_reset; } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ __attribute__ ((section (".boot"))) STATIC void mptask_pre_init (void) { // this one only makes sense after a poweron reset pyb_rtc_pre_init(); // Create the simple link spawn task ASSERT (OSI_OK == VStartSimpleLinkSpawnTask(SIMPLELINK_SPAWN_TASK_PRIORITY)); // Allocate memory for the flash file system ASSERT ((sflash_vfs_fat = mem_Malloc(sizeof(*sflash_vfs_fat))) != NULL); // this one allocates memory for the nvic vault pyb_sleep_pre_init(); // this one allocates memory for the WLAN semaphore wlan_pre_init(); // this one allocates memory for the updater semaphore updater_pre_init(); // this one allocates memory for the socket semaphore modusocket_pre_init(); //CRYPTOHASH_Init(); #ifndef DEBUG OsiTaskHandle svTaskHandle; #endif svTaskHandle = xTaskCreateStatic(TASK_Servers, "Servers", SERVERS_STACK_LEN, NULL, SERVERS_PRIORITY, svTaskStack, &svTaskTCB); ASSERT(svTaskHandle != NULL); } STATIC void mptask_init_sflash_filesystem (void) { FILINFO fno; // Initialise the local flash filesystem. // init the vfs object fs_user_mount_t *vfs_fat = sflash_vfs_fat; vfs_fat->blockdev.flags = 0; pyb_flash_init_vfs(vfs_fat); // Create it if needed, and mount in on /flash. FRESULT res = f_mount(&vfs_fat->fatfs); if (res == FR_NO_FILESYSTEM) { // no filesystem, so create a fresh one uint8_t working_buf[FF_MAX_SS]; res = f_mkfs(&vfs_fat->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf)); if (res == FR_OK) { // success creating fresh LFS } else { __fatal_error("failed to create /flash"); } // create empty main.py mptask_create_main_py(); } else if (res == FR_OK) { // mount sucessful if (FR_OK != f_stat(&vfs_fat->fatfs, "/main.py", &fno)) { // create empty main.py mptask_create_main_py(); } } else { fail: __fatal_error("failed to create /flash"); } // mount the flash device (there should be no other devices mounted at this point) // we allocate this structure on the heap because vfs->next is a root pointer mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); if (vfs == NULL) { goto fail; } vfs->str = "/flash"; vfs->len = 6; vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); vfs->next = NULL; MP_STATE_VM(vfs_mount_table) = vfs; // The current directory is used as the boot up directory. // It is set to the internal flash filesystem by default. MP_STATE_PORT(vfs_cur) = vfs; // create /flash/sys, /flash/lib and /flash/cert if they don't exist if (FR_OK != f_chdir(&vfs_fat->fatfs, "/sys")) { f_mkdir(&vfs_fat->fatfs, "/sys"); } if (FR_OK != f_chdir(&vfs_fat->fatfs, "/lib")) { f_mkdir(&vfs_fat->fatfs, "/lib"); } if (FR_OK != f_chdir(&vfs_fat->fatfs, "/cert")) { f_mkdir(&vfs_fat->fatfs, "/cert"); } f_chdir(&vfs_fat->fatfs, "/"); // make sure we have a /flash/boot.py. Create it if needed. res = f_stat(&vfs_fat->fatfs, "/boot.py", &fno); if (res == FR_OK) { if (fno.fattrib & AM_DIR) { // exists as a directory // TODO handle this case // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation } else { // exists as a file, good! } } else { // doesn't exist, create fresh file FIL fp; f_open(&vfs_fat->fatfs, &fp, "/boot.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); } } STATIC void mptask_enter_ap_mode (void) { // append the mac only if it's not the first boot bool add_mac = !PRCMGetSpecialBit(PRCM_FIRST_BOOT_BIT); // enable simplelink in ap mode (use the MAC address to make the ssid unique) wlan_sl_init (ROLE_AP, MICROPY_PORT_WLAN_AP_SSID, strlen(MICROPY_PORT_WLAN_AP_SSID), MICROPY_PORT_WLAN_AP_SECURITY, MICROPY_PORT_WLAN_AP_KEY, strlen(MICROPY_PORT_WLAN_AP_KEY), MICROPY_PORT_WLAN_AP_CHANNEL, ANTENNA_TYPE_INTERNAL, add_mac); } STATIC void mptask_create_main_py (void) { // create empty main.py FIL fp; f_open(&sflash_vfs_fat->fatfs, &fp, "/main.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n); f_close(&fp); } micropython-1.12/ports/cc3200/mptask.h000066400000000000000000000042361357706137100175400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_MPTASK_H #define MICROPY_INCLUDED_CC3200_MPTASK_H /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define MICROPY_TASK_PRIORITY (2) #define MICROPY_TASK_STACK_SIZE ((6 * 1024) + 512) // in bytes #define MICROPY_TASK_STACK_LEN (MICROPY_TASK_STACK_SIZE / sizeof(StackType_t)) /****************************************************************************** EXPORTED DATA ******************************************************************************/ extern StackType_t mpTaskStack[]; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ extern void TASK_MicroPython (void *pvParameters); #endif // MICROPY_INCLUDED_CC3200_MPTASK_H micropython-1.12/ports/cc3200/mpthreadport.c000066400000000000000000000140141357706137100207400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/gc.h" #include "py/mpthread.h" #include "py/mphal.h" #include "mptask.h" #include "task.h" #include "irq.h" #if MICROPY_PY_THREAD // this structure forms a linked list, one node per active thread typedef struct _thread_t { TaskHandle_t id; // system id of thread int ready; // whether the thread is ready and running void *arg; // thread Python args, a GC root pointer void *stack; // pointer to the stack size_t stack_len; // number of words in the stack struct _thread_t *next; } thread_t; // the mutex controls access to the linked list STATIC mp_thread_mutex_t thread_mutex; STATIC thread_t thread_entry0; STATIC thread_t *thread; // root pointer, handled bp mp_thread_gc_others void mp_thread_init(void) { mp_thread_mutex_init(&thread_mutex); mp_thread_set_state(&mp_state_ctx.thread); // create first entry in linked list of all threads thread = &thread_entry0; thread->id = xTaskGetCurrentTaskHandle(); thread->ready = 1; thread->arg = NULL; thread->stack = mpTaskStack; thread->stack_len = MICROPY_TASK_STACK_LEN; thread->next = NULL; } void mp_thread_gc_others(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { gc_collect_root((void**)&th, 1); gc_collect_root(&th->arg, 1); // probably not needed if (th->id == xTaskGetCurrentTaskHandle()) { continue; } if (!th->ready) { continue; } gc_collect_root(th->stack, th->stack_len); // probably not needed } mp_thread_mutex_unlock(&thread_mutex); } mp_state_thread_t *mp_thread_get_state(void) { return pvTaskGetThreadLocalStoragePointer(NULL, 0); } void mp_thread_set_state(void *state) { vTaskSetThreadLocalStoragePointer(NULL, 0, state); } void mp_thread_start(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == xTaskGetCurrentTaskHandle()) { th->ready = 1; break; } } mp_thread_mutex_unlock(&thread_mutex); } STATIC void *(*ext_thread_entry)(void*) = NULL; STATIC void freertos_entry(void *arg) { if (ext_thread_entry) { ext_thread_entry(arg); } vTaskDelete(NULL); for (;;) { } } void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { // store thread entry function into a global variable so we can access it ext_thread_entry = entry; if (*stack_size == 0) { *stack_size = 4096; // default stack size } else if (*stack_size < 2048) { *stack_size = 2048; // minimum stack size } // allocate TCB, stack and linked-list node (must be outside thread_mutex lock) StaticTask_t *tcb = m_new(StaticTask_t, 1); StackType_t *stack = m_new(StackType_t, *stack_size / sizeof(StackType_t)); thread_t *th = m_new_obj(thread_t); mp_thread_mutex_lock(&thread_mutex, 1); // create thread TaskHandle_t id = xTaskCreateStatic(freertos_entry, "Thread", *stack_size / sizeof(void*), arg, 2, stack, tcb); if (id == NULL) { mp_thread_mutex_unlock(&thread_mutex); mp_raise_msg(&mp_type_OSError, "can't create thread"); } // add thread to linked list of all threads th->id = id; th->ready = 0; th->arg = arg; th->stack = stack; th->stack_len = *stack_size / sizeof(StackType_t); th->next = thread; thread = th; mp_thread_mutex_unlock(&thread_mutex); // adjust stack_size to provide room to recover from hitting the limit *stack_size -= 512; } void mp_thread_finish(void) { mp_thread_mutex_lock(&thread_mutex, 1); // TODO unlink from list for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == xTaskGetCurrentTaskHandle()) { th->ready = 0; break; } } mp_thread_mutex_unlock(&thread_mutex); } void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer); } // To allow hard interrupts to work with threading we only take/give the semaphore // if we are not within an interrupt context and interrupts are enabled. int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) { int ret = xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0); return ret == pdTRUE; } else { return 1; } } void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) { xSemaphoreGive(mutex->handle); // TODO check return value } } #endif // MICROPY_PY_THREAD micropython-1.12/ports/cc3200/mpthreadport.h000066400000000000000000000027451357706137100207550ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef BOOTLOADER #include "FreeRTOS.h" #endif typedef struct _mp_thread_mutex_t { #ifndef BOOTLOADER SemaphoreHandle_t handle; StaticSemaphore_t buffer; #endif } mp_thread_mutex_t; void mp_thread_init(void); void mp_thread_gc_others(void); micropython-1.12/ports/cc3200/qstrdefsport.h000066400000000000000000000025001357706137100207710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // for machine module Q(/) // entries for sys.path Q(/flash) Q(/flash/lib) micropython-1.12/ports/cc3200/serverstask.c000066400000000000000000000150511357706137100206050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpconfig.h" #include "py/misc.h" #include "py/runtime.h" #include "py/mphal.h" #include "serverstask.h" #include "simplelink.h" #include "debug.h" #include "telnet.h" #include "ftp.h" #include "pybwdt.h" #include "modusocket.h" #include "mpexception.h" #include "modnetwork.h" #include "modwlan.h" /****************************************************************************** DEFINE PRIVATE TYPES ******************************************************************************/ typedef struct { uint32_t timeout; bool enabled; bool do_disable; bool do_enable; bool do_reset; bool do_wlan_cycle_power; } servers_data_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ static servers_data_t servers_data = {.timeout = SERVERS_DEF_TIMEOUT_MS}; static volatile bool sleep_sockets = false; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ /****************************************************************************** DECLARE PUBLIC DATA ******************************************************************************/ // This is the static memory (TCB and stack) for the servers task StaticTask_t svTaskTCB __attribute__ ((section (".rtos_heap"))); StackType_t svTaskStack[SERVERS_STACK_LEN] __attribute__ ((section (".rtos_heap"))) __attribute__((aligned (8))); char servers_user[SERVERS_USER_PASS_LEN_MAX + 1]; char servers_pass[SERVERS_USER_PASS_LEN_MAX + 1]; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ void TASK_Servers (void *pvParameters) { bool cycle = false; strcpy (servers_user, SERVERS_DEF_USER); strcpy (servers_pass, SERVERS_DEF_PASS); telnet_init(); ftp_init(); for ( ;; ) { if (servers_data.do_enable) { // enable network services telnet_enable(); ftp_enable(); // now set/clear the flags servers_data.enabled = true; servers_data.do_enable = false; } else if (servers_data.do_disable) { // disable network services telnet_disable(); ftp_disable(); // now clear the flags servers_data.do_disable = false; servers_data.enabled = false; } else if (servers_data.do_reset) { // resetting the servers is needed to prevent half-open sockets servers_data.do_reset = false; if (servers_data.enabled) { telnet_reset(); ftp_reset(); } // and we should also close all user sockets. We do it here // for convinience and to save on code size. modusocket_close_all_user_sockets(); } if (cycle) { telnet_run(); } else { ftp_run(); } if (sleep_sockets) { pybwdt_srv_sleeping(true); modusocket_enter_sleep(); pybwdt_srv_sleeping(false); mp_hal_delay_ms(SERVERS_CYCLE_TIME_MS * 2); if (servers_data.do_wlan_cycle_power) { servers_data.do_wlan_cycle_power = false; wlan_off_on(); } sleep_sockets = false; } // set the alive flag for the wdt pybwdt_srv_alive(); // move to the next cycle cycle = cycle ? false : true; mp_hal_delay_ms(SERVERS_CYCLE_TIME_MS); } } void servers_start (void) { servers_data.do_enable = true; mp_hal_delay_ms(SERVERS_CYCLE_TIME_MS * 3); } void servers_stop (void) { servers_data.do_disable = true; do { mp_hal_delay_ms(SERVERS_CYCLE_TIME_MS); } while (servers_are_enabled()); mp_hal_delay_ms(SERVERS_CYCLE_TIME_MS * 3); } void servers_reset (void) { servers_data.do_reset = true; } void servers_wlan_cycle_power (void) { servers_data.do_wlan_cycle_power = true; } bool servers_are_enabled (void) { return servers_data.enabled; } void server_sleep_sockets (void) { sleep_sockets = true; mp_hal_delay_ms(SERVERS_CYCLE_TIME_MS + 1); } void servers_close_socket (int16_t *sd) { if (*sd > 0) { modusocket_socket_delete(*sd); sl_Close(*sd); *sd = -1; } } void servers_set_login (char *user, char *pass) { if (strlen(user) > SERVERS_USER_PASS_LEN_MAX || strlen(pass) > SERVERS_USER_PASS_LEN_MAX) { mp_raise_ValueError(mpexception_value_invalid_arguments); } memcpy(servers_user, user, SERVERS_USER_PASS_LEN_MAX); memcpy(servers_pass, pass, SERVERS_USER_PASS_LEN_MAX); } void servers_set_timeout (uint32_t timeout) { if (timeout < SERVERS_MIN_TIMEOUT_MS) { // timeout is too low mp_raise_ValueError(mpexception_value_invalid_arguments); } servers_data.timeout = timeout; } uint32_t servers_get_timeout (void) { return servers_data.timeout; } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ micropython-1.12/ports/cc3200/serverstask.h000066400000000000000000000064341357706137100206170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_SERVERSTASK_H #define MICROPY_INCLUDED_CC3200_SERVERSTASK_H /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ #define SERVERS_PRIORITY 2 #define SERVERS_STACK_SIZE 1024 // in bytes #define SERVERS_STACK_LEN (SERVERS_STACK_SIZE / sizeof(StackType_t)) #define SERVERS_SSID_LEN_MAX 16 #define SERVERS_KEY_LEN_MAX 16 #define SERVERS_USER_PASS_LEN_MAX 32 #define SERVERS_CYCLE_TIME_MS 2 #define SERVERS_DEF_USER "micro" #define SERVERS_DEF_PASS "python" #define SERVERS_DEF_TIMEOUT_MS 300000 // 5 minutes #define SERVERS_MIN_TIMEOUT_MS 5000 // 5 seconds /****************************************************************************** DEFINE TYPES ******************************************************************************/ /****************************************************************************** EXPORTED DATA ******************************************************************************/ extern StaticTask_t svTaskTCB; extern StackType_t svTaskStack[]; extern char servers_user[]; extern char servers_pass[]; /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ extern void TASK_Servers (void *pvParameters); extern void servers_start (void); extern void servers_stop (void); extern void servers_reset (void); extern void servers_wlan_cycle_power (void); extern bool servers_are_enabled (void); extern void servers_close_socket (int16_t *sd); extern void servers_set_login (char *user, char *pass); extern void server_sleep_sockets (void); extern void servers_set_timeout (uint32_t timeout); extern uint32_t servers_get_timeout (void); #endif // MICROPY_INCLUDED_CC3200_SERVERSTASK_H micropython-1.12/ports/cc3200/simplelink/000077500000000000000000000000001357706137100202325ustar00rootroot00000000000000micropython-1.12/ports/cc3200/simplelink/cc_pal.c000066400000000000000000000332121357706137100216200ustar00rootroot00000000000000//***************************************************************************** // cc_pal.c // // simplelink abstraction file for CC3200 // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //Simplelink includes #include #include //Driverlib includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define REG_INT_MASK_SET 0x400F7088 #define REG_INT_MASK_CLR 0x400F708C #define APPS_SOFT_RESET_REG 0x4402D000 #define OCP_SHARED_MAC_RESET_REG 0x4402E168 #define SPI_RATE_20M 20000000 #define UNUSED(x) (x = x) // // GLOBAL VARIABLES -- Start // volatile Fd_t g_SpiFd =0; P_EVENT_HANDLER g_pHostIntHdl = NULL; // // GLOBAL VARIABLES -- End // //**************************************************************************** // LOCAL FUNCTION PROTOTYPES //**************************************************************************** static int spi_Read_CPU(unsigned char *pBuff, int len); static int spi_Write_CPU(unsigned char *pBuff, int len); //**************************************************************************** // LOCAL FUNCTION DEFINITIONS //**************************************************************************** /*! \brief attempts to read up to len bytes from SPI channel into a buffer starting at pBuff. \param pBuff - points to first location to start writing the data \param len - number of bytes to read from the SPI channel \return upon successful completion, the function shall return Read Size. Otherwise, -1 shall be returned \sa spi_Read_CPU , spi_Write_CPU \note \warning */ int spi_Read_CPU(unsigned char *pBuff, int len) { unsigned long ulCnt; unsigned long ulStatusReg; unsigned long *ulDataIn; unsigned long ulTxReg; unsigned long ulRxReg; MAP_SPICSEnable(LSPI_BASE); // // Initialize local variable. // ulDataIn = (unsigned long *)pBuff; ulCnt = (len + 3) >> 2; ulStatusReg = LSPI_BASE+MCSPI_O_CH0STAT; ulTxReg = LSPI_BASE + MCSPI_O_TX0; ulRxReg = LSPI_BASE + MCSPI_O_RX0; // // Reading loop // while(ulCnt--) { while(!( HWREG(ulStatusReg)& MCSPI_CH0STAT_TXS )); HWREG(ulTxReg) = 0xFFFFFFFF; while(!( HWREG(ulStatusReg)& MCSPI_CH0STAT_RXS )); *ulDataIn = HWREG(ulRxReg); ulDataIn++; } MAP_SPICSDisable(LSPI_BASE); return len; } /*! \brief attempts to write up to len bytes to the SPI channel \param pBuff - points to first location to start getting the data from \param len - number of bytes to write to the SPI channel \return upon successful completion, the function shall return write size. Otherwise, -1 shall be returned \sa spi_Read_CPU , spi_Write_CPU \note This function could be implemented as zero copy and return only upon successful completion of writing the whole buffer, but in cases that memory allocation is not too tight, the function could copy the data to internal buffer, return back and complete the write in parallel to other activities as long as the other SPI activities would be blocked untill the entire buffer write would be completed \warning */ int spi_Write_CPU(unsigned char *pBuff, int len) { unsigned long ulCnt; unsigned long ulStatusReg; unsigned long *ulDataOut; unsigned long ulDataIn; unsigned long ulTxReg; unsigned long ulRxReg; MAP_SPICSEnable(LSPI_BASE); // // Initialize local variable. // ulDataOut = (unsigned long *)pBuff; ulCnt = (len +3 ) >> 2; ulStatusReg = LSPI_BASE+MCSPI_O_CH0STAT; ulTxReg = LSPI_BASE + MCSPI_O_TX0; ulRxReg = LSPI_BASE + MCSPI_O_RX0; // // Writing Loop // while(ulCnt--) { while(!( HWREG(ulStatusReg)& MCSPI_CH0STAT_TXS )); HWREG(ulTxReg) = *ulDataOut; while(!( HWREG(ulStatusReg)& MCSPI_CH0STAT_RXS )); ulDataIn = HWREG(ulRxReg); ulDataOut++; } MAP_SPICSDisable(LSPI_BASE); UNUSED(ulDataIn); return len; } /*! \brief open spi communication port to be used for communicating with a SimpleLink device Given an interface name and option flags, this function opens the spi communication port and creates a file descriptor. This file descriptor can be used afterwards to read and write data from and to this specific spi channel. The SPI speed, clock polarity, clock phase, chip select and all other attributes are all set to hardcoded values in this function. \param ifName - points to the interface name/path. The interface name is an optional attributes that the simple link driver receives on opening the device. in systems that the spi channel is not implemented as part of the os device drivers, this parameter could be NULL. \param flags - option flags \return upon successful completion, the function shall open the spi channel and return a non-negative integer representing the file descriptor. Otherwise, -1 shall be returned \sa spi_Close , spi_Read , spi_Write \note \warning */ Fd_t spi_Open(char *ifName, unsigned long flags) { unsigned long ulBase; unsigned long ulSpiBitRate = SPI_RATE_20M; //NWP master interface ulBase = LSPI_BASE; //Enable MCSPIA2 MAP_PRCMPeripheralClkEnable(PRCM_LSPI,PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); //Disable Chip Select MAP_SPICSDisable(ulBase); //Disable SPI Channel MAP_SPIDisable(ulBase); // Reset SPI MAP_SPIReset(ulBase); // // Configure SPI interface // MAP_SPIConfigSetExpClk(ulBase,MAP_PRCMPeripheralClockGet(PRCM_LSPI), ulSpiBitRate,SPI_MODE_MASTER,SPI_SUB_MODE_0, (SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF | SPI_CS_ACTIVEHIGH | SPI_WL_32)); MAP_SPIEnable(ulBase); g_SpiFd = 1; return g_SpiFd; } /*! \brief closes an opened spi communication port \param fd - file descriptor of an opened SPI channel \return upon successful completion, the function shall return 0. Otherwise, -1 shall be returned \sa spi_Open \note \warning */ int spi_Close(Fd_t fd) { unsigned long ulBase = LSPI_BASE; g_SpiFd = 0; //Disable Chip Select MAP_SPICSDisable(LSPI_BASE); //Disable SPI Channel MAP_SPIDisable(ulBase); // Reset SPI MAP_SPIReset(ulBase); // Disable SPI Peripheral MAP_PRCMPeripheralClkDisable(PRCM_LSPI,PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); return 0; } /*! \brief closes an opened spi communication port \param fd - file descriptor of an opened SPI channel \return upon successful completion, the function shall return 0. Otherwise, -1 shall be returned \sa spi_Open \note \warning */ int spi_Read(Fd_t fd, unsigned char *pBuff, int len) { if (fd != 1 || g_SpiFd != 1) { return -1; } return spi_Read_CPU(pBuff, len); } /*! \brief attempts to write up to len bytes to the SPI channel \param fd - file descriptor of an opened SPI channel \param pBuff - points to first location to start getting the data from \param len - number of bytes to write to the SPI channel \return upon successful completion, the function shall return 0. Otherwise, -1 shall be returned \sa spi_Open , spi_Read \note This function could be implemented as zero copy and return only upon successful completion of writing the whole buffer, but in cases that memory allocation is not too tight, the function could copy the data to internal buffer, return back and complete the write in parallel to other activities as long as the other SPI activities would be blocked untill the entire buffer write would be completed \warning */ int spi_Write(Fd_t fd, unsigned char *pBuff, int len) { if (fd != 1 || g_SpiFd != 1) { return -1; } return spi_Write_CPU(pBuff,len); } /*! \brief register an interrupt handler for the host IRQ \param InterruptHdl - pointer to interrupt handler function \param pValue - pointer to a memory strcuture that is passed to the interrupt handler. \return upon successful registration, the function shall return 0. Otherwise, -1 shall be returned \sa \note If there is already registered interrupt handler, the function should overwrite the old handler with the new one \warning */ int NwpRegisterInterruptHandler(P_EVENT_HANDLER InterruptHdl , void* pValue) { if(InterruptHdl == NULL) { //De-register Interprocessor communication interrupt between App and NWP #ifdef SL_PLATFORM_MULTI_THREADED osi_InterruptDeRegister(INT_NWPIC); #else MAP_IntDisable(INT_NWPIC); MAP_IntUnregister(INT_NWPIC); MAP_IntPendClear(INT_NWPIC); #endif } else { #ifdef SL_PLATFORM_MULTI_THREADED MAP_IntPendClear(INT_NWPIC); osi_InterruptRegister(INT_NWPIC, (P_OSI_INTR_ENTRY)InterruptHdl,INT_PRIORITY_LVL_1); #else MAP_IntRegister(INT_NWPIC, InterruptHdl); MAP_IntPrioritySet(INT_NWPIC, INT_PRIORITY_LVL_1); MAP_IntPendClear(INT_NWPIC); MAP_IntEnable(INT_NWPIC); #endif } return 0; } /*! \brief Masks host IRQ \sa NwpUnMaskInterrupt \warning */ void NwpMaskInterrupt() { (*(unsigned long *)REG_INT_MASK_SET) = 0x1; } /*! \brief Unmasks host IRQ \sa NwpMaskInterrupt \warning */ void NwpUnMaskInterrupt() { (*(unsigned long *)REG_INT_MASK_CLR) = 0x1; } #ifdef DEBUG /*! \brief Preamble to the enabling the Network Processor. Placeholder to implement any pre-process operations before enabling networking operations. \sa sl_DeviceEnable \note belongs to \ref ported_sec */ void NwpPowerOnPreamble(void) { #define MAX_RETRY_COUNT 1000 unsigned int sl_stop_ind, apps_int_sts_raw, nwp_lpds_wake_cfg; unsigned int retry_count; /* Perform the sl_stop equivalent to ensure network services are turned off if active */ HWREG(0x400F70B8) = 1; /* APPs to NWP interrupt */ UtilsDelay(800000/5); retry_count = 0; nwp_lpds_wake_cfg = HWREG(0x4402D404); sl_stop_ind = HWREG(0x4402E16C); if((nwp_lpds_wake_cfg != 0x20) && /* Check for NWP POR condition */ !(sl_stop_ind & 0x2)) /* Check if sl_stop was executed */ { /* Loop until APPs->NWP interrupt is cleared or timeout */ while(retry_count < MAX_RETRY_COUNT) { apps_int_sts_raw = HWREG(0x400F70C0); if(apps_int_sts_raw & 0x1) { UtilsDelay(800000/5); retry_count++; } else { break; } } } HWREG(0x400F70B0) = 1; /* Clear APPs to NWP interrupt */ UtilsDelay(800000/5); /* Stop the networking services */ NwpPowerOff(); } #endif /*! \brief Enable the Network Processor \sa sl_DeviceDisable \note belongs to \ref ported_sec */ void NwpPowerOn(void) { //bring the 1.32 eco out of reset HWREG(0x4402E16C) &= 0xFFFFFFFD; //NWP Wakeup HWREG(0x44025118) = 1; #ifdef DEBUG UtilsDelay(8000000); #endif //UnMask Host Interrupt NwpUnMaskInterrupt(); } /*! \brief Disable the Network Processor \sa sl_DeviceEnable \note belongs to \ref ported_sec */ void NwpPowerOff(void) { //Must delay 300 usec to enable the NWP to finish all sl_stop activities UtilsDelay(300*80/3); //Mask Host Interrupt NwpMaskInterrupt(); //Switch to PFM Mode HWREG(0x4402F024) &= 0xF7FFFFFF; //sl_stop eco for PG1.32 devices HWREG(0x4402E16C) |= 0x2; UtilsDelay(800000); } micropython-1.12/ports/cc3200/simplelink/cc_pal.h000066400000000000000000000141371357706137100216320ustar00rootroot00000000000000//***************************************************************************** // cc_pal.h // // Simplelink abstraction header file for CC3200 // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __CC31xx_PAL_H__ #define __CC31xx_PAL_H__ #ifdef __cplusplus extern "C" { #endif /*! \brief type definition for the spi channel file descriptor \note On each porting or platform the type could be whatever is needed - integer, pointer to structure etc. */ typedef int Fd_t; /*! \brief type definition for the host interrupt handler \param pValue - pointer to any memory strcuture. The value of this pointer is givven on registration of a new interrupt handler \note */ typedef void (*SL_P_EVENT_HANDLER)(void); #define P_EVENT_HANDLER SL_P_EVENT_HANDLER /*! \brief open spi communication port to be used for communicating with a SimpleLink device Given an interface name and option flags, this function opens the spi communication port and creates a file descriptor. This file descriptor can be used afterwards to read and write data from and to this specific spi channel. The SPI speed, clock polarity, clock phase, chip select and all other attributes are all set to hardcoded values in this function. \param ifName - points to the interface name/path. The interface name is an optional attributes that the simple link driver receives on opening the device. in systems that the spi channel is not implemented as part of the os device drivers, this parameter could be NULL. \param flags - option flags \return upon successful completion, the function shall open the spi channel and return a non-negative integer representing the file descriptor. Otherwise, -1 shall be returned \sa spi_Close , spi_Read , spi_Write \note \warning */ Fd_t spi_Open(char *ifName, unsigned long flags); /*! \brief closes an opened spi communication port \param fd - file descriptor of an opened SPI channel \return upon successful completion, the function shall return 0. Otherwise, -1 shall be returned \sa spi_Open \note \warning */ int spi_Close(Fd_t fd); /*! \brief attempts to read up to len bytes from SPI channel into a buffer starting at pBuff. \param fd - file descriptor of an opened SPI channel \param pBuff - points to first location to start writing the data \param len - number of bytes to read from the SPI channel \return upon successful completion, the function shall return 0. Otherwise, -1 shall be returned \sa spi_Open , spi_Write \note \warning */ int spi_Read(Fd_t fd, unsigned char *pBuff, int len); /*! \brief attempts to write up to len bytes to the SPI channel \param fd - file descriptor of an opened SPI channel \param pBuff - points to first location to start getting the data from \param len - number of bytes to write to the SPI channel \return upon successful completion, the function shall return 0. Otherwise, -1 shall be returned \sa spi_Open , spi_Read \note This function could be implemented as zero copy and return only upon successful completion of writing the whole buffer, but in cases that memory allocation is not too tight, the function could copy the data to internal buffer, return back and complete the write in parallel to other activities as long as the other SPI activities would be blocked untill the entire buffer write would be completed \warning */ int spi_Write(Fd_t fd, unsigned char *pBuff, int len); /*! \brief register an interrupt handler for the host IRQ \param InterruptHdl - pointer to interrupt handler function \param pValue - pointer to a memory strcuture that is passed to the interrupt handler. \return upon successful registration, the function shall return 0. Otherwise, -1 shall be returned \sa \note If there is already registered interrupt handler, the function should overwrite the old handler with the new one \warning */ int NwpRegisterInterruptHandler(P_EVENT_HANDLER InterruptHdl , void* pValue); /*! \brief Masks host IRQ \sa NwpUnMaskInterrupt \warning */ void NwpMaskInterrupt(); /*! \brief Unmasks host IRQ \sa NwpMaskInterrupt \warning */ void NwpUnMaskInterrupt(); void NwpPowerOnPreamble(void); void NwpPowerOff(void); void NwpPowerOn(void); #ifdef __cplusplus } #endif // __cplusplus #endif micropython-1.12/ports/cc3200/simplelink/oslib/000077500000000000000000000000001357706137100213425ustar00rootroot00000000000000micropython-1.12/ports/cc3200/simplelink/oslib/osi.h000066400000000000000000000421431357706137100223110ustar00rootroot00000000000000//***************************************************************************** // osi.h // // MACRO and Function prototypes for TI-RTOS and Free-RTOS API calls // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list zof conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #ifndef __OSI_H__ #define __OSI_H__ #ifdef __cplusplus extern "C" { #endif #define OSI_WAIT_FOREVER (0xFFFFFFFF) #define OSI_NO_WAIT (0) typedef enum { OSI_OK = 0, OSI_FAILURE = -1, OSI_OPERATION_FAILED = -2, OSI_ABORTED = -3, OSI_INVALID_PARAMS = -4, OSI_MEMORY_ALLOCATION_FAILURE = -5, OSI_TIMEOUT = -6, OSI_EVENTS_IN_USE = -7, OSI_EVENT_OPEARTION_FAILURE = -8 }OsiReturnVal_e; //#define ENTER_CRITICAL_SECTION osi_EnterCritical() //#define EXIT_CRITICAL_SECTION osi_ExitCritical() typedef void* OsiMsgQ_t; /*! \brief type definition for a time value \note On each porting or platform the type could be whatever is needed - integer, pointer to structure etc. */ //typedef unsigned int OsiTime_t; typedef unsigned int OsiTime_t; /*! \brief type definition for a sync object container Sync object is object used to synchronize between two threads or thread and interrupt handler. One thread is waiting on the object and the other thread send a signal, which then release the waiting thread. The signal must be able to be sent from interrupt context. This object is generally implemented by binary semaphore or events. \note On each porting or platform the type could be whatever is needed - integer, structure etc. */ //typedef unsigned int OsiSyncObj_t; typedef void * OsiSyncObj_t; /*! \brief type definition for a locking object container Locking object are used to protect a resource from mutual accesses of two or more threads. The locking object should support re-entrant locks by a signal thread. This object is generally implemented by mutex semaphore \note On each porting or platform the type could be whatever is needed - integer, structure etc. */ //typedef unsigned int OsiLockObj_t; typedef void * OsiLockObj_t; /*! \brief type definition for a spawn entry callback the spawn mechanism enable to run a function on different context. This mechanism allow to transfer the execution context from interrupt context to thread context or changing the context from an unknown user thread to general context. The implementation of the spawn mechanism depends on the user's system requirements and could varies from implementation of serialized execution using single thread to creating thread per call \note The stack size of the execution thread must be at least of TBD bytes! */ typedef void (*P_OSI_SPAWN_ENTRY)(void* pValue); typedef void (*P_OSI_EVENT_HANDLER)(void* pValue); typedef void (*P_OSI_TASK_ENTRY)(void* pValue); typedef void (*P_OSI_INTR_ENTRY)(void); typedef void* OsiTaskHandle; /*! \brief This function registers an interrupt in NVIC table The sync object is used for synchronization between different thread or ISR and a thread. \param iIntrNum - Interrupt number to register \param pEntry - Pointer to the interrupt handler \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_InterruptRegister(int iIntrNum,P_OSI_INTR_ENTRY pEntry,unsigned char ucPriority); /*! \brief This function De-registers an interrupt in NVIC table \param iIntrNum - Interrupt number to register \param pEntry - Pointer to the interrupt handler \return upon successful creation the function should return Positive number Otherwise, a negative value indicating the error code shall be returned \note \warning */ void osi_InterruptDeRegister(int iIntrNum); /*! \brief This function creates a sync object The sync object is used for synchronization between different thread or ISR and a thread. \param pSyncObj - pointer to the sync object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_SyncObjCreate(OsiSyncObj_t* pSyncObj); /*! \brief This function deletes a sync object \param pSyncObj - pointer to the sync object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_SyncObjDelete(OsiSyncObj_t* pSyncObj); /*! \brief This function generates a sync signal for the object. All suspended threads waiting on this sync object are resumed \param pSyncObj - pointer to the sync object control block \return upon successful signalling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function could be called from ISR context \warning */ OsiReturnVal_e osi_SyncObjSignal(OsiSyncObj_t* pSyncObj); /*! \brief This function generates a sync signal for the object. from ISR context. All suspended threads waiting on this sync object are resumed \param pSyncObj - pointer to the sync object control block \return upon successful signalling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function is called from ISR context \warning */ OsiReturnVal_e osi_SyncObjSignalFromISR(OsiSyncObj_t* pSyncObj); /*! \brief This function waits for a sync signal of the specific sync object \param pSyncObj - pointer to the sync object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the sync signal Currently, the simple link driver uses only two values: - OSI_WAIT_FOREVER - OSI_NO_WAIT \return upon successful reception of the signal within the timeout window return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_SyncObjWait(OsiSyncObj_t* pSyncObj , OsiTime_t Timeout); /*! \brief This function clears a sync object \param pSyncObj - pointer to the sync object control block \return upon successful clearing the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_SyncObjClear(OsiSyncObj_t* pSyncObj); /*! \brief This function creates a locking object. The locking object is used for protecting a shared resources between different threads. \param pLockObj - pointer to the locking object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_LockObjCreate(OsiLockObj_t* pLockObj); /*! \brief This function deletes a locking object. \param pLockObj - pointer to the locking object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define osi_LockObjDelete osi_SyncObjDelete /*! \brief This function locks a locking object. All other threads that call this function before this thread calls the osi_LockObjUnlock would be suspended \param pLockObj - pointer to the locking object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the locking object Currently, the simple link driver uses only two values: - OSI_WAIT_FOREVER - OSI_NO_WAIT \return upon successful reception of the locking object the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define osi_LockObjLock osi_SyncObjWait /*! \brief This function unlock a locking object. \param pLockObj - pointer to the locking object control block \return upon successful unlocking the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ #define osi_LockObjUnlock osi_SyncObjSignal /*! \brief This function call the pEntry callback from a different context \param pEntry - pointer to the entry callback function \param pValue - pointer to any type of memory structure that would be passed to pEntry callback from the execution thread. \param flags - execution flags - reserved for future usage \return upon successful registration of the spawn the function should return 0 (the function is not blocked till the end of the execution of the function and could be returned before the execution is actually completed) Otherwise, a negative value indicating the error code shall be returned \note \warning */ /*! \brief This function creates a Task. Creates a new Task and add it to the last of tasks that are ready to run \param pEntry - pointer to the Task Function \param pcName - Task Name String \param usStackDepth - Stack Size Stack Size in 32-bit long words \param pvParameters - pointer to structure to be passed to the Task Function \param uxPriority - Task Priority \return upon successful unlocking the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_TaskCreate(P_OSI_TASK_ENTRY pEntry,const signed char * const pcName,unsigned short usStackDepth,void *pvParameters,unsigned long uxPriority,OsiTaskHandle *pTaskHandle); /*! \brief This function Deletes a Task. Deletes a Task and remove it from list of running task \param pTaskHandle - Task Handle \note \warning */ void osi_TaskDelete(OsiTaskHandle* pTaskHandle); /*! \brief This function call the pEntry callback from a different context \param pEntry - pointer to the entry callback function \param pValue - pointer to any type of memory structure that would be passed to pEntry callback from the execution thread. \param flags - execution flags - reserved for future usage \return upon successful registration of the spawn the function should return 0 (the function is not blocked till the end of the execution of the function and could be returned before the execution is actually completed) Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_Spawn(P_OSI_SPAWN_ENTRY pEntry , void* pValue , unsigned long flags); /******************************************************************************* This function creates a message queue that is typically used for inter thread communication. Parameters: pMsgQ - pointer to the message queue control block pMsgQName - pointer to the name of the message queue MsgSize - the size of the message. NOTICE: THE MESSGAE SIZE MUST BE SMALLER THAN 16 MaxMsgs - maximum number of messages. Please note that this function allocates the entire memory required for the maximum number of messages (MsgSize * MaxMsgs). ********************************************************************************/ OsiReturnVal_e osi_MsgQCreate(OsiMsgQ_t* pMsgQ , char* pMsgQName, unsigned long MsgSize, unsigned long MaxMsgs); /******************************************************************************* This function deletes a specific message queue. All threads suspended waiting for a message from this queue are resumed with an error return value. Parameters: pMsgQ - pointer to the message queue control block ********************************************************************************/ OsiReturnVal_e osi_MsgQDelete(OsiMsgQ_t* pMsgQ); /******************************************************************************* This function writes a message to a specific message queue. Notice that the message is copied to the queue from the memory area specified by pMsg pointer. -------------------------------------------------------------------------------- THIS FUNCTION COULD BE CALLED FROM ISR AS LONG AS THE TIMEOUT PARAMETER IS SET TO "OSI_NO_WAIT" -------------------------------------------------------------------------------- Parameters: pMsgQ - pointer to the message queue control block pMsg - pointer to the message Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for available space for the message ********************************************************************************/ OsiReturnVal_e osi_MsgQWrite(OsiMsgQ_t* pMsgQ, void* pMsg , OsiTime_t Timeout); /******************************************************************************* This function retrieves a message from the specified message queue. The retrieved message is copied from the queue into the memory area specified by the pMsg pointer Parameters: pMsgQ - pointer to the message queue control block pMsg - pointer that specify the location where to copy the message Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for a message to be available ********************************************************************************/ OsiReturnVal_e osi_MsgQRead(OsiMsgQ_t* pMsgQ, void* pMsg , OsiTime_t Timeout); /*! \brief This function starts the OS Scheduler \param - void \return - void \note \warning */ void osi_start(); /*! \brief Allocates Memory on Heap \param Size - Size of the Buffer to be allocated \sa \note \warning */ void * mem_Malloc(unsigned long Size); /*! \brief Deallocates Memory \param pMem - Pointer to the Buffer to be freed \return void \sa \note \warning */ void mem_Free(void *pMem); /*! \brief Set Memory \param pBuf - Pointer to the Buffer \param Val - Value to be set \param Size - Size of the memory to be set \sa \note \warning */ void mem_set(void *pBuf,int Val,size_t Size); /*! \brief Copy Memory \param pDst - Pointer to the Destination Buffer \param pSrc - Pointer to the Source Buffer \param Size - Size of the memory to be copied \return void \note \warning */ void mem_copy(void *pDst, void *pSrc,size_t Size); /*! \brief Enter Critical Section \sa \note \warning */ void osi_EnterCritical(void); /*! \brief Exit Critical Section \sa \note \warning */ void osi_ExitCritical(void); /*! \brief This function used to save the os context before sleep \param void \return void \note \warning */ void osi_ContextSave(); /*! \brief This function used to retrieve the context after sleep \param void \return void \note \warning */ void osi_ContextRestore(); /*! \brief This function used to suspend the task for the specified number of milli secs \param MilliSecs - Time in millisecs to suspend the task \return void \note \warning */ void osi_Sleep(unsigned int MilliSecs); /*! \brief This function used to disable the tasks \param - void \return - void \note \warning */ void osi_TaskDisable(void); /*! \brief This function used to enable all tasks \param - void \return - void \note \warning */ void osi_TaskEnable(void); /*! \brief structure definition for simple link spawn message \note On each porting or platform the type could be whatever is needed - integer, pointer to structure etc. */ typedef struct { P_OSI_SPAWN_ENTRY pEntry; void* pValue; }tSimpleLinkSpawnMsg; /* The queue used to send message to simple link spawn task. */ extern void* xSimpleLinkSpawnQueue; /* API for SL Task*/ OsiReturnVal_e VStartSimpleLinkSpawnTask(unsigned long uxPriority); void VDeleteSimpleLinkSpawnTask( void ); #ifdef __cplusplus } #endif // __cplusplus #endif micropython-1.12/ports/cc3200/simplelink/oslib/osi_freertos.c000066400000000000000000000441061357706137100242160ustar00rootroot00000000000000//***************************************************************************** // osi_freertos.c // // Interface APIs for free-rtos function calls // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #include #include #include #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include "portmacro.h" #include "osi.h" #include "rom_map.h" #include "inc/hw_types.h" #include "interrupt.h" #include "pybwdt.h" #include "debug.h" portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; //Local function definition static void vSimpleLinkSpawnTask( void *pvParameters ); //Queue Handler QueueHandle_t xSimpleLinkSpawnQueue = NULL; TaskHandle_t xSimpleLinkSpawnTaskHndl = NULL; // Queue size #define slQUEUE_SIZE ( 3 ) #define SL_SPAWN_MAX_WAIT_MS ( 200 ) // This is the static memory (TCB and stack) for the SL spawn task static StaticTask_t spawnTaskTCB __attribute__ ((section (".rtos_heap"))); static portSTACK_TYPE spawnTaskStack[896 / sizeof(portSTACK_TYPE)] __attribute__ ((section (".rtos_heap"))) __attribute__((aligned (8))); /*! \brief This function registers an interrupt in NVIC table The sync object is used for synchronization between different thread or ISR and a thread. \param iIntrNum - Interrupt number to register \param pEntry - Pointer to the interrupt handler \param ucPriority - priority of the interrupt \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_InterruptRegister(int iIntrNum,P_OSI_INTR_ENTRY pEntry,unsigned char ucPriority) { MAP_IntRegister(iIntrNum,(void(*)(void))pEntry); MAP_IntPrioritySet(iIntrNum, ucPriority); MAP_IntEnable(iIntrNum); return OSI_OK; } /*! \brief This function De registers an interrupt in NVIC table \param iIntrNum - Interrupt number to De register \return none \note \warning */ void osi_InterruptDeRegister(int iIntrNum) { MAP_IntDisable(iIntrNum); MAP_IntUnregister(iIntrNum); } /*! \brief This function creates a sync object The sync object is used for synchronization between different thread or ISR and a thread. \param pSyncObj - pointer to the sync object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_SyncObjCreate(OsiSyncObj_t* pSyncObj) { SemaphoreHandle_t *pl_SyncObj = (SemaphoreHandle_t *)pSyncObj; *pl_SyncObj = xSemaphoreCreateBinary(); ASSERT (*pSyncObj != NULL); return OSI_OK; } /*! \brief This function deletes a sync object \param pSyncObj - pointer to the sync object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_SyncObjDelete(OsiSyncObj_t* pSyncObj) { vSemaphoreDelete(*pSyncObj ); return OSI_OK; } /*! \brief This function generates a sync signal for the object. All suspended threads waiting on this sync object are resumed \param pSyncObj - pointer to the sync object control block \return upon successful signaling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function could be called from ISR context \warning */ OsiReturnVal_e osi_SyncObjSignal(OsiSyncObj_t* pSyncObj) { xSemaphoreGive( *pSyncObj ); return OSI_OK; } /*! \brief This function generates a sync signal for the object from ISR context. All suspended threads waiting on this sync object are resumed \param pSyncObj - pointer to the sync object control block \return upon successful signalling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function is called from ISR context \warning */ OsiReturnVal_e osi_SyncObjSignalFromISR(OsiSyncObj_t* pSyncObj) { xHigherPriorityTaskWoken = pdFALSE; if(pdTRUE == xSemaphoreGiveFromISR( *pSyncObj, &xHigherPriorityTaskWoken )) { if( xHigherPriorityTaskWoken ) { taskYIELD (); } } return OSI_OK; } /*! \brief This function waits for a sync signal of the specific sync object \param pSyncObj - pointer to the sync object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the sync signal Currently, the simple link driver uses only two values: - OSI_WAIT_FOREVER - OSI_NO_WAIT \return upon successful reception of the signal within the timeout window return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_SyncObjWait(OsiSyncObj_t* pSyncObj , OsiTime_t Timeout) { if(pdTRUE == xSemaphoreTake( (SemaphoreHandle_t)*pSyncObj, ( TickType_t )Timeout)) { return OSI_OK; } else { return OSI_OPERATION_FAILED; } } /*! \brief This function clears a sync object \param pSyncObj - pointer to the sync object control block \return upon successful clearing the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_SyncObjClear(OsiSyncObj_t* pSyncObj) { if (OSI_OK == osi_SyncObjWait(pSyncObj,0) ) { return OSI_OK; } else { return OSI_OPERATION_FAILED; } } /*! \brief This function creates a locking object. The locking object is used for protecting a shared resources between different threads. \param pLockObj - pointer to the locking object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_LockObjCreate(OsiLockObj_t* pLockObj) { SemaphoreHandle_t *pl_LockObj = (SemaphoreHandle_t *)pLockObj; vSemaphoreCreateBinary(*pl_LockObj); ASSERT (*pLockObj != NULL); return OSI_OK; } /*! \brief This function creates a Task. Creates a new Task and add it to the last of tasks that are ready to run \param pEntry - pointer to the Task Function \param pcName - Task Name String \param usStackDepth - Stack Size in bytes \param pvParameters - pointer to structure to be passed to the Task Function \param uxPriority - Task Priority \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_TaskCreate(P_OSI_TASK_ENTRY pEntry,const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned long uxPriority,OsiTaskHandle* pTaskHandle) { ASSERT (pdPASS == xTaskCreate( pEntry, (char const*)pcName, (usStackDepth/(sizeof( portSTACK_TYPE ))), pvParameters,(unsigned portBASE_TYPE)uxPriority, (TaskHandle_t*)pTaskHandle )); return OSI_OK; } /*! \brief This function Deletes a Task. Deletes a Task and remove it from list of running task \param pTaskHandle - Task Handle \note \warning */ void osi_TaskDelete(OsiTaskHandle* pTaskHandle) { vTaskDelete((TaskHandle_t)*pTaskHandle); } /*! \brief This function deletes a locking object. \param pLockObj - pointer to the locking object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e _osi_LockObjDelete(OsiLockObj_t* pLockObj) { vSemaphoreDelete((SemaphoreHandle_t)*pLockObj ); return OSI_OK; } /*! \brief This function locks a locking object. All other threads that call this function before this thread calls the osi_LockObjUnlock would be suspended \param pLockObj - pointer to the locking object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the locking object Currently, the simple link driver uses only two values: - OSI_WAIT_FOREVER - OSI_NO_WAIT \return upon successful reception of the locking object the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e _osi_LockObjLock(OsiLockObj_t* pLockObj , OsiTime_t Timeout) { //Take Semaphore if(pdTRUE == xSemaphoreTake( *pLockObj, ( TickType_t ) Timeout )) { return OSI_OK; } else { return OSI_OPERATION_FAILED; } } /*! \brief This function unlock a locking object. \param pLockObj - pointer to the locking object control block \return upon successful unlocking the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e _osi_LockObjUnlock(OsiLockObj_t* pLockObj) { //Release Semaphore if(pdTRUE == xSemaphoreGive( *pLockObj )) { return OSI_OK; } else { return OSI_OPERATION_FAILED; } } /*! \brief This function call the pEntry callback from a different context \param pEntry - pointer to the entry callback function \param pValue - pointer to any type of memory structure that would be passed to pEntry callback from the execution thread. \param flags - execution flags - reserved for future usage \return upon successful registration of the spawn the function should return 0 (the function is not blocked till the end of the execution of the function and could be returned before the execution is actually completed) Otherwise, a negative value indicating the error code shall be returned \note \warning */ OsiReturnVal_e osi_Spawn(P_OSI_SPAWN_ENTRY pEntry , void* pValue , unsigned long flags) { tSimpleLinkSpawnMsg Msg; Msg.pEntry = pEntry; Msg.pValue = pValue; xHigherPriorityTaskWoken = pdFALSE; if(pdTRUE == xQueueSendFromISR( xSimpleLinkSpawnQueue, &Msg, &xHigherPriorityTaskWoken )) { if( xHigherPriorityTaskWoken ) { taskYIELD (); } return OSI_OK; } return OSI_OPERATION_FAILED; } /*! \brief This is the simplelink spawn task to call SL callback from a different context \param pvParameters - pointer to the task parameter \return void \note \warning */ void vSimpleLinkSpawnTask(void *pvParameters) { tSimpleLinkSpawnMsg Msg; portBASE_TYPE ret; for(;;) { ret = xQueueReceive( xSimpleLinkSpawnQueue, &Msg, SL_SPAWN_MAX_WAIT_MS); if(ret == pdPASS) { Msg.pEntry(Msg.pValue); } // set the alive flag for the wdt pybwdt_sl_alive(); } } /*! \brief This is the API to create SL spawn task and create the SL queue \param uxPriority - task priority \return void \note \warning */ __attribute__ ((section (".boot"))) OsiReturnVal_e VStartSimpleLinkSpawnTask(unsigned portBASE_TYPE uxPriority) { xSimpleLinkSpawnQueue = xQueueCreate( slQUEUE_SIZE, sizeof( tSimpleLinkSpawnMsg ) ); ASSERT (xSimpleLinkSpawnQueue != NULL); /* // This is the original code to create a task dynamically ASSERT (pdPASS == xTaskCreate( vSimpleLinkSpawnTask, ( portCHAR * ) "SLSPAWN",\ 896 / sizeof(portSTACK_TYPE), NULL, uxPriority, &xSimpleLinkSpawnTaskHndl )); */ // This code creates the task using static memory for the TCB and stack xSimpleLinkSpawnTaskHndl = xTaskCreateStatic( vSimpleLinkSpawnTask, ( portCHAR * ) "SLSPAWN", 896 / sizeof(portSTACK_TYPE), NULL, uxPriority, spawnTaskStack, &spawnTaskTCB); ASSERT(xSimpleLinkSpawnTaskHndl != NULL); return OSI_OK; } /*! \brief This is the API to delete SL spawn task and delete the SL queue \param none \return void \note \warning */ void VDeleteSimpleLinkSpawnTask( void ) { if(xSimpleLinkSpawnTaskHndl) { vTaskDelete( xSimpleLinkSpawnTaskHndl ); xSimpleLinkSpawnTaskHndl = 0; } if(xSimpleLinkSpawnQueue) { vQueueDelete( xSimpleLinkSpawnQueue ); xSimpleLinkSpawnQueue = 0; } } /*! \brief This function is used to create the MsgQ \param pMsgQ - pointer to the message queue \param pMsgQName - msg queue name \param MsgSize - size of message on the queue \param MaxMsgs - max. number of msgs that the queue can hold \return - OsiReturnVal_e \note \warning */ OsiReturnVal_e osi_MsgQCreate(OsiMsgQ_t* pMsgQ , char* pMsgQName, unsigned long MsgSize, unsigned long MaxMsgs) { QueueHandle_t handle; //Create Queue handle = xQueueCreate( MaxMsgs, MsgSize ); ASSERT (handle != NULL); *pMsgQ = (OsiMsgQ_t)handle; return OSI_OK; } /*! \brief This function is used to delete the MsgQ \param pMsgQ - pointer to the message queue \return - OsiReturnVal_e \note \warning */ OsiReturnVal_e osi_MsgQDelete(OsiMsgQ_t* pMsgQ) { vQueueDelete((QueueHandle_t) *pMsgQ ); return OSI_OK; } /*! \brief This function is used to write data to the MsgQ \param pMsgQ - pointer to the message queue \param pMsg - pointer to the Msg strut to read into \param Timeout - timeout to wait for the Msg to be available \return - OsiReturnVal_e \note \warning */ OsiReturnVal_e osi_MsgQWrite(OsiMsgQ_t* pMsgQ, void* pMsg , OsiTime_t Timeout) { xHigherPriorityTaskWoken = pdFALSE; if(pdPASS == xQueueSendFromISR((QueueHandle_t) *pMsgQ, pMsg, &xHigherPriorityTaskWoken )) { taskYIELD (); return OSI_OK; } else { return OSI_OPERATION_FAILED; } } /*! \brief This function is used to read data from the MsgQ \param pMsgQ - pointer to the message queue \param pMsg - pointer to the Msg strut to read into \param Timeout - timeout to wait for the Msg to be available \return - OsiReturnVal_e \note \warning */ OsiReturnVal_e osi_MsgQRead(OsiMsgQ_t* pMsgQ, void* pMsg , OsiTime_t Timeout) { //Receive Item from Queue if( pdTRUE == xQueueReceive((QueueHandle_t)*pMsgQ,pMsg,Timeout) ) { return OSI_OK; } else { return OSI_OPERATION_FAILED; } } /*! \brief This function to call the memory de-allocation function of the FREERTOS \param Size - size of memory to alloc in bytes \return - void * \note \warning */ void * mem_Malloc(unsigned long Size) { return ( void * ) pvPortMalloc( (size_t)Size ); } /*! \brief This function to call the memory de-allocation function of the FREERTOS \param pMem - pointer to the memory which needs to be freed \return - void \note \warning */ void mem_Free(void *pMem) { vPortFree( pMem ); } /*! \brief This function call the memset function \param pBuf - pointer to the memory to be fill \param Val - Value to be fill \param Size - Size of the memory which needs to be fill \return - void \note \warning */ void mem_set(void *pBuf,int Val,size_t Size) { memset( pBuf,Val,Size); } /*! \brief This function call the memcopy function \param pDst - pointer to the destination \param pSrc - pointer to the source \param Size - Size of the memory which needs to be copy \return - void \note \warning */ void mem_copy(void *pDst, void *pSrc,size_t Size) { memcpy(pDst,pSrc,Size); } /*! \brief This function use to entering into critical section \param void \return - void \note \warning */ void osi_EnterCritical(void) { vPortEnterCritical(); } /*! \brief This function use to exit critical section \param void \return - void \note \warning */ void osi_ExitCritical(void) { vPortExitCritical(); } /*! \brief This function used to start the scheduler \param void \return - void \note \warning */ __attribute__ ((section (".boot"))) void osi_start() { vTaskStartScheduler(); } /*! \brief This function used to suspend the task for the specified number of milli secs \param MilliSecs - Time in millisecs to suspend the task \return - void \note \warning */ void osi_Sleep(unsigned int MilliSecs) { vTaskDelay(MilliSecs); } /*! \brief This function used to disable the tasks \param - void \return - Key with the suspended tasks \note \warning */ void osi_TaskDisable(void) { vTaskSuspendAll(); } /*! \brief This function used to resume all the tasks \param key - returned from suspend tasks \return - void \note \warning */ void osi_TaskEnable(void) { xTaskResumeAll(); } /*! \brief This function used to save the OS context before sleep \param void \return - void \note \warning */ void osi_ContextSave() { } /*! \brief This function used to restore the OS context after sleep \param void \return - void \note \warning */ void osi_ContextRestore() { } micropython-1.12/ports/cc3200/simplelink/user.h000066400000000000000000000716731357706137100213770ustar00rootroot00000000000000/* * user.h - CC31xx/CC32xx Host Driver Implementation * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __USER_H__ #define __USER_H__ #ifdef __cplusplus extern "C" { #endif /*! ****************************************************************************** \defgroup porting_user_include Porting - User Include Files This section IS NOT REQUIRED in case user provided primitives are handled in makefiles or project configurations (IDE) PORTING ACTION: - Include all required header files for the definition of: -# Transport layer library API (e.g. SPI, UART) -# OS primitives definitions (e.g. Task spawn, Semaphores) -# Memory management primitives (e.g. alloc, free) ****************************************************************************** */ #include #include "cc_pal.h" #include "debug.h" /*! \def MAX_CONCURRENT_ACTIONS \brief Defines the maximum number of concurrent action in the system Min:1 , Max: 32 Actions which has async events as return, can be \sa \note In case there are not enough resources for the actions needed in the system, error is received: POOL_IS_EMPTY one option is to increase MAX_CONCURRENT_ACTIONS (improves performance but results in memory consumption) Other option is to call the API later (decrease performance) \warning In case of setting to one, recommend to use non-blocking recv\recvfrom to allow multiple socket recv */ #define MAX_CONCURRENT_ACTIONS 10 /*! \def CPU_FREQ_IN_MHZ \brief Defines CPU frequency for Host side, for better accuracy of busy loops, if any \sa \note \warning If not set the default CPU frequency is set to 200MHz This option will be deprecated in future release */ #define CPU_FREQ_IN_MHZ 80 /*! ****************************************************************************** \defgroup porting_capabilities Porting - Capabilities Set This section IS NOT REQUIRED in case one of the following pre defined capabilities set is in use: - SL_TINY - SL_SMALL - SL_FULL PORTING ACTION: - Define one of the pre-defined capabilities set or uncomment the relevant definitions below to select the required capabilities @{ ******************************************************************************* */ /*! \def SL_INC_ARG_CHECK \brief Defines whether the SimpleLink driver perform argument check or not When defined, the SimpleLink driver perform argument check on function call. Removing this define could reduce some code size and improve slightly the performances but may impact in unpredictable behavior in case of invalid arguments \sa \note belongs to \ref proting_sec \warning Removing argument check may cause unpredictable behavior in case of invalid arguments. In this case the user is responsible to argument validity (for example all handlers must not be NULL) */ #define SL_INC_ARG_CHECK /*! \def SL_INC_STD_BSD_API_NAMING \brief Defines whether SimpleLink driver should expose standard BSD APIs or not When defined, the SimpleLink driver in addtion to its alternative BSD APIs expose also standard BSD APIs. Stadrad BSD API includs the following functions: socket , close , accept , bind , listen , connect , select , setsockopt , getsockopt , recv , recvfrom , write , send , sendto , gethostbyname \sa \note belongs to \ref porting_sec \warning */ /* #define SL_INC_STD_BSD_API_NAMING */ /*! \brief Defines whether to include extended API in SimpleLink driver or not When defined, the SimpleLink driver will include also all exteded API of the included packages \sa ext_api \note belongs to \ref porting_sec \warning */ #define SL_INC_EXT_API /*! \brief Defines whether to include WLAN package in SimpleLink driver or not When defined, the SimpleLink driver will include also the WLAN package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_WLAN_PKG /*! \brief Defines whether to include SOCKET package in SimpleLink driver or not When defined, the SimpleLink driver will include also the SOCKET package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_SOCKET_PKG /*! \brief Defines whether to include NET_APP package in SimpleLink driver or not When defined, the SimpleLink driver will include also the NET_APP package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_NET_APP_PKG /*! \brief Defines whether to include NET_CFG package in SimpleLink driver or not When defined, the SimpleLink driver will include also the NET_CFG package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_NET_CFG_PKG /*! \brief Defines whether to include NVMEM package in SimpleLink driver or not When defined, the SimpleLink driver will include also the NVMEM package \sa \note belongs to \ref porting_sec \warning */ #define SL_INC_NVMEM_PKG /*! \brief Defines whether to include socket server side APIs in SimpleLink driver or not When defined, the SimpleLink driver will include also socket server side APIs \sa server_side \note \warning */ #define SL_INC_SOCK_SERVER_SIDE_API /*! \brief Defines whether to include socket client side APIs in SimpleLink driver or not When defined, the SimpleLink driver will include also socket client side APIs \sa client_side \note belongs to \ref porting_sec \warning */ #define SL_INC_SOCK_CLIENT_SIDE_API /*! \brief Defines whether to include socket receive APIs in SimpleLink driver or not When defined, the SimpleLink driver will include also socket receive side APIs \sa recv_api \note belongs to \ref porting_sec \warning */ #define SL_INC_SOCK_RECV_API /*! \brief Defines whether to include socket send APIs in SimpleLink driver or not When defined, the SimpleLink driver will include also socket send side APIs \sa send_api \note belongs to \ref porting_sec \warning */ #define SL_INC_SOCK_SEND_API /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup ported_enable_device Ported on CC32XX - Device Enable/Disable The enable/disable API provide mechanism to enable/disable the network processor PORTING ACTION: - None @{ ****************************************************************************** */ /*! \brief Preamble to the enabling the Network Processor. Placeholder to implement any pre-process operations before enabling networking operations. \sa sl_DeviceEnable \note belongs to \ref ported_sec */ #ifdef DEBUG #define sl_DeviceEnablePreamble() NwpPowerOnPreamble() #else #define sl_DeviceEnablePreamble() #endif /*! \brief Enable the Network Processor \sa sl_DeviceDisable \note belongs to \ref ported_sec */ #define sl_DeviceEnable() NwpPowerOn() /*! \brief Disable the Network Processor \sa sl_DeviceEnable \note belongs to \ref ported_sec */ #define sl_DeviceDisable() NwpPowerOff() /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup ported_interface Ported on CC32XX - Communication Interface The simple link device can work with different communication channels (e.g. spi/uart). Texas Instruments provides single driver that can work with all these types. This section bind between the physical communication interface channel and the SimpleLink driver \note Correct and efficient implementation of this driver is critical for the performances of the SimpleLink device on this platform. PORTING ACTION: - None @{ ****************************************************************************** */ #define _SlFd_t Fd_t /*! \brief Opens an interface communication port to be used for communicating with a SimpleLink device Given an interface name and option flags, this function opens the communication port and creates a file descriptor. This file descriptor is used afterwards to read and write data from and to this specific communication channel. The speed, clock polarity, clock phase, chip select and all other specific attributes of the channel are all should be set to hardcoded in this function. \param ifName - points to the interface name/path. The interface name is an optional attributes that the simple link driver receives on opening the driver (sl_Start). In systems that the spi channel is not implemented as part of the os device drivers, this parameter could be NULL. \param flags - optional flags parameters for future use \return upon successful completion, the function shall open the channel and return a non-negative integer representing the file descriptor. Otherwise, -1 shall be returned \sa sl_IfClose , sl_IfRead , sl_IfWrite \note The prototype of the function is as follow: Fd_t xxx_IfOpen(char* pIfName , unsigned long flags); \note belongs to \ref ported_sec \warning */ #define sl_IfOpen spi_Open /*! \brief Closes an opened interface communication port \param fd - file descriptor of opened communication channel \return upon successful completion, the function shall return 0. Otherwise, -1 shall be returned \sa sl_IfOpen , sl_IfRead , sl_IfWrite \note The prototype of the function is as follow: int xxx_IfClose(Fd_t Fd); \note belongs to \ref ported_sec \warning */ #define sl_IfClose spi_Close /*! \brief Attempts to read up to len bytes from an opened communication channel into a buffer starting at pBuff. \param fd - file descriptor of an opened communication channel \param pBuff - pointer to the first location of a buffer that contains enough space for all expected data \param len - number of bytes to read from the communication channel \return upon successful completion, the function shall return the number of read bytes. Otherwise, 0 shall be returned \sa sl_IfClose , sl_IfOpen , sl_IfWrite \note The prototype of the function is as follow: int xxx_IfRead(Fd_t Fd , char* pBuff , int Len); \note belongs to \ref ported_sec \warning */ #define sl_IfRead spi_Read /*! \brief attempts to write up to len bytes to the SPI channel \param fd - file descriptor of an opened communication channel \param pBuff - pointer to the first location of a buffer that contains the data to send over the communication channel \param len - number of bytes to write to the communication channel \return upon successful completion, the function shall return the number of sent bytes. therwise, 0 shall be returned \sa sl_IfClose , sl_IfOpen , sl_IfRead \note This function could be implemented as zero copy and return only upon successful completion of writing the whole buffer, but in cases that memory allocation is not too tight, the function could copy the data to internal buffer, return back and complete the write in parallel to other activities as long as the other SPI activities would be blocked until the entire buffer write would be completed The prototype of the function is as follow: int xxx_IfWrite(Fd_t Fd , char* pBuff , int Len); \note belongs to \ref ported_sec \warning */ #define sl_IfWrite spi_Write /*! \brief register an interrupt handler routine for the host IRQ \param InterruptHdl - pointer to interrupt handler routine \param pValue - pointer to a memory structure that is passed to the interrupt handler. \return upon successful registration, the function shall return 0. Otherwise, -1 shall be returned \sa \note If there is already registered interrupt handler, the function should overwrite the old handler with the new one \note If the handler is a null pointer, the function should un-register the interrupt handler, and the interrupts can be disabled. \note belongs to \ref ported_sec \warning */ #define sl_IfRegIntHdlr(InterruptHdl , pValue) NwpRegisterInterruptHandler(InterruptHdl , pValue) /*! \brief Masks the Host IRQ \sa sl_IfUnMaskIntHdlr \note belongs to \ref ported_sec \warning */ #define sl_IfMaskIntHdlr() NwpMaskInterrupt() /*! \brief Unmasks the Host IRQ \sa sl_IfMaskIntHdlr \note belongs to \ref ported_sec \warning */ #define sl_IfUnMaskIntHdlr() NwpUnMaskInterrupt() /*! \brief Write Handers for statistics debug on write \param interface handler - pointer to interrupt handler routine \return no return value \sa \note An optional hooks for monitoring before and after write info \note belongs to \ref ported_sec \warning */ /* #define SL_START_WRITE_STAT */ /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup ported_os Ported on CC32XX - Operating System The simple link driver can run on multi-threaded environment as well as non-os environment (mail loop) This section IS NOT REQUIRED in case you are working on non-os environment. If you choose to work in multi-threaded environment under any operating system you will have to provide some basic adaptation routines to allow the driver to protect access to resources from different threads (locking object) and to allow synchronization between threads (sync objects). PORTING ACTION: -# Uncomment SL_PLATFORM_MULTI_THREADED define -# Bind locking object routines -# Bind synchronization object routines -# Optional - Bind spawn thread routine @{ ****************************************************************************** */ #define SL_PLATFORM_MULTI_THREADED #ifdef SL_PLATFORM_MULTI_THREADED #include "osi.h" /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define SL_OS_RET_CODE_OK ((int)OSI_OK) /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define SL_OS_WAIT_FOREVER ((OsiTime_t)OSI_WAIT_FOREVER) /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define SL_OS_NO_WAIT ((OsiTime_t)OSI_NO_WAIT) /*! \brief type definition for a time value \note On each porting or platform the type could be whatever is needed - integer, pointer to structure etc. \note belongs to \ref ported_sec */ #define _SlTime_t OsiTime_t /*! \brief type definition for a sync object container Sync object is object used to synchronize between two threads or thread and interrupt handler. One thread is waiting on the object and the other thread send a signal, which then release the waiting thread. The signal must be able to be sent from interrupt context. This object is generally implemented by binary semaphore or events. \note On each porting or platform the type could be whatever is needed - integer, structure etc. \note belongs to \ref ported_sec */ typedef OsiSyncObj_t _SlSyncObj_t; /*! \brief This function creates a sync object The sync object is used for synchronization between diffrent thread or ISR and a thread. \param pSyncObj - pointer to the sync object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_SyncObjCreate(pSyncObj,pName) osi_SyncObjCreate(pSyncObj) /*! \brief This function deletes a sync object \param pSyncObj - pointer to the sync object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_SyncObjDelete(pSyncObj) osi_SyncObjDelete(pSyncObj) /*! \brief This function generates a sync signal for the object. All suspended threads waiting on this sync object are resumed \param pSyncObj - pointer to the sync object control block \return upon successful signaling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function could be called from ISR context \warning */ #define sl_SyncObjSignal(pSyncObj) osi_SyncObjSignal(pSyncObj) /*! \brief This function generates a sync signal for the object from Interrupt This is for RTOS that should signal from IRQ using a dedicated API \param pSyncObj - pointer to the sync object control block \return upon successful signaling the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note the function could be called from ISR context \warning */ #define sl_SyncObjSignalFromIRQ(pSyncObj) osi_SyncObjSignalFromISR(pSyncObj) /*! \brief This function waits for a sync signal of the specific sync object \param pSyncObj - pointer to the sync object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the sync signal Currently, the simple link driver uses only two values: - OSI_WAIT_FOREVER - OSI_NO_WAIT \return upon successful reception of the signal within the timeout window return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_SyncObjWait(pSyncObj,Timeout) osi_SyncObjWait(pSyncObj,Timeout) /*! \brief type definition for a locking object container Locking object are used to protect a resource from mutual accesses of two or more threads. The locking object should suppurt reentrant locks by a signal thread. This object is generally implemented by mutex semaphore \note On each porting or platform the type could be whatever is needed - integer, structure etc. \note belongs to \ref ported_sec */ typedef OsiLockObj_t _SlLockObj_t; /*! \brief This function creates a locking object. The locking object is used for protecting a shared resources between different threads. \param pLockObj - pointer to the locking object control block \return upon successful creation the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_LockObjCreate(pLockObj,pName) osi_LockObjCreate(pLockObj) /*! \brief This function deletes a locking object. \param pLockObj - pointer to the locking object control block \return upon successful deletion the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_LockObjDelete(pLockObj) osi_LockObjDelete(pLockObj) /*! \brief This function locks a locking object. All other threads that call this function before this thread calls the osi_LockObjUnlock would be suspended \param pLockObj - pointer to the locking object control block \param Timeout - numeric value specifies the maximum number of mSec to stay suspended while waiting for the locking object Currently, the simple link driver uses only two values: - OSI_WAIT_FOREVER - OSI_NO_WAIT \return upon successful reception of the locking object the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_LockObjLock(pLockObj,Timeout) osi_LockObjLock(pLockObj,Timeout) /*! \brief This function unlock a locking object. \param pLockObj - pointer to the locking object control block \return upon successful unlocking the function should return 0 Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define sl_LockObjUnlock(pLockObj) osi_LockObjUnlock(pLockObj) #endif /*! \brief This function call the pEntry callback from a different context \param pEntry - pointer to the entry callback function \param pValue - pointer to any type of memory structure that would be passed to pEntry callback from the execution thread. \param flags - execution flags - reserved for future usage \return upon successful registration of the spawn the function should return 0 (the function is not blocked till the end of the execution of the function and could be returned before the execution is actually completed) Otherwise, a negative value indicating the error code shall be returned \note belongs to \ref ported_sec \warning */ #define SL_PLATFORM_EXTERNAL_SPAWN #ifdef SL_PLATFORM_EXTERNAL_SPAWN #define sl_Spawn(pEntry,pValue,flags) osi_Spawn(pEntry,pValue,flags) #endif /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup porting_mem_mgm Porting - Memory Management This section declare in which memory management model the SimpleLink driver will run: -# Static -# Dynamic This section IS NOT REQUIRED in case Static model is selected. The default memory model is Static PORTING ACTION: - If dynamic model is selected, define the alloc and free functions. @{ ***************************************************************************** */ /*! \brief Defines whether the SimpleLink driver is working in dynamic memory model or not When defined, the SimpleLink driver use dynamic allocations if dynamic allocation is selected malloc and free functions must be retrieved \sa \note belongs to \ref porting_sec \warning */ #define SL_MEMORY_MGMT_DYNAMIC 1 #define SL_MEMORY_MGMT_STATIC 0 #define SL_MEMORY_MGMT SL_MEMORY_MGMT_DYNAMIC #ifdef SL_MEMORY_MGMT_DYNAMIC #ifdef SL_PLATFORM_MULTI_THREADED /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define sl_Malloc(Size) mem_Malloc(Size) /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define sl_Free(pMem) mem_Free(pMem) #else #include /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define sl_Malloc(Size) malloc(Size) /*! \brief \sa \note belongs to \ref ported_sec \warning */ #define sl_Free(pMem) free(pMem) #endif #endif /*! Close the Doxygen group. @} */ /*! ****************************************************************************** \defgroup porting_events Porting - Event Handlers This section includes the asynchronous event handlers routines PORTING ACTION: -Uncomment the required handler and define your routine as the value of this handler @{ ****************************************************************************** */ /*! \brief \sa \note belongs to \ref porting_sec \warning */ #define sl_GeneralEvtHdlr SimpleLinkGeneralEventHandler /*! \brief An event handler for WLAN connection or disconnection indication This event handles async WLAN events. Possible events are: SL_WLAN_CONNECT_EVENT - indicates WLAN is connected SL_WLAN_DISCONNECT_EVENT - indicates WLAN is disconnected \sa \note belongs to \ref porting_sec \warning */ #define sl_WlanEvtHdlr SimpleLinkWlanEventHandler /*! \brief An event handler for IP address asynchronous event. Usually accepted after new WLAN connection. This event handles networking events. Possible events are: SL_NETAPP_IPV4_ACQUIRED - IP address was acquired (DHCP or Static) \sa \note belongs to \ref porting_sec \warning */ #define sl_NetAppEvtHdlr SimpleLinkNetAppEventHandler /*! \brief A callback for HTTP server events. Possible events are: SL_NETAPP_HTTPGETTOKENVALUE - NWP requests to get the value of a specific token SL_NETAPP_HTTPPOSTTOKENVALUE - NWP post to the host a new value for a specific token \param pServerEvent - Contains the relevant event information (SL_NETAPP_HTTPGETTOKENVALUE or SL_NETAPP_HTTPPOSTTOKENVALUE) \param pServerResponse - Should be filled by the user with the relevant response information (i.e SL_NETAPP_HTTPSETTOKENVALUE as a response to SL_NETAPP_HTTPGETTOKENVALUE event) \sa \note belongs to \ref porting_sec \warning */ #define sl_HttpServerCallback SimpleLinkHttpServerCallback /*! \brief \sa \note belongs to \ref porting_sec \warning */ #define sl_SockEvtHdlr SimpleLinkSockEventHandler #define _SL_USER_TYPES #define _u8 unsigned char #define _i8 signed char #define _u16 unsigned short #define _i16 signed short #define _u32 unsigned int #define _i32 signed int #define _volatile volatile #define _const const /*! Close the Doxygen group. @} */ #ifdef __cplusplus } #endif // __cplusplus #endif // __USER_H__ micropython-1.12/ports/cc3200/telnet/000077500000000000000000000000001357706137100173565ustar00rootroot00000000000000micropython-1.12/ports/cc3200/telnet/telnet.c000066400000000000000000000470461357706137100210300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpconfig.h" #include "py/obj.h" #include "py/mphal.h" #include "lib/utils/interrupt_char.h" #include "telnet.h" #include "simplelink.h" #include "modnetwork.h" #include "modwlan.h" #include "modusocket.h" #include "debug.h" #include "mpexception.h" #include "serverstask.h" #include "genhdr/mpversion.h" #include "irq.h" /****************************************************************************** DEFINE PRIVATE CONSTANTS ******************************************************************************/ #define TELNET_PORT 23 // rxRindex and rxWindex must be uint8_t and TELNET_RX_BUFFER_SIZE == 256 #define TELNET_RX_BUFFER_SIZE 256 #define TELNET_MAX_CLIENTS 1 #define TELNET_TX_RETRIES_MAX 50 #define TELNET_WAIT_TIME_MS 5 #define TELNET_LOGIN_RETRIES_MAX 3 #define TELNET_CYCLE_TIME_MS (SERVERS_CYCLE_TIME_MS * 2) /****************************************************************************** DEFINE PRIVATE TYPES ******************************************************************************/ typedef enum { E_TELNET_RESULT_OK = 0, E_TELNET_RESULT_AGAIN, E_TELNET_RESULT_FAILED } telnet_result_t; typedef enum { E_TELNET_STE_DISABLED = 0, E_TELNET_STE_START, E_TELNET_STE_LISTEN, E_TELNET_STE_CONNECTED, E_TELNET_STE_LOGGED_IN } telnet_state_t; typedef enum { E_TELNET_STE_SUB_WELCOME, E_TELNET_STE_SUB_SND_USER_OPTIONS, E_TELNET_STE_SUB_REQ_USER, E_TELNET_STE_SUB_GET_USER, E_TELNET_STE_SUB_REQ_PASSWORD, E_TELNET_STE_SUB_SND_PASSWORD_OPTIONS, E_TELNET_STE_SUB_GET_PASSWORD, E_TELNET_STE_SUB_INVALID_LOGGIN, E_TELNET_STE_SUB_SND_REPL_OPTIONS, E_TELNET_STE_SUB_LOGGIN_SUCCESS } telnet_connected_substate_t; typedef union { telnet_connected_substate_t connected; } telnet_substate_t; typedef struct { uint8_t *rxBuffer; uint32_t timeout; telnet_state_t state; telnet_substate_t substate; int16_t sd; int16_t n_sd; // rxRindex and rxWindex must be uint8_t and TELNET_RX_BUFFER_SIZE == 256 uint8_t rxWindex; uint8_t rxRindex; uint8_t txRetries; uint8_t logginRetries; bool enabled; bool credentialsValid; } telnet_data_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ static telnet_data_t telnet_data; static const char* telnet_welcome_msg = "MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"; static const char* telnet_request_user = "Login as: "; static const char* telnet_request_password = "Password: "; static const char* telnet_invalid_loggin = "\r\nInvalid credentials, try again.\r\n"; static const char* telnet_loggin_success = "\r\nLogin succeeded!\r\nType \"help()\" for more information.\r\n"; static const uint8_t telnet_options_user[] = // IAC WONT ECHO IAC WONT SUPPRESS_GO_AHEAD IAC WILL LINEMODE { 255, 252, 1, 255, 252, 3, 255, 251, 34 }; static const uint8_t telnet_options_pass[] = // IAC WILL ECHO IAC WONT SUPPRESS_GO_AHEAD IAC WILL LINEMODE { 255, 251, 1, 255, 252, 3, 255, 251, 34 }; static const uint8_t telnet_options_repl[] = // IAC WILL ECHO IAC WILL SUPPRESS_GO_AHEAD IAC WONT LINEMODE { 255, 251, 1, 255, 251, 3, 255, 252, 34 }; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ static void telnet_wait_for_enabled (void); static bool telnet_create_socket (void); static void telnet_wait_for_connection (void); static void telnet_send_and_proceed (void *data, _i16 Len, telnet_connected_substate_t next_state); static telnet_result_t telnet_send_non_blocking (void *data, _i16 Len); static telnet_result_t telnet_recv_text_non_blocking (void *buff, _i16 Maxlen, _i16 *rxLen); static void telnet_process (void); static int telnet_process_credential (char *credential, _i16 rxLen); static void telnet_parse_input (uint8_t *str, int16_t *len); static bool telnet_send_with_retries (int16_t sd, const void *pBuf, int16_t len); static void telnet_reset_buffer (void); /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void telnet_init (void) { // Allocate memory for the receive buffer (from the RTOS heap) ASSERT ((telnet_data.rxBuffer = mem_Malloc(TELNET_RX_BUFFER_SIZE)) != NULL); telnet_data.state = E_TELNET_STE_DISABLED; } void telnet_run (void) { _i16 rxLen; switch (telnet_data.state) { case E_TELNET_STE_DISABLED: telnet_wait_for_enabled(); break; case E_TELNET_STE_START: if (wlan_is_connected() && telnet_create_socket()) { telnet_data.state = E_TELNET_STE_LISTEN; } break; case E_TELNET_STE_LISTEN: telnet_wait_for_connection(); break; case E_TELNET_STE_CONNECTED: switch (telnet_data.substate.connected) { case E_TELNET_STE_SUB_WELCOME: telnet_send_and_proceed((void *)telnet_welcome_msg, strlen(telnet_welcome_msg), E_TELNET_STE_SUB_SND_USER_OPTIONS); break; case E_TELNET_STE_SUB_SND_USER_OPTIONS: telnet_send_and_proceed((void *)telnet_options_user, sizeof(telnet_options_user), E_TELNET_STE_SUB_REQ_USER); break; case E_TELNET_STE_SUB_REQ_USER: // to catch any left over characters from the previous actions telnet_recv_text_non_blocking(telnet_data.rxBuffer, TELNET_RX_BUFFER_SIZE, &rxLen); telnet_send_and_proceed((void *)telnet_request_user, strlen(telnet_request_user), E_TELNET_STE_SUB_GET_USER); break; case E_TELNET_STE_SUB_GET_USER: if (E_TELNET_RESULT_OK == telnet_recv_text_non_blocking(telnet_data.rxBuffer + telnet_data.rxWindex, TELNET_RX_BUFFER_SIZE - telnet_data.rxWindex, &rxLen)) { int result; if ((result = telnet_process_credential (servers_user, rxLen))) { telnet_data.credentialsValid = result > 0 ? true : false; telnet_data.substate.connected = E_TELNET_STE_SUB_REQ_PASSWORD; } } break; case E_TELNET_STE_SUB_REQ_PASSWORD: telnet_send_and_proceed((void *)telnet_request_password, strlen(telnet_request_password), E_TELNET_STE_SUB_SND_PASSWORD_OPTIONS); break; case E_TELNET_STE_SUB_SND_PASSWORD_OPTIONS: // to catch any left over characters from the previous actions telnet_recv_text_non_blocking(telnet_data.rxBuffer, TELNET_RX_BUFFER_SIZE, &rxLen); telnet_send_and_proceed((void *)telnet_options_pass, sizeof(telnet_options_pass), E_TELNET_STE_SUB_GET_PASSWORD); break; case E_TELNET_STE_SUB_GET_PASSWORD: if (E_TELNET_RESULT_OK == telnet_recv_text_non_blocking(telnet_data.rxBuffer + telnet_data.rxWindex, TELNET_RX_BUFFER_SIZE - telnet_data.rxWindex, &rxLen)) { int result; if ((result = telnet_process_credential (servers_pass, rxLen))) { if ((telnet_data.credentialsValid = telnet_data.credentialsValid && (result > 0 ? true : false))) { telnet_data.substate.connected = E_TELNET_STE_SUB_SND_REPL_OPTIONS; } else { telnet_data.substate.connected = E_TELNET_STE_SUB_INVALID_LOGGIN; } } } break; case E_TELNET_STE_SUB_INVALID_LOGGIN: if (E_TELNET_RESULT_OK == telnet_send_non_blocking((void *)telnet_invalid_loggin, strlen(telnet_invalid_loggin))) { telnet_data.credentialsValid = true; if (++telnet_data.logginRetries >= TELNET_LOGIN_RETRIES_MAX) { telnet_reset(); } else { telnet_data.substate.connected = E_TELNET_STE_SUB_SND_USER_OPTIONS; } } break; case E_TELNET_STE_SUB_SND_REPL_OPTIONS: telnet_send_and_proceed((void *)telnet_options_repl, sizeof(telnet_options_repl), E_TELNET_STE_SUB_LOGGIN_SUCCESS); break; case E_TELNET_STE_SUB_LOGGIN_SUCCESS: if (E_TELNET_RESULT_OK == telnet_send_non_blocking((void *)telnet_loggin_success, strlen(telnet_loggin_success))) { // clear the current line and force the prompt telnet_reset_buffer(); telnet_data.state= E_TELNET_STE_LOGGED_IN; } default: break; } break; case E_TELNET_STE_LOGGED_IN: telnet_process(); break; default: break; } if (telnet_data.state >= E_TELNET_STE_CONNECTED) { if (telnet_data.timeout++ > (servers_get_timeout() / TELNET_CYCLE_TIME_MS)) { telnet_reset(); } } } void telnet_tx_strn (const char *str, int len) { if (telnet_data.n_sd > 0 && telnet_data.state == E_TELNET_STE_LOGGED_IN && len > 0) { telnet_send_with_retries(telnet_data.n_sd, str, len); } } bool telnet_rx_any (void) { return (telnet_data.n_sd > 0) ? (telnet_data.rxRindex != telnet_data.rxWindex && telnet_data.state == E_TELNET_STE_LOGGED_IN) : false; } int telnet_rx_char (void) { int rx_char = -1; if (telnet_data.rxRindex != telnet_data.rxWindex) { // rxRindex must be uint8_t and TELNET_RX_BUFFER_SIZE == 256 so that it wraps around automatically rx_char = (int)telnet_data.rxBuffer[telnet_data.rxRindex++]; } return rx_char; } void telnet_enable (void) { telnet_data.enabled = true; } void telnet_disable (void) { telnet_reset(); telnet_data.enabled = false; telnet_data.state = E_TELNET_STE_DISABLED; } void telnet_reset (void) { // close the connection and start all over again servers_close_socket(&telnet_data.n_sd); servers_close_socket(&telnet_data.sd); telnet_data.state = E_TELNET_STE_START; } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ static void telnet_wait_for_enabled (void) { // Init telnet's data telnet_data.n_sd = -1; telnet_data.sd = -1; // Check if the telnet service has been enabled if (telnet_data.enabled) { telnet_data.state = E_TELNET_STE_START; } } static bool telnet_create_socket (void) { SlSockNonblocking_t nonBlockingOption; SlSockAddrIn_t sServerAddress; _i16 result; // Open a socket for telnet ASSERT ((telnet_data.sd = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_TCP)) > 0); if (telnet_data.sd > 0) { // add the socket to the network administration modusocket_socket_add(telnet_data.sd, false); // Enable non-blocking mode nonBlockingOption.NonblockingEnabled = 1; ASSERT ((result = sl_SetSockOpt(telnet_data.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK); // Bind the socket to a port number sServerAddress.sin_family = SL_AF_INET; sServerAddress.sin_addr.s_addr = SL_INADDR_ANY; sServerAddress.sin_port = sl_Htons(TELNET_PORT); ASSERT ((result |= sl_Bind(telnet_data.sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK); // Start listening ASSERT ((result |= sl_Listen (telnet_data.sd, TELNET_MAX_CLIENTS)) == SL_SOC_OK); if (result == SL_SOC_OK) { return true; } servers_close_socket(&telnet_data.sd); } return false; } static void telnet_wait_for_connection (void) { SlSocklen_t in_addrSize; SlSockAddrIn_t sClientAddress; // accepts a connection from a TCP client, if there is any, otherwise returns SL_EAGAIN telnet_data.n_sd = sl_Accept(telnet_data.sd, (SlSockAddr_t *)&sClientAddress, (SlSocklen_t *)&in_addrSize); if (telnet_data.n_sd == SL_EAGAIN) { return; } else { if (telnet_data.n_sd <= 0) { // error telnet_reset(); return; } // close the listening socket, we don't need it anymore servers_close_socket(&telnet_data.sd); // add the new socket to the network administration modusocket_socket_add(telnet_data.n_sd, false); // client connected, so go on telnet_data.rxWindex = 0; telnet_data.rxRindex = 0; telnet_data.txRetries = 0; telnet_data.state = E_TELNET_STE_CONNECTED; telnet_data.substate.connected = E_TELNET_STE_SUB_WELCOME; telnet_data.credentialsValid = true; telnet_data.logginRetries = 0; telnet_data.timeout = 0; } } static void telnet_send_and_proceed (void *data, _i16 Len, telnet_connected_substate_t next_state) { if (E_TELNET_RESULT_OK == telnet_send_non_blocking(data, Len)) { telnet_data.substate.connected = next_state; } } static telnet_result_t telnet_send_non_blocking (void *data, _i16 Len) { int16_t result = sl_Send(telnet_data.n_sd, data, Len, 0); if (result > 0) { telnet_data.txRetries = 0; return E_TELNET_RESULT_OK; } else if ((TELNET_TX_RETRIES_MAX >= ++telnet_data.txRetries) && (result == SL_EAGAIN)) { return E_TELNET_RESULT_AGAIN; } else { // error telnet_reset(); return E_TELNET_RESULT_FAILED; } } static telnet_result_t telnet_recv_text_non_blocking (void *buff, _i16 Maxlen, _i16 *rxLen) { *rxLen = sl_Recv(telnet_data.n_sd, buff, Maxlen, 0); // if there's data received, parse it if (*rxLen > 0) { telnet_data.timeout = 0; telnet_parse_input (buff, rxLen); if (*rxLen > 0) { return E_TELNET_RESULT_OK; } } else if (*rxLen != SL_EAGAIN) { // error telnet_reset(); return E_TELNET_RESULT_FAILED; } return E_TELNET_RESULT_AGAIN; } static void telnet_process (void) { _i16 rxLen; _i16 maxLen = (telnet_data.rxWindex >= telnet_data.rxRindex) ? (TELNET_RX_BUFFER_SIZE - telnet_data.rxWindex) : ((telnet_data.rxRindex - telnet_data.rxWindex) - 1); // to avoid an overrrun maxLen = (telnet_data.rxRindex == 0) ? (maxLen - 1) : maxLen; if (maxLen > 0) { if (E_TELNET_RESULT_OK == telnet_recv_text_non_blocking(&telnet_data.rxBuffer[telnet_data.rxWindex], maxLen, &rxLen)) { // rxWindex must be uint8_t and TELNET_RX_BUFFER_SIZE == 256 so that it wraps around automatically telnet_data.rxWindex = telnet_data.rxWindex + rxLen; } } } static int telnet_process_credential (char *credential, _i16 rxLen) { telnet_data.rxWindex += rxLen; if (telnet_data.rxWindex >= SERVERS_USER_PASS_LEN_MAX) { telnet_data.rxWindex = SERVERS_USER_PASS_LEN_MAX; } uint8_t *p = telnet_data.rxBuffer + SERVERS_USER_PASS_LEN_MAX; // if a '\r' is found, or the length exceeds the max username length if ((p = memchr(telnet_data.rxBuffer, '\r', telnet_data.rxWindex)) || (telnet_data.rxWindex >= SERVERS_USER_PASS_LEN_MAX)) { uint8_t len = p - telnet_data.rxBuffer; telnet_data.rxWindex = 0; if ((len > 0) && (memcmp(credential, telnet_data.rxBuffer, MAX(len, strlen(credential))) == 0)) { return 1; } return -1; } return 0; } static void telnet_parse_input (uint8_t *str, int16_t *len) { int16_t b_len = *len; uint8_t *b_str = str; for (uint8_t *_str = b_str; _str < b_str + b_len; ) { if (*_str <= 127) { if (telnet_data.state == E_TELNET_STE_LOGGED_IN && *_str == mp_interrupt_char) { // raise a keyboard exception mp_keyboard_interrupt(); (*len)--; _str++; } else if (*_str > 0) { *str++ = *_str++; } else { _str++; *len -= 1; } } else { // in case we have received an incomplete telnet option, unlikely, but possible _str += MIN(3, *len); *len -= MIN(3, *len); } } } static bool telnet_send_with_retries (int16_t sd, const void *pBuf, int16_t len) { int32_t retries = 0; uint32_t delay = TELNET_WAIT_TIME_MS; // only if we are not within interrupt context and interrupts are enabled if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) { do { _i16 result = sl_Send(sd, pBuf, len, 0); if (result > 0) { return true; } else if (SL_EAGAIN != result) { return false; } // start with the default delay and increment it on each retry mp_hal_delay_ms(delay++); } while (++retries <= TELNET_TX_RETRIES_MAX); } return false; } static void telnet_reset_buffer (void) { // erase any characters present in the current line memset (telnet_data.rxBuffer, '\b', TELNET_RX_BUFFER_SIZE / 2); telnet_data.rxWindex = TELNET_RX_BUFFER_SIZE / 2; // fake an "enter" key pressed to display the prompt telnet_data.rxBuffer[telnet_data.rxWindex++] = '\r'; } micropython-1.12/ports/cc3200/telnet/telnet.h000066400000000000000000000034711357706137100210270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_TELNET_TELNET_H #define MICROPY_INCLUDED_CC3200_TELNET_TELNET_H /****************************************************************************** DECLARE EXPORTED FUNCTIONS ******************************************************************************/ extern void telnet_init (void); extern void telnet_run (void); extern void telnet_tx_strn (const char *str, int len); extern bool telnet_rx_any (void); extern int telnet_rx_char (void); extern void telnet_enable (void); extern void telnet_disable (void); extern void telnet_reset (void); #endif // MICROPY_INCLUDED_CC3200_TELNET_TELNET_H micropython-1.12/ports/cc3200/tools/000077500000000000000000000000001357706137100172235ustar00rootroot00000000000000micropython-1.12/ports/cc3200/tools/smoke.py000066400000000000000000000035321357706137100207160ustar00rootroot00000000000000from machine import Pin from machine import RTC import time import os """ Execute it like this: python3 run-tests --target wipy --device 192.168.1.1 ../cc3200/tools/smoke.py """ pin_map = [23, 24, 11, 12, 13, 14, 15, 16, 17, 22, 28, 10, 9, 8, 7, 6, 30, 31, 3, 0, 4, 5] test_bytes = os.urandom(1024) def test_pin_read (pull): # enable the pull resistor on all pins, then read the value for p in pin_map: pin = Pin('GP' + str(p), mode=Pin.IN, pull=pull) # read the pin value print(pin()) def test_pin_shorts (pull): if pull == Pin.PULL_UP: pull_inverted = Pin.PULL_DOWN else: pull_inverted = Pin.PULL_UP # enable all pulls of the specified type for p in pin_map: pin = Pin('GP' + str(p), mode=Pin.IN, pull=pull_inverted) # then change the pull one pin at a time and read its value i = 0 while i < len(pin_map): pin = Pin('GP' + str(pin_map[i]), mode=Pin.IN, pull=pull) Pin('GP' + str(pin_map[i - 1]), mode=Pin.IN, pull=pull_inverted) i += 1 # read the pin value print(pin()) test_pin_read(Pin.PULL_UP) test_pin_read(Pin.PULL_DOWN) test_pin_shorts(Pin.PULL_UP) test_pin_shorts(Pin.PULL_DOWN) # create a test directory os.mkdir('/flash/test') os.chdir('/flash/test') print(os.getcwd()) # create a new file f = open('test.txt', 'w') n_w = f.write(test_bytes) print(n_w == len(test_bytes)) f.close() f = open('test.txt', 'r') r = bytes(f.read(), 'ascii') # check that we can write and read it correctly print(r == test_bytes) f.close() os.remove('test.txt') os.chdir('..') os.rmdir('test') ls = os.listdir() print('test' not in ls) print(ls) # test the real time clock rtc = RTC() while rtc.now()[6] > 800: pass time1 = rtc.now() time.sleep_ms(1000) time2 = rtc.now() print(time2[5] - time1[5] == 1) print(time2[6] - time1[6] < 5000) # microseconds micropython-1.12/ports/cc3200/tools/smoke.py.exp000066400000000000000000000004021357706137100215020ustar00rootroot000000000000001 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 /flash/test True True True ['main.py', 'sys', 'lib', 'cert', 'boot.py'] True True micropython-1.12/ports/cc3200/tools/uniflash.py000066400000000000000000000056441357706137100214170ustar00rootroot00000000000000#!/usr/bin/env python """ Flash the WiPy (format, update service pack and program). Example: > python uniflash.py -u "C:\ti\uniflash_3.2\uniflashCLI.bat" -c "C:\VirtualBoxShared\GitHub\wipy_uniflash.usf" -p 8 -s "C:\ti\CC31xx_CC32xx_ServicePack_1.0.0.10.0\servicepack_1.0.0.10.0.bin" or: > python uniflash.py -u "C:\ti\uniflash_3.2\uniflashCLI.bat" -c "C:\VirtualBoxShared\GitHub\launchxl_uniflash.usf" -p 8 -s "C:\ti\CC31xx_CC32xx_ServicePack_1.0.0.10.0\servicepack_1.0.0.10.0.bin" """ import sys import argparse import subprocess def print_exception(e): print ('Exception: {}, on line {}'.format(e, sys.exc_info()[-1].tb_lineno)) def execute(command): process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) cmd_log = "" # Poll process for new output until finished while True: nextline = process.stdout.readline() if nextline == '' and process.poll() != None: break sys.stdout.write(nextline) sys.stdout.flush() cmd_log += nextline output = process.communicate()[0] exitCode = process.returncode if exitCode == 0: return cmd_log else: raise ProcessException(command, exitCode, output) def main(): cmd_parser = argparse.ArgumentParser(description='Flash the WiPy and optionally run a small test on it.') cmd_parser.add_argument('-u', '--uniflash', default=None, help='the path to the uniflash cli executable') cmd_parser.add_argument('-c', '--config', default=None, help='the path to the uniflash config file') cmd_parser.add_argument('-p', '--port', default=8, help='the com serial port') cmd_parser.add_argument('-s', '--servicepack', default=None, help='the path to the servicepack file') args = cmd_parser.parse_args() output = "" com_port = 'com=' + str(args.port) servicepack_path = 'spPath=' + args.servicepack try: if args.uniflash == None or args.config == None: raise ValueError('uniflash path and config path are mandatory') if args.servicepack == None: output += execute([args.uniflash, '-config', args.config, '-setOptions', com_port, '-operations', 'format', 'program']) else: output += execute([args.uniflash, '-config', args.config, '-setOptions', com_port, servicepack_path, '-operations', 'format', 'servicePackUpdate', 'program']) except Exception as e: print_exception(e) output = "" finally: if "Finish Executing operation: program" in output: print("======================================") print("Board programmed OK") print("======================================") sys.exit(0) else: print("======================================") print("ERROR: Programming failed!") print("======================================") sys.exit(1) if __name__ == "__main__": main() micropython-1.12/ports/cc3200/tools/update-wipy.py000066400000000000000000000155561357706137100220610ustar00rootroot00000000000000#!/usr/bin/env python """ The WiPy firmware update script. Transmits the specified firmware file over FTP, and then resets the WiPy and optionally verifies that software was correctly updated. Usage: ./update-wipy.py --file "path_to_mcuimg.bin" --verify Or: python update-wipy.py --file "path_to_mcuimg.bin" """ import sys import argparse import time import socket from ftplib import FTP from telnetlib import Telnet def print_exception(e): print ('Exception: {}, on line {}'.format(e, sys.exc_info()[-1].tb_lineno)) def ftp_directory_exists(ftpobj, directory_name): filelist = [] ftpobj.retrlines('LIST',filelist.append) for f in filelist: if f.split()[-1] == directory_name: return True return False def transfer_file(args): with FTP(args.ip, timeout=20) as ftp: print ('FTP connection established') if '230' in ftp.login(args.user, args.password): print ('Login successful') if '250' in ftp.cwd('/flash'): if not ftp_directory_exists(ftp, 'sys'): print ('/flash/sys directory does not exist') if not '550' in ftp.mkd('sys'): print ('/flash/sys directory created') else: print ('Error: cannot create /flash/sys directory') return False if '250' in ftp.cwd('sys'): print ("Entered '/flash/sys' directory") with open(args.file, "rb") as fwfile: print ('Firmware image found, initiating transfer...') if '226' in ftp.storbinary("STOR " + 'mcuimg.bin', fwfile, 512): print ('File transfer complete') return True else: print ('Error: file transfer failed') else: print ('Error: cannot enter /flash/sys directory') else: print ('Error: cannot enter /flash directory') else: print ('Error: ftp login failed') return False def reset_board(args): success = False try: tn = Telnet(args.ip, timeout=5) print("Connected via Telnet, trying to login now") if b'Login as:' in tn.read_until(b"Login as:", timeout=5): tn.write(bytes(args.user, 'ascii') + b"\r\n") if b'Password:' in tn.read_until(b"Password:", timeout=5): # needed because of internal implementation details of the WiPy's telnet server time.sleep(0.2) tn.write(bytes(args.password, 'ascii') + b"\r\n") if b'Type "help()" for more information.' in tn.read_until(b'Type "help()" for more information.', timeout=5): print("Telnet login succeeded") tn.write(b'\r\x03\x03') # ctrl-C twice: interrupt any running program time.sleep(1) tn.write(b'\r\x02') # ctrl-B: enter friendly REPL if b'Type "help()" for more information.' in tn.read_until(b'Type "help()" for more information.', timeout=5): tn.write(b"import machine\r\n") tn.write(b"machine.reset()\r\n") time.sleep(2) print("Reset performed") success = True else: print("Error: cannot enter friendly REPL") else: print("Error: telnet login failed") except Exception as e: print_exception(e) finally: try: tn.close() except Exception as e: pass return success def verify_update(args): success = False firmware_tag = '' def find_tag (tag): if tag in firmware_tag: print("Verification passed") return True else: print("Error: verification failed, the git tag doesn't match") return False retries = 0 while True: try: # Specify a longer time out value here because the board has just been # reset and the wireless connection might not be fully established yet tn = Telnet(args.ip, timeout=10) print("Connected via telnet again, lets check the git tag") break except socket.timeout: if retries < 5: print("Timeout while connecting via telnet, retrying...") retries += 1 else: print('Error: Telnet connection timed out!') return False try: firmware_tag = tn.read_until (b'with CC3200') tag_file_path = args.file.rstrip('mcuimg.bin') + 'genhdr/mpversion.h' if args.tag is not None: success = find_tag(bytes(args.tag, 'ascii')) else: with open(tag_file_path) as tag_file: for line in tag_file: bline = bytes(line, 'ascii') if b'MICROPY_GIT_HASH' in bline: bline = bline.lstrip(b'#define MICROPY_GIT_HASH ').replace(b'"', b'').replace(b'\r', b'').replace(b'\n', b'') success = find_tag(bline) break except Exception as e: print_exception(e) finally: try: tn.close() except Exception as e: pass return success def main(): cmd_parser = argparse.ArgumentParser(description='Update the WiPy firmware with the specified image file') cmd_parser.add_argument('-f', '--file', default=None, help='the path of the firmware file') cmd_parser.add_argument('-u', '--user', default='micro', help='the username') cmd_parser.add_argument('-p', '--password', default='python', help='the login password') cmd_parser.add_argument('--ip', default='192.168.1.1', help='the ip address of the WiPy') cmd_parser.add_argument('--verify', action='store_true', help='verify that the update succeeded') cmd_parser.add_argument('-t', '--tag', default=None, help='git tag of the firmware image') args = cmd_parser.parse_args() result = 1 try: if args.file is None: raise ValueError('the image file path must be specified') if transfer_file(args): if reset_board(args): if args.verify: print ('Waiting for the WiFi connection to come up again...') # this time is to allow the system's wireless network card to # connect to the WiPy again. time.sleep(5) if verify_update(args): result = 0 else: result = 0 except Exception as e: print_exception(e) finally: sys.exit(result) if __name__ == "__main__": main() micropython-1.12/ports/cc3200/util/000077500000000000000000000000001357706137100170405ustar00rootroot00000000000000micropython-1.12/ports/cc3200/util/cryptohash.c000066400000000000000000000053401357706137100213720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_shamd5.h" #include "inc/hw_dthe.h" #include "hw_memmap.h" #include "rom_map.h" #include "prcm.h" #include "shamd5.h" #include "cryptohash.h" /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void CRYPTOHASH_Init (void) { // Enable the Data Hashing and Transform Engine MAP_PRCMPeripheralClkEnable(PRCM_DTHE, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); MAP_PRCMPeripheralReset(PRCM_DTHE); } void CRYPTOHASH_SHAMD5Start (uint32_t algo, uint32_t blocklen) { // wait until the context is ready while ((HWREG(SHAMD5_BASE + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_CONTEXT_READY) == 0); // Configure the SHA/MD5 module algorithm MAP_SHAMD5ConfigSet(SHAMD5_BASE, algo); // if not a multiple of 64 bytes, close the hash if (blocklen % 64) { HWREG(SHAMD5_BASE + SHAMD5_O_MODE) |= SHAMD5_MODE_CLOSE_HASH; } // set the lenght HWREG(SHAMD5_BASE + SHAMD5_O_LENGTH) = blocklen; } void CRYPTOHASH_SHAMD5Update (uint8_t *data, uint32_t datalen) { // write the data SHAMD5DataWriteMultiple(data, datalen); } void CRYPTOHASH_SHAMD5Read (uint8_t *hash) { // wait for the output to be ready while((HWREG(SHAMD5_BASE + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) == 0); // read the result MAP_SHAMD5ResultRead(SHAMD5_BASE, hash); } micropython-1.12/ports/cc3200/util/cryptohash.h000066400000000000000000000034011357706137100213730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_UTIL_CRYPTOHASH_H #define MICROPY_INCLUDED_CC3200_UTIL_CRYPTOHASH_H /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ extern void CRYPTOHASH_Init (void); extern void CRYPTOHASH_SHAMD5Start (uint32_t algo, uint32_t blocklen); extern void CRYPTOHASH_SHAMD5Update (uint8_t *data, uint32_t datalen); extern void CRYPTOHASH_SHAMD5Read (uint8_t *hash); #endif // MICROPY_INCLUDED_CC3200_UTIL_CRYPTOHASH_H micropython-1.12/ports/cc3200/util/fifo.c000066400000000000000000000073301357706137100201320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "fifo.h" /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void FIFO_Init (FIFO_t *fifo, unsigned int uiElementsMax, void (*pfElmentPush)(void * const pvFifo, const void * const pvElement), void (*pfElementPop)(void * const pvFifo, void * const pvElement)) { if (fifo) { fifo->uiFirst = 0; fifo->uiLast = uiElementsMax - 1; fifo->uiElementCount = 0; fifo->uiElementsMax = uiElementsMax; fifo->pfElementPush = pfElmentPush; fifo->pfElementPop = pfElementPop; } } bool FIFO_bPushElement (FIFO_t *fifo, const void * const pvElement) { if (!fifo) { return false; } // Check if the queue is full if (true == FIFO_IsFull (fifo)) { return false; } // Increment the element count if (fifo->uiElementsMax > fifo->uiElementCount) { fifo->uiElementCount++; } fifo->uiLast++; if (fifo->uiLast == fifo->uiElementsMax) { fifo->uiLast = 0; } // Insert the element into the queue fifo->pfElementPush(fifo, pvElement); return true; } bool FIFO_bPopElement (FIFO_t *fifo, void * const pvElement) { if (!fifo) { return false; } // Check if the queue is empty if (true == FIFO_IsEmpty (fifo)) { return false; } // Get the element from the queue fifo->pfElementPop(fifo, pvElement); // Decrement the element count if (fifo->uiElementCount > 0) { fifo->uiElementCount--; } fifo->uiFirst++; if (fifo->uiFirst == fifo->uiElementsMax) { fifo->uiFirst = 0; } return true; } bool FIFO_bPeekElement (FIFO_t *fifo, void * const pvElement) { if (!fifo) { return false; } // Check if the queue is empty if (true == FIFO_IsEmpty (fifo)) { return false; } // Get the element from the queue fifo->pfElementPop(fifo, pvElement); return true; } bool FIFO_IsEmpty (FIFO_t *fifo) { if (fifo) { return ((fifo->uiElementCount == 0) ? true : false); } return false; } bool FIFO_IsFull (FIFO_t *fifo) { if (fifo) { return ((fifo->uiElementCount < fifo->uiElementsMax) ? false : true); } return false; } void FIFO_Flush (FIFO_t *fifo) { if (fifo) { fifo->uiElementCount = 0; fifo->uiFirst = 0; fifo->uiLast = fifo->uiElementsMax - 1; } } micropython-1.12/ports/cc3200/util/fifo.h000066400000000000000000000042461357706137100201420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_UTIL_FIFO_H #define MICROPY_INCLUDED_CC3200_UTIL_FIFO_H typedef struct { void *pvElements; unsigned int uiElementCount; unsigned int uiElementsMax; unsigned int uiFirst; unsigned int uiLast; void (*pfElementPush)(void * const pvFifo, const void * const pvElement); void (*pfElementPop)(void * const pvFifo, void * const pvElement); }FIFO_t; extern void FIFO_Init (FIFO_t *fifo, unsigned int uiElementsMax, void (*pfElmentPush)(void * const pvFifo, const void * const pvElement), void (*pfElementPop)(void * const pvFifo, void * const pvElement)); extern bool FIFO_bPushElement (FIFO_t *fifo, const void * const pvElement); extern bool FIFO_bPopElement (FIFO_t *fifo, void * const pvElement); extern bool FIFO_bPeekElement (FIFO_t *fifo, void * const pvElement); extern bool FIFO_IsEmpty (FIFO_t *fifo); extern bool FIFO_IsFull (FIFO_t *fifo); extern void FIFO_Flush (FIFO_t *fifo); #endif // MICROPY_INCLUDED_CC3200_UTIL_FIFO_H micropython-1.12/ports/cc3200/util/gccollect.c000066400000000000000000000041141357706137100211430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/gc.h" #include "py/mpthread.h" #include "lib/utils/gchelper.h" #include "gccollect.h" /****************************************************************************** DECLARE PUBLIC FUNCTIONS ******************************************************************************/ void gc_collect(void) { // start the GC gc_collect_start(); // get the registers and the sp mp_uint_t regs[10]; mp_uint_t sp = gc_helper_get_regs_and_sp(regs); // trace the stack, including the registers (since they live on the stack in this function) gc_collect_root((void**)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); // trace root pointers from any threads #if MICROPY_PY_THREAD mp_thread_gc_others(); #endif // end the GC gc_collect_end(); } micropython-1.12/ports/cc3200/util/gccollect.h000066400000000000000000000033121357706137100211470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_UTIL_GCCOLLECT_H #define MICROPY_INCLUDED_CC3200_UTIL_GCCOLLECT_H // variables defining memory layout extern uint32_t _etext; extern uint32_t _data; extern uint32_t _edata; extern uint32_t _boot; extern uint32_t _eboot; extern uint32_t _bss; extern uint32_t _ebss; extern uint32_t _heap; extern uint32_t _eheap; extern uint32_t _stack; extern uint32_t _estack; void gc_collect(void); #endif // MICROPY_INCLUDED_CC3200_UTIL_GCCOLLECT_H micropython-1.12/ports/cc3200/util/random.c000066400000000000000000000071311357706137100204660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "rom_map.h" #include "pybrtc.h" #include "simplelink.h" #include "modnetwork.h" #include "modwlan.h" #include "random.h" #include "debug.h" /****************************************************************************** * LOCAL TYPES ******************************************************************************/ typedef union _rng_id_t { uint32_t id32; uint16_t id16[3]; uint8_t id8[6]; } rng_id_t; /****************************************************************************** * LOCAL VARIABLES ******************************************************************************/ static uint32_t s_seed; /****************************************************************************** * LOCAL FUNCTION DECLARATIONS ******************************************************************************/ STATIC uint32_t lfsr (uint32_t input); /****************************************************************************** * PRIVATE FUNCTIONS ******************************************************************************/ STATIC uint32_t lfsr (uint32_t input) { assert( input != 0 ); return (input >> 1) ^ (-(input & 0x01) & 0x00E10000); } /******************************************************************************/ // MicroPython bindings; STATIC mp_obj_t machine_rng_get(void) { return mp_obj_new_int(rng_get()); } MP_DEFINE_CONST_FUN_OBJ_0(machine_rng_get_obj, machine_rng_get); /****************************************************************************** * PUBLIC FUNCTIONS ******************************************************************************/ void rng_init0 (void) { rng_id_t juggler; uint32_t seconds; uint16_t mseconds; // get the seconds and the milliseconds from the RTC pyb_rtc_get_time(&seconds, &mseconds); wlan_get_mac (juggler.id8); // flatten the 48-bit board identification to 24 bits juggler.id16[0] ^= juggler.id16[2]; juggler.id8[0] ^= juggler.id8[3]; juggler.id8[1] ^= juggler.id8[4]; juggler.id8[2] ^= juggler.id8[5]; s_seed = juggler.id32 & 0x00FFFFFF; s_seed += (seconds & 0x000FFFFF) + mseconds; // the seed must not be zero if (s_seed == 0) { s_seed = 1; } } uint32_t rng_get (void) { s_seed = lfsr( s_seed ); return s_seed; } micropython-1.12/ports/cc3200/util/random.h000066400000000000000000000026671357706137100205040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_UTIL_RANDOM_H #define MICROPY_INCLUDED_CC3200_UTIL_RANDOM_H void rng_init0 (void); uint32_t rng_get (void); MP_DECLARE_CONST_FUN_OBJ_0(machine_rng_get_obj); #endif // MICROPY_INCLUDED_CC3200_UTIL_RANDOM_H micropython-1.12/ports/cc3200/util/sleeprestore.h000066400000000000000000000026471357706137100217360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_UTIL_SLEEPRESTORE_H #define MICROPY_INCLUDED_CC3200_UTIL_SLEEPRESTORE_H extern void sleep_store(void); extern void sleep_restore(void); #endif // MICROPY_INCLUDED_CC3200_UTIL_SLEEPRESTORE_H micropython-1.12/ports/cc3200/util/sleeprestore.s000066400000000000000000000022511357706137100217400ustar00rootroot00000000000000 .syntax unified .cpu cortex-m4 .thumb .text .align 2 @ global variable with the backup registers .extern vault_arm_registers @ global function that performs the wake up actions .extern pyb_sleep_suspend_exit @ uint sleep_store(void) .global sleep_store .thumb .thumb_func .type sleep_store, %function sleep_store: dsb isb push {r0-r12, lr} ldr r1, =vault_arm_registers mrs r0, msp str r0, [r1] mrs r0, psp str r0, [r1, #4] mrs r0, primask str r0, [r1, #12] mrs r0, faultmask str r0, [r1, #16] mrs r0, basepri str r0, [r1, #20] mrs r0, control str r0, [r1, #24] dsb isb bx lr @ uint sleep_restore(void) .global sleep_restore .thumb .thumb_func .type sleep_restore, %function sleep_restore: dsb isb mrs r0, msp msr psp, r0 ldr r1, =vault_arm_registers ldr r0, [r1, #24] msr control, r0 ldr r0, [r1] msr msp, r0 ldr r0, [r1, #12] msr primask, r0 ldr r0, [r1, #16] msr faultmask, r0 ldr r0, [r1, #20] msr basepri, r0 dsb isb bl pyb_sleep_suspend_exit micropython-1.12/ports/cc3200/util/socketfifo.c000066400000000000000000000067741357706137100213560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "osi.h" #include "fifo.h" #include "socketfifo.h" /*---------------------------------------------------------------------------- ** Declare private functions */ static void socketfifo_Push (void * const pvFifo, const void * const pvElement); static void socketfifo_Pop (void * const pvFifo, void * const pvElement); /*---------------------------------------------------------------------------- ** Declare private data */ static FIFO_t *socketfifo; /*---------------------------------------------------------------------------- ** Define public functions */ void SOCKETFIFO_Init (FIFO_t *fifo, void *elements, uint32_t maxcount) { // Initialize global data socketfifo = fifo; socketfifo->pvElements = elements; FIFO_Init (socketfifo, maxcount, socketfifo_Push, socketfifo_Pop); } bool SOCKETFIFO_Push (const void * const element) { return FIFO_bPushElement (socketfifo, element); } bool SOCKETFIFO_Pop (void * const element) { return FIFO_bPopElement (socketfifo, element); } bool SOCKETFIFO_Peek (void * const element) { return FIFO_bPeekElement (socketfifo, element); } bool SOCKETFIFO_IsEmpty (void) { return FIFO_IsEmpty (socketfifo); } bool SOCKETFIFO_IsFull (void) { return FIFO_IsFull (socketfifo); } void SOCKETFIFO_Flush (void) { SocketFifoElement_t element; while (SOCKETFIFO_Pop(&element)) { if (element.freedata) { mem_Free(element.data); } } } unsigned int SOCKETFIFO_Count (void) { return socketfifo->uiElementCount; } /*---------------------------------------------------------------------------- ** Define private functions */ static void socketfifo_Push (void * const pvFifo, const void * const pvElement) { if ((pvFifo != NULL) && (NULL != pvElement)) { unsigned int uiLast = ((FIFO_t *)pvFifo)->uiLast; memcpy (&((SocketFifoElement_t *)((FIFO_t *)pvFifo)->pvElements)[uiLast], pvElement, sizeof(SocketFifoElement_t)); } } static void socketfifo_Pop (void * const pvFifo, void * const pvElement) { if ((pvFifo != NULL) && (NULL != pvElement)) { unsigned int uiFirst = ((FIFO_t *)pvFifo)->uiFirst; memcpy (pvElement, &((SocketFifoElement_t *)((FIFO_t *)pvFifo)->pvElements)[uiFirst], sizeof(SocketFifoElement_t)); } } micropython-1.12/ports/cc3200/util/socketfifo.h000066400000000000000000000045611357706137100213530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_UTIL_SOCKETFIFO_H #define MICROPY_INCLUDED_CC3200_UTIL_SOCKETFIFO_H /*---------------------------------------------------------------------------- ** Imports */ /*---------------------------------------------------------------------------- ** Define constants */ /*---------------------------------------------------------------------------- ** Define types */ typedef struct { void *data; signed short *sd; unsigned short datasize; unsigned char closesockets; bool freedata; }SocketFifoElement_t; /*---------------------------------------------------------------------------- ** Declare public functions */ extern void SOCKETFIFO_Init (FIFO_t *fifo, void *elements, uint32_t maxcount); extern bool SOCKETFIFO_Push (const void * const element); extern bool SOCKETFIFO_Pop (void * const element); extern bool SOCKETFIFO_Peek (void * const element); extern bool SOCKETFIFO_IsEmpty (void); extern bool SOCKETFIFO_IsFull (void); extern void SOCKETFIFO_Flush (void); extern unsigned int SOCKETFIFO_Count (void); #endif // MICROPY_INCLUDED_CC3200_UTIL_SOCKETFIFO_H micropython-1.12/ports/cc3200/version.h000066400000000000000000000026541357706137100177300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Daniel Campora * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_CC3200_VERSION_H #define MICROPY_INCLUDED_CC3200_VERSION_H #define WIPY_SW_VERSION_NUMBER "1.2.0" #endif // MICROPY_INCLUDED_CC3200_VERSION_H micropython-1.12/ports/esp32/000077500000000000000000000000001357706137100161255ustar00rootroot00000000000000micropython-1.12/ports/esp32/Makefile000066400000000000000000001044731357706137100175760ustar00rootroot00000000000000# Select the board to build for: if not given on the command line, # then default to GENERIC. BOARD ?= GENERIC # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD) BOARD_DIR ?= boards/$(BOARD) ifeq ($(wildcard $(BOARD_DIR)/.),) $(error Invalid BOARD specified: $(BOARD_DIR)) endif include ../../py/mkenv.mk # Optional (not currently used for ESP32) -include mpconfigport.mk ifneq ($(SDKCONFIG),) $(error Use the BOARD variable instead of SDKCONFIG) endif # Expected to set SDKCONFIG include $(BOARD_DIR)/mpconfigboard.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h QSTR_GLOBAL_REQUIREMENTS = $(SDKCONFIG_H) MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 MICROPY_PY_BTREE = 1 MICROPY_VFS_FAT = 1 MICROPY_VFS_LFS2 = 1 FROZEN_MANIFEST ?= boards/manifest.py # include py core make definitions include $(TOP)/py/py.mk GIT_SUBMODULES = lib/berkeley-db-1.xx PORT ?= /dev/ttyUSB0 BAUD ?= 460800 FLASH_MODE ?= dio FLASH_FREQ ?= 40m FLASH_SIZE ?= 4MB CROSS_COMPILE ?= xtensa-esp32-elf- OBJDUMP = $(CROSS_COMPILE)objdump SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined SDKCONFIG_H = $(BUILD)/sdkconfig.h # the git hash of the currently supported ESP IDF version ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df ESPIDF_SUPHASH_V4 := 310beae373446ceb9a4ad9b36b5428d7fdf2705f define print_supported_git_hash $(info Supported git hash (v3.3): $(ESPIDF_SUPHASH_V3)) $(info Supported git hash (v4.0-beta1) (experimental): $(ESPIDF_SUPHASH_V4)) endef # paths to ESP IDF and its components ifeq ($(ESPIDF),) ifneq ($(IDF_PATH),) ESPIDF = $(IDF_PATH) else $(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.) $(info See README.md for installation instructions.) $(call print_supported_git_hash) $(error ESPIDF not set) endif endif ESPCOMP = $(ESPIDF)/components ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py ESPCOMP_KCONFIGS = $(shell find $(ESPCOMP) -name Kconfig) ESPCOMP_KCONFIGS_PROJBUILD = $(shell find $(ESPCOMP) -name Kconfig.projbuild) # verify the ESP IDF version ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) $(info Building with ESP IDF v3) else ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) $(info Building with ESP IDF v4) PYPARSING_VERSION = $(shell python3 -c 'import pyparsing; print(pyparsing.__version__)') ifneq ($(PYPARSING_VERSION),2.3.1) $(info ** ERROR **) $(info EDP IDF requires pyparsing version less than 2.4) $(info You will need to set up a Python virtual environment with pyparsing 2.3.1) $(info Please see README.md for more information) $(error Incorrect pyparsing version) endif else $(info ** WARNING **) $(info The git hash of ESP IDF does not match the supported version) $(info The build may complete and the firmware may work but it is not guaranteed) $(info ESP IDF path: $(ESPIDF)) $(info Current git hash: $(ESPIDF_CURHASH)) $(call print_supported_git_hash) endif # pretty format of ESP IDF version, used internally by the IDF IDF_VER := $(shell git -C $(ESPIDF) describe) ifeq ($(shell which $(CC) 2> /dev/null),) $(info ** ERROR **) $(info Cannot find C compiler $(CC)) $(info Add the xtensa toolchain to your PATH. See README.md) $(error C compiler missing) endif # Support BLE by default when building with IDF 4.x. # Can be explicitly disabled on the command line or board config. ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) MICROPY_PY_BLUETOOTH ?= 1 ifeq ($(MICROPY_PY_BLUETOOTH),1) SDKCONFIG += boards/sdkconfig.ble MICROPY_BLUETOOTH_NIMBLE = 1 endif endif # include sdkconfig to get needed configuration values include $(SDKCONFIG) ################################################################################ # Compiler and linker flags INC += -I. INC += -I$(TOP) INC += -I$(TOP)/lib/mp-readline INC += -I$(TOP)/lib/netutils INC += -I$(TOP)/lib/timeutils INC += -I$(BUILD) INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include_bootloader INC_ESPCOMP += -I$(ESPCOMP)/console INC_ESPCOMP += -I$(ESPCOMP)/driver/include INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver INC_ESPCOMP += -I$(ESPCOMP)/efuse/include INC_ESPCOMP += -I$(ESPCOMP)/efuse/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/espcoredump/include INC_ESPCOMP += -I$(ESPCOMP)/soc/include INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/heap/include INC_ESPCOMP += -I$(ESPCOMP)/log/include INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include INC_ESPCOMP += -I$(ESPCOMP)/newlib/include INC_ESPCOMP += -I$(ESPCOMP)/nvs_flash/include INC_ESPCOMP += -I$(ESPCOMP)/freertos/include INC_ESPCOMP += -I$(ESPCOMP)/esp_ringbuf/include INC_ESPCOMP += -I$(ESPCOMP)/esp_event/include INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include INC_ESPCOMP += -I$(ESPCOMP)/lwip/lwip/src/include INC_ESPCOMP += -I$(ESPCOMP)/lwip/port/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include INC_ESPCOMP += -I$(ESPCOMP)/mdns/include INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include INC_ESPCOMP += -I$(ESPCOMP)/ulp/include INC_ESPCOMP += -I$(ESPCOMP)/vfs/include INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include INC_ESPCOMP += -I$(ESPCOMP)/app_update/include INC_ESPCOMP += -I$(ESPCOMP)/pthread/include INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) INC_ESPCOMP += -I$(ESPCOMP)/esp_common/include INC_ESPCOMP += -I$(ESPCOMP)/esp_eth/include INC_ESPCOMP += -I$(ESPCOMP)/esp_event/private_include INC_ESPCOMP += -I$(ESPCOMP)/esp_rom/include INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/include INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps/sntp INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/private_include INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include/esp_supplicant INC_ESPCOMP += -I$(ESPCOMP)/xtensa/include INC_ESPCOMP += -I$(ESPCOMP)/xtensa/esp32/include ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) INC_ESPCOMP += -I$(ESPCOMP)/bt/include INC_ESPCOMP += -I$(ESPCOMP)/bt/common/osi/include INC_ESPCOMP += -I$(ESPCOMP)/bt/common/btc/include INC_ESPCOMP += -I$(ESPCOMP)/bt/common/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/porting/nimble/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/port/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ans/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/bas/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gap/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gatt/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ias/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/lls/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/tps/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/util/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/ram/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/porting/npl/freertos/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/ext/tinycrypt/include INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/esp-hci/include endif else INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include INC_ESPCOMP += -I$(ESPCOMP)/expat/expat/expat/lib INC_ESPCOMP += -I$(ESPCOMP)/expat/port/include INC_ESPCOMP += -I$(ESPCOMP)/json/include INC_ESPCOMP += -I$(ESPCOMP)/json/port/include INC_ESPCOMP += -I$(ESPCOMP)/micro-ecc/micro-ecc INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes endif ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) ifeq ($(MICROPY_PY_BLUETOOTH),1) CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1 endif endif endif # these flags are common to C and C++ compilation CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ -mlongcalls -nostdlib \ -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable \ -Wno-error=unused-variable -Wno-error=deprecated-declarations \ -DESP_PLATFORM CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP) CFLAGS += -DIDF_VER=\"$(IDF_VER)\" CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -I$(BOARD_DIR) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) CFLAGS += -DMICROPY_ESP_IDF_4=1 endif # this is what ESPIDF uses for c++ compilation CXXFLAGS = -std=gnu++11 $(CFLAGS_COMMON) $(INC) $(INC_ESPCOMP) LDFLAGS = -nostdlib -Map=$(@:.elf=.map) --cref LDFLAGS += --gc-sections -static -EL LDFLAGS += -u call_user_start_cpu0 -u uxTopUsedPriority -u ld_include_panic_highint_hdl LDFLAGS += -u __cxa_guard_dummy # so that implementation of static guards is taken from cxx_guards.o instead of libstdc++.a LDFLAGS += -L$(ESPCOMP)/esp32/ld LDFLAGS += -L$(ESPCOMP)/esp_rom/esp32/ld LDFLAGS += -T $(BUILD)/esp32_out.ld LDFLAGS += -T $(BUILD)/esp32.project.ld LDFLAGS += -T esp32.rom.ld LDFLAGS += -T esp32.rom.libgcc.ld LDFLAGS += -T esp32.peripherals.ld LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBSTDCXX_FILE_NAME = $(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a) # Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -g COPT = -O0 else #CFLAGS += -fdata-sections -ffunction-sections COPT += -Os -DNDEBUG #LDFLAGS += --gc-sections endif # Options for mpy-cross MPY_CROSS_FLAGS += -march=xtensawin # Enable SPIRAM support if CONFIG_ESP32_SPIRAM_SUPPORT=y in sdkconfig ifeq ($(CONFIG_ESP32_SPIRAM_SUPPORT),y) CFLAGS_COMMON += -mfix-esp32-psram-cache-issue LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc-psram-workaround.a $(ESPCOMP)/newlib/lib/libm-psram-workaround.a else # Additional newlib symbols that can only be used with spiram disabled. ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) LDFLAGS += -T esp32.rom.newlib-funcs.ld LDFLAGS += -T esp32.rom.newlib-locale.ld LDFLAGS += -T esp32.rom.newlib-data.ld else LDFLAGS += -T esp32.rom.spiram_incompatible_fns.ld endif LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc.a $(ESPCOMP)/newlib/lib/libm.a endif ################################################################################ # List of MicroPython source and object files SRC_C = \ main.c \ uart.c \ gccollect.c \ mphalport.c \ fatfs_port.c \ help.c \ modutime.c \ moduos.c \ machine_timer.c \ machine_pin.c \ machine_touchpad.c \ machine_adc.c \ machine_dac.c \ machine_i2c.c \ machine_pwm.c \ machine_uart.c \ modmachine.c \ modnetwork.c \ network_lan.c \ network_ppp.c \ nimble.c \ modsocket.c \ modesp.c \ esp32_partition.c \ esp32_rmt.c \ esp32_ulp.c \ modesp32.c \ espneopixel.c \ machine_hw_spi.c \ machine_wdt.c \ mpthreadport.c \ machine_rtc.c \ machine_sdcard.c \ $(wildcard $(BOARD_DIR)/*.c) \ $(SRC_MOD) EXTMOD_SRC_C = $(addprefix extmod/,\ modonewire.c \ modbluetooth_nimble.c \ ) LIB_SRC_C = $(addprefix lib/,\ mp-readline/readline.c \ netutils/netutils.c \ timeutils/timeutils.c \ utils/pyexec.c \ utils/interrupt_char.c \ utils/sys_stdio_mphal.c \ ) DRIVERS_SRC_C = $(addprefix drivers/,\ bus/softspi.c \ dht/dht.c \ ) OBJ_MP = OBJ_MP += $(PY_O) OBJ_MP += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ_MP += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ_MP += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ_MP += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(LIB_SRC_C) $(DRIVERS_SRC_C) # Append any auto-generated sources that are needed by sources listed in SRC_QSTR SRC_QSTR_AUTO_DEPS += ################################################################################ # Generate sdkconfig.h from sdkconfig $(SDKCONFIG_COMBINED): $(SDKCONFIG) $(Q)$(MKDIR) -p $(dir $@) $(Q)$(CAT) $^ > $@ $(SDKCONFIG_H): $(SDKCONFIG_COMBINED) $(ECHO) "GEN $@" $(Q)$(MKDIR) -p $(dir $@) $(Q)$(PYTHON) $(ESPIDF)/tools/kconfig_new/confgen.py \ --output header $@ \ --config $< \ --kconfig $(ESPIDF)/Kconfig \ --env "IDF_TARGET=esp32" \ --env "IDF_CMAKE=n" \ --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ --env "IDF_PATH=$(ESPIDF)" $(Q)touch $@ $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard.h ################################################################################ # List of object files from the ESP32 IDF components ESPIDF_BOOTLOADER_SUPPORT_O = $(patsubst %.c,%.o,\ $(filter-out $(ESPCOMP)/bootloader_support/src/bootloader_init.c,\ $(wildcard $(ESPCOMP)/bootloader_support/src/*.c) \ $(wildcard $(ESPCOMP)/bootloader_support/src/idf/*.c) \ )) ESPIDF_DRIVER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/driver/*.c)) ESPIDF_EFUSE_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/efuse/esp32/*.c)\ $(wildcard $(ESPCOMP)/efuse/src/*.c)\ ) $(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-array-bounds ESPIDF_ESP32_O = \ $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/*.c)) \ $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/hwcrypto/*.c)) \ $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/esp32/*.S)) \ ESPIDF_ESP_RINGBUF_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_ringbuf/*.c)) ESPIDF_HEAP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/heap/*.c)) ESPIDF_SOC_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/soc/esp32/*.c) \ $(wildcard $(ESPCOMP)/soc/src/*.c) \ $(wildcard $(ESPCOMP)/soc/src/hal/*.c) \ ) ESPIDF_CXX_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/cxx/*.cpp)) ESPIDF_PTHREAD_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/pthread/*.c)) # Assembler .S files need only basic flags, and in particular should not have # -Os because that generates subtly different code. # We also need custom CFLAGS for .c files because FreeRTOS has headers with # generic names (eg queue.h) which can clash with other files in the port. ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) CFLAGS_ASM = -I$(BUILD) -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I. -I$(ESPCOMP)/xtensa/include -I$(ESPCOMP)/xtensa/esp32/include -I$(ESPCOMP)/esp_common/include else CFLAGS_ASM = -I$(BUILD) -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I. endif $(BUILD)/$(ESPCOMP)/freertos/portasm.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/xtensa_context.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/xtensa_intr_asm.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/xtensa_vectors.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/xtensa_vector_defaults.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/%.o: CFLAGS = $(CFLAGS_BASE) -I. -I$(BUILD) $(INC_ESPCOMP) -I$(ESPCOMP)/freertos/include/freertos -D_ESP_FREERTOS_INTERNAL ESPIDF_FREERTOS_O = \ $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/freertos/*.c)) \ $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/freertos/*.S)) \ ESPIDF_VFS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/vfs/*.c)) ESPIDF_LOG_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/log/*.c)) ESPIDF_XTENSA_DEBUG_MODULE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/xtensa-debug-module/*.c)) ESPIDF_TCPIP_ADAPTER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/tcpip_adapter/*.c)) ESPIDF_APP_TRACE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_trace/*.c)) ESPIDF_APP_UPDATE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_update/*.c)) ESPIDF_NEWLIB_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/newlib/*.c)) ESPIDF_NVS_FLASH_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/nvs_flash/src/*.cpp)) ESPIDF_SMARTCONFIG_ACK_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/smartconfig_ack/*.c)) ESPIDF_SPI_FLASH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/spi_flash/*.c)) ESPIDF_ULP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/ulp/*.c)) $(BUILD)/$(ESPCOMP)/lwip/%.o: CFLAGS += -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable ESPIDF_LWIP_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/lwip/apps/dhcpserver/*.c) \ $(wildcard $(ESPCOMP)/lwip/lwip/src/api/*.c) \ $(wildcard $(ESPCOMP)/lwip/lwip/src/apps/sntp/*.c) \ $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*.c) \ $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*/*.c) \ $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*.c) \ $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*.c) \ $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*/*.c) \ $(wildcard $(ESPCOMP)/lwip/port/esp32/*.c) \ $(wildcard $(ESPCOMP)/lwip/port/esp32/*/*.c) \ ) ESPIDF_MBEDTLS_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/mbedtls/mbedtls/library/*.c) \ $(wildcard $(ESPCOMP)/mbedtls/port/*.c) \ $(wildcard $(ESPCOMP)/mbedtls/port/esp32/*.c) \ ) ESPIDF_MDNS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/mdns/*.c)) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) $(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing -I$(ESPCOMP)/wpa_supplicant/src -Wno-implicit-function-declaration else $(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DALLOW_EVEN_MOD -D__ets__ -Wno-strict-aliasing endif ESPIDF_WPA_SUPPLICANT_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/wpa_supplicant/port/*.c) \ $(wildcard $(ESPCOMP)/wpa_supplicant/src/*/*.c) \ ) ESPIDF_SDMMC_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/sdmmc/*.c)) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) ESPIDF_ESP_COMMON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_common/src/*.c)) ESPIDF_ESP_EVENT_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_event/*.c)) ESPIDF_ESP_WIFI_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_wifi/src/*.c)) ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) ESPIDF_BT_NIMBLE_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/bt/controller/*.c) \ $(wildcard $(ESPCOMP)/bt/common/btc/core/*.c) \ $(wildcard $(ESPCOMP)/bt/common/osi/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/esp-hci/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/ext/tinycrypt/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ans/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/bas/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gap/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gatt/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ias/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/lls/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/tps/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/ram/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/util/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/nimble/src/*.c) \ $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/npl/freertos/src/*.c) \ ) endif $(BUILD)/$(ESPCOMP)/esp_eth/src/esp_eth_mac_dm9051.o: CFLAGS += -fno-strict-aliasing ESPIDF_ESP_ETH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_eth/src/*.c)) ESPIDF_XTENSA_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/xtensa/*.c) \ $(wildcard $(ESPCOMP)/xtensa/esp32/*.c) \ ) else ESPIDF_JSON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/json/cJSON/cJSON*.c)) ESPIDF_ETHERNET_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/ethernet/*.c) \ $(wildcard $(ESPCOMP)/ethernet/eth_phy/*.c) \ ) endif OBJ_ESPIDF = LIB_ESPIDF = BUILD_ESPIDF_LIB = $(BUILD)/esp-idf define gen_espidf_lib_rule OBJ_ESPIDF += $(addprefix $$(BUILD)/,$(2)) LIB_ESPIDF += $(1) $(BUILD_ESPIDF_LIB)/$(1)/lib$(1).a: $(addprefix $$(BUILD)/,$(2)) $(ECHO) "AR $$@" $(Q)$(AR) cru $$@ $$^ endef $(eval $(call gen_espidf_lib_rule,bootloader_support,$(ESPIDF_BOOTLOADER_SUPPORT_O))) $(eval $(call gen_espidf_lib_rule,driver,$(ESPIDF_DRIVER_O))) $(eval $(call gen_espidf_lib_rule,efuse,$(ESPIDF_EFUSE_O))) $(eval $(call gen_espidf_lib_rule,esp32,$(ESPIDF_ESP32_O))) $(eval $(call gen_espidf_lib_rule,esp_ringbuf,$(ESPIDF_ESP_RINGBUF_O))) $(eval $(call gen_espidf_lib_rule,heap,$(ESPIDF_HEAP_O))) $(eval $(call gen_espidf_lib_rule,soc,$(ESPIDF_SOC_O))) $(eval $(call gen_espidf_lib_rule,cxx,$(ESPIDF_CXX_O))) $(eval $(call gen_espidf_lib_rule,pthread,$(ESPIDF_PTHREAD_O))) $(eval $(call gen_espidf_lib_rule,freertos,$(ESPIDF_FREERTOS_O))) $(eval $(call gen_espidf_lib_rule,vfs,$(ESPIDF_VFS_O))) $(eval $(call gen_espidf_lib_rule,json,$(ESPIDF_JSON_O))) $(eval $(call gen_espidf_lib_rule,log,$(ESPIDF_LOG_O))) $(eval $(call gen_espidf_lib_rule,xtensa-debug-module,$(ESPIDF_XTENSA_DEBUG_MODULE_O))) $(eval $(call gen_espidf_lib_rule,tcpip_adapter,$(ESPIDF_TCPIP_ADAPTER_O))) $(eval $(call gen_espidf_lib_rule,app_trace,$(ESPIDF_APP_TRACE_O))) $(eval $(call gen_espidf_lib_rule,app_update,$(ESPIDF_APP_UPDATE_O))) $(eval $(call gen_espidf_lib_rule,newlib,$(ESPIDF_NEWLIB_O))) $(eval $(call gen_espidf_lib_rule,nvs_flash,$(ESPIDF_NVS_FLASH_O))) $(eval $(call gen_espidf_lib_rule,smartconfig_ack,$(ESPIDF_SMARTCONFIG_ACK_O))) $(eval $(call gen_espidf_lib_rule,spi_flash,$(ESPIDF_SPI_FLASH_O))) $(eval $(call gen_espidf_lib_rule,ulp,$(ESPIDF_ULP_O))) $(eval $(call gen_espidf_lib_rule,lwip,$(ESPIDF_LWIP_O))) $(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O))) $(eval $(call gen_espidf_lib_rule,mdns,$(ESPIDF_MDNS_O))) $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) $(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) $(eval $(call gen_espidf_lib_rule,esp_common,$(ESPIDF_ESP_COMMON_O))) $(eval $(call gen_espidf_lib_rule,esp_event,$(ESPIDF_ESP_EVENT_O))) $(eval $(call gen_espidf_lib_rule,esp_wifi,$(ESPIDF_ESP_WIFI_O))) ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) $(eval $(call gen_espidf_lib_rule,bt_nimble,$(ESPIDF_BT_NIMBLE_O))) endif $(eval $(call gen_espidf_lib_rule,esp_eth,$(ESPIDF_ESP_ETH_O))) $(eval $(call gen_espidf_lib_rule,xtensa,$(ESPIDF_XTENSA_O))) else $(eval $(call gen_espidf_lib_rule,ethernet,$(ESPIDF_ETHERNET_O))) endif # Create all destination build dirs before compiling IDF source OBJ_ESPIDF_DIRS = $(sort $(dir $(OBJ_ESPIDF))) $(BUILD_ESPIDF_LIB) $(addprefix $(BUILD_ESPIDF_LIB)/,$(LIB_ESPIDF)) $(OBJ_ESPIDF): | $(OBJ_ESPIDF_DIRS) $(OBJ_ESPIDF_DIRS): $(MKDIR) -p $@ # Make all IDF object files depend on sdkconfig $(OBJ_ESPIDF): $(SDKCONFIG_H) # Add all IDF components to the set of libraries LIB = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) ################################################################################ # ESP IDF ldgen LDGEN_FRAGMENTS = $(shell find $(ESPCOMP) -name "*.lf") ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) LDGEN_LIBRARIES=$(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) $(BUILD_ESPIDF_LIB)/ldgen_libraries: $(LDGEN_LIBRARIES) $(ESPIDF)/make/ldgen.mk printf "$(foreach library,$(LDGEN_LIBRARIES),$(library)\n)" > $(BUILD_ESPIDF_LIB)/ldgen_libraries $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(BUILD_ESPIDF_LIB)/ldgen_libraries $(ECHO) "GEN $@" $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ --input $< \ --output $@ \ --config $(SDKCONFIG_COMBINED) \ --kconfig $(ESPIDF)/Kconfig \ --fragments $(LDGEN_FRAGMENTS) \ --libraries-file $(BUILD_ESPIDF_LIB)/ldgen_libraries \ --env "IDF_TARGET=esp32" \ --env "IDF_CMAKE=n" \ --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ --env "IDF_PATH=$(ESPIDF)" \ --objdump $(OBJDUMP) else LDGEN_SECTIONS_INFO = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a.sections_info) LDGEN_SECTION_INFOS = $(BUILD_ESPIDF_LIB)/ldgen.section_infos define gen_sections_info_rule $(1).sections_info: $(1) $(ECHO) "GEN $(1).sections_info" $(Q)$(OBJDUMP) -h $(1) > $(1).sections_info endef $(eval $(foreach lib,$(LIB_ESPIDF),$(eval $(call gen_sections_info_rule,$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a)))) $(LDGEN_SECTION_INFOS): $(LDGEN_SECTIONS_INFO) $(ESPIDF)/make/ldgen.mk $(Q)printf "$(foreach info,$(LDGEN_SECTIONS_INFO),$(info)\n)" > $@ $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(LDGEN_SECTION_INFOS) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ --input $< \ --output $@ \ --config $(SDKCONFIG_COMBINED) \ --kconfig $(ESPIDF)/Kconfig \ --fragments $(LDGEN_FRAGMENTS) \ --sections $(LDGEN_SECTION_INFOS) \ --env "IDF_TARGET=esp32" \ --env "IDF_CMAKE=n" \ --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ --env "IDF_PATH=$(ESPIDF)" endif ################################################################################ # Main targets all: $(BUILD)/firmware.bin .PHONY: idf-version deploy erase idf-version: $(ECHO) "ESP IDF supported hash: $(ESPIDF_SUPHASH)" $(BUILD)/firmware.bin: $(BUILD)/bootloader.bin $(BUILD)/partitions.bin $(BUILD)/application.bin $(ECHO) "Create $@" $(Q)$(PYTHON) makeimg.py $^ $@ deploy: $(BUILD)/firmware.bin $(ECHO) "Writing $^ to the board" $(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) write_flash -z --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) 0x1000 $^ erase: $(ECHO) "Erasing flash" $(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) erase_flash ################################################################################ # Declarations to build the application OBJ = $(OBJ_MP) APP_LD_ARGS = APP_LD_ARGS += $(LDFLAGS_MOD) APP_LD_ARGS += $(addprefix -T,$(LD_FILES)) APP_LD_ARGS += --start-group APP_LD_ARGS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++ APP_LD_ARGS += $(LIBC_LIBM) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) APP_LD_ARGS += -L$(ESPCOMP)/xtensa/esp32 -lhal APP_LD_ARGS += -L$(ESPCOMP)/bt/controller/lib -lbtdm_app APP_LD_ARGS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lsmartconfig -lcoexist else APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2 endif APP_LD_ARGS += $(OBJ) APP_LD_ARGS += $(LIB) APP_LD_ARGS += --end-group $(BUILD)/esp32_out.ld: $(SDKCONFIG_H) $(Q)$(CC) -I$(BUILD) -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@ $(BUILD)/application.bin: $(BUILD)/application.elf $(ECHO) "Create $@" $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< $(BUILD)/application.elf: $(OBJ) $(LIB) $(BUILD)/esp32_out.ld $(BUILD)/esp32.project.ld $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $(APP_LD_ARGS) $(Q)$(SIZE) $@ define compile_cxx $(ECHO) "CXX $<" $(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< @# The following fixes the dependency file. @# See http://make.paulandlesley.org/autodep.html for details. @# Regex adjusted from the above to play better with Windows paths, etc. @$(CP) $(@:.o=.d) $(@:.o=.P); \ $(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ $(RM) -f $(@:.o=.d) endef vpath %.cpp . $(TOP) $(BUILD)/%.o: %.cpp $(call compile_cxx) ################################################################################ # Declarations to build the bootloader BOOTLOADER_LIB_DIR = $(BUILD)/bootloader BOOTLOADER_LIB_ALL = ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) $(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/efuse/include -I$(ESPCOMP)/esp_rom/include -Wno-error=format \ -I$(ESPCOMP)/esp_common/include \ -I$(ESPCOMP)/xtensa/include \ -I$(ESPCOMP)/xtensa/esp32/include else $(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/micro-ecc/micro-ecc -I$(ESPCOMP)/efuse/include -I$(ESPCOMP)/esp32 -Wno-error=format endif # libbootloader_support.a BOOTLOADER_LIB_ALL += bootloader_support BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ bootloader_support/src/bootloader_clock.o \ bootloader_support/src/bootloader_common.o \ bootloader_support/src/bootloader_flash.o \ bootloader_support/src/bootloader_init.o \ bootloader_support/src/bootloader_random.o \ bootloader_support/src/bootloader_utility.o \ bootloader_support/src/flash_qio_mode.o \ bootloader_support/src/esp_image_format.o \ bootloader_support/src/flash_encrypt.o \ bootloader_support/src/flash_partitions.o \ ) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ bootloader_support/src/esp32/bootloader_sha.o \ bootloader_support/src/bootloader_flash_config.o \ bootloader_support/src/esp32/secure_boot.o \ ) else BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ bootloader_support/src/bootloader_sha.o \ bootloader_support/src/secure_boot_signatures.o \ bootloader_support/src/secure_boot.o \ ) endif $(BOOTLOADER_LIB_DIR)/libbootloader_support.a: $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ # liblog.a BOOTLOADER_LIB_ALL += log BOOTLOADER_LIB_LOG_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ log/log.o \ ) $(BOOTLOADER_LIB_DIR)/liblog.a: $(BOOTLOADER_LIB_LOG_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ # libspi_flash.a BOOTLOADER_LIB_ALL += spi_flash BOOTLOADER_LIB_SPI_FLASH_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ spi_flash/spi_flash_rom_patch.o \ ) $(BOOTLOADER_LIB_DIR)/libspi_flash.a: $(BOOTLOADER_LIB_SPI_FLASH_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) # libmicro-ecc.a BOOTLOADER_LIB_ALL += micro-ecc BOOTLOADER_LIB_MICRO_ECC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ micro-ecc/micro-ecc/uECC.o \ ) $(BOOTLOADER_LIB_DIR)/libmicro-ecc.a: $(BOOTLOADER_LIB_MICRO_ECC_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ endif # libsoc.a $(BUILD)/bootloader/$(ESPCOMP)/soc/esp32/rtc_clk.o: CFLAGS += -fno-jump-tables -fno-tree-switch-conversion BOOTLOADER_LIB_ALL += soc BOOTLOADER_LIB_SOC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/soc/,\ esp32/cpu_util.o \ esp32/gpio_periph.o \ esp32/rtc_clk.o \ esp32/rtc_clk_init.o \ esp32/rtc_init.o \ esp32/rtc_periph.o \ esp32/rtc_pm.o \ esp32/rtc_sleep.o \ esp32/rtc_time.o \ esp32/rtc_wdt.o \ esp32/sdio_slave_periph.o \ esp32/sdmmc_periph.o \ esp32/soc_memory_layout.o \ esp32/spi_periph.o \ src/memory_layout_utils.o \ ) $(BOOTLOADER_LIB_DIR)/libsoc.a: $(BOOTLOADER_LIB_SOC_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ # libmain.a BOOTLOADER_LIB_ALL += main BOOTLOADER_LIB_MAIN_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ bootloader/subproject/main/bootloader_start.o \ ) $(BOOTLOADER_LIB_DIR)/libmain.a: $(BOOTLOADER_LIB_MAIN_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ # all objects files BOOTLOADER_OBJ_ALL = \ $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) \ $(BOOTLOADER_LIB_LOG_OBJ) \ $(BOOTLOADER_LIB_SPI_FLASH_OBJ) \ $(BOOTLOADER_LIB_MICRO_ECC_OBJ) \ $(BOOTLOADER_LIB_SOC_OBJ) \ $(BOOTLOADER_LIB_MAIN_OBJ) $(BOOTLOADER_OBJ_ALL): $(SDKCONFIG_H) BOOTLOADER_LIBS = BOOTLOADER_LIBS += -Wl,--start-group BOOTLOADER_LIBS += $(BOOTLOADER_OBJ) BOOTLOADER_LIBS += -L$(BUILD)/bootloader $(addprefix -l,$(BOOTLOADER_LIB_ALL)) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) BOOTLOADER_LIBS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lrtc else BOOTLOADER_LIBS += -L$(ESPCOMP)/esp32/lib -lrtc endif BOOTLOADER_LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc BOOTLOADER_LIBS += -Wl,--end-group BOOTLOADER_LDFLAGS = BOOTLOADER_LDFLAGS += -nostdlib BOOTLOADER_LDFLAGS += -L$(ESPIDF)/lib BOOTLOADER_LDFLAGS += -L$(ESPIDF)/ld BOOTLOADER_LDFLAGS += -u call_user_start_cpu0 BOOTLOADER_LDFLAGS += -Wl,--gc-sections BOOTLOADER_LDFLAGS += -static BOOTLOADER_LDFLAGS += -Wl,-EL BOOTLOADER_LDFLAGS += -Wl,-Map=$(@:.elf=.map) -Wl,--cref BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.ld BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.rom.ld ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.ld BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld else BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.ld BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.spiram_incompatible_fns.ld endif BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.peripherals.ld BOOTLOADER_OBJ_DIRS = $(sort $(dir $(BOOTLOADER_OBJ_ALL))) $(BOOTLOADER_OBJ_ALL): | $(BOOTLOADER_OBJ_DIRS) $(BOOTLOADER_OBJ_DIRS): $(MKDIR) -p $@ $(BUILD)/bootloader/%.o: %.c $(call compile_c) $(BUILD)/bootloader.bin: $(BUILD)/bootloader.elf $(ECHO) "Create $@" $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< $(BUILD)/bootloader.elf: $(BOOTLOADER_OBJ) $(addprefix $(BOOTLOADER_LIB_DIR)/lib,$(addsuffix .a,$(BOOTLOADER_LIB_ALL))) $(ECHO) "LINK $@" $(Q)$(CC) $(BOOTLOADER_LDFLAGS) -o $@ $(BOOTLOADER_LIBS) ################################################################################ # Declarations to build the partitions PYTHON2 ?= python2 # Can be overriden by mkconfigboard.mk. PART_SRC ?= partitions.csv $(BUILD)/partitions.bin: $(PART_SRC) $(ECHO) "Create $@" $(Q)$(PYTHON2) $(ESPCOMP)/partition_table/gen_esp32part.py -q $< $@ ################################################################################ include $(TOP)/py/mkrules.mk micropython-1.12/ports/esp32/README.md000066400000000000000000000207041357706137100174070ustar00rootroot00000000000000MicroPython port to the ESP32 ============================= This is an experimental port of MicroPython to the Espressif ESP32 microcontroller. It uses the ESP-IDF framework and MicroPython runs as a task under FreeRTOS. Supported features include: - REPL (Python prompt) over UART0. - 16k stack for the MicroPython task and 96k Python heap. - Many of MicroPython's features are enabled: unicode, arbitrary-precision integers, single-precision floats, complex numbers, frozen bytecode, as well as many of the internal modules. - Internal filesystem using the flash (currently 2M in size). - The machine module with GPIO, UART, SPI, software I2C, ADC, DAC, PWM, TouchPad, WDT and Timer. - The network module with WLAN (WiFi) support. Development of this ESP32 port was sponsored in part by Microbric Pty Ltd. Setting up the toolchain and ESP-IDF ------------------------------------ There are two main components that are needed to build the firmware: - the Xtensa cross-compiler that targets the CPU in the ESP32 (this is different to the compiler used by the ESP8266) - the Espressif IDF (IoT development framework, aka SDK) The ESP-IDF changes quickly and MicroPython only supports certain versions. The git hash of these versions (one for 3.x, one for 4.x) can be found by running `make` without a configured `ESPIDF`. Then you can fetch only the given esp-idf using the following command: $ git clone https://github.com/espressif/esp-idf.git $ git checkout $ git submodule update --init --recursive Note: The ESP IDF v4.x support is currently experimental. The binary toolchain (binutils, gcc, etc.) can be installed using the following guides: * [Linux installation](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/linux-setup.html) * [MacOS installation](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/macos-setup.html) * [Windows installation](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/windows-setup.html) If you are on a Windows machine then the [Windows Subsystem for Linux](https://msdn.microsoft.com/en-au/commandline/wsl/install_guide) is the most efficient way to install the ESP32 toolchain and build the project. If you use WSL then follow the [Linux guidelines](https://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html) for the ESP-IDF instead of the Windows ones. You will also need either Python 2 or Python 3, along with the `pyserial` and `pyparsing` packages installed for the version of Python that you will be using (when building you can use, eg, `make PYTHON=python2` to specify the version used). To install the required packages do: ```bash $ pip install pyserial 'pyparsing<2.4' ``` It is recommended to use a Python virtual environment if your system package manager already provides these libraries, especially as the IDF v4.x is currently incompatible with pyparsing 2.4 and higher. Once everything is set up you should have a functioning toolchain with prefix xtensa-esp32-elf- (or otherwise if you configured it differently) as well as a copy of the ESP-IDF repository. You will need to update your `PATH` environment variable to include the ESP32 toolchain. For example, you can issue the following commands on (at least) Linux: $ export PATH=$PATH:$HOME/esp/crosstool-NG/builds/xtensa-esp32-elf/bin You can put this command in your `.profile` or `.bash_login`. You then need to set the `ESPIDF` environment/makefile variable to point to the root of the ESP-IDF repository. You can set the variable in your PATH, or at the command line when calling make, or in your own custom `makefile`. The last option is recommended as it allows you to easily configure other variables for the build. In that case, create a new file in the esp32 directory called `makefile` and add the following lines to that file: ``` ESPIDF = BOARD = GENERIC #PORT = /dev/ttyUSB0 #FLASH_MODE = qio #FLASH_SIZE = 4MB #CROSS_COMPILE = xtensa-esp32-elf- include Makefile ``` Be sure to enter the correct path to your local copy of the IDF repository (and use `$(HOME)`, not tilde, to reference your home directory). If your filesystem is case-insensitive then you'll need to use `GNUmakefile` instead of `makefile`. If the Xtensa cross-compiler is not in your path you can use the `CROSS_COMPILE` variable to set its location. Other options of interest are `PORT` for the serial port of your esp32 module, and `FLASH_MODE` (which may need to be `dio` for some modules) and `FLASH_SIZE`. See the Makefile for further information. The default ESP IDF configuration settings are provided by the `GENERIC` board definition in the directory `boards/GENERIC`. For a custom configuration you can define your own board directory. The `BOARD` variable can be set on the make command line: ```bash $ make BOARD=TINYPICO ``` or added to your custom `makefile` (or `GNUmakefile`) described above. There is also a `GENERIC_SPIRAM` board for for ESP32 modules that have external SPIRAM, but prefer to use a specific board target (or define your own as necessary). Building the firmware --------------------- The MicroPython cross-compiler must be built to pre-compile some of the built-in scripts to bytecode. This can be done by (from the root of this repository): ```bash $ make -C mpy-cross ``` Then to build MicroPython for the ESP32 run: ```bash $ cd ports/esp32 $ make submodules $ make ``` This will produce binary firmware images in the `build/` subdirectory (three of them: bootloader.bin, partitions.bin and application.bin). To flash the firmware you must have your ESP32 module in the bootloader mode and connected to a serial port on your PC. Refer to the documentation for your particular ESP32 module for how to do this. The serial port and flash settings are set in the `Makefile`, and can be overridden in your local `makefile`; see above for more details. You will also need to have user permissions to access the /dev/ttyUSB0 device. On Linux, you can enable this by adding your user to the `dialout` group, and rebooting or logging out and in again. ```bash $ sudo adduser dialout ``` If you are installing MicroPython to your module for the first time, or after installing any other firmware, you should first erase the flash completely: ```bash $ make erase ``` To flash the MicroPython firmware to your ESP32 use: ```bash $ make deploy ``` This will use the `esptool.py` script (provided by ESP-IDF) to download the binary images. Getting a Python prompt ----------------------- You can get a prompt via the serial port, via UART0, which is the same UART that is used for programming the firmware. The baudrate for the REPL is 115200 and you can use a command such as: ```bash $ picocom -b 115200 /dev/ttyUSB0 ``` Configuring the WiFi and using the board ---------------------------------------- The ESP32 port is designed to be (almost) equivalent to the ESP8266 in terms of the modules and user-facing API. There are some small differences, notably that the ESP32 does not automatically connect to the last access point when booting up. But for the most part the documentation and tutorials for the ESP8266 should apply to the ESP32 (at least for the components that are implemented). See http://docs.micropython.org/en/latest/esp8266/esp8266/quickref.html for a quick reference, and http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html for a tutorial. The following function can be used to connect to a WiFi access point (you can either pass in your own SSID and password, or change the defaults so you can quickly call `wlan_connect()` and it just works): ```python def wlan_connect(ssid='MYSSID', password='MYPASS'): import network wlan = network.WLAN(network.STA_IF) if not wlan.active() or not wlan.isconnected(): wlan.active(True) print('connecting to:', ssid) wlan.connect(ssid, password) while not wlan.isconnected(): pass print('network config:', wlan.ifconfig()) ``` Note that some boards require you to configure the WiFi antenna before using the WiFi. On Pycom boards like the LoPy and WiPy 2.0 you need to execute the following code to select the internal antenna (best to put this line in your boot.py file): ```python import machine antenna = machine.Pin(16, machine.Pin.OUT, value=0) ``` Troubleshooting --------------- * Continuous reboots after programming: Ensure FLASH_MODE is correct for your board (e.g. ESP-WROOM-32 should be DIO). Then perform a `make clean`, rebuild, redeploy. micropython-1.12/ports/esp32/README.ulp.md000066400000000000000000000053451357706137100202120ustar00rootroot00000000000000# ULP To compile binarys for the ulp you need the ulp toolkit. Download it from https://github.com/espressif/binutils-esp32ulp/wiki#downloads Then extract it, then add ```esp32ulp-elf-binutils/bin``` to your PATH ## Example Makefile ```make ULP_S_SOURCES := main.S ULP_APP_NAME := test ULP_LD_SCRIPT := esp32.ulp.ld SRC_PATH := src BUILD_PATH := build include $(ESPIDF)/components/ulp/Makefile.projbuild ULP_ELF := $(ULP_APP_NAME).elf ULP_MAP := $(ULP_ELF:.elf=.map) ULP_SYM := $(ULP_ELF:.elf=.sym) ULP_BIN := $(ULP_ELF:.elf=.bin) ULP_EXPORTS_LD := $(ULP_ELF:.elf=.ld) ULP_EXPORTS_HEADER := $(ULP_ELF:.elf=.h) ULP_OBJECTS := $(notdir $(ULP_S_SOURCES:.S=.ulp.o)) ULP_DEP := $(notdir $(ULP_S_SOURCES:.S=.ulp.d)) $(ULP_LD_SCRIPT:.ld=.d) ULP_PREPROCESSED := $(notdir $(ULP_S_SOURCES:.S=.ulp.pS)) ULP_LISTINGS := $(notdir $(ULP_S_SOURCES:.S=.ulp.lst)) .PHONY: all clean all: $(BUILD_PATH) $(BUILD_PATH)/$(ULP_BIN) clean: rm -rf $(BUILD_PATH) $(BUILD_PATH): mkdir $@ # Generate preprocessed linker file. $(BUILD_PATH)/$(ULP_APP_NAME).ld: $(SRC_PATH)/$(ULP_LD_SCRIPT) cpp -P $< -o $@ # Generate preprocessed assembly files. # To inspect these preprocessed files, add a ".PRECIOUS: %.ulp.pS" rule. $(BUILD_PATH)/%.ulp.pS: $(SRC_PATH)/%.S cpp $< -o $@ # Compiled preprocessed files into object files. $(BUILD_PATH)/%.ulp.o: $(BUILD_PATH)/%.ulp.pS $(ULP_AS) -al=$(patsubst %.ulp.o,%.ulp.lst,$@) -o $@ $< # Link object files and generate map file $(BUILD_PATH)/$(ULP_ELF): $(BUILD_PATH)/$(ULP_OBJECTS) $(BUILD_PATH)/$(ULP_APP_NAME).ld $(ULP_LD) -o $@ -A elf32-esp32ulp -Map=$(BUILD_PATH)/$(ULP_MAP) -T $(BUILD_PATH)/$(ULP_APP_NAME).ld $< # Dump the list of global symbols in a convenient format. $(ULP_SYM): $(ULP_ELF) $(ULP_NM) -g -f posix $< > $@ # Dump the binary for inclusion into the project $(BUILD_PATH)/$(ULP_BIN): $(BUILD_PATH)/$(ULP_ELF) $(ULP_OBJCOPY) -O binary $< $@ ``` ## Example linker script for the ulp ``` #define ULP_BIN_MAGIC 0x00706c75 #define HEADER_SIZE 12 #define CONFIG_ULP_COPROC_RESERVE_MEM 4096 MEMORY { ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM } SECTIONS { .text : AT(HEADER_SIZE) { *(.text) } >ram .data : { . = ALIGN(4); *(.data) } >ram .bss : { . = ALIGN(4); *(.bss) } >ram .header : AT(0) { LONG(ULP_BIN_MAGIC) SHORT(LOADADDR(.text)) SHORT(SIZEOF(.text)) SHORT(SIZEOF(.data)) SHORT(SIZEOF(.bss)) } } ``` ## Example ulp code ```asm move R3, 99 move R0, 10 # mem[R0+0] = R3 st R3, R0, 0 HALT ``` ## Example python code using the ulp ```python import esp32 import time u = esp32.ULP() with open('test.bin', 'rb') as f: b = f.read() u.load_binary(0,b) u.run(0) ``` micropython-1.12/ports/esp32/boards/000077500000000000000000000000001357706137100173775ustar00rootroot00000000000000micropython-1.12/ports/esp32/boards/GENERIC/000077500000000000000000000000001357706137100204535ustar00rootroot00000000000000micropython-1.12/ports/esp32/boards/GENERIC/mpconfigboard.h000066400000000000000000000001211357706137100234300ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "ESP32 module" #define MICROPY_HW_MCU_NAME "ESP32" micropython-1.12/ports/esp32/boards/GENERIC/mpconfigboard.mk000066400000000000000000000000431357706137100236130ustar00rootroot00000000000000SDKCONFIG += boards/sdkconfig.base micropython-1.12/ports/esp32/boards/GENERIC_D2WD/000077500000000000000000000000001357706137100212335ustar00rootroot00000000000000micropython-1.12/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h000066400000000000000000000001431357706137100242140ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "Generic ESP32-D2WD module" #define MICROPY_HW_MCU_NAME "ESP32-D2WD" micropython-1.12/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.mk000066400000000000000000000001651357706137100244000ustar00rootroot00000000000000SDKCONFIG += boards/sdkconfig.base PART_SRC = partitions-2MiB.csv FLASH_SIZE = 2MB FLASH_MODE = dio FLASH_FREQ = 40m micropython-1.12/ports/esp32/boards/GENERIC_SPIRAM/000077500000000000000000000000001357706137100215265ustar00rootroot00000000000000micropython-1.12/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h000066400000000000000000000001321357706137100245050ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "ESP32 module (spiram)" #define MICROPY_HW_MCU_NAME "ESP32" micropython-1.12/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk000066400000000000000000000001101357706137100246610ustar00rootroot00000000000000SDKCONFIG += boards/sdkconfig.base SDKCONFIG += boards/sdkconfig.spiram micropython-1.12/ports/esp32/boards/TINYPICO/000077500000000000000000000000001357706137100206355ustar00rootroot00000000000000micropython-1.12/ports/esp32/boards/TINYPICO/manifest.py000066400000000000000000000000741357706137100230160ustar00rootroot00000000000000include('$(PORT_DIR)/boards/manifest.py') freeze("modules") micropython-1.12/ports/esp32/boards/TINYPICO/modules/000077500000000000000000000000001357706137100223055ustar00rootroot00000000000000micropython-1.12/ports/esp32/boards/TINYPICO/modules/dotstar.py000066400000000000000000000207661357706137100243520ustar00rootroot00000000000000# DotStar strip driver for MicroPython # # The MIT License (MIT) # # Copyright (c) 2016 Damien P. George (original Neopixel object) # Copyright (c) 2017 Ladyada # Copyright (c) 2017 Scott Shawcroft for Adafruit Industries # Copyright (c) 2019 Matt Trentini (porting back to MicroPython) # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. START_HEADER_SIZE = 4 LED_START = 0b11100000 # Three "1" bits, followed by 5 brightness bits # Pixel color order constants RGB = (0, 1, 2) RBG = (0, 2, 1) GRB = (1, 0, 2) GBR = (1, 2, 0) BRG = (2, 0, 1) BGR = (2, 1, 0) class DotStar: """ A sequence of dotstars. :param SPI spi: The SPI object to write output to. :param int n: The number of dotstars in the chain :param float brightness: Brightness of the pixels between 0.0 and 1.0 :param bool auto_write: True if the dotstars should immediately change when set. If False, `show` must be called explicitly. :param tuple pixel_order: Set the pixel order on the strip - different strips implement this differently. If you send red, and it looks blue or green on the strip, modify this! It should be one of the values above Example for TinyPICO: .. code-block:: python from dotstar import DotStar from machine import Pin, SPI spi = SPI(sck=Pin(12), mosi=Pin(13), miso=Pin(18)) # Configure SPI - note: miso is unused dotstar = DotStar(spi, 1) dotstar[0] = (128, 0, 0) # Red """ def __init__(self, spi, n, *, brightness=1.0, auto_write=True, pixel_order=BGR): self._spi = spi self._n = n # Supply one extra clock cycle for each two pixels in the strip. self.end_header_size = n // 16 if n % 16 != 0: self.end_header_size += 1 self._buf = bytearray(n * 4 + START_HEADER_SIZE + self.end_header_size) self.end_header_index = len(self._buf) - self.end_header_size self.pixel_order = pixel_order # Four empty bytes to start. for i in range(START_HEADER_SIZE): self._buf[i] = 0x00 # Mark the beginnings of each pixel. for i in range(START_HEADER_SIZE, self.end_header_index, 4): self._buf[i] = 0xff # 0xff bytes at the end. for i in range(self.end_header_index, len(self._buf)): self._buf[i] = 0xff self._brightness = 1.0 # Set auto_write to False temporarily so brightness setter does _not_ # call show() while in __init__. self.auto_write = False self.brightness = brightness self.auto_write = auto_write def deinit(self): """Blank out the DotStars and release the resources.""" self.auto_write = False for i in range(START_HEADER_SIZE, self.end_header_index): if i % 4 != 0: self._buf[i] = 0 self.show() if self._spi: self._spi.deinit() def __enter__(self): return self def __exit__(self, exception_type, exception_value, traceback): self.deinit() def __repr__(self): return "[" + ", ".join([str(x) for x in self]) + "]" def _set_item(self, index, value): """ value can be one of three things: a (r,g,b) list/tuple a (r,g,b, brightness) list/tuple a single, longer int that contains RGB values, like 0xFFFFFF brightness, if specified should be a float 0-1 Set a pixel value. You can set per-pixel brightness here, if it's not passed it will use the max value for pixel brightness value, which is a good default. Important notes about the per-pixel brightness - it's accomplished by PWMing the entire output of the LED, and that PWM is at a much slower clock than the rest of the LEDs. This can cause problems in Persistence of Vision Applications """ offset = index * 4 + START_HEADER_SIZE rgb = value if isinstance(value, int): rgb = (value >> 16, (value >> 8) & 0xff, value & 0xff) if len(rgb) == 4: brightness = value[3] # Ignore value[3] below. else: brightness = 1 # LED startframe is three "1" bits, followed by 5 brightness bits # then 8 bits for each of R, G, and B. The order of those 3 are configurable and # vary based on hardware # same as math.ceil(brightness * 31) & 0b00011111 # Idea from https://www.codeproject.com/Tips/700780/Fast-floor-ceiling-functions brightness_byte = 32 - int(32 - brightness * 31) & 0b00011111 self._buf[offset] = brightness_byte | LED_START self._buf[offset + 1] = rgb[self.pixel_order[0]] self._buf[offset + 2] = rgb[self.pixel_order[1]] self._buf[offset + 3] = rgb[self.pixel_order[2]] def __setitem__(self, index, val): if isinstance(index, slice): start, stop, step = index.indices(self._n) length = stop - start if step != 0: # same as math.ceil(length / step) # Idea from https://fizzbuzzer.com/implement-a-ceil-function/ length = (length + step - 1) // step if len(val) != length: raise ValueError("Slice and input sequence size do not match.") for val_i, in_i in enumerate(range(start, stop, step)): self._set_item(in_i, val[val_i]) else: self._set_item(index, val) if self.auto_write: self.show() def __getitem__(self, index): if isinstance(index, slice): out = [] for in_i in range(*index.indices(self._n)): out.append( tuple(self._buf[in_i * 4 + (3 - i) + START_HEADER_SIZE] for i in range(3))) return out if index < 0: index += len(self) if index >= self._n or index < 0: raise IndexError offset = index * 4 return tuple(self._buf[offset + (3 - i) + START_HEADER_SIZE] for i in range(3)) def __len__(self): return self._n @property def brightness(self): """Overall brightness of the pixel""" return self._brightness @brightness.setter def brightness(self, brightness): self._brightness = min(max(brightness, 0.0), 1.0) if self.auto_write: self.show() def fill(self, color): """Colors all pixels the given ***color***.""" auto_write = self.auto_write self.auto_write = False for i in range(self._n): self[i] = color if auto_write: self.show() self.auto_write = auto_write def show(self): """Shows the new colors on the pixels themselves if they haven't already been autowritten. The colors may or may not be showing after this function returns because it may be done asynchronously.""" # Create a second output buffer if we need to compute brightness buf = self._buf if self.brightness < 1.0: buf = bytearray(self._buf) # Four empty bytes to start. for i in range(START_HEADER_SIZE): buf[i] = 0x00 for i in range(START_HEADER_SIZE, self.end_header_index): buf[i] = self._buf[i] if i % 4 == 0 else int(self._buf[i] * self._brightness) # Four 0xff bytes at the end. for i in range(self.end_header_index, len(buf)): buf[i] = 0xff if self._spi: self._spi.write(buf) micropython-1.12/ports/esp32/boards/TINYPICO/modules/tinypico.py000066400000000000000000000104711357706137100245200ustar00rootroot00000000000000# TinyPICO MicroPython Helper Library # 2019 Seon Rozenblum, Matt Trentini # # Project home: # https://github.com/TinyPICO # # 2019-Mar-12 - v0.1 - Initial implementation # 2019-May-20 - v1.0 - Initial Release # 2019-Oct-23 - v1.1 - Removed temp sensor code, prep for frozen modules # Import required libraries from micropython import const from machine import Pin, SPI, ADC import machine, time, esp32 # TinyPICO Hardware Pin Assignments # Battery BAT_VOLTAGE = const(35) BAT_CHARGE = const(34) # APA102 Dotstar pins for production boards DOTSTAR_CLK = const(12) DOTSTAR_DATA = const(2) DOTSTAR_PWR = const(13) # SPI SPI_MOSI = const(23) SPI_CLK = const(18) SPI_MISO = const(19) #I2C I2C_SDA = const(21) I2C_SCL = const(22) #DAC DAC1 = const(25) DAC2 = const(26) # Helper functions # Get a *rough* estimate of the current battery voltage # If the battery is not present, the charge IC will still report it's trying to charge at X voltage # so it will still show a voltage. def get_battery_voltage(): """ Returns the current battery voltage. If no battery is connected, returns 3.7V This is an approximation only, but useful to detect of the charge state of the battery is getting low. """ adc = ADC(Pin(BAT_VOLTAGE)) # Assign the ADC pin to read measuredvbat = adc.read() # Read the value measuredvbat /= 4095 # divide by 4095 as we are using the default ADC voltage range of 0-1V measuredvbat *= 3.7 # Multiply by 3.7V, our reference voltage return measuredvbat # Return the current charge state of the battery - we need to read the value multiple times # to eliminate false negatives due to the charge IC not knowing the difference between no battery # and a full battery not charging - This is why the charge LED flashes def get_battery_charging(): """ Returns the current battery charging state. This can trigger false positives as the charge IC can't tell the difference between a full battery or no battery connected. """ measuredVal = 0 # start our reading at 0 io = Pin(BAT_CHARGE, Pin.IN) # Assign the pin to read for y in range(0, 10): # loop through 10 times adding the read values together to ensure no false positives measuredVal += io.value() return measuredVal == 0 # return True if the value is 0 # Power to the on-board Dotstar is controlled by a PNP transistor, so low is ON and high is OFF # We also need to set the Dotstar clock and data pins to be inputs to prevent power leakage when power is off # This might be improved at a future date # The reason we have power control for the Dotstar is that it has a quiescent current of around 1mA, so we # need to be able to cut power to it to minimise power consumption during deep sleep or with general battery powered use # to minimise unneeded battery drain def set_dotstar_power(state): """Set the power for the on-board Dostar to allow no current draw when not needed.""" # Set the power pin to the inverse of state if state: Pin(DOTSTAR_PWR, Pin.OUT, None) # Break the PULL_HOLD on the pin Pin(DOTSTAR_PWR).value(False) # Set the pin to LOW to enable the Transistor else: Pin(13, Pin.IN, Pin.PULL_HOLD) # Set PULL_HOLD on the pin to allow the 3V3 pull-up to work Pin(DOTSTAR_CLK, Pin.OUT if state else Pin.IN) # If power is on, set CLK to be output, otherwise input Pin(DOTSTAR_DATA, Pin.OUT if state else Pin.IN) # If power is on, set DATA to be output, otherwise input # A small delay to let the IO change state time.sleep(.035) # Dotstar rainbow colour wheel def dotstar_color_wheel(wheel_pos): """Color wheel to allow for cycling through the rainbow of RGB colors.""" wheel_pos = wheel_pos % 255 if wheel_pos < 85: return 255 - wheel_pos * 3, 0, wheel_pos * 3 elif wheel_pos < 170: wheel_pos -= 85 return 0, wheel_pos * 3, 255 - wheel_pos * 3 else: wheel_pos -= 170 return wheel_pos * 3, 255 - wheel_pos * 3, 0 # Go into deep sleep but shut down the APA first to save power # Use this if you want lowest deep sleep current def go_deepsleep(t): """Deep sleep helper that also powers down the on-board Dotstar.""" set_dotstar_power(False) machine.deepsleep(t) micropython-1.12/ports/esp32/boards/TINYPICO/mpconfigboard.h000066400000000000000000000001251357706137100236160ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "TinyPICO" #define MICROPY_HW_MCU_NAME "ESP32-PICO-D4" micropython-1.12/ports/esp32/boards/TINYPICO/mpconfigboard.mk000066400000000000000000000003311357706137100237750ustar00rootroot00000000000000FLASH_FREQ = 80m SDKCONFIG += boards/sdkconfig.base SDKCONFIG += boards/sdkconfig.240mhz SDKCONFIG += boards/sdkconfig.spiram SDKCONFIG += boards/TINYPICO/sdkconfig.board FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py micropython-1.12/ports/esp32/boards/TINYPICO/sdkconfig.board000066400000000000000000000001531357706137100236140ustar00rootroot00000000000000CONFIG_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y CONFIG_SPIRAM_SPEED_80M=y CONFIG_ESP32_REV_MIN_1=y micropython-1.12/ports/esp32/boards/manifest.py000066400000000000000000000004241357706137100215570ustar00rootroot00000000000000freeze('$(PORT_DIR)/modules') freeze('$(MPY_DIR)/tools', ('upip.py', 'upip_utarfile.py')) freeze('$(MPY_DIR)/ports/esp8266/modules', 'ntptime.py') freeze('$(MPY_DIR)/drivers/dht', 'dht.py') freeze('$(MPY_DIR)/drivers/onewire') include('$(MPY_DIR)/extmod/webrepl/manifest.py') micropython-1.12/ports/esp32/boards/manifest_release.py000066400000000000000000000003501357706137100232550ustar00rootroot00000000000000include('manifest.py') freeze('$(MPY_LIB_DIR)/upysh', 'upysh.py') freeze('$(MPY_LIB_DIR)/urequests', 'urequests.py') freeze('$(MPY_LIB_DIR)/umqtt.simple', 'umqtt/simple.py') freeze('$(MPY_LIB_DIR)/umqtt.robust', 'umqtt/robust.py') micropython-1.12/ports/esp32/boards/sdkconfig.240mhz000066400000000000000000000003151357706137100223130ustar00rootroot00000000000000# MicroPython on ESP32, ESP IDF configuration with 240MHz CPU CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 micropython-1.12/ports/esp32/boards/sdkconfig.base000066400000000000000000000022701357706137100222030ustar00rootroot00000000000000# MicroPython on ESP32, ESP IDF configuration # The following options override the defaults CONFIG_IDF_TARGET="esp32" # Application manager CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y # Bootloader config CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y # ESP32-specific CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n CONFIG_ESP32_XTAL_FREQ_AUTO=y # Power Management CONFIG_PM_ENABLE=y # FreeRTOS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y # UDP CONFIG_LWIP_PPP_SUPPORT=y CONFIG_LWIP_PPP_PAP_SUPPORT=y CONFIG_LWIP_PPP_CHAP_SUPPORT=y # SSL # Use 4kiB output buffer instead of default 16kiB (because IDF heap is fragmented in 4.0) CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y # ULP coprocessor support CONFIG_ESP32_ULP_COPROC_ENABLED=y # v3.3-only (renamed in 4.0) CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=n CONFIG_SUPPORT_STATIC_ALLOCATION=y CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y CONFIG_PPP_SUPPORT=y CONFIG_PPP_PAP_SUPPORT=y CONFIG_PPP_CHAP_SUPPORT=y CONFIG_ULP_COPROC_ENABLED=y micropython-1.12/ports/esp32/boards/sdkconfig.ble000066400000000000000000000005501357706137100220320ustar00rootroot00000000000000# Note this requires building with IDF 4.x CONFIG_BT_ENABLED=y CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY= CONFIG_BTDM_CTRL_MODE_BTDM= CONFIG_BT_NIMBLE_ENABLED=y CONFIG_BT_NIMBLE_MAX_CONNECTIONS=4 # Pin to the same core as MP. CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=n CONFIG_BT_NIMBLE_PINNED_TO_CORE_1=y CONFIG_BT_NIMBLE_PINNED_TO_CORE=1 micropython-1.12/ports/esp32/boards/sdkconfig.spiram000066400000000000000000000003631357706137100225650ustar00rootroot00000000000000# MicroPython on ESP32, ESP IDF configuration with SPIRAM support CONFIG_ESP32_SPIRAM_SUPPORT=y CONFIG_SPIRAM_CACHE_WORKAROUND=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_USE_MEMMAP=y # v3.3-only (renamed in 4.0) CONFIG_SPIRAM_SUPPORT=y micropython-1.12/ports/esp32/esp32_partition.c000066400000000000000000000235031357706137100213210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/vfs.h" #include "modesp32.h" #include "esp_ota_ops.h" // esp_partition_read and esp_partition_write can operate on arbitrary bytes // but esp_partition_erase_range operates on 4k blocks. But to make a partition // implement the standard block protocol all operations are done on 4k blocks. #define BLOCK_SIZE_BYTES (4096) enum { ESP32_PARTITION_BOOT, ESP32_PARTITION_RUNNING, }; typedef struct _esp32_partition_obj_t { mp_obj_base_t base; const esp_partition_t *part; } esp32_partition_obj_t; static inline void check_esp_err(esp_err_t e) { if (e != ESP_OK) { mp_raise_OSError(-e); } } STATIC esp32_partition_obj_t *esp32_partition_new(const esp_partition_t *part) { if (part == NULL) { mp_raise_OSError(MP_ENOENT); } esp32_partition_obj_t *self = m_new_obj(esp32_partition_obj_t); self->base.type = &esp32_partition_type; self->part = part; return self; } STATIC void esp32_partition_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->part->type, self->part->subtype, self->part->address, self->part->size, &self->part->label[0], self->part->encrypted ); } STATIC mp_obj_t esp32_partition_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // Check args mp_arg_check_num(n_args, n_kw, 1, 1, false); // Get requested partition const esp_partition_t *part; if (mp_obj_is_int(all_args[0])) { // Integer given, get that particular partition switch (mp_obj_get_int(all_args[0])) { case ESP32_PARTITION_BOOT: part = esp_ota_get_boot_partition(); break; case ESP32_PARTITION_RUNNING: part = esp_ota_get_running_partition(); break; default: mp_raise_ValueError(NULL); } } else { // String given, search for partition with that label const char *label = mp_obj_str_get_str(all_args[0]); part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, label); if (part == NULL) { part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, label); } } // Return new object return MP_OBJ_FROM_PTR(esp32_partition_new(part)); } STATIC mp_obj_t esp32_partition_find(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // Parse args enum { ARG_type, ARG_subtype, ARG_label }; static const mp_arg_t allowed_args[] = { { MP_QSTR_type, MP_ARG_INT, {.u_int = ESP_PARTITION_TYPE_APP} }, { MP_QSTR_subtype, MP_ARG_INT, {.u_int = ESP_PARTITION_SUBTYPE_ANY} }, { MP_QSTR_label, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // Get optional label string const char *label = NULL; if (args[ARG_label].u_obj != mp_const_none) { label = mp_obj_str_get_str(args[ARG_label].u_obj); } // Build list of matching partitions mp_obj_t list = mp_obj_new_list(0, NULL); esp_partition_iterator_t iter = esp_partition_find(args[ARG_type].u_int, args[ARG_subtype].u_int, label); while (iter != NULL) { mp_obj_list_append(list, MP_OBJ_FROM_PTR(esp32_partition_new(esp_partition_get(iter)))); iter = esp_partition_next(iter); } esp_partition_iterator_release(iter); return list; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_partition_find_fun_obj, 0, esp32_partition_find); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(esp32_partition_find_obj, MP_ROM_PTR(&esp32_partition_find_fun_obj)); STATIC mp_obj_t esp32_partition_info(mp_obj_t self_in) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t tuple[] = { MP_OBJ_NEW_SMALL_INT(self->part->type), MP_OBJ_NEW_SMALL_INT(self->part->subtype), mp_obj_new_int_from_uint(self->part->address), mp_obj_new_int_from_uint(self->part->size), mp_obj_new_str(&self->part->label[0], strlen(&self->part->label[0])), mp_obj_new_bool(self->part->encrypted), }; return mp_obj_new_tuple(6, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_partition_info_obj, esp32_partition_info); STATIC mp_obj_t esp32_partition_readblocks(size_t n_args, const mp_obj_t *args) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t offset = mp_obj_get_int(args[1]) * BLOCK_SIZE_BYTES; mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); if (n_args == 4) { offset += mp_obj_get_int(args[3]); } check_esp_err(esp_partition_read(self->part, offset, bufinfo.buf, bufinfo.len)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_partition_readblocks_obj, 3, 4, esp32_partition_readblocks); STATIC mp_obj_t esp32_partition_writeblocks(size_t n_args, const mp_obj_t *args) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t offset = mp_obj_get_int(args[1]) * BLOCK_SIZE_BYTES; mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); if (n_args == 3) { check_esp_err(esp_partition_erase_range(self->part, offset, bufinfo.len)); } else { offset += mp_obj_get_int(args[3]); } check_esp_err(esp_partition_write(self->part, offset, bufinfo.buf, bufinfo.len)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_partition_writeblocks_obj, 3, 4, esp32_partition_writeblocks); STATIC mp_obj_t esp32_partition_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(0); case MP_BLOCKDEV_IOCTL_DEINIT: return MP_OBJ_NEW_SMALL_INT(0); case MP_BLOCKDEV_IOCTL_SYNC: return MP_OBJ_NEW_SMALL_INT(0); case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(self->part->size / BLOCK_SIZE_BYTES); case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(BLOCK_SIZE_BYTES); case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: { uint32_t offset = mp_obj_get_int(arg_in) * BLOCK_SIZE_BYTES; check_esp_err(esp_partition_erase_range(self->part, offset, BLOCK_SIZE_BYTES)); return MP_OBJ_NEW_SMALL_INT(0); } default: return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_partition_ioctl_obj, esp32_partition_ioctl); STATIC mp_obj_t esp32_partition_set_boot(mp_obj_t self_in) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); esp_ota_set_boot_partition(self->part); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_partition_set_boot_obj, esp32_partition_set_boot); STATIC mp_obj_t esp32_partition_get_next_update(mp_obj_t self_in) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_FROM_PTR(esp32_partition_new(esp_ota_get_next_update_partition(self->part))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_partition_get_next_update_obj, esp32_partition_get_next_update); STATIC const mp_rom_map_elem_t esp32_partition_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&esp32_partition_find_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&esp32_partition_info_obj) }, { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&esp32_partition_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&esp32_partition_writeblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&esp32_partition_ioctl_obj) }, { MP_ROM_QSTR(MP_QSTR_set_boot), MP_ROM_PTR(&esp32_partition_set_boot_obj) }, { MP_ROM_QSTR(MP_QSTR_get_next_update), MP_ROM_PTR(&esp32_partition_get_next_update_obj) }, { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_INT(ESP32_PARTITION_BOOT) }, { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(ESP32_PARTITION_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_TYPE_APP), MP_ROM_INT(ESP_PARTITION_TYPE_APP) }, { MP_ROM_QSTR(MP_QSTR_TYPE_DATA), MP_ROM_INT(ESP_PARTITION_TYPE_DATA) }, }; STATIC MP_DEFINE_CONST_DICT(esp32_partition_locals_dict, esp32_partition_locals_dict_table); const mp_obj_type_t esp32_partition_type = { { &mp_type_type }, .name = MP_QSTR_Partition, .print = esp32_partition_print, .make_new = esp32_partition_make_new, .locals_dict = (mp_obj_dict_t*)&esp32_partition_locals_dict, }; micropython-1.12/ports/esp32/esp32_rmt.c000066400000000000000000000232251357706137100201130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 "Matt Trentini" * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "modmachine.h" #include "mphalport.h" #include "driver/rmt.h" // This exposes the ESP32's RMT module to MicroPython. RMT is provided by the Espressif ESP-IDF: // // https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html // // With some examples provided: // // https://github.com/espressif/arduino-esp32/tree/master/libraries/ESP32/examples/RMT // // RMT allows accurate (down to 12.5ns resolution) transmit - and receive - of pulse signals. // Originally designed to generate infrared remote control signals, the module is very // flexible and quite easy-to-use. // // This current MicroPython implementation lacks some major features, notably receive pulses // and carrier output. // Forward declaration extern const mp_obj_type_t esp32_rmt_type; typedef struct _esp32_rmt_obj_t { mp_obj_base_t base; uint8_t channel_id; gpio_num_t pin; uint8_t clock_div; mp_uint_t num_items; rmt_item32_t* items; } esp32_rmt_obj_t; // Defined in machine_time.c; simply added the error message // Fixme: Should use this updated error hadline more widely in the ESP32 port. // At least update the method in machine_time.c. STATIC esp_err_t check_esp_err(esp_err_t code) { if (code) { mp_raise_msg(&mp_type_OSError, esp_err_to_name(code)); } return code; } STATIC mp_obj_t esp32_rmt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_clock_div, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, // 100ns resolution }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_uint_t channel_id = args[0].u_int; gpio_num_t pin_id = machine_pin_get_id(args[1].u_obj); mp_uint_t clock_div = args[2].u_int; if (clock_div < 1 || clock_div > 255) { mp_raise_ValueError("clock_div must be between 1 and 255"); } esp32_rmt_obj_t *self = m_new_obj_with_finaliser(esp32_rmt_obj_t); self->base.type = &esp32_rmt_type; self->channel_id = channel_id; self->pin = pin_id; self->clock_div = clock_div; rmt_config_t config; config.rmt_mode = RMT_MODE_TX; config.channel = (rmt_channel_t) self->channel_id; config.gpio_num = self->pin; config.mem_block_num = 1; config.tx_config.loop_en = 0; config.tx_config.carrier_en = 0; config.tx_config.idle_output_en = 1; config.tx_config.idle_level = 0; config.tx_config.carrier_duty_percent = 0; config.tx_config.carrier_freq_hz = 0; config.tx_config.carrier_level = 1; config.clk_div = self->clock_div; check_esp_err(rmt_config(&config)); check_esp_err(rmt_driver_install(config.channel, 0, 0)); return MP_OBJ_FROM_PTR(self); } STATIC void esp32_rmt_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->pin != -1) { mp_printf(print, "RMT(channel=%u, pin=%u, source_freq=%u, clock_div=%u)", self->channel_id, self->pin, APB_CLK_FREQ, self->clock_div); } else { mp_printf(print, "RMT()"); } } STATIC mp_obj_t esp32_rmt_deinit(mp_obj_t self_in) { // fixme: check for valid channel. Return exception if error occurs. esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->pin != -1) { // Check if channel has already been deinitialised. rmt_driver_uninstall(self->channel_id); self->pin = -1; // -1 to indicate RMT is unused m_free(self->items); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_rmt_deinit_obj, esp32_rmt_deinit); // Return the source frequency. // Currently only the APB clock (80MHz) can be used but it is possible other // clock sources will added in the future. STATIC mp_obj_t esp32_rmt_source_freq(mp_obj_t self_in) { return mp_obj_new_int(APB_CLK_FREQ); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_rmt_source_freq_obj, esp32_rmt_source_freq); // Return the clock divider. STATIC mp_obj_t esp32_rmt_clock_div(mp_obj_t self_in) { esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int(self->clock_div); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_rmt_clock_div_obj, esp32_rmt_clock_div); // Query whether the channel has finished sending pulses. Takes an optional // timeout (in ticks of the 80MHz clock), returning true if the pulse stream has // completed or false if they are still transmitting (or timeout is reached). STATIC mp_obj_t esp32_rmt_wait_done(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_self, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(args[0].u_obj); esp_err_t err = rmt_wait_tx_done(self->channel_id, args[1].u_int); return err == ESP_OK ? mp_const_true : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_rmt_wait_done_obj, 1, esp32_rmt_wait_done); STATIC mp_obj_t esp32_rmt_loop(mp_obj_t self_in, mp_obj_t loop) { esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(self_in); check_esp_err(rmt_set_tx_loop_mode(self->channel_id, mp_obj_get_int(loop))); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_rmt_loop_obj, esp32_rmt_loop); STATIC mp_obj_t esp32_rmt_write_pulses(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_self, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_pulses, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(args[0].u_obj); mp_obj_t pulses = args[1].u_obj; mp_uint_t start = args[2].u_int; if (start < 0 || start > 1) { mp_raise_ValueError("start must be 0 or 1"); } size_t pulses_length = 0; mp_obj_t* pulses_ptr = NULL; mp_obj_get_array(pulses, &pulses_length, &pulses_ptr); mp_uint_t num_items = (pulses_length / 2) + (pulses_length % 2); if (num_items > self->num_items) { self->items = (rmt_item32_t*)m_realloc(self->items, num_items * sizeof(rmt_item32_t *)); self->num_items = num_items; } for (mp_uint_t item_index = 0; item_index < num_items; item_index++) { mp_uint_t pulse_index = item_index * 2; self->items[item_index].duration0 = mp_obj_get_int(pulses_ptr[pulse_index++]); self->items[item_index].level0 = start++; // Note that start _could_ wrap. if (pulse_index < pulses_length) { self->items[item_index].duration1 = mp_obj_get_int(pulses_ptr[pulse_index]); self->items[item_index].level1 = start++; } } check_esp_err(rmt_write_items(self->channel_id, self->items, num_items, false /* non-blocking */)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_rmt_write_pulses_obj, 2, esp32_rmt_write_pulses); STATIC const mp_rom_map_elem_t esp32_rmt_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&esp32_rmt_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_rmt_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_source_freq), MP_ROM_PTR(&esp32_rmt_source_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_clock_div), MP_ROM_PTR(&esp32_rmt_clock_div_obj) }, { MP_ROM_QSTR(MP_QSTR_wait_done), MP_ROM_PTR(&esp32_rmt_wait_done_obj) }, { MP_ROM_QSTR(MP_QSTR_loop), MP_ROM_PTR(&esp32_rmt_loop_obj) }, { MP_ROM_QSTR(MP_QSTR_write_pulses), MP_ROM_PTR(&esp32_rmt_write_pulses_obj) }, }; STATIC MP_DEFINE_CONST_DICT(esp32_rmt_locals_dict, esp32_rmt_locals_dict_table); const mp_obj_type_t esp32_rmt_type = { { &mp_type_type }, .name = MP_QSTR_RMT, .print = esp32_rmt_print, .make_new = esp32_rmt_make_new, .locals_dict = (mp_obj_dict_t*)&esp32_rmt_locals_dict, }; micropython-1.12/ports/esp32/esp32_ulp.c000066400000000000000000000075651357706137100201220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 "Andreas Valder" * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "esp32/ulp.h" #include "esp_err.h" typedef struct _esp32_ulp_obj_t { mp_obj_base_t base; } esp32_ulp_obj_t; const mp_obj_type_t esp32_ulp_type; // singleton ULP object STATIC const esp32_ulp_obj_t esp32_ulp_obj = {{&esp32_ulp_type}}; STATIC mp_obj_t esp32_ulp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); // return constant object return (mp_obj_t)&esp32_ulp_obj; } STATIC mp_obj_t esp32_ulp_set_wakeup_period(mp_obj_t self_in, mp_obj_t period_index_in, mp_obj_t period_us_in) { mp_uint_t period_index = mp_obj_get_int(period_index_in); mp_uint_t period_us = mp_obj_get_int(period_us_in); int _errno = ulp_set_wakeup_period(period_index, period_us); if (_errno != ESP_OK) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_ulp_set_wakeup_period_obj, esp32_ulp_set_wakeup_period); STATIC mp_obj_t esp32_ulp_load_binary(mp_obj_t self_in, mp_obj_t load_addr_in, mp_obj_t program_binary_in) { mp_uint_t load_addr = mp_obj_get_int(load_addr_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(program_binary_in, &bufinfo, MP_BUFFER_READ); int _errno = ulp_load_binary(load_addr, bufinfo.buf, bufinfo.len/sizeof(uint32_t)); if (_errno != ESP_OK) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_ulp_load_binary_obj, esp32_ulp_load_binary); STATIC mp_obj_t esp32_ulp_run(mp_obj_t self_in, mp_obj_t entry_point_in) { mp_uint_t entry_point = mp_obj_get_int(entry_point_in); int _errno = ulp_run(entry_point/sizeof(uint32_t)); if (_errno != ESP_OK) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_ulp_run_obj, esp32_ulp_run); STATIC const mp_rom_map_elem_t esp32_ulp_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_set_wakeup_period), MP_ROM_PTR(&esp32_ulp_set_wakeup_period_obj) }, { MP_ROM_QSTR(MP_QSTR_load_binary), MP_ROM_PTR(&esp32_ulp_load_binary_obj) }, { MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&esp32_ulp_run_obj) }, #if !MICROPY_ESP_IDF_4 { MP_ROM_QSTR(MP_QSTR_RESERVE_MEM), MP_ROM_INT(CONFIG_ULP_COPROC_RESERVE_MEM) }, #else { MP_ROM_QSTR(MP_QSTR_RESERVE_MEM), MP_ROM_INT(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM) }, #endif }; STATIC MP_DEFINE_CONST_DICT(esp32_ulp_locals_dict, esp32_ulp_locals_dict_table); const mp_obj_type_t esp32_ulp_type = { { &mp_type_type }, .name = MP_QSTR_ULP, .make_new = esp32_ulp_make_new, .locals_dict = (mp_obj_t)&esp32_ulp_locals_dict, }; micropython-1.12/ports/esp32/espneopixel.c000066400000000000000000000041301357706137100206220ustar00rootroot00000000000000// Original version from https://github.com/adafruit/Adafruit_NeoPixel // Modifications by dpgeorge to support auto-CPU-frequency detection // This is a mash-up of the Due show() code + insights from Michael Miller's // ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus // Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution. #include "py/mpconfig.h" #include "py/mphal.h" #include "modesp.h" void IRAM_ATTR esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t timing) { uint8_t *p, *end, pix, mask; uint32_t t, time0, time1, period, c, startTime, pinMask; pinMask = 1 << pin; p = pixels; end = p + numBytes; pix = *p++; mask = 0x80; startTime = 0; uint32_t fcpu = ets_get_cpu_frequency() * 1000000; if (timing == 1) { // 800 KHz time0 = (fcpu * 0.35) / 1000000; // 0.35us time1 = (fcpu * 0.8) / 1000000; // 0.8us period = (fcpu * 1.25) / 1000000; // 1.25us per bit } else { // 400 KHz time0 = (fcpu * 0.5) / 1000000; // 0.35us time1 = (fcpu * 1.2) / 1000000; // 0.8us period = (fcpu * 2.5) / 1000000; // 1.25us per bit } uint32_t irq_state = mp_hal_quiet_timing_enter(); for (t = time0;; t = time0) { if (pix & mask) t = time1; // Bit high duration while (((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, pinMask); // Set high startTime = c; // Save start time while (((c = mp_hal_ticks_cpu()) - startTime) < t); // Wait high duration GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, pinMask); // Set low if (!(mask >>= 1)) { // Next bit/byte if(p >= end) break; pix = *p++; mask = 0x80; } } while ((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit mp_hal_quiet_timing_exit(irq_state); } micropython-1.12/ports/esp32/fatfs_port.c000066400000000000000000000033431357706137100204430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2013, 2014, 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "lib/oofatfs/ff.h" #include "timeutils.h" DWORD get_fattime(void) { struct timeval tv; gettimeofday(&tv, NULL); timeutils_struct_time_t tm; timeutils_seconds_since_2000_to_struct_time(tv.tv_sec, &tm); return (((DWORD)(tm.tm_year - 1980) << 25) | ((DWORD)tm.tm_mon << 21) | ((DWORD)tm.tm_mday << 16) | ((DWORD)tm.tm_hour << 11) | ((DWORD)tm.tm_min << 5) | ((DWORD)tm.tm_sec >> 1)); } micropython-1.12/ports/esp32/gccollect.c000066400000000000000000000041461357706137100202350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2017 Pycom Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpconfig.h" #include "py/mpstate.h" #include "py/gc.h" #include "py/mpthread.h" #include "gccollect.h" #include "soc/cpu.h" #include "xtensa/hal.h" static void gc_collect_inner(int level) { if (level < XCHAL_NUM_AREGS / 8) { gc_collect_inner(level + 1); if (level != 0) { return; } } if (level == XCHAL_NUM_AREGS / 8) { // get the sp volatile uint32_t sp = (uint32_t)get_sp(); gc_collect_root((void**)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); return; } // trace root pointers from any threads #if MICROPY_PY_THREAD mp_thread_gc_others(); #endif } void gc_collect(void) { gc_collect_start(); gc_collect_inner(0); gc_collect_end(); } micropython-1.12/ports/esp32/gccollect.h000066400000000000000000000032161357706137100202370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ extern uint32_t _text_start; extern uint32_t _text_end; extern uint32_t _irom0_text_start; extern uint32_t _irom0_text_end; extern uint32_t _data_start; extern uint32_t _data_end; extern uint32_t _rodata_start; extern uint32_t _rodata_end; extern uint32_t _bss_start; extern uint32_t _bss_end; extern uint32_t _heap_start; extern uint32_t _heap_end; void gc_collect(void); micropython-1.12/ports/esp32/help.c000066400000000000000000000051431357706137100172240ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" const char esp32_help_text[] = "Welcome to MicroPython on the ESP32!\n" "\n" "For generic online docs please visit http://docs.micropython.org/\n" "\n" "For access to the hardware use the 'machine' module:\n" "\n" "import machine\n" "pin12 = machine.Pin(12, machine.Pin.OUT)\n" "pin12.value(1)\n" "pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)\n" "print(pin13.value())\n" "i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))\n" "i2c.scan()\n" "i2c.writeto(addr, b'1234')\n" "i2c.readfrom(addr, 4)\n" "\n" "Basic WiFi configuration:\n" "\n" "import network\n" "sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n" "sta_if.scan() # Scan for available access points\n" "sta_if.connect(\"\", \"\") # Connect to an AP\n" "sta_if.isconnected() # Check for successful connection\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" " CTRL-B -- on a blank line, enter normal REPL mode\n" " CTRL-C -- interrupt a running program\n" " CTRL-D -- on a blank line, do a soft reset of the board\n" " CTRL-E -- on a blank line, enter paste mode\n" "\n" "For further help on a specific object, type help(obj)\n" "For a list of available modules, type help('modules')\n" ; micropython-1.12/ports/esp32/machine_adc.c000066400000000000000000000134471357706137100205150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Nick Moore * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "esp_log.h" #include "driver/gpio.h" #include "driver/adc.h" #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" typedef struct _madc_obj_t { mp_obj_base_t base; gpio_num_t gpio_id; adc1_channel_t adc1_id; } madc_obj_t; STATIC const madc_obj_t madc_obj[] = { {{&machine_adc_type}, GPIO_NUM_36, ADC1_CHANNEL_0}, {{&machine_adc_type}, GPIO_NUM_37, ADC1_CHANNEL_1}, {{&machine_adc_type}, GPIO_NUM_38, ADC1_CHANNEL_2}, {{&machine_adc_type}, GPIO_NUM_39, ADC1_CHANNEL_3}, {{&machine_adc_type}, GPIO_NUM_32, ADC1_CHANNEL_4}, {{&machine_adc_type}, GPIO_NUM_33, ADC1_CHANNEL_5}, {{&machine_adc_type}, GPIO_NUM_34, ADC1_CHANNEL_6}, {{&machine_adc_type}, GPIO_NUM_35, ADC1_CHANNEL_7}, }; STATIC uint8_t adc_bit_width; STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { static int initialized = 0; if (!initialized) { adc1_config_width(ADC_WIDTH_12Bit); adc_bit_width = 12; initialized = 1; } mp_arg_check_num(n_args, n_kw, 1, 1, true); gpio_num_t pin_id = machine_pin_get_id(args[0]); const madc_obj_t *self = NULL; for (int i = 0; i < MP_ARRAY_SIZE(madc_obj); i++) { if (pin_id == madc_obj[i].gpio_id) { self = &madc_obj[i]; break; } } if (!self) mp_raise_ValueError("invalid Pin for ADC"); esp_err_t err = adc1_config_channel_atten(self->adc1_id, ADC_ATTEN_0db); if (err == ESP_OK) return MP_OBJ_FROM_PTR(self); mp_raise_ValueError("Parameter Error"); } STATIC void madc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { madc_obj_t *self = self_in; mp_printf(print, "ADC(Pin(%u))", self->gpio_id); } // read_u16() STATIC mp_obj_t madc_read_u16(mp_obj_t self_in) { madc_obj_t *self = MP_OBJ_TO_PTR(self_in); uint32_t raw = adc1_get_raw(self->adc1_id); // Scale raw reading to 16 bit value using a Taylor expansion (for 8 <= bits <= 16) uint32_t u16 = raw << (16 - adc_bit_width) | raw >> (2 * adc_bit_width - 16); return MP_OBJ_NEW_SMALL_INT(u16); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(madc_read_u16_obj, madc_read_u16); // Legacy method STATIC mp_obj_t madc_read(mp_obj_t self_in) { madc_obj_t *self = self_in; int val = adc1_get_raw(self->adc1_id); if (val == -1) mp_raise_ValueError("Parameter Error"); return MP_OBJ_NEW_SMALL_INT(val); } MP_DEFINE_CONST_FUN_OBJ_1(madc_read_obj, madc_read); STATIC mp_obj_t madc_atten(mp_obj_t self_in, mp_obj_t atten_in) { madc_obj_t *self = self_in; adc_atten_t atten = mp_obj_get_int(atten_in); esp_err_t err = adc1_config_channel_atten(self->adc1_id, atten); if (err == ESP_OK) return mp_const_none; mp_raise_ValueError("Parameter Error"); } MP_DEFINE_CONST_FUN_OBJ_2(madc_atten_obj, madc_atten); STATIC mp_obj_t madc_width(mp_obj_t cls_in, mp_obj_t width_in) { adc_bits_width_t width = mp_obj_get_int(width_in); esp_err_t err = adc1_config_width(width); if (err != ESP_OK) { mp_raise_ValueError("Parameter Error"); } switch (width) { case ADC_WIDTH_9Bit: adc_bit_width = 9; break; case ADC_WIDTH_10Bit: adc_bit_width = 10; break; case ADC_WIDTH_11Bit: adc_bit_width = 11; break; case ADC_WIDTH_12Bit: adc_bit_width = 12; break; default: break; } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(madc_width_fun_obj, madc_width); MP_DEFINE_CONST_CLASSMETHOD_OBJ(madc_width_obj, MP_ROM_PTR(&madc_width_fun_obj)); STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&madc_read_u16_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&madc_read_obj) }, { MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&madc_atten_obj) }, { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&madc_width_obj) }, { MP_ROM_QSTR(MP_QSTR_ATTN_0DB), MP_ROM_INT(ADC_ATTEN_0db) }, { MP_ROM_QSTR(MP_QSTR_ATTN_2_5DB), MP_ROM_INT(ADC_ATTEN_2_5db) }, { MP_ROM_QSTR(MP_QSTR_ATTN_6DB), MP_ROM_INT(ADC_ATTEN_6db) }, { MP_ROM_QSTR(MP_QSTR_ATTN_11DB), MP_ROM_INT(ADC_ATTEN_11db) }, { MP_ROM_QSTR(MP_QSTR_WIDTH_9BIT), MP_ROM_INT(ADC_WIDTH_9Bit) }, { MP_ROM_QSTR(MP_QSTR_WIDTH_10BIT), MP_ROM_INT(ADC_WIDTH_10Bit) }, { MP_ROM_QSTR(MP_QSTR_WIDTH_11BIT), MP_ROM_INT(ADC_WIDTH_11Bit) }, { MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(ADC_WIDTH_12Bit) }, }; STATIC MP_DEFINE_CONST_DICT(madc_locals_dict, madc_locals_dict_table); const mp_obj_type_t machine_adc_type = { { &mp_type_type }, .name = MP_QSTR_ADC, .print = madc_print, .make_new = madc_make_new, .locals_dict = (mp_obj_t)&madc_locals_dict, }; micropython-1.12/ports/esp32/machine_dac.c000066400000000000000000000064161357706137100205130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Nick Moore * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "esp_log.h" #include "driver/gpio.h" #include "driver/dac.h" #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" typedef struct _mdac_obj_t { mp_obj_base_t base; gpio_num_t gpio_id; dac_channel_t dac_id; } mdac_obj_t; STATIC const mdac_obj_t mdac_obj[] = { {{&machine_dac_type}, GPIO_NUM_25, DAC_CHANNEL_1}, {{&machine_dac_type}, GPIO_NUM_26, DAC_CHANNEL_2}, }; STATIC mp_obj_t mdac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, true); gpio_num_t pin_id = machine_pin_get_id(args[0]); const mdac_obj_t *self = NULL; for (int i = 0; i < MP_ARRAY_SIZE(mdac_obj); i++) { if (pin_id == mdac_obj[i].gpio_id) { self = &mdac_obj[i]; break; } } if (!self) mp_raise_ValueError("invalid Pin for DAC"); esp_err_t err = dac_output_enable(self->dac_id); if (err == ESP_OK) { err = dac_output_voltage(self->dac_id, 0); } if (err == ESP_OK) return MP_OBJ_FROM_PTR(self); mp_raise_ValueError("Parameter Error"); } STATIC void mdac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mdac_obj_t *self = self_in; mp_printf(print, "DAC(Pin(%u))", self->gpio_id); } STATIC mp_obj_t mdac_write(mp_obj_t self_in, mp_obj_t value_in) { mdac_obj_t *self = self_in; int value = mp_obj_get_int(value_in); if (value < 0 || value > 255) mp_raise_ValueError("Value out of range"); esp_err_t err = dac_output_voltage(self->dac_id, value); if (err == ESP_OK) return mp_const_none; mp_raise_ValueError("Parameter Error"); } MP_DEFINE_CONST_FUN_OBJ_2(mdac_write_obj, mdac_write); STATIC const mp_rom_map_elem_t mdac_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mdac_write_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mdac_locals_dict, mdac_locals_dict_table); const mp_obj_type_t machine_dac_type = { { &mp_type_type }, .name = MP_QSTR_DAC, .print = mdac_print, .make_new = mdac_make_new, .locals_dict = (mp_obj_t)&mdac_locals_dict, }; micropython-1.12/ports/esp32/machine_hw_spi.c000066400000000000000000000327231357706137100212550ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 "Eric Poulsen" * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" #include "extmod/machine_spi.h" #include "modmachine.h" #include "driver/spi_master.h" #define MP_HW_SPI_MAX_XFER_BYTES (4092) #define MP_HW_SPI_MAX_XFER_BITS (MP_HW_SPI_MAX_XFER_BYTES * 8) // Has to be an even multiple of 8 typedef struct _machine_hw_spi_obj_t { mp_obj_base_t base; spi_host_device_t host; uint32_t baudrate; uint8_t polarity; uint8_t phase; uint8_t bits; uint8_t firstbit; int8_t sck; int8_t mosi; int8_t miso; spi_device_handle_t spi; enum { MACHINE_HW_SPI_STATE_NONE, MACHINE_HW_SPI_STATE_INIT, MACHINE_HW_SPI_STATE_DEINIT } state; } machine_hw_spi_obj_t; // Static objects mapping to HSPI and VSPI hardware peripherals STATIC machine_hw_spi_obj_t machine_hw_spi_obj[2]; STATIC void machine_hw_spi_deinit_internal(machine_hw_spi_obj_t *self) { switch (spi_bus_remove_device(self->spi)) { case ESP_ERR_INVALID_ARG: mp_raise_msg(&mp_type_OSError, "invalid configuration"); return; case ESP_ERR_INVALID_STATE: mp_raise_msg(&mp_type_OSError, "SPI device already freed"); return; } switch (spi_bus_free(self->host)) { case ESP_ERR_INVALID_ARG: mp_raise_msg(&mp_type_OSError, "invalid configuration"); return; case ESP_ERR_INVALID_STATE: mp_raise_msg(&mp_type_OSError, "SPI bus already freed"); return; } int8_t pins[3] = {self->miso, self->mosi, self->sck}; for (int i = 0; i < 3; i++) { if (pins[i] != -1) { gpio_pad_select_gpio(pins[i]); gpio_matrix_out(pins[i], SIG_GPIO_OUT_IDX, false, false); gpio_set_direction(pins[i], GPIO_MODE_INPUT); } } } STATIC void machine_hw_spi_init_internal( machine_hw_spi_obj_t *self, int8_t host, int32_t baudrate, int8_t polarity, int8_t phase, int8_t bits, int8_t firstbit, int8_t sck, int8_t mosi, int8_t miso) { // if we're not initialized, then we're // implicitly 'changed', since this is the init routine bool changed = self->state != MACHINE_HW_SPI_STATE_INIT; esp_err_t ret; machine_hw_spi_obj_t old_self = *self; if (host != -1 && host != self->host) { self->host = host; changed = true; } if (baudrate != -1 && baudrate != self->baudrate) { self->baudrate = baudrate; changed = true; } if (polarity != -1 && polarity != self->polarity) { self->polarity = polarity; changed = true; } if (phase != -1 && phase != self->phase) { self->phase = phase; changed = true; } if (bits != -1 && bits != self->bits) { self->bits = bits; changed = true; } if (firstbit != -1 && firstbit != self->firstbit) { self->firstbit = firstbit; changed = true; } if (sck != -2 && sck != self->sck) { self->sck = sck; changed = true; } if (mosi != -2 && mosi != self->mosi) { self->mosi = mosi; changed = true; } if (miso != -2 && miso != self->miso) { self->miso = miso; changed = true; } if (self->host != HSPI_HOST && self->host != VSPI_HOST) { mp_raise_ValueError("SPI ID must be either HSPI(1) or VSPI(2)"); } if (changed) { if (self->state == MACHINE_HW_SPI_STATE_INIT) { self->state = MACHINE_HW_SPI_STATE_DEINIT; machine_hw_spi_deinit_internal(&old_self); } } else { return; // no changes } spi_bus_config_t buscfg = { .miso_io_num = self->miso, .mosi_io_num = self->mosi, .sclk_io_num = self->sck, .quadwp_io_num = -1, .quadhd_io_num = -1 }; spi_device_interface_config_t devcfg = { .clock_speed_hz = self->baudrate, .mode = self->phase | (self->polarity << 1), .spics_io_num = -1, // No CS pin .queue_size = 1, .flags = self->firstbit == MICROPY_PY_MACHINE_SPI_LSB ? SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST : 0, .pre_cb = NULL }; //Initialize the SPI bus // Select DMA channel based on the hardware SPI host int dma_chan = 0; if (self->host == HSPI_HOST) { dma_chan = 1; } else if (self->host == VSPI_HOST) { dma_chan = 2; } ret = spi_bus_initialize(self->host, &buscfg, dma_chan); switch (ret) { case ESP_ERR_INVALID_ARG: mp_raise_msg(&mp_type_OSError, "invalid configuration"); return; case ESP_ERR_INVALID_STATE: mp_raise_msg(&mp_type_OSError, "SPI host already in use"); return; } ret = spi_bus_add_device(self->host, &devcfg, &self->spi); switch (ret) { case ESP_ERR_INVALID_ARG: mp_raise_msg(&mp_type_OSError, "invalid configuration"); spi_bus_free(self->host); return; case ESP_ERR_NO_MEM: mp_raise_msg(&mp_type_OSError, "out of memory"); spi_bus_free(self->host); return; case ESP_ERR_NOT_FOUND: mp_raise_msg(&mp_type_OSError, "no free slots"); spi_bus_free(self->host); return; } self->state = MACHINE_HW_SPI_STATE_INIT; } STATIC void machine_hw_spi_deinit(mp_obj_base_t *self_in) { machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t *) self_in; if (self->state == MACHINE_HW_SPI_STATE_INIT) { self->state = MACHINE_HW_SPI_STATE_DEINIT; machine_hw_spi_deinit_internal(self); } } STATIC void machine_hw_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { machine_hw_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->state == MACHINE_HW_SPI_STATE_DEINIT) { mp_raise_msg(&mp_type_OSError, "transfer on deinitialized SPI"); return; } struct spi_transaction_t transaction = { 0 }; // Round to nearest whole set of bits int bits_to_send = len * 8 / self->bits * self->bits; if (len <= 4) { if (src != NULL) { memcpy(&transaction.tx_data, src, len); } transaction.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; transaction.length = bits_to_send; spi_device_transmit(self->spi, &transaction); if (dest != NULL) { memcpy(dest, &transaction.rx_data, len); } } else { int offset = 0; int bits_remaining = bits_to_send; while (bits_remaining) { memset(&transaction, 0, sizeof(transaction)); transaction.length = bits_remaining > MP_HW_SPI_MAX_XFER_BITS ? MP_HW_SPI_MAX_XFER_BITS : bits_remaining; if (src != NULL) { transaction.tx_buffer = src + offset; } if (dest != NULL) { transaction.rx_buffer = dest + offset; } spi_device_transmit(self->spi, &transaction); bits_remaining -= transaction.length; // doesn't need ceil(); loop ends when bits_remaining is 0 offset += transaction.length / 8; } } } /******************************************************************************/ // MicroPython bindings for hw_spi STATIC void machine_hw_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hw_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "SPI(id=%u, baudrate=%u, polarity=%u, phase=%u, bits=%u, firstbit=%u, sck=%d, mosi=%d, miso=%d)", self->host, self->baudrate, self->polarity, self->phase, self->bits, self->firstbit, self->sck, self->mosi, self->miso); } STATIC void machine_hw_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t *) self_in; enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); int8_t sck, mosi, miso; if (args[ARG_sck].u_obj == MP_OBJ_NULL) { sck = -2; } else if (args[ARG_sck].u_obj == mp_const_none) { sck = -1; } else { sck = machine_pin_get_id(args[ARG_sck].u_obj); } if (args[ARG_miso].u_obj == MP_OBJ_NULL) { miso = -2; } else if (args[ARG_miso].u_obj == mp_const_none) { miso = -1; } else { miso = machine_pin_get_id(args[ARG_miso].u_obj); } if (args[ARG_mosi].u_obj == MP_OBJ_NULL) { mosi = -2; } else if (args[ARG_mosi].u_obj == mp_const_none) { mosi = -1; } else { mosi = machine_pin_get_id(args[ARG_mosi].u_obj); } machine_hw_spi_init_internal(self, args[ARG_id].u_int, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, args[ARG_phase].u_int, args[ARG_bits].u_int, args[ARG_firstbit].u_int, sck, mosi, miso); } mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); machine_hw_spi_obj_t *self; if (args[ARG_id].u_int == HSPI_HOST) { self = &machine_hw_spi_obj[0]; } else { self = &machine_hw_spi_obj[1]; } self->base.type = &machine_hw_spi_type; machine_hw_spi_init_internal( self, args[ARG_id].u_int, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, args[ARG_phase].u_int, args[ARG_bits].u_int, args[ARG_firstbit].u_int, args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj), args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj), args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj)); return MP_OBJ_FROM_PTR(self); } STATIC const mp_machine_spi_p_t machine_hw_spi_p = { .init = machine_hw_spi_init, .deinit = machine_hw_spi_deinit, .transfer = machine_hw_spi_transfer, }; const mp_obj_type_t machine_hw_spi_type = { { &mp_type_type }, .name = MP_QSTR_SPI, .print = machine_hw_spi_print, .make_new = machine_hw_spi_make_new, .protocol = &machine_hw_spi_p, .locals_dict = (mp_obj_dict_t *) &mp_machine_spi_locals_dict, }; micropython-1.12/ports/esp32/machine_i2c.c000066400000000000000000000145731357706137100204440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mphal.h" #include "py/mperrno.h" #include "extmod/machine_i2c.h" #include "driver/i2c.h" #define I2C_0_DEFAULT_SCL (GPIO_NUM_18) #define I2C_0_DEFAULT_SDA (GPIO_NUM_19) #define I2C_1_DEFAULT_SCL (GPIO_NUM_25) #define I2C_1_DEFAULT_SDA (GPIO_NUM_26) #define I2C_DEFAULT_TIMEOUT_US (10000) // 10ms typedef struct _machine_hw_i2c_obj_t { mp_obj_base_t base; i2c_port_t port : 8; gpio_num_t scl : 8; gpio_num_t sda : 8; } machine_hw_i2c_obj_t; STATIC const mp_obj_type_t machine_hw_i2c_type; STATIC machine_hw_i2c_obj_t machine_hw_i2c_obj[I2C_NUM_MAX]; STATIC void machine_hw_i2c_init(machine_hw_i2c_obj_t *self, uint32_t freq, uint32_t timeout_us, bool first_init) { if (!first_init) { i2c_driver_delete(self->port); } i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = self->sda, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_io_num = self->scl, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = freq, }; i2c_param_config(self->port, &conf); i2c_set_timeout(self->port, I2C_APB_CLK_FREQ / 1000000 * timeout_us); i2c_driver_install(self->port, I2C_MODE_MASTER, 0, 0, 0); } int machine_hw_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { machine_hw_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, addr << 1 | (flags & MP_MACHINE_I2C_FLAG_READ), true); int data_len = 0; for (; n--; ++bufs) { if (flags & MP_MACHINE_I2C_FLAG_READ) { i2c_master_read(cmd, bufs->buf, bufs->len, n == 0 ? I2C_MASTER_LAST_NACK : I2C_MASTER_ACK); } else { if (bufs->len != 0) { i2c_master_write(cmd, bufs->buf, bufs->len, true); } } data_len += bufs->len; } if (flags & MP_MACHINE_I2C_FLAG_STOP) { i2c_master_stop(cmd); } // TODO proper timeout esp_err_t err = i2c_master_cmd_begin(self->port, cmd, 100 * (1 + data_len) / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); if (err == ESP_FAIL) { return -MP_ENODEV; } else if (err == ESP_ERR_TIMEOUT) { return -MP_ETIMEDOUT; } else if (err != ESP_OK) { return -abs(err); } return data_len; } /******************************************************************************/ // MicroPython bindings for machine API STATIC void machine_hw_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hw_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); int h, l; i2c_get_period(self->port, &h, &l); mp_printf(print, "I2C(%u, scl=%u, sda=%u, freq=%u)", self->port, self->scl, self->sda, I2C_APB_CLK_FREQ / (h + l)); } mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // Parse args enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2C_DEFAULT_TIMEOUT_US} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // Get I2C bus mp_int_t i2c_id = mp_obj_get_int(args[ARG_id].u_obj); if (!(I2C_NUM_0 <= i2c_id && i2c_id < I2C_NUM_MAX)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%d) doesn't exist", i2c_id)); } // Get static peripheral object machine_hw_i2c_obj_t *self = (machine_hw_i2c_obj_t*)&machine_hw_i2c_obj[i2c_id]; bool first_init = false; if (self->base.type == NULL) { // Created for the first time, set default pins self->base.type = &machine_hw_i2c_type; self->port = i2c_id; if (self->port == I2C_NUM_0) { self->scl = I2C_0_DEFAULT_SCL; self->sda = I2C_0_DEFAULT_SDA; } else { self->scl = I2C_1_DEFAULT_SCL; self->sda = I2C_1_DEFAULT_SDA; } first_init = true; } // Set SCL/SDA pins if given if (args[ARG_scl].u_obj != MP_OBJ_NULL) { self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj); } if (args[ARG_sda].u_obj != MP_OBJ_NULL) { self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj); } // Initialise the I2C peripheral machine_hw_i2c_init(self, args[ARG_freq].u_int, args[ARG_timeout].u_int, first_init); return MP_OBJ_FROM_PTR(self); } STATIC const mp_machine_i2c_p_t machine_hw_i2c_p = { .transfer = machine_hw_i2c_transfer, }; STATIC const mp_obj_type_t machine_hw_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, .print = machine_hw_i2c_print, .make_new = machine_hw_i2c_make_new, .protocol = &machine_hw_i2c_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict, }; micropython-1.12/ports/esp32/machine_pin.c000066400000000000000000000405041357706137100205460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "driver/gpio.h" #include "py/runtime.h" #include "py/mphal.h" #include "mphalport.h" #include "modmachine.h" #include "extmod/virtpin.h" #include "machine_rtc.h" #include "modesp32.h" // Used to implement a range of pull capabilities #define GPIO_PULL_DOWN (1) #define GPIO_PULL_UP (2) #define GPIO_PULL_HOLD (4) typedef struct _machine_pin_obj_t { mp_obj_base_t base; gpio_num_t id; } machine_pin_obj_t; typedef struct _machine_pin_irq_obj_t { mp_obj_base_t base; gpio_num_t id; } machine_pin_irq_obj_t; STATIC const machine_pin_obj_t machine_pin_obj[] = { {{&machine_pin_type}, GPIO_NUM_0}, {{&machine_pin_type}, GPIO_NUM_1}, {{&machine_pin_type}, GPIO_NUM_2}, {{&machine_pin_type}, GPIO_NUM_3}, {{&machine_pin_type}, GPIO_NUM_4}, {{&machine_pin_type}, GPIO_NUM_5}, {{&machine_pin_type}, GPIO_NUM_6}, {{&machine_pin_type}, GPIO_NUM_7}, {{&machine_pin_type}, GPIO_NUM_8}, {{&machine_pin_type}, GPIO_NUM_9}, {{&machine_pin_type}, GPIO_NUM_10}, {{&machine_pin_type}, GPIO_NUM_11}, {{&machine_pin_type}, GPIO_NUM_12}, {{&machine_pin_type}, GPIO_NUM_13}, {{&machine_pin_type}, GPIO_NUM_14}, {{&machine_pin_type}, GPIO_NUM_15}, {{&machine_pin_type}, GPIO_NUM_16}, {{&machine_pin_type}, GPIO_NUM_17}, {{&machine_pin_type}, GPIO_NUM_18}, {{&machine_pin_type}, GPIO_NUM_19}, {{NULL}, -1}, {{&machine_pin_type}, GPIO_NUM_21}, {{&machine_pin_type}, GPIO_NUM_22}, {{&machine_pin_type}, GPIO_NUM_23}, {{NULL}, -1}, {{&machine_pin_type}, GPIO_NUM_25}, {{&machine_pin_type}, GPIO_NUM_26}, {{&machine_pin_type}, GPIO_NUM_27}, {{NULL}, -1}, {{NULL}, -1}, {{NULL}, -1}, {{NULL}, -1}, {{&machine_pin_type}, GPIO_NUM_32}, {{&machine_pin_type}, GPIO_NUM_33}, {{&machine_pin_type}, GPIO_NUM_34}, {{&machine_pin_type}, GPIO_NUM_35}, {{&machine_pin_type}, GPIO_NUM_36}, {{&machine_pin_type}, GPIO_NUM_37}, {{&machine_pin_type}, GPIO_NUM_38}, {{&machine_pin_type}, GPIO_NUM_39}, }; // forward declaration STATIC const machine_pin_irq_obj_t machine_pin_irq_object[]; void machine_pins_init(void) { static bool did_install = false; if (!did_install) { gpio_install_isr_service(0); did_install = true; } memset(&MP_STATE_PORT(machine_pin_irq_handler[0]), 0, sizeof(MP_STATE_PORT(machine_pin_irq_handler))); } void machine_pins_deinit(void) { for (int i = 0; i < MP_ARRAY_SIZE(machine_pin_obj); ++i) { if (machine_pin_obj[i].id != (gpio_num_t)-1) { gpio_isr_handler_remove(machine_pin_obj[i].id); } } } STATIC void machine_pin_isr_handler(void *arg) { machine_pin_obj_t *self = arg; mp_obj_t handler = MP_STATE_PORT(machine_pin_irq_handler)[self->id]; mp_sched_schedule(handler, MP_OBJ_FROM_PTR(self)); mp_hal_wake_main_task_from_isr(); } gpio_num_t machine_pin_get_id(mp_obj_t pin_in) { if (mp_obj_get_type(pin_in) != &machine_pin_type) { mp_raise_ValueError("expecting a pin"); } machine_pin_obj_t *self = pin_in; return self->id; } STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pin_obj_t *self = self_in; mp_printf(print, "Pin(%u)", self->id); } // pin.init(mode, pull=None, *, value) STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_pull, ARG_value }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = mp_const_none}}, { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)}}, { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // configure the pin for gpio gpio_pad_select_gpio(self->id); // set initial value (do this before configuring mode/pull) if (args[ARG_value].u_obj != MP_OBJ_NULL) { gpio_set_level(self->id, mp_obj_is_true(args[ARG_value].u_obj)); } // configure mode if (args[ARG_mode].u_obj != mp_const_none) { mp_int_t pin_io_mode = mp_obj_get_int(args[ARG_mode].u_obj); if (self->id >= 34 && (pin_io_mode & GPIO_MODE_DEF_OUTPUT)) { mp_raise_ValueError("pin can only be input"); } else { gpio_set_direction(self->id, pin_io_mode); } } // configure pull if (args[ARG_pull].u_obj != MP_OBJ_NEW_SMALL_INT(-1)) { int mode = 0; if (args[ARG_pull].u_obj != mp_const_none) { mode = mp_obj_get_int(args[ARG_pull].u_obj); } if (mode & GPIO_PULL_DOWN) { gpio_pulldown_en(self->id); } else { gpio_pulldown_dis(self->id); } if (mode & GPIO_PULL_UP) { gpio_pullup_en(self->id); } else { gpio_pullup_dis(self->id); } if (mode & GPIO_PULL_HOLD) { gpio_hold_en(self->id); } else if (GPIO_IS_VALID_OUTPUT_GPIO(self->id)) { gpio_hold_dis(self->id); } } return mp_const_none; } // constructor(id, ...) mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get the wanted pin object int wanted_pin = mp_obj_get_int(args[0]); const machine_pin_obj_t *self = NULL; if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) { self = (machine_pin_obj_t*)&machine_pin_obj[wanted_pin]; } if (self == NULL || self->base.type == NULL) { mp_raise_ValueError("invalid pin"); } if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(self); } // fast method for getting/setting pin value STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); machine_pin_obj_t *self = self_in; if (n_args == 0) { // get pin return MP_OBJ_NEW_SMALL_INT(gpio_get_level(self->id)); } else { // set pin gpio_set_level(self->id, mp_obj_is_true(args[0])); return mp_const_none; } } // pin.init(mode, pull) STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); } MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); // pin.value([value]) STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { return machine_pin_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); // pin.off() STATIC mp_obj_t machine_pin_off(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); gpio_set_level(self->id, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_off_obj, machine_pin_off); // pin.on() STATIC mp_obj_t machine_pin_on(mp_obj_t self_in) { machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); gpio_set_level(self->id, 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on); // pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING) STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_handler, ARG_trigger, ARG_wake }; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE} }, { MP_QSTR_wake, MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (n_args > 1 || kw_args->used != 0) { // configure irq mp_obj_t handler = args[ARG_handler].u_obj; uint32_t trigger = args[ARG_trigger].u_int; mp_obj_t wake_obj = args[ARG_wake].u_obj; if ((trigger == GPIO_PIN_INTR_LOLEVEL || trigger == GPIO_PIN_INTR_HILEVEL) && wake_obj != mp_const_none) { mp_int_t wake; if (mp_obj_get_int_maybe(wake_obj, &wake)) { if (wake < 2 || wake > 7) { mp_raise_ValueError("bad wake value"); } } else { mp_raise_ValueError("bad wake value"); } if (machine_rtc_config.wake_on_touch) { // not compatible mp_raise_ValueError("no resources"); } if (!RTC_IS_VALID_EXT_PIN(self->id)) { mp_raise_ValueError("invalid pin for wake"); } if (machine_rtc_config.ext0_pin == -1) { machine_rtc_config.ext0_pin = self->id; } else if (machine_rtc_config.ext0_pin != self->id) { mp_raise_ValueError("no resources"); } machine_rtc_config.ext0_level = trigger == GPIO_PIN_INTR_LOLEVEL ? 0 : 1; machine_rtc_config.ext0_wake_types = wake; } else { if (machine_rtc_config.ext0_pin == self->id) { machine_rtc_config.ext0_pin = -1; } if (handler == mp_const_none) { handler = MP_OBJ_NULL; trigger = 0; } gpio_isr_handler_remove(self->id); MP_STATE_PORT(machine_pin_irq_handler)[self->id] = handler; gpio_set_intr_type(self->id, trigger); gpio_isr_handler_add(self->id, machine_pin_isr_handler, (void*)self); } } // return the irq object return MP_OBJ_FROM_PTR(&machine_pin_irq_object[self->id]); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq); STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) }, { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) }, { MP_ROM_QSTR(MP_QSTR_PULL_HOLD), MP_ROM_INT(GPIO_PULL_HOLD) }, { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, { MP_ROM_QSTR(MP_QSTR_WAKE_LOW), MP_ROM_INT(GPIO_PIN_INTR_LOLEVEL) }, { MP_ROM_QSTR(MP_QSTR_WAKE_HIGH), MP_ROM_INT(GPIO_PIN_INTR_HILEVEL) }, }; STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; machine_pin_obj_t *self = self_in; switch (request) { case MP_PIN_READ: { return gpio_get_level(self->id); } case MP_PIN_WRITE: { gpio_set_level(self->id, arg); return 0; } } return -1; } STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; const mp_obj_type_t machine_pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, .print = machine_pin_print, .make_new = mp_pin_make_new, .call = machine_pin_call, .protocol = &pin_pin_p, .locals_dict = (mp_obj_t)&machine_pin_locals_dict, }; /******************************************************************************/ // Pin IRQ object STATIC const mp_obj_type_t machine_pin_irq_type; STATIC const machine_pin_irq_obj_t machine_pin_irq_object[] = { {{&machine_pin_irq_type}, GPIO_NUM_0}, {{&machine_pin_irq_type}, GPIO_NUM_1}, {{&machine_pin_irq_type}, GPIO_NUM_2}, {{&machine_pin_irq_type}, GPIO_NUM_3}, {{&machine_pin_irq_type}, GPIO_NUM_4}, {{&machine_pin_irq_type}, GPIO_NUM_5}, {{&machine_pin_irq_type}, GPIO_NUM_6}, {{&machine_pin_irq_type}, GPIO_NUM_7}, {{&machine_pin_irq_type}, GPIO_NUM_8}, {{&machine_pin_irq_type}, GPIO_NUM_9}, {{&machine_pin_irq_type}, GPIO_NUM_10}, {{&machine_pin_irq_type}, GPIO_NUM_11}, {{&machine_pin_irq_type}, GPIO_NUM_12}, {{&machine_pin_irq_type}, GPIO_NUM_13}, {{&machine_pin_irq_type}, GPIO_NUM_14}, {{&machine_pin_irq_type}, GPIO_NUM_15}, {{&machine_pin_irq_type}, GPIO_NUM_16}, {{&machine_pin_irq_type}, GPIO_NUM_17}, {{&machine_pin_irq_type}, GPIO_NUM_18}, {{&machine_pin_irq_type}, GPIO_NUM_19}, {{NULL}, -1}, {{&machine_pin_irq_type}, GPIO_NUM_21}, {{&machine_pin_irq_type}, GPIO_NUM_22}, {{&machine_pin_irq_type}, GPIO_NUM_23}, {{NULL}, -1}, {{&machine_pin_irq_type}, GPIO_NUM_25}, {{&machine_pin_irq_type}, GPIO_NUM_26}, {{&machine_pin_irq_type}, GPIO_NUM_27}, {{NULL}, -1}, {{NULL}, -1}, {{NULL}, -1}, {{NULL}, -1}, {{&machine_pin_irq_type}, GPIO_NUM_32}, {{&machine_pin_irq_type}, GPIO_NUM_33}, {{&machine_pin_irq_type}, GPIO_NUM_34}, {{&machine_pin_irq_type}, GPIO_NUM_35}, {{&machine_pin_irq_type}, GPIO_NUM_36}, {{&machine_pin_irq_type}, GPIO_NUM_37}, {{&machine_pin_irq_type}, GPIO_NUM_38}, {{&machine_pin_irq_type}, GPIO_NUM_39}, }; STATIC mp_obj_t machine_pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { machine_pin_irq_obj_t *self = self_in; mp_arg_check_num(n_args, n_kw, 0, 0, false); machine_pin_isr_handler((void*)&machine_pin_obj[self->id]); return mp_const_none; } STATIC mp_obj_t machine_pin_irq_trigger(size_t n_args, const mp_obj_t *args) { machine_pin_irq_obj_t *self = args[0]; uint32_t orig_trig = GPIO.pin[self->id].int_type; if (n_args == 2) { // set trigger gpio_set_intr_type(self->id, mp_obj_get_int(args[1])); } // return original trigger value return MP_OBJ_NEW_SMALL_INT(orig_trig); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_irq_trigger_obj, 1, 2, machine_pin_irq_trigger); STATIC const mp_rom_map_elem_t machine_pin_irq_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&machine_pin_irq_trigger_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pin_irq_locals_dict, machine_pin_irq_locals_dict_table); STATIC const mp_obj_type_t machine_pin_irq_type = { { &mp_type_type }, .name = MP_QSTR_IRQ, .call = machine_pin_irq_call, .locals_dict = (mp_obj_dict_t*)&machine_pin_irq_locals_dict, }; micropython-1.12/ports/esp32/machine_pwm.c000066400000000000000000000222171357706137100205640ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "driver/ledc.h" #include "esp_err.h" #include "py/nlr.h" #include "py/runtime.h" #include "modmachine.h" #include "mphalport.h" // Forward dec'l extern const mp_obj_type_t machine_pwm_type; typedef struct _esp32_pwm_obj_t { mp_obj_base_t base; gpio_num_t pin; uint8_t active; uint8_t channel; } esp32_pwm_obj_t; // Which channel has which GPIO pin assigned? // (-1 if not assigned) STATIC int chan_gpio[LEDC_CHANNEL_MAX]; // Params for PW operation // 5khz #define PWFREQ (5000) // High speed mode #define PWMODE (LEDC_HIGH_SPEED_MODE) // 10-bit resolution (compatible with esp8266 PWM) #define PWRES (LEDC_TIMER_10_BIT) // Timer 1 #define PWTIMER (LEDC_TIMER_1) // Config of timer upon which we run all PWM'ed GPIO pins STATIC bool pwm_inited = false; STATIC ledc_timer_config_t timer_cfg = { .duty_resolution = PWRES, .freq_hz = PWFREQ, .speed_mode = PWMODE, .timer_num = PWTIMER }; STATIC void pwm_init(void) { // Initial condition: no channels assigned for (int x = 0; x < LEDC_CHANNEL_MAX; ++x) { chan_gpio[x] = -1; } // Init with default timer params ledc_timer_config(&timer_cfg); } STATIC int set_freq(int newval) { int ores = timer_cfg.duty_resolution; int oval = timer_cfg.freq_hz; // Find the highest bit resolution for the requested frequency if (newval <= 0) { newval = 1; } unsigned int res = 0; for (unsigned int i = LEDC_APB_CLK_HZ / newval; i > 1; i >>= 1, ++res) { } if (res == 0) { res = 1; } else if (res > PWRES) { // Limit resolution to PWRES to match units of our duty res = PWRES; } // Configure the new resolution and frequency timer_cfg.duty_resolution = res; timer_cfg.freq_hz = newval; if (ledc_timer_config(&timer_cfg) != ESP_OK) { timer_cfg.duty_resolution = ores; timer_cfg.freq_hz = oval; return 0; } return 1; } /******************************************************************************/ // MicroPython bindings for PWM STATIC void esp32_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "PWM(%u", self->pin); if (self->active) { mp_printf(print, ", freq=%u, duty=%u", timer_cfg.freq_hz, ledc_get_duty(PWMODE, self->channel)); } mp_printf(print, ")"); } STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_freq, ARG_duty }; static const mp_arg_t allowed_args[] = { { MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_duty, MP_ARG_INT, {.u_int = -1} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); int channel; int avail = -1; // Find a free PWM channel, also spot if our pin is // already mentioned. for (channel = 0; channel < LEDC_CHANNEL_MAX; ++channel) { if (chan_gpio[channel] == self->pin) { break; } if ((avail == -1) && (chan_gpio[channel] == -1)) { avail = channel; } } if (channel >= LEDC_CHANNEL_MAX) { if (avail == -1) { mp_raise_ValueError("out of PWM channels"); } channel = avail; } self->channel = channel; // New PWM assignment self->active = 1; if (chan_gpio[channel] == -1) { ledc_channel_config_t cfg = { .channel = channel, .duty = (1 << timer_cfg.duty_resolution) / 2, .gpio_num = self->pin, .intr_type = LEDC_INTR_DISABLE, .speed_mode = PWMODE, .timer_sel = PWTIMER, }; if (ledc_channel_config(&cfg) != ESP_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "PWM not supported on pin %d", self->pin)); } chan_gpio[channel] = self->pin; } // Maybe change PWM timer int tval = args[ARG_freq].u_int; if (tval != -1) { if (tval != timer_cfg.freq_hz) { if (!set_freq(tval)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Bad frequency %d", tval)); } } } // Set duty cycle? int dval = args[ARG_duty].u_int; if (dval != -1) { dval &= ((1 << PWRES)-1); dval >>= PWRES - timer_cfg.duty_resolution; ledc_set_duty(PWMODE, channel, dval); ledc_update_duty(PWMODE, channel); } } STATIC mp_obj_t esp32_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); gpio_num_t pin_id = machine_pin_get_id(args[0]); // create PWM object from the given pin esp32_pwm_obj_t *self = m_new_obj(esp32_pwm_obj_t); self->base.type = &machine_pwm_type; self->pin = pin_id; self->active = 0; self->channel = -1; // start the PWM subsystem if it's not already running if (!pwm_inited) { pwm_init(); pwm_inited = true; } // start the PWM running for this channel mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); esp32_pwm_init_helper(self, n_args - 1, args + 1, &kw_args); return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t esp32_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { esp32_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(esp32_pwm_init_obj, 1, esp32_pwm_init); STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) { esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); int chan = self->channel; // Valid channel? if ((chan >= 0) && (chan < LEDC_CHANNEL_MAX)) { // Mark it unused, and tell the hardware to stop routing chan_gpio[chan] = -1; ledc_stop(PWMODE, chan, 0); self->active = 0; self->channel = -1; gpio_matrix_out(self->pin, SIG_GPIO_OUT_IDX, false, false); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_pwm_deinit_obj, esp32_pwm_deinit); STATIC mp_obj_t esp32_pwm_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 1) { // get return MP_OBJ_NEW_SMALL_INT(timer_cfg.freq_hz); } // set int tval = mp_obj_get_int(args[1]); if (!set_freq(tval)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Bad frequency %d", tval)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_freq_obj, 1, 2, esp32_pwm_freq); STATIC mp_obj_t esp32_pwm_duty(size_t n_args, const mp_obj_t *args) { esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); int duty; if (n_args == 1) { // get duty = ledc_get_duty(PWMODE, self->channel); duty <<= PWRES - timer_cfg.duty_resolution; return MP_OBJ_NEW_SMALL_INT(duty); } // set duty = mp_obj_get_int(args[1]); duty &= ((1 << PWRES)-1); duty >>= PWRES - timer_cfg.duty_resolution; ledc_set_duty(PWMODE, self->channel, duty); ledc_update_duty(PWMODE, self->channel); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_duty_obj, 1, 2, esp32_pwm_duty); STATIC const mp_rom_map_elem_t esp32_pwm_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&esp32_pwm_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_pwm_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&esp32_pwm_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&esp32_pwm_duty_obj) }, }; STATIC MP_DEFINE_CONST_DICT(esp32_pwm_locals_dict, esp32_pwm_locals_dict_table); const mp_obj_type_t machine_pwm_type = { { &mp_type_type }, .name = MP_QSTR_PWM, .print = esp32_pwm_print, .make_new = esp32_pwm_make_new, .locals_dict = (mp_obj_dict_t*)&esp32_pwm_locals_dict, }; micropython-1.12/ports/esp32/machine_rtc.c000066400000000000000000000145641357706137100205570ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 "Eric Poulsen" * Copyright (c) 2017 "Tom Manning" * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "driver/gpio.h" #include "py/nlr.h" #include "py/obj.h" #include "py/runtime.h" #include "py/mphal.h" #include "timeutils.h" #include "modmachine.h" #include "machine_rtc.h" typedef struct _machine_rtc_obj_t { mp_obj_base_t base; } machine_rtc_obj_t; /* There is 8K of rtc_slow_memory, but some is used by the system software If the MICROPY_HW_RTC_USER_MEM_MAX is set too high, the following compile error will happen: region `rtc_slow_seg' overflowed by N bytes The current system software allows almost 4096 to be used. To avoid running into issues if the system software uses more, 2048 was picked as a max length You can also change this max length at compile time by defining MICROPY_HW_RTC_USER_MEM_MAX either on your make line, or in your board config. If MICROPY_HW_RTC_USER_MEM_MAX is set to 0, the RTC.memory() functionality will be not be compiled which frees some extra flash and RTC memory. */ #ifndef MICROPY_HW_RTC_USER_MEM_MAX #define MICROPY_HW_RTC_USER_MEM_MAX 2048 #endif // Optionally compile user memory functionality if the size of memory is greater than 0 #if MICROPY_HW_RTC_USER_MEM_MAX > 0 #define MEM_MAGIC 0x75507921 RTC_DATA_ATTR uint32_t rtc_user_mem_magic; RTC_DATA_ATTR uint16_t rtc_user_mem_len; RTC_DATA_ATTR uint8_t rtc_user_mem_data[MICROPY_HW_RTC_USER_MEM_MAX]; #endif // singleton RTC object STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; machine_rtc_config_t machine_rtc_config = { .ext1_pins = 0, .ext0_pin = -1 }; STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); // return constant object return (mp_obj_t)&machine_rtc_obj; } STATIC mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 1) { // Get time struct timeval tv; gettimeofday(&tv, NULL); timeutils_struct_time_t tm; timeutils_seconds_since_2000_to_struct_time(tv.tv_sec, &tm); mp_obj_t tuple[8] = { mp_obj_new_int(tm.tm_year), mp_obj_new_int(tm.tm_mon), mp_obj_new_int(tm.tm_mday), mp_obj_new_int(tm.tm_wday), mp_obj_new_int(tm.tm_hour), mp_obj_new_int(tm.tm_min), mp_obj_new_int(tm.tm_sec), mp_obj_new_int(tv.tv_usec) }; return mp_obj_new_tuple(8, tuple); } else { // Set time mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 8, &items); struct timeval tv = {0}; tv.tv_sec = timeutils_seconds_since_2000(mp_obj_get_int(items[0]), mp_obj_get_int(items[1]), mp_obj_get_int(items[2]), mp_obj_get_int(items[4]), mp_obj_get_int(items[5]), mp_obj_get_int(items[6])); tv.tv_usec = mp_obj_get_int(items[7]); settimeofday(&tv, NULL); return mp_const_none; } } STATIC mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { return machine_rtc_datetime_helper(n_args, args); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, machine_rtc_datetime); STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) { mp_obj_t args[2] = {self_in, date}; machine_rtc_datetime_helper(2, args); #if MICROPY_HW_RTC_USER_MEM_MAX > 0 if (rtc_user_mem_magic != MEM_MAGIC) { rtc_user_mem_magic = MEM_MAGIC; rtc_user_mem_len = 0; } #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); #if MICROPY_HW_RTC_USER_MEM_MAX > 0 STATIC mp_obj_t machine_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 1) { // read RTC memory uint8_t rtcram[MICROPY_HW_RTC_USER_MEM_MAX]; memcpy((char*)rtcram, (char*)rtc_user_mem_data, rtc_user_mem_len); return mp_obj_new_bytes(rtcram, rtc_user_mem_len); } else { // write RTC memory mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); if (bufinfo.len > MICROPY_HW_RTC_USER_MEM_MAX) { mp_raise_ValueError("buffer too long"); } memcpy( (char *) rtc_user_mem_data, (char *) bufinfo.buf, bufinfo.len); rtc_user_mem_len = bufinfo.len; return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_memory_obj, 1, 2, machine_rtc_memory); #endif STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) }, { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) }, #if MICROPY_HW_RTC_USER_MEM_MAX > 0 { MP_ROM_QSTR(MP_QSTR_memory), MP_ROM_PTR(&machine_rtc_memory_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); const mp_obj_type_t machine_rtc_type = { { &mp_type_type }, .name = MP_QSTR_RTC, .make_new = machine_rtc_make_new, .locals_dict = (mp_obj_t)&machine_rtc_locals_dict, }; micropython-1.12/ports/esp32/machine_rtc.h000066400000000000000000000032701357706137100205540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 "Eric Poulsen" * Copyright (c) 2017 "Tom Manning" * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_ESP32_MACHINE_RTC_H #define MICROPY_INCLUDED_ESP32_MACHINE_RTC_H #include "modmachine.h" typedef struct { uint64_t ext1_pins; // set bit == pin# int8_t ext0_pin; // just the pin#, -1 == None bool wake_on_touch : 1; bool ext0_level : 1; wake_type_t ext0_wake_types; bool ext1_level : 1; } machine_rtc_config_t; extern machine_rtc_config_t machine_rtc_config; #endif micropython-1.12/ports/esp32/machine_sdcard.c000066400000000000000000000332741357706137100212260ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Nicko van Someren * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/mphal.h" #include "py/mperrno.h" #include "extmod/vfs_fat.h" #include "driver/sdmmc_host.h" #include "driver/sdspi_host.h" #include "sdmmc_cmd.h" #include "esp_log.h" #define DEBUG 0 #if DEBUG #define DEBUG_printf(...) ESP_LOGI("modsdcard", __VA_ARGS__) #else #define DEBUG_printf(...) (void)0 #endif // // There are three layers of abstraction: host, slot and card. // Creating an SD Card object will initialise the host and slot. // Cards gets initialised by ioctl op==1 and de-inited by ioctl 2 // Hosts are de-inited in __del__. Slots do not need de-initing. // // Currently the ESP32 Library doesn't support MMC cards, so // we don't enable on MICROPY_HW_ENABLE_MMCARD. #if MICROPY_HW_ENABLE_SDCARD // Forward declaration const mp_obj_type_t machine_sdcard_type; typedef struct _sdcard_obj_t { mp_obj_base_t base; mp_int_t flags; sdmmc_host_t host; // The card structure duplicates the host. It's not clear if we // can avoid this given the way that it is copied. sdmmc_card_t card; } sdcard_card_obj_t; #define SDCARD_CARD_FLAGS_HOST_INIT_DONE 0x01 #define SDCARD_CARD_FLAGS_CARD_INIT_DONE 0x02 #define _SECTOR_SIZE(self) (self->card.csd.sector_size) STATIC esp_err_t check_esp_err(esp_err_t code) { switch(code) { case ESP_OK: return ESP_OK; case ESP_ERR_NO_MEM: code = MP_ENOMEM; break; case ESP_ERR_TIMEOUT: code = MP_ETIMEDOUT; break; case ESP_ERR_NOT_SUPPORTED: code = MP_EOPNOTSUPP; break; } mp_raise_OSError(code); } STATIC gpio_num_t pin_or_int(const mp_obj_t arg) { if (mp_obj_is_small_int(arg)) { return MP_OBJ_SMALL_INT_VALUE(arg); } else { // This raises a value error if the argument is not a Pin. return machine_pin_get_id(arg); } } #define SET_CONFIG_PIN(config, pin_var, arg_id) \ if (arg_vals[arg_id].u_obj != mp_const_none) \ config.pin_var = pin_or_int(arg_vals[arg_id].u_obj) STATIC esp_err_t sdcard_ensure_card_init(sdcard_card_obj_t *self, bool force) { if (force || !(self->flags & SDCARD_CARD_FLAGS_CARD_INIT_DONE)) { DEBUG_printf(" Calling card init"); esp_err_t err = sdmmc_card_init(&(self->host), &(self->card)); if (err == ESP_OK) { self->flags |= SDCARD_CARD_FLAGS_CARD_INIT_DONE; } else { self->flags &= ~SDCARD_CARD_FLAGS_CARD_INIT_DONE; } DEBUG_printf(" Card init returned: %i", err); return err; } else { return ESP_OK; } } /******************************************************************************/ // MicroPython bindings // // Expose the SD card or MMC as an object with the block protocol. // Create a new SDCard object // The driver supports either the host SD/MMC controller (default) or SPI mode // In both cases there are two "slots". Slot 0 on the SD/MMC controller is // typically tied up with the flash interface in most ESP32 modules but in // theory supports 1, 4 or 8-bit transfers. Slot 1 supports only 1 and 4-bit // transfers. Only 1-bit is supported on the SPI interfaces. // card = SDCard(slot=1, width=None, present_pin=None, wp_pin=None) STATIC mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments enum { ARG_slot, ARG_width, ARG_cd, ARG_wp, ARG_miso, ARG_mosi, ARG_sck, ARG_cs, }; STATIC const mp_arg_t allowed_args[] = { { MP_QSTR_slot, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_cd, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_wp, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // These are only needed if using SPI mode { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)]; mp_map_t kw_args; DEBUG_printf("Making new SDCard:n"); DEBUG_printf(" Unpacking arguments"); mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); mp_arg_parse_all(n_args, args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals); DEBUG_printf(" slot=%d, width=%d, cd=%p, wp=%p", arg_vals[ARG_slot].u_int, arg_vals[ARG_width].u_int, arg_vals[ARG_cd].u_obj, arg_vals[ARG_wp].u_obj); DEBUG_printf(" miso=%p, mosi=%p, sck=%p, cs=%p", arg_vals[ARG_miso].u_obj, arg_vals[ARG_mosi].u_obj, arg_vals[ARG_sck].u_obj, arg_vals[ARG_cs].u_obj); int slot_num = arg_vals[ARG_slot].u_int; if (slot_num < 0 || slot_num > 3) { mp_raise_ValueError("Slot number must be between 0 and 3 inclusive"); } // Slots 0 and 1 are native SD/MMC, slots 2 and 3 are SPI bool is_spi = (slot_num >= 2); if (is_spi) { slot_num -= 2; } DEBUG_printf(" Setting up host configuration"); sdcard_card_obj_t *self = m_new_obj_with_finaliser(sdcard_card_obj_t); self->base.type = &machine_sdcard_type; self->flags = 0; // Note that these defaults are macros that expand to structure // constants so we can't directly assign them to fields. if (is_spi) { sdmmc_host_t _temp_host = SDSPI_HOST_DEFAULT(); self->host = _temp_host; } else { sdmmc_host_t _temp_host = SDMMC_HOST_DEFAULT(); self->host = _temp_host; } if (is_spi) { self->host.slot = slot_num ? HSPI_HOST : VSPI_HOST; } DEBUG_printf(" Calling host.init()"); check_esp_err(self->host.init()); self->flags |= SDCARD_CARD_FLAGS_HOST_INIT_DONE; if (is_spi) { // SPI interface STATIC const sdspi_slot_config_t slot_defaults[2] = { { .gpio_miso = GPIO_NUM_19, .gpio_mosi = GPIO_NUM_23, .gpio_sck = GPIO_NUM_18, .gpio_cs = GPIO_NUM_5, .gpio_cd = SDSPI_SLOT_NO_CD, .gpio_wp = SDSPI_SLOT_NO_WP, .dma_channel = 2 }, SDSPI_SLOT_CONFIG_DEFAULT() }; DEBUG_printf(" Setting up SPI slot configuration"); sdspi_slot_config_t slot_config = slot_defaults[slot_num]; SET_CONFIG_PIN(slot_config, gpio_cd, ARG_cd); SET_CONFIG_PIN(slot_config, gpio_wp, ARG_wp); SET_CONFIG_PIN(slot_config, gpio_miso, ARG_miso); SET_CONFIG_PIN(slot_config, gpio_mosi, ARG_mosi); SET_CONFIG_PIN(slot_config, gpio_sck, ARG_sck); SET_CONFIG_PIN(slot_config, gpio_cs, ARG_cs); DEBUG_printf(" Calling init_slot()"); check_esp_err(sdspi_host_init_slot(self->host.slot, &slot_config)); } else { // SD/MMC interface DEBUG_printf(" Setting up SDMMC slot configuration"); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); // Stronger external pull-ups are still needed but apparently // it is a good idea to set the internal pull-ups anyway. // slot_config.flags = SDMMC_SLOT_FLAG_INTERNAL_PULLUP; SET_CONFIG_PIN(slot_config, gpio_cd, ARG_cd); SET_CONFIG_PIN(slot_config, gpio_wp, ARG_wp); int width = arg_vals[ARG_width].u_int; if (width == 1 || width == 4 || (width == 8 && slot_num == 0)) { slot_config.width = width; } else { mp_raise_ValueError("Width must be 1 or 4 (or 8 on slot 0)"); } DEBUG_printf(" Calling init_slot()"); check_esp_err(sdmmc_host_init_slot(self->host.slot, &slot_config)); } DEBUG_printf(" Returning new card object: %p", self); return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t sd_deinit(mp_obj_t self_in) { sdcard_card_obj_t *self = self_in; DEBUG_printf("De-init host\n"); if (self->flags & SDCARD_CARD_FLAGS_HOST_INIT_DONE) { self->host.deinit(); self->flags &= ~SDCARD_CARD_FLAGS_HOST_INIT_DONE; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(sd_deinit_obj, sd_deinit); STATIC mp_obj_t sd_info(mp_obj_t self_in) { sdcard_card_obj_t *self = self_in; // We could potential return a great deal more SD card data but it // is not clear that it is worth the extra code space to do // so. For the most part people only care about the card size and // block size. check_esp_err(sdcard_ensure_card_init((sdcard_card_obj_t *) self, false)); uint32_t log_block_nbr = self->card.csd.capacity; uint32_t log_block_size = _SECTOR_SIZE(self); mp_obj_t tuple[2] = { mp_obj_new_int_from_ull((uint64_t)log_block_nbr * (uint64_t)log_block_size), mp_obj_new_int_from_uint(log_block_size), }; return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(sd_info_obj, sd_info); STATIC mp_obj_t machine_sdcard_readblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf) { sdcard_card_obj_t *self = self_in; mp_buffer_info_t bufinfo; esp_err_t err; err = sdcard_ensure_card_init((sdcard_card_obj_t *) self, false); if (err != ESP_OK) { return false; } mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); err = sdmmc_read_sectors(&(self->card), bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / _SECTOR_SIZE(self) ); return mp_obj_new_bool(err == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_readblocks_obj, machine_sdcard_readblocks); STATIC mp_obj_t machine_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf) { sdcard_card_obj_t *self = self_in; mp_buffer_info_t bufinfo; esp_err_t err; err = sdcard_ensure_card_init((sdcard_card_obj_t *) self, false); if (err != ESP_OK) { return false; } mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); err = sdmmc_write_sectors(&(self->card), bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / _SECTOR_SIZE(self) ); return mp_obj_new_bool(err == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_writeblocks_obj, machine_sdcard_writeblocks); STATIC mp_obj_t machine_sdcard_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { sdcard_card_obj_t *self = self_in; esp_err_t err = ESP_OK; mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: err = sdcard_ensure_card_init(self, false); return MP_OBJ_NEW_SMALL_INT((err == ESP_OK) ? 0 : -1); case MP_BLOCKDEV_IOCTL_DEINIT: // Ensure that future attempts to look at info re-read the card self->flags &= ~SDCARD_CARD_FLAGS_CARD_INIT_DONE; return MP_OBJ_NEW_SMALL_INT(0); // success case MP_BLOCKDEV_IOCTL_SYNC: // nothing to do return MP_OBJ_NEW_SMALL_INT(0); // success case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: err = sdcard_ensure_card_init(self, false); if (err != ESP_OK) return MP_OBJ_NEW_SMALL_INT(-1); return MP_OBJ_NEW_SMALL_INT(self->card.csd.capacity); case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: err = sdcard_ensure_card_init(self, false); if (err != ESP_OK) return MP_OBJ_NEW_SMALL_INT(-1); return MP_OBJ_NEW_SMALL_INT(_SECTOR_SIZE(self)); default: // unknown command return MP_OBJ_NEW_SMALL_INT(-1); // error } } STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_ioctl_obj, machine_sdcard_ioctl); STATIC const mp_rom_map_elem_t machine_sdcard_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&sd_info_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&sd_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sd_deinit_obj) }, // block device protocol { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&machine_sdcard_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&machine_sdcard_writeblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&machine_sdcard_ioctl_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_sdcard_locals_dict, machine_sdcard_locals_dict_table); const mp_obj_type_t machine_sdcard_type = { { &mp_type_type }, .name = MP_QSTR_SDCard, .make_new = machine_sdcard_make_new, .locals_dict = (mp_obj_dict_t*)&machine_sdcard_locals_dict, }; #endif // MICROPY_HW_ENABLE_SDCARD micropython-1.12/ports/esp32/machine_timer.c000066400000000000000000000210651357706137100211010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "driver/timer.h" #include "py/obj.h" #include "py/runtime.h" #include "modmachine.h" #include "mphalport.h" #define TIMER_INTR_SEL TIMER_INTR_LEVEL #define TIMER_DIVIDER 8 // TIMER_BASE_CLK is normally 80MHz. TIMER_DIVIDER ought to divide this exactly #define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) #define TIMER_FLAGS 0 typedef struct _machine_timer_obj_t { mp_obj_base_t base; mp_uint_t group; mp_uint_t index; mp_uint_t repeat; // ESP32 timers are 64-bit uint64_t period; mp_obj_t callback; intr_handle_t handle; struct _machine_timer_obj_t *next; } machine_timer_obj_t; const mp_obj_type_t machine_timer_type; STATIC void machine_timer_disable(machine_timer_obj_t *self); STATIC esp_err_t check_esp_err(esp_err_t code) { if (code) { mp_raise_OSError(code); } return code; } void machine_timer_deinit_all(void) { // Disable, deallocate and remove all timers from list machine_timer_obj_t **t = &MP_STATE_PORT(machine_timer_obj_head); while (*t != NULL) { machine_timer_disable(*t); machine_timer_obj_t *next = (*t)->next; m_del_obj(machine_timer_obj_t, *t); *t = next; } } STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_timer_obj_t *self = self_in; timer_config_t config; mp_printf(print, "Timer(%p; ", self); timer_get_config(self->group, self->index, &config); mp_printf(print, "alarm_en=%d, ", config.alarm_en); mp_printf(print, "auto_reload=%d, ", config.auto_reload); mp_printf(print, "counter_en=%d)", config.counter_en); } STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_uint_t group = (mp_obj_get_int(args[0]) >> 1) & 1; mp_uint_t index = mp_obj_get_int(args[0]) & 1; // Check whether the timer is already initialized, if so return it for (machine_timer_obj_t *t = MP_STATE_PORT(machine_timer_obj_head); t; t = t->next) { if (t->group == group && t->index == index) { return t; } } machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); self->base.type = &machine_timer_type; self->group = group; self->index = index; // Add the timer to the linked-list of timers self->next = MP_STATE_PORT(machine_timer_obj_head); MP_STATE_PORT(machine_timer_obj_head) = self; return self; } STATIC void machine_timer_disable(machine_timer_obj_t *self) { if (self->handle) { timer_pause(self->group, self->index); esp_intr_free(self->handle); self->handle = NULL; } // We let the disabled timer stay in the list, as it might be // referenced elsewhere } STATIC void machine_timer_isr(void *self_in) { machine_timer_obj_t *self = self_in; timg_dev_t *device = self->group ? &(TIMERG1) : &(TIMERG0); device->hw_timer[self->index].update = 1; if (self->index) { device->int_clr_timers.t1 = 1; } else { device->int_clr_timers.t0 = 1; } device->hw_timer[self->index].config.alarm_en = self->repeat; mp_sched_schedule(self->callback, self); mp_hal_wake_main_task_from_isr(); } STATIC void machine_timer_enable(machine_timer_obj_t *self) { timer_config_t config; config.alarm_en = TIMER_ALARM_EN; config.auto_reload = self->repeat; config.counter_dir = TIMER_COUNT_UP; config.divider = TIMER_DIVIDER; config.intr_type = TIMER_INTR_LEVEL; config.counter_en = TIMER_PAUSE; check_esp_err(timer_init(self->group, self->index, &config)); check_esp_err(timer_set_counter_value(self->group, self->index, 0x00000000)); check_esp_err(timer_set_alarm_value(self->group, self->index, self->period)); check_esp_err(timer_enable_intr(self->group, self->index)); check_esp_err(timer_isr_register(self->group, self->index, machine_timer_isr, (void*)self, TIMER_FLAGS, &self->handle)); check_esp_err(timer_start(self->group, self->index)); } STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, #if MICROPY_PY_BUILTINS_FLOAT { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, #else { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, #endif }; machine_timer_disable(self); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); #if MICROPY_PY_BUILTINS_FLOAT if (args[ARG_freq].u_obj != mp_const_none) { self->period = (uint64_t)(TIMER_SCALE / mp_obj_get_float(args[ARG_freq].u_obj)); } #else if (args[ARG_freq].u_int != 0xffffffff) { self->period = TIMER_SCALE / ((uint64_t)args[ARG_freq].u_int); } #endif else { self->period = (((uint64_t)args[ARG_period].u_int) * TIMER_SCALE) / args[ARG_tick_hz].u_int; } self->repeat = args[ARG_mode].u_int; self->callback = args[ARG_callback].u_obj; self->handle = NULL; machine_timer_enable(self); return mp_const_none; } STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) { machine_timer_disable(self_in); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); STATIC mp_obj_t machine_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return machine_timer_init_helper(args[0], n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init); STATIC mp_obj_t machine_timer_value(mp_obj_t self_in) { machine_timer_obj_t *self = self_in; double result; timer_get_counter_time_sec(self->group, self->index, &result); return MP_OBJ_NEW_SMALL_INT((mp_uint_t)(result * 1000)); // value in ms } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_value_obj, machine_timer_value); STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_timer_value_obj) }, { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(false) }, { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(true) }, }; STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); const mp_obj_type_t machine_timer_type = { { &mp_type_type }, .name = MP_QSTR_Timer, .print = machine_timer_print, .make_new = machine_timer_make_new, .locals_dict = (mp_obj_t)&machine_timer_locals_dict, }; micropython-1.12/ports/esp32/machine_touchpad.c000066400000000000000000000077721357706137100216010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Nick Moore * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "esp_log.h" #include "driver/gpio.h" #include "driver/touch_pad.h" #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" typedef struct _mtp_obj_t { mp_obj_base_t base; gpio_num_t gpio_id; touch_pad_t touchpad_id; } mtp_obj_t; STATIC const mtp_obj_t touchpad_obj[] = { {{&machine_touchpad_type}, GPIO_NUM_4, TOUCH_PAD_NUM0}, {{&machine_touchpad_type}, GPIO_NUM_0, TOUCH_PAD_NUM1}, {{&machine_touchpad_type}, GPIO_NUM_2, TOUCH_PAD_NUM2}, {{&machine_touchpad_type}, GPIO_NUM_15, TOUCH_PAD_NUM3}, {{&machine_touchpad_type}, GPIO_NUM_13, TOUCH_PAD_NUM4}, {{&machine_touchpad_type}, GPIO_NUM_12, TOUCH_PAD_NUM5}, {{&machine_touchpad_type}, GPIO_NUM_14, TOUCH_PAD_NUM6}, {{&machine_touchpad_type}, GPIO_NUM_27, TOUCH_PAD_NUM7}, {{&machine_touchpad_type}, GPIO_NUM_33, TOUCH_PAD_NUM8}, {{&machine_touchpad_type}, GPIO_NUM_32, TOUCH_PAD_NUM9}, }; STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, true); gpio_num_t pin_id = machine_pin_get_id(args[0]); const mtp_obj_t *self = NULL; for (int i = 0; i < MP_ARRAY_SIZE(touchpad_obj); i++) { if (pin_id == touchpad_obj[i].gpio_id) { self = &touchpad_obj[i]; break; } } if (!self) mp_raise_ValueError("invalid pin for touchpad"); static int initialized = 0; if (!initialized) { touch_pad_init(); touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); initialized = 1; } esp_err_t err = touch_pad_config(self->touchpad_id, 0); if (err == ESP_OK) return MP_OBJ_FROM_PTR(self); mp_raise_ValueError("Touch pad error"); } STATIC mp_obj_t mtp_config(mp_obj_t self_in, mp_obj_t value_in) { mtp_obj_t *self = self_in; uint16_t value = mp_obj_get_int(value_in); esp_err_t err = touch_pad_config(self->touchpad_id, value); if (err == ESP_OK) return mp_const_none; mp_raise_ValueError("Touch pad error"); } MP_DEFINE_CONST_FUN_OBJ_2(mtp_config_obj, mtp_config); STATIC mp_obj_t mtp_read(mp_obj_t self_in) { mtp_obj_t *self = self_in; uint16_t value; esp_err_t err = touch_pad_read(self->touchpad_id, &value); if (err == ESP_OK) return MP_OBJ_NEW_SMALL_INT(value); mp_raise_ValueError("Touch pad error"); } MP_DEFINE_CONST_FUN_OBJ_1(mtp_read_obj, mtp_read); STATIC const mp_rom_map_elem_t mtp_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&mtp_config_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mtp_read_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mtp_locals_dict, mtp_locals_dict_table); const mp_obj_type_t machine_touchpad_type = { { &mp_type_type }, .name = MP_QSTR_TouchPad, .make_new = mtp_make_new, .locals_dict = (mp_obj_t)&mtp_locals_dict, }; micropython-1.12/ports/esp32/machine_uart.c000066400000000000000000000405371357706137100207410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "driver/uart.h" #include "freertos/FreeRTOS.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "modmachine.h" typedef struct _machine_uart_obj_t { mp_obj_base_t base; uart_port_t uart_num; uint8_t bits; uint8_t parity; uint8_t stop; int8_t tx; int8_t rx; int8_t rts; int8_t cts; uint16_t txbuf; uint16_t rxbuf; uint16_t timeout; // timeout waiting for first char (in ms) uint16_t timeout_char; // timeout waiting between chars (in ms) uint32_t invert; // lines to invert } machine_uart_obj_t; STATIC const char *_parity_name[] = {"None", "1", "0"}; /******************************************************************************/ // MicroPython bindings for UART STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); uint32_t baudrate; uart_get_baudrate(self->uart_num, &baudrate); mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, rts=%d, cts=%d, txbuf=%u, rxbuf=%u, timeout=%u, timeout_char=%u", self->uart_num, baudrate, self->bits, _parity_name[self->parity], self->stop, self->tx, self->rx, self->rts, self->cts, self->txbuf, self->rxbuf, self->timeout, self->timeout_char); if (self->invert) { mp_printf(print, ", invert="); uint32_t invert_mask = self->invert; if (invert_mask & UART_INVERSE_TXD) { mp_printf(print, "INV_TX"); invert_mask &= ~UART_INVERSE_TXD; if (invert_mask) { mp_printf(print, "|"); } } if (invert_mask & UART_INVERSE_RXD) { mp_printf(print, "INV_RX"); invert_mask &= ~UART_INVERSE_RXD; if (invert_mask) { mp_printf(print, "|"); } } if (invert_mask & UART_INVERSE_RTS) { mp_printf(print, "INV_RTS"); invert_mask &= ~UART_INVERSE_RTS; if (invert_mask) { mp_printf(print, "|"); } } if (invert_mask & UART_INVERSE_CTS) { mp_printf(print, "INV_CTS"); } } mp_printf(print, ")"); } STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_txbuf, ARG_rxbuf, ARG_timeout, ARG_timeout_char, ARG_invert }; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_stop, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} }, { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} }, { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} }, { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} }, { MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // wait for all data to be transmitted before changing settings uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000)); if (args[ARG_txbuf].u_int >= 0 || args[ARG_rxbuf].u_int >= 0) { // must reinitialise driver to change the tx/rx buffer size if (args[ARG_txbuf].u_int >= 0) { self->txbuf = args[ARG_txbuf].u_int; } if (args[ARG_rxbuf].u_int >= 0) { self->rxbuf = args[ARG_rxbuf].u_int; } uart_config_t uartcfg = { .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .rx_flow_ctrl_thresh = 0 }; uint32_t baudrate; uart_get_baudrate(self->uart_num, &baudrate); uartcfg.baud_rate = baudrate; uart_get_word_length(self->uart_num, &uartcfg.data_bits); uart_get_parity(self->uart_num, &uartcfg.parity); uart_get_stop_bits(self->uart_num, &uartcfg.stop_bits); uart_driver_delete(self->uart_num); uart_param_config(self->uart_num, &uartcfg); uart_driver_install(self->uart_num, self->rxbuf, self->txbuf, 0, NULL, 0); } // set baudrate uint32_t baudrate = 115200; if (args[ARG_baudrate].u_int > 0) { uart_set_baudrate(self->uart_num, args[ARG_baudrate].u_int); uart_get_baudrate(self->uart_num, &baudrate); } uart_set_pin(self->uart_num, args[ARG_tx].u_int, args[ARG_rx].u_int, args[ARG_rts].u_int, args[ARG_cts].u_int); if (args[ARG_tx].u_int != UART_PIN_NO_CHANGE) { self->tx = args[ARG_tx].u_int; } if (args[ARG_rx].u_int != UART_PIN_NO_CHANGE) { self->rx = args[ARG_rx].u_int; } if (args[ARG_rts].u_int != UART_PIN_NO_CHANGE) { self->rts = args[ARG_rts].u_int; } if (args[ARG_cts].u_int != UART_PIN_NO_CHANGE) { self->cts = args[ARG_cts].u_int; } // set data bits switch (args[ARG_bits].u_int) { case 0: break; case 5: uart_set_word_length(self->uart_num, UART_DATA_5_BITS); self->bits = 5; break; case 6: uart_set_word_length(self->uart_num, UART_DATA_6_BITS); self->bits = 6; break; case 7: uart_set_word_length(self->uart_num, UART_DATA_7_BITS); self->bits = 7; break; case 8: uart_set_word_length(self->uart_num, UART_DATA_8_BITS); self->bits = 8; break; default: mp_raise_ValueError("invalid data bits"); break; } // set parity if (args[ARG_parity].u_obj != MP_OBJ_NULL) { if (args[ARG_parity].u_obj == mp_const_none) { uart_set_parity(self->uart_num, UART_PARITY_DISABLE); self->parity = 0; } else { mp_int_t parity = mp_obj_get_int(args[ARG_parity].u_obj); if (parity & 1) { uart_set_parity(self->uart_num, UART_PARITY_ODD); self->parity = 1; } else { uart_set_parity(self->uart_num, UART_PARITY_EVEN); self->parity = 2; } } } // set stop bits switch (args[ARG_stop].u_int) { // FIXME: ESP32 also supports 1.5 stop bits case 0: break; case 1: uart_set_stop_bits(self->uart_num, UART_STOP_BITS_1); self->stop = 1; break; case 2: uart_set_stop_bits(self->uart_num, UART_STOP_BITS_2); self->stop = 2; break; default: mp_raise_ValueError("invalid stop bits"); break; } // set timeout self->timeout = args[ARG_timeout].u_int; // set timeout_char // make sure it is at least as long as a whole character (13 bits to be safe) self->timeout_char = args[ARG_timeout_char].u_int; uint32_t min_timeout_char = 13000 / baudrate + 1; if (self->timeout_char < min_timeout_char) { self->timeout_char = min_timeout_char; } // set line inversion if (args[ARG_invert].u_int & ~UART_LINE_INV_MASK) { mp_raise_ValueError("invalid inversion mask"); } self->invert = args[ARG_invert].u_int; uart_set_line_inverse(self->uart_num, self->invert); } STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get uart id mp_int_t uart_num = mp_obj_get_int(args[0]); if (uart_num < 0 || uart_num >= UART_NUM_MAX) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_num)); } // Attempts to use UART0 from Python has resulted in all sorts of fun errors. // FIXME: UART0 is disabled for now. if (uart_num == UART_NUM_0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) is disabled (dedicated to REPL)", uart_num)); } // Defaults uart_config_t uartcfg = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .rx_flow_ctrl_thresh = 0 }; // create instance machine_uart_obj_t *self = m_new_obj(machine_uart_obj_t); self->base.type = &machine_uart_type; self->uart_num = uart_num; self->bits = 8; self->parity = 0; self->stop = 1; self->rts = UART_PIN_NO_CHANGE; self->cts = UART_PIN_NO_CHANGE; self->txbuf = 256; self->rxbuf = 256; // IDF minimum self->timeout = 0; self->timeout_char = 0; switch (uart_num) { case UART_NUM_0: self->rx = UART_PIN_NO_CHANGE; // GPIO 3 self->tx = UART_PIN_NO_CHANGE; // GPIO 1 break; case UART_NUM_1: self->rx = 9; self->tx = 10; break; case UART_NUM_2: self->rx = 16; self->tx = 17; break; } // Remove any existing configuration uart_driver_delete(self->uart_num); // init the peripheral // Setup uart_param_config(self->uart_num, &uartcfg); uart_driver_install(uart_num, self->rxbuf, self->txbuf, 0, NULL, 0); mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args); // Make sure pins are connected. uart_set_pin(self->uart_num, self->tx, self->rx, self->rts, self->cts); return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); uart_driver_delete(self->uart_num); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); size_t rxbufsize; uart_get_buffered_data_len(self->uart_num, &rxbufsize); return MP_OBJ_NEW_SMALL_INT(rxbufsize); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); // Save settings uart_word_length_t word_length; uart_parity_t parity; uart_get_word_length(self->uart_num, &word_length); uart_get_parity(self->uart_num, &parity); // Synthesise the break condition by either a longer word or using even parity uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000)); if (word_length != UART_DATA_8_BITS) { uart_set_word_length(self->uart_num, UART_DATA_8_BITS); } else if (parity == UART_PARITY_DISABLE) { uart_set_parity(self->uart_num, UART_PARITY_EVEN); } else { // Cannot synthesise break mp_raise_OSError(MP_EPERM); } char buf[1] = {0}; uart_write_bytes(self->uart_num, buf, 1); uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000)); // Restore original settings uart_set_word_length(self->uart_num, word_length); uart_set_parity(self->uart_num, parity); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak); STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, { MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INVERSE_TXD) }, { MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERSE_RXD) }, { MP_ROM_QSTR(MP_QSTR_INV_RTS), MP_ROM_INT(UART_INVERSE_RTS) }, { MP_ROM_QSTR(MP_QSTR_INV_CTS), MP_ROM_INT(UART_INVERSE_CTS) }, }; STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); // make sure we want at least 1 char if (size == 0) { return 0; } TickType_t time_to_wait; if (self->timeout == 0) { time_to_wait = 0; } else { time_to_wait = pdMS_TO_TICKS(self->timeout); } int bytes_read = uart_read_bytes(self->uart_num, buf_in, size, time_to_wait); if (bytes_read <= 0) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } return bytes_read; } STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); int bytes_written = uart_write_bytes(self->uart_num, buf_in, size); if (bytes_written < 0) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } // return number of bytes written return bytes_written; } STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { machine_uart_obj_t *self = self_in; mp_uint_t ret; if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; size_t rxbufsize; uart_get_buffered_data_len(self->uart_num, &rxbufsize); if ((flags & MP_STREAM_POLL_RD) && rxbufsize > 0) { ret |= MP_STREAM_POLL_RD; } if ((flags & MP_STREAM_POLL_WR) && 1) { // FIXME: uart_tx_any_room(self->uart_num) ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; } return ret; } STATIC const mp_stream_p_t uart_stream_p = { .read = machine_uart_read, .write = machine_uart_write, .ioctl = machine_uart_ioctl, .is_text = false, }; const mp_obj_type_t machine_uart_type = { { &mp_type_type }, .name = MP_QSTR_UART, .print = machine_uart_print, .make_new = machine_uart_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &uart_stream_p, .locals_dict = (mp_obj_dict_t*)&machine_uart_locals_dict, }; micropython-1.12/ports/esp32/machine_wdt.c000066400000000000000000000060741357706137100205620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * Copyright (c) 2017 Eric Poulsen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/nlr.h" #include "py/obj.h" #include "py/runtime.h" #include "esp_task_wdt.h" const mp_obj_type_t machine_wdt_type; typedef struct _machine_wdt_obj_t { mp_obj_base_t base; } machine_wdt_obj_t; STATIC machine_wdt_obj_t wdt_default = {{&machine_wdt_type}}; STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} } }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_id].u_int != 0) { mp_raise_ValueError(NULL); } // Convert milliseconds to seconds (esp_task_wdt_init needs seconds) args[ARG_timeout].u_int /= 1000; if (args[ARG_timeout].u_int <= 0) { mp_raise_ValueError("WDT timeout too short"); } mp_int_t rs_code = esp_task_wdt_init(args[ARG_timeout].u_int, true); if (rs_code != ESP_OK) { mp_raise_OSError(rs_code); } esp_task_wdt_add(NULL); return &wdt_default; } STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) { (void)self_in; esp_task_wdt_reset(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed); STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); const mp_obj_type_t machine_wdt_type = { { &mp_type_type }, .name = MP_QSTR_WDT, .make_new = machine_wdt_make_new, .locals_dict = (mp_obj_t)&machine_wdt_locals_dict, }; micropython-1.12/ports/esp32/main.c000066400000000000000000000134401357706137100172170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "nvs_flash.h" #include "esp_task.h" #include "soc/cpu.h" #include "esp_log.h" #if MICROPY_ESP_IDF_4 #include "esp32/spiram.h" #else #include "esp_spiram.h" #endif #include "py/stackctrl.h" #include "py/nlr.h" #include "py/compile.h" #include "py/runtime.h" #include "py/persistentcode.h" #include "py/repl.h" #include "py/gc.h" #include "py/mphal.h" #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" #include "uart.h" #include "modmachine.h" #include "modnetwork.h" #include "mpthreadport.h" // MicroPython runs as a task under FreeRTOS #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) #define MP_TASK_STACK_SIZE (16 * 1024) #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) int vprintf_null(const char *format, va_list ap) { // do nothing: this is used as a log target during raw repl mode return 0; } void mp_task(void *pvParameter) { volatile uint32_t sp = (uint32_t)get_sp(); #if MICROPY_PY_THREAD mp_thread_init(pxTaskGetStackStart(NULL), MP_TASK_STACK_LEN); #endif uart_init(); // TODO: CONFIG_SPIRAM_SUPPORT is for 3.3 compatibility, remove after move to 4.0. #if CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_SPIRAM_SUPPORT // Try to use the entire external SPIRAM directly for the heap size_t mp_task_heap_size; void *mp_task_heap = (void*)0x3f800000; switch (esp_spiram_get_chip_size()) { case ESP_SPIRAM_SIZE_16MBITS: mp_task_heap_size = 2 * 1024 * 1024; break; case ESP_SPIRAM_SIZE_32MBITS: case ESP_SPIRAM_SIZE_64MBITS: mp_task_heap_size = 4 * 1024 * 1024; break; default: // No SPIRAM, fallback to normal allocation mp_task_heap_size = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); mp_task_heap = malloc(mp_task_heap_size); break; } #else // Allocate the uPy heap using malloc and get the largest available region size_t mp_task_heap_size = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); void *mp_task_heap = malloc(mp_task_heap_size); #endif soft_reset: // initialise the stack pointer for the main thread mp_stack_set_top((void *)sp); mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024); gc_init(mp_task_heap, mp_task_heap + mp_task_heap_size); mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); mp_obj_list_init(mp_sys_argv, 0); readline_init0(); // initialise peripherals machine_pins_init(); // run boot-up scripts pyexec_frozen_module("_boot.py"); pyexec_file_if_exists("boot.py"); if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { pyexec_file_if_exists("main.py"); } for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { vprintf_like_t vprintf_log = esp_log_set_vprintf(vprintf_null); if (pyexec_raw_repl() != 0) { break; } esp_log_set_vprintf(vprintf_log); } else { if (pyexec_friendly_repl() != 0) { break; } } } machine_timer_deinit_all(); #if MICROPY_PY_THREAD mp_thread_deinit(); #endif gc_sweep_all(); mp_hal_stdout_tx_str("MPY: soft reboot\r\n"); // deinitialise peripherals machine_pins_deinit(); usocket_events_deinit(); mp_deinit(); fflush(stdout); goto soft_reset; } void app_main(void) { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { nvs_flash_erase(); nvs_flash_init(); } xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_main_task_handle, MP_TASK_COREID); } void nlr_jump_fail(void *val) { printf("NLR jump failed, val=%p\n", val); esp_restart(); } // modussl_mbedtls uses this function but it's not enabled in ESP IDF void mbedtls_debug_set_threshold(int threshold) { (void)threshold; } void *esp_native_code_commit(void *buf, size_t len, void *reloc) { len = (len + 3) & ~3; uint32_t *p = heap_caps_malloc(len, MALLOC_CAP_EXEC); if (p == NULL) { m_malloc_fail(len); } if (reloc) { mp_native_relocate(reloc, buf, (uintptr_t)p); } memcpy(p, buf, len); return p; } micropython-1.12/ports/esp32/makeimg.py000066400000000000000000000013611357706137100201120ustar00rootroot00000000000000import sys OFFSET_BOOTLOADER = 0x1000 OFFSET_PARTITIONS = 0x8000 OFFSET_APPLICATION = 0x10000 files_in = [ ('bootloader', OFFSET_BOOTLOADER, sys.argv[1]), ('partitions', OFFSET_PARTITIONS, sys.argv[2]), ('application', OFFSET_APPLICATION, sys.argv[3]), ] file_out = sys.argv[4] cur_offset = OFFSET_BOOTLOADER with open(file_out, 'wb') as fout: for name, offset, file_in in files_in: assert offset >= cur_offset fout.write(b'\xff' * (offset - cur_offset)) cur_offset = offset with open(file_in, 'rb') as fin: data = fin.read() fout.write(data) cur_offset += len(data) print('%-12s% 8d' % (name, len(data))) print('%-12s% 8d' % ('total', cur_offset)) micropython-1.12/ports/esp32/memory.h000066400000000000000000000001141357706137100176020ustar00rootroot00000000000000// this is needed for extmod/crypto-algorithms/sha256.c #include micropython-1.12/ports/esp32/modesp.c000066400000000000000000000143011357706137100175570ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2015 Paul Sokolovsky * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #if !MICROPY_ESP_IDF_4 #include "rom/gpio.h" #endif #include "esp_log.h" #include "esp_spi_flash.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "drivers/dht/dht.h" #include "modesp.h" STATIC mp_obj_t esp_osdebug(size_t n_args, const mp_obj_t *args) { esp_log_level_t level = LOG_LOCAL_LEVEL; if (n_args == 2) { level = mp_obj_get_int(args[1]); } if (args[0] == mp_const_none) { // Disable logging esp_log_level_set("*", ESP_LOG_ERROR); } else { // Enable logging at the given level // TODO args[0] should set the UART to which debug is sent esp_log_level_set("*", level); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_osdebug_obj, 1, 2, esp_osdebug); STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t buf_in) { mp_int_t offset = mp_obj_get_int(offset_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); esp_err_t res = spi_flash_read(offset, bufinfo.buf, bufinfo.len); if (res != ESP_OK) { mp_raise_OSError(MP_EIO); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read); STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, mp_obj_t buf_in) { mp_int_t offset = mp_obj_get_int(offset_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); esp_err_t res = spi_flash_write(offset, bufinfo.buf, bufinfo.len); if (res != ESP_OK) { mp_raise_OSError(MP_EIO); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write); STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) { mp_int_t sector = mp_obj_get_int(sector_in); esp_err_t res = spi_flash_erase_sector(sector); if (res != ESP_OK) { mp_raise_OSError(MP_EIO); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase); STATIC mp_obj_t esp_flash_size(void) { return mp_obj_new_int_from_uint(spi_flash_get_chip_size()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size); STATIC mp_obj_t esp_flash_user_start(void) { return MP_OBJ_NEW_SMALL_INT(0x200000); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start); STATIC mp_obj_t esp_gpio_matrix_in(mp_obj_t pin, mp_obj_t sig, mp_obj_t inv) { gpio_matrix_in(mp_obj_get_int(pin), mp_obj_get_int(sig), mp_obj_get_int(inv)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_gpio_matrix_in_obj, esp_gpio_matrix_in); STATIC mp_obj_t esp_gpio_matrix_out(size_t n_args, const mp_obj_t *args) { (void)n_args; gpio_matrix_out(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2]), mp_obj_get_int(args[3])); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_gpio_matrix_out_obj, 4, 4, esp_gpio_matrix_out); STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t timing) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); esp_neopixel_write(mp_hal_get_pin_obj(pin), (uint8_t*)bufinfo.buf, bufinfo.len, mp_obj_get_int(timing)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_); STATIC const mp_rom_map_elem_t esp_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp) }, { MP_ROM_QSTR(MP_QSTR_osdebug), MP_ROM_PTR(&esp_osdebug_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_read), MP_ROM_PTR(&esp_flash_read_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_write), MP_ROM_PTR(&esp_flash_write_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) }, { MP_ROM_QSTR(MP_QSTR_gpio_matrix_in), MP_ROM_PTR(&esp_gpio_matrix_in_obj) }, { MP_ROM_QSTR(MP_QSTR_gpio_matrix_out), MP_ROM_PTR(&esp_gpio_matrix_out_obj) }, { MP_ROM_QSTR(MP_QSTR_neopixel_write), MP_ROM_PTR(&esp_neopixel_write_obj) }, { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, // Constants for second arg of osdebug() { MP_ROM_QSTR(MP_QSTR_LOG_NONE), MP_ROM_INT((mp_uint_t)ESP_LOG_NONE)}, { MP_ROM_QSTR(MP_QSTR_LOG_ERROR), MP_ROM_INT((mp_uint_t)ESP_LOG_ERROR)}, { MP_ROM_QSTR(MP_QSTR_LOG_WARNING), MP_ROM_INT((mp_uint_t)ESP_LOG_WARN)}, { MP_ROM_QSTR(MP_QSTR_LOG_INFO), MP_ROM_INT((mp_uint_t)ESP_LOG_INFO)}, { MP_ROM_QSTR(MP_QSTR_LOG_DEBUG), MP_ROM_INT((mp_uint_t)ESP_LOG_DEBUG)}, { MP_ROM_QSTR(MP_QSTR_LOG_VERBOSE), MP_ROM_INT((mp_uint_t)ESP_LOG_VERBOSE)}, }; STATIC MP_DEFINE_CONST_DICT(esp_module_globals, esp_module_globals_table); const mp_obj_module_t esp_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&esp_module_globals, }; micropython-1.12/ports/esp32/modesp.h000066400000000000000000000001321357706137100175610ustar00rootroot00000000000000void esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t timing); micropython-1.12/ports/esp32/modesp32.c000066400000000000000000000151731357706137100177340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 "Eric Poulsen" * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" #include "driver/gpio.h" #include "driver/adc.h" #include "py/nlr.h" #include "py/obj.h" #include "py/runtime.h" #include "py/mphal.h" #include "timeutils.h" #include "modmachine.h" #include "machine_rtc.h" #include "modesp32.h" STATIC mp_obj_t esp32_wake_on_touch(const mp_obj_t wake) { if (machine_rtc_config.ext0_pin != -1) { mp_raise_ValueError("no resources"); } //mp_raise_msg(&mp_type_RuntimeError, "touchpad wakeup not available for this version of ESP-IDF"); machine_rtc_config.wake_on_touch = mp_obj_is_true(wake); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_wake_on_touch_obj, esp32_wake_on_touch); STATIC mp_obj_t esp32_wake_on_ext0(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { if (machine_rtc_config.wake_on_touch) { mp_raise_ValueError("no resources"); } enum {ARG_pin, ARG_level}; const mp_arg_t allowed_args[] = { { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = mp_obj_new_int(machine_rtc_config.ext0_pin)} }, { MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext0_level} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_pin].u_obj == mp_const_none) { machine_rtc_config.ext0_pin = -1; // "None" } else { gpio_num_t pin_id = machine_pin_get_id(args[ARG_pin].u_obj); if (pin_id != machine_rtc_config.ext0_pin) { if (!RTC_IS_VALID_EXT_PIN(pin_id)) { mp_raise_msg(&mp_type_ValueError, "invalid pin"); } machine_rtc_config.ext0_pin = pin_id; } } machine_rtc_config.ext0_level = args[ARG_level].u_bool; machine_rtc_config.ext0_wake_types = MACHINE_WAKE_SLEEP | MACHINE_WAKE_DEEPSLEEP; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_ext0_obj, 0, esp32_wake_on_ext0); STATIC mp_obj_t esp32_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_pins, ARG_level}; const mp_arg_t allowed_args[] = { { MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext1_level} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); uint64_t ext1_pins = machine_rtc_config.ext1_pins; // Check that all pins are allowed if (args[ARG_pins].u_obj != mp_const_none) { mp_uint_t len = 0; mp_obj_t *elem; mp_obj_get_array(args[ARG_pins].u_obj, &len, &elem); ext1_pins = 0; for (int i = 0; i < len; i++) { gpio_num_t pin_id = machine_pin_get_id(elem[i]); if (!RTC_IS_VALID_EXT_PIN(pin_id)) { mp_raise_msg(&mp_type_ValueError, "invalid pin"); break; } ext1_pins |= (1ll << pin_id); } } machine_rtc_config.ext1_level = args[ARG_level].u_bool; machine_rtc_config.ext1_pins = ext1_pins; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_ext1_obj, 0, esp32_wake_on_ext1); STATIC mp_obj_t esp32_raw_temperature(void) { SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 10, SENS_TSENS_CLK_DIV_S); CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP); CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT); SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE); SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP); ets_delay_us(100); SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT); ets_delay_us(5); int res = GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT, SENS_TSENS_OUT_S); return mp_obj_new_int(res); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp32_raw_temperature_obj, esp32_raw_temperature); STATIC mp_obj_t esp32_hall_sensor(void) { adc1_config_width(ADC_WIDTH_12Bit); return MP_OBJ_NEW_SMALL_INT(hall_sensor_read()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp32_hall_sensor_obj, esp32_hall_sensor); STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp32) }, { MP_ROM_QSTR(MP_QSTR_wake_on_touch), MP_ROM_PTR(&esp32_wake_on_touch_obj) }, { MP_ROM_QSTR(MP_QSTR_wake_on_ext0), MP_ROM_PTR(&esp32_wake_on_ext0_obj) }, { MP_ROM_QSTR(MP_QSTR_wake_on_ext1), MP_ROM_PTR(&esp32_wake_on_ext1_obj) }, { MP_ROM_QSTR(MP_QSTR_raw_temperature), MP_ROM_PTR(&esp32_raw_temperature_obj) }, { MP_ROM_QSTR(MP_QSTR_hall_sensor), MP_ROM_PTR(&esp32_hall_sensor_obj) }, { MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) }, { MP_ROM_QSTR(MP_QSTR_RMT), MP_ROM_PTR(&esp32_rmt_type) }, { MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) }, { MP_ROM_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_ROM_PTR(&mp_const_false_obj) }, { MP_ROM_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), MP_ROM_PTR(&mp_const_true_obj) }, }; STATIC MP_DEFINE_CONST_DICT(esp32_module_globals, esp32_module_globals_table); const mp_obj_module_t esp32_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&esp32_module_globals, }; micropython-1.12/ports/esp32/modesp32.h000066400000000000000000000014001357706137100177250ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_ESP32_MODESP32_H #define MICROPY_INCLUDED_ESP32_MODESP32_H #define RTC_VALID_EXT_PINS \ ( \ (1ll << 0) | \ (1ll << 2) | \ (1ll << 4) | \ (1ll << 12) | \ (1ll << 13) | \ (1ll << 14) | \ (1ll << 15) | \ (1ll << 25) | \ (1ll << 26) | \ (1ll << 27) | \ (1ll << 32) | \ (1ll << 33) | \ (1ll << 34) | \ (1ll << 35) | \ (1ll << 36) | \ (1ll << 37) | \ (1ll << 38) | \ (1ll << 39) \ ) #define RTC_LAST_EXT_PIN 39 #define RTC_IS_VALID_EXT_PIN(pin_id) ((1ll << (pin_id)) & RTC_VALID_EXT_PINS) extern const mp_obj_type_t esp32_partition_type; extern const mp_obj_type_t esp32_rmt_type; extern const mp_obj_type_t esp32_ulp_type; #endif // MICROPY_INCLUDED_ESP32_MODESP32_H micropython-1.12/ports/esp32/modmachine.c000066400000000000000000000250441357706137100204020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #if MICROPY_ESP_IDF_4 #include "esp32/rom/rtc.h" #include "esp32/clk.h" #include "esp_sleep.h" #else #include "rom/ets_sys.h" #include "rom/rtc.h" #include "esp_clk.h" #endif #include "esp_pm.h" #include "driver/touch_pad.h" #include "py/obj.h" #include "py/runtime.h" #include "extmod/machine_mem.h" #include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "extmod/machine_spi.h" #include "modmachine.h" #include "machine_rtc.h" #if MICROPY_PY_MACHINE typedef enum { MP_PWRON_RESET = 1, MP_HARD_RESET, MP_WDT_RESET, MP_DEEPSLEEP_RESET, MP_SOFT_RESET } reset_reason_t; STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // get return mp_obj_new_int(esp_clk_cpu_freq()); } else { // set mp_int_t freq = mp_obj_get_int(args[0]) / 1000000; if (freq != 20 && freq != 40 && freq != 80 && freq != 160 && freq != 240) { mp_raise_ValueError("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz"); } esp_pm_config_esp32_t pm; pm.max_freq_mhz = freq; pm.min_freq_mhz = freq; pm.light_sleep_enable = false; esp_err_t ret = esp_pm_configure(&pm); if (ret != ESP_OK) { mp_raise_ValueError(NULL); } while (esp_clk_cpu_freq() != freq * 1000000) { vTaskDelay(1); } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq); STATIC mp_obj_t machine_sleep_helper(wake_type_t wake_type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_sleep_ms}; const mp_arg_t allowed_args[] = { { MP_QSTR_sleep_ms, MP_ARG_INT, { .u_int = 0 } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_int_t expiry = args[ARG_sleep_ms].u_int; if (expiry != 0) { esp_sleep_enable_timer_wakeup(((uint64_t)expiry) * 1000); } if (machine_rtc_config.ext0_pin != -1 && (machine_rtc_config.ext0_wake_types & wake_type)) { esp_sleep_enable_ext0_wakeup(machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0); } if (machine_rtc_config.ext1_pins != 0) { esp_sleep_enable_ext1_wakeup( machine_rtc_config.ext1_pins, machine_rtc_config.ext1_level ? ESP_EXT1_WAKEUP_ANY_HIGH : ESP_EXT1_WAKEUP_ALL_LOW); } if (machine_rtc_config.wake_on_touch) { if (esp_sleep_enable_touchpad_wakeup() != ESP_OK) { mp_raise_msg(&mp_type_RuntimeError, "esp_sleep_enable_touchpad_wakeup() failed"); } } switch(wake_type) { case MACHINE_WAKE_SLEEP: esp_light_sleep_start(); break; case MACHINE_WAKE_DEEPSLEEP: esp_deep_sleep_start(); break; } return mp_const_none; } STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { return machine_sleep_helper(MACHINE_WAKE_SLEEP, n_args, pos_args, kw_args); }; STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_lightsleep_obj, 0, machine_lightsleep); STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { return machine_sleep_helper(MACHINE_WAKE_DEEPSLEEP, n_args, pos_args, kw_args); }; STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_deepsleep_obj, 0, machine_deepsleep); STATIC mp_obj_t machine_reset_cause(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { switch(rtc_get_reset_reason(0)) { case POWERON_RESET: return MP_OBJ_NEW_SMALL_INT(MP_PWRON_RESET); break; case SW_RESET: case SW_CPU_RESET: return MP_OBJ_NEW_SMALL_INT(MP_SOFT_RESET); break; case OWDT_RESET: case TG0WDT_SYS_RESET: case TG1WDT_SYS_RESET: case RTCWDT_SYS_RESET: case RTCWDT_BROWN_OUT_RESET: case RTCWDT_CPU_RESET: case RTCWDT_RTC_RESET: case TGWDT_CPU_RESET: return MP_OBJ_NEW_SMALL_INT(MP_WDT_RESET); break; case DEEPSLEEP_RESET: return MP_OBJ_NEW_SMALL_INT(MP_DEEPSLEEP_RESET); break; case EXT_CPU_RESET: return MP_OBJ_NEW_SMALL_INT(MP_HARD_RESET); break; case NO_MEAN: case SDIO_RESET: case INTRUSION_RESET: default: return MP_OBJ_NEW_SMALL_INT(0); break; } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_reset_cause_obj, 0, machine_reset_cause); STATIC mp_obj_t machine_wake_reason(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { return MP_OBJ_NEW_SMALL_INT(esp_sleep_get_wakeup_cause()); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_wake_reason_obj, 0, machine_wake_reason); STATIC mp_obj_t machine_reset(void) { esp_restart(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); STATIC mp_obj_t machine_unique_id(void) { uint8_t chipid[6]; esp_efuse_mac_get_default(chipid); return mp_obj_new_bytes(chipid, 6); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id); STATIC mp_obj_t machine_idle(void) { taskYIELD(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle); STATIC mp_obj_t machine_disable_irq(void) { uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION(); return mp_obj_new_int(state); } MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq); STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) { uint32_t state = mp_obj_get_int(state_in); MICROPY_END_ATOMIC_SECTION(state); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq); STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, #if MICROPY_HW_ENABLE_SDCARD { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&machine_sdcard_type) }, #endif // wake abilities { MP_ROM_QSTR(MP_QSTR_SLEEP), MP_ROM_INT(MACHINE_WAKE_SLEEP) }, { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, { MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, // Reset reasons { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(MP_HARD_RESET) }, { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(MP_PWRON_RESET) }, { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(MP_WDT_RESET) }, { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(MP_DEEPSLEEP_RESET) }, { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(MP_SOFT_RESET) }, // Wake reasons { MP_ROM_QSTR(MP_QSTR_wake_reason), MP_ROM_PTR(&machine_wake_reason_obj) }, { MP_ROM_QSTR(MP_QSTR_PIN_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_EXT0) }, { MP_ROM_QSTR(MP_QSTR_EXT0_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_EXT0) }, { MP_ROM_QSTR(MP_QSTR_EXT1_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_EXT1) }, { MP_ROM_QSTR(MP_QSTR_TIMER_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_TIMER) }, { MP_ROM_QSTR(MP_QSTR_TOUCHPAD_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_TOUCHPAD) }, { MP_ROM_QSTR(MP_QSTR_ULP_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_ULP) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t mp_module_machine = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; #endif // MICROPY_PY_MACHINE micropython-1.12/ports/esp32/modmachine.h000066400000000000000000000015701357706137100204050ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_ESP32_MODMACHINE_H #define MICROPY_INCLUDED_ESP32_MODMACHINE_H #include "py/obj.h" typedef enum { //MACHINE_WAKE_IDLE=0x01, MACHINE_WAKE_SLEEP=0x02, MACHINE_WAKE_DEEPSLEEP=0x04 } wake_type_t; extern const mp_obj_type_t machine_timer_type; extern const mp_obj_type_t machine_wdt_type; extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_touchpad_type; extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_hw_spi_type; extern const mp_obj_type_t machine_uart_type; extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_sdcard_type; void machine_pins_init(void); void machine_pins_deinit(void); void machine_timer_deinit_all(void); #endif // MICROPY_INCLUDED_ESP32_MODMACHINE_H micropython-1.12/ports/esp32/modnetwork.c000066400000000000000000000746201357706137100204730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * and Mnemote Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2016, 2017 Nick Moore @mnemote * Copyright (c) 2017 "Eric Poulsen" * * Based on esp8266/modnetwork.c which is Copyright (c) 2015 Paul Sokolovsky * And the ESP IDF example code which is Public Domain / CC0 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/nlr.h" #include "py/objlist.h" #include "py/runtime.h" #include "py/mphal.h" #include "py/mperrno.h" #include "netutils.h" #include "esp_eth.h" #include "esp_wifi.h" #include "esp_log.h" #include "lwip/dns.h" #include "tcpip_adapter.h" #include "mdns.h" #if !MICROPY_ESP_IDF_4 #include "esp_wifi_types.h" #include "esp_event_loop.h" #endif #include "modnetwork.h" #define MODNETWORK_INCLUDE_CONSTANTS (1) NORETURN void _esp_exceptions(esp_err_t e) { switch (e) { case ESP_ERR_WIFI_NOT_INIT: mp_raise_msg(&mp_type_OSError, "Wifi Not Initialized"); case ESP_ERR_WIFI_NOT_STARTED: mp_raise_msg(&mp_type_OSError, "Wifi Not Started"); case ESP_ERR_WIFI_NOT_STOPPED: mp_raise_msg(&mp_type_OSError, "Wifi Not Stopped"); case ESP_ERR_WIFI_IF: mp_raise_msg(&mp_type_OSError, "Wifi Invalid Interface"); case ESP_ERR_WIFI_MODE: mp_raise_msg(&mp_type_OSError, "Wifi Invalid Mode"); case ESP_ERR_WIFI_STATE: mp_raise_msg(&mp_type_OSError, "Wifi Internal State Error"); case ESP_ERR_WIFI_CONN: mp_raise_msg(&mp_type_OSError, "Wifi Internal Error"); case ESP_ERR_WIFI_NVS: mp_raise_msg(&mp_type_OSError, "Wifi Internal NVS Error"); case ESP_ERR_WIFI_MAC: mp_raise_msg(&mp_type_OSError, "Wifi Invalid MAC Address"); case ESP_ERR_WIFI_SSID: mp_raise_msg(&mp_type_OSError, "Wifi SSID Invalid"); case ESP_ERR_WIFI_PASSWORD: mp_raise_msg(&mp_type_OSError, "Wifi Invalid Password"); case ESP_ERR_WIFI_TIMEOUT: mp_raise_OSError(MP_ETIMEDOUT); case ESP_ERR_WIFI_WAKE_FAIL: mp_raise_msg(&mp_type_OSError, "Wifi Wakeup Failure"); case ESP_ERR_WIFI_WOULD_BLOCK: mp_raise_msg(&mp_type_OSError, "Wifi Would Block"); case ESP_ERR_WIFI_NOT_CONNECT: mp_raise_msg(&mp_type_OSError, "Wifi Not Connected"); case ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS: mp_raise_msg(&mp_type_OSError, "TCP/IP Invalid Parameters"); case ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY: mp_raise_msg(&mp_type_OSError, "TCP/IP IF Not Ready"); case ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED: mp_raise_msg(&mp_type_OSError, "TCP/IP DHCP Client Start Failed"); case ESP_ERR_TCPIP_ADAPTER_NO_MEM: mp_raise_OSError(MP_ENOMEM); default: nlr_raise(mp_obj_new_exception_msg_varg( &mp_type_RuntimeError, "Wifi Unknown Error 0x%04x", e )); } } static inline void esp_exceptions(esp_err_t e) { if (e != ESP_OK) _esp_exceptions(e); } #define ESP_EXCEPTIONS(x) do { esp_exceptions(x); } while (0); typedef struct _wlan_if_obj_t { mp_obj_base_t base; int if_id; } wlan_if_obj_t; const mp_obj_type_t wlan_if_type; STATIC const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA}; STATIC const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP}; // Set to "true" if esp_wifi_start() was called static bool wifi_started = false; // Set to "true" if the STA interface is requested to be connected by the // user, used for automatic reassociation. static bool wifi_sta_connect_requested = false; // Set to "true" if the STA interface is connected to wifi and has IP address. static bool wifi_sta_connected = false; // Store the current status. 0 means None here, safe to do so as first enum value is WIFI_REASON_UNSPECIFIED=1. static uint8_t wifi_sta_disconn_reason = 0; #if MICROPY_HW_ENABLE_MDNS_QUERIES || MICROPY_HW_ENABLE_MDNS_RESPONDER // Whether mDNS has been initialised or not static bool mdns_initialised = false; #endif // This function is called by the system-event task and so runs in a different // thread to the main MicroPython task. It must not raise any Python exceptions. static esp_err_t event_handler(void *ctx, system_event_t *event) { switch(event->event_id) { case SYSTEM_EVENT_STA_START: ESP_LOGI("wifi", "STA_START"); break; case SYSTEM_EVENT_STA_CONNECTED: ESP_LOGI("network", "CONNECTED"); break; case SYSTEM_EVENT_STA_GOT_IP: ESP_LOGI("network", "GOT_IP"); wifi_sta_connected = true; wifi_sta_disconn_reason = 0; // Success so clear error. (in case of new error will be replaced anyway) #if MICROPY_HW_ENABLE_MDNS_QUERIES || MICROPY_HW_ENABLE_MDNS_RESPONDER if (!mdns_initialised) { mdns_init(); #if MICROPY_HW_ENABLE_MDNS_RESPONDER const char *hostname = NULL; if (tcpip_adapter_get_hostname(WIFI_IF_STA, &hostname) != ESP_OK || hostname == NULL) { hostname = "esp32"; } mdns_hostname_set(hostname); mdns_instance_name_set(hostname); #endif mdns_initialised = true; } #endif break; case SYSTEM_EVENT_STA_DISCONNECTED: { // This is a workaround as ESP32 WiFi libs don't currently // auto-reassociate. system_event_sta_disconnected_t *disconn = &event->event_info.disconnected; char *message = ""; wifi_sta_disconn_reason = disconn->reason; switch (disconn->reason) { case WIFI_REASON_BEACON_TIMEOUT: // AP has dropped out; try to reconnect. message = "\nbeacon timeout"; break; case WIFI_REASON_NO_AP_FOUND: // AP may not exist, or it may have momentarily dropped out; try to reconnect. message = "\nno AP found"; break; case WIFI_REASON_AUTH_FAIL: // Password may be wrong, or it just failed to connect; try to reconnect. message = "\nauthentication failed"; break; default: // Let other errors through and try to reconnect. break; } ESP_LOGI("wifi", "STA_DISCONNECTED, reason:%d%s", disconn->reason, message); wifi_sta_connected = false; if (wifi_sta_connect_requested) { wifi_mode_t mode; if (esp_wifi_get_mode(&mode) == ESP_OK) { if (mode & WIFI_MODE_STA) { // STA is active so attempt to reconnect. esp_err_t e = esp_wifi_connect(); if (e != ESP_OK) { ESP_LOGI("wifi", "error attempting to reconnect: 0x%04x", e); } } } } break; } case SYSTEM_EVENT_GOT_IP6: ESP_LOGI("network", "Got IPv6"); break; case SYSTEM_EVENT_ETH_START: ESP_LOGI("ethernet", "start"); break; case SYSTEM_EVENT_ETH_STOP: ESP_LOGI("ethernet", "stop"); break; case SYSTEM_EVENT_ETH_CONNECTED: ESP_LOGI("ethernet", "LAN cable connected"); break; case SYSTEM_EVENT_ETH_DISCONNECTED: ESP_LOGI("ethernet", "LAN cable disconnected"); break; case SYSTEM_EVENT_ETH_GOT_IP: ESP_LOGI("ethernet", "Got IP"); break; default: ESP_LOGI("network", "event %d", event->event_id); break; } return ESP_OK; } /*void error_check(bool status, const char *msg) { if (!status) { mp_raise_msg(&mp_type_OSError, msg); } } */ STATIC void require_if(mp_obj_t wlan_if, int if_no) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if); if (self->if_id != if_no) { mp_raise_msg(&mp_type_OSError, if_no == WIFI_IF_STA ? "STA required" : "AP required"); } } STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) { static int initialized = 0; if (!initialized) { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_LOGD("modnetwork", "Initializing WiFi"); ESP_EXCEPTIONS( esp_wifi_init(&cfg) ); ESP_EXCEPTIONS( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); ESP_LOGD("modnetwork", "Initialized"); initialized = 1; } int idx = (n_args > 0) ? mp_obj_get_int(args[0]) : WIFI_IF_STA; if (idx == WIFI_IF_STA) { return MP_OBJ_FROM_PTR(&wlan_sta_obj); } else if (idx == WIFI_IF_AP) { return MP_OBJ_FROM_PTR(&wlan_ap_obj); } else { mp_raise_ValueError("invalid WLAN interface identifier"); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan); STATIC mp_obj_t esp_initialize() { static int initialized = 0; if (!initialized) { ESP_LOGD("modnetwork", "Initializing TCP/IP"); tcpip_adapter_init(); ESP_LOGD("modnetwork", "Initializing Event Loop"); ESP_EXCEPTIONS( esp_event_loop_init(event_handler, NULL) ); ESP_LOGD("modnetwork", "esp_event_loop_init done"); initialized = 1; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_initialize_obj, esp_initialize); #if (WIFI_MODE_STA & WIFI_MODE_AP != WIFI_MODE_NULL || WIFI_MODE_STA | WIFI_MODE_AP != WIFI_MODE_APSTA) #error WIFI_MODE_STA and WIFI_MODE_AP are supposed to be bitfields! #endif STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); wifi_mode_t mode; if (!wifi_started) { mode = WIFI_MODE_NULL; } else { ESP_EXCEPTIONS(esp_wifi_get_mode(&mode)); } int bit = (self->if_id == WIFI_IF_STA) ? WIFI_MODE_STA : WIFI_MODE_AP; if (n_args > 1) { bool active = mp_obj_is_true(args[1]); mode = active ? (mode | bit) : (mode & ~bit); if (mode == WIFI_MODE_NULL) { if (wifi_started) { ESP_EXCEPTIONS(esp_wifi_stop()); wifi_started = false; } } else { ESP_EXCEPTIONS(esp_wifi_set_mode(mode)); if (!wifi_started) { ESP_EXCEPTIONS(esp_wifi_start()); wifi_started = true; } } } return (mode & bit) ? mp_const_true : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active); STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ssid, ARG_password, ARG_bssid }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); wifi_config_t wifi_sta_config = {{{0}}}; // configure any parameters that are given if (n_args > 1) { size_t len; const char *p; if (args[ARG_ssid].u_obj != mp_const_none) { p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len); memcpy(wifi_sta_config.sta.ssid, p, MIN(len, sizeof(wifi_sta_config.sta.ssid))); } if (args[ARG_password].u_obj != mp_const_none) { p = mp_obj_str_get_data(args[ARG_password].u_obj, &len); memcpy(wifi_sta_config.sta.password, p, MIN(len, sizeof(wifi_sta_config.sta.password))); } if (args[ARG_bssid].u_obj != mp_const_none) { p = mp_obj_str_get_data(args[ARG_bssid].u_obj, &len); if (len != sizeof(wifi_sta_config.sta.bssid)) { mp_raise_ValueError(NULL); } wifi_sta_config.sta.bssid_set = 1; memcpy(wifi_sta_config.sta.bssid, p, sizeof(wifi_sta_config.sta.bssid)); } ESP_EXCEPTIONS( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config) ); } // connect to the WiFi AP MP_THREAD_GIL_EXIT(); ESP_EXCEPTIONS( esp_wifi_connect() ); MP_THREAD_GIL_ENTER(); wifi_sta_connect_requested = true; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_connect_obj, 1, esp_connect); STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) { wifi_sta_connect_requested = false; ESP_EXCEPTIONS( esp_wifi_disconnect() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect); // Cases similar to ESP8266 user_interface.h // Error cases are referenced from wifi_err_reason_t in ESP-IDF enum { STAT_IDLE = 1000, STAT_CONNECTING = 1001, STAT_GOT_IP = 1010, }; STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { if (self->if_id == WIFI_IF_STA) { // Case of no arg is only for the STA interface if (wifi_sta_connected) { // Happy path, connected with IP return MP_OBJ_NEW_SMALL_INT(STAT_GOT_IP); } else if (wifi_sta_connect_requested) { // No connection or error, but is requested = Still connecting return MP_OBJ_NEW_SMALL_INT(STAT_CONNECTING); } else if (wifi_sta_disconn_reason == 0) { // No activity, No error = Idle return MP_OBJ_NEW_SMALL_INT(STAT_IDLE); } else { // Simply pass the error through from ESP-identifier return MP_OBJ_NEW_SMALL_INT(wifi_sta_disconn_reason); } } return mp_const_none; } // one argument: return status based on query parameter switch ((uintptr_t)args[1]) { case (uintptr_t)MP_OBJ_NEW_QSTR(MP_QSTR_stations): { // return list of connected stations, only if in soft-AP mode require_if(args[0], WIFI_IF_AP); wifi_sta_list_t station_list; ESP_EXCEPTIONS(esp_wifi_ap_get_sta_list(&station_list)); wifi_sta_info_t *stations = (wifi_sta_info_t*)station_list.sta; mp_obj_t list = mp_obj_new_list(0, NULL); for (int i = 0; i < station_list.num; ++i) { mp_obj_tuple_t *t = mp_obj_new_tuple(1, NULL); t->items[0] = mp_obj_new_bytes(stations[i].mac, sizeof(stations[i].mac)); mp_obj_list_append(list, t); } return list; } case (uintptr_t)MP_OBJ_NEW_QSTR(MP_QSTR_rssi): { // return signal of AP, only in STA mode require_if(args[0], WIFI_IF_STA); wifi_ap_record_t info; ESP_EXCEPTIONS(esp_wifi_sta_get_ap_info(&info)); return MP_OBJ_NEW_SMALL_INT(info.rssi); } default: mp_raise_ValueError("unknown status param"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status); STATIC mp_obj_t esp_scan(mp_obj_t self_in) { // check that STA mode is active wifi_mode_t mode; ESP_EXCEPTIONS(esp_wifi_get_mode(&mode)); if ((mode & WIFI_MODE_STA) == 0) { mp_raise_msg(&mp_type_OSError, "STA must be active"); } mp_obj_t list = mp_obj_new_list(0, NULL); wifi_scan_config_t config = { 0 }; // XXX how do we scan hidden APs (and if we can scan them, are they really hidden?) MP_THREAD_GIL_EXIT(); esp_err_t status = esp_wifi_scan_start(&config, 1); MP_THREAD_GIL_ENTER(); if (status == 0) { uint16_t count = 0; ESP_EXCEPTIONS( esp_wifi_scan_get_ap_num(&count) ); wifi_ap_record_t *wifi_ap_records = calloc(count, sizeof(wifi_ap_record_t)); ESP_EXCEPTIONS( esp_wifi_scan_get_ap_records(&count, wifi_ap_records) ); for (uint16_t i = 0; i < count; i++) { mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL); uint8_t *x = memchr(wifi_ap_records[i].ssid, 0, sizeof(wifi_ap_records[i].ssid)); int ssid_len = x ? x - wifi_ap_records[i].ssid : sizeof(wifi_ap_records[i].ssid); t->items[0] = mp_obj_new_bytes(wifi_ap_records[i].ssid, ssid_len); t->items[1] = mp_obj_new_bytes(wifi_ap_records[i].bssid, sizeof(wifi_ap_records[i].bssid)); t->items[2] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].primary); t->items[3] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].rssi); t->items[4] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].authmode); t->items[5] = mp_const_false; // XXX hidden? mp_obj_list_append(list, MP_OBJ_FROM_PTR(t)); } free(wifi_ap_records); } return list; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_scan_obj, esp_scan); STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->if_id == WIFI_IF_STA) { return mp_obj_new_bool(wifi_sta_connected); } else { wifi_sta_list_t sta; esp_wifi_ap_get_sta_list(&sta); return mp_obj_new_bool(sta.num != 0); } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected); STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); tcpip_adapter_ip_info_t info; tcpip_adapter_dns_info_t dns_info; tcpip_adapter_get_ip_info(self->if_id, &info); tcpip_adapter_get_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info); if (n_args == 1) { // get mp_obj_t tuple[4] = { netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&info.netmask, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&info.gw, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&dns_info.ip, NETUTILS_BIG), }; return mp_obj_new_tuple(4, tuple); } else { // set if (mp_obj_is_type(args[1], &mp_type_tuple) || mp_obj_is_type(args[1], &mp_type_list)) { mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 4, &items); netutils_parse_ipv4_addr(items[0], (void*)&info.ip, NETUTILS_BIG); if (mp_obj_is_integer(items[1])) { // allow numeric netmask, i.e.: // 24 -> 255.255.255.0 // 16 -> 255.255.0.0 // etc... uint32_t* m = (uint32_t*)&info.netmask; *m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1]))); } else { netutils_parse_ipv4_addr(items[1], (void*)&info.netmask, NETUTILS_BIG); } netutils_parse_ipv4_addr(items[2], (void*)&info.gw, NETUTILS_BIG); netutils_parse_ipv4_addr(items[3], (void*)&dns_info.ip, NETUTILS_BIG); // To set a static IP we have to disable DHCP first if (self->if_id == WIFI_IF_STA || self->if_id == ESP_IF_ETH) { esp_err_t e = tcpip_adapter_dhcpc_stop(self->if_id); if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e); ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(self->if_id, &info)); ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info)); } else if (self->if_id == WIFI_IF_AP) { esp_err_t e = tcpip_adapter_dhcps_stop(WIFI_IF_AP); if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e); ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(WIFI_IF_AP, &info)); ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(WIFI_IF_AP, TCPIP_ADAPTER_DNS_MAIN, &dns_info)); ESP_EXCEPTIONS(tcpip_adapter_dhcps_start(WIFI_IF_AP)); } } else { // check for the correct string const char *mode = mp_obj_str_get_str(args[1]); if ((self->if_id != WIFI_IF_STA && self->if_id != ESP_IF_ETH) || strcmp("dhcp", mode)) { mp_raise_ValueError("invalid arguments"); } ESP_EXCEPTIONS(tcpip_adapter_dhcpc_start(self->if_id)); } return mp_const_none; } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig); STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { if (n_args != 1 && kwargs->used != 0) { mp_raise_TypeError("either pos or kw args are allowed"); } wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); bool is_wifi = self->if_id == WIFI_IF_AP || self->if_id == WIFI_IF_STA; wifi_config_t cfg; if (is_wifi) { ESP_EXCEPTIONS(esp_wifi_get_config(self->if_id, &cfg)); } #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) if (kwargs->used != 0) { if (!is_wifi) { goto unknown; } for (size_t i = 0; i < kwargs->alloc; i++) { if (mp_map_slot_is_filled(kwargs, i)) { int req_if = -1; switch ((uintptr_t)kwargs->table[i].key) { case QS(MP_QSTR_mac): { mp_buffer_info_t bufinfo; mp_get_buffer_raise(kwargs->table[i].value, &bufinfo, MP_BUFFER_READ); if (bufinfo.len != 6) { mp_raise_ValueError("invalid buffer length"); } ESP_EXCEPTIONS(esp_wifi_set_mac(self->if_id, bufinfo.buf)); break; } case QS(MP_QSTR_essid): { req_if = WIFI_IF_AP; size_t len; const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len); len = MIN(len, sizeof(cfg.ap.ssid)); memcpy(cfg.ap.ssid, s, len); cfg.ap.ssid_len = len; break; } case QS(MP_QSTR_hidden): { req_if = WIFI_IF_AP; cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value); break; } case QS(MP_QSTR_authmode): { req_if = WIFI_IF_AP; cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value); break; } case QS(MP_QSTR_password): { req_if = WIFI_IF_AP; size_t len; const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len); len = MIN(len, sizeof(cfg.ap.password) - 1); memcpy(cfg.ap.password, s, len); cfg.ap.password[len] = 0; break; } case QS(MP_QSTR_channel): { req_if = WIFI_IF_AP; cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value); break; } case QS(MP_QSTR_dhcp_hostname): { const char *s = mp_obj_str_get_str(kwargs->table[i].value); ESP_EXCEPTIONS(tcpip_adapter_set_hostname(self->if_id, s)); break; } default: goto unknown; } // We post-check interface requirements to save on code size if (req_if >= 0) { require_if(args[0], req_if); } } } ESP_EXCEPTIONS(esp_wifi_set_config(self->if_id, &cfg)); return mp_const_none; } // Get config if (n_args != 2) { mp_raise_TypeError("can query only one param"); } int req_if = -1; mp_obj_t val = mp_const_none; switch ((uintptr_t)args[1]) { case QS(MP_QSTR_mac): { uint8_t mac[6]; switch (self->if_id) { case WIFI_IF_AP: // fallthrough intentional case WIFI_IF_STA: ESP_EXCEPTIONS(esp_wifi_get_mac(self->if_id, mac)); return mp_obj_new_bytes(mac, sizeof(mac)); #if !MICROPY_ESP_IDF_4 case ESP_IF_ETH: esp_eth_get_mac(mac); return mp_obj_new_bytes(mac, sizeof(mac)); #endif default: goto unknown; } } case QS(MP_QSTR_essid): switch (self->if_id) { case WIFI_IF_STA: val = mp_obj_new_str((char*)cfg.sta.ssid, strlen((char*)cfg.sta.ssid)); break; case WIFI_IF_AP: val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len); break; default: req_if = WIFI_IF_AP; } break; case QS(MP_QSTR_hidden): req_if = WIFI_IF_AP; val = mp_obj_new_bool(cfg.ap.ssid_hidden); break; case QS(MP_QSTR_authmode): req_if = WIFI_IF_AP; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode); break; case QS(MP_QSTR_channel): req_if = WIFI_IF_AP; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel); break; case QS(MP_QSTR_dhcp_hostname): { const char *s; ESP_EXCEPTIONS(tcpip_adapter_get_hostname(self->if_id, &s)); val = mp_obj_new_str(s, strlen(s)); break; } default: goto unknown; } #undef QS // We post-check interface requirements to save on code size if (req_if >= 0) { require_if(args[0], req_if); } return val; unknown: mp_raise_ValueError("unknown config param"); } MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config); STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&esp_active_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&esp_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&esp_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&esp_status_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&esp_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&esp_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&esp_config_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) }, }; STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table); const mp_obj_type_t wlan_if_type = { { &mp_type_type }, .name = MP_QSTR_WLAN, .locals_dict = (mp_obj_t)&wlan_if_locals_dict, }; STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode); STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_initialize_obj) }, { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) }, #if !MICROPY_ESP_IDF_4 { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) }, { MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&ppp_make_new_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_phy_mode_obj) }, #if MODNETWORK_INCLUDE_CONSTANTS { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(WIFI_IF_STA)}, { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(WIFI_IF_AP)}, { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(WIFI_PROTOCOL_11B) }, { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(WIFI_PROTOCOL_11G) }, { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(WIFI_PROTOCOL_11N) }, { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(WIFI_AUTH_OPEN) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(WIFI_AUTH_WEP) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(WIFI_AUTH_WPA_PSK) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_PSK) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA_WPA2_PSK) }, { MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) }, { MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) }, { MP_ROM_QSTR(MP_QSTR_PHY_TLK110), MP_ROM_INT(PHY_TLK110) }, // ETH Clock modes from ESP-IDF #if !MICROPY_ESP_IDF_4 { MP_ROM_QSTR(MP_QSTR_ETH_CLOCK_GPIO0_IN), MP_ROM_INT(ETH_CLOCK_GPIO0_IN) }, // Disabled at Aug 22nd 2018, reenabled Jan 28th 2019 in ESP-IDF // Because we use older SDK, it's currently disabled //{ MP_ROM_QSTR(MP_QSTR_ETH_CLOCK_GPIO0_OUT), MP_ROM_INT(ETH_CLOCK_GPIO0_OUT) }, { MP_ROM_QSTR(MP_QSTR_ETH_CLOCK_GPIO16_OUT), MP_ROM_INT(ETH_CLOCK_GPIO16_OUT) }, { MP_ROM_QSTR(MP_QSTR_ETH_CLOCK_GPIO17_OUT), MP_ROM_INT(ETH_CLOCK_GPIO17_OUT) }, #endif { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STAT_IDLE)}, { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STAT_CONNECTING)}, { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STAT_GOT_IP)}, // Errors from the ESP-IDF { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND)}, { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(WIFI_REASON_AUTH_FAIL)}, { MP_ROM_QSTR(MP_QSTR_STAT_BEACON_TIMEOUT), MP_ROM_INT(WIFI_REASON_BEACON_TIMEOUT)}, { MP_ROM_QSTR(MP_QSTR_STAT_ASSOC_FAIL), MP_ROM_INT(WIFI_REASON_ASSOC_FAIL)}, { MP_ROM_QSTR(MP_QSTR_STAT_HANDSHAKE_TIMEOUT), MP_ROM_INT(WIFI_REASON_HANDSHAKE_TIMEOUT)}, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); const mp_obj_module_t mp_module_network = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_network_globals, }; micropython-1.12/ports/esp32/modnetwork.h000066400000000000000000000030741357706137100204730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 "Eric Poulsen" * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_ESP32_MODNETWORK_H #define MICROPY_INCLUDED_ESP32_MODNETWORK_H enum { PHY_LAN8720, PHY_TLK110 }; MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj); MP_DECLARE_CONST_FUN_OBJ_1(ppp_make_new_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj); MP_DECLARE_CONST_FUN_OBJ_KW(esp_config_obj); void usocket_events_deinit(void); #endif micropython-1.12/ports/esp32/modsocket.c000066400000000000000000000676631357706137100203030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * and Mnemote Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2016, 2017 Nick Moore @mnemote * * Based on extmod/modlwip.c * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Galen Hazelwood * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/runtime0.h" #include "py/nlr.h" #include "py/objlist.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "py/stream.h" #include "py/mperrno.h" #include "lib/netutils/netutils.h" #include "tcpip_adapter.h" #include "mdns.h" #include "modnetwork.h" #include "lwip/sockets.h" #include "lwip/netdb.h" #include "lwip/ip4.h" #include "lwip/igmp.h" #include "esp_log.h" #if !MICROPY_ESP_IDF_4 #define lwip_bind lwip_bind_r #define lwip_listen lwip_listen_r #define lwip_accept lwip_accept_r #define lwip_setsockopt lwip_setsockopt_r #define lwip_fnctl lwip_fnctl_r #define lwip_recvfrom lwip_recvfrom_r #define lwip_write lwip_write_r #define lwip_sendto lwip_sendto_r #define lwip_close lwip_close_r #endif #define SOCKET_POLL_US (100000) #define MDNS_QUERY_TIMEOUT_MS (5000) #define MDNS_LOCAL_SUFFIX ".local" typedef struct _socket_obj_t { mp_obj_base_t base; int fd; uint8_t domain; uint8_t type; uint8_t proto; bool peer_closed; unsigned int retries; #if MICROPY_PY_USOCKET_EVENTS mp_obj_t events_callback; struct _socket_obj_t *events_next; #endif } socket_obj_t; void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms); #if MICROPY_PY_USOCKET_EVENTS // Support for callbacks on asynchronous socket events (when socket becomes readable) // This divisor is used to reduce the load on the system, so it doesn't poll sockets too often #define USOCKET_EVENTS_DIVISOR (8) STATIC uint8_t usocket_events_divisor; STATIC socket_obj_t *usocket_events_head; void usocket_events_deinit(void) { usocket_events_head = NULL; } // Assumes the socket is not already in the linked list, and adds it STATIC void usocket_events_add(socket_obj_t *sock) { sock->events_next = usocket_events_head; usocket_events_head = sock; } // Assumes the socket is already in the linked list, and removes it STATIC void usocket_events_remove(socket_obj_t *sock) { for (socket_obj_t **s = &usocket_events_head;; s = &(*s)->events_next) { if (*s == sock) { *s = (*s)->events_next; return; } } } // Polls all registered sockets for readability and calls their callback if they are readable void usocket_events_handler(void) { if (usocket_events_head == NULL) { return; } if (--usocket_events_divisor) { return; } usocket_events_divisor = USOCKET_EVENTS_DIVISOR; fd_set rfds; FD_ZERO(&rfds); int max_fd = 0; for (socket_obj_t *s = usocket_events_head; s != NULL; s = s->events_next) { FD_SET(s->fd, &rfds); max_fd = MAX(max_fd, s->fd); } // Poll the sockets struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; int r = select(max_fd + 1, &rfds, NULL, NULL, &timeout); if (r <= 0) { return; } // Call the callbacks for (socket_obj_t *s = usocket_events_head; s != NULL; s = s->events_next) { if (FD_ISSET(s->fd, &rfds)) { mp_call_function_1_protected(s->events_callback, s); } } } #endif // MICROPY_PY_USOCKET_EVENTS NORETURN static void exception_from_errno(int _errno) { // Here we need to convert from lwip errno values to MicroPython's standard ones if (_errno == EINPROGRESS) { _errno = MP_EINPROGRESS; } mp_raise_OSError(_errno); } static inline void check_for_exceptions(void) { mp_handle_pending(); } // This function mimics lwip_getaddrinfo, with added support for mDNS queries static int _socket_getaddrinfo3(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { #if MICROPY_HW_ENABLE_MDNS_QUERIES int nodename_len = strlen(nodename); const int local_len = sizeof(MDNS_LOCAL_SUFFIX) - 1; if (nodename_len > local_len && strcasecmp(nodename + nodename_len - local_len, MDNS_LOCAL_SUFFIX) == 0) { // mDNS query char nodename_no_local[nodename_len - local_len + 1]; memcpy(nodename_no_local, nodename, nodename_len - local_len); nodename_no_local[nodename_len - local_len] = '\0'; struct ip4_addr addr = {0}; esp_err_t err = mdns_query_a(nodename_no_local, MDNS_QUERY_TIMEOUT_MS, &addr); if (err != ESP_OK) { if (err == ESP_ERR_NOT_FOUND){ *res = NULL; return 0; } *res = NULL; return err; } struct addrinfo *ai = memp_malloc(MEMP_NETDB); if (ai == NULL) { *res = NULL; return EAI_MEMORY; } memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); struct sockaddr_in *sa = (struct sockaddr_in*)((uint8_t*)ai + sizeof(struct addrinfo)); inet_addr_from_ip4addr(&sa->sin_addr, &addr); sa->sin_family = AF_INET; sa->sin_len = sizeof(struct sockaddr_in); sa->sin_port = lwip_htons((u16_t)atoi(servname)); ai->ai_family = AF_INET; ai->ai_canonname = ((char*)sa + sizeof(struct sockaddr_storage)); memcpy(ai->ai_canonname, nodename, nodename_len + 1); ai->ai_addrlen = sizeof(struct sockaddr_storage); ai->ai_addr = (struct sockaddr*)sa; *res = ai; return 0; } #endif // Normal query return lwip_getaddrinfo(nodename, servname, hints, res); } static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) { const struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, }; mp_obj_t port = portx; if (mp_obj_is_small_int(port)) { // This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but // that's the API we have to work with ... port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str_via_qstr("%s", 2), port); } const char *host_str = mp_obj_str_get_str(host); const char *port_str = mp_obj_str_get_str(port); if (host_str[0] == '\0') { // a host of "" is equivalent to the default/all-local IP address host_str = "0.0.0.0"; } MP_THREAD_GIL_EXIT(); int res = _socket_getaddrinfo3(host_str, port_str, &hints, resp); MP_THREAD_GIL_ENTER(); return res; } STATIC void _socket_getaddrinfo(const mp_obj_t addrtuple, struct addrinfo **resp) { mp_obj_t *elem; mp_obj_get_array_fixed_n(addrtuple, 2, &elem); int res = _socket_getaddrinfo2(elem[0], elem[1], resp); if (res != 0) { mp_raise_OSError(res); } if (*resp == NULL) { mp_raise_OSError(-2); // name or service not known } } STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 3, false); socket_obj_t *sock = m_new_obj_with_finaliser(socket_obj_t); sock->base.type = type_in; sock->domain = AF_INET; sock->type = SOCK_STREAM; sock->proto = 0; sock->peer_closed = false; if (n_args > 0) { sock->domain = mp_obj_get_int(args[0]); if (n_args > 1) { sock->type = mp_obj_get_int(args[1]); if (n_args > 2) { sock->proto = mp_obj_get_int(args[2]); } } } sock->fd = lwip_socket(sock->domain, sock->type, sock->proto); if (sock->fd < 0) { exception_from_errno(errno); } _socket_settimeout(sock, UINT64_MAX); return MP_OBJ_FROM_PTR(sock); } STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); struct addrinfo *res; _socket_getaddrinfo(arg1, &res); int r = lwip_bind(self->fd, res->ai_addr, res->ai_addrlen); lwip_freeaddrinfo(res); if (r < 0) exception_from_errno(errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); STATIC mp_obj_t socket_listen(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); int backlog = mp_obj_get_int(arg1); int r = lwip_listen(self->fd, backlog); if (r < 0) exception_from_errno(errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); struct sockaddr addr; socklen_t addr_len = sizeof(addr); int new_fd = -1; for (int i=0; i<=self->retries; i++) { MP_THREAD_GIL_EXIT(); new_fd = lwip_accept(self->fd, &addr, &addr_len); MP_THREAD_GIL_ENTER(); if (new_fd >= 0) break; if (errno != EAGAIN) exception_from_errno(errno); check_for_exceptions(); } if (new_fd < 0) { if (self->retries == 0) { mp_raise_OSError(MP_EAGAIN); } else { mp_raise_OSError(MP_ETIMEDOUT); } } // create new socket object socket_obj_t *sock = m_new_obj_with_finaliser(socket_obj_t); sock->base.type = self->base.type; sock->fd = new_fd; sock->domain = self->domain; sock->type = self->type; sock->proto = self->proto; sock->peer_closed = false; _socket_settimeout(sock, UINT64_MAX); // make the return value uint8_t *ip = (uint8_t*)&((struct sockaddr_in*)&addr)->sin_addr; mp_uint_t port = lwip_ntohs(((struct sockaddr_in*)&addr)->sin_port); mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = sock; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return client; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); struct addrinfo *res; _socket_getaddrinfo(arg1, &res); MP_THREAD_GIL_EXIT(); int r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen); MP_THREAD_GIL_ENTER(); lwip_freeaddrinfo(res); if (r != 0) { exception_from_errno(errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { (void)n_args; // always 4 socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); int opt = mp_obj_get_int(args[2]); switch (opt) { // level: SOL_SOCKET case SO_REUSEADDR: { int val = mp_obj_get_int(args[3]); int ret = lwip_setsockopt(self->fd, SOL_SOCKET, opt, &val, sizeof(int)); if (ret != 0) { exception_from_errno(errno); } break; } #if MICROPY_PY_USOCKET_EVENTS // level: SOL_SOCKET // special "register callback" option case 20: { if (args[3] == mp_const_none) { if (self->events_callback != MP_OBJ_NULL) { usocket_events_remove(self); self->events_callback = MP_OBJ_NULL; } } else { if (self->events_callback == MP_OBJ_NULL) { usocket_events_add(self); } self->events_callback = args[3]; } break; } #endif // level: IPPROTO_IP case IP_ADD_MEMBERSHIP: { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); if (bufinfo.len != sizeof(ip4_addr_t) * 2) { mp_raise_ValueError(NULL); } // POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa err_t err = igmp_joingroup((const ip4_addr_t*)bufinfo.buf + 1, bufinfo.buf); if (err != ERR_OK) { mp_raise_OSError(-err); } break; } default: mp_printf(&mp_plat_print, "Warning: lwip.setsockopt() option not implemented\n"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms) { // Rather than waiting for the entire timeout specified, we wait sock->retries times // for SOCKET_POLL_US each, checking for a MicroPython interrupt between timeouts. // with SOCKET_POLL_MS == 100ms, sock->retries allows for timeouts up to 13 years. // if timeout_ms == UINT64_MAX, wait forever. sock->retries = (timeout_ms == UINT64_MAX) ? UINT_MAX : timeout_ms * 1000 / SOCKET_POLL_US; struct timeval timeout = { .tv_sec = 0, .tv_usec = timeout_ms ? SOCKET_POLL_US : 0 }; lwip_setsockopt(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&timeout, sizeof(timeout)); lwip_setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)); lwip_fcntl(sock->fd, F_SETFL, timeout_ms ? 0 : O_NONBLOCK); } STATIC mp_obj_t socket_settimeout(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); if (arg1 == mp_const_none) _socket_settimeout(self, UINT64_MAX); else { #if MICROPY_PY_BUILTINS_FLOAT _socket_settimeout(self, mp_obj_get_float(arg1) * 1000L); #else _socket_settimeout(self, mp_obj_get_int(arg1) * 1000); #endif } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); STATIC mp_obj_t socket_setblocking(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); if (mp_obj_is_true(arg1)) _socket_settimeout(self, UINT64_MAX); else _socket_settimeout(self, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); // XXX this can end up waiting a very long time if the content is dribbled in one character // at a time, as the timeout resets each time a recvfrom succeeds ... this is probably not // good behaviour. STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, struct sockaddr *from, socklen_t *from_len, int *errcode) { socket_obj_t *sock = MP_OBJ_TO_PTR(self_in); // If the peer closed the connection then the lwIP socket API will only return "0" once // from lwip_recvfrom and then block on subsequent calls. To emulate POSIX behaviour, // which continues to return "0" for each call on a closed socket, we set a flag when // the peer closed the socket. if (sock->peer_closed) { return 0; } // XXX Would be nicer to use RTC to handle timeouts for (int i = 0; i <= sock->retries; ++i) { // Poll the socket to see if it has waiting data and only release the GIL if it doesn't. // This ensures higher performance in the case of many small reads, eg for readline. bool release_gil; { fd_set rfds; FD_ZERO(&rfds); FD_SET(sock->fd, &rfds); struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; int r = select(sock->fd + 1, &rfds, NULL, NULL, &timeout); release_gil = r != 1; } if (release_gil) { MP_THREAD_GIL_EXIT(); } int r = lwip_recvfrom(sock->fd, buf, size, 0, from, from_len); if (release_gil) { MP_THREAD_GIL_ENTER(); } if (r == 0) { sock->peer_closed = true; } if (r >= 0) { return r; } if (errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; } check_for_exceptions(); } *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; return MP_STREAM_ERROR; } mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in, struct sockaddr *from, socklen_t *from_len) { size_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); int errcode; mp_uint_t ret = _socket_read_data(self_in, vstr.buf, len, from, from_len, &errcode); if (ret == MP_STREAM_ERROR) { exception_from_errno(errcode); } vstr.len = ret; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { return _socket_recvfrom(self_in, len_in, NULL, NULL); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { struct sockaddr from; socklen_t fromlen = sizeof(from); mp_obj_t tuple[2]; tuple[0] = _socket_recvfrom(self_in, len_in, &from, &fromlen); uint8_t *ip = (uint8_t*)&((struct sockaddr_in*)&from)->sin_addr; mp_uint_t port = lwip_ntohs(((struct sockaddr_in*)&from)->sin_port); tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom); int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) { int sentlen = 0; for (int i=0; i<=sock->retries && sentlen < datalen; i++) { MP_THREAD_GIL_EXIT(); int r = lwip_write(sock->fd, data+sentlen, datalen-sentlen); MP_THREAD_GIL_ENTER(); if (r < 0 && errno != EWOULDBLOCK) exception_from_errno(errno); if (r > 0) sentlen += r; check_for_exceptions(); } if (sentlen == 0) mp_raise_OSError(MP_ETIMEDOUT); return sentlen; } STATIC mp_obj_t socket_send(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *sock = MP_OBJ_TO_PTR(arg0); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg1, &bufinfo, MP_BUFFER_READ); int r = _socket_send(sock, bufinfo.buf, bufinfo.len); return mp_obj_new_int(r); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); STATIC mp_obj_t socket_sendall(const mp_obj_t arg0, const mp_obj_t arg1) { // XXX behaviour when nonblocking (see extmod/modlwip.c) // XXX also timeout behaviour. socket_obj_t *sock = MP_OBJ_TO_PTR(arg0); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg1, &bufinfo, MP_BUFFER_READ); int r = _socket_send(sock, bufinfo.buf, bufinfo.len); if (r < bufinfo.len) mp_raise_OSError(MP_ETIMEDOUT); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_sendall_obj, socket_sendall); STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { socket_obj_t *self = MP_OBJ_TO_PTR(self_in); // get the buffer to send mp_buffer_info_t bufinfo; mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); // create the destination address struct sockaddr_in to; to.sin_len = sizeof(to); to.sin_family = AF_INET; to.sin_port = lwip_htons(netutils_parse_inet_addr(addr_in, (uint8_t*)&to.sin_addr, NETUTILS_BIG)); // send the data for (int i=0; i<=self->retries; i++) { MP_THREAD_GIL_EXIT(); int ret = lwip_sendto(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr*)&to, sizeof(to)); MP_THREAD_GIL_ENTER(); if (ret > 0) return mp_obj_new_int_from_uint(ret); if (ret == -1 && errno != EWOULDBLOCK) { exception_from_errno(errno); } check_for_exceptions(); } mp_raise_OSError(MP_ETIMEDOUT); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); STATIC mp_obj_t socket_fileno(const mp_obj_t arg0) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); return mp_obj_new_int(self->fd); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno); STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { (void)n_args; return args[0]; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile); STATIC mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { return _socket_read_data(self_in, buf, size, NULL, NULL, errcode); } STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { socket_obj_t *sock = self_in; for (int i=0; i<=sock->retries; i++) { MP_THREAD_GIL_EXIT(); int r = lwip_write(sock->fd, buf, size); MP_THREAD_GIL_ENTER(); if (r > 0) return r; if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; } check_for_exceptions(); } *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; return MP_STREAM_ERROR; } STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { socket_obj_t * socket = self_in; if (request == MP_STREAM_POLL) { fd_set rfds; FD_ZERO(&rfds); fd_set wfds; FD_ZERO(&wfds); fd_set efds; FD_ZERO(&efds); struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; if (arg & MP_STREAM_POLL_RD) FD_SET(socket->fd, &rfds); if (arg & MP_STREAM_POLL_WR) FD_SET(socket->fd, &wfds); if (arg & MP_STREAM_POLL_HUP) FD_SET(socket->fd, &efds); int r = select((socket->fd)+1, &rfds, &wfds, &efds, &timeout); if (r < 0) { *errcode = MP_EIO; return MP_STREAM_ERROR; } mp_uint_t ret = 0; if (FD_ISSET(socket->fd, &rfds)) ret |= MP_STREAM_POLL_RD; if (FD_ISSET(socket->fd, &wfds)) ret |= MP_STREAM_POLL_WR; if (FD_ISSET(socket->fd, &efds)) ret |= MP_STREAM_POLL_HUP; return ret; } else if (request == MP_STREAM_CLOSE) { if (socket->fd >= 0) { #if MICROPY_PY_USOCKET_EVENTS if (socket->events_callback != MP_OBJ_NULL) { usocket_events_remove(socket); socket->events_callback = MP_OBJ_NULL; } #endif int ret = lwip_close(socket->fd); if (ret != 0) { *errcode = errno; return MP_STREAM_ERROR; } socket->fd = -1; } return 0; } *errcode = MP_EINVAL; return MP_STREAM_ERROR; } STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, { MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&socket_sendall_obj) }, { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) }, { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, }; STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); STATIC const mp_stream_p_t socket_stream_p = { .read = socket_stream_read, .write = socket_stream_write, .ioctl = socket_stream_ioctl }; STATIC const mp_obj_type_t socket_type = { { &mp_type_type }, .name = MP_QSTR_socket, .make_new = socket_make_new, .protocol = &socket_stream_p, .locals_dict = (mp_obj_t)&socket_locals_dict, }; STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { // TODO support additional args beyond the first two struct addrinfo *res = NULL; _socket_getaddrinfo2(args[0], args[1], &res); mp_obj_t ret_list = mp_obj_new_list(0, NULL); for (struct addrinfo *resi = res; resi; resi = resi->ai_next) { mp_obj_t addrinfo_objs[5] = { mp_obj_new_int(resi->ai_family), mp_obj_new_int(resi->ai_socktype), mp_obj_new_int(resi->ai_protocol), mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname)), mp_const_none }; if (resi->ai_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)resi->ai_addr; // This looks odd, but it's really just a u32_t ip4_addr_t ip4_addr = { .addr = addr->sin_addr.s_addr }; char buf[16]; ip4addr_ntoa_r(&ip4_addr, buf, sizeof(buf)); mp_obj_t inaddr_objs[2] = { mp_obj_new_str(buf, strlen(buf)), mp_obj_new_int(ntohs(addr->sin_port)) }; addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); } mp_obj_list_append(ret_list, mp_obj_new_tuple(5, addrinfo_objs)); } if (res) lwip_freeaddrinfo(res); return ret_list; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_socket_getaddrinfo_obj, 2, 6, esp_socket_getaddrinfo); STATIC mp_obj_t esp_socket_initialize() { static int initialized = 0; if (!initialized) { ESP_LOGI("modsocket", "Initializing"); tcpip_adapter_init(); initialized = 1; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_socket_initialize_obj, esp_socket_initialize); STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_socket_initialize_obj) }, { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&esp_socket_getaddrinfo_obj) }, { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(AF_INET) }, { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(AF_INET6) }, { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SOCK_STREAM) }, { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SOCK_DGRAM) }, { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(SOCK_RAW) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(IPPROTO_TCP) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(IPPROTO_UDP) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(IPPROTO_IP) }, { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(SOL_SOCKET) }, { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SO_REUSEADDR) }, { MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table); const mp_obj_module_t mp_module_usocket = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_socket_globals, }; micropython-1.12/ports/esp32/modules/000077500000000000000000000000001357706137100175755ustar00rootroot00000000000000micropython-1.12/ports/esp32/modules/_boot.py000066400000000000000000000002551357706137100212530ustar00rootroot00000000000000import gc import uos from flashbdev import bdev try: if bdev: uos.mount(bdev, '/') except OSError: import inisetup vfs = inisetup.setup() gc.collect() micropython-1.12/ports/esp32/modules/apa106.py000066400000000000000000000002551357706137100211410ustar00rootroot00000000000000# APA106driver for MicroPython on ESP32 # MIT license; Copyright (c) 2016 Damien P. George from neopixel import NeoPixel class APA106(NeoPixel): ORDER = (0, 1, 2, 3) micropython-1.12/ports/esp32/modules/flashbdev.py000066400000000000000000000001661357706137100221100ustar00rootroot00000000000000from esp32 import Partition bdev = Partition.find(Partition.TYPE_DATA, label='vfs') bdev = bdev[0] if bdev else None micropython-1.12/ports/esp32/modules/inisetup.py000066400000000000000000000017671357706137100220220ustar00rootroot00000000000000import uos from flashbdev import bdev def check_bootsec(): buf = bytearray(bdev.ioctl(5, 0)) # 5 is SEC_SIZE bdev.readblocks(0, buf) empty = True for b in buf: if b != 0xff: empty = False break if empty: return True fs_corrupted() def fs_corrupted(): import time while 1: print("""\ FAT filesystem appears to be corrupted. If you had important data there, you may want to make a flash snapshot to try to recover it. Otherwise, perform factory reprogramming of MicroPython firmware (completely erase flash, followed by firmware programming). """) time.sleep(3) def setup(): check_bootsec() print("Performing initial setup") uos.VfsFat.mkfs(bdev) vfs = uos.VfsFat(bdev) uos.mount(vfs, '/') with open("boot.py", "w") as f: f.write("""\ # This file is executed on every boot (including wake-boot from deepsleep) #import esp #esp.osdebug(None) #import webrepl #webrepl.start() """) return vfs micropython-1.12/ports/esp32/modules/neopixel.py000066400000000000000000000015641357706137100220000ustar00rootroot00000000000000# NeoPixel driver for MicroPython on ESP32 # MIT license; Copyright (c) 2016 Damien P. George from esp import neopixel_write class NeoPixel: ORDER = (1, 0, 2, 3) def __init__(self, pin, n, bpp=3, timing=1): self.pin = pin self.n = n self.bpp = bpp self.buf = bytearray(n * bpp) self.pin.init(pin.OUT) self.timing = timing def __setitem__(self, index, val): offset = index * self.bpp for i in range(self.bpp): self.buf[offset + self.ORDER[i]] = val[i] def __getitem__(self, index): offset = index * self.bpp return tuple(self.buf[offset + self.ORDER[i]] for i in range(self.bpp)) def fill(self, color): for i in range(self.n): self[i] = color def write(self): neopixel_write(self.pin, self.buf, self.timing) micropython-1.12/ports/esp32/moduos.c000066400000000000000000000123371357706137100176050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2015 Josef Gajdusek * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "esp_system.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "extmod/misc.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "extmod/vfs_lfs.h" #include "genhdr/mpversion.h" extern const mp_obj_type_t mp_fat_vfs_type; STATIC const qstr os_uname_info_fields[] = { MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine }; STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); STATIC MP_DEFINE_ATTRTUPLE( os_uname_info_obj, os_uname_info_fields, 5, (mp_obj_t)&os_uname_info_sysname_obj, (mp_obj_t)&os_uname_info_nodename_obj, (mp_obj_t)&os_uname_info_release_obj, (mp_obj_t)&os_uname_info_version_obj, (mp_obj_t)&os_uname_info_machine_obj ); STATIC mp_obj_t os_uname(void) { return (mp_obj_t)&os_uname_info_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); STATIC mp_obj_t os_urandom(mp_obj_t num) { mp_int_t n = mp_obj_get_int(num); vstr_t vstr; vstr_init_len(&vstr, n); uint32_t r = 0; for (int i = 0; i < n; i++) { if ((i & 3) == 0) { r = esp_random(); // returns 32-bit hardware random number } vstr.buf[i] = r; r >>= 8; } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); #if MICROPY_PY_OS_DUPTERM STATIC mp_obj_t os_dupterm_notify(mp_obj_t obj_in) { (void)obj_in; for (;;) { int c = mp_uos_dupterm_rx_chr(); if (c < 0) { break; } ringbuf_put(&stdin_ringbuf, c); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify); #endif STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, #if MICROPY_PY_OS_DUPTERM { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, #endif #if MICROPY_VFS { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif #if MICROPY_VFS_LFS1 { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, #endif #if MICROPY_VFS_LFS2 { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, #endif #endif }; STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); const mp_obj_module_t uos_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&os_module_globals, }; micropython-1.12/ports/esp32/modutime.c000066400000000000000000000104261357706137100201170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "lib/timeutils/timeutils.h" #include "extmod/utime_mphal.h" STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { timeutils_struct_time_t tm; mp_int_t seconds; if (n_args == 0 || args[0] == mp_const_none) { struct timeval tv; gettimeofday(&tv, NULL); seconds = tv.tv_sec; } else { seconds = mp_obj_get_int(args[0]); } timeutils_seconds_since_2000_to_struct_time(seconds, &tm); mp_obj_t tuple[8] = { tuple[0] = mp_obj_new_int(tm.tm_year), tuple[1] = mp_obj_new_int(tm.tm_mon), tuple[2] = mp_obj_new_int(tm.tm_mday), tuple[3] = mp_obj_new_int(tm.tm_hour), tuple[4] = mp_obj_new_int(tm.tm_min), tuple[5] = mp_obj_new_int(tm.tm_sec), tuple[6] = mp_obj_new_int(tm.tm_wday), tuple[7] = mp_obj_new_int(tm.tm_yday), }; return mp_obj_new_tuple(8, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime); STATIC mp_obj_t time_mktime(mp_obj_t tuple) { size_t len; mp_obj_t *elem; mp_obj_get_array(tuple, &len, &elem); // localtime generates a tuple of len 8. CPython uses 9, so we accept both. if (len < 8 || len > 9) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "mktime needs a tuple of length 8 or 9 (%d given)", len)); } return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); STATIC mp_obj_t time_time(void) { struct timeval tv; gettimeofday(&tv, NULL); return mp_obj_new_int(tv.tv_sec); } MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) }, { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) }, { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t utime_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; micropython-1.12/ports/esp32/mpconfigport.h000066400000000000000000000267401357706137100210160ustar00rootroot00000000000000// Options to control how MicroPython is built for this port, // overriding defaults in py/mpconfig.h. // Board-specific definitions #include "mpconfigboard.h" #include #include #if !MICROPY_ESP_IDF_4 #include "rom/ets_sys.h" #endif // object representation and NLR handling #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) #define MICROPY_NLR_SETJMP (1) // memory allocation policies #define MICROPY_ALLOC_PATH_MAX (128) // emitters #define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_XTENSAWIN (1) // compiler configuration #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) // optimisations #define MICROPY_OPT_COMPUTED_GOTO (1) #define MICROPY_OPT_MPZ_BITWISE (1) // Python internal features #define MICROPY_READER_VFS (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_EMACS_KEYS (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) #define MICROPY_WARNINGS (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_CPYTHON_COMPAT (1) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_MODULE_FROZEN_STR (0) #define MICROPY_MODULE_FROZEN_MPY (1) #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_DEPTH (8) #define MICROPY_VFS (1) // control over Python builtins #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) #define MICROPY_PY_BUILTINS_ROUND_INT (1) #define MICROPY_PY_BUILTINS_TIMEOUTERROR (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_EXECFILE (1) #define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_PY_BUILTINS_REVERSED (1) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT esp32_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY___FILE__ (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_COLLECTIONS_DEQUE (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) #define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_GC (1) #define MICROPY_PY_IO (1) #define MICROPY_PY_IO_IOBASE (1) #define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_IO_BYTESIO (1) #define MICROPY_PY_IO_BUFFEREDWRITER (1) #define MICROPY_PY_STRUCT (1) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_MODULES (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_SYS_STDIO_BUFFER (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_THREAD (1) #define MICROPY_PY_THREAD_GIL (1) #define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) // extended modules #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_URE_SUB (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UTIMEQ (1) #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UHASHLIB_SHA1 (1) #define MICROPY_PY_UHASHLIB_SHA256 (1) #define MICROPY_PY_UCRYPTOLIB (1) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UBINASCII_CRC32 (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #define MICROPY_PY_OS_DUPTERM (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hw_i2c_make_new #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SPI_MSB (0) #define MICROPY_PY_MACHINE_SPI_LSB (1) #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new #define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly #define MICROPY_PY_USSL (1) #define MICROPY_SSL_MBEDTLS (1) #define MICROPY_PY_USSL_FINALISER (1) #define MICROPY_PY_UWEBSOCKET (1) #define MICROPY_PY_WEBREPL (1) #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL) #define MICROPY_PY_BLUETOOTH_RANDOM_ADDR (1) #define MICROPY_PY_BLUETOOTH_DEFAULT_NAME ("ESP32") // fatfs configuration #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define mp_type_fileio mp_type_vfs_fat_fileio #define mp_type_textio mp_type_vfs_fat_textio // use vfs's functions for import stat and builtin open #define mp_import_stat mp_vfs_import_stat #define mp_builtin_open mp_vfs_open #define mp_builtin_open_obj mp_vfs_open_obj // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t esp_module; extern const struct _mp_obj_module_t esp32_module; extern const struct _mp_obj_module_t utime_module; extern const struct _mp_obj_module_t uos_module; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_network; extern const struct _mp_obj_module_t mp_module_onewire; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ { MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ #define MP_STATE_PORT MP_STATE_VM struct _machine_timer_obj_t; #if MICROPY_BLUETOOTH_NIMBLE struct mp_bluetooth_nimble_root_pointers_t; #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; #else #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE #endif #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ mp_obj_t machine_pin_irq_handler[40]; \ struct _machine_timer_obj_t *machine_timer_obj_head; \ MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE // type definitions for the specific machine #define BYTES_PER_WORD (4) #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p))) #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) void *esp_native_code_commit(void*, size_t, void*); #define MP_PLAT_COMMIT_EXEC(buf, len, reloc) esp_native_code_commit(buf, len, reloc) #define MP_SSIZE_MAX (0x7fffffff) // Note: these "critical nested" macros do not ensure cross-CPU exclusion, // the only disable interrupts on the current CPU. To full manage exclusion // one should use portENTER_CRITICAL/portEXIT_CRITICAL instead. #include "freertos/FreeRTOS.h" #define MICROPY_BEGIN_ATOMIC_SECTION() portENTER_CRITICAL_NESTED() #define MICROPY_END_ATOMIC_SECTION(state) portEXIT_CRITICAL_NESTED(state) #if MICROPY_PY_USOCKET_EVENTS #define MICROPY_PY_USOCKET_EVENTS_HANDLER extern void usocket_events_handler(void); usocket_events_handler(); #else #define MICROPY_PY_USOCKET_EVENTS_HANDLER #endif #if MICROPY_PY_THREAD #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ MICROPY_PY_USOCKET_EVENTS_HANDLER \ MP_THREAD_GIL_EXIT(); \ MP_THREAD_GIL_ENTER(); \ } while (0); #else #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ MICROPY_PY_USOCKET_EVENTS_HANDLER \ asm("waiti 0"); \ } while (0); #endif #define UINT_FMT "%u" #define INT_FMT "%d" typedef int32_t mp_int_t; // must be pointer size typedef uint32_t mp_uint_t; // must be pointer size typedef long mp_off_t; // ssize_t, off_t as required by POSIX-signatured functions in stream.h #include // board specifics #define MICROPY_PY_SYS_PLATFORM "esp32" #ifndef MICROPY_HW_ENABLE_MDNS_QUERIES #define MICROPY_HW_ENABLE_MDNS_QUERIES (1) #endif #ifndef MICROPY_HW_ENABLE_MDNS_RESPONDER #define MICROPY_HW_ENABLE_MDNS_RESPONDER (1) #endif micropython-1.12/ports/esp32/mphalport.c000066400000000000000000000116241357706137100203030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #if MICROPY_ESP_IDF_4 #include "esp32/rom/uart.h" #else #include "rom/uart.h" #endif #include "py/obj.h" #include "py/stream.h" #include "py/mpstate.h" #include "py/mphal.h" #include "extmod/misc.h" #include "lib/utils/pyexec.h" #include "mphalport.h" TaskHandle_t mp_main_task_handle; STATIC uint8_t stdin_ringbuf_array[256]; ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array)}; uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { ret |= MP_STREAM_POLL_RD; } return ret; } int mp_hal_stdin_rx_chr(void) { for (;;) { int c = ringbuf_get(&stdin_ringbuf); if (c != -1) { return c; } MICROPY_EVENT_POLL_HOOK ulTaskNotifyTake(pdFALSE, 1); } } void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } void mp_hal_stdout_tx_strn(const char *str, uint32_t len) { // Only release the GIL if many characters are being sent bool release_gil = len > 20; if (release_gil) { MP_THREAD_GIL_EXIT(); } for (uint32_t i = 0; i < len; ++i) { uart_tx_one_char(str[i]); } if (release_gil) { MP_THREAD_GIL_ENTER(); } mp_uos_dupterm_tx_strn(str, len); } // Efficiently convert "\n" to "\r\n" void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { const char *last = str; while (len--) { if (*str == '\n') { if (str > last) { mp_hal_stdout_tx_strn(last, str - last); } mp_hal_stdout_tx_strn("\r\n", 2); ++str; last = str; } else { ++str; } } if (str > last) { mp_hal_stdout_tx_strn(last, str - last); } } uint32_t mp_hal_ticks_ms(void) { return esp_timer_get_time() / 1000; } uint32_t mp_hal_ticks_us(void) { return esp_timer_get_time(); } void mp_hal_delay_ms(uint32_t ms) { uint64_t us = ms * 1000; uint64_t dt; uint64_t t0 = esp_timer_get_time(); for (;;) { uint64_t t1 = esp_timer_get_time(); dt = t1 - t0; if (dt + portTICK_PERIOD_MS * 1000 >= us) { // doing a vTaskDelay would take us beyond requested delay time break; } MICROPY_EVENT_POLL_HOOK ulTaskNotifyTake(pdFALSE, 1); } if (dt < us) { // do the remaining delay accurately mp_hal_delay_us(us - dt); } } void mp_hal_delay_us(uint32_t us) { // these constants are tested for a 240MHz clock const uint32_t this_overhead = 5; const uint32_t pend_overhead = 150; // return if requested delay is less than calling overhead if (us < this_overhead) { return; } us -= this_overhead; uint64_t t0 = esp_timer_get_time(); for (;;) { uint64_t dt = esp_timer_get_time() - t0; if (dt >= us) { return; } if (dt + pend_overhead < us) { // we have enough time to service pending events // (don't use MICROPY_EVENT_POLL_HOOK because it also yields) mp_handle_pending(); } } } /* extern int mp_stream_errno; int *__errno() { return &mp_stream_errno; } */ // Wake up the main task if it is sleeping void mp_hal_wake_main_task_from_isr(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR(mp_main_task_handle, &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken == pdTRUE) { portYIELD_FROM_ISR(); } } micropython-1.12/ports/esp32/mphalport.h000066400000000000000000000065731357706137100203170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef INCLUDED_MPHALPORT_H #define INCLUDED_MPHALPORT_H #include "py/ringbuf.h" #include "lib/utils/interrupt_char.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" // The core that the MicroPython task(s) are pinned to #define MP_TASK_COREID (1) extern TaskHandle_t mp_main_task_handle; extern ringbuf_t stdin_ringbuf; uint32_t mp_hal_ticks_us(void); __attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) { uint32_t ccount; __asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); return ccount; } void mp_hal_delay_us(uint32_t); #define mp_hal_delay_us_fast(us) ets_delay_us(us) void mp_hal_set_interrupt_char(int c); uint32_t mp_hal_get_cpu_freq(void); #define mp_hal_quiet_timing_enter() MICROPY_BEGIN_ATOMIC_SECTION() #define mp_hal_quiet_timing_exit(irq_state) MICROPY_END_ATOMIC_SECTION(irq_state) // Wake up the main task if it is sleeping void mp_hal_wake_main_task_from_isr(void); // C-level pin HAL #include "py/obj.h" #include "driver/gpio.h" #define MP_HAL_PIN_FMT "%u" #define mp_hal_pin_obj_t gpio_num_t mp_hal_pin_obj_t machine_pin_get_id(mp_obj_t pin_in); #define mp_hal_get_pin_obj(o) machine_pin_get_id(o) #define mp_obj_get_pin(o) machine_pin_get_id(o) // legacy name; only to support esp8266/modonewire #define mp_hal_pin_name(p) (p) static inline void mp_hal_pin_input(mp_hal_pin_obj_t pin) { gpio_pad_select_gpio(pin); gpio_set_direction(pin, GPIO_MODE_INPUT); } static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) { gpio_pad_select_gpio(pin); gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT); } static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { gpio_pad_select_gpio(pin); gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT_OD); } static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) { gpio_set_level(pin, 0); } static inline void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) { gpio_set_level(pin, 1); } static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) { return gpio_get_level(pin); } static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) { gpio_set_level(pin, v); } #endif // INCLUDED_MPHALPORT_H micropython-1.12/ports/esp32/mpthreadport.c000066400000000000000000000166351357706137100210150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd * Copyright (c) 2017 Pycom Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "stdio.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mpthread.h" #include "py/mphal.h" #include "mpthreadport.h" #include "esp_task.h" #if !MICROPY_ESP_IDF_4 #include "freertos/semphr.h" #endif #if MICROPY_PY_THREAD #define MP_THREAD_MIN_STACK_SIZE (4 * 1024) #define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024) #define MP_THREAD_PRIORITY (ESP_TASK_PRIO_MIN + 1) // this structure forms a linked list, one node per active thread typedef struct _thread_t { TaskHandle_t id; // system id of thread int ready; // whether the thread is ready and running void *arg; // thread Python args, a GC root pointer void *stack; // pointer to the stack size_t stack_len; // number of words in the stack struct _thread_t *next; } thread_t; // the mutex controls access to the linked list STATIC mp_thread_mutex_t thread_mutex; STATIC thread_t thread_entry0; STATIC thread_t *thread = NULL; // root pointer, handled by mp_thread_gc_others void mp_thread_init(void *stack, uint32_t stack_len) { mp_thread_set_state(&mp_state_ctx.thread); // create the first entry in the linked list of all threads thread = &thread_entry0; thread->id = xTaskGetCurrentTaskHandle(); thread->ready = 1; thread->arg = NULL; thread->stack = stack; thread->stack_len = stack_len; thread->next = NULL; mp_thread_mutex_init(&thread_mutex); } void mp_thread_gc_others(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { gc_collect_root((void**)&th, 1); gc_collect_root(&th->arg, 1); // probably not needed if (th->id == xTaskGetCurrentTaskHandle()) { continue; } if (!th->ready) { continue; } gc_collect_root(th->stack, th->stack_len); // probably not needed } mp_thread_mutex_unlock(&thread_mutex); } mp_state_thread_t *mp_thread_get_state(void) { return pvTaskGetThreadLocalStoragePointer(NULL, 1); } void mp_thread_set_state(void *state) { vTaskSetThreadLocalStoragePointer(NULL, 1, state); } void mp_thread_start(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == xTaskGetCurrentTaskHandle()) { th->ready = 1; break; } } mp_thread_mutex_unlock(&thread_mutex); } STATIC void *(*ext_thread_entry)(void*) = NULL; STATIC void freertos_entry(void *arg) { if (ext_thread_entry) { ext_thread_entry(arg); } vTaskDelete(NULL); for (;;); } void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, int priority, char *name) { // store thread entry function into a global variable so we can access it ext_thread_entry = entry; if (*stack_size == 0) { *stack_size = MP_THREAD_DEFAULT_STACK_SIZE; // default stack size } else if (*stack_size < MP_THREAD_MIN_STACK_SIZE) { *stack_size = MP_THREAD_MIN_STACK_SIZE; // minimum stack size } // Allocate linked-list node (must be outside thread_mutex lock) thread_t *th = m_new_obj(thread_t); mp_thread_mutex_lock(&thread_mutex, 1); // create thread BaseType_t result = xTaskCreatePinnedToCore(freertos_entry, name, *stack_size / sizeof(StackType_t), arg, priority, &th->id, MP_TASK_COREID); if (result != pdPASS) { mp_thread_mutex_unlock(&thread_mutex); mp_raise_msg(&mp_type_OSError, "can't create thread"); } // adjust the stack_size to provide room to recover from hitting the limit *stack_size -= 1024; // add thread to linked list of all threads th->ready = 0; th->arg = arg; th->stack = pxTaskGetStackStart(th->id); th->stack_len = *stack_size / sizeof(StackType_t); th->next = thread; thread = th; mp_thread_mutex_unlock(&thread_mutex); } void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread"); } void mp_thread_finish(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == xTaskGetCurrentTaskHandle()) { th->ready = 0; break; } } mp_thread_mutex_unlock(&thread_mutex); } void vPortCleanUpTCB(void *tcb) { if (thread == NULL) { // threading not yet initialised return; } thread_t *prev = NULL; mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; prev = th, th = th->next) { // unlink the node from the list if ((void*)th->id == tcb) { if (prev != NULL) { prev->next = th->next; } else { // move the start pointer thread = th->next; } // explicitly release all its memory m_del(thread_t, th, 1); break; } } mp_thread_mutex_unlock(&thread_mutex); } void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer); } int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { return (pdTRUE == xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0)); } void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { xSemaphoreGive(mutex->handle); } void mp_thread_deinit(void) { for (;;) { // Find a task to delete TaskHandle_t id = NULL; mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { // Don't delete the current task if (th->id != xTaskGetCurrentTaskHandle()) { id = th->id; break; } } mp_thread_mutex_unlock(&thread_mutex); if (id == NULL) { // No tasks left to delete break; } else { // Call FreeRTOS to delete the task (it will call vPortCleanUpTCB) vTaskDelete(id); } } } #else void vPortCleanUpTCB(void *tcb) { } #endif // MICROPY_PY_THREAD micropython-1.12/ports/esp32/mpthreadport.h000066400000000000000000000033601357706137100210110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd * Copyright (c) 2017 Pycom Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_ESP32_MPTHREADPORT_H #define MICROPY_INCLUDED_ESP32_MPTHREADPORT_H #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" typedef struct _mp_thread_mutex_t { SemaphoreHandle_t handle; StaticSemaphore_t buffer; } mp_thread_mutex_t; void mp_thread_init(void *stack, uint32_t stack_len); void mp_thread_gc_others(void); void mp_thread_deinit(void); #endif // MICROPY_INCLUDED_ESP32_MPTHREADPORT_H micropython-1.12/ports/esp32/network_lan.c000066400000000000000000000173051357706137100206220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 "Eric Poulsen" * * Based on the ESP IDF example code which is Public Domain / CC0 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #if !MICROPY_ESP_IDF_4 #include "py/runtime.h" #include "py/mphal.h" #include "eth_phy/phy.h" #include "eth_phy/phy_tlk110.h" #include "eth_phy/phy_lan8720.h" #include "tcpip_adapter.h" #include "modnetwork.h" typedef struct _lan_if_obj_t { mp_obj_base_t base; int if_id; // MUST BE FIRST to match wlan_if_obj_t bool initialized; bool active; uint8_t mdc_pin; uint8_t mdio_pin; int8_t phy_power_pin; uint8_t phy_addr; uint8_t phy_type; eth_phy_check_link_func link_func; eth_phy_power_enable_func power_func; } lan_if_obj_t; const mp_obj_type_t lan_if_type; STATIC lan_if_obj_t lan_obj = {{&lan_if_type}, ESP_IF_ETH, false, false}; STATIC void phy_power_enable(bool enable) { lan_if_obj_t* self = &lan_obj; if (self->phy_power_pin != -1) { if (!enable) { // Do the PHY-specific power_enable(false) function before powering down self->power_func(false); } gpio_pad_select_gpio(self->phy_power_pin); gpio_set_direction(self->phy_power_pin, GPIO_MODE_OUTPUT); if (enable) { gpio_set_level(self->phy_power_pin, 1); } else { gpio_set_level(self->phy_power_pin, 0); } // Allow the power up/down to take effect, min 300us vTaskDelay(1); if (enable) { // Run the PHY-specific power on operations now the PHY has power self->power_func(true); } } } STATIC void init_lan_rmii() { lan_if_obj_t* self = &lan_obj; phy_rmii_configure_data_interface_pins(); phy_rmii_smi_configure_pins(self->mdc_pin, self->mdio_pin); } STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { lan_if_obj_t* self = &lan_obj; if (self->initialized) { return MP_OBJ_FROM_PTR(&lan_obj); } enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type, ARG_clock_mode }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_clock_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_id].u_obj != mp_const_none) { if (mp_obj_get_int(args[ARG_id].u_obj) != 0) { mp_raise_ValueError("invalid LAN interface identifier"); } } self->mdc_pin = machine_pin_get_id(args[ARG_mdc].u_obj); self->mdio_pin = machine_pin_get_id(args[ARG_mdio].u_obj); self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[ARG_power].u_obj); if (args[ARG_phy_addr].u_int < 0x00 || args[ARG_phy_addr].u_int > 0x1f) { mp_raise_ValueError("invalid phy address"); } if (args[ARG_phy_type].u_int != PHY_LAN8720 && args[ARG_phy_type].u_int != PHY_TLK110) { mp_raise_ValueError("invalid phy type"); } if (args[ARG_clock_mode].u_int != -1 && args[ARG_clock_mode].u_int != ETH_CLOCK_GPIO0_IN && // Disabled due ESP-IDF (see modnetwork.c note) //args[ARG_clock_mode].u_int != ETH_CLOCK_GPIO0_OUT && args[ARG_clock_mode].u_int != ETH_CLOCK_GPIO16_OUT && args[ARG_clock_mode].u_int != ETH_CLOCK_GPIO17_OUT) { mp_raise_ValueError("invalid clock mode"); } eth_config_t config; switch (args[ARG_phy_type].u_int) { case PHY_TLK110: config = phy_tlk110_default_ethernet_config; break; case PHY_LAN8720: config = phy_lan8720_default_ethernet_config; break; } self->link_func = config.phy_check_link; // Replace default power func with our own self->power_func = config.phy_power_enable; config.phy_power_enable = phy_power_enable; config.phy_addr = args[ARG_phy_addr].u_int; config.gpio_config = init_lan_rmii; config.tcpip_input = tcpip_adapter_eth_input; if (args[ARG_clock_mode].u_int != -1) { config.clock_mode = args[ARG_clock_mode].u_int; } if (esp_eth_init(&config) == ESP_OK) { self->active = false; self->initialized = true; } else { mp_raise_msg(&mp_type_OSError, "esp_eth_init() failed"); } return MP_OBJ_FROM_PTR(&lan_obj); } MP_DEFINE_CONST_FUN_OBJ_KW(get_lan_obj, 0, get_lan); STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) { lan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args > 1) { if (mp_obj_is_true(args[1])) { self->active = (esp_eth_enable() == ESP_OK); if (!self->active) { mp_raise_msg(&mp_type_OSError, "ethernet enable failed"); } } else { self->active = !(esp_eth_disable() == ESP_OK); if (self->active) { mp_raise_msg(&mp_type_OSError, "ethernet disable failed"); } } } return mp_obj_new_bool(self->active); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lan_active_obj, 1, 2, lan_active); STATIC mp_obj_t lan_status(mp_obj_t self_in) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_status_obj, lan_status); STATIC mp_obj_t lan_isconnected(mp_obj_t self_in) { lan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); return self->active ? mp_obj_new_bool(self->link_func()) : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_isconnected_obj, lan_isconnected); STATIC const mp_rom_map_elem_t lan_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&lan_active_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&lan_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lan_status_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&esp_config_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) }, }; STATIC MP_DEFINE_CONST_DICT(lan_if_locals_dict, lan_if_locals_dict_table); const mp_obj_type_t lan_if_type = { { &mp_type_type }, .name = MP_QSTR_LAN, .locals_dict = (mp_obj_dict_t*)&lan_if_locals_dict, }; #endif // !MICROPY_ESP_IDF_4 micropython-1.12/ports/esp32/network_ppp.c000066400000000000000000000236101357706137100206430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 "Eric Poulsen" * * Based on the ESP IDF example code which is Public Domain / CC0 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #if !MICROPY_ESP_IDF_4 #include "py/runtime.h" #include "py/mphal.h" #include "py/objtype.h" #include "py/stream.h" #include "netutils.h" #include "modmachine.h" #include "netif/ppp/ppp.h" #include "netif/ppp/pppos.h" #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/sys.h" #include "lwip/netdb.h" #include "lwip/dns.h" #include "netif/ppp/pppapi.h" #define PPP_CLOSE_TIMEOUT_MS (4000) typedef struct _ppp_if_obj_t { mp_obj_base_t base; bool active; bool connected; volatile bool clean_close; ppp_pcb *pcb; mp_obj_t stream; SemaphoreHandle_t inactiveWaitSem; volatile TaskHandle_t client_task_handle; struct netif pppif; } ppp_if_obj_t; const mp_obj_type_t ppp_if_type; static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) { ppp_if_obj_t* self = ctx; struct netif *pppif = ppp_netif(self->pcb); switch (err_code) { case PPPERR_NONE: self->connected = (pppif->ip_addr.u_addr.ip4.addr != 0); break; case PPPERR_USER: self->clean_close = true; break; case PPPERR_CONNECT: self->connected = false; break; default: break; } } STATIC mp_obj_t ppp_make_new(mp_obj_t stream) { mp_get_stream_raise(stream, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE); ppp_if_obj_t *self = m_new_obj_with_finaliser(ppp_if_obj_t); self->base.type = &ppp_if_type; self->stream = stream; self->active = false; self->connected = false; self->clean_close = false; self->client_task_handle = NULL; return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_1(ppp_make_new_obj, ppp_make_new); static u32_t ppp_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) { ppp_if_obj_t *self = ctx; int err; return mp_stream_rw(self->stream, data, len, &err, MP_STREAM_RW_WRITE); } static void pppos_client_task(void *self_in) { ppp_if_obj_t *self = (ppp_if_obj_t*)self_in; uint8_t buf[256]; while (ulTaskNotifyTake(pdTRUE, 0) == 0) { int err; int len = mp_stream_rw(self->stream, buf, sizeof(buf), &err, 0); if (len > 0) { pppos_input_tcpip(self->pcb, (u8_t*)buf, len); } } self->client_task_handle = NULL; vTaskDelete(NULL); } STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { ppp_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args > 1) { if (mp_obj_is_true(args[1])) { if (self->active) { return mp_const_true; } self->pcb = pppapi_pppos_create(&self->pppif, ppp_output_callback, ppp_status_cb, self); if (self->pcb == NULL) { mp_raise_msg(&mp_type_RuntimeError, "init failed"); } self->active = true; } else { if (!self->active) { return mp_const_false; } if (self->client_task_handle != NULL) { // is connecting or connected? // Wait for PPPERR_USER, with timeout pppapi_close(self->pcb, 0); uint32_t t0 = mp_hal_ticks_ms(); while (!self->clean_close && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { mp_hal_delay_ms(10); } // Shutdown task xTaskNotifyGive(self->client_task_handle); t0 = mp_hal_ticks_ms(); while (self->client_task_handle != NULL && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { mp_hal_delay_ms(10); } } // Release PPP pppapi_free(self->pcb); self->pcb = NULL; self->active = false; self->connected = false; self->clean_close = false; } } return mp_obj_new_bool(self->active); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ppp_active_obj, 1, 2, ppp_active); STATIC mp_obj_t ppp_connect_py(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { enum { ARG_authmode, ARG_username, ARG_password }; static const mp_arg_t allowed_args[] = { { MP_QSTR_authmode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PPPAUTHTYPE_NONE} }, { MP_QSTR_username, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_password, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args); ppp_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (!self->active) { mp_raise_msg(&mp_type_OSError, "must be active"); } if (self->client_task_handle != NULL) { mp_raise_OSError(MP_EALREADY); } switch (parsed_args[ARG_authmode].u_int) { case PPPAUTHTYPE_NONE: case PPPAUTHTYPE_PAP: case PPPAUTHTYPE_CHAP: break; default: mp_raise_msg(&mp_type_ValueError, "invalid auth"); } if (parsed_args[ARG_authmode].u_int != PPPAUTHTYPE_NONE) { const char* username_str = mp_obj_str_get_str(parsed_args[ARG_username].u_obj); const char* password_str = mp_obj_str_get_str(parsed_args[ARG_password].u_obj); pppapi_set_auth(self->pcb, parsed_args[ARG_authmode].u_int, username_str, password_str); } if (pppapi_set_default(self->pcb) != ESP_OK) { mp_raise_msg(&mp_type_OSError, "set default failed"); } ppp_set_usepeerdns(self->pcb, true); if (pppapi_connect(self->pcb, 0) != ESP_OK) { mp_raise_msg(&mp_type_OSError, "connect failed"); } if (xTaskCreatePinnedToCore(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle, MP_TASK_COREID) != pdPASS) { mp_raise_msg(&mp_type_RuntimeError, "failed to create worker task"); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(ppp_connect_obj, 1, ppp_connect_py); STATIC mp_obj_t ppp_delete(mp_obj_t self_in) { ppp_if_obj_t* self = MP_OBJ_TO_PTR(self_in); mp_obj_t args[] = {self, mp_const_false}; ppp_active(2, args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(ppp_delete_obj, ppp_delete); STATIC mp_obj_t ppp_ifconfig(size_t n_args, const mp_obj_t *args) { ppp_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); ip_addr_t dns; if (n_args == 1) { // get if (self->pcb != NULL) { dns = dns_getserver(0); struct netif *pppif = ppp_netif(self->pcb); mp_obj_t tuple[4] = { netutils_format_ipv4_addr((uint8_t*)&pppif->ip_addr, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&pppif->gw, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&pppif->netmask, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&dns, NETUTILS_BIG), }; return mp_obj_new_tuple(4, tuple); } else { mp_obj_t tuple[4] = { mp_const_none, mp_const_none, mp_const_none, mp_const_none }; return mp_obj_new_tuple(4, tuple); } } else { mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 4, &items); netutils_parse_ipv4_addr(items[3], (uint8_t*)&dns.u_addr.ip4, NETUTILS_BIG); dns_setserver(0, &dns); return mp_const_none; } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ppp_ifconfig_obj, 1, 2, ppp_ifconfig); STATIC mp_obj_t ppp_status(mp_obj_t self_in) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ppp_status_obj, ppp_status); STATIC mp_obj_t ppp_isconnected(mp_obj_t self_in) { ppp_if_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(self->connected); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ppp_isconnected_obj, ppp_isconnected); STATIC const mp_rom_map_elem_t ppp_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&ppp_active_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&ppp_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&ppp_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&ppp_status_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&ppp_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&ppp_delete_obj) }, { MP_ROM_QSTR(MP_QSTR_AUTH_NONE), MP_ROM_INT(PPPAUTHTYPE_NONE) }, { MP_ROM_QSTR(MP_QSTR_AUTH_PAP), MP_ROM_INT(PPPAUTHTYPE_PAP) }, { MP_ROM_QSTR(MP_QSTR_AUTH_CHAP), MP_ROM_INT(PPPAUTHTYPE_CHAP) }, }; STATIC MP_DEFINE_CONST_DICT(ppp_if_locals_dict, ppp_if_locals_dict_table); const mp_obj_type_t ppp_if_type = { { &mp_type_type }, .name = MP_QSTR_PPP, .locals_dict = (mp_obj_dict_t*)&ppp_if_locals_dict, }; #endif // !MICROPY_ESP_IDF_4 micropython-1.12/ports/esp32/nimble.c000066400000000000000000000036201357706137100175400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Jim Mussared * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE #include "esp_nimble_hci.h" #include "nimble/nimble_port.h" #include "nimble/nimble_port_freertos.h" STATIC void ble_host_task(void *param) { nimble_port_run(); //This function will return only when nimble_port_stop() is executed. nimble_port_freertos_deinit(); } void mp_bluetooth_nimble_port_preinit(void) { esp_nimble_hci_and_controller_init(); } void mp_bluetooth_nimble_port_postinit(void) { nimble_port_freertos_init(ble_host_task); } void mp_bluetooth_nimble_port_deinit(void) { nimble_port_stop(); } void mp_bluetooth_nimble_port_start(void) { } #endif micropython-1.12/ports/esp32/partitions-2MiB.csv000066400000000000000000000005301357706137100215630ustar00rootroot00000000000000# Name, Type, SubType, Offset, Size, Flags # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 0x110000, vfs, data, fat, 0x120000, 0xA0000, micropython-1.12/ports/esp32/partitions.csv000066400000000000000000000005131357706137100210350ustar00rootroot00000000000000# Name, Type, SubType, Offset, Size, Flags # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 0x180000, vfs, data, fat, 0x200000, 0x200000, micropython-1.12/ports/esp32/qstrdefsport.h000066400000000000000000000024651357706137100210450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // qstrs specific to this port, only needed if they aren't auto-generated // Entries for sys.path Q(/lib) micropython-1.12/ports/esp32/uart.c000066400000000000000000000047331357706137100172530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "driver/uart.h" #include "py/mpstate.h" #include "py/mphal.h" STATIC void uart_irq_handler(void *arg); void uart_init(void) { uart_isr_handle_t handle; uart_isr_register(UART_NUM_0, uart_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &handle); uart_enable_rx_intr(UART_NUM_0); } // all code executed in ISR must be in IRAM, and any const data must be in DRAM STATIC void IRAM_ATTR uart_irq_handler(void *arg) { volatile uart_dev_t *uart = &UART0; uart->int_clr.rxfifo_full = 1; uart->int_clr.frm_err = 1; uart->int_clr.rxfifo_tout = 1; while (uart->status.rxfifo_cnt) { uint8_t c = uart->fifo.rw_byte; if (c == mp_interrupt_char) { // inline version of mp_keyboard_interrupt(); MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); #if MICROPY_ENABLE_SCHEDULER if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } #endif } else { // this is an inline function so will be in IRAM ringbuf_put(&stdin_ringbuf, c); } } } micropython-1.12/ports/esp32/uart.h000066400000000000000000000026431357706137100172560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_ESP32_UART_H #define MICROPY_INCLUDED_ESP32_UART_H void uart_init(void); #endif // MICROPY_INCLUDED_ESP32_UART_H micropython-1.12/ports/esp8266/000077500000000000000000000000001357706137100163065ustar00rootroot00000000000000micropython-1.12/ports/esp8266/Makefile000066400000000000000000000124641357706137100177550ustar00rootroot00000000000000# Select the board to build for: if not given on the command line, # then default to GENERIC. BOARD ?= GENERIC # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD) BOARD_DIR ?= boards/$(BOARD) ifeq ($(wildcard $(BOARD_DIR)/.),) $(error Invalid BOARD specified: $(BOARD_DIR)) endif include ../../py/mkenv.mk # Optional -include $(BOARD_DIR)/mpconfigboard.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h MICROPY_PY_USSL = 1 MICROPY_SSL_AXTLS = 1 AXTLS_DEFS_EXTRA = -Dabort=abort_ -DRT_MAX_PLAIN_LENGTH=1024 -DRT_EXTRA=4096 MICROPY_PY_BTREE ?= 1 BTREE_DEFS_EXTRA = -DDEFPSIZE=1024 -DMINCACHE=3 FROZEN_MANIFEST ?= boards/manifest.py FROZEN_DIR ?= FROZEN_MPY_DIR ?= # include py core make definitions include $(TOP)/py/py.mk GIT_SUBMODULES = lib/axtls lib/berkeley-db-1.xx FWBIN = $(BUILD)/firmware-combined.bin PORT ?= /dev/ttyACM0 BAUD ?= 115200 FLASH_MODE ?= qio FLASH_SIZE ?= detect CROSS_COMPILE = xtensa-lx106-elf- ESP_SDK = $(shell $(CC) -print-sysroot)/usr INC += -I. INC += -I$(TOP) INC += -I$(BUILD) INC += -I$(ESP_SDK)/include # UART for "os" messages. 0 is normal UART as used by MicroPython REPL, # 1 is debug UART (tx only), -1 to disable. UART_OS = 0 CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \ -D__ets__ -DICACHE_FLASH \ -fno-inline-functions \ -Wl,-EL -mlongcalls -mtext-section-literals -mforce-l32 \ -DLWIP_OPEN_SRC CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \ $(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR) LD_FILES ?= boards/esp8266.ld LDFLAGS = -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD) LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc # Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -g COPT = -O0 else CFLAGS += -fdata-sections -ffunction-sections COPT += -Os -DNDEBUG LDFLAGS += --gc-sections endif # Options for mpy-cross MPY_CROSS_FLAGS += -march=xtensa SRC_C = \ strtoll.c \ main.c \ help.c \ esp_mphal.c \ esp_init_data.c \ gccollect.c \ lexerstr32.c \ uart.c \ esppwm.c \ espneopixel.c \ espapa102.c \ intr.c \ modpyb.c \ modmachine.c \ machine_pin.c \ machine_pwm.c \ machine_rtc.c \ machine_adc.c \ machine_uart.c \ machine_wdt.c \ machine_hspi.c \ modesp.c \ modnetwork.c \ modutime.c \ moduos.c \ ets_alt_task.c \ fatfs_port.c \ posix_helpers.c \ hspi.c \ $(wildcard $(BOARD_DIR)/*.c) \ $(SRC_MOD) EXTMOD_SRC_C = $(addprefix extmod/,\ modlwip.c \ modonewire.c \ ) LIB_SRC_C = $(addprefix lib/,\ libc/string0.c \ libm/math.c \ libm/fmodf.c \ libm/nearbyintf.c \ libm/ef_sqrt.c \ libm/kf_rem_pio2.c \ libm/kf_sin.c \ libm/kf_cos.c \ libm/kf_tan.c \ libm/ef_rem_pio2.c \ libm/sf_sin.c \ libm/sf_cos.c \ libm/sf_tan.c \ libm/sf_frexp.c \ libm/sf_modf.c \ libm/sf_ldexp.c \ libm/asinfacosf.c \ libm/atanf.c \ libm/atan2f.c \ mp-readline/readline.c \ netutils/netutils.c \ timeutils/timeutils.c \ utils/pyexec.c \ utils/interrupt_char.c \ utils/sys_stdio_mphal.c \ ) DRIVERS_SRC_C = $(addprefix drivers/,\ bus/softspi.c \ dht/dht.c \ ) SRC_S = \ gchelper.s \ OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(LIB_SRC_C) $(DRIVERS_SRC_C) # Append any auto-generated sources that are needed by sources listed in SRC_QSTR SRC_QSTR_AUTO_DEPS += all: $(FWBIN) CONFVARS_FILE = $(BUILD)/confvars ifeq ($(wildcard $(CONFVARS_FILE)),) $(shell $(MKDIR) -p $(BUILD)) $(shell echo $(FROZEN_MANIFEST) $(UART_OS) > $(CONFVARS_FILE)) else ifneq ($(shell cat $(CONFVARS_FILE)), $(FROZEN_MANIFEST) $(UART_OS)) $(shell echo $(FROZEN_MANIFEST) $(UART_OS) > $(CONFVARS_FILE)) endif $(BUILD)/uart.o: $(CONFVARS_FILE) FROZEN_EXTRA_DEPS = $(CONFVARS_FILE) ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),) CFLAGS += -DMICROPY_MODULE_FROZEN_MPY CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool endif ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),) CFLAGS += -DMICROPY_MODULE_FROZEN_STR endif .PHONY: deploy deploy: $(BUILD)/firmware-combined.bin $(ECHO) "Writing $< to the board" $(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --verify --flash_size=$(FLASH_SIZE) --flash_mode=$(FLASH_MODE) 0 $< erase: $(ECHO) "Erase flash" $(Q)esptool.py --port $(PORT) --baud $(BAUD) erase_flash reset: echo -e "\r\nimport machine; machine.reset()\r\n" >$(PORT) $(FWBIN): $(BUILD)/firmware.elf $(ECHO) "Create $@" $(Q)esptool.py elf2image $^ $(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x[0-5][1-f]000.bin $@ $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ ota: rm -f $(BUILD)/firmware.elf $(BUILD)/firmware.elf*.bin $(MAKE) LD_FILES=boards/esp8266_ota.ld FWBIN=$(BUILD)/firmware-ota.bin include $(TOP)/py/mkrules.mk clean-modules: git clean -f -d modules rm -f $(BUILD)/frozen*.c micropython-1.12/ports/esp8266/README.md000066400000000000000000000132361357706137100175720ustar00rootroot00000000000000MicroPython port to ESP8266 =========================== This is an experimental port of MicroPython for the WiFi modules based on Espressif ESP8266 chip. WARNING: The port is experimental and many APIs are subject to change. Supported features include: - REPL (Python prompt) over UART0. - Garbage collector, exceptions. - Unicode support. - Builtin modules: gc, array, collections, io, struct, sys, esp, network, many more. - Arbitrary-precision long integers and 30-bit precision floats. - WiFi support. - Sockets using modlwip. - GPIO and bit-banging I2C, SPI support. - 1-Wire and WS2812 (aka Neopixel) protocols support. - Internal filesystem using the flash. - WebREPL over WiFi from a browser (clients at https://github.com/micropython/webrepl). - Modules for HTTP, MQTT, many other formats and protocols via https://github.com/micropython/micropython-lib . Work-in-progress documentation is available at http://docs.micropython.org/en/latest/esp8266/ . Build instructions ------------------ The tool chain required for the build is the OpenSource ESP SDK, which can be found at . Clone this repository and run `make` in its directory to build and install the SDK locally. Make sure to add toolchain bin directory to your PATH. Read esp-open-sdk's README for additional important information on toolchain setup. Add the external dependencies to the MicroPython repository checkout: ```bash $ git submodule update --init ``` See the README in the repository root for more information about external dependencies. The MicroPython cross-compiler must be built to pre-compile some of the built-in scripts to bytecode. This can be done using: ```bash $ make -C mpy-cross ``` Then, to build MicroPython for the ESP8266, just run: ```bash $ cd ports/esp8266 $ make ``` This will produce binary images in the `build-GENERIC/` subdirectory. If you install MicroPython to your module for the first time, or after installing any other firmware, you should erase flash completely: ```bash $ esptool.py --port /dev/ttyXXX erase_flash ``` Erase flash also as a troubleshooting measure, if a module doesn't behave as expected. To flash MicroPython image to your ESP8266, use: ```bash $ make deploy ``` This will use the `esptool.py` script to download the images. You must have your ESP module in the bootloader mode, and connected to a serial port on your PC. The default serial port is `/dev/ttyACM0`, flash mode is `qio` and flash size is `detect` (auto-detect based on Flash ID). To specify other values, use, eg (note that flash size is in megabits): ```bash $ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=32m deploy ``` The image produced is `build-GENERIC/firmware-combined.bin`, to be flashed at 0x00000. The default board definition is the directory `boards/GENERIC`. For a custom configuration you can define your own board in the directory `boards/`. The `BOARD` variable can be set on the make command line, for example: ```bash $ make BOARD=GENERIC_512K ``` __512KB FlashROM version__ The normal build described above requires modules with at least 1MB of FlashROM onboard. There's a special configuration for 512KB modules, which can be built with `make BOARD=GENERIC_512K`. This configuration is highly limited, lacks filesystem support, WebREPL, and has many other features disabled. It's mostly suitable for advanced users who are interested to fine-tune options to achieve a required setup. If you are an end user, please consider using a module with at least 1MB of FlashROM. First start ----------- Be sure to change ESP8266's WiFi access point password ASAP, see below. __Serial prompt__ You can access the REPL (Python prompt) over UART (the same as used for programming). - Baudrate: 115200 Run `help()` for some basic information. __WiFi__ Initially, the device configures itself as a WiFi access point (AP). - ESSID: MicroPython-xxxxxx (x’s are replaced with part of the MAC address). - Password: micropythoN (note the upper-case N). - IP address of the board: 192.168.4.1. - DHCP-server is activated. - Please be sure to change the password to something non-guessable immediately. `help()` gives information how. __WebREPL__ Python prompt over WiFi, connecting through a browser. - Hosted at http://micropython.org/webrepl. - GitHub repository https://github.com/micropython/webrepl. Please follow the instructions there. __upip__ The ESP8266 port comes with builtin `upip` package manager, which can be used to install additional modules (see the main README for more information): ``` >>> import upip >>> upip.install("micropython-pystone_lowmem") [...] >>> import pystone_lowmem >>> pystone_lowmem.main() ``` Downloading and installing packages may requite a lot of free memory, if you get an error, retry immediately after the hard reset. Documentation ------------- More detailed documentation and instructions can be found at http://docs.micropython.org/en/latest/esp8266/ , which includes Quick Reference, Tutorial, General Information related to ESP8266 port, and to MicroPython in general. Troubleshooting --------------- While the port is in beta, it's known to be generally stable. If you experience strange bootloops, crashes, lockups, here's a list to check against: - You didn't erase flash before programming MicroPython firmware. - Firmware can be occasionally flashed incorrectly. Just retry. Recent esptool.py versions have --verify option. - Power supply you use doesn't provide enough power for ESP8266 or isn't stable enough. - A module/flash may be defective (not unheard of for cheap modules). Please consult dedicated ESP8266 forums/resources for hardware-related problems. Additional information may be available by the documentation links above. micropython-1.12/ports/esp8266/boards/000077500000000000000000000000001357706137100175605ustar00rootroot00000000000000micropython-1.12/ports/esp8266/boards/GENERIC/000077500000000000000000000000001357706137100206345ustar00rootroot00000000000000micropython-1.12/ports/esp8266/boards/GENERIC/mpconfigboard.h000066400000000000000000000013441357706137100236210ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "ESP module" #define MICROPY_HW_MCU_NAME "ESP8266" #define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_XTENSA (1) #define MICROPY_EMIT_INLINE_XTENSA (1) #define MICROPY_DEBUG_PRINTERS (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) #define MICROPY_READER_VFS (MICROPY_VFS) #define MICROPY_VFS (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_SYS_STDIO_BUFFER (1) #define MICROPY_PY_URE_SUB (1) #define MICROPY_PY_UCRYPTOLIB (1) #define MICROPY_PY_FRAMEBUF (1) micropython-1.12/ports/esp8266/boards/GENERIC/mpconfigboard.mk000066400000000000000000000000241357706137100237730ustar00rootroot00000000000000MICROPY_VFS_FAT = 1 micropython-1.12/ports/esp8266/boards/GENERIC_512K/000077500000000000000000000000001357706137100213365ustar00rootroot00000000000000micropython-1.12/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h000066400000000000000000000002411357706137100243160ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "ESP module (512K)" #define MICROPY_HW_MCU_NAME "ESP8266" #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) micropython-1.12/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk000066400000000000000000000001131357706137100244740ustar00rootroot00000000000000MICROPY_PY_BTREE = 0 MICROPY_VFS_FAT = 0 LD_FILES = boards/esp8266_512k.ld micropython-1.12/ports/esp8266/boards/eagle.rom.addr.v6.ld000066400000000000000000000341021357706137100232150ustar00rootroot00000000000000PROVIDE ( Cache_Read_Disable = 0x400047f0 ); PROVIDE ( Cache_Read_Enable = 0x40004678 ); PROVIDE ( FilePacketSendReqMsgProc = 0x400035a0 ); PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x4000368c ); PROVIDE ( FlashDwnLdStartMsgProc = 0x40003538 ); PROVIDE ( FlashDwnLdStopReqMsgProc = 0x40003658 ); PROVIDE ( GetUartDevice = 0x40003f4c ); PROVIDE ( MD5Final = 0x40009900 ); PROVIDE ( MD5Init = 0x40009818 ); PROVIDE ( MD5Update = 0x40009834 ); PROVIDE ( MemDwnLdStartMsgProc = 0x400036c4 ); PROVIDE ( MemDwnLdStopReqMsgProc = 0x4000377c ); PROVIDE ( MemPacketSendReqMsgProc = 0x400036f0 ); PROVIDE ( RcvMsg = 0x40003eac ); PROVIDE ( SHA1Final = 0x4000b648 ); PROVIDE ( SHA1Init = 0x4000b584 ); PROVIDE ( SHA1Transform = 0x4000a364 ); PROVIDE ( SHA1Update = 0x4000b5a8 ); PROVIDE ( SPI_read_status = 0x400043c8 ); PROVIDE ( SPI_write_status = 0x40004400 ); PROVIDE ( SPI_write_enable = 0x4000443c ); PROVIDE ( Wait_SPI_Idle = 0x4000448c ); PROVIDE ( Enable_QMode = 0x400044c0 ); PROVIDE ( SPIEraseArea = 0x40004b44 ); PROVIDE ( SPIEraseBlock = 0x400049b4 ); PROVIDE ( SPIEraseChip = 0x40004984 ); PROVIDE ( SPIEraseSector = 0x40004a00 ); PROVIDE ( SPILock = 0x400048a8 ); PROVIDE ( SPIParamCfg = 0x40004c2c ); PROVIDE ( SPIRead = 0x40004b1c ); PROVIDE ( SPIReadModeCnfig = 0x400048ec ); PROVIDE ( SPIUnlock = 0x40004878 ); PROVIDE ( SPIWrite = 0x40004a4c ); PROVIDE ( SelectSpiFunction = 0x40003f58 ); PROVIDE ( SendMsg = 0x40003cf4 ); PROVIDE ( UartConnCheck = 0x40003230 ); PROVIDE ( UartConnectProc = 0x400037a0 ); PROVIDE ( UartDwnLdProc = 0x40003368 ); PROVIDE ( UartGetCmdLn = 0x40003ef4 ); PROVIDE ( UartRegReadProc = 0x4000381c ); PROVIDE ( UartRegWriteProc = 0x400037ac ); PROVIDE ( UartRxString = 0x40003c30 ); PROVIDE ( Uart_Init = 0x40003a14 ); PROVIDE ( _DebugExceptionVector = 0x40000010 ); PROVIDE ( _DoubleExceptionVector = 0x40000070 ); PROVIDE ( _KernelExceptionVector = 0x40000030 ); PROVIDE ( _NMIExceptionVector = 0x40000020 ); PROVIDE ( _ResetHandler = 0x400000a4 ); PROVIDE ( _ResetVector = 0x40000080 ); PROVIDE ( _UserExceptionVector = 0x40000050 ); __adddf3 = 0x4000c538; __addsf3 = 0x4000c180; __divdf3 = 0x4000cb94; __divdi3 = 0x4000ce60; __divsi3 = 0x4000dc88; __extendsfdf2 = 0x4000cdfc; __fixdfsi = 0x4000ccb8; __fixunsdfsi = 0x4000cd00; __fixunssfsi = 0x4000c4c4; __floatsidf = 0x4000e2f0; __floatsisf = 0x4000e2ac; __floatunsidf = 0x4000e2e8; __floatunsisf = 0x4000e2a4; __muldf3 = 0x4000c8f0; __muldi3 = 0x40000650; __mulsf3 = 0x4000c3dc; __subdf3 = 0x4000c688; __subsf3 = 0x4000c268; __truncdfsf2 = 0x4000cd5c; __udivdi3 = 0x4000d310; __udivsi3 = 0x4000e21c; __umoddi3 = 0x4000d770; __umodsi3 = 0x4000e268; __umulsidi3 = 0x4000dcf0; PROVIDE ( _rom_store = 0x4000e388 ); PROVIDE ( _rom_store_table = 0x4000e328 ); PROVIDE ( _start = 0x4000042c ); PROVIDE ( _xtos_alloca_handler = 0x4000dbe0 ); PROVIDE ( _xtos_c_wrapper_handler = 0x40000598 ); PROVIDE ( _xtos_cause3_handler = 0x40000590 ); PROVIDE ( _xtos_ints_off = 0x4000bda4 ); PROVIDE ( _xtos_ints_on = 0x4000bd84 ); PROVIDE ( _xtos_l1int_handler = 0x4000048c ); PROVIDE ( _xtos_p_none = 0x4000dbf8 ); PROVIDE ( _xtos_restore_intlevel = 0x4000056c ); PROVIDE ( _xtos_return_from_exc = 0x4000dc54 ); PROVIDE ( _xtos_set_exception_handler = 0x40000454 ); PROVIDE ( _xtos_set_interrupt_handler = 0x4000bd70 ); PROVIDE ( _xtos_set_interrupt_handler_arg = 0x4000bd28 ); PROVIDE ( _xtos_set_intlevel = 0x4000dbfc ); PROVIDE ( _xtos_set_min_intlevel = 0x4000dc18 ); PROVIDE ( _xtos_set_vpri = 0x40000574 ); PROVIDE ( _xtos_syscall_handler = 0x4000dbe4 ); PROVIDE ( _xtos_unhandled_exception = 0x4000dc44 ); PROVIDE ( _xtos_unhandled_interrupt = 0x4000dc3c ); PROVIDE ( aes_decrypt = 0x400092d4 ); PROVIDE ( aes_decrypt_deinit = 0x400092e4 ); PROVIDE ( aes_decrypt_init = 0x40008ea4 ); PROVIDE ( aes_unwrap = 0x40009410 ); PROVIDE ( base64_decode = 0x40009648 ); PROVIDE ( base64_encode = 0x400094fc ); PROVIDE ( bzero = 0x4000de84 ); PROVIDE ( cmd_parse = 0x40000814 ); PROVIDE ( conv_str_decimal = 0x40000b24 ); PROVIDE ( conv_str_hex = 0x40000cb8 ); PROVIDE ( convert_para_str = 0x40000a60 ); PROVIDE ( dtm_get_intr_mask = 0x400026d0 ); PROVIDE ( dtm_params_init = 0x4000269c ); PROVIDE ( dtm_set_intr_mask = 0x400026c8 ); PROVIDE ( dtm_set_params = 0x400026dc ); PROVIDE ( eprintf = 0x40001d14 ); PROVIDE ( eprintf_init_buf = 0x40001cb8 ); PROVIDE ( eprintf_to_host = 0x40001d48 ); PROVIDE ( est_get_printf_buf_remain_len = 0x40002494 ); PROVIDE ( est_reset_printf_buf_len = 0x4000249c ); PROVIDE ( ets_bzero = 0x40002ae8 ); PROVIDE ( ets_char2xdigit = 0x40002b74 ); PROVIDE ( ets_delay_us = 0x40002ecc ); PROVIDE ( ets_enter_sleep = 0x400027b8 ); PROVIDE ( ets_external_printf = 0x40002578 ); PROVIDE ( ets_get_cpu_frequency = 0x40002f0c ); PROVIDE ( ets_getc = 0x40002bcc ); PROVIDE ( ets_install_external_printf = 0x40002450 ); PROVIDE ( ets_install_putc1 = 0x4000242c ); PROVIDE ( ets_install_putc2 = 0x4000248c ); PROVIDE ( ets_install_uart_printf = 0x40002438 ); PROVIDE ( ets_intr_lock = 0x40000f74 ); PROVIDE ( ets_intr_unlock = 0x40000f80 ); PROVIDE ( ets_isr_attach = 0x40000f88 ); PROVIDE ( ets_isr_mask = 0x40000f98 ); PROVIDE ( ets_isr_unmask = 0x40000fa8 ); PROVIDE ( ets_memcmp = 0x400018d4 ); PROVIDE ( ets_memcpy = 0x400018b4 ); PROVIDE ( ets_memmove = 0x400018c4 ); PROVIDE ( ets_memset = 0x400018a4 ); PROVIDE ( _ets_post = 0x40000e24 ); PROVIDE ( ets_printf = 0x400024cc ); PROVIDE ( ets_putc = 0x40002be8 ); PROVIDE ( ets_rtc_int_register = 0x40002a40 ); PROVIDE ( _ets_run = 0x40000e04 ); PROVIDE ( _ets_set_idle_cb = 0x40000dc0 ); PROVIDE ( ets_set_user_start = 0x40000fbc ); PROVIDE ( ets_str2macaddr = 0x40002af8 ); PROVIDE ( ets_strcmp = 0x40002aa8 ); PROVIDE ( ets_strcpy = 0x40002a88 ); PROVIDE ( ets_strlen = 0x40002ac8 ); PROVIDE ( ets_strncmp = 0x40002ab8 ); PROVIDE ( ets_strncpy = 0x40002a98 ); PROVIDE ( ets_strstr = 0x40002ad8 ); PROVIDE ( _ets_task = 0x40000dd0 ); PROVIDE ( ets_timer_arm = 0x40002cc4 ); PROVIDE ( ets_timer_disarm = 0x40002d40 ); PROVIDE ( ets_timer_done = 0x40002d80 ); PROVIDE ( ets_timer_handler_isr = 0x40002da8 ); PROVIDE ( _ets_timer_init = 0x40002e68 ); PROVIDE ( ets_timer_setfn = 0x40002c48 ); PROVIDE ( ets_uart_printf = 0x40002544 ); PROVIDE ( ets_update_cpu_frequency = 0x40002f04 ); PROVIDE ( ets_vprintf = 0x40001f00 ); PROVIDE ( ets_wdt_disable = 0x400030f0 ); PROVIDE ( ets_wdt_enable = 0x40002fa0 ); PROVIDE ( ets_wdt_get_mode = 0x40002f34 ); PROVIDE ( ets_wdt_init = 0x40003170 ); PROVIDE ( ets_wdt_restore = 0x40003158 ); PROVIDE ( ets_write_char = 0x40001da0 ); PROVIDE ( get_first_seg = 0x4000091c ); PROVIDE ( gpio_init = 0x40004c50 ); PROVIDE ( gpio_input_get = 0x40004cf0 ); PROVIDE ( gpio_intr_ack = 0x40004dcc ); PROVIDE ( gpio_intr_handler_register = 0x40004e28 ); PROVIDE ( gpio_intr_pending = 0x40004d88 ); PROVIDE ( gpio_intr_test = 0x40004efc ); PROVIDE ( gpio_output_set = 0x40004cd0 ); PROVIDE ( gpio_pin_intr_state_set = 0x40004d90 ); PROVIDE ( gpio_pin_wakeup_disable = 0x40004ed4 ); PROVIDE ( gpio_pin_wakeup_enable = 0x40004e90 ); PROVIDE ( gpio_register_get = 0x40004d5c ); PROVIDE ( gpio_register_set = 0x40004d04 ); PROVIDE ( hmac_md5 = 0x4000a2cc ); PROVIDE ( hmac_md5_vector = 0x4000a160 ); PROVIDE ( hmac_sha1 = 0x4000ba28 ); PROVIDE ( hmac_sha1_vector = 0x4000b8b4 ); PROVIDE ( lldesc_build_chain = 0x40004f40 ); PROVIDE ( lldesc_num2link = 0x40005050 ); PROVIDE ( lldesc_set_owner = 0x4000507c ); PROVIDE ( main = 0x40000fec ); PROVIDE ( md5_vector = 0x400097ac ); PROVIDE ( mem_calloc = 0x40001c2c ); PROVIDE ( mem_free = 0x400019e0 ); PROVIDE ( mem_init = 0x40001998 ); PROVIDE ( mem_malloc = 0x40001b40 ); PROVIDE ( mem_realloc = 0x40001c6c ); PROVIDE ( mem_trim = 0x40001a14 ); PROVIDE ( mem_zalloc = 0x40001c58 ); PROVIDE ( memcmp = 0x4000dea8 ); PROVIDE ( memcpy = 0x4000df48 ); PROVIDE ( memmove = 0x4000e04c ); PROVIDE ( memset = 0x4000e190 ); PROVIDE ( multofup = 0x400031c0 ); PROVIDE ( pbkdf2_sha1 = 0x4000b840 ); PROVIDE ( phy_get_romfuncs = 0x40006b08 ); PROVIDE ( rand = 0x40000600 ); PROVIDE ( rc4_skip = 0x4000dd68 ); PROVIDE ( recv_packet = 0x40003d08 ); PROVIDE ( remove_head_space = 0x40000a04 ); PROVIDE ( rijndaelKeySetupDec = 0x40008dd0 ); PROVIDE ( rijndaelKeySetupEnc = 0x40009300 ); PROVIDE ( rom_abs_temp = 0x400060c0 ); PROVIDE ( rom_ana_inf_gating_en = 0x40006b10 ); PROVIDE ( rom_cal_tos_v50 = 0x40007a28 ); PROVIDE ( rom_chip_50_set_channel = 0x40006f84 ); PROVIDE ( rom_chip_v5_disable_cca = 0x400060d0 ); PROVIDE ( rom_chip_v5_enable_cca = 0x400060ec ); PROVIDE ( rom_chip_v5_rx_init = 0x4000711c ); PROVIDE ( rom_chip_v5_sense_backoff = 0x4000610c ); PROVIDE ( rom_chip_v5_tx_init = 0x4000718c ); PROVIDE ( rom_dc_iq_est = 0x4000615c ); PROVIDE ( rom_en_pwdet = 0x400061b8 ); PROVIDE ( rom_get_bb_atten = 0x40006238 ); PROVIDE ( rom_get_corr_power = 0x40006260 ); PROVIDE ( rom_get_fm_sar_dout = 0x400062dc ); PROVIDE ( rom_get_noisefloor = 0x40006394 ); PROVIDE ( rom_get_power_db = 0x400063b0 ); PROVIDE ( rom_i2c_readReg = 0x40007268 ); PROVIDE ( rom_i2c_readReg_Mask = 0x4000729c ); PROVIDE ( rom_i2c_writeReg = 0x400072d8 ); PROVIDE ( rom_i2c_writeReg_Mask = 0x4000730c ); PROVIDE ( rom_iq_est_disable = 0x40006400 ); PROVIDE ( rom_iq_est_enable = 0x40006430 ); PROVIDE ( rom_linear_to_db = 0x40006484 ); PROVIDE ( rom_mhz2ieee = 0x400065a4 ); PROVIDE ( rom_pbus_dco___SA2 = 0x40007bf0 ); PROVIDE ( rom_pbus_debugmode = 0x4000737c ); PROVIDE ( rom_pbus_enter_debugmode = 0x40007410 ); PROVIDE ( rom_pbus_exit_debugmode = 0x40007448 ); PROVIDE ( rom_pbus_force_test = 0x4000747c ); PROVIDE ( rom_pbus_rd = 0x400074d8 ); PROVIDE ( rom_pbus_set_rxgain = 0x4000754c ); PROVIDE ( rom_pbus_set_txgain = 0x40007610 ); PROVIDE ( rom_pbus_workmode = 0x40007648 ); PROVIDE ( rom_pbus_xpd_rx_off = 0x40007688 ); PROVIDE ( rom_pbus_xpd_rx_on = 0x400076cc ); PROVIDE ( rom_pbus_xpd_tx_off = 0x400076fc ); PROVIDE ( rom_pbus_xpd_tx_on = 0x40007740 ); PROVIDE ( rom_pbus_xpd_tx_on__low_gain = 0x400077a0 ); PROVIDE ( rom_phy_reset_req = 0x40007804 ); PROVIDE ( rom_restart_cal = 0x4000781c ); PROVIDE ( rom_rfcal_pwrctrl = 0x40007eb4 ); PROVIDE ( rom_rfcal_rxiq = 0x4000804c ); PROVIDE ( rom_rfcal_rxiq_set_reg = 0x40008264 ); PROVIDE ( rom_rfcal_txcap = 0x40008388 ); PROVIDE ( rom_rfcal_txiq = 0x40008610 ); PROVIDE ( rom_rfcal_txiq_cover = 0x400088b8 ); PROVIDE ( rom_rfcal_txiq_set_reg = 0x40008a70 ); PROVIDE ( rom_rfpll_reset = 0x40007868 ); PROVIDE ( rom_rfpll_set_freq = 0x40007968 ); PROVIDE ( rom_rxiq_cover_mg_mp = 0x40008b6c ); PROVIDE ( rom_rxiq_get_mis = 0x40006628 ); PROVIDE ( rom_sar_init = 0x40006738 ); PROVIDE ( rom_set_ana_inf_tx_scale = 0x4000678c ); PROVIDE ( rom_set_channel_freq = 0x40006c50 ); PROVIDE ( rom_set_loopback_gain = 0x400067c8 ); PROVIDE ( rom_set_noise_floor = 0x40006830 ); PROVIDE ( rom_set_rxclk_en = 0x40006550 ); PROVIDE ( rom_set_txbb_atten = 0x40008c6c ); PROVIDE ( rom_set_txclk_en = 0x4000650c ); PROVIDE ( rom_set_txiq_cal = 0x40008d34 ); PROVIDE ( rom_start_noisefloor = 0x40006874 ); PROVIDE ( rom_start_tx_tone = 0x400068b4 ); PROVIDE ( rom_stop_tx_tone = 0x4000698c ); PROVIDE ( rom_tx_mac_disable = 0x40006a98 ); PROVIDE ( rom_tx_mac_enable = 0x40006ad4 ); PROVIDE ( rom_txtone_linear_pwr = 0x40006a1c ); PROVIDE ( rom_write_rfpll_sdm = 0x400078dc ); PROVIDE ( roundup2 = 0x400031b4 ); PROVIDE ( rtc_enter_sleep = 0x40002870 ); PROVIDE ( rtc_get_reset_reason = 0x400025e0 ); PROVIDE ( rtc_intr_handler = 0x400029ec ); PROVIDE ( rtc_set_sleep_mode = 0x40002668 ); PROVIDE ( save_rxbcn_mactime = 0x400027a4 ); PROVIDE ( save_tsf_us = 0x400027ac ); PROVIDE ( send_packet = 0x40003c80 ); PROVIDE ( sha1_prf = 0x4000ba48 ); PROVIDE ( sha1_vector = 0x4000a2ec ); PROVIDE ( sip_alloc_to_host_evt = 0x40005180 ); PROVIDE ( sip_get_ptr = 0x400058a8 ); PROVIDE ( sip_get_state = 0x40005668 ); PROVIDE ( sip_init_attach = 0x4000567c ); PROVIDE ( sip_install_rx_ctrl_cb = 0x4000544c ); PROVIDE ( sip_install_rx_data_cb = 0x4000545c ); PROVIDE ( sip_post = 0x400050fc ); PROVIDE ( sip_post_init = 0x400056c4 ); PROVIDE ( sip_reclaim_from_host_cmd = 0x4000534c ); PROVIDE ( sip_reclaim_tx_data_pkt = 0x400052c0 ); PROVIDE ( sip_send = 0x40005808 ); PROVIDE ( sip_to_host_chain_append = 0x40005864 ); PROVIDE ( sip_to_host_evt_send_done = 0x40005234 ); PROVIDE ( slc_add_credits = 0x400060ac ); PROVIDE ( slc_enable = 0x40005d90 ); PROVIDE ( slc_from_host_chain_fetch = 0x40005f24 ); PROVIDE ( slc_from_host_chain_recycle = 0x40005e94 ); PROVIDE ( slc_init_attach = 0x40005c50 ); PROVIDE ( slc_init_credit = 0x4000608c ); PROVIDE ( slc_pause_from_host = 0x40006014 ); PROVIDE ( slc_reattach = 0x40005c1c ); PROVIDE ( slc_resume_from_host = 0x4000603c ); PROVIDE ( slc_select_tohost_gpio = 0x40005dc0 ); PROVIDE ( slc_select_tohost_gpio_mode = 0x40005db8 ); PROVIDE ( slc_send_to_host_chain = 0x40005de4 ); PROVIDE ( slc_set_host_io_max_window = 0x40006068 ); PROVIDE ( slc_to_host_chain_recycle = 0x40005f10 ); PROVIDE ( software_reset = 0x4000264c ); PROVIDE ( spi_flash_attach = 0x40004644 ); PROVIDE ( srand = 0x400005f0 ); PROVIDE ( strcmp = 0x4000bdc8 ); PROVIDE ( strcpy = 0x4000bec8 ); PROVIDE ( strlen = 0x4000bf4c ); PROVIDE ( strncmp = 0x4000bfa8 ); PROVIDE ( strncpy = 0x4000c0a0 ); PROVIDE ( strstr = 0x4000e1e0 ); PROVIDE ( timer_insert = 0x40002c64 ); PROVIDE ( uartAttach = 0x4000383c ); PROVIDE ( uart_baudrate_detect = 0x40003924 ); PROVIDE ( uart_buff_switch = 0x400038a4 ); PROVIDE ( uart_div_modify = 0x400039d8 ); PROVIDE ( uart_rx_intr_handler = 0x40003bbc ); PROVIDE ( uart_rx_one_char = 0x40003b8c ); PROVIDE ( uart_rx_one_char_block = 0x40003b64 ); PROVIDE ( uart_rx_readbuff = 0x40003ec8 ); PROVIDE ( uart_tx_one_char = 0x40003b30 ); PROVIDE ( wepkey_128 = 0x4000bc40 ); PROVIDE ( wepkey_64 = 0x4000bb3c ); PROVIDE ( xthal_bcopy = 0x40000688 ); PROVIDE ( xthal_copy123 = 0x4000074c ); PROVIDE ( xthal_get_ccompare = 0x4000dd4c ); PROVIDE ( xthal_get_ccount = 0x4000dd38 ); PROVIDE ( xthal_get_interrupt = 0x4000dd58 ); PROVIDE ( xthal_get_intread = 0x4000dd58 ); PROVIDE ( xthal_memcpy = 0x400006c4 ); PROVIDE ( xthal_set_ccompare = 0x4000dd40 ); PROVIDE ( xthal_set_intclear = 0x4000dd60 ); PROVIDE ( xthal_spill_registers_into_stack_nw = 0x4000e320 ); PROVIDE ( xthal_window_spill = 0x4000e324 ); PROVIDE ( xthal_window_spill_nw = 0x4000e320 ); PROVIDE ( Te0 = 0x3fffccf0 ); PROVIDE ( Td0 = 0x3fffd100 ); PROVIDE ( Td4s = 0x3fffd500); PROVIDE ( rcons = 0x3fffd0f0); PROVIDE ( UartDev = 0x3fffde10 ); PROVIDE ( flashchip = 0x3fffc714); micropython-1.12/ports/esp8266/boards/esp8266.ld000066400000000000000000000005031357706137100212140ustar00rootroot00000000000000/* GNU linker script for ESP8266 */ MEMORY { dport0_0_seg : org = 0x3ff00000, len = 0x10 dram0_0_seg : org = 0x3ffe8000, len = 0x14000 iram1_0_seg : org = 0x40100000, len = 0x8000 irom0_0_seg : org = 0x40209000, len = 0x8f000 } /* define common sections and symbols */ INCLUDE boards/esp8266_common.ld micropython-1.12/ports/esp8266/boards/esp8266_512k.ld000066400000000000000000000005031357706137100217560ustar00rootroot00000000000000/* GNU linker script for ESP8266 */ MEMORY { dport0_0_seg : org = 0x3ff00000, len = 0x10 dram0_0_seg : org = 0x3ffe8000, len = 0x14000 iram1_0_seg : org = 0x40100000, len = 0x8000 irom0_0_seg : org = 0x40209000, len = 0x72000 } /* define common sections and symbols */ INCLUDE boards/esp8266_common.ld micropython-1.12/ports/esp8266/boards/esp8266_common.ld000066400000000000000000000236751357706137100226030ustar00rootroot00000000000000/* GNU linker script for ESP8266, common sections and symbols */ /* define the top of RAM */ _heap_end = ORIGIN(dram0_0_seg) + LENGTH(dram0_0_seg); PHDRS { dport0_0_phdr PT_LOAD; dram0_0_phdr PT_LOAD; dram0_0_bss_phdr PT_LOAD; iram1_0_phdr PT_LOAD; irom0_0_phdr PT_LOAD; } ENTRY(firmware_start) EXTERN(_DebugExceptionVector) EXTERN(_DoubleExceptionVector) EXTERN(_KernelExceptionVector) EXTERN(_NMIExceptionVector) EXTERN(_UserExceptionVector) _firmware_size = ORIGIN(irom0_0_seg) + LENGTH(irom0_0_seg) - 0x40200000; PROVIDE(_memmap_vecbase_reset = 0x40000000); /* Various memory-map dependent cache attribute settings: */ _memmap_cacheattr_wb_base = 0x00000110; _memmap_cacheattr_wt_base = 0x00000110; _memmap_cacheattr_bp_base = 0x00000220; _memmap_cacheattr_unused_mask = 0xFFFFF00F; _memmap_cacheattr_wb_trapnull = 0x2222211F; _memmap_cacheattr_wba_trapnull = 0x2222211F; _memmap_cacheattr_wbna_trapnull = 0x2222211F; _memmap_cacheattr_wt_trapnull = 0x2222211F; _memmap_cacheattr_bp_trapnull = 0x2222222F; _memmap_cacheattr_wb_strict = 0xFFFFF11F; _memmap_cacheattr_wt_strict = 0xFFFFF11F; _memmap_cacheattr_bp_strict = 0xFFFFF22F; _memmap_cacheattr_wb_allvalid = 0x22222112; _memmap_cacheattr_wt_allvalid = 0x22222112; _memmap_cacheattr_bp_allvalid = 0x22222222; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); SECTIONS { .dport0.rodata : ALIGN(4) { _dport0_rodata_start = ABSOLUTE(.); *(.dport0.rodata) *(.dport.rodata) _dport0_rodata_end = ABSOLUTE(.); } >dport0_0_seg :dport0_0_phdr .dport0.literal : ALIGN(4) { _dport0_literal_start = ABSOLUTE(.); *(.dport0.literal) *(.dport.literal) _dport0_literal_end = ABSOLUTE(.); } >dport0_0_seg :dport0_0_phdr .dport0.data : ALIGN(4) { _dport0_data_start = ABSOLUTE(.); *(.dport0.data) *(.dport.data) _dport0_data_end = ABSOLUTE(.); } >dport0_0_seg :dport0_0_phdr .irom0.text : ALIGN(4) { _irom0_text_start = ABSOLUTE(.); *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) /* Vendor SDK in v2.1.0-7-gb8fd588 started to build these with -ffunction-sections -fdata-sections, and require routing to irom via linker: https://github.com/espressif/ESP8266_NONOS_SDK/commit/b8fd588a33f0319dc135523b51655e97b483b205 */ *libcrypto.a:(.literal.* .text.*) *libnet80211.a:(.literal.* .text.*) *libwpa.a:(.literal.* .text.*) *libwpa2.a:(.literal.* .text.*) /* we put some specific text in this section */ *py/argcheck.o*(.literal* .text*) *py/asm*.o*(.literal* .text*) *py/bc.o*(.literal* .text*) *py/binary.o*(.literal* .text*) *py/builtin*.o*(.literal* .text*) *py/compile.o*(.literal* .text*) *py/emit*.o*(.literal* .text*) *py/persistentcode*.o*(.literal* .text*) *py/formatfloat.o*(.literal* .text*) *py/frozenmod.o*(.literal* .text*) *py/gc.o*(.literal* .text*) *py/reader*.o*(.literal* .text*) *py/lexer*.o*(.literal* .text*) *py/malloc*.o*(.literal* .text*) *py/map*.o*(.literal* .text*) *py/mod*.o*(.literal* .text*) *py/mpprint.o*(.literal* .text*) *py/mpstate.o*(.literal* .text*) *py/mpz.o*(.literal* .text*) *py/native*.o*(.literal* .text*) *py/nlr*.o*(.literal* .text*) *py/obj*.o*(.literal* .text*) *py/opmethods.o*(.literal* .text*) *py/parse*.o*(.literal* .text*) *py/profile*.o*(.literal* .text*) *py/qstr.o*(.literal* .text*) *py/repl.o*(.literal* .text*) *py/runtime.o*(.literal* .text*) *py/scheduler.o*(.literal* .text*) *py/scope.o*(.literal* .text*) *py/sequence.o*(.literal* .text*) *py/showbc.o*(.literal* .text*) *py/smallint.o*(.literal* .text*) *py/stackctrl.o*(.literal* .text*) *py/stream.o*(.literal* .text*) *py/unicode.o*(.literal* .text*) *py/vm.o*(.literal* .text*) *py/vstr.o*(.literal* .text*) *py/warning.o*(.literal* .text*) *extmod/*.o*(.literal* .text*) *lib/oofatfs/*.o*(.literal*, .text*) *lib/axtls/*.o(.literal*, .text*) *lib/berkeley-db-1.xx/*.o(.literal*, .text*) *lib/libm/*.o*(.literal*, .text*) *lib/littlefs/*.o*(.literal*, .text*) *lib/mp-readline/*.o(.literal*, .text*) *lib/netutils/*.o*(.literal*, .text*) *lib/timeutils/*.o*(.literal*, .text*) *lib/utils/printf.o*(.literal*, .text*) *lib/utils/sys_stdio_mphal.o*(.literal*, .text*) *lib/utils/pyexec.o*(.literal*, .text*) *lib/utils/stdout_helpers.o*(.literal*, .text*) *lib/utils/interrupt_char.o*(.literal.mp_hal_set_interrupt_char, .text.mp_hal_set_interrupt_char) *drivers/bus/*.o(.literal* .text*) build-*/main.o(.literal* .text*) *fatfs_port.o(.literal* .text*) *gccollect.o(.literal* .text*) *gchelper.o(.literal* .text*) *help.o(.literal* .text*) *lexerstr32.o(.literal* .text*) *utils.o(.literal* .text*) *modpyb.o(.literal*, .text*) *machine_pin.o(.literal*, .text*) *machine_pwm.o(.literal*, .text*) *machine_rtc.o(.literal*, .text*) *machine_adc.o(.literal*, .text*) *machine_uart.o(.literal*, .text*) *modpybi2c.o(.literal*, .text*) *modmachine.o(.literal*, .text*) *machine_wdt.o(.literal*, .text*) *machine_spi.o(.literal*, .text*) *machine_hspi.o(.literal*, .text*) *hspi.o(.literal*, .text*) *modesp.o(.literal* .text*) *modnetwork.o(.literal* .text*) *moduos.o(.literal* .text*) *modutime.o(.literal* .text*) *modlwip.o(.literal* .text*) *modsocket.o(.literal* .text*) *modonewire.o(.literal* .text*) /* we put as much rodata as possible in this section */ /* note that only rodata accessed as a machine word is allowed here */ *py/qstr.o(.rodata.const_pool) *.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */ *.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */ *.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */ */frozen.o(.rodata.mp_frozen_sizes) /* frozen modules */ */frozen.o(.rodata.mp_frozen_content) /* frozen modules */ /* for -mforce-l32 */ build-*/*.o(.rodata*) _irom0_text_end = ABSOLUTE(.); } >irom0_0_seg :irom0_0_phdr .text : ALIGN(4) { _stext = .; _text_start = ABSOLUTE(.); *(.UserEnter.text) . = ALIGN(16); *(.DebugExceptionVector.text) . = ALIGN(16); *(.NMIExceptionVector.text) . = ALIGN(16); *(.KernelExceptionVector.text) LONG(0) LONG(0) LONG(0) LONG(0) . = ALIGN(16); *(.UserExceptionVector.text) LONG(0) LONG(0) LONG(0) LONG(0) . = ALIGN(16); *(.DoubleExceptionVector.text) LONG(0) LONG(0) LONG(0) LONG(0) . = ALIGN (16); *(.entry.text) *(.init.literal) *(.init) *(.literal .text .literal.* .text.* .iram0.literal .iram0.text .iram0.text.*.literal .iram0.text.*) *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.fini.literal) *(.fini) *(.gnu.version) _text_end = ABSOLUTE(.); _etext = .; } >iram1_0_seg :iram1_0_phdr .lit4 : ALIGN(4) { _lit4_start = ABSOLUTE(.); *(*.lit4) *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); } >iram1_0_seg :iram1_0_phdr .data : ALIGN(4) { _data_start = ABSOLUTE(.); *(.data) *(.data.*) *(.gnu.linkonce.d.*) *(.data1) *(.sdata) *(.sdata.*) *(.gnu.linkonce.s.*) *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) *(.jcr) _data_end = ABSOLUTE(.); } >dram0_0_seg :dram0_0_phdr .rodata : ALIGN(4) { _rodata_start = ABSOLUTE(.); *(.sdk.version) *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) *(.rodata1) __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); *(.xt_except_table) *(.gcc_except_table) *(.gnu.linkonce.e.*) *(.gnu.version_r) *(.eh_frame) /* C++ constructor and destructor tables, properly ordered: */ KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) KEEP (*crtbegin.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) /* C++ exception handlers table: */ __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); *(.xt_except_desc) *(.gnu.linkonce.h.*) __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) *(.dynamic) *(.gnu.version_d) . = ALIGN(4); /* this table MUST be 4-byte aligned */ _bss_table_start = ABSOLUTE(.); LONG(_bss_start) LONG(_bss_end) _bss_table_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); } >dram0_0_seg :dram0_0_phdr .bss ALIGN(8) (NOLOAD) : ALIGN(4) { . = ALIGN (8); _bss_start = ABSOLUTE(.); *(.dynsbss) *(.sbss) *(.sbss.*) *(.gnu.linkonce.sb.*) *(.scommon) *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) *(.dynbss) *(.bss) *(.bss.*) *(.gnu.linkonce.b.*) *(COMMON) . = ALIGN (8); _bss_end = ABSOLUTE(.); _heap_start = ABSOLUTE(.); } >dram0_0_seg :dram0_0_bss_phdr } /* get ROM code address */ INCLUDE "boards/eagle.rom.addr.v6.ld" micropython-1.12/ports/esp8266/boards/esp8266_ota.ld000066400000000000000000000006451357706137100220660ustar00rootroot00000000000000/* GNU linker script for ESP8266 */ MEMORY { dport0_0_seg : org = 0x3ff00000, len = 0x10 dram0_0_seg : org = 0x3ffe8000, len = 0x14000 iram1_0_seg : org = 0x40100000, len = 0x8000 /* 0x3c000 is size of bootloader, 0x9000 is size of packed RAM segments */ irom0_0_seg : org = 0x40200000 + 0x3c000 + 0x9000, len = 0x8f000 } /* define common sections and symbols */ INCLUDE boards/esp8266_common.ld micropython-1.12/ports/esp8266/boards/manifest.py000066400000000000000000000003331357706137100217370ustar00rootroot00000000000000freeze('$(PORT_DIR)/modules') freeze('$(MPY_DIR)/tools', ('upip.py', 'upip_utarfile.py')) freeze('$(MPY_DIR)/drivers/dht', 'dht.py') freeze('$(MPY_DIR)/drivers/onewire') include('$(MPY_DIR)/extmod/webrepl/manifest.py') micropython-1.12/ports/esp8266/boards/manifest_release.py000066400000000000000000000016161357706137100234440ustar00rootroot00000000000000include('manifest.py') # drivers freeze('$(MPY_DIR)/drivers/display', 'ssd1306.py') # file utilities freeze('$(MPY_LIB_DIR)/upysh', 'upysh.py') # uasyncio freeze('$(MPY_LIB_DIR)/uasyncio', 'uasyncio/__init__.py') freeze('$(MPY_LIB_DIR)/uasyncio.core', 'uasyncio/core.py') # requests freeze('$(MPY_LIB_DIR)/urequests', 'urequests.py') freeze('$(MPY_LIB_DIR)/urllib.urequest', 'urllib/urequest.py') # umqtt with examples freeze('$(MPY_LIB_DIR)/umqtt.simple', 'umqtt/simple.py') freeze('$(MPY_LIB_DIR)/umqtt.robust', 'umqtt/robust.py') freeze('$(MPY_LIB_DIR)/umqtt.simple', 'example_pub_button.py') freeze('$(MPY_LIB_DIR)/umqtt.simple', 'example_sub_led.py') # HTTP examples freeze('$(MPY_DIR)/examples/network', 'http_client.py') freeze('$(MPY_DIR)/examples/network', 'http_client_ssl.py') freeze('$(MPY_DIR)/examples/network', 'http_server.py') freeze('$(MPY_DIR)/examples/network', 'http_server_ssl.py') micropython-1.12/ports/esp8266/esp_init_data.c000066400000000000000000000061461357706137100212640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "ets_sys.h" #include "etshal.h" #include "esp_mphal.h" #include "user_interface.h" #include "extmod/misc.h" NORETURN void call_user_start(void); void ets_printf(const char *fmt, ...); extern char flashchip; static const uint8_t default_init_data[] __attribute__((aligned(4))) = { 0x05, 0x00, 0x04, 0x02, 0x05, 0x05, 0x05, 0x02, 0x05, 0x00, 0x04, 0x05, 0x05, 0x04, 0x05, 0x05, 0x04, 0xfe, 0xfd, 0xff, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0x0a, 0xff, 0xff, 0xf8, 0x00, 0xf8, 0xf8, 0x52, 0x4e, 0x4a, 0x44, 0x40, 0x38, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x93, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void firmware_start(void) { // For SDK 1.5.2, either address has shifted and not mirrored in // eagle.rom.addr.v6.ld, or extra initial member was added. SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4); char buf[128]; SPIRead(flash->chip_size - 4 * 0x1000, buf, sizeof(buf)); /*for (int i = 0; i < sizeof(buf); i++) { static char hexf[] = "%x "; ets_printf(hexf, buf[i]); }*/ bool inited = false; for (int i = 0; i < sizeof(buf); i++) { if (buf[i] != 0xff) { inited = true; break; } } if (!inited) { static char msg[] = "Writing init data\n"; ets_printf(msg); SPIRead((uint32_t)&default_init_data - 0x40200000, buf, sizeof(buf)); SPIWrite(flash->chip_size - 4 * 0x1000, buf, sizeof(buf)); } asm("j call_user_start"); } micropython-1.12/ports/esp8266/esp_mphal.c000066400000000000000000000134251357706137100204270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "ets_sys.h" #include "etshal.h" #include "uart.h" #include "esp_mphal.h" #include "user_interface.h" #include "ets_alt_task.h" #include "py/runtime.h" #include "py/stream.h" #include "extmod/misc.h" #include "lib/utils/pyexec.h" STATIC byte stdin_ringbuf_array[256]; ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len); const mp_print_t mp_debug_print = {NULL, mp_hal_debug_tx_strn_cooked}; int uart_attached_to_dupterm; void mp_hal_init(void) { //ets_wdt_disable(); // it's a pain while developing mp_hal_rtc_init(); uart_init(UART_BIT_RATE_115200, UART_BIT_RATE_115200); uart_attached_to_dupterm = 0; } void mp_hal_delay_us(uint32_t us) { uint32_t start = system_get_time(); while (system_get_time() - start < us) { ets_event_poll(); } } uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { ret |= MP_STREAM_POLL_RD; } return ret; } int mp_hal_stdin_rx_chr(void) { for (;;) { int c = ringbuf_get(&stdin_ringbuf); if (c != -1) { return c; } #if 0 // Idles CPU but need more testing before enabling if (!ets_loop_iter()) { asm("waiti 0"); } #else mp_hal_delay_us(1); #endif } } #if 0 void mp_hal_debug_str(const char *str) { while (*str) { uart_tx_one_char(UART0, *str++); } uart_flush(UART0); } #endif void mp_hal_stdout_tx_str(const char *str) { mp_uos_dupterm_tx_strn(str, strlen(str)); } void mp_hal_stdout_tx_strn(const char *str, uint32_t len) { mp_uos_dupterm_tx_strn(str, len); } void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) { const char *last = str; while (len--) { if (*str == '\n') { if (str > last) { mp_uos_dupterm_tx_strn(last, str - last); } mp_uos_dupterm_tx_strn("\r\n", 2); ++str; last = str; } else { ++str; } } if (str > last) { mp_uos_dupterm_tx_strn(last, str - last); } } void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) { (void)env; while (len--) { if (*str == '\n') { uart_tx_one_char(UART0, '\r'); } uart_tx_one_char(UART0, *str++); } } uint32_t mp_hal_ticks_ms(void) { // Compute milliseconds from 64-bit microsecond counter system_time_update(); return ((uint64_t)system_time_high_word << 32 | (uint64_t)system_time_low_word) / 1000; } uint32_t mp_hal_ticks_us(void) { return system_get_time(); } void mp_hal_delay_ms(uint32_t delay) { mp_hal_delay_us(delay * 1000); } void ets_event_poll(void) { ets_loop_iter(); mp_handle_pending(); } void __assert_func(const char *file, int line, const char *func, const char *expr) { printf("assert:%s:%d:%s: %s\n", file, line, func, expr); mp_raise_msg(&mp_type_AssertionError, "C-level assert"); } void mp_hal_signal_input(void) { #if MICROPY_REPL_EVENT_DRIVEN system_os_post(UART_TASK_ID, 0, 0); #endif } STATIC void dupterm_task_handler(os_event_t *evt) { static byte lock; if (lock) { return; } lock = 1; while (1) { int c = mp_uos_dupterm_rx_chr(); if (c < 0) { break; } ringbuf_put(&stdin_ringbuf, c); } mp_hal_signal_input(); lock = 0; } STATIC os_event_t dupterm_evt_queue[4]; void dupterm_task_init() { system_os_task(dupterm_task_handler, DUPTERM_TASK_ID, dupterm_evt_queue, MP_ARRAY_SIZE(dupterm_evt_queue)); } void mp_hal_signal_dupterm_input(void) { system_os_post(DUPTERM_TASK_ID, 0, 0); } // Get pointer to esf_buf bookkeeping structure void *ets_get_esf_buf_ctlblk(void) { // Get literal ptr before start of esf_rx_buf_alloc func extern void *esf_rx_buf_alloc(); return ((void**)esf_rx_buf_alloc)[-1]; } // Get number of esf_buf free buffers of given type, as encoded by index // idx 0 corresponds to buf types 1, 2; 1 - 4; 2 - 5; 3 - 7; 4 - 8 // Only following buf types appear to be used: // 1 - tx buffer, 5 - management frame tx buffer; 8 - rx buffer int ets_esf_free_bufs(int idx) { uint32_t *p = ets_get_esf_buf_ctlblk(); uint32_t *b = (uint32_t*)p[idx]; int cnt = 0; while (b) { b = (uint32_t*)b[0x20 / 4]; cnt++; } return cnt; } extern int mp_stream_errno; int *__errno() { return &mp_stream_errno; } micropython-1.12/ports/esp8266/esp_mphal.h000066400000000000000000000074071357706137100204370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/ringbuf.h" #include "lib/utils/interrupt_char.h" #include "xtirq.h" void mp_keyboard_interrupt(void); struct _mp_print_t; // Structure for UART-only output via mp_printf() extern const struct _mp_print_t mp_debug_print; extern ringbuf_t stdin_ringbuf; // Call this after putting data to stdin_ringbuf void mp_hal_signal_input(void); // Call this when data is available in dupterm object void mp_hal_signal_dupterm_input(void); // This variable counts how many times the UART is attached to dupterm extern int uart_attached_to_dupterm; void mp_hal_init(void); void mp_hal_rtc_init(void); uint32_t mp_hal_ticks_us(void); __attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) { uint32_t ccount; __asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); return ccount; } void mp_hal_delay_us(uint32_t); void mp_hal_set_interrupt_char(int c); uint32_t mp_hal_get_cpu_freq(void); #define UART_TASK_ID 0 #define DUPTERM_TASK_ID 1 void uart_task_init(); void dupterm_task_init(); void ets_event_poll(void); #define ETS_POLL_WHILE(cond) { while (cond) ets_event_poll(); } // needed for machine.I2C #include "osapi.h" #define mp_hal_delay_us_fast(us) os_delay_us(us) #define mp_hal_quiet_timing_enter() disable_irq() #define mp_hal_quiet_timing_exit(irq_state) enable_irq(irq_state) // C-level pin HAL #include "etshal.h" #include "gpio.h" #include "modmachine.h" #define MP_HAL_PIN_FMT "%u" #define mp_hal_pin_obj_t uint32_t #define mp_hal_get_pin_obj(o) mp_obj_get_pin(o) #define mp_hal_pin_name(p) (p) void mp_hal_pin_input(mp_hal_pin_obj_t pin); void mp_hal_pin_output(mp_hal_pin_obj_t pin); void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin); #define mp_hal_pin_od_low(p) do { \ if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); } \ else { gpio_output_set(0, 1 << (p), 1 << (p), 0); } \ } while (0) #define mp_hal_pin_od_high(p) do { \ if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); } \ else { gpio_output_set(0, 0, 0, 1 << (p)); /* set as input to avoid glitches */ } \ } while (0) // The DHT driver requires using the open-drain feature of the GPIO to get it to work reliably #define mp_hal_pin_od_high_dht(p) do { \ if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); } \ else { gpio_output_set(1 << (p), 0, 1 << (p), 0); } \ } while (0) #define mp_hal_pin_read(p) pin_get(p) #define mp_hal_pin_write(p, v) pin_set((p), (v)) void *ets_get_esf_buf_ctlblk(void); int ets_esf_free_bufs(int idx); micropython-1.12/ports/esp8266/espapa102.c000066400000000000000000000100021357706137100201370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Robert Foss, Daniel Busch * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_ESP8266_APA102 #include #include "c_types.h" #include "eagle_soc.h" #include "user_interface.h" #include "espapa102.h" #define NOP asm volatile(" nop \n\t") static inline void _esp_apa102_send_byte(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t byte) { for (uint32_t i = 0; i < 8; i++) { if (byte & 0x80) { // set data pin high GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask); } else { // set data pin low GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, dataPinMask); } // set clock pin high GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask); byte <<= 1; NOP; NOP; // set clock pin low GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask); NOP; NOP; } } static inline void _esp_apa102_send_colors(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t *pixels, uint32_t numBytes) { for (uint32_t i = 0; i < numBytes / 4; i++) { _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 3] | 0xE0); _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 2]); _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 1]); _esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4]); } } static inline void _esp_apa102_start_frame(uint32_t clockPinMask, uint32_t dataPinMask) { for (uint32_t i = 0; i < 4; i++) { _esp_apa102_send_byte(clockPinMask, dataPinMask, 0x00); } } static inline void _esp_apa102_append_additionial_cycles(uint32_t clockPinMask, uint32_t dataPinMask, uint32_t numBytes) { GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask); // we need to write some more clock cycles, because each led // delays the data by one edge after inverting the clock for (uint32_t i = 0; i < numBytes / 8 + ((numBytes / 4) % 2); i++) { GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask); NOP; NOP; GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask); NOP; NOP; } } static inline void _esp_apa102_end_frame(uint32_t clockPinMask, uint32_t dataPinMask) { for (uint32_t i = 0; i < 4; i++) { _esp_apa102_send_byte(clockPinMask, dataPinMask, 0xFF); } } void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes) { uint32_t clockPinMask, dataPinMask; clockPinMask = 1 << clockPin; dataPinMask = 1 << dataPin; // start the frame _esp_apa102_start_frame(clockPinMask, dataPinMask); // write pixels _esp_apa102_send_colors(clockPinMask, dataPinMask, pixels, numBytes); // end the frame _esp_apa102_append_additionial_cycles(clockPinMask, dataPinMask, numBytes); _esp_apa102_end_frame(clockPinMask, dataPinMask); } #endif micropython-1.12/ports/esp8266/espapa102.h000066400000000000000000000026731357706137100201630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Robert Foss, Daniel Busch * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_ESP8266_ESPAPA102_H #define MICROPY_INCLUDED_ESP8266_ESPAPA102_H void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes); #endif // MICROPY_INCLUDED_ESP8266_ESPAPA102_H micropython-1.12/ports/esp8266/espneopixel.c000066400000000000000000000041411357706137100210050ustar00rootroot00000000000000// Original version from https://github.com/adafruit/Adafruit_NeoPixel // Modifications by dpgeorge to support auto-CPU-frequency detection // This is a mash-up of the Due show() code + insights from Michael Miller's // ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus // Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution. #include "py/mpconfig.h" #if MICROPY_ESP8266_NEOPIXEL #include "c_types.h" #include "eagle_soc.h" #include "user_interface.h" #include "espneopixel.h" #include "esp_mphal.h" #define NEO_KHZ400 (1) void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) { uint8_t *p, *end, pix, mask; uint32_t t, time0, time1, period, c, startTime, pinMask; pinMask = 1 << pin; p = pixels; end = p + numBytes; pix = *p++; mask = 0x80; startTime = 0; uint32_t fcpu = system_get_cpu_freq() * 1000000; #ifdef NEO_KHZ400 if(is800KHz) { #endif time0 = fcpu / 2857143; // 0.35us time1 = fcpu / 1250000; // 0.8us period = fcpu / 800000; // 1.25us per bit #ifdef NEO_KHZ400 } else { // 400 KHz bitstream time0 = fcpu / 2000000; // 0.5uS time1 = fcpu / 833333; // 1.2us period = fcpu / 400000; // 2.5us per bit } #endif uint32_t irq_state = mp_hal_quiet_timing_enter(); for(t = time0;; t = time0) { if(pix & mask) t = time1; // Bit high duration while(((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high startTime = c; // Save start time while(((c = mp_hal_ticks_cpu()) - startTime) < t); // Wait high duration GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low if(!(mask >>= 1)) { // Next bit/byte if(p >= end) break; pix = *p++; mask = 0x80; } } while((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit mp_hal_quiet_timing_exit(irq_state); } #endif // MICROPY_ESP8266_NEOPIXEL micropython-1.12/ports/esp8266/espneopixel.h000066400000000000000000000003521357706137100210120ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_ESP8266_ESPNEOPIXEL_H #define MICROPY_INCLUDED_ESP8266_ESPNEOPIXEL_H void esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz); #endif // MICROPY_INCLUDED_ESP8266_ESPNEOPIXEL_H micropython-1.12/ports/esp8266/esppwm.c000066400000000000000000000333201357706137100177660ustar00rootroot00000000000000/****************************************************************************** * Copyright 2013-2014 Espressif Systems (Wuxi) * * FileName: pwm.c * * Description: pwm driver * * Modification history: * 2014/5/1, v1.0 create this file. * 2016/3/2: Modifications by dpgeorge to suit MicroPython *******************************************************************************/ #include #include #include "etshal.h" #include "os_type.h" #include "gpio.h" #include "esppwm.h" #include "py/mpprint.h" #define PWM_DBG(...) //#define PWM_DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__) #define ICACHE_RAM_ATTR // __attribute__((section(".text"))) #define PWM_CHANNEL 8 #define PWM_DEPTH 1023 #define PWM_FREQ_MAX 1000 #define PWM_1S 1000000 struct pwm_single_param { uint16_t gpio_set; uint16_t gpio_clear; uint32_t h_time; }; struct pwm_param { uint32_t period; uint16_t freq; uint16_t duty[PWM_CHANNEL]; }; STATIC const uint8_t pin_num[PWM_CHANNEL] = {0, 2, 4, 5, 12, 13, 14, 15}; STATIC struct pwm_single_param pwm_single_toggle[2][PWM_CHANNEL + 1]; STATIC struct pwm_single_param *pwm_single; STATIC struct pwm_param pwm; STATIC int8_t pwm_out_io_num[PWM_CHANNEL] = {-1, -1, -1, -1, -1, -1, -1, -1}; STATIC uint8_t pwm_channel_toggle[2]; STATIC uint8_t *pwm_channel; STATIC uint8_t pwm_toggle = 1; STATIC uint8_t pwm_timer_down = 1; STATIC uint8_t pwm_current_channel = 0; STATIC uint16_t pwm_gpio = 0; STATIC uint8_t pwm_channel_num = 0; //XXX: 0xffffffff/(80000000/16)=35A #define US_TO_RTC_TIMER_TICKS(t) \ ((t) ? \ (((t) > 0x35A) ? \ (((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \ (((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \ 0) //FRC1 #define FRC1_ENABLE_TIMER BIT7 typedef enum { DIVDED_BY_1 = 0, DIVDED_BY_16 = 4, DIVDED_BY_256 = 8, } TIMER_PREDIVED_MODE; typedef enum { TM_LEVEL_INT = 1, TM_EDGE_INT = 0, } TIMER_INT_MODE; STATIC void ICACHE_FLASH_ATTR pwm_insert_sort(struct pwm_single_param pwm[], uint8 n) { uint8 i; for (i = 1; i < n; i++) { if (pwm[i].h_time < pwm[i - 1].h_time) { int8 j = i - 1; struct pwm_single_param tmp; memcpy(&tmp, &pwm[i], sizeof(struct pwm_single_param)); memcpy(&pwm[i], &pwm[i - 1], sizeof(struct pwm_single_param)); while (tmp.h_time < pwm[j].h_time) { memcpy(&pwm[j + 1], &pwm[j], sizeof(struct pwm_single_param)); j--; if (j < 0) { break; } } memcpy(&pwm[j + 1], &tmp, sizeof(struct pwm_single_param)); } } } STATIC volatile uint8 critical = 0; #define LOCK_PWM(c) do { \ while( (c)==1 ); \ (c) = 1; \ } while (0) #define UNLOCK_PWM(c) do { \ (c) = 0; \ } while (0) void ICACHE_FLASH_ATTR pwm_start(void) { uint8 i, j; PWM_DBG("--Function pwm_start() is called\n"); PWM_DBG("pwm_gpio:%x,pwm_channel_num:%d\n",pwm_gpio,pwm_channel_num); PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]); PWM_DBG("pwm.period:%d,pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.period,pwm.duty[0],pwm.duty[1],pwm.duty[2]); LOCK_PWM(critical); // enter critical struct pwm_single_param *local_single = pwm_single_toggle[pwm_toggle ^ 0x01]; uint8 *local_channel = &pwm_channel_toggle[pwm_toggle ^ 0x01]; // step 1: init PWM_CHANNEL+1 channels param for (i = 0; i < pwm_channel_num; i++) { uint32 us = pwm.period * pwm.duty[i] / PWM_DEPTH; local_single[i].h_time = US_TO_RTC_TIMER_TICKS(us); PWM_DBG("i:%d us:%d ht:%d\n",i,us,local_single[i].h_time); local_single[i].gpio_set = 0; local_single[i].gpio_clear = 1 << pin_num[pwm_out_io_num[i]]; } local_single[pwm_channel_num].h_time = US_TO_RTC_TIMER_TICKS(pwm.period); local_single[pwm_channel_num].gpio_set = pwm_gpio; local_single[pwm_channel_num].gpio_clear = 0; PWM_DBG("i:%d period:%d ht:%d\n",pwm_channel_num,pwm.period,local_single[pwm_channel_num].h_time); // step 2: sort, small to big pwm_insert_sort(local_single, pwm_channel_num + 1); *local_channel = pwm_channel_num + 1; PWM_DBG("1channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time); // step 3: combine same duty channels for (i = pwm_channel_num; i > 0; i--) { if (local_single[i].h_time == local_single[i - 1].h_time) { local_single[i - 1].gpio_set |= local_single[i].gpio_set; local_single[i - 1].gpio_clear |= local_single[i].gpio_clear; for (j = i + 1; j < *local_channel; j++) { memcpy(&local_single[j - 1], &local_single[j], sizeof(struct pwm_single_param)); } (*local_channel)--; } } PWM_DBG("2channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time); // step 4: cacl delt time for (i = *local_channel - 1; i > 0; i--) { local_single[i].h_time -= local_single[i - 1].h_time; } // step 5: last channel needs to clean local_single[*local_channel-1].gpio_clear = 0; // step 6: if first channel duty is 0, remove it if (local_single[0].h_time == 0) { local_single[*local_channel - 1].gpio_set &= ~local_single[0].gpio_clear; local_single[*local_channel - 1].gpio_clear |= local_single[0].gpio_clear; for (i = 1; i < *local_channel; i++) { memcpy(&local_single[i - 1], &local_single[i], sizeof(struct pwm_single_param)); } (*local_channel)--; } // if timer is down, need to set gpio and start timer if (pwm_timer_down == 1) { pwm_channel = local_channel; pwm_single = local_single; // start gpio_output_set(local_single[0].gpio_set, local_single[0].gpio_clear, pwm_gpio, 0); pwm_timer_down = 0; RTC_REG_WRITE(FRC1_LOAD_ADDRESS, local_single[0].h_time); } if (pwm_toggle == 1) { pwm_toggle = 0; } else { pwm_toggle = 1; } UNLOCK_PWM(critical); // leave critical PWM_DBG("3channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time); } /****************************************************************************** * FunctionName : pwm_set_duty * Description : set each channel's duty params * Parameters : int16_t duty : 0 ~ PWM_DEPTH * uint8 channel : channel index * Returns : NONE *******************************************************************************/ void ICACHE_FLASH_ATTR pwm_set_duty(int16_t duty, uint8 channel) { uint8 i; for(i=0;i= PWM_DEPTH) { pwm.duty[channel] = PWM_DEPTH; } else { pwm.duty[channel] = duty; } UNLOCK_PWM(critical); // leave critical } /****************************************************************************** * FunctionName : pwm_set_freq * Description : set pwm frequency * Parameters : uint16 freq : 100hz typically * Returns : NONE *******************************************************************************/ void ICACHE_FLASH_ATTR pwm_set_freq(uint16 freq, uint8 channel) { LOCK_PWM(critical); // enter critical if (freq > PWM_FREQ_MAX) { pwm.freq = PWM_FREQ_MAX; } else if (freq < 1) { pwm.freq = 1; } else { pwm.freq = freq; } pwm.period = PWM_1S / pwm.freq; UNLOCK_PWM(critical); // leave critical } /****************************************************************************** * FunctionName : pwm_get_duty * Description : get duty of each channel * Parameters : uint8 channel : channel index * Returns : NONE *******************************************************************************/ uint16 ICACHE_FLASH_ATTR pwm_get_duty(uint8 channel) { uint8 i; for(i=0;i= (*pwm_channel - 1)) { // *pwm_channel may change outside pwm_single = pwm_single_toggle[local_toggle]; pwm_channel = &pwm_channel_toggle[local_toggle]; gpio_output_set(pwm_single[*pwm_channel - 1].gpio_set, pwm_single[*pwm_channel - 1].gpio_clear, pwm_gpio, 0); pwm_current_channel = 0; RTC_REG_WRITE(FRC1_LOAD_ADDRESS, pwm_single[pwm_current_channel].h_time); } else { gpio_output_set(pwm_single[pwm_current_channel].gpio_set, pwm_single[pwm_current_channel].gpio_clear, pwm_gpio, 0); pwm_current_channel++; RTC_REG_WRITE(FRC1_LOAD_ADDRESS, pwm_single[pwm_current_channel].h_time); } } /****************************************************************************** * FunctionName : pwm_init * Description : pwm gpio, params and timer initialization * Parameters : uint16 freq : pwm freq param * uint16 *duty : each channel's duty * Returns : NONE *******************************************************************************/ void ICACHE_FLASH_ATTR pwm_init(void) { uint8 i; RTC_REG_WRITE(FRC1_CTRL_ADDRESS, //FRC2_AUTO_RELOAD| DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT); RTC_REG_WRITE(FRC1_LOAD_ADDRESS, 0); for (i = 0; i < PWM_CHANNEL; i++) { pwm_gpio = 0; pwm.duty[i] = 0; } pwm_set_freq(500, 0); pwm_start(); ETS_FRC_TIMER1_INTR_ATTACH(pwm_tim1_intr_handler, NULL); TM1_EDGE_INT_ENABLE(); ETS_FRC1_INTR_ENABLE(); } int ICACHE_FLASH_ATTR pwm_add(uint8_t pin_id, uint32_t pin_mux, uint32_t pin_func){ PWM_DBG("--Function pwm_add() is called. channel:%d\n", channel); PWM_DBG("pwm_gpio:%x,pwm_channel_num:%d\n",pwm_gpio,pwm_channel_num); PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]); PWM_DBG("pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.duty[0],pwm.duty[1],pwm.duty[2]); int channel = -1; for (int i = 0; i < PWM_CHANNEL; ++i) { if (pin_num[i] == pin_id) { channel = i; break; } } if (channel == -1) { return -1; } uint8 i; for(i=0;i #include void pwm_init(void); void pwm_start(void); void pwm_set_duty(int16_t duty, uint8_t channel); uint16_t pwm_get_duty(uint8_t channel); void pwm_set_freq(uint16_t freq, uint8_t channel); uint16_t pwm_get_freq(uint8_t channel); int pwm_add(uint8_t pin_id, uint32_t pin_mux, uint32_t pin_func); bool pwm_delete(uint8_t channel); #endif // MICROPY_INCLUDED_ESP8266_ESPPWM_H micropython-1.12/ports/esp8266/ets_alt_task.c000066400000000000000000000145021357706137100211310ustar00rootroot00000000000000#include #include "osapi.h" #include "os_type.h" #include "ets_sys.h" #include #include "etshal.h" #include "user_interface.h" #include "ets_alt_task.h" // Use standard ets_task or alternative impl #define USE_ETS_TASK 0 #define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) struct task_entry { os_event_t *queue; os_task_t task; uint8_t qlen; uint8_t prio; int8_t i_get; int8_t i_put; }; static void (*idle_cb)(void *); static void *idle_arg; #if ESP_SDK_VERSION >= 010500 # define FIRST_PRIO 0 #else # define FIRST_PRIO 0x14 #endif #define LAST_PRIO 0x20 #define PRIO2ID(prio) ((prio) - FIRST_PRIO) volatile struct task_entry emu_tasks[PRIO2ID(LAST_PRIO) + 1]; static inline int prio2id(uint8_t prio) { int id = PRIO2ID(prio); if (id < 0 || id >= MP_ARRAY_SIZE(emu_tasks)) { printf("task prio out of range: %d\n", prio); while (1); } return id; } #if DEBUG void dump_task(int prio, volatile struct task_entry *t) { printf("q for task %d: queue: %p, get ptr: %d, put ptr: %d, qlen: %d\n", prio, t->queue, t->i_get, t->i_put, t->qlen); } void dump_tasks(void) { for (int i = 0; i < MP_ARRAY_SIZE(emu_tasks); i++) { if (emu_tasks[i].qlen) { dump_task(i + FIRST_PRIO, &emu_tasks[i]); } } printf("====\n"); } #endif bool ets_task(os_task_t task, uint8 prio, os_event_t *queue, uint8 qlen) { static unsigned cnt; printf("#%d ets_task(%p, %d, %p, %d)\n", cnt++, task, prio, queue, qlen); #if USE_ETS_TASK return _ets_task(task, prio, queue, qlen); #else int id = prio2id(prio); emu_tasks[id].task = task; emu_tasks[id].queue = queue; emu_tasks[id].qlen = qlen; emu_tasks[id].i_get = 0; emu_tasks[id].i_put = 0; return true; #endif } bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) { // static unsigned cnt; printf("#%d ets_post(%d, %x, %x)\n", cnt++, prio, sig, param); #if USE_ETS_TASK return _ets_post(prio, sig, param); #else ets_intr_lock(); const int id = prio2id(prio); os_event_t *q = emu_tasks[id].queue; if (emu_tasks[id].i_put == -1) { // queue is full printf("ets_post: task %d queue full\n", prio); return 1; } q = &q[emu_tasks[id].i_put++]; q->sig = sig; q->par = param; if (emu_tasks[id].i_put == emu_tasks[id].qlen) { emu_tasks[id].i_put = 0; } if (emu_tasks[id].i_put == emu_tasks[id].i_get) { // queue got full emu_tasks[id].i_put = -1; } //printf("after ets_post: "); dump_task(prio, &emu_tasks[id]); //dump_tasks(); ets_intr_unlock(); return 0; #endif } int ets_loop_iter_disable = 0; int ets_loop_dont_feed_sw_wdt = 0; // to implement a 64-bit wide microsecond counter uint32_t system_time_low_word = 0; uint32_t system_time_high_word = 0; void system_time_update(void) { // Handle overflow of system microsecond counter ets_intr_lock(); uint32_t system_time_cur = system_get_time(); if (system_time_cur < system_time_low_word) { system_time_high_word += 1; // record overflow of low 32-bits } system_time_low_word = system_time_cur; ets_intr_unlock(); } bool ets_loop_iter(void) { if (ets_loop_iter_disable) { return false; } // Update 64-bit microsecond counter system_time_update(); // 6 words before pend_flag_noise_check is a variable that is used by // the software WDT. A 1.6 second period timer will increment this // variable and if it gets to 2 then the SW WDT will trigger a reset. extern uint32_t pend_flag_noise_check; uint32_t *sw_wdt = &pend_flag_noise_check - 6; //static unsigned cnt; bool progress = false; for (volatile struct task_entry *t = emu_tasks; t < &emu_tasks[MP_ARRAY_SIZE(emu_tasks)]; t++) { if (!ets_loop_dont_feed_sw_wdt) { system_soft_wdt_feed(); } ets_intr_lock(); //printf("etc_loop_iter: "); dump_task(t - emu_tasks + FIRST_PRIO, t); if (t->i_get != t->i_put) { progress = true; //printf("#%d Calling task %d(%p) (%x, %x)\n", cnt++, // t - emu_tasks + FIRST_PRIO, t->task, t->queue[t->i_get].sig, t->queue[t->i_get].par); int idx = t->i_get; if (t->i_put == -1) { t->i_put = t->i_get; } if (++t->i_get == t->qlen) { t->i_get = 0; } //ets_intr_unlock(); uint32_t old_sw_wdt = *sw_wdt; t->task(&t->queue[idx]); if (ets_loop_dont_feed_sw_wdt) { // Restore previous SW WDT counter, in case task fed/cleared it *sw_wdt = old_sw_wdt; } //ets_intr_lock(); //printf("Done calling task %d\n", t - emu_tasks + FIRST_PRIO); } ets_intr_unlock(); } if (!progress && idle_cb) { idle_cb(idle_arg); } return progress; } #if SDK_BELOW_1_1_1 void my_timer_isr(void *arg) { // uart0_write_char('+'); ets_post(0x1f, 0, 0); } // Timer init func is in ROM, and calls ets_task by relative addr directly in ROM // so, we have to re-init task using our handler void ets_timer_init() { printf("ets_timer_init\n"); // _ets_timer_init(); ets_isr_attach(10, my_timer_isr, NULL); SET_PERI_REG_MASK(0x3FF00004, 4); ETS_INTR_ENABLE(10); ets_task((os_task_t)0x40002E3C, 0x1f, (os_event_t*)0x3FFFDDC0, 4); WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x30, 0); WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x28, 0x88); WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x30, 0); printf("Installed timer ISR\n"); } #endif bool ets_run(void) { #if USE_ETS_TASK #if SDK_BELOW_1_1_1 ets_isr_attach(10, my_timer_isr, NULL); #endif _ets_run(); #else // ets_timer_init(); *(char*)0x3FFFC6FC = 0; ets_intr_lock(); printf("ets_alt_task: ets_run\n"); #if DEBUG dump_tasks(); #endif ets_intr_unlock(); while (1) { if (!ets_loop_iter()) { //printf("idle\n"); ets_intr_lock(); if (idle_cb) { idle_cb(idle_arg); } asm("waiti 0"); ets_intr_unlock(); } } #endif } void ets_set_idle_cb(void (*handler)(void *), void *arg) { //printf("ets_set_idle_cb(%p, %p)\n", handler, arg); idle_cb = handler; idle_arg = arg; } micropython-1.12/ports/esp8266/ets_alt_task.h000066400000000000000000000005431357706137100211360ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_ESP8266_ETS_ALT_TASK_H #define MICROPY_INCLUDED_ESP8266_ETS_ALT_TASK_H extern int ets_loop_iter_disable; extern int ets_loop_dont_feed_sw_wdt; extern uint32_t system_time_low_word; extern uint32_t system_time_high_word; void system_time_update(void); bool ets_loop_iter(void); #endif // MICROPY_INCLUDED_ESP8266_ETS_ALT_TASK_H micropython-1.12/ports/esp8266/etshal.h000066400000000000000000000031421357706137100177370ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_ESP8266_ETSHAL_H #define MICROPY_INCLUDED_ESP8266_ETSHAL_H #include // see http://esp8266-re.foogod.com/wiki/Random_Number_Generator #define WDEV_HWRNG ((volatile uint32_t*)0x3ff20e44) void ets_delay_us(uint16_t us); void ets_intr_lock(void); void ets_intr_unlock(void); void ets_isr_mask(uint32_t mask); void ets_isr_unmask(uint32_t mask); void ets_isr_attach(int irq_no, void (*handler)(void *), void *arg); void ets_install_putc1(); void uart_div_modify(uint8_t uart, uint32_t divisor); void ets_set_idle_cb(void (*handler)(void *), void *arg); void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_milli_timer); void ets_timer_setfn(os_timer_t *tim, ETSTimerFunc callback, void *cb_data); void ets_timer_disarm(os_timer_t *tim); extern void ets_wdt_disable(void); extern void wdt_feed(void); // Opaque structure #ifndef MD5_CTX typedef char MD5_CTX[88]; #endif void MD5Init(MD5_CTX *context); void MD5Update(MD5_CTX *context, const void *data, unsigned int len); void MD5Final(unsigned char digest[16], MD5_CTX *context); // These prototypes are for recent SDKs with "malloc tracking" void *pvPortMalloc(size_t sz, const char *fname, unsigned line); void *pvPortZalloc(size_t sz, const char *fname, unsigned line); void *pvPortRealloc(void *p, unsigned sz, const char *fname, unsigned line); void vPortFree(void *p, const char *fname, unsigned line); uint32_t SPIRead(uint32_t offset, void *buf, uint32_t len); uint32_t SPIWrite(uint32_t offset, const void *buf, uint32_t len); uint32_t SPIEraseSector(int sector); #endif // MICROPY_INCLUDED_ESP8266_ETSHAL_H micropython-1.12/ports/esp8266/fatfs_port.c000066400000000000000000000034571357706137100206320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014, 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" #include "modmachine.h" DWORD get_fattime(void) { // TODO: Optimize division (there's no HW division support on ESP8266, // so it's expensive). uint32_t secs = (uint32_t)(pyb_rtc_get_us_since_2000() / 1000000); timeutils_struct_time_t tm; timeutils_seconds_since_2000_to_struct_time(secs, &tm); return (((DWORD)(tm.tm_year - 1980) << 25) | ((DWORD)tm.tm_mon << 21) | ((DWORD)tm.tm_mday << 16) | ((DWORD)tm.tm_hour << 11) | ((DWORD)tm.tm_min << 5) | ((DWORD)tm.tm_sec >> 1)); } micropython-1.12/ports/esp8266/gccollect.c000066400000000000000000000036021357706137100204120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/gc.h" #include "gccollect.h" // As we do not have control over the application entry point, there is no way // to figure out the real stack base on runtime, so it needs to be hardcoded #define STACK_END 0x40000000 mp_uint_t gc_helper_get_regs_and_sp(mp_uint_t *regs); void gc_collect(void) { // start the GC gc_collect_start(); // get the registers and the sp mp_uint_t regs[8]; mp_uint_t sp = gc_helper_get_regs_and_sp(regs); // trace the stack, including the registers (since they live on the stack in this function) gc_collect_root((void**)sp, (STACK_END - sp) / sizeof(uint32_t)); // end the GC gc_collect_end(); } micropython-1.12/ports/esp8266/gccollect.h000066400000000000000000000033121357706137100204150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_ESP8266_GCCOLLECT_H #define MICROPY_INCLUDED_ESP8266_GCCOLLECT_H extern uint32_t _text_start; extern uint32_t _text_end; extern uint32_t _irom0_text_start; extern uint32_t _irom0_text_end; extern uint32_t _data_start; extern uint32_t _data_end; extern uint32_t _rodata_start; extern uint32_t _rodata_end; extern uint32_t _bss_start; extern uint32_t _bss_end; extern uint32_t _heap_start; extern uint32_t _heap_end; void gc_collect(void); #endif // MICROPY_INCLUDED_ESP8266_GCCOLLECT_H micropython-1.12/ports/esp8266/gchelper.s000066400000000000000000000007671357706137100202750ustar00rootroot00000000000000 .file "gchelper.s" .text .align 4 .global gc_helper_get_regs_and_sp .type gc_helper_get_regs_and_sp, @function gc_helper_get_regs_and_sp: # store regs into given array s32i.n a8, a2, 0 s32i.n a9, a2, 4 s32i.n a10, a2, 8 s32i.n a11, a2, 12 s32i.n a12, a2, 16 s32i.n a13, a2, 20 s32i.n a14, a2, 24 s32i.n a15, a2, 28 # return the sp mov a2, a1 ret.n .size gc_helper_get_regs_and_sp, .-gc_helper_get_regs_and_sp micropython-1.12/ports/esp8266/help.c000066400000000000000000000045541357706137100174120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" const char esp_help_text[] = "Welcome to MicroPython!\n" "\n" "For online docs please visit http://docs.micropython.org/en/latest/esp8266/ .\n" "For diagnostic information to include in bug reports execute 'import port_diag'.\n" "\n" "Basic WiFi configuration:\n" "\n" "import network\n" "sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n" "sta_if.scan() # Scan for available access points\n" "sta_if.connect(\"\", \"\") # Connect to an AP\n" "sta_if.isconnected() # Check for successful connection\n" "# Change name/password of ESP8266's AP:\n" "ap_if = network.WLAN(network.AP_IF)\n" "ap_if.config(essid=\"\", authmode=network.AUTH_WPA_WPA2_PSK, password=\"\")\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" " CTRL-B -- on a blank line, enter normal REPL mode\n" " CTRL-C -- interrupt a running program\n" " CTRL-D -- on a blank line, do a soft reset of the board\n" " CTRL-E -- on a blank line, enter paste mode\n" "\n" "For further help on a specific object, type help(obj)\n" ; micropython-1.12/ports/esp8266/hspi.c000066400000000000000000000310171357706137100174170ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2015 David Ogilvy (MetalPhreak) * Modified 2016 by Radomir Dopieralski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "hspi.h" /* Wrapper to setup HSPI/SPI GPIO pins and default SPI clock spi_no - SPI (0) or HSPI (1) Not used in MicroPython. */ void spi_init(uint8_t spi_no) { spi_init_gpio(spi_no, SPI_CLK_USE_DIV); spi_clock(spi_no, SPI_CLK_PREDIV, SPI_CLK_CNTDIV); spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW); spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW); SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE); } /* Configures SPI mode parameters for clock edge and clock polarity. spi_no - SPI (0) or HSPI (1) spi_cpha - (0) Data is valid on clock leading edge (1) Data is valid on clock trailing edge spi_cpol - (0) Clock is low when inactive (1) Clock is high when inactive For MicroPython this version is different from original. */ void spi_mode(uint8_t spi_no, uint8_t spi_cpha, uint8_t spi_cpol) { if (spi_cpol) { SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE); } else { CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE); } if (spi_cpha == spi_cpol) { // Mode 3 - MOSI is set on falling edge of clock // Mode 0 - MOSI is set on falling edge of clock CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE); SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE); } else { // Mode 2 - MOSI is set on rising edge of clock // Mode 1 - MOSI is set on rising edge of clock SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE); CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE); } } /* Initialise the GPIO pins for use as SPI pins. spi_no - SPI (0) or HSPI (1) sysclk_as_spiclk - SPI_CLK_80MHZ_NODIV (1) if using 80MHz for SPI clock. SPI_CLK_USE_DIV (0) if using divider for lower speed. */ void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk) { uint32_t clock_div_flag = 0; if (sysclk_as_spiclk) { clock_div_flag = 0x0001; } if (spi_no == SPI) { // Set bit 8 if 80MHz sysclock required WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div_flag<<8)); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1); } else if (spi_no == HSPI) { // Set bit 9 if 80MHz sysclock required WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div_flag<<9)); // GPIO12 is HSPI MISO pin (Master Data In) PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); // GPIO13 is HSPI MOSI pin (Master Data Out) PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); // GPIO14 is HSPI CLK pin (Clock) PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); // GPIO15 is HSPI CS pin (Chip Select / Slave Select) // In MicroPython, we are handling CS ourself in drivers. // PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); } } /* Set up the control registers for the SPI clock spi_no - SPI (0) or HSPI (1) prediv - predivider value (actual division value) cntdiv - postdivider value (actual division value) Set either divider to 0 to disable all division (80MHz sysclock) */ void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv) { if (prediv == 0 || cntdiv == 0) { WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK); } else { WRITE_PERI_REG(SPI_CLOCK(spi_no), (((prediv - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) | (((cntdiv - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) | (((cntdiv >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) | ((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S) ); } } /* Setup the byte order for shifting data out of buffer spi_no - SPI (0) or HSPI (1) byte_order - SPI_BYTE_ORDER_HIGH_TO_LOW (1) Data is sent out starting with Bit31 and down to Bit0 SPI_BYTE_ORDER_LOW_TO_HIGH (0) Data is sent out starting with the lowest BYTE, from MSB to LSB, followed by the second lowest BYTE, from MSB to LSB, followed by the second highest BYTE, from MSB to LSB, followed by the highest BYTE, from MSB to LSB 0xABCDEFGH would be sent as 0xGHEFCDAB. */ void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order) { if (byte_order) { SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER); } else { CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER); } } /* Setup the byte order for shifting data into buffer spi_no - SPI (0) or HSPI (1) byte_order - SPI_BYTE_ORDER_HIGH_TO_LOW (1) Data is read in starting with Bit31 and down to Bit0 SPI_BYTE_ORDER_LOW_TO_HIGH (0) Data is read in starting with the lowest BYTE, from MSB to LSB, followed by the second lowest BYTE, from MSB to LSB, followed by the second highest BYTE, from MSB to LSB, followed by the highest BYTE, from MSB to LSB 0xABCDEFGH would be read as 0xGHEFCDAB */ void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order) { if (byte_order) { SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER); } else { CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER); } } /* SPI transaction function spi_no - SPI (0) or HSPI (1) cmd_bits - actual number of bits to transmit cmd_data - command data addr_bits - actual number of bits to transmit addr_data - address data dout_bits - actual number of bits to transmit dout_data - output data din_bits - actual number of bits to receive Returns: read data - uint32_t containing read in data only if RX was set 0 - something went wrong (or actual read data was 0) 1 - data sent ok (or actual read data is 1) Note: all data is assumed to be stored in the lower bits of the data variables (for anything <32 bits). */ uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data, uint32_t addr_bits, uint32_t addr_data, uint32_t dout_bits, uint32_t dout_data, uint32_t din_bits, uint32_t dummy_bits) { while (spi_busy(spi_no)) {}; // Wait for SPI to be ready // Enable SPI Functions // Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set. CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO | SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY); // Enable functions based on number of bits. 0 bits = disabled. // This is rather inefficient but allows for a very generic function. // CMD ADDR and MOSI are set below to save on an extra if statement. if (din_bits) { if (dout_bits) { SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_DOUTDIN); } else { SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO); } } if (dummy_bits) { SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY); } // Setup Bitlengths WRITE_PERI_REG(SPI_USER1(spi_no), // Number of bits in Address ((addr_bits - 1) & SPI_USR_ADDR_BITLEN) << SPI_USR_ADDR_BITLEN_S | // Number of bits to Send ((dout_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S | // Number of bits to receive ((din_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S | // Number of Dummy bits to insert ((dummy_bits - 1) & SPI_USR_DUMMY_CYCLELEN) << SPI_USR_DUMMY_CYCLELEN_S); // Setup Command Data if (cmd_bits) { // Enable COMMAND function in SPI module SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND); // Align command data to high bits uint16_t command = cmd_data << (16-cmd_bits); // Swap byte order command = ((command>>8)&0xff) | ((command<<8)&0xff00); WRITE_PERI_REG(SPI_USER2(spi_no), ( (((cmd_bits - 1) & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | (command & SPI_USR_COMMAND_VALUE) )); } // Setup Address Data if (addr_bits) { // Enable ADDRess function in SPI module SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR); // Align address data to high bits WRITE_PERI_REG(SPI_ADDR(spi_no), addr_data << (32 - addr_bits)); } // Setup DOUT data if (dout_bits) { // Enable MOSI function in SPI module SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI); // Copy data to W0 if (READ_PERI_REG(SPI_USER(spi_no))&SPI_WR_BYTE_ORDER) { WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - dout_bits)); } else { uint8_t dout_extra_bits = dout_bits%8; if (dout_extra_bits) { // If your data isn't a byte multiple (8/16/24/32 bits) and you // don't have SPI_WR_BYTE_ORDER set, you need this to move the // non-8bit remainder to the MSBs. Not sure if there's even a use // case for this, but it's here if you need it... For example, // 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output // as if it were 0x0DA4, of which 0xA4, and then 0x0 would be // shifted out (first 8 bits of low byte, then 4 MSB bits of high // byte - ie reverse byte order). // The code below shifts it out as 0xA4 followed by 0xD as you // might require. WRITE_PERI_REG(SPI_W0(spi_no), ( (0xFFFFFFFF << (dout_bits - dout_extra_bits) & dout_data) << (8-dout_extra_bits) | ((0xFFFFFFFF >> (32 - (dout_bits - dout_extra_bits))) & dout_data) )); } else { WRITE_PERI_REG(SPI_W0(spi_no), dout_data); } } } // Begin SPI Transaction SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR); // Return DIN data if (din_bits) { while (spi_busy(spi_no)) {}; // Wait for SPI transaction to complete if (READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) { // Assuming data in is written to MSB. TBC return READ_PERI_REG(SPI_W0(spi_no)) >> (32 - din_bits); } else { // Read in the same way as DOUT is sent. Note existing contents of // SPI_W0 remain unless overwritten! return READ_PERI_REG(SPI_W0(spi_no)); } return 0; // Something went wrong } // Transaction completed return 1; // Success } /* Just do minimal work needed to send 8 bits. */ inline void spi_tx8fast(uint8_t spi_no, uint8_t dout_data) { while (spi_busy(spi_no)) {}; // Wait for SPI to be ready // Enable SPI Functions // Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set. CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO | SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY); // Setup Bitlengths WRITE_PERI_REG(SPI_USER1(spi_no), // Number of bits to Send ((8 - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S | // Number of bits to receive ((8 - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S); // Setup DOUT data // Enable MOSI function in SPI module SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI); // Copy data to W0 if (READ_PERI_REG(SPI_USER(spi_no)) & SPI_WR_BYTE_ORDER) { WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - 8)); } else { WRITE_PERI_REG(SPI_W0(spi_no), dout_data); } // Begin SPI Transaction SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR); } micropython-1.12/ports/esp8266/hspi.h000066400000000000000000000063231357706137100174260ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2015 David Ogilvy (MetalPhreak) * Modified 2016 by Radomir Dopieralski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef SPI_APP_H #define SPI_APP_H #include "hspi_register.h" #include "ets_sys.h" #include "osapi.h" #include "os_type.h" // Define SPI hardware modules #define SPI 0 #define HSPI 1 #define SPI_CLK_USE_DIV 0 #define SPI_CLK_80MHZ_NODIV 1 #define SPI_BYTE_ORDER_HIGH_TO_LOW 1 #define SPI_BYTE_ORDER_LOW_TO_HIGH 0 #ifndef CPU_CLK_FREQ //Should already be defined in eagle_soc.h #define CPU_CLK_FREQ (80 * 1000000) #endif // Define some default SPI clock settings #define SPI_CLK_PREDIV 10 #define SPI_CLK_CNTDIV 2 #define SPI_CLK_FREQ (CPU_CLK_FREQ / (SPI_CLK_PREDIV * SPI_CLK_CNTDIV)) // 80 / 20 = 4 MHz void spi_init(uint8_t spi_no); void spi_mode(uint8_t spi_no, uint8_t spi_cpha,uint8_t spi_cpol); void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk); void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv); void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order); void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order); uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data, uint32_t addr_bits, uint32_t addr_data, uint32_t dout_bits, uint32_t dout_data, uint32_t din_bits, uint32_t dummy_bits); void spi_tx8fast(uint8_t spi_no, uint8_t dout_data); // Expansion Macros #define spi_busy(spi_no) READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR #define spi_txd(spi_no, bits, data) spi_transaction(spi_no, 0, 0, 0, 0, bits, (uint32_t) data, 0, 0) #define spi_tx8(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 8, (uint32_t) data, 0, 0) #define spi_tx16(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 16, (uint32_t) data, 0, 0) #define spi_tx32(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 32, (uint32_t) data, 0, 0) #define spi_rxd(spi_no, bits) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, bits, 0) #define spi_rx8(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 8, 0) #define spi_rx16(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 16, 0) #define spi_rx32(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 32, 0) #endif micropython-1.12/ports/esp8266/hspi_register.h000066400000000000000000000263661357706137100213430ustar00rootroot00000000000000/* * Copyright (c) 2010 - 2011 Espressif System * Modified by David Ogilvy (MetalPhreak) * Based on original file included in SDK 1.0.0 * * Missing defines from previous SDK versions have * been added and are noted with comments. The * names of these defines are likely to change. */ #ifndef SPI_REGISTER_H_INCLUDED #define SPI_REGISTER_H_INCLUDED #define REG_SPI_BASE(i) (0x60000200-i*0x100) #define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0) #define SPI_FLASH_READ (BIT(31)) //From previous SDK #define SPI_FLASH_WREN (BIT(30)) //From previous SDK #define SPI_FLASH_WRDI (BIT(29)) //From previous SDK #define SPI_FLASH_RDID (BIT(28)) //From previous SDK #define SPI_FLASH_RDSR (BIT(27)) //From previous SDK #define SPI_FLASH_WRSR (BIT(26)) //From previous SDK #define SPI_FLASH_PP (BIT(25)) //From previous SDK #define SPI_FLASH_SE (BIT(24)) //From previous SDK #define SPI_FLASH_BE (BIT(23)) //From previous SDK #define SPI_FLASH_CE (BIT(22)) //From previous SDK #define SPI_FLASH_DP (BIT(21)) //From previous SDK #define SPI_FLASH_RES (BIT(20)) //From previous SDK #define SPI_FLASH_HPM (BIT(19)) //From previous SDK #define SPI_USR (BIT(18)) #define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4) #define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8) #define SPI_WR_BIT_ORDER (BIT(26)) #define SPI_RD_BIT_ORDER (BIT(25)) #define SPI_QIO_MODE (BIT(24)) #define SPI_DIO_MODE (BIT(23)) #define SPI_TWO_BYTE_STATUS_EN (BIT(22)) //From previous SDK #define SPI_WP_REG (BIT(21)) //From previous SDK #define SPI_QOUT_MODE (BIT(20)) #define SPI_SHARE_BUS (BIT(19)) //From previous SDK #define SPI_HOLD_MODE (BIT(18)) //From previous SDK #define SPI_ENABLE_AHB (BIT(17)) //From previous SDK #define SPI_SST_AAI (BIT(16)) //From previous SDK #define SPI_RESANDRES (BIT(15)) //From previous SDK #define SPI_DOUT_MODE (BIT(14)) #define SPI_FASTRD_MODE (BIT(13)) #define SPI_CTRL1(i) (REG_SPI_BASE (i) + 0xC) //From previous SDK. Removed _FLASH_ from name to match other registers. #define SPI_CS_HOLD_DELAY 0x0000000F //Espressif BBS #define SPI_CS_HOLD_DELAY_S 28 //Espressif BBS #define SPI_CS_HOLD_DELAY_RES 0x00000FFF //Espressif BBS #define SPI_CS_HOLD_DELAY_RES_S 16 //Espressif BBS #define SPI_BUS_TIMER_LIMIT 0x0000FFFF //From previous SDK #define SPI_BUS_TIMER_LIMIT_S 0 //From previous SDK #define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10) #define SPI_STATUS_EXT 0x000000FF //From previous SDK #define SPI_STATUS_EXT_S 24 //From previous SDK #define SPI_WB_MODE 0x000000FF //From previous SDK #define SPI_WB_MODE_S 16 //From previous SDK #define SPI_FLASH_STATUS_PRO_FLAG (BIT(7)) //From previous SDK #define SPI_FLASH_TOP_BOT_PRO_FLAG (BIT(5)) //From previous SDK #define SPI_FLASH_BP2 (BIT(4)) //From previous SDK #define SPI_FLASH_BP1 (BIT(3)) //From previous SDK #define SPI_FLASH_BP0 (BIT(2)) //From previous SDK #define SPI_FLASH_WRENABLE_FLAG (BIT(1)) //From previous SDK #define SPI_FLASH_BUSY_FLAG (BIT(0)) //From previous SDK #define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14) #define SPI_CS_DELAY_NUM 0x0000000F #define SPI_CS_DELAY_NUM_S 28 #define SPI_CS_DELAY_MODE 0x00000003 #define SPI_CS_DELAY_MODE_S 26 #define SPI_MOSI_DELAY_NUM 0x00000007 #define SPI_MOSI_DELAY_NUM_S 23 #define SPI_MOSI_DELAY_MODE 0x00000003 //mode 0 : posedge; data set at positive edge of clk //mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk //mode 2 : Do not use this mode. #define SPI_MOSI_DELAY_MODE_S 21 #define SPI_MISO_DELAY_NUM 0x00000007 #define SPI_MISO_DELAY_NUM_S 18 #define SPI_MISO_DELAY_MODE 0x00000003 #define SPI_MISO_DELAY_MODE_S 16 #define SPI_CK_OUT_HIGH_MODE 0x0000000F #define SPI_CK_OUT_HIGH_MODE_S 12 #define SPI_CK_OUT_LOW_MODE 0x0000000F #define SPI_CK_OUT_LOW_MODE_S 8 #define SPI_HOLD_TIME 0x0000000F #define SPI_HOLD_TIME_S 4 #define SPI_SETUP_TIME 0x0000000F #define SPI_SETUP_TIME_S 0 #define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18) #define SPI_CLK_EQU_SYSCLK (BIT(31)) #define SPI_CLKDIV_PRE 0x00001FFF #define SPI_CLKDIV_PRE_S 18 #define SPI_CLKCNT_N 0x0000003F #define SPI_CLKCNT_N_S 12 #define SPI_CLKCNT_H 0x0000003F #define SPI_CLKCNT_H_S 6 #define SPI_CLKCNT_L 0x0000003F #define SPI_CLKCNT_L_S 0 #define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C) #define SPI_USR_COMMAND (BIT(31)) #define SPI_USR_ADDR (BIT(30)) #define SPI_USR_DUMMY (BIT(29)) #define SPI_USR_MISO (BIT(28)) #define SPI_USR_MOSI (BIT(27)) #define SPI_USR_DUMMY_IDLE (BIT(26)) //From previous SDK #define SPI_USR_MOSI_HIGHPART (BIT(25)) #define SPI_USR_MISO_HIGHPART (BIT(24)) #define SPI_USR_PREP_HOLD (BIT(23)) //From previous SDK #define SPI_USR_CMD_HOLD (BIT(22)) //From previous SDK #define SPI_USR_ADDR_HOLD (BIT(21)) //From previous SDK #define SPI_USR_DUMMY_HOLD (BIT(20)) //From previous SDK #define SPI_USR_DIN_HOLD (BIT(19)) //From previous SDK #define SPI_USR_DOUT_HOLD (BIT(18)) //From previous SDK #define SPI_USR_HOLD_POL (BIT(17)) //From previous SDK #define SPI_SIO (BIT(16)) #define SPI_FWRITE_QIO (BIT(15)) #define SPI_FWRITE_DIO (BIT(14)) #define SPI_FWRITE_QUAD (BIT(13)) #define SPI_FWRITE_DUAL (BIT(12)) #define SPI_WR_BYTE_ORDER (BIT(11)) #define SPI_RD_BYTE_ORDER (BIT(10)) #define SPI_AHB_ENDIAN_MODE 0x00000003 //From previous SDK #define SPI_AHB_ENDIAN_MODE_S 8 //From previous SDK #define SPI_CK_OUT_EDGE (BIT(7)) #define SPI_CK_I_EDGE (BIT(6)) #define SPI_CS_SETUP (BIT(5)) #define SPI_CS_HOLD (BIT(4)) #define SPI_AHB_USR_COMMAND (BIT(3)) //From previous SDK #define SPI_FLASH_MODE (BIT(2)) #define SPI_AHB_USR_COMMAND_4BYTE (BIT(1)) //From previous SDK #define SPI_DOUTDIN (BIT(0)) //From previous SDK //AHB = http://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture ? #define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20) #define SPI_USR_ADDR_BITLEN 0x0000003F #define SPI_USR_ADDR_BITLEN_S 26 #define SPI_USR_MOSI_BITLEN 0x000001FF #define SPI_USR_MOSI_BITLEN_S 17 #define SPI_USR_MISO_BITLEN 0x000001FF #define SPI_USR_MISO_BITLEN_S 8 #define SPI_USR_DUMMY_CYCLELEN 0x000000FF #define SPI_USR_DUMMY_CYCLELEN_S 0 #define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24) #define SPI_USR_COMMAND_BITLEN 0x0000000F #define SPI_USR_COMMAND_BITLEN_S 28 #define SPI_USR_COMMAND_VALUE 0x0000FFFF #define SPI_USR_COMMAND_VALUE_S 0 #define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28) //previously defined as SPI_FLASH_USER3. No further info available. #define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C) #define SPI_IDLE_EDGE (BIT(29)) #define SPI_CS2_DIS (BIT(2)) #define SPI_CS1_DIS (BIT(1)) #define SPI_CS0_DIS (BIT(0)) #define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30) #define SPI_SYNC_RESET (BIT(31)) #define SPI_SLAVE_MODE (BIT(30)) #define SPI_SLV_WR_RD_BUF_EN (BIT(29)) #define SPI_SLV_WR_RD_STA_EN (BIT(28)) #define SPI_SLV_CMD_DEFINE (BIT(27)) #define SPI_TRANS_CNT 0x0000000F #define SPI_TRANS_CNT_S 23 #define SPI_SLV_LAST_STATE 0x00000007 //From previous SDK #define SPI_SLV_LAST_STATE_S 20 //From previous SDK #define SPI_SLV_LAST_COMMAND 0x00000007 //From previous SDK #define SPI_SLV_LAST_COMMAND_S 17 //From previous SDK #define SPI_CS_I_MODE 0x00000003 //From previous SDK #define SPI_CS_I_MODE_S 10 //From previous SDK #define SPI_TRANS_DONE_EN (BIT(9)) #define SPI_SLV_WR_STA_DONE_EN (BIT(8)) #define SPI_SLV_RD_STA_DONE_EN (BIT(7)) #define SPI_SLV_WR_BUF_DONE_EN (BIT(6)) #define SPI_SLV_RD_BUF_DONE_EN (BIT(5)) #define SLV_SPI_INT_EN 0x0000001f #define SLV_SPI_INT_EN_S 5 #define SPI_TRANS_DONE (BIT(4)) #define SPI_SLV_WR_STA_DONE (BIT(3)) #define SPI_SLV_RD_STA_DONE (BIT(2)) #define SPI_SLV_WR_BUF_DONE (BIT(1)) #define SPI_SLV_RD_BUF_DONE (BIT(0)) #define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34) #define SPI_SLV_STATUS_BITLEN 0x0000001F #define SPI_SLV_STATUS_BITLEN_S 27 #define SPI_SLV_STATUS_FAST_EN (BIT(26)) //From previous SDK #define SPI_SLV_STATUS_READBACK (BIT(25)) //From previous SDK #define SPI_SLV_BUF_BITLEN 0x000001FF #define SPI_SLV_BUF_BITLEN_S 16 #define SPI_SLV_RD_ADDR_BITLEN 0x0000003F #define SPI_SLV_RD_ADDR_BITLEN_S 10 #define SPI_SLV_WR_ADDR_BITLEN 0x0000003F #define SPI_SLV_WR_ADDR_BITLEN_S 4 #define SPI_SLV_WRSTA_DUMMY_EN (BIT(3)) #define SPI_SLV_RDSTA_DUMMY_EN (BIT(2)) #define SPI_SLV_WRBUF_DUMMY_EN (BIT(1)) #define SPI_SLV_RDBUF_DUMMY_EN (BIT(0)) #define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38) #define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF #define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24 #define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF #define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16 #define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF #define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8 #define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF #define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0 #define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C) #define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF #define SPI_SLV_WRSTA_CMD_VALUE_S 24 #define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF #define SPI_SLV_RDSTA_CMD_VALUE_S 16 #define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF #define SPI_SLV_WRBUF_CMD_VALUE_S 8 #define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF #define SPI_SLV_RDBUF_CMD_VALUE_S 0 //Previous SDKs referred to these following registers as SPI_C0 etc. #define SPI_W0(i) (REG_SPI_BASE(i) +0x40) #define SPI_W1(i) (REG_SPI_BASE(i) +0x44) #define SPI_W2(i) (REG_SPI_BASE(i) +0x48) #define SPI_W3(i) (REG_SPI_BASE(i) +0x4C) #define SPI_W4(i) (REG_SPI_BASE(i) +0x50) #define SPI_W5(i) (REG_SPI_BASE(i) +0x54) #define SPI_W6(i) (REG_SPI_BASE(i) +0x58) #define SPI_W7(i) (REG_SPI_BASE(i) +0x5C) #define SPI_W8(i) (REG_SPI_BASE(i) +0x60) #define SPI_W9(i) (REG_SPI_BASE(i) +0x64) #define SPI_W10(i) (REG_SPI_BASE(i) +0x68) #define SPI_W11(i) (REG_SPI_BASE(i) +0x6C) #define SPI_W12(i) (REG_SPI_BASE(i) +0x70) #define SPI_W13(i) (REG_SPI_BASE(i) +0x74) #define SPI_W14(i) (REG_SPI_BASE(i) +0x78) #define SPI_W15(i) (REG_SPI_BASE(i) +0x7C) // +0x80 to +0xBC could be SPI_W16 through SPI_W31? // +0xC0 to +0xEC not currently defined. #define SPI_EXT0(i) (REG_SPI_BASE(i) + 0xF0) //From previous SDK. Removed _FLASH_ from name to match other registers. #define SPI_T_PP_ENA (BIT(31)) //From previous SDK #define SPI_T_PP_SHIFT 0x0000000F //From previous SDK #define SPI_T_PP_SHIFT_S 16 //From previous SDK #define SPI_T_PP_TIME 0x00000FFF //From previous SDK #define SPI_T_PP_TIME_S 0 //From previous SDK #define SPI_EXT1(i) (REG_SPI_BASE(i) + 0xF4) //From previous SDK. Removed _FLASH_ from name to match other registers. #define SPI_T_ERASE_ENA (BIT(31)) //From previous SDK #define SPI_T_ERASE_SHIFT 0x0000000F //From previous SDK #define SPI_T_ERASE_SHIFT_S 16 //From previous SDK #define SPI_T_ERASE_TIME 0x00000FFF //From previous SDK #define SPI_T_ERASE_TIME_S 0 //From previous SDK #define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) //From previous SDK. Removed _FLASH_ from name to match other registers. #define SPI_ST 0x00000007 //From previous SDK #define SPI_ST_S 0 //From previous SDK #define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) #define SPI_INT_HOLD_ENA 0x00000003 #define SPI_INT_HOLD_ENA_S 0 #endif // SPI_REGISTER_H_INCLUDED micropython-1.12/ports/esp8266/intr.c000066400000000000000000000027751357706137100174410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "etshal.h" #include "ets_alt_task.h" #include "modmachine.h" // this is in a separate file so it can go in iRAM void pin_intr_handler_iram(void *arg) { uint32_t status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, status); pin_intr_handler(status); } micropython-1.12/ports/esp8266/lexerstr32.c000066400000000000000000000045441357706137100204760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/lexer.h" #if MICROPY_ENABLE_COMPILER typedef struct _mp_lexer_str32_buf_t { const uint32_t *src_cur; uint32_t val; uint8_t byte_off; } mp_lexer_str32_buf_t; STATIC mp_uint_t str32_buf_next_byte(void *sb_in) { mp_lexer_str32_buf_t *sb = (mp_lexer_str32_buf_t*)sb_in; byte c = sb->val & 0xff; if (c == 0) { return MP_READER_EOF; } if (++sb->byte_off > 3) { sb->byte_off = 0; sb->val = *sb->src_cur++; } else { sb->val >>= 8; } return c; } STATIC void str32_buf_free(void *sb_in) { mp_lexer_str32_buf_t *sb = (mp_lexer_str32_buf_t*)sb_in; m_del_obj(mp_lexer_str32_buf_t, sb); } mp_lexer_t *mp_lexer_new_from_str32(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len) { mp_lexer_str32_buf_t *sb = m_new_obj(mp_lexer_str32_buf_t); sb->byte_off = (uint32_t)str & 3; sb->src_cur = (uint32_t*)(str - sb->byte_off); sb->val = *sb->src_cur++ >> sb->byte_off * 8; mp_reader_t reader = {sb, str32_buf_next_byte, str32_buf_free}; return mp_lexer_new(src_name, reader); } #endif // MICROPY_ENABLE_COMPILER micropython-1.12/ports/esp8266/machine_adc.c000066400000000000000000000066541357706137100207000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Josef Gajdusek * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "user_interface.h" typedef struct _machine_adc_obj_t { mp_obj_base_t base; bool isvdd; } machine_adc_obj_t; extern const mp_obj_type_t machine_adc_type; STATIC machine_adc_obj_t machine_adc_vdd3 = {{&machine_adc_type}, true}; STATIC machine_adc_obj_t machine_adc_adc = {{&machine_adc_type}, false}; STATIC uint16_t adc_read(machine_adc_obj_t *self) { if (self->isvdd) { return system_get_vdd33(); } else { return system_adc_read(); } } void machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "ADC(%u)", self->isvdd); } mp_obj_t machine_adc_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_int_t chn = mp_obj_get_int(args[0]); switch (chn) { case 0: return &machine_adc_adc; case 1: return &machine_adc_vdd3; default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "ADC(%d) doesn't exist", chn)); } } // read_u16() STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) { machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); uint32_t value = adc_read(self); return MP_OBJ_NEW_SMALL_INT(value * 65535 / 1024); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16); // Legacy method STATIC mp_obj_t machine_adc_read(mp_obj_t self_in) { machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int(adc_read(self)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_obj, machine_adc_read); STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_adc_read_obj) } }; STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); const mp_obj_type_t machine_adc_type = { { &mp_type_type }, .name = MP_QSTR_ADC, .print = machine_adc_print, .make_new = machine_adc_make_new, .locals_dict = (mp_obj_dict_t*)&machine_adc_locals_dict, }; micropython-1.12/ports/esp8266/machine_hspi.c000066400000000000000000000152211357706137100211020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "ets_sys.h" #include "etshal.h" #include "ets_alt_task.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" #include "extmod/machine_spi.h" #include "modmachine.h" #include "hspi.h" #if MICROPY_PY_MACHINE_SPI typedef struct _machine_hspi_obj_t { mp_obj_base_t base; uint32_t baudrate; uint8_t polarity; uint8_t phase; } machine_hspi_obj_t; STATIC void machine_hspi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { (void)self_in; if (dest == NULL) { // fast case when we only need to write data size_t chunk_size = 1024; size_t count = len / chunk_size; size_t i = 0; for (size_t j = 0; j < count; ++j) { for (size_t k = 0; k < chunk_size; ++k) { spi_tx8fast(HSPI, src[i]); ++i; } ets_loop_iter(); } while (i < len) { spi_tx8fast(HSPI, src[i]); ++i; } // wait for SPI transaction to complete while (spi_busy(HSPI)) { } } else { // we need to read and write data // Process data in chunks, let the pending tasks run in between size_t chunk_size = 1024; // TODO this should depend on baudrate size_t count = len / chunk_size; size_t i = 0; for (size_t j = 0; j < count; ++j) { for (size_t k = 0; k < chunk_size; ++k) { dest[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, src[i], 8, 0); ++i; } ets_loop_iter(); } while (i < len) { dest[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, src[i], 8, 0); ++i; } } } /******************************************************************************/ // MicroPython bindings for HSPI STATIC void machine_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "HSPI(id=1, baudrate=%u, polarity=%u, phase=%u)", self->baudrate, self->polarity, self->phase); } STATIC void machine_hspi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { machine_hspi_obj_t *self = (machine_hspi_obj_t*)self_in; enum { ARG_baudrate, ARG_polarity, ARG_phase }; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_baudrate].u_int != -1) { self->baudrate = args[ARG_baudrate].u_int; } if (args[ARG_polarity].u_int != -1) { self->polarity = args[ARG_polarity].u_int; } if (args[ARG_phase].u_int != -1) { self->phase = args[ARG_phase].u_int; } if (self->baudrate == 80000000L) { // Special case for full speed. spi_init_gpio(HSPI, SPI_CLK_80MHZ_NODIV); spi_clock(HSPI, 0, 0); } else if (self->baudrate > 40000000L) { mp_raise_ValueError("impossible baudrate"); } else { uint32_t divider = 40000000L / self->baudrate; uint16_t prediv = MIN(divider, SPI_CLKDIV_PRE + 1); uint16_t cntdiv = (divider / prediv) * 2; // cntdiv has to be even if (cntdiv > SPI_CLKCNT_N + 1 || cntdiv == 0 || prediv == 0) { mp_raise_ValueError("impossible baudrate"); } self->baudrate = 80000000L / (prediv * cntdiv); spi_init_gpio(HSPI, SPI_CLK_USE_DIV); spi_clock(HSPI, prediv, cntdiv); } // TODO: Make the byte order configurable too (discuss param names) spi_tx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW); spi_rx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW); CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE | SPI_USR_MISO | SPI_USR_ADDR | SPI_USR_COMMAND | SPI_USR_DUMMY); // Clear Dual or Quad lines transmission mode CLEAR_PERI_REG_MASK(SPI_CTRL(HSPI), SPI_QIO_MODE | SPI_DIO_MODE | SPI_DOUT_MODE | SPI_QOUT_MODE); spi_mode(HSPI, self->phase, self->polarity); } mp_obj_t machine_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // args[0] holds the id of the peripheral if (args[0] != MP_OBJ_NEW_SMALL_INT(1)) { // FlashROM is on SPI0, so far we don't support its usage mp_raise_ValueError(NULL); } machine_hspi_obj_t *self = m_new_obj(machine_hspi_obj_t); self->base.type = &machine_hspi_type; // set defaults self->baudrate = 80000000L; self->polarity = 0; self->phase = 0; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); machine_hspi_init((mp_obj_base_t*)self, n_args - 1, args + 1, &kw_args); return MP_OBJ_FROM_PTR(self); } STATIC const mp_machine_spi_p_t machine_hspi_p = { .init = machine_hspi_init, .transfer = machine_hspi_transfer, }; const mp_obj_type_t machine_hspi_type = { { &mp_type_type }, .name = MP_QSTR_HSPI, .print = machine_hspi_print, .make_new = mp_machine_spi_make_new, // delegate to master constructor .protocol = &machine_hspi_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_spi_locals_dict, }; #endif // MICROPY_PY_MACHINE_SPI micropython-1.12/ports/esp8266/machine_pin.c000066400000000000000000000426021357706137100207300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014, 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "etshal.h" #include "c_types.h" #include "user_interface.h" #include "gpio.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" #include "extmod/virtpin.h" #include "modmachine.h" #define GET_TRIGGER(phys_port) \ GPIO_PIN_INT_TYPE_GET(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port))) #define SET_TRIGGER(phys_port, trig) \ (GPIO_REG_WRITE(GPIO_PIN_ADDR(phys_port), \ (GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)) & ~GPIO_PIN_INT_TYPE_MASK) \ | GPIO_PIN_INT_TYPE_SET(trig))) \ #define GPIO_MODE_INPUT (0) #define GPIO_MODE_OUTPUT (1) #define GPIO_MODE_OPEN_DRAIN (2) // synthesised #define GPIO_PULL_NONE (0) #define GPIO_PULL_UP (1) // Removed in SDK 1.1.0 //#define GPIO_PULL_DOWN (2) typedef struct _pin_irq_obj_t { mp_obj_base_t base; uint16_t phys_port; } pin_irq_obj_t; const pyb_pin_obj_t pyb_pin_obj[16 + 1] = { {{&pyb_pin_type}, 0, FUNC_GPIO0, PERIPHS_IO_MUX_GPIO0_U}, {{&pyb_pin_type}, 1, FUNC_GPIO1, PERIPHS_IO_MUX_U0TXD_U}, {{&pyb_pin_type}, 2, FUNC_GPIO2, PERIPHS_IO_MUX_GPIO2_U}, {{&pyb_pin_type}, 3, FUNC_GPIO3, PERIPHS_IO_MUX_U0RXD_U}, {{&pyb_pin_type}, 4, FUNC_GPIO4, PERIPHS_IO_MUX_GPIO4_U}, {{&pyb_pin_type}, 5, FUNC_GPIO5, PERIPHS_IO_MUX_GPIO5_U}, {{NULL}, 0, 0, 0}, {{NULL}, 0, 0, 0}, {{NULL}, 0, 0, 0}, {{&pyb_pin_type}, 9, FUNC_GPIO9, PERIPHS_IO_MUX_SD_DATA2_U}, {{&pyb_pin_type}, 10, FUNC_GPIO10, PERIPHS_IO_MUX_SD_DATA3_U}, {{NULL}, 0, 0, 0}, {{&pyb_pin_type}, 12, FUNC_GPIO12, PERIPHS_IO_MUX_MTDI_U}, {{&pyb_pin_type}, 13, FUNC_GPIO13, PERIPHS_IO_MUX_MTCK_U}, {{&pyb_pin_type}, 14, FUNC_GPIO14, PERIPHS_IO_MUX_MTMS_U}, {{&pyb_pin_type}, 15, FUNC_GPIO15, PERIPHS_IO_MUX_MTDO_U}, // GPIO16 is special, belongs to different register set, and // otherwise handled specially. {{&pyb_pin_type}, 16, -1, -1}, }; STATIC uint8_t pin_mode[16 + 1]; // forward declaration STATIC const pin_irq_obj_t pin_irq_obj[16]; // whether the irq is hard or soft STATIC bool pin_irq_is_hard[16]; void pin_init0(void) { ETS_GPIO_INTR_DISABLE(); ETS_GPIO_INTR_ATTACH(pin_intr_handler_iram, NULL); // disable all interrupts memset(&MP_STATE_PORT(pin_irq_handler)[0], 0, 16 * sizeof(mp_obj_t)); memset(pin_irq_is_hard, 0, sizeof(pin_irq_is_hard)); for (int p = 0; p < 16; ++p) { GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << p); SET_TRIGGER(p, 0); } ETS_GPIO_INTR_ENABLE(); } void pin_intr_handler(uint32_t status) { mp_sched_lock(); gc_lock(); status &= 0xffff; for (int p = 0; status; ++p, status >>= 1) { if (status & 1) { mp_obj_t handler = MP_STATE_PORT(pin_irq_handler)[p]; if (handler != MP_OBJ_NULL) { if (pin_irq_is_hard[p]) { mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p])); } else { mp_sched_schedule(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p])); } } } } gc_unlock(); mp_sched_unlock(); } pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) { if (mp_obj_get_type(pin_in) != &pyb_pin_type) { mp_raise_ValueError("expecting a pin"); } pyb_pin_obj_t *self = pin_in; return self; } uint mp_obj_get_pin(mp_obj_t pin_in) { return mp_obj_get_pin_obj(pin_in)->phys_port; } void mp_hal_pin_input(mp_hal_pin_obj_t pin_id) { pin_mode[pin_id] = GPIO_MODE_INPUT; if (pin_id == 16) { WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input } else { const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id]; PIN_FUNC_SELECT(self->periph, self->func); PIN_PULLUP_DIS(self->periph); gpio_output_set(0, 0, 0, 1 << self->phys_port); } } void mp_hal_pin_output(mp_hal_pin_obj_t pin_id) { pin_mode[pin_id] = GPIO_MODE_OUTPUT; if (pin_id == 16) { WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); // output } else { const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id]; PIN_FUNC_SELECT(self->periph, self->func); PIN_PULLUP_DIS(self->periph); gpio_output_set(0, 0, 1 << self->phys_port, 0); } } void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin_id) { const pyb_pin_obj_t *pin = &pyb_pin_obj[pin_id]; if (pin->phys_port == 16) { // configure GPIO16 as input with output register holding 0 WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & ~1)); // out=0 return; } ETS_GPIO_INTR_DISABLE(); PIN_FUNC_SELECT(pin->periph, pin->func); GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin->phys_port)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin->phys_port))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); // open drain GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << pin->phys_port)); ETS_GPIO_INTR_ENABLE(); } int pin_get(uint pin) { if (pin == 16) { return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1; } return GPIO_INPUT_GET(pin); } void pin_set(uint pin, int value) { if (pin == 16) { int out_en = (pin_mode[pin] == GPIO_MODE_OUTPUT); WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | out_en); WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & ~1) | value); return; } uint32_t enable = 0; uint32_t disable = 0; switch (pin_mode[pin]) { case GPIO_MODE_INPUT: value = -1; disable = 1; break; case GPIO_MODE_OUTPUT: enable = 1; break; case GPIO_MODE_OPEN_DRAIN: if (value == -1) { return; } else if (value == 0) { enable = 1; } else { value = -1; disable = 1; } break; } enable <<= pin; disable <<= pin; if (value == -1) { gpio_output_set(0, 0, enable, disable); } else { gpio_output_set(value << pin, (1 - value) << pin, enable, disable); } } STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_pin_obj_t *self = self_in; // pin name mp_printf(print, "Pin(%u)", self->phys_port); } // pin.init(mode, pull=None, *, value) STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_pull, ARG_value }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get io mode uint mode = args[ARG_mode].u_int; // get pull mode uint pull = GPIO_PULL_NONE; if (args[ARG_pull].u_obj != mp_const_none) { pull = mp_obj_get_int(args[ARG_pull].u_obj); } // get initial value int value; if (args[ARG_value].u_obj == MP_OBJ_NULL) { value = -1; } else { value = mp_obj_is_true(args[ARG_value].u_obj); } // save the mode pin_mode[self->phys_port] = mode; // configure the GPIO as requested if (self->phys_port == 16) { // only pull-down seems to be supported by the hardware, and // we only expose pull-up behaviour in software if (pull != GPIO_PULL_NONE) { mp_raise_ValueError("Pin(16) doesn't support pull"); } } else { PIN_FUNC_SELECT(self->periph, self->func); #if 0 // Removed in SDK 1.1.0 if ((pull & GPIO_PULL_DOWN) == 0) { PIN_PULLDWN_DIS(self->periph); } #endif if ((pull & GPIO_PULL_UP) == 0) { PIN_PULLUP_DIS(self->periph); } #if 0 if ((pull & GPIO_PULL_DOWN) != 0) { PIN_PULLDWN_EN(self->periph); } #endif if ((pull & GPIO_PULL_UP) != 0) { PIN_PULLUP_EN(self->periph); } } pin_set(self->phys_port, value); return mp_const_none; } // constructor(id, ...) mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get the wanted pin object int wanted_pin = mp_obj_get_int(args[0]); pyb_pin_obj_t *pin = NULL; if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(pyb_pin_obj)) { pin = (pyb_pin_obj_t*)&pyb_pin_obj[wanted_pin]; } if (pin == NULL || pin->base.type == NULL) { mp_raise_ValueError("invalid pin"); } if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); } return (mp_obj_t)pin; } // fast method for getting/setting pin value STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); pyb_pin_obj_t *self = self_in; if (n_args == 0) { // get pin return MP_OBJ_NEW_SMALL_INT(pin_get(self->phys_port)); } else { // set pin pin_set(self->phys_port, mp_obj_is_true(args[0])); return mp_const_none; } } // pin.init(mode, pull) STATIC mp_obj_t pyb_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); } MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_init_obj, 1, pyb_pin_obj_init); // pin.value([value]) STATIC mp_obj_t pyb_pin_value(size_t n_args, const mp_obj_t *args) { return pyb_pin_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pin_value_obj, 1, 2, pyb_pin_value); STATIC mp_obj_t pyb_pin_off(mp_obj_t self_in) { pyb_pin_obj_t *self = self_in; pin_set(self->phys_port, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_off_obj, pyb_pin_off); STATIC mp_obj_t pyb_pin_on(mp_obj_t self_in) { pyb_pin_obj_t *self = self_in; pin_set(self->phys_port, 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_on_obj, pyb_pin_on); // pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False) STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_handler, ARG_trigger, ARG_hard }; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE} }, { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, }; pyb_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (self->phys_port >= 16) { mp_raise_msg(&mp_type_OSError, "pin does not have IRQ capabilities"); } if (n_args > 1 || kw_args->used != 0) { // configure irq mp_obj_t handler = args[ARG_handler].u_obj; uint32_t trigger = args[ARG_trigger].u_int; if (handler == mp_const_none) { handler = MP_OBJ_NULL; trigger = 0; } ETS_GPIO_INTR_DISABLE(); MP_STATE_PORT(pin_irq_handler)[self->phys_port] = handler; pin_irq_is_hard[self->phys_port] = args[ARG_hard].u_bool; SET_TRIGGER(self->phys_port, trigger); GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << self->phys_port); ETS_GPIO_INTR_ENABLE(); } // return the irq object return MP_OBJ_FROM_PTR(&pin_irq_obj[self->phys_port]); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_irq_obj, 1, pyb_pin_irq); STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode); STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; pyb_pin_obj_t *self = self_in; switch (request) { case MP_PIN_READ: { return pin_get(self->phys_port); } case MP_PIN_WRITE: { pin_set(self->phys_port, arg); return 0; } } return -1; } STATIC const mp_rom_map_elem_t pyb_pin_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_pin_init_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&pyb_pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&pyb_pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&pyb_pin_on_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_pin_irq_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUTPUT) }, { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OPEN_DRAIN) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) }, //{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) }, // IRQ triggers, can be or'd together { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_pin_locals_dict, pyb_pin_locals_dict_table); STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; const mp_obj_type_t pyb_pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, .print = pyb_pin_print, .make_new = mp_pin_make_new, .call = pyb_pin_call, .protocol = &pin_pin_p, .locals_dict = (mp_obj_dict_t*)&pyb_pin_locals_dict, }; /******************************************************************************/ // Pin IRQ object STATIC const mp_obj_type_t pin_irq_type; STATIC const pin_irq_obj_t pin_irq_obj[16] = { {{&pin_irq_type}, 0}, {{&pin_irq_type}, 1}, {{&pin_irq_type}, 2}, {{&pin_irq_type}, 3}, {{&pin_irq_type}, 4}, {{&pin_irq_type}, 5}, {{&pin_irq_type}, 6}, {{&pin_irq_type}, 7}, {{&pin_irq_type}, 8}, {{&pin_irq_type}, 9}, {{&pin_irq_type}, 10}, {{&pin_irq_type}, 11}, {{&pin_irq_type}, 12}, {{&pin_irq_type}, 13}, {{&pin_irq_type}, 14}, {{&pin_irq_type}, 15}, }; STATIC mp_obj_t pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { pin_irq_obj_t *self = self_in; mp_arg_check_num(n_args, n_kw, 0, 0, false); pin_intr_handler(1 << self->phys_port); return mp_const_none; } STATIC mp_obj_t pin_irq_trigger(size_t n_args, const mp_obj_t *args) { pin_irq_obj_t *self = args[0]; uint32_t orig_trig = GET_TRIGGER(self->phys_port); if (n_args == 2) { // set trigger SET_TRIGGER(self->phys_port, mp_obj_get_int(args[1])); } // return original trigger value return MP_OBJ_NEW_SMALL_INT(orig_trig); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_irq_trigger_obj, 1, 2, pin_irq_trigger); STATIC const mp_rom_map_elem_t pin_irq_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&pin_irq_trigger_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pin_irq_locals_dict, pin_irq_locals_dict_table); STATIC const mp_obj_type_t pin_irq_type = { { &mp_type_type }, .name = MP_QSTR_IRQ, .call = pin_irq_call, .locals_dict = (mp_obj_dict_t*)&pin_irq_locals_dict, }; micropython-1.12/ports/esp8266/machine_pwm.c000066400000000000000000000134601357706137100207450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "esppwm.h" #include "py/runtime.h" #include "modmachine.h" typedef struct _pyb_pwm_obj_t { mp_obj_base_t base; pyb_pin_obj_t *pin; uint8_t active; uint8_t channel; } pyb_pwm_obj_t; STATIC bool pwm_inited = false; /******************************************************************************/ // MicroPython bindings for PWM STATIC void pyb_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "PWM(%u", self->pin->phys_port); if (self->active) { mp_printf(print, ", freq=%u, duty=%u", pwm_get_freq(self->channel), pwm_get_duty(self->channel)); } mp_printf(print, ")"); } STATIC void pyb_pwm_init_helper(pyb_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_freq, ARG_duty }; static const mp_arg_t allowed_args[] = { { MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_duty, MP_ARG_INT, {.u_int = -1} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); int channel = pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func); if (channel == -1) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "PWM not supported on pin %d", self->pin->phys_port)); } self->channel = channel; self->active = 1; if (args[ARG_freq].u_int != -1) { pwm_set_freq(args[ARG_freq].u_int, self->channel); } if (args[ARG_duty].u_int != -1) { pwm_set_duty(args[ARG_duty].u_int, self->channel); } pwm_start(); } STATIC mp_obj_t pyb_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); pyb_pin_obj_t *pin = mp_obj_get_pin_obj(args[0]); // create PWM object from the given pin pyb_pwm_obj_t *self = m_new_obj(pyb_pwm_obj_t); self->base.type = &pyb_pwm_type; self->pin = pin; self->active = 0; self->channel = -1; // start the PWM subsystem if it's not already running if (!pwm_inited) { pwm_init(); pwm_inited = true; } // start the PWM running for this channel mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_pwm_init_helper(self, n_args - 1, args + 1, &kw_args); return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t pyb_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { pyb_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pwm_init_obj, 1, pyb_pwm_init); STATIC mp_obj_t pyb_pwm_deinit(mp_obj_t self_in) { pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); pwm_delete(self->channel); self->active = 0; pwm_start(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pwm_deinit_obj, pyb_pwm_deinit); STATIC mp_obj_t pyb_pwm_freq(size_t n_args, const mp_obj_t *args) { //pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get return MP_OBJ_NEW_SMALL_INT(pwm_get_freq(0)); } else { // set pwm_set_freq(mp_obj_get_int(args[1]), 0); pwm_start(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_freq_obj, 1, 2, pyb_pwm_freq); STATIC mp_obj_t pyb_pwm_duty(size_t n_args, const mp_obj_t *args) { pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (!self->active) { pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func); self->active = 1; } if (n_args == 1) { // get return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel)); } else { // set pwm_set_duty(mp_obj_get_int(args[1]), self->channel); pwm_start(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_duty_obj, 1, 2, pyb_pwm_duty); STATIC const mp_rom_map_elem_t pyb_pwm_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_pwm_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_pwm_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_pwm_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&pyb_pwm_duty_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_pwm_locals_dict, pyb_pwm_locals_dict_table); const mp_obj_type_t pyb_pwm_type = { { &mp_type_type }, .name = MP_QSTR_PWM, .print = pyb_pwm_print, .make_new = pyb_pwm_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_pwm_locals_dict, }; micropython-1.12/ports/esp8266/machine_rtc.c000066400000000000000000000223211357706137100207260ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Josef Gajdusek * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "lib/timeutils/timeutils.h" #include "user_interface.h" #include "modmachine.h" typedef struct _pyb_rtc_obj_t { mp_obj_base_t base; } pyb_rtc_obj_t; #define MEM_MAGIC 0x75507921 #define MEM_DELTA_ADDR 64 #define MEM_CAL_ADDR (MEM_DELTA_ADDR + 2) #define MEM_USER_MAGIC_ADDR (MEM_CAL_ADDR + 1) #define MEM_USER_LEN_ADDR (MEM_USER_MAGIC_ADDR + 1) #define MEM_USER_DATA_ADDR (MEM_USER_LEN_ADDR + 1) #define MEM_USER_MAXLEN (512 - (MEM_USER_DATA_ADDR - MEM_DELTA_ADDR) * 4) // singleton RTC object STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}}; // ALARM0 state uint32_t pyb_rtc_alarm0_wake; // see MACHINE_WAKE_xxx constants uint64_t pyb_rtc_alarm0_expiry; // in microseconds // RTC overflow checking STATIC uint32_t rtc_last_ticks; void mp_hal_rtc_init(void) { uint32_t magic; system_rtc_mem_read(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic)); if (magic != MEM_MAGIC) { magic = MEM_MAGIC; system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic)); uint32_t cal = system_rtc_clock_cali_proc(); int64_t delta = 0; system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal)); system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); uint32_t len = 0; system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len)); } // system_get_rtc_time() is always 0 after reset/deepsleep rtc_last_ticks = system_get_rtc_time(); // reset ALARM0 state pyb_rtc_alarm0_wake = 0; pyb_rtc_alarm0_expiry = 0; } STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); // return constant object return (mp_obj_t)&pyb_rtc_obj; } void pyb_rtc_set_us_since_2000(uint64_t nowus) { uint32_t cal = system_rtc_clock_cali_proc(); // Save RTC ticks for overflow detection. rtc_last_ticks = system_get_rtc_time(); int64_t delta = nowus - (((uint64_t)rtc_last_ticks * cal) >> 12); // As the calibration value jitters quite a bit, to make the // clock at least somewhat practically usable, we need to store it system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal)); system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); }; uint64_t pyb_rtc_get_us_since_2000() { uint32_t cal; int64_t delta; uint32_t rtc_ticks; system_rtc_mem_read(MEM_CAL_ADDR, &cal, sizeof(cal)); system_rtc_mem_read(MEM_DELTA_ADDR, &delta, sizeof(delta)); // ESP-SDK system_get_rtc_time() only returns uint32 and therefore // overflow about every 7:45h. Thus, we have to check for // overflow and handle it. rtc_ticks = system_get_rtc_time(); if (rtc_ticks < rtc_last_ticks) { // Adjust delta because of RTC overflow. delta += (uint64_t)cal << 20; system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); } rtc_last_ticks = rtc_ticks; return (((uint64_t)rtc_ticks * cal) >> 12) + delta; }; void rtc_prepare_deepsleep(uint64_t sleep_us) { // RTC time will reset at wake up. Let's be preared for this. int64_t delta = pyb_rtc_get_us_since_2000() + sleep_us; system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta)); } STATIC mp_obj_t pyb_rtc_datetime(size_t n_args, const mp_obj_t *args) { if (n_args == 1) { // Get time uint64_t msecs = pyb_rtc_get_us_since_2000() / 1000; timeutils_struct_time_t tm; timeutils_seconds_since_2000_to_struct_time(msecs / 1000, &tm); mp_obj_t tuple[8] = { mp_obj_new_int(tm.tm_year), mp_obj_new_int(tm.tm_mon), mp_obj_new_int(tm.tm_mday), mp_obj_new_int(tm.tm_wday), mp_obj_new_int(tm.tm_hour), mp_obj_new_int(tm.tm_min), mp_obj_new_int(tm.tm_sec), mp_obj_new_int(msecs % 1000) }; return mp_obj_new_tuple(8, tuple); } else { // Set time mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 8, &items); pyb_rtc_set_us_since_2000( ((uint64_t)timeutils_seconds_since_2000( mp_obj_get_int(items[0]), mp_obj_get_int(items[1]), mp_obj_get_int(items[2]), mp_obj_get_int(items[4]), mp_obj_get_int(items[5]), mp_obj_get_int(items[6])) * 1000 + mp_obj_get_int(items[7])) * 1000); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime); STATIC mp_obj_t pyb_rtc_memory(size_t n_args, const mp_obj_t *args) { uint8_t rtcram[MEM_USER_MAXLEN]; uint32_t len; if (n_args == 1) { // read RTC memory system_rtc_mem_read(MEM_USER_LEN_ADDR, &len, sizeof(len)); system_rtc_mem_read(MEM_USER_DATA_ADDR, rtcram, (len + 3) & ~3); return mp_obj_new_bytes(rtcram, len); } else { // write RTC memory mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); if (bufinfo.len > MEM_USER_MAXLEN) { mp_raise_ValueError("buffer too long"); } len = bufinfo.len; system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len)); int i = 0; for (; i < bufinfo.len; i++) { rtcram[i] = ((uint8_t *)bufinfo.buf)[i]; } system_rtc_mem_write(MEM_USER_DATA_ADDR, rtcram, (len + 3) & ~3); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_memory_obj, 1, 2, pyb_rtc_memory); STATIC mp_obj_t pyb_rtc_alarm(mp_obj_t self_in, mp_obj_t alarm_id, mp_obj_t time_in) { (void)self_in; // unused // check we want alarm0 if (mp_obj_get_int(alarm_id) != 0) { mp_raise_ValueError("invalid alarm"); } // set expiry time (in microseconds) pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + (uint64_t)mp_obj_get_int(time_in) * 1000; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_rtc_alarm_obj, pyb_rtc_alarm); STATIC mp_obj_t pyb_rtc_alarm_left(size_t n_args, const mp_obj_t *args) { // check we want alarm0 if (n_args > 1 && mp_obj_get_int(args[1]) != 0) { mp_raise_ValueError("invalid alarm"); } uint64_t now = pyb_rtc_get_us_since_2000(); if (pyb_rtc_alarm0_expiry <= now) { return MP_OBJ_NEW_SMALL_INT(0); } else { return mp_obj_new_int((pyb_rtc_alarm0_expiry - now) / 1000); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc_alarm_left); STATIC mp_obj_t pyb_rtc_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_trigger, ARG_wake }; static const mp_arg_t allowed_args[] = { { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // check we want alarm0 if (args[ARG_trigger].u_int != 0) { mp_raise_ValueError("invalid alarm"); } // set the wake value pyb_rtc_alarm0_wake = args[ARG_wake].u_int; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq); STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&pyb_rtc_datetime_obj) }, { MP_ROM_QSTR(MP_QSTR_memory), MP_ROM_PTR(&pyb_rtc_memory_obj) }, { MP_ROM_QSTR(MP_QSTR_alarm), MP_ROM_PTR(&pyb_rtc_alarm_obj) }, { MP_ROM_QSTR(MP_QSTR_alarm_left), MP_ROM_PTR(&pyb_rtc_alarm_left_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_rtc_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_ALARM0), MP_ROM_INT(0) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table); const mp_obj_type_t pyb_rtc_type = { { &mp_type_type }, .name = MP_QSTR_RTC, .make_new = pyb_rtc_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_rtc_locals_dict, }; micropython-1.12/ports/esp8266/machine_uart.c000066400000000000000000000255501357706137100211200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "ets_sys.h" #include "user_interface.h" #include "uart.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "modmachine.h" // UartDev is defined and initialized in rom code. extern UartDevice UartDev; typedef struct _pyb_uart_obj_t { mp_obj_base_t base; uint8_t uart_id; uint8_t bits; uint8_t parity; uint8_t stop; uint32_t baudrate; uint16_t timeout; // timeout waiting for first char (in ms) uint16_t timeout_char; // timeout waiting between chars (in ms) } pyb_uart_obj_t; STATIC const char *_parity_name[] = {"None", "1", "0"}; /******************************************************************************/ // MicroPython bindings for UART STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, rxbuf=%u, timeout=%u, timeout_char=%u)", self->uart_id, self->baudrate, self->bits, _parity_name[self->parity], self->stop, uart0_get_rxbuf_len() - 1, self->timeout, self->timeout_char); } STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rxbuf, ARG_timeout, ARG_timeout_char }; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_stop, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // set baudrate if (args[ARG_baudrate].u_int > 0) { self->baudrate = args[ARG_baudrate].u_int; UartDev.baut_rate = self->baudrate; // Sic! } // set data bits switch (args[ARG_bits].u_int) { case 0: break; case 5: UartDev.data_bits = UART_FIVE_BITS; self->bits = 5; break; case 6: UartDev.data_bits = UART_SIX_BITS; self->bits = 6; break; case 7: UartDev.data_bits = UART_SEVEN_BITS; self->bits = 7; break; case 8: UartDev.data_bits = UART_EIGHT_BITS; self->bits = 8; break; default: mp_raise_ValueError("invalid data bits"); break; } // set parity if (args[ARG_parity].u_obj != MP_OBJ_NULL) { if (args[ARG_parity].u_obj == mp_const_none) { UartDev.parity = UART_NONE_BITS; UartDev.exist_parity = UART_STICK_PARITY_DIS; self->parity = 0; } else { mp_int_t parity = mp_obj_get_int(args[ARG_parity].u_obj); UartDev.exist_parity = UART_STICK_PARITY_EN; if (parity & 1) { UartDev.parity = UART_ODD_BITS; self->parity = 1; } else { UartDev.parity = UART_EVEN_BITS; self->parity = 2; } } } // set tx/rx pins mp_hal_pin_obj_t tx = 1, rx = 3; if (args[ARG_tx].u_obj != MP_OBJ_NULL) { tx = mp_hal_get_pin_obj(args[ARG_tx].u_obj); } if (args[ARG_rx].u_obj != MP_OBJ_NULL) { rx = mp_hal_get_pin_obj(args[ARG_rx].u_obj); } if (tx == 1 && rx == 3) { system_uart_de_swap(); } else if (tx == 15 && rx == 13) { system_uart_swap(); } else { mp_raise_ValueError("invalid tx/rx"); } // set stop bits switch (args[ARG_stop].u_int) { case 0: break; case 1: UartDev.stop_bits = UART_ONE_STOP_BIT; self->stop = 1; break; case 2: UartDev.stop_bits = UART_TWO_STOP_BIT; self->stop = 2; break; default: mp_raise_ValueError("invalid stop bits"); break; } // set rx ring buffer if (args[ARG_rxbuf].u_int > 0) { uint16_t len = args[ARG_rxbuf].u_int + 1; // account for usable items in ringbuf byte *buf; if (len <= UART0_STATIC_RXBUF_LEN) { buf = uart_ringbuf_array; MP_STATE_PORT(uart0_rxbuf) = NULL; // clear any old pointer } else { buf = m_new(byte, len); MP_STATE_PORT(uart0_rxbuf) = buf; // retain root pointer } uart0_set_rxbuf(buf, len); } // set timeout self->timeout = args[ARG_timeout].u_int; // set timeout_char // make sure it is at least as long as a whole character (13 bits to be safe) self->timeout_char = args[ARG_timeout_char].u_int; uint32_t min_timeout_char = 13000 / self->baudrate + 1; if (self->timeout_char < min_timeout_char) { self->timeout_char = min_timeout_char; } // setup uart_setup(self->uart_id); } STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get uart id mp_int_t uart_id = mp_obj_get_int(args[0]); if (uart_id != 0 && uart_id != 1) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_id)); } // create instance pyb_uart_obj_t *self = m_new_obj(pyb_uart_obj_t); self->base.type = &pyb_uart_type; self->uart_id = uart_id; self->baudrate = 115200; self->bits = 8; self->parity = 0; self->stop = 1; self->timeout = 0; self->timeout_char = 0; // init the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args); return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t pyb_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(uart_rx_any(self->uart_id)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any); STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->uart_id == 1) { mp_raise_msg(&mp_type_OSError, "UART(1) can't read"); } // make sure we want at least 1 char if (size == 0) { return 0; } // wait for first char to become available if (!uart_rx_wait(self->timeout * 1000)) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } // read the data uint8_t *buf = buf_in; for (;;) { *buf++ = uart_rx_char(); if (--size == 0 || !uart_rx_wait(self->timeout_char * 1000)) { // return number of bytes read return buf - (uint8_t*)buf_in; } } } STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); const byte *buf = buf_in; /* TODO implement non-blocking // wait to be able to write the first character if (!uart_tx_wait(self, timeout)) { *errcode = EAGAIN; return MP_STREAM_ERROR; } */ // write the data for (size_t i = 0; i < size; ++i) { uart_tx_one_char(self->uart_id, *buf++); } // return number of bytes written return size; } STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { pyb_uart_obj_t *self = self_in; mp_uint_t ret; if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; if ((flags & MP_STREAM_POLL_RD) && uart_rx_any(self->uart_id)) { ret |= MP_STREAM_POLL_RD; } if ((flags & MP_STREAM_POLL_WR) && uart_tx_any_room(self->uart_id)) { ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; } return ret; } STATIC const mp_stream_p_t uart_stream_p = { .read = pyb_uart_read, .write = pyb_uart_write, .ioctl = pyb_uart_ioctl, .is_text = false, }; const mp_obj_type_t pyb_uart_type = { { &mp_type_type }, .name = MP_QSTR_UART, .print = pyb_uart_print, .make_new = pyb_uart_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &uart_stream_p, .locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict, }; micropython-1.12/ports/esp8266/machine_wdt.c000066400000000000000000000055001357706137100207340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ //#include #include #include "py/runtime.h" #include "user_interface.h" #include "etshal.h" #include "ets_alt_task.h" const mp_obj_type_t esp_wdt_type; typedef struct _machine_wdt_obj_t { mp_obj_base_t base; } machine_wdt_obj_t; STATIC machine_wdt_obj_t wdt_default = {{&esp_wdt_type}}; STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_int_t id = 0; if (n_args > 0) { id = mp_obj_get_int(args[0]); } switch (id) { case 0: ets_loop_dont_feed_sw_wdt = 1; system_soft_wdt_feed(); return &wdt_default; default: mp_raise_ValueError(NULL); } } STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) { (void)self_in; system_soft_wdt_feed(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed); STATIC mp_obj_t machine_wdt_deinit(mp_obj_t self_in) { (void)self_in; ets_wdt_disable(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_deinit_obj, machine_wdt_deinit); STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_wdt_deinit_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); const mp_obj_type_t esp_wdt_type = { { &mp_type_type }, .name = MP_QSTR_WDT, .make_new = machine_wdt_make_new, .locals_dict = (mp_obj_dict_t*)&machine_wdt_locals_dict, }; micropython-1.12/ports/esp8266/main.c000066400000000000000000000124321357706137100174000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2015-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/compile.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/mperrno.h" #include "py/mphal.h" #include "py/gc.h" // This needs to be defined before any ESP SDK headers are included #define USE_US_TIMER 1 #include "extmod/misc.h" #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" #include "gccollect.h" #include "user_interface.h" STATIC char heap[38 * 1024]; STATIC void mp_reset(void) { mp_stack_set_top((void*)0x40000000); mp_stack_set_limit(8192); mp_hal_init(); gc_init(heap, heap + sizeof(heap)); mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_)); mp_obj_list_init(mp_sys_argv, 0); #if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA extern void esp_native_code_init(void); esp_native_code_init(); #endif pin_init0(); readline_init0(); dupterm_task_init(); // Activate UART(0) on dupterm slot 1 for the REPL { mp_obj_t args[2]; args[0] = MP_OBJ_NEW_SMALL_INT(0); args[1] = MP_OBJ_NEW_SMALL_INT(115200); args[0] = pyb_uart_type.make_new(&pyb_uart_type, 2, 0, args); args[1] = MP_OBJ_NEW_SMALL_INT(1); extern mp_obj_t os_dupterm(size_t n_args, const mp_obj_t *args); os_dupterm(2, args); } #if MICROPY_MODULE_FROZEN pyexec_frozen_module("_boot.py"); pyexec_file_if_exists("boot.py"); if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { pyexec_file_if_exists("main.py"); } #endif } void soft_reset(void) { gc_sweep_all(); mp_hal_stdout_tx_str("MPY: soft reboot\r\n"); mp_hal_delay_us(10000); // allow UART to flush output mp_reset(); #if MICROPY_REPL_EVENT_DRIVEN pyexec_event_repl_init(); #endif } void init_done(void) { // Configure sleep, and put the radio to sleep if no interfaces are active wifi_fpm_set_sleep_type(MODEM_SLEEP_T); if (wifi_get_opmode() == NULL_MODE) { wifi_fpm_open(); wifi_fpm_do_sleep(0xfffffff); } #if MICROPY_REPL_EVENT_DRIVEN uart_task_init(); #endif mp_reset(); mp_hal_stdout_tx_str("\r\n"); #if MICROPY_REPL_EVENT_DRIVEN pyexec_event_repl_init(); #endif #if !MICROPY_REPL_EVENT_DRIVEN soft_reset: for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } soft_reset(); goto soft_reset; #endif } void user_init(void) { system_timer_reinit(); system_init_done_cb(init_done); } #if !MICROPY_VFS mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { (void)path; return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); #endif void MP_FASTCODE(nlr_jump_fail)(void *val) { printf("NLR jump failed\n"); for (;;) { } } //void __assert(const char *file, int line, const char *func, const char *expr) { void __assert(const char *file, int line, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); for (;;) { } } #if !MICROPY_DEBUG_PRINTERS // With MICROPY_DEBUG_PRINTERS disabled DEBUG_printf is not defined but it // is still needed by esp-open-lwip for debugging output, so define it here. #include int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args); int DEBUG_printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); int ret = mp_vprintf(MICROPY_DEBUG_PRINTER, fmt, ap); va_end(ap); return ret; } #endif micropython-1.12/ports/esp8266/makeimg.py000066400000000000000000000017351357706137100203000ustar00rootroot00000000000000import sys import struct import hashlib SEGS_MAX_SIZE = 0x9000 assert len(sys.argv) == 4 md5 = hashlib.md5() with open(sys.argv[3], 'wb') as fout: with open(sys.argv[1], 'rb') as f: data_flash = f.read() fout.write(data_flash) # First 4 bytes include flash size, etc. which may be changed # by esptool.py, etc. md5.update(data_flash[4:]) print('flash ', len(data_flash)) with open(sys.argv[2], 'rb') as f: data_rom = f.read() pad = b'\xff' * (SEGS_MAX_SIZE - len(data_flash)) assert len(pad) >= 4 fout.write(pad[:-4]) md5.update(pad[:-4]) len_data = struct.pack("I", SEGS_MAX_SIZE + len(data_rom)) fout.write(len_data) md5.update(len_data) print('padding ', len(pad)) fout.write(data_rom) md5.update(data_rom) print('irom0text', len(data_rom)) fout.write(md5.digest()) print('total ', SEGS_MAX_SIZE + len(data_rom)) print('md5 ', md5.hexdigest()) micropython-1.12/ports/esp8266/modesp.c000066400000000000000000000347331357706137100177530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/gc.h" #include "py/runtime.h" #include "py/persistentcode.h" #include "py/mperrno.h" #include "py/mphal.h" #include "drivers/dht/dht.h" #include "uart.h" #include "user_interface.h" #include "mem.h" #include "ets_alt_task.h" #include "espneopixel.h" #include "espapa102.h" #include "modmachine.h" #define MODESP_INCLUDE_CONSTANTS (1) void error_check(bool status, const char *msg) { if (!status) { mp_raise_msg(&mp_type_OSError, msg); } } STATIC mp_obj_t esp_osdebug(mp_obj_t val) { if (val == mp_const_none) { uart_os_config(-1); } else { uart_os_config(mp_obj_get_int(val)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_osdebug_obj, esp_osdebug); STATIC mp_obj_t esp_sleep_type(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return mp_obj_new_int(wifi_get_sleep_type()); } else { wifi_set_sleep_type(mp_obj_get_int(args[0])); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_sleep_type_obj, 0, 1, esp_sleep_type); STATIC mp_obj_t esp_deepsleep(size_t n_args, const mp_obj_t *args) { uint32_t sleep_us = n_args > 0 ? mp_obj_get_int(args[0]) : 0; // prepare for RTC reset at wake up rtc_prepare_deepsleep(sleep_us); system_deep_sleep_set_option(n_args > 1 ? mp_obj_get_int(args[1]) : 0); system_deep_sleep(sleep_us); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_deepsleep_obj, 0, 2, esp_deepsleep); STATIC mp_obj_t esp_flash_id() { return mp_obj_new_int(spi_flash_get_id()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_id_obj, esp_flash_id); STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t len_or_buf_in) { mp_int_t offset = mp_obj_get_int(offset_in); mp_int_t len; byte *buf; bool alloc_buf = mp_obj_is_int(len_or_buf_in); if (alloc_buf) { len = mp_obj_get_int(len_or_buf_in); buf = m_new(byte, len); } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(len_or_buf_in, &bufinfo, MP_BUFFER_WRITE); len = bufinfo.len; buf = bufinfo.buf; } // We know that allocation will be 4-byte aligned for sure SpiFlashOpResult res = spi_flash_read(offset, (uint32_t*)buf, len); if (res == SPI_FLASH_RESULT_OK) { if (alloc_buf) { return mp_obj_new_bytes(buf, len); } return mp_const_none; } if (alloc_buf) { m_del(byte, buf, len); } mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read); STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) { mp_int_t offset = mp_obj_get_int(offset_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); if (bufinfo.len & 0x3) { mp_raise_ValueError("len must be multiple of 4"); } ets_loop_iter(); // flash access takes time so run any pending tasks SpiFlashOpResult res = spi_flash_write(offset, bufinfo.buf, bufinfo.len); ets_loop_iter(); if (res == SPI_FLASH_RESULT_OK) { return mp_const_none; } mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write); STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) { mp_int_t sector = mp_obj_get_int(sector_in); ets_loop_iter(); // flash access takes time so run any pending tasks SpiFlashOpResult res = spi_flash_erase_sector(sector); ets_loop_iter(); if (res == SPI_FLASH_RESULT_OK) { return mp_const_none; } mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase); STATIC mp_obj_t esp_flash_size(void) { extern char flashchip; // For SDK 1.5.2, either address has shifted and not mirrored in // eagle.rom.addr.v6.ld, or extra initial member was added. SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4); #if 0 printf("deviceId: %x\n", flash->deviceId); printf("chip_size: %u\n", flash->chip_size); printf("block_size: %u\n", flash->block_size); printf("sector_size: %u\n", flash->sector_size); printf("page_size: %u\n", flash->page_size); printf("status_mask: %u\n", flash->status_mask); #endif return mp_obj_new_int_from_uint(flash->chip_size); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size); // If there's just 1 loadable segment at the start of flash, // we assume there's a yaota8266 bootloader. #define IS_OTA_FIRMWARE() ((*(uint32_t*)0x40200000 & 0xff00) == 0x100) extern byte _firmware_size[]; STATIC mp_obj_t esp_flash_user_start(void) { return MP_OBJ_NEW_SMALL_INT((uint32_t)_firmware_size); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start); STATIC mp_obj_t esp_check_fw(void) { MD5_CTX ctx; char *fw_start = (char*)0x40200000; if (IS_OTA_FIRMWARE()) { // Skip yaota8266 bootloader fw_start += 0x3c000; } uint32_t size = *(uint32_t*)(fw_start + 0x8ffc); printf("size: %d\n", size); if (size > 1024 * 1024) { printf("Invalid size\n"); return mp_const_false; } MD5Init(&ctx); MD5Update(&ctx, fw_start + 4, size - 4); unsigned char digest[16]; MD5Final(digest, &ctx); printf("md5: "); for (int i = 0; i < 16; i++) { printf("%02x", digest[i]); } printf("\n"); return mp_obj_new_bool(memcmp(digest, fw_start + size, sizeof(digest)) == 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_check_fw_obj, esp_check_fw); STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); esp_neopixel_write(mp_obj_get_pin_obj(pin)->phys_port, (uint8_t*)bufinfo.buf, bufinfo.len, mp_obj_is_true(is800k)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_); #if MICROPY_ESP8266_APA102 STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); esp_apa102_write(mp_obj_get_pin_obj(clockPin)->phys_port, mp_obj_get_pin_obj(dataPin)->phys_port, (uint8_t*)bufinfo.buf, bufinfo.len); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_apa102_write_obj, esp_apa102_write_); #endif STATIC mp_obj_t esp_freemem() { return MP_OBJ_NEW_SMALL_INT(system_get_free_heap_size()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_freemem_obj, esp_freemem); STATIC mp_obj_t esp_meminfo() { system_print_meminfo(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_meminfo_obj, esp_meminfo); STATIC mp_obj_t esp_malloc(mp_obj_t size_in) { return MP_OBJ_NEW_SMALL_INT((mp_uint_t)os_malloc(mp_obj_get_int(size_in))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_malloc_obj, esp_malloc); STATIC mp_obj_t esp_free(mp_obj_t addr_in) { os_free((void*)mp_obj_get_int(addr_in)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_free_obj, esp_free); STATIC mp_obj_t esp_esf_free_bufs(mp_obj_t idx_in) { return MP_OBJ_NEW_SMALL_INT(ets_esf_free_bufs(mp_obj_get_int(idx_in))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_esf_free_bufs_obj, esp_esf_free_bufs); #if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA // We provide here a way of committing executable data to a region from // which it can be executed by the CPU. There are 2 such writable regions: // - iram1, which may have some space left at the end of it // - memory-mapped flash rom // // By default the iram1 region (the space at the end of it) is used. The // user can select iram1 or a section of flash by calling the // esp.set_native_code_location() function; see below. If flash is selected // then it is erased as needed. #define IRAM1_END (0x40108000) #define FLASH_START (0x40200000) #define FLASH_END (0x40300000) #define FLASH_SEC_SIZE (4096) #define ESP_NATIVE_CODE_IRAM1 (0) #define ESP_NATIVE_CODE_FLASH (1) extern uint32_t _lit4_end; STATIC uint32_t esp_native_code_location; STATIC uint32_t esp_native_code_start; STATIC uint32_t esp_native_code_end; STATIC uint32_t esp_native_code_cur; STATIC uint32_t esp_native_code_erased; void esp_native_code_init(void) { esp_native_code_location = ESP_NATIVE_CODE_IRAM1; esp_native_code_start = (uint32_t)&_lit4_end; esp_native_code_end = IRAM1_END; esp_native_code_cur = esp_native_code_start; esp_native_code_erased = 0; } void *esp_native_code_commit(void *buf, size_t len, void *reloc) { //printf("COMMIT(buf=%p, len=%u, start=%08x, cur=%08x, end=%08x, erased=%08x)\n", buf, len, esp_native_code_start, esp_native_code_cur, esp_native_code_end, esp_native_code_erased); len = (len + 3) & ~3; if (esp_native_code_cur + len > esp_native_code_end) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "memory allocation failed, allocating %u bytes for native code", (uint)len)); } void *dest; if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) { dest = (void*)esp_native_code_cur; } else { dest = (void*)(FLASH_START + esp_native_code_cur); } if (reloc) { mp_native_relocate(reloc, buf, (uintptr_t)dest); } if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) { memcpy(dest, buf, len); } else { SpiFlashOpResult res; while (esp_native_code_erased < esp_native_code_cur + len) { ets_loop_iter(); // flash access takes time so run any pending tasks res = spi_flash_erase_sector(esp_native_code_erased / FLASH_SEC_SIZE); if (res != SPI_FLASH_RESULT_OK) { break; } esp_native_code_erased += FLASH_SEC_SIZE; } ets_loop_iter(); if (res == SPI_FLASH_RESULT_OK) { res = spi_flash_write(esp_native_code_cur, buf, len); ets_loop_iter(); } if (res != SPI_FLASH_RESULT_OK) { mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO); } } esp_native_code_cur += len; return dest; } STATIC mp_obj_t esp_set_native_code_location(mp_obj_t start_in, mp_obj_t len_in) { if (start_in == mp_const_none && len_in == mp_const_none) { // use end of iram1 region esp_native_code_init(); } else { // use flash; input params are byte offsets from start of flash esp_native_code_location = ESP_NATIVE_CODE_FLASH; esp_native_code_start = mp_obj_get_int(start_in); esp_native_code_end = esp_native_code_start + mp_obj_get_int(len_in); esp_native_code_cur = esp_native_code_start; esp_native_code_erased = esp_native_code_start; // memory-mapped flash is limited in extents to 1MByte if (esp_native_code_end > FLASH_END - FLASH_START) { mp_raise_ValueError("flash location must be below 1MByte"); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_set_native_code_location_obj, esp_set_native_code_location); #endif STATIC const mp_rom_map_elem_t esp_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp) }, { MP_ROM_QSTR(MP_QSTR_osdebug), MP_ROM_PTR(&esp_osdebug_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_type), MP_ROM_PTR(&esp_sleep_type_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&esp_deepsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_id), MP_ROM_PTR(&esp_flash_id_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_read), MP_ROM_PTR(&esp_flash_read_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_write), MP_ROM_PTR(&esp_flash_write_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) }, { MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) }, #if MICROPY_ESP8266_NEOPIXEL { MP_ROM_QSTR(MP_QSTR_neopixel_write), MP_ROM_PTR(&esp_neopixel_write_obj) }, #endif #if MICROPY_ESP8266_APA102 { MP_ROM_QSTR(MP_QSTR_apa102_write), MP_ROM_PTR(&esp_apa102_write_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_freemem), MP_ROM_PTR(&esp_freemem_obj) }, { MP_ROM_QSTR(MP_QSTR_meminfo), MP_ROM_PTR(&esp_meminfo_obj) }, { MP_ROM_QSTR(MP_QSTR_check_fw), MP_ROM_PTR(&esp_check_fw_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_info_obj) }, // TODO delete/rename/move elsewhere { MP_ROM_QSTR(MP_QSTR_malloc), MP_ROM_PTR(&esp_malloc_obj) }, { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&esp_free_obj) }, { MP_ROM_QSTR(MP_QSTR_esf_free_bufs), MP_ROM_PTR(&esp_esf_free_bufs_obj) }, #if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA { MP_ROM_QSTR(MP_QSTR_set_native_code_location), MP_ROM_PTR(&esp_set_native_code_location_obj) }, #endif #if MODESP_INCLUDE_CONSTANTS { MP_ROM_QSTR(MP_QSTR_SLEEP_NONE), MP_ROM_INT(NONE_SLEEP_T) }, { MP_ROM_QSTR(MP_QSTR_SLEEP_LIGHT), MP_ROM_INT(LIGHT_SLEEP_T) }, { MP_ROM_QSTR(MP_QSTR_SLEEP_MODEM), MP_ROM_INT(MODEM_SLEEP_T) }, #endif }; STATIC MP_DEFINE_CONST_DICT(esp_module_globals, esp_module_globals_table); const mp_obj_module_t esp_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&esp_module_globals, }; micropython-1.12/ports/esp8266/modmachine.c000066400000000000000000000370461357706137100205700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "py/runtime.h" // This needs to be set before we include the RTOS headers #define USE_US_TIMER 1 #include "extmod/machine_mem.h" #include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "modmachine.h" #include "xtirq.h" #include "os_type.h" #include "osapi.h" #include "etshal.h" #include "ets_alt_task.h" #include "user_interface.h" #if MICROPY_PY_MACHINE //#define MACHINE_WAKE_IDLE (0x01) //#define MACHINE_WAKE_SLEEP (0x02) #define MACHINE_WAKE_DEEPSLEEP (0x04) extern const mp_obj_type_t esp_wdt_type; STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // get return mp_obj_new_int(system_get_cpu_freq() * 1000000); } else { // set mp_int_t freq = mp_obj_get_int(args[0]) / 1000000; if (freq != 80 && freq != 160) { mp_raise_ValueError("frequency can only be either 80Mhz or 160MHz"); } system_update_cpu_freq(freq); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq); STATIC mp_obj_t machine_reset(void) { system_restart(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); STATIC mp_obj_t machine_reset_cause(void) { return MP_OBJ_NEW_SMALL_INT(system_get_rst_info()->reason); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); STATIC mp_obj_t machine_unique_id(void) { uint32_t id = system_get_chip_id(); return mp_obj_new_bytes((byte*)&id, sizeof(id)); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id); STATIC mp_obj_t machine_idle(void) { uint32_t t = mp_hal_ticks_cpu(); asm("waiti 0"); t = mp_hal_ticks_cpu() - t; ets_event_poll(); // handle any events after possibly a long wait (eg feed WDT) return MP_OBJ_NEW_SMALL_INT(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle); STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { uint32_t max_us = 0xffffffff; if (n_args == 1) { mp_int_t max_ms = mp_obj_get_int(args[0]); if (max_ms < 0) { max_ms = 0; } max_us = max_ms * 1000; } uint32_t wifi_mode = wifi_get_opmode(); uint32_t start = system_get_time(); while (system_get_time() - start <= max_us) { ets_event_poll(); if (wifi_mode == NULL_MODE) { // Can only idle if the wifi is off asm("waiti 0"); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep); STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) { // default to sleep forever uint32_t sleep_us = 0; // see if RTC.ALARM0 should wake the device if (pyb_rtc_alarm0_wake & MACHINE_WAKE_DEEPSLEEP) { uint64_t t = pyb_rtc_get_us_since_2000(); if (pyb_rtc_alarm0_expiry <= t) { sleep_us = 1; // alarm already expired so wake immediately } else { uint64_t delta = pyb_rtc_alarm0_expiry - t; if (delta <= 0xffffffff) { // sleep for the desired time sleep_us = delta; } else { // overflow, just set to maximum sleep time sleep_us = 0xffffffff; } } } // if an argument is given then that's the maximum time to sleep for if (n_args == 1) { mp_int_t max_ms = mp_obj_get_int(args[0]); if (max_ms <= 0) { max_ms = 1; } uint32_t max_us = max_ms * 1000; if (sleep_us == 0 || max_us < sleep_us) { sleep_us = max_us; } } // prepare for RTC reset at wake up rtc_prepare_deepsleep(sleep_us); // put the device in a deep-sleep state system_deep_sleep_set_option(0); // default power down mode; TODO check this system_deep_sleep(sleep_us); for (;;) { // we must not return ets_loop_iter(); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep); // These values are from the datasheet #define ESP_TIMER_US_MIN (100) #define ESP_TIMER_US_MAX (0xfffffff) #define ESP_TIMER_MS_MAX (0x689d0) typedef struct _esp_timer_obj_t { mp_obj_base_t base; os_timer_t timer; uint32_t remain_ms; // if non-zero, remaining time to handle large periods uint32_t period_ms; // if non-zero, periodic timer with a large period mp_obj_t callback; } esp_timer_obj_t; STATIC void esp_timer_arm_ms(esp_timer_obj_t *self, uint32_t ms, bool repeat) { if (ms <= ESP_TIMER_MS_MAX) { self->remain_ms = 0; self->period_ms = 0; } else { self->remain_ms = ms - ESP_TIMER_MS_MAX; if (repeat) { repeat = false; self->period_ms = ms; } else { self->period_ms = 0; } ms = ESP_TIMER_MS_MAX; } os_timer_arm(&self->timer, ms, repeat); } STATIC void esp_timer_arm_us(esp_timer_obj_t *self, uint32_t us, bool repeat) { if (us < ESP_TIMER_US_MIN) { us = ESP_TIMER_US_MIN; } if (us <= ESP_TIMER_US_MAX) { self->remain_ms = 0; self->period_ms = 0; os_timer_arm_us(&self->timer, us, repeat); } else { esp_timer_arm_ms(self, us / 1000, repeat); } } const mp_obj_type_t esp_timer_type; STATIC void esp_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { esp_timer_obj_t *self = self_in; mp_printf(print, "Timer(%p)", &self->timer); } STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); esp_timer_obj_t *tim = m_new_obj(esp_timer_obj_t); tim->base.type = &esp_timer_type; return tim; } STATIC void esp_timer_cb(void *arg) { esp_timer_obj_t *self = arg; if (self->remain_ms != 0) { // Handle periods larger than the maximum system period uint32_t next_period_ms = self->remain_ms; if (next_period_ms > ESP_TIMER_MS_MAX) { next_period_ms = ESP_TIMER_MS_MAX; } self->remain_ms -= next_period_ms; os_timer_arm(&self->timer, next_period_ms, false); } else { mp_sched_schedule(self->callback, self); if (self->period_ms != 0) { // A periodic timer with a larger period: reschedule it esp_timer_arm_ms(self, self->period_ms, true); } } } STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, #if MICROPY_PY_BUILTINS_FLOAT { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, #else { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, #endif }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); self->callback = args[ARG_callback].u_obj; // Be sure to disarm timer before making any changes os_timer_disarm(&self->timer); os_timer_setfn(&self->timer, esp_timer_cb, self); #if MICROPY_PY_BUILTINS_FLOAT if (args[ARG_freq].u_obj != mp_const_none) { mp_float_t freq = mp_obj_get_float(args[ARG_freq].u_obj); if (freq < 0.001) { esp_timer_arm_ms(self, (mp_int_t)(1000 / freq), args[ARG_mode].u_int); } else { esp_timer_arm_us(self, (mp_int_t)(1000000 / freq), args[ARG_mode].u_int); } } #else if (args[ARG_freq].u_int != 0xffffffff) { esp_timer_arm_us(self, 1000000 / args[ARG_freq].u_int, args[ARG_mode].u_int); } #endif else { mp_int_t period = args[ARG_period].u_int; mp_int_t hz = args[ARG_tick_hz].u_int; if (hz == 1000) { esp_timer_arm_ms(self, period, args[ARG_mode].u_int); } else if (hz == 1000000) { esp_timer_arm_us(self, period, args[ARG_mode].u_int); } else { // Use a long long to ensure that we don't either overflow or loose accuracy uint64_t period_us = (((uint64_t)period) * 1000000) / hz; if (period_us < 0x80000000ull) { esp_timer_arm_us(self, (mp_int_t)period_us, args[ARG_mode].u_int); } else { esp_timer_arm_ms(self, (mp_int_t)(period_us / 1000), args[ARG_mode].u_int); } } } return mp_const_none; } STATIC mp_obj_t esp_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return esp_timer_init_helper(args[0], n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_timer_init_obj, 1, esp_timer_init); STATIC mp_obj_t esp_timer_deinit(mp_obj_t self_in) { esp_timer_obj_t *self = self_in; os_timer_disarm(&self->timer); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_timer_deinit_obj, esp_timer_deinit); STATIC const mp_rom_map_elem_t esp_timer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp_timer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&esp_timer_init_obj) }, // { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&esp_timer_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(false) }, { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(true) }, }; STATIC MP_DEFINE_CONST_DICT(esp_timer_locals_dict, esp_timer_locals_dict_table); const mp_obj_type_t esp_timer_type = { { &mp_type_type }, .name = MP_QSTR_Timer, .print = esp_timer_print, .make_new = esp_timer_make_new, .locals_dict = (mp_obj_dict_t*)&esp_timer_locals_dict, }; // this bit is unused in the Xtensa PS register #define ETS_LOOP_ITER_BIT (12) STATIC mp_obj_t machine_disable_irq(void) { uint32_t state = disable_irq(); state = (state & ~(1 << ETS_LOOP_ITER_BIT)) | (ets_loop_iter_disable << ETS_LOOP_ITER_BIT); ets_loop_iter_disable = 1; return mp_obj_new_int(state); } MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq); STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) { uint32_t state = mp_obj_get_int(state_in); ets_loop_iter_disable = (state >> ETS_LOOP_ITER_BIT) & 1; enable_irq(state & ~(1 << ETS_LOOP_ITER_BIT)); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq); // Custom version of this function that feeds system WDT if necessary mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { int nchanges = 2; uint32_t start = system_get_time(); // in microseconds for (;;) { uint32_t dt = system_get_time() - start; // Check if pin changed to wanted value if (mp_hal_pin_read(pin) == pulse_level) { if (--nchanges == 0) { return dt; } pulse_level = 1 - pulse_level; start = system_get_time(); continue; } // Check for timeout if (dt >= timeout_us) { return (mp_uint_t)-nchanges; } // Only feed WDT every now and then, to make sure edge timing is accurate if ((dt & 0xffff) == 0xffff && !ets_loop_dont_feed_sw_wdt) { system_soft_wdt_feed(); } } } STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&esp_wdt_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, #if MICROPY_PY_MACHINE_I2C { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, #endif #if MICROPY_PY_MACHINE_SPI { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hspi_type) }, #endif // wake abilities { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) }, // reset causes { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) }, { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) }, { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(REASON_DEEP_SLEEP_AWAKE) }, { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(REASON_WDT_RST) }, { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(REASON_SOFT_RESTART) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t mp_module_machine = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; #endif // MICROPY_PY_MACHINE micropython-1.12/ports/esp8266/modmachine.h000066400000000000000000000021741357706137100205670ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_ESP8266_MODMACHINE_H #define MICROPY_INCLUDED_ESP8266_MODMACHINE_H #include "py/obj.h" extern const mp_obj_type_t pyb_pin_type; extern const mp_obj_type_t pyb_pwm_type; extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t pyb_rtc_type; extern const mp_obj_type_t pyb_uart_type; extern const mp_obj_type_t pyb_i2c_type; extern const mp_obj_type_t machine_hspi_type; MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj); typedef struct _pyb_pin_obj_t { mp_obj_base_t base; uint16_t phys_port; uint16_t func; uint32_t periph; } pyb_pin_obj_t; const pyb_pin_obj_t pyb_pin_obj[16 + 1]; void pin_init0(void); void pin_intr_handler_iram(void *arg); void pin_intr_handler(uint32_t); uint mp_obj_get_pin(mp_obj_t pin_in); pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in); int pin_get(uint pin); void pin_set(uint pin, int value); extern uint32_t pyb_rtc_alarm0_wake; extern uint64_t pyb_rtc_alarm0_expiry; void pyb_rtc_set_us_since_2000(uint64_t nowus); uint64_t pyb_rtc_get_us_since_2000(); void rtc_prepare_deepsleep(uint64_t sleep_us); #endif // MICROPY_INCLUDED_ESP8266_MODMACHINE_H micropython-1.12/ports/esp8266/modnetwork.c000066400000000000000000000470421357706137100206520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/objlist.h" #include "py/runtime.h" #include "py/mphal.h" #include "lib/netutils/netutils.h" #include "queue.h" #include "user_interface.h" #include "espconn.h" #include "spi_flash.h" #include "ets_alt_task.h" #include "lwip/dns.h" #define MODNETWORK_INCLUDE_CONSTANTS (1) typedef struct _wlan_if_obj_t { mp_obj_base_t base; int if_id; } wlan_if_obj_t; void error_check(bool status, const char *msg); const mp_obj_type_t wlan_if_type; STATIC const wlan_if_obj_t wlan_objs[] = { {{&wlan_if_type}, STATION_IF}, {{&wlan_if_type}, SOFTAP_IF}, }; STATIC void require_if(mp_obj_t wlan_if, int if_no) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if); if (self->if_id != if_no) { error_check(false, if_no == STATION_IF ? "STA required" : "AP required"); } } STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) { int idx = 0; if (n_args > 0) { idx = mp_obj_get_int(args[0]); if (idx < 0 || idx >= sizeof(wlan_objs)) { mp_raise_ValueError(NULL); } } return MP_OBJ_FROM_PTR(&wlan_objs[idx]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan); STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t mode = wifi_get_opmode(); if (n_args > 1) { int mask = self->if_id == STATION_IF ? STATION_MODE : SOFTAP_MODE; if (mp_obj_get_int(args[1]) != 0) { mode |= mask; } else { mode &= ~mask; } if (mode != NULL_MODE) { wifi_fpm_do_wakeup(); wifi_fpm_close(); } error_check(wifi_set_opmode(mode), "Cannot update i/f status"); if (mode == NULL_MODE) { // Wait for the interfaces to go down before forcing power management while (wifi_get_opmode() != NULL_MODE) { ets_loop_iter(); } wifi_fpm_open(); wifi_fpm_do_sleep(0xfffffff); } return mp_const_none; } // Get active status if (self->if_id == STATION_IF) { return mp_obj_new_bool(mode & STATION_MODE); } else { return mp_obj_new_bool(mode & SOFTAP_MODE); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active); STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ssid, ARG_password, ARG_bssid }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); require_if(pos_args[0], STATION_IF); struct station_config config = {{0}}; size_t len; const char *p; bool set_config = false; // set parameters based on given args if (args[ARG_ssid].u_obj != mp_const_none) { p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len); len = MIN(len, sizeof(config.ssid)); memcpy(config.ssid, p, len); set_config = true; } if (args[ARG_password].u_obj != mp_const_none) { p = mp_obj_str_get_data(args[ARG_password].u_obj, &len); len = MIN(len, sizeof(config.password)); memcpy(config.password, p, len); set_config = true; } if (args[ARG_bssid].u_obj != mp_const_none) { p = mp_obj_str_get_data(args[ARG_bssid].u_obj, &len); if (len != sizeof(config.bssid)) { mp_raise_ValueError(NULL); } config.bssid_set = 1; memcpy(config.bssid, p, sizeof(config.bssid)); set_config = true; } if (set_config) { error_check(wifi_station_set_config(&config), "Cannot set STA config"); } error_check(wifi_station_connect(), "Cannot connect to AP"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_connect_obj, 1, esp_connect); STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) { require_if(self_in, STATION_IF); error_check(wifi_station_disconnect(), "Cannot disconnect from AP"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect); STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // Get link status if (self->if_id == STATION_IF) { return MP_OBJ_NEW_SMALL_INT(wifi_station_get_connect_status()); } return MP_OBJ_NEW_SMALL_INT(-1); } else { // Get specific status parameter switch (mp_obj_str_get_qstr(args[1])) { case MP_QSTR_rssi: if (self->if_id == STATION_IF) { return MP_OBJ_NEW_SMALL_INT(wifi_station_get_rssi()); } } mp_raise_ValueError("unknown status param"); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status); STATIC mp_obj_t *esp_scan_list = NULL; STATIC void esp_scan_cb(void *result, STATUS status) { if (esp_scan_list == NULL) { // called unexpectedly return; } if (result && status == 0) { // we need to catch any memory errors nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { for (struct bss_info *bs = result; bs; bs = STAILQ_NEXT(bs, next)) { mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL); #if 1 // struct bss_info::ssid_len is not documented in SDK API Guide, // but is present in SDK headers since 1.4.0 t->items[0] = mp_obj_new_bytes(bs->ssid, bs->ssid_len); #else t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char*)bs->ssid)); #endif t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid)); t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel); t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi); t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode); t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden); mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t)); } nlr_pop(); } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); // indicate error *esp_scan_list = MP_OBJ_NULL; } } else { // indicate error *esp_scan_list = MP_OBJ_NULL; } esp_scan_list = NULL; } STATIC mp_obj_t esp_scan(mp_obj_t self_in) { require_if(self_in, STATION_IF); if ((wifi_get_opmode() & STATION_MODE) == 0) { mp_raise_msg(&mp_type_OSError, "STA must be active"); } mp_obj_t list = mp_obj_new_list(0, NULL); esp_scan_list = &list; wifi_station_scan(NULL, (scan_done_cb_t)esp_scan_cb); while (esp_scan_list != NULL) { // our esp_scan_cb is called via ets_loop_iter so it's safe to set the // esp_scan_list variable to NULL without disabling interrupts if (MP_STATE_VM(mp_pending_exception) != NULL) { esp_scan_list = NULL; mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } ets_loop_iter(); } if (list == MP_OBJ_NULL) { mp_raise_msg(&mp_type_OSError, "scan failed"); } return list; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_scan_obj, esp_scan); /// \method isconnected() /// Return True if connected to an AP and an IP address has been assigned, /// false otherwise. STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->if_id == STATION_IF) { if (wifi_station_get_connect_status() == STATION_GOT_IP) { return mp_const_true; } } else { if (wifi_softap_get_station_num() > 0) { return mp_const_true; } } return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected); STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); struct ip_info info; ip_addr_t dns_addr; wifi_get_ip_info(self->if_id, &info); if (n_args == 1) { // get dns_addr = dns_getserver(0); mp_obj_t tuple[4] = { netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&info.netmask, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&info.gw, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&dns_addr, NETUTILS_BIG), }; return mp_obj_new_tuple(4, tuple); } else { // set mp_obj_t *items; bool restart_dhcp_server = false; mp_obj_get_array_fixed_n(args[1], 4, &items); netutils_parse_ipv4_addr(items[0], (void*)&info.ip, NETUTILS_BIG); if (mp_obj_is_integer(items[1])) { // allow numeric netmask, i.e.: // 24 -> 255.255.255.0 // 16 -> 255.255.0.0 // etc... uint32_t* m = (uint32_t*)&info.netmask; *m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1]))); } else { netutils_parse_ipv4_addr(items[1], (void*)&info.netmask, NETUTILS_BIG); } netutils_parse_ipv4_addr(items[2], (void*)&info.gw, NETUTILS_BIG); netutils_parse_ipv4_addr(items[3], (void*)&dns_addr, NETUTILS_BIG); // To set a static IP we have to disable DHCP first if (self->if_id == STATION_IF) { wifi_station_dhcpc_stop(); } else { restart_dhcp_server = wifi_softap_dhcps_status(); wifi_softap_dhcps_stop(); } if (!wifi_set_ip_info(self->if_id, &info)) { mp_raise_msg(&mp_type_OSError, "wifi_set_ip_info() failed"); } dns_setserver(0, &dns_addr); if (restart_dhcp_server) { wifi_softap_dhcps_start(); } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig); STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { if (n_args != 1 && kwargs->used != 0) { mp_raise_TypeError("either pos or kw args are allowed"); } wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); union { struct station_config sta; struct softap_config ap; } cfg; if (self->if_id == STATION_IF) { error_check(wifi_station_get_config(&cfg.sta), "can't get STA config"); } else { error_check(wifi_softap_get_config(&cfg.ap), "can't get AP config"); } int req_if = -1; if (kwargs->used != 0) { for (mp_uint_t i = 0; i < kwargs->alloc; i++) { if (mp_map_slot_is_filled(kwargs, i)) { #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) switch ((uintptr_t)kwargs->table[i].key) { case QS(MP_QSTR_mac): { mp_buffer_info_t bufinfo; mp_get_buffer_raise(kwargs->table[i].value, &bufinfo, MP_BUFFER_READ); if (bufinfo.len != 6) { mp_raise_ValueError("invalid buffer length"); } wifi_set_macaddr(self->if_id, bufinfo.buf); break; } case QS(MP_QSTR_essid): { req_if = SOFTAP_IF; size_t len; const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len); len = MIN(len, sizeof(cfg.ap.ssid)); memcpy(cfg.ap.ssid, s, len); cfg.ap.ssid_len = len; break; } case QS(MP_QSTR_hidden): { req_if = SOFTAP_IF; cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value); break; } case QS(MP_QSTR_authmode): { req_if = SOFTAP_IF; cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value); break; } case QS(MP_QSTR_password): { req_if = SOFTAP_IF; size_t len; const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len); len = MIN(len, sizeof(cfg.ap.password) - 1); memcpy(cfg.ap.password, s, len); cfg.ap.password[len] = 0; break; } case QS(MP_QSTR_channel): { req_if = SOFTAP_IF; cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value); break; } case QS(MP_QSTR_dhcp_hostname): { req_if = STATION_IF; if (self->if_id == STATION_IF) { const char *s = mp_obj_str_get_str(kwargs->table[i].value); wifi_station_set_hostname((char*)s); } break; } default: goto unknown; } #undef QS } } // We post-check interface requirements to save on code size if (req_if >= 0) { require_if(args[0], req_if); } if (self->if_id == STATION_IF) { error_check(wifi_station_set_config(&cfg.sta), "can't set STA config"); } else { error_check(wifi_softap_set_config(&cfg.ap), "can't set AP config"); } return mp_const_none; } // Get config if (n_args != 2) { mp_raise_TypeError("can query only one param"); } mp_obj_t val; qstr key = mp_obj_str_get_qstr(args[1]); switch (key) { case MP_QSTR_mac: { uint8_t mac[6]; wifi_get_macaddr(self->if_id, mac); return mp_obj_new_bytes(mac, sizeof(mac)); } case MP_QSTR_essid: if (self->if_id == STATION_IF) { val = mp_obj_new_str((char*)cfg.sta.ssid, strlen((char*)cfg.sta.ssid)); } else { val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len); } break; case MP_QSTR_hidden: req_if = SOFTAP_IF; val = mp_obj_new_bool(cfg.ap.ssid_hidden); break; case MP_QSTR_authmode: req_if = SOFTAP_IF; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode); break; case MP_QSTR_channel: req_if = SOFTAP_IF; val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel); break; case MP_QSTR_dhcp_hostname: { req_if = STATION_IF; char* s = wifi_station_get_hostname(); if (s == NULL) { val = MP_OBJ_NEW_QSTR(MP_QSTR_); } else { val = mp_obj_new_str(s, strlen(s)); } break; } default: goto unknown; } // We post-check interface requirements to save on code size if (req_if >= 0) { require_if(args[0], req_if); } return val; unknown: mp_raise_ValueError("unknown config param"); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config); STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&esp_active_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&esp_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&esp_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&esp_status_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&esp_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&esp_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&esp_config_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) }, }; STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table); const mp_obj_type_t wlan_if_type = { { &mp_type_type }, .name = MP_QSTR_WLAN, .locals_dict = (mp_obj_dict_t*)&wlan_if_locals_dict, }; STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return mp_obj_new_int(wifi_get_phy_mode()); } else { wifi_set_phy_mode(mp_obj_get_int(args[0])); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode); STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) }, { MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_phy_mode_obj) }, #if MODNETWORK_INCLUDE_CONSTANTS { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(STATION_IF)}, { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(SOFTAP_IF)}, { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STATION_IDLE)}, { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STATION_CONNECTING)}, { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(STATION_WRONG_PASSWORD)}, { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(STATION_NO_AP_FOUND)}, { MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(STATION_CONNECT_FAIL)}, { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STATION_GOT_IP)}, { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(PHY_MODE_11B) }, { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(PHY_MODE_11G) }, { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(PHY_MODE_11N) }, { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(AUTH_OPEN) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(AUTH_WEP) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(AUTH_WPA_PSK) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(AUTH_WPA2_PSK) }, { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(AUTH_WPA_WPA2_PSK) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); const mp_obj_module_t network_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_network_globals, }; micropython-1.12/ports/esp8266/modpyb.c000066400000000000000000000062111357706137100177440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/gc.h" #include "gccollect.h" #include "modmachine.h" // The pyb module no longer exists since all functionality now appears // elsewhere, in more standard places (eg time, machine modules). The // only remaining function is pyb.info() which has been moved to the // esp module, pending deletion/renaming/moving elsewhere. STATIC mp_obj_t pyb_info(size_t n_args, const mp_obj_t *args) { // print info about memory { printf("_text_start=%p\n", &_text_start); printf("_text_end=%p\n", &_text_end); printf("_irom0_text_start=%p\n", &_irom0_text_start); printf("_irom0_text_end=%p\n", &_irom0_text_end); printf("_data_start=%p\n", &_data_start); printf("_data_end=%p\n", &_data_end); printf("_rodata_start=%p\n", &_rodata_start); printf("_rodata_end=%p\n", &_rodata_end); printf("_bss_start=%p\n", &_bss_start); printf("_bss_end=%p\n", &_bss_end); printf("_heap_start=%p\n", &_heap_start); printf("_heap_end=%p\n", &_heap_end); } // qstr info { mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); } // GC info { gc_info_t info; gc_info(&info); printf("GC:\n"); printf(" " UINT_FMT " total\n", info.total); printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); } if (n_args == 1) { // arg given means dump gc allocation table gc_dump_alloc_table(); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info); micropython-1.12/ports/esp8266/modules/000077500000000000000000000000001357706137100177565ustar00rootroot00000000000000micropython-1.12/ports/esp8266/modules/_boot.py000066400000000000000000000003331357706137100214310ustar00rootroot00000000000000import gc gc.threshold((gc.mem_free() + gc.mem_alloc()) // 4) import uos from flashbdev import bdev try: if bdev: uos.mount(bdev, '/') except OSError: import inisetup inisetup.setup() gc.collect() micropython-1.12/ports/esp8266/modules/apa102.py000066400000000000000000000007261357706137100213210ustar00rootroot00000000000000# APA102 driver for MicroPython on ESP8266 # MIT license; Copyright (c) 2016 Robert Foss, Daniel Busch from esp import apa102_write from neopixel import NeoPixel class APA102(NeoPixel): ORDER = (0, 1, 2, 3) def __init__(self, clock_pin, data_pin, n, bpp=4): super().__init__(data_pin, n, bpp) self.clock_pin = clock_pin self.clock_pin.init(clock_pin.OUT) def write(self): apa102_write(self.clock_pin, self.pin, self.buf) micropython-1.12/ports/esp8266/modules/flashbdev.py000066400000000000000000000025071357706137100222720ustar00rootroot00000000000000import esp class FlashBdev: SEC_SIZE = 4096 RESERVED_SECS = 1 START_SEC = esp.flash_user_start() // SEC_SIZE + RESERVED_SECS NUM_BLK = 0x6b - RESERVED_SECS def __init__(self, blocks=NUM_BLK): self.blocks = blocks def readblocks(self, n, buf, off=0): #print("readblocks(%s, %x(%d), %d)" % (n, id(buf), len(buf), off)) esp.flash_read((n + self.START_SEC) * self.SEC_SIZE + off, buf) def writeblocks(self, n, buf, off=None): #print("writeblocks(%s, %x(%d), %d)" % (n, id(buf), len(buf), off)) #assert len(buf) <= self.SEC_SIZE, len(buf) if off is None: esp.flash_erase(n + self.START_SEC) off = 0 esp.flash_write((n + self.START_SEC) * self.SEC_SIZE + off, buf) def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return self.blocks if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE if op == 6: # MP_BLOCKDEV_IOCTL_BLOCK_ERASE esp.flash_erase(arg + self.START_SEC) return 0 size = esp.flash_size() if size < 1024*1024: bdev = None else: # 20K at the flash end is reserved for SDK params storage bdev = FlashBdev((size - 20480) // FlashBdev.SEC_SIZE - FlashBdev.START_SEC) micropython-1.12/ports/esp8266/modules/inisetup.py000066400000000000000000000026311357706137100221720ustar00rootroot00000000000000import uos import network from flashbdev import bdev def wifi(): import ubinascii ap_if = network.WLAN(network.AP_IF) essid = b"MicroPython-%s" % ubinascii.hexlify(ap_if.config("mac")[-3:]) ap_if.config(essid=essid, authmode=network.AUTH_WPA_WPA2_PSK, password=b"micropythoN") def check_bootsec(): buf = bytearray(bdev.SEC_SIZE) bdev.readblocks(0, buf) empty = True for b in buf: if b != 0xff: empty = False break if empty: return True fs_corrupted() def fs_corrupted(): import time while 1: print("""\ The FAT filesystem starting at sector %d with size %d sectors appears to be corrupted. If you had important data there, you may want to make a flash snapshot to try to recover it. Otherwise, perform factory reprogramming of MicroPython firmware (completely erase flash, followed by firmware programming). """ % (bdev.START_SEC, bdev.blocks)) time.sleep(3) def setup(): check_bootsec() print("Performing initial setup") wifi() uos.VfsFat.mkfs(bdev) vfs = uos.VfsFat(bdev) uos.mount(vfs, '/') with open("boot.py", "w") as f: f.write("""\ # This file is executed on every boot (including wake-boot from deepsleep) #import esp #esp.osdebug(None) import uos, machine #uos.dupterm(None, 1) # disable REPL on UART(0) import gc #import webrepl #webrepl.start() gc.collect() """) return vfs micropython-1.12/ports/esp8266/modules/neopixel.py000066400000000000000000000015041357706137100221530ustar00rootroot00000000000000# NeoPixel driver for MicroPython on ESP8266 # MIT license; Copyright (c) 2016 Damien P. George from esp import neopixel_write class NeoPixel: ORDER = (1, 0, 2, 3) def __init__(self, pin, n, bpp=3): self.pin = pin self.n = n self.bpp = bpp self.buf = bytearray(n * bpp) self.pin.init(pin.OUT) def __setitem__(self, index, val): offset = index * self.bpp for i in range(self.bpp): self.buf[offset + self.ORDER[i]] = val[i] def __getitem__(self, index): offset = index * self.bpp return tuple(self.buf[offset + self.ORDER[i]] for i in range(self.bpp)) def fill(self, color): for i in range(self.n): self[i] = color def write(self): neopixel_write(self.pin, self.buf, True) micropython-1.12/ports/esp8266/modules/ntptime.py000066400000000000000000000016051357706137100220120ustar00rootroot00000000000000try: import usocket as socket except: import socket try: import ustruct as struct except: import struct # (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 NTP_DELTA = 3155673600 host = "pool.ntp.org" def time(): NTP_QUERY = bytearray(48) NTP_QUERY[0] = 0x1b addr = socket.getaddrinfo(host, 123)[0][-1] s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.settimeout(1) res = s.sendto(NTP_QUERY, addr) msg = s.recv(48) finally: s.close() val = struct.unpack("!I", msg[40:44])[0] return val - NTP_DELTA # There's currently no timezone support in MicroPython, so # utime.localtime() will return UTC time (as if it was .gmtime()) def settime(): t = time() import machine import utime tm = utime.localtime(t) machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0)) micropython-1.12/ports/esp8266/modules/port_diag.py000066400000000000000000000021061357706137100222770ustar00rootroot00000000000000import esp import uctypes import network import lwip def main(): ROM = uctypes.bytearray_at(0x40200000, 16) fid = esp.flash_id() print("FlashROM:") print("Flash ID: %x (Vendor: %x Device: %x)" % (fid, fid & 0xff, fid & 0xff00 | fid >> 16)) print("Flash bootloader data:") SZ_MAP = {0: "512KB", 1: "256KB", 2: "1MB", 3: "2MB", 4: "4MB"} FREQ_MAP = {0: "40MHZ", 1: "26MHZ", 2: "20MHz", 0xf: "80MHz"} print("Byte @2: %02x" % ROM[2]) print("Byte @3: %02x (Flash size: %s Flash freq: %s)" % (ROM[3], SZ_MAP.get(ROM[3] >> 4, "?"), FREQ_MAP.get(ROM[3] & 0xf))) print("Firmware checksum:") print(esp.check_fw()) print("\nNetworking:") print("STA ifconfig:", network.WLAN(network.STA_IF).ifconfig()) print("AP ifconfig:", network.WLAN(network.AP_IF).ifconfig()) print("Free WiFi driver buffers of type:") for i, comm in enumerate(("1,2 TX", "4 Mngmt TX(len: 0x41-0x100)", "5 Mngmt TX (len: 0-0x40)", "7", "8 RX")): print("%d: %d (%s)" % (i, esp.esf_free_bufs(i), comm)) print("lwIP PCBs:") lwip.print_pcbs() main() micropython-1.12/ports/esp8266/moduos.c000066400000000000000000000127271357706137100177710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Josef Gajdusek * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/objtuple.h" #include "py/objstr.h" #include "extmod/misc.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "extmod/vfs_lfs.h" #include "genhdr/mpversion.h" #include "esp_mphal.h" #include "user_interface.h" STATIC const qstr os_uname_info_fields[] = { MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine }; STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); STATIC mp_obj_tuple_t os_uname_info_obj = { .base = {&mp_type_attrtuple}, .len = 5, .items = { (mp_obj_t)&os_uname_info_sysname_obj, (mp_obj_t)&os_uname_info_nodename_obj, NULL, (mp_obj_t)&os_uname_info_version_obj, (mp_obj_t)&os_uname_info_machine_obj, (void *)os_uname_info_fields, } }; STATIC mp_obj_t os_uname(void) { // We must populate the "release" field each time in case it was GC'd since the last call. const char *ver = system_get_sdk_version(); os_uname_info_obj.items[2] = mp_obj_new_str(ver, strlen(ver)); return (mp_obj_t)&os_uname_info_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); STATIC mp_obj_t os_urandom(mp_obj_t num) { mp_int_t n = mp_obj_get_int(num); vstr_t vstr; vstr_init_len(&vstr, n); for (int i = 0; i < n; i++) { vstr.buf[i] = *WDEV_HWRNG; } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); // We wrap the mp_uos_dupterm function to detect if a UART is attached or not mp_obj_t os_dupterm(size_t n_args, const mp_obj_t *args) { mp_obj_t prev_obj = mp_uos_dupterm_obj.fun.var(n_args, args); if (mp_obj_get_type(args[0]) == &pyb_uart_type) { ++uart_attached_to_dupterm; } if (mp_obj_get_type(prev_obj) == &pyb_uart_type) { --uart_attached_to_dupterm; } return prev_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_dupterm_obj, 1, 2, os_dupterm); STATIC mp_obj_t os_dupterm_notify(mp_obj_t obj_in) { (void)obj_in; mp_hal_signal_dupterm_input(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify); STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, #if MICROPY_PY_OS_DUPTERM { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&os_dupterm_obj) }, { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, #endif #if MICROPY_VFS { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif #if MICROPY_VFS_LFS1 { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, #endif #if MICROPY_VFS_LFS2 { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, #endif #endif }; STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); const mp_obj_module_t uos_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&os_module_globals, }; micropython-1.12/ports/esp8266/modutime.c000066400000000000000000000123121357706137100202740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Josef Gajdusek * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/gc.h" #include "py/runtime.h" #include "py/mphal.h" #include "py/smallint.h" #include "lib/timeutils/timeutils.h" #include "modmachine.h" #include "user_interface.h" #include "extmod/utime_mphal.h" /// \module time - time related functions /// /// The `time` module provides functions for getting the current time and date, /// and for sleeping. /// \function localtime([secs]) /// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which /// contains: (year, month, mday, hour, minute, second, weekday, yearday) /// If secs is not provided or None, then the current time from the RTC is used. /// year includes the century (for example 2014) /// month is 1-12 /// mday is 1-31 /// hour is 0-23 /// minute is 0-59 /// second is 0-59 /// weekday is 0-6 for Mon-Sun. /// yearday is 1-366 STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { timeutils_struct_time_t tm; mp_int_t seconds; if (n_args == 0 || args[0] == mp_const_none) { seconds = pyb_rtc_get_us_since_2000() / 1000 / 1000; } else { seconds = mp_obj_get_int(args[0]); } timeutils_seconds_since_2000_to_struct_time(seconds, &tm); mp_obj_t tuple[8] = { tuple[0] = mp_obj_new_int(tm.tm_year), tuple[1] = mp_obj_new_int(tm.tm_mon), tuple[2] = mp_obj_new_int(tm.tm_mday), tuple[3] = mp_obj_new_int(tm.tm_hour), tuple[4] = mp_obj_new_int(tm.tm_min), tuple[5] = mp_obj_new_int(tm.tm_sec), tuple[6] = mp_obj_new_int(tm.tm_wday), tuple[7] = mp_obj_new_int(tm.tm_yday), }; return mp_obj_new_tuple(8, tuple); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime); /// \function mktime() /// This is inverse function of localtime. It's argument is a full 8-tuple /// which expresses a time as per localtime. It returns an integer which is /// the number of seconds since Jan 1, 2000. STATIC mp_obj_t time_mktime(mp_obj_t tuple) { size_t len; mp_obj_t *elem; mp_obj_get_array(tuple, &len, &elem); // localtime generates a tuple of len 8. CPython uses 9, so we accept both. if (len < 8 || len > 9) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "mktime needs a tuple of length 8 or 9 (%d given)", len)); } return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); } MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); /// \function time() /// Returns the number of seconds, as an integer, since 1/1/2000. STATIC mp_obj_t time_time(void) { // get date and time return mp_obj_new_int(pyb_rtc_get_us_since_2000() / 1000 / 1000); } MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) }, { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t utime_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; micropython-1.12/ports/esp8266/mpconfigport.h000066400000000000000000000170051357706137100211710ustar00rootroot00000000000000// Options to control how MicroPython is built for this port, // overriding defaults in py/mpconfig.h. // Board-specific definitions #include "mpconfigboard.h" #include #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C) #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t #define MICROPY_ALLOC_PATH_MAX (128) #define MICROPY_ALLOC_LEXER_INDENT_INIT (8) #define MICROPY_ALLOC_PARSE_RULE_INIT (48) #define MICROPY_ALLOC_PARSE_RULE_INC (8) #define MICROPY_ALLOC_PARSE_RESULT_INC (8) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTER (&mp_debug_print) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_ROUND_INT (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_COLLECTIONS_DEQUE (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (1) #define MICROPY_PY_IO_IOBASE (1) #define MICROPY_PY_STRUCT (1) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UTIMEQ (1) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_LWIP (1) #define MICROPY_PY_LWIP_SOCK_RAW (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hspi_make_new #define MICROPY_PY_UWEBSOCKET (1) #define MICROPY_PY_WEBREPL (1) #define MICROPY_PY_WEBREPL_DELAY (20) #define MICROPY_PY_WEBREPL_STATIC_FILEBUF (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_OS_DUPTERM (2) #define MICROPY_CPYTHON_COMPAT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_WARNINGS (1) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str32 #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_ESP8266_APA102 (1) #define MICROPY_ESP8266_NEOPIXEL (1) #define MICROPY_EVENT_POLL_HOOK {ets_event_poll();} #define MICROPY_VM_HOOK_COUNT (10) #define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT; #define MICROPY_VM_HOOK_POLL if (--vm_hook_divisor == 0) { \ vm_hook_divisor = MICROPY_VM_HOOK_COUNT; \ extern void ets_loop_iter(void); \ ets_loop_iter(); \ } #define MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_POLL #define MICROPY_VM_HOOK_RETURN MICROPY_VM_HOOK_POLL // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p))) #define MP_SSIZE_MAX (0x7fffffff) #define UINT_FMT "%u" #define INT_FMT "%d" typedef int32_t mp_int_t; // must be pointer size typedef uint32_t mp_uint_t; // must be pointer size typedef long mp_off_t; typedef uint32_t sys_prot_t; // for modlwip // ssize_t, off_t as required by POSIX-signatured functions in stream.h #include #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) void *esp_native_code_commit(void*, size_t, void*); #define MP_PLAT_COMMIT_EXEC(buf, len, reloc) esp_native_code_commit(buf, len, reloc) // printer for debugging output, goes to UART only extern const struct _mp_print_t mp_debug_print; #if MICROPY_VFS_FAT #define mp_type_fileio mp_type_vfs_fat_fileio #define mp_type_textio mp_type_vfs_fat_textio #elif MICROPY_VFS_LFS1 #define mp_type_fileio mp_type_vfs_lfs1_fileio #define mp_type_textio mp_type_vfs_lfs1_textio #elif MICROPY_VFS_LFS2 #define mp_type_fileio mp_type_vfs_lfs2_fileio #define mp_type_textio mp_type_vfs_lfs2_textio #endif // use vfs's functions for import stat and builtin open #define mp_import_stat mp_vfs_import_stat #define mp_builtin_open mp_vfs_open #define mp_builtin_open_obj mp_vfs_open_obj // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t esp_module; extern const struct _mp_obj_module_t network_module; extern const struct _mp_obj_module_t utime_module; extern const struct _mp_obj_module_t uos_module; extern const struct _mp_obj_module_t mp_module_lwip; extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_onewire; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_esp), MP_ROM_PTR(&esp_module) }, \ { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_lwip) }, \ { MP_ROM_QSTR(MP_QSTR_network), MP_ROM_PTR(&network_module) }, \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&utime_module) }, \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&uos_module) }, \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \ { MP_ROM_QSTR(MP_QSTR__onewire), MP_ROM_PTR(&mp_module_onewire) }, \ #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ mp_obj_t pin_irq_handler[16]; \ byte *uart0_rxbuf; \ // We need to provide a declaration/definition of alloca() #include // board specifics #define MICROPY_MPHALPORT_H "esp_mphal.h" #define MICROPY_PY_SYS_PLATFORM "esp8266" #define MP_FASTCODE(n) __attribute__((section(".iram0.text." #n))) n #define _assert(expr) ((expr) ? (void)0 : __assert_func(__FILE__, __LINE__, __func__, #expr)) micropython-1.12/ports/esp8266/posix_helpers.c000066400000000000000000000042051357706137100213370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mphal.h" #include "py/gc.h" // Functions for external libs like axTLS, BerkeleyDB, etc. void *malloc(size_t size) { void *p = gc_alloc(size, false); if (p == NULL) { // POSIX requires ENOMEM to be set in case of error errno = ENOMEM; } return p; } void free(void *ptr) { gc_free(ptr); } void *calloc(size_t nmemb, size_t size) { return malloc(nmemb * size); } void *realloc(void *ptr, size_t size) { void *p = gc_realloc(ptr, size, true); if (p == NULL) { // POSIX requires ENOMEM to be set in case of error errno = ENOMEM; } return p; } #undef htonl #undef ntohl uint32_t ntohl(uint32_t netlong) { return MP_BE32TOH(netlong); } uint32_t htonl(uint32_t netlong) { return MP_HTOBE32(netlong); } time_t time(time_t *t) { return mp_hal_ticks_ms() / 1000; } time_t mktime(void *tm) { return 0; } micropython-1.12/ports/esp8266/qstrdefsport.h000066400000000000000000000024721357706137100212240ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // qstrs specific to this port, only needed if they aren't auto-generated // Entries for sys.path Q(/) Q(/lib) micropython-1.12/ports/esp8266/strtoll.c000066400000000000000000000011651357706137100201600ustar00rootroot00000000000000#include // assumes endptr != NULL // doesn't check for sign // doesn't check for base-prefix long long int strtoll(const char *nptr, char **endptr, int base) { long long val = 0; for (; *nptr; nptr++) { int v = *nptr; if ('0' <= v && v <= '9') { v -= '0'; } else if ('A' <= v && v <= 'Z') { v -= 'A' - 10; } else if ('a' <= v && v <= 'z') { v -= 'a' - 10; } else { break; } if (v >= base) { break; } val = val * base + v; } *endptr = (char*)nptr; return val; } micropython-1.12/ports/esp8266/uart.c000066400000000000000000000253121357706137100174300ustar00rootroot00000000000000/****************************************************************************** * Copyright 2013-2014 Espressif Systems (Wuxi) * * FileName: uart.c * * Description: Two UART mode configration and interrupt handler. * Check your hardware connection while use this mode. * * Modification history: * 2014/3/12, v1.0 create this file. *******************************************************************************/ #include "ets_sys.h" #include "osapi.h" #include "uart.h" #include "osapi.h" #include "uart_register.h" #include "etshal.h" #include "c_types.h" #include "user_interface.h" #include "esp_mphal.h" // seems that this is missing in the Espressif SDK #define FUNC_U0RXD 0 #define UART_REPL UART0 // UartDev is defined and initialized in rom code. extern UartDevice UartDev; // the uart to which OS messages go; -1 to disable static int uart_os = UART_OS; #if MICROPY_REPL_EVENT_DRIVEN static os_event_t uart_evt_queue[16]; #endif // A small, static ring buffer for incoming chars // This will only be populated if the UART is not attached to dupterm uint8 uart_ringbuf_array[UART0_STATIC_RXBUF_LEN]; static ringbuf_t uart_ringbuf = {uart_ringbuf_array, sizeof(uart_ringbuf_array), 0, 0}; static void uart0_rx_intr_handler(void *para); void soft_reset(void); void mp_keyboard_interrupt(void); /****************************************************************************** * FunctionName : uart_config * Description : Internal used function * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled * UART1 just used for debug output * Parameters : uart_no, use UART0 or UART1 defined ahead * Returns : NONE *******************************************************************************/ static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no) { if (uart_no == UART1) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); } else { ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, NULL); PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD); } uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); WRITE_PERI_REG(UART_CONF0(uart_no), UartDev.exist_parity | UartDev.parity | (UartDev.stop_bits << UART_STOP_BIT_NUM_S) | (UartDev.data_bits << UART_BIT_NUM_S)); // clear rx and tx fifo,not ready SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); if (uart_no == UART0) { // set rx fifo trigger WRITE_PERI_REG(UART_CONF1(uart_no), ((0x10 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | ((0x10 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) | UART_RX_FLOW_EN | (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S | UART_RX_TOUT_EN); SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA); } else { WRITE_PERI_REG(UART_CONF1(uart_no), ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); } // clear all interrupt WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff); // enable rx_interrupt SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA); } /****************************************************************************** * FunctionName : uart1_tx_one_char * Description : Internal used function * Use uart1 interface to transfer one char * Parameters : uint8 TxChar - character to tx * Returns : OK *******************************************************************************/ void uart_tx_one_char(uint8 uart, uint8 TxChar) { while (true) { uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { break; } } WRITE_PERI_REG(UART_FIFO(uart), TxChar); } void uart_flush(uint8 uart) { while (true) { uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) == 0) { break; } } } /****************************************************************************** * FunctionName : uart1_write_char * Description : Internal used function * Do some special deal while tx char is '\r' or '\n' * Parameters : char c - character to tx * Returns : NONE *******************************************************************************/ static void ICACHE_FLASH_ATTR uart_os_write_char(char c) { if (uart_os == -1) { return; } if (c == '\n') { uart_tx_one_char(uart_os, '\r'); uart_tx_one_char(uart_os, '\n'); } else if (c == '\r') { } else { uart_tx_one_char(uart_os, c); } } void ICACHE_FLASH_ATTR uart_os_config(int uart) { uart_os = uart; } /****************************************************************************** * FunctionName : uart0_rx_intr_handler * Description : Internal used function * UART0 interrupt handler, add self handle code inside * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg * Returns : NONE *******************************************************************************/ static void uart0_rx_intr_handler(void *para) { /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents * uart1 and uart0 respectively */ uint8 uart_no = UART_REPL; if (UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)) { // frame error WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR); } if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) { // fifo full goto read_chars; } else if (UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) { read_chars: ETS_UART_INTR_DISABLE(); while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) { uint8 RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff; // For efficiency, when connected to dupterm we put incoming chars // directly on stdin_ringbuf, rather than going via uart_ringbuf if (uart_attached_to_dupterm) { if (RcvChar == mp_interrupt_char) { mp_keyboard_interrupt(); } else { ringbuf_put(&stdin_ringbuf, RcvChar); } } else { ringbuf_put(&uart_ringbuf, RcvChar); } } // Clear pending FIFO interrupts WRITE_PERI_REG(UART_INT_CLR(UART_REPL), UART_RXFIFO_TOUT_INT_CLR | UART_RXFIFO_FULL_INT_ST); ETS_UART_INTR_ENABLE(); if (uart_attached_to_dupterm) { mp_hal_signal_input(); } } } // Waits at most timeout microseconds for at least 1 char to become ready for reading. // Returns true if something available, false if not. bool uart_rx_wait(uint32_t timeout_us) { uint32_t start = system_get_time(); for (;;) { if (uart_ringbuf.iget != uart_ringbuf.iput) { return true; // have at least 1 char ready for reading } if (system_get_time() - start >= timeout_us) { return false; // timeout } ets_event_poll(); } } int uart_rx_any(uint8 uart) { if (uart_ringbuf.iget != uart_ringbuf.iput) { return true; // have at least 1 char ready for reading } return false; } int uart_tx_any_room(uint8 uart) { uint32_t fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S); if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) >= 126) { return false; } return true; } // Returns char from the input buffer, else -1 if buffer is empty. int uart_rx_char(void) { return ringbuf_get(&uart_ringbuf); } int uart_rx_one_char(uint8 uart_no) { if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) { return READ_PERI_REG(UART_FIFO(uart_no)) & 0xff; } return -1; } /****************************************************************************** * FunctionName : uart_init * Description : user interface for init uart * Parameters : UartBautRate uart0_br - uart0 bautrate * UartBautRate uart1_br - uart1 bautrate * Returns : NONE *******************************************************************************/ void ICACHE_FLASH_ATTR uart_init(UartBautRate uart0_br, UartBautRate uart1_br) { // rom use 74880 baut_rate, here reinitialize UartDev.baut_rate = uart0_br; uart_config(UART0); UartDev.baut_rate = uart1_br; uart_config(UART1); ETS_UART_INTR_ENABLE(); // install handler for "os" messages os_install_putc1((void *)uart_os_write_char); } void ICACHE_FLASH_ATTR uart_reattach() { uart_init(UART_BIT_RATE_74880, UART_BIT_RATE_74880); } void ICACHE_FLASH_ATTR uart_setup(uint8 uart) { ETS_UART_INTR_DISABLE(); uart_config(uart); ETS_UART_INTR_ENABLE(); } int ICACHE_FLASH_ATTR uart0_get_rxbuf_len(void) { return uart_ringbuf.size; } void ICACHE_FLASH_ATTR uart0_set_rxbuf(uint8 *buf, int len) { ETS_UART_INTR_DISABLE(); uart_ringbuf.buf = buf; uart_ringbuf.size = len; uart_ringbuf.iget = 0; uart_ringbuf.iput = 0; ETS_UART_INTR_ENABLE(); } // Task-based UART interface #include "py/obj.h" #include "lib/utils/pyexec.h" #if MICROPY_REPL_EVENT_DRIVEN void uart_task_handler(os_event_t *evt) { if (pyexec_repl_active) { // TODO: Just returning here isn't exactly right. // What really should be done is something like // enquing delayed event to itself, for another // chance to feed data to REPL. Otherwise, there // can be situation when buffer has bunch of data, // and sits unprocessed, because we consumed all // processing signals like this. return; } int c, ret = 0; while ((c = ringbuf_get(&stdin_ringbuf)) >= 0) { if (c == mp_interrupt_char) { mp_keyboard_interrupt(); } ret = pyexec_event_repl_process_char(c); if (ret & PYEXEC_FORCED_EXIT) { break; } } if (ret & PYEXEC_FORCED_EXIT) { soft_reset(); } } void uart_task_init() { system_os_task(uart_task_handler, UART_TASK_ID, uart_evt_queue, sizeof(uart_evt_queue) / sizeof(*uart_evt_queue)); } #endif micropython-1.12/ports/esp8266/uart.h000066400000000000000000000052351357706137100174370ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_ESP8266_UART_H #define MICROPY_INCLUDED_ESP8266_UART_H #include #define UART0 (0) #define UART1 (1) #define UART0_STATIC_RXBUF_LEN (16) typedef enum { UART_FIVE_BITS = 0x0, UART_SIX_BITS = 0x1, UART_SEVEN_BITS = 0x2, UART_EIGHT_BITS = 0x3 } UartBitsNum4Char; typedef enum { UART_ONE_STOP_BIT = 0x1, UART_ONE_HALF_STOP_BIT = 0x2, UART_TWO_STOP_BIT = 0x3 } UartStopBitsNum; typedef enum { UART_NONE_BITS = 0, UART_ODD_BITS = BIT0, UART_EVEN_BITS = 0 } UartParityMode; typedef enum { UART_STICK_PARITY_DIS = 0, UART_STICK_PARITY_EN = BIT1 } UartExistParity; typedef enum { UART_BIT_RATE_9600 = 9600, UART_BIT_RATE_19200 = 19200, UART_BIT_RATE_38400 = 38400, UART_BIT_RATE_57600 = 57600, UART_BIT_RATE_74880 = 74880, UART_BIT_RATE_115200 = 115200, UART_BIT_RATE_230400 = 230400, UART_BIT_RATE_256000 = 256000, UART_BIT_RATE_460800 = 460800, UART_BIT_RATE_921600 = 921600 } UartBautRate; typedef enum { UART_NONE_CTRL, UART_HARDWARE_CTRL, UART_XON_XOFF_CTRL } UartFlowCtrl; typedef enum { UART_EMPTY, UART_UNDER_WRITE, UART_WRITE_OVER } RcvMsgBuffState; typedef struct { uint32 RcvBuffSize; uint8 *pRcvMsgBuff; uint8 *pWritePos; uint8 *pReadPos; uint8 TrigLvl; //JLU: may need to pad RcvMsgBuffState BuffState; } RcvMsgBuff; typedef struct { uint32 TrxBuffSize; uint8 *pTrxBuff; } TrxMsgBuff; typedef enum { UART_BAUD_RATE_DET, UART_WAIT_SYNC_FRM, UART_SRCH_MSG_HEAD, UART_RCV_MSG_BODY, UART_RCV_ESC_CHAR, } RcvMsgState; typedef struct { UartBautRate baut_rate; UartBitsNum4Char data_bits; UartExistParity exist_parity; UartParityMode parity; // chip size in byte UartStopBitsNum stop_bits; UartFlowCtrl flow_ctrl; RcvMsgBuff rcv_buff; TrxMsgBuff trx_buff; RcvMsgState rcv_state; int received; int buff_uart_no; //indicate which uart use tx/rx buffer } UartDevice; extern uint8 uart_ringbuf_array[UART0_STATIC_RXBUF_LEN]; void uart_init(UartBautRate uart0_br, UartBautRate uart1_br); int uart0_rx(void); bool uart_rx_wait(uint32_t timeout_us); int uart_rx_char(void); void uart_tx_one_char(uint8 uart, uint8 TxChar); void uart_flush(uint8 uart); void uart_os_config(int uart); void uart_setup(uint8 uart); int uart0_get_rxbuf_len(void); void uart0_set_rxbuf(uint8 *buf, int len); // check status of rx/tx int uart_rx_any(uint8 uart); int uart_tx_any_room(uint8 uart); #endif // MICROPY_INCLUDED_ESP8266_UART_H micropython-1.12/ports/esp8266/uart_register.h000066400000000000000000000110201357706137100213300ustar00rootroot00000000000000//Generated at 2012-07-03 18:44:06 /* * Copyright (c) 2010 - 2011 Espressif System * */ #ifndef UART_REGISTER_H_INCLUDED #define UART_REGISTER_H_INCLUDED #define REG_UART_BASE( i ) (0x60000000+(i)*0xf00) //version value:32'h062000 #define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0) #define UART_RXFIFO_RD_BYTE 0x000000FF #define UART_RXFIFO_RD_BYTE_S 0 #define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4) #define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) #define UART_BRK_DET_INT_RAW (BIT(7)) #define UART_CTS_CHG_INT_RAW (BIT(6)) #define UART_DSR_CHG_INT_RAW (BIT(5)) #define UART_RXFIFO_OVF_INT_RAW (BIT(4)) #define UART_FRM_ERR_INT_RAW (BIT(3)) #define UART_PARITY_ERR_INT_RAW (BIT(2)) #define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) #define UART_RXFIFO_FULL_INT_RAW (BIT(0)) #define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8) #define UART_RXFIFO_TOUT_INT_ST (BIT(8)) #define UART_BRK_DET_INT_ST (BIT(7)) #define UART_CTS_CHG_INT_ST (BIT(6)) #define UART_DSR_CHG_INT_ST (BIT(5)) #define UART_RXFIFO_OVF_INT_ST (BIT(4)) #define UART_FRM_ERR_INT_ST (BIT(3)) #define UART_PARITY_ERR_INT_ST (BIT(2)) #define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) #define UART_RXFIFO_FULL_INT_ST (BIT(0)) #define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC) #define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) #define UART_BRK_DET_INT_ENA (BIT(7)) #define UART_CTS_CHG_INT_ENA (BIT(6)) #define UART_DSR_CHG_INT_ENA (BIT(5)) #define UART_RXFIFO_OVF_INT_ENA (BIT(4)) #define UART_FRM_ERR_INT_ENA (BIT(3)) #define UART_PARITY_ERR_INT_ENA (BIT(2)) #define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) #define UART_RXFIFO_FULL_INT_ENA (BIT(0)) #define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10) #define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) #define UART_BRK_DET_INT_CLR (BIT(7)) #define UART_CTS_CHG_INT_CLR (BIT(6)) #define UART_DSR_CHG_INT_CLR (BIT(5)) #define UART_RXFIFO_OVF_INT_CLR (BIT(4)) #define UART_FRM_ERR_INT_CLR (BIT(3)) #define UART_PARITY_ERR_INT_CLR (BIT(2)) #define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) #define UART_RXFIFO_FULL_INT_CLR (BIT(0)) #define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14) #define UART_CLKDIV_CNT 0x000FFFFF #define UART_CLKDIV_S 0 #define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18) #define UART_GLITCH_FILT 0x000000FF #define UART_GLITCH_FILT_S 8 #define UART_AUTOBAUD_EN (BIT(0)) #define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C) #define UART_TXD (BIT(31)) #define UART_RTSN (BIT(30)) #define UART_DTRN (BIT(29)) #define UART_TXFIFO_CNT 0x000000FF #define UART_TXFIFO_CNT_S 16 #define UART_RXD (BIT(15)) #define UART_CTSN (BIT(14)) #define UART_DSRN (BIT(13)) #define UART_RXFIFO_CNT 0x000000FF #define UART_RXFIFO_CNT_S 0 #define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20) #define UART_TXFIFO_RST (BIT(18)) #define UART_RXFIFO_RST (BIT(17)) #define UART_IRDA_EN (BIT(16)) #define UART_TX_FLOW_EN (BIT(15)) #define UART_LOOPBACK (BIT(14)) #define UART_IRDA_RX_INV (BIT(13)) #define UART_IRDA_TX_INV (BIT(12)) #define UART_IRDA_WCTL (BIT(11)) #define UART_IRDA_TX_EN (BIT(10)) #define UART_IRDA_DPLX (BIT(9)) #define UART_TXD_BRK (BIT(8)) #define UART_SW_DTR (BIT(7)) #define UART_SW_RTS (BIT(6)) #define UART_STOP_BIT_NUM 0x00000003 #define UART_STOP_BIT_NUM_S 4 #define UART_BIT_NUM 0x00000003 #define UART_BIT_NUM_S 2 #define UART_PARITY_EN (BIT(1)) #define UART_PARITY (BIT(0)) #define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24) #define UART_RX_TOUT_EN (BIT(31)) #define UART_RX_TOUT_THRHD 0x0000007F #define UART_RX_TOUT_THRHD_S 24 #define UART_RX_FLOW_EN (BIT(23)) #define UART_RX_FLOW_THRHD 0x0000007F #define UART_RX_FLOW_THRHD_S 16 #define UART_TXFIFO_EMPTY_THRHD 0x0000007F #define UART_TXFIFO_EMPTY_THRHD_S 8 #define UART_RXFIFO_FULL_THRHD 0x0000007F #define UART_RXFIFO_FULL_THRHD_S 0 #define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28) #define UART_LOWPULSE_MIN_CNT 0x000FFFFF #define UART_LOWPULSE_MIN_CNT_S 0 #define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C) #define UART_HIGHPULSE_MIN_CNT 0x000FFFFF #define UART_HIGHPULSE_MIN_CNT_S 0 #define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30) #define UART_PULSE_NUM_CNT 0x0003FF #define UART_PULSE_NUM_CNT_S 0 #define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78) #define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C) #endif // UART_REGISTER_H_INCLUDED micropython-1.12/ports/esp8266/user_config.h000066400000000000000000000000111357706137100207520ustar00rootroot00000000000000// empty micropython-1.12/ports/esp8266/xtirq.h000066400000000000000000000042431357706137100176310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_ESP8266_XTIRQ_H #define MICROPY_INCLUDED_ESP8266_XTIRQ_H #include // returns the value of "intlevel" from the PS register static inline uint32_t query_irq(void) { uint32_t ps; __asm__ volatile("rsr %0, ps" : "=a" (ps)); return ps & 0xf; } // irqs with a priority value lower or equal to "intlevel" will be disabled // "intlevel" should be between 0 and 15 inclusive, and should be an integer static inline uint32_t raise_irq_pri(uint32_t intlevel) { uint32_t old_ps; __asm__ volatile ("rsil %0, %1" : "=a" (old_ps) : "I" (intlevel)); return old_ps; } // "ps" should be the value returned from raise_irq_pri static inline void restore_irq_pri(uint32_t ps) { __asm__ volatile ("wsr %0, ps; rsync" :: "a" (ps)); } static inline uint32_t disable_irq(void) { return raise_irq_pri(15); } static inline void enable_irq(uint32_t irq_state) { restore_irq_pri(irq_state); } #endif // MICROPY_INCLUDED_ESP8266_XTIRQ_H micropython-1.12/ports/javascript/000077500000000000000000000000001357706137100173375ustar00rootroot00000000000000micropython-1.12/ports/javascript/JSBackend.patch000066400000000000000000000005211357706137100221420ustar00rootroot00000000000000--- JSBackend.cpp 2018-01-10 16:35:07.331418145 +1100 +++ JSBackend_mp_js.cpp 2018-01-10 16:40:04.804633134 +1100 @@ -4280,6 +4280,7 @@ void JSWriter::calculateNativizedVars(const Function *F) { NativizedVars.clear(); + return; for (Function::const_iterator I = F->begin(), BE = F->end(); I != BE; ++I) { auto BI = &*I; micropython-1.12/ports/javascript/Makefile000066400000000000000000000035741357706137100210100ustar00rootroot00000000000000include ../../py/mkenv.mk CROSS = 0 QSTR_DEFS = qstrdefsport.h include $(TOP)/py/py.mk CC = emcc -g4 LD = emcc -g4 INC += -I. INC += -I$(TOP) INC += -I$(BUILD) CPP = clang -E ifdef EMSCRIPTEN CPP += -isystem $(EMSCRIPTEN)/system/include/libc -cxx-isystem $(EMSCRIPTEN)/system/include/libcxx endif CFLAGS = -m32 -Wall -Werror $(INC) -std=c99 $(COPT) LDFLAGS = -m32 -Wl,-Map=$@.map,--cref -Wl,--gc-sections CFLAGS += -O0 -DNDEBUG CFLAGS += -fdata-sections -ffunction-sections ifneq ($(FROZEN_MPY_DIR),) # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and # then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY endif SRC_LIB = $(addprefix lib/,\ utils/interrupt_char.c \ utils/stdout_helpers.c \ utils/pyexec.c \ mp-readline/readline.c \ ) SRC_C = \ main.c \ mphalport.c \ modutime.c \ SRC_QSTR += $(SRC_C) OBJ = OBJ = $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) JSFLAGS = -O0 -s EXPORTED_FUNCTIONS="['_mp_js_init', '_mp_js_init_repl', '_mp_js_do_str', '_mp_js_process_char', '_mp_hal_get_interrupt_char', '_mp_keyboard_interrupt']" -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']" -s "BINARYEN_TRAP_MODE='clamp'" --memory-init-file 0 --js-library library.js all: $(BUILD)/micropython.js $(BUILD)/micropython.js: $(OBJ) library.js wrapper.js $(ECHO) "LINK $(BUILD)/firmware.js" $(Q)emcc $(LDFLAGS) -o $(BUILD)/firmware.js $(OBJ) $(JSFLAGS) cat wrapper.js $(BUILD)/firmware.js > $@ min: $(BUILD)/micropython.js uglifyjs $< -c -o $(BUILD)/micropython.min.js test: $(BUILD)/micropython.js $(TOP)/tests/run-tests $(eval DIRNAME=ports/$(notdir $(CURDIR))) cd $(TOP)/tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests include $(TOP)/py/mkrules.mk micropython-1.12/ports/javascript/README.md000066400000000000000000000057711357706137100206300ustar00rootroot00000000000000MicroPython.js ============== MicroPython transmuted into Javascript by Emscripten. Dependencies ------------ Building micropython.js bears the same requirements as the standard MicroPython ports with the addition of Emscripten (and uglify-js for the minified file). A standard installation of Emscripten should provide functional code, however if memory errors are encountered it may be worthwhile to modify the tool. `emscripten-fastcomp/lib/Target/JSBackend.cpp` may require the minor fix found in JSBackend.patch. This patch attempts to address situations where C code running through Emscripten is denied access to Javascript variables leading to false-positives in the MicroPython garbage collector as variables with pointers exclusively in Javascript will be erased prematurely. Refer to Emscripten documentation for instructions on building Emscripten from source. Build instructions ------------------ In order to build micropython.js, run: $ make To generate the minified file micropython.min.js, run: $ make min Running with Node.js -------------------- Access the repl with: $ node build/micropython.js Stack size may be modified using: $ node build/micropython.js -X stack=64K Where stack size may be represented in Bytes, KiB or MiB. MicroPython scripts may be executed using: $ node build/micropython.js hello.py Alternatively micropython.js may by accessed by other javascript programs in node using the require command and the general API outlined below. For example: ```javascript var mp_js = require('./build/micropython.js'); mp_js_init(64 * 1024); mp_js_do_str("print('hello world')\n"); ``` Running with HTML ----------------- The prerequisite for browser operation of micropython.js is an element with the id `mp_js_stdout` which receives `print` events. The following code demonstrates basic functionality: ```html
``` MicroPython code execution will suspend the browser so be sure to atomize usage within this environment. Unfortunately interrupts have not been implemented for the browser. Testing ------- Run the test suite using: $ make test API --- The following functions have been exposed to javascript. ``` mp_js_init(stack_size) ``` Initialize MicroPython with the given stack size in bytes. This must be called before attempting to interact with MicroPython. ``` mp_js_do_str(code) ``` Execute the input code. `code` must be a `string`. ``` mp_js_init_repl() ``` Initialize MicroPython repl. Must be called before entering characters into the repl. ``` mp_js_process_char(char) ``` Input character into MicroPython repl. `char` must be of type `number`. This will execute MicroPython code when necessary. micropython-1.12/ports/javascript/library.h000066400000000000000000000025251357706137100211600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" extern void mp_js_write(const char *str, mp_uint_t len); extern int mp_js_ticks_ms(void); extern void mp_js_hook(void); micropython-1.12/ports/javascript/library.js000066400000000000000000000053431357706137100213460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ mergeInto(LibraryManager.library, { mp_js_write: function(ptr, len) { for (var i = 0; i < len; ++i) { if (typeof window === 'undefined') { var b = Buffer.alloc(1); b.writeInt8(getValue(ptr + i, 'i8')); process.stdout.write(b); } else { var c = String.fromCharCode(getValue(ptr + i, 'i8')); var mp_js_stdout = document.getElementById('mp_js_stdout'); var print = new Event('print'); print.data = c; mp_js_stdout.dispatchEvent(print); } } }, mp_js_ticks_ms: function() { return (new Date()).getTime() - MP_JS_EPOCH; }, mp_js_hook: function() { if (typeof window === 'undefined') { var mp_interrupt_char = Module.ccall('mp_hal_get_interrupt_char', 'number', ['number'], ['null']); var fs = require('fs'); var buf = Buffer.alloc(1); try { var n = fs.readSync(process.stdin.fd, buf, 0, 1); if (n > 0) { if (buf[0] == mp_interrupt_char) { Module.ccall('mp_keyboard_interrupt', 'null', ['null'], ['null']); } else { process.stdout.write(String.fromCharCode(buf[0])); } } } catch (e) { if (e.code === 'EAGAIN') { } else { throw e; } } } }, }); micropython-1.12/ports/javascript/main.c000066400000000000000000000107201357706137100204270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George and 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" #include "py/gc.h" #include "py/mperrno.h" #include "lib/utils/pyexec.h" #include "library.h" #if MICROPY_ENABLE_COMPILER int do_str(const char *src, mp_parse_input_kind_t input_kind) { int ret = 0; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) { mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); if (exit_val != mp_const_none) { mp_int_t int_val; if (mp_obj_get_int_maybe(exit_val, &int_val)) { ret = int_val & 255; } else { ret = 1; } } } else { mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); ret = 1; } } return ret; } #endif static char *stack_top; int mp_js_do_str(const char *code) { return do_str(code, MP_PARSE_FILE_INPUT); } int mp_js_process_char(int c) { return pyexec_event_repl_process_char(c); } void mp_js_init(int heap_size) { int stack_dummy; stack_top = (char*)&stack_dummy; #if MICROPY_ENABLE_GC char *heap = (char*)malloc(heap_size * sizeof(char)); gc_init(heap, heap + heap_size); #endif #if MICROPY_ENABLE_PYSTACK static mp_obj_t pystack[1024]; mp_pystack_init(pystack, &pystack[MP_ARRAY_SIZE(pystack)]); #endif mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); mp_obj_list_init(mp_sys_argv, 0); } void mp_js_init_repl() { pyexec_event_repl_init(); } void gc_collect(void) { // WARNING: This gc_collect implementation doesn't try to get root // pointers from CPU registers, and thus may function incorrectly. jmp_buf dummy; if (setjmp(dummy) == 0) { longjmp(dummy, 1); } gc_collect_start(); gc_collect_root((void*)stack_top, ((mp_uint_t)(void*)(&dummy + 1) - (mp_uint_t)stack_top) / sizeof(mp_uint_t)); gc_collect_end(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { while (1); } void NORETURN __fatal_error(const char *msg) { while (1); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error("Assertion failed"); } #endif micropython-1.12/ports/javascript/modutime.c000066400000000000000000000045701357706137100213340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George and 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "mphalport.h" #include "py/nlr.h" #include "py/smallint.h" #include "py/obj.h" #include "py/runtime.h" #include "lib/timeutils/timeutils.h" #include "extmod/utime_mphal.h" STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t mp_module_utime = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; micropython-1.12/ports/javascript/mpconfigport.h000066400000000000000000000167071357706137100222320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George and 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include // options to control how MicroPython is built // You can disable the built-in MicroPython compiler by setting the following // config option to 0. If you do this then you won't get a REPL prompt, but you // will still be able to execute pre-compiled scripts, compiled with mpy-cross. #define MICROPY_ENABLE_COMPILER (1) #define MICROPY_QSTR_BYTES_IN_HASH (2) #define MICROPY_ALLOC_PATH_MAX (256) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) #define MICROPY_EMIT_X64 (0) //BROKEN #define MICROPY_EMIT_THUMB (0) //BROKEN #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (0) #define MICROPY_COMP_CONST (1) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #define MICROPY_MEM_STATS (0) //BROKEN #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_ENABLE_GC (1) #define MICROPY_GC_ALLOC_THRESHOLD (1) #define MICROPY_GC_USES_ALLOCATED_SIZE (1) #define MICROPY_REPL_EVENT_DRIVEN (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_ENABLE_DOC_STRING (1) #define MICROPY_WARNINGS (1) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1) #define MICROPY_PY_ASYNC_AWAIT (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_REVERSED (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY___FILE__ (1) #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) #define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO (1) #define MICROPY_PY_STRUCT (1) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_CPYTHON_COMPAT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_USE_INTERNAL_PRINTF (0) #define MICROPY_ENABLE_PYSTACK (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_EXECFILE (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_SYS_PLATFORM "javascript" #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #define MICROPY_PY_USELECT (1) #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_DEPTH (1) #define MP_SSIZE_MAX (0x7fffffff) extern const struct _mp_obj_module_t mp_module_utime; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ //#define MICROPY_EVENT_POLL_HOOK {ets_event_poll();} #if MICROPY_PY_THREAD #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ if (pyb_thread_enabled) { \ MP_THREAD_GIL_EXIT(); \ pyb_thread_yield(); \ MP_THREAD_GIL_ENTER(); \ } else { \ } \ } while (0); #define MICROPY_THREAD_YIELD() pyb_thread_yield() #else #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ } while (0); #define MICROPY_THREAD_YIELD() #endif #define MICROPY_VM_HOOK_COUNT (10) #define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT; #define MICROPY_VM_HOOK_POLL if (--vm_hook_divisor == 0) { \ vm_hook_divisor = MICROPY_VM_HOOK_COUNT; \ extern void mp_js_hook(void); \ mp_js_hook(); \ } #define MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_POLL #define MICROPY_VM_HOOK_RETURN MICROPY_VM_HOOK_POLL // type definitions for the specific machine //#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) // This port is intended to be 32-bit, but unfortunately, int32_t for // different targets may be defined in different ways - either as int // or as long. This requires different printf formatting specifiers // to print such value. So, we avoid int32_t and use int directly. #define UINT_FMT "%u" #define INT_FMT "%d" typedef int mp_int_t; // must be pointer size typedef unsigned mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, // We need to provide a declaration/definition of alloca() #include #define MICROPY_HW_BOARD_NAME "JS" #define MICROPY_HW_MCU_NAME "Emscripten" #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; micropython-1.12/ports/javascript/mphalport.c000066400000000000000000000036271357706137100215210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George and 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "library.h" #include "mphalport.h" void mp_hal_stdout_tx_strn(const char *str, size_t len) { mp_js_write(str, len); } void mp_hal_delay_ms(mp_uint_t ms) { uint32_t start = mp_hal_ticks_ms(); while (mp_hal_ticks_ms() - start < ms) { } } void mp_hal_delay_us(mp_uint_t us) { uint32_t start = mp_hal_ticks_us(); while (mp_hal_ticks_us() - start < us) { } } mp_uint_t mp_hal_ticks_us(void) { return mp_js_ticks_ms() * 1000; } mp_uint_t mp_hal_ticks_ms(void) { return mp_js_ticks_ms(); } mp_uint_t mp_hal_ticks_cpu(void) { return 0; } extern int mp_interrupt_char; int mp_hal_get_interrupt_char(void) { return mp_interrupt_char; } micropython-1.12/ports/javascript/mphalport.h000066400000000000000000000031211357706137100215130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George and 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "lib/utils/interrupt_char.h" #define mp_hal_stdin_rx_chr() (0) void mp_hal_stdout_tx_strn(const char *str, size_t len); void mp_hal_delay_ms(mp_uint_t ms); void mp_hal_delay_us(mp_uint_t us); mp_uint_t mp_hal_ticks_ms(void); mp_uint_t mp_hal_ticks_us(void); mp_uint_t mp_hal_ticks_cpu(void); int mp_hal_get_interrupt_char(void); micropython-1.12/ports/javascript/node_run.sh000077500000000000000000000000671357706137100215120ustar00rootroot00000000000000#!/bin/sh node $(dirname $0)/build/micropython.js "$@" micropython-1.12/ports/javascript/qstrdefsport.h000066400000000000000000000000371357706137100222500ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/javascript/wrapper.js000066400000000000000000000056751357706137100213720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017, 2018 Rami Ali * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ var Module = {}; var mainProgram = function() { mp_js_init = Module.cwrap('mp_js_init', 'null', ['number']); mp_js_do_str = Module.cwrap('mp_js_do_str', 'number', ['string']); mp_js_init_repl = Module.cwrap('mp_js_init_repl', 'null', ['null']); mp_js_process_char = Module.cwrap('mp_js_process_char', 'number', ['number']); MP_JS_EPOCH = (new Date()).getTime(); if (typeof window === 'undefined' && require.main === module) { var fs = require('fs'); var stack_size = 64 * 1024; var contents = ''; var repl = true; for (var i = 0; i < process.argv.length; i++) { if (process.argv[i] === '-X' && i < process.argv.length - 1) { if (process.argv[i + 1].includes('stack=')) { stack_size = parseInt(process.argv[i + 1].split('stack=')[1]); if (process.argv[i + 1].substr(-1).toLowerCase() === 'k') { stack_size *= 1024; } else if (process.argv[i + 1].substr(-1).toLowerCase() === 'm') { stack_size *= 1024 * 1024; } } } else if (process.argv[i].includes('.py')) { contents += fs.readFileSync(process.argv[i], 'utf8'); repl = false;; } } mp_js_init(stack_size); if (repl) { mp_js_init_repl(); process.stdin.setRawMode(true); process.stdin.on('data', function (data) { for (var i = 0; i < data.length; i++) { if (mp_js_process_char(data[i])) { process.exit() } } }); } else { process.exitCode = mp_js_do_str(contents); } } } Module["onRuntimeInitialized"] = mainProgram; micropython-1.12/ports/minimal/000077500000000000000000000000001357706137100166175ustar00rootroot00000000000000micropython-1.12/ports/minimal/Makefile000066400000000000000000000045701357706137100202650ustar00rootroot00000000000000include ../../py/mkenv.mk CROSS = 0 # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk ifeq ($(CROSS), 1) CROSS_COMPILE = arm-none-eabi- endif INC += -I. INC += -I$(TOP) INC += -I$(BUILD) ifeq ($(CROSS), 1) DFU = $(TOP)/tools/dfu.py PYDFU = $(TOP)/tools/pydfu.py CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -fsingle-precision-constant -Wdouble-promotion CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref --gc-sections else LD = gcc CFLAGS = -m32 $(INC) -Wall -Werror -std=c99 $(COPT) LDFLAGS = -m32 -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif CSUPEROPT = -Os # save some code space # Tune for Debugging or Optimization ifeq ($(DEBUG), 1) CFLAGS += -O0 -ggdb else CFLAGS += -Os -DNDEBUG CFLAGS += -fdata-sections -ffunction-sections endif LIBS = SRC_C = \ main.c \ uart_core.c \ lib/utils/printf.c \ lib/utils/stdout_helpers.c \ lib/utils/pyexec.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ $(BUILD)/_frozen_mpy.c \ OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) ifeq ($(CROSS), 1) all: $(BUILD)/firmware.dfu else all: $(BUILD)/firmware.elf endif $(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h $(ECHO) "MISC freezing bytecode" $(Q)$(TOP)/tools/mpy-tool.py -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $< > $@ $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data $^ $(BUILD)/firmware.bin $(BUILD)/firmware.dfu: $(BUILD)/firmware.bin $(ECHO) "Create $@" $(Q)$(PYTHON) $(DFU) -b 0x08000000:$(BUILD)/firmware.bin $@ deploy: $(BUILD)/firmware.dfu $(ECHO) "Writing $< to the board" $(Q)$(PYTHON) $(PYDFU) -u $< # Run emulation build on a POSIX system with suitable terminal settings run: stty raw opost -echo build/firmware.elf @echo Resetting terminal... # This sleep is useful to spot segfaults sleep 1 reset test: $(BUILD)/firmware.elf $(Q)/bin/echo -e "print('hello world!', list(x+1 for x in range(10)), end='eol\\\\n')\\r\\n\\x04" | $(BUILD)/firmware.elf | tail -n2 | grep "^hello world! \\[1, 2, 3, 4, 5, 6, 7, 8, 9, 10\\]eol" include $(TOP)/py/mkrules.mk micropython-1.12/ports/minimal/README.md000066400000000000000000000030761357706137100201040ustar00rootroot00000000000000# The minimal port This port is intended to be a minimal MicroPython port that actually runs. It can run under Linux (or similar) and on any STM32F4xx MCU (eg the pyboard). ## Building and running Linux version By default the port will be built for the host machine: $ make To run the executable and get a basic working REPL do: $ make run ## Building for an STM32 MCU The Makefile has the ability to build for a Cortex-M CPU, and by default includes some start-up code for an STM32F4xx MCU and also enables a UART for communication. To build: $ make CROSS=1 If you previously built the Linux version, you will need to first run `make clean` to get rid of incompatible object files. Building will produce the build/firmware.dfu file which can be programmed to an MCU using: $ make CROSS=1 deploy This version of the build will work out-of-the-box on a pyboard (and anything similar), and will give you a MicroPython REPL on UART1 at 9600 baud. Pin PA13 will also be driven high, and this turns on the red LED on the pyboard. ## Building without the built-in MicroPython compiler This minimal port can be built with the built-in MicroPython compiler disabled. This will reduce the firmware by about 20k on a Thumb2 machine, and by about 40k on 32-bit x86. Without the compiler the REPL will be disabled, but pre-compiled scripts can still be executed. To test out this feature, change the `MICROPY_ENABLE_COMPILER` config option to "0" in the mpconfigport.h file in this directory. Then recompile and run the firmware and it will execute the frozentest.py file. micropython-1.12/ports/minimal/frozentest.mpy000066400000000000000000000003041357706137100215460ustar00rootroot00000000000000M Tfrozentest.py)(((+({uPy4Y{#4Y{#4Y{#4Y{"4YBWi{4YWCYQcs"a long string that is not interneds&a string that has unicode αβγ charsb bytes 1234micropython-1.12/ports/minimal/frozentest.py000066400000000000000000000002631357706137100213750ustar00rootroot00000000000000print('uPy') print('a long string that is not interned') print('a string that has unicode αβγ chars') print(b'bytes 1234\x01') print(123456789) for i in range(4): print(i) micropython-1.12/ports/minimal/main.c000066400000000000000000000164551357706137100177220ustar00rootroot00000000000000#include #include #include #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" #include "py/gc.h" #include "py/mperrno.h" #include "lib/utils/pyexec.h" #if MICROPY_ENABLE_COMPILER void do_str(const char *src, mp_parse_input_kind_t input_kind) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } } #endif static char *stack_top; #if MICROPY_ENABLE_GC static char heap[2048]; #endif int main(int argc, char **argv) { int stack_dummy; stack_top = (char*)&stack_dummy; #if MICROPY_ENABLE_GC gc_init(heap, heap + sizeof(heap)); #endif mp_init(); #if MICROPY_ENABLE_COMPILER #if MICROPY_REPL_EVENT_DRIVEN pyexec_event_repl_init(); for (;;) { int c = mp_hal_stdin_rx_chr(); if (pyexec_event_repl_process_char(c)) { break; } } #else pyexec_friendly_repl(); #endif //do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT); //do_str("for i in range(10):\r\n print(i)", MP_PARSE_FILE_INPUT); #else pyexec_frozen_module("frozentest.py"); #endif mp_deinit(); return 0; } void gc_collect(void) { // WARNING: This gc_collect implementation doesn't try to get root // pointers from CPU registers, and thus may function incorrectly. void *dummy; gc_collect_start(); gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); gc_collect_end(); gc_dump_info(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { while (1); } void NORETURN __fatal_error(const char *msg) { while (1); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error("Assertion failed"); } #endif #if MICROPY_MIN_USE_CORTEX_CPU // this is a minimal IRQ and reset framework for any Cortex-M CPU extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; void Reset_Handler(void) __attribute__((naked)); void Reset_Handler(void) { // set stack pointer __asm volatile ("ldr sp, =_estack"); // copy .data section from flash to RAM for (uint32_t *src = &_sidata, *dest = &_sdata; dest < &_edata;) { *dest++ = *src++; } // zero out .bss section for (uint32_t *dest = &_sbss; dest < &_ebss;) { *dest++ = 0; } // jump to board initialisation void _start(void); _start(); } void Default_Handler(void) { for (;;) { } } const uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = { (uint32_t)&_estack, (uint32_t)&Reset_Handler, (uint32_t)&Default_Handler, // NMI_Handler (uint32_t)&Default_Handler, // HardFault_Handler (uint32_t)&Default_Handler, // MemManage_Handler (uint32_t)&Default_Handler, // BusFault_Handler (uint32_t)&Default_Handler, // UsageFault_Handler 0, 0, 0, 0, (uint32_t)&Default_Handler, // SVC_Handler (uint32_t)&Default_Handler, // DebugMon_Handler 0, (uint32_t)&Default_Handler, // PendSV_Handler (uint32_t)&Default_Handler, // SysTick_Handler }; void _start(void) { // when we get here: stack is initialised, bss is clear, data is copied // SCB->CCR: enable 8-byte stack alignment for IRQ handlers, in accord with EABI *((volatile uint32_t*)0xe000ed14) |= 1 << 9; // initialise the cpu and peripherals #if MICROPY_MIN_USE_STM32_MCU void stm32_init(void); stm32_init(); #endif // now that we have a basic system up and running we can call main main(0, NULL); // we must not return for (;;) { } } #endif #if MICROPY_MIN_USE_STM32_MCU // this is minimal set-up code for an STM32 MCU typedef struct { volatile uint32_t CR; volatile uint32_t PLLCFGR; volatile uint32_t CFGR; volatile uint32_t CIR; uint32_t _1[8]; volatile uint32_t AHB1ENR; volatile uint32_t AHB2ENR; volatile uint32_t AHB3ENR; uint32_t _2; volatile uint32_t APB1ENR; volatile uint32_t APB2ENR; } periph_rcc_t; typedef struct { volatile uint32_t MODER; volatile uint32_t OTYPER; volatile uint32_t OSPEEDR; volatile uint32_t PUPDR; volatile uint32_t IDR; volatile uint32_t ODR; volatile uint16_t BSRRL; volatile uint16_t BSRRH; volatile uint32_t LCKR; volatile uint32_t AFR[2]; } periph_gpio_t; typedef struct { volatile uint32_t SR; volatile uint32_t DR; volatile uint32_t BRR; volatile uint32_t CR1; } periph_uart_t; #define USART1 ((periph_uart_t*) 0x40011000) #define GPIOA ((periph_gpio_t*) 0x40020000) #define GPIOB ((periph_gpio_t*) 0x40020400) #define RCC ((periph_rcc_t*) 0x40023800) // simple GPIO interface #define GPIO_MODE_IN (0) #define GPIO_MODE_OUT (1) #define GPIO_MODE_ALT (2) #define GPIO_PULL_NONE (0) #define GPIO_PULL_UP (0) #define GPIO_PULL_DOWN (1) void gpio_init(periph_gpio_t *gpio, int pin, int mode, int pull, int alt) { gpio->MODER = (gpio->MODER & ~(3 << (2 * pin))) | (mode << (2 * pin)); // OTYPER is left as default push-pull // OSPEEDR is left as default low speed gpio->PUPDR = (gpio->PUPDR & ~(3 << (2 * pin))) | (pull << (2 * pin)); gpio->AFR[pin >> 3] = (gpio->AFR[pin >> 3] & ~(15 << (4 * (pin & 7)))) | (alt << (4 * (pin & 7))); } #define gpio_get(gpio, pin) ((gpio->IDR >> (pin)) & 1) #define gpio_set(gpio, pin, value) do { gpio->ODR = (gpio->ODR & ~(1 << (pin))) | (value << pin); } while (0) #define gpio_low(gpio, pin) do { gpio->BSRRH = (1 << (pin)); } while (0) #define gpio_high(gpio, pin) do { gpio->BSRRL = (1 << (pin)); } while (0) void stm32_init(void) { // basic MCU config RCC->CR |= (uint32_t)0x00000001; // set HSION RCC->CFGR = 0x00000000; // reset all RCC->CR &= (uint32_t)0xfef6ffff; // reset HSEON, CSSON, PLLON RCC->PLLCFGR = 0x24003010; // reset PLLCFGR RCC->CR &= (uint32_t)0xfffbffff; // reset HSEBYP RCC->CIR = 0x00000000; // disable IRQs // leave the clock as-is (internal 16MHz) // enable GPIO clocks RCC->AHB1ENR |= 0x00000003; // GPIOAEN, GPIOBEN // turn on an LED! (on pyboard it's the red one) gpio_init(GPIOA, 13, GPIO_MODE_OUT, GPIO_PULL_NONE, 0); gpio_high(GPIOA, 13); // enable UART1 at 9600 baud (TX=B6, RX=B7) gpio_init(GPIOB, 6, GPIO_MODE_ALT, GPIO_PULL_NONE, 7); gpio_init(GPIOB, 7, GPIO_MODE_ALT, GPIO_PULL_NONE, 7); RCC->APB2ENR |= 0x00000010; // USART1EN USART1->BRR = (104 << 4) | 3; // 16MHz/(16*104.1875) = 9598 baud USART1->CR1 = 0x0000200c; // USART enable, tx enable, rx enable } #endif micropython-1.12/ports/minimal/mpconfigport.h000066400000000000000000000072111357706137100215000ustar00rootroot00000000000000#include // options to control how MicroPython is built // You can disable the built-in MicroPython compiler by setting the following // config option to 0. If you do this then you won't get a REPL prompt, but you // will still be able to execute pre-compiled scripts, compiled with mpy-cross. #define MICROPY_ENABLE_COMPILER (1) #define MICROPY_QSTR_BYTES_IN_HASH (1) #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool #define MICROPY_ALLOC_PATH_MAX (256) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (0) #define MICROPY_COMP_CONST (0) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_ENABLE_GC (1) #define MICROPY_GC_ALLOC_THRESHOLD (0) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_BUILTINS_BYTEARRAY (0) #define MICROPY_PY_BUILTINS_DICT_FROMKEYS (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_SLICE (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_BUILTINS_MIN_MAX (0) #define MICROPY_PY_BUILTINS_STR_COUNT (0) #define MICROPY_PY_BUILTINS_STR_OP_MODULO (0) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_GC (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS (0) #define MICROPY_MODULE_FROZEN_MPY (1) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) // This port is intended to be 32-bit, but unfortunately, int32_t for // different targets may be defined in different ways - either as int // or as long. This requires different printf formatting specifiers // to print such value. So, we avoid int32_t and use int directly. #define UINT_FMT "%u" #define INT_FMT "%d" typedef int mp_int_t; // must be pointer size typedef unsigned mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, // We need to provide a declaration/definition of alloca() #include #define MICROPY_HW_BOARD_NAME "minimal" #define MICROPY_HW_MCU_NAME "unknown-cpu" #ifdef __linux__ #define MICROPY_MIN_USE_STDOUT (1) #endif #ifdef __thumb__ #define MICROPY_MIN_USE_CORTEX_CPU (1) #define MICROPY_MIN_USE_STM32_MCU (1) #endif #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; micropython-1.12/ports/minimal/mphalport.h000066400000000000000000000001641357706137100207770ustar00rootroot00000000000000static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; } static inline void mp_hal_set_interrupt_char(char c) {} micropython-1.12/ports/minimal/qstrdefsport.h000066400000000000000000000000371357706137100215300ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/minimal/stm32f405.ld000066400000000000000000000041631357706137100205130ustar00rootroot00000000000000/* GNU linker script for STM32F405 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x100000 /* entire flash, 1 MiB */ CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 0x010000 /* 64 KiB */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x020000 /* 128 KiB */ } /* top end of the stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); /* define output sections */ SECTIONS { /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); KEEP(*(.isr_vector)) /* isr vector table */ *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ _sidata = _etext; /* This is used by the startup in order to initialize the .data secion */ } >FLASH /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ .data : AT ( _sidata ) { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM /* Uninitialized data section */ .bss : { . = ALIGN(4); _sbss = .; /* define a global symbol at bss start; used by startup code */ *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end; used by startup code */ } >RAM .ARM.attributes 0 : { *(.ARM.attributes) } } micropython-1.12/ports/minimal/uart_core.c000066400000000000000000000016151357706137100207510ustar00rootroot00000000000000#include #include "py/mpconfig.h" /* * Core UART functions to implement for a port */ #if MICROPY_MIN_USE_STM32_MCU typedef struct { volatile uint32_t SR; volatile uint32_t DR; } periph_uart_t; #define USART1 ((periph_uart_t*)0x40011000) #endif // Receive single character int mp_hal_stdin_rx_chr(void) { unsigned char c = 0; #if MICROPY_MIN_USE_STDOUT int r = read(0, &c, 1); (void)r; #elif MICROPY_MIN_USE_STM32_MCU // wait for RXNE while ((USART1->SR & (1 << 5)) == 0) { } c = USART1->DR; #endif return c; } // Send string of given length void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { #if MICROPY_MIN_USE_STDOUT int r = write(1, str, len); (void)r; #elif MICROPY_MIN_USE_STM32_MCU while (len--) { // wait for TXE while ((USART1->SR & (1 << 7)) == 0) { } USART1->DR = *str++; } #endif } micropython-1.12/ports/nrf/000077500000000000000000000000001357706137100157565ustar00rootroot00000000000000micropython-1.12/ports/nrf/.gitignore000066400000000000000000000000741357706137100177470ustar00rootroot00000000000000# Nordic files ##################### drivers/bluetooth/s1*/ micropython-1.12/ports/nrf/Makefile000066400000000000000000000305111357706137100174160ustar00rootroot00000000000000# Select the board to build for: if not given on the command line, # then default to pca10040. BOARD ?= pca10040 ifeq ($(wildcard boards/$(BOARD)/.),) $(error Invalid BOARD specified) endif # If SoftDevice is selected, try to use that one. SD ?= SD_LOWER = $(shell echo $(SD) | tr '[:upper:]' '[:lower:]') # TODO: Verify that it is a valid target. include boards/$(BOARD)/mpconfigboard.mk ifeq ($(SD), ) # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD) include ../../py/mkenv.mk else # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD)-$(SD_LOWER) include ../../py/mkenv.mk LD_FILES += boards/$(SD_LOWER)_$(SOFTDEV_VERSION).ld include drivers/bluetooth/bluetooth_common.mk endif LD_FILES += boards/memory.ld boards/common.ld ifneq ($(LD_FILE),) # Use custom LD file LD_FILES = $(LD_FILE) endif -include boards/$(BOARD)/modules/boardmodules.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h # include py core make definitions include ../../py/py.mk GIT_SUBMODULES = lib/nrfx lib/tinyusb MICROPY_VFS_FAT ?= 0 MPY_CROSS = ../../mpy-cross/mpy-cross MPY_TOOL = ../../tools/mpy-tool.py CROSS_COMPILE = arm-none-eabi- INC += -I. INC += -I../.. INC += -I$(BUILD) INC += -I./../../lib/cmsis/inc INC += -I./modules/machine INC += -I./modules/ubluepy INC += -I./modules/music INC += -I./modules/random INC += -I./modules/ble INC += -I./modules/board INC += -I../../lib/mp-readline INC += -I./drivers/bluetooth INC += -I./drivers INC += -I../../lib/nrfx/ INC += -I../../lib/nrfx/drivers INC += -I../../lib/nrfx/drivers/include INC += -I../../lib/nrfx/mdk INC += -I../../lib/nrfx/hal INC += -I../../lib/nrfx/drivers/src/ MCU_VARIANT_UPPER = $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]') MCU_SUB_VARIANT_UPPER = $(shell echo $(MCU_SUB_VARIANT) | tr '[:lower:]' '[:upper:]') # Figure out correct system file to use base on chip sub-variant name. SYSTEM_C_SRC := ifeq ($(MCU_SUB_VARIANT),nrf51822) SYSTEM_C_SRC += $(addprefix lib/nrfx/mdk/, system_nrf51.c) NRF_DEFINES += -D$(MCU_VARIANT_UPPER) else ifeq ($(MCU_SUB_VARIANT),nrf52832) SYSTEM_C_SRC += $(addprefix lib/nrfx/mdk/, system_nrf52.c) NRF_DEFINES += -D$(MCU_VARIANT_UPPER) else ifeq ($(MCU_SUB_VARIANT),nrf52840) SYSTEM_C_SRC += $(addprefix lib/nrfx/mdk/, system_nrf52840.c) # Do not pass MCU_VARIANT_UPPER flag, as NRF52 defines NRF52832 only. else ifeq ($(MCU_SUB_VARIANT),nrf9160) SYSTEM_C_SRC += $(addprefix lib/nrfx/mdk/, system_nrf9160.c) NRF_DEFINES += -D$(MCU_VARIANT_UPPER) endif NRF_DEFINES += -D$(MCU_SUB_VARIANT_UPPER) NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET CFLAGS_CORTEX_M = -mthumb -mabi=aapcs -fsingle-precision-constant -Wdouble-promotion CFLAGS_MCU_m33 = $(CFLAGS_CORTEX_M) -mcpu=cortex-m33 -march=armv8-m.main+dsp -mcmse -mfpu=fpv5-sp-d16 -mfloat-abi=hard CFLAGS_MCU_m4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard CFLAGS_MCU_m0 = $(CFLAGS_CORTEX_M) -fshort-enums -mtune=cortex-m0 -mcpu=cortex-m0 -mfloat-abi=soft -fno-builtin LTO ?= 1 ifeq ($(LTO),1) CFLAGS += -flto else CFLAGS += -ffunction-sections -fdata-sections LDFLAGS += -Wl,--gc-sections endif CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(INC) -Wall -Werror -g -ansi -std=c11 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_MOD) CFLAGS += -fno-strict-aliasing CFLAGS += -Iboards/$(BOARD) CFLAGS += -DNRF5_HAL_H='<$(MCU_VARIANT)_hal.h>' LDFLAGS = $(CFLAGS) LDFLAGS += -Xlinker -Map=$(@:.elf=.map) LDFLAGS += -mthumb -mabi=aapcs $(addprefix -T,$(LD_FILES)) -L boards/ #Debugging/Optimization ifeq ($(DEBUG), 1) #ASMFLAGS += -g -gtabs+ CFLAGS += -O0 -ggdb LDFLAGS += -O0 else CFLAGS += -Os -DNDEBUG LDFLAGS += -Os endif LIBS = \ ifeq ($(MCU_VARIANT), nrf52) SRC_LIB += $(addprefix lib/,\ libm/math.c \ libm/fmodf.c \ libm/nearbyintf.c \ libm/ef_sqrt.c \ libm/kf_rem_pio2.c \ libm/kf_sin.c \ libm/kf_cos.c \ libm/kf_tan.c \ libm/ef_rem_pio2.c \ libm/sf_sin.c \ libm/sf_cos.c \ libm/sf_tan.c \ libm/sf_frexp.c \ libm/sf_modf.c \ libm/sf_ldexp.c \ libm/asinfacosf.c \ libm/atanf.c \ libm/atan2f.c \ ) endif ifeq ($(MCU_VARIANT), nrf91) SRC_LIB += $(addprefix lib/,\ libm/math.c \ libm/fmodf.c \ libm/nearbyintf.c \ libm/ef_sqrt.c \ libm/kf_rem_pio2.c \ libm/kf_sin.c \ libm/kf_cos.c \ libm/kf_tan.c \ libm/ef_rem_pio2.c \ libm/sf_sin.c \ libm/sf_cos.c \ libm/sf_tan.c \ libm/sf_frexp.c \ libm/sf_modf.c \ libm/sf_ldexp.c \ libm/asinfacosf.c \ libm/atanf.c \ libm/atan2f.c \ ) SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\ nrfx_uarte.c \ nrfx_twim.c \ ) include drivers/secureboot/secureboot.mk endif SRC_LIB += $(addprefix lib/,\ libc/string0.c \ mp-readline/readline.c \ utils/pyexec.c \ utils/sys_stdio_mphal.c \ utils/interrupt_char.c \ timeutils/timeutils.c \ ) ifeq ($(MICROPY_FATFS), 1) SRC_LIB += $(addprefix lib/,\ oofatfs/ff.c \ oofatfs/ffunicode.c \ ) endif SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\ prs/nrfx_prs.c \ nrfx_uart.c \ nrfx_adc.c \ nrfx_saadc.c \ nrfx_rng.c \ nrfx_twi.c \ nrfx_spi.c \ nrfx_spim.c \ nrfx_rtc.c \ nrfx_timer.c \ nrfx_pwm.c \ nrfx_gpiote.c \ nrfx_nvmc.c \ nrfx_power.c \ nrfx_clock.c \ ) SRC_C += \ main.c \ mphalport.c \ help.c \ gccollect.c \ pin_named_pins.c \ fatfs_port.c \ drivers/flash.c \ drivers/softpwm.c \ drivers/ticker.c \ drivers/bluetooth/ble_drv.c \ drivers/bluetooth/ble_uart.c \ ifeq ($(MCU_SUB_VARIANT), nrf52840) INC += -I./drivers/usb INC += -I../../lib/tinyusb/src # If SoftDevice is selected. ifneq ($(SD), ) # For external tinyusb drivers to enable SoftDevice mode. CFLAGS += -DSOFTDEVICE_PRESENT endif SRC_C += $(addprefix drivers/usb/,\ usb_cdc.c \ usb_descriptors.c \ ) SRC_C += $(addprefix lib/tinyusb/src/,\ common/tusb_fifo.c \ device/usbd.c \ device/usbd_control.c \ class/cdc/cdc_device.c \ tusb.c \ portable/nordic/nrf5x/dcd_nrf5x.c \ portable/nordic/nrf5x/hal_nrf5x.c \ ) endif DRIVERS_SRC_C += $(addprefix modules/,\ machine/modmachine.c \ machine/uart.c \ machine/spi.c \ machine/i2c.c \ machine/adc.c \ machine/pin.c \ machine/timer.c \ machine/rtcounter.c \ machine/pwm.c \ machine/temp.c \ uos/moduos.c \ uos/microbitfs.c \ utime/modutime.c \ board/modboard.c \ board/led.c \ ubluepy/modubluepy.c \ ubluepy/ubluepy_peripheral.c \ ubluepy/ubluepy_service.c \ ubluepy/ubluepy_characteristic.c \ ubluepy/ubluepy_uuid.c \ ubluepy/ubluepy_delegate.c \ ubluepy/ubluepy_constants.c \ ubluepy/ubluepy_descriptor.c \ ubluepy/ubluepy_scanner.c \ ubluepy/ubluepy_scan_entry.c \ music/modmusic.c \ music/musictunes.c \ ble/modble.c \ random/modrandom.c \ ) # Custom micropython startup file with smaller interrupt vector table # than the file provided in nrfx. SRC_C += \ device/startup_$(MCU_SUB_VARIANT).c \ ifneq ($(FROZEN_MPY_DIR),) FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) endif LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc OBJ += $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SYSTEM_C_SRC:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(BUILD)/pins_gen.o $(BUILD)/$(OOFATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os .PHONY: all flash deploy sd binary hex ifeq ($(MCU_VARIANT), nrf91) all: binary hex secureboot else all: binary hex endif OUTPUT_FILENAME = firmware ## Create binary .bin file from the .out file binary: $(BUILD)/$(OUTPUT_FILENAME).bin $(BUILD)/$(OUTPUT_FILENAME).bin: $(BUILD)/$(OUTPUT_FILENAME).elf $(OBJCOPY) -O binary $< $@ ## Create binary .hex file from the .out file hex: $(BUILD)/$(OUTPUT_FILENAME).hex $(BUILD)/$(OUTPUT_FILENAME).hex: $(BUILD)/$(OUTPUT_FILENAME).elf $(OBJCOPY) -O ihex $< $@ FLASHER ?= ifeq ($(FLASHER),) ifeq ($(MCU_VARIANT), nrf91) deploy: $(BUILD)/$(OUTPUT_FILENAME).hex $(BUILD)/secureboot.hex nrfjprog --program $(BUILD)/secureboot.hex --sectorerase -f $(MCU_VARIANT) nrfjprog --program $(BUILD)/$(OUTPUT_FILENAME).hex --sectorerase -f $(MCU_VARIANT) nrfjprog --reset -f $(MCU_VARIANT) else deploy: $(BUILD)/$(OUTPUT_FILENAME).hex nrfjprog --program $< --sectorerase -f $(MCU_VARIANT) nrfjprog --reset -f $(MCU_VARIANT) endif sd: $(BUILD)/$(OUTPUT_FILENAME).hex nrfjprog --eraseall -f $(MCU_VARIANT) nrfjprog --program $(SOFTDEV_HEX) -f $(MCU_VARIANT) nrfjprog --program $< --sectorerase -f $(MCU_VARIANT) nrfjprog --reset -f $(MCU_VARIANT) else ifeq ($(FLASHER), pyocd) deploy: $(BUILD)/$(OUTPUT_FILENAME).hex pyocd-flashtool -t $(MCU_VARIANT) $< sd: $(BUILD)/$(OUTPUT_FILENAME).hex pyocd-flashtool -t $(MCU_VARIANT) --chip_erase pyocd-flashtool -t $(MCU_VARIANT) $(SOFTDEV_HEX) pyocd-flashtool -t $(MCU_VARIANT) $< else ifeq ($(FLASHER), idap) deploy: $(BUILD)/$(OUTPUT_FILENAME).hex IDAPnRFPRog $< sd: $(BUILD)/$(OUTPUT_FILENAME).hex IDAPnRFPRog $(SOFTDEV_HEX) $< else ifeq ($(FLASHER), bmp) BMP_PORT ?= /dev/ttyACM0 deploy: $(BUILD)/$(OUTPUT_FILENAME).elf $(Q)$(GDB) \ -ex 'target extended-remote $(BMP_PORT)' \ -ex 'monitor tpwr enable' \ -ex 'monitor swdp_scan' \ -ex 'attach 1' \ -ex 'set mem inaccessible-by-default off' \ -ex 'load' \ -ex 'kill' \ -ex 'quit' \ $< sd: $(BUILD)/$(OUTPUT_FILENAME).elf $(Q)$(GDB) \ -ex 'target extended-remote $(BMP_PORT)' \ -ex 'monitor tpwr enable' \ -ex 'monitor swdp_scan' \ -ex 'attach 1' \ -ex 'set mem inaccessible-by-default off' \ -ex 'monitor erase_mass' \ -ex 'load' \ -ex 'file $(SOFTDEV_HEX)' \ -ex 'load' \ -ex 'kill' \ -ex 'quit' \ $< endif flash: deploy $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(Q)$(SIZE) $@ # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(SRC_LIB) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += # Making OBJ use an order-only depenedency on the generated pins.h file # has the side effect of making the pins.h file before we actually compile # any of the objects. The normal dependency generation will deal with the # case when pins.h is modified. But when it doesn't exist, we don't know # which source files might need it. $(OBJ): | $(HEADER_BUILD)/pins.h # Use a pattern rule here so that make will only call make-pins.py once to make # both pins_gen.c and pins.h $(BUILD)/%_gen.c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(BUILD)/%_qstr.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD) $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC) $(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c $(call compile_c) MAKE_PINS = boards/make-pins.py BOARD_PINS = boards/$(BOARD)/pins.csv AF_FILE = $(MCU_VARIANT)_af.csv PREFIX_FILE = boards/$(MCU_VARIANT)_prefix.c GEN_PINS_SRC = $(BUILD)/pins_gen.c GEN_PINS_HDR = $(HEADER_BUILD)/pins.h GEN_PINS_QSTR = $(BUILD)/pins_qstr.h GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h GEN_PINS_AF_PY = $(BUILD)/pins_af.py ifneq ($(FROZEN_DIR),) # To use frozen source modules, put your .py files in a subdirectory (eg scripts/) # and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch). CFLAGS += -DMICROPY_MODULE_FROZEN_STR endif ifneq ($(FROZEN_MPY_DIR),) # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and # then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY endif $(PY_BUILD)/nlr%.o: CFLAGS += -Os -fno-lto include ../../py/mkrules.mk micropython-1.12/ports/nrf/README.md000066400000000000000000000214711357706137100172420ustar00rootroot00000000000000# MicroPython Port To The Nordic Semiconductor nRF Series This is a port of MicroPython to the Nordic Semiconductor nRF series of chips. ## Supported Features * UART * SPI * LEDs * Pins * ADC * I2C * PWM (nRF52 only) * Temperature * RTC (Real Time Counter. Low-Power counter) * BLE support including: * Peripheral role on nrf51 targets * Central role and Peripheral role on nrf52 targets * _REPL over Bluetooth LE_ (optionally using WebBluetooth) * ubluepy: Bluetooth LE module for MicroPython * 1 non-connectable advertiser while in connection ## Tested Hardware * nRF51 * [micro:bit](http://microbit.org/) * PCA10000 (dongle) * PCA10001 * PCA10028 * PCA10031 (dongle) * [WT51822-S4AT](http://www.wireless-tag.com/wireless_module/BLE/WT51822-S4AT.html) * nRF52832 * [PCA10040](http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52%2Fdita%2Fnrf52%2Fdevelopment%2Fnrf52_dev_kit.html) * [Adafruit Feather nRF52](https://www.adafruit.com/product/3406) * [Thingy:52](http://www.nordicsemi.com/eng/Products/Nordic-Thingy-52) * [Arduino Primo](http://www.arduino.org/products/boards/arduino-primo) * [IBK-BLYST-NANO breakout board](https://www.crowdsupply.com/i-syst/blyst-nano) * [BLUEIO-TAG-EVIM BLYST Nano Sensor board](https://www.crowdsupply.com/i-syst/blyst-nano) * [uBlox EVK-NINA-B1](https://www.u-blox.com/en/product/evk-nina-b1) * nRF52840 * [PCA10056](http://www.nordicsemi.com/eng/Products/nRF52840-Preview-DK) * [PCA10059](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) * [Particle Xenon](https://docs.particle.io/xenon/) * nRF9160 * [PCA10090](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF9160-DK) ## Compile and Flash Prerequisite steps for building the nrf port: git clone .git micropython cd micropython make -C mpy-cross By default, the PCA10040 (nrf52832) is used as compile target. To build and flash issue the following command inside the ports/nrf/ folder: make submodules make make flash Alternatively the target board could be defined: make BOARD=pca10040 make BOARD=pca10040 flash ## Compile without LTO enabled As a space optimization, LTO (Link Time Optimization) has been enabled on all targets in the nrf-port. The `-flto` linker flag can be toggled easily by using the argument LTO when building. The example below shows how to disable LTO for the compilation: make BOARD=pca10040 LTO=0 **Note**: There have been several issues with use of LTO in conjunction with GNU ARM Embedded Toolchain 7.2.1/4Q17. It's recommended to use a toolchain after this release, for example 7.3.1/2Q18 or 8.2.1/4Q18. The alternative would be to build the target using the LTO=0 as described above. ## Compile and Flash with Bluetooth Stack First prepare the bluetooth folder by downloading Bluetooth LE stacks and headers: ./drivers/bluetooth/download_ble_stack.sh If the Bluetooth stacks has been downloaded, compile the target with the following command: make BOARD=pca10040 SD=s132 The **make sd** will trigger a flash of the bluetooth stack before that application is flashed. Note that **make sd** will perform a full erase of the chip, which could cause 3rd party bootloaders to also be wiped. make BOARD=pca10040 SD=s132 sd Note: further tuning of features to include in bluetooth or even setting up the device to use REPL over Bluetooth can be configured in the `bluetooth_conf.h`. ## Compile with frozen modules Frozen modules are Python modules compiled to bytecode and added to the firmware image, as part of MicroPython. They can be imported as usual, using the `import` statement. The advantage is that frozen modules use a lot less RAM as the bytecode is stored in flash, not in RAM like when importing from a filesystem. Also, frozen modules are available even when no filesystem is present to import from. To use frozen modules, put them in a directory (e.g. `freeze/`) and supply `make` with the given directory. For example: make BOARD=pca10040 FROZEN_MPY_DIR=freeze ## Enable MICROPY_VFS_FAT As the `oofatfs` module is not having header guards that can exclude the implementation compile time, this port provides a flag to enable it explicitly. The MICROPY_VFS_FAT is by default set to 0 and has to be set to 1 if `oofatfs` files should be compiled. This will be in addition of setting `MICROPY_VFS` in mpconfigport.h. For example: make BOARD=pca10040 MICROPY_VFS_FAT=1 ## Target Boards and Make Flags Target Board (BOARD) | Bluetooth Stack (SD) | Bluetooth Support | Flash Util ---------------------|-------------------------|------------------------|------------------------------- microbit | s110 | Peripheral | [PyOCD](#pyocdopenocd-targets) pca10000 | s110 | Peripheral | [Segger](#segger-targets) pca10001 | s110 | Peripheral | [Segger](#segger-targets) pca10028 | s110 | Peripheral | [Segger](#segger-targets) pca10031 | s110 | Peripheral | [Segger](#segger-targets) wt51822_s4at | s110 | Peripheral | Manual, see [datasheet](https://4tronix.co.uk/picobot2/WT51822-S4AT.pdf) for pinout pca10040 | s132 | Peripheral and Central | [Segger](#segger-targets) feather52 | s132 | Peripheral and Central | Manual, SWDIO and SWCLK solder points on the bottom side of the board arduino_primo | s132 | Peripheral and Central | [PyOCD](#pyocdopenocd-targets) ibk_blyst_nano | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) idk_blyst_nano | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) blueio_tag_evim | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) evk_nina_b1 | s132 | Peripheral and Central | [Segger](#segger-targets) pca10056 | s140 | Peripheral and Central | [Segger](#segger-targets) pca10059 | s140 | Peripheral and Central | Manual, SWDIO and SWCLK solder points on the sides. particle_xenon | s140 | Peripheral and Central | [Black Magic Probe](#black-magic-probe-targets) pca10090 | None (bsdlib.a) | None (LTE/GNSS) | [Segger](#segger-targets) ## IDAP-M/IDAP-Link Targets Install the necessary tools to flash and debug using IDAP-M/IDAP-Link CMSIS-DAP Debug JTAG: [IDAPnRFProg for Linux](https://sourceforge.net/projects/idaplinkfirmware/files/Linux/IDAPnRFProg_1_7_190320.zip/download) [IDAPnRFProg for OSX](https://sourceforge.net/projects/idaplinkfirmware/files/OSX/IDAPnRFProg_1_7_190320.zip/download) [IDAPnRFProg for Windows](https://sourceforge.net/projects/idaplinkfirmware/files/Windows/IDAPnRFProg_1_7_190320.zip/download) ## Segger Targets Install the necessary tools to flash and debug using Segger: [JLink Download](https://www.segger.com/downloads/jlink#) [nrfjprog Download](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF5-Command-Line-Tools/Download#infotabs) note: On Linux it might be required to link SEGGER's `libjlinkarm.so` inside nrfjprog's folder. ## PyOCD/OpenOCD Targets Install the necessary tools to flash and debug using OpenOCD: sudo apt-get install openocd sudo pip install pyOCD ## Black Magic Probe Targets This requires no further dependencies other than `arm-none-eabi-gdb`. `make deploy` will use gdb to load and run new firmware. See [this guide](https://github.com/blacksphere/blackmagic/wiki/Useful-GDB-commands) for more tips about using the BMP with GDB. ## Bluetooth LE REPL The port also implements a BLE REPL driver. This feature is disabled by default, as it will deactivate the UART REPL when activated. As some of the nRF devices only have one UART, using the BLE REPL free's the UART instance such that it can be used as a general UART peripheral not bound to REPL. The configuration can be enabled by editing the `bluetooth_conf.h` and set `MICROPY_PY_BLE_NUS` to 1. When enabled you have different options to test it: * [NUS Console for Linux](https://github.com/tralamazza/nus_console) (recommended) * [WebBluetooth REPL](https://aykevl.nl/apps/nus/) (experimental) Other: * nRF UART application for IPhone/Android WebBluetooth mode can also be configured by editing `bluetooth_conf.h` and set `BLUETOOTH_WEBBLUETOOTH_REPL` to 1. This will alternate advertisement between Eddystone URL and regular connectable advertisement. The Eddystone URL will point the phone or PC to download [WebBluetooth REPL](https://aykevl.nl/apps/nus/) (experimental), which subsequently can be used to connect to the Bluetooth REPL from the PC or Phone browser. micropython-1.12/ports/nrf/bluetooth_conf.h000066400000000000000000000021711357706137100211420ustar00rootroot00000000000000#ifndef BLUETOOTH_CONF_H__ #define BLUETOOTH_CONF_H__ // SD specific configurations. #if (BLUETOOTH_SD == 110) #define MICROPY_PY_BLE (1) #define MICROPY_PY_BLE_NUS (0) #define BLUETOOTH_WEBBLUETOOTH_REPL (0) #define MICROPY_PY_UBLUEPY (1) #define MICROPY_PY_UBLUEPY_PERIPHERAL (1) #elif (BLUETOOTH_SD == 132) #define MICROPY_PY_BLE (1) #define MICROPY_PY_BLE_NUS (0) #define BLUETOOTH_WEBBLUETOOTH_REPL (0) #define MICROPY_PY_UBLUEPY (1) #define MICROPY_PY_UBLUEPY_PERIPHERAL (1) #define MICROPY_PY_UBLUEPY_CENTRAL (1) #elif (BLUETOOTH_SD == 140) #define MICROPY_PY_BLE (1) #define MICROPY_PY_BLE_NUS (0) #define BLUETOOTH_WEBBLUETOOTH_REPL (0) #define MICROPY_PY_UBLUEPY (1) #define MICROPY_PY_UBLUEPY_PERIPHERAL (1) #define MICROPY_PY_UBLUEPY_CENTRAL (1) #else #error "SD not supported" #endif // Default defines. #ifndef MICROPY_PY_BLE #define MICROPY_PY_BLE (0) #endif #ifndef MICROPY_PY_BLE_NUS #define MICROPY_PY_BLE_NUS (0) #endif #endif micropython-1.12/ports/nrf/boards/000077500000000000000000000000001357706137100172305ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/arduino_primo/000077500000000000000000000000001357706137100220775ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/arduino_primo/mpconfigboard.h000066400000000000000000000050261357706137100250650ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "Arduino Primo" #define MICROPY_HW_MCU_NAME "NRF52832" #define MICROPY_PY_SYS_PLATFORM "nrf52" #define MICROPY_PY_MACHINE_SOFT_PWM (1) #define MICROPY_PY_MUSIC (1) #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (1) #define MICROPY_HW_LED_PULLUP (0) #define MICROPY_HW_LED1 (20) // LED1 // UART config #define MICROPY_HW_UART1_RX (11) #define MICROPY_HW_UART1_TX (12) #define MICROPY_HW_UART1_HWFC (0) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (25) // (Arduino D13) #define MICROPY_HW_SPI0_MOSI (23) // (Arduino D11) #define MICROPY_HW_SPI0_MISO (24) // (Arduino D12) #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" // buzzer pin #define MICROPY_HW_MUSIC_PIN (8) #define HELP_TEXT_BOARD_LED "1" micropython-1.12/ports/nrf/boards/arduino_primo/mpconfigboard.mk000066400000000000000000000002571357706137100252460ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52832 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52832_512k_64k.ld FLASHER = pyocd NRF_DEFINES += -DNRF52832_XXAA micropython-1.12/ports/nrf/boards/arduino_primo/pins.csv000066400000000000000000000003401357706137100235620ustar00rootroot00000000000000P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/blueio_tag_evim/000077500000000000000000000000001357706137100223625ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h000066400000000000000000000053771357706137100253610ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 I-SYST inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "BLUEIO-TAG-EVIM" #define MICROPY_HW_MCU_NAME "NRF52832" #define MICROPY_PY_SYS_PLATFORM "BLYST Nano" #define MICROPY_PY_MACHINE_SOFT_PWM (1) #define MICROPY_PY_MUSIC (1) #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED1 (30) // LED1 #define MICROPY_HW_LED1_PULLUP (0) #define MICROPY_HW_LED2 (20) // LED2 #define MICROPY_HW_LED3 (19) // LED3 #define MICROPY_HW_LED4 (18) // LED4 // UART config #define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_TX (7) #define MICROPY_HW_UART1_CTS (12) #define MICROPY_HW_UART1_RTS (11) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (23) // #define MICROPY_HW_SPI0_MOSI (24) // #define MICROPY_HW_SPI0_MISO (25) // #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" // buzzer pin #define MICROPY_HW_MUSIC_PIN (14) #define HELP_TEXT_BOARD_LED "1,2,3,4" micropython-1.12/ports/nrf/boards/blueio_tag_evim/mpconfigboard.mk000066400000000000000000000002561357706137100255300ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52832 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52832_512k_64k.ld FLASHER = idap NRF_DEFINES += -DNRF52832_XXAA micropython-1.12/ports/nrf/boards/blueio_tag_evim/pins.csv000066400000000000000000000003401357706137100240450ustar00rootroot00000000000000P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/common.ld000066400000000000000000000046341357706137100210500ustar00rootroot00000000000000/* define output sections */ SECTIONS { /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ /* *(.glue_7t) */ /* glue thumb to arm code */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ } >FLASH_TEXT /* .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH */ /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ _ram_start = .; /* create a global symbol at ram start for garbage collector */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM AT>FLASH_TEXT /* Uninitialized data section */ .bss : { . = ALIGN(4); _sbss = .; /* define a global symbol at bss start; used by startup code */ *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end; used by startup code and GC */ } >RAM /* Remove information from the standard libraries */ /* /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } */ .ARM.attributes 0 : { *(.ARM.attributes) } } /* Define heap and stack areas */ _ram_end = ORIGIN(RAM) + LENGTH(RAM); _estack = ORIGIN(RAM) + LENGTH(RAM); micropython-1.12/ports/nrf/boards/dvk_bl652/000077500000000000000000000000001357706137100207265ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/dvk_bl652/mpconfigboard.h000066400000000000000000000047271357706137100237230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "DVK-BL652" #define MICROPY_HW_MCU_NAME "NRF52832" #define MICROPY_PY_SYS_PLATFORM "bl652" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (2) #define MICROPY_HW_LED_PULLUP (0) #define MICROPY_HW_LED1 (17) // LED1 #define MICROPY_HW_LED2 (19) // LED2 // UART config #define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_TX (6) #define MICROPY_HW_UART1_CTS (7) #define MICROPY_HW_UART1_RTS (5) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (25) #define MICROPY_HW_SPI0_MOSI (23) #define MICROPY_HW_SPI0_MISO (24) #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #define HELP_TEXT_BOARD_LED "1,2" micropython-1.12/ports/nrf/boards/dvk_bl652/mpconfigboard.mk000066400000000000000000000002761357706137100240760ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52832 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52832_512k_64k.ld NRF_DEFINES += -DNRF52832_XXAA CFLAGS += -DBLUETOOTH_LFCLK_RC micropython-1.12/ports/nrf/boards/dvk_bl652/pins.csv000066400000000000000000000003671357706137100224220ustar00rootroot00000000000000P2,P2 P3,P3 P4,P4 UART_RTS,P5 UART_TX,P6 UART_CTS,P7 UART_RX,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/evk_nina_b1/000077500000000000000000000000001357706137100214045ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/evk_nina_b1/mpconfigboard.h000066400000000000000000000055601357706137100243750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Roland van Straten * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Datasheet for board: // https://www.u-blox.com/sites/default/files/EVK-NINA-B1_UserGuide_%28UBX-15028120%29.pdf #define MICROPY_HW_BOARD_NAME "EVK_NINA_B1" #define MICROPY_HW_MCU_NAME "NRF52832" #define MICROPY_PY_SYS_PLATFORM "nrf52" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_TRICOLOR (1) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED_RED (8) // LED1 DS8 Red #define MICROPY_HW_LED_GREEN (16) // LED2 DS8 Green #define MICROPY_HW_LED_BLUE (18) // LED3 DS8 Blue // LEDs conflict with UART //#define MICROPY_HW_LED4 (7) // DS1 Green //#define MICROPY_HW_LED5 (31) // DS2 Orange //#define MICROPY_HW_LED6 (5) // DS7 Green //#define MICROPY_HW_LED7 (6) // DS8 Orange // UART config #define MICROPY_HW_UART1_RX (5) #define MICROPY_HW_UART1_TX (6) #define MICROPY_HW_UART1_CTS (7) #define MICROPY_HW_UART1_RTS (31) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (14) #define MICROPY_HW_SPI0_MOSI (13) #define MICROPY_HW_SPI0_MISO (12) #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #define HELP_TEXT_BOARD_LED "1,2,3" micropython-1.12/ports/nrf/boards/evk_nina_b1/mpconfigboard.mk000066400000000000000000000002371357706137100245510ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52832 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52832_512k_64k.ld NRF_DEFINES += -DNRF52832_XXAA micropython-1.12/ports/nrf/boards/evk_nina_b1/pins.csv000066400000000000000000000005731357706137100230770ustar00rootroot00000000000000A0,P3,ADC0_IN1 A1,P2,ADC0_IN0 A2,P4,ADC0_IN2 A3,P30,ADC0_IN6 A4,P29,ADC0_IN5 A5,P28,ADC0_IN4 LED1,P8 LED2,P16 LED3,P18 SW2,P30 UART1_RX,P5 UART1_TX,P6 UART1_CTS,P7 UART1_RTS,P8 SDA,P2 SCL,P3 NFC1,P9 NFC2,P10 D0,P5 D1,P6 D2,P7 D3,P31 D4,P18 D6,P9 D7,P10 D9,P8 D10,P11 D11,P13 D12,P12 D13,P14 P15,P15 P17,P17 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 micropython-1.12/ports/nrf/boards/feather52/000077500000000000000000000000001357706137100210155ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/feather52/mpconfigboard.h000066400000000000000000000047101357706137100240020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "Bluefruit nRF52 Feather" #define MICROPY_HW_MCU_NAME "NRF52832" #define MICROPY_PY_SYS_PLATFORM "nrf52" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (2) #define MICROPY_HW_LED_PULLUP (0) #define MICROPY_HW_LED1 (17) // LED1 #define MICROPY_HW_LED2 (19) // LED2 // UART config #define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_TX (6) #define MICROPY_HW_UART1_HWFC (0) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (12) // (Arduino D13) #define MICROPY_HW_SPI0_MOSI (13) // (Arduino D11) #define MICROPY_HW_SPI0_MISO (14) // (Arduino D12) #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #define HELP_TEXT_BOARD_LED "1,2" micropython-1.12/ports/nrf/boards/feather52/mpconfigboard.mk000066400000000000000000000002401357706137100241540ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52832 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52832_512k_64k.ld NRF_DEFINES += -DNRF52832_XXAA micropython-1.12/ports/nrf/boards/feather52/pins.csv000066400000000000000000000004451357706137100225060ustar00rootroot00000000000000P2,P2,ADC0_IN0 P3,P3,ADC0_IN1 P4,P4,ADC0_IN2 P5,P5,ADC0_IN3 UART_TX,P6 P7,P7 UART_RX,P8 NFC1,P9 NFC2,P10 P11,P11 SPI_SCK,P12 SPI_MOSI,P13 SPI_MISO,P14 P15,P15 P16,P16 LED1,P17 LED2,P19 P20,P20 I2C_SDA,P25 I2C_SCL,P26 P27,P27 P28,P28,ADC0_IN4 P29,P29,ADC0_IN5 P30,P30,ADC0_IN6 P31,P31,ADC0_IN7 micropython-1.12/ports/nrf/boards/ibk_blyst_nano/000077500000000000000000000000001357706137100222255ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h000066400000000000000000000051531357706137100252140ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 I-SYST inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "IBK-BLYST-NANO" #define MICROPY_HW_MCU_NAME "NRF52832" #define MICROPY_PY_SYS_PLATFORM "BLYST Nano" #define MICROPY_PY_MACHINE_SOFT_PWM (1) #define MICROPY_PY_MUSIC (1) #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (3) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED1 (30) // LED1 #define MICROPY_HW_LED2 (29) // LED2 #define MICROPY_HW_LED3 (28) // LED3 // UART config #define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_TX (7) #define MICROPY_HW_UART1_CTS (12) #define MICROPY_HW_UART1_RTS (11) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (23) // #define MICROPY_HW_SPI0_MOSI (24) // #define MICROPY_HW_SPI0_MISO (25) // #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #define HELP_TEXT_BOARD_LED "1,2,3" micropython-1.12/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.mk000066400000000000000000000002561357706137100253730ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52832 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52832_512k_64k.ld FLASHER = idap NRF_DEFINES += -DNRF52832_XXAA micropython-1.12/ports/nrf/boards/ibk_blyst_nano/pins.csv000066400000000000000000000003401357706137100237100ustar00rootroot00000000000000P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/idk_blyst_nano/000077500000000000000000000000001357706137100222275ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/idk_blyst_nano/mpconfigboard.h000066400000000000000000000052361357706137100252200ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 I-SYST inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "IDK-BLYST-NANO" #define MICROPY_HW_MCU_NAME "NRF52832" #define MICROPY_PY_SYS_PLATFORM "BLYST Nano" #define MICROPY_PY_MACHINE_SOFT_PWM (1) #define MICROPY_PY_MUSIC (1) #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED1 (30) // LED1 #define MICROPY_HW_LED2 (29) // LED2 #define MICROPY_HW_LED3 (28) // LED3 #define MICROPY_HW_LED4 (27) // LED4 // UART config #define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_TX (7) #define MICROPY_HW_UART1_CTS (12) #define MICROPY_HW_UART1_RTS (11) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (23) // #define MICROPY_HW_SPI0_MOSI (24) // #define MICROPY_HW_SPI0_MISO (25) // #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #define HELP_TEXT_BOARD_LED "1,2,3,4" micropython-1.12/ports/nrf/boards/idk_blyst_nano/mpconfigboard.mk000066400000000000000000000002561357706137100253750ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52832 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52832_512k_64k.ld FLASHER = idap NRF_DEFINES += -DNRF52832_XXAA micropython-1.12/ports/nrf/boards/idk_blyst_nano/pins.csv000066400000000000000000000003401357706137100237120ustar00rootroot00000000000000P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/make-pins.py000066400000000000000000000333111357706137100214670ustar00rootroot00000000000000#!/usr/bin/env python """Creates the pin file for the nRF5.""" from __future__ import print_function import argparse import sys import csv SUPPORTED_FN = { 'UART' : ['RX', 'TX', 'CTS', 'RTS'] } def parse_pin(name_str): """Parses a string and returns a pin-num.""" if len(name_str) < 1: raise ValueError("Expecting pin name to be at least 4 charcters.") if name_str[0] != 'P': raise ValueError("Expecting pin name to start with P") pin_str = name_str[1:].split('/')[0] if not pin_str.isdigit(): raise ValueError("Expecting numeric pin number.") return int(pin_str) def split_name_num(name_num): num = None for num_idx in range(len(name_num) - 1, -1, -1): if not name_num[num_idx].isdigit(): name = name_num[0:num_idx + 1] num_str = name_num[num_idx + 1:] if len(num_str) > 0: num = int(num_str) break return name, num class AlternateFunction(object): """Holds the information associated with a pins alternate function.""" def __init__(self, idx, af_str): self.idx = idx self.af_str = af_str self.func = '' self.fn_num = None self.pin_type = '' self.supported = False af_words = af_str.split('_', 1) self.func, self.fn_num = split_name_num(af_words[0]) if len(af_words) > 1: self.pin_type = af_words[1] if self.func in SUPPORTED_FN: pin_types = SUPPORTED_FN[self.func] if self.pin_type in pin_types: self.supported = True def is_supported(self): return self.supported def ptr(self): """Returns the numbered function (i.e. USART6) for this AF.""" if self.fn_num is None: return self.func return '{:s}{:d}'.format(self.func, self.fn_num) def mux_name(self): return 'AF{:d}_{:s}'.format(self.idx, self.ptr()) def print(self): """Prints the C representation of this AF.""" if self.supported: print(' AF', end='') else: print(' //', end='') fn_num = self.fn_num if fn_num is None: fn_num = 0 print('({:2d}, {:8s}, {:2d}, {:10s}, {:8s}), // {:s}'.format(self.idx, self.func, fn_num, self.pin_type, self.ptr(), self.af_str)) def qstr_list(self): return [self.mux_name()] class Pin(object): """Holds the information associated with a pin.""" def __init__(self, pin): self.pin = pin self.alt_fn = [] self.alt_fn_count = 0 self.adc_num = 0 self.adc_channel = 0 self.board_pin = False self.board_index = None def cpu_pin_name(self): return '{:s}{:d}'.format("P", self.pin) def is_board_pin(self): return self.board_pin def set_is_board_pin(self): self.board_pin = True def set_board_index(self, index): self.board_index = index def parse_adc(self, adc_str): if (adc_str[:3] != 'ADC'): return (adc,channel) = adc_str.split('_') for idx in range(3, len(adc)): self.adc_num = int(adc[idx]) self.adc_channel = int(channel[2:]) def parse_af(self, af_idx, af_strs_in): if len(af_strs_in) == 0: return # If there is a slash, then the slash separates 2 aliases for the # same alternate function. af_strs = af_strs_in.split('/') for af_str in af_strs: alt_fn = AlternateFunction(af_idx, af_str) self.alt_fn.append(alt_fn) if alt_fn.is_supported(): self.alt_fn_count += 1 def alt_fn_name(self, null_if_0=False): if null_if_0 and self.alt_fn_count == 0: return 'NULL' return 'pin_{:s}_af'.format(self.cpu_pin_name()) def adc_num_str(self): str = '' for adc_num in range(1,4): if self.adc_num & (1 << (adc_num - 1)): if len(str) > 0: str += ' | ' str += 'PIN_ADC' str += chr(ord('0') + adc_num) if len(str) == 0: str = '0' return str def print_const_table_entry(self): print(' PIN({:d}, {:s}, {:s}, {:d}),'.format( self.pin, self.alt_fn_name(null_if_0=True), self.adc_num_str(), self.adc_channel)) def print(self): if self.alt_fn_count == 0: print("// ", end='') print('const pin_af_obj_t {:s}[] = {{'.format(self.alt_fn_name())) for alt_fn in self.alt_fn: alt_fn.print() if self.alt_fn_count == 0: print("// ", end='') print('};') print('') print('const pin_obj_t pin_{:s} = PIN({:d}, {:s}, {:s}, {:d});'.format( self.cpu_pin_name(), self.pin, self.alt_fn_name(null_if_0=True), self.adc_num_str(), self.adc_channel)) print('') def print_header(self, hdr_file): hdr_file.write('extern const pin_obj_t pin_{:s};\n'. format(self.cpu_pin_name())) if self.alt_fn_count > 0: hdr_file.write('extern const pin_af_obj_t pin_{:s}_af[];\n'. format(self.cpu_pin_name())) def qstr_list(self): result = [] for alt_fn in self.alt_fn: if alt_fn.is_supported(): result += alt_fn.qstr_list() return result class NamedPin(object): def __init__(self, name, pin): self._name = name self._pin = pin def pin(self): return self._pin def name(self): return self._name class Pins(object): def __init__(self): self.cpu_pins = [] # list of NamedPin objects self.board_pins = [] # list of NamedPin objects def find_pin(self, pin_num): for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.pin == pin_num: return pin def parse_af_file(self, filename, pinname_col, af_col, af_col_end): with open(filename, 'r') as csvfile: rows = csv.reader(csvfile) for row in rows: try: pin_num = parse_pin(row[pinname_col]) except: continue pin = Pin(pin_num) for af_idx in range(af_col, len(row)): if af_idx < af_col_end: pin.parse_af(af_idx - af_col, row[af_idx]) elif af_idx == af_col_end: pin.parse_adc(row[af_idx]) self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin)) def parse_board_file(self, filename): with open(filename, 'r') as csvfile: rows = csv.reader(csvfile) for row in rows: try: pin_num = parse_pin(row[1]) except: continue pin = self.find_pin(pin_num) if pin: pin.set_is_board_pin() self.board_pins.append(NamedPin(row[0], pin)) def print_named(self, label, named_pins): print('STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label)) for named_pin in named_pins: pin = named_pin.pin() if pin.is_board_pin(): print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&machine_board_pin_obj[{:d}]) }},'.format(named_pin.name(), pin.board_index)) print('};') print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label)); def print_const_table(self): num_board_pins = 0 for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): pin.set_board_index(num_board_pins) num_board_pins += 1 print('') print('const uint8_t machine_pin_num_of_board_pins = {:d};'.format(num_board_pins)) print('') print('const pin_obj_t machine_board_pin_obj[{:d}] = {{'.format(num_board_pins)) for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): pin.print_const_table_entry() print('};'); def print(self): self.print_named('cpu', self.cpu_pins) print('') self.print_named('board', self.board_pins) def print_adc(self, adc_num): print(''); print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num)) for channel in range(16): adc_found = False for named_pin in self.cpu_pins: pin = named_pin.pin() if (pin.is_board_pin() and (pin.adc_num & (1 << (adc_num - 1))) and (pin.adc_channel == channel)): print(' &pin_{:s}, // {:d}'.format(pin.cpu_pin_name(), channel)) adc_found = True break if not adc_found: print(' NULL, // {:d}'.format(channel)) print('};') def print_header(self, hdr_filename): with open(hdr_filename, 'wt') as hdr_file: for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): pin.print_header(hdr_file) hdr_file.write('extern const pin_obj_t * const pin_adc1[];\n') hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n') hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n') def print_qstr(self, qstr_filename): with open(qstr_filename, 'wt') as qstr_file: qstr_set = set([]) for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): qstr_set |= set(pin.qstr_list()) qstr_set |= set([named_pin.name()]) for named_pin in self.board_pins: qstr_set |= set([named_pin.name()]) for qstr in sorted(qstr_set): print('Q({})'.format(qstr), file=qstr_file) def print_af_hdr(self, af_const_filename): with open(af_const_filename, 'wt') as af_const_file: af_hdr_set = set([]) mux_name_width = 0 for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): for af in pin.alt_fn: if af.is_supported(): mux_name = af.mux_name() af_hdr_set |= set([mux_name]) if len(mux_name) > mux_name_width: mux_name_width = len(mux_name) for mux_name in sorted(af_hdr_set): key = 'MP_ROM_QSTR(MP_QSTR_{}),'.format(mux_name) val = 'MP_ROM_INT(GPIO_{})'.format(mux_name) print(' { %-*s %s },' % (mux_name_width + 26, key, val), file=af_const_file) def print_af_py(self, af_py_filename): with open(af_py_filename, 'wt') as af_py_file: print('PINS_AF = (', file=af_py_file); for named_pin in self.board_pins: print(" ('%s', " % named_pin.name(), end='', file=af_py_file) for af in named_pin.pin().alt_fn: if af.is_supported(): print("(%d, '%s'), " % (af.idx, af.af_str), end='', file=af_py_file) print('),', file=af_py_file) print(')', file=af_py_file) def main(): parser = argparse.ArgumentParser( prog="make-pins.py", usage="%(prog)s [options] [command]", description="Generate board specific pin file" ) parser.add_argument( "-a", "--af", dest="af_filename", help="Specifies the alternate function file for the chip", default="nrf.csv" ) parser.add_argument( "--af-const", dest="af_const_filename", help="Specifies header file for alternate function constants.", default="build/pins_af_const.h" ) parser.add_argument( "--af-py", dest="af_py_filename", help="Specifies the filename for the python alternate function mappings.", default="build/pins_af.py" ) parser.add_argument( "-b", "--board", dest="board_filename", help="Specifies the board file", ) parser.add_argument( "-p", "--prefix", dest="prefix_filename", help="Specifies beginning portion of generated pins file", default="nrf52_prefix.c" ) parser.add_argument( "-q", "--qstr", dest="qstr_filename", help="Specifies name of generated qstr header file", default="build/pins_qstr.h" ) parser.add_argument( "-r", "--hdr", dest="hdr_filename", help="Specifies name of generated pin header file", default="build/pins.h" ) args = parser.parse_args(sys.argv[1:]) pins = Pins() print('// This file was automatically generated by make-pins.py') print('//') if args.af_filename: print('// --af {:s}'.format(args.af_filename)) pins.parse_af_file(args.af_filename, 1, 2, 2) if args.board_filename: print('// --board {:s}'.format(args.board_filename)) pins.parse_board_file(args.board_filename) if args.prefix_filename: print('// --prefix {:s}'.format(args.prefix_filename)) print('') with open(args.prefix_filename, 'r') as prefix_file: print(prefix_file.read()) pins.print_const_table() pins.print() pins.print_header(args.hdr_filename) pins.print_qstr(args.qstr_filename) pins.print_af_hdr(args.af_const_filename) pins.print_af_py(args.af_py_filename) if __name__ == "__main__": main() micropython-1.12/ports/nrf/boards/memory.ld000066400000000000000000000016431357706137100210650ustar00rootroot00000000000000 /* Flash layout: softdevice | application | filesystem */ /* RAM layout: softdevice RAM | application RAM */ _sd_size = DEFINED(_sd_size) ? _sd_size : 0; _sd_ram = DEFINED(_sd_ram) ? _sd_ram : 0; _fs_size = DEFINED(_fs_size) ? _fs_size : 64K; /* TODO: set to 0 if not using the filesystem */ _app_size = _flash_size - _sd_size - _fs_size; _app_start = _sd_size; _fs_start = _sd_size + _app_size; _fs_end = _fs_start + _fs_size; _app_ram_start = 0x20000000 + _sd_ram; _app_ram_size = _ram_size - _sd_ram; _heap_start = _ebss; _heap_end = _ram_end - _stack_size; _heap_size = _heap_end - _heap_start; ASSERT(_heap_size >= _minimum_heap_size, "not enough RAM left for heap") /* Specify the memory areas */ MEMORY { FLASH_TEXT (rx) : ORIGIN = _app_start, LENGTH = _app_size /* app */ RAM (xrw) : ORIGIN = _app_ram_start, LENGTH = _app_ram_size } micropython-1.12/ports/nrf/boards/microbit/000077500000000000000000000000001357706137100210405ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/microbit/custom_nrf51822_s110_microbit.ld000066400000000000000000000000201357706137100265660ustar00rootroot00000000000000_fs_size = 12K; micropython-1.12/ports/nrf/boards/microbit/modules/000077500000000000000000000000001357706137100225105ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/microbit/modules/AUTHORS000066400000000000000000000004141357706137100235570ustar00rootroot00000000000000Damien P. George (@dpgeorge) Nicholas H. Tollervey (@ntoll) Matthew Else (@matthewelse) Alan M. Jackson (@alanmjackson) Mark Shannon (@markshannon) Larry Hastings (@larryhastings) Mariia Koroliuk (@marichkakorolyuk) Andrew Mulholland (@gbaman) Joe Glancy (@JoeGlancy) micropython-1.12/ports/nrf/boards/microbit/modules/LICENSE000066400000000000000000000022031357706137100235120ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2013-2016 The MicroPython-on-micro:bit Developers, as listed in the accompanying AUTHORS file Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. micropython-1.12/ports/nrf/boards/microbit/modules/boardmodules.h000066400000000000000000000030631357706137100253430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_NRF_BOARD_MICROBIT_BOARD_MODULES_H #define MICROPY_INCLUDED_NRF_BOARD_MICROBIT_BOARD_MODULES_H #include "modmicrobit.h" extern const struct _mp_obj_module_t microbit_module; #define BOARD_MODULES \ { MP_ROM_QSTR(MP_QSTR_microbit), MP_ROM_PTR(µbit_module) }, \ #endif // MICROPY_INCLUDED_NRF_BOARD_MICROBIT_BOARD_MODULES_H micropython-1.12/ports/nrf/boards/microbit/modules/boardmodules.mk000066400000000000000000000007701357706137100255250ustar00rootroot00000000000000BOARD_MICROBIT_DIR = boards/microbit/modules INC += -I./$(BOARD_MICROBIT_DIR) CFLAGS += -DBOARD_SPECIFIC_MODULES SRC_BOARD_MODULES = $(addprefix $(BOARD_MICROBIT_DIR)/,\ microbitdisplay.c \ microbitimage.c \ iters.c \ microbitconstimage.c \ microbitconstimagetuples.c \ modmicrobit.c \ ) OBJ += $(addprefix $(BUILD)/, $(SRC_BOARD_MODULES:.c=.o)) micropython-1.12/ports/nrf/boards/microbit/modules/iters.c000066400000000000000000000044641357706137100240120ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015/6 Mark Shannon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "iters.h" typedef struct _repeat_iterator_t { mp_obj_base_t base; mp_obj_t iterable; mp_int_t index; } repeat_iterator_t; static mp_obj_t microbit_repeat_iter_next(mp_obj_t iter_in) { repeat_iterator_t *iter = (repeat_iterator_t *)iter_in; iter->index++; if (iter->index >= mp_obj_get_int(mp_obj_len(iter->iterable))) { iter->index = 0; } return mp_obj_subscr(iter->iterable, MP_OBJ_NEW_SMALL_INT(iter->index), MP_OBJ_SENTINEL); } const mp_obj_type_t microbit_repeat_iterator_type = { { &mp_type_type }, .name = MP_QSTR_iterator, .print = NULL, .make_new = NULL, .call = NULL, .unary_op = NULL, .binary_op = NULL, .attr = NULL, .subscr = NULL, .getiter = mp_identity_getiter, .iternext = microbit_repeat_iter_next, .buffer_p = {NULL}, MP_OBJ_NULL }; mp_obj_t microbit_repeat_iterator(mp_obj_t iterable) { repeat_iterator_t *result = m_new_obj(repeat_iterator_t); result->base.type = µbit_repeat_iterator_type; result->iterable = iterable; result->index = -1; return result; } micropython-1.12/ports/nrf/boards/microbit/modules/iters.h000066400000000000000000000001201357706137100240000ustar00rootroot00000000000000 #include "py/runtime.h" mp_obj_t microbit_repeat_iterator(mp_obj_t iterable); micropython-1.12/ports/nrf/boards/microbit/modules/microbitconstimage.c000066400000000000000000000233051357706137100265410ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "microbitimage.h" #define IMAGE_T const monochrome_5by5_t IMAGE_T microbit_const_image_heart_obj = SMALL_IMAGE( 0,1,0,1,0, 1,1,1,1,1, 1,1,1,1,1, 0,1,1,1,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_heart_small_obj = SMALL_IMAGE( 0,0,0,0,0, 0,1,0,1,0, 0,1,1,1,0, 0,0,1,0,0, 0,0,0,0,0 ); // smilies IMAGE_T microbit_const_image_happy_obj = SMALL_IMAGE( 0,0,0,0,0, 0,1,0,1,0, 0,0,0,0,0, 1,0,0,0,1, 0,1,1,1,0 ); IMAGE_T microbit_const_image_smile_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,0,0,0,1, 0,1,1,1,0 ); IMAGE_T microbit_const_image_sad_obj = SMALL_IMAGE( 0,0,0,0,0, 0,1,0,1,0, 0,0,0,0,0, 0,1,1,1,0, 1,0,0,0,1 ); IMAGE_T microbit_const_image_confused_obj = SMALL_IMAGE( 0,0,0,0,0, 0,1,0,1,0, 0,0,0,0,0, 0,1,0,1,0, 1,0,1,0,1 ); IMAGE_T microbit_const_image_angry_obj = SMALL_IMAGE( 1,0,0,0,1, 0,1,0,1,0, 0,0,0,0,0, 1,1,1,1,1, 1,0,1,0,1 ); IMAGE_T microbit_const_image_asleep_obj = SMALL_IMAGE( 0,0,0,0,0, 1,1,0,1,1, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_surprised_obj = SMALL_IMAGE( 0,1,0,1,0, 0,0,0,0,0, 0,0,1,0,0, 0,1,0,1,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_silly_obj = SMALL_IMAGE( 1,0,0,0,1, 0,0,0,0,0, 1,1,1,1,1, 0,0,1,0,1, 0,0,1,1,1 ); IMAGE_T microbit_const_image_fabulous_obj = SMALL_IMAGE( 1,1,1,1,1, 1,1,0,1,1, 0,0,0,0,0, 0,1,0,1,0, 0,1,1,1,0 ); IMAGE_T microbit_const_image_meh_obj = SMALL_IMAGE( 0,1,0,1,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,1,0,0, 0,1,0,0,0 ); // yes/no IMAGE_T microbit_const_image_yes_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,1, 0,0,0,1,0, 1,0,1,0,0, 0,1,0,0,0 ); IMAGE_T microbit_const_image_no_obj = SMALL_IMAGE( 1,0,0,0,1, 0,1,0,1,0, 0,0,1,0,0, 0,1,0,1,0, 1,0,0,0,1 ); // clock hands IMAGE_T microbit_const_image_clock12_obj = SMALL_IMAGE( 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_clock1_obj = SMALL_IMAGE( 0,0,0,1,0, 0,0,0,1,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_clock2_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,1,1, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_clock3_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,1, 0,0,0,0,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_clock4_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,1,1, 0,0,0,0,0 ); IMAGE_T microbit_const_image_clock5_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,1,0, 0,0,0,1,0 ); IMAGE_T microbit_const_image_clock6_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_clock7_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,1,0,0,0, 0,1,0,0,0 ); IMAGE_T microbit_const_image_clock8_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 1,1,0,0,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_clock9_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,0,0,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_clock10_obj = SMALL_IMAGE( 0,0,0,0,0, 1,1,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_clock11_obj = SMALL_IMAGE( 0,1,0,0,0, 0,1,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0 ); // arrows IMAGE_T microbit_const_image_arrow_n_obj = SMALL_IMAGE( 0,0,1,0,0, 0,1,1,1,0, 1,0,1,0,1, 0,0,1,0,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_arrow_ne_obj = SMALL_IMAGE( 0,0,1,1,1, 0,0,0,1,1, 0,0,1,0,1, 0,1,0,0,0, 1,0,0,0,0 ); IMAGE_T microbit_const_image_arrow_e_obj = SMALL_IMAGE( 0,0,1,0,0, 0,0,0,1,0, 1,1,1,1,1, 0,0,0,1,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_arrow_se_obj = SMALL_IMAGE( 1,0,0,0,0, 0,1,0,0,0, 0,0,1,0,1, 0,0,0,1,1, 0,0,1,1,1 ); IMAGE_T microbit_const_image_arrow_s_obj = SMALL_IMAGE( 0,0,1,0,0, 0,0,1,0,0, 1,0,1,0,1, 0,1,1,1,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_arrow_sw_obj = SMALL_IMAGE( 0,0,0,0,1, 0,0,0,1,0, 1,0,1,0,0, 1,1,0,0,0, 1,1,1,0,0 ); IMAGE_T microbit_const_image_arrow_w_obj = SMALL_IMAGE( 0,0,1,0,0, 0,1,0,0,0, 1,1,1,1,1, 0,1,0,0,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_arrow_nw_obj = SMALL_IMAGE( 1,1,1,0,0, 1,1,0,0,0, 1,0,1,0,0, 0,0,0,1,0, 0,0,0,0,1 ); // geometry IMAGE_T microbit_const_image_triangle_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,1,0,0, 0,1,0,1,0, 1,1,1,1,1, 0,0,0,0,0 ); IMAGE_T microbit_const_image_triangle_left_obj = SMALL_IMAGE( 1,0,0,0,0, 1,1,0,0,0, 1,0,1,0,0, 1,0,0,1,0, 1,1,1,1,1 ); IMAGE_T microbit_const_image_chessboard_obj = SMALL_IMAGE( 0,1,0,1,0, 1,0,1,0,1, 0,1,0,1,0, 1,0,1,0,1, 0,1,0,1,0 ); IMAGE_T microbit_const_image_diamond_obj = SMALL_IMAGE( 0,0,1,0,0, 0,1,0,1,0, 1,0,0,0,1, 0,1,0,1,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_diamond_small_obj = SMALL_IMAGE( 0,0,0,0,0, 0,0,1,0,0, 0,1,0,1,0, 0,0,1,0,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_square_obj = SMALL_IMAGE( 1,1,1,1,1, 1,0,0,0,1, 1,0,0,0,1, 1,0,0,0,1, 1,1,1,1,1 ); IMAGE_T microbit_const_image_square_small_obj = SMALL_IMAGE( 0,0,0,0,0, 0,1,1,1,0, 0,1,0,1,0, 0,1,1,1,0, 0,0,0,0,0 ); // animals IMAGE_T microbit_const_image_rabbit = SMALL_IMAGE( 1,0,1,0,0, 1,0,1,0,0, 1,1,1,1,0, 1,1,0,1,0, 1,1,1,1,0 ); IMAGE_T microbit_const_image_cow = SMALL_IMAGE( 1,0,0,0,1, 1,0,0,0,1, 1,1,1,1,1, 0,1,1,1,0, 0,0,1,0,0 ); // musical notes IMAGE_T microbit_const_image_music_crotchet_obj = SMALL_IMAGE( 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0, 1,1,1,0,0, 1,1,1,0,0 ); IMAGE_T microbit_const_image_music_quaver_obj = SMALL_IMAGE( 0,0,1,0,0, 0,0,1,1,0, 0,0,1,0,1, 1,1,1,0,0, 1,1,1,0,0 ); IMAGE_T microbit_const_image_music_quavers_obj = SMALL_IMAGE( 0,1,1,1,1, 0,1,0,0,1, 0,1,0,0,1, 1,1,0,1,1, 1,1,0,1,1 ); // other icons IMAGE_T microbit_const_image_pitchfork_obj = SMALL_IMAGE( 1,0,1,0,1, 1,0,1,0,1, 1,1,1,1,1, 0,0,1,0,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_xmas_obj = SMALL_IMAGE( 0,0,1,0,0, 0,1,1,1,0, 0,0,1,0,0, 0,1,1,1,0, 1,1,1,1,1 ); IMAGE_T microbit_const_image_pacman_obj = SMALL_IMAGE( 0,1,1,1,1, 1,1,0,1,0, 1,1,1,0,0, 1,1,1,1,0, 0,1,1,1,1 ); IMAGE_T microbit_const_image_target_obj = SMALL_IMAGE( 0,0,1,0,0, 0,1,1,1,0, 1,1,0,1,1, 0,1,1,1,0, 0,0,1,0,0 ); /* The following images were designed by Abbie Brooks. */ IMAGE_T microbit_const_image_tshirt_obj = SMALL_IMAGE( 1,1,0,1,1, 1,1,1,1,1, 0,1,1,1,0, 0,1,1,1,0, 0,1,1,1,0 ); IMAGE_T microbit_const_image_rollerskate_obj = SMALL_IMAGE( 0,0,0,1,1, 0,0,0,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,1,0,1,0 ); IMAGE_T microbit_const_image_duck_obj = SMALL_IMAGE( 0,1,1,0,0, 1,1,1,0,0, 0,1,1,1,1, 0,1,1,1,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_house_obj = SMALL_IMAGE( 0,0,1,0,0, 0,1,1,1,0, 1,1,1,1,1, 0,1,1,1,0, 0,1,0,1,0 ); IMAGE_T microbit_const_image_tortoise_obj = SMALL_IMAGE( 0,0,0,0,0, 0,1,1,1,0, 1,1,1,1,1, 0,1,0,1,0, 0,0,0,0,0 ); IMAGE_T microbit_const_image_butterfly_obj = SMALL_IMAGE( 1,1,0,1,1, 1,1,1,1,1, 0,0,1,0,0, 1,1,1,1,1, 1,1,0,1,1 ); IMAGE_T microbit_const_image_stickfigure_obj = SMALL_IMAGE( 0,0,1,0,0, 1,1,1,1,1, 0,0,1,0,0, 0,1,0,1,0, 1,0,0,0,1 ); IMAGE_T microbit_const_image_ghost_obj = SMALL_IMAGE( 1,1,1,1,1, 1,0,1,0,1, 1,1,1,1,1, 1,1,1,1,1, 1,0,1,0,1 ); IMAGE_T microbit_const_image_sword_obj = SMALL_IMAGE( 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0, 0,1,1,1,0, 0,0,1,0,0 ); IMAGE_T microbit_const_image_giraffe_obj = SMALL_IMAGE( 1,1,0,0,0, 0,1,0,0,0, 0,1,0,0,0, 0,1,1,1,0, 0,1,0,1,0 ); IMAGE_T microbit_const_image_skull_obj = SMALL_IMAGE( 0,1,1,1,0, 1,0,1,0,1, 1,1,1,1,1, 0,1,1,1,0, 0,1,1,1,0 ); IMAGE_T microbit_const_image_umbrella_obj = SMALL_IMAGE( 0,1,1,1,0, 1,1,1,1,1, 0,0,1,0,0, 1,0,1,0,0, 0,1,1,0,0 ); IMAGE_T microbit_const_image_snake_obj = SMALL_IMAGE( 1,1,0,0,0, 1,1,0,1,1, 0,1,0,1,0, 0,1,1,1,0, 0,0,0,0,0 ); micropython-1.12/ports/nrf/boards/microbit/modules/microbitconstimage.h000066400000000000000000000144221357706137100265460ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __MICROPY_INCLUDED_MICROBIT_CONSTIMAGE_H__ #define __MICROPY_INCLUDED_MICROBIT_CONSTIMAGE_H__ typedef struct _image_tuple_12 { mp_obj_base_t base; size_t len; mp_rom_obj_t items[12]; } image_tuple_12_t; typedef struct _image_tuple_8 { mp_obj_base_t base; size_t len; mp_rom_obj_t items[8]; } image_tuple_8_t; extern const image_tuple_12_t microbit_const_image_all_clocks_tuple_obj; extern const image_tuple_8_t microbit_const_image_all_arrows_tuple_obj; extern const mp_obj_type_t microbit_const_image_type; extern const struct _monochrome_5by5_t microbit_const_image_heart_obj; extern const struct _monochrome_5by5_t microbit_const_image_heart_small_obj; extern const struct _monochrome_5by5_t microbit_const_image_happy_obj; extern const struct _monochrome_5by5_t microbit_const_image_smile_obj; extern const struct _monochrome_5by5_t microbit_const_image_sad_obj; extern const struct _monochrome_5by5_t microbit_const_image_confused_obj; extern const struct _monochrome_5by5_t microbit_const_image_angry_obj; extern const struct _monochrome_5by5_t microbit_const_image_asleep_obj; extern const struct _monochrome_5by5_t microbit_const_image_surprised_obj; extern const struct _monochrome_5by5_t microbit_const_image_silly_obj; extern const struct _monochrome_5by5_t microbit_const_image_fabulous_obj; extern const struct _monochrome_5by5_t microbit_const_image_meh_obj; extern const struct _monochrome_5by5_t microbit_const_image_yes_obj; extern const struct _monochrome_5by5_t microbit_const_image_no_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock12_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock1_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock2_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock3_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock4_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock5_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock6_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock7_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock8_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock9_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock10_obj; extern const struct _monochrome_5by5_t microbit_const_image_clock11_obj; extern const struct _monochrome_5by5_t microbit_const_image_arrow_n_obj; extern const struct _monochrome_5by5_t microbit_const_image_arrow_ne_obj; extern const struct _monochrome_5by5_t microbit_const_image_arrow_e_obj; extern const struct _monochrome_5by5_t microbit_const_image_arrow_se_obj; extern const struct _monochrome_5by5_t microbit_const_image_arrow_s_obj; extern const struct _monochrome_5by5_t microbit_const_image_arrow_sw_obj; extern const struct _monochrome_5by5_t microbit_const_image_arrow_w_obj; extern const struct _monochrome_5by5_t microbit_const_image_arrow_nw_obj; extern const struct _monochrome_5by5_t microbit_const_image_triangle_obj; extern const struct _monochrome_5by5_t microbit_const_image_triangle_left_obj; extern const struct _monochrome_5by5_t microbit_const_image_chessboard_obj; extern const struct _monochrome_5by5_t microbit_const_image_diamond_obj; extern const struct _monochrome_5by5_t microbit_const_image_diamond_small_obj; extern const struct _monochrome_5by5_t microbit_const_image_square_obj; extern const struct _monochrome_5by5_t microbit_const_image_square_small_obj; extern const struct _monochrome_5by5_t microbit_const_image_rabbit; extern const struct _monochrome_5by5_t microbit_const_image_cow; extern const struct _monochrome_5by5_t microbit_const_image_music_crotchet_obj; extern const struct _monochrome_5by5_t microbit_const_image_music_quaver_obj; extern const struct _monochrome_5by5_t microbit_const_image_music_quavers_obj; extern const struct _monochrome_5by5_t microbit_const_image_pitchfork_obj; extern const struct _monochrome_5by5_t microbit_const_image_xmas_obj; extern const struct _monochrome_5by5_t microbit_const_image_pacman_obj; extern const struct _monochrome_5by5_t microbit_const_image_target_obj; extern const struct _monochrome_5by5_t microbit_const_image_tshirt_obj; extern const struct _monochrome_5by5_t microbit_const_image_rollerskate_obj; extern const struct _monochrome_5by5_t microbit_const_image_duck_obj; extern const struct _monochrome_5by5_t microbit_const_image_house_obj; extern const struct _monochrome_5by5_t microbit_const_image_tortoise_obj; extern const struct _monochrome_5by5_t microbit_const_image_butterfly_obj; extern const struct _monochrome_5by5_t microbit_const_image_stickfigure_obj; extern const struct _monochrome_5by5_t microbit_const_image_ghost_obj; extern const struct _monochrome_5by5_t microbit_const_image_sword_obj; extern const struct _monochrome_5by5_t microbit_const_image_giraffe_obj; extern const struct _monochrome_5by5_t microbit_const_image_skull_obj; extern const struct _monochrome_5by5_t microbit_const_image_umbrella_obj; extern const struct _monochrome_5by5_t microbit_const_image_snake_obj; #endif // __MICROPY_INCLUDED_MICROBIT_CONSTIMAGE_H__ micropython-1.12/ports/nrf/boards/microbit/modules/microbitconstimagetuples.c000066400000000000000000000047231357706137100300010ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2015 Mark Shannon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "microbitconstimage.h" const image_tuple_12_t microbit_const_image_all_clocks_tuple_obj = { {&mp_type_tuple}, .len = 12, .items = { (mp_obj_t)µbit_const_image_clock12_obj, (mp_obj_t)µbit_const_image_clock1_obj, (mp_obj_t)µbit_const_image_clock2_obj, (mp_obj_t)µbit_const_image_clock3_obj, (mp_obj_t)µbit_const_image_clock4_obj, (mp_obj_t)µbit_const_image_clock5_obj, (mp_obj_t)µbit_const_image_clock6_obj, (mp_obj_t)µbit_const_image_clock7_obj, (mp_obj_t)µbit_const_image_clock8_obj, (mp_obj_t)µbit_const_image_clock9_obj, (mp_obj_t)µbit_const_image_clock10_obj, (mp_obj_t)µbit_const_image_clock11_obj } }; const image_tuple_8_t microbit_const_image_all_arrows_tuple_obj = { {&mp_type_tuple}, .len = 8, .items = { (mp_obj_t)µbit_const_image_arrow_n_obj, (mp_obj_t)µbit_const_image_arrow_ne_obj, (mp_obj_t)µbit_const_image_arrow_e_obj, (mp_obj_t)µbit_const_image_arrow_se_obj, (mp_obj_t)µbit_const_image_arrow_s_obj, (mp_obj_t)µbit_const_image_arrow_sw_obj, (mp_obj_t)µbit_const_image_arrow_w_obj, (mp_obj_t)µbit_const_image_arrow_nw_obj } }; micropython-1.12/ports/nrf/boards/microbit/modules/microbitdisplay.c000066400000000000000000000520001357706137100260470ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" #include "py/runtime.h" #include "py/gc.h" #include "nrf_gpio.h" #include "microbitimage.h" #include "microbitdisplay.h" #include "iters.h" #include "ticker.h" #define min(a,b) (((a)<(b))?(a):(b)) void microbit_display_show(microbit_display_obj_t *display, microbit_image_obj_t *image) { mp_int_t w = min(imageWidth(image), 5); mp_int_t h = min(imageHeight(image), 5); mp_int_t x = 0; mp_int_t brightnesses = 0; for (; x < w; ++x) { mp_int_t y = 0; for (; y < h; ++y) { uint8_t pix = imageGetPixelValue(image, x, y); display->image_buffer[x][y] = pix; brightnesses |= (1 << pix); } for (; y < 5; ++y) { display->image_buffer[x][y] = 0; } } for (; x < 5; ++x) { for (mp_int_t y = 0; y < 5; ++y) { display->image_buffer[x][y] = 0; } } display->brightnesses = brightnesses; } #define DEFAULT_PRINT_SPEED 400 mp_obj_t microbit_display_show_func(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // Cancel any animations. MP_STATE_PORT(async_data)[0] = NULL; MP_STATE_PORT(async_data)[1] = NULL; static const mp_arg_t show_allowed_args[] = { { MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_delay, MP_ARG_INT, {.u_int = DEFAULT_PRINT_SPEED} }, { MP_QSTR_clear, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, { MP_QSTR_loop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; // Parse the args. microbit_display_obj_t *self = (microbit_display_obj_t*)pos_args[0]; mp_arg_val_t args[MP_ARRAY_SIZE(show_allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(show_allowed_args), show_allowed_args, args); mp_obj_t image = args[0].u_obj; mp_int_t delay = args[1].u_int; bool clear = args[2].u_bool; bool wait = args[3].u_bool; bool loop = args[4].u_bool; if (mp_obj_is_str(image)) { // arg is a string object size_t len; const char *str = mp_obj_str_get_data(image, &len); if (len == 0) { // There are no chars; do nothing. return mp_const_none; } else if (len == 1) { if (!clear && !loop) { // A single char; convert to an image and print that. image = microbit_image_for_char(str[0]); goto single_image_immediate; } } image = microbit_string_facade(image); } else if (mp_obj_get_type(image) == µbit_image_type) { if (!clear && !loop) { goto single_image_immediate; } image = mp_obj_new_tuple(1, &image); } // iterable: if (args[4].u_bool) { /*loop*/ image = microbit_repeat_iterator(image); } microbit_display_animate(self, image, delay, clear, wait); return mp_const_none; single_image_immediate: microbit_display_show(self, (microbit_image_obj_t *)image); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(microbit_display_show_obj, 1, microbit_display_show_func); static uint8_t async_mode; static mp_obj_t async_iterator = NULL; // Record if an error occurs in async animation. Unfortunately there is no way to report this. static volatile bool wakeup_event = false; static mp_uint_t async_delay = 1000; static mp_uint_t async_tick = 0; static bool async_clear = false; bool microbit_display_active_animation(void) { return async_mode == ASYNC_MODE_ANIMATION; } STATIC void async_stop(void) { async_iterator = NULL; async_mode = ASYNC_MODE_STOPPED; async_tick = 0; async_delay = 1000; async_clear = false; MP_STATE_PORT(async_data)[0] = NULL; MP_STATE_PORT(async_data)[1] = NULL; wakeup_event = true; } STATIC void wait_for_event(void) { while (!wakeup_event) { // allow CTRL-C to stop the animation if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { async_stop(); return; } __WFI(); } wakeup_event = false; } typedef struct { uint8_t x; uint8_t y; } DisplayPoint; #define NO_CONN 0 #define ROW_COUNT 3 #define COLUMN_COUNT 9 static const DisplayPoint display_map[COLUMN_COUNT][ROW_COUNT] = { {{0,0}, {4,2}, {2,4}}, {{2,0}, {0,2}, {4,4}}, {{4,0}, {2,2}, {0,4}}, {{4,3}, {1,0}, {0,1}}, {{3,3}, {3,0}, {1,1}}, {{2,3}, {3,4}, {2,1}}, {{1,3}, {1,4}, {3,1}}, {{0,3}, {NO_CONN,NO_CONN}, {4,1}}, {{1,2}, {NO_CONN,NO_CONN}, {3,2}} }; #define MIN_COLUMN_PIN 4 #define COLUMN_PINS_MASK 0x1ff0 #define MIN_ROW_PIN 13 #define MAX_ROW_PIN 15 #define ROW_PINS_MASK 0xe000 static inline void displaySetPinsForRow(microbit_display_obj_t * p_display, uint8_t brightness) { if (brightness == 0) { nrf_gpio_port_out_clear(NRF_GPIO, COLUMN_PINS_MASK & ~p_display->pins_for_brightness[brightness]); } else { nrf_gpio_pin_set(p_display->pins_for_brightness[brightness]); } } /* This is the primary PWM driver/display driver. It will operate on one row * (9 pins) per invocation. It will turn on LEDs with maximum brightness, * then let the "callback" callback turn off the LEDs as appropriate for the * required brightness level. * * For each row * Turn off all the LEDs in the previous row * Set the column bits high (off) * Set the row strobe low (off) * Turn on all the LEDs in the current row that have maximum brightness * Set the row strobe high (on) * Set some/all column bits low (on) * Register the PWM callback * For each callback start with brightness 0 * If brightness 0 * Turn off the LEDs specified at this level * Else * Turn on the LEDs specified at this level * If brightness max * Disable the PWM callback * Else * Re-queue the PWM callback after the appropriate delay */ static void displayAdvanceRow(microbit_display_obj_t * p_display) { /* Clear all of the column bits */ nrf_gpio_port_out_set(NRF_GPIO, COLUMN_PINS_MASK); /* Clear the strobe bit for this row */ nrf_gpio_pin_clear(p_display->strobe_row + MIN_ROW_PIN); /* Move to the next row. Before this, "this row" refers to the row * manipulated by the previous invocation of this function. After this, * "this row" refers to the row manipulated by the current invocation of * this function. */ p_display->strobe_row++; // Reset the row counts and bit mask when we have hit the max. if (p_display->strobe_row == ROW_COUNT) { p_display->strobe_row = 0; } // Set pin for this row. // Prepare row for rendering. for (int i = 0; i <= MAX_BRIGHTNESS; i++) { p_display->pins_for_brightness[i] = 0; } for (int i = 0; i < COLUMN_COUNT; i++) { int x = display_map[i][p_display->strobe_row].x; int y = display_map[i][p_display->strobe_row].y; int brightness = microbit_display_obj.image_buffer[x][y]; p_display->pins_for_brightness[brightness] |= (1<<(i+MIN_COLUMN_PIN)); (void)brightness; } /* Enable the strobe bit for this row */ nrf_gpio_pin_set(p_display->strobe_row + MIN_ROW_PIN); /* Enable the column bits for all pins that need to be on. */ nrf_gpio_port_out_clear(NRF_GPIO, p_display->pins_for_brightness[MAX_BRIGHTNESS]); } static const uint16_t render_timings[] = // The scale is (approximately) exponential, // each step is approx x1.9 greater than the previous. { 0, // Bright, Ticks Duration, Relative power 2, // 1, 2, 32us, inf 2, // 2, 4, 64us, 200% 4, // 3, 8, 128us, 200% 7, // 4, 15, 240us, 187% 13, // 5, 28, 448us, 187% 25, // 6, 53, 848us, 189% 49, // 7, 102, 1632us, 192% 97, // 8, 199, 3184us, 195% // Always on 9, 375, 6000us, 188% }; #define DISPLAY_TICKER_SLOT 1 /* This is the PWM callback. It is registered by the animation callback and * will unregister itself when all of the brightness steps are complete. */ static int32_t callback(void) { microbit_display_obj_t *display = µbit_display_obj; mp_uint_t brightness = display->previous_brightness; displaySetPinsForRow(display, brightness); brightness += 1; if (brightness == MAX_BRIGHTNESS) { clear_ticker_callback(DISPLAY_TICKER_SLOT); return -1; } display->previous_brightness = brightness; // Return interval (in 16us ticks) until next callback return render_timings[brightness]; } static void draw_object(mp_obj_t obj) { microbit_display_obj_t *display = (microbit_display_obj_t*)MP_STATE_PORT(async_data)[0]; if (obj == MP_OBJ_STOP_ITERATION) { if (async_clear) { microbit_display_show(µbit_display_obj, BLANK_IMAGE); async_clear = false; } else { async_stop(); } } else if (mp_obj_get_type(obj) == µbit_image_type) { microbit_display_show(display, (microbit_image_obj_t *)obj); } else if (mp_obj_is_str(obj)) { size_t len; const char *str = mp_obj_str_get_data(obj, &len); if (len == 1) { microbit_display_show(display, microbit_image_for_char(str[0])); } else { async_stop(); } } else { MP_STATE_VM(mp_pending_exception) = mp_obj_new_exception_msg(&mp_type_TypeError, "not an image."); async_stop(); } } static void microbit_display_update(void) { async_tick += MILLISECONDS_PER_MACRO_TICK; if (async_tick < async_delay) { return; } async_tick = 0; switch (async_mode) { case ASYNC_MODE_ANIMATION: { if (MP_STATE_PORT(async_data)[0] == NULL || MP_STATE_PORT(async_data)[1] == NULL) { async_stop(); break; } /* WARNING: We are executing in an interrupt handler. * If an exception is raised here then we must hand it to the VM. */ mp_obj_t obj; nlr_buf_t nlr; gc_lock(); if (nlr_push(&nlr) == 0) { obj = mp_iternext_allow_raise(async_iterator); nlr_pop(); gc_unlock(); } else { gc_unlock(); if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { // An exception other than StopIteration, so set it for the VM to raise later // If memory error, write an appropriate message. if (mp_obj_get_type(nlr.ret_val) == &mp_type_MemoryError) { mp_printf(&mp_plat_print, "Allocation in interrupt handler"); } MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(nlr.ret_val); } obj = MP_OBJ_STOP_ITERATION; } draw_object(obj); break; } case ASYNC_MODE_CLEAR: microbit_display_show(µbit_display_obj, BLANK_IMAGE); async_stop(); break; } } #define GREYSCALE_MASK ((1<active = true; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(microbit_display_on_obj, microbit_display_on_func); mp_obj_t microbit_display_off_func(mp_obj_t obj) { microbit_display_obj_t *self = (microbit_display_obj_t*)obj; /* Disable the display loop. This will pause any animations in progress. * It will not prevent a user from attempting to modify the state, but * modifications will not appear to have any effect until the display loop * is re-enabled. */ self->active = false; /* Disable the row strobes, allowing the columns to be used freely for * GPIO. */ nrf_gpio_port_out_clear(0, ROW_PINS_MASK); /* Free pins for other uses */ /* microbit_obj_pin_free(µbit_p3_obj); microbit_obj_pin_free(µbit_p4_obj); microbit_obj_pin_free(µbit_p6_obj); microbit_obj_pin_free(µbit_p7_obj); microbit_obj_pin_free(µbit_p9_obj); microbit_obj_pin_free(µbit_p10_obj); */ return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(microbit_display_off_obj, microbit_display_off_func); mp_obj_t microbit_display_is_on_func(mp_obj_t obj) { microbit_display_obj_t *self = (microbit_display_obj_t*)obj; if (self->active) { return mp_const_true; } else { return mp_const_false; } } MP_DEFINE_CONST_FUN_OBJ_1(microbit_display_is_on_obj, microbit_display_is_on_func); void microbit_display_clear(void) { // Reset repeat state, cancel animation and clear screen. wakeup_event = false; async_mode = ASYNC_MODE_CLEAR; async_tick = async_delay - MILLISECONDS_PER_MACRO_TICK; wait_for_event(); } mp_obj_t microbit_display_clear_func(mp_obj_t self_in) { microbit_display_clear(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(microbit_display_clear_obj, microbit_display_clear_func); void microbit_display_set_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y, mp_int_t bright) { if (x < 0 || y < 0 || x > 4 || y > 4) { mp_raise_ValueError("index out of bounds."); } if (bright < 0 || bright > MAX_BRIGHTNESS) { mp_raise_ValueError("brightness out of bounds."); } display->image_buffer[x][y] = bright; display->brightnesses |= (1 << bright); } STATIC mp_obj_t microbit_display_set_pixel_func(mp_uint_t n_args, const mp_obj_t *args) { (void)n_args; microbit_display_obj_t *self = (microbit_display_obj_t*)args[0]; microbit_display_set_pixel(self, mp_obj_get_int(args[1]), mp_obj_get_int(args[2]), mp_obj_get_int(args[3])); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_display_set_pixel_obj, 4, 4, microbit_display_set_pixel_func); mp_int_t microbit_display_get_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y) { if (x < 0 || y < 0 || x > 4 || y > 4) { mp_raise_ValueError("index out of bounds."); } return display->image_buffer[x][y]; } STATIC mp_obj_t microbit_display_get_pixel_func(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) { microbit_display_obj_t *self = (microbit_display_obj_t*)self_in; return MP_OBJ_NEW_SMALL_INT(microbit_display_get_pixel(self, mp_obj_get_int(x_in), mp_obj_get_int(y_in))); } MP_DEFINE_CONST_FUN_OBJ_3(microbit_display_get_pixel_obj, microbit_display_get_pixel_func); STATIC const mp_rom_map_elem_t microbit_display_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_get_pixel), MP_ROM_PTR(µbit_display_get_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(µbit_display_set_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(µbit_display_show_obj) }, { MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(µbit_display_scroll_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(µbit_display_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(µbit_display_on_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(µbit_display_off_obj) }, { MP_ROM_QSTR(MP_QSTR_is_on), MP_ROM_PTR(µbit_display_is_on_obj) }, }; STATIC MP_DEFINE_CONST_DICT(microbit_display_locals_dict, microbit_display_locals_dict_table); const mp_obj_type_t microbit_display_type = { { &mp_type_type }, .name = MP_QSTR_MicroBitDisplay, .print = NULL, .make_new = NULL, .call = NULL, .unary_op = NULL, .binary_op = NULL, .attr = NULL, .subscr = NULL, .getiter = NULL, .iternext = NULL, .buffer_p = {NULL}, .locals_dict = (mp_obj_dict_t*)µbit_display_locals_dict, }; microbit_display_obj_t microbit_display_obj = { {µbit_display_type}, {{ 0, }}, .previous_brightness = 0, .active = 1, .strobe_row = 0, .brightnesses = 0, .pins_for_brightness = { 0 }, }; void microbit_display_init(void) { // Set pins as output. for (int i = MIN_COLUMN_PIN; i <= MAX_ROW_PIN; i++) { nrf_gpio_cfg_output(i); } } micropython-1.12/ports/nrf/boards/microbit/modules/microbitdisplay.h000066400000000000000000000026121357706137100260600ustar00rootroot00000000000000 #ifndef __MICROPY_INCLUDED_MICROBIT_DISPLAY_H__ #define __MICROPY_INCLUDED_MICROBIT_DISPLAY_H__ #include "py/runtime.h" #include "microbitimage.h" typedef struct _microbit_display_obj_t { mp_obj_base_t base; uint8_t image_buffer[5][5]; uint8_t previous_brightness; bool active; /* Current row for strobing */ uint8_t strobe_row; /* boolean histogram of brightness in buffer */ uint16_t brightnesses; uint16_t pins_for_brightness[MAX_BRIGHTNESS+1]; } microbit_display_obj_t; #define ASYNC_MODE_STOPPED 0 #define ASYNC_MODE_ANIMATION 1 #define ASYNC_MODE_CLEAR 2 extern microbit_display_obj_t microbit_display_obj; extern const mp_obj_type_t microbit_image_type; void microbit_display_show(microbit_display_obj_t *display, microbit_image_obj_t *image); void microbit_display_animate(microbit_display_obj_t *display, mp_obj_t iterable, mp_int_t delay, bool clear, bool wait); void microbit_display_scroll(microbit_display_obj_t *display, const char* str, bool wait); mp_int_t microbit_display_get_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y); void microbit_display_set_pixel(microbit_display_obj_t *display, mp_int_t x, mp_int_t y, mp_int_t val); void microbit_display_clear(void); void microbit_display_init(void); void microbit_display_tick(void); bool microbit_display_active_animation(void); #endif // __MICROPY_INCLUDED_MICROBIT_DISPLAY_H__ micropython-1.12/ports/nrf/boards/microbit/modules/microbitfont.h000066400000000000000000000114101357706137100253550ustar00rootroot00000000000000/* The MIT License (MIT) Copyright (c) 2016 British Broadcasting Corporation. This software is provided by Lancaster University by arrangement with the BBC. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * A MicroBitFont is 5x5. * Each Row is represented by a byte in the array. * * Row Format: * ================================================================ * | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | * ================================================================ * | N/A | N/A | N/A | Col 1 | Col 2 | Col 3 | Col 4 | Col 5 | * | 0x80 | 0x40 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 | * * Example: { 0x08, 0x08, 0x08, 0x0, 0x08 } * * The above will produce an exclaimation mark on the second column in form the left. * * We could compress further, but the complexity of decode would likely outweigh the gains. */ #ifndef MICROPY_INCLUDED_NRF_BOARD_MICROBIT_MICROBITFONT_H #define MICROPY_INCLUDED_NRF_BOARD_MICROBIT_MICROBITFONT_H const unsigned char font_pendolino3_5x5_pad3msb[475] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0x8, 0xa, 0x4a, 0x40, 0x0, 0x0, 0xa, 0x5f, 0xea, 0x5f, 0xea, 0xe, 0xd9, 0x2e, 0xd3, 0x6e, 0x19, 0x32, 0x44, 0x89, 0x33, 0xc, 0x92, 0x4c, 0x92, 0x4d, 0x8, 0x8, 0x0, 0x0, 0x0, 0x4, 0x88, 0x8, 0x8, 0x4, 0x8, 0x4, 0x84, 0x84, 0x88, 0x0, 0xa, 0x44, 0x8a, 0x40, 0x0, 0x4, 0x8e, 0xc4, 0x80, 0x0, 0x0, 0x0, 0x4, 0x88, 0x0, 0x0, 0xe, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1, 0x22, 0x44, 0x88, 0x10, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x4, 0x8c, 0x84, 0x84, 0x8e, 0x1c, 0x82, 0x4c, 0x90, 0x1e, 0x1e, 0xc2, 0x44, 0x92, 0x4c, 0x6, 0xca, 0x52, 0x5f, 0xe2, 0x1f, 0xf0, 0x1e, 0xc1, 0x3e, 0x2, 0x44, 0x8e, 0xd1, 0x2e, 0x1f, 0xe2, 0x44, 0x88, 0x10, 0xe, 0xd1, 0x2e, 0xd1, 0x2e, 0xe, 0xd1, 0x2e, 0xc4, 0x88, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x4, 0x80, 0x4, 0x88, 0x2, 0x44, 0x88, 0x4, 0x82, 0x0, 0xe, 0xc0, 0xe, 0xc0, 0x8, 0x4, 0x82, 0x44, 0x88, 0xe, 0xd1, 0x26, 0xc0, 0x4, 0xe, 0xd1, 0x35, 0xb3, 0x6c, 0xc, 0x92, 0x5e, 0xd2, 0x52, 0x1c, 0x92, 0x5c, 0x92, 0x5c, 0xe, 0xd0, 0x10, 0x10, 0xe, 0x1c, 0x92, 0x52, 0x52, 0x5c, 0x1e, 0xd0, 0x1c, 0x90, 0x1e, 0x1e, 0xd0, 0x1c, 0x90, 0x10, 0xe, 0xd0, 0x13, 0x71, 0x2e, 0x12, 0x52, 0x5e, 0xd2, 0x52, 0x1c, 0x88, 0x8, 0x8, 0x1c, 0x1f, 0xe2, 0x42, 0x52, 0x4c, 0x12, 0x54, 0x98, 0x14, 0x92, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x11, 0x3b, 0x75, 0xb1, 0x31, 0x11, 0x39, 0x35, 0xb3, 0x71, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x1c, 0x92, 0x5c, 0x90, 0x10, 0xc, 0x92, 0x52, 0x4c, 0x86, 0x1c, 0x92, 0x5c, 0x92, 0x51, 0xe, 0xd0, 0xc, 0x82, 0x5c, 0x1f, 0xe4, 0x84, 0x84, 0x84, 0x12, 0x52, 0x52, 0x52, 0x4c, 0x11, 0x31, 0x31, 0x2a, 0x44, 0x11, 0x31, 0x35, 0xbb, 0x71, 0x12, 0x52, 0x4c, 0x92, 0x52, 0x11, 0x2a, 0x44, 0x84, 0x84, 0x1e, 0xc4, 0x88, 0x10, 0x1e, 0xe, 0xc8, 0x8, 0x8, 0xe, 0x10, 0x8, 0x4, 0x82, 0x41, 0xe, 0xc2, 0x42, 0x42, 0x4e, 0x4, 0x8a, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x8, 0x4, 0x80, 0x0, 0x0, 0x0, 0xe, 0xd2, 0x52, 0x4f, 0x10, 0x10, 0x1c, 0x92, 0x5c, 0x0, 0xe, 0xd0, 0x10, 0xe, 0x2, 0x42, 0x4e, 0xd2, 0x4e, 0xc, 0x92, 0x5c, 0x90, 0xe, 0x6, 0xc8, 0x1c, 0x88, 0x8, 0xe, 0xd2, 0x4e, 0xc2, 0x4c, 0x10, 0x10, 0x1c, 0x92, 0x52, 0x8, 0x0, 0x8, 0x8, 0x8, 0x2, 0x40, 0x2, 0x42, 0x4c, 0x10, 0x14, 0x98, 0x14, 0x92, 0x8, 0x8, 0x8, 0x8, 0x6, 0x0, 0x1b, 0x75, 0xb1, 0x31, 0x0, 0x1c, 0x92, 0x52, 0x52, 0x0, 0xc, 0x92, 0x52, 0x4c, 0x0, 0x1c, 0x92, 0x5c, 0x90, 0x0, 0xe, 0xd2, 0x4e, 0xc2, 0x0, 0xe, 0xd0, 0x10, 0x10, 0x0, 0x6, 0xc8, 0x4, 0x98, 0x8, 0x8, 0xe, 0xc8, 0x7, 0x0, 0x12, 0x52, 0x52, 0x4f, 0x0, 0x11, 0x31, 0x2a, 0x44, 0x0, 0x11, 0x31, 0x35, 0xbb, 0x0, 0x12, 0x4c, 0x8c, 0x92, 0x0, 0x11, 0x2a, 0x44, 0x98, 0x0, 0x1e, 0xc4, 0x88, 0x1e, 0x6, 0xc4, 0x8c, 0x84, 0x86, 0x8, 0x8, 0x8, 0x8, 0x8, 0x18, 0x8, 0xc, 0x88, 0x18, 0x0, 0x0, 0xc, 0x83, 0x60 }; #endif // MICROPY_INCLUDED_NRF_BOARD_MICROBIT_MICROBITFONT_H micropython-1.12/ports/nrf/boards/microbit/modules/microbitimage.c000066400000000000000000001074251357706137100255000ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien George, Mark Shannon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "microbitimage.h" #include "microbitconstimage.h" #include "py/runtime0.h" #include "microbitfont.h" #define min(a,b) (((a)<(b))?(a):(b)) #define max(a,b) (((a)>(b))?(a):(b)) const monochrome_5by5_t microbit_blank_image = { { µbit_image_type }, 1, 0, 0, 0, { 0, 0, 0 } }; STATIC void microbit_image_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; mp_printf(print, "Image("); if (kind == PRINT_STR) mp_printf(print, "\n "); mp_printf(print, "'"); for (int y = 0; y < imageHeight(self); ++y) { for (int x = 0; x < imageWidth(self); ++x) { mp_printf(print, "%c", "0123456789"[imageGetPixelValue(self, x, y)]); } mp_printf(print, ":"); if (kind == PRINT_STR && y < imageHeight(self)-1) mp_printf(print, "'\n '"); } mp_printf(print, "'"); if (kind == PRINT_STR) mp_printf(print, "\n"); mp_printf(print, ")"); } uint8_t monochromeGetPixelValue(monochrome_5by5_t * p_mono, mp_int_t x, mp_int_t y) { unsigned int index = y*5+x; if (index == 24) return p_mono->pixel44; return (p_mono->bits24[index>>3] >> (index&7))&1; } uint8_t greyscaleGetPixelValue(greyscale_t * p_greyscale, mp_int_t x, mp_int_t y) { unsigned int index = y*p_greyscale->width+x; unsigned int shift = ((index<<2)&4); return (p_greyscale->byte_data[index>>1] >> shift)&15; } void greyscaleSetPixelValue(greyscale_t * p_greyscale, mp_int_t x, mp_int_t y, mp_int_t val) { unsigned int index = y*p_greyscale->width+x; unsigned int shift = ((index<<2)&4); uint8_t mask = 240 >> shift; p_greyscale->byte_data[index>>1] = (p_greyscale->byte_data[index>>1] & mask) | (val << shift); } void greyscaleFill(greyscale_t * p_greyscale, mp_int_t val) { mp_int_t byte = (val<<4) | val; for (int i = 0; i < ((p_greyscale->width*p_greyscale->height+1)>>1); i++) { p_greyscale->byte_data[i] = byte; } } void greyscaleClear(greyscale_t * p_greyscale) { memset(&p_greyscale->byte_data, 0, (p_greyscale->width*p_greyscale->height+1)>>1); } uint8_t imageGetPixelValue(microbit_image_obj_t * p_image, mp_int_t x, mp_int_t y) { if (p_image->base.five) return monochromeGetPixelValue(&p_image->monochrome_5by5, x, y)*MAX_BRIGHTNESS; else return greyscaleGetPixelValue(&p_image->greyscale, x, y); } mp_int_t imageWidth(microbit_image_obj_t * p_image) { if (p_image->base.five) return 5; else return p_image->greyscale.width; } mp_int_t imageHeight(microbit_image_obj_t * p_image) { if (p_image->base.five) return 5; else return p_image->greyscale.height; } STATIC greyscale_t *greyscale_new(mp_int_t w, mp_int_t h) { greyscale_t *result = m_new_obj_var(greyscale_t, uint8_t, (w*h+1)>>1); result->base.type = µbit_image_type; result->five = 0; result->width = w; result->height = h; return result; } greyscale_t * imageCopy(microbit_image_obj_t * p_image) { mp_int_t w = imageWidth(p_image); mp_int_t h = imageHeight(p_image); greyscale_t *result = greyscale_new(w, h); for (mp_int_t y = 0; y < h; y++) { for (mp_int_t x = 0; x < w; ++x) { greyscaleSetPixelValue(result, x,y, imageGetPixelValue(p_image, x,y)); } } return result; } greyscale_t * imageInvert(microbit_image_obj_t * p_image) { mp_int_t w = imageWidth(p_image); mp_int_t h = imageHeight(p_image); greyscale_t *result = greyscale_new(w, h); for (mp_int_t y = 0; y < h; y++) { for (mp_int_t x = 0; x < w; ++x) { greyscaleSetPixelValue(result, x,y, MAX_BRIGHTNESS - imageGetPixelValue(p_image, x,y)); } } return result; } STATIC microbit_image_obj_t *image_from_parsed_str(const char *s, mp_int_t len) { mp_int_t w = 0; mp_int_t h = 0; mp_int_t line_len = 0; greyscale_t *result; /*First pass -- Establish metadata */ for (int i = 0; i < len; i++) { char c = s[i]; if (c == '\n' || c == ':') { w = max(line_len, w); line_len = 0; ++h; } else if (c == ' ') { ++line_len; } else if ('c' >= '0' && c <= '9') { ++line_len; } else { mp_raise_ValueError("Unexpected character in Image definition."); } } if (line_len) { // Omitted trailing terminator ++h; w = max(line_len, w); } result = greyscale_new(w, h); mp_int_t x = 0; mp_int_t y = 0; /* Second pass -- Fill in data */ for (int i = 0; i < len; i++) { char c = s[i]; if (c == '\n' || c == ':') { while (x < w) { greyscaleSetPixelValue(result, x, y, 0); x++; } ++y; x = 0; } else if (c == ' ') { /* Treat spaces as 0 */ greyscaleSetPixelValue(result, x, y, 0); ++x; } else if ('c' >= '0' && c <= '9') { greyscaleSetPixelValue(result, x, y, c - '0'); ++x; } } if (y < h) { while (x < w) { greyscaleSetPixelValue(result, x, y, 0); x++; } } return (microbit_image_obj_t *)result; } STATIC mp_obj_t microbit_image_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 3, false); switch (n_args) { case 0: { greyscale_t *image = greyscale_new(5, 5); greyscaleClear(image); return image; } case 1: { if (mp_obj_is_str(args[0])) { // arg is a string object size_t len; const char *str = mp_obj_str_get_data(args[0], &len); // make image from string if (len == 1) { /* For a single charater, return the font glyph */ return microbit_image_for_char(str[0]); } else { /* Otherwise parse the image description string */ return image_from_parsed_str(str, len); } } else { mp_raise_msg(&mp_type_TypeError, "Image(s) takes a string."); } } case 2: case 3: { mp_int_t w = mp_obj_get_int(args[0]); mp_int_t h = mp_obj_get_int(args[1]); greyscale_t *image = greyscale_new(w, h); if (n_args == 2) { greyscaleClear(image); } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); if (w < 0 || h < 0 || (size_t)(w * h) != bufinfo.len) { mp_raise_ValueError("image data is incorrect size"); } mp_int_t i = 0; for (mp_int_t y = 0; y < h; y++) { for (mp_int_t x = 0; x < w; ++x) { uint8_t val = min(((const uint8_t*)bufinfo.buf)[i], MAX_BRIGHTNESS); greyscaleSetPixelValue(image, x, y, val); ++i; } } } return image; } default: { mp_raise_msg(&mp_type_TypeError, "Image() takes 0 to 3 arguments"); } } } static void clear_rect(greyscale_t *img, mp_int_t x0, mp_int_t y0,mp_int_t x1, mp_int_t y1) { for (int i = x0; i < x1; ++i) { for (int j = y0; j < y1; ++j) { greyscaleSetPixelValue(img, i, j, 0); } } } STATIC void image_blit(microbit_image_obj_t *src, greyscale_t *dest, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h, mp_int_t xdest, mp_int_t ydest) { if (w < 0) w = 0; if (h < 0) h = 0; mp_int_t intersect_x0 = max(max(0, x), -xdest); mp_int_t intersect_y0 = max(max(0, y), -ydest); mp_int_t intersect_x1 = min(min(dest->width+x-xdest, imageWidth(src)), x+w); mp_int_t intersect_y1 = min(min(dest->height+y-ydest, imageHeight(src)), y+h); mp_int_t xstart, xend, ystart, yend, xdel, ydel; mp_int_t clear_x0 = max(0, xdest); mp_int_t clear_y0 = max(0, ydest); mp_int_t clear_x1 = min(dest->width, xdest+w); mp_int_t clear_y1 = min(dest->height, ydest+h); if (intersect_x0 >= intersect_x1 || intersect_y0 >= intersect_y1) { // Nothing to copy clear_rect(dest, clear_x0, clear_y0, clear_x1, clear_y1); return; } if (x > xdest) { xstart = intersect_x0; xend = intersect_x1; xdel = 1; } else { xstart = intersect_x1-1; xend = intersect_x0-1; xdel = -1; } if (y > ydest) { ystart = intersect_y0; yend = intersect_y1; ydel = 1; } else { ystart = intersect_y1-1; yend = intersect_y0-1; ydel = -1; } for (int i = xstart; i != xend; i += xdel) { for (int j = ystart; j != yend; j += ydel) { int val = imageGetPixelValue(src, i, j); greyscaleSetPixelValue(dest, i+xdest-x, j+ydest-y, val); } } // Adjust intersection rectange to dest intersect_x0 += xdest-x; intersect_y0 += ydest-y; intersect_x1 += xdest-x; intersect_y1 += ydest-y; // Clear four rectangles in the cleared area surrounding the copied area. clear_rect(dest, clear_x0, clear_y0, intersect_x0, intersect_y1); clear_rect(dest, clear_x0, intersect_y1, intersect_x1, clear_y1); clear_rect(dest, intersect_x1, intersect_y0, clear_x1, clear_y1); clear_rect(dest, intersect_x0, clear_y0, clear_x1, intersect_y0); } greyscale_t *image_shift(microbit_image_obj_t *self, mp_int_t x, mp_int_t y) { greyscale_t *result = greyscale_new(imageWidth(self), imageWidth(self)); image_blit(self, result, x, y, imageWidth(self), imageWidth(self), 0, 0); return result; } STATIC microbit_image_obj_t *image_crop(microbit_image_obj_t *img, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h) { if (w < 0) w = 0; if (h < 0) h = 0; greyscale_t *result = greyscale_new(w, h); image_blit(img, result, x, y, w, h, 0, 0); return (microbit_image_obj_t *)result; } mp_obj_t microbit_image_width(mp_obj_t self_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; return MP_OBJ_NEW_SMALL_INT(imageWidth(self)); } MP_DEFINE_CONST_FUN_OBJ_1(microbit_image_width_obj, microbit_image_width); mp_obj_t microbit_image_height(mp_obj_t self_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; return MP_OBJ_NEW_SMALL_INT(imageHeight(self)); } MP_DEFINE_CONST_FUN_OBJ_1(microbit_image_height_obj, microbit_image_height); mp_obj_t microbit_image_get_pixel(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; mp_int_t x = mp_obj_get_int(x_in); mp_int_t y = mp_obj_get_int(y_in); if (x < 0 || y < 0) { mp_raise_ValueError("index cannot be negative"); } if (x < imageWidth(self) && y < imageHeight(self)) { return MP_OBJ_NEW_SMALL_INT(imageGetPixelValue(self, x, y)); } mp_raise_ValueError("index too large"); } MP_DEFINE_CONST_FUN_OBJ_3(microbit_image_get_pixel_obj, microbit_image_get_pixel); /* Raise an exception if not mutable */ static void check_mutability(microbit_image_obj_t *self) { if (self->base.five) { mp_raise_msg(&mp_type_TypeError, "image cannot be modified (try copying first)"); } } mp_obj_t microbit_image_set_pixel(mp_uint_t n_args, const mp_obj_t *args) { (void)n_args; microbit_image_obj_t *self = (microbit_image_obj_t*)args[0]; check_mutability(self); mp_int_t x = mp_obj_get_int(args[1]); mp_int_t y = mp_obj_get_int(args[2]); if (x < 0 || y < 0) { mp_raise_ValueError("index cannot be negative"); } mp_int_t bright = mp_obj_get_int(args[3]); if (bright < 0 || bright > MAX_BRIGHTNESS) mp_raise_ValueError("brightness out of bounds."); if (x < imageWidth(self) && y < imageHeight(self)) { greyscaleSetPixelValue(&(self->greyscale), x, y, bright); return mp_const_none; } mp_raise_ValueError("index too large"); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_set_pixel_obj, 4, 4, microbit_image_set_pixel); mp_obj_t microbit_image_fill(mp_obj_t self_in, mp_obj_t n_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; check_mutability(self); mp_int_t n = mp_obj_get_int(n_in); if (n < 0 || n > MAX_BRIGHTNESS) { mp_raise_ValueError("brightness out of bounds."); } greyscaleFill(&self->greyscale, n); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_fill_obj, microbit_image_fill); mp_obj_t microbit_image_blit(mp_uint_t n_args, const mp_obj_t *args) { microbit_image_obj_t *self = (microbit_image_obj_t*)args[0]; check_mutability(self); mp_obj_t src = args[1]; if (mp_obj_get_type(src) != µbit_image_type) { mp_raise_msg(&mp_type_TypeError, "expecting an image"); } if (n_args == 7) { mp_raise_msg(&mp_type_TypeError, "must specify both offsets"); } mp_int_t x = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[3]); mp_int_t w = mp_obj_get_int(args[4]); mp_int_t h = mp_obj_get_int(args[5]); if (w < 0 || h < 0) { mp_raise_ValueError("size cannot be negative"); } mp_int_t xdest; mp_int_t ydest; if (n_args == 6) { xdest = 0; ydest = 0; } else { xdest = mp_obj_get_int(args[6]); ydest = mp_obj_get_int(args[7]); } image_blit((microbit_image_obj_t *)src, &(self->greyscale), x, y, w, h, xdest, ydest); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_blit_obj, 6, 8, microbit_image_blit); mp_obj_t microbit_image_crop(mp_uint_t n_args, const mp_obj_t *args) { (void)n_args; microbit_image_obj_t *self = (microbit_image_obj_t*)args[0]; mp_int_t x0 = mp_obj_get_int(args[1]); mp_int_t y0 = mp_obj_get_int(args[2]); mp_int_t x1 = mp_obj_get_int(args[3]); mp_int_t y1 = mp_obj_get_int(args[4]); return image_crop(self, x0, y0, x1, y1); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_image_crop_obj, 5, 5, microbit_image_crop); mp_obj_t microbit_image_shift_left(mp_obj_t self_in, mp_obj_t n_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; mp_int_t n = mp_obj_get_int(n_in); return image_shift(self, n, 0); } MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_left_obj, microbit_image_shift_left); mp_obj_t microbit_image_shift_right(mp_obj_t self_in, mp_obj_t n_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; mp_int_t n = mp_obj_get_int(n_in); return image_shift(self, -n, 0); } MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_right_obj, microbit_image_shift_right); mp_obj_t microbit_image_shift_up(mp_obj_t self_in, mp_obj_t n_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; mp_int_t n = mp_obj_get_int(n_in); return image_shift(self, 0, n); } MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_up_obj, microbit_image_shift_up); mp_obj_t microbit_image_shift_down(mp_obj_t self_in, mp_obj_t n_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; mp_int_t n = mp_obj_get_int(n_in); return image_shift(self, 0, -n); } MP_DEFINE_CONST_FUN_OBJ_2(microbit_image_shift_down_obj, microbit_image_shift_down); mp_obj_t microbit_image_copy(mp_obj_t self_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; return imageCopy(self); } MP_DEFINE_CONST_FUN_OBJ_1(microbit_image_copy_obj, microbit_image_copy); mp_obj_t microbit_image_invert(mp_obj_t self_in) { microbit_image_obj_t *self = (microbit_image_obj_t*)self_in; return imageInvert(self); } MP_DEFINE_CONST_FUN_OBJ_1(microbit_image_invert_obj, microbit_image_invert); STATIC const mp_rom_map_elem_t microbit_image_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(µbit_image_width_obj) }, { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(µbit_image_height_obj) }, { MP_ROM_QSTR(MP_QSTR_get_pixel), MP_ROM_PTR(µbit_image_get_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(µbit_image_set_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_shift_left), MP_ROM_PTR(µbit_image_shift_left_obj) }, { MP_ROM_QSTR(MP_QSTR_shift_right), MP_ROM_PTR(µbit_image_shift_right_obj) }, { MP_ROM_QSTR(MP_QSTR_shift_up), MP_ROM_PTR(µbit_image_shift_up_obj) }, { MP_ROM_QSTR(MP_QSTR_shift_down), MP_ROM_PTR(µbit_image_shift_down_obj) }, { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(µbit_image_copy_obj) }, { MP_ROM_QSTR(MP_QSTR_crop), MP_ROM_PTR(µbit_image_crop_obj) }, { MP_ROM_QSTR(MP_QSTR_invert), MP_ROM_PTR(µbit_image_invert_obj) }, { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(µbit_image_fill_obj) }, { MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(µbit_image_blit_obj) }, { MP_ROM_QSTR(MP_QSTR_HEART), MP_ROM_PTR(µbit_const_image_heart_obj) }, { MP_ROM_QSTR(MP_QSTR_HEART_SMALL), MP_ROM_PTR(µbit_const_image_heart_small_obj) }, { MP_ROM_QSTR(MP_QSTR_HAPPY), MP_ROM_PTR(µbit_const_image_happy_obj) }, { MP_ROM_QSTR(MP_QSTR_SMILE), MP_ROM_PTR(µbit_const_image_smile_obj) }, { MP_ROM_QSTR(MP_QSTR_SAD), MP_ROM_PTR(µbit_const_image_sad_obj) }, { MP_ROM_QSTR(MP_QSTR_CONFUSED), MP_ROM_PTR(µbit_const_image_confused_obj) }, { MP_ROM_QSTR(MP_QSTR_ANGRY), MP_ROM_PTR(µbit_const_image_angry_obj) }, { MP_ROM_QSTR(MP_QSTR_ASLEEP), MP_ROM_PTR(µbit_const_image_asleep_obj) }, { MP_ROM_QSTR(MP_QSTR_SURPRISED), MP_ROM_PTR(µbit_const_image_surprised_obj) }, { MP_ROM_QSTR(MP_QSTR_SILLY), MP_ROM_PTR(µbit_const_image_silly_obj) }, { MP_ROM_QSTR(MP_QSTR_FABULOUS), MP_ROM_PTR(µbit_const_image_fabulous_obj) }, { MP_ROM_QSTR(MP_QSTR_MEH), MP_ROM_PTR(µbit_const_image_meh_obj) }, { MP_ROM_QSTR(MP_QSTR_YES), MP_ROM_PTR(µbit_const_image_yes_obj) }, { MP_ROM_QSTR(MP_QSTR_NO), MP_ROM_PTR(µbit_const_image_no_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK12), MP_ROM_PTR(µbit_const_image_clock12_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK1), MP_ROM_PTR(µbit_const_image_clock1_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK2), MP_ROM_PTR(µbit_const_image_clock2_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK3), MP_ROM_PTR(µbit_const_image_clock3_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK4), MP_ROM_PTR(µbit_const_image_clock4_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK5), MP_ROM_PTR(µbit_const_image_clock5_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK6), MP_ROM_PTR(µbit_const_image_clock6_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK7), MP_ROM_PTR(µbit_const_image_clock7_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK8), MP_ROM_PTR(µbit_const_image_clock8_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK9), MP_ROM_PTR(µbit_const_image_clock9_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK10), MP_ROM_PTR(µbit_const_image_clock10_obj) }, { MP_ROM_QSTR(MP_QSTR_CLOCK11), MP_ROM_PTR(µbit_const_image_clock11_obj) }, { MP_ROM_QSTR(MP_QSTR_ARROW_N), MP_ROM_PTR(µbit_const_image_arrow_n_obj) }, { MP_ROM_QSTR(MP_QSTR_ARROW_NE), MP_ROM_PTR(µbit_const_image_arrow_ne_obj) }, { MP_ROM_QSTR(MP_QSTR_ARROW_E), MP_ROM_PTR(µbit_const_image_arrow_e_obj) }, { MP_ROM_QSTR(MP_QSTR_ARROW_SE), MP_ROM_PTR(µbit_const_image_arrow_se_obj) }, { MP_ROM_QSTR(MP_QSTR_ARROW_S), MP_ROM_PTR(µbit_const_image_arrow_s_obj) }, { MP_ROM_QSTR(MP_QSTR_ARROW_SW), MP_ROM_PTR(µbit_const_image_arrow_sw_obj) }, { MP_ROM_QSTR(MP_QSTR_ARROW_W), MP_ROM_PTR(µbit_const_image_arrow_w_obj) }, { MP_ROM_QSTR(MP_QSTR_ARROW_NW), MP_ROM_PTR(µbit_const_image_arrow_nw_obj) }, { MP_ROM_QSTR(MP_QSTR_TRIANGLE), MP_ROM_PTR(µbit_const_image_triangle_obj) }, { MP_ROM_QSTR(MP_QSTR_TRIANGLE_LEFT), MP_ROM_PTR(µbit_const_image_triangle_left_obj) }, { MP_ROM_QSTR(MP_QSTR_CHESSBOARD), MP_ROM_PTR(µbit_const_image_chessboard_obj) }, { MP_ROM_QSTR(MP_QSTR_DIAMOND), MP_ROM_PTR(µbit_const_image_diamond_obj) }, { MP_ROM_QSTR(MP_QSTR_DIAMOND_SMALL), MP_ROM_PTR(µbit_const_image_diamond_small_obj) }, { MP_ROM_QSTR(MP_QSTR_SQUARE), MP_ROM_PTR(µbit_const_image_square_obj) }, { MP_ROM_QSTR(MP_QSTR_SQUARE_SMALL), MP_ROM_PTR(µbit_const_image_square_small_obj) }, { MP_ROM_QSTR(MP_QSTR_RABBIT), MP_ROM_PTR(µbit_const_image_rabbit) }, { MP_ROM_QSTR(MP_QSTR_COW), MP_ROM_PTR(µbit_const_image_cow) }, { MP_ROM_QSTR(MP_QSTR_MUSIC_CROTCHET), MP_ROM_PTR(µbit_const_image_music_crotchet_obj) }, { MP_ROM_QSTR(MP_QSTR_MUSIC_QUAVER), MP_ROM_PTR(µbit_const_image_music_quaver_obj) }, { MP_ROM_QSTR(MP_QSTR_MUSIC_QUAVERS), MP_ROM_PTR(µbit_const_image_music_quavers_obj) }, { MP_ROM_QSTR(MP_QSTR_PITCHFORK), MP_ROM_PTR(µbit_const_image_pitchfork_obj) }, { MP_ROM_QSTR(MP_QSTR_XMAS), MP_ROM_PTR(µbit_const_image_xmas_obj) }, { MP_ROM_QSTR(MP_QSTR_PACMAN), MP_ROM_PTR(µbit_const_image_pacman_obj) }, { MP_ROM_QSTR(MP_QSTR_TARGET), MP_ROM_PTR(µbit_const_image_target_obj) }, { MP_ROM_QSTR(MP_QSTR_ALL_CLOCKS), MP_ROM_PTR(µbit_const_image_all_clocks_tuple_obj) }, { MP_ROM_QSTR(MP_QSTR_ALL_ARROWS), MP_ROM_PTR(µbit_const_image_all_arrows_tuple_obj) }, { MP_ROM_QSTR(MP_QSTR_TSHIRT), MP_ROM_PTR(µbit_const_image_tshirt_obj) }, { MP_ROM_QSTR(MP_QSTR_ROLLERSKATE), MP_ROM_PTR(µbit_const_image_rollerskate_obj) }, { MP_ROM_QSTR(MP_QSTR_DUCK), MP_ROM_PTR(µbit_const_image_duck_obj) }, { MP_ROM_QSTR(MP_QSTR_HOUSE), MP_ROM_PTR(µbit_const_image_house_obj) }, { MP_ROM_QSTR(MP_QSTR_TORTOISE), MP_ROM_PTR(µbit_const_image_tortoise_obj) }, { MP_ROM_QSTR(MP_QSTR_BUTTERFLY), MP_ROM_PTR(µbit_const_image_butterfly_obj) }, { MP_ROM_QSTR(MP_QSTR_STICKFIGURE), MP_ROM_PTR(µbit_const_image_stickfigure_obj) }, { MP_ROM_QSTR(MP_QSTR_GHOST), MP_ROM_PTR(µbit_const_image_ghost_obj) }, { MP_ROM_QSTR(MP_QSTR_SWORD), MP_ROM_PTR(µbit_const_image_sword_obj) }, { MP_ROM_QSTR(MP_QSTR_GIRAFFE), MP_ROM_PTR(µbit_const_image_giraffe_obj) }, { MP_ROM_QSTR(MP_QSTR_SKULL), MP_ROM_PTR(µbit_const_image_skull_obj) }, { MP_ROM_QSTR(MP_QSTR_UMBRELLA), MP_ROM_PTR(µbit_const_image_umbrella_obj) }, { MP_ROM_QSTR(MP_QSTR_SNAKE), MP_ROM_PTR(µbit_const_image_snake_obj) }, }; STATIC MP_DEFINE_CONST_DICT(microbit_image_locals_dict, microbit_image_locals_dict_table); #define THE_FONT font_pendolino3_5x5_pad3msb #define ASCII_START 32 #define ASCII_END 126 STATIC const unsigned char *get_font_data_from_char(char c) { if (c < ASCII_START || c > ASCII_END) { c = '?'; } int offset = (c-ASCII_START) * 5; return THE_FONT + offset; } STATIC mp_int_t get_pixel_from_font_data(const unsigned char *data, int x, int y) { /* The following logic belongs in MicroBitFont */ return ((data[y]>>(4-x))&1); } void microbit_image_set_from_char(greyscale_t *img, char c) { const unsigned char *data = get_font_data_from_char(c); for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { greyscaleSetPixelValue(img, x, y, get_pixel_from_font_data(data, x, y)*MAX_BRIGHTNESS); } } } microbit_image_obj_t *microbit_image_for_char(char c) { greyscale_t *result = greyscale_new(5,5); microbit_image_set_from_char(result, c); return (microbit_image_obj_t *)result; } #if MICROPY_PY_BUILTINS_FLOAT microbit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_float_t fval) { #else microbit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_int_t fval) { #endif if (fval < 0) mp_raise_ValueError("Brightness multiplier must not be negative."); greyscale_t *result = greyscale_new(imageWidth(lhs), imageHeight(lhs)); for (int x = 0; x < imageWidth(lhs); ++x) { for (int y = 0; y < imageWidth(lhs); ++y) { #if MICROPY_PY_BUILTINS_FLOAT int val = min((int)imageGetPixelValue(lhs, x,y)*fval+0.5, MAX_BRIGHTNESS); #else int val = min((int)imageGetPixelValue(lhs, x,y)*fval, MAX_BRIGHTNESS); #endif greyscaleSetPixelValue(result, x, y, val); } } return (microbit_image_obj_t *)result; } microbit_image_obj_t *microbit_image_sum(microbit_image_obj_t *lhs, microbit_image_obj_t *rhs, bool add) { mp_int_t h = imageHeight(lhs); mp_int_t w = imageWidth(lhs); if (imageHeight(rhs) != h || imageWidth(lhs) != w) { // TODO: verify that image width in test above should really test (lhs != w) mp_raise_ValueError("Images must be the same size."); } greyscale_t *result = greyscale_new(w, h); for (int x = 0; x < w; ++x) { for (int y = 0; y < h; ++y) { int val; int lval = imageGetPixelValue(lhs, x,y); int rval = imageGetPixelValue(rhs, x,y); if (add) val = min(lval + rval, MAX_BRIGHTNESS); else val = max(0, lval - rval); greyscaleSetPixelValue(result, x, y, val); } } return (microbit_image_obj_t *)result; } STATIC mp_obj_t image_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { if (mp_obj_get_type(lhs_in) != µbit_image_type) { return MP_OBJ_NULL; // op not supported } microbit_image_obj_t *lhs = (microbit_image_obj_t *)lhs_in; switch(op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_SUBTRACT: break; case MP_BINARY_OP_MULTIPLY: #if MICROPY_PY_BUILTINS_FLOAT return microbit_image_dim(lhs, mp_obj_get_float(rhs_in)); #else return microbit_image_dim(lhs, mp_obj_get_int(rhs_in) * 10); #endif case MP_BINARY_OP_TRUE_DIVIDE: #if MICROPY_PY_BUILTINS_FLOAT return microbit_image_dim(lhs, 1.0/mp_obj_get_float(rhs_in)); #else break; case MP_BINARY_OP_FLOOR_DIVIDE: return microbit_image_dim(lhs, (100/mp_obj_get_int(rhs_in) + 5) / 10); #endif default: return MP_OBJ_NULL; // op not supported } if (mp_obj_get_type(rhs_in) != µbit_image_type) { return MP_OBJ_NULL; // op not supported } return microbit_image_sum(lhs, (microbit_image_obj_t *)rhs_in, op == MP_BINARY_OP_ADD); } const mp_obj_type_t microbit_image_type = { { &mp_type_type }, .name = MP_QSTR_MicroBitImage, .print = microbit_image_print, .make_new = microbit_image_make_new, .call = NULL, .unary_op = NULL, .binary_op = image_binary_op, .attr = NULL, .subscr = NULL, .getiter = NULL, .iternext = NULL, .buffer_p = {NULL}, .locals_dict = (mp_obj_dict_t*)µbit_image_locals_dict, }; typedef struct _scrolling_string_t { mp_obj_base_t base; char const *str; mp_uint_t len; mp_obj_t ref; bool monospace; bool repeat; } scrolling_string_t; typedef struct _scrolling_string_iterator_t { mp_obj_base_t base; mp_obj_t ref; greyscale_t *img; char const *next_char; char const *start; char const *end; uint8_t offset; uint8_t offset_limit; bool monospace; bool repeat; char right; } scrolling_string_iterator_t; extern const mp_obj_type_t microbit_scrolling_string_type; extern const mp_obj_type_t microbit_scrolling_string_iterator_type; mp_obj_t scrolling_string_image_iterable(const char* str, mp_uint_t len, mp_obj_t ref, bool monospace, bool repeat) { scrolling_string_t *result = m_new_obj(scrolling_string_t); result->base.type = µbit_scrolling_string_type; result->str = str; result->len = len; result->ref = ref; result->monospace = monospace; result->repeat = repeat; return result; } STATIC int font_column_non_blank(const unsigned char *font_data, unsigned int col) { for (int y = 0; y < 5; ++y) { if (get_pixel_from_font_data(font_data, col, y)) { return 1; } } return 0; } /* Not strictly the rightmost non-blank column, but the rightmost in columns 2,3 or 4. */ STATIC unsigned int rightmost_non_blank_column(const unsigned char *font_data) { if (font_column_non_blank(font_data, 4)) { return 4; } if (font_column_non_blank(font_data, 3)) { return 3; } return 2; } static void restart(scrolling_string_iterator_t *iter) { iter->next_char = iter->start; iter->offset = 0; if (iter->start < iter->end) { iter->right = *iter->next_char; if (iter->monospace) { iter->offset_limit = 5; } else { iter->offset_limit = rightmost_non_blank_column(get_font_data_from_char(iter->right)) + 1; } } else { iter->right = ' '; iter->offset_limit = 5; } } STATIC mp_obj_t get_microbit_scrolling_string_iter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { (void)iter_buf; scrolling_string_t *str = (scrolling_string_t *)o_in; scrolling_string_iterator_t *result = m_new_obj(scrolling_string_iterator_t); result->base.type = µbit_scrolling_string_iterator_type; result->img = greyscale_new(5,5); result->start = str->str; result->ref = str->ref; result->monospace = str->monospace; result->end = result->start + str->len; result->repeat = str->repeat; restart(result); return result; } STATIC mp_obj_t microbit_scrolling_string_iter_next(mp_obj_t o_in) { scrolling_string_iterator_t *iter = (scrolling_string_iterator_t *)o_in; if (iter->next_char == iter->end && iter->offset == 5) { if (iter->repeat) { restart(iter); greyscaleClear(iter->img); } else { return MP_OBJ_STOP_ITERATION; } } for (int x = 0; x < 4; x++) { for (int y = 0; y < 5; y++) { greyscaleSetPixelValue(iter->img, x, y, greyscaleGetPixelValue(iter->img, x+1, y)); } } for (int y = 0; y < 5; y++) { greyscaleSetPixelValue(iter->img, 4, y, 0); } const unsigned char *font_data; if (iter->offset < iter->offset_limit) { font_data = get_font_data_from_char(iter->right); for (int y = 0; y < 5; ++y) { int pix = get_pixel_from_font_data(font_data, iter->offset, y)*MAX_BRIGHTNESS; greyscaleSetPixelValue(iter->img, 4, y, pix); } } else if (iter->offset == iter->offset_limit) { ++iter->next_char; if (iter->next_char == iter->end) { iter->right = ' '; iter->offset_limit = 5; iter->offset = 0; } else { iter->right = *iter->next_char; font_data = get_font_data_from_char(iter->right); if (iter->monospace) { iter->offset = -1; iter->offset_limit = 5; } else { iter->offset = -font_column_non_blank(font_data, 0); iter->offset_limit = rightmost_non_blank_column(font_data)+1; } } } ++iter->offset; return iter->img; } const mp_obj_type_t microbit_scrolling_string_type = { { &mp_type_type }, .name = MP_QSTR_ScrollingString, .print = NULL, .make_new = NULL, .call = NULL, .unary_op = NULL, .binary_op = NULL, .attr = NULL, .subscr = NULL, .getiter = get_microbit_scrolling_string_iter, .iternext = NULL, .buffer_p = {NULL}, .locals_dict = NULL, }; const mp_obj_type_t microbit_scrolling_string_iterator_type = { { &mp_type_type }, .name = MP_QSTR_iterator, .print = NULL, .make_new = NULL, .call = NULL, .unary_op = NULL, .binary_op = NULL, .attr = NULL, .subscr = NULL, .getiter = mp_identity_getiter, .iternext = microbit_scrolling_string_iter_next, .buffer_p = {NULL}, .locals_dict = NULL, }; /** Facade types to present a string as a sequence of images. * These are necessary to avoid allocation during iteration, * which may happen in interrupt handlers. */ typedef struct _string_image_facade_t { mp_obj_base_t base; mp_obj_t string; greyscale_t *image; } string_image_facade_t; static mp_obj_t string_image_facade_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_SENTINEL) { // Fill in image string_image_facade_t *self = (string_image_facade_t *)self_in; size_t len; const char *text = mp_obj_str_get_data(self->string, &len); mp_uint_t index = mp_get_index(self->base.type, len, index_in, false); microbit_image_set_from_char(self->image, text[index]); return self->image; } else { return MP_OBJ_NULL; // op not supported } } static mp_obj_t facade_unary_op(mp_unary_op_t op, mp_obj_t self_in) { string_image_facade_t *self = (string_image_facade_t *)self_in; switch (op) { case MP_UNARY_OP_LEN: return mp_obj_len(self->string); default: return MP_OBJ_NULL; // op not supported } } static mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf); const mp_obj_type_t string_image_facade_type = { { &mp_type_type }, .name = MP_QSTR_Facade, .print = NULL, .make_new = NULL, .call = NULL, .unary_op = facade_unary_op, .binary_op = NULL, .attr = NULL, .subscr = string_image_facade_subscr, .getiter = microbit_facade_iterator, .iternext = NULL, .buffer_p = {NULL}, NULL }; typedef struct _facade_iterator_t { mp_obj_base_t base; mp_obj_t string; mp_uint_t index; greyscale_t *image; } facade_iterator_t; mp_obj_t microbit_string_facade(mp_obj_t string) { string_image_facade_t *result = m_new_obj(string_image_facade_t); result->base.type = &string_image_facade_type; result->string = string; result->image = greyscale_new(5,5); return result; } static mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) { facade_iterator_t *iter = (facade_iterator_t *)iter_in; size_t len; const char *text = mp_obj_str_get_data(iter->string, &len); if (iter->index >= len) { return MP_OBJ_STOP_ITERATION; } microbit_image_set_from_char(iter->image, text[iter->index]); iter->index++; return iter->image; } const mp_obj_type_t microbit_facade_iterator_type = { { &mp_type_type }, .name = MP_QSTR_iterator, .print = NULL, .make_new = NULL, .call = NULL, .unary_op = NULL, .binary_op = NULL, .attr = NULL, .subscr = NULL, .getiter = mp_identity_getiter, .iternext = microbit_facade_iter_next, .buffer_p = {NULL}, NULL }; mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf) { (void)iter_buf; facade_iterator_t *result = m_new_obj(facade_iterator_t); string_image_facade_t *iterable = (string_image_facade_t *)iterable_in; result->base.type = µbit_facade_iterator_type; result->string = iterable->string; result->image = iterable->image; result->index = 0; return result; } micropython-1.12/ports/nrf/boards/microbit/modules/microbitimage.h000066400000000000000000000074031357706137100255000ustar00rootroot00000000000000#ifndef __MICROPY_INCLUDED_MICROBIT_IMAGE_H__ #define __MICROPY_INCLUDED_MICROBIT_IMAGE_H__ #include "py/runtime.h" #define MAX_BRIGHTNESS 9 /** Monochrome images are immutable, which means that * we only need one bit per pixel which saves quite a lot * of memory */ /* we reserve a couple of bits, so we won't need to modify the * layout if we need to add more functionality or subtypes. */ #define TYPE_AND_FLAGS \ mp_obj_base_t base; \ uint8_t five:1; \ uint8_t reserved1:1; \ uint8_t reserved2:1 typedef struct _image_base_t { TYPE_AND_FLAGS; } image_base_t; typedef struct _monochrome_5by5_t { TYPE_AND_FLAGS; uint8_t pixel44: 1; uint8_t bits24[3]; } monochrome_5by5_t; /* This is an internal method it is up to the caller to validate the inputs */ uint8_t monochromeGetPixelValue(monochrome_5by5_t * p_mono, mp_int_t x, mp_int_t y); typedef struct _greyscale_t { TYPE_AND_FLAGS; uint8_t height; uint8_t width; uint8_t byte_data[]; /* Static initializer for this will have to be C, not C++ */ } greyscale_t; #if 1 void clear(greyscale_t * p_greyscale); /* Thiese are internal methods and it is up to the caller to validate the inputs */ uint8_t greyscaleGetPixelValue(greyscale_t * p_greyscale, mp_int_t x, mp_int_t y); void greyscaleSetPixelValue(greyscale_t * p_greyscale, mp_int_t x, mp_int_t y, mp_int_t val); void greyscaleFill(greyscale_t * p_greyscale, mp_int_t val); #endif typedef union _microbit_image_obj_t { image_base_t base; monochrome_5by5_t monochrome_5by5; greyscale_t greyscale; } microbit_image_obj_t; #if 1 mp_int_t imageHeight(microbit_image_obj_t * p_image_obj); mp_int_t imageWidth(microbit_image_obj_t * p_image_obj); greyscale_t * imageCopy(microbit_image_obj_t * p_image_obj); greyscale_t * imageInvert(microbit_image_obj_t * p_image_obj); /* This is an internal method it is up to the caller to validate the inputs */ uint8_t imageGetPixelValue(microbit_image_obj_t * p_image_obj, mp_int_t x, mp_int_t y); #endif /** Return a facade object that presents the string as a sequence of images */ mp_obj_t microbit_string_facade(mp_obj_t string); void microbit_image_set_from_char(greyscale_t *img, char c); microbit_image_obj_t *microbit_image_for_char(char c); mp_obj_t microbit_image_slice(microbit_image_obj_t *img, mp_int_t start, mp_int_t width, mp_int_t stride); /* ref exists so that we can pull a string out of an object and not have it GC'ed while oterating over it */ mp_obj_t scrolling_string_image_iterable(const char* str, mp_uint_t len, mp_obj_t ref, bool monospace, bool repeat); #define SMALL_IMAGE(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p44) \ { \ { µbit_image_type }, \ 1, 0, 0, (p44), \ { \ (p0)|((p1)<<1)|((p2)<<2)|((p3)<<3)|((p4)<<4)|((p5)<<5)|((p6)<<6)|((p7)<<7), \ (p8)|((p9)<<1)|((p10)<<2)|((p11)<<3)|((p12)<<4)|((p13)<<5)|((p14)<<6)|((p15)<<7), \ (p16)|((p17)<<1)|((p18)<<2)|((p19)<<3)|((p20)<<4)|((p21)<<5)|((p22)<<6)|((p23)<<7) \ } \ } extern const monochrome_5by5_t microbit_blank_image; extern const monochrome_5by5_t microbit_const_image_heart_obj; extern const mp_obj_type_t microbit_image_type; #define BLANK_IMAGE (microbit_image_obj_t *)(µbit_blank_image) #define HEART_IMAGE (microbit_image_obj_t *)(µbit_const_image_heart_obj) #define HAPPY_IMAGE (microbit_image_obj_t *)(µbit_const_image_happy_obj) #if MICROPY_PY_BUILTINS_FLOAT microbit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_float_t fval); #else microbit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_int_t val); #endif microbit_image_obj_t *microbit_image_sum(microbit_image_obj_t *lhs, microbit_image_obj_t *rhs, bool add); #endif // __MICROPY_INCLUDED_MICROBIT_IMAGE_H__ micropython-1.12/ports/nrf/boards/microbit/modules/modmicrobit.c000066400000000000000000000136751357706137100252000ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/mphal.h" #include "modmicrobit.h" #include "microbitdisplay.h" #include "microbitimage.h" #include "softpwm.h" #include "ticker.h" #include "nrf_temp.h" extern uint32_t ticks; STATIC mp_obj_t microbit_reset_(void) { NVIC_SystemReset(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(microbit_reset_obj, microbit_reset_); STATIC mp_obj_t microbit_sleep(mp_obj_t ms_in) { mp_int_t ms = 0; if (mp_obj_is_integer(ms_in)) { ms = mp_obj_get_int(ms_in); #if MICROPY_PY_BUILTINS_FLOAT } else { ms = (mp_int_t)mp_obj_get_float(ms_in); #endif } if (ms > 0) { mp_hal_delay_ms(ms); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(microbit_sleep_obj, microbit_sleep); STATIC mp_obj_t microbit_running_time(void) { return MP_OBJ_NEW_SMALL_INT(ticks); } MP_DEFINE_CONST_FUN_OBJ_0(microbit_running_time_obj, microbit_running_time); static const monochrome_5by5_t panic = SMALL_IMAGE( 1,1,0,1,1, 1,1,0,1,1, 0,0,0,0,0, 0,1,1,1,0, 1,0,0,0,1 ); STATIC mp_obj_t microbit_panic(mp_uint_t n_args, const mp_obj_t *args) { while(true) { microbit_display_show(µbit_display_obj, (microbit_image_obj_t*)&panic); mp_hal_delay_ms(1000); char num[4]; int code; if (n_args) { code = mp_obj_get_int(args[0]); } else { code = 0; } num[2] = code%10 + '0'; code /= 10; num[1] = code%10 + '0'; code /= 10; num[0] = code%10 + '0'; for (int i = 0; i < 3; i++) { microbit_display_show(µbit_display_obj, microbit_image_for_char(num[i])); mp_hal_delay_ms(1000); } } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_panic_obj, 0, 1, microbit_panic); STATIC mp_obj_t microbit_temperature(void) { int temp = nrf_temp_read(); #if MICROPY_PY_BUILTINS_FLOAT return mp_obj_new_float(temp / 4); #else return mp_obj_new_int(temp / 4); #endif } MP_DEFINE_CONST_FUN_OBJ_0(microbit_temperature_obj, microbit_temperature); void board_modules_init0(void) { ticker_register_low_pri_callback(microbit_display_tick); } STATIC const mp_rom_map_elem_t microbit_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Image), MP_ROM_PTR(µbit_image_type) }, { MP_ROM_QSTR(MP_QSTR_display), MP_ROM_PTR(µbit_display_obj) }, /* { MP_OBJ_NEW_QSTR(MP_QSTR_button_a), (mp_obj_t)µbit_button_a_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_button_b), (mp_obj_t)µbit_button_b_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_accelerometer), (mp_obj_t)µbit_accelerometer_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_compass), (mp_obj_t)µbit_compass_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_i2c), (mp_obj_t)µbit_i2c_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_uart), (mp_obj_t)µbit_uart_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_spi), (mp_obj_t)µbit_spi_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)µbit_reset_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)µbit_sleep_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_running_time), (mp_obj_t)µbit_running_time_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_panic), (mp_obj_t)µbit_panic_obj }, */ { MP_OBJ_NEW_QSTR(MP_QSTR_temperature), (mp_obj_t)µbit_temperature_obj }, /* { MP_OBJ_NEW_QSTR(MP_QSTR_pin0), (mp_obj_t)µbit_p0_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin1), (mp_obj_t)µbit_p1_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin2), (mp_obj_t)µbit_p2_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin3), (mp_obj_t)µbit_p3_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin4), (mp_obj_t)µbit_p4_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin5), (mp_obj_t)µbit_p5_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin6), (mp_obj_t)µbit_p6_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin7), (mp_obj_t)µbit_p7_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin8), (mp_obj_t)µbit_p8_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin9), (mp_obj_t)µbit_p9_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin10), (mp_obj_t)µbit_p10_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin11), (mp_obj_t)µbit_p11_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin12), (mp_obj_t)µbit_p12_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin13), (mp_obj_t)µbit_p13_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin14), (mp_obj_t)µbit_p14_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin15), (mp_obj_t)µbit_p15_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin16), (mp_obj_t)µbit_p16_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin19), (mp_obj_t)µbit_p19_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pin20), (mp_obj_t)µbit_p20_obj }, */ }; STATIC MP_DEFINE_CONST_DICT(microbit_module_globals, microbit_module_globals_table); const mp_obj_module_t microbit_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)µbit_module_globals, }; micropython-1.12/ports/nrf/boards/microbit/modules/modmicrobit.h000066400000000000000000000023531357706137100251740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ void board_modules_init0(void); micropython-1.12/ports/nrf/boards/microbit/mpconfigboard.h000066400000000000000000000042211357706137100240220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "micro:bit" #define MICROPY_HW_MCU_NAME "NRF51822" #define MICROPY_PY_SYS_PLATFORM "nrf51" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MUSIC (1) #define MICROPY_PY_MACHINE_SOFT_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (0) // UART config #define MICROPY_HW_UART1_RX (25) #define MICROPY_HW_UART1_TX (24) #define MICROPY_HW_UART1_HWFC (0) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (23) #define MICROPY_HW_SPI0_MOSI (21) #define MICROPY_HW_SPI0_MISO (22) // micro:bit music pin #define MICROPY_HW_MUSIC_PIN (3) micropython-1.12/ports/nrf/boards/microbit/mpconfigboard.mk000066400000000000000000000004011357706137100241760ustar00rootroot00000000000000MCU_SERIES = m0 MCU_VARIANT = nrf51 MCU_SUB_VARIANT = nrf51822 SOFTDEV_VERSION = 8.0.0 ifneq ($(SD),) LD_FILES += boards/microbit/custom_nrf51822_s110_microbit.ld endif LD_FILES += boards/nrf51x22_256k_16k.ld FLASHER = pyocd CFLAGS += -DBLUETOOTH_LFCLK_RC micropython-1.12/ports/nrf/boards/microbit/pins.csv000066400000000000000000000004271357706137100225310ustar00rootroot00000000000000I2C_SCL,P0 P1,P1 P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 UART_RTS,P8 UART_TX,P9 UART_CTS,P10 UART_RX,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 SPI_MOSI,P21 SPI_MISO,P22 SPI_SCK,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 I2C_SDA,P30 P31,P31 micropython-1.12/ports/nrf/boards/nrf51_prefix.c000066400000000000000000000013301357706137100217010ustar00rootroot00000000000000// nrf51_prefix.c becomes the initial portion of the generated pins file. #include #include "py/obj.h" #include "py/mphal.h" #include "pin.h" #define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ { \ { &pin_af_type }, \ .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \ .idx = (af_idx), \ .fn = AF_FN_ ## af_fn, \ .unit = (af_unit), \ .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ .af_fn = (af_ptr) \ } #define PIN(p_pin, p_af, p_adc_num, p_adc_channel) \ { \ { &pin_type }, \ .name = MP_QSTR_P ## p_pin, \ .pin = (p_pin), \ .num_af = (sizeof(p_af) / sizeof(pin_af_obj_t)), \ .af = p_af, \ .adc_num = p_adc_num, \ .adc_channel = p_adc_channel, \ } micropython-1.12/ports/nrf/boards/nrf51x22_256k_16k.ld000066400000000000000000000003361357706137100222720ustar00rootroot00000000000000/* GNU linker script for NRF51 AA */ SEARCH_DIR(.) GROUP(-lgcc -lc -lnosys) _flash_size = 256K; _ram_size = 16K; /* Default stack size when there is no SoftDevice */ _stack_size = 4K; _minimum_heap_size = 8K; micropython-1.12/ports/nrf/boards/nrf51x22_256k_32k.ld000066400000000000000000000003371357706137100222710ustar00rootroot00000000000000/* GNU linker script for NRF51 AC */ SEARCH_DIR(.) GROUP(-lgcc -lc -lnosys) _flash_size = 256K; _ram_size = 32K; /* Default stack size when there is no SoftDevice */ _stack_size = 4K; _minimum_heap_size = 24K; micropython-1.12/ports/nrf/boards/nrf52832_512k_64k.ld000066400000000000000000000003171357706137100221710ustar00rootroot00000000000000/* GNU linker script for NRF52832 */ _flash_size = 512K; _ram_size = 64K; /* produce a link error if there is not this amount of RAM for these sections */ _stack_size = 8K; _minimum_heap_size = 32K; micropython-1.12/ports/nrf/boards/nrf52840_1M_256k.ld000066400000000000000000000003171357706137100220460ustar00rootroot00000000000000/* GNU linker script for NRF52840 */ _flash_size = 1M; _ram_size = 256K; /* produce a link error if there is not this amount of RAM for these sections */ _stack_size = 8K; _minimum_heap_size = 128K; micropython-1.12/ports/nrf/boards/nrf52_prefix.c000066400000000000000000000013301357706137100217020ustar00rootroot00000000000000// nrf52_prefix.c becomes the initial portion of the generated pins file. #include #include "py/obj.h" #include "py/mphal.h" #include "pin.h" #define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ { \ { &pin_af_type }, \ .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \ .idx = (af_idx), \ .fn = AF_FN_ ## af_fn, \ .unit = (af_unit), \ .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ .af_fn = (af_ptr) \ } #define PIN(p_pin, p_af, p_adc_num, p_adc_channel) \ { \ { &pin_type }, \ .name = MP_QSTR_P ## p_pin, \ .pin = (p_pin), \ .num_af = (sizeof(p_af) / sizeof(pin_af_obj_t)), \ .af = p_af, \ .adc_num = p_adc_num, \ .adc_channel = p_adc_channel, \ } micropython-1.12/ports/nrf/boards/nrf9160_1M_256k.ld000066400000000000000000000004171357706137100217640ustar00rootroot00000000000000/* GNU linker script for NRF9160 NS */ _flash_size = 1M; _ram_size = 256K; _sd_size = 0x00008000; _sd_ram = 0x00020000; _fs_size = 80K; /* produce a link error if there is not this amount of RAM for these sections */ _stack_size = 32K; _minimum_heap_size = 64K; micropython-1.12/ports/nrf/boards/nrf9160_1M_256k_secure.ld000066400000000000000000000002421357706137100233260ustar00rootroot00000000000000/* Specify the memory areas */ MEMORY { FLASH_TEXT (rx) : ORIGIN = 0x00000000, LENGTH = 32K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K } micropython-1.12/ports/nrf/boards/nrf91_prefix.c000066400000000000000000000013301357706137100217050ustar00rootroot00000000000000// nrf91_prefix.c becomes the initial portion of the generated pins file. #include #include "py/obj.h" #include "py/mphal.h" #include "pin.h" #define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ { \ { &pin_af_type }, \ .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \ .idx = (af_idx), \ .fn = AF_FN_ ## af_fn, \ .unit = (af_unit), \ .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ .af_fn = (af_ptr) \ } #define PIN(p_pin, p_af, p_adc_num, p_adc_channel) \ { \ { &pin_type }, \ .name = MP_QSTR_P ## p_pin, \ .pin = (p_pin), \ .num_af = (sizeof(p_af) / sizeof(pin_af_obj_t)), \ .af = p_af, \ .adc_num = p_adc_num, \ .adc_channel = p_adc_channel, \ } micropython-1.12/ports/nrf/boards/particle_xenon/000077500000000000000000000000001357706137100222425ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/particle_xenon/mpconfigboard.h000066400000000000000000000051731357706137100252330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Jim Mussared * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "XENON" #define MICROPY_HW_MCU_NAME "NRF52840" #define MICROPY_PY_SYS_PLATFORM "PARTICLE-XENON" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_USB_CDC (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_TRICOLOR (1) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED_RED (13) // LED1 #define MICROPY_HW_LED_GREEN (14) // LED2 #define MICROPY_HW_LED_BLUE (15) // LED3 // UART config #define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_TX (6) #define MICROPY_HW_UART1_CTS (32+2) #define MICROPY_HW_UART1_RTS (32+1) #define MICROPY_HW_UART1_HWFC (0) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (32+15) #define MICROPY_HW_SPI0_MOSI (32+13) #define MICROPY_HW_SPI0_MISO (32+14) #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #if 0 #define MICROPY_HW_PWM3_NAME "PWM3" #endif #define HELP_TEXT_BOARD_LED "1,2,3" micropython-1.12/ports/nrf/boards/particle_xenon/mpconfigboard.mk000066400000000000000000000002361357706137100254060ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52840_1M_256k.ld NRF_DEFINES += -DNRF52840_XXAA micropython-1.12/ports/nrf/boards/particle_xenon/pins.csv000066400000000000000000000006131357706137100237300ustar00rootroot00000000000000LED1,P13 LED2,P14 LED3,P15 A0,P3,ADC0_IN1 A1,P4,ADC0_IN2 A2,P28,ADC0_IN4 A3,P29,ADC0_IN5 A4,P30,ADC0_IN6 A5,P31,ADC0_IN7 SPI_SS,P31 SPI_SCK,P47 SPI_MOSI,P45 SPI_MISO,P46 SPI1_SCK,P33 SPI1_MOSI,P34 SPI1_MISO,P40 UART1_RX,P8 UART1_TX,P6 UART2_RX,P42 UART2_TX,P40 SDA,P26 SCL,P27 SDA1,P33 SCL1,P34 D0,P26 D1,P27 D2,P33 D3,P34 D4,P40 D5,P42 D6,P43 D7,P44 D8,P35 D9,P6 D10,P8 D11,P46 D12,P45 D13,P47 micropython-1.12/ports/nrf/boards/pca10000/000077500000000000000000000000001357706137100203545ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10000/mpconfigboard.h000066400000000000000000000041411357706137100233370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "PCA10000" #define MICROPY_HW_MCU_NAME "NRF51822" #define MICROPY_PY_SYS_PLATFORM "nrf51-dongle" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_SPI (0) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (0) #define MICROPY_PY_MACHINE_ADC (0) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_TRICOLOR (1) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED_RED (21) // RED #define MICROPY_HW_LED_GREEN (22) // GREEN #define MICROPY_HW_LED_BLUE (23) // BLUE // UART config #define MICROPY_HW_UART1_RX (11) #define MICROPY_HW_UART1_TX (9) #define MICROPY_HW_UART1_HWFC (0) #define HELP_TEXT_BOARD_LED "1,2,3" micropython-1.12/ports/nrf/boards/pca10000/mpconfigboard.mk000066400000000000000000000001771357706137100235240ustar00rootroot00000000000000MCU_SERIES = m0 MCU_VARIANT = nrf51 MCU_SUB_VARIANT = nrf51822 SOFTDEV_VERSION = 8.0.0 LD_FILES += boards/nrf51x22_256k_16k.ld micropython-1.12/ports/nrf/boards/pca10000/pins.csv000066400000000000000000000001271357706137100220420ustar00rootroot00000000000000UART_RTS,P8 UART_TX,P9 UART_CTS,P10 UART_RX,P11 LED_RED,P21 LED_GREEN,P22 LED_BLUE,P23 micropython-1.12/ports/nrf/boards/pca10001/000077500000000000000000000000001357706137100203555ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10001/mpconfigboard.h000066400000000000000000000041731357706137100233450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "PCA10001" #define MICROPY_HW_MCU_NAME "NRF51822" #define MICROPY_PY_SYS_PLATFORM "nrf51-DK" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_SPI (0) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (2) #define MICROPY_HW_LED_PULLUP (0) #define MICROPY_HW_LED1 (18) // LED1 #define MICROPY_HW_LED2 (19) // LED2 // UART config #define MICROPY_HW_UART1_RX (11) #define MICROPY_HW_UART1_TX (9) #define MICROPY_HW_UART1_CTS (10) #define MICROPY_HW_UART1_RTS (8) #define MICROPY_HW_UART1_HWFC (0) #define HELP_TEXT_BOARD_LED "1,2" micropython-1.12/ports/nrf/boards/pca10001/mpconfigboard.mk000066400000000000000000000001771357706137100235250ustar00rootroot00000000000000MCU_SERIES = m0 MCU_VARIANT = nrf51 MCU_SUB_VARIANT = nrf51822 SOFTDEV_VERSION = 8.0.0 LD_FILES += boards/nrf51x22_256k_16k.ld micropython-1.12/ports/nrf/boards/pca10001/pins.csv000066400000000000000000000004001357706137100220350ustar00rootroot00000000000000P0,P0 P1,P1 P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 UART_RTS,P8 UART_TX,P9 UART_CTS,P10 UART_RX,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/pca10028/000077500000000000000000000000001357706137100203665ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10028/mpconfigboard.h000066400000000000000000000046271357706137100233620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "PCA10028" #define MICROPY_HW_MCU_NAME "NRF51822" #define MICROPY_PY_SYS_PLATFORM "nrf51-DK" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED1 (21) // LED1 #define MICROPY_HW_LED2 (22) // LED2 #define MICROPY_HW_LED3 (23) // LED3 #define MICROPY_HW_LED4 (24) // LED4 // UART config #define MICROPY_HW_UART1_RX (11) #define MICROPY_HW_UART1_TX (9) #define MICROPY_HW_UART1_CTS (10) #define MICROPY_HW_UART1_RTS (8) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (29) #define MICROPY_HW_SPI0_MOSI (25) #define MICROPY_HW_SPI0_MISO (28) #define HELP_TEXT_BOARD_LED "1,2,3,4" micropython-1.12/ports/nrf/boards/pca10028/mpconfigboard.mk000066400000000000000000000001771357706137100235360ustar00rootroot00000000000000MCU_SERIES = m0 MCU_VARIANT = nrf51 MCU_SUB_VARIANT = nrf51822 SOFTDEV_VERSION = 8.0.0 LD_FILES += boards/nrf51x22_256k_32k.ld micropython-1.12/ports/nrf/boards/pca10028/pins.csv000066400000000000000000000004661357706137100220620ustar00rootroot00000000000000P0,P0 P1,P1,ADC0_IN2 P2,P2,ADC0_IN3 P3,P3,ADC0_IN4 P4,P4,ADC0_IN5 P5,P5,ADC0_IN6 P6,P6,ADC0_IN7 P7,P7 UART_RTS,P8 UART_TX,P9 UART_CTS,P10 UART_RX,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/pca10031/000077500000000000000000000000001357706137100203605ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10031/mpconfigboard.h000066400000000000000000000045501357706137100233470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "PCA10031" #define MICROPY_HW_MCU_NAME "NRF51822" #define MICROPY_PY_SYS_PLATFORM "nrf51-dongle" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_TRICOLOR (1) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED_RED (21) // RED #define MICROPY_HW_LED_GREEN (22) // GREEN #define MICROPY_HW_LED_BLUE (23) // BLUE // UART config #define MICROPY_HW_UART1_RX (11) #define MICROPY_HW_UART1_TX (9) #define MICROPY_HW_UART1_CTS (10) #define MICROPY_HW_UART1_RTS (8) #define MICROPY_HW_UART1_HWFC (0) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (15) #define MICROPY_HW_SPI0_MOSI (16) #define MICROPY_HW_SPI0_MISO (17) #define HELP_TEXT_BOARD_LED "1,2,3" micropython-1.12/ports/nrf/boards/pca10031/mpconfigboard.mk000066400000000000000000000001771357706137100235300ustar00rootroot00000000000000MCU_SERIES = m0 MCU_VARIANT = nrf51 MCU_SUB_VARIANT = nrf51822 SOFTDEV_VERSION = 8.0.0 LD_FILES += boards/nrf51x22_256k_32k.ld micropython-1.12/ports/nrf/boards/pca10031/pins.csv000066400000000000000000000002071357706137100220450ustar00rootroot00000000000000UART_RTS,P8 UART_TX,P9 UART_CTS,P10 UART_RX,P11 LED_RED,P21 LED_GREEN,P22 LED_BLUE,P23 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 micropython-1.12/ports/nrf/boards/pca10040/000077500000000000000000000000001357706137100203605ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10040/mpconfigboard.h000066400000000000000000000051621357706137100233470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "PCA10040" #define MICROPY_HW_MCU_NAME "NRF52832" #define MICROPY_PY_SYS_PLATFORM "nrf52-DK" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED1 (17) // LED1 #define MICROPY_HW_LED2 (18) // LED2 #define MICROPY_HW_LED3 (19) // LED3 #define MICROPY_HW_LED4 (20) // LED4 // UART config #define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_TX (6) #define MICROPY_HW_UART1_CTS (7) #define MICROPY_HW_UART1_RTS (5) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (25) // (Arduino D13) #define MICROPY_HW_SPI0_MOSI (23) // (Arduino D11) #define MICROPY_HW_SPI0_MISO (24) // (Arduino D12) #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #define HELP_TEXT_BOARD_LED "1,2,3,4" micropython-1.12/ports/nrf/boards/pca10040/mpconfigboard.mk000066400000000000000000000002371357706137100235250ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52832 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52832_512k_64k.ld NRF_DEFINES += -DNRF52832_XXAA micropython-1.12/ports/nrf/boards/pca10040/pins.csv000066400000000000000000000003401357706137100220430ustar00rootroot00000000000000P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/pca10056/000077500000000000000000000000001357706137100203675ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10056/mpconfigboard.h000066400000000000000000000051741357706137100233610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "PCA10056" #define MICROPY_HW_MCU_NAME "NRF52840" #define MICROPY_PY_SYS_PLATFORM "nrf52840-PDK" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED1 (13) // LED1 #define MICROPY_HW_LED2 (14) // LED2 #define MICROPY_HW_LED3 (15) // LED3 #define MICROPY_HW_LED4 (16) // LED4 // UART config #define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_TX (6) #define MICROPY_HW_UART1_CTS (7) #define MICROPY_HW_UART1_RTS (5) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (47) #define MICROPY_HW_SPI0_MOSI (45) #define MICROPY_HW_SPI0_MISO (46) #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #if 0 #define MICROPY_HW_PWM3_NAME "PWM3" #endif #define HELP_TEXT_BOARD_LED "1,2,3,4" micropython-1.12/ports/nrf/boards/pca10056/mpconfigboard.mk000066400000000000000000000002361357706137100235330ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52840_1M_256k.ld NRF_DEFINES += -DNRF52840_XXAA micropython-1.12/ports/nrf/boards/pca10056/pins.csv000066400000000000000000000006641357706137100220630ustar00rootroot00000000000000P0,P0 P1,P1 P2,P2,ADC0_IN0 P3,P3,ADC0_IN1 P4,P4,ADC0_IN2 P5,P5,ADC0_IN3 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28,ADC0_IN4 P29,P29,ADC0_IN5 P30,P30,ADC0_IN6 P31,P31,ADC0_IN7 P32,P32 P33,P33 P34,P34 P35,P35 P36,P36 P37,P37 P38,P38 P39,P39 P40,P40 P41,P41 P42,P42 P43,P43 P44,P44 P45,P45 P46,P46 P47,P47 micropython-1.12/ports/nrf/boards/pca10059/000077500000000000000000000000001357706137100203725ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10059/modules/000077500000000000000000000000001357706137100220425ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10059/modules/boardmodules.h000066400000000000000000000026721357706137100247020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_NRF_BOARD_PCA10059_BOARD_MODULES_H #define MICROPY_INCLUDED_NRF_BOARD_PCA10059_BOARD_MODULES_H #define BOARD_MODULES void board_modules_init0(void); #endif // MICROPY_INCLUDED_NRF_BOARD_PCA10059_BOARD_MODULES_H micropython-1.12/ports/nrf/boards/pca10059/modules/boardmodules.mk000066400000000000000000000004571357706137100250610ustar00rootroot00000000000000BOARD_PCA10059_DIR = boards/pca10059/modules INC += -I./$(BOARD_PCA10059_DIR) CFLAGS += -DBOARD_SPECIFIC_MODULES SRC_BOARD_MODULES = $(addprefix $(BOARD_PCA10059_DIR)/,\ recover_uicr_regout0.c \ ) OBJ += $(addprefix $(BUILD)/, $(SRC_BOARD_MODULES:.c=.o)) micropython-1.12/ports/nrf/boards/pca10059/modules/recover_uicr_regout0.c000066400000000000000000000041771357706137100263530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "nrf.h" #include "nrf52840_bitfields.h" bool uicr_REGOUT0_erased() { if (NRF_UICR->REGOUT0 == 0xFFFFFFFFUL) { return true; } return false; } void board_modules_init0(void) { if (uicr_REGOUT0_erased()) { // Wait for pending NVMC operations to finish. while (NRF_NVMC->READY != NVMC_READY_READY_Ready); // Enable write mode in NVMC. NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; while (NRF_NVMC->READY != NVMC_READY_READY_Ready); // Write 3v3 value to UICR->REGOUT0. NRF_UICR->REGOUT0 = (UICR_REGOUT0_VOUT_3V3 & UICR_REGOUT0_VOUT_Msk) << UICR_REGOUT0_VOUT_Pos; while (NRF_NVMC->READY != NVMC_READY_READY_Ready); // Enable read mode in NVMC. NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; while (NRF_NVMC->READY != NVMC_READY_READY_Ready); // Reset to apply the update. NVIC_SystemReset(); } } micropython-1.12/ports/nrf/boards/pca10059/mpconfigboard.h000066400000000000000000000053231357706137100233600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "PCA10059" #define MICROPY_HW_MCU_NAME "NRF52840" #define MICROPY_PY_SYS_PLATFORM "nrf52840-Dongle" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_USB_CDC (1) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED1 (6) // LED1 GREEN #define MICROPY_HW_LED2 (8) // LED2 RED (RGB) #define MICROPY_HW_LED3 (41) // LED2 GREEN (RGB) #define MICROPY_HW_LED4 (12) // LED2 BLUE (RGB) // UART config #define MICROPY_HW_UART1_RX (13) #define MICROPY_HW_UART1_TX (15) #define MICROPY_HW_UART1_CTS (17) #define MICROPY_HW_UART1_RTS (20) #define MICROPY_HW_UART1_HWFC (1) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (22) #define MICROPY_HW_SPI0_MOSI (32) #define MICROPY_HW_SPI0_MISO (24) #define MICROPY_HW_PWM0_NAME "PWM0" #define MICROPY_HW_PWM1_NAME "PWM1" #define MICROPY_HW_PWM2_NAME "PWM2" #if 0 #define MICROPY_HW_PWM3_NAME "PWM3" #endif #define HELP_TEXT_BOARD_LED "1,2,3,4" micropython-1.12/ports/nrf/boards/pca10059/mpconfigboard.mk000066400000000000000000000002361357706137100235360ustar00rootroot00000000000000MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 SOFTDEV_VERSION = 6.1.1 LD_FILES += boards/nrf52840_1M_256k.ld NRF_DEFINES += -DNRF52840_XXAA micropython-1.12/ports/nrf/boards/pca10059/pins.csv000066400000000000000000000005531357706137100220630ustar00rootroot00000000000000P2,P2,ADC0_IN0 P4,P4,ADC0_IN2 LED1_GREEN,P6 LED2_RED,P8 P9,P9 P10,P10 P11,P11 LED2_BLUE,P12 UART1_RX,P13 P14,P14 UART1_TX,P15 P16,P16 UART1_CTS,P17 SWITCH2_NRESET,P18 UART1_RTS,P20 SPI0_SCK,P22,P22 SPI0_MISO,P24 P26,P26 P29,P29,ADC0_IN5 P31,P31,ADC0_IN7 SPI0_MOSI,P32 P33,P33 P34,P34 P36,P36 SWITCH1,P38,P38 P39,P39 LED2_GREEN,P41 P42,P42 P43,P43 P45,P45 P47,P47 micropython-1.12/ports/nrf/boards/pca10090/000077500000000000000000000000001357706137100203655ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/pca10090/mpconfigboard.h000066400000000000000000000062761357706137100233630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define PCA10090 #define MICROPY_HW_BOARD_NAME "PCA10090" #define MICROPY_HW_MCU_NAME "NRF9160" #define MICROPY_PY_SYS_PLATFORM "nrf9160-DK" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_PWM (0) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (0) #define MICROPY_PY_MACHINE_RTCOUNTER (0) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (0) #define MICROPY_PY_MACHINE_TEMP (0) #define MICROPY_PY_RANDOM_HW_RNG (0) #define MICROPY_MBFS (0) #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_HAS_SWITCH (0) #define MICROPY_HW_HAS_FLASH (0) #define MICROPY_HW_HAS_SDCARD (0) #define MICROPY_HW_HAS_MMA7660 (0) #define MICROPY_HW_HAS_LIS3DSH (0) #define MICROPY_HW_HAS_LCD (0) #define MICROPY_HW_ENABLE_RNG (0) #define MICROPY_HW_ENABLE_RTC (0) #define MICROPY_HW_ENABLE_TIMER (0) #define MICROPY_HW_ENABLE_SERVO (0) #define MICROPY_HW_ENABLE_DAC (0) #define MICROPY_HW_ENABLE_CAN (0) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (0) #define MICROPY_HW_LED1 (2) // LED1 #define MICROPY_HW_LED2 (3) // LED2 #define MICROPY_HW_LED3 (4) // LED3 #define MICROPY_HW_LED4 (5) // LED4 // UART config // VCOM0 #define MICROPY_HW_UART1_RX (28) #define MICROPY_HW_UART1_TX (29) #define MICROPY_HW_UART1_CTS (26) #define MICROPY_HW_UART1_RTS (27) #define MICROPY_HW_UART1_HWFC (1) /* // VCOM2 #define MICROPY_HW_UART1_RX (0) #define MICROPY_HW_UART1_TX (1) #define MICROPY_HW_UART1_CTS (15) #define MICROPY_HW_UART1_RTS (14) #define MICROPY_HW_UART1_HWFC (1) */ // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (13) #define MICROPY_HW_SPI0_MOSI (11) #define MICROPY_HW_SPI0_MISO (12) #define HELP_TEXT_BOARD_LED "1,2,3,4" micropython-1.12/ports/nrf/boards/pca10090/mpconfigboard.mk000066400000000000000000000002361357706137100235310ustar00rootroot00000000000000MCU_SERIES = m33 MCU_VARIANT = nrf91 MCU_SUB_VARIANT = nrf9160 LD_FILES += boards/nrf9160_1M_256k.ld NRF_DEFINES += -DNRF9160_XXAA -DNRF_TRUSTZONE_NONSECURE micropython-1.12/ports/nrf/boards/pca10090/pins.csv000066400000000000000000000003541357706137100220550ustar00rootroot00000000000000P0,P0 P1,P1 P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/boards/s110_8.0.0.ld000066400000000000000000000003341357706137100207600ustar00rootroot00000000000000 /* GNU linker script for s110 SoftDevice version 8.0.0 */ _sd_size = 0x00018000; _sd_ram = 0x00002000; _fs_size = DEFINED(_fs_size) ? _fs_size : 20K; _stack_size = _ram_size > 16K ? 4K : 2K; _minimum_heap_size = 4K; micropython-1.12/ports/nrf/boards/s132_6.1.1.ld000066400000000000000000000001511357706137100207610ustar00rootroot00000000000000/* GNU linker script for s132 SoftDevice version 6.1.1 */ _sd_size = 0x00026000; _sd_ram = 0x000039c0; micropython-1.12/ports/nrf/boards/s140_6.1.1.ld000066400000000000000000000001511357706137100207600ustar00rootroot00000000000000/* GNU linker script for s140 SoftDevice version 6.1.1 */ _sd_size = 0x00026000; _sd_ram = 0x000039c0; micropython-1.12/ports/nrf/boards/wt51822_s4at/000077500000000000000000000000001357706137100212175ustar00rootroot00000000000000micropython-1.12/ports/nrf/boards/wt51822_s4at/mpconfigboard.h000066400000000000000000000041131357706137100242010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Datasheet for board: // https://4tronix.co.uk/picobot2/WT51822-S4AT.pdf #define MICROPY_HW_BOARD_NAME "WT51822-S4AT" #define MICROPY_HW_MCU_NAME "NRF51822" #define MICROPY_PY_SYS_PLATFORM "nrf51" #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_HW_SPI (1) #define MICROPY_PY_MACHINE_TIMER (1) #define MICROPY_PY_MACHINE_RTCOUNTER (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) #define MICROPY_HW_HAS_LED (0) // UART config #define MICROPY_HW_UART1_RX (1) #define MICROPY_HW_UART1_TX (2) #define MICROPY_HW_UART1_HWFC (0) // SPI0 config #define MICROPY_HW_SPI0_NAME "SPI0" #define MICROPY_HW_SPI0_SCK (9) #define MICROPY_HW_SPI0_MOSI (10) #define MICROPY_HW_SPI0_MISO (13) micropython-1.12/ports/nrf/boards/wt51822_s4at/mpconfigboard.mk000066400000000000000000000002371357706137100243640ustar00rootroot00000000000000MCU_SERIES = m0 MCU_VARIANT = nrf51 MCU_SUB_VARIANT = nrf51822 SOFTDEV_VERSION = 8.0.0 LD_FILES += boards/nrf51x22_256k_16k.ld CFLAGS += -DBLUETOOTH_LFCLK_RC micropython-1.12/ports/nrf/boards/wt51822_s4at/pins.csv000066400000000000000000000000561357706137100227060ustar00rootroot00000000000000P1,P1 P2,P2 P3,P3 P4,P4 P9,P9 P10,P10 P13,P13 micropython-1.12/ports/nrf/device/000077500000000000000000000000001357706137100172155ustar00rootroot00000000000000micropython-1.12/ports/nrf/device/startup_nrf51822.c000066400000000000000000000127571357706137100223460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include extern uint32_t _estack; extern uint32_t _sidata; extern uint32_t _sdata; extern uint32_t _edata; extern uint32_t _sbss; extern uint32_t _ebss; typedef void (*func)(void); extern void _start(void) __attribute__((noreturn)); extern void SystemInit(void); void Default_Handler(void) { while (1); } void Reset_Handler(void) { uint32_t * ram_on_addr = (uint32_t *)0x40000524; uint32_t * ram_on_b_addr = (uint32_t *)0x40000554; // RAM on in on-mode *ram_on_addr = 3; // block 0 and 1 *ram_on_b_addr = 3; // block 2 and 3 #if 0 // RAM on in off-mode ram_on_addr = 1 << 16; ram_on_b_addr = 1 << 17; #endif uint32_t * p_src = &_sidata; uint32_t * p_dest = &_sdata; while (p_dest < &_edata) { *p_dest++ = *p_src++; } uint32_t * p_bss = &_sbss; uint32_t * p_bss_end = &_ebss; while (p_bss < p_bss_end) { *p_bss++ = 0ul; } SystemInit(); _start(); } void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void HardFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void PendSV_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void SysTick_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void POWER_CLOCK_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RADIO_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void UART0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPI0_TWI0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPI1_TWI1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void GPIOTE_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void ADC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RTC0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TEMP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RNG_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void ECB_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void CCM_AAR_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void WDT_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RTC1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void QDEC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void LPCOMP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI5_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); const func __Vectors[] __attribute__ ((section(".isr_vector"),used)) = { (func)&_estack, Reset_Handler, NMI_Handler, HardFault_Handler, 0, 0, 0, 0, 0, 0, 0, SVC_Handler, 0, 0, PendSV_Handler, SysTick_Handler, /* External Interrupts */ POWER_CLOCK_IRQHandler, RADIO_IRQHandler, UART0_IRQHandler, SPI0_TWI0_IRQHandler, SPI1_TWI1_IRQHandler, 0, GPIOTE_IRQHandler, ADC_IRQHandler, TIMER0_IRQHandler, TIMER1_IRQHandler, TIMER2_IRQHandler, RTC0_IRQHandler, TEMP_IRQHandler, RNG_IRQHandler, ECB_IRQHandler, CCM_AAR_IRQHandler, WDT_IRQHandler, RTC1_IRQHandler, QDEC_IRQHandler, LPCOMP_IRQHandler, SWI0_IRQHandler, SWI1_IRQHandler, SWI2_IRQHandler, SWI3_IRQHandler, SWI4_IRQHandler, SWI5_IRQHandler }; micropython-1.12/ports/nrf/device/startup_nrf52832.c000066400000000000000000000157211357706137100223420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include extern uint32_t _estack; extern uint32_t _sidata; extern uint32_t _sdata; extern uint32_t _edata; extern uint32_t _sbss; extern uint32_t _ebss; typedef void (*func)(void); extern void _start(void) __attribute__((noreturn)); extern void SystemInit(void); void Default_Handler(void) { while (1); } void Reset_Handler(void) { uint32_t * p_src = &_sidata; uint32_t * p_dest = &_sdata; while (p_dest < &_edata) { *p_dest++ = *p_src++; } uint32_t * p_bss = &_sbss; uint32_t * p_bss_end = &_ebss; while (p_bss < p_bss_end) { *p_bss++ = 0ul; } SystemInit(); _start(); } void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void HardFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void MemoryManagement_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void BusFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void UsageFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void DebugMon_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void PendSV_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void SysTick_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void POWER_CLOCK_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RADIO_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void UARTE0_UART0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void NFCT_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void GPIOTE_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SAADC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RTC0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TEMP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RNG_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void ECB_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void CCM_AAR_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void WDT_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RTC1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void QDEC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void COMP_LPCOMP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI0_EGU0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI1_EGU1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI2_EGU2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI3_EGU3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI4_EGU4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI5_EGU5_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PWM0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PDM_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void MWU_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PWM1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PWM2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPIM2_SPIS2_SPI2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RTC2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void I2S_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); const func __Vectors[] __attribute__ ((section(".isr_vector"),used)) = { (func)&_estack, Reset_Handler, NMI_Handler, HardFault_Handler, MemoryManagement_Handler, BusFault_Handler, UsageFault_Handler, 0, 0, 0, 0, SVC_Handler, DebugMon_Handler, 0, PendSV_Handler, SysTick_Handler, /* External Interrupts */ POWER_CLOCK_IRQHandler, RADIO_IRQHandler, UARTE0_UART0_IRQHandler, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler, NFCT_IRQHandler, GPIOTE_IRQHandler, SAADC_IRQHandler, TIMER0_IRQHandler, TIMER1_IRQHandler, TIMER2_IRQHandler, RTC0_IRQHandler, TEMP_IRQHandler, RNG_IRQHandler, ECB_IRQHandler, CCM_AAR_IRQHandler, WDT_IRQHandler, RTC1_IRQHandler, QDEC_IRQHandler, COMP_LPCOMP_IRQHandler, SWI0_EGU0_IRQHandler, SWI1_EGU1_IRQHandler, SWI2_EGU2_IRQHandler, SWI3_EGU3_IRQHandler, SWI4_EGU4_IRQHandler, SWI5_EGU5_IRQHandler, TIMER3_IRQHandler, TIMER4_IRQHandler, PWM0_IRQHandler, PDM_IRQHandler, 0, 0, MWU_IRQHandler, PWM1_IRQHandler, PWM2_IRQHandler, SPIM2_SPIS2_SPI2_IRQHandler, RTC2_IRQHandler, I2S_IRQHandler }; micropython-1.12/ports/nrf/device/startup_nrf52840.c000066400000000000000000000175661357706137100223520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include extern uint32_t _estack; extern uint32_t _sidata; extern uint32_t _sdata; extern uint32_t _edata; extern uint32_t _sbss; extern uint32_t _ebss; typedef void (*func)(void); extern void _start(void) __attribute__((noreturn)); extern void SystemInit(void); void Default_Handler(void) { while (1); } void Reset_Handler(void) { uint32_t * p_src = &_sidata; uint32_t * p_dest = &_sdata; while (p_dest < &_edata) { *p_dest++ = *p_src++; } uint32_t * p_bss = &_sbss; uint32_t * p_bss_end = &_ebss; while (p_bss < p_bss_end) { *p_bss++ = 0ul; } SystemInit(); _start(); } void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void HardFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void MemoryManagement_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void BusFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void UsageFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void DebugMon_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void PendSV_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void SysTick_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void POWER_CLOCK_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RADIO_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void UARTE0_UART0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void NFCT_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void GPIOTE_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SAADC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RTC0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TEMP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RNG_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void ECB_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void CCM_AAR_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void WDT_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RTC1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void QDEC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void COMP_LPCOMP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI0_EGU0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI1_EGU1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI2_EGU2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI3_EGU3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI4_EGU4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SWI5_EGU5_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void TIMER4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PWM0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PDM_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void MWU_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PWM1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PWM2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPIM2_SPIS2_SPI2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void RTC2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void I2S_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void FPU_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void USBD_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void UARTE1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void QSPI_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void CRYPTOCELL_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void SPIM3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); void PWM3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler"))); const func __Vectors[] __attribute__ ((section(".isr_vector"),used)) = { (func)&_estack, Reset_Handler, NMI_Handler, HardFault_Handler, MemoryManagement_Handler, BusFault_Handler, UsageFault_Handler, 0, 0, 0, 0, SVC_Handler, DebugMon_Handler, 0, PendSV_Handler, SysTick_Handler, /* External Interrupts */ POWER_CLOCK_IRQHandler, RADIO_IRQHandler, UARTE0_UART0_IRQHandler, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler, NFCT_IRQHandler, GPIOTE_IRQHandler, SAADC_IRQHandler, TIMER0_IRQHandler, TIMER1_IRQHandler, TIMER2_IRQHandler, RTC0_IRQHandler, TEMP_IRQHandler, RNG_IRQHandler, ECB_IRQHandler, CCM_AAR_IRQHandler, WDT_IRQHandler, RTC1_IRQHandler, QDEC_IRQHandler, COMP_LPCOMP_IRQHandler, SWI0_EGU0_IRQHandler, SWI1_EGU1_IRQHandler, SWI2_EGU2_IRQHandler, SWI3_EGU3_IRQHandler, SWI4_EGU4_IRQHandler, SWI5_EGU5_IRQHandler, TIMER3_IRQHandler, TIMER4_IRQHandler, PWM0_IRQHandler, PDM_IRQHandler, 0, 0, MWU_IRQHandler, PWM1_IRQHandler, PWM2_IRQHandler, SPIM2_SPIS2_SPI2_IRQHandler, RTC2_IRQHandler, I2S_IRQHandler, FPU_IRQHandler, USBD_IRQHandler, UARTE1_IRQHandler, QSPI_IRQHandler, CRYPTOCELL_IRQHandler, 0, 0, PWM3_IRQHandler, 0, SPIM3_IRQHandler, }; micropython-1.12/ports/nrf/device/startup_nrf9160.c000066400000000000000000000302671357706137100222600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include extern uint32_t _estack; extern uint32_t _sidata; extern uint32_t _sdata; extern uint32_t _edata; extern uint32_t _sbss; extern uint32_t _ebss; typedef void (*func)(void); extern void _start(void) __attribute__((noreturn)); extern void SystemInit(void); void Default_Handler(void) { while (1); } void Reserved_Handler1(void) { while (1); } void Reserved_Handler2(void) { while (1); } void Reserved_Handler3(void) { while (1); } void Reserved_Handler4(void) { while (1); } void Reserved_Handler5(void) { while (1); } void Reserved_Handler6(void) { while (1); } void Reserved_Handler7(void) { while (1); } void Reserved_Handler8(void) { while (1); } void Reserved_Handler9(void) { while (1); } void Reserved_Handler10(void) { while (1); } void Reserved_Handler11(void) { while (1); } void Reserved_Handler12(void) { while (1); } void Reserved_Handler13(void) { while (1); } void Reserved_Handler14(void) { while (1); } void Reserved_Handler15(void) { while (1); } void Reserved_Handler16(void) { while (1); } void Reserved_Handler17(void) { while (1); } void Reserved_Handler18(void) { while (1); } void Reserved_Handler19(void) { while (1); } void Reserved_Handler20(void) { while (1); } void Reserved_Handler21(void) { while (1); } void Reserved_Handler22(void) { while (1); } void Reserved_Handler23(void) { while (1); } void Reserved_Handler24(void) { while (1); } void Reserved_Handler25(void) { while (1); } void Reserved_Handler26(void) { while (1); } void Reserved_Handler27(void) { while (1); } void Reserved_Handler28(void) { while (1); } void Reserved_Handler29(void) { while (1); } void Reserved_Handler30(void) { while (1); } void Reserved_Handler31(void) { while (1); } void Reserved_Handler32(void) { while (1); } void Reserved_Handler33(void) { while (1); } void Reserved_Handler34(void) { while (1); } void Reserved_Handler35(void) { while (1); } void Reserved_Handler36(void) { while (1); } void Reserved_Handler37(void) { while (1); } void Reserved_Handler38(void) { while (1); } void Default_NMI_Handler (void) { while (1); } void Default_HardFault_Handler (void) { while (1); } void Default_MemoryManagement_Handler (void) { while (1); } void Default_BusFault_Handler (void) { while (1); } void Default_UsageFault_Handler (void) { while (1); } void Default_SecureFault_Handler (void) { while (1); } void Default_SVC_Handler (void) { while (1); } void Default_DebugMon_Handler (void) { while (1); } void Default_PendSV_Handler (void) { while (1); } void Default_SysTick_Handler (void) { while (1); } void Default_SPU_IRQHandler (void) { while (1); } void Default_CLOCK_POWER_IRQHandler (void) { while (1); } void Default_UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQHandler (void) { while (1); } void Default_UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQHandler (void) { while (1); } void Default_UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQHandler (void) { while (1); } void Default_UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQHandler (void) { while (1); } void Default_GPIOTE0_IRQHandler (void) { while (1); } void Default_SAADC_IRQHandler (void) { while (1); } void Default_TIMER0_IRQHandler (void) { while (1); } void Default_TIMER1_IRQHandler (void) { while (1); } void Default_TIMER2_IRQHandler (void) { while (1); } void Default_RTC0_IRQHandler (void) { while (1); } void Default_RTC1_IRQHandler (void) { while (1); } void Default_WDT_IRQHandler (void) { while (1); } void Default_EGU0_IRQHandler (void) { while (1); } void Default_EGU1_IRQHandler (void) { while (1); } void Default_EGU2_IRQHandler (void) { while (1); } void Default_EGU3_IRQHandler (void) { while (1); } void Default_EGU4_IRQHandler (void) { while (1); } void Default_EGU5_IRQHandler (void) { while (1); } void Default_PWM0_IRQHandler (void) { while (1); } void Default_PWM1_IRQHandler (void) { while (1); } void Default_PWM2_IRQHandler (void) { while (1); } void Default_PWM3_IRQHandler (void) { while (1); } void Default_PDM_IRQHandler (void) { while (1); } void Default_I2S_IRQHandler (void) { while (1); } void Default_IPC_IRQHandler (void) { while (1); } void Default_FPU_IRQHandler (void) { while (1); } void Default_GPIOTE1_IRQHandler (void) { while (1); } void Default_KMU_IRQHandler (void) { while (1); } void Default_CRYPTOCELL_IRQHandler (void) { while (1); } void Reset_Handler(void) { uint32_t * p_src = &_sidata; uint32_t * p_dest = &_sdata; while (p_dest < &_edata) { *p_dest++ = *p_src++; } uint32_t * p_bss = &_sbss; uint32_t * p_bss_end = &_ebss; while (p_bss < p_bss_end) { *p_bss++ = 0ul; } SystemInit(); _start(); } void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); void HardFault_Handler (void) __attribute__ ((weak, alias("Default_HardFault_Handler"))); void MemoryManagement_Handler (void) __attribute__ ((weak, alias("Default_MemoryManagement_Handler"))); void BusFault_Handler (void) __attribute__ ((weak, alias("Default_BusFault_Handler"))); void UsageFault_Handler (void) __attribute__ ((weak, alias("Default_UsageFault_Handler"))); void SecureFault_Handler (void) __attribute__ ((weak, alias("Default_SecureFault_Handler"))); void SVC_Handler (void) __attribute__ ((weak, alias("Default_SVC_Handler"))); void DebugMon_Handler (void) __attribute__ ((weak, alias("Default_DebugMon_Handler"))); void PendSV_Handler (void) __attribute__ ((weak, alias("Default_PendSV_Handler"))); void SysTick_Handler (void) __attribute__ ((weak, alias("Default_SysTick_Handler"))); void SPU_IRQHandler (void) __attribute__ ((weak, alias("Default_SPU_IRQHandler"))); void CLOCK_POWER_IRQHandler (void) __attribute__ ((weak, alias("Default_CLOCK_POWER_IRQHandler"))); void UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQHandler (void) __attribute__ ((weak, alias("Default_UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQHandler"))); void UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQHandler (void) __attribute__ ((weak, alias("Default_UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQHandler"))); void UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQHandler (void) __attribute__ ((weak, alias("Default_UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQHandler"))); void UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQHandler (void) __attribute__ ((weak, alias("Default_UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQHandler"))); void GPIOTE0_IRQHandler (void) __attribute__ ((weak, alias("Default_GPIOTE0_IRQHandler"))); void SAADC_IRQHandler (void) __attribute__ ((weak, alias("Default_SAADC_IRQHandler"))); void TIMER0_IRQHandler (void) __attribute__ ((weak, alias("Default_TIMER0_IRQHandler"))); void TIMER1_IRQHandler (void) __attribute__ ((weak, alias("Default_TIMER1_IRQHandler"))); void TIMER2_IRQHandler (void) __attribute__ ((weak, alias("Default_TIMER2_IRQHandler"))); void RTC0_IRQHandler (void) __attribute__ ((weak, alias("Default_RTC0_IRQHandler"))); void RTC1_IRQHandler (void) __attribute__ ((weak, alias("Default_RTC1_IRQHandler"))); void WDT_IRQHandler (void) __attribute__ ((weak, alias("Default_WDT_IRQHandler"))); void EGU0_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU0_IRQHandler"))); void EGU1_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU1_IRQHandler"))); void EGU2_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU2_IRQHandler"))); void EGU3_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU3_IRQHandler"))); void EGU4_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU4_IRQHandler"))); void EGU5_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU5_IRQHandler"))); void PWM0_IRQHandler (void) __attribute__ ((weak, alias("Default_PWM0_IRQHandler"))); void PWM1_IRQHandler (void) __attribute__ ((weak, alias("Default_PWM1_IRQHandler"))); void PWM2_IRQHandler (void) __attribute__ ((weak, alias("Default_PWM2_IRQHandler"))); void PWM3_IRQHandler (void) __attribute__ ((weak, alias("Default_PWM3_IRQHandler"))); void PDM_IRQHandler (void) __attribute__ ((weak, alias("Default_PDM_IRQHandler"))); void I2S_IRQHandler (void) __attribute__ ((weak, alias("Default_I2S_IRQHandler"))); void IPC_IRQHandler (void) __attribute__ ((weak, alias("Default_IPC_IRQHandler"))); void FPU_IRQHandler (void) __attribute__ ((weak, alias("Default_FPU_IRQHandler"))); void GPIOTE1_IRQHandler (void) __attribute__ ((weak, alias("Default_GPIOTE1_IRQHandler"))); void KMU_IRQHandler (void) __attribute__ ((weak, alias("Default_KMU_IRQHandler"))); void CRYPTOCELL_IRQHandler (void) __attribute__ ((weak, alias("Default_CRYPTOCELL_IRQHandler"))); const func __Vectors[] __attribute__ ((section(".isr_vector"),used)) = { (func)&_estack, Reset_Handler, NMI_Handler, HardFault_Handler, MemoryManagement_Handler, BusFault_Handler, UsageFault_Handler, SecureFault_Handler, Reserved_Handler1, Reserved_Handler2, Reserved_Handler3, SVC_Handler, DebugMon_Handler, Reserved_Handler4, PendSV_Handler, SysTick_Handler, /* External Interrupts */ Reserved_Handler5, Reserved_Handler6, Reserved_Handler7, SPU_IRQHandler, Reserved_Handler8, CLOCK_POWER_IRQHandler, Reserved_Handler9, Reserved_Handler10, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQHandler, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQHandler, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQHandler, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQHandler, Reserved_Handler11, GPIOTE0_IRQHandler, SAADC_IRQHandler, TIMER0_IRQHandler, TIMER1_IRQHandler, TIMER2_IRQHandler, Reserved_Handler12, Reserved_Handler13, RTC0_IRQHandler, RTC1_IRQHandler, Reserved_Handler14, Reserved_Handler15, WDT_IRQHandler, Reserved_Handler16, Reserved_Handler17, EGU0_IRQHandler, EGU1_IRQHandler, EGU2_IRQHandler, EGU3_IRQHandler, EGU4_IRQHandler, EGU5_IRQHandler, PWM0_IRQHandler, PWM1_IRQHandler, PWM2_IRQHandler, PWM3_IRQHandler, Reserved_Handler18, PDM_IRQHandler, Reserved_Handler19, I2S_IRQHandler, Reserved_Handler20, IPC_IRQHandler, Reserved_Handler21, FPU_IRQHandler, Reserved_Handler22, Reserved_Handler23, Reserved_Handler24, Reserved_Handler25, GPIOTE1_IRQHandler, Reserved_Handler26, Reserved_Handler27, Reserved_Handler28, Reserved_Handler29, Reserved_Handler30, Reserved_Handler31, Reserved_Handler32, KMU_IRQHandler, Reserved_Handler33, Reserved_Handler34, Reserved_Handler35, Reserved_Handler36, Reserved_Handler37, Reserved_Handler38, CRYPTOCELL_IRQHandler, }; micropython-1.12/ports/nrf/drivers/000077500000000000000000000000001357706137100174345ustar00rootroot00000000000000micropython-1.12/ports/nrf/drivers/bluetooth/000077500000000000000000000000001357706137100214415ustar00rootroot00000000000000micropython-1.12/ports/nrf/drivers/bluetooth/ble_drv.c000066400000000000000000001270111357706137100232240ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 - 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #if BLUETOOTH_SD #include #include #include #include "py/runtime.h" #include "ble_drv.h" #include "mpconfigport.h" #include "nrf_sdm.h" #include "ble_gap.h" #include "ble.h" // sd_ble_uuid_encode #include "drivers/flash.h" #include "mphalport.h" #if MICROPY_HW_USB_CDC #include "usb_cdc.h" #endif #define BLE_DRIVER_VERBOSE 0 #if BLE_DRIVER_VERBOSE #define BLE_DRIVER_LOG printf #else #define BLE_DRIVER_LOG(...) #endif #define BLE_ADV_LENGTH_FIELD_SIZE 1 #define BLE_ADV_AD_TYPE_FIELD_SIZE 1 #define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 #define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) #define UNIT_0_625_MS (625) #define UNIT_10_MS (10000) #define APP_CFG_NON_CONN_ADV_TIMEOUT 0 // Disable timeout. #define NON_CONNECTABLE_ADV_INTERVAL MSEC_TO_UNITS(100, UNIT_0_625_MS) #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(12, UNIT_0_625_MS) #define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(12, UNIT_0_625_MS) #define BLE_SLAVE_LATENCY 0 #define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) #if (BLUETOOTH_SD == 110) #define MAX_TX_IN_PROGRESS (6) #else #define MAX_TX_IN_PROGRESS (10) #endif #if !defined(GATT_MTU_SIZE_DEFAULT) && defined(BLE_GATT_ATT_MTU_DEFAULT) #define GATT_MTU_SIZE_DEFAULT BLE_GATT_ATT_MTU_DEFAULT #endif #define SD_TEST_OR_ENABLE() \ if (ble_drv_stack_enabled() == 0) { \ (void)ble_drv_stack_enable(); \ } static volatile bool m_adv_in_progress; static volatile uint8_t m_tx_in_progress; static ble_drv_gap_evt_callback_t gap_event_handler; static ble_drv_gatts_evt_callback_t gatts_event_handler; static mp_obj_t mp_gap_observer; static mp_obj_t mp_gatts_observer; #if (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) static volatile bool m_primary_service_found; static volatile bool m_characteristic_found; static volatile bool m_write_done; static volatile ble_drv_adv_evt_callback_t adv_event_handler; static volatile ble_drv_gattc_evt_callback_t gattc_event_handler; static volatile ble_drv_disc_add_service_callback_t disc_add_service_handler; static volatile ble_drv_disc_add_char_callback_t disc_add_char_handler; static volatile ble_drv_gattc_char_data_callback_t gattc_char_data_handle; static mp_obj_t mp_adv_observer; static mp_obj_t mp_gattc_observer; static mp_obj_t mp_gattc_disc_service_observer; static mp_obj_t mp_gattc_disc_char_observer; static mp_obj_t mp_gattc_char_data_observer; #endif #if (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) #include "nrf_nvic.h" #define BLE_GAP_ADV_MAX_SIZE 31 #define BLE_DRV_CONN_CONFIG_TAG 1 static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; static uint8_t m_scan_buffer[BLE_GAP_SCAN_BUFFER_MIN]; nrf_nvic_state_t nrf_nvic_state = {0}; #endif #if (BLUETOOTH_SD == 110) void softdevice_assert_handler(uint32_t pc, uint16_t line_number, const uint8_t * p_file_name) { BLE_DRIVER_LOG("ERROR: SoftDevice assert!!!"); } #else void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { BLE_DRIVER_LOG("ERROR: SoftDevice assert!!!"); } #endif uint32_t ble_drv_stack_enable(void) { m_adv_in_progress = false; m_tx_in_progress = 0; #if (BLUETOOTH_SD == 110) #if BLUETOOTH_LFCLK_RC uint32_t err_code = sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_RC_250_PPM_250MS_CALIBRATION, softdevice_assert_handler); #else uint32_t err_code = sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, softdevice_assert_handler); #endif // BLUETOOTH_LFCLK_RC #endif // (BLUETOOTH_SD == 110) #if (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) #if BLUETOOTH_LFCLK_RC nrf_clock_lf_cfg_t clock_config = { .source = NRF_CLOCK_LF_SRC_RC, .rc_ctiv = 16, .rc_temp_ctiv = 2, .accuracy = NRF_CLOCK_LF_ACCURACY_250_PPM }; #else nrf_clock_lf_cfg_t clock_config = { .source = NRF_CLOCK_LF_SRC_XTAL, .rc_ctiv = 0, .rc_temp_ctiv = 0, .accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM }; #endif // BLUETOOTH_LFCLK_RC uint32_t err_code = sd_softdevice_enable(&clock_config, softdevice_assert_handler); #endif // (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) BLE_DRIVER_LOG("SoftDevice enable status: " UINT_FMT "\n", (uint16_t)err_code); err_code = sd_nvic_EnableIRQ(SD_EVT_IRQn); BLE_DRIVER_LOG("IRQ enable status: " UINT_FMT "\n", (uint16_t)err_code); #if (BLUETOOTH_SD == 110) ble_enable_params_t ble_enable_params; memset(&ble_enable_params, 0x00, sizeof(ble_enable_params)); ble_enable_params.gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT; ble_enable_params.gatts_enable_params.service_changed = 0; #else ble_cfg_t ble_conf; uint32_t app_ram_start_cfg = 0x200039c0; ble_conf.conn_cfg.conn_cfg_tag = BLE_DRV_CONN_CONFIG_TAG; ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = 2; ble_conf.conn_cfg.params.gap_conn_cfg.event_length = 3; err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_conf, app_ram_start_cfg); BLE_DRIVER_LOG("BLE_CONN_CFG_GAP status: " UINT_FMT "\n", (uint16_t)err_code); memset(&ble_conf, 0, sizeof(ble_conf)); ble_conf.gap_cfg.role_count_cfg.periph_role_count = 1; ble_conf.gap_cfg.role_count_cfg.central_role_count = 1; ble_conf.gap_cfg.role_count_cfg.central_sec_count = 0; err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_conf, app_ram_start_cfg); BLE_DRIVER_LOG("BLE_GAP_CFG_ROLE_COUNT status: " UINT_FMT "\n", (uint16_t)err_code); memset(&ble_conf, 0, sizeof(ble_conf)); ble_conf.conn_cfg.conn_cfg_tag = BLE_DRV_CONN_CONFIG_TAG; ble_conf.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = MAX_TX_IN_PROGRESS; err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_conf, app_ram_start_cfg); BLE_DRIVER_LOG("BLE_CONN_CFG_GATTS status: " UINT_FMT "\n", (uint16_t)err_code); #endif #if (BLUETOOTH_SD == 110) err_code = sd_ble_enable(&ble_enable_params); #else uint32_t app_ram_start = 0x200039c0; err_code = sd_ble_enable(&app_ram_start); // 8K SD headroom from linker script. BLE_DRIVER_LOG("BLE ram size: " UINT_FMT "\n", (uint16_t)app_ram_start); #endif BLE_DRIVER_LOG("BLE enable status: " UINT_FMT "\n", (uint16_t)err_code); // set up security mode ble_gap_conn_params_t gap_conn_params; ble_gap_conn_sec_mode_t sec_mode; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); const char device_name[] = "micr"; if ((err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)device_name, strlen(device_name))) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Cannot apply GAP parameters.")); } // set connection parameters memset(&gap_conn_params, 0, sizeof(gap_conn_params)); gap_conn_params.min_conn_interval = BLE_MIN_CONN_INTERVAL; gap_conn_params.max_conn_interval = BLE_MAX_CONN_INTERVAL; gap_conn_params.slave_latency = BLE_SLAVE_LATENCY; gap_conn_params.conn_sup_timeout = BLE_CONN_SUP_TIMEOUT; if (sd_ble_gap_ppcp_set(&gap_conn_params) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Cannot set PPCP parameters.")); } return err_code; } void ble_drv_stack_disable(void) { sd_softdevice_disable(); } uint8_t ble_drv_stack_enabled(void) { uint8_t is_enabled; uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); (void)err_code; BLE_DRIVER_LOG("Is enabled status: " UINT_FMT "\n", (uint16_t)err_code); return is_enabled; } void ble_drv_address_get(ble_drv_addr_t * p_addr) { SD_TEST_OR_ENABLE(); ble_gap_addr_t local_ble_addr; #if (BLUETOOTH_SD == 110) uint32_t err_code = sd_ble_gap_address_get(&local_ble_addr); #else uint32_t err_code = sd_ble_gap_addr_get(&local_ble_addr); #endif if (err_code != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not query for the device address.")); } BLE_DRIVER_LOG("ble address, type: " HEX2_FMT ", " \ "address: " HEX2_FMT ":" HEX2_FMT ":" HEX2_FMT ":" \ HEX2_FMT ":" HEX2_FMT ":" HEX2_FMT "\n", \ local_ble_addr.addr_type, \ local_ble_addr.addr[5], local_ble_addr.addr[4], local_ble_addr.addr[3], \ local_ble_addr.addr[2], local_ble_addr.addr[1], local_ble_addr.addr[0]); p_addr->addr_type = local_ble_addr.addr_type; memcpy(p_addr->addr, local_ble_addr.addr, 6); } bool ble_drv_uuid_add_vs(uint8_t * p_uuid, uint8_t * idx) { SD_TEST_OR_ENABLE(); if (sd_ble_uuid_vs_add((ble_uuid128_t const *)p_uuid, idx) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not add Vendor Specific 128-bit UUID.")); } return true; } bool ble_drv_service_add(ubluepy_service_obj_t * p_service_obj) { SD_TEST_OR_ENABLE(); if (p_service_obj->p_uuid->type > BLE_UUID_TYPE_BLE) { ble_uuid_t uuid; uuid.type = p_service_obj->p_uuid->uuid_vs_idx; uuid.uuid = p_service_obj->p_uuid->value[0]; uuid.uuid += p_service_obj->p_uuid->value[1] << 8; if (sd_ble_gatts_service_add(p_service_obj->type, &uuid, &p_service_obj->handle) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not add Service.")); } } else if (p_service_obj->p_uuid->type == BLE_UUID_TYPE_BLE) { BLE_DRIVER_LOG("adding service\n"); ble_uuid_t uuid; uuid.type = p_service_obj->p_uuid->type; uuid.uuid = p_service_obj->p_uuid->value[0]; uuid.uuid += p_service_obj->p_uuid->value[1] << 8; if (sd_ble_gatts_service_add(p_service_obj->type, &uuid, &p_service_obj->handle) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not add Service.")); } } return true; } bool ble_drv_characteristic_add(ubluepy_characteristic_obj_t * p_char_obj) { ble_gatts_char_md_t char_md; ble_gatts_attr_md_t cccd_md; ble_gatts_attr_t attr_char_value; ble_uuid_t uuid; ble_gatts_attr_md_t attr_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.broadcast = (p_char_obj->props & UBLUEPY_PROP_BROADCAST) ? 1 : 0; char_md.char_props.read = (p_char_obj->props & UBLUEPY_PROP_READ) ? 1 : 0; char_md.char_props.write_wo_resp = (p_char_obj->props & UBLUEPY_PROP_WRITE_WO_RESP) ? 1 : 0; char_md.char_props.write = (p_char_obj->props & UBLUEPY_PROP_WRITE) ? 1 : 0; char_md.char_props.notify = (p_char_obj->props & UBLUEPY_PROP_NOTIFY) ? 1 : 0; char_md.char_props.indicate = (p_char_obj->props & UBLUEPY_PROP_INDICATE) ? 1 : 0; #if 0 char_md.char_props.auth_signed_wr = (p_char_obj->props & UBLUEPY_PROP_NOTIFY) ? 1 : 0; #endif char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_sccd_md = NULL; // if cccd if (p_char_obj->attrs & UBLUEPY_ATTR_CCCD) { memset(&cccd_md, 0, sizeof(cccd_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); cccd_md.vloc = BLE_GATTS_VLOC_STACK; char_md.p_cccd_md = &cccd_md; } else { char_md.p_cccd_md = NULL; } uuid.type = p_char_obj->p_uuid->type; uuid.uuid = p_char_obj->p_uuid->value[0]; uuid.uuid += p_char_obj->p_uuid->value[1] << 8; memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_STACK; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 1; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = sizeof(uint8_t); attr_char_value.init_offs = 0; attr_char_value.max_len = (GATT_MTU_SIZE_DEFAULT - 3); ble_gatts_char_handles_t handles; if (sd_ble_gatts_characteristic_add(p_char_obj->service_handle, &char_md, &attr_char_value, &handles) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not add Characteristic.")); } // apply handles to object instance p_char_obj->handle = handles.value_handle; p_char_obj->user_desc_handle = handles.user_desc_handle; p_char_obj->cccd_handle = handles.cccd_handle; p_char_obj->sccd_handle = handles.sccd_handle; return true; } bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params) { SD_TEST_OR_ENABLE(); uint8_t byte_pos = 0; static uint8_t adv_data[BLE_GAP_ADV_MAX_SIZE]; if (p_adv_params->device_name_len > 0) { ble_gap_conn_sec_mode_t sec_mode; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); if (sd_ble_gap_device_name_set(&sec_mode, p_adv_params->p_device_name, p_adv_params->device_name_len) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not apply device name in the stack.")); } BLE_DRIVER_LOG("Device name applied\n"); adv_data[byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + p_adv_params->device_name_len); byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; adv_data[byte_pos] = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; memcpy(&adv_data[byte_pos], p_adv_params->p_device_name, p_adv_params->device_name_len); // increment position counter to see if it fits, and in case more content should // follow in this adv packet. byte_pos += p_adv_params->device_name_len; } // Add FLAGS only if manually controlled data has not been used. if (p_adv_params->data_len == 0) { // set flags, default to disc mode adv_data[byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + BLE_AD_TYPE_FLAGS_DATA_SIZE); byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; adv_data[byte_pos] = BLE_GAP_AD_TYPE_FLAGS; byte_pos += BLE_AD_TYPE_FLAGS_DATA_SIZE; adv_data[byte_pos] = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; byte_pos += 1; } if (p_adv_params->num_of_services > 0) { bool type_16bit_present = false; bool type_128bit_present = false; for (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)p_adv_params->p_services[i]; if (p_service->p_uuid->type == UBLUEPY_UUID_16_BIT) { type_16bit_present = true; } if (p_service->p_uuid->type == UBLUEPY_UUID_128_BIT) { type_128bit_present = true; } } if (type_16bit_present) { uint8_t size_byte_pos = byte_pos; // skip length byte for now, apply total length post calculation byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; adv_data[byte_pos] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE; byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; uint8_t uuid_total_size = 0; uint8_t encoded_size = 0; for (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)p_adv_params->p_services[i]; ble_uuid_t uuid; uuid.type = p_service->p_uuid->type; uuid.uuid = p_service->p_uuid->value[0]; uuid.uuid += p_service->p_uuid->value[1] << 8; // calculate total size of uuids if (sd_ble_uuid_encode(&uuid, &encoded_size, NULL) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not encode UUID, to check length.")); } // do encoding into the adv buffer if (sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can encode UUID into the advertisment packet.")); } BLE_DRIVER_LOG("encoded uuid for service %u: ", 0); for (uint8_t j = 0; j < encoded_size; j++) { BLE_DRIVER_LOG(HEX2_FMT " ", adv_data[byte_pos + j]); } BLE_DRIVER_LOG("\n"); uuid_total_size += encoded_size; // size of entry byte_pos += encoded_size; // relative to adv data packet BLE_DRIVER_LOG("ADV: uuid size: %u, type: %u, uuid: %x%x, vs_idx: %u\n", encoded_size, p_service->p_uuid->type, p_service->p_uuid->value[1], p_service->p_uuid->value[0], p_service->p_uuid->uuid_vs_idx); } adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); } if (type_128bit_present) { uint8_t size_byte_pos = byte_pos; // skip length byte for now, apply total length post calculation byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; adv_data[byte_pos] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE; byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; uint8_t uuid_total_size = 0; uint8_t encoded_size = 0; for (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)p_adv_params->p_services[i]; ble_uuid_t uuid; uuid.type = p_service->p_uuid->uuid_vs_idx; uuid.uuid = p_service->p_uuid->value[0]; uuid.uuid += p_service->p_uuid->value[1] << 8; // calculate total size of uuids if (sd_ble_uuid_encode(&uuid, &encoded_size, NULL) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not encode UUID, to check length.")); } // do encoding into the adv buffer if (sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can encode UUID into the advertisment packet.")); } BLE_DRIVER_LOG("encoded uuid for service %u: ", 0); for (uint8_t j = 0; j < encoded_size; j++) { BLE_DRIVER_LOG(HEX2_FMT " ", adv_data[byte_pos + j]); } BLE_DRIVER_LOG("\n"); uuid_total_size += encoded_size; // size of entry byte_pos += encoded_size; // relative to adv data packet BLE_DRIVER_LOG("ADV: uuid size: %u, type: %x%x, uuid: %u, vs_idx: %u\n", encoded_size, p_service->p_uuid->type, p_service->p_uuid->value[1], p_service->p_uuid->value[0], p_service->p_uuid->uuid_vs_idx); } adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); } } if ((p_adv_params->data_len > 0) && (p_adv_params->p_data != NULL)) { if (p_adv_params->data_len + byte_pos > BLE_GAP_ADV_MAX_SIZE) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not fit data into the advertisment packet.")); } memcpy(adv_data, p_adv_params->p_data, p_adv_params->data_len); byte_pos += p_adv_params->data_len; } // scan response data not set uint32_t err_code; #if (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) const ble_gap_adv_data_t m_adv_data = { .adv_data.p_data = adv_data, .adv_data.len = byte_pos, .scan_rsp_data.p_data = NULL, .scan_rsp_data.len = 0 }; #endif static ble_gap_adv_params_t m_adv_params; memset(&m_adv_params, 0, sizeof(m_adv_params)); // initialize advertising params if (p_adv_params->connectable) { #if (BLUETOOTH_SD == 110) m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; #else m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; #endif } else { #if (BLUETOOTH_SD == 110) m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND; #else m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED; #endif } #if (BLUETOOTH_SD == 110) m_adv_params.fp = BLE_GAP_ADV_FP_ANY; m_adv_params.timeout = 0; // infinite advertisment #else m_adv_params.properties.anonymous = 0; m_adv_params.properties.include_tx_power = 0; m_adv_params.filter_policy = 0; m_adv_params.max_adv_evts = 0; // infinite advertisment m_adv_params.primary_phy = BLE_GAP_PHY_AUTO; m_adv_params.secondary_phy = BLE_GAP_PHY_AUTO; m_adv_params.scan_req_notification = 0; // Do not raise scan request notifications when scanned. #endif m_adv_params.p_peer_addr = NULL; // undirected advertisement m_adv_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); // approx 8 ms #if (BLUETOOTH_SD == 110) if ((err_code = sd_ble_gap_adv_data_set(adv_data, byte_pos, NULL, 0)) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not apply advertisment data. status: 0x" HEX2_FMT, (uint16_t)err_code)); } #else if ((err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params)) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not apply advertisment data. status: 0x" HEX2_FMT, (uint16_t)err_code)); } #endif BLE_DRIVER_LOG("Set Adv data size: " UINT_FMT "\n", byte_pos); ble_drv_advertise_stop(); #if (BLUETOOTH_SD == 110) err_code = sd_ble_gap_adv_start(&m_adv_params); #else uint8_t conf_tag = BLE_DRV_CONN_CONFIG_TAG; // Could also be set to tag from sd_ble_cfg_set err_code = sd_ble_gap_adv_start(m_adv_handle, conf_tag); #endif if (err_code != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not start advertisment. status: 0x" HEX2_FMT, (uint16_t)err_code)); } m_adv_in_progress = true; return true; } void ble_drv_advertise_stop(void) { if (m_adv_in_progress == true) { uint32_t err_code; #if (BLUETOOTH_SD == 110) if ((err_code = sd_ble_gap_adv_stop()) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not stop advertisment. status: 0x" HEX2_FMT, (uint16_t)err_code)); } #else if ((err_code = sd_ble_gap_adv_stop(m_adv_handle)) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not stop advertisment. status: 0x" HEX2_FMT, (uint16_t)err_code)); } #endif } m_adv_in_progress = false; } void ble_drv_attr_s_read(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data) { ble_gatts_value_t gatts_value; memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = len; gatts_value.offset = 0; gatts_value.p_value = p_data; uint32_t err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value); if (err_code != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not read attribute value. status: 0x" HEX2_FMT, (uint16_t)err_code)); } } void ble_drv_attr_s_write(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data) { ble_gatts_value_t gatts_value; memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = len; gatts_value.offset = 0; gatts_value.p_value = p_data; uint32_t err_code = sd_ble_gatts_value_set(conn_handle, handle, &gatts_value); if (err_code != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not write attribute value. status: 0x" HEX2_FMT, (uint16_t)err_code)); } } void ble_drv_attr_s_notify(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data) { uint16_t hvx_len = len; ble_gatts_hvx_params_t hvx_params; memset(&hvx_params, 0, sizeof(hvx_params)); hvx_params.handle = handle; hvx_params.type = BLE_GATT_HVX_NOTIFICATION; hvx_params.offset = 0; hvx_params.p_len = &hvx_len; hvx_params.p_data = p_data; while (m_tx_in_progress > MAX_TX_IN_PROGRESS) { ; } BLE_DRIVER_LOG("Request TX, m_tx_in_progress: %u\n", m_tx_in_progress); uint32_t err_code; if ((err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params)) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not notify attribute value. status: 0x" HEX2_FMT, (uint16_t)err_code)); } m_tx_in_progress++; BLE_DRIVER_LOG("Queued TX, m_tx_in_progress: %u\n", m_tx_in_progress); } void ble_drv_gap_event_handler_set(mp_obj_t obj, ble_drv_gap_evt_callback_t evt_handler) { mp_gap_observer = obj; gap_event_handler = evt_handler; } void ble_drv_gatts_event_handler_set(mp_obj_t obj, ble_drv_gatts_evt_callback_t evt_handler) { mp_gatts_observer = obj; gatts_event_handler = evt_handler; } #if (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) void ble_drv_gattc_event_handler_set(mp_obj_t obj, ble_drv_gattc_evt_callback_t evt_handler) { mp_gattc_observer = obj; gattc_event_handler = evt_handler; } void ble_drv_adv_report_handler_set(mp_obj_t obj, ble_drv_adv_evt_callback_t evt_handler) { mp_adv_observer = obj; adv_event_handler = evt_handler; } void ble_drv_attr_c_read(uint16_t conn_handle, uint16_t handle, mp_obj_t obj, ble_drv_gattc_char_data_callback_t cb) { mp_gattc_char_data_observer = obj; gattc_char_data_handle = cb; uint32_t err_code = sd_ble_gattc_read(conn_handle, handle, 0); if (err_code != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not read attribute value. status: 0x" HEX2_FMT, (uint16_t)err_code)); } while (gattc_char_data_handle != NULL) { ; } } void ble_drv_attr_c_write(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data, bool w_response) { ble_gattc_write_params_t write_params; if (w_response) { write_params.write_op = BLE_GATT_OP_WRITE_REQ; } else { write_params.write_op = BLE_GATT_OP_WRITE_CMD; } write_params.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL; write_params.handle = handle; write_params.offset = 0; write_params.len = len; write_params.p_value = p_data; m_write_done = !w_response; uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params); if (err_code != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not write attribute value. status: 0x" HEX2_FMT, (uint16_t)err_code)); } while (m_write_done != true) { ; } } void ble_drv_scan_start(bool cont) { SD_TEST_OR_ENABLE(); ble_gap_scan_params_t scan_params; memset(&scan_params, 0, sizeof(ble_gap_scan_params_t)); scan_params.extended = 0; scan_params.active = 1; scan_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); scan_params.window = MSEC_TO_UNITS(100, UNIT_0_625_MS); scan_params.timeout = 0; // Infinite ble_data_t scan_buffer = { .p_data = m_scan_buffer, .len = BLE_GAP_SCAN_BUFFER_MIN }; uint32_t err_code; ble_gap_scan_params_t * p_scan_params = &scan_params; if (cont) { p_scan_params = NULL; } if ((err_code = sd_ble_gap_scan_start(p_scan_params, &scan_buffer)) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not start scanning. status: 0x" HEX2_FMT, (uint16_t)err_code)); } } void ble_drv_scan_stop(void) { sd_ble_gap_scan_stop(); } void ble_drv_connect(uint8_t * p_addr, uint8_t addr_type) { SD_TEST_OR_ENABLE(); ble_gap_scan_params_t scan_params; memset(&scan_params, 0, sizeof(ble_gap_scan_params_t)); scan_params.extended = 0; scan_params.active = 1; scan_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); scan_params.window = MSEC_TO_UNITS(100, UNIT_0_625_MS); scan_params.timeout = 0; // infinite ble_gap_addr_t addr; memset(&addr, 0, sizeof(addr)); addr.addr_type = addr_type; memcpy(addr.addr, p_addr, 6); BLE_DRIVER_LOG("GAP CONNECTING: "HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT", type: %d\n", addr.addr[0], addr.addr[1], addr.addr[2], addr.addr[3], addr.addr[4], addr.addr[5], addr.addr_type); ble_gap_conn_params_t conn_params; // set connection parameters memset(&conn_params, 0, sizeof(conn_params)); conn_params.min_conn_interval = BLE_MIN_CONN_INTERVAL; conn_params.max_conn_interval = BLE_MAX_CONN_INTERVAL; conn_params.slave_latency = BLE_SLAVE_LATENCY; conn_params.conn_sup_timeout = BLE_CONN_SUP_TIMEOUT; uint8_t conn_tag = BLE_DRV_CONN_CONFIG_TAG; uint32_t err_code; if ((err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, conn_tag)) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Can not connect. status: 0x" HEX2_FMT, (uint16_t)err_code)); } } bool ble_drv_discover_services(mp_obj_t obj, uint16_t conn_handle, uint16_t start_handle, ble_drv_disc_add_service_callback_t cb) { BLE_DRIVER_LOG("Discover primary services. Conn handle: 0x" HEX2_FMT "\n", conn_handle); mp_gattc_disc_service_observer = obj; disc_add_service_handler = cb; m_primary_service_found = false; uint32_t err_code; err_code = sd_ble_gattc_primary_services_discover(conn_handle, start_handle, NULL); if (err_code != 0) { return false; } // busy loop until last service has been iterated while (disc_add_service_handler != NULL) { ; } if (m_primary_service_found) { return true; } else { return false; } } bool ble_drv_discover_characteristic(mp_obj_t obj, uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, ble_drv_disc_add_char_callback_t cb) { BLE_DRIVER_LOG("Discover characteristicts. Conn handle: 0x" HEX2_FMT "\n", conn_handle); mp_gattc_disc_char_observer = obj; disc_add_char_handler = cb; ble_gattc_handle_range_t handle_range; handle_range.start_handle = start_handle; handle_range.end_handle = end_handle; m_characteristic_found = false; uint32_t err_code; err_code = sd_ble_gattc_characteristics_discover(conn_handle, &handle_range); if (err_code != 0) { return false; } // busy loop until last service has been iterated while (disc_add_char_handler != NULL) { ; } if (m_characteristic_found) { return true; } else { return false; } } void ble_drv_discover_descriptors(void) { } #endif // (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) static void sd_evt_handler(uint32_t evt_id) { switch (evt_id) { #if MICROPY_MBFS case NRF_EVT_FLASH_OPERATION_SUCCESS: flash_operation_finished(FLASH_STATE_SUCCESS); break; case NRF_EVT_FLASH_OPERATION_ERROR: flash_operation_finished(FLASH_STATE_ERROR); break; #endif default: // unhandled event! break; } #if MICROPY_HW_USB_CDC // Farward SOC events to USB CDC driver. usb_cdc_sd_event_handler(evt_id); #endif } static void ble_evt_handler(ble_evt_t * p_ble_evt) { // S132 event ranges. // Common 0x01 -> 0x0F // GAP 0x10 -> 0x2F // GATTC 0x30 -> 0x4F // GATTS 0x50 -> 0x6F // L2CAP 0x70 -> 0x8F switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: BLE_DRIVER_LOG("GAP CONNECT\n"); m_adv_in_progress = false; gap_event_handler(mp_gap_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); ble_gap_conn_params_t conn_params; (void)sd_ble_gap_ppcp_get(&conn_params); (void)sd_ble_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle, &conn_params); break; case BLE_GAP_EVT_DISCONNECTED: BLE_DRIVER_LOG("GAP DISCONNECT\n"); gap_event_handler(mp_gap_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); break; case BLE_GATTS_EVT_HVC: gatts_event_handler(mp_gatts_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gatts_evt.params.hvc.handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); break; case BLE_GATTS_EVT_WRITE: BLE_DRIVER_LOG("GATTS write\n"); uint16_t handle = p_ble_evt->evt.gatts_evt.params.write.handle; uint16_t data_len = p_ble_evt->evt.gatts_evt.params.write.len; uint8_t * p_data = &p_ble_evt->evt.gatts_evt.params.write.data[0]; gatts_event_handler(mp_gatts_observer, p_ble_evt->header.evt_id, handle, data_len, p_data); break; case BLE_GAP_EVT_CONN_PARAM_UPDATE: BLE_DRIVER_LOG("GAP CONN PARAM UPDATE\n"); break; case BLE_GATTS_EVT_SYS_ATTR_MISSING: // No system attributes have been stored. (void)sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0); break; #if (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) case BLE_GATTS_EVT_HVN_TX_COMPLETE: #else case BLE_EVT_TX_COMPLETE: #endif BLE_DRIVER_LOG("BLE EVT TX COMPLETE\n"); #if (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) BLE_DRIVER_LOG("HVN_TX_COMPLETE, count: %u\n", p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count); m_tx_in_progress -= p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count; BLE_DRIVER_LOG("TX_COMPLETE, m_tx_in_progress: %u\n", m_tx_in_progress); #else BLE_DRIVER_LOG("TX_COMPLETE, count: %u\n", p_ble_evt->evt.common_evt.params.tx_complete.count); m_tx_in_progress -= p_ble_evt->evt.common_evt.params.tx_complete.count; BLE_DRIVER_LOG("TX_COMPLETE, m_tx_in_progress: %u\n", m_tx_in_progress); #endif break; case BLE_GAP_EVT_SEC_PARAMS_REQUEST: BLE_DRIVER_LOG("BLE EVT SEC PARAMS REQUEST\n"); // pairing not supported (void)sd_ble_gap_sec_params_reply(p_ble_evt->evt.gatts_evt.conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); break; #if (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) case BLE_GAP_EVT_ADV_REPORT: BLE_DRIVER_LOG("BLE EVT ADV REPORT\n"); ble_drv_adv_data_t adv_data = { .p_peer_addr = p_ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr, .addr_type = p_ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr_type, .is_scan_resp = p_ble_evt->evt.gap_evt.params.adv_report.type.scan_response, .rssi = p_ble_evt->evt.gap_evt.params.adv_report.rssi, .data_len = p_ble_evt->evt.gap_evt.params.adv_report.data.len, .p_data = p_ble_evt->evt.gap_evt.params.adv_report.data.p_data, // .adv_type = }; // TODO: Fix unsafe callback to possible undefined callback... adv_event_handler(mp_adv_observer, p_ble_evt->header.evt_id, &adv_data); break; case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: BLE_DRIVER_LOG("BLE EVT CONN PARAM UPDATE REQUEST\n"); (void)sd_ble_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle, &p_ble_evt->evt.gap_evt.params.conn_param_update_request.conn_params); break; case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: BLE_DRIVER_LOG("BLE EVT PRIMARY SERVICE DISCOVERY RESPONSE\n"); BLE_DRIVER_LOG(">>> service count: %d\n", p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count); for (uint16_t i = 0; i < p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count; i++) { ble_gattc_service_t * p_service = &p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[i]; ble_drv_service_data_t service; service.uuid_type = p_service->uuid.type; service.uuid = p_service->uuid.uuid; service.start_handle = p_service->handle_range.start_handle; service.end_handle = p_service->handle_range.end_handle; disc_add_service_handler(mp_gattc_disc_service_observer, &service); } if (p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count > 0) { m_primary_service_found = true; } // mark end of service discovery disc_add_service_handler = NULL; break; case BLE_GATTC_EVT_CHAR_DISC_RSP: BLE_DRIVER_LOG("BLE EVT CHAR DISCOVERY RESPONSE\n"); BLE_DRIVER_LOG(">>> characteristic count: %d\n", p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count); for (uint16_t i = 0; i < p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count; i++) { ble_gattc_char_t * p_char = &p_ble_evt->evt.gattc_evt.params.char_disc_rsp.chars[i]; ble_drv_char_data_t char_data; char_data.uuid_type = p_char->uuid.type; char_data.uuid = p_char->uuid.uuid; char_data.decl_handle = p_char->handle_decl; char_data.value_handle = p_char->handle_value; char_data.props = (p_char->char_props.broadcast) ? UBLUEPY_PROP_BROADCAST : 0; char_data.props |= (p_char->char_props.read) ? UBLUEPY_PROP_READ : 0; char_data.props |= (p_char->char_props.write_wo_resp) ? UBLUEPY_PROP_WRITE_WO_RESP : 0; char_data.props |= (p_char->char_props.write) ? UBLUEPY_PROP_WRITE : 0; char_data.props |= (p_char->char_props.notify) ? UBLUEPY_PROP_NOTIFY : 0; char_data.props |= (p_char->char_props.indicate) ? UBLUEPY_PROP_INDICATE : 0; #if 0 char_data.props |= (p_char->char_props.auth_signed_wr) ? UBLUEPY_PROP_NOTIFY : 0; #endif disc_add_char_handler(mp_gattc_disc_char_observer, &char_data); } if (p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count > 0) { m_characteristic_found = true; } // mark end of characteristic discovery disc_add_char_handler = NULL; break; case BLE_GATTC_EVT_READ_RSP: BLE_DRIVER_LOG("BLE EVT READ RESPONSE, offset: 0x"HEX2_FMT", length: 0x"HEX2_FMT"\n", p_ble_evt->evt.gattc_evt.params.read_rsp.offset, p_ble_evt->evt.gattc_evt.params.read_rsp.len); gattc_char_data_handle(mp_gattc_char_data_observer, p_ble_evt->evt.gattc_evt.params.read_rsp.len, p_ble_evt->evt.gattc_evt.params.read_rsp.data); // mark end of read gattc_char_data_handle = NULL; break; case BLE_GATTC_EVT_WRITE_RSP: BLE_DRIVER_LOG("BLE EVT WRITE RESPONSE\n"); m_write_done = true; break; case BLE_GATTC_EVT_HVX: BLE_DRIVER_LOG("BLE EVT HVX RESPONSE\n"); break; case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: BLE_DRIVER_LOG("GATTS EVT EXCHANGE MTU REQUEST\n"); (void)sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, 23); // MAX MTU size break; #endif // (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140) default: BLE_DRIVER_LOG(">>> unhandled evt: 0x" HEX2_FMT "\n", p_ble_evt->header.evt_id); break; } } static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (GATT_MTU_SIZE_DEFAULT)] __attribute__ ((aligned (4))); #ifdef NRF51 void SWI2_IRQHandler(void) { #else void SWI2_EGU2_IRQHandler(void) { #endif uint32_t evt_id; while (sd_evt_get(&evt_id) != NRF_ERROR_NOT_FOUND) { sd_evt_handler(evt_id); } while (1) { uint16_t evt_len = sizeof(m_ble_evt_buf); uint32_t err_code = sd_ble_evt_get(m_ble_evt_buf, &evt_len); if (err_code != NRF_SUCCESS) { // Possible error conditions: // * NRF_ERROR_NOT_FOUND: no events left, break // * NRF_ERROR_DATA_SIZE: retry with a bigger data buffer // (currently not handled, TODO) // * NRF_ERROR_INVALID_ADDR: pointer is not aligned, should // not happen. // In all cases, it's best to simply stop now. if (err_code == NRF_ERROR_DATA_SIZE) { BLE_DRIVER_LOG("NRF_ERROR_DATA_SIZE\n"); } break; } ble_evt_handler((ble_evt_t *)m_ble_evt_buf); } } #endif // BLUETOOTH_SD micropython-1.12/ports/nrf/drivers/bluetooth/ble_drv.h000066400000000000000000000113351357706137100232320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef BLUETOOTH_LE_DRIVER_H__ #define BLUETOOTH_LE_DRIVER_H__ #if BLUETOOTH_SD #include #include #include "modubluepy.h" typedef struct { uint8_t addr[6]; uint8_t addr_type; } ble_drv_addr_t; typedef struct { uint8_t * p_peer_addr; uint8_t addr_type; bool is_scan_resp; int8_t rssi; uint8_t data_len; uint8_t * p_data; uint8_t adv_type; } ble_drv_adv_data_t; typedef struct { uint16_t uuid; uint8_t uuid_type; uint16_t start_handle; uint16_t end_handle; } ble_drv_service_data_t; typedef struct { uint16_t uuid; uint8_t uuid_type; uint8_t props; uint16_t decl_handle; uint16_t value_handle; } ble_drv_char_data_t; typedef void (*ble_drv_gap_evt_callback_t)(mp_obj_t self, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data); typedef void (*ble_drv_gatts_evt_callback_t)(mp_obj_t self, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data); typedef void (*ble_drv_gattc_evt_callback_t)(mp_obj_t self, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data); typedef void (*ble_drv_adv_evt_callback_t)(mp_obj_t self, uint16_t event_id, ble_drv_adv_data_t * data); typedef void (*ble_drv_disc_add_service_callback_t)(mp_obj_t self, ble_drv_service_data_t * p_service_data); typedef void (*ble_drv_disc_add_char_callback_t)(mp_obj_t self, ble_drv_char_data_t * p_desc_data); typedef void (*ble_drv_gattc_char_data_callback_t)(mp_obj_t self, uint16_t length, uint8_t * p_data); uint32_t ble_drv_stack_enable(void); void ble_drv_stack_disable(void); uint8_t ble_drv_stack_enabled(void); void ble_drv_address_get(ble_drv_addr_t * p_addr); bool ble_drv_uuid_add_vs(uint8_t * p_uuid, uint8_t * idx); bool ble_drv_service_add(ubluepy_service_obj_t * p_service_obj); bool ble_drv_characteristic_add(ubluepy_characteristic_obj_t * p_char_obj); bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params); void ble_drv_advertise_stop(void); void ble_drv_gap_event_handler_set(mp_obj_t obs, ble_drv_gap_evt_callback_t evt_handler); void ble_drv_gatts_event_handler_set(mp_obj_t obj, ble_drv_gatts_evt_callback_t evt_handler); void ble_drv_gattc_event_handler_set(mp_obj_t obj, ble_drv_gattc_evt_callback_t evt_handler); void ble_drv_attr_s_read(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data); void ble_drv_attr_c_read(uint16_t conn_handle, uint16_t handle, mp_obj_t obj, ble_drv_gattc_char_data_callback_t cb); void ble_drv_attr_s_write(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data); void ble_drv_attr_s_notify(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data); void ble_drv_attr_c_write(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data, bool w_response); void ble_drv_scan_start(bool cont); void ble_drv_scan_stop(void); void ble_drv_adv_report_handler_set(mp_obj_t obj, ble_drv_adv_evt_callback_t evt_handler); void ble_drv_connect(uint8_t * p_addr, uint8_t addr_type); bool ble_drv_discover_services(mp_obj_t obj, uint16_t conn_handle, uint16_t start_handle, ble_drv_disc_add_service_callback_t cb); bool ble_drv_discover_characteristic(mp_obj_t obj, uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, ble_drv_disc_add_char_callback_t cb); void ble_drv_discover_descriptors(void); #endif // BLUETOOTH_SD #endif // BLUETOOTH_LE_DRIVER_H__ micropython-1.12/ports/nrf/drivers/bluetooth/ble_uart.c000066400000000000000000000220131357706137100234000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #if BLUETOOTH_SD #include #include "ble_uart.h" #include "ringbuffer.h" #include "mphalport.h" #include "lib/utils/interrupt_char.h" #if MICROPY_PY_BLE_NUS static ubluepy_uuid_obj_t uuid_obj_service = { .base.type = &ubluepy_uuid_type, .type = UBLUEPY_UUID_128_BIT, .value = {0x01, 0x00} }; static ubluepy_uuid_obj_t uuid_obj_char_tx = { .base.type = &ubluepy_uuid_type, .type = UBLUEPY_UUID_128_BIT, .value = {0x03, 0x00} }; static ubluepy_uuid_obj_t uuid_obj_char_rx = { .base.type = &ubluepy_uuid_type, .type = UBLUEPY_UUID_128_BIT, .value = {0x02, 0x00} }; static ubluepy_service_obj_t ble_uart_service = { .base.type = &ubluepy_service_type, .p_uuid = &uuid_obj_service, .type = UBLUEPY_SERVICE_PRIMARY }; static ubluepy_characteristic_obj_t ble_uart_char_rx = { .base.type = &ubluepy_characteristic_type, .p_uuid = &uuid_obj_char_rx, .props = UBLUEPY_PROP_WRITE | UBLUEPY_PROP_WRITE_WO_RESP, .attrs = 0, }; static ubluepy_characteristic_obj_t ble_uart_char_tx = { .base.type = &ubluepy_characteristic_type, .p_uuid = &uuid_obj_char_tx, .props = UBLUEPY_PROP_NOTIFY, .attrs = UBLUEPY_ATTR_CCCD, }; static ubluepy_peripheral_obj_t ble_uart_peripheral = { .base.type = &ubluepy_peripheral_type, .conn_handle = 0xFFFF, }; static volatile bool m_cccd_enabled; static volatile bool m_connected; ringBuffer_typedef(uint8_t, ringbuffer_t); static ringbuffer_t m_rx_ring_buffer; static ringbuffer_t * mp_rx_ring_buffer = &m_rx_ring_buffer; static uint8_t m_rx_ring_buffer_data[128]; static ubluepy_advertise_data_t m_adv_data_uart_service; #if BLUETOOTH_WEBBLUETOOTH_REPL static ubluepy_advertise_data_t m_adv_data_eddystone_url; #endif // BLUETOOTH_WEBBLUETOOTH_REPL int mp_hal_stdin_rx_chr(void) { while (!ble_uart_enabled()) { // wait for connection } while (isBufferEmpty(mp_rx_ring_buffer)) { ; } uint8_t byte; bufferRead(mp_rx_ring_buffer, byte); return (int)byte; } void mp_hal_stdout_tx_strn(const char *str, size_t len) { // Not connected: drop output if (!ble_uart_enabled()) return; uint8_t *buf = (uint8_t *)str; size_t send_len; while (len > 0) { if (len >= 20) { send_len = 20; // (GATT_MTU_SIZE_DEFAULT - 3) } else { send_len = len; } ubluepy_characteristic_obj_t * p_char = &ble_uart_char_tx; ble_drv_attr_s_notify(p_char->p_service->p_periph->conn_handle, p_char->handle, send_len, buf); len -= send_len; buf += send_len; } } void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { mp_hal_stdout_tx_strn(str, len); } STATIC void gap_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data) { ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); if (event_id == 16) { // connect event self->conn_handle = conn_handle; m_connected = true; } else if (event_id == 17) { // disconnect event self->conn_handle = 0xFFFF; // invalid connection handle m_connected = false; m_cccd_enabled = false; ble_uart_advertise(); } } STATIC void gatts_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); (void)self; if (event_id == 80) { // gatts write if (ble_uart_char_tx.cccd_handle == attr_handle) { m_cccd_enabled = true; } else if (ble_uart_char_rx.handle == attr_handle) { for (uint16_t i = 0; i < length; i++) { #if MICROPY_KBD_EXCEPTION if (data[i] == mp_interrupt_char) { mp_keyboard_interrupt(); m_rx_ring_buffer.start = 0; m_rx_ring_buffer.end = 0; } else #endif { bufferWrite(mp_rx_ring_buffer, data[i]); } } } } } void ble_uart_init0(void) { uint8_t base_uuid[] = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}; uint8_t uuid_vs_idx; (void)ble_drv_uuid_add_vs(base_uuid, &uuid_vs_idx); uuid_obj_service.uuid_vs_idx = uuid_vs_idx; uuid_obj_char_tx.uuid_vs_idx = uuid_vs_idx; uuid_obj_char_rx.uuid_vs_idx = uuid_vs_idx; (void)ble_drv_service_add(&ble_uart_service); ble_uart_service.char_list = mp_obj_new_list(0, NULL); // add TX characteristic ble_uart_char_tx.service_handle = ble_uart_service.handle; bool retval = ble_drv_characteristic_add(&ble_uart_char_tx); if (retval) { ble_uart_char_tx.p_service = &ble_uart_service; } mp_obj_list_append(ble_uart_service.char_list, MP_OBJ_FROM_PTR(&ble_uart_char_tx)); // add RX characteristic ble_uart_char_rx.service_handle = ble_uart_service.handle; retval = ble_drv_characteristic_add(&ble_uart_char_rx); if (retval) { ble_uart_char_rx.p_service = &ble_uart_service; } mp_obj_list_append(ble_uart_service.char_list, MP_OBJ_FROM_PTR(&ble_uart_char_rx)); // setup the peripheral ble_uart_peripheral.service_list = mp_obj_new_list(0, NULL); mp_obj_list_append(ble_uart_peripheral.service_list, MP_OBJ_FROM_PTR(&ble_uart_service)); ble_uart_service.p_periph = &ble_uart_peripheral; ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(&ble_uart_peripheral), gap_event_handler); ble_drv_gatts_event_handler_set(MP_OBJ_FROM_PTR(&ble_uart_peripheral), gatts_event_handler); ble_uart_peripheral.conn_handle = 0xFFFF; char device_name[] = "mpus"; mp_obj_t service_list = mp_obj_new_list(0, NULL); mp_obj_list_append(service_list, MP_OBJ_FROM_PTR(&ble_uart_service)); mp_obj_t * services = NULL; mp_uint_t num_services; mp_obj_get_array(service_list, &num_services, &services); m_adv_data_uart_service.p_services = services; m_adv_data_uart_service.num_of_services = num_services; m_adv_data_uart_service.p_device_name = (uint8_t *)device_name; m_adv_data_uart_service.device_name_len = strlen(device_name); m_adv_data_uart_service.connectable = true; m_adv_data_uart_service.p_data = NULL; #if BLUETOOTH_WEBBLUETOOTH_REPL // for now point eddystone URL to https://goo.gl/F7fZ69 => https://aykevl.nl/apps/nus/ static uint8_t eddystone_url_data[27] = {0x2, 0x1, 0x6, 0x3, 0x3, 0xaa, 0xfe, 19, 0x16, 0xaa, 0xfe, 0x10, 0xee, 0x3, 'g', 'o', 'o', '.', 'g', 'l', '/', 'F', '7', 'f', 'Z', '6', '9'}; // eddystone url adv data m_adv_data_eddystone_url.p_data = eddystone_url_data; m_adv_data_eddystone_url.data_len = sizeof(eddystone_url_data); m_adv_data_eddystone_url.connectable = false; #endif m_cccd_enabled = false; // initialize ring buffer m_rx_ring_buffer.size = sizeof(m_rx_ring_buffer_data) + 1; m_rx_ring_buffer.start = 0; m_rx_ring_buffer.end = 0; m_rx_ring_buffer.elems = m_rx_ring_buffer_data; m_connected = false; ble_uart_advertise(); } void ble_uart_advertise(void) { #if BLUETOOTH_WEBBLUETOOTH_REPL while (!m_connected) { (void)ble_drv_advertise_data(&m_adv_data_uart_service); mp_hal_delay_ms(500); (void)ble_drv_advertise_data(&m_adv_data_eddystone_url); mp_hal_delay_ms(500); } ble_drv_advertise_stop(); #else (void)ble_drv_advertise_data(&m_adv_data_uart_service); #endif // BLUETOOTH_WEBBLUETOOTH_REPL } bool ble_uart_connected(void) { return (m_connected); } bool ble_uart_enabled(void) { return (m_cccd_enabled); } #endif // MICROPY_PY_BLE_NUS #endif // BLUETOOTH_SD micropython-1.12/ports/nrf/drivers/bluetooth/ble_uart.h000066400000000000000000000027671357706137100234230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef BLUETOOTH_LE_UART_H__ #define BLUETOOTH_LE_UART_H__ #if BLUETOOTH_SD #include "modubluepy.h" #include "ble_drv.h" void ble_uart_init0(void); void ble_uart_advertise(void); bool ble_uart_connected(void); bool ble_uart_enabled(void); #endif // BLUETOOTH_SD #endif // BLUETOOTH_LE_UART_H__ micropython-1.12/ports/nrf/drivers/bluetooth/bluetooth_common.mk000066400000000000000000000035711357706137100253550ustar00rootroot00000000000000 SOFTDEV_HEX_NAME ?= SOFTDEV_HEX_PATH ?= ifeq ($(SD), s110) INC += -Idrivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include CFLAGS += -DBLUETOOTH_SD_DEBUG=1 CFLAGS += -DBLUETOOTH_SD=110 else ifeq ($(SD), s132) INC += -Idrivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include INC += -Idrivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include/$(MCU_VARIANT) CFLAGS += -DBLUETOOTH_SD_DEBUG=1 CFLAGS += -DBLUETOOTH_SD=132 else ifeq ($(SD), s140) INC += -Idrivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include INC += -Idrivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include/$(MCU_VARIANT) CFLAGS += -DBLUETOOTH_SD_DEBUG=1 CFLAGS += -DBLUETOOTH_SD=140 else $(error Incorrect softdevice set flag) endif SOFTDEV_HEX_NAME = $(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_softdevice.hex SOFTDEV_HEX_PATH = drivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION) define STACK_MISSING_ERROR ###### ERROR: Bluetooth LE Stack not found ############ # # # The build target requires a Bluetooth LE stack. # # $(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION) Bluetooth LE stack not found. # # # # Please run the download script: # # # # drivers/bluetooth/download_ble_stack.sh # # # ####################################################### endef SOFTDEV_HEX = $(SOFTDEV_HEX_PATH)/$(SOFTDEV_HEX_NAME) ifeq ($(shell test ! -e $(SOFTDEV_HEX) && echo -n no),no) $(error $(STACK_MISSING_ERROR)) endif micropython-1.12/ports/nrf/drivers/bluetooth/download_ble_stack.sh000077500000000000000000000043541357706137100256240ustar00rootroot00000000000000#!/bin/bash function download_s110_nrf51_8_0_0 { echo "" echo "####################################" echo "### Downloading s110_nrf51_8.0.0 ###" echo "####################################" echo "" mkdir -p $1/s110_nrf51_8.0.0 cd $1/s110_nrf51_8.0.0 wget --post-data="fileName=DeviceDownload&ids=DBBEB2467E4A4EBCB791C2E7BE3FC7A8" https://www.nordicsemi.com/api/sitecore/Products/MedialibraryZipDownload2 mv MedialibraryZipDownload2 temp.zip unzip -u temp.zip unzip -u s110nrf51800.zip rm s110nrf51800.zip rm temp.zip cd - } function download_s132_nrf52_6_1_1 { echo "" echo "####################################" echo "### Downloading s132_nrf52_6.1.1 ###" echo "####################################" echo "" mkdir -p $1/s132_nrf52_6.1.1 cd $1/s132_nrf52_6.1.1 wget --post-data="fileName=DeviceDownload&ids=3AB3E86666FE4361A4A3B7E0D1CBB9B9" https://www.nordicsemi.com/api/sitecore/Products/MedialibraryZipDownload2 mv MedialibraryZipDownload2 temp.zip unzip -u temp.zip unzip -u s132nrf52611.zip rm s132nrf52611.zip rm temp.zip cd - } function download_s140_nrf52_6_1_1 { echo "" echo "####################################" echo "### Downloading s140_nrf52_6.1.1 ###" echo "####################################" echo "" mkdir -p $1/s140_nrf52_6.1.1 cd $1/s140_nrf52_6.1.1 wget --post-data="fileName=DeviceDownload&ids=CE89BA7633C540AFA48AB88E934DBF05" https://www.nordicsemi.com/api/sitecore/Products/MedialibraryZipDownload2 mv MedialibraryZipDownload2 temp.zip unzip -u temp.zip unzip -u s140nrf52611.zip rm s140nrf52611.zip rm temp.zip cd - } SCRIPT_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [ $# -eq 0 ]; then echo "No Bluetooth LE stack defined, downloading all." download_s110_nrf51_8_0_0 ${SCRIPT_DIR} download_s132_nrf52_6_1_1 ${SCRIPT_DIR} download_s140_nrf52_6_1_1 ${SCRIPT_DIR} else case $1 in "s110_nrf51" ) download_s110_nrf51_8_0_0 ${SCRIPT_DIR} ;; "s132_nrf52_6_1_1" ) download_s132_nrf52_6_1_1 ${SCRIPT_DIR} ;; "s140_nrf52_6_1_1" ) download_s140_nrf52_6_1_1 ${SCRIPT_DIR} ;; esac fi exit 0 micropython-1.12/ports/nrf/drivers/bluetooth/ringbuffer.h000066400000000000000000000060321357706137100237440ustar00rootroot00000000000000/* The MIT License (MIT) * * Copyright (c) 2013 Philip Thrasher * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Philip Thrasher's Crazy Awesome Ring Buffer Macros! * * Below you will find some naughty macros for easy owning and manipulating * generic ring buffers. Yes, they are slightly evil in readability, but they * are really fast, and they work great. * * Example usage: * * #include * * // So we can use this in any method, this gives us a typedef * // named 'intBuffer'. * ringBuffer_typedef(int, intBuffer); * * int main() { * // Declare vars. * intBuffer myBuffer; * * bufferInit(myBuffer,1024,int); * * // We must have the pointer. All of the macros deal with the pointer. * // (except for init.) * intBuffer* myBuffer_ptr; * myBuffer_ptr = &myBuffer; * * // Write two values. * bufferWrite(myBuffer_ptr,37); * bufferWrite(myBuffer_ptr,72); * * // Read a value into a local variable. * int first; * bufferRead(myBuffer_ptr,first); * assert(first == 37); // true * * int second; * bufferRead(myBuffer_ptr,second); * assert(second == 72); // true * * return 0; * } * */ #ifndef _ringbuffer_h #define _ringbuffer_h #define ringBuffer_typedef(T, NAME) \ typedef struct { \ int size; \ volatile int start; \ volatile int end; \ T* elems; \ } NAME #define bufferInit(BUF, S, T) \ BUF.size = S+1; \ BUF.start = 0; \ BUF.end = 0; \ BUF.elems = (T*)calloc(BUF.size, sizeof(T)) #define bufferDestroy(BUF) free(BUF->elems) #define nextStartIndex(BUF) ((BUF->start + 1) % BUF->size) #define nextEndIndex(BUF) ((BUF->end + 1) % BUF->size) #define isBufferEmpty(BUF) (BUF->end == BUF->start) #define isBufferFull(BUF) (nextEndIndex(BUF) == BUF->start) #define bufferWrite(BUF, ELEM) \ BUF->elems[BUF->end] = ELEM; \ BUF->end = (BUF->end + 1) % BUF->size; \ if (isBufferEmpty(BUF)) { \ BUF->start = nextStartIndex(BUF); \ } #define bufferRead(BUF, ELEM) \ ELEM = BUF->elems[BUF->start]; \ BUF->start = nextStartIndex(BUF); #endif micropython-1.12/ports/nrf/drivers/flash.c000066400000000000000000000102761357706137100207030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_MBFS && BLUETOOTH_SD #include "drivers/flash.h" #include "drivers/bluetooth/ble_drv.h" #include "nrf_soc.h" // Rotates bits in `value` left `shift` times. STATIC inline uint32_t rotate_left(uint32_t value, uint32_t shift) { return (value << shift) | (value >> (32 - shift)); } STATIC volatile flash_state_t flash_operation_state = FLASH_STATE_BUSY; STATIC void operation_init(void) { flash_operation_state = FLASH_STATE_BUSY; } void flash_operation_finished(flash_state_t result) { flash_operation_state = result; } STATIC bool operation_wait(uint32_t result) { if (ble_drv_stack_enabled() != 1) { // SoftDevice is not enabled, no event will be generated. return result == NRF_SUCCESS; } if (result != NRF_SUCCESS) { // In all other (non-success) cases, the command hasn't been // started and no event will be generated. return false; } // Wait until the event has been generated. while (flash_operation_state == FLASH_STATE_BUSY) { sd_app_evt_wait(); } // Now we can safely continue, flash operation has completed. return flash_operation_state == FLASH_STATE_SUCCESS; } void flash_write_byte(uint32_t address, uint8_t b) { uint32_t address_aligned = address & ~3; // Value to write - leave all bits that should not change at 0xff. uint32_t value = 0xffffff00 | b; // Rotate bits in value to an aligned position. value = rotate_left(value, (address & 3) * 8); while (1) { operation_init(); uint32_t result = sd_flash_write((uint32_t*)address_aligned, &value, 1); if (operation_wait(result)) break; } } void flash_page_erase(uint32_t pageaddr) { while (1) { operation_init(); uint32_t result = sd_flash_page_erase(pageaddr / FLASH_PAGESIZE); if (operation_wait(result)) break; } } void flash_write_bytes(uint32_t dst, const uint8_t *src, uint32_t num_bytes) { const uint8_t *src_end = src + num_bytes; // sd_flash_write does not accept unaligned addresses so we have to // work around that by writing all unaligned addresses byte-by-byte. // Write first bytes to align the write address. while (src != src_end && (dst & 0b11)) { flash_write_byte(dst, *src); dst++; src++; } // Write as many words as possible. // dst is now aligned, src possibly not. while (src_end - src >= 4) { uint8_t buf[4] __attribute__((aligned(4))); for (int i = 0; i < 4; i++) { buf[i] = ((uint8_t*)src)[i]; } operation_init(); uint32_t result = sd_flash_write((uint32_t*)dst, (const uint32_t*)&buf, 1); if (operation_wait(result)) { // If it is successfully written, go to the next word. src += 4; dst += 4; } } // Write remaining unaligned bytes. while (src != src_end) { flash_write_byte(dst, *src); dst++; src++; } } #endif // MICROPY_MBFS micropython-1.12/ports/nrf/drivers/flash.h000066400000000000000000000041761357706137100207120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __MICROPY_INCLUDED_LIB_FLASH_H__ #define __MICROPY_INCLUDED_LIB_FLASH_H__ #include "nrfx_nvmc.h" #if defined(NRF51) #define FLASH_PAGESIZE (1024) #elif defined(NRF52_SERIES) #define FLASH_PAGESIZE (4096) #elif defined(NRF91_SERIES) #define FLASH_PAGESIZE (4096) #else #error Unknown chip #endif #define FLASH_IS_PAGE_ALIGNED(addr) (((uint32_t)(addr) & (FLASH_PAGESIZE - 1)) == 0) #if BLUETOOTH_SD typedef enum { FLASH_STATE_BUSY, FLASH_STATE_SUCCESS, FLASH_STATE_ERROR, } flash_state_t; void flash_page_erase(uint32_t address); void flash_write_byte(uint32_t address, uint8_t value); void flash_write_bytes(uint32_t address, const uint8_t *src, uint32_t num_bytes); void flash_operation_finished(flash_state_t result); #else #define flash_page_erase nrfx_nvmc_page_erase #define flash_write_byte nrfx_nvmc_byte_write #define flash_write_bytes nrfx_nvmc_bytes_write #endif #endif // __MICROPY_INCLUDED_LIB_FLASH_H__ micropython-1.12/ports/nrf/drivers/secureboot/000077500000000000000000000000001357706137100216065ustar00rootroot00000000000000micropython-1.12/ports/nrf/drivers/secureboot/secureboot.mk000066400000000000000000000032541357706137100243150ustar00rootroot00000000000000DRIVERS_SECUREBOOT_DIR = drivers/secureboot SRC_SECUREBOOT += $(addprefix $(DRIVERS_SECUREBOOT_DIR)/,\ secureboot_main.c \ ) SRC_SECUREBOOT += $(addprefix device/,\ startup_nrf9160.c \ ) SRC_SECUREBOOT += $(addprefix $(TOP)/lib/nrfx/mdk/,\ system_nrf9160.c \ ) .PHONY: secureboot clean INC_SECUREBOOT += -I./../../lib/nrfx/mdk INC_SECUREBOOT += -I./../../lib/cmsis/inc MCU_SERIES = m33 CFLAGS_CORTEX_M = -mthumb -mabi=aapcs -fsingle-precision-constant -Wdouble-promotion CFLAGS_MCU_m33 = $(CFLAGS_CORTEX_M) -mcpu=cortex-m33 -march=armv8-m.main+dsp -mcmse -mfpu=fpv5-sp-d16 -mfloat-abi=hard CFLAGS_SECUREBOOT += -DNRF9160_XXAA CFLAGS_SECUREBOOT += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS_SECUREBOOT += -Wall -Werror -g -ansi -std=c11 -nostdlib $(COPT) CFLAGS_SECUREBOOT += -fno-strict-aliasing LD_FILES_SECUREBOOT += nrf9160_1M_256k_secure.ld common.ld LDFLAGS_SECUREBOOT = $(CFLAGS_SECUREBOOT) LDFLAGS_SECUREBOOT += -Xlinker -Map=$(@:.elf=.map) LDFLAGS_SECUREBOOT += -mthumb -mabi=aapcs $(addprefix -T,$(LD_FILES_SECUREBOOT)) -L ./boards CC = arm-none-eabi-gcc SIZE = arm-none-eabi-size OBJCOPY = arm-none-eabi-objcopy LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS_SECUREBOOT) -print-libgcc-file-name) LIBC_FILE_NAME = $(shell $(CC) $(CFLAGS_SECUREBOOT) -print-file-name=libc.a) LIBS_SECUREBOOT += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc LIBS_SECUREBOOT += -L $(dir $(LIBC_FILE_NAME)) -lc $(BUILD)/secureboot.elf: $(Q)$(CC) $(LDFLAGS_SECUREBOOT) $(SRC_SECUREBOOT) $(INC_SECUREBOOT) -O3 -o $@ $(LIBS_SECUREBOOT) $(SIZE) $@ $(BUILD)/secureboot.hex: $(BUILD)/secureboot.elf $(OBJCOPY) -O ihex $< $@ secureboot: $(BUILD)/secureboot.hex @echo "Secure boot" micropython-1.12/ports/nrf/drivers/secureboot/secureboot_main.c000066400000000000000000000167621357706137100251440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include // Secure flash 32K. #define SECURE_32K_FLASH_PAGE_START (0) #define SECURE_32K_FLASH_PAGE_END (0) // Non-secure flash 992K. #define NONSECURE_32K_FLASH_PAGE_START (1) #define NONSECURE_32K_FLASH_PAGE_END (31) // Secure RAM 64K. #define SECURE_8K_RAM_BLOCK_START (0) #define SECURE_8K_RAM_BLOCK_END (7) // Non-secure RAM 128K + 64K BSD lib. #define NONSECURE_8K_RAM_BLOCK_START (8) #define NONSECURE_8K_RAM_BLOCK_END (31) #define PERIPHERAL_ID_GET(base_addr) (((uint32_t)(base_addr) >> 12) & 0xFF) #if !defined(__ARM_FEATURE_CMSE) #pragma warning "CMSE not enabled" #endif static void configure_flash(void) { for (uint8_t i = SECURE_32K_FLASH_PAGE_START; i <= SECURE_32K_FLASH_PAGE_END; i++) { uint32_t perm = 0; perm |= (SPU_FLASHREGION_PERM_EXECUTE_Enable << SPU_FLASHREGION_PERM_EXECUTE_Pos); perm |= (SPU_FLASHREGION_PERM_WRITE_Enable << SPU_FLASHREGION_PERM_WRITE_Pos); perm |= (SPU_FLASHREGION_PERM_READ_Enable << SPU_FLASHREGION_PERM_READ_Pos); perm |= (SPU_FLASHREGION_PERM_LOCK_Locked << SPU_FLASHREGION_PERM_LOCK_Pos); perm |= (SPU_FLASHREGION_PERM_SECATTR_Secure << SPU_FLASHREGION_PERM_SECATTR_Pos); NRF_SPU_S->FLASHREGION[i].PERM = perm; } for (uint8_t i = NONSECURE_32K_FLASH_PAGE_START; i <= NONSECURE_32K_FLASH_PAGE_END; i++) { uint32_t perm = 0; perm |= (SPU_FLASHREGION_PERM_EXECUTE_Enable << SPU_FLASHREGION_PERM_EXECUTE_Pos); perm |= (SPU_FLASHREGION_PERM_WRITE_Enable << SPU_FLASHREGION_PERM_WRITE_Pos); perm |= (SPU_FLASHREGION_PERM_READ_Enable << SPU_FLASHREGION_PERM_READ_Pos); perm |= (SPU_FLASHREGION_PERM_LOCK_Locked << SPU_FLASHREGION_PERM_LOCK_Pos); perm |= (SPU_FLASHREGION_PERM_SECATTR_Non_Secure << SPU_FLASHREGION_PERM_SECATTR_Pos); NRF_SPU_S->FLASHREGION[i].PERM = perm; } } static void configure_ram(void) { for (uint8_t i = SECURE_8K_RAM_BLOCK_START; i <= SECURE_8K_RAM_BLOCK_END; i++) { uint32_t perm = 0; perm |= (SPU_RAMREGION_PERM_EXECUTE_Enable << SPU_RAMREGION_PERM_EXECUTE_Pos); perm |= (SPU_RAMREGION_PERM_WRITE_Enable << SPU_RAMREGION_PERM_WRITE_Pos); perm |= (SPU_RAMREGION_PERM_READ_Enable << SPU_RAMREGION_PERM_READ_Pos); perm |= (SPU_RAMREGION_PERM_LOCK_Locked << SPU_RAMREGION_PERM_LOCK_Pos); perm |= (SPU_RAMREGION_PERM_SECATTR_Secure << SPU_RAMREGION_PERM_SECATTR_Pos); NRF_SPU_S->RAMREGION[i].PERM = perm; } for (uint8_t i = NONSECURE_8K_RAM_BLOCK_START; i <= NONSECURE_8K_RAM_BLOCK_END; i++) { uint32_t perm = 0; perm |= (SPU_RAMREGION_PERM_EXECUTE_Enable << SPU_RAMREGION_PERM_EXECUTE_Pos); perm |= (SPU_RAMREGION_PERM_WRITE_Enable << SPU_RAMREGION_PERM_WRITE_Pos); perm |= (SPU_RAMREGION_PERM_READ_Enable << SPU_RAMREGION_PERM_READ_Pos); perm |= (SPU_RAMREGION_PERM_LOCK_Locked << SPU_RAMREGION_PERM_LOCK_Pos); perm |= (SPU_RAMREGION_PERM_SECATTR_Non_Secure << SPU_RAMREGION_PERM_SECATTR_Pos); NRF_SPU_S->RAMREGION[i].PERM = perm; } } static void peripheral_setup(uint8_t peripheral_id) { NVIC_DisableIRQ(peripheral_id); uint32_t perm = 0; perm |= (SPU_PERIPHID_PERM_PRESENT_IsPresent << SPU_PERIPHID_PERM_PRESENT_Pos); perm |= (SPU_PERIPHID_PERM_SECATTR_NonSecure << SPU_PERIPHID_PERM_SECATTR_Pos); perm |= (SPU_PERIPHID_PERM_LOCK_Locked << SPU_PERIPHID_PERM_LOCK_Pos); NRF_SPU_S->PERIPHID[peripheral_id].PERM = perm; NVIC_SetTargetState(peripheral_id); } static void configure_peripherals(void) { NRF_SPU_S->GPIOPORT[0].PERM = 0; peripheral_setup(PERIPHERAL_ID_GET(NRF_REGULATORS_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_CLOCK_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE0_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE2_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE3_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_SAADC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER0_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER2_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_RTC0_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_RTC1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_DPPIC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_WDT_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU2_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU3_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU4_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU5_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM0_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM2_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM3_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PDM_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_I2S_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_IPC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_FPU_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_GPIOTE1_NS)); peripheral_setup(PERIPHERAL_ID_GET(NRF_NVMC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_VMC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_P0_NS)); } typedef void __attribute__((cmse_nonsecure_call)) nsfunc(void); static void jump_to_non_secure(void) { TZ_SAU_Disable(); SAU->CTRL |= SAU_CTRL_ALLNS_Msk; // Set NS vector table. uint32_t * vtor_ns = (uint32_t *)0x8000; SCB_NS->VTOR = (uint32_t)vtor_ns; // Allow for FPU to be used by NS. SCB->NSACR |= (1UL << SCB_NSACR_CP10_Pos) | (1UL << SCB_NSACR_CP11_Pos); // Set stack pointers. __TZ_set_MSP_NS(vtor_ns[0]); __TZ_set_PSP_NS(0); uint32_t control_ns = __TZ_get_CONTROL_NS(); control_ns &= ~(CONTROL_SPSEL_Msk | CONTROL_nPRIV_Msk); __TZ_set_CONTROL_NS(control_ns); // Cast NS Reset_Handler to a non-secure function. nsfunc *fp = (nsfunc *)vtor_ns[1]; fp = (nsfunc *)((intptr_t)(fp) & ~1); if (cmse_is_nsfptr(fp)) { __DSB(); __ISB(); // Jump to Non-Secure function. fp(); } } int main(void) { configure_flash(); configure_ram(); configure_peripherals(); jump_to_non_secure(); while (1) { ; } return 0; } void _start(void) {main();} micropython-1.12/ports/nrf/drivers/softpwm.c000066400000000000000000000167441357706137100213130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Mark Shannon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mphal.h" #if MICROPY_PY_MACHINE_SOFT_PWM #include "stddef.h" #include "py/runtime.h" #include "py/gc.h" #include "nrf_timer.h" #include "nrf_gpio.h" #include "pin.h" #include "ticker.h" #define CYCLES_PER_MICROSECONDS 16 #define MICROSECONDS_PER_TICK 16 #define CYCLES_PER_TICK (CYCLES_PER_MICROSECONDS*MICROSECONDS_PER_TICK) // This must be an integer multiple of MICROSECONDS_PER_TICK #define MICROSECONDS_PER_MACRO_TICK 6000 #define MILLISECONDS_PER_MACRO_TICK 6 #define PWM_TICKER_INDEX 2 // Default period of 20ms #define DEFAULT_PERIOD ((20*1000)/MICROSECONDS_PER_TICK) typedef struct _pwm_event { uint16_t time; uint8_t pin; uint8_t turn_on; } pwm_event; typedef struct _pwm_events { uint8_t count; uint16_t period; uint32_t all_pins; pwm_event events[1]; } pwm_events; static const pwm_events OFF_EVENTS = { .count = 1, .period = DEFAULT_PERIOD, .all_pins = 0, .events = { { .time = 1024, .pin = 31, .turn_on = 0 } } }; #define active_events MP_STATE_PORT(pwm_active_events) #define pending_events MP_STATE_PORT(pwm_pending_events) void softpwm_init0(void) { active_events = &OFF_EVENTS; pending_events = NULL; } static uint8_t next_event = 0; static inline int32_t pwm_get_period_ticks(void) { const pwm_events *tmp = pending_events; if (tmp == NULL) tmp = active_events; return tmp->period; } #if 0 void pwm_dump_events(const pwm_events *events) { printf("Count %d, period %d, all pins %d\r\n", events->count, events->period, events->all_pins); for (uint32_t i = 0; i < events->count; i++) { const pwm_event *event = &events->events[i]; printf("Event. pin: %d, duty cycle: %d, turn_on: %d\r\n", event->pin, event->time, event->turn_on); } } void pwm_dump_state(void) { while(pending_events); pwm_dump_events(active_events); } #endif static const pwm_events *swap_pending(const pwm_events *in) { __disable_irq(); const pwm_events *result = pending_events; pending_events = in; __enable_irq(); return result; } static pwm_events *copy_events(const pwm_events *orig, uint32_t count) { pwm_events *events = m_malloc(sizeof(pwm_events) + (count-1)*sizeof(pwm_event)); events->count = count; uint32_t copy = count > orig->count ? orig->count : count; for (uint32_t i = 0; i < copy; i++) { events->events[i] = orig->events[i]; } return events; } static int find_pin_in_events(const pwm_events *events, uint32_t pin) { for (int i = 0; i < events->count; i++) { if (events->events[i].pin == pin) return i; } return -1; } static void sort_events(pwm_events *events) { // Insertion sort for (int32_t i = 1; i < events->count; i++) { pwm_event x = events->events[i]; int32_t j; for (j = i - 1; j >= 0 && events->events[j].time > x.time; j--) { events->events[j+1] = events->events[j]; } events->events[j+1] = x; } } int32_t pwm_callback(void) { int32_t tdiff; const pwm_events *events = active_events; const pwm_event *event = &events->events[next_event]; int32_t tnow = (event->time*events->period)>>10; do { if (event->turn_on) { nrf_gpio_pin_set(event->pin); next_event++; } else { // TODO: Resolve port for nrf52 nrf_gpio_port_out_clear(NRF_GPIO, events->all_pins); next_event = 0; tnow = 0; if (pending_events) { events = pending_events; active_events = events; pending_events = NULL; } } event = &events->events[next_event]; tdiff = ((event->time*events->period)>>10) - tnow; } while (tdiff == 0); return tdiff; } void pwm_start(void) { set_ticker_callback(PWM_TICKER_INDEX, pwm_callback, 120); } void pwm_stop(void) { clear_ticker_callback(PWM_TICKER_INDEX); } static void pwm_set_period_ticks(int32_t ticks) { const pwm_events *old_events = swap_pending(NULL); if (old_events == NULL) { old_events = active_events; } pwm_events *events = copy_events(old_events, old_events->count); events->all_pins = old_events->all_pins; events->period = ticks; pending_events = events; } int pwm_set_period_us(int32_t us) { if ((us < 256) || (us > 1000000)) { return -1; } pwm_set_period_ticks(us/MICROSECONDS_PER_TICK); return 0; } int32_t pwm_get_period_us(void) { return pwm_get_period_ticks()*MICROSECONDS_PER_TICK; } void pwm_set_duty_cycle(int32_t pin, uint32_t value) { if (value >= (1<<10)) { value = (1<<10)-1; } uint32_t turn_on_time = 1024-value; const pwm_events *old_events = swap_pending(NULL); if (old_events == NULL) { old_events = active_events; } if (((1<all_pins) == 0) { nrf_gpio_cfg_output(pin); } int ev = find_pin_in_events(old_events, pin); pwm_events *events; if (ev < 0 && value == 0) { return; } else if (ev < 0) { events = copy_events(old_events, old_events->count+1); events->all_pins = old_events->all_pins | (1<events[old_events->count].time = turn_on_time; events->events[old_events->count].pin = pin; events->events[old_events->count].turn_on = 1; } else if (value == 0) { events = copy_events(old_events, old_events->count-1); events->all_pins = old_events->all_pins & ~(1<count-1) { events->events[ev] = old_events->events[old_events->count-1]; } } else { events = copy_events(old_events, old_events->count); events->all_pins = old_events->all_pins; events->events[ev].time = turn_on_time; } events->period = old_events->period; sort_events(events); pending_events = events; return; } void pwm_release(int32_t pin) { pwm_set_duty_cycle(pin, 0); const pwm_events *ev = active_events; int i = find_pin_in_events(ev, pin); if (i < 0) return; // If i >= 0 it means that `ev` is in RAM, so it safe to discard the const qualifier ((pwm_events *)ev)->events[i].pin = 31; nrf_gpio_pin_clear(pin); } #endif // MICROPY_PY_MACHINE_SOFT_PWM micropython-1.12/ports/nrf/drivers/softpwm.h000066400000000000000000000034311357706137100213050ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2013-2016 The MicroPython-on-micro:bit Developers: * Damien P. George (@dpgeorge) * Nicholas H. Tollervey (@ntoll) * Matthew Else (@matthewelse) * Alan M. Jackson (@alanmjackson) * Mark Shannon (@markshannon) * Larry Hastings (@larryhastings) * Mariia Koroliuk (@marichkakorolyuk) * Andrew Mulholland (@gbaman) * Joe Glancy (@JoeGlancy) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __MICROPY_INCLUDED_LIB_PWM_H__ #define __MICROPY_INCLUDED_LIB_PWM_H__ void softpwm_init0(void); void pwm_start(void); void pwm_stop(void); int pwm_set_period_us(int32_t us); int32_t pwm_get_period_us(void); void pwm_set_duty_cycle(int32_t pin, int32_t value); void pwm_release(int32_t pin); #endif // __MICROPY_INCLUDED_LIB_PWM_H__ micropython-1.12/ports/nrf/drivers/ticker.c000066400000000000000000000120651357706137100210650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Mark Shannon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mphal.h" #if MICROPY_PY_MACHINE_SOFT_PWM #include "ticker.h" #include "nrfx_glue.h" #define FastTicker NRF_TIMER1 #define FastTicker_IRQn TIMER1_IRQn #define FastTicker_IRQHandler TIMER1_IRQHandler #define SlowTicker_IRQn SWI0_IRQn #define SlowTicker_IRQHandler SWI0_IRQHandler // Ticker callback function called every MACRO_TICK static volatile uint8_t m_num_of_slow_tickers = 0; static volatile callback_ptr m_slow_tickers[2] = {NULL, NULL}; void ticker_init0(void) { NRF_TIMER_Type *ticker = FastTicker; #ifdef NRF51 ticker->POWER = 1; #endif __NOP(); ticker_stop(); ticker->TASKS_CLEAR = 1; ticker->CC[3] = MICROSECONDS_PER_MACRO_TICK; ticker->MODE = TIMER_MODE_MODE_Timer; ticker->BITMODE = TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos; ticker->PRESCALER = 4; // 1 tick == 1 microsecond ticker->INTENSET = TIMER_INTENSET_COMPARE3_Msk; ticker->SHORTS = 0; #ifdef NRF51 NRFX_IRQ_PRIORITY_SET(FastTicker_IRQn, 1); #else NRFX_IRQ_PRIORITY_SET(FastTicker_IRQn, 2); #endif NRFX_IRQ_PRIORITY_SET(SlowTicker_IRQn, 3); NRFX_IRQ_ENABLE(SlowTicker_IRQn); } void ticker_register_low_pri_callback(callback_ptr slow_ticker_callback) { m_slow_tickers[m_num_of_slow_tickers++] = slow_ticker_callback; } /* Start and stop timer 1 including workarounds for Anomaly 73 for Timer * http://www.nordicsemi.com/eng/content/download/29490/494569/file/nRF51822-PAN%20v3.0.pdf */ void ticker_start(void) { NRFX_IRQ_ENABLE(FastTicker_IRQn); #ifdef NRF51 *(uint32_t *)0x40009C0C = 1; // for Timer 1 #endif FastTicker->TASKS_START = 1; } void ticker_stop(void) { NRFX_IRQ_DISABLE(FastTicker_IRQn); FastTicker->TASKS_STOP = 1; #ifdef NRF51 *(uint32_t *)0x40009C0C = 0; // for Timer 1 #endif } int32_t noop(void) { return -1; } volatile uint32_t ticks; static ticker_callback_ptr callbacks[3] = { noop, noop, noop }; void FastTicker_IRQHandler(void) { NRF_TIMER_Type *ticker = FastTicker; ticker_callback_ptr *call = callbacks; if (ticker->EVENTS_COMPARE[0]) { ticker->EVENTS_COMPARE[0] = 0; ticker->CC[0] += call[0]()*MICROSECONDS_PER_TICK; } if (ticker->EVENTS_COMPARE[1]) { ticker->EVENTS_COMPARE[1] = 0; ticker->CC[1] += call[1]()*MICROSECONDS_PER_TICK; } if (ticker->EVENTS_COMPARE[2]) { ticker->EVENTS_COMPARE[2] = 0; ticker->CC[2] += call[2]()*MICROSECONDS_PER_TICK; } if (ticker->EVENTS_COMPARE[3]) { ticker->EVENTS_COMPARE[3] = 0; ticker->CC[3] += MICROSECONDS_PER_MACRO_TICK; ticks += MILLISECONDS_PER_MACRO_TICK; NRFX_IRQ_PENDING_SET(SlowTicker_IRQn); } } static const uint32_t masks[3] = { TIMER_INTENCLR_COMPARE0_Msk, TIMER_INTENCLR_COMPARE1_Msk, TIMER_INTENCLR_COMPARE2_Msk, }; int set_ticker_callback(uint32_t index, ticker_callback_ptr func, int32_t initial_delay_us) { if (index > 3) return -1; NRF_TIMER_Type *ticker = FastTicker; callbacks[index] = noop; ticker->INTENCLR = masks[index]; ticker->TASKS_CAPTURE[index] = 1; uint32_t t = FastTicker->CC[index]; // Need to make sure that set tick is aligned to lastest tick // Use CC[3] as a reference, as that is always up-to-date. int32_t cc3 = FastTicker->CC[3]; int32_t delta = t+initial_delay_us-cc3; delta = (delta/MICROSECONDS_PER_TICK+1)*MICROSECONDS_PER_TICK; callbacks[index] = func; ticker->INTENSET = masks[index]; FastTicker->CC[index] = cc3 + delta; return 0; } int clear_ticker_callback(uint32_t index) { if (index > 3) return -1; FastTicker->INTENCLR = masks[index]; callbacks[index] = noop; return 0; } void SlowTicker_IRQHandler(void) { for (int i = 0; i < m_num_of_slow_tickers; i++) { if (m_slow_tickers[i] != NULL) { m_slow_tickers[i](); } } } #endif // MICROPY_PY_MACHINE_SOFT_PWM micropython-1.12/ports/nrf/drivers/ticker.h000066400000000000000000000045101357706137100210660ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2013-2016 The MicroPython-on-micro:bit Developers: * Damien P. George (@dpgeorge) * Nicholas H. Tollervey (@ntoll) * Matthew Else (@matthewelse) * Alan M. Jackson (@alanmjackson) * Mark Shannon (@markshannon) * Larry Hastings (@larryhastings) * Mariia Koroliuk (@marichkakorolyuk) * Andrew Mulholland (@gbaman) * Joe Glancy (@JoeGlancy) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __MICROPY_INCLUDED_LIB_TICKER_H__ #define __MICROPY_INCLUDED_LIB_TICKER_H__ /************************************* * 62.5kHz (16us cycle time) ticker. ************************************/ #include "nrf.h" typedef void (*callback_ptr)(void); typedef int32_t (*ticker_callback_ptr)(void); void ticker_init0(void); void ticker_start(void); void ticker_stop(void); int clear_ticker_callback(uint32_t index); int set_ticker_callback(uint32_t index, ticker_callback_ptr func, int32_t initial_delay_us); void ticker_register_low_pri_callback(callback_ptr callback); #define CYCLES_PER_MICROSECONDS 16 #define MICROSECONDS_PER_TICK 16 #define CYCLES_PER_TICK (CYCLES_PER_MICROSECONDS*MICROSECONDS_PER_TICK) // This must be an integer multiple of MICROSECONDS_PER_TICK #define MICROSECONDS_PER_MACRO_TICK 6000 #define MILLISECONDS_PER_MACRO_TICK 6 #endif // __MICROPY_INCLUDED_LIB_TICKER_H__ micropython-1.12/ports/nrf/drivers/usb/000077500000000000000000000000001357706137100202255ustar00rootroot00000000000000micropython-1.12/ports/nrf/drivers/usb/tusb_config.h000066400000000000000000000033371357706137100227060ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_NRF_TUSB_CONFIG_H #define MICROPY_INCLUDED_NRF_TUSB_CONFIG_H // Common configuration #define CFG_TUSB_MCU OPT_MCU_NRF5X #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #define CFG_TUSB_MEM_SECTION #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) // Device configuration #define CFG_TUD_ENDOINT0_SIZE (64) #define CFG_TUD_CDC (1) #define CFG_TUD_CDC_RX_BUFSIZE (64) #define CFG_TUD_CDC_TX_BUFSIZE (64) #endif // MICROPY_INCLUDED_NRF_TUSB_CONFIG_H micropython-1.12/ports/nrf/drivers/usb/usb_cdc.c000066400000000000000000000137341357706137100220030ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) * Copyright (c) 2019 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * This file is part of the TinyUSB stack. */ #include "py/mphal.h" #if MICROPY_HW_USB_CDC #include "tusb.h" #include "nrfx.h" #include "nrfx_power.h" #include "nrfx_uart.h" #include "py/ringbuf.h" #ifdef BLUETOOTH_SD #include "nrf_sdm.h" #include "nrf_soc.h" #include "ble_drv.h" #endif extern void tusb_hal_nrf_power_event(uint32_t event); static void cdc_task(void); static uint8_t rx_ringbuf_array[1024]; static uint8_t tx_ringbuf_array[1024]; static volatile ringbuf_t rx_ringbuf; static volatile ringbuf_t tx_ringbuf; static void board_init(void) { // Config clock source. #ifndef BLUETOOTH_SD NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk); NRF_CLOCK->TASKS_LFCLKSTART = 1UL; #endif // Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice // 2 is highest for application NRFX_IRQ_PRIORITY_SET(USBD_IRQn, 2); // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially uint32_t usb_reg; #ifdef BLUETOOTH_SD uint8_t sd_en = false; sd_softdevice_is_enabled(&sd_en); if (sd_en) { sd_power_usbdetected_enable(true); sd_power_usbpwrrdy_enable(true); sd_power_usbremoved_enable(true); sd_power_usbregstatus_get(&usb_reg); } else #endif { // Power module init const nrfx_power_config_t pwr_cfg = { 0 }; nrfx_power_init(&pwr_cfg); // Register tusb function as USB power handler const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event }; nrfx_power_usbevt_init(&config); nrfx_power_usbevt_enable(); usb_reg = NRF_POWER->USBREGSTATUS; } if (usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk) { tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); } #ifndef BLUETOOTH_SD if (usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk) { tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); } #endif } static bool cdc_rx_any(void) { return rx_ringbuf.iput != rx_ringbuf.iget; } static int cdc_rx_char(void) { return ringbuf_get((ringbuf_t*)&rx_ringbuf); } static bool cdc_tx_any(void) { return tx_ringbuf.iput != tx_ringbuf.iget; } static int cdc_tx_char(void) { return ringbuf_get((ringbuf_t*)&tx_ringbuf); } static void cdc_task(void) { if ( tud_cdc_connected() ) { // connected and there are data available while (tud_cdc_available()) { int c; uint32_t count = tud_cdc_read(&c, 1); (void)count; ringbuf_put((ringbuf_t*)&rx_ringbuf, c); } int chars = 0; while (cdc_tx_any()) { if (chars < 64) { tud_cdc_write_char(cdc_tx_char()); chars++; } else { chars = 0; tud_cdc_write_flush(); } } tud_cdc_write_flush(); } } static void usb_cdc_loop(void) { tud_task(); cdc_task(); } int usb_cdc_init(void) { static bool initialized = false; if (!initialized) { #if BLUETOOTH_SD // Initialize the clock and BLE stack. ble_drv_stack_enable(); #endif board_init(); initialized = true; } rx_ringbuf.buf = rx_ringbuf_array; rx_ringbuf.size = sizeof(rx_ringbuf_array); rx_ringbuf.iget = 0; rx_ringbuf.iput = 0; tx_ringbuf.buf = tx_ringbuf_array; tx_ringbuf.size = sizeof(tx_ringbuf_array); tx_ringbuf.iget = 0; tx_ringbuf.iput = 0; tusb_init(); return 0; } #ifdef BLUETOOTH_SD // process SOC event from SD void usb_cdc_sd_event_handler(uint32_t soc_evt) { /*------------- usb power event handler -------------*/ int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED ) ? NRFX_POWER_USB_EVT_DETECTED: (soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY : (soc_evt == NRF_EVT_POWER_USB_REMOVED ) ? NRFX_POWER_USB_EVT_REMOVED : -1; if (usbevt >= 0) { tusb_hal_nrf_power_event(usbevt); } } #endif int mp_hal_stdin_rx_chr(void) { for (;;) { usb_cdc_loop(); if (cdc_rx_any()) { return cdc_rx_char(); } } return 0; } void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { for (const char *top = str + len; str < top; str++) { ringbuf_put((ringbuf_t*)&tx_ringbuf, *str); usb_cdc_loop(); } } void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { for (const char *top = str + len; str < top; str++) { if (*str == '\n') { ringbuf_put((ringbuf_t*)&tx_ringbuf, '\r'); usb_cdc_loop(); } ringbuf_put((ringbuf_t*)&tx_ringbuf, *str); usb_cdc_loop(); } } #endif // MICROPY_HW_USB_CDC micropython-1.12/ports/nrf/drivers/usb/usb_cdc.h000066400000000000000000000027461357706137100220110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef NRF_DRIVERS_USB_CDC_H__ #define NRF_DRIVERS_USB_CDC_H__ #include "tusb.h" void usb_cdc_init(void); void usb_cdc_loop(void); int usb_cdc_read_char(void); void usb_cdc_write_char(char c); void usb_cdc_sd_event_handler(uint32_t soc_evt); #endif // NRF_DRIVERS_USB_CDC_H__ micropython-1.12/ports/nrf/drivers/usb/usb_descriptors.c000066400000000000000000000075061357706137100236130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "tusb.h" #define USBD_VID (0xf055) #define USBD_PID (0x9802) #define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) #define USBD_MAX_POWER_MA (250) #define USBD_ITF_CDC (0) // needs 2 interfaces #define USBD_ITF_MAX (2) #define USBD_CDC_EP_CMD (0x81) #define USBD_CDC_EP_OUT (0x02) #define USBD_CDC_EP_IN (0x82) #define USBD_CDC_CMD_MAX_SIZE (8) #define USBD_STR_0 (0x00) #define USBD_STR_MANUF (0x01) #define USBD_STR_PRODUCT (0x02) #define USBD_STR_SERIAL (0x03) #define USBD_STR_CDC (0x04) // Note: descriptors returned from callbacks must exist long enough for transfer to complete static const tusb_desc_device_t usbd_desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, .idVendor = USBD_VID, .idProduct = USBD_PID, .bcdDevice = 0x0100, .iManufacturer = USBD_STR_MANUF, .iProduct = USBD_STR_PRODUCT, .iSerialNumber = USBD_STR_SERIAL, .bNumConfigurations = 1, }; static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { TUD_CONFIG_DESCRIPTOR(USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, CFG_TUD_CDC_RX_BUFSIZE), }; static const char *const usbd_desc_str[] = { [USBD_STR_MANUF] = "MicroPython", [USBD_STR_PRODUCT] = "Board in FS mode", [USBD_STR_SERIAL] = "000000000000", // TODO [USBD_STR_CDC] = "Board CDC", }; const uint8_t *tud_descriptor_device_cb(void) { return (const uint8_t*)&usbd_desc_device; } const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { (void)index; return usbd_desc_cfg; } const uint16_t *tud_descriptor_string_cb(uint8_t index) { #define DESC_STR_MAX (20) static uint16_t desc_str[DESC_STR_MAX]; uint8_t len; if (index == 0) { desc_str[1] = 0x0409; // supported language is English len = 1; } else { if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { return NULL; } const char* str = usbd_desc_str[index]; for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { desc_str[1 + len] = str[len]; } } // first byte is len, second byte is string type desc_str[0] = TUD_DESC_STR_HEADER(len); return desc_str; } micropython-1.12/ports/nrf/examples/000077500000000000000000000000001357706137100175745ustar00rootroot00000000000000micropython-1.12/ports/nrf/examples/mountsd.py000066400000000000000000000014571357706137100216460ustar00rootroot00000000000000""" Example for pca10040 / nrf52832 to show how mount and list a sdcard connected over SPI. Direct wireing on SD card (SPI): ______________________________ | \ | 9. | NC | \ | 1. | ~CS | | | 2. | MOSI | | | 3. | GND | | | 4. | VCC3.3| | | 5. | SCK | | | 6. | GND | | | 7. | MISO | | | 8. | NC | | | | --------------------------------- """ import os from machine import SPI, Pin from sdcard import SDCard def mnt(): cs = Pin("P22", mode=Pin.OUT) sd = SDCard(SPI(0), cs) os.mount(sd, '/') def list(): files = os.listdir() print(files) micropython-1.12/ports/nrf/examples/musictest.py000066400000000000000000000003431357706137100221660ustar00rootroot00000000000000# # Example usage where "P3" is the Buzzer pin. # # from musictest import play # play("P3") # from machine import Pin import music def play(pin_str): p = Pin(pin_str, mode=Pin.OUT) music.play(music.PRELUDE, pin=p) micropython-1.12/ports/nrf/examples/nrf52_pwm.py000066400000000000000000000006401357706137100217650ustar00rootroot00000000000000import time from machine import PWM, Pin def pulse(): for i in range(0, 101): p = PWM(0, Pin("P17", mode=Pin.OUT), freq=PWM.FREQ_16MHZ, duty=i, period=16000) p.init() time.sleep_ms(10) p.deinit() for i in range(0, 101): p = PWM(0, Pin("P17", mode=Pin.OUT), freq=PWM.FREQ_16MHZ, duty=100-i, period=16000) p.init() time.sleep_ms(10) p.deinit() micropython-1.12/ports/nrf/examples/nrf52_servo.py000066400000000000000000000040011357706137100223130ustar00rootroot00000000000000# This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2017 Glenn Ruben Bakke # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE import time from machine import PWM, Pin class Servo(): def __init__(self, pin_name=""): if pin_name: self.pin = Pin(pin_name, mode=Pin.OUT, pull=Pin.PULL_DOWN) else: self.pin = Pin("P22", mode=Pin.OUT, pull=Pin.PULL_DOWN) def left(self): p = PWM(0, self.pin, freq=PWM.FREQ_125KHZ, pulse_width=105, period=2500, mode=PWM.MODE_HIGH_LOW) p.init() time.sleep_ms(200) p.deinit() def center(self): p = PWM(0, self.pin, freq=PWM.FREQ_125KHZ, pulse_width=188, period=2500, mode=PWM.MODE_HIGH_LOW) p.init() time.sleep_ms(200) p.deinit() def right(self): p = PWM(0, self.pin, freq=PWM.FREQ_125KHZ, pulse_width=275, period=2500, mode=PWM.MODE_HIGH_LOW) p.init() time.sleep_ms(200) p.deinit() micropython-1.12/ports/nrf/examples/powerup.py000066400000000000000000000145771357706137100216650ustar00rootroot00000000000000# This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2017 Glenn Ruben Bakke # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE # MicroPython controller for PowerUp 3.0 paper airplane # https://www.poweruptoys.com/products/powerup-v3 # # Examples is written for nrf52832, pca10040 using s132 bluetooth stack. # # Joystick shield pin mapping: # - analog stick x-direction - ADC0 - P0.02/"P2" # - buttons P0.13 - P0.16 / "P13", "P14", "P15", "P16" # # Example usage: # # from powerup import PowerUp3 # p = PowerUp3() import time from machine import ADC from machine import Pin from ubluepy import Peripheral, Scanner, constants def bytes_to_str(bytes): string = "" for b in bytes: string += chr(b) return string def get_device_names(scan_entries): dev_names = [] for e in scan_entries: scan = e.getScanData() if scan: for s in scan: if s[0] == constants.ad_types.AD_TYPE_COMPLETE_LOCAL_NAME: dev_names.append((e, bytes_to_str(s[2]))) return dev_names def find_device_by_name(name): s = Scanner() scan_res = s.scan(500) device_names = get_device_names(scan_res) for dev in device_names: if name == dev[1]: return dev[0] class PowerUp3: def __init__(self): self.x_adc = ADC(1) self.btn_speed_up = Pin("P13", mode=Pin.IN, pull=Pin.PULL_UP) self.btn_speed_down = Pin("P15", mode=Pin.IN, pull=Pin.PULL_UP) self.btn_speed_full = Pin("P14", mode=Pin.IN, pull=Pin.PULL_UP) self.btn_speed_off = Pin("P16", mode=Pin.IN, pull=Pin.PULL_UP) self.x_mid = 0 self.calibrate() self.connect() self.loop() def read_stick_x(self): return self.x_adc.value() def button_speed_up(self): return not bool(self.btn_speed_up.value()) def button_speed_down(self): return not bool(self.btn_speed_down.value()) def button_speed_full(self): return not bool(self.btn_speed_full.value()) def button_speed_off(self): return not bool(self.btn_speed_off.value()) def calibrate(self): self.x_mid = self.read_stick_x() def __str__(self): return "calibration x: %i, y: %i" % (self.x_mid) def map_chars(self): s = self.p.getServices() service_batt = s[3] service_control = s[4] self.char_batt_lvl = service_batt.getCharacteristics()[0] self.char_control_speed = service_control.getCharacteristics()[0] self.char_control_angle = service_control.getCharacteristics()[2] def battery_level(self): return int(self.char_batt_lvl.read()[0]) def speed(self, new_speed=None): if new_speed == None: return int(self.char_control_speed.read()[0]) else: self.char_control_speed.write(bytearray([new_speed])) def angle(self, new_angle=None): if new_angle == None: return int(self.char_control_angle.read()[0]) else: self.char_control_angle.write(bytearray([new_angle])) def connect(self): dev = None # connect to the airplane while not dev: dev = find_device_by_name("TailorToys PowerUp") if dev: self.p = Peripheral() self.p.connect(dev.addr()) # locate interesting characteristics self.map_chars() def rudder_center(self): if self.old_angle != 0: self.old_angle = 0 self.angle(0) def rudder_left(self, angle): steps = (angle // self.interval_size_left) new_angle = 60 - steps if self.old_angle != new_angle: self.angle(new_angle) self.old_angle = new_angle def rudder_right(self, angle): steps = (angle // self.interval_size_right) new_angle = -steps if self.old_angle != new_angle: self.angle(new_angle) self.old_angle = new_angle def throttle(self, speed): if (speed > 200): speed = 200 elif (speed < 0): speed = 0 if self.old_speed != speed: self.speed(speed) self.old_speed = speed def loop(self): adc_threshold = 10 right_threshold = self.x_mid + adc_threshold left_threshold = self.x_mid - adc_threshold self.interval_size_left = self.x_mid // 60 self.interval_size_right = (255 - self.x_mid) // 60 self.old_angle = 0 self.old_speed = 0 while True: time.sleep_ms(100) # read out new angle new_angle = self.read_stick_x() if (new_angle < 256): if (new_angle > right_threshold): self.rudder_right(new_angle - self.x_mid) elif (new_angle < left_threshold): self.rudder_left(new_angle) else: self.rudder_center() # read out new speed new_speed = self.old_speed if self.button_speed_up(): new_speed += 25 elif self.button_speed_down(): new_speed -= 25 elif self.button_speed_full(): new_speed = 200 elif self.button_speed_off(): new_speed = 0 else: pass self.throttle(new_speed) micropython-1.12/ports/nrf/examples/seeed_tft.py000066400000000000000000000141351357706137100221140ustar00rootroot00000000000000# This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2016 Glenn Ruben Bakke # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ MicroPython Seeedstudio TFT Shield V2 driver, SPI interfaces, Analog GPIO Contains SD-card reader, LCD and Touch sensor The pca10040 pin layout is used as reference. Example usage of LCD: from seeedstudio_tft_shield_v2 import ILI9341 lcd = ILI9341(240, 320) lcd.text("Hello World!, 32, 32) lcd.show() Example usage of SD card reader: import os from seeedstudio_tft_shield_v2 import mount_tf tf = mount_tf() os.listdir() """ import os import time import framebuf from machine import SPI, Pin from sdcard import SDCard def mount_tf(self, mount_point="/"): sd = SDCard(SPI(0), Pin("P15", mode=Pin.OUT)) os.mount(sd, mount_point) class ILI9341: def __init__(self, width, height): self.width = width self.height = height self.pages = self.height // 8 self.buffer = bytearray(self.pages * self.width) self.framebuf = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MONO_VLSB) self.spi = SPI(0) # chip select self.cs = Pin("P16", mode=Pin.OUT, pull=Pin.PULL_UP) # command self.dc = Pin("P17", mode=Pin.OUT, pull=Pin.PULL_UP) # initialize all pins high self.cs.high() self.dc.high() self.spi.init(baudrate=8000000, phase=0, polarity=0) self.init_display() def init_display(self): time.sleep_ms(500) self.write_cmd(0x01) time.sleep_ms(200) self.write_cmd(0xCF) self.write_data(bytearray([0x00, 0x8B, 0x30])) self.write_cmd(0xED) self.write_data(bytearray([0x67, 0x03, 0x12, 0x81])) self.write_cmd(0xE8) self.write_data(bytearray([0x85, 0x10, 0x7A])) self.write_cmd(0xCB) self.write_data(bytearray([0x39, 0x2C, 0x00, 0x34, 0x02])) self.write_cmd(0xF7) self.write_data(bytearray([0x20])) self.write_cmd(0xEA) self.write_data(bytearray([0x00, 0x00])) # Power control self.write_cmd(0xC0) # VRH[5:0] self.write_data(bytearray([0x1B])) # Power control self.write_cmd(0xC1) # SAP[2:0];BT[3:0] self.write_data(bytearray([0x10])) # VCM control self.write_cmd(0xC5) self.write_data(bytearray([0x3F, 0x3C])) # VCM control2 self.write_cmd(0xC7) self.write_data(bytearray([0xB7])) # Memory Access Control self.write_cmd(0x36) self.write_data(bytearray([0x08])) self.write_cmd(0x3A) self.write_data(bytearray([0x55])) self.write_cmd(0xB1) self.write_data(bytearray([0x00, 0x1B])) # Display Function Control self.write_cmd(0xB6) self.write_data(bytearray([0x0A, 0xA2])) # 3Gamma Function Disable self.write_cmd(0xF2) self.write_data(bytearray([0x00])) # Gamma curve selected self.write_cmd(0x26) self.write_data(bytearray([0x01])) # Set Gamma self.write_cmd(0xE0) self.write_data(bytearray([0x0F, 0x2A, 0x28, 0x08, 0x0E, 0x08, 0x54, 0XA9, 0x43, 0x0A, 0x0F, 0x00, 0x00, 0x00, 0x00])) # Set Gamma self.write_cmd(0XE1) self.write_data(bytearray([0x00, 0x15, 0x17, 0x07, 0x11, 0x06, 0x2B, 0x56, 0x3C, 0x05, 0x10, 0x0F, 0x3F, 0x3F, 0x0F])) # Exit Sleep self.write_cmd(0x11) time.sleep_ms(120) # Display on self.write_cmd(0x29) time.sleep_ms(500) self.fill(0) def show(self): # set col self.write_cmd(0x2A) self.write_data(bytearray([0x00, 0x00])) self.write_data(bytearray([0x00, 0xef])) # set page self.write_cmd(0x2B) self.write_data(bytearray([0x00, 0x00])) self.write_data(bytearray([0x01, 0x3f])) self.write_cmd(0x2c); num_of_pixels = self.height * self.width for row in range(0, self.pages): for pixel_pos in range(0, 8): for col in range(0, self.width): compressed_pixel = self.buffer[row * 240 + col] if ((compressed_pixel >> pixel_pos) & 0x1) == 0: self.write_data(bytearray([0x00, 0x00])) else: self.write_data(bytearray([0xFF, 0xFF])) def fill(self, col): self.framebuf.fill(col) def pixel(self, x, y, col): self.framebuf.pixel(x, y, col) def scroll(self, dx, dy): self.framebuf.scroll(dx, dy) def text(self, string, x, y, col=1): self.framebuf.text(string, x, y, col) def write_cmd(self, cmd): self.dc.low() self.cs.low() self.spi.write(bytearray([cmd])) self.cs.high() def write_data(self, buf): self.dc.high() self.cs.low() self.spi.write(buf) self.cs.high() micropython-1.12/ports/nrf/examples/ssd1306_mod.py000066400000000000000000000030671357706137100221160ustar00rootroot00000000000000# NOTE: Modified version to align with implemented I2C API in nrf port. # # Examples usage of SSD1306_SPI on pca10040 # # from machine import Pin, SPI # from ssd1306 import SSD1306_SPI # spi = SPI(0, baudrate=40000000) # dc = Pin.board.PA11 # res = Pin.board.PA12 # cs = Pin.board.PA13 # disp = SSD1306_SPI(128, 64, spi, dc, res, cs) # # # Example usage of SSD1306_I2C on pca10040 # # from machine import Pin, I2C # from ssd1306_mod import SSD1306_I2C_Mod # i2c = I2C(0, Pin.board.PA3, Pin.board.PA4) # disp = SSD1306_I2C_Mod(128, 64, i2c) from ssd1306 import SSD1306_I2C SET_COL_ADDR = const(0x21) SET_PAGE_ADDR = const(0x22) class SSD1306_I2C_Mod(SSD1306_I2C): def show(self): x0 = 0 x1 = self.width - 1 if self.width == 64: # displays with width of 64 pixels are shifted by 32 x0 += 32 x1 += 32 self.write_cmd(SET_COL_ADDR) self.write_cmd(x0) self.write_cmd(x1) self.write_cmd(SET_PAGE_ADDR) self.write_cmd(0) self.write_cmd(self.pages - 1) chunk_size = 254 # 255, excluding opcode. num_of_chunks = len(self.buffer) // chunk_size leftover = len(self.buffer) - (num_of_chunks * chunk_size) for i in range(0, num_of_chunks): self.write_data(self.buffer[chunk_size*i:chunk_size*(i+1)]) if (leftover > 0): self.write_data(self.buffer[chunk_size * num_of_chunks:]) def write_data(self, buf): buffer = bytearray([0x40]) + buf # Co=0, D/C#=1 self.i2c.writeto(self.addr, buffer) micropython-1.12/ports/nrf/examples/ubluepy_eddystone.py000066400000000000000000000036541357706137100237210ustar00rootroot00000000000000from ubluepy import Peripheral, constants BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE = const(0x02) BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED = const(0x04) BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE = const(BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) EDDYSTONE_FRAME_TYPE_URL = const(0x10) EDDYSTONE_URL_PREFIX_HTTP_WWW = const(0x00) # "http://www". EDDYSTONE_URL_SUFFIX_DOT_COM = const(0x01) # ".com" def string_to_binarray(text): b = bytearray([]) for c in text: b.append(ord(c)) return b def gen_ad_type_content(ad_type, data): b = bytearray(1) b.append(ad_type) b.extend(data) b[0] = len(b) - 1 return b def generate_eddystone_adv_packet(url): # flags disc_mode = bytearray([BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE]) packet_flags = gen_ad_type_content(constants.ad_types.AD_TYPE_FLAGS, disc_mode) # 16-bit uuid uuid = bytearray([0xAA, 0xFE]) packet_uuid16 = gen_ad_type_content(constants.ad_types.AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, uuid) # eddystone data rssi = 0xEE # -18 dB, approx signal strength at 0m. eddystone_data = bytearray([]) eddystone_data.append(EDDYSTONE_FRAME_TYPE_URL) eddystone_data.append(rssi) eddystone_data.append(EDDYSTONE_URL_PREFIX_HTTP_WWW) eddystone_data.extend(string_to_binarray(url)) eddystone_data.append(EDDYSTONE_URL_SUFFIX_DOT_COM) # service data service_data = uuid + eddystone_data packet_service_data = gen_ad_type_content(constants.ad_types.AD_TYPE_SERVICE_DATA, service_data) # generate advertisment packet packet = bytearray([]) packet.extend(packet_flags) packet.extend(packet_uuid16) packet.extend(packet_service_data) return packet def start(): adv_packet = generate_eddystone_adv_packet("micropython") p = Peripheral() p.advertise(data=adv_packet, connectable=False)micropython-1.12/ports/nrf/examples/ubluepy_scan.py000066400000000000000000000016521357706137100226430ustar00rootroot00000000000000from ubluepy import Scanner, constants def bytes_to_str(bytes): string = "" for b in bytes: string += chr(b) return string def get_device_names(scan_entries): dev_names = [] for e in scan_entries: scan = e.getScanData() if scan: for s in scan: if s[0] == constants.ad_types.AD_TYPE_COMPLETE_LOCAL_NAME: dev_names.append((e, bytes_to_str(s[2]))) return dev_names def find_device_by_name(name): s = Scanner() scan_res = s.scan(100) device_names = get_device_names(scan_res) for dev in device_names: if name == dev[1]: return dev[0] # >>> res = find_device_by_name("micr") # >>> if res: # ... print("address:", res.addr()) # ... print("address type:", res.addr_type()) # ... print("rssi:", res.rssi()) # ... # ... # ... # address: c2:73:61:89:24:45 # address type: 1 # rssi: -26 micropython-1.12/ports/nrf/examples/ubluepy_temp.py000066400000000000000000000061321357706137100226620ustar00rootroot00000000000000# This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2017 Glenn Ruben Bakke # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE from board import LED from machine import RTCounter, Temp from ubluepy import Service, Characteristic, UUID, Peripheral, constants def event_handler(id, handle, data): global rtc global periph global serv_env_sense global notif_enabled if id == constants.EVT_GAP_CONNECTED: # indicated 'connected' LED(1).on() elif id == constants.EVT_GAP_DISCONNECTED: # stop low power timer rtc.stop() # indicate 'disconnected' LED(1).off() # restart advertisment periph.advertise(device_name="micr_temp", services=[serv_env_sense]) elif id == constants.EVT_GATTS_WRITE: # write to this Characteristic is to CCCD if int(data[0]) == 1: notif_enabled = True # start low power timer rtc.start() else: notif_enabled = False # stop low power timer rtc.stop() def send_temp(timer_id): global notif_enabled global char_temp if notif_enabled: # measure chip temperature temp = Temp.read() temp = temp * 100 char_temp.write(bytearray([temp & 0xFF, temp >> 8])) # start off with LED(1) off LED(1).off() # use RTC1 as RTC0 is used by bluetooth stack # set up RTC callback every 5 second rtc = RTCounter(1, period=50, mode=RTCounter.PERIODIC, callback=send_temp) notif_enabled = False uuid_env_sense = UUID("0x181A") # Environmental Sensing service uuid_temp = UUID("0x2A6E") # Temperature characteristic serv_env_sense = Service(uuid_env_sense) temp_props = Characteristic.PROP_NOTIFY | Characteristic.PROP_READ temp_attrs = Characteristic.ATTR_CCCD char_temp = Characteristic(uuid_temp, props = temp_props, attrs = temp_attrs) serv_env_sense.addCharacteristic(char_temp) periph = Peripheral() periph.addService(serv_env_sense) periph.setConnectionHandler(event_handler) periph.advertise(device_name="micr_temp", services=[serv_env_sense]) micropython-1.12/ports/nrf/fatfs_port.c000066400000000000000000000027001357706137100202700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "lib/oofatfs/ff.h" DWORD get_fattime(void) { // TODO: Implement this function. For now, fake it. return ((2016 - 1980) << 25) | ((12) << 21) | ((4) << 16) | ((00) << 11) | ((18) << 5) | (23 / 2); } micropython-1.12/ports/nrf/freeze/000077500000000000000000000000001357706137100172365ustar00rootroot00000000000000micropython-1.12/ports/nrf/freeze/test.py000066400000000000000000000000771357706137100205730ustar00rootroot00000000000000import sys def hello(): print("Hello %s!" % sys.platform) micropython-1.12/ports/nrf/gccollect.c000066400000000000000000000034131357706137100200620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "py/gc.h" #include "gccollect.h" static inline uintptr_t get_sp(void) { uintptr_t result; __asm__ ("mov %0, sp\n" : "=r" (result) ); return result; } void gc_collect(void) { // start the GC gc_collect_start(); // Get stack pointer uintptr_t sp = get_sp(); // trace the stack, including the registers (since they live on the stack in this function) gc_collect_root((void**)sp, ((uint32_t)&_ram_end - sp) / sizeof(uint32_t)); // end the GC gc_collect_end(); } micropython-1.12/ports/nrf/gccollect.h000066400000000000000000000031351357706137100200700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef GC_COLLECT_H__ #define GC_COLLECT_H__ extern uint32_t _etext; extern uint32_t _sidata; extern uint32_t _ram_start; extern uint32_t _sdata; extern uint32_t _edata; extern uint32_t _sbss; extern uint32_t _ebss; extern uint32_t _heap_start; extern uint32_t _heap_end; extern uint32_t _estack; extern uint32_t _ram_end; void gc_collect(void); #endif micropython-1.12/ports/nrf/help.c000066400000000000000000000037431357706137100170610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 - 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" #if BLUETOOTH_SD #include "help_sd.h" #endif const char nrf5_help_text[] = "Welcome to MicroPython!\n" "\n" "For online help please visit http://micropython.org/help/.\n" "\n" "Quick overview of commands for the board:\n" #if MICROPY_HW_HAS_LED " board.LED(n) -- create an LED object for LED n (n=" HELP_TEXT_BOARD_LED ")\n" "\n" #endif #if BLUETOOTH_SD HELP_TEXT_SD #endif "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" " CTRL-B -- on a blank line, enter normal REPL mode\n" " CTRL-D -- on a blank line, do a soft reset of the board\n" " CTRL-E -- on a blank line, enter paste mode\n" "\n" "For further help on a specific object, type help(obj)\n" ; micropython-1.12/ports/nrf/main.c000066400000000000000000000203531357706137100170510ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/nlr.h" #include "py/mperrno.h" #include "py/lexer.h" #include "py/parse.h" #include "py/obj.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" #include "py/compile.h" #include "lib/utils/pyexec.h" #include "readline.h" #include "gccollect.h" #include "modmachine.h" #include "modmusic.h" #include "modules/uos/microbitfs.h" #include "led.h" #include "uart.h" #include "nrf.h" #include "pin.h" #include "spi.h" #include "i2c.h" #include "adc.h" #include "rtcounter.h" #if MICROPY_PY_MACHINE_HW_PWM #include "pwm.h" #endif #include "timer.h" #if BLUETOOTH_SD #include "nrf_sdm.h" #endif #if (MICROPY_PY_BLE_NUS) #include "ble_uart.h" #endif #if MICROPY_PY_MACHINE_SOFT_PWM #include "ticker.h" #include "softpwm.h" #endif #if MICROPY_HW_USB_CDC #include "usb_cdc.h" #endif void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { printf("MemoryError: lexer could not allocate memory\n"); return; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr source_name = lex->source_name; mp_parse_tree_t pn = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(&pn, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } } extern uint32_t _heap_start; extern uint32_t _heap_end; int main(int argc, char **argv) { soft_reset: led_init(); led_state(1, 1); // MICROPY_HW_LED_1 aka MICROPY_HW_LED_RED mp_stack_set_top(&_ram_end); // Stack limit should be less than real stack size, so we have a chance // to recover from limit hit. (Limit is measured in bytes.) mp_stack_set_limit((char*)&_ram_end - (char*)&_heap_end - 400); machine_init(); gc_init(&_heap_start, &_heap_end); mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) mp_obj_list_init(mp_sys_argv, 0); pyb_set_repl_info(MP_OBJ_NEW_SMALL_INT(0)); readline_init0(); #if MICROPY_PY_MACHINE_HW_SPI spi_init0(); #endif #if MICROPY_PY_MACHINE_I2C i2c_init0(); #endif #if MICROPY_PY_MACHINE_ADC adc_init0(); #endif #if MICROPY_PY_MACHINE_HW_PWM pwm_init0(); #endif #if MICROPY_PY_MACHINE_RTCOUNTER rtc_init0(); #endif #if MICROPY_PY_MACHINE_TIMER timer_init0(); #endif #if MICROPY_PY_MACHINE_UART uart_init0(); #endif #if (MICROPY_PY_BLE_NUS == 0) && (MICROPY_HW_USB_CDC == 0) { mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_NEW_SMALL_INT(115200), }; MP_STATE_PORT(board_stdio_uart) = machine_hard_uart_type.make_new((mp_obj_t)&machine_hard_uart_type, MP_ARRAY_SIZE(args), 0, args); } #endif pin_init0(); #if MICROPY_MBFS microbit_filesystem_init(); #endif #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { // create vfs object fs_user_mount_t *vfs = m_new_obj_maybe(fs_user_mount_t); if (vfs == NULL) { goto no_mem_for_sd; } vfs->str = "/sd"; vfs->len = 3; vfs->flags = MP_BLOCKDEV_FLAG_FREE_OBJ; sdcard_init_vfs(vfs); // put the sd device in slot 1 (it will be unused at this point) MP_STATE_PORT(fs_user_mount)[1] = vfs; FRESULT res = f_mount(&vfs->fatfs, vfs->str, 1); if (res != FR_OK) { printf("MPY: can't mount SD card\n"); MP_STATE_PORT(fs_user_mount)[1] = NULL; m_del_obj(fs_user_mount_t, vfs); } else { // TODO these should go before the /flash entries in the path mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib)); // use SD card as current directory f_chdrive("/sd"); } no_mem_for_sd:; } #endif // Main script is finished, so now go into REPL mode. // The REPL mode can change, or it can request a soft reset. int ret_code = 0; #if MICROPY_PY_BLE_NUS ble_uart_init0(); #endif #if MICROPY_PY_MACHINE_SOFT_PWM ticker_init0(); softpwm_init0(); #endif #if MICROPY_PY_MUSIC microbit_music_init0(); #endif #if BOARD_SPECIFIC_MODULES board_modules_init0(); #endif #if MICROPY_PY_MACHINE_SOFT_PWM ticker_start(); pwm_start(); #endif led_state(1, 0); #if MICROPY_VFS || MICROPY_MBFS || MICROPY_MODULE_FROZEN // run boot.py and main.py if they exist. pyexec_file_if_exists("boot.py"); pyexec_file_if_exists("main.py"); #endif #if MICROPY_HW_USB_CDC usb_cdc_init(); #endif for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { ret_code = pyexec_friendly_repl(); if (ret_code != 0) { break; } } } mp_deinit(); printf("MPY: soft reboot\n"); #if BLUETOOTH_SD sd_softdevice_disable(); #endif goto soft_reset; return 0; } #if !MICROPY_VFS #if MICROPY_MBFS // Use micro:bit filesystem mp_lexer_t *mp_lexer_new_from_file(const char *filename) { return uos_mbfs_new_reader(filename); } mp_import_stat_t mp_import_stat(const char *path) { return uos_mbfs_import_stat(path); } STATIC mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args) { return uos_mbfs_open(n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open); #else // use dummy functions - no filesystem available mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } STATIC mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { mp_raise_OSError(MP_EPERM); } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); #endif #endif void HardFault_Handler(void) { #if defined(NRF52_SERIES) || defined(NRF91_SERIES) static volatile uint32_t reg; static volatile uint32_t reg2; static volatile uint32_t bfar; reg = SCB->HFSR; reg2 = SCB->CFSR; bfar = SCB->BFAR; for (int i = 0; i < 0; i++) { (void)reg; (void)reg2; (void)bfar; } #endif } void NORETURN __fatal_error(const char *msg) { while (1); } void nlr_jump_fail(void *val) { printf("FATAL: uncaught exception %p\n", val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)val); __fatal_error(""); } void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error("Assertion failed"); } void _start(void) {main(0, NULL);} micropython-1.12/ports/nrf/modules/000077500000000000000000000000001357706137100174265ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/ble/000077500000000000000000000000001357706137100201705ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/ble/help_sd.h000066400000000000000000000032731357706137100217640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef HELP_SD_H__ #define HELP_SD_H__ #include "bluetooth_conf.h" #if MICROPY_PY_BLE #define HELP_TEXT_SD \ "If compiled with SD= the additional commands are\n" \ "available:\n" \ " ble.enable() -- enable bluetooth stack\n" \ " ble.disable() -- disable bluetooth stack\n" \ " ble.enabled() -- check whether bluetooth stack is enabled\n" \ " ble.address() -- return device address as text string\n" \ "\n" #else #define HELP_TEXT_SD #endif // MICROPY_PY_BLE #endif micropython-1.12/ports/nrf/modules/ble/modble.c000066400000000000000000000067341357706137100216100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_BLE #include "led.h" #include "mpconfigboard.h" #include "ble_drv.h" /// \method enable() /// Enable BLE softdevice. mp_obj_t ble_obj_enable(void) { printf("SoftDevice enabled\n"); uint32_t err_code = ble_drv_stack_enable(); if (err_code < 0) { // TODO: raise exception. } return mp_const_none; } /// \method disable() /// Disable BLE softdevice. mp_obj_t ble_obj_disable(void) { ble_drv_stack_disable(); return mp_const_none; } /// \method enabled() /// Get state of whether the softdevice is enabled or not. mp_obj_t ble_obj_enabled(void) { uint8_t is_enabled = ble_drv_stack_enabled(); mp_int_t enabled = is_enabled; return MP_OBJ_NEW_SMALL_INT(enabled); } /// \method address() /// Return device address as text string. mp_obj_t ble_obj_address(void) { ble_drv_addr_t local_addr; ble_drv_address_get(&local_addr); vstr_t vstr; vstr_init(&vstr, 17); vstr_printf(&vstr, ""HEX2_FMT":"HEX2_FMT":"HEX2_FMT":" \ HEX2_FMT":"HEX2_FMT":"HEX2_FMT"", local_addr.addr[5], local_addr.addr[4], local_addr.addr[3], local_addr.addr[2], local_addr.addr[1], local_addr.addr[0]); mp_obj_t mac_str = mp_obj_new_str(vstr.buf, vstr.len); vstr_clear(&vstr); return mac_str; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(ble_obj_enable_obj, ble_obj_enable); STATIC MP_DEFINE_CONST_FUN_OBJ_0(ble_obj_disable_obj, ble_obj_disable); STATIC MP_DEFINE_CONST_FUN_OBJ_0(ble_obj_enabled_obj, ble_obj_enabled); STATIC MP_DEFINE_CONST_FUN_OBJ_0(ble_obj_address_obj, ble_obj_address); STATIC const mp_rom_map_elem_t ble_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ble) }, { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&ble_obj_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&ble_obj_disable_obj) }, { MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&ble_obj_enabled_obj) }, { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&ble_obj_address_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ble_module_globals, ble_module_globals_table); const mp_obj_module_t ble_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&ble_module_globals, }; #endif // MICROPY_PY_BLE micropython-1.12/ports/nrf/modules/board/000077500000000000000000000000001357706137100205155ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/board/led.c000066400000000000000000000140731357706137100214320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * Copyright (c) 2015 - 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "mphalport.h" #include "led.h" #include "mpconfigboard.h" #if MICROPY_HW_HAS_LED typedef struct _board_led_obj_t { mp_obj_base_t base; mp_uint_t led_id; mp_uint_t hw_pin; uint8_t hw_pin_port; bool pullup; } board_led_obj_t; static inline void led_off(board_led_obj_t * const led_obj) { if (led_obj->pullup) { nrf_gpio_pin_set(led_obj->hw_pin); } else { nrf_gpio_pin_clear(led_obj->hw_pin); } } static inline void led_on(board_led_obj_t * const led_obj) { if (led_obj->pullup) { nrf_gpio_pin_clear(led_obj->hw_pin); } else { nrf_gpio_pin_set(led_obj->hw_pin); } } static const board_led_obj_t board_led_obj[] = { #if MICROPY_HW_LED_TRICOLOR {{&board_led_type}, BOARD_LED_RED, MICROPY_HW_LED_RED, 0, MICROPY_HW_LED_PULLUP}, {{&board_led_type}, BOARD_LED_GREEN, MICROPY_HW_LED_GREEN, 0, MICROPY_HW_LED_PULLUP}, {{&board_led_type}, BOARD_LED_BLUE, MICROPY_HW_LED_BLUE, 0, MICROPY_HW_LED_PULLUP}, #endif #if (MICROPY_HW_LED_COUNT >= 1) {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, #ifdef MICROPY_HW_LED1_PULLUP MICROPY_HW_LED1_PULLUP #else MICROPY_HW_LED_PULLUP #endif }, #endif #if (MICROPY_HW_LED_COUNT >= 2) {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2, 0, #ifdef MICROPY_HW_LED2_PULLUP MICROPY_HW_LED2_PULLUP #else MICROPY_HW_LED_PULLUP #endif }, #endif #if (MICROPY_HW_LED_COUNT >= 3) {{&board_led_type}, BOARD_LED3, MICROPY_HW_LED3, 0, #ifdef MICROPY_HW_LED3_PULLUP MICROPY_HW_LED3_PULLUP #else MICROPY_HW_LED_PULLUP #endif }, #endif #if (MICROPY_HW_LED_COUNT == 4) {{&board_led_type}, BOARD_LED4, MICROPY_HW_LED4, 0, #ifdef MICROPY_HW_LED4_PULLUP MICROPY_HW_LED4_PULLUP #else MICROPY_HW_LED_PULLUP #endif }, #endif }; #define NUM_LEDS MP_ARRAY_SIZE(board_led_obj) void led_init(void) { for (uint8_t i = 0; i < NUM_LEDS; i++) { led_off((board_led_obj_t*)&board_led_obj[i]); nrf_gpio_cfg_output(board_led_obj[i].hw_pin); } } void led_state(board_led_t led, int state) { if (state == 1) { led_on((board_led_obj_t*)&board_led_obj[led-1]); } else { led_off((board_led_obj_t*)&board_led_obj[led-1]); } } void led_toggle(board_led_t led) { nrf_gpio_pin_toggle(board_led_obj[led-1].hw_pin); } /******************************************************************************/ /* MicroPython bindings */ void led_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { board_led_obj_t *self = self_in; mp_printf(print, "LED(%lu)", self->led_id); } /// \classmethod \constructor(id) /// Create an LED object associated with the given LED: /// /// - `id` is the LED number, 1-4. STATIC mp_obj_t led_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); // get led number mp_int_t led_id = mp_obj_get_int(args[0]); // check led number if (!(1 <= led_id && led_id <= NUM_LEDS)) { mp_raise_ValueError("LED doesn't exist"); } // return static led object return (mp_obj_t)&board_led_obj[led_id - 1]; } /// \method on() /// Turn the LED on. mp_obj_t led_obj_on(mp_obj_t self_in) { board_led_obj_t *self = self_in; led_state(self->led_id, 1); return mp_const_none; } /// \method off() /// Turn the LED off. mp_obj_t led_obj_off(mp_obj_t self_in) { board_led_obj_t *self = self_in; led_state(self->led_id, 0); return mp_const_none; } /// \method toggle() /// Toggle the LED between on and off. mp_obj_t led_obj_toggle(mp_obj_t self_in) { board_led_obj_t *self = self_in; led_toggle(self->led_id); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on); STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off); STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_toggle_obj, led_obj_toggle); STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&led_obj_on_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&led_obj_off_obj) }, { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj) }, }; STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); const mp_obj_type_t board_led_type = { { &mp_type_type }, .name = MP_QSTR_LED, .print = led_obj_print, .make_new = led_obj_make_new, .locals_dict = (mp_obj_dict_t*)&led_locals_dict, }; #else // For boards with no LEDs, we leave an empty function here so that we don't // have to put conditionals everywhere. void led_init(void) { } void led_state(board_led_t led, int state) { } void led_toggle(board_led_t led) { } #endif // MICROPY_HW_HAS_LED micropython-1.12/ports/nrf/modules/board/led.h000066400000000000000000000035521357706137100214370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 - 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef LED_H #define LED_H typedef enum { #if MICROPY_HW_LED_TRICOLOR BOARD_LED_RED = 1, BOARD_LED_GREEN = 2, BOARD_LED_BLUE = 3 #elif (MICROPY_HW_LED_COUNT == 1) BOARD_LED1 = 1, #elif (MICROPY_HW_LED_COUNT == 2) BOARD_LED1 = 1, BOARD_LED2 = 2, #elif (MICROPY_HW_LED_COUNT == 3) BOARD_LED1 = 1, BOARD_LED2 = 2, BOARD_LED3 = 3, #else BOARD_LED1 = 1, BOARD_LED2 = 2, BOARD_LED3 = 3, BOARD_LED4 = 4 #endif } board_led_t; void led_init(void); void led_state(board_led_t, int); void led_toggle(board_led_t); extern const mp_obj_type_t board_led_type; #endif // LED_H micropython-1.12/ports/nrf/modules/board/modboard.c000066400000000000000000000037331357706137100224560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 - 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" #include "lib/utils/pyexec.h" #include "py/runtime.h" #include "py/obj.h" #include "led.h" #include "nrf.h" // TODO: figure out where to put this import #include "pin.h" #if MICROPY_HW_HAS_LED #define PYB_LED_MODULE { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&board_led_type) }, #else #define PYB_LED_MODULE #endif STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_board) }, { MP_ROM_QSTR(MP_QSTR_repl_info), MP_ROM_PTR(&pyb_set_repl_info_obj) }, PYB_LED_MODULE }; STATIC MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); const mp_obj_module_t board_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&board_module_globals, }; micropython-1.12/ports/nrf/modules/machine/000077500000000000000000000000001357706137100210325ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/machine/adc.c000066400000000000000000000240451357706137100217320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017-2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #if MICROPY_PY_MACHINE_ADC #include "adc.h" #if NRF51 #include "nrfx_adc.h" #else #include "nrfx_saadc.h" #endif typedef struct _machine_adc_obj_t { mp_obj_base_t base; uint8_t id; #if NRF51 uint8_t ain; #endif } machine_adc_obj_t; STATIC const machine_adc_obj_t machine_adc_obj[] = { #if NRF51 {{&machine_adc_type}, .id = 0, .ain = NRF_ADC_CONFIG_INPUT_0}, {{&machine_adc_type}, .id = 1, .ain = NRF_ADC_CONFIG_INPUT_1}, {{&machine_adc_type}, .id = 2, .ain = NRF_ADC_CONFIG_INPUT_2}, {{&machine_adc_type}, .id = 3, .ain = NRF_ADC_CONFIG_INPUT_3}, {{&machine_adc_type}, .id = 4, .ain = NRF_ADC_CONFIG_INPUT_4}, {{&machine_adc_type}, .id = 5, .ain = NRF_ADC_CONFIG_INPUT_5}, {{&machine_adc_type}, .id = 6, .ain = NRF_ADC_CONFIG_INPUT_6}, {{&machine_adc_type}, .id = 7, .ain = NRF_ADC_CONFIG_INPUT_7}, #else {{&machine_adc_type}, .id = 0}, {{&machine_adc_type}, .id = 1}, {{&machine_adc_type}, .id = 2}, {{&machine_adc_type}, .id = 3}, {{&machine_adc_type}, .id = 4}, {{&machine_adc_type}, .id = 5}, {{&machine_adc_type}, .id = 6}, {{&machine_adc_type}, .id = 7}, #endif }; #if defined(NRF52_SERIES) STATIC void saadc_event_handler(nrfx_saadc_evt_t const * p_event) { (void)p_event; } #endif void adc_init0(void) { #if defined(NRF52_SERIES) const nrfx_saadc_config_t config = { .resolution = NRF_SAADC_RESOLUTION_8BIT, .oversample = NRF_SAADC_OVERSAMPLE_DISABLED, .interrupt_priority = 6, .low_power_mode = false }; nrfx_saadc_init(&config, saadc_event_handler); #endif } STATIC int adc_find(mp_obj_t id) { int adc_idx; if (mp_obj_is_int(id)) { // Given an integer id adc_idx = mp_obj_get_int(id); } else { // Assume it's a pin-compatible object and convert it to an ADC channel number mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(id); if (pin->adc_num & PIN_ADC1) { adc_idx = pin->adc_channel; } else { mp_raise_ValueError("invalid Pin for ADC"); } } if (adc_idx >= 0 && adc_idx < MP_ARRAY_SIZE(machine_adc_obj) && machine_adc_obj[adc_idx].id != (uint8_t)-1) { return adc_idx; } mp_raise_ValueError("ADC doesn't exist"); } /// \method __str__() /// Return a string describing the ADC object. STATIC void machine_adc_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { machine_adc_obj_t *self = o; mp_printf(print, "ADC(%u)", self->id); } /******************************************************************************/ /* MicroPython bindings for machine API */ // for make_new STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1) } }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); int adc_id = adc_find(args[ARG_id].u_obj); const machine_adc_obj_t *self = &machine_adc_obj[adc_id]; #if defined(NRF52_SERIES) const nrf_saadc_channel_config_t config = { .resistor_p = NRF_SAADC_RESISTOR_DISABLED, .resistor_n = NRF_SAADC_RESISTOR_DISABLED, .gain = NRF_SAADC_GAIN1_4, .reference = NRF_SAADC_REFERENCE_VDD4, .acq_time = NRF_SAADC_ACQTIME_3US, .mode = NRF_SAADC_MODE_SINGLE_ENDED, .burst = NRF_SAADC_BURST_DISABLED, .pin_p = 1 + self->id, // pin_p=0 is AIN0, pin_p=8 is AIN7 .pin_n = NRF_SAADC_INPUT_DISABLED }; nrfx_saadc_channel_init(self->id, &config); #endif return MP_OBJ_FROM_PTR(self); } int16_t machine_adc_value_read(machine_adc_obj_t * adc_obj) { #if NRF51 nrf_adc_value_t value = 0; nrfx_adc_channel_t channel_config = { .config.resolution = NRF_ADC_CONFIG_RES_8BIT, .config.input = NRF_ADC_CONFIG_SCALING_INPUT_TWO_THIRDS, .config.reference = NRF_ADC_CONFIG_REF_VBG, .config.input = adc_obj->ain, .config.extref = ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos // Currently not defined in nrfx/hal. }; nrfx_adc_sample_convert(&channel_config, &value); #else // NRF52 nrf_saadc_value_t value = 0; nrfx_saadc_sample_convert(adc_obj->id, &value); #endif return value; } // read_u16() STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) { machine_adc_obj_t *self = self_in; int16_t raw = machine_adc_value_read(self); #if defined(NRF52_SERIES) // raw is signed but the channel is in single-ended mode and this method cannot return negative values if (raw < 0) { raw = 0; } #endif // raw is an 8-bit value return MP_OBJ_NEW_SMALL_INT(raw << 8 | raw); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_adc_read_u16_obj, machine_adc_read_u16); /// \method value() /// Read adc level. mp_obj_t machine_adc_value(mp_obj_t self_in) { machine_adc_obj_t *self = self_in; int16_t value = machine_adc_value_read(self); return MP_OBJ_NEW_SMALL_INT(value); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_adc_value_obj, machine_adc_value); #if NRF51 #define ADC_REF_VOLTAGE_IN_MILLIVOLT (1200) // Reference voltage in mV (1.2V). #define ADC_PRE_SCALING_MULTIPLIER (3) // VDD 1/3 prescaling as input. Hence, multiplied by 3 to get the value of the battery voltage. #else // NRF52 #define ADC_REF_VOLTAGE_IN_MILLIVOLT (600) // Reference voltage in mV (0.6V). #define ADC_PRE_SCALING_MULTIPLIER (6) // VDD 1/6 prescaling as input. Hence, multiplied by 6 to get the value of the battery voltage. #endif #define DIODE_VOLT_DROP_MILLIVOLT (270) // Voltage drop over diode. #define BATTERY_MILLIVOLT(VALUE) \ ((((VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLT) / 255) * ADC_PRE_SCALING_MULTIPLIER) static uint8_t battery_level_in_percent(const uint16_t mvolts) { uint8_t battery_level; if (mvolts >= 3000) { battery_level = 100; } else if (mvolts > 2900) { battery_level = 100 - ((3000 - mvolts) * 58) / 100; } else if (mvolts > 2740) { battery_level = 42 - ((2900 - mvolts) * 24) / 160; } else if (mvolts > 2440) { battery_level = 18 - ((2740 - mvolts) * 12) / 300; } else if (mvolts > 2100) { battery_level = 6 - ((2440 - mvolts) * 6) / 340; } else { battery_level = 0; } return battery_level; } /// \method battery_level() /// Get battery level in percentage. mp_obj_t machine_adc_battery_level(void) { #if NRF51 nrf_adc_value_t value = 0; nrfx_adc_channel_t channel_config = { .config.resolution = NRF_ADC_CONFIG_RES_8BIT, .config.input = NRF_ADC_CONFIG_SCALING_SUPPLY_ONE_THIRD, .config.reference = NRF_ADC_CONFIG_REF_VBG, .config.input = NRF_ADC_CONFIG_INPUT_DISABLED, .config.extref = ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos // Currently not defined in nrfx/hal. }; nrfx_adc_sample_convert(&channel_config, &value); #else // NRF52 nrf_saadc_value_t value = 0; const nrf_saadc_channel_config_t config = { .resistor_p = NRF_SAADC_RESISTOR_DISABLED, .resistor_n = NRF_SAADC_RESISTOR_DISABLED, .gain = NRF_SAADC_GAIN1_6, .reference = NRF_SAADC_REFERENCE_INTERNAL, .acq_time = NRF_SAADC_ACQTIME_3US, .mode = NRF_SAADC_MODE_SINGLE_ENDED, .burst = NRF_SAADC_BURST_DISABLED, .pin_p = NRF_SAADC_INPUT_VDD, .pin_n = NRF_SAADC_INPUT_DISABLED }; nrfx_saadc_channel_init(0, &config); nrfx_saadc_sample_convert(0, &value); #endif uint16_t batt_lvl_in_milli_volts = BATTERY_MILLIVOLT(value) + DIODE_VOLT_DROP_MILLIVOLT; uint16_t batt_in_percent = battery_level_in_percent(batt_lvl_in_milli_volts); return MP_OBJ_NEW_SMALL_INT(batt_in_percent); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_machine_adc_battery_level_obj, machine_adc_battery_level); STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&mp_machine_adc_read_u16_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&mp_machine_adc_value_obj) }, // class methods { MP_ROM_QSTR(MP_QSTR_battery_level), MP_ROM_PTR(&mp_machine_adc_battery_level_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); const mp_obj_type_t machine_adc_type = { { &mp_type_type }, .name = MP_QSTR_ADC, .make_new = machine_adc_make_new, .locals_dict = (mp_obj_dict_t*)&machine_adc_locals_dict, .print = machine_adc_print, }; #endif // MICROPY_PY_MACHINE_ADC micropython-1.12/ports/nrf/modules/machine/adc.h000066400000000000000000000026671357706137100217450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef ADC_H__ #define ADC_H__ typedef struct _machine_adc_obj_t machine_adc_obj_t; extern const mp_obj_type_t machine_adc_type; void adc_init0(void); int16_t machine_adc_value_read(machine_adc_obj_t * adc_obj); #endif // ADC_H__ micropython-1.12/ports/nrf/modules/machine/i2c.c000066400000000000000000000124421357706137100216560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/nlr.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #if MICROPY_PY_MACHINE_I2C #include "extmod/machine_i2c.h" #include "i2c.h" #if NRFX_TWI_ENABLED #include "nrfx_twi.h" #else #include "nrfx_twim.h" #endif #if NRFX_TWIM_ENABLED #define nrfx_twi_t nrfx_twim_t #define nrfx_twi_config_t nrfx_twim_config_t #define nrfx_twi_init nrfx_twim_init #define nrfx_twi_enable nrfx_twim_enable #define nrfx_twi_rx nrfx_twim_rx #define nrfx_twi_tx nrfx_twim_tx #define nrfx_twi_disable nrfx_twim_disable #define NRFX_TWI_INSTANCE NRFX_TWIM_INSTANCE #define NRF_TWI_FREQ_400K NRF_TWIM_FREQ_400K #endif STATIC const mp_obj_type_t machine_hard_i2c_type; typedef struct _machine_hard_i2c_obj_t { mp_obj_base_t base; nrfx_twi_t p_twi; // Driver instance } machine_hard_i2c_obj_t; STATIC const machine_hard_i2c_obj_t machine_hard_i2c_obj[] = { {{&machine_hard_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(0)}, {{&machine_hard_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(1)}, }; void i2c_init0(void) { } STATIC int i2c_find(mp_obj_t id) { // given an integer id int i2c_id = mp_obj_get_int(id); if (i2c_id >= 0 && i2c_id < MP_ARRAY_SIZE(machine_hard_i2c_obj)) { return i2c_id; } mp_raise_ValueError("I2C doesn't exist"); } STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hard_i2c_obj_t *self = self_in; mp_printf(print, "I2C(%u)", self->p_twi.drv_inst_idx); } /******************************************************************************/ /* MicroPython bindings for machine API */ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_scl, ARG_sda }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get static peripheral object int i2c_id = i2c_find(args[ARG_id].u_obj); const machine_hard_i2c_obj_t *self = &machine_hard_i2c_obj[i2c_id]; nrfx_twi_config_t config; config.scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj)->pin; config.sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj)->pin; config.frequency = NRF_TWI_FREQ_400K; config.hold_bus_uninit = false; // Set context to this object. nrfx_twi_init(&self->p_twi, &config, NULL, (void *)self); return MP_OBJ_FROM_PTR(self); } int machine_hard_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) { machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)self_in; nrfx_twi_enable(&self->p_twi); nrfx_err_t err_code; int transfer_ret = 0; if (flags & MP_MACHINE_I2C_FLAG_READ) { err_code = nrfx_twi_rx(&self->p_twi, addr, buf, len); } else { err_code = nrfx_twi_tx(&self->p_twi, addr, buf, len, (flags & MP_MACHINE_I2C_FLAG_STOP) == 0); transfer_ret = len; } if (err_code != NRFX_SUCCESS) { if (err_code == NRFX_ERROR_DRV_TWI_ERR_ANACK) { return -MP_ENODEV; } else if (err_code == NRFX_ERROR_DRV_TWI_ERR_DNACK) { return -MP_EIO; } return -MP_ETIMEDOUT; } nrfx_twi_disable(&self->p_twi); return transfer_ret; } STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { .transfer = mp_machine_i2c_transfer_adaptor, .transfer_single = machine_hard_i2c_transfer_single, }; STATIC const mp_obj_type_t machine_hard_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, .print = machine_hard_i2c_print, .make_new = machine_hard_i2c_make_new, .protocol = &machine_hard_i2c_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict, }; #endif // MICROPY_PY_MACHINE_I2C micropython-1.12/ports/nrf/modules/machine/i2c.h000066400000000000000000000025031357706137100216600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef I2C_H__ #define I2C_H__ extern const mp_obj_type_t machine_i2c_type; void i2c_init0(void); #endif // I2C_H__ micropython-1.12/ports/nrf/modules/machine/modmachine.c000066400000000000000000000215311357706137100233040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "modmachine.h" #include "py/gc.h" #include "py/runtime.h" #include "py/mphal.h" #include "extmod/machine_mem.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "gccollect.h" #include "pin.h" #include "uart.h" #include "spi.h" #include "i2c.h" #include "timer.h" #if MICROPY_PY_MACHINE_HW_PWM #include "pwm.h" #endif #if MICROPY_PY_MACHINE_ADC #include "adc.h" #endif #if MICROPY_PY_MACHINE_TEMP #include "temp.h" #endif #if MICROPY_PY_MACHINE_RTCOUNTER #include "rtcounter.h" #endif #define PYB_RESET_HARD (0) #define PYB_RESET_WDT (1) #define PYB_RESET_SOFT (2) #define PYB_RESET_LOCKUP (3) #define PYB_RESET_POWER_ON (16) #define PYB_RESET_LPCOMP (17) #define PYB_RESET_DIF (18) #define PYB_RESET_NFC (19) STATIC uint32_t reset_cause; void machine_init(void) { uint32_t state = NRF_POWER->RESETREAS; if (state & POWER_RESETREAS_RESETPIN_Msk) { reset_cause = PYB_RESET_HARD; } else if (state & POWER_RESETREAS_DOG_Msk) { reset_cause = PYB_RESET_WDT; } else if (state & POWER_RESETREAS_SREQ_Msk) { reset_cause = PYB_RESET_SOFT; } else if (state & POWER_RESETREAS_LOCKUP_Msk) { reset_cause = PYB_RESET_LOCKUP; } else if (state & POWER_RESETREAS_OFF_Msk) { reset_cause = PYB_RESET_POWER_ON; #if !defined(NRF9160_XXAA) } else if (state & POWER_RESETREAS_LPCOMP_Msk) { reset_cause = PYB_RESET_LPCOMP; #endif } else if (state & POWER_RESETREAS_DIF_Msk) { reset_cause = PYB_RESET_DIF; #if defined(NRF52_SERIES) } else if (state & POWER_RESETREAS_NFC_Msk) { reset_cause = PYB_RESET_NFC; #endif } // clear reset reason NRF_POWER->RESETREAS = (1 << reset_cause); } // machine.info([dump_alloc_table]) // Print out lots of information about the board. STATIC mp_obj_t machine_info(mp_uint_t n_args, const mp_obj_t *args) { // to print info about memory { printf("_etext=%p\n", &_etext); printf("_sidata=%p\n", &_sidata); printf("_sdata=%p\n", &_sdata); printf("_edata=%p\n", &_edata); printf("_sbss=%p\n", &_sbss); printf("_ebss=%p\n", &_ebss); printf("_estack=%p\n", &_estack); printf("_ram_start=%p\n", &_ram_start); printf("_heap_start=%p\n", &_heap_start); printf("_heap_end=%p\n", &_heap_end); printf("_ram_end=%p\n", &_ram_end); } // qstr info { mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); } // GC info { gc_info_t info; gc_info(&info); printf("GC:\n"); printf(" " UINT_FMT " total\n", info.total); printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); } if (n_args == 1) { // arg given means dump gc allocation table gc_dump_alloc_table(); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info); // Resets the board in a manner similar to pushing the external RESET button. STATIC mp_obj_t machine_reset(void) { NVIC_SystemReset(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); STATIC mp_obj_t machine_soft_reset(void) { pyexec_system_exit = PYEXEC_FORCED_EXIT; nlr_raise(mp_obj_new_exception(&mp_type_SystemExit)); } MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); STATIC mp_obj_t machine_lightsleep(void) { __WFE(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_lightsleep_obj, machine_lightsleep); STATIC mp_obj_t machine_deepsleep(void) { __WFI(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep); STATIC mp_obj_t machine_reset_cause(void) { return MP_OBJ_NEW_SMALL_INT(reset_cause); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); STATIC mp_obj_t machine_enable_irq(void) { #ifndef BLUETOOTH_SD __enable_irq(); #else #endif return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_enable_irq_obj, machine_enable_irq); // Resets the board in a manner similar to pushing the external RESET button. STATIC mp_obj_t machine_disable_irq(void) { #ifndef BLUETOOTH_SD __disable_irq(); #else #endif return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq); STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, #if MICROPY_HW_ENABLE_RNG { MP_ROM_QSTR(MP_QSTR_rng), MP_ROM_PTR(&random_module) }, #endif { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, #if MICROPY_PY_MACHINE_UART { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_hard_uart_type) }, #endif #if MICROPY_PY_MACHINE_HW_SPI { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, #endif #if MICROPY_PY_MACHINE_I2C { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, #endif #if MICROPY_PY_MACHINE_ADC { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, #endif #if MICROPY_PY_MACHINE_RTCOUNTER { MP_ROM_QSTR(MP_QSTR_RTCounter), MP_ROM_PTR(&machine_rtcounter_type) }, #endif #if MICROPY_PY_MACHINE_TIMER { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, #endif #if MICROPY_PY_MACHINE_HW_PWM { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_hard_pwm_type) }, #endif #if MICROPY_PY_MACHINE_TEMP { MP_ROM_QSTR(MP_QSTR_Temp), MP_ROM_PTR(&machine_temp_type) }, #endif { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(PYB_RESET_HARD) }, { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(PYB_RESET_WDT) }, { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(PYB_RESET_SOFT) }, { MP_ROM_QSTR(MP_QSTR_LOCKUP_RESET), MP_ROM_INT(PYB_RESET_LOCKUP) }, { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(PYB_RESET_POWER_ON) }, { MP_ROM_QSTR(MP_QSTR_LPCOMP_RESET), MP_ROM_INT(PYB_RESET_LPCOMP) }, { MP_ROM_QSTR(MP_QSTR_DEBUG_IF_RESET), MP_ROM_INT(PYB_RESET_DIF) }, #if defined(NRF52_SERIES) { MP_ROM_QSTR(MP_QSTR_NFC_RESET), MP_ROM_INT(PYB_RESET_NFC) }, #endif }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t machine_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; micropython-1.12/ports/nrf/modules/machine/modmachine.h000066400000000000000000000032611357706137100233110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __MICROPY_INCLUDED_NRF5_MODMACHINE_H__ #define __MICROPY_INCLUDED_NRF5_MODMACHINE_H__ #include "py/mpstate.h" #include "py/nlr.h" #include "py/obj.h" void machine_init(void); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_lightsleep_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_deepsleep_obj); #endif // __MICROPY_INCLUDED_NRF5_MODMACHINE_H__ micropython-1.12/ports/nrf/modules/machine/pin.c000066400000000000000000000576601357706137100220020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016, 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #include "pin.h" #include "nrf_gpio.h" #include "nrfx_gpiote.h" extern const pin_obj_t machine_board_pin_obj[]; extern const uint8_t machine_pin_num_of_board_pins; /// \moduleref machine /// \class Pin - control I/O pins /// /// A pin is the basic object to control I/O pins. It has methods to set /// the mode of the pin (input, output, etc) and methods to get and set the /// digital logic level. For analog control of a pin, see the ADC class. /// /// Usage Model: /// /// All Board Pins are predefined as machine.Pin.board.Name /// /// x1_pin = machine.Pin.board.X1 /// /// g = machine.Pin(machine.Pin.board.X1, machine.Pin.IN) /// /// CPU pins which correspond to the board pins are available /// as `machine.cpu.Name`. For the CPU pins, the names are the port letter /// followed by the pin number. On the PYBv1.0, `machine.Pin.board.X1` and /// `machine.Pin.cpu.B6` are the same pin. /// /// You can also use strings: /// /// g = machine.Pin('X1', machine.Pin.OUT) /// /// Users can add their own names: /// /// MyMapperDict = { 'LeftMotorDir' : machine.Pin.cpu.C12 } /// machine.Pin.dict(MyMapperDict) /// g = machine.Pin("LeftMotorDir", machine.Pin.OUT) /// /// and can query mappings /// /// pin = machine.Pin("LeftMotorDir") /// /// Users can also add their own mapping function: /// /// def MyMapper(pin_name): /// if pin_name == "LeftMotorDir": /// return machine.Pin.cpu.A0 /// /// machine.Pin.mapper(MyMapper) /// /// So, if you were to call: `machine.Pin("LeftMotorDir", machine.Pin.OUT)` /// then `"LeftMotorDir"` is passed directly to the mapper function. /// /// To summarise, the following order determines how things get mapped into /// an ordinal pin number: /// /// 1. Directly specify a pin object /// 2. User supplied mapping function /// 3. User supplied mapping (object must be usable as a dictionary key) /// 4. Supply a string which matches a board pin /// 5. Supply a string which matches a CPU port/pin /// /// You can set `machine.Pin.debug(True)` to get some debug information about /// how a particular object gets mapped to a pin. #define PIN_DEBUG (0) // Pin class variables #if PIN_DEBUG STATIC bool pin_class_debug; #else #define pin_class_debug (0) #endif void pin_init0(void) { MP_STATE_PORT(pin_class_mapper) = mp_const_none; MP_STATE_PORT(pin_class_map_dict) = mp_const_none; for (int i = 0; i < NUM_OF_PINS; i++) { MP_STATE_PORT(pin_irq_handlers)[i] = mp_const_none; } // Initialize GPIOTE if not done yet. if (!nrfx_gpiote_is_init()) { nrfx_gpiote_init(); } #if PIN_DEBUG pin_class_debug = false; #endif } // C API used to convert a user-supplied pin name into an ordinal pin number. const pin_obj_t *pin_find(mp_obj_t user_obj) { const pin_obj_t *pin_obj; // If pin is SMALL_INT if (mp_obj_is_small_int(user_obj)) { uint8_t value = MP_OBJ_SMALL_INT_VALUE(user_obj); for (uint8_t i = 0; i < machine_pin_num_of_board_pins; i++) { if (machine_board_pin_obj[i].pin == value) { return &machine_board_pin_obj[i]; } } } // If a pin was provided, then use it if (mp_obj_is_type(user_obj, &pin_type)) { pin_obj = user_obj; if (pin_class_debug) { printf("Pin map passed pin "); mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); printf("\n"); } return pin_obj; } if (MP_STATE_PORT(pin_class_mapper) != mp_const_none) { pin_obj = mp_call_function_1(MP_STATE_PORT(pin_class_mapper), user_obj); if (pin_obj != mp_const_none) { if (!mp_obj_is_type(pin_obj, &pin_type)) { mp_raise_ValueError("Pin.mapper didn't return a Pin object"); } if (pin_class_debug) { printf("Pin.mapper maps "); mp_obj_print(user_obj, PRINT_REPR); printf(" to "); mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); printf("\n"); } return pin_obj; } // The pin mapping function returned mp_const_none, fall through to // other lookup methods. } if (MP_STATE_PORT(pin_class_map_dict) != mp_const_none) { mp_map_t *pin_map_map = mp_obj_dict_get_map(MP_STATE_PORT(pin_class_map_dict)); mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP); if (elem != NULL && elem->value != NULL) { pin_obj = elem->value; if (pin_class_debug) { printf("Pin.map_dict maps "); mp_obj_print(user_obj, PRINT_REPR); printf(" to "); mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); printf("\n"); } return pin_obj; } } // See if the pin name matches a board pin pin_obj = pin_find_named_pin(&pin_board_pins_locals_dict, user_obj); if (pin_obj) { if (pin_class_debug) { printf("Pin.board maps "); mp_obj_print(user_obj, PRINT_REPR); printf(" to "); mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); printf("\n"); } return pin_obj; } // See if the pin name matches a cpu pin pin_obj = pin_find_named_pin(&pin_cpu_pins_locals_dict, user_obj); if (pin_obj) { if (pin_class_debug) { printf("Pin.cpu maps "); mp_obj_print(user_obj, PRINT_REPR); printf(" to "); mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); printf("\n"); } return pin_obj; } mp_raise_ValueError("not a valid pin identifier"); } /// \method __str__() /// Return a string describing the pin object. STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pin_obj_t *self = self_in; char *pull = "PULL_DISABLED"; switch (nrf_gpio_pin_pull_get(self->pin)) { case NRF_GPIO_PIN_PULLUP: pull = "PULL_UP"; break; case NRF_GPIO_PIN_PULLDOWN: pull = "PULL_DOWN"; break; default: break; } mp_printf(print, "Pin(%d, mode=%s, pull=%s)", self->pin, (nrf_gpio_pin_dir_get(self->pin) == NRF_GPIO_PIN_DIR_OUTPUT) ? "OUT" : "IN", pull); } STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *pin, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args); /// \classmethod \constructor(id, ...) /// Create a new Pin object associated with the id. If additional arguments are given, /// they are used to initialise the pin. See `init`. STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // Run an argument through the mapper and return the result. const pin_obj_t *pin = pin_find(args[0]); if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); } return (mp_obj_t)pin; } // fast method for getting/setting pin value STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); pin_obj_t *self = self_in; if (n_args == 0) { // get pin return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self)); } else { // set pin mp_hal_pin_write(self, mp_obj_is_true(args[0])); return mp_const_none; } } STATIC mp_obj_t pin_off(mp_obj_t self_in) { pin_obj_t *self = self_in; mp_hal_pin_low(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_off_obj, pin_off); STATIC mp_obj_t pin_on(mp_obj_t self_in) { pin_obj_t *self = self_in; mp_hal_pin_high(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_on_obj, pin_on); /// \classmethod mapper([fun]) /// Get or set the pin mapper function. STATIC mp_obj_t pin_mapper(mp_uint_t n_args, const mp_obj_t *args) { if (n_args > 1) { MP_STATE_PORT(pin_class_mapper) = args[1]; return mp_const_none; } return MP_STATE_PORT(pin_class_mapper); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_mapper_fun_obj, 1, 2, pin_mapper); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_mapper_obj, (mp_obj_t)&pin_mapper_fun_obj); /// \classmethod dict([dict]) /// Get or set the pin mapper dictionary. STATIC mp_obj_t pin_map_dict(mp_uint_t n_args, const mp_obj_t *args) { if (n_args > 1) { MP_STATE_PORT(pin_class_map_dict) = args[1]; return mp_const_none; } return MP_STATE_PORT(pin_class_map_dict); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_dict_fun_obj, 1, 2, pin_map_dict); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_map_dict_obj, (mp_obj_t)&pin_map_dict_fun_obj); /// \classmethod af_list() /// Returns an array of alternate functions available for this pin. STATIC mp_obj_t pin_af_list(mp_obj_t self_in) { pin_obj_t *self = self_in; mp_obj_t result = mp_obj_new_list(0, NULL); const pin_af_obj_t *af = self->af; for (mp_uint_t i = 0; i < self->num_af; i++, af++) { mp_obj_list_append(result, (mp_obj_t)af); } return result; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_list_obj, pin_af_list); #if PIN_DEBUG /// \classmethod debug([state]) /// Get or set the debugging state (`True` or `False` for on or off). STATIC mp_obj_t pin_debug(mp_uint_t n_args, const mp_obj_t *args) { if (n_args > 1) { pin_class_debug = mp_obj_is_true(args[1]); return mp_const_none; } return mp_obj_new_bool(pin_class_debug); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_debug_fun_obj, 1, 2, pin_debug); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, (mp_obj_t)&pin_debug_fun_obj); #endif // init(mode, pull=None, af=-1, *, value, alt) STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, { MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}}, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get pull mode nrf_gpio_pin_pull_t pull = NRF_GPIO_PIN_NOPULL; if (args[1].u_obj != mp_const_none) { pull = (nrf_gpio_pin_pull_t)mp_obj_get_int(args[1].u_obj); } // if given, set the pin value before initialising to prevent glitches if (args[3].u_obj != MP_OBJ_NULL) { mp_hal_pin_write(self, mp_obj_is_true(args[3].u_obj)); } // get io mode nrf_gpio_pin_dir_t mode = (nrf_gpio_pin_dir_t)args[0].u_int; // Connect input or not nrf_gpio_pin_input_t input = (mode == NRF_GPIO_PIN_DIR_INPUT) ? NRF_GPIO_PIN_INPUT_CONNECT : NRF_GPIO_PIN_INPUT_DISCONNECT; if (mode == NRF_GPIO_PIN_DIR_OUTPUT || mode == NRF_GPIO_PIN_DIR_INPUT) { nrf_gpio_cfg(self->pin, mode, input, pull, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin mode: %d", mode)); } return mp_const_none; } STATIC mp_obj_t pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); } MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init); /// \method value([value]) /// Get or set the digital logic level of the pin: /// /// - With no argument, return 0 or 1 depending on the logic level of the pin. /// - With `value` given, set the logic level of the pin. `value` can be /// anything that converts to a boolean. If it converts to `True`, the pin /// is set high, otherwise it is set low. STATIC mp_obj_t pin_value(mp_uint_t n_args, const mp_obj_t *args) { return pin_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value); /// \method low() /// Set the pin to a low logic level. STATIC mp_obj_t pin_low(mp_obj_t self_in) { pin_obj_t *self = self_in; mp_hal_pin_low(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low); /// \method high() /// Set the pin to a high logic level. STATIC mp_obj_t pin_high(mp_obj_t self_in) { pin_obj_t *self = self_in; mp_hal_pin_high(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_high_obj, pin_high); /// \method name() /// Get the pin name. STATIC mp_obj_t pin_name(mp_obj_t self_in) { pin_obj_t *self = self_in; return MP_OBJ_NEW_QSTR(self->name); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_name_obj, pin_name); /// \method names() /// Returns the cpu and board names for this pin. STATIC mp_obj_t pin_names(mp_obj_t self_in) { pin_obj_t *self = self_in; mp_obj_t result = mp_obj_new_list(0, NULL); mp_obj_list_append(result, MP_OBJ_NEW_QSTR(self->name)); mp_map_t *map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict); mp_map_elem_t *elem = map->table; for (mp_uint_t i = 0; i < map->used; i++, elem++) { if (elem->value == self) { mp_obj_list_append(result, elem->key); } } return result; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_names_obj, pin_names); /// \method port() /// Get the pin port. STATIC mp_obj_t pin_port(mp_obj_t self_in) { pin_obj_t *self = self_in; return MP_OBJ_NEW_SMALL_INT(self->pin / 32); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_port_obj, pin_port); /// \method pin() /// Get the pin number. STATIC mp_obj_t pin_pin(mp_obj_t self_in) { pin_obj_t *self = self_in; return MP_OBJ_NEW_SMALL_INT(self->pin); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pin_obj, pin_pin); /// \method mode() /// Returns the currently configured mode of the pin. The integer returned /// will match one of the allowed constants for the mode argument to the init /// function. STATIC mp_obj_t pin_mode(mp_obj_t self_in) { return mp_const_none; // TODO: MP_OBJ_NEW_SMALL_INT(pin_get_mode(self_in)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_mode_obj, pin_mode); /// \method pull() /// Returns the currently configured pull of the pin. The integer returned /// will match one of the allowed constants for the pull argument to the init /// function. STATIC mp_obj_t pin_pull(mp_obj_t self_in) { return mp_const_none; // TODO: MP_OBJ_NEW_SMALL_INT(pin_get_pull(self_in)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pull_obj, pin_pull); /// \method af() /// Returns the currently configured alternate-function of the pin. The /// integer returned will match one of the allowed constants for the af /// argument to the init function. STATIC mp_obj_t pin_af(mp_obj_t self_in) { return mp_const_none; // TODO: MP_OBJ_NEW_SMALL_INT(pin_get_af(self_in)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_obj, pin_af); STATIC void pin_common_irq_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { mp_obj_t pin_handler = MP_STATE_PORT(pin_irq_handlers)[pin]; mp_obj_t pin_number = MP_OBJ_NEW_SMALL_INT(pin); const pin_obj_t *pin_obj = pin_find(pin_number); mp_call_function_1(pin_handler, (mp_obj_t)pin_obj); } STATIC mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_handler, ARG_trigger, ARG_wake}; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = mp_const_none} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = NRF_GPIOTE_POLARITY_LOTOHI | NRF_GPIOTE_POLARITY_HITOLO} }, { MP_QSTR_wake, MP_ARG_BOOL, {.u_bool = false} }, }; pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); nrfx_gpiote_pin_t pin = self->pin; nrfx_gpiote_in_config_t config = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(true); if (args[ARG_trigger].u_int == NRF_GPIOTE_POLARITY_LOTOHI) { config.sense = NRF_GPIOTE_POLARITY_LOTOHI; } else if (args[ARG_trigger].u_int == NRF_GPIOTE_POLARITY_HITOLO) { config.sense = NRF_GPIOTE_POLARITY_HITOLO; } config.pull = NRF_GPIO_PIN_PULLUP; nrfx_err_t err_code = nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); if (err_code == NRFX_ERROR_INVALID_STATE) { // Re-init if already configured. nrfx_gpiote_in_uninit(pin); nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); } MP_STATE_PORT(pin_irq_handlers)[pin] = args[ARG_handler].u_obj; nrfx_gpiote_in_event_enable(pin, true); // return the irq object return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_irq_obj, 1, pin_irq); STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pin_init_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&pin_on_obj) }, { MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&pin_low_obj) }, { MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&pin_high_obj) }, { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&pin_name_obj) }, { MP_ROM_QSTR(MP_QSTR_names), MP_ROM_PTR(&pin_names_obj) }, { MP_ROM_QSTR(MP_QSTR_af_list), MP_ROM_PTR(&pin_af_list_obj) }, { MP_ROM_QSTR(MP_QSTR_port), MP_ROM_PTR(&pin_port_obj) }, { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&pin_pin_obj) }, { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&pin_mode_obj) }, { MP_ROM_QSTR(MP_QSTR_pull), MP_ROM_PTR(&pin_pull_obj) }, { MP_ROM_QSTR(MP_QSTR_af), MP_ROM_PTR(&pin_af_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pin_irq_obj) }, // class methods { MP_ROM_QSTR(MP_QSTR_mapper), MP_ROM_PTR(&pin_mapper_obj) }, { MP_ROM_QSTR(MP_QSTR_dict), MP_ROM_PTR(&pin_map_dict_obj) }, #if PIN_DEBUG { MP_ROM_QSTR(MP_QSTR_debug), MP_ROM_PTR(&pin_debug_obj) }, #endif // class attributes { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) }, { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&pin_cpu_pins_obj_type) }, // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(NRF_GPIO_PIN_DIR_INPUT) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(NRF_GPIO_PIN_DIR_OUTPUT) }, /* { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) }, { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_AF_PP) }, { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_AF_OD) }, { MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(GPIO_MODE_ANALOG) }, */ { MP_ROM_QSTR(MP_QSTR_PULL_DISABLED), MP_ROM_INT(NRF_GPIO_PIN_NOPULL) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(NRF_GPIO_PIN_PULLUP) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(NRF_GPIO_PIN_PULLDOWN) }, // IRQ triggers, can be or'd together { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(NRF_GPIOTE_POLARITY_LOTOHI) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(NRF_GPIOTE_POLARITY_HITOLO) }, /* // legacy class constants { MP_ROM_QSTR(MP_QSTR_OUT_PP), MP_ROM_INT(GPIO_MODE_OUTPUT_PP) }, { MP_ROM_QSTR(MP_QSTR_OUT_OD), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) }, { MP_ROM_QSTR(MP_QSTR_AF_PP), MP_ROM_INT(GPIO_MODE_AF_PP) }, { MP_ROM_QSTR(MP_QSTR_AF_OD), MP_ROM_INT(GPIO_MODE_AF_OD) }, { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(GPIO_NOPULL) }, */ #include "genhdr/pins_af_const.h" }; STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table); const mp_obj_type_t pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, .print = pin_print, .make_new = pin_make_new, .call = pin_call, .locals_dict = (mp_obj_dict_t*)&pin_locals_dict, }; /// \moduleref machine /// \class PinAF - Pin Alternate Functions /// /// A Pin represents a physical pin on the microcprocessor. Each pin /// can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF /// object represents a particular function for a pin. /// /// Usage Model: /// /// x3 = machine.Pin.board.X3 /// x3_af = x3.af_list() /// /// x3_af will now contain an array of PinAF objects which are availble on /// pin X3. /// /// For the pyboard, x3_af would contain: /// [Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2] /// /// Normally, each peripheral would configure the af automatically, but sometimes /// the same function is available on multiple pins, and having more control /// is desired. /// /// To configure X3 to expose TIM2_CH3, you could use: /// pin = machine.Pin(machine.Pin.board.X3, mode=machine.Pin.AF_PP, af=machine.Pin.AF1_TIM2) /// or: /// pin = machine.Pin(machine.Pin.board.X3, mode=machine.Pin.AF_PP, af=1) /// \method __str__() /// Return a string describing the alternate function. STATIC void pin_af_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pin_af_obj_t *self = self_in; mp_printf(print, "Pin.%q", self->name); } /// \method index() /// Return the alternate function index. STATIC mp_obj_t pin_af_index(mp_obj_t self_in) { pin_af_obj_t *af = self_in; return MP_OBJ_NEW_SMALL_INT(af->idx); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_index_obj, pin_af_index); /// \method name() /// Return the name of the alternate function. STATIC mp_obj_t pin_af_name(mp_obj_t self_in) { pin_af_obj_t *af = self_in; return MP_OBJ_NEW_QSTR(af->name); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_name_obj, pin_af_name); /// \method reg() /// Return the base register associated with the peripheral assigned to this /// alternate function. STATIC mp_obj_t pin_af_reg(mp_obj_t self_in) { pin_af_obj_t *af = self_in; return MP_OBJ_NEW_SMALL_INT((mp_uint_t)af->reg); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_reg_obj, pin_af_reg); STATIC const mp_rom_map_elem_t pin_af_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&pin_af_index_obj) }, { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&pin_af_name_obj) }, { MP_ROM_QSTR(MP_QSTR_reg), MP_ROM_PTR(&pin_af_reg_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table); const mp_obj_type_t pin_af_type = { { &mp_type_type }, .name = MP_QSTR_PinAF, .print = pin_af_obj_print, .locals_dict = (mp_obj_dict_t*)&pin_af_locals_dict, }; micropython-1.12/ports/nrf/modules/machine/pin.h000066400000000000000000000062151357706137100217750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __MICROPY_INCLUDED_NRF5_PIN_H__ #define __MICROPY_INCLUDED_NRF5_PIN_H__ // This file requires pin_defs_xxx.h (which has port specific enums and // defines, so we include it here. It should never be included directly #include MICROPY_PIN_DEFS_PORT_H #include "py/obj.h" typedef struct { mp_obj_base_t base; qstr name; uint8_t idx; uint8_t fn; uint8_t unit; uint8_t type; union { void *reg; PIN_DEFS_PORT_AF_UNION }; } pin_af_obj_t; typedef struct { mp_obj_base_t base; qstr name; uint32_t pin : 8; uint32_t num_af : 4; uint32_t adc_channel : 5; // Some ARM processors use 32 bits/PORT uint32_t adc_num : 3; // 1 bit per ADC const pin_af_obj_t *af; uint32_t pull; } pin_obj_t; extern const mp_obj_type_t pin_type; extern const mp_obj_type_t pin_af_type; typedef struct { const char *name; const pin_obj_t *pin; } pin_named_pin_t; extern const pin_named_pin_t pin_board_pins[]; extern const pin_named_pin_t pin_cpu_pins[]; //extern pin_map_obj_t pin_map_obj; typedef struct { mp_obj_base_t base; qstr name; const pin_named_pin_t *named_pins; } pin_named_pins_obj_t; extern const mp_obj_type_t pin_board_pins_obj_type; extern const mp_obj_type_t pin_cpu_pins_obj_type; extern const mp_obj_dict_t pin_cpu_pins_locals_dict; extern const mp_obj_dict_t pin_board_pins_locals_dict; MP_DECLARE_CONST_FUN_OBJ_KW(pin_init_obj); void pin_init0(void); uint32_t pin_get_mode(const pin_obj_t *pin); uint32_t pin_get_pull(const pin_obj_t *pin); uint32_t pin_get_af(const pin_obj_t *pin); const pin_obj_t *pin_find(mp_obj_t user_obj); const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name); const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit); const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx); const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name); #endif // __MICROPY_INCLUDED_NRF5_PIN_H__ micropython-1.12/ports/nrf/modules/machine/pwm.c000066400000000000000000000303521357706137100220040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016-2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #if MICROPY_PY_MACHINE_HW_PWM #include "pin.h" #include "genhdr/pins.h" #include "pwm.h" #if defined(NRF52_SERIES) // Use PWM hardware. #include "nrfx_pwm.h" #endif typedef enum { MODE_LOW_HIGH, MODE_HIGH_LOW } pwm_mode_t; typedef struct { uint8_t pwm_pin; uint8_t duty; uint16_t pulse_width; uint16_t period; nrf_pwm_clk_t freq; pwm_mode_t mode; } machine_pwm_config_t; typedef struct _machine_hard_pwm_obj_t { mp_obj_base_t base; const nrfx_pwm_t * p_pwm; machine_pwm_config_t * p_config; } machine_hard_pwm_obj_t; STATIC const nrfx_pwm_t machine_hard_pwm_instances[] = { #if defined(NRF52_SERIES) NRFX_PWM_INSTANCE(0), NRFX_PWM_INSTANCE(1), NRFX_PWM_INSTANCE(2), #if NRF52840 NRFX_PWM_INSTANCE(3), #endif #endif }; STATIC machine_pwm_config_t hard_configs[MP_ARRAY_SIZE(machine_hard_pwm_instances)]; STATIC const machine_hard_pwm_obj_t machine_hard_pwm_obj[] = { #if defined(NRF52_SERIES) {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[0], .p_config = &hard_configs[0]}, {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[1], .p_config = &hard_configs[1]}, {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[2], .p_config = &hard_configs[2]}, #if NRF52840 {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[3], .p_config = &hard_configs[3]}, #endif #endif }; void pwm_init0(void) { } STATIC int hard_pwm_find(mp_obj_t id) { if (mp_obj_is_int(id)) { // given an integer id int pwm_id = mp_obj_get_int(id); if (pwm_id >= 0 && pwm_id < MP_ARRAY_SIZE(machine_hard_pwm_obj)) { return pwm_id; } mp_raise_ValueError("PWM doesn't exist"); } return -1; } STATIC void machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hard_pwm_obj_t *self = self_in; mp_printf(print, "PWM(%u)", self->p_pwm->drv_inst_idx); } /******************************************************************************/ /* MicroPython bindings for machine API */ STATIC mp_obj_t machine_hard_pwm_make_new(mp_arg_val_t *args); STATIC void machine_hard_pwm_init(mp_obj_t self, mp_arg_val_t *args); STATIC void machine_hard_pwm_deinit(mp_obj_t self); STATIC mp_obj_t machine_hard_pwm_freq(mp_obj_t self, mp_arg_val_t *args); /* common code for both soft and hard implementations *************************/ STATIC mp_obj_t machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_pin, ARG_freq, ARG_period, ARG_duty, ARG_pulse_width, ARG_mode }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} }, { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_duty, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_pulse_width, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_id].u_obj == MP_OBJ_NEW_SMALL_INT(-1)) { // TODO: implement soft PWM // return machine_soft_pwm_make_new(args); return mp_const_none; } else { // hardware peripheral id given return machine_hard_pwm_make_new(args); } } STATIC mp_obj_t machine_pwm_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_INIT_pin }; static const mp_arg_t allowed_args[] = { { MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} } }; // parse args mp_obj_t self = pos_args[0]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // dispatch to specific implementation if (mp_obj_get_type(self) == &machine_hard_pwm_type) { machine_hard_pwm_init(self, args); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pwm_init_obj, 1, machine_pwm_init); STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self) { // dispatch to specific implementation if (mp_obj_get_type(self) == &machine_hard_pwm_type) { machine_hard_pwm_deinit(self); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pwm_deinit_obj, machine_pwm_deinit); STATIC mp_obj_t machine_pwm_freq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_FREQ_freq }; static const mp_arg_t allowed_args[] = { { MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} }, }; mp_obj_t self = pos_args[0]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (mp_obj_get_type(self) == &machine_hard_pwm_type) { machine_hard_pwm_freq(self, args); } else { // soft pwm } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_pwm_freq_obj, 1, machine_pwm_freq); STATIC mp_obj_t machine_pwm_period(size_t n_args, const mp_obj_t *args) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_pwm_period_obj, 1, 2, machine_pwm_period); STATIC mp_obj_t machine_pwm_duty(size_t n_args, const mp_obj_t *args) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_pwm_duty_obj, 1, 2, machine_pwm_duty); STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pwm_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_pwm_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&mp_machine_pwm_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&mp_machine_pwm_period_obj) }, { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&mp_machine_pwm_duty_obj) }, { MP_ROM_QSTR(MP_QSTR_FREQ_16MHZ), MP_ROM_INT(NRF_PWM_CLK_16MHz) }, { MP_ROM_QSTR(MP_QSTR_FREQ_8MHZ), MP_ROM_INT(NRF_PWM_CLK_8MHz) }, { MP_ROM_QSTR(MP_QSTR_FREQ_4MHZ), MP_ROM_INT(NRF_PWM_CLK_4MHz) }, { MP_ROM_QSTR(MP_QSTR_FREQ_2MHZ), MP_ROM_INT(NRF_PWM_CLK_2MHz) }, { MP_ROM_QSTR(MP_QSTR_FREQ_1MHZ), MP_ROM_INT(NRF_PWM_CLK_1MHz) }, { MP_ROM_QSTR(MP_QSTR_FREQ_500KHZ), MP_ROM_INT(NRF_PWM_CLK_500kHz) }, { MP_ROM_QSTR(MP_QSTR_FREQ_250KHZ), MP_ROM_INT(NRF_PWM_CLK_250kHz) }, { MP_ROM_QSTR(MP_QSTR_FREQ_125KHZ), MP_ROM_INT(NRF_PWM_CLK_125kHz) }, { MP_ROM_QSTR(MP_QSTR_MODE_LOW_HIGH), MP_ROM_INT(MODE_LOW_HIGH) }, { MP_ROM_QSTR(MP_QSTR_MODE_HIGH_LOW), MP_ROM_INT(MODE_HIGH_LOW) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict, machine_pwm_locals_dict_table); /* code for hard implementation ***********************************************/ STATIC mp_obj_t machine_hard_pwm_make_new(mp_arg_val_t *args) { enum { ARG_id, ARG_pin, ARG_freq, ARG_period, ARG_duty, ARG_pulse_width, ARG_mode }; // get static peripheral object int pwm_id = hard_pwm_find(args[ARG_id].u_obj); const machine_hard_pwm_obj_t *self = &machine_hard_pwm_obj[pwm_id]; // check if PWM pin is set if (args[ARG_pin].u_obj != MP_OBJ_NULL) { self->p_config->pwm_pin = mp_hal_get_pin_obj(args[ARG_pin].u_obj)->pin; } else { // TODO: raise exception. } if (args[ARG_freq].u_obj != MP_OBJ_NULL) { self->p_config->freq = mp_obj_get_int(args[ARG_freq].u_obj); } else { self->p_config->freq = 50; // 50 Hz by default. } if (args[ARG_period].u_obj != MP_OBJ_NULL) { self->p_config->period = mp_obj_get_int(args[ARG_period].u_obj); } else { mp_raise_ValueError("PWM period must be within 16000 cycles"); } if (args[ARG_duty].u_obj != MP_OBJ_NULL) { self->p_config->duty = mp_obj_get_int(args[ARG_duty].u_obj); } else { self->p_config->duty = 50; // 50% by default. } if (args[ARG_pulse_width].u_obj != MP_OBJ_NULL) { self->p_config->pulse_width = mp_obj_get_int(args[ARG_pulse_width].u_obj); } else { self->p_config->pulse_width = 0; } if (args[ARG_mode].u_obj != MP_OBJ_NULL) { self->p_config->mode = mp_obj_get_int(args[ARG_mode].u_obj); } else { self->p_config->mode = MODE_HIGH_LOW; } return MP_OBJ_FROM_PTR(self); } STATIC void machine_hard_pwm_init(mp_obj_t self_in, mp_arg_val_t *args) { machine_hard_pwm_obj_t *self = self_in; nrfx_pwm_config_t config; config.output_pins[0] = self->p_config->pwm_pin; config.output_pins[1] = NRFX_PWM_PIN_NOT_USED; config.output_pins[2] = NRFX_PWM_PIN_NOT_USED; config.output_pins[3] = NRFX_PWM_PIN_NOT_USED; config.irq_priority = 6; config.base_clock = self->p_config->freq; config.count_mode = NRF_PWM_MODE_UP; config.top_value = self->p_config->period; config.load_mode = NRF_PWM_LOAD_INDIVIDUAL; config.step_mode = NRF_PWM_STEP_AUTO; nrfx_pwm_init(self->p_pwm, &config, NULL); uint16_t pulse_width = ((self->p_config->period * self->p_config->duty) / 100); // If manual period has been set, override duty-cycle. if (self->p_config->pulse_width > 0) { pulse_width = self->p_config->pulse_width; } // TODO: Move DMA buffer to global memory. volatile static uint16_t pwm_seq[4]; if (self->p_config->mode == MODE_HIGH_LOW) { pwm_seq[0] = self->p_config->period - pulse_width; pwm_seq[1] = self->p_config->period - pulse_width; } else { pwm_seq[0] = self->p_config->period - pulse_width; pwm_seq[1] = self->p_config->period - pulse_width; } pwm_seq[2] = self->p_config->period - pulse_width; pwm_seq[3] = self->p_config->period - pulse_width; const nrf_pwm_sequence_t pwm_sequence = { .values.p_raw = (const uint16_t *)&pwm_seq, .length = 4, .repeats = 0, .end_delay = 0 }; nrfx_pwm_simple_playback(self->p_pwm, &pwm_sequence, 0, // Loop disabled. 0); } STATIC void machine_hard_pwm_deinit(mp_obj_t self_in) { machine_hard_pwm_obj_t *self = self_in; (void)self; nrfx_pwm_stop(self->p_pwm, true); nrfx_pwm_uninit(self->p_pwm); } STATIC mp_obj_t machine_hard_pwm_freq(mp_obj_t self_in, mp_arg_val_t *args) { machine_hard_pwm_obj_t *self = self_in; (void)self; return mp_const_none; } const mp_obj_type_t machine_hard_pwm_type = { { &mp_type_type }, .name = MP_QSTR_PWM, .print = machine_pwm_print, .make_new = machine_pwm_make_new, .locals_dict = (mp_obj_dict_t*)&machine_pwm_locals_dict, }; #endif // MICROPY_PY_MACHINE_HW_PWM micropython-1.12/ports/nrf/modules/machine/pwm.h000066400000000000000000000024311357706137100220060ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016-2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ void pwm_init0(void); extern const mp_obj_type_t machine_hard_pwm_type; micropython-1.12/ports/nrf/modules/machine/rtcounter.c000066400000000000000000000215621357706137100232310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * Copyright (c) 2018 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/nlr.h" #include "py/runtime.h" #include "rtcounter.h" #include "nrfx_rtc.h" #include "nrf_clock.h" #if MICROPY_PY_MACHINE_RTCOUNTER // Count every 125ms (~maximum prescaler setting) #define RTC_FREQUENCY (8UL) enum { RTC_MODE_ONESHOT, RTC_MODE_PERIODIC, }; // Volatile part of the RTCounter object. typedef struct { mp_obj_t callback; uint32_t period; } machine_rtc_config_t; // Non-volatile part of the RTCounter object. typedef struct _machine_rtc_obj_t { mp_obj_base_t base; const nrfx_rtc_t * p_rtc; // Driver instance nrfx_rtc_handler_t handler; // interrupt callback machine_rtc_config_t * config; // pointer to volatile part } machine_rtc_obj_t; STATIC const nrfx_rtc_t machine_rtc_instances[] = { NRFX_RTC_INSTANCE(0), NRFX_RTC_INSTANCE(1), #if defined(NRF52_SERIES) NRFX_RTC_INSTANCE(2), #endif }; STATIC machine_rtc_config_t configs[MP_ARRAY_SIZE(machine_rtc_instances)]; STATIC void interrupt_handler0(nrfx_rtc_int_type_t int_type); STATIC void interrupt_handler1(nrfx_rtc_int_type_t int_type); #if defined(NRF52_SERIES) STATIC void interrupt_handler2(nrfx_rtc_int_type_t int_type); #endif STATIC const machine_rtc_obj_t machine_rtc_obj[] = { {{&machine_rtcounter_type}, .p_rtc = &machine_rtc_instances[0], .handler=interrupt_handler0, .config=&configs[0]}, {{&machine_rtcounter_type}, .p_rtc = &machine_rtc_instances[1], .handler=interrupt_handler1, .config=&configs[1]}, #if defined(NRF52_SERIES) {{&machine_rtcounter_type}, .p_rtc = &machine_rtc_instances[2], .handler=interrupt_handler2, .config=&configs[2]}, #endif }; STATIC void interrupt_handler(size_t instance_id) { const machine_rtc_obj_t * self = &machine_rtc_obj[instance_id]; machine_rtc_config_t *config = self->config; if (config->callback != NULL) { mp_call_function_1((mp_obj_t)config->callback, (mp_obj_t)self); } if (config->period == 0) { nrfx_rtc_cc_disable(self->p_rtc, 0); } else { // periodic uint32_t val = nrfx_rtc_counter_get(self->p_rtc) + config->period; nrfx_rtc_cc_set(self->p_rtc, 0, val, true); } } STATIC void interrupt_handler0(nrfx_rtc_int_type_t int_type) { interrupt_handler(0); } STATIC void interrupt_handler1(nrfx_rtc_int_type_t int_type) { interrupt_handler(1); } #if defined(NRF52_SERIES) STATIC void interrupt_handler2(nrfx_rtc_int_type_t int_type) { interrupt_handler(2); } #endif void rtc_init0(void) { } STATIC int rtc_find(mp_obj_t id) { // given an integer id int rtc_id = mp_obj_get_int(id); if (rtc_id >= 0 && rtc_id < MP_ARRAY_SIZE(machine_rtc_obj)) { return rtc_id; } mp_raise_ValueError("RTCounter doesn't exist"); } STATIC void rtc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_rtc_obj_t *self = self_in; mp_printf(print, "RTCounter(%u)", self->p_rtc->instance_id); } /******************************************************************************/ /* MicroPython bindings for machine API */ const nrfx_rtc_config_t machine_rtc_config = { .prescaler = RTC_FREQ_TO_PRESCALER(RTC_FREQUENCY), .reliable = 0, .tick_latency = 0, // ignored when reliable == 0 #ifdef NRF51 .interrupt_priority = 3, #else .interrupt_priority = 6, #endif }; STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_period, ARG_mode, ARG_callback }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = RTC_FREQUENCY} }, // 1 second { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = RTC_MODE_PERIODIC} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); int rtc_id = rtc_find(args[ARG_id].u_obj); // const and non-const part of the RTC object. const machine_rtc_obj_t * self = &machine_rtc_obj[rtc_id]; machine_rtc_config_t *config = self->config; if (args[ARG_callback].u_obj == mp_const_none) { config->callback = NULL; } else if (mp_obj_is_fun(args[ARG_callback].u_obj)) { config->callback = args[ARG_callback].u_obj; } else { mp_raise_ValueError("callback must be a function"); } // Periodic or one-shot if (args[ARG_mode].u_int == RTC_MODE_ONESHOT) { // One-shot config->period = 0; } else { // Period between the intervals config->period = args[ARG_period].u_int; } // Start the low-frequency clock (if it hasn't been started already) if (!nrf_clock_lf_is_running()) { nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART); } // Make sure it's uninitialized. nrfx_rtc_uninit(self->p_rtc); nrfx_rtc_counter_clear(self->p_rtc); // Initialize and set the correct IRQ. nrfx_rtc_init(self->p_rtc, &machine_rtc_config, self->handler); nrfx_rtc_cc_set(self->p_rtc, 0 /*channel*/, args[ARG_period].u_int, true /*enable irq*/); return MP_OBJ_FROM_PTR(self); } /// \method start() /// Start the RTCounter. Timeout occurs after number of periods /// in the configured frequency has been reached. /// STATIC mp_obj_t machine_rtc_start(mp_obj_t self_in) { machine_rtc_obj_t * self = MP_OBJ_TO_PTR(self_in); nrfx_rtc_enable(self->p_rtc); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_start_obj, machine_rtc_start); /// \method stop() /// Stop the RTCounter. /// STATIC mp_obj_t machine_rtc_stop(mp_obj_t self_in) { machine_rtc_obj_t * self = MP_OBJ_TO_PTR(self_in); nrfx_rtc_disable(self->p_rtc); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_stop_obj, machine_rtc_stop); /// \method counter() /// Return the current counter value. Wraps around after about 24 days /// with the current prescaler (2^24 / 8 = 2097152 seconds). /// STATIC mp_obj_t machine_rtc_counter(mp_obj_t self_in) { machine_rtc_obj_t * self = MP_OBJ_TO_PTR(self_in); uint32_t counter = nrfx_rtc_counter_get(self->p_rtc); return MP_OBJ_NEW_SMALL_INT(counter); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_counter_obj, machine_rtc_counter); /// \method deinit() /// Free resources associated with this RTC. /// STATIC mp_obj_t machine_rtc_deinit(mp_obj_t self_in) { machine_rtc_obj_t * self = MP_OBJ_TO_PTR(self_in); nrfx_rtc_uninit(self->p_rtc); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_deinit_obj, machine_rtc_deinit); STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_rtc_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_rtc_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_counter), MP_ROM_PTR(&machine_rtc_counter_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_rtc_deinit_obj) }, // constants { MP_ROM_QSTR(MP_QSTR_ONESHOT), MP_ROM_INT(RTC_MODE_ONESHOT) }, { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(RTC_MODE_PERIODIC) }, { MP_ROM_QSTR(MP_QSTR_FREQUENCY), MP_ROM_INT(RTC_FREQUENCY) }, }; STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); const mp_obj_type_t machine_rtcounter_type = { { &mp_type_type }, .name = MP_QSTR_RTCounter, .print = rtc_print, .make_new = machine_rtc_make_new, .locals_dict = (mp_obj_dict_t*)&machine_rtc_locals_dict }; #endif // MICROPY_PY_MACHINE_RTCOUNTER micropython-1.12/ports/nrf/modules/machine/rtcounter.h000066400000000000000000000025331357706137100232330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef RTCOUNTER_H__ #define RTCOUNTER_H__ extern const mp_obj_type_t machine_rtcounter_type; void rtc_init0(void); #endif // RTCOUNTER_H__ micropython-1.12/ports/nrf/modules/machine/spi.c000066400000000000000000000400561357706137100217760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 - 2018 Glenn Ruben Bakke * Copyright (c) 2018 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_MACHINE_HW_SPI #include "py/nlr.h" #include "py/mphal.h" #include "extmod/machine_spi.h" #include "pin.h" #include "genhdr/pins.h" #include "spi.h" #if NRFX_SPI_ENABLED #include "nrfx_spi.h" #else #include "nrfx_spim.h" #endif /// \moduleref machine /// \class SPI - a master-driven serial protocol /// /// SPI is a serial protocol that is driven by a master. At the physical level /// there are 3 lines: SCK, MOSI, MISO. /// /// See usage model of I2C; SPI is very similar. Main difference is /// parameters to init the SPI bus: /// /// from machine import SPI /// spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7) /// /// Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be /// 0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1 /// to sample data on the first or second clock edge respectively. Crc can be /// None for no CRC, or a polynomial specifier. /// /// Additional method for SPI: /// /// data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes /// buf = bytearray(4) /// spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf /// spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf #if NRFX_SPIM_ENABLED #define nrfx_spi_t nrfx_spim_t #define nrfx_spi_config_t nrfx_spim_config_t #define nrfx_spi_xfer_desc_t nrfx_spim_xfer_desc_t #define NRFX_SPI_PIN_NOT_USED NRFX_SPIM_PIN_NOT_USED #define NRFX_SPI_INSTANCE NRFX_SPIM_INSTANCE #define NRF_SPI_BIT_ORDER_LSB_FIRST NRF_SPIM_BIT_ORDER_LSB_FIRST #define NRF_SPI_BIT_ORDER_MSB_FIRST NRF_SPIM_BIT_ORDER_MSB_FIRST #define NRF_SPI_MODE_0 NRF_SPIM_MODE_0 #define NRF_SPI_MODE_1 NRF_SPIM_MODE_1 #define NRF_SPI_MODE_2 NRF_SPIM_MODE_2 #define NRF_SPI_MODE_3 NRF_SPIM_MODE_3 #define NRF_SPI_FREQ_125K NRF_SPIM_FREQ_125K #define NRF_SPI_FREQ_250K NRF_SPIM_FREQ_250K #define NRF_SPI_FREQ_500K NRF_SPIM_FREQ_500K #define NRF_SPI_FREQ_1M NRF_SPIM_FREQ_1M #define NRF_SPI_FREQ_2M NRF_SPIM_FREQ_2M #define NRF_SPI_FREQ_4M NRF_SPIM_FREQ_4M #define NRF_SPI_FREQ_8M NRF_SPIM_FREQ_8M #define nrfx_spi_init nrfx_spim_init #define nrfx_spi_uninit nrfx_spim_uninit #define nrfx_spi_xfer nrfx_spim_xfer #endif // NRFX_SPIM_ENABLED typedef struct _machine_hard_spi_obj_t { mp_obj_base_t base; const nrfx_spi_t * p_spi; // Driver instance nrfx_spi_config_t * p_config; // pointer to volatile part } machine_hard_spi_obj_t; STATIC const nrfx_spi_t machine_spi_instances[] = { NRFX_SPI_INSTANCE(0), NRFX_SPI_INSTANCE(1), #if defined(NRF52_SERIES) NRFX_SPI_INSTANCE(2), #if defined(NRF52840_XXAA) && NRFX_SPIM_ENABLED NRFX_SPI_INSTANCE(3), #endif // NRF52840_XXAA && NRFX_SPIM_ENABLED #endif // NRF52_SERIES }; STATIC nrfx_spi_config_t configs[MP_ARRAY_SIZE(machine_spi_instances)]; STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = { {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[0], .p_config = &configs[0]}, {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[1], .p_config = &configs[1]}, #if defined(NRF52_SERIES) {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[2], .p_config = &configs[2]}, #if defined(NRF52840_XXAA) && NRFX_SPIM_ENABLED {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[3], .p_config = &configs[3]}, #endif // NRF52840_XXAA && NRFX_SPIM_ENABLED #endif // NRF52_SERIES }; void spi_init0(void) { } STATIC int spi_find(mp_obj_t id) { if (mp_obj_is_str(id)) { // given a string id const char *port = mp_obj_str_get_str(id); if (0) { #ifdef MICROPY_HW_SPI0_NAME } else if (strcmp(port, MICROPY_HW_SPI0_NAME) == 0) { return 1; #endif } mp_raise_ValueError("SPI doesn't exist"); } else { // given an integer id int spi_id = mp_obj_get_int(id); if (spi_id >= 0 && spi_id < MP_ARRAY_SIZE(machine_hard_spi_obj)) { return spi_id; } mp_raise_ValueError("SPI doesn't exist"); } } void spi_transfer(const machine_hard_spi_obj_t * self, size_t len, const void * src, void * dest) { nrfx_spi_xfer_desc_t xfer_desc = { .p_tx_buffer = src, .tx_length = len, .p_rx_buffer = dest, .rx_length = len }; nrfx_spi_xfer(self->p_spi, &xfer_desc, 0); } /******************************************************************************/ /* MicroPython bindings for machine API */ // for make_new enum { ARG_NEW_id, ARG_NEW_baudrate, ARG_NEW_polarity, ARG_NEW_phase, ARG_NEW_bits, ARG_NEW_firstbit, ARG_NEW_sck, ARG_NEW_mosi, ARG_NEW_miso }; // for init enum { ARG_INIT_baudrate, ARG_INIT_polarity, ARG_INIT_phase, ARG_INIT_bits, ARG_INIT_firstbit }; STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args); STATIC void machine_hard_spi_init(mp_obj_t self, mp_arg_val_t *args); STATIC void machine_hard_spi_deinit(mp_obj_t self); /* common code for both soft and hard implementations *************************/ STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 1000000} }, { MP_QSTR_polarity, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_phase, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_firstbit, MP_ARG_INT, {.u_int = 0 /* SPI_FIRSTBIT_MSB */} }, { MP_QSTR_sck, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mosi, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_miso, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_NEW_id].u_obj == MP_OBJ_NEW_SMALL_INT(-1)) { // TODO: implement soft SPI // return machine_soft_spi_make_new(args); return mp_const_none; } else { // hardware peripheral id given return machine_hard_spi_make_new(args); } } STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; // parse args mp_obj_t self = pos_args[0]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // dispatch to specific implementation if (mp_obj_get_type(self) == &machine_hard_spi_type) { machine_hard_spi_init(self, args); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init); STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) { // dispatch to specific implementation if (mp_obj_get_type(self) == &machine_hard_spi_type) { machine_hard_spi_deinit(self); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit); STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_spi_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(NRF_SPI_BIT_ORDER_MSB_FIRST) }, { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(NRF_SPI_BIT_ORDER_LSB_FIRST) }, }; STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, machine_spi_locals_dict_table); /* code for hard implementation ***********************************************/ STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hard_spi_obj_t *self = self_in; mp_printf(print, "SPI(%u)", self->p_spi->drv_inst_idx); } STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args) { // get static peripheral object int spi_id = spi_find(args[ARG_NEW_id].u_obj); const machine_hard_spi_obj_t *self = &machine_hard_spi_obj[spi_id]; // here we would check the sck/mosi/miso pins and configure them if (args[ARG_NEW_sck].u_obj != MP_OBJ_NULL && args[ARG_NEW_mosi].u_obj != MP_OBJ_NULL && args[ARG_NEW_miso].u_obj != MP_OBJ_NULL) { self->p_config->sck_pin = mp_hal_get_pin_obj(args[ARG_NEW_sck].u_obj)->pin; self->p_config->mosi_pin = mp_hal_get_pin_obj(args[ARG_NEW_mosi].u_obj)->pin; self->p_config->miso_pin = mp_hal_get_pin_obj(args[ARG_NEW_miso].u_obj)->pin; } else { self->p_config->sck_pin = MICROPY_HW_SPI0_SCK; self->p_config->mosi_pin = MICROPY_HW_SPI0_MOSI; self->p_config->miso_pin = MICROPY_HW_SPI0_MISO; } // Manually trigger slave select from upper layer. self->p_config->ss_pin = NRFX_SPI_PIN_NOT_USED; #ifdef NRF51 self->p_config->irq_priority = 3; #else self->p_config->irq_priority = 6; #endif mp_obj_t self_obj = MP_OBJ_FROM_PTR(self); machine_hard_spi_init(self_obj, &args[1]); // Skip instance id param. return self_obj; } STATIC void machine_hard_spi_init(mp_obj_t self_in, mp_arg_val_t *args) { const machine_hard_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); int baudrate = args[ARG_INIT_baudrate].u_int; if (baudrate <= 125000) { self->p_config->frequency = NRF_SPI_FREQ_125K; } else if (baudrate <= 250000) { self->p_config->frequency = NRF_SPI_FREQ_250K; } else if (baudrate <= 500000) { self->p_config->frequency = NRF_SPI_FREQ_500K; } else if (baudrate <= 1000000) { self->p_config->frequency = NRF_SPI_FREQ_1M; } else if (baudrate <= 2000000) { self->p_config->frequency = NRF_SPI_FREQ_2M; } else if (baudrate <= 4000000) { self->p_config->frequency = NRF_SPI_FREQ_4M; } else if (baudrate <= 8000000) { self->p_config->frequency = NRF_SPI_FREQ_8M; #if defined(NRF52840_XXAA) && NRFX_SPIM_ENABLED } else if (baudrate <= 16000000) { self->p_config->frequency = NRF_SPIM_FREQ_16M; } else if (baudrate <= 32000000) { self->p_config->frequency = NRF_SPIM_FREQ_32M; #endif // NRF52840_XXAA && NRFX_SPIM_ENABLED } else { // Default self->p_config->frequency = NRF_SPI_FREQ_1M; } // Active high if (args[ARG_INIT_polarity].u_int == 0) { if (args[ARG_INIT_phase].u_int == 0) { // First clock edge self->p_config->mode = NRF_SPI_MODE_0; } else { // Second clock edge self->p_config->mode = NRF_SPI_MODE_1; } // Active low } else { if (args[ARG_INIT_phase].u_int == 0) { // First clock edge self->p_config->mode = NRF_SPI_MODE_2; } else { // Second clock edge self->p_config->mode = NRF_SPI_MODE_3; } } self->p_config->orc = 0xFF; // Overrun character self->p_config->bit_order = (args[ARG_INIT_firstbit].u_int == 0) ? NRF_SPI_BIT_ORDER_MSB_FIRST : NRF_SPI_BIT_ORDER_LSB_FIRST; // Set context to this instance of SPI nrfx_err_t err_code = nrfx_spi_init(self->p_spi, self->p_config, NULL, (void *)self); if (err_code == NRFX_ERROR_INVALID_STATE) { // Instance already initialized, deinitialize first. nrfx_spi_uninit(self->p_spi); // Initialize again. nrfx_spi_init(self->p_spi, self->p_config, NULL, (void *)self); } } STATIC void machine_hard_spi_deinit(mp_obj_t self_in) { const machine_hard_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); nrfx_spi_uninit(self->p_spi); } STATIC void machine_hard_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { const machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in; spi_transfer(self, len, src, dest); } STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) { vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(args[1])); memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len); spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read); STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); memset(bufinfo.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, bufinfo.len); spi_transfer(args[0], bufinfo.len, bufinfo.buf, bufinfo.buf); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto); STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self, mp_obj_t wr_buf) { mp_buffer_info_t src; mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); spi_transfer(self, src.len, (const uint8_t*)src.buf, NULL); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write); STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self, mp_obj_t wr_buf, mp_obj_t rd_buf) { mp_buffer_info_t src; mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); mp_buffer_info_t dest; mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE); if (src.len != dest.len) { mp_raise_ValueError("buffers must be the same length"); } spi_transfer(self, src.len, src.buf, dest.buf); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto); STATIC const mp_machine_spi_p_t machine_hard_spi_p = { .transfer = machine_hard_spi_transfer, }; const mp_obj_type_t machine_hard_spi_type = { { &mp_type_type }, .name = MP_QSTR_SPI, .print = machine_hard_spi_print, .make_new = machine_spi_make_new, .protocol = &machine_hard_spi_p, .locals_dict = (mp_obj_dict_t*)&machine_spi_locals_dict, }; #endif // MICROPY_PY_MACHINE_HW_SPI micropython-1.12/ports/nrf/modules/machine/spi.h000066400000000000000000000031661357706137100220040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 - 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" typedef struct _machine_hard_spi_obj_t machine_hard_spi_obj_t; extern const mp_obj_type_t machine_hard_spi_type; void spi_init0(void); void spi_transfer(const machine_hard_spi_obj_t * self, size_t len, const void * src, void * dest); micropython-1.12/ports/nrf/modules/machine/temp.c000066400000000000000000000070201357706137100221420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Bander F. Ajba * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" #if MICROPY_PY_MACHINE_TEMP #include "temp.h" #include "nrf_temp.h" #if BLUETOOTH_SD #include "py/nlr.h" #include "ble_drv.h" #include "nrf_soc.h" #define BLUETOOTH_STACK_ENABLED() (ble_drv_stack_enabled()) #endif // BLUETOOTH_SD typedef struct _machine_temp_obj_t { mp_obj_base_t base; } machine_temp_obj_t; /// \method __str__() /// Return a string describing the Temp object. STATIC void machine_temp_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { machine_temp_obj_t *self = o; (void)self; mp_printf(print, "Temp"); } /******************************************************************************/ /* MicroPython bindings for machine API */ STATIC mp_obj_t machine_temp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = { { }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); machine_temp_obj_t *self = m_new_obj(machine_temp_obj_t); self->base.type = &machine_temp_type; return MP_OBJ_FROM_PTR(self); } /// \method read() /// Get temperature. STATIC mp_obj_t machine_temp_read(mp_uint_t n_args, const mp_obj_t *args) { #if BLUETOOTH_SD if (BLUETOOTH_STACK_ENABLED() == 1) { int32_t temp; (void)sd_temp_get(&temp); return MP_OBJ_NEW_SMALL_INT(temp / 4); // resolution of 0.25 degree celsius } #endif // BLUETOOTH_SD return MP_OBJ_NEW_SMALL_INT(nrf_temp_read()); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_temp_read_obj, 0, 1, machine_temp_read); STATIC const mp_rom_map_elem_t machine_temp_locals_dict_table[] = { // instance methods // class methods { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_temp_read_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_temp_locals_dict, machine_temp_locals_dict_table); const mp_obj_type_t machine_temp_type = { { &mp_type_type }, .name = MP_QSTR_Temp, .make_new = machine_temp_make_new, .locals_dict = (mp_obj_dict_t*)&machine_temp_locals_dict, .print = machine_temp_print, }; #endif // MICROPY_PY_MACHINE_TEMP micropython-1.12/ports/nrf/modules/machine/temp.h000066400000000000000000000025071357706137100221540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Bander F. Ajba * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef TEMP_H__ #define TEMP_H__ extern const mp_obj_type_t machine_temp_type; int32_t temp_read(void); #endif // TEMP_H__ micropython-1.12/ports/nrf/modules/machine/timer.c000066400000000000000000000201671357706137100223240ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/nlr.h" #include "py/runtime.h" #include "timer.h" #include "nrfx_timer.h" #if MICROPY_PY_MACHINE_TIMER enum { TIMER_MODE_ONESHOT, TIMER_MODE_PERIODIC, }; typedef struct _machine_timer_obj_t { mp_obj_base_t base; nrfx_timer_t p_instance; } machine_timer_obj_t; STATIC mp_obj_t machine_timer_callbacks[] = { NULL, NULL, NULL, #if defined(NRF52_SERIES) NULL, NULL, #endif }; STATIC const machine_timer_obj_t machine_timer_obj[] = { {{&machine_timer_type}, NRFX_TIMER_INSTANCE(0)}, #if MICROPY_PY_MACHINE_SOFT_PWM { }, #else {{&machine_timer_type}, NRFX_TIMER_INSTANCE(1)}, #endif {{&machine_timer_type}, NRFX_TIMER_INSTANCE(2)}, #if defined(NRF52_SERIES) {{&machine_timer_type}, NRFX_TIMER_INSTANCE(3)}, {{&machine_timer_type}, NRFX_TIMER_INSTANCE(4)}, #endif }; void timer_init0(void) { for (int i = 0; i < MP_ARRAY_SIZE(machine_timer_obj); i++) { nrfx_timer_uninit(&machine_timer_obj[i].p_instance); } } STATIC int timer_find(mp_obj_t id) { // given an integer id int timer_id = mp_obj_get_int(id); if (timer_id >= 0 && timer_id < MP_ARRAY_SIZE(machine_timer_obj)) { return timer_id; } mp_raise_ValueError("Timer doesn't exist"); } STATIC void timer_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { machine_timer_obj_t *self = o; mp_printf(print, "Timer(%u)", self->p_instance.instance_id); } STATIC void timer_event_handler(nrf_timer_event_t event_type, void *p_context) { machine_timer_obj_t *self = p_context; mp_obj_t callback = machine_timer_callbacks[self->p_instance.instance_id]; if (callback != NULL) { mp_call_function_1(callback, self); } } /******************************************************************************/ /* MicroPython bindings for machine API */ STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_period, ARG_mode, ARG_callback }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, // 1 second { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_MODE_PERIODIC} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get static peripheral object int timer_id = timer_find(args[ARG_id].u_obj); #if BLUETOOTH_SD if (timer_id == 0) { mp_raise_ValueError("Timer reserved by Bluetooth LE stack"); } #endif #if MICROPY_PY_MACHINE_SOFT_PWM if (timer_id == 1) { mp_raise_ValueError("Timer reserved by ticker driver"); } #endif machine_timer_obj_t *self = (machine_timer_obj_t*)&machine_timer_obj[timer_id]; if (mp_obj_is_fun(args[ARG_callback].u_obj)) { machine_timer_callbacks[timer_id] = args[ARG_callback].u_obj; } else if (args[ARG_callback].u_obj == mp_const_none) { machine_timer_callbacks[timer_id] = NULL; } else { mp_raise_ValueError("callback must be a function"); } // Timer peripheral usage: // Every timer instance has a numer of capture/compare (CC) registers. // These can store either the value to compare against (to trigger an // interrupt or a shortcut) or store a value returned from a // capture/compare event. // We use channel 0 for comparing (to trigger the callback and clear // shortcut) and channel 1 for capturing the current time. const nrfx_timer_config_t config = { .frequency = NRF_TIMER_FREQ_1MHz, .mode = NRF_TIMER_MODE_TIMER, .bit_width = NRF_TIMER_BIT_WIDTH_24, #ifdef NRF51 .interrupt_priority = 3, #else .interrupt_priority = 6, #endif .p_context = self, }; // Initialize the drive. // When it is already initialized, this is a no-op. nrfx_timer_init(&self->p_instance, &config, timer_event_handler); // Configure channel 0. nrf_timer_short_mask_t short_mask = NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK | ((args[ARG_mode].u_int == TIMER_MODE_ONESHOT) ? NRF_TIMER_SHORT_COMPARE0_STOP_MASK : 0); bool enable_interrupts = true; nrfx_timer_extended_compare( &self->p_instance, NRF_TIMER_CC_CHANNEL0, args[ARG_period].u_int, short_mask, enable_interrupts); return MP_OBJ_FROM_PTR(self); } /// \method period() /// Return counter value, which is currently in us. /// STATIC mp_obj_t machine_timer_period(mp_obj_t self_in) { machine_timer_obj_t * self = MP_OBJ_TO_PTR(self_in); uint32_t period = nrfx_timer_capture(&self->p_instance, NRF_TIMER_CC_CHANNEL1); return MP_OBJ_NEW_SMALL_INT(period); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_period_obj, machine_timer_period); /// \method start() /// Start the timer. /// STATIC mp_obj_t machine_timer_start(mp_obj_t self_in) { machine_timer_obj_t * self = MP_OBJ_TO_PTR(self_in); nrfx_timer_enable(&self->p_instance); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_start_obj, machine_timer_start); /// \method stop() /// Stop the timer. /// STATIC mp_obj_t machine_timer_stop(mp_obj_t self_in) { machine_timer_obj_t * self = MP_OBJ_TO_PTR(self_in); nrfx_timer_disable(&self->p_instance); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_stop_obj, machine_timer_stop); /// \method deinit() /// Free resources associated with the timer. /// STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) { machine_timer_obj_t * self = MP_OBJ_TO_PTR(self_in); nrfx_timer_uninit(&self->p_instance); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&machine_timer_period_obj) }, // alias { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&machine_timer_period_obj) }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_timer_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_timer_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) }, // constants { MP_ROM_QSTR(MP_QSTR_ONESHOT), MP_ROM_INT(TIMER_MODE_ONESHOT) }, { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_MODE_PERIODIC) }, }; STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); const mp_obj_type_t machine_timer_type = { { &mp_type_type }, .name = MP_QSTR_Timer, .print = timer_print, .make_new = machine_timer_make_new, .locals_dict = (mp_obj_dict_t*)&machine_timer_locals_dict }; #endif // MICROPY_PY_MACHINE_TIMER micropython-1.12/ports/nrf/modules/machine/timer.h000066400000000000000000000025151357706137100223260ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef TIMER_H__ #define TIMER_H__ extern const mp_obj_type_t machine_timer_type; void timer_init0(void); #endif // TIMER_H__ micropython-1.12/ports/nrf/modules/machine/uart.c000066400000000000000000000306121357706137100221530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Glenn Ruben Bakke * Copyright (c) 2018 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/nlr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "py/ringbuf.h" #include "pin.h" #include "genhdr/pins.h" #include "lib/utils/interrupt_char.h" #include "uart.h" #include "mpconfigboard.h" #include "nrf.h" #include "mphalport.h" #if NRFX_UART_ENABLED #include "nrfx_uart.h" #else #include "nrfx_uarte.h" #endif #if MICROPY_PY_MACHINE_UART typedef struct _machine_hard_uart_buf_t { uint8_t tx_buf[1]; uint8_t rx_buf[1]; uint8_t rx_ringbuf_array[64]; volatile ringbuf_t rx_ringbuf; } machine_hard_uart_buf_t; #if NRFX_UARTE_ENABLED #define nrfx_uart_t nrfx_uarte_t #define nrfx_uart_config_t nrfx_uarte_config_t #define nrfx_uart_rx nrfx_uarte_rx #define nrfx_uart_tx nrfx_uarte_tx #define nrfx_uart_tx_in_progress nrfx_uarte_tx_in_progress #define nrfx_uart_init nrfx_uarte_init #define nrfx_uart_event_t nrfx_uarte_event_t #define NRFX_UART_INSTANCE NRFX_UARTE_INSTANCE #define NRF_UART_HWFC_ENABLED NRF_UARTE_HWFC_ENABLED #define NRF_UART_HWFC_DISABLED NRF_UARTE_HWFC_DISABLED #define NRF_UART_PARITY_EXCLUDED NRF_UARTE_PARITY_EXCLUDED #define NRFX_UART_EVT_RX_DONE NRFX_UARTE_EVT_RX_DONE #define NRF_UART_BAUDRATE_1200 NRF_UARTE_BAUDRATE_1200 #define NRF_UART_BAUDRATE_2400 NRF_UARTE_BAUDRATE_2400 #define NRF_UART_BAUDRATE_4800 NRF_UARTE_BAUDRATE_4800 #define NRF_UART_BAUDRATE_9600 NRF_UARTE_BAUDRATE_9600 #define NRF_UART_BAUDRATE_14400 NRF_UARTE_BAUDRATE_14400 #define NRF_UART_BAUDRATE_19200 NRF_UARTE_BAUDRATE_19200 #define NRF_UART_BAUDRATE_28800 NRF_UARTE_BAUDRATE_28800 #define NRF_UART_BAUDRATE_38400 NRF_UARTE_BAUDRATE_38400 #define NRF_UART_BAUDRATE_57600 NRF_UARTE_BAUDRATE_57600 #define NRF_UART_BAUDRATE_76800 NRF_UARTE_BAUDRATE_76800 #define NRF_UART_BAUDRATE_115200 NRF_UARTE_BAUDRATE_115200 #define NRF_UART_BAUDRATE_230400 NRF_UARTE_BAUDRATE_230400 #define NRF_UART_BAUDRATE_250000 NRF_UARTE_BAUDRATE_250000 #define NRF_UART_BAUDRATE_1000000 NRF_UARTE_BAUDRATE_1000000 #endif typedef struct _machine_hard_uart_obj_t { mp_obj_base_t base; const nrfx_uart_t * p_uart; // Driver instance machine_hard_uart_buf_t *buf; } machine_hard_uart_obj_t; static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE(0); STATIC machine_hard_uart_buf_t machine_hard_uart_buf[1]; STATIC const machine_hard_uart_obj_t machine_hard_uart_obj[] = { {{&machine_hard_uart_type}, .p_uart = &instance0, .buf = &machine_hard_uart_buf[0]}, }; void uart_init0(void) { } STATIC int uart_find(mp_obj_t id) { // given an integer id int uart_id = mp_obj_get_int(id); if (uart_id >= 0 && uart_id < MP_ARRAY_SIZE(machine_hard_uart_obj)) { return uart_id; } mp_raise_ValueError("UART doesn't exist"); } STATIC void uart_event_handler(nrfx_uart_event_t const *p_event, void *p_context) { machine_hard_uart_obj_t *self = p_context; if (p_event->type == NRFX_UART_EVT_RX_DONE) { int chr = self->buf->rx_buf[0]; nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1); #if !MICROPY_PY_BLE_NUS && MICROPY_KBD_EXCEPTION if (chr == mp_interrupt_char) { mp_keyboard_interrupt(); } else #endif { ringbuf_put((ringbuf_t*)&self->buf->rx_ringbuf, chr); } } } bool uart_rx_any(const machine_hard_uart_obj_t *self) { return self->buf->rx_ringbuf.iput != self->buf->rx_ringbuf.iget; } int uart_rx_char(const machine_hard_uart_obj_t * self) { return ringbuf_get((ringbuf_t*)&self->buf->rx_ringbuf); } STATIC nrfx_err_t uart_tx_char(const machine_hard_uart_obj_t * self, int c) { while (nrfx_uart_tx_in_progress(self->p_uart)) { ; } self->buf->tx_buf[0] = c; return nrfx_uart_tx(self->p_uart, &self->buf->tx_buf[0], 1); } void uart_tx_strn(const machine_hard_uart_obj_t *uart_obj, const char *str, uint len) { for (const char *top = str + len; str < top; str++) { uart_tx_char(uart_obj, *str); } } void uart_tx_strn_cooked(const machine_hard_uart_obj_t *uart_obj, const char *str, uint len) { for (const char *top = str + len; str < top; str++) { if (*str == '\n') { uart_tx_char(uart_obj, '\r'); } uart_tx_char(uart_obj, *str); } } /******************************************************************************/ /* MicroPython bindings */ STATIC void machine_hard_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_printf(print, "UART(0)"); } /// \method init(id, baudrate) /// /// Initialise the UART bus with the given parameters: /// - `id`is bus id. /// - `baudrate` is the clock rate. STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_baudrate }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get static peripheral object int uart_id = uart_find(args[ARG_id].u_obj); const machine_hard_uart_obj_t * self = &machine_hard_uart_obj[uart_id]; nrfx_uart_config_t config; // flow control #if MICROPY_HW_UART1_HWFC config.hwfc = NRF_UART_HWFC_ENABLED; #else config.hwfc = NRF_UART_HWFC_DISABLED; #endif config.parity = NRF_UART_PARITY_EXCLUDED; #if (BLUETOOTH_SD == 100) config.interrupt_priority = 3; #else config.interrupt_priority = 6; #endif // These baudrates are not supported, it seems. if (args[ARG_baudrate].u_int < 1200 || args[ARG_baudrate].u_int > 1000000) { mp_raise_ValueError("UART baudrate not supported"); } // Magic: calculate 'baudrate' register from the input number. // Every value listed in the datasheet will be converted to the // correct register value, except for 192600. I believe the value // listed in the nrf52 datasheet (0x0EBED000) is incorrectly rounded // and should be 0x0EBEE000, as the nrf51 datasheet lists the // nonrounded value 0x0EBEDFA4. // Some background: // https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values/2046#2046 config.baudrate = args[ARG_baudrate].u_int / 400 * (uint32_t)(400ULL * (uint64_t)UINT32_MAX / 16000000ULL); config.baudrate = (config.baudrate + 0x800) & 0xffffff000; // rounding config.pseltxd = MICROPY_HW_UART1_TX; config.pselrxd = MICROPY_HW_UART1_RX; #if MICROPY_HW_UART1_HWFC config.pselrts = MICROPY_HW_UART1_RTS; config.pselcts = MICROPY_HW_UART1_CTS; #endif // Set context to this instance of UART config.p_context = (void *)self; // Initialise ring buffer self->buf->rx_ringbuf.buf = self->buf->rx_ringbuf_array; self->buf->rx_ringbuf.size = sizeof(self->buf->rx_ringbuf_array); self->buf->rx_ringbuf.iget = 0; self->buf->rx_ringbuf.iput = 0; // Enable event callback and start asynchronous receive nrfx_uart_init(self->p_uart, &config, uart_event_handler); nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1); #if NRFX_UART_ENABLED nrfx_uart_rx_enable(self->p_uart); #endif return MP_OBJ_FROM_PTR(self); } /// \method writechar(char) /// Write a single character on the bus. `char` is an integer to write. /// Return value: `None`. STATIC mp_obj_t machine_hard_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { machine_hard_uart_obj_t *self = self_in; // get the character to write (might be 9 bits) int data = mp_obj_get_int(char_in); nrfx_err_t err = uart_tx_char(self, data); if (err != NRFX_SUCCESS) { mp_hal_raise(err); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hard_uart_writechar_obj, machine_hard_uart_writechar); /// \method readchar() /// Receive a single character on the bus. /// Return value: The character read, as an integer. Returns -1 on timeout. STATIC mp_obj_t machine_hard_uart_readchar(mp_obj_t self_in) { machine_hard_uart_obj_t *self = self_in; return MP_OBJ_NEW_SMALL_INT(uart_rx_char(self)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hard_uart_readchar_obj, machine_hard_uart_readchar); // uart.sendbreak() STATIC mp_obj_t machine_hard_uart_sendbreak(mp_obj_t self_in) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hard_uart_sendbreak_obj, machine_hard_uart_sendbreak); STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_hard_uart_writechar_obj) }, { MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_hard_uart_readchar_obj) }, { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_hard_uart_sendbreak_obj) }, // class constants /* { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, */ }; STATIC MP_DEFINE_CONST_DICT(machine_hard_uart_locals_dict, machine_hard_uart_locals_dict_table); STATIC mp_uint_t machine_hard_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { const machine_hard_uart_obj_t *self = self_in; byte *buf = buf_in; // read the data for (size_t i = 0; i < size; i++) { while (!uart_rx_any(self)) { } buf[i] = uart_rx_char(self); } return size; } STATIC mp_uint_t machine_hard_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { machine_hard_uart_obj_t *self = self_in; const byte *buf = buf_in; nrfx_err_t err = NRFX_SUCCESS; for (int i = 0; i < size; i++) { err = uart_tx_char(self, (int)((uint8_t *)buf)[i]); } if (err == NRFX_SUCCESS) { // return number of bytes written return size; } else { *errcode = mp_hal_status_to_errno_table[err]; return MP_STREAM_ERROR; } } STATIC mp_uint_t machine_hard_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { machine_hard_uart_obj_t *self = self_in; (void)self; return MP_STREAM_ERROR; } STATIC const mp_stream_p_t uart_stream_p = { .read = machine_hard_uart_read, .write = machine_hard_uart_write, .ioctl = machine_hard_uart_ioctl, .is_text = false, }; const mp_obj_type_t machine_hard_uart_type = { { &mp_type_type }, .name = MP_QSTR_UART, .print = machine_hard_uart_print, .make_new = machine_hard_uart_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &uart_stream_p, .locals_dict = (mp_obj_dict_t*)&machine_hard_uart_locals_dict, }; #endif // MICROPY_PY_MACHINE_UART micropython-1.12/ports/nrf/modules/machine/uart.h000066400000000000000000000035221357706137100221600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 - 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef UART_H__ #define UART_H__ #include "pin.h" #include "genhdr/pins.h" typedef struct _machine_hard_uart_obj_t machine_hard_uart_obj_t; extern const mp_obj_type_t machine_hard_uart_type; void uart_init0(void); void uart_deinit(void); void uart_irq_handler(mp_uint_t uart_id); bool uart_rx_any(const machine_hard_uart_obj_t * uart_obj); int uart_rx_char(const machine_hard_uart_obj_t * uart_obj); void uart_tx_strn(const machine_hard_uart_obj_t * uart_obj, const char *str, uint len); void uart_tx_strn_cooked(const machine_hard_uart_obj_t *uart_obj, const char *str, uint len); #endif micropython-1.12/ports/nrf/modules/music/000077500000000000000000000000001357706137100205465ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/music/modmusic.c000066400000000000000000000450321357706137100225360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mphal.h" #if MICROPY_PY_MUSIC // #include "microbitobj.h" // #include "microbitmusic.h" #include "py/obj.h" #include "py/runtime.h" #include "py/objstr.h" #include "modmusic.h" #include "musictunes.h" #include "softpwm.h" #include "ticker.h" #include "pin.h" #include "genhdr/pins.h" #define DEFAULT_BPM 120 #define DEFAULT_TICKS 4 // i.e. 4 ticks per beat #define DEFAULT_OCTAVE 4 // C4 is middle C #define DEFAULT_DURATION 4 // Crotchet #define ARTICULATION_MS 10 // articulation between notes in milliseconds typedef struct _music_data_t { uint16_t bpm; uint16_t ticks; // store these to simplify the writing process uint8_t last_octave; uint8_t last_duration; // Asynchronous parts. volatile uint8_t async_state; bool async_loop; uint32_t async_wait_ticks; uint16_t async_notes_len; uint16_t async_notes_index; const pin_obj_t *async_pin; mp_obj_t async_note; } music_data_t; enum { ASYNC_MUSIC_STATE_IDLE, ASYNC_MUSIC_STATE_NEXT_NOTE, ASYNC_MUSIC_STATE_ARTICULATE, }; #define music_data MP_STATE_PORT(music_data) extern volatile uint32_t ticks; STATIC uint32_t start_note(const char *note_str, size_t note_len, const pin_obj_t *pin); void microbit_music_init0(void) { ticker_register_low_pri_callback(microbit_music_tick); } void microbit_music_tick(void) { if (music_data == NULL) { // music module not yet imported return; } if (music_data->async_state == ASYNC_MUSIC_STATE_IDLE) { // nothing to do return; } if (ticks < music_data->async_wait_ticks) { // need to wait for timeout to expire return; } if (music_data->async_state == ASYNC_MUSIC_STATE_ARTICULATE) { // turn off output and rest pwm_set_duty_cycle(music_data->async_pin->pin, 0); // TODO: remove pin setting. music_data->async_wait_ticks = ticks + ARTICULATION_MS; music_data->async_state = ASYNC_MUSIC_STATE_NEXT_NOTE; } else if (music_data->async_state == ASYNC_MUSIC_STATE_NEXT_NOTE) { // play next note if (music_data->async_notes_index >= music_data->async_notes_len) { if (music_data->async_loop) { music_data->async_notes_index = 0; } else { music_data->async_state = ASYNC_MUSIC_STATE_IDLE; // TODO: microbit_obj_pin_free(music_data->async_pin); music_data->async_pin = NULL; return; } } mp_obj_t note; if (music_data->async_notes_len == 1) { note = music_data->async_note; } else { note = ((mp_obj_t*)music_data->async_note)[music_data->async_notes_index]; } if (note == mp_const_none) { // a rest (is this even used anymore?) pwm_set_duty_cycle(music_data->async_pin->pin, 0); // TODO: remove pin setting. music_data->async_wait_ticks = 60000 / music_data->bpm; music_data->async_state = ASYNC_MUSIC_STATE_NEXT_NOTE; } else { // a note size_t note_len; const char *note_str = mp_obj_str_get_data(note, ¬e_len); uint32_t delay_on = start_note(note_str, note_len, music_data->async_pin); music_data->async_wait_ticks = ticks + delay_on; music_data->async_notes_index += 1; music_data->async_state = ASYNC_MUSIC_STATE_ARTICULATE; } } } STATIC void wait_async_music_idle(void) { // wait for the async music state to become idle while (music_data->async_state != ASYNC_MUSIC_STATE_IDLE) { // allow CTRL-C to stop the music if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { music_data->async_state = ASYNC_MUSIC_STATE_IDLE; pwm_set_duty_cycle(music_data->async_pin->pin, 0); // TODO: remove pin setting. break; } } } STATIC uint32_t start_note(const char *note_str, size_t note_len, const pin_obj_t *pin) { pwm_set_duty_cycle(pin->pin, 128); // TODO: remove pin setting. // [NOTE](#|b)(octave)(:length) // technically, c4 is middle c, so we'll go with that... // if we define A as 0 and G as 7, then we can use the following // array of us periods // these are the periods of note4 (the octave ascending from middle c) from A->B then C->G STATIC uint16_t periods_us[] = {2273, 2025, 3822, 3405, 3034, 2863, 2551}; // A#, -, C#, D#, -, F#, G# STATIC uint16_t periods_sharps_us[] = {2145, 0, 3608, 3214, 0, 2703, 2408}; // we'll represent the note as an integer (A=0, G=6) // TODO: validate the note uint8_t note_index = (note_str[0] & 0x1f) - 1; // TODO: the duration and bpm should be persistent between notes uint32_t ms_per_tick = (60000 / music_data->bpm) / music_data->ticks; int8_t octave = 0; bool sharp = false; size_t current_position = 1; // parse sharp or flat if (current_position < note_len && (note_str[current_position] == '#' || note_str[current_position] == 'b')) { if (note_str[current_position] == 'b') { // make sure we handle wrapping round gracefully if (note_index == 0) { note_index = 6; } else { note_index--; } // handle the unusual edge case of Cb if (note_index == 1) { octave--; } } sharp = true; current_position++; } // parse the octave if (current_position < note_len && note_str[current_position] != ':') { // currently this will only work with a one digit number // use +=, since the sharp/flat code changes octave to compensate. music_data->last_octave = (note_str[current_position] & 0xf); current_position++; } octave += music_data->last_octave; // parse the duration if (current_position < note_len && note_str[current_position] == ':') { // I'll make this handle up to two digits for the time being. current_position++; if (current_position < note_len) { music_data->last_duration = note_str[current_position] & 0xf; current_position++; if (current_position < note_len) { music_data->last_duration *= 10; music_data->last_duration += note_str[current_position] & 0xf; } } else { // technically, this should be a syntax error, since this means // that no duration has been specified. For the time being, // we'll let you off :D } } // play the note! // make the octave relative to octave 4 octave -= 4; // 18 is 'r' or 'R' if (note_index < 10) { uint32_t period; if (sharp) { if (octave >= 0) { period = periods_sharps_us[note_index] >> octave; } else { period = periods_sharps_us[note_index] << -octave; } } else { if (octave >= 0) { period = periods_us[note_index] >> octave; } else { period = periods_us[note_index] << -octave; } } pwm_set_period_us(period); } else { pwm_set_duty_cycle(pin->pin, 0); // TODO: remove pin setting. } // Cut off a short time from end of note so we hear articulation. mp_int_t gap_ms = (ms_per_tick * music_data->last_duration) - ARTICULATION_MS; if (gap_ms < ARTICULATION_MS) { gap_ms = ARTICULATION_MS; } return gap_ms; } STATIC mp_obj_t microbit_music_reset(void) { music_data->bpm = DEFAULT_BPM; music_data->ticks = DEFAULT_TICKS; music_data->last_octave = DEFAULT_OCTAVE; music_data->last_duration = DEFAULT_DURATION; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(microbit_music_reset_obj, microbit_music_reset); STATIC mp_obj_t microbit_music_get_tempo(void) { mp_obj_t tempo_tuple[2]; tempo_tuple[0] = mp_obj_new_int(music_data->bpm); tempo_tuple[1] = mp_obj_new_int(music_data->ticks); return mp_obj_new_tuple(2, tempo_tuple); } MP_DEFINE_CONST_FUN_OBJ_0(microbit_music_get_tempo_obj, microbit_music_get_tempo); STATIC mp_obj_t microbit_music_stop(mp_uint_t n_args, const mp_obj_t *args) { const pin_obj_t *pin; if (n_args == 0) { #ifdef MICROPY_HW_MUSIC_PIN pin = mp_hal_get_pin_obj(MP_OBJ_NEW_SMALL_INT(MICROPY_HW_MUSIC_PIN)); #else mp_raise_ValueError("pin parameter not given"); #endif } else { pin = (pin_obj_t *)args[0]; } (void)pin; // Raise exception if the pin we are trying to stop is not in a compatible mode. // TODO: microbit_obj_pin_acquire(pin, microbit_pin_mode_music); pwm_set_duty_cycle(pin->pin, 0); // TODO: remove pin setting. // TODO: microbit_obj_pin_free(pin); music_data->async_pin = NULL; music_data->async_state = ASYNC_MUSIC_STATE_IDLE; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(microbit_music_stop_obj, 0, 1, microbit_music_stop); STATIC mp_obj_t microbit_music_play(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_music, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_wait, MP_ARG_BOOL, {.u_bool = true} }, { MP_QSTR_loop, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // reset octave and duration so tunes always play the same music_data->last_octave = DEFAULT_OCTAVE; music_data->last_duration = DEFAULT_DURATION; // get either a single note or a list of notes mp_uint_t len; mp_obj_t *items; if (mp_obj_is_str_or_bytes(args[0].u_obj)) { len = 1; items = &args[0].u_obj; } else { mp_obj_get_array(args[0].u_obj, &len, &items); } // Release the previous pin // TODO: microbit_obj_pin_free(music_data->async_pin); music_data->async_pin = NULL; // get the pin to play on const pin_obj_t *pin; if (args[1].u_obj == MP_OBJ_NULL) { #ifdef MICROPY_HW_MUSIC_PIN pin = mp_hal_get_pin_obj(MP_OBJ_NEW_SMALL_INT(MICROPY_HW_MUSIC_PIN)); #else mp_raise_ValueError("pin parameter not given"); #endif } else { pin = (pin_obj_t *)args[1].u_obj; } // TODO: microbit_obj_pin_acquire(pin, microbit_pin_mode_music); // start the tune running in the background music_data->async_state = ASYNC_MUSIC_STATE_IDLE; music_data->async_wait_ticks = ticks; music_data->async_loop = args[3].u_bool; music_data->async_notes_len = len; music_data->async_notes_index = 0; if (len == 1) { // If a string was passed as a single note then we can't store a pointer // to args[0].u_obj, so instead store the single string directly (also // works if a tuple/list of one element was passed). music_data->async_note = items[0]; } else { music_data->async_note = items; } music_data->async_pin = pin; music_data->async_state = ASYNC_MUSIC_STATE_NEXT_NOTE; if (args[2].u_bool) { // wait for tune to finish wait_async_music_idle(); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(microbit_music_play_obj, 0, microbit_music_play); STATIC mp_obj_t microbit_music_pitch(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_duration, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_wait, MP_ARG_BOOL, {.u_bool = true} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the parameters mp_uint_t frequency = args[0].u_int; mp_int_t duration = args[1].u_int; // get the pin to play on const pin_obj_t *pin; if (args[2].u_obj == MP_OBJ_NULL) { #ifdef MICROPY_HW_MUSIC_PIN pin = mp_hal_get_pin_obj(MP_OBJ_NEW_SMALL_INT(MICROPY_HW_MUSIC_PIN)); #else mp_raise_ValueError("pin parameter not given"); #endif } else { pin = (pin_obj_t *)args[2].u_obj; } // Update pin modes //TODO: microbit_obj_pin_free(music_data->async_pin); music_data->async_pin = NULL; //TODO: microbit_obj_pin_acquire(pin, microbit_pin_mode_music); bool wait = args[3].u_bool; pwm_set_duty_cycle(pin->pin, 128); // TODO: remove pin setting. if (frequency == 0) { //TODO: pwm_release(pin->name); } else if (pwm_set_period_us(1000000/frequency)) { pwm_release(pin->pin); // TODO: remove pin setting. mp_raise_ValueError("invalid pitch"); } if (duration >= 0) { // use async machinery to stop the pitch after the duration music_data->async_state = ASYNC_MUSIC_STATE_IDLE; music_data->async_wait_ticks = ticks + duration; music_data->async_loop = false; music_data->async_notes_len = 0; music_data->async_notes_index = 0; music_data->async_note = NULL; music_data->async_pin = pin; music_data->async_state = ASYNC_MUSIC_STATE_ARTICULATE; if (wait) { // wait for the pitch to finish wait_async_music_idle(); } } else { // don't block here, since there's no reason to leave a pitch forever in a blocking C function } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(microbit_music_pitch_obj, 0, microbit_music_pitch); STATIC mp_obj_t microbit_music_set_tempo(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_ticks, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bpm, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[0].u_int != 0) { // set ticks music_data->ticks = args[0].u_int; } if (args[1].u_int != 0) { music_data->bpm = args[1].u_int; } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(microbit_music_set_tempo_obj, 0, microbit_music_set_tempo); static mp_obj_t music_init(void) { music_data = m_new_obj(music_data_t); music_data->bpm = DEFAULT_BPM; music_data->ticks = DEFAULT_TICKS; music_data->last_octave = DEFAULT_OCTAVE; music_data->last_duration = DEFAULT_DURATION; music_data->async_state = ASYNC_MUSIC_STATE_IDLE; music_data->async_pin = NULL; music_data->async_note = NULL; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(music___init___obj, music_init); STATIC const mp_rom_map_elem_t microbit_music_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&music___init___obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(µbit_music_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_set_tempo), MP_ROM_PTR(µbit_music_set_tempo_obj) }, { MP_ROM_QSTR(MP_QSTR_get_tempo), MP_ROM_PTR(µbit_music_get_tempo_obj) }, { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(µbit_music_play_obj) }, { MP_ROM_QSTR(MP_QSTR_pitch), MP_ROM_PTR(µbit_music_pitch_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(µbit_music_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_DADADADUM), MP_ROM_PTR(µbit_music_tune_dadadadum_obj) }, { MP_ROM_QSTR(MP_QSTR_ENTERTAINER), MP_ROM_PTR(µbit_music_tune_entertainer_obj) }, { MP_ROM_QSTR(MP_QSTR_PRELUDE), MP_ROM_PTR(µbit_music_tune_prelude_obj) }, { MP_ROM_QSTR(MP_QSTR_ODE), MP_ROM_PTR(µbit_music_tune_ode_obj) }, { MP_ROM_QSTR(MP_QSTR_NYAN), MP_ROM_PTR(µbit_music_tune_nyan_obj) }, { MP_ROM_QSTR(MP_QSTR_RINGTONE), MP_ROM_PTR(µbit_music_tune_ringtone_obj) }, { MP_ROM_QSTR(MP_QSTR_FUNK), MP_ROM_PTR(µbit_music_tune_funk_obj) }, { MP_ROM_QSTR(MP_QSTR_BLUES), MP_ROM_PTR(µbit_music_tune_blues_obj) }, { MP_ROM_QSTR(MP_QSTR_BIRTHDAY), MP_ROM_PTR(µbit_music_tune_birthday_obj) }, { MP_ROM_QSTR(MP_QSTR_WEDDING), MP_ROM_PTR(µbit_music_tune_wedding_obj) }, { MP_ROM_QSTR(MP_QSTR_FUNERAL), MP_ROM_PTR(µbit_music_tune_funeral_obj) }, { MP_ROM_QSTR(MP_QSTR_PUNCHLINE), MP_ROM_PTR(µbit_music_tune_punchline_obj) }, { MP_ROM_QSTR(MP_QSTR_PYTHON), MP_ROM_PTR(µbit_music_tune_python_obj) }, { MP_ROM_QSTR(MP_QSTR_BADDY), MP_ROM_PTR(µbit_music_tune_baddy_obj) }, { MP_ROM_QSTR(MP_QSTR_CHASE), MP_ROM_PTR(µbit_music_tune_chase_obj) }, { MP_ROM_QSTR(MP_QSTR_BA_DING), MP_ROM_PTR(µbit_music_tune_ba_ding_obj) }, { MP_ROM_QSTR(MP_QSTR_WAWAWAWAA), MP_ROM_PTR(µbit_music_tune_wawawawaa_obj) }, { MP_ROM_QSTR(MP_QSTR_JUMP_UP), MP_ROM_PTR(µbit_music_tune_jump_up_obj) }, { MP_ROM_QSTR(MP_QSTR_JUMP_DOWN), MP_ROM_PTR(µbit_music_tune_jump_down_obj) }, { MP_ROM_QSTR(MP_QSTR_POWER_UP), MP_ROM_PTR(µbit_music_tune_power_up_obj) }, { MP_ROM_QSTR(MP_QSTR_POWER_DOWN), MP_ROM_PTR(µbit_music_tune_power_down_obj) }, }; STATIC MP_DEFINE_CONST_DICT(microbit_music_locals_dict, microbit_music_locals_dict_table); const mp_obj_module_t music_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)µbit_music_locals_dict, }; #endif // MICROPY_PY_MUSIC micropython-1.12/ports/nrf/modules/music/modmusic.h000066400000000000000000000003171357706137100225400ustar00rootroot00000000000000#ifndef __MICROPY_INCLUDED_MICROBIT_MUSIC_H__ #define __MICROPY_INCLUDED_MICROBIT_MUSIC_H__ void microbit_music_init0(void); void microbit_music_tick(void); #endif // __MICROPY_INCLUDED_MICROBIT_MUSIC_H__ micropython-1.12/ports/nrf/modules/music/musictunes.c000066400000000000000000000171721357706137100231210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The music encoded herein is either in the public domain, composed by * Nicholas H.Tollervey or the composer is untraceable and covered by fair * (educational) use. * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * Copyright (c) 2015 Nicholas H. Tollervey * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mphal.h" #include "py/objtuple.h" #if MICROPY_PY_MUSIC #define N(q) MP_ROM_QSTR(MP_QSTR_ ## q) #define T(name, ...) \ typedef struct music_tune_ ## name ## _s {\ mp_obj_base_t base; \ size_t len; \ mp_rom_obj_t items[sizeof((mp_obj_t[]){__VA_ARGS__})/sizeof(mp_obj_t)]; \ } music_tune_ ## name ## _t; \ \ const music_tune_ ## name ## _t microbit_music_tune_ ## name ## _obj = {{&mp_type_tuple}, .len = (sizeof((mp_obj_t[]){__VA_ARGS__})/sizeof(mp_obj_t)), .items = {__VA_ARGS__}}; T(dadadadum, N(r4_colon_2), N(g), N(g), N(g), N(eb_colon_8), N(r_colon_2), N(f), N(f), N(f), N(d_colon_8)); T(entertainer, N(d4_colon_1), N(d_hash_), N(e), N(c5_colon_2), N(e4_colon_1), N(c5_colon_2), N(e4_colon_1), N(c5_colon_3), N(c_colon_1), N(d), N(d_hash_), N(e), N(c), N(d), N(e_colon_2), N(b4_colon_1), N(d5_colon_2), N(c_colon_4)); T(prelude, N(c4_colon_1), N(e), N(g), N(c5), N(e), N(g4), N(c5), N(e), N(c4), N(e), N(g), N(c5), N(e), N(g4), N(c5), N(e), N(c4), N(d), N(g), N(d5), N(f), N(g4), N(d5), N(f), N(c4), N(d), N(g), N(d5), N(f), N(g4), N(d5), N(f), N(b3), N(d4), N(g), N(d5), N(f), N(g4), N(d5), N(f), N(b3), N(d4), N(g), N(d5), N(f), N(g4), N(d5), N(f), N(c4), N(e), N(g), N(c5), N(e), N(g4), N(c5), N(e), N(c4), N(e), N(g), N(c5), N(e), N(g4), N(c5), N(e)); T(ode, N(e4), N(e), N(f), N(g), N(g), N(f), N(e), N(d), N(c), N(c), N(d), N(e), N(e_colon_6), N(d_colon_2), N(d_colon_8), N(e_colon_4), N(e), N(f), N(g), N(g), N(f), N(e), N(d), N(c), N(c), N(d), N(e), N(d_colon_6), N(c_colon_2), N(c_colon_8)); T(nyan, N(f_hash_5_colon_2), N(g_hash_), N(c_hash__colon_1), N(d_hash__colon_2), N(b4_colon_1), N(d5_colon_1), N(c_hash_), N(b4_colon_2), N(b), N(c_hash_5), N(d), N(d_colon_1), N(c_hash_), N(b4_colon_1), N(c_hash_5_colon_1), N(d_hash_), N(f_hash_), N(g_hash_), N(d_hash_), N(f_hash_), N(c_hash_), N(d), N(b4), N(c_hash_5), N(b4), N(d_hash_5_colon_2), N(f_hash_), N(g_hash__colon_1), N(d_hash_), N(f_hash_), N(c_hash_), N(d_hash_), N(b4), N(d5), N(d_hash_), N(d), N(c_hash_), N(b4), N(c_hash_5), N(d_colon_2), N(b4_colon_1), N(c_hash_5), N(d_hash_), N(f_hash_), N(c_hash_), N(d), N(c_hash_), N(b4), N(c_hash_5_colon_2), N(b4), N(c_hash_5), N(b4), N(f_hash__colon_1), N(g_hash_), N(b_colon_2), N(f_hash__colon_1), N(g_hash_), N(b), N(c_hash_5), N(d_hash_), N(b4), N(e5), N(d_hash_), N(e), N(f_hash_), N(b4_colon_2), N(b), N(f_hash__colon_1), N(g_hash_), N(b), N(f_hash_), N(e5), N(d_hash_), N(c_hash_), N(b4), N(f_hash_), N(d_hash_), N(e), N(f_hash_), N(b_colon_2), N(f_hash__colon_1), N(g_hash_), N(b_colon_2), N(f_hash__colon_1), N(g_hash_), N(b), N(b), N(c_hash_5), N(d_hash_), N(b4), N(f_hash_), N(g_hash_), N(f_hash_), N(b_colon_2), N(b_colon_1), N(a_hash_), N(b), N(f_hash_), N(g_hash_), N(b), N(e5), N(d_hash_), N(e), N(f_hash_), N(b4_colon_2), N(c_hash_5)); T(ringtone, N(c4_colon_1), N(d), N(e_colon_2), N(g), N(d_colon_1), N(e), N(f_colon_2), N(a), N(e_colon_1), N(f), N(g_colon_2), N(b), N(c5_colon_4)); T(funk, N(c2_colon_2), N(c), N(d_hash_), N(c_colon_1), N(f_colon_2), N(c_colon_1), N(f_colon_2), N(f_hash_), N(g), N(c), N(c), N(g), N(c_colon_1), N(f_hash__colon_2), N(c_colon_1), N(f_hash__colon_2), N(f), N(d_hash_)); T(blues, N(c2_colon_2), N(e), N(g), N(a), N(a_hash_), N(a), N(g), N(e), N(c2_colon_2), N(e), N(g), N(a), N(a_hash_), N(a), N(g), N(e), N(f), N(a), N(c3), N(d), N(d_hash_), N(d), N(c), N(a2), N(c2_colon_2), N(e), N(g), N(a), N(a_hash_), N(a), N(g), N(e), N(g), N(b), N(d3), N(f), N(f2), N(a), N(c3), N(d_hash_), N(c2_colon_2), N(e), N(g), N(e), N(g), N(f), N(e), N(d)); T(birthday, N(c4_colon_3), N(c_colon_1), N(d_colon_4), N(c_colon_4), N(f), N(e_colon_8), N(c_colon_3), N(c_colon_1), N(d_colon_4), N(c_colon_4), N(g), N(f_colon_8), N(c_colon_3), N(c_colon_1), N(c5_colon_4), N(a4), N(f), N(e), N(d), N(a_hash__colon_3), N(a_hash__colon_1), N(a_colon_4), N(f), N(g), N(f_colon_8)); T(wedding, N(c4_colon_4), N(f_colon_3), N(f_colon_1), N(f_colon_8), N(c_colon_4), N(g_colon_3), N(e_colon_1), N(f_colon_8), N(c_colon_4), N(f_colon_3), N(a_colon_1), N(c5_colon_4), N(a4_colon_3), N(f_colon_1), N(f_colon_4), N(e_colon_3), N(f_colon_1), N(g_colon_8)); T(funeral, N(c3_colon_4), N(c_colon_3), N(c_colon_1), N(c_colon_4), N(d_hash__colon_3), N(d_colon_1), N(d_colon_3), N(c_colon_1), N(c_colon_3), N(b2_colon_1), N(c3_colon_4)); T(punchline, N(c4_colon_3), N(g3_colon_1), N(f_hash_), N(g), N(g_hash__colon_3), N(g), N(r), N(b), N(c4)); T(python, N(d5_colon_1), N(b4), N(r), N(b), N(b), N(a_hash_), N(b), N(g5), N(r), N(d), N(d), N(r), N(b4), N(c5), N(r), N(c), N(c), N(r), N(d), N(e_colon_5), N(c_colon_1), N(a4), N(r), N(a), N(a), N(g_hash_), N(a), N(f_hash_5), N(r), N(e), N(e), N(r), N(c), N(b4), N(r), N(b), N(b), N(r), N(c5), N(d_colon_5), N(d_colon_1), N(b4), N(r), N(b), N(b), N(a_hash_), N(b), N(b5), N(r), N(g), N(g), N(r), N(d), N(c_hash_), N(r), N(a), N(a), N(r), N(a), N(a_colon_5), N(g_colon_1), N(f_hash__colon_2), N(a_colon_1), N(a), N(g_hash_), N(a), N(e_colon_2), N(a_colon_1), N(a), N(g_hash_), N(a), N(d), N(r), N(c_hash_), N(d), N(r), N(c_hash_), N(d_colon_2), N(r_colon_3)); T(baddy, N(c3_colon_3), N(r), N(d_colon_2), N(d_hash_), N(r), N(c), N(r), N(f_hash__colon_8), ); T(chase, N(a4_colon_1), N(b), N(c5), N(b4), N(a_colon_2), N(r), N(a_colon_1), N(b), N(c5), N(b4), N(a_colon_2), N(r), N(a_colon_2), N(e5), N(d_hash_), N(e), N(f), N(e), N(d_hash_), N(e), N(b4_colon_1), N(c5), N(d), N(c), N(b4_colon_2), N(r), N(b_colon_1), N(c5), N(d), N(c), N(b4_colon_2), N(r), N(b_colon_2), N(e5), N(d_hash_), N(e), N(f), N(e), N(d_hash_), N(e), ); T(ba_ding, N(b5_colon_1), N(e6_colon_3), ); T(wawawawaa, N(e3_colon_3), N(r_colon_1), N(d_hash__colon_3), N(r_colon_1), N(d_colon_4), N(r_colon_1), N(c_hash__colon_8), ); T(jump_up, N(c5_colon_1), N(d), N(e), N(f), N(g), ); T(jump_down, N(g5_colon_1), N(f), N(e), N(d), N(c), ); T(power_up, N(g4_colon_1), N(c5), N(e), N(g_colon_2), N(e_colon_1), N(g_colon_3), ); T(power_down, N(g5_colon_1), N(d_hash_), N(c), N(g4_colon_2), N(b_colon_1), N(c5_colon_3), ); #undef N #undef T #endif // MICROPY_PY_MUSIC micropython-1.12/ports/nrf/modules/music/musictunes.h000066400000000000000000000067371357706137100231330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MUSIC_TUNES_H__ #define MUSIC_TUNES_H__ struct music_tune_dadadum_s; struct music_tune_entertainer_s; struct music_tune_prelude_s; struct music_tune_ode_s; struct music_tune_nyan_s; struct music_tune_ringtone_s; struct music_tune_funk_s; struct music_tune_blues_s; struct music_tune_birthday_s; struct music_tune_wedding_s; struct music_tune_funeral_s; struct music_tune_punchline_s; struct music_tune_python_s; struct music_tune_baddy_s; struct music_tune_chase_s; struct music_tune_ba_ding_s; struct music_tune_wawawawaa_s; struct music_tune_jump_up_s; struct music_tune_jump_down_s; struct music_tune_power_up_s; struct music_tune_power_down_s; extern const struct music_tune_dadadadum_s microbit_music_tune_dadadadum_obj; extern const struct music_tune_entertainer_s microbit_music_tune_entertainer_obj; extern const struct music_tune_prelude_s microbit_music_tune_prelude_obj; extern const struct music_tune_ode_s microbit_music_tune_ode_obj; extern const struct music_tune_nyan_s microbit_music_tune_nyan_obj; extern const struct music_tune_ringtone_s microbit_music_tune_ringtone_obj; extern const struct music_tune_funk_s microbit_music_tune_funk_obj; extern const struct music_tune_blues_s microbit_music_tune_blues_obj; extern const struct music_tune_birthday_s microbit_music_tune_birthday_obj; extern const struct music_tune_wedding_s microbit_music_tune_wedding_obj; extern const struct music_tune_funeral_s microbit_music_tune_funeral_obj; extern const struct music_tune_punchline_s microbit_music_tune_punchline_obj; extern const struct music_tune_python_s microbit_music_tune_python_obj; extern const struct music_tune_baddy_s microbit_music_tune_baddy_obj; extern const struct music_tune_chase_s microbit_music_tune_chase_obj; extern const struct music_tune_ba_ding_s microbit_music_tune_ba_ding_obj; extern const struct music_tune_wawawawaa_s microbit_music_tune_wawawawaa_obj; extern const struct music_tune_jump_up_s microbit_music_tune_jump_up_obj; extern const struct music_tune_jump_down_s microbit_music_tune_jump_down_obj; extern const struct music_tune_power_up_s microbit_music_tune_power_up_obj; extern const struct music_tune_power_down_s microbit_music_tune_power_down_obj; #endif // MUSIC_TUNES_H__ micropython-1.12/ports/nrf/modules/random/000077500000000000000000000000001357706137100207065ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/random/modrandom.c000066400000000000000000000162251357706137100230400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_RANDOM_HW_RNG #include "nrf_rng.h" #include "modrandom.h" #if BLUETOOTH_SD #include "nrf_soc.h" #include "ble_drv.h" #define BLUETOOTH_STACK_ENABLED() (ble_drv_stack_enabled()) #endif static inline uint32_t generate_hw_random(void) { uint32_t retval = 0; uint8_t * p_retval = (uint8_t *)&retval; nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY); nrf_rng_task_trigger(NRF_RNG_TASK_START); for (uint16_t i = 0; i < 4; i++) { while (!nrf_rng_event_get(NRF_RNG_EVENT_VALRDY)) { ; } nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY); p_retval[i] = nrf_rng_random_value_get(); } nrf_rng_task_trigger(NRF_RNG_TASK_STOP); return retval; } uint32_t machine_rng_generate_random_word(void) { #if BLUETOOTH_SD if (BLUETOOTH_STACK_ENABLED() == 1) { uint32_t retval = 0; uint32_t status; do { status = sd_rand_application_vector_get((uint8_t *)&retval, 4); // Extract 4 bytes } while (status != 0); return retval; } #endif return generate_hw_random(); } static inline int rand30(void) { uint32_t val = machine_rng_generate_random_word(); return (val & 0x3fffffff); // binary mask b00111111111111111111111111111111 } static inline int randbelow(int n) { return rand30() % n; } STATIC mp_obj_t mod_random_getrandbits(mp_obj_t num_in) { int n = mp_obj_get_int(num_in); if (n > 30 || n == 0) { mp_raise_ValueError(NULL); } uint32_t mask = ~0; // Beware of C undefined behavior when shifting by >= than bit size mask >>= (32 - n); return mp_obj_new_int_from_uint(rand30() & mask); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_random_getrandbits_obj, mod_random_getrandbits); STATIC mp_obj_t mod_random_randrange(size_t n_args, const mp_obj_t *args) { mp_int_t start = mp_obj_get_int(args[0]); if (n_args == 1) { // range(stop) if (start > 0) { return mp_obj_new_int(randbelow(start)); } else { mp_raise_ValueError(NULL); } } else { mp_int_t stop = mp_obj_get_int(args[1]); if (n_args == 2) { // range(start, stop) if (start < stop) { return mp_obj_new_int(start + randbelow(stop - start)); } else { mp_raise_ValueError(NULL); } } else { // range(start, stop, step) mp_int_t step = mp_obj_get_int(args[2]); mp_int_t n; if (step > 0) { n = (stop - start + step - 1) / step; } else if (step < 0) { n = (stop - start + step + 1) / step; } else { mp_raise_ValueError(NULL); } if (n > 0) { return mp_obj_new_int(start + step * randbelow(n)); } else { mp_raise_ValueError(NULL); } } } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_randrange_obj, 1, 3, mod_random_randrange); STATIC mp_obj_t mod_random_randint(mp_obj_t a_in, mp_obj_t b_in) { mp_int_t a = mp_obj_get_int(a_in); mp_int_t b = mp_obj_get_int(b_in); if (a <= b) { return mp_obj_new_int(a + randbelow(b - a + 1)); } else { mp_raise_ValueError(NULL); } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_random_randint_obj, mod_random_randint); STATIC mp_obj_t mod_random_choice(mp_obj_t seq) { mp_int_t len = mp_obj_get_int(mp_obj_len(seq)); if (len > 0) { return mp_obj_subscr(seq, mp_obj_new_int(randbelow(len)), MP_OBJ_SENTINEL); } else { nlr_raise(mp_obj_new_exception(&mp_type_IndexError)); } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_random_choice_obj, mod_random_choice); #if MICROPY_PY_BUILTINS_FLOAT // returns a number in the range [0..1) using RNG to fill in the fraction bits STATIC mp_float_t randfloat(void) { #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE typedef uint64_t mp_float_int_t; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT typedef uint32_t mp_float_int_t; #endif union { mp_float_t f; #if MP_ENDIANNESS_LITTLE struct { mp_float_int_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p; #else struct { mp_float_int_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p; #endif } u; u.p.sgn = 0; u.p.exp = (1 << (MP_FLOAT_EXP_BITS - 1)) - 1; if (MP_FLOAT_FRAC_BITS <= 30) { u.p.frc = rand30(); } else { u.p.frc = ((uint64_t)rand30() << 30) | (uint64_t)rand30(); } return u.f - 1; } STATIC mp_obj_t mod_random_random(void) { return mp_obj_new_float(randfloat()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_random_random_obj, mod_random_random); STATIC mp_obj_t mod_random_uniform(mp_obj_t a_in, mp_obj_t b_in) { mp_float_t a = mp_obj_get_float(a_in); mp_float_t b = mp_obj_get_float(b_in); return mp_obj_new_float(a + (b - a) * randfloat()); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_random_uniform_obj, mod_random_uniform); #endif STATIC const mp_rom_map_elem_t mp_module_random_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_random) }, { MP_ROM_QSTR(MP_QSTR_getrandbits), MP_ROM_PTR(&mod_random_getrandbits_obj) }, { MP_ROM_QSTR(MP_QSTR_randrange), MP_ROM_PTR(&mod_random_randrange_obj) }, { MP_ROM_QSTR(MP_QSTR_randint), MP_ROM_PTR(&mod_random_randint_obj) }, { MP_ROM_QSTR(MP_QSTR_choice), MP_ROM_PTR(&mod_random_choice_obj) }, #if MICROPY_PY_BUILTINS_FLOAT { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_random_random_obj) }, { MP_ROM_QSTR(MP_QSTR_uniform), MP_ROM_PTR(&mod_random_uniform_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_random_globals, mp_module_random_globals_table); const mp_obj_module_t random_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_random_globals, }; #endif // MICROPY_PY_RANDOM_HW_RNG micropython-1.12/ports/nrf/modules/random/modrandom.h000066400000000000000000000023731357706137100230440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ uint32_t machine_rng_generate_random_word(void); micropython-1.12/ports/nrf/modules/ubluepy/000077500000000000000000000000001357706137100211135ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/ubluepy/modubluepy.c000066400000000000000000000060041357706137100234440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #if MICROPY_PY_UBLUEPY extern const mp_obj_type_t ubluepy_peripheral_type; extern const mp_obj_type_t ubluepy_service_type; extern const mp_obj_type_t ubluepy_uuid_type; extern const mp_obj_type_t ubluepy_characteristic_type; extern const mp_obj_type_t ubluepy_delegate_type; extern const mp_obj_type_t ubluepy_constants_type; extern const mp_obj_type_t ubluepy_scanner_type; extern const mp_obj_type_t ubluepy_scan_entry_type; STATIC const mp_rom_map_elem_t mp_module_ubluepy_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluepy) }, #if MICROPY_PY_UBLUEPY_PERIPHERAL { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&ubluepy_peripheral_type) }, #endif #if 0 // MICROPY_PY_UBLUEPY_CENTRAL { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&ubluepy_central_type) }, #endif #if MICROPY_PY_UBLUEPY_CENTRAL { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&ubluepy_scanner_type) }, { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&ubluepy_scan_entry_type) }, #endif { MP_ROM_QSTR(MP_QSTR_DefaultDelegate), MP_ROM_PTR(&ubluepy_delegate_type) }, { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&ubluepy_uuid_type) }, { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&ubluepy_service_type) }, { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&ubluepy_characteristic_type) }, { MP_ROM_QSTR(MP_QSTR_constants), MP_ROM_PTR(&ubluepy_constants_type) }, #if MICROPY_PY_UBLUEPY_DESCRIPTOR { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&ubluepy_descriptor_type) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_ubluepy_globals, mp_module_ubluepy_globals_table); const mp_obj_module_t mp_module_ubluepy = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_ubluepy_globals, }; #endif // MICROPY_PY_UBLUEPY micropython-1.12/ports/nrf/modules/ubluepy/modubluepy.h000066400000000000000000000140351357706137100234540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef UBLUEPY_H__ #define UBLUEPY_H__ /* Examples: Advertisment: from ubluepy import Peripheral p = Peripheral() p.advertise(device_name="MicroPython") DB setup: from ubluepy import Service, Characteristic, UUID, Peripheral, constants from board import LED def event_handler(id, handle, data): print("BLE event:", id, "handle:", handle) print(data) if id == constants.EVT_GAP_CONNECTED: # connected LED(2).on() elif id == constants.EVT_GAP_DISCONNECTED: # disconnect LED(2).off() elif id == 80: print("id 80, data:", data) # u0 = UUID("0x180D") # HRM service # u1 = UUID("0x2A37") # HRM measurement u0 = UUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e") u1 = UUID("6e400002-b5a3-f393-e0a9-e50e24dcca9e") u2 = UUID("6e400003-b5a3-f393-e0a9-e50e24dcca9e") s = Service(u0) c0 = Characteristic(u1, props = Characteristic.PROP_WRITE | Characteristic.PROP_WRITE_WO_RESP) c1 = Characteristic(u2, props = Characteristic.PROP_NOTIFY, attrs = Characteristic.ATTR_CCCD) s.addCharacteristic(c0) s.addCharacteristic(c1) p = Peripheral() p.addService(s) p.setConnectionHandler(event_handler) p.advertise(device_name="micr", services=[s]) */ #include "py/obj.h" extern const mp_obj_type_t ubluepy_uuid_type; extern const mp_obj_type_t ubluepy_service_type; extern const mp_obj_type_t ubluepy_characteristic_type; extern const mp_obj_type_t ubluepy_peripheral_type; extern const mp_obj_type_t ubluepy_scanner_type; extern const mp_obj_type_t ubluepy_scan_entry_type; extern const mp_obj_type_t ubluepy_constants_type; extern const mp_obj_type_t ubluepy_constants_ad_types_type; typedef enum { UBLUEPY_UUID_16_BIT = 1, UBLUEPY_UUID_128_BIT } ubluepy_uuid_type_t; typedef enum { UBLUEPY_SERVICE_PRIMARY = 1, UBLUEPY_SERVICE_SECONDARY = 2 } ubluepy_service_type_t; typedef enum { UBLUEPY_ADDR_TYPE_PUBLIC = 0, UBLUEPY_ADDR_TYPE_RANDOM_STATIC = 1, #if 0 UBLUEPY_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = 2, UBLUEPY_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE = 3, #endif } ubluepy_addr_type_t; typedef enum { UBLUEPY_ROLE_PERIPHERAL, UBLUEPY_ROLE_CENTRAL } ubluepy_role_type_t; typedef struct _ubluepy_uuid_obj_t { mp_obj_base_t base; ubluepy_uuid_type_t type; uint8_t value[2]; uint8_t uuid_vs_idx; } ubluepy_uuid_obj_t; typedef struct _ubluepy_peripheral_obj_t { mp_obj_base_t base; ubluepy_role_type_t role; volatile uint16_t conn_handle; mp_obj_t delegate; mp_obj_t notif_handler; mp_obj_t conn_handler; mp_obj_t service_list; } ubluepy_peripheral_obj_t; typedef struct _ubluepy_service_obj_t { mp_obj_base_t base; uint16_t handle; uint8_t type; ubluepy_uuid_obj_t * p_uuid; ubluepy_peripheral_obj_t * p_periph; mp_obj_t char_list; uint16_t start_handle; uint16_t end_handle; } ubluepy_service_obj_t; typedef struct _ubluepy_characteristic_obj_t { mp_obj_base_t base; uint16_t handle; ubluepy_uuid_obj_t * p_uuid; uint16_t service_handle; uint16_t user_desc_handle; uint16_t cccd_handle; uint16_t sccd_handle; uint8_t props; uint8_t attrs; ubluepy_service_obj_t * p_service; mp_obj_t value_data; } ubluepy_characteristic_obj_t; typedef struct _ubluepy_descriptor_obj_t { mp_obj_base_t base; uint16_t handle; ubluepy_uuid_obj_t * p_uuid; } ubluepy_descriptor_obj_t; typedef struct _ubluepy_delegate_obj_t { mp_obj_base_t base; } ubluepy_delegate_obj_t; typedef struct _ubluepy_advertise_data_t { uint8_t * p_device_name; uint8_t device_name_len; mp_obj_t * p_services; uint8_t num_of_services; uint8_t * p_data; uint8_t data_len; bool connectable; } ubluepy_advertise_data_t; typedef struct _ubluepy_scanner_obj_t { mp_obj_base_t base; mp_obj_t adv_reports; } ubluepy_scanner_obj_t; typedef struct _ubluepy_scan_entry_obj_t { mp_obj_base_t base; mp_obj_t addr; uint8_t addr_type; bool connectable; int8_t rssi; mp_obj_t data; } ubluepy_scan_entry_obj_t; typedef enum _ubluepy_prop_t { UBLUEPY_PROP_BROADCAST = 0x01, UBLUEPY_PROP_READ = 0x02, UBLUEPY_PROP_WRITE_WO_RESP = 0x04, UBLUEPY_PROP_WRITE = 0x08, UBLUEPY_PROP_NOTIFY = 0x10, UBLUEPY_PROP_INDICATE = 0x20, UBLUEPY_PROP_AUTH_SIGNED_WR = 0x40, } ubluepy_prop_t; typedef enum _ubluepy_attr_t { UBLUEPY_ATTR_CCCD = 0x01, UBLUEPY_ATTR_SCCD = 0x02, } ubluepy_attr_t; #endif // UBLUEPY_H__ micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_characteristic.c000066400000000000000000000206271357706137100260230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/runtime.h" #if MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL #include "modubluepy.h" #include "ble_drv.h" STATIC void ubluepy_characteristic_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { ubluepy_characteristic_obj_t * self = (ubluepy_characteristic_obj_t *)o; mp_printf(print, "Characteristic(handle: 0x" HEX2_FMT ", conn_handle: " HEX2_FMT ")", self->handle, self->p_service->p_periph->conn_handle); } STATIC mp_obj_t ubluepy_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED| MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_props, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UBLUEPY_PROP_READ | UBLUEPY_PROP_WRITE} }, { MP_QSTR_attrs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); ubluepy_characteristic_obj_t *s = m_new_obj(ubluepy_characteristic_obj_t); s->base.type = type; mp_obj_t uuid_obj = args[0].u_obj; if (uuid_obj == mp_const_none) { return MP_OBJ_FROM_PTR(s); } if (mp_obj_is_type(uuid_obj, &ubluepy_uuid_type)) { s->p_uuid = MP_OBJ_TO_PTR(uuid_obj); // (void)sd_characterstic_add(s); } else { mp_raise_ValueError("Invalid UUID parameter"); } if (args[1].u_int > 0) { s->props = (uint8_t)args[1].u_int; } if (args[2].u_int > 0) { s->attrs = (uint8_t)args[2].u_int; } // clear pointer to service s->p_service = NULL; // clear pointer to char value data s->value_data = NULL; return MP_OBJ_FROM_PTR(s); } void char_data_callback(mp_obj_t self_in, uint16_t length, uint8_t * p_data) { ubluepy_characteristic_obj_t * self = MP_OBJ_TO_PTR(self_in); self->value_data = mp_obj_new_bytearray(length, p_data); } /// \method read() /// Read Characteristic value. /// STATIC mp_obj_t char_read(mp_obj_t self_in) { ubluepy_characteristic_obj_t * self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_UBLUEPY_CENTRAL // TODO: free any previous allocation of value_data ble_drv_attr_c_read(self->p_service->p_periph->conn_handle, self->handle, self_in, char_data_callback); return self->value_data; #else (void)self; return mp_const_none; #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_characteristic_read_obj, char_read); /// \method write(data, [with_response=False]) /// Write Characteristic value. /// STATIC mp_obj_t char_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { ubluepy_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_obj_t data = pos_args[1]; static const mp_arg_t allowed_args[] = { { MP_QSTR_with_response, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false } }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); // figure out mode of the Peripheral ubluepy_role_type_t role = self->p_service->p_periph->role; if (role == UBLUEPY_ROLE_PERIPHERAL) { if (self->props & UBLUEPY_PROP_NOTIFY) { ble_drv_attr_s_notify(self->p_service->p_periph->conn_handle, self->handle, bufinfo.len, bufinfo.buf); } else { ble_drv_attr_s_write(self->p_service->p_periph->conn_handle, self->handle, bufinfo.len, bufinfo.buf); } } else { #if MICROPY_PY_UBLUEPY_CENTRAL bool with_response = args[0].u_bool; ble_drv_attr_c_write(self->p_service->p_periph->conn_handle, self->handle, bufinfo.len, bufinfo.buf, with_response); #endif } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ubluepy_characteristic_write_obj, 2, char_write); /// \method properties() /// Read Characteristic value properties. /// STATIC mp_obj_t char_properties(mp_obj_t self_in) { ubluepy_characteristic_obj_t * self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(self->props); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_characteristic_get_properties_obj, char_properties); /// \method uuid() /// Get UUID instance of the characteristic. /// STATIC mp_obj_t char_uuid(mp_obj_t self_in) { ubluepy_characteristic_obj_t * self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_FROM_PTR(self->p_uuid); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_characteristic_get_uuid_obj, char_uuid); STATIC const mp_rom_map_elem_t ubluepy_characteristic_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&ubluepy_characteristic_read_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&ubluepy_characteristic_write_obj) }, #if 0 { MP_ROM_QSTR(MP_QSTR_supportsRead), MP_ROM_PTR(&ubluepy_characteristic_supports_read_obj) }, { MP_ROM_QSTR(MP_QSTR_propertiesToString), MP_ROM_PTR(&ubluepy_characteristic_properties_to_str_obj) }, { MP_ROM_QSTR(MP_QSTR_getHandle), MP_ROM_PTR(&ubluepy_characteristic_get_handle_obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_peripheral), MP_ROM_PTR(&ubluepy_characteristic_get_peripheral_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&ubluepy_characteristic_get_uuid_obj) }, { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&ubluepy_characteristic_get_properties_obj) }, { MP_ROM_QSTR(MP_QSTR_PROP_BROADCAST), MP_ROM_INT(UBLUEPY_PROP_BROADCAST) }, { MP_ROM_QSTR(MP_QSTR_PROP_READ), MP_ROM_INT(UBLUEPY_PROP_READ) }, { MP_ROM_QSTR(MP_QSTR_PROP_WRITE_WO_RESP), MP_ROM_INT(UBLUEPY_PROP_WRITE_WO_RESP) }, { MP_ROM_QSTR(MP_QSTR_PROP_WRITE), MP_ROM_INT(UBLUEPY_PROP_WRITE) }, { MP_ROM_QSTR(MP_QSTR_PROP_NOTIFY), MP_ROM_INT(UBLUEPY_PROP_NOTIFY) }, { MP_ROM_QSTR(MP_QSTR_PROP_INDICATE), MP_ROM_INT(UBLUEPY_PROP_INDICATE) }, { MP_ROM_QSTR(MP_QSTR_PROP_AUTH_SIGNED_WR), MP_ROM_INT(UBLUEPY_PROP_AUTH_SIGNED_WR) }, #if MICROPY_PY_UBLUEPY_PERIPHERAL { MP_ROM_QSTR(MP_QSTR_ATTR_CCCD), MP_ROM_INT(UBLUEPY_ATTR_CCCD) }, #endif #if MICROPY_PY_UBLUEPY_CENTRAL { MP_ROM_QSTR(MP_QSTR_PROP_AUTH_SIGNED_WR), MP_ROM_INT(UBLUEPY_ATTR_SCCD) }, #endif }; STATIC MP_DEFINE_CONST_DICT(ubluepy_characteristic_locals_dict, ubluepy_characteristic_locals_dict_table); const mp_obj_type_t ubluepy_characteristic_type = { { &mp_type_type }, .name = MP_QSTR_Characteristic, .print = ubluepy_characteristic_print, .make_new = ubluepy_characteristic_make_new, .locals_dict = (mp_obj_dict_t*)&ubluepy_characteristic_locals_dict }; #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_constants.c000066400000000000000000000127551357706137100250520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/runtime.h" #if MICROPY_PY_UBLUEPY #include "modubluepy.h" STATIC const mp_rom_map_elem_t ubluepy_constants_ad_types_locals_dict_table[] = { // GAP AD Types { MP_ROM_QSTR(MP_QSTR_AD_TYPE_FLAGS), MP_ROM_INT(0x01) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE), MP_ROM_INT(0x02) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE), MP_ROM_INT(0x03) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE), MP_ROM_INT(0x04) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE), MP_ROM_INT(0x05) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE), MP_ROM_INT(0x06) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE), MP_ROM_INT(0x07) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SHORT_LOCAL_NAME), MP_ROM_INT(0x08) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_COMPLETE_LOCAL_NAME), MP_ROM_INT(0x09) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_TX_POWER_LEVEL), MP_ROM_INT(0x0A) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_CLASS_OF_DEVICE), MP_ROM_INT(0x0D) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SIMPLE_PAIRING_HASH_C), MP_ROM_INT(0x0E) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R), MP_ROM_INT(0x0F) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SECURITY_MANAGER_TK_VALUE), MP_ROM_INT(0x10) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS), MP_ROM_INT(0x11) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE), MP_ROM_INT(0x12) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT), MP_ROM_INT(0x14) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT), MP_ROM_INT(0x15) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SERVICE_DATA), MP_ROM_INT(0x16) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_PUBLIC_TARGET_ADDRESS), MP_ROM_INT(0x17) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_RANDOM_TARGET_ADDRESS), MP_ROM_INT(0x18) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_APPEARANCE), MP_ROM_INT(0x19) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_ADVERTISING_INTERVAL), MP_ROM_INT(0x1A) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS), MP_ROM_INT(0x1B) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_LE_ROLE), MP_ROM_INT(0x1C) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SIMPLE_PAIRING_HASH_C256), MP_ROM_INT(0x1D) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256), MP_ROM_INT(0x1E) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SERVICE_DATA_32BIT_UUID), MP_ROM_INT(0x20) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SERVICE_DATA_128BIT_UUID), MP_ROM_INT(0x21) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_URI), MP_ROM_INT(0x24) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_3D_INFORMATION_DATA), MP_ROM_INT(0x3D) }, { MP_ROM_QSTR(MP_QSTR_AD_TYPE_MANUFACTURER_SPECIFIC_DATA), MP_ROM_INT(0xFF) }, }; STATIC MP_DEFINE_CONST_DICT(ubluepy_constants_ad_types_locals_dict, ubluepy_constants_ad_types_locals_dict_table); const mp_obj_type_t ubluepy_constants_ad_types_type = { { &mp_type_type }, .name = MP_QSTR_ad_types, .locals_dict = (mp_obj_dict_t*)&ubluepy_constants_ad_types_locals_dict }; STATIC const mp_rom_map_elem_t ubluepy_constants_locals_dict_table[] = { // GAP events { MP_ROM_QSTR(MP_QSTR_EVT_GAP_CONNECTED), MP_ROM_INT(16) }, { MP_ROM_QSTR(MP_QSTR_EVT_GAP_DISCONNECTED), MP_ROM_INT(17) }, { MP_ROM_QSTR(MP_QSTR_EVT_GATTS_WRITE), MP_ROM_INT(80) }, { MP_ROM_QSTR(MP_QSTR_UUID_CCCD), MP_ROM_INT(0x2902) }, { MP_ROM_QSTR(MP_QSTR_ADDR_TYPE_PUBLIC), MP_ROM_INT(UBLUEPY_ADDR_TYPE_PUBLIC) }, { MP_ROM_QSTR(MP_QSTR_ADDR_TYPE_RANDOM_STATIC), MP_ROM_INT(UBLUEPY_ADDR_TYPE_RANDOM_STATIC) }, { MP_ROM_QSTR(MP_QSTR_ad_types), MP_ROM_PTR(&ubluepy_constants_ad_types_type) }, }; STATIC MP_DEFINE_CONST_DICT(ubluepy_constants_locals_dict, ubluepy_constants_locals_dict_table); const mp_obj_type_t ubluepy_constants_type = { { &mp_type_type }, .name = MP_QSTR_constants, .locals_dict = (mp_obj_dict_t*)&ubluepy_constants_locals_dict }; #endif // MICROPY_PY_UBLUEPY micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_delegate.c000066400000000000000000000063171357706137100246050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/runtime.h" #if MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL #include "modubluepy.h" STATIC void ubluepy_delegate_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { ubluepy_delegate_obj_t * self = (ubluepy_delegate_obj_t *)o; (void)self; mp_printf(print, "DefaultDelegate()"); } STATIC mp_obj_t ubluepy_delegate_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { ubluepy_delegate_obj_t *s = m_new_obj(ubluepy_delegate_obj_t); s->base.type = type; return MP_OBJ_FROM_PTR(s); } /// \method handleConnection() /// Handle connection events. /// STATIC mp_obj_t delegate_handle_conn(mp_obj_t self_in) { ubluepy_delegate_obj_t *self = MP_OBJ_TO_PTR(self_in); (void)self; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_delegate_handle_conn_obj, delegate_handle_conn); /// \method handleNotification() /// Handle notification events. /// STATIC mp_obj_t delegate_handle_notif(mp_obj_t self_in) { ubluepy_delegate_obj_t *self = MP_OBJ_TO_PTR(self_in); (void)self; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_delegate_handle_notif_obj, delegate_handle_notif); STATIC const mp_rom_map_elem_t ubluepy_delegate_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_handleConnection), MP_ROM_PTR(&ubluepy_delegate_handle_conn_obj) }, { MP_ROM_QSTR(MP_QSTR_handleNotification), MP_ROM_PTR(&ubluepy_delegate_handle_notif_obj) }, #if 0 { MP_ROM_QSTR(MP_QSTR_handleDiscovery), MP_ROM_PTR(&ubluepy_delegate_handle_disc_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(ubluepy_delegate_locals_dict, ubluepy_delegate_locals_dict_table); const mp_obj_type_t ubluepy_delegate_type = { { &mp_type_type }, .name = MP_QSTR_DefaultDelegate, .print = ubluepy_delegate_print, .make_new = ubluepy_delegate_make_new, .locals_dict = (mp_obj_dict_t*)&ubluepy_delegate_locals_dict }; #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_descriptor.c000066400000000000000000000055201357706137100252040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/runtime.h" #include "py/objstr.h" #include "py/misc.h" #if MICROPY_PY_UBLUEPY #include "modubluepy.h" #include "ble_drv.h" STATIC void ubluepy_descriptor_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { ubluepy_descriptor_obj_t * self = (ubluepy_descriptor_obj_t *)o; mp_printf(print, "Descriptor(uuid: 0x" HEX2_FMT HEX2_FMT ")", self->p_uuid->value[1], self->p_uuid->value[0]); } STATIC mp_obj_t ubluepy_descriptor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_NEW_UUID }; static const mp_arg_t allowed_args[] = { { ARG_NEW_UUID, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); ubluepy_descriptor_obj_t * s = m_new_obj(ubluepy_descriptor_obj_t); s->base.type = type; mp_obj_t uuid_obj = args[ARG_NEW_UUID].u_obj; (void)uuid_obj; return MP_OBJ_FROM_PTR(s); } STATIC const mp_rom_map_elem_t ubluepy_descriptor_locals_dict_table[] = { #if 0 { MP_ROM_QSTR(MP_QSTR_binVal), MP_ROM_PTR(&ubluepy_descriptor_bin_val_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(ubluepy_descriptor_locals_dict, ubluepy_descriptor_locals_dict_table); const mp_obj_type_t ubluepy_descriptor_type = { { &mp_type_type }, .name = MP_QSTR_Descriptor, .print = ubluepy_descriptor_print, .make_new = ubluepy_descriptor_make_new, .locals_dict = (mp_obj_dict_t*)&ubluepy_descriptor_locals_dict }; #endif // MICROPY_PY_UBLUEPY micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_peripheral.c000066400000000000000000000461031357706137100251630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" #include "py/runtime.h" #include "py/objstr.h" #include "py/objlist.h" #if MICROPY_PY_UBLUEPY #include "ble_drv.h" STATIC void ubluepy_peripheral_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { ubluepy_peripheral_obj_t * self = (ubluepy_peripheral_obj_t *)o; (void)self; mp_printf(print, "Peripheral(conn_handle: " HEX2_FMT ")", self->conn_handle); } STATIC void gap_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); if (event_id == 16) { // connect event self->conn_handle = conn_handle; } else if (event_id == 17) { // disconnect event self->conn_handle = 0xFFFF; // invalid connection handle } if (self->conn_handler != mp_const_none) { mp_obj_t args[3]; mp_uint_t num_of_args = 3; args[0] = MP_OBJ_NEW_SMALL_INT(event_id); args[1] = MP_OBJ_NEW_SMALL_INT(conn_handle); if (data != NULL) { args[2] = mp_obj_new_bytearray_by_ref(length, data); } else { args[2] = mp_const_none; } // for now hard-code all events to conn_handler mp_call_function_n_kw(self->conn_handler, num_of_args, 0, args); } (void)self; } STATIC void gatts_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->conn_handler != mp_const_none) { mp_obj_t args[3]; mp_uint_t num_of_args = 3; args[0] = MP_OBJ_NEW_SMALL_INT(event_id); args[1] = MP_OBJ_NEW_SMALL_INT(attr_handle); if (data != NULL) { args[2] = mp_obj_new_bytearray_by_ref(length, data); } else { args[2] = mp_const_none; } // for now hard-code all events to conn_handler mp_call_function_n_kw(self->conn_handler, num_of_args, 0, args); } } #if MICROPY_PY_UBLUEPY_CENTRAL static volatile bool m_disc_evt_received; STATIC void gattc_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); (void)self; m_disc_evt_received = true; } #endif STATIC mp_obj_t ubluepy_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_NEW_DEVICE_ADDR, ARG_NEW_ADDR_TYPE }; static const mp_arg_t allowed_args[] = { { ARG_NEW_DEVICE_ADDR, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { ARG_NEW_ADDR_TYPE, MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); ubluepy_peripheral_obj_t *s = m_new_obj(ubluepy_peripheral_obj_t); s->base.type = type; s->delegate = mp_const_none; s->conn_handler = mp_const_none; s->notif_handler = mp_const_none; s->conn_handle = 0xFFFF; s->service_list = mp_obj_new_list(0, NULL); return MP_OBJ_FROM_PTR(s); } /// \method withDelegate(DefaultDelegate) /// Set delegate instance for handling Bluetooth LE events. /// STATIC mp_obj_t peripheral_with_delegate(mp_obj_t self_in, mp_obj_t delegate) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); self->delegate = delegate; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_with_delegate_obj, peripheral_with_delegate); /// \method setNotificationHandler(func) /// Set handler for Bluetooth LE notification events. /// STATIC mp_obj_t peripheral_set_notif_handler(mp_obj_t self_in, mp_obj_t func) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); self->notif_handler = func; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_set_notif_handler_obj, peripheral_set_notif_handler); /// \method setConnectionHandler(func) /// Set handler for Bluetooth LE connection events. /// STATIC mp_obj_t peripheral_set_conn_handler(mp_obj_t self_in, mp_obj_t func) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); self->conn_handler = func; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_set_conn_handler_obj, peripheral_set_conn_handler); #if MICROPY_PY_UBLUEPY_PERIPHERAL /// \method advertise(device_name, [service=[service1, service2, ...]], [data=bytearray], [connectable=True]) /// Start advertising. Connectable advertisment type by default. /// STATIC mp_obj_t peripheral_advertise(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_device_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_services, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); self->role = UBLUEPY_ROLE_PERIPHERAL; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_obj_t device_name_obj = args[0].u_obj; mp_obj_t service_obj = args[1].u_obj; mp_obj_t data_obj = args[2].u_obj; mp_obj_t connectable_obj = args[3].u_obj; ubluepy_advertise_data_t adv_data; memset(&adv_data, 0, sizeof(ubluepy_advertise_data_t)); if (device_name_obj != mp_const_none && mp_obj_is_str(device_name_obj)) { GET_STR_DATA_LEN(device_name_obj, str_data, str_len); adv_data.p_device_name = (uint8_t *)str_data; adv_data.device_name_len = str_len; } if (service_obj != mp_const_none) { mp_obj_t * services = NULL; mp_uint_t num_services; mp_obj_get_array(service_obj, &num_services, &services); if (num_services > 0) { adv_data.p_services = services; adv_data.num_of_services = num_services; } } if (data_obj != mp_const_none) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ); if (bufinfo.len > 0) { adv_data.p_data = bufinfo.buf; adv_data.data_len = bufinfo.len; } } adv_data.connectable = true; if (connectable_obj != mp_const_none && !(mp_obj_is_true(connectable_obj))) { adv_data.connectable = false; } else { ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(self), gap_event_handler); ble_drv_gatts_event_handler_set(MP_OBJ_FROM_PTR(self), gatts_event_handler); } (void)ble_drv_advertise_data(&adv_data); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ubluepy_peripheral_advertise_obj, 0, peripheral_advertise); /// \method advertise_stop() /// Stop advertisment if any onging advertisment. /// STATIC mp_obj_t peripheral_advertise_stop(mp_obj_t self_in) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); (void)self; ble_drv_advertise_stop(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_advertise_stop_obj, peripheral_advertise_stop); #endif // MICROPY_PY_UBLUEPY_PERIPHERAL /// \method disconnect() /// disconnect connection. /// STATIC mp_obj_t peripheral_disconnect(mp_obj_t self_in) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); (void)self; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_disconnect_obj, peripheral_disconnect); /// \method addService(Service) /// Add service to the Peripheral. /// STATIC mp_obj_t peripheral_add_service(mp_obj_t self_in, mp_obj_t service) { ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); ubluepy_service_obj_t * p_service = MP_OBJ_TO_PTR(service); p_service->p_periph = self; mp_obj_list_append(self->service_list, service); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_add_service_obj, peripheral_add_service); /// \method getServices() /// Return list with all service registered in the Peripheral. /// STATIC mp_obj_t peripheral_get_services(mp_obj_t self_in) { ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); return self->service_list; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_get_services_obj, peripheral_get_services); #if MICROPY_PY_UBLUEPY_CENTRAL void static disc_add_service(mp_obj_t self, ble_drv_service_data_t * p_service_data) { ubluepy_service_obj_t * p_service = m_new_obj(ubluepy_service_obj_t); p_service->base.type = &ubluepy_service_type; ubluepy_uuid_obj_t * p_uuid = m_new_obj(ubluepy_uuid_obj_t); p_uuid->base.type = &ubluepy_uuid_type; p_service->p_uuid = p_uuid; p_uuid->type = p_service_data->uuid_type; p_uuid->value[0] = p_service_data->uuid & 0xFF; p_uuid->value[1] = p_service_data->uuid >> 8; p_service->handle = p_service_data->start_handle; p_service->start_handle = p_service_data->start_handle; p_service->end_handle = p_service_data->end_handle; p_service->char_list = mp_obj_new_list(0, NULL); peripheral_add_service(self, MP_OBJ_FROM_PTR(p_service)); } void static disc_add_char(mp_obj_t service_in, ble_drv_char_data_t * p_desc_data) { ubluepy_service_obj_t * p_service = MP_OBJ_TO_PTR(service_in); ubluepy_characteristic_obj_t * p_char = m_new_obj(ubluepy_characteristic_obj_t); p_char->base.type = &ubluepy_characteristic_type; ubluepy_uuid_obj_t * p_uuid = m_new_obj(ubluepy_uuid_obj_t); p_uuid->base.type = &ubluepy_uuid_type; p_char->p_uuid = p_uuid; p_uuid->type = p_desc_data->uuid_type; p_uuid->value[0] = p_desc_data->uuid & 0xFF; p_uuid->value[1] = p_desc_data->uuid >> 8; // add characteristic specific data from discovery p_char->props = p_desc_data->props; p_char->handle = p_desc_data->value_handle; // equivalent to ubluepy_service.c - service_add_characteristic() // except the registration of the characteristic towards the bluetooth stack p_char->service_handle = p_service->handle; p_char->p_service = p_service; mp_obj_list_append(p_service->char_list, MP_OBJ_FROM_PTR(p_char)); } /// \method connect(device_address [, addr_type=ADDR_TYPE_PUBLIC]) /// Connect to device peripheral with the given device address. /// addr_type can be either ADDR_TYPE_PUBLIC (default) or /// ADDR_TYPE_RANDOM_STATIC. /// STATIC mp_obj_t peripheral_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_obj_t dev_addr = pos_args[1]; self->role = UBLUEPY_ROLE_CENTRAL; static const mp_arg_t allowed_args[] = { { MP_QSTR_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UBLUEPY_ADDR_TYPE_PUBLIC } }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); uint8_t addr_type = args[0].u_int; ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(self), gap_event_handler); if (mp_obj_is_str(dev_addr)) { GET_STR_DATA_LEN(dev_addr, str_data, str_len); if (str_len == 17) { // Example "11:22:33:aa:bb:cc" uint8_t * p_addr = m_new(uint8_t, 6); p_addr[0] = unichar_xdigit_value(str_data[16]); p_addr[0] += unichar_xdigit_value(str_data[15]) << 4; p_addr[1] = unichar_xdigit_value(str_data[13]); p_addr[1] += unichar_xdigit_value(str_data[12]) << 4; p_addr[2] = unichar_xdigit_value(str_data[10]); p_addr[2] += unichar_xdigit_value(str_data[9]) << 4; p_addr[3] = unichar_xdigit_value(str_data[7]); p_addr[3] += unichar_xdigit_value(str_data[6]) << 4; p_addr[4] = unichar_xdigit_value(str_data[4]); p_addr[4] += unichar_xdigit_value(str_data[3]) << 4; p_addr[5] = unichar_xdigit_value(str_data[1]); p_addr[5] += unichar_xdigit_value(str_data[0]) << 4; ble_drv_connect(p_addr, addr_type); m_del(uint8_t, p_addr, 6); } } // block until connected while (self->conn_handle == 0xFFFF) { ; } ble_drv_gattc_event_handler_set(MP_OBJ_FROM_PTR(self), gattc_event_handler); bool service_disc_retval = ble_drv_discover_services(self, self->conn_handle, 0x0001, disc_add_service); // continue discovery of primary services ... while (service_disc_retval) { // locate the last added service mp_obj_t * services = NULL; mp_uint_t num_services; mp_obj_get_array(self->service_list, &num_services, &services); ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)services[num_services - 1]; service_disc_retval = ble_drv_discover_services(self, self->conn_handle, p_service->end_handle + 1, disc_add_service); } // For each service perform a characteristic discovery mp_obj_t * services = NULL; mp_uint_t num_services; mp_obj_get_array(self->service_list, &num_services, &services); for (uint16_t s = 0; s < num_services; s++) { ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)services[s]; bool char_disc_retval = ble_drv_discover_characteristic(p_service, self->conn_handle, p_service->start_handle, p_service->end_handle, disc_add_char); // continue discovery of characteristics ... while (char_disc_retval) { mp_obj_t * characteristics = NULL; mp_uint_t num_chars; mp_obj_get_array(p_service->char_list, &num_chars, &characteristics); ubluepy_characteristic_obj_t * p_char = (ubluepy_characteristic_obj_t *)characteristics[num_chars - 1]; uint16_t next_handle = p_char->handle + 1; if ((next_handle) < p_service->end_handle) { char_disc_retval = ble_drv_discover_characteristic(p_service, self->conn_handle, next_handle, p_service->end_handle, disc_add_char); } else { break; } } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ubluepy_peripheral_connect_obj, 2, peripheral_connect); #endif STATIC const mp_rom_map_elem_t ubluepy_peripheral_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_withDelegate), MP_ROM_PTR(&ubluepy_peripheral_with_delegate_obj) }, { MP_ROM_QSTR(MP_QSTR_setNotificationHandler), MP_ROM_PTR(&ubluepy_peripheral_set_notif_handler_obj) }, { MP_ROM_QSTR(MP_QSTR_setConnectionHandler), MP_ROM_PTR(&ubluepy_peripheral_set_conn_handler_obj) }, { MP_ROM_QSTR(MP_QSTR_getServices), MP_ROM_PTR(&ubluepy_peripheral_get_services_obj) }, #if MICROPY_PY_UBLUEPY_CENTRAL { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&ubluepy_peripheral_connect_obj) }, #if 0 { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&ubluepy_peripheral_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_getServiceByUUID), MP_ROM_PTR(&ubluepy_peripheral_get_service_by_uuid_obj) }, { MP_ROM_QSTR(MP_QSTR_getCharacteristics), MP_ROM_PTR(&ubluepy_peripheral_get_chars_obj) }, { MP_ROM_QSTR(MP_QSTR_getDescriptors), MP_ROM_PTR(&ubluepy_peripheral_get_descs_obj) }, { MP_ROM_QSTR(MP_QSTR_waitForNotifications), MP_ROM_PTR(&ubluepy_peripheral_wait_for_notif_obj) }, { MP_ROM_QSTR(MP_QSTR_writeCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_write_char_obj) }, { MP_ROM_QSTR(MP_QSTR_readCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_read_char_obj) }, #endif // 0 #endif // MICROPY_PY_UBLUEPY_CENTRAL #if MICROPY_PY_UBLUEPY_PERIPHERAL { MP_ROM_QSTR(MP_QSTR_advertise), MP_ROM_PTR(&ubluepy_peripheral_advertise_obj) }, { MP_ROM_QSTR(MP_QSTR_advertise_stop), MP_ROM_PTR(&ubluepy_peripheral_advertise_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&ubluepy_peripheral_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_addService), MP_ROM_PTR(&ubluepy_peripheral_add_service_obj) }, #if 0 { MP_ROM_QSTR(MP_QSTR_addCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_add_char_obj) }, { MP_ROM_QSTR(MP_QSTR_addDescriptor), MP_ROM_PTR(&ubluepy_peripheral_add_desc_obj) }, { MP_ROM_QSTR(MP_QSTR_writeCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_write_char_obj) }, { MP_ROM_QSTR(MP_QSTR_readCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_read_char_obj) }, #endif #endif #if MICROPY_PY_UBLUEPY_BROADCASTER { MP_ROM_QSTR(MP_QSTR_advertise), MP_ROM_PTR(&ubluepy_peripheral_advertise_obj) }, #endif #if MICROPY_PY_UBLUEPY_OBSERVER // Nothing yet. #endif }; STATIC MP_DEFINE_CONST_DICT(ubluepy_peripheral_locals_dict, ubluepy_peripheral_locals_dict_table); const mp_obj_type_t ubluepy_peripheral_type = { { &mp_type_type }, .name = MP_QSTR_Peripheral, .print = ubluepy_peripheral_print, .make_new = ubluepy_peripheral_make_new, .locals_dict = (mp_obj_dict_t*)&ubluepy_peripheral_locals_dict }; #endif // MICROPY_PY_UBLUEPY micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c000066400000000000000000000125461357706137100252010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" #include "py/runtime.h" #include "py/objstr.h" #include "py/objlist.h" #include "py/objarray.h" #include "py/objtuple.h" #include "py/qstr.h" #if MICROPY_PY_UBLUEPY_CENTRAL #include "ble_drv.h" STATIC void ubluepy_scan_entry_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { ubluepy_scan_entry_obj_t * self = (ubluepy_scan_entry_obj_t *)o; (void)self; mp_printf(print, "ScanEntry"); } /// \method addr() /// Return address as text string. /// STATIC mp_obj_t scan_entry_get_addr(mp_obj_t self_in) { ubluepy_scan_entry_obj_t *self = MP_OBJ_TO_PTR(self_in); return self->addr; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scan_entry_get_addr_obj, scan_entry_get_addr); /// \method addr_type() /// Return address type value. /// STATIC mp_obj_t scan_entry_get_addr_type(mp_obj_t self_in) { ubluepy_scan_entry_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int(self->addr_type); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scan_entry_get_addr_type_obj, scan_entry_get_addr_type); /// \method rssi() /// Return RSSI value. /// STATIC mp_obj_t scan_entry_get_rssi(mp_obj_t self_in) { ubluepy_scan_entry_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int(self->rssi); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scan_entry_get_rssi_obj, scan_entry_get_rssi); /// \method getScanData() /// Return list of the scan data tupples (ad_type, description, value) /// STATIC mp_obj_t scan_entry_get_scan_data(mp_obj_t self_in) { ubluepy_scan_entry_obj_t * self = MP_OBJ_TO_PTR(self_in); mp_obj_t retval_list = mp_obj_new_list(0, NULL); // TODO: check if self->data is set mp_obj_array_t * data = MP_OBJ_TO_PTR(self->data); uint16_t byte_index = 0; while (byte_index < data->len) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); uint8_t adv_item_len = ((uint8_t * )data->items)[byte_index]; uint8_t adv_item_type = ((uint8_t * )data->items)[byte_index + 1]; mp_obj_t description = mp_const_none; mp_map_t *constant_map = mp_obj_dict_get_map(ubluepy_constants_ad_types_type.locals_dict); mp_map_elem_t *ad_types_table = MP_OBJ_TO_PTR(constant_map->table); uint16_t num_of_elements = constant_map->used; for (uint16_t i = 0; i < num_of_elements; i++) { mp_map_elem_t element = (mp_map_elem_t)*ad_types_table; ad_types_table++; uint16_t element_value = mp_obj_get_int(element.value); if (adv_item_type == element_value) { qstr key_qstr = MP_OBJ_QSTR_VALUE(element.key); const char * text = qstr_str(key_qstr); size_t len = qstr_len(key_qstr); vstr_t vstr; vstr_init(&vstr, len); vstr_printf(&vstr, "%s", text); description = mp_obj_new_str(vstr.buf, vstr.len); vstr_clear(&vstr); } } t->items[0] = MP_OBJ_NEW_SMALL_INT(adv_item_type); t->items[1] = description; t->items[2] = mp_obj_new_bytearray(adv_item_len - 1, &((uint8_t * )data->items)[byte_index + 2]); mp_obj_list_append(retval_list, MP_OBJ_FROM_PTR(t)); byte_index += adv_item_len + 1; } return retval_list; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_scan_entry_get_scan_data_obj, scan_entry_get_scan_data); STATIC const mp_rom_map_elem_t ubluepy_scan_entry_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_addr), MP_ROM_PTR(&bluepy_scan_entry_get_addr_obj) }, { MP_ROM_QSTR(MP_QSTR_addr_type), MP_ROM_PTR(&bluepy_scan_entry_get_addr_type_obj) }, { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bluepy_scan_entry_get_rssi_obj) }, { MP_ROM_QSTR(MP_QSTR_getScanData), MP_ROM_PTR(&ubluepy_scan_entry_get_scan_data_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ubluepy_scan_entry_locals_dict, ubluepy_scan_entry_locals_dict_table); const mp_obj_type_t ubluepy_scan_entry_type = { { &mp_type_type }, .name = MP_QSTR_ScanEntry, .print = ubluepy_scan_entry_print, .locals_dict = (mp_obj_dict_t*)&ubluepy_scan_entry_locals_dict }; #endif // MICROPY_PY_UBLUEPY_CENTRAL micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_scanner.c000066400000000000000000000102231357706137100244530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" #include "py/runtime.h" #include "py/objstr.h" #include "py/objlist.h" #if MICROPY_PY_UBLUEPY_CENTRAL #include "ble_drv.h" #include "mphalport.h" STATIC void adv_event_handler(mp_obj_t self_in, uint16_t event_id, ble_drv_adv_data_t * data) { ubluepy_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); ubluepy_scan_entry_obj_t * item = m_new_obj(ubluepy_scan_entry_obj_t); item->base.type = &ubluepy_scan_entry_type; vstr_t vstr; vstr_init(&vstr, 17); vstr_printf(&vstr, ""HEX2_FMT":"HEX2_FMT":"HEX2_FMT":" \ HEX2_FMT":"HEX2_FMT":"HEX2_FMT"", data->p_peer_addr[5], data->p_peer_addr[4], data->p_peer_addr[3], data->p_peer_addr[2], data->p_peer_addr[1], data->p_peer_addr[0]); item->addr = mp_obj_new_str(vstr.buf, vstr.len); vstr_clear(&vstr); item->addr_type = data->addr_type; item->rssi = data->rssi; item->data = mp_obj_new_bytearray(data->data_len, data->p_data); mp_obj_list_append(self->adv_reports, item); // Continue scanning ble_drv_scan_start(true); } STATIC void ubluepy_scanner_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { ubluepy_scanner_obj_t * self = (ubluepy_scanner_obj_t *)o; (void)self; mp_printf(print, "Scanner"); } STATIC mp_obj_t ubluepy_scanner_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = { }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); ubluepy_scanner_obj_t * s = m_new_obj(ubluepy_scanner_obj_t); s->base.type = type; return MP_OBJ_FROM_PTR(s); } /// \method scan(timeout) /// Scan for devices. Timeout is in milliseconds and will set the duration /// of the scanning. /// STATIC mp_obj_t scanner_scan(mp_obj_t self_in, mp_obj_t timeout_in) { ubluepy_scanner_obj_t * self = MP_OBJ_TO_PTR(self_in); mp_int_t timeout = mp_obj_get_int(timeout_in); self->adv_reports = mp_obj_new_list(0, NULL); ble_drv_adv_report_handler_set(MP_OBJ_FROM_PTR(self), adv_event_handler); // start ble_drv_scan_start(false); // sleep mp_hal_delay_ms(timeout); // stop ble_drv_scan_stop(); return self->adv_reports; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_scanner_scan_obj, scanner_scan); STATIC const mp_rom_map_elem_t ubluepy_scanner_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&ubluepy_scanner_scan_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ubluepy_scanner_locals_dict, ubluepy_scanner_locals_dict_table); const mp_obj_type_t ubluepy_scanner_type = { { &mp_type_type }, .name = MP_QSTR_Scanner, .print = ubluepy_scanner_print, .make_new = ubluepy_scanner_make_new, .locals_dict = (mp_obj_dict_t*)&ubluepy_scanner_locals_dict }; #endif // MICROPY_PY_UBLUEPY_CENTRAL micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_service.c000066400000000000000000000146701357706137100244740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/runtime.h" #include "py/objlist.h" #if MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL #include "modubluepy.h" #include "ble_drv.h" STATIC void ubluepy_service_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { ubluepy_service_obj_t * self = (ubluepy_service_obj_t *)o; mp_printf(print, "Service(handle: 0x" HEX2_FMT ")", self->handle); } STATIC mp_obj_t ubluepy_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_NEW_UUID, ARG_NEW_TYPE }; static const mp_arg_t allowed_args[] = { { ARG_NEW_UUID, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { ARG_NEW_TYPE, MP_ARG_INT, {.u_int = UBLUEPY_SERVICE_PRIMARY} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); ubluepy_service_obj_t *s = m_new_obj(ubluepy_service_obj_t); s->base.type = type; mp_obj_t uuid_obj = args[ARG_NEW_UUID].u_obj; if (uuid_obj == MP_OBJ_NULL) { return MP_OBJ_FROM_PTR(s); } if (mp_obj_is_type(uuid_obj, &ubluepy_uuid_type)) { s->p_uuid = MP_OBJ_TO_PTR(uuid_obj); uint8_t type = args[ARG_NEW_TYPE].u_int; if (type > 0 && type <= UBLUEPY_SERVICE_PRIMARY) { s->type = type; } else { mp_raise_ValueError("Invalid Service type"); } (void)ble_drv_service_add(s); } else { mp_raise_ValueError("Invalid UUID parameter"); } // clear reference to peripheral s->p_periph = NULL; s->char_list = mp_obj_new_list(0, NULL); return MP_OBJ_FROM_PTR(s); } /// \method addCharacteristic(Characteristic) /// Add Characteristic to the Service. /// STATIC mp_obj_t service_add_characteristic(mp_obj_t self_in, mp_obj_t characteristic) { ubluepy_service_obj_t * self = MP_OBJ_TO_PTR(self_in); ubluepy_characteristic_obj_t * p_char = MP_OBJ_TO_PTR(characteristic); p_char->service_handle = self->handle; bool retval = ble_drv_characteristic_add(p_char); if (retval) { p_char->p_service = self; } mp_obj_list_append(self->char_list, characteristic); // return mp_obj_new_bool(retval); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_service_add_char_obj, service_add_characteristic); /// \method getCharacteristics() /// Return list with all characteristics registered in the Service. /// STATIC mp_obj_t service_get_chars(mp_obj_t self_in) { ubluepy_service_obj_t * self = MP_OBJ_TO_PTR(self_in); return self->char_list; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_service_get_chars_obj, service_get_chars); /// \method getCharacteristic(UUID) /// Return Characteristic with the given UUID. /// STATIC mp_obj_t service_get_characteristic(mp_obj_t self_in, mp_obj_t uuid) { ubluepy_service_obj_t * self = MP_OBJ_TO_PTR(self_in); ubluepy_uuid_obj_t * p_uuid = MP_OBJ_TO_PTR(uuid); // validate that there is an UUID object passed in as parameter if (!(mp_obj_is_type(uuid, &ubluepy_uuid_type))) { mp_raise_ValueError("Invalid UUID parameter"); } mp_obj_t * chars = NULL; mp_uint_t num_chars = 0; mp_obj_get_array(self->char_list, &num_chars, &chars); for (uint8_t i = 0; i < num_chars; i++) { ubluepy_characteristic_obj_t * p_char = (ubluepy_characteristic_obj_t *)chars[i]; bool type_match = p_char->p_uuid->type == p_uuid->type; bool uuid_match = ((uint16_t)(*(uint16_t *)&p_char->p_uuid->value[0]) == (uint16_t)(*(uint16_t *)&p_uuid->value[0])); if (type_match && uuid_match) { return MP_OBJ_FROM_PTR(p_char); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_service_get_char_obj, service_get_characteristic); /// \method uuid() /// Get UUID instance of the Service. /// STATIC mp_obj_t service_uuid(mp_obj_t self_in) { ubluepy_service_obj_t * self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_FROM_PTR(self->p_uuid); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_service_get_uuid_obj, service_uuid); STATIC const mp_rom_map_elem_t ubluepy_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_getCharacteristic), MP_ROM_PTR(&ubluepy_service_get_char_obj) }, { MP_ROM_QSTR(MP_QSTR_addCharacteristic), MP_ROM_PTR(&ubluepy_service_add_char_obj) }, { MP_ROM_QSTR(MP_QSTR_getCharacteristics), MP_ROM_PTR(&ubluepy_service_get_chars_obj) }, #if 0 // Properties { MP_ROM_QSTR(MP_QSTR_peripheral), MP_ROM_PTR(&ubluepy_service_get_peripheral_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&ubluepy_service_get_uuid_obj) }, { MP_ROM_QSTR(MP_QSTR_PRIMARY), MP_ROM_INT(UBLUEPY_SERVICE_PRIMARY) }, { MP_ROM_QSTR(MP_QSTR_SECONDARY), MP_ROM_INT(UBLUEPY_SERVICE_SECONDARY) }, }; STATIC MP_DEFINE_CONST_DICT(ubluepy_service_locals_dict, ubluepy_service_locals_dict_table); const mp_obj_type_t ubluepy_service_type = { { &mp_type_type }, .name = MP_QSTR_Service, .print = ubluepy_service_print, .make_new = ubluepy_service_make_new, .locals_dict = (mp_obj_dict_t*)&ubluepy_service_locals_dict }; #endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL micropython-1.12/ports/nrf/modules/ubluepy/ubluepy_uuid.c000066400000000000000000000157451357706137100240060ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/runtime.h" #include "py/objstr.h" #include "py/misc.h" #if MICROPY_PY_UBLUEPY #include "modubluepy.h" #include "ble_drv.h" STATIC void ubluepy_uuid_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { ubluepy_uuid_obj_t * self = (ubluepy_uuid_obj_t *)o; if (self->type == UBLUEPY_UUID_16_BIT) { mp_printf(print, "UUID(uuid: 0x" HEX2_FMT HEX2_FMT ")", self->value[1], self->value[0]); } else { mp_printf(print, "UUID(uuid: 0x" HEX2_FMT HEX2_FMT ", VS idx: " HEX2_FMT ")", self->value[1], self->value[0], self->uuid_vs_idx); } } STATIC mp_obj_t ubluepy_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_NEW_UUID }; static const mp_arg_t allowed_args[] = { { ARG_NEW_UUID, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); ubluepy_uuid_obj_t *s = m_new_obj(ubluepy_uuid_obj_t); s->base.type = type; mp_obj_t uuid_obj = args[ARG_NEW_UUID].u_obj; if (uuid_obj == MP_OBJ_NULL) { return MP_OBJ_FROM_PTR(s); } if (mp_obj_is_int(uuid_obj)) { s->type = UBLUEPY_UUID_16_BIT; s->value[1] = (((uint16_t)mp_obj_get_int(uuid_obj)) >> 8) & 0xFF; s->value[0] = ((uint8_t)mp_obj_get_int(uuid_obj)) & 0xFF; } else if (mp_obj_is_str(uuid_obj)) { GET_STR_DATA_LEN(uuid_obj, str_data, str_len); if (str_len == 6) { // Assume hex digit prefixed with 0x s->type = UBLUEPY_UUID_16_BIT; s->value[0] = unichar_xdigit_value(str_data[5]); s->value[0] += unichar_xdigit_value(str_data[4]) << 4; s->value[1] = unichar_xdigit_value(str_data[3]); s->value[1] += unichar_xdigit_value(str_data[2]) << 4; } else if (str_len == 36) { s->type = UBLUEPY_UUID_128_BIT; uint8_t buffer[16]; buffer[0] = unichar_xdigit_value(str_data[35]); buffer[0] += unichar_xdigit_value(str_data[34]) << 4; buffer[1] = unichar_xdigit_value(str_data[33]); buffer[1] += unichar_xdigit_value(str_data[32]) << 4; buffer[2] = unichar_xdigit_value(str_data[31]); buffer[2] += unichar_xdigit_value(str_data[30]) << 4; buffer[3] = unichar_xdigit_value(str_data[29]); buffer[3] += unichar_xdigit_value(str_data[28]) << 4; buffer[4] = unichar_xdigit_value(str_data[27]); buffer[4] += unichar_xdigit_value(str_data[26]) << 4; buffer[5] = unichar_xdigit_value(str_data[25]); buffer[5] += unichar_xdigit_value(str_data[24]) << 4; // 23 '-' buffer[6] = unichar_xdigit_value(str_data[22]); buffer[6] += unichar_xdigit_value(str_data[21]) << 4; buffer[7] = unichar_xdigit_value(str_data[20]); buffer[7] += unichar_xdigit_value(str_data[19]) << 4; // 18 '-' buffer[8] = unichar_xdigit_value(str_data[17]); buffer[8] += unichar_xdigit_value(str_data[16]) << 4; buffer[9] = unichar_xdigit_value(str_data[15]); buffer[9] += unichar_xdigit_value(str_data[14]) << 4; // 13 '-' buffer[10] = unichar_xdigit_value(str_data[12]); buffer[10] += unichar_xdigit_value(str_data[11]) << 4; buffer[11] = unichar_xdigit_value(str_data[10]); buffer[11] += unichar_xdigit_value(str_data[9]) << 4; // 8 '-' // 16-bit field s->value[0] = unichar_xdigit_value(str_data[7]); s->value[0] += unichar_xdigit_value(str_data[6]) << 4; s->value[1] = unichar_xdigit_value(str_data[5]); s->value[1] += unichar_xdigit_value(str_data[4]) << 4; buffer[14] = unichar_xdigit_value(str_data[3]); buffer[14] += unichar_xdigit_value(str_data[2]) << 4; buffer[15] = unichar_xdigit_value(str_data[1]); buffer[15] += unichar_xdigit_value(str_data[0]) << 4; ble_drv_uuid_add_vs(buffer, &s->uuid_vs_idx); } else { mp_raise_ValueError("Invalid UUID string length"); } } else if (mp_obj_is_type(uuid_obj, &ubluepy_uuid_type)) { // deep copy instance ubluepy_uuid_obj_t * p_old = MP_OBJ_TO_PTR(uuid_obj); s->type = p_old->type; s->value[0] = p_old->value[0]; s->value[1] = p_old->value[1]; } else { mp_raise_ValueError("Invalid UUID parameter"); } return MP_OBJ_FROM_PTR(s); } /// \method binVal() /// Get binary value of the 16 or 128 bit UUID. Returned as bytearray type. /// STATIC mp_obj_t uuid_bin_val(mp_obj_t self_in) { ubluepy_uuid_obj_t * self = MP_OBJ_TO_PTR(self_in); // TODO: Extend the uint16 byte value to 16 byte if 128-bit, // also encapsulate it in a bytearray. For now, return // the uint16_t field of the UUID. return MP_OBJ_NEW_SMALL_INT(self->value[0] | self->value[1] << 8); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_uuid_bin_val_obj, uuid_bin_val); STATIC const mp_rom_map_elem_t ubluepy_uuid_locals_dict_table[] = { #if 0 { MP_ROM_QSTR(MP_QSTR_getCommonName), MP_ROM_PTR(&ubluepy_uuid_get_common_name_obj) }, #endif // Properties { MP_ROM_QSTR(MP_QSTR_binVal), MP_ROM_PTR(&ubluepy_uuid_bin_val_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ubluepy_uuid_locals_dict, ubluepy_uuid_locals_dict_table); const mp_obj_type_t ubluepy_uuid_type = { { &mp_type_type }, .name = MP_QSTR_UUID, .print = ubluepy_uuid_print, .make_new = ubluepy_uuid_make_new, .locals_dict = (mp_obj_dict_t*)&ubluepy_uuid_locals_dict }; #endif // MICROPY_PY_UBLUEPY micropython-1.12/ports/nrf/modules/uos/000077500000000000000000000000001357706137100202345ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/uos/microbitfs.c000066400000000000000000000615061357706137100225510ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Mark Shannon * Copyright (c) 2017 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "microbitfs.h" #include "drivers/flash.h" #include "modrandom.h" #include "py/obj.h" #include "py/stream.h" #include "py/runtime.h" #include "extmod/vfs.h" #include "mpconfigport.h" #if MICROPY_MBFS #define DEBUG_FILE 0 #if DEBUG_FILE #define DEBUG(s) printf s #else #define DEBUG(s) (void)0 #endif /** How it works: * The File System consists of up to MAX_CHUNKS_IN_FILE_SYSTEM chunks of CHUNK_SIZE each, * plus one spare page which holds persistent configuration data and is used. for bulk erasing. * The spare page is either the first or the last page and will be switched by a bulk erase. * The exact number of chunks will depend on the amount of flash available. * * Each chunk consists of a one byte marker and a one byte tail * The marker shows whether this chunk is the start of a file, the midst of a file * (in which case it refers to the previous chunk in the file) or whether it is UNUSED * (and erased) or FREED (which means it is unused, but not erased). * Chunks are selected in a randomised round-robin fashion to even out wear on the flash * memory as much as possible. * A file consists of a linked list of chunks. The first chunk in a file contains its name * as well as the end chunk and offset. * Files are found by linear search of the chunks, this means that no meta-data needs to be stored * outside of the file, which prevents wear hot-spots. Since there are fewer than 250 chunks, * the search is fast enough. * * Chunks are numbered from 1 as we need to reserve 0 as the FREED marker. * * Writing to files relies on the persistent API which is high-level wrapper on top of the Nordic SDK. */ #define CHUNK_SIZE (1<>MBFS_LOG_CHUNK_SIZE; } STATIC void randomise_start_index(void) { start_index = machine_rng_generate_random_word() % chunks_in_file_system + 1; } void microbit_filesystem_init(void) { init_limits(); randomise_start_index(); file_chunk *base = first_page(); if (base->marker == PERSISTENT_DATA_MARKER) { file_system_chunks = &base[(FLASH_PAGESIZE>>MBFS_LOG_CHUNK_SIZE)-1]; } else if (((file_chunk *)last_page())->marker == PERSISTENT_DATA_MARKER) { file_system_chunks = &base[-1]; } else { flash_write_byte((uint32_t)&((file_chunk *)last_page())->marker, PERSISTENT_DATA_MARKER); file_system_chunks = &base[-1]; } } STATIC void copy_page(void *dest, void *src) { DEBUG(("FILE DEBUG: Copying page from %lx to %lx.\r\n", (uint32_t)src, (uint32_t)dest)); flash_page_erase((uint32_t)dest); file_chunk *src_chunk = src; file_chunk *dest_chunk = dest; uint32_t chunks = FLASH_PAGESIZE>>MBFS_LOG_CHUNK_SIZE; for (uint32_t i = 0; i < chunks; i++) { if (src_chunk[i].marker != FREED_CHUNK) { flash_write_bytes((uint32_t)&dest_chunk[i], (uint8_t*)&src_chunk[i], CHUNK_SIZE); } } } // Move entire file system up or down one page, copying all used chunks // Freed chunks are not copied, so become erased. // There should be no erased chunks before the sweep (or it would be unnecessary) // but if there are this should work correctly. // // The direction of the sweep depends on whether the persistent data is in the first or last page // The persistent data is copied to RAM, leaving its page unused. // Then all the pages are copied, one by one, into the adjacent newly unused page. // Finally, the persistent data is saved back to the opposite end of the filesystem from whence it came. // STATIC void filesystem_sweep(void) { persistent_config_t config; uint8_t *page; uint8_t *end_page; int step; uint32_t page_size = FLASH_PAGESIZE; DEBUG(("FILE DEBUG: Sweeping file system\r\n")); if (((file_chunk *)first_page())->marker == PERSISTENT_DATA_MARKER) { config = *(persistent_config_t *)first_page(); page = first_page(); end_page = last_page(); step = page_size; } else { config = *(persistent_config_t *)last_page(); page = last_page(); end_page = first_page(); step = -page_size; } while (page != end_page) { uint8_t *next_page = page+step; flash_page_erase((uint32_t)page); copy_page(page, next_page); page = next_page; } flash_page_erase((uint32_t)end_page); flash_write_bytes((uint32_t)end_page, (uint8_t*)&config, sizeof(config)); microbit_filesystem_init(); } STATIC inline byte *seek_address(file_descriptor_obj *self) { return (byte*)&(file_system_chunks[self->seek_chunk].data[self->seek_offset]); } STATIC uint8_t microbit_find_file(const char *name, int name_len) { for (uint8_t index = 1; index <= chunks_in_file_system; index++) { const file_chunk *p = &file_system_chunks[index]; if (p->marker != FILE_START) continue; if (p->header.name_len != name_len) continue; if (memcmp(name, &p->header.filename[0], name_len) == 0) { DEBUG(("FILE DEBUG: File found. index %d\r\n", index)); return index; } } DEBUG(("FILE DEBUG: File not found.\r\n")); return FILE_NOT_FOUND; } // Return a free, erased chunk. // Search the chunks: // 1 If an UNUSED chunk is found, then return that. // 2. If an entire page of FREED chunks is found, then erase the page and return the first chunk // 3. If the number of FREED chunks is >= MIN_CHUNKS_FOR_SWEEP, then // 3a. Sweep the filesystem and restart. // 3b. Fail and return FILE_NOT_FOUND // STATIC uint8_t find_chunk_and_erase(void) { // Start search at a random chunk to spread the wear more evenly. // Search for unused chunk uint8_t index = start_index; do { const file_chunk *p = &file_system_chunks[index]; if (p->marker == UNUSED_CHUNK) { DEBUG(("FILE DEBUG: Unused chunk found: %d\r\n", index)); return index; } index++; if (index == chunks_in_file_system+1) index = 1; } while (index != start_index); // Search for FREED page, and total up FREED chunks uint32_t freed_chunks = 0; index = start_index; uint32_t chunks_per_page = FLASH_PAGESIZE>>MBFS_LOG_CHUNK_SIZE; do { const file_chunk *p = &file_system_chunks[index]; if (p->marker == FREED_CHUNK) { freed_chunks++; } if (FLASH_IS_PAGE_ALIGNED(p)) { uint32_t i; for (i = 0; i < chunks_per_page; i++) { if (p[i].marker != FREED_CHUNK) break; } if (i == chunks_per_page) { DEBUG(("FILE DEBUG: Found freed page of chunks: %d\r\n", index)); flash_page_erase((uint32_t)&file_system_chunks[index]); return index; } } index++; if (index == chunks_in_file_system+1) index = 1; } while (index != start_index); DEBUG(("FILE DEBUG: %lu free chunks\r\n", freed_chunks)); if (freed_chunks < MIN_CHUNKS_FOR_SWEEP) { return FILE_NOT_FOUND; } // No freed pages, so sweep file system. filesystem_sweep(); // This is guaranteed to succeed. return find_chunk_and_erase(); } STATIC mp_obj_t microbit_file_name(file_descriptor_obj *fd) { return mp_obj_new_str(&(file_system_chunks[fd->start_chunk].header.filename[0]), file_system_chunks[fd->start_chunk].header.name_len); } STATIC file_descriptor_obj *microbit_file_descriptor_new(uint8_t start_chunk, bool write, bool binary); STATIC void clear_file(uint8_t chunk) { do { flash_write_byte((uint32_t)&(file_system_chunks[chunk].marker), FREED_CHUNK); DEBUG(("FILE DEBUG: Freeing chunk %d.\n", chunk)); chunk = file_system_chunks[chunk].next_chunk; } while (chunk <= chunks_in_file_system); } STATIC file_descriptor_obj *microbit_file_open(const char *name, size_t name_len, bool write, bool binary) { if (name_len > MAX_FILENAME_LENGTH) { return NULL; } uint8_t index = microbit_find_file(name, name_len); if (write) { if (index != FILE_NOT_FOUND) { // Free old file clear_file(index); } index = find_chunk_and_erase(); if (index == FILE_NOT_FOUND) { mp_raise_OSError(MP_ENOSPC); } flash_write_byte((uint32_t)&(file_system_chunks[index].marker), FILE_START); flash_write_byte((uint32_t)&(file_system_chunks[index].header.name_len), name_len); flash_write_bytes((uint32_t)&(file_system_chunks[index].header.filename[0]), (uint8_t*)name, name_len); } else { if (index == FILE_NOT_FOUND) { return NULL; } } return microbit_file_descriptor_new(index, write, binary); } STATIC file_descriptor_obj *microbit_file_descriptor_new(uint8_t start_chunk, bool write, bool binary) { file_descriptor_obj *res = m_new_obj(file_descriptor_obj); if (binary) { res->base.type = &uos_mbfs_fileio_type; } else { res->base.type = &uos_mbfs_textio_type; } res->start_chunk = start_chunk; res->seek_chunk = start_chunk; res->seek_offset = file_system_chunks[start_chunk].header.name_len+2; res->writable = write; res->open = true; res->binary = binary; return res; } STATIC mp_obj_t microbit_remove(mp_obj_t filename) { size_t name_len; const char *name = mp_obj_str_get_data(filename, &name_len); mp_uint_t index = microbit_find_file(name, name_len); if (index == 255) { mp_raise_OSError(MP_ENOENT); } clear_file(index); return mp_const_none; } STATIC void check_file_open(file_descriptor_obj *self) { if (!self->open) { mp_raise_ValueError("I/O operation on closed file"); } } STATIC int advance(file_descriptor_obj *self, uint32_t n, bool write) { DEBUG(("FILE DEBUG: Advancing from chunk %d, offset %d.\r\n", self->seek_chunk, self->seek_offset)); self->seek_offset += n; if (self->seek_offset == DATA_PER_CHUNK) { self->seek_offset = 0; if (write) { uint8_t next_chunk = find_chunk_and_erase(); if (next_chunk == FILE_NOT_FOUND) { clear_file(self->start_chunk); self->open = false; return MP_ENOSPC; } // Link next chunk to this one flash_write_byte((uint32_t)&(file_system_chunks[self->seek_chunk].next_chunk), next_chunk); flash_write_byte((uint32_t)&(file_system_chunks[next_chunk].marker), self->seek_chunk); } self->seek_chunk = file_system_chunks[self->seek_chunk].next_chunk; } DEBUG(("FILE DEBUG: Advanced to chunk %d, offset %d.\r\n", self->seek_chunk, self->seek_offset)); return 0; } STATIC mp_uint_t microbit_file_read(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) { file_descriptor_obj *self = (file_descriptor_obj *)obj; check_file_open(self); if (self->writable || file_system_chunks[self->start_chunk].marker == FREED_CHUNK) { *errcode = MP_EBADF; return MP_STREAM_ERROR; } uint32_t bytes_read = 0; uint8_t *data = buf; while (1) { mp_uint_t to_read = DATA_PER_CHUNK - self->seek_offset; if (file_system_chunks[self->seek_chunk].next_chunk == UNUSED_CHUNK) { uint8_t end_offset = file_system_chunks[self->start_chunk].header.end_offset; if (end_offset == UNUSED_CHUNK) { to_read = 0; } else { to_read = MIN(to_read, (mp_uint_t)end_offset-self->seek_offset); } } to_read = MIN(to_read, size-bytes_read); if (to_read == 0) { break; } memcpy(data+bytes_read, seek_address(self), to_read); advance(self, to_read, false); bytes_read += to_read; } return bytes_read; } STATIC mp_uint_t microbit_file_write(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode) { file_descriptor_obj *self = (file_descriptor_obj *)obj; check_file_open(self); if (!self->writable || file_system_chunks[self->start_chunk].marker == FREED_CHUNK) { *errcode = MP_EBADF; return MP_STREAM_ERROR; } uint32_t len = size; const uint8_t *data = buf; while (len) { uint32_t to_write = MIN(((uint32_t)(DATA_PER_CHUNK - self->seek_offset)), len); flash_write_bytes((uint32_t)seek_address(self), data, to_write); int err = advance(self, to_write, true); if (err) { *errcode = err; return MP_STREAM_ERROR; } data += to_write; len -= to_write; } return size; } STATIC void microbit_file_close(file_descriptor_obj *fd) { if (fd->writable) { flash_write_byte((uint32_t)&(file_system_chunks[fd->start_chunk].header.end_offset), fd->seek_offset); } fd->open = false; } STATIC mp_obj_t microbit_file_list(void) { mp_obj_t res = mp_obj_new_list(0, NULL); for (uint8_t index = 1; index <= chunks_in_file_system; index++) { if (file_system_chunks[index].marker == FILE_START) { mp_obj_t name = mp_obj_new_str(&file_system_chunks[index].header.filename[0], file_system_chunks[index].header.name_len); mp_obj_list_append(res, name); } } return res; } STATIC mp_obj_t microbit_file_size(mp_obj_t filename) { size_t name_len; const char *name = mp_obj_str_get_data(filename, &name_len); uint8_t chunk = microbit_find_file(name, name_len); if (chunk == 255) { mp_raise_OSError(MP_ENOENT); } mp_uint_t len = 0; uint8_t end_offset = file_system_chunks[chunk].header.end_offset; uint8_t offset = file_system_chunks[chunk].header.name_len+2; while (file_system_chunks[chunk].next_chunk != UNUSED_CHUNK) { len += DATA_PER_CHUNK - offset; chunk = file_system_chunks[chunk].next_chunk; offset = 0; } len += end_offset - offset; return mp_obj_new_int(len); } STATIC mp_uint_t file_read_byte(file_descriptor_obj *fd) { if (file_system_chunks[fd->seek_chunk].next_chunk == UNUSED_CHUNK) { uint8_t end_offset = file_system_chunks[fd->start_chunk].header.end_offset; if (end_offset == UNUSED_CHUNK || fd->seek_offset == end_offset) { return (mp_uint_t)-1; } } mp_uint_t res = file_system_chunks[fd->seek_chunk].data[fd->seek_offset]; advance(fd, 1, false); return res; } // Now follows the code to integrate this filesystem into the uos module. mp_lexer_t *uos_mbfs_new_reader(const char *filename) { file_descriptor_obj *fd = microbit_file_open(filename, strlen(filename), false, false); if (fd == NULL) { mp_raise_OSError(MP_ENOENT); } mp_reader_t reader; reader.data = fd; reader.readbyte = (mp_uint_t(*)(void*))file_read_byte; reader.close = (void(*)(void*))microbit_file_close; // no-op return mp_lexer_new(qstr_from_str(filename), reader); } mp_import_stat_t uos_mbfs_import_stat(const char *path) { uint8_t chunk = microbit_find_file(path, strlen(path)); if (chunk == FILE_NOT_FOUND) { return MP_IMPORT_STAT_NO_EXIST; } else { return MP_IMPORT_STAT_FILE; } } STATIC mp_obj_t uos_mbfs_file_name(mp_obj_t self) { file_descriptor_obj *fd = (file_descriptor_obj*)self; return microbit_file_name(fd); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(uos_mbfs_file_name_obj, uos_mbfs_file_name); STATIC mp_obj_t uos_mbfs_file_close(mp_obj_t self) { file_descriptor_obj *fd = (file_descriptor_obj*)self; microbit_file_close(fd); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(uos_mbfs_file_close_obj, uos_mbfs_file_close); STATIC mp_obj_t uos_mbfs_remove(mp_obj_t name) { return microbit_remove(name); } MP_DEFINE_CONST_FUN_OBJ_1(uos_mbfs_remove_obj, uos_mbfs_remove); STATIC mp_obj_t uos_mbfs_file___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; return uos_mbfs_file_close(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uos_mbfs_file___exit___obj, 4, 4, uos_mbfs_file___exit__); typedef struct { mp_obj_base_t base; mp_fun_1_t iternext; uint8_t index; } uos_mbfs_ilistdir_it_t; STATIC mp_obj_t uos_mbfs_ilistdir_it_iternext(mp_obj_t self_in) { uos_mbfs_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); // Read until the next FILE_START chunk. for (; self->index <= chunks_in_file_system; self->index++) { if (file_system_chunks[self->index].marker != FILE_START) { continue; } // Get the file name as str object. mp_obj_t name = mp_obj_new_str(&file_system_chunks[self->index].header.filename[0], file_system_chunks[self->index].header.name_len); // make 3-tuple with info about this entry mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); t->items[0] = name; t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG); // all entries are files t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number self->index++; return MP_OBJ_FROM_PTR(t); } return MP_OBJ_STOP_ITERATION; } STATIC mp_obj_t uos_mbfs_ilistdir(void) { uos_mbfs_ilistdir_it_t *iter = m_new_obj(uos_mbfs_ilistdir_it_t); iter->base.type = &mp_type_polymorph_iter; iter->iternext = uos_mbfs_ilistdir_it_iternext; iter->index = 1; return MP_OBJ_FROM_PTR(iter); } MP_DEFINE_CONST_FUN_OBJ_0(uos_mbfs_ilistdir_obj, uos_mbfs_ilistdir); MP_DEFINE_CONST_FUN_OBJ_0(uos_mbfs_listdir_obj, microbit_file_list); STATIC mp_obj_t microbit_file_writable(mp_obj_t self) { return mp_obj_new_bool(((file_descriptor_obj *)self)->writable); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(microbit_file_writable_obj, microbit_file_writable); STATIC const mp_map_elem_t uos_mbfs_file_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&uos_mbfs_file_close_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&uos_mbfs_file_name_obj }, { MP_ROM_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj }, { MP_ROM_QSTR(MP_QSTR___exit__), (mp_obj_t)&uos_mbfs_file___exit___obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_writable), (mp_obj_t)µbit_file_writable_obj }, /* Stream methods */ { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj}, { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj}, }; STATIC MP_DEFINE_CONST_DICT(uos_mbfs_file_locals_dict, uos_mbfs_file_locals_dict_table); STATIC const mp_stream_p_t textio_stream_p = { .read = microbit_file_read, .write = microbit_file_write, .is_text = true, }; const mp_obj_type_t uos_mbfs_textio_type = { { &mp_type_type }, .name = MP_QSTR_TextIO, .protocol = &textio_stream_p, .locals_dict = (mp_obj_dict_t*)&uos_mbfs_file_locals_dict, }; STATIC const mp_stream_p_t fileio_stream_p = { .read = microbit_file_read, .write = microbit_file_write, }; const mp_obj_type_t uos_mbfs_fileio_type = { { &mp_type_type }, .name = MP_QSTR_FileIO, .protocol = &fileio_stream_p, .locals_dict = (mp_obj_dict_t*)&uos_mbfs_file_locals_dict, }; // From micro:bit fileobj.c mp_obj_t uos_mbfs_open(size_t n_args, const mp_obj_t *args) { /// -1 means default; 0 explicitly false; 1 explicitly true. int read = -1; int text = -1; if (n_args == 2) { size_t len; const char *mode = mp_obj_str_get_data(args[1], &len); for (mp_uint_t i = 0; i < len; i++) { if (mode[i] == 'r' || mode[i] == 'w') { if (read >= 0) { goto mode_error; } read = (mode[i] == 'r'); } else if (mode[i] == 'b' || mode[i] == 't') { if (text >= 0) { goto mode_error; } text = (mode[i] == 't'); } else { goto mode_error; } } } size_t name_len; const char *filename = mp_obj_str_get_data(args[0], &name_len); file_descriptor_obj *res = microbit_file_open(filename, name_len, read == 0, text == 0); if (res == NULL) { mp_raise_OSError(MP_ENOENT); } return res; mode_error: mp_raise_ValueError("illegal mode"); } STATIC mp_obj_t uos_mbfs_stat(mp_obj_t filename) { mp_obj_t file_size = microbit_file_size(filename); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG); // st_mode t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid t->items[6] = file_size; // st_size t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // st_atime t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // st_mtime t->items[9] = MP_OBJ_NEW_SMALL_INT(0); // st_ctime return MP_OBJ_FROM_PTR(t); } MP_DEFINE_CONST_FUN_OBJ_1(uos_mbfs_stat_obj, uos_mbfs_stat); #endif // MICROPY_MBFS micropython-1.12/ports/nrf/modules/uos/microbitfs.h000066400000000000000000000042061357706137100225500ustar00rootroot00000000000000/* * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Mark Shannon * Copyright (c) 2017 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __MICROPY_INCLUDED_FILESYSTEM_H__ #define __MICROPY_INCLUDED_FILESYSTEM_H__ #include "py/obj.h" #include "py/lexer.h" #ifndef MBFS_LOG_CHUNK_SIZE // This property can be tuned to make the filesystem bigger (while keeping // the max number of blocks). Note that it cannot (currently) be increased // beyond 8 or uint8_t integers will overflow. // 2^7 == 128 bytes // (128-2) bytes/block * 252 blocks = 31752 usable bytes #define MBFS_LOG_CHUNK_SIZE 7 #endif mp_obj_t uos_mbfs_open(size_t n_args, const mp_obj_t *args); void microbit_filesystem_init(void); mp_lexer_t *uos_mbfs_new_reader(const char *filename); mp_import_stat_t uos_mbfs_import_stat(const char *path); MP_DECLARE_CONST_FUN_OBJ_0(uos_mbfs_listdir_obj); MP_DECLARE_CONST_FUN_OBJ_0(uos_mbfs_ilistdir_obj); MP_DECLARE_CONST_FUN_OBJ_1(uos_mbfs_remove_obj); MP_DECLARE_CONST_FUN_OBJ_1(uos_mbfs_stat_obj); #endif // __MICROPY_INCLUDED_FILESYSTEM_H__ micropython-1.12/ports/nrf/modules/uos/moduos.c000066400000000000000000000160041357706137100217070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpstate.h" #include "py/runtime.h" #include "py/objtuple.h" #include "py/objstr.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "modules/uos/microbitfs.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "genhdr/mpversion.h" //#include "timeutils.h" #include "uart.h" //#include "portmodules.h" #if MICROPY_HW_ENABLE_RNG #include "modrandom.h" #endif // MICROPY_HW_ENABLE_RNG /// \module os - basic "operating system" services /// /// The `os` module contains functions for filesystem access and `urandom`. /// /// The filesystem has `/` as the root directory, and the available physical /// drives are accessible from here. They are currently: /// /// /flash -- the internal flash filesystem /// /sd -- the SD card (if it exists) /// /// On boot up, the current directory is `/flash` if no SD card is inserted, /// otherwise it is `/sd`. STATIC const qstr os_uname_info_fields[] = { MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine }; STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "pyboard"); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "pyboard"); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); STATIC MP_DEFINE_ATTRTUPLE( os_uname_info_obj, os_uname_info_fields, 5, (mp_obj_t)&os_uname_info_sysname_obj, (mp_obj_t)&os_uname_info_nodename_obj, (mp_obj_t)&os_uname_info_release_obj, (mp_obj_t)&os_uname_info_version_obj, (mp_obj_t)&os_uname_info_machine_obj ); STATIC mp_obj_t os_uname(void) { return (mp_obj_t)&os_uname_info_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); #if MICROPY_VFS /// \function sync() /// Sync all filesystems. STATIC mp_obj_t os_sync(void) { for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { // this assumes that vfs->obj is fs_user_mount_t with block device functions disk_ioctl(MP_OBJ_TO_PTR(vfs->obj), CTRL_SYNC, NULL); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(mod_os_sync_obj, os_sync); #endif #if MICROPY_HW_ENABLE_RNG /// \function urandom(n) /// Return a bytes object with n random bytes, generated by the hardware /// random number generator. STATIC mp_obj_t os_urandom(mp_obj_t num) { mp_int_t n = mp_obj_get_int(num); vstr_t vstr; vstr_init_len(&vstr, n); for (int i = 0; i < n; i++) { vstr.buf[i] = (uint8_t)(machine_rng_generate_random_word() & 0xFF); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); #endif #if MICROPY_PY_MACHINE_UART // Get or set the UART object that the REPL is repeated on. // TODO should accept any object with read/write methods. STATIC mp_obj_t os_dupterm(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 0) { if (MP_STATE_PORT(board_stdio_uart) == NULL) { return mp_const_none; } else { return MP_STATE_PORT(board_stdio_uart); } } else { if (args[0] == mp_const_none) { MP_STATE_PORT(board_stdio_uart) = NULL; } else if (mp_obj_get_type(args[0]) == &machine_hard_uart_type) { MP_STATE_PORT(board_stdio_uart) = args[0]; } else { mp_raise_ValueError("need a UART object"); } return mp_const_none; } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_dupterm_obj, 0, 1, os_dupterm); #endif // MICROPY_PY_MACHINE_UART STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, #if MICROPY_VFS { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mod_os_sync_obj) }, #elif MICROPY_MBFS { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&uos_mbfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&uos_mbfs_ilistdir_obj) }, // uses ~136 bytes { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&uos_mbfs_stat_obj) }, // uses ~228 bytes { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&uos_mbfs_remove_obj) }, #endif /// \constant sep - separation character used in paths { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) }, #if MICROPY_HW_ENABLE_RNG { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, #endif // these are MicroPython extensions #if MICROPY_PY_MACHINE_UART { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mod_os_dupterm_obj) }, #endif #if MICROPY_VFS { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif }; STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); const mp_obj_module_t mp_module_uos = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&os_module_globals, }; micropython-1.12/ports/nrf/modules/utime/000077500000000000000000000000001357706137100205515ustar00rootroot00000000000000micropython-1.12/ports/nrf/modules/utime/modutime.c000066400000000000000000000037301357706137100225430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/nlr.h" #include "py/smallint.h" #include "py/obj.h" #include "extmod/utime_mphal.h" /// \module time - time related functions /// /// The `time` module provides functions for getting the current time and date, /// and for sleeping. STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t mp_module_utime = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; micropython-1.12/ports/nrf/mpconfigport.h000066400000000000000000000245521357706137100206460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef NRF5_MPCONFIGPORT_H__ #define NRF5_MPCONFIGPORT_H__ #include // options to control how MicroPython is built #ifndef MICROPY_VFS #define MICROPY_VFS (0) #endif #define MICROPY_ALLOC_PATH_MAX (512) #define MICROPY_PERSISTENT_CODE_LOAD (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (0) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #define MICROPY_READER_VFS (MICROPY_VFS) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_EMACS_KEYS (0) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #if NRF51 #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #else #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #endif #if NRF51 #define MICROPY_ALLOC_GC_STACK_SIZE (32) #endif #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #define MICROPY_OPT_MPZ_BITWISE (0) // fatfs configuration used in ffconf.h #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MULTI_PARTITION (1) // TODO these should be generic, not bound to fatfs #define mp_type_fileio fatfs_type_fileio #define mp_type_textio fatfs_type_textio // use vfs's functions for import stat and builtin open #if MICROPY_VFS #define mp_import_stat mp_vfs_import_stat #define mp_builtin_open mp_vfs_open #define mp_builtin_open_obj mp_vfs_open_obj #endif // Enable micro:bit filesystem by default. #ifndef MICROPY_MBFS #define MICROPY_MBFS (1) #endif #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (0) #define MICROPY_PY_BUILTINS_STR_CENTER (0) #define MICROPY_PY_BUILTINS_STR_PARTITION (0) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_EXECFILE (0) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT nrf5_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_STDFILES (0) #define MICROPY_PY_SYS_STDIO_BUFFER (0) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_UERRNO (0) #define MICROPY_PY_UBINASCII (0) #define MICROPY_PY_URANDOM (0) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) #define MICROPY_PY_UCTYPES (0) #define MICROPY_PY_UZLIB (0) #define MICROPY_PY_UJSON (0) #define MICROPY_PY_URE (0) #define MICROPY_PY_UHEAPQ (0) #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (0) #define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hard_i2c_make_new #define MICROPY_PY_MACHINE_SPI (0) #define MICROPY_PY_MACHINE_SPI_MIN_DELAY (0) #define MICROPY_PY_FRAMEBUF (0) #ifndef MICROPY_HW_LED_COUNT #define MICROPY_HW_LED_COUNT (0) #endif #ifndef MICROPY_HW_LED_PULLUP #define MICROPY_HW_LED_PULLUP (0) #endif #ifndef MICROPY_PY_MUSIC #define MICROPY_PY_MUSIC (0) #endif #ifndef MICROPY_PY_MACHINE_ADC #define MICROPY_PY_MACHINE_ADC (0) #endif #ifndef MICROPY_PY_MACHINE_I2C #define MICROPY_PY_MACHINE_I2C (0) #endif #ifndef MICROPY_PY_MACHINE_HW_SPI #define MICROPY_PY_MACHINE_HW_SPI (1) #endif #ifndef MICROPY_PY_MACHINE_HW_PWM #define MICROPY_PY_MACHINE_HW_PWM (0) #endif #ifndef MICROPY_PY_MACHINE_SOFT_PWM #define MICROPY_PY_MACHINE_SOFT_PWM (0) #endif #ifndef MICROPY_PY_MACHINE_TIMER #define MICROPY_PY_MACHINE_TIMER (0) #endif #ifndef MICROPY_PY_MACHINE_RTCOUNTER #define MICROPY_PY_MACHINE_RTCOUNTER (0) #endif #ifndef MICROPY_PY_RANDOM_HW_RNG #define MICROPY_PY_RANDOM_HW_RNG (0) #endif #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) // if sdk is in use, import configuration #if BLUETOOTH_SD #include "bluetooth_conf.h" #endif #ifndef MICROPY_PY_UBLUEPY #define MICROPY_PY_UBLUEPY (0) #endif #ifndef MICROPY_PY_BLE_NUS #define MICROPY_PY_BLE_NUS (0) #endif // type definitions for the specific machine #define BYTES_PER_WORD (4) #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) #define MP_SSIZE_MAX (0x7fffffff) #define UINT_FMT "%u" #define INT_FMT "%d" #define HEX2_FMT "%02x" typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size typedef long mp_off_t; // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t board_module; extern const struct _mp_obj_module_t machine_module; extern const struct _mp_obj_module_t mp_module_utime; extern const struct _mp_obj_module_t mp_module_uos; extern const struct _mp_obj_module_t mp_module_ubluepy; extern const struct _mp_obj_module_t music_module; extern const struct _mp_obj_module_t random_module; #if MICROPY_PY_UBLUEPY #define UBLUEPY_MODULE { MP_ROM_QSTR(MP_QSTR_ubluepy), MP_ROM_PTR(&mp_module_ubluepy) }, #else #define UBLUEPY_MODULE #endif #if MICROPY_PY_MUSIC #define MUSIC_MODULE { MP_ROM_QSTR(MP_QSTR_music), MP_ROM_PTR(&music_module) }, #else #define MUSIC_MODULE #endif #if MICROPY_PY_RANDOM_HW_RNG #define RANDOM_MODULE { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&random_module) }, #else #define RANDOM_MODULE #endif #if BOARD_SPECIFIC_MODULES #include "boardmodules.h" #define MICROPY_BOARD_BUILTINS BOARD_MODULES #else #define MICROPY_BOARD_BUILTINS #endif // BOARD_SPECIFIC_MODULES #if BLUETOOTH_SD #if MICROPY_PY_BLE extern const struct _mp_obj_module_t ble_module; #define BLE_MODULE { MP_ROM_QSTR(MP_QSTR_ble), MP_ROM_PTR(&ble_module) }, #else #define BLE_MODULE #endif #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&board_module) }, \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_utime) }, \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ BLE_MODULE \ MUSIC_MODULE \ UBLUEPY_MODULE \ RANDOM_MODULE \ MICROPY_BOARD_BUILTINS \ #else extern const struct _mp_obj_module_t ble_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&board_module) }, \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ MUSIC_MODULE \ RANDOM_MODULE \ MICROPY_BOARD_BUILTINS \ #endif // BLUETOOTH_SD // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_help), MP_ROM_PTR(&mp_builtin_help_obj) }, \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, \ // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&board_module) }, \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&machine_module) }, \ BLE_MODULE \ #define MP_STATE_PORT MP_STATE_VM #if MICROPY_PY_MUSIC #define ROOT_POINTERS_MUSIC \ struct _music_data_t *music_data; #else #define ROOT_POINTERS_MUSIC #endif #if MICROPY_PY_MACHINE_SOFT_PWM #define ROOT_POINTERS_SOFTPWM \ const struct _pwm_events *pwm_active_events; \ const struct _pwm_events *pwm_pending_events; #else #define ROOT_POINTERS_SOFTPWM #endif #if defined(NRF52840_XXAA) #define NUM_OF_PINS 48 #else #define NUM_OF_PINS 32 #endif #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ mp_obj_t pin_class_mapper; \ mp_obj_t pin_class_map_dict; \ mp_obj_t pin_irq_handlers[NUM_OF_PINS]; \ \ /* stdio is repeated on this UART object if it's not null */ \ struct _machine_hard_uart_obj_t *board_stdio_uart; \ \ ROOT_POINTERS_MUSIC \ ROOT_POINTERS_SOFTPWM \ \ /* micro:bit root pointers */ \ void *async_data[2]; \ #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // We need to provide a declaration/definition of alloca() #include #define MICROPY_PIN_DEFS_PORT_H "pin_defs_nrf5.h" #endif micropython-1.12/ports/nrf/mphalport.c000066400000000000000000000151701357706137100201340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpstate.h" #include "py/mphal.h" #include "py/mperrno.h" #include "py/runtime.h" #include "py/stream.h" #include "uart.h" #include "nrfx_errors.h" #include "nrfx_config.h" // this table converts from HAL_StatusTypeDef to POSIX errno const byte mp_hal_status_to_errno_table[4] = { [HAL_OK] = 0, [HAL_ERROR] = MP_EIO, [HAL_BUSY] = MP_EBUSY, [HAL_TIMEOUT] = MP_ETIMEDOUT, }; NORETURN void mp_hal_raise(HAL_StatusTypeDef status) { mp_raise_OSError(mp_hal_status_to_errno_table[status]); } #if !MICROPY_KBD_EXCEPTION void mp_hal_set_interrupt_char(int c) { } #endif #if !MICROPY_PY_BLE_NUS uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if ((poll_flags & MP_STREAM_POLL_RD) && MP_STATE_PORT(board_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(board_stdio_uart))) { ret |= MP_STREAM_POLL_RD; } return ret; } #endif #if !MICROPY_PY_BLE_NUS && !MICROPY_HW_USB_CDC int mp_hal_stdin_rx_chr(void) { for (;;) { if (MP_STATE_PORT(board_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(board_stdio_uart))) { return uart_rx_char(MP_STATE_PORT(board_stdio_uart)); } __WFI(); } return 0; } void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { if (MP_STATE_PORT(board_stdio_uart) != NULL) { uart_tx_strn(MP_STATE_PORT(board_stdio_uart), str, len); } } void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { if (MP_STATE_PORT(board_stdio_uart) != NULL) { uart_tx_strn_cooked(MP_STATE_PORT(board_stdio_uart), str, len); } } #endif void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } void mp_hal_delay_us(mp_uint_t us) { if (us == 0) { return; } register uint32_t delay __ASM ("r0") = us; __ASM volatile ( #ifdef NRF51 ".syntax unified\n" #endif "1:\n" " SUBS %0, %0, #1\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" #if defined(NRF52) || defined(NRF9160_XXAA) " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" #endif " BNE 1b\n" : "+r" (delay)); } void mp_hal_delay_ms(mp_uint_t ms) { for (mp_uint_t i = 0; i < ms; i++) { mp_hal_delay_us(999); } } #if defined(NRFX_LOG_ENABLED) && (NRFX_LOG_ENABLED == 1) static const char nrfx_error_unknown[1] = ""; static const char nrfx_error_success[] = "NRFX_SUCCESS"; static const char nrfx_error_internal[] = "NRFX_ERROR_INTERNAL"; static const char nrfx_error_no_mem[] = "NRFX_ERROR_NO_MEM"; static const char nrfx_error_not_supported[] = "NRFX_ERROR_NOT_SUPPORTED"; static const char nrfx_error_invalid_param[] = "NRFX_ERROR_INVALID_PARAM"; static const char nrfx_error_invalid_state[] = "NRFX_ERROR_INVALID_STATE"; static const char nrfx_error_invalid_length[] = "NRFX_ERROR_INVALID_LENGTH"; static const char nrfx_error_timeout[] = "NRFX_ERROR_TIMEOUT"; static const char nrfx_error_forbidden[] = "NRFX_ERROR_FORBIDDEN"; static const char nrfx_error_null[] = "NRFX_ERROR_NULL"; static const char nrfx_error_invalid_addr[] = "NRFX_ERROR_INVALID_ADDR"; static const char nrfx_error_busy[] = "NRFX_ERROR_BUSY"; static const char nrfx_error_already_initalized[] = "NRFX_ERROR_ALREADY_INITIALIZED"; static const char * nrfx_error_strings[13] = { nrfx_error_success, nrfx_error_internal, nrfx_error_no_mem, nrfx_error_not_supported, nrfx_error_invalid_param, nrfx_error_invalid_state, nrfx_error_invalid_length, nrfx_error_timeout, nrfx_error_forbidden, nrfx_error_null, nrfx_error_invalid_addr, nrfx_error_busy, nrfx_error_already_initalized }; static const char nrfx_drv_error_twi_err_overrun[] = "NRFX_ERROR_DRV_TWI_ERR_OVERRUN"; static const char nrfx_drv_error_twi_err_anack[] = "NRFX_ERROR_DRV_TWI_ERR_ANACK"; static const char nrfx_drv_error_twi_err_dnack[] = "NRFX_ERROR_DRV_TWI_ERR_DNACK"; static const char * nrfx_drv_error_strings[3] = { nrfx_drv_error_twi_err_overrun, nrfx_drv_error_twi_err_anack, nrfx_drv_error_twi_err_dnack }; const char * nrfx_error_code_lookup(uint32_t err_code) { if (err_code >= NRFX_ERROR_BASE_NUM && err_code <= NRFX_ERROR_BASE_NUM + 13) { return nrfx_error_strings[err_code - NRFX_ERROR_BASE_NUM]; } else if (err_code >= NRFX_ERROR_DRIVERS_BASE_NUM && err_code <= NRFX_ERROR_DRIVERS_BASE_NUM + 3) { return nrfx_drv_error_strings[err_code - NRFX_ERROR_DRIVERS_BASE_NUM]; } return nrfx_error_unknown; } #endif // NRFX_LOG_ENABLED micropython-1.12/ports/nrf/mphalport.h000066400000000000000000000054371357706137100201460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __NRF52_HAL #define __NRF52_HAL #include "py/mpconfig.h" #include #include "pin.h" #include "nrf_gpio.h" #include "nrfx_config.h" typedef enum { HAL_OK = 0x00, HAL_ERROR = 0x01, HAL_BUSY = 0x02, HAL_TIMEOUT = 0x03 } HAL_StatusTypeDef; static inline uint32_t hal_tick_fake(void) { return 0; } #define mp_hal_ticks_ms hal_tick_fake // TODO: implement. Right now, return 0 always extern const unsigned char mp_hal_status_to_errno_table[4]; NORETURN void mp_hal_raise(HAL_StatusTypeDef status); void mp_hal_set_interrupt_char(int c); // -1 to disable int mp_hal_stdin_rx_chr(void); void mp_hal_stdout_tx_str(const char *str); void mp_hal_delay_ms(mp_uint_t ms); void mp_hal_delay_us(mp_uint_t us); const char * nrfx_error_code_lookup(uint32_t err_code); #define mp_hal_pin_obj_t const pin_obj_t* #define mp_hal_get_pin_obj(o) pin_find(o) #define mp_hal_pin_high(p) nrf_gpio_pin_set(p->pin) #define mp_hal_pin_low(p) nrf_gpio_pin_clear(p->pin) #define mp_hal_pin_read(p) (nrf_gpio_pin_dir_get(p->pin) == NRF_GPIO_PIN_DIR_OUTPUT) ? nrf_gpio_pin_out_read(p->pin) : nrf_gpio_pin_read(p->pin) #define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) #define mp_hal_pin_od_low(p) mp_hal_pin_low(p) #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_open_drain(p) nrf_gpio_cfg_input(p->pin, NRF_GPIO_PIN_NOPULL) // TODO: empty implementation for now. Used by machine_spi.c:69 #define mp_hal_delay_us_fast(p) #define mp_hal_ticks_us() (0) #define mp_hal_ticks_cpu() (0) #endif micropython-1.12/ports/nrf/nrf51_af.csv000066400000000000000000000004421357706137100200740ustar00rootroot00000000000000P0,P0 P1,P1,ADC0_IN2 P2,P2,ADC0_IN3 P3,P3,ADC0_IN4 P4,P4,ADC0_IN5 P5,P5,ADC0_IN6 P6,P6,ADC0_IN7 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/nrf52_af.csv000066400000000000000000000006641357706137100201030ustar00rootroot00000000000000P0,P0 P1,P1 P2,P2,ADC1_CH0 P3,P3,ADC1_CH1 P4,P4,ADC1_CH2 P5,P5,ADC1_CH3 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28,ADC1_CH4 P29,P29,ADC1_CH5 P30,P30,ADC1_CH6 P31,P31,ADC1_CH7 P32,P32 P33,P33 P34,P34 P35,P35 P36,P36 P37,P37 P38,P38 P39,P39 P40,P40 P41,P41 P42,P42 P43,P43 P44,P44 P45,P45 P46,P46 P47,P47 micropython-1.12/ports/nrf/nrf91_af.csv000066400000000000000000000003541357706137100201020ustar00rootroot00000000000000P0,P0 P1,P1 P2,P2 P3,P3 P4,P4 P5,P5 P6,P6 P7,P7 P8,P8 P9,P9 P10,P10 P11,P11 P12,P12 P13,P13 P14,P14 P15,P15 P16,P16 P17,P17 P18,P18 P19,P19 P20,P20 P21,P21 P22,P22 P23,P23 P24,P24 P25,P25 P26,P26 P27,P27 P28,P28 P29,P29 P30,P30 P31,P31 micropython-1.12/ports/nrf/nrfx_config.h000066400000000000000000000170721357706137100204400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Glenn Ruben Bakke * Copyright (c) 2018 Ayke van Laethem * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef NRFX_CONFIG_H #define NRFX_CONFIG_H #include "mpconfigport.h" #include "nrf.h" // Port specific defines #ifndef NRFX_LOG_ENABLED #define NRFX_LOG_ENABLED 0 #endif #define NRFX_LOG_UART_DISABLED 1 // NRFX configurations #if NRF51 || NRF52832 #define GPIO_COUNT 1 #elif NRF52840 || NRF52840_XXAA #define GPIO_COUNT 2 #elif NRF9160_XXAA #define GPIO_COUNT 1 #endif #if defined(NRF52840) // for tinyusb //#define NRFX_IRQ_IS_ENABLED 1 #define NRFX_POWER_ENABLED 1 #define NRFX_POWER_CONFIG_IRQ_PRIORITY 2 #define NRFX_SYSTICK_ENABLED 1 #endif #define NRFX_GPIOTE_ENABLED 1 #define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1 #if NRF51 #define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 3 #else #define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 6 #endif #if defined(NRF51) || defined(NRF52_SERIES) #define NRFX_UART_ENABLED 1 #define NRFX_UART0_ENABLED 1 #define NRFX_UART1_ENABLED 1 #else #define NRFX_UARTE_ENABLED 1 #define NRFX_UARTE0_ENABLED 1 #define NRFX_UARTE1_ENABLED 1 #define NRFX_UARTE2_ENABLED 1 #define NRFX_UARTE3_ENABLED 1 #endif #if defined(NRF51) || defined(NRF52_SERIES) #define NRFX_TWI_ENABLED (MICROPY_PY_MACHINE_I2C) #define NRFX_TWI0_ENABLED 1 #define NRFX_TWI1_ENABLED 1 #elif defined(NRF9160_XXAA) #define NRFX_TWIM_ENABLED (MICROPY_PY_MACHINE_I2C) #define NRFX_TWIM0_ENABLED 1 #define NRFX_TWIM1_ENABLED 1 #endif #if defined(NRF51) || defined(NRF52832) #define NRFX_SPI_ENABLED (MICROPY_PY_MACHINE_HW_SPI) #define NRFX_SPI0_ENABLED 1 #define NRFX_SPI1_ENABLED 1 #if defined(NRF52832) #define NRFX_SPI2_ENABLED 1 #endif #elif defined(NRF52840) #define NRFX_SPIM_ENABLED (MICROPY_PY_MACHINE_HW_SPI) #define NRFX_SPIM0_ENABLED 1 #define NRFX_SPIM1_ENABLED 1 #define NRFX_SPIM2_ENABLED 1 #define NRFX_SPIM3_ENABLED (NRF52840) #elif defined(NRF9160_XXAA) #define NRFX_SPIM_ENABLED (MICROPY_PY_MACHINE_HW_SPI) #define NRFX_SPIM0_ENABLED 1 #define NRFX_SPIM1_ENABLED 1 // 0 NRF_GPIO_PIN_NOPULL // 1 NRF_GPIO_PIN_PULLDOWN // 3 NRF_GPIO_PIN_PULLUP #define NRFX_SPIM_MISO_PULL_CFG 1 #endif // NRF51 // 0 NRF_GPIO_PIN_NOPULL // 1 NRF_GPIO_PIN_PULLDOWN // 3 NRF_GPIO_PIN_PULLUP #define NRFX_SPI_MISO_PULL_CFG 1 #define NRFX_SPIM_MISO_PULL_CFG 1 #define NRFX_RTC_ENABLED (MICROPY_PY_MACHINE_RTCOUNTER) #define NRFX_RTC0_ENABLED 1 #define NRFX_RTC1_ENABLED 1 #define NRFX_RTC2_ENABLED (!NRF51) #define NRFX_TIMER_ENABLED (MICROPY_PY_MACHINE_TIMER) #define NRFX_TIMER0_ENABLED 1 #define NRFX_TIMER1_ENABLED (!MICROPY_PY_MACHINE_SOFT_PWM) #define NRFX_TIMER2_ENABLED 1 #define NRFX_TIMER3_ENABLED (!NRF51) && (!NRF9160_XXAA) #define NRFX_TIMER4_ENABLED (!NRF51) && (!NRF9160_XXAA) #define NRFX_PWM_ENABLED (!NRF51) && MICROPY_PY_MACHINE_HW_PWM #define NRFX_PWM0_ENABLED 1 #define NRFX_PWM1_ENABLED 1 #define NRFX_PWM2_ENABLED 1 #define NRFX_PWM3_ENABLED (NRF52840) #define NRFX_NVMC_ENABLED 1 // Peripheral Resource Sharing #if defined(NRF51) || defined(NRF52832) #define NRFX_PRS_BOX_0_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI0_ENABLED && NRFX_SPI_ENABLED && NRFX_SPI0_ENABLED) #define NRFX_PRS_BOX_1_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI1_ENABLED && NRFX_SPI_ENABLED && NRFX_SPI1_ENABLED) #if defined(NRF52832) #define NRFX_PRS_BOX_2_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI1_ENABLED && NRFX_SPI_ENABLED && NRFX_SPI1_ENABLED) #endif #elif defined(NRF52840) #define NRFX_PRS_BOX_0_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI0_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM0_ENABLED) #define NRFX_PRS_BOX_1_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI1_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM1_ENABLED) #define NRFX_PRS_BOX_2_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI2_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM2_ENABLED) #elif defined(NRF9160_XXAA) #define NRFX_PRS_BOX_0_ENABLED (NRFX_TWIM_ENABLED && NRFX_TWIM0_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM0_ENABLED) #define NRFX_PRS_BOX_1_ENABLED (NRFX_TWIM_ENABLED && NRFX_TWIM1_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM1_ENABLED) #define NRFX_PRS_BOX_2_ENABLED (NRFX_TWIM_ENABLED && NRFX_TWIM2_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM2_ENABLED) #endif #define NRFX_PRS_ENABLED (NRFX_PRS_BOX_0_ENABLED || NRFX_PRS_BOX_1_ENABLED || NRFX_PRS_BOX_2_ENABLED) #define NRFX_SAADC_ENABLED !(NRF51) && (MICROPY_PY_MACHINE_ADC) #define NRFX_ADC_ENABLED (NRF51) && (MICROPY_PY_MACHINE_ADC) #if defined(NRF9160_XXAA) #define NRF_CLOCK NRF_CLOCK_NS #define NRF_DPPIC NRF_DPPIC_NS #define NRF_EGU0 NRF_EGU0_NS #define NRF_EGU1 NRF_EGU1_NS #define NRF_EGU2 NRF_EGU2_NS #define NRF_EGU3 NRF_EGU3_NS #define NRF_EGU4 NRF_EGU4_NS #define NRF_EGU5 NRF_EGU5_NS #define NRF_FPU NRF_FPU_NS #define NRF_P0 NRF_P0_NS #define NRF_I2S NRF_I2S_NS #define NRF_KMU NRF_KMU_NS #define NRF_NVMC NRF_NVMC_NS #define NRF_PDM NRF_PDM_NS #define NRF_POWER NRF_POWER_NS #define NRF_PWM0 NRF_PWM0_NS #define NRF_PWM1 NRF_PWM1_NS #define NRF_PWM2 NRF_PWM2_NS #define NRF_PWM3 NRF_PWM3_NS #define NRF_REGULATORS NRF_REGULATORS_NS #define NRF_RTC0 NRF_RTC0_NS #define NRF_RTC1 NRF_RTC1_NS #define NRF_SAADC NRF_SAADC_NS #define NRF_SPIM0 NRF_SPIM0_NS #define NRF_SPIM1 NRF_SPIM1_NS #define NRF_SPIM2 NRF_SPIM2_NS #define NRF_SPIM3 NRF_SPIM3_NS #define NRF_SPIS0 NRF_SPIS0_NS #define NRF_SPIS1 NRF_SPIS1_NS #define NRF_SPIS2 NRF_SPIS2_NS #define NRF_SPIS3 NRF_SPIS3_NS #define NRF_TIMER0 NRF_TIMER0_NS #define NRF_TIMER1 NRF_TIMER1_NS #define NRF_TIMER2 NRF_TIMER2_NS #define NRF_TWIM0 NRF_TWIM0_NS #define NRF_TWIM1 NRF_TWIM1_NS #define NRF_TWIM2 NRF_TWIM2_NS #define NRF_TWIM3 NRF_TWIM3_NS #define NRF_TWIS0 NRF_TWIS0_NS #define NRF_TWIS1 NRF_TWIS1_NS #define NRF_TWIS2 NRF_TWIS2_NS #define NRF_TWIS3 NRF_TWIS3_NS #define NRF_UARTE0 NRF_UARTE0_NS #define NRF_UARTE1 NRF_UARTE1_NS #define NRF_UARTE2 NRF_UARTE2_NS #define NRF_UARTE3 NRF_UARTE3_NS #define NRF_VMC NRF_VMC_NS #define NRF_WDT NRF_WDT_NS #define NRF_IPC NRF_IPC_NS #define NRF_CRYPTOCELL NRF_CRYPTOCELL_S #define NRF_FICR NRF_FICR_S #define NRF_GPIOTE0 NRF_GPIOTE0_S #define NRF_GPIOTE1 NRF_GPIOTE1_NS #define NRF_SPU NRF_SPU_S #define NRF_UICR NRF_UICR_S #define NRF_GPIOTE NRF_GPIOTE1_NS #define GPIOTE_IRQn GPIOTE1_IRQn #define GPIOTE_IRQHandler GPIOTE1_IRQHandler #endif #endif // NRFX_CONFIG_H micropython-1.12/ports/nrf/nrfx_glue.h000066400000000000000000000107171357706137100201260ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef NRFX_GLUE_H #define NRFX_GLUE_H #include #define NRFX_STATIC_ASSERT(expression) #define NRFX_ASSERT(expression) do { bool res = expression; (void)res; } while (0) #define NRFX_DELAY_US mp_hal_delay_us #if BLUETOOTH_SD #if NRF51 #include "nrf_soc.h" #else #include "nrf_nvic.h" #endif #include "ble_drv.h" #if (BLUETOOTH_SD == 110) #define NRFX_IRQ_ENABLE(irq_number) \ do { \ if (ble_drv_stack_enabled() == 1) \ { \ sd_nvic_EnableIRQ(irq_number); \ } else { \ NVIC_EnableIRQ(irq_number); \ } \ } while(0) #else #define NRFX_IRQ_ENABLE(irq_number) sd_nvic_EnableIRQ(irq_number) #endif #if (BLUETOOTH_SD == 110) #define NRFX_IRQ_DISABLE(irq_number) \ do { \ if (ble_drv_stack_enabled() == 1) \ { \ sd_nvic_DisableIRQ(irq_number); \ } else { \ NVIC_DisableIRQ(irq_number); \ } \ } while(0) #else #define NRFX_IRQ_DISABLE(irq_number) sd_nvic_DisableIRQ(irq_number) #endif #if (BLUETOOTH_SD == 110) #define NRFX_IRQ_PRIORITY_SET(irq_number, priority) \ do { \ if (ble_drv_stack_enabled() == 1) \ { \ sd_nvic_SetPriority(irq_number, priority); \ } else { \ NVIC_SetPriority(irq_number, priority); \ } \ } while(0) #else #define NRFX_IRQ_PRIORITY_SET(irq_number, priority) sd_nvic_SetPriority(irq_number, priority) #endif #if (BLUETOOTH_SD == 110) #define NRFX_IRQ_PENDING_SET(irq_number) \ do { \ if (ble_drv_stack_enabled() == 1) \ { \ sd_nvic_SetPendingIRQ(irq_number); \ } else { \ NVIC_SetPendingIRQ(irq_number); \ } \ } while(0) #else #define NRFX_IRQ_PENDING_SET(irq_number) sd_nvic_SetPendingIRQ(irq_number) #endif #if (BLUETOOTH_SD == 110) #define NRFX_IRQ_PENDING_CLEAR(irq_number) \ do { \ if (ble_drv_stack_enabled() == 1) \ { \ sd_nvic_ClearPendingIRQ(irq_number); \ } else { \ NVIC_ClearPendingIRQ(irq_number)(irq_number); \ } \ } while(0) #else #define NRFX_IRQ_PENDING_CLEAR(irq_number) sd_nvic_ClearPendingIRQ(irq_number) #endif #define NRFX_CRITICAL_SECTION_ENTER() \ { \ uint8_t _is_nested_critical_region; \ sd_nvic_critical_region_enter(&_is_nested_critical_region); #define NRFX_CRITICAL_SECTION_EXIT() \ sd_nvic_critical_region_exit(_is_nested_critical_region); \ } #else // BLUETOOTH_SD #define NRFX_IRQ_ENABLE(irq_number) NVIC_EnableIRQ(irq_number) #define NRFX_IRQ_DISABLE(irq_number) NVIC_DisableIRQ(irq_number) #define NRFX_IRQ_PRIORITY_SET(irq_number, priority) NVIC_SetPriority(irq_number, priority) #define NRFX_IRQ_PENDING_SET(irq_number) NVIC_SetPendingIRQ(irq_number) #define NRFX_IRQ_PENDING_CLEAR(irq_number) NVIC_ClearPendingIRQ(irq_number) // Source: // https://devzone.nordicsemi.com/f/nordic-q-a/8572/disable-interrupts-and-enable-interrupts-if-they-where-enabled/31347#31347 #define NRFX_CRITICAL_SECTION_ENTER() { int _old_primask = __get_PRIMASK(); __disable_irq(); #define NRFX_CRITICAL_SECTION_EXIT() __set_PRIMASK(_old_primask); } #endif // !BLUETOOTH_SD #define NRFX_IRQ_IS_ENABLED(irq_number) (0 != (NVIC->ISER[irq_number / 32] & (1UL << (irq_number % 32)))) #endif // NRFX_GLUE_H micropython-1.12/ports/nrf/nrfx_log.h000066400000000000000000000054451357706137100177550ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef NRFX_LOG_H #define NRFX_LOG_H #include #include "mphalport.h" #include "nrfx_config.h" #define LOG_TEST_UART 1 #define TEST_MODULE_IMPL(x, y) LOG_TEST_ ## x == LOG_TEST_ ## y #define TEST_MODULE(x, y) TEST_MODULE_IMPL(x, y) #if (!defined(NRFX_LOG_ENABLED) || (NRFX_LOG_ENABLED == 0)) || \ (TEST_MODULE(NRFX_LOG_MODULE, UART) && defined(NRFX_LOG_UART_DISABLED) && NRFX_LOG_UART_DISABLED) #define NRFX_LOG_DEBUG(fmt, ...) #define NRFX_LOG_ERROR(fmt, ...) #define NRFX_LOG_WARNING(fmt, ...) #define NRFX_LOG_INFO(fmt, ...) #define NRFX_LOG_HEXDUMP_ERROR(p_memory, length) #define NRFX_LOG_HEXDUMP_WARNING(p_memory, length) #define NRFX_LOG_HEXDUMP_INFO(p_memory, length) #define NRFX_LOG_HEXDUMP_DEBUG(p_memory, length) #define NRFX_LOG_ERROR_STRING_GET(error_code) "" #else #define VALUE_TO_STR(x) #x #define VALUE(x) VALUE_TO_STR(x) #define LOG_PRINTF(fmt, ...) \ do { \ printf("%s: ", VALUE(NRFX_LOG_MODULE)); \ printf(fmt, ##__VA_ARGS__); \ printf("\n"); \ } while (0) #define NRFX_LOG_DEBUG LOG_PRINTF #define NRFX_LOG_ERROR LOG_PRINTF #define NRFX_LOG_WARNING LOG_PRINTF #define NRFX_LOG_INFO LOG_PRINTF #define NRFX_LOG_HEXDUMP_ERROR(p_memory, length) #define NRFX_LOG_HEXDUMP_WARNING(p_memory, length) #define NRFX_LOG_HEXDUMP_INFO(p_memory, length) #define NRFX_LOG_HEXDUMP_DEBUG(p_memory, length) #define NRFX_LOG_ERROR_STRING_GET(error_code) \ nrfx_error_code_lookup(error_code) #endif // NRFX_LOG_ENABLED #endif // NRFX_LOG_H micropython-1.12/ports/nrf/pin_defs_nrf5.h000066400000000000000000000037611357706137100206570ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // This file contains pin definitions that are specific to the nrf port. // This file should only ever be #included by pin.h and not directly. #include "nrf_gpio.h" enum { PORT_A, PORT_B, }; enum { AF_FN_UART, AF_FN_SPI, }; enum { AF_PIN_TYPE_UART_TX = 0, AF_PIN_TYPE_UART_RX, AF_PIN_TYPE_UART_CTS, AF_PIN_TYPE_UART_RTS, AF_PIN_TYPE_SPI_MOSI = 0, AF_PIN_TYPE_SPI_MISO, AF_PIN_TYPE_SPI_SCK, AF_PIN_TYPE_SPI_NSS, }; #if defined(NRF51) || defined(NRF52_SERIES) #define PIN_DEFS_PORT_AF_UNION \ NRF_UART_Type *UART; // NRF_SPI_Type *SPIM; // NRF_SPIS_Type *SPIS; #elif defined(NRF91_SERIES) #define PIN_DEFS_PORT_AF_UNION \ NRF_UARTE_Type *UART; #endif enum { PIN_ADC1 = (1 << 0), }; typedef NRF_GPIO_Type pin_gpio_t; micropython-1.12/ports/nrf/pin_named_pins.c000066400000000000000000000060701357706137100211100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "pin.h" STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pin_named_pins_obj_t *self = self_in; mp_printf(print, "", self->name); } const mp_obj_type_t pin_cpu_pins_obj_type = { { &mp_type_type }, .name = MP_QSTR_cpu, .print = pin_named_pins_obj_print, .locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict, }; const mp_obj_type_t pin_board_pins_obj_type = { { &mp_type_type }, .name = MP_QSTR_board, .print = pin_named_pins_obj_print, .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict, }; const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins); mp_map_elem_t *named_elem = mp_map_lookup(named_map, name, MP_MAP_LOOKUP); if (named_elem != NULL && named_elem->value != NULL) { return named_elem->value; } return NULL; } const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit) { const pin_af_obj_t *af = pin->af; for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { if (af->fn == fn && af->unit == unit) { return af; } } return NULL; } const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx) { const pin_af_obj_t *af = pin->af; for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { if (af->idx == af_idx) { return af; } } return NULL; } /* unused const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name) { const pin_af_obj_t *af = pin->af; for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { if (strcmp(name, qstr_str(af->name)) == 0) { return af; } } return NULL; } */ micropython-1.12/ports/nrf/qstrdefsport.h000066400000000000000000000037761357706137100207040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // qstrs specific to this port Q(a) Q(a#) Q(a#:1) Q(a#:3) Q(a2) Q(a4) Q(a4:1) Q(a4:3) Q(a:1) Q(a:2) Q(a:4) Q(a:5) Q(b) Q(b2:1) Q(b3) Q(b4) Q(b4:1) Q(b4:2) Q(b5) Q(b5:1) Q(b:1) Q(b:2) Q(c) Q(c#) Q(c#5) Q(c#5:1) Q(c#5:2) Q(c#:1) Q(c#:8) Q(c2:2) Q(c3) Q(c3:3) Q(c3:4) Q(c4) Q(c4:1) Q(c4:3) Q(c4:4) Q(c5) Q(c5:1) Q(c5:2) Q(c5:3) Q(c5:4) Q(c:1) Q(c:2) Q(c:3) Q(c:4) Q(c:8) Q(d) Q(d#) Q(d#5:2) Q(d#:2) Q(d#:3) Q(d3) Q(d4) Q(d4:1) Q(d5) Q(d5:1) Q(d5:2) Q(d:1) Q(d:2) Q(d:3) Q(d:4) Q(d:5) Q(d:6) Q(d:8) Q(e) Q(e3:3) Q(e4) Q(e4:1) Q(e5) Q(e6:3) Q(e:1) Q(e:2) Q(e:3) Q(e:4) Q(e:5) Q(e:6) Q(e:8) Q(eb:8) Q(f) Q(f#) Q(f#5) Q(f#5:2) Q(f#:1) Q(f#:2) Q(f#:8) Q(f2) Q(f:1) Q(f:2) Q(f:3) Q(f:4) Q(f:8) Q(g) Q(g#) Q(g#:1) Q(g#:3) Q(g3:1) Q(g4) Q(g4:1) Q(g4:2) Q(g5) Q(g5:1) Q(g:1) Q(g:2) Q(g:3) Q(g:8) Q(r) Q(r4:2) Q(r:1) Q(r:2) Q(r:3) micropython-1.12/ports/pic16bit/000077500000000000000000000000001357706137100166125ustar00rootroot00000000000000micropython-1.12/ports/pic16bit/Makefile000066400000000000000000000030201357706137100202450ustar00rootroot00000000000000include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk XC16 = /opt/microchip/xc16/v1.35 CROSS_COMPILE = $(XC16)/bin/xc16- PARTFAMILY = dsPIC33F PART = 33FJ256GP506 INC += -I. INC += -I$(TOP) INC += -I$(BUILD) INC += -I$(XC16)/include INC += -I$(XC16)/support/$(PARTFAMILY)/h CFLAGS_PIC16BIT = -mcpu=$(PART) -mlarge-code CFLAGS = $(INC) -Wall -Werror -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT) #Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -O0 -ggdb else CFLAGS += -O1 -DNDEBUG endif LDFLAGS = --heap=0 -nostdlib -T $(XC16)/support/$(PARTFAMILY)/gld/p$(PART).gld -Map=$@.map --cref -p$(PART) LIBS = -L$(XC16)/lib -L$(XC16)/lib/$(PARTFAMILY) -lc -lm -lpic30 SRC_C = \ main.c \ board.c \ pic16bit_mphal.c \ modpyb.c \ modpybled.c \ modpybswitch.c \ lib/utils/pyexec.c \ lib/utils/sys_stdio_mphal.c \ lib/mp-readline/readline.c \ SRC_S = \ # gchelper.s \ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o)) # List of sources for qstr extraction SRC_QSTR += $(SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += all: $(BUILD)/firmware.hex $(BUILD)/firmware.hex: $(BUILD)/firmware.elf $(ECHO) "Create $@" $(Q)$(CROSS_COMPILE)bin2hex $< $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)size $@ $(PY_BUILD)/gc.o: CFLAGS += -O1 $(PY_BUILD)/vm.o: CFLAGS += -O1 include $(TOP)/py/mkrules.mk micropython-1.12/ports/pic16bit/board.c000066400000000000000000000075761357706137100200640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "board.h" /********************************************************************/ // CPU void cpu_init(void) { // set oscillator to operate at 40MHz // Fosc = Fin*M/(N1*N2), Fcy = Fosc/2 // Fosc = 7.37M*40/(2*2) = 80Mhz for 7.37M input clock PLLFBD = 41; // M=39 CLKDIVbits.PLLPOST = 0; // N1=2 CLKDIVbits.PLLPRE = 0; // N2=2 OSCTUN = 0; // initiate clock switch to FRC with PLL __builtin_write_OSCCONH(0x01); __builtin_write_OSCCONL(0x01); // wait for clock switch to occur while (OSCCONbits.COSC != 0x01) { } while (!OSCCONbits.LOCK) { } } /********************************************************************/ // LEDs #define RED_LED_TRIS _TRISC15 #define YELLOW_LED_TRIS _TRISC13 #define GREEN_LED_TRIS _TRISC14 #define RED_LED _LATC15 #define YELLOW_LED _LATC13 #define GREEN_LED _LATC14 #define LED_ON (0) #define LED_OFF (1) void led_init(void) { // set led GPIO as outputs RED_LED_TRIS = 0; YELLOW_LED_TRIS = 0; GREEN_LED_TRIS = 0; // turn off the LEDs RED_LED = LED_OFF; YELLOW_LED = LED_OFF; GREEN_LED = LED_OFF; } void led_state(int led, int state) { int val = state ? LED_ON : LED_OFF; switch (led) { case 1: RED_LED = val; break; case 2: YELLOW_LED = val; break; case 3: GREEN_LED = val; break; } } void led_toggle(int led) { switch (led) { case 1: RED_LED ^= 1; break; case 2: YELLOW_LED ^= 1; break; case 3: GREEN_LED ^= 1; break; } } /********************************************************************/ // switches #define SWITCH_S1_TRIS _TRISD8 #define SWITCH_S2_TRIS _TRISD9 #define SWITCH_S1 _RD8 #define SWITCH_S2 _RD9 void switch_init(void) { // set switch GPIO as inputs SWITCH_S1_TRIS = 1; SWITCH_S2_TRIS = 1; } int switch_get(int sw) { int val = 1; switch (sw) { case 1: val = SWITCH_S1; break; case 2: val = SWITCH_S2; break; } return val == 0; } /********************************************************************/ // UART /* // TODO need an irq void uart_rx_irq(void) { if (c == interrupt_char) { MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(keyboard_interrupt_obj); } } */ void uart_init(void) { // baudrate = F_CY / 16 (uxbrg + 1) // F_CY = 40MHz for us UART1.uxbrg = 64; // 38400 baud UART1.uxmode = 1 << 15; // UARTEN UART1.uxsta = 1 << 10; // UTXEN } int uart_rx_any(void) { return UART1.uxsta & 1; // URXDA } int uart_rx_char(void) { return UART1.uxrxreg; } void uart_tx_char(int chr) { while (UART1.uxsta & (1 << 9)) { // tx fifo is full } UART1.uxtxreg = chr; } micropython-1.12/ports/pic16bit/board.h000066400000000000000000000031071357706137100200530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PIC16BIT_BOARD_H #define MICROPY_INCLUDED_PIC16BIT_BOARD_H void cpu_init(void); void led_init(void); void led_state(int led, int state); void led_toggle(int led); void switch_init(void); int switch_get(int sw); void uart_init(void); int uart_rx_any(void); int uart_rx_char(void); void uart_tx_char(int chr); #endif // MICROPY_INCLUDED_PIC16BIT_BOARD_H micropython-1.12/ports/pic16bit/main.c000066400000000000000000000071131357706137100177040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/compile.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" #include "py/mperrno.h" #include "lib/utils/pyexec.h" #include "lib/mp-readline/readline.h" #include "board.h" #include "modpyb.h" #pragma config GWRP = OFF #pragma config GSS = GCP_OFF #pragma config FNOSC = FRC #pragma config FCKSM = CSECMD #pragma config OSCIOFNC = ON #pragma config POSCMD = NONE #pragma config FWDTEN = OFF // maximum heap for device with 8k RAM static char heap[4600]; int main(int argc, char **argv) { // init the CPU and the peripherals cpu_init(); led_init(); switch_init(); uart_init(); soft_reset: // flash green led for 150ms to indicate boot led_state(1, 0); led_state(2, 0); led_state(3, 1); mp_hal_delay_ms(150); led_state(3, 0); // init MicroPython runtime int stack_dummy; MP_STATE_THREAD(stack_top) = (char*)&stack_dummy; gc_init(heap, heap + sizeof(heap)); mp_init(); mp_hal_init(); readline_init0(); // REPL loop for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } printf("MPY: soft reboot\n"); mp_deinit(); goto soft_reset; } void gc_collect(void) { // TODO possibly need to trace registers void *dummy; gc_collect_start(); // Node: stack is ascending gc_collect_root(&dummy, ((mp_uint_t)&dummy - (mp_uint_t)MP_STATE_THREAD(stack_top)) / sizeof(mp_uint_t)); gc_collect_end(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { while (1); } void NORETURN __fatal_error(const char *msg) { while (1); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error("Assertion failed"); } #endif micropython-1.12/ports/pic16bit/modpyb.c000066400000000000000000000051461357706137100202560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" #include "py/mphal.h" #include "modpyb.h" STATIC mp_obj_t pyb_millis(void) { return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis); STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) { uint32_t startMillis = mp_obj_get_int(start); uint32_t currMillis = mp_hal_ticks_ms(); return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x1fff); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis); STATIC mp_obj_t pyb_delay(mp_obj_t ms_in) { mp_int_t ms = mp_obj_get_int(ms_in); if (ms >= 0) { mp_hal_delay_ms(ms); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_delay_obj, pyb_delay); STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) }, { MP_ROM_QSTR(MP_QSTR_millis), MP_ROM_PTR(&pyb_millis_obj) }, { MP_ROM_QSTR(MP_QSTR_elapsed_millis), MP_ROM_PTR(&pyb_elapsed_millis_obj) }, { MP_ROM_QSTR(MP_QSTR_delay), MP_ROM_PTR(&pyb_delay_obj) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pyb_led_type) }, { MP_ROM_QSTR(MP_QSTR_Switch), MP_ROM_PTR(&pyb_switch_type) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table); const mp_obj_module_t pyb_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&pyb_module_globals, }; micropython-1.12/ports/pic16bit/modpyb.h000066400000000000000000000027141357706137100202610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PIC16BIT_MODPYB_H #define MICROPY_INCLUDED_PIC16BIT_MODPYB_H extern const mp_obj_type_t pyb_led_type; extern const mp_obj_type_t pyb_switch_type; extern const mp_obj_module_t pyb_module; #endif // MICROPY_INCLUDED_PIC16BIT_MODPYB_H micropython-1.12/ports/pic16bit/modpybled.c000066400000000000000000000063571357706137100207500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "board.h" #include "modpyb.h" typedef struct _pyb_led_obj_t { mp_obj_base_t base; } pyb_led_obj_t; STATIC const pyb_led_obj_t pyb_led_obj[] = { {{&pyb_led_type}}, {{&pyb_led_type}}, {{&pyb_led_type}}, }; #define NUM_LED MP_ARRAY_SIZE(pyb_led_obj) #define LED_ID(obj) ((obj) - &pyb_led_obj[0] + 1) void pyb_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_led_obj_t *self = self_in; mp_printf(print, "LED(%u)", LED_ID(self)); } STATIC mp_obj_t pyb_led_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_int_t led_id = mp_obj_get_int(args[0]); if (!(1 <= led_id && led_id <= NUM_LED)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "LED %d does not exist", led_id)); } return (mp_obj_t)&pyb_led_obj[led_id - 1]; } mp_obj_t pyb_led_on(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_state(LED_ID(self), 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_led_on_obj, pyb_led_on); mp_obj_t pyb_led_off(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_state(LED_ID(self), 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_led_off_obj, pyb_led_off); mp_obj_t pyb_led_toggle(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_toggle(LED_ID(self)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_led_toggle_obj, pyb_led_toggle); STATIC const mp_rom_map_elem_t pyb_led_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&pyb_led_on_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&pyb_led_off_obj) }, { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&pyb_led_toggle_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_led_locals_dict, pyb_led_locals_dict_table); const mp_obj_type_t pyb_led_type = { { &mp_type_type }, .name = MP_QSTR_LED, .print = pyb_led_print, .make_new = pyb_led_make_new, .locals_dict = (mp_obj_t)&pyb_led_locals_dict, }; micropython-1.12/ports/pic16bit/modpybswitch.c000066400000000000000000000060051357706137100214730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "board.h" #include "modpyb.h" typedef struct _pyb_switch_obj_t { mp_obj_base_t base; } pyb_switch_obj_t; STATIC const pyb_switch_obj_t pyb_switch_obj[] = { {{&pyb_switch_type}}, {{&pyb_switch_type}}, }; #define NUM_SWITCH MP_ARRAY_SIZE(pyb_switch_obj) #define SWITCH_ID(obj) ((obj) - &pyb_switch_obj[0] + 1) void pyb_switch_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_switch_obj_t *self = self_in; mp_printf(print, "Switch(%u)", SWITCH_ID(self)); } STATIC mp_obj_t pyb_switch_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_int_t sw_id = mp_obj_get_int(args[0]); if (!(1 <= sw_id && sw_id <= NUM_SWITCH)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Switch %d does not exist", sw_id)); } return (mp_obj_t)&pyb_switch_obj[sw_id - 1]; } mp_obj_t pyb_switch_value(mp_obj_t self_in) { pyb_switch_obj_t *self = self_in; return switch_get(SWITCH_ID(self)) ? mp_const_true : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_switch_value_obj, pyb_switch_value); mp_obj_t pyb_switch_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 0, false); return pyb_switch_value(self_in); } STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&pyb_switch_value_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table); const mp_obj_type_t pyb_switch_type = { { &mp_type_type }, .name = MP_QSTR_Switch, .print = pyb_switch_print, .make_new = pyb_switch_make_new, .call = pyb_switch_call, .locals_dict = (mp_obj_t)&pyb_switch_locals_dict, }; micropython-1.12/ports/pic16bit/mpconfigport.h000066400000000000000000000103201357706137100214660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include // options to control how MicroPython is built #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_B) #define MICROPY_ALLOC_PATH_MAX (64) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (0) #define MICROPY_COMP_CONST (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_ENABLE_GC (1) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_BUILTINS_BYTEARRAY (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_SLICE (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS (0) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_NO_ALLOCA (1) // type definitions for the specific machine #define MP_ENDIANNESS_LITTLE (1) #define MPZ_DIG_SIZE (8) // The xc16 compiler doesn't seem to respect alignment (!!) so we // need to use instead an object representation that allows for // 2-byte aligned pointers (see config setting above). //#define MICROPY_OBJ_BASE_ALIGNMENT __attribute__((aligned(4))) #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p))) #define UINT_FMT "%u" #define INT_FMT "%d" typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size typedef int mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // extra builtin names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, // extra builtin modules to add to the list of known ones extern const struct _mp_obj_module_t pyb_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_pyb), MP_ROM_PTR(&pyb_module) }, \ #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ char *readline_hist[8]; \ mp_obj_t keyboard_interrupt_obj; \ #define MICROPY_MPHALPORT_H "pic16bit_mphal.h" #define MICROPY_HW_BOARD_NAME "dsPICSK" #define MICROPY_HW_MCU_NAME "dsPIC33" // XC16 toolchain doesn't seem to define these typedef int intptr_t; typedef unsigned int uintptr_t; micropython-1.12/ports/pic16bit/pic16bit_mphal.c000066400000000000000000000047231357706137100215660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/stream.h" #include "py/mphal.h" #include "board.h" static int interrupt_char; void mp_hal_init(void) { MP_STATE_PORT(keyboard_interrupt_obj) = mp_obj_new_exception(&mp_type_KeyboardInterrupt); } mp_uint_t mp_hal_ticks_ms(void) { // TODO return 0; } void mp_hal_delay_ms(mp_uint_t ms) { // tuned for fixed CPU frequency for (int i = ms; i > 0; i--) { for (volatile int j = 0; j < 5000; j++) { } } } void mp_hal_set_interrupt_char(int c) { interrupt_char = c; } uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if ((poll_flags & MP_STREAM_POLL_RD) && uart_rx_any()) { ret |= MP_STREAM_POLL_RD; } return ret; } int mp_hal_stdin_rx_chr(void) { for (;;) { if (uart_rx_any()) { return uart_rx_char(); } } } void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } void mp_hal_stdout_tx_strn(const char *str, size_t len) { for (; len > 0; --len) { uart_tx_char(*str++); } } void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { for (; len > 0; --len) { if (*str == '\n') { uart_tx_char('\r'); } uart_tx_char(*str++); } } micropython-1.12/ports/pic16bit/pic16bit_mphal.h000066400000000000000000000024431357706137100215700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" void mp_hal_init(void); void mp_hal_set_interrupt_char(int c); micropython-1.12/ports/pic16bit/qstrdefsport.h000066400000000000000000000000371357706137100215230ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/pic16bit/unistd.h000066400000000000000000000003661357706137100202760ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_PIC16BIT_UNISTD_H #define MICROPY_INCLUDED_PIC16BIT_UNISTD_H // XC16 compiler doesn't seem to have unistd.h file #define SEEK_SET 0 #define SEEK_CUR 1 typedef int ssize_t; #endif // MICROPY_INCLUDED_PIC16BIT_UNISTD_H micropython-1.12/ports/powerpc/000077500000000000000000000000001357706137100166505ustar00rootroot00000000000000micropython-1.12/ports/powerpc/Makefile000066400000000000000000000031001357706137100203020ustar00rootroot00000000000000include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk ARCH = $(shell uname -m) ifneq ("$(ARCH)", "ppc64") ifneq ("$(ARCH)", "ppc64le") CROSS_COMPILE = powerpc64le-linux- endif endif INC += -I. INC += -I$(TOP) INC += -I$(BUILD) CFLAGS = $(INC) -g -Wall -std=c99 $(COPT) CFLAGS += -mno-string -mno-multiple -mno-vsx -mno-altivec -nostdlib CFLAGS += -mlittle-endian -mstrict-align -msoft-float CFLAGS += -Os CFLAGS += -fdata-sections -ffunction-sections -fno-stack-protector -ffreestanding CFLAGS += -U_FORTIFY_SOURCE LDFLAGS = -N -T powerpc.lds -nostdlib LIBS = SRC_C = \ main.c \ uart_core.c \ uart_potato.c \ uart_lpc_serial.c \ lib/utils/printf.c \ lib/utils/stdout_helpers.c \ lib/utils/pyexec.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ $(BUILD)/_frozen_mpy.c \ OBJ = $(PY_CORE_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(BUILD)/head.o all: $(BUILD)/firmware.elf $(BUILD)/firmware.map $(BUILD)/firmware.bin $(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h $(ECHO) "MISC freezing bytecode" $(Q)$(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=mpz $< > $@ $(BUILD)/firmware.elf: $(OBJ) powerpc.lds $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(Q)$(OBJCOPY) -O binary $^ $(BUILD)/firmware.bin $(BUILD)/firmware.map: $(BUILD)/firmware.elf $(Q)nm $^ | sort > $(BUILD)/firmware.map include $(TOP)/py/mkrules.mk micropython-1.12/ports/powerpc/README.md000066400000000000000000000021411357706137100201250ustar00rootroot00000000000000# The PowerPC port that runs on microwatt and qemu This port is intended to be a minimal MicroPython port that runs in QEMU, microwatt simulator with ghdl or microwatt on Xilinx FPGA with potato UART. ## Building By default the port will be built for the host machine: $ make ## Cross compilation for POWERPC If you need to cross compilers you'll want to grab a powerpc64le compiler (not powerpc or powerpc64). On Ubuntu (18.04) you'll want: $ apt install gcc-powerpc64le-linux-gnu *(Use CROSS_COMPILE=powerpc64le-linux-gnu-)* If your distro doesn't have cross compilers, you can get cross compilers here: - https://toolchains.bootlin.com/ *(use CROSS_COMPILE=powerpc64le-buildroot-linux-gnu-)* (Avoid musl libc as it defines __assert_fail() differently to glibc which breaks the micropython powerpc code) Then do: $ make CROSS_COMPILE= Building will produce the build/firmware.bin file which can be used QEMU or [microwatt](https://github.com/antonblanchard/microwatt). To run in QEMU use: $ ./qemu-system-ppc64 -M powernv -cpu POWER9 -nographic -bios build/firmware.bin micropython-1.12/ports/powerpc/frozentest.mpy000066400000000000000000000003041357706137100215770ustar00rootroot00000000000000M Tfrozentest.py)(((+({uPy4Y{#4Y{#4Y{#4Y{"4YBWi{4YWCYQcs"a long string that is not interneds&a string that has unicode αβγ charsb bytes 1234micropython-1.12/ports/powerpc/frozentest.py000066400000000000000000000002631357706137100214260ustar00rootroot00000000000000print('uPy') print('a long string that is not interned') print('a string that has unicode αβγ chars') print(b'bytes 1234\x01') print(123456789) for i in range(4): print(i) micropython-1.12/ports/powerpc/head.S000066400000000000000000000072711357706137100177040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define STACK_TOP 0x60000 #define FIXUP_ENDIAN \ tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ b 191f; /* Skip trampoline if endian is good */ \ .long 0xa600607d; /* mfmsr r11 */ \ .long 0x01006b69; /* xori r11,r11,1 */ \ .long 0x05009f42; /* bcl 20,31,$+4 */ \ .long 0xa602487d; /* mflr r10 */ \ .long 0x14004a39; /* addi r10,r10,20 */ \ .long 0xa64b5a7d; /* mthsrr0 r10 */ \ .long 0xa64b7b7d; /* mthsrr1 r11 */ \ .long 0x2402004c; /* hrfid */ \ 191: /* Load an immediate 64-bit value into a register */ #define LOAD_IMM64(r, e) \ lis r,(e)@highest; \ ori r,r,(e)@higher; \ rldicr r,r, 32, 31; \ oris r,r, (e)@h; \ ori r,r, (e)@l; .section ".head","ax" /* * Microwatt comes in at 0 as little endian so we do not need to worry up * FIXUP_ENDIAN. */ . = 0 .global _start _start: b boot_entry /* QEMU comes in at 0x10. Put a value in argc/r3 to distingush from * microwatt. */ . = 0x10 FIXUP_ENDIAN LOAD_IMM64(%r3, 1) b boot_entry .global boot_entry boot_entry: /* Save R3 to non-volatile register */ mr %r14, %r3 restart: /* * setup stack with a safety gap, since we might write to the * previous frame. */ LOAD_IMM64(%r1, STACK_TOP - 0x100) LOAD_IMM64(%r12, main) mtctr %r12 bctrl /* On exit, restart */ mr %r3, %r14 b restart #define EXCEPTION(nr) \ .= nr; \ b . /* More exception stubs */ EXCEPTION(0x300) EXCEPTION(0x380) EXCEPTION(0x400) EXCEPTION(0x480) EXCEPTION(0x500) EXCEPTION(0x600) EXCEPTION(0x700) EXCEPTION(0x800) EXCEPTION(0x900) EXCEPTION(0x980) EXCEPTION(0xa00) EXCEPTION(0xb00) EXCEPTION(0xc00) EXCEPTION(0xd00) EXCEPTION(0xe00) EXCEPTION(0xe20) EXCEPTION(0xe40) EXCEPTION(0xe60) EXCEPTION(0xe80) EXCEPTION(0xf00) EXCEPTION(0xf20) EXCEPTION(0xf40) EXCEPTION(0xf60) EXCEPTION(0xf80) EXCEPTION(0x1000) EXCEPTION(0x1100) EXCEPTION(0x1200) EXCEPTION(0x1300) EXCEPTION(0x1400) EXCEPTION(0x1500) EXCEPTION(0x1600) micropython-1.12/ports/powerpc/main.c000066400000000000000000000076101357706137100177440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" #include "py/gc.h" #include "py/mperrno.h" #include "py/stackctrl.h" #include "lib/utils/pyexec.h" void __stack_chk_fail(void); void __stack_chk_fail(void) { static bool failed_once; if (failed_once) { return; } failed_once = true; printf("Stack corruption detected !\n"); assert(0); } /* fill in __assert_fail for libc */ void __assert_fail(const char *__assertion, const char *__file, unsigned int __line, const char *__function) { printf("Assert at %s:%d:%s() \"%s\" failed\n", __file, __line, __function, __assertion); for (;;) ; } static char *stack_top; #if MICROPY_ENABLE_GC static char heap[32 * 1024]; #endif extern void uart_init_ppc(int qemu); int main(int argc, char **argv) { int stack_dummy; stack_top = (char*)&stack_dummy; // microwatt has argc/r3 = 0 whereas QEMU has r3 set in head.S uart_init_ppc(argc); #if MICROPY_ENABLE_PYSTACK static mp_obj_t pystack[1024]; mp_pystack_init(pystack, &pystack[1024]); #endif #if MICROPY_STACK_CHECK mp_stack_ctrl_init(); mp_stack_set_limit(48 * 1024); #endif #if MICROPY_ENABLE_GC gc_init(heap, heap + sizeof(heap)); #endif mp_init(); #if MICROPY_ENABLE_COMPILER #if MICROPY_REPL_EVENT_DRIVEN pyexec_event_repl_init(); for (;;) { int c = mp_hal_stdin_rx_chr(); if (pyexec_event_repl_process_char(c)) { break; } } #else pyexec_friendly_repl(); #endif #else pyexec_frozen_module("frozentest.py"); #endif mp_deinit(); return 0; } void gc_collect(void) { // WARNING: This gc_collect implementation doesn't try to get root // pointers from CPU registers, and thus may function incorrectly. void *dummy; gc_collect_start(); gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); gc_collect_end(); gc_dump_info(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { while (1); } void NORETURN __fatal_error(const char *msg) { while (1); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error("Assertion failed"); } #endif micropython-1.12/ports/powerpc/mpconfigport.h000066400000000000000000000114321357706137100215310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include // options to control how MicroPython is built // You can disable the built-in MicroPython compiler by setting the following // config option to 0. If you do this then you won't get a REPL prompt, but you // will still be able to execute pre-compiled scripts, compiled with mpy-cross. #define MICROPY_ENABLE_COMPILER (1) //#define MICROPY_DEBUG_VERBOSE (1) #define MICROPY_QSTR_BYTES_IN_HASH (1) #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool #define MICROPY_ALLOC_PATH_MAX (256) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (0) #define MICROPY_COMP_CONST (0) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_GC_ALLOC_THRESHOLD (0) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #define MICROPY_PY_BUILTINS_DICT_FROMKEYS (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_REVERSED (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY_BUILTINS_STR_COUNT (1) #define MICROPY_PY_BUILTINS_STR_OP_MODULO (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_STRUCT (1) #define MICROPY_PY_SYS (1) #define MICROPY_MODULE_FROZEN_MPY (1) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_ENABLE_PYSTACK (1) #define MICROPY_USE_INTERNAL_PRINTF (1) // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) // This port is 64-bit #define UINT_FMT "%lu" #define INT_FMT "%ld" typedef signed long mp_int_t; // must be pointer size typedef unsigned long mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, #define MICROPY_HW_BOARD_NAME "bare-metal" #define MICROPY_HW_MCU_NAME "POWERPC" #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; // powerpc64 gcc doesn't seem to define these // These are pointers, so make them 64 bit types typedef long intptr_t; typedef unsigned long uintptr_t; micropython-1.12/ports/powerpc/mphalport.h000066400000000000000000000032341357706137100210310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define mftb() ({unsigned long rval; \ __asm__ volatile("mftb %0" : "=r" (rval)); rval;}) #define TBFREQ 512000000 static inline mp_uint_t mp_hal_ticks_ms(void) { unsigned long tb = mftb(); return tb * 1000 / TBFREQ; } static inline mp_uint_t mp_hal_ticks_us(void) { unsigned long tb = mftb(); return tb * 1000000 / TBFREQ; } static inline void mp_hal_set_interrupt_char(char c) { } micropython-1.12/ports/powerpc/powerpc.lds000066400000000000000000000003531357706137100210340ustar00rootroot00000000000000SECTIONS { . = 0; _start = .; .head : { KEEP(*(.head)) } /* Put this at 0x1700 which is right after our execption * vectors in head.S. */ . = 0x1700; } micropython-1.12/ports/powerpc/qstrdefsport.h000066400000000000000000000000371357706137100215610ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/powerpc/uart_core.c000066400000000000000000000042021357706137100207750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpconfig.h" #include "uart_potato.h" #include "uart_lpc_serial.h" static int lpc_console; static int potato_console; void uart_init_ppc(int lpc) { lpc_console = lpc; if (!lpc_console) { potato_console = 1; potato_uart_init(); } else { lpc_uart_init(); } } // Receive single character int mp_hal_stdin_rx_chr(void) { unsigned char c = 0; if (lpc_console) { c = lpc_uart_read(); } else if (potato_console) { c = potato_uart_read(); } return c; } // Send string of given length void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { if (lpc_console) { int i; for (i = 0; i < len; i++) { lpc_uart_write(str[i]); } } else if (potato_console) { int i; for (i = 0; i < len; i++) { potato_uart_write(str[i]); } } } micropython-1.12/ports/powerpc/uart_lpc_serial.c000066400000000000000000000062571357706137100221760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * This is the LPC serial UART used by POWER9 boxes. This is modelled * in the qemu POWER9 machine. */ #include #include #include "py/mpconfig.h" #define PROC_FREQ 50000000 #define UART_FREQ 115200 #define UART_BASE 0xc0002000 #define LPC_UART_BASE 0x60300d00103f8 /* Taken from skiboot */ #define REG_RBR 0 #define REG_THR 0 #define REG_DLL 0 #define REG_IER 1 #define REG_DLM 1 #define REG_FCR 2 #define REG_IIR 2 #define REG_LCR 3 #define REG_MCR 4 #define REG_LSR 5 #define REG_MSR 6 #define REG_SCR 7 #define LSR_DR 0x01 /* Data ready */ #define LSR_OE 0x02 /* Overrun */ #define LSR_PE 0x04 /* Parity error */ #define LSR_FE 0x08 /* Framing error */ #define LSR_BI 0x10 /* Break */ #define LSR_THRE 0x20 /* Xmit holding register empty */ #define LSR_TEMT 0x40 /* Xmitter empty */ #define LSR_ERR 0x80 /* Error */ #define LCR_DLAB 0x80 /* DLL access */ #define IER_RX 0x01 #define IER_THRE 0x02 #define IER_ALL 0x0f static uint64_t lpc_uart_base; static void lpc_uart_reg_write(uint64_t offset, uint8_t val) { uint64_t addr; addr = lpc_uart_base + offset; *(volatile uint8_t *)addr = val; } static uint8_t lpc_uart_reg_read(uint64_t offset) { uint64_t addr; uint8_t val; addr = lpc_uart_base + offset; val = *(volatile uint8_t *)addr; return val; } static int lpc_uart_tx_full(void) { return !(lpc_uart_reg_read(REG_LSR) & LSR_THRE); } static int lpc_uart_rx_empty(void) { return !(lpc_uart_reg_read(REG_LSR) & LSR_DR); } void lpc_uart_init(void) { lpc_uart_base = LPC_UART_BASE; } char lpc_uart_read(void) { while (lpc_uart_rx_empty()) ; return lpc_uart_reg_read(REG_THR); } void lpc_uart_write(char c) { while (lpc_uart_tx_full()); lpc_uart_reg_write(REG_RBR, c); } micropython-1.12/ports/powerpc/uart_lpc_serial.h000066400000000000000000000024551357706137100221770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ void lpc_uart_init(void); char lpc_uart_read(void); void lpc_uart_write(char c); micropython-1.12/ports/powerpc/uart_potato.c000066400000000000000000000066431357706137100213660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * This is a driver for the potato UART used by the microwatt core. * The original potato UART came from here * https://github.com/skordal/potato */ #include #include #include "py/mpconfig.h" #define PROC_FREQ 50000000 #define UART_FREQ 115200 #define POTATO_UART_BASE 0xc0002000 uint64_t potato_uart_base; #define POTATO_CONSOLE_TX 0x00 #define POTATO_CONSOLE_RX 0x08 #define POTATO_CONSOLE_STATUS 0x10 #define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01 #define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02 #define POTATO_CONSOLE_STATUS_RX_FULL 0x04 #define POTATO_CONSOLE_STATUS_TX_FULL 0x08 #define POTATO_CONSOLE_CLOCK_DIV 0x18 #define POTATO_CONSOLE_IRQ_EN 0x20 static uint64_t potato_uart_reg_read(int offset) { uint64_t addr; uint64_t val; addr = potato_uart_base + offset; val = *(volatile uint64_t *)addr; return val; } void potato_uart_reg_write(int offset, uint64_t val) { uint64_t addr; addr = potato_uart_base + offset; *(volatile uint64_t *)addr = val; } static int potato_uart_rx_empty(void) { uint64_t val; val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); if (val & POTATO_CONSOLE_STATUS_RX_EMPTY) { return 1; } return 0; } static int potato_uart_tx_full(void) { uint64_t val; val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); if (val & POTATO_CONSOLE_STATUS_TX_FULL) { return 1; } return 0; } static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq) { return proc_freq / (uart_freq * 16) - 1; } void potato_uart_init(void) { potato_uart_base = POTATO_UART_BASE; potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ)); } char potato_uart_read(void) { uint64_t val; while (potato_uart_rx_empty()); val = potato_uart_reg_read(POTATO_CONSOLE_RX); return (char)(val & 0x000000ff); } void potato_uart_write(char c) { uint64_t val; val = c; while (potato_uart_tx_full()); potato_uart_reg_write(POTATO_CONSOLE_TX, val); } micropython-1.12/ports/powerpc/uart_potato.h000066400000000000000000000024661357706137100213720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ void potato_uart_init(void); char potato_uart_read(void); void potato_uart_write(char c); micropython-1.12/ports/powerpc/unistd.h000066400000000000000000000027251357706137100203350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_POWERPC_UNISTD_H #define MICROPY_INCLUDED_POWERPC_UNISTD_H // powerpc gcc compiler doesn't seem to have unistd.h file #define SEEK_SET 0 #define SEEK_CUR 1 typedef int ssize_t; #endif // MICROPY_INCLUDED_POWERPC_UNISTD_H micropython-1.12/ports/qemu-arm/000077500000000000000000000000001357706137100167155ustar00rootroot00000000000000micropython-1.12/ports/qemu-arm/Makefile000066400000000000000000000067001357706137100203600ustar00rootroot00000000000000include ../../py/mkenv.mk -include mpconfigport.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk BOARD ?= netduino2 ifeq ($(BOARD),netduino2) CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_STM32 LDSCRIPT = stm32.ld SRC_BOARD_O = lib/utils/gchelper_m3.o endif ifeq ($(BOARD),microbit) CFLAGS += -mthumb -mcpu=cortex-m0 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_NRF51 LDSCRIPT = nrf51.ld QEMU_EXTRA = -global nrf51-soc.flash-size=1048576 -global nrf51-soc.sram-size=262144 SRC_BOARD_O = lib/utils/gchelper_m0.o endif ifeq ($(BOARD),mps2-an385) CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_MPS2 LDSCRIPT = mps2.ld SRC_BOARD_O = lib/utils/gchelper_m3.o endif CROSS_COMPILE ?= arm-none-eabi- INC += -I. INC += -I$(TOP) INC += -I$(BUILD) CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 $(COPT) \ -ffunction-sections -fdata-sections #Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -g -DPENDSV_DEBUG COPT = -O0 else COPT += -Os -DNDEBUG endif ## With CoudeSourcery it's actually a little different, you just need `-T generic-m-hosted.ld`. ## Although for some reason `$(LD)` will not find that linker script, it works with `$(CC)`. ## It turns out that this is specific to CoudeSourcery, and ARM version of GCC ships something ## else instead and according to the following files, this is what we need to pass to `$(CC). ## - gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/src/makefile.conf ## - gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/src/qemu/Makefile LDFLAGS= -T $(LDSCRIPT) --gc-sections -Map=$(@:.elf=.map) LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) SRC_COMMON_C = \ startup.c \ uart.c \ moduos.c \ modmachine.c \ SRC_RUN_C = \ main.c \ SRC_TEST_C = \ test_main.c \ lib/tinytest/tinytest.c \ LIB_SRC_C += $(addprefix lib/,\ libc/string0.c \ libm/math.c \ libm/fmodf.c \ libm/nearbyintf.c \ libm/ef_sqrt.c \ libm/kf_rem_pio2.c \ libm/kf_sin.c \ libm/kf_cos.c \ libm/kf_tan.c \ libm/ef_rem_pio2.c \ libm/sf_sin.c \ libm/sf_cos.c \ libm/sf_tan.c \ libm/sf_frexp.c \ libm/sf_modf.c \ libm/sf_ldexp.c \ libm/asinfacosf.c \ libm/atanf.c \ libm/atan2f.c \ utils/sys_stdio_mphal.c \ ) OBJ_COMMON = OBJ_COMMON += $(PY_O) OBJ_COMMON += $(addprefix $(BUILD)/, $(SRC_COMMON_C:.c=.o)) OBJ_COMMON += $(addprefix $(BUILD)/, $(SRC_BOARD_O)) OBJ_COMMON += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ_RUN = OBJ_RUN += $(addprefix $(BUILD)/, $(SRC_RUN_C:.c=.o)) ALL_OBJ_RUN = $(OBJ_COMMON) $(OBJ_RUN) OBJ_TEST = OBJ_TEST += $(addprefix $(BUILD)/, $(SRC_TEST_C:.c=.o)) ALL_OBJ_TEST = $(OBJ_COMMON) $(OBJ_TEST) # All object files, needed to get dependencies correct OBJ = $(OBJ_COMMON) $(OBJ_RUN) $(OBJ_TEST) # List of sources for qstr extraction SRC_QSTR += $(SRC_COMMON_C) $(SRC_RUN_C) $(LIB_SRC_C) ifneq ($(FROZEN_MANIFEST),) CFLAGS += -DMICROPY_MODULE_FROZEN_STR CFLAGS += -DMICROPY_MODULE_FROZEN_MPY CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool MPY_CROSS_FLAGS += -march=armv7m endif all: run run: $(BUILD)/firmware.elf qemu-system-arm -machine $(BOARD) $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< ## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here. $(BUILD)/firmware.elf: $(LDSCRIPT) $(ALL_OBJ_RUN) $(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_RUN) $(LIBS) $(Q)$(SIZE) $@ include $(TOP)/py/mkrules.mk micropython-1.12/ports/qemu-arm/Makefile.test000066400000000000000000000016511357706137100213360ustar00rootroot00000000000000LIB_SRC_C = lib/upytesthelper/upytesthelper.c FROZEN_MANIFEST ?= "freeze('test-frzmpy')" include Makefile CFLAGS += -DTEST .PHONY: $(BUILD)/genhdr/tests.h $(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h $(BUILD)/genhdr/tests.h: (cd $(TOP)/tests; ./run-tests --target=qemu-arm --write-exp) $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py) > $@ $(BUILD)/lib/tinytest/tinytest.o: CFLAGS += -DNO_FORKING $(BUILD)/firmware-test.elf: $(LDSCRIPT) $(ALL_OBJ_TEST) $(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_TEST) $(LIBS) $(Q)$(SIZE) $@ # Note: Using timeout(1) to handle cases where qemu hangs (e.g. this can happen with alignment errors). test: $(BUILD)/firmware-test.elf timeout --foreground -k 5s 30s qemu-system-arm -machine $(BOARD) $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< > $(BUILD)/console.out $(Q)tail -n2 $(BUILD)/console.out $(Q)tail -n1 $(BUILD)/console.out | grep -q "status: 0" micropython-1.12/ports/qemu-arm/README.md000066400000000000000000000021671357706137100202020ustar00rootroot00000000000000This is experimental, community-supported port for Cortex-M emulation as provided by QEMU (http://qemu.org). The purposes of this port are to enable: 1. Continuous integration - run tests against architecture-specific parts of code base 2. Experimentation - simulation & prototyping of anything that has architecture-specific code - exploring instruction set in terms of optimising some part of MicroPython or a module 3. Streamlined debugging - no need for JTAG or even an MCU chip itself - no need to use OpenOCD or anything else that might slow down the process in terms of plugging things together, pressing buttons, etc. This port will only work with with [GCC ARM Embedded](launchpad.net/gcc-arm-embedded) toolchain and not with CodeSourcery toolchain. You will need to modify `LDFLAGS` if you want to use CodeSourcery's version of `arm-none-eabi`. The difference is that CodeSourcery needs `-T generic-m-hosted.ld` while ARM's version requires `--specs=nano.specs --specs=rdimon.specs` to be passed to the linker. To build and run image with builtin testsuite: make -f Makefile.test test micropython-1.12/ports/qemu-arm/main.c000066400000000000000000000030561357706137100200110ustar00rootroot00000000000000#include #include #include #include #include #include "py/obj.h" #include "py/compile.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" #include "py/repl.h" #include "py/mperrno.h" void do_str(const char *src, mp_parse_input_kind_t input_kind) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } } int main(int argc, char **argv) { mp_stack_ctrl_init(); mp_stack_set_limit(10240); uint32_t heap[16*1024 / 4]; gc_init(heap, (char*)heap + 16 * 1024); mp_init(); do_str("print('hello world!')", MP_PARSE_SINGLE_INPUT); mp_deinit(); return 0; } void gc_collect(void) { } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { printf("uncaught NLR\n"); exit(1); } micropython-1.12/ports/qemu-arm/modmachine.c000066400000000000000000000037661357706137100212010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "extmod/machine_mem.h" #include "extmod/machine_pinbase.h" #include "extmod/machine_signal.h" STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t mp_module_machine = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; micropython-1.12/ports/qemu-arm/moduos.c000066400000000000000000000046061357706137100203750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "extmod/vfs.h" STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, // MicroPython extensions { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, }; STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); const mp_obj_module_t mp_module_uos = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&os_module_globals, }; micropython-1.12/ports/qemu-arm/mpconfigport.h000066400000000000000000000051571357706137100216050ustar00rootroot00000000000000#include // options to control how MicroPython is built #define MICROPY_ALLOC_PATH_MAX (512) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (1) #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) #define MICROPY_MEM_STATS (1) #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_ENABLE_GC (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_HELPER_REPL (0) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_WARNINGS (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_IO (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_USE_INTERNAL_PRINTF (1) #define MICROPY_VFS (1) // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) #define MP_SSIZE_MAX (0x7fffffff) #define UINT_FMT "%lu" #define INT_FMT "%ld" typedef int32_t mp_int_t; // must be pointer size typedef uint32_t mp_uint_t; // must be pointer size typedef long mp_off_t; // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, // extra built-in modules to add to the list of known ones extern const struct _mp_obj_module_t mp_module_uos; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ // We need to provide a declaration/definition of alloca() #include #ifdef TEST #include "lib/upytesthelper/upytesthelper.h" #undef MP_PLAT_PRINT_STRN #define MP_PLAT_PRINT_STRN(str, len) upytest_output(str, len) #endif micropython-1.12/ports/qemu-arm/mphalport.h000066400000000000000000000002131357706137100210700ustar00rootroot00000000000000#include #include "uart.h" #define mp_hal_stdin_rx_chr() (0) #define mp_hal_stdout_tx_strn_cooked(s, l) uart_tx_strn((s), (l)) micropython-1.12/ports/qemu-arm/mps2.ld000066400000000000000000000011061357706137100201150ustar00rootroot00000000000000MEMORY { RAM : ORIGIN = 0x00000000, LENGTH = 4M } _estack = ORIGIN(RAM) + LENGTH(RAM); SECTIONS { .text : { . = ALIGN(4); KEEP(*(.isr_vector)) *(.text*) *(.rodata*) . = ALIGN(4); _etext = .; _sidata = _etext; } > RAM .data : AT ( _sidata ) { . = ALIGN(4); _sdata = .; *(.data*) . = ALIGN(4); _edata = .; } >RAM .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM } micropython-1.12/ports/qemu-arm/nrf51.ld000066400000000000000000000011631357706137100201720ustar00rootroot00000000000000MEMORY { ROM : ORIGIN = 0x00000000, LENGTH = 1M RAM : ORIGIN = 0x20000000, LENGTH = 256K } _estack = ORIGIN(RAM) + LENGTH(RAM); SECTIONS { .text : { . = ALIGN(4); KEEP(*(.isr_vector)) *(.text*) *(.rodata*) . = ALIGN(4); _etext = .; _sidata = _etext; } > ROM .data : AT ( _sidata ) { . = ALIGN(4); _sdata = .; *(.data*) . = ALIGN(4); _edata = .; } >RAM .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM } micropython-1.12/ports/qemu-arm/qstrdefsport.h000066400000000000000000000000371357706137100216260ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/qemu-arm/startup.c000066400000000000000000000037621357706137100205730ustar00rootroot00000000000000#include #include #include "uart.h" extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; __attribute__((naked)) void Reset_Handler(void) { // set stack pointer __asm volatile ("ldr r0, =_estack"); __asm volatile ("mov sp, r0"); // copy .data section from flash to RAM for (uint32_t *src = &_sidata, *dest = &_sdata; dest < &_edata;) { *dest++ = *src++; } // zero out .bss section for (uint32_t *dest = &_sbss; dest < &_ebss;) { *dest++ = 0; } // jump to board initialisation void _start(void); _start(); } void Default_Handler(void) { for (;;) { } } const uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = { (uint32_t)&_estack, (uint32_t)&Reset_Handler, (uint32_t)&Default_Handler, // NMI_Handler (uint32_t)&Default_Handler, // HardFault_Handler (uint32_t)&Default_Handler, // MemManage_Handler (uint32_t)&Default_Handler, // BusFault_Handler (uint32_t)&Default_Handler, // UsageFault_Handler 0, 0, 0, 0, (uint32_t)&Default_Handler, // SVC_Handler (uint32_t)&Default_Handler, // DebugMon_Handler 0, (uint32_t)&Default_Handler, // PendSV_Handler (uint32_t)&Default_Handler, // SysTick_Handler }; void _start(void) { // Enable the UART uart_init(); // Now that we have a basic system up and running we can call main extern int main(); main(0, 0); // Finished exit(0); } __attribute__((naked)) void exit(int status) { // Force qemu to exit using ARM Semihosting __asm volatile ( "mov r1, r0\n" "cmp r1, #0\n" "bne .notclean\n" "ldr r1, =0x20026\n" // ADP_Stopped_ApplicationExit, a clean exit ".notclean:\n" "movs r0, #0x18\n" // SYS_EXIT "bkpt 0xab\n" ); for (;;) { } } // The following are needed for tinytest #include int setvbuf(FILE *stream, char *buf, int mode, size_t size) { return 0; } struct _reent *_impure_ptr; micropython-1.12/ports/qemu-arm/stm32.ld000066400000000000000000000011631357706137100202070ustar00rootroot00000000000000MEMORY { ROM : ORIGIN = 0x00000000, LENGTH = 1M RAM : ORIGIN = 0x20000000, LENGTH = 128K } _estack = ORIGIN(RAM) + LENGTH(RAM); SECTIONS { .text : { . = ALIGN(4); KEEP(*(.isr_vector)) *(.text*) *(.rodata*) . = ALIGN(4); _etext = .; _sidata = _etext; } > ROM .data : AT ( _sidata ) { . = ALIGN(4); _sdata = .; *(.data*) . = ALIGN(4); _edata = .; } >RAM .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM } micropython-1.12/ports/qemu-arm/test-frzmpy/000077500000000000000000000000001357706137100212215ustar00rootroot00000000000000micropython-1.12/ports/qemu-arm/test-frzmpy/native_frozen_align.py000066400000000000000000000002701357706137100256150ustar00rootroot00000000000000import micropython @micropython.native def native_x(x): print(x + 1) @micropython.native def native_y(x): print(x + 1) @micropython.native def native_z(x): print(x + 1) micropython-1.12/ports/qemu-arm/test_main.c000066400000000000000000000027731357706137100210550ustar00rootroot00000000000000#include #include #include #include #include #include #include "py/obj.h" #include "py/compile.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" #include "py/mperrno.h" #include "lib/utils/gchelper.h" #include "lib/tinytest/tinytest.h" #include "lib/tinytest/tinytest_macros.h" #define HEAP_SIZE (100 * 1024) #include "genhdr/tests.h" int main() { mp_stack_ctrl_init(); mp_stack_set_limit(10240); static uint32_t heap[HEAP_SIZE / sizeof(uint32_t)]; upytest_set_heap(heap, (char*)heap + HEAP_SIZE); int r = tinytest_main(0, NULL, groups); printf("status: %d\n", r); return r; } void gc_collect(void) { gc_collect_start(); // get the registers and the sp uintptr_t regs[10]; uintptr_t sp = gc_helper_get_regs_and_sp(regs); // trace the stack, including the registers (since they live on the stack in this function) gc_collect_root((void**)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - (uint32_t)sp) / sizeof(uint32_t)); gc_collect_end(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { printf("uncaught NLR\n"); exit(1); } micropython-1.12/ports/qemu-arm/uart.c000066400000000000000000000030341357706137100200340ustar00rootroot00000000000000#include #include #include "uart.h" #if defined(QEMU_SOC_STM32) typedef struct _UART_t { volatile uint32_t SR; volatile uint32_t DR; } UART_t; #define UART0 ((UART_t*)(0x40011000)) void uart_init(void) { } void uart_tx_strn(const char *buf, size_t len) { for (size_t i = 0; i < len; ++i) { UART0->DR = buf[i]; } } #elif defined(QEMU_SOC_NRF51) typedef struct _UART_t { volatile uint32_t r0[2]; volatile uint32_t STARTTX; // 0x008 volatile uint32_t r1[(0x500 - 0x008) / 4 - 1]; volatile uint32_t ENABLE; // 0x500 volatile uint32_t r2[(0x51c - 0x500) / 4 - 1]; volatile uint32_t TXD; // 0x51c } UART_t; #define UART0 ((UART_t*)(0x40002000)) void uart_init(void) { UART0->ENABLE = 4; UART0->STARTTX = 1; } void uart_tx_strn(const char *buf, size_t len) { for (size_t i = 0; i < len; ++i) { UART0->TXD = buf[i]; } } #elif defined(QEMU_SOC_MPS2) #define UART_STATE_TXFULL (1 << 0) #define UART_CTRL_TX_EN (1 << 0) #define UART_CTRL_RX_EN (1 << 1) typedef struct _UART_t { volatile uint32_t DATA; volatile uint32_t STATE; volatile uint32_t CTRL; volatile uint32_t INTSTATUS; volatile uint32_t BAUDDIV; } UART_t; #define UART0 ((UART_t*)(0x40004000)) void uart_init(void) { UART0->BAUDDIV = 16; UART0->CTRL = UART_CTRL_TX_EN; } void uart_tx_strn(const char *buf, size_t len) { for (size_t i = 0; i < len; ++i) { while (UART0->STATE & UART_STATE_TXFULL) { } UART0->DATA = buf[i]; } } #endif micropython-1.12/ports/qemu-arm/uart.h000066400000000000000000000001061357706137100200360ustar00rootroot00000000000000void uart_init(void); void uart_tx_strn(const char *buf, size_t len); micropython-1.12/ports/samd/000077500000000000000000000000001357706137100161155ustar00rootroot00000000000000micropython-1.12/ports/samd/Makefile000066400000000000000000000055031357706137100175600ustar00rootroot00000000000000BOARD ?= ADAFRUIT_ITSYBITSY_M4_EXPRESS BOARD_DIR ?= boards/$(BOARD) BUILD ?= build-$(BOARD) CROSS_COMPILE ?= arm-none-eabi- UF2CONV ?= $(TOP)/tools/uf2conv.py ifeq ($(wildcard $(BOARD_DIR)/.),) $(error Invalid BOARD specified: $(BOARD_DIR)) endif include ../../py/mkenv.mk include $(BOARD_DIR)/mpconfigboard.mk # Qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h # Include py core make definitions include $(TOP)/py/py.mk GIT_SUBMODULES = lib/asf4 lib/tinyusb INC += -I. INC += -I$(TOP) INC += -I$(BUILD) INC += -I$(BOARD_DIR) INC += -I$(TOP)/lib/cmsis/inc INC += -I$(TOP)/lib/asf4/$(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]')/include INC += -I$(TOP)/lib/tinyusb/src CFLAGS_MCU_SAMD21 = -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ LDFLAGS = -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Tune for Debugging or Optimization ifeq ($(DEBUG),1) CFLAGS += -O0 -ggdb else CFLAGS += -Os -DNDEBUG LDFLAGS += --gc-sections CFLAGS += -fdata-sections -ffunction-sections endif SRC_C = \ main.c \ modutime.c \ modmachine.c \ mphalport.c \ samd_isr.c \ samd_soc.c \ tusb_port.c \ lib/libc/string0.c \ lib/libm/ef_sqrt.c \ lib/libm/fmodf.c \ lib/libm/math.c \ lib/libm/nearbyintf.c \ lib/mp-readline/readline.c \ lib/tinyusb/src/class/cdc/cdc_device.c \ lib/tinyusb/src/common/tusb_fifo.c \ lib/tinyusb/src/device/usbd.c \ lib/tinyusb/src/device/usbd_control.c \ lib/tinyusb/src/tusb.c \ lib/utils/printf.c \ lib/utils/pyexec.c \ lib/utils/stdout_helpers.c \ ifeq ($(MCU_SERIES),SAMD21) SRC_C += lib/tinyusb/src/portable/microchip/samd21/dcd_samd21.c SRC_S = lib/utils/gchelper_m0.s else SRC_C += lib/tinyusb/src/portable/microchip/samd51/dcd_samd51.c SRC_S = lib/utils/gchelper_m3.s endif # List of sources for qstr extraction SRC_QSTR += modutime.c modmachine.c OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) # Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };" $(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces all: $(BUILD)/firmware.uf2 $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data $^ $(BUILD)/firmware.bin $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(Q)$(PYTHON) $(UF2CONV) -b $(TEXT0) -c -o $@ $< include $(TOP)/py/mkrules.mk micropython-1.12/ports/samd/README.md000066400000000000000000000002221357706137100173700ustar00rootroot00000000000000Port of MicroPython to Microchip SAMD MCUs ========================================== Supports SAMD21 and SAMD51. Features: - REPL over USB VCP micropython-1.12/ports/samd/boards/000077500000000000000000000000001357706137100173675ustar00rootroot00000000000000micropython-1.12/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/000077500000000000000000000000001357706137100234715ustar00rootroot00000000000000micropython-1.12/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h000066400000000000000000000001361357706137100264540ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "Feather M0 Express" #define MICROPY_HW_MCU_NAME "SAMD21G18A" micropython-1.12/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk000066400000000000000000000001461357706137100266350ustar00rootroot00000000000000MCU_SERIES = SAMD21 CMSIS_MCU = SAMD21G18A LD_FILES = boards/samd21x18a.ld sections.ld TEXT0 = 0x2000 micropython-1.12/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/000077500000000000000000000000001357706137100240225ustar00rootroot00000000000000micropython-1.12/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h000066400000000000000000000004501357706137100270040ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "ItsyBitsy M4 Express" #define MICROPY_HW_MCU_NAME "SAMD51G19A" #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) micropython-1.12/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk000066400000000000000000000001461357706137100271660ustar00rootroot00000000000000MCU_SERIES = SAMD51 CMSIS_MCU = SAMD51G19A LD_FILES = boards/samd51g19a.ld sections.ld TEXT0 = 0x4000 micropython-1.12/ports/samd/boards/ADAFRUIT_TRINKET_M0/000077500000000000000000000000001357706137100223225ustar00rootroot00000000000000micropython-1.12/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h000066400000000000000000000001261357706137100253040ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "Trinket M0" #define MICROPY_HW_MCU_NAME "SAMD21E18A" micropython-1.12/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.mk000066400000000000000000000001461357706137100254660ustar00rootroot00000000000000MCU_SERIES = SAMD21 CMSIS_MCU = SAMD21E18A LD_FILES = boards/samd21x18a.ld sections.ld TEXT0 = 0x2000 micropython-1.12/ports/samd/boards/MINISAM_M4/000077500000000000000000000000001357706137100210245ustar00rootroot00000000000000micropython-1.12/ports/samd/boards/MINISAM_M4/mpconfigboard.h000066400000000000000000000004371357706137100240130ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "Mini SAM M4" #define MICROPY_HW_MCU_NAME "SAMD51G19A" #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) micropython-1.12/ports/samd/boards/MINISAM_M4/mpconfigboard.mk000066400000000000000000000002501357706137100241640ustar00rootroot00000000000000# https://www.minifigboards.com/mini-sam-m4/mini-sam-m4-hardware/ MCU_SERIES = SAMD51 CMSIS_MCU = SAMD51G19A LD_FILES = boards/samd51g19a.ld sections.ld TEXT0 = 0x4000 micropython-1.12/ports/samd/boards/SAMD21_XPLAINED_PRO/000077500000000000000000000000001357706137100222625ustar00rootroot00000000000000micropython-1.12/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h000066400000000000000000000001371357706137100252460ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "SAMD21-XPLAINED-PRO" #define MICROPY_HW_MCU_NAME "SAMD21J18A" micropython-1.12/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk000066400000000000000000000001461357706137100254260ustar00rootroot00000000000000MCU_SERIES = SAMD21 CMSIS_MCU = SAMD21J18A LD_FILES = boards/samd21x18a.ld sections.ld TEXT0 = 0x2000 micropython-1.12/ports/samd/boards/samd21x18a.ld000066400000000000000000000005431357706137100215030ustar00rootroot00000000000000/* GNU linker script for SAMD21 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x00002000, LENGTH = 256K - 8K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } /* Top end of the stack, with room for double-tap variable */ _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 8K; _sheap = _ebss; _eheap = _sstack; micropython-1.12/ports/samd/boards/samd51g19a.ld000066400000000000000000000005461357706137100214710ustar00rootroot00000000000000/* GNU linker script for SAMD51 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 512K - 16K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K } /* Top end of the stack, with room for double-tap variable */ _estack = ORIGIN(RAM) + LENGTH(RAM) - 8; _sstack = _estack - 16K; _sheap = _ebss; _eheap = _sstack; micropython-1.12/ports/samd/main.c000066400000000000000000000061061357706137100172100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/compile.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mperrno.h" #include "py/stackctrl.h" #include "lib/utils/gchelper.h" #include "lib/utils/pyexec.h" extern uint8_t _sstack, _estack, _sheap, _eheap; void samd_main(void) { mp_stack_set_top(&_estack); mp_stack_set_limit(&_estack - &_sstack - 1024); for (;;) { gc_init(&_sheap, &_eheap); mp_init(); mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); gc_sweep_all(); mp_deinit(); } } void gc_collect(void) { gc_collect_start(); uintptr_t regs[10]; uintptr_t sp = gc_helper_get_regs_and_sp(regs); gc_collect_root((void**)sp, ((uintptr_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); gc_collect_end(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { for (;;) { } } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { mp_printf(MP_PYTHON_PRINTER, "Assertion '%s' failed, at file %s:%d\n", expr, file, line); for(;;) { } } #endif micropython-1.12/ports/samd/modmachine.c000066400000000000000000000056661357706137100204020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "extmod/machine_mem.h" #include "samd_soc.h" #if defined(MCU_SAMD21) #define DBL_TAP_ADDR ((volatile uint32_t *)(0x20000000 + 32 * 1024 - 4)) #elif defined(MCU_SAMD51) #define DBL_TAP_ADDR ((volatile uint32_t *)(0x20000000 + 192 * 1024 - 4)) #endif #define DBL_TAP_MAGIC_LOADER 0xf01669ef #define DBL_TAP_MAGIC_RESET 0xf02669ef STATIC mp_obj_t machine_reset(void) { *DBL_TAP_ADDR = DBL_TAP_MAGIC_RESET; NVIC_SystemReset(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); STATIC mp_obj_t machine_bootloader(void) { *DBL_TAP_ADDR = DBL_TAP_MAGIC_LOADER; NVIC_SystemReset(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_bootloader_obj, machine_bootloader); STATIC mp_obj_t machine_freq(void) { return MP_OBJ_NEW_SMALL_INT(CPU_FREQ); } MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq); STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t mp_module_machine = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; micropython-1.12/ports/samd/modutime.c000066400000000000000000000042351357706137100201100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "extmod/utime_mphal.h" STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t mp_module_utime = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; micropython-1.12/ports/samd/mpconfigport.h000066400000000000000000000101501357706137100207720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Options controlling how MicroPython is built, overriding defaults in py/mpconfig.h // Board specific definitions #include "mpconfigboard.h" // Memory allocation policies #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t #define MICROPY_GC_ALLOC_THRESHOLD (0) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (32) #define MICROPY_ALLOC_PATH_MAX (256) #define MICROPY_QSTR_BYTES_IN_HASH (1) // Compiler configuration #define MICROPY_COMP_CONST (0) // Python internal features #define MICROPY_ENABLE_GC (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) // Control over Python builtins #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_BUILTINS_STR_COUNT (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_MIN_MAX (0) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_SYS_MAXSIZE (1) // Extended modules #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_MACHINE (1) // Hooks to add builtins #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_utime; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; #define MP_STATE_PORT MP_STATE_VM // Miscellaneous settings #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ __WFI(); \ } while (0); #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #define MP_SSIZE_MAX (0x7fffffff) typedef int mp_int_t; // must be pointer size typedef unsigned mp_uint_t; // must be pointer size typedef long mp_off_t; // Need to provide a declaration/definition of alloca() #include micropython-1.12/ports/samd/mphalport.c000066400000000000000000000064261357706137100202770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #include "py/mphal.h" #include "lib/utils/interrupt_char.h" #include "samd_soc.h" #include "tusb.h" #if MICROPY_KBD_EXCEPTION void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { (void)itf; (void)wanted_char; tud_cdc_read_char(); // discard interrupt char mp_keyboard_interrupt(); } void mp_hal_set_interrupt_char(int c) { if (c != -1) { mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); } tud_cdc_set_wanted_char(c); } void mp_keyboard_interrupt(void) { MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); #if MICROPY_ENABLE_SCHEDULER if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } #endif } #endif void mp_hal_delay_ms(mp_uint_t ms) { ms += 1; uint32_t t0 = systick_ms; while (systick_ms - t0 < ms) { MICROPY_EVENT_POLL_HOOK } } void mp_hal_delay_us(mp_uint_t us) { uint32_t ms = us / 1000 + 1; uint32_t t0 = systick_ms; while (systick_ms - t0 < ms) { __WFI(); } } int mp_hal_stdin_rx_chr(void) { for (;;) { if (USARTx->USART.INTFLAG.bit.RXC) { return USARTx->USART.DATA.bit.DATA; } if (tud_cdc_connected() && tud_cdc_available()) { uint8_t buf[1]; uint32_t count = tud_cdc_read(buf, sizeof(buf)); if (count) { return buf[0]; } } __WFI(); } } void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { if (tud_cdc_connected()) { for (size_t i = 0; i < len;) { uint32_t n = len - i; uint32_t n2 = tud_cdc_write(str + i, n); if (n2 < n) { while (!tud_cdc_write_flush()) { __WFI(); } } i += n2; } while (!tud_cdc_write_flush()) { __WFI(); } } while (len--) { while (!(USARTx->USART.INTFLAG.bit.DRE)) { } USARTx->USART.DATA.bit.DATA = *str++; } } micropython-1.12/ports/samd/mphalport.h000066400000000000000000000031741357706137100203010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_SAMD_MPHALPORT_H #define MICROPY_INCLUDED_SAMD_MPHALPORT_H #include extern volatile uint32_t systick_ms; void mp_hal_set_interrupt_char(int c); static inline mp_uint_t mp_hal_ticks_ms(void) { return systick_ms; } static inline mp_uint_t mp_hal_ticks_us(void) { return systick_ms * 1000; } static inline mp_uint_t mp_hal_ticks_cpu(void) { return 0; } #endif // MICROPY_INCLUDED_SAMD_MPHALPORT_H micropython-1.12/ports/samd/qstrdefsport.h000066400000000000000000000000371357706137100210260ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/samd/samd_isr.c000066400000000000000000000104521357706137100200640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "samd_soc.h" typedef void (*ISR)(void); extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; const ISR isr_vector[]; uint32_t systick_ms; void Reset_Handler(void) __attribute__((naked)); void Reset_Handler(void) { // Set stack pointer #if __CORTEX_M >= 0x03 __asm volatile ("ldr sp, =_estack"); #else __asm volatile ("ldr r0, =_estack"); __asm volatile ("mov sp, r0"); #endif // Copy .data section from flash to RAM for (uint32_t *src = &_sidata, *dest = &_sdata; dest < &_edata;) { *dest++ = *src++; } // Zero out .bss section for (uint32_t *dest = &_sbss; dest < &_ebss;) { *dest++ = 0; } // When we get here: stack is initialised, bss is clear, data is copied #if __FPU_PRESENT == 1 && __FPU_USED == 1 // Set CP10 and CP11 Full Access SCB->CPACR |= (3UL << 10 * 2) | (3UL << 11 * 2); #endif // SCB->VTOR *((volatile uint32_t*)0xe000ed08) = (uint32_t)&isr_vector; // SCB->CCR: enable 8-byte stack alignment for IRQ handlers, in accord with EABI *((volatile uint32_t*)0xe000ed14) |= 1 << 9; // Initialise the cpu and peripherals samd_init(); // Now that we have a basic system up and running we can call main samd_main(); // we must not return for (;;) { } } void Default_Handler(void) { for (;;) { } } void SysTick_Handler(void) { systick_ms += 1; } const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { (ISR)&_estack, &Reset_Handler, &Default_Handler, // NMI_Handler &Default_Handler, // HardFault_Handler &Default_Handler, // MemManage_Handler &Default_Handler, // BusFault_Handler &Default_Handler, // UsageFault_Handler 0, 0, 0, 0, &Default_Handler, // SVC_Handler &Default_Handler, // DebugMon_Handler 0, &Default_Handler, // PendSV_Handler &SysTick_Handler, // SysTick_Handler 0, // line 0 0, 0, 0, 0, 0, 0, #if defined(MCU_SAMD21) USB_Handler_wrapper, // line 7 #else 0, #endif 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #if defined(MCU_SAMD51) &USB_0_Handler_wrapper, // line 80 &USB_1_Handler_wrapper, &USB_2_Handler_wrapper, &USB_3_Handler_wrapper, #else 0, 0, 0, 0, #endif 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; micropython-1.12/ports/samd/samd_soc.c000066400000000000000000000125311357706137100200530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "samd_soc.h" #include "tusb.h" static void uart0_init(void) { #if defined(MCU_SAMD21) // SERCOM0, TX=PA06=PAD2, RX=PA07=PAD3, ALT-D PORT->Group[0].PMUX[3].reg = 0x33; PORT->Group[0].PINCFG[6].reg = 1; PORT->Group[0].PINCFG[7].reg = 1; PM->APBCMASK.bit.SERCOM0_ = 1; GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_SERCOM0_CORE; while (GCLK->STATUS.bit.SYNCBUSY) { } uint32_t rxpo = 3; uint32_t txpo = 1; #elif defined(MCU_SAMD51) // SERCOM3, TX=PA17=PAD0, RX=PA16=PAD1, ALT-D PORT->Group[0].PMUX[8].reg = 0x33; PORT->Group[0].PINCFG[16].reg = 1; PORT->Group[0].PINCFG[17].reg = 1; // Use Generator 0 which is already enabled and switched to DFLL @ 48MHz GCLK->PCHCTRL[SERCOM3_GCLK_ID_CORE].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0; MCLK->APBBMASK.bit.SERCOM3_ = 1; uint32_t rxpo = 1; uint32_t txpo = 2; #endif while (USARTx->USART.SYNCBUSY.bit.SWRST) { } USARTx->USART.CTRLA.bit.SWRST = 1; while (USARTx->USART.SYNCBUSY.bit.SWRST) { } USARTx->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_RXPO(rxpo) | SERCOM_USART_CTRLA_TXPO(txpo) | SERCOM_USART_CTRLA_MODE(1) ; USARTx->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN; while (USARTx->USART.SYNCBUSY.bit.CTRLB) { } #if CPU_FREQ == 8000000 uint32_t baud = 50437; // 115200 baud; 65536*(1 - 16 * 115200/8e6) #elif CPU_FREQ == 48000000 uint32_t baud = 63019; // 115200 baud; 65536*(1 - 16 * 115200/48e6) #elif CPU_FREQ == 120000000 uint32_t baud = 64529; // 115200 baud; 65536*(1 - 16 * 115200/120e6) #endif USARTx->USART.BAUD.bit.BAUD = baud; USARTx->USART.CTRLA.bit.ENABLE = 1; while (USARTx->USART.SYNCBUSY.bit.ENABLE) { } } static void usb_init(void) { // Init USB clock #if defined(MCU_SAMD21) GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_USB; PM->AHBMASK.bit.USB_ = 1; PM->APBBMASK.bit.USB_ = 1; uint8_t alt = 6; // alt G, USB #elif defined(MCU_SAMD51) GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK1; while (GCLK->PCHCTRL[USB_GCLK_ID].bit.CHEN == 0) { } MCLK->AHBMASK.bit.USB_ = 1; MCLK->APBBMASK.bit.USB_ = 1; uint8_t alt = 7; // alt H, USB #endif // Init USB pins PORT->Group[0].DIRSET.reg = 1 << 25 | 1 << 24; PORT->Group[0].OUTCLR.reg = 1 << 25 | 1 << 24; PORT->Group[0].PMUX[12].reg = alt << 4 | alt; PORT->Group[0].PINCFG[24].reg = PORT_PINCFG_PMUXEN; PORT->Group[0].PINCFG[25].reg = PORT_PINCFG_PMUXEN; tusb_init(); } void samd_init(void) { #if defined(MCU_SAMD21) NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz // Enable DFLL48M SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {} SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) | SYSCTRL_DFLLMUL_MUL(48000); uint32_t coarse = (*((uint32_t*)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos; if (coarse == 0x3f) { coarse = 0x1f; } uint32_t fine = 512; SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(fine); SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE; while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {} GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1); GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0); while (GCLK->STATUS.bit.SYNCBUSY) { } // Configure PA10 as output for LED PORT->Group[0].DIRSET.reg = 1 << 10; #elif defined(MCU_SAMD51) GCLK->GENCTRL[1].reg = 1 << GCLK_GENCTRL_DIV_Pos | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; while (GCLK->SYNCBUSY.bit.GENCTRL1) { } // Configure PA22 as output for LED PORT->Group[0].DIRSET.reg = 1 << 22; #endif SysTick_Config(CPU_FREQ / 1000); uart0_init(); usb_init(); } micropython-1.12/ports/samd/samd_soc.h000066400000000000000000000033471357706137100200650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_SAMD_SAMD_SOC_H #define MICROPY_INCLUDED_SAMD_SAMD_SOC_H #include #include "sam.h" #if defined(MCU_SAMD21) #define CPU_FREQ (48000000) #define USARTx SERCOM0 #elif defined(MCU_SAMD51) #define CPU_FREQ (48000000) #define USARTx SERCOM3 #endif void samd_init(void); void samd_main(void); void USB_Handler_wrapper(void); void USB_0_Handler_wrapper(void); void USB_1_Handler_wrapper(void); void USB_2_Handler_wrapper(void); void USB_3_Handler_wrapper(void); #endif // MICROPY_INCLUDED_SAMD_SAMD_SOC_H micropython-1.12/ports/samd/sections.ld000066400000000000000000000011201357706137100202570ustar00rootroot00000000000000/* Define output sections */ SECTIONS { .text : { . = ALIGN(4); KEEP(*(.isr_vector)) *(.text) *(.text*) *(.rodata) *(.rodata*) . = ALIGN(4); _etext = .; _sidata = _etext; } >FLASH .data : AT ( _sidata ) { . = ALIGN(4); _sdata = .; *(.data) *(.data*) . = ALIGN(4); _edata = .; } >RAM .bss : { . = ALIGN(4); _sbss = .; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM } micropython-1.12/ports/samd/tusb_config.h000066400000000000000000000035161357706137100205750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_SAMD_TUSB_CONFIG_H #define MICROPY_INCLUDED_SAMD_TUSB_CONFIG_H // Common configuration #if defined(MCU_SAMD21) #define CFG_TUSB_MCU OPT_MCU_SAMD21 #elif defined(MCU_SAMD51) #define CFG_TUSB_MCU OPT_MCU_SAMD51 #endif #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #define CFG_TUSB_MEM_SECTION #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) // Device configuration #define CFG_TUD_ENDOINT0_SIZE (64) #define CFG_TUD_CDC (1) #define CFG_TUD_CDC_RX_BUFSIZE (64) #define CFG_TUD_CDC_TX_BUFSIZE (64) #endif // MICROPY_INCLUDED_SAMD_TUSB_CONFIG_H micropython-1.12/ports/samd/tusb_port.c000066400000000000000000000104131357706137100203010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "samd_soc.h" #include "tusb.h" #define USBD_VID (0xf055) #define USBD_PID (0x9802) #define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) #define USBD_MAX_POWER_MA (250) #define USBD_ITF_CDC (0) // needs 2 interfaces #define USBD_ITF_MAX (2) #define USBD_CDC_EP_CMD (0x81) #define USBD_CDC_EP_OUT (0x02) #define USBD_CDC_EP_IN (0x82) #define USBD_CDC_CMD_MAX_SIZE (8) #define USBD_STR_0 (0x00) #define USBD_STR_MANUF (0x01) #define USBD_STR_PRODUCT (0x02) #define USBD_STR_SERIAL (0x03) #define USBD_STR_CDC (0x04) // Note: descriptors returned from callbacks must exist long enough for transfer to complete static const tusb_desc_device_t usbd_desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, .idVendor = USBD_VID, .idProduct = USBD_PID, .bcdDevice = 0x0100, .iManufacturer = USBD_STR_MANUF, .iProduct = USBD_STR_PRODUCT, .iSerialNumber = USBD_STR_SERIAL, .bNumConfigurations = 1, }; static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { TUD_CONFIG_DESCRIPTOR(USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, CFG_TUD_CDC_RX_BUFSIZE), }; static const char *const usbd_desc_str[] = { [USBD_STR_MANUF] = "MicroPython", [USBD_STR_PRODUCT] = "Board in FS mode", [USBD_STR_SERIAL] = "000000000000", // TODO [USBD_STR_CDC] = "Board CDC", }; const uint8_t *tud_descriptor_device_cb(void) { return (const uint8_t*)&usbd_desc_device; } const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { (void)index; return usbd_desc_cfg; } const uint16_t *tud_descriptor_string_cb(uint8_t index) { #define DESC_STR_MAX (20) static uint16_t desc_str[DESC_STR_MAX]; uint8_t len; if (index == 0) { desc_str[1] = 0x0409; // supported language is English len = 1; } else { if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { return NULL; } const char* str = usbd_desc_str[index]; for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { desc_str[1 + len] = str[len]; } } // first byte is len, second byte is string type desc_str[0] = TUD_DESC_STR_HEADER(len); return desc_str; } #if defined(MCU_SAMD21) void USB_Handler_wrapper(void) { USB_Handler(); tud_task(); } #elif defined(MCU_SAMD51) void USB_0_Handler_wrapper(void) { USB_0_Handler(); tud_task(); } void USB_1_Handler_wrapper(void) { USB_1_Handler(); tud_task(); } void USB_2_Handler_wrapper(void) { USB_2_Handler(); tud_task(); } void USB_3_Handler_wrapper(void) { USB_3_Handler(); tud_task(); } #endif micropython-1.12/ports/stm32/000077500000000000000000000000001357706137100161415ustar00rootroot00000000000000micropython-1.12/ports/stm32/Makefile000066400000000000000000000436441357706137100176140ustar00rootroot00000000000000# Select the board to build for: if not given on the command line, # then default to PYBV10. BOARD ?= PYBV10 # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD) BOARD_DIR ?= boards/$(BOARD) ifeq ($(wildcard $(BOARD_DIR)/.),) $(error Invalid BOARD specified: $(BOARD_DIR)) endif include ../../py/mkenv.mk -include mpconfigport.mk include $(BOARD_DIR)/mpconfigboard.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h $(BUILD)/modstm_qstr.h QSTR_GLOBAL_DEPENDENCIES = mpconfigboard_common.h $(BOARD_DIR)/mpconfigboard.h # File containing description of content to be frozen into firmware. FROZEN_MANIFEST ?= boards/manifest.py # include py core make definitions include $(TOP)/py/py.mk GIT_SUBMODULES = lib/lwip lib/mbedtls lib/mynewt-nimble lib/stm32lib MCU_SERIES_UPPER = $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') CMSIS_MCU_LOWER = $(shell echo $(CMSIS_MCU) | tr '[:upper:]' '[:lower:]') LD_DIR=boards CMSIS_DIR=$(TOP)/lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Include HAL_DIR=lib/stm32lib/STM32$(MCU_SERIES_UPPER)xx_HAL_Driver USBDEV_DIR=usbdev #USBHOST_DIR=usbhost DFU=$(TOP)/tools/dfu.py # may need to prefix dfu-util with sudo USE_PYDFU ?= 1 PYDFU ?= $(TOP)/tools/pydfu.py DFU_UTIL ?= dfu-util DEVICE=0483:df11 STFLASH ?= st-flash OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg STARTUP_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/gcc/startup_$(CMSIS_MCU_LOWER).o SYSTEM_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/system_stm32$(MCU_SERIES)xx.o # Select the cross compile prefix CROSS_COMPILE ?= arm-none-eabi- INC += -I. INC += -I$(TOP) INC += -I$(BUILD) INC += -I$(TOP)/lib/cmsis/inc INC += -I$(CMSIS_DIR)/ INC += -I$(TOP)/$(HAL_DIR)/Inc INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc #INC += -I$(USBHOST_DIR) INC += -Ilwip_inc # Basic Cortex-M flags CFLAGS_CORTEX_M = -mthumb # Select hardware floating-point support SUPPORTS_HARDWARE_FP_SINGLE = 0 SUPPORTS_HARDWARE_FP_DOUBLE = 0 ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32F765xx STM32F767xx STM32F769xx STM32H743xx)) CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard SUPPORTS_HARDWARE_FP_SINGLE = 1 SUPPORTS_HARDWARE_FP_DOUBLE = 1 else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0)) CFLAGS_CORTEX_M += -msoft-float else CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard SUPPORTS_HARDWARE_FP_SINGLE = 1 endif endif # Options for particular MCU series CFLAGS_MCU_f0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0 -mcpu=cortex-m0 CFLAGS_MCU_f4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -D$(CMSIS_MCU) CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(COPT) CFLAGS += -I$(BOARD_DIR) CFLAGS += -DSTM32_HAL_H='' CFLAGS += -DMICROPY_HW_VTOR=$(TEXT0_ADDR) ifeq ($(MICROPY_FLOAT_IMPL),double) CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE else ifeq ($(MICROPY_FLOAT_IMPL),none) CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE else CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT CFLAGS += -fsingle-precision-constant -Wdouble-promotion endif endif LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref LDFLAGS += --defsym=_estack_reserve=8 LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Remove uncalled code from the final image. CFLAGS += -fdata-sections -ffunction-sections LDFLAGS += --gc-sections # Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -g -DPENDSV_DEBUG COPT = -O0 else COPT += -Os -DNDEBUG endif # Options for mpy-cross MPY_CROSS_FLAGS += -march=armv7m SRC_LIB = $(addprefix lib/,\ libc/string0.c \ mp-readline/readline.c \ netutils/netutils.c \ netutils/trace.c \ netutils/dhcpserver.c \ timeutils/timeutils.c \ utils/pyexec.c \ utils/interrupt_char.c \ utils/sys_stdio_mphal.c \ utils/mpirq.c \ ) ifeq ($(MICROPY_FLOAT_IMPL),double) SRC_LIBM = $(addprefix lib/libm_dbl/,\ __cos.c \ __expo2.c \ __fpclassify.c \ __rem_pio2.c \ __rem_pio2_large.c \ __signbit.c \ __sin.c \ __tan.c \ acos.c \ acosh.c \ asin.c \ asinh.c \ atan.c \ atan2.c \ atanh.c \ ceil.c \ cos.c \ cosh.c \ copysign.c \ erf.c \ exp.c \ expm1.c \ floor.c \ fmod.c \ frexp.c \ ldexp.c \ lgamma.c \ log.c \ log10.c \ log1p.c \ modf.c \ nearbyint.c \ pow.c \ rint.c \ scalbn.c \ sin.c \ sinh.c \ tan.c \ tanh.c \ tgamma.c \ trunc.c \ ) ifeq ($(SUPPORTS_HARDWARE_FP_DOUBLE),1) SRC_LIBM += lib/libm_dbl/thumb_vfp_sqrt.c else SRC_LIBM += lib/libm_dbl/sqrt.c endif else SRC_LIBM = $(addprefix lib/libm/,\ math.c \ acoshf.c \ asinfacosf.c \ asinhf.c \ atan2f.c \ atanf.c \ atanhf.c \ ef_rem_pio2.c \ erf_lgamma.c \ fmodf.c \ kf_cos.c \ kf_rem_pio2.c \ kf_sin.c \ kf_tan.c \ log1pf.c \ nearbyintf.c \ sf_cos.c \ sf_erf.c \ sf_frexp.c \ sf_ldexp.c \ sf_modf.c \ sf_sin.c \ sf_tan.c \ wf_lgamma.c \ wf_tgamma.c \ ) ifeq ($(SUPPORTS_HARDWARE_FP_SINGLE),1) SRC_LIBM += lib/libm/thumb_vfp_sqrtf.c else SRC_LIBM += lib/libm/ef_sqrt.c endif endif EXTMOD_SRC_C = $(addprefix extmod/,\ modonewire.c \ ) DRIVERS_SRC_C = $(addprefix drivers/,\ bus/softspi.c \ bus/softqspi.c \ memory/spiflash.c \ dht/dht.c \ ) SRC_C = \ main.c \ stm32_it.c \ usbd_conf.c \ usbd_desc.c \ usbd_cdc_interface.c \ usbd_hid_interface.c \ usbd_msc_interface.c \ mphalport.c \ mpthreadport.c \ irq.c \ pendsv.c \ systick.c \ softtimer.c \ powerctrl.c \ powerctrlboot.c \ rfcore.c \ pybthread.c \ factoryreset.c \ timer.c \ led.c \ pin.c \ pin_defs_stm32.c \ pin_named_pins.c \ bufhelper.c \ dma.c \ i2c.c \ pyb_i2c.c \ spi.c \ pyb_spi.c \ qspi.c \ uart.c \ can.c \ fdcan.c \ pyb_can.c \ usb.c \ wdt.c \ eth.c \ gccollect.c \ help.c \ machine_adc.c \ machine_i2c.c \ machine_spi.c \ machine_timer.c \ machine_uart.c \ modmachine.c \ modpyb.c \ modstm.c \ moduos.c \ modutime.c \ modusocket.c \ network_lan.c \ modnetwork.c \ extint.c \ usrsw.c \ rng.c \ rtc.c \ flash.c \ flashbdev.c \ spibdev.c \ storage.c \ sdcard.c \ sdram.c \ fatfs_port.c \ lcd.c \ accel.c \ servo.c \ dac.c \ adc.c \ $(wildcard $(BOARD_DIR)/*.c) SRC_O = \ $(STARTUP_FILE) \ $(SYSTEM_FILE) ifeq ($(MCU_SERIES),f0) SRC_O += \ resethandler_m0.o \ lib/utils/gchelper_m0.o else ifeq ($(MCU_SERIES),l0) CSUPEROPT = -Os # save some code space SRC_O += \ resethandler_m0.o \ lib/utils/gchelper_m0.o else SRC_O += \ system_stm32.o \ resethandler.o \ lib/utils/gchelper_m3.o endif endif SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal.c \ hal_adc.c \ hal_adc_ex.c \ hal_cortex.c \ hal_dma.c \ hal_flash.c \ hal_flash_ex.c \ hal_gpio.c \ hal_i2c.c \ hal_pcd.c \ hal_pcd_ex.c \ hal_pwr.c \ hal_pwr_ex.c \ hal_rcc.c \ hal_rcc_ex.c \ hal_rtc.c \ hal_rtc_ex.c \ hal_spi.c \ hal_tim.c \ hal_tim_ex.c \ hal_uart.c \ ) ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4 wb)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ ll_usb.c \ ) endif ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l4)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_sd.c \ ll_sdmmc.c \ ll_fmc.c \ ) endif ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_mmc.c \ hal_sdram.c \ hal_dma_ex.c \ hal_dcmi.c \ ) endif ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c) else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 h7 l4)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_can.c) endif endif SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\ core/src/usbd_core.c \ core/src/usbd_ctlreq.c \ core/src/usbd_ioreq.c \ class/src/usbd_cdc_msc_hid.c \ class/src/usbd_msc_bot.c \ class/src/usbd_msc_scsi.c \ ) ifeq ($(MICROPY_PY_BLUETOOTH),1) CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK=1 endif ifeq ($(MICROPY_PY_NETWORK_CYW43),1) CFLAGS_MOD += -DMICROPY_PY_NETWORK_CYW43=1 SRC_C += sdio.c EXTMOD_SRC_C += extmod/network_cyw43.c DRIVERS_SRC_C += drivers/cyw43/cyw43_ctrl.c drivers/cyw43/cyw43_lwip.c LIBS += $(TOP)/drivers/cyw43/libcyw43.a endif ifneq ($(MICROPY_PY_WIZNET5K),0) WIZNET5K_DIR=drivers/wiznet5k INC += -I$(TOP)/$(WIZNET5K_DIR) CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=$(MICROPY_PY_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_WIZNET5K) ifeq ($(MICROPY_PY_LWIP),1) # When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket CFLAGS_MOD += -DWIZCHIP_USE_MAX_BUFFER endif SRC_MOD += network_wiznet5k.c modnwwiznet5k.c SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\ ethernet/w$(MICROPY_PY_WIZNET5K)/w$(MICROPY_PY_WIZNET5K).c \ ethernet/wizchip_conf.c \ ethernet/socket.c \ internet/dns/dns.c \ ) endif # for CC3000 module ifeq ($(MICROPY_PY_CC3K),1) CC3000_DIR=drivers/cc3000 INC += -I$(TOP)/$(CC3000_DIR)/inc CFLAGS_MOD += -DMICROPY_PY_CC3K=1 SRC_MOD += modnwcc3k.c SRC_MOD += $(addprefix $(CC3000_DIR)/src/,\ cc3000_common.c \ evnt_handler.c \ hci.c \ netapp.c \ nvmem.c \ security.c \ socket.c \ wlan.c \ ccspi.c \ inet_ntop.c \ inet_pton.c \ patch.c \ patch_prog.c \ ) endif ifeq ($(MICROPY_SSL_MBEDTLS),1) CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' SRC_MOD += mbedtls/mbedtls_port.c endif ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) include $(TOP)/extmod/nimble/nimble.mk SRC_C += nimble.c SRC_C += nimble_hci_uart.c EXTMOD_SRC_C += extmod/modbluetooth_nimble.c ifeq ($(MICROPY_PY_NETWORK_CYW43),1) DRIVERS_SRC_C += drivers/cyw43/cywbt.c endif endif OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_O)) OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_USBDEV:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(BUILD)/pins_$(BOARD).o # This file contains performance critical functions so turn up the optimisation # level. It doesn't add much to the code size and improves performance a bit. # Don't use -O3 with this file because gcc tries to optimise memset in terms of itself. $(BUILD)/lib/libc/string0.o: COPT += -O2 # We put several files into the first 16K section with the ISRs. # If we compile these using -O0 then it won't fit. So if you really want these # to be compiled with -O0, then edit boards/common.ld (in the .isr_vector section) # and comment out the following lines. $(BUILD)/$(OOFATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os $(PY_BUILD)/formatfloat.o: COPT += -Os $(PY_BUILD)/parsenum.o: COPT += -Os $(PY_BUILD)/mpprint.o: COPT += -Os all: $(TOP)/lib/stm32lib/README.md $(BUILD)/firmware.dfu $(BUILD)/firmware.hex # For convenience, automatically fetch required submodules if they don't exist $(TOP)/lib/stm32lib/README.md: $(ECHO) "stm32lib submodule not found, fetching it now..." (cd $(TOP) && git submodule update --init lib/stm32lib) ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),) # To use frozen source modules, put your .py files in a subdirectory (eg scripts/) # and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch). CFLAGS += -DMICROPY_MODULE_FROZEN_STR endif ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),) # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and # then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY endif .PHONY: deploy deploy: $(BUILD)/firmware.dfu $(ECHO) "Writing $< to the board" ifeq ($(USE_PYDFU),1) $(Q)$(PYTHON) $(PYDFU) -u $< else $(Q)$(DFU_UTIL) -a 0 -d $(DEVICE) -D $< endif # A board should specify TEXT0_ADDR if to use a different location than the # default for the firmware memory location. A board can also optionally define # TEXT1_ADDR to split the firmware into two sections; see below for details. TEXT0_ADDR ?= 0x08000000 ifeq ($(TEXT1_ADDR),) # No TEXT1_ADDR given so put all firmware at TEXT0_ADDR location TEXT0_SECTIONS ?= .isr_vector .text .data deploy-stlink: $(BUILD)/firmware.dfu $(ECHO) "Writing $(BUILD)/firmware.bin to the board via ST-LINK" $(Q)$(STFLASH) write $(BUILD)/firmware.bin $(TEXT0_ADDR) deploy-openocd: $(BUILD)/firmware.dfu $(ECHO) "Writing $(BUILD)/firmware.bin to the board via ST-LINK using OpenOCD" $(Q)$(OPENOCD) -f $(OPENOCD_CONFIG) -c "stm_flash $(BUILD)/firmware.bin $(TEXT0_ADDR)" $(BUILD)/firmware.dfu: $(BUILD)/firmware.elf $(ECHO) "Create $@" $(Q)$(OBJCOPY) -O binary $(addprefix -j ,$(TEXT0_SECTIONS)) $^ $(BUILD)/firmware.bin $(Q)$(PYTHON) $(DFU) -b $(TEXT0_ADDR):$(BUILD)/firmware.bin $@ else # TEXT0_ADDR and TEXT1_ADDR are specified so split firmware between these locations TEXT0_SECTIONS ?= .isr_vector TEXT1_SECTIONS ?= .text .data deploy-stlink: $(BUILD)/firmware.dfu $(ECHO) "Writing $(BUILD)/firmware0.bin to the board via ST-LINK" $(Q)$(STFLASH) write $(BUILD)/firmware0.bin $(TEXT0_ADDR) $(ECHO) "Writing $(BUILD)/firmware1.bin to the board via ST-LINK" $(Q)$(STFLASH) --reset write $(BUILD)/firmware1.bin $(TEXT1_ADDR) deploy-openocd: $(BUILD)/firmware.dfu $(ECHO) "Writing $(BUILD)/firmware{0,1}.bin to the board via ST-LINK using OpenOCD" $(Q)$(OPENOCD) -f $(OPENOCD_CONFIG) -c "stm_flash $(BUILD)/firmware0.bin $(TEXT0_ADDR) $(BUILD)/firmware1.bin $(TEXT1_ADDR)" $(BUILD)/firmware.dfu: $(BUILD)/firmware.elf $(ECHO) "GEN $@" $(Q)$(OBJCOPY) -O binary $(addprefix -j ,$(TEXT0_SECTIONS)) $^ $(BUILD)/firmware0.bin $(Q)$(OBJCOPY) -O binary $(addprefix -j ,$(TEXT1_SECTIONS)) $^ $(BUILD)/firmware1.bin $(Q)$(PYTHON) $(DFU) -b $(TEXT0_ADDR):$(BUILD)/firmware0.bin -b $(TEXT1_ADDR):$(BUILD)/firmware1.bin $@ endif $(BUILD)/firmware.hex: $(BUILD)/firmware.elf $(ECHO) "GEN $@" $(Q)$(OBJCOPY) -O ihex $< $@ $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LDFLAGS_MOD) $(LIBS) $(Q)$(SIZE) $@ ifneq ($(TEXT0_ADDR),0x08000000) $(ECHO) "INFO: this build requires mboot to be installed first" endif ifeq ($(TEXT1_ADDR),0x90000000) $(ECHO) "INFO: this build places firmware in external QSPI flash" endif PLLVALUES = boards/pllvalues.py MAKE_PINS = boards/make-pins.py BOARD_PINS = $(BOARD_DIR)/pins.csv PREFIX_FILE = boards/stm32f4xx_prefix.c GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c GEN_PINS_HDR = $(HEADER_BUILD)/pins.h GEN_PINS_QSTR = $(BUILD)/pins_qstr.h GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h GEN_PINS_AF_PY = $(BUILD)/pins_af.py INSERT_USB_IDS = $(TOP)/tools/insert-usb-ids.py FILE2H = $(TOP)/tools/file2h.py USB_IDS_FILE = usb.h CDCINF_TEMPLATE = pybcdc.inf_template GEN_CDCINF_FILE = $(HEADER_BUILD)/pybcdc.inf GEN_CDCINF_HEADER = $(HEADER_BUILD)/pybcdc_inf.h # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(SRC_MOD) $(SRC_LIB) $(EXTMOD_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += $(GEN_CDCINF_HEADER) # Making OBJ use an order-only depenedency on the generated pins.h file # has the side effect of making the pins.h file before we actually compile # any of the objects. The normal dependency generation will deal with the # case when pins.h is modified. But when it doesn't exist, we don't know # which source files might need it. $(OBJ): | $(GEN_PINS_HDR) # With conditional pins, we may need to regenerate qstrdefs.h when config # options change. $(HEADER_BUILD)/qstrdefs.generated.h: $(BOARD_DIR)/mpconfigboard.h # main.c can't be even preprocessed without $(GEN_CDCINF_HEADER) main.c: $(GEN_CDCINF_HEADER) # Use a pattern rule here so that make will only call make-pins.py once to make # both pins_$(BOARD).c and pins.h $(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(HEADER_BUILD)/%_af_defs.h $(BUILD)/%_qstr.h: $(BOARD_DIR)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) \ --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --hdr-obj-decls \ --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) \ --af-defs $(GEN_PINS_AF_DEFS) --af-defs-cmp-strings \ --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC) $(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c $(call compile_c) GEN_PLLFREQTABLE_HDR = $(HEADER_BUILD)/pllfreqtable.h GEN_STMCONST_HDR = $(HEADER_BUILD)/modstm_const.h GEN_STMCONST_QSTR = $(BUILD)/modstm_qstr.h GEN_STMCONST_MPZ = $(HEADER_BUILD)/modstm_mpz.h CMSIS_MCU_HDR = $(CMSIS_DIR)/$(CMSIS_MCU_LOWER).h modmachine.c: $(GEN_PLLFREQTABLE_HDR) $(GEN_PLLFREQTABLE_HDR): $(PLLVALUES) | $(HEADER_BUILD) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(PLLVALUES) -c $(if $(filter $(MCU_SERIES),f7),--relax-pll48,) file:$(BOARD_DIR)/stm32$(MCU_SERIES)xx_hal_conf.h > $@ $(BUILD)/modstm.o: $(GEN_STMCONST_HDR) # Use a pattern rule here so that make will only call make-stmconst.py once to # make both modstm_const.h and modstm_qstr.h $(HEADER_BUILD)/%_const.h $(BUILD)/%_qstr.h: $(CMSIS_MCU_HDR) make-stmconst.py | $(HEADER_BUILD) $(ECHO) "GEN stmconst $@" $(Q)$(PYTHON) make-stmconst.py --qstr $(GEN_STMCONST_QSTR) --mpz $(GEN_STMCONST_MPZ) $(CMSIS_MCU_HDR) > $(GEN_STMCONST_HDR) $(GEN_CDCINF_HEADER): $(GEN_CDCINF_FILE) $(FILE2H) | $(HEADER_BUILD) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(FILE2H) $< > $@ $(GEN_CDCINF_FILE): $(CDCINF_TEMPLATE) $(INSERT_USB_IDS) $(USB_IDS_FILE) | $(HEADER_BUILD) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(INSERT_USB_IDS) $(USB_IDS_FILE) $< > $@ include $(TOP)/py/mkrules.mk micropython-1.12/ports/stm32/README.md000066400000000000000000000117741357706137100174320ustar00rootroot00000000000000MicroPython port to STM32 MCUs ============================== This directory contains the port of MicroPython to ST's line of STM32 microcontrollers. Supported MCU series are: STM32F0, STM32F4, STM32F7 and STM32L4. Parts of the code here utilise the STM32Cube HAL library. The officially supported boards are the line of pyboards: PYBv1.0 and PYBv1.1 (both with STM32F405), and PYBLITEv1.0 (with STM32F411). See [micropython.org/pyboard](http://www.micropython.org/pyboard/) for further details. Other boards that are supported include ST Discovery and Nucleo boards. See the boards/ subdirectory, which contains the configuration files used to build each individual board. The STM32H7 series has preliminary support: there is a working REPL via USB and UART, as well as very basic peripheral support, but some things do not work and none of the advanced features of the STM32H7 are yet supported, such as the clock tree. At this point the STM32H7 should be considered as a fast version of the STM32F7. Build instructions ------------------ Before building the firmware for a given board the MicroPython cross-compiler must be built; it will be used to pre-compile some of the built-in scripts to bytecode. The cross-compiler is built and run on the host machine, using: ```bash $ make -C mpy-cross ``` This command should be executed from the root directory of this repository. All other commands below should be executed from the ports/stm32/ directory. An ARM compiler is required for the build, along with the associated binary utilities. The default compiler is `arm-none-eabi-gcc`, which is available for Arch Linux via the package `arm-none-eabi-gcc`, for Ubuntu via instructions [here](https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa), or see [here](https://launchpad.net/gcc-arm-embedded) for the main GCC ARM Embedded page. The compiler can be changed using the `CROSS_COMPILE` variable when invoking `make`. First the submodules must be obtained using: $ make submodules Then to build for a given board, run: $ make BOARD=PYBV11 The default board is PYBV10 but any of the names of the subdirectories in the `boards/` directory can be passed as the argument to `BOARD=`. The above command should produce binary images in the `build-PYBV11/` subdirectory (or the equivalent directory for the board specified). You must then get your board/microcontroller into DFU mode. On the pyboard connect the 3V3 pin to the P1/DFU pin with a wire (they are next to each other on the bottom left of the board, second row from the bottom) and then reset (by pressing the RST button) or power on the board. Then flash the firmware using the command: $ make BOARD=PYBV11 deploy This will use the included `tools/pydfu.py` script. You can use instead the `dfu-util` program (available [here](http://dfu-util.sourceforge.net/)) by passing `USE_PYDFU=0`: $ make BOARD=PYBV11 USE_PYDFU=0 deploy If flashing the firmware does not work it may be because you don't have the correct permissions. Try then: $ sudo make BOARD=PYBV11 deploy Or using `dfu-util` directly: $ sudo dfu-util -a 0 -d 0483:df11 -D build-PYBV11/firmware.dfu ### Flashing the Firmware with stlink ST Discovery or Nucleo boards have a builtin programmer called ST-LINK. With these boards and using Linux or OS X, you have the option to upload the `stm32` firmware using the `st-flash` utility from the [stlink](https://github.com/texane/stlink) project. To do so, connect the board with a mini USB cable to its ST-LINK USB port and then use the make target `deploy-stlink`. For example, if you have the STM32F4DISCOVERY board, you can run: $ make BOARD=STM32F4DISC deploy-stlink The `st-flash` program should detect the USB connection to the board automatically. If not, run `lsusb` to determine its USB bus and device number and set the `STLINK_DEVICE` environment variable accordingly, using the format `:`. Example: $ lsusb [...] Bus 002 Device 035: ID 0483:3748 STMicroelectronics ST-LINK/V2 $ export STLINK_DEVICE="002:0035" $ make BOARD=STM32F4DISC deploy-stlink ### Flashing the Firmware with OpenOCD Another option to deploy the firmware on ST Discovery or Nucleo boards with a ST-LINK interface uses [OpenOCD](http://openocd.org/). Connect the board with a mini USB cable to its ST-LINK USB port and then use the make target `deploy-openocd`. For example, if you have the STM32F4DISCOVERY board: $ make BOARD=STM32F4DISC deploy-openocd The `openocd` program, which writes the firmware to the target board's flash, is configured via the file `ports/stm32/boards/openocd_stm32f4.cfg`. This configuration should work for all boards based on a STM32F4xx MCU with a ST-LINKv2 interface. You can override the path to this configuration by setting `OPENOCD_CONFIG` in your Makefile or on the command line. Accessing the board ------------------- Once built and deployed, access the MicroPython REPL (the Python prompt) via USB serial or UART, depending on the board. For the pyboard you can try: $ picocom /dev/ttyACM0 micropython-1.12/ports/stm32/accel.c000066400000000000000000000234011357706137100173540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mphal.h" #include "py/runtime.h" #include "pin.h" #include "i2c.h" #include "accel.h" #if MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3 /// \moduleref pyb /// \class Accel - accelerometer control /// /// Accel is an object that controls the MMA7660 or the KXTJ3 accelerometer /// depending on one/two constant in mpconfigboard.h file of board project : /// #define MICROPY_HW_HAS_MMA7660 (1) /// #define MICROPY_HW_HAS_KXTJ3 (0) // not mandatory if equal to 0 /// /// Example usage: /// /// accel = pyb.Accel() /// for i in range(10): /// print(accel.x(), accel.y(), accel.z()) /// /// Raw values are between -32 and 31 for -/+ 1.5G acceleration for MMA7660. /// Raw values are between -128 and 127 for -/+ 8G acceleration for KXTJ3. #define I2C_TIMEOUT_MS (50) #if MICROPY_HW_HAS_MMA7660 #define ACCEL_ADDR (76) #define ACCEL_REG_X (0) #define ACCEL_REG_Y (1) #define ACCEL_REG_Z (2) #define ACCEL_REG_TILT (3) #define ACCEL_REG_MODE (7) #define ACCEL_AXIS_SIGNED_VALUE(i) (((i) & 0x3f) | ((i) & 0x20 ? (~0x1f) : 0)) #elif MICROPY_HW_HAS_KXTJ3 #define ACCEL_ADDR (0x0f) #define ACCEL_REG_DCST_RESP (0x0c) #define ACCEL_REG_WHO_AM_I (0x0f) #define ACCEL_REG_X (0x07) // XOUT_H #define ACCEL_REG_Y (0x09) // YOUT_H #define ACCEL_REG_Z (0x0B) // ZOUT_H #define ACCEL_REG_CTRL_REG1 (0x1B) #define ACCEL_REG_CTRL_REG2 (0x1d) #define ACCEL_REG_CTRL_REG2 (0x1d) #define ACCEL_REG_DATA_CTRL_REG (0x21) #define ACCEL_AXIS_SIGNED_VALUE(i) (((i) & 0x7f) | ((i) & 0x80 ? (~0x7f) : 0)) #endif void accel_init(void) { #if MICROPY_HW_HAS_MMA7660 // PB5 is connected to AVDD; pull high to enable MMA accel device mp_hal_pin_low(MICROPY_HW_MMA_AVDD_PIN); // turn off AVDD mp_hal_pin_output(MICROPY_HW_MMA_AVDD_PIN); #endif } STATIC void accel_start(void) { // start the I2C bus in master mode i2c_init(I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA, 400000, I2C_TIMEOUT_MS); #if MICROPY_HW_HAS_MMA7660 // turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again mp_hal_pin_low(MICROPY_HW_MMA_AVDD_PIN); // turn off mp_hal_delay_ms(30); mp_hal_pin_high(MICROPY_HW_MMA_AVDD_PIN); // turn on mp_hal_delay_ms(30); int ret; for (int i = 0; i < 4; i++) { ret = i2c_writeto(I2C1, ACCEL_ADDR, NULL, 0, true); if (ret == 0) { break; } } if (ret != 0) { mp_raise_msg(&mp_type_OSError, "accelerometer not found"); } // set MMA to active mode uint8_t data[2] = {ACCEL_REG_MODE, 1}; // active mode i2c_writeto(I2C1, ACCEL_ADDR, data, 2, true); // wait for MMA to become active mp_hal_delay_ms(30); #elif MICROPY_HW_HAS_KXTJ3 // readout WHO_AM_I register to check KXTJ3 device presence uint8_t data[2] = { ACCEL_REG_WHO_AM_I }; i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); if (data[0] != 0x35) { mp_raise_msg(&mp_type_OSError, "accelerometer not found"); } // set operating mode (default: 8 bits, range +/-8G) data[0] = ACCEL_REG_CTRL_REG1; data[1] = 0x90; i2c_writeto(I2C1, ACCEL_ADDR, data, 2, true); // set dat output rates to 200Hz (LPF roll-over 10ms), idd=35uA data[0] = ACCEL_REG_DATA_CTRL_REG; data[1] = 0x04; i2c_writeto(I2C1, ACCEL_ADDR, data, 2, true); #endif } /******************************************************************************/ /* MicroPython bindings */ #define NUM_AXIS (3) #define FILT_DEPTH (4) typedef struct _pyb_accel_obj_t { mp_obj_base_t base; int16_t buf[NUM_AXIS * FILT_DEPTH]; } pyb_accel_obj_t; STATIC pyb_accel_obj_t pyb_accel_obj; /// \classmethod \constructor() /// Create and return an accelerometer object. /// /// Note: if you read accelerometer values immediately after creating this object /// you will get 0. It takes around 20ms for the first sample to be ready, so, /// unless you have some other code between creating this object and reading its /// values, you should put a `pyb.delay(20)` after creating it. For example: /// /// accel = pyb.Accel() /// pyb.delay(20) /// print(accel.x()) STATIC mp_obj_t pyb_accel_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); // init accel object pyb_accel_obj.base.type = &pyb_accel_type; accel_start(); return MP_OBJ_FROM_PTR(&pyb_accel_obj); } STATIC mp_obj_t read_axis(int axis) { uint8_t data[1] = { axis }; i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); return mp_obj_new_int(ACCEL_AXIS_SIGNED_VALUE(data[0])); } /// \method x() /// Get the x-axis value. STATIC mp_obj_t pyb_accel_x(mp_obj_t self_in) { return read_axis(ACCEL_REG_X); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_x_obj, pyb_accel_x); /// \method y() /// Get the y-axis value. STATIC mp_obj_t pyb_accel_y(mp_obj_t self_in) { return read_axis(ACCEL_REG_Y); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_y_obj, pyb_accel_y); /// \method z() /// Get the z-axis value. STATIC mp_obj_t pyb_accel_z(mp_obj_t self_in) { return read_axis(ACCEL_REG_Z); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_z_obj, pyb_accel_z); /// \method tilt() /// Get the tilt register. STATIC mp_obj_t pyb_accel_tilt(mp_obj_t self_in) { #if MICROPY_HW_HAS_MMA7660 uint8_t data[1] = { ACCEL_REG_TILT }; i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); return mp_obj_new_int(data[0]); #elif MICROPY_HW_HAS_KXTJ3 /// No tilt like register with KXTJ3 accelerometer return 0; #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_tilt_obj, pyb_accel_tilt); /// \method filtered_xyz() /// Get a 3-tuple of filtered x, y and z values. STATIC mp_obj_t pyb_accel_filtered_xyz(mp_obj_t self_in) { pyb_accel_obj_t *self = MP_OBJ_TO_PTR(self_in); memmove(self->buf, self->buf + NUM_AXIS, NUM_AXIS * (FILT_DEPTH - 1) * sizeof(int16_t)); #if MICROPY_HW_HAS_MMA7660 const size_t DATA_SIZE = NUM_AXIS; const size_t DATA_STRIDE = 1; #elif MICROPY_HW_HAS_KXTJ3 const size_t DATA_SIZE = 5; const size_t DATA_STRIDE = 2; #endif uint8_t data[DATA_SIZE]; data[0] = ACCEL_REG_X; i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); i2c_readfrom(I2C1, ACCEL_ADDR, data, DATA_SIZE, true); mp_obj_t tuple[NUM_AXIS]; for (int i = 0; i < NUM_AXIS; i++) { self->buf[NUM_AXIS * (FILT_DEPTH - 1) + i] = ACCEL_AXIS_SIGNED_VALUE(data[i * DATA_STRIDE]); int32_t val = 0; for (int j = 0; j < FILT_DEPTH; j++) { val += self->buf[i + NUM_AXIS * j]; } tuple[i] = mp_obj_new_int(val); } return mp_obj_new_tuple(3, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_filtered_xyz_obj, pyb_accel_filtered_xyz); STATIC mp_obj_t pyb_accel_read(mp_obj_t self_in, mp_obj_t reg) { uint8_t data[1] = { mp_obj_get_int(reg) }; i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); return mp_obj_new_int(data[0]); } MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_read_obj, pyb_accel_read); STATIC mp_obj_t pyb_accel_write(mp_obj_t self_in, mp_obj_t reg, mp_obj_t val) { uint8_t data[2] = { mp_obj_get_int(reg), mp_obj_get_int(val) }; i2c_writeto(I2C1, ACCEL_ADDR, data, 2, true); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(pyb_accel_write_obj, pyb_accel_write); STATIC const mp_rom_map_elem_t pyb_accel_locals_dict_table[] = { // TODO add init, deinit, and perhaps reset methods { MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&pyb_accel_x_obj) }, { MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&pyb_accel_y_obj) }, { MP_ROM_QSTR(MP_QSTR_z), MP_ROM_PTR(&pyb_accel_z_obj) }, { MP_ROM_QSTR(MP_QSTR_tilt), MP_ROM_PTR(&pyb_accel_tilt_obj) }, { MP_ROM_QSTR(MP_QSTR_filtered_xyz), MP_ROM_PTR(&pyb_accel_filtered_xyz_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_accel_read_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_accel_write_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_accel_locals_dict, pyb_accel_locals_dict_table); const mp_obj_type_t pyb_accel_type = { { &mp_type_type }, .name = MP_QSTR_Accel, .make_new = pyb_accel_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_accel_locals_dict, }; #endif // MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3 micropython-1.12/ports/stm32/accel.h000066400000000000000000000026131357706137100173630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_ACCEL_H #define MICROPY_INCLUDED_STM32_ACCEL_H extern const mp_obj_type_t pyb_accel_type; void accel_init(void); #endif // MICROPY_INCLUDED_STM32_ACCEL_H micropython-1.12/ports/stm32/adc.c000066400000000000000000000754361357706137100170530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/binary.h" #include "py/mphal.h" #include "adc.h" #include "pin.h" #include "timer.h" #if MICROPY_HW_ENABLE_ADC /// \moduleref pyb /// \class ADC - analog to digital conversion: read analog values on a pin /// /// Usage: /// /// adc = pyb.ADC(pin) # create an analog object from a pin /// val = adc.read() # read an analog value /// /// adc = pyb.ADCAll(resolution) # creale an ADCAll object /// val = adc.read_channel(channel) # read the given channel /// val = adc.read_core_temp() # read MCU temperature /// val = adc.read_core_vbat() # read MCU VBAT /// val = adc.read_core_vref() # read MCU VREF /* ADC defintions */ #if defined(STM32H7) #define ADCx (ADC3) #define PIN_ADC_MASK PIN_ADC3 #define pin_adc_table pin_adc3 #else #define ADCx (ADC1) #define PIN_ADC_MASK PIN_ADC1 #define pin_adc_table pin_adc1 #endif #define ADCx_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE #if defined(STM32F0) #define ADC_FIRST_GPIO_CHANNEL (0) #define ADC_LAST_GPIO_CHANNEL (15) #define ADC_SCALE_V (3.3f) #define ADC_CAL_ADDRESS (0x1ffff7ba) #define ADC_CAL1 ((uint16_t*)0x1ffff7b8) #define ADC_CAL2 ((uint16_t*)0x1ffff7c2) #define ADC_CAL_BITS (12) #elif defined(STM32F4) #define ADC_FIRST_GPIO_CHANNEL (0) #define ADC_LAST_GPIO_CHANNEL (15) #define ADC_SCALE_V (3.3f) #define ADC_CAL_ADDRESS (0x1fff7a2a) #define ADC_CAL1 ((uint16_t*)(ADC_CAL_ADDRESS + 2)) #define ADC_CAL2 ((uint16_t*)(ADC_CAL_ADDRESS + 4)) #define ADC_CAL_BITS (12) #elif defined(STM32F7) #define ADC_FIRST_GPIO_CHANNEL (0) #define ADC_LAST_GPIO_CHANNEL (15) #define ADC_SCALE_V (3.3f) #if defined(STM32F722xx) || defined(STM32F723xx) || \ defined(STM32F732xx) || defined(STM32F733xx) #define ADC_CAL_ADDRESS (0x1ff07a2a) #else #define ADC_CAL_ADDRESS (0x1ff0f44a) #endif #define ADC_CAL1 ((uint16_t*)(ADC_CAL_ADDRESS + 2)) #define ADC_CAL2 ((uint16_t*)(ADC_CAL_ADDRESS + 4)) #define ADC_CAL_BITS (12) #elif defined(STM32H7) #define ADC_FIRST_GPIO_CHANNEL (0) #define ADC_LAST_GPIO_CHANNEL (16) #define ADC_SCALE_V (3.3f) #define ADC_CAL_ADDRESS (0x1FF1E860) #define ADC_CAL1 ((uint16_t*)(0x1FF1E820)) #define ADC_CAL2 ((uint16_t*)(0x1FF1E840)) #define ADC_CAL_BITS (16) #elif defined(STM32L4) #define ADC_FIRST_GPIO_CHANNEL (1) #define ADC_LAST_GPIO_CHANNEL (16) #define ADC_SCALE_V (3.0f) #define ADC_CAL_ADDRESS (0x1fff75aa) #define ADC_CAL1 ((uint16_t*)(ADC_CAL_ADDRESS - 2)) #define ADC_CAL2 ((uint16_t*)(ADC_CAL_ADDRESS + 0x20)) #define ADC_CAL_BITS (12) #else #error Unsupported processor #endif #if defined(STM32F091xC) #define VBAT_DIV (2) #elif defined(STM32F405xx) || defined(STM32F415xx) || \ defined(STM32F407xx) || defined(STM32F417xx) || \ defined(STM32F401xC) || defined(STM32F401xE) #define VBAT_DIV (2) #elif defined(STM32F411xE) || defined(STM32F413xx) || \ defined(STM32F427xx) || defined(STM32F429xx) || \ defined(STM32F437xx) || defined(STM32F439xx) || \ defined(STM32F446xx) #define VBAT_DIV (4) #elif defined(STM32F722xx) || defined(STM32F723xx) || \ defined(STM32F732xx) || defined(STM32F733xx) || \ defined(STM32F746xx) || defined(STM32F765xx) || \ defined(STM32F767xx) || defined(STM32F769xx) #define VBAT_DIV (4) #elif defined(STM32H743xx) #define VBAT_DIV (4) #elif defined(STM32L432xx) || \ defined(STM32L451xx) || defined(STM32L452xx) || \ defined(STM32L462xx) || defined(STM32L475xx) || \ defined(STM32L476xx) || defined(STM32L496xx) #define VBAT_DIV (3) #else #error Unsupported processor #endif // Timeout for waiting for end-of-conversion, in ms #define EOC_TIMEOUT (10) /* Core temperature sensor definitions */ #define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */ #define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */ // scale and calibration values for VBAT and VREF #define ADC_SCALE (ADC_SCALE_V / ((1 << ADC_CAL_BITS) - 1)) #define VREFIN_CAL ((uint16_t *)ADC_CAL_ADDRESS) #ifndef __HAL_ADC_IS_CHANNEL_INTERNAL #define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \ (channel == ADC_CHANNEL_VBAT \ || channel == ADC_CHANNEL_VREFINT \ || channel == ADC_CHANNEL_TEMPSENSOR) #endif typedef struct _pyb_obj_adc_t { mp_obj_base_t base; mp_obj_t pin_name; int channel; ADC_HandleTypeDef handle; } pyb_obj_adc_t; // convert user-facing channel number into internal channel number static inline uint32_t adc_get_internal_channel(uint32_t channel) { #if defined(STM32F4) || defined(STM32F7) // on F4 and F7 MCUs we want channel 16 to always be the TEMPSENSOR // (on some MCUs ADC_CHANNEL_TEMPSENSOR=16, on others it doesn't) if (channel == 16) { channel = ADC_CHANNEL_TEMPSENSOR; } #endif return channel; } STATIC bool is_adcx_channel(int channel) { #if defined(STM32F411xE) // The HAL has an incorrect IS_ADC_CHANNEL macro for the F411 so we check for temp return IS_ADC_CHANNEL(channel) || channel == ADC_CHANNEL_TEMPSENSOR; #elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) return IS_ADC_CHANNEL(channel); #elif defined(STM32H7) return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) || IS_ADC_CHANNEL(__HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); #elif defined(STM32L4) ADC_HandleTypeDef handle; handle.Instance = ADCx; return IS_ADC_CHANNEL(&handle, channel); #else #error Unsupported processor #endif } STATIC void adc_wait_for_eoc_or_timeout(int32_t timeout) { uint32_t tickstart = HAL_GetTick(); #if defined(STM32F4) || defined(STM32F7) while ((ADCx->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { #elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) while (READ_BIT(ADCx->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { #else #error Unsupported processor #endif if (((HAL_GetTick() - tickstart ) > timeout)) { break; // timeout } } } STATIC void adcx_clock_enable(void) { #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) ADCx_CLK_ENABLE(); #elif defined(STM32H7) __HAL_RCC_ADC3_CLK_ENABLE(); __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); #elif defined(STM32L4) __HAL_RCC_ADC_CLK_ENABLE(); #else #error Unsupported processor #endif } STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adcx_clock_enable(); adch->Instance = ADCx; adch->Init.Resolution = resolution; adch->Init.ContinuousConvMode = DISABLE; adch->Init.DiscontinuousConvMode = DISABLE; #if !defined(STM32F0) adch->Init.NbrOfDiscConversion = 0; adch->Init.NbrOfConversion = 1; #endif adch->Init.EOCSelection = ADC_EOC_SINGLE_CONV; adch->Init.ExternalTrigConv = ADC_SOFTWARE_START; adch->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; #if defined(STM32F0) adch->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 12MHz adch->Init.ScanConvMode = DISABLE; adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; adch->Init.DMAContinuousRequests = DISABLE; adch->Init.SamplingTimeCommon = ADC_SAMPLETIME_55CYCLES_5; // ~4uS #elif defined(STM32F4) || defined(STM32F7) adch->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; adch->Init.ScanConvMode = DISABLE; adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; adch->Init.DMAContinuousRequests = DISABLE; #elif defined(STM32H7) adch->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; adch->Init.ScanConvMode = DISABLE; adch->Init.LowPowerAutoWait = DISABLE; adch->Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; adch->Init.OversamplingMode = DISABLE; adch->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; adch->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; #elif defined(STM32L4) adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; adch->Init.ScanConvMode = ADC_SCAN_DISABLE; adch->Init.LowPowerAutoWait = DISABLE; adch->Init.Overrun = ADC_OVR_DATA_PRESERVED; adch->Init.OversamplingMode = DISABLE; adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; adch->Init.DMAContinuousRequests = DISABLE; #else #error Unsupported processor #endif HAL_ADC_Init(adch); #if defined(STM32H7) HAL_ADCEx_Calibration_Start(adch, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); #endif #if defined(STM32L4) HAL_ADCEx_Calibration_Start(adch, ADC_SINGLE_ENDED); #endif } STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) { if (ADC_FIRST_GPIO_CHANNEL <= adc_obj->channel && adc_obj->channel <= ADC_LAST_GPIO_CHANNEL) { // Channels 0-16 correspond to real pins. Configure the GPIO pin in ADC mode. const pin_obj_t *pin = pin_adc_table[adc_obj->channel]; mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0); } adcx_init_periph(&adc_obj->handle, ADC_RESOLUTION_12B); #if defined(STM32L4) && defined(ADC_DUALMODE_REGSIMULT_INJECSIMULT) ADC_MultiModeTypeDef multimode; multimode.Mode = ADC_MODE_INDEPENDENT; if (HAL_ADCEx_MultiModeConfigChannel(&adc_obj->handle, &multimode) != HAL_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Can not set multimode on ADC1 channel: %d", adc_obj->channel)); } #endif } STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) { ADC_ChannelConfTypeDef sConfig; #if defined (STM32H7) sConfig.Rank = ADC_REGULAR_RANK_1; if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel) == 0) { channel = __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel); } #else sConfig.Rank = 1; #endif sConfig.Channel = channel; #if defined(STM32F0) sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; #elif defined(STM32F4) || defined(STM32F7) sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; #elif defined(STM32H7) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5; } else { sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5; } sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.OffsetRightShift = DISABLE; sConfig.OffsetSignedSaturation = DISABLE; #elif defined(STM32L4) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; } else { sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; } sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; #else #error Unsupported processor #endif #if defined(STM32F0) // On the STM32F0 we must select only one channel at a time to sample, so clear all // channels before calling HAL_ADC_ConfigChannel, which will select the desired one. adc_handle->Instance->CHSELR = 0; #endif HAL_ADC_ConfigChannel(adc_handle, &sConfig); } STATIC uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) { HAL_ADC_Start(adcHandle); adc_wait_for_eoc_or_timeout(EOC_TIMEOUT); uint32_t value = ADCx->DR; HAL_ADC_Stop(adcHandle); return value; } STATIC uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32_t channel) { adc_config_channel(adcHandle, channel); uint32_t raw_value = adc_read_channel(adcHandle); #if defined(STM32F4) || defined(STM32F7) // ST docs say that (at least on STM32F42x and STM32F43x), VBATE must // be disabled when TSVREFE is enabled for TEMPSENSOR and VREFINT // conversions to work. VBATE is enabled by the above call to read // the channel, and here we disable VBATE so a subsequent call for // TEMPSENSOR or VREFINT works correctly. if (channel == ADC_CHANNEL_VBAT) { ADC->CCR &= ~ADC_CCR_VBATE; } #endif return raw_value; } /******************************************************************************/ /* MicroPython bindings : adc object (single channel) */ STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_obj_adc_t *self = MP_OBJ_TO_PTR(self_in); mp_print_str(print, "pin_name, PRINT_STR); mp_printf(print, " channel=%u>", self->channel); } /// \classmethod \constructor(pin) /// Create an ADC object associated with the given pin. /// This allows you to then read analog values on that pin. STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check number of arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); // 1st argument is the pin name mp_obj_t pin_obj = args[0]; uint32_t channel; if (mp_obj_is_int(pin_obj)) { channel = adc_get_internal_channel(mp_obj_get_int(pin_obj)); } else { const pin_obj_t *pin = pin_find(pin_obj); if ((pin->adc_num & PIN_ADC_MASK) == 0) { // No ADC1 function on that pin nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %q does not have ADC capabilities", pin->name)); } channel = pin->adc_channel; } if (!is_adcx_channel(channel)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "not a valid ADC Channel: %d", channel)); } if (ADC_FIRST_GPIO_CHANNEL <= channel && channel <= ADC_LAST_GPIO_CHANNEL) { // these channels correspond to physical GPIO ports so make sure they exist if (pin_adc_table[channel] == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "channel %d not available on this board", channel)); } } pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t); memset(o, 0, sizeof(*o)); o->base.type = &pyb_adc_type; o->pin_name = pin_obj; o->channel = channel; adc_init_single(o); return MP_OBJ_FROM_PTR(o); } /// \method read() /// Read the value on the analog pin and return it. The returned value /// will be between 0 and 4095. STATIC mp_obj_t adc_read(mp_obj_t self_in) { pyb_obj_adc_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int(adc_config_and_read_channel(&self->handle, self->channel)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read); /// \method read_timed(buf, timer) /// /// Read analog values into `buf` at a rate set by the `timer` object. /// /// `buf` can be bytearray or array.array for example. The ADC values have /// 12-bit resolution and are stored directly into `buf` if its element size is /// 16 bits or greater. If `buf` has only 8-bit elements (eg a bytearray) then /// the sample resolution will be reduced to 8 bits. /// /// `timer` should be a Timer object, and a sample is read each time the timer /// triggers. The timer must already be initialised and running at the desired /// sampling frequency. /// /// To support previous behaviour of this function, `timer` can also be an /// integer which specifies the frequency (in Hz) to sample at. In this case /// Timer(6) will be automatically configured to run at the given frequency. /// /// Example using a Timer object (preferred way): /// /// adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 /// tim = pyb.Timer(6, freq=10) # create a timer running at 10Hz /// buf = bytearray(100) # creat a buffer to store the samples /// adc.read_timed(buf, tim) # sample 100 values, taking 10s /// /// Example using an integer for the frequency: /// /// adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 /// buf = bytearray(100) # create a buffer of 100 bytes /// adc.read_timed(buf, 10) # read analog values into buf at 10Hz /// # this will take 10 seconds to finish /// for val in buf: # loop over all values /// print(val) # print the value out /// /// This function does not allocate any memory. STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_in) { pyb_obj_adc_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); size_t typesize = mp_binary_get_size('@', bufinfo.typecode, NULL); TIM_HandleTypeDef *tim; #if defined(TIM6) if (mp_obj_is_integer(freq_in)) { // freq in Hz given so init TIM6 (legacy behaviour) tim = timer_tim6_init(mp_obj_get_int(freq_in)); HAL_TIM_Base_Start(tim); } else #endif { // use the supplied timer object as the sampling time base tim = pyb_timer_get_handle(freq_in); } // configure the ADC channel adc_config_channel(&self->handle, self->channel); // This uses the timer in polling mode to do the sampling // TODO use DMA uint nelems = bufinfo.len / typesize; for (uint index = 0; index < nelems; index++) { // Wait for the timer to trigger so we sample at the correct frequency while (__HAL_TIM_GET_FLAG(tim, TIM_FLAG_UPDATE) == RESET) { } __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); if (index == 0) { // for the first sample we need to turn the ADC on HAL_ADC_Start(&self->handle); } else { // for subsequent samples we can just set the "start sample" bit #if defined(STM32F4) || defined(STM32F7) ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; #elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) SET_BIT(ADCx->CR, ADC_CR_ADSTART); #else #error Unsupported processor #endif } // wait for sample to complete adc_wait_for_eoc_or_timeout(EOC_TIMEOUT); // read value uint value = ADCx->DR; // store value in buffer if (typesize == 1) { value >>= 4; } mp_binary_set_val_array_from_int(bufinfo.typecode, bufinfo.buf, index, value); } // turn the ADC off HAL_ADC_Stop(&self->handle); #if defined(TIM6) if (mp_obj_is_integer(freq_in)) { // stop timer if we initialised TIM6 in this function (legacy behaviour) HAL_TIM_Base_Stop(tim); } #endif return mp_obj_new_int(bufinfo.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(adc_read_timed_obj, adc_read_timed); // read_timed_multi((adcx, adcy, ...), (bufx, bufy, ...), timer) // // Read analog values from multiple ADC's into buffers at a rate set by the // timer. The ADC values have 12-bit resolution and are stored directly into // the corresponding buffer if its element size is 16 bits or greater, otherwise // the sample resolution will be reduced to 8 bits. // // This function should not allocate any heap memory. STATIC mp_obj_t adc_read_timed_multi(mp_obj_t adc_array_in, mp_obj_t buf_array_in, mp_obj_t tim_in) { size_t nadcs, nbufs; mp_obj_t *adc_array, *buf_array; mp_obj_get_array(adc_array_in, &nadcs, &adc_array); mp_obj_get_array(buf_array_in, &nbufs, &buf_array); if (nadcs < 1) { mp_raise_ValueError("need at least 1 ADC"); } if (nadcs != nbufs) { mp_raise_ValueError("length of ADC and buffer lists differ"); } // Get buf for first ADC, get word size, check other buffers match in type mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_array[0], &bufinfo, MP_BUFFER_WRITE); size_t typesize = mp_binary_get_size('@', bufinfo.typecode, NULL); void *bufptrs[nbufs]; for (uint array_index = 0; array_index < nbufs; array_index++) { mp_buffer_info_t bufinfo_curr; mp_get_buffer_raise(buf_array[array_index], &bufinfo_curr, MP_BUFFER_WRITE); if ((bufinfo.len != bufinfo_curr.len) || (bufinfo.typecode != bufinfo_curr.typecode)) { mp_raise_ValueError("size and type of buffers must match"); } bufptrs[array_index] = bufinfo_curr.buf; } // Use the supplied timer object as the sampling time base TIM_HandleTypeDef *tim; tim = pyb_timer_get_handle(tim_in); // Start adc; this is slow so wait for it to start pyb_obj_adc_t *adc0 = MP_OBJ_TO_PTR(adc_array[0]); adc_config_channel(&adc0->handle, adc0->channel); HAL_ADC_Start(&adc0->handle); // Wait for sample to complete and discard adc_wait_for_eoc_or_timeout(EOC_TIMEOUT); // Read (and discard) value uint value = ADCx->DR; // Ensure first sample is on a timer tick __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); while (__HAL_TIM_GET_FLAG(tim, TIM_FLAG_UPDATE) == RESET) { } __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); // Overrun check: assume success bool success = true; size_t nelems = bufinfo.len / typesize; for (size_t elem_index = 0; elem_index < nelems; elem_index++) { if (__HAL_TIM_GET_FLAG(tim, TIM_FLAG_UPDATE) != RESET) { // Timer has already triggered success = false; } else { // Wait for the timer to trigger so we sample at the correct frequency while (__HAL_TIM_GET_FLAG(tim, TIM_FLAG_UPDATE) == RESET) { } } __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); for (size_t array_index = 0; array_index < nadcs; array_index++) { pyb_obj_adc_t *adc = MP_OBJ_TO_PTR(adc_array[array_index]); // configure the ADC channel adc_config_channel(&adc->handle, adc->channel); // for the first sample we need to turn the ADC on // ADC is started: set the "start sample" bit #if defined(STM32F4) || defined(STM32F7) ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; #elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) SET_BIT(ADCx->CR, ADC_CR_ADSTART); #else #error Unsupported processor #endif // wait for sample to complete adc_wait_for_eoc_or_timeout(EOC_TIMEOUT); // read value value = ADCx->DR; // store values in buffer if (typesize == 1) { value >>= 4; } mp_binary_set_val_array_from_int(bufinfo.typecode, bufptrs[array_index], elem_index, value); } } // Turn the ADC off adc0 = MP_OBJ_TO_PTR(adc_array[0]); HAL_ADC_Stop(&adc0->handle); return mp_obj_new_bool(success); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(adc_read_timed_multi_fun_obj, adc_read_timed_multi); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(adc_read_timed_multi_obj, MP_ROM_PTR(&adc_read_timed_multi_fun_obj)); STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&adc_read_obj) }, { MP_ROM_QSTR(MP_QSTR_read_timed), MP_ROM_PTR(&adc_read_timed_obj) }, { MP_ROM_QSTR(MP_QSTR_read_timed_multi), MP_ROM_PTR(&adc_read_timed_multi_obj) }, }; STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table); const mp_obj_type_t pyb_adc_type = { { &mp_type_type }, .name = MP_QSTR_ADC, .print = adc_print, .make_new = adc_make_new, .locals_dict = (mp_obj_dict_t*)&adc_locals_dict, }; /******************************************************************************/ /* adc all object */ typedef struct _pyb_adc_all_obj_t { mp_obj_base_t base; ADC_HandleTypeDef handle; } pyb_adc_all_obj_t; void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_mask) { switch (resolution) { #if !defined(STM32H7) case 6: resolution = ADC_RESOLUTION_6B; break; #endif case 8: resolution = ADC_RESOLUTION_8B; break; case 10: resolution = ADC_RESOLUTION_10B; break; case 12: resolution = ADC_RESOLUTION_12B; break; #if defined(STM32H7) case 16: resolution = ADC_RESOLUTION_16B; break; #endif default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "resolution %d not supported", resolution)); } for (uint32_t channel = ADC_FIRST_GPIO_CHANNEL; channel <= ADC_LAST_GPIO_CHANNEL; ++channel) { // only initialise those channels that are selected with the en_mask if (en_mask & (1 << channel)) { // Channels 0-16 correspond to real pins. Configure the GPIO pin in // ADC mode. const pin_obj_t *pin = pin_adc_table[channel]; if (pin) { mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0); } } } adcx_init_periph(&adc_all->handle, resolution); } int adc_get_resolution(ADC_HandleTypeDef *adcHandle) { uint32_t res_reg = ADC_GET_RESOLUTION(adcHandle); switch (res_reg) { #if !defined(STM32H7) case ADC_RESOLUTION_6B: return 6; #endif case ADC_RESOLUTION_8B: return 8; case ADC_RESOLUTION_10B: return 10; #if defined(STM32H7) case ADC_RESOLUTION_16B: return 16; #endif } return 12; } STATIC uint32_t adc_config_and_read_ref(ADC_HandleTypeDef *adcHandle, uint32_t channel) { uint32_t raw_value = adc_config_and_read_channel(adcHandle, channel); // Scale raw reading to the number of bits used by the calibration constants return raw_value << (ADC_CAL_BITS - adc_get_resolution(adcHandle)); } int adc_read_core_temp(ADC_HandleTypeDef *adcHandle) { int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR); return ((raw_value - CORE_TEMP_V25) / CORE_TEMP_AVG_SLOPE) + 25; } #if MICROPY_PY_BUILTINS_FLOAT // correction factor for reference value STATIC volatile float adc_refcor = 1.0f; float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) { int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR); float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 80.0; return (((float)raw_value * adc_refcor - *ADC_CAL1) / core_temp_avg_slope) + 30.0f; } float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) { uint32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_VBAT); return raw_value * VBAT_DIV * ADC_SCALE * adc_refcor; } float adc_read_core_vref(ADC_HandleTypeDef *adcHandle) { uint32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_VREFINT); // update the reference correction factor adc_refcor = ((float)(*VREFIN_CAL)) / ((float)raw_value); return (*VREFIN_CAL) * ADC_SCALE; } #endif /******************************************************************************/ /* MicroPython bindings : adc_all object */ STATIC mp_obj_t adc_all_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check number of arguments mp_arg_check_num(n_args, n_kw, 1, 2, false); // make ADCAll object pyb_adc_all_obj_t *o = m_new_obj(pyb_adc_all_obj_t); o->base.type = &pyb_adc_all_type; mp_int_t res = mp_obj_get_int(args[0]); uint32_t en_mask = 0xffffffff; if (n_args > 1) { en_mask = mp_obj_get_int(args[1]); } adc_init_all(o, res, en_mask); return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t adc_all_read_channel(mp_obj_t self_in, mp_obj_t channel) { pyb_adc_all_obj_t *self = MP_OBJ_TO_PTR(self_in); uint32_t chan = adc_get_internal_channel(mp_obj_get_int(channel)); uint32_t data = adc_config_and_read_channel(&self->handle, chan); return mp_obj_new_int(data); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(adc_all_read_channel_obj, adc_all_read_channel); STATIC mp_obj_t adc_all_read_core_temp(mp_obj_t self_in) { pyb_adc_all_obj_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_BUILTINS_FLOAT float data = adc_read_core_temp_float(&self->handle); return mp_obj_new_float(data); #else int data = adc_read_core_temp(&self->handle); return mp_obj_new_int(data); #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_temp_obj, adc_all_read_core_temp); #if MICROPY_PY_BUILTINS_FLOAT STATIC mp_obj_t adc_all_read_core_vbat(mp_obj_t self_in) { pyb_adc_all_obj_t *self = MP_OBJ_TO_PTR(self_in); float data = adc_read_core_vbat(&self->handle); return mp_obj_new_float(data); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vbat_obj, adc_all_read_core_vbat); STATIC mp_obj_t adc_all_read_core_vref(mp_obj_t self_in) { pyb_adc_all_obj_t *self = MP_OBJ_TO_PTR(self_in); float data = adc_read_core_vref(&self->handle); return mp_obj_new_float(data); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vref_obj, adc_all_read_core_vref); STATIC mp_obj_t adc_all_read_vref(mp_obj_t self_in) { pyb_adc_all_obj_t *self = MP_OBJ_TO_PTR(self_in); adc_read_core_vref(&self->handle); return mp_obj_new_float(ADC_SCALE_V * adc_refcor); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_vref_obj, adc_all_read_vref); #endif STATIC const mp_rom_map_elem_t adc_all_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read_channel), MP_ROM_PTR(&adc_all_read_channel_obj) }, { MP_ROM_QSTR(MP_QSTR_read_core_temp), MP_ROM_PTR(&adc_all_read_core_temp_obj) }, #if MICROPY_PY_BUILTINS_FLOAT { MP_ROM_QSTR(MP_QSTR_read_core_vbat), MP_ROM_PTR(&adc_all_read_core_vbat_obj) }, { MP_ROM_QSTR(MP_QSTR_read_core_vref), MP_ROM_PTR(&adc_all_read_core_vref_obj) }, { MP_ROM_QSTR(MP_QSTR_read_vref), MP_ROM_PTR(&adc_all_read_vref_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(adc_all_locals_dict, adc_all_locals_dict_table); const mp_obj_type_t pyb_adc_all_type = { { &mp_type_type }, .name = MP_QSTR_ADCAll, .make_new = adc_all_make_new, .locals_dict = (mp_obj_dict_t*)&adc_all_locals_dict, }; #endif // MICROPY_HW_ENABLE_ADC micropython-1.12/ports/stm32/adc.h000066400000000000000000000026301357706137100170420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_ADC_H #define MICROPY_INCLUDED_STM32_ADC_H extern const mp_obj_type_t pyb_adc_type; extern const mp_obj_type_t pyb_adc_all_type; #endif // MICROPY_INCLUDED_STM32_ADC_H micropython-1.12/ports/stm32/autoflash000077500000000000000000000015331357706137100200570ustar00rootroot00000000000000#!/bin/sh # # This script loops doing the following: # - wait for DFU device # - flash DFU device # - wait for DFU to exit # - wait for serial port to appear # - run a terminal SERIAL=/dev/ttyACM0 DEVICE=0483:df11 while true; do echo "waiting for DFU device..." while true; do if lsusb | grep -q DFU; then break fi sleep 1s done echo "found DFU device, flashing" dfu-util -a 0 -d $DEVICE -D build/flash.dfu echo "waiting for DFU to exit..." while true; do if lsusb | grep -q DFU; then sleep 1s continue fi break done echo "waiting for $SERIAL..." while true; do if ls /dev/tty* | grep -q $SERIAL; then break fi sleep 1s continue done sleep 1s picocom $SERIAL done micropython-1.12/ports/stm32/boards/000077500000000000000000000000001357706137100174135ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/000077500000000000000000000000001357706137100225215ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h000066400000000000000000000060161357706137100255070ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "Adafruit Feather STM32F405" #define MICROPY_HW_MCU_NAME "STM32F405RG" #define MICROPY_HW_HAS_SWITCH (0) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_HAS_MMA7660 (0) #define MICROPY_HW_HAS_LCD (0) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 12MHz #define MICROPY_HW_CLK_PLLM (12) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) #define MICROPY_HW_CLK_LAST_FREQ (1) // The Feather has a 32kHz crystal for the RTC #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (1) // UART config #define MICROPY_HW_UART3_NAME "UART3" // on RX / TX #define MICROPY_HW_UART3_TX (pin_B10) // TX #define MICROPY_HW_UART3_RX (pin_B11) // RX #define MICROPY_HW_UART3_RTS (pin_B14) // MISO #define MICROPY_HW_UART3_CTS (pin_B13) // SCK #define MICROPY_HW_UART2_NAME "UART2" // on SDA/SCL #define MICROPY_HW_UART2_TX (pin_B6) // SCL #define MICROPY_HW_UART2_RX (pin_B7) // SDA #define MICROPY_HW_UART6_NAME "UART6" // on D5/D6 #define MICROPY_HW_UART6_TX (pin_C6) // D6 #define MICROPY_HW_UART6_RX (pin_C7) // D5 // I2C busses #define MICROPY_HW_I2C1_NAME "I2C1" #define MICROPY_HW_I2C1_SCL (pin_B6) // SCL #define MICROPY_HW_I2C1_SDA (pin_B7) // SDA #define MICROPY_HW_I2C2_NAME "I2C2" #define MICROPY_HW_I2C2_SCL (pin_B10) // TX #define MICROPY_HW_I2C2_SDA (pin_B11) // RX // SPI busses #define MICROPY_HW_SPI1_NAME "SPIFLASH" #define MICROPY_HW_SPI1_NSS (pin_A15) // FLASH CS #define MICROPY_HW_SPI1_SCK (pin_B3) // FLASH CLK #define MICROPY_HW_SPI1_MISO (pin_B4) // FLASH MISO #define MICROPY_HW_SPI1_MOSI (pin_B5) // FLASH MOSI #define MICROPY_HW_SPI2_NAME "SPI1" #define MICROPY_HW_SPI2_NSS (pin_B12) // SD DETECT #define MICROPY_HW_SPI2_SCK (pin_B13) // SCK #define MICROPY_HW_SPI2_MISO (pin_B14) // MISO #define MICROPY_HW_SPI2_MOSI (pin_B15) // MOSI // CAN busses #define MICROPY_HW_CAN1_NAME "CAN1" #define MICROPY_HW_CAN1_TX (pin_B9) // D10 #define MICROPY_HW_CAN1_RX (pin_B8) // D9 // The Feather has 1 LED #define MICROPY_HW_LED1 (pin_C1) // red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_B12) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // Bootloader configuration (only needed if Mboot is used) #define MBOOT_I2C_PERIPH_ID 1 #define MBOOT_I2C_SCL (pin_B8) #define MBOOT_I2C_SDA (pin_B9) #define MBOOT_I2C_ALTFUNC (4) micropython-1.12/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.mk000066400000000000000000000006631357706137100256710ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv ifeq ($(USE_MBOOT),1) # When using Mboot all the text goes together after the filesystem LD_FILES = boards/stm32f405.ld boards/common_blifs.ld TEXT0_ADDR = 0x08020000 else # When not using Mboot the ISR text goes first, then the rest after the filesystem LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 endif micropython-1.12/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/pins.csv000066400000000000000000000007371357706137100242160ustar00rootroot00000000000000POWER,3.3V GND,GND USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 SWDIO,PA13 SWCLK,PA14 FLASH_CS,PA15 BATTERY_MONITOR,PA3 A0,PA4 A1,PA5 A2,PA6 A3,PA7 USB_VBUS,PA9 TX,PB10 D1,PB10 RX,PB11 D0,PB11 SD_DETECT,PB12 SCK,PB13 MISO,PB14 MOSI,PB15 BOOT1,PB2 FLASH_SCK,PB3 FLASH_MISO,PB4 FLASH_MOSI,PB5 SCL,PB6 SDA,PB7 D9,PB8 D10,PB9 D8,PC0 NEOPIXEL,PC0 D13,PC1 SD_D2,PC10 SD_D3,PC11 SD_CK,PC12 D12,PC2 D11,PC3 A4,PC4 A5,PC5 D6,PC6 D5,PC7 SD_D0,PC8 SD_D1,PC9 SD_CMD,PD2 NC_A0,PA0 NC_A1,PA1 NC_A2,PA2 micropython-1.12/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/stm32f4xx_hal_conf.h000066400000000000000000000010451357706137100263050ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (12000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/B_L072Z_LRWAN1/000077500000000000000000000000001357706137100214565ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h000066400000000000000000000046431357706137100244500ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * MIT License; Copyright (c) 2019 Damien P. George */ #define MICROPY_HW_BOARD_NAME "B-L072Z-LRWAN1" #define MICROPY_HW_MCU_NAME "STM32L072CZ" #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_FRAMEBUF (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_ADC (0) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_HAS_SWITCH (1) // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) // USART2 is connected to the ST-LINK USB VCP #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A15) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // USER B1 has a pull-up and is active low #define MICROPY_HW_USRSW_PIN (pin_B2) #define MICROPY_HW_USRSW_PULL (0) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // 4 user LEDs #define MICROPY_HW_LED1 (pin_B5) // Green #define MICROPY_HW_LED2 (pin_A5) // Green (next to power LED) #define MICROPY_HW_LED3 (pin_B6) // Blue #define MICROPY_HW_LED4 (pin_B7) // Red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config (need to bridge SB15/SB16) #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_MSC (0) #define MICROPY_HW_USB_HID (0) #define USBD_CDC_RX_DATA_SIZE (256) #define USBD_CDC_TX_DATA_SIZE (256) micropython-1.12/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk000066400000000000000000000004471357706137100246260ustar00rootroot00000000000000MCU_SERIES = l0 CMSIS_MCU = STM32L072xx MICROPY_FLOAT_IMPL = none AF_FILE = boards/stm32l072_af.csv LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld # MicroPython settings MICROPY_VFS_FAT = 0 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= micropython-1.12/ports/stm32/boards/B_L072Z_LRWAN1/pins.csv000066400000000000000000000005501357706137100231440ustar00rootroot00000000000000D0,PA3 D1,PA2 D2,PA10 D3,PB13 D4,PB5 D5,PB7 D6,PB2 D7,PA8 D8,PA9 D9,PB12 D10,PB6 D11,PB15 D12,PB14 D13,PB13 D14,PB9 D15,PB8 A0,PA0 A2,PA4 USER_B1,PB2 LED2,PA5 LED1,PB5 LED3,PB6 LED4,PB7 LED_GREEN,PB5 LED_BLUE,PB6 LED_RED,PB7 ,PA0 ,PA2 ,PA3 ,PA4 ,PA5 ,PA6 ,PA7 ,PA8 ,PA9 ,PA10 ,PA11 ,PA12 ,PA13 ,PA14 ,PA15 ,PB2 ,PB5 ,PB6 ,PB7 ,PB8 ,PB9 ,PB12 ,PB13 ,PB14 ,PB15 micropython-1.12/ports/stm32/boards/B_L072Z_LRWAN1/stm32l0xx_hal_conf.h000066400000000000000000000007741357706137100252540ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H #include "boards/stm32l0xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/B_L475E_IOT01A/000077500000000000000000000000001357706137100213715ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h000066400000000000000000000050251357706137100243560ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "B-L475E-IOT01A" #define MICROPY_HW_MCU_NAME "STM32L475" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) // MSI is used and is 4MHz #define MICROPY_HW_CLK_PLLM (1) #define MICROPY_HW_CLK_PLLN (40) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV4) #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) // USART1 config connected to ST-Link #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) // USART2 config connected to PMOD: Flow control is defined and therfore used #define MICROPY_HW_UART2_CTS (pin_D3) #define MICROPY_HW_UART2_RTS (pin_D4) #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) // USART3 config for internal use #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) // USART4 config #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) // USART 1 is connected to the virtual com port on the ST-LINK #define MICROPY_HW_UART_REPL PYB_UART_1 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI2_NSS (pin_D0) #define MICROPY_HW_SPI2_SCK (pin_D1) #define MICROPY_HW_SPI2_MISO (pin_D3) #define MICROPY_HW_SPI2_MOSI (pin_D4) #define MICROPY_HW_SPI3_NSS (pin_A15) #define MICROPY_HW_SPI3_SCK (pin_C10) #define MICROPY_HW_SPI3_MISO (pin_C11) #define MICROPY_HW_SPI3_MOSI (pin_C12) // User and wake-up switch. Pressing the button makes the input go low. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED1 (pin_A5) // green #define MICROPY_HW_LED2 (pin_B14) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) micropython-1.12/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.mk000066400000000000000000000004441357706137100245360ustar00rootroot00000000000000MCU_SERIES = l4 CMSIS_MCU = STM32L475xx # The stm32l475 does not have a LDC controller which is # the only difference to the stm32l476 - so reuse some files. AF_FILE = boards/stm32l476_af.csv LD_FILES = boards/stm32l476xg.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg micropython-1.12/ports/stm32/boards/B_L475E_IOT01A/pins.csv000066400000000000000000000013141357706137100230560ustar00rootroot00000000000000PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA13,PA13 PA14,PA14 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 PH0,PH0 PH1,PH1 micropython-1.12/ports/stm32/boards/B_L475E_IOT01A/stm32l4xx_hal_conf.h000066400000000000000000000011201357706137100251550ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #include "boards/stm32l4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) #define EXTERNAL_SAI2_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/CERB40/000077500000000000000000000000001357706137100202725ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/CERB40/mpconfigboard.h000066400000000000000000000040051357706137100232540ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "Cerb40" #define MICROPY_HW_MCU_NAME "STM32F405RG" #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) // HSE is 12MHz #define MICROPY_HW_CLK_PLLM (12) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART3_RTS (pin_D12) #define MICROPY_HW_UART3_CTS (pin_D11) #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART5_TX (pin_C12) #define MICROPY_HW_UART5_RX (pin_D2) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) #define MICROPY_HW_I2C3_SCL (pin_A8) #define MICROPY_HW_I2C3_SDA (pin_C9) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI3_NSS (pin_A4) #define MICROPY_HW_SPI3_SCK (pin_B3) #define MICROPY_HW_SPI3_MISO (pin_B4) #define MICROPY_HW_SPI3_MOSI (pin_B5) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // The Cerb40 has No LEDs // The Cerb40 has No SDCard // USB config #define MICROPY_HW_USB_FS (1) //#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) //#define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) micropython-1.12/ports/stm32/boards/CERB40/mpconfigboard.mk000066400000000000000000000002561357706137100234400ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/CERB40/pins.csv000066400000000000000000000007651357706137100217700ustar00rootroot00000000000000JP1,3.3V JP2,GND JP3,PA8 JP4,PA13 JP5,PA7 JP6,PA6 JP7,PC10 JP8,PA14 JP9,PC11 JP10,PB4 JP11,PB9 JP12,PB3 JP13,PD2 JP14,PC12 JP15,VBAT JP16,PB8 JP17,Loader JP18,PB7 JP19,PB6 JP20,PB5 JP21,Reset JP22,PC0 JP23,PC1 JP24,PC2 JP25,PC3 JP26,PA0 JP27,PA1 JP28,PA2 JP29,PA3 JP30,PA4 JP31,PA5 JP32,PB10 JP33,PB11 JP34,PB14 JP35,PB15 JP36,PC6 JP37,PC7 JP38,PC8 JP39,PC9 JP40,VUSB UART1_TX,PA9 UART1_RX,PA10 UART3_TX,PD8 UART3_RX,PD9 UART3_RTS,PD12 UART3_CTS,PD11 CAN2_TX,PB13 CAN2_RX,PB12 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/CERB40/stm32f4xx_hal_conf.h000066400000000000000000000010451357706137100240560ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (12000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/ESPRUINO_PICO/000077500000000000000000000000001357706137100214715ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.h000066400000000000000000000044671357706137100244670ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "Espruino Pico" #define MICROPY_HW_MCU_NAME "STM32F401CD" #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SERVO (1) // Pico has an 8 MHz HSE and the F401 does 84 MHz max #define MICROPY_HW_CLK_PLLM (5) #define MICROPY_HW_CLK_PLLN (210) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV4) #define MICROPY_HW_CLK_PLLQ (7) // does not have a 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (0) // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART6_TX (pin_A11) #define MICROPY_HW_UART6_RX (pin_A12) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B3) #define MICROPY_HW_I2C3_SCL (pin_A8) #define MICROPY_HW_I2C3_SDA (pin_B4) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // BTN1 has no pullup or pulldown; it is active high and broken out on a header #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_PULLDOWN) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // Pico has 2 LEDs #define MICROPY_HW_LED1 (pin_B2) // red #define MICROPY_HW_LED2 (pin_B12) // green #define MICROPY_HW_LED3 (pin_B12) // green #define MICROPY_HW_LED4 (pin_B12) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) micropython-1.12/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.mk000066400000000000000000000004171357706137100246360ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F401xE AF_FILE = boards/stm32f401_af.csv LD_FILES = boards/stm32f401xd.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= micropython-1.12/ports/stm32/boards/ESPRUINO_PICO/pins.csv000066400000000000000000000004531357706137100231610ustar00rootroot00000000000000B3,PB3 B4,PB4 B5,PB5 B6,PB6 B7,PB7 A8,PA8 B8,PB8 B9,PB9 A10,PA10 A0,PA0 A1,PA1 A2,PA2 A3,PA3 A4,PA4 A5,PA5 A6,PA6 A7,PA7 B1,PB1 B10,PB10 B13,PB13 B14,PB14 B15,PB15 B0,PB0 SW,PC13 LED_RED,PB2 LED_GREEN,PB12 USB_VBUS,PA9 USB_DM,PA11 USB_DP,PA12 OSC32_IN,PC14 OSC32_OUT,PC15 NC1,PA13 NC2,PA14 NC3,PA15 micropython-1.12/ports/stm32/boards/ESPRUINO_PICO/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100252540ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/HYDRABUS/000077500000000000000000000000001357706137100206345ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/HYDRABUS/mpconfigboard.h000066400000000000000000000052451357706137100236250ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "HydraBus1.0" #define MICROPY_HW_MCU_NAME "STM32F4" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART3_RTS (pin_D12) #define MICROPY_HW_UART3_CTS (pin_D11) #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) #define MICROPY_HW_SPI3_NSS (pin_A4) #define MICROPY_HW_SPI3_SCK (pin_B3) #define MICROPY_HW_SPI3_MISO (pin_B4) #define MICROPY_HW_SPI3_MOSI (pin_B5) // USRSW/UBTN (Needs Jumper UBTN) is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // The HydraBus has 1 LED (Needs jumper on ULED) #define MICROPY_HW_LED1 (pin_A4) // green #define MICROPY_HW_LED2 (pin_A4) // same as LED1 #define MICROPY_HW_LED3 (pin_A4) // same as LED1 #define MICROPY_HW_LED4 (pin_A4) // same as LED1 #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch (not used, always on) #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (1) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) micropython-1.12/ports/stm32/boards/HYDRABUS/mpconfigboard.mk000066400000000000000000000002561357706137100240020ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/HYDRABUS/pins.csv000066400000000000000000000007421357706137100223250ustar00rootroot00000000000000PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 VUSB,PB13 USB1D_N,PB14 USB1D_P,PB15 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PD2,PD2 BOOT0,BOOT0 PA15,PA15 UART3_TX,PD8 UART3_RX,PD9 UART3_RTS,PD12 UART3_CTS,PD11 micropython-1.12/ports/stm32/boards/HYDRABUS/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100244170ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/LIMIFROG/000077500000000000000000000000001357706137100206235ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/LIMIFROG/board_init.c000066400000000000000000000124351357706137100231060ustar00rootroot00000000000000// The code is this file allows the user to enter DFU mode when the board // starts up, by connecting POS10 on the external connector to GND. // The code itself is taken from the LimiFrog software repository found at // https://github.com/LimiFrog/LimiFrog-SW, and the original license header // is copied below. #include STM32_HAL_H static void LBF_DFU_If_Needed(void); void LIMIFROG_board_early_init(void) { LBF_DFU_If_Needed(); } /******************************************************************************* * LBF_DFU_If_Needed.c * * (c)2015 LimiFrog / CYMEYA * This program is licensed under the terms of the MIT License. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. * Please refer to the License File LICENSE.txt located at the root of this * project for full licensing conditions, * or visit https://opensource.org/licenses/MIT. ******************************************************************************/ #define __LIMIFROG_02 /* ==== BTLE (excl UART) ======================================== */ // PC9 = BT_RST (active high) #define BT_RST_PIN GPIO_PIN_9 #define BT_RST_PORT GPIOC // Position 10 #ifdef __LIMIFROG_01 #define CONN_POS10_PIN GPIO_PIN_9 #define CONN_POS10_PORT GPIOB #else #define CONN_POS10_PIN GPIO_PIN_8 #define CONN_POS10_PORT GPIOB #endif static inline void GPIO_HIGH(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { GPIOx->BSRR = (uint32_t)GPIO_Pin; } static inline int IS_GPIO_RESET(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { GPIO_PinState bitstatus; if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET) { bitstatus = GPIO_PIN_SET; } else { bitstatus = GPIO_PIN_RESET; } return (bitstatus==GPIO_PIN_RESET); } /************************************************************** RATIONALE FOR THIS FUNCTION : - The STM32 embeds in ROM a bootloader that allows to obtain code and boot from a number of different interfaces, including USB in a mode called "DFU" (Device Frimware Update) [see AN3606 from ST for full details] This bootloader code is executed instead of the regular application code when pin BOOT0 is pulled-up (which on LimiFrog0.2 is achieved by pressing the general-purpose pushbutton switch on the side. - The bootloader monitors a number of IOs of the STM32 to decide from which interface it should boot. - Problem in LimiFrog (up to versions 0.2a at least): upon power-up the BLE modules generates some activity on UART3, which is part of the pins monitored by the STM32. This misleads the bootloader in trying to boot from UART3 and, as a result, not continuing with booting from USB. - This code implements an alternative solution to launch the bootloader while making sure UART3 remains stable. - The idea it to start application code with a check, prior to any other applicative code, of whether USB bootload is required (as flagged by a GPIO pulled low at reset, in the same way as BOOT0). The hadware reset pin of BLE is asserted (so that now it won't generate any acitivity on UART3), and if USB bootload is required : bootload ROM is remapped at address 0x0, stack pointer is updated and the code is branched to the start of the bootloader. - This code is run prior to any applicative configuration of clocks, IRQs etc. -- the STM32 is therefore still running from MSI THIS FUNCTION MAY BE SUPPRESSED IF YOU NEVER NEED TO BOOT DFU MODE ********************************************************************/ static void LBF_DFU_If_Needed(void) { GPIO_InitTypeDef GPIO_InitStruct; // Initialize and assert pin BTLE_RST // (hw reset to BLE module, so it won't drive UART3) __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Pin = BT_RST_PIN; HAL_GPIO_Init(BT_RST_PORT, &GPIO_InitStruct); GPIO_HIGH(BT_RST_PORT, BT_RST_PIN); // assert BTLE reset /* -- Bootloader will be called if position 10 on the extension port is actively pulled low -- */ // Note - this is an arbitrary choice, code could be modified to // monitor another GPIO of the STM32 and/or decide that active level // is high rather than low // Initialize Extension Port Position 10 = PB8 (bears I2C1_SCL) // Use weak pull-up to detect if pin is externally pulled low __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Pin = CONN_POS10_PIN; HAL_GPIO_Init(CONN_POS10_PORT, &GPIO_InitStruct); // If selection pin pulled low... if ( IS_GPIO_RESET(CONN_POS10_PORT, CONN_POS10_PIN )) { // Remap bootloader ROM (ie System Flash) to address 0x0 SYSCFG->MEMRMP = 0x00000001; // Init stack pointer with value residing at ROM base asm ( "LDR R0, =0x00000000\n\t" // load ROM base address" "LDR SP,[R0, #0]\n\t" // assign main stack pointer" ); // Jump to address pointed by 0x00000004 -- */ asm ( "LDR R0,[R0, #4]\n\t" // load bootloader address "BX R0\n\t" ); } } micropython-1.12/ports/stm32/boards/LIMIFROG/mpconfigboard.h000066400000000000000000000035371357706137100236160ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "LIMIFROG" #define MICROPY_HW_MCU_NAME "STM32L476" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_BOARD_EARLY_INIT LIMIFROG_board_early_init void LIMIFROG_board_early_init(void); // MSI is used and is 4MHz #define MICROPY_HW_CLK_PLLM (1) #define MICROPY_HW_CLK_PLLN (40) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) // USART config #define MICROPY_HW_UART3_TX (pin_C10) #define MICROPY_HW_UART3_RX (pin_C11) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI3_NSS (pin_A15) #define MICROPY_HW_SPI3_SCK (pin_B3) #define MICROPY_HW_SPI3_MISO (pin_B4) #define MICROPY_HW_SPI3_MOSI (pin_B5) #define MICROPY_HW_USRSW_PIN (pin_A15) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_C3) // red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) // #define MICROPY_HW_USB_OTG_ID_PIN (pin_C12) // This is not the official ID Pin which should be PA10 micropython-1.12/ports/stm32/boards/LIMIFROG/mpconfigboard.mk000066400000000000000000000002021357706137100237600ustar00rootroot00000000000000MCU_SERIES = l4 CMSIS_MCU = STM32L476xx AF_FILE = boards/stm32l476_af.csv LD_FILES = boards/stm32l476xe.ld boards/common_basic.ld micropython-1.12/ports/stm32/boards/LIMIFROG/pins.csv000066400000000000000000000017441357706137100223170ustar00rootroot00000000000000PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA13,PA13 PA14,PA14 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 PF0,PF0 PF1,PF1 PF2,PF2 PF3,PF3 PF4,PF4 PF5,PF5 PF6,PF6 PF7,PF7 PF8,PF8 PF9,PF9 PF10,PF10 PF11,PF11 PF12,PF12 PF13,PF13 PF14,PF14 PF15,PF15 PG0,PG0 PG1,PG1 PG2,PG2 PG3,PG3 PG4,PG4 PG5,PG5 PG6,PG6 PG7,PG7 PG8,PG8 PG9,PG9 PG10,PG10 PG11,PG11 PG12,PG12 PG13,PG13 PG14,PG14 PG15,PG15 PH0,PH0 PH1,PH1 micropython-1.12/ports/stm32/boards/LIMIFROG/stm32l4xx_hal_conf.h000066400000000000000000000011201357706137100244070ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #include "boards/stm32l4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) #define EXTERNAL_SAI2_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/MIKROE_CLICKER2_STM32/000077500000000000000000000000001357706137100225075ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h000066400000000000000000000060371357706137100255000ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "MIKROE_CLICKER2_STM32" #define MICROPY_HW_MCU_NAME "STM32F407" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) // HSE is 25MHz #define MICROPY_HW_CLK_PLLM (25) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) #define MICROPY_HW_CLK_LAST_FREQ (1) // The board has a 32kHz crystal for the RTC #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (0) // turn on/off PC13 512Hz output // UART config // mikroBUS slot 1 #define MICROPY_HW_UART2_NAME "SLOT1" #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) // mikroBUS slot 2 #define MICROPY_HW_UART3_NAME "SLOT2" #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) // HDR2 #define MICROPY_HW_UART4_NAME "HDR2" #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) // I2C buses // mikroBUS slot 2 / HDR2 #define MICROPY_HW_I2C2_NAME "SLOT2" #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // mikroBUS slot 1 #define MICROPY_HW_I2C3_NAME "SLOT1" #define MICROPY_HW_I2C3_SCL (pin_A8) #define MICROPY_HW_I2C3_SDA (pin_C9) // SPI buses // mikroBUS slot 2 / HDR1 #define MICROPY_HW_SPI2_NAME "SLOT2" #define MICROPY_HW_SPI2_NSS (pin_E11) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // mikroBUS slot 1 #define MICROPY_HW_SPI3_NAME "SLOT1" #define MICROPY_HW_SPI3_NSS (pin_E8) #define MICROPY_HW_SPI3_SCK (pin_C10) #define MICROPY_HW_SPI3_MISO (pin_C11) #define MICROPY_HW_SPI3_MOSI (pin_C12) // USRSW is pulled high; pressing the button makes the input go low #define MICROPY_HW_USRSW_PIN (pin_E0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED1 (pin_E12) // red #define MICROPY_HW_LED2 (pin_E15) // red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) // Bootloader configuration (only needed if Mboot is used) #define MBOOT_I2C_PERIPH_ID 2 #define MBOOT_I2C_SCL (pin_B10) #define MBOOT_I2C_SDA (pin_B11) #define MBOOT_I2C_ALTFUNC (4) #define MBOOT_BOOTPIN_PIN (pin_A10) #define MBOOT_BOOTPIN_PULL (MP_HAL_PIN_PULL_NONE) #define MBOOT_BOOTPIN_ACTIVE (0) #define MBOOT_FSLOAD (1) micropython-1.12/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.mk000066400000000000000000000006631357706137100256570ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F407xx AF_FILE = boards/stm32f405_af.csv ifeq ($(USE_MBOOT),1) # When using Mboot all the text goes together after the filesystem LD_FILES = boards/stm32f405.ld boards/common_blifs.ld TEXT0_ADDR = 0x08020000 else # When not using Mboot the ISR text goes first, then the rest after the filesystem LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 endif micropython-1.12/ports/stm32/boards/MIKROE_CLICKER2_STM32/pins.csv000066400000000000000000000016721357706137100242030ustar00rootroot00000000000000MB1_AN,PA2 MB1_RST,PE7 MB1_CS,PE8 MB1_SCK,PC10 MB1_MISO,PC11 MB1_MOSI,PC12 MB1_PWM,PE9 MB1_INT,PE10 MB1_RX,PD6 MB1_TX,PD5 MB1_SCL,PA8 MB1_SDA,PC9 MB2_AN,PA3 MB2_RST,PE13 MB2_CS,PE11 MB2_SCK,PB13 MB2_MISO,PB14 MB2_MOSI,PB15 MB2_PWM,PD12 MB2_INT,PE14 MB2_RX,PD9 MB2_TX,PD8 MB2_SCL,PB10 MB2_SDA,PB11 PIN1,VSYS PIN2,GND PIN3,PC0 PIN4,PC1 PIN5,PC2 PIN6,PC3 PIN7,PB1 PIN8,PA4 PIN9,PC4 PIN10,PD3 PIN11,PD1 PIN12,PD2 PIN13,PD0 PIN14,PC8 PIN15,PD15 PIN16,PD14 PIN17,PD13 PIN18,PB7 PIN19,PC7 PIN20,PD11 PIN21,PD10 PIN22,PB13 PIN23,PB14 PIN24,PB15 PIN25,3.3V PIN26,GND PIN27,RST PIN28,GND PIN30,NC PIN31,PB9 PIN32,PB8 PIN33,PE5 PIN34,PB0 PIN35,PA5 PIN36,PA6 PIN37,PA7 PIN38,PE1 PIN39,PE2 PIN40,PE3 PIN41,PE4 PIN42,PE6 PIN43,PB6 PIN44,PB5 PIN45,PD7 PIN46,PC13 PIN47,PA1 PIN48,PA0 PIN49,PB10 PIN50,PB11 PIN51,3.3V PIN52,GND OSC32_OUT,PC15 OSC32_IN,PC14 VSENSE,PC5 SENSEL,PB12 FAULT,PC6 BATSTAT,PD4 LD1,PE12 LD2,PE15 T2,PE0 T3,PA10 USB_VBUS,PA9 USB_DM,PA11 USB_DP,PA12micropython-1.12/ports/stm32/boards/MIKROE_CLICKER2_STM32/stm32f4xx_hal_conf.h000066400000000000000000000010451357706137100262730ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (25000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NADHAT_PYBF405/000077500000000000000000000000001357706137100214235ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.h000066400000000000000000000101171357706137100244060ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NADHAT_PYBF405" #define MICROPY_HW_MCU_NAME "STM32F405RG" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_HAS_KXTJ3 (1) #define MICROPY_HW_HAS_LCD (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 16MHz #define MICROPY_HW_CLK_PLLM (16) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) #define MICROPY_HW_CLK_LAST_FREQ (1) // The board has a 32kHz crystal for the RTC #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (1) // UART config #define MICROPY_HW_UART1_NAME "XB" #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_NAME "YB" #define MICROPY_HW_UART3_TX (pin_B10) #define MICROPY_HW_UART3_RX (pin_B11) #define MICROPY_HW_UART3_RTS (pin_B14) #define MICROPY_HW_UART3_CTS (pin_B13) #define MICROPY_HW_UART4_NAME "XA" #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART6_NAME "YA" #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C buses #define MICROPY_HW_I2C1_NAME "X" #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_NAME "Y" #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI buses #define MICROPY_HW_SPI1_NAME "X" #define MICROPY_HW_SPI1_NSS (pin_A4) // X5 #define MICROPY_HW_SPI1_SCK (pin_A5) // X6 #define MICROPY_HW_SPI1_MISO (pin_A6) // X7 #define MICROPY_HW_SPI1_MOSI (pin_A7) // X8 #define MICROPY_HW_SPI2_NAME "Y" #define MICROPY_HW_SPI2_NSS (pin_B12) // Y5 #define MICROPY_HW_SPI2_SCK (pin_B13) // Y6 #define MICROPY_HW_SPI2_MISO (pin_B14) // Y7 #define MICROPY_HW_SPI2_MOSI (pin_B15) // Y8 // CAN buses #define MICROPY_HW_CAN1_NAME "YA" #define MICROPY_HW_CAN1_TX (pin_B9) // Y4 #define MICROPY_HW_CAN1_RX (pin_B8) // Y3 #define MICROPY_HW_CAN2_NAME "YB" #define MICROPY_HW_CAN2_TX (pin_B13) // Y6 #define MICROPY_HW_CAN2_RX (pin_B12) // Y5 // USRSW has no pullup or pulldown, and pressing the switch makes the input go low #define MICROPY_HW_USRSW_PIN (pin_B3) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // The board has 4 LEDs #define MICROPY_HW_LED1 (pin_A13) // red #define MICROPY_HW_LED2 (pin_A14) // green #define MICROPY_HW_LED3 (pin_A15) // yellow #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // Bootloader configuration (only needed if Mboot is used) #define MBOOT_I2C_PERIPH_ID 1 #define MBOOT_I2C_SCL (pin_B8) #define MBOOT_I2C_SDA (pin_B9) #define MBOOT_I2C_ALTFUNC (4) micropython-1.12/ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.mk000066400000000000000000000006631357706137100245730ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv ifeq ($(USE_MBOOT),1) # When using Mboot all the text goes together after the filesystem LD_FILES = boards/stm32f405.ld boards/common_blifs.ld TEXT0_ADDR = 0x08020000 else # When not using Mboot the ISR text goes first, then the rest after the filesystem LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 endif micropython-1.12/ports/stm32/boards/NADHAT_PYBF405/pins.csv000066400000000000000000000010051357706137100231050ustar00rootroot00000000000000X1,PA0 X2,PA1 X3,PA2 X4,PA3 X5,PA4 X6,PA5 X7,PA6 X8,PA7 X9,PB6 X10,PB7 X11,PC4 X12,PC5 X13,Reset X14,GND X15,3.3V X16,VIN X17,PB3 X18,PC13 X19,PC0 X20,PC1 X21,PC2 X22,PC3 X23,A3.3V X24,AGND Y1,PC6 Y2,PC7 Y3,PB8 Y4,PB9 Y5,PB12 Y6,PB13 Y7,PB14 Y8,PB15 Y9,PB10 Y10,PB11 Y11,PB0 Y12,PB1 Y13,PB2 Y14,GND Y15,3.3V Y16,VIN SW,PB3 LED_RED,PA13 LED_GREEN,PA14 LED_YELLOW,PA15 LED_BLUE,PB4 NC,PB5 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD,PA8 SD_SW,PA8 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/NADHAT_PYBF405/stm32f4xx_hal_conf.h000066400000000000000000000010451357706137100252070ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (16000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NETDUINO_PLUS_2/000077500000000000000000000000001357706137100217245ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NETDUINO_PLUS_2/board_init.c000066400000000000000000000014311357706137100242010ustar00rootroot00000000000000#include STM32_HAL_H void NETDUINO_PLUS_2_board_early_init(void) { __HAL_RCC_GPIOB_CLK_ENABLE(); // Turn off the backlight. LCD_BL_CTRL = PK3 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_PULLUP; #if MICROPY_HW_ENABLE_SDCARD // Turn on the power enable for the sdcard (PB1) GPIO_InitStructure.Pin = GPIO_PIN_1; HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); #endif // Turn on the power for the 5V on the expansion header (PB2) GPIO_InitStructure.Pin = GPIO_PIN_2; HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); } micropython-1.12/ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.h000066400000000000000000000046471357706137100247220ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NetduinoPlus2" #define MICROPY_HW_MCU_NAME "STM32F405RG" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) // On the netuino, the sdcard appears to be wired up as a 1-bit // SPI, so the driver needs to be converted to support that before // we can turn this on. #define MICROPY_HW_ENABLE_SDCARD (0) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SERVO (1) void NETDUINO_PLUS_2_board_early_init(void); #define MICROPY_BOARD_EARLY_INIT NETDUINO_PLUS_2_board_early_init // HSE is 25MHz #define MICROPY_HW_CLK_PLLM (25) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART3_RTS (pin_D12) #define MICROPY_HW_UART3_CTS (pin_D11) #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART5_TX (pin_C12) #define MICROPY_HW_UART5_RX (pin_D2) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) // SPI busses #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_B11) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_A10) // Blue LED #define MICROPY_HW_LED2 (pin_C13) // White LED (aka Power) #define MICROPY_HW_LED3 (pin_A10) // Same as Led(1) #define MICROPY_HW_LED4 (pin_C13) // Same as Led(2) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) micropython-1.12/ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.mk000066400000000000000000000002561357706137100250720ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/NETDUINO_PLUS_2/pins.csv000066400000000000000000000005361357706137100234160ustar00rootroot00000000000000D0,PC7 D1,PC6 D2,PA3 D3,PA2 D4,PB12 D5,PB8 D6,PB9 D7,PA1 D8,PA0 D9,PA6 D10,PB10 D11,PB15 D12,PB14 D13,PB13 SDA,PB6 SCL,PB7 A0,PC0 A1,PC1 A2,PC2 A3,PC3 A4,PC4 A5,PC5 LED,PA10 SW,PB11 PWR_LED,PC13 PWR_SD,PB1 PWR_HDR,PB2 PWR_ETH,PC15 RST_ETH,PD2 UART1_TX,PA9 UART3_TX,PD8 UART3_RX,PD9 UART3_RTS,PD12 UART3_CTS,PD11 UART5_TX,PC12 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/NETDUINO_PLUS_2/stm32f4xx_hal_conf.h000066400000000000000000000010451357706137100255100ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (25000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F091RC/000077500000000000000000000000001357706137100213245ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h000066400000000000000000000063431357706137100243150ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-F091RC" #define MICROPY_HW_MCU_NAME "STM32F091RCT6" #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_ADC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_TIMER (1) #define MICROPY_HW_HAS_SWITCH (1) // For system clock, enable one source: //#define MICROPY_HW_CLK_USE_HSI (1) // internal 8MHz -> PLL = 48MHz. #define MICROPY_HW_CLK_USE_HSI48 (1) // internal 48MHz. //#define MICROPY_HW_CLK_USE_HSE (1) // external crystal -> PLL = 48MHz. // For HSE set the crystal / clock input frequency HSE_VALUE in stm32f0xx_hal_conf.h #if MICROPY_HW_CLK_USE_HSE #define MICROPY_HW_CLK_USE_BYPASS (1) // HSE comes from STLINK 8MHz, not crystal. #endif // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART3_TX (pin_C10) #define MICROPY_HW_UART3_RX (pin_C11) #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART5_TX (pin_B3) #define MICROPY_HW_UART5_RX (pin_B4) #define MICROPY_HW_UART6_TX (pin_C0) #define MICROPY_HW_UART6_RX (pin_C1) #define MICROPY_HW_UART7_TX (pin_C6) #define MICROPY_HW_UART7_RX (pin_C7) #define MICROPY_HW_UART8_TX (pin_C2) #define MICROPY_HW_UART8_RX (pin_C3) // USART2 is connected to the ST-LINK USB VCP #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 #define MICROPY_HW_I2C1_SDA (pin_B9) // Arduino D14, pin 5 on CN10 #define MICROPY_HW_I2C2_SCL (pin_B10) // Arduino D6, pin 25 on CN10 #define MICROPY_HW_I2C2_SDA (pin_B11) // pin 18 on CN10 // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 #define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 #define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 #define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 #define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 #define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 #define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 #define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 // USER B1 has a pull-up and is active low #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (0) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // NUCLEO-64 has one user LED #define MICROPY_HW_LED1 (pin_A5) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) micropython-1.12/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk000066400000000000000000000004151357706137100244670ustar00rootroot00000000000000MCU_SERIES = f0 CMSIS_MCU = STM32F091xC AF_FILE = boards/stm32f091_af.csv LD_FILES = boards/stm32f091xc.ld boards/common_basic.ld # MicroPython settings MICROPY_VFS_FAT = 0 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= micropython-1.12/ports/stm32/boards/NUCLEO_F091RC/pins.csv000066400000000000000000000013431357706137100230130ustar00rootroot00000000000000D0,PA3 D1,PA2 D2,PA10 D3,PB3 D4,PB5 D5,PB4 D6,PB10 D7,PA8 D8,PA9 D9,PC7 D10,PB6 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 A0,PA0 A1,PA1 A2,PA4 A3,PB0 A4,PC1 A5,PC0 RX,PA3 TX,PA2 SCL,PB8 SDA,PB9 SCK,PA5 MISO,PA6 MOSI,PA7 CS,PB6 BOOT0,PF11 SWDIO,PA13 SWCLK,PA14 USER_B1,PC13 LED_GREEN,PA5 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA13,PA13 PA14,PA14 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD2,PD2 PF0,PF0 PF1,PF1 PF11,PF11 micropython-1.12/ports/stm32/boards/NUCLEO_F091RC/stm32f0xx_hal_conf.h000066400000000000000000000007741357706137100251140ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F0XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F0XX_HAL_CONF_H #include "boards/stm32f0xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F0XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F401RE/000077500000000000000000000000001357706137100213215ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F401RE/mpconfigboard.h000066400000000000000000000055551357706137100243160ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-F401RE" #define MICROPY_HW_MCU_NAME "STM32F401xE" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) // HSE is 8MHz, HSI is 16MHz CPU freq set to 84MHz // Default source for the clock is HSI. // For revisions of the board greater than C-01, HSE can be used as a // clock source by removing the #define MICROPY_HW_CLK_USE_HSE line #define MICROPY_HW_CLK_USE_HSI (1) #if MICROPY_HW_CLK_USE_HSI #define MICROPY_HW_CLK_PLLM (16) #else #define MICROPY_HW_CLK_PLLM (8) #endif #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV4) #define MICROPY_HW_CLK_PLLQ (7) // UART config #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // UART 2 connects to the STM32F103 (STLINK) on the Nucleo board // and this is exposed as a USB Serial port. #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 #define MICROPY_HW_I2C1_SDA (pin_B9) // D14, pin 5 on CN10 #define MICROPY_HW_I2C2_SCL (pin_B10) // Arduino D6, pin 25 on CN10 #define MICROPY_HW_I2C2_SDA (pin_B3) // Arduino D3, pin 31 on CN10 #define MICROPY_HW_I2C3_SCL (pin_A8) // Arduino D7, pin 23 on CN10 #define MICROPY_HW_I2C3_SDA (pin_C9) // pin 1 on CN10 // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 #define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 #define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 #define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 #define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 #define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 #define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 #define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 #define MICROPY_HW_SPI3_NSS (pin_A4) // Arduino A2, pin 32 on CN7 #define MICROPY_HW_SPI3_SCK (pin_B3) // Arduino D3, pin 31 on CN10 #define MICROPY_HW_SPI3_MISO (pin_B4) // Arduino D5, pin 27 on CN10 #define MICROPY_HW_SPI3_MOSI (pin_B5) // Arduino D4, pin 29 on CN10 // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED1 (pin_A5) // Green LD2 LED on Nucleo #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) micropython-1.12/ports/stm32/boards/NUCLEO_F401RE/mpconfigboard.mk000066400000000000000000000002601357706137100244620ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F401xE AF_FILE = boards/stm32f401_af.csv LD_FILES = boards/stm32f401xe.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/NUCLEO_F401RE/pins.csv000066400000000000000000000011761357706137100230140ustar00rootroot00000000000000D0,PA3 D1,PA2 D2,PA10 D3,PB3 D4,PB5 D5,PB4 D6,PB10 D7,PA8 D8,PA9 D9,PC7 D10,PB6 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 A0,PA0 A1,PA1 A2,PA4 A3,PB0 A4,PC1 A5,PC0 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD2,PD2 PH0,PH0 PH1,PH1 LED_GREEN,PA5 LED_ORANGE,PA5 LED_RED,PA5 LED_BLUE,PA4 SW,PC13 micropython-1.12/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100251040ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F411RE/000077500000000000000000000000001357706137100213225ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F411RE/mpconfigboard.h000066400000000000000000000062321357706137100243100ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-F411RE" #define MICROPY_HW_MCU_NAME "STM32F411xE" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) // HSE is 8MHz, CPU freq set to 96MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (192) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (4) // UART config #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // UART 2 connects to the STM32F103 (STLINK) on the Nucleo board // and this is exposed as a USB Serial port. #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 #define MICROPY_HW_I2C1_SDA (pin_B9) // D14, pin 5 on CN10 #define MICROPY_HW_I2C2_SCL (pin_B10) // Arduino D6, pin 25 on CN10 #define MICROPY_HW_I2C2_SDA (pin_B3) // Arduino D3, pin 31 on CN10 #define MICROPY_HW_I2C3_SCL (pin_A8) // Arduino D7, pin 23 on CN10 #define MICROPY_HW_I2C3_SDA (pin_C9) // pin 1 on CN10 // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 #define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 #define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 #define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 #define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 #define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 #define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 #define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 #define MICROPY_HW_SPI3_NSS (pin_A4) // Arduino A2, pin 32 on CN7 #define MICROPY_HW_SPI3_SCK (pin_B3) // Arduino D3, pin 31 on CN10 #define MICROPY_HW_SPI3_MISO (pin_B4) // Arduino D5, pin 27 on CN10 #define MICROPY_HW_SPI3_MOSI (pin_B5) // Arduino D4, pin 29 on CN10 #define MICROPY_HW_SPI4_NSS (pin_B12) // pin 16 on CN10 #define MICROPY_HW_SPI4_SCK (pin_B13) // pin 30 on CN10 #define MICROPY_HW_SPI4_MISO (pin_A1) // pin 30 on CN7 #define MICROPY_HW_SPI4_MOSI (pin_A11) // pin 14 on CN10 #define MICROPY_HW_SPI5_NSS (pin_B1) // pin 24 on CN10 #define MICROPY_HW_SPI5_SCK (pin_A10) // pin 33 on CN10 #define MICROPY_HW_SPI5_MISO (pin_A12) // pin 12 on CN10 #define MICROPY_HW_SPI5_MOSI (pin_B0) // pin 34 on CN7 // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED1 (pin_A5) // Green LD2 LED on Nucleo #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) micropython-1.12/ports/stm32/boards/NUCLEO_F411RE/mpconfigboard.mk000066400000000000000000000002561357706137100244700ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F411xE AF_FILE = boards/stm32f411_af.csv LD_FILES = boards/stm32f411.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/NUCLEO_F411RE/pins.csv000066400000000000000000000011761357706137100230150ustar00rootroot00000000000000D0,PA3 D1,PA2 D2,PA10 D3,PB3 D4,PB5 D5,PB4 D6,PB10 D7,PA8 D8,PA9 D9,PC7 D10,PB6 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 A0,PA0 A1,PA1 A2,PA4 A3,PB0 A4,PC1 A5,PC0 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD2,PD2 PH0,PH0 PH1,PH1 LED_GREEN,PA5 LED_ORANGE,PA5 LED_RED,PA5 LED_BLUE,PA4 SW,PC13 micropython-1.12/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100251050ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F413ZH/000077500000000000000000000000001357706137100213375ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h000066400000000000000000000075461357706137100243360ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-F413ZH" #define MICROPY_HW_MCU_NAME "STM32F413" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) // HSE is 8MHz, CPU freq set to 96MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (192) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (4) // For 2.7 to 3.6 V, 75 to 100 MHz: 3 wait states. #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_3 // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B3) // shared with CAN3 #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART4_TX (pin_D1) #define MICROPY_HW_UART4_RX (pin_D0) #define MICROPY_HW_UART5_TX (pin_C12) #define MICROPY_HW_UART5_RX (pin_D2) #define MICROPY_HW_UART6_TX (pin_G14) #define MICROPY_HW_UART6_RX (pin_G9) #define MICROPY_HW_UART7_TX (pin_E8) #define MICROPY_HW_UART7_RX (pin_E7) #define MICROPY_HW_UART8_TX (pin_E1) #define MICROPY_HW_UART8_RX (pin_E0) #define MICROPY_HW_UART9_TX (pin_D15) #define MICROPY_HW_UART9_RX (pin_D14) #define MICROPY_HW_UART10_TX (pin_E3) #define MICROPY_HW_UART10_RX (pin_E2) #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_F1) #define MICROPY_HW_I2C2_SDA (pin_F0) #define MICROPY_HW_I2C3_SCL (pin_A8) #define MICROPY_HW_I2C3_SDA (pin_C9) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) // shared with DAC #define MICROPY_HW_SPI1_SCK (pin_A5) // shared with DAC #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_C7) #define MICROPY_HW_SPI2_MISO (pin_C2) #define MICROPY_HW_SPI2_MOSI (pin_C3) #define MICROPY_HW_SPI3_NSS (pin_A15) #define MICROPY_HW_SPI3_SCK (pin_C10) #define MICROPY_HW_SPI3_MISO (pin_C11) #define MICROPY_HW_SPI3_MOSI (pin_B5) #define MICROPY_HW_SPI4_NSS (pin_E4) #define MICROPY_HW_SPI4_SCK (pin_B13) #define MICROPY_HW_SPI4_MISO (pin_E5) #define MICROPY_HW_SPI4_MOSI (pin_E6) #define MICROPY_HW_SPI5_NSS (pin_E11) #define MICROPY_HW_SPI5_SCK (pin_E12) #define MICROPY_HW_SPI5_MISO (pin_E13) #define MICROPY_HW_SPI5_MOSI (pin_E14) // CAN busses #define MICROPY_HW_CAN1_TX (pin_G1) #define MICROPY_HW_CAN1_RX (pin_G0) #define MICROPY_HW_CAN2_TX (pin_G12) #define MICROPY_HW_CAN2_RX (pin_G11) #define MICROPY_HW_CAN3_TX (pin_B4) #define MICROPY_HW_CAN3_RX (pin_B3) // shared with UART1 or use pin_A8 shared with I2C3 // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_B14) // red #define MICROPY_HW_LED2 (pin_B0) // green #define MICROPY_HW_LED3 (pin_B7) // blue #define MICROPY_HW_LED1_PWM { TIM12, 12, TIM_CHANNEL_1, GPIO_AF9_TIM12 } #define MICROPY_HW_LED2_PWM { TIM3, 3, TIM_CHANNEL_3, GPIO_AF2_TIM3 } #define MICROPY_HW_LED3_PWM { TIM4, 4, TIM_CHANNEL_2, GPIO_AF2_TIM4 } #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config (CN13 - USB OTG FS) #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) micropython-1.12/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk000066400000000000000000000002601357706137100245000ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F413xx AF_FILE = boards/stm32f413_af.csv LD_FILES = boards/stm32f413xh.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08060000 micropython-1.12/ports/stm32/boards/NUCLEO_F413ZH/pins.csv000066400000000000000000000020201357706137100230170ustar00rootroot00000000000000PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA13,PA13 PA14,PA14 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 PF0,PF0 PF1,PF1 PF2,PF2 PF3,PF3 PF4,PF4 PF5,PF5 PF6,PF6 PF7,PF7 PF8,PF8 PF9,PF9 PF10,PF10 PF11,PF11 PF12,PF12 PF13,PF13 PF14,PF14 PF15,PF15 PG0,PG0 PG1,PG1 PG2,PG2 PG3,PG3 PG4,PG4 PG5,PG5 PG6,PG6 PG7,PG7 PG8,PG8 PG9,PG9 PG10,PG10 PG11,PG11 PG12,PG12 PG13,PG13 PG14,PG14 PG15,PG15 PH0,PH0 PH1,PH1 SW,C13 LED_RED,B14 LED_GREEN,B0 LED_BLUE,B7 micropython-1.12/ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100251220ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F429ZI/000077500000000000000000000000001357706137100213475ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h000066400000000000000000000060251357706137100243350ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-F429ZI" #define MICROPY_HW_MCU_NAME "STM32F429" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // From the reference manual, for 2.7V to 3.6V // 151-180 MHz => 5 wait states // 181-210 MHz => 6 wait states // 211-216 MHz => 7 wait states #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_6 // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_C11) #define MICROPY_HW_UART5_TX (pin_C12) #define MICROPY_HW_UART5_RX (pin_D2) #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C3_SCL (pin_A8) #define MICROPY_HW_I2C3_SDA (pin_C9) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_B3) #define MICROPY_HW_SPI1_MISO (pin_B4) #define MICROPY_HW_SPI1_MOSI (pin_B5) #define MICROPY_HW_SPI4_NSS (pin_E4) #define MICROPY_HW_SPI4_SCK (pin_E2) #define MICROPY_HW_SPI4_MISO (pin_E5) #define MICROPY_HW_SPI4_MOSI (pin_E6) #define MICROPY_HW_SPI5_NSS (pin_F6) #define MICROPY_HW_SPI5_SCK (pin_F7) #define MICROPY_HW_SPI5_MISO (pin_F8) #define MICROPY_HW_SPI5_MOSI (pin_F9) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_B0) // green #define MICROPY_HW_LED2 (pin_B7) // blue #define MICROPY_HW_LED3 (pin_B14) // red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config (CN13 - USB OTG FS) #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // Ethernet via RMII #define MICROPY_HW_ETH_MDC (pin_C1) #define MICROPY_HW_ETH_MDIO (pin_A2) #define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1) #define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7) #define MICROPY_HW_ETH_RMII_RXD0 (pin_C4) #define MICROPY_HW_ETH_RMII_RXD1 (pin_C5) #define MICROPY_HW_ETH_RMII_TX_EN (pin_G11) #define MICROPY_HW_ETH_RMII_TXD0 (pin_G13) #define MICROPY_HW_ETH_RMII_TXD1 (pin_B13) micropython-1.12/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk000066400000000000000000000004061357706137100245120ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F429xx AF_FILE = boards/stm32f429_af.csv LD_FILES = boards/stm32f429.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 micropython-1.12/ports/stm32/boards/NUCLEO_F429ZI/pins.csv000066400000000000000000000022471357706137100230420ustar00rootroot00000000000000PF4,PF4 PF5,PF5 PF2,PF2 PF3,PF3 PF0,PF0 PF1,PF1 PC14,PC14 PC15,PC15 PE6,PE6 PC13,PC13 PE4,PE4 PE5,PE5 PE2,PE2 PE3,PE3 PE0,PE0 PE1,PE1 PB8,PB8 PB9,PB9 PB6,PB6 PB7,PB7 PB4,PB4 PB5,PB5 PG15,PG15 PB3,PB3 PG13,PG13 PG14,PG14 PG11,PG11 PG12,PG12 PG9,PG9 PG10,PG10 PD7,PD7 PD6,PD6 PD5,PD5 PD4,PD4 PD3,PD3 PD2,PD2 PD1,PD1 PD0,PD0 PC12,PC12 PC11,PC11 PC10,PC10 PA15,PA15 PA14,PA14 PA13,PA13 PA12,PA12 PA11,PA11 PA10,PA10 PA9,PA9 PA8,PA8 PC9,PC9 PC8,PC8 PC7,PC7 PC6,PC6 PG8,PG8 PG7,PG7 PG6,PG6 PG5,PG5 PG4,PG4 PF6,PF6 PF8,PF8 PF7,PF7 PF10,PF10 PF9,PF9 PH1,PH1 PH0,PH0 PC1,PC1 PC0,PC0 PC3,PC3 PC2,PC2 PA1,PA1 PA0,PA0 PA3,PA3 PA2,PA2 PA5,PA5 PA4,PA4 PA7,PA7 PA6,PA6 PC5,PC5 PC4,PC4 PB1,PB1 PB0,PB0 PB2,PB2 PF12,PF12 PF11,PF11 PF14,PF14 PF13,PF13 PG0,PG0 PF15,PF15 PE7,PE7 PG1,PG1 PE9,PE9 PE8,PE8 PE11,PE11 PE10,PE10 PE13,PE13 PE12,PE12 PE15,PE15 PE14,PE14 PB11,PB11 PB10,PB10 PB13,PB13 PB12,PB12 PB15,PB15 PB14,PB14 PD9,PD9 PD8,PD8 PD11,PD11 PD10,PD10 PD13,PD13 PD12,PD12 PD15,PD15 PD14,PD14 PG3,PG3 PG2,PG2 SW,PA0 LED_GREEN,PG13 LED_RED,PG14 ETH_MDC,PC1 ETH_MDIO,PA2 ETH_RMII_REF_CLK,PA1 ETH_RMII_CRS_DV,PA7 ETH_RMII_RXD0,PC4 ETH_RMII_RXD1,PC5 ETH_RMII_TX_EN,PG11 ETH_RMII_TXD0,PG13 ETH_RMII_TXD1,PB13 micropython-1.12/ports/stm32/boards/NUCLEO_F429ZI/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100251320ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F446RE/000077500000000000000000000000001357706137100213325ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h000066400000000000000000000060451357706137100243220ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-F446RE" #define MICROPY_HW_MCU_NAME "STM32F446xx" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) // HSE is 8MHz, CPU freq set to 168MHz. Using PLLQ for USB this gives a nice // 48 MHz clock for USB. To goto 180 MHz, I think that USB would need to be // configured to use PLLSAI #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // UART config #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // UART 2 connects to the STM32F103 (STLINK) on the Nucleo board // and this is exposed as a USB Serial port. #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B6) // Arduino D10, pin 17 on CN10 #define MICROPY_HW_I2C1_SDA (pin_B7) // pin 21 on CN7 #define MICROPY_HW_I2C2_SCL (pin_B10) // Arduino D6, pin 25 on CN10 #define MICROPY_HW_I2C2_SDA (pin_B3) // Arduino D3, pin 31 on CN10 #define MICROPY_HW_I2C3_SCL (pin_A8) // Arduino D7, pin 23 on CN10 #define MICROPY_HW_I2C3_SDA (pin_C9) // pin 1 on CN10 // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 #define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 #define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 #define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 #define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 #define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 #define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 #define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 #define MICROPY_HW_SPI3_NSS (pin_A4) // Arduino A2, pin 32 on CN7 #define MICROPY_HW_SPI3_SCK (pin_B3) // Arduino D3, pin 31 on CN10 #define MICROPY_HW_SPI3_MISO (pin_B4) // Arduino D5, pin 27 on CN10 #define MICROPY_HW_SPI3_MOSI (pin_B5) // Arduino D4, pin 29 on CN10 #define MICROPY_HW_SPI4_NSS (pin_B12) // pin 16 on CN10 #define MICROPY_HW_SPI4_SCK (pin_B13) // pin 30 on CN10 #define MICROPY_HW_SPI4_MISO (pin_A1) // pin 30 on CN7 #define MICROPY_HW_SPI4_MOSI (pin_A11) // pin 14 on CN10 // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED1 (pin_A5) // Green LD2 LED on Nucleo #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) micropython-1.12/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk000066400000000000000000000002561357706137100245000ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F446xx AF_FILE = boards/stm32f429_af.csv LD_FILES = boards/stm32f411.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/NUCLEO_F446RE/pins.csv000066400000000000000000000011201357706137100230120ustar00rootroot00000000000000D0,PA3 D1,PA2 D2,PA10 D3,PB3 D4,PB5 D5,PB4 D6,PB10 D7,PA8 D8,PA9 D9,PC7 D10,PB6 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 A0,PA0 A1,PA1 A2,PA4 A3,PB0 A4,PC1 A5,PC0 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD2,PD2 PH0,PH0 PH1,PH1 LED,PA5 SW,PC13 micropython-1.12/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100251150ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F722ZE/000077500000000000000000000000001357706137100213375ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F722ZE/board_init.c000066400000000000000000000003141357706137100236130ustar00rootroot00000000000000#include "py/mphal.h" void board_early_init(void) { // Turn off the USB switch #define USB_PowerSwitchOn pin_G6 mp_hal_pin_output(USB_PowerSwitchOn); mp_hal_pin_low(USB_PowerSwitchOn); } micropython-1.12/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h000066400000000000000000000047621357706137100243330ustar00rootroot00000000000000// This board is only confirmed to operate using DFU mode and openocd. // DFU mode can be accessed by setting BOOT0 (see schematics) // To use openocd run "OPENOCD_CONFIG=boards/openocd_stm32f7.cfg" in // the make command. #define MICROPY_HW_BOARD_NAME "NUCLEO-F722ZE" #define MICROPY_HW_MCU_NAME "STM32F722" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_BOARD_EARLY_INIT board_early_init void board_early_init(void); // HSE is 8MHz, run SYSCLK at 216MHz #define MICROPY_HW_CLK_PLLM (4) #define MICROPY_HW_CLK_PLLN (216) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (9) #define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_7) // 210-216 MHz needs 7 wait states // UART config #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) #define MICROPY_HW_UART2_RTS (pin_D4) #define MICROPY_HW_UART2_CTS (pin_D3) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART6_TX (pin_G14) #define MICROPY_HW_UART6_RX (pin_G9) #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C buses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) // SPI buses #define MICROPY_HW_SPI3_NSS (pin_A4) #define MICROPY_HW_SPI3_SCK (pin_B3) #define MICROPY_HW_SPI3_MISO (pin_B4) #define MICROPY_HW_SPI3_MOSI (pin_B5) // CAN buses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) // USRSW is pulled low, and pressing the button makes the input go high #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_B0) // green #define MICROPY_HW_LED2 (pin_B7) // blue #define MICROPY_HW_LED3 (pin_B14) // red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config (CN13 - USB OTG FS) #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) micropython-1.12/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.mk000066400000000000000000000002561357706137100245050ustar00rootroot00000000000000MCU_SERIES = f7 CMSIS_MCU = STM32F722xx AF_FILE = boards/stm32f722_af.csv LD_FILES = boards/stm32f722.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/NUCLEO_F722ZE/pins.csv000066400000000000000000000016701357706137100230310ustar00rootroot00000000000000A0,PA3 A1,PC0 A2,PC3 A3,PF3 A4,PF5 A5,PF10 A6,PB1 A7,PC2 A8,PF4 D0,PG9 D1,PG14 D2,PF15 D3,PE13 D4,PF14 D5,PE11 D6,PE9 D7,PF13 D8,PF12 D9,PD15 D10,PD14 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 D16,PC6 D17,PB15 D18,PB13 D19,PB12 D20,PA15 D21,PC7 D22,PB5 D23,PB3 D24,PA4 D25,PB4 D26,PB6 D27,PB2 D28,PD13 D29,PD12 D30,PD11 D31,PE2 D32,PA0 D33,PB0 D34,PE0 D35,PB11 D36,PB10 D37,PE15 D38,PE14 D39,PE12 D40,PE10 D41,PE7 D42,PE8 D43,PC8 D44,PC9 D45,PC10 D46,PC11 D47,PC12 D48,PD2 D49,PG2 D50,PG3 D51,PD7 D52,PD6 D53,PD5 D54,PD4 D55,PD3 D56,PE2 D57,PE4 D58,PE5 D59,PE6 D60,PE3 D61,PF8 D62,PF7 D63,PF9 D64,PG1 D65,PG0 D66,PD1 D67,PD0 D68,PF0 D69,PF1 D70,PF2 D71,PA7 LED1,PB0 LED2,PB7 LED3,PB14 SW,PC13 SD_SW,PC13 OTG_FS_POWER,PG6 OTG_FS_OVER_CURRENT,PG7 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 USB_POWER,PG6 VCP_TX,PD8 VCP_RX,PD9 UART2_TX,PD5 UART2_RX,PD6 UART2_RTS,PD4 UART2_CTS,PD3 UART6_TX,PG14 UART6_RX,PG9 SPI_B_NSS,PA4 SPI_B_SCK,PB3 SPI_B_MOSI,PB5 micropython-1.12/ports/stm32/boards/NUCLEO_F722ZE/stm32f7xx_hal_conf.h000066400000000000000000000010311357706137100251210ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * MIT License; Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #include "boards/stm32f7xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (5000) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F746ZG/000077500000000000000000000000001357706137100213475ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h000066400000000000000000000064041357706137100243360ustar00rootroot00000000000000// This board is only confirmed to operate using DFU mode and openocd. // DFU mode can be accessed by setting BOOT0 (see schematics) // To use openocd run "OPENOCD_CONFIG=boards/openocd_stm32f7.cfg" in // the make command. #define MICROPY_HW_BOARD_NAME "NUCLEO-F746ZG" #define MICROPY_HW_MCU_NAME "STM32F746" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) // HSE is 8MHz // VCOClock = HSE * PLLN / PLLM = 8 MHz * 216 / 4 = 432 MHz // SYSCLK = VCOClock / PLLP = 432 MHz / 2 = 216 MHz // USB/SDMMC/RNG Clock = VCOClock / PLLQ = 432 MHz / 9 = 48 MHz #define MICROPY_HW_CLK_PLLM (4) #define MICROPY_HW_CLK_PLLN (216) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (9) // From the reference manual, for 2.7V to 3.6V // 151-180 MHz => 5 wait states // 181-210 MHz => 6 wait states // 211-216 MHz => 7 wait states #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_7 // 210-216 MHz needs 7 wait states // UART config #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) #define MICROPY_HW_UART2_RTS (pin_D4) #define MICROPY_HW_UART2_CTS (pin_D3) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART6_TX (pin_G14) #define MICROPY_HW_UART6_RX (pin_G9) #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C3_SCL (pin_H7) #define MICROPY_HW_I2C3_SDA (pin_H8) // SPI #define MICROPY_HW_SPI3_NSS (pin_A4) #define MICROPY_HW_SPI3_SCK (pin_B3) #define MICROPY_HW_SPI3_MISO (pin_B4) #define MICROPY_HW_SPI3_MOSI (pin_B5) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_B0) // green #define MICROPY_HW_LED2 (pin_B7) // blue #define MICROPY_HW_LED3 (pin_B14) // red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config (CN13 - USB OTG FS) #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // Ethernet via RMII #define MICROPY_HW_ETH_MDC (pin_C1) #define MICROPY_HW_ETH_MDIO (pin_A2) #define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1) #define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7) #define MICROPY_HW_ETH_RMII_RXD0 (pin_C4) #define MICROPY_HW_ETH_RMII_RXD1 (pin_C5) #define MICROPY_HW_ETH_RMII_TX_EN (pin_G11) #define MICROPY_HW_ETH_RMII_TXD0 (pin_G13) #define MICROPY_HW_ETH_RMII_TXD1 (pin_B13) micropython-1.12/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk000066400000000000000000000004061357706137100245120ustar00rootroot00000000000000MCU_SERIES = f7 CMSIS_MCU = STM32F746xx AF_FILE = boards/stm32f746_af.csv LD_FILES = boards/stm32f746.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 micropython-1.12/ports/stm32/boards/NUCLEO_F746ZG/pins.csv000066400000000000000000000015551357706137100230430ustar00rootroot00000000000000A0,PA3 A1,PC0 A2,PC3 A3,PF3 A4,PF5 A5,PF10 D0,PG9 D1,PG14 D2,PF15 D3,PE13 D4,PF14 D5,PE11 D6,PE9 D7,PF13 D8,PF12 D9,PD15 D10,PD14 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 D16,PC6 D17,PB15 D18,PB13 D19,PB12 D20,PA15 D21,PC7 D22,PB5 D23,PB3 D24,PA4 D25,PB4 LED1,PB0 LED2,PB7 LED3,PB14 SW,PC13 TP1,PH2 TP2,PI8 TP3,PH15 AUDIO_INT,PD6 AUDIO_SDA,PH8 AUDIO_SCL,PH7 EXT_SDA,PB9 EXT_SCL,PB8 EXT_RST,PG3 SD_SW,PC13 LCD_BL_CTRL,PK3 LCD_INT,PI13 LCD_SDA,PH8 LCD_SCL,PH7 OTG_FS_POWER,PD5 OTG_FS_OVER_CURRENT,PD4 OTG_HS_OVER_CURRENT,PE3 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 VCP_TX,PD8 VCP_RX,PD9 UART2_TX,PD5 UART2_RX,PD6 UART2_RTS,PD4 UART2_CTS,PD3 UART6_TX,PG14 UART6_RX,PG9 SPI_B_NSS,PA4 SPI_B_SCK,PB3 SPI_B_MOSI,PB5 ETH_MDC,PC1 ETH_MDIO,PA2 ETH_RMII_REF_CLK,PA1 ETH_RMII_CRS_DV,PA7 ETH_RMII_RXD0,PC4 ETH_RMII_RXD1,PC5 ETH_RMII_TX_EN,PG11 ETH_RMII_TXD0,PG13 ETH_RMII_TXD1,PB13 micropython-1.12/ports/stm32/boards/NUCLEO_F746ZG/stm32f7xx_hal_conf.h000066400000000000000000000010451357706137100251360ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #include "boards/stm32f7xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (5000) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_F767ZI/000077500000000000000000000000001357706137100213545ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_F767ZI/board_init.c000066400000000000000000000003321357706137100236300ustar00rootroot00000000000000#include "py/mphal.h" void NUCLEO_F767ZI_board_early_init(void) { // Turn off the USB switch #define USB_PowerSwitchOn pin_G6 mp_hal_pin_output(USB_PowerSwitchOn); mp_hal_pin_low(USB_PowerSwitchOn); } micropython-1.12/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h000066400000000000000000000070711357706137100243440ustar00rootroot00000000000000// Note: if the board shows odd behaviour check the option bits and make sure nDBANK is // set to make the 2MByte space continuous instead of divided into two 1MByte segments. #define MICROPY_HW_BOARD_NAME "NUCLEO-F767ZI" #define MICROPY_HW_MCU_NAME "STM32F767" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_BOARD_EARLY_INIT NUCLEO_F767ZI_board_early_init void NUCLEO_F767ZI_board_early_init(void); // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (4) #define MICROPY_HW_CLK_PLLN (216) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (9) #define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_7) // 210-216 MHz needs 7 wait states // UART config #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) #define MICROPY_HW_UART2_RTS (pin_D4) #define MICROPY_HW_UART2_CTS (pin_D3) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) #define MICROPY_HW_UART5_TX (pin_B6) #define MICROPY_HW_UART5_RX (pin_B12) #define MICROPY_HW_UART7_TX (pin_F7) #define MICROPY_HW_UART7_RX (pin_F6) #define MICROPY_HW_UART8_TX (pin_E1) #define MICROPY_HW_UART8_RX (pin_E0) #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_F1) #define MICROPY_HW_I2C2_SDA (pin_F0) #define MICROPY_HW_I2C4_SCL (pin_F14) #define MICROPY_HW_I2C4_SDA (pin_F15) // SPI #define MICROPY_HW_SPI3_NSS (pin_A4) #define MICROPY_HW_SPI3_SCK (pin_B3) #define MICROPY_HW_SPI3_MISO (pin_B4) #define MICROPY_HW_SPI3_MOSI (pin_B5) // CAN busses #define MICROPY_HW_CAN1_TX (pin_D1) #define MICROPY_HW_CAN1_RX (pin_D0) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_B0) // green #define MICROPY_HW_LED2 (pin_B7) // blue #define MICROPY_HW_LED3 (pin_B14) // red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config (CN13 - USB OTG FS) #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // SD card detect switch (actual pin may need to be changed for a particular use) #define MICROPY_HW_SDCARD_DETECT_PIN (pin_G2) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // Ethernet via RMII #define MICROPY_HW_ETH_MDC (pin_C1) #define MICROPY_HW_ETH_MDIO (pin_A2) #define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1) #define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7) #define MICROPY_HW_ETH_RMII_RXD0 (pin_C4) #define MICROPY_HW_ETH_RMII_RXD1 (pin_C5) #define MICROPY_HW_ETH_RMII_TX_EN (pin_G11) #define MICROPY_HW_ETH_RMII_TXD0 (pin_G13) #define MICROPY_HW_ETH_RMII_TXD1 (pin_B13) micropython-1.12/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk000066400000000000000000000004421357706137100245170ustar00rootroot00000000000000MCU_SERIES = f7 CMSIS_MCU = STM32F767xx MICROPY_FLOAT_IMPL = double AF_FILE = boards/stm32f767_af.csv LD_FILES = boards/stm32f767.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 micropython-1.12/ports/stm32/boards/NUCLEO_F767ZI/pins.csv000066400000000000000000000025651357706137100230520ustar00rootroot00000000000000A0,PA3 A1,PC0 A2,PC3 A3,PF3 A4,PF5 A5,PF10 A6,PB1 A7,PC2 A8,PF4 D0,PG9 D1,PG14 D2,PF15 D3,PE13 D4,PF14 D5,PE11 D6,PE9 D7,PF13 D8,PF12 D9,PD15 D10,PD14 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 D16,PC6 D17,PB15 D18,PB13 D19,PB12 D20,PA15 D21,PC7 D22,PB5 D23,PB3 D24,PA4 D25,PB4 D26,PB6 D27,PB2 D28,PD13 D29,PD12 D30,PD11 D31,PE2 D32,PA0 D33,PB0 D34,PE0 D35,PB11 D36,PB10 D37,PE15 D38,PE14 D39,PE12 D40,PE10 D41,PE7 D42,PE8 D43,PC8 D44,PC9 D45,PC10 D46,PC11 D47,PC12 D48,PD2 D49,PG2 D50,PG3 D51,PD7 D52,PD6 D53,PD5 D54,PD4 D55,PD3 D56,PE2 D57,PE4 D58,PE5 D59,PE6 D60,PE3 D61,PF8 D62,PF7 D63,PF9 D64,PG1 D65,PG0 D66,PD1 D67,PD0 D68,PF0 D69,PF1 D70,PF2 D71,PA7 DAC1,PA4 DAC2,PA5 LED1,PB0 LED2,PB7 LED3,PB14 SW,PC13 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD_SW,PG2 OTG_FS_POWER,PG6 OTG_FS_OVER_CURRENT,PG7 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 UART2_TX,PD5 UART2_RX,PD6 UART2_RTS,PD4 UART2_CTS,PD3 VCP_TX,PD8 VCP_RX,PD9 UART3_TX,PD8 UART3_RX,PD9 UART5_TX,PB6 UART5_RX,PB12 UART6_TX,PC6 UART6_RX,PC7 UART7_TX,PF7 UART7_RX,PF6 UART8_TX,PE1 UART8_RX,PE0 SPI3_NSS,PA4 SPI3_SCK,PB3 SPI3_MISO,PB4 SPI3_MOSI,PB5 I2C1_SDA,PB9 I2C1_SCL,PB8 I2C2_SDA,PF0 I2C2_SCL,PF1 I2C4_SCL,PF14 I2C4_SDA,PF15 ETH_MDC,PC1 ETH_MDIO,PA2 ETH_RMII_REF_CLK,PA1 ETH_RMII_CRS_DV,PA7 ETH_RMII_RXD0,PC4 ETH_RMII_RXD1,PC5 ETH_RMII_TX_EN,PG11 ETH_RMII_TXD0,PG13 ETH_RMII_TXD1,PB13 SWDIO,PA13 SWDCLK,PA14 micropython-1.12/ports/stm32/boards/NUCLEO_F767ZI/stm32f7xx_hal_conf.h000066400000000000000000000010451357706137100251430ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #include "boards/stm32f7xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (5000) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_H743ZI/000077500000000000000000000000001357706137100213505ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_H743ZI/board_init.c000066400000000000000000000003321357706137100236240ustar00rootroot00000000000000#include "py/mphal.h" void NUCLEO_H743ZI_board_early_init(void) { // Turn off the USB switch #define USB_PowerSwitchOn pin_G6 mp_hal_pin_output(USB_PowerSwitchOn); mp_hal_pin_low(USB_PowerSwitchOn); } micropython-1.12/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h000066400000000000000000000073001357706137100243330ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO_H743ZI" #define MICROPY_HW_MCU_NAME "STM32H743" #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_ADC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_BOARD_EARLY_INIT NUCLEO_H743ZI_board_early_init void NUCLEO_H743ZI_board_early_init(void); // The board has an 8MHz HSE, the following gives 400MHz CPU speed #define MICROPY_HW_CLK_PLLM (4) #define MICROPY_HW_CLK_PLLN (400) #define MICROPY_HW_CLK_PLLP (2) #define MICROPY_HW_CLK_PLLQ (4) #define MICROPY_HW_CLK_PLLR (2) // The USB clock is set using PLL3 #define MICROPY_HW_CLK_PLL3M (4) #define MICROPY_HW_CLK_PLL3N (120) #define MICROPY_HW_CLK_PLL3P (2) #define MICROPY_HW_CLK_PLL3Q (5) #define MICROPY_HW_CLK_PLL3R (2) // 4 wait states #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // UART config #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) #define MICROPY_HW_UART2_RTS (pin_D4) #define MICROPY_HW_UART2_CTS (pin_D3) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART5_TX (pin_B6) #define MICROPY_HW_UART5_RX (pin_B12) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) #define MICROPY_HW_UART7_TX (pin_F7) #define MICROPY_HW_UART7_RX (pin_F6) #define MICROPY_HW_UART8_TX (pin_E1) #define MICROPY_HW_UART8_RX (pin_E0) #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_F1) #define MICROPY_HW_I2C2_SDA (pin_F0) #define MICROPY_HW_I2C4_SCL (pin_F14) #define MICROPY_HW_I2C4_SDA (pin_F15) // SPI #define MICROPY_HW_SPI3_NSS (pin_A4) #define MICROPY_HW_SPI3_SCK (pin_B3) #define MICROPY_HW_SPI3_MISO (pin_B4) #define MICROPY_HW_SPI3_MOSI (pin_B5) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_B0) // green #define MICROPY_HW_LED2 (pin_B7) // blue #define MICROPY_HW_LED3 (pin_B14) // red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // FDCAN bus #define MICROPY_HW_CAN1_NAME "FDCAN1" #define MICROPY_HW_CAN1_TX (pin_D1) #define MICROPY_HW_CAN1_RX (pin_D0) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_G2) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // Ethernet via RMII (MDC define disabled for now until eth.c supports H7) //#define MICROPY_HW_ETH_MDC (pin_C1) #define MICROPY_HW_ETH_MDIO (pin_A2) #define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1) #define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7) #define MICROPY_HW_ETH_RMII_RXD0 (pin_C4) #define MICROPY_HW_ETH_RMII_RXD1 (pin_C5) #define MICROPY_HW_ETH_RMII_TX_EN (pin_G11) #define MICROPY_HW_ETH_RMII_TXD0 (pin_G13) #define MICROPY_HW_ETH_RMII_TXD1 (pin_B13) micropython-1.12/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk000066400000000000000000000011071357706137100245120ustar00rootroot00000000000000USE_MBOOT ?= 0 # MCU settings MCU_SERIES = h7 CMSIS_MCU = STM32H743xx MICROPY_FLOAT_IMPL = double AF_FILE = boards/stm32h743_af.csv ifeq ($(USE_MBOOT),1) # When using Mboot all the text goes together after the filesystem LD_FILES = boards/stm32h743.ld boards/common_blifs.ld TEXT0_ADDR = 0x08040000 else # When not using Mboot the ISR text goes first, then the rest after the filesystem LD_FILES = boards/stm32h743.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08040000 endif # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 micropython-1.12/ports/stm32/boards/NUCLEO_H743ZI/pins.csv000066400000000000000000000024271357706137100230430ustar00rootroot00000000000000A0,PA3 A1,PC0 A2,PC3 A3,PB1 A4,PC2 A5,PF10 A6,PF4 A7,PF5 A8,PF6 D0,PB7 D1,PB6 D2,PG14 D3,PE13 D4,PE14 D5,PE11 D6,PE9 D7,PG12 D8,PF3 D9,PD15 D10,PD14 D11,PB5 D12,PA6 D13,PA7 D14,PB9 D15,PB8 D16,PC6 D17,PB15 D18,PB13 D19,PB12 D20,PA15 D21,PC7 D22,PB5 D23,PB3 D24,PA4 D25,PB4 D26,PG6 D27,PB2 D28,PD13 D29,PD12 D30,PD11 D31,PE2 D32,PA0 D33,PB0 D34,PE0 D35,PB11 D36,PB10 D37,PE15 D38,PE6 D39,PE12 D40,PE10 D41,PE7 D42,PE8 D43,PC8 D44,PC9 D45,PC10 D46,PC11 D47,PC12 D48,PD2 D49,PG2 D50,PG3 D51,PD7 D52,PD6 D53,PD5 D54,PD4 D55,PD3 D56,PE2 D57,PE4 D58,PE5 D59,PE6 D60,PE3 D61,PF8 D62,PF7 D63,PF9 D64,PG1 D65,PG0 D66,PD1 D67,PD0 D68,PF0 D69,PF1 D70,PF2 D71,PE9 D72,PB2 DAC1,PA4 DAC2,PA5 LED1,PB0 LED2,PB7 LED3,PB14 SW,PC13 I2C1_SDA,PB9 I2C1_SCL,PB8 I2C2_SDA,PF0 I2C2_SCL,PF1 I2C4_SCL,PF14 I2C4_SDA,PF15 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD_SW,PG2 OTG_FS_POWER,PG6 OTG_FS_OVER_CURRENT,PG7 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 UART2_TX,PD5 UART2_RX,PD6 UART2_RTS,PD4 UART2_CTS,PD3 UART3_TX,PD8 UART3_RX,PD9 UART5_TX,PB6 UART5_RX,PB12 UART6_TX,PC6 UART6_RX,PC7 UART7_TX,PF7 UART7_RX,PF6 UART8_TX,PE1 UART8_RX,PE0 ETH_MDC,PC1 ETH_MDIO,PA2 ETH_RMII_REF_CLK,PA1 ETH_RMII_CRS_DV,PA7 ETH_RMII_RXD0,PC4 ETH_RMII_RXD1,PC5 ETH_RMII_TX_EN,PG11 ETH_RMII_TXD0,PG13 ETH_RMII_TXD1,PB13 micropython-1.12/ports/stm32/boards/NUCLEO_H743ZI/stm32h7xx_hal_conf.h000066400000000000000000000010451357706137100251410ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H #include "boards/stm32h7xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (5000) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_L073RZ/000077500000000000000000000000001357706137100213615ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h000066400000000000000000000037011357706137100243450ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * MIT License; Copyright (c) 2019 Damien P. George */ #define MICROPY_HW_BOARD_NAME "NUCLEO-L073RZ" #define MICROPY_HW_MCU_NAME "STM32L073RZT6" #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_FRAMEBUF (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_ADC (0) #define MICROPY_HW_HAS_SWITCH (1) // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) // USART2 is connected to the ST-LINK USB VCP #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 #define MICROPY_HW_I2C1_SDA (pin_B9) // Arduino D14, pin 5 on CN10 // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 #define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 #define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 #define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 // USER B1 has a pull-up and is active low #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (0) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // NUCLEO-64 has one user LED #define MICROPY_HW_LED1 (pin_A5) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) micropython-1.12/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk000066400000000000000000000004151357706137100245240ustar00rootroot00000000000000MCU_SERIES = l0 CMSIS_MCU = STM32L073xx AF_FILE = boards/stm32l072_af.csv LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld # MicroPython settings MICROPY_VFS_FAT = 0 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= micropython-1.12/ports/stm32/boards/NUCLEO_L073RZ/pins.csv000066400000000000000000000010641357706137100230500ustar00rootroot00000000000000D0,PA3 D1,PA2 D2,PA10 D3,PB3 D4,PB5 D5,PB4 D6,PB10 D7,PA8 D8,PA9 D9,PC7 D10,PB6 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 A0,PA0 A1,PA1 A2,PA4 A3,PB0 A4,PC1 A5,PC0 RX,PA3 TX,PA2 SCL,PB8 SDA,PB9 SCK,PA5 MISO,PA6 MOSI,PA7 CS,PB6 BOOT0,PF11 SWDIO,PA13 SWCLK,PA14 USER_B1,PC13 LED_GREEN,PA5 ,PA0 ,PA1 ,PA2 ,PA3 ,PA4 ,PA5 ,PA6 ,PA7 ,PA8 ,PA9 ,PA10 ,PA11 ,PA12 ,PA13 ,PA14 ,PA15 ,PB0 ,PB1 ,PB2 ,PB3 ,PB4 ,PB5 ,PB6 ,PB7 ,PB8 ,PB9 ,PB10 ,PB11 ,PB12 ,PB13 ,PB14 ,PB15 ,PC0 ,PC1 ,PC2 ,PC3 ,PC4 ,PC5 ,PC6 ,PC7 ,PC8 ,PC9 ,PC10 ,PC11 ,PC12 ,PC13 ,PC14 ,PC15 ,PD2 ,PF0 ,PF1 ,PF11 micropython-1.12/ports/stm32/boards/NUCLEO_L073RZ/stm32l0xx_hal_conf.h000066400000000000000000000007741357706137100251570ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H #include "boards/stm32l0xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_L432KC/000077500000000000000000000000001357706137100213225ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h000066400000000000000000000043601357706137100243100ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-L432KC" #define MICROPY_HW_MCU_NAME "STM32L432KC" #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_ADC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (0) // requires a custom USB connector on PA11/PA12 #define MICROPY_HW_ENABLE_TIMER (1) #define MICROPY_HW_HAS_SWITCH (0) // MSI is used and is 4MHz #define MICROPY_HW_CLK_PLLM (1) #define MICROPY_HW_CLK_PLLN (16) #define MICROPY_HW_CLK_PLLR (2) #define MICROPY_HW_CLK_PLLP (7) #define MICROPY_HW_CLK_PLLQ (2) // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) // VCP TX #define MICROPY_HW_UART2_RX (pin_A15) // VCP RX #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_A9) #define MICROPY_HW_I2C1_SDA (pin_A10) #define MICROPY_HW_I2C3_SCL (pin_A7) #define MICROPY_HW_I2C3_SDA (pin_B4) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_B0) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI3_NSS (pin_A4) #define MICROPY_HW_SPI3_SCK (pin_B3) #define MICROPY_HW_SPI3_MISO (pin_B4) #define MICROPY_HW_SPI3_MOSI (pin_B5) // LEDs #define MICROPY_HW_LED1 (pin_B3) // Green LD3 LED on Nucleo #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (MICROPY_HW_ENABLE_USB) #define MICROPY_HW_USB_MSC (0) #define MICROPY_HW_USB_HID (0) #define USBD_CDC_RX_DATA_SIZE (256) #define USBD_CDC_TX_DATA_SIZE (256) micropython-1.12/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk000066400000000000000000000004671357706137100244740ustar00rootroot00000000000000MCU_SERIES = l4 CMSIS_MCU = STM32L432xx AF_FILE = boards/stm32l432_af.csv LD_FILES = boards/stm32l432.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg # MicroPython settings MICROPY_VFS_FAT = 0 # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= micropython-1.12/ports/stm32/boards/NUCLEO_L432KC/pins.csv000066400000000000000000000005751357706137100230170ustar00rootroot00000000000000D0,PA10 D1,PA9 D2,PA12 D3,PB0 D4,PB7 D5,PB6 D6,PB1 D7,PC14 D8,PC15 D9,PA8 D10,PA11 D11,PB5 D12,PB4 D13,PB3 A0,PA0 A1,PA1 A2,PA3 A3,PA4 A4,PA5 A5,PA6 A6,PA7 A7,PA2 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA15,PA15 PB0,PB0 PB1,PB1 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PC14,PC14 PC15,PC15 PH3,PH3 LED_GREEN,PB3 micropython-1.12/ports/stm32/boards/NUCLEO_L432KC/stm32l4xx_hal_conf.h000077500000000000000000000011201357706137100251110ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #include "boards/stm32l4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) #define EXTERNAL_SAI2_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_L452RE/000077500000000000000000000000001357706137100213355ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h000066400000000000000000000063741357706137100243320ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-L452RE" #define MICROPY_HW_MCU_NAME "STM32L452RE" #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_SERVO (0) // SERVO requires TIM5 (not on L452). #define MICROPY_HW_HAS_SWITCH (1) // MSI is used and is 4MHz #define MICROPY_HW_CLK_PLLM (1) #define MICROPY_HW_CLK_PLLN (40) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) // VCP TX #define MICROPY_HW_UART2_RX (pin_A3) // VCP RX #define MICROPY_HW_UART3_TX (pin_C10) #define MICROPY_HW_UART3_RX (pin_C11) #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) // USART2 is connected to the ST-LINK USB VCP #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 #define MICROPY_HW_I2C1_SDA (pin_B9) // Arduino D14, pin 5 on CN10 #define MICROPY_HW_I2C2_SCL (pin_B10) // Arduino D6, pin 25 on CN10 #define MICROPY_HW_I2C2_SDA (pin_B11) // pin 18 on CN10 #define MICROPY_HW_I2C3_SCL (pin_A7) // pin 15 on CN10 #define MICROPY_HW_I2C3_SDA (pin_B4) // pin 27 on CN10 #define MICROPY_HW_I2C4_SCL (pin_C0) // pin 38 on CN7 #define MICROPY_HW_I2C4_SDA (pin_C1) // pin 36 on CN7 // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 #define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 #define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 #define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 #define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 #define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 #define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 #define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 #define MICROPY_HW_SPI3_NSS (pin_A4) // pin 32 on CN7 #define MICROPY_HW_SPI3_SCK (pin_C10) // pin 1 on CN7 #define MICROPY_HW_SPI3_MISO (pin_C11) // pin 2 on CN7 #define MICROPY_HW_SPI3_MOSI (pin_C12) // pin 3 on CN7 // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) // USER B1 has a pull-up and is active low #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (0) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // NUCLEO-64 has one user LED #define MICROPY_HW_LED1 (pin_A5) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) micropython-1.12/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.mk000066400000000000000000000002561357706137100245030ustar00rootroot00000000000000MCU_SERIES = l4 CMSIS_MCU = STM32L452xx AF_FILE = boards/stm32l452_af.csv LD_FILES = boards/stm32l452xe.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg micropython-1.12/ports/stm32/boards/NUCLEO_L452RE/pins.csv000066400000000000000000000017531357706137100230310ustar00rootroot00000000000000CN9_D0,PA3 CN9_D1,PA2 CN9_D2,PA10 CN9_D3,PB3 CN9_D4,PB5 CN9_D5,PB4 CN9_D6,PB10 CN9_D7,PA8 CN5_D8,PA9 CN5_D9,PC7 CN5_D10,PB6 CN5_D11,PA7 CN5_D12,PA6 CN5_D13,PA5 CN5_D14,PB9 CN5_D15,PB8 CN8_A0,PA0 CN8_A1,PA1 CN8_A2,PA4 CN8_A3,PB0 CN8_A4,PC1 CN8_A5,PC0 CN9_RX,PA3 CN9_TX,PA2 CN5_SCL,PB8 CN5_SDA,PB9 CN5_SCK,PA5 CN5_MISO,PA6 CN5_MOSI,PA7 CN5_CS,PB6 CN7_28,PA0 CN7_30,PA1 CN10_35,PA2 CN10_37,PA3 CN7_32,PA4 CN10_11,PA5 CN10_13,PA6 CN10_15,PA7 CN10_23,PA8 CN10_21,PA9 CN10_33,PA10 CN10_14,PA11 CN10_12,PA12 CN7_13,PA13 CN7_15,PA14 CN7_17,PA15 CN7_34,PB0 CN10_24,PB1 CN10_22,PB2 CN10_31,PB3 CN10_27,PB4 CN10_29,PB5 CN10_17,PB6 CN7_21,PB7 CN10_3,PB8 CN10_5,PB9 CN10_25,PB10 CN10_18,PB11 CN10_16,PB12 CN10_30,PB13 CN10_28,PB14 CN10_26,PB15 CN7_38,PC0 CN7_36,PC1 CN7_35,PC2 CN7_37,PC3 CN10_34,PC4 CN10_6,PC5 CN10_4,PC6 CN10_19,PC7 CN10_2,PC8 CN10_1,PC9 CN7_1,PC10 CN7_2,PC11 CN7_3,PC12 CN7_23,PC13 CN7_25,PC14 CN7_27,PC15 CN7_4,PD2 CN7_29,PH0 CN7_31,PH1 BOOT0,PH3 SWDIO,PA13 SWCLK,PA14 USER_B1,PC13 LED_GREEN,PA5 micropython-1.12/ports/stm32/boards/NUCLEO_L452RE/stm32l4xx_hal_conf.h000066400000000000000000000011201357706137100251210ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #include "boards/stm32l4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) #define EXTERNAL_SAI2_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_L476RG/000077500000000000000000000000001357706137100213455ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h000066400000000000000000000040261357706137100243320ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "NUCLEO-L476RG" #define MICROPY_HW_MCU_NAME "STM32L476RG" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_DAC (1) // MSI is used and is 4MHz #define MICROPY_HW_CLK_PLLM (1) #define MICROPY_HW_CLK_PLLN (40) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) // UART config #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) #define MICROPY_HW_I2C3_SCL (pin_C0) #define MICROPY_HW_I2C3_SDA (pin_C1) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_B3) #define MICROPY_HW_SPI1_MISO (pin_B4) #define MICROPY_HW_SPI1_MOSI (pin_B5) #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // CAN bus #define MICROPY_HW_CAN1_TX (pin_A12) #define MICROPY_HW_CAN1_RX (pin_A11) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED1 (pin_A5) // Green LED on Nucleo #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) micropython-1.12/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.mk000066400000000000000000000002561357706137100245130ustar00rootroot00000000000000MCU_SERIES = l4 CMSIS_MCU = STM32L476xx AF_FILE = boards/stm32l476_af.csv LD_FILES = boards/stm32l476xg.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg micropython-1.12/ports/stm32/boards/NUCLEO_L476RG/pins.csv000066400000000000000000000012101357706137100230250ustar00rootroot00000000000000D0,PA3 D1,PA2 D2,PA10 D3,PB3 D4,PB5 D5,PB4 D6,PB10 D7,PA8 D8,PA9 D9,PC7 D10,PB6 D11,PA7 D12,PA6 D13,PA5 D14,PB9 D15,PB8 A0,PA0 A1,PA1 A2,PA4 A3,PB0 A4,PC1 A5,PC0 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD2,PD2 PH0,PH0 PH1,PH1 LED_GREEN,PA5 LED_ORANGE,PA5 LED_RED,PA5 LED_BLUE,PA4 SW,PC13 micropython-1.12/ports/stm32/boards/NUCLEO_L476RG/stm32l4xx_hal_conf.h000077500000000000000000000011201357706137100251340ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #include "boards/stm32l4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) #define EXTERNAL_SAI2_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/NUCLEO_WB55/000077500000000000000000000000001357706137100211425ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h000066400000000000000000000053251357706137100241320ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * MIT License; Copyright (c) 2019 Damien P. George */ #define MICROPY_HW_BOARD_NAME "NUCLEO-WB55" #define MICROPY_HW_MCU_NAME "STM32WB55RGV6" #define MICROPY_PY_PYB_LEGACY (0) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_ADC (0) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_HAS_SWITCH (1) // There is an external 32kHz oscillator #define RTC_ASYNCH_PREDIV (0) #define RTC_SYNCH_PREDIV (0x7fff) #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (1) // UART buses #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) // USART 1 is connected to the virtual com port on the ST-LINK #define MICROPY_HW_UART_REPL PYB_UART_1 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C buses #define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 #define MICROPY_HW_I2C1_SDA (pin_B9) // Arduino D14, pin 5 on CN10 #define MICROPY_HW_I2C3_SCL (pin_C0) // Arduino A0, pin 28 on CN7 #define MICROPY_HW_I2C3_SDA (pin_C1) // Arduino A1, pin 30 on CN7 // SPI buses #if 0 // TODO need working DMA #define MICROPY_HW_SPI1_NSS (pin_A4) // Arduino D10 pin 17 on CN10 #define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 #define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 #define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 #define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 #define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 #define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 #define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 #endif // User switch; pressing the button makes the input go low #define MICROPY_HW_USRSW_PIN (pin_C4) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED1 (pin_B1) // red #define MICROPY_HW_LED2 (pin_B0) // green #define MICROPY_HW_LED3 (pin_B5) // blue #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) #define USBD_CDC_RX_DATA_SIZE (512) #define USBD_CDC_TX_DATA_SIZE (512) // Bluetooth config #define MICROPY_HW_BLE_UART_ID (0) #define MICROPY_HW_BLE_UART_BAUDRATE (115200) micropython-1.12/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk000066400000000000000000000005001357706137100243000ustar00rootroot00000000000000MCU_SERIES = wb CMSIS_MCU = STM32WB55xx AF_FILE = boards/stm32wb55_af.csv LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld STARTUP_FILE = lib/stm32lib/CMSIS/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.o # MicroPython settings MICROPY_PY_BLUETOOTH = 1 MICROPY_BLUETOOTH_NIMBLE = 1 MICROPY_VFS_LFS2 = 1 micropython-1.12/ports/stm32/boards/NUCLEO_WB55/pins.csv000066400000000000000000000003301357706137100226240ustar00rootroot00000000000000,PA0 ,PA1 ,PA2 ,PA3 ,PA4 ,PA5 ,PA6 ,PA7 ,PB0 ,PB1 ,PB2 ,PB3 ,PB4 ,PB5 ,PB6 ,PB7 ,PB8 ,PB9 ,PB10 ,PB11 ,PB12 ,PB13 ,PB14 ,PB15 ,PC0 ,PC1 ,PC2 ,PC3 SW,PC4 LED_GREEN,PB0 LED_RED,PB1 LED_BLUE,PB5 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/NUCLEO_WB55/stm32wbxx_hal_conf.h000066400000000000000000000010471357706137100250270ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H #define MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H // Oscillator values in Hz #define HSE_VALUE (32000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #include "boards/stm32wbxx_hal_conf_base.h" #endif // MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H micropython-1.12/ports/stm32/boards/OLIMEX_E407/000077500000000000000000000000001357706137100211075ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/OLIMEX_E407/mpconfigboard.h000066400000000000000000000053641357706137100241020ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "OLIMEX STM32-E407" #define MICROPY_HW_MCU_NAME "STM32F407" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 12MHz #define MICROPY_HW_CLK_PLLM (12) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART3_RTS (pin_D12) #define MICROPY_HW_UART3_CTS (pin_D11) #if MICROPY_HW_HAS_SWITCH == 0 // NOTE: A0 also connects to the user switch. To use UART4 you should // set MICROPY_HW_HAS_SWITCH to 0, and also remove SB20 (on the back // of the board near the USER switch). #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #endif #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_C13) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_C11) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) micropython-1.12/ports/stm32/boards/OLIMEX_E407/mpconfigboard.mk000066400000000000000000000002561357706137100242550ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F407xx AF_FILE = boards/stm32f405_af.csv LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/OLIMEX_E407/pins.csv000066400000000000000000000013751357706137100226030ustar00rootroot00000000000000PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PC4,PC4 PC5,PC5 PB0,PB0 PB1,PB1 PB2,PB2 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PA8,PA8 PA9,PA9 PA10,PA10 PA13,PA13 PA14,PA14 PA15,PA15 PC10,PC10 PC11,PC11 PC12,PC12 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 LED_GREEN,PC13 PC14,PC14 PC15,PC15 PH0,PH0 PH1,PH1 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PA0,PA0 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/OLIMEX_E407/stm32f4xx_hal_conf.h000066400000000000000000000010451357706137100246730ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (12000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/PYBD_SF2/000077500000000000000000000000001357706137100206235ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/PYBD_SF2/bdev.c000066400000000000000000000042231357706137100217100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "storage.h" #include "qspi.h" // Shared cache for first and second SPI block devices STATIC mp_spiflash_cache_t spi_bdev_cache; // First external SPI flash uses software QSPI interface STATIC const mp_soft_qspi_obj_t soft_qspi_bus = { .cs = MICROPY_HW_SPIFLASH_CS, .clk = MICROPY_HW_SPIFLASH_SCK, .io0 = MICROPY_HW_SPIFLASH_IO0, .io1 = MICROPY_HW_SPIFLASH_IO1, .io2 = MICROPY_HW_SPIFLASH_IO2, .io3 = MICROPY_HW_SPIFLASH_IO3, }; const mp_spiflash_config_t spiflash_config = { .bus_kind = MP_SPIFLASH_BUS_QSPI, .bus.u_qspi.data = (void*)&soft_qspi_bus, .bus.u_qspi.proto = &mp_soft_qspi_proto, .cache = &spi_bdev_cache, }; spi_bdev_t spi_bdev; // Second external SPI flash uses hardware QSPI interface const mp_spiflash_config_t spiflash2_config = { .bus_kind = MP_SPIFLASH_BUS_QSPI, .bus.u_qspi.data = NULL, .bus.u_qspi.proto = &qspi_proto, .cache = &spi_bdev_cache, }; spi_bdev_t spi_bdev2; micropython-1.12/ports/stm32/boards/PYBD_SF2/board_init.c000066400000000000000000000051551357706137100231070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mphal.h" #include "storage.h" #if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) #define OTP_ADDR (0x1ff079e0) #else #define OTP_ADDR (0x1ff0f3c0) #endif #define OTP ((pyb_otp_t*)OTP_ADDR) typedef struct _pyb_otp_t { uint16_t series; uint16_t rev; uint8_t mac[6]; } pyb_otp_t; void mboot_board_early_init(void) { // Enable 500mA on WBUS-DIP28 mp_hal_pin_config(pyb_pin_W23, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); } void board_early_init(void) { // Configure EN_3V3 as an output pin, but keep it turned off mp_hal_pin_config(pyb_pin_EN_3V3, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // Explicitly init SPI2 because it's not enabled as a block device spi_bdev_ioctl(&spi_bdev2, BDEV_IOCTL_INIT, (uint32_t)&spiflash2_config); } #if !BUILDING_MBOOT void board_sleep(int value) { mp_spiflash_deepsleep(&spi_bdev.spiflash, value); mp_spiflash_deepsleep(&spi_bdev2.spiflash, value); } void mp_hal_get_mac(int idx, uint8_t buf[6]) { // Check if OTP region has a valid MAC address, and use it if it does if (OTP->series == 0x00d1 && OTP->mac[0] == 'H' && OTP->mac[1] == 'J' && OTP->mac[2] == '0') { memcpy(buf, OTP->mac, 6); buf[5] += idx; return; } // Generate a random locally administered MAC address (LAA) mp_hal_generate_laa_mac(idx, buf); } #endif micropython-1.12/ports/stm32/boards/PYBD_SF2/f722_qspi.ld000066400000000000000000000046021357706137100226620ustar00rootroot00000000000000/* Linker script for PYBD with STM32F722/STM32F723/STM32F732/STM32F733 Memory layout for mboot configuration (this here describes the app part): FLASH_APP .isr_vector FLASH_APP .text FLASH_APP .data FLASH_EXT .big_const RAM .data RAM .bss RAM .heap RAM .stack */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sectors 0,1 */ FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 480K /* sectors 2-7 */ FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 2048K /* external QSPI */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256K /* DTCM+SRAM1+SRAM2 */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; ENTRY(Reset_Handler) /* Define output sections */ SECTIONS { .text_ext : { . = ALIGN(4); *lib/mbedtls/*(.text* .rodata*) *lib/mynewt-nimble/*(.text* .rodata*) . = ALIGN(512); *(.big_const*) . = ALIGN(4); } >FLASH_EXT .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); } >FLASH_APP .text : { . = ALIGN(4); *(.text*) *(.rodata*) . = ALIGN(4); _etext = .; } >FLASH_APP _sidata = LOADADDR(.data); .data : { . = ALIGN(4); _sdata = .; *(.data*) . = ALIGN(4); _edata = .; } >RAM AT> FLASH_APP .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM .heap : { . = ALIGN(4); . = . + _minimum_heap_size; . = ALIGN(4); } >RAM .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM } micropython-1.12/ports/stm32/boards/PYBD_SF2/manifest.py000066400000000000000000000001331357706137100230000ustar00rootroot00000000000000include('$(PORT_DIR)/boards/manifest.py') include('$(MPY_DIR)/extmod/webrepl/manifest.py') micropython-1.12/ports/stm32/boards/PYBD_SF2/mpconfigboard.h000066400000000000000000000217401357706137100236120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define MICROPY_HW_BOARD_NAME "PYBD-SF2W" #define MICROPY_HW_MCU_NAME "STM32F722IEK" #define MICROPY_PY_PYB_LEGACY (1) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_TIMER (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_HW_ENABLE_MMCARD (1) #define MICROPY_BOARD_EARLY_INIT board_early_init #define MICROPY_BOARD_ENTER_STOP board_sleep(1); #define MICROPY_BOARD_LEAVE_STOP board_sleep(0); #define MICROPY_BOARD_ENTER_STANDBY board_sleep(1); #define MICROPY_BOARD_SDCARD_POWER mp_hal_pin_high(pyb_pin_EN_3V3); void board_early_init(void); void board_sleep(int value); // HSE is 25MHz, run SYS at 120MHz #define MICROPY_HW_CLK_PLLM (20) #define MICROPY_HW_CLK_PLLN (192) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (5) #define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_3) // There is an external 32kHz oscillator #define RTC_ASYNCH_PREDIV (0) #define RTC_SYNCH_PREDIV (0x7fff) #define MICROPY_HW_RTC_USE_BYPASS (1) #define MICROPY_HW_RTC_USE_US (1) #define MICROPY_HW_RTC_USE_CALOUT (1) // SPI flash #1, for R/W storage #define MICROPY_HW_SOFTQSPI_SCK_LOW(self) (GPIOE->BSRR = (0x10000 << 11)) #define MICROPY_HW_SOFTQSPI_SCK_HIGH(self) (GPIOE->BSRR = (1 << 11)) #define MICROPY_HW_SOFTQSPI_NIBBLE_READ(self) ((GPIOE->IDR >> 7) & 0xf) #define MICROPY_HW_SPIFLASH_SIZE_BITS (16 * 1024 * 1024) #define MICROPY_HW_SPIFLASH_CS (pyb_pin_QSPI1_CS) #define MICROPY_HW_SPIFLASH_SCK (pyb_pin_QSPI1_CLK) #define MICROPY_HW_SPIFLASH_IO0 (pyb_pin_QSPI1_D0) #define MICROPY_HW_SPIFLASH_IO1 (pyb_pin_QSPI1_D1) #define MICROPY_HW_SPIFLASH_IO2 (pyb_pin_QSPI1_D2) #define MICROPY_HW_SPIFLASH_IO3 (pyb_pin_QSPI1_D3) // SPI flash #1, block device config extern const struct _mp_spiflash_config_t spiflash_config; extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_BDEV_IOCTL(op, arg) ( \ (op) == BDEV_IOCTL_NUM_BLOCKS ? (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE) : \ (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \ spi_bdev_ioctl(&spi_bdev, (op), (arg)) \ ) #define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n)) #define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n)) #define MICROPY_HW_BDEV_SPIFLASH_EXTENDED (&spi_bdev) // for extended block protocol // SPI flash #2, to be memory mapped #define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (24) #define MICROPY_HW_QSPIFLASH_CS (pyb_pin_QSPI2_CS) #define MICROPY_HW_QSPIFLASH_SCK (pyb_pin_QSPI2_CLK) #define MICROPY_HW_QSPIFLASH_IO0 (pyb_pin_QSPI2_D0) #define MICROPY_HW_QSPIFLASH_IO1 (pyb_pin_QSPI2_D1) #define MICROPY_HW_QSPIFLASH_IO2 (pyb_pin_QSPI2_D2) #define MICROPY_HW_QSPIFLASH_IO3 (pyb_pin_QSPI2_D3) // SPI flash #2, block device config extern const struct _mp_spiflash_config_t spiflash2_config; extern struct _spi_bdev_t spi_bdev2; // UART config #define MICROPY_HW_UART1_NAME "YA" #define MICROPY_HW_UART1_TX (pyb_pin_Y1) #define MICROPY_HW_UART1_RX (pyb_pin_Y2) #define MICROPY_HW_UART2_TX (pyb_pin_X3) #define MICROPY_HW_UART2_RX (pyb_pin_X4) #define MICROPY_HW_UART2_RTS (pyb_pin_X2) #define MICROPY_HW_UART2_CTS (pyb_pin_X1) #define MICROPY_HW_UART3_NAME "YB" #define MICROPY_HW_UART3_TX (pyb_pin_Y9) #define MICROPY_HW_UART3_RX (pyb_pin_Y10) #define MICROPY_HW_UART4_NAME "XA" #define MICROPY_HW_UART4_TX (pyb_pin_X1) #define MICROPY_HW_UART4_RX (pyb_pin_X2) #define MICROPY_HW_UART6_TX (pyb_pin_BT_TXD) #define MICROPY_HW_UART6_RX (pyb_pin_BT_RXD) #define MICROPY_HW_UART6_RTS (pyb_pin_BT_RTS) #define MICROPY_HW_UART6_CTS (pyb_pin_BT_CTS) // I2C busses #define MICROPY_HW_I2C1_NAME "X" #define MICROPY_HW_I2C1_SCL (pyb_pin_X9) #define MICROPY_HW_I2C1_SDA (pyb_pin_X10) #define MICROPY_HW_I2C2_NAME "Y" #define MICROPY_HW_I2C2_SCL (pyb_pin_Y9) #define MICROPY_HW_I2C2_SDA (pyb_pin_Y10) // SPI busses #define MICROPY_HW_SPI1_NAME "X" #define MICROPY_HW_SPI1_NSS (pyb_pin_X5) #define MICROPY_HW_SPI1_SCK (pyb_pin_X6) #define MICROPY_HW_SPI1_MISO (pyb_pin_X7) #define MICROPY_HW_SPI1_MOSI (pyb_pin_X8) #define MICROPY_HW_SPI2_NAME "Y" #define MICROPY_HW_SPI2_NSS (pyb_pin_Y5) #define MICROPY_HW_SPI2_SCK (pyb_pin_Y6) #define MICROPY_HW_SPI2_MISO (pyb_pin_Y7) #define MICROPY_HW_SPI2_MOSI (pyb_pin_Y8) #define MICROPY_HW_SPI3_NSS (pyb_pin_W16) #define MICROPY_HW_SPI3_SCK (pyb_pin_W29) #define MICROPY_HW_SPI3_MISO (pyb_pin_W50) #define MICROPY_HW_SPI3_MOSI (pyb_pin_W46) // CAN busses #define MICROPY_HW_CAN1_NAME "X" #define MICROPY_HW_CAN1_TX (pyb_pin_X10) #define MICROPY_HW_CAN1_RX (pyb_pin_X9) // USRSW is not pulled, and pressing the button makes the input go low. #define MICROPY_HW_USRSW_PIN (pyb_pin_USR) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED_INVERTED (1) // LEDs are on when pin is driven low #define MICROPY_HW_LED1 (pyb_pin_LED_RED) #define MICROPY_HW_LED2 (pyb_pin_LED_GREEN) #define MICROPY_HW_LED3 (pyb_pin_LED_BLUE) #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) // SD card #define MICROPY_HW_SDMMC2_CK (pyb_pin_SD_CK) #define MICROPY_HW_SDMMC2_CMD (pyb_pin_SD_CMD) #define MICROPY_HW_SDMMC2_D0 (pyb_pin_SD_D0) #define MICROPY_HW_SDMMC2_D1 (pyb_pin_SD_D1) #define MICROPY_HW_SDMMC2_D2 (pyb_pin_SD_D2) #define MICROPY_HW_SDMMC2_D3 (pyb_pin_SD_D3) #define MICROPY_HW_SDCARD_DETECT_PIN (pyb_pin_SD_SW) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) #define MICROPY_HW_SDCARD_MOUNT_AT_BOOT (0) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_HS (1) #define MICROPY_HW_USB_HS_IN_FS (1) #define MICROPY_HW_USB_MAIN_DEV (USB_PHY_HS_ID) // Bluetooth config #define MICROPY_HW_BLE_UART_ID (PYB_UART_6) #define MICROPY_HW_BLE_UART_BAUDRATE (115200) /******************************************************************************/ // Bootloader configuration #define MBOOT_USB_AUTODETECT_PORT (1) #define MBOOT_FSLOAD (1) #define MBOOT_I2C_PERIPH_ID 1 #define MBOOT_I2C_SCL (pin_B8) #define MBOOT_I2C_SDA (pin_B9) #define MBOOT_I2C_ALTFUNC (4) #define MBOOT_SPIFLASH_ADDR (0x80000000) #define MBOOT_SPIFLASH_BYTE_SIZE (64 * 32 * 1024) #define MBOOT_SPIFLASH_LAYOUT "/0x80000000/64*32Kg" #define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (32 / 4) #define MBOOT_SPIFLASH_SPIFLASH (&spi_bdev.spiflash) #define MBOOT_SPIFLASH_CONFIG (&spiflash_config) #define MBOOT_SPIFLASH2_ADDR (0x90000000) #define MBOOT_SPIFLASH2_BYTE_SIZE (64 * 32 * 1024) #define MBOOT_SPIFLASH2_LAYOUT "/0x90000000/64*32Kg" #define MBOOT_SPIFLASH2_ERASE_BLOCKS_PER_PAGE (32 / 4) #define MBOOT_SPIFLASH2_SPIFLASH (&spi_bdev2.spiflash) #define MBOOT_SPIFLASH2_CONFIG (&spiflash2_config) #define MBOOT_BOARD_EARLY_INIT mboot_board_early_init void mboot_board_early_init(void); micropython-1.12/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk000066400000000000000000000010341357706137100237640ustar00rootroot00000000000000# MCU settings MCU_SERIES = f7 CMSIS_MCU = STM32F722xx MICROPY_FLOAT_IMPL = single AF_FILE = boards/stm32f722_af.csv LD_FILES = boards/PYBD_SF2/f722_qspi.ld TEXT0_ADDR = 0x08008000 TEXT1_ADDR = 0x90000000 TEXT0_SECTIONS = .isr_vector .text .data TEXT1_SECTIONS = .text_ext # MicroPython settings MICROPY_PY_BLUETOOTH = 1 MICROPY_BLUETOOTH_NIMBLE = 1 MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 MICROPY_VFS_LFS2 = 1 # PYBD-specific frozen modules FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py micropython-1.12/ports/stm32/boards/PYBD_SF2/pins.csv000066400000000000000000000034661357706137100223220ustar00rootroot00000000000000W3,PE3 W5,PA11 W5B,PI0 W6,PA5 W7,PA4 W7B,PG7 W8,PB11 W9,PA12 W9B,PI1 W10,PA6 W11,PA3 W12,PB10 W14,PA7 W15,PA2 W16,PA15 W17,PA1 W18,PD3 W19,PA0 W20,PD0 W21,PC14 W22,PE12 W22B,PF6 W22C,PF7 W22D,PF10 W23,PE1 W24,PC1 W25,PE0 W26,PC13 W27,PA8 W27B,PC6 W28,PE6 W29,PB3 W30,PE5 W32,PE4 W33,PH2 W34,PH3 W43,PB0 W43B,PC0 W43C,PF9 W43D,PF11 W45,PB12 W45B,PE14 W45C,PH8 W46,PB5 W47,PC5 W47B,PF14 W49,PB13 W50,PB4 W51,PC4 W51B,PF15 W52,PA10 W53,PC2 W53B,PF8 W54,PA9 W55,PB9 W56,PA14 W57,PC3 W57B,PF13 W58,PG11 W59,PB8 W60,PG12 W61,PB7 W62,PD7 W63,PB1 W63B,PD9 W64,PD6 W65,PD8 W66,PG9 W67,PA13 W68,PG10 W70,PB14 W71,PE15 W72,PB15 W73,PH6 W74,PH7 X1,PA0 X2,PA1 X3,PA2 X4,PA3 X5,PA4 X5B,PG7 X6,PA5 X7,PA6 X8,PA7 X9,PB8 X10,PB9 X11,PC4 X11B,PF15 X12,PC5 X12B,PF14 Y1,PA9 Y2,PA10 Y3,PB4 Y4,PB5 Y5,PB12 Y5B,PE14 Y5C,PH8 Y6,PB13 Y7,PC2 Y7B,PF8 Y8,PC3 Y8B,PF13 Y9,PB10 Y10,PB11 Y11,PB0 Y11B,PC0 Y11C,PF9 Y11D,PF11 Y12,PB1 Y12B,PD9 EN_3V3,PF2 PULL_SCL,PF1 PULL_SDA,PH5 LED_RED,PF3 LED_GREEN,PF4 LED_BLUE,PF5 USR,PA13 USB_DM,PA11 USB_DP,PA12 USB_HS_DM,PB14 USB_HS_DP,PB15 -QSPI1_CS,PE13 -QSPI1_CLK,PE11 -QSPI1_D0,PE7 -QSPI1_D1,PE8 -QSPI1_D2,PE9 -QSPI1_D3,PE10 -QSPI2_CS,PB6 -QSPI2_CLK,PB2 -QSPI2_D0,PD11 -QSPI2_D1,PD12 -QSPI2_D2,PE2 -QSPI2_D3,PD13 -SD_D0,PG9 -SD_D1,PG10 -SD_D2,PG11 -SD_D3,PG12 -SD_CMD,PD7 -SD_CK,PD6 SD_SW,PA14 -WL_REG_ON,PD4 -WL_HOST_WAKE,PI8 -WL_RFSW_VDD,PI9 -WL_GPIO_1,PI11 -WL_GPIO_2,PI7 -WL_GPIO_4,PI9 -WL_SDIO_0,PC8 -WL_SDIO_1,PC9 -WL_SDIO_2,PC10 -WL_SDIO_3,PC11 -WL_SDIO_CMD,PD2 -WL_SDIO_CLK,PC12 -BT_RXD,PC7 -BT_TXD,PG14 -BT_CTS,PG13 -BT_RTS,PG8 -BT_GPIO_3,PG15 -BT_GPIO_4,PI5 -BT_GPIO_5,PI4 -BT_PCM_SYNC,PE4 -BT_PCM_IN,PE6 -BT_PCM_OUT,PE3 -BT_PCM_CLK,PE5 -BT_I2C_D0,PI10 -BT_REG_ON,PI6 -BT_HOST_WAKE,PD10 -BT_DEV_WAKE,PD5 ,PD1 ,PD14 ,PD15 ,PF0 ,PF12 ,PG0 ,PG1 ,PG2 ,PG3 ,PG4 ,PG5 ,PG6 ,PH4 ,PH9 ,PH10 ,PH11 ,PH12 ,PH13 ,PH14 ,PH15 ,PI2 ,PI3 micropython-1.12/ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h000066400000000000000000000010461357706137100244130ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #include "boards/stm32f7xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (25000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (5000) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/PYBD_SF3/000077500000000000000000000000001357706137100206245ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/PYBD_SF3/bdev.c000066400000000000000000000000421357706137100217040ustar00rootroot00000000000000#include "boards/PYBD_SF2/bdev.c" micropython-1.12/ports/stm32/boards/PYBD_SF3/board_init.c000066400000000000000000000000501357706137100230750ustar00rootroot00000000000000#include "boards/PYBD_SF2/board_init.c" micropython-1.12/ports/stm32/boards/PYBD_SF3/mpconfigboard.h000066400000000000000000000026761357706137100236220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Take PYBD_SF2 as base configuration #include "boards/PYBD_SF2/mpconfigboard.h" #undef MICROPY_HW_BOARD_NAME #undef MICROPY_HW_MCU_NAME #define MICROPY_HW_BOARD_NAME "PYBD-SF3W" #define MICROPY_HW_MCU_NAME "STM32F733IEK" micropython-1.12/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk000066400000000000000000000010121357706137100237610ustar00rootroot00000000000000# MCU settings MCU_SERIES = f7 CMSIS_MCU = STM32F733xx MICROPY_FLOAT_IMPL = single AF_FILE = boards/stm32f722_af.csv LD_FILES = boards/PYBD_SF2/f722_qspi.ld TEXT0_ADDR = 0x08008000 TEXT1_ADDR = 0x90000000 TEXT0_SECTIONS = .isr_vector .text .data TEXT1_SECTIONS = .text_ext # MicroPython settings MICROPY_PY_BLUETOOTH = 1 MICROPY_BLUETOOTH_NIMBLE = 1 MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 # PYBD-specific frozen modules FROZEN_MANIFEST = boards/PYBD_SF2/manifest.py micropython-1.12/ports/stm32/boards/PYBD_SF3/pins.csv000066400000000000000000000034661357706137100223230ustar00rootroot00000000000000W3,PE3 W5,PA11 W5B,PI0 W6,PA5 W7,PA4 W7B,PG7 W8,PB11 W9,PA12 W9B,PI1 W10,PA6 W11,PA3 W12,PB10 W14,PA7 W15,PA2 W16,PA15 W17,PA1 W18,PD3 W19,PA0 W20,PD0 W21,PC14 W22,PE12 W22B,PF6 W22C,PF7 W22D,PF10 W23,PE1 W24,PC1 W25,PE0 W26,PC13 W27,PA8 W27B,PC6 W28,PE6 W29,PB3 W30,PE5 W32,PE4 W33,PH2 W34,PH3 W43,PB0 W43B,PC0 W43C,PF9 W43D,PF11 W45,PB12 W45B,PE14 W45C,PH8 W46,PB5 W47,PC5 W47B,PF14 W49,PB13 W50,PB4 W51,PC4 W51B,PF15 W52,PA10 W53,PC2 W53B,PF8 W54,PA9 W55,PB9 W56,PA14 W57,PC3 W57B,PF13 W58,PG11 W59,PB8 W60,PG12 W61,PB7 W62,PD7 W63,PB1 W63B,PD9 W64,PD6 W65,PD8 W66,PG9 W67,PA13 W68,PG10 W70,PB14 W71,PE15 W72,PB15 W73,PH6 W74,PH7 X1,PA0 X2,PA1 X3,PA2 X4,PA3 X5,PA4 X5B,PG7 X6,PA5 X7,PA6 X8,PA7 X9,PB8 X10,PB9 X11,PC4 X11B,PF15 X12,PC5 X12B,PF14 Y1,PA9 Y2,PA10 Y3,PB4 Y4,PB5 Y5,PB12 Y5B,PE14 Y5C,PH8 Y6,PB13 Y7,PC2 Y7B,PF8 Y8,PC3 Y8B,PF13 Y9,PB10 Y10,PB11 Y11,PB0 Y11B,PC0 Y11C,PF9 Y11D,PF11 Y12,PB1 Y12B,PD9 EN_3V3,PF2 PULL_SCL,PF1 PULL_SDA,PH5 LED_RED,PF3 LED_GREEN,PF4 LED_BLUE,PF5 USR,PA13 USB_DM,PA11 USB_DP,PA12 USB_HS_DM,PB14 USB_HS_DP,PB15 -QSPI1_CS,PE13 -QSPI1_CLK,PE11 -QSPI1_D0,PE7 -QSPI1_D1,PE8 -QSPI1_D2,PE9 -QSPI1_D3,PE10 -QSPI2_CS,PB6 -QSPI2_CLK,PB2 -QSPI2_D0,PD11 -QSPI2_D1,PD12 -QSPI2_D2,PE2 -QSPI2_D3,PD13 -SD_D0,PG9 -SD_D1,PG10 -SD_D2,PG11 -SD_D3,PG12 -SD_CMD,PD7 -SD_CK,PD6 SD_SW,PA14 -WL_REG_ON,PD4 -WL_HOST_WAKE,PI8 -WL_RFSW_VDD,PI9 -WL_GPIO_1,PI11 -WL_GPIO_2,PI7 -WL_GPIO_4,PI9 -WL_SDIO_0,PC8 -WL_SDIO_1,PC9 -WL_SDIO_2,PC10 -WL_SDIO_3,PC11 -WL_SDIO_CMD,PD2 -WL_SDIO_CLK,PC12 -BT_RXD,PC7 -BT_TXD,PG14 -BT_CTS,PG13 -BT_RTS,PG8 -BT_GPIO_3,PG15 -BT_GPIO_4,PI5 -BT_GPIO_5,PI4 -BT_PCM_SYNC,PE4 -BT_PCM_IN,PE6 -BT_PCM_OUT,PE3 -BT_PCM_CLK,PE5 -BT_I2C_D0,PI10 -BT_REG_ON,PI6 -BT_HOST_WAKE,PD10 -BT_DEV_WAKE,PD5 ,PD1 ,PD14 ,PD15 ,PF0 ,PF12 ,PG0 ,PG1 ,PG2 ,PG3 ,PG4 ,PG5 ,PG6 ,PH4 ,PH9 ,PH10 ,PH11 ,PH12 ,PH13 ,PH14 ,PH15 ,PI2 ,PI3 micropython-1.12/ports/stm32/boards/PYBD_SF3/stm32f7xx_hal_conf.h000066400000000000000000000000601357706137100244070ustar00rootroot00000000000000#include "boards/PYBD_SF2/stm32f7xx_hal_conf.h" micropython-1.12/ports/stm32/boards/PYBD_SF6/000077500000000000000000000000001357706137100206275ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/PYBD_SF6/bdev.c000066400000000000000000000000421357706137100217070ustar00rootroot00000000000000#include "boards/PYBD_SF2/bdev.c" micropython-1.12/ports/stm32/boards/PYBD_SF6/board_init.c000066400000000000000000000000501357706137100231000ustar00rootroot00000000000000#include "boards/PYBD_SF2/board_init.c" micropython-1.12/ports/stm32/boards/PYBD_SF6/f767.ld000066400000000000000000000043401357706137100216420ustar00rootroot00000000000000/* Linker script for PYBD with STM32F767 Memory layout for mboot configuration (this here describes the app part): FLASH_APP .isr_vector FLASH_APP .text FLASH_APP .big_const FLASH_APP .data RAM .data RAM .bss RAM .heap RAM .stack */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sector 0, 32K */ FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 2016K /* sectors 1-11 3x32K 1*128K 7*256K */ FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 2048K /* external QSPI */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 512K /* DTCM=128k, SRAM1=368K, SRAM2=16K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 24K; /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; ENTRY(Reset_Handler) /* Define output sections */ SECTIONS { .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); } >FLASH_APP .text : { . = ALIGN(4); *(.text*) *(.rodata*) . = ALIGN(512); *(.big_const*) . = ALIGN(4); _etext = .; } >FLASH_APP _sidata = LOADADDR(.data); .data : { . = ALIGN(4); _sdata = .; *(.data*) . = ALIGN(4); _edata = .; } >RAM AT> FLASH_APP .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM .heap : { . = ALIGN(4); . = . + _minimum_heap_size; . = ALIGN(4); } >RAM .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM } micropython-1.12/ports/stm32/boards/PYBD_SF6/mpconfigboard.h000066400000000000000000000051041357706137100236120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Take PYBD_SF2 as base configuration #include "boards/PYBD_SF2/mpconfigboard.h" #undef MICROPY_HW_BOARD_NAME #undef MICROPY_HW_MCU_NAME #undef MICROPY_HW_CLK_PLLM #undef MICROPY_HW_CLK_PLLN #undef MICROPY_HW_CLK_PLLP #undef MICROPY_HW_CLK_PLLQ #undef MICROPY_HW_FLASH_LATENCY #define MICROPY_HW_BOARD_NAME "PYBD-SF6W" #define MICROPY_HW_MCU_NAME "STM32F767IIK" // HSE is 25MHz, run SYS at 144MHz #define MICROPY_HW_CLK_PLLM (25) #define MICROPY_HW_CLK_PLLN (288) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (6) #define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_4) // Extra UART config #define MICROPY_HW_UART7_TX (pyb_pin_W16) #define MICROPY_HW_UART7_RX (pyb_pin_W22B) // Extra CAN busses #define MICROPY_HW_CAN2_NAME "Y" #define MICROPY_HW_CAN2_TX (pyb_pin_Y6) #define MICROPY_HW_CAN2_RX (pyb_pin_Y5) // Ethernet via RMII #define MICROPY_HW_ETH_MDC (pyb_pin_W24) #define MICROPY_HW_ETH_MDIO (pyb_pin_W15) #define MICROPY_HW_ETH_RMII_REF_CLK (pyb_pin_W17) #define MICROPY_HW_ETH_RMII_CRS_DV (pyb_pin_W14) #define MICROPY_HW_ETH_RMII_RXD0 (pyb_pin_W51) #define MICROPY_HW_ETH_RMII_RXD1 (pyb_pin_W47) #define MICROPY_HW_ETH_RMII_TX_EN (pyb_pin_W8) #define MICROPY_HW_ETH_RMII_TXD0 (pyb_pin_W45) #define MICROPY_HW_ETH_RMII_TXD1 (pyb_pin_W49) micropython-1.12/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk000066400000000000000000000006511357706137100237740ustar00rootroot00000000000000# MCU settings MCU_SERIES = f7 CMSIS_MCU = STM32F767xx MICROPY_FLOAT_IMPL = double AF_FILE = boards/stm32f767_af.csv LD_FILES = boards/PYBD_SF6/f767.ld TEXT0_ADDR = 0x08008000 # MicroPython settings MICROPY_PY_BLUETOOTH = 1 MICROPY_BLUETOOTH_NIMBLE = 1 MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 # PYBD-specific frozen modules FROZEN_MANIFEST = boards/PYBD_SF2/manifest.py micropython-1.12/ports/stm32/boards/PYBD_SF6/pins.csv000066400000000000000000000034661357706137100223260ustar00rootroot00000000000000W3,PE3 W5,PA11 W5B,PI0 W6,PA5 W7,PA4 W7B,PG7 W8,PB11 W9,PA12 W9B,PI1 W10,PA6 W11,PA3 W12,PB10 W14,PA7 W15,PA2 W16,PA15 W17,PA1 W18,PD3 W19,PA0 W20,PD0 W21,PC14 W22,PE12 W22B,PF6 W22C,PF7 W22D,PF10 W23,PE1 W24,PC1 W25,PE0 W26,PC13 W27,PA8 W27B,PC6 W28,PE6 W29,PB3 W30,PE5 W32,PE4 W33,PH2 W34,PH3 W43,PB0 W43B,PC0 W43C,PF9 W43D,PF11 W45,PB12 W45B,PE14 W45C,PH8 W46,PB5 W47,PC5 W47B,PF14 W49,PB13 W50,PB4 W51,PC4 W51B,PF15 W52,PA10 W53,PC2 W53B,PF8 W54,PA9 W55,PB9 W56,PA14 W57,PC3 W57B,PF13 W58,PG11 W59,PB8 W60,PG12 W61,PB7 W62,PD7 W63,PB1 W63B,PD9 W64,PD6 W65,PD8 W66,PG9 W67,PA13 W68,PG10 W70,PB14 W71,PE15 W72,PB15 W73,PH6 W74,PH7 X1,PA0 X2,PA1 X3,PA2 X4,PA3 X5,PA4 X5B,PG7 X6,PA5 X7,PA6 X8,PA7 X9,PB8 X10,PB9 X11,PC4 X11B,PF15 X12,PC5 X12B,PF14 Y1,PA9 Y2,PA10 Y3,PB4 Y4,PB5 Y5,PB12 Y5B,PE14 Y5C,PH8 Y6,PB13 Y7,PC2 Y7B,PF8 Y8,PC3 Y8B,PF13 Y9,PB10 Y10,PB11 Y11,PB0 Y11B,PC0 Y11C,PF9 Y11D,PF11 Y12,PB1 Y12B,PD9 EN_3V3,PF2 PULL_SCL,PF1 PULL_SDA,PH5 LED_RED,PF3 LED_GREEN,PF4 LED_BLUE,PF5 USR,PA13 USB_DM,PA11 USB_DP,PA12 USB_HS_DM,PB14 USB_HS_DP,PB15 -QSPI1_CS,PE13 -QSPI1_CLK,PE11 -QSPI1_D0,PE7 -QSPI1_D1,PE8 -QSPI1_D2,PE9 -QSPI1_D3,PE10 -QSPI2_CS,PB6 -QSPI2_CLK,PB2 -QSPI2_D0,PD11 -QSPI2_D1,PD12 -QSPI2_D2,PE2 -QSPI2_D3,PD13 -SD_D0,PG9 -SD_D1,PG10 -SD_D2,PG11 -SD_D3,PG12 -SD_CMD,PD7 -SD_CK,PD6 SD_SW,PA14 -WL_REG_ON,PD4 -WL_HOST_WAKE,PI8 -WL_RFSW_VDD,PI9 -WL_GPIO_1,PI11 -WL_GPIO_2,PI7 -WL_GPIO_4,PI9 -WL_SDIO_0,PC8 -WL_SDIO_1,PC9 -WL_SDIO_2,PC10 -WL_SDIO_3,PC11 -WL_SDIO_CMD,PD2 -WL_SDIO_CLK,PC12 -BT_RXD,PC7 -BT_TXD,PG14 -BT_CTS,PG13 -BT_RTS,PG8 -BT_GPIO_3,PG15 -BT_GPIO_4,PI5 -BT_GPIO_5,PI4 -BT_PCM_SYNC,PE4 -BT_PCM_IN,PE6 -BT_PCM_OUT,PE3 -BT_PCM_CLK,PE5 -BT_I2C_D0,PI10 -BT_REG_ON,PI6 -BT_HOST_WAKE,PD10 -BT_DEV_WAKE,PD5 ,PD1 ,PD14 ,PD15 ,PF0 ,PF12 ,PG0 ,PG1 ,PG2 ,PG3 ,PG4 ,PG5 ,PG6 ,PH4 ,PH9 ,PH10 ,PH11 ,PH12 ,PH13 ,PH14 ,PH15 ,PI2 ,PI3 micropython-1.12/ports/stm32/boards/PYBD_SF6/stm32f7xx_hal_conf.h000066400000000000000000000000601357706137100244120ustar00rootroot00000000000000#include "boards/PYBD_SF2/stm32f7xx_hal_conf.h" micropython-1.12/ports/stm32/boards/PYBLITEV10/000077500000000000000000000000001357706137100210125ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/PYBLITEV10/mpconfigboard.h000066400000000000000000000060111357706137100237730ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "PYBLITEv1.0" #define MICROPY_HW_MCU_NAME "STM32F411RE" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_HAS_MMA7660 (1) #define MICROPY_HW_HAS_LCD (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 12MHz #define MICROPY_HW_CLK_PLLM (12) #define MICROPY_HW_CLK_PLLN (192) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (4) #define MICROPY_HW_CLK_LAST_FREQ (1) // Pyboard lite has an optional 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (1) // UART config #define MICROPY_HW_UART1_NAME "XB" #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_NAME "XA" #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART6_NAME "YA" #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_NAME "X" #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C3_NAME "Y" #define MICROPY_HW_I2C3_SCL (pin_A8) #define MICROPY_HW_I2C3_SDA (pin_B8) // SPI busses #define MICROPY_HW_SPI1_NAME "X" #define MICROPY_HW_SPI1_NSS (pin_A4) // X5 #define MICROPY_HW_SPI1_SCK (pin_A5) // X6 #define MICROPY_HW_SPI1_MISO (pin_A6) // X7 #define MICROPY_HW_SPI1_MOSI (pin_A7) // X8 #define MICROPY_HW_SPI2_NAME "Y" #define MICROPY_HW_SPI2_NSS (pin_B12) // Y5 #define MICROPY_HW_SPI2_SCK (pin_B13) // Y6 #define MICROPY_HW_SPI2_MISO (pin_B14) // Y7 #define MICROPY_HW_SPI2_MOSI (pin_B15) // Y8 // USRSW has no pullup or pulldown, and pressing the switch makes the input go low #define MICROPY_HW_USRSW_PIN (pin_B3) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // The pyboard has 4 LEDs #define MICROPY_HW_LED1 (pin_A13) // red #define MICROPY_HW_LED2 (pin_A14) // green #define MICROPY_HW_LED3 (pin_A15) // yellow #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_B5) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) // MMA accelerometer config #define MICROPY_HW_MMA_AVDD_PIN (pin_A10) micropython-1.12/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk000066400000000000000000000002561357706137100241600ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F411xE AF_FILE = boards/stm32f411_af.csv LD_FILES = boards/stm32f411.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/PYBLITEV10/pins.csv000066400000000000000000000010571357706137100225030ustar00rootroot00000000000000X1,PA2 X2,PA3 X3,PA0 X4,PA1 X5,PA4 X6,PA5 X7,PA6 X8,PA7 X9,PB6 X10,PB7 X11,PC4 X12,PC5 X13,Reset X14,GND X15,3.3V X16,VIN X17,PB3 X18,PC13 X19,PC0 X20,PC1 X21,PC2 X22,PC3 X23,A3.3V X24,AGND Y1,PC6 Y2,PC7 Y3,PB10 Y4,PB9 Y5,PB12 Y6,PB13 Y7,PB14 Y8,PB15 Y9,PA8 Y10,PB8 Y11,PB0 Y12,PB1 Y13,Reset Y14,GND Y15,3.3V Y16,VIN SW,PB3 LED_BLUE,PB4 LED_RED,PA13 LED_GREEN,PA14 LED_YELLOW,PA15 MMA_AVDD,PA10 MMA_INT,PB2 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD_SW,PB5 USB_VBUS,PA9 USB_DM,PA11 USB_DP,PA12 USB_ID,PA10 OSC32_IN,PC14 OSC32_OUT,PC15 micropython-1.12/ports/stm32/boards/PYBLITEV10/stm32f4xx_hal_conf.h000066400000000000000000000010451357706137100245760ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (12000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/PYBV10/000077500000000000000000000000001357706137100203345ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/PYBV10/mpconfigboard.h000066400000000000000000000075401357706137100233250ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "PYBv1.0" #define MICROPY_HW_MCU_NAME "STM32F405RG" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_HAS_MMA7660 (1) #define MICROPY_HW_HAS_LCD (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) #define MICROPY_HW_CLK_LAST_FREQ (1) // The pyboard has a 32kHz crystal for the RTC #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (1) // UART config #define MICROPY_HW_UART1_NAME "XB" #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_NAME "YB" #define MICROPY_HW_UART3_TX (pin_B10) #define MICROPY_HW_UART3_RX (pin_B11) #define MICROPY_HW_UART3_RTS (pin_B14) #define MICROPY_HW_UART3_CTS (pin_B13) #define MICROPY_HW_UART4_NAME "XA" #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART6_NAME "YA" #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_NAME "X" #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_NAME "Y" #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NAME "X" #define MICROPY_HW_SPI1_NSS (pin_A4) // X5 #define MICROPY_HW_SPI1_SCK (pin_A5) // X6 #define MICROPY_HW_SPI1_MISO (pin_A6) // X7 #define MICROPY_HW_SPI1_MOSI (pin_A7) // X8 #define MICROPY_HW_SPI2_NAME "Y" #define MICROPY_HW_SPI2_NSS (pin_B12) // Y5 #define MICROPY_HW_SPI2_SCK (pin_B13) // Y6 #define MICROPY_HW_SPI2_MISO (pin_B14) // Y7 #define MICROPY_HW_SPI2_MOSI (pin_B15) // Y8 // CAN busses #define MICROPY_HW_CAN1_NAME "YA" #define MICROPY_HW_CAN1_TX (pin_B9) // Y4 #define MICROPY_HW_CAN1_RX (pin_B8) // Y3 #define MICROPY_HW_CAN2_NAME "YB" #define MICROPY_HW_CAN2_TX (pin_B13) // Y6 #define MICROPY_HW_CAN2_RX (pin_B12) // Y5 // USRSW has no pullup or pulldown, and pressing the switch makes the input go low #define MICROPY_HW_USRSW_PIN (pin_B3) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // The pyboard has 4 LEDs #define MICROPY_HW_LED1 (pin_A13) // red #define MICROPY_HW_LED2 (pin_A14) // green #define MICROPY_HW_LED3 (pin_A15) // yellow #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // MMA accelerometer config #define MICROPY_HW_MMA_AVDD_PIN (pin_B5) // Bootloader configuration (only needed if Mboot is used) #define MBOOT_I2C_PERIPH_ID 1 #define MBOOT_I2C_SCL (pin_B8) #define MBOOT_I2C_SDA (pin_B9) #define MBOOT_I2C_ALTFUNC (4) micropython-1.12/ports/stm32/boards/PYBV10/mpconfigboard.mk000066400000000000000000000007401357706137100235000ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv ifeq ($(USE_MBOOT),1) # When using Mboot all the text goes together after the filesystem LD_FILES = boards/stm32f405.ld boards/common_blifs.ld TEXT0_ADDR = 0x08020000 else # When not using Mboot the ISR text goes first, then the rest after the filesystem LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 endif # MicroPython settings MICROPY_VFS_LFS2 = 1 micropython-1.12/ports/stm32/boards/PYBV10/pins.csv000066400000000000000000000010311357706137100220150ustar00rootroot00000000000000X1,PA0 X2,PA1 X3,PA2 X4,PA3 X5,PA4 X6,PA5 X7,PA6 X8,PA7 X9,PB6 X10,PB7 X11,PC4 X12,PC5 X13,Reset X14,GND X15,3.3V X16,VIN X17,PB3 X18,PC13 X19,PC0 X20,PC1 X21,PC2 X22,PC3 X23,A3.3V X24,AGND Y1,PC6 Y2,PC7 Y3,PB8 Y4,PB9 Y5,PB12 Y6,PB13 Y7,PB14 Y8,PB15 Y9,PB10 Y10,PB11 Y11,PB0 Y12,PB1 Y13,Reset Y14,GND Y15,3.3V Y16,VIN SW,PB3 LED_RED,PA13 LED_GREEN,PA14 LED_YELLOW,PA15 LED_BLUE,PB4 MMA_INT,PB2 MMA_AVDD,PB5 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD,PA8 SD_SW,PA8 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/PYBV10/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100241170ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/PYBV11/000077500000000000000000000000001357706137100203355ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/PYBV11/mpconfigboard.h000066400000000000000000000075421357706137100233300ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "PYBv1.1" #define MICROPY_HW_MCU_NAME "STM32F405RG" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_HAS_MMA7660 (1) #define MICROPY_HW_HAS_LCD (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 12MHz #define MICROPY_HW_CLK_PLLM (12) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) #define MICROPY_HW_CLK_LAST_FREQ (1) // The pyboard has a 32kHz crystal for the RTC #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (0) #define MICROPY_HW_RTC_USE_CALOUT (1) // UART config #define MICROPY_HW_UART1_NAME "XB" #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_NAME "YB" #define MICROPY_HW_UART3_TX (pin_B10) #define MICROPY_HW_UART3_RX (pin_B11) #define MICROPY_HW_UART3_RTS (pin_B14) #define MICROPY_HW_UART3_CTS (pin_B13) #define MICROPY_HW_UART4_NAME "XA" #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART6_NAME "YA" #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_NAME "X" #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_NAME "Y" #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NAME "X" #define MICROPY_HW_SPI1_NSS (pin_A4) // X5 #define MICROPY_HW_SPI1_SCK (pin_A5) // X6 #define MICROPY_HW_SPI1_MISO (pin_A6) // X7 #define MICROPY_HW_SPI1_MOSI (pin_A7) // X8 #define MICROPY_HW_SPI2_NAME "Y" #define MICROPY_HW_SPI2_NSS (pin_B12) // Y5 #define MICROPY_HW_SPI2_SCK (pin_B13) // Y6 #define MICROPY_HW_SPI2_MISO (pin_B14) // Y7 #define MICROPY_HW_SPI2_MOSI (pin_B15) // Y8 // CAN busses #define MICROPY_HW_CAN1_NAME "YA" #define MICROPY_HW_CAN1_TX (pin_B9) // Y4 #define MICROPY_HW_CAN1_RX (pin_B8) // Y3 #define MICROPY_HW_CAN2_NAME "YB" #define MICROPY_HW_CAN2_TX (pin_B13) // Y6 #define MICROPY_HW_CAN2_RX (pin_B12) // Y5 // USRSW has no pullup or pulldown, and pressing the switch makes the input go low #define MICROPY_HW_USRSW_PIN (pin_B3) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // The pyboard has 4 LEDs #define MICROPY_HW_LED1 (pin_A13) // red #define MICROPY_HW_LED2 (pin_A14) // green #define MICROPY_HW_LED3 (pin_A15) // yellow #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // MMA accelerometer config #define MICROPY_HW_MMA_AVDD_PIN (pin_B5) // Bootloader configuration (only needed if Mboot is used) #define MBOOT_I2C_PERIPH_ID 1 #define MBOOT_I2C_SCL (pin_B8) #define MBOOT_I2C_SDA (pin_B9) #define MBOOT_I2C_ALTFUNC (4) micropython-1.12/ports/stm32/boards/PYBV11/mpconfigboard.mk000066400000000000000000000007401357706137100235010ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv ifeq ($(USE_MBOOT),1) # When using Mboot all the text goes together after the filesystem LD_FILES = boards/stm32f405.ld boards/common_blifs.ld TEXT0_ADDR = 0x08020000 else # When not using Mboot the ISR text goes first, then the rest after the filesystem LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 endif # MicroPython settings MICROPY_VFS_LFS2 = 1 micropython-1.12/ports/stm32/boards/PYBV11/pins.csv000066400000000000000000000010311357706137100220160ustar00rootroot00000000000000X1,PA0 X2,PA1 X3,PA2 X4,PA3 X5,PA4 X6,PA5 X7,PA6 X8,PA7 X9,PB6 X10,PB7 X11,PC4 X12,PC5 X13,Reset X14,GND X15,3.3V X16,VIN X17,PB3 X18,PC13 X19,PC0 X20,PC1 X21,PC2 X22,PC3 X23,A3.3V X24,AGND Y1,PC6 Y2,PC7 Y3,PB8 Y4,PB9 Y5,PB12 Y6,PB13 Y7,PB14 Y8,PB15 Y9,PB10 Y10,PB11 Y11,PB0 Y12,PB1 Y13,Reset Y14,GND Y15,3.3V Y16,VIN SW,PB3 LED_RED,PA13 LED_GREEN,PA14 LED_YELLOW,PA15 LED_BLUE,PB4 MMA_INT,PB2 MMA_AVDD,PB5 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD,PA8 SD_SW,PA8 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/PYBV11/stm32f4xx_hal_conf.h000066400000000000000000000010451357706137100241210ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (12000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/PYBV3/000077500000000000000000000000001357706137100202565ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/PYBV3/mpconfigboard.h000066400000000000000000000065151357706137100232500ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "PYBv3" #define MICROPY_HW_MCU_NAME "STM32F405RG" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_HAS_MMA7660 (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // The pyboard has a 32kHz crystal for the RTC #define MICROPY_HW_RTC_USE_LSE (1) // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_TX (pin_B10) #define MICROPY_HW_UART3_RX (pin_B11) #define MICROPY_HW_UART3_RTS (pin_B14) #define MICROPY_HW_UART3_CTS (pin_B13) #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // X-skin: X9=PB6=SCL, X10=PB7=SDA #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) // Y-skin: Y9=PB10=SCL, Y10=PB11=SDA #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NAME "X" #define MICROPY_HW_SPI1_NSS (pin_A4) // X5 #define MICROPY_HW_SPI1_SCK (pin_A5) // X6 #define MICROPY_HW_SPI1_MISO (pin_A6) // X7 #define MICROPY_HW_SPI1_MOSI (pin_A7) // X8 #define MICROPY_HW_SPI2_NAME "Y" #define MICROPY_HW_SPI2_NSS (pin_B12) // Y5 #define MICROPY_HW_SPI2_SCK (pin_B13) // Y6 #define MICROPY_HW_SPI2_MISO (pin_B14) // Y7 #define MICROPY_HW_SPI2_MOSI (pin_B15) // Y8 // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) // Y4 #define MICROPY_HW_CAN1_RX (pin_B8) // Y3 #define MICROPY_HW_CAN2_TX (pin_B13) // Y6 #define MICROPY_HW_CAN2_RX (pin_B12) // Y5 // USRSW has no pullup or pulldown, and pressing the switch makes the input go low #define MICROPY_HW_USRSW_PIN (pin_A13) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED_INVERTED (1) // LEDs are on when pin is driven low #define MICROPY_HW_LED1 (pin_A8) // R1 - red #define MICROPY_HW_LED2 (pin_A10) // R2 - red #define MICROPY_HW_LED3 (pin_C4) // G1 - green #define MICROPY_HW_LED4 (pin_C5) // G2 - green #define MICROPY_HW_LED1_PWM { TIM1, 1, TIM_CHANNEL_1, GPIO_AF1_TIM1 } #define MICROPY_HW_LED2_PWM { TIM1, 1, TIM_CHANNEL_3, GPIO_AF1_TIM1 } #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_C13) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLDOWN) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_SET) // USB VBUS detect pin #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) // MMA accelerometer config #define MICROPY_HW_MMA_AVDD_PIN (pin_B5) micropython-1.12/ports/stm32/boards/PYBV3/mpconfigboard.mk000066400000000000000000000002561357706137100234240ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/PYBV3/pins.csv000066400000000000000000000006461357706137100217520ustar00rootroot00000000000000B13,PB13 B14,PB14 B15,PB15 C6,PC6 C7,PC7 A13,PA13 A14,PA14 A15,PA15 B3,PB3 B4,PB4 B6,PB6 B7,PB7 B8,PB8 B9,PB9 C0,PC0 C1,PC1 C2,PC2 C3,PC3 A0,PA0 A1,PA1 A2,PA2 A3,PA3 A4,PA4 A5,PA5 A6,PA6 A7,PA7 B0,PB0 B1,PB1 B10,PB10 B11,PB11 B12,PB12 LED_R1,PA8 LED_R2,PA10 LED_G1,PC4 LED_G2,PC5 SW,PA13 SD,PC13 MMA_INT,PB2 MMA_AVDD,PB5 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CK,PC12 SD_CMD,PD2 UART1_TX,PA9 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/PYBV3/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100240410ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/PYBV4/000077500000000000000000000000001357706137100202575ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/PYBV4/mpconfigboard.h000066400000000000000000000071571357706137100232540ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "PYBv4" #define MICROPY_HW_MCU_NAME "STM32F405RG" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_HAS_MMA7660 (1) #define MICROPY_HW_HAS_LCD (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // The pyboard has a 32kHz crystal for the RTC #define MICROPY_HW_RTC_USE_LSE (1) // UART config #define MICROPY_HW_UART1_NAME "XB" #define MICROPY_HW_UART1_PORT (GPIOB) #define MICROPY_HW_UART1_PINS (GPIO_PIN_6 | GPIO_PIN_7) #define MICROPY_HW_UART2_PORT (GPIOA) #define MICROPY_HW_UART2_PINS (GPIO_PIN_2 | GPIO_PIN_3) #define MICROPY_HW_UART2_RTS (GPIO_PIN_1) #define MICROPY_HW_UART2_CTS (GPIO_PIN_0) #define MICROPY_HW_UART3_NAME "YB" #define MICROPY_HW_UART3_PORT (GPIOB) #define MICROPY_HW_UART3_PINS (GPIO_PIN_10 | GPIO_PIN_11) #define MICROPY_HW_UART3_RTS (GPIO_PIN_14) #define MICROPY_HW_UART3_CTS (GPIO_PIN_13) #define MICROPY_HW_UART4_NAME "XA" #define MICROPY_HW_UART4_PORT (GPIOA) #define MICROPY_HW_UART4_PINS (GPIO_PIN_0 | GPIO_PIN_1) #define MICROPY_HW_UART6_NAME "YA" #define MICROPY_HW_UART6_PORT (GPIOC) #define MICROPY_HW_UART6_PINS (GPIO_PIN_6 | GPIO_PIN_7) // I2C busses #define MICROPY_HW_I2C1_NAME "X" #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_NAME "Y" #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NAME "X" #define MICROPY_HW_SPI1_NSS (pin_A4) // X5 #define MICROPY_HW_SPI1_SCK (pin_A5) // X6 #define MICROPY_HW_SPI1_MISO (pin_A6) // X7 #define MICROPY_HW_SPI1_MOSI (pin_A7) // X8 #define MICROPY_HW_SPI2_NAME "Y" #define MICROPY_HW_SPI2_NSS (pin_B12) // Y5 #define MICROPY_HW_SPI2_SCK (pin_B13) // Y6 #define MICROPY_HW_SPI2_MISO (pin_B14) // Y7 #define MICROPY_HW_SPI2_MOSI (pin_B15) // Y8 // CAN busses #define MICROPY_HW_CAN1_NAME "YA" #define MICROPY_HW_CAN1_TX (pin_B9) // Y4 #define MICROPY_HW_CAN1_RX (pin_B8) // Y3 #define MICROPY_HW_CAN2_NAME "YB" #define MICROPY_HW_CAN2_TX (pin_B13) // Y6 #define MICROPY_HW_CAN2_RX (pin_B12) // Y5 // USRSW has no pullup or pulldown, and pressing the switch makes the input go low #define MICROPY_HW_USRSW_PIN (pin_B3) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // The pyboard has 4 LEDs #define MICROPY_HW_LED1 (pin_A13) // red #define MICROPY_HW_LED2 (pin_A14) // green #define MICROPY_HW_LED3 (pin_A15) // yellow #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // MMA accelerometer config #define MICROPY_HW_MMA_AVDD_PIN (pin_B5) micropython-1.12/ports/stm32/boards/PYBV4/mpconfigboard.mk000066400000000000000000000002561357706137100234250ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F405xx AF_FILE = boards/stm32f405_af.csv LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/PYBV4/pins.csv000066400000000000000000000010311357706137100217400ustar00rootroot00000000000000X1,PA0 X2,PA1 X3,PA2 X4,PA3 X5,PA4 X6,PA5 X7,PA6 X8,PA7 X9,PB6 X10,PB7 X11,PC4 X12,PC5 X13,Reset X14,GND X15,3.3V X16,VIN X17,PB3 X18,PC13 X19,PC0 X20,PC1 X21,PC2 X22,PC3 X23,A3.3V X24,AGND Y1,PC6 Y2,PC7 Y3,PB8 Y4,PB9 Y5,PB12 Y6,PB13 Y7,PB14 Y8,PB15 Y9,PB10 Y10,PB11 Y11,PB0 Y12,PB1 Y13,Reset Y14,GND Y15,3.3V Y16,VIN SW,PB3 LED_RED,PA13 LED_GREEN,PA14 LED_YELLOW,PA15 LED_BLUE,PB4 MMA_INT,PB2 MMA_AVDD,PB5 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD,PA8 SD_SW,PA8 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/PYBV4/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100240420ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/STM32F411DISC/000077500000000000000000000000001357706137100212225ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/STM32F411DISC/mpconfigboard.h000066400000000000000000000042311357706137100242050ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "F411DISC" #define MICROPY_HW_MCU_NAME "STM32F411" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SERVO (1) // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (5) #define MICROPY_HW_CLK_PLLN (210) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV4) #define MICROPY_HW_CLK_PLLQ (7) // does not have a 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (0) // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B9) //#define MICROPY_HW_I2C2_SCL (pin_B10) //#define MICROPY_HW_I2C2_SDA (pin_B11) #define MICROPY_HW_I2C3_SCL (pin_A8) #define MICROPY_HW_I2C3_SDA (pin_A9) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_D14) // red #define MICROPY_HW_LED2 (pin_D12) // green #define MICROPY_HW_LED3 (pin_D13) // orange #define MICROPY_HW_LED4 (pin_D15) // blue #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) micropython-1.12/ports/stm32/boards/STM32F411DISC/mpconfigboard.mk000066400000000000000000000002561357706137100243700ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F411xE AF_FILE = boards/stm32f411_af.csv LD_FILES = boards/stm32f411.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/STM32F411DISC/pins.csv000066400000000000000000000014111357706137100227050ustar00rootroot00000000000000PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PC4,PC4 PC5,PC5 PB0,PB0 PB1,PB1 PB2,PB2 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PA8,PA8 PA9,PA9 PA10,PA10 PA13,PA13 PA14,PA14 PA15,PA15 PC10,PC10 PC11,PC11 PC12,PC12 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 PC13,PC13 PC14,PC14 PC15,PC15 PH0,PH0 PH1,PH1 LED_GREEN,PD12 LED_ORANGE,PD13 LED_RED,PD14 LED_BLUE,PD15 SW,PA0 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/STM32F411DISC/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100250050ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/STM32F429DISC/000077500000000000000000000000001357706137100212335ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/STM32F429DISC/mpconfigboard.h000066400000000000000000000124461357706137100242250ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "F429I-DISCO" #define MICROPY_HW_MCU_NAME "STM32F429" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) #define MICROPY_HW_UART_REPL PYB_UART_1 #define MICROPY_HW_UART_REPL_BAUD 115200 // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_D8) #define MICROPY_HW_UART2_RX (pin_D9) // I2C busses #define MICROPY_HW_I2C3_SCL (pin_A8) #define MICROPY_HW_I2C3_SDA (pin_C9) // SPI busses //#define MICROPY_HW_SPI1_NSS (pin_A4) //#define MICROPY_HW_SPI1_SCK (pin_A5) //#define MICROPY_HW_SPI1_MISO (pin_A6) //#define MICROPY_HW_SPI1_MOSI (pin_A7) #if defined(USE_USB_HS_IN_FS) // The HS USB uses B14 & B15 for D- and D+ #else #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) #endif //#define MICROPY_HW_SPI4_NSS (pin_E11) //#define MICROPY_HW_SPI4_SCK (pin_E12) //#define MICROPY_HW_SPI4_MISO (pin_E13) //#define MICROPY_HW_SPI4_MOSI (pin_E14) #define MICROPY_HW_SPI5_NSS (pin_F6) #define MICROPY_HW_SPI5_SCK (pin_F7) #define MICROPY_HW_SPI5_MISO (pin_F8) #define MICROPY_HW_SPI5_MOSI (pin_F9) //#define MICROPY_HW_SPI6_NSS (pin_G8) //#define MICROPY_HW_SPI6_SCK (pin_G13) //#define MICROPY_HW_SPI6_MISO (pin_G12) //#define MICROPY_HW_SPI6_MOSI (pin_G14) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_G14) // red #define MICROPY_HW_LED2 (pin_G13) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_HS (1) #define MICROPY_HW_USB_HS_IN_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_B13) #define MICROPY_HW_USB_OTG_ID_PIN (pin_B12) // SDRAM #define MICROPY_HW_SDRAM_SIZE (64 / 8 * 1024 * 1024) // 64 Mbit #define MICROPY_HW_SDRAM_STARTUP_TEST (1) #define MICROPY_HEAP_START sdram_start() #define MICROPY_HEAP_END sdram_end() // Timing configuration for 90 Mhz (11.90ns) of SD clock frequency (180Mhz/2) #define MICROPY_HW_SDRAM_TIMING_TMRD (2) #define MICROPY_HW_SDRAM_TIMING_TXSR (7) #define MICROPY_HW_SDRAM_TIMING_TRAS (4) #define MICROPY_HW_SDRAM_TIMING_TRC (7) #define MICROPY_HW_SDRAM_TIMING_TWR (2) #define MICROPY_HW_SDRAM_TIMING_TRP (2) #define MICROPY_HW_SDRAM_TIMING_TRCD (2) #define MICROPY_HW_SDRAM_REFRESH_RATE (64) // ms #define MICROPY_HW_SDRAM_BURST_LENGTH 2 #define MICROPY_HW_SDRAM_CAS_LATENCY 3 #define MICROPY_HW_SDRAM_COLUMN_BITS_NUM 8 #define MICROPY_HW_SDRAM_ROW_BITS_NUM 12 #define MICROPY_HW_SDRAM_MEM_BUS_WIDTH 16 #define MICROPY_HW_SDRAM_INTERN_BANKS_NUM 4 #define MICROPY_HW_SDRAM_CLOCK_PERIOD 2 #define MICROPY_HW_SDRAM_RPIPE_DELAY 1 #define MICROPY_HW_SDRAM_RBURST (0) #define MICROPY_HW_SDRAM_WRITE_PROTECTION (0) #define MICROPY_HW_SDRAM_AUTOREFRESH_NUM (4) #define MICROPY_HW_FMC_SDCKE1 (pin_B5) #define MICROPY_HW_FMC_SDNE1 (pin_B6) #define MICROPY_HW_FMC_SDCLK (pin_G8) #define MICROPY_HW_FMC_SDNCAS (pin_G15) #define MICROPY_HW_FMC_SDNRAS (pin_F11) #define MICROPY_HW_FMC_SDNWE (pin_C0) #define MICROPY_HW_FMC_BA0 (pin_G4) #define MICROPY_HW_FMC_BA1 (pin_G5) #define MICROPY_HW_FMC_NBL0 (pin_E0) #define MICROPY_HW_FMC_NBL1 (pin_E1) #define MICROPY_HW_FMC_A0 (pin_F0) #define MICROPY_HW_FMC_A1 (pin_F1) #define MICROPY_HW_FMC_A2 (pin_F2) #define MICROPY_HW_FMC_A3 (pin_F3) #define MICROPY_HW_FMC_A4 (pin_F4) #define MICROPY_HW_FMC_A5 (pin_F5) #define MICROPY_HW_FMC_A6 (pin_F12) #define MICROPY_HW_FMC_A7 (pin_F13) #define MICROPY_HW_FMC_A8 (pin_F14) #define MICROPY_HW_FMC_A9 (pin_F15) #define MICROPY_HW_FMC_A10 (pin_G0) #define MICROPY_HW_FMC_A11 (pin_G1) #define MICROPY_HW_FMC_D0 (pin_D14) #define MICROPY_HW_FMC_D1 (pin_D15) #define MICROPY_HW_FMC_D2 (pin_D0) #define MICROPY_HW_FMC_D3 (pin_D1) #define MICROPY_HW_FMC_D4 (pin_E7) #define MICROPY_HW_FMC_D5 (pin_E8) #define MICROPY_HW_FMC_D6 (pin_E9) #define MICROPY_HW_FMC_D7 (pin_E10) #define MICROPY_HW_FMC_D8 (pin_E11) #define MICROPY_HW_FMC_D9 (pin_E12) #define MICROPY_HW_FMC_D10 (pin_E13) #define MICROPY_HW_FMC_D11 (pin_E14) #define MICROPY_HW_FMC_D12 (pin_E15) #define MICROPY_HW_FMC_D13 (pin_D8) #define MICROPY_HW_FMC_D14 (pin_D9) #define MICROPY_HW_FMC_D15 (pin_D10) micropython-1.12/ports/stm32/boards/STM32F429DISC/mpconfigboard.mk000066400000000000000000000002561357706137100244010ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F429xx AF_FILE = boards/stm32f429_af.csv LD_FILES = boards/stm32f429.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/STM32F429DISC/pins.csv000066400000000000000000000020071357706137100227200ustar00rootroot00000000000000PF4,PF4 PF5,PF5 PF2,PF2 PF3,PF3 PF0,PF0 PF1,PF1 PC14,PC14 PC15,PC15 PE6,PE6 PC13,PC13 PE4,PE4 PE5,PE5 PE2,PE2 PE3,PE3 PE0,PE0 PE1,PE1 PB8,PB8 PB9,PB9 PB6,PB6 PB7,PB7 PB4,PB4 PB5,PB5 PG15,PG15 PB3,PB3 PG13,PG13 PG14,PG14 PG11,PG11 PG12,PG12 PG9,PG9 PG10,PG10 PD7,PD7 PD6,PD6 PD5,PD5 PD4,PD4 PD3,PD3 PD2,PD2 PD1,PD1 PD0,PD0 PC12,PC12 PC11,PC11 PC10,PC10 PA15,PA15 PA14,PA14 PA13,PA13 PA12,PA12 PA11,PA11 PA10,PA10 PA9,PA9 PA8,PA8 PC9,PC9 PC8,PC8 PC7,PC7 PC6,PC6 PG8,PG8 PG7,PG7 PG6,PG6 PG5,PG5 PG4,PG4 PF6,PF6 PF8,PF8 PF7,PF7 PF10,PF10 PF9,PF9 PH1,PH1 PH0,PH0 PC1,PC1 PC0,PC0 PC3,PC3 PC2,PC2 PA1,PA1 PA0,PA0 PA3,PA3 PA2,PA2 PA5,PA5 PA4,PA4 PA7,PA7 PA6,PA6 PC5,PC5 PC4,PC4 PB1,PB1 PB0,PB0 PB2,PB2 PF12,PF12 PF11,PF11 PF14,PF14 PF13,PF13 PG0,PG0 PF15,PF15 PE7,PE7 PG1,PG1 PE9,PE9 PE8,PE8 PE11,PE11 PE10,PE10 PE13,PE13 PE12,PE12 PE15,PE15 PE14,PE14 PB11,PB11 PB10,PB10 PB13,PB13 PB12,PB12 PB15,PB15 PB14,PB14 PD9,PD9 PD8,PD8 PD11,PD11 PD10,PD10 PD13,PD13 PD12,PD12 PD15,PD15 PD14,PD14 PG3,PG3 PG2,PG2 SW,PA0 LED_GREEN,PG13 LED_RED,PG14 micropython-1.12/ports/stm32/boards/STM32F429DISC/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100250160ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/STM32F439/000077500000000000000000000000001357706137100205715ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/STM32F439/mpconfigboard.h000066400000000000000000000061471357706137100235640ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "CustomPCB" #define MICROPY_HW_MCU_NAME "STM32F439" #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) // works with no SD card too // SD card detect switch #if MICROPY_HW_ENABLE_SDCARD #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (1) #endif // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (8) //divide external clock by this to get 1MHz #define MICROPY_HW_CLK_PLLN (384) //this number is the PLL clock in MHz #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) //divide PLL clock by this to get core clock #define MICROPY_HW_CLK_PLLQ (8) //divide core clock by this to get 48MHz // USB config #define MICROPY_HW_USB_FS (1) // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) #define MICROPY_HW_UART2_RTS (pin_D1) #define MICROPY_HW_UART2_CTS (pin_D0) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART3_RTS (pin_D12) #define MICROPY_HW_UART3_CTS (pin_D11) #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_A8) #define MICROPY_HW_I2C1_SDA (pin_C9) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #if MICROPY_HW_USB_HS_IN_FS // The HS USB uses B14 & B15 for D- and D+ #else #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) #endif #define MICROPY_HW_SPI3_NSS (pin_E11) #define MICROPY_HW_SPI3_SCK (pin_E12) #define MICROPY_HW_SPI3_MISO (pin_E13) #define MICROPY_HW_SPI3_MOSI (pin_E14) //#define MICROPY_HW_SPI4_NSS (pin_E11) //#define MICROPY_HW_SPI4_SCK (pin_E12) //#define MICROPY_HW_SPI4_MISO (pin_E13) //#define MICROPY_HW_SPI4_MOSI (pin_E14) //#define MICROPY_HW_SPI5_NSS (pin_F6) //#define MICROPY_HW_SPI5_SCK (pin_F7) //#define MICROPY_HW_SPI5_MISO (pin_F8) //#define MICROPY_HW_SPI5_MOSI (pin_F9) //#define MICROPY_HW_SPI6_NSS (pin_G8) //#define MICROPY_HW_SPI6_SCK (pin_G13) //#define MICROPY_HW_SPI6_MISO (pin_G12) //#define MICROPY_HW_SPI6_MOSI (pin_G14) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) micropython-1.12/ports/stm32/boards/STM32F439/mpconfigboard.mk000066400000000000000000000002561357706137100237370ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F439xx AF_FILE = boards/stm32f439_af.csv LD_FILES = boards/stm32f439.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/STM32F439/pins.csv000066400000000000000000000013641357706137100222630ustar00rootroot00000000000000PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 VUSB,PB13 USB1D_N,PB14 USB1D_P,PB15 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PD2,PD2 BOOT0,BOOT0 PA15,PA15 PA13,PA13 PA14,PA14 PB13,PB13 PB14,PB14 PB15,PB15 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 micropython-1.12/ports/stm32/boards/STM32F439/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100243540ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/STM32F4DISC/000077500000000000000000000000001357706137100210605ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/STM32F4DISC/mpconfigboard.h000066400000000000000000000061001357706137100240400ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "F4DISC" #define MICROPY_HW_MCU_NAME "STM32F407" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) // HSE is 8MHz #define MICROPY_HW_CLK_PLLM (8) #define MICROPY_HW_CLK_PLLN (336) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (7) // UART config #if 0 // A9 is used for USB VBUS detect, and A10 is used for USB_FS_ID. // UART1 is also on PB6/7 but PB6 is tied to the Audio SCL line. // Without board modifications, this makes UART1 unusable on this board. #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #endif #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) #define MICROPY_HW_UART2_RTS (pin_A1) #define MICROPY_HW_UART2_CTS (pin_A0) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) #define MICROPY_HW_UART3_RTS (pin_D12) #define MICROPY_HW_UART3_CTS (pin_D11) #if MICROPY_HW_HAS_SWITCH == 0 // NOTE: A0 also connects to the user switch. To use UART4 you should // set MICROPY_HW_HAS_SWITCH to 0, and also remove SB20 (on the back // of the board near the USER switch). #define MICROPY_HW_UART4_TX (pin_A0) #define MICROPY_HW_UART4_RX (pin_A1) #endif // NOTE: PC7 is connected to MCLK on the Audio chip. This is an input signal // so I think as long as you're not using the audio chip then it should // be fine to use as a UART pin. #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI1_NSS (pin_A4) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_A6) #define MICROPY_HW_SPI1_MOSI (pin_A7) #define MICROPY_HW_SPI2_NSS (pin_B12) #define MICROPY_HW_SPI2_SCK (pin_B13) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_D14) // red #define MICROPY_HW_LED2 (pin_D12) // green #define MICROPY_HW_LED3 (pin_D13) // orange #define MICROPY_HW_LED4 (pin_D15) // blue #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) micropython-1.12/ports/stm32/boards/STM32F4DISC/mpconfigboard.mk000066400000000000000000000002561357706137100242260ustar00rootroot00000000000000MCU_SERIES = f4 CMSIS_MCU = STM32F407xx AF_FILE = boards/stm32f405_af.csv LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 micropython-1.12/ports/stm32/boards/STM32F4DISC/pins.csv000066400000000000000000000014111357706137100225430ustar00rootroot00000000000000PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PC4,PC4 PC5,PC5 PB0,PB0 PB1,PB1 PB2,PB2 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PA8,PA8 PA9,PA9 PA10,PA10 PA13,PA13 PA14,PA14 PA15,PA15 PC10,PC10 PC11,PC11 PC12,PC12 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 PC13,PC13 PC14,PC14 PC15,PC15 PH0,PH0 PH1,PH1 LED_GREEN,PD12 LED_ORANGE,PD13 LED_RED,PD14 LED_BLUE,PD15 SW,PA0 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/STM32F4DISC/staccel.py000066400000000000000000000064161357706137100230570ustar00rootroot00000000000000""" Driver for accelerometer on STM32F4 Discover board. Sets accelerometer range at +-2g. Returns list containing X,Y,Z axis acceleration values in 'g' units (9.8m/s^2). See: STM32Cube_FW_F4_V1.1.0/Drivers/BSP/Components/lis302dl/lis302dl.h STM32Cube_FW_F4_V1.1.0/Drivers/BSP/Components/lis302dl/lis302dl.c STM32Cube_FW_F4_V1.1.0/Drivers/BSP/STM32F4-Discovery/stm32f4_discovery.c STM32Cube_FW_F4_V1.1.0/Drivers/BSP/STM32F4-Discovery/stm32f4_discovery.h STM32Cube_FW_F4_V1.1.0/Drivers/BSP/STM32F4-Discovery/stm32f4_discovery_accelerometer.c STM32Cube_FW_F4_V1.1.0/Drivers/BSP/STM32F4-Discovery/stm32f4_discovery_accelerometer.h STM32Cube_FW_F4_V1.1.0/Projects/STM32F4-Discovery/Demonstrations/Src/main.c """ from micropython import const from pyb import Pin from pyb import SPI READWRITE_CMD = const(0x80) MULTIPLEBYTE_CMD = const(0x40) WHO_AM_I_ADDR = const(0x0f) OUT_X_ADDR = const(0x29) OUT_Y_ADDR = const(0x2b) OUT_Z_ADDR = const(0x2d) OUT_T_ADDR = const(0x0c) LIS302DL_WHO_AM_I_VAL = const(0x3b) LIS302DL_CTRL_REG1_ADDR = const(0x20) # Configuration for 100Hz sampling rate, +-2g range LIS302DL_CONF = const(0b01000111) LIS3DSH_WHO_AM_I_VAL = const(0x3f) LIS3DSH_CTRL_REG4_ADDR = const(0x20) LIS3DSH_CTRL_REG5_ADDR = const(0x24) # Configuration for 100Hz sampling rate, +-2g range LIS3DSH_CTRL_REG4_CONF = const(0b01100111) LIS3DSH_CTRL_REG5_CONF = const(0b00000000) class STAccel: def __init__(self): self.cs_pin = Pin('PE3', Pin.OUT_PP, Pin.PULL_NONE) self.cs_pin.high() self.spi = SPI(1, SPI.MASTER, baudrate=328125, polarity=0, phase=1, bits=8) self.who_am_i = self.read_id() if self.who_am_i == LIS302DL_WHO_AM_I_VAL: self.write_bytes(LIS302DL_CTRL_REG1_ADDR, bytearray([LIS302DL_CONF])) self.sensitivity = 18 elif self.who_am_i == LIS3DSH_WHO_AM_I_VAL: self.write_bytes(LIS3DSH_CTRL_REG4_ADDR, bytearray([LIS3DSH_CTRL_REG4_CONF])) self.write_bytes(LIS3DSH_CTRL_REG5_ADDR, bytearray([LIS3DSH_CTRL_REG5_CONF])) self.sensitivity = 0.06 * 256 else: raise Exception('LIS302DL or LIS3DSH accelerometer not present') def convert_raw_to_g(self, x): if x & 0x80: x = x - 256 return x * self.sensitivity / 1000 def read_bytes(self, addr, nbytes): if nbytes > 1: addr |= READWRITE_CMD | MULTIPLEBYTE_CMD else: addr |= READWRITE_CMD self.cs_pin.low() self.spi.send(addr) #buf = self.spi.send_recv(bytearray(nbytes * [0])) # read data, MSB first buf = self.spi.recv(nbytes) self.cs_pin.high() return buf def write_bytes(self, addr, buf): if len(buf) > 1: addr |= MULTIPLEBYTE_CMD self.cs_pin.low() self.spi.send(addr) for b in buf: self.spi.send(b) self.cs_pin.high() def read_id(self): return self.read_bytes(WHO_AM_I_ADDR, 1)[0] def x(self): return self.convert_raw_to_g(self.read_bytes(OUT_X_ADDR, 1)[0]) def y(self): return self.convert_raw_to_g(self.read_bytes(OUT_Y_ADDR, 1)[0]) def z(self): return self.convert_raw_to_g(self.read_bytes(OUT_Z_ADDR, 1)[0]) def xyz(self): return (self.x(), self.y(), self.z()) micropython-1.12/ports/stm32/boards/STM32F4DISC/stm32f4xx_hal_conf.h000066400000000000000000000010441357706137100246430ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H #include "boards/stm32f4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/STM32F769DISC/000077500000000000000000000000001357706137100212425ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/STM32F769DISC/board_init.c000066400000000000000000000010021357706137100235110ustar00rootroot00000000000000#include "drivers/memory/spiflash.h" #include "qspi.h" // This configuration is needed for mboot to be able to write to the external QSPI flash const mp_spiflash_config_t spiflash_config = { .bus_kind = MP_SPIFLASH_BUS_QSPI, .bus.u_qspi.data = NULL, .bus.u_qspi.proto = &qspi_proto, .cache = NULL, }; mp_spiflash_t spiflash_instance; // This init function is needed to memory map the QSPI flash early in the boot process void board_early_init(void) { qspi_init(); qspi_memory_map(); } micropython-1.12/ports/stm32/boards/STM32F769DISC/f769_qspi.ld000066400000000000000000000051651357706137100233210ustar00rootroot00000000000000/* Custom linker script for STM32F769DISC board with external memory-mapped QSPI flash Memory layout: FLASH_QSPI .text_qspi FLASH_APP .isr_vector FLASH_APP .text FLASH_APP .data RAM .data RAM .bss RAM .heap RAM .stack */ MEMORY { FLASH_APP (rx) : ORIGIN = 0x08020000, LENGTH = 1920K /* sectors 4-11 1*128K 7*256K */ FLASH_QSPI (rx) : ORIGIN = 0x90000000, LENGTH = 64M /* external QSPI flash in XIP mode */ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for storage cache */ RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 384K /* SRAM1 = 368K, SRAM2 = 16K */ } /* Produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; ENTRY(Reset_Handler) SECTIONS { /* Define the code that goes in QSPI flash */ .text_qspi : { . = ALIGN(4); *extmod/*(.text* .rodata*) . = ALIGN(4); } >FLASH_QSPI /* The startup code goes first into main flash */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); } >FLASH_APP /* The program code and other data goes into flash */ .text : { . = ALIGN(4); *(.text*) *(.rodata*) . = ALIGN(4); _etext = .; } >FLASH_APP /* Used by the startup to initialize data */ _sidata = LOADADDR(.data); /* The initialized data section */ .data : { . = ALIGN(4); _sdata = .; *(.data*) . = ALIGN(4); _edata = .; } >RAM AT> FLASH_APP /* The uninitialized (zeroed) data section */ .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM /* Define the start of the heap, and make sure we have a minimum size */ .heap : { . = ALIGN(4); . = . + _minimum_heap_size; . = ALIGN(4); } >RAM /* Just checks there is enough RAM for the stack */ .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM } micropython-1.12/ports/stm32/boards/STM32F769DISC/mpconfigboard.h000066400000000000000000000212331357706137100242260ustar00rootroot00000000000000// This board is confirmed to operate using stlink and openocd. // REPL is on UART(1) and is available through the stlink USB-UART device. // To use openocd run "OPENOCD_CONFIG=boards/openocd_stm32f7.cfg" in // the make command. #define MICROPY_HW_BOARD_NAME "F769DISC" #define MICROPY_HW_MCU_NAME "STM32F769" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_BOARD_EARLY_INIT board_early_init void board_early_init(void); // HSE is 25MHz // VCOClock = HSE * PLLN / PLLM = 25 MHz * 432 / 25 = 432 MHz // SYSCLK = VCOClock / PLLP = 432 MHz / 2 = 216 MHz // USB/SDMMC/RNG Clock = VCOClock / PLLQ = 432 MHz / 9 = 48 MHz #define MICROPY_HW_CLK_PLLM (25) #define MICROPY_HW_CLK_PLLN (432) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (9) #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_7 // 210-216 MHz needs 7 wait states // 512MBit external QSPI flash, to be memory mapped #define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (29) #define MICROPY_HW_QSPIFLASH_CS (pin_B6) #define MICROPY_HW_QSPIFLASH_SCK (pin_B2) #define MICROPY_HW_QSPIFLASH_IO0 (pin_C9) #define MICROPY_HW_QSPIFLASH_IO1 (pin_C10) #define MICROPY_HW_QSPIFLASH_IO2 (pin_E2) #define MICROPY_HW_QSPIFLASH_IO3 (pin_D13) // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) #define MICROPY_HW_UART5_TX (pin_C12) #define MICROPY_HW_UART5_RX (pin_D2) #define MICROPY_HW_UART_REPL PYB_UART_1 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C3_SCL (pin_H7) #define MICROPY_HW_I2C3_SDA (pin_H8) // SPI #define MICROPY_HW_SPI2_NSS (pin_A11) #define MICROPY_HW_SPI2_SCK (pin_A12) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_J13) // red #define MICROPY_HW_LED2 (pin_J5) // green #define MICROPY_HW_LED3 (pin_A12) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDMMC2_CK (pin_D6) #define MICROPY_HW_SDMMC2_CMD (pin_D7) #define MICROPY_HW_SDMMC2_D0 (pin_G9) #define MICROPY_HW_SDMMC2_D1 (pin_G10) #define MICROPY_HW_SDMMC2_D2 (pin_B3) #define MICROPY_HW_SDMMC2_D3 (pin_B4) #define MICROPY_HW_SDCARD_DETECT_PIN (pin_I15) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config (CN15 - USB OTG HS with external PHY) #define MICROPY_HW_USB_HS (1) // Ethernet via RMII #define MICROPY_HW_ETH_MDC (pin_C1) #define MICROPY_HW_ETH_MDIO (pin_A2) #define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1) #define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7) #define MICROPY_HW_ETH_RMII_RXD0 (pin_C4) #define MICROPY_HW_ETH_RMII_RXD1 (pin_C5) #define MICROPY_HW_ETH_RMII_TX_EN (pin_G11) #define MICROPY_HW_ETH_RMII_TXD0 (pin_G13) #define MICROPY_HW_ETH_RMII_TXD1 (pin_G14) #if 0 // Optional SDRAM configuration. // Note: This requires SYSCLK <= 200MHz. 192MHz example below: // #define MICROPY_HW_CLK_PLLM (25) // #define MICROPY_HW_CLK_PLLN (384) // #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) // #define MICROPY_HW_CLK_PLLQ (8) #define MICROPY_HW_SDRAM_SIZE (128 * 1024 * 1024 / 8) // 128 Mbit #define MICROPY_HW_SDRAM_STARTUP_TEST (0) #define MICROPY_HEAP_START sdram_start() #define MICROPY_HEAP_END sdram_end() // Timing configuration for 90 Mhz (11.90ns) of SD clock frequency (180Mhz/2) #define MICROPY_HW_SDRAM_TIMING_TMRD (2) #define MICROPY_HW_SDRAM_TIMING_TXSR (7) #define MICROPY_HW_SDRAM_TIMING_TRAS (4) #define MICROPY_HW_SDRAM_TIMING_TRC (7) #define MICROPY_HW_SDRAM_TIMING_TWR (2) #define MICROPY_HW_SDRAM_TIMING_TRP (2) #define MICROPY_HW_SDRAM_TIMING_TRCD (2) #define MICROPY_HW_SDRAM_REFRESH_RATE (64) // ms #define MICROPY_HW_SDRAM_BURST_LENGTH 1 #define MICROPY_HW_SDRAM_CAS_LATENCY 2 #define MICROPY_HW_SDRAM_COLUMN_BITS_NUM 8 #define MICROPY_HW_SDRAM_ROW_BITS_NUM 12 #define MICROPY_HW_SDRAM_MEM_BUS_WIDTH 32 #define MICROPY_HW_SDRAM_INTERN_BANKS_NUM 4 #define MICROPY_HW_SDRAM_CLOCK_PERIOD 2 #define MICROPY_HW_SDRAM_RPIPE_DELAY 0 #define MICROPY_HW_SDRAM_RBURST (1) #define MICROPY_HW_SDRAM_WRITE_PROTECTION (0) #define MICROPY_HW_SDRAM_AUTOREFRESH_NUM (8) // See pins.csv for CPU pin mapping #define MICROPY_HW_FMC_SDCKE0 (pyb_pin_FMC_SDCKE0) #define MICROPY_HW_FMC_SDNE0 (pyb_pin_FMC_SDNE0) #define MICROPY_HW_FMC_SDCLK (pyb_pin_FMC_SDCLK) #define MICROPY_HW_FMC_SDNCAS (pyb_pin_FMC_SDNCAS) #define MICROPY_HW_FMC_SDNRAS (pyb_pin_FMC_SDNRAS) #define MICROPY_HW_FMC_SDNWE (pyb_pin_FMC_SDNWE) #define MICROPY_HW_FMC_BA0 (pyb_pin_FMC_BA0) #define MICROPY_HW_FMC_BA1 (pyb_pin_FMC_BA1) #define MICROPY_HW_FMC_NBL0 (pyb_pin_FMC_NBL0) #define MICROPY_HW_FMC_NBL1 (pyb_pin_FMC_NBL1) #define MICROPY_HW_FMC_NBL2 (pyb_pin_FMC_NBL2) #define MICROPY_HW_FMC_NBL3 (pyb_pin_FMC_NBL3) #define MICROPY_HW_FMC_A0 (pyb_pin_FMC_A0) #define MICROPY_HW_FMC_A1 (pyb_pin_FMC_A1) #define MICROPY_HW_FMC_A2 (pyb_pin_FMC_A2) #define MICROPY_HW_FMC_A3 (pyb_pin_FMC_A3) #define MICROPY_HW_FMC_A4 (pyb_pin_FMC_A4) #define MICROPY_HW_FMC_A5 (pyb_pin_FMC_A5) #define MICROPY_HW_FMC_A6 (pyb_pin_FMC_A6) #define MICROPY_HW_FMC_A7 (pyb_pin_FMC_A7) #define MICROPY_HW_FMC_A8 (pyb_pin_FMC_A8) #define MICROPY_HW_FMC_A9 (pyb_pin_FMC_A9) #define MICROPY_HW_FMC_A10 (pyb_pin_FMC_A10) #define MICROPY_HW_FMC_A11 (pyb_pin_FMC_A11) #define MICROPY_HW_FMC_A12 (pyb_pin_FMC_A12) #define MICROPY_HW_FMC_D0 (pyb_pin_FMC_D0) #define MICROPY_HW_FMC_D1 (pyb_pin_FMC_D1) #define MICROPY_HW_FMC_D2 (pyb_pin_FMC_D2) #define MICROPY_HW_FMC_D3 (pyb_pin_FMC_D3) #define MICROPY_HW_FMC_D4 (pyb_pin_FMC_D4) #define MICROPY_HW_FMC_D5 (pyb_pin_FMC_D5) #define MICROPY_HW_FMC_D6 (pyb_pin_FMC_D6) #define MICROPY_HW_FMC_D7 (pyb_pin_FMC_D7) #define MICROPY_HW_FMC_D8 (pyb_pin_FMC_D8) #define MICROPY_HW_FMC_D9 (pyb_pin_FMC_D9) #define MICROPY_HW_FMC_D10 (pyb_pin_FMC_D10) #define MICROPY_HW_FMC_D11 (pyb_pin_FMC_D11) #define MICROPY_HW_FMC_D12 (pyb_pin_FMC_D12) #define MICROPY_HW_FMC_D13 (pyb_pin_FMC_D13) #define MICROPY_HW_FMC_D14 (pyb_pin_FMC_D14) #define MICROPY_HW_FMC_D15 (pyb_pin_FMC_D15) #define MICROPY_HW_FMC_D16 (pyb_pin_FMC_D16) #define MICROPY_HW_FMC_D17 (pyb_pin_FMC_D17) #define MICROPY_HW_FMC_D18 (pyb_pin_FMC_D18) #define MICROPY_HW_FMC_D19 (pyb_pin_FMC_D19) #define MICROPY_HW_FMC_D20 (pyb_pin_FMC_D20) #define MICROPY_HW_FMC_D21 (pyb_pin_FMC_D21) #define MICROPY_HW_FMC_D22 (pyb_pin_FMC_D22) #define MICROPY_HW_FMC_D23 (pyb_pin_FMC_D23) #define MICROPY_HW_FMC_D24 (pyb_pin_FMC_D24) #define MICROPY_HW_FMC_D25 (pyb_pin_FMC_D25) #define MICROPY_HW_FMC_D26 (pyb_pin_FMC_D26) #define MICROPY_HW_FMC_D27 (pyb_pin_FMC_D27) #define MICROPY_HW_FMC_D28 (pyb_pin_FMC_D28) #define MICROPY_HW_FMC_D29 (pyb_pin_FMC_D29) #define MICROPY_HW_FMC_D30 (pyb_pin_FMC_D30) #define MICROPY_HW_FMC_D31 (pyb_pin_FMC_D31) #endif /******************************************************************************/ // Bootloader configuration // Give Mboot access to the external QSPI flash extern const struct _mp_spiflash_config_t spiflash_config; extern struct _mp_spiflash_t spiflash_instance; #define MBOOT_SPIFLASH_ADDR (0x90000000) #define MBOOT_SPIFLASH_BYTE_SIZE (512 * 128 * 1024) #define MBOOT_SPIFLASH_LAYOUT "/0x90000000/512*128Kg" #define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (128 / 4) // 128k page, 4k erase block #define MBOOT_SPIFLASH_CONFIG (&spiflash_config) #define MBOOT_SPIFLASH_SPIFLASH (&spiflash_instance) micropython-1.12/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk000066400000000000000000000021541357706137100244070ustar00rootroot00000000000000# By default this board is configured to use mboot which must be deployed first USE_MBOOT ?= 1 # By default this board puts some code into external QSPI flash set in XIP mode # USE_MBOOT must be enabled; see f769_qspi.ld for code that goes in QSPI flash USE_QSPI ?= 1 # MCU settings MCU_SERIES = f7 CMSIS_MCU = STM32F769xx MICROPY_FLOAT_IMPL = double AF_FILE = boards/stm32f767_af.csv ifeq ($(USE_MBOOT),1) ifeq ($(USE_QSPI),1) # When using Mboot and QSPI the text is split between internal and external flash LD_FILES = boards/STM32F769DISC/f769_qspi.ld TEXT0_ADDR = 0x08020000 TEXT1_ADDR = 0x90000000 TEXT0_SECTIONS = .isr_vector .text .data TEXT1_SECTIONS = .text_qspi else # When using Mboot but not QSPI all the text goes together after the filesystem LD_FILES = boards/stm32f769.ld boards/common_blifs.ld TEXT0_ADDR = 0x08020000 endif else # When not using Mboot the ISR text goes first, then the rest after the filesystem LD_FILES = boards/stm32f769.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 endif # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 micropython-1.12/ports/stm32/boards/STM32F769DISC/pins.csv000066400000000000000000000032521357706137100227320ustar00rootroot00000000000000A0,PA0 A1,PF10 A2,PF9 A3,PF8 A4,PF7 A5,PF6 D0,PC7 D1,PC6 D2,PG6 D3,PB4 D4,PG7 D5,PA8 D6,PH6 D7,PI3 D8,PI2 D9,PA15 D10,PI0 D11,PB15 D12,PB14 D13,PI1 D14,PB9 D15,PB8 LED1,PJ13 LED2,PJ5 LED3,PA12 SW,PI11 TP1,PH2 TP2,PI8 TP3,PH15 AUDIO_INT,PD6 AUDIO_SDA,PH8 AUDIO_SCL,PH7 EXT_SDA,PB9 EXT_SCL,PB8 EXT_RST,PG3 SD_D0,PG9 SD_D1,PG10 SD_D2,PB3 SD_D3,PB4 SD_CK,PD6 SD_CMD,PD7 SD_SW,PI15 LCD_BL_CTRL,PK3 LCD_INT,PI13 LCD_SDA,PH8 LCD_SCL,PH7 OTG_FS_POWER,PD5 OTG_FS_OVER_CURRENT,PD4 OTG_HS_OVER_CURRENT,PE3 USB_VBUS,PJ12 USB_ID,PA8 USB_DM,PA11 USB_DP,PA12 USB_HS_CLK,PA5 USB_HS_STP,PC0 USB_HS_NXT,PH4 USB_HS_DIR,PI11 USB_HS_D0,PA3 USB_HS_D1,PB0 USB_HS_D2,PB1 USB_HS_D3,PB5 USB_HS_D4,PB10 USB_HS_D5,PB11 USB_HS_D6,PB12 USB_HS_D7,PB13 UART1_TX,PA9 UART1_RX,PA10 UART5_TX,PC12 UART5_RX,PD2 CAN2_TX,PB13 CAN2_RX,PB12 QSPI_CS,PB6 QSPI_CLK,PB2 QSPI_D0,PC9 QSPI_D1,PC10 QSPI_D2,PE2 QSPI_D3,PD13 ETH_REF_CLK,PA1 ETH_MDIO,PA2 ETH_CRS_DV,PA7 ETH_MDC,PC1 ETH_RXD0,PC4 ETH_RXD1,PC5 ETH_TX_EN,PG11 ETH_TXD0,PG13 ETH_TXD1,PG14 FMC_SDCKE0,PH2 FMC_SDNE0,PH3 FMC_SDCLK,PG8 FMC_SDNCAS,PG15 FMC_SDNRAS,PF11 FMC_SDNWE,PH5 FMC_BA0,PG4 FMC_BA1,PG5 FMC_NBL0,PE0 FMC_NBL1,PE1 FMC_NBL2,PI4 FMC_NBL3,PI5 FMC_A0,PF0 FMC_A1,PF1 FMC_A2,PF2 FMC_A3,PF3 FMC_A4,PF4 FMC_A5,PF5 FMC_A6,PF12 FMC_A7,PF13 FMC_A8,PF14 FMC_A9,PF15 FMC_A10,PG0 FMC_A11,PG1 FMC_A12,PG2 FMC_D0,PD14 FMC_D1,PD15 FMC_D2,PD0 FMC_D3,PD1 FMC_D4,PE7 FMC_D5,PE8 FMC_D6,PE9 FMC_D7,PE10 FMC_D8,PE11 FMC_D9,PE12 FMC_D10,PE13 FMC_D11,PE14 FMC_D12,PE15 FMC_D13,PD8 FMC_D14,PD9 FMC_D15,PD10 FMC_D16,PH8 FMC_D17,PH9 FMC_D18,PH10 FMC_D19,PH11 FMC_D20,PH12 FMC_D21,PH13 FMC_D22,PH14 FMC_D23,PH15 FMC_D24,PI0 FMC_D25,PI1 FMC_D26,PI2 FMC_D27,PI3 FMC_D28,PI6 FMC_D29,PI7 FMC_D30,PI9 FMC_D31,PI10 micropython-1.12/ports/stm32/boards/STM32F769DISC/stm32f7xx_hal_conf.h000066400000000000000000000010461357706137100250320ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #include "boards/stm32f7xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (25000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (5000) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/STM32F7DISC/000077500000000000000000000000001357706137100210635ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/STM32F7DISC/board_init.c000066400000000000000000000007521357706137100233450ustar00rootroot00000000000000#include STM32_HAL_H void STM32F7DISC_board_early_init(void) { GPIO_InitTypeDef GPIO_InitStructure; __HAL_RCC_GPIOK_CLK_ENABLE(); // Turn off the backlight. LCD_BL_CTRL = PK3 GPIO_InitStructure.Pin = GPIO_PIN_3; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOK, &GPIO_InitStructure); HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET); } micropython-1.12/ports/stm32/boards/STM32F7DISC/mpconfigboard.h000066400000000000000000000143731357706137100240560ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "F7DISC" #define MICROPY_HW_MCU_NAME "STM32F746" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_BOARD_EARLY_INIT STM32F7DISC_board_early_init void STM32F7DISC_board_early_init(void); // HSE is 25MHz // VCOClock = HSE * PLLN / PLLM = 25 MHz * 384 / 25 = 384 MHz // SYSCLK = VCOClock / PLLP = 384 MHz / 2 = 192 MHz // USB/SDMMC/RNG Clock = VCOClock / PLLQ = 384 MHz / 8 = 48 MHz // Note: SDRAM requires SYSCLK <= 200MHz // SYSCLK can be increased to 216MHz if SDRAM is disabled #define MICROPY_HW_CLK_PLLM (25) #define MICROPY_HW_CLK_PLLN (384) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) #define MICROPY_HW_CLK_PLLQ (8) // From the reference manual, for 2.7V to 3.6V // 151-180 MHz => 5 wait states // 181-210 MHz => 6 wait states // 211-216 MHz => 7 wait states #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_6 // 181-210 MHz => 6 wait states // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_B7) #define MICROPY_HW_UART6_TX (pin_C6) #define MICROPY_HW_UART6_RX (pin_C7) #define MICROPY_HW_UART7_TX (pin_F6) #define MICROPY_HW_UART7_RX (pin_F7) #define MICROPY_HW_UART_REPL PYB_UART_1 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C3_SCL (pin_H7) #define MICROPY_HW_I2C3_SDA (pin_H8) // SPI #define MICROPY_HW_SPI2_NSS (pin_I0) #define MICROPY_HW_SPI2_SCK (pin_I1) #define MICROPY_HW_SPI2_MISO (pin_B14) #define MICROPY_HW_SPI2_MOSI (pin_B15) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) #define MICROPY_HW_CAN2_TX (pin_B13) #define MICROPY_HW_CAN2_RX (pin_B12) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_I11) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_I1) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_C13) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) // USB config (CN13 - USB OTG FS) // The Hardware VBUS detect only works on pin PA9. The STM32F7 Discovery uses // PA9 for VCP_TX functionality and connects the VBUS to pin J12 (so software // only detect). So we don't define the VBUS detect pin since that requires PA9. #define MICROPY_HW_USB_FS (1) /*#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_J12)*/ #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) // Ethernet via RMII #define MICROPY_HW_ETH_MDC (pin_C1) #define MICROPY_HW_ETH_MDIO (pin_A2) #define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1) #define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7) #define MICROPY_HW_ETH_RMII_RXD0 (pin_C4) #define MICROPY_HW_ETH_RMII_RXD1 (pin_C5) #define MICROPY_HW_ETH_RMII_RXER (pin_G2) #define MICROPY_HW_ETH_RMII_TX_EN (pin_G11) #define MICROPY_HW_ETH_RMII_TXD0 (pin_G13) #define MICROPY_HW_ETH_RMII_TXD1 (pin_G14) // SDRAM #define MICROPY_HW_SDRAM_SIZE (64 / 8 * 1024 * 1024) // 64 Mbit #define MICROPY_HW_SDRAM_STARTUP_TEST (1) #define MICROPY_HEAP_START sdram_start() #define MICROPY_HEAP_END sdram_end() // Timing configuration for 90 Mhz (11.90ns) of SD clock frequency (180Mhz/2) #define MICROPY_HW_SDRAM_TIMING_TMRD (2) #define MICROPY_HW_SDRAM_TIMING_TXSR (7) #define MICROPY_HW_SDRAM_TIMING_TRAS (4) #define MICROPY_HW_SDRAM_TIMING_TRC (7) #define MICROPY_HW_SDRAM_TIMING_TWR (2) #define MICROPY_HW_SDRAM_TIMING_TRP (2) #define MICROPY_HW_SDRAM_TIMING_TRCD (2) #define MICROPY_HW_SDRAM_REFRESH_RATE (64) // ms #define MICROPY_HW_SDRAM_BURST_LENGTH 1 #define MICROPY_HW_SDRAM_CAS_LATENCY 2 #define MICROPY_HW_SDRAM_COLUMN_BITS_NUM 8 #define MICROPY_HW_SDRAM_ROW_BITS_NUM 12 #define MICROPY_HW_SDRAM_MEM_BUS_WIDTH 16 #define MICROPY_HW_SDRAM_INTERN_BANKS_NUM 4 #define MICROPY_HW_SDRAM_CLOCK_PERIOD 2 #define MICROPY_HW_SDRAM_RPIPE_DELAY 0 #define MICROPY_HW_SDRAM_RBURST (1) #define MICROPY_HW_SDRAM_WRITE_PROTECTION (0) #define MICROPY_HW_SDRAM_AUTOREFRESH_NUM (8) #define MICROPY_HW_FMC_SDCKE0 (pin_C3) #define MICROPY_HW_FMC_SDNE0 (pin_H3) #define MICROPY_HW_FMC_SDCLK (pin_G8) #define MICROPY_HW_FMC_SDNCAS (pin_G15) #define MICROPY_HW_FMC_SDNRAS (pin_F11) #define MICROPY_HW_FMC_SDNWE (pin_H5) #define MICROPY_HW_FMC_BA0 (pin_G4) #define MICROPY_HW_FMC_BA1 (pin_G5) #define MICROPY_HW_FMC_NBL0 (pin_E0) #define MICROPY_HW_FMC_NBL1 (pin_E1) #define MICROPY_HW_FMC_A0 (pin_F0) #define MICROPY_HW_FMC_A1 (pin_F1) #define MICROPY_HW_FMC_A2 (pin_F2) #define MICROPY_HW_FMC_A3 (pin_F3) #define MICROPY_HW_FMC_A4 (pin_F4) #define MICROPY_HW_FMC_A5 (pin_F5) #define MICROPY_HW_FMC_A6 (pin_F12) #define MICROPY_HW_FMC_A7 (pin_F13) #define MICROPY_HW_FMC_A8 (pin_F14) #define MICROPY_HW_FMC_A9 (pin_F15) #define MICROPY_HW_FMC_A10 (pin_G0) #define MICROPY_HW_FMC_A11 (pin_G1) #define MICROPY_HW_FMC_D0 (pin_D14) #define MICROPY_HW_FMC_D1 (pin_D15) #define MICROPY_HW_FMC_D2 (pin_D0) #define MICROPY_HW_FMC_D3 (pin_D1) #define MICROPY_HW_FMC_D4 (pin_E7) #define MICROPY_HW_FMC_D5 (pin_E8) #define MICROPY_HW_FMC_D6 (pin_E9) #define MICROPY_HW_FMC_D7 (pin_E10) #define MICROPY_HW_FMC_D8 (pin_E11) #define MICROPY_HW_FMC_D9 (pin_E12) #define MICROPY_HW_FMC_D10 (pin_E13) #define MICROPY_HW_FMC_D11 (pin_E14) #define MICROPY_HW_FMC_D12 (pin_E15) #define MICROPY_HW_FMC_D13 (pin_D8) #define MICROPY_HW_FMC_D14 (pin_D9) #define MICROPY_HW_FMC_D15 (pin_D10) micropython-1.12/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk000066400000000000000000000004061357706137100242260ustar00rootroot00000000000000MCU_SERIES = f7 CMSIS_MCU = STM32F746xx AF_FILE = boards/stm32f746_af.csv LD_FILES = boards/stm32f746.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 micropython-1.12/ports/stm32/boards/STM32F7DISC/pins.csv000066400000000000000000000024161357706137100225540ustar00rootroot00000000000000A0,PA0 A1,PF10 A2,PF9 A3,PF8 A4,PF7 A5,PF6 D0,PC7 D1,PC6 D2,PG6 D3,PB4 D4,PG7 D5,PA8 D6,PH6 D7,PI3 D8,PI2 D9,PA15 D10,PI0 D11,PB15 D12,PB14 D13,PI1 D14,PB9 D15,PB8 LED,PI1 SW,PI11 TP1,PH2 TP2,PI8 TP3,PH15 AUDIO_INT,PD6 AUDIO_SDA,PH8 AUDIO_SCL,PH7 EXT_SDA,PB9 EXT_SCL,PB8 EXT_RST,PG3 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 SD_D3,PC11 SD_CK,PC12 SD_CMD,PD2 SD_SW,PC13 LCD_BL_CTRL,PK3 LCD_INT,PI13 LCD_SDA,PH8 LCD_SCL,PH7 OTG_FS_POWER,PD5 OTG_FS_OVER_CURRENT,PD4 OTG_HS_OVER_CURRENT,PE3 USB_VBUS,PJ12 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 VCP_TX,PA9 VCP_RX,PB7 CAN_TX,PB13 CAN_RX,PB12 ETH_MDC,PC1 ETH_MDIO,PA2 ETH_RMII_REF_CLK,PA1 ETH_RMII_CRS_DV,PA7 ETH_RMII_RXD0,PC4 ETH_RMII_RXD1,PC5 ETH_RMII_RXER,PG2 ETH_RMII_TX_EN,PG11 ETH_RMII_TXD0,PG13 ETH_RMII_TXD1,PG14 SDRAM_SDCKE0,PC3 SDRAM_SDNE0,PH3 SDRAM_SDCLK,PG8 SDRAM_SDNCAS,PG15 SDRAM_SDNRAS,PF11 SDRAM_SDNWE,PH5 SDRAM_BA0,PG4 SDRAM_BA1,PG5 SDRAM_NBL0,PE0 SDRAM_NBL1,PE1 SDRAM_A0,PF0 SDRAM_A1,PF1 SDRAM_A2,PF2 SDRAM_A3,PF3 SDRAM_A4,PF4 SDRAM_A5,PF5 SDRAM_A6,PF12 SDRAM_A7,PF13 SDRAM_A8,PF14 SDRAM_A9,PF15 SDRAM_A10,PG0 SDRAM_A11,PG1 SDRAM_D0,PD14 SDRAM_D1,PD15 SDRAM_D2,PD0 SDRAM_D3,PD1 SDRAM_D4,PE7 SDRAM_D5,PE8 SDRAM_D6,PE9 SDRAM_D7,PE10 SDRAM_D8,PE11 SDRAM_D9,PE12 SDRAM_D10,PE13 SDRAM_D11,PE14 SDRAM_D12,PE15 SDRAM_D13,PD8 SDRAM_D14,PD9 SDRAM_D15,PD10 micropython-1.12/ports/stm32/boards/STM32F7DISC/stm32f7xx_hal_conf.h000066400000000000000000000010461357706137100246530ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #include "boards/stm32f7xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (25000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (5000) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/STM32L476DISC/000077500000000000000000000000001357706137100212435ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/STM32L476DISC/bdev.c000066400000000000000000000011721357706137100223300ustar00rootroot00000000000000#include "storage.h" // External SPI flash uses standard SPI interface STATIC const mp_soft_spi_obj_t soft_spi_bus = { .delay_half = MICROPY_HW_SOFTSPI_MIN_DELAY, .polarity = 0, .phase = 0, .sck = MICROPY_HW_SPIFLASH_SCK, .mosi = MICROPY_HW_SPIFLASH_MOSI, .miso = MICROPY_HW_SPIFLASH_MISO, }; STATIC mp_spiflash_cache_t spi_bdev_cache; const mp_spiflash_config_t spiflash_config = { .bus_kind = MP_SPIFLASH_BUS_SPI, .bus.u_spi.cs = MICROPY_HW_SPIFLASH_CS, .bus.u_spi.data = (void*)&soft_spi_bus, .bus.u_spi.proto = &mp_soft_spi_proto, .cache = &spi_bdev_cache, }; spi_bdev_t spi_bdev; micropython-1.12/ports/stm32/boards/STM32L476DISC/board_init.c000066400000000000000000000003641357706137100235240ustar00rootroot00000000000000#include "py/mphal.h" void STM32L476DISC_board_early_init(void) { // set SPI flash WP and HOLD pins high mp_hal_pin_output(pin_E14); mp_hal_pin_output(pin_E15); mp_hal_pin_write(pin_E14, 1); mp_hal_pin_write(pin_E15, 1); } micropython-1.12/ports/stm32/boards/STM32L476DISC/mpconfigboard.h000066400000000000000000000060171357706137100242320ustar00rootroot00000000000000#define MICROPY_BOARD_EARLY_INIT STM32L476DISC_board_early_init void STM32L476DISC_board_early_init(void); #define MICROPY_HW_BOARD_NAME "L476-DISCO" #define MICROPY_HW_MCU_NAME "STM32L476" #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_SERVO (1) #define MICROPY_HW_ENABLE_USB (1) // use external SPI flash for storage #define MICROPY_HW_SPIFLASH_SIZE_BITS (128 * 1024 * 1024) #define MICROPY_HW_SPIFLASH_CS (pin_E11) #define MICROPY_HW_SPIFLASH_SCK (pin_E10) #define MICROPY_HW_SPIFLASH_MOSI (pin_E12) #define MICROPY_HW_SPIFLASH_MISO (pin_E13) // block device config for SPI flash extern const struct _mp_spiflash_config_t spiflash_config; extern struct _spi_bdev_t spi_bdev; #define MICROPY_HW_BDEV_IOCTL(op, arg) ( \ (op) == BDEV_IOCTL_NUM_BLOCKS ? (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE) : \ (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \ spi_bdev_ioctl(&spi_bdev, (op), (arg)) \ ) #define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n)) #define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n)) // MSI is used and is 4MHz #define MICROPY_HW_CLK_PLLM (1) #define MICROPY_HW_CLK_PLLN (40) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // USART config #define MICROPY_HW_UART2_TX (pin_D5) #define MICROPY_HW_UART2_RX (pin_D6) // USART 2 is connected to the virtual com port on the ST-LINK #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B6) #define MICROPY_HW_I2C1_SDA (pin_B7) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) // SPI busses #define MICROPY_HW_SPI2_NSS (pin_D0) #define MICROPY_HW_SPI2_SCK (pin_D1) #define MICROPY_HW_SPI2_MISO (pin_D3) #define MICROPY_HW_SPI2_MOSI (pin_D4) // CAN busses #define MICROPY_HW_CAN1_TX (pin_B9) #define MICROPY_HW_CAN1_RX (pin_B8) // Joystick is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LEDs #define MICROPY_HW_LED1 (pin_B2) // red #define MICROPY_HW_LED2 (pin_E8) // green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) // #define MICROPY_HW_USB_OTG_ID_PIN (pin_C12) // This is not the official ID Pin which should be PA10 micropython-1.12/ports/stm32/boards/STM32L476DISC/mpconfigboard.mk000066400000000000000000000002561357706137100244110ustar00rootroot00000000000000MCU_SERIES = l4 CMSIS_MCU = STM32L476xx AF_FILE = boards/stm32l476_af.csv LD_FILES = boards/stm32l476xg.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg micropython-1.12/ports/stm32/boards/STM32L476DISC/pins.csv000066400000000000000000000017441357706137100227370ustar00rootroot00000000000000PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA13,PA13 PA14,PA14 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 PF0,PF0 PF1,PF1 PF2,PF2 PF3,PF3 PF4,PF4 PF5,PF5 PF6,PF6 PF7,PF7 PF8,PF8 PF9,PF9 PF10,PF10 PF11,PF11 PF12,PF12 PF13,PF13 PF14,PF14 PF15,PF15 PG0,PG0 PG1,PG1 PG2,PG2 PG3,PG3 PG4,PG4 PG5,PG5 PG6,PG6 PG7,PG7 PG8,PG8 PG9,PG9 PG10,PG10 PG11,PG11 PG12,PG12 PG13,PG13 PG14,PG14 PG15,PG15 PH0,PH0 PH1,PH1 micropython-1.12/ports/stm32/boards/STM32L476DISC/stm32l4xx_hal_conf.h000066400000000000000000000011201357706137100250270ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #include "boards/stm32l4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) #define EXTERNAL_SAI2_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/STM32L496GDISC/000077500000000000000000000000001357706137100213545ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/STM32L496GDISC/mpconfigboard.h000066400000000000000000000036151357706137100243440ustar00rootroot00000000000000#define MICROPY_HW_BOARD_NAME "L496G-DISCO" #define MICROPY_HW_MCU_NAME "STM32L496" #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_TIMER (1) #define MICROPY_HW_ENABLE_USB (1) // MSI is used and is 4MHz, // Resulting core frequency is 80MHz: #define MICROPY_HW_CLK_PLLM (1) #define MICROPY_HW_CLK_PLLN (40) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) // USART config #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_D6) // USART 2 is connected to the virtual com port on the ST-LINK #define MICROPY_HW_UART_REPL PYB_UART_2 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_G14) #define MICROPY_HW_I2C1_SDA (pin_G13) #define MICROPY_HW_I2C2_SCL (pin_H4) #define MICROPY_HW_I2C2_SDA (pin_B14) // SPI busses // -> To the arduino connector #define MICROPY_HW_SPI1_NSS (pin_A15) #define MICROPY_HW_SPI1_SCK (pin_A5) #define MICROPY_HW_SPI1_MISO (pin_B4) #define MICROPY_HW_SPI1_MOSI (pin_B5) // Use Sel from joystick. Joystick is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) #define MICROPY_HW_USRSW_PULL (GPIO_PULLDOWN) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) #define MICROPY_HW_USRSW_PRESSED (1) // LED (The orange LED is controlled over MFX) #define MICROPY_HW_LED1 (pin_B13) // Green #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) // USB config #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) micropython-1.12/ports/stm32/boards/STM32L496GDISC/mpconfigboard.mk000066400000000000000000000002561357706137100245220ustar00rootroot00000000000000MCU_SERIES = l4 CMSIS_MCU = STM32L496xx AF_FILE = boards/stm32l496_af.csv LD_FILES = boards/stm32l496xg.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg micropython-1.12/ports/stm32/boards/STM32L496GDISC/pins.csv000066400000000000000000000023041357706137100230410ustar00rootroot00000000000000PA0,PA0 PA1,PA1 PA2,PA2 PA3,PA3 PA4,PA4 PA5,PA5 PA6,PA6 PA7,PA7 PA8,PA8 PA9,PA9 PA10,PA10 PA11,PA11 PA12,PA12 PA13,PA13 PA14,PA14 PA15,PA15 PB0,PB0 PB1,PB1 PB2,PB2 PB3,PB3 PB4,PB4 PB5,PB5 PB6,PB6 PB7,PB7 PB8,PB8 PB9,PB9 PB10,PB10 PB11,PB11 PB12,PB12 PB13,PB13 PB14,PB14 PB15,PB15 PC0,PC0 PC1,PC1 PC2,PC2 PC3,PC3 PC4,PC4 PC5,PC5 PC6,PC6 PC7,PC7 PC8,PC8 PC9,PC9 PC10,PC10 PC11,PC11 PC12,PC12 PC13,PC13 PC14,PC14 PC15,PC15 PD0,PD0 PD1,PD1 PD2,PD2 PD3,PD3 PD4,PD4 PD5,PD5 PD6,PD6 PD7,PD7 PD8,PD8 PD9,PD9 PD10,PD10 PD11,PD11 PD12,PD12 PD13,PD13 PD14,PD14 PD15,PD15 PE0,PE0 PE1,PE1 PE2,PE2 PE3,PE3 PE4,PE4 PE5,PE5 PE6,PE6 PE7,PE7 PE8,PE8 PE9,PE9 PE10,PE10 PE11,PE11 PE12,PE12 PE13,PE13 PE14,PE14 PE15,PE15 PF0,PF0 PF1,PF1 PF2,PF2 PF3,PF3 PF4,PF4 PF5,PF5 PF6,PF6 PF7,PF7 PF8,PF8 PF9,PF9 PF10,PF10 PF11,PF11 PF12,PF12 PF13,PF13 PF14,PF14 PF15,PF15 PG0,PG0 PG1,PG1 PG2,PG2 PG3,PG3 PG4,PG4 PG5,PG5 PG6,PG6 PG7,PG7 PG8,PG8 PG9,PG9 PG10,PG10 PG11,PG11 PG12,PG12 PG13,PG13 PG14,PG14 PG15,PG15 PH0,PH0 PH1,PH1 PH2,PH2 PH3,PH3 PH4,PH4 PH5,PH5 PH6,PH6 PH7,PH7 PH8,PH8 PH9,PH9 PH10,PH10 PH11,PH11 PH12,PH12 PH13,PH13 PH14,PH14 PH15,PH15 PI0,PI0 PI1,PI1 PI2,PI2 PI3,PI3 PI4,PI4 PI5,PI5 PI6,PI6 PI7,PI7 PI8,PI8 PI9,PI9 PI10,PI10 PI11,PI11 micropython-1.12/ports/stm32/boards/STM32L496GDISC/stm32l4xx_hal_conf.h000066400000000000000000000011201357706137100251400ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H #include "boards/stm32l4xx_hal_conf_base.h" // Oscillator values in Hz #define HSE_VALUE (8000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) #define EXTERNAL_SAI2_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H micropython-1.12/ports/stm32/boards/USBDONGLE_WB55/000077500000000000000000000000001357706137100214775ustar00rootroot00000000000000micropython-1.12/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h000066400000000000000000000031171357706137100244640ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * MIT License; Copyright (c) 2019 Damien P. George */ #define MICROPY_HW_BOARD_NAME "USBDongle-WB55" #define MICROPY_HW_MCU_NAME "STM32WB55CGU6" #define MICROPY_PY_PYB_LEGACY (0) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_ADC (0) #define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_HAS_SWITCH (1) // There is an external 32kHz oscillator #define RTC_ASYNCH_PREDIV (0) #define RTC_SYNCH_PREDIV (0x7fff) #define MICROPY_HW_RTC_USE_LSE (1) #define MICROPY_HW_RTC_USE_US (1) // I2C buses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) // User switch; pressing the button makes the input go low #define MICROPY_HW_USRSW_PIN (pin_A10) #define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) #define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) #define MICROPY_HW_USRSW_PRESSED (0) // LEDs #define MICROPY_HW_LED1 (pin_B1) // red #define MICROPY_HW_LED2 (pin_B0) // green #define MICROPY_HW_LED3 (pin_A4) // blue #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_FS (1) #define USBD_CDC_RX_DATA_SIZE (512) #define USBD_CDC_TX_DATA_SIZE (512) // Bluetooth config #define MICROPY_HW_BLE_UART_ID (0) #define MICROPY_HW_BLE_UART_BAUDRATE (115200) micropython-1.12/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk000066400000000000000000000005001357706137100246350ustar00rootroot00000000000000MCU_SERIES = wb CMSIS_MCU = STM32WB55xx AF_FILE = boards/stm32wb55_af.csv LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld STARTUP_FILE = lib/stm32lib/CMSIS/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.o # MicroPython settings MICROPY_PY_BLUETOOTH = 1 MICROPY_BLUETOOTH_NIMBLE = 1 MICROPY_VFS_LFS2 = 1 micropython-1.12/ports/stm32/boards/USBDONGLE_WB55/pins.csv000066400000000000000000000003171357706137100231660ustar00rootroot00000000000000,PA0 ,PA1 ,PA2 ,PA3 ,PA4 ,PA5 ,PA6 ,PA7 ,PA8 ,PA9 ,PA10 ,PA11 ,PA12 ,PA13 ,PA14 ,PA15 ,PB0 ,PB1 ,PB2 ,PB3 ,PB4 ,PB5 ,PB6 ,PB7 ,PB8 ,PB9 SW,PA10 LED_GREEN,PB0 LED_RED,PB1 LED_BLUE,PA4 USB_DM,PA11 USB_DP,PA12 micropython-1.12/ports/stm32/boards/USBDONGLE_WB55/stm32wbxx_hal_conf.h000066400000000000000000000010471357706137100253640ustar00rootroot00000000000000/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) * Copyright (c) 2019 Damien P. George */ #ifndef MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H #define MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H // Oscillator values in Hz #define HSE_VALUE (32000000) #define LSE_VALUE (32768) #define EXTERNAL_SAI1_CLOCK_VALUE (48000) // Oscillator timeouts in ms #define HSE_STARTUP_TIMEOUT (100) #define LSE_STARTUP_TIMEOUT (5000) #include "boards/stm32wbxx_hal_conf_base.h" #endif // MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H micropython-1.12/ports/stm32/boards/common_basic.ld000066400000000000000000000045431357706137100223730ustar00rootroot00000000000000/* Memory layout for basic configuration: FLASH .isr_vector FLASH .text FLASH .data RAM .data RAM .bss RAM .heap RAM .stack */ ENTRY(Reset_Handler) /* define output sections */ SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text*) /* .text* sections (code) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ /* *(.glue_7t) */ /* glue thumb to arm code */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ } >FLASH /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM AT> FLASH /* Uninitialized data section */ .bss : { . = ALIGN(4); _sbss = .; /* define a global symbol at bss start; used by startup code */ *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end; used by startup code and GC */ } >RAM /* this is to define the start of the heap, and make sure we have a minimum size */ .heap : { . = ALIGN(4); . = . + _minimum_heap_size; . = ALIGN(4); } >RAM /* this just checks there is enough RAM for the stack */ .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM .ARM.attributes 0 : { *(.ARM.attributes) } } micropython-1.12/ports/stm32/boards/common_bl.ld000066400000000000000000000046271357706137100217120ustar00rootroot00000000000000/* Memory layout for bootloader configuration (this here describes the app part): FLASH_APP .isr_vector FLASH_APP .text FLASH_APP .data RAM .data RAM .bss RAM .heap RAM .stack */ ENTRY(Reset_Handler) /* define output sections */ SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH_APP /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text*) /* .text* sections (code) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ /* *(.glue_7t) */ /* glue thumb to arm code */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ } >FLASH_APP /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM AT> FLASH_APP /* Uninitialized data section */ .bss : { . = ALIGN(4); _sbss = .; /* define a global symbol at bss start; used by startup code */ *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end; used by startup code and GC */ } >RAM /* this is to define the start of the heap, and make sure we have a minimum size */ .heap : { . = ALIGN(4); . = . + _minimum_heap_size; . = ALIGN(4); } >RAM /* this just checks there is enough RAM for the stack */ .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM .ARM.attributes 0 : { *(.ARM.attributes) } } micropython-1.12/ports/stm32/boards/common_blifs.ld000066400000000000000000000046621357706137100224130ustar00rootroot00000000000000/* Memory layout for bootloader and internal filesystem configuration (this here describes the app part): FLASH_TEXT .isr_vector FLASH_TEXT .text FLASH_TEXT .data RAM .data RAM .bss RAM .heap RAM .stack */ ENTRY(Reset_Handler) /* define output sections */ SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH_TEXT /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text*) /* .text* sections (code) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ /* *(.glue_7t) */ /* glue thumb to arm code */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ } >FLASH_TEXT /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM AT> FLASH_TEXT /* Uninitialized data section */ .bss : { . = ALIGN(4); _sbss = .; /* define a global symbol at bss start; used by startup code */ *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end; used by startup code and GC */ } >RAM /* this is to define the start of the heap, and make sure we have a minimum size */ .heap : { . = ALIGN(4); . = . + _minimum_heap_size; . = ALIGN(4); } >RAM /* this just checks there is enough RAM for the stack */ .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM .ARM.attributes 0 : { *(.ARM.attributes) } } micropython-1.12/ports/stm32/boards/common_ifs.ld000066400000000000000000000056521357706137100220750ustar00rootroot00000000000000/* Memory layout for internal flash storage configuration: FLASH_ISR .isr_vector FLASH_TEXT .text FLASH_TEXT .data RAM .data RAM .bss RAM .heap RAM .stack */ ENTRY(Reset_Handler) /* define output sections */ SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ /* This first flash block is 16K annd the isr vectors only take up about 400 bytes. So we pull in a couple of object files to pad it out. */ . = ALIGN(4); /* NOTE: If you update the list of files contained in .isr_vector, then be sure to also update smhal/Makefile where it forcibly builds each of these files with -Os */ */ff.o(.text*) */vfs_fat_*.o(.text*) */py/formatfloat.o(.text*) */py/parsenum.o(.text*) */py/mpprint.o(.text*) . = ALIGN(4); } >FLASH_ISR /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text*) /* .text* sections (code) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ /* *(.glue_7t) */ /* glue thumb to arm code */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ } >FLASH_TEXT /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM AT> FLASH_TEXT /* Uninitialized data section */ .bss : { . = ALIGN(4); _sbss = .; /* define a global symbol at bss start; used by startup code */ *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end; used by startup code and GC */ } >RAM /* this is to define the start of the heap, and make sure we have a minimum size */ .heap : { . = ALIGN(4); . = . + _minimum_heap_size; . = ALIGN(4); } >RAM /* this just checks there is enough RAM for the stack */ .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM .ARM.attributes 0 : { *(.ARM.attributes) } } micropython-1.12/ports/stm32/boards/make-pins.py000077500000000000000000000467771357706137100217010ustar00rootroot00000000000000#!/usr/bin/env python """Creates the pin file for the STM32F4xx.""" from __future__ import print_function import argparse import sys import csv # Must have matching entries in AF_FN_* enum in ../pin_defs_stm32.h SUPPORTED_FN = { 'TIM' : ['CH1', 'CH2', 'CH3', 'CH4', 'CH1N', 'CH2N', 'CH3N', 'CH1_ETR', 'ETR', 'BKIN'], 'I2C' : ['SDA', 'SCL'], 'I2S' : ['CK', 'MCK', 'SD', 'WS', 'EXTSD'], 'USART' : ['RX', 'TX', 'CTS', 'RTS', 'CK'], 'UART' : ['RX', 'TX', 'CTS', 'RTS'], 'SPI' : ['NSS', 'SCK', 'MISO', 'MOSI'], 'SDMMC' : ['CK', 'CMD', 'D0', 'D1', 'D2', 'D3'], 'CAN' : ['TX', 'RX'], } CONDITIONAL_VAR = { 'I2C' : 'MICROPY_HW_I2C{num}_SCL', 'I2S' : 'MICROPY_HW_ENABLE_I2S{num}', 'SPI' : 'MICROPY_HW_SPI{num}_SCK', 'UART' : 'MICROPY_HW_UART{num}_TX', 'USART' : 'MICROPY_HW_UART{num}_TX', 'SDMMC' : 'MICROPY_HW_SDMMC{num}_CK', 'CAN' : 'MICROPY_HW_CAN{num}_TX', } def parse_port_pin(name_str): """Parses a string and returns a (port-num, pin-num) tuple.""" if len(name_str) < 3: raise ValueError("Expecting pin name to be at least 3 charcters.") if name_str[0] != 'P': raise ValueError("Expecting pin name to start with P") if name_str[1] < 'A' or name_str[1] > 'K': raise ValueError("Expecting pin port to be between A and K") port = ord(name_str[1]) - ord('A') pin_str = name_str[2:] if not pin_str.isdigit(): raise ValueError("Expecting numeric pin number.") return (port, int(pin_str)) def split_name_num(name_num): num = None for num_idx in range(len(name_num) - 1, -1, -1): if not name_num[num_idx].isdigit(): name = name_num[0:num_idx + 1] num_str = name_num[num_idx + 1:] if len(num_str) > 0: num = int(num_str) break return name, num def conditional_var(name_num): # Try the specific instance first. For example, if name_num is UART4_RX # then try UART4 first, and then try UART second. name, num = split_name_num(name_num) var = [] if name in CONDITIONAL_VAR: var.append(CONDITIONAL_VAR[name].format(num=num)) if name_num in CONDITIONAL_VAR: var.append(CONDITIONAL_VAR[name_num]) return var def print_conditional_if(cond_var, file=None): if cond_var: cond_str = [] for var in cond_var: if var.find('ENABLE') >= 0: cond_str.append('(defined({0}) && {0})'.format(var)) else: cond_str.append('defined({0})'.format(var)) print('#if ' + ' || '.join(cond_str), file=file) def print_conditional_endif(cond_var, file=None): if cond_var: print('#endif', file=file) class AlternateFunction(object): """Holds the information associated with a pins alternate function.""" def __init__(self, idx, af_str): self.idx = idx # Special case. We change I2S2ext_SD into I2S2_EXTSD so that it parses # the same way the other peripherals do. af_str = af_str.replace('ext_', '_EXT') self.af_str = af_str self.func = '' self.fn_num = None self.pin_type = '' self.supported = False af_words = af_str.split('_', 1) self.func, self.fn_num = split_name_num(af_words[0]) if len(af_words) > 1: self.pin_type = af_words[1] if self.func in SUPPORTED_FN: pin_types = SUPPORTED_FN[self.func] if self.pin_type in pin_types: self.supported = True def is_supported(self): return self.supported def ptr(self): """Returns the numbered function (i.e. USART6) for this AF.""" if self.fn_num is None: return self.func return '{:s}{:d}'.format(self.func, self.fn_num) def mux_name(self): return 'AF{:d}_{:s}'.format(self.idx, self.ptr()) def print(self): """Prints the C representation of this AF.""" cond_var = None if self.supported: cond_var = conditional_var('{}{}'.format(self.func, self.fn_num)) print_conditional_if(cond_var) print(' AF', end='') else: print(' //', end='') fn_num = self.fn_num if fn_num is None: fn_num = 0 print('({:2d}, {:8s}, {:2d}, {:10s}, {:8s}), // {:s}'.format(self.idx, self.func, fn_num, self.pin_type, self.ptr(), self.af_str)) print_conditional_endif(cond_var) def qstr_list(self): return [self.mux_name()] class Pin(object): """Holds the information associated with a pin.""" def __init__(self, port, pin): self.port = port self.pin = pin self.alt_fn = [] self.alt_fn_count = 0 self.adc_num = 0 self.adc_channel = 0 self.board_pin = False def port_letter(self): return chr(self.port + ord('A')) def cpu_pin_name(self): return '{:s}{:d}'.format(self.port_letter(), self.pin) def is_board_pin(self): return self.board_pin def set_is_board_pin(self): self.board_pin = True def parse_adc(self, adc_str): if (adc_str[:3] != 'ADC'): return if adc_str.find('_INP') != -1: # STM32H7xx, entries have the form: ADCxx_IN[PN]yy/... # for now just pick the entry with the most ADC periphs adc, channel = None, None for ss in adc_str.split('/'): if ss.find('_INP') != -1: a, c = ss.split('_') if adc is None or len(a) > len(adc): adc, channel = a, c if adc is None: return channel = channel[3:] else: # all other MCUs, entries have the form: ADCxx_INyy adc, channel = adc_str.split('_') channel = channel[2:] for idx in range(3, len(adc)): adc_num = int(adc[idx]) # 1, 2, or 3 self.adc_num |= (1 << (adc_num - 1)) self.adc_channel = int(channel) def parse_af(self, af_idx, af_strs_in): if len(af_strs_in) == 0: return # If there is a slash, then the slash separates 2 aliases for the # same alternate function. af_strs = af_strs_in.split('/') for af_str in af_strs: alt_fn = AlternateFunction(af_idx, af_str) self.alt_fn.append(alt_fn) if alt_fn.is_supported(): self.alt_fn_count += 1 def alt_fn_name(self, null_if_0=False): if null_if_0 and self.alt_fn_count == 0: return 'NULL' return 'pin_{:s}_af'.format(self.cpu_pin_name()) def adc_num_str(self): str = '' for adc_num in range(1,4): if self.adc_num & (1 << (adc_num - 1)): if len(str) > 0: str += ' | ' str += 'PIN_ADC' str += chr(ord('0') + adc_num) if len(str) == 0: str = '0' return str def print(self): if self.alt_fn_count == 0: print("// ", end='') print('const pin_af_obj_t {:s}[] = {{'.format(self.alt_fn_name())) for alt_fn in self.alt_fn: alt_fn.print() if self.alt_fn_count == 0: print("// ", end='') print('};') print('') print('const pin_obj_t pin_{:s}_obj = PIN({:s}, {:d}, {:s}, {:s}, {:d});'.format( self.cpu_pin_name(), self.port_letter(), self.pin, self.alt_fn_name(null_if_0=True), self.adc_num_str(), self.adc_channel)) print('') def print_header(self, hdr_file): n = self.cpu_pin_name() hdr_file.write('extern const pin_obj_t pin_{:s}_obj;\n'.format(n)) hdr_file.write('#define pin_{:s} (&pin_{:s}_obj)\n'.format(n, n)) if self.alt_fn_count > 0: hdr_file.write('extern const pin_af_obj_t pin_{:s}_af[];\n'.format(n)) def qstr_list(self): result = [] for alt_fn in self.alt_fn: if alt_fn.is_supported(): result += alt_fn.qstr_list() return result class NamedPin(object): def __init__(self, name, pin): if name.startswith('-'): self._is_hidden = True self._name = name[1:] else: self._is_hidden = False self._name = name self._pin = pin def is_hidden(self): return self._is_hidden def pin(self): return self._pin def name(self): return self._name class Pins(object): def __init__(self): self.cpu_pins = [] # list of NamedPin objects self.board_pins = [] # list of NamedPin objects def find_pin(self, port_num, pin_num): for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.port == port_num and pin.pin == pin_num: return pin def parse_af_file(self, filename, pinname_col, af_col): with open(filename, 'r') as csvfile: rows = csv.reader(csvfile) for row in rows: try: (port_num, pin_num) = parse_port_pin(row[pinname_col]) except: continue pin = Pin(port_num, pin_num) for af_idx in range(af_col, len(row)): if af_idx < af_col + 16: pin.parse_af(af_idx - af_col, row[af_idx]) elif af_idx == af_col + 16: pin.parse_adc(row[af_idx]) self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin)) def parse_board_file(self, filename): with open(filename, 'r') as csvfile: rows = csv.reader(csvfile) for row in rows: try: (port_num, pin_num) = parse_port_pin(row[1]) except: continue pin = self.find_pin(port_num, pin_num) if pin: pin.set_is_board_pin() if row[0]: # Only add board pins that have a name self.board_pins.append(NamedPin(row[0], pin)) def print_named(self, label, named_pins): print('STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label)) for named_pin in named_pins: pin = named_pin.pin() if pin.is_board_pin() and not named_pin.is_hidden(): print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}_obj) }},'.format(named_pin.name(), pin.cpu_pin_name())) print('};') print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label)) def print(self): for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): pin.print() self.print_named('cpu', self.cpu_pins) print('') self.print_named('board', self.board_pins) def print_adc(self, adc_num): print('') print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num)) for channel in range(17): if channel == 16: print('#if defined(STM32L4)') adc_found = False for named_pin in self.cpu_pins: pin = named_pin.pin() if (pin.is_board_pin() and (pin.adc_num & (1 << (adc_num - 1))) and (pin.adc_channel == channel)): print(' &pin_{:s}_obj, // {:d}'.format(pin.cpu_pin_name(), channel)) adc_found = True break if not adc_found: print(' NULL, // {:d}'.format(channel)) if channel == 16: print('#endif') print('};') def print_header(self, hdr_filename, obj_decls): with open(hdr_filename, 'wt') as hdr_file: if obj_decls: for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): pin.print_header(hdr_file) hdr_file.write('extern const pin_obj_t * const pin_adc1[];\n') hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n') hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n') # provide #define's mapping board to cpu name for named_pin in self.board_pins: hdr_file.write("#define pyb_pin_{:s} pin_{:s}\n".format(named_pin.name(), named_pin.pin().cpu_pin_name())) def print_qstr(self, qstr_filename): with open(qstr_filename, 'wt') as qstr_file: qstr_set = set([]) for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): qstr_set |= set(pin.qstr_list()) qstr_set |= set([named_pin.name()]) for named_pin in self.board_pins: if not named_pin.is_hidden(): qstr_set |= set([named_pin.name()]) for qstr in sorted(qstr_set): cond_var = None if qstr.startswith('AF'): af_words = qstr.split('_') cond_var = conditional_var(af_words[1]) print_conditional_if(cond_var, file=qstr_file) print('Q({})'.format(qstr), file=qstr_file) print_conditional_endif(cond_var, file=qstr_file) def print_af_hdr(self, af_const_filename): with open(af_const_filename, 'wt') as af_const_file: af_hdr_set = set([]) mux_name_width = 0 for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): for af in pin.alt_fn: if af.is_supported(): mux_name = af.mux_name() af_hdr_set |= set([mux_name]) if len(mux_name) > mux_name_width: mux_name_width = len(mux_name) for mux_name in sorted(af_hdr_set): af_words = mux_name.split('_') # ex mux_name: AF9_I2C2 cond_var = conditional_var(af_words[1]) print_conditional_if(cond_var, file=af_const_file) key = 'MP_ROM_QSTR(MP_QSTR_{}),'.format(mux_name) val = 'MP_ROM_INT(GPIO_{})'.format(mux_name) print(' { %-*s %s },' % (mux_name_width + 26, key, val), file=af_const_file) print_conditional_endif(cond_var, file=af_const_file) def print_af_defs(self, af_defs_filename, cmp_strings): with open(af_defs_filename, 'wt') as af_defs_file: STATIC_AF_TOKENS = {} for named_pin in self.board_pins: for af in named_pin.pin().alt_fn: func = "%s%d" % (af.func, af.fn_num) if af.fn_num else af.func pin_type = (af.pin_type or "NULL").split('(')[0] tok = "#define STATIC_AF_%s_%s(pin_obj) ( \\" % (func, pin_type) if tok not in STATIC_AF_TOKENS: STATIC_AF_TOKENS[tok] = [] if cmp_strings: pin_name = named_pin.pin().cpu_pin_name() cmp_str = ' ((strcmp( #pin_obj , "(&pin_%s_obj)") ' \ ' & strcmp( #pin_obj , "((&pin_%s_obj))")) == 0) ? (%d) : \\' % ( pin_name, pin_name, af.idx ) else: cmp_str = ' ((pin_obj) == (pin_%s)) ? (%d) : \\' % ( named_pin.pin().cpu_pin_name(), af.idx ) STATIC_AF_TOKENS[tok].append(cmp_str) for tok, pins in STATIC_AF_TOKENS.items(): print(tok, file=af_defs_file) print("\n".join(sorted(pins)), file=af_defs_file) print(" (0xffffffffffffffffULL))\n", file=af_defs_file) def print_af_py(self, af_py_filename): with open(af_py_filename, 'wt') as af_py_file: print('PINS_AF = (', file=af_py_file) for named_pin in self.board_pins: if named_pin.is_hidden(): continue print(" ('%s', " % named_pin.name(), end='', file=af_py_file) for af in named_pin.pin().alt_fn: if af.is_supported(): print("(%d, '%s'), " % (af.idx, af.af_str), end='', file=af_py_file) print('),', file=af_py_file) print(')', file=af_py_file) def main(): parser = argparse.ArgumentParser( prog="make-pins.py", usage="%(prog)s [options] [command]", description="Generate board specific pin file" ) parser.add_argument( "-a", "--af", dest="af_filename", help="Specifies the alternate function file for the chip", default="stm32f4xx_af.csv" ) parser.add_argument( "--af-const", dest="af_const_filename", help="Specifies header file for alternate function constants.", default="build/pins_af_const.h" ) parser.add_argument( "--af-py", dest="af_py_filename", help="Specifies the filename for the python alternate function mappings.", default="build/pins_af.py" ) parser.add_argument( "--af-defs", dest="af_defs_filename", help="Specifies the filename for the alternate function defines.", default="build/pins_af_defs.h" ) parser.add_argument( "--af-defs-cmp-strings", dest="af_defs_cmp_strings", help="Whether to compare pin name strings for the alternate function defines instead of object values", action="store_true", ) parser.add_argument( "-b", "--board", dest="board_filename", help="Specifies the board file", ) parser.add_argument( "-p", "--prefix", dest="prefix_filename", help="Specifies beginning portion of generated pins file", default="stm32f4xx_prefix.c" ) parser.add_argument( "-q", "--qstr", dest="qstr_filename", help="Specifies name of generated qstr header file", default="build/pins_qstr.h" ) parser.add_argument( "-r", "--hdr", dest="hdr_filename", help="Specifies name of generated pin header file", default="build/pins.h" ) parser.add_argument( "--hdr-obj-decls", dest="hdr_obj_decls", help="Whether to include declarations for pin objects in pin header file", action="store_true" ) args = parser.parse_args(sys.argv[1:]) pins = Pins() print('// This file was automatically generated by make-pins.py') print('//') if args.af_filename: print('// --af {:s}'.format(args.af_filename)) pins.parse_af_file(args.af_filename, 1, 2) if args.board_filename: print('// --board {:s}'.format(args.board_filename)) pins.parse_board_file(args.board_filename) if args.prefix_filename: print('// --prefix {:s}'.format(args.prefix_filename)) print('') with open(args.prefix_filename, 'r') as prefix_file: print(prefix_file.read()) pins.print() pins.print_adc(1) pins.print_adc(2) pins.print_adc(3) pins.print_header(args.hdr_filename, args.hdr_obj_decls) pins.print_qstr(args.qstr_filename) pins.print_af_hdr(args.af_const_filename) pins.print_af_py(args.af_py_filename) pins.print_af_defs(args.af_defs_filename, args.af_defs_cmp_strings) if __name__ == "__main__": main() micropython-1.12/ports/stm32/boards/manifest.py000066400000000000000000000002501357706137100215700ustar00rootroot00000000000000freeze('$(MPY_DIR)/drivers/dht', 'dht.py') freeze('$(MPY_DIR)/drivers/display', ('lcd160cr.py', 'lcd160cr_test.py')) freeze('$(MPY_DIR)/drivers/onewire', 'onewire.py') micropython-1.12/ports/stm32/boards/openocd_stm32f4.cfg000066400000000000000000000017071357706137100230120ustar00rootroot00000000000000# This script configures OpenOCD for use with an ST-Link V2 programmer/debugger # and an STM32F4 target microcontroller. # # To flash your firmware: # # $ openocd -f openocd_stm32f4.cfg \ # -c "stm_flash build-BOARD/firmware0.bin 0x08000000 build-BOARD/firmware1.bin 0x08020000" # # For a gdb server on port 3333: # # $ openocd -f openocd_stm32f4.cfg source [find interface/stlink-v2.cfg] transport select hla_swd source [find target/stm32f4x.cfg] reset_config srst_only init proc stm_flash { BIN0 ADDR0 {BIN1 ""} {ADDR1 ""} } { reset halt sleep 100 wait_halt 2 flash write_image erase $BIN0 $ADDR0 sleep 100 verify_image $BIN0 $ADDR0 sleep 100 if {$BIN1 ne ""} { flash write_image erase $BIN1 $ADDR1 sleep 100 verify_image $BIN1 $ADDR1 sleep 100 } reset run shutdown } proc stm_erase {} { reset halt sleep 100 stm32f4x mass_erase 0 sleep 100 shutdown } micropython-1.12/ports/stm32/boards/openocd_stm32f7.cfg000066400000000000000000000017111357706137100230100ustar00rootroot00000000000000# This script configures OpenOCD for use with an ST-Link V2 programmer/debugger # and an STM32F7 target microcontroller. # # To flash your firmware: # # $ openocd -f openocd_stm32f7.cfg \ # -c "stm_flash build-BOARD/firmware0.bin 0x08000000 build-BOARD/firmware1.bin 0x08020000" # # For a gdb server on port 3333: # # $ openocd -f openocd_stm32f7.cfg source [find interface/stlink-v2-1.cfg] transport select hla_swd source [find target/stm32f7x.cfg] reset_config srst_only init proc stm_flash { BIN0 ADDR0 {BIN1 ""} {ADDR1 ""} } { reset halt sleep 100 wait_halt 2 flash write_image erase $BIN0 $ADDR0 sleep 100 verify_image $BIN0 $ADDR0 sleep 100 if {$BIN1 ne ""} { flash write_image erase $BIN1 $ADDR1 sleep 100 verify_image $BIN1 $ADDR1 sleep 100 } reset run shutdown } proc stm_erase {} { reset halt sleep 100 stm32f7x mass_erase 0 sleep 100 shutdown } micropython-1.12/ports/stm32/boards/openocd_stm32l4.cfg000066400000000000000000000017111357706137100230130ustar00rootroot00000000000000# This script configures OpenOCD for use with an ST-Link V2 programmer/debugger # and an STM32L4 target microcontroller. # # To flash your firmware: # # $ openocd -f openocd_stm32l4.cfg \ # -c "stm_flash build-BOARD/firmware0.bin 0x08000000 build-BOARD/firmware1.bin 0x08004000" # # For a gdb server on port 3333: # # $ openocd -f openocd_stm32l4.cfg source [find interface/stlink-v2-1.cfg] transport select hla_swd source [find target/stm32l4x.cfg] reset_config srst_only init proc stm_flash { BIN0 ADDR0 {BIN1 ""} {ADDR1 ""} } { reset halt sleep 100 wait_halt 2 flash write_image erase $BIN0 $ADDR0 sleep 100 verify_image $BIN0 $ADDR0 sleep 100 if {$BIN1 ne ""} { flash write_image erase $BIN1 $ADDR1 sleep 100 verify_image $BIN1 $ADDR1 sleep 100 } reset run shutdown } proc stm_erase {} { reset halt sleep 100 stm32l4x mass_erase 0 sleep 100 shutdown } micropython-1.12/ports/stm32/boards/pllvalues.py000066400000000000000000000155051357706137100220020ustar00rootroot00000000000000""" This is an auxiliary script that is used to compute valid PLL values to set the CPU frequency to a given value. The algorithm here appears as C code for the machine.freq() function. """ from __future__ import print_function import re def close_int(x): return abs(x - round(x)) < 0.01 # original version that requires N/M to be an integer (for simplicity) def compute_pll(hse, sys): for P in (2, 4, 6, 8): # allowed values of P Q = sys * P / 48 NbyM = sys * P / hse # N/M and Q must be integers if not (close_int(NbyM) and close_int(Q)): continue # VCO_OUT must be between 192MHz and 432MHz if not (192 <= hse * NbyM <= 432): continue # compute M M = int(192 // NbyM) while hse > 2 * M or NbyM * M < 192: M += 1 # VCO_IN must be between 1MHz and 2MHz (2MHz recommended) if not (M <= hse): continue # compute N N = NbyM * M # N and Q are restricted if not (192 <= N <= 432 and 2 <= Q <= 15): continue # found valid values assert NbyM == N // M return (M, N, P, Q) # no valid values found return None # improved version that doesn't require N/M to be an integer def compute_pll2(hse, sys, relax_pll48): # Loop over the allowed values of P, looking for a valid PLL configuration # that gives the desired "sys" frequency. We use floats for P to force # floating point arithmetic on Python 2. fallback = None for P in (2.0, 4.0, 6.0, 8.0): NbyM = sys * P / hse # VCO_OUT must be between 192MHz and 432MHz if not (192 <= hse * NbyM <= 432): continue # scan M M = int(192 // NbyM) # starting value while 2 * M < hse: M += 1 # VCO_IN must be between 1MHz and 2MHz (2MHz recommended) for M in range(M, hse + 1): if NbyM * M < 191.99 or not close_int(NbyM * M): continue # compute N N = NbyM * M # N must be an integer if not close_int(N): continue # N is restricted if not (192 <= N <= 432): continue Q = (sys * P / 48) # Q must be an integer in a set range if not (2 <= Q <= 15): continue if not close_int(Q): if int(M) == int(hse) and fallback is None: # the values don't give 48MHz on PLL48 but are otherwise OK fallback = M, N, P, int(Q) continue # found valid values return (M, N, P, Q) if relax_pll48: # might have found values which don't give 48MHz on PLL48 return fallback else: # no valid values found which give 48MHz on PLL48 return None def compute_derived(hse, pll): M, N, P, Q = pll vco_in = hse / M vco_out = hse * N / M pllck = hse / M * N / P pll48ck = hse / M * N / Q return (vco_in, vco_out, pllck, pll48ck) def verify_pll(hse, pll): M, N, P, Q = pll vco_in, vco_out, pllck, pll48ck = compute_derived(hse, pll) # verify ints assert close_int(M) assert close_int(N) assert close_int(P) assert close_int(Q) # verify range assert 2 <= M <= 63 assert 192 <= N <= 432 assert P in (2, 4, 6, 8) assert 2 <= Q <= 15 assert 1 <= vco_in <= 2 assert 192 <= vco_out <= 432 def compute_pll_table(source_clk, relax_pll48): valid_plls = [] for sysclk in range(2, 217, 2): pll = compute_pll2(source_clk, sysclk, relax_pll48) if pll is not None: verify_pll(source_clk, pll) valid_plls.append((sysclk, pll)) return valid_plls def generate_c_table(hse, valid_plls): valid_plls.sort() print("// (M, P/2-1, SYS) values for %u MHz source" % hse) print("static const uint16_t pll_freq_table[%u] = {" % len(valid_plls)) for sys, (M, N, P, Q) in valid_plls: print(" (%u << 10) | (%u << 8) | %u," % (M, P // 2 - 1, sys)) print("};") def print_table(hse, valid_plls): print("HSE =", hse, "MHz") print("sys : M N P Q : VCO_IN VCO_OUT PLLCK PLL48CK") out_format = "%3u : %2u %.1f %.2f %.2f : %5.2f %6.2f %6.2f %6.2f" for sys, pll in valid_plls: print(out_format % ((sys,) + pll + compute_derived(hse, pll))) print("found %u valid configurations" % len(valid_plls)) def search_header_for_hsx_values(filename, vals): regex_inc = re.compile(r'#include "(boards/[A-Za-z0-9_./]+)"') regex_def = re.compile(r'#define +(HSE_VALUE|HSI_VALUE) +\((\(uint32_t\))?([0-9]+)\)') with open(filename) as f: for line in f: line = line.strip() m = regex_inc.match(line) if m: # Search included file search_header_for_hsx_values(m.group(1), vals) continue m = regex_def.match(line) if m: # Found HSE_VALUE or HSI_VALUE val = int(m.group(3)) // 1000000 if m.group(1) == 'HSE_VALUE': vals[0] = val else: vals[1] = val return vals def main(): global out_format # parse input args import sys argv = sys.argv[1:] c_table = False relax_pll48 = False hse = None hsi = None while True: if argv[0] == '-c': c_table = True argv.pop(0) elif argv[0] == '--relax-pll48': relax_pll48 = True argv.pop(0) else: break if len(argv) != 1: print("usage: pllvalues.py [-c] ") sys.exit(1) if argv[0].startswith("file:"): # extract HSE_VALUE, and optionally HSI_VALUE, from header file hse, hsi = search_header_for_hsx_values(argv[0][5:], [None, None]) if hse is None: raise ValueError("%s does not contain a definition of HSE_VALUE" % argv[0]) if hsi is not None and hsi > 16: # Currently, a HSI value greater than 16MHz is not supported hsi = None else: # HSE given directly as an integer hse = int(argv[0]) hse_valid_plls = compute_pll_table(hse, relax_pll48) if hsi is not None: hsi_valid_plls = compute_pll_table(hsi, relax_pll48) if c_table: print('#if MICROPY_HW_CLK_USE_HSI') if hsi is not None: hsi_valid_plls.append((hsi, (0, 0, 2, 0))) generate_c_table(hsi, hsi_valid_plls) print('#else') if hsi is not None: hse_valid_plls.append((hsi, (0, 0, 2, 0))) hse_valid_plls.append((hse, (1, 0, 2, 0))) generate_c_table(hse, hse_valid_plls) print('#endif') else: print_table(hse, hse_valid_plls) if __name__ == "__main__": main() micropython-1.12/ports/stm32/boards/stm32f091_af.csv000066400000000000000000000120671357706137100221540ustar00rootroot00000000000000Port,Pin,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,,,,,,,,, ,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,,,,,,,,,ADC PortA,PA0,,USART2_CTS,TIM2_CH1_ETR,TSC_G1_IO1,USART4_TX,,,COMP1_OUT,,,,,,,,,ADC1_IN0 PortA,PA1,EVENTOUT,USART2_RTS,TIM2_CH2,TSC_G1_IO2,USART4_RX,TIM15_CH1N,,,,,,,,,,,ADC1_IN1 PortA,PA2,TIM15_CH1,USART2_TX,TIM2_CH3,TSC_G1_IO3,,,,COMP2_OUT,,,,,,,,,ADC1_IN2 PortA,PA3,TIM15_CH2,USART2_RX,TIM2_CH4,TSC_G1_IO4,,,,,,,,,,,,,ADC1_IN3 PortA,PA4,SPI1_NSS/I2S1_WS,USART2_CK,,TSC_G2_IO1,TIM14_CH1,USART6_TX,,,,,,,,,,,ADC1_IN4 PortA,PA5,SPI1_SCK/I2S1_CK,CEC,TIM2_CH1_ETR,TSC_G2_IO2,,USART6_RX,,,,,,,,,,,ADC1_IN5 PortA,PA6,SPI1_MISO/I2S1_MCK,TIM3_CH1,TIM1_BKIN,TSC_G2_IO3,USART3_CTS,TIM16_CH1,EVENTOUT,COMP1_OUT,,,,,,,,,ADC1_IN6 PortA,PA7,SPI1_MOSI/I2S1_SD,TIM3_CH2,TIM1_CH1N,TSC_G2_IO4,TIM14_CH1,TIM17_CH1,EVENTOUT,COMP2_OUT,,,,,,,,,ADC1_IN7 PortA,PA8,MCO,USART1_CK,TIM1_CH1,EVENTOUT,CRS_SYNC,,,,,,,,,,,, PortA,PA9,TIM15_BKIN,USART1_TX,TIM1_CH2,TSC_G4_IO1,I2C1_SCL,MCO,,,,,,,,,,, PortA,PA10,TIM17_BKIN,USART1_RX,TIM1_CH3,TSC_G4_IO2,I2C1_SDA,,,,,,,,,,,, PortA,PA11,EVENTOUT,USART1_CTS,TIM1_CH4,TSC_G4_IO3,CAN1_RX,I2C2_SCL,,COMP1_OUT,,,,,,,,, PortA,PA12,EVENTOUT,USART1_RTS,TIM1_ETR,TSC_G4_IO4,CAN1_TX,I2C2_SDA,,COMP2_OUT,,,,,,,,, PortA,PA13,SWDIO,IR_OUT,,,,,,,,,,,,,,, PortA,PA14,SWCLK,USART2_TX,,,,,,,,,,,,,,, PortA,PA15,SPI1_NSS/I2S1_WS,USART2_RX,TIM2_CH1_ETR,EVENTOUT,USART4_RTS,,,,,,,,,,,, PortB,PB0,EVENTOUT,TIM3_CH3,TIM1_CH2N,TSC_G3_IO2,USART3_CK,,,,,,,,,,,,ADC1_IN8 PortB,PB1,TIM14_CH1,TIM3_CH4,TIM1_CH3N,TSC_G3_IO3,USART3_RTS,,,,,,,,,,,,ADC1_IN9 PortB,PB2,,,,TSC_G3_IO4,,,,,,,,,,,,, PortB,PB3,SPI1_SCK/I2S1_CK,EVENTOUT,TIM2_CH2,TSC_G5_IO1,USART5_TX,,,,,,,,,, PortB,PB4,SPI1_MISO/I2S1_MCK,TIM3_CH1,EVENTOUT,TSC_G5_IO2,USART5_RX,TIM17_BKIN,,,,,,,,, PortB,PB5,SPI1_MOSI/I2S1_SD,TIM3_CH2,TIM16_BKIN,I2C1_SMBA,USART5_CK/USART5_RTS,,,,,,,,,, PortB,PB6,USART1_TX,I2C1_SCL,TIM16_CH1N,TSC_G5_IO3,,,,,,,,,,, PortB,PB7,USART1_RX,I2C1_SDA,TIM17_CH1N,TSC_G5_IO4,USART4_CTS,,,,,,,,,, PortB,PB8,CEC,I2C1_SCL,TIM16_CH1,TSC_SYNC,CAN1_RX,,,,,,,,,, PortB,PB9,IR_OUT,I2C1_SDA,TIM17_CH1,EVENTOUT,CAN1_TX,SPI2_NSS/I2S2_WS,,,,,,,,, PortB,PB10,CEC,I2C2_SCL,TIM2_CH3,TSC_SYNC,USART3_TX,SPI2_SCK/I2S2_CK,,,,,,,,, PortB,PB11,EVENTOUT,I2C2_SDA,TIM2_CH4,TSC_G6_IO1,USART3_RX,,,,,,,,,, PortB,PB12,SPI2_NSS/I2S2_WS,EVENTOUT,TIM1_BKIN,TSC_G6_IO2,USART3_CK,TIM15_BKIN,,,,,,,,, PortB,PB13,SPI2_SCK/I2S2_CK,,TIM1_CH1N,TSC_G6_IO3,USART3_CTS,I2C2_SCL,,,,,,,,, PortB,PB14,SPI2_MISO/I2S2_MCK,TIM15_CH1,TIM1_CH2N,TSC_G6_IO4,USART3_RTS,I2C2_SDA,,,,,,,,, PortB,PB15,SPI2_MOSI/I2S2_SD,TIM15_CH2,TIM1_CH3N,TIM15_CH1N,,,,,,,,,,, PortC,PC0,EVENTOUT,USART7_TX,USART6_TX,,,,,,,,,,,,,,ADC1_IN10 PortC,PC1,EVENTOUT,USART7_RX,USART6_RX,,,,,,,,,,,,,,ADC1_IN11 PortC,PC2,EVENTOUT,SPI2_MISO/I2S2_MCK,USART8_TX,,,,,,,,,,,,,,ADC1_IN12 PortC,PC3,EVENTOUT,SPI2_MOSI/I2S2_SD,USART8_RX,,,,,,,,,,,,,,ADC1_IN13 PortC,PC4,EVENTOUT,USART3_TX,,,,,,,,,,,,,,,ADC1_IN14 PortC,PC5,TSC_G3_IO1,USART3_RX,,,,,,,,,,,,,,,ADC1_IN15 PortC,PC6,TIM3_CH1,USART7_TX,,,,,,,,,,,,,,, PortC,PC7,TIM3_CH2,USART7_RX,,,,,,,,,,,,,,, PortC,PC8,TIM3_CH3,USART8_TX,,,,,,,,,,,,,,, PortC,PC9,TIM3_CH4,USART8_RX,,,,,,,,,,,,,,, PortC,PC10,USART4_TX,USART3_TX,,,,,,,,,,,,,,, PortC,PC11,USART4_RX,USART3_RX,,,,,,,,,,,,,,, PortC,PC12,USART4_CK,USART3_CK,USART5_TX,,,,,,,,,,,,,, PortC,PC13,,,,,,,,,,,,,,,,, PortC,PC14,,,,,,,,,,,,,,,,, PortC,PC15,,,,,,,,,,,,,,,,, PortD,PD0,CAN1_RX,SPI2_NSS/I2S2_WS,,,,,,,,,,,,,,, PortD,PD1,CAN1_TX,SPI2_SCK/I2S2_CK,,,,,,,,,,,,,,, PortD,PD2,TIM3_ETR,USART3_RTS,USART5_RX,,,,,,,,,,,,,, PortD,PD3,USART2_CTS,SPI2_MISO/I2S2_MCK,,,,,,,,,,,,,,, PortD,PD4,USART2_RTS,SPI2_MOSI/I2S2_SD,,,,,,,,,,,,,,, PortD,PD5,USART2_TX,,,,,,,,,,,,,,,, PortD,PD6,USART2_RX,,,,,,,,,,,,,,,, PortD,PD7,USART2_CK,,,,,,,,,,,,,,,, PortD,PD8,USART3_TX,,,,,,,,,,,,,,,, PortD,PD9,USART3_RX,,,,,,,,,,,,,,,, PortD,PD10,USART3_CK,,,,,,,,,,,,,,,, PortD,PD11,USART3_CTS,,,,,,,,,,,,,,,, PortD,PD12,USART3_RTS,TSC_G8_IO1,USART8_CK/USART8_RTS,,,,,,,,,,,,,, PortD,PD13,USART8_TX,TSC_G8_IO2,,,,,,,,,,,,,,, PortD,PD14,USART8_RX,TSC_G8_IO3,,,,,,,,,,,,,,, PortD,PD15,CRS_SYNC,TSC_G8_IO4,USART7_CK/USART7_RTS,,,,,,,,,,,,,, PortE,PE0,TIM16_CH1,EVENTOUT,,,,,,,,,,,,,,, PortE,PE1,TIM17_CH1,EVENTOUT,,,,,,,,,,,,,,, PortE,PE2,TIM3_ETR,TSC_G7_IO1,,,,,,,,,,,,,,, PortE,PE3,TIM3_CH1,TSC_G7_IO2,,,,,,,,,,,,,,, PortE,PE4,TIM3_CH2,TSC_G7_IO3,,,,,,,,,,,,,,, PortE,PE5,TIM3_CH3,TSC_G7_IO4,,,,,,,,,,,,,,, PortE,PE6,TIM3_CH4,,,,,,,,,,,,,,,, PortE,PE7,TIM1_ETR,USART5_CK/USART5_RTS,,,,,,,,,,,,,,, PortE,PE8,TIM1_CH1N,USART4_TX,,,,,,,,,,,,,,, PortE,PE9,TIM1_CH1,USART4_RX,,,,,,,,,,,,,,, PortE,PE10,TIM1_CH2N,USART5_TX,,,,,,,,,,,,,,, PortE,PE11,TIM1_CH2,USART5_RX,,,,,,,,,,,,,,, PortE,PE12,TIM1_CH3N,SPI1_NSS/I2S1_WS,,,,,,,,,,,,,,, PortE,PE13,TIM1_CH3,SPI1_SCK/I2S1_CK,,,,,,,,,,,,,,, PortE,PE14,TIM1_CH4,SPI1_MISO/I2S1_MCK,,,,,,,,,,,,,,, PortE,PE15,TIM1_BKIN,SPI1_MOSI/I2S1_SD,,,,,,,,,,,,,,, PortF,PF0,CRS_SYNC,I2C1_SDA,,,,,,,,,,,,,,, PortF,PF1,,I2C1_SCL,,,,,,,,,,,,,,, PortF,PF2,EVENTOUT,USART7_TX,USART7_CK/USART7_RTS,,,,,,,,,,,,,, PortF,PF3,EVENTOUT,USART7_RX,USART6_CK/USART6_RTS,,,,,,,,,,,,,, PortF,PF6,,,,,,,,,,,,,,,,, PortF,PF9,TIM15_CH1,USART6_TX,,,,,,,,,,,,,,, PortF,PF10,TIM15_CH2,USART6_RX,,,,,,,,,,,,,,, micropython-1.12/ports/stm32/boards/stm32f091xc.ld000066400000000000000000000015511357706137100216410ustar00rootroot00000000000000/* GNU linker script for STM32F091xC */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 256K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 6K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f0xx_hal_conf_base.h000066400000000000000000000060641357706137100241730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32F0XX_HAL_CONF_BASE_H #define MICROPY_INCLUDED_STM32F0XX_HAL_CONF_BASE_H // Include various HAL modules for convenience #include "stm32f0xx_hal_dma.h" #include "stm32f0xx_hal_adc.h" #include "stm32f0xx_hal_can.h" #include "stm32f0xx_hal_cortex.h" #include "stm32f0xx_hal_crc.h" #include "stm32f0xx_hal_dac.h" #include "stm32f0xx_hal_flash.h" #include "stm32f0xx_hal_gpio.h" #include "stm32f0xx_hal_i2c.h" #include "stm32f0xx_hal_i2s.h" #include "stm32f0xx_hal_iwdg.h" #include "stm32f0xx_hal_pcd.h" #include "stm32f0xx_hal_pwr.h" #include "stm32f0xx_hal_rcc.h" #include "stm32f0xx_hal_rtc.h" #include "stm32f0xx_hal_spi.h" #include "stm32f0xx_hal_tim.h" #include "stm32f0xx_hal_uart.h" #include "stm32f0xx_hal_usart.h" #include "stm32f0xx_hal_wwdg.h" // Enable various HAL modules #define HAL_MODULE_ENABLED #define HAL_ADC_MODULE_ENABLED #define HAL_CAN_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED #define HAL_CRC_MODULE_ENABLED #define HAL_DAC_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED #define HAL_I2S_MODULE_ENABLED #define HAL_IWDG_MODULE_ENABLED #define HAL_PCD_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_RTC_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED #define HAL_WWDG_MODULE_ENABLED // Oscillator values in Hz #define HSI_VALUE (8000000) #define HSI48_VALUE (48000000) #define LSI_VALUE (40000) // SysTick has the highest priority #define TICK_INT_PRIORITY (0x00) // Miscellaneous HAL settings #define PREFETCH_ENABLE 1 #define USE_RTOS 0 #define USE_SPI_CRC 1 // HAL parameter assertions are disabled #define assert_param(expr) ((void)0) #endif // MICROPY_INCLUDED_STM32F0XX_HAL_CONF_BASE_H micropython-1.12/ports/stm32/boards/stm32f401_af.csv000066400000000000000000000112371357706137100221450ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS_AF,TIM1/TIM2,TIM3/TIM4/TIM5,TIM9/TIM10/TIM11,I2C1/I2C2/I2C3,SPI1/SPI2/I2S2/SPI3/I2S3/SPI4,SPI2/I2S2/SPI3/I2S3,SPI3/I2S3/USART1/USART2,USART6,I2C2/I2C3,OTG1_FS,,SDIO,,,,ADC PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,,,,,USART2_CTS,,,,,,,,EVENTOUT,ADC1_IN0 PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,,,,,,,,EVENTOUT,ADC1_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,,,,,EVENTOUT,ADC1_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,,,,,,EVENTOUT,ADC1_IN3 PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,,,,EVENTOUT,ADC1_IN4 PortA,PA5,,TIM2_CH1/TIM2_ETR,,,,SPI1_SCK,,,,,,,,,,EVENTOUT,ADC1_IN5 PortA,PA6,,TIM1_BKIN,TIM3_CH1,,,SPI1_MISO,,,,,,,,,,EVENTOUT,ADC1_IN6 PortA,PA7,,TIM1_CH1N,TIM3_CH2,,,SPI1_MOSI,,,,,,,,,,EVENTOUT,ADC1_IN7 PortA,PA8,MCO_1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT, PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,,,USART1_TX,,,OTG_FS_VBUS,,,,,EVENTOUT, PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,,,EVENTOUT, PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,USART6_TX,,OTG_FS_DM,,,,,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,USART6_RX,,OTG_FS_DP,,,,,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,,,,,,,,,,,,,EVENTOUT,ADC1_IN8 PortB,PB1,,TIM1_CH3N,TIM3_CH4,,,,,,,,,,,,,EVENTOUT,ADC1_IN9 PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK/I2S3_CK,,,I2C2_SDA,,,,,,EVENTOUT, PortB,PB4,JTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,I2C3_SDA,,,,,,EVENTOUT, PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,,,,,,,EVENTOUT, PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,,,,,,,EVENTOUT, PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,,,,EVENTOUT, PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,,,,SDIO_D4,,,EVENTOUT, PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,,,,SDIO_D5,,,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,,,,,,,,,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,,,,,,,,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,,,,,,,,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,,,SPI2_MISO,I2S2ext_SD,,,,,,,,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,,,SPI2_MOSI/I2S2_SD,,,,,,,,,,EVENTOUT, PortC,PC0,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN10 PortC,PC1,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN11 PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,,,,,,EVENTOUT,ADC1_IN12 PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,,,,,,EVENTOUT,ADC1_IN13 PortC,PC4,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN14 PortC,PC5,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN15 PortC,PC6,,,TIM3_CH1,,,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,,,EVENTOUT, PortC,PC7,,,TIM3_CH2,,,,I2S3_MCK,,USART6_RX,,,,SDIO_D7,,,EVENTOUT, PortC,PC8,,,TIM3_CH3,,,,,,USART6_CK,,,,SDIO_D0,,,EVENTOUT, PortC,PC9,MCO_2,,TIM3_CH4,,I2C3_SDA,I2S_CKIN,,,,,,,SDIO_D1,,,EVENTOUT, PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,,,,,,SDIO_D2,,,EVENTOUT, PortC,PC11,,,,,,I2S3ext_SD,SPI3_MISO,,,,,,SDIO_D3,,,EVENTOUT, PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,,,,,,SDIO_CK,,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD1,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD2,,,TIM3_ETR,,,,,,,,,,SDIO_CMD,,,EVENTOUT, PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,,,,EVENTOUT, PortD,PD4,,,,,,,,USART2_RTS,,,,,,,,EVENTOUT, PortD,PD5,,,,,,,,USART2_TX,,,,,,,,EVENTOUT, PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,,USART2_RX,,,,,,,,EVENTOUT, PortD,PD7,,,,,,,,USART2_CK,,,,,,,,EVENTOUT, PortD,PD8,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD9,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD10,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD11,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD12,,,TIM4_CH1,,,,,,,,,,,,,EVENTOUT, PortD,PD13,,,TIM4_CH2,,,,,,,,,,,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,,,,,,,,,,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,,,,,,,,,,,,EVENTOUT, PortE,PE0,,,TIM4_ETR,,,,,,,,,,,,,EVENTOUT, PortE,PE1,,TIM1_CH2N,,,,,,,,,,,,,,EVENTOUT, PortE,PE2,TRACECLK,,,,,SPI4_SCK,,,,,,,,,,EVENTOUT, PortE,PE3,TRACED0,,,,,,,,,,,,,,,EVENTOUT, PortE,PE4,TRACED1,,,,,SPI4_NSS,,,,,,,,,,EVENTOUT, PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,,,,,,,,,,EVENTOUT, PortE,PE6,TRACED3,,,TIM9_CH2,,SPI4_MOSI,,,,,,,,,,EVENTOUT, PortE,PE7,,TIM1_ETR,,,,,,,,,,,,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,,,,,,,,,,,,,EVENTOUT, PortE,PE9,,TIM1_CH1,,,,,,,,,,,,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,,,,,,,,,,,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,,,,,,EVENTOUT, PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,,,,,,EVENTOUT, PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,,,,,,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,,,,,,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,,,,,,,,,,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32f401xd.ld000066400000000000000000000020561357706137100216360ustar00rootroot00000000000000/* GNU linker script for STM32F401xD */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K /* entire flash */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1,2,3 are 16K, 4 is 64K */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 256K /* sectors 5,6 are 128K */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* tunable */ /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f401xe.ld000066400000000000000000000020601357706137100216320ustar00rootroot00000000000000/* GNU linker script for STM32F401xE */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1,2,3 are 16K, 4 is 64K */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 384K /* sectors 5,6,7 are 128K */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f405.ld000066400000000000000000000021541357706137100213050ustar00rootroot00000000000000/* GNU linker script for STM32F405 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1,2,3,4 are for filesystem */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 896K /* sectors 5,6,7,8,9,10,11 */ CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f405_af.csv000066400000000000000000000216141357706137100221510ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,,,ADC PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0 PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,,EVENTOUT,ADC123_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT,ADC123_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,,EVENTOUT,ADC123_IN3 PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT,ADC12_IN4 PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5 PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCK,,EVENTOUT,ADC12_IN6 PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT,ADC12_IN7 PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT, PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT, PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT, PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT,ADC12_IN8 PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT,ADC12_IN9 PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT, PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,,,,,,,EVENTOUT, PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,,DCMI_D10,,EVENTOUT, PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,CAN2_TX,,,,DCMI_D5,,EVENTOUT, PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FSMC_NL,DCMI_VSYNC,,EVENTOUT, PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDIO_D4,DCMI_D6,,EVENTOUT, PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDIO_D5,DCMI_D7,,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,,EVENTOUT, PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,I2S2ext_SD,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT, PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,,,,EVENTOUT,ADC123_IN10 PortC,PC1,,,,,,,,,,,,ETH_MDC,,,,EVENTOUT,ADC123_IN11 PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,,,,EVENTOUT,ADC123_IN12 PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,,,,EVENTOUT,ADC123_IN13 PortC,PC4,,,,,,,,,,,,ETH_MII_RXD0/ETH_RMII_RXD0,,,,EVENTOUT,ADC123_IN14 PortC,PC5,,,,,,,,,,,,ETH_MII_RXD1/ETH_RMII_RXD1,,,,EVENTOUT,ADC123_IN15 PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,DCMI_D0,,EVENTOUT, PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDIO_D7,DCMI_D1,,EVENTOUT, PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,USART6_CK,,,,SDIO_D0,DCMI_D2,,EVENTOUT, PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,,,,,,SDIO_D1,DCMI_D3,,EVENTOUT, PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,,,,SDIO_D2,DCMI_D8,,EVENTOUT, PortC,PC11,,,,,,I2S3ext_SD,SPI3_MISO,USART3_RX,UART4_RX,,,,SDIO_D3,DCMI_D4,,EVENTOUT, PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDIO_CK,DCMI_D9,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,,,,,,,CAN1_RX,,,FSMC_D2,,,EVENTOUT, PortD,PD1,,,,,,,,,,CAN1_TX,,,FSMC_D3,,,EVENTOUT, PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,SDIO_CMD,DCMI_D11,,EVENTOUT, PortD,PD3,,,,,,,,USART2_CTS,,,,,FSMC_CLK,,,EVENTOUT, PortD,PD4,,,,,,,,USART2_RTS,,,,,FSMC_NOE,,,EVENTOUT, PortD,PD5,,,,,,,,USART2_TX,,,,,FSMC_NWE,,,EVENTOUT, PortD,PD6,,,,,,,,USART2_RX,,,,,FSMC_NWAIT,,,EVENTOUT, PortD,PD7,,,,,,,,USART2_CK,,,,,FSMC_NE1/FSMC_NCE2,,,EVENTOUT, PortD,PD8,,,,,,,,USART3_TX,,,,,FSMC_D13,,,EVENTOUT, PortD,PD9,,,,,,,,USART3_RX,,,,,FSMC_D14,,,EVENTOUT, PortD,PD10,,,,,,,,USART3_CK,,,,,FSMC_D15,,,EVENTOUT, PortD,PD11,,,,,,,,USART3_CTS,,,,,FSMC_A16,,,EVENTOUT, PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS,,,,,FSMC_A17,,,EVENTOUT, PortD,PD13,,,TIM4_CH2,,,,,,,,,,FSMC_A18,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,,,,,,,,,FSMC_D0,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,,,,,,,,,FSMC_D1,,,EVENTOUT, PortE,PE0,,,TIM4_ETR,,,,,,,,,,FSMC_NBL0,DCMI_D2,,EVENTOUT, PortE,PE1,,,,,,,,,,,,,FSMC_NBL1,DCMI_D3,,EVENTOUT, PortE,PE2,TRACECLK,,,,,,,,,,,ETH_MII_TXD3,FSMC_A23,,,EVENTOUT, PortE,PE3,TRACED0,,,,,,,,,,,,FSMC_A19,,,EVENTOUT, PortE,PE4,TRACED1,,,,,,,,,,,,FSMC_A20,DCMI_D4,,EVENTOUT, PortE,PE5,TRACED2,,,TIM9_CH1,,,,,,,,,FSMC_A21,DCMI_D6,,EVENTOUT, PortE,PE6,TRACED3,,,TIM9_CH2,,,,,,,,,FSMC_A22,DCMI_D7,,EVENTOUT, PortE,PE7,,TIM1_ETR,,,,,,,,,,,FSMC_D4,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,,,,,,,,,,FSMC_D5,,,EVENTOUT, PortE,PE9,,TIM1_CH1,,,,,,,,,,,FSMC_D6,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,,,,,,,,,,FSMC_D7,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,,,,,,,,,,FSMC_D8,,,EVENTOUT, PortE,PE12,,TIM1_CH3N,,,,,,,,,,,FSMC_D9,,,EVENTOUT, PortE,PE13,,TIM1_CH3,,,,,,,,,,,FSMC_D10,,,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,,,,,,,,FSMC_D11,,,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FSMC_D12,,,EVENTOUT, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FSMC_A0,,,EVENTOUT, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FSMC_A1,,,EVENTOUT, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FSMC_A2,,,EVENTOUT, PortF,PF3,,,,,,,,,,,,,FSMC_A3,,,EVENTOUT,ADC3_IN9 PortF,PF4,,,,,,,,,,,,,FSMC_A4,,,EVENTOUT,ADC3_IN14 PortF,PF5,,,,,,,,,,,,,FSMC_A5,,,EVENTOUT,ADC3_IN15 PortF,PF6,,,,TIM10_CH1,,,,,,,,,FSMC_NIORD,,,EVENTOUT,ADC3_IN4 PortF,PF7,,,,TIM11_CH1,,,,,,,,,FSMC_NREG,,,EVENTOUT,ADC3_IN5 PortF,PF8,,,,,,,,,,TIM13_CH1,,,FSMC_NIOWR,,,EVENTOUT,ADC3_IN6 PortF,PF9,,,,,,,,,,TIM14_CH1,,,FSMC_CD,,,EVENTOUT,ADC3_IN7 PortF,PF10,,,,,,,,,,,,,FSMC_INTR,,,EVENTOUT,ADC3_IN8 PortF,PF11,,,,,,,,,,,,,,DCMI_D12,,EVENTOUT, PortF,PF12,,,,,,,,,,,,,FSMC_A6,,,EVENTOUT, PortF,PF13,,,,,,,,,,,,,FSMC_A7,,,EVENTOUT, PortF,PF14,,,,,,,,,,,,,FSMC_A8,,,EVENTOUT, PortF,PF15,,,,,,,,,,,,,FSMC_A9,,,EVENTOUT, PortG,PG0,,,,,,,,,,,,,FSMC_A10,,,EVENTOUT, PortG,PG1,,,,,,,,,,,,,FSMC_A11,,,EVENTOUT, PortG,PG2,,,,,,,,,,,,,FSMC_A12,,,EVENTOUT, PortG,PG3,,,,,,,,,,,,,FSMC_A13,,,EVENTOUT, PortG,PG4,,,,,,,,,,,,,FSMC_A14,,,EVENTOUT, PortG,PG5,,,,,,,,,,,,,FSMC_A15,,,EVENTOUT, PortG,PG6,,,,,,,,,,,,,FSMC_INT2,,,EVENTOUT, PortG,PG7,,,,,,,,,USART6_CK,,,,FSMC_INT3,,,EVENTOUT, PortG,PG8,,,,,,,,,USART6_RTS,,,ETH_PPS_OUT,,,,EVENTOUT, PortG,PG9,,,,,,,,,USART6_RX,,,,FSMC_NE2/FSMC_NCE3,,,EVENTOUT, PortG,PG10,,,,,,,,,,,,,FSMC_NCE4_1/FSMC_NE3,,,EVENTOUT, PortG,PG11,,,,,,,,,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,FSMC_NCE4_2,,,EVENTOUT, PortG,PG12,,,,,,,,,USART6_RTS,,,,FSMC_NE4,,,EVENTOUT, PortG,PG13,,,,,,,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FSMC_A24,,,EVENTOUT, PortG,PG14,,,,,,,,,USART6_TX,,,ETH_MII_TXD1/ETH_RMII_TXD1,FSMC_A25,,,EVENTOUT, PortG,PG15,,,,,,,,,USART6_CTS,,,,,DCMI_D13,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH2,,,,,,,,,,,,ETH_MII_CRS,,,,EVENTOUT, PortH,PH3,,,,,,,,,,,,ETH_MII_COL,,,,EVENTOUT, PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT, PortH,PH5,,,,,I2C2_SDA,,,,,,,,,,,EVENTOUT, PortH,PH6,,,,,I2C2_SMBA,,,,,TIM12_CH1,,ETH_MII_RXD2,,,,EVENTOUT, PortH,PH7,,,,,I2C3_SCL,,,,,,,ETH_MII_RXD3,,,,EVENTOUT, PortH,PH8,,,,,I2C3_SDA,,,,,,,,,DCMI_HSYNC,,EVENTOUT, PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,,DCMI_D0,,EVENTOUT, PortH,PH10,,,TIM5_CH1,,,,,,,,,,,DCMI_D1,,EVENTOUT, PortH,PH11,,,TIM5_CH2,,,,,,,,,,,DCMI_D2,,EVENTOUT, PortH,PH12,,,TIM5_CH3,,,,,,,,,,,DCMI_D3,,EVENTOUT, PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,,,,EVENTOUT, PortH,PH14,,,,TIM8_CH2N,,,,,,,,,,DCMI_D4,,EVENTOUT, PortH,PH15,,,,TIM8_CH3N,,,,,,,,,,DCMI_D11,,EVENTOUT, PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,,DCMI_D13,,EVENTOUT, PortI,PI1,,,,,,SPI2_SCK/I2S2_CK,,,,,,,,DCMI_D8,,EVENTOUT, PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,I2S2ext_SD,,,,,,,DCMI_D9,,EVENTOUT, PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,,DCMI_D10,,EVENTOUT, PortI,PI4,,,,TIM8_BKIN,,,,,,,,,,DCMI_D5,,EVENTOUT, PortI,PI5,,,,TIM8_CH1,,,,,,,,,,DCMI_VSYNC,,EVENTOUT, PortI,PI6,,,,TIM8_CH2,,,,,,,,,,DCMI_D6,,EVENTOUT, PortI,PI7,,,,TIM8_CH3,,,,,,,,,,DCMI_D7,,EVENTOUT, PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI9,,,,,,,,,,CAN1_RX,,,,,,EVENTOUT, PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,,,,EVENTOUT, PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32f411.ld000066400000000000000000000020571357706137100213040ustar00rootroot00000000000000/* GNU linker script for STM32F411 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1,2,3 are 16K, 4 is 64K */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 384K /* sectors 5,6,7 are 128K */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f411_af.csv000066400000000000000000000123341357706137100221450ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS_AF,TIM1/TIM2,TIM3/TIM4/TIM5,TIM9/TIM10/TIM11,I2C1/I2C2/I2C3,SPI1/I2S1/SPI2/I2S2/SPI3/I2S3,SPI2/I2S2/SPI3/I2S3/SPI4/I2S4/SPI5/I2S5,SPI3/I2S3/USART1/USART2,USART6,I2C2/I2C3,,,SDIO,,,,ADC PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,,,,,USART2_CTS,,,,,,,,EVENTOUT,ADC1_IN0 PortA,PA1,,TIM2_CH2,TIM5_CH2,,,SPI4_MOSI/I2S4_SD,,USART2_RTS,,,,,,,,EVENTOUT,ADC1_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,I2S2_CKIN,,USART2_TX,,,,,,,,EVENTOUT,ADC1_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,I2S2_MCK,,USART2_RX,,,,,,,,EVENTOUT,ADC1_IN3 PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,,,,EVENTOUT,ADC1_IN4 PortA,PA5,,TIM2_CH1/TIM2_ETR,,,,SPI1_SCK/I2S1_CK,,,,,,,,,,EVENTOUT,ADC1_IN5 PortA,PA6,,TIM1_BKIN,TIM3_CH1,,,SPI1_MISO,I2S2_MCK,,,,,,SDIO_CMD,,,EVENTOUT,ADC1_IN6 PortA,PA7,,TIM1_CH1N,TIM3_CH2,,,SPI1_MOSI/I2S1_SD,,,,,,,,,,EVENTOUT,ADC1_IN7 PortA,PA8,MCO_1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,USB_FS_SOF,,SDIO_D1,,,EVENTOUT, PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,,,USART1_TX,,,USB_FS_VBUS,,SDIO_D2,,,EVENTOUT, PortA,PA10,,TIM1_CH3,,,,,SPI5_MOSI/I2S5_SD,USART1_RX,,,USB_FS_ID,,,,,EVENTOUT, PortA,PA11,,TIM1_CH4,,,,,SPI4_MISO,USART1_CTS,USART6_TX,,USB_FS_DM,,,,,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,,SPI5_MISO,USART1_RTS,USART6_RX,,USB_FS_DP,,,,,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART1_TX,,,,,,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,,,,SPI5_SCK/I2S5_CK,,,,,,,,,EVENTOUT,ADC1_IN8 PortB,PB1,,TIM1_CH3N,TIM3_CH4,,,,SPI5_NSS/I2S5_WS,,,,,,,,,EVENTOUT,ADC1_IN9 PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,USART1_RX,,I2C2_SDA,,,,,,EVENTOUT, PortB,PB4,JTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,I2C3_SDA,,,SDIO_D0,,,EVENTOUT, PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,,,,SDIO_D3,,,EVENTOUT, PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,,,,,,,EVENTOUT, PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,SDIO_D0,,,EVENTOUT, PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,SPI5_MOSI/I2S5_SD,,,I2C3_SDA,,,SDIO_D4,,,EVENTOUT, PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,I2C2_SDA,,,SDIO_D5,,,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,I2S3_MCK,,,,,,SDIO_D7,,,EVENTOUT, PortB,PB11,,TIM2_CH4,,,I2C2_SDA,I2S2_CKIN,,,,,,,,,,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,SPI4_NSS/I2S4_WS,SPI3_SCK/I2S3_CK,,,,,,,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,SPI4_SCK/I2S4_CK,,,,,,,,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,,,SPI2_MISO,I2S2ext_SD,,,,,,SDIO_D6,,,EVENTOUT, PortB,PB15,RTC_50Hz,TIM1_CH3N,,,,SPI2_MOSI/I2S2_SD,,,,,,,SDIO_CK,,,EVENTOUT, PortC,PC0,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN10 PortC,PC1,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN11 PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,,,,,,EVENTOUT,ADC1_IN12 PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,,,,,,EVENTOUT,ADC1_IN13 PortC,PC4,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN14 PortC,PC5,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN15 PortC,PC6,,,TIM3_CH1,,,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,,,EVENTOUT, PortC,PC7,,,TIM3_CH2,,,SPI2_SCK/I2S2_CK,I2S3_MCK,,USART6_RX,,,,SDIO_D7,,,EVENTOUT, PortC,PC8,,,TIM3_CH3,,,,,,USART6_CK,,,,SDIO_D0,,,EVENTOUT, PortC,PC9,MCO_2,,TIM3_CH4,,I2C3_SDA,I2S2_CKIN,,,,,,,SDIO_D1,,,EVENTOUT, PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,,,,,,SDIO_D2,,,EVENTOUT, PortC,PC11,,,,,,I2S3ext_SD,SPI3_MISO,,,,,,SDIO_D3,,,EVENTOUT, PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,,,,,,SDIO_CK,,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD1,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD2,,,TIM3_ETR,,,,,,,,,,SDIO_CMD,,,EVENTOUT, PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,,,,EVENTOUT, PortD,PD4,,,,,,,,USART2_RTS,,,,,,,,EVENTOUT, PortD,PD5,,,,,,,,USART2_TX,,,,,,,,EVENTOUT, PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,,USART2_RX,,,,,,,,EVENTOUT, PortD,PD7,,,,,,,,USART2_CK,,,,,,,,EVENTOUT, PortD,PD8,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD9,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD10,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD11,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD12,,,TIM4_CH1,,,,,,,,,,,,,EVENTOUT, PortD,PD13,,,TIM4_CH2,,,,,,,,,,,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,,,,,,,,,,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,,,,,,,,,,,,EVENTOUT, PortE,PE0,,,TIM4_ETR,,,,,,,,,,,,,EVENTOUT, PortE,PE1,,,,,,,,,,,,,,,,EVENTOUT, PortE,PE2,TRACECLK,,,,,SPI4_SCK/I2S4_CK,SPI5_SCK/I2S5_CK,,,,,,,,,EVENTOUT, PortE,PE3,TRACED0,,,,,,,,,,,,,,,EVENTOUT, PortE,PE4,TRACED1,,,,,SPI4_NSS/I2S4_WS,SPI5_NSS/I2S5_WS,,,,,,,,,EVENTOUT, PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SPI5_MISO,,,,,,,,,EVENTOUT, PortE,PE6,TRACED3,,,TIM9_CH2,,SPI4_MOSI/I2S4_SD,SPI5_MOSI/I2S5_SD,,,,,,,,,EVENTOUT, PortE,PE7,,TIM1_ETR,,,,,,,,,,,,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,,,,,,,,,,,,,EVENTOUT, PortE,PE9,,TIM1_CH1,,,,,,,,,,,,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,,,,,,,,,,,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,,,SPI4_NSS/I2S4_WS,SPI5_NSS/I2S5_WS,,,,,,,,,EVENTOUT, PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK/I2S4_CK,SPI5_SCK/I2S5_CK,,,,,,,,,EVENTOUT, PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,SPI5_MISO,,,,,,,,,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI/I2S4_SD,SPI5_MOSI/I2S5_SD,,,,,,,,,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,,,,,,,,,,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32f413_af.csv000066400000000000000000000231511357706137100221460ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS_AF,TIM1/TIM2/LPTIM1,TIM3/TIM4/TIM5,TIM8/9/10/11/DFSDM2,I2C1/2/3/I2CFMP1,SPI1/2/3/4/I2S1/2/3/4,SPI2/3/4/5/I2S2/3/4/5/DFSDM1/2,SPI3/I2S3/USART1/2/3/DFSDM2,USART3/4/5/6/7/8/CAN1/DFSDM1,I2C2/I2C3/I2CFMP1/CAN1/2/TIM12/13/14/QUADSPI,SAI1/DFSDM1/DFSDM2/QUADSPI/FSMC/OTG1_FS,UART4/5/9/10/CAN3,FSMC /SDIO,,RNG,SYS_AF,ADC PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,,,,,EVENTOUT,ADC1_IN0 PortA,PA1,,TIM2_CH2,TIM5_CH2,,,SPI4_MOSI/I2S4_SD,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC1_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,I2S2_CKIN,,USART2_TX,,,,,FSMC_D4,,,EVENTOUT,ADC1_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,I2S2_MCK,,USART2_RX,,,SAI1_SD_B,,FSMC_D5,,,EVENTOUT,ADC1_IN3 PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,DFSDM1_DATIN1,,,,FSMC_D6,,,EVENTOUT,ADC1_IN4 PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,DFSDM1_CKIN1,,,,FSMC_D7,,,EVENTOUT,ADC1_IN5 PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,I2S2_MCK,DFSDM2_CKIN1,,TIM13_CH1,QUADSPI_BK2_IO0,,SDIO_CMD,,,EVENTOUT,ADC1_IN6 PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,DFSDM2_DATIN1,,TIM14_CH1,QUADSPI_BK2_IO1,,,,,EVENTOUT,ADC1_IN7 PortA,PA8,MCO_1,TIM1_CH1,,,I2C3_SCL,,DFSDM1_CKOUT,USART1_CK,UART7_RX,,USB_FS_SOF,CAN3_RX,SDIO_D1,,,EVENTOUT, PortA,PA9,,TIM1_CH2,,DFSDM2_CKIN3,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,USB_FS_VBUS,,SDIO_D2,,,EVENTOUT, PortA,PA10,,TIM1_CH3,,DFSDM2_DATIN3,,SPI2_MOSI/I2S2_SD,SPI5_MOSI/I2S5_SD,USART1_RX,,,USB_FS_ID,,,,,EVENTOUT, PortA,PA11,,TIM1_CH4,,DFSDM2_CKIN5,,SPI2_NSS/I2S2_WS,SPI4_MISO,USART1_CTS,USART6_TX,CAN1_RX,USB_FS_DM,UART4_RX,,,,EVENTOUT, PortA,PA12,,TIM1_ETR,,DFSDM2_DATIN5,,SPI2_MISO,SPI5_MISO,USART1_RTS,USART6_RX,CAN1_TX,USB_FS_DP,UART4_TX,,,,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART1_TX,UART7_TX,,SAI1_MCLK_A,CAN3_TX,,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,SPI5_SCK/I2S5_CK,,,,,,,,,EVENTOUT,ADC1_IN8 PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,SPI5_NSS/I2S5_WS,,DFSDM1_DATIN0,QUADSPI_CLK,,,,,,EVENTOUT,ADC1_IN9 PortB,PB2,,LPTIM1_OUT,,,,,DFSDM1_CKIN0,,,QUADSPI_CLK,,,,,,EVENTOUT, PortB,PB3,JTDO,TIM2_CH2,,,I2CFMP1_SDA,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,USART1_RX,UART7_RX,I2C2_SDA,SAI1_SD_A,CAN3_RX,,,,EVENTOUT, PortB,PB4,JTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,UART7_TX,I2C3_SDA,SAI1_SCK_A,CAN3_TX,SDIO_D0,,,EVENTOUT, PortB,PB5,,LPTIM1_IN1,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,SAI1_FS_A,UART5_RX,SDIO_D3,,,EVENTOUT, PortB,PB6,,LPTIM1_ETR,TIM4_CH1,,I2C1_SCL,,DFSDM2_CKIN7,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,UART5_TX,SDIO_D0,,,EVENTOUT, PortB,PB7,,LPTIM1_IN2,TIM4_CH2,,I2C1_SDA,,DFSDM2_DATIN7,USART1_RX,,,,,FSMC_NL,,,EVENTOUT, PortB,PB8,,LPTIM1_OUT,TIM4_CH3,TIM10_CH1,I2C1_SCL,,SPI5_MOSI/I2S5_SD,DFSDM2_CKIN1,CAN1_RX,I2C3_SDA,,UART5_RX,SDIO_D4,,,EVENTOUT, PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,DFSDM2_DATIN1,,CAN1_TX,I2C2_SDA,,UART5_TX,SDIO_D5,,,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,I2S3_MCK,USART3_TX,,I2CFMP4_SCL,DFSDM2_CKOUT,,SDIO_D7,,,EVENTOUT, PortB,PB11,,TIM2_CH4,,,I2C2_SDA,I2S2_CKIN,,USART3_RX,,,,,,,,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,SPI4_NSS/I2S4_WS,SPI3_SCK/I2S3_CK,USART3__CK,CAN2_RX,DFSDM1_DATIN1,UART5_RX,FSMC_D13/FSMC_DA13,,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,I2CFMP1_SMBA,SPI2_SCK/I2S2_CK,SPI4_SCK/I2S4_CK,,USART3_CTS,CAN2_TX,DFSDM1_CKIN1,UART5_TX,,,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,I2CFMP1_SDA,SPI2_MISO,I2S2ext_SD,USART3_RTS,DFSDM1_DATIN2,TIM12_CH1,FSMC_D0,,SDIO_D6,,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,I2CFMP1_SCL,SPI2_MOSI/I2S2_SD,,,DFSDM1_CKIN2,TIM12_CH2,,,SDIO_CK,,,EVENTOUT, PortC,PC0,,LPTIM1_IN1,,DFSDM2_CKIN4,,,,SAI1_MCLK_B,,,,,,,,EVENTOUT,ADC1_IN10 PortC,PC1,,LPTIM1_OUT,,DFSDM2_DATIN4,,,,SAI1_SD_B,,,,,,,,EVENTOUT,ADC1_IN11 PortC,PC2,,LPTIM1_IN2,,DFSDM2_DATIN7,,SPI2_MISO,I2S2ext_SD,SAI1_SCK_B,DFSDM1_CKOUT,,,,FSMC_NWE,,,EVENTOUT,ADC1_IN12 PortC,PC3,,LPTIM1_ETR,,DFSDM2_CKIN7,,SPI2_MOSI/I2S2_SD,,SAI1_FS_B,,,,,FSMC_A0,,,EVENTOUT,ADC1_IN13 PortC,PC4,,,,DFSDM2_CKIN2,,I2S1_MCK,,,,,QUADSPI_BK2_IO2,,FSMC_NE4,,,EVENTOUT,ADC1_IN14 PortC,PC5,,,,DFSDM2_DATIN2,I2CFMP1_SMBA,,,USART3_RX,,,QUADSPI_BK2_IO3,,FSMC_NOE,,,EVENTOUT,ADC1_IN15 PortC,PC6,,,TIM3_CH1,TIM8_CH1,2CFMP1_SCL,I2S2_MCK,DFSDM1_CKIN3,DFSDM2_DATIN6,USART6_TX,,FSMC_D1,,SDIO_D6,,,EVENTOUT, PortC,PC7,,,TIM3_CH2,TIM8_CH2,I2CFMP1_SDA,SPI2_SCK/I2S2_CK,I2S3_MCK,DFSDM2_CKIN6,USART6_RX,,DFSDM1_DATIN3,,SDIO_D7,,,EVENTOUT, PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,DFSDM2_CKIN3,USART6_CK,QUADSPI_BK1_IO2,,,SDIO_D0,,,EVENTOUT, PortC,PC9,MCO_2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S2_CKIN,,DFSDM2_DATIN3,,QUADSPI_BK1_IO0,,,SDIO_D1,,,EVENTOUT, PortC,PC10,,,,DFSDM2_CKIN5,,,SPI3_SCK/I2S3_CK,USART3_TX,,QUADSPI_BK1_IO1,,,SDIO_D2,,,EVENTOUT, PortC,PC11,,,,DFSDM2_DATIN5,,I2S3ext_SD,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,FSMC_D2,,SDIO_D3,,,EVENTOUT, PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,FSMC_D3,,SDIO_CK,,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,DFSDM2_CKIN6,,,,,,CAN1_RX,,UART4_RX,FSMC_D2/FSMC_DA2,,,EVENTOUT, PortD,PD1,,,,DFSDM2_DATIN6,,,,,,CAN1_TX,,UART4_TX,FSMC_D3/FSMC_DA3,,,EVENTOUT, PortD,PD2,,,TIM3_ETR,DFSDM2_CKOUT,,,,,UART5_RX,,FSMC_NWE,,SDIO_CMD,,,EVENTOUT, PortD,PD3,TRACED1,,,,,SPI2_SCK/I2S2_CK,DFSDM1_DATIN0,USART2_CTS,,QUADSPI_CLK,,,FSMC_CLK,,,EVENTOUT, PortD,PD4,,,,,,,DFSDM1_CKIN0,USART2_RTS,,,,,FSMC_NOE,,,EVENTOUT, PortD,PD5,,,,DFSDM2_CKOUT,,,,USART2_TX,,,,,FSMC_NWE,,,EVENTOUT, PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,DFSDM1_DATIN1,USART2_RX,,,,,FSMC_NWAIT,,,EVENTOUT, PortD,PD7,,,,,,,DFSDM1_CKIN1,USART2_CK,,,,,FSMC_NE1,,,EVENTOUT, PortD,PD8,,,,,,,,USART3_TX,,,,,FSMC_D13/FSMC_DA13,,,EVENTOUT, PortD,PD9,,,,,,,,USART3_RX,,,,,FSMC_D14/FSMC_DA14,,,EVENTOUT, PortD,PD10,,,,,,,,USART3_CK,UART4_TX,,,,FSMC_D15/FSMC_DA15,,,EVENTOUT, PortD,PD11,,,,DFSDM2_DATIN2,I2CFMP1_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,,,FSMC_A16,,,EVENTOUT, PortD,PD12,,,TIM4_CH1,DFSDM2_CKIN2,I2CFMP1_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,,,FSMC_A17,,,EVENTOUT, PortD,PD13,,,TIM4_CH2,,I2CFMP1_SDA,,,,,QUADSPI_BK1_IO3,,,FSMC_A18,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,I2CFMP1_SCL,,,,,,DFSDM2_CKIN0,UART9_RX,FSMC_D0/FSMC_DA0,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,I2CFMP1_SDA,,,,,,DFSDM2_DATIN0,UART9_TX,FSMC_D1/FSMC_DA1,,,EVENTOUT, PortE,PE0,,,TIM4_ETR,DFSDM2_CKIN4,,,,,UART8_RX,,,,FSMC_NBL0,,,EVENTOUT, PortE,PE1,,,,DFSDM2_DATIN4,,,,,UART8_TX,,,,FSMC_NBL1,,,EVENTOUT, PortE,PE2,TRACECLK,,,,,SPI4_SCK/I2S4_CK,SPI5_SCK/I2S5_CK,SAI1_MCLK_A,,QUADSPI_BK1_IO2,,UART10_RX,FSMC_A23,,,EVENTOUT, PortE,PE3,TRACED0,,,,,,,SAI1_SD_B,,,,UART10_TX,FSMC_A19,,,EVENTOUT, PortE,PE4,TRACED1,,,,,SPI4_NSS/I2S4_WS,SPI5_NSS/I2S5_WS,SAI1_SD_A,DFSDM1_DATIN3,,,,FSMC_A20,,,EVENTOUT, PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SPI5_MISO,SAI1_SCK_A,DFSDM1_CKIN3,,,,FSMC_A21,,,EVENTOUT, PortE,PE6,TRACED3,,,TIM9_CH2,,SPI4_MOSI/I2S4_SD,SPI5_MOSI/I2S5_SD,SAI1_FS_A,,,,,FSMC_A22,,,EVENTOUT, PortE,PE7,,TIM1_ETR,,,,,DFSDM1_DATIN2,,UART7_RX,,QUADSPI_BK2_IO0,,FSMC_D4/FSMC_DA4,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,,,,DFSDM1_CKIN2,,UART7_TX,,QUADSPI_BK2_IO1,,FSMC_D5/FSMC_DA5,,,EVENTOUT, PortE,PE9,,TIM1_CH1,,,,,DFSDM1_CKOUT,,,,QUADSPI_BK2_IO2,,FSMC_D6/FSMC_DA6,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,DFSDM2_DATIN0,,,,,,,QUADSPI_BK2_IO3,,FSMC_D7/FSMC_DA7,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,DFSDM2_CKIN0,,SPI4_NSS/I2S4_WS,SPI5_NSS/I2S5_WS,,,,,,FSMC_D8/FSMC_DA8,,,EVENTOUT, PortE,PE12,,TIM1_CH3N,,DFSDM2_DATIN7,,SPI4_SCK/I2S4_CK,SPI5_SCK/I2S5_CK,,,,,,FSMC_D9/FSMC_DA9,,,EVENTOUT, PortE,PE13,,TIM1_CH3,,DFSDM2_CKIN7,,SPI4_MISO,SPI5_MISO,,,,,,FSMC_D10/FSMC_DA10,,,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI/I2S4_SD,SPI5_MOSI/I2S5_SD,,,,DFSDM2_DATIN1,,FSMC_D11/FSMC_DA11,,,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,,,,,,DFSDM2_CKIN1,,FSMC_D12/FSMC_DA12,,,EVENTOUT, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FSMC_A0,,,EVENTOUT, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FSMC_A1,,,EVENTOUT, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FSMC_A2,,,EVENTOUT, PortF,PF3,,,TIM5_CH1,,,,,,,,,,FSMC_A3,,,EVENTOUT, PortF,PF4,,,TIM5_CH2,,,,,,,,,,FSMC_A4,,,EVENTOUT, PortF,PF5,,,TIM5_CH3,,,,,,,,,,FSMC_A5,,,EVENTOUT, PortF,PF6,TRACED0,,,TIM10_CH1,,,,SAI1_SD_B,UART7_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT, PortF,PF7,TRACED1,,,TIM11_CH1,,,,SAI1_MCLK_B,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT, PortF,PF8,,,,,,,,SAI1_SCK_B,UART8_RX,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT, PortF,PF9,,,,,,,,SAI1_FS_B,UART8_TX,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT, PortF,PF10,,TIM1_ETR,TIM5_CH4,,,,,,,,,,,,,EVENTOUT, PortF,PF11,,,,TIM8_ETR,,,,,,,,,,,,EVENTOUT, PortF,PF12,,,,TIM8_BKIN,,,,,,,,,FSMC_A6,,,EVENTOUT, PortF,PF13,,,,,I2CFMP1_SMBA,,,,,,,,FSMC_A7,,,EVENTOUT, PortF,PF14,,,,,I2CFMP1_SCL,,,,,,,,FSMC_A8,,,EVENTOUT, PortF,PF15,,,,,I2CFMP1_SDA,,,,,,,,FSMC_A9,,,EVENTOUT, PortG,PG0,,,,,,,,,,CAN1_RX,,UART9_RX,FSMC_A10,,,EVENTOUT, PortG,PG1,,,,,,,,,,CAN1_TX,,UART9_TX,FSMC_A11,,,EVENTOUT, PortG,PG2,,,,,,,,,,,,,FSMC_A12,,,EVENTOUT, PortG,PG3,,,,,,,,,,,,,FSMC_A13,,,EVENTOUT, PortG,PG4,,,,,,,,,,,,,FSMC_A14,,,EVENTOUT, PortG,PG5,,,,,,,,,,,,,FSMC_A15,,,EVENTOUT, PortG,PG6,,,,,,,,,,,QUADSPI_BK1_NCS,,,,,EVENTOUT, PortG,PG7,,,,,,,,,USART6_CK,,,,,,,EVENTOUT, PortG,PG8,,,,,,,,,USART6_RTS,,,,,,,EVENTOUT, PortG,PG9,,,,,,,,,USART6_RX,QUADSPI_BK2_IO2,,,FSMC_NE2,,,EVENTOUT, PortG,PG10,,,,,,,,,,,,,FSMC_NE3,,,EVENTOUT, PortG,PG11,,,,,,,,,,CAN2_RX,,UART10_RX,,,,EVENTOUT, PortG,PG12,,,,,,,,,USART6_RTS,CAN2_TX,,UART10_TX,FSMC_NE4,,,EVENTOUT, PortG,PG13,TRACED2,,,,,,,,USART6_CTS,,,,FSMC_A24,,,EVENTOUT, PortG,PG14,TRACED3,,,,,,,,USART6_TX,QUADSPI_BK2_IO3,,,FSMC_A25,,,EVENTOUT, PortG,PG15,,,,,,,,,USART6_CTS,,,,,,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32f413xg.ld000066400000000000000000000026301357706137100216420ustar00rootroot00000000000000/* GNU linker script for STM32F413xg (1MB flash, 320kB RAM) */ /* Specify the memory areas */ /* FLASH_FS2 is placed before FLASH_TEXT to support 1MB and 1.5MB FLASH with common code in flashbdev.c */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 176K /* sectors 1,2,3 are 16K, 4 is 64K, 5 is 128K (64K used) for filesystem */ FLASH_FS2 (rx) : ORIGIN = 0x08040000, LENGTH = 128K /* sector 6 is 128K (64K used) for filesystem, Total filesystem 240K */ FLASH_TEXT (rx) : ORIGIN = 0x08060000, LENGTH = 640K /* sectors 7,8,9,10,11 are 128K*/ SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 64K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f413xh.ld000066400000000000000000000026471357706137100216530ustar00rootroot00000000000000/* GNU linker script for STM32F413xh (1.5MB flash, 320kB RAM) */ /* Specify the memory areas */ /* FLASH_FS2 is placed before FLASH_TEXT to support 1MB and 1.5MB FLASH with common code in flashbdev.c */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1536K /* entire flash */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 176K /* sectors 1,2,3 are 16K, 4 is 64K, 5 is 128K (64K used) for filesystem */ FLASH_FS2 (rx) : ORIGIN = 0x08040000, LENGTH = 128K /* sector 6 is 128K (64K used) for filesystem, Total filesystem 240K */ FLASH_TEXT (rx) : ORIGIN = 0x08060000, LENGTH = 1152K /* sectors 7,8,9,10,11,12,13,14,15 are 128K*/ SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 64K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f429.ld000066400000000000000000000022221357706137100213070ustar00rootroot00000000000000/* GNU linker script for STM32F429i-Discovery kit with external 8MByte SDRam */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* entire flash */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0, 16 KiB */ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1-4: 3*16K+64K */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 896K /* sectors 5-11 are 128K */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K SDRAM(xrw) : ORIGIN = 0xC0000000, LENGTH = 8192K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f429_af.csv000066400000000000000000000256561357706137100221710ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/2/3/4/5/6,SPI2/3/SAI1,SPI3/USART1/2/3,USART6/UART4/5/7/8,CAN1/2/TIM12/13/14/LCD,OTG2_HS/OTG1_FS,ETH,FMC/SDIO/OTG2_FS,DCMI,LCD,SYS, PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT, PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,,EVENTOUT,ADC123_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT,ADC123_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT,ADC123_IN3 PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT,ADC12_IN4 PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5 PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCLK,LCD_G2,EVENTOUT,ADC12_IN6 PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT,ADC12_IN7 PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,LCD_R6,EVENTOUT, PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT, PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT, PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,,CAN1_TX,OTG_FS_DP,,,,LCD_R5,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT,ADC12_IN8 PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT,ADC12_IN9 PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT, PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,,,,,,,EVENTOUT, PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,,EVENTOUT, PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,CAN2_TX,,,FMC_SDNE1,DCMI_D5,,EVENTOUT, PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT, PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDIO_D4,DCMI_D6,LCD_B6,EVENTOUT, PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDIO_D5,DCMI_D7,LCD_B7,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT, PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,I2S2ext_SD,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT, PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,FMC_SDNWE,,,EVENTOUT,ADC123_IN10 PortC,PC1,,,,,,,,,,,,ETH_MDC,,,,EVENTOUT,ADC123_IN11 PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT,ADC123_IN12 PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13 PortC,PC4,,,,,,,,,,,,ETH_MII_RXD0/ETH_RMII_RXD0,,,,EVENTOUT,ADC12_IN14 PortC,PC5,,,,,,,,,,,,ETH_MII_RXD1/ETH_RMII_RXD1,,,,EVENTOUT,ADC12_IN15 PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,DCMI_D0,LCD_HSYNC,EVENTOUT, PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDIO_D7,DCMI_D1,LCD_G6,EVENTOUT, PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,USART6_CK,,,,SDIO_D0,DCMI_D2,,EVENTOUT, PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,,,,,,SDIO_D1,DCMI_D3,,EVENTOUT, PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,,,,SDIO_D2,DCMI_D8,LCD_R2,EVENTOUT, PortC,PC11,,,,,,I2S3ext_SD,SPI3_MISO,USART3_RX,UART4_RX,,,,SDIO_D3,DCMI_D4,,EVENTOUT, PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDIO_CK,DCMI_D9,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,,,,,,,CAN1_RX,,,FMC_D2,,,EVENTOUT, PortD,PD1,,,,,,,,,,CAN1_TX,,,FMC_D3,,,EVENTOUT, PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,SDIO_CMD,DCMI_D11,,EVENTOUT, PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT, PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT, PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT, PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT, PortD,PD7,,,,,,,,USART2_CK,,,,,FMC_NE1/FMC_NCE2,,,EVENTOUT, PortD,PD8,,,,,,,,USART3_TX,,,,,FMC_D13,,,EVENTOUT, PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT, PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT, PortD,PD11,,,,,,,,USART3_CTS,,,,,FMC_A16,,,EVENTOUT, PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS,,,,,FMC_A17,,,EVENTOUT, PortD,PD13,,,TIM4_CH2,,,,,,,,,,FMC_A18,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,,,,,,,,,FMC_D0,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,,,,,,,,,FMC_D1,,,EVENTOUT, PortE,PE0,,,TIM4_ETR,,,,,,UART8_RX,,,,FMC_NBL0,DCMI_D2,,EVENTOUT, PortE,PE1,,,,,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3,,EVENTOUT, PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,,,ETH_MII_TXD3,FMC_A23,,,EVENTOUT, PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT, PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT, PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT, PortE,PE6,TRACED3,,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,,,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT, PortE,PE7,,TIM1_ETR,,,,,,,UART7_RX,,,,FMC_D4,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,,,,,,UART7_TX,,,,FMC_D5,,,EVENTOUT, PortE,PE9,,TIM1_CH1,,,,,,,,,,,FMC_D6,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,,,,,,,,,,FMC_D7,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,,,FMC_D8,,LCD_G3,EVENTOUT, PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,,,FMC_D9,,LCD_B4,EVENTOUT, PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,,,FMC_D10,,LCD_DE,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,,,FMC_D11,,LCD_CLK,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,LCD_R7,EVENTOUT, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT, PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN9 PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN14 PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN15 PortF,PF6,,,,TIM10_CH1,,SPI5_NSS,SAI1_SD_B,,UART7_RX,,,,FMC_NIORD,,,EVENTOUT,ADC3_IN4 PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,,,,FMC_NREG,,,EVENTOUT,ADC3_IN5 PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,,TIM13_CH1,,,FMC_NIOWR,,,EVENTOUT,ADC3_IN6 PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,,TIM14_CH1,,,FMC_CD,,,EVENTOUT,ADC3_IN7 PortF,PF10,,,,,,,,,,,,,FMC_INTR,DCMI_D11,LCD_DE,EVENTOUT,ADC3_IN8 PortF,PF11,,,,,,SPI5_MOSI,,,,,,,FMC_SDNRAS,DCMI_D12,,EVENTOUT, PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT, PortF,PF13,,,,,,,,,,,,,FMC_A7,,,EVENTOUT, PortF,PF14,,,,,,,,,,,,,FMC_A8,,,EVENTOUT, PortF,PF15,,,,,,,,,,,,,FMC_A9,,,EVENTOUT, PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT, PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT, PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT, PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT, PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT, PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT, PortG,PG6,,,,,,,,,,,,,FMC_INT2,DCMI_D12,LCD_R7,EVENTOUT, PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT3,DCMI_D13,LCD_CLK,EVENTOUT, PortG,PG8,,,,,,SPI6_NSS,,,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,,EVENTOUT, PortG,PG9,,,,,,,,,USART6_RX,,,,FMC_NE2/FMC_NCE3,DCMI_VSYNC(1),,EVENTOUT, PortG,PG10,,,,,,,,,,LCD_G3,,,FMC_NCE4_1/FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT, PortG,PG11,,,,,,,,,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,FMC_NCE4_2,DCMI_D3,LCD_B3,EVENTOUT, PortG,PG12,,,,,,SPI6_MISO,,,USART6_RTS,LCD_B4,,,FMC_NE4,,LCD_B1,EVENTOUT, PortG,PG13,,,,,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,,EVENTOUT, PortG,PG14,,,,,,SPI6_MOSI,,,USART6_TX,,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,,EVENTOUT, PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH2,,,,,,,,,,,,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT, PortH,PH3,,,,,,,,,,,,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT, PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT, PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT, PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,,FMC_SDNE1,DCMI_D8,,, PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,, PortH,PH8,,,,,I2C3_SDA,,,,,,,,FMC_D16,DCMI_HSYNC,LCD_R2,EVENTOUT, PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,FMC_D17,DCMI_D0,LCD_R3,EVENTOUT, PortH,PH10,,,TIM5_CH1,,,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT, PortH,PH11,,,TIM5_CH2,,,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT, PortH,PH12,,,TIM5_CH3,,,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT, PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT, PortH,PH14,,,,TIM8_CH2N,,,,,,,,,FMC_D22,DCMI_D4,LCD_G3,EVENTOUT, PortH,PH15,,,,TIM8_CH3N,,,,,,,,,FMC_D23,DCMI_D11,LCD_G4,EVENTOUT, PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,FMC_D24,DCMI_D13,LCD_G5,EVENTOUT, PortI,PI1,,,,,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT, PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,I2S2ext_SD,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT, PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT, PortI,PI4,,,,TIM8_BKIN,,,,,,,,,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT, PortI,PI5,,,,TIM8_CH1,,,,,,,,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT, PortI,PI6,,,,TIM8_CH2,,,,,,,,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT, PortI,PI7,,,,TIM8_CH3,,,,,,,,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT, PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI9,,,,,,,,,,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT, PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT, PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT, PortI,PI12,,,,,,,,,,,,,,,LCD_HSYNC,EVENTOUT, PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT, PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT, PortI,PI15,,,,,,,,,,,,,,,LCD_R0,EVENTOUT, PortJ,PJ0,,,,,,,,,,,,,,,LCD_R1,EVENTOUT, PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT, PortJ,PJ2,,,,,,,,,,,,,,,LCD_R3,EVENTOUT, PortJ,PJ3,,,,,,,,,,,,,,,LCD_R4,EVENTOUT, PortJ,PJ4,,,,,,,,,,,,,,,LCD_R5,EVENTOUT, PortJ,PJ5,,,,,,,,,,,,,,,LCD_R6,EVENTOUT, PortJ,PJ6,,,,,,,,,,,,,,,LCD_R7,EVENTOUT, PortJ,PJ7,,,,,,,,,,,,,,,LCD_G0,EVENTOUT, PortJ,PJ8,,,,,,,,,,,,,,,LCD_G1,EVENTOUT, PortJ,PJ9,,,,,,,,,,,,,,,LCD_G2,EVENTOUT, PortJ,PJ10,,,,,,,,,,,,,,,LCD_G3,EVENTOUT, PortJ,PJ11,,,,,,,,,,,,,,,LCD_G4,EVENTOUT, PortJ,PJ12,,,,,,,,,,,,,,,LCD_B0,EVENTOUT, PortJ,PJ13,,,,,,,,,,,,,,,LCD_B1,EVENTOUT, PortJ,PJ14,,,,,,,,,,,,,,,LCD_B2,EVENTOUT, PortJ,PJ15,,,,,,,,,,,,,,,LCD_B3,EVENTOUT, PortK,PK0,,,,,,,,,,,,,,,LCD_G5,EVENTOUT, PortK,PK1,,,,,,,,,,,,,,,LCD_G6,EVENTOUT, PortK,PK2,,,,,,,,,,,,,,,LCD_G7,EVENTOUT, PortK,PK3,,,,,,,,,,,,,,,LCD_B4,EVENTOUT, PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT, PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT, PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT, PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32f439.ld000066400000000000000000000022611357706137100213130ustar00rootroot00000000000000/* GNU linker script for STM32F439 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* entire flash */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 896K /* sectors 5-11 are 128K */ FLASH_FS (rx) : ORIGIN = 0x08100000, LENGTH = 256K /* sectors 12-17 are 4*16K+64K+128K */ FLASH_FS2 (rx) : ORIGIN = 0x08140000, LENGTH = 128K /* sector 18 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f439_af.csv000066400000000000000000000257171357706137100221700ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/2/3/4/5/6,SPI2/3/SAI1,SPI3/USART1/2/3,USART6/UART4/5/7/8,CAN1/2/TIM12/13/14/LCD,OTG2_HS/OTG1_FS,ETH,FMC/SDIO/OTG2_FS,DCMI,LCD,SYS, PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0 PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,,EVENTOUT,ADC123_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT,ADC123_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT,ADC123_IN3 PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT,ADC12_IN4 PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5 PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCLK,LCD_G2,EVENTOUT,ADC12_IN6 PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT,ADC12_IN7 PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,LCD_R6,EVENTOUT, PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT, PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT, PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,,CAN1_TX,OTG_FS_DP,,,,LCD_R5,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT,ADC12_IN8 PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT,ADC12_IN9 PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT, PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,,,,,,,EVENTOUT, PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,,EVENTOUT, PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,CAN2_TX,,,FMC_SDNE1,DCMI_D5,,EVENTOUT, PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT, PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDIO_D4,DCMI_D6,LCD_B6,EVENTOUT, PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDIO_D5,DCMI_D7,LCD_B7,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT, PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,I2S2ext_SD,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT, PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,FMC_SDNWE,,,EVENTOUT,ADC123_IN10 PortC,PC1,,,,,,,,,,,,ETH_MDC,,,,EVENTOUT,ADC123_IN11 PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT,ADC123_IN12 PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13 PortC,PC4,,,,,,,,,,,,ETH_MII_RXD0/ETH_RMII_RXD0,,,,EVENTOUT,ADC12_IN14 PortC,PC5,,,,,,,,,,,,ETH_MII_RXD1/ETH_RMII_RXD1,,,,EVENTOUT,ADC12_IN15 PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,DCMI_D0,LCD_HSYNC,EVENTOUT, PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDIO_D7,DCMI_D1,LCD_G6,EVENTOUT, PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,USART6_CK,,,,SDIO_D0,DCMI_D2,,EVENTOUT, PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,,,,,,SDIO_D1,DCMI_D3,,EVENTOUT, PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,,,,SDIO_D2,DCMI_D8,LCD_R2,EVENTOUT, PortC,PC11,,,,,,I2S3ext_SD,SPI3_MISO,USART3_RX,UART4_RX,,,,SDIO_D3,DCMI_D4,,EVENTOUT, PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDIO_CK,DCMI_D9,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,,,,,,,CAN1_RX,,,FMC_D2,,,EVENTOUT, PortD,PD1,,,,,,,,,,CAN1_TX,,,FMC_D3,,,EVENTOUT, PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,SDIO_CMD,DCMI_D11,,EVENTOUT, PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT, PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT, PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT, PortD,PD6,,,,,,I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT, PortD,PD7,,,,,,,,USART2_CK,,,,,FMC_NE1/FMC_NCE2,,,EVENTOUT, PortD,PD8,,,,,,,,USART3_TX,,,,,FMC_D13,,,EVENTOUT, PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT, PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT, PortD,PD11,,,,,,,,USART3_CTS,,,,,FMC_A16,,,EVENTOUT, PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS,,,,,FMC_A17,,,EVENTOUT, PortD,PD13,,,TIM4_CH2,,,,,,,,,,FMC_A18,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,,,,,,,,,FMC_D0,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,,,,,,,,,FMC_D1,,,EVENTOUT, PortE,PE0,,,TIM4_ETR,,,,,,UART8_RX,,,,FMC_NBL0,DCMI_D2,,EVENTOUT, PortE,PE1,,,,,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3,,EVENTOUT, PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,,,ETH_MII_TXD3,FMC_A23,,,EVENTOUT, PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT, PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT, PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT, PortE,PE6,TRACED3,,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,,,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT, PortE,PE7,,TIM1_ETR,,,,,,,UART7_RX,,,,FMC_D4,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,,,,,,UART7_TX,,,,FMC_D5,,,EVENTOUT, PortE,PE9,,TIM1_CH1,,,,,,,,,,,FMC_D6,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,,,,,,,,,,FMC_D7,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,SPI3_NSS,,,,,,FMC_D8,,LCD_G3,EVENTOUT, PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,SPI3_SCK,,,,,,FMC_D9,,LCD_B4,EVENTOUT, PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,SPI3_MISO,,,,,,FMC_D10,,LCD_DE,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,SP3_MOSI,,,,,,FMC_D11,,LCD_CLK,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,LCD_R7,EVENTOUT, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT, PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN9 PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN14 PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN15 PortF,PF6,,,,TIM10_CH1,,SPI5_NSS,SAI1_SD_B,,UART7_RX,,,,FMC_NIORD,,,EVENTOUT,ADC3_IN4 PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,,,,FMC_NREG,,,EVENTOUT,ADC3_IN5 PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,,TIM13_CH1,,,FMC_NIOWR,,,EVENTOUT,ADC3_IN6 PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,,TIM14_CH1,,,FMC_CD,,,EVENTOUT,ADC3_IN7 PortF,PF10,,,,,,,,,,,,,FMC_INTR,DCMI_D11,LCD_DE,EVENTOUT,ADC3_IN8 PortF,PF11,,,,,,SPI5_MOSI,,,,,,,FMC_SDNRAS,DCMI_D12,,EVENTOUT, PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT, PortF,PF13,,,,,,,,,,,,,FMC_A7,,,EVENTOUT, PortF,PF14,,,,,,,,,,,,,FMC_A8,,,EVENTOUT, PortF,PF15,,,,,,,,,,,,,FMC_A9,,,EVENTOUT, PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT, PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT, PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT, PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT, PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT, PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT, PortG,PG6,,,,,,,,,,,,,FMC_INT2,DCMI_D12,LCD_R7,EVENTOUT, PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT3,DCMI_D13,LCD_CLK,EVENTOUT, PortG,PG8,,,,,,SPI6_NSS,,,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,,EVENTOUT, PortG,PG9,,,,,,,,,USART6_RX,,,,FMC_NE2/FMC_NCE3,DCMI_VSYNC(1),,EVENTOUT, PortG,PG10,,,,,,,,,,LCD_G3,,,FMC_NCE4_1/FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT, PortG,PG11,,,,,,,,,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,FMC_NCE4_2,DCMI_D3,LCD_B3,EVENTOUT, PortG,PG12,,,,,,SPI6_MISO,,,USART6_RTS,LCD_B4,,,FMC_NE4,,LCD_B1,EVENTOUT, PortG,PG13,,,,,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,,EVENTOUT, PortG,PG14,,,,,,SPI6_MOSI,,,USART6_TX,,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,,EVENTOUT, PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH2,,,,,,,,,,,,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT, PortH,PH3,,,,,,,,,,,,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT, PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT, PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT, PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,,FMC_SDNE1,DCMI_D8,,, PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,, PortH,PH8,,,,,I2C3_SDA,,,,,,,,FMC_D16,DCMI_HSYNC,LCD_R2,EVENTOUT, PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,FMC_D17,DCMI_D0,LCD_R3,EVENTOUT, PortH,PH10,,,TIM5_CH1,,,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT, PortH,PH11,,,TIM5_CH2,,,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT, PortH,PH12,,,TIM5_CH3,,,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT, PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT, PortH,PH14,,,,TIM8_CH2N,,,,,,,,,FMC_D22,DCMI_D4,LCD_G3,EVENTOUT, PortH,PH15,,,,TIM8_CH3N,,,,,,,,,FMC_D23,DCMI_D11,LCD_G4,EVENTOUT, PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,FMC_D24,DCMI_D13,LCD_G5,EVENTOUT, PortI,PI1,,,,,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT, PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,I2S2ext_SD,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT, PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT, PortI,PI4,,,,TIM8_BKIN,,,,,,,,,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT, PortI,PI5,,,,TIM8_CH1,,,,,,,,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT, PortI,PI6,,,,TIM8_CH2,,,,,,,,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT, PortI,PI7,,,,TIM8_CH3,,,,,,,,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT, PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI9,,,,,,,,,,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT, PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT, PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT, PortI,PI12,,,,,,,,,,,,,,,LCD_HSYNC,EVENTOUT, PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT, PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT, PortI,PI15,,,,,,,,,,,,,,,LCD_R0,EVENTOUT, PortJ,PJ0,,,,,,,,,,,,,,,LCD_R1,EVENTOUT, PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT, PortJ,PJ2,,,,,,,,,,,,,,,LCD_R3,EVENTOUT, PortJ,PJ3,,,,,,,,,,,,,,,LCD_R4,EVENTOUT, PortJ,PJ4,,,,,,,,,,,,,,,LCD_R5,EVENTOUT, PortJ,PJ5,,,,,,,,,,,,,,,LCD_R6,EVENTOUT, PortJ,PJ6,,,,,,,,,,,,,,,LCD_R7,EVENTOUT, PortJ,PJ7,,,,,,,,,,,,,,,LCD_G0,EVENTOUT, PortJ,PJ8,,,,,,,,,,,,,,,LCD_G1,EVENTOUT, PortJ,PJ9,,,,,,,,,,,,,,,LCD_G2,EVENTOUT, PortJ,PJ10,,,,,,,,,,,,,,,LCD_G3,EVENTOUT, PortJ,PJ11,,,,,,,,,,,,,,,LCD_G4,EVENTOUT, PortJ,PJ12,,,,,,,,,,,,,,,LCD_B0,EVENTOUT, PortJ,PJ13,,,,,,,,,,,,,,,LCD_B1,EVENTOUT, PortJ,PJ14,,,,,,,,,,,,,,,LCD_B2,EVENTOUT, PortJ,PJ15,,,,,,,,,,,,,,,LCD_B3,EVENTOUT, PortK,PK0,,,,,,,,,,,,,,,LCD_G5,EVENTOUT, PortK,PK1,,,,,,,,,,,,,,,LCD_G6,EVENTOUT, PortK,PK2,,,,,,,,,,,,,,,LCD_G7,EVENTOUT, PortK,PK3,,,,,,,,,,,,,,,LCD_B4,EVENTOUT, PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT, PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT, PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT, PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32f4xx_hal_conf_base.h000066400000000000000000000066731357706137100242050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_BASE_H #define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_BASE_H // Include various HAL modules for convenience #include "stm32f4xx_hal_dma.h" #include "stm32f4xx_hal_adc.h" #include "stm32f4xx_hal_can.h" #include "stm32f4xx_hal_cortex.h" #include "stm32f4xx_hal_crc.h" #include "stm32f4xx_hal_dac.h" #include "stm32f4xx_hal_dcmi.h" #include "stm32f4xx_hal_eth.h" #include "stm32f4xx_hal_flash.h" #include "stm32f4xx_hal_gpio.h" #include "stm32f4xx_hal_hash.h" #include "stm32f4xx_hal_hcd.h" #include "stm32f4xx_hal_i2c.h" #include "stm32f4xx_hal_i2s.h" #include "stm32f4xx_hal_iwdg.h" #include "stm32f4xx_hal_pcd.h" #include "stm32f4xx_hal_pwr.h" #include "stm32f4xx_hal_rcc.h" #include "stm32f4xx_hal_rtc.h" #include "stm32f4xx_hal_sd.h" #include "stm32f4xx_hal_sdram.h" #include "stm32f4xx_hal_spi.h" #include "stm32f4xx_hal_tim.h" #include "stm32f4xx_hal_uart.h" #include "stm32f4xx_hal_usart.h" #include "stm32f4xx_hal_wwdg.h" // Enable various HAL modules #define HAL_ADC_MODULE_ENABLED #define HAL_CAN_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED #define HAL_CRC_MODULE_ENABLED #define HAL_DAC_MODULE_ENABLED #define HAL_DCMI_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED #define HAL_ETH_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_HASH_MODULE_ENABLED #define HAL_HCD_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED #define HAL_I2S_MODULE_ENABLED #define HAL_IWDG_MODULE_ENABLED #define HAL_PCD_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_RTC_MODULE_ENABLED #define HAL_SD_MODULE_ENABLED #define HAL_SDRAM_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED #define HAL_WWDG_MODULE_ENABLED // Oscillator values in Hz #define HSI_VALUE (16000000) #define LSI_VALUE (40000) // SysTick has the highest priority #define TICK_INT_PRIORITY (0x00) // Miscellaneous HAL settings #define DATA_CACHE_ENABLE 1 #define INSTRUCTION_CACHE_ENABLE 1 #define PREFETCH_ENABLE 1 #define USE_RTOS 0 // HAL parameter assertions are disabled #define assert_param(expr) ((void)0) #endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_BASE_H micropython-1.12/ports/stm32/boards/stm32f4xx_prefix.c000066400000000000000000000015231357706137100227170ustar00rootroot00000000000000// stm32f4xx_prefix.c becomes the initial portion of the generated pins file. #include #include "py/obj.h" #include "py/mphal.h" #include "pin.h" #define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ { \ { &pin_af_type }, \ .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \ .idx = (af_idx), \ .fn = AF_FN_ ## af_fn, \ .unit = (af_unit), \ .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ .reg = (af_ptr) \ } #define PIN(p_port, p_pin, p_af, p_adc_num, p_adc_channel) \ { \ { &pin_type }, \ .name = MP_QSTR_ ## p_port ## p_pin, \ .port = PORT_ ## p_port, \ .pin = (p_pin), \ .num_af = (sizeof(p_af) / sizeof(pin_af_obj_t)), \ .pin_mask = (1 << ((p_pin) & 0x0f)), \ .gpio = GPIO ## p_port, \ .af = p_af, \ .adc_num = p_adc_num, \ .adc_channel = p_adc_channel, \ } micropython-1.12/ports/stm32/boards/stm32f722.ld000066400000000000000000000023101357706137100213010ustar00rootroot00000000000000/* GNU linker script for STM32F722, STM32F723, STM32F732, STM32F733 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0, 16K */ FLASH_FS (r) : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1-4 3*16KiB 1*64KiB*/ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 384K /* sectors 5-7 3*128KiB = 384K */ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* Used for storage cache */ RAM (xrw) : ORIGIN = 0x20010000, LENGTH = 192K /* SRAM1 = 176K, SRAM2 = 16K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f722_af.csv000066400000000000000000000235761357706137100221640ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/LPTIM1,I2C1/2/3/USART1,SPI1/I2S1/SPI2/I2S2/SPI3/I2S3/SPI4/5,SPI2/I2S2/SPI3/I2S3/SPI3/I2S3/SAI1/UART4,SPI2/I2S2/SPI3/I2S3/USART1/2/3/UART5,SAI2/USART6/UART4/5/7/8/OTG1_FS,CAN1/TIM12/13/14/QUADSPI/FMC/OTG2_HS,SAI2/QUADSPI/SDMMC2/OTG2_HS/OTG1_FS,SDMMC2,UART7/FMC/SDMMC1/OTG2_FS,,,SYS,ADC PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,SAI2_SD_B,,,,,EVENTOUT,ADC123_IN0 PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,,,,,EVENTOUT,ADC123_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,,,,,EVENTOUT,ADC123_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,,,,,EVENTOUT,ADC123_IN3 PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,,,EVENTOUT,ADC12_IN4 PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5 PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,,,EVENTOUT,ADC12_IN6 PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,,TIM14_CH1,,,FMC_SDNWE,,,EVENTOUT,ADC12_IN7 PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT, PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,,,,,,EVENTOUT, PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,,,EVENTOUT, PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,UART4_RTS,,,,,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,UART4_CTS,,OTG_HS_ULPI_D1,,,,,EVENTOUT,ADC12_IN8 PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,,,,,EVENTOUT,ADC12_IN9 PortB,PB2,,,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,,,,,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,SDMMC2_D2,,,,,EVENTOUT, PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,SDMMC2_D3,,,,,EVENTOUT, PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,,OTG_HS_ULPI_D7,,FMC_SDCKE1,,,EVENTOUT, PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,,QUADSPI_BK1_NCS,,FMC_SDNE1,,,EVENTOUT, PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FMC_NL,,,EVENTOUT, PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,SDMMC2_D4,,SDMMC1_D4,,,EVENTOUT, PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,SDMMC2_D5,,SDMMC1_D5,,,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,,,,,EVENTOUT, PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,,,,,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,,OTG_HS_ULPI_D5,,OTG_HS_ID,,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,,OTG_HS_ULPI_D6,,,,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,SDMMC2_D0,,OTG_HS_DM,,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,SDMMC2_D1,,OTG_HS_DP,,,EVENTOUT, PortC,PC0,,,,,,,,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,,EVENTOUT,ADC123_IN10 PortC,PC1,TRACED0,,,,,SPI2_MOSI/I2S2_SD,SAI1_SD_A,,,,,,,,,EVENTOUT,ADC123_IN11 PortC,PC2,,,,,,SPI2_MISO,,,,,OTG_HS_ULPI_DIR,,FMC_SDNE0,,,EVENTOUT,ADC123_IN12 PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13 PortC,PC4,,,,,,I2S1_MCK,,,,,,,FMC_SDNE0,,,EVENTOUT,ADC12_IN14 PortC,PC5,,,,,,,,,,,,,FMC_SDCKE0,,,EVENTOUT,ADC12_IN15 PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,SDMMC2_D6,,SDMMC1_D6,,,EVENTOUT, PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,SDMMC2_D7,,SDMMC1_D7,,,EVENTOUT, PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,,,,SDMMC1_D0,,,EVENTOUT, PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,,,SDMMC1_D1,,,EVENTOUT, PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,,,EVENTOUT, PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDMMC1_D3,,,EVENTOUT, PortC,PC12,TRACED3,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDMMC1_CK,,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,,,,,,,CAN1_RX,,,FMC_D2,,,EVENTOUT, PortD,PD1,,,,,,,,,,CAN1_TX,,,FMC_D3,,,EVENTOUT, PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,,,EVENTOUT, PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,FMC_CLK,,,EVENTOUT, PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT, PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT, PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,SDMMC2_CK,FMC_NWAIT,,,EVENTOUT, PortD,PD7,,,,,,,,USART2_CK,,,,SDMMC2_CMD,FMC_NE1,,,EVENTOUT, PortD,PD8,,,,,,,,USART3_TX,,,,,FMC_D13,,,EVENTOUT, PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT, PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,,EVENTOUT, PortD,PD11,,,,,,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT, PortD,PD12,,,TIM4_CH1,LPTIM1_IN1,,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17/FMC_ALE,,,EVENTOUT, PortD,PD13,,,TIM4_CH2,LPTIM1_OUT,,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,,FMC_D0,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS,,,,FMC_D1,,,EVENTOUT, PortE,PE0,,,TIM4_ETR,LPTIM1_ETR,,,,,UART8_RX,,SAI2_MCK_A,,FMC_NBL0,,,EVENTOUT, PortE,PE1,,,,LPTIM1_IN2,,,,,UART8_TX,,,,FMC_NBL1,,,EVENTOUT, PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,,FMC_A23,,,EVENTOUT, PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT, PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,,,EVENTOUT, PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,,,EVENTOUT, PortE,PE6,TRACED3,TIM1_BKIN2,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,SAI2_MCK_B,,FMC_A22,,,EVENTOUT, PortE,PE7,,TIM1_ETR,,,,,,,UART7_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,,,,,,UART7_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT, PortE,PE9,,TIM1_CH1,,,,,,,UART7_RTS,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,,,,,,UART7_CTS,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,SAI2_SD_B,,FMC_D8,,,EVENTOUT, PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9,,,EVENTOUT, PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10,,,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCK_B,,FMC_D11,,,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,,EVENTOUT, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT, PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN9 PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN14 PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN15 PortF,PF6,,,,TIM10_CH1,,SPI5_NSS,SAI1_SD_B,,UART7_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC3_IN4 PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT,ADC3_IN5 PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,UART7_RTS,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT,ADC3_IN6 PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,UART7_CTS,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT,ADC3_IN7 PortF,PF10,,,,,,,,,,,,,,,,EVENTOUT,ADC3_IN8 PortF,PF11,,,,,,SPI5_MOSI,,,,,SAI2_SD_B,,FMC_SDNRAS,,,EVENTOUT, PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT, PortF,PF13,,,,,,,,,,,,,FMC_A7,,,EVENTOUT, PortF,PF14,,,,,,,,,,,,,FMC_A8,,,EVENTOUT, PortF,PF15,,,,,,,,,,,,,FMC_A9,,,EVENTOUT, PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT, PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT, PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT, PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT, PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT, PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT, PortG,PG6,,,,,,,,,,,,,,,,EVENTOUT, PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT,,,EVENTOUT, PortG,PG8,,,,,,,,,USART6_RTS,,,,FMC_SDCLK,,,EVENTOUT, PortG,PG9,,,,,,,,,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,SDMMC2_D0,FMC_NE2/FMC_NCE,,,EVENTOUT, PortG,PG10,,,,,,,,,,,SAI2_SD_B,SDMMC2_D1,FMC_NE3,,,EVENTOUT, PortG,PG11,,,,,,,,,,,SDMMC2_D2,,,,,EVENTOUT, PortG,PG12,,,,LPTIM1_IN1,,,,,USART6_RTS,,,SDMMC2_D3,FMC_NE4,,,EVENTOUT, PortG,PG13,TRACED0,,,LPTIM1_OUT,,,,,USART6_CTS,,,,FMC_A24,,,EVENTOUT, PortG,PG14,TRACED1,,,LPTIM1_ETR,,,,,USART6_TX,QUADSPI_BK2_IO3,,,FMC_A25,,,EVENTOUT, PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH2,,,,LPTIM1_IN2,,,,,,QUADSPI_BK2_IO0,SAI2_SCK_B,,FMC_SDCKE0,,,EVENTOUT, PortH,PH3,,,,,,,,,,QUADSPI_BK2_IO1,SAI2_MCK_B,,FMC_SDNE0,,,EVENTOUT, PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT, PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT, PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,,FMC_SDNE1,,,EVENTOUT, PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,,FMC_SDCKE1,,,EVENTOUT, PortH,PH8,,,,,I2C3_SDA,,,,,,,,FMC_D16,,,EVENTOUT, PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,FMC_D17,,,EVENTOUT, PortH,PH10,,,TIM5_CH1,,,,,,,,,,FMC_D18,,,EVENTOUT, PortH,PH11,,,TIM5_CH2,,,,,,,,,,FMC_D19,,,EVENTOUT, PortH,PH12,,,TIM5_CH3,,,,,,,,,,FMC_D20,,,EVENTOUT, PortH,PH13,,,,TIM8_CH1N,,,,,UART4_TX,CAN1_TX,,,FMC_D21,,,EVENTOUT, PortH,PH14,,,,TIM8_CH2N,,,,,UART4_RX,CAN1_RX,,,FMC_D22,,,EVENTOUT, PortH,PH15,,,,TIM8_CH3N,,,,,,,,,FMC_D23,,,EVENTOUT, PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,FMC_D24,,,EVENTOUT, PortI,PI1,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,,,EVENTOUT, PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,,,,,,,FMC_D26,,,EVENTOUT, PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,,,EVENTOUT, PortI,PI4,,,,TIM8_BKIN,,,,,,,SAI2_MCK_A,,FMC_NBL2,,,EVENTOUT, PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,FMC_NBL3,,,EVENTOUT, PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,FMC_D28,,,EVENTOUT, PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,FMC_D29,,,EVENTOUT, PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI9,,,,,,,,,UART4_RX,CAN1_RX,,,FMC_D30,,,EVENTOUT, PortI,PI10,,,,,,,,,,,,,FMC_D31,,,EVENTOUT, PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT, PortI,PI12,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI13,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI14,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI15,,,,,,,,,,,,,,,,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32f746.ld000066400000000000000000000022611357706137100213140ustar00rootroot00000000000000/* GNU linker script for STM32F746 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sector 0, 32K */ FLASH_FS (r) : ORIGIN = 0x08008000, LENGTH = 96K /* sectors 1, 2, 3 (32K each) */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 896K /* sectors 4-7 1*128Kib 3*256KiB = 896K */ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* Used for storage cache */ RAM (xrw) : ORIGIN = 0x20010000, LENGTH = 256K /* SRAM1 = 240K, SRAM2 = 16K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f746_af.csv000066400000000000000000000273051357706137100221640ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15 ,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/LPTIM1/CEC,I2C1/2/3/4/CEC,SPI1/2/3/4/5/6,SPI3/SAI1,SPI2/3/USART1/2/3/UART5/SPDIFRX,SAI2/USART6/UART4/5/7/8/SPDIFRX,CAN1/2/TIM12/13/14/QUADSPI/LCD,SAI2/QUADSPI/OTG2_HS/OTG1_FS,ETH/OTG1_FS,FMC/SDMMC1/OTG2_FS,DCMI,LCD,SYS PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,SAI2_SD_B,ETH_MII_CRS,,,,EVENTOUT PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,LCD_R2,EVENTOUT PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,,,LCD_R1,EVENTOUT PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCLK,LCD_G2,EVENTOUT PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,,EVENTOUT PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,LCD_R6,EVENTOUT PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,LCD_R5,EVENTOUT PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,UART4_RTS,,,,,,,EVENTOUT PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT PortB,PB2,,,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,,,,,,EVENTOUT PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,,,,,,EVENTOUT PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,,EVENTOUT PortB,PB6,,,TIM4_CH1,HDMI_CEC,I2C1_SCL,,,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,,FMC_SDNE1,DCMI_D5,,EVENTOUT PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT PortC,PC0,,,,,,,,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,LCD_R5,EVENTOUT PortC,PC1,TRACED0,,,,,SPI2_MOSI/I2S2_SD,SAI1_SD_A,,,,,ETH_MDC,,,,EVENTOUT PortC,PC2,,,,,,SPI2_MISO,,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT PortC,PC4,,,,,,I2S1_MCK,,,SPDIFRX_IN2,,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT PortC,PC5,,,,,,,,,SPDIFRX_IN3,,,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,EVENTOUT PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,,,,SDMMC1_D0,DCMI_D2,,EVENTOUT PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,,,SDMMC1_D1,DCMI_D3,,EVENTOUT PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,DCMI_D8,LCD_R2,EVENTOUT PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDMMC1_D3,DCMI_D4,,EVENTOUT PortC,PC12,TRACED3,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9,,EVENTOUT PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT PortD,PD0,,,,,,,,,,CAN1_RX,,,FMC_D2,,,EVENTOUT PortD,PD1,,,,,,,,,,CAN1_TX,,,FMC_D3,,,EVENTOUT PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11,,EVENTOUT PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT PortD,PD7,,,,,,,,USART2_CK,SPDIFRX_IN0,,,,FMC_NE1,,,EVENTOUT PortD,PD8,,,,,,,,USART3_TX,SPDIFRX_IN1,,,,FMC_D13,,,EVENTOUT PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT PortD,PD12,,,TIM4_CH1,LPTIM1_IN1,I2C4_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17/FMC_ALE,,,EVENTOUT PortD,PD13,,,TIM4_CH2,LPTIM1_OUT,I2C4_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,,FMC_D0,,,EVENTOUT PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS,,,,FMC_D1,,,EVENTOUT PortE,PE0,,,TIM4_ETR,LPTIM1_ETR,,,,,UART8_RX,,SAI2_MCK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT PortE,PE1,,,,LPTIM1_IN2,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3,,EVENTOUT PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,ETH_MII_TXD3,FMC_A23,,,EVENTOUT PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT PortE,PE6,TRACED3,TIM1_BKIN2,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,SAI2_MCK_B,,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT PortE,PE7,,TIM1_ETR,,,,,,,UART7_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT PortE,PE8,,TIM1_CH1N,,,,,,,UART7_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT PortE,PE9,,TIM1_CH1,,,,,,,UART7_RTS,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT PortE,PE10,,TIM1_CH2N,,,,,,,UART7_CTS,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,SAI2_SD_B,,FMC_D8,,LCD_G3,EVENTOUT PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9,,LCD_B4,EVENTOUT PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10,,LCD_DE,EVENTOUT PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCK_B,,FMC_D11,,LCD_CLK,EVENTOUT PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,LCD_R7,EVENTOUT PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT PortF,PF6,,,,TIM10_CH1,,SPI5_NSS,SAI1_SD_B,,UART7_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,UART7_RTS,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,UART7_CTS,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT PortF,PF10,,,,,,,,,,,,,,DCMI_D11,LCD_DE,EVENTOUT PortF,PF11,,,,,,SPI5_MOSI,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT PortF,PF13,,,,,I2C4_SMBA,,,,,,,,FMC_A7,,,EVENTOUT PortF,PF14,,,,,I2C4_SCL,,,,,,,,FMC_A8,,,EVENTOUT PortF,PF15,,,,,I2C4_SDA,,,,,,,,FMC_A9,,,EVENTOUT PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT PortG,PG6,,,,,,,,,,,,,,DCMI_D12,LCD_R7,EVENTOUT PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT,DCMI_D13,LCD_CLK,EVENTOUT PortG,PG8,,,,,,SPI6_NSS,,SPDIFRX_IN2,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,,EVENTOUT PortG,PG9,,,,,,,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT PortG,PG10,,,,,,,,,,LCD_G3,SAI2_SD_B,,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT PortG,PG11,,,,,,,,SPDIFRX_IN0,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT PortG,PG12,,,,LPTIM1_IN1,,SPI6_MISO,,SPDIFRX_IN1,USART6_RTS,LCD_B4,,,FMC_NE4,,LCD_B1,EVENTOUT PortG,PG13,TRACED0,,,LPTIM1_OUT,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,LCD_R0,EVENTOUT PortG,PG14,TRACED1,,,LPTIM1_ETR,,SPI6_MOSI,,,USART6_TX,QUADSPI_BK2_IO3,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,LCD_B0,EVENTOUT PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT PortH,PH2,,,,LPTIM1_IN2,,,,,,QUADSPI_BK2_IO0,SAI2_SCK_B,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT PortH,PH3,,,,,,,,,,QUADSPI_BK2_IO1,SAI2_MCK_B,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,ETH_MII_RXD2,FMC_SDNE1,DCMI_D8,,EVENTOUT PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,EVENTOUT PortH,PH8,,,,,I2C3_SDA,,,,,,,,FMC_D16,DCMI_HSYNC,LCD_R2,EVENTOUT PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,FMC_D17,DCMI_D0,LCD_R3,EVENTOUT PortH,PH10,,,TIM5_CH1,,I2C4_SMBA,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT PortH,PH11,,,TIM5_CH2,,I2C4_SCL,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT PortH,PH12,,,TIM5_CH3,,I2C4_SDA,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT PortH,PH14,,,,TIM8_CH2N,,,,,,,,,FMC_D22,DCMI_D4,LCD_G3,EVENTOUT PortH,PH15,,,,TIM8_CH3N,,,,,,,,,FMC_D23,DCMI_D11,LCD_G4,EVENTOUT PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,FMC_D24,DCMI_D13,LCD_G5,EVENTOUT PortI,PI1,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT PortI,PI4,,,,TIM8_BKIN,,,,,,,SAI2_MCK_A,,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT PortI,PI9,,,,,,,,,,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT PortI,PI12,,,,,,,,,,,,,,,LCD_HSYNC,EVENTOUT PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT PortI,PI15,,,,,,,,,,,,,,,LCD_R0,EVENTOUT PortJ,PJ0,,,,,,,,,,,,,,,LCD_R1,EVENTOUT PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT PortJ,PJ2,,,,,,,,,,,,,,,LCD_R3,EVENTOUT PortJ,PJ3,,,,,,,,,,,,,,,LCD_R4,EVENTOUT PortJ,PJ4,,,,,,,,,,,,,,,LCD_R5,EVENTOUT PortJ,PJ5,,,,,,,,,,,,,,,LCD_R6,EVENTOUT PortJ,PJ6,,,,,,,,,,,,,,,LCD_R7,EVENTOUT PortJ,PJ7,,,,,,,,,,,,,,,LCD_G0,EVENTOUT PortJ,PJ8,,,,,,,,,,,,,,,LCD_G1,EVENTOUT PortJ,PJ9,,,,,,,,,,,,,,,LCD_G2,EVENTOUT PortJ,PJ10,,,,,,,,,,,,,,,LCD_G3,EVENTOUT PortJ,PJ11,,,,,,,,,,,,,,,LCD_G4,EVENTOUT PortJ,PJ12,,,,,,,,,,,,,,,LCD_B0,EVENTOUT PortJ,PJ13,,,,,,,,,,,,,,,LCD_B1,EVENTOUT PortJ,PJ14,,,,,,,,,,,,,,,LCD_B2,EVENTOUT PortJ,PJ15,,,,,,,,,,,,,,,LCD_B3,EVENTOUT PortK,PK0,,,,,,,,,,,,,,,LCD_G5,EVENTOUT PortK,PK1,,,,,,,,,,,,,,,LCD_G6,EVENTOUT PortK,PK2,,,,,,,,,,,,,,,LCD_G7,EVENTOUT PortK,PK3,,,,,,,,,,,,,,,LCD_B4,EVENTOUT PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT micropython-1.12/ports/stm32/boards/stm32f767.ld000066400000000000000000000024241357706137100213200ustar00rootroot00000000000000/* GNU linker script for STM32F767 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sector 0, 32K */ FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 2016K /* sectors 1-11 3x32K 1*128K 7*256K */ FLASH_FS (r) : ORIGIN = 0x08008000, LENGTH = 96K /* sectors 1, 2, 3 (32K each) */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 896K /* sectors 4-7 1*128Kib 3*256KiB = 896K */ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for storage cache */ RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 384K /* SRAM1 = 368K, SRAM2 = 16K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f767_af.csv000066400000000000000000000332101357706137100221570ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS,I2C4/UART5/TIM1/2,TIM3/4/5,TIM8/9/10/11/LPTIM1/DFSDM1/CEC,I2C1/2/3/4/USART1/CEC,SPI1/I2S1/SPI2/I2S2/SPI3/I2S3/SPI4/5/6,SPI2/I2S2/SPI3/I2S3/SAI1/I2C4/UART4/DFSDM1,SPI2/I2S2/SPI3/I2S3/SPI6/USART1/2/3/UART5/DFSDM1/SPDIF,SPI6/SAI2/USART6/UART4/5/7/8/OTG_FS/SPDIF,CAN1/2/TIM12/13/14/QUADSPI/FMC/LCD,SAI2/QUADSPI/SDMMC2/DFSDM1/OTG2_HS/OTG1_FS/LCD,I2C4/CAN3/SDMMC2/ETH,UART7/FMC/SDMMC1/MDIOS/OTG2_FS,DCMI/LCD/DSI,LCD,SYS,ADC PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,SAI2_SD_B,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0 PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,LCD_R2,EVENTOUT,ADC123_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,MDIOS_MDIO,,LCD_R1,EVENTOUT,ADC123_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,LCD_B2,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT,ADC123_IN3 PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,SPI6_NSS,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT,ADC12_IN4 PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,SPI6_SCK,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT,ADC12_IN5 PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,SPI6_MISO,TIM13_CH1,,,MDIOS_MDC,DCMI_PIXCLK,LCD_G2,EVENTOUT,ADC12_IN6 PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,SPI6_MOSI,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,,EVENTOUT,ADC12_IN7 PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,CAN3_RX,UART7_RX,LCD_B3,LCD_R6,EVENTOUT, PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,,,,DCMI_D0,LCD_R5,EVENTOUT, PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,LCD_B4,OTG_FS_ID,,MDIOS_MDIO,DCMI_D1,LCD_B1,EVENTOUT, PortA,PA11,,TIM1_CH4,,,,SPI2_NSS/I2S2_WS,UART4_RX,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,SPI2_SCK/I2S2_CK,UART4_TX,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,LCD_R5,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,SPI6_NSS,UART4_RTS,,,CAN3_TX,UART7_TX,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,DFSDM1_CKOUT,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,LCD_G1,EVENTOUT,ADC12_IN8 PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,DFSDM1_DATAIN1,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,LCD_G0,EVENTOUT,ADC12_IN9 PortB,PB2,,,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,DFSDM1_CKIN1,,,,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,SPI6_SCK,,SDMMC2_D2,CAN3_RX,UART7_RX,,,EVENTOUT, PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,SPI6_MISO,,SDMMC2_D3,CAN3_TX,UART7_TX,,,EVENTOUT, PortB,PB5,,UART5_RX,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,SPI6_MOSI,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,LCD_G7,EVENTOUT, PortB,PB6,,UART5_TX,TIM4_CH1,HDMI_CEC,I2C1_SCL,,DFSDM1_DATAIN5,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,I2C4_SCL,FMC_SDNE1,DCMI_D5,,EVENTOUT, PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,DFSDM1_CKIN5,USART1_RX,,,,I2C4_SDA,FMC_NL,DCMI_VSYNC,,EVENTOUT, PortB,PB8,,I2C4_SCL,TIM4_CH3,TIM10_CH1,I2C1_SCL,,DFSDM1_CKIN7,UART5_RX,,CAN1_RX,SDMMC2_D4,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT, PortB,PB9,,I2C4_SDA,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,DFSDM1_DATAIN7,UART5_TX,,CAN1_TX,SDMMC2_D5,I2C4_SMBA,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,DFSDM1_DATAIN7,USART3_TX,,QUADSPI_BK1_NCS,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT, PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,DFSDM1_CKIN7,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DSI_TE,LCD_G5,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,DFSDM1_DATAIN1,USART3_CK,UART5_RX,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,DFSDM1_CKIN1,USART3_CTS,UART5_TX,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,USART1_TX,SPI2_MISO,DFSDM1_DATAIN2,USART3_RTS,UART4_RTS,TIM12_CH1,SDMMC2_D0,,OTG_HS_DM,,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,USART1_RX,SPI2_MOSI/I2S2_SD,DFSDM1_CKIN2,,UART4_CTS,TIM12_CH2,SDMMC2_D1,,OTG_HS_DP,,,EVENTOUT, PortC,PC0,,,,DFSDM1_CKIN0,,,DFSDM1_DATAIN4,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,LCD_R5,EVENTOUT,ADC123_IN10 PortC,PC1,TRACED0,,,DFSDM1_DATAIN0,,SPI2_MOSI/I2S2_SD,SAI1_SD_A,,,,DFSDM1_CKIN4,ETH_MDC,MDIOS_MDC,,,EVENTOUT,ADC123_IN11 PortC,PC2,,,,DFSDM1_CKIN1,,SPI2_MISO,DFSDM1_CKOUT,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT,ADC123_IN12 PortC,PC3,,,,DFSDM1_DATAIN1,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13 PortC,PC4,,,,DFSDM1_CKIN2,,I2S1_MCK,,,SPDIFRX_IN2,,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT,ADC12_IN14 PortC,PC5,,,,DFSDM1_DATAIN2,,,,,SPDIFRX_IN3,,,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,EVENTOUT,ADC12_IN15 PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,DFSDM1_CKIN3,USART6_TX,FMC_NWAIT,SDMMC2_D6,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT, PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,DFSDM1_DATAIN3,USART6_RX,FMC_NE1,SDMMC2_D7,,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT, PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,FMC_NE2/FMC_NCE,,,SDMMC1_D0,DCMI_D2,,EVENTOUT, PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,LCD_G3,,SDMMC1_D1,DCMI_D3,LCD_B2,EVENTOUT, PortC,PC10,,,,DFSDM1_CKIN5,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,DCMI_D8,LCD_R2,EVENTOUT, PortC,PC11,,,,DFSDM1_DATAIN5,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDMMC1_D3,DCMI_D4,,EVENTOUT, PortC,PC12,TRACED3,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,DFSDM1_CKIN6,,,DFSDM1_DATAIN7,,UART4_RX,CAN1_RX,,,FMC_D2,,,EVENTOUT, PortD,PD1,,,,DFSDM1_DATAIN6,,,DFSDM1_CKIN7,,UART4_TX,CAN1_TX,,,FMC_D3,,,EVENTOUT, PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11,,EVENTOUT, PortD,PD3,,,,DFSDM1_CKOUT,,SPI2_SCK/I2S2_CK,DFSDM1_DATAIN0,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT, PortD,PD4,,,,,,,DFSDM1_CKIN0,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT, PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT, PortD,PD6,,,,DFSDM1_CKIN4,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,DFSDM1_DATAIN1,SDMMC2_CK,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT, PortD,PD7,,,,DFSDM1_DATAIN4,,SPI1_MOSI/I2S1_SD,DFSDM1_CKIN1,USART2_CK,SPDIFRX_IN0,,,SDMMC2_CMD,FMC_NE1,,,EVENTOUT, PortD,PD8,,,,DFSDM1_CKIN3,,,,USART3_TX,SPDIFRX_IN1,,,,FMC_D13,,,EVENTOUT, PortD,PD9,,,,DFSDM1_DATAIN3,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT, PortD,PD10,,,,DFSDM1_CKOUT,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT, PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT, PortD,PD12,,,TIM4_CH1,LPTIM1_IN1,I2C4_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17/FMC_ALE,,,EVENTOUT, PortD,PD13,,,TIM4_CH2,LPTIM1_OUT,I2C4_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,,FMC_D0,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS,,,,FMC_D1,,,EVENTOUT, PortE,PE0,,,TIM4_ETR,LPTIM1_ETR,,,,,UART8_RX,,SAI2_MCK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT, PortE,PE1,,,,LPTIM1_IN2,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3,,EVENTOUT, PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,ETH_MII_TXD3,FMC_A23,,,EVENTOUT, PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT, PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,DFSDM1_DATAIN3,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT, PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,DFSDM1_CKIN3,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT, PortE,PE6,TRACED3,TIM1_BKIN2,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,SAI2_MCK_B,,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT, PortE,PE7,,TIM1_ETR,,,,,DFSDM1_DATAIN2,,UART7_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,,,,DFSDM1_CKIN2,,UART7_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT, PortE,PE9,,TIM1_CH1,,,,,DFSDM1_CKOUT,,UART7_RTS,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,,,,DFSDM1_DATAIN4,,UART7_CTS,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,DFSDM1_CKIN4,,,,SAI2_SD_B,,FMC_D8,,LCD_G3,EVENTOUT, PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,DFSDM1_DATAIN5,,,,SAI2_SCK_B,,FMC_D9,,LCD_B4,EVENTOUT, PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,DFSDM1_CKIN5,,,,SAI2_FS_B,,FMC_D10,,LCD_DE,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCK_B,,FMC_D11,,LCD_CLK,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,LCD_R7,EVENTOUT, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT, PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN9 PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN14 PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN15 PortF,PF6,,,,TIM10_CH1,,SPI5_NSS,SAI1_SD_B,,UART7_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC3_IN4 PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT,ADC3_IN5 PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,UART7_RTS,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT,ADC3_IN6 PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,UART7_CTS,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT,ADC3_IN7 PortF,PF10,,,,,,,,,,QUADSPI_CLK,,,,DCMI_D11,LCD_DE,EVENTOUT,ADC3_IN8 PortF,PF11,,,,,,SPI5_MOSI,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT, PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT, PortF,PF13,,,,,I2C4_SMBA,,DFSDM1_DATAIN6,,,,,,FMC_A7,,,EVENTOUT, PortF,PF14,,,,,I2C4_SCL,,DFSDM1_CKIN6,,,,,,FMC_A8,,,EVENTOUT, PortF,PF15,,,,,I2C4_SDA,,,,,,,,FMC_A9,,,EVENTOUT, PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT, PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT, PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT, PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT, PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT, PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT, PortG,PG6,,,,,,,,,,,,,FMC_NE3,DCMI_D12,LCD_R7,EVENTOUT, PortG,PG7,,,,,,,SAI1_MCLK_A,,USART6_CK,,,,FMC_INT,DCMI_D13,LCD_CLK,EVENTOUT, PortG,PG8,,,,,,SPI6_NSS,,SPDIFRX_IN2,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,LCD_G7,EVENTOUT, PortG,PG9,,,,,,SPI1_MISO,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,SDMMC2_D0,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT, PortG,PG10,,,,,,SPI1_NSS/I2S1_WS,,,,LCD_G3,SAI2_SD_B,SDMMC2_D1,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT, PortG,PG11,,,,,,SPI1_SCK/I2S1_CK,,SPDIFRX_IN0,,,SDMMC2_D2,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT, PortG,PG12,,,,LPTIM1_IN1,,SPI6_MISO,,SPDIFRX_IN1,USART6_RTS,LCD_B4,,SDMMC2_D3,FMC_NE4,,LCD_B1,EVENTOUT, PortG,PG13,TRACED0,,,LPTIM1_OUT,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,LCD_R0,EVENTOUT, PortG,PG14,TRACED1,,,LPTIM1_ETR,,SPI6_MOSI,,,USART6_TX,QUADSPI_BK2_IO3,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,LCD_B0,EVENTOUT, PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH2,,,,LPTIM1_IN2,,,,,,QUADSPI_BK2_IO0,SAI2_SCK_B,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT, PortH,PH3,,,,,,,,,,QUADSPI_BK2_IO1,SAI2_MCK_B,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT, PortH,PH4,,,,,I2C2_SCL,,,,,LCD_G5,OTG_HS_ULPI_NXT,,,,LCD_G4,EVENTOUT, PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT, PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,ETH_MII_RXD2,FMC_SDNE1,DCMI_D8,,EVENTOUT, PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,EVENTOUT, PortH,PH8,,,,,I2C3_SDA,,,,,,,,FMC_D16,DCMI_HSYNC,LCD_R2,EVENTOUT, PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,FMC_D17,DCMI_D0,LCD_R3,EVENTOUT, PortH,PH10,,,TIM5_CH1,,I2C4_SMBA,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT, PortH,PH11,,,TIM5_CH2,,I2C4_SCL,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT, PortH,PH12,,,TIM5_CH3,,I2C4_SDA,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT, PortH,PH13,,,,TIM8_CH1N,,,,,UART4_TX,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT, PortH,PH14,,,,TIM8_CH2N,,,,,UART4_RX,CAN1_RX,,,FMC_D22,DCMI_D4,LCD_G3,EVENTOUT, PortH,PH15,,,,TIM8_CH3N,,,,,,,,,FMC_D23,DCMI_D11,LCD_G4,EVENTOUT, PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,FMC_D24,DCMI_D13,LCD_G5,EVENTOUT, PortI,PI1,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT, PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT, PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT, PortI,PI4,,,,TIM8_BKIN,,,,,,,SAI2_MCK_A,,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT, PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT, PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT, PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT, PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI9,,,,,,,,,UART4_RX,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT, PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT, PortI,PI11,,,,,,,,,,LCD_G6,OTG_HS_ULPI_DIR,,,,,EVENTOUT, PortI,PI12,,,,,,,,,,,,,,,LCD_HSYNC,EVENTOUT, PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT, PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT, PortI,PI15,,,,,,,,,,LCD_G2,,,,,LCD_R0,EVENTOUT, PortJ,PJ0,,,,,,,,,,LCD_R7,,,,,LCD_R1,EVENTOUT, PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT, PortJ,PJ2,,,,,,,,,,,,,,DSI_TE,LCD_R3,EVENTOUT, PortJ,PJ3,,,,,,,,,,,,,,,LCD_R4,EVENTOUT, PortJ,PJ4,,,,,,,,,,,,,,,LCD_R5,EVENTOUT, PortJ,PJ5,,,,,,,,,,,,,,,LCD_R6,EVENTOUT, PortJ,PJ6,,,,,,,,,,,,,,,LCD_R7,EVENTOUT, PortJ,PJ7,,,,,,,,,,,,,,,LCD_G0,EVENTOUT, PortJ,PJ8,,,,,,,,,,,,,,,LCD_G1,EVENTOUT, PortJ,PJ9,,,,,,,,,,,,,,,LCD_G2,EVENTOUT, PortJ,PJ10,,,,,,,,,,,,,,,LCD_G3,EVENTOUT, PortJ,PJ11,,,,,,,,,,,,,,,LCD_G4,EVENTOUT, PortJ,PJ12,,,,,,,,,,LCD_G3,,,,,LCD_B0,EVENTOUT, PortJ,PJ13,,,,,,,,,,LCD_G4,,,,,LCD_B1,EVENTOUT, PortJ,PJ14,,,,,,,,,,,,,,,LCD_B2,EVENTOUT, PortJ,PJ15,,,,,,,,,,,,,,,LCD_B3,EVENTOUT, PortK,PK0,,,,,,,,,,,,,,,LCD_G5,EVENTOUT, PortK,PK1,,,,,,,,,,,,,,,LCD_G6,EVENTOUT, PortK,PK2,,,,,,,,,,,,,,,LCD_G7,EVENTOUT, PortK,PK3,,,,,,,,,,,,,,,LCD_B4,EVENTOUT, PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT, PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT, PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT, PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32f769.ld000066400000000000000000000022611357706137100213210ustar00rootroot00000000000000/* GNU linker script for STM32F769 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sector 0, 32K */ FLASH_FS (r) : ORIGIN = 0x08008000, LENGTH = 96K /* sectors 1, 2, 3 (32K each) */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 896K /* sectors 4-7 1*128Kib 3*256KiB = 896K */ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for storage cache */ RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 384K /* SRAM1 = 368K, SRAM2 = 16K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32f7xx_hal_conf_base.h000066400000000000000000000065471357706137100242100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_BASE_H #define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_BASE_H // Include various HAL modules for convenience #include "stm32f7xx_hal_dma.h" #include "stm32f7xx_hal_adc.h" #include "stm32f7xx_hal_can.h" #include "stm32f7xx_hal_cortex.h" #include "stm32f7xx_hal_crc.h" #include "stm32f7xx_hal_dac.h" #include "stm32f7xx_hal_dcmi.h" #include "stm32f7xx_hal_flash.h" #include "stm32f7xx_hal_gpio.h" #include "stm32f7xx_hal_hash.h" #include "stm32f7xx_hal_hcd.h" #include "stm32f7xx_hal_i2c.h" #include "stm32f7xx_hal_i2s.h" #include "stm32f7xx_hal_iwdg.h" #include "stm32f7xx_hal_mmc.h" #include "stm32f7xx_hal_pcd.h" #include "stm32f7xx_hal_pwr.h" #include "stm32f7xx_hal_rcc.h" #include "stm32f7xx_hal_rtc.h" #include "stm32f7xx_hal_sd.h" #include "stm32f7xx_hal_sdram.h" #include "stm32f7xx_hal_spi.h" #include "stm32f7xx_hal_tim.h" #include "stm32f7xx_hal_uart.h" #include "stm32f7xx_hal_usart.h" #include "stm32f7xx_hal_wwdg.h" // Enable various HAL modules #define HAL_ADC_MODULE_ENABLED #define HAL_CAN_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED #define HAL_CRC_MODULE_ENABLED #define HAL_DAC_MODULE_ENABLED #define HAL_DCMI_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_HASH_MODULE_ENABLED #define HAL_HCD_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED #define HAL_I2S_MODULE_ENABLED #define HAL_IWDG_MODULE_ENABLED #define HAL_MMC_MODULE_ENABLED #define HAL_PCD_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_RTC_MODULE_ENABLED #define HAL_SD_MODULE_ENABLED #define HAL_SDRAM_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED #define HAL_WWDG_MODULE_ENABLED // Oscillator values in Hz #define HSI_VALUE (16000000) #define LSI_VALUE (32000) // SysTick has the highest priority #define TICK_INT_PRIORITY (0x00) // Miscellaneous HAL settings #define ART_ACCLERATOR_ENABLE 1 #define USE_RTOS 0 // HAL parameter assertions are disabled #define assert_param(expr) ((void)0) #endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_BASE_H micropython-1.12/ports/stm32/boards/stm32h743.ld000066400000000000000000000022061357706137100213120ustar00rootroot00000000000000/* GNU linker script for STM32H743 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 128K /* sector 0, 128K */ FLASH_FS (r) : ORIGIN = 0x08020000, LENGTH = 128K /* sector 1, 128K */ FLASH_TEXT (rx) : ORIGIN = 0x08040000, LENGTH = 1792K /* sectors 6*128 + 8*128 */ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for storage cache */ RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K /* AXI SRAM */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32h743_af.csv000066400000000000000000000374451357706137100221710ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS,TIM1/2/16/17/LPTIM1/HRTIM1,SAI1/TIM3/4/5/12/HRTIM1,LPUART/TIM8/LPTIM2/3/4/5/HRTIM1/DFSDM,I2C1/2/3/4/USART1/TIM15/LPTIM2/DFSDM/CEC,SPI1/2/3/4/5/6/CEC,SPI2/3/SAI1/3/I2C4/UART4/DFSDM,SPI2/3/6/USART1/2/3/6/UART7/SDMMC1,SPI6/SAI2/4/UART4/5/8/LPUART/SDMMC1/SPDIFRX,SAI4/FDCAN1/2/TIM13/14/QUADSPI/FMC/SDMMC2/LCD/SPDIFRX,SAI2/4/TIM8/QUADSPI/SDMMC2/OTG1_HS/OTG2_FS/LCD,I2C4/UART7/SWPMI1/TIM1/8/DFSDM/SDMMC2/MDIOS/ETH,TIM1/8/FMC/SDMMC1/MDIOS/OTG1_FS/LCD,TIM1/DCMI/LCD/COMP,UART5/LCD,SYS,ADC PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,TIM15_BKIN,,,USART2_CTS/USART2_NSS,UART4_TX,SDMMC2_CMD,SAI2_SD_B,ETH_MII_CRS,,,,EVENTOUT,ADC1_INP16/ADC12_INN1/ADC12_INP0 PortA,PA1,,TIM2_CH2,TIM5_CH2,LPTIM3_OUT,TIM15_CH1N,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,LCD_R2,EVENTOUT,ADC1_INN16/ADC1_INP17/ADC12_INP1 PortA,PA2,,TIM2_CH3,TIM5_CH3,LPTIM4_OUT,TIM15_CH1,,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,MDIOS_MDIO,,LCD_R1,EVENTOUT,ADC12_INP14 PortA,PA3,,TIM2_CH4,TIM5_CH4,LPTIM5_OUT,TIM15_CH2,,,USART2_RX,,LCD_B2,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT,ADC12_INP15 PortA,PA4,,,TIM5_ETR,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,SPI6_NSS,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT,ADC12_INP18 PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,SPI6_SCK,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT,ADC12_INN18/ADC12_INP19 PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO/I2S1_SDI,,,SPI6_MISO,TIM13_CH1,TIM8_BKIN_COMP12,MDIOS_MDC,TIM1_BKIN_COMP12,DCMI_PIXCLK,LCD_G2,EVENTOUT,ADC12_INP3 PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SDO,,,SPI6_MOSI,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,,EVENTOUT,ADC12_INN3/ADC12_INP7 PortA,PA8,MCO1,TIM1_CH1,HRTIM_CHB2,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,UART7_RX,TIM8_BKIN2_COMP12,LCD_B3,LCD_R6,EVENTOUT, PortA,PA9,,TIM1_CH2,HRTIM_CHC1,LPUART1_TX,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,CAN1_RXFD,,ETH_TX_ER,,DCMI_D0,LCD_R5,EVENTOUT, PortA,PA10,,TIM1_CH3,HRTIM_CHC2,LPUART1_RX,,,,USART1_RX,,CAN1_TXFD,OTG_FS_ID,MDIOS_MDIO,LCD_B4,DCMI_D1,LCD_B1,EVENTOUT, PortA,PA11,,TIM1_CH4,HRTIM_CHD1,LPUART1_CTS,,SPI2_NSS/I2S2_WS,UART4_RX,USART1_CTS/USART1_NSS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT, PortA,PA12,,TIM1_ETR,HRTIM_CHD2,LPUART1_RTS,,SPI2_SCK/I2S2_CK,UART4_TX,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,LCD_R5,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,HRTIM_FLT1,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,SPI6_NSS,UART4_RTS,,,UART7_TX,,,,EVENTOUT, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,DFSDM_CKOUT,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,LCD_G1,EVENTOUT,ADC12_INN5/ADC12_INP9 PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,DFSDM_DATIN1,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,LCD_G0,EVENTOUT,ADC12_INP5 PortB,PB2,,,SAI1_D1,,DFSDM_CKIN1,,SAI1_SD_A,SPI3_MOSI/I2S3_SDO,SAI4_SD_A,QUADSPI_CLK,SAI4_D1,ETH_TX_ER,,,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,HRTIM_FLT4,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,SPI6_SCK,SDMMC2_D2,,UART7_RX,,,,EVENTOUT, PortB,PB4,NJTRST,TIM16_BKIN,TIM3_CH1,HRTIM_EEV6,,SPI1_MISO/I2S1_SDI,SPI3_MISO/I2S3_SDI,SPI2_NSS/I2S2_WS,SPI6_MISO,SDMMC2_D3,,UART7_TX,,,,EVENTOUT, PortB,PB5,,TIM17_BKIN,TIM3_CH2,HRTIM_EEV7,I2C1_SMBA,SPI1_MOSI/I2S1_SDO,I2C4_SMBA,SPI3_MOSI/I2S3_SDO,SPI6_MOSI,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,UART5_RX,EVENTOUT, PortB,PB6,,TIM16_CH1N,TIM4_CH1,HRTIM_EEV8,I2C1_SCL,HDMI_CEC,I2C4_SCL,USART1_TX,LPUART1_TX,CAN2_TX,QUADSPI_BK1_NCS,DFSDM_DATIN5,FMC_SDNE1,DCMI_D5,UART5_TX,EVENTOUT, PortB,PB7,,TIM17_CH1N,TIM4_CH2,HRTIM_EEV9,I2C1_SDA,,I2C4_SDA,USART1_RX,LPUART1_RX,CAN2_TXFD,,DFSDM_CKIN5,FMC_NL,DCMI_VSYNC,,EVENTOUT, PortB,PB8,,TIM16_CH1,TIM4_CH3,DFSDM_CKIN7,I2C1_SCL,,I2C4_SCL,SDMMC1_CKIN,UART4_RX,CAN1_RX,SDMMC2_D4,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT, PortB,PB9,,TIM17_CH1,TIM4_CH4,DFSDM_DATIN7,I2C1_SDA,SPI2_NSS/I2S2_WS,I2C4_SDA,SDMMC1_CDIR,UART4_TX,CAN1_TX,SDMMC2_D5,I2C4_SMBA,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT, PortB,PB10,,TIM2_CH3,HRTIM_SCOUT,LPTIM2_IN1,I2C2_SCL,SPI2_SCK/I2S2_CK,DFSDM_DATIN7,USART3_TX,,QUADSPI_BK1_NCS,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT, PortB,PB11,,TIM2_CH4,HRTIM_SCIN,LPTIM2_ETR,I2C2_SDA,,DFSDM_CKIN7,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT, PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,DFSDM_DATIN1,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,TIM1_BKIN_COMP12,UART5_RX,EVENTOUT, PortB,PB13,,TIM1_CH1N,,LPTIM2_OUT,,SPI2_SCK/I2S2_CK,DFSDM_CKIN1,USART3_CTS/USART3_NSS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,UART5_TX,EVENTOUT, PortB,PB14,,TIM1_CH2N,TIM12_CH1,TIM8_CH2N,USART1_TX,SPI2_MISO/I2S2_SDI,DFSDM_DATIN2,USART3_RTS,UART4_RTS,SDMMC2_D0,,,OTG_HS_DM,,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,TIM12_CH2,TIM8_CH3N,USART1_RX,SPI2_MOSI/I2S2_SDO,DFSDM_CKIN2,,UART4_CTS,SDMMC2_D1,,,OTG_HS_DP,,,EVENTOUT, PortC,PC0,,,,DFSDM_CKIN0,,,DFSDM_DATIN4,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,LCD_R5,EVENTOUT,ADC123_INP10 PortC,PC1,TRACED0,,SAI1_D1,DFSDM_DATIN0,DFSDM_CKIN4,SPI2_MOSI/I2S2_SDO,SAI1_SD_A,,SAI4_SD_A,SDMMC2_CK,SAI4_D1,ETH_MDC,MDIOS_MDC,,,EVENTOUT,ADC123_INN10/ADC123_INP11 PortC,PC2,,,,DFSDM_CKIN1,,SPI2_MISO/I2S2_SDI,DFSDM_CKOUT,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT,ADC123_INN11/ADC123_INP12/ADC3_INN1/ADC3_INP0 PortC,PC3,,,,DFSDM_DATIN1,,SPI2_MOSI/I2S2_SDO,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT,ADC12_INN12/ADC12_INP13/ADC3_INP1 PortC,PC4,,,,DFSDM_CKIN2,,I2S1_MCK,,,,SPDIFRX_IN2,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT,ADC12_INP4 PortC,PC5,,,SAI1_D3,DFSDM_DATIN2,,,,,,SPDIFRX_IN3,SAI4_D3,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,COMP_1_OUT,,EVENTOUT,ADC12_INN4/ADC12_INP8 PortC,PC6,,HRTIM_CHA1,TIM3_CH1,TIM8_CH1,DFSDM_CKIN3,I2S2_MCK,,USART6_TX,SDMMC1_D0DIR,FMC_NWAIT,SDMMC2_D6,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT, PortC,PC7,TRGIO,HRTIM_CHA2,TIM3_CH2,TIM8_CH2,DFSDM_DATIN3,,I2S3_MCK,USART6_RX,SDMMC1_D123DIR,FMC_NE1,SDMMC2_D7,SWPMI_TX,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT, PortC,PC8,TRACED1,HRTIM_CHB1,TIM3_CH3,TIM8_CH3,,,,USART6_CK,UART5_RTS,FMC_NE2/FMC_NCE,,SWPMI_RX,SDMMC1_D0,DCMI_D2,,EVENTOUT, PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,,UART5_CTS,QUADSPI_BK1_IO0,LCD_G3,SWPMI_SUSPEND,SDMMC1_D1,DCMI_D3,LCD_B2,EVENTOUT, PortC,PC10,,,HRTIM_EEV1,DFSDM_CKIN5,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,DCMI_D8,LCD_R2,EVENTOUT, PortC,PC11,,,HRTIM_FLT2,DFSDM_DATIN5,,,SPI3_MISO/I2S3_SDI,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDMMC1_D3,DCMI_D4,,EVENTOUT, PortC,PC12,TRACED3,,HRTIM_EEV2,,,,SPI3_MOSI/I2S3_SDO,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,DFSDM_CKIN6,,,SAI3_SCK_A,,UART4_RX,CAN1_RX,,,FMC_D2/FMC_DA2,,,EVENTOUT, PortD,PD1,,,,DFSDM_DATIN6,,,SAI3_SD_A,,UART4_TX,CAN1_TX,,,FMC_D3/FMC_DA3,,,EVENTOUT, PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11,,EVENTOUT, PortD,PD3,,,,DFSDM_CKOUT,,SPI2_SCK/I2S2_CK,,USART2_CTS/USART2_NSS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT, PortD,PD4,,,HRTIM_FLT3,,,,SAI3_FS_A,USART2_RTS,,CAN1_RXFD,,,FMC_NOE,,,EVENTOUT, PortD,PD5,,,HRTIM_EEV3,,,,,USART2_TX,,CAN1_TXFD,,,FMC_NWE,,,EVENTOUT, PortD,PD6,,,SAI1_D1,DFSDM_CKIN4,DFSDM_DATIN1,SPI3_MOSI/I2S3_SDO,SAI1_SD_A,USART2_RX,SAI4_SD_A,CAN2_RXFD,SAI4_D1,SDMMC2_CK,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT, PortD,PD7,,,,DFSDM_DATIN4,,SPI1_MOSI/I2S1_SDO,DFSDM_CKIN1,USART2_CK,,SPDIFRX_IN0,,SDMMC2_CMD,FMC_NE1,,,EVENTOUT, PortD,PD8,,,,DFSDM_CKIN3,,,SAI3_SCK_B,USART3_TX,,SPDIFRX_IN1,,,FMC_D13/FMC_DA13,,,EVENTOUT, PortD,PD9,,,,DFSDM_DATIN3,,,SAI3_SD_B,USART3_RX,,CAN2_RXFD,,,FMC_D14/FMC_DA14,,,EVENTOUT, PortD,PD10,,,,DFSDM_CKOUT,,,SAI3_FS_B,USART3_CK,,CAN2_TXFD,,,FMC_D15/FMC_DA15,,LCD_B3,EVENTOUT, PortD,PD11,,,,LPTIM2_IN2,I2C4_SMBA,,,USART3_CTS/USART3_NSS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16,,,EVENTOUT, PortD,PD12,,LPTIM1_IN1,TIM4_CH1,LPTIM2_IN1,I2C4_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17,,,EVENTOUT, PortD,PD13,,LPTIM1_OUT,TIM4_CH2,,I2C4_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT, PortD,PD14,,,TIM4_CH3,,,,SAI3_MCLK_B,,UART8_CTS,,,,FMC_D0/FMC_DA0,,,EVENTOUT, PortD,PD15,,,TIM4_CH4,,,,SAI3_MCLK_A,,UART8_RTS,,,,FMC_D1/FMC_DA1,,,EVENTOUT, PortE,PE0,,LPTIM1_ETR,TIM4_ETR,HRTIM_SCIN,LPTIM2_ETR,,,,UART8_RX,CAN1_RXFD,SAI2_MCK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT, PortE,PE1,,LPTIM1_IN2,,HRTIM_SCOUT,,,,,UART8_TX,CAN1_TXFD,,,FMC_NBL1,DCMI_D3,,EVENTOUT, PortE,PE2,TRACECLK,,SAI1_CK1,,,SPI4_SCK,SAI1_MCLK_A,,SAI4_MCLK_A,QUADSPI_BK1_IO2,SAI4_CK1,ETH_MII_TXD3,FMC_A23,,,EVENTOUT, PortE,PE3,TRACED0,,,,TIM15_BKIN,,SAI1_SD_B,,SAI4_SD_B,,,,FMC_A19,,,EVENTOUT, PortE,PE4,TRACED1,,SAI1_D2,DFSDM_DATIN3,TIM15_CH1N,SPI4_NSS,SAI1_FS_A,,SAI4_FS_A,,SAI4_D2,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT, PortE,PE5,TRACED2,,SAI1_CK2,DFSDM_CKIN3,TIM15_CH1,SPI4_MISO,SAI1_SCK_A,,SAI4_SCK_A,,SAI4_CK2,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT, PortE,PE6,TRACED3,TIM1_BKIN2,SAI1_D1,,TIM15_CH2,SPI4_MOSI,SAI1_SD_A,,SAI4_SD_A,SAI4_D1,SAI2_MCK_B,TIM1_BKIN2_COMP12,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT, PortE,PE7,,TIM1_ETR,,DFSDM_DATIN2,,,,UART7_RX,,,QUADSPI_BK2_IO0,,FMC_D4/FMC_DA4,,,EVENTOUT, PortE,PE8,,TIM1_CH1N,,DFSDM_CKIN2,,,,UART7_TX,,,QUADSPI_BK2_IO1,,FMC_D5/FMC_DA5,COMP_2_OUT,,EVENTOUT, PortE,PE9,,TIM1_CH1,,DFSDM_CKOUT,,,,UART7_RTS,,,QUADSPI_BK2_IO2,,FMC_D6/FMC_DA6,,,EVENTOUT, PortE,PE10,,TIM1_CH2N,,DFSDM_DATIN4,,,,UART7_CTS,,,QUADSPI_BK2_IO3,,FMC_D7/FMC_DA7,,,EVENTOUT, PortE,PE11,,TIM1_CH2,,DFSDM_CKIN4,,SPI4_NSS,,,,,SAI2_SD_B,,FMC_D8/FMC_DA8,,LCD_G3,EVENTOUT, PortE,PE12,,TIM1_CH3N,,DFSDM_DATIN5,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9/FMC_DA9,COMP_1_OUT,LCD_B4,EVENTOUT, PortE,PE13,,TIM1_CH3,,DFSDM_CKIN5,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10/FMC_DA10,COMP_2_OUT,LCD_DE,EVENTOUT, PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCK_B,,FMC_D11/FMC_DA11,,LCD_CLK,EVENTOUT, PortE,PE15,,TIM1_BKIN,,,,HDMI__TIM1_BKIN,,,,,,,FMC_D12/FMC_DA12,TIM1_BKIN_COMP12,LCD_R7,EVENTOUT, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT, PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_INP5 PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_INN5/ADC3_INP9 PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_INP4 PortF,PF6,,TIM16_CH1,,,,SPI5_NSS,SAI1_SD_B,UART7_RX,SAI4_SD_B,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC3_INN4/ADC3_INP8 PortF,PF7,,TIM17_CH1,,,,SPI5_SCK,SAI1_MCLK_B,UART7_TX,SAI4_MCLK_B,QUADSPI_BK1_IO2,,,,,,EVENTOUT,ADC3_INP3 PortF,PF8,,TIM16_CH1N,,,,SPI5_MISO,SAI1_SCK_B,UART7_RTS,SAI4_SCK_B,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT,ADC3_INN3/ADC3_INP7 PortF,PF9,,TIM17_CH1N,,,,SPI5_MOSI,SAI1_FS_B,UART7_CTS,SAI4_FS_B,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT,ADC3_INP2 PortF,PF10,,TIM16_BKIN,SAI1_D3,,,,,,,QUADSPI_CLK,SAI4_D3,,,DCMI_D11,LCD_DE,EVENTOUT,ADC3_INN2/ADC3_INP6 PortF,PF11,,,,,,SPI5_MOSI,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT,ADC1_INP2 PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT,ADC1_INN2/DC1_INP6 PortF,PF13,,,,DFSDM_DATIN6,I2C4_SMBA,,,,,,,,FMC_A7,,,EVENTOUT,ACD2_INP2 PortF,PF14,,,,DFSDM_CKIN6,I2C4_SCL,,,,,,,,FMC_A8,,,EVENTOUT,ADC2_INN2/ADC2_INP6 PortF,PF15,,,,,I2C4_SDA,,,,,,,,FMC_A9,,,EVENTOUT, PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT, PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT, PortG,PG2,,,,TIM8_BKIN,,,,,,,,TIM8_BKIN_COMP12,FMC_A12,,,EVENTOUT, PortG,PG3,,,,TIM8_BKIN2,,,,,,,,TIM8_BKIN2_COMP12,FMC_A13,,,EVENTOUT, PortG,PG4,,TIM1_BKIN2,,,,,,,,,,TIM1_BKIN2_COMP12,FMC_A14/FMC_BA0,,,EVENTOUT, PortG,PG5,,TIM1_ETR,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT, PortG,PG6,,TIM17_BKIN,HRTIM_CHE1,,,,,,,,QUADSPI_BK1_NCS,,FMC_NE3,DCMI_D12,LCD_R7,EVENTOUT, PortG,PG7,,,HRTIM_CHE2,,,,SAI1_MCLK_A,USART6_CK,,,,,FMC_INT,DCMI_D13,LCD_CLK,EVENTOUT, PortG,PG8,,,,TIM8_ETR,,SPI6_NSS,,USART6_RTS,SPDIFRX_IN2,,,ETH_PPS_OUT,FMC_SDCLK,,LCD_G7,EVENTOUT, PortG,PG9,,,,,,SPI1_MISO/I2S1_SDI,,USART6_RX,SPDIFRX_IN3,QUADSPI_BK2_IO2,SAI2_FS_B,,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT, PortG,PG10,,,HRTIM_FLT5,,,SPI1_NSS/I2S1_WS,,,,LCD_G3,SAI2_SD_B,,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT, PortG,PG11,,,HRTIM_EEV4,,,SPI1_SCK/I2S1_CK,,,SPDIFRX_IN0,,SDMMC2_D2,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT, PortG,PG12,,LPTIM1_IN1,HRTIM_EEV5,,,SPI6_MISO,,USART6_RTS,SPDIFRX_IN1,LCD_B4,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_NE4,,LCD_B1,EVENTOUT, PortG,PG13,TRACED0,LPTIM1_OUT,HRTIM_EEV10,,,SPI6_SCK,,USART6_CTS/USART6_NSS,,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,LCD_R0,EVENTOUT, PortG,PG14,TRACED1,LPTIM1_ETR,,,,SPI6_MOSI,,USART6_TX,,QUADSPI_BK2_IO3,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,LCD_B0,EVENTOUT, PortG,PG15,,,,,,,,USART6_CTS/USART6_NSS,,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH2,,LPTIM1_IN2,,,,,,,,QUADSPI_BK2_IO0,SAI2_SCK_B,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT,ADC3_INP13 PortH,PH3,,,,,,,,,,QUADSPI_BK2_IO1,SAI2_MCK_B,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT,ADC3_INN13/ADC3_INP14 PortH,PH4,,,,,I2C2_SCL,,,,,LCD_G5,OTG_HS_ULPI_NXT,,,,LCD_G4,EVENTOUT,ADC3_INN14/ADC3_INP15 PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT,ADC3_INN15/ADC3_INP16 PortH,PH6,,,TIM12_CH1,,I2C2_SMBA,SPI5_SCK,,,,,,ETH_MII_RXD2,FMC_SDNE1,DCMI_D8,,EVENTOUT, PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,EVENTOUT, PortH,PH8,,,TIM5_ETR,,I2C3_SDA,,,,,,,,FMC_D16,DCMI_HSYNC,LCD_R2,EVENTOUT, PortH,PH9,,,TIM12_CH2,,I2C3_SMBA,,,,,,,,FMC_D17,DCMI_D0,LCD_R3,EVENTOUT, PortH,PH10,,,TIM5_CH1,,I2C4_SMBA,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT, PortH,PH11,,,TIM5_CH2,,I2C4_SCL,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT, PortH,PH12,,,TIM5_CH3,,I2C4_SDA,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT, PortH,PH13,,,,TIM8_CH1N,,,,,UART4_TX,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT, PortH,PH14,,,,TIM8_CH2N,,,,,UART4_RX,CAN1_RX,,,FMC_D22,DCMI_D4,LCD_G3,EVENTOUT, PortH,PH15,,,,TIM8_CH3N,,,,,,CAN1_TXFD,,,FMC_D23,DCMI_D11,LCD_G4,EVENTOUT, PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,CAN1_RXFD,,,FMC_D24,DCMI_D13,LCD_G5,EVENTOUT, PortI,PI1,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,TIM8_BKIN2_COMP12,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT, PortI,PI2,,,,TIM8_CH4,,SPI2_MISO/I2S2_SDI,,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT, PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SDO,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT, PortI,PI4,,,,TIM8_BKIN,,,,,,,SAI2_MCK_A,TIM8_BKIN_COMP12,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT, PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT, PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT, PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT, PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT, PortI,PI9,,,,,,,,,UART4_RX,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT, PortI,PI10,,,,,,,,,,CAN1_RXFD,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT, PortI,PI11,,,,,,,,,,LCD_G6,OTG_HS_ULPI_DIR,,,,,EVENTOUT, PortI,PI12,,,,,,,,,,,,ETH_TX_ER,,,LCD_HSYNC,EVENTOUT, PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT, PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT, PortI,PI15,,,,,,,,,,LCD_G2,,,,,LCD_R0,EVENTOUT, PortJ,PJ0,,,,,,,,,,LCD_R7,,,,,LCD_R1,EVENTOUT, PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT, PortJ,PJ2,,,,,,,,,,,,,,,LCD_R3,EVENTOUT, PortJ,PJ3,,,,,,,,,,,,,,,LCD_R4,EVENTOUT, PortJ,PJ4,,,,,,,,,,,,,,,LCD_R5,EVENTOUT, PortJ,PJ5,,,,,,,,,,,,,,,LCD_R6,EVENTOUT, PortJ,PJ6,,,,TIM8_CH2,,,,,,,,,,,LCD_R7,EVENTOUT, PortJ,PJ7,TRGIN,,,TIM8_CH2N,,,,,,,,,,,LCD_G0,EVENTOUT, PortJ,PJ8,,TIM1_CH3N,,TIM8_CH1,,,,,UART8_TX,,,,,,LCD_G1,EVENTOUT, PortJ,PJ9,,TIM1_CH3,,TIM8_CH1N,,,,,UART8_RX,,,,,,LCD_G2,EVENTOUT, PortJ,PJ10,,TIM1_CH2N,,TIM8_CH2,,SPI5_MOSI,,,,,,,,,LCD_G3,EVENTOUT, PortJ,PJ11,,TIM1_CH2,,TIM8_CH2N,,SPI5_MISO,,,,,,,,,LCD_G4,EVENTOUT, PortJ,PJ12,TRGOUT,,,,,,,,,LCD_G3,,,,,LCD_B0,EVENTOUT, PortJ,PJ13,,,,,,,,,,LCD_B4,,,,,LCD_B1,EVENTOUT, PortJ,PJ14,,,,,,,,,,,,,,,LCD_B2,EVENTOUT, PortJ,PJ15,,,,,,,,,,,,,,,LCD_B3,EVENTOUT, PortK,PK0,,TIM1_CH1N,,TIM8_CH3,,SPI5_SCK,,,,,,,,,LCD_G5,EVENTOUT, PortK,PK1,,TIM1_CH1,,TIM8_CH3N,,SPI5_NSS,,,,,,,,,LCD_G6,EVENTOUT, PortK,PK2,,TIM1_BKIN,,TIM8_BKIN,,,,,,,TIM8_BKIN_COMP12,TIM1_BKIN_COMP12,,,LCD_G7,EVENTOUT, PortK,PK3,,,,,,,,,,,,,,,LCD_B4,EVENTOUT, PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT, PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT, PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT, PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32h7xx_hal_conf_base.h000066400000000000000000000065451357706137100242100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32H7XX_HAL_CONF_BASE_H #define MICROPY_INCLUDED_STM32H7XX_HAL_CONF_BASE_H // Include various HAL modules for convenience #include "stm32h7xx_hal_dma.h" #include "stm32h7xx_hal_mdma.h" #include "stm32h7xx_hal_adc.h" #include "stm32h7xx_hal_cortex.h" #include "stm32h7xx_hal_crc.h" #include "stm32h7xx_hal_dac.h" #include "stm32h7xx_hal_dcmi.h" #include "stm32h7xx_hal_fdcan.h" #include "stm32h7xx_hal_flash.h" #include "stm32h7xx_hal_gpio.h" #include "stm32h7xx_hal_hash.h" #include "stm32h7xx_hal_hcd.h" #include "stm32h7xx_hal_i2c.h" #include "stm32h7xx_hal_i2s.h" #include "stm32h7xx_hal_iwdg.h" #include "stm32h7xx_hal_pcd.h" #include "stm32h7xx_hal_pwr.h" #include "stm32h7xx_hal_rcc.h" #include "stm32h7xx_hal_rtc.h" #include "stm32h7xx_hal_sd.h" #include "stm32h7xx_hal_sdram.h" #include "stm32h7xx_hal_spi.h" #include "stm32h7xx_hal_tim.h" #include "stm32h7xx_hal_uart.h" #include "stm32h7xx_hal_usart.h" #include "stm32h7xx_hal_wwdg.h" // Enable various HAL modules #define HAL_ADC_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED #define HAL_CRC_MODULE_ENABLED #define HAL_DAC_MODULE_ENABLED #define HAL_DCMI_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED #define HAL_FDCAN_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_HASH_MODULE_ENABLED #define HAL_HCD_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED #define HAL_I2S_MODULE_ENABLED #define HAL_IWDG_MODULE_ENABLED #define HAL_PCD_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_RTC_MODULE_ENABLED #define HAL_SD_MODULE_ENABLED #define HAL_SDRAM_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED #define HAL_WWDG_MODULE_ENABLED // Oscillator values in Hz #define CSI_VALUE (4000000) #define HSI_VALUE (64000000) // SysTick has the highest priority #define TICK_INT_PRIORITY (0x00) // Miscellaneous HAL settings #define USE_RTOS 0 #define USE_SD_TRANSCEIVER 0 #define USE_SPI_CRC 1 // HAL parameter assertions are disabled #define assert_param(expr) ((void)0) #endif // MICROPY_INCLUDED_STM32H7XX_HAL_CONF_BASE_H micropython-1.12/ports/stm32/boards/stm32l072_af.csv000066400000000000000000000105251357706137100221560ustar00rootroot00000000000000Port,Pin,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,, ,,SPI1/SPI2/I2S2/USART1/2/LPUART1/USB/LPTIM1/TSC/TIM2/21/22/EVENTOUT/SYS_AF,SPI1/SPI2/I2S2/I2C1/TIM2/21,SPI1/SPI2/I2S2/LPUART1/USART5/USB/LPTIM1/TIM2/3/EVENTOUT/SYS_AF,I2C1/TSC/EVENTOUT,I2C1/USART1/2/LPUART1/TIM3/22/EVENTOUT,SPI2/I2S2/I2C2/USART1/TIM2/21/22,I2C1/2/LPUART1/USART4/UASRT5/TIM21/EVENTOUT,I2C3/LPUART1/COMP1/2/TIM3,,ADC PortA,PA0,,,TIM2_CH1,TSC_G1_IO1,USART2_CTS,TIM2_ETR,USART4_TX,COMP1_OUT,,ADC_IN0 PortA,PA1,EVENTOUT,,TIM2_CH2,TSC_G1_IO2,USART2_RTS_DE,TIM21_ETR,USART4_RX,,,ADC_IN1 PortA,PA2,TIM21_CH1,,TIM2_CH3,TSC_G1_IO3,USART2_TX,,LPUART1_TX,COMP2_OUT,,ADC_IN2 PortA,PA3,TIM21_CH2,,TIM2_CH4,TSC_G1_IO4,USART2_RX,,LPUART1_RX,,,ADC_IN3 PortA,PA4,SPI1_NSS,,,TSC_G2_IO1,USART2_CK,TIM22_ETR,,,,ADC_IN4 PortA,PA5,SPI1_SCK,,TIM2_ETR,TSC_G2_IO2,,TIM2_CH1,,,,ADC_IN5 PortA,PA6,SPI1_MISO,,TIM3_CH1,TSC_G2_IO3,LPUART1_CTS,TIM22_CH1,EVENTOUT,COMP1_OUT,,ADC_IN6 PortA,PA7,SPI1_MOSI,,TIM3_CH2,TSC_G2_IO4,,TIM22_CH2,EVENTOUT,COMP2_OUT,,ADC_IN7 PortA,PA8,MCO,,USB_CRS_SYNC,EVENTOUT,USART1_CK,,,I2C3_SCL,, PortA,PA9,MCO,,,TSC_G4_IO1,USART1_TX,,I2C1_SCL,I2C3_SMBA,, PortA,PA10,,,,TSC_G4_IO2,USART1_RX,,I2C1_SDA,,, PortA,PA11,SPI1_MISO,,EVENTOUT,TSC_G4_IO3,USART1_CTS,,,COMP1_OUT,, PortA,PA12,SPI1_MOSI,,EVENTOUT,TSC_G4_IO4,USART1_RTS_DE,,,COMP2_OUT,, PortA,PA13,SWDIO,,USB_NOE,,,,LPUART1_RX,,, PortA,PA14,SWCLK,,,,USART2_TX,,LPUART1_TX,,, PortA,PA15,SPI1_NSS,,TIM2_ETR,EVENTOUT,USART2_RX,TIM2_CH1,USART4_RTS_DE,,, PortB,PB0,EVENTOUT,,TIM3_CH3,TSC_G3_IO2,,,,,,ADC_IN8 PortB,PB1,,,TIM3_CH4,TSC_G3_IO3,LPUART1_RTS_DE,,,,,ADC_IN9 PortB,PB2,,,LPTIM1_OUT,TSC_G3_IO4,,,,I2C3_SMBA,, PortB,PB3,SPI1_SCK,,TIM2_CH2,TSC_G5_IO1,EVENTOUT,USART1_RTS_DE,USART5_TX,,, PortB,PB4,SPI1_MISO,,TIM3_CH1,TSC_G5_IO2,TIM22_CH1,USART1_CTS,USART5_RX,I2C3_SDA,, PortB,PB5,SPI1_MOSI,,LPTIM1_IN1,I2C1_SMBA,TIM3_CH2/TIM22_CH2,USART1_CK,USART5_CK/USART5_RTS_DE,,, PortB,PB6,USART1_TX,I2C1_SCL,LPTIM1_ETR,TSC_G5_IO3,,,,,, PortB,PB7,USART1_RX,I2C1_SDA,LPTIM1_IN2,TSC_G5_IO4,,,USART4_CTS,,, PortB,PB8,,,,TSC_SYNC,I2C1_SCL,,,,, PortB,PB9,,,EVENTOUT,,I2C1_SDA,SPI2_NSS/I2S2_WS,,,, PortB,PB10,,,TIM2_CH3,TSC_SYNC,LPUART1_TX,SPI2_SCK,I2C2_SCL,LPUART1_RX,, PortB,PB11,EVENTOUT,,TIM2_CH4,TSC_G6_IO1,LPUART1_RX,,I2C2_SDA,LPUART1_TX,, PortB,PB12,SPI2_NSS/I2S2_WS,,LPUART1_RTS_DE,TSC_G6_IO2,I2C2_SMBA,,EVENTOUT,,, PortB,PB13,SPI2_SCK/I2S2_CK,,MCO,TSC_G6_IO3,LPUART1_CTS,I2C2_SCL,TIM21_CH1,,, PortB,PB14,SPI2_MISO/I2S2_MCK,,RTC_OUT,TSC_G6_IO4,LPUART1_RTS_DE,I2C2_SDA,TIM21_CH2,,, PortB,PB15,SPI2_MOSI/I2S2_SD,,RTC_REFIN,,,,,,, PortC,PC0,LPTIM1_IN1,,EVENTOUT,TSC_G7_IO1,,,LPUART1_RX,I2C3_SCL,,ADC_IN10 PortC,PC1,LPTIM1_OUT,,EVENTOUT,TSC_G7_IO2,,,LPUART1_TX,I2C3_SDA,,ADC_IN11 PortC,PC2,LPTIM1_IN2,,SPI2_MISO/I2S2_MCK,TSC_G7_IO3,,,,,,ADC_IN12 PortC,PC3,LPTIM1_ETR,,SPI2_MOSI/I2S2_SD,TSC_G7_IO4,,,,,,ADC_IN13 PortC,PC4,EVENTOUT,,LPUART1_TX,,,,,,,ADC_IN14 PortC,PC5,LPUART1_RX,,TSC_G3_IO1,,,,,,,ADC_IN15 PortC,PC6,TIM22_CH1,,TIM3_CH1,TSC_G8_IO1,,,,,, PortC,PC7,TIM22_CH2,,TIM3_CH2,TSC_G8_IO2,,,,,, PortC,PC8,TIM22_ETR,,TIM3_CH3,TSC_G8_IO3,,,,,, PortC,PC9,TIM21_ETR,,USB_NOE/TIM3_CH4,TSC_G8_IO4,,,,I2C3_SDA,, PortC,PC10,LPUART1_TX,,,,,,USART4_TX,,, PortC,PC11,LPUART1_RX,,,,,,USART4_RX,,, PortC,PC12,,,USART5_TX,,,,USART4_CK,,, PortC,PC13,,,,,,,,,, PortC,PC14,,,,,,,,,, PortC,PC15,,,,,,,,,, PortD,PD0,TIM21_CH1,SPI2_NSS/I2S2_WS,,,,,,,, PortD,PD1,,SPI2_SCK/I2S2_CK,,,,,,,, PortD,PD2,LPUART1_RTS_DE,,TIM3_ETR,,,,USART5_RX,,, PortD,PD3,USART2_CTS,,SPI2_MISO/I2S2_MCK,,,,,,, PortD,PD4,USART2_RTS_DE,SPI2_MOSI/I2S2_SD,,,,,,,, PortD,PD5,USART2_TX,,,,,,,,, PortD,PD6,USART2_RX,,,,,,,,, PortD,PD7,USART2_CK,TIM21_CH2,,,,,,,, PortD,PD8,LPUART1_TX,,,,,,,,, PortD,PD9,LPUART1_RX,,,,,,,,, PortD,PD10,,,,,,,,,, PortD,PD11,LPUART1_CTS,,,,,,,,, PortD,PD12,LPUART1_RTS_DE,,,,,,,,, PortD,PD13,,,,,,,,,, PortD,PD14,,,,,,,,,, PortD,PD15,USB_CRS_SYNC,,,,,,,,, PortE,PE0,,,EVENTOUT,,,,,,, PortE,PE1,,,EVENTOUT,,,,,,, PortE,PE2,,,TIM3_ETR,,,,,,, PortE,PE3,TIM22_CH1,,TIM3_CH1,,,,,,, PortE,PE4,TIM22_CH2,,TIM3_CH2,,,,,,, PortE,PE5,TIM21_CH1,,TIM3_CH3,,,,,,, PortE,PE6,TIM21_CH2,,TIM3_CH4,,,,,,, PortE,PE7,,,,,,,USART5_CK/USART5_RTS_DE,,, PortE,PE8,,,,,,,USART4_TX,,, PortE,PE9,TIM2_CH1,,TIM2_ETR,,,,USART4_RX,,, PortE,PE10,TIM2_CH2,,,,,,USART5_TX,,, PortE,PE11,TIM2_CH3,,,,,,USART5_RX,,, PortE,PE12,TIM2_CH4,,SPI1_NSS,,,,,,, PortE,PE13,,,SPI1_SCK,,,,,,, PortE,PE14,,,SPI1_MISO,,,,,,, PortE,PE15,,,SPI1_MOSI,,,,,,, PortH,PH0,USB_CRS_SYNC,,,,,,,,, PortH,PH1,,,,,,,,,, micropython-1.12/ports/stm32/boards/stm32l072xz.ld000066400000000000000000000013431357706137100216740ustar00rootroot00000000000000/* GNU linker script for STM32F072xZ */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 192K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 8K; _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); /* Define the top end of the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 4K; /* RAM extents for the main heap */ _heap_start = _ebss; _heap_end = _sstack; micropython-1.12/ports/stm32/boards/stm32l0xx_hal_conf_base.h000066400000000000000000000061611357706137100241770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32L0XX_HAL_CONF_BASE_H #define MICROPY_INCLUDED_STM32L0XX_HAL_CONF_BASE_H // Include various HAL modules for convenience #include "stm32l0xx_hal_dma.h" #include "stm32l0xx_hal_adc.h" #include "stm32l0xx_hal_cortex.h" #include "stm32l0xx_hal_crc.h" #include "stm32l0xx_hal_dac.h" #include "stm32l0xx_hal_flash.h" #include "stm32l0xx_hal_gpio.h" #include "stm32l0xx_hal_i2c.h" #include "stm32l0xx_hal_i2s.h" #include "stm32l0xx_hal_iwdg.h" #include "stm32l0xx_hal_pcd.h" #include "stm32l0xx_hal_pwr.h" #include "stm32l0xx_hal_rcc.h" #include "stm32l0xx_hal_rtc.h" #include "stm32l0xx_hal_spi.h" #include "stm32l0xx_hal_tim.h" #include "stm32l0xx_hal_uart.h" #include "stm32l0xx_hal_usart.h" #include "stm32l0xx_hal_wwdg.h" // Enable various HAL modules #define HAL_MODULE_ENABLED #define HAL_ADC_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED #define HAL_CRC_MODULE_ENABLED #define HAL_DAC_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED #define HAL_I2S_MODULE_ENABLED #define HAL_IWDG_MODULE_ENABLED #define HAL_PCD_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_RTC_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED #define HAL_WWDG_MODULE_ENABLED // Oscillator values in Hz #define HSI_VALUE (16000000) #define HSI48_VALUE (48000000) #define LSI_VALUE (37000) #define MSI_VALUE (2097152) // SysTick has the highest priority #define TICK_INT_PRIORITY (0x00) // Miscellaneous HAL settings #define PREFETCH_ENABLE 1 #define PREREAD_ENABLE 0 #define BUFFER_CACHE_DISABLE 0 #define USE_RTOS 0 #define USE_SPI_CRC 0 // HAL parameter assertions are disabled #define assert_param(expr) ((void)0) #endif // MICROPY_INCLUDED_STM32L0XX_HAL_CONF_BASE_H micropython-1.12/ports/stm32/boards/stm32l432.ld000066400000000000000000000022561357706137100213160ustar00rootroot00000000000000/* GNU linker script for STM32L432KC */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 230K /* sectors 0-114 */ FLASH_FS (r) : ORIGIN = 0x08060000, LENGTH = 26K /* sectors 115-127 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* SRAM1, 48K + SRAM2, 16K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM, or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _ram_fs_cache_end = _ram_end; _ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ _estack = _ram_fs_cache_start - _estack_reserve; _sstack = _estack - 10K; /* stack = 10K */ _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; /* bss + heap = 52K, tunable by adjusting stack size */ _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); micropython-1.12/ports/stm32/boards/stm32l432_af.csv000066400000000000000000000053241357706137100221570ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,,, ,,SYS_AF,TIM1/TIM2/LPTIM1,TIM1/TIM2,USART2,I2C1/I2C2/I2C3,SPI1/SPI2,SPI3,USART1/USART2/USART3,LPUART1,CAN1/TSC,USB/QUADSPI,,COMP1/COMP2/SWPMI1,SAI1,TIM2/TIM15/TIM16/LPTIM2,EVENTOUT,ADC,COMP,DAC PortA,PA0,,TIM2_CH1,,,,,,USART2_CTS,,,,,COMP1_OUT,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC1_IN5,COMP1_INM, PortA,PA1,,TIM2_CH2,,,I2C1_SMBA,SPI1_SCK,,USART2_RTS/USART2_DE,,,,,,,TIM15_CH1N,EVENTOUT,ADC1_IN6,COMP1_INP, PortA,PA2,,TIM2_CH3,,,,,,USART2_TX,LPUART1_TX,,QUADSPI_BK1_NCS,,COMP2_OUT,,TIM15_CH1,EVENTOUT,ADC1_IN7,COMP2_INM, PortA,PA3,,TIM2_CH4,,,,,,USART2_RX,LPUART1_RX,,QUADSPI_CLK,,,SAI1_MCLK_A,TIM15_CH2,EVENTOUT,ADC1_IN8,COMP2_INP, PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS,USART2_CK,,,,,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC1_IN9,COMP1_INM/COMP2_INM,DAC1_OUT1 PortA,PA5,,TIM2_CH1,TIM2_ETR,,,SPI1_SCK,,,,,,,,,LPTIM2_ETR,EVENTOUT,ADC1_IN10,COMP1_INM/COMP2_INM,DAC1_OUT2 PortA,PA6,,TIM1_BKIN,,,,SPI1_MISO,COMP1_OUT,USART3_CTS,,,QUADSPI_BK1_IO3,,TIM1_BKIN_COMP2,,TIM16_CH1,EVENTOUT,ADC1_IN11,, PortA,PA7,,TIM1_CH1N,,,I2C3_SCL,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,,COMP2_OUT,,,EVENTOUT,ADC1_IN12,, PortA,PA8,MCO,TIM1_CH1,,,,,,USART1_CK,,,,,SWPMI1_IO,SAI1_SCLK_A,LPTIM2_OUT,EVENTOUT,,, PortA,PA9,,TIM1_CH2,,,I2C1_SCL,,,USART1_TX,,,,,,SAI1_FS_A,TIM15_BKIN,EVENTOUT,,, PortA,PA10,,TIM1_CH3,,,I2C1_SDA,,,USART1_RX,,,USB_CRS_SYNC,,,SAI1_SD_A,,EVENTOUT,,, PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,SPI1_MISO,COMP1_OUT,USART1_CTS,,CAN1_RX,USB_DM,,TIM1_BKIN2_COMP1,,,EVENTOUT,,, PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS/USART1_DE,,CAN1_TX,USB_DP,,,,,EVENTOUT,,, PortA,PA13,JTMS/SWDIO,IR_OUT,,,,,,,,,USB_NOE,,SWPMI1_TX,,,EVENTOUT,,, PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,,SWPMI1_RX,SAI1_SD_B,,EVENTOUT,,, PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,USART2_RX,,SPI1_NSS,SPI3_NSS,USART3_RTS/USART3_DE,,TSC_G3_IO1,,,SWPMI1_SUSPEND,SAI1_FS_B,,EVENTOUT,,, PortB,PB0,,TIM1_CH2N,,,,SPI1_NSS,,USART3_CK,,,QUADSPI_BK1_IO1,,COMP1_OUT,SA1_EXTCLK,,EVENTOUT,ADC1_IN15,, PortB,PB1,,TIM1_CH3N,,,,,,USART3_RTS/USART3_DE,LPUART1_RTS/LPUART1_DE,,QUADSPI_BK1_IO0,,,,LPTIM2_IN1,EVENTOUT,ADC1_IN16,COMP1_INM, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK,USART1_RTS/USART1_DE,,,,,,SAI1_SCK_B,,EVENTOUT,,COMP2_INM, PortB,PB4,NJTRST,,,,I2C3_SDA,SPI1_MISO,SPI3_MISO,USART1_CTS,,TSC_G2_IO1,,,,SAI1_MCLK_B,,EVENTOUT,,COMP2_INP, PortB,PB5,,LPTIM1_IN1,,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI,USART1_CK,,TSC_G2_IO2,,,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT,,, PortB,PB6,,LPTIM1_ETR,,,I2C1_SCL,,,USART1_TX,,TSC_G2_IO3,,,,SAI1_FS_B,TIM16_CH1N,EVENTOUT,,COMP2_INP, PortB,PB7,,LPTIM1_IN2,,,I2C1_SDA,,,USART1_RX,,TSC_G2_IO4,,,,,,EVENTOUT,,COMP2_INM, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,,, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,,, PortH,PH3,,,,,,,,,,,,,,,,EVENTOUT,,,micropython-1.12/ports/stm32/boards/stm32l452_af.csv000066400000000000000000000162001357706137100221540ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,,, ,,SYS_AF,TIM1/TIM2/LPTIM1,I2C4/TIM1/TIM2/TIM3,I2C4/USART2/CAN1/TIM1,I2C1/I2C2/I2C3/I2C4,SPI1/SPI2/I2C4,SPI3/DFSDM/COMP1,USART1/USART2/USART3,UART4/LPUART1/CAN1,CAN1/TSC,CAN1/USB/QUADSPI,,SDMMC1/COMP1/COMP2,SAI1,TIM2/TIM15/TIM16/LPTIM2,EVENTOUT,ADC,COMP,DAC PortA,PA0,,TIM2_CH1,,,,,,USART2_CTS,UART4_TX,,,,COMP1_OUT,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC12_IN5,COMP1_INM, PortA,PA1,,TIM2_CH2,,,I2C1_SMBA,SPI1_SCK,,USART2_RTS/USART2_DE,UART4_RX,,,,,,TIM15_CH1N,EVENTOUT,ADC12_IN6,COMP1_INP, PortA,PA2,,TIM2_CH3,,,,,,USART2_TX,LPUART1_TX,,QUADSPI_BK1_NCS,,COMP2_OUT,,TIM15_CH1,EVENTOUT,ADC12_IN7,COMP2_INM, PortA,PA3,,TIM2_CH4,,,,,,USART2_RX,LPUART1_RX,,QUADSPI_CLK,,,SAI1_MCLK_A,TIM15_CH2,EVENTOUT,ADC12_IN8,COMP2_INP, PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS,USART2_CK,,,,,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC12_IN9,COMP1_INM/COMP2_INM,DAC1_OUT1 PortA,PA5,,TIM2_CH1,TIM2_ETR,,,SPI1_SCK,DFSDM1_CKOUT,,,,,,,,LPTIM2_ETR,EVENTOUT,ADC12_IN10,COMP1_INM/COMP2_INM, PortA,PA6,,TIM1_BKIN,TIM3_CH1,,,SPI1_MISO,COMP1_OUT,USART3_CTS,LPUART1_CTS,,QUADSPI_BK1_IO3,,TIM1_BKIN_COMP2,,TIM16_CH1,EVENTOUT,ADC12_IN11,, PortA,PA7,,TIM1_CH1N,TIM3_CH2,,I2C3_SCL,SPI1_MOSI,DFSDM1_DATIN0,,,,QUADSPI_BK1_IO2,,COMP2_OUT,,,EVENTOUT,ADC12_IN12,, PortA,PA8,MCO,TIM1_CH1,,,,,DFSDM1_CKIN1,USART1_CK,,,,,,SAI1_SCK_A,LPTIM2_OUT,EVENTOUT,,, PortA,PA9,,TIM1_CH2,,,I2C1_SCL,,DFSDM1_DATIN1,USART1_TX,,,,,,SAI1_FS_A,TIM15_BKIN,EVENTOUT,,, PortA,PA10,,TIM1_CH3,,,I2C1_SDA,,,USART1_RX,,,USBCRS_SYNC,,,SAI1_SD_A,,EVENTOUT,,, PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,SPI1_MISO,COMP1_OUT,USART1_CTS,,CAN1_RX,USBDM,,TIM1_BKIN2_COMP1,,,EVENTOUT,,, PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS/USART1_DE,,CAN1_TX,USBDP,,,,,EVENTOUT,,, PortA,PA13,JTMS/SWDIO,IR_OUT,,,,,,,,,USBNOE,,,SAI1_SD_B,,EVENTOUT,,, PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,I2C4_SMBA,,,,,,,,SAI1_FS_B,,EVENTOUT,,, PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,USART2_RX,,SPI1_NSS,SPI3_NSS,USART3_RTS/USART3_DE,UART4_RTS/UART4_DE,TSC_G3_IO1,,,,,,EVENTOUT,,, PortB,PB0,,TIM1_CH2N,TIM3_CH3,,,SPI1_NSS,DFSDM1_CKIN0,USART3_CK,,,QUADSPI_BK1_IO1,,COMP1_OUT,SAI1_EXTCLK,,EVENTOUT,ADC12_IN15,, PortB,PB1,,TIM1_CH3N,TIM3_CH4,,,,DFSDM_DATIN0,USART3_RTS/USART3_DE,LPUART1_RTS/LPUART1_DE,,QUADSPI_BK1_IO0,,,,LPTIM2_IN1,EVENTOUT,ADC12_IN16,COMP1_INN, PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,,DFSDM_CKIN0,,,,,,,,,EVENTOUT,,COMP1_INP, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK,USART1_RTS/USART1_DE,,,,,,SAI1_SCK_B,,EVENTOUT,,COMP2_INM, PortB,PB4,NJTRST,,TIM3_CH1,,I2C3_SDA,SPI1_MISO,SPI3_MISO,USART1_CTS,,TSC_G2_IO1,,,,SAI1_MCLK_B,,EVENTOUT,,COMP2_INP, PortB,PB5,,LPTIM1_IN1,TIM3_CH2,CAN1_RX,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI,USART1_CK,,TSC_G2_IO2,,,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT,,, PortB,PB6,,LPTIM1_ETR,,,I2C1_SCL,I2C4_SCL,,USART1_TX,CAN1_TX,TSC_G2_IO3,,,,SAI1_FS_B,TIM16_CH1N,EVENTOUT,,COMP2_INP, PortB,PB7,,LPTIM1_IN2,,,I2C1_SDA,I2C4_SDA,,USART1_RX,UART4_CTS,TSC_G2_IO4,,,,,,EVENTOUT,,COMP2_INM, PortB,PB8,,,,,I2C1_SCL,,,,,CAN1_RX,,,SDMMC1_D4,SAI1_MCLK_A,TIM16_CH1,EVENTOUT,,, PortB,PB9,,IR_OUT,,,I2C1_SDA,SPI2_NSS,,,,CAN1_TX,,,SDMMC1_D5,SAI1_FS_A,,EVENTOUT,,, PortB,PB10,,TIM2_CH3,,I2C4_SCL,I2C2_SCL,SPI2_SCK,,USART3_TX,LPUART1_RX,TSC_SYNC,QUADSPI_CLK,,COMP1_OUT,SAI1_SCK_A,,EVENTOUT,,, PortB,PB11,,TIM2_CH4,,I2C4_SDA,I2C2_SDA,,,USART3_RX,LPUART1_TX,,QUADSPI_NCS,,COMP2_OUT,,,EVENTOUT,,, PortB,PB12,,TIM1_BKIN,,TIM1_BKIN_COMP2,I2C2_SMBA,SPI2_NSS,DFSDM_DATIN1,USART3_CK,LPUART1_RTS/LPUART1_DE,TSC_G1_IO1,CAN1_RX,,,SAI1_FS_A,TIM15_BKIN,EVENTOUT,,, PortB,PB13,,TIM1_CH1N,,,I2C2_SCL,SPI2_SCK,DFSDM_CKIN1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,CAN1_TX,,,SAI1_SCK_A,TIM15_CH1N,EVENTOUT,,, PortB,PB14,,TIM1_CH2N,,,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS_DE,,TSC_G1_IO3,,,,SAI1_MCLK_A,TIM15_CH1,EVENTOUT,,, PortB,PB15,RTC_REFIN,TIM1_CH3N,,,,SPI2_MOSI,DFSDM_CKIN2,,,TSC_G1_IO4,,,,SAI1_SD_A,TIM15_CH2,EVENTOUT,,, PortC,PC0,,LPTIM1_IN1,I2C4_SCL,,I2C3_SCL,,,,LPUART1_RX,,,,,,LPTIM2_IN1,EVENTOUT,ADC123_IN1,, PortC,PC1,TRACED0,LPTIM1_OUT,I2C4_SDA,,I2C3_SDA,,,,LPUART1_TX,,,,,,,EVENTOUT,ADC123_IN2,, PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,DFSDM_CKOUT,,,,,,,,,EVENTOUT,ADC123_IN3,, PortC,PC3,,LPTIM1_ETR,,,,SPI2_MOSI,,,,,,,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC123_IN4,, PortC,PC4,,,,,,,,USART3_TX,,,,,,,,EVENTOUT,ADC12_IN13,COMP1_INM, PortC,PC5,,,,,,,,USART3_RX,,,,,,,,EVENTOUT,ADC12_IN14,COMP1_INP, PortC,PC6,,,TIM3_CH1,,,,DFSDM_CKIN3,,,TSC_G4_IO1,,,SDMMC1_D6,,,EVENTOUT,,, PortC,PC7,,,TIM3_CH2,,,,DFSDM_DATIN3,,,TSC_G4_IO2,,,SDMMC1_D7,,,EVENTOUT,,, PortC,PC8,,,TIM3_CH3,,,,,,,TSC_G4_IO3,,,SDMMC1_D0,,,EVENTOUT,,, PortC,PC9,,,TIM3_CH4,,,,,,,TSC_G4_IO4,USBNOE,,SDMMC1_D1,,,EVENTOUT,,, PortC,PC10,TRACED1,,,,,,SPI3_SCK,USART3_TX,UART4_TX,TSC_G3_IO2,,,SDMMC1_D2,,,EVENTOUT,,, PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,TSC_G3_IO3,,,SDMMC1_D3,,,EVENTOUT,,, PortC,PC12,TRACED3,,,,,,SPI3_MOSI,USART3_CK,,TSC_G3_IO4,,,SDMMC1_CK,,,EVENTOUT,,, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,,, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,,, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,,, PortD,PD0,,,,,,SPI2_NSS,,,,CAN1_RX,,,,,,EVENTOUT,,, PortD,PD1,,,,,,SPI2_SCK,,,,CAN1_TX,,,,,,EVENTOUT,,, PortD,PD2,TRACED2,,TIM3_ETR,,,,,USART3_RTS/USART3_DE,,TSC_SYNC,,,SDMMC1_CMD,,,EVENTOUT,,, PortD,PD3,,,,,,SPI2_MISO,DFSDM_DATIN0,USART2_CTS,,,QUADSPI_BK2_NCS,,,,,EVENTOUT,,, PortD,PD4,,,,,,SPI2_MOSI,DFSDM_CKIN0,USART2_RTS/USART2_DE,,,QUADSPI_BK2_IO0,,,,,EVENTOUT,,, PortD,PD5,,,,,,,,USART2_TX,,,QUADSPI_BK2_IO1,,,,,EVENTOUT,,, PortD,PD6,,,,,,,DFSDM_DATIN1,USART2_RX,,,QUADSPI_BK2_IO2,,,SAI1_SD_A,,EVENTOUT,,, PortD,PD7,,,,,,,DFSDM_CKIN1,USART2_CK,,,QUADSPI_BK2_IO3,,,,,EVENTOUT,,, PortD,PD8,,,,,,,,USART3_TX,,,,,,,,EVENTOUT,,, PortD,PD9,,,,,,,,USART3_RX,,,,,,,,EVENTOUT,,, PortD,PD10,,,,,,,,USART3_CK,,TSC_G6_IO1,,,,,,EVENTOUT,,, PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,TSC_G6_IO2,,,,,LPTIM2_ETR,EVENTOUT,,, PortD,PD12,,,,,I2C4_SCL,,,USART3_RTS/USART3_DE,,TSC_G6_IO3,,,,,LPTIM2_IN1,EVENTOUT,,, PortD,PD13,,,,,I2C4_SDA,,,,,TSC_G6_IO4,,,,,LPTIM2_OUT,EVENTOUT,,, PortD,PD14,,,,,,,,,,,,,,,,EVENTOUT,,, PortD,PD15,,,,,,,,,,,,,,,,EVENTOUT,,, PortE,PE0,,,,,,,,,,,,,,,TIM16_CH1,EVENTOUT,,, PortE,PE1,,,,,,,,,,,,,,,,EVENTOUT,,, PortE,PE2,TRACECLK,,TIM3_ETR,,,,,,,TSC_G7_IO1,,,,SAI1_MCLK_A,,EVENTOUT,,, PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,TSC_G7_IO2,,,,SAI1_SD_B,,EVENTOUT,,, PortE,PE4,TRACED1,,TIM3_CH2,,,,DFSDM_DATIN3,,,TSC_G7_IO3,,,,SAI1_FS_A,,EVENTOUT,,, PortE,PE5,TRACED2,,TIM3_CH3,,,,DFSDM_CKIN3,,,TSC_G7_IO4,,,,SAI1_SCK_A,,EVENTOUT,,, PortE,PE6,TRACED3,,TIM3_CH4,,,,,,,,,,,SAI1_SD_A,,EVENTOUT,,, PortE,PE7,,TIM1_ETR,,,,,DFSDM_DATIN2,,,,,,,SAI1_SD_B,,EVENTOUT,,, PortE,PE8,,TIM1_CH1N,,,,,DFSDM_CKIN2,,,,,,,SAI1_SCK_B,,EVENTOUT,,, PortE,PE9,,TIM1_CH1,,,,,DFSDM_CKOUT,,,,,,,SAI1_FS_B,,EVENTOUT,,, PortE,PE10,,TIM1_CH2N,,,,,,,,TSC_G5_IO1,QUADSPI_CLK,,,SAI1_MCLK_B,,EVENTOUT,,, PortE,PE11,,TIM1_CH2,,,,,,,,TSC_G5_IO2,QUADSPI_BK1_NCS,,,,,EVENTOUT,,, PortE,PE12,,TIM1_CH3N,,,,SPI1_NSS,,,,TSC_G5_IO3,QUADSPI_BK1_IO0,,,,,EVENTOUT,,, PortE,PE13,,TIM1_CH3,,,,SPI1_SCK,,,,TSC_G5_IO4,QUADSPI_BK1_IO1,,,,,EVENTOUT,,, PortE,PE14,,TIM1_CH4,TIM1_BKIN2,TIM1_BKIN2_COMP2,,SPI1_MISO,,,,,QUADSPI_BK1_IO2,,,,,EVENTOUT,,, PortE,PE15,,TIM1_BKIN,,TIM1_BKIN_COMP1,,SPI1_MOSI,,,,,QUADSPI_BK1_IO3,,,,,EVENTOUT,,, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT,,, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT,,, PortH,PH3,,,,,,,,,,,,,,,,,,, micropython-1.12/ports/stm32/boards/stm32l452xe.ld000066400000000000000000000022621357706137100216520ustar00rootroot00000000000000/* GNU linker script for STM32L452XE */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K /* sectors 0-191 */ FLASH_FS (r) : ORIGIN = 0x08060000, LENGTH = 128K /* sectors 192-255 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 160K /* SRAM1, 128K + SRAM2, 32K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM, or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _ram_fs_cache_end = _ram_end; _ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ _estack = _ram_fs_cache_start - _estack_reserve; _sstack = _estack - 16K; /* stack = 16K */ _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; /* bss + heap = 142K, tunable by adjusting stack size */ _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); micropython-1.12/ports/stm32/boards/stm32l476_af.csv000066400000000000000000000232671357706137100221750ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,, ,,SYS_AF,TIM1/TIM2/TIM5/TIM8/LPTIM1,TIM1/TIM2/TIM3/TIM4/TIM5,TIM8,I2C1/I2C2/I2C3,SPI1/SPI2,SPI3/DFSDM,USART1/USART2/USART3,UART4/UART5/LPUART1,CAN1/TSC,OTG_FS/QUADSPI,LCD,SDMMC1/COMP1/COMP2/FMC/SWPMI1,SAI1/SAI2,TIM2/TIM15/TIM16/TIM17/LPTIM2,EVENTOUT,ADC,COMP PortA,PA0,,TIM2_CH1,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,,,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC12_IN5, PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS/USART2_DE,UART4_RX,,,LCD_SEG0,,,TIM15_CH1N,EVENTOUT,ADC12_IN6, PortA,PA2,,TIM2_CH3,TIM5_CH3,,,,,USART2_TX,,,,LCD_SEG1,,SAI2_EXTCLK,TIM15_CH1,EVENTOUT,ADC12_IN7, PortA,PA3,,TIM2_CH4,TIM5_CH4,,,,,USART2_RX,,,,LCD_SEG2,,,TIM15_CH2,EVENTOUT,ADC12_IN8, PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS,USART2_CK,,,,,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC12_IN9, PortA,PA5,,TIM2_CH1,TIM2_ETR,TIM8_CH1N,,SPI1_SCK,,,,,,,,,LPTIM2_ETR,EVENTOUT,ADC12_IN10, PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,USART3_CTS,,,QUADSPI_BK1_IO3,LCD_SEG3,TIM1_BKIN_COMP2,TIM8_BKIN_COMP2,TIM16_CH1,EVENTOUT,ADC12_IN11, PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,LCD_SEG4,,,TIM17_CH1,EVENTOUT,ADC12_IN12, PortA,PA8,MCO,TIM1_CH1,,,,,,USART1_CK,,,OTG_FS_SOF,LCD_COM0,,,LPTIM2_OUT,EVENTOUT,, PortA,PA9,,TIM1_CH2,,,,,,USART1_TX,,,,LCD_COM1,,,TIM15_BKIN,EVENTOUT,, PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,LCD_COM2,,,TIM17_BKIN,EVENTOUT,, PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,TIM1_BKIN2_COMP1,,,EVENTOUT,, PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS/USART1_DE,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT,, PortA,PA13,JTMS/SWDIO,IR_OUT,,,,,,,,,OTG_FS_NOE,,,,,EVENTOUT,, PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT,, PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,,,SPI1_NSS,SPI3_NSS,,UART4_RTS/UART4_DE,TSC_G3_IO1,,LCD_SEG17,,SAI2_FS_B,,EVENTOUT,, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,USART3_CK,,,QUADSPI_BK1_IO1,LCD_SEG5,COMP1_OUT,,,EVENTOUT,ADC12_IN15, PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,DFSDM_DATIN0,USART3_RTS/USART3_DE,,,QUADSPI_BK1_IO0,LCD_SEG6,,,LPTIM2_IN1,EVENTOUT,ADC12_IN16,COMP1_INN PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,,DFSDM_CKIN0,,,,,,,,,EVENTOUT,,COMP1_INP PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK,USART1_RTS/USART1_DE,,,,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT,,COMP2_INM PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,USART1_CTS,UART5_RTS/UART5_DE,TSC_G2_IO1,,LCD_SEG8,,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT,,COMP2_INP PortB,PB5,,LPTIM1_IN1,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI,USART1_CK,UART5_CTS,TSC_G2_IO2,,LCD_SEG9,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT,, PortB,PB6,,LPTIM1_ETR,TIM4_CH1,TIM8_BKIN2,I2C1_SCL,,DFSDM_DATIN5,USART1_TX,,TSC_G2_IO3,,,TIM8_BKIN2_COMP2,SAI1_FS_B,TIM16_CH1N,EVENTOUT,,COMP2_INP PortB,PB7,,LPTIM1_IN2,TIM4_CH2,TIM8_BKIN,I2C1_SDA,,DFSDM_CKIN5,USART1_RX,UART4_CTS,TSC_G2_IO4,,LCD_SEG21,FMC_NL,TIM8_BKIN_COMP1,TIM17_CH1N,EVENTOUT,,COMP2_INM PortB,PB8,,,TIM4_CH3,,I2C1_SCL,,DFSDM_DATIN6,,,CAN1_RX,,LCD_SEG16,SDMMC1_D4,SAI1_MCLK_A,TIM16_CH1,EVENTOUT,, PortB,PB9,,IR_OUT,TIM4_CH4,,I2C1_SDA,SPI2_NSS,DFSDM_CKIN6,,,CAN1_TX,,LCD_COM3,SDMMC1_D5,SAI1_FS_A,TIM17_CH1,EVENTOUT,, PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK,DFSDM_DATIN7,USART3_TX,LPUART1_RX,,QUADSPI_CLK,LCD_SEG10,COMP1_OUT,SAI1_SCK_A,,EVENTOUT,, PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,DFSDM_CKIN7,USART3_RX,LPUART1_TX,,QUADSPI_NCS,LCD_SEG11,COMP2_OUT,,,EVENTOUT,, PortB,PB12,,TIM1_BKIN,,TIM1_BKIN_COMP2,I2C2_SMBA,SPI2_NSS,DFSDM_DATIN1,USART3_CK,LPUART1_RTS/LPUART1_DE,TSC_G1_IO1,,LCD_SEG12,SWPMI1_IO,SAI2_FS_A,TIM15_BKIN,EVENTOUT,, PortB,PB13,,TIM1_CH1N,,,I2C2_SCL,SPI2_SCK,DFSDM_CKIN1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,,LCD_SEG13,SWPMI1_TX,SAI2_SCK_A,TIM15_CH1N,EVENTOUT,, PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS_DE,,TSC_G1_IO3,,LCD_SEG14,SWPMI1_RX,SAI2_MCLK_A,TIM15_CH1,EVENTOUT,, PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI,DFSDM_CKIN2,,,TSC_G1_IO4,,LCD_SEG15,SWPMI1_SUSPEND,SAI2_SD_A,TIM15_CH2,EVENTOUT,, PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,DFSDM_DATIN4,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT,ADC123_IN1, PortC,PC1,,LPTIM1_OUT,,,I2C3_SDA,,DFSDM_CKIN4,,LPUART1_TX,,,LCD_SEG19,,,,EVENTOUT,ADC123_IN2, PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,DFSDM_CKOUT,,,,,LCD_SEG20,,,,EVENTOUT,ADC123_IN3, PortC,PC3,,LPTIM1_ETR,,,,SPI2_MOSI,,,,,,LCD_VLCD,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC123_IN4, PortC,PC4,,,,,,,,USART3_TX,,,,LCD_SEG22,,,,EVENTOUT,ADC12_IN13,COMP1_INM PortC,PC5,,,,,,,,USART3_RX,,,,LCD_SEG23,,,,EVENTOUT,ADC12_IN14,COMP1_INP PortC,PC6,,,TIM3_CH1,TIM8_CH1,,,DFSDM_CKIN3,,,TSC_G4_IO1,,LCD_SEG24,SDMMC1_D6,SAI2_MCLK_A,,EVENTOUT,, PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,DFSDM_DATIN3,,,TSC_G4_IO2,,LCD_SEG25,SDMMC1_D7,SAI2_MCLK_B,,EVENTOUT,, PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,,TSC_G4_IO3,,LCD_SEG26,SDMMC1_D0,,,EVENTOUT,, PortC,PC9,,TIM8_BKIN2,TIM3_CH4,TIM8_CH4,,,,,,TSC_G4_IO4,OTG_FS_NOE,LCD_SEG27,SDMMC1_D1,SAI2_EXTCLK,TIM8_BKIN2_COMP1,EVENTOUT,, PortC,PC10,,,,,,,SPI3_SCK,USART3_TX,UART4_TX,TSC_G3_IO2,,LCD_COM4/LCD_SEG28/LCD_SEG40,SDMMC1_D2,SAI2_SCK_B,,EVENTOUT,, PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,TSC_G3_IO3,,LCD_COM5/LCD_SEG29/LCD_SEG41,SDMMC1_D3,SAI2_MCLK_B,,EVENTOUT,, PortC,PC12,,,,,,,SPI3_MOSI,USART3_CK,UART5_TX,TSC_G3_IO4,,LCD_COM6/LCD_SEG30/LCD_SEG42,SDMMC1_CK,SAI2_SD_B,,EVENTOUT,, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,, PortD,PD0,,,,,,SPI2_NSS,DFSDM_DATIN7,,,CAN1_RX,,,FMC_D2,,,EVENTOUT,, PortD,PD1,,,,,,SPI2_SCK,DFSDM_CKIN7,,,CAN1_TX,,,FMC_D3,,,EVENTOUT,, PortD,PD2,,,TIM3_ETR,,,,,USART3_RTS/USART3_DE,UART5_RX,TSC_SYNC,,LCD_COM7/LCD_SEG31/LCD_SEG43,SDMMC1_CMD,,,EVENTOUT,, PortD,PD3,,,,,,SPI2_MISO,DFSDM_DATIN0,USART2_CTS,,,,,FMC_CLK,,,EVENTOUT,, PortD,PD4,,,,,,SPI2_MOSI,DFSDM_CKIN0,USART2_RTS/USART2_DE,,,,,FMC_NOE,,,EVENTOUT,, PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT,, PortD,PD6,,,,,,,DFSDM_DATIN1,USART2_RX,,,,,FMC_NWAIT,SAI1_SD_A,,EVENTOUT,, PortD,PD7,,,,,,,DFSDM_CKIN1,USART2_CK,,,,,FMC_NE1,,,EVENTOUT,, PortD,PD8,,,,,,,,USART3_TX,,,,LCD_SEG28,FMC_D13,,,EVENTOUT,, PortD,PD9,,,,,,,,USART3_RX,,,,LCD_SEG29,FMC_D14,SAI2_MCLK_A,,EVENTOUT,, PortD,PD10,,,,,,,,USART3_CK,,TSC_G6_IO1,,LCD_SEG30,FMC_D15,SAI2_SCK_A,,EVENTOUT,, PortD,PD11,,,,,,,,USART3_CTS,,TSC_G6_IO2,,LCD_SEG31,FMC_A16,SAI2_SD_A,LPTIM2_ETR,EVENTOUT,, PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS/USART3_DE,,TSC_G6_IO3,,LCD_SEG32,FMC_A17,SAI2_FS_A,LPTIM2_IN1,EVENTOUT,, PortD,PD13,,,TIM4_CH2,,,,,,,TSC_G6_IO4,,LCD_SEG33,FMC_A18,,LPTIM2_OUT,EVENTOUT,, PortD,PD14,,,TIM4_CH3,,,,,,,,,LCD_SEG34,FMC_D0,,,EVENTOUT,, PortD,PD15,,,TIM4_CH4,,,,,,,,,LCD_SEG35,FMC_D1,,,EVENTOUT,, PortE,PE0,,,TIM4_ETR,,,,,,,,,LCD_SEG36,FMC_NBL0,,TIM16_CH1,EVENTOUT,, PortE,PE1,,,,,,,,,,,,LCD_SEG37,FMC_NBL1,,TIM17_CH1,EVENTOUT,, PortE,PE2,TRACECLK,,TIM3_ETR,,,,,,,TSC_G7_IO1,,LCD_SEG38,FMC_A23,SAI1_MCLK_A,,EVENTOUT,, PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,TSC_G7_IO2,,LCD_SEG39,FMC_A19,SAI1_SD_B,,EVENTOUT,, PortE,PE4,TRACED1,,TIM3_CH2,,,,DFSDM_DATIN3,,,TSC_G7_IO3,,,FMC_A20,SAI1_FS_A,,EVENTOUT,, PortE,PE5,TRACED2,,TIM3_CH3,,,,DFSDM_CKIN3,,,TSC_G7_IO4,,,FMC_A21,SAI1_SCK_A,,EVENTOUT,, PortE,PE6,TRACED3,,TIM3_CH4,,,,,,,,,,FMC_A22,SAI1_SD_A,,EVENTOUT,, PortE,PE7,,TIM1_ETR,,,,,DFSDM_DATIN2,,,,,,FMC_D4,SAI1_SD_B,,EVENTOUT,, PortE,PE8,,TIM1_CH1N,,,,,DFSDM_CKIN2,,,,,,FMC_D5,SAI1_SCK_B,,EVENTOUT,, PortE,PE9,,TIM1_CH1,,,,,DFSDM_CKOUT,,,,,,FMC_D6,SAI1_FS_B,,EVENTOUT,, PortE,PE10,,TIM1_CH2N,,,,,DFSDM_DATIN4,,,TSC_G5_IO1,QUADSPI_CLK,,FMC_D7,SAI1_MCLK_B,,EVENTOUT,, PortE,PE11,,TIM1_CH2,,,,,DFSDM_CKIN4,,,TSC_G5_IO2,QUADSPI_NCS,,FMC_D8,,,EVENTOUT,, PortE,PE12,,TIM1_CH3N,,,,SPI1_NSS,DFSDM_DATIN5,,,TSC_G5_IO3,QUADSPI_BK1_IO0,,FMC_D9,,,EVENTOUT,, PortE,PE13,,TIM1_CH3,,,,SPI1_SCK,DFSDM_CKIN5,,,TSC_G5_IO4,QUADSPI_BK1_IO1,,FMC_D10,,,EVENTOUT,, PortE,PE14,,TIM1_CH4,TIM1_BKIN2,TIM1_BKIN2_COMP2,,SPI1_MISO,,,,,QUADSPI_BK1_IO2,,FMC_D11,,,EVENTOUT,, PortE,PE15,,TIM1_BKIN,,TIM1_BKIN_COMP1,,SPI1_MOSI,,,,,QUADSPI_BK1_IO3,,FMC_D12,,,EVENTOUT,, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT,, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT,, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT,, PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN6, PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN7, PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN8, PortF,PF6,,TIM5_ETR,TIM5_CH1,,,,,,,,,,,SAI1_SD_B,,EVENTOUT,ADC3_IN9, PortF,PF7,,,TIM5_CH2,,,,,,,,,,,SAI1_MCLK_B,,EVENTOUT,ADC3_IN10, PortF,PF8,,,TIM5_CH3,,,,,,,,,,,SAI1_SCK_B,,EVENTOUT,ADC3_IN11, PortF,PF9,,,TIM5_CH4,,,,,,,,,,,SAI1_FS_B,TIM15_CH1,EVENTOUT,ADC3_IN12, PortF,PF10,,,,,,,,,,,,,,,TIM15_CH2,EVENTOUT,ADC3_IN13, PortF,PF11,,,,,,,,,,,,,,,,EVENTOUT,, PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT,, PortF,PF13,,,,,,,DFSDM_DATIN6,,,,,,FMC_A7,,,EVENTOUT,, PortF,PF14,,,,,,,DFSDM_CKIN6,,,TSC_G8_IO1,,,FMC_A8,,,EVENTOUT,, PortF,PF15,,,,,,,,,,TSC_G8_IO2,,,FMC_A9,,,EVENTOUT,, PortG,PG0,,,,,,,,,,TSC_G8_IO3,,,FMC_A10,,,EVENTOUT,, PortG,PG1,,,,,,,,,,TSC_G8_IO4,,,FMC_A11,,,EVENTOUT,, PortG,PG2,,,,,,SPI1_SCK,,,,,,,FMC_A12,SAI2_SCK_B,,EVENTOUT,, PortG,PG3,,,,,,SPI1_MISO,,,,,,,FMC_A13,SAI2_FS_B,,EVENTOUT,, PortG,PG4,,,,,,SPI1_MOSI,,,,,,,FMC_A14,SAI2_MCLK_B,,EVENTOUT,, PortG,PG5,,,,,,SPI1_NSS,,,LPUART1_CTS,,,,FMC_A15,SAI2_SD_B,,EVENTOUT,, PortG,PG6,,,,,I2C3_SMBA,,,,LPUART1_RTS/LPUART1_DE,,,,,,,EVENTOUT,, PortG,PG7,,,,,I2C3_SCL,,,,LPUART1_TX,,,,FMC_INT3,,,EVENTOUT,, PortG,PG8,,,,,I2C3_SDA,,,,LPUART1_RX,,,,,,,EVENTOUT,, PortG,PG9,,,,,,,SPI3_SCK,USART1_TX,,,,,FMC_NCE3/FMC_NE2,SAI2_SCK_A,TIM15_CH1N,EVENTOUT,, PortG,PG10,,LPTIM1_IN1,,,,,SPI3_MISO,USART1_RX,,,,,FMC_NE3,SAI2_FS_A,TIM15_CH1,EVENTOUT,, PortG,PG11,,LPTIM1_IN2,,,,,SPI3_MOSI,USART1_CTS,,,,,,SAI2_MCLK_A,TIM15_CH2,EVENTOUT,, PortG,PG12,,LPTIM1_ETR,,,,,SPI3_NSS,USART1_RTS/USART1_DE,,,,,FMC_NE4,SAI2_SD_A,,EVENTOUT,, PortG,PG13,,,,,I2C1_SDA,,,USART1_CK,,,,,FMC_A24,,,EVENTOUT,, PortG,PG14,,,,,I2C1_SCL,,,,,,,,FMC_A25,,,EVENTOUT,, PortG,PG15,,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,,,,,EVENTOUT,, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT,, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT,, micropython-1.12/ports/stm32/boards/stm32l476xe.ld000066400000000000000000000024521357706137100216610ustar00rootroot00000000000000/* GNU linker script for STM32L476XE */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K /* sectors 0-191 */ FLASH_FS (r) : ORIGIN = 0x08060000, LENGTH = 128K /* sectors 192-255 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 32K /* not contiguous with RAM */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM, or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _ram_fs_cache_end = ORIGIN(SRAM2) + LENGTH(SRAM2); /* fs_cache in SRAM2 */ _ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ _estack = _ram_fs_cache_start - _estack_reserve; /* stack in SRAM2 */ _sstack = ORIGIN(SRAM2); /* stack = 30K */ _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _ram_end; /* bss + heap = 96K, tunable by adjusting stack size */ _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); micropython-1.12/ports/stm32/boards/stm32l476xg.ld000066400000000000000000000024521357706137100216630ustar00rootroot00000000000000/* GNU linker script for STM32L476XG */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* sectors 0-255 */ FLASH_FS (r) : ORIGIN = 0x08080000, LENGTH = 512K /* sectors 256-511 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 32K /* not contiguous with RAM */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM, or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _ram_fs_cache_end = ORIGIN(SRAM2) + LENGTH(SRAM2); /* fs_cache in SRAM2 */ _ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ _estack = _ram_fs_cache_start - _estack_reserve; /* stack in SRAM2 */ _sstack = ORIGIN(SRAM2); /* stack = 30K */ _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _ram_end; /* bss + heap = 96K, tunable by adjusting stack size */ _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); micropython-1.12/ports/stm32/boards/stm32l496_af.csv000066400000000000000000000302671357706137100221750ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,,, ,,SYS_AF,TIM1/TIM2/TIM5/TIM8/LPTIM1,TIM1/TIM2/TIM3/TIM4/TIM5,TIM8,I2C1/I2C2/I2C3,SPI1/SPI2,SPI3/DFSDM,USART1/USART2/USART3,UART4/UART5/LPUART1,CAN1/TSC,OTG_FS/QUADSPI,LCD,SDMMC1/COMP1/COMP2/FMC/SWPMI1,SAI1/SAI2,TIM2/TIM15/TIM16/TIM17/LPTIM2,EVENTOUT,ADC,COMP,DAC PortA,PA0,,TIM2_CH1,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,,,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC12_IN5,, PortA,PA1,,TIM2_CH2,TIM5_CH2,,I2C1_SMBA,SPI1_SCK,,USART2_RTS/USART2_DE,UART4_RX,,,LCD_SEG0,,,TIM15_CH1N,EVENTOUT,ADC12_IN6,, PortA,PA2,,TIM2_CH3,TIM5_CH3,,,,,USART2_TX,LPUART1_TX,,QUADSPI_BK1_NCS,LCD_SEG1,,SAI2_EXTCLK,TIM15_CH1,EVENTOUT,ADC12_IN7,, PortA,PA3,,TIM2_CH4,TIM5_CH4,,,,,USART2_RX,LPUART1_RX,,QUADSPI_CLK,LCD_SEG2,,SAI1_MCLK_A,TIM15_CH2,EVENTOUT,ADC12_IN8,, PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS,USART2_CK,,,DCMI_HSYNC,,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC12_IN9,,DAC1_OUT1 PortA,PA5,,TIM2_CH1,TIM2_ETR,TIM8_CH1N,,SPI1_SCK,,,,,,,,,LPTIM2_ETR,EVENTOUT,ADC12_IN10,,DAC1_OUT2 PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,DCMI_PIXCLK,SPI1_MISO,,USART3_CTS,LPUART1_CTS,,QUADSPI_BK1_IO3,LCD_SEG3,TIM1_BKIN_COMP2,TIM8_BKIN_COMP2,TIM16_CH1,EVENTOUT,ADC12_IN11,, PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,I2C3_SCL,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,LCD_SEG4,,,TIM17_CH1,EVENTOUT,ADC12_IN12,, PortA,PA8,MCO,TIM1_CH1,,,,,,USART1_CK,,,OTG_FS_SOF,LCD_COM0,SWPMI1_IO,SAI1_SCK_A,LPTIM2_OUT,EVENTOUT,,, PortA,PA9,,TIM1_CH2,,SPI2_SCK,I2C1_SCL,DCMI_D0,,USART1_TX,,,,LCD_COM1,,SAI1_FS_A,TIM15_BKIN,EVENTOUT,,, PortA,PA10,,TIM1_CH3,,,I2C1_SDA,DCMI_D1,,USART1_RX,,,OTG_FS_ID,LCD_COM2,,SAI1_SD_A,TIM17_BKIN,EVENTOUT,,, PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,SPI1_MISO,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,TIM1_BKIN2_COMP1,,,EVENTOUT,,, PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS/USART1_DE,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT,,, PortA,PA13,JTMS/SWDIO,IR_OUT,,,,,,,,,OTG_FS_NOE,,SWPMI1_TX,SAI1_SD_B,,EVENTOUT,,, PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,I2C4_SMBA,,,,,OTG_FS_SOF,,SWPMI1_RX,SAI1_FS_B,,EVENTOUT,,, PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,USART2_RX,,SPI1_NSS,SPI3_NSS,USART3_RTS/USART3_DE,UART4_RTS/UART4_DE,TSC_G3_IO1,,LCD_SEG17,SWPMI1_SUSPEND,SAI2_FS_B,,EVENTOUT,,, PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,SPI1_NSS,,USART3_CK,,,QUADSPI_BK1_IO1,LCD_SEG5,COMP1_OUT,SAI1_EXTCLK,,EVENTOUT,ADC12_IN15,, PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,DFSDM1_DATIN0,USART3_RTS/USART3_DE,LPUART1_RTS/LPUART1_DE,,QUADSPI_BK1_IO0,LCD_SEG6,,,LPTIM2_IN1,EVENTOUT,ADC12_IN16,COMP1_INM, PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,,DFSDM1_CKIN0,,,,,LCD_VLCD,,,,EVENTOUT,,COMP1_INP, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK,USART1_RTS/USART1_DE,,,OTG_FS_CRS_SYNC,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT,,COMP2_INM, PortB,PB4,NJTRST,,TIM3_CH1,,I2C3_SDA,SPI1_MISO,SPI3_MISO,USART1_CTS,UART5_RTS/UART5_DE,TSC_G2_IO1,DCMI_D12,LCD_SEG8,,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT,,COMP2_INP, PortB,PB5,,LPTIM1_IN1,TIM3_CH2,CAN2_RX,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI,USART1_CK,UART5_CTS,TSC_G2_IO2,DCMI_D10,LCD_SEG9,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT,,, PortB,PB6,,LPTIM1_ETR,TIM4_CH1,TIM8_BKIN2,I2C1_SCL,I2C4_SCL,DFSDM1_DATIN5,USART1_TX,CAN2_TX,TSC_G2_IO3,DCMI_D5,,TIM8_BKIN2_COMP2,SAI1_FS_B,TIM16_CH1N,EVENTOUT,,COMP2_INP, PortB,PB7,,LPTIM1_IN2,TIM4_CH2,TIM8_BKIN,I2C1_SDA,I2C4_SDA,DFSDM1_CKIN5,USART1_RX,UART4_CTS,TSC_G2_IO4,DCMI_VSYNC,LCD_SEG21,FMC_NL,TIM8_BKIN_COMP1,TIM17_CH1N,EVENTOUT,,COMP2_INM, PortB,PB8,,,TIM4_CH3,,I2C1_SCL,,DFSDM1_DATIN6,,,CAN1_RX,DCMI_D6,LCD_SEG16,SDMMC1_D4,SAI1_MCLK_A,TIM16_CH1,EVENTOUT,,, PortB,PB9,,IR_OUT,TIM4_CH4,,I2C1_SDA,SPI2_NSS,DFSDM1_CKIN6,,,CAN1_TX,DCMI_D7,LCD_COM3,SDMMC1_D5,SAI1_FS_A,TIM17_CH1,EVENTOUT,,, PortB,PB10,,TIM2_CH3,,I2C4_SCL,I2C2_SCL,SPI2_SCK,DFSDM1_DATIN7,USART3_TX,LPUART1_RX,TSC_SYNC,QUADSPI_CLK,LCD_SEG10,COMP1_OUT,SAI1_SCK_A,,EVENTOUT,,, PortB,PB11,,TIM2_CH4,,I2C4_SDA,I2C2_SDA,,DFSDM1_CKIN7,USART3_RX,LPUART1_TX,,QUADSPI_BK1_NCS,LCD_SEG11,COMP2_OUT,,,EVENTOUT,,, PortB,PB12,,TIM1_BKIN,,TIM1_BKIN_COMP2,I2C2_SMBA,SPI2_NSS,DFSDM1_DATIN1,USART3_CK,LPUART1_RTS/LPUART1_DE,TSC_G1_IO1,CAN2_RX,LCD_SEG12,SWPMI1_IO,SAI2_FS_A,TIM15_BKIN,EVENTOUT,,, PortB,PB13,,TIM1_CH1N,,,I2C2_SCL,SPI2_SCK,DFSDM1_CKIN1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,CAN2_TX,LCD_SEG13,SWPMI1_TX,SAI2_SCK_A,TIM15_CH1N,EVENTOUT,,, PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,I2C2_SDA,SPI2_MISO,DFSDM1_DATIN2,USART3_RTS/USART3_DE,,TSC_G1_IO3,,LCD_SEG14,SWPMI1_RX,SAI2_MCLK_A,TIM15_CH1,EVENTOUT,,, PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI,DFSDM1_CKIN2,,,TSC_G1_IO4,,LCD_SEG15,SWPMI1_SUSPEND,SAI2_SD_A,TIM15_CH2,EVENTOUT,,, PortC,PC0,,LPTIM1_IN1,I2C4_SCL,,I2C3_SCL,,DFSDM1_DATIN4,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT,ADC123_IN1,, PortC,PC1,TRACED0,LPTIM1_OUT,I2C4_SDA,SPI2_MOSI,I2C3_SDA,,DFSDM1_CKIN4,,LPUART1_TX,,QUADSPI_BK2_IO0,LCD_SEG19,,SAI1_SD_A,,EVENTOUT,ADC123_IN2,, PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,DFSDM1_CKOUT,,,,QUADSPI_BK2_IO1,LCD_SEG20,,,,EVENTOUT,ADC123_IN3,, PortC,PC3,,LPTIM1_ETR,,,,SPI2_MOSI,,,,,QUADSPI_BK2_IO2,LCD_VLCD,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC123_IN4,, PortC,PC4,,,,,,,,USART3_TX,,,QUADSPI_BK2_IO3,LCD_SEG22,,,,EVENTOUT,ADC12_IN13,COMP1_INM, PortC,PC5,,,,,,,,USART3_RX,,,,LCD_SEG23,,,,EVENTOUT,ADC12_IN14,COMP1_INP, PortC,PC6,,,TIM3_CH1,TIM8_CH1,,,DFSDM1_CKIN3,,,TSC_G4_IO1,DCMI_D0,LCD_SEG24,SDMMC1_D6,SAI2_MCLK_A,,EVENTOUT,,, PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,DFSDM1_DATIN3,,,TSC_G4_IO2,DCMI_D1,LCD_SEG25,SDMMC1_D7,SAI2_MCLK_B,,EVENTOUT,,, PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,,TSC_G4_IO3,DCMI_D2,LCD_SEG26,SDMMC1_D0,,,EVENTOUT,,, PortC,PC9,,TIM8_BKIN2,TIM3_CH4,TIM8_CH4,DCMI_D3,,I2C3_SDA,,,TSC_G4_IO4,OTG_FS_NOE,LCD_SEG27,SDMMC1_D1,SAI2_EXTCLK,TIM8_BKIN2_COMP1,EVENTOUT,,, PortC,PC10,TRACED1,,,,,,SPI3_SCK,USART3_TX,UART4_TX,TSC_G3_IO2,DCMI_D8,LCD_COM4/LCD_SEG28/LCD_SEG40,SDMMC1_D2,SAI2_SCK_B,,EVENTOUT,,, PortC,PC11,,,,,,QUADSPI_BK2_NCS,SPI3_MISO,USART3_RX,UART4_RX,TSC_G3_IO3,DCMI_D4,LCD_COM5/LCD_SEG29/LCD_SEG41,SDMMC1_D3,SAI2_MCLK_B,,EVENTOUT,,, PortC,PC12,TRACED3,,,,,,SPI3_MOSI,USART3_CK,UART5_TX,TSC_G3_IO4,DCMI_D9,LCD_COM6/LCD_SEG30/LCD_SEG42,SDMMC1_CK,SAI2_SD_B,,EVENTOUT,,, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,,, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,,, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,,, PortD,PD0,,,,,,SPI2_NSS,DFSDM1_DATIN7,,,CAN1_RX,,,FMC_D2,,,EVENTOUT,,, PortD,PD1,,,,,,SPI2_SCK,DFSDM1_CKIN7,,,CAN1_TX,,,FMC_D3,,,EVENTOUT,,, PortD,PD2,TRACED2,,TIM3_ETR,,,,,USART3_RTS/USART3_DE,UART5_RX,TSC_SYNC,DCMI_D11,LCD_COM7/LCD_SEG31/LCD_SEG43,SDMMC1_CMD,,,EVENTOUT,,, PortD,PD3,,,,SPI2_SCK,DCMI_D5,SPI2_MISO,DFSDM1_DATIN0,USART2_CTS,,,QUADSPI_BK2_NCS,,FMC_CLK,,,EVENTOUT,,, PortD,PD4,,,,,,SPI2_MOSI,DFSDM1_CKIN0,USART2_RTS/USART2_DE,,,QUADSPI_BK2_IO0,,FMC_NOE,,,EVENTOUT,,, PortD,PD5,,,,,,,,USART2_TX,,,QUADSPI_BK2_IO1,,FMC_NWE,,,EVENTOUT,,, PortD,PD6,,,,,DCMI_D10,QUADSPI_BK2_IO1,DFSDM1_DATIN1,USART2_RX,,,QUADSPI_BK2_IO2,,FMC_NWAIT,SAI1_SD_A,,EVENTOUT,,, PortD,PD7,,,,,,,DFSDM1_CKIN1,USART2_CK,,,QUADSPI_BK2_IO3,,FMC_NE1,,,EVENTOUT,,, PortD,PD8,,,,,,,,USART3_TX,,,DCMI_HSYNC,LCD_SEG28,FMC_D13,,,EVENTOUT,,, PortD,PD9,,,,,,,,USART3_RX,,,DCMI_PIXCLK,LCD_SEG29,FMC_D14,SAI2_MCLK_A,,EVENTOUT,,, PortD,PD10,,,,,,,,USART3_CK,,TSC_G6_IO1,,LCD_SEG30,FMC_D15,SAI2_SCK_A,,EVENTOUT,,, PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,TSC_G6_IO2,,LCD_SEG31,FMC_A16,SAI2_SD_A,LPTIM2_ETR,EVENTOUT,,, PortD,PD12,,,TIM4_CH1,,I2C4_SCL,,,USART3_RTS/USART3_DE,,TSC_G6_IO3,,LCD_SEG32,FMC_A17,SAI2_FS_A,LPTIM2_IN1,EVENTOUT,,, PortD,PD13,,,TIM4_CH2,,I2C4_SDA,,,,,TSC_G6_IO4,,LCD_SEG33,FMC_A18,,LPTIM2_OUT,EVENTOUT,,, PortD,PD14,,,TIM4_CH3,,,,,,,,,LCD_SEG34,FMC_D0,,,EVENTOUT,,, PortD,PD15,,,TIM4_CH4,,,,,,,,,LCD_SEG35,FMC_D1,,,EVENTOUT,,, PortE,PE0,,,TIM4_ETR,,,,,,,,DCMI_D2,LCD_SEG36,FMC_NBL0,,TIM16_CH1,EVENTOUT,,, PortE,PE1,,,,,,,,,,,DCMI_D3,LCD_SEG37,FMC_NBL1,,TIM17_CH1,EVENTOUT,,, PortE,PE2,TRACECLK,,TIM3_ETR,,,,,,,TSC_G7_IO1,,LCD_SEG38,FMC_A23,SAI1_MCLK_A,,EVENTOUT,,, PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,TSC_G7_IO2,,LCD_SEG39,FMC_A19,SAI1_SD_B,,EVENTOUT,,, PortE,PE4,TRACED1,,TIM3_CH2,,,,DFSDM1_DATIN3,,,TSC_G7_IO3,DCMI_D4,,FMC_A20,SAI1_FS_A,,EVENTOUT,,, PortE,PE5,TRACED2,,TIM3_CH3,,,,DFSDM1_CKIN3,,,TSC_G7_IO4,DCMI_D6,,FMC_A21,SAI1_SCK_A,,EVENTOUT,,, PortE,PE6,TRACED3,,TIM3_CH4,,,,,,,,DCMI_D7,,FMC_A22,SAI1_SD_A,,EVENTOUT,,, PortE,PE7,,TIM1_ETR,,,,,DFSDM1_DATIN2,,,,,,FMC_D4,SAI1_SD_B,,EVENTOUT,,, PortE,PE8,,TIM1_CH1N,,,,,DFSDM1_CKIN2,,,,,,FMC_D5,SAI1_SCK_B,,EVENTOUT,,, PortE,PE9,,TIM1_CH1,,,,,DFSDM1_CKOUT,,,,,,FMC_D6,SAI1_FS_B,,EVENTOUT,,, PortE,PE10,,TIM1_CH2N,,,,,DFSDM1_DATIN4,,,TSC_G5_IO1,QUADSPI_CLK,,FMC_D7,SAI1_MCLK_B,,EVENTOUT,,, PortE,PE11,,TIM1_CH2,,,,,DFSDM1_CKIN4,,,TSC_G5_IO2,QUADSPI_BK1_NCS,,FMC_D8,,,EVENTOUT,,, PortE,PE12,,TIM1_CH3N,,,,SPI1_NSS,DFSDM1_DATIN5,,,TSC_G5_IO3,QUADSPI_BK1_IO0,,FMC_D9,,,EVENTOUT,,, PortE,PE13,,TIM1_CH3,,,,SPI1_SCK,DFSDM1_CKIN5,,,TSC_G5_IO4,QUADSPI_BK1_IO1,,FMC_D10,,,EVENTOUT,,, PortE,PE14,,TIM1_CH4,TIM1_BKIN2,TIM1_BKIN2_COMP2,,SPI1_MISO,,,,,QUADSPI_BK1_IO2,,FMC_D11,,,EVENTOUT,,, PortE,PE15,,TIM1_BKIN,,TIM1_BKIN_COMP1,,SPI1_MOSI,,,,,QUADSPI_BK1_IO3,,FMC_D12,,,EVENTOUT,,, PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT,,, PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT,,, PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT,,, PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN6,, PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN7,, PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN8,, PortF,PF6,,TIM5_ETR,TIM5_CH1,,,,,,,,QUADSPI_BK1_IO3,,,SAI1_SD_B,,EVENTOUT,ADC3_IN9,, PortF,PF7,,,TIM5_CH2,,,,,,,,QUADSPI_BK1_IO2,,,SAI1_MCLK_B,,EVENTOUT,ADC3_IN10,, PortF,PF8,,,TIM5_CH3,,,,,,,,QUADSPI_BK1_IO0,,,SAI1_SCK_B,,EVENTOUT,ADC3_IN11,, PortF,PF9,,,TIM5_CH4,,,,,,,,QUADSPI_BK1_IO1,,,SAI1_FS_B,TIM15_CH1,EVENTOUT,ADC3_IN12,, PortF,PF10,,,,QUADSPI_CLK,,,,,,,DCMI_D11,,,,TIM15_CH2,EVENTOUT,ADC3_IN13,, PortF,PF11,,,,,,,,,,,DCMI_D12,,,,,EVENTOUT,,, PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT,,, PortF,PF13,,,,,I2C4_SMBA,,DFSDM1_DATIN6,,,,,,FMC_A7,,,EVENTOUT,,, PortF,PF14,,,,,I2C4_SCL,,DFSDM1_CKIN6,,,TSC_G8_IO1,,,FMC_A8,,,EVENTOUT,,, PortF,PF15,,,,,I2C4_SDA,,,,,TSC_G8_IO2,,,FMC_A9,,,EVENTOUT,,, PortG,PG0,,,,,,,,,,TSC_G8_IO3,,,FMC_A10,,,EVENTOUT,,, PortG,PG1,,,,,,,,,,TSC_G8_IO4,,,FMC_A11,,,EVENTOUT,,, PortG,PG2,,,,,,SPI1_SCK,,,,,,,FMC_A12,SAI2_SCK_B,,EVENTOUT,,, PortG,PG3,,,,,,SPI1_MISO,,,,,,,FMC_A13,SAI2_FS_B,,EVENTOUT,,, PortG,PG4,,,,,,SPI1_MOSI,,,,,,,FMC_A14,SAI2_MCLK_B,,EVENTOUT,,, PortG,PG5,,,,,,SPI1_NSS,,,LPUART1_CTS,,,,FMC_A15,SAI2_SD_B,,EVENTOUT,,, PortG,PG6,,,,,I2C3_SMBA,,,,LPUART1_RTS/LPUART1_DE,,,,,,,EVENTOUT,,, PortG,PG7,,,,,I2C3_SCL,,,,LPUART1_TX,,,,FMC_INT,SAI1_MCLK_A,,EVENTOUT,,, PortG,PG8,,,,,I2C3_SDA,,,,LPUART1_RX,,,,,,,EVENTOUT,,, PortG,PG9,,,,,,,SPI3_SCK,USART1_TX,,,,,FMC_NCE/FMC_NE2,SAI2_SCK_A,TIM15_CH1N,EVENTOUT,,, PortG,PG10,,LPTIM1_IN1,,,,,SPI3_MISO,USART1_RX,,,,,FMC_NE3,SAI2_FS_A,TIM15_CH1,EVENTOUT,,, PortG,PG11,,LPTIM1_IN2,,,,,SPI3_MOSI,USART1_CTS,,,,,,SAI2_MCLK_A,TIM15_CH2,EVENTOUT,,, PortG,PG12,,LPTIM1_ETR,,,,,SPI3_NSS,USART1_RTS/USART1_DE,,,,,FMC_NE4,SAI2_SD_A,,EVENTOUT,,, PortG,PG13,,,,,I2C1_SDA,,,USART1_CK,,,,,FMC_A24,,,EVENTOUT,,, PortG,PG14,,,,,I2C1_SCL,,,,,,,,FMC_A25,,,EVENTOUT,,, PortG,PG15,,LPTIM1_OUT,,,I2C1_SMBA,,,,,,DCMI_D13,,,,,EVENTOUT,,, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT,,, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT,,, PortH,PH2,,,,QUADSPI_BK2_IO0,,,,,,,,,,,,EVENTOUT,,, PortH,PH3,,,,,,,,,,,,,,,,EVENTOUT,,, PortH,PH4,,,,,I2C2_SCL,,,,,,,,,,,EVENTOUT,,, PortH,PH5,,,,,I2C2_SDA,,,,,,DCMI_PIXCLK,,,,,EVENTOUT,,, PortH,PH6,,,,,I2C2_SMBA,,,,,,DCMI_D8,,,,,EVENTOUT,,, PortH,PH7,,,,,I2C3_SCL,,,,,,DCMI_D9,,,,,EVENTOUT,,, PortH,PH8,,,,,I2C3_SDA,,,,,,DCMI_HSYNC,,,,,EVENTOUT,,, PortH,PH9,,,,,I2C3_SMBA,,,,,,DCMI_D0,,,,,EVENTOUT,,, PortH,PH10,,,TIM5_CH1,,,,,,,,DCMI_D1,,,,,EVENTOUT,,, PortH,PH11,,,TIM5_CH2,,,,,,,,DCMI_D2,,,,,EVENTOUT,,, PortH,PH12,,,TIM5_CH3,,,,,,,,DCMI_D3,,,,,EVENTOUT,,, PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,,,,EVENTOUT,,, PortH,PH14,,,,TIM8_CH2N,,,,,,,DCMI_D4,,,,,EVENTOUT,,, PortH,PH15,,,,TIM8_CH3N,,,,,,,DCMI_D11,,,,,EVENTOUT,,, PortI,PI0,,,TIM5_CH4,,,SPI2_NSS,,,,,DCMI_D13,,,,,EVENTOUT,,, PortI,PI1,,,,,,SPI2_SCK,,,,,DCMI_D8,,,,,EVENTOUT,,, PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,,,,,DCMI_D9,,,,,EVENTOUT,,, PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI,,,,,DCMI_D10,,,,,EVENTOUT,,, PortI,PI4,,,,TIM8_BKIN,,,,,,,DCMI_D5,,,,,EVENTOUT,,, PortI,PI5,,,,TIM8_CH1,,,,,,,DCMI_VSYNC,,,,,EVENTOUT,,, PortI,PI6,,,,TIM8_CH2,,,,,,,DCMI_D6,,,,,EVENTOUT,,, PortI,PI7,,,,TIM8_CH3,,,,,,,DCMI_D7,,,,,EVENTOUT,,, PortI,PI8,,,,,,,,,,,DCMI_D12,,,,,EVENTOUT,,, PortI,PI9,,,,,,,,,,CAN1_RX,,,,,,EVENTOUT,,, PortI,PI10,,,,,,,,,,,,,,,,EVENTOUT,,, PortI,PI11,,,,,,,,,,,,,,,,EVENTOUT,,, micropython-1.12/ports/stm32/boards/stm32l496xg.ld000066400000000000000000000022721357706137100216650ustar00rootroot00000000000000/* GNU linker script for STM32L496XG */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 612K /* sectors 0-305 */ FLASH_FS (r) : ORIGIN = 0x08099000, LENGTH = 412K /* sectors 306-511 412 KiB */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K /* SRAM1, 256K + SRAM2, 64K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM, or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _ram_fs_cache_end = _ram_end; _ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ _estack = _ram_fs_cache_start - _estack_reserve; _sstack = _estack - 16K; /* stack = 16K */ _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; /* bss + heap = 302K, tunable by adjusting stack size */ _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); micropython-1.12/ports/stm32/boards/stm32l4xx_hal_conf_base.h000066400000000000000000000065771357706137100242160ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_BASE_H #define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_BASE_H // Include various HAL modules for convenience #include "stm32l4xx_hal_dma.h" #include "stm32l4xx_hal_adc.h" #include "stm32l4xx_hal_can.h" #include "stm32l4xx_hal_cortex.h" #include "stm32l4xx_hal_crc.h" #include "stm32l4xx_hal_dac.h" #include "stm32l4xx_hal_dcmi.h" #include "stm32l4xx_hal_flash.h" #include "stm32l4xx_hal_gpio.h" #include "stm32l4xx_hal_hash.h" #include "stm32l4xx_hal_hcd.h" #include "stm32l4xx_hal_i2c.h" #include "stm32l4xx_hal_iwdg.h" #include "stm32l4xx_hal_pcd.h" #include "stm32l4xx_hal_pwr.h" #include "stm32l4xx_hal_rcc.h" #include "stm32l4xx_hal_rtc.h" #include "stm32l4xx_hal_sd.h" #include "stm32l4xx_hal_spi.h" #include "stm32l4xx_hal_tim.h" #include "stm32l4xx_hal_uart.h" #include "stm32l4xx_hal_usart.h" #include "stm32l4xx_hal_wwdg.h" // Enable various HAL modules #define HAL_MODULE_ENABLED #define HAL_ADC_MODULE_ENABLED #define HAL_CAN_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED #define HAL_CRC_MODULE_ENABLED #define HAL_DAC_MODULE_ENABLED #define HAL_DCMI_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_HASH_MODULE_ENABLED #define HAL_HCD_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED #define HAL_IWDG_MODULE_ENABLED #define HAL_PCD_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_RTC_MODULE_ENABLED #define HAL_SD_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED #define HAL_WWDG_MODULE_ENABLED // Oscillator values in Hz #define HSI_VALUE (16000000) #define HSI48_VALUE (48000000) #define LSI_VALUE (32000) #define MSI_VALUE (4000000) // SysTick has the highest priority #define TICK_INT_PRIORITY (0x00) // Miscellaneous HAL settings #define DATA_CACHE_ENABLE 1 #define INSTRUCTION_CACHE_ENABLE 1 #define PREFETCH_ENABLE 1 #define USE_SPI_CRC 0 #define USE_RTOS 0 // HAL parameter assertions are disabled #define assert_param(expr) ((void)0) #endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_BASE_H micropython-1.12/ports/stm32/boards/stm32wb55_af.csv000066400000000000000000000131371357706137100222560ustar00rootroot00000000000000Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS_AF,TIM1/TIM2/LPTIM1,TIM1/TIM2,SPI2/SAI1/TIM1,I2C1/I2C3,SPI1/SPI2,RF,USART1,LPUART1,TSC,USB/QUADSPI,LCD,COMP1/COMP2/TIM1,SAI1,TIM2/TIM16/TIM17/LPTIM2,EVENTOUT,ADC PortA,PA0,,TIM2_CH1,,,,,,,,,,,COMP1_OUT,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC1_IN5 PortA,PA1,,TIM2_CH2,,,I2C1_SMBA,SPI1_SCK,,,,,,LCD_SEG0,,,,EVENTOUT,ADC1_IN6 PortA,PA2,LSCO,TIM2_CH3,,,,,,,LPUART1_TX,,QUADSPI_BK1_NCS,LCD_SEG1,COMP2_OUT,,,EVENTOUT,ADC1_IN7 PortA,PA3,,TIM2_CH4,,SAI1_PDM_CK1,,,,,LPUART1_RX,,QUADSPI_CLK,LCD_SEG2,,SAI1_MCLK_A,,EVENTOUT,ADC1_IN8 PortA,PA4,,,,,,SPI1_NSS,,,,,,LCD_SEG5,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC1_IN9 PortA,PA5,,TIM2_CH1,TIM2_ETR,,,SPI1_SCK,,,,,,,,SAI1_SD_B,LPTIM2_ETR,EVENTOUT,ADC1_IN10 PortA,PA6,,TIM1_BKIN,,,,SPI1_MISO,,,LPUART1_CTS,,QUADSPI_BK1_IO3,LCD_SEG3,TIM1_BKIN,,TIM16_CH1,EVENTOUT,ADC1_IN11 PortA,PA7,,TIM1_CH1N,,,I2C3_SCL,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,LCD_SEG4,COMP2_OUT,,TIM17_CH1,EVENTOUT,ADC1_IN12 PortA,PA8,MCO,TIM1_CH1,,SAI1_PDM_CK2,,,,USART1_CK,,,,LCD_COM0,,SAI1_SCK_A,LPTIM2_OUT,EVENTOUT,ADC1_IN15 PortA,PA9,,TIM1_CH2,,SAI1_PDM_DI2,I2C1_SCL,SPI2_SCK,,USART1_TX,,,,LCD_COM1,,SAI1_FS_A,,EVENTOUT,ADC1_IN16 PortA,PA10,,TIM1_CH3,,SAI1_PDM_DI1,I2C1_SDA,,,USART1_RX,,,USB_CRS_SYNC,LCD_COM2,,SAI1_SD_A,TIM17_BKIN,EVENTOUT, PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,SPI1_MISO,,USART1_CTS,,,USB_DM,,TIM1_BKIN2,,,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS_DE,LPUART1_RX,,USB_DP,,,,,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,IR_OUT,,USB_NOE,,,SAI1_SD_B,,EVENTOUT, PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,LCD_SEG5,,SAI1_FS_B,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,,,SPI1_NSS,,,,TSC_G3_IO1,,LCD_SEG17,,,,EVENTOUT, PortB,PB0,,,,,,,EXT_PA_TX,,,,,,COMP1_OUT,,,EVENTOUT, PortB,PB1,,,,,,,,,LPUART1_RTS_DE,,,,,,LPTIM2_IN1,EVENTOUT, PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,SPI1_NSS,,,,,,LCD_VLCD,,SAI1_EXTCLK,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,,USART1_RTS_DE,,,,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT, PortB,PB4,NJTRST,,,,I2C3_SDA,SPI1_MISO,,USART1_CTS,,TSC_G2_IO1,,LCD_SEG8,,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT, PortB,PB5,,LPTIM1_IN1,,,I2C1_SMBA,SPI1_MOSI,,USART1_CK,LPUART1_TX,TSC_G2_IO2,,LCD_SEG9,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT, PortB,PB6,MCO,LPTIM1_ETR,,,I2C1_SCL,,,USART1_TX,,TSC_G2_IO3,,LCD_SEG6,,SAI1_FS_B,TIM16_CH1N,EVENTOUT, PortB,PB7,,LPTIM1_IN2,,TIM1_BKIN,I2C1_SDA,,,USART1_RX,,TSC_G2_IO4,,LCD_SEG21,,,TIM17_CH1N,EVENTOUT, PortB,PB8,,TIM1_CH2N,,SAI1_PDM_CK1,I2C1_SCL,,,,,,QUADSPI_BK1_IO1,LCD_SEG16,,SAI1_MCLK_A,TIM16_CH1,EVENTOUT, PortB,PB9,,TIM1_CH3N,,SAI1_PDM_DI2,I2C1_SDA,SPI2_NSS,,,IR_OUT,TSC_G7_IO4,QUADSPI_BK1_IO0,LCD_COM3,,SAI1_FS_A,TIM17_CH1,EVENTOUT, PortB,PB10,,TIM2_CH3,,,I2C3_SCL,SPI2_SCK,,,LPUART1_RX,TSC_SYNC,QUADSPI_CLK,LCD_SEG10,COMP1_OUT,SAI1_SCK_A,,EVENTOUT, PortB,PB11,,TIM2_CH4,,,I2C3_SDA,,,,LPUART1_TX,,QUADSPI_BK1_NCS,LCD_SEG11,COMP2_OUT,,,EVENTOUT, PortB,PB12,,TIM1_BKIN,,TIM1_BKIN,I2C3_SMBA,SPI2_NSS,,,LPUART1_RTS,TSC_G1_IO1,,LCD_SEG12,,SAI1_FS_A,,EVENTOUT, PortB,PB13,,TIM1_CH1N,,,I2C3_SCL,SPI2_SCK,,,LPUART1_CTS,TSC_G1_IO2,,LCD_SEG13,,SAI1_SCK_A,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,,I2C3_SDA,SPI2_MISO,,,,TSC_G1_IO3,,LCD_SEG14,,SAI1_MCLK_A,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,,,SPI2_MOSI,,,,TSC_G1_IO4,,LCD_SEG15,,SAI1_SD_A,,EVENTOUT, PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT,ADC1_IN1 PortC,PC1,,LPTIM1_OUT,,SPI2_MOSI,I2C3_SDA,,,,LPUART1_TX,,,LCD_SEG19,,,,EVENTOUT,ADC1_IN2 PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,,,,,,LCD_SEG20,,,,EVENTOUT,ADC1_IN3 PortC,PC3,,LPTIM1_ETR,,SAI1_PDM_DI1,,SPI2_MOSI,,,,,,LCD_VLCD,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC1_IN4 PortC,PC4,,,,,,,,,,,,LCD_SEG22,,,,EVENTOUT,ADC1_IN13 PortC,PC5,,,,SAI1_PDM_DI3,,,,,,,,LCD_SEG23,,,,EVENTOUT,ADC1_IN14 PortC,PC6,,,,,,,,,,TSC_G4_IO1,,LCD_SEG24,,,,EVENTOUT, PortC,PC7,,,,,,,,,,TSC_G4_IO2,,LCD_SEG25,,,,EVENTOUT, PortC,PC8,,,,,,,,,,TSC_G4_IO3,,LCD_SEG26,,,,EVENTOUT, PortC,PC9,,,,TIM1_BKIN,,,,,,TSC_G4_IO4,USB_NOE,LCD_SEG27,,SAI1_SCK_B,,EVENTOUT, PortC,PC10,TRACED1,,,,,,,,,TSC_G3_IO2,,LCD_COM4LCD_SEG28LCD_SEG40,,,,EVENTOUT, PortC,PC11,,,,,,,,,,TSC_G3_IO3,,LCD_COM5LCD_SEG29LCD_SEG41,,,,EVENTOUT, PortC,PC12,TRACED3,,,,,,,,,TSC_G3_IO4,,LCD_COM6LCD_SEG30LCD_SEG42,,,,EVENTOUT, PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, PortD,PD0,,,,,,SPI2_NSS,,,,,,,,,,EVENTOUT, PortD,PD1,,,,,,SPI2_SCK,,,,,,,,,,EVENTOUT, PortD,PD2,TRACED2,,,,,,,,,TSC_SYNC,,LCD_COM7LCD_SEG31LCD_SEG43,,,,EVENTOUT, PortD,PD3,,,,SPI2_SCK,,SPI2_MISO,,,,,QUADSPI_BK1_NCS,,,,,EVENTOUT, PortD,PD4,,,,,,SPI2_MOSI,,,,TSC_G5_IO1,QUADSPI_BK1_IO0,,,,,EVENTOUT, PortD,PD5,,,,,,,,,,TSC_G5_IO2,QUADSPI_BK1_IO1,,,SAI1_MCLK_B,,EVENTOUT, PortD,PD6,,,,SAI1_PDM_DI1,,,,,,TSC_G5_IO3,QUADSPI_BK1_IO2,,,SAI1_SD_A,,EVENTOUT, PortD,PD7,,,,,,,,,,TSC_G5_IO4,QUADSPI_BK1_IO3,LCD_SEG39,,,,EVENTOUT, PortD,PD8,,,TIM1_BKIN2,,,,,,,,,LCD_SEG28,,,,EVENTOUT, PortD,PD9,TRACED0,,,,,,,,,,,LCD_SEG29,,,,EVENTOUT, PortD,PD10,TRIG_INOUT,,,,,,,,,TSC_G6_IO1,,LCD_SEG30,,,,EVENTOUT, PortD,PD11,,,,,,,,,,TSC_G6_IO2,,LCD_SEG31,,,LPTIM2_ETR,EVENTOUT, PortD,PD12,,,,,,,,,,TSC_G6_IO3,,LCD_SEG32,,,LPTIM2_IN1,EVENTOUT, PortD,PD13,,,,,,,,,,TSC_G6_IO4,,LCD_SEG33,,,LPTIM2_OUT,EVENTOUT, PortD,PD14,,TIM1_CH1,,,,,,,,,,LCD_SEG34,,,,EVENTOUT, PortD,PD15,,TIM1_CH2,,,,,,,,,,LCD_SEG35,,,,EVENTOUT, PortE,PE0,,TIM1_ETR,,,,,,,,TSC_G7_IO3,,LCD_SEG36,,,TIM16_CH1,EVENTOUT, PortE,PE1,,,,,,,,,,TSC_G7_IO2,,LCD_SEG37,,,TIM17_CH1,EVENTOUT, PortE,PE2,TRACECK,,,SAI1_PDM_CK1,,,,,,TSC_G7_IO1,,LCD_SEG38,,SAI1_MCLK_A,,EVENTOUT, PortE,PE3,,,,,,,,,,,,,,,,EVENTOUT, PortE,PE4,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, PortH,PH3,LSCO,,,,,,,,,,,,,,,EVENTOUT, micropython-1.12/ports/stm32/boards/stm32wb55xg.ld000066400000000000000000000024161357706137100217510ustar00rootroot00000000000000/* GNU linker script for STM32WB55xG */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* sectors 0-127 */ FLASH_FS (r) : ORIGIN = 0x08080000, LENGTH = 256K /* sectors 128-191 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K /* SRAM1 */ RAM2A (xrw) : ORIGIN = 0x20030020, LENGTH = 8K /* SRAM2A */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _ram_fs_cache_end = ORIGIN(RAM) + LENGTH(RAM); _ram_fs_cache_start = _ram_fs_cache_end - 4K; /* fs cache = 4K */ /* Define the stack. The stack is full descending so begins at the bottom of FS cache. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = _ram_fs_cache_start - _estack_reserve; _sstack = _estack - 16K; _heap_start = _ebss; /* heap starts just after statically allocated memory */ _heap_end = _sstack; _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); SECTIONS { .ram2a_bss : { . = ALIGN(4); *rfcore.o(.bss.ipcc_mem_*) . = ALIGN(4); } >RAM2A } micropython-1.12/ports/stm32/boards/stm32wbxx_hal_conf_base.h000066400000000000000000000053611357706137100242750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32WBXX_HAL_CONF_BASE_H #define MICROPY_INCLUDED_STM32WBXX_HAL_CONF_BASE_H // Include various HAL modules for convenience #include "stm32wbxx_hal_dma.h" #include "stm32wbxx_hal_adc.h" #include "stm32wbxx_hal_cortex.h" #include "stm32wbxx_hal_flash.h" #include "stm32wbxx_hal_gpio.h" #include "stm32wbxx_hal_i2c.h" #include "stm32wbxx_hal_pcd.h" #include "stm32wbxx_hal_pwr.h" #include "stm32wbxx_hal_rcc.h" #include "stm32wbxx_hal_rtc.h" #include "stm32wbxx_hal_spi.h" #include "stm32wbxx_hal_tim.h" #include "stm32wbxx_hal_uart.h" #include "stm32wbxx_hal_usart.h" // Enable various HAL modules #define HAL_MODULE_ENABLED #define HAL_ADC_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED #define HAL_PCD_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_RTC_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED // Oscillator values in Hz #define MSI_VALUE (4000000) // SysTick has the highest priority #define TICK_INT_PRIORITY (0x00) // Miscellaneous HAL settings #define DATA_CACHE_ENABLE 1 #define INSTRUCTION_CACHE_ENABLE 1 #define PREFETCH_ENABLE 0 #define USE_SPI_CRC 0 #define USE_RTOS 0 // HAL parameter assertions are disabled #define assert_param(expr) ((void)0) #endif // MICROPY_INCLUDED_STM32WBXX_HAL_CONF_BASE_H micropython-1.12/ports/stm32/bufhelper.c000066400000000000000000000037761357706137100202760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "bufhelper.h" void pyb_buf_get_for_send(mp_obj_t o, mp_buffer_info_t *bufinfo, byte *tmp_data) { if (mp_obj_is_int(o)) { tmp_data[0] = mp_obj_get_int(o); bufinfo->buf = tmp_data; bufinfo->len = 1; bufinfo->typecode = 'B'; } else { mp_get_buffer_raise(o, bufinfo, MP_BUFFER_READ); } } mp_obj_t pyb_buf_get_for_recv(mp_obj_t o, vstr_t *vstr) { if (mp_obj_is_int(o)) { // allocate a new bytearray of given length vstr_init_len(vstr, mp_obj_get_int(o)); return MP_OBJ_NULL; } else { // get the existing buffer mp_buffer_info_t bufinfo; mp_get_buffer_raise(o, &bufinfo, MP_BUFFER_WRITE); vstr->buf = bufinfo.buf; vstr->len = bufinfo.len; return o; } } micropython-1.12/ports/stm32/bufhelper.h000066400000000000000000000027371357706137100202770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_BUFHELPER_H #define MICROPY_INCLUDED_STM32_BUFHELPER_H void pyb_buf_get_for_send(mp_obj_t o, mp_buffer_info_t *bufinfo, byte *tmp_data); mp_obj_t pyb_buf_get_for_recv(mp_obj_t o, vstr_t *vstr); #endif // MICROPY_INCLUDED_STM32_BUFHELPER_H micropython-1.12/ports/stm32/can.c000066400000000000000000000343531357706137100170560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "can.h" #include "irq.h" #if MICROPY_HW_ENABLE_CAN void can_init0(void) { for (uint i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_can_obj_all)); i++) { MP_STATE_PORT(pyb_can_obj_all)[i] = NULL; } } void can_deinit_all(void) { for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_can_obj_all)); i++) { pyb_can_obj_t *can_obj = MP_STATE_PORT(pyb_can_obj_all)[i]; if (can_obj != NULL) { can_deinit(can_obj); } } } #if !MICROPY_HW_ENABLE_FDCAN bool can_init(pyb_can_obj_t *can_obj, uint32_t mode, uint32_t prescaler, uint32_t sjw, uint32_t bs1, uint32_t bs2, bool auto_restart) { CAN_InitTypeDef *init = &can_obj->can.Init; init->Mode = mode << 4; // shift-left so modes fit in a small-int init->Prescaler = prescaler; init->SJW = ((sjw - 1) & 3) << 24; init->BS1 = ((bs1 - 1) & 0xf) << 16; init->BS2 = ((bs2 - 1) & 7) << 20; init->TTCM = DISABLE; init->ABOM = auto_restart ? ENABLE : DISABLE; init->AWUM = DISABLE; init->NART = DISABLE; init->RFLM = DISABLE; init->TXFP = DISABLE; CAN_TypeDef *CANx = NULL; uint32_t sce_irq = 0; const pin_obj_t *pins[2]; switch (can_obj->can_id) { #if defined(MICROPY_HW_CAN1_TX) case PYB_CAN_1: CANx = CAN1; sce_irq = CAN1_SCE_IRQn; pins[0] = MICROPY_HW_CAN1_TX; pins[1] = MICROPY_HW_CAN1_RX; __HAL_RCC_CAN1_CLK_ENABLE(); break; #endif #if defined(MICROPY_HW_CAN2_TX) case PYB_CAN_2: CANx = CAN2; sce_irq = CAN2_SCE_IRQn; pins[0] = MICROPY_HW_CAN2_TX; pins[1] = MICROPY_HW_CAN2_RX; __HAL_RCC_CAN1_CLK_ENABLE(); // CAN2 is a "slave" and needs CAN1 enabled as well __HAL_RCC_CAN2_CLK_ENABLE(); break; #endif #if defined(MICROPY_HW_CAN3_TX) case PYB_CAN_3: CANx = CAN3; sce_irq = CAN3_SCE_IRQn; pins[0] = MICROPY_HW_CAN3_TX; pins[1] = MICROPY_HW_CAN3_RX; __HAL_RCC_CAN3_CLK_ENABLE(); // CAN3 is a "master" and doesn't need CAN1 enabled as well break; #endif default: return false; } // init GPIO uint32_t pin_mode = MP_HAL_PIN_MODE_ALT; uint32_t pin_pull = MP_HAL_PIN_PULL_UP; for (int i = 0; i < 2; i++) { if (!mp_hal_pin_config_alt(pins[i], pin_mode, pin_pull, AF_FN_CAN, can_obj->can_id)) { return false; } } // init CANx can_obj->can.Instance = CANx; HAL_CAN_Init(&can_obj->can); can_obj->is_enabled = true; can_obj->num_error_warning = 0; can_obj->num_error_passive = 0; can_obj->num_bus_off = 0; __HAL_CAN_ENABLE_IT(&can_obj->can, CAN_IT_ERR | CAN_IT_BOF | CAN_IT_EPV | CAN_IT_EWG); NVIC_SetPriority(sce_irq, IRQ_PRI_CAN); HAL_NVIC_EnableIRQ(sce_irq); return true; } void can_deinit(pyb_can_obj_t *self) { self->is_enabled = false; HAL_CAN_DeInit(&self->can); if (self->can.Instance == CAN1) { HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn); HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn); HAL_NVIC_DisableIRQ(CAN1_SCE_IRQn); __HAL_RCC_CAN1_FORCE_RESET(); __HAL_RCC_CAN1_RELEASE_RESET(); __HAL_RCC_CAN1_CLK_DISABLE(); #if defined(CAN2) } else if (self->can.Instance == CAN2) { HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn); HAL_NVIC_DisableIRQ(CAN2_RX1_IRQn); HAL_NVIC_DisableIRQ(CAN2_SCE_IRQn); __HAL_RCC_CAN2_FORCE_RESET(); __HAL_RCC_CAN2_RELEASE_RESET(); __HAL_RCC_CAN2_CLK_DISABLE(); #endif #if defined(CAN3) } else if (self->can.Instance == CAN3) { HAL_NVIC_DisableIRQ(CAN3_RX0_IRQn); HAL_NVIC_DisableIRQ(CAN3_RX1_IRQn); HAL_NVIC_DisableIRQ(CAN3_SCE_IRQn); __HAL_RCC_CAN3_FORCE_RESET(); __HAL_RCC_CAN3_RELEASE_RESET(); __HAL_RCC_CAN3_CLK_DISABLE(); #endif } } void can_clearfilter(pyb_can_obj_t *self, uint32_t f, uint8_t bank) { CAN_FilterConfTypeDef filter; filter.FilterIdHigh = 0; filter.FilterIdLow = 0; filter.FilterMaskIdHigh = 0; filter.FilterMaskIdLow = 0; filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; filter.FilterNumber = f; filter.FilterMode = CAN_FILTERMODE_IDMASK; filter.FilterScale = CAN_FILTERSCALE_16BIT; filter.FilterActivation = DISABLE; filter.BankNumber = bank; HAL_CAN_ConfigFilter(NULL, &filter); } int can_receive(CAN_HandleTypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint8_t *data, uint32_t timeout_ms) { volatile uint32_t *rfr; if (fifo == CAN_FIFO0) { rfr = &can->Instance->RF0R; } else { rfr = &can->Instance->RF1R; } // Wait for a message to become available, with timeout uint32_t start = HAL_GetTick(); while ((*rfr & 3) == 0) { MICROPY_EVENT_POLL_HOOK if (HAL_GetTick() - start >= timeout_ms) { return -MP_ETIMEDOUT; } } // Read message data CAN_FIFOMailBox_TypeDef *box = &can->Instance->sFIFOMailBox[fifo]; msg->IDE = box->RIR & 4; if (msg->IDE == CAN_ID_STD) { msg->StdId = box->RIR >> 21; } else { msg->ExtId = box->RIR >> 3; } msg->RTR = box->RIR & 2; msg->DLC = box->RDTR & 0xf; msg->FMI = box->RDTR >> 8 & 0xff; uint32_t rdlr = box->RDLR; data[0] = rdlr; data[1] = rdlr >> 8; data[2] = rdlr >> 16; data[3] = rdlr >> 24; uint32_t rdhr = box->RDHR; data[4] = rdhr; data[5] = rdhr >> 8; data[6] = rdhr >> 16; data[7] = rdhr >> 24; // Release (free) message from FIFO *rfr |= CAN_RF0R_RFOM0; return 0; // success } // We have our own version of CAN transmit so we can handle Timeout=0 correctly. HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout) { uint32_t transmitmailbox; uint32_t tickstart; uint32_t rqcpflag; uint32_t txokflag; // Check the parameters assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE)); assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR)); assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC)); // Select one empty transmit mailbox if ((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) { transmitmailbox = CAN_TXMAILBOX_0; rqcpflag = CAN_FLAG_RQCP0; txokflag = CAN_FLAG_TXOK0; } else if ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) { transmitmailbox = CAN_TXMAILBOX_1; rqcpflag = CAN_FLAG_RQCP1; txokflag = CAN_FLAG_TXOK1; } else if ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2) { transmitmailbox = CAN_TXMAILBOX_2; rqcpflag = CAN_FLAG_RQCP2; txokflag = CAN_FLAG_TXOK2; } else { transmitmailbox = CAN_TXSTATUS_NOMAILBOX; } if (transmitmailbox != CAN_TXSTATUS_NOMAILBOX) { // Set up the Id hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ; if (hcan->pTxMsg->IDE == CAN_ID_STD) { assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId)); hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21) | \ hcan->pTxMsg->RTR); } else { assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId)); hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3) | \ hcan->pTxMsg->IDE | \ hcan->pTxMsg->RTR); } // Set up the DLC hcan->pTxMsg->DLC &= (uint8_t)0x0000000F; hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0; hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC; // Set up the data field hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3] << 24) | ((uint32_t)hcan->pTxMsg->Data[2] << 16) | ((uint32_t)hcan->pTxMsg->Data[1] << 8) | ((uint32_t)hcan->pTxMsg->Data[0])); hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7] << 24) | ((uint32_t)hcan->pTxMsg->Data[6] << 16) | ((uint32_t)hcan->pTxMsg->Data[5] << 8) | ((uint32_t)hcan->pTxMsg->Data[4])); // Request transmission hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ; if (Timeout == 0) { return HAL_OK; } // Get tick tickstart = HAL_GetTick(); // Check End of transmission flag while (!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox))) { // Check for the Timeout if (Timeout != HAL_MAX_DELAY) { if ((HAL_GetTick() - tickstart) > Timeout) { // When the timeout expires, we try to abort the transmission of the packet __HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox); while (!__HAL_CAN_GET_FLAG(hcan, rqcpflag)) { } if (__HAL_CAN_GET_FLAG(hcan, txokflag)) { // The abort attempt failed and the message was sent properly return HAL_OK; } else { return HAL_TIMEOUT; } } } } return HAL_OK; } else { return HAL_BUSY; } } STATIC void can_rx_irq_handler(uint can_id, uint fifo_id) { mp_obj_t callback; pyb_can_obj_t *self; mp_obj_t irq_reason = MP_OBJ_NEW_SMALL_INT(0); byte *state; self = MP_STATE_PORT(pyb_can_obj_all)[can_id - 1]; if (fifo_id == CAN_FIFO0) { callback = self->rxcallback0; state = &self->rx_state0; } else { callback = self->rxcallback1; state = &self->rx_state1; } switch (*state) { case RX_STATE_FIFO_EMPTY: __HAL_CAN_DISABLE_IT(&self->can, (fifo_id == CAN_FIFO0) ? CAN_IT_FMP0 : CAN_IT_FMP1); irq_reason = MP_OBJ_NEW_SMALL_INT(0); *state = RX_STATE_MESSAGE_PENDING; break; case RX_STATE_MESSAGE_PENDING: __HAL_CAN_DISABLE_IT(&self->can, (fifo_id == CAN_FIFO0) ? CAN_IT_FF0 : CAN_IT_FF1); __HAL_CAN_CLEAR_FLAG(&self->can, (fifo_id == CAN_FIFO0) ? CAN_FLAG_FF0 : CAN_FLAG_FF1); irq_reason = MP_OBJ_NEW_SMALL_INT(1); *state = RX_STATE_FIFO_FULL; break; case RX_STATE_FIFO_FULL: __HAL_CAN_DISABLE_IT(&self->can, (fifo_id == CAN_FIFO0) ? CAN_IT_FOV0 : CAN_IT_FOV1); __HAL_CAN_CLEAR_FLAG(&self->can, (fifo_id == CAN_FIFO0) ? CAN_FLAG_FOV0 : CAN_FLAG_FOV1); irq_reason = MP_OBJ_NEW_SMALL_INT(2); *state = RX_STATE_FIFO_OVERFLOW; break; case RX_STATE_FIFO_OVERFLOW: // This should never happen break; } pyb_can_handle_callback(self, fifo_id, callback, irq_reason); } STATIC void can_sce_irq_handler(uint can_id) { pyb_can_obj_t *self = MP_STATE_PORT(pyb_can_obj_all)[can_id - 1]; if (self) { self->can.Instance->MSR = CAN_MSR_ERRI; uint32_t esr = self->can.Instance->ESR; if (esr & CAN_ESR_BOFF) { ++self->num_bus_off; } else if (esr & CAN_ESR_EPVF) { ++self->num_error_passive; } else if (esr & CAN_ESR_EWGF) { ++self->num_error_warning; } } } #if defined(MICROPY_HW_CAN1_TX) void CAN1_RX0_IRQHandler(void) { IRQ_ENTER(CAN1_RX0_IRQn); can_rx_irq_handler(PYB_CAN_1, CAN_FIFO0); IRQ_EXIT(CAN1_RX0_IRQn); } void CAN1_RX1_IRQHandler(void) { IRQ_ENTER(CAN1_RX1_IRQn); can_rx_irq_handler(PYB_CAN_1, CAN_FIFO1); IRQ_EXIT(CAN1_RX1_IRQn); } void CAN1_SCE_IRQHandler(void) { IRQ_ENTER(CAN1_SCE_IRQn); can_sce_irq_handler(PYB_CAN_1); IRQ_EXIT(CAN1_SCE_IRQn); } #endif #if defined(MICROPY_HW_CAN2_TX) void CAN2_RX0_IRQHandler(void) { IRQ_ENTER(CAN2_RX0_IRQn); can_rx_irq_handler(PYB_CAN_2, CAN_FIFO0); IRQ_EXIT(CAN2_RX0_IRQn); } void CAN2_RX1_IRQHandler(void) { IRQ_ENTER(CAN2_RX1_IRQn); can_rx_irq_handler(PYB_CAN_2, CAN_FIFO1); IRQ_EXIT(CAN2_RX1_IRQn); } void CAN2_SCE_IRQHandler(void) { IRQ_ENTER(CAN2_SCE_IRQn); can_sce_irq_handler(PYB_CAN_2); IRQ_EXIT(CAN2_SCE_IRQn); } #endif #if defined(MICROPY_HW_CAN3_TX) void CAN3_RX0_IRQHandler(void) { IRQ_ENTER(CAN3_RX0_IRQn); can_rx_irq_handler(PYB_CAN_3, CAN_FIFO0); IRQ_EXIT(CAN3_RX0_IRQn); } void CAN3_RX1_IRQHandler(void) { IRQ_ENTER(CAN3_RX1_IRQn); can_rx_irq_handler(PYB_CAN_3, CAN_FIFO1); IRQ_EXIT(CAN3_RX1_IRQn); } void CAN3_SCE_IRQHandler(void) { IRQ_ENTER(CAN3_SCE_IRQn); can_sce_irq_handler(PYB_CAN_3); IRQ_EXIT(CAN3_SCE_IRQn); } #endif #endif // !MICROPY_HW_ENABLE_FDCAN #endif // MICROPY_HW_ENABLE_CAN micropython-1.12/ports/stm32/can.h000066400000000000000000000060411357706137100170540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_CAN_H #define MICROPY_INCLUDED_STM32_CAN_H #include "py/obj.h" #if MICROPY_HW_ENABLE_CAN #define PYB_CAN_1 (1) #define PYB_CAN_2 (2) #define PYB_CAN_3 (3) #define MASK16 (0) #define LIST16 (1) #define MASK32 (2) #define LIST32 (3) #if MICROPY_HW_ENABLE_FDCAN #define CAN_TypeDef FDCAN_GlobalTypeDef #define CAN_HandleTypeDef FDCAN_HandleTypeDef #define CanTxMsgTypeDef FDCAN_TxHeaderTypeDef #define CanRxMsgTypeDef FDCAN_RxHeaderTypeDef #endif enum { CAN_STATE_STOPPED, CAN_STATE_ERROR_ACTIVE, CAN_STATE_ERROR_WARNING, CAN_STATE_ERROR_PASSIVE, CAN_STATE_BUS_OFF, }; typedef enum _rx_state_t { RX_STATE_FIFO_EMPTY = 0, RX_STATE_MESSAGE_PENDING, RX_STATE_FIFO_FULL, RX_STATE_FIFO_OVERFLOW, } rx_state_t; typedef struct _pyb_can_obj_t { mp_obj_base_t base; mp_obj_t rxcallback0; mp_obj_t rxcallback1; mp_uint_t can_id : 8; bool is_enabled : 1; bool extframe : 1; byte rx_state0; byte rx_state1; uint16_t num_error_warning; uint16_t num_error_passive; uint16_t num_bus_off; CAN_HandleTypeDef can; } pyb_can_obj_t; extern const mp_obj_type_t pyb_can_type; void can_init0(void); void can_deinit_all(void); bool can_init(pyb_can_obj_t *can_obj, uint32_t mode, uint32_t prescaler, uint32_t sjw, uint32_t bs1, uint32_t bs2, bool auto_restart); void can_deinit(pyb_can_obj_t *self); void can_clearfilter(pyb_can_obj_t *self, uint32_t f, uint8_t bank); int can_receive(CAN_HandleTypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint8_t *data, uint32_t timeout_ms); HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout); void pyb_can_handle_callback(pyb_can_obj_t *self, uint fifo_id, mp_obj_t callback, mp_obj_t irq_reason); #endif // MICROPY_HW_ENABLE_CAN #endif // MICROPY_INCLUDED_STM32_CAN_H micropython-1.12/ports/stm32/dac.c000066400000000000000000000422121357706137100170350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/mphal.h" #include "timer.h" #include "dac.h" #include "dma.h" #include "pin.h" /// \moduleref pyb /// \class DAC - digital to analog conversion /// /// The DAC is used to output analog values (a specific voltage) on pin X5 or pin X6. /// The voltage will be between 0 and 3.3V. /// /// *This module will undergo changes to the API.* /// /// Example usage: /// /// from pyb import DAC /// /// dac = DAC(1) # create DAC 1 on pin X5 /// dac.write(128) # write a value to the DAC (makes X5 1.65V) /// /// To output a continuous sine-wave: /// /// import math /// from pyb import DAC /// /// # create a buffer containing a sine-wave /// buf = bytearray(100) /// for i in range(len(buf)): /// buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf))) /// /// # output the sine-wave at 400Hz /// dac = DAC(1) /// dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR) #if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC #if defined(STM32H7) #define DAC DAC1 #endif #if defined(TIM6) STATIC void TIM6_Config(uint freq) { // Init TIM6 at the required frequency (in Hz) TIM_HandleTypeDef *tim = timer_tim6_init(freq); // TIM6 TRGO selection TIM_MasterConfigTypeDef config; config.MasterOutputTrigger = TIM_TRGO_UPDATE; config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(tim, &config); // TIM6 start counter HAL_TIM_Base_Start(tim); } #endif STATIC uint32_t TIMx_Config(mp_obj_t timer) { // TRGO selection to trigger DAC TIM_HandleTypeDef *tim = pyb_timer_get_handle(timer); TIM_MasterConfigTypeDef config; config.MasterOutputTrigger = TIM_TRGO_UPDATE; config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(tim, &config); // work out the trigger channel (only certain ones are supported) if (tim->Instance == TIM2) { return DAC_TRIGGER_T2_TRGO; #if defined(TIM4) } else if (tim->Instance == TIM4) { return DAC_TRIGGER_T4_TRGO; #endif #if defined(TIM5) } else if (tim->Instance == TIM5) { return DAC_TRIGGER_T5_TRGO; #endif #if defined(TIM6) } else if (tim->Instance == TIM6) { return DAC_TRIGGER_T6_TRGO; #endif #if defined(TIM7) } else if (tim->Instance == TIM7) { return DAC_TRIGGER_T7_TRGO; #endif #if defined(TIM8) } else if (tim->Instance == TIM8) { return DAC_TRIGGER_T8_TRGO; #endif } else { mp_raise_ValueError("Timer does not support DAC triggering"); } } STATIC void dac_deinit(uint32_t dac_channel) { DAC->CR &= ~(DAC_CR_EN1 << dac_channel); #if defined(STM32H7) || defined(STM32L4) DAC->MCR = (DAC->MCR & ~(DAC_MCR_MODE1_Msk << dac_channel)) | (DAC_OUTPUTBUFFER_DISABLE << dac_channel); #else DAC->CR |= DAC_CR_BOFF1 << dac_channel; #endif } STATIC void dac_config_channel(uint32_t dac_channel, uint32_t trig, uint32_t outbuf) { DAC->CR &= ~(DAC_CR_EN1 << dac_channel); uint32_t cr_off = DAC_CR_DMAEN1 | DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1; uint32_t cr_on = trig; #if defined(STM32H7) || defined(STM32L4) DAC->MCR = (DAC->MCR & ~(DAC_MCR_MODE1_Msk << dac_channel)) | (outbuf << dac_channel); #else cr_off |= DAC_CR_BOFF1; cr_on |= outbuf; #endif DAC->CR = (DAC->CR & ~(cr_off << dac_channel)) | (cr_on << dac_channel); } STATIC void dac_set_value(uint32_t dac_channel, uint32_t align, uint32_t value) { uint32_t base; if (dac_channel == DAC_CHANNEL_1) { base = (uint32_t)&DAC->DHR12R1; #if !defined(STM32L452xx) } else { base = (uint32_t)&DAC->DHR12R2; #endif } *(volatile uint32_t*)(base + align) = value; } STATIC void dac_start(uint32_t dac_channel) { DAC->CR |= DAC_CR_EN1 << dac_channel; } STATIC void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, uint32_t dma_mode, uint32_t bit_size, uint32_t dac_align, size_t len, void *buf) { uint32_t dma_align; if (bit_size == 8) { dma_align = DMA_MDATAALIGN_BYTE | DMA_PDATAALIGN_BYTE; } else { dma_align = DMA_MDATAALIGN_HALFWORD | DMA_PDATAALIGN_HALFWORD; } uint32_t base; if (dac_channel == DAC_CHANNEL_1) { base = (uint32_t)&DAC->DHR12R1; #if !defined(STM32L452xx) } else { base = (uint32_t)&DAC->DHR12R2; #endif } dma_nohal_deinit(dma_descr); dma_nohal_init(dma_descr, DMA_MEMORY_TO_PERIPH | dma_mode | dma_align); dma_nohal_start(dma_descr, (uint32_t)buf, base + dac_align, len); DAC->CR |= DAC_CR_EN1 << dac_channel; } /******************************************************************************/ // MicroPython bindings typedef struct _pyb_dac_obj_t { mp_obj_base_t base; uint8_t dac_channel; // DAC_CHANNEL_1 or DAC_CHANNEL_2. STM32L452 only has CHANNEL_1. uint8_t bits; // 8 or 12 uint8_t outbuf_single; uint8_t outbuf_waveform; } pyb_dac_obj_t; STATIC pyb_dac_obj_t pyb_dac_obj[2]; STATIC void pyb_dac_reconfigure(pyb_dac_obj_t *self, uint32_t cr, uint32_t outbuf, uint32_t value) { bool restart = false; const uint32_t cr_mask = DAC_CR_DMAEN1 | DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1 | DAC_CR_EN1; if (((DAC->CR >> self->dac_channel) & cr_mask) != (cr | DAC_CR_EN1)) { const dma_descr_t *tx_dma_descr; if (self->dac_channel == DAC_CHANNEL_1) { tx_dma_descr = &dma_DAC_1_TX; #if !defined(STM32L452xx) } else { tx_dma_descr = &dma_DAC_2_TX; #endif } dma_nohal_deinit(tx_dma_descr); dac_config_channel(self->dac_channel, cr, outbuf); restart = true; } dac_set_value(self->dac_channel, DAC_ALIGN_12B_R, value); if (restart) { dac_start(self->dac_channel); } } STATIC void pyb_dac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "DAC(%u, bits=%u)", self->dac_channel == DAC_CHANNEL_1 ? 1 : 2, self->bits); } STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_buffering, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // GPIO configuration mp_hal_pin_obj_t pin; if (self->dac_channel == DAC_CHANNEL_1) { pin = pin_A4; #if !defined(STM32L452xx) } else { pin = pin_A5; #endif } mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); // DAC peripheral clock #if defined(STM32F4) || defined(STM32F7) __DAC_CLK_ENABLE(); #elif defined(STM32H7) __HAL_RCC_DAC12_CLK_ENABLE(); #elif defined(STM32F0) || defined(STM32L4) __HAL_RCC_DAC1_CLK_ENABLE(); #else #error Unsupported Processor #endif // Stop the DAC in case it was already running DAC->CR &= ~(DAC_CR_EN1 << self->dac_channel); // set bit resolution if (args[0].u_int == 8 || args[0].u_int == 12) { self->bits = args[0].u_int; } else { mp_raise_ValueError("unsupported bits"); } // set output buffer config if (args[1].u_obj == mp_const_none) { // due to legacy, default values differ for single and waveform outputs self->outbuf_single = DAC_OUTPUTBUFFER_DISABLE; self->outbuf_waveform = DAC_OUTPUTBUFFER_ENABLE; } else if (mp_obj_is_true(args[1].u_obj)) { self->outbuf_single = DAC_OUTPUTBUFFER_ENABLE; self->outbuf_waveform = DAC_OUTPUTBUFFER_ENABLE; } else { self->outbuf_single = DAC_OUTPUTBUFFER_DISABLE; self->outbuf_waveform = DAC_OUTPUTBUFFER_DISABLE; } return mp_const_none; } // create the dac object // currently support either DAC1 on X5 (id = 1) or DAC2 on X6 (id = 2) /// \classmethod \constructor(port) /// Construct a new DAC object. /// /// `port` can be a pin object, or an integer (1 or 2). /// DAC(1) is on pin X5 and DAC(2) is on pin X6. STATIC mp_obj_t pyb_dac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get pin/channel to output on mp_int_t dac_id; if (mp_obj_is_int(args[0])) { dac_id = mp_obj_get_int(args[0]); } else { const pin_obj_t *pin = pin_find(args[0]); if (pin == pin_A4) { dac_id = 1; } else if (pin == pin_A5) { dac_id = 2; } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Pin(%q) doesn't have DAC capabilities", pin->name)); } } uint32_t dac_channel; if (dac_id == 1) { dac_channel = DAC_CHANNEL_1; #if !defined(STM32L452xx) } else if (dac_id == 2) { dac_channel = DAC_CHANNEL_2; #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "DAC(%d) doesn't exist", dac_id)); } pyb_dac_obj_t *dac = &pyb_dac_obj[dac_id - 1]; dac->base.type = &pyb_dac_type; dac->dac_channel = dac_channel; if (dac->bits == 0 || n_args > 1 || n_kw > 0) { // configure the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_dac_init_helper(dac, n_args - 1, args + 1, &kw_args); } // return object return MP_OBJ_FROM_PTR(dac); } STATIC mp_obj_t pyb_dac_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_dac_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_init_obj, 1, pyb_dac_init); /// \method deinit() /// Turn off the DAC, enable other use of pin. STATIC mp_obj_t pyb_dac_deinit(mp_obj_t self_in) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); dac_deinit(self->dac_channel); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_dac_deinit_obj, pyb_dac_deinit); #if defined(TIM6) /// \method noise(freq) /// Generate a pseudo-random noise signal. A new random sample is written /// to the DAC output at the given frequency. STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); // set TIM6 to trigger the DAC at the given frequency TIM6_Config(mp_obj_get_int(freq)); // Configure DAC in noise mode with trigger via TIM6 uint32_t cr = DAC_LFSRUNMASK_BITS11_0 | DAC_CR_WAVE1_0 | DAC_TRIGGER_T6_TRGO; pyb_dac_reconfigure(self, cr, self->outbuf_waveform, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_noise_obj, pyb_dac_noise); #endif #if defined(TIM6) /// \method triangle(freq) /// Generate a triangle wave. The value on the DAC output changes at /// the given frequency, and the frequency of the repeating triangle wave /// itself is 8192 times smaller. STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); // set TIM6 to trigger the DAC at the given frequency TIM6_Config(mp_obj_get_int(freq)); // Configure DAC in full-scale triangle mode with trigger via TIM6 uint32_t cr = DAC_TRIANGLEAMPLITUDE_4095 | DAC_CR_WAVE1_1 | DAC_TRIGGER_T6_TRGO; pyb_dac_reconfigure(self, cr, self->outbuf_waveform, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_triangle_obj, pyb_dac_triangle); #endif /// \method write(value) /// Direct access to the DAC output (8 bit only at the moment). STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); // DAC output is always 12-bit at the hardware level, and we provide support // for multiple bit "resolutions" simply by shifting the input value. uint32_t cr = DAC_TRIGGER_NONE; uint32_t value = mp_obj_get_int(val) << (12 - self->bits); pyb_dac_reconfigure(self, cr, self->outbuf_single, value); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_write_obj, pyb_dac_write); #if defined(TIM6) /// \method write_timed(data, freq, *, mode=DAC.NORMAL) /// Initiates a burst of RAM to DAC using a DMA transfer. /// The input data is treated as an array of bytes (8 bit data). /// /// `freq` can be an integer specifying the frequency to write the DAC /// samples at, using Timer(6). Or it can be an already-initialised /// Timer object which is used to trigger the DAC sample. Valid timers /// are 2, 4, 5, 6, 7 and 8. /// /// `mode` can be `DAC.NORMAL` or `DAC.CIRCULAR`. /// // TODO add callback argument, to call when transfer is finished // TODO add double buffer argument // // TODO reconsider API, eg: write_trig(data, *, trig=None, loop=False) // Then trigger can be timer (preinitialised with desired freq) or pin (extint9), // and we can reuse the same timer for both DACs (and maybe also ADC) without // setting the freq twice. // Can still do 1-liner: dac.write_trig(buf, trig=Timer(6, freq=100), loop=True) mp_obj_t pyb_dac_write_timed(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DMA_NORMAL} }, }; // parse args pyb_dac_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the data to write mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0].u_obj, &bufinfo, MP_BUFFER_READ); uint32_t dac_trigger; if (mp_obj_is_integer(args[1].u_obj)) { // set TIM6 to trigger the DAC at the given frequency TIM6_Config(mp_obj_get_int(args[1].u_obj)); dac_trigger = DAC_TRIGGER_T6_TRGO; } else { // set the supplied timer to trigger the DAC (timer should be initialised) dac_trigger = TIMx_Config(args[1].u_obj); } dac_config_channel(self->dac_channel, DAC_CR_DMAEN1 | dac_trigger, self->outbuf_waveform); const dma_descr_t *tx_dma_descr; if (self->dac_channel == DAC_CHANNEL_1) { tx_dma_descr = &dma_DAC_1_TX; #if !defined(STM32L452xx) } else { tx_dma_descr = &dma_DAC_2_TX; #endif } uint32_t align; if (self->bits == 8) { align = DAC_ALIGN_8B_R; } else { align = DAC_ALIGN_12B_R; bufinfo.len /= 2; } dac_start_dma(self->dac_channel, tx_dma_descr, args[2].u_int, self->bits, align, bufinfo.len, bufinfo.buf); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_write_timed_obj, 1, pyb_dac_write_timed); #endif STATIC const mp_rom_map_elem_t pyb_dac_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_dac_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_dac_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_dac_write_obj) }, #if defined(TIM6) { MP_ROM_QSTR(MP_QSTR_noise), MP_ROM_PTR(&pyb_dac_noise_obj) }, { MP_ROM_QSTR(MP_QSTR_triangle), MP_ROM_PTR(&pyb_dac_triangle_obj) }, { MP_ROM_QSTR(MP_QSTR_write_timed), MP_ROM_PTR(&pyb_dac_write_timed_obj) }, #endif // class constants { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(DMA_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_CIRCULAR), MP_ROM_INT(DMA_CIRCULAR) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_dac_locals_dict, pyb_dac_locals_dict_table); const mp_obj_type_t pyb_dac_type = { { &mp_type_type }, .name = MP_QSTR_DAC, .print = pyb_dac_print, .make_new = pyb_dac_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_dac_locals_dict, }; #endif // MICROPY_HW_ENABLE_DAC micropython-1.12/ports/stm32/dac.h000066400000000000000000000025531357706137100170460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_DAC_H #define MICROPY_INCLUDED_STM32_DAC_H extern const mp_obj_type_t pyb_dac_type; #endif // MICROPY_INCLUDED_STM32_DAC_H micropython-1.12/ports/stm32/dma.c000066400000000000000000001227411357706137100170550ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/obj.h" #include "py/mphal.h" #include "systick.h" #include "dma.h" #include "irq.h" #if defined(STM32WB) // DMA is currently not implemented for this MCU void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data) { } void dma_deinit(const dma_descr_t *dma_descr) { } #else #define DMA_IDLE_ENABLED() (dma_idle.enabled != 0) #define DMA_SYSTICK_LOG2 (3) #define DMA_SYSTICK_MASK ((1 << DMA_SYSTICK_LOG2) - 1) #define DMA_IDLE_TICK_MAX (8) // 8*8 = 64 msec #define DMA_IDLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & DMA_SYSTICK_MASK) == 0) #define ENABLE_SDIO (MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD) typedef enum { dma_id_not_defined=-1, dma_id_0, dma_id_1, dma_id_2, dma_id_3, dma_id_4, dma_id_5, dma_id_6, dma_id_7, dma_id_8, dma_id_9, dma_id_10, dma_id_11, dma_id_12, dma_id_13, dma_id_14, dma_id_15, } dma_id_t; typedef union { uint16_t enabled; // Used to test if both counters are == 0 uint8_t counter[2]; } dma_idle_count_t; struct _dma_descr_t { #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) DMA_Stream_TypeDef *instance; #elif defined(STM32F0) || defined(STM32L0) || defined(STM32L4) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" #endif uint32_t sub_instance; dma_id_t id; const DMA_InitTypeDef *init; }; // Default parameters to dma_init() shared by spi and i2c; Channel and Direction // vary depending on the peripheral instance so they get passed separately static const DMA_InitTypeDef dma_init_struct_spi_i2c = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, #elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) .Request = 0, #endif .Direction = 0, .PeriphInc = DMA_PINC_DISABLE, .MemInc = DMA_MINC_ENABLE, .PeriphDataAlignment = DMA_PDATAALIGN_BYTE, .MemDataAlignment = DMA_MDATAALIGN_BYTE, .Mode = DMA_NORMAL, .Priority = DMA_PRIORITY_LOW, #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) .FIFOMode = DMA_FIFOMODE_DISABLE, .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL, .MemBurst = DMA_MBURST_INC4, .PeriphBurst = DMA_PBURST_INC4 #endif }; #if ENABLE_SDIO && !defined(STM32H7) // Parameters to dma_init() for SDIO tx and rx. static const DMA_InitTypeDef dma_init_struct_sdio = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, #elif defined(STM32L0) || defined(STM32L4) .Request = 0, #endif .Direction = 0, .PeriphInc = DMA_PINC_DISABLE, .MemInc = DMA_MINC_ENABLE, .PeriphDataAlignment = DMA_PDATAALIGN_WORD, .MemDataAlignment = DMA_MDATAALIGN_WORD, #if defined(STM32F4) || defined(STM32F7) .Mode = DMA_PFCTRL, #elif defined(STM32L0) || defined(STM32L4) .Mode = DMA_NORMAL, #endif .Priority = DMA_PRIORITY_VERY_HIGH, #if defined(STM32F4) || defined(STM32F7) .FIFOMode = DMA_FIFOMODE_ENABLE, .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL, .MemBurst = DMA_MBURST_INC4, .PeriphBurst = DMA_PBURST_INC4, #endif }; #endif #if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC // Default parameters to dma_init() for DAC tx static const DMA_InitTypeDef dma_init_struct_dac = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, #elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) .Request = 0, #endif .Direction = 0, .PeriphInc = DMA_PINC_DISABLE, .MemInc = DMA_MINC_ENABLE, .PeriphDataAlignment = DMA_PDATAALIGN_BYTE, .MemDataAlignment = DMA_MDATAALIGN_BYTE, .Mode = DMA_NORMAL, .Priority = DMA_PRIORITY_HIGH, #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) .FIFOMode = DMA_FIFOMODE_DISABLE, .FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL, .MemBurst = DMA_MBURST_SINGLE, .PeriphBurst = DMA_PBURST_SINGLE, #endif }; #endif #if MICROPY_HW_ENABLE_DCMI static const DMA_InitTypeDef dma_init_struct_dcmi = { #if defined(STM32H7) .Request = DMA_REQUEST_DCMI, #else .Channel = DMA_CHANNEL_1, #endif .Direction = DMA_PERIPH_TO_MEMORY, .PeriphInc = DMA_PINC_DISABLE, .MemInc = DMA_MINC_ENABLE, .PeriphDataAlignment = DMA_PDATAALIGN_WORD, .MemDataAlignment = DMA_MDATAALIGN_WORD, .Mode = DMA_NORMAL, .Priority = DMA_PRIORITY_HIGH, .FIFOMode = DMA_FIFOMODE_ENABLE, .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL, .MemBurst = DMA_MBURST_INC4, .PeriphBurst = DMA_PBURST_SINGLE }; #endif #if defined(STM32F0) #define NCONTROLLERS (2) #define NSTREAMS_PER_CONTROLLER (7) #define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) #define DMA_SUB_INSTANCE_AS_UINT8(dma_channel) ((dma_channel) >> ((dma_channel >> 28) * 4)) #define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponding to DMA1 (7 channels) #define DMA2_ENABLE_MASK (0x0f80) // Bits in dma_enable_mask corresponding to DMA2 (only 5 channels) // DMA1 streams #if MICROPY_HW_ENABLE_DAC const dma_descr_t dma_DAC_1_TX = { DMA1_Channel3, HAL_DMA1_CH3_DAC_CH1, dma_id_2, &dma_init_struct_dac }; const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, HAL_DMA1_CH4_DAC_CH2, dma_id_3, &dma_init_struct_dac }; #endif const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, HAL_DMA1_CH5_SPI2_TX, dma_id_4, &dma_init_struct_spi_i2c}; const dma_descr_t dma_SPI_2_RX = { DMA1_Channel6, HAL_DMA1_CH6_SPI2_RX, dma_id_5, &dma_init_struct_spi_i2c}; const dma_descr_t dma_SPI_1_RX = { DMA2_Channel3, HAL_DMA2_CH3_SPI1_RX, dma_id_9, &dma_init_struct_spi_i2c}; const dma_descr_t dma_SPI_1_TX = { DMA2_Channel4, HAL_DMA2_CH4_SPI1_TX, dma_id_10, &dma_init_struct_spi_i2c}; static const uint8_t dma_irqn[NSTREAM] = { DMA1_Ch1_IRQn, DMA1_Ch2_3_DMA2_Ch1_2_IRQn, DMA1_Ch2_3_DMA2_Ch1_2_IRQn, DMA1_Ch4_7_DMA2_Ch3_5_IRQn, DMA1_Ch4_7_DMA2_Ch3_5_IRQn, DMA1_Ch4_7_DMA2_Ch3_5_IRQn, DMA1_Ch4_7_DMA2_Ch3_5_IRQn, DMA1_Ch2_3_DMA2_Ch1_2_IRQn, DMA1_Ch2_3_DMA2_Ch1_2_IRQn, DMA1_Ch4_7_DMA2_Ch3_5_IRQn, DMA1_Ch4_7_DMA2_Ch3_5_IRQn, DMA1_Ch4_7_DMA2_Ch3_5_IRQn, 0, 0, }; #elif defined(STM32F4) || defined(STM32F7) #define NCONTROLLERS (2) #define NSTREAMS_PER_CONTROLLER (8) #define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) #define DMA_SUB_INSTANCE_AS_UINT8(dma_channel) (((dma_channel) & DMA_SxCR_CHSEL) >> 25) #define DMA1_ENABLE_MASK (0x00ff) // Bits in dma_enable_mask corresponding to DMA1 #define DMA2_ENABLE_MASK (0xff00) // Bits in dma_enable_mask corresponding to DMA2 // These descriptors are ordered by DMAx_Stream number, and within a stream by channel // number. The duplicate streams are ok as long as they aren't used at the same time. // // Currently I2C and SPI are synchronous and they call dma_init/dma_deinit // around each transfer. // DMA1 streams const dma_descr_t dma_I2C_1_RX = { DMA1_Stream0, DMA_CHANNEL_1, dma_id_0, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_3_RX = { DMA1_Stream2, DMA_CHANNEL_0, dma_id_2, &dma_init_struct_spi_i2c }; #if defined(STM32F7) const dma_descr_t dma_I2C_4_RX = { DMA1_Stream2, DMA_CHANNEL_2, dma_id_2, &dma_init_struct_spi_i2c }; #endif const dma_descr_t dma_I2C_3_RX = { DMA1_Stream2, DMA_CHANNEL_3, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_2_RX = { DMA1_Stream2, DMA_CHANNEL_7, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_RX = { DMA1_Stream3, DMA_CHANNEL_0, dma_id_3, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_TX = { DMA1_Stream4, DMA_CHANNEL_0, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_3_TX = { DMA1_Stream4, DMA_CHANNEL_3, dma_id_4, &dma_init_struct_spi_i2c }; #if defined(STM32F7) const dma_descr_t dma_I2C_4_TX = { DMA1_Stream5, DMA_CHANNEL_2, dma_id_5, &dma_init_struct_spi_i2c }; #endif #if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC const dma_descr_t dma_DAC_1_TX = { DMA1_Stream5, DMA_CHANNEL_7, dma_id_5, &dma_init_struct_dac }; const dma_descr_t dma_DAC_2_TX = { DMA1_Stream6, DMA_CHANNEL_7, dma_id_6, &dma_init_struct_dac }; #endif const dma_descr_t dma_SPI_3_TX = { DMA1_Stream7, DMA_CHANNEL_0, dma_id_7, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_1_TX = { DMA1_Stream7, DMA_CHANNEL_1, dma_id_7, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_2_TX = { DMA1_Stream7, DMA_CHANNEL_7, dma_id_7, &dma_init_struct_spi_i2c }; /* not preferred streams const dma_descr_t dma_SPI_3_RX = { DMA1_Stream0, DMA_CHANNEL_0, dma_id_0, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_1_TX = { DMA1_Stream6, DMA_CHANNEL_1, dma_id_6, &dma_init_struct_spi_i2c }; */ // DMA2 streams #if defined(STM32F7) && defined(SDMMC2) && ENABLE_SDIO const dma_descr_t dma_SDMMC_2 = { DMA2_Stream0, DMA_CHANNEL_11, dma_id_8, &dma_init_struct_sdio }; #endif #if MICROPY_HW_ENABLE_DCMI const dma_descr_t dma_DCMI_0 = { DMA2_Stream1, DMA_CHANNEL_1, dma_id_9, &dma_init_struct_dcmi }; #endif const dma_descr_t dma_SPI_1_RX = { DMA2_Stream2, DMA_CHANNEL_3, dma_id_10, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_5_RX = { DMA2_Stream3, DMA_CHANNEL_2, dma_id_11, &dma_init_struct_spi_i2c }; #if ENABLE_SDIO const dma_descr_t dma_SDIO_0 = { DMA2_Stream3, DMA_CHANNEL_4, dma_id_11, &dma_init_struct_sdio }; #endif const dma_descr_t dma_SPI_4_RX = { DMA2_Stream3, DMA_CHANNEL_5, dma_id_11, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_5_TX = { DMA2_Stream4, DMA_CHANNEL_2, dma_id_12, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_4_TX = { DMA2_Stream4, DMA_CHANNEL_5, dma_id_12, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_6_TX = { DMA2_Stream5, DMA_CHANNEL_1, dma_id_13, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_1_TX = { DMA2_Stream5, DMA_CHANNEL_3, dma_id_13, &dma_init_struct_spi_i2c }; //#if defined(STM32F7) && defined(SDMMC2) && ENABLE_SDIO //const dma_descr_t dma_SDMMC_2 = { DMA2_Stream5, DMA_CHANNEL_11, dma_id_13, &dma_init_struct_sdio }; //#endif const dma_descr_t dma_SPI_6_RX = { DMA2_Stream6, DMA_CHANNEL_1, dma_id_14, &dma_init_struct_spi_i2c }; //#if ENABLE_SDIO //const dma_descr_t dma_SDIO_0 = { DMA2_Stream6, DMA_CHANNEL_4, dma_id_14, &dma_init_struct_sdio }; //#endif /* not preferred streams const dma_descr_t dma_SPI_1_TX = { DMA2_Stream3, DMA_CHANNEL_3, dma_id_11, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_1_RX = { DMA2_Stream0, DMA_CHANNEL_3, dma_id_8, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_4_RX = { DMA2_Stream0, DMA_CHANNEL_4, dma_id_8, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_4_TX = { DMA2_Stream1, DMA_CHANNEL_4, dma_id_9, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_5_RX = { DMA2_Stream5, DMA_CHANNEL_7, dma_id_13, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_5_TX = { DMA2_Stream6, DMA_CHANNEL_7, dma_id_14, &dma_init_struct_spi_i2c }; */ static const uint8_t dma_irqn[NSTREAM] = { DMA1_Stream0_IRQn, DMA1_Stream1_IRQn, DMA1_Stream2_IRQn, DMA1_Stream3_IRQn, DMA1_Stream4_IRQn, DMA1_Stream5_IRQn, DMA1_Stream6_IRQn, DMA1_Stream7_IRQn, DMA2_Stream0_IRQn, DMA2_Stream1_IRQn, DMA2_Stream2_IRQn, DMA2_Stream3_IRQn, DMA2_Stream4_IRQn, DMA2_Stream5_IRQn, DMA2_Stream6_IRQn, DMA2_Stream7_IRQn, }; #elif defined(STM32L0) #define NCONTROLLERS (1) #define NSTREAMS_PER_CONTROLLER (7) #define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) #define DMA_SUB_INSTANCE_AS_UINT8(dma_request) (dma_request) #define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponding to DMA1 // These descriptors are ordered by DMAx_Channel number, and within a channel by request // number. The duplicate streams are ok as long as they aren't used at the same time. // DMA1 streams const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, DMA_REQUEST_1, dma_id_1, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_3_TX = { DMA1_Channel2, DMA_REQUEST_14, dma_id_1, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_DAC const dma_descr_t dma_DAC_1_TX = { DMA1_Channel2, DMA_REQUEST_9, dma_id_1, &dma_init_struct_dac }; #endif const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, DMA_REQUEST_1, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_3_RX = { DMA1_Channel3, DMA_REQUEST_14, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, DMA_REQUEST_2, dma_id_3, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, DMA_REQUEST_7, dma_id_3, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_DAC const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, DMA_REQUEST_15, dma_id_3, &dma_init_struct_dac }; #endif const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, DMA_REQUEST_2, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, DMA_REQUEST_7, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, DMA_REQUEST_6, dma_id_5, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, DMA_REQUEST_6, dma_id_6, &dma_init_struct_spi_i2c }; static const uint8_t dma_irqn[NSTREAM] = { DMA1_Channel1_IRQn, DMA1_Channel2_3_IRQn, DMA1_Channel2_3_IRQn, DMA1_Channel4_5_6_7_IRQn, DMA1_Channel4_5_6_7_IRQn, DMA1_Channel4_5_6_7_IRQn, DMA1_Channel4_5_6_7_IRQn, }; #elif defined(STM32L4) #define NCONTROLLERS (2) #define NSTREAMS_PER_CONTROLLER (7) #define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) #define DMA_SUB_INSTANCE_AS_UINT8(dma_request) (dma_request) #define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponding to DMA1 #define DMA2_ENABLE_MASK (0x3f80) // Bits in dma_enable_mask corresponding to DMA2 // These descriptors are ordered by DMAx_Channel number, and within a channel by request // number. The duplicate streams are ok as long as they aren't used at the same time. // DMA1 streams //const dma_descr_t dma_ADC_1_RX = { DMA1_Channel1, DMA_REQUEST_0, dma_id_0, NULL }; // unused //const dma_descr_t dma_ADC_2_RX = { DMA1_Channel2, DMA_REQUEST_0, dma_id_1, NULL }; // unused const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, DMA_REQUEST_1, dma_id_1, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_3_TX = { DMA1_Channel2, DMA_REQUEST_3, dma_id_1, &dma_init_struct_spi_i2c }; //const dma_descr_t dma_ADC_3_RX = { DMA1_Channel3, DMA_REQUEST_0, dma_id_2, NULL }; // unused const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, DMA_REQUEST_1, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_3_RX = { DMA1_Channel3, DMA_REQUEST_3, dma_id_2, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_DAC const dma_descr_t dma_DAC_1_TX = { DMA1_Channel3, DMA_REQUEST_6, dma_id_2, &dma_init_struct_dac }; #endif const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, DMA_REQUEST_1, dma_id_3, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, DMA_REQUEST_3, dma_id_3, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_DAC const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, DMA_REQUEST_5, dma_id_3, &dma_init_struct_dac }; #endif const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, DMA_REQUEST_1, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, DMA_REQUEST_3, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, DMA_REQUEST_3, dma_id_5, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, DMA_REQUEST_3, dma_id_6, &dma_init_struct_spi_i2c }; // DMA2 streams const dma_descr_t dma_I2C_4_RX = { DMA2_Channel1, DMA_REQUEST_0, dma_id_0, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_3_RX = { DMA2_Channel1, DMA_REQUEST_3, dma_id_7, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_4_TX = { DMA2_Channel2, DMA_REQUEST_0, dma_id_1, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_3_TX = { DMA2_Channel2, DMA_REQUEST_3, dma_id_8, &dma_init_struct_spi_i2c }; /* not preferred streams const dma_descr_t dma_ADC_1_RX = { DMA2_Channel3, DMA_REQUEST_0, dma_id_9, NULL }; const dma_descr_t dma_SPI_1_RX = { DMA2_Channel3, DMA_REQUEST_4, dma_id_9, &dma_init_struct_spi_i2c }; const dma_descr_t dma_ADC_2_RX = { DMA2_Channel4, DMA_REQUEST_0, dma_id_10, NULL }; const dma_descr_t dma_DAC_1_TX = { DMA2_Channel4, DMA_REQUEST_3, dma_id_10, &dma_init_struct_dac }; const dma_descr_t dma_SPI_1_TX = { DMA2_Channel4, DMA_REQUEST_4, dma_id_10, &dma_init_struct_spi_i2c }; */ #if ENABLE_SDIO const dma_descr_t dma_SDIO_0 = { DMA2_Channel4, DMA_REQUEST_7, dma_id_10, &dma_init_struct_sdio }; #endif /* not preferred streams const dma_descr_t dma_ADC_3_RX = { DMA2_Channel5, DMA_REQUEST_0, dma_id_11, NULL }; const dma_descr_t dma_DAC_2_TX = { DMA2_Channel5, DMA_REQUEST_3, dma_id_11, &dma_init_struct_dac }; const dma_descr_t dma_SDIO_0_TX= { DMA2_Channel5, DMA_REQUEST_7, dma_id_11, &dma_init_struct_sdio }; const dma_descr_t dma_I2C_1_RX = { DMA2_Channel6, DMA_REQUEST_5, dma_id_12, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_1_TX = { DMA2_Channel7, DMA_REQUEST_5, dma_id_13, &dma_init_struct_spi_i2c }; */ static const uint8_t dma_irqn[NSTREAM] = { DMA1_Channel1_IRQn, DMA1_Channel2_IRQn, DMA1_Channel3_IRQn, DMA1_Channel4_IRQn, DMA1_Channel5_IRQn, DMA1_Channel6_IRQn, DMA1_Channel7_IRQn, DMA2_Channel1_IRQn, DMA2_Channel2_IRQn, DMA2_Channel3_IRQn, DMA2_Channel4_IRQn, DMA2_Channel5_IRQn, DMA2_Channel6_IRQn, DMA2_Channel7_IRQn, }; #elif defined(STM32H7) #define NCONTROLLERS (2) #define NSTREAMS_PER_CONTROLLER (8) #define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) #define DMA_SUB_INSTANCE_AS_UINT8(dma_channel) (dma_channel) #define DMA1_ENABLE_MASK (0x00ff) // Bits in dma_enable_mask corresponding to DMA1 #define DMA2_ENABLE_MASK (0xff00) // Bits in dma_enable_mask corresponding to DMA2 // These descriptors are ordered by DMAx_Stream number, and within a stream by channel // number. The duplicate streams are ok as long as they aren't used at the same time. // // Currently I2C and SPI are synchronous and they call dma_init/dma_deinit // around each transfer. // DMA1 streams const dma_descr_t dma_I2C_1_RX = { DMA1_Stream0, DMA_REQUEST_I2C1_RX, dma_id_0, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_3_RX = { DMA1_Stream2, DMA_REQUEST_SPI3_RX, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_4_RX = { DMA1_Stream2, BDMA_REQUEST_I2C4_RX, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_3_RX = { DMA1_Stream2, DMA_REQUEST_I2C3_RX, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_2_RX = { DMA1_Stream2, DMA_REQUEST_I2C2_RX, dma_id_2, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_RX = { DMA1_Stream3, DMA_REQUEST_SPI2_RX, dma_id_3, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_2_TX = { DMA1_Stream4, DMA_REQUEST_SPI2_TX, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_3_TX = { DMA1_Stream4, DMA_REQUEST_I2C3_TX, dma_id_4, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_4_TX = { DMA1_Stream5, BDMA_REQUEST_I2C4_TX, dma_id_5, &dma_init_struct_spi_i2c }; #if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC const dma_descr_t dma_DAC_1_TX = { DMA1_Stream5, DMA_REQUEST_DAC1_CH1, dma_id_5, &dma_init_struct_dac }; const dma_descr_t dma_DAC_2_TX = { DMA1_Stream6, DMA_REQUEST_DAC1_CH2, dma_id_6, &dma_init_struct_dac }; #endif const dma_descr_t dma_SPI_3_TX = { DMA1_Stream7, DMA_REQUEST_SPI3_TX, dma_id_7, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_1_TX = { DMA1_Stream7, DMA_REQUEST_I2C1_TX, dma_id_7, &dma_init_struct_spi_i2c }; const dma_descr_t dma_I2C_2_TX = { DMA1_Stream7, DMA_REQUEST_I2C2_TX, dma_id_7, &dma_init_struct_spi_i2c }; // DMA2 streams #if MICROPY_HW_ENABLE_DCMI const dma_descr_t dma_DCMI_0 = { DMA2_Stream1, DMA_REQUEST_DCMI, dma_id_9, &dma_init_struct_dcmi }; #endif const dma_descr_t dma_SPI_1_RX = { DMA2_Stream2, DMA_REQUEST_SPI1_RX, dma_id_10, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_5_RX = { DMA2_Stream3, DMA_REQUEST_SPI5_RX, dma_id_11, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_4_RX = { DMA2_Stream3, DMA_REQUEST_SPI4_RX, dma_id_11, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_5_TX = { DMA2_Stream4, DMA_REQUEST_SPI5_TX, dma_id_12, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_4_TX = { DMA2_Stream4, DMA_REQUEST_SPI4_TX, dma_id_12, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_6_TX = { DMA2_Stream5, BDMA_REQUEST_SPI6_TX, dma_id_13, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_1_TX = { DMA2_Stream5, DMA_REQUEST_SPI1_TX, dma_id_13, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_6_RX = { DMA2_Stream6, BDMA_REQUEST_SPI6_RX, dma_id_14, &dma_init_struct_spi_i2c }; static const uint8_t dma_irqn[NSTREAM] = { DMA1_Stream0_IRQn, DMA1_Stream1_IRQn, DMA1_Stream2_IRQn, DMA1_Stream3_IRQn, DMA1_Stream4_IRQn, DMA1_Stream5_IRQn, DMA1_Stream6_IRQn, DMA1_Stream7_IRQn, DMA2_Stream0_IRQn, DMA2_Stream1_IRQn, DMA2_Stream2_IRQn, DMA2_Stream3_IRQn, DMA2_Stream4_IRQn, DMA2_Stream5_IRQn, DMA2_Stream6_IRQn, DMA2_Stream7_IRQn, }; #endif static DMA_HandleTypeDef *dma_handle[NSTREAM] = {NULL}; static uint8_t dma_last_sub_instance[NSTREAM]; static volatile uint32_t dma_enable_mask = 0; volatile dma_idle_count_t dma_idle; #define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid #if defined(STM32F0) || defined(STM32L0) #define DMA1_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != 0) #if defined(DMA2) #define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0) #endif #else #define DMA1_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA1EN) != 0) #define DMA2_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN) != 0) #endif #if defined(STM32F0) void DMA1_Ch1_IRQHandler(void) { IRQ_ENTER(DMA1_Ch1_IRQn); if (dma_handle[dma_id_0] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_0]); } } void DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler(void) { IRQ_ENTER(DMA1_Ch2_3_DMA2_Ch1_2_IRQn); if (dma_handle[dma_id_1] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_1]); } if (dma_handle[dma_id_2] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_2]); } if (dma_handle[dma_id_7] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_7]); } if (dma_handle[dma_id_8] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_8]); } IRQ_EXIT(DMA1_Ch2_3_DMA2_Ch1_2_IRQn); } void DMA1_Ch4_7_DMA2_Ch3_5_IRQHandler(void) { IRQ_ENTER(DMA1_Ch4_7_DMA2_Ch3_5_IRQn); for (unsigned int i = 0; i < 4; ++i) { if (dma_handle[dma_id_3 + i] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_3 + i]); } // When i==3 this will check an invalid handle, but it will always be NULL if (dma_handle[dma_id_9 + i] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_9 + i]); } } IRQ_EXIT(DMA1_Ch4_7_DMA2_Ch3_5_IRQn); } #elif defined(STM32F4) || defined(STM32F7) || defined(STM32H7) void DMA1_Stream0_IRQHandler(void) { IRQ_ENTER(DMA1_Stream0_IRQn); if (dma_handle[dma_id_0] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_0]); } IRQ_EXIT(DMA1_Stream0_IRQn); } void DMA1_Stream1_IRQHandler(void) { IRQ_ENTER(DMA1_Stream1_IRQn); if (dma_handle[dma_id_1] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_1]); } IRQ_EXIT(DMA1_Stream1_IRQn); } void DMA1_Stream2_IRQHandler(void) { IRQ_ENTER(DMA1_Stream2_IRQn); if (dma_handle[dma_id_2] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_2]); } IRQ_EXIT(DMA1_Stream2_IRQn); } void DMA1_Stream3_IRQHandler(void) { IRQ_ENTER(DMA1_Stream3_IRQn); if (dma_handle[dma_id_3] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_3]); } IRQ_EXIT(DMA1_Stream3_IRQn); } void DMA1_Stream4_IRQHandler(void) { IRQ_ENTER(DMA1_Stream4_IRQn); if (dma_handle[dma_id_4] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_4]); } IRQ_EXIT(DMA1_Stream4_IRQn); } void DMA1_Stream5_IRQHandler(void) { IRQ_ENTER(DMA1_Stream5_IRQn); if (dma_handle[dma_id_5] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_5]); } IRQ_EXIT(DMA1_Stream5_IRQn); } void DMA1_Stream6_IRQHandler(void) { IRQ_ENTER(DMA1_Stream6_IRQn); if (dma_handle[dma_id_6] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_6]); } IRQ_EXIT(DMA1_Stream6_IRQn); } void DMA1_Stream7_IRQHandler(void) { IRQ_ENTER(DMA1_Stream7_IRQn); if (dma_handle[dma_id_7] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_7]); } IRQ_EXIT(DMA1_Stream7_IRQn); } void DMA2_Stream0_IRQHandler(void) { IRQ_ENTER(DMA2_Stream0_IRQn); if (dma_handle[dma_id_8] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_8]); } IRQ_EXIT(DMA2_Stream0_IRQn); } void DMA2_Stream1_IRQHandler(void) { IRQ_ENTER(DMA2_Stream1_IRQn); if (dma_handle[dma_id_9] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_9]); } IRQ_EXIT(DMA2_Stream1_IRQn); } void DMA2_Stream2_IRQHandler(void) { IRQ_ENTER(DMA2_Stream2_IRQn); if (dma_handle[dma_id_10] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_10]); } IRQ_EXIT(DMA2_Stream2_IRQn); } void DMA2_Stream3_IRQHandler(void) { IRQ_ENTER(DMA2_Stream3_IRQn); if (dma_handle[dma_id_11] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_11]); } IRQ_EXIT(DMA2_Stream3_IRQn); } void DMA2_Stream4_IRQHandler(void) { IRQ_ENTER(DMA2_Stream4_IRQn); if (dma_handle[dma_id_12] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_12]); } IRQ_EXIT(DMA2_Stream4_IRQn); } void DMA2_Stream5_IRQHandler(void) { IRQ_ENTER(DMA2_Stream5_IRQn); if (dma_handle[dma_id_13] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_13]); } IRQ_EXIT(DMA2_Stream5_IRQn); } void DMA2_Stream6_IRQHandler(void) { IRQ_ENTER(DMA2_Stream6_IRQn); if (dma_handle[dma_id_14] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_14]); } IRQ_EXIT(DMA2_Stream6_IRQn); } void DMA2_Stream7_IRQHandler(void) { IRQ_ENTER(DMA2_Stream7_IRQn); if (dma_handle[dma_id_15] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_15]); } IRQ_EXIT(DMA2_Stream7_IRQn); } #elif defined(STM32L0) void DMA1_Channel1_IRQHandler(void) { IRQ_ENTER(DMA1_Channel1_IRQn); if (dma_handle[dma_id_0] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_0]); } IRQ_EXIT(DMA1_Channel1_IRQn); } void DMA1_Channel2_3_IRQHandler(void) { IRQ_ENTER(DMA1_Channel2_3_IRQn); if (dma_handle[dma_id_1] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_1]); } if (dma_handle[dma_id_2] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_2]); } IRQ_EXIT(DMA1_Channel2_3_IRQn); } void DMA1_Channel4_5_6_7_IRQHandler(void) { IRQ_ENTER(DMA1_Channel4_5_6_7_IRQn); if (dma_handle[dma_id_3] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_3]); } if (dma_handle[dma_id_4] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_4]); } if (dma_handle[dma_id_5] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_5]); } if (dma_handle[dma_id_6] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_6]); } IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn); } #elif defined(STM32L4) void DMA1_Channel1_IRQHandler(void) { IRQ_ENTER(DMA1_Channel1_IRQn); if (dma_handle[dma_id_0] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_0]); } IRQ_EXIT(DMA1_Channel1_IRQn); } void DMA1_Channel2_IRQHandler(void) { IRQ_ENTER(DMA1_Channel2_IRQn); if (dma_handle[dma_id_1] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_1]); } IRQ_EXIT(DMA1_Channel2_IRQn); } void DMA1_Channel3_IRQHandler(void) { IRQ_ENTER(DMA1_Channel3_IRQn); if (dma_handle[dma_id_2] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_2]); } IRQ_EXIT(DMA1_Channel3_IRQn); } void DMA1_Channel4_IRQHandler(void) { IRQ_ENTER(DMA1_Channel4_IRQn); if (dma_handle[dma_id_3] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_3]); } IRQ_EXIT(DMA1_Channel4_IRQn); } void DMA1_Channel5_IRQHandler(void) { IRQ_ENTER(DMA1_Channel5_IRQn); if (dma_handle[dma_id_4] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_4]); } IRQ_EXIT(DMA1_Channel5_IRQn); } void DMA1_Channel6_IRQHandler(void) { IRQ_ENTER(DMA1_Channel6_IRQn); if (dma_handle[dma_id_5] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_5]); } IRQ_EXIT(DMA1_Channel6_IRQn); } void DMA1_Channel7_IRQHandler(void) { IRQ_ENTER(DMA1_Channel7_IRQn); if (dma_handle[dma_id_6] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_6]); } IRQ_EXIT(DMA1_Channel7_IRQn); } void DMA2_Channel1_IRQHandler(void) { IRQ_ENTER(DMA2_Channel1_IRQn); if (dma_handle[dma_id_7] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_7]); } IRQ_EXIT(DMA2_Channel1_IRQn); } void DMA2_Channel2_IRQHandler(void) { IRQ_ENTER(DMA2_Channel2_IRQn); if (dma_handle[dma_id_8] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_8]); } IRQ_EXIT(DMA2_Channel2_IRQn); } void DMA2_Channel3_IRQHandler(void) { IRQ_ENTER(DMA2_Channel3_IRQn); if (dma_handle[dma_id_9] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_9]); } IRQ_EXIT(DMA2_Channel3_IRQn); } void DMA2_Channel4_IRQHandler(void) { IRQ_ENTER(DMA2_Channel4_IRQn); if (dma_handle[dma_id_10] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_10]);} IRQ_EXIT(DMA2_Channel4_IRQn); } void DMA2_Channel5_IRQHandler(void) { IRQ_ENTER(DMA2_Channel5_IRQn); if (dma_handle[dma_id_11] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_11]);} IRQ_EXIT(DMA2_Channel5_IRQn); } void DMA2_Channel6_IRQHandler(void) { IRQ_ENTER(DMA2_Channel6_IRQn); if (dma_handle[dma_id_12] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_12]);} IRQ_EXIT(DMA2_Channel6_IRQn); } void DMA2_Channel7_IRQHandler(void) { IRQ_ENTER(DMA2_Channel7_IRQn); if (dma_handle[dma_id_13] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_13]);} IRQ_EXIT(DMA2_Channel7_IRQn); } #endif static void dma_idle_handler(uint32_t tick); // Resets the idle counter for the DMA controller associated with dma_id. static void dma_tickle(dma_id_t dma_id) { dma_idle.counter[(dma_id < NSTREAMS_PER_CONTROLLER) ? 0 : 1] = 1; systick_enable_dispatch(SYSTICK_DISPATCH_DMA, dma_idle_handler); } static void dma_enable_clock(dma_id_t dma_id) { // We don't want dma_tick_handler() to turn off the clock right after we // enable it, so we need to mark the channel in use in an atomic fashion. mp_uint_t irq_state = MICROPY_BEGIN_ATOMIC_SECTION(); uint32_t old_enable_mask = dma_enable_mask; dma_enable_mask |= (1 << dma_id); MICROPY_END_ATOMIC_SECTION(irq_state); if (dma_id < NSTREAMS_PER_CONTROLLER) { if (((old_enable_mask & DMA1_ENABLE_MASK) == 0) && !DMA1_IS_CLK_ENABLED()) { __HAL_RCC_DMA1_CLK_ENABLE(); // We just turned on the clock. This means that anything stored // in dma_last_channel (for DMA1) needs to be invalidated. for (int channel = 0; channel < NSTREAMS_PER_CONTROLLER; channel++) { dma_last_sub_instance[channel] = DMA_INVALID_CHANNEL; } } } #if defined(DMA2) else { if (((old_enable_mask & DMA2_ENABLE_MASK) == 0) && !DMA2_IS_CLK_ENABLED()) { __HAL_RCC_DMA2_CLK_ENABLE(); // We just turned on the clock. This means that anything stored // in dma_last_channel (for DMA2) needs to be invalidated. for (int channel = NSTREAMS_PER_CONTROLLER; channel < NSTREAM; channel++) { dma_last_sub_instance[channel] = DMA_INVALID_CHANNEL; } } } #endif } static void dma_disable_clock(dma_id_t dma_id) { // We just mark the clock as disabled here, but we don't actually disable it. // We wait for the timer to expire first, which means that back-to-back // transfers don't have to initialize as much. dma_tickle(dma_id); dma_enable_mask &= ~(1 << dma_id); } void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data) { // initialise parameters dma->Instance = dma_descr->instance; dma->Init = *dma_descr->init; dma->Init.Direction = dir; #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) dma->Init.Request = dma_descr->sub_instance; #else #if !defined(STM32F0) dma->Init.Channel = dma_descr->sub_instance; #endif #endif // half of __HAL_LINKDMA(data, xxx, *dma) // caller must implement other half by doing: data->xxx = dma dma->Parent = data; } void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data){ // Some drivers allocate the DMA_HandleTypeDef from the stack // (i.e. dac, i2c, spi) and for those cases we need to clear the // structure so we don't get random values from the stack) memset(dma, 0, sizeof(*dma)); if (dma_descr != NULL) { dma_id_t dma_id = dma_descr->id; dma_init_handle(dma, dma_descr, dir, data); // set global pointer for IRQ handler dma_handle[dma_id] = dma; dma_enable_clock(dma_id); #if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) // Always reset and configure the H7 and L0/L4 DMA peripheral // (dma->State is set to HAL_DMA_STATE_RESET by memset above) // TODO: understand how L0/L4 DMA works so this is not needed HAL_DMA_DeInit(dma); HAL_DMA_Init(dma); NVIC_SetPriority(IRQn_NONNEG(dma_irqn[dma_id]), IRQ_PRI_DMA); #else // if this stream was previously configured for this channel/request and direction then we // can skip most of the initialisation uint8_t sub_inst = DMA_SUB_INSTANCE_AS_UINT8(dma_descr->sub_instance) | (dir == DMA_PERIPH_TO_MEMORY) << 7; if (dma_last_sub_instance[dma_id] != sub_inst) { dma_last_sub_instance[dma_id] = sub_inst; // reset and configure DMA peripheral // (dma->State is set to HAL_DMA_STATE_RESET by memset above) HAL_DMA_DeInit(dma); HAL_DMA_Init(dma); NVIC_SetPriority(IRQn_NONNEG(dma_irqn[dma_id]), IRQ_PRI_DMA); #if defined(STM32F0) if (dma->Instance < DMA2_Channel1) { __HAL_DMA1_REMAP(dma_descr->sub_instance); } else { __HAL_DMA2_REMAP(dma_descr->sub_instance); } #endif } else { // only necessary initialization dma->State = HAL_DMA_STATE_READY; #if defined(STM32F0) // These variables are used to access the relevant 4 bits in ISR and IFCR if (dma_id < NSTREAMS_PER_CONTROLLER) { dma->DmaBaseAddress = DMA1; dma->ChannelIndex = dma_id * 4; } else { dma->DmaBaseAddress = DMA2; dma->ChannelIndex = (dma_id - NSTREAMS_PER_CONTROLLER) * 4; } #elif defined(STM32F4) || defined(STM32F7) // calculate DMA base address and bitshift to be used in IRQ handler extern uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma); DMA_CalcBaseAndBitshift(dma); #endif } #endif HAL_NVIC_EnableIRQ(dma_irqn[dma_id]); } } void dma_deinit(const dma_descr_t *dma_descr) { if (dma_descr != NULL) { #if !defined(STM32F0) HAL_NVIC_DisableIRQ(dma_irqn[dma_descr->id]); #endif dma_handle[dma_descr->id] = NULL; dma_disable_clock(dma_descr->id); } } void dma_invalidate_channel(const dma_descr_t *dma_descr) { if (dma_descr != NULL) { dma_id_t dma_id = dma_descr->id; // Only compare the sub-instance, not the direction bit (MSB) if ((dma_last_sub_instance[dma_id] & 0x7f) == DMA_SUB_INSTANCE_AS_UINT8(dma_descr->sub_instance) ) { dma_last_sub_instance[dma_id] = DMA_INVALID_CHANNEL; } } } // Called from the SysTick handler // We use LSB of tick to select which controller to process static void dma_idle_handler(uint32_t tick) { if (!DMA_IDLE_ENABLED() || !DMA_IDLE_TICK(tick)) { return; } static const uint32_t controller_mask[] = { DMA1_ENABLE_MASK, #if defined(DMA2) DMA2_ENABLE_MASK, #endif }; { int controller = (tick >> DMA_SYSTICK_LOG2) & 1; if (dma_idle.counter[controller] == 0) { return; } if (++dma_idle.counter[controller] > DMA_IDLE_TICK_MAX) { if ((dma_enable_mask & controller_mask[controller]) == 0) { // Nothing is active and we've reached our idle timeout, // Now we'll really disable the clock. dma_idle.counter[controller] = 0; if (controller == 0) { __HAL_RCC_DMA1_CLK_DISABLE(); } #if defined(DMA2) else { __HAL_RCC_DMA2_CLK_DISABLE(); } #endif } else { // Something is still active, but the counter never got // reset, so we'll reset the counter here. dma_idle.counter[controller] = 1; } } } } #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { DMA_Channel_TypeDef *dma = descr->instance; // Enable the DMA peripheral dma_enable_clock(descr->id); // Set main configuration register dma->CCR = descr->init->Priority // PL | descr->init->MemInc // MINC | descr->init->PeriphInc // PINC | config // MSIZE | PSIZE | CIRC | DIR ; // Select channel that the DMA stream uses #if defined(STM32F0) if (dma < DMA2_Channel1) { __HAL_DMA1_REMAP(descr->sub_instance); } else { __HAL_DMA2_REMAP(descr->sub_instance); } #else DMA_Request_TypeDef *dma_ctrl = (void*)(((uint32_t)dma & ~0xff) + (DMA1_CSELR_BASE - DMA1_BASE)); // DMA1_CSELR or DMA2_CSELR uint32_t channel_number = (((uint32_t)dma & 0xff) - 0x08) / 20; // 0 through 6 uint32_t channel_pos = channel_number * 4; dma_ctrl->CSELR = (dma_ctrl->CSELR & ~(0xf << channel_pos)) | (descr->sub_instance << channel_pos); #endif } void dma_nohal_deinit(const dma_descr_t *descr) { DMA_Channel_TypeDef *dma = descr->instance; dma->CCR &= ~DMA_CCR_EN; dma->CCR = 0; dma->CNDTR = 0; dma_deinit(descr); } void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_addr, uint16_t len) { DMA_Channel_TypeDef *dma = descr->instance; dma->CNDTR = len; dma->CPAR = dst_addr; dma->CMAR = src_addr; dma->CCR |= DMA_CCR_EN; } #else void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { DMA_Stream_TypeDef *dma = descr->instance; // Enable the DMA peripheral dma_enable_clock(descr->id); // Set main configuration register const DMA_InitTypeDef *init = descr->init; dma->CR = descr->sub_instance // CHSEL | init->MemBurst // MBURST | init->PeriphBurst // PBURST | init->Priority // PL | init->MemInc // MINC | init->PeriphInc // PINC | config // MSIZE | PSIZE | CIRC | DIR ; // Set FIFO control register dma->FCR = init->FIFOMode // DMDIS | init->FIFOThreshold // FTH ; } void dma_nohal_deinit(const dma_descr_t *descr) { DMA_Stream_TypeDef *dma = descr->instance; dma->CR &= ~DMA_SxCR_EN; uint32_t t0 = mp_hal_ticks_ms(); while ((dma->CR & DMA_SxCR_EN) && mp_hal_ticks_ms() - t0 < 100) { } dma->CR = 0; dma->NDTR = 0; dma->FCR = 0x21; dma_deinit(descr); } void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_addr, uint16_t len) { // Must clear all event flags for this stream before enabling it DMA_TypeDef *dma_ctrl; uint32_t ch = descr->id; if (ch < NSTREAMS_PER_CONTROLLER) { dma_ctrl = DMA1; } else { dma_ctrl = DMA2; ch -= NSTREAMS_PER_CONTROLLER; } __IO uint32_t *ifcr; if (ch <= 3) { ifcr = &dma_ctrl->LIFCR; } else { ifcr = &dma_ctrl->HIFCR; ch -= 4; } if (ch <= 1) { ch = ch * 6; } else { ch = 4 + ch * 6; } *ifcr = 0x3d << ch; // Configure and enable stream DMA_Stream_TypeDef *dma = descr->instance; dma->CR &= ~DMA_SxCR_DBM; dma->NDTR = len; dma->PAR = dst_addr; dma->M0AR = src_addr; dma->CR |= DMA_SxCR_EN; } #endif #endif // defined(STM32WB) micropython-1.12/ports/stm32/dma.h000066400000000000000000000103771357706137100170630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_DMA_H #define MICROPY_INCLUDED_STM32_DMA_H typedef struct _dma_descr_t dma_descr_t; #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7) extern const dma_descr_t dma_I2C_1_RX; extern const dma_descr_t dma_SPI_3_RX; extern const dma_descr_t dma_I2C_4_RX; extern const dma_descr_t dma_I2C_3_RX; extern const dma_descr_t dma_I2C_2_RX; extern const dma_descr_t dma_SPI_2_RX; extern const dma_descr_t dma_SPI_2_TX; extern const dma_descr_t dma_I2C_3_TX; extern const dma_descr_t dma_I2C_4_TX; extern const dma_descr_t dma_DAC_1_TX; extern const dma_descr_t dma_DAC_2_TX; extern const dma_descr_t dma_SPI_3_TX; extern const dma_descr_t dma_I2C_1_TX; extern const dma_descr_t dma_I2C_2_TX; extern const dma_descr_t dma_SDMMC_2; extern const dma_descr_t dma_SPI_1_RX; extern const dma_descr_t dma_SPI_5_RX; extern const dma_descr_t dma_SDIO_0; extern const dma_descr_t dma_SPI_4_RX; extern const dma_descr_t dma_SPI_5_TX; extern const dma_descr_t dma_SPI_4_TX; extern const dma_descr_t dma_SPI_6_TX; extern const dma_descr_t dma_SPI_1_TX; extern const dma_descr_t dma_SDMMC_2; extern const dma_descr_t dma_SPI_6_RX; extern const dma_descr_t dma_SDIO_0; extern const dma_descr_t dma_DCMI_0; #elif defined(STM32L0) extern const dma_descr_t dma_SPI_1_RX; extern const dma_descr_t dma_I2C_3_TX; extern const dma_descr_t dma_SPI_1_TX; extern const dma_descr_t dma_I2C_3_RX; extern const dma_descr_t dma_DAC_1_TX; extern const dma_descr_t dma_SPI_2_RX; extern const dma_descr_t dma_I2C_2_TX; extern const dma_descr_t dma_DAC_2_TX; extern const dma_descr_t dma_SPI_2_TX; extern const dma_descr_t dma_I2C_2_RX; extern const dma_descr_t dma_I2C_1_TX; extern const dma_descr_t dma_I2C_1_RX; #elif defined(STM32L4) || defined(STM32WB) extern const dma_descr_t dma_ADC_1_RX; extern const dma_descr_t dma_ADC_2_RX; extern const dma_descr_t dma_SPI_1_RX; extern const dma_descr_t dma_I2C_3_TX; extern const dma_descr_t dma_ADC_3_RX; extern const dma_descr_t dma_SPI_1_TX; extern const dma_descr_t dma_I2C_3_RX; extern const dma_descr_t dma_DAC_1_TX; extern const dma_descr_t dma_SPI_2_RX; extern const dma_descr_t dma_I2C_2_TX; extern const dma_descr_t dma_DAC_2_TX; extern const dma_descr_t dma_SPI_2_TX; extern const dma_descr_t dma_I2C_2_RX; extern const dma_descr_t dma_I2C_1_TX; extern const dma_descr_t dma_I2C_1_RX; extern const dma_descr_t dma_SPI_3_RX; extern const dma_descr_t dma_SPI_3_TX; extern const dma_descr_t dma_SDIO_0; extern const dma_descr_t dma_I2C_4_TX; extern const dma_descr_t dma_I2C_4_RX; #endif void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data); void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data); void dma_deinit(const dma_descr_t *dma_descr); void dma_invalidate_channel(const dma_descr_t *dma_descr); void dma_nohal_init(const dma_descr_t *descr, uint32_t config); void dma_nohal_deinit(const dma_descr_t *descr); void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_addr, uint16_t len); #endif // MICROPY_INCLUDED_STM32_DMA_H micropython-1.12/ports/stm32/eth.c000066400000000000000000000451351357706137100170750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mphal.h" #include "py/mperrno.h" #include "lib/netutils/netutils.h" #include "pin_static_af.h" #include "modnetwork.h" #include "mpu.h" #include "eth.h" #if defined(MICROPY_HW_ETH_MDC) #include "lwip/etharp.h" #include "lwip/dns.h" #include "lwip/dhcp.h" #include "netif/ethernet.h" // ETH PHY register definitions (for LAN8742) #undef PHY_BCR #define PHY_BCR (0x0000) #define PHY_BCR_SOFT_RESET (0x8000) #define PHY_BCR_AUTONEG_EN (0x1000) #undef PHY_BSR #define PHY_BSR (0x0001) #define PHY_BSR_LINK_STATUS (0x0004) #define PHY_BSR_AUTONEG_DONE (0x0020) #define PHY_SCSR (0x001f) #define PHY_SCSR_SPEED_Pos (2) #define PHY_SCSR_SPEED_Msk (7 << PHY_SCSR_SPEED_Pos) #define PHY_SCSR_SPEED_10HALF (1 << PHY_SCSR_SPEED_Pos) #define PHY_SCSR_SPEED_10FULL (5 << PHY_SCSR_SPEED_Pos) #define PHY_SCSR_SPEED_100HALF (2 << PHY_SCSR_SPEED_Pos) #define PHY_SCSR_SPEED_100FULL (6 << PHY_SCSR_SPEED_Pos) // ETH DMA RX and TX descriptor definitions #define RX_DESCR_0_OWN_Pos (31) #define RX_DESCR_0_FL_Pos (16) #define RX_DESCR_0_FL_Msk (0x3fff << RX_DESCR_0_FL_Pos) #define RX_DESCR_1_RER_Pos (15) #define RX_DESCR_1_RCH_Pos (14) #define RX_DESCR_1_RBS2_Pos (16) #define RX_DESCR_1_RBS1_Pos (0) #define TX_DESCR_0_OWN_Pos (31) #define TX_DESCR_0_LS_Pos (29) #define TX_DESCR_0_FS_Pos (28) #define TX_DESCR_0_DP_Pos (26) #define TX_DESCR_0_CIC_Pos (22) #define TX_DESCR_0_TER_Pos (21) #define TX_DESCR_0_TCH_Pos (20) #define TX_DESCR_1_TBS1_Pos (0) // Configuration values #define PHY_INIT_TIMEOUT_MS (10000) #define RX_BUF_SIZE (1524) // includes 4-byte CRC at end #define TX_BUF_SIZE (1524) #define RX_BUF_NUM (5) #define TX_BUF_NUM (5) typedef struct _eth_dma_rx_descr_t { volatile uint32_t rdes0, rdes1, rdes2, rdes3; } eth_dma_rx_descr_t; typedef struct _eth_dma_tx_descr_t { volatile uint32_t tdes0, tdes1, tdes2, tdes3; } eth_dma_tx_descr_t; typedef struct _eth_dma_t { eth_dma_rx_descr_t rx_descr[RX_BUF_NUM]; eth_dma_tx_descr_t tx_descr[TX_BUF_NUM]; uint8_t rx_buf[RX_BUF_NUM * RX_BUF_SIZE] __attribute__((aligned(4))); uint8_t tx_buf[TX_BUF_NUM * TX_BUF_SIZE] __attribute__((aligned(4))); size_t rx_descr_idx; size_t tx_descr_idx; uint8_t padding[16384 - 15408]; } eth_dma_t; typedef struct _eth_t { uint32_t trace_flags; struct netif netif; struct dhcp dhcp_struct; } eth_t; static eth_dma_t eth_dma __attribute__((aligned(16384))); eth_t eth_instance; STATIC void eth_mac_deinit(eth_t *self); STATIC void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf); STATIC void eth_phy_write(uint32_t reg, uint32_t val) { while (ETH->MACMIIAR & ETH_MACMIIAR_MB) { } ETH->MACMIIDR = val; uint32_t ar = ETH->MACMIIAR; ar = reg << ETH_MACMIIAR_MR_Pos | (ar & ETH_MACMIIAR_CR_Msk) | ETH_MACMIIAR_MW | ETH_MACMIIAR_MB; ETH->MACMIIAR = ar; while (ETH->MACMIIAR & ETH_MACMIIAR_MB) { } } STATIC uint32_t eth_phy_read(uint32_t reg) { while (ETH->MACMIIAR & ETH_MACMIIAR_MB) { } uint32_t ar = ETH->MACMIIAR; ar = reg << ETH_MACMIIAR_MR_Pos | (ar & ETH_MACMIIAR_CR_Msk) | ETH_MACMIIAR_MB; ETH->MACMIIAR = ar; while (ETH->MACMIIAR & ETH_MACMIIAR_MB) { } return ETH->MACMIIDR; } void eth_init(eth_t *self, int mac_idx) { mp_hal_get_mac(mac_idx, &self->netif.hwaddr[0]); self->netif.hwaddr_len = 6; } void eth_set_trace(eth_t *self, uint32_t value) { self->trace_flags = value; } STATIC int eth_mac_init(eth_t *self) { // Configure MPU uint32_t irq_state = mpu_config_start(); mpu_config_region(MPU_REGION_ETH, (uint32_t)ð_dma, MPU_CONFIG_ETH(MPU_REGION_SIZE_16KB)); mpu_config_end(irq_state); // Configure GPIO mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDC, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDC); mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDIO, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDIO); mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_REF_CLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_REF_CLK); mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_CRS_DV, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_CRS_DV); mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_RXD0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_RXD0); mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_RXD1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_RXD1); mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_TX_EN, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_TX_EN); mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_TXD0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_TXD0); mp_hal_pin_config_alt_static(MICROPY_HW_ETH_RMII_TXD1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_RMII_TXD1); __HAL_RCC_ETH_CLK_ENABLE(); __HAL_RCC_ETHMAC_FORCE_RESET(); // Select RMII interface __HAL_RCC_SYSCFG_CLK_ENABLE(); SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; __HAL_RCC_ETHMAC_RELEASE_RESET(); __HAL_RCC_ETHMAC_CLK_SLEEP_ENABLE(); __HAL_RCC_ETHMACTX_CLK_SLEEP_ENABLE(); __HAL_RCC_ETHMACRX_CLK_SLEEP_ENABLE(); // Do a soft reset of the MAC core ETH->DMABMR = ETH_DMABMR_SR; mp_hal_delay_ms(2); // Wait for soft reset to finish uint32_t t0 = mp_hal_ticks_ms(); while (ETH->DMABMR & ETH_DMABMR_SR) { if (mp_hal_ticks_ms() - t0 > 1000) { return -MP_ETIMEDOUT; } } // Set MII clock range uint32_t hclk = HAL_RCC_GetHCLKFreq(); uint32_t cr_div; if (hclk < 35000000) { cr_div = ETH_MACMIIAR_CR_Div16; } else if (hclk < 60000000) { cr_div = ETH_MACMIIAR_CR_Div26; } else if (hclk < 100000000) { cr_div = ETH_MACMIIAR_CR_Div42; } else if (hclk < 150000000) { cr_div = ETH_MACMIIAR_CR_Div62; } else { cr_div = ETH_MACMIIAR_CR_Div102; } ETH->MACMIIAR = cr_div; // Reset the PHY eth_phy_write(PHY_BCR, PHY_BCR_SOFT_RESET); mp_hal_delay_ms(50); // Wait for the PHY link to be established int phy_state = 0; t0 = mp_hal_ticks_ms(); while (phy_state != 3) { if (mp_hal_ticks_ms() - t0 > PHY_INIT_TIMEOUT_MS) { eth_mac_deinit(self); return -MP_ETIMEDOUT; } uint16_t bcr = eth_phy_read(0); uint16_t bsr = eth_phy_read(1); switch (phy_state) { case 0: if (!(bcr & PHY_BCR_SOFT_RESET)) { phy_state = 1; } break; case 1: if (bsr & PHY_BSR_LINK_STATUS) { eth_phy_write(PHY_BCR, PHY_BCR_AUTONEG_EN); phy_state = 2; } break; case 2: if ((bsr & (PHY_BSR_AUTONEG_DONE | PHY_BSR_LINK_STATUS)) == (PHY_BSR_AUTONEG_DONE | PHY_BSR_LINK_STATUS)) { phy_state = 3; } break; } mp_hal_delay_ms(2); } // Get register with link status uint16_t phy_scsr = eth_phy_read(PHY_SCSR); // Burst mode configuration ETH->DMABMR = 0; mp_hal_delay_ms(2); // Select DMA interrupts ETH->DMAIER = ETH_DMAIER_NISE // enable normal interrupts | ETH_DMAIER_RIE // enable RX interrupt ; // Configure RX descriptor lists for (size_t i = 0; i < RX_BUF_NUM; ++i) { eth_dma.rx_descr[i].rdes0 = 1 << RX_DESCR_0_OWN_Pos; eth_dma.rx_descr[i].rdes1 = 1 << RX_DESCR_1_RCH_Pos // chained | RX_BUF_SIZE << RX_DESCR_1_RBS1_Pos ; eth_dma.rx_descr[i].rdes2 = (uint32_t)ð_dma.rx_buf[i * RX_BUF_SIZE]; eth_dma.rx_descr[i].rdes3 = (uint32_t)ð_dma.rx_descr[(i + 1) % RX_BUF_NUM]; } ETH->DMARDLAR = (uint32_t)ð_dma.rx_descr[0]; eth_dma.rx_descr_idx = 0; // Configure TX descriptor lists for (size_t i = 0; i < TX_BUF_NUM; ++i) { eth_dma.tx_descr[i].tdes0 = 1 << TX_DESCR_0_TCH_Pos; eth_dma.tx_descr[i].tdes1 = 0; eth_dma.tx_descr[i].tdes2 = 0; eth_dma.tx_descr[i].tdes3 = (uint32_t)ð_dma.tx_descr[(i + 1) % TX_BUF_NUM]; } ETH->DMATDLAR = (uint32_t)ð_dma.tx_descr[0]; eth_dma.tx_descr_idx = 0; // Configure DMA ETH->DMAOMR = ETH_DMAOMR_RSF // read from RX FIFO after a full frame is written | ETH_DMAOMR_TSF // transmit when a full frame is in TX FIFO (needed by errata) ; mp_hal_delay_ms(2); // Select MAC filtering options ETH->MACFFR = ETH_MACFFR_RA // pass all frames up ; mp_hal_delay_ms(2); // Set MAC address u8_t *mac = &self->netif.hwaddr[0]; ETH->MACA0HR = mac[5] << 8 | mac[4]; mp_hal_delay_ms(2); ETH->MACA0LR = mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]; mp_hal_delay_ms(2); // Set main MAC control register ETH->MACCR = (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_10FULL ? ETH_MACCR_DM : (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_100HALF ? ETH_MACCR_FES : (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM) : 0 ; mp_hal_delay_ms(2); // Start MAC layer ETH->MACCR |= ETH_MACCR_TE // enable TX | ETH_MACCR_RE // enable RX ; mp_hal_delay_ms(2); // Start DMA layer ETH->DMAOMR |= ETH_DMAOMR_ST // start TX | ETH_DMAOMR_SR // start RX ; mp_hal_delay_ms(2); // Enable interrupts NVIC_SetPriority(ETH_IRQn, IRQ_PRI_PENDSV); HAL_NVIC_EnableIRQ(ETH_IRQn); return 0; } STATIC void eth_mac_deinit(eth_t *self) { (void)self; HAL_NVIC_DisableIRQ(ETH_IRQn); __HAL_RCC_ETHMAC_FORCE_RESET(); __HAL_RCC_ETHMAC_RELEASE_RESET(); __HAL_RCC_ETH_CLK_DISABLE(); } STATIC int eth_tx_buf_get(size_t len, uint8_t **buf) { if (len > TX_BUF_SIZE) { return -MP_EINVAL; } // Wait for DMA to release the current TX descriptor (if it has it) eth_dma_tx_descr_t *tx_descr = ð_dma.tx_descr[eth_dma.tx_descr_idx]; uint32_t t0 = mp_hal_ticks_ms(); for (;;) { if (!(tx_descr->tdes0 & (1 << TX_DESCR_0_OWN_Pos))) { break; } if (mp_hal_ticks_ms() - t0 > 1000) { return -MP_ETIMEDOUT; } } // Update TX descriptor with length, buffer pointer and linked list pointer *buf = ð_dma.tx_buf[eth_dma.tx_descr_idx * TX_BUF_SIZE]; tx_descr->tdes1 = len << TX_DESCR_1_TBS1_Pos; tx_descr->tdes2 = (uint32_t)*buf; tx_descr->tdes3 = (uint32_t)ð_dma.tx_descr[(eth_dma.tx_descr_idx + 1) % TX_BUF_NUM]; return 0; } STATIC int eth_tx_buf_send(void) { // Get TX descriptor and move to next one eth_dma_tx_descr_t *tx_descr = ð_dma.tx_descr[eth_dma.tx_descr_idx]; eth_dma.tx_descr_idx = (eth_dma.tx_descr_idx + 1) % TX_BUF_NUM; // Schedule to send next outgoing frame tx_descr->tdes0 = 1 << TX_DESCR_0_OWN_Pos // owned by DMA | 1 << TX_DESCR_0_LS_Pos // last segment | 1 << TX_DESCR_0_FS_Pos // first segment | 3 << TX_DESCR_0_CIC_Pos // enable all checksums inserted by hardware | 1 << TX_DESCR_0_TCH_Pos // TX descriptor is chained ; // Notify ETH DMA that there is a new TX descriptor for sending __DMB(); if (ETH->DMASR & ETH_DMASR_TBUS) { ETH->DMASR = ETH_DMASR_TBUS; ETH->DMATPDR = 0; } return 0; } STATIC void eth_dma_rx_free(void) { // Get RX descriptor, RX buffer and move to next one eth_dma_rx_descr_t *rx_descr = ð_dma.rx_descr[eth_dma.rx_descr_idx]; uint8_t *buf = ð_dma.rx_buf[eth_dma.rx_descr_idx * RX_BUF_SIZE]; eth_dma.rx_descr_idx = (eth_dma.rx_descr_idx + 1) % RX_BUF_NUM; // Schedule to get next incoming frame rx_descr->rdes1 = 1 << RX_DESCR_1_RCH_Pos // RX descriptor is chained | RX_BUF_SIZE << RX_DESCR_1_RBS1_Pos // maximum buffer length ; rx_descr->rdes2 = (uint32_t)buf; rx_descr->rdes3 = (uint32_t)ð_dma.rx_descr[eth_dma.rx_descr_idx]; rx_descr->rdes0 = 1 << RX_DESCR_0_OWN_Pos; // owned by DMA // Notify ETH DMA that there is a new RX descriptor available __DMB(); ETH->DMARPDR = 0; } void ETH_IRQHandler(void) { uint32_t sr = ETH->DMASR; ETH->DMASR = ETH_DMASR_NIS; if (sr & ETH_DMASR_RS) { ETH->DMASR = ETH_DMASR_RS; for (;;) { eth_dma_rx_descr_t *rx_descr = ð_dma.rx_descr[eth_dma.rx_descr_idx]; if (rx_descr->rdes0 & (1 << RX_DESCR_0_OWN_Pos)) { // No more RX descriptors ready to read break; } // Get RX buffer containing new frame size_t len = (rx_descr->rdes0 & RX_DESCR_0_FL_Msk) >> RX_DESCR_0_FL_Pos; len -= 4; // discard CRC at end uint8_t *buf = (uint8_t*)rx_descr->rdes2; // Process frame eth_process_frame(ð_instance, len, buf); eth_dma_rx_free(); } } } /*******************************************************************************/ // ETH-LwIP bindings #define TRACE_ASYNC_EV (0x0001) #define TRACE_ETH_TX (0x0002) #define TRACE_ETH_RX (0x0004) #define TRACE_ETH_FULL (0x0008) STATIC void eth_trace(eth_t *self, size_t len, const void *data, unsigned int flags) { if (((flags & NETUTILS_TRACE_IS_TX) && (self->trace_flags & TRACE_ETH_TX)) || (!(flags & NETUTILS_TRACE_IS_TX) && (self->trace_flags & TRACE_ETH_RX))) { const uint8_t *buf; if (len == (size_t)-1) { // data is a pbuf const struct pbuf *pbuf = data; buf = pbuf->payload; len = pbuf->len; // restricted to print only the first chunk of the pbuf } else { // data is actual data buffer buf = data; } if (self->trace_flags & TRACE_ETH_FULL) { flags |= NETUTILS_TRACE_PAYLOAD; } netutils_ethernet_trace(MP_PYTHON_PRINTER, len, buf, flags); } } STATIC err_t eth_netif_output(struct netif *netif, struct pbuf *p) { // This function should always be called from a context where PendSV-level IRQs are disabled LINK_STATS_INC(link.xmit); eth_trace(netif->state, (size_t)-1, p, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE); uint8_t *buf; int ret = eth_tx_buf_get(p->tot_len, &buf); if (ret == 0) { pbuf_copy_partial(p, buf, p->tot_len, 0); ret = eth_tx_buf_send(); } return ret ? ERR_BUF : ERR_OK; } STATIC err_t eth_netif_init(struct netif *netif) { netif->linkoutput = eth_netif_output; netif->output = etharp_output; netif->mtu = 1500; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; // Checksums only need to be checked on incoming frames, not computed on outgoing frames NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_CHECK_IP | NETIF_CHECKSUM_CHECK_UDP | NETIF_CHECKSUM_CHECK_TCP | NETIF_CHECKSUM_CHECK_ICMP | NETIF_CHECKSUM_CHECK_ICMP6); return ERR_OK; } STATIC void eth_lwip_init(eth_t *self) { ip_addr_t ipconfig[4]; IP4_ADDR(&ipconfig[0], 0, 0, 0, 0); IP4_ADDR(&ipconfig[2], 192, 168, 0, 1); IP4_ADDR(&ipconfig[1], 255, 255, 255, 0); IP4_ADDR(&ipconfig[3], 8, 8, 8, 8); MICROPY_PY_LWIP_ENTER struct netif *n = &self->netif; n->name[0] = 'e'; n->name[1] = '0'; netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, eth_netif_init, ethernet_input); netif_set_hostname(n, "MPY"); netif_set_default(n); netif_set_up(n); dns_setserver(0, &ipconfig[3]); dhcp_set_struct(n, &self->dhcp_struct); dhcp_start(n); netif_set_link_up(n); MICROPY_PY_LWIP_EXIT } STATIC void eth_lwip_deinit(eth_t *self) { MICROPY_PY_LWIP_ENTER for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { if (netif == &self->netif) { netif_remove(netif); netif->ip_addr.addr = 0; netif->flags = 0; } } MICROPY_PY_LWIP_EXIT } STATIC void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf) { eth_trace(self, len, buf, NETUTILS_TRACE_NEWLINE); struct netif *netif = &self->netif; if (netif->flags & NETIF_FLAG_LINK_UP) { struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != NULL) { pbuf_take(p, buf, len); if (netif->input(p, netif) != ERR_OK) { pbuf_free(p); } } } } struct netif *eth_netif(eth_t *self) { return &self->netif; } int eth_link_status(eth_t *self) { struct netif *netif = &self->netif; if ((netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) { if (netif->ip_addr.addr != 0) { return 3; // link up } else { return 2; // link no-ip; } } else { int s = eth_phy_read(0) | eth_phy_read(0x10) << 16; if (s == 0) { return 0; // link down } else { return 1; // link join } } } int eth_start(eth_t *self) { eth_lwip_deinit(self); int ret = eth_mac_init(self); if (ret < 0) { return ret; } eth_lwip_init(self); return 0; } int eth_stop(eth_t *self) { eth_lwip_deinit(self); eth_mac_deinit(self); return 0; } #endif // defined(MICROPY_HW_ETH_MDC) micropython-1.12/ports/stm32/eth.h000066400000000000000000000031161357706137100170730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_ETH_H #define MICROPY_INCLUDED_STM32_ETH_H typedef struct _eth_t eth_t; extern eth_t eth_instance; void eth_init(eth_t *self, int mac_idx); void eth_set_trace(eth_t *self, uint32_t value); struct netif *eth_netif(eth_t *self); int eth_link_status(eth_t *self); int eth_start(eth_t *self); int eth_stop(eth_t *self); #endif // MICROPY_INCLUDED_STM32_ETH_H micropython-1.12/ports/stm32/extint.c000066400000000000000000000632441357706137100176310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" #include "pendsv.h" #include "pin.h" #include "extint.h" #include "irq.h" /// \moduleref pyb /// \class ExtInt - configure I/O pins to interrupt on external events /// /// There are a total of 22 interrupt lines. 16 of these can come from GPIO pins /// and the remaining 6 are from internal sources. /// /// For lines 0 thru 15, a given line can map to the corresponding line from an /// arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and /// line 1 can map to Px1 where x is A, B, C, ... /// /// def callback(line): /// print("line =", line) /// /// Note: ExtInt will automatically configure the gpio line as an input. /// /// extint = pyb.ExtInt(pin, pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, callback) /// /// Now every time a falling edge is seen on the X1 pin, the callback will be /// called. Caution: mechanical pushbuttons have "bounce" and pushing or /// releasing a switch will often generate multiple edges. /// See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed /// explanation, along with various techniques for debouncing. /// /// Trying to register 2 callbacks onto the same pin will throw an exception. /// /// If pin is passed as an integer, then it is assumed to map to one of the /// internal interrupt sources, and must be in the range 16 thru 22. /// /// All other pin objects go through the pin mapper to come up with one of the /// gpio pins. /// /// extint = pyb.ExtInt(pin, mode, pull, callback) /// /// Valid modes are pyb.ExtInt.IRQ_RISING, pyb.ExtInt.IRQ_FALLING, /// pyb.ExtInt.IRQ_RISING_FALLING, pyb.ExtInt.EVT_RISING, /// pyb.ExtInt.EVT_FALLING, and pyb.ExtInt.EVT_RISING_FALLING. /// /// Only the IRQ_xxx modes have been tested. The EVT_xxx modes have /// something to do with sleep mode and the WFE instruction. /// /// Valid pull values are pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN, pyb.Pin.PULL_NONE. /// /// There is also a C API, so that drivers which require EXTI interrupt lines /// can also use this code. See extint.h for the available functions and /// usrsw.h for an example of using this. // TODO Add python method to change callback object. #if defined(STM32F4) || defined(STM32L4) // These MCUs have bitband support so define macros to atomically set/clear bits in IMR/EMR and SWIER #define EXTI_OFFSET (EXTI_BASE - PERIPH_BASE) #define EXTI_MODE_BB(mode, line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + (mode)) * 32) + ((line) * 4))) #define EXTI_SWIER_BB(line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + offsetof(EXTI_TypeDef, SWIER)) * 32) + ((line) * 4))) #endif #if defined(STM32L4) || defined(STM32WB) // The L4 MCU supports 40 Events/IRQs lines of the type configurable and direct. // Here we only support configurable line types. Details, see page 330 of RM0351, Rev 1. // The USB_FS_WAKUP event is a direct type and there is no support for it. #define EXTI_Mode_Interrupt offsetof(EXTI_TypeDef, IMR1) #define EXTI_Mode_Event offsetof(EXTI_TypeDef, EMR1) #define EXTI_Trigger_Rising offsetof(EXTI_TypeDef, RTSR1) #define EXTI_Trigger_Falling offsetof(EXTI_TypeDef, FTSR1) #define EXTI_RTSR EXTI->RTSR1 #define EXTI_FTSR EXTI->FTSR1 #elif defined(STM32H7) #define EXTI_Mode_Interrupt offsetof(EXTI_Core_TypeDef, IMR1) #define EXTI_Mode_Event offsetof(EXTI_Core_TypeDef, EMR1) #define EXTI_Trigger_Rising offsetof(EXTI_Core_TypeDef, RTSR1) #define EXTI_Trigger_Falling offsetof(EXTI_Core_TypeDef, FTSR1) #define EXTI_RTSR EXTI->RTSR1 #define EXTI_FTSR EXTI->FTSR1 #else #define EXTI_Mode_Interrupt offsetof(EXTI_TypeDef, IMR) #define EXTI_Mode_Event offsetof(EXTI_TypeDef, EMR) #define EXTI_Trigger_Rising offsetof(EXTI_TypeDef, RTSR) #define EXTI_Trigger_Falling offsetof(EXTI_TypeDef, FTSR) #define EXTI_RTSR EXTI->RTSR #define EXTI_FTSR EXTI->FTSR #endif typedef struct { mp_obj_base_t base; mp_int_t line; } extint_obj_t; STATIC uint8_t pyb_extint_mode[EXTI_NUM_VECTORS]; STATIC bool pyb_extint_hard_irq[EXTI_NUM_VECTORS]; // The callback arg is a small-int or a ROM Pin object, so no need to scan by GC STATIC mp_obj_t pyb_extint_callback_arg[EXTI_NUM_VECTORS]; #if !defined(ETH) #define ETH_WKUP_IRQn 62 // Some MCUs don't have ETH, but we want a value to put in our table #endif #if !defined(OTG_HS_WKUP_IRQn) #define OTG_HS_WKUP_IRQn 76 // Some MCUs don't have HS, but we want a value to put in our table #endif #if !defined(OTG_FS_WKUP_IRQn) #define OTG_FS_WKUP_IRQn 42 // Some MCUs don't have FS IRQ, but we want a value to put in our table #endif STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { #if defined(STM32F0) || defined(STM32L0) EXTI0_1_IRQn, EXTI0_1_IRQn, EXTI2_3_IRQn, EXTI2_3_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, #if defined(STM32L0) PVD_IRQn, #else PVD_VDDIO2_IRQn, #endif RTC_IRQn, 0, // internal USB wakeup event RTC_IRQn, RTC_IRQn, ADC1_COMP_IRQn, ADC1_COMP_IRQn, #else EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, #if defined(STM32H7) PVD_AVD_IRQn, RTC_Alarm_IRQn, TAMP_STAMP_IRQn, RTC_WKUP_IRQn, #elif defined(STM32WB) PVD_PVM_IRQn, RTC_Alarm_IRQn, TAMP_STAMP_LSECSS_IRQn, RTC_WKUP_IRQn, #else #if defined(STM32L4) PVD_PVM_IRQn, #else PVD_IRQn, #endif #if defined(STM32L4) OTG_FS_WKUP_IRQn, RTC_Alarm_IRQn, #else RTC_Alarm_IRQn, OTG_FS_WKUP_IRQn, #endif ETH_WKUP_IRQn, OTG_HS_WKUP_IRQn, TAMP_STAMP_IRQn, RTC_WKUP_IRQn, #endif #endif }; // Set override_callback_obj to true if you want to unconditionally set the // callback function. uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t callback_obj, bool override_callback_obj) { const pin_obj_t *pin = NULL; uint v_line; if (mp_obj_is_int(pin_obj)) { // If an integer is passed in, then use it to identify lines 16 thru 22 // We expect lines 0 thru 15 to be passed in as a pin, so that we can // get both the port number and line number. v_line = mp_obj_get_int(pin_obj); if (v_line < 16) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "ExtInt vector %d < 16, use a Pin object", v_line)); } if (v_line >= EXTI_NUM_VECTORS) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "ExtInt vector %d >= max of %d", v_line, EXTI_NUM_VECTORS)); } } else { pin = pin_find(pin_obj); v_line = pin->pin; } if (mode != GPIO_MODE_IT_RISING && mode != GPIO_MODE_IT_FALLING && mode != GPIO_MODE_IT_RISING_FALLING && mode != GPIO_MODE_EVT_RISING && mode != GPIO_MODE_EVT_FALLING && mode != GPIO_MODE_EVT_RISING_FALLING) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid ExtInt Mode: %d", mode)); } if (pull != GPIO_NOPULL && pull != GPIO_PULLUP && pull != GPIO_PULLDOWN) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid ExtInt Pull: %d", pull)); } mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[v_line]; if (!override_callback_obj && *cb != mp_const_none && callback_obj != mp_const_none) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "ExtInt vector %d is already in use", v_line)); } // We need to update callback atomically, so we disable the line // before we update anything. extint_disable(v_line); *cb = callback_obj; pyb_extint_mode[v_line] = (mode & 0x00010000) ? // GPIO_MODE_IT == 0x00010000 EXTI_Mode_Interrupt : EXTI_Mode_Event; if (*cb != mp_const_none) { pyb_extint_hard_irq[v_line] = true; pyb_extint_callback_arg[v_line] = MP_OBJ_NEW_SMALL_INT(v_line); if (pin == NULL) { // pin will be NULL for non GPIO EXTI lines extint_trigger_mode(v_line, mode); extint_enable(v_line); } else { mp_hal_gpio_clock_enable(pin->gpio); GPIO_InitTypeDef exti; exti.Pin = pin->pin_mask; exti.Mode = mode; exti.Pull = pull; exti.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(pin->gpio, &exti); // Calling HAL_GPIO_Init does an implicit extint_enable } /* Enable and set NVIC Interrupt to the lowest priority */ NVIC_SetPriority(IRQn_NONNEG(nvic_irq_channel[v_line]), IRQ_PRI_EXTINT); HAL_NVIC_EnableIRQ(nvic_irq_channel[v_line]); } return v_line; } // This function is intended to be used by the Pin.irq() method void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_obj_t callback_obj) { uint32_t line = pin->pin; // Check if the ExtInt line is already in use by another Pin/ExtInt mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line]; if (*cb != mp_const_none && MP_OBJ_FROM_PTR(pin) != pyb_extint_callback_arg[line]) { if (mp_obj_is_small_int(pyb_extint_callback_arg[line])) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "ExtInt vector %d is already in use", line)); } else { const pin_obj_t *other_pin = MP_OBJ_TO_PTR(pyb_extint_callback_arg[line]); nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "IRQ resource already taken by Pin('%q')", other_pin->name)); } } extint_disable(line); *cb = callback_obj; pyb_extint_mode[line] = (mode & 0x00010000) ? // GPIO_MODE_IT == 0x00010000 EXTI_Mode_Interrupt : EXTI_Mode_Event; if (*cb != mp_const_none) { // Configure and enable the callback pyb_extint_hard_irq[line] = hard_irq; pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); // Route the GPIO to EXTI #if !defined(STM32WB) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif SYSCFG->EXTICR[line >> 2] = (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); extint_trigger_mode(line, mode); // Configure the NVIC NVIC_SetPriority(IRQn_NONNEG(nvic_irq_channel[line]), IRQ_PRI_EXTINT); HAL_NVIC_EnableIRQ(nvic_irq_channel[line]); // Enable the interrupt extint_enable(line); } } void extint_set(const pin_obj_t *pin, uint32_t mode) { uint32_t line = pin->pin; mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line]; extint_disable(line); *cb = MP_OBJ_SENTINEL; pyb_extint_mode[line] = (mode & 0x00010000) ? // GPIO_MODE_IT == 0x00010000 EXTI_Mode_Interrupt : EXTI_Mode_Event; { // Configure and enable the callback pyb_extint_hard_irq[line] = 1; pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); // Route the GPIO to EXTI #if !defined(STM32WB) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif SYSCFG->EXTICR[line >> 2] = (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); // Enable or disable the rising detector if ((mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING) { EXTI_RTSR |= 1 << line; } else { EXTI_RTSR &= ~(1 << line); } // Enable or disable the falling detector if ((mode & GPIO_MODE_IT_FALLING) == GPIO_MODE_IT_FALLING) { EXTI_FTSR |= 1 << line; } else { EXTI_FTSR &= ~(1 << line); } // Configure the NVIC NVIC_SetPriority(IRQn_NONNEG(nvic_irq_channel[line]), IRQ_PRI_EXTINT); HAL_NVIC_EnableIRQ(nvic_irq_channel[line]); // Enable the interrupt extint_enable(line); } } void extint_enable(uint line) { if (line >= EXTI_NUM_VECTORS) { return; } #if !defined(EXTI_MODE_BB) // This MCU doesn't have bitband support. mp_uint_t irq_state = disable_irq(); if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) { #if defined(STM32H7) EXTI_D1->IMR1 |= (1 << line); #elif defined(STM32WB) EXTI->IMR1 |= (1 << line); #else EXTI->IMR |= (1 << line); #endif } else { #if defined(STM32H7) EXTI_D1->EMR1 |= (1 << line); #elif defined(STM32WB) EXTI->EMR1 |= (1 << line); #else EXTI->EMR |= (1 << line); #endif } enable_irq(irq_state); #else // Since manipulating IMR/EMR is a read-modify-write, and we want this to // be atomic, we use the bit-band area to just affect the bit we're // interested in. EXTI_MODE_BB(pyb_extint_mode[line], line) = 1; #endif } void extint_disable(uint line) { if (line >= EXTI_NUM_VECTORS) { return; } #if !defined(EXTI_MODE_BB) // This MCU doesn't have bitband support. mp_uint_t irq_state = disable_irq(); #if defined(STM32H7) EXTI_D1->IMR1 &= ~(1 << line); EXTI_D1->EMR1 &= ~(1 << line); #elif defined(STM32WB) EXTI->IMR1 &= ~(1 << line); EXTI->EMR1 &= ~(1 << line); #else EXTI->IMR &= ~(1 << line); EXTI->EMR &= ~(1 << line); #endif enable_irq(irq_state); #else // Since manipulating IMR/EMR is a read-modify-write, and we want this to // be atomic, we use the bit-band area to just affect the bit we're // interested in. EXTI_MODE_BB(EXTI_Mode_Interrupt, line) = 0; EXTI_MODE_BB(EXTI_Mode_Event, line) = 0; #endif } void extint_swint(uint line) { if (line >= EXTI_NUM_VECTORS) { return; } // we need 0 to 1 transition to trigger the interrupt #if defined(STM32L4) || defined(STM32H7) || defined(STM32WB) EXTI->SWIER1 &= ~(1 << line); EXTI->SWIER1 |= (1 << line); #else EXTI->SWIER &= ~(1 << line); EXTI->SWIER |= (1 << line); #endif } void extint_trigger_mode(uint line, uint32_t mode) { if (line >= EXTI_NUM_VECTORS) { return; } #if !defined(EXTI_MODE_BB) // This MCU doesn't have bitband support. mp_uint_t irq_state = disable_irq(); // Enable or disable the rising detector if ((mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING) { EXTI_RTSR |= (1 << line); } else { EXTI_RTSR &= ~(1 << line); } // Enable or disable the falling detector if ((mode & GPIO_MODE_IT_FALLING) == GPIO_MODE_IT_FALLING) { EXTI_FTSR |= 1 << line; } else { EXTI_FTSR &= ~(1 << line); } enable_irq(irq_state); #else // Since manipulating FTSR/RTSR is a read-modify-write, and we want this to // be atomic, we use the bit-band area to just affect the bit we're // interested in. EXTI_MODE_BB(EXTI_Trigger_Rising, line) = (mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING; EXTI_MODE_BB(EXTI_Trigger_Falling, line) = (mode & GPIO_MODE_IT_FALLING) == GPIO_MODE_IT_FALLING; #endif } /// \method line() /// Return the line number that the pin is mapped to. STATIC mp_obj_t extint_obj_line(mp_obj_t self_in) { extint_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(self->line); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_line_obj, extint_obj_line); /// \method enable() /// Enable a disabled interrupt. STATIC mp_obj_t extint_obj_enable(mp_obj_t self_in) { extint_obj_t *self = MP_OBJ_TO_PTR(self_in); extint_enable(self->line); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_enable_obj, extint_obj_enable); /// \method disable() /// Disable the interrupt associated with the ExtInt object. /// This could be useful for debouncing. STATIC mp_obj_t extint_obj_disable(mp_obj_t self_in) { extint_obj_t *self = MP_OBJ_TO_PTR(self_in); extint_disable(self->line); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_disable_obj, extint_obj_disable); /// \method swint() /// Trigger the callback from software. STATIC mp_obj_t extint_obj_swint(mp_obj_t self_in) { extint_obj_t *self = MP_OBJ_TO_PTR(self_in); extint_swint(self->line); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint); // TODO document as a staticmethod /// \classmethod regs() /// Dump the values of the EXTI registers. STATIC mp_obj_t extint_regs(void) { #if defined(STM32L4) || defined(STM32WB) printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1); printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI->IMR2); printf("EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1); printf("EXTI_EMR2 %08x\n", (unsigned int)EXTI->EMR2); printf("EXTI_RTSR1 %08x\n", (unsigned int)EXTI->RTSR1); printf("EXTI_RTSR2 %08x\n", (unsigned int)EXTI->RTSR2); printf("EXTI_FTSR1 %08x\n", (unsigned int)EXTI->FTSR1); printf("EXTI_FTSR2 %08x\n", (unsigned int)EXTI->FTSR2); printf("EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1); printf("EXTI_SWIER2 %08x\n", (unsigned int)EXTI->SWIER2); printf("EXTI_PR1 %08x\n", (unsigned int)EXTI->PR1); printf("EXTI_PR2 %08x\n", (unsigned int)EXTI->PR2); #elif defined(STM32H7) printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI_D1->IMR1); printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI_D1->IMR2); printf("EXTI_IMR3 %08x\n", (unsigned int)EXTI_D1->IMR3); printf("EXTI_EMR1 %08x\n", (unsigned int)EXTI_D1->EMR1); printf("EXTI_EMR2 %08x\n", (unsigned int)EXTI_D1->EMR2); printf("EXTI_EMR3 %08x\n", (unsigned int)EXTI_D1->EMR3); printf("EXTI_RTSR1 %08x\n", (unsigned int)EXTI->RTSR1); printf("EXTI_RTSR2 %08x\n", (unsigned int)EXTI->RTSR2); printf("EXTI_RTSR3 %08x\n", (unsigned int)EXTI->RTSR3); printf("EXTI_FTSR1 %08x\n", (unsigned int)EXTI->FTSR1); printf("EXTI_FTSR2 %08x\n", (unsigned int)EXTI->FTSR2); printf("EXTI_FTSR3 %08x\n", (unsigned int)EXTI->FTSR3); printf("EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1); printf("EXTI_SWIER2 %08x\n", (unsigned int)EXTI->SWIER2); printf("EXTI_SWIER3 %08x\n", (unsigned int)EXTI->SWIER3); printf("EXTI_PR1 %08x\n", (unsigned int)EXTI_D1->PR1); printf("EXTI_PR2 %08x\n", (unsigned int)EXTI_D1->PR2); printf("EXTI_PR3 %08x\n", (unsigned int)EXTI_D1->PR3); #else printf("EXTI_IMR %08x\n", (unsigned int)EXTI->IMR); printf("EXTI_EMR %08x\n", (unsigned int)EXTI->EMR); printf("EXTI_RTSR %08x\n", (unsigned int)EXTI->RTSR); printf("EXTI_FTSR %08x\n", (unsigned int)EXTI->FTSR); printf("EXTI_SWIER %08x\n", (unsigned int)EXTI->SWIER); printf("EXTI_PR %08x\n", (unsigned int)EXTI->PR); #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(extint_regs_fun_obj, extint_regs); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(extint_regs_obj, MP_ROM_PTR(&extint_regs_fun_obj)); /// \classmethod \constructor(pin, mode, pull, callback) /// Create an ExtInt object: /// /// - `pin` is the pin on which to enable the interrupt (can be a pin object or any valid pin name). /// - `mode` can be one of: /// - `ExtInt.IRQ_RISING` - trigger on a rising edge; /// - `ExtInt.IRQ_FALLING` - trigger on a falling edge; /// - `ExtInt.IRQ_RISING_FALLING` - trigger on a rising or falling edge. /// - `pull` can be one of: /// - `pyb.Pin.PULL_NONE` - no pull up or down resistors; /// - `pyb.Pin.PULL_UP` - enable the pull-up resistor; /// - `pyb.Pin.PULL_DOWN` - enable the pull-down resistor. /// - `callback` is the function to call when the interrupt triggers. The /// callback function must accept exactly 1 argument, which is the line that /// triggered the interrupt. STATIC const mp_arg_t pyb_extint_make_new_args[] = { { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_pull, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; #define PYB_EXTINT_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(pyb_extint_make_new_args) STATIC mp_obj_t extint_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // type_in == extint_obj_type // parse args mp_arg_val_t vals[PYB_EXTINT_MAKE_NEW_NUM_ARGS]; mp_arg_parse_all_kw_array(n_args, n_kw, args, PYB_EXTINT_MAKE_NEW_NUM_ARGS, pyb_extint_make_new_args, vals); extint_obj_t *self = m_new_obj(extint_obj_t); self->base.type = type; self->line = extint_register(vals[0].u_obj, vals[1].u_int, vals[2].u_int, vals[3].u_obj, false); return MP_OBJ_FROM_PTR(self); } STATIC void extint_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { extint_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->line); } STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&extint_obj_line_obj) }, { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&extint_obj_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&extint_obj_disable_obj) }, { MP_ROM_QSTR(MP_QSTR_swint), MP_ROM_PTR(&extint_obj_swint_obj) }, { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&extint_regs_obj) }, // class constants /// \constant IRQ_RISING - interrupt on a rising edge /// \constant IRQ_FALLING - interrupt on a falling edge /// \constant IRQ_RISING_FALLING - interrupt on a rising or falling edge { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_MODE_IT_RISING) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_MODE_IT_FALLING) }, { MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(GPIO_MODE_IT_RISING_FALLING) }, { MP_ROM_QSTR(MP_QSTR_EVT_RISING), MP_ROM_INT(GPIO_MODE_EVT_RISING) }, { MP_ROM_QSTR(MP_QSTR_EVT_FALLING), MP_ROM_INT(GPIO_MODE_EVT_FALLING) }, { MP_ROM_QSTR(MP_QSTR_EVT_RISING_FALLING), MP_ROM_INT(GPIO_MODE_EVT_RISING_FALLING) }, }; STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table); const mp_obj_type_t extint_type = { { &mp_type_type }, .name = MP_QSTR_ExtInt, .print = extint_obj_print, .make_new = extint_make_new, .locals_dict = (mp_obj_dict_t*)&extint_locals_dict, }; void extint_init0(void) { for (int i = 0; i < PYB_EXTI_NUM_VECTORS; i++) { if (MP_STATE_PORT(pyb_extint_callback)[i] == MP_OBJ_SENTINEL) { continue; } MP_STATE_PORT(pyb_extint_callback)[i] = mp_const_none; pyb_extint_mode[i] = EXTI_Mode_Interrupt; } } // Interrupt handler void Handle_EXTI_Irq(uint32_t line) { if (__HAL_GPIO_EXTI_GET_FLAG(1 << line)) { __HAL_GPIO_EXTI_CLEAR_FLAG(1 << line); if (line < EXTI_NUM_VECTORS) { mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line]; #if MICROPY_PY_NETWORK_CYW43 && defined(pyb_pin_WL_HOST_WAKE) if (pyb_extint_callback_arg[line] == MP_OBJ_FROM_PTR(pyb_pin_WL_HOST_WAKE)) { extern void (*cyw43_poll)(void); if (cyw43_poll) { pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); } return; } #endif if (*cb != mp_const_none) { // If it's a soft IRQ handler then just schedule callback for later if (!pyb_extint_hard_irq[line]) { mp_sched_schedule(*cb, pyb_extint_callback_arg[line]); return; } mp_sched_lock(); // When executing code within a handler we must lock the GC to prevent // any memory allocations. We must also catch any exceptions. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_1(*cb, pyb_extint_callback_arg[line]); nlr_pop(); } else { // Uncaught exception; disable the callback so it doesn't run again. *cb = mp_const_none; extint_disable(line); mp_printf(MICROPY_ERROR_PRINTER, "uncaught exception in ExtInt interrupt handler line %u\n", (unsigned int)line); mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } gc_unlock(); mp_sched_unlock(); } } } } micropython-1.12/ports/stm32/extint.h000066400000000000000000000052461357706137100176340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_EXTINT_H #define MICROPY_INCLUDED_STM32_EXTINT_H #include "py/mphal.h" // Vectors 0-15 are for regular pins // Vectors 16-22 are for internal sources. // // Use the following constants for the internal sources: #define EXTI_PVD_OUTPUT (16) #if defined(STM32L4) #define EXTI_RTC_ALARM (18) #define EXTI_USB_OTG_FS_WAKEUP (17) #else #define EXTI_RTC_ALARM (17) #define EXTI_USB_OTG_FS_WAKEUP (18) #endif #define EXTI_ETH_WAKEUP (19) #define EXTI_USB_OTG_HS_WAKEUP (20) #if defined(STM32F0) || defined(STM32L4) #define EXTI_RTC_TIMESTAMP (19) #define EXTI_RTC_WAKEUP (20) #elif defined(STM32H7) || defined(STM32WB) #define EXTI_RTC_TIMESTAMP (18) #define EXTI_RTC_WAKEUP (19) #else #define EXTI_RTC_TIMESTAMP (21) #define EXTI_RTC_WAKEUP (22) #endif #if defined(STM32F7) #define EXTI_LPTIM1_ASYNC_EVENT (23) #endif #define EXTI_NUM_VECTORS (PYB_EXTI_NUM_VECTORS) void extint_init0(void); uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t callback_obj, bool override_callback_obj); void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_obj_t callback_obj); void extint_enable(uint line); void extint_disable(uint line); void extint_swint(uint line); void extint_trigger_mode(uint line, uint32_t mode); void Handle_EXTI_Irq(uint32_t line); extern const mp_obj_type_t extint_type; #endif // MICROPY_INCLUDED_STM32_EXTINT_H micropython-1.12/ports/stm32/factoryreset.c000066400000000000000000000105031357706137100210160ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/vfs_fat.h" #include "systick.h" #include "led.h" #include "storage.h" #include "factoryreset.h" #if MICROPY_HW_ENABLE_STORAGE static const char fresh_boot_py[] = "# boot.py -- run on boot-up\r\n" "# can run arbitrary Python, but best to keep it minimal\r\n" "\r\n" "import machine\r\n" "import pyb\r\n" "pyb.country('US') # ISO 3166-1 Alpha-2 code, eg US, GB, DE, AU\r\n" "#pyb.main('main.py') # main script to run after this one\r\n" #if MICROPY_HW_ENABLE_USB "#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n" "#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse\r\n" #endif ; static const char fresh_main_py[] = "# main.py -- put your code here!\r\n" ; #if MICROPY_HW_ENABLE_USB static const char fresh_pybcdc_inf[] = #include "genhdr/pybcdc_inf.h" ; static const char fresh_readme_txt[] = "This is a MicroPython board\r\n" "\r\n" "You can get started right away by writing your Python code in 'main.py'.\r\n" "\r\n" "For a serial prompt:\r\n" " - Windows: you need to go to 'Device manager', right click on the unknown device,\r\n" " then update the driver software, using the 'pybcdc.inf' file found on this drive.\r\n" " Then use a terminal program like Hyperterminal or putty.\r\n" " - Mac OS X: use the command: screen /dev/tty.usbmodem*\r\n" " - Linux: use the command: screen /dev/ttyACM0\r\n" "\r\n" "Please visit http://micropython.org/help/ for further help.\r\n" ; #endif typedef struct _factory_file_t { const char *name; size_t len; const char *data; } factory_file_t; static const factory_file_t factory_files[] = { {"boot.py", sizeof(fresh_boot_py) - 1, fresh_boot_py}, {"main.py", sizeof(fresh_main_py) - 1, fresh_main_py}, #if MICROPY_HW_ENABLE_USB {"pybcdc.inf", sizeof(fresh_pybcdc_inf) - 1, fresh_pybcdc_inf}, {"README.txt", sizeof(fresh_readme_txt) - 1, fresh_readme_txt}, #endif }; MP_WEAK void factory_reset_make_files(FATFS *fatfs) { for (int i = 0; i < MP_ARRAY_SIZE(factory_files); ++i) { const factory_file_t *f = &factory_files[i]; FIL fp; FRESULT res = f_open(fatfs, &fp, f->name, FA_WRITE | FA_CREATE_ALWAYS); if (res == FR_OK) { UINT n; f_write(&fp, f->data, f->len, &n); f_close(&fp); } } } MP_WEAK int factory_reset_create_filesystem(void) { // LED on to indicate creation of local filesystem led_state(PYB_LED_GREEN, 1); uint32_t start_tick = HAL_GetTick(); fs_user_mount_t vfs; pyb_flash_init_vfs(&vfs); uint8_t working_buf[FF_MAX_SS]; FRESULT res = f_mkfs(&vfs.fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); if (res != FR_OK) { mp_printf(&mp_plat_print, "MPY: can't create flash filesystem\n"); return -MP_ENODEV; } // Set label f_setlabel(&vfs.fatfs, MICROPY_HW_FLASH_FS_LABEL); // Populate the filesystem with factory files factory_reset_make_files(&vfs.fatfs); // Keep LED on for at least 200ms systick_wait_at_least(start_tick, 200); led_state(PYB_LED_GREEN, 0); return 0; // success } #endif // MICROPY_HW_ENABLE_STORAGE micropython-1.12/ports/stm32/factoryreset.h000066400000000000000000000027141357706137100210300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_FACTORYRESET_H #define MICROPY_INCLUDED_STM32_FACTORYRESET_H #include "lib/oofatfs/ff.h" void factory_reset_make_files(FATFS *fatfs); int factory_reset_create_filesystem(void); #endif // MICROPY_INCLUDED_STM32_FACTORYRESET_H micropython-1.12/ports/stm32/fatfs_port.c000066400000000000000000000035461357706137100204640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "rtc.h" MP_WEAK DWORD get_fattime(void) { #if MICROPY_HW_ENABLE_RTC rtc_init_finalise(); RTC_TimeTypeDef time; RTC_DateTypeDef date; HAL_RTC_GetTime(&RTCHandle, &time, RTC_FORMAT_BIN); HAL_RTC_GetDate(&RTCHandle, &date, RTC_FORMAT_BIN); return ((2000 + date.Year - 1980) << 25) | ((date.Month) << 21) | ((date.Date) << 16) | ((time.Hours) << 11) | ((time.Minutes) << 5) | (time.Seconds / 2); #else // Jan 1st, 2018 at midnight. Not sure what timezone. return ((2018 - 1980) << 25) | ((1) << 21) | ((1) << 16) | ((0) << 11) | ((0) << 5) | (0 / 2); #endif } micropython-1.12/ports/stm32/fdcan.c000066400000000000000000000266671357706137100174010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "can.h" #include "irq.h" #if MICROPY_HW_ENABLE_CAN && MICROPY_HW_ENABLE_FDCAN #define FDCAN_ELEMENT_MASK_STDID (0x1ffc0000) // Standard Identifier #define FDCAN_ELEMENT_MASK_EXTID (0x1fffffff) // Extended Identifier #define FDCAN_ELEMENT_MASK_RTR (0x20000000) // Remote Transmission Request #define FDCAN_ELEMENT_MASK_XTD (0x40000000) // Extended Identifier #define FDCAN_ELEMENT_MASK_ESI (0x80000000) // Error State Indicator #define FDCAN_ELEMENT_MASK_TS (0x0000ffff) // Timestamp #define FDCAN_ELEMENT_MASK_DLC (0x000f0000) // Data Length Code #define FDCAN_ELEMENT_MASK_BRS (0x00100000) // Bit Rate Switch #define FDCAN_ELEMENT_MASK_FDF (0x00200000) // FD Format #define FDCAN_ELEMENT_MASK_FIDX (0x7f000000) // Filter Index #define FDCAN_ELEMENT_MASK_ANMF (0x80000000) // Accepted Non-matching Frame bool can_init(pyb_can_obj_t *can_obj, uint32_t mode, uint32_t prescaler, uint32_t sjw, uint32_t bs1, uint32_t bs2, bool auto_restart) { (void)auto_restart; FDCAN_InitTypeDef *init = &can_obj->can.Init; init->FrameFormat = FDCAN_FRAME_CLASSIC; init->Mode = mode; init->NominalPrescaler = prescaler; // tq = NominalPrescaler x (1/fdcan_ker_ck) init->NominalSyncJumpWidth = sjw; init->NominalTimeSeg1 = bs1; // NominalTimeSeg1 = Propagation_segment + Phase_segment_1 init->NominalTimeSeg2 = bs2; init->AutoRetransmission = ENABLE; init->TransmitPause = DISABLE; init->ProtocolException = ENABLE; // The Message RAM is shared between CAN1 and CAN2. Setting the offset to half // the Message RAM for the second CAN and using half the resources for each CAN. if (can_obj->can_id == PYB_CAN_1) { init->MessageRAMOffset = 0; } else { init->MessageRAMOffset = 2560/2; } init->StdFiltersNbr = 64; // 128 / 2 init->ExtFiltersNbr = 0; // Not used init->TxEventsNbr = 16; // 32 / 2 init->RxBuffersNbr = 32; // 64 / 2 init->TxBuffersNbr = 16; // 32 / 2 init->RxFifo0ElmtsNbr = 64; // 128 / 2 init->RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; init->RxFifo1ElmtsNbr = 64; // 128 / 2 init->RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; init->TxFifoQueueElmtsNbr = 16; // Tx fifo elements init->TxElmtSize = FDCAN_DATA_BYTES_8; init->TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; FDCAN_GlobalTypeDef *CANx = NULL; const pin_obj_t *pins[2]; switch (can_obj->can_id) { #if defined(MICROPY_HW_CAN1_TX) case PYB_CAN_1: CANx = FDCAN1; pins[0] = MICROPY_HW_CAN1_TX; pins[1] = MICROPY_HW_CAN1_RX; break; #endif #if defined(MICROPY_HW_CAN2_TX) case PYB_CAN_2: CANx = FDCAN2; pins[0] = MICROPY_HW_CAN2_TX; pins[1] = MICROPY_HW_CAN2_RX; break; #endif default: return false; } // Enable FDCAN clock __HAL_RCC_FDCAN_CLK_ENABLE(); // init GPIO uint32_t pin_mode = MP_HAL_PIN_MODE_ALT; uint32_t pin_pull = MP_HAL_PIN_PULL_UP; for (int i = 0; i < 2; ++i) { if (!mp_hal_pin_config_alt(pins[i], pin_mode, pin_pull, AF_FN_CAN, can_obj->can_id)) { return false; } } // init CANx can_obj->can.Instance = CANx; HAL_FDCAN_Init(&can_obj->can); // Disable acceptance of non-matching frames (enabled by default) HAL_FDCAN_ConfigGlobalFilter(&can_obj->can, FDCAN_REJECT, FDCAN_REJECT, DISABLE, DISABLE); // The configuration registers are locked after CAN is started. HAL_FDCAN_Start(&can_obj->can); // Reset all filters for (int f = 0; f < 64; ++f) { can_clearfilter(can_obj, f, 0); } can_obj->is_enabled = true; can_obj->num_error_warning = 0; can_obj->num_error_passive = 0; can_obj->num_bus_off = 0; switch (can_obj->can_id) { case PYB_CAN_1: NVIC_SetPriority(FDCAN1_IT0_IRQn, IRQ_PRI_CAN); HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); NVIC_SetPriority(FDCAN1_IT1_IRQn, IRQ_PRI_CAN); HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn); break; case PYB_CAN_2: NVIC_SetPriority(FDCAN2_IT0_IRQn, IRQ_PRI_CAN); HAL_NVIC_EnableIRQ(FDCAN2_IT0_IRQn); NVIC_SetPriority(FDCAN2_IT1_IRQn, IRQ_PRI_CAN); HAL_NVIC_EnableIRQ(FDCAN2_IT1_IRQn); break; default: return false; } __HAL_FDCAN_ENABLE_IT(&can_obj->can, FDCAN_IT_BUS_OFF | FDCAN_IT_ERROR_WARNING | FDCAN_IT_ERROR_PASSIVE); __HAL_FDCAN_ENABLE_IT(&can_obj->can, FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO1_NEW_MESSAGE); __HAL_FDCAN_ENABLE_IT(&can_obj->can, FDCAN_IT_RX_FIFO0_MESSAGE_LOST | FDCAN_IT_RX_FIFO1_MESSAGE_LOST); __HAL_FDCAN_ENABLE_IT(&can_obj->can, FDCAN_IT_RX_FIFO0_FULL | FDCAN_IT_RX_FIFO1_FULL); return true; } void can_deinit(pyb_can_obj_t *self) { self->is_enabled = false; HAL_FDCAN_DeInit(&self->can); if (self->can.Instance == FDCAN1) { HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn); HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn); // TODO check if FDCAN2 is used. __HAL_RCC_FDCAN_FORCE_RESET(); __HAL_RCC_FDCAN_RELEASE_RESET(); __HAL_RCC_FDCAN_CLK_DISABLE(); #if defined(MICROPY_HW_CAN2_TX) } else if (self->can.Instance == FDCAN2) { HAL_NVIC_DisableIRQ(FDCAN2_IT0_IRQn); HAL_NVIC_DisableIRQ(FDCAN2_IT1_IRQn); // TODO check if FDCAN2 is used. __HAL_RCC_FDCAN_FORCE_RESET(); __HAL_RCC_FDCAN_RELEASE_RESET(); __HAL_RCC_FDCAN_CLK_DISABLE(); #endif } } void can_clearfilter(pyb_can_obj_t *self, uint32_t f, uint8_t bank) { if (self && self->can.Instance) { FDCAN_FilterTypeDef filter = {0}; filter.IdType = FDCAN_STANDARD_ID; filter.FilterIndex = f; filter.FilterConfig = FDCAN_FILTER_DISABLE; HAL_FDCAN_ConfigFilter(&self->can, &filter); } } int can_receive(FDCAN_HandleTypeDef *can, int fifo, FDCAN_RxHeaderTypeDef *hdr, uint8_t *data, uint32_t timeout_ms) { volatile uint32_t *rxf, *rxa; if (fifo == FDCAN_RX_FIFO0) { rxf = &can->Instance->RXF0S; rxa = &can->Instance->RXF0A; } else { rxf = &can->Instance->RXF1S; rxa = &can->Instance->RXF1A; } // Wait for a message to become available, with timeout uint32_t start = HAL_GetTick(); while ((*rxf & 7) == 0) { MICROPY_EVENT_POLL_HOOK if (HAL_GetTick() - start >= timeout_ms) { return -MP_ETIMEDOUT; } } // Get pointer to incoming message uint32_t index = (can->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> 8; uint32_t *address = (uint32_t*)(can->msgRam.RxFIFO0SA + (index * can->Init.RxFifo0ElmtSize * 4)); // Parse header of message hdr->IdType = *address & FDCAN_ELEMENT_MASK_XTD; if(hdr->IdType == FDCAN_STANDARD_ID) { hdr->Identifier = (*address & FDCAN_ELEMENT_MASK_STDID) >> 18; } else { hdr->Identifier = *address & FDCAN_ELEMENT_MASK_EXTID; } hdr->RxFrameType = *address & FDCAN_ELEMENT_MASK_RTR; hdr->ErrorStateIndicator = *address++ & FDCAN_ELEMENT_MASK_ESI; hdr->RxTimestamp = *address & FDCAN_ELEMENT_MASK_TS; hdr->DataLength = (*address & FDCAN_ELEMENT_MASK_DLC) >> 16; hdr->BitRateSwitch = *address & FDCAN_ELEMENT_MASK_BRS; hdr->FDFormat = *address & FDCAN_ELEMENT_MASK_FDF; hdr->FilterIndex = (*address & FDCAN_ELEMENT_MASK_FIDX) >> 24; hdr->IsFilterMatchingFrame = (*address++ & FDCAN_ELEMENT_MASK_ANMF) >> 31; // Copy data uint8_t *pdata = (uint8_t*)address; for(uint32_t i = 0; i < 8; ++i) { // TODO use DLCtoBytes[hdr->DataLength] for length > 8 *data++ = *pdata++; } // Release (free) message from FIFO *rxa = index; return 0; // success } STATIC void can_rx_irq_handler(uint can_id, uint fifo_id) { mp_obj_t callback; pyb_can_obj_t *self; mp_obj_t irq_reason = MP_OBJ_NEW_SMALL_INT(0); byte *state; self = MP_STATE_PORT(pyb_can_obj_all)[can_id - 1]; if (fifo_id == FDCAN_RX_FIFO0) { callback = self->rxcallback0; state = &self->rx_state0; } else { callback = self->rxcallback1; state = &self->rx_state1; } switch (*state) { case RX_STATE_FIFO_EMPTY: __HAL_FDCAN_DISABLE_IT(&self->can, (fifo_id == FDCAN_RX_FIFO0) ? FDCAN_IT_RX_FIFO0_NEW_MESSAGE : FDCAN_IT_RX_FIFO1_NEW_MESSAGE); irq_reason = MP_OBJ_NEW_SMALL_INT(0); *state = RX_STATE_MESSAGE_PENDING; break; case RX_STATE_MESSAGE_PENDING: __HAL_FDCAN_DISABLE_IT(&self->can, (fifo_id == FDCAN_RX_FIFO0) ? FDCAN_IT_RX_FIFO0_FULL : FDCAN_IT_RX_FIFO1_FULL); __HAL_FDCAN_CLEAR_FLAG(&self->can, (fifo_id == FDCAN_RX_FIFO0) ? FDCAN_FLAG_RX_FIFO0_FULL : FDCAN_FLAG_RX_FIFO1_FULL); irq_reason = MP_OBJ_NEW_SMALL_INT(1); *state = RX_STATE_FIFO_FULL; break; case RX_STATE_FIFO_FULL: __HAL_FDCAN_DISABLE_IT(&self->can, (fifo_id == FDCAN_RX_FIFO0) ? FDCAN_IT_RX_FIFO0_MESSAGE_LOST : FDCAN_IT_RX_FIFO1_MESSAGE_LOST); __HAL_FDCAN_CLEAR_FLAG(&self->can, (fifo_id == FDCAN_RX_FIFO0) ? FDCAN_FLAG_RX_FIFO0_MESSAGE_LOST : FDCAN_FLAG_RX_FIFO1_MESSAGE_LOST); irq_reason = MP_OBJ_NEW_SMALL_INT(2); *state = RX_STATE_FIFO_OVERFLOW; break; case RX_STATE_FIFO_OVERFLOW: // This should never happen break; } pyb_can_handle_callback(self, fifo_id, callback, irq_reason); } #if defined(MICROPY_HW_CAN1_TX) void FDCAN1_IT0_IRQHandler(void) { IRQ_ENTER(FDCAN1_IT0_IRQn); can_rx_irq_handler(PYB_CAN_1, FDCAN_RX_FIFO0); IRQ_EXIT(FDCAN1_IT0_IRQn); } void FDCAN1_IT1_IRQHandler(void) { IRQ_ENTER(FDCAN1_IT1_IRQn); can_rx_irq_handler(PYB_CAN_1, FDCAN_RX_FIFO1); IRQ_EXIT(FDCAN1_IT1_IRQn); } #endif #if defined(MICROPY_HW_CAN2_TX) void FDCAN2_IT0_IRQHandler(void) { IRQ_ENTER(FDCAN2_IT0_IRQn); can_rx_irq_handler(PYB_CAN_2, FDCAN_RX_FIFO0); IRQ_EXIT(FDCAN2_IT0_IRQn); } void FDCAN2_IT1_IRQHandler(void) { IRQ_ENTER(FDCAN2_IT1_IRQn); can_rx_irq_handler(PYB_CAN_2, FDCAN_RX_FIFO1); IRQ_EXIT(FDCAN2_IT1_IRQn); } #endif #endif // MICROPY_HW_ENABLE_CAN && MICROPY_HW_ENABLE_FDCAN micropython-1.12/ports/stm32/flash.c000066400000000000000000000274001357706137100174050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #include "py/misc.h" #include "flash.h" typedef struct { uint32_t base_address; uint32_t sector_size; uint32_t sector_count; } flash_layout_t; #if defined(STM32F0) static const flash_layout_t flash_layout[] = { { FLASH_BASE, FLASH_PAGE_SIZE, (FLASH_BANK1_END + 1 - FLASH_BASE) / FLASH_PAGE_SIZE }, }; #elif defined(STM32F4) static const flash_layout_t flash_layout[] = { { 0x08000000, 0x04000, 4 }, { 0x08010000, 0x10000, 1 }, { 0x08020000, 0x20000, 3 }, #if defined(FLASH_SECTOR_8) { 0x08080000, 0x20000, 4 }, #endif #if defined(FLASH_SECTOR_12) { 0x08100000, 0x04000, 4 }, { 0x08110000, 0x10000, 1 }, { 0x08120000, 0x20000, 7 }, #endif }; #elif defined(STM32F7) // FLASH_FLAG_PGSERR (Programming Sequence Error) was renamed to // FLASH_FLAG_ERSERR (Erasing Sequence Error) in STM32F7 #define FLASH_FLAG_PGSERR FLASH_FLAG_ERSERR #if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) static const flash_layout_t flash_layout[] = { { 0x08000000, 0x04000, 4 }, { 0x08010000, 0x10000, 1 }, { 0x08020000, 0x20000, 3 }, }; #else static const flash_layout_t flash_layout[] = { { 0x08000000, 0x08000, 4 }, { 0x08020000, 0x20000, 1 }, { 0x08040000, 0x40000, 3 }, }; #endif #elif defined(STM32L0) || defined(STM32L4) || defined(STM32WB) static const flash_layout_t flash_layout[] = { { (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 }, }; #elif defined(STM32H7) static const flash_layout_t flash_layout[] = { { 0x08000000, 0x20000, 16 }, }; #else #error Unsupported processor #endif #if (defined(STM32L4) && defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32H7) // get the bank of a given flash address static uint32_t get_bank(uint32_t addr) { #if defined(STM32H7) if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_SWAP_BANK) == 0) { #else if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) { #endif // no bank swap if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) { return FLASH_BANK_1; } else { return FLASH_BANK_2; } } else { // bank swap if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) { return FLASH_BANK_2; } else { return FLASH_BANK_1; } } } #if (defined(STM32L4) && defined(SYSCFG_MEMRMP_FB_MODE)) // get the page of a given flash address static uint32_t get_page(uint32_t addr) { if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) { // bank 1 return (addr - FLASH_BASE) / FLASH_PAGE_SIZE; } else { // bank 2 return (addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE; } } #endif #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) static uint32_t get_page(uint32_t addr) { return (addr - FLASH_BASE) / FLASH_PAGE_SIZE; } #endif uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size) { if (addr >= flash_layout[0].base_address) { uint32_t sector_index = 0; for (int i = 0; i < MP_ARRAY_SIZE(flash_layout); ++i) { for (int j = 0; j < flash_layout[i].sector_count; ++j) { uint32_t sector_start_next = flash_layout[i].base_address + (j + 1) * flash_layout[i].sector_size; if (addr < sector_start_next) { if (start_addr != NULL) { *start_addr = flash_layout[i].base_address + j * flash_layout[i].sector_size; } if (size != NULL) { *size = flash_layout[i].sector_size; } return sector_index; } ++sector_index; } } } return 0; } void flash_erase(uint32_t flash_dest, uint32_t num_word32) { // check there is something to write if (num_word32 == 0) { return; } // unlock HAL_FLASH_Unlock(); FLASH_EraseInitTypeDef EraseInitStruct; #if defined(STM32F0) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; #elif defined(STM32L0) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Page = get_page(flash_dest); EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; #elif defined(STM32L4) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); // erase the sector(s) // The sector returned by flash_get_sector_info can not be used // as the flash has on each bank 0/1 pages 0..255 EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Banks = get_bank(flash_dest); EraseInitStruct.Page = get_page(flash_dest); EraseInitStruct.NbPages = get_page(flash_dest + 4 * num_word32 - 1) - EraseInitStruct.Page + 1;; #else // Clear pending flags (if any) #if defined(STM32H7) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2); #else __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); #endif // erase the sector(s) EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V #if defined(STM32H7) EraseInitStruct.Banks = get_bank(flash_dest); #endif EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL); EraseInitStruct.NbSectors = flash_get_sector_info(flash_dest + 4 * num_word32 - 1, NULL, NULL) - EraseInitStruct.Sector + 1; #endif uint32_t SectorError = 0; if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { // error occurred during sector erase HAL_FLASH_Lock(); // lock the flash return; } } /* // erase the sector using an interrupt void flash_erase_it(uint32_t flash_dest, uint32_t num_word32) { // check there is something to write if (num_word32 == 0) { return; } // unlock HAL_FLASH_Unlock(); // Clear pending flags (if any) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); // erase the sector(s) FLASH_EraseInitTypeDef EraseInitStruct; EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL); EraseInitStruct.NbSectors = flash_get_sector_info(flash_dest + 4 * num_word32 - 1, NULL, NULL) - EraseInitStruct.Sector + 1; if (HAL_FLASHEx_Erase_IT(&EraseInitStruct) != HAL_OK) { // error occurred during sector erase HAL_FLASH_Lock(); // lock the flash return; } } */ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { #if defined(STM32L4) || defined(STM32WB) // program the flash uint64 by uint64 for (int i = 0; i < num_word32 / 2; i++) { uint64_t val = *(uint64_t*)src; if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val) != HAL_OK) { // error occurred during flash write HAL_FLASH_Lock(); // lock the flash return; } flash_dest += 8; src += 2; } if ((num_word32 & 0x01) == 1) { uint64_t val = *(uint64_t*)flash_dest; val = (val & 0xffffffff00000000uL) | (*src); if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val) != HAL_OK) { // error occurred during flash write HAL_FLASH_Lock(); // lock the flash return; } } #elif defined(STM32H7) // program the flash 256 bits at a time for (int i = 0; i < num_word32 / 8; i++) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, flash_dest, (uint64_t)(uint32_t)src) != HAL_OK) { // error occurred during flash write HAL_FLASH_Lock(); // lock the flash return; } flash_dest += 32; src += 8; } #else // program the flash word by word for (int i = 0; i < num_word32; i++) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, flash_dest, *src) != HAL_OK) { // error occurred during flash write HAL_FLASH_Lock(); // lock the flash return; } flash_dest += 4; src += 1; } #endif // lock the flash HAL_FLASH_Lock(); } /* use erase, then write void flash_erase_and_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { // check there is something to write if (num_word32 == 0) { return; } // unlock HAL_FLASH_Unlock(); // Clear pending flags (if any) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); // erase the sector(s) FLASH_EraseInitTypeDef EraseInitStruct; EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL); EraseInitStruct.NbSectors = flash_get_sector_info(flash_dest + 4 * num_word32 - 1, NULL, NULL) - EraseInitStruct.Sector + 1; uint32_t SectorError = 0; if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { // error occurred during sector erase HAL_FLASH_Lock(); // lock the flash return; } // program the flash word by word for (int i = 0; i < num_word32; i++) { if (HAL_FLASH_Program(TYPEPROGRAM_WORD, flash_dest, *src) != HAL_OK) { // error occurred during flash write HAL_FLASH_Lock(); // lock the flash return; } flash_dest += 4; src += 1; } // lock the flash HAL_FLASH_Lock(); } */ micropython-1.12/ports/stm32/flash.h000066400000000000000000000030521357706137100174070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_FLASH_H #define MICROPY_INCLUDED_STM32_FLASH_H uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size); void flash_erase(uint32_t flash_dest, uint32_t num_word32); void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32); #endif // MICROPY_INCLUDED_STM32_FLASH_H micropython-1.12/ports/stm32/flashbdev.c000066400000000000000000000312221357706137100202430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "py/mperrno.h" #include "irq.h" #include "led.h" #include "flash.h" #include "storage.h" #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE // Here we try to automatically configure the location and size of the flash // pages to use for the internal storage. We also configure the location of the // cache used for writing. #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) #define CACHE_MEM_START_ADDR (0x10000000) // CCM data RAM, 64k #define FLASH_SECTOR_SIZE_MAX (0x10000) // 64k max, size of CCM #define FLASH_MEM_SEG1_START_ADDR (0x08004000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (224) // sectors 1,2,3,4: 16k+16k+16k+64k=112k // enable this to get an extra 64k of storage (uses the last sector of the flash) #if 0 #define FLASH_MEM_SEG2_START_ADDR (0x080e0000) // sector 11 #define FLASH_MEM_SEG2_NUM_BLOCKS (128) // sector 11: 128k #endif #elif defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) STATIC byte flash_cache_mem[0x4000] __attribute__((aligned(4))); // 16k #define CACHE_MEM_START_ADDR (&flash_cache_mem[0]) #define FLASH_SECTOR_SIZE_MAX (0x4000) // 16k max due to size of cache buffer #define FLASH_MEM_SEG1_START_ADDR (0x08004000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (128) // sectors 1,2,3,4: 16k+16k+16k+16k(of 64k)=64k #elif defined(STM32F413xx) #define CACHE_MEM_START_ADDR (0x10000000) // SRAM2 data RAM, 64k #define FLASH_SECTOR_SIZE_MAX (0x10000) // 64k max, size of SRAM2 #define FLASH_MEM_SEG1_START_ADDR (0x08004000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (352) // sectors 1,2,3,4,5: 16k+16k+16k+64k+64k(of 128k)=176k #define FLASH_MEM_SEG2_START_ADDR (0x08040000) // sector 6 #define FLASH_MEM_SEG2_NUM_BLOCKS (128) // sector 6: 64k(of 128k). Filesystem 176K + 64K = 240K #elif defined(STM32F429xx) #define CACHE_MEM_START_ADDR (0x10000000) // CCM data RAM, 64k #define FLASH_SECTOR_SIZE_MAX (0x10000) // 64k max, size of CCM #define FLASH_MEM_SEG1_START_ADDR (0x08004000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (224) // sectors 1,2,3,4: 16k+16k+16k+64k=112k #elif defined(STM32F439xx) #define CACHE_MEM_START_ADDR (0x10000000) // CCM data RAM, 64k #define FLASH_SECTOR_SIZE_MAX (0x10000) // 64k max, size of CCM #define FLASH_MEM_SEG1_START_ADDR (0x08100000) // sector 12 #define FLASH_MEM_SEG1_NUM_BLOCKS (384) // sectors 12,13,14,15,16,17: 16k+16k+16k+16k+64k+64k(of 128k)=192k #define FLASH_MEM_SEG2_START_ADDR (0x08140000) // sector 18 #define FLASH_MEM_SEG2_NUM_BLOCKS (128) // sector 18: 64k(of 128k) #elif defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) #define CACHE_MEM_START_ADDR (0x20000000) // DTCM data RAM, 64k #define FLASH_SECTOR_SIZE_MAX (0x10000) // 64k max #define FLASH_MEM_SEG1_START_ADDR (0x08004000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (224) // sectors 1,2,3,4: 16k+16k+16k+64k=112k #elif defined(STM32F746xx) || defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) // The STM32F746 doesn't really have CCRAM, so we use the 64K DTCM for this. #define CACHE_MEM_START_ADDR (0x20000000) // DTCM data RAM, 64k #define FLASH_SECTOR_SIZE_MAX (0x08000) // 32k max #define FLASH_MEM_SEG1_START_ADDR (0x08008000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (192) // sectors 1,2,3: 32k+32k+32=96k #elif defined(STM32H743xx) // The STM32H743 flash sectors are 128K #define CACHE_MEM_START_ADDR (0x20000000) // DTCM data RAM, 128k #define FLASH_SECTOR_SIZE_MAX (0x20000) // 128k max #define FLASH_MEM_SEG1_START_ADDR (0x08020000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (256) // Sector 1: 128k / 512b = 256 blocks #elif defined(STM32L432xx) || \ defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) || \ defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx) || \ defined(STM32WB) // The STM32L4xx doesn't have CCRAM, so we use SRAM2 for this, although // actual location and size is defined by the linker script. extern uint8_t _flash_fs_start; extern uint8_t _flash_fs_end; extern uint8_t _ram_fs_cache_start[]; // size determined by linker file extern uint8_t _ram_fs_cache_end[]; #define CACHE_MEM_START_ADDR ((uintptr_t)&_ram_fs_cache_start[0]) #define FLASH_SECTOR_SIZE_MAX (&_ram_fs_cache_end[0] - &_ram_fs_cache_start[0]) // 2k max #define FLASH_MEM_SEG1_START_ADDR ((long)&_flash_fs_start) #define FLASH_MEM_SEG1_NUM_BLOCKS ((&_flash_fs_end - &_flash_fs_start) / 512) #else #error "no internal flash storage support for this MCU" #endif #if !defined(FLASH_MEM_SEG2_START_ADDR) #define FLASH_MEM_SEG2_START_ADDR (0) // no second segment #define FLASH_MEM_SEG2_NUM_BLOCKS (0) // no second segment #endif #define FLASH_FLAG_DIRTY (1) #define FLASH_FLAG_FORCE_WRITE (2) #define FLASH_FLAG_ERASED (4) static __IO uint8_t flash_flags = 0; static uint32_t flash_cache_sector_id; static uint32_t flash_cache_sector_start; static uint32_t flash_cache_sector_size; static uint32_t flash_tick_counter_last_write; static void flash_bdev_irq_handler(void); int32_t flash_bdev_ioctl(uint32_t op, uint32_t arg) { (void)arg; switch (op) { case BDEV_IOCTL_INIT: flash_flags = 0; flash_cache_sector_id = 0; flash_tick_counter_last_write = 0; return 0; case BDEV_IOCTL_NUM_BLOCKS: return FLASH_MEM_SEG1_NUM_BLOCKS + FLASH_MEM_SEG2_NUM_BLOCKS; case BDEV_IOCTL_IRQ_HANDLER: flash_bdev_irq_handler(); return 0; case BDEV_IOCTL_SYNC: { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access if (flash_flags & FLASH_FLAG_DIRTY) { flash_flags |= FLASH_FLAG_FORCE_WRITE; while (flash_flags & FLASH_FLAG_DIRTY) { flash_bdev_irq_handler(); } } restore_irq_pri(basepri); return 0; } } return -MP_EINVAL; } static uint8_t *flash_cache_get_addr_for_write(uint32_t flash_addr) { uint32_t flash_sector_start; uint32_t flash_sector_size; uint32_t flash_sector_id = flash_get_sector_info(flash_addr, &flash_sector_start, &flash_sector_size); if (flash_sector_size > FLASH_SECTOR_SIZE_MAX) { flash_sector_size = FLASH_SECTOR_SIZE_MAX; } if (flash_cache_sector_id != flash_sector_id) { flash_bdev_ioctl(BDEV_IOCTL_SYNC, 0); memcpy((void*)CACHE_MEM_START_ADDR, (const void*)flash_sector_start, flash_sector_size); flash_cache_sector_id = flash_sector_id; flash_cache_sector_start = flash_sector_start; flash_cache_sector_size = flash_sector_size; } flash_flags |= FLASH_FLAG_DIRTY; led_state(PYB_LED_RED, 1); // indicate a dirty cache with LED on flash_tick_counter_last_write = HAL_GetTick(); return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start; } static uint8_t *flash_cache_get_addr_for_read(uint32_t flash_addr) { uint32_t flash_sector_start; uint32_t flash_sector_size; uint32_t flash_sector_id = flash_get_sector_info(flash_addr, &flash_sector_start, &flash_sector_size); if (flash_cache_sector_id == flash_sector_id) { // in cache, copy from there return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start; } // not in cache, copy straight from flash return (uint8_t*)flash_addr; } static uint32_t convert_block_to_flash_addr(uint32_t block) { if (block < FLASH_MEM_SEG1_NUM_BLOCKS) { return FLASH_MEM_SEG1_START_ADDR + block * FLASH_BLOCK_SIZE; } if (block < FLASH_MEM_SEG1_NUM_BLOCKS + FLASH_MEM_SEG2_NUM_BLOCKS) { return FLASH_MEM_SEG2_START_ADDR + (block - FLASH_MEM_SEG1_NUM_BLOCKS) * FLASH_BLOCK_SIZE; } // can add more flash segments here if needed, following above pattern // bad block return -1; } static void flash_bdev_irq_handler(void) { if (!(flash_flags & FLASH_FLAG_DIRTY)) { return; } // This code uses interrupts to erase the flash /* if (flash_erase_state == 0) { flash_erase_it(flash_cache_sector_start, flash_cache_sector_size / 4); flash_erase_state = 1; return; } if (flash_erase_state == 1) { // wait for erase // TODO add timeout #define flash_erase_done() (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) == RESET) if (!flash_erase_done()) { return; } flash_erase_state = 2; } */ // This code erases the flash directly, waiting for it to finish if (!(flash_flags & FLASH_FLAG_ERASED)) { flash_erase(flash_cache_sector_start, flash_cache_sector_size / 4); flash_flags |= FLASH_FLAG_ERASED; return; } // If not a forced write, wait at least 5 seconds after last write to flush // On file close and flash unmount we get a forced write, so we can afford to wait a while if ((flash_flags & FLASH_FLAG_FORCE_WRITE) || HAL_GetTick() - flash_tick_counter_last_write >= 5000) { // sync the cache RAM buffer by writing it to the flash page flash_write(flash_cache_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, flash_cache_sector_size / 4); // clear the flash flags now that we have a clean cache flash_flags = 0; // indicate a clean cache with LED off led_state(PYB_LED_RED, 0); } } bool flash_bdev_readblock(uint8_t *dest, uint32_t block) { // non-MBR block, get data from flash memory, possibly via cache uint32_t flash_addr = convert_block_to_flash_addr(block); if (flash_addr == -1) { // bad block number return false; } uint8_t *src = flash_cache_get_addr_for_read(flash_addr); memcpy(dest, src, FLASH_BLOCK_SIZE); return true; } bool flash_bdev_writeblock(const uint8_t *src, uint32_t block) { // non-MBR block, copy to cache uint32_t flash_addr = convert_block_to_flash_addr(block); if (flash_addr == -1) { // bad block number return false; } uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access uint8_t *dest = flash_cache_get_addr_for_write(flash_addr); memcpy(dest, src, FLASH_BLOCK_SIZE); restore_irq_pri(basepri); return true; } int flash_bdev_readblocks_ext(uint8_t *dest, uint32_t block, uint32_t offset, uint32_t len) { // Get data from flash memory, possibly via cache while (len) { uint32_t l = MIN(len, FLASH_BLOCK_SIZE - offset); uint32_t flash_addr = convert_block_to_flash_addr(block); if (flash_addr == -1) { // bad block number return -1; } uint8_t *src = flash_cache_get_addr_for_read(flash_addr + offset); memcpy(dest, src, l); dest += l; block += 1; offset = 0; len -= l; } return 0; } int flash_bdev_writeblocks_ext(const uint8_t *src, uint32_t block, uint32_t offset, uint32_t len) { // Copy to cache while (len) { uint32_t l = MIN(len, FLASH_BLOCK_SIZE - offset); uint32_t flash_addr = convert_block_to_flash_addr(block); if (flash_addr == -1) { // bad block number return -1; } uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access uint8_t *dest = flash_cache_get_addr_for_write(flash_addr + offset); memcpy(dest, src, l); restore_irq_pri(basepri); src += l; block += 1; offset = 0; len -= l; } return 0; } #endif // MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE micropython-1.12/ports/stm32/font_petme128_8x8.h000066400000000000000000000146301357706137100214200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H #define MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H static const uint8_t font_petme128_8x8[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 32= 0x00,0x00,0x00,0x4f,0x4f,0x00,0x00,0x00, // 33=! 0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, // 34=" 0x14,0x7f,0x7f,0x14,0x14,0x7f,0x7f,0x14, // 35=# 0x00,0x24,0x2e,0x6b,0x6b,0x3a,0x12,0x00, // 36=$ 0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00, // 37=% 0x00,0x32,0x7f,0x4d,0x4d,0x77,0x72,0x50, // 38=& 0x00,0x00,0x00,0x04,0x06,0x03,0x01,0x00, // 39=' 0x00,0x00,0x1c,0x3e,0x63,0x41,0x00,0x00, // 40=( 0x00,0x00,0x41,0x63,0x3e,0x1c,0x00,0x00, // 41=) 0x08,0x2a,0x3e,0x1c,0x1c,0x3e,0x2a,0x08, // 42=* 0x00,0x08,0x08,0x3e,0x3e,0x08,0x08,0x00, // 43=+ 0x00,0x00,0x80,0xe0,0x60,0x00,0x00,0x00, // 44=, 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, // 45=- 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, // 46=. 0x00,0x40,0x60,0x30,0x18,0x0c,0x06,0x02, // 47=/ 0x00,0x3e,0x7f,0x49,0x45,0x7f,0x3e,0x00, // 48=0 0x00,0x40,0x44,0x7f,0x7f,0x40,0x40,0x00, // 49=1 0x00,0x62,0x73,0x51,0x49,0x4f,0x46,0x00, // 50=2 0x00,0x22,0x63,0x49,0x49,0x7f,0x36,0x00, // 51=3 0x00,0x18,0x18,0x14,0x16,0x7f,0x7f,0x10, // 52=4 0x00,0x27,0x67,0x45,0x45,0x7d,0x39,0x00, // 53=5 0x00,0x3e,0x7f,0x49,0x49,0x7b,0x32,0x00, // 54=6 0x00,0x03,0x03,0x79,0x7d,0x07,0x03,0x00, // 55=7 0x00,0x36,0x7f,0x49,0x49,0x7f,0x36,0x00, // 56=8 0x00,0x26,0x6f,0x49,0x49,0x7f,0x3e,0x00, // 57=9 0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x00, // 58=: 0x00,0x00,0x80,0xe4,0x64,0x00,0x00,0x00, // 59=; 0x00,0x08,0x1c,0x36,0x63,0x41,0x41,0x00, // 60=< 0x00,0x14,0x14,0x14,0x14,0x14,0x14,0x00, // 61== 0x00,0x41,0x41,0x63,0x36,0x1c,0x08,0x00, // 62=> 0x00,0x02,0x03,0x51,0x59,0x0f,0x06,0x00, // 63=? 0x00,0x3e,0x7f,0x41,0x4d,0x4f,0x2e,0x00, // 64=@ 0x00,0x7c,0x7e,0x0b,0x0b,0x7e,0x7c,0x00, // 65=A 0x00,0x7f,0x7f,0x49,0x49,0x7f,0x36,0x00, // 66=B 0x00,0x3e,0x7f,0x41,0x41,0x63,0x22,0x00, // 67=C 0x00,0x7f,0x7f,0x41,0x63,0x3e,0x1c,0x00, // 68=D 0x00,0x7f,0x7f,0x49,0x49,0x41,0x41,0x00, // 69=E 0x00,0x7f,0x7f,0x09,0x09,0x01,0x01,0x00, // 70=F 0x00,0x3e,0x7f,0x41,0x49,0x7b,0x3a,0x00, // 71=G 0x00,0x7f,0x7f,0x08,0x08,0x7f,0x7f,0x00, // 72=H 0x00,0x00,0x41,0x7f,0x7f,0x41,0x00,0x00, // 73=I 0x00,0x20,0x60,0x41,0x7f,0x3f,0x01,0x00, // 74=J 0x00,0x7f,0x7f,0x1c,0x36,0x63,0x41,0x00, // 75=K 0x00,0x7f,0x7f,0x40,0x40,0x40,0x40,0x00, // 76=L 0x00,0x7f,0x7f,0x06,0x0c,0x06,0x7f,0x7f, // 77=M 0x00,0x7f,0x7f,0x0e,0x1c,0x7f,0x7f,0x00, // 78=N 0x00,0x3e,0x7f,0x41,0x41,0x7f,0x3e,0x00, // 79=O 0x00,0x7f,0x7f,0x09,0x09,0x0f,0x06,0x00, // 80=P 0x00,0x1e,0x3f,0x21,0x61,0x7f,0x5e,0x00, // 81=Q 0x00,0x7f,0x7f,0x19,0x39,0x6f,0x46,0x00, // 82=R 0x00,0x26,0x6f,0x49,0x49,0x7b,0x32,0x00, // 83=S 0x00,0x01,0x01,0x7f,0x7f,0x01,0x01,0x00, // 84=T 0x00,0x3f,0x7f,0x40,0x40,0x7f,0x3f,0x00, // 85=U 0x00,0x1f,0x3f,0x60,0x60,0x3f,0x1f,0x00, // 86=V 0x00,0x7f,0x7f,0x30,0x18,0x30,0x7f,0x7f, // 87=W 0x00,0x63,0x77,0x1c,0x1c,0x77,0x63,0x00, // 88=X 0x00,0x07,0x0f,0x78,0x78,0x0f,0x07,0x00, // 89=Y 0x00,0x61,0x71,0x59,0x4d,0x47,0x43,0x00, // 90=Z 0x00,0x00,0x7f,0x7f,0x41,0x41,0x00,0x00, // 91=[ 0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0x40, // 92='\' 0x00,0x00,0x41,0x41,0x7f,0x7f,0x00,0x00, // 93=] 0x00,0x08,0x0c,0x06,0x06,0x0c,0x08,0x00, // 94=^ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, // 95=_ 0x00,0x00,0x01,0x03,0x06,0x04,0x00,0x00, // 96=` 0x00,0x20,0x74,0x54,0x54,0x7c,0x78,0x00, // 97=a 0x00,0x7f,0x7f,0x44,0x44,0x7c,0x38,0x00, // 98=b 0x00,0x38,0x7c,0x44,0x44,0x6c,0x28,0x00, // 99=c 0x00,0x38,0x7c,0x44,0x44,0x7f,0x7f,0x00, // 100=d 0x00,0x38,0x7c,0x54,0x54,0x5c,0x58,0x00, // 101=e 0x00,0x08,0x7e,0x7f,0x09,0x03,0x02,0x00, // 102=f 0x00,0x98,0xbc,0xa4,0xa4,0xfc,0x7c,0x00, // 103=g 0x00,0x7f,0x7f,0x04,0x04,0x7c,0x78,0x00, // 104=h 0x00,0x00,0x00,0x7d,0x7d,0x00,0x00,0x00, // 105=i 0x00,0x40,0xc0,0x80,0x80,0xfd,0x7d,0x00, // 106=j 0x00,0x7f,0x7f,0x30,0x38,0x6c,0x44,0x00, // 107=k 0x00,0x00,0x41,0x7f,0x7f,0x40,0x00,0x00, // 108=l 0x00,0x7c,0x7c,0x18,0x30,0x18,0x7c,0x7c, // 109=m 0x00,0x7c,0x7c,0x04,0x04,0x7c,0x78,0x00, // 110=n 0x00,0x38,0x7c,0x44,0x44,0x7c,0x38,0x00, // 111=o 0x00,0xfc,0xfc,0x24,0x24,0x3c,0x18,0x00, // 112=p 0x00,0x18,0x3c,0x24,0x24,0xfc,0xfc,0x00, // 113=q 0x00,0x7c,0x7c,0x04,0x04,0x0c,0x08,0x00, // 114=r 0x00,0x48,0x5c,0x54,0x54,0x74,0x20,0x00, // 115=s 0x04,0x04,0x3f,0x7f,0x44,0x64,0x20,0x00, // 116=t 0x00,0x3c,0x7c,0x40,0x40,0x7c,0x3c,0x00, // 117=u 0x00,0x1c,0x3c,0x60,0x60,0x3c,0x1c,0x00, // 118=v 0x00,0x1c,0x7c,0x30,0x18,0x30,0x7c,0x1c, // 119=w 0x00,0x44,0x6c,0x38,0x38,0x6c,0x44,0x00, // 120=x 0x00,0x9c,0xbc,0xa0,0xa0,0xfc,0x7c,0x00, // 121=y 0x00,0x44,0x64,0x74,0x5c,0x4c,0x44,0x00, // 122=z 0x00,0x08,0x08,0x3e,0x77,0x41,0x41,0x00, // 123={ 0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00, // 124=| 0x00,0x41,0x41,0x77,0x3e,0x08,0x08,0x00, // 125=} 0x00,0x02,0x03,0x01,0x03,0x02,0x03,0x01, // 126=~ 0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55, // 127 }; #endif // MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H micropython-1.12/ports/stm32/gccollect.c000066400000000000000000000046431357706137100202530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpstate.h" #include "py/gc.h" #include "py/mpthread.h" #include "lib/utils/gchelper.h" #include "gccollect.h" #include "systick.h" void gc_collect(void) { // get current time, in case we want to time the GC #if 0 uint32_t start = mp_hal_ticks_us(); #endif // start the GC gc_collect_start(); // get the registers and the sp uintptr_t regs[10]; uintptr_t sp = gc_helper_get_regs_and_sp(regs); // trace the stack, including the registers (since they live on the stack in this function) gc_collect_root((void**)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); // trace root pointers from any threads #if MICROPY_PY_THREAD mp_thread_gc_others(); #endif // end the GC gc_collect_end(); #if 0 // print GC info uint32_t ticks = mp_hal_ticks_us() - start; gc_info_t info; gc_info(&info); printf("GC@%lu %lums\n", start, ticks); printf(" " UINT_FMT " total\n", info.total); printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); #endif } micropython-1.12/ports/stm32/gccollect.h000066400000000000000000000033241357706137100202530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_GCCOLLECT_H #define MICROPY_INCLUDED_STM32_GCCOLLECT_H // variables defining memory layout // (these probably belong somewhere else...) extern uint32_t _etext; extern uint32_t _sidata; extern uint32_t _ram_start; extern uint32_t _sdata; extern uint32_t _edata; extern uint32_t _sbss; extern uint32_t _ebss; extern uint32_t _heap_start; extern uint32_t _heap_end; extern uint32_t _sstack; extern uint32_t _estack; extern uint32_t _ram_end; #endif // MICROPY_INCLUDED_STM32_GCCOLLECT_H micropython-1.12/ports/stm32/help.c000066400000000000000000000067151357706137100172460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" const char stm32_help_text[] = "Welcome to MicroPython!\n" "\n" "For online help please visit http://micropython.org/help/.\n" "\n" "Quick overview of commands for the board:\n" " pyb.info() -- print some general information\n" " pyb.delay(n) -- wait for n milliseconds\n" " pyb.millis() -- get number of milliseconds since hard reset\n" " pyb.Switch() -- create a switch object\n" " Switch methods: (), callback(f)\n" " pyb.LED(n) -- create an LED object for LED n (n=1,2,3,4)\n" " LED methods: on(), off(), toggle(), intensity()\n" " pyb.Pin(pin) -- get a pin, eg pyb.Pin('X1')\n" " pyb.Pin(pin, m, [p]) -- get a pin and configure it for IO mode m, pull mode p\n" " Pin methods: init(..), value([v]), high(), low()\n" " pyb.ExtInt(pin, m, p, callback) -- create an external interrupt object\n" " pyb.ADC(pin) -- make an analog object from a pin\n" " ADC methods: read(), read_timed(buf, freq)\n" " pyb.DAC(port) -- make a DAC object\n" " DAC methods: triangle(freq), write(n), write_timed(buf, freq)\n" " pyb.RTC() -- make an RTC object; methods: datetime([val])\n" " pyb.rng() -- get a 30-bit hardware random number\n" " pyb.Servo(n) -- create Servo object for servo n (n=1,2,3,4)\n" " Servo methods: calibration(..), angle([x, [t]]), speed([x, [t]])\n" " pyb.Accel() -- create an Accelerometer object\n" " Accelerometer methods: x(), y(), z(), tilt(), filtered_xyz()\n" "\n" "Pins are numbered X1-X12, X17-X22, Y1-Y12, or by their MCU name\n" "Pin IO modes are: pyb.Pin.IN, pyb.Pin.OUT_PP, pyb.Pin.OUT_OD\n" "Pin pull modes are: pyb.Pin.PULL_NONE, pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN\n" "Additional serial bus objects: pyb.I2C(n), pyb.SPI(n), pyb.UART(n)\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" " CTRL-B -- on a blank line, enter normal REPL mode\n" " CTRL-C -- interrupt a running program\n" " CTRL-D -- on a blank line, do a soft reset of the board\n" " CTRL-E -- on a blank line, enter paste mode\n" "\n" "For further help on a specific object, type help(obj)\n" "For a list of available modules, type help('modules')\n" ; micropython-1.12/ports/stm32/i2c.c000066400000000000000000000333021357706137100167630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mperrno.h" #include "py/mphal.h" #include "i2c.h" #if MICROPY_HW_ENABLE_HW_I2C #if defined(STM32F4) STATIC uint16_t i2c_timeout_ms[MICROPY_HW_MAX_I2C]; int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq, uint16_t timeout_ms) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); // Init pins if (!mp_hal_pin_config_alt(scl, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, AF_FN_I2C, i2c_id + 1)) { return -MP_EPERM; } if (!mp_hal_pin_config_alt(sda, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, AF_FN_I2C, i2c_id + 1)) { return -MP_EPERM; } // Save timeout value i2c_timeout_ms[i2c_id] = timeout_ms; // Force reset I2C peripheral RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST << i2c_id; RCC->APB1RSTR &= ~(RCC_APB1RSTR_I2C1RST << i2c_id); // Enable I2C peripheral clock RCC->APB1ENR |= RCC_APB1ENR_I2C1EN << i2c_id; volatile uint32_t tmp = RCC->APB1ENR; // delay after RCC clock enable (void)tmp; uint32_t PCLK1 = HAL_RCC_GetPCLK1Freq(); // Initialise I2C peripheral i2c->CR1 = 0; i2c->CR2 = PCLK1 / 1000000; i2c->OAR1 = 0; i2c->OAR2 = 0; freq = MIN(freq, 400000); // SM: MAX(4, PCLK1 / (F * 2)) // FM, 16:9 duty: 0xc000 | MAX(1, (PCLK1 / (F * (16 + 9)))) if (freq <= 100000) { i2c->CCR = MAX(4, PCLK1 / (freq * 2)); } else { i2c->CCR = 0xc000 | MAX(1, PCLK1 / (freq * 25)); } // SM: 1000ns / (1/PCLK1) + 1 = PCLK1 * 1e-6 + 1 // FM: 300ns / (1/PCLK1) + 1 = 300e-3 * PCLK1 * 1e-6 + 1 if (freq <= 100000) { i2c->TRISE = PCLK1 / 1000000 + 1; // 1000ns rise time in SM } else { i2c->TRISE = PCLK1 / 1000000 * 3 / 10 + 1; // 300ns rise time in FM } #if defined(I2C_FLTR_ANOFF) i2c->FLTR = 0; // analog filter on, digital filter off #endif return 0; } STATIC int i2c_wait_sr1_set(i2c_t *i2c, uint32_t mask) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); uint32_t t0 = HAL_GetTick(); while (!(i2c->SR1 & mask)) { if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { i2c->CR1 &= ~I2C_CR1_PE; return -MP_ETIMEDOUT; } } return 0; } STATIC int i2c_wait_stop(i2c_t *i2c) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); uint32_t t0 = HAL_GetTick(); while (i2c->CR1 & I2C_CR1_STOP) { if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { i2c->CR1 &= ~I2C_CR1_PE; return -MP_ETIMEDOUT; } } i2c->CR1 &= ~I2C_CR1_PE; return 0; } // For write: len = 0, 1 or N // For read: len = 1, 2 or N; stop = true int i2c_start_addr(i2c_t *i2c, int rd_wrn, uint16_t addr, size_t next_len, bool stop) { if (!(i2c->CR1 & I2C_CR1_PE) && (i2c->SR2 & I2C_SR2_MSL)) { // The F4 I2C peripheral can sometimes get into a bad state where it's disabled // (PE low) but still an active master (MSL high). It seems the best way to get // out of this is a full reset. uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST << i2c_id; RCC->APB1RSTR &= ~(RCC_APB1RSTR_I2C1RST << i2c_id); } // It looks like it's possible to terminate the reading by sending a // START condition instead of STOP condition but we don't support that. if (rd_wrn) { if (!stop) { return -MP_EINVAL; } } // Repurpose OAR1 to hold stop flag i2c->OAR1 = stop; // Enable peripheral and send START condition i2c->CR1 |= I2C_CR1_PE; i2c->CR1 |= I2C_CR1_START; // Wait for START to be sent int ret; if ((ret = i2c_wait_sr1_set(i2c, I2C_SR1_SB))) { return ret; } // Send the 7-bit address with read/write bit i2c->DR = addr << 1 | rd_wrn; // Wait for address to be sent if ((ret = i2c_wait_sr1_set(i2c, I2C_SR1_AF | I2C_SR1_ADDR))) { return ret; } // Check if the slave responded or not if (i2c->SR1 & I2C_SR1_AF) { // Got a NACK i2c->CR1 |= I2C_CR1_STOP; i2c_wait_stop(i2c); // Don't leak errors from this call return -MP_ENODEV; } if (rd_wrn) { // For reading, set up ACK/NACK control based on number of bytes to read (at least 1 byte) if (next_len <= 1) { // NACK next received byte i2c->CR1 &= ~I2C_CR1_ACK; } else if (next_len <= 2) { // NACK second received byte i2c->CR1 |= I2C_CR1_POS; i2c->CR1 &= ~I2C_CR1_ACK; } else { // ACK next received byte i2c->CR1 |= I2C_CR1_ACK; } } // Read SR2 to clear SR1_ADDR uint32_t sr2 = i2c->SR2; (void)sr2; return 0; } // next_len = 0 or N (>=2) int i2c_read(i2c_t *i2c, uint8_t *dest, size_t len, size_t next_len) { if (len == 0) { return -MP_EINVAL; } if (next_len == 1) { return -MP_EINVAL; } size_t remain = len + next_len; if (remain == 1) { // Special case i2c->CR1 |= I2C_CR1_STOP; int ret; if ((ret = i2c_wait_sr1_set(i2c, I2C_SR1_RXNE))) { return ret; } *dest = i2c->DR; } else { for (; len; --len) { remain = len + next_len; int ret; if ((ret = i2c_wait_sr1_set(i2c, I2C_SR1_BTF))) { return ret; } if (remain == 2) { // In this case next_len == 0 (it's not allowed to be 1) i2c->CR1 |= I2C_CR1_STOP; *dest++ = i2c->DR; *dest = i2c->DR; break; } else if (remain == 3) { // NACK next received byte i2c->CR1 &= ~I2C_CR1_ACK; } *dest++ = i2c->DR; } } if (!next_len) { // We sent a stop above, just wait for it to be finished return i2c_wait_stop(i2c); } return 0; } // next_len = 0 or N int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { int ret; if ((ret = i2c_wait_sr1_set(i2c, I2C_SR1_AF | I2C_SR1_TXE))) { return ret; } // Write out the data int num_acks = 0; while (len--) { i2c->DR = *src++; if ((ret = i2c_wait_sr1_set(i2c, I2C_SR1_AF | I2C_SR1_BTF))) { return ret; } if (i2c->SR1 & I2C_SR1_AF) { // Slave did not respond to byte so stop sending break; } ++num_acks; } if (!next_len) { if (i2c->OAR1) { // Send a STOP and wait for it to finish i2c->CR1 |= I2C_CR1_STOP; if ((ret = i2c_wait_stop(i2c))) { return ret; } } } return num_acks; } #elif defined(STM32F0) || defined(STM32F7) STATIC uint16_t i2c_timeout_ms[MICROPY_HW_MAX_I2C]; int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq, uint16_t timeout_ms) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); // Init pins if (!mp_hal_pin_config_alt(scl, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, AF_FN_I2C, i2c_id + 1)) { return -MP_EPERM; } if (!mp_hal_pin_config_alt(sda, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, AF_FN_I2C, i2c_id + 1)) { return -MP_EPERM; } // Save timeout value i2c_timeout_ms[i2c_id] = timeout_ms; // Enable I2C peripheral clock RCC->APB1ENR |= RCC_APB1ENR_I2C1EN << i2c_id; volatile uint32_t tmp = RCC->APB1ENR; // delay after RCC clock enable (void)tmp; // Initialise I2C peripheral i2c->CR1 = 0; i2c->CR2 = 0; i2c->OAR1 = 0; i2c->OAR2 = 0; // These timing values are for f_I2CCLK=54MHz and are only approximate if (freq >= 1000000) { i2c->TIMINGR = 0x50100103; } else if (freq >= 400000) { i2c->TIMINGR = 0x70330309; } else if (freq >= 100000) { i2c->TIMINGR = 0xb0420f13; } else { return -MP_EINVAL; } i2c->TIMEOUTR = 0; return 0; } STATIC int i2c_wait_cr2_clear(i2c_t *i2c, uint32_t mask) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); uint32_t t0 = HAL_GetTick(); while (i2c->CR2 & mask) { if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { i2c->CR1 &= ~I2C_CR1_PE; return -MP_ETIMEDOUT; } } return 0; } STATIC int i2c_wait_isr_set(i2c_t *i2c, uint32_t mask) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); uint32_t t0 = HAL_GetTick(); while (!(i2c->ISR & mask)) { if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { i2c->CR1 &= ~I2C_CR1_PE; return -MP_ETIMEDOUT; } } return 0; } // len = 0, 1 or N int i2c_start_addr(i2c_t *i2c, int rd_wrn, uint16_t addr, size_t len, bool stop) { // Enable the peripheral and send the START condition with slave address i2c->CR1 |= I2C_CR1_PE; i2c->CR2 = (len > 1) << I2C_CR2_RELOAD_Pos | (len > 0) << I2C_CR2_NBYTES_Pos | rd_wrn << I2C_CR2_RD_WRN_Pos | (addr & 0x7f) << 1; i2c->CR2 |= I2C_CR2_START; // Wait for address to be sent int ret; if ((ret = i2c_wait_cr2_clear(i2c, I2C_CR2_START))) { return ret; } // Check if the slave responded or not if (i2c->ISR & I2C_ISR_NACKF) { // If we get a NACK then I2C periph unconditionally sends a STOP i2c_wait_isr_set(i2c, I2C_ISR_STOPF); // Don't leak errors from this call i2c->CR1 &= ~I2C_CR1_PE; return -MP_ENODEV; } // Configure automatic STOP if needed if (stop) { i2c->CR2 |= I2C_CR2_AUTOEND; } // Repurpose OAR1 to indicate that we loaded CR2 i2c->OAR1 = 1; return 0; } STATIC int i2c_check_stop(i2c_t *i2c) { if (i2c->CR2 & I2C_CR2_AUTOEND) { // Wait for the STOP condition and then disable the peripheral int ret; if ((ret = i2c_wait_isr_set(i2c, I2C_ISR_STOPF))) { return ret; } i2c->CR1 &= ~I2C_CR1_PE; } return 0; } // next_len = 0 or N int i2c_read(i2c_t *i2c, uint8_t *dest, size_t len, size_t next_len) { if (i2c->OAR1) { i2c->OAR1 = 0; } else { goto load_cr2; } // Read in the data while (len--) { int ret; if ((ret = i2c_wait_isr_set(i2c, I2C_ISR_RXNE))) { return ret; } *dest++ = i2c->RXDR; load_cr2: if (len) { i2c->CR2 = (i2c->CR2 & I2C_CR2_AUTOEND) | (len + next_len > 1) << I2C_CR2_RELOAD_Pos | 1 << I2C_CR2_NBYTES_Pos; } } if (!next_len) { int ret; if ((ret = i2c_check_stop(i2c))) { return ret; } } return 0; } // next_len = 0 or N int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { int num_acks = 0; if (i2c->OAR1) { i2c->OAR1 = 0; } else { goto load_cr2; } // Write out the data while (len--) { int ret; if ((ret = i2c_wait_isr_set(i2c, I2C_ISR_TXE))) { return ret; } i2c->TXDR = *src++; if ((ret = i2c_wait_isr_set(i2c, I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF))) { return ret; } uint32_t isr = i2c->ISR; if (isr & I2C_ISR_NACKF) { // Slave did not respond to byte so stop sending if (!(isr & I2C_ISR_TXE)) { // The TXDR is still full so the byte previous to that wasn't actually ACK'd --num_acks; } break; } ++num_acks; load_cr2: if (len) { i2c->CR2 = (i2c->CR2 & I2C_CR2_AUTOEND) | (len + next_len > 1) << I2C_CR2_RELOAD_Pos | 1 << I2C_CR2_NBYTES_Pos; } } if (!next_len) { int ret; if ((ret = i2c_check_stop(i2c))) { return ret; } } return num_acks; } #endif #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) int i2c_readfrom(i2c_t *i2c, uint16_t addr, uint8_t *dest, size_t len, bool stop) { int ret; if ((ret = i2c_start_addr(i2c, 1, addr, len, stop))) { return ret; } return i2c_read(i2c, dest, len, 0); } int i2c_writeto(i2c_t *i2c, uint16_t addr, const uint8_t *src, size_t len, bool stop) { int ret; if ((ret = i2c_start_addr(i2c, 0, addr, len, stop))) { return ret; } return i2c_write(i2c, src, len, 0); } #endif #endif // MICROPY_HW_ENABLE_HW_I2C micropython-1.12/ports/stm32/i2c.h000066400000000000000000000052051357706137100167710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_I2C_H #define MICROPY_INCLUDED_STM32_I2C_H #include "dma.h" // use this for OwnAddress1 to configure I2C in master mode #define PYB_I2C_MASTER_ADDRESS (0xfe) typedef struct _pyb_i2c_obj_t { mp_obj_base_t base; I2C_HandleTypeDef *i2c; const dma_descr_t *tx_dma_descr; const dma_descr_t *rx_dma_descr; bool *use_dma; } pyb_i2c_obj_t; extern I2C_HandleTypeDef I2CHandle1; extern I2C_HandleTypeDef I2CHandle2; extern I2C_HandleTypeDef I2CHandle3; extern I2C_HandleTypeDef I2CHandle4; extern const mp_obj_type_t pyb_i2c_type; extern const pyb_i2c_obj_t pyb_i2c_obj[4]; void i2c_init0(void); void pyb_i2c_init(I2C_HandleTypeDef *i2c); void pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq); uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c); void i2c_ev_irq_handler(mp_uint_t i2c_id); void i2c_er_irq_handler(mp_uint_t i2c_id); typedef I2C_TypeDef i2c_t; int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq, uint16_t timeout); int i2c_start_addr(i2c_t *i2c, int rd_wrn, uint16_t addr, size_t len, bool stop); int i2c_read(i2c_t *i2c, uint8_t *dest, size_t len, size_t next_len); int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len); int i2c_readfrom(i2c_t *i2c, uint16_t addr, uint8_t *dest, size_t len, bool stop); int i2c_writeto(i2c_t *i2c, uint16_t addr, const uint8_t *src, size_t len, bool stop); #endif // MICROPY_INCLUDED_STM32_I2C_H micropython-1.12/ports/stm32/i2cslave.c000066400000000000000000000065551357706137100200300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "i2cslave.h" #if defined(STM32F4) void i2c_slave_init_helper(i2c_slave_t *i2c, int addr) { i2c->CR2 = I2C_CR2_ITBUFEN | I2C_CR2_ITEVTEN | 4 << I2C_CR2_FREQ_Pos; i2c->OAR1 = 1 << 14 | addr << 1; i2c->OAR2 = 0; i2c->CR1 = I2C_CR1_ACK | I2C_CR1_PE; } void i2c_slave_ev_irq_handler(i2c_slave_t *i2c) { uint32_t sr1 = i2c->SR1; if (sr1 & I2C_SR1_ADDR) { // Address matched // Read of SR1, SR2 needed to clear ADDR bit sr1 = i2c->SR1; uint32_t sr2 = i2c->SR2; i2c_slave_process_addr_match((sr2 >> I2C_SR2_TRA_Pos) & 1); } if (sr1 & I2C_SR1_TXE) { i2c->DR = i2c_slave_process_tx_byte(); } if (sr1 & I2C_SR1_RXNE) { i2c_slave_process_rx_byte(i2c->DR); } if (sr1 & I2C_SR1_STOPF) { // STOPF only set at end of RX mode (in TX mode AF is set on NACK) // Read of SR1, write CR1 needed to clear STOPF bit sr1 = i2c->SR1; i2c->CR1 &= ~I2C_CR1_ACK; i2c_slave_process_rx_end(); i2c->CR1 |= I2C_CR1_ACK; } } #elif defined(STM32F7) || defined(STM32H7) void i2c_slave_init_helper(i2c_slave_t *i2c, int addr) { i2c->CR1 = I2C_CR1_STOPIE | I2C_CR1_ADDRIE | I2C_CR1_RXIE | I2C_CR1_TXIE; i2c->CR2 = 0; i2c->OAR1 = I2C_OAR1_OA1EN | addr << 1; i2c->OAR2 = 0; i2c->CR1 |= I2C_CR1_PE; } void i2c_slave_ev_irq_handler(i2c_slave_t *i2c) { uint32_t isr = i2c->ISR; if (isr & I2C_ISR_ADDR) { // Address matched // Set TXE so that TXDR is flushed and ready for the first byte i2c->ISR = I2C_ISR_TXE; i2c->ICR = I2C_ICR_ADDRCF; i2c_slave_process_addr_match(0); } if (isr & I2C_ISR_TXIS) { i2c->TXDR = i2c_slave_process_tx_byte(); } if (isr & I2C_ISR_RXNE) { i2c_slave_process_rx_byte(i2c->RXDR); } if (isr & I2C_ISR_STOPF) { // STOPF only set for STOP condition, not a repeated START i2c->ICR = I2C_ICR_STOPCF; i2c->OAR1 &= ~I2C_OAR1_OA1EN; if (i2c->ISR & I2C_ISR_DIR) { //i2c_slave_process_tx_end(); } else { i2c_slave_process_rx_end(); } i2c->OAR1 |= I2C_OAR1_OA1EN; } } #endif micropython-1.12/ports/stm32/i2cslave.h000066400000000000000000000046661357706137100200360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_I2CSLAVE_H #define MICROPY_INCLUDED_STM32_I2CSLAVE_H #include STM32_HAL_H typedef I2C_TypeDef i2c_slave_t; void i2c_slave_init_helper(i2c_slave_t *i2c, int addr); static inline void i2c_slave_init(i2c_slave_t *i2c, int irqn, int irq_pri, int addr) { int i2c_idx = ((uintptr_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); #if defined(STM32F4) || defined(STM32F7) RCC->APB1ENR |= 1 << (RCC_APB1ENR_I2C1EN_Pos + i2c_idx); volatile uint32_t tmp = RCC->APB1ENR; // Delay after enabling clock (void)tmp; #elif defined(STM32H7) RCC->APB1LENR |= 1 << (RCC_APB1LENR_I2C1EN_Pos + i2c_idx); volatile uint32_t tmp = RCC->APB1LENR; // Delay after enabling clock (void)tmp; #endif i2c_slave_init_helper(i2c, addr); NVIC_SetPriority(irqn, irq_pri); NVIC_EnableIRQ(irqn); } static inline void i2c_slave_shutdown(i2c_slave_t *i2c, int irqn) { i2c->CR1 = 0; NVIC_DisableIRQ(irqn); } void i2c_slave_ev_irq_handler(i2c_slave_t *i2c); // These should be provided externally int i2c_slave_process_addr_match(int rw); int i2c_slave_process_rx_byte(uint8_t val); void i2c_slave_process_rx_end(void); uint8_t i2c_slave_process_tx_byte(void); #endif // MICROPY_INCLUDED_STM32_I2CSLAVE_H micropython-1.12/ports/stm32/irq.c000066400000000000000000000056331357706137100171070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/mphal.h" #include "irq.h" /// \moduleref pyb #if IRQ_ENABLE_STATS uint32_t irq_stats[IRQ_STATS_MAX] = {0}; #endif /// \function wfi() /// Wait for an interrupt. /// This executies a `wfi` instruction which reduces power consumption /// of the MCU until an interrupt occurs, at which point execution continues. STATIC mp_obj_t pyb_wfi(void) { __WFI(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi); /// \function disable_irq() /// Disable interrupt requests. /// Returns the previous IRQ state: `False`/`True` for disabled/enabled IRQs /// respectively. This return value can be passed to enable_irq to restore /// the IRQ to its original state. STATIC mp_obj_t pyb_disable_irq(void) { return mp_obj_new_bool(disable_irq() == IRQ_STATE_ENABLED); } MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq); /// \function enable_irq(state=True) /// Enable interrupt requests. /// If `state` is `True` (the default value) then IRQs are enabled. /// If `state` is `False` then IRQs are disabled. The most common use of /// this function is to pass it the value returned by `disable_irq` to /// exit a critical section. STATIC mp_obj_t pyb_enable_irq(uint n_args, const mp_obj_t *arg) { enable_irq((n_args == 0 || mp_obj_is_true(arg[0])) ? IRQ_STATE_ENABLED : IRQ_STATE_DISABLED); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj, 0, 1, pyb_enable_irq); #if IRQ_ENABLE_STATS // return a memoryview of the irq statistics array STATIC mp_obj_t pyb_irq_stats(void) { return mp_obj_new_memoryview(0x80 | 'I', MP_ARRAY_SIZE(irq_stats), &irq_stats[0]); } MP_DEFINE_CONST_FUN_OBJ_0(pyb_irq_stats_obj, pyb_irq_stats); #endif micropython-1.12/ports/stm32/irq.h000066400000000000000000000154171357706137100171150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_IRQ_H #define MICROPY_INCLUDED_STM32_IRQ_H // Use this macro together with NVIC_SetPriority to indicate that an IRQn is non-negative, // which helps the compiler optimise the resulting inline function. #define IRQn_NONNEG(pri) ((pri) & 0x7f) // these states correspond to values from query_irq, enable_irq and disable_irq #define IRQ_STATE_DISABLED (0x00000001) #define IRQ_STATE_ENABLED (0x00000000) // Enable this to get a count for the number of times each irq handler is called, // accessible via pyb.irq_stats(). #define IRQ_ENABLE_STATS (0) #if IRQ_ENABLE_STATS #if defined(STM32H7) #define IRQ_STATS_MAX (256) #else #define IRQ_STATS_MAX (128) #endif extern uint32_t irq_stats[IRQ_STATS_MAX]; #define IRQ_ENTER(irq) ++irq_stats[irq] #define IRQ_EXIT(irq) #else #define IRQ_ENTER(irq) #define IRQ_EXIT(irq) #endif static inline mp_uint_t query_irq(void) { return __get_PRIMASK(); } // enable_irq and disable_irq are defined inline in mpconfigport.h #if __CORTEX_M >= 0x03 // irqs with a priority value greater or equal to "pri" will be disabled // "pri" should be between 1 and 15 inclusive static inline uint32_t raise_irq_pri(uint32_t pri) { uint32_t basepri = __get_BASEPRI(); // If non-zero, the processor does not process any exception with a // priority value greater than or equal to BASEPRI. // When writing to BASEPRI_MAX the write goes to BASEPRI only if either: // - Rn is non-zero and the current BASEPRI value is 0 // - Rn is non-zero and less than the current BASEPRI value pri <<= (8 - __NVIC_PRIO_BITS); __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory"); return basepri; } // "basepri" should be the value returned from raise_irq_pri static inline void restore_irq_pri(uint32_t basepri) { __set_BASEPRI(basepri); } #else static inline uint32_t raise_irq_pri(uint32_t pri) { return disable_irq(); } // "state" should be the value returned from raise_irq_pri static inline void restore_irq_pri(uint32_t state) { enable_irq(state); } #endif MP_DECLARE_CONST_FUN_OBJ_0(pyb_wfi_obj); MP_DECLARE_CONST_FUN_OBJ_0(pyb_disable_irq_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj); MP_DECLARE_CONST_FUN_OBJ_0(pyb_irq_stats_obj); // IRQ priority definitions. // // Lower number implies higher interrupt priority. // // The default priority grouping is set to NVIC_PRIORITYGROUP_4 in the // HAL_Init function. This corresponds to 4 bits for the priority field // and 0 bits for the sub-priority field (which means that for all intensive // purposes that the sub-priorities below are ignored). // // While a given interrupt is being processed, only higher priority (lower number) // interrupts will preempt a given interrupt. If sub-priorities are active // then the sub-priority determines the order that pending interrupts of // a given priority are executed. This is only meaningful if 2 or more // interrupts of the same priority are pending at the same time. // // The priority of the SysTick timer is determined from the TICK_INT_PRIORITY // value which is normally set to 0 in the stm32f4xx_hal_conf.h file. // // The following interrupts are arranged from highest priority to lowest // priority to make it a bit easier to figure out. #if __CORTEX_M == 0 #define IRQ_PRI_SYSTICK 0 #define IRQ_PRI_UART 1 #define IRQ_PRI_SDIO 1 #define IRQ_PRI_DMA 1 #define IRQ_PRI_FLASH 2 #define IRQ_PRI_OTG_FS 2 #define IRQ_PRI_OTG_HS 2 #define IRQ_PRI_TIM5 2 #define IRQ_PRI_CAN 2 #define IRQ_PRI_TIMX 2 #define IRQ_PRI_EXTINT 2 #define IRQ_PRI_PENDSV 3 #define IRQ_PRI_RTC_WKUP 3 #else #define IRQ_PRI_SYSTICK NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 0, 0) // The UARTs have no FIFOs, so if they don't get serviced quickly then characters // get dropped. The handling for each character only consumes about 0.5 usec #define IRQ_PRI_UART NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 1, 0) // SDIO must be higher priority than DMA for SDIO DMA transfers to work. #define IRQ_PRI_SDIO NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 4, 0) // DMA should be higher priority than USB, since USB Mass Storage calls // into the sdcard driver which waits for the DMA to complete. #define IRQ_PRI_DMA NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 5, 0) // Flash IRQ (used for flushing storage cache) must be at the same priority as // the USB IRQs, so that the IRQ priority can be raised to this level to disable // both the USB and cache flushing, when storage transfers are in progress. #define IRQ_PRI_FLASH NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) #define IRQ_PRI_OTG_FS NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) #define IRQ_PRI_OTG_HS NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) #define IRQ_PRI_TIM5 NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 6, 0) #define IRQ_PRI_CAN NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0) #define IRQ_PRI_SPI NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 8, 0) // Interrupt priority for non-special timers. #define IRQ_PRI_TIMX NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 13, 0) #define IRQ_PRI_EXTINT NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0) // PENDSV should be at the lowst priority so that other interrupts complete // before exception is raised. #define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) #define IRQ_PRI_RTC_WKUP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0) #endif #endif // MICROPY_INCLUDED_STM32_IRQ_H micropython-1.12/ports/stm32/lcd.c000066400000000000000000000463501357706137100170570ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mphal.h" #include "py/runtime.h" #if MICROPY_HW_HAS_LCD #include "pin.h" #include "bufhelper.h" #include "spi.h" #include "font_petme128_8x8.h" #include "lcd.h" /// \moduleref pyb /// \class LCD - LCD control for the LCD touch-sensor pyskin /// /// The LCD class is used to control the LCD on the LCD touch-sensor pyskin, /// LCD32MKv1.0. The LCD is a 128x32 pixel monochrome screen, part NHD-C12832A1Z. /// /// The pyskin must be connected in either the X or Y positions, and then /// an LCD object is made using: /// /// lcd = pyb.LCD('X') # if pyskin is in the X position /// lcd = pyb.LCD('Y') # if pyskin is in the Y position /// /// Then you can use: /// /// lcd.light(True) # turn the backlight on /// lcd.write('Hello world!\n') # print text to the screen /// /// This driver implements a double buffer for setting/getting pixels. /// For example, to make a bouncing dot, try: /// /// x = y = 0 /// dx = dy = 1 /// while True: /// # update the dot's position /// x += dx /// y += dy /// /// # make the dot bounce of the edges of the screen /// if x <= 0 or x >= 127: dx = -dx /// if y <= 0 or y >= 31: dy = -dy /// /// lcd.fill(0) # clear the buffer /// lcd.pixel(x, y, 1) # draw the dot /// lcd.show() # show the buffer /// pyb.delay(50) # pause for 50ms #define LCD_INSTR (0) #define LCD_DATA (1) #define LCD_CHAR_BUF_W (16) #define LCD_CHAR_BUF_H (4) #define LCD_PIX_BUF_W (128) #define LCD_PIX_BUF_H (32) #define LCD_PIX_BUF_BYTE_SIZE (LCD_PIX_BUF_W * LCD_PIX_BUF_H / 8) typedef struct _pyb_lcd_obj_t { mp_obj_base_t base; // hardware control for the LCD const spi_t *spi; const pin_obj_t *pin_cs1; const pin_obj_t *pin_rst; const pin_obj_t *pin_a0; const pin_obj_t *pin_bl; // character buffer for stdout-like output char char_buffer[LCD_CHAR_BUF_W * LCD_CHAR_BUF_H]; int line; int column; int next_line; // double buffering for pixel buffer byte pix_buf[LCD_PIX_BUF_BYTE_SIZE]; byte pix_buf2[LCD_PIX_BUF_BYTE_SIZE]; } pyb_lcd_obj_t; STATIC void lcd_delay(void) { __asm volatile ("nop\nnop"); } STATIC void lcd_out(pyb_lcd_obj_t *lcd, int instr_data, uint8_t i) { lcd_delay(); mp_hal_pin_low(lcd->pin_cs1); // CS=0; enable if (instr_data == LCD_INSTR) { mp_hal_pin_low(lcd->pin_a0); // A0=0; select instr reg } else { mp_hal_pin_high(lcd->pin_a0); // A0=1; select data reg } lcd_delay(); HAL_SPI_Transmit(lcd->spi->spi, &i, 1, 1000); lcd_delay(); mp_hal_pin_high(lcd->pin_cs1); // CS=1; disable } // write a string to the LCD at the current cursor location // output it straight away (doesn't use the pixel buffer) STATIC void lcd_write_strn(pyb_lcd_obj_t *lcd, const char *str, unsigned int len) { int redraw_min = lcd->line * LCD_CHAR_BUF_W + lcd->column; int redraw_max = redraw_min; for (; len > 0; len--, str++) { // move to next line if needed if (lcd->next_line) { if (lcd->line + 1 < LCD_CHAR_BUF_H) { lcd->line += 1; } else { lcd->line = LCD_CHAR_BUF_H - 1; for (int i = 0; i < LCD_CHAR_BUF_W * (LCD_CHAR_BUF_H - 1); i++) { lcd->char_buffer[i] = lcd->char_buffer[i + LCD_CHAR_BUF_W]; } for (int i = 0; i < LCD_CHAR_BUF_W; i++) { lcd->char_buffer[LCD_CHAR_BUF_W * (LCD_CHAR_BUF_H - 1) + i] = ' '; } redraw_min = 0; redraw_max = LCD_CHAR_BUF_W * LCD_CHAR_BUF_H; } lcd->next_line = 0; lcd->column = 0; } if (*str == '\n') { lcd->next_line = 1; } else if (*str == '\r') { lcd->column = 0; } else if (*str == '\b') { if (lcd->column > 0) { lcd->column--; redraw_min = 0; // could optimise this to not redraw everything } } else if (lcd->column >= LCD_CHAR_BUF_W) { lcd->next_line = 1; str -= 1; len += 1; } else { lcd->char_buffer[lcd->line * LCD_CHAR_BUF_W + lcd->column] = *str; lcd->column += 1; int max = lcd->line * LCD_CHAR_BUF_W + lcd->column; if (max > redraw_max) { redraw_max = max; } } } // we must draw upside down, because the LCD is upside down for (int i = redraw_min; i < redraw_max; i++) { uint page = i / LCD_CHAR_BUF_W; uint offset = 8 * (LCD_CHAR_BUF_W - 1 - (i - (page * LCD_CHAR_BUF_W))); lcd_out(lcd, LCD_INSTR, 0xb0 | page); // page address set lcd_out(lcd, LCD_INSTR, 0x10 | ((offset >> 4) & 0x0f)); // column address set upper lcd_out(lcd, LCD_INSTR, 0x00 | (offset & 0x0f)); // column address set lower int chr = lcd->char_buffer[i]; if (chr < 32 || chr > 126) { chr = 127; } const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8]; for (int j = 7; j >= 0; j--) { lcd_out(lcd, LCD_DATA, chr_data[j]); } } } /// \classmethod \constructor(skin_position) /// /// Construct an LCD object in the given skin position. `skin_position` can be 'X' or 'Y', and /// should match the position where the LCD pyskin is plugged in. STATIC mp_obj_t pyb_lcd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); // get LCD position const char *lcd_id = mp_obj_str_get_str(args[0]); // create lcd object pyb_lcd_obj_t *lcd = m_new_obj(pyb_lcd_obj_t); lcd->base.type = &pyb_lcd_type; // configure pins // TODO accept an SPI object and pin objects for full customisation if ((lcd_id[0] | 0x20) == 'x' && lcd_id[1] == '\0') { lcd->spi = &spi_obj[0]; lcd->pin_cs1 = pyb_pin_X3; lcd->pin_rst = pyb_pin_X4; lcd->pin_a0 = pyb_pin_X5; lcd->pin_bl = pyb_pin_X12; } else if ((lcd_id[0] | 0x20) == 'y' && lcd_id[1] == '\0') { lcd->spi = &spi_obj[1]; lcd->pin_cs1 = pyb_pin_Y3; lcd->pin_rst = pyb_pin_Y4; lcd->pin_a0 = pyb_pin_Y5; lcd->pin_bl = pyb_pin_Y12; } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "LCD(%s) doesn't exist", lcd_id)); } // init the SPI bus SPI_InitTypeDef *init = &lcd->spi->spi->Init; init->Mode = SPI_MODE_MASTER; // compute the baudrate prescaler from the desired baudrate // select a prescaler that yields at most the desired baudrate uint spi_clock; if (lcd->spi->spi->Instance == SPI1) { // SPI1 is on APB2 spi_clock = HAL_RCC_GetPCLK2Freq(); } else { // SPI2 and SPI3 are on APB1 spi_clock = HAL_RCC_GetPCLK1Freq(); } uint br_prescale = spi_clock / 16000000; // datasheet says LCD can run at 20MHz, but we go for 16MHz if (br_prescale <= 2) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; } else if (br_prescale <= 4) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; } else if (br_prescale <= 8) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; } else if (br_prescale <= 16) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; } else if (br_prescale <= 32) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; } else if (br_prescale <= 64) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; } else if (br_prescale <= 128) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; } else { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; } // data is sent bigendian, latches on rising clock init->CLKPolarity = SPI_POLARITY_HIGH; init->CLKPhase = SPI_PHASE_2EDGE; init->Direction = SPI_DIRECTION_2LINES; init->DataSize = SPI_DATASIZE_8BIT; init->NSS = SPI_NSS_SOFT; init->FirstBit = SPI_FIRSTBIT_MSB; init->TIMode = SPI_TIMODE_DISABLED; init->CRCCalculation = SPI_CRCCALCULATION_DISABLED; init->CRCPolynomial = 0; // init the SPI bus spi_init(lcd->spi, false); // set the pins to default values mp_hal_pin_high(lcd->pin_cs1); mp_hal_pin_high(lcd->pin_rst); mp_hal_pin_high(lcd->pin_a0); mp_hal_pin_low(lcd->pin_bl); // init the pins to be push/pull outputs mp_hal_pin_output(lcd->pin_cs1); mp_hal_pin_output(lcd->pin_rst); mp_hal_pin_output(lcd->pin_a0); mp_hal_pin_output(lcd->pin_bl); // init the LCD mp_hal_delay_ms(1); // wait a bit mp_hal_pin_low(lcd->pin_rst); // RST=0; reset mp_hal_delay_ms(1); // wait for reset; 2us min mp_hal_pin_high(lcd->pin_rst); // RST=1; enable mp_hal_delay_ms(1); // wait for reset; 2us min lcd_out(lcd, LCD_INSTR, 0xa0); // ADC select, normal lcd_out(lcd, LCD_INSTR, 0xc0); // common output mode select, normal (this flips the display) lcd_out(lcd, LCD_INSTR, 0xa2); // LCD bias set, 1/9 bias lcd_out(lcd, LCD_INSTR, 0x2f); // power control set, 0b111=(booster on, vreg on, vfollow on) lcd_out(lcd, LCD_INSTR, 0x21); // v0 voltage regulator internal resistor ratio set, 0b001=small lcd_out(lcd, LCD_INSTR, 0x81); // electronic volume mode set lcd_out(lcd, LCD_INSTR, 0x28); // electronic volume register set lcd_out(lcd, LCD_INSTR, 0x40); // display start line set, 0 lcd_out(lcd, LCD_INSTR, 0xaf); // LCD display, on // clear LCD RAM for (int page = 0; page < 4; page++) { lcd_out(lcd, LCD_INSTR, 0xb0 | page); // page address set lcd_out(lcd, LCD_INSTR, 0x10); // column address set upper lcd_out(lcd, LCD_INSTR, 0x00); // column address set lower for (int i = 0; i < 128; i++) { lcd_out(lcd, LCD_DATA, 0x00); } } // clear local char buffer memset(lcd->char_buffer, ' ', LCD_CHAR_BUF_H * LCD_CHAR_BUF_W); lcd->line = 0; lcd->column = 0; lcd->next_line = 0; // clear local pixel buffer memset(lcd->pix_buf, 0, LCD_PIX_BUF_BYTE_SIZE); memset(lcd->pix_buf2, 0, LCD_PIX_BUF_BYTE_SIZE); return MP_OBJ_FROM_PTR(lcd); } /// \method command(instr_data, buf) /// /// Send an arbitrary command to the LCD. Pass 0 for `instr_data` to send an /// instruction, otherwise pass 1 to send data. `buf` is a buffer with the /// instructions/data to send. STATIC mp_obj_t pyb_lcd_command(mp_obj_t self_in, mp_obj_t instr_data_in, mp_obj_t val) { pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(self_in); // get whether instr or data int instr_data = mp_obj_get_int(instr_data_in); // get the buffer to send from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(val, &bufinfo, data); // send the data for (uint i = 0; i < bufinfo.len; i++) { lcd_out(self, instr_data, ((byte*)bufinfo.buf)[i]); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_lcd_command_obj, pyb_lcd_command); /// \method contrast(value) /// /// Set the contrast of the LCD. Valid values are between 0 and 47. STATIC mp_obj_t pyb_lcd_contrast(mp_obj_t self_in, mp_obj_t contrast_in) { pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(self_in); int contrast = mp_obj_get_int(contrast_in); if (contrast < 0) { contrast = 0; } else if (contrast > 0x2f) { contrast = 0x2f; } lcd_out(self, LCD_INSTR, 0x81); // electronic volume mode set lcd_out(self, LCD_INSTR, contrast); // electronic volume register set return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_contrast_obj, pyb_lcd_contrast); /// \method light(value) /// /// Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off. STATIC mp_obj_t pyb_lcd_light(mp_obj_t self_in, mp_obj_t value) { pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(self_in); if (mp_obj_is_true(value)) { mp_hal_pin_high(self->pin_bl); // set pin high to turn backlight on } else { mp_hal_pin_low(self->pin_bl); // set pin low to turn backlight off } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_light_obj, pyb_lcd_light); /// \method write(str) /// /// Write the string `str` to the screen. It will appear immediately. STATIC mp_obj_t pyb_lcd_write(mp_obj_t self_in, mp_obj_t str) { pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(self_in); size_t len; const char *data = mp_obj_str_get_data(str, &len); lcd_write_strn(self, data, len); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_write_obj, pyb_lcd_write); /// \method fill(colour) /// /// Fill the screen with the given colour (0 or 1 for white or black). /// /// This method writes to the hidden buffer. Use `show()` to show the buffer. STATIC mp_obj_t pyb_lcd_fill(mp_obj_t self_in, mp_obj_t col_in) { pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(self_in); int col = mp_obj_get_int(col_in); if (col) { col = 0xff; } memset(self->pix_buf, col, LCD_PIX_BUF_BYTE_SIZE); memset(self->pix_buf2, col, LCD_PIX_BUF_BYTE_SIZE); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_fill_obj, pyb_lcd_fill); /// \method get(x, y) /// /// Get the pixel at the position `(x, y)`. Returns 0 or 1. /// /// This method reads from the visible buffer. STATIC mp_obj_t pyb_lcd_get(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) { pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(self_in); int x = mp_obj_get_int(x_in); int y = mp_obj_get_int(y_in); if (0 <= x && x <= 127 && 0 <= y && y <= 31) { uint byte_pos = x + 128 * ((uint)y >> 3); if (self->pix_buf[byte_pos] & (1 << (y & 7))) { return mp_obj_new_int(1); } } return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_lcd_get_obj, pyb_lcd_get); /// \method pixel(x, y, colour) /// /// Set the pixel at `(x, y)` to the given colour (0 or 1). /// /// This method writes to the hidden buffer. Use `show()` to show the buffer. STATIC mp_obj_t pyb_lcd_pixel(size_t n_args, const mp_obj_t *args) { pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]); int x = mp_obj_get_int(args[1]); int y = mp_obj_get_int(args[2]); if (0 <= x && x <= 127 && 0 <= y && y <= 31) { uint byte_pos = x + 128 * ((uint)y >> 3); if (mp_obj_get_int(args[3]) == 0) { self->pix_buf2[byte_pos] &= ~(1 << (y & 7)); } else { self->pix_buf2[byte_pos] |= 1 << (y & 7); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_lcd_pixel_obj, 4, 4, pyb_lcd_pixel); /// \method text(str, x, y, colour) /// /// Draw the given text to the position `(x, y)` using the given colour (0 or 1). /// /// This method writes to the hidden buffer. Use `show()` to show the buffer. STATIC mp_obj_t pyb_lcd_text(size_t n_args, const mp_obj_t *args) { // extract arguments pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]); size_t len; const char *data = mp_obj_str_get_data(args[1], &len); int x0 = mp_obj_get_int(args[2]); int y0 = mp_obj_get_int(args[3]); int col = mp_obj_get_int(args[4]); // loop over chars for (const char *top = data + len; data < top; data++) { // get char and make sure its in range of font uint chr = *(byte*)data; if (chr < 32 || chr > 127) { chr = 127; } // get char data const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8]; // loop over char data for (uint j = 0; j < 8; j++, x0++) { if (0 <= x0 && x0 < LCD_PIX_BUF_W) { // clip x uint vline_data = chr_data[j]; // each byte of char data is a vertical column of 8 pixels, LSB at top for (int y = y0; vline_data; vline_data >>= 1, y++) { // scan over vertical column if (vline_data & 1) { // only draw if pixel set if (0 <= y && y < LCD_PIX_BUF_H) { // clip y uint byte_pos = x0 + LCD_PIX_BUF_W * ((uint)y >> 3); if (col == 0) { // clear pixel self->pix_buf2[byte_pos] &= ~(1 << (y & 7)); } else { // set pixel self->pix_buf2[byte_pos] |= 1 << (y & 7); } } } } } } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_lcd_text_obj, 5, 5, pyb_lcd_text); /// \method show() /// /// Show the hidden buffer on the screen. STATIC mp_obj_t pyb_lcd_show(mp_obj_t self_in) { pyb_lcd_obj_t *self = MP_OBJ_TO_PTR(self_in); memcpy(self->pix_buf, self->pix_buf2, LCD_PIX_BUF_BYTE_SIZE); for (uint page = 0; page < 4; page++) { lcd_out(self, LCD_INSTR, 0xb0 | page); // page address set lcd_out(self, LCD_INSTR, 0x10); // column address set upper; 0 lcd_out(self, LCD_INSTR, 0x00); // column address set lower; 0 for (uint i = 0; i < 128; i++) { lcd_out(self, LCD_DATA, self->pix_buf[128 * page + 127 - i]); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_lcd_show_obj, pyb_lcd_show); STATIC const mp_rom_map_elem_t pyb_lcd_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_command), MP_ROM_PTR(&pyb_lcd_command_obj) }, { MP_ROM_QSTR(MP_QSTR_contrast), MP_ROM_PTR(&pyb_lcd_contrast_obj) }, { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&pyb_lcd_light_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_lcd_write_obj) }, { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&pyb_lcd_fill_obj) }, { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&pyb_lcd_get_obj) }, { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&pyb_lcd_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&pyb_lcd_text_obj) }, { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&pyb_lcd_show_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_lcd_locals_dict, pyb_lcd_locals_dict_table); const mp_obj_type_t pyb_lcd_type = { { &mp_type_type }, .name = MP_QSTR_LCD, .make_new = pyb_lcd_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_lcd_locals_dict, }; #endif // MICROPY_HW_HAS_LCD micropython-1.12/ports/stm32/lcd.h000066400000000000000000000025531357706137100170610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_LCD_H #define MICROPY_INCLUDED_STM32_LCD_H extern const mp_obj_type_t pyb_lcd_type; #endif // MICROPY_INCLUDED_STM32_LCD_H micropython-1.12/ports/stm32/led.c000066400000000000000000000272511357706137100170600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/mphal.h" #include "timer.h" #include "led.h" #include "pin.h" #if defined(MICROPY_HW_LED1) /// \moduleref pyb /// \class LED - LED object /// /// The LED object controls an individual LED (Light Emitting Diode). // the default is that LEDs are not inverted, and pin driven high turns them on #ifndef MICROPY_HW_LED_INVERTED #define MICROPY_HW_LED_INVERTED (0) #endif typedef struct _pyb_led_obj_t { mp_obj_base_t base; mp_uint_t led_id; const pin_obj_t *led_pin; } pyb_led_obj_t; STATIC const pyb_led_obj_t pyb_led_obj[] = { {{&pyb_led_type}, 1, MICROPY_HW_LED1}, #if defined(MICROPY_HW_LED2) {{&pyb_led_type}, 2, MICROPY_HW_LED2}, #if defined(MICROPY_HW_LED3) {{&pyb_led_type}, 3, MICROPY_HW_LED3}, #if defined(MICROPY_HW_LED4) {{&pyb_led_type}, 4, MICROPY_HW_LED4}, #endif #endif #endif }; #define NUM_LEDS MP_ARRAY_SIZE(pyb_led_obj) void led_init(void) { /* Turn off LEDs and initialize */ for (int led = 0; led < NUM_LEDS; led++) { const pin_obj_t *led_pin = pyb_led_obj[led].led_pin; mp_hal_gpio_clock_enable(led_pin->gpio); MICROPY_HW_LED_OFF(led_pin); mp_hal_pin_output(led_pin); } } #if defined(MICROPY_HW_LED1_PWM) \ || defined(MICROPY_HW_LED2_PWM) \ || defined(MICROPY_HW_LED3_PWM) \ || defined(MICROPY_HW_LED4_PWM) // The following is semi-generic code to control LEDs using PWM. // It currently supports TIM1, TIM2 and TIM3, channels 1-4. // Configure by defining the relevant MICROPY_HW_LEDx_PWM macros in mpconfigboard.h. // If they are not defined then PWM will not be available for that LED. #define LED_PWM_ENABLED (1) #ifndef MICROPY_HW_LED1_PWM #define MICROPY_HW_LED1_PWM { NULL, 0, 0, 0 } #endif #ifndef MICROPY_HW_LED2_PWM #define MICROPY_HW_LED2_PWM { NULL, 0, 0, 0 } #endif #ifndef MICROPY_HW_LED3_PWM #define MICROPY_HW_LED3_PWM { NULL, 0, 0, 0 } #endif #ifndef MICROPY_HW_LED4_PWM #define MICROPY_HW_LED4_PWM { NULL, 0, 0, 0 } #endif #define LED_PWM_TIM_PERIOD (10000) // TIM runs at 1MHz and fires every 10ms // this gives the address of the CCR register for channels 1-4 #define LED_PWM_CCR(pwm_cfg) ((volatile uint32_t*)&(pwm_cfg)->tim->CCR1 + ((pwm_cfg)->tim_channel >> 2)) typedef struct _led_pwm_config_t { TIM_TypeDef *tim; uint8_t tim_id; uint8_t tim_channel; uint8_t alt_func; } led_pwm_config_t; STATIC const led_pwm_config_t led_pwm_config[] = { MICROPY_HW_LED1_PWM, MICROPY_HW_LED2_PWM, MICROPY_HW_LED3_PWM, MICROPY_HW_LED4_PWM, }; STATIC uint8_t led_pwm_state = 0; static inline bool led_pwm_is_enabled(int led) { return (led_pwm_state & (1 << led)) != 0; } // this function has a large stack so it should not be inlined STATIC void led_pwm_init(int led) __attribute__((noinline)); STATIC void led_pwm_init(int led) { const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin; const led_pwm_config_t *pwm_cfg = &led_pwm_config[led - 1]; // GPIO configuration mp_hal_pin_config(led_pin, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, pwm_cfg->alt_func); // TIM configuration switch (pwm_cfg->tim_id) { case 1: __TIM1_CLK_ENABLE(); break; case 2: __TIM2_CLK_ENABLE(); break; case 3: __TIM3_CLK_ENABLE(); break; default: assert(0); } TIM_HandleTypeDef tim = {0}; tim.Instance = pwm_cfg->tim; tim.Init.Period = LED_PWM_TIM_PERIOD - 1; tim.Init.Prescaler = timer_get_source_freq(pwm_cfg->tim_id) / 1000000 - 1; // TIM runs at 1MHz tim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; tim.Init.CounterMode = TIM_COUNTERMODE_UP; tim.Init.RepetitionCounter = 0; HAL_TIM_PWM_Init(&tim); // PWM configuration TIM_OC_InitTypeDef oc_init; oc_init.OCMode = TIM_OCMODE_PWM1; oc_init.Pulse = 0; // off oc_init.OCPolarity = MICROPY_HW_LED_INVERTED ? TIM_OCPOLARITY_LOW : TIM_OCPOLARITY_HIGH; oc_init.OCFastMode = TIM_OCFAST_DISABLE; oc_init.OCNPolarity = TIM_OCNPOLARITY_HIGH; // needed for TIM1 and TIM8 oc_init.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 oc_init.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8 HAL_TIM_PWM_ConfigChannel(&tim, &oc_init, pwm_cfg->tim_channel); HAL_TIM_PWM_Start(&tim, pwm_cfg->tim_channel); // indicate that this LED is using PWM led_pwm_state |= 1 << led; } STATIC void led_pwm_deinit(int led) { // make the LED's pin a standard GPIO output pin const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin; GPIO_TypeDef *g = led_pin->gpio; uint32_t pin = led_pin->pin; static const int mode = 1; // output static const int alt = 0; // no alt func g->MODER = (g->MODER & ~(3 << (2 * pin))) | (mode << (2 * pin)); g->AFR[pin >> 3] = (g->AFR[pin >> 3] & ~(15 << (4 * (pin & 7)))) | (alt << (4 * (pin & 7))); led_pwm_state &= ~(1 << led); } #else #define LED_PWM_ENABLED (0) #endif void led_state(pyb_led_t led, int state) { if (led < 1 || led > NUM_LEDS) { return; } const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin; //printf("led_state(%d,%d)\n", led, state); if (state == 0) { // turn LED off MICROPY_HW_LED_OFF(led_pin); } else { // turn LED on MICROPY_HW_LED_ON(led_pin); } #if LED_PWM_ENABLED if (led_pwm_is_enabled(led)) { led_pwm_deinit(led); } #endif } void led_toggle(pyb_led_t led) { if (led < 1 || led > NUM_LEDS) { return; } #if LED_PWM_ENABLED if (led_pwm_is_enabled(led)) { // if PWM is enabled then LED has non-zero intensity, so turn it off led_state(led, 0); return; } #endif // toggle the output data register to toggle the LED state const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin; led_pin->gpio->ODR ^= led_pin->pin_mask; } int led_get_intensity(pyb_led_t led) { if (led < 1 || led > NUM_LEDS) { return 0; } #if LED_PWM_ENABLED if (led_pwm_is_enabled(led)) { const led_pwm_config_t *pwm_cfg = &led_pwm_config[led - 1]; mp_uint_t i = (*LED_PWM_CCR(pwm_cfg) * 255 + LED_PWM_TIM_PERIOD - 2) / (LED_PWM_TIM_PERIOD - 1); if (i > 255) { i = 255; } return i; } #endif const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin; GPIO_TypeDef *gpio = led_pin->gpio; if (gpio->ODR & led_pin->pin_mask) { // pin is high return MICROPY_HW_LED_INVERTED ? 0 : 255; } else { // pin is low return MICROPY_HW_LED_INVERTED ? 255 : 0; } } void led_set_intensity(pyb_led_t led, mp_int_t intensity) { #if LED_PWM_ENABLED if (intensity > 0 && intensity < 255) { const led_pwm_config_t *pwm_cfg = &led_pwm_config[led - 1]; if (pwm_cfg->tim != NULL) { // set intensity using PWM pulse width if (!led_pwm_is_enabled(led)) { led_pwm_init(led); } *LED_PWM_CCR(pwm_cfg) = intensity * (LED_PWM_TIM_PERIOD - 1) / 255; return; } } #endif // intensity not supported for this LED; just turn it on/off led_state(led, intensity > 0); } void led_debug(int n, int delay) { led_state(1, n & 1); led_state(2, n & 2); led_state(3, n & 4); led_state(4, n & 8); mp_hal_delay_ms(delay); } /******************************************************************************/ /* MicroPython bindings */ void led_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_led_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "LED(%u)", self->led_id); } /// \classmethod \constructor(id) /// Create an LED object associated with the given LED: /// /// - `id` is the LED number, 1-4. STATIC mp_obj_t led_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); // get led number mp_int_t led_id = mp_obj_get_int(args[0]); // check led number if (!(1 <= led_id && led_id <= NUM_LEDS)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "LED(%d) doesn't exist", led_id)); } // return static led object return MP_OBJ_FROM_PTR(&pyb_led_obj[led_id - 1]); } /// \method on() /// Turn the LED on. mp_obj_t led_obj_on(mp_obj_t self_in) { pyb_led_obj_t *self = MP_OBJ_TO_PTR(self_in); led_state(self->led_id, 1); return mp_const_none; } /// \method off() /// Turn the LED off. mp_obj_t led_obj_off(mp_obj_t self_in) { pyb_led_obj_t *self = MP_OBJ_TO_PTR(self_in); led_state(self->led_id, 0); return mp_const_none; } /// \method toggle() /// Toggle the LED between on and off. mp_obj_t led_obj_toggle(mp_obj_t self_in) { pyb_led_obj_t *self = MP_OBJ_TO_PTR(self_in); led_toggle(self->led_id); return mp_const_none; } /// \method intensity([value]) /// Get or set the LED intensity. Intensity ranges between 0 (off) and 255 (full on). /// If no argument is given, return the LED intensity. /// If an argument is given, set the LED intensity and return `None`. mp_obj_t led_obj_intensity(size_t n_args, const mp_obj_t *args) { pyb_led_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { return mp_obj_new_int(led_get_intensity(self->led_id)); } else { led_set_intensity(self->led_id, mp_obj_get_int(args[1])); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on); STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off); STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_toggle_obj, led_obj_toggle); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(led_obj_intensity_obj, 1, 2, led_obj_intensity); STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&led_obj_on_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&led_obj_off_obj) }, { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj) }, { MP_ROM_QSTR(MP_QSTR_intensity), MP_ROM_PTR(&led_obj_intensity_obj) }, }; STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); const mp_obj_type_t pyb_led_type = { { &mp_type_type }, .name = MP_QSTR_LED, .print = led_obj_print, .make_new = led_obj_make_new, .locals_dict = (mp_obj_dict_t*)&led_locals_dict, }; #else // For boards with no LEDs, we leave an empty function here so that we don't // have to put conditionals everywhere. void led_init(void) { } void led_state(pyb_led_t led, int state) { } void led_toggle(pyb_led_t led) { } #endif // defined(MICROPY_HW_LED1) micropython-1.12/ports/stm32/led.h000066400000000000000000000031501357706137100170550ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_LED_H #define MICROPY_INCLUDED_STM32_LED_H typedef enum { PYB_LED_RED = 1, PYB_LED_GREEN = 2, PYB_LED_YELLOW = 3, PYB_LED_BLUE = 4, } pyb_led_t; void led_init(void); void led_state(pyb_led_t led, int state); void led_toggle(pyb_led_t led); void led_debug(int value, int delay); extern const mp_obj_type_t pyb_led_type; #endif // MICROPY_INCLUDED_STM32_LED_H micropython-1.12/ports/stm32/lwip_inc/000077500000000000000000000000001357706137100177455ustar00rootroot00000000000000micropython-1.12/ports/stm32/lwip_inc/arch/000077500000000000000000000000001357706137100206625ustar00rootroot00000000000000micropython-1.12/ports/stm32/lwip_inc/arch/cc.h000066400000000000000000000004131357706137100214160ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H #define MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H #include #define LWIP_PLATFORM_DIAG(x) #define LWIP_PLATFORM_ASSERT(x) { assert(1); } #define LWIP_NO_CTYPE_H 1 #endif // MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H micropython-1.12/ports/stm32/lwip_inc/arch/sys_arch.h000066400000000000000000000000111357706137100226360ustar00rootroot00000000000000// empty micropython-1.12/ports/stm32/lwip_inc/lwipopts.h000066400000000000000000000046221357706137100220030ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_STM32_LWIP_LWIPOPTS_H #define MICROPY_INCLUDED_STM32_LWIP_LWIPOPTS_H #include // This protection is not needed, instead we execute all lwIP code at PendSV priority #define SYS_ARCH_DECL_PROTECT(lev) do { } while (0) #define SYS_ARCH_PROTECT(lev) do { } while (0) #define SYS_ARCH_UNPROTECT(lev) do { } while (0) #define NO_SYS 1 #define SYS_LIGHTWEIGHT_PROT 1 #define MEM_ALIGNMENT 4 #define LWIP_CHKSUM_ALGORITHM 3 #define LWIP_CHECKSUM_CTRL_PER_NETIF 1 #define LWIP_ARP 1 #define LWIP_ETHERNET 1 #define LWIP_RAW 1 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 #define LWIP_STATS 0 #define LWIP_NETIF_HOSTNAME 1 #define LWIP_NETIF_EXT_STATUS_CALLBACK 1 #define LWIP_IPV6 0 #define LWIP_DHCP 1 #define LWIP_DHCP_CHECK_LINK_UP 1 #define DHCP_DOES_ARP_CHECK 0 // to speed DHCP up #define LWIP_DNS 1 #define LWIP_DNS_SUPPORT_MDNS_QUERIES 1 #define LWIP_MDNS_RESPONDER 1 #define LWIP_IGMP 1 #define LWIP_NUM_NETIF_CLIENT_DATA LWIP_MDNS_RESPONDER #define MEMP_NUM_UDP_PCB (4 + LWIP_MDNS_RESPONDER) #define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL + LWIP_MDNS_RESPONDER) #define SO_REUSE 1 #define TCP_LISTEN_BACKLOG 1 extern uint32_t rng_get(void); #define LWIP_RAND() rng_get() // default // lwip takes 15800 bytes; TCP d/l: 380k/s local, 7.2k/s remote // TCP u/l is very slow #if 0 // lwip takes 19159 bytes; TCP d/l and u/l are around 320k/s on local network #define MEM_SIZE (5000) #define TCP_WND (4 * TCP_MSS) #define TCP_SND_BUF (4 * TCP_MSS) #endif #if 1 // lwip takes 26700 bytes; TCP dl/ul are around 750/600 k/s on local network #define MEM_SIZE (8000) #define TCP_MSS (800) #define TCP_WND (8 * TCP_MSS) #define TCP_SND_BUF (8 * TCP_MSS) #define MEMP_NUM_TCP_SEG (32) #endif #if 0 // lwip takes 45600 bytes; TCP dl/ul are around 1200/1000 k/s on local network #define MEM_SIZE (16000) #define TCP_MSS (1460) #define TCP_WND (8 * TCP_MSS) #define TCP_SND_BUF (8 * TCP_MSS) #define MEMP_NUM_TCP_SEG (32) #endif typedef uint32_t sys_prot_t; #endif // MICROPY_INCLUDED_STM32_LWIP_LWIPOPTS_H micropython-1.12/ports/stm32/machine_adc.c000066400000000000000000000345501357706137100205270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mphal.h" #if defined(STM32F0) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) #define ADC_V2 (1) #else #define ADC_V2 (0) #endif #if defined(STM32F4) || defined(STM32L4) #define ADCx_COMMON ADC_COMMON_REGISTER(0) #elif defined(STM32F7) #define ADCx_COMMON ADC123_COMMON #endif #if defined(STM32F0) || defined(STM32L0) #define ADC_STAB_DELAY_US (1) #define ADC_TEMPSENSOR_DELAY_US (10) #elif defined(STM32L4) #define ADC_STAB_DELAY_US (10) #elif defined(STM32WB) #define ADC_STAB_DELAY_US (1) #endif #if defined(STM32F0) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_13CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_239CYCLES_5 #elif defined(STM32F4) || defined(STM32F7) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_15CYCLES #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_480CYCLES #elif defined(STM32H7) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_8CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_387CYCLES_5 #elif defined(STM32L0) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_160CYCLES_5 #elif defined(STM32L4) || defined(STM32WB) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5 #endif // Timeout for waiting for end-of-conversion #define ADC_EOC_TIMEOUT_MS (10) // This is a synthesised channel representing the maximum ADC reading (useful to scale other channels) #define ADC_CHANNEL_VREF (0xffff) static inline void adc_stabilisation_delay_us(uint32_t us) { mp_hal_delay_us(us + 1); } STATIC void adc_wait_eoc(ADC_TypeDef *adc, int32_t timeout_ms) { uint32_t t0 = mp_hal_ticks_ms(); #if ADC_V2 while (!(adc->ISR & ADC_ISR_EOC)) #else while (!(adc->SR & ADC_SR_EOC)) #endif { if (mp_hal_ticks_ms() - t0 > timeout_ms) { break; // timeout } } } #if defined(STM32H7) STATIC const uint8_t adc_cr_to_bits_table[] = {16, 14, 12, 10, 8, 8, 8, 8}; #else STATIC const uint8_t adc_cr_to_bits_table[] = {12, 10, 8, 6}; #endif STATIC void adc_config(ADC_TypeDef *adc, uint32_t bits) { // Configure ADC clock source and enable ADC clock #if defined(STM32L4) || defined(STM32WB) __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); __HAL_RCC_ADC_CLK_ENABLE(); #else if (adc == ADC1) { #if defined(STM32H7) __HAL_RCC_ADC12_CLK_ENABLE(); #else __HAL_RCC_ADC1_CLK_ENABLE(); #endif } #if defined(ADC2) if (adc == ADC2) { #if defined(STM32H7) __HAL_RCC_ADC12_CLK_ENABLE(); #else __HAL_RCC_ADC2_CLK_ENABLE(); #endif } #endif #if defined(ADC3) if (adc == ADC3) { __HAL_RCC_ADC3_CLK_ENABLE(); } #endif #endif // Configure clock mode #if defined(STM32F0) adc->CFGR2 = 2 << ADC_CFGR2_CKMODE_Pos; // PCLK/4 (synchronous clock mode) #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L4) ADCx_COMMON->CCR = 0; // ADCPR=PCLK/2 #elif defined(STM32H7) ADC12_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; ADC3_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; #elif defined(STM32L0) || defined(STM32WB) ADC1_COMMON->CCR = 0; // ADCPR=PCLK/2 #endif #if defined(STM32H7) || defined(STM32L4) || defined(STM32WB) if (adc->CR & ADC_CR_DEEPPWD) { adc->CR = 0; // disable deep powerdown } #endif #if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) if (!(adc->CR & ADC_CR_ADVREGEN)) { adc->CR = ADC_CR_ADVREGEN; // enable VREG #if defined(STM32H7) mp_hal_delay_us(10); // T_ADCVREG_STUP #elif defined(STM32L4) || defined(STM32WB) mp_hal_delay_us(20); // T_ADCVREG_STUP #endif } #endif #if ADC_V2 if (adc->CR == 0) { // ADC hasn't been enabled so calibrate it adc->CR |= ADC_CR_ADCAL; while (adc->CR & ADC_CR_ADCAL) { } } if (adc->CR & ADC_CR_ADEN) { // ADC enabled, need to disable it to change configuration if (adc->CR & ADC_CR_ADSTART) { adc->CR |= ADC_CR_ADSTP; while (adc->CR & ADC_CR_ADSTP) { } } adc->CR |= ADC_CR_ADDIS; while (adc->CR & ADC_CR_ADDIS) { } } #endif // Find resolution, defaulting to last element in table uint32_t res; for (res = 0; res <= MP_ARRAY_SIZE(adc_cr_to_bits_table); ++res) { if (adc_cr_to_bits_table[res] == bits) { break; } } #if defined(STM32F0) || defined(STM32L0) uint32_t cfgr1_clr = ADC_CFGR1_CONT | ADC_CFGR1_EXTEN | ADC_CFGR1_ALIGN | ADC_CFGR1_RES | ADC_CFGR1_DMAEN; uint32_t cfgr1 = res << ADC_CFGR1_RES_Pos; adc->CFGR1 = (adc->CFGR1 & ~cfgr1_clr) | cfgr1; #elif defined(STM32F4) || defined(STM32F7) uint32_t cr1_clr = ADC_CR1_RES; uint32_t cr1 = res << ADC_CR1_RES_Pos; adc->CR1 = (adc->CR1 & ~cr1_clr) | cr1; uint32_t cr2_clr = ADC_CR2_EXTEN | ADC_CR2_ALIGN | ADC_CR2_DMA | ADC_CR2_CONT; uint32_t cr2 = 0; adc->CR2 = (adc->CR2 & ~cr2_clr) | cr2; adc->SQR1 = 1 << ADC_SQR1_L_Pos; // 1 conversion in regular sequence #elif defined(STM32H7) || defined(STM32L4) || defined(STM32WB) uint32_t cfgr_clr = ADC_CFGR_CONT | ADC_CFGR_EXTEN | ADC_CFGR_RES; #if defined(STM32H7) cfgr_clr |= ADC_CFGR_DMNGT; #else cfgr_clr |= ADC_CFGR_ALIGN | ADC_CFGR_DMAEN; #endif uint32_t cfgr = res << ADC_CFGR_RES_Pos; adc->CFGR = (adc->CFGR & ~cfgr_clr) | cfgr; #endif } STATIC int adc_get_bits(ADC_TypeDef *adc) { #if defined(STM32F0) || defined(STM32L0) uint32_t res = (adc->CFGR1 & ADC_CFGR1_RES) >> ADC_CFGR1_RES_Pos; #elif defined(STM32F4) || defined(STM32F7) uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos; #elif defined(STM32H7) || defined(STM32L4) || defined(STM32WB) uint32_t res = (adc->CFGR & ADC_CFGR_RES) >> ADC_CFGR_RES_Pos; #endif return adc_cr_to_bits_table[res]; } STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t sample_time) { #if ADC_V2 if (!(adc->CR & ADC_CR_ADEN)) { if (adc->CR & 0x3f) { // Cannot enable ADC with CR!=0 return; } adc->ISR = ADC_ISR_ADRDY; // clear ADRDY adc->CR |= ADC_CR_ADEN; adc_stabilisation_delay_us(ADC_STAB_DELAY_US); while (!(adc->ISR & ADC_ISR_ADRDY)) { } } #else if (!(adc->CR2 & ADC_CR2_ADON)) { adc->CR2 |= ADC_CR2_ADON; adc_stabilisation_delay_us(ADC_STAB_DELAY_US); } #endif #if defined(STM32F0) || defined(STM32L0) if (channel == ADC_CHANNEL_VREFINT) { ADC1_COMMON->CCR |= ADC_CCR_VREFEN; } else if (channel == ADC_CHANNEL_TEMPSENSOR) { ADC1_COMMON->CCR |= ADC_CCR_TSEN; adc_stabilisation_delay_us(ADC_TEMPSENSOR_DELAY_US); #if defined(ADC_CHANNEL_VBAT) } else if (channel == ADC_CHANNEL_VBAT) { ADC1_COMMON->CCR |= ADC_CCR_VBATEN; #endif } adc->SMPR = sample_time << ADC_SMPR_SMP_Pos; // select sample time adc->CHSELR = 1 << channel; // select channel for conversion #elif defined(STM32F4) || defined(STM32F7) if (channel == ADC_CHANNEL_VREFINT || channel == ADC_CHANNEL_TEMPSENSOR) { ADCx_COMMON->CCR = (ADCx_COMMON->CCR & ~ADC_CCR_VBATE) | ADC_CCR_TSVREFE; if (channel == ADC_CHANNEL_TEMPSENSOR) { adc_stabilisation_delay_us(ADC_TEMPSENSOR_DELAY_US); } } else if (channel == ADC_CHANNEL_VBAT) { ADCx_COMMON->CCR |= ADC_CCR_VBATE; } adc->SQR3 = (channel & 0x1f) << ADC_SQR3_SQ1_Pos; // select channel for first conversion __IO uint32_t *smpr; if (channel <= 9) { smpr = &adc->SMPR2; } else { smpr = &adc->SMPR1; channel -= 10; } *smpr = (*smpr & ~(7 << (channel * 3))) | sample_time << (channel * 3); // select sample time #elif defined(STM32H7) || defined(STM32L4) || defined(STM32WB) #if defined(STM32H7) adc->PCSEL |= 1 << channel; ADC_Common_TypeDef *adc_common = adc == ADC3 ? ADC3_COMMON : ADC12_COMMON; #elif defined(STM32L4) ADC_Common_TypeDef *adc_common = ADCx_COMMON; #elif defined(STM32WB) ADC_Common_TypeDef *adc_common = ADC1_COMMON; #endif if (channel == ADC_CHANNEL_VREFINT) { adc_common->CCR |= ADC_CCR_VREFEN; } else if (channel == ADC_CHANNEL_TEMPSENSOR) { adc_common->CCR |= ADC_CCR_TSEN; adc_stabilisation_delay_us(ADC_TEMPSENSOR_DELAY_US); } else if (channel == ADC_CHANNEL_VBAT) { adc_common->CCR |= ADC_CCR_VBATEN; } adc->SQR1 = (channel & 0x1f) << ADC_SQR1_SQ1_Pos | (1 - 1) << ADC_SQR1_L_Pos; __IO uint32_t *smpr; if (channel <= 9) { smpr = &adc->SMPR1; } else { smpr = &adc->SMPR2; channel -= 10; } *smpr = (*smpr & ~(7 << (channel * 3))) | sample_time << (channel * 3); // select sample time #endif } STATIC uint32_t adc_read_channel(ADC_TypeDef *adc) { #if ADC_V2 adc->CR |= ADC_CR_ADSTART; #else adc->CR2 |= ADC_CR2_SWSTART; #endif adc_wait_eoc(adc, ADC_EOC_TIMEOUT_MS); uint32_t value = adc->DR; return value; } STATIC uint32_t adc_config_and_read_u16(ADC_TypeDef *adc, uint32_t channel, uint32_t sample_time) { if (channel == ADC_CHANNEL_VREF) { return 0xffff; } adc_config_channel(adc, channel, sample_time); uint32_t raw = adc_read_channel(adc); uint32_t bits = adc_get_bits(adc); // Scale raw reading to 16 bit value using a Taylor expansion (for 8 <= bits <= 16) #if defined(STM32H7) if (bits < 8) { // For 6 and 7 bits return raw << (16 - bits) | raw << (16 - 2 * bits) | raw >> (3 * bits - 16); } #endif return raw << (16 - bits) | raw >> (2 * bits - 16); } /******************************************************************************/ // MicroPython bindings for machine.ADC const mp_obj_type_t machine_adc_type; typedef struct _machine_adc_obj_t { mp_obj_base_t base; ADC_TypeDef *adc; uint32_t channel; uint32_t sample_time; } machine_adc_obj_t; STATIC void machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); unsigned adc_id = 1; #if defined(ADC2) if (self->adc == ADC2) { adc_id = 2; } #endif #if defined(ADC3) if (self->adc == ADC3) { adc_id = 3; } #endif mp_printf(print, "", adc_id, self->channel); } // ADC(id) STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // Check number of arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_obj_t source = all_args[0]; uint32_t channel; uint32_t sample_time = ADC_SAMPLETIME_DEFAULT; ADC_TypeDef *adc; if (mp_obj_is_int(source)) { adc = ADC1; channel = mp_obj_get_int(source); if (channel == ADC_CHANNEL_VREFINT || channel == ADC_CHANNEL_TEMPSENSOR #if defined(ADC_CHANNEL_VBAT) || channel == ADC_CHANNEL_VBAT #endif ) { sample_time = ADC_SAMPLETIME_DEFAULT_INT; } } else { const pin_obj_t *pin = pin_find(source); if (pin->adc_num & PIN_ADC1) { adc = ADC1; #if defined(ADC2) } else if (pin->adc_num & PIN_ADC2) { adc = ADC2; #endif #if defined(ADC2) } else if (pin->adc_num & PIN_ADC3) { adc = ADC3; #endif } else { // No ADC function on given pin nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Pin(%q) does not have ADC capabilities", pin->name)); } channel = pin->adc_channel; // Configure the GPIO pin in ADC mode mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0); } adc_config(adc, 12); machine_adc_obj_t *o = m_new_obj(machine_adc_obj_t); o->base.type = &machine_adc_type; o->adc = adc; o->channel = channel; o->sample_time = sample_time; return MP_OBJ_FROM_PTR(o); } // read_u16() STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) { machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(adc_config_and_read_u16(self->adc, self->channel, self->sample_time)); } MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16); STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) }, { MP_ROM_QSTR(MP_QSTR_VREF), MP_ROM_INT(ADC_CHANNEL_VREF) }, { MP_ROM_QSTR(MP_QSTR_CORE_VREF), MP_ROM_INT(ADC_CHANNEL_VREFINT) }, { MP_ROM_QSTR(MP_QSTR_CORE_TEMP), MP_ROM_INT(ADC_CHANNEL_TEMPSENSOR) }, #if defined(ADC_CHANNEL_VBAT) { MP_ROM_QSTR(MP_QSTR_CORE_VBAT), MP_ROM_INT(ADC_CHANNEL_VBAT) }, #endif }; STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); const mp_obj_type_t machine_adc_type = { { &mp_type_type }, .name = MP_QSTR_ADC, .print = machine_adc_print, .make_new = machine_adc_make_new, .locals_dict = (mp_obj_dict_t*)&machine_adc_locals_dict, }; micropython-1.12/ports/stm32/machine_i2c.c000066400000000000000000000235061357706137100204540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "py/mperrno.h" #include "extmod/machine_i2c.h" #include "i2c.h" #if MICROPY_HW_ENABLE_HW_I2C STATIC const mp_obj_type_t machine_hard_i2c_type; #define I2C_POLL_DEFAULT_TIMEOUT_US (50000) // 50ms #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) typedef struct _machine_hard_i2c_obj_t { mp_obj_base_t base; i2c_t *i2c; mp_hal_pin_obj_t scl; mp_hal_pin_obj_t sda; } machine_hard_i2c_obj_t; STATIC const machine_hard_i2c_obj_t machine_hard_i2c_obj[MICROPY_HW_MAX_I2C] = { #if defined(MICROPY_HW_I2C1_SCL) [0] = {{&machine_hard_i2c_type}, I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, #endif #if defined(MICROPY_HW_I2C2_SCL) [1] = {{&machine_hard_i2c_type}, I2C2, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, #endif #if defined(MICROPY_HW_I2C3_SCL) [2] = {{&machine_hard_i2c_type}, I2C3, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, #endif #if defined(MICROPY_HW_I2C4_SCL) [3] = {{&machine_hard_i2c_type}, I2C4, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, #endif }; STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); #if defined(STM32F4) uint32_t freq = self->i2c->CR2 & 0x3f; uint32_t ccr = self->i2c->CCR; if (ccr & 0x8000) { // Fast mode, assume duty cycle of 16/9 freq = freq * 40000 / (ccr & 0xfff); } else { // Standard mode freq = freq * 500000 / (ccr & 0xfff); } mp_printf(print, "I2C(%u, scl=%q, sda=%q, freq=%u)", self - &machine_hard_i2c_obj[0] + 1, mp_hal_pin_name(self->scl), mp_hal_pin_name(self->sda), freq); #else uint32_t timingr = self->i2c->TIMINGR; uint32_t presc = timingr >> 28; uint32_t sclh = timingr >> 8 & 0xff; uint32_t scll = timingr & 0xff; uint32_t freq = HAL_RCC_GetPCLK1Freq() / (presc + 1) / (sclh + scll + 2); mp_printf(print, "I2C(%u, scl=%q, sda=%q, freq=%u, timingr=0x%08x)", self - &machine_hard_i2c_obj[0] + 1, mp_hal_pin_name(self->scl), mp_hal_pin_name(self->sda), freq, timingr); #endif } void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, uint32_t timeout_us) { uint32_t timeout_ms = (timeout_us + 999) / 1000; i2c_init(self->i2c, self->scl, self->sda, freq, timeout_ms); } int machine_hard_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); size_t remain_len = 0; for (size_t i = 0; i < n; ++i) { remain_len += bufs[i].len; } int ret = i2c_start_addr(self->i2c, flags & MP_MACHINE_I2C_FLAG_READ, addr, remain_len, flags & MP_MACHINE_I2C_FLAG_STOP); if (ret < 0) { return ret; } int num_acks = 0; // only valid for write; for read it'll be 0 for (; n--; ++bufs) { remain_len -= bufs->len; if (flags & MP_MACHINE_I2C_FLAG_READ) { ret = i2c_read(self->i2c, bufs->buf, bufs->len, remain_len); } else { ret = i2c_write(self->i2c, bufs->buf, bufs->len, remain_len); } if (ret < 0) { return ret; } num_acks += ret; } return num_acks; } #else // No hardware I2C driver for this MCU so use the software implementation typedef mp_machine_soft_i2c_obj_t machine_hard_i2c_obj_t; STATIC machine_hard_i2c_obj_t machine_hard_i2c_obj[MICROPY_HW_MAX_I2C] = { #if defined(MICROPY_HW_I2C1_SCL) [0] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, #endif #if defined(MICROPY_HW_I2C2_SCL) [1] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, #endif #if defined(MICROPY_HW_I2C3_SCL) [2] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, #endif #if defined(MICROPY_HW_I2C4_SCL) [3] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, #endif }; STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "I2C(%u, scl=%q, sda=%q, freq=%u, timeout=%u)", self - &machine_hard_i2c_obj[0] + 1, self->scl->name, self->sda->name, 500000 / self->us_delay, self->us_timeout); } STATIC void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, uint32_t timeout) { // set parameters if (freq >= 1000000) { // allow fastest possible bit-bang rate self->us_delay = 0; } else { self->us_delay = 500000 / freq; if (self->us_delay == 0) { self->us_delay = 1; } } self->us_timeout = timeout; // init pins mp_hal_pin_open_drain(self->scl); mp_hal_pin_open_drain(self->sda); } #define machine_hard_i2c_transfer mp_machine_soft_i2c_transfer #endif /******************************************************************************/ /* MicroPython bindings for machine API */ #if defined(STM32F0) || defined(STM32F7) #define MACHINE_I2C_TIMINGR (1) #else #define MACHINE_I2C_TIMINGR (0) #endif mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout, ARG_timingr }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2C_POLL_DEFAULT_TIMEOUT_US} }, #if MACHINE_I2C_TIMINGR { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, #endif }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // work out i2c bus int i2c_id = 0; if (mp_obj_is_str(args[ARG_id].u_obj)) { const char *port = mp_obj_str_get_str(args[ARG_id].u_obj); if (0) { #ifdef MICROPY_HW_I2C1_NAME } else if (strcmp(port, MICROPY_HW_I2C1_NAME) == 0) { i2c_id = 1; #endif #ifdef MICROPY_HW_I2C2_NAME } else if (strcmp(port, MICROPY_HW_I2C2_NAME) == 0) { i2c_id = 2; #endif #ifdef MICROPY_HW_I2C3_NAME } else if (strcmp(port, MICROPY_HW_I2C3_NAME) == 0) { i2c_id = 3; #endif #ifdef MICROPY_HW_I2C4_NAME } else if (strcmp(port, MICROPY_HW_I2C4_NAME) == 0) { i2c_id = 4; #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%s) doesn't exist", port)); } } else { i2c_id = mp_obj_get_int(args[ARG_id].u_obj); if (i2c_id < 1 || i2c_id > MP_ARRAY_SIZE(machine_hard_i2c_obj) || machine_hard_i2c_obj[i2c_id - 1].base.type == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%d) doesn't exist", i2c_id)); } } // get static peripheral object machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)&machine_hard_i2c_obj[i2c_id - 1]; // here we would check the scl/sda pins and configure them, but it's not implemented if (args[ARG_scl].u_obj != MP_OBJ_NULL || args[ARG_sda].u_obj != MP_OBJ_NULL) { mp_raise_ValueError("explicit choice of scl/sda is not implemented"); } // initialise the I2C peripheral machine_hard_i2c_init(self, args[ARG_freq].u_int, args[ARG_timeout].u_int); #if MACHINE_I2C_TIMINGR // If given, explicitly set the TIMINGR value if (args[ARG_timingr].u_obj != mp_const_none) { self->i2c->TIMINGR = mp_obj_get_int_truncated(args[ARG_timingr].u_obj); } #endif return MP_OBJ_FROM_PTR(self); } STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { .transfer = machine_hard_i2c_transfer, }; STATIC const mp_obj_type_t machine_hard_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, .print = machine_hard_i2c_print, .make_new = machine_hard_i2c_make_new, .protocol = &machine_hard_i2c_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict, }; #endif // MICROPY_HW_ENABLE_HW_I2C micropython-1.12/ports/stm32/machine_spi.c000066400000000000000000000142621357706137100205710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "extmod/machine_spi.h" #include "spi.h" /******************************************************************************/ // Implementation of hard SPI for machine module STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = { {{&machine_hard_spi_type}, &spi_obj[0]}, {{&machine_hard_spi_type}, &spi_obj[1]}, {{&machine_hard_spi_type}, &spi_obj[2]}, {{&machine_hard_spi_type}, &spi_obj[3]}, {{&machine_hard_spi_type}, &spi_obj[4]}, {{&machine_hard_spi_type}, &spi_obj[5]}, }; STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hard_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); spi_print(print, self->spi, false); } mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_FIRSTBIT_MSB} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get static peripheral object int spi_id = spi_find_index(args[ARG_id].u_obj); const machine_hard_spi_obj_t *self = &machine_hard_spi_obj[spi_id - 1]; // here we would check the sck/mosi/miso pins and configure them, but it's not implemented if (args[ARG_sck].u_obj != MP_OBJ_NULL || args[ARG_mosi].u_obj != MP_OBJ_NULL || args[ARG_miso].u_obj != MP_OBJ_NULL) { mp_raise_ValueError("explicit choice of sck/mosi/miso is not implemented"); } // set the SPI configuration values SPI_InitTypeDef *init = &self->spi->spi->Init; init->Mode = SPI_MODE_MASTER; // these parameters are not currently configurable init->Direction = SPI_DIRECTION_2LINES; init->NSS = SPI_NSS_SOFT; init->TIMode = SPI_TIMODE_DISABLE; init->CRCCalculation = SPI_CRCCALCULATION_DISABLE; init->CRCPolynomial = 0; // set configurable paramaters spi_set_params(self->spi, 0xffffffff, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, args[ARG_phase].u_int, args[ARG_bits].u_int, args[ARG_firstbit].u_int); // init the SPI bus spi_init(self->spi, false); return MP_OBJ_FROM_PTR(self); } STATIC void machine_hard_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in; enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // set the SPI configuration values spi_set_params(self->spi, 0xffffffff, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, args[ARG_phase].u_int, args[ARG_bits].u_int, args[ARG_firstbit].u_int); // re-init the SPI bus spi_init(self->spi, false); } STATIC void machine_hard_spi_deinit(mp_obj_base_t *self_in) { machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in; spi_deinit(self->spi); } STATIC void machine_hard_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in; spi_transfer(self->spi, len, src, dest, SPI_TRANSFER_TIMEOUT(len)); } STATIC const mp_machine_spi_p_t machine_hard_spi_p = { .init = machine_hard_spi_init, .deinit = machine_hard_spi_deinit, .transfer = machine_hard_spi_transfer, }; const mp_obj_type_t machine_hard_spi_type = { { &mp_type_type }, .name = MP_QSTR_SPI, .print = machine_hard_spi_print, .make_new = mp_machine_spi_make_new, // delegate to master constructor .protocol = &machine_hard_spi_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_spi_locals_dict, }; micropython-1.12/ports/stm32/machine_timer.c000066400000000000000000000122651357706137100211170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mphal.h" #include "softtimer.h" typedef soft_timer_entry_t machine_timer_obj_t; const mp_obj_type_t machine_timer_type; STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_timer_obj_t *self = self_in; qstr mode = self->mode == SOFT_TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC; mp_printf(print, "Timer(mode=%q, period=%u)", mode, self->delta_ms); } STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SOFT_TIMER_MODE_PERIODIC} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // Parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); self->mode = args[ARG_mode].u_int; if (args[ARG_freq].u_obj != mp_const_none) { // Frequency specified in Hz #if MICROPY_PY_BUILTINS_FLOAT self->delta_ms = 1000 / mp_obj_get_float(args[ARG_freq].u_obj); #else self->delta_ms = 1000 / mp_obj_get_int(args[ARG_freq].u_obj); #endif } else { // Period specified self->delta_ms = args[ARG_period].u_int * 1000 / args[ARG_tick_hz].u_int; } if (self->delta_ms < 1) { self->delta_ms = 1; } self->expiry_ms = mp_hal_ticks_ms() + self->delta_ms; self->callback = args[ARG_callback].u_obj; soft_timer_insert(self); return mp_const_none; } STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); self->base.type = &machine_timer_type; // Get timer id (only soft timer (-1) supported at the moment) mp_int_t id = -1; if (n_args > 0) { id = mp_obj_get_int(args[0]); --n_args; ++args; } if (id != -1) { mp_raise_ValueError("Timer doesn't exist"); } if (n_args > 0 || n_kw > 0) { // Start the timer mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); machine_timer_init_helper(self, n_args, args, &kw_args); } return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]); soft_timer_remove(self); return machine_timer_init_helper(self, n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init); STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) { machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); soft_timer_remove(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(SOFT_TIMER_MODE_ONE_SHOT) }, { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(SOFT_TIMER_MODE_PERIODIC) }, }; STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); const mp_obj_type_t machine_timer_type = { { &mp_type_type }, .name = MP_QSTR_Timer, .print = machine_timer_print, .make_new = machine_timer_make_new, .locals_dict = (mp_obj_dict_t*)&machine_timer_locals_dict, }; micropython-1.12/ports/stm32/machine_uart.c000066400000000000000000000574531357706137100207620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "lib/utils/interrupt_char.h" #include "lib/utils/mpirq.h" #include "uart.h" #include "irq.h" #include "pendsv.h" /// \moduleref pyb /// \class UART - duplex serial communication bus /// /// UART implements the standard UART/USART duplex serial communications protocol. At /// the physical level it consists of 2 lines: RX and TX. The unit of communication /// is a character (not to be confused with a string character) which can be 8 or 9 /// bits wide. /// /// UART objects can be created and initialised using: /// /// from pyb import UART /// /// uart = UART(1, 9600) # init with given baudrate /// uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters /// /// Bits can be 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2. /// /// A UART object acts like a stream object and reading and writing is done /// using the standard stream methods: /// /// uart.read(10) # read 10 characters, returns a bytes object /// uart.read() # read all available characters /// uart.readline() # read a line /// uart.readinto(buf) # read and store into the given buffer /// uart.write('abc') # write the 3 characters /// /// Individual characters can be read/written using: /// /// uart.readchar() # read 1 character and returns it as an integer /// uart.writechar(42) # write 1 character /// /// To check if there is anything to be read, use: /// /// uart.any() # returns True if any characters waiting typedef struct _pyb_uart_irq_map_t { uint16_t irq_en; uint16_t flag; } pyb_uart_irq_map_t; STATIC const pyb_uart_irq_map_t mp_irq_map[] = { { USART_CR1_IDLEIE, UART_FLAG_IDLE}, // RX idle { USART_CR1_PEIE, UART_FLAG_PE}, // parity error { USART_CR1_TXEIE, UART_FLAG_TXE}, // TX register empty { USART_CR1_TCIE, UART_FLAG_TC}, // TX complete { USART_CR1_RXNEIE, UART_FLAG_RXNE}, // RX register not empty #if 0 // For now only IRQs selected by CR1 are supported #if defined(STM32F4) { USART_CR2_LBDIE, UART_FLAG_LBD}, // LIN break detection #else { USART_CR2_LBDIE, UART_FLAG_LBDF}, // LIN break detection #endif { USART_CR3_CTSIE, UART_FLAG_CTS}, // CTS #endif }; // OR-ed IRQ flags which should not be touched by the user STATIC const uint32_t mp_irq_reserved = UART_FLAG_RXNE; // OR-ed IRQ flags which are allowed to be used by the user STATIC const uint32_t mp_irq_allowed = UART_FLAG_IDLE; STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC void pyb_uart_irq_config(pyb_uart_obj_t *self, bool enable) { if (self->mp_irq_trigger) { for (size_t entry = 0; entry < MP_ARRAY_SIZE(mp_irq_map); ++entry) { if (mp_irq_map[entry].flag & mp_irq_reserved) { continue; } if (mp_irq_map[entry].flag & self->mp_irq_trigger) { if (enable) { self->uartx->CR1 |= mp_irq_map[entry].irq_en; } else { self->uartx->CR1 &= ~mp_irq_map[entry].irq_en; } } } } } STATIC mp_uint_t pyb_uart_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); pyb_uart_irq_config(self, false); self->mp_irq_trigger = new_trigger; pyb_uart_irq_config(self, true); return 0; } STATIC mp_uint_t pyb_uart_irq_info(mp_obj_t self_in, mp_uint_t info_type) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); if (info_type == MP_IRQ_INFO_FLAGS) { return self->mp_irq_flags; } else if (info_type == MP_IRQ_INFO_TRIGGERS) { return self->mp_irq_trigger; } return 0; } STATIC const mp_irq_methods_t pyb_uart_irq_methods = { .init = pyb_uart_irq, .trigger = pyb_uart_irq_trigger, .info = pyb_uart_irq_info, }; STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!self->is_enabled) { mp_printf(print, "UART(%u)", self->uart_id); } else { mp_int_t bits; uint32_t cr1 = self->uartx->CR1; #if defined(UART_CR1_M1) if (cr1 & UART_CR1_M1) { bits = 7; } else if (cr1 & UART_CR1_M0) { bits = 9; } else { bits = 8; } #else if (cr1 & USART_CR1_M) { bits = 9; } else { bits = 8; } #endif if (cr1 & USART_CR1_PCE) { bits -= 1; } mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=", self->uart_id, uart_get_baudrate(self), bits); if (!(cr1 & USART_CR1_PCE)) { mp_print_str(print, "None"); } else if (!(cr1 & USART_CR1_PS)) { mp_print_str(print, "0"); } else { mp_print_str(print, "1"); } uint32_t cr2 = self->uartx->CR2; mp_printf(print, ", stop=%u, flow=", ((cr2 >> USART_CR2_STOP_Pos) & 3) == 0 ? 1 : 2); uint32_t cr3 = self->uartx->CR3; if (!(cr3 & (USART_CR3_CTSE | USART_CR3_RTSE))) { mp_print_str(print, "0"); } else { if (cr3 & USART_CR3_RTSE) { mp_print_str(print, "RTS"); if (cr3 & USART_CR3_CTSE) { mp_print_str(print, "|"); } } if (cr3 & USART_CR3_CTSE) { mp_print_str(print, "CTS"); } } mp_printf(print, ", timeout=%u, timeout_char=%u, rxbuf=%u", self->timeout, self->timeout_char, self->read_buf_len == 0 ? 0 : self->read_buf_len - 1); // -1 to adjust for usable length of buffer if (self->mp_irq_trigger != 0) { mp_printf(print, "; irq=0x%x", self->mp_irq_trigger); } mp_print_str(print, ")"); } } /// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0, flow=0, read_buf_len=64) /// /// Initialise the UART bus with the given parameters: /// /// - `baudrate` is the clock rate. /// - `bits` is the number of bits per byte, 7, 8 or 9. /// - `parity` is the parity, `None`, 0 (even) or 1 (odd). /// - `stop` is the number of stop bits, 1 or 2. /// - `timeout` is the timeout in milliseconds to wait for the first character. /// - `timeout_char` is the timeout in milliseconds to wait between characters. /// - `flow` is RTS | CTS where RTS == 256, CTS == 512 /// - `read_buf_len` is the character length of the read buffer (0 to disable). STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_parity, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_HWCONTROL_NONE} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_read_buf_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, // legacy }; // parse args struct { mp_arg_val_t baudrate, bits, parity, stop, flow, timeout, timeout_char, rxbuf, read_buf_len; } args; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); // static UARTs are used for internal purposes and shouldn't be reconfigured if (self->is_static) { mp_raise_ValueError("UART is static and can't be init'd"); } // baudrate uint32_t baudrate = args.baudrate.u_int; // parity uint32_t bits = args.bits.u_int; uint32_t parity; if (args.parity.u_obj == mp_const_none) { parity = UART_PARITY_NONE; } else { mp_int_t p = mp_obj_get_int(args.parity.u_obj); parity = (p & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN; bits += 1; // STs convention has bits including parity } // number of bits if (bits == 8) { bits = UART_WORDLENGTH_8B; } else if (bits == 9) { bits = UART_WORDLENGTH_9B; #ifdef UART_WORDLENGTH_7B } else if (bits == 7) { bits = UART_WORDLENGTH_7B; #endif } else { mp_raise_ValueError("unsupported combination of bits and parity"); } // stop bits uint32_t stop; switch (args.stop.u_int) { case 1: stop = UART_STOPBITS_1; break; default: stop = UART_STOPBITS_2; break; } // flow control uint32_t flow = args.flow.u_int; // init UART (if it fails, it's because the port doesn't exist) if (!uart_init(self, baudrate, bits, parity, stop, flow)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) doesn't exist", self->uart_id)); } // set timeout self->timeout = args.timeout.u_int; // set timeout_char // make sure it is at least as long as a whole character (13 bits to be safe) // minimum value is 2ms because sys-tick has a resolution of only 1ms self->timeout_char = args.timeout_char.u_int; uint32_t min_timeout_char = 13000 / baudrate + 2; if (self->timeout_char < min_timeout_char) { self->timeout_char = min_timeout_char; } // setup the read buffer m_del(byte, self->read_buf, self->read_buf_len << self->char_width); if (args.rxbuf.u_int >= 0) { // rxbuf overrides legacy read_buf_len args.read_buf_len.u_int = args.rxbuf.u_int; } if (args.read_buf_len.u_int <= 0) { // no read buffer uart_set_rxbuf(self, 0, NULL); } else { // read buffer using interrupts size_t len = args.read_buf_len.u_int + 1; // +1 to adjust for usable length of buffer uint8_t *buf = m_new(byte, len << self->char_width); uart_set_rxbuf(self, len, buf); } // compute actual baudrate that was configured uint32_t actual_baudrate = uart_get_baudrate(self); // check we could set the baudrate within 5% uint32_t baudrate_diff; if (actual_baudrate > baudrate) { baudrate_diff = actual_baudrate - baudrate; } else { baudrate_diff = baudrate - actual_baudrate; } if (20 * baudrate_diff > actual_baudrate) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "set baudrate %d is not within 5%% of desired value", actual_baudrate)); } return mp_const_none; } /// \classmethod \constructor(bus, ...) /// /// Construct a UART object on the given bus. `bus` can be 1-6, or 'XA', 'XB', 'YA', or 'YB'. /// With no additional parameters, the UART object is created but not /// initialised (it has the settings from the last initialisation of /// the bus, if any). If extra arguments are given, the bus is initialised. /// See `init` for parameters of initialisation. /// /// The physical pins of the UART busses are: /// /// - `UART(4)` is on `XA`: `(TX, RX) = (X1, X2) = (PA0, PA1)` /// - `UART(1)` is on `XB`: `(TX, RX) = (X9, X10) = (PB6, PB7)` /// - `UART(6)` is on `YA`: `(TX, RX) = (Y1, Y2) = (PC6, PC7)` /// - `UART(3)` is on `YB`: `(TX, RX) = (Y9, Y10) = (PB10, PB11)` /// - `UART(2)` is on: `(TX, RX) = (X3, X4) = (PA2, PA3)` STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // work out port int uart_id = 0; if (mp_obj_is_str(args[0])) { const char *port = mp_obj_str_get_str(args[0]); if (0) { #ifdef MICROPY_HW_UART1_NAME } else if (strcmp(port, MICROPY_HW_UART1_NAME) == 0) { uart_id = PYB_UART_1; #endif #ifdef MICROPY_HW_UART2_NAME } else if (strcmp(port, MICROPY_HW_UART2_NAME) == 0) { uart_id = PYB_UART_2; #endif #ifdef MICROPY_HW_UART3_NAME } else if (strcmp(port, MICROPY_HW_UART3_NAME) == 0) { uart_id = PYB_UART_3; #endif #ifdef MICROPY_HW_UART4_NAME } else if (strcmp(port, MICROPY_HW_UART4_NAME) == 0) { uart_id = PYB_UART_4; #endif #ifdef MICROPY_HW_UART5_NAME } else if (strcmp(port, MICROPY_HW_UART5_NAME) == 0) { uart_id = PYB_UART_5; #endif #ifdef MICROPY_HW_UART6_NAME } else if (strcmp(port, MICROPY_HW_UART6_NAME) == 0) { uart_id = PYB_UART_6; #endif #ifdef MICROPY_HW_UART7_NAME } else if (strcmp(port, MICROPY_HW_UART7_NAME) == 0) { uart_id = PYB_UART_7; #endif #ifdef MICROPY_HW_UART8_NAME } else if (strcmp(port, MICROPY_HW_UART8_NAME) == 0) { uart_id = PYB_UART_8; #endif #ifdef MICROPY_HW_UART9_NAME } else if (strcmp(port, MICROPY_HW_UART9_NAME) == 0) { uart_id = PYB_UART_9; #endif #ifdef MICROPY_HW_UART10_NAME } else if (strcmp(port, MICROPY_HW_UART10_NAME) == 0) { uart_id = PYB_UART_10; #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%s) doesn't exist", port)); } } else { uart_id = mp_obj_get_int(args[0]); if (!uart_exists(uart_id)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) doesn't exist", uart_id)); } } pyb_uart_obj_t *self; if (MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] == NULL) { // create new UART object self = m_new0(pyb_uart_obj_t, 1); self->base.type = &pyb_uart_type; self->uart_id = uart_id; MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] = self; } else { // reference existing UART object self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1]; } if (n_args > 1 || n_kw > 0) { // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t pyb_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_uart_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); /// \method deinit() /// Turn off the UART bus. STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); uart_deinit(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit); /// \method any() /// Return `True` if any characters waiting, else `False`. STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(uart_rx_any(self)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any); /// \method writechar(char) /// Write a single character on the bus. `char` is an integer to write. /// Return value: `None`. STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); // get the character to write (might be 9 bits) uint16_t data = mp_obj_get_int(char_in); // write the character int errcode; if (uart_tx_wait(self, self->timeout)) { uart_tx_data(self, &data, 1, &errcode); } else { errcode = MP_ETIMEDOUT; } if (errcode != 0) { mp_raise_OSError(errcode); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_uart_writechar_obj, pyb_uart_writechar); /// \method readchar() /// Receive a single character on the bus. /// Return value: The character read, as an integer. Returns -1 on timeout. STATIC mp_obj_t pyb_uart_readchar(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); if (uart_rx_wait(self, self->timeout)) { return MP_OBJ_NEW_SMALL_INT(uart_rx_char(self)); } else { // return -1 on timeout return MP_OBJ_NEW_SMALL_INT(-1); } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar); // uart.sendbreak() STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) self->uartx->RQR = USART_RQR_SBKRQ; // write-only register #else self->uartx->CR1 |= USART_CR1_SBK; #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak); // irq(handler, trigger, hard) STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_IRQ_ARG_INIT_NUM_ARGS, mp_irq_init_args, args); pyb_uart_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); if (self->mp_irq_obj == NULL) { self->mp_irq_trigger = 0; self->mp_irq_obj = mp_irq_new(&pyb_uart_irq_methods, MP_OBJ_FROM_PTR(self)); } if (n_args > 1 || kw_args->used != 0) { // Check the handler mp_obj_t handler = args[MP_IRQ_ARG_INIT_handler].u_obj; if (handler != mp_const_none && !mp_obj_is_callable(handler)) { mp_raise_ValueError("handler must be None or callable"); } // Check the trigger mp_uint_t trigger = args[MP_IRQ_ARG_INIT_trigger].u_int; mp_uint_t not_supported = trigger & ~mp_irq_allowed; if (trigger != 0 && not_supported) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "trigger 0x%08x unsupported", not_supported)); } // Reconfigure user IRQs pyb_uart_irq_config(self, false); self->mp_irq_obj->handler = handler; self->mp_irq_obj->ishard = args[MP_IRQ_ARG_INIT_hard].u_bool; self->mp_irq_trigger = trigger; pyb_uart_irq_config(self, true); } return MP_OBJ_FROM_PTR(self->mp_irq_obj); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq); STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) }, /// \method read([nbytes]) { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, /// \method readline() { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, /// \method readinto(buf[, nbytes]) { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, /// \method write(buf) { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_uart_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&pyb_uart_writechar_obj) }, { MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&pyb_uart_readchar_obj) }, { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, // IRQ flags { MP_ROM_QSTR(MP_QSTR_IRQ_RXIDLE), MP_ROM_INT(UART_FLAG_IDLE) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); byte *buf = buf_in; // check that size is a multiple of character width if (size & self->char_width) { *errcode = MP_EIO; return MP_STREAM_ERROR; } // convert byte size to char size size >>= self->char_width; // make sure we want at least 1 char if (size == 0) { return 0; } // wait for first char to become available if (!uart_rx_wait(self, self->timeout)) { // return EAGAIN error to indicate non-blocking (then read() method returns None) *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } // read the data byte *orig_buf = buf; for (;;) { int data = uart_rx_char(self); if (self->char_width == CHAR_WIDTH_9BIT) { *(uint16_t*)buf = data; buf += 2; } else { *buf++ = data; } if (--size == 0 || !uart_rx_wait(self, self->timeout_char)) { // return number of bytes read return buf - orig_buf; } } } STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); const byte *buf = buf_in; // check that size is a multiple of character width if (size & self->char_width) { *errcode = MP_EIO; return MP_STREAM_ERROR; } // wait to be able to write the first character. EAGAIN causes write to return None if (!uart_tx_wait(self, self->timeout)) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } // write the data size_t num_tx = uart_tx_data(self, buf, size >> self->char_width, errcode); if (*errcode == 0 || *errcode == MP_ETIMEDOUT) { // return number of bytes written, even if there was a timeout return num_tx << self->char_width; } else { return MP_STREAM_ERROR; } } STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { uintptr_t flags = arg; ret = 0; if ((flags & MP_STREAM_POLL_RD) && uart_rx_any(self)) { ret |= MP_STREAM_POLL_RD; } if ((flags & MP_STREAM_POLL_WR) && uart_tx_avail(self)) { ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; } return ret; } STATIC const mp_stream_p_t uart_stream_p = { .read = pyb_uart_read, .write = pyb_uart_write, .ioctl = pyb_uart_ioctl, .is_text = false, }; const mp_obj_type_t pyb_uart_type = { { &mp_type_type }, .name = MP_QSTR_UART, .print = pyb_uart_print, .make_new = pyb_uart_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &uart_stream_p, .locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict, }; micropython-1.12/ports/stm32/main.c000066400000000000000000000567761357706137100172560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" #include "py/mperrno.h" #include "py/mphal.h" #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" #include "lib/littlefs/lfs1.h" #include "lib/littlefs/lfs1_util.h" #include "lib/littlefs/lfs2.h" #include "lib/littlefs/lfs2_util.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "extmod/vfs_lfs.h" #if MICROPY_PY_LWIP #include "lwip/init.h" #include "lwip/apps/mdns.h" #include "drivers/cyw43/cyw43.h" #endif #if MICROPY_BLUETOOTH_NIMBLE #include "extmod/modbluetooth.h" #endif #include "mpu.h" #include "rfcore.h" #include "systick.h" #include "pendsv.h" #include "powerctrl.h" #include "pybthread.h" #include "gccollect.h" #include "factoryreset.h" #include "modmachine.h" #include "softtimer.h" #include "i2c.h" #include "spi.h" #include "uart.h" #include "timer.h" #include "led.h" #include "pin.h" #include "extint.h" #include "usrsw.h" #include "usb.h" #include "rtc.h" #include "storage.h" #include "sdcard.h" #include "sdram.h" #include "rng.h" #include "accel.h" #include "servo.h" #include "dac.h" #include "can.h" #include "modnetwork.h" #if MICROPY_PY_THREAD STATIC pyb_thread_t pyb_thread_main; #endif #if defined(MICROPY_HW_UART_REPL) #ifndef MICROPY_HW_UART_REPL_RXBUF #define MICROPY_HW_UART_REPL_RXBUF (260) #endif STATIC pyb_uart_obj_t pyb_uart_repl_obj; STATIC uint8_t pyb_uart_repl_rxbuf[MICROPY_HW_UART_REPL_RXBUF]; #endif void flash_error(int n) { for (int i = 0; i < n; i++) { led_state(PYB_LED_RED, 1); led_state(PYB_LED_GREEN, 0); mp_hal_delay_ms(250); led_state(PYB_LED_RED, 0); led_state(PYB_LED_GREEN, 1); mp_hal_delay_ms(250); } led_state(PYB_LED_GREEN, 0); } void NORETURN __fatal_error(const char *msg) { for (volatile uint delay = 0; delay < 10000000; delay++) { } led_state(1, 1); led_state(2, 1); led_state(3, 1); led_state(4, 1); mp_hal_stdout_tx_strn("\nFATAL ERROR:\n", 14); mp_hal_stdout_tx_strn(msg, strlen(msg)); for (uint i = 0;;) { led_toggle(((i++) & 3) + 1); for (volatile uint delay = 0; delay < 10000000; delay++) { } if (i >= 16) { // to conserve power __WFI(); } } } void nlr_jump_fail(void *val) { printf("FATAL: uncaught exception %p\n", val); mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val)); __fatal_error(""); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { (void)func; printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error(""); } #endif STATIC mp_obj_t pyb_main(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_opt, MP_ARG_INT, {.u_int = 0} } }; if (mp_obj_is_str(pos_args[0])) { MP_STATE_PORT(pyb_config_main) = pos_args[0]; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); #if MICROPY_ENABLE_COMPILER MP_STATE_VM(mp_optimise_value) = args[0].u_int; #endif } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(pyb_main_obj, 1, pyb_main); #if MICROPY_HW_ENABLE_STORAGE STATIC int vfs_mount_and_chdir(mp_obj_t bdev, mp_obj_t mount_point) { nlr_buf_t nlr; mp_int_t ret = -MP_EIO; if (nlr_push(&nlr) == 0) { mp_obj_t args[] = { bdev, mount_point }; mp_vfs_mount(2, args, (mp_map_t*)&mp_const_empty_map); mp_vfs_chdir(mount_point); ret = 0; // success nlr_pop(); } else { mp_obj_base_t *exc = nlr.ret_val; if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_OSError))) { mp_obj_t v = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); mp_obj_get_int_maybe(v, &ret); // get errno value ret = -ret; } } return ret; } // avoid inlining to avoid stack usage within main() MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { if (reset_mode == 3) { // Asked by user to reset filesystem factory_reset_create_filesystem(); } // Default block device to entire flash storage mp_obj_t bdev = MP_OBJ_FROM_PTR(&pyb_flash_obj); #if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2 // Try to detect the block device used for the main filesystem, based on the first block uint8_t buf[FLASH_BLOCK_SIZE]; storage_read_blocks(buf, FLASH_PART1_START_BLOCK, 1); mp_int_t len = -1; #if MICROPY_VFS_LFS1 if (memcmp(&buf[40], "littlefs", 8) == 0) { // LFS1 lfs1_superblock_t *superblock = (void*)&buf[12]; uint32_t block_size = lfs1_fromle32(superblock->d.block_size); uint32_t block_count = lfs1_fromle32(superblock->d.block_count); len = block_count * block_size; } #endif #if MICROPY_VFS_LFS2 if (memcmp(&buf[8], "littlefs", 8) == 0) { // LFS2 lfs2_superblock_t *superblock = (void*)&buf[20]; uint32_t block_size = lfs2_fromle32(superblock->block_size); uint32_t block_count = lfs2_fromle32(superblock->block_count); len = block_count * block_size; } #endif if (len != -1) { // Detected a littlefs filesystem so create correct block device for it mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR_len), MP_OBJ_NEW_SMALL_INT(len) }; bdev = pyb_flash_type.make_new(&pyb_flash_type, 0, 1, args); } #endif // Try to mount the flash on "/flash" and chdir to it for the boot-up directory. mp_obj_t mount_point = MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash); int ret = vfs_mount_and_chdir(bdev, mount_point); if (ret == -MP_ENODEV && bdev == MP_OBJ_FROM_PTR(&pyb_flash_obj) && reset_mode != 3) { // No filesystem, bdev is still the default (so didn't detect a possibly corrupt littlefs), // and didn't already create a filesystem, so try to create a fresh one now. ret = factory_reset_create_filesystem(); if (ret == 0) { ret = vfs_mount_and_chdir(bdev, mount_point); } } if (ret != 0) { printf("MPY: can't mount flash\n"); return false; } return true; } #endif #if MICROPY_HW_SDCARD_MOUNT_AT_BOOT STATIC bool init_sdcard_fs(void) { bool first_part = true; for (int part_num = 1; part_num <= 4; ++part_num) { // create vfs object fs_user_mount_t *vfs_fat = m_new_obj_maybe(fs_user_mount_t); mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); if (vfs == NULL || vfs_fat == NULL) { break; } vfs_fat->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; sdcard_init_vfs(vfs_fat, part_num); // try to mount the partition FRESULT res = f_mount(&vfs_fat->fatfs); if (res != FR_OK) { // couldn't mount m_del_obj(fs_user_mount_t, vfs_fat); m_del_obj(mp_vfs_mount_t, vfs); } else { // mounted via FatFs, now mount the SD partition in the VFS if (first_part) { // the first available partition is traditionally called "sd" for simplicity vfs->str = "/sd"; vfs->len = 3; } else { // subsequent partitions are numbered by their index in the partition table if (part_num == 2) { vfs->str = "/sd2"; } else if (part_num == 2) { vfs->str = "/sd3"; } else { vfs->str = "/sd4"; } vfs->len = 4; } vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); vfs->next = NULL; for (mp_vfs_mount_t **m = &MP_STATE_VM(vfs_mount_table);; m = &(*m)->next) { if (*m == NULL) { *m = vfs; break; } } #if MICROPY_HW_ENABLE_USB if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_NONE) { // if no USB MSC medium is selected then use the SD card pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_SDCARD; } #endif #if MICROPY_HW_ENABLE_USB // only use SD card as current directory if that's what the USB medium is if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_SDCARD) #endif { if (first_part) { // use SD card as current directory MP_STATE_PORT(vfs_cur) = vfs; } } first_part = false; } } if (first_part) { printf("MPY: can't mount SD card\n"); return false; } else { return true; } } #endif #if !MICROPY_HW_USES_BOOTLOADER STATIC uint update_reset_mode(uint reset_mode) { #if MICROPY_HW_HAS_SWITCH if (switch_get()) { // The original method used on the pyboard is appropriate if you have 2 // or more LEDs. #if defined(MICROPY_HW_LED2) for (uint i = 0; i < 3000; i++) { if (!switch_get()) { break; } mp_hal_delay_ms(20); if (i % 30 == 29) { if (++reset_mode > 3) { reset_mode = 1; } led_state(2, reset_mode & 1); led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); } } // flash the selected reset mode for (uint i = 0; i < 6; i++) { led_state(2, 0); led_state(3, 0); led_state(4, 0); mp_hal_delay_ms(50); led_state(2, reset_mode & 1); led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); mp_hal_delay_ms(50); } mp_hal_delay_ms(400); #elif defined(MICROPY_HW_LED1) // For boards with only a single LED, we'll flash that LED the // appropriate number of times, with a pause between each one for (uint i = 0; i < 10; i++) { led_state(1, 0); for (uint j = 0; j < reset_mode; j++) { if (!switch_get()) { break; } led_state(1, 1); mp_hal_delay_ms(100); led_state(1, 0); mp_hal_delay_ms(200); } mp_hal_delay_ms(400); if (!switch_get()) { break; } if (++reset_mode > 3) { reset_mode = 1; } } // Flash the selected reset mode for (uint i = 0; i < 2; i++) { for (uint j = 0; j < reset_mode; j++) { led_state(1, 1); mp_hal_delay_ms(100); led_state(1, 0); mp_hal_delay_ms(200); } mp_hal_delay_ms(400); } #else #error Need a reset mode update method #endif } #endif return reset_mode; } #endif void stm32_main(uint32_t reset_mode) { #if !defined(STM32F0) && defined(MICROPY_HW_VTOR) // Change IRQ vector table if configured differently SCB->VTOR = MICROPY_HW_VTOR; #endif // Enable 8-byte stack alignment for IRQ handlers, in accord with EABI SCB->CCR |= SCB_CCR_STKALIGN_Msk; // Check if bootloader should be entered instead of main application powerctrl_check_enter_bootloader(); // Enable caches and prefetch buffers #if defined(STM32F4) #if INSTRUCTION_CACHE_ENABLE __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); #endif #if DATA_CACHE_ENABLE __HAL_FLASH_DATA_CACHE_ENABLE(); #endif #if PREFETCH_ENABLE __HAL_FLASH_PREFETCH_BUFFER_ENABLE(); #endif #elif defined(STM32F7) || defined(STM32H7) #if ART_ACCLERATOR_ENABLE __HAL_FLASH_ART_ENABLE(); #endif SCB_EnableICache(); SCB_EnableDCache(); #elif defined(STM32L4) #if !INSTRUCTION_CACHE_ENABLE __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); #endif #if !DATA_CACHE_ENABLE __HAL_FLASH_DATA_CACHE_DISABLE(); #endif #if PREFETCH_ENABLE __HAL_FLASH_PREFETCH_BUFFER_ENABLE(); #endif #endif mpu_init(); #if __CORTEX_M >= 0x03 // Set the priority grouping NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); #endif // SysTick is needed by HAL_RCC_ClockConfig (called in SystemClock_Config) HAL_InitTick(TICK_INT_PRIORITY); // set the system clock to be HSE SystemClock_Config(); // enable GPIO clocks __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); #if defined(GPIOD) __HAL_RCC_GPIOD_CLK_ENABLE(); #endif #if defined(STM32F4) || defined(STM32F7) #if defined(__HAL_RCC_DTCMRAMEN_CLK_ENABLE) // The STM32F746 doesn't really have CCM memory, but it does have DTCM, // which behaves more or less like normal SRAM. __HAL_RCC_DTCMRAMEN_CLK_ENABLE(); #elif defined(CCMDATARAM_BASE) // enable the CCM RAM __HAL_RCC_CCMDATARAMEN_CLK_ENABLE(); #endif #elif defined(STM32H7) // Enable D2 SRAM1/2/3 clocks. __HAL_RCC_D2SRAM1_CLK_ENABLE(); __HAL_RCC_D2SRAM2_CLK_ENABLE(); __HAL_RCC_D2SRAM3_CLK_ENABLE(); #endif #if defined(MICROPY_BOARD_EARLY_INIT) MICROPY_BOARD_EARLY_INIT(); #endif // basic sub-system init #if defined(STM32WB) rfcore_init(); #endif #if MICROPY_HW_SDRAM_SIZE sdram_init(); #if MICROPY_HW_SDRAM_STARTUP_TEST sdram_test(true); #endif #endif #if MICROPY_PY_THREAD pyb_thread_init(&pyb_thread_main); #endif pendsv_init(); led_init(); #if MICROPY_HW_HAS_SWITCH switch_init0(); #endif machine_init(); #if MICROPY_HW_ENABLE_RTC rtc_init_start(false); #endif uart_init0(); spi_init0(); #if MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C i2c_init0(); #endif #if MICROPY_HW_ENABLE_SDCARD sdcard_init(); #endif #if MICROPY_HW_ENABLE_STORAGE storage_init(); #endif #if MICROPY_PY_LWIP // lwIP doesn't allow to reinitialise itself by subsequent calls to this function // because the system timeout list (next_timeout) is only ever reset by BSS clearing. // So for now we only init the lwIP stack once on power-up. lwip_init(); #if LWIP_MDNS_RESPONDER mdns_resp_init(); #endif systick_enable_dispatch(SYSTICK_DISPATCH_LWIP, mod_network_lwip_poll_wrapper); #endif #if MICROPY_BLUETOOTH_NIMBLE extern void mod_bluetooth_nimble_poll_wrapper(uint32_t ticks_ms); systick_enable_dispatch(SYSTICK_DISPATCH_NIMBLE, mod_bluetooth_nimble_poll_wrapper); #endif #if MICROPY_PY_NETWORK_CYW43 { cyw43_init(&cyw43_state); uint8_t buf[8]; memcpy(&buf[0], "PYBD", 4); mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, (char*)&buf[4]); cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf); cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t*)"pybd0123"); } #endif #if defined(MICROPY_HW_UART_REPL) // Set up a UART REPL using a statically allocated object pyb_uart_repl_obj.base.type = &pyb_uart_type; pyb_uart_repl_obj.uart_id = MICROPY_HW_UART_REPL; pyb_uart_repl_obj.is_static = true; pyb_uart_repl_obj.timeout = 0; pyb_uart_repl_obj.timeout_char = 2; uart_init(&pyb_uart_repl_obj, MICROPY_HW_UART_REPL_BAUD, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, 0); uart_set_rxbuf(&pyb_uart_repl_obj, sizeof(pyb_uart_repl_rxbuf), pyb_uart_repl_rxbuf); uart_attach_to_repl(&pyb_uart_repl_obj, true); MP_STATE_PORT(pyb_uart_obj_all)[MICROPY_HW_UART_REPL - 1] = &pyb_uart_repl_obj; #endif soft_reset: #if defined(MICROPY_HW_LED2) led_state(1, 0); led_state(2, 1); #else led_state(1, 1); led_state(2, 0); #endif led_state(3, 0); led_state(4, 0); #if !MICROPY_HW_USES_BOOTLOADER // check if user switch held to select the reset mode reset_mode = update_reset_mode(1); #endif // Python threading init #if MICROPY_PY_THREAD mp_thread_init(); #endif // Stack limit should be less than real stack size, so we have a chance // to recover from limit hit. (Limit is measured in bytes.) // Note: stack control relies on main thread being initialised above mp_stack_set_top(&_estack); mp_stack_set_limit((char*)&_estack - (char*)&_sstack - 1024); // GC init gc_init(MICROPY_HEAP_START, MICROPY_HEAP_END); #if MICROPY_ENABLE_PYSTACK static mp_obj_t pystack[384]; mp_pystack_init(pystack, &pystack[384]); #endif // MicroPython init mp_init(); mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); // Initialise low-level sub-systems. Here we need to very basic things like // zeroing out memory and resetting any of the sub-systems. Following this // we can run Python scripts (eg boot.py), but anything that is configurable // by boot.py must be set after boot.py is run. #if defined(MICROPY_HW_UART_REPL) MP_STATE_PORT(pyb_stdio_uart) = &pyb_uart_repl_obj; #else MP_STATE_PORT(pyb_stdio_uart) = NULL; #endif readline_init0(); pin_init0(); extint_init0(); timer_init0(); #if MICROPY_HW_ENABLE_CAN can_init0(); #endif #if MICROPY_HW_ENABLE_USB pyb_usb_init0(); #endif // Initialise the local flash filesystem. // Create it if needed, mount in on /flash, and set it as current dir. bool mounted_flash = false; #if MICROPY_HW_ENABLE_STORAGE mounted_flash = init_flash_fs(reset_mode); #endif bool mounted_sdcard = false; #if MICROPY_HW_SDCARD_MOUNT_AT_BOOT // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { // if there is a file in the flash called "SKIPSD", then we don't mount the SD card if (!mounted_flash || mp_vfs_import_stat("SKIPSD") == MP_IMPORT_STAT_NO_EXIST) { mounted_sdcard = init_sdcard_fs(); } } #endif #if MICROPY_HW_ENABLE_USB // if the SD card isn't used as the USB MSC medium then use the internal flash if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_NONE) { pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_FLASH; } #endif // set sys.path based on mounted filesystems (/sd is first so it can override /flash) if (mounted_sdcard) { mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib)); } if (mounted_flash) { mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash_slash_lib)); } // reset config variables; they should be set by boot.py MP_STATE_PORT(pyb_config_main) = MP_OBJ_NULL; // run boot.py, if it exists // TODO perhaps have pyb.reboot([bootpy]) function to soft-reboot and execute custom boot.py if (reset_mode == 1 || reset_mode == 3) { const char *boot_py = "boot.py"; int ret = pyexec_file_if_exists(boot_py); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } if (!ret) { flash_error(4); } } // turn boot-up LEDs off #if !defined(MICROPY_HW_LED2) // If there is only one LED on the board then it's used to signal boot-up // and so we turn it off here. Otherwise LED(1) is used to indicate dirty // flash cache and so we shouldn't change its state. led_state(1, 0); #endif led_state(2, 0); led_state(3, 0); led_state(4, 0); // Now we initialise sub-systems that need configuration from boot.py, // or whose initialisation can be safely deferred until after running // boot.py. #if MICROPY_HW_ENABLE_USB // init USB device to default setting if it was not already configured if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) { #if MICROPY_HW_USB_MSC const uint16_t pid = USBD_PID_CDC_MSC; const uint8_t mode = USBD_MODE_CDC_MSC; #else const uint16_t pid = USBD_PID_CDC; const uint8_t mode = USBD_MODE_CDC; #endif pyb_usb_dev_init(pyb_usb_dev_detect(), USBD_VID, pid, mode, 0, NULL, NULL); } #endif #if MICROPY_HW_HAS_MMA7660 // MMA accel: init and reset accel_init(); #endif #if MICROPY_HW_ENABLE_SERVO servo_init(); #endif #if MICROPY_PY_NETWORK mod_network_init(); #endif // At this point everything is fully configured and initialised. // Run the main script from the current directory. if ((reset_mode == 1 || reset_mode == 3) && pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { const char *main_py; if (MP_STATE_PORT(pyb_config_main) == MP_OBJ_NULL) { main_py = "main.py"; } else { main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main)); } int ret = pyexec_file_if_exists(main_py); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } if (!ret) { flash_error(3); } } #if MICROPY_ENABLE_COMPILER // Main script is finished, so now go into REPL mode. // The REPL mode can change, or it can request a soft reset. for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } #endif soft_reset_exit: // soft reset #if MICROPY_HW_ENABLE_STORAGE printf("MPY: sync filesystems\n"); storage_flush(); #endif printf("MPY: soft reboot\n"); #if MICROPY_BLUETOOTH_NIMBLE mp_bluetooth_deinit(); #endif #if MICROPY_PY_NETWORK mod_network_deinit(); #endif soft_timer_deinit(); timer_deinit(); uart_deinit_all(); #if MICROPY_HW_ENABLE_CAN can_deinit_all(); #endif machine_deinit(); #if MICROPY_PY_THREAD pyb_thread_deinit(); #endif gc_sweep_all(); goto soft_reset; } micropython-1.12/ports/stm32/make-stmconst.py000066400000000000000000000226351357706137100213100ustar00rootroot00000000000000""" This script reads in the given CMSIS device include file (eg stm32f405xx.h), extracts relevant peripheral constants, and creates qstrs, mpz's and constants for the stm module. """ from __future__ import print_function import argparse import re # Python 2/3 compatibility import platform if platform.python_version_tuple()[0] == '2': def convert_bytes_to_str(b): return b elif platform.python_version_tuple()[0] == '3': def convert_bytes_to_str(b): try: return str(b, 'utf8') except ValueError: # some files have invalid utf8 bytes, so filter them out return ''.join(chr(l) for l in b if l <= 126) # end compatibility code # given a list of (name,regex) pairs, find the first one that matches the given line def re_match_first(regexs, line): for name, regex in regexs: match = re.match(regex, line) if match: return name, match return None, None class LexerError(Exception): def __init__(self, line): self.line = line class Lexer: re_io_reg = r'__IO uint(?P8|16|32)_t +(?P[A-Z0-9]+)' re_comment = r'(?P[A-Za-z0-9 \-/_()&]+)' re_addr_offset = r'Address offset: (?P0x[0-9A-Z]{2,3})' regexs = ( ('#define hex', re.compile(r'#define +(?P[A-Z0-9_]+) +\(?(\(uint32_t\))?(?P0x[0-9A-F]+)U?L?\)?($| */\*)')), ('#define X', re.compile(r'#define +(?P[A-Z0-9_]+) +(?P[A-Z0-9_]+)($| +/\*)')), ('#define X+hex', re.compile(r'#define +(?P[A-Za-z0-9_]+) +\(?(?P[A-Z0-9_]+) \+ (?P0x[0-9A-F]+)U?L?\)?($| +/\*)')), ('#define typedef', re.compile(r'#define +(?P[A-Z0-9_]+(ext)?) +\(\([A-Za-z0-9_]+_TypeDef \*\) (?P[A-Za-z0-9_]+)\)($| +/\*)')), ('typedef struct', re.compile(r'typedef struct$')), ('{', re.compile(r'{$')), ('}', re.compile(r'}$')), ('} TypeDef', re.compile(r'} *(?P[A-Z][A-Za-z0-9_]+)_(?P([A-Za-z0-9_]+)?)TypeDef;$')), ('IO reg', re.compile(re_io_reg + r'; */\*!< *' + re_comment + r', +' + re_addr_offset + r' *\*/')), ('IO reg array', re.compile(re_io_reg + r'\[(?P[2-8])\]; */\*!< *' + re_comment + r', +' + re_addr_offset + r'-(0x[0-9A-Z]{2,3}) *\*/')), ) def __init__(self, filename): self.file = open(filename, 'rb') self.line_number = 0 def next_match(self, strictly_next=False): while True: line = self.file.readline() line = convert_bytes_to_str(line) self.line_number += 1 if len(line) == 0: return ('EOF', None) match = re_match_first(Lexer.regexs, line.strip()) if strictly_next or match[0] is not None: return match def must_match(self, kind): match = self.next_match(strictly_next=True) if match[0] != kind: raise LexerError(self.line_number) return match def parse_file(filename): lexer = Lexer(filename) reg_defs = {} consts = {} periphs = [] while True: m = lexer.next_match() if m[0] == 'EOF': break elif m[0] == '#define hex': d = m[1].groupdict() consts[d['id']] = int(d['hex'], base=16) elif m[0] == '#define X': d = m[1].groupdict() if d['id2'] in consts: consts[d['id']] = consts[d['id2']] elif m[0] == '#define X+hex': d = m[1].groupdict() if d['id2'] in consts: consts[d['id']] = consts[d['id2']] + int(d['hex'], base=16) elif m[0] == '#define typedef': d = m[1].groupdict() if d['id2'] in consts: periphs.append((d['id'], consts[d['id2']])) elif m[0] == 'typedef struct': lexer.must_match('{') m = lexer.next_match() regs = [] while m[0] in ('IO reg', 'IO reg array'): d = m[1].groupdict() reg = d['reg'] offset = int(d['offset'], base=16) bits = int(d['bits']) comment = d['comment'] if m[0] == 'IO reg': regs.append((reg, offset, bits, comment)) else: for i in range(int(d['array'])): regs.append((reg + str(i), offset + i * bits // 8, bits, comment)) m = lexer.next_match() if m[0] == '}': pass elif m[0] == '} TypeDef': reg_defs[m[1].groupdict()['id']] = regs else: raise LexerError(lexer.line_number) return periphs, reg_defs def print_int_obj(val, needed_mpzs): if -0x40000000 <= val < 0x40000000: print('MP_ROM_INT(%#x)' % val, end='') else: print('MP_ROM_PTR(&mpz_%08x)' % val, end='') needed_mpzs.add(val) def print_periph(periph_name, periph_val, needed_qstrs, needed_mpzs): qstr = periph_name.upper() print('{ MP_ROM_QSTR(MP_QSTR_%s), ' % qstr, end='') print_int_obj(periph_val, needed_mpzs) print(' },') needed_qstrs.add(qstr) def print_regs(reg_name, reg_defs, needed_qstrs, needed_mpzs): reg_name = reg_name.upper() for r in reg_defs: qstr = reg_name + '_' + r[0] print('{ MP_ROM_QSTR(MP_QSTR_%s), ' % qstr, end='') print_int_obj(r[1], needed_mpzs) print(' }, // %s-bits, %s' % (r[2], r[3])) needed_qstrs.add(qstr) # This version of print regs groups registers together into submodules (eg GPIO submodule). # This makes the qstrs shorter, and makes the list of constants more manageable (since # they are not all in one big module) but it is then harder to compile the constants, and # is more cumbersome to access. # As such, we don't use this version. # And for the number of constants we have, this function seems to use about the same amount # of ROM as print_regs. def print_regs_as_submodules(reg_name, reg_defs, modules, needed_qstrs): mod_name_lower = reg_name.lower() + '_' mod_name_upper = mod_name_lower.upper() modules.append((mod_name_lower, mod_name_upper)) print(""" STATIC const mp_rom_map_elem_t stm_%s_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_%s) }, """ % (mod_name_lower, mod_name_upper)) needed_qstrs.add(mod_name_upper) for r in reg_defs: print(' { MP_ROM_QSTR(MP_QSTR_%s), MP_ROM_INT(%#x) }, // %s-bits, %s' % (r[0], r[1], r[2], r[3])) needed_qstrs.add(r[0]) print("""}; STATIC MP_DEFINE_CONST_DICT(stm_%s_globals, stm_%s_globals_table); const mp_obj_module_t stm_%s_obj = { .base = { &mp_type_module }, .name = MP_QSTR_%s, .globals = (mp_obj_dict_t*)&stm_%s_globals, }; """ % (mod_name_lower, mod_name_lower, mod_name_lower, mod_name_upper, mod_name_lower)) def main(): cmd_parser = argparse.ArgumentParser(description='Extract ST constants from a C header file.') cmd_parser.add_argument('file', nargs=1, help='input file') cmd_parser.add_argument('-q', '--qstr', dest='qstr_filename', default='build/stmconst_qstr.h', help='Specified the name of the generated qstr header file') cmd_parser.add_argument('--mpz', dest='mpz_filename', default='build/stmconst_mpz.h', help='the destination file of the generated mpz header') args = cmd_parser.parse_args() periphs, reg_defs = parse_file(args.file[0]) # add legacy GPIO constants that were removed when upgrading CMSIS if 'GPIO' in reg_defs and 'stm32f4' in args.file[0]: reg_defs['GPIO'].append(['BSRRL', 0x18, 16, 'legacy register']) reg_defs['GPIO'].append(['BSRRH', 0x1a, 16, 'legacy register']) modules = [] needed_qstrs = set() needed_mpzs = set() print("// Automatically generated from %s by make-stmconst.py" % args.file[0]) print("") for periph_name, periph_val in periphs: print_periph(periph_name, periph_val, needed_qstrs, needed_mpzs) for reg in ( 'ADC', #'ADC_Common', #'CAN_TxMailBox', #'CAN_FIFOMailBox', #'CAN_FilterRegister', #'CAN', 'CRC', 'DAC', 'DBGMCU', 'DMA_Stream', 'DMA', 'EXTI', 'FLASH', 'GPIO', 'SYSCFG', 'I2C', 'IWDG', 'PWR', 'RCC', 'RTC', #'SDIO', 'SPI', 'TIM', 'USART', 'WWDG', 'RNG', ): if reg in reg_defs: print_regs(reg, reg_defs[reg], needed_qstrs, needed_mpzs) #print_regs_as_submodules(reg, reg_defs[reg], modules, needed_qstrs) #print("#define MOD_STM_CONST_MODULES \\") #for mod_lower, mod_upper in modules: # print(" { MP_ROM_QSTR(MP_QSTR_%s), MP_ROM_PTR(&stm_%s_obj) }, \\" % (mod_upper, mod_lower)) print("") with open(args.qstr_filename, 'wt') as qstr_file: print('#if MICROPY_PY_STM', file=qstr_file) for qstr in sorted(needed_qstrs): print('Q({})'.format(qstr), file=qstr_file) print('#endif // MICROPY_PY_STM', file=qstr_file) with open(args.mpz_filename, 'wt') as mpz_file: for mpz in sorted(needed_mpzs): assert 0 <= mpz <= 0xffffffff print('STATIC const mp_obj_int_t mpz_%08x = {{&mp_type_int}, ' '{.neg=0, .fixed_dig=1, .alloc=2, .len=2, ' '.dig=(uint16_t*)(const uint16_t[]){%#x, %#x}}};' % (mpz, mpz & 0xffff, (mpz >> 16) & 0xffff), file=mpz_file) if __name__ == "__main__": main() micropython-1.12/ports/stm32/mbedtls/000077500000000000000000000000001357706137100175735ustar00rootroot00000000000000micropython-1.12/ports/stm32/mbedtls/mbedtls_config.h000066400000000000000000000063441357706137100227320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H // Set mbedtls configuration #define MBEDTLS_PLATFORM_MEMORY #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS #define MBEDTLS_DEPRECATED_REMOVED #define MBEDTLS_ENTROPY_HARDWARE_ALT #define MBEDTLS_AES_ROM_TABLES #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #define MBEDTLS_ECP_DP_SECP224R1_ENABLED #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_ECP_DP_SECP384R1_ENABLED #define MBEDTLS_ECP_DP_SECP521R1_ENABLED #define MBEDTLS_ECP_DP_SECP192K1_ENABLED #define MBEDTLS_ECP_DP_SECP224K1_ENABLED #define MBEDTLS_ECP_DP_SECP256K1_ENABLED #define MBEDTLS_ECP_DP_BP256R1_ENABLED #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED #define MBEDTLS_ECP_DP_CURVE25519_ENABLED #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED #define MBEDTLS_NO_PLATFORM_ENTROPY #define MBEDTLS_PKCS1_V15 #define MBEDTLS_SHA256_SMALLER #define MBEDTLS_SSL_PROTO_TLS1 #define MBEDTLS_SSL_PROTO_TLS1_1 #define MBEDTLS_SSL_PROTO_TLS1_2 #define MBEDTLS_SSL_SERVER_NAME_INDICATION // Enable mbedtls modules #define MBEDTLS_AES_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_CIPHER_C #define MBEDTLS_CTR_DRBG_C //#define MBEDTLS_ECP_C #define MBEDTLS_ENTROPY_C #define MBEDTLS_MD_C #define MBEDTLS_MD5_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS5_C #define MBEDTLS_PK_C #define MBEDTLS_PK_PARSE_C #define MBEDTLS_PLATFORM_C #define MBEDTLS_RSA_C #define MBEDTLS_SHA1_C #define MBEDTLS_SHA256_C #define MBEDTLS_SHA512_C #define MBEDTLS_SSL_CLI_C #define MBEDTLS_SSL_SRV_C #define MBEDTLS_SSL_TLS_C #define MBEDTLS_X509_CRT_PARSE_C #define MBEDTLS_X509_USE_C // Memory allocation hooks #include #include void *m_calloc_mbedtls(size_t nmemb, size_t size); void m_free_mbedtls(void *ptr); #define MBEDTLS_PLATFORM_STD_CALLOC m_calloc_mbedtls #define MBEDTLS_PLATFORM_STD_FREE m_free_mbedtls #define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf #include "mbedtls/check_config.h" #endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ micropython-1.12/ports/stm32/mbedtls/mbedtls_port.c000066400000000000000000000055121357706137100224400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/gc.h" #include "rng.h" #include "mbedtls_config.h" #define DEBUG (0) #if DEBUG static size_t count_links(uint32_t *nb) { void **p = MP_STATE_PORT(mbedtls_memory); size_t n = 0; *nb = 0; while (p != NULL) { ++n; *nb += gc_nbytes(p); p = (void**)p[1]; } return n; } #endif void *m_calloc_mbedtls(size_t nmemb, size_t size) { void **ptr = m_malloc0(nmemb * size + 2 * sizeof(uintptr_t)); #if DEBUG uint32_t nb; size_t n = count_links(&nb); printf("mbed_alloc(%u, %u) -> (%u;%u) %p\n", nmemb, size, n, (uint)nb, ptr); #endif if (MP_STATE_PORT(mbedtls_memory) != NULL) { MP_STATE_PORT(mbedtls_memory)[0] = ptr; } ptr[0] = NULL; ptr[1] = MP_STATE_PORT(mbedtls_memory); MP_STATE_PORT(mbedtls_memory) = ptr; return &ptr[2]; } void m_free_mbedtls(void *ptr_in) { void **ptr = &((void**)ptr_in)[-2]; #if DEBUG uint32_t nb; size_t n = count_links(&nb); printf("mbed_free(%p, [%p, %p], nbytes=%u, links=%u;%u)\n", ptr, ptr[0], ptr[1], gc_nbytes(ptr), n, (uint)nb); #endif if (ptr[1] != NULL) { ((void**)ptr[1])[0] = ptr[0]; } if (ptr[0] != NULL) { ((void**)ptr[0])[1] = ptr[1]; } else { MP_STATE_PORT(mbedtls_memory) = ptr[1]; } m_free(ptr); } int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) { uint32_t val; int n = 0; *olen = len; while (len--) { if (!n) { val = rng_get(); n = 4; } *output++ = val; val >>= 8; --n; } return 0; } micropython-1.12/ports/stm32/mboot/000077500000000000000000000000001357706137100172615ustar00rootroot00000000000000micropython-1.12/ports/stm32/mboot/Makefile000077500000000000000000000155121357706137100207300ustar00rootroot00000000000000# Select the board to build for: if not given on the command line, # then default to PYBV10. BOARD ?= PYBV10 # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD) # Allow the directory containing the board configuration to be specified BOARD_DIR ?= $(abspath ../boards/$(BOARD)) # Set USE_MBOOT to 1 so that TEXT0_ADDR gets set properly for those boards # that can be built with or without mboot. USE_MBOOT ?= 1 # Sanity check that the board configuration directory exists ifeq ($(wildcard $(BOARD_DIR)/.),) $(error Invalid BOARD specified: $(BOARD_DIR)) endif include ../../../py/mkenv.mk include $(BOARD_DIR)/mpconfigboard.mk MCU_SERIES_UPPER = $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') CMSIS_MCU_LOWER = $(shell echo $(CMSIS_MCU) | tr '[:upper:]' '[:lower:]') CMSIS_DIR=$(TOP)/lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Include HAL_DIR=lib/stm32lib/STM32$(MCU_SERIES_UPPER)xx_HAL_Driver USBDEV_DIR=usbdev DFU=$(TOP)/tools/dfu.py PYDFU ?= $(TOP)/tools/pydfu.py DEVICE=0483:df11 STFLASH ?= st-flash OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg STARTUP_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/gcc/startup_$(CMSIS_MCU_LOWER).o CROSS_COMPILE = arm-none-eabi- INC += -I. INC += -I.. INC += -I$(TOP) INC += -I$(BUILD) INC += -I$(TOP)/lib/cmsis/inc INC += -I$(CMSIS_DIR)/ INC += -I$(TOP)/$(HAL_DIR)/Inc INC += -I../$(USBDEV_DIR)/core/inc -I../$(USBDEV_DIR)/class/inc # Basic Cortex-M flags CFLAGS_CORTEX_M = -mthumb # Options for particular MCU series CFLAGS_MCU_f4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -D$(CMSIS_MCU) CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(COPT) CFLAGS += -I$(BOARD_DIR) CFLAGS += -DSTM32_HAL_H='' CFLAGS += -DBOARD_$(BOARD) CFLAGS += -DAPPLICATION_ADDR=$(TEXT0_ADDR) CFLAGS += -DFFCONF_H=\"ports/stm32/mboot/ffconf.h\" CFLAGS += -DBUILDING_MBOOT=1 LDFLAGS = -nostdlib -L . -T stm32_generic.ld -Map=$(@:.elf=.map) --cref LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Remove uncalled code from the final image. CFLAGS += -fdata-sections -ffunction-sections LDFLAGS += --gc-sections # Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -g -DPENDSV_DEBUG COPT = -O0 else COPT += -Os -DNDEBUG endif SRC_LIB = \ lib/libc/string0.c \ lib/oofatfs/ff.c \ lib/oofatfs/ffunicode.c \ extmod/uzlib/crc32.c \ extmod/uzlib/adler32.c \ extmod/uzlib/tinflate.c \ extmod/uzlib/tinfgzip.c SRC_C = \ main.c \ elem.c \ fsload.c \ diskio.c \ drivers/bus/softspi.c \ drivers/bus/softqspi.c \ drivers/memory/spiflash.c \ ports/stm32/i2cslave.c \ ports/stm32/qspi.c \ ports/stm32/flashbdev.c \ ports/stm32/spibdev.c \ ports/stm32/usbd_conf.c \ $(wildcard $(BOARD_DIR)/*.c) SRC_O = \ $(STARTUP_FILE) \ ports/stm32/resethandler.o \ $(BUILD)/$(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_ll_usb.o: CFLAGS += -Wno-attributes SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_cortex.c \ hal_flash.c \ hal_flash_ex.c \ hal_pcd.c \ hal_pcd_ex.c \ ll_usb.c \ ) SRC_USBDEV = $(addprefix ports/stm32/$(USBDEV_DIR)/,\ core/src/usbd_core.c \ core/src/usbd_ctlreq.c \ core/src/usbd_ioreq.c \ ) OBJ = OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_O)) OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_USBDEV:.c=.o)) all: $(TOP)/lib/stm32lib/README.md $(BUILD)/firmware.dfu $(BUILD)/firmware.hex # For convenience, automatically fetch required submodules if they don't exist $(TOP)/lib/stm32lib/README.md: $(ECHO) "stm32lib submodule not found, fetching it now..." (cd $(TOP) && git submodule update --init lib/stm32lib) .PHONY: deploy deploy-stlink FLASH_ADDR = 0x08000000 deploy: $(BUILD)/firmware.dfu $(ECHO) "Writing $< to the board" $(Q)$(PYTHON) $(PYDFU) -u $< deploy-stlink: $(BUILD)/firmware.dfu $(ECHO) "Writing $< to the board via ST-LINK" $(Q)$(STFLASH) write $(BUILD)/firmware.bin $(FLASH_ADDR) $(BUILD)/firmware.dfu: $(BUILD)/firmware.elf $(ECHO) "Create $@" $(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data $^ $(BUILD)/firmware.bin $(Q)$(PYTHON) $(DFU) -b $(FLASH_ADDR):$(BUILD)/firmware.bin $@ $(BUILD)/firmware.hex: $(BUILD)/firmware.elf $(ECHO) "Create $@" $(Q)$(OBJCOPY) -O ihex $< $@ $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ ######################################### # Rules to generate header files MAKE_PINS = ../boards/make-pins.py PREFIX_FILE = ../boards/stm32f4xx_prefix.c BOARD_PINS = $(BOARD_DIR)/pins.csv HEADER_BUILD = $(BUILD)/genhdr GEN_QSTRDEFS_GENERATED = $(HEADER_BUILD)/qstrdefs.generated.h GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c GEN_PINS_HDR = $(HEADER_BUILD)/pins.h GEN_PINS_QSTR = $(HEADER_BUILD)/pins_qstr.h GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h GEN_PINS_AF_PY = $(BUILD)/pins_af.py $(OBJ): $(GEN_QSTRDEFS_GENERATED) $(GEN_PINS_AF_DEFS) $(HEADER_BUILD): $(MKDIR) -p $(BUILD)/genhdr $(GEN_QSTRDEFS_GENERATED): | $(HEADER_BUILD) $(Q)echo "// empty" > $@ $(GEN_PINS_AF_DEFS): $(BOARD_PINS) $(MAKE_PINS) ../$(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af ../$(AF_FILE) \ --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) \ --af-const $(GEN_PINS_AF_CONST) --af-defs $(GEN_PINS_AF_DEFS) \ --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC) ######################################### vpath %.S . $(TOP) $(BUILD)/%.o: %.S $(ECHO) "CC $<" $(Q)$(CC) $(CFLAGS) -c -o $@ $< vpath %.s . $(TOP) $(BUILD)/%.o: %.s $(ECHO) "AS $<" $(Q)$(AS) -o $@ $< define compile_c $(ECHO) "CC $<" $(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< @# The following fixes the dependency file. @# See http://make.paulandlesley.org/autodep.html for details. @# Regex adjusted from the above to play better with Windows paths, etc. @$(CP) $(@:.o=.d) $(@:.o=.P); \ $(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ $(RM) -f $(@:.o=.d) endef vpath %.c . $(TOP) $(BUILD)/%.o: %.c $(call compile_c) # $(sort $(var)) removes duplicates # # The net effect of this, is it causes the objects to depend on the # object directories (but only for existence), and the object directories # will be created if they don't exist. OBJ_DIRS = $(sort $(dir $(OBJ))) $(OBJ): | $(OBJ_DIRS) $(OBJ_DIRS): $(MKDIR) -p $@ clean: $(RM) -rf $(BUILD) $(CLEAN_EXTRA) .PHONY: clean ########################################### -include $(OBJ:.o=.P) micropython-1.12/ports/stm32/mboot/README.md000066400000000000000000000157211357706137100205460ustar00rootroot00000000000000Mboot - MicroPython boot loader =============================== Mboot is a custom bootloader for STM32 MCUs, and currently supports the STM32F4xx and STM32F7xx families. It can provide a standard USB DFU interface on either the FS or HS peripherals, as well as a sophisticated, custom I2C interface. It can also load and program firmware in .dfu.gz format from a filesystem. It can fit in 16k of flash space, but all features enabled requires 32k. How to use ---------- 1. Configure your board to use a boot loader by editing the mpconfigboard.mk and mpconfigboard.h files. For example, for an F767 be sure to have these lines in mpconfigboard.mk: LD_FILES = boards/stm32f767.ld boards/common_bl.ld TEXT0_ADDR = 0x08008000 And this in mpconfigboard.h (recommended to put at the end of the file): // Bootloader configuration #define MBOOT_I2C_PERIPH_ID 1 #define MBOOT_I2C_SCL (pin_B8) #define MBOOT_I2C_SDA (pin_B9) #define MBOOT_I2C_ALTFUNC (4) To configure a pin to force entry into the boot loader the following options can be used (with example configuration): #define MBOOT_BOOTPIN_PIN (pin_A0) #define MBOOT_BOOTPIN_PULL (MP_HAL_PIN_PULL_UP) #define MBOOT_BOOTPIN_ACTIVE (0) Mboot supports programming external SPI flash via the DFU and I2C interfaces. SPI flash will be mapped to an address range. To configure it use the following options (edit as needed): #define MBOOT_SPIFLASH_ADDR (0x80000000) #define MBOOT_SPIFLASH_BYTE_SIZE (2 * 1024 * 1024) #define MBOOT_SPIFLASH_LAYOUT "/0x80000000/64*32Kg" #define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (32 / 4) #define MBOOT_SPIFLASH_SPIFLASH (&spi_bdev.spiflash) #define MBOOT_SPIFLASH_CONFIG (&spiflash_config) This assumes that the board declares and defines the relevant SPI flash configuration structs, eg in the board-specific bdev.c file. The `MBOOT_SPIFLASH_LAYOUT` string will be seen by the USB DFU utility and must describe the SPI flash layout. Note that the number of pages in this layout description (the `64` above) cannot be larger than 99 (it must fit in two digits) so the reported page size (the `32Kg` above) must be made large enough so the number of pages fits in two digits. Alternatively the layout can specify multiple sections like `32*16Kg,32*16Kg`, in which case `MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE` must be changed to `16 / 4` to match the `16Kg` value. Mboot supports up to two external SPI flash devices. To configure the second one use the same configuration names as above but with `SPIFLASH2`, ie `MBOOT_SPIFLASH2_ADDR` etc. To enable loading firmware from a filesystem use: #define MBOOT_FSLOAD (1) 2. Build the board's main application firmware as usual. 3. Build mboot via: $ cd mboot $ make BOARD= That should produce a DFU file for mboot. It can be deployed using USB DFU programming via (it will be placed at location 0x08000000): $ make BOARD= deploy 4. Reset the board while holding USR until all 3 LEDs are lit (the 4th option in the cycle) and then release USR. LED0 will then blink once per second to indicate that it's in mboot 5. Use either USB DFU or I2C to download firmware. The script mboot.py shows how to communicate with the I2C boot loader interface. It should be run on a pyboard connected via I2C to the target board. Entering Mboot from application code ------------------------------------ To enter Mboot from a running application do the following: 1. Make sure I and D caches are disabled. 2. Load register r0 with the value 0x70ad0000. The lower 7 bits can be optionally or'd with the desired I2C address. 3. Load the MSP with the value held at 0x08000000. 4. Jump to the value held at 0x08000004. Additional data can be passed to Mboot from application code by storing this data in a special region of RAM. This region begins at the address held at location 0x08000000 (which will point to just after Mboot's stack). A maximum of 1024 bytes can be stored here. To indicate to Mboot that this region is valid load register r0 with 0x70ad0080 (instead of step 2 above), optionally or'd with the desired I2C address. Data in this region is a sequence of elements. Each element has the form: where `type` and `len` are bytes (designated by `u8`) and `payload` is 0 or more bytes. `len` must be the number of bytes in `payload`. The last element in the data sequence must be the end element: * END: type=1, len=0 Note: MicroPython's `machine.bootloader()` function performs steps 1-4 above, and also accepts an optional bytes argument as additional data to pass through to Mboot. Loading firmware from a filesystem ---------------------------------- To get Mboot to load firmware from a filesystem and automatically program it requires passing data elements (see above) which tell where the filesystems are located and what filename to program. The elements to use are: * MOUNT: type=2, len=10, payload=( ) * FSLOAD: type=3, len=1+n, payload=( ) `u32` means unsigned 32-bit little-endian integer. The firmware to load must be a gzip'd DfuSe file (.dfu.gz). The provided fwupdate.py script contains helper functions to call into Mboot with the correct data, and also to update Mboot itself. Example: Mboot on PYBv1.x ------------------------- By default mboot is not used on PYBv1.x, but full mboot configuration is provided for these boards to demonstrate how it works and for testing. To build and deploy mboot on these pyboards the only difference from the normal build process is to pass `USE_MBOOT=1` to make, so that the mboot configuration is used instead of the non-mboot configuration. In detail for PYBv1.0 (for PYBv1.1 use PYBV11 instead of PYBV10): 1. Make sure the pyboard is in factory DFU mode (power up with BOOT0 connected to 3V3), then build mboot and deploy it (from the stm32/mboot/ directory): $ make BOARD=PYBV10 USE_MBOOT=1 clean all deploy This will put mboot on the pyboard. 2. Now put the pyboard in mboot mode by holding down USR, pressing RST, and continue to hold down USR until the blue LED is lit (the 4th option in the cycle) and then release USR. The red LED will blink once per second to indicate that it's in mboot. Then build the MicroPython firmware and deploy it (from the stm32/ directory): $ make BOARD=PYBV10 USE_MBOOT=1 clean all deploy MicroPython will now be on the device and should boot straightaway. On PYBv1.x without mboot the flash layout is as follows: 0x08000000 0x08004000 0x08020000 | ISR text | filesystem | rest of MicroPython firmware On PYBv1.x with mboot the flash layout is as follows: 0x08000000 0x08004000 0x08020000 | mboot | filesystem | ISR and full MicroPython firmware Note that the filesystem remains intact when going to/from an mboot configuration so its contents will be preserved. micropython-1.12/ports/stm32/mboot/diskio.c000066400000000000000000000045731357706137100207200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mphal.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "mboot.h" #if MBOOT_FSLOAD #if FF_MAX_SS == FF_MIN_SS #define SECSIZE (FF_MIN_SS) #else #error Unsupported #endif DRESULT disk_read(void *pdrv, BYTE *buf, DWORD sector, UINT count) { fsload_bdev_t *bdev = pdrv; if (0 <= sector && sector < bdev->byte_len / 512) { do_read(bdev->base_addr + sector * SECSIZE, count * SECSIZE, buf); return RES_OK; } return RES_PARERR; } DRESULT disk_ioctl(void *pdrv, BYTE cmd, void *buf) { fsload_bdev_t *bdev = pdrv; switch (cmd) { case CTRL_SYNC: return RES_OK; case GET_SECTOR_COUNT: *((DWORD*)buf) = bdev->byte_len / SECSIZE; return RES_OK; case GET_SECTOR_SIZE: *((WORD*)buf) = SECSIZE; return RES_OK; case GET_BLOCK_SIZE: *((DWORD*)buf) = 1; // erase block size in units of sector size return RES_OK; case IOCTL_INIT: case IOCTL_STATUS: *((DSTATUS*)buf) = STA_PROTECT; return RES_OK; default: return RES_PARERR; } } #endif // MBOOT_FSLOAD micropython-1.12/ports/stm32/mboot/elem.c000066400000000000000000000032701357706137100203510ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "mboot.h" // Elements are of the form: (type:u8, len:u8, payload) const uint8_t *elem_search(const uint8_t *elem, uint8_t elem_id) { while (elem + 2 + elem[1] <= ELEM_DATA_MAX) { if (elem[0] == elem_id) { // Found element, return a pointer to the element data return elem + 2; } if (elem[0] == ELEM_TYPE_END) { // End of elements return NULL; } elem += 2 + elem[1]; } return NULL; } micropython-1.12/ports/stm32/mboot/ffconf.h000066400000000000000000000043241357706137100206760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #define FFCONF_DEF 86604 #define FF_FS_READONLY 1 #define FF_FS_MINIMIZE 0 #define FF_USE_STRFUNC 0 #define FF_USE_FIND 0 #define FF_USE_MKFS 0 #define FF_USE_FASTSEEK 0 #define FF_USE_EXPAND 0 #define FF_USE_CHMOD 0 #define FF_USE_LABEL 0 #define FF_USE_FORWARD 0 #define FF_CODE_PAGE 437 #define FF_USE_LFN 1 #define FF_MAX_LFN 255 #define FF_LFN_UNICODE 0 #define FF_LFN_BUF 255 #define FF_SFN_BUF 12 #define FF_STRF_ENCODE 3 #define FF_FS_RPATH 0 #define FF_VOLUMES 1 #define FF_STR_VOLUME_ID 0 #define FF_MULTI_PARTITION 0 #define FF_MIN_SS 512 #define FF_MAX_SS 512 #define FF_USE_TRIM 0 #define FF_FS_NOFSINFO 0 #define FF_FS_TINY 1 #define FF_FS_EXFAT 0 #define FF_FS_NORTC 1 #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 #define FF_NORTC_YEAR 2019 #define FF_FS_LOCK 0 #define FF_FS_REENTRANT 0 micropython-1.12/ports/stm32/mboot/fsload.c000066400000000000000000000174311357706137100207030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mphal.h" #include "lib/oofatfs/ff.h" #include "extmod/uzlib/uzlib.h" #include "mboot.h" #if MBOOT_FSLOAD #define DICT_SIZE (1 << 15) typedef struct _gz_stream_t { FIL fp; TINF_DATA tinf; uint8_t buf[512]; uint8_t dict[DICT_SIZE]; } gz_stream_t; static gz_stream_t gz_stream SECTION_NOZERO_BSS; static int gz_stream_read_src(TINF_DATA *tinf) { UINT n; FRESULT res = f_read(&gz_stream.fp, gz_stream.buf, sizeof(gz_stream.buf), &n); if (res != FR_OK) { return -1; } if (n == 0) { return -1; } tinf->source = gz_stream.buf + 1; tinf->source_limit = gz_stream.buf + n; return gz_stream.buf[0]; } static int gz_stream_open(FATFS *fatfs, const char *filename) { FRESULT res = f_open(fatfs, &gz_stream.fp, filename, FA_READ); if (res != FR_OK) { return -1; } memset(&gz_stream.tinf, 0, sizeof(gz_stream.tinf)); gz_stream.tinf.readSource = gz_stream_read_src; int st = uzlib_gzip_parse_header(&gz_stream.tinf); if (st != TINF_OK) { f_close(&gz_stream.fp); return -1; } uzlib_uncompress_init(&gz_stream.tinf, gz_stream.dict, DICT_SIZE); return 0; } static int gz_stream_read(size_t len, uint8_t *buf) { gz_stream.tinf.dest = buf; gz_stream.tinf.dest_limit = buf + len; int st = uzlib_uncompress_chksum(&gz_stream.tinf); if (st == TINF_DONE) { return 0; } if (st < 0) { return st; } return gz_stream.tinf.dest - buf; } static int fsload_program_file(FATFS *fatfs, const char *filename, bool write_to_flash) { int res = gz_stream_open(fatfs, filename); if (res != 0) { return res; } // Parse DFU uint8_t buf[512]; size_t file_offset; // Read file header, <5sBIB res = gz_stream_read(11, buf); if (res != 11) { return -1; } file_offset = 11; // Validate header, version 1 if (memcmp(buf, "DfuSe\x01", 6) != 0) { return -1; } // Must have only 1 target if (buf[10] != 1) { return -2; } // Get total size uint32_t total_size = get_le32(buf + 6); // Read target header, <6sBi255sII res = gz_stream_read(274, buf); if (res != 274) { return -1; } file_offset += 274; // Validate target header, with alt being 0 if (memcmp(buf, "Target\x00", 7) != 0) { return -1; } // Get target size and number of elements uint32_t target_size = get_le32(buf + 266); uint32_t num_elems = get_le32(buf + 270); size_t file_offset_target = file_offset; // Parse each element for (size_t elem = 0; elem < num_elems; ++elem) { // Read element header, sizeof(buf)) { l = sizeof(buf); } res = gz_stream_read(l, buf); if (res != l) { return -1; } if (write_to_flash) { res = do_write(elem_addr, buf, l); if (res != 0) { return -1; } elem_addr += l; } s -= l; } file_offset += elem_size; } if (target_size != file_offset - file_offset_target) { return -1; } if (total_size != file_offset) { return -1; } // Read trailing info res = gz_stream_read(16, buf); if (res != 16) { return -1; } // TODO validate CRC32 return 0; } static int fsload_process_fatfs(uint32_t base_addr, uint32_t byte_len, size_t fname_len, const char *fname) { fsload_bdev_t bdev = {base_addr, byte_len}; FATFS fatfs; fatfs.drv = &bdev; FRESULT res = f_mount(&fatfs); if (res != FR_OK) { return -1; } FF_DIR dp; res = f_opendir(&fatfs, &dp, "/"); if (res != FR_OK) { return -1; } // Search for firmware file with correct name int r; for (;;) { FILINFO fno; res = f_readdir(&dp, &fno); char *fn = fno.fname; if (res != FR_OK || fn[0] == 0) { // Finished listing dir, no firmware found r = -1; break; } if (memcmp(fn, fname, fname_len) == 0 && fn[fname_len] == '\0') { // Found firmware led_state_all(2); r = fsload_program_file(&fatfs, fn, false); if (r == 0) { // Firmware is valid, program it led_state_all(4); r = fsload_program_file(&fatfs, fn, true); } break; } } return r; } int fsload_process(void) { const uint8_t *elem = elem_search(ELEM_DATA_START, ELEM_TYPE_FSLOAD); if (elem == NULL || elem[-1] < 2) { return -1; } uint8_t mount_point = elem[0]; uint8_t fname_len = elem[-1] - 1; const char *fname = (const char*)&elem[1]; elem = ELEM_DATA_START; for (;;) { elem = elem_search(elem, ELEM_TYPE_MOUNT); if (elem == NULL || elem[-1] != 10) { // End of elements, or invalid MOUNT element return -1; } if (elem[0] == mount_point) { uint32_t base_addr = get_le32(&elem[2]); uint32_t byte_len = get_le32(&elem[6]); if (elem[1] == ELEM_MOUNT_FAT) { int ret = fsload_process_fatfs(base_addr, byte_len, fname_len, fname); // Flash LEDs based on success/failure of update for (int i = 0; i < 4; ++i) { if (ret == 0) { led_state_all(7); } else { led_state_all(1); } mp_hal_delay_ms(100); led_state_all(0); mp_hal_delay_ms(100); } return ret; } // Unknown filesystem type return -1; } elem += elem[-1]; } } #endif // MBOOT_FSLOAD micropython-1.12/ports/stm32/mboot/fwupdate.py000066400000000000000000000111421357706137100214510ustar00rootroot00000000000000# Update Mboot or MicroPython from a .dfu.gz file on the board's filesystem # MIT license; Copyright (c) 2019 Damien P. George import struct, time import uzlib, machine, stm FLASH_KEY1 = 0x45670123 FLASH_KEY2 = 0xcdef89ab def check_mem_contains(addr, buf): mem8 = stm.mem8 r = range(len(buf)) for off in r: if mem8[addr + off] != buf[off]: return False return True def check_mem_erased(addr, size): mem16 = stm.mem16 r = range(0, size, 2) for off in r: if mem16[addr + off] != 0xffff: return False return True def dfu_read(filename): f = open(filename, 'rb') hdr = f.read(3) f.seek(0) if hdr == b'Dfu': pass elif hdr == b'\x1f\x8b\x08': f = uzlib.DecompIO(f, 16 + 15) else: print('Invalid firmware', filename) return None elems = [] hdr = f.read(11) sig, ver, size, num_targ = struct.unpack('<5sBIB', hdr) file_offset = 11 for i in range(num_targ): hdr = f.read(274) sig, alt, has_name, name, t_size, num_elem = struct.unpack('<6sBi255sII', hdr) file_offset += 274 file_offset_t = file_offset for j in range(num_elem): hdr = f.read(8) addr, e_size = struct.unpack(' 16 * 1024 and not check_mem_erased(mboot_addr + 16 * 1024, 16 * 1024): flash_erase_sector(1) flash_write(mboot_addr, mboot_fw) flash_lock() machine.enable_irq(irq) print('New Mboot programmed.') if check_mem_contains(mboot_addr, mboot_fw): print('Verification of new Mboot succeeded.') else: print('Verification of new Mboot FAILED! Try rerunning.') print('Programming finished, can now reset or turn off.') def update_mpy(filename, fs_base, fs_len): # Check firmware is of .dfu.gz type try: with open(filename, 'rb') as f: hdr = uzlib.DecompIO(f, 16 + 15).read(6) except Exception: hdr = None if hdr != b'DfuSe\x01': print('Firmware must be a .dfu.gz file.') return ELEM_TYPE_END = 1 ELEM_TYPE_MOUNT = 2 ELEM_TYPE_FSLOAD = 3 ELEM_MOUNT_FAT = 1 mount_point = 1 mount = struct.pack(' #include #include "py/mphal.h" #include "extmod/crypto-algorithms/sha256.c" #include "usbd_core.h" #include "storage.h" #include "i2cslave.h" #include "mboot.h" // Using polling is about 10% faster than not using it (and using IRQ instead) // This DFU code with polling runs in about 70% of the time of the ST bootloader #define USE_USB_POLLING (1) // Using cache probably won't make it faster because we run at a low frequency, and best // to keep the MCU config as minimal as possible. #define USE_CACHE (0) // IRQ priorities (encoded values suitable for NVIC_SetPriority) #define IRQ_PRI_SYSTICK (NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 0, 0)) #define IRQ_PRI_I2C (NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 1, 0)) // Configure PLL to give the desired CPU freq #undef MICROPY_HW_FLASH_LATENCY #if defined(STM32H7) #define CORE_PLL_FREQ (96000000) #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_2 #else #define CORE_PLL_FREQ (48000000) #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_1 #endif #undef MICROPY_HW_CLK_PLLM #undef MICROPY_HW_CLK_PLLN #undef MICROPY_HW_CLK_PLLP #undef MICROPY_HW_CLK_PLLQ #undef MICROPY_HW_CLK_PLLR #define MICROPY_HW_CLK_PLLM (HSE_VALUE / 1000000) #define MICROPY_HW_CLK_PLLN (192) #define MICROPY_HW_CLK_PLLP (MICROPY_HW_CLK_PLLN / (CORE_PLL_FREQ / 1000000)) #define MICROPY_HW_CLK_PLLQ (4) #define MICROPY_HW_CLK_PLLR (2) // Work out which USB device to use for the USB DFU interface #if !defined(MICROPY_HW_USB_MAIN_DEV) #if MICROPY_HW_USB_FS #define MICROPY_HW_USB_MAIN_DEV (USB_PHY_FS_ID) #elif MICROPY_HW_USB_HS #define MICROPY_HW_USB_MAIN_DEV (USB_PHY_HS_ID) #else #error Unable to determine proper MICROPY_HW_USB_MAIN_DEV to use #endif #endif // These bits are used to detect valid application firmware at APPLICATION_ADDR #define APP_VALIDITY_BITS (0x00000003) #define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) static void do_reset(void); uint32_t get_le32(const uint8_t *b) { return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24; } void mp_hal_delay_us(mp_uint_t usec) { // use a busy loop for the delay // sys freq is always a multiple of 2MHz, so division here won't lose precision const uint32_t ucount = CORE_PLL_FREQ / 2000000 * usec / 2; for (uint32_t count = 0; ++count <= ucount;) { } } static volatile uint32_t systick_ms; void mp_hal_delay_ms(mp_uint_t ms) { if (__get_PRIMASK() == 0) { // IRQs enabled, use systick if (ms != 0 && ms != (mp_uint_t)-1) { ++ms; // account for the fact that systick_ms may roll over immediately } uint32_t start = systick_ms; while (systick_ms - start < ms) { __WFI(); } } else { // IRQs disabled, so need to use a busy loop for the delay. // To prevent possible overflow of the counter we use a double loop. const uint32_t count_1ms = 16000000 / 8000; for (uint32_t i = 0; i < ms; i++) { for (volatile uint32_t count = 0; ++count <= count_1ms;) { } } } } // Needed by parts of the HAL uint32_t HAL_GetTick(void) { return systick_ms; } // Needed by parts of the HAL void HAL_Delay(uint32_t ms) { mp_hal_delay_ms(ms); } static void __fatal_error(const char *msg) { NVIC_SystemReset(); for (;;) { } } /******************************************************************************/ // CLOCK #if defined(STM32F4) || defined(STM32F7) #define CONFIG_RCC_CR_1ST (RCC_CR_HSION) #define CONFIG_RCC_CR_2ND (RCC_CR_HSEON || RCC_CR_CSSON || RCC_CR_PLLON) #define CONFIG_RCC_PLLCFGR (0x24003010) #elif defined(STM32H7) #define CONFIG_RCC_CR_1ST (RCC_CR_HSION) #define CONFIG_RCC_CR_2ND (RCC_CR_PLL3ON | RCC_CR_PLL2ON | RCC_CR_PLL1ON | RCC_CR_CSSHSEON \ | RCC_CR_HSEON | RCC_CR_HSI48ON | RCC_CR_CSIKERON | RCC_CR_CSION) #define CONFIG_RCC_PLLCFGR (0x00000000) #else #error Unknown processor #endif void SystemInit(void) { #if defined(STM32H7) // Configure write-once power options, and wait for voltage levels to be ready PWR->CR3 = PWR_CR3_LDOEN; while (!(PWR->CSR1 & PWR_CSR1_ACTVOSRDY)) { } #endif // Set HSION bit RCC->CR |= CONFIG_RCC_CR_1ST; // Reset CFGR register RCC->CFGR = 0x00000000; // Reset HSEON, CSSON and PLLON bits RCC->CR &= ~CONFIG_RCC_CR_2ND; // Reset PLLCFGR register RCC->PLLCFGR = CONFIG_RCC_PLLCFGR; #if defined(STM32H7) // Reset PLL and clock configuration registers RCC->D1CFGR = 0x00000000; RCC->D2CFGR = 0x00000000; RCC->D3CFGR = 0x00000000; RCC->PLLCKSELR = 0x00000000; RCC->D1CCIPR = 0x00000000; RCC->D2CCIP1R = 0x00000000; RCC->D2CCIP2R = 0x00000000; RCC->D3CCIPR = 0x00000000; #endif // Reset HSEBYP bit RCC->CR &= (uint32_t)0xFFFBFFFF; // Disable all interrupts #if defined(STM32F4) || defined(STM32F7) RCC->CIR = 0x00000000; #elif defined(STM32H7) RCC->CIER = 0x00000000; #endif // Set location of vector table SCB->VTOR = FLASH_BASE; // Enable 8-byte stack alignment for IRQ handlers, in accord with EABI SCB->CCR |= SCB_CCR_STKALIGN_Msk; } void systick_init(void) { // Configure SysTick as 1ms ticker SysTick_Config(SystemCoreClock / 1000); NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_SYSTICK); } #if defined(STM32F4) || defined(STM32F7) void SystemClock_Config(void) { // This function assumes that HSI is used as the system clock (see RCC->CFGR, SWS bits) // Enable Power Control clock __HAL_RCC_PWR_CLK_ENABLE(); // Reduce power consumption __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); // Turn HSE on __HAL_RCC_HSE_CONFIG(RCC_HSE_ON); while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET) { } // Disable PLL __HAL_RCC_PLL_DISABLE(); while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET) { } // Configure PLL factors and source RCC->PLLCFGR = 1 << RCC_PLLCFGR_PLLSRC_Pos // HSE selected as PLL source | MICROPY_HW_CLK_PLLM << RCC_PLLCFGR_PLLM_Pos | MICROPY_HW_CLK_PLLN << RCC_PLLCFGR_PLLN_Pos | ((MICROPY_HW_CLK_PLLP >> 1) - 1) << RCC_PLLCFGR_PLLP_Pos | MICROPY_HW_CLK_PLLQ << RCC_PLLCFGR_PLLQ_Pos #ifdef RCC_PLLCFGR_PLLR | 2 << RCC_PLLCFGR_PLLR_Pos // default PLLR value of 2 #endif ; // Enable PLL __HAL_RCC_PLL_ENABLE(); while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) { } // Increase latency before changing clock if (MICROPY_HW_FLASH_LATENCY > (FLASH->ACR & FLASH_ACR_LATENCY)) { __HAL_FLASH_SET_LATENCY(MICROPY_HW_FLASH_LATENCY); } // Configure AHB divider MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1); // Configure SYSCLK source from PLL __HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_PLLCLK); while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) { } // Decrease latency after changing clock if (MICROPY_HW_FLASH_LATENCY < (FLASH->ACR & FLASH_ACR_LATENCY)) { __HAL_FLASH_SET_LATENCY(MICROPY_HW_FLASH_LATENCY); } // Set APB clock dividers MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_HCLK_DIV4); MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_HCLK_DIV2 << 3); // Update clock value and reconfigure systick now that the frequency changed SystemCoreClock = CORE_PLL_FREQ; systick_init(); #if defined(STM32F7) // The DFU bootloader changes the clocksource register from its default power // on reset value, so we set it back here, so the clocksources are the same // whether we were started from DFU or from a power on reset. RCC->DCKCFGR2 = 0; #endif } #elif defined(STM32H7) void SystemClock_Config(void) { // This function assumes that HSI is used as the system clock (see RCC->CFGR, SWS bits) // Select VOS level as high voltage to give reliable operation __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY) == RESET) { } // Turn HSE on __HAL_RCC_HSE_CONFIG(RCC_HSE_ON); while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET) { } // Disable PLL1 __HAL_RCC_PLL_DISABLE(); while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET) { } // Configure PLL1 factors and source RCC->PLLCKSELR = MICROPY_HW_CLK_PLLM << RCC_PLLCKSELR_DIVM1_Pos | 2 << RCC_PLLCKSELR_PLLSRC_Pos; // HSE selected as PLL source RCC->PLL1DIVR = (MICROPY_HW_CLK_PLLN - 1) << RCC_PLL1DIVR_N1_Pos | (MICROPY_HW_CLK_PLLP - 1) << RCC_PLL1DIVR_P1_Pos // only even P allowed | (MICROPY_HW_CLK_PLLQ - 1) << RCC_PLL1DIVR_Q1_Pos | (MICROPY_HW_CLK_PLLR - 1) << RCC_PLL1DIVR_R1_Pos; // Enable PLL1 outputs for SYSCLK and USB RCC->PLLCFGR = RCC_PLLCFGR_DIVP1EN | RCC_PLLCFGR_DIVQ1EN; // Select PLL1-Q for USB clock source RCC->D2CCIP2R |= 1 << RCC_D2CCIP2R_USBSEL_Pos; // Enable PLL1 __HAL_RCC_PLL_ENABLE(); while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) { } // Increase latency before changing SYSCLK if (MICROPY_HW_FLASH_LATENCY > (FLASH->ACR & FLASH_ACR_LATENCY)) { __HAL_FLASH_SET_LATENCY(MICROPY_HW_FLASH_LATENCY); } // Configure AHB divider RCC->D1CFGR = 0 << RCC_D1CFGR_D1CPRE_Pos // SYSCLK prescaler of 1 | 8 << RCC_D1CFGR_HPRE_Pos // AHB prescaler of 2 ; // Configure SYSCLK source from PLL __HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_PLLCLK); while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) { } // Decrease latency after changing clock if (MICROPY_HW_FLASH_LATENCY < (FLASH->ACR & FLASH_ACR_LATENCY)) { __HAL_FLASH_SET_LATENCY(MICROPY_HW_FLASH_LATENCY); } // Set APB clock dividers RCC->D1CFGR |= 4 << RCC_D1CFGR_D1PPRE_Pos // APB3 prescaler of 2 ; RCC->D2CFGR = 4 << RCC_D2CFGR_D2PPRE2_Pos // APB2 prescaler of 2 | 4 << RCC_D2CFGR_D2PPRE1_Pos // APB1 prescaler of 2 ; RCC->D3CFGR = 4 << RCC_D3CFGR_D3PPRE_Pos // APB4 prescaler of 2 ; // Update clock value and reconfigure systick now that the frequency changed SystemCoreClock = CORE_PLL_FREQ; systick_init(); } #endif // Needed by HAL_PCD_IRQHandler uint32_t HAL_RCC_GetHCLKFreq(void) { return SystemCoreClock; } /******************************************************************************/ // GPIO #if defined(STM32F4) || defined(STM32F7) #define AHBxENR AHB1ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB1ENR_GPIOAEN_Pos #elif defined(STM32H7) #define AHBxENR AHB4ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB4ENR_GPIOAEN_Pos #endif void mp_hal_pin_config(mp_hal_pin_obj_t port_pin, uint32_t mode, uint32_t pull, uint32_t alt) { GPIO_TypeDef *gpio = (GPIO_TypeDef*)(port_pin & ~0xf); // Enable the GPIO peripheral clock uint32_t gpio_idx = ((uintptr_t)gpio - GPIOA_BASE) / (GPIOB_BASE - GPIOA_BASE); RCC->AHBxENR |= 1 << (AHBxENR_GPIOAEN_Pos + gpio_idx); volatile uint32_t tmp = RCC->AHBxENR; // Delay after enabling clock (void)tmp; // Configure the pin uint32_t pin = port_pin & 0xf; gpio->MODER = (gpio->MODER & ~(3 << (2 * pin))) | ((mode & 3) << (2 * pin)); gpio->OTYPER = (gpio->OTYPER & ~(1 << pin)) | ((mode >> 2) << pin); gpio->OSPEEDR = (gpio->OSPEEDR & ~(3 << (2 * pin))) | (2 << (2 * pin)); // full speed gpio->PUPDR = (gpio->PUPDR & ~(3 << (2 * pin))) | (pull << (2 * pin)); gpio->AFR[pin >> 3] = (gpio->AFR[pin >> 3] & ~(15 << (4 * (pin & 7)))) | (alt << (4 * (pin & 7))); } void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) { GPIO_TypeDef *gpio = (GPIO_TypeDef*)(port_pin & ~0xf); uint32_t pin = port_pin & 0xf; gpio->OSPEEDR = (gpio->OSPEEDR & ~(3 << (2 * pin))) | (speed << (2 * pin)); } /******************************************************************************/ // LED #define LED0 MICROPY_HW_LED1 #define LED1 MICROPY_HW_LED2 #ifdef MICROPY_HW_LED3 #define LED2 MICROPY_HW_LED3 #endif #ifdef MICROPY_HW_LED4 #define LED3 MICROPY_HW_LED4 #endif void led_init(void) { mp_hal_pin_output(LED0); mp_hal_pin_output(LED1); #ifdef LED2 mp_hal_pin_output(LED2); #endif #ifdef LED3 mp_hal_pin_output(LED3); #endif } void led_state(int led, int val) { if (led == 1) { led = LED0; } if (val) { MICROPY_HW_LED_ON(led); } else { MICROPY_HW_LED_OFF(led); } } void led_state_all(unsigned int mask) { led_state(LED0, mask & 1); led_state(LED1, mask & 2); #ifdef LED2 led_state(LED2, mask & 4); #endif #ifdef LED3 led_state(LED3, mask & 8); #endif } /******************************************************************************/ // USR BUTTON static void usrbtn_init(void) { mp_hal_pin_config(MICROPY_HW_USRSW_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_USRSW_PULL, 0); } static int usrbtn_state(void) { return mp_hal_pin_read(MICROPY_HW_USRSW_PIN) == MICROPY_HW_USRSW_PRESSED; } /******************************************************************************/ // FLASH #ifndef MBOOT_SPIFLASH_LAYOUT #define MBOOT_SPIFLASH_LAYOUT "" #endif #ifndef MBOOT_SPIFLASH2_LAYOUT #define MBOOT_SPIFLASH2_LAYOUT "" #endif typedef struct { uint32_t base_address; uint32_t sector_size; uint32_t sector_count; } flash_layout_t; #if defined(STM32F7) // FLASH_FLAG_PGSERR (Programming Sequence Error) was renamed to // FLASH_FLAG_ERSERR (Erasing Sequence Error) in STM32F7 #define FLASH_FLAG_PGSERR FLASH_FLAG_ERSERR #endif #if defined(STM32F4) \ || defined(STM32F722xx) \ || defined(STM32F723xx) \ || defined(STM32F732xx) \ || defined(STM32F733xx) #define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT static const flash_layout_t flash_layout[] = { { 0x08000000, 0x04000, 4 }, { 0x08010000, 0x10000, 1 }, { 0x08020000, 0x20000, 3 }, #if defined(FLASH_SECTOR_8) { 0x08080000, 0x20000, 4 }, #endif #if defined(FLASH_SECTOR_12) { 0x08100000, 0x04000, 4 }, { 0x08110000, 0x10000, 1 }, { 0x08120000, 0x20000, 7 }, #endif }; #elif defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) #define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/04*032Kg,01*128Kg,07*256Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT // This is for dual-bank mode disabled static const flash_layout_t flash_layout[] = { { 0x08000000, 0x08000, 4 }, { 0x08020000, 0x20000, 1 }, { 0x08040000, 0x40000, 7 }, }; #elif defined(STM32H743xx) #define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/16*128Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT static const flash_layout_t flash_layout[] = { { 0x08000000, 0x20000, 16 }, }; #endif static uint32_t flash_get_sector_index(uint32_t addr, uint32_t *sector_size) { if (addr >= flash_layout[0].base_address) { uint32_t sector_index = 0; for (int i = 0; i < MP_ARRAY_SIZE(flash_layout); ++i) { for (int j = 0; j < flash_layout[i].sector_count; ++j) { uint32_t sector_start_next = flash_layout[i].base_address + (j + 1) * flash_layout[i].sector_size; if (addr < sector_start_next) { *sector_size = flash_layout[i].sector_size; return sector_index; } ++sector_index; } } } return 0; } #if defined(STM32H7) // get the bank of a given flash address static uint32_t get_bank(uint32_t addr) { if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_SWAP_BANK) == 0) { // no bank swap if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) { return FLASH_BANK_1; } else { return FLASH_BANK_2; } } else { // bank swap if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) { return FLASH_BANK_2; } else { return FLASH_BANK_1; } } } #endif static int flash_mass_erase(void) { // TODO return -1; } static int flash_page_erase(uint32_t addr, uint32_t *next_addr) { uint32_t sector_size = 0; uint32_t sector = flash_get_sector_index(addr, §or_size); if (sector == 0) { // Don't allow to erase the sector with this bootloader in it return -1; } *next_addr = addr + sector_size; HAL_FLASH_Unlock(); // Clear pending flags (if any) #if defined(STM32H7) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2); #else __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); #endif // erase the sector(s) FLASH_EraseInitTypeDef EraseInitStruct; EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V #if defined(STM32H7) EraseInitStruct.Banks = get_bank(addr); #endif EraseInitStruct.Sector = sector; EraseInitStruct.NbSectors = 1; uint32_t SectorError = 0; if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { // error occurred during sector erase return -1; } // Check the erase set bits to 1, at least for the first 256 bytes for (int i = 0; i < 64; ++i) { if (((volatile uint32_t*)addr)[i] != 0xffffffff) { return -2; } } return 0; } static int flash_write(uint32_t addr, const uint8_t *src8, size_t len) { if (addr >= flash_layout[0].base_address && addr < flash_layout[0].base_address + flash_layout[0].sector_size) { // Don't allow to write the sector with this bootloader in it return -1; } const uint32_t *src = (const uint32_t*)src8; size_t num_word32 = (len + 3) / 4; HAL_FLASH_Unlock(); #if defined(STM32H7) // program the flash 256 bits at a time for (int i = 0; i < num_word32 / 8; ++i) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr, (uint64_t)(uint32_t)src) != HAL_OK) { return - 1; } addr += 32; src += 8; } #else // program the flash word by word for (size_t i = 0; i < num_word32; i++) { if (HAL_FLASH_Program(TYPEPROGRAM_WORD, addr, *src) != HAL_OK) { return -1; } addr += 4; src += 1; } #endif // TODO verify data return 0; } /******************************************************************************/ // Writable address space interface static int do_mass_erase(void) { // TODO return flash_mass_erase(); } #if defined(MBOOT_SPIFLASH_ADDR) || defined(MBOOT_SPIFLASH2_ADDR) static int spiflash_page_erase(mp_spiflash_t *spif, uint32_t addr, uint32_t n_blocks) { for (int i = 0; i < n_blocks; ++i) { int ret = mp_spiflash_erase_block(spif, addr); if (ret != 0) { return ret; } addr += MP_SPIFLASH_ERASE_BLOCK_SIZE; } return 0; } #endif int do_page_erase(uint32_t addr, uint32_t *next_addr) { led_state(LED0, 1); #if defined(MBOOT_SPIFLASH_ADDR) if (MBOOT_SPIFLASH_ADDR <= addr && addr < MBOOT_SPIFLASH_ADDR + MBOOT_SPIFLASH_BYTE_SIZE) { *next_addr = addr + MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE * MP_SPIFLASH_ERASE_BLOCK_SIZE; return spiflash_page_erase(MBOOT_SPIFLASH_SPIFLASH, addr - MBOOT_SPIFLASH_ADDR, MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE); } #endif #if defined(MBOOT_SPIFLASH2_ADDR) if (MBOOT_SPIFLASH2_ADDR <= addr && addr < MBOOT_SPIFLASH2_ADDR + MBOOT_SPIFLASH2_BYTE_SIZE) { *next_addr = addr + MBOOT_SPIFLASH2_ERASE_BLOCKS_PER_PAGE * MP_SPIFLASH_ERASE_BLOCK_SIZE; return spiflash_page_erase(MBOOT_SPIFLASH2_SPIFLASH, addr - MBOOT_SPIFLASH2_ADDR, MBOOT_SPIFLASH2_ERASE_BLOCKS_PER_PAGE); } #endif return flash_page_erase(addr, next_addr); } void do_read(uint32_t addr, int len, uint8_t *buf) { #if defined(MBOOT_SPIFLASH_ADDR) if (MBOOT_SPIFLASH_ADDR <= addr && addr < MBOOT_SPIFLASH_ADDR + MBOOT_SPIFLASH_BYTE_SIZE) { mp_spiflash_read(MBOOT_SPIFLASH_SPIFLASH, addr - MBOOT_SPIFLASH_ADDR, len, buf); return; } #endif #if defined(MBOOT_SPIFLASH2_ADDR) if (MBOOT_SPIFLASH2_ADDR <= addr && addr < MBOOT_SPIFLASH2_ADDR + MBOOT_SPIFLASH2_BYTE_SIZE) { mp_spiflash_read(MBOOT_SPIFLASH2_SPIFLASH, addr - MBOOT_SPIFLASH2_ADDR, len, buf); return; } #endif // Other addresses, just read directly from memory memcpy(buf, (void*)addr, len); } int do_write(uint32_t addr, const uint8_t *src8, size_t len) { static uint32_t led_tog = 0; led_state(LED0, (led_tog++) & 4); #if defined(MBOOT_SPIFLASH_ADDR) if (MBOOT_SPIFLASH_ADDR <= addr && addr < MBOOT_SPIFLASH_ADDR + MBOOT_SPIFLASH_BYTE_SIZE) { return mp_spiflash_write(MBOOT_SPIFLASH_SPIFLASH, addr - MBOOT_SPIFLASH_ADDR, len, src8); } #endif #if defined(MBOOT_SPIFLASH2_ADDR) if (MBOOT_SPIFLASH2_ADDR <= addr && addr < MBOOT_SPIFLASH2_ADDR + MBOOT_SPIFLASH2_BYTE_SIZE) { return mp_spiflash_write(MBOOT_SPIFLASH2_SPIFLASH, addr - MBOOT_SPIFLASH2_ADDR, len, src8); } #endif return flash_write(addr, src8, len); } /******************************************************************************/ // I2C slave interface #if defined(MBOOT_I2C_SCL) #define PASTE2(a, b) a ## b #define PASTE3(a, b, c) a ## b ## c #define EVAL_PASTE2(a, b) PASTE2(a, b) #define EVAL_PASTE3(a, b, c) PASTE3(a, b, c) #define MBOOT_I2Cx EVAL_PASTE2(I2C, MBOOT_I2C_PERIPH_ID) #define I2Cx_EV_IRQn EVAL_PASTE3(I2C, MBOOT_I2C_PERIPH_ID, _EV_IRQn) #define I2Cx_EV_IRQHandler EVAL_PASTE3(I2C, MBOOT_I2C_PERIPH_ID, _EV_IRQHandler) #define I2C_CMD_BUF_LEN (129) enum { I2C_CMD_ECHO = 1, I2C_CMD_GETID, // () -> u8*12 unique id, ASCIIZ mcu name, ASCIIZ board name I2C_CMD_GETCAPS, // not implemented I2C_CMD_RESET, // () -> () I2C_CMD_CONFIG, // not implemented I2C_CMD_GETLAYOUT, // () -> ASCII string I2C_CMD_MASSERASE, // () -> () I2C_CMD_PAGEERASE, // le32 -> () I2C_CMD_SETRDADDR, // le32 -> () I2C_CMD_SETWRADDR, // le32 -> () I2C_CMD_READ, // u8 -> bytes I2C_CMD_WRITE, // bytes -> () I2C_CMD_COPY, // not implemented I2C_CMD_CALCHASH, // le32 -> u8*32 I2C_CMD_MARKVALID, // () -> () }; typedef struct _i2c_obj_t { volatile bool cmd_send_arg; volatile bool cmd_arg_sent; volatile int cmd_arg; volatile uint32_t cmd_rdaddr; volatile uint32_t cmd_wraddr; volatile uint16_t cmd_buf_pos; uint8_t cmd_buf[I2C_CMD_BUF_LEN]; } i2c_obj_t; static i2c_obj_t i2c_obj; void i2c_init(int addr) { i2c_obj.cmd_send_arg = false; mp_hal_pin_config(MBOOT_I2C_SCL, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, MBOOT_I2C_ALTFUNC); mp_hal_pin_config(MBOOT_I2C_SDA, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, MBOOT_I2C_ALTFUNC); i2c_slave_init(MBOOT_I2Cx, I2Cx_EV_IRQn, IRQ_PRI_I2C, addr); } int i2c_slave_process_addr_match(int rw) { if (i2c_obj.cmd_arg_sent) { i2c_obj.cmd_send_arg = false; } i2c_obj.cmd_buf_pos = 0; return 0; // ACK } int i2c_slave_process_rx_byte(uint8_t val) { if (i2c_obj.cmd_buf_pos < sizeof(i2c_obj.cmd_buf)) { i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++] = val; } return 0; // ACK } void i2c_slave_process_rx_end(void) { if (i2c_obj.cmd_buf_pos == 0) { return; } int len = i2c_obj.cmd_buf_pos - 1; uint8_t *buf = i2c_obj.cmd_buf; if (buf[0] == I2C_CMD_ECHO) { ++len; } else if (buf[0] == I2C_CMD_GETID && len == 0) { memcpy(buf, (uint8_t*)MP_HAL_UNIQUE_ID_ADDRESS, 12); memcpy(buf + 12, MICROPY_HW_MCU_NAME, sizeof(MICROPY_HW_MCU_NAME)); memcpy(buf + 12 + sizeof(MICROPY_HW_MCU_NAME), MICROPY_HW_BOARD_NAME, sizeof(MICROPY_HW_BOARD_NAME) - 1); len = 12 + sizeof(MICROPY_HW_MCU_NAME) + sizeof(MICROPY_HW_BOARD_NAME) - 1; } else if (buf[0] == I2C_CMD_RESET && len == 0) { do_reset(); } else if (buf[0] == I2C_CMD_GETLAYOUT && len == 0) { len = strlen(FLASH_LAYOUT_STR); memcpy(buf, FLASH_LAYOUT_STR, len); } else if (buf[0] == I2C_CMD_MASSERASE && len == 0) { len = do_mass_erase(); } else if (buf[0] == I2C_CMD_PAGEERASE && len == 4) { uint32_t next_addr; len = do_page_erase(get_le32(buf + 1), &next_addr); } else if (buf[0] == I2C_CMD_SETRDADDR && len == 4) { i2c_obj.cmd_rdaddr = get_le32(buf + 1); len = 0; } else if (buf[0] == I2C_CMD_SETWRADDR && len == 4) { i2c_obj.cmd_wraddr = get_le32(buf + 1); len = 0; } else if (buf[0] == I2C_CMD_READ && len == 1) { len = buf[1]; if (len > I2C_CMD_BUF_LEN) { len = I2C_CMD_BUF_LEN; } do_read(i2c_obj.cmd_rdaddr, len, buf); i2c_obj.cmd_rdaddr += len; } else if (buf[0] == I2C_CMD_WRITE) { if (i2c_obj.cmd_wraddr == APPLICATION_ADDR) { // Mark the 2 lower bits to indicate invalid app firmware buf[1] |= APP_VALIDITY_BITS; } int ret = do_write(i2c_obj.cmd_wraddr, buf + 1, len); if (ret < 0) { len = ret; } else { i2c_obj.cmd_wraddr += len; len = 0; } } else if (buf[0] == I2C_CMD_CALCHASH && len == 4) { uint32_t hashlen = get_le32(buf + 1); static CRYAL_SHA256_CTX ctx; sha256_init(&ctx); sha256_update(&ctx, (const void*)i2c_obj.cmd_rdaddr, hashlen); i2c_obj.cmd_rdaddr += hashlen; sha256_final(&ctx, buf); len = 32; } else if (buf[0] == I2C_CMD_MARKVALID && len == 0) { uint32_t buf; buf = *(volatile uint32_t*)APPLICATION_ADDR; if ((buf & APP_VALIDITY_BITS) != APP_VALIDITY_BITS) { len = -1; } else { buf &= ~APP_VALIDITY_BITS; int ret = do_write(APPLICATION_ADDR, (void*)&buf, 4); if (ret < 0) { len = ret; } else { buf = *(volatile uint32_t*)APPLICATION_ADDR; if ((buf & APP_VALIDITY_BITS) != 0) { len = -2; } else { len = 0; } } } } else { len = -127; } i2c_obj.cmd_arg = len; i2c_obj.cmd_send_arg = true; i2c_obj.cmd_arg_sent = false; } uint8_t i2c_slave_process_tx_byte(void) { if (i2c_obj.cmd_send_arg) { i2c_obj.cmd_arg_sent = true; return i2c_obj.cmd_arg; } else if (i2c_obj.cmd_buf_pos < sizeof(i2c_obj.cmd_buf)) { return i2c_obj.cmd_buf[i2c_obj.cmd_buf_pos++]; } else { return 0; } } #endif // defined(MBOOT_I2C_SCL) /******************************************************************************/ // DFU #define DFU_XFER_SIZE (2048) enum { DFU_DNLOAD = 1, DFU_UPLOAD = 2, DFU_GETSTATUS = 3, DFU_CLRSTATUS = 4, DFU_ABORT = 6, }; enum { DFU_STATUS_IDLE = 2, DFU_STATUS_BUSY = 4, DFU_STATUS_DNLOAD_IDLE = 5, DFU_STATUS_MANIFEST = 7, DFU_STATUS_UPLOAD_IDLE = 9, DFU_STATUS_ERROR = 0xa, }; enum { DFU_CMD_NONE = 0, DFU_CMD_EXIT = 1, DFU_CMD_UPLOAD = 7, DFU_CMD_DNLOAD = 8, }; typedef struct _dfu_state_t { int status; int cmd; uint16_t wBlockNum; uint16_t wLength; uint32_t addr; uint8_t buf[DFU_XFER_SIZE] __attribute__((aligned(4))); } dfu_state_t; static dfu_state_t dfu_state SECTION_NOZERO_BSS; static void dfu_init(void) { dfu_state.status = DFU_STATUS_IDLE; dfu_state.cmd = DFU_CMD_NONE; dfu_state.addr = 0x08000000; } static int dfu_process_dnload(void) { int ret = -1; if (dfu_state.wBlockNum == 0) { // download control commands if (dfu_state.wLength >= 1 && dfu_state.buf[0] == 0x41) { if (dfu_state.wLength == 1) { // mass erase ret = do_mass_erase(); } else if (dfu_state.wLength == 5) { // erase page uint32_t next_addr; ret = do_page_erase(get_le32(&dfu_state.buf[1]), &next_addr); } } else if (dfu_state.wLength >= 1 && dfu_state.buf[0] == 0x21) { if (dfu_state.wLength == 5) { // set address dfu_state.addr = get_le32(&dfu_state.buf[1]); ret = 0; } } } else if (dfu_state.wBlockNum > 1) { // write data to memory uint32_t addr = (dfu_state.wBlockNum - 2) * DFU_XFER_SIZE + dfu_state.addr; ret = do_write(addr, dfu_state.buf, dfu_state.wLength); } if (ret == 0) { return DFU_STATUS_DNLOAD_IDLE; } else { return DFU_STATUS_ERROR; } } static void dfu_handle_rx(int cmd, int arg, int len, const void *buf) { if (cmd == DFU_CLRSTATUS) { // clear status dfu_state.status = DFU_STATUS_IDLE; dfu_state.cmd = DFU_CMD_NONE; } else if (cmd == DFU_ABORT) { // clear status dfu_state.status = DFU_STATUS_IDLE; dfu_state.cmd = DFU_CMD_NONE; } else if (cmd == DFU_DNLOAD) { if (len == 0) { // exit DFU dfu_state.cmd = DFU_CMD_EXIT; } else { // download dfu_state.cmd = DFU_CMD_DNLOAD; dfu_state.wBlockNum = arg; dfu_state.wLength = len; memcpy(dfu_state.buf, buf, len); } } } static void dfu_process(void) { if (dfu_state.status == DFU_STATUS_MANIFEST) { do_reset(); } if (dfu_state.status == DFU_STATUS_BUSY) { if (dfu_state.cmd == DFU_CMD_DNLOAD) { dfu_state.cmd = DFU_CMD_NONE; dfu_state.status = dfu_process_dnload(); } } } static int dfu_handle_tx(int cmd, int arg, int len, uint8_t *buf, int max_len) { if (cmd == DFU_UPLOAD) { if (arg >= 2) { dfu_state.cmd = DFU_CMD_UPLOAD; uint32_t addr = (arg - 2) * max_len + dfu_state.addr; do_read(addr, len, buf); return len; } } else if (cmd == DFU_GETSTATUS && len == 6) { // execute command and get status switch (dfu_state.cmd) { case DFU_CMD_NONE: break; case DFU_CMD_EXIT: dfu_state.status = DFU_STATUS_MANIFEST; break; case DFU_CMD_UPLOAD: dfu_state.status = DFU_STATUS_UPLOAD_IDLE; break; case DFU_CMD_DNLOAD: dfu_state.status = DFU_STATUS_BUSY; break; } buf[0] = 0; buf[1] = dfu_state.cmd; // TODO is this correct? buf[2] = 0; buf[3] = 0; buf[4] = dfu_state.status; buf[5] = 0; return 6; } return -1; } /******************************************************************************/ // USB #define USB_XFER_SIZE (DFU_XFER_SIZE) #define USB_PHY_FS_ID (0) #define USB_PHY_HS_ID (1) typedef struct _pyb_usbdd_obj_t { bool started; bool tx_pending; USBD_HandleTypeDef hUSBDDevice; uint8_t bRequest; uint16_t wValue; uint16_t wLength; __ALIGN_BEGIN uint8_t rx_buf[USB_XFER_SIZE] __ALIGN_END; __ALIGN_BEGIN uint8_t tx_buf[USB_XFER_SIZE] __ALIGN_END; // RAM to hold the current descriptors, which we configure on the fly __ALIGN_BEGIN uint8_t usbd_device_desc[USB_LEN_DEV_DESC] __ALIGN_END; __ALIGN_BEGIN uint8_t usbd_str_desc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; } pyb_usbdd_obj_t; #ifndef MBOOT_USBD_LANGID_STRING #define MBOOT_USBD_LANGID_STRING (0x409) #endif #ifndef MBOOT_USBD_MANUFACTURER_STRING #define MBOOT_USBD_MANUFACTURER_STRING "MicroPython" #endif #ifndef MBOOT_USBD_PRODUCT_STRING #define MBOOT_USBD_PRODUCT_STRING "Pyboard DFU" #endif #ifndef MBOOT_USB_VID #define MBOOT_USB_VID 0x0483 #endif #ifndef MBOOT_USB_PID #define MBOOT_USB_PID 0xDF11 #endif static const uint8_t usbd_fifo_size[] = { 32, 8, 16, 8, 16, 0, 0, // FS: RX, EP0(in), 5x IN endpoints #if MICROPY_HW_USB_HS 116, 8, 64, 4, 64, 0, 0, 0, 0, 0, // HS: RX, EP0(in), 8x IN endpoints #endif }; __ALIGN_BEGIN static const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(MBOOT_USBD_LANGID_STRING), HIBYTE(MBOOT_USBD_LANGID_STRING), }; static const uint8_t dev_descr[0x12] = { 0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, LOBYTE(MBOOT_USB_VID), HIBYTE(MBOOT_USB_VID), LOBYTE(MBOOT_USB_PID), HIBYTE(MBOOT_USB_PID), 0x00, 0x22, 0x01, 0x02, 0x03, 0x01 }; // This may be modified by USBD_GetDescriptor static uint8_t cfg_descr[9 + 9 + 9] = "\x09\x02\x1b\x00\x01\x01\x00\xc0\x32" "\x09\x04\x00\x00\x00\xfe\x01\x02\x04" "\x09\x21\x0b\xff\x00\x00\x08\x1a\x01" // \x00\x08 goes with USB_XFER_SIZE ; static uint8_t *pyb_usbdd_DeviceDescriptor(USBD_HandleTypeDef *pdev, uint16_t *length) { *length = USB_LEN_DEV_DESC; return (uint8_t*)dev_descr; } static char get_hex_char(int val) { val &= 0xf; if (val <= 9) { return '0' + val; } else { return 'A' + val - 10; } } static void format_hex(char *buf, int val) { buf[0] = get_hex_char(val >> 4); buf[1] = get_hex_char(val); } static uint8_t *pyb_usbdd_StrDescriptor(USBD_HandleTypeDef *pdev, uint8_t idx, uint16_t *length) { pyb_usbdd_obj_t *self = (pyb_usbdd_obj_t*)pdev->pClassData; uint8_t *str_desc = self->usbd_str_desc; switch (idx) { case USBD_IDX_LANGID_STR: *length = sizeof(USBD_LangIDDesc); return (uint8_t*)USBD_LangIDDesc; // the data should only be read from this buf case USBD_IDX_MFC_STR: USBD_GetString((uint8_t*)MBOOT_USBD_MANUFACTURER_STRING, str_desc, length); return str_desc; case USBD_IDX_PRODUCT_STR: USBD_GetString((uint8_t*)MBOOT_USBD_PRODUCT_STRING, str_desc, length); return str_desc; case USBD_IDX_SERIAL_STR: { // This document: http://www.usb.org/developers/docs/devclass_docs/usbmassbulk_10.pdf // says that the serial number has to be at least 12 digits long and that // the last 12 digits need to be unique. It also stipulates that the valid // character set is that of upper-case hexadecimal digits. // // The onboard DFU bootloader produces a 12-digit serial number based on // the 96-bit unique ID, so for consistency we go with this algorithm. // You can see the serial number if you do: // // dfu-util -l // // See: https://my.st.com/52d187b7 for the algorithim used. uint8_t *id = (uint8_t*)MP_HAL_UNIQUE_ID_ADDRESS; char serial_buf[16]; format_hex(&serial_buf[0], id[11]); format_hex(&serial_buf[2], id[10] + id[2]); format_hex(&serial_buf[4], id[9]); format_hex(&serial_buf[6], id[8] + id[0]); format_hex(&serial_buf[8], id[7]); format_hex(&serial_buf[10], id[6]); serial_buf[12] = '\0'; USBD_GetString((uint8_t*)serial_buf, str_desc, length); return str_desc; } case USBD_IDX_CONFIG_STR: USBD_GetString((uint8_t*)FLASH_LAYOUT_STR, str_desc, length); return str_desc; default: return NULL; } } static const USBD_DescriptorsTypeDef pyb_usbdd_descriptors = { pyb_usbdd_DeviceDescriptor, pyb_usbdd_StrDescriptor, }; static uint8_t pyb_usbdd_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { pyb_usbdd_obj_t *self = (pyb_usbdd_obj_t*)pdev->pClassData; (void)self; return USBD_OK; } static uint8_t pyb_usbdd_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { pyb_usbdd_obj_t *self = (pyb_usbdd_obj_t*)pdev->pClassData; (void)self; return USBD_OK; } static uint8_t pyb_usbdd_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { pyb_usbdd_obj_t *self = (pyb_usbdd_obj_t*)pdev->pClassData; (void)self; self->bRequest = req->bRequest; self->wValue = req->wValue; self->wLength = req->wLength; if (req->bmRequest == 0x21) { // host-to-device request if (req->wLength == 0) { // no data, process command straightaway dfu_handle_rx(self->bRequest, self->wValue, 0, NULL); } else { // have data, prepare to receive it USBD_CtlPrepareRx(pdev, self->rx_buf, req->wLength); } } else if (req->bmRequest == 0xa1) { // device-to-host request int len = dfu_handle_tx(self->bRequest, self->wValue, self->wLength, self->tx_buf, USB_XFER_SIZE); if (len >= 0) { self->tx_pending = true; USBD_CtlSendData(&self->hUSBDDevice, self->tx_buf, len); } } return USBD_OK; } static uint8_t pyb_usbdd_EP0_TxSent(USBD_HandleTypeDef *pdev) { pyb_usbdd_obj_t *self = (pyb_usbdd_obj_t*)pdev->pClassData; self->tx_pending = false; #if !USE_USB_POLLING // Process now that we have sent a response dfu_process(); #endif return USBD_OK; } static uint8_t pyb_usbdd_EP0_RxReady(USBD_HandleTypeDef *pdev) { pyb_usbdd_obj_t *self = (pyb_usbdd_obj_t*)pdev->pClassData; dfu_handle_rx(self->bRequest, self->wValue, self->wLength, self->rx_buf); return USBD_OK; } static uint8_t *pyb_usbdd_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t *length) { *length = sizeof(cfg_descr); return (uint8_t*)cfg_descr; } // this is used only in high-speed mode, which we don't support static uint8_t *pyb_usbdd_GetDeviceQualifierDescriptor(USBD_HandleTypeDef *pdev, uint16_t *length) { pyb_usbdd_obj_t *self = (pyb_usbdd_obj_t*)pdev->pClassData; (void)self; /* *length = sizeof(USBD_CDC_MSC_HID_DeviceQualifierDesc); return USBD_CDC_MSC_HID_DeviceQualifierDesc; */ *length = 0; return NULL; } static const USBD_ClassTypeDef pyb_usbdd_class = { pyb_usbdd_Init, pyb_usbdd_DeInit, pyb_usbdd_Setup, pyb_usbdd_EP0_TxSent, pyb_usbdd_EP0_RxReady, NULL, // pyb_usbdd_DataIn, NULL, // pyb_usbdd_DataOut, NULL, // SOF NULL, // IsoINIncomplete NULL, // IsoOUTIncomplete pyb_usbdd_GetCfgDesc, pyb_usbdd_GetCfgDesc, pyb_usbdd_GetCfgDesc, pyb_usbdd_GetDeviceQualifierDescriptor, }; static pyb_usbdd_obj_t pyb_usbdd SECTION_NOZERO_BSS; static int pyb_usbdd_detect_port(void) { #if MBOOT_USB_AUTODETECT_PORT mp_hal_pin_config(pin_A11, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); mp_hal_pin_config(pin_A12, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); int state = mp_hal_pin_read(pin_A11) == 0 && mp_hal_pin_read(pin_A12) == 0; mp_hal_pin_config(pin_A11, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); mp_hal_pin_config(pin_A12, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); if (state) { return USB_PHY_FS_ID; } mp_hal_pin_config(pin_B14, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); state = mp_hal_pin_read(pin_B14) == 0 && mp_hal_pin_read(pin_B15) == 0; mp_hal_pin_config(pin_B14, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); if (state) { return USB_PHY_HS_ID; } #endif return MICROPY_HW_USB_MAIN_DEV; } static void pyb_usbdd_init(pyb_usbdd_obj_t *self, int phy_id) { self->started = false; self->tx_pending = false; USBD_HandleTypeDef *usbd = &self->hUSBDDevice; usbd->id = phy_id; usbd->dev_state = USBD_STATE_DEFAULT; usbd->pDesc = (USBD_DescriptorsTypeDef*)&pyb_usbdd_descriptors; usbd->pClass = &pyb_usbdd_class; usbd->pClassData = self; } static void pyb_usbdd_start(pyb_usbdd_obj_t *self) { if (!self->started) { #if defined(STM32H7) PWR->CR3 |= PWR_CR3_USB33DEN; while (!(PWR->CR3 & PWR_CR3_USB33RDY)) { } #endif USBD_LL_Init(&self->hUSBDDevice, 0, usbd_fifo_size); USBD_LL_Start(&self->hUSBDDevice); self->started = true; } } static void pyb_usbdd_stop(pyb_usbdd_obj_t *self) { if (self->started) { USBD_Stop(&self->hUSBDDevice); self->started = false; } } static int pyb_usbdd_shutdown(void) { pyb_usbdd_stop(&pyb_usbdd); return 0; } /******************************************************************************/ // main #define RESET_MODE_NUM_STATES (4) #define RESET_MODE_TIMEOUT_CYCLES (8) #ifdef LED2 #ifdef LED3 #define RESET_MODE_LED_STATES 0x8421 #else #define RESET_MODE_LED_STATES 0x7421 #endif #else #define RESET_MODE_LED_STATES 0x3210 #endif static int get_reset_mode(void) { usrbtn_init(); int reset_mode = 1; if (usrbtn_state()) { // Cycle through reset modes while USR is held // Timeout is roughly 20s, where reset_mode=1 systick_init(); led_init(); reset_mode = 0; for (int i = 0; i < (RESET_MODE_NUM_STATES * RESET_MODE_TIMEOUT_CYCLES + 1) * 32; i++) { if (i % 32 == 0) { if (++reset_mode > RESET_MODE_NUM_STATES) { reset_mode = 1; } uint8_t l = RESET_MODE_LED_STATES >> ((reset_mode - 1) * 4); led_state_all(l); } if (!usrbtn_state()) { break; } mp_hal_delay_ms(19); } // Flash the selected reset mode for (int i = 0; i < 6; i++) { led_state_all(0); mp_hal_delay_ms(50); uint8_t l = RESET_MODE_LED_STATES >> ((reset_mode - 1) * 4); led_state_all(l); mp_hal_delay_ms(50); } mp_hal_delay_ms(300); } return reset_mode; } static void do_reset(void) { led_state_all(0); mp_hal_delay_ms(50); pyb_usbdd_shutdown(); #if defined(MBOOT_I2C_SCL) i2c_slave_shutdown(MBOOT_I2Cx, I2Cx_EV_IRQn); #endif mp_hal_delay_ms(50); NVIC_SystemReset(); } uint32_t SystemCoreClock; extern PCD_HandleTypeDef pcd_fs_handle; extern PCD_HandleTypeDef pcd_hs_handle; void stm32_main(int initial_r0) { #if defined(STM32F4) #if INSTRUCTION_CACHE_ENABLE __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); #endif #if DATA_CACHE_ENABLE __HAL_FLASH_DATA_CACHE_ENABLE(); #endif #if PREFETCH_ENABLE __HAL_FLASH_PREFETCH_BUFFER_ENABLE(); #endif #elif defined(STM32F7) #if ART_ACCLERATOR_ENABLE __HAL_FLASH_ART_ENABLE(); #endif #endif NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); #if USE_CACHE && defined(STM32F7) SCB_EnableICache(); SCB_EnableDCache(); #endif #if defined(MBOOT_BOARD_EARLY_INIT) MBOOT_BOARD_EARLY_INIT(); #endif #ifdef MBOOT_BOOTPIN_PIN mp_hal_pin_config(MBOOT_BOOTPIN_PIN, MP_HAL_PIN_MODE_INPUT, MBOOT_BOOTPIN_PULL, 0); if (mp_hal_pin_read(MBOOT_BOOTPIN_PIN) == MBOOT_BOOTPIN_ACTIVE) { goto enter_bootloader; } #endif if ((initial_r0 & 0xffffff00) == 0x70ad0000) { goto enter_bootloader; } // MCU starts up with HSI SystemCoreClock = HSI_VALUE; int reset_mode = get_reset_mode(); uint32_t msp = *(volatile uint32_t*)APPLICATION_ADDR; if (reset_mode != 4 && (msp & APP_VALIDITY_BITS) == 0) { // not DFU mode so jump to application, passing through reset_mode // undo our DFU settings // TODO probably should disable all IRQ sources first #if USE_CACHE && defined(STM32F7) SCB_DisableICache(); SCB_DisableDCache(); #endif __set_MSP(msp); ((void (*)(uint32_t)) *((volatile uint32_t*)(APPLICATION_ADDR + 4)))(reset_mode); } enter_bootloader: // Init subsystems (get_reset_mode() may call these, calling them again is ok) led_init(); // set the system clock to be HSE SystemClock_Config(); #if USE_USB_POLLING // irqs with a priority value greater or equal to "pri" will be disabled // "pri" should be between 1 and 15 inclusive uint32_t pri = 2; pri <<= (8 - __NVIC_PRIO_BITS); __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory"); #endif #if defined(MBOOT_SPIFLASH_ADDR) MBOOT_SPIFLASH_SPIFLASH->config = MBOOT_SPIFLASH_CONFIG; mp_spiflash_init(MBOOT_SPIFLASH_SPIFLASH); #endif #if defined(MBOOT_SPIFLASH2_ADDR) MBOOT_SPIFLASH2_SPIFLASH->config = MBOOT_SPIFLASH2_CONFIG; mp_spiflash_init(MBOOT_SPIFLASH2_SPIFLASH); #endif #if MBOOT_FSLOAD if ((initial_r0 & 0xffffff80) == 0x70ad0080) { // Application passed through elements, validate then process them const uint8_t *elem_end = elem_search(ELEM_DATA_START, ELEM_TYPE_END); if (elem_end != NULL && elem_end[-1] == 0) { fsload_process(); } // Always reset because the application is expecting to resume led_state_all(0); NVIC_SystemReset(); } #endif dfu_init(); pyb_usbdd_init(&pyb_usbdd, pyb_usbdd_detect_port()); pyb_usbdd_start(&pyb_usbdd); #if defined(MBOOT_I2C_SCL) initial_r0 &= 0x7f; if (initial_r0 == 0) { initial_r0 = 0x23; // Default I2C address } i2c_init(initial_r0); #endif led_state_all(0); #if USE_USB_POLLING uint32_t ss = systick_ms; int ss2 = -1; #endif #if MBOOT_USB_RESET_ON_DISCONNECT bool has_connected = false; #endif for (;;) { #if USE_USB_POLLING #if MBOOT_USB_AUTODETECT_PORT || MICROPY_HW_USB_MAIN_DEV == USB_PHY_FS_ID if (USB_OTG_FS->GINTSTS & USB_OTG_FS->GINTMSK) { HAL_PCD_IRQHandler(&pcd_fs_handle); } #endif #if MBOOT_USB_AUTODETECT_PORT || MICROPY_HW_USB_MAIN_DEV == USB_PHY_HS_ID if (USB_OTG_HS->GINTSTS & USB_OTG_HS->GINTMSK) { HAL_PCD_IRQHandler(&pcd_hs_handle); } #endif if (!pyb_usbdd.tx_pending) { dfu_process(); } #endif #if USE_USB_POLLING //__WFI(); // slows it down way too much; might work with 10x faster systick if (systick_ms - ss > 50) { ss += 50; ss2 = (ss2 + 1) % 20; switch (ss2) { case 0: led_state(LED0, 1); break; case 1: led_state(LED0, 0); break; } } #else led_state(LED0, 1); mp_hal_delay_ms(50); led_state(LED0, 0); mp_hal_delay_ms(950); #endif #if MBOOT_USB_RESET_ON_DISCONNECT if (pyb_usbdd.hUSBDDevice.dev_state == USBD_STATE_CONFIGURED) { has_connected = true; } if (has_connected && pyb_usbdd.hUSBDDevice.dev_state == USBD_STATE_SUSPENDED) { do_reset(); } #endif } } void NMI_Handler(void) { } void MemManage_Handler(void) { while (1) { __fatal_error("MemManage"); } } void BusFault_Handler(void) { while (1) { __fatal_error("BusFault"); } } void UsageFault_Handler(void) { while (1) { __fatal_error("UsageFault"); } } void SVC_Handler(void) { } void DebugMon_Handler(void) { } void PendSV_Handler(void) { } void SysTick_Handler(void) { systick_ms += 1; // Read the systick control regster. This has the side effect of clearing // the COUNTFLAG bit, which makes the logic in mp_hal_ticks_us // work properly. SysTick->CTRL; } #if defined(MBOOT_I2C_SCL) void I2Cx_EV_IRQHandler(void) { i2c_slave_ev_irq_handler(MBOOT_I2Cx); } #endif #if !USE_USB_POLLING #if MBOOT_USB_AUTODETECT_PORT || MICROPY_HW_USB_MAIN_DEV == USB_PHY_FS_ID void OTG_FS_IRQHandler(void) { HAL_PCD_IRQHandler(&pcd_fs_handle); } #endif #if MBOOT_USB_AUTODETECT_PORT || MICROPY_HW_USB_MAIN_DEV == USB_PHY_HS_ID void OTG_HS_IRQHandler(void) { HAL_PCD_IRQHandler(&pcd_hs_handle); } #endif #endif micropython-1.12/ports/stm32/mboot/mboot.h000066400000000000000000000041211357706137100205500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include // Use this to tag global static data in RAM that doesn't need to be zeroed on startup #define SECTION_NOZERO_BSS __attribute__((section(".nozero_bss"))) #define ELEM_DATA_SIZE (1024) #define ELEM_DATA_START (&_estack[0]) #define ELEM_DATA_MAX (&_estack[ELEM_DATA_SIZE]) enum { ELEM_TYPE_END = 1, ELEM_TYPE_MOUNT, ELEM_TYPE_FSLOAD, }; enum { ELEM_MOUNT_FAT = 1, }; typedef struct _fsload_bdev_t { uint32_t base_addr; uint32_t byte_len; } fsload_bdev_t; extern uint8_t _estack[ELEM_DATA_SIZE]; uint32_t get_le32(const uint8_t *b); void led_state_all(unsigned int mask); int do_page_erase(uint32_t addr, uint32_t *next_addr); void do_read(uint32_t addr, int len, uint8_t *buf); int do_write(uint32_t addr, const uint8_t *src8, size_t len); const uint8_t *elem_search(const uint8_t *elem, uint8_t elem_id); int fsload_process(void); micropython-1.12/ports/stm32/mboot/mboot.py000066400000000000000000000133061357706137100207560ustar00rootroot00000000000000# Driver for Mboot, the MicroPython boot loader # MIT license; Copyright (c) 2018 Damien P. George import struct, time, os, hashlib I2C_CMD_ECHO = 1 I2C_CMD_GETID = 2 I2C_CMD_GETCAPS = 3 I2C_CMD_RESET = 4 I2C_CMD_CONFIG = 5 I2C_CMD_GETLAYOUT = 6 I2C_CMD_MASSERASE = 7 I2C_CMD_PAGEERASE = 8 I2C_CMD_SETRDADDR = 9 I2C_CMD_SETWRADDR = 10 I2C_CMD_READ = 11 I2C_CMD_WRITE = 12 I2C_CMD_COPY = 13 I2C_CMD_CALCHASH = 14 I2C_CMD_MARKVALID = 15 class Bootloader: def __init__(self, i2c, addr): self.i2c = i2c self.addr = addr self.buf1 = bytearray(1) try: self.i2c.writeto(addr, b'') except OSError: raise Exception('no I2C mboot device found') def wait_response(self): start = time.ticks_ms() while 1: try: self.i2c.readfrom_into(self.addr, self.buf1) n = self.buf1[0] break except OSError as er: time.sleep_us(500) if time.ticks_diff(time.ticks_ms(), start) > 5000: raise Exception('timeout') if n >= 129: raise Exception(n) if n == 0: return b'' else: return self.i2c.readfrom(self.addr, n) def wait_empty_response(self): ret = self.wait_response() if ret: raise Exception('expected empty response got %r' % ret) else: return None def echo(self, data): self.i2c.writeto(self.addr, struct.pack(' #include "genhdr/pins.h" #define mp_hal_delay_us_fast(us) mp_hal_delay_us(us) #define MP_HAL_PIN_MODE_INPUT (0) #define MP_HAL_PIN_MODE_OUTPUT (1) #define MP_HAL_PIN_MODE_ALT (2) #define MP_HAL_PIN_MODE_ANALOG (3) #define MP_HAL_PIN_MODE_OPEN_DRAIN (5) #define MP_HAL_PIN_MODE_ALT_OPEN_DRAIN (6) #define MP_HAL_PIN_PULL_NONE (GPIO_NOPULL) #define MP_HAL_PIN_PULL_UP (GPIO_PULLUP) #define MP_HAL_PIN_PULL_DOWN (GPIO_PULLDOWN) #define MP_HAL_PIN_SPEED_LOW (GPIO_SPEED_FREQ_LOW) #define MP_HAL_PIN_SPEED_MEDIUM (GPIO_SPEED_FREQ_MEDIUM) #define MP_HAL_PIN_SPEED_HIGH (GPIO_SPEED_FREQ_HIGH) #define MP_HAL_PIN_SPEED_VERY_HIGH (GPIO_SPEED_FREQ_VERY_HIGH) #define mp_hal_pin_obj_t uint32_t #define mp_hal_pin_input(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_output(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_open_drain(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_low(p) (((GPIO_TypeDef*)((p) & ~0xf))->BSRR = 0x10000 << ((p) & 0xf)) #define mp_hal_pin_high(p) (((GPIO_TypeDef*)((p) & ~0xf))->BSRR = 1 << ((p) & 0xf)) #define mp_hal_pin_od_low(p) mp_hal_pin_low(p) #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_read(p) ((((GPIO_TypeDef*)((p) & ~0xf))->IDR >> ((p) & 0xf)) & 1) #define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) void mp_hal_pin_config(uint32_t port_pin, uint32_t mode, uint32_t pull, uint32_t alt); void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed); #define pin_A0 (GPIOA_BASE | 0) #define pin_A1 (GPIOA_BASE | 1) #define pin_A2 (GPIOA_BASE | 2) #define pin_A3 (GPIOA_BASE | 3) #define pin_A4 (GPIOA_BASE | 4) #define pin_A5 (GPIOA_BASE | 5) #define pin_A6 (GPIOA_BASE | 6) #define pin_A7 (GPIOA_BASE | 7) #define pin_A8 (GPIOA_BASE | 8) #define pin_A9 (GPIOA_BASE | 9) #define pin_A10 (GPIOA_BASE | 10) #define pin_A11 (GPIOA_BASE | 11) #define pin_A12 (GPIOA_BASE | 12) #define pin_A13 (GPIOA_BASE | 13) #define pin_A14 (GPIOA_BASE | 14) #define pin_A15 (GPIOA_BASE | 15) #define pin_B0 (GPIOB_BASE | 0) #define pin_B1 (GPIOB_BASE | 1) #define pin_B2 (GPIOB_BASE | 2) #define pin_B3 (GPIOB_BASE | 3) #define pin_B4 (GPIOB_BASE | 4) #define pin_B5 (GPIOB_BASE | 5) #define pin_B6 (GPIOB_BASE | 6) #define pin_B7 (GPIOB_BASE | 7) #define pin_B8 (GPIOB_BASE | 8) #define pin_B9 (GPIOB_BASE | 9) #define pin_B10 (GPIOB_BASE | 10) #define pin_B11 (GPIOB_BASE | 11) #define pin_B12 (GPIOB_BASE | 12) #define pin_B13 (GPIOB_BASE | 13) #define pin_B14 (GPIOB_BASE | 14) #define pin_B15 (GPIOB_BASE | 15) #define pin_C0 (GPIOC_BASE | 0) #define pin_C1 (GPIOC_BASE | 1) #define pin_C2 (GPIOC_BASE | 2) #define pin_C3 (GPIOC_BASE | 3) #define pin_C4 (GPIOC_BASE | 4) #define pin_C5 (GPIOC_BASE | 5) #define pin_C6 (GPIOC_BASE | 6) #define pin_C7 (GPIOC_BASE | 7) #define pin_C8 (GPIOC_BASE | 8) #define pin_C9 (GPIOC_BASE | 9) #define pin_C10 (GPIOC_BASE | 10) #define pin_C11 (GPIOC_BASE | 11) #define pin_C12 (GPIOC_BASE | 12) #define pin_C13 (GPIOC_BASE | 13) #define pin_C14 (GPIOC_BASE | 14) #define pin_C15 (GPIOC_BASE | 15) #define pin_D0 (GPIOD_BASE | 0) #define pin_D1 (GPIOD_BASE | 1) #define pin_D2 (GPIOD_BASE | 2) #define pin_D3 (GPIOD_BASE | 3) #define pin_D4 (GPIOD_BASE | 4) #define pin_D5 (GPIOD_BASE | 5) #define pin_D6 (GPIOD_BASE | 6) #define pin_D7 (GPIOD_BASE | 7) #define pin_D8 (GPIOD_BASE | 8) #define pin_D9 (GPIOD_BASE | 9) #define pin_D10 (GPIOD_BASE | 10) #define pin_D11 (GPIOD_BASE | 11) #define pin_D12 (GPIOD_BASE | 12) #define pin_D13 (GPIOD_BASE | 13) #define pin_D14 (GPIOD_BASE | 14) #define pin_D15 (GPIOD_BASE | 15) #define pin_E0 (GPIOE_BASE | 0) #define pin_E1 (GPIOE_BASE | 1) #define pin_E2 (GPIOE_BASE | 2) #define pin_E3 (GPIOE_BASE | 3) #define pin_E4 (GPIOE_BASE | 4) #define pin_E5 (GPIOE_BASE | 5) #define pin_E6 (GPIOE_BASE | 6) #define pin_E7 (GPIOE_BASE | 7) #define pin_E8 (GPIOE_BASE | 8) #define pin_E9 (GPIOE_BASE | 9) #define pin_E10 (GPIOE_BASE | 10) #define pin_E11 (GPIOE_BASE | 11) #define pin_E12 (GPIOE_BASE | 12) #define pin_E13 (GPIOE_BASE | 13) #define pin_E14 (GPIOE_BASE | 14) #define pin_E15 (GPIOE_BASE | 15) #define pin_F0 (GPIOF_BASE | 0) #define pin_F1 (GPIOF_BASE | 1) #define pin_F2 (GPIOF_BASE | 2) #define pin_F3 (GPIOF_BASE | 3) #define pin_F4 (GPIOF_BASE | 4) #define pin_F5 (GPIOF_BASE | 5) #define pin_F6 (GPIOF_BASE | 6) #define pin_F7 (GPIOF_BASE | 7) #define pin_F8 (GPIOF_BASE | 8) #define pin_F9 (GPIOF_BASE | 9) #define pin_F10 (GPIOF_BASE | 10) #define pin_F11 (GPIOF_BASE | 11) #define pin_F12 (GPIOF_BASE | 12) #define pin_F13 (GPIOF_BASE | 13) #define pin_F14 (GPIOF_BASE | 14) #define pin_F15 (GPIOF_BASE | 15) #define pin_G0 (GPIOG_BASE | 0) #define pin_G1 (GPIOG_BASE | 1) #define pin_G2 (GPIOG_BASE | 2) #define pin_G3 (GPIOG_BASE | 3) #define pin_G4 (GPIOG_BASE | 4) #define pin_G5 (GPIOG_BASE | 5) #define pin_G6 (GPIOG_BASE | 6) #define pin_G7 (GPIOG_BASE | 7) #define pin_G8 (GPIOG_BASE | 8) #define pin_G9 (GPIOG_BASE | 9) #define pin_G10 (GPIOG_BASE | 10) #define pin_G11 (GPIOG_BASE | 11) #define pin_G12 (GPIOG_BASE | 12) #define pin_G13 (GPIOG_BASE | 13) #define pin_G14 (GPIOG_BASE | 14) #define pin_G15 (GPIOG_BASE | 15) #define pin_H0 (GPIOH_BASE | 0) #define pin_H1 (GPIOH_BASE | 1) #define pin_H2 (GPIOH_BASE | 2) #define pin_H3 (GPIOH_BASE | 3) #define pin_H4 (GPIOH_BASE | 4) #define pin_H5 (GPIOH_BASE | 5) #define pin_H6 (GPIOH_BASE | 6) #define pin_H7 (GPIOH_BASE | 7) #define pin_H8 (GPIOH_BASE | 8) #define pin_H9 (GPIOH_BASE | 9) #define pin_H10 (GPIOH_BASE | 10) #define pin_H11 (GPIOH_BASE | 11) #define pin_H12 (GPIOH_BASE | 12) #define pin_H13 (GPIOH_BASE | 13) #define pin_H14 (GPIOH_BASE | 14) #define pin_H15 (GPIOH_BASE | 15) #define pin_I0 (GPIOI_BASE | 0) #define pin_I1 (GPIOI_BASE | 1) #define pin_I2 (GPIOI_BASE | 2) #define pin_I3 (GPIOI_BASE | 3) #define pin_I4 (GPIOI_BASE | 4) #define pin_I5 (GPIOI_BASE | 5) #define pin_I6 (GPIOI_BASE | 6) #define pin_I7 (GPIOI_BASE | 7) #define pin_I8 (GPIOI_BASE | 8) #define pin_I9 (GPIOI_BASE | 9) #define pin_I10 (GPIOI_BASE | 10) #define pin_I11 (GPIOI_BASE | 11) #define pin_I12 (GPIOI_BASE | 12) #define pin_I13 (GPIOI_BASE | 13) #define pin_I14 (GPIOI_BASE | 14) #define pin_I15 (GPIOI_BASE | 15) #define pin_J0 (GPIOJ_BASE | 0) #define pin_J1 (GPIOJ_BASE | 1) #define pin_J2 (GPIOJ_BASE | 2) #define pin_J3 (GPIOJ_BASE | 3) #define pin_J4 (GPIOJ_BASE | 4) #define pin_J5 (GPIOJ_BASE | 5) #define pin_J6 (GPIOJ_BASE | 6) #define pin_J7 (GPIOJ_BASE | 7) #define pin_J8 (GPIOJ_BASE | 8) #define pin_J9 (GPIOJ_BASE | 9) #define pin_J10 (GPIOJ_BASE | 10) #define pin_J11 (GPIOJ_BASE | 11) #define pin_J12 (GPIOJ_BASE | 12) #define pin_J13 (GPIOJ_BASE | 13) #define pin_J14 (GPIOJ_BASE | 14) #define pin_J15 (GPIOJ_BASE | 15) micropython-1.12/ports/stm32/mboot/stm32_generic.ld000066400000000000000000000033751357706137100222560ustar00rootroot00000000000000/* GNU linker script for generic STM32xxx MCU */ /* Specify the memory areas */ MEMORY { FLASH_BL (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sector 0 (can be 32K) */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; /* Define tho top end of the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); ENTRY(Reset_Handler) SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH_BL /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text*) *(.rodata*) . = ALIGN(4); _etext = .; } >FLASH_BL /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* Initialized data section */ .data : { . = ALIGN(4); _sdata = .; *(.data*) . = ALIGN(4); _edata = .; } >RAM AT> FLASH_BL /* Zeroed-out data section */ .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM /* Uninitialized data section */ .nozero_bss (NOLOAD) : { . = ALIGN(4); *(.nozero_bss*) . = ALIGN(4); } >RAM /* this just checks there is enough RAM for the stack */ .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM .ARM.attributes 0 : { *(.ARM.attributes) } } micropython-1.12/ports/stm32/modmachine.c000066400000000000000000000366551357706137100204300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "modmachine.h" #include "py/gc.h" #include "py/runtime.h" #include "py/objstr.h" #include "py/mperrno.h" #include "py/mphal.h" #include "extmod/machine_mem.h" #include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "gccollect.h" #include "irq.h" #include "powerctrl.h" #include "pybthread.h" #include "rng.h" #include "storage.h" #include "pin.h" #include "timer.h" #include "usb.h" #include "rtc.h" #include "i2c.h" #include "spi.h" #include "uart.h" #include "wdt.h" #if defined(STM32L0) // L0 does not have a BOR, so use POR instead #define RCC_CSR_BORRSTF RCC_CSR_PORRSTF #endif #if defined(STM32L4) || defined(STM32WB) // L4 does not have a POR, so use BOR instead #define RCC_CSR_PORRSTF RCC_CSR_BORRSTF #endif #if defined(STM32H7) #define RCC_SR RSR #define RCC_SR_IWDGRSTF RCC_RSR_IWDG1RSTF #define RCC_SR_WWDGRSTF RCC_RSR_WWDG1RSTF #define RCC_SR_PORRSTF RCC_RSR_PORRSTF #define RCC_SR_BORRSTF RCC_RSR_BORRSTF #define RCC_SR_PINRSTF RCC_RSR_PINRSTF #define RCC_SR_RMVF RCC_RSR_RMVF #else #define RCC_SR CSR #define RCC_SR_IWDGRSTF RCC_CSR_IWDGRSTF #define RCC_SR_WWDGRSTF RCC_CSR_WWDGRSTF #define RCC_SR_PORRSTF RCC_CSR_PORRSTF #define RCC_SR_BORRSTF RCC_CSR_BORRSTF #define RCC_SR_PINRSTF RCC_CSR_PINRSTF #define RCC_SR_RMVF RCC_CSR_RMVF #endif #define PYB_RESET_SOFT (0) #define PYB_RESET_POWER_ON (1) #define PYB_RESET_HARD (2) #define PYB_RESET_WDT (3) #define PYB_RESET_DEEPSLEEP (4) STATIC uint32_t reset_cause; void machine_init(void) { #if defined(STM32F4) if (PWR->CSR & PWR_CSR_SBF) { // came out of standby reset_cause = PYB_RESET_DEEPSLEEP; PWR->CR |= PWR_CR_CSBF; } else #elif defined(STM32F7) if (PWR->CSR1 & PWR_CSR1_SBF) { // came out of standby reset_cause = PYB_RESET_DEEPSLEEP; PWR->CR1 |= PWR_CR1_CSBF; } else #elif defined(STM32H7) if (PWR->CPUCR & PWR_CPUCR_SBF || PWR->CPUCR & PWR_CPUCR_STOPF) { // came out of standby or stop mode reset_cause = PYB_RESET_DEEPSLEEP; PWR->CPUCR |= PWR_CPUCR_CSSF; } else #elif defined(STM32L4) if (PWR->SR1 & PWR_SR1_SBF) { // came out of standby reset_cause = PYB_RESET_DEEPSLEEP; PWR->SCR |= PWR_SCR_CSBF; } else #endif { // get reset cause from RCC flags uint32_t state = RCC->RCC_SR; if (state & RCC_SR_IWDGRSTF || state & RCC_SR_WWDGRSTF) { reset_cause = PYB_RESET_WDT; } else if (state & RCC_SR_PORRSTF #if !defined(STM32F0) || state & RCC_SR_BORRSTF #endif ) { reset_cause = PYB_RESET_POWER_ON; } else if (state & RCC_SR_PINRSTF) { reset_cause = PYB_RESET_HARD; } else { // default is soft reset reset_cause = PYB_RESET_SOFT; } } // clear RCC reset flags RCC->RCC_SR |= RCC_SR_RMVF; } void machine_deinit(void) { // we are doing a soft-reset so change the reset_cause reset_cause = PYB_RESET_SOFT; } // machine.info([dump_alloc_table]) // Print out lots of information about the board. STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) { // get and print unique id; 96 bits { byte *id = (byte*)MP_HAL_UNIQUE_ID_ADDRESS; printf("ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]); } // get and print clock speeds // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz { #if defined(STM32F0) printf("S=%u\nH=%u\nP1=%u\n", (unsigned int)HAL_RCC_GetSysClockFreq(), (unsigned int)HAL_RCC_GetHCLKFreq(), (unsigned int)HAL_RCC_GetPCLK1Freq()); #else printf("S=%u\nH=%u\nP1=%u\nP2=%u\n", (unsigned int)HAL_RCC_GetSysClockFreq(), (unsigned int)HAL_RCC_GetHCLKFreq(), (unsigned int)HAL_RCC_GetPCLK1Freq(), (unsigned int)HAL_RCC_GetPCLK2Freq()); #endif } // to print info about memory { printf("_etext=%p\n", &_etext); printf("_sidata=%p\n", &_sidata); printf("_sdata=%p\n", &_sdata); printf("_edata=%p\n", &_edata); printf("_sbss=%p\n", &_sbss); printf("_ebss=%p\n", &_ebss); printf("_sstack=%p\n", &_sstack); printf("_estack=%p\n", &_estack); printf("_ram_start=%p\n", &_ram_start); printf("_heap_start=%p\n", &_heap_start); printf("_heap_end=%p\n", &_heap_end); printf("_ram_end=%p\n", &_ram_end); } // qstr info { size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); printf("qstr:\n n_pool=%u\n n_qstr=%u\n n_str_data_bytes=%u\n n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); } // GC info { gc_info_t info; gc_info(&info); printf("GC:\n"); printf(" %u total\n", info.total); printf(" %u : %u\n", info.used, info.free); printf(" 1=%u 2=%u m=%u\n", info.num_1block, info.num_2block, info.max_block); } // free space on flash { #if MICROPY_VFS_FAT for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { if (strncmp("/flash", vfs->str, vfs->len) == 0) { // assumes that it's a FatFs filesystem fs_user_mount_t *vfs_fat = MP_OBJ_TO_PTR(vfs->obj); DWORD nclst; f_getfree(&vfs_fat->fatfs, &nclst); printf("LFS free: %u bytes\n", (uint)(nclst * vfs_fat->fatfs.csize * 512)); break; } } #endif } #if MICROPY_PY_THREAD pyb_thread_dump(); #endif if (n_args == 1) { // arg given means dump gc allocation table gc_dump_alloc_table(); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info); // Returns a string of 12 bytes (96 bits), which is the unique ID for the MCU. STATIC mp_obj_t machine_unique_id(void) { byte *id = (byte*)MP_HAL_UNIQUE_ID_ADDRESS; return mp_obj_new_bytes(id, 12); } MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id); // Resets the pyboard in a manner similar to pushing the external RESET button. STATIC mp_obj_t machine_reset(void) { powerctrl_mcu_reset(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); STATIC mp_obj_t machine_soft_reset(void) { pyexec_system_exit = PYEXEC_FORCED_EXIT; nlr_raise(mp_obj_new_exception(&mp_type_SystemExit)); } MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); // Activate the bootloader without BOOT* pins. STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { #if MICROPY_HW_ENABLE_USB pyb_usb_dev_deinit(); #endif #if MICROPY_HW_ENABLE_STORAGE storage_flush(); #endif __disable_irq(); #if MICROPY_HW_USES_BOOTLOADER if (n_args == 0 || !mp_obj_is_true(args[0])) { // By default, with no args given, we enter the custom bootloader (mboot) powerctrl_enter_bootloader(0x70ad0000, 0x08000000); } if (n_args == 1 && mp_obj_is_str_or_bytes(args[0])) { // With a string/bytes given, pass its data to the custom bootloader size_t len; const char *data = mp_obj_str_get_data(args[0], &len); void *mboot_region = (void*)*((volatile uint32_t*)0x08000000); memmove(mboot_region, data, len); powerctrl_enter_bootloader(0x70ad0080, 0x08000000); } #endif #if defined(STM32F7) || defined(STM32H7) powerctrl_enter_bootloader(0, 0x1ff00000); #else powerctrl_enter_bootloader(0, 0x00000000); #endif while (1); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader); // get or set the MCU frequencies STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // get mp_obj_t tuple[] = { mp_obj_new_int(HAL_RCC_GetSysClockFreq()), mp_obj_new_int(HAL_RCC_GetHCLKFreq()), mp_obj_new_int(HAL_RCC_GetPCLK1Freq()), #if !defined(STM32F0) mp_obj_new_int(HAL_RCC_GetPCLK2Freq()), #endif }; return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); } else { // set #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) mp_raise_NotImplementedError("machine.freq set not supported yet"); #else mp_int_t sysclk = mp_obj_get_int(args[0]); mp_int_t ahb = sysclk; mp_int_t apb1 = ahb / 4; mp_int_t apb2 = ahb / 2; if (n_args > 1) { ahb = mp_obj_get_int(args[1]); if (n_args > 2) { apb1 = mp_obj_get_int(args[2]); if (n_args > 3) { apb2 = mp_obj_get_int(args[3]); } } } int ret = powerctrl_set_sysclk(sysclk, ahb, apb1, apb2); if (ret == -MP_EINVAL) { mp_raise_ValueError("invalid freq"); } else if (ret < 0) { void NORETURN __fatal_error(const char *msg); __fatal_error("can't change freq"); } return mp_const_none; #endif } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 4, machine_freq); STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { if (n_args != 0) { mp_obj_t args2[2] = {MP_OBJ_NULL, args[0]}; pyb_rtc_wakeup(2, args2); } powerctrl_enter_stop_mode(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep); STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) { if (n_args != 0) { mp_obj_t args2[2] = {MP_OBJ_NULL, args[0]}; pyb_rtc_wakeup(2, args2); } powerctrl_enter_standby_mode(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep); STATIC mp_obj_t machine_reset_cause(void) { return MP_OBJ_NEW_SMALL_INT(reset_cause); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, #if MICROPY_HW_ENABLE_RNG { MP_ROM_QSTR(MP_QSTR_rng), MP_ROM_PTR(&pyb_rng_get_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&pyb_wfi_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, #if 0 { MP_ROM_QSTR(MP_QSTR_wake_reason), MP_ROM_PTR(&machine_wake_reason_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, #if MICROPY_PY_MACHINE_I2C { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, #endif { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&pyb_wdt_type) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, #if 0 { MP_ROM_QSTR(MP_QSTR_HeartBeat), MP_ROM_PTR(&pyb_heartbeat_type) }, { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sd_type) }, // class constants { MP_ROM_QSTR(MP_QSTR_IDLE), MP_ROM_INT(PYB_PWR_MODE_ACTIVE) }, { MP_ROM_QSTR(MP_QSTR_SLEEP), MP_ROM_INT(PYB_PWR_MODE_LPDS) }, { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(PYB_PWR_MODE_HIBERNATE) }, #endif { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(PYB_RESET_POWER_ON) }, { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(PYB_RESET_HARD) }, { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(PYB_RESET_WDT) }, { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(PYB_RESET_DEEPSLEEP) }, { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(PYB_RESET_SOFT) }, #if 0 { MP_ROM_QSTR(MP_QSTR_WLAN_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_WLAN) }, { MP_ROM_QSTR(MP_QSTR_PIN_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_GPIO) }, { MP_ROM_QSTR(MP_QSTR_RTC_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_RTC) }, #endif }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t machine_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; micropython-1.12/ports/stm32/modmachine.h000066400000000000000000000036101357706137100204160ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_MODMACHINE_H #define MICROPY_INCLUDED_STM32_MODMACHINE_H #include "py/obj.h" extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t machine_timer_type; void machine_init(void); void machine_deinit(void); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj); #endif // MICROPY_INCLUDED_STM32_MODMACHINE_H micropython-1.12/ports/stm32/modnetwork.c000066400000000000000000000155521357706137100205060ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/objlist.h" #include "py/runtime.h" #include "py/mphal.h" #include "lib/netutils/netutils.h" #include "systick.h" #include "pendsv.h" #include "modnetwork.h" #if MICROPY_PY_NETWORK #if MICROPY_PY_LWIP #include "lwip/netif.h" #include "lwip/timeouts.h" #include "lwip/dns.h" #include "lwip/dhcp.h" #include "lwip/apps/mdns.h" #include "extmod/network_cyw43.h" #include "drivers/cyw43/cyw43.h" // Poll lwIP every 128ms #define LWIP_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0) u32_t sys_now(void) { return mp_hal_ticks_ms(); } STATIC void pyb_lwip_poll(void) { #if MICROPY_PY_WIZNET5K // Poll the NIC for incoming data wiznet5k_poll(); #endif // Run the lwIP internal updates sys_check_timeouts(); #if MICROPY_BLUETOOTH_NIMBLE extern void nimble_poll(void); nimble_poll(); #endif } void mod_network_lwip_poll_wrapper(uint32_t ticks_ms) { if (LWIP_TICK(ticks_ms)) { pendsv_schedule_dispatch(PENDSV_DISPATCH_LWIP, pyb_lwip_poll); } #if MICROPY_PY_NETWORK_CYW43 if (cyw43_poll) { if (cyw43_sleep != 0) { if (--cyw43_sleep == 0) { pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); } } } #endif } #endif /// \module network - network configuration /// /// This module provides network drivers and routing configuration. void mod_network_init(void) { mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0); } void mod_network_deinit(void) { } void mod_network_register_nic(mp_obj_t nic) { for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) { // nic already registered return; } } // nic not registered so add to list mp_obj_list_append(MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)), nic); } mp_obj_t mod_network_find_nic(const uint8_t *ip) { // find a NIC that is suited to given IP address for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; // TODO check IP suitability here //mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); return nic; } mp_raise_msg(&mp_type_OSError, "no available NIC"); } STATIC mp_obj_t network_route(void) { return MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route); STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, #if defined(MICROPY_HW_ETH_MDC) { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&network_lan_type) }, #endif #if MICROPY_PY_NETWORK_CYW43 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mp_network_cyw43_type) }, #endif #if MICROPY_PY_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) }, #endif #if MICROPY_PY_CC3K { MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) }, #endif { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, // Constants #if MICROPY_PY_NETWORK_CYW43 { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(CYW43_ITF_STA)}, { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(CYW43_ITF_AP)}, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); const mp_obj_module_t mp_module_network = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_network_globals, }; /*******************************************************************************/ // Implementations of network methods that can be used by any interface #if MICROPY_PY_LWIP mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // Get IP addresses const ip_addr_t *dns = dns_getserver(0); mp_obj_t tuple[4] = { netutils_format_ipv4_addr((uint8_t*)&netif->ip_addr, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&netif->netmask, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&netif->gw, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)dns, NETUTILS_BIG), }; return mp_obj_new_tuple(4, tuple); } else if (args[0] == MP_OBJ_NEW_QSTR(MP_QSTR_dhcp)) { // Start the DHCP client if (dhcp_supplied_address(netif)) { dhcp_renew(netif); } else { dhcp_stop(netif); dhcp_start(netif); } // Wait for DHCP to get IP address uint32_t start = mp_hal_ticks_ms(); while (!dhcp_supplied_address(netif)) { if (mp_hal_ticks_ms() - start > 10000) { mp_raise_msg(&mp_type_OSError, "timeout waiting for DHCP to get IP address"); } mp_hal_delay_ms(100); } return mp_const_none; } else { // Release and stop any existing DHCP dhcp_release(netif); dhcp_stop(netif); // Set static IP addresses mp_obj_t *items; mp_obj_get_array_fixed_n(args[0], 4, &items); netutils_parse_ipv4_addr(items[0], (uint8_t*)&netif->ip_addr, NETUTILS_BIG); netutils_parse_ipv4_addr(items[1], (uint8_t*)&netif->netmask, NETUTILS_BIG); netutils_parse_ipv4_addr(items[2], (uint8_t*)&netif->gw, NETUTILS_BIG); ip_addr_t dns; netutils_parse_ipv4_addr(items[3], (uint8_t*)&dns, NETUTILS_BIG); dns_setserver(0, &dns); return mp_const_none; } } #endif #endif // MICROPY_PY_NETWORK micropython-1.12/ports/stm32/modnetwork.h000066400000000000000000000102111357706137100204760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_MODNETWORK_H #define MICROPY_INCLUDED_STM32_MODNETWORK_H #define MOD_NETWORK_IPADDR_BUF_SIZE (4) #define MOD_NETWORK_AF_INET (2) #define MOD_NETWORK_AF_INET6 (10) #define MOD_NETWORK_SOCK_STREAM (1) #define MOD_NETWORK_SOCK_DGRAM (2) #define MOD_NETWORK_SOCK_RAW (3) #if MICROPY_PY_LWIP struct netif; extern const mp_obj_type_t network_lan_type; extern const mp_obj_type_t mod_network_nic_type_wiznet5k; void mod_network_lwip_poll_wrapper(uint32_t ticks_ms); mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args); void wiznet5k_poll(void); #else struct _mod_network_socket_obj_t; typedef struct _mod_network_nic_type_t { mp_obj_type_t base; // API for non-socket operations int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out); // API for socket operations; return -1 on error int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno); void (*close)(struct _mod_network_socket_obj_t *socket); int (*bind)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); int (*listen)(struct _mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno); int (*accept)(struct _mod_network_socket_obj_t *socket, struct _mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno); int (*connect)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); mp_uint_t (*send)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno); mp_uint_t (*recv)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno); mp_uint_t (*sendto)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno); mp_uint_t (*recvfrom)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno); int (*setsockopt)(struct _mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); } mod_network_nic_type_t; typedef struct _mod_network_socket_obj_t { mp_obj_base_t base; mp_obj_t nic; mod_network_nic_type_t *nic_type; union { struct { uint8_t domain; uint8_t type; int8_t fileno; } u_param; mp_uint_t u_state; }; } mod_network_socket_obj_t; extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; extern const mod_network_nic_type_t mod_network_nic_type_cc3k; #endif void mod_network_init(void); void mod_network_deinit(void); void mod_network_register_nic(mp_obj_t nic); mp_obj_t mod_network_find_nic(const uint8_t *ip); #endif // MICROPY_INCLUDED_STM32_MODNETWORK_H micropython-1.12/ports/stm32/modnwcc3k.c000066400000000000000000000465421357706137100202100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include // CC3000 defines its own ENOBUFS (different to standard one!) #undef ENOBUFS #include "py/objtuple.h" #include "py/objlist.h" #include "py/stream.h" #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #include "lib/netutils/netutils.h" #include "modnetwork.h" #include "pin.h" #include "spi.h" #include "hci.h" #include "socket.h" #include "inet_ntop.h" #include "inet_pton.h" #include "ccspi.h" #include "wlan.h" #include "nvmem.h" #include "netapp.h" #include "patch_prog.h" #define MAX_ADDRSTRLEN (128) #define MAX_RX_PACKET (CC3000_RX_BUFFER_SIZE-CC3000_MINIMAL_RX_SIZE-1) #define MAX_TX_PACKET (CC3000_TX_BUFFER_SIZE-CC3000_MINIMAL_TX_SIZE-1) #define MAKE_SOCKADDR(addr, ip, port) \ sockaddr addr; \ addr.sa_family = AF_INET; \ addr.sa_data[0] = port >> 8; \ addr.sa_data[1] = port; \ addr.sa_data[2] = ip[0]; \ addr.sa_data[3] = ip[1]; \ addr.sa_data[4] = ip[2]; \ addr.sa_data[5] = ip[3]; #define UNPACK_SOCKADDR(addr, ip, port) \ port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \ ip[0] = addr.sa_data[2]; \ ip[1] = addr.sa_data[3]; \ ip[2] = addr.sa_data[4]; \ ip[3] = addr.sa_data[5]; STATIC int cc3k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); int CC3000_EXPORT(errno); // for cc3000 driver STATIC volatile uint32_t fd_closed_state = 0; STATIC volatile bool wlan_connected = false; STATIC volatile bool ip_obtained = false; STATIC int cc3k_get_fd_closed_state(int fd) { return fd_closed_state & (1 << fd); } STATIC void cc3k_set_fd_closed_state(int fd) { fd_closed_state |= 1 << fd; } STATIC void cc3k_reset_fd_closed_state(int fd) { fd_closed_state &= ~(1 << fd); } STATIC void cc3k_callback(long event_type, char *data, unsigned char length) { switch (event_type) { case HCI_EVNT_WLAN_UNSOL_CONNECT: wlan_connected = true; break; case HCI_EVNT_WLAN_UNSOL_DISCONNECT: // link down wlan_connected = false; ip_obtained = false; break; case HCI_EVNT_WLAN_UNSOL_DHCP: ip_obtained = true; break; case HCI_EVNT_BSD_TCP_CLOSE_WAIT: // mark socket for closure cc3k_set_fd_closed_state(data[0]); break; } } STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { uint32_t ip; // CC3000 gethostbyname is unreliable and usually returns -95 on first call for (int retry = 5; CC3000_EXPORT(gethostbyname)((char*)name, len, &ip) < 0; retry--) { if (retry == 0 || CC3000_EXPORT(errno) != -95) { return CC3000_EXPORT(errno); } mp_hal_delay_ms(50); } if (ip == 0) { // unknown host return -2; } out_ip[0] = ip >> 24; out_ip[1] = ip >> 16; out_ip[2] = ip >> 8; out_ip[3] = ip; return 0; } STATIC int cc3k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { if (socket->u_param.domain != MOD_NETWORK_AF_INET) { *_errno = MP_EAFNOSUPPORT; return -1; } mp_uint_t type; switch (socket->u_param.type) { case MOD_NETWORK_SOCK_STREAM: type = SOCK_STREAM; break; case MOD_NETWORK_SOCK_DGRAM: type = SOCK_DGRAM; break; case MOD_NETWORK_SOCK_RAW: type = SOCK_RAW; break; default: *_errno = MP_EINVAL; return -1; } // open socket int fd = CC3000_EXPORT(socket)(AF_INET, type, 0); if (fd < 0) { *_errno = CC3000_EXPORT(errno); return -1; } // clear socket state cc3k_reset_fd_closed_state(fd); // store state of this socket socket->u_state = fd; // make accept blocking by default int optval = SOCK_OFF; socklen_t optlen = sizeof(optval); CC3000_EXPORT(setsockopt)(socket->u_state, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, &optval, optlen); return 0; } STATIC void cc3k_socket_close(mod_network_socket_obj_t *socket) { CC3000_EXPORT(closesocket)(socket->u_state); } STATIC int cc3k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) int ret = CC3000_EXPORT(bind)(socket->u_state, &addr, sizeof(addr)); if (ret != 0) { *_errno = ret; return -1; } return 0; } STATIC int cc3k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) { int ret = CC3000_EXPORT(listen)(socket->u_state, backlog); if (ret != 0) { *_errno = ret; return -1; } return 0; } STATIC int cc3k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) { // accept incoming connection int fd; sockaddr addr; socklen_t addr_len = sizeof(addr); if ((fd = CC3000_EXPORT(accept)(socket->u_state, &addr, &addr_len)) < 0) { if (fd == SOC_IN_PROGRESS) { *_errno = MP_EAGAIN; } else { *_errno = -fd; } return -1; } // clear socket state cc3k_reset_fd_closed_state(fd); // store state in new socket object socket2->u_state = fd; // return ip and port // it seems CC3000 returns little endian for accept?? //UNPACK_SOCKADDR(addr, ip, *port); *port = (addr.sa_data[1] << 8) | addr.sa_data[0]; ip[3] = addr.sa_data[2]; ip[2] = addr.sa_data[3]; ip[1] = addr.sa_data[4]; ip[0] = addr.sa_data[5]; return 0; } STATIC int cc3k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) int ret = CC3000_EXPORT(connect)(socket->u_state, &addr, sizeof(addr)); if (ret != 0) { *_errno = CC3000_EXPORT(errno); return -1; } return 0; } STATIC mp_uint_t cc3k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { if (cc3k_get_fd_closed_state(socket->u_state)) { CC3000_EXPORT(closesocket)(socket->u_state); *_errno = MP_EPIPE; return -1; } // CC3K does not handle fragmentation, and will overflow, // split the packet into smaller ones and send them out. mp_int_t bytes = 0; while (bytes < len) { int n = MIN((len - bytes), MAX_TX_PACKET); n = CC3000_EXPORT(send)(socket->u_state, (uint8_t*)buf + bytes, n, 0); if (n <= 0) { *_errno = CC3000_EXPORT(errno); return -1; } bytes += n; } return bytes; } STATIC mp_uint_t cc3k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { // check the socket is open if (cc3k_get_fd_closed_state(socket->u_state)) { // socket is closed, but CC3000 may have some data remaining in buffer, so check fd_set rfds; FD_ZERO(&rfds); FD_SET(socket->u_state, &rfds); cc3000_timeval tv; tv.tv_sec = 0; tv.tv_usec = 1; int nfds = CC3000_EXPORT(select)(socket->u_state + 1, &rfds, NULL, NULL, &tv); if (nfds == -1 || !FD_ISSET(socket->u_state, &rfds)) { // no data waiting, so close socket and return 0 data CC3000_EXPORT(closesocket)(socket->u_state); return 0; } } // cap length at MAX_RX_PACKET len = MIN(len, MAX_RX_PACKET); // do the recv int ret = CC3000_EXPORT(recv)(socket->u_state, buf, len, 0); if (ret < 0) { *_errno = CC3000_EXPORT(errno); return -1; } return ret; } STATIC mp_uint_t cc3k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) int ret = CC3000_EXPORT(sendto)(socket->u_state, (byte*)buf, len, 0, (sockaddr*)&addr, sizeof(addr)); if (ret < 0) { *_errno = CC3000_EXPORT(errno); return -1; } return ret; } STATIC mp_uint_t cc3k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { sockaddr addr; socklen_t addr_len = sizeof(addr); mp_int_t ret = CC3000_EXPORT(recvfrom)(socket->u_state, buf, len, 0, &addr, &addr_len); if (ret < 0) { *_errno = CC3000_EXPORT(errno); return -1; } UNPACK_SOCKADDR(addr, ip, *port); return ret; } STATIC int cc3k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { int ret = CC3000_EXPORT(setsockopt)(socket->u_state, level, opt, optval, optlen); if (ret < 0) { *_errno = CC3000_EXPORT(errno); return -1; } return 0; } STATIC int cc3k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) { int ret; if (timeout_ms == 0 || timeout_ms == -1) { int optval; socklen_t optlen = sizeof(optval); if (timeout_ms == 0) { // set non-blocking mode optval = SOCK_ON; } else { // set blocking mode optval = SOCK_OFF; } ret = CC3000_EXPORT(setsockopt)(socket->u_state, SOL_SOCKET, SOCKOPT_RECV_NONBLOCK, &optval, optlen); if (ret == 0) { ret = CC3000_EXPORT(setsockopt)(socket->u_state, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, &optval, optlen); } } else { // set timeout socklen_t optlen = sizeof(timeout_ms); ret = CC3000_EXPORT(setsockopt)(socket->u_state, SOL_SOCKET, SOCKOPT_RECV_TIMEOUT, &timeout_ms, optlen); } if (ret != 0) { *_errno = CC3000_EXPORT(errno); return -1; } return 0; } STATIC int cc3k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) { mp_uint_t ret; if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; int fd = socket->u_state; // init fds fd_set rfds, wfds, xfds; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&xfds); // set fds if needed if (flags & MP_STREAM_POLL_RD) { FD_SET(fd, &rfds); // A socked that just closed is available for reading. A call to // recv() returns 0 which is consistent with BSD. if (cc3k_get_fd_closed_state(fd)) { ret |= MP_STREAM_POLL_RD; } } if (flags & MP_STREAM_POLL_WR) { FD_SET(fd, &wfds); } if (flags & MP_STREAM_POLL_HUP) { FD_SET(fd, &xfds); } // call cc3000 select with minimum timeout cc3000_timeval tv; tv.tv_sec = 0; tv.tv_usec = 1; int nfds = CC3000_EXPORT(select)(fd + 1, &rfds, &wfds, &xfds, &tv); // check for error if (nfds == -1) { *_errno = CC3000_EXPORT(errno); return -1; } // check return of select if (FD_ISSET(fd, &rfds)) { ret |= MP_STREAM_POLL_RD; } if (FD_ISSET(fd, &wfds)) { ret |= MP_STREAM_POLL_WR; } if (FD_ISSET(fd, &xfds)) { ret |= MP_STREAM_POLL_HUP; } } else { *_errno = MP_EINVAL; ret = -1; } return ret; } /******************************************************************************/ // MicroPython bindings; CC3K class typedef struct _cc3k_obj_t { mp_obj_base_t base; } cc3k_obj_t; STATIC const cc3k_obj_t cc3k_obj = {{(mp_obj_type_t*)&mod_network_nic_type_cc3k}}; // \classmethod \constructor(spi, pin_cs, pin_en, pin_irq) // Initialise the CC3000 using the given SPI bus and pins and return a CC3K object. // // Note: pins were originally hard-coded to: // PYBv1.0: init(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) // [SPI on Y position; Y6=B13=SCK, Y7=B14=MISO, Y8=B15=MOSI] // // STM32F4DISC: init(pyb.SPI(2), pyb.Pin.cpu.A15, pyb.Pin.cpu.B10, pyb.Pin.cpu.B11) STATIC mp_obj_t cc3k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 4, 4, false); // set the pins to use SpiInit( spi_from_mp_obj(args[0])->spi, pin_find(args[1]), pin_find(args[2]), pin_find(args[3]) ); // initialize and start the module wlan_init(cc3k_callback, NULL, NULL, NULL, ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin); if (wlan_start(0) != 0) { mp_raise_msg(&mp_type_OSError, "failed to init CC3000 module"); } // set connection policy. this should be called explicitly by the user // wlan_ioctl_set_connection_policy(0, 0, 0); // Mask out all non-required events from the CC3000 wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE| HCI_EVNT_WLAN_UNSOL_INIT| HCI_EVNT_WLAN_ASYNC_PING_REPORT| HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE); // register with network module mod_network_register_nic((mp_obj_t)&cc3k_obj); return (mp_obj_t)&cc3k_obj; } // method connect(ssid, key=None, *, security=WPA2, bssid=None) STATIC mp_obj_t cc3k_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = WLAN_SEC_WPA2} }, { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get ssid size_t ssid_len; const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len); // get key and sec size_t key_len = 0; const char *key = NULL; mp_uint_t sec = WLAN_SEC_UNSEC; if (args[1].u_obj != mp_const_none) { key = mp_obj_str_get_data(args[1].u_obj, &key_len); sec = args[2].u_int; } // get bssid const char *bssid = NULL; if (args[3].u_obj != mp_const_none) { bssid = mp_obj_str_get_str(args[3].u_obj); } // connect to AP if (wlan_connect(sec, (char*)ssid, ssid_len, (uint8_t*)bssid, (uint8_t*)key, key_len) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "could not connect to ssid=%s, sec=%d, key=%s\n", ssid, sec, key)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_connect_obj, 1, cc3k_connect); STATIC mp_obj_t cc3k_disconnect(mp_obj_t self_in) { // should we check return value? wlan_disconnect(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_disconnect_obj, cc3k_disconnect); STATIC mp_obj_t cc3k_isconnected(mp_obj_t self_in) { return mp_obj_new_bool(wlan_connected && ip_obtained); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_isconnected_obj, cc3k_isconnected); STATIC mp_obj_t cc3k_ifconfig(mp_obj_t self_in) { tNetappIpconfigRetArgs ipconfig; netapp_ipconfig(&ipconfig); // render MAC address VSTR_FIXED(mac_vstr, 18); const uint8_t *mac = ipconfig.uaMacAddr; vstr_printf(&mac_vstr, "%02x:%02x:%02x:%02x:%02x:%02x", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]); // create and return tuple with ifconfig info mp_obj_t tuple[7] = { netutils_format_ipv4_addr(ipconfig.aucIP, NETUTILS_LITTLE), netutils_format_ipv4_addr(ipconfig.aucSubnetMask, NETUTILS_LITTLE), netutils_format_ipv4_addr(ipconfig.aucDefaultGateway, NETUTILS_LITTLE), netutils_format_ipv4_addr(ipconfig.aucDNSServer, NETUTILS_LITTLE), netutils_format_ipv4_addr(ipconfig.aucDHCPServer, NETUTILS_LITTLE), mp_obj_new_str(mac_vstr.buf, mac_vstr.len), mp_obj_new_str((const char*)ipconfig.uaSSID, strlen((const char*)ipconfig.uaSSID)), }; return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_ifconfig_obj, cc3k_ifconfig); STATIC mp_obj_t cc3k_patch_version(mp_obj_t self_in) { uint8_t pver[2]; mp_obj_tuple_t *t_pver; nvmem_read_sp_version(pver); t_pver = mp_obj_new_tuple(2, NULL); t_pver->items[0] = mp_obj_new_int(pver[0]); t_pver->items[1] = mp_obj_new_int(pver[1]); return t_pver; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_patch_version_obj, cc3k_patch_version); STATIC mp_obj_t cc3k_patch_program(mp_obj_t self_in, mp_obj_t key_in) { const char *key = mp_obj_str_get_str(key_in); if (key[0] == 'p' && key[1] == 'g' && key[2] == 'm' && key[3] == '\0') { patch_prog_start(); } else { mp_print_str(&mp_plat_print, "pass 'pgm' as argument in order to program\n"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc3k_patch_program_obj, cc3k_patch_program); STATIC const mp_rom_map_elem_t cc3k_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&cc3k_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&cc3k_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&cc3k_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&cc3k_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_patch_version), MP_ROM_PTR(&cc3k_patch_version_obj) }, { MP_ROM_QSTR(MP_QSTR_patch_program), MP_ROM_PTR(&cc3k_patch_program_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_WEP), MP_ROM_INT(WLAN_SEC_WEP) }, { MP_ROM_QSTR(MP_QSTR_WPA), MP_ROM_INT(WLAN_SEC_WPA) }, { MP_ROM_QSTR(MP_QSTR_WPA2), MP_ROM_INT(WLAN_SEC_WPA2) }, }; STATIC MP_DEFINE_CONST_DICT(cc3k_locals_dict, cc3k_locals_dict_table); const mod_network_nic_type_t mod_network_nic_type_cc3k = { .base = { { &mp_type_type }, .name = MP_QSTR_CC3K, .make_new = cc3k_make_new, .locals_dict = (mp_obj_dict_t*)&cc3k_locals_dict, }, .gethostbyname = cc3k_gethostbyname, .socket = cc3k_socket_socket, .close = cc3k_socket_close, .bind = cc3k_socket_bind, .listen = cc3k_socket_listen, .accept = cc3k_socket_accept, .connect = cc3k_socket_connect, .send = cc3k_socket_send, .recv = cc3k_socket_recv, .sendto = cc3k_socket_sendto, .recvfrom = cc3k_socket_recvfrom, .setsockopt = cc3k_socket_setsockopt, .settimeout = cc3k_socket_settimeout, .ioctl = cc3k_socket_ioctl, }; micropython-1.12/ports/stm32/modnwwiznet5k.c000066400000000000000000000414141357706137100211360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/objlist.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "lib/netutils/netutils.h" #include "modnetwork.h" #include "pin.h" #include "spi.h" #if MICROPY_PY_WIZNET5K && !MICROPY_PY_LWIP #include "ethernet/wizchip_conf.h" #include "ethernet/socket.h" #include "internet/dns/dns.h" /// \moduleref network typedef struct _wiznet5k_obj_t { mp_obj_base_t base; mp_uint_t cris_state; const spi_t *spi; const pin_obj_t *cs; const pin_obj_t *rst; uint8_t socket_used; } wiznet5k_obj_t; STATIC wiznet5k_obj_t wiznet5k_obj; STATIC void wiz_cris_enter(void) { wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION(); } STATIC void wiz_cris_exit(void) { MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state); } STATIC void wiz_cs_select(void) { mp_hal_pin_low(wiznet5k_obj.cs); } STATIC void wiz_cs_deselect(void) { mp_hal_pin_high(wiznet5k_obj.cs); } STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) { HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi->spi, buf, len, 5000); (void)status; } STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) { HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi->spi, (uint8_t*)buf, len, 5000); (void)status; } STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8}; uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE); DNS_init(0, buf); mp_int_t ret = DNS_run(dns_ip, (uint8_t*)name, out_ip); m_del(uint8_t, buf, MAX_DNS_BUF_SIZE); if (ret == 1) { // success return 0; } else { // failure return -2; } } STATIC int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { if (socket->u_param.domain != MOD_NETWORK_AF_INET) { *_errno = MP_EAFNOSUPPORT; return -1; } switch (socket->u_param.type) { case MOD_NETWORK_SOCK_STREAM: socket->u_param.type = Sn_MR_TCP; break; case MOD_NETWORK_SOCK_DGRAM: socket->u_param.type = Sn_MR_UDP; break; default: *_errno = MP_EINVAL; return -1; } if (socket->u_param.fileno == -1) { // get first unused socket number for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) { if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) { wiznet5k_obj.socket_used |= (1 << sn); socket->u_param.fileno = sn; break; } } if (socket->u_param.fileno == -1) { // too many open sockets *_errno = MP_EMFILE; return -1; } } // WIZNET does not have a concept of pure "open socket". You need to know // if it's a server or client at the time of creation of the socket. // So, we defer the open until we know what kind of socket we want. // use "domain" to indicate that this socket has not yet been opened socket->u_param.domain = 0; return 0; } STATIC void wiznet5k_socket_close(mod_network_socket_obj_t *socket) { uint8_t sn = (uint8_t)socket->u_param.fileno; if (sn < _WIZCHIP_SOCK_NUM_) { wiznet5k_obj.socket_used &= ~(1 << sn); WIZCHIP_EXPORT(close)(sn); } } STATIC int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { // open the socket in server mode (if port != 0) mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->u_param.fileno, socket->u_param.type, port, 0); if (ret < 0) { wiznet5k_socket_close(socket); *_errno = -ret; return -1; } // indicate that this socket has been opened socket->u_param.domain = 1; // success return 0; } STATIC int wiznet5k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) { mp_int_t ret = WIZCHIP_EXPORT(listen)(socket->u_param.fileno); if (ret < 0) { wiznet5k_socket_close(socket); *_errno = -ret; return -1; } return 0; } STATIC int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) { for (;;) { int sr = getSn_SR((uint8_t)socket->u_param.fileno); if (sr == SOCK_ESTABLISHED) { socket2->u_param = socket->u_param; getSn_DIPR((uint8_t)socket2->u_param.fileno, ip); *port = getSn_PORT(socket2->u_param.fileno); // WIZnet turns the listening socket into the client socket, so we // need to re-bind and re-listen on another socket for the server. // TODO handle errors, especially no-more-sockets error socket->u_param.domain = MOD_NETWORK_AF_INET; socket->u_param.fileno = -1; int _errno2; if (wiznet5k_socket_socket(socket, &_errno2) != 0) { //printf("(bad resocket %d)\n", _errno2); } else if (wiznet5k_socket_bind(socket, NULL, *port, &_errno2) != 0) { //printf("(bad rebind %d)\n", _errno2); } else if (wiznet5k_socket_listen(socket, 0, &_errno2) != 0) { //printf("(bad relisten %d)\n", _errno2); } return 0; } if (sr == SOCK_CLOSED || sr == SOCK_CLOSE_WAIT) { wiznet5k_socket_close(socket); *_errno = MP_ENOTCONN; // ?? return -1; } mp_hal_delay_ms(1); } } STATIC int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { // use "bind" function to open the socket in client mode if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) { return -1; } // now connect MP_THREAD_GIL_EXIT(); mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->u_param.fileno, ip, port); MP_THREAD_GIL_ENTER(); if (ret < 0) { wiznet5k_socket_close(socket); *_errno = -ret; return -1; } // success return 0; } STATIC mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { MP_THREAD_GIL_EXIT(); mp_int_t ret = WIZCHIP_EXPORT(send)(socket->u_param.fileno, (byte*)buf, len); MP_THREAD_GIL_ENTER(); // TODO convert Wiz errno's to POSIX ones if (ret < 0) { wiznet5k_socket_close(socket); *_errno = -ret; return -1; } return ret; } STATIC mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { MP_THREAD_GIL_EXIT(); mp_int_t ret = WIZCHIP_EXPORT(recv)(socket->u_param.fileno, buf, len); MP_THREAD_GIL_ENTER(); // TODO convert Wiz errno's to POSIX ones if (ret < 0) { wiznet5k_socket_close(socket); *_errno = -ret; return -1; } return ret; } STATIC mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { if (socket->u_param.domain == 0) { // socket not opened; use "bind" function to open the socket in client mode if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) { return -1; } } MP_THREAD_GIL_EXIT(); mp_int_t ret = WIZCHIP_EXPORT(sendto)(socket->u_param.fileno, (byte*)buf, len, ip, port); MP_THREAD_GIL_ENTER(); if (ret < 0) { wiznet5k_socket_close(socket); *_errno = -ret; return -1; } return ret; } STATIC mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { uint16_t port2; MP_THREAD_GIL_EXIT(); mp_int_t ret = WIZCHIP_EXPORT(recvfrom)(socket->u_param.fileno, buf, len, ip, &port2); MP_THREAD_GIL_ENTER(); *port = port2; if (ret < 0) { wiznet5k_socket_close(socket); *_errno = -ret; return -1; } return ret; } STATIC int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { // TODO *_errno = MP_EINVAL; return -1; } STATIC int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) { // TODO *_errno = MP_EINVAL; return -1; /* if (timeout_ms == 0) { // set non-blocking mode uint8_t arg = SOCK_IO_NONBLOCK; WIZCHIP_EXPORT(ctlsocket)(socket->u_param.fileno, CS_SET_IOMODE, &arg); } */ } STATIC int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) { if (request == MP_STREAM_POLL) { int ret = 0; if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->u_param.fileno) != 0) { ret |= MP_STREAM_POLL_RD; } if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->u_param.fileno) != 0) { ret |= MP_STREAM_POLL_WR; } return ret; } else { *_errno = MP_EINVAL; return MP_STREAM_ERROR; } } #if 0 STATIC void wiznet5k_socket_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { wiznet5k_socket_obj_t *self = self_in; print(env, "", self->sn, getSn_MR(self->sn)); } STATIC mp_obj_t wiznet5k_socket_disconnect(mp_obj_t self_in) { mp_int_t ret = WIZCHIP_EXPORT(disconnect)(self->sn); return 0; } #endif /******************************************************************************/ // MicroPython bindings /// \classmethod \constructor(spi, pin_cs, pin_rst) /// Create and return a WIZNET5K object. STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 3, 3, false); // init the wiznet5k object wiznet5k_obj.base.type = (mp_obj_type_t*)&mod_network_nic_type_wiznet5k; wiznet5k_obj.cris_state = 0; wiznet5k_obj.spi = spi_from_mp_obj(args[0]); wiznet5k_obj.cs = pin_find(args[1]); wiznet5k_obj.rst = pin_find(args[2]); wiznet5k_obj.socket_used = 0; /*!< SPI configuration */ SPI_InitTypeDef *init = &wiznet5k_obj.spi->spi->Init; init->Mode = SPI_MODE_MASTER; init->Direction = SPI_DIRECTION_2LINES; init->DataSize = SPI_DATASIZE_8BIT; init->CLKPolarity = SPI_POLARITY_LOW; // clock is low when idle init->CLKPhase = SPI_PHASE_1EDGE; // data latched on first edge, which is rising edge for low-idle init->NSS = SPI_NSS_SOFT; init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz init->FirstBit = SPI_FIRSTBIT_MSB; init->TIMode = SPI_TIMODE_DISABLED; init->CRCCalculation = SPI_CRCCALCULATION_DISABLED; init->CRCPolynomial = 7; // unused spi_init(wiznet5k_obj.spi, false); mp_hal_pin_output(wiznet5k_obj.cs); mp_hal_pin_output(wiznet5k_obj.rst); mp_hal_pin_low(wiznet5k_obj.rst); mp_hal_delay_ms(1); // datasheet says 2us mp_hal_pin_high(wiznet5k_obj.rst); mp_hal_delay_ms(160); // datasheet says 150ms reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit); reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect); reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write); uint8_t sn_size[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; // 2k buffer for each socket ctlwizchip(CW_INIT_WIZCHIP, sn_size); // set some sensible default values; they are configurable using ifconfig method wiz_NetInfo netinfo = { .mac = {0x00, 0x08, 0xdc, 0xab, 0xcd, 0xef}, .ip = {192, 168, 0, 18}, .sn = {255, 255, 255, 0}, .gw = {192, 168, 0, 1}, .dns = {8, 8, 8, 8}, // Google public DNS .dhcp = NETINFO_STATIC, }; ctlnetwork(CN_SET_NETINFO, (void*)&netinfo); // seems we need a small delay after init mp_hal_delay_ms(250); // register with network module mod_network_register_nic(&wiznet5k_obj); // return wiznet5k object return &wiznet5k_obj; } /// \method regs() /// Dump WIZNET5K registers. STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) { //wiznet5k_obj_t *self = self_in; printf("Wiz CREG:"); for (int i = 0; i < 0x50; ++i) { if (i % 16 == 0) { printf("\n %04x:", i); } #if MICROPY_PY_WIZNET5K == 5200 uint32_t reg = i; #else uint32_t reg = _W5500_IO_BASE_ | i << 8; #endif printf(" %02x", WIZCHIP_READ(reg)); } for (int sn = 0; sn < 4; ++sn) { printf("\nWiz SREG[%d]:", sn); for (int i = 0; i < 0x30; ++i) { if (i % 16 == 0) { printf("\n %04x:", i); } #if MICROPY_PY_WIZNET5K == 5200 uint32_t reg = WIZCHIP_SREG_ADDR(sn, i); #else uint32_t reg = _W5500_IO_BASE_ | i << 8 | WIZCHIP_SREG_BLOCK(sn) << 3; #endif printf(" %02x", WIZCHIP_READ(reg)); } } printf("\n"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_regs_obj, wiznet5k_regs); STATIC mp_obj_t wiznet5k_isconnected(mp_obj_t self_in) { (void)self_in; return mp_obj_new_bool(wizphy_getphylink() == PHY_LINK_ON); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_isconnected_obj, wiznet5k_isconnected); /// \method ifconfig([(ip, subnet, gateway, dns)]) /// Get/set IP address, subnet mask, gateway and DNS. STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) { wiz_NetInfo netinfo; ctlnetwork(CN_GET_NETINFO, &netinfo); if (n_args == 1) { // get mp_obj_t tuple[4] = { netutils_format_ipv4_addr(netinfo.ip, NETUTILS_BIG), netutils_format_ipv4_addr(netinfo.sn, NETUTILS_BIG), netutils_format_ipv4_addr(netinfo.gw, NETUTILS_BIG), netutils_format_ipv4_addr(netinfo.dns, NETUTILS_BIG), }; return mp_obj_new_tuple(4, tuple); } else { // set mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 4, &items); netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG); netutils_parse_ipv4_addr(items[1], netinfo.sn, NETUTILS_BIG); netutils_parse_ipv4_addr(items[2], netinfo.gw, NETUTILS_BIG); netutils_parse_ipv4_addr(items[3], netinfo.dns, NETUTILS_BIG); ctlnetwork(CN_SET_NETINFO, &netinfo); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig); STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&wiznet5k_regs_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wiznet5k_isconnected_obj) }, }; STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table); const mod_network_nic_type_t mod_network_nic_type_wiznet5k = { .base = { { &mp_type_type }, .name = MP_QSTR_WIZNET5K, .make_new = wiznet5k_make_new, .locals_dict = (mp_obj_dict_t*)&wiznet5k_locals_dict, }, .gethostbyname = wiznet5k_gethostbyname, .socket = wiznet5k_socket_socket, .close = wiznet5k_socket_close, .bind = wiznet5k_socket_bind, .listen = wiznet5k_socket_listen, .accept = wiznet5k_socket_accept, .connect = wiznet5k_socket_connect, .send = wiznet5k_socket_send, .recv = wiznet5k_socket_recv, .sendto = wiznet5k_socket_sendto, .recvfrom = wiznet5k_socket_recvfrom, .setsockopt = wiznet5k_socket_setsockopt, .settimeout = wiznet5k_socket_settimeout, .ioctl = wiznet5k_socket_ioctl, }; #endif // MICROPY_PY_WIZNET5K && !MICROPY_PY_LWIP micropython-1.12/ports/stm32/modpyb.c000066400000000000000000000231701357706137100176020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "lib/utils/pyexec.h" #include "drivers/dht/dht.h" #include "stm32_it.h" #include "irq.h" #include "led.h" #include "timer.h" #include "extint.h" #include "usrsw.h" #include "rng.h" #include "rtc.h" #include "i2c.h" #include "spi.h" #include "uart.h" #include "can.h" #include "adc.h" #include "storage.h" #include "sdcard.h" #include "accel.h" #include "servo.h" #include "dac.h" #include "lcd.h" #include "usb.h" #include "portmodules.h" #include "modmachine.h" #include "extmod/vfs.h" #include "extmod/utime_mphal.h" char pyb_country_code[2]; STATIC mp_obj_t pyb_fault_debug(mp_obj_t value) { pyb_hard_fault_debug = mp_obj_is_true(value); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_fault_debug_obj, pyb_fault_debug); #if MICROPY_PY_PYB_LEGACY // Returns the number of milliseconds which have elapsed since `start`. // This function takes care of counter wrap and always returns a positive number. STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) { uint32_t startMillis = mp_obj_get_int(start); uint32_t currMillis = mp_hal_ticks_ms(); return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis); // Returns the number of microseconds which have elapsed since `start`. // This function takes care of counter wrap and always returns a positive number. STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) { uint32_t startMicros = mp_obj_get_int(start); uint32_t currMicros = mp_hal_ticks_us(); return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros); #endif MP_DECLARE_CONST_FUN_OBJ_KW(pyb_main_obj); // defined in main.c // Get or set the UART object that the REPL is repeated on. // This is a legacy function, use of uos.dupterm is preferred. STATIC mp_obj_t pyb_repl_uart(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { if (MP_STATE_PORT(pyb_stdio_uart) == NULL) { return mp_const_none; } else { return MP_OBJ_FROM_PTR(MP_STATE_PORT(pyb_stdio_uart)); } } else { if (args[0] == mp_const_none) { if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { uart_attach_to_repl(MP_STATE_PORT(pyb_stdio_uart), false); MP_STATE_PORT(pyb_stdio_uart) = NULL; } } else if (mp_obj_get_type(args[0]) == &pyb_uart_type) { MP_STATE_PORT(pyb_stdio_uart) = MP_OBJ_TO_PTR(args[0]); uart_attach_to_repl(MP_STATE_PORT(pyb_stdio_uart), true); } else { mp_raise_ValueError("need a UART object"); } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart); STATIC mp_obj_t pyb_country(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return mp_obj_new_str(pyb_country_code, 2); } else { size_t len; const char *str = mp_obj_str_get_data(args[0], &len); if (len != 2) { mp_raise_ValueError(NULL); } pyb_country_code[0] = str[0]; pyb_country_code[1] = str[1]; return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_country_obj, 0, 1, pyb_country); STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) }, { MP_ROM_QSTR(MP_QSTR_fault_debug), MP_ROM_PTR(&pyb_fault_debug_obj) }, #if MICROPY_PY_PYB_LEGACY { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_hard_reset), MP_ROM_PTR(&machine_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_repl_info), MP_ROM_PTR(&pyb_set_repl_info_obj) }, { MP_ROM_QSTR(MP_QSTR_wfi), MP_ROM_PTR(&pyb_wfi_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) }, #if IRQ_ENABLE_STATS { MP_ROM_QSTR(MP_QSTR_irq_stats), MP_ROM_PTR(&pyb_irq_stats_obj) }, #endif #if MICROPY_PY_PYB_LEGACY { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_standby), MP_ROM_PTR(&machine_deepsleep_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_main), MP_ROM_PTR(&pyb_main_obj) }, { MP_ROM_QSTR(MP_QSTR_repl_uart), MP_ROM_PTR(&pyb_repl_uart_obj) }, { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&pyb_country_obj) }, #if MICROPY_HW_ENABLE_USB { MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&pyb_usb_mode_obj) }, #if MICROPY_HW_USB_HID { MP_ROM_QSTR(MP_QSTR_hid_mouse), MP_ROM_PTR(&pyb_usb_hid_mouse_obj) }, { MP_ROM_QSTR(MP_QSTR_hid_keyboard), MP_ROM_PTR(&pyb_usb_hid_keyboard_obj) }, { MP_ROM_QSTR(MP_QSTR_USB_HID), MP_ROM_PTR(&pyb_usb_hid_type) }, #endif { MP_ROM_QSTR(MP_QSTR_USB_VCP), MP_ROM_PTR(&pyb_usb_vcp_type) }, #if MICROPY_PY_PYB_LEGACY // these 2 are deprecated; use USB_VCP.isconnected and USB_HID.send instead { MP_ROM_QSTR(MP_QSTR_have_cdc), MP_ROM_PTR(&pyb_have_cdc_obj) }, #if MICROPY_HW_USB_HID { MP_ROM_QSTR(MP_QSTR_hid), MP_ROM_PTR(&pyb_hid_send_report_obj) }, #endif #endif #endif #if MICROPY_PY_PYB_LEGACY { MP_ROM_QSTR(MP_QSTR_millis), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_elapsed_millis), MP_ROM_PTR(&pyb_elapsed_millis_obj) }, { MP_ROM_QSTR(MP_QSTR_micros), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_elapsed_micros), MP_ROM_PTR(&pyb_elapsed_micros_obj) }, { MP_ROM_QSTR(MP_QSTR_delay), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_udelay), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mod_os_sync_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, #endif // This function is not intended to be public and may be moved elsewhere { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) }, #if MICROPY_HW_ENABLE_RNG { MP_ROM_QSTR(MP_QSTR_rng), MP_ROM_PTR(&pyb_rng_get_obj) }, #endif #if MICROPY_HW_ENABLE_RTC { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) }, #endif { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, { MP_ROM_QSTR(MP_QSTR_ExtInt), MP_ROM_PTR(&extint_type) }, #if MICROPY_HW_ENABLE_SERVO { MP_ROM_QSTR(MP_QSTR_pwm), MP_ROM_PTR(&pyb_pwm_set_obj) }, { MP_ROM_QSTR(MP_QSTR_servo), MP_ROM_PTR(&pyb_servo_set_obj) }, { MP_ROM_QSTR(MP_QSTR_Servo), MP_ROM_PTR(&pyb_servo_type) }, #endif #if MICROPY_HW_HAS_SWITCH { MP_ROM_QSTR(MP_QSTR_Switch), MP_ROM_PTR(&pyb_switch_type) }, #endif #if MICROPY_HW_HAS_FLASH { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&pyb_flash_type) }, #endif #if MICROPY_HW_ENABLE_SDCARD #if MICROPY_PY_PYB_LEGACY { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sdcard_obj) }, // now obsolete #endif { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&pyb_sdcard_type) }, #endif #if MICROPY_HW_ENABLE_MMCARD { MP_ROM_QSTR(MP_QSTR_MMCard), MP_ROM_PTR(&pyb_mmcard_type) }, #endif #if defined(MICROPY_HW_LED1) { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pyb_led_type) }, #endif #if MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&pyb_i2c_type) }, #endif { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, #if MICROPY_HW_ENABLE_CAN { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&pyb_can_type) }, #endif #if MICROPY_HW_ENABLE_ADC { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) }, { MP_ROM_QSTR(MP_QSTR_ADCAll), MP_ROM_PTR(&pyb_adc_all_type) }, #endif #if MICROPY_HW_ENABLE_DAC { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&pyb_dac_type) }, #endif #if MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3 { MP_ROM_QSTR(MP_QSTR_Accel), MP_ROM_PTR(&pyb_accel_type) }, #endif #if MICROPY_HW_HAS_LCD { MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&pyb_lcd_type) }, #endif }; STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table); const mp_obj_module_t pyb_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&pyb_module_globals, }; micropython-1.12/ports/stm32/modstm.c000066400000000000000000000037441357706137100176200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "py/objint.h" #include "extmod/machine_mem.h" #include "portmodules.h" #if MICROPY_PY_STM #include "genhdr/modstm_mpz.h" STATIC const mp_rom_map_elem_t stm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_stm) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, #include "genhdr/modstm_const.h" }; STATIC MP_DEFINE_CONST_DICT(stm_module_globals, stm_module_globals_table); const mp_obj_module_t stm_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&stm_module_globals, }; #endif // MICROPY_PY_STM micropython-1.12/ports/stm32/moduos.c000066400000000000000000000160111357706137100176120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/objtuple.h" #include "py/objstr.h" #include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/misc.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "extmod/vfs_lfs.h" #include "genhdr/mpversion.h" #include "rng.h" #include "usb.h" #include "uart.h" #include "portmodules.h" /// \module os - basic "operating system" services /// /// The `os` module contains functions for filesystem access and `urandom`. /// /// The filesystem has `/` as the root directory, and the available physical /// drives are accessible from here. They are currently: /// /// /flash -- the internal flash filesystem /// /sd -- the SD card (if it exists) /// /// On boot up, the current directory is `/flash` if no SD card is inserted, /// otherwise it is `/sd`. STATIC const qstr os_uname_info_fields[] = { MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine }; STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "pyboard"); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "pyboard"); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); STATIC MP_DEFINE_ATTRTUPLE( os_uname_info_obj, os_uname_info_fields, 5, MP_ROM_PTR(&os_uname_info_sysname_obj), MP_ROM_PTR(&os_uname_info_nodename_obj), MP_ROM_PTR(&os_uname_info_release_obj), MP_ROM_PTR(&os_uname_info_version_obj), MP_ROM_PTR(&os_uname_info_machine_obj) ); STATIC mp_obj_t os_uname(void) { return MP_OBJ_FROM_PTR(&os_uname_info_obj); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); /// \function sync() /// Sync all filesystems. STATIC mp_obj_t os_sync(void) { #if MICROPY_VFS_FAT for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { // this assumes that vfs->obj is fs_user_mount_t with block device functions disk_ioctl(MP_OBJ_TO_PTR(vfs->obj), CTRL_SYNC, NULL); } #endif return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(mod_os_sync_obj, os_sync); #if MICROPY_HW_ENABLE_RNG /// \function urandom(n) /// Return a bytes object with n random bytes, generated by the hardware /// random number generator. STATIC mp_obj_t os_urandom(mp_obj_t num) { mp_int_t n = mp_obj_get_int(num); vstr_t vstr; vstr_init_len(&vstr, n); for (int i = 0; i < n; i++) { vstr.buf[i] = rng_get(); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); #endif bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream) { mp_obj_type_t *type = mp_obj_get_type(stream); return type == &pyb_uart_type #if MICROPY_HW_ENABLE_USB || type == &pyb_usb_vcp_type #endif ; } STATIC mp_obj_t uos_dupterm(size_t n_args, const mp_obj_t *args) { mp_obj_t prev_obj = mp_uos_dupterm_obj.fun.var(n_args, args); if (mp_obj_get_type(prev_obj) == &pyb_uart_type) { uart_attach_to_repl(MP_OBJ_TO_PTR(prev_obj), false); } #if MICROPY_HW_ENABLE_USB if (mp_obj_get_type(prev_obj) == &pyb_usb_vcp_type) { usb_vcp_attach_to_repl(MP_OBJ_TO_PTR(prev_obj), false); } #endif if (mp_obj_get_type(args[0]) == &pyb_uart_type) { uart_attach_to_repl(MP_OBJ_TO_PTR(args[0]), true); } #if MICROPY_HW_ENABLE_USB if (mp_obj_get_type(args[0]) == &pyb_usb_vcp_type) { usb_vcp_attach_to_repl(MP_OBJ_TO_PTR(args[0]), true); } #endif return prev_obj; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uos_dupterm_obj, 1, 2, uos_dupterm); STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename),MP_ROM_PTR(&mp_vfs_rename_obj)}, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mod_os_sync_obj) }, /// \constant sep - separation character used in paths { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) }, #if MICROPY_HW_ENABLE_RNG { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, #endif // these are MicroPython extensions { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&uos_dupterm_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif #if MICROPY_VFS_LFS1 { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, #endif #if MICROPY_VFS_LFS2 { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, #endif }; STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); const mp_obj_module_t mp_module_uos = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&os_module_globals, }; micropython-1.12/ports/stm32/modusocket.c000066400000000000000000000407301357706137100204660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objtuple.h" #include "py/objlist.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "lib/netutils/netutils.h" #include "modnetwork.h" #if MICROPY_PY_USOCKET && !MICROPY_PY_LWIP /******************************************************************************/ // socket class STATIC const mp_obj_type_t socket_type; // constructor socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 4, false); // create socket object (not bound to any NIC yet) mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t); s->base.type = &socket_type; s->nic = MP_OBJ_NULL; s->nic_type = NULL; s->u_param.domain = MOD_NETWORK_AF_INET; s->u_param.type = MOD_NETWORK_SOCK_STREAM; s->u_param.fileno = -1; if (n_args >= 1) { s->u_param.domain = mp_obj_get_int(args[0]); if (n_args >= 2) { s->u_param.type = mp_obj_get_int(args[1]); if (n_args >= 4) { s->u_param.fileno = mp_obj_get_int(args[3]); } } } return MP_OBJ_FROM_PTR(s); } STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) { if (self->nic == MP_OBJ_NULL) { // select NIC based on IP self->nic = mod_network_find_nic(ip); self->nic_type = (mod_network_nic_type_t*)mp_obj_get_type(self->nic); // call the NIC to open the socket int _errno; if (self->nic_type->socket(self, &_errno) != 0) { mp_raise_OSError(_errno); } } } // method socket.bind(address) STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); // get address uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); // check if we need to select a NIC socket_select_nic(self, ip); // call the NIC to bind the socket int _errno; if (self->nic_type->bind(self, ip, port, &_errno) != 0) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); // method socket.listen(backlog) STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->nic == MP_OBJ_NULL) { // not connected // TODO I think we can listen even if not bound... mp_raise_OSError(MP_ENOTCONN); } int _errno; if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); // method socket.accept() STATIC mp_obj_t socket_accept(mp_obj_t self_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->nic == MP_OBJ_NULL) { // not bound mp_raise_OSError(MP_EINVAL); } // create new socket object // starts with empty NIC so that finaliser doesn't run close() method if accept() fails mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); socket2->base.type = &socket_type; socket2->nic = MP_OBJ_NULL; socket2->nic_type = NULL; // accept incoming connection uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; mp_uint_t port; int _errno; if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) { mp_raise_OSError(_errno); } // new socket has valid state, so set the NIC to the same as parent socket2->nic = self->nic; socket2->nic_type = self->nic_type; // make the return value mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); client->items[0] = MP_OBJ_FROM_PTR(socket2); client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return MP_OBJ_FROM_PTR(client); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); // method socket.connect(address) STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); // get address uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); // check if we need to select a NIC socket_select_nic(self, ip); // call the NIC to connect the socket int _errno; if (self->nic_type->connect(self, ip, port, &_errno) != 0) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); // method socket.send(bytes) STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->nic == MP_OBJ_NULL) { // not connected mp_raise_OSError(MP_EPIPE); } mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); int _errno; mp_uint_t ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno); if (ret == -1) { mp_raise_OSError(_errno); } return mp_obj_new_int_from_uint(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); // method socket.recv(bufsize) STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->nic == MP_OBJ_NULL) { // not connected mp_raise_OSError(MP_ENOTCONN); } mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); int _errno; mp_uint_t ret = self->nic_type->recv(self, (byte*)vstr.buf, len, &_errno); if (ret == -1) { mp_raise_OSError(_errno); } if (ret == 0) { return mp_const_empty_bytes; } vstr.len = ret; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); // method socket.sendto(bytes, address) STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); // get the data mp_buffer_info_t bufinfo; mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); // get address uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); // check if we need to select a NIC socket_select_nic(self, ip); // call the NIC to sendto int _errno; mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); if (ret == -1) { mp_raise_OSError(_errno); } return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); // method socket.recvfrom(bufsize) STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->nic == MP_OBJ_NULL) { // not connected mp_raise_OSError(MP_ENOTCONN); } vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(len_in)); byte ip[4]; mp_uint_t port; int _errno; mp_int_t ret = self->nic_type->recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); if (ret == -1) { mp_raise_OSError(_errno); } mp_obj_t tuple[2]; if (ret == 0) { tuple[0] = mp_const_empty_bytes; } else { vstr.len = ret; tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom); // method socket.setsockopt(level, optname, value) STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t level = mp_obj_get_int(args[1]); mp_int_t opt = mp_obj_get_int(args[2]); const void *optval; mp_uint_t optlen; mp_int_t val; if (mp_obj_is_integer(args[3])) { val = mp_obj_get_int_truncated(args[3]); optval = &val; optlen = sizeof(val); } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); optval = bufinfo.buf; optlen = bufinfo.len; } int _errno; if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); // method socket.settimeout(value) // timeout=0 means non-blocking // timeout=None means blocking // otherwise, timeout is in seconds STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->nic == MP_OBJ_NULL) { // not connected mp_raise_OSError(MP_ENOTCONN); } mp_uint_t timeout; if (timeout_in == mp_const_none) { timeout = -1; } else { #if MICROPY_PY_BUILTINS_FLOAT timeout = 1000 * mp_obj_get_float(timeout_in); #else timeout = 1000 * mp_obj_get_int(timeout_in); #endif } int _errno; if (self->nic_type->settimeout(self, timeout, &_errno) != 0) { mp_raise_OSError(_errno); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); // method socket.setblocking(flag) STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { if (mp_obj_is_true(blocking)) { return socket_settimeout(self_in, mp_const_none); } else { return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0)); } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, }; STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (request == MP_STREAM_CLOSE) { if (self->nic != MP_OBJ_NULL) { self->nic_type->close(self); self->nic = MP_OBJ_NULL; } return 0; } if (self->nic == MP_OBJ_NULL) { if (request == MP_STREAM_POLL) { return MP_STREAM_POLL_NVAL; } *errcode = MP_EINVAL; return MP_STREAM_ERROR; } return self->nic_type->ioctl(self, request, arg, errcode); } STATIC const mp_stream_p_t socket_stream_p = { .ioctl = socket_ioctl, .is_text = false, }; STATIC const mp_obj_type_t socket_type = { { &mp_type_type }, .name = MP_QSTR_socket, .make_new = socket_make_new, .protocol = &socket_stream_p, .locals_dict = (mp_obj_dict_t*)&socket_locals_dict, }; /******************************************************************************/ // usocket module // function usocket.getaddrinfo(host, port) STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { size_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE]; bool have_ip = false; if (hlen > 0) { // check if host is already in IP form nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { netutils_parse_ipv4_addr(host_in, out_ip, NETUTILS_BIG); have_ip = true; nlr_pop(); } else { // swallow exception: host was not in IP form so need to do DNS lookup } } if (!have_ip) { // find a NIC that can do a name lookup for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); if (nic_type->gethostbyname != NULL) { int ret = nic_type->gethostbyname(nic, host, hlen, out_ip); if (ret != 0) { mp_raise_OSError(ret); } have_ip = true; break; } } } if (!have_ip) { mp_raise_msg(&mp_type_OSError, "no available NIC"); } mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG); return mp_obj_new_list(1, (mp_obj_t*)&tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo); STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_usocket_getaddrinfo_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(MOD_NETWORK_AF_INET) }, { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) }, { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) }, { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) }, { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) }, /* { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(MOD_NETWORK_IPPROTO_IP) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_ICMP), MP_ROM_INT(MOD_NETWORK_IPPROTO_ICMP) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV4), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV4) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(MOD_NETWORK_IPPROTO_TCP) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(MOD_NETWORK_IPPROTO_UDP) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV6), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV6) }, { MP_ROM_QSTR(MP_QSTR_IPPROTO_RAW), MP_ROM_INT(MOD_NETWORK_IPPROTO_RAW) }, */ }; STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); const mp_obj_module_t mp_module_usocket = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, }; #endif // MICROPY_PY_USOCKET && !MICROPY_PY_LWIP micropython-1.12/ports/stm32/modutime.c000066400000000000000000000144001357706137100201270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/smallint.h" #include "py/obj.h" #include "lib/timeutils/timeutils.h" #include "extmod/utime_mphal.h" #include "systick.h" #include "portmodules.h" #include "rtc.h" /// \module time - time related functions /// /// The `time` module provides functions for getting the current time and date, /// and for sleeping. /// \function localtime([secs]) /// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which /// contains: (year, month, mday, hour, minute, second, weekday, yearday) /// If secs is not provided or None, then the current time from the RTC is used. /// year includes the century (for example 2014) /// month is 1-12 /// mday is 1-31 /// hour is 0-23 /// minute is 0-59 /// second is 0-59 /// weekday is 0-6 for Mon-Sun. /// yearday is 1-366 STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { if (n_args == 0 || args[0] == mp_const_none) { // get current date and time // note: need to call get time then get date to correctly access the registers rtc_init_finalise(); RTC_DateTypeDef date; RTC_TimeTypeDef time; HAL_RTC_GetTime(&RTCHandle, &time, RTC_FORMAT_BIN); HAL_RTC_GetDate(&RTCHandle, &date, RTC_FORMAT_BIN); mp_obj_t tuple[8] = { mp_obj_new_int(2000 + date.Year), mp_obj_new_int(date.Month), mp_obj_new_int(date.Date), mp_obj_new_int(time.Hours), mp_obj_new_int(time.Minutes), mp_obj_new_int(time.Seconds), mp_obj_new_int(date.WeekDay - 1), mp_obj_new_int(timeutils_year_day(2000 + date.Year, date.Month, date.Date)), }; return mp_obj_new_tuple(8, tuple); } else { mp_int_t seconds = mp_obj_get_int(args[0]); timeutils_struct_time_t tm; timeutils_seconds_since_2000_to_struct_time(seconds, &tm); mp_obj_t tuple[8] = { tuple[0] = mp_obj_new_int(tm.tm_year), tuple[1] = mp_obj_new_int(tm.tm_mon), tuple[2] = mp_obj_new_int(tm.tm_mday), tuple[3] = mp_obj_new_int(tm.tm_hour), tuple[4] = mp_obj_new_int(tm.tm_min), tuple[5] = mp_obj_new_int(tm.tm_sec), tuple[6] = mp_obj_new_int(tm.tm_wday), tuple[7] = mp_obj_new_int(tm.tm_yday), }; return mp_obj_new_tuple(8, tuple); } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime); /// \function mktime() /// This is inverse function of localtime. It's argument is a full 8-tuple /// which expresses a time as per localtime. It returns an integer which is /// the number of seconds since Jan 1, 2000. STATIC mp_obj_t time_mktime(mp_obj_t tuple) { size_t len; mp_obj_t *elem; mp_obj_get_array(tuple, &len, &elem); // localtime generates a tuple of len 8. CPython uses 9, so we accept both. if (len < 8 || len > 9) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "mktime needs a tuple of length 8 or 9 (%d given)", len)); } return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); } MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); /// \function time() /// Returns the number of seconds, as an integer, since 1/1/2000. STATIC mp_obj_t time_time(void) { // get date and time // note: need to call get time then get date to correctly access the registers rtc_init_finalise(); RTC_DateTypeDef date; RTC_TimeTypeDef time; HAL_RTC_GetTime(&RTCHandle, &time, RTC_FORMAT_BIN); HAL_RTC_GetDate(&RTCHandle, &date, RTC_FORMAT_BIN); return mp_obj_new_int(timeutils_seconds_since_2000(2000 + date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds)); } MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) }, { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) }, { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t mp_module_utime = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; micropython-1.12/ports/stm32/mpconfigboard_common.h000066400000000000000000000240451357706137100225010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Common settings and defaults for board configuration. // The defaults here should be overridden in mpconfigboard.h. #include STM32_HAL_H /*****************************************************************************/ // Feature settings with defaults // Whether to include the stm module, with peripheral register constants #ifndef MICROPY_PY_STM #define MICROPY_PY_STM (1) #endif // Whether to include legacy functions and classes in the pyb module #ifndef MICROPY_PY_PYB_LEGACY #define MICROPY_PY_PYB_LEGACY (1) #endif // Whether to enable storage on the internal flash of the MCU #ifndef MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (1) #endif // Whether to enable the RTC, exposed as pyb.RTC #ifndef MICROPY_HW_ENABLE_RTC #define MICROPY_HW_ENABLE_RTC (0) #endif // Whether to enable the hardware RNG peripheral, exposed as pyb.rng() #ifndef MICROPY_HW_ENABLE_RNG #define MICROPY_HW_ENABLE_RNG (0) #endif // Whether to enable the ADC peripheral, exposed as pyb.ADC and pyb.ADCAll #ifndef MICROPY_HW_ENABLE_ADC #define MICROPY_HW_ENABLE_ADC (1) #endif // Whether to enable the DAC peripheral, exposed as pyb.DAC #ifndef MICROPY_HW_ENABLE_DAC #define MICROPY_HW_ENABLE_DAC (0) #endif // Whether to enable the DCMI peripheral #ifndef MICROPY_HW_ENABLE_DCMI #define MICROPY_HW_ENABLE_DCMI (0) #endif // Whether to enable USB support #ifndef MICROPY_HW_ENABLE_USB #define MICROPY_HW_ENABLE_USB (0) #endif // Whether to enable the PA0-PA3 servo driver, exposed as pyb.Servo #ifndef MICROPY_HW_ENABLE_SERVO #define MICROPY_HW_ENABLE_SERVO (0) #endif // Whether to enable a USR switch, exposed as pyb.Switch #ifndef MICROPY_HW_HAS_SWITCH #define MICROPY_HW_HAS_SWITCH (0) #endif // Whether to expose internal flash storage as pyb.Flash #ifndef MICROPY_HW_HAS_FLASH #define MICROPY_HW_HAS_FLASH (0) #endif // Whether to enable the SD card interface, exposed as pyb.SDCard #ifndef MICROPY_HW_ENABLE_SDCARD #define MICROPY_HW_ENABLE_SDCARD (0) #endif // Whether to enable the MMC interface, exposed as pyb.MMCard #ifndef MICROPY_HW_ENABLE_MMCARD #define MICROPY_HW_ENABLE_MMCARD (0) #endif // SD/MMC interface bus width (defaults to 4 bits) #ifndef MICROPY_HW_SDMMC_BUS_WIDTH #define MICROPY_HW_SDMMC_BUS_WIDTH (4) #endif // Whether to automatically mount (and boot from) the SD card if it's present #ifndef MICROPY_HW_SDCARD_MOUNT_AT_BOOT #define MICROPY_HW_SDCARD_MOUNT_AT_BOOT (MICROPY_HW_ENABLE_SDCARD) #endif // Whether to enable the MMA7660 driver, exposed as pyb.Accel #ifndef MICROPY_HW_HAS_MMA7660 #define MICROPY_HW_HAS_MMA7660 (0) #endif // Whether to enable the LCD32MK driver, exposed as pyb.LCD #ifndef MICROPY_HW_HAS_LCD #define MICROPY_HW_HAS_LCD (0) #endif // The volume label used when creating the flash filesystem #ifndef MICROPY_HW_FLASH_FS_LABEL #define MICROPY_HW_FLASH_FS_LABEL "pybflash" #endif /*****************************************************************************/ // General configuration // Heap start / end definitions #ifndef MICROPY_HEAP_START #define MICROPY_HEAP_START &_heap_start #endif #ifndef MICROPY_HEAP_END #define MICROPY_HEAP_END &_heap_end #endif // Configuration for STM32F0 series #if defined(STM32F0) #define MP_HAL_UNIQUE_ID_ADDRESS (0x1ffff7ac) #define PYB_EXTI_NUM_VECTORS (23) #define MICROPY_HW_MAX_I2C (2) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) // Configuration for STM32F4 series #elif defined(STM32F4) #define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7a10) #define PYB_EXTI_NUM_VECTORS (23) #define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_TIMER (14) #if defined(UART10) #define MICROPY_HW_MAX_UART (10) #elif defined(UART9) #define MICROPY_HW_MAX_UART (9) #elif defined(UART8) #define MICROPY_HW_MAX_UART (8) #elif defined(UART7) #define MICROPY_HW_MAX_UART (7) #else #define MICROPY_HW_MAX_UART (6) #endif // Configuration for STM32F7 series #elif defined(STM32F7) #if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) #define MP_HAL_UNIQUE_ID_ADDRESS (0x1ff07a10) #else #define MP_HAL_UNIQUE_ID_ADDRESS (0x1ff0f420) #endif #define PYB_EXTI_NUM_VECTORS (24) #define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) // Configuration for STM32H7 series #elif defined(STM32H7) #define MP_HAL_UNIQUE_ID_ADDRESS (0x1ff1e800) #define PYB_EXTI_NUM_VECTORS (24) #define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) // Configuration for STM32L0 series #elif defined(STM32L0) #define MP_HAL_UNIQUE_ID_ADDRESS (0x1FF80050) #define PYB_EXTI_NUM_VECTORS (30) // TODO (22 configurable, 7 direct) #define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_TIMER (22) #define MICROPY_HW_MAX_UART (5) // Configuration for STM32L4 series #elif defined(STM32L4) #define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7590) #define PYB_EXTI_NUM_VECTORS (23) #define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (6) // Configuration for STM32WB series #elif defined(STM32WB) #define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE) #define PYB_EXTI_NUM_VECTORS (20) #define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (1) #else #error Unsupported MCU series #endif #if MICROPY_HW_CLK_USE_HSI // Use HSI as clock source #define MICROPY_HW_CLK_VALUE (HSI_VALUE) #define MICROPY_HW_RCC_OSCILLATOR_TYPE (RCC_OSCILLATORTYPE_HSI) #define MICROPY_HW_RCC_PLL_SRC (RCC_PLLSOURCE_HSI) #define MICROPY_HW_RCC_CR_HSxON (RCC_CR_HSION) #define MICROPY_HW_RCC_HSI_STATE (RCC_HSI_ON) #define MICROPY_HW_RCC_FLAG_HSxRDY (RCC_FLAG_HSIRDY) #define MICROPY_HW_RCC_HSE_STATE (RCC_HSE_OFF) #else // Use HSE as a clock source (bypass or oscillator) #define MICROPY_HW_CLK_VALUE (HSE_VALUE) #define MICROPY_HW_RCC_OSCILLATOR_TYPE (RCC_OSCILLATORTYPE_HSE) #define MICROPY_HW_RCC_PLL_SRC (RCC_PLLSOURCE_HSE) #define MICROPY_HW_RCC_CR_HSxON (RCC_CR_HSEON) #define MICROPY_HW_RCC_HSI_STATE (RCC_HSI_OFF) #define MICROPY_HW_RCC_FLAG_HSxRDY (RCC_FLAG_HSERDY) #if MICROPY_HW_CLK_USE_BYPASS #define MICROPY_HW_RCC_HSE_STATE (RCC_HSE_BYPASS) #else #define MICROPY_HW_RCC_HSE_STATE (RCC_HSE_ON) #endif #endif // If disabled then try normal (non-bypass) LSE first, with fallback to LSI. // If enabled first try LSE in bypass mode. If that fails to start, try non-bypass mode, with fallback to LSI. #ifndef MICROPY_HW_RTC_USE_BYPASS #define MICROPY_HW_RTC_USE_BYPASS (0) #endif #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE // Provide block device macros if internal flash storage is enabled #define MICROPY_HW_BDEV_IOCTL flash_bdev_ioctl #define MICROPY_HW_BDEV_READBLOCK flash_bdev_readblock #define MICROPY_HW_BDEV_WRITEBLOCK flash_bdev_writeblock #endif // Enable the storage sub-system if a block device is defined #if defined(MICROPY_HW_BDEV_IOCTL) #define MICROPY_HW_ENABLE_STORAGE (1) #else #define MICROPY_HW_ENABLE_STORAGE (0) #endif // Enable hardware I2C if there are any peripherals defined #if defined(MICROPY_HW_I2C1_SCL) || defined(MICROPY_HW_I2C2_SCL) \ || defined(MICROPY_HW_I2C3_SCL) || defined(MICROPY_HW_I2C4_SCL) #define MICROPY_HW_ENABLE_HW_I2C (1) #else #define MICROPY_HW_ENABLE_HW_I2C (0) #endif // Enable CAN if there are any peripherals defined #if defined(MICROPY_HW_CAN1_TX) || defined(MICROPY_HW_CAN2_TX) || defined(MICROPY_HW_CAN3_TX) #define MICROPY_HW_ENABLE_CAN (1) #if defined(STM32H7) #define MICROPY_HW_ENABLE_FDCAN (1) // define for MCUs with FDCAN #endif #else #define MICROPY_HW_ENABLE_CAN (0) #define MICROPY_HW_MAX_CAN (0) #endif #if defined(MICROPY_HW_CAN3_TX) #define MICROPY_HW_MAX_CAN (3) #elif defined(MICROPY_HW_CAN2_TX) #define MICROPY_HW_MAX_CAN (2) #elif defined(MICROPY_HW_CAN1_TX) #define MICROPY_HW_MAX_CAN (1) #endif // Whether the USB peripheral is device-only, or multiple OTG #if defined(STM32L0) || defined(STM32L432xx) || defined(STM32WB) #define MICROPY_HW_USB_IS_MULTI_OTG (0) #else #define MICROPY_HW_USB_IS_MULTI_OTG (1) #endif // Configure maximum number of CDC VCP interfaces, and whether MSC/HID are supported #ifndef MICROPY_HW_USB_CDC_NUM #define MICROPY_HW_USB_CDC_NUM (1) #endif #ifndef MICROPY_HW_USB_MSC #define MICROPY_HW_USB_MSC (MICROPY_HW_ENABLE_USB) #endif #ifndef MICROPY_HW_USB_HID #define MICROPY_HW_USB_HID (MICROPY_HW_ENABLE_USB) #endif // Pin definition header file #define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h" // D-cache clean/invalidate helpers #if __DCACHE_PRESENT == 1 #define MP_HAL_CLEANINVALIDATE_DCACHE(addr, size) \ (SCB_CleanInvalidateDCache_by_Addr((uint32_t*)((uint32_t)addr & ~0x1f), \ ((uint32_t)((uint8_t*)addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f))) #define MP_HAL_CLEAN_DCACHE(addr, size) \ (SCB_CleanDCache_by_Addr((uint32_t*)((uint32_t)addr & ~0x1f), \ ((uint32_t)((uint8_t*)addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f))) #else #define MP_HAL_CLEANINVALIDATE_DCACHE(addr, size) #define MP_HAL_CLEAN_DCACHE(addr, size) #endif #define MICROPY_HW_USES_BOOTLOADER (MICROPY_HW_VTOR != 0x08000000) micropython-1.12/ports/stm32/mpconfigport.h000066400000000000000000000330541357706137100210260ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Options to control how MicroPython is built for this port, // overriding defaults in py/mpconfig.h. // board specific definitions #include "mpconfigboard.h" #include "mpconfigboard_common.h" // memory allocation policies #ifndef MICROPY_GC_STACK_ENTRY_TYPE #if MICROPY_HW_SDRAM_SIZE #define MICROPY_GC_STACK_ENTRY_TYPE uint32_t #else #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t #endif #endif #define MICROPY_ALLOC_PATH_MAX (128) // emitters #define MICROPY_PERSISTENT_CODE_LOAD (1) #ifndef MICROPY_EMIT_THUMB #define MICROPY_EMIT_THUMB (1) #endif #ifndef MICROPY_EMIT_INLINE_THUMB #define MICROPY_EMIT_INLINE_THUMB (1) #endif // compiler configuration #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_RETURN_IF_EXPR (1) // optimisations #define MICROPY_OPT_COMPUTED_GOTO (1) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #define MICROPY_OPT_MPZ_BITWISE (1) #define MICROPY_OPT_MATH_FACTORIAL (1) // Python internal features #define MICROPY_READER_VFS (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_EMACS_KEYS (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_ENABLE_SOURCE_LINE (1) #ifndef MICROPY_FLOAT_IMPL // can be configured by each board via mpconfigboard.mk #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #endif #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_DEPTH (8) #define MICROPY_VFS (1) // control over Python builtins #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_DELATTR_SETATTR (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_BUILTINS_ROUND_INT (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_COMPILE (MICROPY_ENABLE_COMPILER) #define MICROPY_PY_BUILTINS_EXECFILE (MICROPY_ENABLE_COMPILER) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT stm32_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_COLLECTIONS_DEQUE (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) #define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_MATH_FACTORIAL (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO (1) #define MICROPY_PY_IO_IOBASE (1) #define MICROPY_PY_IO_FILEIO (MICROPY_VFS_FAT) // because mp_type_fileio/textio point to fatfs impl #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_SYS_STDIO_BUFFER (1) #ifndef MICROPY_PY_SYS_PLATFORM // let boards override it if they want #define MICROPY_PY_SYS_PLATFORM "pyboard" #endif #define MICROPY_PY_UERRNO (1) #ifndef MICROPY_PY_THREAD #define MICROPY_PY_THREAD (0) #endif // extended modules #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_URE_SUB (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UHASHLIB_MD5 (MICROPY_PY_USSL) #define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL) #define MICROPY_PY_UCRYPTOLIB (MICROPY_PY_USSL) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIMEQ (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_OS_DUPTERM (3) #define MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM (1) #define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_PY_MACHINE_I2C (1) #if MICROPY_HW_ENABLE_HW_I2C #define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hard_i2c_make_new #endif #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SPI_MSB (SPI_FIRSTBIT_MSB) #define MICROPY_PY_MACHINE_SPI_LSB (SPI_FIRSTBIT_LSB) #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hard_spi_make_new #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (HAL_RCC_GetSysClockFreq() / 48) #define MICROPY_PY_UWEBSOCKET (MICROPY_PY_LWIP) #define MICROPY_PY_WEBREPL (MICROPY_PY_LWIP) #ifndef MICROPY_PY_FRAMEBUF #define MICROPY_PY_FRAMEBUF (1) #endif #ifndef MICROPY_PY_USOCKET #define MICROPY_PY_USOCKET (1) #endif #ifndef MICROPY_PY_NETWORK #define MICROPY_PY_NETWORK (1) #endif // fatfs configuration used in ffconf.h #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MULTI_PARTITION (1) // TODO these should be generic, not bound to fatfs #define mp_type_fileio mp_type_vfs_fat_fileio #define mp_type_textio mp_type_vfs_fat_textio // use vfs's functions for import stat and builtin open #define mp_import_stat mp_vfs_import_stat #define mp_builtin_open mp_vfs_open #define mp_builtin_open_obj mp_vfs_open_obj // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t machine_module; extern const struct _mp_obj_module_t pyb_module; extern const struct _mp_obj_module_t stm_module; extern const struct _mp_obj_module_t mp_module_ubinascii; extern const struct _mp_obj_module_t mp_module_ure; extern const struct _mp_obj_module_t mp_module_uzlib; extern const struct _mp_obj_module_t mp_module_ujson; extern const struct _mp_obj_module_t mp_module_uheapq; extern const struct _mp_obj_module_t mp_module_uhashlib; extern const struct _mp_obj_module_t mp_module_uos; extern const struct _mp_obj_module_t mp_module_utime; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_network; extern const struct _mp_obj_module_t mp_module_onewire; #if MICROPY_PY_STM #define STM_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_stm), MP_ROM_PTR(&stm_module) }, #else #define STM_BUILTIN_MODULE #endif #if MICROPY_PY_USOCKET && MICROPY_PY_LWIP // usocket implementation provided by lwIP #define SOCKET_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_lwip) }, #elif MICROPY_PY_USOCKET // usocket implementation provided by skeleton wrapper #define SOCKET_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) }, #else // no usocket module #define SOCKET_BUILTIN_MODULE #endif #if MICROPY_PY_NETWORK #define NETWORK_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_network), MP_ROM_PTR(&mp_module_network) }, #else #define NETWORK_BUILTIN_MODULE #endif #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_pyb), MP_ROM_PTR(&pyb_module) }, \ STM_BUILTIN_MODULE \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ SOCKET_BUILTIN_MODULE \ NETWORK_BUILTIN_MODULE \ { MP_ROM_QSTR(MP_QSTR__onewire), MP_ROM_PTR(&mp_module_onewire) }, \ // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_pyb), MP_ROM_PTR(&pyb_module) }, \ STM_BUILTIN_MODULE \ #define MP_STATE_PORT MP_STATE_VM #if MICROPY_SSL_MBEDTLS #define MICROPY_PORT_ROOT_POINTER_MBEDTLS void **mbedtls_memory; #else #define MICROPY_PORT_ROOT_POINTER_MBEDTLS #endif #if MICROPY_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t; #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE void **bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; #else #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE #endif #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ \ mp_obj_t pyb_hid_report_desc; \ \ mp_obj_t pyb_config_main; \ \ mp_obj_t pyb_switch_callback; \ \ mp_obj_t pin_class_mapper; \ mp_obj_t pin_class_map_dict; \ \ mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \ \ struct _soft_timer_entry_t *soft_timer_head; \ \ /* pointers to all Timer objects (if they have been created) */ \ struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \ \ /* stdio is repeated on this UART object if it's not null */ \ struct _pyb_uart_obj_t *pyb_stdio_uart; \ \ /* pointers to all UART objects (if they have been created) */ \ struct _pyb_uart_obj_t *pyb_uart_obj_all[MICROPY_HW_MAX_UART]; \ \ /* pointers to all CAN objects (if they have been created) */ \ struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]; \ \ /* list of registered NICs */ \ mp_obj_list_t mod_network_nic_list; \ \ MICROPY_PORT_ROOT_POINTER_MBEDTLS \ MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \ // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) #define MP_SSIZE_MAX (0x7fffffff) #define UINT_FMT "%u" #define INT_FMT "%d" typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // We have inlined IRQ functions for efficiency (they are generally // 1 machine instruction). // // Note on IRQ state: you should not need to know the specific // value of the state variable, but rather just pass the return // value from disable_irq back to enable_irq. If you really need // to know the machine-specific values, see irq.h. static inline void enable_irq(mp_uint_t state) { __set_PRIMASK(state); } static inline mp_uint_t disable_irq(void) { mp_uint_t state = __get_PRIMASK(); __disable_irq(); return state; } #define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) #if MICROPY_PY_THREAD #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ if (pyb_thread_enabled) { \ MP_THREAD_GIL_EXIT(); \ pyb_thread_yield(); \ MP_THREAD_GIL_ENTER(); \ } else { \ __WFI(); \ } \ } while (0); #define MICROPY_THREAD_YIELD() pyb_thread_yield() #else #define MICROPY_EVENT_POLL_HOOK \ do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ __WFI(); \ } while (0); #define MICROPY_THREAD_YIELD() #endif // The LwIP interface must run at a raised IRQ priority #define MICROPY_PY_LWIP_ENTER uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); #define MICROPY_PY_LWIP_REENTER irq_state = raise_irq_pri(IRQ_PRI_PENDSV); #define MICROPY_PY_LWIP_EXIT restore_irq_pri(irq_state); // Bluetooth calls must run at a raised IRQ priority #define MICROPY_PY_BLUETOOTH_ENTER MICROPY_PY_LWIP_ENTER #define MICROPY_PY_BLUETOOTH_EXIT MICROPY_PY_LWIP_EXIT // We need an implementation of the log2 function which is not a macro #define MP_NEED_LOG2 (1) // We need to provide a declaration/definition of alloca() #include micropython-1.12/ports/stm32/mpconfigport.mk000066400000000000000000000004701357706137100212020ustar00rootroot00000000000000# Enable/disable extra modules # wiznet5k module for ethernet support; valid values are: # 0 : no Wiznet support # 5200 : support for W5200 module # 5500 : support for W5500 module MICROPY_PY_WIZNET5K ?= 0 # cc3k module for wifi support MICROPY_PY_CC3K ?= 0 # VFS FAT FS support MICROPY_VFS_FAT ?= 1 micropython-1.12/ports/stm32/mphalport.c000066400000000000000000000143111357706137100203130ustar00rootroot00000000000000#include #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "extmod/misc.h" #include "usb.h" #include "uart.h" // this table converts from HAL_StatusTypeDef to POSIX errno const byte mp_hal_status_to_errno_table[4] = { [HAL_OK] = 0, [HAL_ERROR] = MP_EIO, [HAL_BUSY] = MP_EBUSY, [HAL_TIMEOUT] = MP_ETIMEDOUT, }; NORETURN void mp_hal_raise(HAL_StatusTypeDef status) { mp_raise_OSError(mp_hal_status_to_errno_table[status]); } MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { int errcode; const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_PORT(pyb_stdio_uart)); ret = stream_p->ioctl(MP_STATE_PORT(pyb_stdio_uart), MP_STREAM_POLL, poll_flags, &errcode); } return ret | mp_uos_dupterm_poll(poll_flags); } MP_WEAK int mp_hal_stdin_rx_chr(void) { for (;;) { #if 0 #ifdef USE_HOST_MODE pyb_usb_host_process(); int c = pyb_usb_host_get_keyboard(); if (c != 0) { return c; } #endif #endif if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart)); } int dupterm_c = mp_uos_dupterm_rx_chr(); if (dupterm_c >= 0) { return dupterm_c; } MICROPY_EVENT_POLL_HOOK } } void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } MP_WEAK void mp_hal_stdout_tx_strn(const char *str, size_t len) { if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len); } #if 0 && defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD lcd_print_strn(str, len); #endif mp_uos_dupterm_tx_strn(str, len); } // Efficiently convert "\n" to "\r\n" void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { const char *last = str; while (len--) { if (*str == '\n') { if (str > last) { mp_hal_stdout_tx_strn(last, str - last); } mp_hal_stdout_tx_strn("\r\n", 2); ++str; last = str; } else { ++str; } } if (str > last) { mp_hal_stdout_tx_strn(last, str - last); } } #if __CORTEX_M >= 0x03 void mp_hal_ticks_cpu_enable(void) { if (!(DWT->CTRL & DWT_CTRL_CYCCNTENA_Msk)) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; #if defined(__CORTEX_M) && __CORTEX_M == 7 // on Cortex-M7 we must unlock the DWT before writing to its registers DWT->LAR = 0xc5acce55; #endif DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; } } #endif void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { #if defined(STM32L476xx) || defined(STM32L496xx) if (gpio == GPIOG) { // Port G pins 2 thru 15 are powered using VddIO2 on these MCUs. HAL_PWREx_EnableVddIO2(); } #endif // This logic assumes that all the GPIOx_EN bits are adjacent and ordered in one register #if defined(STM32F0) #define AHBxENR AHBENR #define AHBxENR_GPIOAEN_Pos RCC_AHBENR_GPIOAEN_Pos #elif defined(STM32F4) || defined(STM32F7) #define AHBxENR AHB1ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB1ENR_GPIOAEN_Pos #elif defined(STM32H7) #define AHBxENR AHB4ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB4ENR_GPIOAEN_Pos #elif defined(STM32L0) #define AHBxENR IOPENR #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_IOPAEN_Pos #elif defined(STM32L4) || defined(STM32WB) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos #endif uint32_t gpio_idx = ((uint32_t)gpio - GPIOA_BASE) / (GPIOB_BASE - GPIOA_BASE); RCC->AHBxENR |= 1 << (AHBxENR_GPIOAEN_Pos + gpio_idx); volatile uint32_t tmp = RCC->AHBxENR; // Delay after enabling clock (void)tmp; } void mp_hal_pin_config(mp_hal_pin_obj_t pin_obj, uint32_t mode, uint32_t pull, uint32_t alt) { GPIO_TypeDef *gpio = pin_obj->gpio; uint32_t pin = pin_obj->pin; mp_hal_gpio_clock_enable(gpio); gpio->MODER = (gpio->MODER & ~(3 << (2 * pin))) | ((mode & 3) << (2 * pin)); #if defined(GPIO_ASCR_ASC0) // The L4 has a special analog switch to connect the GPIO to the ADC gpio->OTYPER = (gpio->OTYPER & ~(1 << pin)) | (((mode >> 2) & 1) << pin); gpio->ASCR = (gpio->ASCR & ~(1 << pin)) | ((mode >> 3) & 1) << pin; #else gpio->OTYPER = (gpio->OTYPER & ~(1 << pin)) | ((mode >> 2) << pin); #endif gpio->OSPEEDR = (gpio->OSPEEDR & ~(3 << (2 * pin))) | (2 << (2 * pin)); // full speed gpio->PUPDR = (gpio->PUPDR & ~(3 << (2 * pin))) | (pull << (2 * pin)); gpio->AFR[pin >> 3] = (gpio->AFR[pin >> 3] & ~(15 << (4 * (pin & 7)))) | (alt << (4 * (pin & 7))); } bool mp_hal_pin_config_alt(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint8_t fn, uint8_t unit) { const pin_af_obj_t *af = pin_find_af(pin, fn, unit); if (af == NULL) { return false; } mp_hal_pin_config(pin, mode, pull, af->idx); return true; } void mp_hal_pin_config_speed(mp_hal_pin_obj_t pin_obj, uint32_t speed) { GPIO_TypeDef *gpio = pin_obj->gpio; uint32_t pin = pin_obj->pin; gpio->OSPEEDR = (gpio->OSPEEDR & ~(3 << (2 * pin))) | (speed << (2 * pin)); } /*******************************************************************************/ // MAC address // Generate a random locally administered MAC address (LAA) void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) { uint8_t *id = (uint8_t *)MP_HAL_UNIQUE_ID_ADDRESS; buf[0] = 0x02; // LAA range buf[1] = (id[11] << 4) | (id[10] & 0xf); buf[2] = (id[9] << 4) | (id[8] & 0xf); buf[3] = (id[7] << 4) | (id[6] & 0xf); buf[4] = id[2]; buf[5] = (id[0] << 2) | idx; } // A board can override this if needed MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) { mp_hal_generate_laa_mac(idx, buf); } void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) { static const char hexchr[16] = "0123456789ABCDEF"; uint8_t mac[6]; mp_hal_get_mac(idx, mac); for (; chr_len; ++chr_off, --chr_len) { *dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf]; } } micropython-1.12/ports/stm32/mphalport.h000066400000000000000000000064201357706137100203220ustar00rootroot00000000000000// We use the ST Cube HAL library for most hardware peripherals #include STM32_HAL_H #include "pin.h" extern const unsigned char mp_hal_status_to_errno_table[4]; NORETURN void mp_hal_raise(HAL_StatusTypeDef status); void mp_hal_set_interrupt_char(int c); // -1 to disable // timing functions #include "irq.h" #if __CORTEX_M == 0 // Don't have raise_irq_pri on Cortex-M0 so keep IRQs enabled to have SysTick timing #define mp_hal_quiet_timing_enter() (1) #define mp_hal_quiet_timing_exit(irq_state) (void)(irq_state) #else #define mp_hal_quiet_timing_enter() raise_irq_pri(1) #define mp_hal_quiet_timing_exit(irq_state) restore_irq_pri(irq_state) #endif #define mp_hal_delay_us_fast(us) mp_hal_delay_us(us) void mp_hal_ticks_cpu_enable(void); static inline mp_uint_t mp_hal_ticks_cpu(void) { #if __CORTEX_M == 0 return 0; #else if (!(DWT->CTRL & DWT_CTRL_CYCCNTENA_Msk)) { mp_hal_ticks_cpu_enable(); } return DWT->CYCCNT; #endif } // C-level pin HAL #include "pin.h" #define MP_HAL_PIN_FMT "%q" #define MP_HAL_PIN_MODE_INPUT (0) #define MP_HAL_PIN_MODE_OUTPUT (1) #define MP_HAL_PIN_MODE_ALT (2) #define MP_HAL_PIN_MODE_ANALOG (3) #if defined(GPIO_ASCR_ASC0) #define MP_HAL_PIN_MODE_ADC (11) #else #define MP_HAL_PIN_MODE_ADC (3) #endif #define MP_HAL_PIN_MODE_OPEN_DRAIN (5) #define MP_HAL_PIN_MODE_ALT_OPEN_DRAIN (6) #define MP_HAL_PIN_PULL_NONE (GPIO_NOPULL) #define MP_HAL_PIN_PULL_UP (GPIO_PULLUP) #define MP_HAL_PIN_PULL_DOWN (GPIO_PULLDOWN) #define MP_HAL_PIN_SPEED_LOW (GPIO_SPEED_FREQ_LOW) #define MP_HAL_PIN_SPEED_MEDIUM (GPIO_SPEED_FREQ_MEDIUM) #define MP_HAL_PIN_SPEED_HIGH (GPIO_SPEED_FREQ_HIGH) #define MP_HAL_PIN_SPEED_VERY_HIGH (GPIO_SPEED_FREQ_VERY_HIGH) #define mp_hal_pin_obj_t const pin_obj_t* #define mp_hal_get_pin_obj(o) pin_find(o) #define mp_hal_pin_name(p) ((p)->name) #define mp_hal_pin_input(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_output(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_open_drain(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_high(p) (((p)->gpio->BSRR) = (p)->pin_mask) #define mp_hal_pin_low(p) (((p)->gpio->BSRR) = ((p)->pin_mask << 16)) #define mp_hal_pin_od_low(p) mp_hal_pin_low(p) #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_read(p) (((p)->gpio->IDR >> (p)->pin) & 1) #define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio); void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt); bool mp_hal_pin_config_alt(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint8_t fn, uint8_t unit); void mp_hal_pin_config_speed(mp_hal_pin_obj_t pin_obj, uint32_t speed); enum { MP_HAL_MAC_WLAN0 = 0, MP_HAL_MAC_WLAN1, MP_HAL_MAC_BDADDR, MP_HAL_MAC_ETH0, }; void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]); void mp_hal_get_mac(int idx, uint8_t buf[6]); void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest); micropython-1.12/ports/stm32/mpthreadport.c000066400000000000000000000060301357706137100210150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/gc.h" #include "py/mpthread.h" #include "gccollect.h" #if MICROPY_PY_THREAD // the mutex controls access to the linked list STATIC mp_thread_mutex_t thread_mutex; void mp_thread_init(void) { mp_thread_mutex_init(&thread_mutex); mp_thread_set_state(&mp_state_ctx.thread); } void mp_thread_gc_others(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (pyb_thread_t *th = pyb_thread_all; th != NULL; th = th->all_next) { gc_collect_root((void**)&th, 1); gc_collect_root(&th->arg, 1); gc_collect_root(&th->stack, 1); if (th != pyb_thread_cur) { gc_collect_root(th->stack, th->stack_len); } } mp_thread_mutex_unlock(&thread_mutex); } void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { if (*stack_size == 0) { *stack_size = 4096; // default stack size } else if (*stack_size < 2048) { *stack_size = 2048; // minimum stack size } // round stack size to a multiple of the word size size_t stack_len = *stack_size / sizeof(uint32_t); *stack_size = stack_len * sizeof(uint32_t); // allocate stack and linked-list node (must be done outside thread_mutex lock) uint32_t *stack = m_new(uint32_t, stack_len); pyb_thread_t *th = m_new_obj(pyb_thread_t); mp_thread_mutex_lock(&thread_mutex, 1); // create thread uint32_t id = pyb_thread_new(th, stack, stack_len, entry, arg); if (id == 0) { mp_thread_mutex_unlock(&thread_mutex); mp_raise_msg(&mp_type_OSError, "can't create thread"); } mp_thread_mutex_unlock(&thread_mutex); // adjust stack_size to provide room to recover from hitting the limit *stack_size -= 1024; } void mp_thread_start(void) { } void mp_thread_finish(void) { } #endif // MICROPY_PY_THREAD micropython-1.12/ports/stm32/mpthreadport.h000066400000000000000000000035131357706137100210250ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpthread.h" #include "pybthread.h" typedef pyb_mutex_t mp_thread_mutex_t; void mp_thread_init(void); void mp_thread_gc_others(void); static inline void mp_thread_set_state(void *state) { pyb_thread_set_local(state); } static inline struct _mp_state_thread_t *mp_thread_get_state(void) { return pyb_thread_get_local(); } static inline void mp_thread_mutex_init(mp_thread_mutex_t *m) { pyb_mutex_init(m); } static inline int mp_thread_mutex_lock(mp_thread_mutex_t *m, int wait) { return pyb_mutex_lock(m, wait); } static inline void mp_thread_mutex_unlock(mp_thread_mutex_t *m) { pyb_mutex_unlock(m); } micropython-1.12/ports/stm32/mpu.h000066400000000000000000000076341357706137100171250ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_MPU_H #define MICROPY_INCLUDED_STM32_MPU_H #if defined(STM32F7) || defined(STM32H7) || defined(MICROPY_HW_ETH_MDC) #define MPU_REGION_ETH (MPU_REGION_NUMBER0) #define MPU_REGION_QSPI1 (MPU_REGION_NUMBER1) #define MPU_REGION_QSPI2 (MPU_REGION_NUMBER2) #define MPU_REGION_QSPI3 (MPU_REGION_NUMBER3) #define MPU_REGION_SDRAM1 (MPU_REGION_NUMBER4) #define MPU_REGION_SDRAM2 (MPU_REGION_NUMBER5) #define MPU_CONFIG_DISABLE(srd, size) ( \ MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos \ | MPU_REGION_NO_ACCESS << MPU_RASR_AP_Pos \ | MPU_TEX_LEVEL0 << MPU_RASR_TEX_Pos \ | MPU_ACCESS_NOT_SHAREABLE << MPU_RASR_S_Pos \ | MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos \ | MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos \ | (srd) << MPU_RASR_SRD_Pos \ | (size) << MPU_RASR_SIZE_Pos \ | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos \ ) #define MPU_CONFIG_ETH(size) ( \ MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos \ | MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos \ | MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos \ | MPU_ACCESS_SHAREABLE << MPU_RASR_S_Pos \ | MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos \ | MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos \ | 0x00 << MPU_RASR_SRD_Pos \ | (size) << MPU_RASR_SIZE_Pos \ | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos \ ) #define MPU_CONFIG_SDRAM(size) ( \ MPU_INSTRUCTION_ACCESS_ENABLE << MPU_RASR_XN_Pos \ | MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos \ | MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos \ | MPU_ACCESS_NOT_SHAREABLE << MPU_RASR_S_Pos \ | MPU_ACCESS_CACHEABLE << MPU_RASR_C_Pos \ | MPU_ACCESS_BUFFERABLE << MPU_RASR_B_Pos \ | 0x00 << MPU_RASR_SRD_Pos \ | (size) << MPU_RASR_SIZE_Pos \ | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos \ ) static inline void mpu_init(void) { MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk; SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; __DSB(); __ISB(); } static inline uint32_t mpu_config_start(void) { return disable_irq(); } static inline void mpu_config_region(uint32_t region, uint32_t base_addr, uint32_t attr_size) { MPU->RNR = region; MPU->RBAR = base_addr; MPU->RASR = attr_size; } static inline void mpu_config_end(uint32_t irq_state) { __ISB(); __DSB(); __DMB(); enable_irq(irq_state); } #else static inline void mpu_init(void) { } #endif #endif // MICROPY_INCLUDED_STM32_MPU_H micropython-1.12/ports/stm32/network_lan.c000066400000000000000000000136751357706137100206440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mphal.h" #include "modnetwork.h" #include "eth.h" #if defined(MICROPY_HW_ETH_MDC) #include "lwip/netif.h" typedef struct _network_lan_obj_t { mp_obj_base_t base; eth_t *eth; } network_lan_obj_t; STATIC const network_lan_obj_t network_lan_eth0 = { { &network_lan_type }, ð_instance }; STATIC void network_lan_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_lan_obj_t *self = MP_OBJ_TO_PTR(self_in); struct netif *netif = eth_netif(self->eth); int status = eth_link_status(self->eth); mp_printf(print, "", status, netif->ip_addr.addr & 0xff, netif->ip_addr.addr >> 8 & 0xff, netif->ip_addr.addr >> 16 & 0xff, netif->ip_addr.addr >> 24 ); } STATIC mp_obj_t network_lan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 0, false); const network_lan_obj_t *self = &network_lan_eth0; eth_init(self->eth, MP_HAL_MAC_ETH0); return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t network_lan_active(size_t n_args, const mp_obj_t *args) { network_lan_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { return mp_obj_new_bool(eth_link_status(self->eth)); } else { int ret; if (mp_obj_is_true(args[1])) { ret = eth_start(self->eth); } else { ret = eth_stop(self->eth); } if (ret < 0) { mp_raise_OSError(-ret); } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_lan_active_obj, 1, 2, network_lan_active); STATIC mp_obj_t network_lan_isconnected(mp_obj_t self_in) { network_lan_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(eth_link_status(self->eth) == 3); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_lan_isconnected_obj, network_lan_isconnected); STATIC mp_obj_t network_lan_ifconfig(size_t n_args, const mp_obj_t *args) { network_lan_obj_t *self = MP_OBJ_TO_PTR(args[0]); return mod_network_nic_ifconfig(eth_netif(self->eth), n_args - 1, args + 1); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_lan_ifconfig_obj, 1, 2, network_lan_ifconfig); STATIC mp_obj_t network_lan_status(size_t n_args, const mp_obj_t *args) { network_lan_obj_t *self = MP_OBJ_TO_PTR(args[0]); (void)self; if (n_args == 1) { // No arguments: return link status return MP_OBJ_NEW_SMALL_INT(eth_link_status(self->eth)); } mp_raise_ValueError("unknown status param"); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_lan_status_obj, 1, 2, network_lan_status); STATIC mp_obj_t network_lan_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { network_lan_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (kwargs->used == 0) { // Get config value if (n_args != 2) { mp_raise_TypeError("must query one param"); } switch (mp_obj_str_get_qstr(args[1])) { case MP_QSTR_mac: { return mp_obj_new_bytes(ð_netif(self->eth)->hwaddr[0], 6); } default: mp_raise_ValueError("unknown config param"); } } else { // Set config value(s) if (n_args != 1) { mp_raise_TypeError("can't specify pos and kw args"); } for (size_t i = 0; i < kwargs->alloc; ++i) { if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { mp_map_elem_t *e = &kwargs->table[i]; switch (mp_obj_str_get_qstr(e->key)) { case MP_QSTR_trace: { eth_set_trace(self->eth, mp_obj_get_int(e->value)); break; } default: mp_raise_ValueError("unknown config param"); } } } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_lan_config_obj, 1, network_lan_config); STATIC const mp_rom_map_elem_t network_lan_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_lan_active_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_lan_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_lan_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_lan_status_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_lan_config_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_lan_locals_dict, network_lan_locals_dict_table); const mp_obj_type_t network_lan_type = { { &mp_type_type }, .name = MP_QSTR_LAN, .print = network_lan_print, .make_new = network_lan_make_new, .locals_dict = (mp_obj_dict_t*)&network_lan_locals_dict, }; #endif // defined(MICROPY_HW_ETH_MDC) micropython-1.12/ports/stm32/network_wiznet5k.c000066400000000000000000000374731357706137100216540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "spi.h" #include "modnetwork.h" #if MICROPY_PY_WIZNET5K && MICROPY_PY_LWIP #include "lib/netutils/netutils.h" #include "drivers/wiznet5k/ethernet/socket.h" #include "lwip/err.h" #include "lwip/dns.h" #include "lwip/dhcp.h" #include "netif/etharp.h" #define TRACE_ETH_TX (0x0002) #define TRACE_ETH_RX (0x0004) /*******************************************************************************/ // Wiznet5k Ethernet driver in MACRAW mode typedef struct _wiznet5k_obj_t { mp_obj_base_t base; mp_uint_t cris_state; const spi_t *spi; mp_hal_pin_obj_t cs; mp_hal_pin_obj_t rst; uint8_t eth_frame[1514]; uint32_t trace_flags; struct netif netif; struct dhcp dhcp_struct; } wiznet5k_obj_t; // Global object holding the Wiznet5k state STATIC wiznet5k_obj_t wiznet5k_obj; STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self); STATIC void wiz_cris_enter(void) { wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION(); } STATIC void wiz_cris_exit(void) { MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state); } STATIC void wiz_cs_select(void) { mp_hal_pin_low(wiznet5k_obj.cs); } STATIC void wiz_cs_deselect(void) { mp_hal_pin_high(wiznet5k_obj.cs); } STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) { HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi->spi, buf, len, 5000); (void)status; } STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) { HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi->spi, (uint8_t*)buf, len, 5000); (void)status; } STATIC void wiznet5k_init(void) { // SPI configuration SPI_InitTypeDef *init = &wiznet5k_obj.spi->spi->Init; init->Mode = SPI_MODE_MASTER; init->Direction = SPI_DIRECTION_2LINES; init->DataSize = SPI_DATASIZE_8BIT; init->CLKPolarity = SPI_POLARITY_LOW; // clock is low when idle init->CLKPhase = SPI_PHASE_1EDGE; // data latched on first edge, which is rising edge for low-idle init->NSS = SPI_NSS_SOFT; init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz init->FirstBit = SPI_FIRSTBIT_MSB; init->TIMode = SPI_TIMODE_DISABLED; init->CRCCalculation = SPI_CRCCALCULATION_DISABLED; init->CRCPolynomial = 7; // unused spi_init(wiznet5k_obj.spi, false); mp_hal_pin_output(wiznet5k_obj.cs); mp_hal_pin_output(wiznet5k_obj.rst); // Reset the chip mp_hal_pin_low(wiznet5k_obj.rst); mp_hal_delay_ms(1); // datasheet says 2us mp_hal_pin_high(wiznet5k_obj.rst); mp_hal_delay_ms(150); // datasheet says 150ms // Set physical interface callbacks reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit); reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect); reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write); // Configure 16k buffers for fast MACRAW uint8_t sn_size[16] = {16, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0}; ctlwizchip(CW_INIT_WIZCHIP, sn_size); // Seems we need a small delay after init mp_hal_delay_ms(250); // If the device doesn't have a MAC address then set one uint8_t mac[6]; getSHAR(mac); if ((mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]) == 0) { mp_hal_get_mac(MP_HAL_MAC_ETH0, mac); setSHAR(mac); } // Hook the Wiznet into lwIP wiznet5k_lwip_init(&wiznet5k_obj); } STATIC void wiznet5k_deinit(void) { for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { if (netif == &wiznet5k_obj.netif) { netif_remove(netif); netif->flags = 0; break; } } } STATIC void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) { (void)self; getSHAR(mac); } STATIC void wiznet5k_send_ethernet(wiznet5k_obj_t *self, size_t len, const uint8_t *buf) { uint8_t ip[4] = {1, 1, 1, 1}; // dummy int ret = WIZCHIP_EXPORT(sendto)(0, (byte*)buf, len, ip, 11); // dummy port if (ret != len) { printf("wiznet5k_send_ethernet: fatal error %d\n", ret); netif_set_link_down(&self->netif); netif_set_down(&self->netif); } } // Stores the frame in self->eth_frame and returns number of bytes in the frame, 0 for no frame STATIC uint16_t wiznet5k_recv_ethernet(wiznet5k_obj_t *self) { uint16_t len = getSn_RX_RSR(0); if (len == 0) { return 0; } byte ip[4]; uint16_t port; int ret = WIZCHIP_EXPORT(recvfrom)(0, self->eth_frame, 1514, ip, &port); if (ret <= 0) { printf("wiznet5k_poll: fatal error len=%u ret=%d\n", len, ret); netif_set_link_down(&self->netif); netif_set_down(&self->netif); return 0; } return ret; } /*******************************************************************************/ // Wiznet5k lwIP interface STATIC err_t wiznet5k_netif_output(struct netif *netif, struct pbuf *p) { wiznet5k_obj_t *self = netif->state; pbuf_copy_partial(p, self->eth_frame, p->tot_len, 0); if (self->trace_flags & TRACE_ETH_TX) { netutils_ethernet_trace(MP_PYTHON_PRINTER, p->tot_len, self->eth_frame, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE); } wiznet5k_send_ethernet(self, p->tot_len, self->eth_frame); return ERR_OK; } STATIC err_t wiznet5k_netif_init(struct netif *netif) { netif->linkoutput = wiznet5k_netif_output; netif->output = etharp_output; netif->mtu = 1500; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; wiznet5k_get_mac_address(netif->state, netif->hwaddr); netif->hwaddr_len = sizeof(netif->hwaddr); int ret = WIZCHIP_EXPORT(socket)(0, Sn_MR_MACRAW, 0, 0); if (ret != 0) { printf("WIZNET fatal error in netifinit: %d\n", ret); return ERR_IF; } // Enable MAC filtering so we only get frames destined for us, to reduce load on lwIP setSn_MR(0, getSn_MR(0) | Sn_MR_MFEN); return ERR_OK; } STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self) { ip_addr_t ipconfig[4]; ipconfig[0].addr = 0; ipconfig[1].addr = 0; ipconfig[2].addr = 0; ipconfig[3].addr = 0; netif_add(&self->netif, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, wiznet5k_netif_init, ethernet_input); self->netif.name[0] = 'e'; self->netif.name[1] = '0'; netif_set_default(&self->netif); dns_setserver(0, &ipconfig[3]); dhcp_set_struct(&self->netif, &self->dhcp_struct); // Setting NETIF_FLAG_UP then clearing it is a workaround for dhcp_start and the // LWIP_DHCP_CHECK_LINK_UP option, so that the DHCP client schedules itself to // automatically start when the interface later goes up. self->netif.flags |= NETIF_FLAG_UP; dhcp_start(&self->netif); self->netif.flags &= ~NETIF_FLAG_UP; } void wiznet5k_poll(void) { wiznet5k_obj_t *self = &wiznet5k_obj; if (!(self->netif.flags & NETIF_FLAG_LINK_UP)) { return; } uint16_t len; while ((len = wiznet5k_recv_ethernet(self)) > 0) { if (self->trace_flags & TRACE_ETH_RX) { netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE); } struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != NULL) { pbuf_take(p, self->eth_frame, len); if (self->netif.input(p, &self->netif) != ERR_OK) { pbuf_free(p); } } } } /*******************************************************************************/ // MicroPython bindings // WIZNET5K([spi, pin_cs, pin_rst]) STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 3, 3, false); const spi_t *spi = spi_from_mp_obj(args[0]); mp_hal_pin_obj_t cs = pin_find(args[1]); mp_hal_pin_obj_t rst = pin_find(args[2]); // Access the existing object, if it has been constructed with the same hardware interface if (wiznet5k_obj.base.type == &mod_network_nic_type_wiznet5k) { if (!(wiznet5k_obj.spi == spi && wiznet5k_obj.cs == cs && wiznet5k_obj.rst == rst && wiznet5k_obj.netif.flags != 0)) { wiznet5k_deinit(); } } // Init the wiznet5k object wiznet5k_obj.base.type = &mod_network_nic_type_wiznet5k; wiznet5k_obj.cris_state = 0; wiznet5k_obj.spi = spi; wiznet5k_obj.cs = cs; wiznet5k_obj.rst = rst; wiznet5k_obj.trace_flags = 0; // Return wiznet5k object return MP_OBJ_FROM_PTR(&wiznet5k_obj); } STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) { (void)self_in; printf("Wiz CREG:"); for (int i = 0; i < 0x50; ++i) { if (i % 16 == 0) { printf("\n %04x:", i); } #if MICROPY_PY_WIZNET5K == 5200 uint32_t reg = i; #else uint32_t reg = _W5500_IO_BASE_ | i << 8; #endif printf(" %02x", WIZCHIP_READ(reg)); } for (int sn = 0; sn < 4; ++sn) { printf("\nWiz SREG[%d]:", sn); for (int i = 0; i < 0x30; ++i) { if (i % 16 == 0) { printf("\n %04x:", i); } #if MICROPY_PY_WIZNET5K == 5200 uint32_t reg = WIZCHIP_SREG_ADDR(sn, i); #else uint32_t reg = _W5500_IO_BASE_ | i << 8 | WIZCHIP_SREG_BLOCK(sn) << 3; #endif printf(" %02x", WIZCHIP_READ(reg)); } } printf("\n"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_regs_obj, wiznet5k_regs); STATIC mp_obj_t wiznet5k_isconnected(mp_obj_t self_in) { wiznet5k_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool( wizphy_getphylink() == PHY_LINK_ON && (self->netif.flags & NETIF_FLAG_UP) && self->netif.ip_addr.addr != 0 ); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_isconnected_obj, wiznet5k_isconnected); STATIC mp_obj_t wiznet5k_active(size_t n_args, const mp_obj_t *args) { wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { return mp_obj_new_bool(self->netif.flags & NETIF_FLAG_UP); } else { if (mp_obj_is_true(args[1])) { if (!(self->netif.flags & NETIF_FLAG_UP)) { wiznet5k_init(); netif_set_link_up(&self->netif); netif_set_up(&self->netif); } } else { if (self->netif.flags & NETIF_FLAG_UP) { netif_set_down(&self->netif); netif_set_link_down(&self->netif); wiznet5k_deinit(); } } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_active_obj, 1, 2, wiznet5k_active); STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) { wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]); return mod_network_nic_ifconfig(&self->netif, n_args - 1, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig); STATIC mp_obj_t wiznet5k_status(size_t n_args, const mp_obj_t *args) { wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]); (void)self; if (n_args == 1) { // No arguments: return link status if (self->netif.flags && wizphy_getphylink() == PHY_LINK_ON) { if ((self->netif.flags & NETIF_FLAG_UP) && self->netif.ip_addr.addr != 0) { return MP_OBJ_NEW_SMALL_INT(2); } else { return MP_OBJ_NEW_SMALL_INT(1); } } else { return MP_OBJ_NEW_SMALL_INT(0); } } mp_raise_ValueError("unknown config param"); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_status_obj, 1, 2, wiznet5k_status); STATIC mp_obj_t wiznet5k_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (kwargs->used == 0) { // Get config value if (n_args != 2) { mp_raise_TypeError("must query one param"); } switch (mp_obj_str_get_qstr(args[1])) { case MP_QSTR_mac: { uint8_t buf[6]; wiznet5k_get_mac_address(self, buf); return mp_obj_new_bytes(buf, 6); } default: mp_raise_ValueError("unknown config param"); } } else { // Set config value(s) if (n_args != 1) { mp_raise_TypeError("can't specify pos and kw args"); } for (size_t i = 0; i < kwargs->alloc; ++i) { if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { mp_map_elem_t *e = &kwargs->table[i]; switch (mp_obj_str_get_qstr(e->key)) { case MP_QSTR_mac: { mp_buffer_info_t buf; mp_get_buffer_raise(e->value, &buf, MP_BUFFER_READ); if (buf.len != 6) { mp_raise_ValueError(NULL); } setSHAR(buf.buf); memcpy(self->netif.hwaddr, buf.buf, 6); break; } case MP_QSTR_trace: { self->trace_flags = mp_obj_get_int(e->value); break; } default: mp_raise_ValueError("unknown config param"); } } } return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wiznet5k_config_obj, 1, wiznet5k_config); STATIC mp_obj_t send_ethernet_wrapper(mp_obj_t self_in, mp_obj_t buf_in) { wiznet5k_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t buf; mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ); wiznet5k_send_ethernet(self, buf.len, buf.buf); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(send_ethernet_obj, send_ethernet_wrapper); STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&wiznet5k_regs_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wiznet5k_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&wiznet5k_active_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&wiznet5k_status_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&wiznet5k_config_obj) }, { MP_ROM_QSTR(MP_QSTR_send_ethernet), MP_ROM_PTR(&send_ethernet_obj) }, }; STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table); const mp_obj_type_t mod_network_nic_type_wiznet5k = { { &mp_type_type }, .name = MP_QSTR_WIZNET5K, .make_new = wiznet5k_make_new, .locals_dict = (mp_obj_dict_t*)&wiznet5k_locals_dict, }; #endif // MICROPY_PY_WIZNET5K && MICROPY_PY_LWIP micropython-1.12/ports/stm32/nimble.c000066400000000000000000000050111357706137100175500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Jim Mussared * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE #include "systick.h" #include "pendsv.h" #include "transport/uart/ble_hci_uart.h" #include "host/ble_hs.h" #include "extmod/modbluetooth_nimble.h" extern void nimble_uart_process(void); extern void os_eventq_run_all(void); extern void os_callout_process(void); // Hook for pendsv poller to run this periodically every 128ms #define NIMBLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0) void nimble_poll(void) { if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { return; } nimble_uart_process(); os_callout_process(); os_eventq_run_all(); } void mod_bluetooth_nimble_poll_wrapper(uint32_t ticks_ms) { if (NIMBLE_TICK(ticks_ms)) { pendsv_schedule_dispatch(PENDSV_DISPATCH_NIMBLE, nimble_poll); } } void mp_bluetooth_nimble_port_preinit(void) { MP_STATE_PORT(bluetooth_nimble_memory) = NULL; ble_hci_uart_init(); } void mp_bluetooth_nimble_port_postinit(void) { } void mp_bluetooth_nimble_port_deinit(void) { #ifdef pyb_pin_BT_REG_ON mp_hal_pin_low(pyb_pin_BT_REG_ON); #endif } void mp_bluetooth_nimble_port_start(void) { ble_hs_start(); } #endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE micropython-1.12/ports/stm32/nimble_hci_uart.c000066400000000000000000000125221357706137100214330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mphal.h" #include "extmod/nimble/nimble/hci_uart.h" #if MICROPY_BLUETOOTH_NIMBLE #if defined(STM32WB) /******************************************************************************/ // HCI over IPCC #include "rfcore.h" int nimble_hci_uart_configure(uint32_t port) { (void)port; return 0; } int nimble_hci_uart_set_baudrate(uint32_t baudrate) { (void)baudrate; return 0; } int nimble_hci_uart_activate(void) { rfcore_ble_init(); return 0; } void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) { // Protect in case it's called from ble_npl_sem_pend at thread-level MICROPY_PY_LWIP_ENTER rfcore_ble_check_msg(rx_cb, rx_arg); MICROPY_PY_LWIP_EXIT } void nimble_hci_uart_tx_strn(const char *str, uint len) { MICROPY_PY_LWIP_ENTER rfcore_ble_hci_cmd(len, (const uint8_t*)str); MICROPY_PY_LWIP_EXIT } #else /******************************************************************************/ // HCI over UART #include "pendsv.h" #include "uart.h" #include "drivers/cyw43/cywbt.h" pyb_uart_obj_t bt_hci_uart_obj; static uint8_t hci_uart_rxbuf[512]; #ifdef pyb_pin_BT_DEV_WAKE static uint32_t bt_sleep_ticks; #endif extern void nimble_poll(void); mp_obj_t mp_uart_interrupt(mp_obj_t self_in) { pendsv_schedule_dispatch(PENDSV_DISPATCH_NIMBLE, nimble_poll); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_uart_interrupt_obj, mp_uart_interrupt); int nimble_hci_uart_set_baudrate(uint32_t baudrate) { uart_init(&bt_hci_uart_obj, baudrate, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, UART_HWCONTROL_RTS | UART_HWCONTROL_CTS); uart_set_rxbuf(&bt_hci_uart_obj, sizeof(hci_uart_rxbuf), hci_uart_rxbuf); return 0; } int nimble_hci_uart_configure(uint32_t port) { // bits (8), stop (1), parity (none) and flow (rts/cts) are assumed to match MYNEWT_VAL_BLE_HCI_UART_ constants in syscfg.h. bt_hci_uart_obj.base.type = &pyb_uart_type; bt_hci_uart_obj.uart_id = port; bt_hci_uart_obj.is_static = true; bt_hci_uart_obj.timeout = 2; bt_hci_uart_obj.timeout_char = 2; MP_STATE_PORT(pyb_uart_obj_all)[bt_hci_uart_obj.uart_id - 1] = &bt_hci_uart_obj; return 0; } int nimble_hci_uart_activate(void) { // Interrupt on RX chunk received (idle) // Trigger nimble poll when this happens mp_obj_t uart_irq_fn = mp_load_attr(&bt_hci_uart_obj, MP_QSTR_irq); mp_obj_t uargs[] = { MP_OBJ_FROM_PTR(&mp_uart_interrupt_obj), MP_OBJ_NEW_SMALL_INT(UART_FLAG_IDLE), mp_const_true, }; mp_call_function_n_kw(uart_irq_fn, 3, 0, uargs); #if MICROPY_PY_NETWORK_CYW43 cywbt_init(); cywbt_activate(); #endif return 0; } void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) { #ifdef pyb_pin_BT_HOST_WAKE int host_wake = 0; host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE); /* // this is just for info/tracing purposes static int last_host_wake = 0; if (host_wake != last_host_wake) { printf("HOST_WAKE change %d -> %d\n", last_host_wake, host_wake); last_host_wake = host_wake; } */ #endif while (uart_rx_any(&bt_hci_uart_obj)) { uint8_t data = uart_rx_char(&bt_hci_uart_obj); //printf("UART RX: %02x\n", data); rx_cb(rx_arg, data); } #ifdef pyb_pin_BT_DEV_WAKE if (host_wake == 1 && mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 0) { if (mp_hal_ticks_ms() - bt_sleep_ticks > 500) { //printf("BT SLEEP\n"); mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep } } #endif } void nimble_hci_uart_tx_strn(const char *str, uint len) { #ifdef pyb_pin_BT_DEV_WAKE bt_sleep_ticks = mp_hal_ticks_ms(); if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) { //printf("BT WAKE for TX\n"); mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up // Use delay_us rather than delay_ms to prevent running the scheduler (which // might result in more BLE operations). mp_hal_delay_us(5000); // can't go lower than this } #endif uart_tx_strn(&bt_hci_uart_obj, str, len); } #endif // defined(STM32WB) #endif // MICROPY_BLUETOOTH_NIMBLE micropython-1.12/ports/stm32/pendsv.c000066400000000000000000000152171357706137100176120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "lib/utils/interrupt_char.h" #include "pendsv.h" #include "irq.h" // This variable is used to save the exception object between a ctrl-C and the // PENDSV call that actually raises the exception. It must be non-static // otherwise gcc-5 optimises it away. It can point to the heap but is not // traced by GC. This is okay because we only ever set it to // mp_kbd_exception which is in the root-pointer set. void *pendsv_object; #if defined(PENDSV_DISPATCH_NUM_SLOTS) uint32_t pendsv_dispatch_active; pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS]; #endif void pendsv_init(void) { #if defined(PENDSV_DISPATCH_NUM_SLOTS) pendsv_dispatch_active = false; #endif // set PendSV interrupt at lowest priority NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV); } // Call this function to raise a pending exception during an interrupt. // It will first try to raise the exception "softly" by setting the // mp_pending_exception variable and hoping that the VM will notice it. // If this function is called a second time (ie with the mp_pending_exception // variable already set) then it will force the exception by using the hardware // PENDSV feature. This will wait until all interrupts are finished then raise // the given exception object using nlr_jump in the context of the top-level // thread. void pendsv_kbd_intr(void) { if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_NULL) { mp_keyboard_interrupt(); } else { MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; pendsv_object = &MP_STATE_VM(mp_kbd_exception); SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; } } #if defined(PENDSV_DISPATCH_NUM_SLOTS) void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) { pendsv_dispatch_table[slot] = f; pendsv_dispatch_active = true; SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; } void pendsv_dispatch_handler(void) { for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) { if (pendsv_dispatch_table[i] != NULL) { pendsv_dispatch_t f = pendsv_dispatch_table[i]; pendsv_dispatch_table[i] = NULL; f(); } } } #endif __attribute__((naked)) void PendSV_Handler(void) { // Handle a PendSV interrupt // // For the case of an asynchronous exception, re-jig the // stack so that when we return from this interrupt handler // it returns instead to nlr_jump with argument pendsv_object // note that stack has a different layout if DEBUG is enabled // // For the case of a thread switch, swap stacks. // // on entry to this (naked) function, stack has the following layout: // // stack layout with DEBUG disabled: // sp[6]: pc=r15 // sp[5]: lr=r14 // sp[4]: r12 // sp[3]: r3 // sp[2]: r2 // sp[1]: r1 // sp[0]: r0 // // stack layout with DEBUG enabled: // sp[8]: pc=r15 // sp[7]: lr=r14 // sp[6]: r12 // sp[5]: r3 // sp[4]: r2 // sp[3]: r1 // sp[2]: r0 // sp[1]: 0xfffffff9 // sp[0]: ? __asm volatile ( #if defined(PENDSV_DISPATCH_NUM_SLOTS) // Check if there are any pending calls to dispatch to "ldr r1, pendsv_dispatch_active_ptr\n" "ldr r0, [r1]\n" "cmp r0, #0\n" "beq .no_dispatch\n" "mov r2, #0\n" "str r2, [r1]\n" // clear pendsv_dispatch_active "b pendsv_dispatch_handler\n" // jump to the handler ".no_dispatch:\n" #endif // Check if there is an active object to throw via nlr_jump "ldr r1, pendsv_object_ptr\n" "ldr r0, [r1]\n" "cmp r0, #0\n" "beq .no_obj\n" #if defined(PENDSV_DEBUG) "str r0, [sp, #8]\n" // store to r0 on stack #else "str r0, [sp, #0]\n" // store to r0 on stack #endif "mov r0, #0\n" "str r0, [r1]\n" // clear pendsv_object "ldr r0, nlr_jump_ptr\n" #if defined(PENDSV_DEBUG) "str r0, [sp, #32]\n" // store to pc on stack #else "str r0, [sp, #24]\n" // store to pc on stack #endif "bx lr\n" // return from interrupt; will return to nlr_jump ".no_obj:\n" // pendsv_object==NULL #if MICROPY_PY_THREAD // Do a thread context switch "push {r4-r11, lr}\n" "vpush {s16-s31}\n" "mrs r5, primask\n" // save PRIMASK in r5 "cpsid i\n" // disable interrupts while we change stacks "mov r0, sp\n" // pass sp to save "mov r4, lr\n" // save lr because we are making a call "bl pyb_thread_next\n" // get next thread to execute "mov lr, r4\n" // restore lr "mov sp, r0\n" // switch stacks "msr primask, r5\n" // reenable interrupts "vpop {s16-s31}\n" "pop {r4-r11, lr}\n" "bx lr\n" // return from interrupt; will return to new thread #else // Spurious pendsv, just return "bx lr\n" #endif // Data ".align 2\n" #if defined(PENDSV_DISPATCH_NUM_SLOTS) "pendsv_dispatch_active_ptr: .word pendsv_dispatch_active\n" #endif "pendsv_object_ptr: .word pendsv_object\n" "nlr_jump_ptr: .word nlr_jump\n" ); } micropython-1.12/ports/stm32/pendsv.h000066400000000000000000000035361357706137100176200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_PENDSV_H #define MICROPY_INCLUDED_STM32_PENDSV_H enum { PENDSV_DISPATCH_SOFT_TIMER, #if MICROPY_PY_NETWORK && MICROPY_PY_LWIP PENDSV_DISPATCH_LWIP, #if MICROPY_PY_NETWORK_CYW43 PENDSV_DISPATCH_CYW43, #endif #endif #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE PENDSV_DISPATCH_NIMBLE, #endif PENDSV_DISPATCH_MAX }; #define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX typedef void (*pendsv_dispatch_t)(void); void pendsv_init(void); void pendsv_kbd_intr(void); void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f); #endif // MICROPY_INCLUDED_STM32_PENDSV_H micropython-1.12/ports/stm32/pin.c000066400000000000000000000601451357706137100171010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/mphal.h" #include "extmod/virtpin.h" #include "pin.h" #include "extint.h" /// \moduleref pyb /// \class Pin - control I/O pins /// /// A pin is the basic object to control I/O pins. It has methods to set /// the mode of the pin (input, output, etc) and methods to get and set the /// digital logic level. For analog control of a pin, see the ADC class. /// /// Usage Model: /// /// All Board Pins are predefined as pyb.Pin.board.Name /// /// x1_pin = pyb.Pin.board.X1 /// /// g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN) /// /// CPU pins which correspond to the board pins are available /// as `pyb.cpu.Name`. For the CPU pins, the names are the port letter /// followed by the pin number. On the PYBv1.0, `pyb.Pin.board.X1` and /// `pyb.Pin.cpu.B6` are the same pin. /// /// You can also use strings: /// /// g = pyb.Pin('X1', pyb.Pin.OUT_PP) /// /// Users can add their own names: /// /// MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 } /// pyb.Pin.dict(MyMapperDict) /// g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD) /// /// and can query mappings /// /// pin = pyb.Pin("LeftMotorDir") /// /// Users can also add their own mapping function: /// /// def MyMapper(pin_name): /// if pin_name == "LeftMotorDir": /// return pyb.Pin.cpu.A0 /// /// pyb.Pin.mapper(MyMapper) /// /// So, if you were to call: `pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)` /// then `"LeftMotorDir"` is passed directly to the mapper function. /// /// To summarise, the following order determines how things get mapped into /// an ordinal pin number: /// /// 1. Directly specify a pin object /// 2. User supplied mapping function /// 3. User supplied mapping (object must be usable as a dictionary key) /// 4. Supply a string which matches a board pin /// 5. Supply a string which matches a CPU port/pin /// /// You can set `pyb.Pin.debug(True)` to get some debug information about /// how a particular object gets mapped to a pin. // Pin class variables STATIC bool pin_class_debug; void pin_init0(void) { MP_STATE_PORT(pin_class_mapper) = mp_const_none; MP_STATE_PORT(pin_class_map_dict) = mp_const_none; pin_class_debug = false; } // C API used to convert a user-supplied pin name into an ordinal pin number. const pin_obj_t *pin_find(mp_obj_t user_obj) { const pin_obj_t *pin_obj; // If a pin was provided, then use it if (mp_obj_is_type(user_obj, &pin_type)) { pin_obj = MP_OBJ_TO_PTR(user_obj); if (pin_class_debug) { printf("Pin map passed pin "); mp_obj_print(MP_OBJ_FROM_PTR(pin_obj), PRINT_STR); printf("\n"); } return pin_obj; } if (MP_STATE_PORT(pin_class_mapper) != mp_const_none) { mp_obj_t o = mp_call_function_1(MP_STATE_PORT(pin_class_mapper), user_obj); if (o != mp_const_none) { if (!mp_obj_is_type(o, &pin_type)) { mp_raise_ValueError("Pin.mapper didn't return a Pin object"); } if (pin_class_debug) { printf("Pin.mapper maps "); mp_obj_print(user_obj, PRINT_REPR); printf(" to "); mp_obj_print(o, PRINT_STR); printf("\n"); } return MP_OBJ_TO_PTR(o); } // The pin mapping function returned mp_const_none, fall through to // other lookup methods. } if (MP_STATE_PORT(pin_class_map_dict) != mp_const_none) { mp_map_t *pin_map_map = mp_obj_dict_get_map(MP_STATE_PORT(pin_class_map_dict)); mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP); if (elem != NULL && elem->value != MP_OBJ_NULL) { mp_obj_t o = elem->value; if (pin_class_debug) { printf("Pin.map_dict maps "); mp_obj_print(user_obj, PRINT_REPR); printf(" to "); mp_obj_print(o, PRINT_STR); printf("\n"); } return MP_OBJ_TO_PTR(o); } } // See if the pin name matches a board pin pin_obj = pin_find_named_pin(&pin_board_pins_locals_dict, user_obj); if (pin_obj) { if (pin_class_debug) { printf("Pin.board maps "); mp_obj_print(user_obj, PRINT_REPR); printf(" to "); mp_obj_print(MP_OBJ_FROM_PTR(pin_obj), PRINT_STR); printf("\n"); } return pin_obj; } // See if the pin name matches a cpu pin pin_obj = pin_find_named_pin(&pin_cpu_pins_locals_dict, user_obj); if (pin_obj) { if (pin_class_debug) { printf("Pin.cpu maps "); mp_obj_print(user_obj, PRINT_REPR); printf(" to "); mp_obj_print(MP_OBJ_FROM_PTR(pin_obj), PRINT_STR); printf("\n"); } return pin_obj; } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Pin(%s) doesn't exist", mp_obj_str_get_str(user_obj))); } /// \method __str__() /// Return a string describing the pin object. STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); // pin name mp_printf(print, "Pin(Pin.cpu.%q, mode=Pin.", self->name); uint32_t mode = pin_get_mode(self); if (mode == GPIO_MODE_ANALOG) { // analog mp_print_str(print, "ANALOG)"); } else { // IO mode bool af = false; qstr mode_qst; if (mode == GPIO_MODE_INPUT) { mode_qst = MP_QSTR_IN; } else if (mode == GPIO_MODE_OUTPUT_PP) { mode_qst = MP_QSTR_OUT; } else if (mode == GPIO_MODE_OUTPUT_OD) { mode_qst = MP_QSTR_OPEN_DRAIN; } else { af = true; if (mode == GPIO_MODE_AF_PP) { mode_qst = MP_QSTR_ALT; } else { mode_qst = MP_QSTR_ALT_OPEN_DRAIN; } } mp_print_str(print, qstr_str(mode_qst)); // pull mode qstr pull_qst = MP_QSTRnull; uint32_t pull = pin_get_pull(self); if (pull == GPIO_PULLUP) { pull_qst = MP_QSTR_PULL_UP; } else if (pull == GPIO_PULLDOWN) { pull_qst = MP_QSTR_PULL_DOWN; } if (pull_qst != MP_QSTRnull) { mp_printf(print, ", pull=Pin.%q", pull_qst); } // AF mode if (af) { mp_uint_t af_idx = pin_get_af(self); const pin_af_obj_t *af_obj = pin_find_af_by_index(self, af_idx); if (af_obj == NULL) { mp_printf(print, ", af=%d)", af_idx); } else { mp_printf(print, ", af=Pin.%q)", af_obj->name); } } else { mp_print_str(print, ")"); } } } STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *pin, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); /// \classmethod \constructor(id, ...) /// Create a new Pin object associated with the id. If additional arguments are given, /// they are used to initialise the pin. See `init`. mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // Run an argument through the mapper and return the result. const pin_obj_t *pin = pin_find(args[0]); if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(pin); } // fast method for getting/setting pin value STATIC mp_obj_t pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); pin_obj_t *self = MP_OBJ_TO_PTR(self_in); if (n_args == 0) { // get pin return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self)); } else { // set pin mp_hal_pin_write(self, mp_obj_is_true(args[0])); return mp_const_none; } } /// \classmethod mapper([fun]) /// Get or set the pin mapper function. STATIC mp_obj_t pin_mapper(size_t n_args, const mp_obj_t *args) { if (n_args > 1) { MP_STATE_PORT(pin_class_mapper) = args[1]; return mp_const_none; } return MP_STATE_PORT(pin_class_mapper); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_mapper_fun_obj, 1, 2, pin_mapper); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_mapper_obj, MP_ROM_PTR(&pin_mapper_fun_obj)); /// \classmethod dict([dict]) /// Get or set the pin mapper dictionary. STATIC mp_obj_t pin_map_dict(size_t n_args, const mp_obj_t *args) { if (n_args > 1) { MP_STATE_PORT(pin_class_map_dict) = args[1]; return mp_const_none; } return MP_STATE_PORT(pin_class_map_dict); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_dict_fun_obj, 1, 2, pin_map_dict); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_map_dict_obj, MP_ROM_PTR(&pin_map_dict_fun_obj)); /// \classmethod af_list() /// Returns an array of alternate functions available for this pin. STATIC mp_obj_t pin_af_list(mp_obj_t self_in) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t result = mp_obj_new_list(0, NULL); const pin_af_obj_t *af = self->af; for (mp_uint_t i = 0; i < self->num_af; i++, af++) { mp_obj_list_append(result, MP_OBJ_FROM_PTR(af)); } return result; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_list_obj, pin_af_list); /// \classmethod debug([state]) /// Get or set the debugging state (`True` or `False` for on or off). STATIC mp_obj_t pin_debug(size_t n_args, const mp_obj_t *args) { if (n_args > 1) { pin_class_debug = mp_obj_is_true(args[1]); return mp_const_none; } return mp_obj_new_bool(pin_class_debug); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_debug_fun_obj, 1, 2, pin_debug); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, MP_ROM_PTR(&pin_debug_fun_obj)); // init(mode, pull=None, af=-1, *, value, alt) STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)}}, { MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}}, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get io mode uint mode = args[0].u_int; if (!IS_GPIO_MODE(mode)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin mode: %d", mode)); } // get pull mode uint pull = GPIO_NOPULL; if (args[1].u_obj != mp_const_none) { pull = mp_obj_get_int(args[1].u_obj); } if (!IS_GPIO_PULL(pull)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin pull: %d", pull)); } // get af (alternate function); alt-arg overrides af-arg mp_int_t af = args[4].u_int; if (af == -1) { af = args[2].u_int; } if ((mode == GPIO_MODE_AF_PP || mode == GPIO_MODE_AF_OD) && !IS_GPIO_AF(af)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin af: %d", af)); } // enable the peripheral clock for the port of this pin mp_hal_gpio_clock_enable(self->gpio); // if given, set the pin value before initialising to prevent glitches if (args[3].u_obj != MP_OBJ_NULL) { mp_hal_pin_write(self, mp_obj_is_true(args[3].u_obj)); } // configure the GPIO as requested GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = self->pin_mask; GPIO_InitStructure.Mode = mode; GPIO_InitStructure.Pull = pull; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStructure.Alternate = af; HAL_GPIO_Init(self->gpio, &GPIO_InitStructure); return mp_const_none; } STATIC mp_obj_t pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pin_obj_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); } MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init); /// \method value([value]) /// Get or set the digital logic level of the pin: /// /// - With no argument, return 0 or 1 depending on the logic level of the pin. /// - With `value` given, set the logic level of the pin. `value` can be /// anything that converts to a boolean. If it converts to `True`, the pin /// is set high, otherwise it is set low. STATIC mp_obj_t pin_value(size_t n_args, const mp_obj_t *args) { return pin_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value); STATIC mp_obj_t pin_off(mp_obj_t self_in) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_hal_pin_low(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_off_obj, pin_off); STATIC mp_obj_t pin_on(mp_obj_t self_in) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_hal_pin_high(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_on_obj, pin_on); // pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False) STATIC mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_handler, ARG_trigger, ARG_hard }; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_MODE_IT_RISING | GPIO_MODE_IT_FALLING} }, { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, }; pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (n_args > 1 || kw_args->used != 0) { // configure irq extint_register_pin(self, args[ARG_trigger].u_int, args[ARG_hard].u_bool, args[ARG_handler].u_obj); } // TODO should return an IRQ object return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_irq_obj, 1, pin_irq); /// \method name() /// Get the pin name. STATIC mp_obj_t pin_name(mp_obj_t self_in) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_QSTR(self->name); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_name_obj, pin_name); /// \method names() /// Returns the cpu and board names for this pin. STATIC mp_obj_t pin_names(mp_obj_t self_in) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t result = mp_obj_new_list(0, NULL); mp_obj_list_append(result, MP_OBJ_NEW_QSTR(self->name)); const mp_map_t *map = &pin_board_pins_locals_dict.map; mp_map_elem_t *elem = map->table; for (mp_uint_t i = 0; i < map->used; i++, elem++) { if (elem->value == self_in) { mp_obj_list_append(result, elem->key); } } return result; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_names_obj, pin_names); /// \method port() /// Get the pin port. STATIC mp_obj_t pin_port(mp_obj_t self_in) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(self->port); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_port_obj, pin_port); /// \method pin() /// Get the pin number. STATIC mp_obj_t pin_pin(mp_obj_t self_in) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(self->pin); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pin_obj, pin_pin); /// \method gpio() /// Returns the base address of the GPIO block associated with this pin. STATIC mp_obj_t pin_gpio(mp_obj_t self_in) { pin_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT((intptr_t)self->gpio); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_gpio_obj, pin_gpio); /// \method mode() /// Returns the currently configured mode of the pin. The integer returned /// will match one of the allowed constants for the mode argument to the init /// function. STATIC mp_obj_t pin_mode(mp_obj_t self_in) { return MP_OBJ_NEW_SMALL_INT(pin_get_mode(MP_OBJ_TO_PTR(self_in))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_mode_obj, pin_mode); /// \method pull() /// Returns the currently configured pull of the pin. The integer returned /// will match one of the allowed constants for the pull argument to the init /// function. STATIC mp_obj_t pin_pull(mp_obj_t self_in) { return MP_OBJ_NEW_SMALL_INT(pin_get_pull(MP_OBJ_TO_PTR(self_in))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pull_obj, pin_pull); /// \method af() /// Returns the currently configured alternate-function of the pin. The /// integer returned will match one of the allowed constants for the af /// argument to the init function. STATIC mp_obj_t pin_af(mp_obj_t self_in) { return MP_OBJ_NEW_SMALL_INT(pin_get_af(MP_OBJ_TO_PTR(self_in))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_obj, pin_af); STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pin_init_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&pin_on_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pin_irq_obj) }, // Legacy names as used by pyb.Pin { MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&pin_on_obj) }, { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&pin_name_obj) }, { MP_ROM_QSTR(MP_QSTR_names), MP_ROM_PTR(&pin_names_obj) }, { MP_ROM_QSTR(MP_QSTR_af_list), MP_ROM_PTR(&pin_af_list_obj) }, { MP_ROM_QSTR(MP_QSTR_port), MP_ROM_PTR(&pin_port_obj) }, { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&pin_pin_obj) }, { MP_ROM_QSTR(MP_QSTR_gpio), MP_ROM_PTR(&pin_gpio_obj) }, { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&pin_mode_obj) }, { MP_ROM_QSTR(MP_QSTR_pull), MP_ROM_PTR(&pin_pull_obj) }, { MP_ROM_QSTR(MP_QSTR_af), MP_ROM_PTR(&pin_af_obj) }, // class methods { MP_ROM_QSTR(MP_QSTR_mapper), MP_ROM_PTR(&pin_mapper_obj) }, { MP_ROM_QSTR(MP_QSTR_dict), MP_ROM_PTR(&pin_map_dict_obj) }, { MP_ROM_QSTR(MP_QSTR_debug), MP_ROM_PTR(&pin_debug_obj) }, // class attributes { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) }, { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&pin_cpu_pins_obj_type) }, // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUTPUT_PP) }, { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) }, { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_AF_PP) }, { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_AF_OD) }, { MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(GPIO_MODE_ANALOG) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN) }, { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_MODE_IT_RISING) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_MODE_IT_FALLING) }, // legacy class constants { MP_ROM_QSTR(MP_QSTR_OUT_PP), MP_ROM_INT(GPIO_MODE_OUTPUT_PP) }, { MP_ROM_QSTR(MP_QSTR_OUT_OD), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) }, { MP_ROM_QSTR(MP_QSTR_AF_PP), MP_ROM_INT(GPIO_MODE_AF_PP) }, { MP_ROM_QSTR(MP_QSTR_AF_OD), MP_ROM_INT(GPIO_MODE_AF_OD) }, { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(GPIO_NOPULL) }, #include "genhdr/pins_af_const.h" }; STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table); STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; pin_obj_t *self = MP_OBJ_TO_PTR(self_in); switch (request) { case MP_PIN_READ: { return mp_hal_pin_read(self); } case MP_PIN_WRITE: { mp_hal_pin_write(self, arg); return 0; } } return -1; } STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; const mp_obj_type_t pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, .print = pin_print, .make_new = mp_pin_make_new, .call = pin_call, .protocol = &pin_pin_p, .locals_dict = (mp_obj_dict_t*)&pin_locals_dict, }; /// \moduleref pyb /// \class PinAF - Pin Alternate Functions /// /// A Pin represents a physical pin on the microcprocessor. Each pin /// can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF /// object represents a particular function for a pin. /// /// Usage Model: /// /// x3 = pyb.Pin.board.X3 /// x3_af = x3.af_list() /// /// x3_af will now contain an array of PinAF objects which are availble on /// pin X3. /// /// For the pyboard, x3_af would contain: /// [Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2] /// /// Normally, each peripheral would configure the af automatically, but sometimes /// the same function is available on multiple pins, and having more control /// is desired. /// /// To configure X3 to expose TIM2_CH3, you could use: /// pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2) /// or: /// pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1) /// \method __str__() /// Return a string describing the alternate function. STATIC void pin_af_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pin_af_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "Pin.%q", self->name); } /// \method index() /// Return the alternate function index. STATIC mp_obj_t pin_af_index(mp_obj_t self_in) { pin_af_obj_t *af = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(af->idx); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_index_obj, pin_af_index); /// \method name() /// Return the name of the alternate function. STATIC mp_obj_t pin_af_name(mp_obj_t self_in) { pin_af_obj_t *af = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_QSTR(af->name); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_name_obj, pin_af_name); /// \method reg() /// Return the base register associated with the peripheral assigned to this /// alternate function. For example, if the alternate function were TIM2_CH3 /// this would return stm.TIM2 STATIC mp_obj_t pin_af_reg(mp_obj_t self_in) { pin_af_obj_t *af = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT((uintptr_t)af->reg); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_reg_obj, pin_af_reg); STATIC const mp_rom_map_elem_t pin_af_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&pin_af_index_obj) }, { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&pin_af_name_obj) }, { MP_ROM_QSTR(MP_QSTR_reg), MP_ROM_PTR(&pin_af_reg_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table); const mp_obj_type_t pin_af_type = { { &mp_type_type }, .name = MP_QSTR_PinAF, .print = pin_af_obj_print, .locals_dict = (mp_obj_dict_t*)&pin_af_locals_dict, }; micropython-1.12/ports/stm32/pin.h000066400000000000000000000064341357706137100171070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_PIN_H #define MICROPY_INCLUDED_STM32_PIN_H // This file requires pin_defs_xxx.h (which has port specific enums and // defines, so we include it here. It should never be included directly #include MICROPY_PIN_DEFS_PORT_H #include "py/obj.h" typedef struct { mp_obj_base_t base; qstr name; uint8_t idx; uint8_t fn; uint8_t unit; uint8_t type; void *reg; // The peripheral associated with this AF } pin_af_obj_t; typedef struct { mp_obj_base_t base; qstr name; uint32_t port : 4; uint32_t pin : 5; // Some ARM processors use 32 bits/PORT uint32_t num_af : 4; uint32_t adc_channel : 5; // Some ARM processors use 32 bits/PORT uint32_t adc_num : 3; // 1 bit per ADC uint32_t pin_mask; pin_gpio_t *gpio; const pin_af_obj_t *af; } pin_obj_t; extern const mp_obj_type_t pin_type; extern const mp_obj_type_t pin_af_type; // Include all of the individual pin objects #include "genhdr/pins.h" typedef struct { const char *name; const pin_obj_t *pin; } pin_named_pin_t; extern const pin_named_pin_t pin_board_pins[]; extern const pin_named_pin_t pin_cpu_pins[]; //extern pin_map_obj_t pin_map_obj; typedef struct { mp_obj_base_t base; qstr name; const pin_named_pin_t *named_pins; } pin_named_pins_obj_t; extern const mp_obj_type_t pin_board_pins_obj_type; extern const mp_obj_type_t pin_cpu_pins_obj_type; extern const mp_obj_dict_t pin_cpu_pins_locals_dict; extern const mp_obj_dict_t pin_board_pins_locals_dict; MP_DECLARE_CONST_FUN_OBJ_KW(pin_init_obj); void pin_init0(void); uint32_t pin_get_mode(const pin_obj_t *pin); uint32_t pin_get_pull(const pin_obj_t *pin); uint32_t pin_get_af(const pin_obj_t *pin); const pin_obj_t *pin_find(mp_obj_t user_obj); const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name); const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit); const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx); const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name); #endif // MICROPY_INCLUDED_STM32_PIN_H micropython-1.12/ports/stm32/pin_defs_stm32.c000066400000000000000000000016631357706137100211320ustar00rootroot00000000000000#include "py/obj.h" #include "pin.h" // Returns the pin mode. This value returned by this macro should be one of: // GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD, // GPIO_MODE_AF_PP, GPIO_MODE_AF_OD, or GPIO_MODE_ANALOG. uint32_t pin_get_mode(const pin_obj_t *pin) { GPIO_TypeDef *gpio = pin->gpio; uint32_t mode = (gpio->MODER >> (pin->pin * 2)) & 3; if (mode != GPIO_MODE_ANALOG) { if (gpio->OTYPER & pin->pin_mask) { mode |= 1 << 4; } } return mode; } // Returns the pin pullup/pulldown. The value returned by this macro should // be one of GPIO_NOPULL, GPIO_PULLUP, or GPIO_PULLDOWN. uint32_t pin_get_pull(const pin_obj_t *pin) { return (pin->gpio->PUPDR >> (pin->pin * 2)) & 3; } // Returns the af (alternate function) index currently set for a pin. uint32_t pin_get_af(const pin_obj_t *pin) { return (pin->gpio->AFR[pin->pin >> 3] >> ((pin->pin & 7) * 4)) & 0xf; } micropython-1.12/ports/stm32/pin_defs_stm32.h000066400000000000000000000066131357706137100211370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // This file contains pin definitions that are specific to the stm32 port. // This file should only ever be #included by pin.h and not directly. enum { PORT_A, PORT_B, PORT_C, PORT_D, PORT_E, PORT_F, PORT_G, PORT_H, PORT_I, PORT_J, PORT_K, }; // Must have matching entries in SUPPORTED_FN in boards/make-pins.py enum { AF_FN_TIM, AF_FN_I2C, AF_FN_USART, AF_FN_UART = AF_FN_USART, AF_FN_SPI, AF_FN_I2S, AF_FN_SDMMC, AF_FN_CAN, }; enum { AF_PIN_TYPE_TIM_CH1 = 0, AF_PIN_TYPE_TIM_CH2, AF_PIN_TYPE_TIM_CH3, AF_PIN_TYPE_TIM_CH4, AF_PIN_TYPE_TIM_CH1N, AF_PIN_TYPE_TIM_CH2N, AF_PIN_TYPE_TIM_CH3N, AF_PIN_TYPE_TIM_CH1_ETR, AF_PIN_TYPE_TIM_ETR, AF_PIN_TYPE_TIM_BKIN, AF_PIN_TYPE_I2C_SDA = 0, AF_PIN_TYPE_I2C_SCL, AF_PIN_TYPE_USART_TX = 0, AF_PIN_TYPE_USART_RX, AF_PIN_TYPE_USART_CTS, AF_PIN_TYPE_USART_RTS, AF_PIN_TYPE_USART_CK, AF_PIN_TYPE_UART_TX = AF_PIN_TYPE_USART_TX, AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX, AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS, AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS, AF_PIN_TYPE_SPI_MOSI = 0, AF_PIN_TYPE_SPI_MISO, AF_PIN_TYPE_SPI_SCK, AF_PIN_TYPE_SPI_NSS, AF_PIN_TYPE_I2S_CK = 0, AF_PIN_TYPE_I2S_MCK, AF_PIN_TYPE_I2S_SD, AF_PIN_TYPE_I2S_WS, AF_PIN_TYPE_I2S_EXTSD, AF_PIN_TYPE_SDMMC_CK = 0, AF_PIN_TYPE_SDMMC_CMD, AF_PIN_TYPE_SDMMC_D0, AF_PIN_TYPE_SDMMC_D1, AF_PIN_TYPE_SDMMC_D2, AF_PIN_TYPE_SDMMC_D3, AF_PIN_TYPE_CAN_TX = 0, AF_PIN_TYPE_CAN_RX, }; // The HAL uses a slightly different naming than we chose, so we provide // some #defines to massage things. Also I2S and SPI share the same // peripheral. #define GPIO_AF5_I2S2 GPIO_AF5_SPI2 #define GPIO_AF5_I2S3 GPIO_AF5_I2S3ext #define GPIO_AF6_I2S2 GPIO_AF6_I2S2ext #define GPIO_AF6_I2S3 GPIO_AF6_SPI3 #define GPIO_AF7_I2S2 GPIO_AF7_SPI2 #define GPIO_AF7_I2S3 GPIO_AF7_I2S3ext #define I2S2 SPI2 #define I2S3 SPI3 #if defined(STM32H7) // Make H7 FDCAN more like CAN #define CAN1 FDCAN1 #define CAN2 FDCAN2 #define GPIO_AF9_CAN1 GPIO_AF9_FDCAN1 #define GPIO_AF9_CAN2 GPIO_AF9_FDCAN2 #endif enum { PIN_ADC1 = (1 << 0), PIN_ADC2 = (1 << 1), PIN_ADC3 = (1 << 2), }; typedef GPIO_TypeDef pin_gpio_t; micropython-1.12/ports/stm32/pin_named_pins.c000066400000000000000000000055011357706137100212710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "pin.h" const mp_obj_type_t pin_cpu_pins_obj_type = { { &mp_type_type }, .name = MP_QSTR_cpu, .locals_dict = (mp_obj_dict_t*)&pin_cpu_pins_locals_dict, }; const mp_obj_type_t pin_board_pins_obj_type = { { &mp_type_type }, .name = MP_QSTR_board, .locals_dict = (mp_obj_dict_t*)&pin_board_pins_locals_dict, }; const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { const mp_map_t *named_map = &named_pins->map; mp_map_elem_t *named_elem = mp_map_lookup((mp_map_t*)named_map, name, MP_MAP_LOOKUP); if (named_elem != NULL && named_elem->value != MP_OBJ_NULL) { return MP_OBJ_TO_PTR(named_elem->value); } return NULL; } const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit) { const pin_af_obj_t *af = pin->af; for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { if (af->fn == fn && af->unit == unit) { return af; } } return NULL; } const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx) { const pin_af_obj_t *af = pin->af; for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { if (af->idx == af_idx) { return af; } } return NULL; } /* unused const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name) { const pin_af_obj_t *af = pin->af; for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { if (strcmp(name, qstr_str(af->name)) == 0) { return af; } } return NULL; } */ micropython-1.12/ports/stm32/pin_static_af.h000066400000000000000000000042431357706137100211200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_PIN_STATIC_AF_H #define MICROPY_INCLUDED_STM32_PIN_STATIC_AF_H #include "py/mphal.h" #include "genhdr/pins.h" #include "genhdr/pins_af_defs.h" #if 0 // Enable to test if AF's are statically compiled #define mp_hal_pin_config_alt_static(pin_obj, mode, pull, fn_type) \ mp_hal_pin_config(pin_obj, mode, pull, fn_type(pin_obj)); \ _Static_assert(fn_type(pin_obj) != -1, ""); \ _Static_assert(__builtin_constant_p(fn_type(pin_obj)) == 1, "") #else #define mp_hal_pin_config_alt_static(pin_obj, mode, pull, fn_type) \ mp_hal_pin_config(pin_obj, mode, pull, fn_type(pin_obj)) /* Overflow Error => alt func not found */ #define mp_hal_pin_config_alt_static_speed(pin_obj, mode, pull, speed, fn_type) \ mp_hal_pin_config(pin_obj, mode, pull, fn_type(pin_obj)); /* Overflow Error => alt func not found */ \ mp_hal_pin_config_speed(pin_obj, speed) #endif #endif // MICROPY_INCLUDED_STM32_PIN_STATIC_AF_H micropython-1.12/ports/stm32/portmodules.h000066400000000000000000000034651357706137100206770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_PORTMODULES_H #define MICROPY_INCLUDED_STM32_PORTMODULES_H extern const mp_obj_module_t pyb_module; extern const mp_obj_module_t stm_module; extern const mp_obj_module_t mp_module_uos; extern const mp_obj_module_t mp_module_utime; extern const mp_obj_module_t mp_module_usocket; // additional helper functions exported by the modules MP_DECLARE_CONST_FUN_OBJ_1(time_sleep_ms_obj); MP_DECLARE_CONST_FUN_OBJ_1(time_sleep_us_obj); MP_DECLARE_CONST_FUN_OBJ_0(mod_os_sync_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_dupterm_obj); #endif // MICROPY_INCLUDED_STM32_PORTMODULES_H micropython-1.12/ports/stm32/powerctrl.c000066400000000000000000000400551357706137100203320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mperrno.h" #include "py/mphal.h" #include "powerctrl.h" #include "rtc.h" #include "genhdr/pllfreqtable.h" #if defined(STM32H7) #define RCC_SR RSR #define RCC_SR_SFTRSTF RCC_RSR_SFTRSTF #define RCC_SR_RMVF RCC_RSR_RMVF #else #define RCC_SR CSR #define RCC_SR_SFTRSTF RCC_CSR_SFTRSTF #define RCC_SR_RMVF RCC_CSR_RMVF #endif // Location in RAM of bootloader state (just after the top of the stack) extern uint32_t _estack[]; #define BL_STATE ((uint32_t*)&_estack) NORETURN void powerctrl_mcu_reset(void) { BL_STATE[1] = 1; // invalidate bootloader address #if __DCACHE_PRESENT == 1 SCB_CleanDCache(); #endif NVIC_SystemReset(); } NORETURN void powerctrl_enter_bootloader(uint32_t r0, uint32_t bl_addr) { BL_STATE[0] = r0; BL_STATE[1] = bl_addr; #if __DCACHE_PRESENT == 1 SCB_CleanDCache(); #endif NVIC_SystemReset(); } static __attribute__((naked)) void branch_to_bootloader(uint32_t r0, uint32_t bl_addr) { __asm volatile ( "ldr r2, [r1, #0]\n" // get address of stack pointer "msr msp, r2\n" // get stack pointer "ldr r2, [r1, #4]\n" // get address of destination "bx r2\n" // branch to bootloader ); } void powerctrl_check_enter_bootloader(void) { uint32_t bl_addr = BL_STATE[1]; BL_STATE[1] = 1; // invalidate bootloader address if ((bl_addr & 0xfff) == 0 && (RCC->RCC_SR & RCC_SR_SFTRSTF)) { // Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader RCC->RCC_SR = RCC_SR_RMVF; #if defined(STM32F0) || defined(STM32F4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); #endif uint32_t r0 = BL_STATE[0]; branch_to_bootloader(r0, bl_addr); } } #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32WB) // Assumes that PLL is used as the SYSCLK source int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai) { uint32_t flash_latency; #if defined(STM32F7) if (need_pllsai) { // Configure PLLSAI at 48MHz for those peripherals that need this freq const uint32_t pllsain = 192; const uint32_t pllsaip = 4; const uint32_t pllsaiq = 2; RCC->PLLSAICFGR = pllsaiq << RCC_PLLSAICFGR_PLLSAIQ_Pos | (pllsaip / 2 - 1) << RCC_PLLSAICFGR_PLLSAIP_Pos | pllsain << RCC_PLLSAICFGR_PLLSAIN_Pos; RCC->CR |= RCC_CR_PLLSAION; uint32_t ticks = mp_hal_ticks_ms(); while (!(RCC->CR & RCC_CR_PLLSAIRDY)) { if (mp_hal_ticks_ms() - ticks > 200) { return -MP_ETIMEDOUT; } } RCC->DCKCFGR2 |= RCC_DCKCFGR2_CK48MSEL; } // If possible, scale down the internal voltage regulator to save power uint32_t volt_scale; if (sysclk_mhz <= 151) { volt_scale = PWR_REGULATOR_VOLTAGE_SCALE3; } else if (sysclk_mhz <= 180) { volt_scale = PWR_REGULATOR_VOLTAGE_SCALE2; } else { volt_scale = PWR_REGULATOR_VOLTAGE_SCALE1; } if (HAL_PWREx_ControlVoltageScaling(volt_scale) != HAL_OK) { return -MP_EIO; } // These flash_latency values assume a supply voltage between 2.7V and 3.6V if (sysclk_mhz <= 30) { flash_latency = FLASH_LATENCY_0; } else if (sysclk_mhz <= 60) { flash_latency = FLASH_LATENCY_1; } else if (sysclk_mhz <= 90) { flash_latency = FLASH_LATENCY_2; } else if (sysclk_mhz <= 120) { flash_latency = FLASH_LATENCY_3; } else if (sysclk_mhz <= 150) { flash_latency = FLASH_LATENCY_4; } else if (sysclk_mhz <= 180) { flash_latency = FLASH_LATENCY_5; } else if (sysclk_mhz <= 210) { flash_latency = FLASH_LATENCY_6; } else { flash_latency = FLASH_LATENCY_7; } #elif defined(MICROPY_HW_FLASH_LATENCY) flash_latency = MICROPY_HW_FLASH_LATENCY; #else flash_latency = FLASH_LATENCY_5; #endif rcc_init->SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; if (HAL_RCC_ClockConfig(rcc_init, flash_latency) != HAL_OK) { return -MP_EIO; } return 0; } #endif #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; } else if (wanted_div <= 2) { return RCC_SYSCLK_DIV2; } else if (wanted_div <= 4) { return RCC_SYSCLK_DIV4; } else if (wanted_div <= 8) { return RCC_SYSCLK_DIV8; } else if (wanted_div <= 16) { return RCC_SYSCLK_DIV16; } else if (wanted_div <= 64) { return RCC_SYSCLK_DIV64; } else if (wanted_div <= 128) { return RCC_SYSCLK_DIV128; } else if (wanted_div <= 256) { return RCC_SYSCLK_DIV256; } else { return RCC_SYSCLK_DIV512; } } STATIC uint32_t calc_apb_div(uint32_t wanted_div) { if (wanted_div <= 1) { return RCC_HCLK_DIV1; } else if (wanted_div <= 2) { return RCC_HCLK_DIV2; } else if (wanted_div <= 4) { return RCC_HCLK_DIV4; } else if (wanted_div <= 8) { return RCC_HCLK_DIV8; } else { return RCC_SYSCLK_DIV16; } } int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2) { // Return straightaway if the clocks are already at the desired frequency if (sysclk == HAL_RCC_GetSysClockFreq() && ahb == HAL_RCC_GetHCLKFreq() && apb1 == HAL_RCC_GetPCLK1Freq() && apb2 == HAL_RCC_GetPCLK2Freq()) { return 0; } // Default PLL parameters that give 48MHz on PLL48CK uint32_t m = MICROPY_HW_CLK_VALUE / 1000000, n = 336, p = 2, q = 7; uint32_t sysclk_source; bool need_pllsai = false; // Search for a valid PLL configuration that keeps USB at 48MHz uint32_t sysclk_mhz = sysclk / 1000000; for (const uint16_t *pll = &pll_freq_table[MP_ARRAY_SIZE(pll_freq_table) - 1]; pll >= &pll_freq_table[0]; --pll) { uint32_t sys = *pll & 0xff; if (sys <= sysclk_mhz) { m = (*pll >> 10) & 0x3f; p = ((*pll >> 7) & 0x6) + 2; if (m == 0) { // special entry for using HSI directly sysclk_source = RCC_SYSCLKSOURCE_HSI; } else if (m == 1) { // special entry for using HSE directly sysclk_source = RCC_SYSCLKSOURCE_HSE; } else { // use PLL sysclk_source = RCC_SYSCLKSOURCE_PLLCLK; uint32_t vco_out = sys * p; n = vco_out * m / (MICROPY_HW_CLK_VALUE / 1000000); q = vco_out / 48; #if defined(STM32F7) need_pllsai = vco_out % 48 != 0; #endif } goto set_clk; } } return -MP_EINVAL; set_clk: // Let the USB CDC have a chance to process before we change the clock mp_hal_delay_ms(5); // Desired system clock source is in sysclk_source RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) { // Set HSE as system clock source to allow modification of the PLL configuration // We then change to PLL after re-configuring PLL #if MICROPY_HW_CLK_USE_HSI RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; #else RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; #endif } else { // Directly set the system clock source as desired RCC_ClkInitStruct.SYSCLKSource = sysclk_source; } // Determine the bus clock dividers // Note: AHB freq required to be >= 14.2MHz for USB operation RCC_ClkInitStruct.AHBCLKDivider = calc_ahb_div(sysclk / ahb); #if !defined(STM32H7) ahb = sysclk >> AHBPrescTable[RCC_ClkInitStruct.AHBCLKDivider >> RCC_CFGR_HPRE_Pos]; #endif RCC_ClkInitStruct.APB1CLKDivider = calc_apb_div(ahb / apb1); RCC_ClkInitStruct.APB2CLKDivider = calc_apb_div(ahb / apb2); #if MICROPY_HW_CLK_LAST_FREQ // Save the bus dividers for use later uint32_t h = RCC_ClkInitStruct.AHBCLKDivider >> 4; uint32_t b1 = RCC_ClkInitStruct.APB1CLKDivider >> 10; uint32_t b2 = RCC_ClkInitStruct.APB2CLKDivider >> 10; #endif // Configure clock if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { return -MP_EIO; } #if defined(STM32F7) // Deselect PLLSAI as 48MHz source if we were using it RCC->DCKCFGR2 &= ~RCC_DCKCFGR2_CK48MSEL; // Turn PLLSAI off because we are changing PLLM (which drives PLLSAI) RCC->CR &= ~RCC_CR_PLLSAION; #endif // Re-configure PLL // Even if we don't use the PLL for the system clock, we still need it for USB, RNG and SDIO RCC_OscInitTypeDef RCC_OscInitStruct; RCC_OscInitStruct.OscillatorType = MICROPY_HW_RCC_OSCILLATOR_TYPE; RCC_OscInitStruct.HSEState = MICROPY_HW_RCC_HSE_STATE; RCC_OscInitStruct.HSIState = MICROPY_HW_RCC_HSI_STATE; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = MICROPY_HW_RCC_PLL_SRC; RCC_OscInitStruct.PLL.PLLM = m; RCC_OscInitStruct.PLL.PLLN = n; RCC_OscInitStruct.PLL.PLLP = p; RCC_OscInitStruct.PLL.PLLQ = q; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { return -MP_EIO; } // Set PLL as system clock source if wanted if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) { RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; int ret = powerctrl_rcc_clock_config_pll(&RCC_ClkInitStruct, sysclk_mhz, need_pllsai); if (ret != 0) { return ret; } } #if MICROPY_HW_CLK_LAST_FREQ // Save settings in RTC backup register to reconfigure clocks on hard-reset #if defined(STM32F7) #define FREQ_BKP BKP31R #else #define FREQ_BKP BKP19R #endif // qqqqqqqq pppppppp nnnnnnnn nnmmmmmm // qqqqQQQQ ppppppPP nNNNNNNN NNMMMMMM // 222111HH HHQQQQPP nNNNNNNN NNMMMMMM p = (p / 2) - 1; RTC->FREQ_BKP = m | (n << 6) | (p << 16) | (q << 18) | (h << 22) | (b1 << 26) | (b2 << 29); #endif return 0; } #endif void powerctrl_enter_stop_mode(void) { // Disable IRQs so that the IRQ that wakes the device from stop mode is not // executed until after the clocks are reconfigured uint32_t irq_state = disable_irq(); #if defined(MICROPY_BOARD_ENTER_STOP) MICROPY_BOARD_ENTER_STOP #endif #if defined(STM32L4) // Configure the MSI as the clock source after waking up __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); #endif #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); #endif # if defined(STM32F7) HAL_PWR_EnterSTOPMode((PWR_CR1_LPDS | PWR_CR1_LPUDS | PWR_CR1_FPDS | PWR_CR1_UDEN), PWR_STOPENTRY_WFI); # else HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); #endif // reconfigure the system clock after waking up #if defined(STM32F0) // Enable HSI48 __HAL_RCC_HSI48_ENABLE(); while (!__HAL_RCC_GET_FLAG(RCC_FLAG_HSI48RDY)) { } // Select HSI48 as system clock source MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_HSI48); while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI48) { } #else #if !defined(STM32L4) // enable clock __HAL_RCC_HSE_CONFIG(MICROPY_HW_RCC_HSE_STATE); #if MICROPY_HW_CLK_USE_HSI __HAL_RCC_HSI_ENABLE(); #endif while (!__HAL_RCC_GET_FLAG(MICROPY_HW_RCC_FLAG_HSxRDY)) { } #endif // enable PLL __HAL_RCC_PLL_ENABLE(); while (!__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)) { } // select PLL as system clock source MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK); #if defined(STM32H7) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) { } #elif defined(STM32WB) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) { } #else while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) { } #endif #if defined(STM32F7) if (RCC->DCKCFGR2 & RCC_DCKCFGR2_CK48MSEL) { // Enable PLLSAI if it is selected as 48MHz source RCC->CR |= RCC_CR_PLLSAION; while (!(RCC->CR & RCC_CR_PLLSAIRDY)) { } } #endif #if defined(STM32L4) // Enable PLLSAI1 for peripherals that use it RCC->CR |= RCC_CR_PLLSAI1ON; while (!(RCC->CR & RCC_CR_PLLSAI1RDY)) { } #endif #endif #if defined(MICROPY_BOARD_LEAVE_STOP) MICROPY_BOARD_LEAVE_STOP #endif // Enable IRQs now that all clocks are reconfigured enable_irq(irq_state); } void powerctrl_enter_standby_mode(void) { rtc_init_finalise(); #if defined(MICROPY_BOARD_ENTER_STANDBY) MICROPY_BOARD_ENTER_STANDBY #endif // We need to clear the PWR wake-up-flag before entering standby, since // the flag may have been set by a previous wake-up event. Furthermore, // we need to disable the wake-up sources while clearing this flag, so // that if a source is active it does actually wake the device. // See section 5.3.7 of RM0090. // Note: we only support RTC ALRA, ALRB, WUT and TS. // TODO support TAMP and WKUP (PA0 external pin). #if defined(STM32F0) || defined(STM32L0) #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_WUTIE | RTC_CR_TSIE) #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TSF) #else #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_ALRBIE | RTC_CR_WUTIE | RTC_CR_TSIE) #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_ALRBF | RTC_ISR_WUTF | RTC_ISR_TSF) #endif // save RTC interrupts uint32_t save_irq_bits = RTC->CR & CR_BITS; // disable RTC interrupts RTC->CR &= ~CR_BITS; // clear RTC wake-up flags RTC->ISR &= ~ISR_BITS; #if defined(STM32F7) // disable wake-up flags PWR->CSR2 &= ~(PWR_CSR2_EWUP6 | PWR_CSR2_EWUP5 | PWR_CSR2_EWUP4 | PWR_CSR2_EWUP3 | PWR_CSR2_EWUP2 | PWR_CSR2_EWUP1); // clear global wake-up flag PWR->CR2 |= PWR_CR2_CWUPF6 | PWR_CR2_CWUPF5 | PWR_CR2_CWUPF4 | PWR_CR2_CWUPF3 | PWR_CR2_CWUPF2 | PWR_CR2_CWUPF1; #elif defined(STM32H7) // TODO #elif defined(STM32L4) || defined(STM32WB) // clear all wake-up flags PWR->SCR |= PWR_SCR_CWUF5 | PWR_SCR_CWUF4 | PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1; // TODO #else // clear global wake-up flag PWR->CR |= PWR_CR_CWUF; #endif // enable previously-enabled RTC interrupts RTC->CR |= save_irq_bits; #if defined(STM32F7) // Enable the internal (eg RTC) wakeup sources // See Errata 2.2.2 "Wakeup from Standby mode when the back-up SRAM regulator is enabled" PWR->CSR1 |= PWR_CSR1_EIWUP; #endif // enter standby mode HAL_PWR_EnterSTANDBYMode(); // we never return; MCU is reset on exit from standby } micropython-1.12/ports/stm32/powerctrl.h000066400000000000000000000034621357706137100203400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_POWERCTRL_H #define MICROPY_INCLUDED_STM32_POWERCTRL_H #include void SystemClock_Config(void); NORETURN void powerctrl_mcu_reset(void); NORETURN void powerctrl_enter_bootloader(uint32_t r0, uint32_t bl_addr); void powerctrl_check_enter_bootloader(void); int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai); int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2); void powerctrl_enter_stop_mode(void); void powerctrl_enter_standby_mode(void); #endif // MICROPY_INCLUDED_STM32_POWERCTRL_H micropython-1.12/ports/stm32/powerctrlboot.c000066400000000000000000000145371357706137100212240ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mphal.h" #include "powerctrl.h" static inline void powerctrl_config_systick(void) { // Configure SYSTICK to run at 1kHz (1ms interval) SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; SysTick_Config(HAL_RCC_GetHCLKFreq() / 1000); NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_SYSTICK); } #if defined(STM32F0) void SystemClock_Config(void) { // Enable power control peripheral __HAL_RCC_PWR_CLK_ENABLE(); // Set flash latency to 1 because SYSCLK > 24MHz FLASH->ACR = (FLASH->ACR & ~0x7) | 0x1; #if MICROPY_HW_CLK_USE_HSI48 // Use the 48MHz internal oscillator // HAL does not support RCC CFGR SW=3 (HSI48 direct to SYSCLK) // so use HSI48 -> PREDIV(divide by 2) -> PLL (mult by 2) -> SYSCLK. RCC->CR2 |= RCC_CR2_HSI48ON; while ((RCC->CR2 & RCC_CR2_HSI48RDY) == 0) { // Wait for HSI48 to be ready } RCC->CFGR = 0 << RCC_CFGR_PLLMUL_Pos | 3 << RCC_CFGR_PLLSRC_Pos; // PLL mult by 2, src = HSI48/PREDIV RCC->CFGR2 = 1; // Input clock divided by 2 #elif MICROPY_HW_CLK_USE_HSE // Use HSE and the PLL to get a 48MHz SYSCLK #if MICROPY_HW_CLK_USE_BYPASS RCC->CR |= RCC_CR_HSEBYP; #endif RCC->CR |= RCC_CR_HSEON; while ((RCC->CR & RCC_CR_HSERDY) == 0) { // Wait for HSE to be ready } RCC->CFGR = ((48000000 / HSE_VALUE) - 2) << RCC_CFGR_PLLMUL_Pos | 2 << RCC_CFGR_PLLSRC_Pos; RCC->CFGR2 = 0; // Input clock not divided #elif MICROPY_HW_CLK_USE_HSI // Use the 8MHz internal oscillator and the PLL to get a 48MHz SYSCLK RCC->CR |= RCC_CR_HSION; while ((RCC->CR & RCC_CR_HSIRDY) == 0) { // Wait for HSI to be ready } RCC->CFGR = 4 << RCC_CFGR_PLLMUL_Pos | 1 << RCC_CFGR_PLLSRC_Pos; // PLL mult by 6, src = HSI RCC->CFGR2 = 0; // Input clock not divided #else #error System clock not specified #endif RCC->CR |= RCC_CR_PLLON; // Turn PLL on while ((RCC->CR & RCC_CR_PLLRDY) == 0) { // Wait for PLL to lock } const uint32_t sysclk_src = 2; // Select SYSCLK source RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { // Wait for SYSCLK source to change } SystemCoreClockUpdate(); powerctrl_config_systick(); } #elif defined(STM32L0) void SystemClock_Config(void) { // Enable power control peripheral __HAL_RCC_PWR_CLK_ENABLE(); // Set flash latency to 1 because SYSCLK > 16MHz FLASH->ACR |= FLASH_ACR_LATENCY; // Enable the 16MHz internal oscillator RCC->CR |= RCC_CR_HSION; while (!(RCC->CR & RCC_CR_HSIRDY)) { } // Use HSI16 and the PLL to get a 32MHz SYSCLK RCC->CFGR = 1 << RCC_CFGR_PLLDIV_Pos | 1 << RCC_CFGR_PLLMUL_Pos; RCC->CR |= RCC_CR_PLLON; while (!(RCC->CR & RCC_CR_PLLRDY)) { // Wait for PLL to lock } const uint32_t sysclk_src = 3; // Select SYSCLK source RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { // Wait for SYSCLK source to change } SystemCoreClockUpdate(); powerctrl_config_systick(); #if MICROPY_HW_ENABLE_RNG || MICROPY_HW_ENABLE_USB // Enable the 48MHz internal oscillator RCC->CRRCR |= RCC_CRRCR_HSI48ON; RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48; while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) { // Wait for HSI48 to be ready } // Select RC48 as HSI48 for USB and RNG RCC->CCIPR |= RCC_CCIPR_HSI48SEL; #if MICROPY_HW_ENABLE_USB // Synchronise HSI48 with 1kHz USB SoF __HAL_RCC_CRS_CLK_ENABLE(); CRS->CR = 0x20 << CRS_CR_TRIM_Pos; CRS->CFGR = 2 << CRS_CFGR_SYNCSRC_Pos | 0x22 << CRS_CFGR_FELIM_Pos | __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000) << CRS_CFGR_RELOAD_Pos; #endif #endif } #elif defined(STM32WB) void SystemClock_Config(void) { // Enable the 32MHz external oscillator RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR & RCC_CR_HSERDY)) { } // Use HSE and the PLL to get a 64MHz SYSCLK #define PLLM (HSE_VALUE / 8000000) // VCO input is 8MHz #define PLLN (24) // 24*8MHz = 192MHz #define PLLQ (4) // f_Q = 48MHz #define PLLR (3) // f_R = 64MHz RCC->PLLCFGR = (PLLR - 1) << RCC_PLLCFGR_PLLR_Pos | RCC_PLLCFGR_PLLREN | (PLLQ - 1) << RCC_PLLCFGR_PLLQ_Pos | RCC_PLLCFGR_PLLQEN | PLLN << RCC_PLLCFGR_PLLN_Pos | (PLLM - 1) << RCC_PLLCFGR_PLLM_Pos | 3 << RCC_PLLCFGR_PLLSRC_Pos; RCC->CR |= RCC_CR_PLLON; while (!(RCC->CR & RCC_CR_PLLRDY)) { // Wait for PLL to lock } const uint32_t sysclk_src = 3; // Set divider for HCLK2 to 2 so f_HCLK2 = 32MHz RCC->EXTCFGR = 8 << RCC_EXTCFGR_C2HPRE_Pos; // Set flash latency to 3 because SYSCLK > 54MHz FLASH->ACR |= 3 << FLASH_ACR_LATENCY_Pos; // Select SYSCLK source RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { // Wait for SYSCLK source to change } // Select PLLQ as 48MHz source for USB and RNG RCC->CCIPR = 2 << RCC_CCIPR_CLK48SEL_Pos; SystemCoreClockUpdate(); powerctrl_config_systick(); } #endif micropython-1.12/ports/stm32/pyb_can.c000066400000000000000000001061531357706137100177260ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/objarray.h" #include "py/runtime.h" #include "py/gc.h" #include "py/binary.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "bufhelper.h" #include "can.h" #include "irq.h" #if MICROPY_HW_ENABLE_CAN #if MICROPY_HW_ENABLE_FDCAN #define CAN_MAX_FILTER (64) #define CAN_FIFO0 FDCAN_RX_FIFO0 #define CAN_FIFO1 FDCAN_RX_FIFO1 #define CAN_FILTER_FIFO0 (0) // Default timings; 125Kbps assuming 48MHz clock #define CAN_DEFAULT_PRESCALER (32) #define CAN_DEFAULT_SJW (1) #define CAN_DEFAULT_BS1 (8) #define CAN_DEFAULT_BS2 (3) #define CAN_MODE_NORMAL FDCAN_MODE_NORMAL #define CAN_MODE_LOOPBACK FDCAN_MODE_EXTERNAL_LOOPBACK #define CAN_MODE_SILENT FDCAN_MODE_BUS_MONITORING #define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK #define CAN1_RX0_IRQn FDCAN1_IT0_IRQn #define CAN1_RX1_IRQn FDCAN1_IT1_IRQn #define CAN2_RX0_IRQn FDCAN2_IT0_IRQn #define CAN2_RX1_IRQn FDCAN2_IT1_IRQn #define CAN_IT_FIFO0_FULL FDCAN_IT_RX_FIFO0_FULL #define CAN_IT_FIFO1_FULL FDCAN_IT_RX_FIFO1_FULL #define CAN_IT_FIFO0_OVRF FDCAN_IT_RX_FIFO0_MESSAGE_LOST #define CAN_IT_FIFO1_OVRF FDCAN_IT_RX_FIFO1_MESSAGE_LOST #define CAN_IT_FIFO0_PENDING FDCAN_IT_RX_FIFO0_NEW_MESSAGE #define CAN_IT_FIFO1_PENDING FDCAN_IT_RX_FIFO1_NEW_MESSAGE #define CAN_FLAG_FIFO0_FULL FDCAN_FLAG_RX_FIFO0_FULL #define CAN_FLAG_FIFO1_FULL FDCAN_FLAG_RX_FIFO1_FULL #define CAN_FLAG_FIFO0_OVRF FDCAN_FLAG_RX_FIFO0_MESSAGE_LOST #define CAN_FLAG_FIFO1_OVRF FDCAN_FLAG_RX_FIFO1_MESSAGE_LOST #define __HAL_CAN_ENABLE_IT __HAL_FDCAN_ENABLE_IT #define __HAL_CAN_DISABLE_IT __HAL_FDCAN_DISABLE_IT #define __HAL_CAN_CLEAR_FLAG __HAL_FDCAN_CLEAR_FLAG #define __HAL_CAN_MSG_PENDING HAL_FDCAN_GetRxFifoFillLevel // Both banks start at 0 STATIC uint8_t can2_start_bank = 0; #else #define CAN_MAX_FILTER (28) #define CAN_DEFAULT_PRESCALER (100) #define CAN_DEFAULT_SJW (1) #define CAN_DEFAULT_BS1 (6) #define CAN_DEFAULT_BS2 (8) #define CAN_IT_FIFO0_FULL CAN_IT_FF0 #define CAN_IT_FIFO1_FULL CAN_IT_FF1 #define CAN_IT_FIFO0_OVRF CAN_IT_FOV0 #define CAN_IT_FIFO1_OVRF CAN_IT_FOV1 #define CAN_IT_FIFO0_PENDING CAN_IT_FMP0 #define CAN_IT_FIFO1_PENDING CAN_IT_FMP1 #define CAN_FLAG_FIFO0_FULL CAN_FLAG_FF0 #define CAN_FLAG_FIFO1_FULL CAN_FLAG_FF1 #define CAN_FLAG_FIFO0_OVRF CAN_FLAG_FOV0 #define CAN_FLAG_FIFO1_OVRF CAN_FLAG_FOV1 STATIC uint8_t can2_start_bank = 14; #endif STATIC void pyb_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!self->is_enabled) { mp_printf(print, "CAN(%u)", self->can_id); } else { qstr mode; switch (self->can.Init.Mode) { case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; case CAN_MODE_LOOPBACK: mode = MP_QSTR_LOOPBACK; break; case CAN_MODE_SILENT: mode = MP_QSTR_SILENT; break; case CAN_MODE_SILENT_LOOPBACK: default: mode = MP_QSTR_SILENT_LOOPBACK; break; } mp_printf(print, "CAN(%u, CAN.%q, extframe=%q, auto_restart=%q)", self->can_id, mode, self->extframe ? MP_QSTR_True : MP_QSTR_False, #if MICROPY_HW_ENABLE_FDCAN (self->can.Instance->CCCR & FDCAN_CCCR_DAR) ? MP_QSTR_True : MP_QSTR_False #else (self->can.Instance->MCR & CAN_MCR_ABOM) ? MP_QSTR_True : MP_QSTR_False #endif ); } } // init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8) STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, ARG_auto_restart }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_prescaler, MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, { MP_QSTR_auto_restart, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); self->extframe = args[ARG_extframe].u_bool; // set the CAN configuration values memset(&self->can, 0, sizeof(self->can)); // init CAN (if it fails, it's because the port doesn't exist) if (!can_init(self, args[ARG_mode].u_int, args[ARG_prescaler].u_int, args[ARG_sjw].u_int, args[ARG_bs1].u_int, args[ARG_bs2].u_int, args[ARG_auto_restart].u_bool)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", self->can_id)); } return mp_const_none; } // CAN(bus, ...) STATIC mp_obj_t pyb_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // work out port mp_uint_t can_idx; if (mp_obj_is_str(args[0])) { const char *port = mp_obj_str_get_str(args[0]); if (0) { #ifdef MICROPY_HW_CAN1_NAME } else if (strcmp(port, MICROPY_HW_CAN1_NAME) == 0) { can_idx = PYB_CAN_1; #endif #ifdef MICROPY_HW_CAN2_NAME } else if (strcmp(port, MICROPY_HW_CAN2_NAME) == 0) { can_idx = PYB_CAN_2; #endif #ifdef MICROPY_HW_CAN3_NAME } else if (strcmp(port, MICROPY_HW_CAN3_NAME) == 0) { can_idx = PYB_CAN_3; #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%s) doesn't exist", port)); } } else { can_idx = mp_obj_get_int(args[0]); } if (can_idx < 1 || can_idx > MP_ARRAY_SIZE(MP_STATE_PORT(pyb_can_obj_all))) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } pyb_can_obj_t *self; if (MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1] == NULL) { self = m_new_obj(pyb_can_obj_t); self->base.type = &pyb_can_type; self->can_id = can_idx; self->is_enabled = false; MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1] = self; } else { self = MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1]; } if (!self->is_enabled || n_args > 1) { if (self->is_enabled) { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode can_deinit(self); } self->rxcallback0 = mp_const_none; self->rxcallback1 = mp_const_none; self->rx_state0 = RX_STATE_FIFO_EMPTY; self->rx_state1 = RX_STATE_FIFO_EMPTY; if (n_args > 1 || n_kw > 0) { // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_can_init_helper(self, n_args - 1, args + 1, &kw_args); } } return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t pyb_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_can_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_init_obj, 1, pyb_can_init); // deinit() STATIC mp_obj_t pyb_can_deinit(mp_obj_t self_in) { pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); can_deinit(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_deinit_obj, pyb_can_deinit); // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t pyb_can_restart(mp_obj_t self_in) { pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!self->is_enabled) { mp_raise_ValueError(NULL); } CAN_TypeDef *can = self->can.Instance; #if MICROPY_HW_ENABLE_FDCAN can->CCCR |= FDCAN_CCCR_INIT; while ((can->CCCR & FDCAN_CCCR_INIT) == 0) { } can->CCCR &= ~FDCAN_CCCR_INIT; while ((can->CCCR & FDCAN_CCCR_INIT)) { } #else can->MCR |= CAN_MCR_INRQ; while ((can->MSR & CAN_MSR_INAK) == 0) { } can->MCR &= ~CAN_MCR_INRQ; while ((can->MSR & CAN_MSR_INAK)) { } #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_restart_obj, pyb_can_restart); // Get the state of the controller STATIC mp_obj_t pyb_can_state(mp_obj_t self_in) { pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t state = CAN_STATE_STOPPED; if (self->is_enabled) { CAN_TypeDef *can = self->can.Instance; #if MICROPY_HW_ENABLE_FDCAN if (can->PSR & FDCAN_PSR_BO) { state = CAN_STATE_BUS_OFF; } else if (can->PSR & FDCAN_PSR_EP) { state = CAN_STATE_ERROR_PASSIVE; } else if (can->PSR & FDCAN_PSR_EW) { state = CAN_STATE_ERROR_WARNING; } else { state = CAN_STATE_ERROR_ACTIVE; } #else if (can->ESR & CAN_ESR_BOFF) { state = CAN_STATE_BUS_OFF; } else if (can->ESR & CAN_ESR_EPVF) { state = CAN_STATE_ERROR_PASSIVE; } else if (can->ESR & CAN_ESR_EWGF) { state = CAN_STATE_ERROR_WARNING; } else { state = CAN_STATE_ERROR_ACTIVE; } #endif } return MP_OBJ_NEW_SMALL_INT(state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_state_obj, pyb_can_state); // Get info about error states and TX/RX buffers STATIC mp_obj_t pyb_can_info(size_t n_args, const mp_obj_t *args) { #if MICROPY_HW_ENABLE_FDCAN // TODO implement for FDCAN return mp_const_none; #else pyb_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; if (n_args == 1) { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); } else { if (!mp_obj_is_type(args[1], &mp_type_list)) { mp_raise_TypeError(NULL); } list = MP_OBJ_TO_PTR(args[1]); if (list->len < 8) { mp_raise_ValueError(NULL); } } CAN_TypeDef *can = self->can.Instance; uint32_t esr = can->ESR; list->items[0] = MP_OBJ_NEW_SMALL_INT(esr >> CAN_ESR_TEC_Pos & 0xff); list->items[1] = MP_OBJ_NEW_SMALL_INT(esr >> CAN_ESR_REC_Pos & 0xff); list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive); list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off); int n_tx_pending = 0x01121223 >> ((can->TSR >> CAN_TSR_TME_Pos & 7) << 2) & 0xf; list->items[5] = MP_OBJ_NEW_SMALL_INT(n_tx_pending); list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3); list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); return MP_OBJ_FROM_PTR(list); #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_can_info_obj, 1, 2, pyb_can_info); // any(fifo) - return `True` if any message waiting on the FIFO, else `False` STATIC mp_obj_t pyb_can_any(mp_obj_t self_in, mp_obj_t fifo_in) { pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t fifo = mp_obj_get_int(fifo_in); if (fifo == 0) { if (__HAL_CAN_MSG_PENDING(&self->can, CAN_FIFO0) != 0) { return mp_const_true; } } else { if (__HAL_CAN_MSG_PENDING(&self->can, CAN_FIFO1) != 0) { return mp_const_true; } } return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_any_obj, pyb_can_any); // send(send, addr, *, timeout=5000) STATIC mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr }; static const mp_arg_t allowed_args[] = { { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; // parse args pyb_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the buffer to send from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(args[ARG_data].u_obj, &bufinfo, data); if (bufinfo.len > 8) { mp_raise_ValueError("CAN data field too long"); } // send the data CanTxMsgTypeDef tx_msg; #if MICROPY_HW_ENABLE_FDCAN uint8_t tx_data[8]; tx_msg.MessageMarker = 0; tx_msg.ErrorStateIndicator = FDCAN_ESI_ACTIVE; tx_msg.BitRateSwitch = FDCAN_BRS_OFF; tx_msg.FDFormat = FDCAN_CLASSIC_CAN; tx_msg.TxEventFifoControl = FDCAN_NO_TX_EVENTS; tx_msg.DataLength = (bufinfo.len << 16); // TODO DLC for len > 8 if (self->extframe) { tx_msg.Identifier = args[ARG_id].u_int & 0x1FFFFFFF; tx_msg.IdType = FDCAN_EXTENDED_ID; } else { tx_msg.Identifier = args[ARG_id].u_int & 0x7FF; tx_msg.IdType = FDCAN_STANDARD_ID; } if (args[ARG_rtr].u_bool == false) { tx_msg.TxFrameType = FDCAN_DATA_FRAME; } else { tx_msg.TxFrameType = FDCAN_REMOTE_FRAME; } #else tx_msg.DLC = bufinfo.len; uint8_t *tx_data = tx_msg.Data; // Data is uint32_t but holds only 1 byte if (self->extframe) { tx_msg.ExtId = args[ARG_id].u_int & 0x1FFFFFFF; tx_msg.IDE = CAN_ID_EXT; } else { tx_msg.StdId = args[ARG_id].u_int & 0x7FF; tx_msg.IDE = CAN_ID_STD; } if (args[ARG_rtr].u_bool == false) { tx_msg.RTR = CAN_RTR_DATA; } else { tx_msg.RTR = CAN_RTR_REMOTE; } #endif for (mp_uint_t i = 0; i < bufinfo.len; i++) { tx_data[i] = ((byte*)bufinfo.buf)[i]; } HAL_StatusTypeDef status; #if MICROPY_HW_ENABLE_FDCAN status = HAL_FDCAN_AddMessageToTxFifoQ(&self->can, &tx_msg, tx_data); #else self->can.pTxMsg = &tx_msg; status = CAN_Transmit(&self->can, args[ARG_timeout].u_int); #endif if (status != HAL_OK) { mp_hal_raise(status); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_send_obj, 1, pyb_can_send); // recv(fifo, list=None, *, timeout=5000) STATIC mp_obj_t pyb_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_fifo, ARG_list, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args pyb_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // receive the data CanRxMsgTypeDef rx_msg; #if MICROPY_HW_ENABLE_FDCAN uint8_t rx_data[8]; #else uint8_t *rx_data = rx_msg.Data; #endif mp_uint_t fifo = args[ARG_fifo].u_int; if (fifo == 0) { fifo = CAN_FIFO0; } else if (fifo == 1) { fifo = CAN_FIFO1; } else { mp_raise_TypeError(NULL); } int ret = can_receive(&self->can, fifo, &rx_msg, rx_data, args[ARG_timeout].u_int); if (ret < 0) { mp_raise_OSError(-ret); } #if MICROPY_HW_ENABLE_FDCAN uint32_t rx_dlc = rx_msg.DataLength; #else uint32_t rx_dlc = rx_msg.DLC; #endif // Manage the rx state machine if ((fifo == CAN_FIFO0 && self->rxcallback0 != mp_const_none) || (fifo == CAN_FIFO1 && self->rxcallback1 != mp_const_none)) { byte *state = (fifo == CAN_FIFO0) ? &self->rx_state0 : &self->rx_state1; switch (*state) { case RX_STATE_FIFO_EMPTY: break; case RX_STATE_MESSAGE_PENDING: if (__HAL_CAN_MSG_PENDING(&self->can, fifo) == 0) { // Fifo is empty __HAL_CAN_ENABLE_IT(&self->can, (fifo == CAN_FIFO0) ? CAN_IT_FIFO0_PENDING : CAN_IT_FIFO1_PENDING); *state = RX_STATE_FIFO_EMPTY; } break; case RX_STATE_FIFO_FULL: __HAL_CAN_ENABLE_IT(&self->can, (fifo == CAN_FIFO0) ? CAN_IT_FIFO0_FULL : CAN_IT_FIFO1_FULL); *state = RX_STATE_MESSAGE_PENDING; break; case RX_STATE_FIFO_OVERFLOW: __HAL_CAN_ENABLE_IT(&self->can, (fifo == CAN_FIFO0) ? CAN_IT_FIFO0_OVRF : CAN_IT_FIFO1_OVRF); __HAL_CAN_ENABLE_IT(&self->can, (fifo == CAN_FIFO0) ? CAN_IT_FIFO0_FULL : CAN_IT_FIFO1_FULL); *state = RX_STATE_MESSAGE_PENDING; break; } } // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; mp_obj_t *items; if (ret_obj == mp_const_none) { ret_obj = mp_obj_new_tuple(4, NULL); items = ((mp_obj_tuple_t*)MP_OBJ_TO_PTR(ret_obj))->items; items[3] = mp_obj_new_bytes(rx_data, rx_dlc); } else { // User should provide a list of length at least 4 to hold the values if (!mp_obj_is_type(ret_obj, &mp_type_list)) { mp_raise_TypeError(NULL); } mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); if (list->len < 4) { mp_raise_ValueError(NULL); } items = list->items; // Fourth element must be a memoryview which we assume points to a // byte-like array which is large enough, and then we resize it inplace if (!mp_obj_is_type(items[3], &mp_type_memoryview)) { mp_raise_TypeError(NULL); } mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) { mp_raise_ValueError(NULL); } mv->len = rx_dlc; memcpy(mv->items, rx_data, rx_dlc); } // Populate the first 3 values of the tuple/list #if MICROPY_HW_ENABLE_FDCAN items[0] = MP_OBJ_NEW_SMALL_INT(rx_msg.Identifier); items[1] = rx_msg.RxFrameType == FDCAN_REMOTE_FRAME ? mp_const_true : mp_const_false; items[2] = MP_OBJ_NEW_SMALL_INT(rx_msg.FilterIndex); #else items[0] = MP_OBJ_NEW_SMALL_INT((rx_msg.IDE == CAN_ID_STD ? rx_msg.StdId : rx_msg.ExtId)); items[1] = rx_msg.RTR == CAN_RTR_REMOTE ? mp_const_true : mp_const_false; items[2] = MP_OBJ_NEW_SMALL_INT(rx_msg.FMI); #endif // Return the result return ret_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_recv_obj, 1, pyb_can_recv); // initfilterbanks(n) STATIC mp_obj_t pyb_can_initfilterbanks(mp_obj_t self, mp_obj_t bank_in) { #if MICROPY_HW_ENABLE_FDCAN can2_start_bank = 0; #else can2_start_bank = mp_obj_get_int(bank_in); #endif for (int f = 0; f < CAN_MAX_FILTER; f++) { can_clearfilter(self, f, can2_start_bank); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_initfilterbanks_fun_obj, pyb_can_initfilterbanks); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pyb_can_initfilterbanks_obj, MP_ROM_PTR(&pyb_can_initfilterbanks_fun_obj)); STATIC mp_obj_t pyb_can_clearfilter(mp_obj_t self_in, mp_obj_t bank_in) { pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t f = mp_obj_get_int(bank_in); if (self->can_id == 2) { f += can2_start_bank; } can_clearfilter(self, f, can2_start_bank); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_clearfilter_obj, pyb_can_clearfilter); // setfilter(bank, mode, fifo, params, *, rtr) #define EXTENDED_ID_TO_16BIT_FILTER(id) (((id & 0xC00000) >> 13) | ((id & 0x38000) >> 15)) | 8 STATIC mp_obj_t pyb_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bank, ARG_mode, ARG_fifo, ARG_params, ARG_rtr }; static const mp_arg_t allowed_args[] = { { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_FILTER_FIFO0} }, { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; // parse args pyb_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); #if MICROPY_HW_ENABLE_FDCAN FDCAN_FilterTypeDef filter = {0}; filter.IdType = FDCAN_STANDARD_ID; // TODO check filter index filter.FilterIndex = args[ARG_bank].u_int; // Check filter mode if (((args[ARG_mode].u_int != FDCAN_FILTER_RANGE) && (args[ARG_mode].u_int != FDCAN_FILTER_DUAL) && (args[ARG_mode].u_int != FDCAN_FILTER_MASK))) { goto error; } // Check FIFO index. if (args[ARG_fifo].u_int == 0) { filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; } else if (args[ARG_fifo].u_int == 1) { filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1; } else { goto error; } size_t len; mp_obj_t *params; mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); if (len != 2) { // Check params len goto error; } filter.FilterID1 = mp_obj_get_int(params[0]); filter.FilterID2 = mp_obj_get_int(params[1]); filter.FilterType = args[ARG_mode].u_int; HAL_FDCAN_ConfigFilter(&self->can, &filter); #else size_t len; size_t rtr_len; mp_uint_t rtr_masks[4] = {0, 0, 0, 0}; mp_obj_t *rtr_flags; mp_obj_t *params; mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); if (args[ARG_rtr].u_obj != MP_OBJ_NULL){ mp_obj_get_array(args[ARG_rtr].u_obj, &rtr_len, &rtr_flags); } CAN_FilterConfTypeDef filter; if (args[ARG_mode].u_int == MASK16 || args[ARG_mode].u_int == LIST16) { if (len != 4) { goto error; } filter.FilterScale = CAN_FILTERSCALE_16BIT; if (self->extframe) { if (args[ARG_rtr].u_obj != MP_OBJ_NULL) { if (args[ARG_mode].u_int == MASK16) { rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0; rtr_masks[1] = 0x02; rtr_masks[2] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0; rtr_masks[3] = 0x02; } else { // LIST16 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0; rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0; rtr_masks[2] = mp_obj_get_int(rtr_flags[2]) ? 0x02 : 0; rtr_masks[3] = mp_obj_get_int(rtr_flags[3]) ? 0x02 : 0; } } filter.FilterIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[0])) | rtr_masks[0]; // id1 filter.FilterMaskIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[1])) | rtr_masks[1]; // mask1 filter.FilterIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[2])) | rtr_masks[2]; // id2 filter.FilterMaskIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[3])) | rtr_masks[3]; // mask2 } else { // Basic frames if (args[ARG_rtr].u_obj != MP_OBJ_NULL) { if (args[ARG_mode].u_int == MASK16) { rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x10 : 0; rtr_masks[1] = 0x10; rtr_masks[2] = mp_obj_get_int(rtr_flags[1]) ? 0x10 : 0; rtr_masks[3] = 0x10; } else { // LIST16 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x10 : 0; rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x10 : 0; rtr_masks[2] = mp_obj_get_int(rtr_flags[2]) ? 0x10 : 0; rtr_masks[3] = mp_obj_get_int(rtr_flags[3]) ? 0x10 : 0; } } filter.FilterIdLow = (mp_obj_get_int(params[0]) << 5) | rtr_masks[0]; // id1 filter.FilterMaskIdLow = (mp_obj_get_int(params[1]) << 5) | rtr_masks[1]; // mask1 filter.FilterIdHigh = (mp_obj_get_int(params[2]) << 5) | rtr_masks[2]; // id2 filter.FilterMaskIdHigh = (mp_obj_get_int(params[3]) << 5) | rtr_masks[3]; // mask2 } if (args[ARG_mode].u_int == MASK16) { filter.FilterMode = CAN_FILTERMODE_IDMASK; } if (args[ARG_mode].u_int == LIST16) { filter.FilterMode = CAN_FILTERMODE_IDLIST; } } else if (args[ARG_mode].u_int == MASK32 || args[ARG_mode].u_int == LIST32) { if (len != 2) { goto error; } filter.FilterScale = CAN_FILTERSCALE_32BIT; if (args[ARG_rtr].u_obj != MP_OBJ_NULL) { if (args[ARG_mode].u_int == MASK32) { rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0; rtr_masks[1] = 0x02; } else { // LIST32 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0; rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0; } } filter.FilterIdHigh = (mp_obj_get_int(params[0]) & 0x1FFFE000) >> 13; filter.FilterIdLow = (((mp_obj_get_int(params[0]) & 0x00001FFF) << 3) | 4) | rtr_masks[0]; filter.FilterMaskIdHigh = (mp_obj_get_int(params[1]) & 0x1FFFE000 ) >> 13; filter.FilterMaskIdLow = (((mp_obj_get_int(params[1]) & 0x00001FFF) << 3) | 4) | rtr_masks[1]; if (args[ARG_mode].u_int == MASK32) { filter.FilterMode = CAN_FILTERMODE_IDMASK; } if (args[ARG_mode].u_int == LIST32) { filter.FilterMode = CAN_FILTERMODE_IDLIST; } } else { goto error; } filter.FilterFIFOAssignment = args[ARG_fifo].u_int; filter.FilterNumber = args[ARG_bank].u_int; if (self->can_id == 1) { if (filter.FilterNumber >= can2_start_bank) { goto error; } } else if (self->can_id == 2) { filter.FilterNumber = filter.FilterNumber + can2_start_bank; if (filter.FilterNumber > 27) { goto error; } } else { if (filter.FilterNumber > 13) { // CAN3 is independant and has its own 14 filters. goto error; } } filter.FilterActivation = ENABLE; filter.BankNumber = can2_start_bank; HAL_CAN_ConfigFilter(&self->can, &filter); #endif return mp_const_none; error: mp_raise_ValueError("CAN filter parameter error"); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_setfilter_obj, 1, pyb_can_setfilter); STATIC mp_obj_t pyb_can_rxcallback(mp_obj_t self_in, mp_obj_t fifo_in, mp_obj_t callback_in) { pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t fifo = mp_obj_get_int(fifo_in); mp_obj_t *callback; callback = (fifo == 0) ? &self->rxcallback0 : &self->rxcallback1; if (callback_in == mp_const_none) { __HAL_CAN_DISABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_PENDING : CAN_IT_FIFO1_PENDING); __HAL_CAN_DISABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_FULL : CAN_IT_FIFO1_FULL); __HAL_CAN_DISABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_OVRF : CAN_IT_FIFO1_OVRF); __HAL_CAN_CLEAR_FLAG(&self->can, (fifo == CAN_FIFO0) ? CAN_FLAG_FIFO0_FULL : CAN_FLAG_FIFO1_FULL); __HAL_CAN_CLEAR_FLAG(&self->can, (fifo == CAN_FIFO0) ? CAN_FLAG_FIFO0_OVRF : CAN_FLAG_FIFO1_OVRF); *callback = mp_const_none; } else if (*callback != mp_const_none) { // Rx call backs has already been initialized // only the callback function should be changed *callback = callback_in; } else if (mp_obj_is_callable(callback_in)) { *callback = callback_in; uint32_t irq = 0; if (self->can_id == PYB_CAN_1) { irq = (fifo == 0) ? CAN1_RX0_IRQn : CAN1_RX1_IRQn; #if defined(CAN2) } else if (self->can_id == PYB_CAN_2) { irq = (fifo == 0) ? CAN2_RX0_IRQn : CAN2_RX1_IRQn; #endif #if defined(CAN3) } else { irq = (fifo == 0) ? CAN3_RX0_IRQn : CAN3_RX1_IRQn; #endif } NVIC_SetPriority(irq, IRQ_PRI_CAN); HAL_NVIC_EnableIRQ(irq); __HAL_CAN_ENABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_PENDING : CAN_IT_FIFO1_PENDING); __HAL_CAN_ENABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_FULL : CAN_IT_FIFO1_FULL); __HAL_CAN_ENABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_OVRF : CAN_IT_FIFO1_OVRF); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_can_rxcallback_obj, pyb_can_rxcallback); STATIC const mp_rom_map_elem_t pyb_can_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_can_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&pyb_can_restart_obj) }, { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&pyb_can_state_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_can_info_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_can_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_can_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) }, { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) }, { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) }, { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&pyb_can_rxcallback_obj) }, #if MICROPY_HW_ENABLE_FDCAN { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_LOOPBACK) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_SILENT) }, { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_SILENT_LOOPBACK) }, { MP_ROM_QSTR(MP_QSTR_RANGE), MP_ROM_INT(FDCAN_FILTER_RANGE) }, { MP_ROM_QSTR(MP_QSTR_DUAL), MP_ROM_INT(FDCAN_FILTER_DUAL) }, { MP_ROM_QSTR(MP_QSTR_MASK), MP_ROM_INT(FDCAN_FILTER_MASK) }, #else // class constants // Note: we use the ST constants >> 4 so they fit in a small-int. The // right-shift is undone when the constants are used in the init function. { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL >> 4) }, { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_LOOPBACK >> 4) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_SILENT >> 4) }, { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_SILENT_LOOPBACK >> 4) }, { MP_ROM_QSTR(MP_QSTR_MASK16), MP_ROM_INT(MASK16) }, { MP_ROM_QSTR(MP_QSTR_LIST16), MP_ROM_INT(LIST16) }, { MP_ROM_QSTR(MP_QSTR_MASK32), MP_ROM_INT(MASK32) }, { MP_ROM_QSTR(MP_QSTR_LIST32), MP_ROM_INT(LIST32) }, #endif // values for CAN.state() { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_ERROR_ACTIVE) }, { MP_ROM_QSTR(MP_QSTR_ERROR_WARNING), MP_ROM_INT(CAN_STATE_ERROR_WARNING) }, { MP_ROM_QSTR(MP_QSTR_ERROR_PASSIVE), MP_ROM_INT(CAN_STATE_ERROR_PASSIVE) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_can_locals_dict, pyb_can_locals_dict_table); STATIC mp_uint_t can_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { uintptr_t flags = arg; ret = 0; if ((flags & MP_STREAM_POLL_RD) && ((__HAL_CAN_MSG_PENDING(&self->can, CAN_FIFO0) != 0) || (__HAL_CAN_MSG_PENDING(&self->can, CAN_FIFO1) != 0))) { ret |= MP_STREAM_POLL_RD; } #if MICROPY_HW_ENABLE_FDCAN if ((flags & MP_STREAM_POLL_WR) && (self->can.Instance->IR & FDCAN_IR_TFE)) #else if ((flags & MP_STREAM_POLL_WR) && (self->can.Instance->TSR & CAN_TSR_TME)) #endif { ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; ret = -1; } return ret; } void pyb_can_handle_callback(pyb_can_obj_t *self, uint fifo_id, mp_obj_t callback, mp_obj_t irq_reason) { if (callback != mp_const_none) { mp_sched_lock(); gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_2(callback, MP_OBJ_FROM_PTR(self), irq_reason); nlr_pop(); } else { // Uncaught exception; disable the callback so it doesn't run again. pyb_can_rxcallback(MP_OBJ_FROM_PTR(self), MP_OBJ_NEW_SMALL_INT(fifo_id), mp_const_none); mp_printf(MICROPY_ERROR_PRINTER, "uncaught exception in CAN(%u) rx interrupt handler\n", self->can_id); mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } gc_unlock(); mp_sched_unlock(); } } STATIC const mp_stream_p_t can_stream_p = { //.read = can_read, // is read sensible for CAN? //.write = can_write, // is write sensible for CAN? .ioctl = can_ioctl, .is_text = false, }; const mp_obj_type_t pyb_can_type = { { &mp_type_type }, .name = MP_QSTR_CAN, .print = pyb_can_print, .make_new = pyb_can_make_new, .protocol = &can_stream_p, .locals_dict = (mp_obj_dict_t*)&pyb_can_locals_dict, }; #endif // MICROPY_HW_ENABLE_CAN micropython-1.12/ports/stm32/pyb_i2c.c000066400000000000000000001125531357706137100176430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "irq.h" #include "pin.h" #include "bufhelper.h" #include "dma.h" #include "i2c.h" #if MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C /// \moduleref pyb /// \class I2C - a two-wire serial protocol /// /// I2C is a two-wire protocol for communicating between devices. At the physical /// level it consists of 2 wires: SCL and SDA, the clock and data lines respectively. /// /// I2C objects are created attached to a specific bus. They can be initialised /// when created, or initialised later on: /// /// from pyb import I2C /// /// i2c = I2C(1) # create on bus 1 /// i2c = I2C(1, I2C.MASTER) # create and init as a master /// i2c.init(I2C.MASTER, baudrate=20000) # init as a master /// i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address /// i2c.deinit() # turn off the peripheral /// /// Printing the i2c object gives you information about its configuration. /// /// Basic methods for slave are send and recv: /// /// i2c.send('abc') # send 3 bytes /// i2c.send(0x42) # send a single byte, given by the number /// data = i2c.recv(3) # receive 3 bytes /// /// To receive inplace, first create a bytearray: /// /// data = bytearray(3) # create a buffer /// i2c.recv(data) # receive 3 bytes, writing them into data /// /// You can specify a timeout (in ms): /// /// i2c.send(b'123', timeout=2000) # timout after 2 seconds /// /// A master must specify the recipient's address: /// /// i2c.init(I2C.MASTER) /// i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42 /// i2c.send(b'456', addr=0x42) # keyword for address /// /// Master also has other methods: /// /// i2c.is_ready(0x42) # check if slave 0x42 is ready /// i2c.scan() # scan for slaves on the bus, returning /// # a list of valid addresses /// i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42, /// # starting at address 2 in the slave /// i2c.mem_write('abc', 0x42, 2, timeout=1000) #define PYB_I2C_MASTER (0) #define PYB_I2C_SLAVE (1) #define PYB_I2C_SPEED_STANDARD (100000L) #define PYB_I2C_SPEED_FULL (400000L) #define PYB_I2C_SPEED_FAST (1000000L) #if defined(MICROPY_HW_I2C1_SCL) I2C_HandleTypeDef I2CHandle1 = {.Instance = NULL}; #endif #if defined(MICROPY_HW_I2C2_SCL) I2C_HandleTypeDef I2CHandle2 = {.Instance = NULL}; #endif #if defined(MICROPY_HW_I2C3_SCL) I2C_HandleTypeDef I2CHandle3 = {.Instance = NULL}; #endif #if defined(MICROPY_HW_I2C4_SCL) I2C_HandleTypeDef I2CHandle4 = {.Instance = NULL}; #endif STATIC bool pyb_i2c_use_dma[4]; const pyb_i2c_obj_t pyb_i2c_obj[] = { #if defined(MICROPY_HW_I2C1_SCL) {{&pyb_i2c_type}, &I2CHandle1, &dma_I2C_1_TX, &dma_I2C_1_RX, &pyb_i2c_use_dma[0]}, #else {{&pyb_i2c_type}, NULL, NULL, NULL, NULL}, #endif #if defined(MICROPY_HW_I2C2_SCL) {{&pyb_i2c_type}, &I2CHandle2, &dma_I2C_2_TX, &dma_I2C_2_RX, &pyb_i2c_use_dma[1]}, #else {{&pyb_i2c_type}, NULL, NULL, NULL, NULL}, #endif #if defined(MICROPY_HW_I2C3_SCL) {{&pyb_i2c_type}, &I2CHandle3, &dma_I2C_3_TX, &dma_I2C_3_RX, &pyb_i2c_use_dma[2]}, #else {{&pyb_i2c_type}, NULL, NULL, NULL, NULL}, #endif #if defined(MICROPY_HW_I2C4_SCL) {{&pyb_i2c_type}, &I2CHandle4, &dma_I2C_4_TX, &dma_I2C_4_RX, &pyb_i2c_use_dma[3]}, #else {{&pyb_i2c_type}, NULL, NULL, NULL, NULL}, #endif }; #if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) // The STM32F0, F3, F7, H7 and L4 use a TIMINGR register rather than ClockSpeed and // DutyCycle. #define PYB_I2C_TIMINGR (1) #if defined(STM32F746xx) // The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant // defined in the STM32F7Cube file Drivers/BSP/STM32F746G-Discovery/stm32f7456g_discovery.h #define MICROPY_HW_I2C_BAUDRATE_TIMING { \ {PYB_I2C_SPEED_STANDARD, 0x40912732}, \ {PYB_I2C_SPEED_FULL, 0x10911823}, \ {PYB_I2C_SPEED_FAST, 0x00611116}, \ } #define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) #define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FAST) #elif defined(STM32F722xx) || defined(STM32F723xx) \ || defined(STM32F732xx) || defined(STM32F733xx) \ || defined(STM32F765xx) || defined(STM32F767xx) \ || defined(STM32F769xx) // These timing values are for f_I2CCLK=54MHz and are only approximate #define MICROPY_HW_I2C_BAUDRATE_TIMING { \ {PYB_I2C_SPEED_STANDARD, 0xb0420f13}, \ {PYB_I2C_SPEED_FULL, 0x70330309}, \ {PYB_I2C_SPEED_FAST, 0x50100103}, \ } #define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) #define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FAST) #elif defined(STM32H7) // I2C TIMINGs obtained from the STHAL examples. #define MICROPY_HW_I2C_BAUDRATE_TIMING { \ {PYB_I2C_SPEED_STANDARD, 0x40604E73}, \ {PYB_I2C_SPEED_FULL, 0x00901954}, \ {PYB_I2C_SPEED_FAST, 0x10810915}, \ } #define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) #define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FAST) #elif defined(STM32L4) // The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant // defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h #define MICROPY_HW_I2C_BAUDRATE_TIMING {{PYB_I2C_SPEED_STANDARD, 0x90112626}} #define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_STANDARD) #define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_STANDARD) #else #error "no I2C timings for this MCU" #endif STATIC const struct { uint32_t baudrate; uint32_t timing; } pyb_i2c_baudrate_timing[] = MICROPY_HW_I2C_BAUDRATE_TIMING; #define NUM_BAUDRATE_TIMINGS MP_ARRAY_SIZE(pyb_i2c_baudrate_timing) STATIC void i2c_set_baudrate(I2C_InitTypeDef *init, uint32_t baudrate) { for (int i = 0; i < NUM_BAUDRATE_TIMINGS; i++) { if (pyb_i2c_baudrate_timing[i].baudrate == baudrate) { init->Timing = pyb_i2c_baudrate_timing[i].timing; return; } } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Unsupported I2C baudrate: %u", baudrate)); } uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c) { for (int i = 0; i < NUM_BAUDRATE_TIMINGS; i++) { if (pyb_i2c_baudrate_timing[i].timing == i2c->Init.Timing) { return pyb_i2c_baudrate_timing[i].baudrate; } } return 0; } #else #define PYB_I2C_TIMINGR (0) #define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) #define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FULL) STATIC void i2c_set_baudrate(I2C_InitTypeDef *init, uint32_t baudrate) { init->ClockSpeed = baudrate; init->DutyCycle = I2C_DUTYCYCLE_16_9; } uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c) { uint32_t pfreq = i2c->Instance->CR2 & 0x3f; uint32_t ccr = i2c->Instance->CCR & 0xfff; if (i2c->Instance->CCR & 0x8000) { // Fast mode, assume duty cycle of 16/9 return pfreq * 40000 / ccr; } else { // Standard mode return pfreq * 500000 / ccr; } } #endif void i2c_init0(void) { // Initialise the I2C handles. // The structs live on the BSS so all other fields will be zero after a reset. #if defined(MICROPY_HW_I2C1_SCL) I2CHandle1.Instance = I2C1; #endif #if defined(MICROPY_HW_I2C2_SCL) I2CHandle2.Instance = I2C2; #endif #if defined(MICROPY_HW_I2C3_SCL) I2CHandle3.Instance = I2C3; #endif #if defined(MICROPY_HW_I2C4_SCL) I2CHandle4.Instance = I2C4; #endif } void pyb_i2c_init(I2C_HandleTypeDef *i2c) { int i2c_unit; const pin_obj_t *scl_pin; const pin_obj_t *sda_pin; if (0) { #if defined(MICROPY_HW_I2C1_SCL) } else if (i2c == &I2CHandle1) { i2c_unit = 1; scl_pin = MICROPY_HW_I2C1_SCL; sda_pin = MICROPY_HW_I2C1_SDA; __HAL_RCC_I2C1_CLK_ENABLE(); #endif #if defined(MICROPY_HW_I2C2_SCL) } else if (i2c == &I2CHandle2) { i2c_unit = 2; scl_pin = MICROPY_HW_I2C2_SCL; sda_pin = MICROPY_HW_I2C2_SDA; __HAL_RCC_I2C2_CLK_ENABLE(); #endif #if defined(MICROPY_HW_I2C3_SCL) } else if (i2c == &I2CHandle3) { i2c_unit = 3; scl_pin = MICROPY_HW_I2C3_SCL; sda_pin = MICROPY_HW_I2C3_SDA; __HAL_RCC_I2C3_CLK_ENABLE(); #endif #if defined(MICROPY_HW_I2C4_SCL) } else if (i2c == &I2CHandle4) { i2c_unit = 4; scl_pin = MICROPY_HW_I2C4_SCL; sda_pin = MICROPY_HW_I2C4_SDA; __HAL_RCC_I2C4_CLK_ENABLE(); #endif } else { // I2C does not exist for this board (shouldn't get here, should be checked by caller) return; } // init the GPIO lines uint32_t mode = MP_HAL_PIN_MODE_ALT_OPEN_DRAIN; uint32_t pull = MP_HAL_PIN_PULL_NONE; // have external pull-up resistors on both lines mp_hal_pin_config_alt(scl_pin, mode, pull, AF_FN_I2C, i2c_unit); mp_hal_pin_config_alt(sda_pin, mode, pull, AF_FN_I2C, i2c_unit); // init the I2C device if (HAL_I2C_Init(i2c) != HAL_OK) { // init error // TODO should raise an exception, but this function is not necessarily going to be // called via Python, so may not be properly wrapped in an NLR handler printf("OSError: HAL_I2C_Init failed\n"); return; } // invalidate the DMA channels so they are initialised on first use const pyb_i2c_obj_t *self = &pyb_i2c_obj[i2c_unit - 1]; dma_invalidate_channel(self->tx_dma_descr); dma_invalidate_channel(self->rx_dma_descr); if (0) { #if defined(MICROPY_HW_I2C1_SCL) } else if (i2c->Instance == I2C1) { HAL_NVIC_EnableIRQ(I2C1_EV_IRQn); HAL_NVIC_EnableIRQ(I2C1_ER_IRQn); #endif #if defined(MICROPY_HW_I2C2_SCL) } else if (i2c->Instance == I2C2) { HAL_NVIC_EnableIRQ(I2C2_EV_IRQn); HAL_NVIC_EnableIRQ(I2C2_ER_IRQn); #endif #if defined(MICROPY_HW_I2C3_SCL) } else if (i2c->Instance == I2C3) { HAL_NVIC_EnableIRQ(I2C3_EV_IRQn); HAL_NVIC_EnableIRQ(I2C3_ER_IRQn); #endif #if defined(MICROPY_HW_I2C4_SCL) } else if (i2c->Instance == I2C4) { HAL_NVIC_EnableIRQ(I2C4_EV_IRQn); HAL_NVIC_EnableIRQ(I2C4_ER_IRQn); #endif } } void i2c_deinit(I2C_HandleTypeDef *i2c) { HAL_I2C_DeInit(i2c); if (0) { #if defined(MICROPY_HW_I2C1_SCL) } else if (i2c->Instance == I2C1) { __HAL_RCC_I2C1_FORCE_RESET(); __HAL_RCC_I2C1_RELEASE_RESET(); __HAL_RCC_I2C1_CLK_DISABLE(); HAL_NVIC_DisableIRQ(I2C1_EV_IRQn); HAL_NVIC_DisableIRQ(I2C1_ER_IRQn); #endif #if defined(MICROPY_HW_I2C2_SCL) } else if (i2c->Instance == I2C2) { __HAL_RCC_I2C2_FORCE_RESET(); __HAL_RCC_I2C2_RELEASE_RESET(); __HAL_RCC_I2C2_CLK_DISABLE(); HAL_NVIC_DisableIRQ(I2C2_EV_IRQn); HAL_NVIC_DisableIRQ(I2C2_ER_IRQn); #endif #if defined(MICROPY_HW_I2C3_SCL) } else if (i2c->Instance == I2C3) { __HAL_RCC_I2C3_FORCE_RESET(); __HAL_RCC_I2C3_RELEASE_RESET(); __HAL_RCC_I2C3_CLK_DISABLE(); HAL_NVIC_DisableIRQ(I2C3_EV_IRQn); HAL_NVIC_DisableIRQ(I2C3_ER_IRQn); #endif #if defined(MICROPY_HW_I2C4_SCL) } else if (i2c->Instance == I2C4) { __HAL_RCC_I2C4_FORCE_RESET(); __HAL_RCC_I2C4_RELEASE_RESET(); __HAL_RCC_I2C4_CLK_DISABLE(); HAL_NVIC_DisableIRQ(I2C4_EV_IRQn); HAL_NVIC_DisableIRQ(I2C4_ER_IRQn); #endif } } void pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) { I2C_InitTypeDef *init = &self->i2c->Init; init->AddressingMode = I2C_ADDRESSINGMODE_7BIT; init->DualAddressMode = I2C_DUALADDRESS_DISABLED; init->GeneralCallMode = I2C_GENERALCALL_DISABLED; init->NoStretchMode = I2C_NOSTRETCH_DISABLE; init->OwnAddress1 = PYB_I2C_MASTER_ADDRESS; init->OwnAddress2 = 0; // unused if (freq != -1) { i2c_set_baudrate(init, MIN(freq, MICROPY_HW_I2C_BAUDRATE_MAX)); } *self->use_dma = false; // init the I2C bus i2c_deinit(self->i2c); pyb_i2c_init(self->i2c); } STATIC void i2c_reset_after_error(I2C_HandleTypeDef *i2c) { // wait for bus-busy flag to be cleared, with a timeout for (int timeout = 50; timeout > 0; --timeout) { if (!__HAL_I2C_GET_FLAG(i2c, I2C_FLAG_BUSY)) { // stop bit was generated and bus is back to normal return; } mp_hal_delay_ms(1); } // bus was/is busy, need to reset the peripheral to get it to work again i2c_deinit(i2c); pyb_i2c_init(i2c); } void i2c_ev_irq_handler(mp_uint_t i2c_id) { I2C_HandleTypeDef *hi2c; switch (i2c_id) { #if defined(MICROPY_HW_I2C1_SCL) case 1: hi2c = &I2CHandle1; break; #endif #if defined(MICROPY_HW_I2C2_SCL) case 2: hi2c = &I2CHandle2; break; #endif #if defined(MICROPY_HW_I2C3_SCL) case 3: hi2c = &I2CHandle3; break; #endif #if defined(MICROPY_HW_I2C4_SCL) case 4: hi2c = &I2CHandle4; break; #endif default: return; } #if defined(STM32F4) if (hi2c->Instance->SR1 & I2C_FLAG_BTF && hi2c->State == HAL_I2C_STATE_BUSY_TX) { if (hi2c->XferCount != 0U) { hi2c->Instance->DR = *hi2c->pBuffPtr++; hi2c->XferCount--; } else { __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); if (hi2c->XferOptions != I2C_FIRST_FRAME) { hi2c->Instance->CR1 |= I2C_CR1_STOP; } hi2c->Mode = HAL_I2C_MODE_NONE; hi2c->State = HAL_I2C_STATE_READY; } } #else // if not an F4 MCU, use the HAL's IRQ handler HAL_I2C_EV_IRQHandler(hi2c); #endif } void i2c_er_irq_handler(mp_uint_t i2c_id) { I2C_HandleTypeDef *hi2c; switch (i2c_id) { #if defined(MICROPY_HW_I2C1_SCL) case 1: hi2c = &I2CHandle1; break; #endif #if defined(MICROPY_HW_I2C2_SCL) case 2: hi2c = &I2CHandle2; break; #endif #if defined(MICROPY_HW_I2C3_SCL) case 3: hi2c = &I2CHandle3; break; #endif #if defined(MICROPY_HW_I2C4_SCL) case 4: hi2c = &I2CHandle4; break; #endif default: return; } #if defined(STM32F4) uint32_t sr1 = hi2c->Instance->SR1; // I2C Bus error if (sr1 & I2C_FLAG_BERR) { hi2c->ErrorCode |= HAL_I2C_ERROR_BERR; __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR); } // I2C Arbitration Loss error if (sr1 & I2C_FLAG_ARLO) { hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO; __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO); } // I2C Acknowledge failure if (sr1 & I2C_FLAG_AF) { hi2c->ErrorCode |= HAL_I2C_ERROR_AF; SET_BIT(hi2c->Instance->CR1,I2C_CR1_STOP); __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); } // I2C Over-Run/Under-Run if (sr1 & I2C_FLAG_OVR) { hi2c->ErrorCode |= HAL_I2C_ERROR_OVR; __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR); } #else // if not an F4 MCU, use the HAL's IRQ handler HAL_I2C_ER_IRQHandler(hi2c); #endif } STATIC HAL_StatusTypeDef i2c_wait_dma_finished(I2C_HandleTypeDef *i2c, uint32_t timeout) { // Note: we can't use WFI to idle in this loop because the DMA completion // interrupt may occur before the WFI. Hence we miss it and have to wait // until the next sys-tick (up to 1ms). uint32_t start = HAL_GetTick(); while (HAL_I2C_GetState(i2c) != HAL_I2C_STATE_READY) { if (HAL_GetTick() - start >= timeout) { return HAL_TIMEOUT; } } return HAL_OK; } /******************************************************************************/ /* MicroPython bindings */ static inline bool in_master_mode(pyb_i2c_obj_t *self) { return self->i2c->Init.OwnAddress1 == PYB_I2C_MASTER_ADDRESS; } STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); uint i2c_num = 0; if (0) { } #if defined(MICROPY_HW_I2C1_SCL) else if (self->i2c->Instance == I2C1) { i2c_num = 1; } #endif #if defined(MICROPY_HW_I2C2_SCL) else if (self->i2c->Instance == I2C2) { i2c_num = 2; } #endif #if defined(MICROPY_HW_I2C3_SCL) else if (self->i2c->Instance == I2C3) { i2c_num = 3; } #endif #if defined(MICROPY_HW_I2C4_SCL) else if (self->i2c->Instance == I2C4) { i2c_num = 4; } #endif if (self->i2c->State == HAL_I2C_STATE_RESET) { mp_printf(print, "I2C(%u)", i2c_num); } else { if (in_master_mode(self)) { mp_printf(print, "I2C(%u, I2C.MASTER, baudrate=%u" #if PYB_I2C_TIMINGR ", timingr=0x%08x" #endif ")", i2c_num, pyb_i2c_get_baudrate(self->i2c) #if PYB_I2C_TIMINGR , self->i2c->Init.Timing #endif ); } else { mp_printf(print, "I2C(%u, I2C.SLAVE, addr=0x%02x)", i2c_num, (self->i2c->Instance->OAR1 >> 1) & 0x7f); } } } /// \method init(mode, *, addr=0x12, baudrate=400000, gencall=False) /// /// Initialise the I2C bus with the given parameters: /// /// - `mode` must be either `I2C.MASTER` or `I2C.SLAVE` /// - `addr` is the 7-bit address (only sensible for a slave) /// - `baudrate` is the SCL clock rate (only sensible for a master) /// - `gencall` is whether to support general call mode STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_INT, {.u_int = PYB_I2C_MASTER} }, { MP_QSTR_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x12} }, { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_HW_I2C_BAUDRATE_DEFAULT} }, { MP_QSTR_gencall, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_dma, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, #if PYB_I2C_TIMINGR { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, #endif }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // set the I2C configuration values I2C_InitTypeDef *init = &self->i2c->Init; if (args[0].u_int == PYB_I2C_MASTER) { // use a special address to indicate we are a master init->OwnAddress1 = PYB_I2C_MASTER_ADDRESS; } else { init->OwnAddress1 = (args[1].u_int << 1) & 0xfe; } // Set baudrate or timing value (if supported) #if PYB_I2C_TIMINGR if (args[5].u_obj != mp_const_none) { init->Timing = mp_obj_get_int_truncated(args[5].u_obj); } else #endif { i2c_set_baudrate(init, MIN(args[2].u_int, MICROPY_HW_I2C_BAUDRATE_MAX)); } init->AddressingMode = I2C_ADDRESSINGMODE_7BIT; init->DualAddressMode = I2C_DUALADDRESS_DISABLED; init->GeneralCallMode = args[3].u_bool ? I2C_GENERALCALL_ENABLED : I2C_GENERALCALL_DISABLED; init->OwnAddress2 = 0; // unused init->NoStretchMode = I2C_NOSTRETCH_DISABLE; *self->use_dma = args[4].u_bool; // init the I2C bus i2c_deinit(self->i2c); pyb_i2c_init(self->i2c); return mp_const_none; } /// \classmethod \constructor(bus, ...) /// /// Construct an I2C object on the given bus. `bus` can be 1 or 2. /// With no additional parameters, the I2C object is created but not /// initialised (it has the settings from the last initialisation of /// the bus, if any). If extra arguments are given, the bus is initialised. /// See `init` for parameters of initialisation. /// /// The physical pins of the I2C busses are: /// /// - `I2C(1)` is on the X position: `(SCL, SDA) = (X9, X10) = (PB6, PB7)` /// - `I2C(2)` is on the Y position: `(SCL, SDA) = (Y9, Y10) = (PB10, PB11)` STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // work out i2c bus int i2c_id = 0; if (mp_obj_is_str(args[0])) { const char *port = mp_obj_str_get_str(args[0]); if (0) { #ifdef MICROPY_HW_I2C1_NAME } else if (strcmp(port, MICROPY_HW_I2C1_NAME) == 0) { i2c_id = 1; #endif #ifdef MICROPY_HW_I2C2_NAME } else if (strcmp(port, MICROPY_HW_I2C2_NAME) == 0) { i2c_id = 2; #endif #ifdef MICROPY_HW_I2C3_NAME } else if (strcmp(port, MICROPY_HW_I2C3_NAME) == 0) { i2c_id = 3; #endif #ifdef MICROPY_HW_I2C4_NAME } else if (strcmp(port, MICROPY_HW_I2C4_NAME) == 0) { i2c_id = 4; #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%s) doesn't exist", port)); } } else { i2c_id = mp_obj_get_int(args[0]); if (i2c_id < 1 || i2c_id > MP_ARRAY_SIZE(pyb_i2c_obj) || pyb_i2c_obj[i2c_id - 1].i2c == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%d) doesn't exist", i2c_id)); } } // get I2C object const pyb_i2c_obj_t *i2c_obj = &pyb_i2c_obj[i2c_id - 1]; if (n_args > 1 || n_kw > 0) { // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_i2c_init_helper(i2c_obj, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(i2c_obj); } STATIC mp_obj_t pyb_i2c_init_(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_i2c_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init_); /// \method deinit() /// Turn off the I2C bus. STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) { pyb_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); i2c_deinit(self->i2c); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit); /// \method is_ready(addr) /// Check if an I2C device responds to the given address. Only valid when in master mode. STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) { pyb_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!in_master_mode(self)) { mp_raise_TypeError("I2C must be a master"); } mp_uint_t i2c_addr = mp_obj_get_int(i2c_addr_o) << 1; for (int i = 0; i < 10; i++) { HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c, i2c_addr, 10, 200); if (status == HAL_OK) { return mp_const_true; } } return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_is_ready_obj, pyb_i2c_is_ready); /// \method scan() /// Scan all I2C addresses from 0x08 to 0x77 and return a list of those that respond. /// Only valid when in master mode. STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) { pyb_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!in_master_mode(self)) { mp_raise_TypeError("I2C must be a master"); } mp_obj_t list = mp_obj_new_list(0, NULL); for (uint addr = 0x08; addr <= 0x77; addr++) { HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c, addr << 1, 1, 200); if (status == HAL_OK) { mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); } } return list; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_scan_obj, pyb_i2c_scan); /// \method send(send, addr=0x00, timeout=5000) /// Send data on the bus: /// /// - `send` is the data to send (an integer to send, or a buffer object) /// - `addr` is the address to send to (only required in master mode) /// - `timeout` is the timeout in milliseconds to wait for the send /// /// Return value: `None`. STATIC mp_obj_t pyb_i2c_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_addr, MP_ARG_INT, {.u_int = PYB_I2C_MASTER_ADDRESS} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args pyb_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the buffer to send from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data); // if option is set and IRQs are enabled then we can use DMA bool use_dma = *self->use_dma && query_irq() == IRQ_STATE_ENABLED; DMA_HandleTypeDef tx_dma; if (use_dma) { dma_init(&tx_dma, self->tx_dma_descr, DMA_MEMORY_TO_PERIPH, self->i2c); self->i2c->hdmatx = &tx_dma; self->i2c->hdmarx = NULL; } // send the data HAL_StatusTypeDef status; if (in_master_mode(self)) { if (args[1].u_int == PYB_I2C_MASTER_ADDRESS) { if (use_dma) { dma_deinit(self->tx_dma_descr); } mp_raise_TypeError("addr argument required"); } mp_uint_t i2c_addr = args[1].u_int << 1; if (!use_dma) { status = HAL_I2C_Master_Transmit(self->i2c, i2c_addr, bufinfo.buf, bufinfo.len, args[2].u_int); } else { MP_HAL_CLEAN_DCACHE(bufinfo.buf, bufinfo.len); status = HAL_I2C_Master_Transmit_DMA(self->i2c, i2c_addr, bufinfo.buf, bufinfo.len); } } else { if (!use_dma) { status = HAL_I2C_Slave_Transmit(self->i2c, bufinfo.buf, bufinfo.len, args[2].u_int); } else { MP_HAL_CLEAN_DCACHE(bufinfo.buf, bufinfo.len); status = HAL_I2C_Slave_Transmit_DMA(self->i2c, bufinfo.buf, bufinfo.len); } } // if we used DMA, wait for it to finish if (use_dma) { if (status == HAL_OK) { status = i2c_wait_dma_finished(self->i2c, args[2].u_int); } dma_deinit(self->tx_dma_descr); } if (status != HAL_OK) { i2c_reset_after_error(self->i2c); mp_hal_raise(status); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_send_obj, 1, pyb_i2c_send); /// \method recv(recv, addr=0x00, timeout=5000) /// /// Receive data on the bus: /// /// - `recv` can be an integer, which is the number of bytes to receive, /// or a mutable buffer, which will be filled with received bytes /// - `addr` is the address to receive from (only required in master mode) /// - `timeout` is the timeout in milliseconds to wait for the receive /// /// Return value: if `recv` is an integer then a new buffer of the bytes received, /// otherwise the same buffer that was passed in to `recv`. STATIC mp_obj_t pyb_i2c_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_addr, MP_ARG_INT, {.u_int = PYB_I2C_MASTER_ADDRESS} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args pyb_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the buffer to receive into vstr_t vstr; mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr); // if option is set and IRQs are enabled then we can use DMA bool use_dma = *self->use_dma && query_irq() == IRQ_STATE_ENABLED; DMA_HandleTypeDef rx_dma; if (use_dma) { dma_init(&rx_dma, self->rx_dma_descr, DMA_PERIPH_TO_MEMORY, self->i2c); self->i2c->hdmatx = NULL; self->i2c->hdmarx = &rx_dma; } // receive the data HAL_StatusTypeDef status; if (in_master_mode(self)) { if (args[1].u_int == PYB_I2C_MASTER_ADDRESS) { mp_raise_TypeError("addr argument required"); } mp_uint_t i2c_addr = args[1].u_int << 1; if (!use_dma) { status = HAL_I2C_Master_Receive(self->i2c, i2c_addr, (uint8_t*)vstr.buf, vstr.len, args[2].u_int); } else { MP_HAL_CLEANINVALIDATE_DCACHE(vstr.buf, vstr.len); status = HAL_I2C_Master_Receive_DMA(self->i2c, i2c_addr, (uint8_t*)vstr.buf, vstr.len); } } else { if (!use_dma) { status = HAL_I2C_Slave_Receive(self->i2c, (uint8_t*)vstr.buf, vstr.len, args[2].u_int); } else { MP_HAL_CLEANINVALIDATE_DCACHE(vstr.buf, vstr.len); status = HAL_I2C_Slave_Receive_DMA(self->i2c, (uint8_t*)vstr.buf, vstr.len); } } // if we used DMA, wait for it to finish if (use_dma) { if (status == HAL_OK) { status = i2c_wait_dma_finished(self->i2c, args[2].u_int); } dma_deinit(self->rx_dma_descr); } if (status != HAL_OK) { i2c_reset_after_error(self->i2c); mp_hal_raise(status); } // return the received data if (o_ret != MP_OBJ_NULL) { return o_ret; } else { return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_recv_obj, 1, pyb_i2c_recv); /// \method mem_read(data, addr, memaddr, timeout=5000, addr_size=8) /// /// Read from the memory of an I2C device: /// /// - `data` can be an integer or a buffer to read into /// - `addr` is the I2C device address /// - `memaddr` is the memory location within the I2C device /// - `timeout` is the timeout in milliseconds to wait for the read /// - `addr_size` selects width of memaddr: 8 or 16 bits /// /// Returns the read data. /// This is only valid in master mode. STATIC const mp_arg_t pyb_i2c_mem_read_allowed_args[] = { { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, { MP_QSTR_addr_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, }; STATIC mp_obj_t pyb_i2c_mem_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args pyb_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_mem_read_allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(pyb_i2c_mem_read_allowed_args), pyb_i2c_mem_read_allowed_args, args); if (!in_master_mode(self)) { mp_raise_TypeError("I2C must be a master"); } // get the buffer to read into vstr_t vstr; mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr); // get the addresses mp_uint_t i2c_addr = args[1].u_int << 1; mp_uint_t mem_addr = args[2].u_int; // determine width of mem_addr; default is 8 bits, entering any other value gives 16 bit width mp_uint_t mem_addr_size = I2C_MEMADD_SIZE_8BIT; if (args[4].u_int != 8) { mem_addr_size = I2C_MEMADD_SIZE_16BIT; } // if option is set and IRQs are enabled then we can use DMA bool use_dma = *self->use_dma && query_irq() == IRQ_STATE_ENABLED; HAL_StatusTypeDef status; if (!use_dma) { status = HAL_I2C_Mem_Read(self->i2c, i2c_addr, mem_addr, mem_addr_size, (uint8_t*)vstr.buf, vstr.len, args[3].u_int); } else { DMA_HandleTypeDef rx_dma; dma_init(&rx_dma, self->rx_dma_descr, DMA_PERIPH_TO_MEMORY, self->i2c); self->i2c->hdmatx = NULL; self->i2c->hdmarx = &rx_dma; MP_HAL_CLEANINVALIDATE_DCACHE(vstr.buf, vstr.len); status = HAL_I2C_Mem_Read_DMA(self->i2c, i2c_addr, mem_addr, mem_addr_size, (uint8_t*)vstr.buf, vstr.len); if (status == HAL_OK) { status = i2c_wait_dma_finished(self->i2c, args[3].u_int); } dma_deinit(self->rx_dma_descr); } if (status != HAL_OK) { i2c_reset_after_error(self->i2c); mp_hal_raise(status); } // return the read data if (o_ret != MP_OBJ_NULL) { return o_ret; } else { return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_read_obj, 1, pyb_i2c_mem_read); /// \method mem_write(data, addr, memaddr, timeout=5000, addr_size=8) /// /// Write to the memory of an I2C device: /// /// - `data` can be an integer or a buffer to write from /// - `addr` is the I2C device address /// - `memaddr` is the memory location within the I2C device /// - `timeout` is the timeout in milliseconds to wait for the write /// - `addr_size` selects width of memaddr: 8 or 16 bits /// /// Returns `None`. /// This is only valid in master mode. STATIC mp_obj_t pyb_i2c_mem_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args (same as mem_read) pyb_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_mem_read_allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(pyb_i2c_mem_read_allowed_args), pyb_i2c_mem_read_allowed_args, args); if (!in_master_mode(self)) { mp_raise_TypeError("I2C must be a master"); } // get the buffer to write from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data); // get the addresses mp_uint_t i2c_addr = args[1].u_int << 1; mp_uint_t mem_addr = args[2].u_int; // determine width of mem_addr; default is 8 bits, entering any other value gives 16 bit width mp_uint_t mem_addr_size = I2C_MEMADD_SIZE_8BIT; if (args[4].u_int != 8) { mem_addr_size = I2C_MEMADD_SIZE_16BIT; } // if option is set and IRQs are enabled then we can use DMA bool use_dma = *self->use_dma && query_irq() == IRQ_STATE_ENABLED; HAL_StatusTypeDef status; if (!use_dma) { status = HAL_I2C_Mem_Write(self->i2c, i2c_addr, mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len, args[3].u_int); } else { DMA_HandleTypeDef tx_dma; dma_init(&tx_dma, self->tx_dma_descr, DMA_MEMORY_TO_PERIPH, self->i2c); self->i2c->hdmatx = &tx_dma; self->i2c->hdmarx = NULL; MP_HAL_CLEAN_DCACHE(bufinfo.buf, bufinfo.len); status = HAL_I2C_Mem_Write_DMA(self->i2c, i2c_addr, mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len); if (status == HAL_OK) { status = i2c_wait_dma_finished(self->i2c, args[3].u_int); } dma_deinit(self->tx_dma_descr); } if (status != HAL_OK) { i2c_reset_after_error(self->i2c); mp_hal_raise(status); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_write_obj, 1, pyb_i2c_mem_write); STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_i2c_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_i2c_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_is_ready), MP_ROM_PTR(&pyb_i2c_is_ready_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&pyb_i2c_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_i2c_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_i2c_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_mem_read), MP_ROM_PTR(&pyb_i2c_mem_read_obj) }, { MP_ROM_QSTR(MP_QSTR_mem_write), MP_ROM_PTR(&pyb_i2c_mem_write_obj) }, // class constants /// \constant MASTER - for initialising the bus to master mode /// \constant SLAVE - for initialising the bus to slave mode { MP_ROM_QSTR(MP_QSTR_MASTER), MP_ROM_INT(PYB_I2C_MASTER) }, { MP_ROM_QSTR(MP_QSTR_SLAVE), MP_ROM_INT(PYB_I2C_SLAVE) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table); const mp_obj_type_t pyb_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, .print = pyb_i2c_print, .make_new = pyb_i2c_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_i2c_locals_dict, }; #endif // MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C micropython-1.12/ports/stm32/pyb_spi.c000066400000000000000000000347251357706137100177650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "extmod/machine_spi.h" #include "bufhelper.h" #include "spi.h" /******************************************************************************/ // MicroPython bindings for legacy pyb API // class pyb.SPI - a master-driven serial protocol // // SPI is a serial protocol that is driven by a master. At the physical level // there are 3 lines: SCK, MOSI, MISO. // // See usage model of I2C; SPI is very similar. Main difference is // parameters to init the SPI bus: // // from pyb import SPI // spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7) // // Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be // 0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1 // to sample data on the first or second clock edge respectively. Crc can be // None for no CRC, or a polynomial specifier. // // Additional method for SPI: // // data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes // buf = bytearray(4) // spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf // spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf STATIC const pyb_spi_obj_t pyb_spi_obj[] = { {{&pyb_spi_type}, &spi_obj[0]}, {{&pyb_spi_type}, &spi_obj[1]}, {{&pyb_spi_type}, &spi_obj[2]}, {{&pyb_spi_type}, &spi_obj[3]}, {{&pyb_spi_type}, &spi_obj[4]}, {{&pyb_spi_type}, &spi_obj[5]}, }; STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); spi_print(print, self->spi, true); } // init(mode, baudrate=328125, *, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) // // Initialise the SPI bus with the given parameters: // - `mode` must be either `SPI.MASTER` or `SPI.SLAVE`. // - `baudrate` is the SCK clock rate (only sensible for a master). STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 328125} }, { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_dir, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_DIRECTION_2LINES} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_nss, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_NSS_SOFT} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_FIRSTBIT_MSB} }, { MP_QSTR_ti, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_crc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // set the SPI configuration values SPI_InitTypeDef *init = &self->spi->spi->Init; init->Mode = args[0].u_int; spi_set_params(self->spi, args[2].u_int, args[1].u_int, args[3].u_int, args[4].u_int, args[6].u_int, args[8].u_int); init->Direction = args[5].u_int; init->NSS = args[7].u_int; init->TIMode = args[9].u_bool ? SPI_TIMODE_ENABLE : SPI_TIMODE_DISABLE; if (args[10].u_obj == mp_const_none) { init->CRCCalculation = SPI_CRCCALCULATION_DISABLE; init->CRCPolynomial = 0; } else { init->CRCCalculation = SPI_CRCCALCULATION_ENABLE; init->CRCPolynomial = mp_obj_get_int(args[10].u_obj); } // init the SPI bus spi_init(self->spi, init->NSS != SPI_NSS_SOFT); return mp_const_none; } // constructor(bus, ...) // // Construct an SPI object on the given bus. `bus` can be 1 or 2. // With no additional parameters, the SPI object is created but not // initialised (it has the settings from the last initialisation of // the bus, if any). If extra arguments are given, the bus is initialised. // See `init` for parameters of initialisation. // // The physical pins of the SPI busses are: // - `SPI(1)` is on the X position: `(NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7)` // - `SPI(2)` is on the Y position: `(NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)` // // At the moment, the NSS pin is not used by the SPI driver and is free // for other use. STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // work out SPI bus int spi_id = spi_find_index(args[0]); // get SPI object const pyb_spi_obj_t *spi_obj = &pyb_spi_obj[spi_id - 1]; if (n_args > 1 || n_kw > 0) { // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_spi_init_helper(spi_obj, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(spi_obj); } STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_spi_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init); // deinit() // Turn off the SPI bus. STATIC mp_obj_t pyb_spi_deinit(mp_obj_t self_in) { pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); spi_deinit(self->spi); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_spi_deinit_obj, pyb_spi_deinit); // send(send, *, timeout=5000) // Send data on the bus: // - `send` is the data to send (an integer to send, or a buffer object). // - `timeout` is the timeout in milliseconds to wait for the send. // // Return value: `None`. STATIC mp_obj_t pyb_spi_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide static const mp_arg_t allowed_args[] = { { MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args pyb_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the buffer to send from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data); // send the data spi_transfer(self->spi, bufinfo.len, bufinfo.buf, NULL, args[1].u_int); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_obj, 1, pyb_spi_send); // recv(recv, *, timeout=5000) // // Receive data on the bus: // - `recv` can be an integer, which is the number of bytes to receive, // or a mutable buffer, which will be filled with received bytes. // - `timeout` is the timeout in milliseconds to wait for the receive. // // Return value: if `recv` is an integer then a new buffer of the bytes received, // otherwise the same buffer that was passed in to `recv`. STATIC mp_obj_t pyb_spi_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide static const mp_arg_t allowed_args[] = { { MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args pyb_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the buffer to receive into vstr_t vstr; mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr); // receive the data spi_transfer(self->spi, vstr.len, NULL, (uint8_t*)vstr.buf, args[1].u_int); // return the received data if (o_ret != MP_OBJ_NULL) { return o_ret; } else { return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_recv_obj, 1, pyb_spi_recv); // send_recv(send, recv=None, *, timeout=5000) // // Send and receive data on the bus at the same time: // - `send` is the data to send (an integer to send, or a buffer object). // - `recv` is a mutable buffer which will be filled with received bytes. // It can be the same as `send`, or omitted. If omitted, a new buffer will // be created. // - `timeout` is the timeout in milliseconds to wait for the receive. // // Return value: the buffer with the received bytes. STATIC mp_obj_t pyb_spi_send_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide static const mp_arg_t allowed_args[] = { { MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args pyb_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get buffers to send from/receive to mp_buffer_info_t bufinfo_send; uint8_t data_send[1]; mp_buffer_info_t bufinfo_recv; vstr_t vstr_recv; mp_obj_t o_ret; if (args[0].u_obj == args[1].u_obj) { // same object for send and receive, it must be a r/w buffer mp_get_buffer_raise(args[0].u_obj, &bufinfo_send, MP_BUFFER_RW); bufinfo_recv = bufinfo_send; o_ret = args[0].u_obj; } else { // get the buffer to send from pyb_buf_get_for_send(args[0].u_obj, &bufinfo_send, data_send); // get the buffer to receive into if (args[1].u_obj == MP_OBJ_NULL) { // only send argument given, so create a fresh buffer of the send length vstr_init_len(&vstr_recv, bufinfo_send.len); bufinfo_recv.len = vstr_recv.len; bufinfo_recv.buf = vstr_recv.buf; o_ret = MP_OBJ_NULL; } else { // recv argument given mp_get_buffer_raise(args[1].u_obj, &bufinfo_recv, MP_BUFFER_WRITE); if (bufinfo_recv.len != bufinfo_send.len) { mp_raise_ValueError("recv must be same length as send"); } o_ret = args[1].u_obj; } } // do the transfer spi_transfer(self->spi, bufinfo_send.len, bufinfo_send.buf, bufinfo_recv.buf, args[2].u_int); // return the received data if (o_ret != MP_OBJ_NULL) { return o_ret; } else { return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr_recv); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_recv_obj, 1, pyb_spi_send_recv); STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_spi_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, // legacy methods { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_spi_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_spi_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_send_recv), MP_ROM_PTR(&pyb_spi_send_recv_obj) }, // class constants /// \constant MASTER - for initialising the bus to master mode /// \constant SLAVE - for initialising the bus to slave mode /// \constant MSB - set the first bit to MSB /// \constant LSB - set the first bit to LSB { MP_ROM_QSTR(MP_QSTR_MASTER), MP_ROM_INT(SPI_MODE_MASTER) }, { MP_ROM_QSTR(MP_QSTR_SLAVE), MP_ROM_INT(SPI_MODE_SLAVE) }, { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(SPI_FIRSTBIT_MSB) }, { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(SPI_FIRSTBIT_LSB) }, /* TODO { MP_ROM_QSTR(MP_QSTR_DIRECTION_2LINES ((uint32_t)0x00000000) { MP_ROM_QSTR(MP_QSTR_DIRECTION_2LINES_RXONLY SPI_CR1_RXONLY { MP_ROM_QSTR(MP_QSTR_DIRECTION_1LINE SPI_CR1_BIDIMODE { MP_ROM_QSTR(MP_QSTR_NSS_SOFT SPI_CR1_SSM { MP_ROM_QSTR(MP_QSTR_NSS_HARD_INPUT ((uint32_t)0x00000000) { MP_ROM_QSTR(MP_QSTR_NSS_HARD_OUTPUT ((uint32_t)0x00040000) */ }; STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table); STATIC void spi_transfer_machine(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { pyb_spi_obj_t *self = (pyb_spi_obj_t*)self_in; spi_transfer(self->spi, len, src, dest, SPI_TRANSFER_TIMEOUT(len)); } STATIC const mp_machine_spi_p_t pyb_spi_p = { .transfer = spi_transfer_machine, }; const mp_obj_type_t pyb_spi_type = { { &mp_type_type }, .name = MP_QSTR_SPI, .print = pyb_spi_print, .make_new = pyb_spi_make_new, .protocol = &pyb_spi_p, .locals_dict = (mp_obj_dict_t*)&pyb_spi_locals_dict, }; micropython-1.12/ports/stm32/pybcdc.inf_template000066400000000000000000000053451357706137100220050ustar00rootroot00000000000000; Windows USB CDC ACM Setup File ; Based on INF files which were: ; Copyright (c) 2000 Microsoft Corporation ; Copyright (C) 2007 Microchip Technology Inc. ; Likely to be covered by the MLPL as found at: ; . [Version] Signature="$Windows NT$" Class=Ports ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} Provider=%MFGNAME% LayoutFile=layout.inf DriverVer=03/11/2010,5.1.2600.3 [Manufacturer] %MFGNAME%=DeviceList, NTamd64 [DestinationDirs] DefaultDestDir=12 ;--------------------------------------------------------------------- ; Windows 2000/XP/Server2003/Vista/Server2008/7 - 32bit Sections [DriverInstall.nt] include=mdmcpq.inf CopyFiles=DriverCopyFiles.nt AddReg=DriverInstall.nt.AddReg [DriverCopyFiles.nt] usbser.sys,,,0x20 [DriverInstall.nt.AddReg] HKR,,DevLoader,,*ntkern HKR,,NTMPDriver,,usbser.sys HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" [DriverInstall.nt.Services] AddService=usbser, 0x00000002, DriverService.nt [DriverService.nt] DisplayName=%SERVICE% ServiceType=1 StartType=3 ErrorControl=1 ServiceBinary=%12%\usbser.sys ;--------------------------------------------------------------------- ; Windows XP/Server2003/Vista/Server2008/7 - 64bit Sections [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=%SERVICE% ServiceType=1 StartType=3 ErrorControl=1 ServiceBinary=%12%\usbser.sys ;--------------------------------------------------------------------- ; Vendor and Product ID Definitions [SourceDisksFiles] [SourceDisksNames] [DeviceList] %DESCRIPTION%=DriverInstall, USB\VID_${USB_VID}&PID_${USB_PID_CDC_MSC}&MI_00, USB\VID_${USB_VID}&PID_${USB_PID_CDC_MSC}&MI_01, USB\VID_${USB_VID}&PID_${USB_PID_CDC_HID}&MI_00, USB\VID_${USB_VID}&PID_${USB_PID_CDC_HID}&MI_01, USB\VID_${USB_VID}&PID_${USB_PID_CDC} [DeviceList.NTamd64] %DESCRIPTION%=DriverInstall, USB\VID_${USB_VID}&PID_${USB_PID_CDC_MSC}&MI_00, USB\VID_${USB_VID}&PID_${USB_PID_CDC_MSC}&MI_01, USB\VID_${USB_VID}&PID_${USB_PID_CDC_HID}&MI_00, USB\VID_${USB_VID}&PID_${USB_PID_CDC_HID}&MI_01, USB\VID_${USB_VID}&PID_${USB_PID_CDC} ;--------------------------------------------------------------------- ; String Definitions [Strings] MFGFILENAME="pybcdc" MFGNAME="MicroPython" DESCRIPTION="Pyboard USB Comm Port" SERVICE="USB Serial Driver" micropython-1.12/ports/stm32/pybthread.c000066400000000000000000000175511357706137100203000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "gccollect.h" #include "irq.h" #include "pybthread.h" #if MICROPY_PY_THREAD #define PYB_MUTEX_UNLOCKED ((void*)0) #define PYB_MUTEX_LOCKED ((void*)1) // These macros are used when we only need to protect against a thread // switch; other interrupts are still allowed to proceed. #define RAISE_IRQ_PRI() raise_irq_pri(IRQ_PRI_PENDSV) #define RESTORE_IRQ_PRI(state) restore_irq_pri(state) extern void __fatal_error(const char*); volatile int pyb_thread_enabled; pyb_thread_t *volatile pyb_thread_all; pyb_thread_t *volatile pyb_thread_cur; static inline void pyb_thread_add_to_runable(pyb_thread_t *thread) { thread->run_prev = pyb_thread_cur->run_prev; thread->run_next = pyb_thread_cur; pyb_thread_cur->run_prev->run_next = thread; pyb_thread_cur->run_prev = thread; } static inline void pyb_thread_remove_from_runable(pyb_thread_t *thread) { if (thread->run_next == thread) { __fatal_error("deadlock"); } thread->run_prev->run_next = thread->run_next; thread->run_next->run_prev = thread->run_prev; } void pyb_thread_init(pyb_thread_t *thread) { pyb_thread_enabled = 0; pyb_thread_all = thread; pyb_thread_cur = thread; thread->sp = NULL; // will be set when this thread switches out thread->local_state = 0; // will be set by mp_thread_init thread->arg = NULL; thread->stack = &_sstack; thread->stack_len = ((uint32_t)&_estack - (uint32_t)&_sstack) / sizeof(uint32_t); thread->all_next = NULL; thread->run_prev = thread; thread->run_next = thread; thread->queue_next = NULL; } void pyb_thread_deinit() { uint32_t irq_state = disable_irq(); pyb_thread_enabled = 0; pyb_thread_all = pyb_thread_cur; pyb_thread_cur->all_next = NULL; pyb_thread_cur->run_prev = pyb_thread_cur; pyb_thread_cur->run_next = pyb_thread_cur; enable_irq(irq_state); } STATIC void pyb_thread_terminate(void) { uint32_t irq_state = disable_irq(); pyb_thread_t *thread = pyb_thread_cur; // take current thread off the run list pyb_thread_remove_from_runable(thread); // take current thread off the list of all threads for (pyb_thread_t **n = (pyb_thread_t**)&pyb_thread_all;; n = &(*n)->all_next) { if (*n == thread) { *n = thread->all_next; break; } } // clean pointers as much as possible to help GC thread->all_next = NULL; thread->queue_next = NULL; thread->stack = NULL; if (pyb_thread_all->all_next == NULL) { // only 1 thread left pyb_thread_enabled = 0; } // thread switch will occur after we enable irqs SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; enable_irq(irq_state); // should not return __fatal_error("could not terminate"); } uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, void *entry, void *arg) { uint32_t *stack_top = (uint32_t*)stack + stack_len; // stack is full descending *--stack_top = 0x01000000; // xPSR (thumb bit set) *--stack_top = (uint32_t)entry & 0xfffffffe; // pc (must have bit 0 cleared, even for thumb code) *--stack_top = (uint32_t)pyb_thread_terminate; // lr *--stack_top = 0; // r12 *--stack_top = 0; // r3 *--stack_top = 0; // r2 *--stack_top = 0; // r1 *--stack_top = (uint32_t)arg; // r0 *--stack_top = 0xfffffff9; // lr (return to thread mode, non-FP, use MSP) stack_top -= 8; // r4-r11 stack_top -= 16; // s16-s31 (we assume all threads use FP registers) thread->sp = stack_top; thread->local_state = 0; thread->arg = arg; thread->stack = stack; thread->stack_len = stack_len; thread->queue_next = NULL; uint32_t irq_state = disable_irq(); pyb_thread_enabled = 1; thread->all_next = pyb_thread_all; pyb_thread_all = thread; pyb_thread_add_to_runable(thread); enable_irq(irq_state); return (uint32_t)thread; // success } void pyb_thread_dump(void) { if (!pyb_thread_enabled) { printf("THREAD: only main thread\n"); } else { printf("THREAD:\n"); for (pyb_thread_t *th = pyb_thread_all; th != NULL; th = th->all_next) { bool runable = false; for (pyb_thread_t *th2 = pyb_thread_cur;; th2 = th2->run_next) { if (th == th2) { runable = true; break; } if (th2->run_next == pyb_thread_cur) { break; } } printf(" id=%p sp=%p sz=%u", th, th->stack, th->stack_len); if (runable) { printf(" (runable)"); } printf("\n"); } } } // should only be called from pendsv_isr_handler void *pyb_thread_next(void *sp) { pyb_thread_cur->sp = sp; pyb_thread_cur = pyb_thread_cur->run_next; pyb_thread_cur->timeslice = 4; // in milliseconds return pyb_thread_cur->sp; } void pyb_mutex_init(pyb_mutex_t *m) { *m = PYB_MUTEX_UNLOCKED; } int pyb_mutex_lock(pyb_mutex_t *m, int wait) { uint32_t irq_state = RAISE_IRQ_PRI(); if (*m == PYB_MUTEX_UNLOCKED) { // mutex is available *m = PYB_MUTEX_LOCKED; RESTORE_IRQ_PRI(irq_state); } else { // mutex is locked if (!wait) { RESTORE_IRQ_PRI(irq_state); return 0; // failed to lock mutex } if (*m == PYB_MUTEX_LOCKED) { *m = pyb_thread_cur; } else { for (pyb_thread_t *n = *m;; n = n->queue_next) { if (n->queue_next == NULL) { n->queue_next = pyb_thread_cur; break; } } } pyb_thread_cur->queue_next = NULL; // take current thread off the run list pyb_thread_remove_from_runable(pyb_thread_cur); // thread switch will occur after we enable irqs SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; RESTORE_IRQ_PRI(irq_state); // when we come back we have the mutex } return 1; // have mutex } void pyb_mutex_unlock(pyb_mutex_t *m) { uint32_t irq_state = RAISE_IRQ_PRI(); if (*m == PYB_MUTEX_LOCKED) { // no threads are blocked on the mutex *m = PYB_MUTEX_UNLOCKED; } else { // at least one thread is blocked on this mutex pyb_thread_t *th = *m; if (th->queue_next == NULL) { // no other threads are blocked *m = PYB_MUTEX_LOCKED; } else { // at least one other thread is still blocked *m = th->queue_next; } // put unblocked thread on runable list pyb_thread_add_to_runable(th); } RESTORE_IRQ_PRI(irq_state); } #endif // MICROPY_PY_THREAD micropython-1.12/ports/stm32/pybthread.h000066400000000000000000000053231357706137100202770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_PYBTHREAD_H #define MICROPY_INCLUDED_STM32_PYBTHREAD_H typedef struct _pyb_thread_t { void *sp; uint32_t local_state; void *arg; // thread Python args, a GC root pointer void *stack; // pointer to the stack size_t stack_len; // number of words in the stack uint32_t timeslice; struct _pyb_thread_t *all_next; struct _pyb_thread_t *run_prev; struct _pyb_thread_t *run_next; struct _pyb_thread_t *queue_next; } pyb_thread_t; typedef pyb_thread_t *pyb_mutex_t; extern volatile int pyb_thread_enabled; extern pyb_thread_t *volatile pyb_thread_all; extern pyb_thread_t *volatile pyb_thread_cur; void pyb_thread_init(pyb_thread_t *th); void pyb_thread_deinit(); uint32_t pyb_thread_new(pyb_thread_t *th, void *stack, size_t stack_len, void *entry, void *arg); void pyb_thread_dump(void); static inline uint32_t pyb_thread_get_id(void) { return (uint32_t)pyb_thread_cur; } static inline void pyb_thread_set_local(void *value) { pyb_thread_cur->local_state = (uint32_t)value; } static inline void *pyb_thread_get_local(void) { return (void*)pyb_thread_cur->local_state; } static inline void pyb_thread_yield(void) { if (pyb_thread_cur->run_next == pyb_thread_cur) { __WFI(); } else { SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; } } void pyb_mutex_init(pyb_mutex_t *m); int pyb_mutex_lock(pyb_mutex_t *m, int wait); void pyb_mutex_unlock(pyb_mutex_t *m); #endif // MICROPY_INCLUDED_STM32_PYBTHREAD_H micropython-1.12/ports/stm32/qspi.c000066400000000000000000000321701357706137100172640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mperrno.h" #include "py/mphal.h" #include "mpu.h" #include "qspi.h" #include "pin_static_af.h" #if defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2) #define QSPI_MAP_ADDR (0x90000000) #ifndef MICROPY_HW_QSPI_PRESCALER #define MICROPY_HW_QSPI_PRESCALER 3 // F_CLK = F_AHB/3 (72MHz when CPU is 216MHz) #endif #ifndef MICROPY_HW_QSPI_SAMPLE_SHIFT #define MICROPY_HW_QSPI_SAMPLE_SHIFT 1 // sample shift enabled #endif #ifndef MICROPY_HW_QSPI_TIMEOUT_COUNTER #define MICROPY_HW_QSPI_TIMEOUT_COUNTER 0 // timeout counter disabled (see F7 errata) #endif #ifndef MICROPY_HW_QSPI_CS_HIGH_CYCLES #define MICROPY_HW_QSPI_CS_HIGH_CYCLES 2 // nCS stays high for 2 cycles #endif static inline void qspi_mpu_disable_all(void) { // Configure MPU to disable access to entire QSPI region, to prevent CPU // speculative execution from accessing this region and modifying QSPI registers. uint32_t irq_state = mpu_config_start(); mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x00, MPU_REGION_SIZE_256MB)); mpu_config_end(irq_state); } static inline void qspi_mpu_enable_mapped(void) { // Configure MPU to allow access to only the valid part of external SPI flash. // The memory accesses to the mapped QSPI are faster if the MPU is not used // for the memory-mapped region, so 3 MPU regions are used to disable access // to everything except the valid address space, using holes in the bottom // of the regions and nesting them. // At the moment this is hard-coded to 2MiB of QSPI address space. uint32_t irq_state = mpu_config_start(); mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB)); mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0f, MPU_REGION_SIZE_32MB)); mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_16MB)); mpu_config_end(irq_state); } void qspi_init(void) { qspi_mpu_disable_all(); // Configure pins mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_CS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_BK1_NCS); mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_SCK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_CLK); mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_IO0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_BK1_IO0); mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_IO1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_BK1_IO1); mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_IO2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_BK1_IO2); mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_IO3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_BK1_IO3); // Bring up the QSPI peripheral __HAL_RCC_QSPI_CLK_ENABLE(); __HAL_RCC_QSPI_FORCE_RESET(); __HAL_RCC_QSPI_RELEASE_RESET(); QUADSPI->CR = (MICROPY_HW_QSPI_PRESCALER - 1) << QUADSPI_CR_PRESCALER_Pos | 3 << QUADSPI_CR_FTHRES_Pos // 4 bytes must be available to read/write #if defined(QUADSPI_CR_FSEL_Pos) | 0 << QUADSPI_CR_FSEL_Pos // FLASH 1 selected #endif #if defined(QUADSPI_CR_DFM_Pos) | 0 << QUADSPI_CR_DFM_Pos // dual-flash mode disabled #endif | MICROPY_HW_QSPI_SAMPLE_SHIFT << QUADSPI_CR_SSHIFT_Pos | MICROPY_HW_QSPI_TIMEOUT_COUNTER << QUADSPI_CR_TCEN_Pos | 1 << QUADSPI_CR_EN_Pos // enable the peripheral ; QUADSPI->DCR = (MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) << QUADSPI_DCR_FSIZE_Pos | (MICROPY_HW_QSPI_CS_HIGH_CYCLES - 1) << QUADSPI_DCR_CSHT_Pos | 0 << QUADSPI_DCR_CKMODE_Pos // CLK idles at low state ; } void qspi_memory_map(void) { // Enable memory-mapped mode QUADSPI->ABR = 0; // disable continuous read mode QUADSPI->CCR = 0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 3 << QUADSPI_CCR_FMODE_Pos // memory-mapped mode | 3 << QUADSPI_CCR_DMODE_Pos // data on 4 lines | 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles | 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte | 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines | 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size | 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | 0xeb << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode ; qspi_mpu_enable_mapped(); } STATIC int qspi_ioctl(void *self_in, uint32_t cmd) { (void)self_in; switch (cmd) { case MP_QSPI_IOCTL_INIT: qspi_init(); break; case MP_QSPI_IOCTL_BUS_ACQUIRE: // Disable memory-mapped region during bus access qspi_mpu_disable_all(); // Abort any ongoing transfer if peripheral is busy if (QUADSPI->SR & QUADSPI_SR_BUSY) { QUADSPI->CR |= QUADSPI_CR_ABORT; while (QUADSPI->CR & QUADSPI_CR_ABORT) { } } break; case MP_QSPI_IOCTL_BUS_RELEASE: // Switch to memory-map mode when bus is idle qspi_memory_map(); break; } return 0; // success } STATIC void qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) { (void)self_in; QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag if (len == 0) { QUADSPI->CCR = 0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 0 << QUADSPI_CCR_FMODE_Pos // indirect write mode | 0 << QUADSPI_CCR_DMODE_Pos // no data | 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles | 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte | 0 << QUADSPI_CCR_ADMODE_Pos // no address | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode ; } else { QUADSPI->DLR = len - 1; QUADSPI->CCR = 0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 0 << QUADSPI_CCR_FMODE_Pos // indirect write mode | 1 << QUADSPI_CCR_DMODE_Pos // data on 1 line | 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles | 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte | 0 << QUADSPI_CCR_ADMODE_Pos // no address | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode ; // This assumes len==2 *(uint16_t*)&QUADSPI->DR = data; } // Wait for write to finish while (!(QUADSPI->SR & QUADSPI_SR_TCF)) { } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag } STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { (void)self_in; QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag if (len == 0) { QUADSPI->CCR = 0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 0 << QUADSPI_CCR_FMODE_Pos // indirect write mode | 0 << QUADSPI_CCR_DMODE_Pos // no data | 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles | 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte | 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size | 1 << QUADSPI_CCR_ADMODE_Pos // address on 1 line | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode ; QUADSPI->AR = addr; } else { QUADSPI->DLR = len - 1; QUADSPI->CCR = 0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 0 << QUADSPI_CCR_FMODE_Pos // indirect write mode | 1 << QUADSPI_CCR_DMODE_Pos // data on 1 line | 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles | 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte | 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size | 1 << QUADSPI_CCR_ADMODE_Pos // address on 1 line | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode ; QUADSPI->AR = addr; // Write out the data 1 byte at a time while (len) { while (!(QUADSPI->SR & QUADSPI_SR_FTF)) { } *(volatile uint8_t*)&QUADSPI->DR = *src++; --len; } } // Wait for write to finish while (!(QUADSPI->SR & QUADSPI_SR_TCF)) { } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag } STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { (void)self_in; QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag QUADSPI->DLR = len - 1; // number of bytes to read QUADSPI->CCR = 0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 1 << QUADSPI_CCR_FMODE_Pos // indirect read mode | 1 << QUADSPI_CCR_DMODE_Pos // data on 1 line | 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles | 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte | 0 << QUADSPI_CCR_ADMODE_Pos // no address | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // read opcode ; // Wait for read to finish while (!(QUADSPI->SR & QUADSPI_SR_TCF)) { } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag // Read result return QUADSPI->DR; } STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { (void)self_in; QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag QUADSPI->DLR = len - 1; // number of bytes to read QUADSPI->CCR = 0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction | 1 << QUADSPI_CCR_FMODE_Pos // indirect read mode | 3 << QUADSPI_CCR_DMODE_Pos // data on 4 lines | 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles | 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte | 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines | 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size | 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode ; QUADSPI->ABR = 0; // alternate byte: disable continuous read mode QUADSPI->AR = addr; // addres to read from // Read in the data 4 bytes at a time if dest is aligned if (((uintptr_t)dest & 3) == 0) { while (len >= 4) { while (!(QUADSPI->SR & QUADSPI_SR_FTF)) { } *(uint32_t*)dest = QUADSPI->DR; dest += 4; len -= 4; } } // Read in remaining data 1 byte at a time while (len) { while (!((QUADSPI->SR >> QUADSPI_SR_FLEVEL_Pos) & 0x3f)) { } *dest++ = *(volatile uint8_t*)&QUADSPI->DR; --len; } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag } const mp_qspi_proto_t qspi_proto = { .ioctl = qspi_ioctl, .write_cmd_data = qspi_write_cmd_data, .write_cmd_addr_data = qspi_write_cmd_addr_data, .read_cmd = qspi_read_cmd, .read_cmd_qaddr_qdata = qspi_read_cmd_qaddr_qdata, }; #endif // defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2) micropython-1.12/ports/stm32/qspi.h000066400000000000000000000026721357706137100172750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_QSPI_H #define MICROPY_INCLUDED_STM32_QSPI_H #include "drivers/bus/qspi.h" extern const mp_qspi_proto_t qspi_proto; void qspi_init(void); void qspi_memory_map(void); #endif // MICROPY_INCLUDED_STM32_QSPI_H micropython-1.12/ports/stm32/qstrdefsport.h000066400000000000000000000026331357706137100210560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // qstrs specific to this port // Entries for sys.path Q(/flash) Q(/flash/lib) Q(/sd) Q(/sd/lib) // For uos.sep Q(/) #if MICROPY_HW_ENABLE_USB // for usb modes Q(MSC+HID) Q(VCP+MSC) Q(VCP+HID) #endif micropython-1.12/ports/stm32/resethandler.s000066400000000000000000000043051357706137100210070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ .syntax unified .cpu cortex-m4 .thumb .section .text.Reset_Handler .global Reset_Handler .type Reset_Handler, %function Reset_Handler: /* Save the first argument to pass through to stm32_main */ mov r4, r0 /* Load the stack pointer */ ldr sp, =_estack /* Initialise the data section */ ldr r1, =_sidata ldr r2, =_sdata ldr r3, =_edata b .data_copy_entry .data_copy_loop: ldr r0, [r1], #4 /* Should be 4-aligned to be as fast as possible */ str r0, [r2], #4 .data_copy_entry: cmp r2, r3 bcc .data_copy_loop /* Zero out the BSS section */ movs r0, #0 ldr r1, =_sbss ldr r2, =_ebss b .bss_zero_entry .bss_zero_loop: str r0, [r1], #4 /* Should be 4-aligned to be as fast as possible */ .bss_zero_entry: cmp r1, r2 bcc .bss_zero_loop /* Initialise the system and jump to the main code */ bl SystemInit mov r0, r4 b stm32_main .size Reset_Handler, .-Reset_Handler micropython-1.12/ports/stm32/resethandler_m0.s000066400000000000000000000042211357706137100214000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ .syntax unified .cpu cortex-m0 .thumb .section .text.Reset_Handler .global Reset_Handler .type Reset_Handler, %function Reset_Handler: /* Save the first argument to pass through to stm32_main */ mov r4, r0 /* Load the stack pointer */ ldr r0, =_estack mov sp, r0 /* Initialise the data section */ ldr r1, =_sidata ldr r2, =_sdata ldr r3, =_edata b .data_copy_entry .data_copy_loop: ldr r0, [r1] adds r1, #4 str r0, [r2] adds r2, #4 .data_copy_entry: cmp r2, r3 bcc .data_copy_loop /* Zero out the BSS section */ movs r0, #0 ldr r1, =_sbss ldr r2, =_ebss b .bss_zero_entry .bss_zero_loop: str r0, [r1] adds r1, #4 .bss_zero_entry: cmp r1, r2 bcc .bss_zero_loop /* Initialise the system and jump to the main code */ bl SystemInit mov r0, r4 bl stm32_main .size Reset_Handler, .-Reset_Handler micropython-1.12/ports/stm32/rfcore.c000066400000000000000000000330771357706137100175770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mperrno.h" #include "py/mphal.h" #include "rtc.h" #include "rfcore.h" #if defined(STM32WB) // Define to 1 to print traces of HCI packets #define HCI_TRACE (0) #define IPCC_CH_BLE (0x01) // BLE HCI command and response #define IPCC_CH_SYS (0x02) // system HCI command and response #define IPCC_CH_MM (0x08) // release buffer #define IPCC_CH_HCI_ACL (0x20) // HCI ACL outgoing data #define OGF_VENDOR (0x3f) #define OCF_WRITE_CONFIG (0x0c) #define OCF_SET_TX_POWER (0x0f) #define OCF_BLE_INIT (0x66) #define HCI_OPCODE(ogf, ocf) ((ogf) << 10 | (ocf)) typedef struct _tl_list_node_t { volatile struct _tl_list_node_t *next; volatile struct _tl_list_node_t *prev; uint8_t body[0]; } tl_list_node_t; typedef struct _parse_hci_info_t { int (*cb_fun)(void*, uint8_t); void *cb_env; bool was_hci_reset_evt; } parse_hci_info_t; static volatile uint32_t ipcc_mem_dev_info_tab[8]; static volatile uint32_t ipcc_mem_ble_tab[4]; static volatile uint32_t ipcc_mem_sys_tab[2]; static volatile uint32_t ipcc_mem_memmgr_tab[7]; static volatile uint32_t ipcc_mem_sys_cmd_buf[272 / 4]; static volatile tl_list_node_t ipcc_mem_sys_queue; static volatile tl_list_node_t ipcc_mem_memmgr_free_buf_queue; static volatile uint32_t ipcc_mem_memmgr_ble_spare_evt_buf[272 / 4]; static volatile uint32_t ipcc_mem_memmgr_sys_spare_evt_buf[272 / 4]; static volatile uint32_t ipcc_mem_memmgr_evt_pool[6 * 272 / 4]; static volatile uint32_t ipcc_mem_ble_cmd_buf[272 / 4]; static volatile uint32_t ipcc_mem_ble_cs_buf[272 / 4]; static volatile tl_list_node_t ipcc_mem_ble_evt_queue; static volatile uint32_t ipcc_mem_ble_hci_acl_data_buf[272 / 4]; /******************************************************************************/ // Transport layer linked list STATIC void tl_list_init(volatile tl_list_node_t *n) { n->next = n; n->prev = n; } STATIC volatile tl_list_node_t *tl_list_unlink(volatile tl_list_node_t *n) { volatile tl_list_node_t *next = n->next; volatile tl_list_node_t *prev = n->prev; prev->next = next; next->prev = prev; return next; } STATIC void tl_list_append(volatile tl_list_node_t *head, volatile tl_list_node_t *n) { n->next = head; n->prev = head->prev; head->prev->next = n; head->prev = n; } /******************************************************************************/ // IPCC interface STATIC uint32_t get_ipccdba(void) { return *(uint32_t*)(OPTION_BYTE_BASE + 0x68) & 0x3fff; } STATIC volatile void **get_buffer_table(void) { return (volatile void**)(SRAM2A_BASE + get_ipccdba()); } void ipcc_init(uint32_t irq_pri) { // Setup buffer table pointers volatile void **tab = get_buffer_table(); tab[0] = &ipcc_mem_dev_info_tab[0]; tab[1] = &ipcc_mem_ble_tab[0]; tab[3] = &ipcc_mem_sys_tab[0]; tab[4] = &ipcc_mem_memmgr_tab[0]; // Start IPCC peripheral __HAL_RCC_IPCC_CLK_ENABLE(); // Enable wanted IRQs IPCC->C1CR = 0;//IPCC_C1CR_RXOIE; IPCC->C1MR = 0xffffffff; NVIC_SetPriority(IPCC_C1_RX_IRQn, irq_pri); HAL_NVIC_EnableIRQ(IPCC_C1_RX_IRQn); // Device info table will be populated by FUS/WS // Populate system table tl_list_init(&ipcc_mem_sys_queue); ipcc_mem_sys_tab[0] = (uint32_t)&ipcc_mem_sys_cmd_buf[0]; ipcc_mem_sys_tab[1] = (uint32_t)&ipcc_mem_sys_queue; // Populate memory manager table tl_list_init(&ipcc_mem_memmgr_free_buf_queue); ipcc_mem_memmgr_tab[0] = (uint32_t)&ipcc_mem_memmgr_ble_spare_evt_buf[0]; ipcc_mem_memmgr_tab[1] = (uint32_t)&ipcc_mem_memmgr_sys_spare_evt_buf[0]; ipcc_mem_memmgr_tab[2] = (uint32_t)&ipcc_mem_memmgr_evt_pool[0]; ipcc_mem_memmgr_tab[3] = sizeof(ipcc_mem_memmgr_evt_pool); ipcc_mem_memmgr_tab[4] = (uint32_t)&ipcc_mem_memmgr_free_buf_queue; ipcc_mem_memmgr_tab[5] = 0; ipcc_mem_memmgr_tab[6] = 0; // Populate BLE table tl_list_init(&ipcc_mem_ble_evt_queue); ipcc_mem_ble_tab[0] = (uint32_t)&ipcc_mem_ble_cmd_buf[0]; ipcc_mem_ble_tab[1] = (uint32_t)&ipcc_mem_ble_cs_buf[0]; ipcc_mem_ble_tab[2] = (uint32_t)&ipcc_mem_ble_evt_queue; ipcc_mem_ble_tab[3] = (uint32_t)&ipcc_mem_ble_hci_acl_data_buf[0]; } STATIC int ipcc_wait_ack(unsigned int ch, uint32_t timeout_ms) { uint32_t t0 = mp_hal_ticks_ms(); while (IPCC->C1TOC2SR & ch) { if (mp_hal_ticks_ms() - t0 > timeout_ms) { printf("ipcc_wait_ack: timeout\n"); return -MP_ETIMEDOUT; } } // C2 cleared IPCC flag return 0; } STATIC int ipcc_wait_msg(unsigned int ch, uint32_t timeout_ms) { uint32_t t0 = mp_hal_ticks_ms(); while (!(IPCC->C2TOC1SR & ch)) { if (mp_hal_ticks_ms() - t0 > timeout_ms) { printf("ipcc_wait_msg: timeout\n"); return -MP_ETIMEDOUT; } } // C2 set IPCC flag return 0; } /******************************************************************************/ // Transport layer HCI interface STATIC void tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) { const char *kind; size_t len = 3 + buf[2]; switch (buf[0]) { case 0x02: { // Standard BT HCI ACL packet kind = "HCI_ACL"; if (parse != NULL) { for (size_t i = 0; i < len; ++i) { parse->cb_fun(parse->cb_env, buf[i]); } } break; } case 0x04: { // Standard BT HCI event packet kind = "HCI_EVT"; if (parse != NULL) { bool fix = false; if (buf[1] == 0x0e && len == 7 && buf[3] == 0x01 && buf[4] == 0x63 && buf[5] == 0x0c && buf[6] == 0x01) { len -= 1; fix = true; } for (size_t i = 0; i < len; ++i) { parse->cb_fun(parse->cb_env, buf[i]); } if (fix) { len += 1; parse->cb_fun(parse->cb_env, 0x00); // success } // Check for successful HCI_Reset event parse->was_hci_reset_evt = buf[1] == 0x0e && buf[2] == 0x04 && buf[3] == 0x01 && buf[4] == 0x03 && buf[5] == 0x0c && buf[6] == 0x00; } break; } case 0x11: { // Response packet // assert(buf[1] == 0x0e); kind = "VEND_RESP"; //uint16_t cmd = buf[4] | buf[5] << 8; //uint8_t status = buf[6]; break; } case 0x12: { // Event packet // assert(buf[1] == 0xff); kind = "VEND_EVT"; //uint16_t evt = buf[3] | buf[4] << 8; break; } default: kind = "HCI_UNKNOWN"; break; } #if HCI_TRACE printf("[% 8d] %s(%02x", mp_hal_ticks_ms(), kind, buf[0]); for (int i = 1; i < len; ++i) { printf(":%02x", buf[i]); } printf(")\n"); #else (void)kind; #endif } STATIC void tl_check_msg(volatile tl_list_node_t *head, unsigned int ch, parse_hci_info_t *parse) { if (IPCC->C2TOC1SR & ch) { // Message available on CH2 volatile tl_list_node_t *cur = head->next; bool free = false; while (cur != head) { tl_parse_hci_msg((uint8_t*)cur->body, parse); volatile tl_list_node_t *next = tl_list_unlink(cur); if ((void*)&ipcc_mem_memmgr_evt_pool[0] <= (void*)cur && (void*)cur < (void*)&ipcc_mem_memmgr_evt_pool[MP_ARRAY_SIZE(ipcc_mem_memmgr_evt_pool)]) { // Place memory back in free pool tl_list_append(&ipcc_mem_memmgr_free_buf_queue, cur); free = true; } cur = next; } if (free) { // Notify change in free pool IPCC->C1SCR = IPCC_CH_MM << 16; } // Clear receive channel IPCC->C1SCR = ch; } } STATIC void tl_hci_cmd(uint8_t *cmd, unsigned int ch, uint8_t hdr, uint16_t opcode, size_t len, const uint8_t *buf) { tl_list_node_t *n = (tl_list_node_t*)cmd; n->next = n; n->prev = n; cmd[8] = hdr; cmd[9] = opcode; cmd[10] = opcode >> 8; cmd[11] = len; memcpy(&cmd[12], buf, len); // IPCC indicate IPCC->C1SCR = ch << 16; } STATIC void tl_sys_wait_resp(const uint8_t *buf, unsigned int ch) { if (ipcc_wait_ack(ch, 250) == 0) { tl_parse_hci_msg(buf, NULL); } } STATIC void tl_sys_hci_cmd_resp(uint16_t opcode, size_t len, const uint8_t *buf) { tl_hci_cmd((uint8_t*)&ipcc_mem_sys_cmd_buf, IPCC_CH_SYS, 0x10, opcode, len, buf); tl_sys_wait_resp((uint8_t*)&ipcc_mem_sys_cmd_buf, IPCC_CH_SYS); } STATIC void tl_ble_hci_cmd_resp(uint16_t opcode, size_t len, const uint8_t *buf) { tl_hci_cmd((uint8_t*)&ipcc_mem_ble_cmd_buf[0], IPCC_CH_BLE, 0x01, opcode, len, buf); ipcc_wait_msg(IPCC_CH_BLE, 250); tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, NULL); } /******************************************************************************/ // RF core interface void rfcore_init(void) { // Ensure LSE is running rtc_init_finalise(); // Select LSE as RF wakeup source RCC->CSR = (RCC->CSR & ~RCC_CSR_RFWKPSEL) | 1 << RCC_CSR_RFWKPSEL_Pos; // Initialise IPCC and shared memory structures ipcc_init(IRQ_PRI_SDIO); // Boot the second core __SEV(); __WFE(); PWR->CR4 |= PWR_CR4_C2BOOT; } static const struct { uint8_t* pBleBufferAddress; // unused uint32_t BleBufferSize; // unused uint16_t NumAttrRecord; uint16_t NumAttrServ; uint16_t AttrValueArrSize; uint8_t NumOfLinks; uint8_t ExtendedPacketLengthEnable; uint8_t PrWriteListSize; uint8_t MblockCount; uint16_t AttMtu; uint16_t SlaveSca; uint8_t MasterSca; uint8_t LsSource; // 0=LSE 1=internal RO uint32_t MaxConnEventLength; uint16_t HsStartupTime; uint8_t ViterbiEnable; uint8_t LlOnly; // 0=LL+Host, 1=LL only uint8_t HwVersion; } ble_init_params = { 0, 0, 0, // NumAttrRecord 0, // NumAttrServ 0, // AttrValueArrSize 1, // NumOfLinks 1, // ExtendedPacketLengthEnable 0, // PrWriteListSize 0x79, // MblockCount 0, // AttMtu 0, // SlaveSca 0, // MasterSca 1, // LsSource 0xffffffff, // MaxConnEventLength 0x148, // HsStartupTime 0, // ViterbiEnable 1, // LlOnly 0, // HwVersion }; void rfcore_ble_init(void) { // Clear any outstanding messages from ipcc_init tl_check_msg(&ipcc_mem_sys_queue, IPCC_CH_SYS, NULL); tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, NULL); // Configure and reset the BLE controller tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), sizeof(ble_init_params), (const uint8_t*)&ble_init_params); tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), 0, NULL); } void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) { #if HCI_TRACE printf("[% 8d] HCI_CMD(%02x", mp_hal_ticks_ms(), src[0]); for (int i = 1; i < len; ++i) { printf(":%02x", src[i]); } printf(")\n"); #endif tl_list_node_t *n; uint32_t ch; if (src[0] == 0x01) { n = (tl_list_node_t*)&ipcc_mem_ble_cmd_buf[0]; ch = IPCC_CH_BLE; } else if (src[0] == 0x02) { n = (tl_list_node_t*)&ipcc_mem_ble_hci_acl_data_buf[0]; ch = IPCC_CH_HCI_ACL; } else { printf("** UNEXPECTED HCI HDR: 0x%02x **\n", src[0]); return; } n->next = n; n->prev = n; memcpy(n->body, src, len); // IPCC indicate IPCC->C1SCR = ch << 16; } void rfcore_ble_check_msg(int (*cb)(void*, uint8_t), void *env) { parse_hci_info_t parse = { cb, env, false }; tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, &parse); // Intercept HCI_Reset events and reconfigure the controller following the reset if (parse.was_hci_reset_evt) { uint8_t buf[8]; buf[0] = 0; // config offset buf[1] = 6; // config length mp_hal_get_mac(MP_HAL_MAC_BDADDR, &buf[2]); #define SWAP_UINT8(a, b) { uint8_t temp = a; a = b; b = temp; } SWAP_UINT8(buf[2], buf[7]); SWAP_UINT8(buf[3], buf[6]); SWAP_UINT8(buf[4], buf[5]); tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_WRITE_CONFIG), 8, buf); // set BDADDR tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_SET_TX_POWER), 2, (const uint8_t*)"\x00\x06"); // 0 dBm } } #endif // defined(STM32WB) micropython-1.12/ports/stm32/rfcore.h000066400000000000000000000030111357706137100175650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_RFCORE_H #define MICROPY_INCLUDED_STM32_RFCORE_H #include void rfcore_init(void); void rfcore_ble_init(void); void rfcore_ble_hci_cmd(size_t len, const uint8_t *src); void rfcore_ble_check_msg(int (*cb)(void*, uint8_t), void *env); #endif // MICROPY_INCLUDED_STM32_RFCORE_H micropython-1.12/ports/stm32/rng.c000066400000000000000000000056711357706137100171040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "rng.h" #if MICROPY_HW_ENABLE_RNG #define RNG_TIMEOUT_MS (10) uint32_t rng_get(void) { // Enable the RNG peripheral if it's not already enabled if (!(RNG->CR & RNG_CR_RNGEN)) { #if defined(STM32H7) // Set RNG Clock source __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ); __HAL_RCC_RNG_CONFIG(RCC_RNGCLKSOURCE_PLL); #endif __HAL_RCC_RNG_CLK_ENABLE(); RNG->CR |= RNG_CR_RNGEN; } // Wait for a new random number to be ready, takes on the order of 10us uint32_t start = HAL_GetTick(); while (!(RNG->SR & RNG_SR_DRDY)) { if (HAL_GetTick() - start >= RNG_TIMEOUT_MS) { return 0; } } // Get and return the new random number return RNG->DR; } // Return a 30-bit hardware generated random number. STATIC mp_obj_t pyb_rng_get(void) { return mp_obj_new_int(rng_get() >> 2); } MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get); #else // MICROPY_HW_ENABLE_RNG // For MCUs that don't have an RNG we still need to provide a rng_get() function, // eg for lwIP. A pseudo-RNG is not really ideal but we go with it for now. We // don't want to use urandom's pRNG because then the user won't see a reproducible // random stream. // Yasmarang random number generator by Ilya Levin // http://www.literatecode.com/yasmarang STATIC uint32_t pyb_rng_yasmarang(void) { static uint32_t pad = 0xeda4baba, n = 69, d = 233; static uint8_t dat = 0; pad += dat + d * n; pad = (pad << 3) + (pad >> 29); n = pad | 2; d ^= (pad << 31) + (pad >> 1); dat ^= (char)pad ^ (d >> 8) ^ 1; return pad ^ (d << 5) ^ (pad >> 18) ^ (dat << 1); } uint32_t rng_get(void) { return pyb_rng_yasmarang(); } #endif // MICROPY_HW_ENABLE_RNG micropython-1.12/ports/stm32/rng.h000066400000000000000000000026351357706137100171060ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_RNG_H #define MICROPY_INCLUDED_STM32_RNG_H #include "py/obj.h" uint32_t rng_get(void); MP_DECLARE_CONST_FUN_OBJ_0(pyb_rng_get_obj); #endif // MICROPY_INCLUDED_STM32_RNG_H micropython-1.12/ports/stm32/rtc.c000066400000000000000000000642311357706137100171030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "extint.h" #include "rtc.h" #include "irq.h" #if defined(STM32WB) #define RCC_CSR_LSION RCC_CSR_LSI1ON #define RCC_FLAG_LSIRDY RCC_FLAG_LSI1RDY #define RCC_OSCILLATORTYPE_LSI RCC_OSCILLATORTYPE_LSI1 #define __HAL_RCC_LSI_ENABLE __HAL_RCC_LSI1_ENABLE #define __HAL_RCC_LSI_DISABLE __HAL_RCC_LSI1_DISABLE #endif /// \moduleref pyb /// \class RTC - real time clock /// /// The RTC is and independent clock that keeps track of the date /// and time. /// /// Example usage: /// /// rtc = pyb.RTC() /// rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0)) /// print(rtc.datetime()) RTC_HandleTypeDef RTCHandle; // rtc_info indicates various things about RTC startup // it's a bit of a hack at the moment static mp_uint_t rtc_info; // Note: LSI is around (32KHz), these dividers should work either way // ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1) // modify RTC_ASYNCH_PREDIV & RTC_SYNCH_PREDIV in board//mpconfigport.h to change sub-second ticks // default is 3906.25 us, min is ~30.52 us (will increase Ivbat by ~500nA) #ifndef RTC_ASYNCH_PREDIV #define RTC_ASYNCH_PREDIV (0x7f) #endif #ifndef RTC_SYNCH_PREDIV #define RTC_SYNCH_PREDIV (0x00ff) #endif STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc); STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse, bool rtc_use_byp); STATIC HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc); STATIC void RTC_CalendarConfig(void); #if MICROPY_HW_RTC_USE_LSE || MICROPY_HW_RTC_USE_BYPASS STATIC bool rtc_use_lse = true; #else STATIC bool rtc_use_lse = false; #endif STATIC uint32_t rtc_startup_tick; STATIC bool rtc_need_init_finalise = false; #if defined(STM32L0) #define BDCR CSR #define RCC_BDCR_RTCEN RCC_CSR_RTCEN #define RCC_BDCR_RTCSEL RCC_CSR_RTCSEL #define RCC_BDCR_RTCSEL_0 RCC_CSR_RTCSEL_0 #define RCC_BDCR_RTCSEL_1 RCC_CSR_RTCSEL_1 #define RCC_BDCR_LSEON RCC_CSR_LSEON #define RCC_BDCR_LSERDY RCC_CSR_LSERDY #define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP #endif void rtc_init_start(bool force_init) { RTCHandle.Instance = RTC; /* Configure RTC prescaler and RTC data registers */ /* RTC configured as follow: - Hour Format = Format 24 - Asynch Prediv = Value according to source clock - Synch Prediv = Value according to source clock - OutPut = Output Disable - OutPutPolarity = High Polarity - OutPutType = Open Drain */ RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24; RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV; RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV; RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; rtc_need_init_finalise = false; if (!force_init) { uint32_t bdcr = RCC->BDCR; if ((bdcr & (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL | RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) == (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_0 | RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) { // LSE is enabled & ready --> no need to (re-)init RTC // remove Backup Domain write protection HAL_PWR_EnableBkUpAccess(); // Clear source Reset Flag __HAL_RCC_CLEAR_RESET_FLAGS(); // provide some status information rtc_info |= 0x40000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8; return; } else if ((bdcr & (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL)) == (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_1)) { // LSI configured as the RTC clock source --> no need to (re-)init RTC // remove Backup Domain write protection HAL_PWR_EnableBkUpAccess(); // Clear source Reset Flag __HAL_RCC_CLEAR_RESET_FLAGS(); // Turn the LSI on (it may need this even if the RTC is running) RCC->CSR |= RCC_CSR_LSION; // provide some status information rtc_info |= 0x80000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8; return; } } rtc_startup_tick = HAL_GetTick(); rtc_info = 0x3f000000 | (rtc_startup_tick & 0xffffff); PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse, MICROPY_HW_RTC_USE_BYPASS); } void rtc_init_finalise() { if (!rtc_need_init_finalise) { return; } rtc_info = 0; while (PYB_RTC_Init(&RTCHandle) != HAL_OK) { if (rtc_use_lse) { #if MICROPY_HW_RTC_USE_BYPASS if (RCC->BDCR & RCC_BDCR_LSEBYP) { // LSEBYP failed, fallback to LSE non-bypass rtc_info |= 0x02000000; } else #endif { // LSE failed, fallback to LSI rtc_use_lse = false; rtc_info |= 0x01000000; } rtc_startup_tick = HAL_GetTick(); PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse, false); HAL_PWR_EnableBkUpAccess(); RTCHandle.State = HAL_RTC_STATE_RESET; } else { // init error rtc_info |= 0xffff; // indicate error return; } } // RTC started successfully rtc_info = 0x20000000; // record if LSE or LSI is used rtc_info |= (rtc_use_lse << 28); // record how long it took for the RTC to start up rtc_info |= (HAL_GetTick() - rtc_startup_tick) & 0xffff; // fresh reset; configure RTC Calendar RTC_CalendarConfig(); #if defined(STM32L4) || defined(STM32WB) if(__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) != RESET) { #else if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) { #endif // power on reset occurred rtc_info |= 0x10000; } if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET) { // external reset occurred rtc_info |= 0x20000; } // Clear source Reset Flag __HAL_RCC_CLEAR_RESET_FLAGS(); rtc_need_init_finalise = false; } STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) { /*------------------------------ LSI Configuration -------------------------*/ if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) { // Check the LSI State if (RCC_OscInitStruct->LSIState != RCC_LSI_OFF) { // Enable the Internal Low Speed oscillator (LSI). __HAL_RCC_LSI_ENABLE(); } else { // Disable the Internal Low Speed oscillator (LSI). __HAL_RCC_LSI_DISABLE(); } } /*------------------------------ LSE Configuration -------------------------*/ if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) { #if !defined(STM32H7) && !defined(STM32WB) // Enable Power Clock __HAL_RCC_PWR_CLK_ENABLE(); #endif // Enable access to the backup domain HAL_PWR_EnableBkUpAccess(); uint32_t tickstart = HAL_GetTick(); #if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) //__HAL_RCC_PWR_CLK_ENABLE(); // Enable write access to Backup domain //PWR->CR1 |= PWR_CR1_DBP; // Wait for Backup domain Write protection disable while ((PWR->CR1 & PWR_CR1_DBP) == RESET) { if (HAL_GetTick() - tickstart > RCC_DBP_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } #else // Enable write access to Backup domain //PWR->CR |= PWR_CR_DBP; // Wait for Backup domain Write protection disable while ((PWR->CR & PWR_CR_DBP) == RESET) { if (HAL_GetTick() - tickstart > RCC_DBP_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } #endif #if MICROPY_HW_RTC_USE_BYPASS // If LSEBYP is enabled and new state is non-bypass then disable LSEBYP if (RCC_OscInitStruct->LSEState == RCC_LSE_ON && (RCC->BDCR & RCC_BDCR_LSEBYP)) { CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); while (RCC->BDCR & RCC_BDCR_LSERDY) { } CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); } #endif // Set the new LSE configuration __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); } return HAL_OK; } STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) { // Check the RTC peripheral state if (hrtc == NULL) { return HAL_ERROR; } if (hrtc->State == HAL_RTC_STATE_RESET) { // Allocate lock resource and initialize it hrtc->Lock = HAL_UNLOCKED; // Initialize RTC MSP if (PYB_RTC_MspInit_Finalise(hrtc) != HAL_OK) { return HAL_ERROR; } } // Set RTC state hrtc->State = HAL_RTC_STATE_BUSY; // Disable the write protection for RTC registers __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); // Set Initialization mode if (RTC_EnterInitMode(hrtc) != HAL_OK) { // Enable the write protection for RTC registers __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); // Set RTC state hrtc->State = HAL_RTC_STATE_ERROR; return HAL_ERROR; } else { // Clear RTC_CR FMT, OSEL and POL Bits hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL)); // Set RTC_CR register hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity); // Configure the RTC PRER hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv); hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << 16); // Exit Initialization mode hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) hrtc->Instance->OR &= (uint32_t)~RTC_OR_ALARMOUTTYPE; hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType); #elif defined(STM32F7) hrtc->Instance->OR &= (uint32_t)~RTC_OR_ALARMTYPE; hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType); #else hrtc->Instance->TAFCR &= (uint32_t)~RTC_TAFCR_ALARMOUTTYPE; hrtc->Instance->TAFCR |= (uint32_t)(hrtc->Init.OutPutType); #endif // Enable the write protection for RTC registers __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); // Set RTC state hrtc->State = HAL_RTC_STATE_READY; return HAL_OK; } } STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse, bool rtc_use_byp) { /* To change the source clock of the RTC feature (LSE, LSI), You have to: - Enable the power clock using __PWR_CLK_ENABLE() - Enable write access using HAL_PWR_EnableBkUpAccess() function before to configure the RTC clock source (to be done once after reset). - Reset the Back up Domain using __HAL_RCC_BACKUPRESET_FORCE() and __HAL_RCC_BACKUPRESET_RELEASE(). - Configure the needed RTc clock source */ // RTC clock source uses LSE (external crystal) only if relevant // configuration variable is set. Otherwise it uses LSI (internal osc). RCC_OscInitTypeDef RCC_OscInitStruct; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; #if MICROPY_HW_RTC_USE_BYPASS if (rtc_use_byp) { RCC_OscInitStruct.LSEState = RCC_LSE_BYPASS; RCC_OscInitStruct.LSIState = RCC_LSI_OFF; } else #endif if (rtc_use_lse) { RCC_OscInitStruct.LSEState = RCC_LSE_ON; RCC_OscInitStruct.LSIState = RCC_LSI_OFF; } else { RCC_OscInitStruct.LSEState = RCC_LSE_OFF; RCC_OscInitStruct.LSIState = RCC_LSI_ON; } PYB_RCC_OscConfig(&RCC_OscInitStruct); // now ramp up osc. in background and flag calendear init needed rtc_need_init_finalise = true; } #ifndef MICROPY_HW_RTC_LSE_TIMEOUT_MS #define MICROPY_HW_RTC_LSE_TIMEOUT_MS 1000 // ST docs spec 2000 ms LSE startup, seems to be too pessimistic #endif #ifndef MICROPY_HW_RTC_LSI_TIMEOUT_MS #define MICROPY_HW_RTC_LSI_TIMEOUT_MS 500 // this is way too pessimistic, typ. < 1ms #endif #ifndef MICROPY_HW_RTC_BYP_TIMEOUT_MS #define MICROPY_HW_RTC_BYP_TIMEOUT_MS 150 #endif STATIC HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc) { // we already had a kick so now wait for the corresponding ready state... if (rtc_use_lse) { // we now have to wait for LSE ready or timeout uint32_t timeout = MICROPY_HW_RTC_LSE_TIMEOUT_MS; #if MICROPY_HW_RTC_USE_BYPASS if (RCC->BDCR & RCC_BDCR_LSEBYP) { timeout = MICROPY_HW_RTC_BYP_TIMEOUT_MS; } #endif uint32_t tickstart = rtc_startup_tick; while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) { if ((HAL_GetTick() - tickstart ) > timeout) { return HAL_TIMEOUT; } } } else { // we now have to wait for LSI ready or timeout uint32_t tickstart = rtc_startup_tick; while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET) { if ((HAL_GetTick() - tickstart ) > MICROPY_HW_RTC_LSI_TIMEOUT_MS) { return HAL_TIMEOUT; } } } RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; if (rtc_use_lse) { PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; } else { PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; } if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { //Error_Handler(); return HAL_ERROR; } // enable RTC peripheral clock __HAL_RCC_RTC_ENABLE(); return HAL_OK; } STATIC void RTC_CalendarConfig(void) { // set the date to 1st Jan 2015 RTC_DateTypeDef date; date.Year = 15; date.Month = 1; date.Date = 1; date.WeekDay = RTC_WEEKDAY_THURSDAY; if(HAL_RTC_SetDate(&RTCHandle, &date, RTC_FORMAT_BIN) != HAL_OK) { // init error return; } // set the time to 00:00:00 RTC_TimeTypeDef time; time.Hours = 0; time.Minutes = 0; time.Seconds = 0; time.TimeFormat = RTC_HOURFORMAT12_AM; time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; time.StoreOperation = RTC_STOREOPERATION_RESET; if (HAL_RTC_SetTime(&RTCHandle, &time, RTC_FORMAT_BIN) != HAL_OK) { // init error return; } } /******************************************************************************/ // MicroPython bindings typedef struct _pyb_rtc_obj_t { mp_obj_base_t base; } pyb_rtc_obj_t; STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}}; /// \classmethod \constructor() /// Create an RTC object. STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); // return constant object return MP_OBJ_FROM_PTR(&pyb_rtc_obj); } // force rtc to re-initialise mp_obj_t pyb_rtc_init(mp_obj_t self_in) { rtc_init_start(true); rtc_init_finalise(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_init_obj, pyb_rtc_init); /// \method info() /// Get information about the startup time and reset source. /// /// - The lower 0xffff are the number of milliseconds the RTC took to /// start up. /// - Bit 0x10000 is set if a power-on reset occurred. /// - Bit 0x20000 is set if an external reset occurred mp_obj_t pyb_rtc_info(mp_obj_t self_in) { return mp_obj_new_int(rtc_info); } MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_info_obj, pyb_rtc_info); /// \method datetime([datetimetuple]) /// Get or set the date and time of the RTC. /// /// With no arguments, this method returns an 8-tuple with the current /// date and time. With 1 argument (being an 8-tuple) it sets the date /// and time. /// /// The 8-tuple has the following format: /// /// (year, month, day, weekday, hours, minutes, seconds, subseconds) /// /// `weekday` is 1-7 for Monday through Sunday. /// /// `subseconds` counts down from 255 to 0 #define MEG_DIV_64 (1000000 / 64) #define MEG_DIV_SCALE ((RTC_SYNCH_PREDIV + 1) / 64) #if defined(MICROPY_HW_RTC_USE_US) && MICROPY_HW_RTC_USE_US uint32_t rtc_subsec_to_us(uint32_t ss) { return ((RTC_SYNCH_PREDIV - ss) * MEG_DIV_64) / MEG_DIV_SCALE; } uint32_t rtc_us_to_subsec(uint32_t us) { return RTC_SYNCH_PREDIV - (us * MEG_DIV_SCALE / MEG_DIV_64); } #else #define rtc_us_to_subsec #define rtc_subsec_to_us #endif mp_obj_t pyb_rtc_datetime(size_t n_args, const mp_obj_t *args) { rtc_init_finalise(); if (n_args == 1) { // get date and time // note: need to call get time then get date to correctly access the registers RTC_DateTypeDef date; RTC_TimeTypeDef time; HAL_RTC_GetTime(&RTCHandle, &time, RTC_FORMAT_BIN); HAL_RTC_GetDate(&RTCHandle, &date, RTC_FORMAT_BIN); mp_obj_t tuple[8] = { mp_obj_new_int(2000 + date.Year), mp_obj_new_int(date.Month), mp_obj_new_int(date.Date), mp_obj_new_int(date.WeekDay), mp_obj_new_int(time.Hours), mp_obj_new_int(time.Minutes), mp_obj_new_int(time.Seconds), mp_obj_new_int(rtc_subsec_to_us(time.SubSeconds)), }; return mp_obj_new_tuple(8, tuple); } else { // set date and time mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 8, &items); RTC_DateTypeDef date; date.Year = mp_obj_get_int(items[0]) - 2000; date.Month = mp_obj_get_int(items[1]); date.Date = mp_obj_get_int(items[2]); date.WeekDay = mp_obj_get_int(items[3]); HAL_RTC_SetDate(&RTCHandle, &date, RTC_FORMAT_BIN); RTC_TimeTypeDef time; time.Hours = mp_obj_get_int(items[4]); time.Minutes = mp_obj_get_int(items[5]); time.Seconds = mp_obj_get_int(items[6]); time.TimeFormat = RTC_HOURFORMAT12_AM; time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; time.StoreOperation = RTC_STOREOPERATION_SET; HAL_RTC_SetTime(&RTCHandle, &time, RTC_FORMAT_BIN); return mp_const_none; } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime); #if defined(STM32F0) || defined(STM32L0) #define RTC_WKUP_IRQn RTC_IRQn #endif // wakeup(None) // wakeup(ms, callback=None) // wakeup(wucksel, wut, callback) mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { // wut is wakeup counter start value, wucksel is clock source // counter is decremented at wucksel rate, and wakes the MCU when it gets to 0 // wucksel=0b000 is RTC/16 (RTC runs at 32768Hz) // wucksel=0b001 is RTC/8 // wucksel=0b010 is RTC/4 // wucksel=0b011 is RTC/2 // wucksel=0b100 is 1Hz clock // wucksel=0b110 is 1Hz clock with 0x10000 added to wut // so a 1 second wakeup could be wut=2047, wucksel=0b000, or wut=4095, wucksel=0b001, etc rtc_init_finalise(); // disable wakeup IRQ while we configure it HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn); bool enable = false; mp_int_t wucksel; mp_int_t wut; mp_obj_t callback = mp_const_none; if (n_args <= 3) { if (args[1] == mp_const_none) { // disable wakeup } else { // time given in ms mp_int_t ms = mp_obj_get_int(args[1]); mp_int_t div = 2; wucksel = 3; while (div <= 16 && ms > 2000 * div) { div *= 2; wucksel -= 1; } if (div <= 16) { wut = 32768 / div * ms / 1000; } else { // use 1Hz clock wucksel = 4; wut = ms / 1000; if (wut > 0x10000) { // wut too large for 16-bit register, try to offset by 0x10000 wucksel = 6; wut -= 0x10000; if (wut > 0x10000) { // wut still too large mp_raise_ValueError("wakeup value too large"); } } } // wut register should be 1 less than desired value, but guard against wut=0 if (wut > 0) { wut -= 1; } enable = true; } if (n_args == 3) { callback = args[2]; } } else { // config values given directly wucksel = mp_obj_get_int(args[1]); wut = mp_obj_get_int(args[2]); callback = args[3]; enable = true; } // set the callback MP_STATE_PORT(pyb_extint_callback)[EXTI_RTC_WAKEUP] = callback; // disable register write protection RTC->WPR = 0xca; RTC->WPR = 0x53; // clear WUTE RTC->CR &= ~RTC_CR_WUTE; // wait until WUTWF is set while (!(RTC->ISR & RTC_ISR_WUTWF)) { } if (enable) { // program WUT RTC->WUTR = wut; // set WUTIE to enable wakeup interrupts // set WUTE to enable wakeup // program WUCKSEL RTC->CR = (RTC->CR & ~7) | (1 << 14) | (1 << 10) | (wucksel & 7); // enable register write protection RTC->WPR = 0xff; // enable external interrupts on line EXTI_RTC_WAKEUP #if defined(STM32L4) || defined(STM32WB) EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; #else EXTI->IMR |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR |= 1 << EXTI_RTC_WAKEUP; #endif // clear interrupt flags RTC->ISR &= ~RTC_ISR_WUTF; #if defined(STM32L4) || defined(STM32WB) EXTI->PR1 = 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) EXTI_D1->PR1 = 1 << EXTI_RTC_WAKEUP; #else EXTI->PR = 1 << EXTI_RTC_WAKEUP; #endif NVIC_SetPriority(RTC_WKUP_IRQn, IRQ_PRI_RTC_WKUP); HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn); //printf("wut=%d wucksel=%d\n", wut, wucksel); } else { // clear WUTIE to disable interrupts RTC->CR &= ~RTC_CR_WUTIE; // enable register write protection RTC->WPR = 0xff; // disable external interrupts on line EXTI_RTC_WAKEUP #if defined(STM32L4) || defined(STM32WB) EXTI->IMR1 &= ~(1 << EXTI_RTC_WAKEUP); #elif defined(STM32H7) EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP; #else EXTI->IMR &= ~(1 << EXTI_RTC_WAKEUP); #endif } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_wakeup_obj, 2, 4, pyb_rtc_wakeup); // calibration(None) // calibration(cal) // When an integer argument is provided, check that it falls in the range [-511 to 512] // and set the calibration value; otherwise return calibration value mp_obj_t pyb_rtc_calibration(size_t n_args, const mp_obj_t *args) { rtc_init_finalise(); mp_int_t cal; if (n_args == 2) { cal = mp_obj_get_int(args[1]); mp_uint_t cal_p, cal_m; if (cal < -511 || cal > 512) { #if defined(MICROPY_HW_RTC_USE_CALOUT) && MICROPY_HW_RTC_USE_CALOUT if ((cal & 0xfffe) == 0x0ffe) { // turn on/off X18 (PC13) 512Hz output // Note: // Output will stay active even in VBAT mode (and inrease current) if (cal & 1) { HAL_RTCEx_SetCalibrationOutPut(&RTCHandle, RTC_CALIBOUTPUT_512HZ); } else { HAL_RTCEx_DeactivateCalibrationOutPut(&RTCHandle); } return mp_obj_new_int(cal & 1); } else { mp_raise_ValueError("calibration value out of range"); } #else mp_raise_ValueError("calibration value out of range"); #endif } if (cal > 0) { cal_p = RTC_SMOOTHCALIB_PLUSPULSES_SET; cal_m = 512 - cal; } else { cal_p = RTC_SMOOTHCALIB_PLUSPULSES_RESET; cal_m = -cal; } HAL_RTCEx_SetSmoothCalib(&RTCHandle, RTC_SMOOTHCALIB_PERIOD_32SEC, cal_p, cal_m); return mp_const_none; } else { // printf("CALR = 0x%x\n", (mp_uint_t) RTCHandle.Instance->CALR); // DEBUG // Test if CALP bit is set in CALR: if (RTCHandle.Instance->CALR & 0x8000) { cal = 512 - (RTCHandle.Instance->CALR & 0x1ff); } else { cal = -(RTCHandle.Instance->CALR & 0x1ff); } return mp_obj_new_int(cal); } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_calibration_obj, 1, 2, pyb_rtc_calibration); STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_rtc_init_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_rtc_info_obj) }, { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&pyb_rtc_datetime_obj) }, { MP_ROM_QSTR(MP_QSTR_wakeup), MP_ROM_PTR(&pyb_rtc_wakeup_obj) }, { MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&pyb_rtc_calibration_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table); const mp_obj_type_t pyb_rtc_type = { { &mp_type_type }, .name = MP_QSTR_RTC, .make_new = pyb_rtc_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_rtc_locals_dict, }; micropython-1.12/ports/stm32/rtc.h000066400000000000000000000030231357706137100171000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_RTC_H #define MICROPY_INCLUDED_STM32_RTC_H extern RTC_HandleTypeDef RTCHandle; extern const mp_obj_type_t pyb_rtc_type; void rtc_init_start(bool force_init); void rtc_init_finalise(void); mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args); #endif // MICROPY_INCLUDED_STM32_RTC_H micropython-1.12/ports/stm32/sdcard.c000066400000000000000000000747121357706137100175600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/mphal.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs_fat.h" #include "sdcard.h" #include "pin.h" #include "pin_static_af.h" #include "bufhelper.h" #include "dma.h" #include "irq.h" #if MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD #if defined(STM32F7) || defined(STM32H7) || defined(STM32L4) // The F7 has 2 SDMMC units but at the moment we only support using one of them in // a given build. If a boards config file defines MICROPY_HW_SDMMC2_CK then SDMMC2 // is used, otherwise SDMMC1 is used. #if defined(MICROPY_HW_SDMMC2_CK) #define SDIO SDMMC2 #define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC2_CLK_ENABLE() #define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC2_CLK_DISABLE() #define SDMMC_IRQn SDMMC2_IRQn #define SDMMC_DMA dma_SDMMC_2 #else #define SDIO SDMMC1 #define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC1_CLK_ENABLE() #define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC1_CLK_DISABLE() #define SDMMC_IRQn SDMMC1_IRQn #define SDMMC_DMA dma_SDIO_0 #define STATIC_AF_SDMMC_CK STATIC_AF_SDMMC1_CK #define STATIC_AF_SDMMC_CMD STATIC_AF_SDMMC1_CMD #define STATIC_AF_SDMMC_D0 STATIC_AF_SDMMC1_D0 #define STATIC_AF_SDMMC_D1 STATIC_AF_SDMMC1_D1 #define STATIC_AF_SDMMC_D2 STATIC_AF_SDMMC1_D2 #define STATIC_AF_SDMMC_D3 STATIC_AF_SDMMC1_D3 #endif // The F7 & L4 series calls the peripheral SDMMC rather than SDIO, so provide some // #defines for backwards compatability. #define SDIO_CLOCK_EDGE_RISING SDMMC_CLOCK_EDGE_RISING #define SDIO_CLOCK_EDGE_FALLING SDMMC_CLOCK_EDGE_FALLING #define SDIO_CLOCK_BYPASS_DISABLE SDMMC_CLOCK_BYPASS_DISABLE #define SDIO_CLOCK_BYPASS_ENABLE SDMMC_CLOCK_BYPASS_ENABLE #define SDIO_CLOCK_POWER_SAVE_DISABLE SDMMC_CLOCK_POWER_SAVE_DISABLE #define SDIO_CLOCK_POWER_SAVE_ENABLE SDMMC_CLOCK_POWER_SAVE_ENABLE #define SDIO_BUS_WIDE_1B SDMMC_BUS_WIDE_1B #define SDIO_BUS_WIDE_4B SDMMC_BUS_WIDE_4B #define SDIO_BUS_WIDE_8B SDMMC_BUS_WIDE_8B #define SDIO_HARDWARE_FLOW_CONTROL_DISABLE SDMMC_HARDWARE_FLOW_CONTROL_DISABLE #define SDIO_HARDWARE_FLOW_CONTROL_ENABLE SDMMC_HARDWARE_FLOW_CONTROL_ENABLE #if defined(STM32H7) #define GPIO_AF12_SDIO GPIO_AF12_SDIO1 #define SDIO_IRQHandler SDMMC1_IRQHandler #define SDIO_TRANSFER_CLK_DIV SDMMC_NSpeed_CLK_DIV #define SDIO_USE_GPDMA 0 #else #define SDIO_TRANSFER_CLK_DIV SDMMC_TRANSFER_CLK_DIV #define SDIO_USE_GPDMA 1 #endif #else // These are definitions for F4 MCUs so there is a common macro across all MCUs. #define SDMMC_CLK_ENABLE() __SDIO_CLK_ENABLE() #define SDMMC_CLK_DISABLE() __SDIO_CLK_DISABLE() #define SDMMC_IRQn SDIO_IRQn #define SDMMC_DMA dma_SDIO_0 #define SDIO_USE_GPDMA 1 #define STATIC_AF_SDMMC_CK STATIC_AF_SDIO_CK #define STATIC_AF_SDMMC_CMD STATIC_AF_SDIO_CMD #define STATIC_AF_SDMMC_D0 STATIC_AF_SDIO_D0 #define STATIC_AF_SDMMC_D1 STATIC_AF_SDIO_D1 #define STATIC_AF_SDMMC_D2 STATIC_AF_SDIO_D2 #define STATIC_AF_SDMMC_D3 STATIC_AF_SDIO_D3 #endif // If no custom SDIO pins defined, use the default ones #ifndef MICROPY_HW_SDMMC_CK #define MICROPY_HW_SDMMC_D0 (pin_C8) #define MICROPY_HW_SDMMC_D1 (pin_C9) #define MICROPY_HW_SDMMC_D2 (pin_C10) #define MICROPY_HW_SDMMC_D3 (pin_C11) #define MICROPY_HW_SDMMC_CK (pin_C12) #define MICROPY_HW_SDMMC_CMD (pin_D2) #endif #define PYB_SDMMC_FLAG_SD (0x01) #define PYB_SDMMC_FLAG_MMC (0x02) #define PYB_SDMMC_FLAG_ACTIVE (0x04) static uint8_t pyb_sdmmc_flags; // TODO: I think that as an optimization, we can allocate these dynamically // if an sd card is detected. This will save approx 260 bytes of RAM // when no sdcard was being used. static union { SD_HandleTypeDef sd; #if MICROPY_HW_ENABLE_MMCARD MMC_HandleTypeDef mmc; #endif } sdmmc_handle; void sdcard_init(void) { // Set SD/MMC to no mode and inactive pyb_sdmmc_flags = 0; // configure SD GPIO // we do this here an not in HAL_SD_MspInit because it apparently // makes it more robust to have the pins always pulled high // Note: the mp_hal_pin_config function will configure the GPIO in // fast mode which can do up to 50MHz. This should be plenty for SDIO // which clocks up to 25MHz maximum. #if defined(MICROPY_HW_SDMMC2_CK) // Use SDMMC2 peripheral with pins provided by the board's config mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_CK); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_CMD); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_D0); #if MICROPY_HW_SDMMC_BUS_WIDTH == 4 mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_D1); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_D2); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_D3); #endif #else // Default SDIO/SDMMC1 config mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_CK); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_CMD); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_D0); #if MICROPY_HW_SDMMC_BUS_WIDTH == 4 mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_D1); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_D2); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_D3); #endif #endif // configure the SD card detect pin // we do this here so we can detect if the SD card is inserted before powering it on #if defined(MICROPY_HW_SDCARD_DETECT_PIN) mp_hal_pin_config(MICROPY_HW_SDCARD_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_SDCARD_DETECT_PULL, 0); #endif } STATIC void sdmmc_msp_init(void) { // enable SDIO clock SDMMC_CLK_ENABLE(); #if defined(STM32H7) // Reset SDMMC #if defined(MICROPY_HW_SDMMC2_CK) __HAL_RCC_SDMMC2_FORCE_RESET(); __HAL_RCC_SDMMC2_RELEASE_RESET(); #else __HAL_RCC_SDMMC1_FORCE_RESET(); __HAL_RCC_SDMMC1_RELEASE_RESET(); #endif #endif // NVIC configuration for SDIO interrupts NVIC_SetPriority(SDMMC_IRQn, IRQ_PRI_SDIO); HAL_NVIC_EnableIRQ(SDMMC_IRQn); // GPIO have already been initialised by sdcard_init } void sdmmc_msp_deinit(void) { HAL_NVIC_DisableIRQ(SDMMC_IRQn); SDMMC_CLK_DISABLE(); } #if MICROPY_HW_ENABLE_SDCARD void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { sdmmc_msp_init(); } void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { sdmmc_msp_deinit(); } #endif #if MICROPY_HW_ENABLE_MMCARD void HAL_MMC_MspInit(MMC_HandleTypeDef *hsd) { sdmmc_msp_init(); } void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hsd) { sdmmc_msp_deinit(); } #endif bool sdcard_is_present(void) { #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { return false; } #endif #if defined(MICROPY_HW_SDCARD_DETECT_PIN) return HAL_GPIO_ReadPin(MICROPY_HW_SDCARD_DETECT_PIN->gpio, MICROPY_HW_SDCARD_DETECT_PIN->pin_mask) == MICROPY_HW_SDCARD_DETECT_PRESENT; #else return true; #endif } #if MICROPY_HW_ENABLE_SDCARD STATIC HAL_StatusTypeDef sdmmc_init_sd(void) { // SD device interface configuration sdmmc_handle.sd.Instance = SDIO; sdmmc_handle.sd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; #ifndef STM32H7 sdmmc_handle.sd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; #endif sdmmc_handle.sd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE; sdmmc_handle.sd.Init.BusWide = SDIO_BUS_WIDE_1B; sdmmc_handle.sd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; sdmmc_handle.sd.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV; // init the SD interface, with retry if it's not ready yet HAL_StatusTypeDef status; for (int retry = 10; (status = HAL_SD_Init(&sdmmc_handle.sd)) != HAL_OK; retry--) { if (retry == 0) { return status; } mp_hal_delay_ms(50); } #if MICROPY_HW_SDMMC_BUS_WIDTH == 4 // configure the SD bus width for 4-bit wide operation status = HAL_SD_ConfigWideBusOperation(&sdmmc_handle.sd, SDIO_BUS_WIDE_4B); if (status != HAL_OK) { HAL_SD_DeInit(&sdmmc_handle.sd); return status; } #endif return HAL_OK; } #endif #if MICROPY_HW_ENABLE_MMCARD STATIC HAL_StatusTypeDef sdmmc_init_mmc(void) { // MMC device interface configuration sdmmc_handle.mmc.Instance = SDIO; sdmmc_handle.mmc.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; #ifndef STM32H7 sdmmc_handle.mmc.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; #endif sdmmc_handle.mmc.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE; sdmmc_handle.mmc.Init.BusWide = SDIO_BUS_WIDE_1B; sdmmc_handle.mmc.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; sdmmc_handle.mmc.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV; // Init the SDIO interface HAL_StatusTypeDef status = HAL_MMC_Init(&sdmmc_handle.mmc); if (status != HAL_OK) { return status; } // As this is an eMMC card, overwrite LogBlockNbr with actual value sdmmc_handle.mmc.MmcCard.LogBlockNbr = 7469056 + 2048; #if MICROPY_HW_SDMMC_BUS_WIDTH == 4 // Configure the SDIO bus width for 4-bit wide operation #ifdef STM32F7 sdmmc_handle.mmc.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE; #endif status = HAL_MMC_ConfigWideBusOperation(&sdmmc_handle.mmc, SDIO_BUS_WIDE_4B); if (status != HAL_OK) { HAL_MMC_DeInit(&sdmmc_handle.mmc); return status; } #endif return HAL_OK; } #endif bool sdcard_power_on(void) { if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_ACTIVE) { return true; } #ifdef MICROPY_BOARD_SDCARD_POWER MICROPY_BOARD_SDCARD_POWER #endif HAL_StatusTypeDef status = HAL_ERROR; switch (pyb_sdmmc_flags) { #if MICROPY_HW_ENABLE_SDCARD case PYB_SDMMC_FLAG_SD: if (sdcard_is_present()) { status = sdmmc_init_sd(); } break; #endif #if MICROPY_HW_ENABLE_MMCARD case PYB_SDMMC_FLAG_MMC: status = sdmmc_init_mmc(); break; #endif } if (status == HAL_OK) { pyb_sdmmc_flags |= PYB_SDMMC_FLAG_ACTIVE; return true; } else { return false; } } void sdcard_power_off(void) { switch (pyb_sdmmc_flags) { #if MICROPY_HW_ENABLE_SDCARD case PYB_SDMMC_FLAG_ACTIVE | PYB_SDMMC_FLAG_SD: HAL_SD_DeInit(&sdmmc_handle.sd); break; #endif #if MICROPY_HW_ENABLE_MMCARD case PYB_SDMMC_FLAG_ACTIVE | PYB_SDMMC_FLAG_MMC: HAL_MMC_DeInit(&sdmmc_handle.mmc); break; #endif } pyb_sdmmc_flags &= ~PYB_SDMMC_FLAG_ACTIVE; } uint64_t sdcard_get_capacity_in_bytes(void) { switch (pyb_sdmmc_flags) { #if MICROPY_HW_ENABLE_SDCARD case PYB_SDMMC_FLAG_ACTIVE | PYB_SDMMC_FLAG_SD: { HAL_SD_CardInfoTypeDef cardinfo; HAL_SD_GetCardInfo(&sdmmc_handle.sd, &cardinfo); return (uint64_t)cardinfo.LogBlockNbr * (uint64_t)cardinfo.LogBlockSize; } #endif #if MICROPY_HW_ENABLE_MMCARD case PYB_SDMMC_FLAG_ACTIVE | PYB_SDMMC_FLAG_MMC: { HAL_MMC_CardInfoTypeDef cardinfo; HAL_MMC_GetCardInfo(&sdmmc_handle.mmc, &cardinfo); return (uint64_t)cardinfo.LogBlockNbr * (uint64_t)cardinfo.LogBlockSize; } #endif default: return 0; } } STATIC void sdmmc_irq_handler(void) { switch (pyb_sdmmc_flags) { #if MICROPY_HW_ENABLE_SDCARD case PYB_SDMMC_FLAG_ACTIVE | PYB_SDMMC_FLAG_SD: HAL_SD_IRQHandler(&sdmmc_handle.sd); break; #endif #if MICROPY_HW_ENABLE_MMCARD case PYB_SDMMC_FLAG_ACTIVE | PYB_SDMMC_FLAG_MMC: HAL_MMC_IRQHandler(&sdmmc_handle.mmc); break; #endif } } #if !defined(MICROPY_HW_SDMMC2_CK) void SDIO_IRQHandler(void) { IRQ_ENTER(SDIO_IRQn); sdmmc_irq_handler(); IRQ_EXIT(SDIO_IRQn); } #endif #if defined(STM32F7) void SDMMC2_IRQHandler(void) { IRQ_ENTER(SDMMC2_IRQn); sdmmc_irq_handler(); IRQ_EXIT(SDMMC2_IRQn); } #endif STATIC void sdcard_reset_periph(void) { // Fully reset the SDMMC peripheral before calling HAL SD DMA functions. // (There could be an outstanding DTIMEOUT event from a previous call and the // HAL function enables IRQs before fully configuring the SDMMC peripheral.) SDIO->DTIMER = 0; SDIO->DLEN = 0; SDIO->DCTRL = 0; SDIO->ICR = SDMMC_STATIC_FLAGS; } STATIC HAL_StatusTypeDef sdcard_wait_finished(uint32_t timeout) { // Wait for HAL driver to be ready (eg for DMA to finish) uint32_t start = HAL_GetTick(); for (;;) { // Do an atomic check of the state; WFI will exit even if IRQs are disabled uint32_t irq_state = disable_irq(); #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { if (sdmmc_handle.mmc.State != HAL_MMC_STATE_BUSY) { enable_irq(irq_state); break; } } else #endif { if (sdmmc_handle.sd.State != HAL_SD_STATE_BUSY) { enable_irq(irq_state); break; } } __WFI(); enable_irq(irq_state); if (HAL_GetTick() - start >= timeout) { return HAL_TIMEOUT; } } // Wait for SD card to complete the operation for (;;) { uint32_t state; #if MICROPY_HW_ENABLE_MMCARD MP_STATIC_ASSERT((uint32_t)HAL_SD_CARD_TRANSFER == (uint32_t)HAL_MMC_CARD_TRANSFER); MP_STATIC_ASSERT((uint32_t)HAL_SD_CARD_SENDING == (uint32_t)HAL_MMC_CARD_SENDING); MP_STATIC_ASSERT((uint32_t)HAL_SD_CARD_RECEIVING == (uint32_t)HAL_MMC_CARD_RECEIVING); MP_STATIC_ASSERT((uint32_t)HAL_SD_CARD_PROGRAMMING == (uint32_t)HAL_MMC_CARD_PROGRAMMING); if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { state = HAL_MMC_GetCardState(&sdmmc_handle.mmc); } else #endif { state = HAL_SD_GetCardState(&sdmmc_handle.sd); } if (state == HAL_SD_CARD_TRANSFER) { return HAL_OK; } if (!(state == HAL_SD_CARD_SENDING || state == HAL_SD_CARD_RECEIVING || state == HAL_SD_CARD_PROGRAMMING)) { return HAL_ERROR; } if (HAL_GetTick() - start >= timeout) { return HAL_TIMEOUT; } __WFI(); } return HAL_OK; } mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (!(pyb_sdmmc_flags & PYB_SDMMC_FLAG_ACTIVE)) { return HAL_ERROR; } HAL_StatusTypeDef err = HAL_OK; // check that dest pointer is aligned on a 4-byte boundary uint8_t *orig_dest = NULL; uint32_t saved_word; if (((uint32_t)dest & 3) != 0) { // Pointer is not aligned so it needs fixing. // We could allocate a temporary block of RAM (as sdcard_write_blocks // does) but instead we are going to use the dest buffer inplace. We // are going to align the pointer, save the initial word at the aligned // location, read into the aligned memory, move the memory back to the // unaligned location, then restore the initial bytes at the aligned // location. We should have no trouble doing this as those initial // bytes at the aligned location should be able to be changed for the // duration of this function call. orig_dest = dest; dest = (uint8_t*)((uint32_t)dest & ~3); saved_word = *(uint32_t*)dest; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); #if SDIO_USE_GPDMA DMA_HandleTypeDef sd_dma; dma_init(&sd_dma, &SDMMC_DMA, DMA_PERIPH_TO_MEMORY, &sdmmc_handle); #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { sdmmc_handle.mmc.hdmarx = &sd_dma; } else #endif { sdmmc_handle.sd.hdmarx = &sd_dma; } #endif // make sure cache is flushed and invalidated so when DMA updates the RAM // from reading the peripheral the CPU then reads the new data MP_HAL_CLEANINVALIDATE_DCACHE(dest, num_blocks * SDCARD_BLOCK_SIZE); sdcard_reset_periph(); #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { err = HAL_MMC_ReadBlocks_DMA(&sdmmc_handle.mmc, dest, block_num, num_blocks); } else #endif { err = HAL_SD_ReadBlocks_DMA(&sdmmc_handle.sd, dest, block_num, num_blocks); } if (err == HAL_OK) { err = sdcard_wait_finished(60000); } #if SDIO_USE_GPDMA dma_deinit(&SDMMC_DMA); #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { sdmmc_handle.mmc.hdmarx = NULL; } else #endif { sdmmc_handle.sd.hdmarx = NULL; } #endif restore_irq_pri(basepri); } else { #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { err = HAL_MMC_ReadBlocks(&sdmmc_handle.mmc, dest, block_num, num_blocks, 60000); } else #endif { err = HAL_SD_ReadBlocks(&sdmmc_handle.sd, dest, block_num, num_blocks, 60000); } if (err == HAL_OK) { err = sdcard_wait_finished(60000); } } if (orig_dest != NULL) { // move the read data to the non-aligned position, and restore the initial bytes memmove(orig_dest, dest, num_blocks * SDCARD_BLOCK_SIZE); memcpy(dest, &saved_word, orig_dest - dest); } return err; } mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (!(pyb_sdmmc_flags & PYB_SDMMC_FLAG_ACTIVE)) { return HAL_ERROR; } HAL_StatusTypeDef err = HAL_OK; // check that src pointer is aligned on a 4-byte boundary if (((uint32_t)src & 3) != 0) { // pointer is not aligned, so allocate a temporary block to do the write uint8_t *src_aligned = m_new_maybe(uint8_t, SDCARD_BLOCK_SIZE); if (src_aligned == NULL) { return HAL_ERROR; } for (size_t i = 0; i < num_blocks; ++i) { memcpy(src_aligned, src + i * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE); err = sdcard_write_blocks(src_aligned, block_num + i, 1); if (err != HAL_OK) { break; } } m_del(uint8_t, src_aligned, SDCARD_BLOCK_SIZE); return err; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); #if SDIO_USE_GPDMA DMA_HandleTypeDef sd_dma; dma_init(&sd_dma, &SDMMC_DMA, DMA_MEMORY_TO_PERIPH, &sdmmc_handle); #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { sdmmc_handle.mmc.hdmatx = &sd_dma; } else #endif { sdmmc_handle.sd.hdmatx = &sd_dma; } #endif // make sure cache is flushed to RAM so the DMA can read the correct data MP_HAL_CLEAN_DCACHE(src, num_blocks * SDCARD_BLOCK_SIZE); sdcard_reset_periph(); #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { err = HAL_MMC_WriteBlocks_DMA(&sdmmc_handle.mmc, (uint8_t*)src, block_num, num_blocks); } else #endif { err = HAL_SD_WriteBlocks_DMA(&sdmmc_handle.sd, (uint8_t*)src, block_num, num_blocks); } if (err == HAL_OK) { err = sdcard_wait_finished(60000); } #if SDIO_USE_GPDMA dma_deinit(&SDMMC_DMA); #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { sdmmc_handle.mmc.hdmatx = NULL; } else #endif { sdmmc_handle.sd.hdmatx = NULL; } #endif restore_irq_pri(basepri); } else { #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { err = HAL_MMC_WriteBlocks(&sdmmc_handle.mmc, (uint8_t*)src, block_num, num_blocks, 60000); } else #endif { err = HAL_SD_WriteBlocks(&sdmmc_handle.sd, (uint8_t*)src, block_num, num_blocks, 60000); } if (err == HAL_OK) { err = sdcard_wait_finished(60000); } } return err; } /******************************************************************************/ // MicroPython bindings // // Expose the SD card or MMC as an object with the block protocol. // There are singleton SDCard/MMCard objects #if MICROPY_HW_ENABLE_SDCARD const mp_obj_base_t pyb_sdcard_obj = {&pyb_sdcard_type}; #endif #if MICROPY_HW_ENABLE_MMCARD const mp_obj_base_t pyb_mmcard_obj = {&pyb_mmcard_type}; #endif #if MICROPY_HW_ENABLE_SDCARD STATIC mp_obj_t pyb_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { mp_raise_ValueError("peripheral used by MMCard"); } #endif pyb_sdmmc_flags |= PYB_SDMMC_FLAG_SD; // return singleton object return MP_OBJ_FROM_PTR(&pyb_sdcard_obj); } #endif #if MICROPY_HW_ENABLE_MMCARD STATIC mp_obj_t pyb_mmcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); #if MICROPY_HW_ENABLE_SDCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_SD) { mp_raise_ValueError("peripheral used by SDCard"); } #endif pyb_sdmmc_flags |= PYB_SDMMC_FLAG_MMC; // return singleton object return MP_OBJ_FROM_PTR(&pyb_mmcard_obj); } #endif STATIC mp_obj_t sd_present(mp_obj_t self) { return mp_obj_new_bool(sdcard_is_present()); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(sd_present_obj, sd_present); STATIC mp_obj_t sd_power(mp_obj_t self, mp_obj_t state) { bool result; if (mp_obj_is_true(state)) { result = sdcard_power_on(); } else { sdcard_power_off(); result = true; } return mp_obj_new_bool(result); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(sd_power_obj, sd_power); STATIC mp_obj_t sd_info(mp_obj_t self) { if (!(pyb_sdmmc_flags & PYB_SDMMC_FLAG_ACTIVE)) { return mp_const_none; } uint32_t card_type; uint32_t log_block_nbr; uint32_t log_block_size; #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { card_type = sdmmc_handle.mmc.MmcCard.CardType; log_block_nbr = sdmmc_handle.mmc.MmcCard.LogBlockNbr; log_block_size = sdmmc_handle.mmc.MmcCard.LogBlockSize; } else #endif { card_type = sdmmc_handle.sd.SdCard.CardType; log_block_nbr = sdmmc_handle.sd.SdCard.LogBlockNbr; log_block_size = sdmmc_handle.sd.SdCard.LogBlockSize; } // cardinfo.SD_csd and cardinfo.SD_cid have lots of info but we don't use them mp_obj_t tuple[3] = { mp_obj_new_int_from_ull((uint64_t)log_block_nbr * (uint64_t)log_block_size), mp_obj_new_int_from_uint(log_block_size), mp_obj_new_int(card_type), }; return mp_obj_new_tuple(3, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(sd_info_obj, sd_info); // now obsolete, kept for backwards compatibility STATIC mp_obj_t sd_read(mp_obj_t self, mp_obj_t block_num) { uint8_t *dest = m_new(uint8_t, SDCARD_BLOCK_SIZE); mp_uint_t ret = sdcard_read_blocks(dest, mp_obj_get_int(block_num), 1); if (ret != 0) { m_del(uint8_t, dest, SDCARD_BLOCK_SIZE); nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "sdcard_read_blocks failed [%u]", ret)); } return mp_obj_new_bytearray_by_ref(SDCARD_BLOCK_SIZE, dest); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(sd_read_obj, sd_read); // now obsolete, kept for backwards compatibility STATIC mp_obj_t sd_write(mp_obj_t self, mp_obj_t block_num, mp_obj_t data) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); if (bufinfo.len % SDCARD_BLOCK_SIZE != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "writes must be a multiple of %d bytes", SDCARD_BLOCK_SIZE)); } mp_uint_t ret = sdcard_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_BLOCK_SIZE); if (ret != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "sdcard_write_blocks failed [%u]", ret)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(sd_write_obj, sd_write); STATIC mp_obj_t pyb_sdcard_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); mp_uint_t ret = sdcard_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_BLOCK_SIZE); return mp_obj_new_bool(ret == 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sdcard_readblocks_obj, pyb_sdcard_readblocks); STATIC mp_obj_t pyb_sdcard_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); mp_uint_t ret = sdcard_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_BLOCK_SIZE); return mp_obj_new_bool(ret == 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sdcard_writeblocks_obj, pyb_sdcard_writeblocks); STATIC mp_obj_t pyb_sdcard_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: if (!sdcard_power_on()) { return MP_OBJ_NEW_SMALL_INT(-1); // error } return MP_OBJ_NEW_SMALL_INT(0); // success case MP_BLOCKDEV_IOCTL_DEINIT: sdcard_power_off(); return MP_OBJ_NEW_SMALL_INT(0); // success case MP_BLOCKDEV_IOCTL_SYNC: // nothing to do return MP_OBJ_NEW_SMALL_INT(0); // success case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(sdcard_get_capacity_in_bytes() / SDCARD_BLOCK_SIZE); case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(SDCARD_BLOCK_SIZE); default: // unknown command return MP_OBJ_NEW_SMALL_INT(-1); // error } } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sdcard_ioctl_obj, pyb_sdcard_ioctl); STATIC const mp_rom_map_elem_t pyb_sdcard_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_present), MP_ROM_PTR(&sd_present_obj) }, { MP_ROM_QSTR(MP_QSTR_power), MP_ROM_PTR(&sd_power_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&sd_info_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&sd_read_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&sd_write_obj) }, // block device protocol { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&pyb_sdcard_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&pyb_sdcard_writeblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&pyb_sdcard_ioctl_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_sdcard_locals_dict, pyb_sdcard_locals_dict_table); #if MICROPY_HW_ENABLE_SDCARD const mp_obj_type_t pyb_sdcard_type = { { &mp_type_type }, .name = MP_QSTR_SDCard, .make_new = pyb_sdcard_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_sdcard_locals_dict, }; #endif #if MICROPY_HW_ENABLE_MMCARD const mp_obj_type_t pyb_mmcard_type = { { &mp_type_type }, .name = MP_QSTR_MMCard, .make_new = pyb_mmcard_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_sdcard_locals_dict, }; #endif void sdcard_init_vfs(fs_user_mount_t *vfs, int part) { pyb_sdmmc_flags = (pyb_sdmmc_flags & PYB_SDMMC_FLAG_ACTIVE) | PYB_SDMMC_FLAG_SD; // force SD mode vfs->base.type = &mp_fat_vfs_type; vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; vfs->fatfs.part = part; vfs->blockdev.readblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_readblocks_obj); vfs->blockdev.readblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); vfs->blockdev.readblocks[2] = MP_OBJ_FROM_PTR(sdcard_read_blocks); // native version vfs->blockdev.writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_writeblocks_obj); vfs->blockdev.writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); vfs->blockdev.writeblocks[2] = MP_OBJ_FROM_PTR(sdcard_write_blocks); // native version vfs->blockdev.u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_ioctl_obj); vfs->blockdev.u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); } #endif // MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD micropython-1.12/ports/stm32/sdcard.h000066400000000000000000000040211357706137100175470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_SDCARD_H #define MICROPY_INCLUDED_STM32_SDCARD_H // this is a fixed size and should not be changed #define SDCARD_BLOCK_SIZE (512) void sdcard_init(void); bool sdcard_is_present(void); bool sdcard_power_on(void); void sdcard_power_off(void); uint64_t sdcard_get_capacity_in_bytes(void); // these return 0 on success, non-zero on error mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); extern const struct _mp_obj_type_t pyb_sdcard_type; extern const struct _mp_obj_type_t pyb_mmcard_type; extern const struct _mp_obj_base_t pyb_sdcard_obj; struct _fs_user_mount_t; void sdcard_init_vfs(struct _fs_user_mount_t *vfs, int part); #endif // MICROPY_INCLUDED_STM32_SDCARD_H micropython-1.12/ports/stm32/sdio.c000066400000000000000000000312171357706137100172470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mperrno.h" #include "py/mphal.h" #include "genhdr/pins.h" #include "pendsv.h" #include "sdio.h" #if MICROPY_PY_NETWORK_CYW43 #define DEFAULT_MASK (0) enum { SDMMC_IRQ_STATE_DONE, SDMMC_IRQ_STATE_CMD_DONE, SDMMC_IRQ_STATE_CMD_DATA_PENDING, }; static volatile int sdmmc_irq_state; static volatile uint32_t sdmmc_block_size_log2; static volatile bool sdmmc_write; static volatile bool sdmmc_dma; static volatile uint32_t sdmmc_error; static volatile uint8_t *sdmmc_buf_cur; static volatile uint8_t *sdmmc_buf_top; void sdio_init(uint32_t irq_pri) { // configure IO pins mp_hal_pin_config(pin_C8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); mp_hal_pin_config(pin_C9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); mp_hal_pin_config(pin_C10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); mp_hal_pin_config(pin_C11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); mp_hal_pin_config(pin_C12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 12); // CLK doesn't need pull-up mp_hal_pin_config(pin_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); __HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral SDMMC_TypeDef *SDIO = SDMMC1; SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_PWRSAV | 118; // 1-bit, 400kHz mp_hal_delay_us(10); SDIO->POWER = 3; // the card is clocked mp_hal_delay_us(10); SDIO->DCTRL = 1 << 10; // RWMOD is SDIO_CK SDIO->CLKCR |= SDMMC_CLKCR_CLKEN; mp_hal_delay_us(10); __HAL_RCC_DMA2_CLK_ENABLE(); // enable DMA2 peripheral NVIC_SetPriority(SDMMC1_IRQn, irq_pri); SDIO->MASK = 0; HAL_NVIC_EnableIRQ(SDMMC1_IRQn); } void sdio_deinit(void) { RCC->APB2ENR &= ~RCC_APB2ENR_SDMMC1EN; // disable SDIO peripheral RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA2EN; // disable DMA2 peripheral } void sdio_enable_high_speed_4bit(void) { SDMMC_TypeDef *SDIO = SDMMC1; SDIO->POWER = 0; // power off mp_hal_delay_us(10); SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_WIDBUS_0 | SDMMC_CLKCR_BYPASS /*| SDMMC_CLKCR_PWRSAV*/; // 4-bit, 48MHz mp_hal_delay_us(10); SDIO->POWER = 3; // the card is clocked mp_hal_delay_us(10); SDIO->DCTRL = 1 << 11 | 1 << 10; // SDIOEN, RWMOD is SDIO_CK SDIO->CLKCR |= SDMMC_CLKCR_CLKEN; SDIO->MASK = DEFAULT_MASK; mp_hal_delay_us(10); } void SDMMC1_IRQHandler(void) { if (SDMMC1->STA & SDMMC_STA_CMDREND) { SDMMC1->ICR = SDMMC_ICR_CMDRENDC; uint32_t r1 = SDMMC1->RESP1; if (SDMMC1->RESPCMD == 53 && r1 & 0x800) { printf("bad RESP1: %lu %lx\n", SDMMC1->RESPCMD, r1); sdmmc_error = 0xffffffff; SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; return; } if (sdmmc_buf_cur >= sdmmc_buf_top) { // data transfer finished, so we are done SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; return; } if (sdmmc_write) { SDMMC1->DCTRL = (sdmmc_block_size_log2 << 4) | 1 | (1 << 11) | (!sdmmc_write << 1) | (sdmmc_dma << 3) | (0 << 10); if (!sdmmc_dma) { SDMMC1->MASK |= SDMMC_MASK_TXFIFOHEIE; } } sdmmc_irq_state = SDMMC_IRQ_STATE_CMD_DONE; } else if (SDMMC1->STA & SDMMC_STA_DATAEND) { // data transfer complete // note: it's possible to get DATAEND before CMDREND SDMMC1->ICR = SDMMC_ICR_DATAENDC; // check if there is some remaining data in RXFIFO if (!sdmmc_dma) { while (SDMMC1->STA & SDMMC_STA_RXDAVL) { *(uint32_t*)sdmmc_buf_cur = SDMMC1->FIFO; sdmmc_buf_cur += 4; } } if (sdmmc_irq_state == SDMMC_IRQ_STATE_CMD_DONE) { // command and data finished, so we are done SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; } } else if (SDMMC1->STA & SDMMC_STA_TXFIFOHE) { if (!sdmmc_dma && sdmmc_write) { // write up to 8 words to fifo for (size_t i = 8; i && sdmmc_buf_cur < sdmmc_buf_top; --i) { SDMMC1->FIFO = *(uint32_t*)sdmmc_buf_cur; sdmmc_buf_cur += 4; } if (sdmmc_buf_cur >= sdmmc_buf_top) { // finished, disable IRQ SDMMC1->MASK &= ~SDMMC_MASK_TXFIFOHEIE; } } } else if (SDMMC1->STA & SDMMC_STA_RXFIFOHF) { if (!sdmmc_dma && !sdmmc_write) { // read up to 8 words from fifo for (size_t i = 8; i && sdmmc_buf_cur < sdmmc_buf_top; --i) { *(uint32_t*)sdmmc_buf_cur = SDMMC1->FIFO; sdmmc_buf_cur += 4; } } } else if (SDMMC1->STA & SDMMC_STA_SDIOIT) { SDMMC1->MASK &= ~SDMMC_MASK_SDIOITIE; SDMMC1->ICR = SDMMC_ICR_SDIOITC; #if MICROPY_PY_NETWORK_CYW43 extern void (*cyw43_poll)(void); if (cyw43_poll) { pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); } #endif } else if (SDMMC1->STA & 0x3f) { // an error sdmmc_error = SDMMC1->STA; SDMMC1->ICR = SDMMC_STATIC_FLAGS; SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; } } int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) { // Wait for any outstanding TX to complete while (SDMMC1->STA & SDMMC_STA_TXACT) { } DMA2_Stream3->CR = 0; // ensure DMA is reset SDMMC1->ICR = SDMMC_STATIC_FLAGS; // clear interrupts SDMMC1->ARG = arg; SDMMC1->CMD = cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; sdmmc_irq_state = SDMMC_IRQ_STATE_CMD_DATA_PENDING; sdmmc_error = 0; sdmmc_buf_cur = NULL; sdmmc_buf_top = NULL; SDMMC1->MASK = (SDMMC1->MASK & SDMMC_MASK_SDIOITIE) | SDMMC_MASK_CMDRENDIE | 0x3f; uint32_t start = mp_hal_ticks_ms(); for (;;) { __WFI(); if (sdmmc_irq_state == SDMMC_IRQ_STATE_DONE) { break; } if (mp_hal_ticks_ms() - start > 1000) { SDMMC1->MASK = DEFAULT_MASK; printf("sdio_transfer timeout STA=0x%08x\n", (uint)SDMMC1->STA); return -MP_ETIMEDOUT; } } SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; if (sdmmc_error == SDMMC_STA_CCRCFAIL && cmd == 5) { // Errata: CMD CRC error is incorrectly generated for CMD 5 return 0; } else if (sdmmc_error) { return -(0x1000000 | sdmmc_error); } uint32_t rcmd = SDMMC1->RESPCMD; if (rcmd != cmd) { printf("sdio_transfer: cmd=%lu rcmd=%lu\n", cmd, rcmd); return -MP_EIO; } if (resp != NULL) { *resp = SDMMC1->RESP1; } return 0; } int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf) { // Wait for any outstanding TX to complete while (SDMMC1->STA & SDMMC_STA_TXACT) { } // for SDIO_BYTE_MODE the SDIO chuck of data must be a single block of the length of buf int block_size_log2 = 0; if (block_size == 4) { block_size_log2 = 2; } else if (block_size == 8) { block_size_log2 = 3; } else if (block_size == 16) { block_size_log2 = 4; } else if (block_size == 32) { block_size_log2 = 5; } else if (block_size == 64) { block_size_log2 = 6; } else if (block_size == 128) { block_size_log2 = 7; } else if (block_size == 256) { block_size_log2 = 8; } else { printf("sdio_transfer_cmd53: invalid block_size %lu", block_size); return -MP_EINVAL; } bool dma = (len > 16); SDMMC1->ICR = SDMMC_STATIC_FLAGS; // clear interrupts SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; SDMMC1->DTIMER = 0x2000000; // about 700ms running at 48MHz SDMMC1->DLEN = (len + block_size - 1) & ~(block_size - 1); DMA2_Stream3->CR = 0; if (dma) { // prepare DMA so it's ready when the DPSM starts its transfer // enable DMA2 peripheral in case it was turned off by someone else RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; if (write) { // make sure cache is flushed to RAM so the DMA can read the correct data MP_HAL_CLEAN_DCACHE(buf, len); } else { // make sure cache is flushed and invalidated so when DMA updates the RAM // from reading the peripheral the CPU then reads the new data MP_HAL_CLEANINVALIDATE_DCACHE(buf, len); } DMA2->LIFCR = 0x3f << 22; DMA2_Stream3->FCR = 0x07; // ? DMA2_Stream3->PAR = (uint32_t)&SDMMC1->FIFO; if ((uint32_t)buf & 3) { printf("sdio_transfer_cmd53: buf=%p is not aligned for DMA\n", buf); return -MP_EINVAL; } DMA2_Stream3->M0AR = (uint32_t)buf; DMA2_Stream3->NDTR = ((len + block_size - 1) & ~(block_size - 1)) / 4; DMA2_Stream3->CR = 4 << 25 // channel 4 | 1 << 23 // MBURST INCR4 | 1 << 21 // PBURST INCR4 | 3 << 16 // PL very high | 2 << 13 // MSIZE word | 2 << 11 // PSIZE word | 1 << 10 // MINC enabled | 0 << 9 // PINC disabled | write << 6 // DIR mem-to-periph | 1 << 5 // PFCTRL periph is flow controller | 1 << 0 // EN ; } // for reading, need to initialise the DPSM before starting the CPSM // so that the DPSM is ready to receive when the device sends data // (and in case we get a long-running unrelated IRQ here on the host just // after writing to CMD to initiate the command) if (!write) { SDMMC1->DCTRL = (block_size_log2 << 4) | 1 | (1 << 11) | (!write << 1) | (dma << 3); } SDMMC1->ARG = arg; SDMMC1->CMD = 53 | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; sdmmc_irq_state = SDMMC_IRQ_STATE_CMD_DATA_PENDING; sdmmc_block_size_log2 = block_size_log2; sdmmc_write = write; sdmmc_dma = dma; sdmmc_error = 0; sdmmc_buf_cur = (uint8_t*)buf; sdmmc_buf_top = (uint8_t*)buf + len; SDMMC1->MASK = (SDMMC1->MASK & SDMMC_MASK_SDIOITIE) | SDMMC_MASK_CMDRENDIE | SDMMC_MASK_DATAENDIE | SDMMC_MASK_RXFIFOHFIE | 0x3f; // wait to complete transfer uint32_t start = mp_hal_ticks_ms(); for (;;) { __WFI(); if (sdmmc_irq_state == SDMMC_IRQ_STATE_DONE) { break; } if (mp_hal_ticks_ms() - start > 200) { SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; printf("sdio_transfer_cmd53: timeout wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x DMA=%08x:%08x:%08x RCC=%08x\n", write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->FIFOCNT, (uint)DMA2->LISR, (uint)DMA2->HISR, (uint)DMA2_Stream3->NDTR, (uint)RCC->AHB1ENR); return -MP_ETIMEDOUT; } } SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; if (sdmmc_error) { printf("sdio_transfer_cmd53: error=%08lx wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x DMA=%08x:%08x:%08x RCC=%08x\n", sdmmc_error, write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->FIFOCNT, (uint)DMA2->LISR, (uint)DMA2->HISR, (uint)DMA2_Stream3->NDTR, (uint)RCC->AHB1ENR); return -(0x1000000 | sdmmc_error); } if (!sdmmc_dma) { if (sdmmc_buf_cur != sdmmc_buf_top) { printf("sdio_transfer_cmd53: didn't transfer correct length: cur=%p top=%p\n", sdmmc_buf_cur, sdmmc_buf_top); return -MP_EIO; } } return 0; } #endif micropython-1.12/ports/stm32/sdio.h000066400000000000000000000031611357706137100172510ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_SDIO_H #define MICROPY_INCLUDED_STM32_SDIO_H #include #include void sdio_init(uint32_t irq_pri); void sdio_deinit(void); void sdio_enable_high_speed_4bit(void); int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp); int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf); #endif // MICROPY_INCLUDED_STM32_SDIO_H micropython-1.12/ports/stm32/sdram.c000066400000000000000000000435261357706137100174250ustar00rootroot00000000000000/* * This file is part of the OpenMV project. * Copyright (c) 2013/2014 Ibrahim Abdelkader * This work is licensed under the MIT license, see the file LICENSE for details. * * SDRAM Driver. * */ #include #include #include #include "py/runtime.h" #include "py/mphal.h" #include "pin.h" #include "pin_static_af.h" #include "mpu.h" #include "systick.h" #include "sdram.h" #define SDRAM_TIMEOUT ((uint32_t)0xFFFF) #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) #if defined(MICROPY_HW_FMC_SDCKE0) && defined(MICROPY_HW_FMC_SDNE0) #define FMC_SDRAM_BANK FMC_SDRAM_BANK1 #define FMC_SDRAM_CMD_TARGET_BANK FMC_SDRAM_CMD_TARGET_BANK1 #define SDRAM_START_ADDRESS 0xC0000000 #elif defined(MICROPY_HW_FMC_SDCKE1) && defined(MICROPY_HW_FMC_SDNE1) #define FMC_SDRAM_BANK FMC_SDRAM_BANK2 #define FMC_SDRAM_CMD_TARGET_BANK FMC_SDRAM_CMD_TARGET_BANK2 #define SDRAM_START_ADDRESS 0xD0000000 #endif // Provides the MPU_REGION_SIZE_X value when passed the size of region in bytes // "m" must be a power of 2 between 32 and 4G (2**5 and 2**32) and this formula // computes the log2 of "m", minus 1 #define MPU_REGION_SIZE(m) (((m) - 1) / (((m) - 1) % 255 + 1) / 255 % 255 * 8 + 7 - 86 / (((m) - 1) % 255 + 12) - 1) #define SDRAM_MPU_REGION_SIZE (MPU_REGION_SIZE(MICROPY_HW_SDRAM_SIZE)) #ifdef FMC_SDRAM_BANK static void sdram_init_seq(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *command); extern void __fatal_error(const char *msg); bool sdram_init(void) { SDRAM_HandleTypeDef hsdram; FMC_SDRAM_TimingTypeDef SDRAM_Timing; FMC_SDRAM_CommandTypeDef command; __HAL_RCC_FMC_CLK_ENABLE(); #if defined(MICROPY_HW_FMC_SDCKE0) mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDCKE0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDCKE0); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDNE0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDNE0); #elif defined(MICROPY_HW_FMC_SDCKE1) mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDCKE1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDCKE1); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDNE1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDNE1); #endif mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDCLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDCLK); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDNCAS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDNCAS); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDNRAS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDNRAS); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDNWE, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDNWE); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_BA0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_BA0); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_BA1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_BA1); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_NBL0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_NBL0); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_NBL1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_NBL1); #ifdef MICROPY_HW_FMC_NBL2 mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_NBL2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_NBL2); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_NBL3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_NBL3); #endif mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A0); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A1); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A2); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A3); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A4, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A4); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A5); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A6); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A7); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A8); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A9); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A10); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A11); #ifdef MICROPY_HW_FMC_A12 mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A12); #endif mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D0); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D1); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D2); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D3); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D4, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D4); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D5); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D6); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D7); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D8); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D9); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D10); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D11); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D12); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D13, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D13); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D14, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D14); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D15, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D15); #ifdef MICROPY_HW_FMC_D16 mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D16, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D16); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D17, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D17); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D18, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D18); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D19, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D19); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D20, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D20); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D21, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D21); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D22, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D22); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D23, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D23); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D24, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D24); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D25, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D25); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D26, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D26); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D27, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D27); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D28, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D28); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D29, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D29); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D30, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D30); mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_D31, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_D31); #endif /* SDRAM device configuration */ hsdram.Instance = FMC_SDRAM_DEVICE; /* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */ /* TMRD: 2 Clock cycles */ SDRAM_Timing.LoadToActiveDelay = MICROPY_HW_SDRAM_TIMING_TMRD; /* TXSR: min=70ns (6x11.90ns) */ SDRAM_Timing.ExitSelfRefreshDelay = MICROPY_HW_SDRAM_TIMING_TXSR; /* TRAS */ SDRAM_Timing.SelfRefreshTime = MICROPY_HW_SDRAM_TIMING_TRAS; /* TRC */ SDRAM_Timing.RowCycleDelay = MICROPY_HW_SDRAM_TIMING_TRC; /* TWR */ SDRAM_Timing.WriteRecoveryTime = MICROPY_HW_SDRAM_TIMING_TWR; /* TRP */ SDRAM_Timing.RPDelay = MICROPY_HW_SDRAM_TIMING_TRP; /* TRCD */ SDRAM_Timing.RCDDelay = MICROPY_HW_SDRAM_TIMING_TRCD; #define _FMC_INIT(x, n) x ## _ ## n #define FMC_INIT(x, n) _FMC_INIT(x, n) hsdram.Init.SDBank = FMC_SDRAM_BANK; hsdram.Init.ColumnBitsNumber = FMC_INIT(FMC_SDRAM_COLUMN_BITS_NUM, MICROPY_HW_SDRAM_COLUMN_BITS_NUM); hsdram.Init.RowBitsNumber = FMC_INIT(FMC_SDRAM_ROW_BITS_NUM, MICROPY_HW_SDRAM_ROW_BITS_NUM); hsdram.Init.MemoryDataWidth = FMC_INIT(FMC_SDRAM_MEM_BUS_WIDTH, MICROPY_HW_SDRAM_MEM_BUS_WIDTH); hsdram.Init.InternalBankNumber = FMC_INIT(FMC_SDRAM_INTERN_BANKS_NUM, MICROPY_HW_SDRAM_INTERN_BANKS_NUM); hsdram.Init.CASLatency = FMC_INIT(FMC_SDRAM_CAS_LATENCY, MICROPY_HW_SDRAM_CAS_LATENCY); hsdram.Init.SDClockPeriod = FMC_INIT(FMC_SDRAM_CLOCK_PERIOD, MICROPY_HW_SDRAM_CLOCK_PERIOD); hsdram.Init.ReadPipeDelay = FMC_INIT(FMC_SDRAM_RPIPE_DELAY, MICROPY_HW_SDRAM_RPIPE_DELAY); hsdram.Init.ReadBurst = (MICROPY_HW_SDRAM_RBURST) ? FMC_SDRAM_RBURST_ENABLE : FMC_SDRAM_RBURST_DISABLE; hsdram.Init.WriteProtection = (MICROPY_HW_SDRAM_WRITE_PROTECTION) ? FMC_SDRAM_WRITE_PROTECTION_ENABLE : FMC_SDRAM_WRITE_PROTECTION_DISABLE; /* Initialize the SDRAM controller */ if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK) { return false; } sdram_init_seq(&hsdram, &command); return true; } void *sdram_start(void) { return (void*)SDRAM_START_ADDRESS; } void *sdram_end(void) { return (void*)(SDRAM_START_ADDRESS + MICROPY_HW_SDRAM_SIZE); } static void sdram_init_seq(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *command) { /* Program the SDRAM external device */ __IO uint32_t tmpmrd =0; /* Step 3: Configure a clock configuration enable command */ command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK; command->AutoRefreshNumber = 1; command->ModeRegisterDefinition = 0; /* Send the command */ HAL_SDRAM_SendCommand(hsdram, command, 0x1000); /* Step 4: Insert 100 ms delay */ HAL_Delay(100); /* Step 5: Configure a PALL (precharge all) command */ command->CommandMode = FMC_SDRAM_CMD_PALL; command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK; command->AutoRefreshNumber = 1; command->ModeRegisterDefinition = 0; /* Send the command */ HAL_SDRAM_SendCommand(hsdram, command, 0x1000); /* Step 6 : Configure a Auto-Refresh command */ command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK; command->AutoRefreshNumber = MICROPY_HW_SDRAM_AUTOREFRESH_NUM; command->ModeRegisterDefinition = 0; /* Send the command */ HAL_SDRAM_SendCommand(hsdram, command, 0x1000); /* Step 7: Program the external memory mode register */ tmpmrd = (uint32_t)FMC_INIT(SDRAM_MODEREG_BURST_LENGTH, MICROPY_HW_SDRAM_BURST_LENGTH) | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | FMC_INIT(SDRAM_MODEREG_CAS_LATENCY, MICROPY_HW_SDRAM_CAS_LATENCY) | SDRAM_MODEREG_OPERATING_MODE_STANDARD | SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE; command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK; command->AutoRefreshNumber = 1; command->ModeRegisterDefinition = tmpmrd; /* Send the command */ HAL_SDRAM_SendCommand(hsdram, command, 0x1000); /* Step 8: Set the refresh rate counter RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc RefreshCycles = 7.8125 us * 90 MHz = 703 According to the formula on p.1665 of the reference manual, we also need to subtract 20 from the value, so the target refresh rate is 703 - 20 = 683. */ #define REFRESH_COUNT (MICROPY_HW_SDRAM_REFRESH_RATE * 90000 / 8192 - 20) HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT); #if defined(STM32F7) /* Enable MPU for the SDRAM Memory Region to allow non-aligned accesses (hard-fault otherwise) Initially disable all access for the entire SDRAM memory space, then enable access/caching for the size used */ uint32_t irq_state = mpu_config_start(); mpu_config_region(MPU_REGION_SDRAM1, SDRAM_START_ADDRESS, MPU_CONFIG_DISABLE(0x00, MPU_REGION_SIZE_512MB)); mpu_config_region(MPU_REGION_SDRAM2, SDRAM_START_ADDRESS, MPU_CONFIG_SDRAM(SDRAM_MPU_REGION_SIZE)); mpu_config_end(irq_state); #endif } bool __attribute__((optimize("O0"))) sdram_test(bool fast) { uint8_t const pattern = 0xaa; uint8_t const antipattern = 0x55; uint8_t *const mem_base = (uint8_t*)sdram_start(); /* test data bus */ for (uint8_t i = 1; i; i <<= 1) { *mem_base = i; if (*mem_base != i) { printf("data bus lines test failed! data (%d)\n", i); __asm__ volatile ("BKPT"); } } /* test address bus */ /* Check individual address lines */ for (uint32_t i = 1; i < MICROPY_HW_SDRAM_SIZE; i <<= 1) { mem_base[i] = pattern; if (mem_base[i] != pattern) { printf("address bus lines test failed! address (%p)\n", &mem_base[i]); __asm__ volatile ("BKPT"); } } /* Check for aliasing (overlaping addresses) */ mem_base[0] = antipattern; for (uint32_t i = 1; i < MICROPY_HW_SDRAM_SIZE; i <<= 1) { if (mem_base[i] != pattern) { printf("address bus overlap %p\n", &mem_base[i]); __asm__ volatile ("BKPT"); } } /* test all ram cells */ if (!fast) { for (uint32_t i = 0; i < MICROPY_HW_SDRAM_SIZE; ++i) { mem_base[i] = pattern; if (mem_base[i] != pattern) { printf("address bus test failed! address (%p)\n", &mem_base[i]); __asm__ volatile ("BKPT"); } } } else { memset(mem_base, pattern, MICROPY_HW_SDRAM_SIZE); } return true; } #endif // FMC_SDRAM_BANK micropython-1.12/ports/stm32/sdram.h000066400000000000000000000006041357706137100174200ustar00rootroot00000000000000/* * This file is part of the OpenMV project. * Copyright (c) 2013/2014 Ibrahim Abdelkader * This work is licensed under the MIT license, see the file LICENSE for details. * * SDRAM Driver. * */ #ifndef __SDRAM_H__ #define __SDRAM_H__ bool sdram_init(void); void *sdram_start(void); void *sdram_end(void); bool sdram_test(bool fast); #endif // __SDRAM_H__ micropython-1.12/ports/stm32/servo.c000066400000000000000000000305331357706137100174470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/mphal.h" #include "pin.h" #include "timer.h" #include "servo.h" #if MICROPY_HW_ENABLE_SERVO // This file implements the pyb.Servo class which controls standard hobby servo // motors that have 3-wires (ground, power, signal). // // The driver uses hardware PWM to drive servos on pins X1, X2, X3, X4 which are // assumed to be on PA0, PA1, PA2, PA3 but not necessarily in that order (the // pins PA0-PA3 are used directly if the X pins are not defined). // // TIM2 and TIM5 have CH1-CH4 on PA0-PA3 respectively. They are both 32-bit // counters with 16-bit prescaler. TIM5 is used by this driver. #define PYB_SERVO_NUM (4) typedef struct _pyb_servo_obj_t { mp_obj_base_t base; const pin_obj_t *pin; uint8_t pulse_min; // units of 10us uint8_t pulse_max; // units of 10us uint8_t pulse_centre; // units of 10us uint8_t pulse_angle_90; // units of 10us; pulse at 90 degrees, minus pulse_centre uint8_t pulse_speed_100; // units of 10us; pulse at 100% forward speed, minus pulse_centre uint16_t pulse_cur; // units of 10us uint16_t pulse_dest; // units of 10us int16_t pulse_accum; uint16_t time_left; } pyb_servo_obj_t; STATIC pyb_servo_obj_t pyb_servo_obj[PYB_SERVO_NUM]; void servo_init(void) { // reset servo objects for (int i = 0; i < PYB_SERVO_NUM; i++) { pyb_servo_obj[i].base.type = &pyb_servo_type; pyb_servo_obj[i].pulse_min = 64; pyb_servo_obj[i].pulse_max = 242; pyb_servo_obj[i].pulse_centre = 150; pyb_servo_obj[i].pulse_angle_90 = 97; pyb_servo_obj[i].pulse_speed_100 = 70; pyb_servo_obj[i].pulse_cur = 150; pyb_servo_obj[i].pulse_dest = 0; pyb_servo_obj[i].time_left = 0; } // assign servo objects to specific pins (must be some permutation of PA0-PA3) #ifdef pyb_pin_X1 pyb_servo_obj[0].pin = pyb_pin_X1; pyb_servo_obj[1].pin = pyb_pin_X2; pyb_servo_obj[2].pin = pyb_pin_X3; pyb_servo_obj[3].pin = pyb_pin_X4; #else pyb_servo_obj[0].pin = pin_A0; pyb_servo_obj[1].pin = pin_A1; pyb_servo_obj[2].pin = pin_A2; pyb_servo_obj[3].pin = pin_A3; #endif } void servo_timer_irq_callback(void) { bool need_it = false; for (int i = 0; i < PYB_SERVO_NUM; i++) { pyb_servo_obj_t *s = &pyb_servo_obj[i]; if (s->pulse_cur != s->pulse_dest) { // clamp pulse to within min/max if (s->pulse_dest < s->pulse_min) { s->pulse_dest = s->pulse_min; } else if (s->pulse_dest > s->pulse_max) { s->pulse_dest = s->pulse_max; } // adjust cur to get closer to dest if (s->time_left <= 1) { s->pulse_cur = s->pulse_dest; s->time_left = 0; } else { s->pulse_accum += s->pulse_dest - s->pulse_cur; s->pulse_cur += s->pulse_accum / s->time_left; s->pulse_accum %= s->time_left; s->time_left--; need_it = true; } // set the pulse width *(&TIM5->CCR1 + s->pin->pin) = s->pulse_cur; } } if (need_it) { __HAL_TIM_ENABLE_IT(&TIM5_Handle, TIM_IT_UPDATE); } else { __HAL_TIM_DISABLE_IT(&TIM5_Handle, TIM_IT_UPDATE); } } STATIC void servo_init_channel(pyb_servo_obj_t *s) { static const uint8_t channel_table[4] = {TIM_CHANNEL_1, TIM_CHANNEL_2, TIM_CHANNEL_3, TIM_CHANNEL_4}; uint32_t channel = channel_table[s->pin->pin]; // GPIO configuration mp_hal_pin_config(s->pin, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, GPIO_AF2_TIM5); if (__HAL_RCC_TIM5_IS_CLK_DISABLED()) { timer_tim5_init(); } // PWM mode configuration TIM_OC_InitTypeDef oc_init; oc_init.OCMode = TIM_OCMODE_PWM1; oc_init.Pulse = s->pulse_cur; // units of 10us oc_init.OCPolarity = TIM_OCPOLARITY_HIGH; oc_init.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&TIM5_Handle, &oc_init, channel); // start PWM HAL_TIM_PWM_Start(&TIM5_Handle, channel); } /******************************************************************************/ // MicroPython bindings STATIC mp_obj_t pyb_servo_set(mp_obj_t port, mp_obj_t value) { int p = mp_obj_get_int(port); int v = mp_obj_get_int(value); if (v < 50) { v = 50; } if (v > 250) { v = 250; } switch (p) { case 1: TIM5->CCR1 = v; break; case 2: TIM5->CCR2 = v; break; case 3: TIM5->CCR3 = v; break; case 4: TIM5->CCR4 = v; break; } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(pyb_servo_set_obj, pyb_servo_set); STATIC mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse) { int pe = mp_obj_get_int(period); int pu = mp_obj_get_int(pulse); TIM5->ARR = pe; TIM5->CCR3 = pu; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(pyb_pwm_set_obj, pyb_pwm_set); STATIC void pyb_servo_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_servo_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self - &pyb_servo_obj[0] + 1, 10 * self->pulse_cur); } /// \classmethod \constructor(id) /// Create a servo object. `id` is 1-4. STATIC mp_obj_t pyb_servo_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); // get servo number mp_int_t servo_id = mp_obj_get_int(args[0]) - 1; // check servo number if (!(0 <= servo_id && servo_id < PYB_SERVO_NUM)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Servo(%d) doesn't exist", servo_id + 1)); } // get and init servo object pyb_servo_obj_t *s = &pyb_servo_obj[servo_id]; s->pulse_dest = s->pulse_cur; s->time_left = 0; servo_init_channel(s); return MP_OBJ_FROM_PTR(s); } /// \method pulse_width([value]) /// Get or set the pulse width in milliseconds. STATIC mp_obj_t pyb_servo_pulse_width(size_t n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get pulse width, in us return mp_obj_new_int(10 * self->pulse_cur); } else { // set pulse width, in us self->pulse_dest = mp_obj_get_int(args[1]) / 10; self->time_left = 0; servo_timer_irq_callback(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_servo_pulse_width_obj, 1, 2, pyb_servo_pulse_width); /// \method calibration([pulse_min, pulse_max, pulse_centre, [pulse_angle_90, pulse_speed_100]]) /// Get or set the calibration of the servo timing. // TODO should accept 1 arg, a 5-tuple of values to set STATIC mp_obj_t pyb_servo_calibration(size_t n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get calibration values mp_obj_t tuple[5]; tuple[0] = mp_obj_new_int(10 * self->pulse_min); tuple[1] = mp_obj_new_int(10 * self->pulse_max); tuple[2] = mp_obj_new_int(10 * self->pulse_centre); tuple[3] = mp_obj_new_int(10 * (self->pulse_angle_90 + self->pulse_centre)); tuple[4] = mp_obj_new_int(10 * (self->pulse_speed_100 + self->pulse_centre)); return mp_obj_new_tuple(5, tuple); } else if (n_args >= 4) { // set min, max, centre self->pulse_min = mp_obj_get_int(args[1]) / 10; self->pulse_max = mp_obj_get_int(args[2]) / 10; self->pulse_centre = mp_obj_get_int(args[3]) / 10; if (n_args == 4) { return mp_const_none; } else if (n_args == 6) { self->pulse_angle_90 = mp_obj_get_int(args[4]) / 10 - self->pulse_centre; self->pulse_speed_100 = mp_obj_get_int(args[5]) / 10 - self->pulse_centre; return mp_const_none; } } // bad number of arguments nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "calibration expecting 1, 4 or 6 arguments, got %d", n_args)); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_servo_calibration_obj, 1, 6, pyb_servo_calibration); /// \method angle([angle, time=0]) /// Get or set the angle of the servo. /// /// - `angle` is the angle to move to in degrees. /// - `time` is the number of milliseconds to take to get to the specified angle. STATIC mp_obj_t pyb_servo_angle(size_t n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get angle return mp_obj_new_int((self->pulse_cur - self->pulse_centre) * 90 / self->pulse_angle_90); } else { #if MICROPY_PY_BUILTINS_FLOAT self->pulse_dest = self->pulse_centre + self->pulse_angle_90 * mp_obj_get_float(args[1]) / 90.0; #else self->pulse_dest = self->pulse_centre + self->pulse_angle_90 * mp_obj_get_int(args[1]) / 90; #endif if (n_args == 2) { // set angle immediately self->time_left = 0; } else { // set angle over a given time (given in milli seconds) self->time_left = mp_obj_get_int(args[2]) / 20; self->pulse_accum = 0; } servo_timer_irq_callback(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_servo_angle_obj, 1, 3, pyb_servo_angle); /// \method speed([speed, time=0]) /// Get or set the speed of a continuous rotation servo. /// /// - `speed` is the speed to move to change to, between -100 and 100. /// - `time` is the number of milliseconds to take to get to the specified speed. STATIC mp_obj_t pyb_servo_speed(size_t n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get speed return mp_obj_new_int((self->pulse_cur - self->pulse_centre) * 100 / self->pulse_speed_100); } else { #if MICROPY_PY_BUILTINS_FLOAT self->pulse_dest = self->pulse_centre + self->pulse_speed_100 * mp_obj_get_float(args[1]) / 100.0; #else self->pulse_dest = self->pulse_centre + self->pulse_speed_100 * mp_obj_get_int(args[1]) / 100; #endif if (n_args == 2) { // set speed immediately self->time_left = 0; } else { // set speed over a given time (given in milli seconds) self->time_left = mp_obj_get_int(args[2]) / 20; self->pulse_accum = 0; } servo_timer_irq_callback(); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_servo_speed_obj, 1, 3, pyb_servo_speed); STATIC const mp_rom_map_elem_t pyb_servo_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_pulse_width), MP_ROM_PTR(&pyb_servo_pulse_width_obj) }, { MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&pyb_servo_calibration_obj) }, { MP_ROM_QSTR(MP_QSTR_angle), MP_ROM_PTR(&pyb_servo_angle_obj) }, { MP_ROM_QSTR(MP_QSTR_speed), MP_ROM_PTR(&pyb_servo_speed_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_servo_locals_dict, pyb_servo_locals_dict_table); const mp_obj_type_t pyb_servo_type = { { &mp_type_type }, .name = MP_QSTR_Servo, .print = pyb_servo_print, .make_new = pyb_servo_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_servo_locals_dict, }; #endif // MICROPY_HW_ENABLE_SERVO micropython-1.12/ports/stm32/servo.h000066400000000000000000000030151357706137100174470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_SERVO_H #define MICROPY_INCLUDED_STM32_SERVO_H void servo_init(void); void servo_timer_irq_callback(void); extern const mp_obj_type_t pyb_servo_type; MP_DECLARE_CONST_FUN_OBJ_2(pyb_servo_set_obj); MP_DECLARE_CONST_FUN_OBJ_2(pyb_pwm_set_obj); #endif // MICROPY_INCLUDED_STM32_SERVO_H micropython-1.12/ports/stm32/softtimer.c000066400000000000000000000077301357706137100203300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "irq.h" #include "softtimer.h" #define TICKS_PERIOD 0x80000000 #define TICKS_DIFF(t1, t0) ((int32_t)(((t1 - t0 + TICKS_PERIOD / 2) & (TICKS_PERIOD - 1)) - TICKS_PERIOD / 2)) extern __IO uint32_t uwTick; volatile uint32_t soft_timer_next; void soft_timer_deinit(void) { MP_STATE_PORT(soft_timer_head) = NULL; } STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { uint32_t irq_state = disable_irq(); uint32_t uw_tick = uwTick; if (TICKS_DIFF(ticks_ms, uw_tick) <= 0) { soft_timer_next = uw_tick + 1; } else { soft_timer_next = ticks_ms; } enable_irq(irq_state); } // Must be executed at IRQ_PRI_PENDSV void soft_timer_handler(void) { uint32_t ticks_ms = uwTick; soft_timer_entry_t *head = MP_STATE_PORT(soft_timer_head); while (head != NULL && TICKS_DIFF(head->expiry_ms, ticks_ms) <= 0) { mp_sched_schedule(head->callback, MP_OBJ_FROM_PTR(head)); if (head->mode == SOFT_TIMER_MODE_PERIODIC) { head->expiry_ms += head->delta_ms; // Shift this node along to its new position soft_timer_entry_t *cur = head; while (cur->next != NULL && TICKS_DIFF(head->expiry_ms, cur->next->expiry_ms) >= 0) { cur = cur->next; } if (cur != head) { soft_timer_entry_t *next = head->next; head->next = cur->next; cur->next = head; head = next; } } else { head = head->next; } } MP_STATE_PORT(soft_timer_head) = head; if (head == NULL) { // No more timers left, set largest delay possible soft_timer_next = uwTick; } else { // Set soft_timer_next so SysTick calls us back at the correct time soft_timer_schedule_systick(head->expiry_ms); } } void soft_timer_insert(soft_timer_entry_t *entry) { uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); soft_timer_entry_t **head_ptr = &MP_STATE_PORT(soft_timer_head); while (*head_ptr != NULL && TICKS_DIFF(entry->expiry_ms, (*head_ptr)->expiry_ms) >= 0) { head_ptr = &(*head_ptr)->next; } entry->next = *head_ptr; *head_ptr = entry; if (head_ptr == &MP_STATE_PORT(soft_timer_head)) { // This new timer became the earliest one so set soft_timer_next soft_timer_schedule_systick((*head_ptr)->expiry_ms); } restore_irq_pri(irq_state); } void soft_timer_remove(soft_timer_entry_t *entry) { uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); soft_timer_entry_t **cur = &MP_STATE_PORT(soft_timer_head); while (*cur != NULL) { if (*cur == entry) { *cur = entry->next; break; } } restore_irq_pri(irq_state); } micropython-1.12/ports/stm32/softtimer.h000066400000000000000000000036441357706137100203350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_SOFTTIMER_H #define MICROPY_INCLUDED_STM32_SOFTTIMER_H #include "py/obj.h" #define SOFT_TIMER_MODE_ONE_SHOT (1) #define SOFT_TIMER_MODE_PERIODIC (2) typedef struct _soft_timer_entry_t { mp_obj_base_t base; // so struct can be used as an object and still be traced by GC struct _soft_timer_entry_t *next; uint32_t mode; uint32_t expiry_ms; uint32_t delta_ms; // for periodic mode mp_obj_t callback; } soft_timer_entry_t; extern volatile uint32_t soft_timer_next; void soft_timer_deinit(void); void soft_timer_handler(void); void soft_timer_insert(soft_timer_entry_t *entry); void soft_timer_remove(soft_timer_entry_t *entry); #endif // MICROPY_INCLUDED_STM32_SOFTTIMER_H micropython-1.12/ports/stm32/spi.c000066400000000000000000000546761357706137100171220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mphal.h" #include "spi.h" // Possible DMA configurations for SPI busses: // SPI1_TX: DMA2_Stream3.CHANNEL_3 or DMA2_Stream5.CHANNEL_3 // SPI1_RX: DMA2_Stream0.CHANNEL_3 or DMA2_Stream2.CHANNEL_3 // SPI2_TX: DMA1_Stream4.CHANNEL_0 // SPI2_RX: DMA1_Stream3.CHANNEL_0 // SPI3_TX: DMA1_Stream5.CHANNEL_0 or DMA1_Stream7.CHANNEL_0 // SPI3_RX: DMA1_Stream0.CHANNEL_0 or DMA1_Stream2.CHANNEL_0 // SPI4_TX: DMA2_Stream4.CHANNEL_5 or DMA2_Stream1.CHANNEL_4 // SPI4_RX: DMA2_Stream3.CHANNEL_5 or DMA2_Stream0.CHANNEL_4 // SPI5_TX: DMA2_Stream4.CHANNEL_2 or DMA2_Stream6.CHANNEL_7 // SPI5_RX: DMA2_Stream3.CHANNEL_2 or DMA2_Stream5.CHANNEL_7 // SPI6_TX: DMA2_Stream5.CHANNEL_1 // SPI6_RX: DMA2_Stream6.CHANNEL_1 #if defined(MICROPY_HW_SPI1_SCK) SPI_HandleTypeDef SPIHandle1 = {.Instance = NULL}; #endif #if defined(MICROPY_HW_SPI2_SCK) SPI_HandleTypeDef SPIHandle2 = {.Instance = NULL}; #endif #if defined(MICROPY_HW_SPI3_SCK) SPI_HandleTypeDef SPIHandle3 = {.Instance = NULL}; #endif #if defined(MICROPY_HW_SPI4_SCK) SPI_HandleTypeDef SPIHandle4 = {.Instance = NULL}; #endif #if defined(MICROPY_HW_SPI5_SCK) SPI_HandleTypeDef SPIHandle5 = {.Instance = NULL}; #endif #if defined(MICROPY_HW_SPI6_SCK) SPI_HandleTypeDef SPIHandle6 = {.Instance = NULL}; #endif const spi_t spi_obj[6] = { #if defined(MICROPY_HW_SPI1_SCK) {&SPIHandle1, &dma_SPI_1_TX, &dma_SPI_1_RX}, #else {NULL, NULL, NULL}, #endif #if defined(MICROPY_HW_SPI2_SCK) {&SPIHandle2, &dma_SPI_2_TX, &dma_SPI_2_RX}, #else {NULL, NULL, NULL}, #endif #if defined(MICROPY_HW_SPI3_SCK) {&SPIHandle3, &dma_SPI_3_TX, &dma_SPI_3_RX}, #else {NULL, NULL, NULL}, #endif #if defined(MICROPY_HW_SPI4_SCK) {&SPIHandle4, &dma_SPI_4_TX, &dma_SPI_4_RX}, #else {NULL, NULL, NULL}, #endif #if defined(MICROPY_HW_SPI5_SCK) {&SPIHandle5, &dma_SPI_5_TX, &dma_SPI_5_RX}, #else {NULL, NULL, NULL}, #endif #if defined(MICROPY_HW_SPI6_SCK) {&SPIHandle6, &dma_SPI_6_TX, &dma_SPI_6_RX}, #else {NULL, NULL, NULL}, #endif }; #if defined(STM32H7) // STM32H7 HAL requires SPI IRQs to be enabled and handled. #if defined(MICROPY_HW_SPI1_SCK) void SPI1_IRQHandler(void) { IRQ_ENTER(SPI1_IRQn); HAL_SPI_IRQHandler(&SPIHandle1); IRQ_EXIT(SPI1_IRQn); } #endif #if defined(MICROPY_HW_SPI2_SCK) void SPI2_IRQHandler(void) { IRQ_ENTER(SPI2_IRQn); HAL_SPI_IRQHandler(&SPIHandle2); IRQ_EXIT(SPI2_IRQn); } #endif #if defined(MICROPY_HW_SPI3_SCK) void SPI3_IRQHandler(void) { IRQ_ENTER(SPI3_IRQn); HAL_SPI_IRQHandler(&SPIHandle3); IRQ_EXIT(SPI3_IRQn); } #endif #if defined(MICROPY_HW_SPI4_SCK) void SPI4_IRQHandler(void) { IRQ_ENTER(SPI4_IRQn); HAL_SPI_IRQHandler(&SPIHandle4); IRQ_EXIT(SPI4_IRQn); } #endif #if defined(MICROPY_HW_SPI5_SCK) void SPI5_IRQHandler(void) { IRQ_ENTER(SPI5_IRQn); HAL_SPI_IRQHandler(&SPIHandle5); IRQ_EXIT(SPI5_IRQn); } #endif #if defined(MICROPY_HW_SPI6_SCK) void SPI6_IRQHandler(void) { IRQ_ENTER(SPI6_IRQn); HAL_SPI_IRQHandler(&SPIHandle6); IRQ_EXIT(SPI6_IRQn); } #endif #endif void spi_init0(void) { // Initialise the SPI handles. // The structs live on the BSS so all other fields will be zero after a reset. #if defined(MICROPY_HW_SPI1_SCK) SPIHandle1.Instance = SPI1; #endif #if defined(MICROPY_HW_SPI2_SCK) SPIHandle2.Instance = SPI2; #endif #if defined(MICROPY_HW_SPI3_SCK) SPIHandle3.Instance = SPI3; #endif #if defined(MICROPY_HW_SPI4_SCK) SPIHandle4.Instance = SPI4; #endif #if defined(MICROPY_HW_SPI5_SCK) SPIHandle5.Instance = SPI5; #endif #if defined(MICROPY_HW_SPI6_SCK) SPIHandle6.Instance = SPI6; #endif } int spi_find_index(mp_obj_t id) { if (mp_obj_is_str(id)) { // given a string id const char *port = mp_obj_str_get_str(id); if (0) { #ifdef MICROPY_HW_SPI1_NAME } else if (strcmp(port, MICROPY_HW_SPI1_NAME) == 0) { return 1; #endif #ifdef MICROPY_HW_SPI2_NAME } else if (strcmp(port, MICROPY_HW_SPI2_NAME) == 0) { return 2; #endif #ifdef MICROPY_HW_SPI3_NAME } else if (strcmp(port, MICROPY_HW_SPI3_NAME) == 0) { return 3; #endif #ifdef MICROPY_HW_SPI4_NAME } else if (strcmp(port, MICROPY_HW_SPI4_NAME) == 0) { return 4; #endif #ifdef MICROPY_HW_SPI5_NAME } else if (strcmp(port, MICROPY_HW_SPI5_NAME) == 0) { return 5; #endif #ifdef MICROPY_HW_SPI6_NAME } else if (strcmp(port, MICROPY_HW_SPI6_NAME) == 0) { return 6; #endif } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "SPI(%s) doesn't exist", port)); } else { // given an integer id int spi_id = mp_obj_get_int(id); if (spi_id >= 1 && spi_id <= MP_ARRAY_SIZE(spi_obj) && spi_obj[spi_id - 1].spi != NULL) { return spi_id; } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "SPI(%d) doesn't exist", spi_id)); } } STATIC uint32_t spi_get_source_freq(SPI_HandleTypeDef *spi) { #if defined(STM32F0) return HAL_RCC_GetPCLK1Freq(); #elif defined(STM32H7) if (spi->Instance == SPI1 || spi->Instance == SPI2 || spi->Instance == SPI3) { return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123); } else if (spi->Instance == SPI4 || spi->Instance == SPI5) { return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45); } else { return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6); } #else #if defined(SPI2) if (spi->Instance == SPI2) { // SPI2 is on APB1 return HAL_RCC_GetPCLK1Freq(); } else #endif #if defined(SPI3) if (spi->Instance == SPI3) { // SPI3 is on APB1 return HAL_RCC_GetPCLK1Freq(); } else #endif { // SPI1, SPI4, SPI5 and SPI6 are on APB2 return HAL_RCC_GetPCLK2Freq(); } #endif } // sets the parameters in the SPI_InitTypeDef struct // if an argument is -1 then the corresponding parameter is not changed void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate, int32_t polarity, int32_t phase, int32_t bits, int32_t firstbit) { SPI_HandleTypeDef *spi = spi_obj->spi; SPI_InitTypeDef *init = &spi->Init; if (prescale != 0xffffffff || baudrate != -1) { if (prescale == 0xffffffff) { // prescaler not given, so select one that yields at most the requested baudrate prescale = (spi_get_source_freq(spi) + baudrate - 1) / baudrate; } if (prescale <= 2) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; } else if (prescale <= 4) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; } else if (prescale <= 8) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; } else if (prescale <= 16) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; } else if (prescale <= 32) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; } else if (prescale <= 64) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; } else if (prescale <= 128) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; } else { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; } } if (polarity != -1) { init->CLKPolarity = polarity == 0 ? SPI_POLARITY_LOW : SPI_POLARITY_HIGH; } if (phase != -1) { init->CLKPhase = phase == 0 ? SPI_PHASE_1EDGE : SPI_PHASE_2EDGE; } if (bits != -1) { init->DataSize = (bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT; } if (firstbit != -1) { init->FirstBit = firstbit; } } // TODO allow to take a list of pins to use void spi_init(const spi_t *self, bool enable_nss_pin) { SPI_HandleTypeDef *spi = self->spi; uint32_t irqn = 0; const pin_obj_t *pins[4] = { NULL, NULL, NULL, NULL }; if (0) { #if defined(MICROPY_HW_SPI1_SCK) } else if (spi->Instance == SPI1) { irqn = SPI1_IRQn; #if defined(MICROPY_HW_SPI1_NSS) pins[0] = MICROPY_HW_SPI1_NSS; #endif pins[1] = MICROPY_HW_SPI1_SCK; #if defined(MICROPY_HW_SPI1_MISO) pins[2] = MICROPY_HW_SPI1_MISO; #endif pins[3] = MICROPY_HW_SPI1_MOSI; // enable the SPI clock __HAL_RCC_SPI1_CLK_ENABLE(); #endif #if defined(MICROPY_HW_SPI2_SCK) } else if (spi->Instance == SPI2) { irqn = SPI2_IRQn; #if defined(MICROPY_HW_SPI2_NSS) pins[0] = MICROPY_HW_SPI2_NSS; #endif pins[1] = MICROPY_HW_SPI2_SCK; #if defined(MICROPY_HW_SPI2_MISO) pins[2] = MICROPY_HW_SPI2_MISO; #endif pins[3] = MICROPY_HW_SPI2_MOSI; // enable the SPI clock __HAL_RCC_SPI2_CLK_ENABLE(); #endif #if defined(MICROPY_HW_SPI3_SCK) } else if (spi->Instance == SPI3) { irqn = SPI3_IRQn; #if defined(MICROPY_HW_SPI3_NSS) pins[0] = MICROPY_HW_SPI3_NSS; #endif pins[1] = MICROPY_HW_SPI3_SCK; #if defined(MICROPY_HW_SPI3_MISO) pins[2] = MICROPY_HW_SPI3_MISO; #endif pins[3] = MICROPY_HW_SPI3_MOSI; // enable the SPI clock __HAL_RCC_SPI3_CLK_ENABLE(); #endif #if defined(MICROPY_HW_SPI4_SCK) } else if (spi->Instance == SPI4) { irqn = SPI4_IRQn; #if defined(MICROPY_HW_SPI4_NSS) pins[0] = MICROPY_HW_SPI4_NSS; #endif pins[1] = MICROPY_HW_SPI4_SCK; #if defined(MICROPY_HW_SPI4_MISO) pins[2] = MICROPY_HW_SPI4_MISO; #endif pins[3] = MICROPY_HW_SPI4_MOSI; // enable the SPI clock __HAL_RCC_SPI4_CLK_ENABLE(); #endif #if defined(MICROPY_HW_SPI5_SCK) } else if (spi->Instance == SPI5) { irqn = SPI5_IRQn; #if defined(MICROPY_HW_SPI5_NSS) pins[0] = MICROPY_HW_SPI5_NSS; #endif pins[1] = MICROPY_HW_SPI5_SCK; #if defined(MICROPY_HW_SPI5_MISO) pins[2] = MICROPY_HW_SPI5_MISO; #endif pins[3] = MICROPY_HW_SPI5_MOSI; // enable the SPI clock __HAL_RCC_SPI5_CLK_ENABLE(); #endif #if defined(MICROPY_HW_SPI6_SCK) } else if (spi->Instance == SPI6) { irqn = SPI6_IRQn; #if defined(MICROPY_HW_SPI6_NSS) pins[0] = MICROPY_HW_SPI6_NSS; #endif pins[1] = MICROPY_HW_SPI6_SCK; #if defined(MICROPY_HW_SPI6_MISO) pins[2] = MICROPY_HW_SPI6_MISO; #endif pins[3] = MICROPY_HW_SPI6_MOSI; // enable the SPI clock __HAL_RCC_SPI6_CLK_ENABLE(); #endif } else { // SPI does not exist for this board (shouldn't get here, should be checked by caller) return; } // init the GPIO lines uint32_t mode = MP_HAL_PIN_MODE_ALT; uint32_t pull = spi->Init.CLKPolarity == SPI_POLARITY_LOW ? MP_HAL_PIN_PULL_DOWN : MP_HAL_PIN_PULL_UP; for (uint i = (enable_nss_pin ? 0 : 1); i < 4; i++) { if (pins[i] == NULL) { continue; } mp_hal_pin_config_alt(pins[i], mode, pull, AF_FN_SPI, (self - &spi_obj[0]) + 1); } // init the SPI device if (HAL_SPI_Init(spi) != HAL_OK) { // init error // TODO should raise an exception, but this function is not necessarily going to be // called via Python, so may not be properly wrapped in an NLR handler printf("OSError: HAL_SPI_Init failed\n"); return; } // After calling HAL_SPI_Init() it seems that the DMA gets disconnected if // it was previously configured. So we invalidate the DMA channel to force // an initialisation the next time we use it. dma_invalidate_channel(self->tx_dma_descr); dma_invalidate_channel(self->rx_dma_descr); #if defined(STM32H7) NVIC_SetPriority(irqn, IRQ_PRI_SPI); HAL_NVIC_EnableIRQ(irqn); #else (void)irqn; #endif } void spi_deinit(const spi_t *spi_obj) { SPI_HandleTypeDef *spi = spi_obj->spi; HAL_SPI_DeInit(spi); if (0) { #if defined(MICROPY_HW_SPI1_SCK) } else if (spi->Instance == SPI1) { __HAL_RCC_SPI1_FORCE_RESET(); __HAL_RCC_SPI1_RELEASE_RESET(); __HAL_RCC_SPI1_CLK_DISABLE(); HAL_NVIC_DisableIRQ(SPI1_IRQn); #endif #if defined(MICROPY_HW_SPI2_SCK) } else if (spi->Instance == SPI2) { __HAL_RCC_SPI2_FORCE_RESET(); __HAL_RCC_SPI2_RELEASE_RESET(); __HAL_RCC_SPI2_CLK_DISABLE(); HAL_NVIC_DisableIRQ(SPI2_IRQn); #endif #if defined(MICROPY_HW_SPI3_SCK) } else if (spi->Instance == SPI3) { __HAL_RCC_SPI3_FORCE_RESET(); __HAL_RCC_SPI3_RELEASE_RESET(); __HAL_RCC_SPI3_CLK_DISABLE(); HAL_NVIC_DisableIRQ(SPI3_IRQn); #endif #if defined(MICROPY_HW_SPI4_SCK) } else if (spi->Instance == SPI4) { __HAL_RCC_SPI4_FORCE_RESET(); __HAL_RCC_SPI4_RELEASE_RESET(); __HAL_RCC_SPI4_CLK_DISABLE(); HAL_NVIC_DisableIRQ(SPI4_IRQn); #endif #if defined(MICROPY_HW_SPI5_SCK) } else if (spi->Instance == SPI5) { __HAL_RCC_SPI5_FORCE_RESET(); __HAL_RCC_SPI5_RELEASE_RESET(); __HAL_RCC_SPI5_CLK_DISABLE(); HAL_NVIC_DisableIRQ(SPI5_IRQn); #endif #if defined(MICROPY_HW_SPI6_SCK) } else if (spi->Instance == SPI6) { __HAL_RCC_SPI6_FORCE_RESET(); __HAL_RCC_SPI6_RELEASE_RESET(); __HAL_RCC_SPI6_CLK_DISABLE(); HAL_NVIC_DisableIRQ(SPI6_IRQn); #endif } } STATIC HAL_StatusTypeDef spi_wait_dma_finished(const spi_t *spi, uint32_t t_start, uint32_t timeout) { volatile HAL_SPI_StateTypeDef *state = &spi->spi->State; for (;;) { // Do an atomic check of the state; WFI will exit even if IRQs are disabled uint32_t irq_state = disable_irq(); if (*state == HAL_SPI_STATE_READY) { enable_irq(irq_state); return HAL_OK; } __WFI(); enable_irq(irq_state); if (HAL_GetTick() - t_start >= timeout) { return HAL_TIMEOUT; } } return HAL_OK; } void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint8_t *dest, uint32_t timeout) { // Note: there seems to be a problem sending 1 byte using DMA the first // time directly after the SPI/DMA is initialised. The cause of this is // unknown but we sidestep the issue by using polling for 1 byte transfer. // Note: DMA transfers are limited to 65535 bytes at a time. HAL_StatusTypeDef status; if (dest == NULL) { // send only if (len == 1 || query_irq() == IRQ_STATE_DISABLED) { status = HAL_SPI_Transmit(self->spi, (uint8_t*)src, len, timeout); } else { DMA_HandleTypeDef tx_dma; dma_init(&tx_dma, self->tx_dma_descr, DMA_MEMORY_TO_PERIPH, self->spi); self->spi->hdmatx = &tx_dma; self->spi->hdmarx = NULL; MP_HAL_CLEAN_DCACHE(src, len); uint32_t t_start = HAL_GetTick(); do { uint32_t l = MIN(len, 65535); status = HAL_SPI_Transmit_DMA(self->spi, (uint8_t*)src, l); if (status != HAL_OK) { break; } status = spi_wait_dma_finished(self, t_start, timeout); if (status != HAL_OK) { break; } len -= l; src += l; } while (len); dma_deinit(self->tx_dma_descr); } } else if (src == NULL) { // receive only if (len == 1 || query_irq() == IRQ_STATE_DISABLED) { status = HAL_SPI_Receive(self->spi, dest, len, timeout); } else { DMA_HandleTypeDef tx_dma, rx_dma; if (self->spi->Init.Mode == SPI_MODE_MASTER) { // in master mode the HAL actually does a TransmitReceive call dma_init(&tx_dma, self->tx_dma_descr, DMA_MEMORY_TO_PERIPH, self->spi); self->spi->hdmatx = &tx_dma; } else { self->spi->hdmatx = NULL; } dma_init(&rx_dma, self->rx_dma_descr, DMA_PERIPH_TO_MEMORY, self->spi); self->spi->hdmarx = &rx_dma; MP_HAL_CLEANINVALIDATE_DCACHE(dest, len); uint32_t t_start = HAL_GetTick(); do { uint32_t l = MIN(len, 65535); status = HAL_SPI_Receive_DMA(self->spi, dest, l); if (status != HAL_OK) { break; } status = spi_wait_dma_finished(self, t_start, timeout); if (status != HAL_OK) { break; } len -= l; dest += l; } while (len); if (self->spi->hdmatx != NULL) { dma_deinit(self->tx_dma_descr); } dma_deinit(self->rx_dma_descr); } } else { // send and receive if (len == 1 || query_irq() == IRQ_STATE_DISABLED) { status = HAL_SPI_TransmitReceive(self->spi, (uint8_t*)src, dest, len, timeout); } else { DMA_HandleTypeDef tx_dma, rx_dma; dma_init(&tx_dma, self->tx_dma_descr, DMA_MEMORY_TO_PERIPH, self->spi); self->spi->hdmatx = &tx_dma; dma_init(&rx_dma, self->rx_dma_descr, DMA_PERIPH_TO_MEMORY, self->spi); self->spi->hdmarx = &rx_dma; MP_HAL_CLEAN_DCACHE(src, len); MP_HAL_CLEANINVALIDATE_DCACHE(dest, len); uint32_t t_start = HAL_GetTick(); do { uint32_t l = MIN(len, 65535); status = HAL_SPI_TransmitReceive_DMA(self->spi, (uint8_t*)src, dest, l); if (status != HAL_OK) { break; } status = spi_wait_dma_finished(self, t_start, timeout); if (status != HAL_OK) { break; } len -= l; src += l; dest += l; } while (len); dma_deinit(self->tx_dma_descr); dma_deinit(self->rx_dma_descr); } } if (status != HAL_OK) { mp_hal_raise(status); } } void spi_print(const mp_print_t *print, const spi_t *spi_obj, bool legacy) { SPI_HandleTypeDef *spi = spi_obj->spi; uint spi_num = 1; // default to SPI1 if (0) { } #if defined(SPI2) else if (spi->Instance == SPI2) { spi_num = 2; } #endif #if defined(SPI3) else if (spi->Instance == SPI3) { spi_num = 3; } #endif #if defined(SPI4) else if (spi->Instance == SPI4) { spi_num = 4; } #endif #if defined(SPI5) else if (spi->Instance == SPI5) { spi_num = 5; } #endif #if defined(SPI6) else if (spi->Instance == SPI6) { spi_num = 6; } #endif mp_printf(print, "SPI(%u", spi_num); if (spi->State != HAL_SPI_STATE_RESET) { if (spi->Init.Mode == SPI_MODE_MASTER) { // compute baudrate uint log_prescaler = (spi->Init.BaudRatePrescaler >> 3) + 1; uint baudrate = spi_get_source_freq(spi) >> log_prescaler; if (legacy) { mp_printf(print, ", SPI.MASTER"); } mp_printf(print, ", baudrate=%u", baudrate); if (legacy) { mp_printf(print, ", prescaler=%u", 1 << log_prescaler); } } else { mp_printf(print, ", SPI.SLAVE"); } mp_printf(print, ", polarity=%u, phase=%u, bits=%u", spi->Init.CLKPolarity == SPI_POLARITY_LOW ? 0 : 1, spi->Init.CLKPhase == SPI_PHASE_1EDGE ? 0 : 1, spi->Init.DataSize == SPI_DATASIZE_8BIT ? 8 : 16); if (spi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) { mp_printf(print, ", crc=0x%x", spi->Init.CRCPolynomial); } } mp_print_str(print, ")"); } const spi_t *spi_from_mp_obj(mp_obj_t o) { if (mp_obj_is_type(o, &pyb_spi_type)) { pyb_spi_obj_t *self = MP_OBJ_TO_PTR(o); return self->spi; } else if (mp_obj_is_type(o, &machine_hard_spi_type)) { machine_hard_spi_obj_t *self = MP_OBJ_TO_PTR(o); return self->spi; } else { mp_raise_TypeError("expecting an SPI object"); } } /******************************************************************************/ // Implementation of low-level SPI C protocol STATIC int spi_proto_ioctl(void *self_in, uint32_t cmd) { spi_proto_cfg_t *self = (spi_proto_cfg_t*)self_in; switch (cmd) { case MP_SPI_IOCTL_INIT: self->spi->spi->Init.Mode = SPI_MODE_MASTER; self->spi->spi->Init.Direction = SPI_DIRECTION_2LINES; self->spi->spi->Init.NSS = SPI_NSS_SOFT; self->spi->spi->Init.TIMode = SPI_TIMODE_DISABLE; self->spi->spi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; spi_set_params(self->spi, 0xffffffff, self->baudrate, self->polarity, self->phase, self->bits, self->firstbit); spi_init(self->spi, false); break; case MP_SPI_IOCTL_DEINIT: spi_deinit(self->spi); break; } return 0; } STATIC void spi_proto_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) { spi_proto_cfg_t *self = (spi_proto_cfg_t*)self_in; spi_transfer(self->spi, len, src, dest, SPI_TRANSFER_TIMEOUT(len)); } const mp_spi_proto_t spi_proto = { .ioctl = spi_proto_ioctl, .transfer = spi_proto_transfer, }; micropython-1.12/ports/stm32/spi.h000066400000000000000000000061211357706137100171050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_SPI_H #define MICROPY_INCLUDED_STM32_SPI_H #include "drivers/bus/spi.h" #include "dma.h" typedef struct _spi_t { SPI_HandleTypeDef *spi; const dma_descr_t *tx_dma_descr; const dma_descr_t *rx_dma_descr; } spi_t; typedef struct _spi_proto_cfg_t { const spi_t *spi; uint32_t baudrate; uint8_t polarity; uint8_t phase; uint8_t bits; uint8_t firstbit; } spi_proto_cfg_t; typedef struct _pyb_spi_obj_t { mp_obj_base_t base; const spi_t *spi; } pyb_spi_obj_t; typedef struct _machine_hard_spi_obj_t { mp_obj_base_t base; const spi_t *spi; } machine_hard_spi_obj_t; extern SPI_HandleTypeDef SPIHandle1; extern SPI_HandleTypeDef SPIHandle2; extern SPI_HandleTypeDef SPIHandle3; extern SPI_HandleTypeDef SPIHandle4; extern SPI_HandleTypeDef SPIHandle5; extern SPI_HandleTypeDef SPIHandle6; extern const spi_t spi_obj[6]; extern const mp_spi_proto_t spi_proto; extern const mp_obj_type_t pyb_spi_type; extern const mp_obj_type_t machine_soft_spi_type; extern const mp_obj_type_t machine_hard_spi_type; // A transfer of "len" bytes should take len*8*1000/baudrate milliseconds. // To simplify the calculation we assume the baudrate is never less than 8kHz // and use that value for the baudrate in the formula, plus a small constant. #define SPI_TRANSFER_TIMEOUT(len) ((len) + 100) void spi_init0(void); void spi_init(const spi_t *spi, bool enable_nss_pin); void spi_deinit(const spi_t *spi_obj); int spi_find_index(mp_obj_t id); void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate, int32_t polarity, int32_t phase, int32_t bits, int32_t firstbit); void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint8_t *dest, uint32_t timeout); void spi_print(const mp_print_t *print, const spi_t *spi_obj, bool legacy); const spi_t *spi_from_mp_obj(mp_obj_t o); #endif // MICROPY_INCLUDED_STM32_SPI_H micropython-1.12/ports/stm32/spibdev.c000066400000000000000000000105031357706137100177400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/mperrno.h" #include "irq.h" #include "led.h" #include "storage.h" #if MICROPY_HW_ENABLE_STORAGE int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) { switch (op) { case BDEV_IOCTL_INIT: bdev->spiflash.config = (const mp_spiflash_config_t*)arg; mp_spiflash_init(&bdev->spiflash); bdev->flash_tick_counter_last_write = 0; return 0; case BDEV_IOCTL_IRQ_HANDLER: if ((bdev->spiflash.flags & 1) && HAL_GetTick() - bdev->flash_tick_counter_last_write >= 1000) { mp_spiflash_cache_flush(&bdev->spiflash); led_state(PYB_LED_RED, 0); // indicate a clean cache with LED off } return 0; case BDEV_IOCTL_SYNC: if (bdev->spiflash.flags & 1) { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access mp_spiflash_cache_flush(&bdev->spiflash); led_state(PYB_LED_RED, 0); // indicate a clean cache with LED off restore_irq_pri(basepri); } return 0; case BDEV_IOCTL_BLOCK_ERASE: { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access mp_spiflash_erase_block(&bdev->spiflash, arg * MP_SPIFLASH_ERASE_BLOCK_SIZE); restore_irq_pri(basepri); return 0; } } return -MP_EINVAL; } int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access mp_spiflash_cached_read(&bdev->spiflash, block_num * FLASH_BLOCK_SIZE, num_blocks * FLASH_BLOCK_SIZE, dest); restore_irq_pri(basepri); return 0; } int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access int ret = mp_spiflash_cached_write(&bdev->spiflash, block_num * FLASH_BLOCK_SIZE, num_blocks * FLASH_BLOCK_SIZE, src); if (bdev->spiflash.flags & 1) { led_state(PYB_LED_RED, 1); // indicate a dirty cache with LED on bdev->flash_tick_counter_last_write = HAL_GetTick(); } restore_irq_pri(basepri); return ret; } int spi_bdev_readblocks_raw(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access mp_spiflash_read(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, dest); restore_irq_pri(basepri); return 0; } int spi_bdev_writeblocks_raw(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access int ret = mp_spiflash_write(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, src); restore_irq_pri(basepri); return ret; } #endif micropython-1.12/ports/stm32/stm32_it.c000066400000000000000000000550721357706137100177620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Original template from ST Cube library. See below for header. * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /** ****************************************************************************** * @file Templates/Src/stm32f4xx_it.c * @author MCD Application Team * @version V1.0.1 * @date 26-February-2014 * @brief Main Interrupt Service Routines. * This file provides template for all exceptions handler and * peripherals interrupt service routine. ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2014 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ #include #include "py/obj.h" #include "py/mphal.h" #include "stm32_it.h" #include "pendsv.h" #include "irq.h" #include "powerctrl.h" #include "pybthread.h" #include "gccollect.h" #include "extint.h" #include "timer.h" #include "uart.h" #include "storage.h" #include "dma.h" #include "i2c.h" #include "usb.h" extern void __fatal_error(const char*); #if defined(MICROPY_HW_USB_FS) extern PCD_HandleTypeDef pcd_fs_handle; #endif #if defined(MICROPY_HW_USB_HS) extern PCD_HandleTypeDef pcd_hs_handle; #endif /******************************************************************************/ /* Cortex-M4 Processor Exceptions Handlers */ /******************************************************************************/ // Set the following to 1 to get some more information on the Hard Fault // More information about decoding the fault registers can be found here: // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0646a/Cihdjcfc.html STATIC char *fmt_hex(uint32_t val, char *buf) { const char *hexDig = "0123456789abcdef"; buf[0] = hexDig[(val >> 28) & 0x0f]; buf[1] = hexDig[(val >> 24) & 0x0f]; buf[2] = hexDig[(val >> 20) & 0x0f]; buf[3] = hexDig[(val >> 16) & 0x0f]; buf[4] = hexDig[(val >> 12) & 0x0f]; buf[5] = hexDig[(val >> 8) & 0x0f]; buf[6] = hexDig[(val >> 4) & 0x0f]; buf[7] = hexDig[(val >> 0) & 0x0f]; buf[8] = '\0'; return buf; } STATIC void print_reg(const char *label, uint32_t val) { char hexStr[9]; mp_hal_stdout_tx_str(label); mp_hal_stdout_tx_str(fmt_hex(val, hexStr)); mp_hal_stdout_tx_str("\r\n"); } STATIC void print_hex_hex(const char *label, uint32_t val1, uint32_t val2) { char hex_str[9]; mp_hal_stdout_tx_str(label); mp_hal_stdout_tx_str(fmt_hex(val1, hex_str)); mp_hal_stdout_tx_str(" "); mp_hal_stdout_tx_str(fmt_hex(val2, hex_str)); mp_hal_stdout_tx_str("\r\n"); } // The ARMv7M Architecture manual (section B.1.5.6) says that upon entry // to an exception, that the registers will be in the following order on the // // stack: R0, R1, R2, R3, R12, LR, PC, XPSR typedef struct { uint32_t r0, r1, r2, r3, r12, lr, pc, xpsr; } ExceptionRegisters_t; int pyb_hard_fault_debug = 0; void HardFault_C_Handler(ExceptionRegisters_t *regs) { if (!pyb_hard_fault_debug) { powerctrl_mcu_reset(); } #if MICROPY_HW_ENABLE_USB // We need to disable the USB so it doesn't try to write data out on // the VCP and then block indefinitely waiting for the buffer to drain. pyb_usb_flags = 0; #endif mp_hal_stdout_tx_str("HardFault\r\n"); print_reg("R0 ", regs->r0); print_reg("R1 ", regs->r1); print_reg("R2 ", regs->r2); print_reg("R3 ", regs->r3); print_reg("R12 ", regs->r12); print_reg("SP ", (uint32_t)regs); print_reg("LR ", regs->lr); print_reg("PC ", regs->pc); print_reg("XPSR ", regs->xpsr); #if __CORTEX_M >= 3 uint32_t cfsr = SCB->CFSR; print_reg("HFSR ", SCB->HFSR); print_reg("CFSR ", cfsr); if (cfsr & 0x80) { print_reg("MMFAR ", SCB->MMFAR); } if (cfsr & 0x8000) { print_reg("BFAR ", SCB->BFAR); } #endif if ((void*)&_ram_start <= (void*)regs && (void*)regs < (void*)&_ram_end) { mp_hal_stdout_tx_str("Stack:\r\n"); uint32_t *stack_top = &_estack; if ((void*)regs < (void*)&_sstack) { // stack not in static stack area so limit the amount we print stack_top = (uint32_t*)regs + 32; } for (uint32_t *sp = (uint32_t*)regs; sp < stack_top; ++sp) { print_hex_hex(" ", (uint32_t)sp, *sp); } } /* Go to infinite loop when Hard Fault exception occurs */ while (1) { __fatal_error("HardFault"); } } // Naked functions have no compiler generated gunk, so are the best thing to // use for asm functions. __attribute__((naked)) void HardFault_Handler(void) { // From the ARMv7M Architecture Reference Manual, section B.1.5.6 // on entry to the Exception, the LR register contains, amongst other // things, the value of CONTROL.SPSEL. This can be found in bit 3. // // If CONTROL.SPSEL is 0, then the exception was stacked up using the // main stack pointer (aka MSP). If CONTROL.SPSEL is 1, then the exception // was stacked up using the process stack pointer (aka PSP). #if __CORTEX_M == 0 __asm volatile( " mov r0, lr \n" " lsr r0, r0, #3 \n" // Shift Bit 3 into carry to see which stack pointer we should use. " mrs r0, msp \n" // Make R0 point to main stack pointer " bcc .use_msp \n" // Keep MSP in R0 if SPSEL (carry) is 0 " mrs r0, psp \n" // Make R0 point to process stack pointer " .use_msp: \n" " b HardFault_C_Handler \n" // Off to C land ); #else __asm volatile( " tst lr, #4 \n" // Test Bit 3 to see which stack pointer we should use. " ite eq \n" // Tell the assembler that the nest 2 instructions are if-then-else " mrseq r0, msp \n" // Make R0 point to main stack pointer " mrsne r0, psp \n" // Make R0 point to process stack pointer " b HardFault_C_Handler \n" // Off to C land ); #endif } /** * @brief This function handles NMI exception. * @param None * @retval None */ void NMI_Handler(void) { } /** * @brief This function handles Memory Manage exception. * @param None * @retval None */ void MemManage_Handler(void) { /* Go to infinite loop when Memory Manage exception occurs */ while (1) { __fatal_error("MemManage"); } } /** * @brief This function handles Bus Fault exception. * @param None * @retval None */ void BusFault_Handler(void) { /* Go to infinite loop when Bus Fault exception occurs */ while (1) { __fatal_error("BusFault"); } } /** * @brief This function handles Usage Fault exception. * @param None * @retval None */ void UsageFault_Handler(void) { /* Go to infinite loop when Usage Fault exception occurs */ while (1) { __fatal_error("UsageFault"); } } /** * @brief This function handles SVCall exception. * @param None * @retval None */ void SVC_Handler(void) { } /** * @brief This function handles Debug Monitor exception. * @param None * @retval None */ void DebugMon_Handler(void) { } /******************************************************************************/ /* STM32F4xx Peripherals Interrupt Handlers */ /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ /* available peripheral interrupt handler's name please refer to the startup */ /* file (startup_stm32f4xx.s). */ /******************************************************************************/ #if defined(STM32L0) || defined(STM32L432xx) #if MICROPY_HW_USB_FS void USB_IRQHandler(void) { HAL_PCD_IRQHandler(&pcd_fs_handle); } #endif #elif defined(STM32WB) #if MICROPY_HW_USB_FS void USB_LP_IRQHandler(void) { HAL_PCD_IRQHandler(&pcd_fs_handle); } #endif #else /** * @brief This function handles USB-On-The-Go FS global interrupt request. * @param None * @retval None */ #if MICROPY_HW_USB_FS void OTG_FS_IRQHandler(void) { IRQ_ENTER(OTG_FS_IRQn); HAL_PCD_IRQHandler(&pcd_fs_handle); IRQ_EXIT(OTG_FS_IRQn); } #endif #if MICROPY_HW_USB_HS void OTG_HS_IRQHandler(void) { IRQ_ENTER(OTG_HS_IRQn); HAL_PCD_IRQHandler(&pcd_hs_handle); IRQ_EXIT(OTG_HS_IRQn); } #endif #if MICROPY_HW_USB_FS || MICROPY_HW_USB_HS /** * @brief This function handles USB OTG Common FS/HS Wakeup functions. * @param *pcd_handle for FS or HS * @retval None */ STATIC void OTG_CMD_WKUP_Handler(PCD_HandleTypeDef *pcd_handle) { if (pcd_handle->Init.low_power_enable) { /* Reset SLEEPDEEP bit of Cortex System Control Register */ SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); /* Configures system clock after wake-up from STOP: enable HSE/HSI, PLL and select PLL as system clock source (HSE/HSI and PLL are disabled in STOP mode) */ __HAL_RCC_HSE_CONFIG(MICROPY_HW_RCC_HSE_STATE); #if MICROPY_HW_CLK_USE_HSI __HAL_RCC_HSI_ENABLE(); #endif /* Wait till HSE/HSI is ready */ while(__HAL_RCC_GET_FLAG(MICROPY_HW_RCC_FLAG_HSxRDY) == RESET) {} /* Enable the main PLL. */ __HAL_RCC_PLL_ENABLE(); /* Wait till PLL is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) {} /* Select PLL as SYSCLK */ MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK); #if defined(STM32H7) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) {} #else while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) {} #endif /* ungate PHY clock */ __HAL_PCD_UNGATE_PHYCLOCK(pcd_handle); } } #endif #if MICROPY_HW_USB_FS /** * @brief This function handles USB OTG FS Wakeup IRQ Handler. * @param None * @retval None */ void OTG_FS_WKUP_IRQHandler(void) { IRQ_ENTER(OTG_FS_WKUP_IRQn); OTG_CMD_WKUP_Handler(&pcd_fs_handle); #if !defined(STM32H7) /* Clear EXTI pending Bit*/ __HAL_USB_FS_EXTI_CLEAR_FLAG(); #endif IRQ_EXIT(OTG_FS_WKUP_IRQn); } #endif #if MICROPY_HW_USB_HS /** * @brief This function handles USB OTG HS Wakeup IRQ Handler. * @param None * @retval None */ void OTG_HS_WKUP_IRQHandler(void) { IRQ_ENTER(OTG_HS_WKUP_IRQn); OTG_CMD_WKUP_Handler(&pcd_hs_handle); /* Clear EXTI pending Bit*/ __HAL_USB_HS_EXTI_CLEAR_FLAG(); IRQ_EXIT(OTG_HS_WKUP_IRQn); } #endif #endif // !defined(STM32L0) /** * @brief This function handles PPP interrupt request. * @param None * @retval None */ /*void PPP_IRQHandler(void) { }*/ /** * @brief These functions handle the EXTI interrupt requests. * @param None * @retval None */ void EXTI0_IRQHandler(void) { IRQ_ENTER(EXTI0_IRQn); Handle_EXTI_Irq(0); IRQ_EXIT(EXTI0_IRQn); } void EXTI1_IRQHandler(void) { IRQ_ENTER(EXTI1_IRQn); Handle_EXTI_Irq(1); IRQ_EXIT(EXTI1_IRQn); } void EXTI2_IRQHandler(void) { IRQ_ENTER(EXTI2_IRQn); Handle_EXTI_Irq(2); IRQ_EXIT(EXTI2_IRQn); } void EXTI3_IRQHandler(void) { IRQ_ENTER(EXTI3_IRQn); Handle_EXTI_Irq(3); IRQ_EXIT(EXTI3_IRQn); } void EXTI4_IRQHandler(void) { IRQ_ENTER(EXTI4_IRQn); Handle_EXTI_Irq(4); IRQ_EXIT(EXTI4_IRQn); } void EXTI9_5_IRQHandler(void) { IRQ_ENTER(EXTI9_5_IRQn); Handle_EXTI_Irq(5); Handle_EXTI_Irq(6); Handle_EXTI_Irq(7); Handle_EXTI_Irq(8); Handle_EXTI_Irq(9); IRQ_EXIT(EXTI9_5_IRQn); } void EXTI15_10_IRQHandler(void) { IRQ_ENTER(EXTI15_10_IRQn); Handle_EXTI_Irq(10); Handle_EXTI_Irq(11); Handle_EXTI_Irq(12); Handle_EXTI_Irq(13); Handle_EXTI_Irq(14); Handle_EXTI_Irq(15); IRQ_EXIT(EXTI15_10_IRQn); } void PVD_IRQHandler(void) { IRQ_ENTER(PVD_IRQn); Handle_EXTI_Irq(EXTI_PVD_OUTPUT); IRQ_EXIT(PVD_IRQn); } #if defined(STM32L4) void PVD_PVM_IRQHandler(void) { IRQ_ENTER(PVD_PVM_IRQn); Handle_EXTI_Irq(EXTI_PVD_OUTPUT); IRQ_EXIT(PVD_PVM_IRQn); } #endif void RTC_Alarm_IRQHandler(void) { IRQ_ENTER(RTC_Alarm_IRQn); Handle_EXTI_Irq(EXTI_RTC_ALARM); IRQ_EXIT(RTC_Alarm_IRQn); } #if defined(ETH) // The 407 has ETH, the 405 doesn't void ETH_WKUP_IRQHandler(void) { IRQ_ENTER(ETH_WKUP_IRQn); Handle_EXTI_Irq(EXTI_ETH_WAKEUP); IRQ_EXIT(ETH_WKUP_IRQn); } #endif void TAMP_STAMP_IRQHandler(void) { IRQ_ENTER(TAMP_STAMP_IRQn); Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); IRQ_EXIT(TAMP_STAMP_IRQn); } void RTC_WKUP_IRQHandler(void) { IRQ_ENTER(RTC_WKUP_IRQn); RTC->ISR &= ~RTC_ISR_WUTF; // clear wakeup interrupt flag Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback IRQ_EXIT(RTC_WKUP_IRQn); } #if defined(STM32F0) || defined(STM32L0) void RTC_IRQHandler(void) { IRQ_ENTER(RTC_IRQn); if (RTC->ISR & RTC_ISR_WUTF) { RTC->ISR &= ~RTC_ISR_WUTF; // clear wakeup interrupt flag Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback } if (RTC->ISR & RTC_ISR_ALRAF) { RTC->ISR &= ~RTC_ISR_ALRAF; // clear Alarm A flag Handle_EXTI_Irq(EXTI_RTC_ALARM); // clear EXTI flag and execute optional callback } if (RTC->ISR & RTC_ISR_TSF) { RTC->ISR &= ~RTC_ISR_TSF; // clear timestamp flag Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); // clear EXTI flag and execute optional callback } IRQ_EXIT(RTC_IRQn); } void EXTI0_1_IRQHandler(void) { IRQ_ENTER(EXTI0_1_IRQn); Handle_EXTI_Irq(0); Handle_EXTI_Irq(1); IRQ_EXIT(EXTI0_1_IRQn); } void EXTI2_3_IRQHandler(void) { IRQ_ENTER(EXTI2_3_IRQn); Handle_EXTI_Irq(2); Handle_EXTI_Irq(3); IRQ_EXIT(EXTI2_3_IRQn); } void EXTI4_15_IRQHandler(void) { IRQ_ENTER(EXTI4_15_IRQn); for (int i = 4; i <= 15; ++i) { Handle_EXTI_Irq(i); } IRQ_EXIT(EXTI4_15_IRQn); } void TIM1_BRK_UP_TRG_COM_IRQHandler(void) { IRQ_ENTER(TIM1_BRK_UP_TRG_COM_IRQn); timer_irq_handler(1); IRQ_EXIT(TIM1_BRK_UP_TRG_COM_IRQn); } #endif void TIM1_BRK_TIM9_IRQHandler(void) { IRQ_ENTER(TIM1_BRK_TIM9_IRQn); timer_irq_handler(9); IRQ_EXIT(TIM1_BRK_TIM9_IRQn); } #if defined(STM32L4) void TIM1_BRK_TIM15_IRQHandler(void) { IRQ_ENTER(TIM1_BRK_TIM15_IRQn); timer_irq_handler(15); IRQ_EXIT(TIM1_BRK_TIM15_IRQn); } #endif void TIM1_UP_TIM10_IRQHandler(void) { IRQ_ENTER(TIM1_UP_TIM10_IRQn); timer_irq_handler(1); timer_irq_handler(10); IRQ_EXIT(TIM1_UP_TIM10_IRQn); } #if defined(STM32L4) void TIM1_UP_TIM16_IRQHandler(void) { IRQ_ENTER(TIM1_UP_TIM16_IRQn); timer_irq_handler(1); timer_irq_handler(16); IRQ_EXIT(TIM1_UP_TIM16_IRQn); } #endif #if defined(STM32H7) void TIM1_UP_IRQHandler(void) { IRQ_ENTER(TIM1_UP_IRQn); timer_irq_handler(1); IRQ_EXIT(TIM1_UP_IRQn); } #endif void TIM1_TRG_COM_TIM11_IRQHandler(void) { IRQ_ENTER(TIM1_TRG_COM_TIM11_IRQn); timer_irq_handler(11); IRQ_EXIT(TIM1_TRG_COM_TIM11_IRQn); } #if defined(STM32L4) void TIM1_TRG_COM_TIM17_IRQHandler(void) { IRQ_ENTER(TIM1_TRG_COM_TIM17_IRQn); timer_irq_handler(17); IRQ_EXIT(TIM1_TRG_COM_TIM17_IRQn); } #endif void TIM1_CC_IRQHandler(void) { IRQ_ENTER(TIM1_CC_IRQn); timer_irq_handler(1); IRQ_EXIT(TIM1_CC_IRQn); } void TIM2_IRQHandler(void) { IRQ_ENTER(TIM2_IRQn); timer_irq_handler(2); IRQ_EXIT(TIM2_IRQn); } void TIM3_IRQHandler(void) { IRQ_ENTER(TIM3_IRQn); timer_irq_handler(3); IRQ_EXIT(TIM3_IRQn); } void TIM4_IRQHandler(void) { IRQ_ENTER(TIM4_IRQn); timer_irq_handler(4); IRQ_EXIT(TIM4_IRQn); } void TIM5_IRQHandler(void) { IRQ_ENTER(TIM5_IRQn); timer_irq_handler(5); HAL_TIM_IRQHandler(&TIM5_Handle); IRQ_EXIT(TIM5_IRQn); } #if defined(TIM6) // STM32F401 doesn't have TIM6 void TIM6_DAC_IRQHandler(void) { IRQ_ENTER(TIM6_DAC_IRQn); timer_irq_handler(6); IRQ_EXIT(TIM6_DAC_IRQn); } #endif #if defined(TIM7) // STM32F401 doesn't have TIM7 void TIM7_IRQHandler(void) { IRQ_ENTER(TIM7_IRQn); timer_irq_handler(7); IRQ_EXIT(TIM7_IRQn); } #endif #if defined(TIM8) // STM32F401 doesn't have TIM8 void TIM8_BRK_TIM12_IRQHandler(void) { IRQ_ENTER(TIM8_BRK_TIM12_IRQn); timer_irq_handler(12); IRQ_EXIT(TIM8_BRK_TIM12_IRQn); } void TIM8_UP_TIM13_IRQHandler(void) { IRQ_ENTER(TIM8_UP_TIM13_IRQn); timer_irq_handler(8); timer_irq_handler(13); IRQ_EXIT(TIM8_UP_TIM13_IRQn); } #if defined(STM32L4) void TIM8_UP_IRQHandler(void) { IRQ_ENTER(TIM8_UP_IRQn); timer_irq_handler(8); IRQ_EXIT(TIM8_UP_IRQn); } #endif void TIM8_CC_IRQHandler(void) { IRQ_ENTER(TIM8_CC_IRQn); timer_irq_handler(8); IRQ_EXIT(TIM8_CC_IRQn); } void TIM8_TRG_COM_TIM14_IRQHandler(void) { IRQ_ENTER(TIM8_TRG_COM_TIM14_IRQn); timer_irq_handler(14); IRQ_EXIT(TIM8_TRG_COM_TIM14_IRQn); } #endif #if defined(STM32H7) void TIM15_IRQHandler(void) { IRQ_ENTER(TIM15_IRQn); timer_irq_handler(15); IRQ_EXIT(TIM15_IRQn); } void TIM16_IRQHandler(void) { IRQ_ENTER(TIM16_IRQn); timer_irq_handler(16); IRQ_EXIT(TIM16_IRQn); } void TIM17_IRQHandler(void) { IRQ_ENTER(TIM17_IRQn); timer_irq_handler(17); IRQ_EXIT(TIM17_IRQn); } #endif // UART/USART IRQ handlers void USART1_IRQHandler(void) { IRQ_ENTER(USART1_IRQn); uart_irq_handler(1); IRQ_EXIT(USART1_IRQn); } void USART2_IRQHandler(void) { IRQ_ENTER(USART2_IRQn); uart_irq_handler(2); IRQ_EXIT(USART2_IRQn); } #if defined(STM32F0) void USART3_8_IRQHandler(void) { IRQ_ENTER(USART3_8_IRQn); uart_irq_handler(3); uart_irq_handler(4); uart_irq_handler(5); uart_irq_handler(6); uart_irq_handler(7); uart_irq_handler(8); IRQ_EXIT(USART3_8_IRQn); } #elif defined(STM32L0) void USART4_5_IRQHandler(void) { IRQ_ENTER(USART4_5_IRQn); uart_irq_handler(4); uart_irq_handler(5); IRQ_EXIT(USART4_5_IRQn); } #else void USART3_IRQHandler(void) { IRQ_ENTER(USART3_IRQn); uart_irq_handler(3); IRQ_EXIT(USART3_IRQn); } void UART4_IRQHandler(void) { IRQ_ENTER(UART4_IRQn); uart_irq_handler(4); IRQ_EXIT(UART4_IRQn); } void UART5_IRQHandler(void) { IRQ_ENTER(UART5_IRQn); uart_irq_handler(5); IRQ_EXIT(UART5_IRQn); } void USART6_IRQHandler(void) { IRQ_ENTER(USART6_IRQn); uart_irq_handler(6); IRQ_EXIT(USART6_IRQn); } #if defined(UART7) void UART7_IRQHandler(void) { IRQ_ENTER(UART7_IRQn); uart_irq_handler(7); IRQ_EXIT(UART7_IRQn); } #endif #if defined(UART8) void UART8_IRQHandler(void) { IRQ_ENTER(UART8_IRQn); uart_irq_handler(8); IRQ_EXIT(UART8_IRQn); } #endif #if defined(UART9) void UART9_IRQHandler(void) { IRQ_ENTER(UART9_IRQn); uart_irq_handler(9); IRQ_EXIT(UART9_IRQn); } #endif #if defined(UART10) void UART10_IRQHandler(void) { IRQ_ENTER(UART10_IRQn); uart_irq_handler(10); IRQ_EXIT(UART10_IRQn); } #endif #endif #if MICROPY_PY_PYB_LEGACY #if defined(MICROPY_HW_I2C1_SCL) void I2C1_EV_IRQHandler(void) { IRQ_ENTER(I2C1_EV_IRQn); i2c_ev_irq_handler(1); IRQ_EXIT(I2C1_EV_IRQn); } void I2C1_ER_IRQHandler(void) { IRQ_ENTER(I2C1_ER_IRQn); i2c_er_irq_handler(1); IRQ_EXIT(I2C1_ER_IRQn); } #endif // defined(MICROPY_HW_I2C1_SCL) #if defined(MICROPY_HW_I2C2_SCL) void I2C2_EV_IRQHandler(void) { IRQ_ENTER(I2C2_EV_IRQn); i2c_ev_irq_handler(2); IRQ_EXIT(I2C2_EV_IRQn); } void I2C2_ER_IRQHandler(void) { IRQ_ENTER(I2C2_ER_IRQn); i2c_er_irq_handler(2); IRQ_EXIT(I2C2_ER_IRQn); } #endif // defined(MICROPY_HW_I2C2_SCL) #if defined(MICROPY_HW_I2C3_SCL) void I2C3_EV_IRQHandler(void) { IRQ_ENTER(I2C3_EV_IRQn); i2c_ev_irq_handler(3); IRQ_EXIT(I2C3_EV_IRQn); } void I2C3_ER_IRQHandler(void) { IRQ_ENTER(I2C3_ER_IRQn); i2c_er_irq_handler(3); IRQ_EXIT(I2C3_ER_IRQn); } #endif // defined(MICROPY_HW_I2C3_SCL) #if defined(MICROPY_HW_I2C4_SCL) void I2C4_EV_IRQHandler(void) { IRQ_ENTER(I2C4_EV_IRQn); i2c_ev_irq_handler(4); IRQ_EXIT(I2C4_EV_IRQn); } void I2C4_ER_IRQHandler(void) { IRQ_ENTER(I2C4_ER_IRQn); i2c_er_irq_handler(4); IRQ_EXIT(I2C4_ER_IRQn); } #endif // defined(MICROPY_HW_I2C4_SCL) #endif // MICROPY_PY_PYB_LEGACY micropython-1.12/ports/stm32/stm32_it.h000066400000000000000000000074301357706137100177620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Original template from ST Cube library. See below for header. * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_STM32_IT_H #define MICROPY_INCLUDED_STM32_STM32_IT_H /** ****************************************************************************** * @file Templates/Inc/stm32f4xx_it.h * @author MCD Application Team * @version V1.0.1 * @date 26-February-2014 * @brief This file contains the headers of the interrupt handlers. ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2014 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ extern int pyb_hard_fault_debug; void NMI_Handler(void); void HardFault_Handler(void); void MemManage_Handler(void); void BusFault_Handler(void); void UsageFault_Handler(void); void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void OTG_FS_IRQHandler(void); void OTG_HS_IRQHandler(void); #endif // MICROPY_INCLUDED_STM32_STM32_IT_H micropython-1.12/ports/stm32/storage.c000066400000000000000000000416551357706137100177640ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/vfs_fat.h" #include "systick.h" #include "led.h" #include "storage.h" #include "irq.h" #if MICROPY_HW_ENABLE_STORAGE #define STORAGE_SYSTICK_MASK (0x1ff) // 512ms #define STORAGE_IDLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & STORAGE_SYSTICK_MASK) == 0) #if defined(MICROPY_HW_BDEV2_IOCTL) #define FLASH_PART2_START_BLOCK (FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) #endif static bool storage_is_initialised = false; static void storage_systick_callback(uint32_t ticks_ms); void storage_init(void) { if (!storage_is_initialised) { storage_is_initialised = true; systick_enable_dispatch(SYSTICK_DISPATCH_STORAGE, storage_systick_callback); MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_INIT, 0); #if defined(MICROPY_HW_BDEV2_IOCTL) MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_INIT, 0); #endif // Enable the flash IRQ, which is used to also call our storage IRQ handler // It must go at the same priority as USB (see comment in irq.h). NVIC_SetPriority(FLASH_IRQn, IRQ_PRI_FLASH); HAL_NVIC_EnableIRQ(FLASH_IRQn); } } uint32_t storage_get_block_size(void) { return FLASH_BLOCK_SIZE; } uint32_t storage_get_block_count(void) { #if defined(MICROPY_HW_BDEV2_IOCTL) return FLASH_PART2_START_BLOCK + MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0); #else return FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0); #endif } static void storage_systick_callback(uint32_t ticks_ms) { if (STORAGE_IDLE_TICK(ticks_ms)) { // Trigger a FLASH IRQ to execute at a lower priority NVIC->STIR = FLASH_IRQn; } } void FLASH_IRQHandler(void) { IRQ_ENTER(FLASH_IRQn); MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_IRQ_HANDLER, 0); #if defined(MICROPY_HW_BDEV2_IOCTL) MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_IRQ_HANDLER, 0); #endif IRQ_EXIT(FLASH_IRQn); } void storage_flush(void) { MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_SYNC, 0); #if defined(MICROPY_HW_BDEV2_IOCTL) MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_SYNC, 0); #endif } static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) { buf[0] = boot; if (num_blocks == 0) { buf[1] = 0; buf[2] = 0; buf[3] = 0; } else { buf[1] = 0xff; buf[2] = 0xff; buf[3] = 0xff; } buf[4] = type; if (num_blocks == 0) { buf[5] = 0; buf[6] = 0; buf[7] = 0; } else { buf[5] = 0xff; buf[6] = 0xff; buf[7] = 0xff; } buf[8] = start_block; buf[9] = start_block >> 8; buf[10] = start_block >> 16; buf[11] = start_block >> 24; buf[12] = num_blocks; buf[13] = num_blocks >> 8; buf[14] = num_blocks >> 16; buf[15] = num_blocks >> 24; } bool storage_read_block(uint8_t *dest, uint32_t block) { //printf("RD %u\n", block); if (block == 0) { // fake the MBR so we can decide on our own partition table for (int i = 0; i < 446; i++) { dest[i] = 0; } build_partition(dest + 446, 0, 0x01 /* FAT12 */, FLASH_PART1_START_BLOCK, MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)); #if defined(MICROPY_HW_BDEV2_IOCTL) build_partition(dest + 462, 0, 0x01 /* FAT12 */, FLASH_PART2_START_BLOCK, MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)); #else build_partition(dest + 462, 0, 0, 0, 0); #endif build_partition(dest + 478, 0, 0, 0, 0); build_partition(dest + 494, 0, 0, 0, 0); dest[510] = 0x55; dest[511] = 0xaa; return true; #if defined(MICROPY_HW_BDEV_READBLOCK) } else if (FLASH_PART1_START_BLOCK <= block && block < FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) { return MICROPY_HW_BDEV_READBLOCK(dest, block - FLASH_PART1_START_BLOCK); #endif } else { return false; } } bool storage_write_block(const uint8_t *src, uint32_t block) { //printf("WR %u\n", block); if (block == 0) { // can't write MBR, but pretend we did return true; #if defined(MICROPY_HW_BDEV_WRITEBLOCK) } else if (FLASH_PART1_START_BLOCK <= block && block < FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) { return MICROPY_HW_BDEV_WRITEBLOCK(src, block - FLASH_PART1_START_BLOCK); #endif } else { return false; } } int storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { #if defined(MICROPY_HW_BDEV_READBLOCKS) if (FLASH_PART1_START_BLOCK <= block_num && block_num + num_blocks <= FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) { return MICROPY_HW_BDEV_READBLOCKS(dest, block_num - FLASH_PART1_START_BLOCK, num_blocks); } #endif #if defined(MICROPY_HW_BDEV2_READBLOCKS) if (FLASH_PART2_START_BLOCK <= block_num && block_num + num_blocks <= FLASH_PART2_START_BLOCK + MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) { return MICROPY_HW_BDEV2_READBLOCKS(dest, block_num - FLASH_PART2_START_BLOCK, num_blocks); } #endif for (size_t i = 0; i < num_blocks; i++) { if (!storage_read_block(dest + i * FLASH_BLOCK_SIZE, block_num + i)) { return -MP_EIO; // error } } return 0; // success } int storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { #if defined(MICROPY_HW_BDEV_WRITEBLOCKS) if (FLASH_PART1_START_BLOCK <= block_num && block_num + num_blocks <= FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) { return MICROPY_HW_BDEV_WRITEBLOCKS(src, block_num - FLASH_PART1_START_BLOCK, num_blocks); } #endif #if defined(MICROPY_HW_BDEV2_WRITEBLOCKS) if (FLASH_PART2_START_BLOCK <= block_num && block_num + num_blocks <= FLASH_PART2_START_BLOCK + MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) { return MICROPY_HW_BDEV2_WRITEBLOCKS(src, block_num - FLASH_PART2_START_BLOCK, num_blocks); } #endif for (size_t i = 0; i < num_blocks; i++) { if (!storage_write_block(src + i * FLASH_BLOCK_SIZE, block_num + i)) { return -MP_EIO; // error } } return 0; // success } /******************************************************************************/ // MicroPython bindings // // Expose the flash as an object with the block protocol. #ifdef MICROPY_HW_BDEV_SPIFLASH_EXTENDED // Board defined an external SPI flash for use with extended block protocol #define SPIFLASH (MICROPY_HW_BDEV_SPIFLASH_EXTENDED) #define PYB_FLASH_NATIVE_BLOCK_SIZE (MP_SPIFLASH_ERASE_BLOCK_SIZE) #define MICROPY_HW_BDEV_READBLOCKS_EXT(dest, bl, off, len) (spi_bdev_readblocks_raw(SPIFLASH, (dest), (bl), (off), (len))) #define MICROPY_HW_BDEV_WRITEBLOCKS_EXT(dest, bl, off, len) (spi_bdev_writeblocks_raw(SPIFLASH, (dest), (bl), (off), (len))) #elif (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) && MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE // Board uses littlefs and internal flash, so enable extended block protocol on internal flash #define PYB_FLASH_NATIVE_BLOCK_SIZE (FLASH_BLOCK_SIZE) #define MICROPY_HW_BDEV_READBLOCKS_EXT(dest, bl, off, len) (flash_bdev_readblocks_ext((dest), (bl), (off), (len))) #define MICROPY_HW_BDEV_WRITEBLOCKS_EXT(dest, bl, off, len) (flash_bdev_writeblocks_ext((dest), (bl), (off), (len))) #endif #ifndef PYB_FLASH_NATIVE_BLOCK_SIZE #define PYB_FLASH_NATIVE_BLOCK_SIZE (FLASH_BLOCK_SIZE) #endif typedef struct _pyb_flash_obj_t { mp_obj_base_t base; uint32_t start; // in bytes uint32_t len; // in bytes #if defined(SPIFLASH) bool use_native_block_size; #endif } pyb_flash_obj_t; // This Flash object represents the entire available flash, with emulated partition table at start const pyb_flash_obj_t pyb_flash_obj = { { &pyb_flash_type }, -(FLASH_PART1_START_BLOCK * FLASH_BLOCK_SIZE), // to offset FLASH_PART1_START_BLOCK 0, // actual size handled in ioctl, MP_BLOCKDEV_IOCTL_BLOCK_COUNT case }; STATIC void pyb_flash_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self == &pyb_flash_obj) { mp_printf(print, "Flash()"); } else { mp_printf(print, "Flash(start=%u, len=%u)", self->start, self->len); } } STATIC mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // Parse arguments enum { ARG_start, ARG_len }; static const mp_arg_t allowed_args[] = { { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_start].u_int == -1 && args[ARG_len].u_int == -1) { // Default singleton object that accesses entire flash, including virtual partition table return MP_OBJ_FROM_PTR(&pyb_flash_obj); } pyb_flash_obj_t *self = m_new_obj(pyb_flash_obj_t); self->base.type = &pyb_flash_type; #if defined(SPIFLASH) self->use_native_block_size = false; #endif uint32_t bl_len = (storage_get_block_count() - FLASH_PART1_START_BLOCK) * FLASH_BLOCK_SIZE; mp_int_t start = args[ARG_start].u_int; if (start == -1) { start = 0; } else if (!(0 <= start && start < bl_len && start % PYB_FLASH_NATIVE_BLOCK_SIZE == 0)) { mp_raise_ValueError(NULL); } mp_int_t len = args[ARG_len].u_int; if (len == -1) { len = bl_len - start; } else if (!(0 < len && start + len <= bl_len && len % PYB_FLASH_NATIVE_BLOCK_SIZE == 0)) { mp_raise_ValueError(NULL); } self->start = start; self->len = len; return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t pyb_flash_readblocks(size_t n_args, const mp_obj_t *args) { pyb_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t block_num = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); mp_uint_t ret = -MP_EIO; if (n_args == 3) { // Cast self->start to signed in case it's pyb_flash_obj with negative start block_num += FLASH_PART1_START_BLOCK + (int32_t)self->start / FLASH_BLOCK_SIZE; ret = storage_read_blocks(bufinfo.buf, block_num, bufinfo.len / FLASH_BLOCK_SIZE); } #if defined(MICROPY_HW_BDEV_READBLOCKS_EXT) else if (self != &pyb_flash_obj) { // Extended block read on a sub-section of the flash storage uint32_t offset = mp_obj_get_int(args[3]); block_num += self->start / PYB_FLASH_NATIVE_BLOCK_SIZE; ret = MICROPY_HW_BDEV_READBLOCKS_EXT(bufinfo.buf, block_num, offset, bufinfo.len); } #endif return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_flash_readblocks_obj, 3, 4, pyb_flash_readblocks); STATIC mp_obj_t pyb_flash_writeblocks(size_t n_args, const mp_obj_t *args) { pyb_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t block_num = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); mp_uint_t ret = -MP_EIO; if (n_args == 3) { // Cast self->start to signed in case it's pyb_flash_obj with negative start block_num += FLASH_PART1_START_BLOCK + (int32_t)self->start / FLASH_BLOCK_SIZE; ret = storage_write_blocks(bufinfo.buf, block_num, bufinfo.len / FLASH_BLOCK_SIZE); } #if defined(MICROPY_HW_BDEV_WRITEBLOCKS_EXT) else if (self != &pyb_flash_obj) { // Extended block write on a sub-section of the flash storage uint32_t offset = mp_obj_get_int(args[3]); block_num += self->start / PYB_FLASH_NATIVE_BLOCK_SIZE; ret = MICROPY_HW_BDEV_WRITEBLOCKS_EXT(bufinfo.buf, block_num, offset, bufinfo.len); } #endif return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_flash_writeblocks_obj, 3, 4, pyb_flash_writeblocks); STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { pyb_flash_obj_t *self = self_in; mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: { mp_int_t ret = 0; storage_init(); if (mp_obj_get_int(arg_in) == 1) { // Will be using extended block protocol if (self == &pyb_flash_obj) { ret = -1; #if defined(SPIFLASH) } else { // Switch to use native block size of SPI flash self->use_native_block_size = true; #endif } } return MP_OBJ_NEW_SMALL_INT(ret); } case MP_BLOCKDEV_IOCTL_DEINIT: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly case MP_BLOCKDEV_IOCTL_SYNC: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: { mp_int_t n; if (self == &pyb_flash_obj) { // Get true size n = storage_get_block_count(); #if defined(SPIFLASH) } else if (self->use_native_block_size) { n = self->len / PYB_FLASH_NATIVE_BLOCK_SIZE; #endif } else { n = self->len / FLASH_BLOCK_SIZE; } return MP_OBJ_NEW_SMALL_INT(n); } case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: { mp_int_t n = FLASH_BLOCK_SIZE; #if defined(SPIFLASH) if (self->use_native_block_size) { n = PYB_FLASH_NATIVE_BLOCK_SIZE; } #endif return MP_OBJ_NEW_SMALL_INT(n); } case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: { int ret = 0; #if defined(SPIFLASH) if (self->use_native_block_size) { mp_int_t block_num = self->start / PYB_FLASH_NATIVE_BLOCK_SIZE + mp_obj_get_int(arg_in); ret = spi_bdev_ioctl(SPIFLASH, BDEV_IOCTL_BLOCK_ERASE, block_num); } #endif return MP_OBJ_NEW_SMALL_INT(ret); } default: return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_ioctl_obj, pyb_flash_ioctl); STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&pyb_flash_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&pyb_flash_writeblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&pyb_flash_ioctl_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table); const mp_obj_type_t pyb_flash_type = { { &mp_type_type }, .name = MP_QSTR_Flash, .print = pyb_flash_print, .make_new = pyb_flash_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_flash_locals_dict, }; void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; vfs->fatfs.part = 1; // flash filesystem lives on first partition vfs->blockdev.readblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_readblocks_obj); vfs->blockdev.readblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); vfs->blockdev.readblocks[2] = MP_OBJ_FROM_PTR(storage_read_blocks); // native version vfs->blockdev.writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_writeblocks_obj); vfs->blockdev.writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); vfs->blockdev.writeblocks[2] = MP_OBJ_FROM_PTR(storage_write_blocks); // native version vfs->blockdev.u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_flash_ioctl_obj); vfs->blockdev.u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); } #endif micropython-1.12/ports/stm32/storage.h000066400000000000000000000065671357706137100177740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_STORAGE_H #define MICROPY_INCLUDED_STM32_STORAGE_H #include "drivers/memory/spiflash.h" #define FLASH_BLOCK_SIZE (512) #define FLASH_PART1_START_BLOCK (0x100) // Try to match Python-level VFS block protocol where possible for these constants enum { BDEV_IOCTL_INIT = 1, BDEV_IOCTL_SYNC = 3, BDEV_IOCTL_NUM_BLOCKS = 4, BDEV_IOCTL_BLOCK_ERASE = 6, BDEV_IOCTL_IRQ_HANDLER = 7, }; void storage_init(void); uint32_t storage_get_block_size(void); uint32_t storage_get_block_count(void); void storage_flush(void); bool storage_read_block(uint8_t *dest, uint32_t block); bool storage_write_block(const uint8_t *src, uint32_t block); // these return 0 on success, negative errno on error int storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); int storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); int32_t flash_bdev_ioctl(uint32_t op, uint32_t arg); bool flash_bdev_readblock(uint8_t *dest, uint32_t block); bool flash_bdev_writeblock(const uint8_t *src, uint32_t block); int flash_bdev_readblocks_ext(uint8_t *dest, uint32_t block, uint32_t offset, uint32_t len); int flash_bdev_writeblocks_ext(const uint8_t *src, uint32_t block, uint32_t offset, uint32_t len); typedef struct _spi_bdev_t { mp_spiflash_t spiflash; uint32_t flash_tick_counter_last_write; } spi_bdev_t; int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg); int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t num_blocks); int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t num_blocks); // These raw functions bypass the cache and go directly to SPI flash int spi_bdev_readblocks_raw(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes); int spi_bdev_writeblocks_raw(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes); extern const struct _mp_obj_type_t pyb_flash_type; extern const struct _pyb_flash_obj_t pyb_flash_obj; struct _fs_user_mount_t; void pyb_flash_init_vfs(struct _fs_user_mount_t *vfs); #endif // MICROPY_INCLUDED_STM32_STORAGE_H micropython-1.12/ports/stm32/system_stm32.c000066400000000000000000000422671357706137100206740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Taken from ST Cube library and modified. See below for original header. * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /** ****************************************************************************** * @file system_stm32.c * @author MCD Application Team * @version V1.0.1 * @date 26-February-2014 * @brief CMSIS Cortex-M4/M7 Device Peripheral Access Layer System Source File. * * This file provides two functions and one global variable to be called from * user application: * - SystemInit(): This function is called at startup just after reset and * before branch to main program. This call is made inside * the "startup_stm32.s" file. * * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used * by the user application to setup the SysTick * timer or configure other parameters. * * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ #include "py/mphal.h" #include "powerctrl.h" #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4) void __fatal_error(const char *msg); /** * @brief System Clock Configuration * * The system Clock is configured for F4/F7 as follows: * (HSx should be read as HSE or HSI depending on the value of MICROPY_HW_CLK_USE_HSI) * System Clock source = PLL (HSx) * SYSCLK(Hz) = 168000000 * HCLK(Hz) = 168000000 * AHB Prescaler = 1 * APB1 Prescaler = 4 * APB2 Prescaler = 2 * HSx Frequency(Hz) = HSx_VALUE * PLL_M = HSx_VALUE/1000000 * PLL_N = 336 * PLL_P = 4 * PLL_Q = 7 * VDD(V) = 3.3 * Main regulator output voltage = Scale1 mode * Flash Latency(WS) = 5 * * The system Clock is configured for L4 as follows: * System Clock source = PLL (MSI) * SYSCLK(Hz) = 80000000 * HCLK(Hz) = 80000000 * AHB Prescaler = 1 * APB1 Prescaler = 1 * APB2 Prescaler = 1 * MSI Frequency(Hz) = MSI_VALUE (4000000) * LSE Frequency(Hz) = 32768 * PLL_M = 1 * PLL_N = 40 * PLL_P = 7 * PLL_Q = 2 * PLL_R = 2 <= This is the source for SysClk, not as on F4/7 PLL_P * Flash Latency(WS) = 4 * @param None * @retval None * * PLL is configured as follows: * * VCO_IN * F4/F7 = HSx / M * L4 = MSI / M * VCO_OUT * F4/F7 = HSx / M * N * L4 = MSI / M * N * PLLCLK * F4/F7 = HSx / M * N / P * L4 = MSI / M * N / R * PLL48CK * F4/F7 = HSx / M * N / Q * L4 = MSI / M * N / Q USB Clock is obtained over PLLSAI1 * * SYSCLK = PLLCLK * HCLK = SYSCLK / AHB_PRESC * PCLKx = HCLK / APBx_PRESC * * Constraints on parameters: * * VCO_IN between 1MHz and 2MHz (2MHz recommended) * VCO_OUT between 192MHz and 432MHz * HSE = 8MHz * HSI = 16MHz * M = 2 .. 63 (inclusive) * N = 192 ... 432 (inclusive) * P = 2, 4, 6, 8 * Q = 2 .. 15 (inclusive) * * AHB_PRESC=1,2,4,8,16,64,128,256,512 * APBx_PRESC=1,2,4,8,16 * * Output clocks: * * CPU SYSCLK max 168MHz * USB,RNG,SDIO PLL48CK must be 48MHz for USB * AHB HCLK max 168MHz * APB1 PCLK1 max 42MHz * APB2 PCLK2 max 84MHz * * Timers run from APBx if APBx_PRESC=1, else 2x APBx */ void SystemClock_Config(void) { #if defined(STM32F7) // The DFU bootloader changes the clocksource register from its default power // on reset value, so we set it back here, so the clocksources are the same // whether we were started from DFU or from a power on reset. RCC->DCKCFGR2 = 0; #endif RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; #if defined(STM32H7) RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; #endif #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) /* Enable Power Control clock */ #if defined(STM32H7) MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN, 0); #else __PWR_CLK_ENABLE(); #endif /* The voltage scaling allows optimizing the power consumption when the device is clocked below the maximum system frequency, to update the voltage scaling value regarding system frequency refer to product datasheet. */ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); #elif defined(STM32L4) // Configure LSE Drive Capability __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); #endif #if defined(STM32H7) // Wait for PWR_FLAG_VOSRDY while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) { } #endif /* Enable HSE Oscillator and activate PLL with HSE as source */ #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) RCC_OscInitStruct.OscillatorType = MICROPY_HW_RCC_OSCILLATOR_TYPE; RCC_OscInitStruct.HSEState = MICROPY_HW_RCC_HSE_STATE; RCC_OscInitStruct.HSIState = MICROPY_HW_RCC_HSI_STATE; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; #if defined(STM32H7) RCC_OscInitStruct.CSIState = RCC_CSI_OFF; #endif RCC_OscInitStruct.PLL.PLLSource = MICROPY_HW_RCC_PLL_SRC; #elif defined(STM32L4) #if MICROPY_HW_CLK_USE_HSE RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = MICROPY_HW_CLK_PLLM; RCC_OscInitStruct.PLL.PLLN = MICROPY_HW_CLK_PLLN; RCC_OscInitStruct.PLL.PLLP = MICROPY_HW_CLK_PLLP; RCC_OscInitStruct.PLL.PLLQ = MICROPY_HW_CLK_PLLQ; RCC_OscInitStruct.PLL.PLLR = MICROPY_HW_CLK_PLLR; RCC_OscInitStruct.MSIState = RCC_MSI_OFF; #else RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.MSIState = RCC_MSI_ON; RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; #endif #if MICROPY_HW_RTC_USE_LSE RCC_OscInitStruct.LSEState = RCC_LSE_ON; #else RCC_OscInitStruct.LSEState = RCC_LSE_OFF; #endif #endif RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); #if defined(STM32H7) RCC_ClkInitStruct.ClockType |= (RCC_CLOCKTYPE_D3PCLK1 | RCC_CLOCKTYPE_D1PCLK1); #endif #if defined(MICROPY_HW_CLK_LAST_FREQ) && MICROPY_HW_CLK_LAST_FREQ #if defined(STM32F7) #define FREQ_BKP BKP31R #elif defined(STM32L4) #error Unsupported Processor #else #define FREQ_BKP BKP19R #endif uint32_t m = RTC->FREQ_BKP; uint32_t n; uint32_t p; uint32_t q; // 222111HH HHQQQQPP nNNNNNNN NNMMMMMM uint32_t h = (m >> 22) & 0xf; uint32_t b1 = (m >> 26) & 0x7; uint32_t b2 = (m >> 29) & 0x7; q = (m >> 18) & 0xf; p = (((m >> 16) & 0x03)+1)*2; n = (m >> 6) & 0x3ff; m &= 0x3f; if ((q < 2) || (q > 15) || (p > 8) || (p < 2) || (n < 192) || (n >= 433) || (m < 2)) { m = MICROPY_HW_CLK_PLLM; n = MICROPY_HW_CLK_PLLN; p = MICROPY_HW_CLK_PLLP; q = MICROPY_HW_CLK_PLLQ; h = RCC_SYSCLK_DIV1; b1 = RCC_HCLK_DIV4; b2 = RCC_HCLK_DIV2; } else { h <<= 4; b1 <<= 10; b2 <<= 10; } RCC_OscInitStruct.PLL.PLLM = m; //MICROPY_HW_CLK_PLLM; RCC_OscInitStruct.PLL.PLLN = n; //MICROPY_HW_CLK_PLLN; RCC_OscInitStruct.PLL.PLLP = p; //MICROPY_HW_CLK_PLLP; RCC_OscInitStruct.PLL.PLLQ = q; //MICROPY_HW_CLK_PLLQ; RCC_ClkInitStruct.AHBCLKDivider = h; //RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = b1; //RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = b2; //RCC_HCLK_DIV2; #else // defined(MICROPY_HW_CLK_LAST_FREQ) && MICROPY_HW_CLK_LAST_FREQ RCC_OscInitStruct.PLL.PLLM = MICROPY_HW_CLK_PLLM; RCC_OscInitStruct.PLL.PLLN = MICROPY_HW_CLK_PLLN; RCC_OscInitStruct.PLL.PLLP = MICROPY_HW_CLK_PLLP; RCC_OscInitStruct.PLL.PLLQ = MICROPY_HW_CLK_PLLQ; #if defined(STM32L4) || defined(STM32H7) RCC_OscInitStruct.PLL.PLLR = MICROPY_HW_CLK_PLLR; #endif #if defined(STM32H7) RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; RCC_OscInitStruct.PLL.PLLFRACN = 0; #endif #if defined(STM32F4) || defined(STM32F7) RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; #elif defined(STM32L4) RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; #elif defined(STM32H7) RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; #endif #endif if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { __fatal_error("HAL_RCC_OscConfig"); } #if defined(STM32H7) /* PLL3 for USB Clock */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3; PeriphClkInitStruct.PLL3.PLL3M = MICROPY_HW_CLK_PLL3M; PeriphClkInitStruct.PLL3.PLL3N = MICROPY_HW_CLK_PLL3N; PeriphClkInitStruct.PLL3.PLL3P = MICROPY_HW_CLK_PLL3P; PeriphClkInitStruct.PLL3.PLL3Q = MICROPY_HW_CLK_PLL3Q; PeriphClkInitStruct.PLL3.PLL3R = MICROPY_HW_CLK_PLL3R; PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_1; PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE; PeriphClkInitStruct.PLL3.PLL3FRACN = 0; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { __fatal_error("HAL_RCCEx_PeriphCLKConfig"); } #endif #if defined(STM32F7) /* Activate the OverDrive to reach the 200 MHz Frequency */ if (HAL_PWREx_EnableOverDrive() != HAL_OK) { __fatal_error("HAL_PWREx_EnableOverDrive"); } #endif uint32_t vco_out = RCC_OscInitStruct.PLL.PLLN * (MICROPY_HW_CLK_VALUE / 1000000) / RCC_OscInitStruct.PLL.PLLM; uint32_t sysclk_mhz = vco_out / RCC_OscInitStruct.PLL.PLLP; bool need_pllsai = vco_out % 48 != 0; if (powerctrl_rcc_clock_config_pll(&RCC_ClkInitStruct, sysclk_mhz, need_pllsai) != 0) { __fatal_error("HAL_RCC_ClockConfig"); } #if defined(STM32H7) /* Activate CSI clock mandatory for I/O Compensation Cell*/ __HAL_RCC_CSI_ENABLE() ; /* Enable SYSCFG clock mandatory for I/O Compensation Cell */ __HAL_RCC_SYSCFG_CLK_ENABLE() ; /* Enable the I/O Compensation Cell */ HAL_EnableCompensationCell(); /* Enable the USB voltage level detector */ HAL_PWREx_EnableUSBVoltageDetector(); #endif #if defined(STM32L4) // Enable MSI-Hardware auto calibration mode with LSE HAL_RCCEx_EnableMSIPLLMode(); RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1|RCC_PERIPHCLK_I2C1 |RCC_PERIPHCLK_USB |RCC_PERIPHCLK_ADC |RCC_PERIPHCLK_RNG |RCC_PERIPHCLK_RTC; PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1; PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1; PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1; #if MICROPY_HW_RTC_USE_LSE PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; #else PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; #endif #if MICROPY_HW_CLK_USE_HSE PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE; PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 1; //MICROPY_HW_CLK_PLLSAIM; PeriphClkInitStruct.PLLSAI1.PLLSAI1N = MICROPY_HW_CLK_PLLSAIN; PeriphClkInitStruct.PLLSAI1.PLLSAI1P = MICROPY_HW_CLK_PLLSAIP; PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = MICROPY_HW_CLK_PLLSAIQ; PeriphClkInitStruct.PLLSAI1.PLLSAI1R = MICROPY_HW_CLK_PLLSAIR; #else /* PLLSAI is used to clock USB, ADC, I2C1 and RNG. The frequency is MSI(4MHz)/PLLM(1)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz. See the STM32CubeMx application or the reference manual. */ PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_MSI; PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 1; PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24; PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7; PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2; PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2; #endif PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK |RCC_PLLSAI1_48M2CLK |RCC_PLLSAI1_ADC1CLK; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { __fatal_error("HAL_RCCEx_PeriphCLKConfig"); } __PWR_CLK_ENABLE(); HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, TICK_INT_PRIORITY, 0)); #endif } #endif micropython-1.12/ports/stm32/systick.c000066400000000000000000000155661357706137100200130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/mphal.h" #include "irq.h" #include "pendsv.h" #include "systick.h" #include "softtimer.h" #include "pybthread.h" extern __IO uint32_t uwTick; systick_dispatch_t systick_dispatch_table[SYSTICK_DISPATCH_NUM_SLOTS]; void SysTick_Handler(void) { // Instead of calling HAL_IncTick we do the increment here of the counter. // This is purely for efficiency, since SysTick is called 1000 times per // second at the highest interrupt priority. uint32_t uw_tick = uwTick + 1; uwTick = uw_tick; // Read the systick control regster. This has the side effect of clearing // the COUNTFLAG bit, which makes the logic in mp_hal_ticks_us // work properly. SysTick->CTRL; // Dispatch to any registered handlers in a cycle systick_dispatch_t f = systick_dispatch_table[uw_tick & (SYSTICK_DISPATCH_NUM_SLOTS - 1)]; if (f != NULL) { f(uw_tick); } if (soft_timer_next == uw_tick) { pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); } #if MICROPY_PY_THREAD if (pyb_thread_enabled) { if (pyb_thread_cur->timeslice == 0) { if (pyb_thread_cur->run_next != pyb_thread_cur) { SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; } } else { --pyb_thread_cur->timeslice; } } #endif } // We provide our own version of HAL_Delay that calls __WFI while waiting, // and works when interrupts are disabled. This function is intended to be // used only by the ST HAL functions. void HAL_Delay(uint32_t Delay) { if (query_irq() == IRQ_STATE_ENABLED) { // IRQs enabled, so can use systick counter to do the delay uint32_t start = uwTick; // Wraparound of tick is taken care of by 2's complement arithmetic. while (uwTick - start < Delay) { // Enter sleep mode, waiting for (at least) the SysTick interrupt. __WFI(); } } else { // IRQs disabled, use mp_hal_delay_ms routine. mp_hal_delay_ms(Delay); } } // Core delay function that does an efficient sleep and may switch thread context. // If IRQs are enabled then we must have the GIL. void mp_hal_delay_ms(mp_uint_t Delay) { if (query_irq() == IRQ_STATE_ENABLED) { // IRQs enabled, so can use systick counter to do the delay uint32_t start = uwTick; // Wraparound of tick is taken care of by 2's complement arithmetic. while (uwTick - start < Delay) { // This macro will execute the necessary idle behaviour. It may // raise an exception, switch threads or enter sleep mode (waiting for // (at least) the SysTick interrupt). MICROPY_EVENT_POLL_HOOK } } else { // IRQs disabled, so need to use a busy loop for the delay. // To prevent possible overflow of the counter we use a double loop. const uint32_t count_1ms = HAL_RCC_GetSysClockFreq() / 4000; for (int i = 0; i < Delay; i++) { for (uint32_t count = 0; ++count <= count_1ms;) { } } } } // delay for given number of microseconds void mp_hal_delay_us(mp_uint_t usec) { if (query_irq() == IRQ_STATE_ENABLED) { // IRQs enabled, so can use systick counter to do the delay uint32_t start = mp_hal_ticks_us(); while (mp_hal_ticks_us() - start < usec) { } } else { // IRQs disabled, so need to use a busy loop for the delay // sys freq is always a multiple of 2MHz, so division here won't lose precision const uint32_t ucount = HAL_RCC_GetSysClockFreq() / 2000000 * usec / 2; for (uint32_t count = 0; ++count <= ucount;) { } } } bool systick_has_passed(uint32_t start_tick, uint32_t delay_ms) { return HAL_GetTick() - start_tick >= delay_ms; } // waits until at least delay_ms milliseconds have passed from the sampling of // startTick. Handles overflow properly. Assumes stc was taken from // HAL_GetTick() some time before calling this function. void systick_wait_at_least(uint32_t start_tick, uint32_t delay_ms) { while (!systick_has_passed(start_tick, delay_ms)) { __WFI(); // enter sleep mode, waiting for interrupt } } mp_uint_t mp_hal_ticks_ms(void) { return uwTick; } // The SysTick timer counts down at 168 MHz, so we can use that knowledge // to grab a microsecond counter. // // We assume that HAL_GetTickis returns milliseconds. mp_uint_t mp_hal_ticks_us(void) { mp_uint_t irq_state = disable_irq(); uint32_t counter = SysTick->VAL; uint32_t milliseconds = HAL_GetTick(); uint32_t status = SysTick->CTRL; enable_irq(irq_state); // It's still possible for the countflag bit to get set if the counter was // reloaded between reading VAL and reading CTRL. With interrupts disabled // it definitely takes less than 50 HCLK cycles between reading VAL and // reading CTRL, so the test (counter > 50) is to cover the case where VAL // is +ve and very close to zero, and the COUNTFLAG bit is also set. if ((status & SysTick_CTRL_COUNTFLAG_Msk) && counter > 50) { // This means that the HW reloaded VAL between the time we read VAL and the // time we read CTRL, which implies that there is an interrupt pending // to increment the tick counter. milliseconds++; } uint32_t load = SysTick->LOAD; counter = load - counter; // Convert from decrementing to incrementing // ((load + 1) / 1000) is the number of counts per microsecond. // // counter / ((load + 1) / 1000) scales from the systick clock to microseconds // and is the same thing as (counter * 1000) / (load + 1) return milliseconds * 1000 + (counter * 1000) / (load + 1); } micropython-1.12/ports/stm32/systick.h000066400000000000000000000044561357706137100200140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_SYSTICK_H #define MICROPY_INCLUDED_STM32_SYSTICK_H // Works for x between 0 and 16 inclusive #define POW2_CEIL(x) ((((x) - 1) | ((x) - 1) >> 1 | ((x) - 1) >> 2 | ((x) - 1) >> 3) + 1) enum { SYSTICK_DISPATCH_DMA = 0, #if MICROPY_HW_ENABLE_STORAGE SYSTICK_DISPATCH_STORAGE, #endif #if MICROPY_PY_NETWORK && MICROPY_PY_LWIP SYSTICK_DISPATCH_LWIP, #endif #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE SYSTICK_DISPATCH_NIMBLE, #endif SYSTICK_DISPATCH_MAX }; #define SYSTICK_DISPATCH_NUM_SLOTS POW2_CEIL(SYSTICK_DISPATCH_MAX) typedef void (*systick_dispatch_t)(uint32_t); extern systick_dispatch_t systick_dispatch_table[SYSTICK_DISPATCH_NUM_SLOTS]; static inline void systick_enable_dispatch(size_t slot, systick_dispatch_t f) { systick_dispatch_table[slot] = f; } static inline void systick_disable_dispatch(size_t slot) { systick_dispatch_table[slot] = NULL; } void systick_wait_at_least(uint32_t stc, uint32_t delay_ms); bool systick_has_passed(uint32_t stc, uint32_t delay_ms); #endif // MICROPY_INCLUDED_STM32_SYSTICK_H micropython-1.12/ports/stm32/timer.c000066400000000000000000001744361357706137100174440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/gc.h" #include "timer.h" #include "servo.h" #include "pin.h" #include "irq.h" /// \moduleref pyb /// \class Timer - periodically call a function /// /// Timers can be used for a great variety of tasks. At the moment, only /// the simplest case is implemented: that of calling a function periodically. /// /// Each timer consists of a counter that counts up at a certain rate. The rate /// at which it counts is the peripheral clock frequency (in Hz) divided by the /// timer prescaler. When the counter reaches the timer period it triggers an /// event, and the counter resets back to zero. By using the callback method, /// the timer event can call a Python function. /// /// Example usage to toggle an LED at a fixed frequency: /// /// tim = pyb.Timer(4) # create a timer object using timer 4 /// tim.init(freq=2) # trigger at 2Hz /// tim.callback(lambda t:pyb.LED(1).toggle()) /// /// Further examples: /// /// tim = pyb.Timer(4, freq=100) # freq in Hz /// tim = pyb.Timer(4, prescaler=0, period=99) /// tim.counter() # get counter (can also set) /// tim.prescaler(2) # set prescaler (can also get) /// tim.period(199) # set period (can also get) /// tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance) /// tim.callback(None) # clear callback /// /// *Note:* Timer 3 is used for fading the blue LED. Timer 5 controls /// the servo driver, and Timer 6 is used for timed ADC/DAC reading/writing. /// It is recommended to use the other timers in your programs. // The timers can be used by multiple drivers, and need a common point for // the interrupts to be dispatched, so they are all collected here. // // TIM3: // - LED 4, PWM to set the LED intensity // // TIM5: // - servo controller, PWM // // TIM6: // - ADC, DAC for read_timed and write_timed typedef enum { CHANNEL_MODE_PWM_NORMAL, CHANNEL_MODE_PWM_INVERTED, CHANNEL_MODE_OC_TIMING, CHANNEL_MODE_OC_ACTIVE, CHANNEL_MODE_OC_INACTIVE, CHANNEL_MODE_OC_TOGGLE, CHANNEL_MODE_OC_FORCED_ACTIVE, CHANNEL_MODE_OC_FORCED_INACTIVE, CHANNEL_MODE_IC, CHANNEL_MODE_ENC_A, CHANNEL_MODE_ENC_B, CHANNEL_MODE_ENC_AB, } pyb_channel_mode; STATIC const struct { qstr name; uint32_t oc_mode; } channel_mode_info[] = { { MP_QSTR_PWM, TIM_OCMODE_PWM1 }, { MP_QSTR_PWM_INVERTED, TIM_OCMODE_PWM2 }, { MP_QSTR_OC_TIMING, TIM_OCMODE_TIMING }, { MP_QSTR_OC_ACTIVE, TIM_OCMODE_ACTIVE }, { MP_QSTR_OC_INACTIVE, TIM_OCMODE_INACTIVE }, { MP_QSTR_OC_TOGGLE, TIM_OCMODE_TOGGLE }, { MP_QSTR_OC_FORCED_ACTIVE, TIM_OCMODE_FORCED_ACTIVE }, { MP_QSTR_OC_FORCED_INACTIVE, TIM_OCMODE_FORCED_INACTIVE }, { MP_QSTR_IC, 0 }, { MP_QSTR_ENC_A, TIM_ENCODERMODE_TI1 }, { MP_QSTR_ENC_B, TIM_ENCODERMODE_TI2 }, { MP_QSTR_ENC_AB, TIM_ENCODERMODE_TI12 }, }; enum { BRK_OFF, BRK_LOW, BRK_HIGH, }; typedef struct _pyb_timer_channel_obj_t { mp_obj_base_t base; struct _pyb_timer_obj_t *timer; uint8_t channel; uint8_t mode; mp_obj_t callback; struct _pyb_timer_channel_obj_t *next; } pyb_timer_channel_obj_t; typedef struct _pyb_timer_obj_t { mp_obj_base_t base; uint8_t tim_id; uint8_t is_32bit; mp_obj_t callback; TIM_HandleTypeDef tim; IRQn_Type irqn; pyb_timer_channel_obj_t *channel; } pyb_timer_obj_t; // The following yields TIM_IT_UPDATE when channel is zero and // TIM_IT_CC1..TIM_IT_CC4 when channel is 1..4 #define TIMER_IRQ_MASK(channel) (1 << (channel)) #define TIMER_CNT_MASK(self) ((self)->is_32bit ? 0xffffffff : 0xffff) #define TIMER_CHANNEL(self) ((((self)->channel) - 1) << 2) TIM_HandleTypeDef TIM5_Handle; TIM_HandleTypeDef TIM6_Handle; #define PYB_TIMER_OBJ_ALL_NUM MP_ARRAY_SIZE(MP_STATE_PORT(pyb_timer_obj_all)) STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in); STATIC mp_obj_t pyb_timer_callback(mp_obj_t self_in, mp_obj_t callback); STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback); void timer_init0(void) { for (uint i = 0; i < PYB_TIMER_OBJ_ALL_NUM; i++) { MP_STATE_PORT(pyb_timer_obj_all)[i] = NULL; } } // unregister all interrupt sources void timer_deinit(void) { for (uint i = 0; i < PYB_TIMER_OBJ_ALL_NUM; i++) { pyb_timer_obj_t *tim = MP_STATE_PORT(pyb_timer_obj_all)[i]; if (tim != NULL) { pyb_timer_deinit(MP_OBJ_FROM_PTR(tim)); } } } #if defined(TIM5) // TIM5 is set-up for the servo controller // This function inits but does not start the timer void timer_tim5_init(void) { // TIM5 clock enable __HAL_RCC_TIM5_CLK_ENABLE(); // set up and enable interrupt NVIC_SetPriority(TIM5_IRQn, IRQ_PRI_TIM5); HAL_NVIC_EnableIRQ(TIM5_IRQn); // PWM clock configuration TIM5_Handle.Instance = TIM5; TIM5_Handle.Init.Period = 2000 - 1; // timer cycles at 50Hz TIM5_Handle.Init.Prescaler = (timer_get_source_freq(5) / 100000) - 1; // timer runs at 100kHz TIM5_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; TIM5_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; HAL_TIM_PWM_Init(&TIM5_Handle); } #endif #if defined(TIM6) // Init TIM6 with a counter-overflow at the given frequency (given in Hz) // TIM6 is used by the DAC and ADC for auto sampling at a given frequency // This function inits but does not start the timer TIM_HandleTypeDef *timer_tim6_init(uint freq) { // TIM6 clock enable __HAL_RCC_TIM6_CLK_ENABLE(); // Timer runs at SystemCoreClock / 2 // Compute the prescaler value so TIM6 triggers at freq-Hz uint32_t period = MAX(1, timer_get_source_freq(6) / freq); uint32_t prescaler = 1; while (period > 0xffff) { period >>= 1; prescaler <<= 1; } // Time base clock configuration TIM6_Handle.Instance = TIM6; TIM6_Handle.Init.Period = period - 1; TIM6_Handle.Init.Prescaler = prescaler - 1; TIM6_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // unused for TIM6 TIM6_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6 HAL_TIM_Base_Init(&TIM6_Handle); return &TIM6_Handle; } #endif // Interrupt dispatch void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { #if MICROPY_HW_ENABLE_SERVO if (htim == &TIM5_Handle) { servo_timer_irq_callback(); } #endif } // Get the frequency (in Hz) of the source clock for the given timer. // On STM32F405/407/415/417 there are 2 cases for how the clock freq is set. // If the APB prescaler is 1, then the timer clock is equal to its respective // APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its // respective APB clock. See DM00031020 Rev 4, page 115. uint32_t timer_get_source_freq(uint32_t tim_id) { uint32_t source, clk_div; if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { // TIM{1,8,9,10,11} are on APB2 #if defined(STM32F0) source = HAL_RCC_GetPCLK1Freq(); clk_div = RCC->CFGR & RCC_CFGR_PPRE; #elif defined(STM32H7) source = HAL_RCC_GetPCLK2Freq(); clk_div = RCC->D2CFGR & RCC_D2CFGR_D2PPRE2; #else source = HAL_RCC_GetPCLK2Freq(); clk_div = RCC->CFGR & RCC_CFGR_PPRE2; #endif } else { // TIM{2,3,4,5,6,7,12,13,14} are on APB1 source = HAL_RCC_GetPCLK1Freq(); #if defined(STM32F0) clk_div = RCC->CFGR & RCC_CFGR_PPRE; #elif defined(STM32H7) clk_div = RCC->D2CFGR & RCC_D2CFGR_D2PPRE1; #else clk_div = RCC->CFGR & RCC_CFGR_PPRE1; #endif } if (clk_div != 0) { // APB prescaler for this timer is > 1 source *= 2; } return source; } /******************************************************************************/ /* MicroPython bindings */ STATIC const mp_obj_type_t pyb_timer_channel_type; // This is the largest value that we can multiply by 100 and have the result // fit in a uint32_t. #define MAX_PERIOD_DIV_100 42949672 // computes prescaler and period so TIM triggers at freq-Hz STATIC uint32_t compute_prescaler_period_from_freq(pyb_timer_obj_t *self, mp_obj_t freq_in, uint32_t *period_out) { uint32_t source_freq = timer_get_source_freq(self->tim_id); uint32_t prescaler = 1; uint32_t period; if (0) { #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_type(freq_in, &mp_type_float)) { float freq = mp_obj_get_float(freq_in); if (freq <= 0) { goto bad_freq; } while (freq < 1 && prescaler < 6553) { prescaler *= 10; freq *= 10; } period = (float)source_freq / freq; #endif } else { mp_int_t freq = mp_obj_get_int(freq_in); if (freq <= 0) { goto bad_freq; bad_freq: mp_raise_ValueError("must have positive freq"); } period = source_freq / freq; } period = MAX(1, period); while (period > TIMER_CNT_MASK(self)) { // if we can divide exactly, do that first if (period % 5 == 0) { prescaler *= 5; period /= 5; } else if (period % 3 == 0) { prescaler *= 3; period /= 3; } else { // may not divide exactly, but loses minimal precision prescaler <<= 1; period >>= 1; } } *period_out = (period - 1) & TIMER_CNT_MASK(self); return (prescaler - 1) & 0xffff; } // computes prescaler and period so TIM triggers with a period of t_num/t_den seconds STATIC uint32_t compute_prescaler_period_from_t(pyb_timer_obj_t *self, int32_t t_num, int32_t t_den, uint32_t *period_out) { uint32_t source_freq = timer_get_source_freq(self->tim_id); if (t_num <= 0 || t_den <= 0) { mp_raise_ValueError("must have positive freq"); } uint64_t period = (uint64_t)source_freq * (uint64_t)t_num / (uint64_t)t_den; uint32_t prescaler = 1; while (period > TIMER_CNT_MASK(self)) { // if we can divide exactly, and without prescaler overflow, do that first if (prescaler <= 13107 && period % 5 == 0) { prescaler *= 5; period /= 5; } else if (prescaler <= 21845 && period % 3 == 0) { prescaler *= 3; period /= 3; } else { // may not divide exactly, but loses minimal precision uint32_t period_lsb = period & 1; prescaler <<= 1; period >>= 1; if (period < prescaler) { // round division up prescaler |= period_lsb; } if (prescaler > 0x10000) { mp_raise_ValueError("period too large"); } } } *period_out = (period - 1) & TIMER_CNT_MASK(self); return (prescaler - 1) & 0xffff; } // Helper function for determining the period used for calculating percent STATIC uint32_t compute_period(pyb_timer_obj_t *self) { // In center mode, compare == period corresponds to 100% // In edge mode, compare == (period + 1) corresponds to 100% uint32_t period = (__HAL_TIM_GET_AUTORELOAD(&self->tim) & TIMER_CNT_MASK(self)); if (period != 0xffffffff) { if (self->tim.Init.CounterMode == TIM_COUNTERMODE_UP || self->tim.Init.CounterMode == TIM_COUNTERMODE_DOWN) { // Edge mode period++; } } return period; } // Helper function to compute PWM value from timer period and percent value. // 'percent_in' can be an int or a float between 0 and 100 (out of range // values are clamped). STATIC uint32_t compute_pwm_value_from_percent(uint32_t period, mp_obj_t percent_in) { uint32_t cmp; if (0) { #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_type(percent_in, &mp_type_float)) { mp_float_t percent = mp_obj_get_float(percent_in); if (percent <= 0.0) { cmp = 0; } else if (percent >= 100.0) { cmp = period; } else { cmp = percent / 100.0 * ((mp_float_t)period); } #endif } else { // For integer arithmetic, if period is large and 100*period will // overflow, then divide period before multiplying by cmp. Otherwise // do it the other way round to retain precision. mp_int_t percent = mp_obj_get_int(percent_in); if (percent <= 0) { cmp = 0; } else if (percent >= 100) { cmp = period; } else if (period > MAX_PERIOD_DIV_100) { cmp = (uint32_t)percent * (period / 100); } else { cmp = ((uint32_t)percent * period) / 100; } } return cmp; } // Helper function to compute percentage from timer perion and PWM value. STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t percent; if (cmp >= period) { percent = 100.0; } else { percent = (mp_float_t)cmp * 100.0 / ((mp_float_t)period); } return mp_obj_new_float(percent); #else mp_int_t percent; if (cmp >= period) { percent = 100; } else if (cmp > MAX_PERIOD_DIV_100) { percent = cmp / (period / 100); } else { percent = cmp * 100 / period; } return mp_obj_new_int(percent); #endif } #if !defined(STM32L0) // Computes the 8-bit value for the DTG field in the BDTR register. // // 1 tick = 1 count of the timer's clock (source_freq) divided by div. // 0-128 ticks in inrements of 1 // 128-256 ticks in increments of 2 // 256-512 ticks in increments of 8 // 512-1008 ticks in increments of 16 STATIC uint32_t compute_dtg_from_ticks(mp_int_t ticks) { if (ticks <= 0) { return 0; } if (ticks < 128) { return ticks; } if (ticks < 256) { return 0x80 | ((ticks - 128) / 2); } if (ticks < 512) { return 0xC0 | ((ticks - 256) / 8); } if (ticks < 1008) { return 0xE0 | ((ticks - 512) / 16); } return 0xFF; } // Given the 8-bit value stored in the DTG field of the BDTR register, compute // the number of ticks. STATIC mp_int_t compute_ticks_from_dtg(uint32_t dtg) { if ((dtg & 0x80) == 0) { return dtg & 0x7F; } if ((dtg & 0xC0) == 0x80) { return 128 + ((dtg & 0x3F) * 2); } if ((dtg & 0xE0) == 0xC0) { return 256 + ((dtg & 0x1F) * 8); } return 512 + ((dtg & 0x1F) * 16); } STATIC void config_deadtime(pyb_timer_obj_t *self, mp_int_t ticks, mp_int_t brk) { TIM_BreakDeadTimeConfigTypeDef deadTimeConfig; deadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; deadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; deadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; deadTimeConfig.DeadTime = compute_dtg_from_ticks(ticks); deadTimeConfig.BreakState = brk == BRK_OFF ? TIM_BREAK_DISABLE : TIM_BREAK_ENABLE; deadTimeConfig.BreakPolarity = brk == BRK_LOW ? TIM_BREAKPOLARITY_LOW : TIM_BREAKPOLARITY_HIGH; #if defined(STM32F7) || defined(STM32H7) | defined(STM32L4) deadTimeConfig.BreakFilter = 0; deadTimeConfig.Break2State = TIM_BREAK_DISABLE; deadTimeConfig.Break2Polarity = TIM_BREAKPOLARITY_LOW; deadTimeConfig.Break2Filter = 0; #endif deadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; HAL_TIMEx_ConfigBreakDeadTime(&self->tim, &deadTimeConfig); } #endif TIM_HandleTypeDef *pyb_timer_get_handle(mp_obj_t timer) { if (mp_obj_get_type(timer) != &pyb_timer_type) { mp_raise_ValueError("need a Timer object"); } pyb_timer_obj_t *self = MP_OBJ_TO_PTR(timer); return &self->tim; } STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->tim.State == HAL_TIM_STATE_RESET) { mp_printf(print, "Timer(%u)", self->tim_id); } else { uint32_t prescaler = self->tim.Instance->PSC & 0xffff; uint32_t period = __HAL_TIM_GET_AUTORELOAD(&self->tim) & TIMER_CNT_MASK(self); // for efficiency, we compute and print freq as an int (not a float) uint32_t freq = timer_get_source_freq(self->tim_id) / ((prescaler + 1) * (period + 1)); mp_printf(print, "Timer(%u, freq=%u, prescaler=%u, period=%u, mode=%s, div=%u", self->tim_id, freq, prescaler, period, self->tim.Init.CounterMode == TIM_COUNTERMODE_UP ? "UP" : self->tim.Init.CounterMode == TIM_COUNTERMODE_DOWN ? "DOWN" : "CENTER", self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 : self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1); #if !defined(STM32L0) #if defined(IS_TIM_ADVANCED_INSTANCE) if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) #elif defined(IS_TIM_BREAK_INSTANCE) if (IS_TIM_BREAK_INSTANCE(self->tim.Instance)) #else if (0) #endif { mp_printf(print, ", deadtime=%u", compute_ticks_from_dtg(self->tim.Instance->BDTR & TIM_BDTR_DTG)); if ((self->tim.Instance->BDTR & TIM_BDTR_BKE) == TIM_BDTR_BKE) { mp_printf(print, ", brk=%s", ((self->tim.Instance->BDTR & TIM_BDTR_BKP) == TIM_BDTR_BKP) ? "BRK_HIGH" : "BRK_LOW"); } else { mp_printf(print, ", brk=BRK_OFF"); } } #endif mp_print_str(print, ")"); } } /// \method init(*, freq, prescaler, period) /// Initialise the timer. Initialisation must be either by frequency (in Hz) /// or by prescaler and period: /// /// tim.init(freq=100) # set the timer to trigger at 100Hz /// tim.init(prescaler=83, period=999) # set the prescaler and period directly /// /// Keyword arguments: /// /// - `freq` - specifies the periodic frequency of the timer. You migh also /// view this as the frequency with which the timer goes through /// one complete cycle. /// /// - `prescaler` [0-0xffff] - specifies the value to be loaded into the /// timer's Prescaler Register (PSC). The timer clock source is divided by /// (`prescaler + 1`) to arrive at the timer clock. Timers 2-7 and 12-14 /// have a clock source of 84 MHz (pyb.freq()[2] * 2), and Timers 1, and 8-11 /// have a clock source of 168 MHz (pyb.freq()[3] * 2). /// /// - `period` [0-0xffff] for timers 1, 3, 4, and 6-15. [0-0x3fffffff] for timers 2 & 5. /// Specifies the value to be loaded into the timer's AutoReload /// Register (ARR). This determines the period of the timer (i.e. when the /// counter cycles). The timer counter will roll-over after `period + 1` /// timer clock cycles. /// /// - `mode` can be one of: /// - `Timer.UP` - configures the timer to count from 0 to ARR (default) /// - `Timer.DOWN` - configures the timer to count from ARR down to 0. /// - `Timer.CENTER` - confgures the timer to count from 0 to ARR and /// then back down to 0. /// /// - `div` can be one of 1, 2, or 4. Divides the timer clock to determine /// the sampling clock used by the digital filters. /// /// - `callback` - as per Timer.callback() /// /// - `deadtime` - specifies the amount of "dead" or inactive time between /// transitions on complimentary channels (both channels will be inactive) /// for this time). `deadtime` may be an integer between 0 and 1008, with /// the following restrictions: 0-128 in steps of 1. 128-256 in steps of /// 2, 256-512 in steps of 8, and 512-1008 in steps of 16. `deadime` /// measures ticks of `source_freq` divided by `div` clock ticks. /// `deadtime` is only available on timers 1 and 8. /// /// - `brk` - specifies if the break mode is used to kill the output of /// the PWM when the BRK_IN input is asserted. The polarity set how the /// BRK_IN input is triggered. It can be set to `BRK_OFF`, `BRK_LOW` /// and `BRK_HIGH`. /// /// /// You must either specify freq or both of period and prescaler. STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_freq, ARG_prescaler, ARG_period, ARG_tick_hz, ARG_mode, ARG_div, ARG_callback, ARG_deadtime, ARG_brk }; static const mp_arg_t allowed_args[] = { { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_COUNTERMODE_UP} }, { MP_QSTR_div, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_deadtime, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_brk, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BRK_OFF} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // set the TIM configuration values TIM_Base_InitTypeDef *init = &self->tim.Init; if (args[ARG_freq].u_obj != mp_const_none) { // set prescaler and period from desired frequency init->Prescaler = compute_prescaler_period_from_freq(self, args[ARG_freq].u_obj, &init->Period); } else if (args[ARG_prescaler].u_int != 0xffffffff && args[ARG_period].u_int != 0xffffffff) { // set prescaler and period directly init->Prescaler = args[ARG_prescaler].u_int; init->Period = args[ARG_period].u_int; } else if (args[ARG_period].u_int != 0xffffffff) { // set prescaler and period from desired period and tick_hz scale init->Prescaler = compute_prescaler_period_from_t(self, args[ARG_period].u_int, args[ARG_tick_hz].u_int, &init->Period); } else { mp_raise_TypeError("must specify either freq, period, or prescaler and period"); } init->CounterMode = args[ARG_mode].u_int; if (!IS_TIM_COUNTER_MODE(init->CounterMode)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid mode (%d)", init->CounterMode)); } init->ClockDivision = args[ARG_div].u_int == 2 ? TIM_CLOCKDIVISION_DIV2 : args[ARG_div].u_int == 4 ? TIM_CLOCKDIVISION_DIV4 : TIM_CLOCKDIVISION_DIV1; #if !defined(STM32L0) init->RepetitionCounter = 0; #endif // enable TIM clock switch (self->tim_id) { #if defined(TIM1) case 1: __HAL_RCC_TIM1_CLK_ENABLE(); break; #endif case 2: __HAL_RCC_TIM2_CLK_ENABLE(); break; #if defined(TIM3) case 3: __HAL_RCC_TIM3_CLK_ENABLE(); break; #endif #if defined(TIM4) case 4: __HAL_RCC_TIM4_CLK_ENABLE(); break; #endif #if defined(TIM5) case 5: __HAL_RCC_TIM5_CLK_ENABLE(); break; #endif #if defined(TIM6) case 6: __HAL_RCC_TIM6_CLK_ENABLE(); break; #endif #if defined(TIM7) case 7: __HAL_RCC_TIM7_CLK_ENABLE(); break; #endif #if defined(TIM8) case 8: __HAL_RCC_TIM8_CLK_ENABLE(); break; #endif #if defined(TIM9) case 9: __HAL_RCC_TIM9_CLK_ENABLE(); break; #endif #if defined(TIM10) case 10: __HAL_RCC_TIM10_CLK_ENABLE(); break; #endif #if defined(TIM11) case 11: __HAL_RCC_TIM11_CLK_ENABLE(); break; #endif #if defined(TIM12) case 12: __HAL_RCC_TIM12_CLK_ENABLE(); break; #endif #if defined(TIM13) case 13: __HAL_RCC_TIM13_CLK_ENABLE(); break; #endif #if defined(TIM14) case 14: __HAL_RCC_TIM14_CLK_ENABLE(); break; #endif #if defined(TIM15) case 15: __HAL_RCC_TIM15_CLK_ENABLE(); break; #endif #if defined(TIM16) case 16: __HAL_RCC_TIM16_CLK_ENABLE(); break; #endif #if defined(TIM17) case 17: __HAL_RCC_TIM17_CLK_ENABLE(); break; #endif #if defined(TIM18) case 18: __HAL_RCC_TIM18_CLK_ENABLE(); break; #endif #if defined(TIM19) case 19: __HAL_RCC_TIM19_CLK_ENABLE(); break; #endif #if defined(TIM20) case 20: __HAL_RCC_TIM20_CLK_ENABLE(); break; #endif #if defined(TIM21) case 21: __HAL_RCC_TIM21_CLK_ENABLE(); break; #endif #if defined(TIM22) case 22: __HAL_RCC_TIM22_CLK_ENABLE(); break; #endif } // set IRQ priority (if not a special timer) if (self->tim_id != 5) { NVIC_SetPriority(IRQn_NONNEG(self->irqn), IRQ_PRI_TIMX); if (self->tim_id == 1) { #if defined(TIM1) NVIC_SetPriority(TIM1_CC_IRQn, IRQ_PRI_TIMX); #endif } else if (self->tim_id == 8) { #if defined(TIM8) NVIC_SetPriority(TIM8_CC_IRQn, IRQ_PRI_TIMX); #endif } } // init TIM HAL_TIM_Base_Init(&self->tim); #if !defined(STM32L0) #if defined(IS_TIM_ADVANCED_INSTANCE) if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) { #elif defined(IS_TIM_BREAK_INSTANCE) if (IS_TIM_BREAK_INSTANCE(self->tim.Instance)) { #else if (0) { #endif config_deadtime(self, args[ARG_deadtime].u_int, args[ARG_brk].u_int); } #endif // Enable ARPE so that the auto-reload register is buffered. // This allows to smoothly change the frequency of the timer. self->tim.Instance->CR1 |= TIM_CR1_ARPE; // Start the timer running if (args[ARG_callback].u_obj == mp_const_none) { HAL_TIM_Base_Start(&self->tim); } else { pyb_timer_callback(MP_OBJ_FROM_PTR(self), args[ARG_callback].u_obj); } return mp_const_none; } // This table encodes the timer instance and irq number (for the update irq). // It assumes that timer instance pointer has the lower 8 bits cleared. #define TIM_ENTRY(id, irq) [id - 1] = (uint32_t)TIM##id | irq STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #if defined(TIM1) #if defined(STM32F0) TIM_ENTRY(1, TIM1_BRK_UP_TRG_COM_IRQn), #elif defined(STM32F4) || defined(STM32F7) TIM_ENTRY(1, TIM1_UP_TIM10_IRQn), #elif defined(STM32H7) TIM_ENTRY(1, TIM1_UP_IRQn), #elif defined(STM32L4) TIM_ENTRY(1, TIM1_UP_TIM16_IRQn), #endif #endif TIM_ENTRY(2, TIM2_IRQn), #if defined(TIM3) TIM_ENTRY(3, TIM3_IRQn), #endif #if defined(TIM4) TIM_ENTRY(4, TIM4_IRQn), #endif #if defined(TIM5) TIM_ENTRY(5, TIM5_IRQn), #endif #if defined(TIM6) TIM_ENTRY(6, TIM6_DAC_IRQn), #endif #if defined(TIM7) TIM_ENTRY(7, TIM7_IRQn), #endif #if defined(TIM8) #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) TIM_ENTRY(8, TIM8_UP_TIM13_IRQn), #elif defined(STM32L4) TIM_ENTRY(8, TIM8_UP_IRQn), #endif #endif #if defined(TIM9) TIM_ENTRY(9, TIM1_BRK_TIM9_IRQn), #endif #if defined(TIM10) TIM_ENTRY(10, TIM1_UP_TIM10_IRQn), #endif #if defined(TIM11) TIM_ENTRY(11, TIM1_TRG_COM_TIM11_IRQn), #endif #if defined(TIM12) TIM_ENTRY(12, TIM8_BRK_TIM12_IRQn), #endif #if defined(TIM13) TIM_ENTRY(13, TIM8_UP_TIM13_IRQn), #endif #if defined(STM32F0) TIM_ENTRY(14, TIM14_IRQn), #elif defined(TIM14) TIM_ENTRY(14, TIM8_TRG_COM_TIM14_IRQn), #endif #if defined(TIM15) #if defined(STM32F0) || defined(STM32H7) TIM_ENTRY(15, TIM15_IRQn), #else TIM_ENTRY(15, TIM1_BRK_TIM15_IRQn), #endif #endif #if defined(TIM16) #if defined(STM32F0) || defined(STM32H7) TIM_ENTRY(16, TIM16_IRQn), #else TIM_ENTRY(16, TIM1_UP_TIM16_IRQn), #endif #endif #if defined(TIM17) #if defined(STM32F0) || defined(STM32H7) TIM_ENTRY(17, TIM17_IRQn), #else TIM_ENTRY(17, TIM1_TRG_COM_TIM17_IRQn), #endif #endif }; #undef TIM_ENTRY /// \classmethod \constructor(id, ...) /// Construct a new timer object of the given id. If additional /// arguments are given, then the timer is initialised by `init(...)`. /// `id` can be 1 to 14, excluding 3. STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get the timer id mp_int_t tim_id = mp_obj_get_int(args[0]); // check if the timer exists if (tim_id <= 0 || tim_id > MICROPY_HW_MAX_TIMER || tim_instance_table[tim_id - 1] == 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer(%d) doesn't exist", tim_id)); } pyb_timer_obj_t *tim; if (MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1] == NULL) { // create new Timer object tim = m_new_obj(pyb_timer_obj_t); memset(tim, 0, sizeof(*tim)); tim->base.type = &pyb_timer_type; tim->tim_id = tim_id; tim->is_32bit = tim_id == 2 || tim_id == 5; tim->callback = mp_const_none; uint32_t ti = tim_instance_table[tim_id - 1]; tim->tim.Instance = (TIM_TypeDef*)(ti & 0xffffff00); tim->irqn = ti & 0xff; MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1] = tim; } else { // reference existing Timer object tim = MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1]; } if (n_args > 1 || n_kw > 0) { // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_timer_init_helper(tim, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(tim); } STATIC mp_obj_t pyb_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_timer_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init); // timer.deinit() STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) { pyb_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); // Disable the base interrupt pyb_timer_callback(self_in, mp_const_none); pyb_timer_channel_obj_t *chan = self->channel; self->channel = NULL; // Disable the channel interrupts while (chan != NULL) { pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), mp_const_none); pyb_timer_channel_obj_t *prev_chan = chan; chan = chan->next; prev_chan->next = NULL; } self->tim.State = HAL_TIM_STATE_RESET; self->tim.Instance->CCER = 0x0000; // disable all capture/compare outputs self->tim.Instance->CR1 = 0x0000; // disable the timer and reset its state return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit); /// \method channel(channel, mode, ...) /// /// If only a channel number is passed, then a previously initialized channel /// object is returned (or `None` if there is no previous channel). /// /// Othwerwise, a TimerChannel object is initialized and returned. /// /// Each channel can be configured to perform pwm, output compare, or /// input capture. All channels share the same underlying timer, which means /// that they share the same timer clock. /// /// Keyword arguments: /// /// - `mode` can be one of: /// - `Timer.PWM` - configure the timer in PWM mode (active high). /// - `Timer.PWM_INVERTED` - configure the timer in PWM mode (active low). /// - `Timer.OC_TIMING` - indicates that no pin is driven. /// - `Timer.OC_ACTIVE` - the pin will be made active when a compare /// match occurs (active is determined by polarity) /// - `Timer.OC_INACTIVE` - the pin will be made inactive when a compare /// match occurs. /// - `Timer.OC_TOGGLE` - the pin will be toggled when an compare match occurs. /// - `Timer.OC_FORCED_ACTIVE` - the pin is forced active (compare match is ignored). /// - `Timer.OC_FORCED_INACTIVE` - the pin is forced inactive (compare match is ignored). /// - `Timer.IC` - configure the timer in Input Capture mode. /// - `Timer.ENC_A` --- configure the timer in Encoder mode. The counter only changes when CH1 changes. /// - `Timer.ENC_B` --- configure the timer in Encoder mode. The counter only changes when CH2 changes. /// - `Timer.ENC_AB` --- configure the timer in Encoder mode. The counter changes when CH1 or CH2 changes. /// /// - `callback` - as per TimerChannel.callback() /// /// - `pin` None (the default) or a Pin object. If specified (and not None) /// this will cause the alternate function of the the indicated pin /// to be configured for this timer channel. An error will be raised if /// the pin doesn't support any alternate functions for this timer channel. /// /// Keyword arguments for Timer.PWM modes: /// /// - `pulse_width` - determines the initial pulse width value to use. /// - `pulse_width_percent` - determines the initial pulse width percentage to use. /// /// Keyword arguments for Timer.OC modes: /// /// - `compare` - determines the initial value of the compare register. /// /// - `polarity` can be one of: /// - `Timer.HIGH` - output is active high /// - `Timer.LOW` - output is acive low /// /// Optional keyword arguments for Timer.IC modes: /// /// - `polarity` can be one of: /// - `Timer.RISING` - captures on rising edge. /// - `Timer.FALLING` - captures on falling edge. /// - `Timer.BOTH` - captures on both edges. /// /// Note that capture only works on the primary channel, and not on the /// complimentary channels. /// /// Notes for Timer.ENC modes: /// /// - Requires 2 pins, so one or both pins will need to be configured to use /// the appropriate timer AF using the Pin API. /// - Read the encoder value using the timer.counter() method. /// - Only works on CH1 and CH2 (and not on CH1N or CH2N) /// - The channel number is ignored when setting the encoder mode. /// /// PWM Example: /// /// timer = pyb.Timer(2, freq=1000) /// ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.X2, pulse_width=210000) /// ch3 = timer.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width=420000) STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_pulse_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_pulse_width_percent, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_compare, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, }; pyb_timer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_int_t channel = mp_obj_get_int(pos_args[1]); if (channel < 1 || channel > 4) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid channel (%d)", channel)); } pyb_timer_channel_obj_t *chan = self->channel; pyb_timer_channel_obj_t *prev_chan = NULL; while (chan != NULL) { if (chan->channel == channel) { break; } prev_chan = chan; chan = chan->next; } // If only the channel number is given return the previously allocated // channel (or None if no previous channel). if (n_args == 2 && kw_args->used == 0) { if (chan) { return MP_OBJ_FROM_PTR(chan); } return mp_const_none; } // If there was already a channel, then remove it from the list. Note that // the order we do things here is important so as to appear atomic to // the IRQ handler. if (chan) { // Turn off any IRQ associated with the channel. pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), mp_const_none); // Unlink the channel from the list. if (prev_chan) { prev_chan->next = chan->next; } self->channel = chan->next; chan->next = NULL; } // Allocate and initialize a new channel mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); chan = m_new_obj(pyb_timer_channel_obj_t); memset(chan, 0, sizeof(*chan)); chan->base.type = &pyb_timer_channel_type; chan->timer = self; chan->channel = channel; chan->mode = args[0].u_int; chan->callback = args[1].u_obj; mp_obj_t pin_obj = args[2].u_obj; if (pin_obj != mp_const_none) { if (!mp_obj_is_type(pin_obj, &pin_type)) { mp_raise_ValueError("pin argument needs to be be a Pin type"); } const pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj); const pin_af_obj_t *af = pin_find_af(pin, AF_FN_TIM, self->tim_id); if (af == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Pin(%q) doesn't have an af for Timer(%d)", pin->name, self->tim_id)); } // pin.init(mode=AF_PP, af=idx) const mp_obj_t args2[6] = { MP_OBJ_FROM_PTR(&pin_init_obj), pin_obj, MP_OBJ_NEW_QSTR(MP_QSTR_mode), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP), MP_OBJ_NEW_QSTR(MP_QSTR_af), MP_OBJ_NEW_SMALL_INT(af->idx) }; mp_call_method_n_kw(0, 2, args2); } // Link the channel to the timer before we turn the channel on. // Note that this needs to appear atomic to the IRQ handler (the write // to self->channel is atomic, so we're good, but I thought I'd mention // in case this was ever changed in the future). chan->next = self->channel; self->channel = chan; switch (chan->mode) { case CHANNEL_MODE_PWM_NORMAL: case CHANNEL_MODE_PWM_INVERTED: { TIM_OC_InitTypeDef oc_config; oc_config.OCMode = channel_mode_info[chan->mode].oc_mode; if (args[4].u_obj != mp_const_none) { // pulse width percent given uint32_t period = compute_period(self); oc_config.Pulse = compute_pwm_value_from_percent(period, args[4].u_obj); } else { // use absolute pulse width value (defaults to 0 if nothing given) oc_config.Pulse = args[3].u_int; } oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; oc_config.OCFastMode = TIM_OCFAST_DISABLE; #if !defined(STM32L0) oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; oc_config.OCIdleState = TIM_OCIDLESTATE_SET; oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET; #endif HAL_TIM_PWM_ConfigChannel(&self->tim, &oc_config, TIMER_CHANNEL(chan)); if (chan->callback == mp_const_none) { HAL_TIM_PWM_Start(&self->tim, TIMER_CHANNEL(chan)); } else { pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); } #if !defined(STM32L0) // Start the complimentary channel too (if its supported) if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { HAL_TIMEx_PWMN_Start(&self->tim, TIMER_CHANNEL(chan)); } #endif break; } case CHANNEL_MODE_OC_TIMING: case CHANNEL_MODE_OC_ACTIVE: case CHANNEL_MODE_OC_INACTIVE: case CHANNEL_MODE_OC_TOGGLE: case CHANNEL_MODE_OC_FORCED_ACTIVE: case CHANNEL_MODE_OC_FORCED_INACTIVE: { TIM_OC_InitTypeDef oc_config; oc_config.OCMode = channel_mode_info[chan->mode].oc_mode; oc_config.Pulse = args[5].u_int; oc_config.OCPolarity = args[6].u_int; if (oc_config.OCPolarity == 0xffffffff) { oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; } oc_config.OCFastMode = TIM_OCFAST_DISABLE; #if !defined(STM32L0) if (oc_config.OCPolarity == TIM_OCPOLARITY_HIGH) { oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; } else { oc_config.OCNPolarity = TIM_OCNPOLARITY_LOW; } oc_config.OCIdleState = TIM_OCIDLESTATE_SET; oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET; #endif if (!IS_TIM_OC_POLARITY(oc_config.OCPolarity)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid polarity (%d)", oc_config.OCPolarity)); } HAL_TIM_OC_ConfigChannel(&self->tim, &oc_config, TIMER_CHANNEL(chan)); if (chan->callback == mp_const_none) { HAL_TIM_OC_Start(&self->tim, TIMER_CHANNEL(chan)); } else { pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); } #if !defined(STM32L0) // Start the complimentary channel too (if its supported) if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { HAL_TIMEx_OCN_Start(&self->tim, TIMER_CHANNEL(chan)); } #endif break; } case CHANNEL_MODE_IC: { TIM_IC_InitTypeDef ic_config; ic_config.ICPolarity = args[6].u_int; if (ic_config.ICPolarity == 0xffffffff) { ic_config.ICPolarity = TIM_ICPOLARITY_RISING; } ic_config.ICSelection = TIM_ICSELECTION_DIRECTTI; ic_config.ICPrescaler = TIM_ICPSC_DIV1; ic_config.ICFilter = 0; if (!IS_TIM_IC_POLARITY(ic_config.ICPolarity)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid polarity (%d)", ic_config.ICPolarity)); } HAL_TIM_IC_ConfigChannel(&self->tim, &ic_config, TIMER_CHANNEL(chan)); if (chan->callback == mp_const_none) { HAL_TIM_IC_Start(&self->tim, TIMER_CHANNEL(chan)); } else { pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); } break; } case CHANNEL_MODE_ENC_A: case CHANNEL_MODE_ENC_B: case CHANNEL_MODE_ENC_AB: { TIM_Encoder_InitTypeDef enc_config; enc_config.EncoderMode = channel_mode_info[chan->mode].oc_mode; enc_config.IC1Polarity = args[6].u_int; if (enc_config.IC1Polarity == 0xffffffff) { enc_config.IC1Polarity = TIM_ICPOLARITY_RISING; } enc_config.IC2Polarity = enc_config.IC1Polarity; enc_config.IC1Selection = TIM_ICSELECTION_DIRECTTI; enc_config.IC2Selection = TIM_ICSELECTION_DIRECTTI; enc_config.IC1Prescaler = TIM_ICPSC_DIV1; enc_config.IC2Prescaler = TIM_ICPSC_DIV1; enc_config.IC1Filter = 0; enc_config.IC2Filter = 0; if (!IS_TIM_IC_POLARITY(enc_config.IC1Polarity)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid polarity (%d)", enc_config.IC1Polarity)); } // Only Timers 1, 2, 3, 4, 5, and 8 support encoder mode if ( #if defined(TIM1) self->tim.Instance != TIM1 && #endif self->tim.Instance != TIM2 #if defined(TIM3) && self->tim.Instance != TIM3 #endif #if defined(TIM4) && self->tim.Instance != TIM4 #endif #if defined(TIM5) && self->tim.Instance != TIM5 #endif #if defined(TIM8) && self->tim.Instance != TIM8 #endif ) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "encoder not supported on timer %d", self->tim_id)); } // Disable & clear the timer interrupt so that we don't trigger // an interrupt by initializing the timer. __HAL_TIM_DISABLE_IT(&self->tim, TIM_IT_UPDATE); HAL_TIM_Encoder_Init(&self->tim, &enc_config); __HAL_TIM_SET_COUNTER(&self->tim, 0); if (self->callback != mp_const_none) { __HAL_TIM_CLEAR_FLAG(&self->tim, TIM_IT_UPDATE); __HAL_TIM_ENABLE_IT(&self->tim, TIM_IT_UPDATE); } HAL_TIM_Encoder_Start(&self->tim, TIM_CHANNEL_ALL); break; } default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid mode (%d)", chan->mode)); } return MP_OBJ_FROM_PTR(chan); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel); /// \method counter([value]) /// Get or set the timer counter. STATIC mp_obj_t pyb_timer_counter(size_t n_args, const mp_obj_t *args) { pyb_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get return mp_obj_new_int(self->tim.Instance->CNT); } else { // set __HAL_TIM_SET_COUNTER(&self->tim, mp_obj_get_int(args[1])); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_counter_obj, 1, 2, pyb_timer_counter); /// \method source_freq() /// Get the frequency of the source of the timer. STATIC mp_obj_t pyb_timer_source_freq(mp_obj_t self_in) { pyb_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); uint32_t source_freq = timer_get_source_freq(self->tim_id); return mp_obj_new_int(source_freq); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_source_freq_obj, pyb_timer_source_freq); /// \method freq([value]) /// Get or set the frequency for the timer (changes prescaler and period if set). STATIC mp_obj_t pyb_timer_freq(size_t n_args, const mp_obj_t *args) { pyb_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get uint32_t prescaler = self->tim.Instance->PSC & 0xffff; uint32_t period = __HAL_TIM_GET_AUTORELOAD(&self->tim) & TIMER_CNT_MASK(self); uint32_t source_freq = timer_get_source_freq(self->tim_id); uint32_t divide_a = prescaler + 1; uint32_t divide_b = period + 1; #if MICROPY_PY_BUILTINS_FLOAT if (source_freq % divide_a != 0) { return mp_obj_new_float((mp_float_t)source_freq / (mp_float_t)divide_a / (mp_float_t)divide_b); } source_freq /= divide_a; if (source_freq % divide_b != 0) { return mp_obj_new_float((mp_float_t)source_freq / (mp_float_t)divide_b); } else { return mp_obj_new_int(source_freq / divide_b); } #else return mp_obj_new_int(source_freq / divide_a / divide_b); #endif } else { // set uint32_t period; uint32_t prescaler = compute_prescaler_period_from_freq(self, args[1], &period); self->tim.Instance->PSC = prescaler; __HAL_TIM_SET_AUTORELOAD(&self->tim, period); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_freq_obj, 1, 2, pyb_timer_freq); /// \method prescaler([value]) /// Get or set the prescaler for the timer. STATIC mp_obj_t pyb_timer_prescaler(size_t n_args, const mp_obj_t *args) { pyb_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get return mp_obj_new_int(self->tim.Instance->PSC & 0xffff); } else { // set self->tim.Instance->PSC = mp_obj_get_int(args[1]) & 0xffff; return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_prescaler_obj, 1, 2, pyb_timer_prescaler); /// \method period([value]) /// Get or set the period of the timer. STATIC mp_obj_t pyb_timer_period(size_t n_args, const mp_obj_t *args) { pyb_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get return mp_obj_new_int(__HAL_TIM_GET_AUTORELOAD(&self->tim) & TIMER_CNT_MASK(self)); } else { // set __HAL_TIM_SET_AUTORELOAD(&self->tim, mp_obj_get_int(args[1]) & TIMER_CNT_MASK(self)); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_period_obj, 1, 2, pyb_timer_period); /// \method callback(fun) /// Set the function to be called when the timer triggers. /// `fun` is passed 1 argument, the timer object. /// If `fun` is `None` then the callback will be disabled. STATIC mp_obj_t pyb_timer_callback(mp_obj_t self_in, mp_obj_t callback) { pyb_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); if (callback == mp_const_none) { // stop interrupt (but not timer) __HAL_TIM_DISABLE_IT(&self->tim, TIM_IT_UPDATE); self->callback = mp_const_none; } else if (mp_obj_is_callable(callback)) { __HAL_TIM_DISABLE_IT(&self->tim, TIM_IT_UPDATE); self->callback = callback; // start timer, so that it interrupts on overflow, but clear any // pending interrupts which may have been set by initializing it. __HAL_TIM_CLEAR_FLAG(&self->tim, TIM_IT_UPDATE); HAL_TIM_Base_Start_IT(&self->tim); // This will re-enable the IRQ HAL_NVIC_EnableIRQ(self->irqn); } else { mp_raise_ValueError("callback must be None or a callable object"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_timer_callback_obj, pyb_timer_callback); STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_timer_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_timer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&pyb_timer_channel_obj) }, { MP_ROM_QSTR(MP_QSTR_counter), MP_ROM_PTR(&pyb_timer_counter_obj) }, { MP_ROM_QSTR(MP_QSTR_source_freq), MP_ROM_PTR(&pyb_timer_source_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_timer_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_prescaler), MP_ROM_PTR(&pyb_timer_prescaler_obj) }, { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&pyb_timer_period_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&pyb_timer_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_UP), MP_ROM_INT(TIM_COUNTERMODE_UP) }, { MP_ROM_QSTR(MP_QSTR_DOWN), MP_ROM_INT(TIM_COUNTERMODE_DOWN) }, { MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(TIM_COUNTERMODE_CENTERALIGNED1) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_INT(CHANNEL_MODE_PWM_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_PWM_INVERTED), MP_ROM_INT(CHANNEL_MODE_PWM_INVERTED) }, { MP_ROM_QSTR(MP_QSTR_OC_TIMING), MP_ROM_INT(CHANNEL_MODE_OC_TIMING) }, { MP_ROM_QSTR(MP_QSTR_OC_ACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_ACTIVE) }, { MP_ROM_QSTR(MP_QSTR_OC_INACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_INACTIVE) }, { MP_ROM_QSTR(MP_QSTR_OC_TOGGLE), MP_ROM_INT(CHANNEL_MODE_OC_TOGGLE) }, { MP_ROM_QSTR(MP_QSTR_OC_FORCED_ACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_FORCED_ACTIVE) }, { MP_ROM_QSTR(MP_QSTR_OC_FORCED_INACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_FORCED_INACTIVE) }, { MP_ROM_QSTR(MP_QSTR_IC), MP_ROM_INT(CHANNEL_MODE_IC) }, { MP_ROM_QSTR(MP_QSTR_ENC_A), MP_ROM_INT(CHANNEL_MODE_ENC_A) }, { MP_ROM_QSTR(MP_QSTR_ENC_B), MP_ROM_INT(CHANNEL_MODE_ENC_B) }, { MP_ROM_QSTR(MP_QSTR_ENC_AB), MP_ROM_INT(CHANNEL_MODE_ENC_AB) }, { MP_ROM_QSTR(MP_QSTR_HIGH), MP_ROM_INT(TIM_OCPOLARITY_HIGH) }, { MP_ROM_QSTR(MP_QSTR_LOW), MP_ROM_INT(TIM_OCPOLARITY_LOW) }, { MP_ROM_QSTR(MP_QSTR_RISING), MP_ROM_INT(TIM_ICPOLARITY_RISING) }, { MP_ROM_QSTR(MP_QSTR_FALLING), MP_ROM_INT(TIM_ICPOLARITY_FALLING) }, { MP_ROM_QSTR(MP_QSTR_BOTH), MP_ROM_INT(TIM_ICPOLARITY_BOTHEDGE) }, { MP_ROM_QSTR(MP_QSTR_BRK_OFF), MP_ROM_INT(BRK_OFF) }, { MP_ROM_QSTR(MP_QSTR_BRK_LOW), MP_ROM_INT(BRK_LOW) }, { MP_ROM_QSTR(MP_QSTR_BRK_HIGH), MP_ROM_INT(BRK_HIGH) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table); const mp_obj_type_t pyb_timer_type = { { &mp_type_type }, .name = MP_QSTR_Timer, .print = pyb_timer_print, .make_new = pyb_timer_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_timer_locals_dict, }; /// \moduleref pyb /// \class TimerChannel - setup a channel for a timer. /// /// Timer channels are used to generate/capture a signal using a timer. /// /// TimerChannel objects are created using the Timer.channel() method. STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_timer_channel_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "TimerChannel(timer=%u, channel=%u, mode=%s)", self->timer->tim_id, self->channel, qstr_str(channel_mode_info[self->mode].name)); } /// \method capture([value]) /// Get or set the capture value associated with a channel. /// capture, compare, and pulse_width are all aliases for the same function. /// capture is the logical name to use when the channel is in input capture mode. /// \method compare([value]) /// Get or set the compare value associated with a channel. /// capture, compare, and pulse_width are all aliases for the same function. /// compare is the logical name to use when the channel is in output compare mode. /// \method pulse_width([value]) /// Get or set the pulse width value associated with a channel. /// capture, compare, and pulse_width are all aliases for the same function. /// pulse_width is the logical name to use when the channel is in PWM mode. /// /// In edge aligned mode, a pulse_width of `period + 1` corresponds to a duty cycle of 100% /// In center aligned mode, a pulse width of `period` corresponds to a duty cycle of 100% STATIC mp_obj_t pyb_timer_channel_capture_compare(size_t n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 1) { // get return mp_obj_new_int(__HAL_TIM_GET_COMPARE(&self->timer->tim, TIMER_CHANNEL(self)) & TIMER_CNT_MASK(self->timer)); } else { // set __HAL_TIM_SET_COMPARE(&self->timer->tim, TIMER_CHANNEL(self), mp_obj_get_int(args[1]) & TIMER_CNT_MASK(self->timer)); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_capture_compare_obj, 1, 2, pyb_timer_channel_capture_compare); /// \method pulse_width_percent([value]) /// Get or set the pulse width percentage associated with a channel. The value /// is a number between 0 and 100 and sets the percentage of the timer period /// for which the pulse is active. The value can be an integer or /// floating-point number for more accuracy. For example, a value of 25 gives /// a duty cycle of 25%. STATIC mp_obj_t pyb_timer_channel_pulse_width_percent(size_t n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *self = MP_OBJ_TO_PTR(args[0]); uint32_t period = compute_period(self->timer); if (n_args == 1) { // get uint32_t cmp = __HAL_TIM_GET_COMPARE(&self->timer->tim, TIMER_CHANNEL(self)) & TIMER_CNT_MASK(self->timer); return compute_percent_from_pwm_value(period, cmp); } else { // set uint32_t cmp = compute_pwm_value_from_percent(period, args[1]); __HAL_TIM_SET_COMPARE(&self->timer->tim, TIMER_CHANNEL(self), cmp & TIMER_CNT_MASK(self->timer)); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_pulse_width_percent_obj, 1, 2, pyb_timer_channel_pulse_width_percent); /// \method callback(fun) /// Set the function to be called when the timer channel triggers. /// `fun` is passed 1 argument, the timer object. /// If `fun` is `None` then the callback will be disabled. STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback) { pyb_timer_channel_obj_t *self = MP_OBJ_TO_PTR(self_in); if (callback == mp_const_none) { // stop interrupt (but not timer) __HAL_TIM_DISABLE_IT(&self->timer->tim, TIMER_IRQ_MASK(self->channel)); self->callback = mp_const_none; } else if (mp_obj_is_callable(callback)) { self->callback = callback; __HAL_TIM_CLEAR_IT(&self->timer->tim, TIMER_IRQ_MASK(self->channel)); #if defined(TIM1) if (self->timer->tim_id == 1) { HAL_NVIC_EnableIRQ(TIM1_CC_IRQn); } else #endif #if defined(TIM8) // STM32F401 doesn't have a TIM8 if (self->timer->tim_id == 8) { HAL_NVIC_EnableIRQ(TIM8_CC_IRQn); } else #endif { HAL_NVIC_EnableIRQ(self->timer->irqn); } // start timer, so that it interrupts on overflow switch (self->mode) { case CHANNEL_MODE_PWM_NORMAL: case CHANNEL_MODE_PWM_INVERTED: HAL_TIM_PWM_Start_IT(&self->timer->tim, TIMER_CHANNEL(self)); break; case CHANNEL_MODE_OC_TIMING: case CHANNEL_MODE_OC_ACTIVE: case CHANNEL_MODE_OC_INACTIVE: case CHANNEL_MODE_OC_TOGGLE: case CHANNEL_MODE_OC_FORCED_ACTIVE: case CHANNEL_MODE_OC_FORCED_INACTIVE: HAL_TIM_OC_Start_IT(&self->timer->tim, TIMER_CHANNEL(self)); break; case CHANNEL_MODE_IC: HAL_TIM_IC_Start_IT(&self->timer->tim, TIMER_CHANNEL(self)); break; } } else { mp_raise_ValueError("callback must be None or a callable object"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_timer_channel_callback_obj, pyb_timer_channel_callback); STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&pyb_timer_channel_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_pulse_width), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) }, { MP_ROM_QSTR(MP_QSTR_pulse_width_percent), MP_ROM_PTR(&pyb_timer_channel_pulse_width_percent_obj) }, { MP_ROM_QSTR(MP_QSTR_capture), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) }, { MP_ROM_QSTR(MP_QSTR_compare), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table); STATIC const mp_obj_type_t pyb_timer_channel_type = { { &mp_type_type }, .name = MP_QSTR_TimerChannel, .print = pyb_timer_channel_print, .locals_dict = (mp_obj_dict_t*)&pyb_timer_channel_locals_dict, }; STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_obj_t callback) { uint32_t irq_mask = TIMER_IRQ_MASK(channel); if (__HAL_TIM_GET_FLAG(&tim->tim, irq_mask) != RESET) { if (__HAL_TIM_GET_IT_SOURCE(&tim->tim, irq_mask) != RESET) { // clear the interrupt __HAL_TIM_CLEAR_IT(&tim->tim, irq_mask); // execute callback if it's set if (callback != mp_const_none) { mp_sched_lock(); // When executing code within a handler we must lock the GC to prevent // any memory allocations. We must also catch any exceptions. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_1(callback, MP_OBJ_FROM_PTR(tim)); nlr_pop(); } else { // Uncaught exception; disable the callback so it doesn't run again. tim->callback = mp_const_none; __HAL_TIM_DISABLE_IT(&tim->tim, irq_mask); if (channel == 0) { mp_printf(MICROPY_ERROR_PRINTER, "uncaught exception in Timer(%u) interrupt handler\n", tim->tim_id); } else { mp_printf(MICROPY_ERROR_PRINTER, "uncaught exception in Timer(%u) channel %u interrupt handler\n", tim->tim_id, channel); } mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } gc_unlock(); mp_sched_unlock(); } } } } void timer_irq_handler(uint tim_id) { if (tim_id - 1 < PYB_TIMER_OBJ_ALL_NUM) { // get the timer object pyb_timer_obj_t *tim = MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1]; if (tim == NULL) { // Timer object has not been set, so we can't do anything. // This can happen under normal circumstances for timers like // 1 & 10 which use the same IRQ. return; } // Check for timer (versus timer channel) interrupt. timer_handle_irq_channel(tim, 0, tim->callback); uint32_t handled = TIMER_IRQ_MASK(0); // Check to see if a timer channel interrupt was pending pyb_timer_channel_obj_t *chan = tim->channel; while (chan != NULL) { timer_handle_irq_channel(tim, chan->channel, chan->callback); handled |= TIMER_IRQ_MASK(chan->channel); chan = chan->next; } // Finally, clear any remaining interrupt sources. Otherwise we'll // just get called continuously. uint32_t unhandled = tim->tim.Instance->DIER & 0xff & ~handled; if (unhandled != 0) { __HAL_TIM_DISABLE_IT(&tim->tim, unhandled); __HAL_TIM_CLEAR_IT(&tim->tim, unhandled); mp_printf(MICROPY_ERROR_PRINTER, "unhandled interrupt SR=0x%02x (now disabled)\n", (unsigned int)unhandled); } } } micropython-1.12/ports/stm32/timer.h000066400000000000000000000032471357706137100174400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_TIMER_H #define MICROPY_INCLUDED_STM32_TIMER_H extern TIM_HandleTypeDef TIM5_Handle; extern const mp_obj_type_t pyb_timer_type; void timer_init0(void); void timer_tim5_init(void); TIM_HandleTypeDef *timer_tim6_init(uint freq); void timer_deinit(void); uint32_t timer_get_source_freq(uint32_t tim_id); void timer_irq_handler(uint tim_id); TIM_HandleTypeDef *pyb_timer_get_handle(mp_obj_t timer); #endif // MICROPY_INCLUDED_STM32_TIMER_H micropython-1.12/ports/stm32/uart.c000066400000000000000000000670231357706137100172700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "lib/utils/interrupt_char.h" #include "lib/utils/mpirq.h" #include "uart.h" #include "irq.h" #include "pendsv.h" #if defined(STM32F4) #define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE) #elif defined(STM32H7) #define UART_RXNE_IS_SET(uart) ((uart)->ISR & USART_ISR_RXNE_RXFNE) #else #define UART_RXNE_IS_SET(uart) ((uart)->ISR & USART_ISR_RXNE) #endif #define UART_RXNE_IT_EN(uart) do { (uart)->CR1 |= USART_CR1_RXNEIE; } while (0) #define UART_RXNE_IT_DIS(uart) do { (uart)->CR1 &= ~USART_CR1_RXNEIE; } while (0) #define USART_CR1_IE_BASE (USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE | USART_CR1_IDLEIE) #define USART_CR2_IE_BASE (USART_CR2_LBDIE) #define USART_CR3_IE_BASE (USART_CR3_CTSIE | USART_CR3_EIE) #if defined(STM32F0) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) #elif defined(STM32F4) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE) #elif defined(STM32F7) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #if defined(USART_CR3_TCBGTIE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_TCBGTIE) #else #define USART_CR3_IE_ALL (USART_CR3_IE_BASE) #endif #elif defined(STM32H7) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_RXFFIE | USART_CR1_TXFEIE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_RXFTIE | USART_CR3_TCBGTIE | USART_CR3_TXFTIE | USART_CR3_WUFIE) #elif defined(STM32L0) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) #elif defined(STM32L4) || defined(STM32WB) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #if defined(USART_CR3_TCBGTIE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_TCBGTIE | USART_CR3_WUFIE) #else #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) #endif #endif extern void NORETURN __fatal_error(const char *msg); void uart_init0(void) { #if defined(STM32H7) RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0}; // Configure USART1/6 clock source RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART16; RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2; if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) { __fatal_error("HAL_RCCEx_PeriphCLKConfig"); } // Configure USART2/3/4/5/7/8 clock source RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART234578; RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1; if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) { __fatal_error("HAL_RCCEx_PeriphCLKConfig"); } #endif } // unregister all interrupt sources void uart_deinit_all(void) { for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all)); i++) { pyb_uart_obj_t *uart_obj = MP_STATE_PORT(pyb_uart_obj_all)[i]; if (uart_obj != NULL && !uart_obj->is_static) { uart_deinit(uart_obj); MP_STATE_PORT(pyb_uart_obj_all)[i] = NULL; } } } bool uart_exists(int uart_id) { if (uart_id > MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all))) { // safeguard against pyb_uart_obj_all array being configured too small return false; } switch (uart_id) { #if defined(MICROPY_HW_UART1_TX) && defined(MICROPY_HW_UART1_RX) case PYB_UART_1: return true; #endif #if defined(MICROPY_HW_UART2_TX) && defined(MICROPY_HW_UART2_RX) case PYB_UART_2: return true; #endif #if defined(MICROPY_HW_UART3_TX) && defined(MICROPY_HW_UART3_RX) case PYB_UART_3: return true; #endif #if defined(MICROPY_HW_UART4_TX) && defined(MICROPY_HW_UART4_RX) case PYB_UART_4: return true; #endif #if defined(MICROPY_HW_UART5_TX) && defined(MICROPY_HW_UART5_RX) case PYB_UART_5: return true; #endif #if defined(MICROPY_HW_UART6_TX) && defined(MICROPY_HW_UART6_RX) case PYB_UART_6: return true; #endif #if defined(MICROPY_HW_UART7_TX) && defined(MICROPY_HW_UART7_RX) case PYB_UART_7: return true; #endif #if defined(MICROPY_HW_UART8_TX) && defined(MICROPY_HW_UART8_RX) case PYB_UART_8: return true; #endif #if defined(MICROPY_HW_UART9_TX) && defined(MICROPY_HW_UART9_RX) case PYB_UART_9: return true; #endif #if defined(MICROPY_HW_UART10_TX) && defined(MICROPY_HW_UART10_RX) case PYB_UART_10: return true; #endif default: return false; } } // assumes Init parameters have been set up correctly bool uart_init(pyb_uart_obj_t *uart_obj, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop, uint32_t flow) { USART_TypeDef *UARTx; IRQn_Type irqn; int uart_unit; const pin_obj_t *pins[4] = {0}; switch (uart_obj->uart_id) { #if defined(MICROPY_HW_UART1_TX) && defined(MICROPY_HW_UART1_RX) case PYB_UART_1: uart_unit = 1; UARTx = USART1; irqn = USART1_IRQn; pins[0] = MICROPY_HW_UART1_TX; pins[1] = MICROPY_HW_UART1_RX; __HAL_RCC_USART1_CLK_ENABLE(); break; #endif #if defined(MICROPY_HW_UART2_TX) && defined(MICROPY_HW_UART2_RX) case PYB_UART_2: uart_unit = 2; UARTx = USART2; irqn = USART2_IRQn; pins[0] = MICROPY_HW_UART2_TX; pins[1] = MICROPY_HW_UART2_RX; #if defined(MICROPY_HW_UART2_RTS) if (flow & UART_HWCONTROL_RTS) { pins[2] = MICROPY_HW_UART2_RTS; } #endif #if defined(MICROPY_HW_UART2_CTS) if (flow & UART_HWCONTROL_CTS) { pins[3] = MICROPY_HW_UART2_CTS; } #endif __HAL_RCC_USART2_CLK_ENABLE(); break; #endif #if defined(MICROPY_HW_UART3_TX) && defined(MICROPY_HW_UART3_RX) case PYB_UART_3: uart_unit = 3; UARTx = USART3; #if defined(STM32F0) irqn = USART3_8_IRQn; #else irqn = USART3_IRQn; #endif pins[0] = MICROPY_HW_UART3_TX; pins[1] = MICROPY_HW_UART3_RX; #if defined(MICROPY_HW_UART3_RTS) if (flow & UART_HWCONTROL_RTS) { pins[2] = MICROPY_HW_UART3_RTS; } #endif #if defined(MICROPY_HW_UART3_CTS) if (flow & UART_HWCONTROL_CTS) { pins[3] = MICROPY_HW_UART3_CTS; } #endif __HAL_RCC_USART3_CLK_ENABLE(); break; #endif #if defined(MICROPY_HW_UART4_TX) && defined(MICROPY_HW_UART4_RX) case PYB_UART_4: uart_unit = 4; #if defined(STM32F0) UARTx = USART4; irqn = USART3_8_IRQn; __HAL_RCC_USART4_CLK_ENABLE(); #elif defined(STM32L0) UARTx = USART4; irqn = USART4_5_IRQn; __HAL_RCC_USART4_CLK_ENABLE(); #else UARTx = UART4; irqn = UART4_IRQn; __HAL_RCC_UART4_CLK_ENABLE(); #endif pins[0] = MICROPY_HW_UART4_TX; pins[1] = MICROPY_HW_UART4_RX; #if defined(MICROPY_HW_UART4_RTS) if (flow & UART_HWCONTROL_RTS) { pins[2] = MICROPY_HW_UART4_RTS; } #endif #if defined(MICROPY_HW_UART4_CTS) if (flow & UART_HWCONTROL_CTS) { pins[3] = MICROPY_HW_UART4_CTS; } #endif break; #endif #if defined(MICROPY_HW_UART5_TX) && defined(MICROPY_HW_UART5_RX) case PYB_UART_5: uart_unit = 5; #if defined(STM32F0) UARTx = USART5; irqn = USART3_8_IRQn; __HAL_RCC_USART5_CLK_ENABLE(); #elif defined(STM32L0) UARTx = USART5; irqn = USART4_5_IRQn; __HAL_RCC_USART5_CLK_ENABLE(); #else UARTx = UART5; irqn = UART5_IRQn; __HAL_RCC_UART5_CLK_ENABLE(); #endif pins[0] = MICROPY_HW_UART5_TX; pins[1] = MICROPY_HW_UART5_RX; break; #endif #if defined(MICROPY_HW_UART6_TX) && defined(MICROPY_HW_UART6_RX) case PYB_UART_6: uart_unit = 6; UARTx = USART6; #if defined(STM32F0) irqn = USART3_8_IRQn; #else irqn = USART6_IRQn; #endif pins[0] = MICROPY_HW_UART6_TX; pins[1] = MICROPY_HW_UART6_RX; #if defined(MICROPY_HW_UART6_RTS) if (flow & UART_HWCONTROL_RTS) { pins[2] = MICROPY_HW_UART6_RTS; } #endif #if defined(MICROPY_HW_UART6_CTS) if (flow & UART_HWCONTROL_CTS) { pins[3] = MICROPY_HW_UART6_CTS; } #endif __HAL_RCC_USART6_CLK_ENABLE(); break; #endif #if defined(MICROPY_HW_UART7_TX) && defined(MICROPY_HW_UART7_RX) case PYB_UART_7: uart_unit = 7; #if defined(STM32F0) UARTx = USART7; irqn = USART3_8_IRQn; __HAL_RCC_USART7_CLK_ENABLE(); #else UARTx = UART7; irqn = UART7_IRQn; __HAL_RCC_UART7_CLK_ENABLE(); #endif pins[0] = MICROPY_HW_UART7_TX; pins[1] = MICROPY_HW_UART7_RX; break; #endif #if defined(MICROPY_HW_UART8_TX) && defined(MICROPY_HW_UART8_RX) case PYB_UART_8: uart_unit = 8; #if defined(STM32F0) UARTx = USART8; irqn = USART3_8_IRQn; __HAL_RCC_USART8_CLK_ENABLE(); #else UARTx = UART8; irqn = UART8_IRQn; __HAL_RCC_UART8_CLK_ENABLE(); #endif pins[0] = MICROPY_HW_UART8_TX; pins[1] = MICROPY_HW_UART8_RX; break; #endif #if defined(MICROPY_HW_UART9_TX) && defined(MICROPY_HW_UART9_RX) case PYB_UART_9: uart_unit = 9; UARTx = UART9; irqn = UART9_IRQn; __HAL_RCC_UART9_CLK_ENABLE(); pins[0] = MICROPY_HW_UART9_TX; pins[1] = MICROPY_HW_UART9_RX; break; #endif #if defined(MICROPY_HW_UART10_TX) && defined(MICROPY_HW_UART10_RX) case PYB_UART_10: uart_unit = 10; UARTx = UART10; irqn = UART10_IRQn; __HAL_RCC_UART10_CLK_ENABLE(); pins[0] = MICROPY_HW_UART10_TX; pins[1] = MICROPY_HW_UART10_RX; break; #endif default: // UART does not exist or is not configured for this board return false; } uint32_t mode = MP_HAL_PIN_MODE_ALT; uint32_t pull = MP_HAL_PIN_PULL_UP; for (uint i = 0; i < 4; i++) { if (pins[i] != NULL) { bool ret = mp_hal_pin_config_alt(pins[i], mode, pull, AF_FN_UART, uart_unit); if (!ret) { return false; } } } uart_obj->uartx = UARTx; // init UARTx UART_HandleTypeDef huart; memset(&huart, 0, sizeof(huart)); huart.Instance = UARTx; huart.Init.BaudRate = baudrate; huart.Init.WordLength = bits; huart.Init.StopBits = stop; huart.Init.Parity = parity; huart.Init.Mode = UART_MODE_TX_RX; huart.Init.HwFlowCtl = flow; huart.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&huart); // Disable all individual UART IRQs, but enable the global handler uart_obj->uartx->CR1 &= ~USART_CR1_IE_ALL; uart_obj->uartx->CR2 &= ~USART_CR2_IE_ALL; uart_obj->uartx->CR3 &= ~USART_CR3_IE_ALL; NVIC_SetPriority(IRQn_NONNEG(irqn), IRQ_PRI_UART); HAL_NVIC_EnableIRQ(irqn); uart_obj->is_enabled = true; uart_obj->attached_to_repl = false; if (bits == UART_WORDLENGTH_9B && parity == UART_PARITY_NONE) { uart_obj->char_mask = 0x1ff; uart_obj->char_width = CHAR_WIDTH_9BIT; } else { if (bits == UART_WORDLENGTH_9B || parity == UART_PARITY_NONE) { uart_obj->char_mask = 0xff; } else { uart_obj->char_mask = 0x7f; } uart_obj->char_width = CHAR_WIDTH_8BIT; } uart_obj->mp_irq_trigger = 0; uart_obj->mp_irq_obj = NULL; return true; } void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf) { self->read_buf_head = 0; self->read_buf_tail = 0; self->read_buf_len = len; self->read_buf = buf; if (len == 0) { UART_RXNE_IT_DIS(self->uartx); } else { UART_RXNE_IT_EN(self->uartx); } } void uart_deinit(pyb_uart_obj_t *self) { self->is_enabled = false; // Disable UART self->uartx->CR1 &= ~USART_CR1_UE; // Reset and turn off the UART peripheral if (self->uart_id == 1) { HAL_NVIC_DisableIRQ(USART1_IRQn); __HAL_RCC_USART1_FORCE_RESET(); __HAL_RCC_USART1_RELEASE_RESET(); __HAL_RCC_USART1_CLK_DISABLE(); #if defined(USART2) } else if (self->uart_id == 2) { HAL_NVIC_DisableIRQ(USART2_IRQn); __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); __HAL_RCC_USART2_CLK_DISABLE(); #endif #if defined(USART3) } else if (self->uart_id == 3) { #if !defined(STM32F0) HAL_NVIC_DisableIRQ(USART3_IRQn); #endif __HAL_RCC_USART3_FORCE_RESET(); __HAL_RCC_USART3_RELEASE_RESET(); __HAL_RCC_USART3_CLK_DISABLE(); #endif #if defined(UART4) } else if (self->uart_id == 4) { HAL_NVIC_DisableIRQ(UART4_IRQn); __HAL_RCC_UART4_FORCE_RESET(); __HAL_RCC_UART4_RELEASE_RESET(); __HAL_RCC_UART4_CLK_DISABLE(); #endif #if defined(USART4) } else if (self->uart_id == 4) { __HAL_RCC_USART4_FORCE_RESET(); __HAL_RCC_USART4_RELEASE_RESET(); __HAL_RCC_USART4_CLK_DISABLE(); #endif #if defined(UART5) } else if (self->uart_id == 5) { HAL_NVIC_DisableIRQ(UART5_IRQn); __HAL_RCC_UART5_FORCE_RESET(); __HAL_RCC_UART5_RELEASE_RESET(); __HAL_RCC_UART5_CLK_DISABLE(); #endif #if defined(USART5) } else if (self->uart_id == 5) { __HAL_RCC_USART5_FORCE_RESET(); __HAL_RCC_USART5_RELEASE_RESET(); __HAL_RCC_USART5_CLK_DISABLE(); #endif #if defined(UART6) } else if (self->uart_id == 6) { HAL_NVIC_DisableIRQ(USART6_IRQn); __HAL_RCC_USART6_FORCE_RESET(); __HAL_RCC_USART6_RELEASE_RESET(); __HAL_RCC_USART6_CLK_DISABLE(); #endif #if defined(UART7) } else if (self->uart_id == 7) { HAL_NVIC_DisableIRQ(UART7_IRQn); __HAL_RCC_UART7_FORCE_RESET(); __HAL_RCC_UART7_RELEASE_RESET(); __HAL_RCC_UART7_CLK_DISABLE(); #endif #if defined(USART7) } else if (self->uart_id == 7) { __HAL_RCC_USART7_FORCE_RESET(); __HAL_RCC_USART7_RELEASE_RESET(); __HAL_RCC_USART7_CLK_DISABLE(); #endif #if defined(UART8) } else if (self->uart_id == 8) { HAL_NVIC_DisableIRQ(UART8_IRQn); __HAL_RCC_UART8_FORCE_RESET(); __HAL_RCC_UART8_RELEASE_RESET(); __HAL_RCC_UART8_CLK_DISABLE(); #endif #if defined(USART8) } else if (self->uart_id == 8) { __HAL_RCC_USART8_FORCE_RESET(); __HAL_RCC_USART8_RELEASE_RESET(); __HAL_RCC_USART8_CLK_DISABLE(); #endif #if defined(UART9) } else if (self->uart_id == 9) { HAL_NVIC_DisableIRQ(UART9_IRQn); __HAL_RCC_UART9_FORCE_RESET(); __HAL_RCC_UART9_RELEASE_RESET(); __HAL_RCC_UART9_CLK_DISABLE(); #endif #if defined(UART10) } else if (self->uart_id == 10) { HAL_NVIC_DisableIRQ(UART10_IRQn); __HAL_RCC_UART10_FORCE_RESET(); __HAL_RCC_UART10_RELEASE_RESET(); __HAL_RCC_UART10_CLK_DISABLE(); #endif } } void uart_attach_to_repl(pyb_uart_obj_t *self, bool attached) { self->attached_to_repl = attached; } uint32_t uart_get_baudrate(pyb_uart_obj_t *self) { uint32_t uart_clk = 0; #if defined(STM32F0) uart_clk = HAL_RCC_GetPCLK1Freq(); #elif defined(STM32F7) switch ((RCC->DCKCFGR2 >> ((self->uart_id - 1) * 2)) & 3) { case 0: if (self->uart_id == 1 || self->uart_id == 6) { uart_clk = HAL_RCC_GetPCLK2Freq(); } else { uart_clk = HAL_RCC_GetPCLK1Freq(); } break; case 1: uart_clk = HAL_RCC_GetSysClockFreq(); break; case 2: uart_clk = HSI_VALUE; break; case 3: uart_clk = LSE_VALUE; break; } #elif defined(STM32H7) uint32_t csel; if (self->uart_id == 1 || self->uart_id == 6) { csel = RCC->D2CCIP2R >> 3; } else { csel = RCC->D2CCIP2R; } switch (csel & 3) { case 0: if (self->uart_id == 1 || self->uart_id == 6) { uart_clk = HAL_RCC_GetPCLK2Freq(); } else { uart_clk = HAL_RCC_GetPCLK1Freq(); } break; case 3: uart_clk = HSI_VALUE; break; case 4: uart_clk = CSI_VALUE; break; case 5: uart_clk = LSE_VALUE; break; default: break; } #else if (self->uart_id == 1 #if defined(USART6) || self->uart_id == 6 #endif #if defined(UART9) || self->uart_id == 9 #endif #if defined(UART10) || self->uart_id == 10 #endif ) { uart_clk = HAL_RCC_GetPCLK2Freq(); } else { uart_clk = HAL_RCC_GetPCLK1Freq(); } #endif // This formula assumes UART_OVERSAMPLING_16 uint32_t baudrate = uart_clk / self->uartx->BRR; return baudrate; } mp_uint_t uart_rx_any(pyb_uart_obj_t *self) { int buffer_bytes = self->read_buf_head - self->read_buf_tail; if (buffer_bytes < 0) { return buffer_bytes + self->read_buf_len; } else if (buffer_bytes > 0) { return buffer_bytes; } else { return UART_RXNE_IS_SET(self->uartx) != 0; } } // Waits at most timeout milliseconds for at least 1 char to become ready for // reading (from buf or for direct reading). // Returns true if something available, false if not. bool uart_rx_wait(pyb_uart_obj_t *self, uint32_t timeout) { uint32_t start = HAL_GetTick(); for (;;) { if (self->read_buf_tail != self->read_buf_head || UART_RXNE_IS_SET(self->uartx)) { return true; // have at least 1 char ready for reading } if (HAL_GetTick() - start >= timeout) { return false; // timeout } MICROPY_EVENT_POLL_HOOK } } // assumes there is a character available int uart_rx_char(pyb_uart_obj_t *self) { if (self->read_buf_tail != self->read_buf_head) { // buffering via IRQ int data; if (self->char_width == CHAR_WIDTH_9BIT) { data = ((uint16_t*)self->read_buf)[self->read_buf_tail]; } else { data = self->read_buf[self->read_buf_tail]; } self->read_buf_tail = (self->read_buf_tail + 1) % self->read_buf_len; if (UART_RXNE_IS_SET(self->uartx)) { // UART was stalled by flow ctrl: re-enable IRQ now we have room in buffer UART_RXNE_IT_EN(self->uartx); } return data; } else { // no buffering #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) int data = self->uartx->RDR & self->char_mask; self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set return data; #else return self->uartx->DR & self->char_mask; #endif } } // Waits at most timeout milliseconds for TX register to become empty. // Returns true if can write, false if can't. bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout) { uint32_t start = HAL_GetTick(); for (;;) { if (uart_tx_avail(self)) { return true; // tx register is empty } if (HAL_GetTick() - start >= timeout) { return false; // timeout } MICROPY_EVENT_POLL_HOOK } } // Waits at most timeout milliseconds for UART flag to be set. // Returns true if flag is/was set, false on timeout. STATIC bool uart_wait_flag_set(pyb_uart_obj_t *self, uint32_t flag, uint32_t timeout) { // Note: we don't use WFI to idle in this loop because UART tx doesn't generate // an interrupt and the flag can be set quickly if the baudrate is large. uint32_t start = HAL_GetTick(); for (;;) { #if defined(STM32F4) if (self->uartx->SR & flag) { return true; } #else if (self->uartx->ISR & flag) { return true; } #endif if (timeout == 0 || HAL_GetTick() - start >= timeout) { return false; // timeout } } } // src - a pointer to the data to send (16-bit aligned for 9-bit chars) // num_chars - number of characters to send (9-bit chars count for 2 bytes from src) // *errcode - returns 0 for success, MP_Exxx on error // returns the number of characters sent (valid even if there was an error) size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, int *errcode) { if (num_chars == 0) { *errcode = 0; return 0; } uint32_t timeout; if (self->uartx->CR3 & USART_CR3_CTSE) { // CTS can hold off transmission for an arbitrarily long time. Apply // the overall timeout rather than the character timeout. timeout = self->timeout; } else { // The timeout specified here is for waiting for the TX data register to // become empty (ie between chars), as well as for the final char to be // completely transferred. The default value for timeout_char is long // enough for 1 char, but we need to double it to wait for the last char // to be transferred to the data register, and then to be transmitted. timeout = 2 * self->timeout_char; } const uint8_t *src = (const uint8_t*)src_in; size_t num_tx = 0; USART_TypeDef *uart = self->uartx; while (num_tx < num_chars) { if (!uart_wait_flag_set(self, UART_FLAG_TXE, timeout)) { *errcode = MP_ETIMEDOUT; return num_tx; } uint32_t data; if (self->char_width == CHAR_WIDTH_9BIT) { data = *((uint16_t*)src) & 0x1ff; src += 2; } else { data = *src++; } #if defined(STM32F4) uart->DR = data; #else uart->TDR = data; #endif ++num_tx; } // wait for the UART frame to complete if (!uart_wait_flag_set(self, UART_FLAG_TC, timeout)) { *errcode = MP_ETIMEDOUT; return num_tx; } *errcode = 0; return num_tx; } void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len) { int errcode; uart_tx_data(uart_obj, str, len, &errcode); } // this IRQ handler is set up to handle RXNE interrupts only void uart_irq_handler(mp_uint_t uart_id) { // get the uart object pyb_uart_obj_t *self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1]; if (self == NULL) { // UART object has not been set, so we can't do anything, not // even disable the IRQ. This should never happen. return; } if (UART_RXNE_IS_SET(self->uartx)) { if (self->read_buf_len != 0) { uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len; if (next_head != self->read_buf_tail) { // only read data if room in buf #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) int data = self->uartx->RDR; // clears UART_FLAG_RXNE self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set #else int data = self->uartx->DR; // clears UART_FLAG_RXNE #endif data &= self->char_mask; if (self->attached_to_repl && data == mp_interrupt_char) { // Handle interrupt coming in on a UART REPL pendsv_kbd_intr(); } else { if (self->char_width == CHAR_WIDTH_9BIT) { ((uint16_t*)self->read_buf)[self->read_buf_head] = data; } else { self->read_buf[self->read_buf_head] = data; } self->read_buf_head = next_head; } } else { // No room: leave char in buf, disable interrupt UART_RXNE_IT_DIS(self->uartx); } } } // If RXNE is clear but ORE set then clear the ORE flag (it's tied to RXNE IRQ) #if defined(STM32F4) else if (self->uartx->SR & USART_SR_ORE) { (void)self->uartx->DR; } #else else if (self->uartx->ISR & USART_ISR_ORE) { self->uartx->ICR = USART_ICR_ORECF; } #endif // Set user IRQ flags self->mp_irq_flags = 0; #if defined(STM32F4) if (self->uartx->SR & USART_SR_IDLE) { (void)self->uartx->SR; (void)self->uartx->DR; self->mp_irq_flags |= UART_FLAG_IDLE; } #else if (self->uartx->ISR & USART_ISR_IDLE) { self->uartx->ICR = USART_ICR_IDLECF; self->mp_irq_flags |= UART_FLAG_IDLE; } #endif // Check the flags to see if the user handler should be called if (self->mp_irq_trigger & self->mp_irq_flags) { mp_irq_handler(self->mp_irq_obj); } } micropython-1.12/ports/stm32/uart.h000066400000000000000000000075571357706137100173030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_UART_H #define MICROPY_INCLUDED_STM32_UART_H struct _mp_irq_obj_t; typedef enum { PYB_UART_NONE = 0, PYB_UART_1 = 1, PYB_UART_2 = 2, PYB_UART_3 = 3, PYB_UART_4 = 4, PYB_UART_5 = 5, PYB_UART_6 = 6, PYB_UART_7 = 7, PYB_UART_8 = 8, PYB_UART_9 = 9, PYB_UART_10 = 10, } pyb_uart_t; #define CHAR_WIDTH_8BIT (0) #define CHAR_WIDTH_9BIT (1) typedef struct _pyb_uart_obj_t { mp_obj_base_t base; USART_TypeDef *uartx; pyb_uart_t uart_id : 8; bool is_static : 1; bool is_enabled : 1; bool attached_to_repl; // whether the UART is attached to REPL byte char_width; // 0 for 7,8 bit chars, 1 for 9 bit chars uint16_t char_mask; // 0x7f for 7 bit, 0xff for 8 bit, 0x1ff for 9 bit uint16_t timeout; // timeout waiting for first char uint16_t timeout_char; // timeout waiting between chars uint16_t read_buf_len; // len in chars; buf can hold len-1 chars volatile uint16_t read_buf_head; // indexes first empty slot uint16_t read_buf_tail; // indexes first full slot (not full if equals head) byte *read_buf; // byte or uint16_t, depending on char size uint16_t mp_irq_trigger; // user IRQ trigger mask uint16_t mp_irq_flags; // user IRQ active IRQ flags struct _mp_irq_obj_t *mp_irq_obj; // user IRQ object } pyb_uart_obj_t; extern const mp_obj_type_t pyb_uart_type; void uart_init0(void); void uart_deinit_all(void); bool uart_exists(int uart_id); bool uart_init(pyb_uart_obj_t *uart_obj, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop, uint32_t flow); void uart_set_rxbuf(pyb_uart_obj_t *self, size_t len, void *buf); void uart_deinit(pyb_uart_obj_t *uart_obj); void uart_irq_handler(mp_uint_t uart_id); void uart_attach_to_repl(pyb_uart_obj_t *self, bool attached); uint32_t uart_get_baudrate(pyb_uart_obj_t *self); mp_uint_t uart_rx_any(pyb_uart_obj_t *uart_obj); bool uart_rx_wait(pyb_uart_obj_t *self, uint32_t timeout); int uart_rx_char(pyb_uart_obj_t *uart_obj); bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout); size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars, int *errcode); void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); static inline bool uart_tx_avail(pyb_uart_obj_t *self) { #if defined(STM32F4) return self->uartx->SR & USART_SR_TXE; #elif defined(STM32H7) return self->uartx->ISR & USART_ISR_TXE_TXFNF; #else return self->uartx->ISR & USART_ISR_TXE; #endif } #endif // MICROPY_INCLUDED_STM32_UART_H micropython-1.12/ports/stm32/usb.c000066400000000000000000001072701357706137100171050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014, 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "usbd_core.h" #include "usbd_desc.h" #include "usbd_cdc_msc_hid.h" #include "usbd_cdc_interface.h" #include "usbd_msc_interface.h" #include "usbd_hid_interface.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "bufhelper.h" #include "storage.h" #include "sdcard.h" #include "usb.h" #if MICROPY_HW_ENABLE_USB // Work out which USB device to use as the main one (the one with the REPL) #if !defined(MICROPY_HW_USB_MAIN_DEV) #if defined(MICROPY_HW_USB_FS) #define MICROPY_HW_USB_MAIN_DEV (USB_PHY_FS_ID) #elif defined(MICROPY_HW_USB_HS) #define MICROPY_HW_USB_MAIN_DEV (USB_PHY_HS_ID) #else #error Unable to determine proper MICROPY_HW_USB_MAIN_DEV to use #endif #endif // Maximum number of endpoints (excluding EP0) #if defined(STM32L0) || defined(STM32WB) #define MAX_ENDPOINT(dev_id) (7) #elif defined(STM32L4) #define MAX_ENDPOINT(dev_id) (5) #elif defined(STM32F4) #define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 3 : 5) #elif defined(STM32F7) #define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 5 : 8) #elif defined(STM32H7) #define MAX_ENDPOINT(dev_id) (8) #endif STATIC void pyb_usb_vcp_init0(void); // this will be persistent across a soft-reset mp_uint_t pyb_usb_flags = 0; typedef struct _usb_device_t { uint32_t enabled; USBD_HandleTypeDef hUSBDDevice; usbd_cdc_msc_hid_state_t usbd_cdc_msc_hid_state; usbd_cdc_itf_t usbd_cdc_itf[MICROPY_HW_USB_CDC_NUM]; #if MICROPY_HW_USB_HID usbd_hid_itf_t usbd_hid_itf; #endif } usb_device_t; usb_device_t usb_device = {0}; pyb_usb_storage_medium_t pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_NONE; #if !MICROPY_HW_USB_IS_MULTI_OTG // Units of FIFO size arrays below are 4x 16-bit words = 8 bytes // There are 512x 16-bit words it total to use here (when using PCD_SNG_BUF) // EP0(out), EP0(in), MSC/HID(out), MSC/HID(in), unused, CDC_CMD(in), CDC_DATA(out), CDC_DATA(in) STATIC const uint8_t usbd_fifo_size_cdc1[] = {16, 16, 16, 16, 0, 16, 16, 16}; #else // Units of FIFO size arrays below are 4x 32-bit words = 16 bytes // FS: there are 320x 32-bit words in total to use here // HS: there are 1024x 32-bit words in total to use here // RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA STATIC const uint8_t usbd_fifo_size_cdc1[] = { 32, 8, 16, 8, 16, 0, 0, // FS: RX, EP0(in), 5x IN endpoints #if MICROPY_HW_USB_HS 116, 8, 64, 4, 64, 0, 0, 0, 0, 0, // HS: RX, EP0(in), 8x IN endpoints #endif }; // RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, HID STATIC const uint8_t usbd_fifo_size_cdc1_msc_hid[] = { 32, 8, 16, 4, 12, 8, 0, #if MICROPY_HW_USB_HS 116, 8, 64, 4, 56, 8, 0, 0, 0, 0, #endif }; #if MICROPY_HW_USB_CDC_NUM >= 2 // RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD, CDC2_DATA STATIC const uint8_t usbd_fifo_size_cdc2[] = { 32, 8, 16, 4, 8, 4, 8, #if MICROPY_HW_USB_HS 116, 8, 64, 2, 32, 2, 32, 0, 0, 0, #endif }; // RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD/HID, CDC2_DATA, HID STATIC const uint8_t usbd_fifo_size_cdc2_msc_hid[] = { 0, 0, 0, 0, 0, 0, 0, // FS: can't support 2xVCP+MSC+HID #if MICROPY_HW_USB_HS 102, 8, 64, 2, 32, 8, 32, 8, 0, 0, #endif }; #endif #if MICROPY_HW_USB_CDC_NUM >= 3 // RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD, CDC2_DATA, CDC3_CMD, CDC3_DATA STATIC const uint8_t usbd_fifo_size_cdc3[] = { 0, 0, 0, 0, 0, 0, 0, // FS: can't support 3x VCP mode #if MICROPY_HW_USB_HS 82, 8, 64, 2, 32, 2, 32, 2, 32, 0, #endif }; // RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD/HID, CDC2_DATA, CDC3_CMD/HID, CDC3_DATA, HID STATIC const uint8_t usbd_fifo_size_cdc3_msc_hid[] = { 0, 0, 0, 0, 0, 0, 0, // FS: can't support 3x VCP mode #if MICROPY_HW_USB_HS 82, 8, 64, 2, 25, 8, 25, 8, 25, 8, #endif }; #endif #endif #if MICROPY_HW_USB_HID // predefined hid mouse data STATIC const mp_obj_str_t pyb_usb_hid_mouse_desc_obj = { {&mp_type_bytes}, 0, // hash not valid USBD_HID_MOUSE_REPORT_DESC_SIZE, USBD_HID_MOUSE_ReportDesc, }; const mp_rom_obj_tuple_t pyb_usb_hid_mouse_obj = { {&mp_type_tuple}, 5, { MP_ROM_INT(1), // subclass: boot MP_ROM_INT(2), // protocol: mouse MP_ROM_INT(USBD_HID_MOUSE_MAX_PACKET), MP_ROM_INT(8), // polling interval: 8ms MP_ROM_PTR(&pyb_usb_hid_mouse_desc_obj), }, }; // predefined hid keyboard data STATIC const mp_obj_str_t pyb_usb_hid_keyboard_desc_obj = { {&mp_type_bytes}, 0, // hash not valid USBD_HID_KEYBOARD_REPORT_DESC_SIZE, USBD_HID_KEYBOARD_ReportDesc, }; const mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj = { {&mp_type_tuple}, 5, { MP_ROM_INT(1), // subclass: boot MP_ROM_INT(1), // protocol: keyboard MP_ROM_INT(USBD_HID_KEYBOARD_MAX_PACKET), MP_ROM_INT(8), // polling interval: 8ms MP_ROM_PTR(&pyb_usb_hid_keyboard_desc_obj), }, }; #endif void pyb_usb_init0(void) { for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { usb_device.usbd_cdc_itf[i].attached_to_repl = false; } MP_STATE_PORT(pyb_hid_report_desc) = MP_OBJ_NULL; pyb_usb_vcp_init0(); } int pyb_usb_dev_detect(void) { if (usb_device.enabled) { return usb_device.hUSBDDevice.id; } #if MICROPY_HW_USB_FS && MICROPY_HW_USB_HS // Try to auto-detect which USB is connected by reading DP/DM pins for (int i = 0; i < 2; ++i) { mp_hal_pin_obj_t dp = i == 0 ? pyb_pin_USB_DP : pyb_pin_USB_HS_DP; mp_hal_pin_obj_t dm = i == 0 ? pyb_pin_USB_DM : pyb_pin_USB_HS_DM; mp_hal_pin_config(dp, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); mp_hal_pin_config(dm, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); int state = mp_hal_pin_read(dp) == 0 && mp_hal_pin_read(dm) == 0; mp_hal_pin_config(dp, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); mp_hal_pin_config(dm, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); if (state) { // DP and DM pins are actively held low so assume USB is connected return i == 0 ? USB_PHY_FS_ID : USB_PHY_HS_ID; } } #endif return MICROPY_HW_USB_MAIN_DEV; } bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info) { usb_device_t *usb_dev = &usb_device; if (!usb_dev->enabled) { // only init USB once in the device's power-lifetime // set up the USBD state USBD_HandleTypeDef *usbd = &usb_dev->hUSBDDevice; usbd->id = dev_id; usbd->dev_state = USBD_STATE_DEFAULT; usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors; usbd->pClass = &USBD_CDC_MSC_HID; usb_dev->usbd_cdc_msc_hid_state.pdev = usbd; for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { usb_dev->usbd_cdc_msc_hid_state.cdc[i] = &usb_dev->usbd_cdc_itf[i].base; } #if MICROPY_HW_USB_HID usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf.base; #endif usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state; // configure the VID, PID and the USBD mode (interfaces it will expose) int cdc_only = (mode & USBD_MODE_IFACE_MASK) == USBD_MODE_CDC; USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, cdc_only); if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info, MAX_ENDPOINT(dev_id)) != 0) { return false; } #if MICROPY_HW_USB_MSC // Configure the MSC interface const void *msc_unit_default[1]; if (msc_n == 0) { msc_n = 1; msc_unit = msc_unit_default; switch (pyb_usb_storage_medium) { #if MICROPY_HW_ENABLE_SDCARD case PYB_USB_STORAGE_MEDIUM_SDCARD: msc_unit_default[0] = &pyb_sdcard_type; break; #endif default: msc_unit_default[0] = &pyb_flash_type; break; } } usbd_msc_init_lu(msc_n, msc_unit); USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&usbd_msc_fops); #endif const uint8_t *fifo_size = usbd_fifo_size_cdc1; #if MICROPY_HW_USB_IS_MULTI_OTG if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { fifo_size = usbd_fifo_size_cdc1_msc_hid; } #endif #if MICROPY_HW_USB_CDC_NUM >= 3 if (mode & USBD_MODE_IFACE_CDC(2)) { if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { fifo_size = usbd_fifo_size_cdc3_msc_hid; } else { fifo_size = usbd_fifo_size_cdc3; } } else #endif #if MICROPY_HW_USB_CDC_NUM >= 2 if (mode & USBD_MODE_IFACE_CDC(1)) { if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { fifo_size = usbd_fifo_size_cdc2_msc_hid; } else { fifo_size = usbd_fifo_size_cdc2; } } #endif // start the USB device USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0, fifo_size); USBD_LL_Start(usbd); usb_dev->enabled = true; } return true; } void pyb_usb_dev_deinit(void) { usb_device_t *usb_dev = &usb_device; if (usb_dev->enabled) { USBD_Stop(&usb_dev->hUSBDDevice); USBD_DeInit(&usb_dev->hUSBDDevice); usb_dev->enabled = false; } } bool usb_vcp_is_enabled(void) { return usb_device.enabled; } int usb_vcp_recv_byte(uint8_t *c) { return usbd_cdc_rx(&usb_device.usbd_cdc_itf[0], c, 1, 0); } void usb_vcp_send_strn(const char *str, int len) { if (usb_device.enabled) { usbd_cdc_tx_always(&usb_device.usbd_cdc_itf[0], (const uint8_t*)str, len); } } usbd_cdc_itf_t *usb_vcp_get(int idx) { return &usb_device.usbd_cdc_itf[idx]; } /******************************************************************************/ // MicroPython bindings for USB /* Philosophy of USB driver and Python API: pyb.usb_mode(...) configures the USB on the board. The USB itself is not an entity, rather the interfaces are, and can be accessed by creating objects, such as pyb.USB_VCP() and pyb.USB_HID(). We have: pyb.usb_mode() # return the current usb mode pyb.usb_mode(None) # disable USB pyb.usb_mode('VCP') # enable with VCP interface pyb.usb_mode('VCP+MSC') # enable with VCP and MSC interfaces pyb.usb_mode('VCP+HID') # enable with VCP and HID, defaulting to mouse protocol pyb.usb_mode('VCP+HID', vid=0xf055, pid=0x9800) # specify VID and PID pyb.usb_mode('VCP+HID', hid=pyb.hid_mouse) pyb.usb_mode('VCP+HID', hid=pyb.hid_keyboard) pyb.usb_mode('VCP+HID', pid=0x1234, hid=(subclass, protocol, max_packet_len, polling_interval, report_desc)) vcp = pyb.USB_VCP() # get the VCP device for read/write hid = pyb.USB_HID() # get the HID device for write/poll Possible extensions: pyb.usb_mode('host', ...) pyb.usb_mode('OTG', ...) pyb.usb_mode(..., port=2) # for second USB port */ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_port, ARG_vid, ARG_pid, #if MICROPY_HW_USB_MSC ARG_msc, #endif #if MICROPY_HW_USB_HID ARG_hid, #endif #if USBD_SUPPORT_HS_MODE ARG_high_speed #endif }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_vid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = USBD_VID} }, { MP_QSTR_pid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, #if MICROPY_HW_USB_MSC { MP_QSTR_msc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_empty_tuple_obj)} }, #endif #if MICROPY_HW_USB_HID { MP_QSTR_hid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&pyb_usb_hid_mouse_obj)} }, #endif #if USBD_SUPPORT_HS_MODE { MP_QSTR_high_speed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, #endif }; // fetch the current usb mode -> pyb.usb_mode() if (n_args == 0) { #if defined(USE_HOST_MODE) return MP_OBJ_NEW_QSTR(MP_QSTR_host); #else uint8_t mode = USBD_GetMode(&usb_device.usbd_cdc_msc_hid_state); switch (mode & USBD_MODE_IFACE_MASK) { case USBD_MODE_CDC: return MP_OBJ_NEW_QSTR(MP_QSTR_VCP); case USBD_MODE_MSC: return MP_OBJ_NEW_QSTR(MP_QSTR_MSC); case USBD_MODE_HID: return MP_OBJ_NEW_QSTR(MP_QSTR_HID); case USBD_MODE_CDC_MSC: return MP_OBJ_NEW_QSTR(MP_QSTR_VCP_plus_MSC); case USBD_MODE_CDC_HID: return MP_OBJ_NEW_QSTR(MP_QSTR_VCP_plus_HID); case USBD_MODE_MSC_HID: return MP_OBJ_NEW_QSTR(MP_QSTR_MSC_plus_HID); default: return mp_const_none; } #endif } // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // record the fact that the usb has been explicitly configured pyb_usb_flags |= PYB_USB_FLAG_USB_MODE_CALLED; // check if user wants to disable the USB if (args[ARG_mode].u_obj == mp_const_none) { // disable usb pyb_usb_dev_deinit(); return mp_const_none; } // get mode string const char *mode_str = mp_obj_str_get_str(args[ARG_mode].u_obj); #if defined(USE_HOST_MODE) // hardware configured for USB host mode if (strcmp(mode_str, "host") == 0) { pyb_usb_host_init(); } else { goto bad_mode; } #else // hardware configured for USB device mode // get the VID, PID and USB mode // note: PID=-1 means select PID based on mode // note: we support CDC as a synonym for VCP for backward compatibility uint16_t vid = args[ARG_vid].u_int; mp_int_t pid = args[ARG_pid].u_int; uint8_t mode; if (strcmp(mode_str, "CDC+MSC") == 0 || strcmp(mode_str, "VCP+MSC") == 0) { if (pid == -1) { pid = USBD_PID_CDC_MSC; } mode = USBD_MODE_CDC_MSC; } else if (strcmp(mode_str, "VCP+MSC+HID") == 0) { if (pid == -1) { pid = USBD_PID_CDC_MSC_HID; } mode = USBD_MODE_CDC_MSC_HID; #if MICROPY_HW_USB_CDC_NUM >= 2 } else if (strcmp(mode_str, "VCP+VCP") == 0) { if (pid == -1) { pid = USBD_PID_CDC2; } mode = USBD_MODE_CDC2; } else if (strcmp(mode_str, "VCP+VCP+MSC") == 0) { if (pid == -1) { pid = USBD_PID_CDC2_MSC; } mode = USBD_MODE_CDC2_MSC; } else if (strcmp(mode_str, "2xVCP+MSC+HID") == 0) { if (pid == -1) { pid = USBD_PID_CDC2_MSC_HID; } mode = USBD_MODE_CDC2_MSC_HID; #endif #if MICROPY_HW_USB_CDC_NUM >= 3 } else if (strcmp(mode_str, "3xVCP") == 0) { if (pid == -1) { pid = USBD_PID_CDC3; } mode = USBD_MODE_CDC3; } else if (strcmp(mode_str, "3xVCP+MSC") == 0) { if (pid == -1) { pid = USBD_PID_CDC3_MSC; } mode = USBD_MODE_CDC3_MSC; } else if (strcmp(mode_str, "3xVCP+MSC+HID") == 0) { if (pid == -1) { pid = USBD_PID_CDC3_MSC_HID; } mode = USBD_MODE_CDC3_MSC_HID; #endif } else if (strcmp(mode_str, "CDC+HID") == 0 || strcmp(mode_str, "VCP+HID") == 0) { if (pid == -1) { pid = USBD_PID_CDC_HID; } mode = USBD_MODE_CDC_HID; } else if (strcmp(mode_str, "CDC") == 0 || strcmp(mode_str, "VCP") == 0) { if (pid == -1) { pid = USBD_PID_CDC; } mode = USBD_MODE_CDC; } else if (strcmp(mode_str, "MSC") == 0) { if (pid == -1) { pid = USBD_PID_MSC; } mode = USBD_MODE_MSC; } else { goto bad_mode; } // Get MSC logical units size_t msc_n = 0; const void *msc_unit[USBD_MSC_MAX_LUN]; #if MICROPY_HW_USB_MSC if (mode & USBD_MODE_IFACE_MSC) { mp_obj_t *items; mp_obj_get_array(args[ARG_msc].u_obj, &msc_n, &items); if (msc_n > USBD_MSC_MAX_LUN) { mp_raise_ValueError("too many logical units"); } for (size_t i = 0; i < msc_n; ++i) { mp_obj_type_t *type = mp_obj_get_type(items[i]); if (type == &pyb_flash_type #if MICROPY_HW_ENABLE_SDCARD || type == &pyb_sdcard_type #endif #if MICROPY_HW_ENABLE_MMCARD || type == &pyb_mmcard_type #endif ) { msc_unit[i] = type; } else { mp_raise_ValueError("unsupported logical unit"); } } } #endif // get hid info if user selected such a mode USBD_HID_ModeInfoTypeDef hid_info; #if MICROPY_HW_USB_HID if (mode & USBD_MODE_IFACE_HID) { mp_obj_t *items; mp_obj_get_array_fixed_n(args[ARG_hid].u_obj, 5, &items); hid_info.subclass = mp_obj_get_int(items[0]); hid_info.protocol = mp_obj_get_int(items[1]); hid_info.max_packet_len = mp_obj_get_int(items[2]); hid_info.polling_interval = mp_obj_get_int(items[3]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(items[4], &bufinfo, MP_BUFFER_READ); hid_info.report_desc = bufinfo.buf; hid_info.report_desc_len = bufinfo.len; // need to keep a copy of this so report_desc does not get GC'd MP_STATE_PORT(pyb_hid_report_desc) = items[4]; } #endif #if USBD_SUPPORT_HS_MODE if (args[ARG_high_speed].u_bool) { mode |= USBD_MODE_HIGH_SPEED; } #endif // Work out which port/peripheral to use, either user supplied or auto detect int dev_id = args[ARG_port].u_int; if (dev_id == -1) { dev_id = pyb_usb_dev_detect(); } // init the USB device if (!pyb_usb_dev_init(dev_id, vid, pid, mode, msc_n, msc_unit, &hid_info)) { goto bad_mode; } #endif return mp_const_none; bad_mode: mp_raise_ValueError("bad USB mode"); } MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_mode_obj, 0, pyb_usb_mode); /******************************************************************************/ // MicroPython bindings for USB VCP /// \moduleref pyb /// \class USB_VCP - USB virtual comm port /// /// The USB_VCP class allows creation of an object representing the USB /// virtual comm port. It can be used to read and write data over USB to /// the connected host. typedef struct _pyb_usb_vcp_obj_t { mp_obj_base_t base; usbd_cdc_itf_t *cdc_itf; } pyb_usb_vcp_obj_t; const pyb_usb_vcp_obj_t pyb_usb_vcp_obj[MICROPY_HW_USB_CDC_NUM] = { {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[0]}, #if MICROPY_HW_USB_CDC_NUM >= 2 {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[1]}, #endif #if MICROPY_HW_USB_CDC_NUM >= 3 {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[2]}, #endif }; STATIC void pyb_usb_vcp_init0(void) { // Activate USB_VCP(0) on dupterm slot 1 for the REPL MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0]); usb_vcp_attach_to_repl(&pyb_usb_vcp_obj[0], true); } STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf[0]; mp_printf(print, "USB_VCP(%u)", id); } void usb_vcp_attach_to_repl(const pyb_usb_vcp_obj_t *self, bool attached) { self->cdc_itf->attached_to_repl = attached; if (attached) { // Default behavior is non-blocking when attached to repl self->cdc_itf->flow &= ~USBD_CDC_FLOWCONTROL_CTS; } else { self->cdc_itf->flow |= USBD_CDC_FLOWCONTROL_CTS; } } /// \classmethod \constructor() /// Create a new USB_VCP object. STATIC mp_obj_t pyb_usb_vcp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 1, false); // TODO raise exception if USB is not configured for VCP int id = (n_args == 0) ? 0 : mp_obj_get_int(args[0]); if (0 <= id && id < MICROPY_HW_USB_CDC_NUM) { return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[id]); } else { mp_raise_ValueError(NULL); } } // init(*, flow=-1) STATIC mp_obj_t pyb_usb_vcp_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_flow }; static const mp_arg_t allowed_args[] = { { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // flow control if (args[ARG_flow].u_int != -1) { self->cdc_itf->flow = args[ARG_flow].u_int; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_init_obj, 1, pyb_usb_vcp_init); STATIC mp_obj_t pyb_usb_vcp_setinterrupt(mp_obj_t self_in, mp_obj_t int_chr_in) { mp_hal_set_interrupt_char(mp_obj_get_int(int_chr_in)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_usb_vcp_setinterrupt_obj, pyb_usb_vcp_setinterrupt); STATIC mp_obj_t pyb_usb_vcp_isconnected(mp_obj_t self_in) { pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(usbd_cdc_is_connected(self->cdc_itf)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_vcp_isconnected_obj, pyb_usb_vcp_isconnected); // deprecated in favour of USB_VCP.isconnected STATIC mp_obj_t pyb_have_cdc(void) { return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0])); } MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc); /// \method any() /// Return `True` if any characters waiting, else `False`. STATIC mp_obj_t pyb_usb_vcp_any(mp_obj_t self_in) { pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(self_in); if (usbd_cdc_rx_num(self->cdc_itf) > 0) { return mp_const_true; } else { return mp_const_false; } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_vcp_any_obj, pyb_usb_vcp_any); /// \method send(data, *, timeout=5000) /// Send data over the USB VCP: /// /// - `data` is the data to send (an integer to send, or a buffer object). /// - `timeout` is the timeout in milliseconds to wait for the send. /// /// Return value: number of bytes sent. STATIC const mp_arg_t pyb_usb_vcp_send_args[] = { { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; #define PYB_USB_VCP_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_usb_vcp_send_args) STATIC mp_obj_t pyb_usb_vcp_send(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { // parse args pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_arg_val_t vals[PYB_USB_VCP_SEND_NUM_ARGS]; mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_USB_VCP_SEND_NUM_ARGS, pyb_usb_vcp_send_args, vals); // get the buffer to send from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data); // send the data int ret = usbd_cdc_tx(self->cdc_itf, bufinfo.buf, bufinfo.len, vals[1].u_int); return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_send_obj, 1, pyb_usb_vcp_send); /// \method recv(data, *, timeout=5000) /// /// Receive data on the bus: /// /// - `data` can be an integer, which is the number of bytes to receive, /// or a mutable buffer, which will be filled with received bytes. /// - `timeout` is the timeout in milliseconds to wait for the receive. /// /// Return value: if `data` is an integer then a new buffer of the bytes received, /// otherwise the number of bytes read into `data` is returned. STATIC mp_obj_t pyb_usb_vcp_recv(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { // parse args pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_arg_val_t vals[PYB_USB_VCP_SEND_NUM_ARGS]; mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_USB_VCP_SEND_NUM_ARGS, pyb_usb_vcp_send_args, vals); // get the buffer to receive into vstr_t vstr; mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr); // receive the data int ret = usbd_cdc_rx(self->cdc_itf, (uint8_t*)vstr.buf, vstr.len, vals[1].u_int); // return the received data if (o_ret != MP_OBJ_NULL) { return mp_obj_new_int(ret); // number of bytes read into given buffer } else { vstr.len = ret; // set actual number of bytes read return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); // create a new buffer } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_recv_obj, 1, pyb_usb_vcp_recv); mp_obj_t pyb_usb_vcp___exit__(size_t n_args, const mp_obj_t *args) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_usb_vcp___exit___obj, 4, 4, pyb_usb_vcp___exit__); STATIC const mp_rom_map_elem_t pyb_usb_vcp_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_usb_vcp_init_obj) }, { MP_ROM_QSTR(MP_QSTR_setinterrupt), MP_ROM_PTR(&pyb_usb_vcp_setinterrupt_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&pyb_usb_vcp_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_usb_vcp_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_usb_vcp_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_usb_vcp_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)}, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&pyb_usb_vcp___exit___obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(USBD_CDC_FLOWCONTROL_RTS) }, { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(USBD_CDC_FLOWCONTROL_CTS) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table); STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(self_in); int ret = usbd_cdc_rx(self->cdc_itf, (byte*)buf, size, 0); if (ret == 0) { // return EAGAIN error to indicate non-blocking *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } return ret; } STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(self_in); int ret = usbd_cdc_tx_flow(self->cdc_itf, (const byte*)buf, size); if (ret == 0) { // return EAGAIN error to indicate non-blocking *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } return ret; } STATIC mp_uint_t pyb_usb_vcp_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_uint_t ret; pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(self_in); if (request == MP_STREAM_POLL) { uintptr_t flags = arg; ret = 0; if ((flags & MP_STREAM_POLL_RD) && usbd_cdc_rx_num(self->cdc_itf) > 0) { ret |= MP_STREAM_POLL_RD; } if ((flags & MP_STREAM_POLL_WR) && usbd_cdc_tx_half_empty(self->cdc_itf)) { ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; } return ret; } STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = { .read = pyb_usb_vcp_read, .write = pyb_usb_vcp_write, .ioctl = pyb_usb_vcp_ioctl, }; const mp_obj_type_t pyb_usb_vcp_type = { { &mp_type_type }, .name = MP_QSTR_USB_VCP, .print = pyb_usb_vcp_print, .make_new = pyb_usb_vcp_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &pyb_usb_vcp_stream_p, .locals_dict = (mp_obj_dict_t*)&pyb_usb_vcp_locals_dict, }; /******************************************************************************/ // MicroPython bindings for USB HID #if MICROPY_HW_USB_HID typedef struct _pyb_usb_hid_obj_t { mp_obj_base_t base; usb_device_t *usb_dev; } pyb_usb_hid_obj_t; STATIC const pyb_usb_hid_obj_t pyb_usb_hid_obj = {{&pyb_usb_hid_type}, &usb_device}; STATIC mp_obj_t pyb_usb_hid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); // TODO raise exception if USB is not configured for HID // return the USB HID object return MP_OBJ_FROM_PTR(&pyb_usb_hid_obj); } /// \method recv(data, *, timeout=5000) /// /// Receive data on the bus: /// /// - `data` can be an integer, which is the number of bytes to receive, /// or a mutable buffer, which will be filled with received bytes. /// - `timeout` is the timeout in milliseconds to wait for the receive. /// /// Return value: if `data` is an integer then a new buffer of the bytes received, /// otherwise the number of bytes read into `data` is returned. STATIC mp_obj_t pyb_usb_hid_recv(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args pyb_usb_hid_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); // get the buffer to receive into vstr_t vstr; mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr); // receive the data int ret = usbd_hid_rx(&self->usb_dev->usbd_hid_itf, vstr.len, (uint8_t*)vstr.buf, vals[1].u_int); if (ret < 0) { // error, just return 0/empty bytes ret = 0; } // return the received data if (o_ret != MP_OBJ_NULL) { return mp_obj_new_int(ret); // number of bytes read into given buffer } else { vstr.len = ret; // set actual number of bytes read return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); // create a new buffer } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_hid_recv_obj, 1, pyb_usb_hid_recv); STATIC mp_obj_t pyb_usb_hid_send(mp_obj_t self_in, mp_obj_t report_in) { pyb_usb_hid_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; byte temp_buf[8]; // get the buffer to send from // we accept either a byte array, or a tuple/list of integers if (!mp_get_buffer(report_in, &bufinfo, MP_BUFFER_READ)) { mp_obj_t *items; mp_obj_get_array(report_in, &bufinfo.len, &items); if (bufinfo.len > sizeof(temp_buf)) { mp_raise_ValueError("tuple/list too large for HID report; use bytearray instead"); } for (int i = 0; i < bufinfo.len; i++) { temp_buf[i] = mp_obj_get_int(items[i]); } bufinfo.buf = temp_buf; } // send the data if (USBD_OK == USBD_HID_SendReport(&self->usb_dev->usbd_hid_itf.base, bufinfo.buf, bufinfo.len)) { return mp_obj_new_int(bufinfo.len); } else { return mp_obj_new_int(0); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_usb_hid_send_obj, pyb_usb_hid_send); // deprecated in favour of USB_HID.send STATIC mp_obj_t pyb_hid_send_report(mp_obj_t arg) { return pyb_usb_hid_send(MP_OBJ_FROM_PTR(&pyb_usb_hid_obj), arg); } MP_DEFINE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj, pyb_hid_send_report); STATIC const mp_rom_map_elem_t pyb_usb_hid_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_usb_hid_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_usb_hid_recv_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_usb_hid_locals_dict, pyb_usb_hid_locals_dict_table); STATIC mp_uint_t pyb_usb_hid_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { pyb_usb_hid_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; if (request == MP_STREAM_POLL) { uintptr_t flags = arg; ret = 0; if ((flags & MP_STREAM_POLL_RD) && usbd_hid_rx_num(&self->usb_dev->usbd_hid_itf) > 0) { ret |= MP_STREAM_POLL_RD; } if ((flags & MP_STREAM_POLL_WR) && USBD_HID_CanSendReport(&self->usb_dev->usbd_hid_itf.base)) { ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; } return ret; } STATIC const mp_stream_p_t pyb_usb_hid_stream_p = { .ioctl = pyb_usb_hid_ioctl, }; const mp_obj_type_t pyb_usb_hid_type = { { &mp_type_type }, .name = MP_QSTR_USB_HID, .make_new = pyb_usb_hid_make_new, .protocol = &pyb_usb_hid_stream_p, .locals_dict = (mp_obj_dict_t*)&pyb_usb_hid_locals_dict, }; #endif // MICROPY_HW_USB_HID /******************************************************************************/ // code for experimental USB OTG support #ifdef USE_HOST_MODE #include "led.h" #include "usbh_core.h" #include "usbh_usr.h" #include "usbh_hid_core.h" #include "usbh_hid_keybd.h" #include "usbh_hid_mouse.h" __ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; static int host_is_enabled = 0; void pyb_usb_host_init(void) { if (!host_is_enabled) { // only init USBH once in the device's power-lifetime /* Init Host Library */ USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks); } host_is_enabled = 1; } void pyb_usb_host_process(void) { USBH_Process(&USB_OTG_Core, &USB_Host); } uint8_t usb_keyboard_key = 0; // TODO this is an ugly hack to get key presses uint pyb_usb_host_get_keyboard(void) { uint key = usb_keyboard_key; usb_keyboard_key = 0; return key; } void USR_MOUSE_Init(void) { led_state(4, 1); USB_OTG_BSP_mDelay(100); led_state(4, 0); } void USR_MOUSE_ProcessData(HID_MOUSE_Data_TypeDef *data) { led_state(4, 1); USB_OTG_BSP_mDelay(50); led_state(4, 0); } void USR_KEYBRD_Init(void) { led_state(4, 1); USB_OTG_BSP_mDelay(100); led_state(4, 0); } void USR_KEYBRD_ProcessData(uint8_t pbuf) { led_state(4, 1); USB_OTG_BSP_mDelay(50); led_state(4, 0); usb_keyboard_key = pbuf; } #endif // USE_HOST_MODE #endif // MICROPY_HW_ENABLE_USB micropython-1.12/ports/stm32/usb.h000066400000000000000000000063511357706137100171100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014, 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_USB_H #define MICROPY_INCLUDED_STM32_USB_H #include "usbd_cdc_msc_hid0.h" #define PYB_USB_FLAG_USB_MODE_CALLED (0x0002) // Windows needs a different PID to distinguish different device configurations #define USBD_VID (0xf055) #define USBD_PID_CDC_MSC (0x9800) #define USBD_PID_CDC_HID (0x9801) #define USBD_PID_CDC (0x9802) #define USBD_PID_MSC (0x9803) #define USBD_PID_CDC2_MSC (0x9804) #define USBD_PID_CDC2 (0x9805) #define USBD_PID_CDC3 (0x9806) #define USBD_PID_CDC3_MSC (0x9807) #define USBD_PID_CDC_MSC_HID (0x9808) #define USBD_PID_CDC2_MSC_HID (0x9809) #define USBD_PID_CDC3_MSC_HID (0x980a) typedef enum { PYB_USB_STORAGE_MEDIUM_NONE = 0, PYB_USB_STORAGE_MEDIUM_FLASH, PYB_USB_STORAGE_MEDIUM_SDCARD, } pyb_usb_storage_medium_t; typedef enum { USB_PHY_FS_ID = 0, USB_PHY_HS_ID = 1, } USB_PHY_ID; typedef struct _pyb_usb_vcp_obj_t pyb_usb_vcp_obj_t; extern mp_uint_t pyb_usb_flags; extern pyb_usb_storage_medium_t pyb_usb_storage_medium; extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_mouse_obj; extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj; extern const mp_obj_type_t pyb_usb_vcp_type; extern const mp_obj_type_t pyb_usb_hid_type; MP_DECLARE_CONST_FUN_OBJ_KW(pyb_usb_mode_obj); MP_DECLARE_CONST_FUN_OBJ_0(pyb_have_cdc_obj); // deprecated MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated void pyb_usb_init0(void); int pyb_usb_dev_detect(void); bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info); void pyb_usb_dev_deinit(void); bool usb_vcp_is_enabled(void); int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0 void usb_vcp_send_strn(const char* str, int len); void usb_vcp_attach_to_repl(const pyb_usb_vcp_obj_t *self, bool attached); void pyb_usb_host_init(void); void pyb_usb_host_process(void); uint pyb_usb_host_get_keyboard(void); #endif // MICROPY_INCLUDED_STM32_USB_H micropython-1.12/ports/stm32/usbd_cdc_interface.c000066400000000000000000000373311357706137100221020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * Taken from ST Cube library and heavily modified. See below for original * copyright header. */ /** ****************************************************************************** * @file USB_Device/CDC_Standalone/Src/usbd_cdc_interface.c * @author MCD Application Team * @version V1.0.1 * @date 26-February-2014 * @brief Source file for USBD CDC interface ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include #include #include "usbd_cdc_msc_hid.h" #include "usbd_cdc_interface.h" #include "pendsv.h" #include "py/obj.h" #include "lib/utils/interrupt_char.h" #include "irq.h" #if MICROPY_HW_ENABLE_USB // CDC control commands #define CDC_SEND_ENCAPSULATED_COMMAND 0x00 #define CDC_GET_ENCAPSULATED_RESPONSE 0x01 #define CDC_SET_COMM_FEATURE 0x02 #define CDC_GET_COMM_FEATURE 0x03 #define CDC_CLEAR_COMM_FEATURE 0x04 #define CDC_SET_LINE_CODING 0x20 #define CDC_GET_LINE_CODING 0x21 #define CDC_SET_CONTROL_LINE_STATE 0x22 #define CDC_SEND_BREAK 0x23 // Used to control the connect_state variable when USB host opens the serial port static uint8_t usbd_cdc_connect_tx_timer; uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in; // Reset the CDC state due to a new USB host connection // Note: we don't reset tx_buf_ptr_* in order to allow the output buffer to // be filled (by usbd_cdc_tx_always) before the USB device is connected, and // to retain transmit buffer state across multiple USB connections (they will // be 0 at MCU reset since the variables live in the BSS). cdc->rx_buf_put = 0; cdc->rx_buf_get = 0; cdc->rx_buf_full = false; cdc->tx_need_empty_packet = 0; cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED; if (cdc->attached_to_repl) { // Default behavior is non-blocking when attached to repl cdc->flow &= ~USBD_CDC_FLOWCONTROL_CTS; } else { cdc->flow |= USBD_CDC_FLOWCONTROL_CTS; } // Return the buffer to place the first USB OUT packet return cdc->rx_packet_buf; } void usbd_cdc_deinit(usbd_cdc_state_t *cdc_in) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in; cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED; } // Manage the CDC class requests // cmd: command code // pbuf: buffer containing command data (request parameters) // length: number of data to be sent (in bytes) // Returns USBD_OK if all operations are OK else USBD_FAIL int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, uint16_t length) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in; switch (cmd) { case CDC_SEND_ENCAPSULATED_COMMAND: /* Add your code here */ break; case CDC_GET_ENCAPSULATED_RESPONSE: /* Add your code here */ break; case CDC_SET_COMM_FEATURE: /* Add your code here */ break; case CDC_GET_COMM_FEATURE: /* Add your code here */ break; case CDC_CLEAR_COMM_FEATURE: /* Add your code here */ break; case CDC_SET_LINE_CODING: #if 0 LineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\ (pbuf[2] << 16) | (pbuf[3] << 24)); LineCoding.format = pbuf[4]; LineCoding.paritytype = pbuf[5]; LineCoding.datatype = pbuf[6]; /* Set the new configuration */ #endif break; case CDC_GET_LINE_CODING: /* Add your code here */ pbuf[0] = (uint8_t)(115200); pbuf[1] = (uint8_t)(115200 >> 8); pbuf[2] = (uint8_t)(115200 >> 16); pbuf[3] = (uint8_t)(115200 >> 24); pbuf[4] = 0; // stop bits (1) pbuf[5] = 0; // parity (none) pbuf[6] = 8; // number of bits (8) break; case CDC_SET_CONTROL_LINE_STATE: { // wValue, indicating the state, is passed in length (bit of a hack) if (length & 1) { // The actual connection state is delayed to give the host a chance to // configure its serial port (in most cases to disable local echo) cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTING; usbd_cdc_connect_tx_timer = 8; // wait for 8 SOF IRQs #if !MICROPY_HW_USB_IS_MULTI_OTG USB->CNTR |= USB_CNTR_SOFM; #else PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData; hpcd->Instance->GINTMSK |= USB_OTG_GINTMSK_SOFM; #endif } else { cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED; } break; } case CDC_SEND_BREAK: /* Add your code here */ break; default: break; } return USBD_OK; } // Called when the USB IN endpoint is ready to receive more data // (cdc.base.tx_in_progress must be 0) void usbd_cdc_tx_ready(usbd_cdc_state_t *cdc_in) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in; cdc->tx_buf_ptr_out = cdc->tx_buf_ptr_out_shadow; if (cdc->tx_buf_ptr_out == cdc->tx_buf_ptr_in && !cdc->tx_need_empty_packet) { // No outstanding data to send return; } uint32_t len; if (cdc->tx_buf_ptr_out > cdc->tx_buf_ptr_in) { // rollback len = USBD_CDC_TX_DATA_SIZE - cdc->tx_buf_ptr_out; } else { len = cdc->tx_buf_ptr_in - cdc->tx_buf_ptr_out; } // Should always succeed because cdc.base.tx_in_progress==0 USBD_CDC_TransmitPacket(&cdc->base, len, &cdc->tx_buf[cdc->tx_buf_ptr_out]); cdc->tx_buf_ptr_out_shadow += len; if (cdc->tx_buf_ptr_out_shadow == USBD_CDC_TX_DATA_SIZE) { cdc->tx_buf_ptr_out_shadow = 0; } // According to the USB specification, a packet size of 64 bytes (CDC_DATA_FS_MAX_PACKET_SIZE) // gets held at the USB host until the next packet is sent. This is because a // packet of maximum size is considered to be part of a longer chunk of data, and // the host waits for all data to arrive (ie, waits for a packet < max packet size). // To flush a packet of exactly max packet size, we need to send a zero-size packet. // See eg http://www.cypress.com/?id=4&rID=92719 cdc->tx_need_empty_packet = (len > 0 && len % usbd_cdc_max_packet(cdc->base.usbd->pdev) == 0 && cdc->tx_buf_ptr_out_shadow == cdc->tx_buf_ptr_in); } // Attempt to queue data on the USB IN endpoint static void usbd_cdc_try_tx(usbd_cdc_itf_t *cdc) { uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); if (cdc == NULL || cdc->connect_state == USBD_CDC_CONNECT_STATE_DISCONNECTED) { // CDC device is not connected to a host, so we are unable to send any data } else if (cdc->base.tx_in_progress) { // USB driver will call callback when ready } else { usbd_cdc_tx_ready(&cdc->base); } restore_irq_pri(basepri); } void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { if (usbd_cdc_connect_tx_timer > 0) { --usbd_cdc_connect_tx_timer; } else { usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData; #if !MICROPY_HW_USB_IS_MULTI_OTG USB->CNTR &= ~USB_CNTR_SOFM; #else hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; #endif for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc[i]; if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) { cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED; usbd_cdc_try_tx(cdc); } } } } bool usbd_cdc_rx_buffer_full(usbd_cdc_itf_t *cdc) { int get = cdc->rx_buf_get, put = cdc->rx_buf_put; int remaining = (get - put) + (-((int) (get <= put)) & USBD_CDC_RX_DATA_SIZE); return remaining < CDC_DATA_MAX_PACKET_SIZE + 1; } void usbd_cdc_rx_check_resume(usbd_cdc_itf_t *cdc) { uint32_t irq_state = disable_irq(); if (cdc->rx_buf_full) { if (!usbd_cdc_rx_buffer_full(cdc)) { cdc->rx_buf_full = false; enable_irq(irq_state); USBD_CDC_ReceivePacket(&cdc->base, cdc->rx_packet_buf); return; } } enable_irq(irq_state); } // Data received over USB OUT endpoint is processed here. // len: number of bytes received into the buffer we passed to USBD_CDC_ReceivePacket // Returns USBD_OK if all operations are OK else USBD_FAIL int8_t usbd_cdc_receive(usbd_cdc_state_t *cdc_in, size_t len) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in; // copy the incoming data into the circular buffer for (const uint8_t *src = cdc->rx_packet_buf, *top = cdc->rx_packet_buf + len; src < top; ++src) { if (cdc->attached_to_repl && mp_interrupt_char != -1 && *src == mp_interrupt_char) { pendsv_kbd_intr(); } else { uint16_t next_put = (cdc->rx_buf_put + 1) & (USBD_CDC_RX_DATA_SIZE - 1); if (next_put == cdc->rx_buf_get) { // overflow, we just discard the rest of the chars break; } cdc->rx_user_buf[cdc->rx_buf_put] = *src; cdc->rx_buf_put = next_put; } } if ((cdc->flow & USBD_CDC_FLOWCONTROL_RTS) && (usbd_cdc_rx_buffer_full(cdc))) { cdc->rx_buf_full = true; return USBD_BUSY; } else { // initiate next USB packet transfer cdc->rx_buf_full = false; return USBD_CDC_ReceivePacket(&cdc->base, cdc->rx_packet_buf); } } int usbd_cdc_tx_half_empty(usbd_cdc_itf_t *cdc) { int32_t tx_waiting = (int32_t)cdc->tx_buf_ptr_in - (int32_t)cdc->tx_buf_ptr_out; if (tx_waiting < 0) { tx_waiting += USBD_CDC_TX_DATA_SIZE; } return tx_waiting <= USBD_CDC_TX_DATA_SIZE / 2; } // Writes only the data that fits if flow & CTS, else writes all data // Returns number of bytes actually written to the device int usbd_cdc_tx_flow(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len) { if (cdc->flow & USBD_CDC_FLOWCONTROL_CTS) { // Only write as much as can fit in tx buffer return usbd_cdc_tx(cdc, buf, len, 0); } else { // Never block, keep most recent data in rolling buffer usbd_cdc_tx_always(cdc, buf, len); return len; } } // timout in milliseconds. // Returns number of bytes written to the device. int usbd_cdc_tx(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len, uint32_t timeout) { for (uint32_t i = 0; i < len; i++) { // Wait until the device is connected and the buffer has space, with a given timeout uint32_t start = HAL_GetTick(); while (cdc->connect_state == USBD_CDC_CONNECT_STATE_DISCONNECTED || ((cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1)) == cdc->tx_buf_ptr_out) { usbd_cdc_try_tx(cdc); // Wraparound of tick is taken care of by 2's complement arithmetic. if (HAL_GetTick() - start >= timeout) { // timeout return i; } if (query_irq() == IRQ_STATE_DISABLED) { // IRQs disabled so buffer will never be drained; return immediately return i; } __WFI(); // enter sleep mode, waiting for interrupt } // Write data to device buffer cdc->tx_buf[cdc->tx_buf_ptr_in] = buf[i]; cdc->tx_buf_ptr_in = (cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1); } usbd_cdc_try_tx(cdc); // Success, return number of bytes read return len; } // Always write all of the data to the device tx buffer, even if the // device is not connected, or if the buffer is full. Has a small timeout // to wait for the buffer to be drained, in the case the device is connected. void usbd_cdc_tx_always(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len) { for (int i = 0; i < len; i++) { // If the CDC device is not connected to the host then we don't have anyone to receive our data. // The device may become connected in the future, so we should at least try to fill the buffer // and hope that it doesn't overflow by the time the device connects. // If the device is not connected then we should go ahead and fill the buffer straight away, // ignoring overflow. Otherwise, we should make sure that we have enough room in the buffer. if (cdc->connect_state != USBD_CDC_CONNECT_STATE_DISCONNECTED) { // If the buffer is full, wait until it gets drained, with a timeout of 500ms // (wraparound of tick is taken care of by 2's complement arithmetic). uint32_t start = HAL_GetTick(); while (((cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1)) == cdc->tx_buf_ptr_out && HAL_GetTick() - start <= 500) { usbd_cdc_try_tx(cdc); if (query_irq() == IRQ_STATE_DISABLED) { // IRQs disabled so buffer will never be drained; exit loop break; } __WFI(); // enter sleep mode, waiting for interrupt } } cdc->tx_buf[cdc->tx_buf_ptr_in] = buf[i]; cdc->tx_buf_ptr_in = (cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1); } usbd_cdc_try_tx(cdc); } // Returns number of bytes in the rx buffer. int usbd_cdc_rx_num(usbd_cdc_itf_t *cdc) { int32_t rx_waiting = (int32_t)cdc->rx_buf_put - (int32_t)cdc->rx_buf_get; if (rx_waiting < 0) { rx_waiting += USBD_CDC_RX_DATA_SIZE; } usbd_cdc_rx_check_resume(cdc); return rx_waiting; } // timout in milliseconds. // Returns number of bytes read from the device. int usbd_cdc_rx(usbd_cdc_itf_t *cdc, uint8_t *buf, uint32_t len, uint32_t timeout) { // loop to read bytes for (uint32_t i = 0; i < len; i++) { // Wait until we have at least 1 byte to read uint32_t start = HAL_GetTick(); while (cdc->rx_buf_put == cdc->rx_buf_get) { // Wraparound of tick is taken care of by 2's complement arithmetic. if (HAL_GetTick() - start >= timeout) { // timeout return i; } if (query_irq() == IRQ_STATE_DISABLED) { // IRQs disabled so buffer will never be filled; return immediately return i; } usbd_cdc_rx_check_resume(cdc); __WFI(); // enter sleep mode, waiting for interrupt } // Copy byte from device to user buffer buf[i] = cdc->rx_user_buf[cdc->rx_buf_get]; cdc->rx_buf_get = (cdc->rx_buf_get + 1) & (USBD_CDC_RX_DATA_SIZE - 1); } usbd_cdc_rx_check_resume(cdc); // Success, return number of bytes read return len; } #endif micropython-1.12/ports/stm32/usbd_cdc_interface.h000066400000000000000000000073111357706137100221020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ */ #ifndef MICROPY_INCLUDED_STM32_USBD_CDC_INTERFACE_H #define MICROPY_INCLUDED_STM32_USBD_CDC_INTERFACE_H /** ****************************************************************************** * @file USB_Device/CDC_Standalone/Inc/usbd_cdc_interface.h * @author MCD Application Team * @version V1.0.1 * @date 26-February-2014 * @brief Header for usbd_cdc_interface.c file. ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ #ifndef USBD_CDC_RX_DATA_SIZE #define USBD_CDC_RX_DATA_SIZE (1024) // this must be 2 or greater, and a power of 2 #endif #ifndef USBD_CDC_TX_DATA_SIZE #define USBD_CDC_TX_DATA_SIZE (1024) // I think this can be any value (was 2048) #endif // Values for connect_state #define USBD_CDC_CONNECT_STATE_DISCONNECTED (0) #define USBD_CDC_CONNECT_STATE_CONNECTING (1) #define USBD_CDC_CONNECT_STATE_CONNECTED (2) // Flow control settings #define USBD_CDC_FLOWCONTROL_NONE (0) #define USBD_CDC_FLOWCONTROL_RTS (1) #define USBD_CDC_FLOWCONTROL_CTS (2) typedef struct _usbd_cdc_itf_t { usbd_cdc_state_t base; // state for the base CDC layer uint8_t rx_packet_buf[CDC_DATA_MAX_PACKET_SIZE]; // received data from USB OUT endpoint is stored in this buffer uint8_t rx_user_buf[USBD_CDC_RX_DATA_SIZE]; // received data is buffered here until the user reads it volatile uint16_t rx_buf_put; // circular buffer index uint16_t rx_buf_get; // circular buffer index uint8_t rx_buf_full; // rx from host will be blocked while this is true uint8_t tx_buf[USBD_CDC_TX_DATA_SIZE]; // data for USB IN endpoind is stored in this buffer uint16_t tx_buf_ptr_in; // increment this pointer modulo USBD_CDC_TX_DATA_SIZE when new data is available volatile uint16_t tx_buf_ptr_out; // increment this pointer modulo USBD_CDC_TX_DATA_SIZE when data is drained uint16_t tx_buf_ptr_out_shadow; // shadow of above uint8_t tx_need_empty_packet; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size volatile uint8_t connect_state; // indicates if we are connected uint8_t attached_to_repl; // indicates if interface is connected to REPL uint8_t flow; // USBD_CDC_FLOWCONTROL_* setting flags } usbd_cdc_itf_t; // This is implemented in usb.c usbd_cdc_itf_t *usb_vcp_get(int idx); static inline int usbd_cdc_is_connected(usbd_cdc_itf_t *cdc) { return cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTED; } int usbd_cdc_tx_half_empty(usbd_cdc_itf_t *cdc); int usbd_cdc_tx_flow(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len); int usbd_cdc_tx(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len, uint32_t timeout); void usbd_cdc_tx_always(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len); int usbd_cdc_rx_num(usbd_cdc_itf_t *cdc); int usbd_cdc_rx(usbd_cdc_itf_t *cdc, uint8_t *buf, uint32_t len, uint32_t timeout); #endif // MICROPY_INCLUDED_STM32_USBD_CDC_INTERFACE_H micropython-1.12/ports/stm32/usbd_conf.c000066400000000000000000000467161357706137100202650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ */ /** ****************************************************************************** * @file USB_Device/CDC_Standalone/Src/usbd_conf.c * @author MCD Application Team * @version V1.0.1 * @date 26-February-2014 * @brief This file implements the USB Device library callbacks and MSP ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ #include "usbd_core.h" #include "py/obj.h" #include "py/mphal.h" #include "irq.h" #include "usb.h" #if MICROPY_HW_USB_FS || MICROPY_HW_USB_HS #if MICROPY_HW_USB_FS PCD_HandleTypeDef pcd_fs_handle; #endif #if MICROPY_HW_USB_HS PCD_HandleTypeDef pcd_hs_handle; #endif #if !MICROPY_HW_USB_IS_MULTI_OTG // The MCU has a single USB device-only instance #define USB_OTG_FS USB #endif /******************************************************************************* PCD BSP Routines *******************************************************************************/ /** * @brief Initializes the PCD MSP. * @param hpcd: PCD handle * @retval None */ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { if (hpcd->Instance == USB_OTG_FS) { #if defined(STM32H7) const uint32_t otg_alt = GPIO_AF10_OTG1_FS; #elif defined(STM32L0) const uint32_t otg_alt = GPIO_AF0_USB; #elif defined(STM32L432xx) const uint32_t otg_alt = GPIO_AF10_USB_FS; #elif defined(STM32WB) const uint32_t otg_alt = GPIO_AF10_USB; #else const uint32_t otg_alt = GPIO_AF10_OTG_FS; #endif mp_hal_pin_config(pin_A11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt); mp_hal_pin_config_speed(pin_A11, GPIO_SPEED_FREQ_VERY_HIGH); mp_hal_pin_config(pin_A12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt); mp_hal_pin_config_speed(pin_A12, GPIO_SPEED_FREQ_VERY_HIGH); #if defined(MICROPY_HW_USB_VBUS_DETECT_PIN) // USB VBUS detect pin is always A9 mp_hal_pin_config(MICROPY_HW_USB_VBUS_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); #endif #if defined(MICROPY_HW_USB_OTG_ID_PIN) // USB ID pin is always A10 mp_hal_pin_config(MICROPY_HW_USB_OTG_ID_PIN, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, otg_alt); #endif #if defined(STM32H7) // Keep USB clock running during sleep or else __WFI() will disable the USB __HAL_RCC_USB2_OTG_FS_CLK_SLEEP_ENABLE(); __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE(); #endif // Enable USB FS Clocks #if !MICROPY_HW_USB_IS_MULTI_OTG __HAL_RCC_USB_CLK_ENABLE(); #else __USB_OTG_FS_CLK_ENABLE(); #endif #if defined(STM32L4) // Enable VDDUSB if (__HAL_RCC_PWR_IS_CLK_DISABLED()) { __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWREx_EnableVddUSB(); __HAL_RCC_PWR_CLK_DISABLE(); } else { HAL_PWREx_EnableVddUSB(); } #endif // Configure and enable USB FS interrupt #if defined(STM32L0) NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_IRQn); #elif defined(STM32L432xx) NVIC_SetPriority(USB_FS_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_FS_IRQn); #elif defined(STM32WB) NVIC_SetPriority(USB_LP_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_LP_IRQn); #else NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(OTG_FS_IRQn); #endif } #if MICROPY_HW_USB_HS else if (hpcd->Instance == USB_OTG_HS) { #if MICROPY_HW_USB_HS_IN_FS #if defined(STM32H7) const uint32_t otg_alt = GPIO_AF12_OTG2_FS; #else const uint32_t otg_alt = GPIO_AF12_OTG_HS_FS; #endif // Configure USB FS GPIOs mp_hal_pin_config(pin_B14, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt); mp_hal_pin_config_speed(pin_B14, GPIO_SPEED_FREQ_VERY_HIGH); mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt); mp_hal_pin_config_speed(pin_B15, GPIO_SPEED_FREQ_VERY_HIGH); #if defined(MICROPY_HW_USB_VBUS_DETECT_PIN) // Configure VBUS Pin mp_hal_pin_config(MICROPY_HW_USB_VBUS_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); #endif #if defined(MICROPY_HW_USB_OTG_ID_PIN) // Configure ID pin mp_hal_pin_config(MICROPY_HW_USB_OTG_ID_PIN, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, otg_alt); #endif // Enable calling WFI and correct function of the embedded USB_FS_IN_HS phy __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE(); __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE(); // Enable USB HS Clocks #if defined(STM32F723xx) || defined(STM32F733xx) // Needs to remain awake during sleep or else __WFI() will disable the USB __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE(); __HAL_RCC_OTGPHYC_CLK_ENABLE(); __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); #endif __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); #else // !MICROPY_HW_USB_HS_IN_FS // Configure USB HS GPIOs static const mp_hal_pin_obj_t usb_pins[] = { pin_A5, pin_C0, pin_H4, pin_I11, // CLK, STP, NXT, DIR pin_A3, pin_B0, pin_B1, pin_B5, pin_B10, pin_B11, pin_B12, pin_B13, // D0-D7 }; for (size_t i = 0; i < MP_ARRAY_SIZE(usb_pins); ++i) { mp_hal_pin_config(usb_pins[i], MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, GPIO_AF10_OTG_HS); mp_hal_pin_config_speed(usb_pins[i], GPIO_SPEED_FREQ_VERY_HIGH); } // Enable USB HS Clocks __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE(); __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE(); #endif // !MICROPY_HW_USB_HS_IN_FS // Configure and enable USB HS interrupt NVIC_SetPriority(OTG_HS_IRQn, IRQ_PRI_OTG_HS); HAL_NVIC_EnableIRQ(OTG_HS_IRQn); } #endif // MICROPY_HW_USB_HS } /** * @brief DeInitializes the PCD MSP. * @param hpcd: PCD handle * @retval None */ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { #if !MICROPY_HW_USB_IS_MULTI_OTG __HAL_RCC_USB_CLK_DISABLE(); #else if (hpcd->Instance == USB_OTG_FS) { /* Disable USB FS Clocks */ __USB_OTG_FS_CLK_DISABLE(); __SYSCFG_CLK_DISABLE(); } #if MICROPY_HW_USB_HS else if (hpcd->Instance == USB_OTG_HS) { /* Disable USB FS Clocks */ __USB_OTG_HS_CLK_DISABLE(); __SYSCFG_CLK_DISABLE(); } #endif #endif } /******************************************************************************* LL Driver Callbacks (PCD -> USB Device Library) *******************************************************************************/ /** * @brief Setup stage callback. * @param hpcd: PCD handle * @retval None */ void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup); } /** * @brief Data Out stage callback. * @param hpcd: PCD handle * @param epnum: Endpoint Number * @retval None */ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBD_LL_DataOutStage(hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); } /** * @brief Data In stage callback. * @param hpcd: PCD handle * @param epnum: Endpoint Number * @retval None */ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBD_LL_DataInStage(hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); } /** * @brief SOF callback. * @param hpcd: PCD handle * @retval None */ /* This is now handled by the USB CDC interface. void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_SOF(hpcd->pData); } */ /** * @brief Reset callback. * @param hpcd: PCD handle * @retval None */ void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) { USBD_SpeedTypeDef speed = USBD_SPEED_FULL; // Set USB Current Speed switch (hpcd->Init.speed) { #if defined(PCD_SPEED_HIGH) case PCD_SPEED_HIGH: speed = USBD_SPEED_HIGH; break; #endif case PCD_SPEED_FULL: speed = USBD_SPEED_FULL; break; default: speed = USBD_SPEED_FULL; break; } USBD_LL_SetSpeed(hpcd->pData, speed); // Reset Device USBD_LL_Reset(hpcd->pData); } /** * @brief Suspend callback. * @param hpcd: PCD handle * @retval None */ void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_Suspend(hpcd->pData); } /** * @brief Resume callback. * @param hpcd: PCD handle * @retval None */ void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_Resume(hpcd->pData); } /** * @brief ISOC Out Incomplete callback. * @param hpcd: PCD handle * @param epnum: Endpoint Number * @retval None */ void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBD_LL_IsoOUTIncomplete(hpcd->pData, epnum); } /** * @brief ISOC In Incomplete callback. * @param hpcd: PCD handle * @param epnum: Endpoint Number * @retval None */ void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { USBD_LL_IsoINIncomplete(hpcd->pData, epnum); } /** * @brief Connect callback. * @param hpcd: PCD handle * @retval None */ void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_DevConnected(hpcd->pData); } /** * @brief Disconnect callback. * @param hpcd: PCD handle * @retval None */ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_DevDisconnected(hpcd->pData); } /******************************************************************************* LL Driver Interface (USB Device Library --> PCD) *******************************************************************************/ /** * @brief Initializes the Low Level portion of the Device driver. * @param pdev: Device handle * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const uint8_t *fifo_size) { #if MICROPY_HW_USB_FS if (pdev->id == USB_PHY_FS_ID) { #if defined(STM32WB) PWR->CR2 |= PWR_CR2_USV; // USB supply is valid #endif // Set LL Driver parameters pcd_fs_handle.Instance = USB_OTG_FS; #if MICROPY_HW_USB_CDC_NUM == 2 pcd_fs_handle.Init.dev_endpoints = 6; #else pcd_fs_handle.Init.dev_endpoints = 4; #endif pcd_fs_handle.Init.ep0_mps = 0x40; pcd_fs_handle.Init.low_power_enable = 0; pcd_fs_handle.Init.phy_itface = PCD_PHY_EMBEDDED; pcd_fs_handle.Init.Sof_enable = 0; pcd_fs_handle.Init.speed = PCD_SPEED_FULL; #if defined(STM32L4) pcd_fs_handle.Init.lpm_enable = DISABLE; pcd_fs_handle.Init.battery_charging_enable = DISABLE; #endif #if MICROPY_HW_USB_IS_MULTI_OTG pcd_fs_handle.Init.use_dedicated_ep1 = 0; pcd_fs_handle.Init.dma_enable = 0; #if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN) pcd_fs_handle.Init.vbus_sensing_enable = 0; // No VBUS Sensing on USB0 #else pcd_fs_handle.Init.vbus_sensing_enable = 1; #endif #endif // Link The driver to the stack pcd_fs_handle.pData = pdev; pdev->pData = &pcd_fs_handle; // Initialize LL Driver HAL_PCD_Init(&pcd_fs_handle); // Set FIFO buffer sizes #if !MICROPY_HW_USB_IS_MULTI_OTG uint32_t fifo_offset = USBD_PMA_RESERVE; // need to reserve some data at start of FIFO for (size_t i = 0; i < USBD_PMA_NUM_FIFO; ++i) { uint16_t ep_addr = ((i & 1) * 0x80) | (i >> 1); HAL_PCDEx_PMAConfig(&pcd_fs_handle, ep_addr, PCD_SNG_BUF, fifo_offset); fifo_offset += fifo_size[i] * 4; } #else HAL_PCD_SetRxFiFo(&pcd_fs_handle, fifo_size[0] * 4); for (size_t i = 0; i < USBD_FS_NUM_TX_FIFO; ++i) { HAL_PCD_SetTxFiFo(&pcd_fs_handle, i, fifo_size[1 + i] * 4); } #endif } #endif #if MICROPY_HW_USB_HS if (pdev->id == USB_PHY_HS_ID) { // Set LL Driver parameters pcd_hs_handle.Instance = USB_OTG_HS; #if MICROPY_HW_USB_CDC_NUM == 3 pcd_hs_handle.Init.dev_endpoints = 8; #else pcd_hs_handle.Init.dev_endpoints = 6; #endif pcd_hs_handle.Init.use_dedicated_ep1 = 0; pcd_hs_handle.Init.ep0_mps = 0x40; pcd_hs_handle.Init.dma_enable = 0; pcd_hs_handle.Init.low_power_enable = 0; pcd_hs_handle.Init.lpm_enable = DISABLE; pcd_hs_handle.Init.battery_charging_enable = DISABLE; pcd_hs_handle.Init.Sof_enable = 0; pcd_hs_handle.Init.use_external_vbus = 0; #if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN) pcd_hs_handle.Init.vbus_sensing_enable = 0; // No VBUS Sensing on USB0 #else pcd_hs_handle.Init.vbus_sensing_enable = 1; #endif #if MICROPY_HW_USB_HS_IN_FS #if defined(STM32F723xx) || defined(STM32F733xx) pcd_hs_handle.Init.phy_itface = USB_OTG_HS_EMBEDDED_PHY; #else pcd_hs_handle.Init.phy_itface = PCD_PHY_EMBEDDED; #endif if (high_speed) { pcd_hs_handle.Init.speed = PCD_SPEED_HIGH; } else { pcd_hs_handle.Init.speed = PCD_SPEED_HIGH_IN_FULL; } #else // USB HS with external PHY pcd_hs_handle.Init.phy_itface = PCD_PHY_ULPI; pcd_hs_handle.Init.speed = PCD_SPEED_HIGH; #endif // Link The driver to the stack pcd_hs_handle.pData = pdev; pdev->pData = &pcd_hs_handle; // Initialize LL Driver HAL_PCD_Init(&pcd_hs_handle); // Set FIFO buffer sizes fifo_size += USBD_FS_NUM_FIFO; // skip over FS FIFO size values HAL_PCD_SetRxFiFo(&pcd_hs_handle, fifo_size[0] * 4); for (size_t i = 0; i < USBD_HS_NUM_TX_FIFO; ++i) { HAL_PCD_SetTxFiFo(&pcd_hs_handle, i, fifo_size[1 + i] * 4); } } #endif // MICROPY_HW_USB_HS return USBD_OK; } /** * @brief De-Initializes the Low Level portion of the Device driver. * @param pdev: Device handle * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) { HAL_PCD_DeInit(pdev->pData); return USBD_OK; } /** * @brief Starts the Low Level portion of the Device driver. * @param pdev: Device handle * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) { HAL_PCD_Start(pdev->pData); return USBD_OK; } /** * @brief Stops the Low Level portion of the Device driver. * @param pdev: Device handle * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) { HAL_PCD_Stop(pdev->pData); return USBD_OK; } /** * @brief Opens an endpoint of the Low Level Driver. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @param ep_type: Endpoint Type * @param ep_mps: Endpoint Max Packet Size * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) { HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); return USBD_OK; } /** * @brief Closes an endpoint of the Low Level Driver. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_Close(pdev->pData, ep_addr); return USBD_OK; } /** * @brief Flushes an endpoint of the Low Level Driver. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_Flush(pdev->pData, ep_addr); return USBD_OK; } /** * @brief Sets a Stall condition on an endpoint of the Low Level Driver. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_SetStall(pdev->pData, ep_addr); return USBD_OK; } /** * @brief Clears a Stall condition on an endpoint of the Low Level Driver. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); return USBD_OK; } /** * @brief Returns Stall condition. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @retval Stall (1: yes, 0: No) */ uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { PCD_HandleTypeDef *hpcd = pdev->pData; if ((ep_addr & 0x80) == 0x80) { return hpcd->IN_ep[ep_addr & 0x7F].is_stall; } else { return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; } } /** * @brief Assigns an USB address to the device * @param pdev: Device handle * @param dev_addr: USB address * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) { HAL_PCD_SetAddress(pdev->pData, dev_addr); return USBD_OK; } /** * @brief Transmits data over an endpoint * @param pdev: Device handle * @param ep_addr: Endpoint Number * @param pbuf: Pointer to data to be sent * @param size: Data size * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size) { HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); return USBD_OK; } /** * @brief Prepares an endpoint for reception * @param pdev: Device handle * @param ep_addr: Endpoint Number * @param pbuf:pointer to data to be received * @param size: data size * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size) { HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); return USBD_OK; } /** * @brief Returns the last transfered packet size. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @retval Recived Data Size */ uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr); } /** * @brief Delay routine for the USB Device Library * @param Delay: Delay in ms * @retval None */ void USBD_LL_Delay(uint32_t Delay) { HAL_Delay(Delay); } #endif // MICROPY_HW_USB_FS || MICROPY_HW_USB_HS /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbd_conf.h000066400000000000000000000044121357706137100202550ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ */ /** ****************************************************************************** * @file USB_Device/CDC_Standalone/Inc/usbd_conf.h * @author MCD Application Team * @version V1.0.1 * @date 26-February-2014 * @brief General low level driver configuration ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ #ifndef MICROPY_INCLUDED_STM32_USBD_CONF_H #define MICROPY_INCLUDED_STM32_USBD_CONF_H #include #include #include #include #include "py/mpconfig.h" #define USBD_MAX_NUM_INTERFACES 8 #define USBD_MAX_NUM_CONFIGURATION 1 #define USBD_MAX_STR_DESC_SIZ 0x100 #if MICROPY_HW_USB_SELF_POWERED #define USBD_SELF_POWERED 1 #else #define USBD_SELF_POWERED 0 #endif #define USBD_DEBUG_LEVEL 0 // For MCUs with a device-only USB peripheral #define USBD_PMA_RESERVE (64) #define USBD_PMA_NUM_FIFO (8) // For MCUs with multiple OTG USB peripherals #define USBD_FS_NUM_TX_FIFO (6) #define USBD_FS_NUM_FIFO (1 + USBD_FS_NUM_TX_FIFO) #define USBD_HS_NUM_TX_FIFO (9) #define USBD_HS_NUM_FIFO (1 + USBD_HS_NUM_TX_FIFO) #endif // MICROPY_INCLUDED_STM32_USBD_CONF_H /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbd_desc.c000066400000000000000000000164321357706137100202460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ */ /** ****************************************************************************** * @file USB_Device/CDC_Standalone/Src/usbd_desc.c * @author MCD Application Team * @version V1.0.1 * @date 26-February-2014 * @brief This file provides the USBD descriptors and string formating method. ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ #include "usbd_core.h" #include "usbd_desc.h" #include "usbd_conf.h" // need this header just for MP_HAL_UNIQUE_ID_ADDRESS #include "py/mphal.h" // need this header for any overrides to the below constants #include "py/mpconfig.h" #ifndef USBD_LANGID_STRING #define USBD_LANGID_STRING 0x409 #endif #ifndef USBD_MANUFACTURER_STRING #define USBD_MANUFACTURER_STRING "MicroPython" #endif #ifndef USBD_PRODUCT_HS_STRING #define USBD_PRODUCT_HS_STRING "Pyboard Virtual Comm Port in HS Mode" #endif #ifndef USBD_PRODUCT_FS_STRING #define USBD_PRODUCT_FS_STRING "Pyboard Virtual Comm Port in FS Mode" #endif #ifndef USBD_CONFIGURATION_HS_STRING #define USBD_CONFIGURATION_HS_STRING "Pyboard Config" #endif #ifndef USBD_INTERFACE_HS_STRING #define USBD_INTERFACE_HS_STRING "Pyboard Interface" #endif #ifndef USBD_CONFIGURATION_FS_STRING #define USBD_CONFIGURATION_FS_STRING "Pyboard Config" #endif #ifndef USBD_INTERFACE_FS_STRING #define USBD_INTERFACE_FS_STRING "Pyboard Interface" #endif __ALIGN_BEGIN static const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING), HIBYTE(USBD_LANGID_STRING), }; // set the VID, PID and device release number void USBD_SetVIDPIDRelease(usbd_cdc_msc_hid_state_t *usbd, uint16_t vid, uint16_t pid, uint16_t device_release_num, int cdc_only) { uint8_t *dev_desc = &usbd->usbd_device_desc[0]; dev_desc[0] = USB_LEN_DEV_DESC; // bLength dev_desc[1] = USB_DESC_TYPE_DEVICE; // bDescriptorType dev_desc[2] = 0x00; // bcdUSB dev_desc[3] = 0x02; // bcdUSB if (cdc_only) { // Make it look like a Communications device if we're only // using CDC. Otherwise, windows gets confused when we tell it that // its a composite device with only a cdc serial interface. dev_desc[4] = 0x02; // bDeviceClass dev_desc[5] = 0x00; // bDeviceSubClass dev_desc[6] = 0x00; // bDeviceProtocol } else { // For the other modes, we make this look like a composite device. dev_desc[4] = 0xef; // bDeviceClass: Miscellaneous Device Class dev_desc[5] = 0x02; // bDeviceSubClass: Common Class dev_desc[6] = 0x01; // bDeviceProtocol: Interface Association Descriptor } dev_desc[7] = USB_MAX_EP0_SIZE; // bMaxPacketSize dev_desc[8] = LOBYTE(vid); // idVendor dev_desc[9] = HIBYTE(vid); // idVendor dev_desc[10] = LOBYTE(pid); // idVendor dev_desc[11] = HIBYTE(pid); // idVendor dev_desc[12] = LOBYTE(device_release_num); // bcdDevice dev_desc[13] = HIBYTE(device_release_num); // bcdDevice dev_desc[14] = USBD_IDX_MFC_STR; // Index of manufacturer string dev_desc[15] = USBD_IDX_PRODUCT_STR; // Index of product string dev_desc[16] = USBD_IDX_SERIAL_STR; // Index of serial number string dev_desc[17] = USBD_MAX_NUM_CONFIGURATION; // bNumConfigurations } /** * @brief Returns the device descriptor. * @param speed: Current device speed * @param length: Pointer to data length variable * @retval Pointer to descriptor buffer */ STATIC uint8_t *USBD_DeviceDescriptor(USBD_HandleTypeDef *pdev, uint16_t *length) { uint8_t *dev_desc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->usbd_device_desc; *length = USB_LEN_DEV_DESC; return dev_desc; } /** * @brief Returns a string descriptor * @param idx: Index of the string descriptor to retrieve * @param length: Pointer to data length variable * @retval Pointer to descriptor buffer, or NULL if idx is invalid */ STATIC uint8_t *USBD_StrDescriptor(USBD_HandleTypeDef *pdev, uint8_t idx, uint16_t *length) { char str_buf[16]; const char *str = NULL; switch (idx) { case USBD_IDX_LANGID_STR: *length = sizeof(USBD_LangIDDesc); return (uint8_t*)USBD_LangIDDesc; // the data should only be read from this buf case USBD_IDX_MFC_STR: str = USBD_MANUFACTURER_STRING; break; case USBD_IDX_PRODUCT_STR: if (pdev->dev_speed == USBD_SPEED_HIGH) { str = USBD_PRODUCT_HS_STRING; } else { str = USBD_PRODUCT_FS_STRING; } break; case USBD_IDX_SERIAL_STR: { // This document: http://www.usb.org/developers/docs/devclass_docs/usbmassbulk_10.pdf // says that the serial number has to be at least 12 digits long and that // the last 12 digits need to be unique. It also stipulates that the valid // character set is that of upper-case hexadecimal digits. // // The onboard DFU bootloader produces a 12-digit serial number based on // the 96-bit unique ID, so for consistency we go with this algorithm. // You can see the serial number if you use: lsusb -v // // See: https://my.st.com/52d187b7 for the algorithim used. uint8_t *id = (uint8_t *)MP_HAL_UNIQUE_ID_ADDRESS; snprintf(str_buf, sizeof(str_buf), "%02X%02X%02X%02X%02X%02X", id[11], id[10] + id[2], id[9], id[8] + id[0], id[7], id[6]); str = str_buf; break; } case USBD_IDX_CONFIG_STR: if (pdev->dev_speed == USBD_SPEED_HIGH) { str = USBD_CONFIGURATION_HS_STRING; } else { str = USBD_CONFIGURATION_FS_STRING; } break; case USBD_IDX_INTERFACE_STR: if (pdev->dev_speed == USBD_SPEED_HIGH) { str = USBD_INTERFACE_HS_STRING; } else { str = USBD_INTERFACE_FS_STRING; } break; default: // invalid string index return NULL; } uint8_t *str_desc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->usbd_str_desc; USBD_GetString((uint8_t*)str, str_desc, length); return str_desc; } const USBD_DescriptorsTypeDef USBD_Descriptors = { USBD_DeviceDescriptor, USBD_StrDescriptor, }; /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbd_desc.h000066400000000000000000000030641357706137100202500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014, 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_USBD_DESC_H #define MICROPY_INCLUDED_STM32_USBD_DESC_H #include "usbd_cdc_msc_hid.h" extern const USBD_DescriptorsTypeDef USBD_Descriptors; void USBD_SetVIDPIDRelease(usbd_cdc_msc_hid_state_t *usbd, uint16_t vid, uint16_t pid, uint16_t device_release_num, int cdc_only); #endif // MICROPY_INCLUDED_STM32_USBD_DESC_H micropython-1.12/ports/stm32/usbd_hid_interface.c000066400000000000000000000051341357706137100221110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "usbd_hid_interface.h" #include "py/mpstate.h" #include "py/mperrno.h" #include "py/mphal.h" #include "usb.h" #if MICROPY_HW_USB_HID uint8_t *usbd_hid_init(usbd_hid_state_t *hid_in) { usbd_hid_itf_t *hid = (usbd_hid_itf_t*)hid_in; hid->report_in_len = USBD_HID_REPORT_INVALID; return &hid->report_in_buf[0]; // location to place first incoming report } int8_t usbd_hid_receive(usbd_hid_state_t *hid_in, size_t len) { // Incoming report: save the length but don't schedule next report until user reads this one usbd_hid_itf_t *hid = (usbd_hid_itf_t*)hid_in; hid->report_in_len = len; return USBD_OK; } int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_ms) { // Wait for an incoming report uint32_t t0 = mp_hal_ticks_ms(); while (hid->report_in_len == USBD_HID_REPORT_INVALID) { if (mp_hal_ticks_ms() - t0 >= timeout_ms || query_irq() == IRQ_STATE_DISABLED) { return -MP_ETIMEDOUT; } MICROPY_EVENT_POLL_HOOK } // Copy bytes from report to user buffer int n = MIN(len, hid->report_in_len); memcpy(buf, &hid->report_in_buf[0], n); // Schedule to receive next incoming report hid->report_in_len = USBD_HID_REPORT_INVALID; USBD_HID_ReceivePacket(&hid->base, &hid->report_in_buf[0]); // Return number of bytes read into user buffer return n; } #endif // MICROPY_HW_USB_HID micropython-1.12/ports/stm32/usbd_hid_interface.h000066400000000000000000000013471357706137100221200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ */ #ifndef MICROPY_INCLUDED_STM32_USBD_HID_INTERFACE_H #define MICROPY_INCLUDED_STM32_USBD_HID_INTERFACE_H #include #include "usbd_cdc_msc_hid.h" #define USBD_HID_REPORT_INVALID ((size_t)-1) typedef struct _usbd_hid_itf_t { usbd_hid_state_t base; // state for the base HID layer volatile size_t report_in_len; uint8_t report_in_buf[HID_DATA_FS_MAX_PACKET_SIZE]; } usbd_hid_itf_t; static inline int usbd_hid_rx_num(usbd_hid_itf_t *hid) { return hid->report_in_len != USBD_HID_REPORT_INVALID; } int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_ms); #endif // MICROPY_INCLUDED_STM32_USBD_HID_INTERFACE_H micropython-1.12/ports/stm32/usbd_msc_interface.c000066400000000000000000000246511357706137100221340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "usbd_cdc_msc_hid.h" #include "usbd_msc_interface.h" #include "extmod/vfs.h" #include "storage.h" #include "sdcard.h" #if MICROPY_HW_USB_MSC // This flag is needed to support removal of the medium, so that the USB drive // can be unmounted and won't be remounted automatically. #define FLAGS_STARTED (0x01) #define FLAGS_READONLY (0x02) STATIC const void *usbd_msc_lu_data[USBD_MSC_MAX_LUN]; STATIC uint8_t usbd_msc_lu_num; STATIC uint16_t usbd_msc_lu_flags; static inline void lu_flag_set(uint8_t lun, uint8_t flag) { usbd_msc_lu_flags |= flag << (lun * 2); } static inline void lu_flag_clr(uint8_t lun, uint8_t flag) { usbd_msc_lu_flags &= ~(flag << (lun * 2)); } static inline bool lu_flag_is_set(uint8_t lun, uint8_t flag) { return usbd_msc_lu_flags & (flag << (lun * 2)); } // Sent in response to MODE SENSE(6) command const uint8_t USBD_MSC_Mode_Sense6_Data[4] = { 0x03, // mode data length 0x00, // medium type 0x00, // bit 7: write protect 0x00, // block descriptor length }; // Sent in response to MODE SENSE(10) command const uint8_t USBD_MSC_Mode_Sense10_Data[8] = { 0x00, 0x06, // mode data length 0x00, // medium type 0x00, // bit 7: write protect 0x00, 0x00, 0x00, 0x00, // block descriptor length }; STATIC const uint8_t usbd_msc_vpd00[6] = { 0x00, // peripheral qualifier; peripheral device type 0x00, // page code 0x00, // reserved 2, // page length (additional bytes beyond this entry) 0x00, // page 0x00 supported 0x83, // page 0x83 supported }; STATIC const uint8_t usbd_msc_vpd83[4] = { 0x00, // peripheral qualifier; peripheral device type 0x83, // page code 0x00, 0x00, // page length (additional bytes beyond this entry) }; STATIC const int8_t usbd_msc_inquiry_data[36] = { 0x00, // peripheral qualifier; peripheral device type 0x80, // 0x00 for a fixed drive, 0x80 for a removable drive 0x02, // version 0x02, // response data format (STANDARD_INQUIRY_DATA_LEN - 5), // additional length 0x00, // various flags 0x00, // various flags 0x00, // various flags 'M', 'i', 'c', 'r', 'o', 'P', 'y', ' ', // Manufacturer : 8 bytes 'p', 'y', 'b', 'o', 'a', 'r', 'd', ' ', // Product : 16 Bytes 'F', 'l', 'a', 's', 'h', ' ', ' ', ' ', '1', '.', '0' ,'0', // Version : 4 Bytes }; // Set the logical units that will be exposed over MSC void usbd_msc_init_lu(size_t lu_n, const void *lu_data) { usbd_msc_lu_num = MIN(lu_n, USBD_MSC_MAX_LUN); memcpy(usbd_msc_lu_data, lu_data, sizeof(void*) * usbd_msc_lu_num); usbd_msc_lu_flags = 0; } // Helper function to perform an ioctl on a logical unit STATIC int lu_ioctl(uint8_t lun, int op, uint32_t *data) { if (lun >= usbd_msc_lu_num) { return -1; } const void *lu = usbd_msc_lu_data[lun]; if (lu == &pyb_flash_type) { switch (op) { case MP_BLOCKDEV_IOCTL_INIT: storage_init(); *data = 0; return 0; case MP_BLOCKDEV_IOCTL_SYNC: storage_flush(); return 0; case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: *data = storage_get_block_size(); return 0; case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: *data = storage_get_block_count(); return 0; default: return -1; } #if MICROPY_HW_ENABLE_SDCARD } else if (lu == &pyb_sdcard_type #if MICROPY_HW_ENABLE_MMCARD || lu == &pyb_mmcard_type #endif ) { switch (op) { case MP_BLOCKDEV_IOCTL_INIT: if (!sdcard_power_on()) { return -1; } *data = 0; return 0; case MP_BLOCKDEV_IOCTL_SYNC: return 0; case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: *data = SDCARD_BLOCK_SIZE; return 0; case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: *data = sdcard_get_capacity_in_bytes() / (uint64_t)SDCARD_BLOCK_SIZE; return 0; default: return -1; } #endif } else { return -1; } } // Initialise all logical units (it's only ever called once, with lun_in=0) STATIC int8_t usbd_msc_Init(uint8_t lun_in) { if (lun_in != 0) { return 0; } for (int lun = 0; lun < usbd_msc_lu_num; ++lun) { uint32_t data = 0; int res = lu_ioctl(lun, MP_BLOCKDEV_IOCTL_INIT, &data); if (res != 0) { lu_flag_clr(lun, FLAGS_STARTED); } else { lu_flag_set(lun, FLAGS_STARTED); if (data) { lu_flag_set(lun, FLAGS_READONLY); } } } return 0; } // Process SCSI INQUIRY command for the logical unit STATIC int usbd_msc_Inquiry(uint8_t lun, const uint8_t *params, uint8_t *data_out) { if (params[1] & 1) { // EVPD set - return vital product data parameters uint8_t page_code = params[2]; switch (page_code) { case 0x00: // Supported VPD pages memcpy(data_out, usbd_msc_vpd00, sizeof(usbd_msc_vpd00)); return sizeof(usbd_msc_vpd00); case 0x83: // Device identification memcpy(data_out, usbd_msc_vpd83, sizeof(usbd_msc_vpd83)); return sizeof(usbd_msc_vpd83); default: // Unsupported return -1; } } // A standard inquiry if (lun >= usbd_msc_lu_num) { return -1; } uint8_t alloc_len = params[3] << 8 | params[4]; int len = MIN(sizeof(usbd_msc_inquiry_data), alloc_len); memcpy(data_out, usbd_msc_inquiry_data, len); #if MICROPY_HW_ENABLE_SDCARD const void *lu = usbd_msc_lu_data[lun]; if (len == sizeof(usbd_msc_inquiry_data)) { if (lu == &pyb_sdcard_type) { memcpy(data_out + 24, "SDCard", sizeof("SDCard") - 1); } #if MICROPY_HW_ENABLE_MMCARD else if (lu == &pyb_mmcard_type) { memcpy(data_out + 24, "MMCard", sizeof("MMCard") - 1); } #endif } #endif return len; } // Get storage capacity of a logical unit STATIC int8_t usbd_msc_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { uint32_t block_size_u32 = 0; int res = lu_ioctl(lun, MP_BLOCKDEV_IOCTL_BLOCK_SIZE, &block_size_u32); if (res != 0) { return -1; } *block_size = block_size_u32; return lu_ioctl(lun, MP_BLOCKDEV_IOCTL_BLOCK_COUNT, block_num); } // Check if a logical unit is ready STATIC int8_t usbd_msc_IsReady(uint8_t lun) { if (lun >= usbd_msc_lu_num) { return -1; } return lu_flag_is_set(lun, FLAGS_STARTED) ? 0 : -1; } // Check if a logical unit is write protected STATIC int8_t usbd_msc_IsWriteProtected(uint8_t lun) { if (lun >= usbd_msc_lu_num) { return -1; } return lu_flag_is_set(lun, FLAGS_READONLY) ? 1 : 0; } // Start or stop a logical unit STATIC int8_t usbd_msc_StartStopUnit(uint8_t lun, uint8_t started) { if (lun >= usbd_msc_lu_num) { return -1; } if (started) { lu_flag_set(lun, FLAGS_STARTED); } else { lu_flag_clr(lun, FLAGS_STARTED); } return 0; } // Prepare a logical unit for possible removal STATIC int8_t usbd_msc_PreventAllowMediumRemoval(uint8_t lun, uint8_t param) { uint32_t dummy; // Sync the logical unit so the device can be unplugged/turned off return lu_ioctl(lun, MP_BLOCKDEV_IOCTL_SYNC, &dummy); } // Read data from a logical unit STATIC int8_t usbd_msc_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { if (lun >= usbd_msc_lu_num) { return -1; } const void *lu = usbd_msc_lu_data[lun]; if (lu == &pyb_flash_type) { storage_read_blocks(buf, blk_addr, blk_len); return 0; #if MICROPY_HW_ENABLE_SDCARD } else if (lu == &pyb_sdcard_type #if MICROPY_HW_ENABLE_MMCARD || lu == &pyb_mmcard_type #endif ) { if (sdcard_read_blocks(buf, blk_addr, blk_len) == 0) { return 0; } #endif } return -1; } // Write data to a logical unit STATIC int8_t usbd_msc_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { if (lun >= usbd_msc_lu_num) { return -1; } const void *lu = usbd_msc_lu_data[lun]; if (lu == &pyb_flash_type) { storage_write_blocks(buf, blk_addr, blk_len); return 0; #if MICROPY_HW_ENABLE_SDCARD } else if (lu == &pyb_sdcard_type #if MICROPY_HW_ENABLE_MMCARD || lu == &pyb_mmcard_type #endif ) { if (sdcard_write_blocks(buf, blk_addr, blk_len) == 0) { return 0; } #endif } return -1; } // Get the number of attached logical units STATIC int8_t usbd_msc_GetMaxLun(void) { return usbd_msc_lu_num - 1; } // Table of operations for the SCSI layer to call const USBD_StorageTypeDef usbd_msc_fops = { usbd_msc_Init, usbd_msc_Inquiry, usbd_msc_GetCapacity, usbd_msc_IsReady, usbd_msc_IsWriteProtected, usbd_msc_StartStopUnit, usbd_msc_PreventAllowMediumRemoval, usbd_msc_Read, usbd_msc_Write, usbd_msc_GetMaxLun, }; #endif // MICROPY_HW_USB_MSC micropython-1.12/ports/stm32/usbd_msc_interface.h000066400000000000000000000027671357706137100221450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H #define MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H #define USBD_MSC_MAX_LUN (2) extern const USBD_StorageTypeDef usbd_msc_fops; void usbd_msc_init_lu(size_t lu_n, const void *lu_data); #endif // MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H micropython-1.12/ports/stm32/usbdev/000077500000000000000000000000001357706137100174315ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbdev/class/000077500000000000000000000000001357706137100205365ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbdev/class/inc/000077500000000000000000000000001357706137100213075ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h000066400000000000000000000152461357706137100247240ustar00rootroot00000000000000#ifndef _USB_CDC_MSC_CORE_H_ #define _USB_CDC_MSC_CORE_H_ #include "usbd_cdc_msc_hid0.h" #include "usbd_msc_bot.h" #include "usbd_msc_scsi.h" #include "usbd_ioreq.h" // These are included to get direct access the MICROPY_HW_USB_xxx config #include "py/mpconfig.h" // Work out if we should support USB high-speed device mode #if MICROPY_HW_USB_HS \ && (!MICROPY_HW_USB_HS_IN_FS || defined(STM32F723xx) || defined(STM32F733xx)) #define USBD_SUPPORT_HS_MODE (1) #else #define USBD_SUPPORT_HS_MODE (0) #endif // Should be maximum of possible config descriptors that might be configured // Maximum is: 9 + MSC + NxCDC + HID #define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + (23) + MICROPY_HW_USB_CDC_NUM * (8 + 58) + (9 + 9 + 7 + 7)) // CDC, MSC and HID packet sizes #define MSC_FS_MAX_PACKET (64) #define MSC_HS_MAX_PACKET (512) #define CDC_DATA_FS_MAX_PACKET_SIZE (64) // endpoint IN & OUT packet size #define CDC_DATA_HS_MAX_PACKET_SIZE (512) // endpoint IN & OUT packet size #if USBD_SUPPORT_HS_MODE #define CDC_DATA_MAX_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE #else #define CDC_DATA_MAX_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE #endif #define MSC_MEDIA_PACKET (2048) // was 8192; how low can it go whilst still working? #define HID_DATA_FS_MAX_PACKET_SIZE (64) // endpoint IN & OUT packet size // Need to define here for BOT and SCSI layers #define MSC_IN_EP (0x81) #define MSC_OUT_EP (0x01) struct _usbd_cdc_msc_hid_state_t; typedef struct { struct _usbd_cdc_msc_hid_state_t *usbd; // The parent USB device uint32_t ctl_packet_buf[CDC_DATA_MAX_PACKET_SIZE / 4]; // Force 32-bit alignment uint8_t iface_num; uint8_t in_ep; uint8_t out_ep; uint8_t cur_request; uint8_t cur_length; volatile uint8_t tx_in_progress; } usbd_cdc_state_t; typedef struct _USBD_STORAGE { int8_t (* Init) (uint8_t lun); int (* Inquiry) (uint8_t lun, const uint8_t *params, uint8_t *data_out); int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size); int8_t (* IsReady) (uint8_t lun); int8_t (* IsWriteProtected) (uint8_t lun); int8_t (* StartStopUnit)(uint8_t lun, uint8_t started); int8_t (* PreventAllowMediumRemoval)(uint8_t lun, uint8_t param0); int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); int8_t (* GetMaxLun)(void); } USBD_StorageTypeDef; typedef struct { uint32_t max_lun; uint32_t interface; uint8_t bot_state; uint8_t bot_status; uint16_t bot_data_length; uint8_t bot_data[MSC_MEDIA_PACKET]; USBD_MSC_BOT_CBWTypeDef cbw; USBD_MSC_BOT_CSWTypeDef csw; USBD_SCSI_SenseTypeDef scsi_sense [SENSE_LIST_DEEPTH]; uint8_t scsi_sense_head; uint8_t scsi_sense_tail; uint16_t scsi_blk_size; uint32_t scsi_blk_nbr; uint32_t scsi_blk_addr_in_blks; uint32_t scsi_blk_len; // operations of the underlying block device USBD_StorageTypeDef *bdev_ops; } USBD_MSC_BOT_HandleTypeDef; typedef enum { HID_IDLE = 0, HID_BUSY, } HID_StateTypeDef; typedef struct { struct _usbd_cdc_msc_hid_state_t *usbd; // The parent USB device uint8_t iface_num; uint8_t in_ep; uint8_t out_ep; uint8_t state; uint8_t ctl_protocol; uint8_t ctl_idle_state; uint8_t ctl_alt_setting; uint8_t *desc; const uint8_t *report_desc; } usbd_hid_state_t; typedef struct _usbd_cdc_msc_hid_state_t { USBD_HandleTypeDef *pdev; uint8_t usbd_mode; uint16_t usbd_config_desc_size; #if MICROPY_HW_USB_MSC USBD_MSC_BOT_HandleTypeDef MSC_BOT_ClassData; #endif // RAM to hold the current descriptors, which we configure on the fly __ALIGN_BEGIN uint8_t usbd_device_desc[USB_LEN_DEV_DESC] __ALIGN_END; __ALIGN_BEGIN uint8_t usbd_str_desc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; __ALIGN_BEGIN uint8_t usbd_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END; usbd_cdc_state_t *cdc[MICROPY_HW_USB_CDC_NUM]; #if MICROPY_HW_USB_HID usbd_hid_state_t *hid; #endif } usbd_cdc_msc_hid_state_t; extern const uint8_t USBD_MSC_Mode_Sense6_Data[4]; extern const uint8_t USBD_MSC_Mode_Sense10_Data[8]; #define USBD_HID_MOUSE_MAX_PACKET (4) #define USBD_HID_MOUSE_REPORT_DESC_SIZE (74) extern const uint8_t USBD_HID_MOUSE_ReportDesc[USBD_HID_MOUSE_REPORT_DESC_SIZE]; #define USBD_HID_KEYBOARD_MAX_PACKET (8) #define USBD_HID_KEYBOARD_REPORT_DESC_SIZE (63) extern const uint8_t USBD_HID_KEYBOARD_ReportDesc[USBD_HID_KEYBOARD_REPORT_DESC_SIZE]; extern const USBD_ClassTypeDef USBD_CDC_MSC_HID; static inline uint32_t usbd_msc_max_packet(USBD_HandleTypeDef *pdev) { #if USBD_SUPPORT_HS_MODE if (pdev->dev_speed == USBD_SPEED_HIGH) { return MSC_HS_MAX_PACKET; } else #endif { return MSC_FS_MAX_PACKET; } } static inline uint32_t usbd_cdc_max_packet(USBD_HandleTypeDef *pdev) { #if USBD_SUPPORT_HS_MODE if (pdev->dev_speed == USBD_SPEED_HIGH) { return CDC_DATA_HS_MAX_PACKET_SIZE; } else #endif { return CDC_DATA_FS_MAX_PACKET_SIZE; } } // returns 0 on success, -1 on failure int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t max_endpoint); // returns the current usb mode uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd); uint8_t USBD_CDC_ReceivePacket(usbd_cdc_state_t *cdc, uint8_t *buf); uint8_t USBD_CDC_TransmitPacket(usbd_cdc_state_t *cdc, size_t len, const uint8_t *buf); #if MICROPY_HW_USB_MSC static inline void USBD_MSC_RegisterStorage(usbd_cdc_msc_hid_state_t *usbd, USBD_StorageTypeDef *fops) { usbd->MSC_BOT_ClassData.bdev_ops = fops; } #endif uint8_t USBD_HID_ReceivePacket(usbd_hid_state_t *usbd, uint8_t *buf); int USBD_HID_CanSendReport(usbd_hid_state_t *usbd); uint8_t USBD_HID_SendReport(usbd_hid_state_t *usbd, uint8_t *report, uint16_t len); uint8_t USBD_HID_SetNAK(usbd_hid_state_t *usbd); uint8_t USBD_HID_ClearNAK(usbd_hid_state_t *usbd); // These are provided externally to implement the CDC interface uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc); void usbd_cdc_deinit(usbd_cdc_state_t *cdc); void usbd_cdc_tx_ready(usbd_cdc_state_t *cdc); int8_t usbd_cdc_control(usbd_cdc_state_t *cdc, uint8_t cmd, uint8_t* pbuf, uint16_t length); int8_t usbd_cdc_receive(usbd_cdc_state_t *cdc, size_t len); // These are provided externally to implement the HID interface uint8_t *usbd_hid_init(usbd_hid_state_t *hid); int8_t usbd_hid_receive(usbd_hid_state_t *hid, size_t len); #endif // _USB_CDC_MSC_CORE_H_ micropython-1.12/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h000066400000000000000000000064541357706137100250050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_USBDEV_CLASS_INC_USBD_CDC_MSC_HID0_H #define MICROPY_INCLUDED_STM32_USBDEV_CLASS_INC_USBD_CDC_MSC_HID0_H // these are exports for the CDC/MSC/HID interface that are independent // from any other definitions/declarations // These can be or'd together (but not all combinations may be available) #define USBD_MODE_IFACE_MASK (0x7f) #define USBD_MODE_IFACE_CDC(i) (0x01 << (i)) #define USBD_MODE_IFACE_HID (0x10) #define USBD_MODE_IFACE_MSC (0x20) #define USBD_MODE_HIGH_SPEED (0x80) // Convenience macros for supported mode combinations #define USBD_MODE_CDC (USBD_MODE_IFACE_CDC(0)) #define USBD_MODE_CDC2 (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1)) #define USBD_MODE_CDC3 (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2)) #define USBD_MODE_CDC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_HID) #define USBD_MODE_CDC_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC) #define USBD_MODE_CDC2_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC) #define USBD_MODE_CDC3_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2) | USBD_MODE_IFACE_MSC) #define USBD_MODE_CDC_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) #define USBD_MODE_CDC2_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) #define USBD_MODE_CDC3_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) #define USBD_MODE_HID (USBD_MODE_IFACE_HID) #define USBD_MODE_MSC (USBD_MODE_IFACE_MSC) #define USBD_MODE_MSC_HID (USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) typedef struct _USBD_HID_ModeInfoTypeDef { uint8_t subclass; // 0=no sub class, 1=boot uint8_t protocol; // 0=none, 1=keyboard, 2=mouse uint8_t max_packet_len; // only support up to 255 uint8_t polling_interval; // in units of 1ms uint8_t report_desc_len; const uint8_t *report_desc; } USBD_HID_ModeInfoTypeDef; #endif // MICROPY_INCLUDED_STM32_USBDEV_CLASS_INC_USBD_CDC_MSC_HID0_H micropython-1.12/ports/stm32/usbdev/class/inc/usbd_msc_bot.h000066400000000000000000000076061357706137100241340ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_msc_bot.h * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief header for the usbd_msc_bot.c file ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #include "usbd_core.h" /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USBD_MSC_BOT_H #define __USBD_MSC_BOT_H /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup MSC_BOT * @brief This file is the Header file for usbd_bot.c * @{ */ /** @defgroup USBD_CORE_Exported_Defines * @{ */ #define USBD_BOT_IDLE 0 /* Idle state */ #define USBD_BOT_DATA_OUT 1 /* Data Out state */ #define USBD_BOT_DATA_IN 2 /* Data In state */ #define USBD_BOT_LAST_DATA_IN 3 /* Last Data In Last */ #define USBD_BOT_SEND_DATA 4 /* Send Immediate data */ #define USBD_BOT_NO_DATA 5 /* No data Stage */ #define USBD_BOT_CBW_SIGNATURE 0x43425355 #define USBD_BOT_CSW_SIGNATURE 0x53425355 #define USBD_BOT_CBW_LENGTH 31 #define USBD_BOT_CSW_LENGTH 13 #define USBD_BOT_MAX_DATA 256 /* CSW Status Definitions */ #define USBD_CSW_CMD_PASSED 0x00 #define USBD_CSW_CMD_FAILED 0x01 #define USBD_CSW_PHASE_ERROR 0x02 /* BOT Status */ #define USBD_BOT_STATUS_NORMAL 0 #define USBD_BOT_STATUS_RECOVERY 1 #define USBD_BOT_STATUS_ERROR 2 #define USBD_DIR_IN 0 #define USBD_DIR_OUT 1 #define USBD_BOTH_DIR 2 /** * @} */ /** @defgroup MSC_CORE_Private_TypesDefinitions * @{ */ typedef struct { uint32_t dSignature; uint32_t dTag; uint32_t dDataLength; uint8_t bmFlags; uint8_t bLUN; uint8_t bCBLength; uint8_t CB[16]; uint8_t ReservedForAlign; } USBD_MSC_BOT_CBWTypeDef; typedef struct { uint32_t dSignature; uint32_t dTag; uint32_t dDataResidue; uint8_t bStatus; uint8_t ReservedForAlign[3]; } USBD_MSC_BOT_CSWTypeDef; /** * @} */ /** @defgroup USBD_CORE_Exported_Types * @{ */ /** * @} */ /** @defgroup USBD_CORE_Exported_FunctionsPrototypes * @{ */ void MSC_BOT_Init (USBD_HandleTypeDef *pdev); void MSC_BOT_Reset (USBD_HandleTypeDef *pdev); void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev); void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum); void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum); void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev, uint8_t CSW_Status); void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev, uint8_t epnum); /** * @} */ #endif /* __USBD_MSC_BOT_H */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/class/inc/usbd_msc_scsi.h000066400000000000000000000140221357706137100242770ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_msc_scsi.h * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief header for the usbd_msc_scsi.c file ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USBD_MSC_SCSI_H #define __USBD_MSC_SCSI_H /* Includes ------------------------------------------------------------------*/ #include "usbd_def.h" /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_SCSI * @brief header file for the storage disk file * @{ */ /** @defgroup USBD_SCSI_Exported_Defines * @{ */ #define SENSE_LIST_DEEPTH 4 /* SCSI Commands */ #define SCSI_FORMAT_UNIT 0x04 #define SCSI_INQUIRY 0x12 #define SCSI_MODE_SELECT6 0x15 #define SCSI_MODE_SELECT10 0x55 #define SCSI_MODE_SENSE6 0x1A #define SCSI_MODE_SENSE10 0x5A #define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E #define SCSI_SYNCHRONIZE_CACHE10 0x35 #define SCSI_SYNCHRONIZE_CACHE16 0x91 #define SCSI_READ6 0x08 #define SCSI_READ10 0x28 #define SCSI_READ12 0xA8 #define SCSI_READ16 0x88 #define SCSI_READ_CAPACITY10 0x25 #define SCSI_READ_CAPACITY16 0x9E #define SCSI_REQUEST_SENSE 0x03 #define SCSI_START_STOP_UNIT 0x1B #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_WRITE6 0x0A #define SCSI_WRITE10 0x2A #define SCSI_WRITE12 0xAA #define SCSI_WRITE16 0x8A #define SCSI_VERIFY10 0x2F #define SCSI_VERIFY12 0xAF #define SCSI_VERIFY16 0x8F #define SCSI_SEND_DIAGNOSTIC 0x1D #define SCSI_READ_FORMAT_CAPACITIES 0x23 #define NO_SENSE 0 #define RECOVERED_ERROR 1 #define NOT_READY 2 #define MEDIUM_ERROR 3 #define HARDWARE_ERROR 4 #define ILLEGAL_REQUEST 5 #define UNIT_ATTENTION 6 #define DATA_PROTECT 7 #define BLANK_CHECK 8 #define VENDOR_SPECIFIC 9 #define COPY_ABORTED 10 #define ABORTED_COMMAND 11 #define VOLUME_OVERFLOW 13 #define MISCOMPARE 14 #define INVALID_CDB 0x20 #define INVALID_FIELED_IN_COMMAND 0x24 #define PARAMETER_LIST_LENGTH_ERROR 0x1A #define INVALID_FIELD_IN_PARAMETER_LIST 0x26 #define ADDRESS_OUT_OF_RANGE 0x21 #define MEDIUM_NOT_PRESENT 0x3A #define MEDIUM_HAVE_CHANGED 0x28 #define WRITE_PROTECTED 0x27 #define UNRECOVERED_READ_ERROR 0x11 #define WRITE_FAULT 0x03 #define READ_FORMAT_CAPACITY_DATA_LEN 0x0C #define READ_CAPACITY10_DATA_LEN 0x08 #define MODE_SENSE10_DATA_LEN 0x08 #define MODE_SENSE6_DATA_LEN 0x04 #define REQUEST_SENSE_DATA_LEN 0x12 #define STANDARD_INQUIRY_DATA_LEN 0x24 #define BLKVFY 0x04 extern uint8_t Page00_Inquiry_Data[]; extern uint8_t Standard_Inquiry_Data[]; extern uint8_t Standard_Inquiry_Data2[]; extern uint8_t Mode_Sense6_data[]; extern uint8_t Mode_Sense10_data[]; extern uint8_t Scsi_Sense_Data[]; extern uint8_t ReadCapacity10_Data[]; extern uint8_t ReadFormatCapacity_Data []; /** * @} */ /** @defgroup USBD_SCSI_Exported_TypesDefinitions * @{ */ typedef struct _SENSE_ITEM { char Skey; union { struct _ASCs { char ASC; char ASCQ; }b; unsigned int ASC; char *pData; } w; } USBD_SCSI_SenseTypeDef; /** * @} */ /** @defgroup USBD_SCSI_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBD_SCSI_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBD_SCSI_Exported_FunctionsPrototype * @{ */ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd); void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC); /** * @} */ #endif /* __USBD_MSC_SCSI_H */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/class/src/000077500000000000000000000000001357706137100213255ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c000066400000000000000000001416151357706137100247350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include STM32_HAL_H #include "usbd_ioreq.h" #include "usbd_cdc_msc_hid.h" #if MICROPY_HW_ENABLE_USB #define HEAD_DESC_SIZE (9) #define MSC_CLASS_DESC_SIZE (9 + 7 + 7) #define CDC_CLASS_DESC_SIZE (8 + 58) #define HID_CLASS_DESC_SIZE (9 + 9 + 7 + 7) #define MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC_MSC_TEMPLATE_CDC_DESC_OFFSET (40) #define CDC2_TEMPLATE_CDC_DESC_OFFSET (9 + 8) #define CDC2_TEMPLATE_CDC2_DESC_OFFSET (9 + (8 + 58) + 8) #define CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8) #define CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8) #define CDC3_TEMPLATE_CDC_DESC_OFFSET (9 + 8) #define CDC3_TEMPLATE_CDC2_DESC_OFFSET (9 + (8 + 58) + 8) #define CDC3_TEMPLATE_CDC3_DESC_OFFSET (9 + (8 + 58) + (8 + 58) + 8) #define CDC3_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC3_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8) #define CDC3_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8) #define CDC3_MSC_TEMPLATE_CDC3_DESC_OFFSET (9 + 23 + (8 + 58) + (8 + 58) + 8) #define CDC_HID_TEMPLATE_CDC_DESC_OFFSET (49) #define CDC_TEMPLATE_CDC_DESC_OFFSET (9) #define CDC_DESC_OFFSET_INTR_INTERVAL (34) #define CDC_DESC_OFFSET_OUT_MAX_PACKET_LO (48) #define CDC_DESC_OFFSET_OUT_MAX_PACKET_HI (49) #define CDC_DESC_OFFSET_IN_MAX_PACKET_LO (55) #define CDC_DESC_OFFSET_IN_MAX_PACKET_HI (56) #define HID_DESC_OFFSET_SUBCLASS (6) #define HID_DESC_OFFSET_PROTOCOL (7) #define HID_DESC_OFFSET_SUBDESC (9) #define HID_DESC_OFFSET_REPORT_DESC_LEN (16) #define HID_DESC_OFFSET_IN_EP (20) #define HID_DESC_OFFSET_MAX_PACKET_LO (22) #define HID_DESC_OFFSET_MAX_PACKET_HI (23) #define HID_DESC_OFFSET_POLLING_INTERVAL (24) #define HID_DESC_OFFSET_OUT_EP (27) #define HID_DESC_OFFSET_MAX_PACKET_OUT_LO (29) #define HID_DESC_OFFSET_MAX_PACKET_OUT_HI (30) #define HID_DESC_OFFSET_POLLING_INTERVAL_OUT (31) #define HID_SUBDESC_LEN (9) #define CDC_IFACE_NUM_ALONE (0) #define CDC_IFACE_NUM_WITH_MSC (1) #define CDC2_IFACE_NUM_WITH_CDC (2) #define CDC3_IFACE_NUM_WITH_CDC (4) #define CDC2_IFACE_NUM_WITH_MSC (3) #define CDC3_IFACE_NUM_WITH_MSC (5) #define CDC_IFACE_NUM_WITH_HID (1) #define MSC_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_MSC (1) #define HID_IFACE_NUM_WITH_CDC_MSC (3) #define HID_IFACE_NUM_WITH_CDC2_MSC (5) #define HID_IFACE_NUM_WITH_CDC3_MSC (7) #define CDC_IN_EP(i) (0x83 + 2 * (i)) #define CDC_OUT_EP(i) (0x03 + 2 * (i)) #define CDC_CMD_EP(i) (0x82 + 2 * (i)) #define HID_IN_EP_WITH_CDC (0x81) #define HID_OUT_EP_WITH_CDC (0x01) #define HID_IN_EP_WITH_MSC (0x83) #define HID_OUT_EP_WITH_MSC (0x03) #define HID_IN_EP_WITH_CDC_MSC (0x84) #define HID_OUT_EP_WITH_CDC_MSC (0x04) #define HID_IN_EP_WITH_CDC2_MSC (0x86) #define HID_OUT_EP_WITH_CDC2_MSC (0x06) #define HID_IN_EP_WITH_CDC3_MSC (0x88) #define HID_OUT_EP_WITH_CDC3_MSC (0x08) #define USB_DESC_TYPE_ASSOCIATION (0x0b) #define CDC_CMD_PACKET_SIZE (8) // Control Endpoint Packet size #define BOT_GET_MAX_LUN (0xfe) #define BOT_RESET (0xff) #define HID_DESCRIPTOR_TYPE (0x21) #define HID_REPORT_DESC (0x22) #define HID_REQ_SET_PROTOCOL (0x0b) #define HID_REQ_GET_PROTOCOL (0x03) #define HID_REQ_SET_IDLE (0x0a) #define HID_REQ_GET_IDLE (0x02) // Value used in the configuration descriptor for the bmAttributes entry #if MICROPY_HW_USB_SELF_POWERED #define CONFIG_DESC_ATTRIBUTES (0xc0) // self powered #else #define CONFIG_DESC_ATTRIBUTES (0x80) // bus powered #endif // Value used in the configuration descriptor for the bMaxPower entry #if defined(MICROPY_HW_USB_MAX_POWER_MA) #define CONFIG_DESC_MAXPOWER (MICROPY_HW_USB_MAX_POWER_MA / 2) // in units of 2mA #else #define CONFIG_DESC_MAXPOWER (0xfa) // 500mA in units of 2mA #endif #if USBD_SUPPORT_HS_MODE // USB Standard Device Descriptor __ALIGN_BEGIN static uint8_t USBD_CDC_MSC_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = { USB_LEN_DEV_QUALIFIER_DESC, USB_DESC_TYPE_DEVICE_QUALIFIER, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, // same for CDC and MSC (latter being MSC_FS_MAX_PACKET), HID is 0x04 0x01, 0x00, }; #endif // USB partial configuration descriptor static const uint8_t head_desc_data[HEAD_DESC_SIZE] = { //-------------------------------------------------------------------------- // Configuration Descriptor 0x09, // bLength: Configuration Descriptor size USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration 0x00, // wTotalLength -- to be filled in 0x00, // wTotalLength -- to be filled in 0x00, // bNumInterfaces -- to be filled in 0x01, // bConfigurationValue: Configuration value 0x00, // iConfiguration: Index of string descriptor describing the configuration CONFIG_DESC_ATTRIBUTES, // bmAttributes CONFIG_DESC_MAXPOWER, // bMaxPower }; #if MICROPY_HW_USB_MSC // USB MSC partial configuration descriptor static const uint8_t msc_class_desc_data[MSC_CLASS_DESC_SIZE] = { //========================================================================== // MSC only has 1 interface so doesn't need an IAD //-------------------------------------------------------------------------- // Interface Descriptor 0x09, // bLength: Interface Descriptor size USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface descriptor MSC_IFACE_NUM_WITH_CDC, // bInterfaceNumber: Number of Interface 0x00, // bAlternateSetting: Alternate setting 0x02, // bNumEndpoints 0x08, // bInterfaceClass: MSC Class 0x06, // bInterfaceSubClass : SCSI transparent 0x50, // nInterfaceProtocol 0x00, // iInterface: // Endpoint IN descriptor 0x07, // bLength: Endpoint descriptor length USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type MSC_IN_EP, // bEndpointAddress: IN, address 3 0x02, // bmAttributes: Bulk endpoint type LOBYTE(MSC_FS_MAX_PACKET), // wMaxPacketSize HIBYTE(MSC_FS_MAX_PACKET), 0x00, // bInterval: ignore for Bulk transfer // Endpoint OUT descriptor 0x07, // bLength: Endpoint descriptor length USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type MSC_OUT_EP, // bEndpointAddress: OUT, address 3 0x02, // bmAttributes: Bulk endpoint type LOBYTE(MSC_FS_MAX_PACKET), // wMaxPacketSize HIBYTE(MSC_FS_MAX_PACKET), 0x00, // bInterval: ignore for Bulk transfer }; #endif // USB CDC partial configuration descriptor static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { //========================================================================== // Interface Association for CDC VCP 0x08, // bLength: 8 bytes USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD 0x00, // bFirstInterface: first interface for this association -- to be filled in 0x02, // bInterfaceCount: nummber of interfaces for this association 0x02, // bFunctionClass: Communication Interface Class 0x02, // bFunctionSubClass: Abstract Control Model 0x01, // bFunctionProtocol: Common AT commands 0x00, // iFunction: index of string for this function //-------------------------------------------------------------------------- // Interface Descriptor 0x09, // bLength: Interface Descriptor size USB_DESC_TYPE_INTERFACE, // bDescriptorType: Interface 0x00, // bInterfaceNumber: Number of Interface -- to be filled in 0x00, // bAlternateSetting: Alternate setting 0x01, // bNumEndpoints: One endpoints used 0x02, // bInterfaceClass: Communication Interface Class 0x02, // bInterfaceSubClass: Abstract Control Model 0x01, // bInterfaceProtocol: Common AT commands 0x00, // iInterface: // Header Functional Descriptor 0x05, // bLength: Endpoint Descriptor size 0x24, // bDescriptorType: CS_INTERFACE 0x00, // bDescriptorSubtype: Header Func Desc 0x10, // bcdCDC: spec release number 0x01, // ? // Call Management Functional Descriptor 0x05, // bFunctionLength 0x24, // bDescriptorType: CS_INTERFACE 0x01, // bDescriptorSubtype: Call Management Func Desc 0x00, // bmCapabilities: D0+D1 0x00, // bDataInterface -- to be filled in // ACM Functional Descriptor 0x04, // bFunctionLength 0x24, // bDescriptorType: CS_INTERFACE 0x02, // bDescriptorSubtype: Abstract Control Management desc 0x02, // bmCapabilities // Union Functional Descriptor 0x05, // bFunctionLength 0x24, // bDescriptorType: CS_INTERFACE 0x06, // bDescriptorSubtype: Union func desc 0x00, // bMasterInterface: Communication class interface -- to be filled in 0x00, // bSlaveInterface0: Data Class Interface -- to be filled in // Endpoint CMD Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint CDC_CMD_EP(0), // bEndpointAddress 0x03, // bmAttributes: Interrupt LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize: HIBYTE(CDC_CMD_PACKET_SIZE), 0x20, // bInterval: polling interval in frames of 1ms //-------------------------------------------------------------------------- // Data class interface descriptor 0x09, // bLength: Endpoint Descriptor size USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface 0x00, // bInterfaceNumber: Number of Interface -- to be filled in 0x00, // bAlternateSetting: Alternate setting 0x02, // bNumEndpoints: Two endpoints used 0x0A, // bInterfaceClass: CDC 0x00, // bInterfaceSubClass: ? 0x00, // bInterfaceProtocol: ? 0x00, // iInterface: // Endpoint OUT Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint CDC_OUT_EP(0), // bEndpointAddress 0x02, // bmAttributes: Bulk LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), 0x00, // bInterval: ignore for Bulk transfer // Endpoint IN Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint CDC_IN_EP(0), // bEndpointAddress 0x02, // bmAttributes: Bulk LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), 0x00, // bInterval: ignore for Bulk transfer }; #if MICROPY_HW_USB_HID // USB HID partial configuration descriptor static const uint8_t hid_class_desc_data[HID_CLASS_DESC_SIZE] = { //========================================================================== // HID only has 1 interface so doesn't need an IAD //-------------------------------------------------------------------------- // Interface Descriptor 0x09, // bLength: Interface Descriptor size USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface descriptor HID_IFACE_NUM_WITH_CDC, // bInterfaceNumber: Number of Interface 0x00, // bAlternateSetting: Alternate setting 0x02, // bNumEndpoints 0x03, // bInterfaceClass: HID Class 0x01, // bInterfaceSubClass: 0=no sub class, 1=boot 0x02, // nInterfaceProtocol: 0=none, 1=keyboard, 2=mouse 0x00, // iInterface: // HID descriptor 0x09, // bLength: HID Descriptor size HID_DESCRIPTOR_TYPE, // bDescriptorType: HID 0x11, // bcdHID: HID Class Spec release number 0x01, 0x00, // bCountryCode: Hardware target country 0x01, // bNumDescriptors: Number of HID class descriptors to follow 0x22, // bDescriptorType USBD_HID_MOUSE_REPORT_DESC_SIZE, // wItemLength: Total length of Report descriptor 0x00, // Endpoint IN descriptor 0x07, // bLength: Endpoint descriptor length USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type HID_IN_EP_WITH_CDC, // bEndpointAddress: IN 0x03, // bmAttributes: Interrupt endpoint type LOBYTE(USBD_HID_MOUSE_MAX_PACKET), // wMaxPacketSize HIBYTE(USBD_HID_MOUSE_MAX_PACKET), 0x08, // bInterval: Polling interval // Endpoint OUT descriptor 0x07, // bLength: Endpoint descriptor length USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type HID_OUT_EP_WITH_CDC, // bEndpointAddress: OUT 0x03, // bmAttributes: Interrupt endpoint type LOBYTE(USBD_HID_MOUSE_MAX_PACKET), // wMaxPacketSize HIBYTE(USBD_HID_MOUSE_MAX_PACKET), 0x08, // bInterval: Polling interval }; __ALIGN_BEGIN const uint8_t USBD_HID_MOUSE_ReportDesc[USBD_HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END = { 0x05, 0x01, // Usage Page (Generic Desktop), 0x09, 0x02, // Usage (Mouse), 0xA1, 0x01, // Collection (Application), 0x09, 0x01, // Usage (Pointer), 0xA1, 0x00, // Collection (Physical), 0x05, 0x09, // Usage Page (Buttons), 0x19, 0x01, // Usage Minimum (01), 0x29, 0x03, // Usage Maximum (03), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x01, // Logical Maximum (1), 0x95, 0x03, // Report Count (3), 0x75, 0x01, // Report Size (1), 0x81, 0x02, // Input(Data, Variable, Absolute), -- 3 button bits 0x95, 0x01, // Report Count(1), 0x75, 0x05, // Report Size(5), 0x81, 0x01, // Input(Constant), -- 5 bit padding 0x05, 0x01, // Usage Page (Generic Desktop), 0x09, 0x30, // Usage (X), 0x09, 0x31, // Usage (Y), 0x09, 0x38, // Usage (Wheel), 0x15, 0x81, // Logical Minimum (-127), 0x25, 0x7F, // Logical Maximum (127), 0x75, 0x08, // Report Size (8), 0x95, 0x03, // Report Count (3), 0x81, 0x06, // Input(Data, Variable, Relative), -- 3 position bytes (X,Y,Wheel) 0xC0, // End Collection, 0x09, 0x3c, // Usage (Motion Wakeup), 0x05, 0xff, // Usage Page (?), 0x09, 0x01, // Usage (?), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x01, // Logical Maximum (1), 0x75, 0x01, // Report Size(1), 0x95, 0x02, // Report Count(2), 0xb1, 0x22, // ? 0x75, 0x06, // Report Size(6), 0x95, 0x01, // Report Count(1), 0xb1, 0x01, // ? 0xc0 // End Collection }; __ALIGN_BEGIN const uint8_t USBD_HID_KEYBOARD_ReportDesc[USBD_HID_KEYBOARD_REPORT_DESC_SIZE] __ALIGN_END = { // From p69 of http://www.usb.org/developers/devclass_docs/HID1_11.pdf 0x05, 0x01, // Usage Page (Generic Desktop), 0x09, 0x06, // Usage (Keyboard), 0xA1, 0x01, // Collection (Application), 0x05, 0x07, // Usage Page (Key Codes); 0x19, 0xE0, // Usage Minimum (224), 0x29, 0xE7, // Usage Maximum (231), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x01, // Logical Maximum (1), 0x75, 0x01, // Report Size (1), 0x95, 0x08, // Report Count (8), 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte 0x95, 0x01, // Report Count (1), 0x75, 0x08, // Report Size (8), 0x81, 0x01, // Input (Constant), ;Reserved byte 0x95, 0x05, // Report Count (5), 0x75, 0x01, // Report Size (1), 0x05, 0x08, // Usage Page (Page# for LEDs), 0x19, 0x01, // Usage Minimum (1), 0x29, 0x05, // Usage Maximum (5), 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report 0x95, 0x01, // Report Count (1), 0x75, 0x03, // Report Size (3), 0x91, 0x01, // Output (Constant), ;LED report padding 0x95, 0x06, // Report Count (6), 0x75, 0x08, // Report Size (8), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x65, // Logical Maximum(101), 0x05, 0x07, // Usage Page (Key Codes), 0x19, 0x00, // Usage Minimum (0), 0x29, 0x65, // Usage Maximum (101), 0x81, 0x00, // Input (Data, Array), ;Key arrays (6 bytes) 0xC0 // End Collection }; #endif static void make_head_desc(uint8_t *dest, uint16_t len, uint8_t num_itf) { memcpy(dest, head_desc_data, sizeof(head_desc_data)); dest[2] = LOBYTE(len); // wTotalLength dest[3] = HIBYTE(len); dest[4] = num_itf; // bNumInterfaces } #if MICROPY_HW_USB_MSC static size_t make_msc_desc(uint8_t *dest) { memcpy(dest, msc_class_desc_data, sizeof(msc_class_desc_data)); return sizeof(msc_class_desc_data); } #endif static size_t make_cdc_desc(uint8_t *dest, int need_iad, uint8_t iface_num) { if (need_iad) { memcpy(dest, cdc_class_desc_data, sizeof(cdc_class_desc_data)); dest[2] = iface_num; // bFirstInterface dest += 8; } else { memcpy(dest, cdc_class_desc_data + 8, sizeof(cdc_class_desc_data) - 8); } dest[2] = iface_num; // bInterfaceNumber, main class dest[18] = iface_num + 1; // bDataInterface dest[26] = iface_num + 0; // bMasterInterface dest[27] = iface_num + 1; // bSlaveInterface dest[37] = iface_num + 1; // bInterfaceNumber, data class return need_iad ? 8 + 58 : 58; } #if MICROPY_HW_USB_CDC_NUM >= 2 static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, uint8_t cmd_ep, uint8_t out_ep, uint8_t in_ep) { size_t n = make_cdc_desc(dest, need_iad, iface_num); if (need_iad) { dest += 8; } dest[30] = cmd_ep; // bEndpointAddress, main class CMD dest[46] = out_ep; // bEndpointAddress, data class OUT dest[53] = in_ep; // bEndpointAddress, data class IN return n; } #endif #if MICROPY_HW_USB_HID static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t iface_num) { memcpy(dest, hid_class_desc_data, sizeof(hid_class_desc_data)); dest[2] = iface_num; dest[HID_DESC_OFFSET_SUBCLASS] = hid_info->subclass; dest[HID_DESC_OFFSET_PROTOCOL] = hid_info->protocol; dest[HID_DESC_OFFSET_REPORT_DESC_LEN] = hid_info->report_desc_len; dest[HID_DESC_OFFSET_MAX_PACKET_LO] = hid_info->max_packet_len; dest[HID_DESC_OFFSET_MAX_PACKET_HI] = 0; dest[HID_DESC_OFFSET_POLLING_INTERVAL] = hid_info->polling_interval; dest[HID_DESC_OFFSET_MAX_PACKET_OUT_LO] = hid_info->max_packet_len; dest[HID_DESC_OFFSET_MAX_PACKET_OUT_HI] = 0; dest[HID_DESC_OFFSET_POLLING_INTERVAL_OUT] = hid_info->polling_interval; return sizeof(hid_class_desc_data); } #if MICROPY_HW_USB_MSC static size_t make_hid_desc_ep(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t iface_num, uint8_t in_ep, uint8_t out_ep) { size_t n = make_hid_desc(dest, hid_info, iface_num); dest[HID_DESC_OFFSET_IN_EP] = in_ep; dest[HID_DESC_OFFSET_OUT_EP] = out_ep; return n; } #endif #endif // return the saved usb mode uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd) { return usbd->usbd_mode; } int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t max_endpoint) { // save mode usbd->usbd_mode = mode; // construct config desc size_t n = HEAD_DESC_SIZE; uint8_t *d = usbd->usbd_config_desc; uint8_t num_itf = 0; switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) { #if MICROPY_HW_USB_MSC case USBD_MODE_MSC: n += make_msc_desc(d + n); num_itf = 1; break; case USBD_MODE_CDC_MSC: n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; num_itf = 3; break; #if MICROPY_HW_USB_HID case USBD_MODE_CDC_MSC_HID: n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); usbd->hid->desc = d + n; n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC_MSC, HID_IN_EP_WITH_CDC_MSC, HID_OUT_EP_WITH_CDC_MSC); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; usbd->hid->in_ep = HID_IN_EP_WITH_CDC_MSC; usbd->hid->out_ep = HID_OUT_EP_WITH_CDC_MSC; usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC_MSC; usbd->hid->report_desc = hid_info->report_desc; num_itf = 4; break; #endif #endif #if MICROPY_HW_USB_CDC_NUM >= 2 case USBD_MODE_CDC2: { n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_ALONE); n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE; usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_CDC; num_itf = 4; break; } #if MICROPY_HW_USB_MSC case USBD_MODE_CDC2_MSC: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; num_itf = 5; break; } case USBD_MODE_CDC2_MSC_HID: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); usbd->hid->desc = d + n; n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC2_MSC, HID_IN_EP_WITH_CDC2_MSC, HID_OUT_EP_WITH_CDC2_MSC); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; usbd->hid->in_ep = HID_IN_EP_WITH_CDC2_MSC; usbd->hid->out_ep = HID_OUT_EP_WITH_CDC2_MSC; usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC2_MSC; usbd->hid->report_desc = hid_info->report_desc; num_itf = 6; break; } #endif #endif #if MICROPY_HW_USB_CDC_NUM >= 3 case USBD_MODE_CDC3: { n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_ALONE); n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); n += make_cdc_desc_ep(d + n, 1, CDC3_IFACE_NUM_WITH_CDC, CDC_CMD_EP(2), CDC_OUT_EP(2), CDC_IN_EP(2)); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE; usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_CDC; usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_CDC; num_itf = 6; break; } #if MICROPY_HW_USB_MSC case USBD_MODE_CDC3_MSC: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); n += make_cdc_desc_ep(d + n, 1, CDC3_IFACE_NUM_WITH_MSC, CDC_CMD_EP(2), CDC_OUT_EP(2), CDC_IN_EP(2)); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_MSC; num_itf = 7; break; } case USBD_MODE_CDC3_MSC_HID: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); n += make_cdc_desc_ep(d + n, 1, CDC3_IFACE_NUM_WITH_MSC, CDC_CMD_EP(2), CDC_OUT_EP(2), CDC_IN_EP(2)); usbd->hid->desc = d + n; n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC3_MSC, HID_IN_EP_WITH_CDC3_MSC, HID_OUT_EP_WITH_CDC3_MSC); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_MSC; usbd->hid->in_ep = HID_IN_EP_WITH_CDC3_MSC; usbd->hid->out_ep = HID_OUT_EP_WITH_CDC3_MSC; usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC3_MSC; usbd->hid->report_desc = hid_info->report_desc; num_itf = 8; break; } #endif #endif #if MICROPY_HW_USB_HID case USBD_MODE_CDC_HID: usbd->hid->desc = d + n; n += make_hid_desc(d + n, hid_info, HID_IFACE_NUM_WITH_CDC); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_HID); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_HID; usbd->hid->in_ep = HID_IN_EP_WITH_CDC; usbd->hid->out_ep = HID_OUT_EP_WITH_CDC; usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC; usbd->hid->report_desc = hid_info->report_desc; num_itf = 3; break; #endif case USBD_MODE_CDC: n += make_cdc_desc(d + n, 0, CDC_IFACE_NUM_ALONE); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE; num_itf = 2; break; /* // not implemented case USBD_MODE_MSC_HID: hid_in_ep = HID_IN_EP_WITH_MSC; hid_out_ep = HID_OUT_EP_WITH_MSC; hid_iface_num = HID_IFACE_NUM_WITH_MSC; break; */ default: // mode not supported return -1; } make_head_desc(d, n, num_itf); usbd->usbd_config_desc_size = n; for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) { usbd->cdc[i]->in_ep = CDC_IN_EP(i); usbd->cdc[i]->out_ep = CDC_OUT_EP(i); } } // Verify that the endpoints that are used fit within the maximum number d = usbd->usbd_config_desc; const uint8_t *d_top = d + n; while (d < d_top) { if (d[0] == 7 && d[1] == USB_DESC_TYPE_ENDPOINT && (d[2] & 0x7f) > max_endpoint) { // Endpoint out of range of hardware return -1; } d += d[0]; } return 0; } static void usbd_cdc_state_init(USBD_HandleTypeDef *pdev, usbd_cdc_msc_hid_state_t *usbd, usbd_cdc_state_t *cdc, uint8_t cmd_ep) { int mp = usbd_cdc_max_packet(pdev); // Open endpoints USBD_LL_OpenEP(pdev, cdc->in_ep, USBD_EP_TYPE_BULK, mp); USBD_LL_OpenEP(pdev, cdc->out_ep, USBD_EP_TYPE_BULK, mp); USBD_LL_OpenEP(pdev, cmd_ep, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE); // Init state cdc->usbd = usbd; cdc->cur_request = 0xff; cdc->tx_in_progress = 0; // Init interface uint8_t *buf = usbd_cdc_init(cdc); // Prepare Out endpoint to receive next packet USBD_LL_PrepareReceive(pdev, cdc->out_ep, buf, mp); } static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { #if !USBD_SUPPORT_HS_MODE if (pdev->dev_speed == USBD_SPEED_HIGH) { // can't handle high speed return 1; } #endif usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; // CDC VCP component(s) for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) { usbd_cdc_state_init(pdev, usbd, usbd->cdc[i], CDC_CMD_EP(i)); } } #if MICROPY_HW_USB_MSC if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) { // MSC component int mp = usbd_msc_max_packet(pdev); // Open EP OUT USBD_LL_OpenEP(pdev, MSC_OUT_EP, USBD_EP_TYPE_BULK, mp); // Open EP IN USBD_LL_OpenEP(pdev, MSC_IN_EP, USBD_EP_TYPE_BULK, mp); // Init the BOT layer MSC_BOT_Init(pdev); } #endif #if MICROPY_HW_USB_HID if (usbd->usbd_mode & USBD_MODE_IFACE_HID) { // HID component // get max packet lengths from descriptor uint16_t mps_in = usbd->hid->desc[HID_DESC_OFFSET_MAX_PACKET_LO] | (usbd->hid->desc[HID_DESC_OFFSET_MAX_PACKET_HI] << 8); uint16_t mps_out = usbd->hid->desc[HID_DESC_OFFSET_MAX_PACKET_OUT_LO] | (usbd->hid->desc[HID_DESC_OFFSET_MAX_PACKET_OUT_HI] << 8); // Open EP IN USBD_LL_OpenEP(pdev, usbd->hid->in_ep, USBD_EP_TYPE_INTR, mps_in); // Open EP OUT USBD_LL_OpenEP(pdev, usbd->hid->out_ep, USBD_EP_TYPE_INTR, mps_out); usbd->hid->usbd = usbd; uint8_t *buf = usbd_hid_init(usbd->hid); // Prepare Out endpoint to receive next packet USBD_LL_PrepareReceive(pdev, usbd->hid->out_ep, buf, mps_out); usbd->hid->state = HID_IDLE; } #endif return 0; } static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && usbd->cdc[i]) { // CDC VCP component usbd_cdc_deinit(usbd->cdc[i]); // close endpoints USBD_LL_CloseEP(pdev, CDC_IN_EP(i)); USBD_LL_CloseEP(pdev, CDC_OUT_EP(i)); USBD_LL_CloseEP(pdev, CDC_CMD_EP(i)); } } #if MICROPY_HW_USB_MSC if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) { // MSC component // close endpoints USBD_LL_CloseEP(pdev, MSC_OUT_EP); USBD_LL_CloseEP(pdev, MSC_IN_EP); // DeInit the BOT layer MSC_BOT_DeInit(pdev); } #endif #if MICROPY_HW_USB_HID if (usbd->usbd_mode & USBD_MODE_IFACE_HID) { // HID component // close endpoints USBD_LL_CloseEP(pdev, usbd->hid->in_ep); USBD_LL_CloseEP(pdev, usbd->hid->out_ep); } #endif return 0; } static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { /* printf("SU: %x %x %x %x\n", req->bmRequest, req->bRequest, req->wValue, req->wIndex); This is what we get when MSC is IFACE=0 and CDC is IFACE=1,2: SU: 21 22 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE SU: 21 20 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_LINE_CODING SU: a1 fe 0 0 -- 0x80 | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; BOT_GET_MAX_LUN; 0; 0 SU: 21 22 3 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE On a Mac OS X, with MSC then CDC: SU: a1 fe 0 0 SU: 21 22 2 1 SU: 21 22 3 1 SU: 21 20 0 1 */ usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; // Work out the recipient of the setup request uint8_t mode = usbd->usbd_mode; uint8_t recipient = 0; usbd_cdc_state_t *cdc = NULL; switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) { case USB_REQ_RECIPIENT_INTERFACE: { uint16_t iface = req->wIndex; #if MICROPY_HW_USB_MSC if ((mode & USBD_MODE_IFACE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) { recipient = USBD_MODE_MSC; } else #endif #if MICROPY_HW_USB_HID if ((mode & USBD_MODE_IFACE_HID) && iface == usbd->hid->iface_num) { recipient = USBD_MODE_HID; } else #endif { for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if ((mode & USBD_MODE_IFACE_CDC(i)) && iface == usbd->cdc[i]->iface_num) { recipient = USBD_MODE_CDC; cdc = usbd->cdc[i]; break; } } } break; } case USB_REQ_RECIPIENT_ENDPOINT: { uint8_t ep = req->wIndex & 0x7f; #if MICROPY_HW_USB_MSC if ((mode & USBD_MODE_IFACE_MSC) && ep == MSC_OUT_EP) { recipient = USBD_MODE_MSC; } else #endif #if MICROPY_HW_USB_HID if ((mode & USBD_MODE_IFACE_HID) && ep == usbd->hid->out_ep) { recipient = USBD_MODE_HID; } else #endif { for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if ((mode & USBD_MODE_IFACE_CDC(i)) && (ep == CDC_OUT_EP(i) || ep == (CDC_CMD_EP(i) & 0x7f))) { recipient = USBD_MODE_CDC; cdc = usbd->cdc[i]; break; } } } break; } } // Fail the request if we didn't have a valid recipient if (recipient == 0) { USBD_CtlError(pdev, req); return USBD_FAIL; } switch (req->bmRequest & USB_REQ_TYPE_MASK) { // Class request case USB_REQ_TYPE_CLASS: if (recipient == USBD_MODE_CDC) { if (req->wLength) { if (req->bmRequest & 0x80) { // device-to-host request usbd_cdc_control(cdc, req->bRequest, (uint8_t*)cdc->ctl_packet_buf, req->wLength); USBD_CtlSendData(pdev, (uint8_t*)cdc->ctl_packet_buf, req->wLength); } else { // host-to-device request cdc->cur_request = req->bRequest; cdc->cur_length = req->wLength; USBD_CtlPrepareRx(pdev, (uint8_t*)cdc->ctl_packet_buf, req->wLength); } } else { // Not a Data request // Transfer the command to the interface layer return usbd_cdc_control(cdc, req->bRequest, NULL, req->wValue); } } #if MICROPY_HW_USB_MSC if (recipient == USBD_MODE_MSC) { switch (req->bRequest) { case BOT_GET_MAX_LUN: if ((req->wValue == 0) && (req->wLength == 1) && ((req->bmRequest & 0x80) == 0x80)) { usbd->MSC_BOT_ClassData.max_lun = usbd->MSC_BOT_ClassData.bdev_ops->GetMaxLun(); USBD_CtlSendData(pdev, (uint8_t *)&usbd->MSC_BOT_ClassData.max_lun, 1); } else { USBD_CtlError(pdev, req); return USBD_FAIL; } break; case BOT_RESET: if ((req->wValue == 0) && (req->wLength == 0) && ((req->bmRequest & 0x80) != 0x80)) { MSC_BOT_Reset(pdev); } else { USBD_CtlError(pdev, req); return USBD_FAIL; } break; default: USBD_CtlError(pdev, req); return USBD_FAIL; } } #endif #if MICROPY_HW_USB_HID if (recipient == USBD_MODE_HID) { switch (req->bRequest) { case HID_REQ_SET_PROTOCOL: usbd->hid->ctl_protocol = (uint8_t)(req->wValue); break; case HID_REQ_GET_PROTOCOL: USBD_CtlSendData(pdev, &usbd->hid->ctl_protocol, 1); break; case HID_REQ_SET_IDLE: usbd->hid->ctl_idle_state = (uint8_t)(req->wValue >> 8); break; case HID_REQ_GET_IDLE: USBD_CtlSendData(pdev, &usbd->hid->ctl_idle_state, 1); break; default: USBD_CtlError(pdev, req); return USBD_FAIL; } } #endif break; case USB_REQ_TYPE_STANDARD: #if MICROPY_HW_USB_MSC if (recipient == USBD_MODE_MSC) { switch (req->bRequest) { case USB_REQ_GET_INTERFACE : USBD_CtlSendData(pdev, (uint8_t *)&usbd->MSC_BOT_ClassData.interface, 1); break; case USB_REQ_SET_INTERFACE : usbd->MSC_BOT_ClassData.interface = (uint8_t)(req->wValue); break; case USB_REQ_CLEAR_FEATURE: // Flush the FIFO and Clear the stall status USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex); // Re-activate the EP USBD_LL_CloseEP(pdev, (uint8_t)req->wIndex); if((((uint8_t)req->wIndex) & 0x80) == 0x80) { // Open EP IN USBD_LL_OpenEP(pdev, MSC_IN_EP, USBD_EP_TYPE_BULK, usbd_msc_max_packet(pdev)); } else { // Open EP OUT USBD_LL_OpenEP(pdev, MSC_OUT_EP, USBD_EP_TYPE_BULK, usbd_msc_max_packet(pdev)); } // Handle BOT error MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); break; } } #endif #if MICROPY_HW_USB_HID if (recipient == USBD_MODE_HID) { switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: { uint16_t len = 0; const uint8_t *pbuf = NULL; if (req->wValue >> 8 == HID_REPORT_DESC) { len = usbd->hid->desc[HID_DESC_OFFSET_REPORT_DESC_LEN]; len = MIN(len, req->wLength); pbuf = usbd->hid->report_desc; } else if (req->wValue >> 8 == HID_DESCRIPTOR_TYPE) { len = MIN(HID_SUBDESC_LEN, req->wLength); pbuf = usbd->hid->desc + HID_DESC_OFFSET_SUBDESC; } USBD_CtlSendData(pdev, (uint8_t*)pbuf, len); break; } case USB_REQ_GET_INTERFACE: USBD_CtlSendData(pdev, &usbd->hid->ctl_alt_setting, 1); break; case USB_REQ_SET_INTERFACE: usbd->hid->ctl_alt_setting = (uint8_t)(req->wValue); break; } } #endif break; } return USBD_OK; } /* unused static uint8_t EP0_TxSent(USBD_HandleTypeDef *pdev) { } */ static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if (usbd->cdc[i] != NULL && usbd->cdc[i]->cur_request != 0xff) { usbd_cdc_control(usbd->cdc[i], usbd->cdc[i]->cur_request, (uint8_t*)usbd->cdc[i]->ctl_packet_buf, usbd->cdc[i]->cur_length); usbd->cdc[i]->cur_request = 0xff; } } return USBD_OK; } static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && (epnum == (CDC_IN_EP(i) & 0x7f) || epnum == (CDC_CMD_EP(i) & 0x7f))) { usbd->cdc[i]->tx_in_progress = 0; usbd_cdc_tx_ready(usbd->cdc[i]); return USBD_OK; } } #if MICROPY_HW_USB_MSC if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { MSC_BOT_DataIn(pdev, epnum); return USBD_OK; } #endif #if MICROPY_HW_USB_HID if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) { /* Ensure that the FIFO is empty before a new transfer, this condition could be caused by a new transfer before the end of the previous transfer */ usbd->hid->state = HID_IDLE; return USBD_OK; } #endif return USBD_OK; } static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && epnum == (CDC_OUT_EP(i) & 0x7f)) { size_t len = USBD_LL_GetRxDataSize(pdev, epnum); // USB data will be immediately processed, and next USB traffic is NAKed until it's done return usbd_cdc_receive(usbd->cdc[i], len); } } #if MICROPY_HW_USB_MSC if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) { MSC_BOT_DataOut(pdev, epnum); return USBD_OK; } #endif #if MICROPY_HW_USB_HID if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) { size_t len = USBD_LL_GetRxDataSize(pdev, epnum); return usbd_hid_receive(usbd->hid, len); } #endif return USBD_OK; } #if USBD_SUPPORT_HS_MODE static void usbd_cdc_desc_config_max_packet(USBD_HandleTypeDef *pdev, uint8_t *cdc_desc) { uint32_t mp = usbd_cdc_max_packet(pdev); cdc_desc[CDC_DESC_OFFSET_OUT_MAX_PACKET_LO] = LOBYTE(mp); cdc_desc[CDC_DESC_OFFSET_OUT_MAX_PACKET_HI] = HIBYTE(mp); cdc_desc[CDC_DESC_OFFSET_IN_MAX_PACKET_LO] = LOBYTE(mp); cdc_desc[CDC_DESC_OFFSET_IN_MAX_PACKET_HI] = HIBYTE(mp); uint8_t interval; // polling interval in frames of 1ms if (pdev->dev_speed == USBD_SPEED_HIGH) { interval = 0x09; } else { interval = 0x20; } cdc_desc[CDC_DESC_OFFSET_INTR_INTERVAL] = interval; } #endif static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t *length) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; #if USBD_SUPPORT_HS_MODE uint8_t *cdc_desc[MICROPY_HW_USB_CDC_NUM] = {0}; uint8_t *msc_desc = NULL; switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) { #if MICROPY_HW_USB_MSC case USBD_MODE_MSC: msc_desc = usbd->usbd_config_desc + MSC_TEMPLATE_MSC_DESC_OFFSET; break; case USBD_MODE_CDC_MSC: cdc_desc[0] = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_MSC_DESC_OFFSET; break; #endif #if MICROPY_HW_USB_CDC_NUM >= 2 case USBD_MODE_CDC2: cdc_desc[0] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC_DESC_OFFSET; cdc_desc[1] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC2_DESC_OFFSET; break; #if MICROPY_HW_USB_MSC case USBD_MODE_CDC2_MSC: cdc_desc[0] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET; cdc_desc[1] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET; break; #endif #endif #if MICROPY_HW_USB_CDC_NUM >= 3 case USBD_MODE_CDC3: cdc_desc[0] = usbd->usbd_config_desc + CDC3_TEMPLATE_CDC_DESC_OFFSET; cdc_desc[1] = usbd->usbd_config_desc + CDC3_TEMPLATE_CDC2_DESC_OFFSET; cdc_desc[2] = usbd->usbd_config_desc + CDC3_TEMPLATE_CDC3_DESC_OFFSET; break; #if MICROPY_HW_USB_MSC case USBD_MODE_CDC3_MSC: cdc_desc[0] = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_CDC_DESC_OFFSET; cdc_desc[1] = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_CDC2_DESC_OFFSET; cdc_desc[2] = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_CDC3_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_MSC_DESC_OFFSET; break; #endif #endif #if MICROPY_HW_USB_HID case USBD_MODE_CDC_HID: cdc_desc[0] = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET; break; #endif case USBD_MODE_CDC: cdc_desc[0] = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET; break; } // configure CDC descriptors, if needed for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if (cdc_desc[i] != NULL) { usbd_cdc_desc_config_max_packet(pdev, cdc_desc[i]); } } if (msc_desc != NULL) { uint32_t mp = usbd_msc_max_packet(pdev); msc_desc[13] = LOBYTE(mp); msc_desc[14] = HIBYTE(mp); msc_desc[20] = LOBYTE(mp); msc_desc[21] = HIBYTE(mp); } #endif *length = usbd->usbd_config_desc_size; return usbd->usbd_config_desc; } uint8_t *USBD_CDC_MSC_HID_GetDeviceQualifierDescriptor(USBD_HandleTypeDef *pdev, uint16_t *length) { #if USBD_SUPPORT_HS_MODE *length = sizeof(USBD_CDC_MSC_HID_DeviceQualifierDesc); return USBD_CDC_MSC_HID_DeviceQualifierDesc; #else *length = 0; return NULL; #endif } // data received on non-control OUT endpoint uint8_t USBD_CDC_TransmitPacket(usbd_cdc_state_t *cdc, size_t len, const uint8_t *buf) { if (cdc->tx_in_progress == 0) { // transmit next packet USBD_LL_Transmit(cdc->usbd->pdev, cdc->in_ep, (uint8_t*)buf, len); // Tx transfer in progress cdc->tx_in_progress = 1; return USBD_OK; } else { return USBD_BUSY; } } // prepare OUT endpoint for reception uint8_t USBD_CDC_ReceivePacket(usbd_cdc_state_t *cdc, uint8_t *buf) { // Suspend or Resume USB Out process #if !USBD_SUPPORT_HS_MODE if (cdc->usbd->pdev->dev_speed == USBD_SPEED_HIGH) { return USBD_FAIL; } #endif // Prepare Out endpoint to receive next packet USBD_LL_PrepareReceive(cdc->usbd->pdev, cdc->out_ep, buf, usbd_cdc_max_packet(cdc->usbd->pdev)); return USBD_OK; } #if MICROPY_HW_USB_HID // prepare OUT endpoint for reception uint8_t USBD_HID_ReceivePacket(usbd_hid_state_t *hid, uint8_t *buf) { // Suspend or Resume USB Out process #if !USBD_SUPPORT_HS_MODE if (hid->usbd->pdev->dev_speed == USBD_SPEED_HIGH) { return USBD_FAIL; } #endif // Prepare Out endpoint to receive next packet uint16_t mps_out = hid->desc[HID_DESC_OFFSET_MAX_PACKET_OUT_LO] | (hid->desc[HID_DESC_OFFSET_MAX_PACKET_OUT_HI] << 8); USBD_LL_PrepareReceive(hid->usbd->pdev, hid->out_ep, buf, mps_out); return USBD_OK; } int USBD_HID_CanSendReport(usbd_hid_state_t *hid) { return hid->usbd->pdev->dev_state == USBD_STATE_CONFIGURED && hid->state == HID_IDLE; } uint8_t USBD_HID_SendReport(usbd_hid_state_t *hid, uint8_t *report, uint16_t len) { if (hid->usbd->pdev->dev_state == USBD_STATE_CONFIGURED) { if (hid->state == HID_IDLE) { hid->state = HID_BUSY; USBD_LL_Transmit(hid->usbd->pdev, hid->in_ep, report, len); return USBD_OK; } } return USBD_FAIL; } #endif // CDC/MSC/HID interface class callback structure const USBD_ClassTypeDef USBD_CDC_MSC_HID = { USBD_CDC_MSC_HID_Init, USBD_CDC_MSC_HID_DeInit, USBD_CDC_MSC_HID_Setup, NULL, // EP0_TxSent USBD_CDC_MSC_HID_EP0_RxReady, USBD_CDC_MSC_HID_DataIn, USBD_CDC_MSC_HID_DataOut, NULL, // SOF NULL, // IsoINIncomplete NULL, // IsoOUTIncomplete USBD_CDC_MSC_HID_GetCfgDesc, USBD_CDC_MSC_HID_GetCfgDesc, USBD_CDC_MSC_HID_GetCfgDesc, USBD_CDC_MSC_HID_GetDeviceQualifierDescriptor, }; #endif micropython-1.12/ports/stm32/usbdev/class/src/usbd_msc_bot.c000066400000000000000000000231611357706137100241370ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_msc_bot.c * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief This file provides all the BOT protocol core functions. ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbd_msc_bot.h" #include "usbd_msc_scsi.h" #include "usbd_cdc_msc_hid.h" #include "usbd_ioreq.h" #if MICROPY_HW_USB_MSC /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup MSC_BOT * @brief BOT protocol module * @{ */ /** @defgroup MSC_BOT_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup MSC_BOT_Private_Defines * @{ */ /** * @} */ /** @defgroup MSC_BOT_Private_Macros * @{ */ /** * @} */ /** @defgroup MSC_BOT_Private_Variables * @{ */ /** * @} */ /** @defgroup MSC_BOT_Private_FunctionPrototypes * @{ */ static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev); static void MSC_BOT_SendData (USBD_HandleTypeDef *pdev, uint8_t* pbuf, uint16_t len); static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev); /** * @} */ /** @defgroup MSC_BOT_Private_Functions * @{ */ /** * @brief MSC_BOT_Init * Initialize the BOT Process * @param pdev: device instance * @retval None */ void MSC_BOT_Init (USBD_HandleTypeDef *pdev) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->bot_state = USBD_BOT_IDLE; hmsc->bot_status = USBD_BOT_STATUS_NORMAL; hmsc->scsi_sense_tail = 0; hmsc->scsi_sense_head = 0; hmsc->bdev_ops->Init(0); USBD_LL_FlushEP(pdev, MSC_OUT_EP); USBD_LL_FlushEP(pdev, MSC_IN_EP); /* Prapare EP to Receive First BOT Cmd */ USBD_LL_PrepareReceive (pdev, MSC_OUT_EP, (uint8_t *)&hmsc->cbw, USBD_BOT_CBW_LENGTH); } /** * @brief MSC_BOT_Reset * Reset the BOT Machine * @param pdev: device instance * @retval None */ void MSC_BOT_Reset (USBD_HandleTypeDef *pdev) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->bot_state = USBD_BOT_IDLE; hmsc->bot_status = USBD_BOT_STATUS_RECOVERY; /* Prapare EP to Receive First BOT Cmd */ USBD_LL_PrepareReceive (pdev, MSC_OUT_EP, (uint8_t *)&hmsc->cbw, USBD_BOT_CBW_LENGTH); } /** * @brief MSC_BOT_DeInit * Uninitialize the BOT Machine * @param pdev: device instance * @retval None */ void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->bot_state = USBD_BOT_IDLE; } /** * @brief MSC_BOT_DataIn * Handle BOT IN data stage * @param pdev: device instance * @param epnum: endpoint index * @retval None */ void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; switch (hmsc->bot_state) { case USBD_BOT_DATA_IN: if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0) { MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED); } break; case USBD_BOT_SEND_DATA: case USBD_BOT_LAST_DATA_IN: MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED); break; default: break; } } /** * @brief MSC_BOT_DataOut * Proccess MSC OUT data * @param pdev: device instance * @param epnum: endpoint index * @retval None */ void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; switch (hmsc->bot_state) { case USBD_BOT_IDLE: MSC_BOT_CBW_Decode(pdev); break; case USBD_BOT_DATA_OUT: if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0) { MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED); } break; default: break; } } /** * @brief MSC_BOT_CBW_Decode * Decode the CBW command and set the BOT state machine accordingtly * @param pdev: device instance * @retval None */ static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->csw.dTag = hmsc->cbw.dTag; hmsc->csw.dDataResidue = hmsc->cbw.dDataLength; if ((USBD_LL_GetRxDataSize (pdev ,MSC_OUT_EP) != USBD_BOT_CBW_LENGTH) || (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE)|| (hmsc->cbw.bLUN > 1) || (hmsc->cbw.bCBLength < 1) || (hmsc->cbw.bCBLength > 16)) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); hmsc->bot_status = USBD_BOT_STATUS_ERROR; MSC_BOT_Abort(pdev); } else { if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0) { if(hmsc->bot_state == USBD_BOT_NO_DATA) { MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED); } else { MSC_BOT_Abort(pdev); } } /*Burst xfer handled internally*/ else if ((hmsc->bot_state != USBD_BOT_DATA_IN) && (hmsc->bot_state != USBD_BOT_DATA_OUT) && (hmsc->bot_state != USBD_BOT_LAST_DATA_IN)) { if (hmsc->bot_data_length > 0) { MSC_BOT_SendData(pdev, hmsc->bot_data, hmsc->bot_data_length); } else if (hmsc->bot_data_length == 0) { MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED); } } } } /** * @brief MSC_BOT_SendData * Send the requested data * @param pdev: device instance * @param buf: pointer to data buffer * @param len: Data Length * @retval None */ static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, uint8_t* buf, uint16_t len) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; len = MIN (hmsc->cbw.dDataLength, len); hmsc->csw.dDataResidue -= len; hmsc->csw.bStatus = USBD_CSW_CMD_PASSED; hmsc->bot_state = USBD_BOT_SEND_DATA; USBD_LL_Transmit (pdev, MSC_IN_EP, buf, len); } /** * @brief MSC_BOT_SendCSW * Send the Command Status Wrapper * @param pdev: device instance * @param status : CSW status * @retval None */ void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev, uint8_t CSW_Status) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE; hmsc->csw.bStatus = CSW_Status; hmsc->bot_state = USBD_BOT_IDLE; USBD_LL_Transmit (pdev, MSC_IN_EP, (uint8_t *)&hmsc->csw, USBD_BOT_CSW_LENGTH); /* Prapare EP to Receive next Cmd */ USBD_LL_PrepareReceive (pdev, MSC_OUT_EP, (uint8_t *)&hmsc->cbw, USBD_BOT_CBW_LENGTH); } /** * @brief MSC_BOT_Abort * Abort the current transfer * @param pdev: device instance * @retval status */ static void MSC_BOT_Abort (USBD_HandleTypeDef *pdev) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; if ((hmsc->cbw.bmFlags == 0) && (hmsc->cbw.dDataLength != 0) && (hmsc->bot_status == USBD_BOT_STATUS_NORMAL) ) { USBD_LL_StallEP(pdev, MSC_OUT_EP ); } USBD_LL_StallEP(pdev, MSC_IN_EP); if(hmsc->bot_status == USBD_BOT_STATUS_ERROR) { USBD_LL_PrepareReceive (pdev, MSC_OUT_EP, (uint8_t *)&hmsc->cbw, USBD_BOT_CBW_LENGTH); } } /** * @brief MSC_BOT_CplClrFeature * Complete the clear feature request * @param pdev: device instance * @param epnum: endpoint index * @retval None */ void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; if(hmsc->bot_status == USBD_BOT_STATUS_ERROR )/* Bad CBW Signature */ { USBD_LL_StallEP(pdev, MSC_IN_EP); hmsc->bot_status = USBD_BOT_STATUS_NORMAL; } else if(((epnum & 0x80) == 0x80) && ( hmsc->bot_status != USBD_BOT_STATUS_RECOVERY)) { MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED); } } /** * @} */ /** * @} */ /** * @} */ #endif // MICROPY_HW_USB_MSC /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/class/src/usbd_msc_scsi.c000066400000000000000000000514341357706137100243200ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_msc_scsi.c * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief This file provides all the USBD SCSI layer functions. ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbd_msc_bot.h" #include "usbd_msc_scsi.h" #include "usbd_cdc_msc_hid.h" #if MICROPY_HW_USB_MSC /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup MSC_SCSI * @brief Mass storage SCSI layer module * @{ */ /** @defgroup MSC_SCSI_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup MSC_SCSI_Private_Defines * @{ */ /** * @} */ /** @defgroup MSC_SCSI_Private_Macros * @{ */ /** * @} */ /** @defgroup MSC_SCSI_Private_Variables * @{ */ /** * @} */ /** @defgroup MSC_SCSI_Private_FunctionPrototypes * @{ */ static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_SynchronizeCache(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params); static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params); static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr); static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun); static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun); /** * @} */ /** @defgroup MSC_SCSI_Private_Functions * @{ */ /** * @brief SCSI_ProcessCmd * Process SCSI commands * @param pdev: device instance * @param lun: Logical unit number * @param params: Command parameters * @retval status */ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { /* if (params[0] != SCSI_READ10 && params[0] != SCSI_WRITE10) { printf("SCSI_ProcessCmd(lun=%d, params=%x, %x)\n", lun, params[0], params[1]); } */ switch (params[0]) { case SCSI_TEST_UNIT_READY: return SCSI_TestUnitReady(pdev, lun, params); case SCSI_REQUEST_SENSE: return SCSI_RequestSense (pdev, lun, params); case SCSI_INQUIRY: return SCSI_Inquiry(pdev, lun, params); case SCSI_START_STOP_UNIT: return SCSI_StartStopUnit(pdev, lun, params); case SCSI_ALLOW_MEDIUM_REMOVAL: return SCSI_AllowMediumRemoval(pdev, lun, params); case SCSI_MODE_SENSE6: return SCSI_ModeSense6 (pdev, lun, params); case SCSI_MODE_SENSE10: return SCSI_ModeSense10 (pdev, lun, params); case SCSI_SYNCHRONIZE_CACHE10: case SCSI_SYNCHRONIZE_CACHE16: return SCSI_SynchronizeCache(pdev, lun, params); case SCSI_READ_FORMAT_CAPACITIES: return SCSI_ReadFormatCapacity(pdev, lun, params); case SCSI_READ_CAPACITY10: return SCSI_ReadCapacity10(pdev, lun, params); case SCSI_READ10: return SCSI_Read10(pdev, lun, params); case SCSI_WRITE10: return SCSI_Write10(pdev, lun, params); case SCSI_VERIFY10: return SCSI_Verify10(pdev, lun, params); default: SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); return -1; } } /** * @brief SCSI_TestUnitReady * Process SCSI Test Unit Ready Command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; /* case 9 : Hi > D0 */ if (hmsc->cbw.dDataLength != 0) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } if(hmsc->bdev_ops->IsReady(lun) !=0 ) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); hmsc->bot_state = USBD_BOT_NO_DATA; return -1; } hmsc->bot_data_length = 0; return 0; } /** * @brief SCSI_Inquiry * Process Inquiry command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; int res = hmsc->bdev_ops->Inquiry(lun, params, hmsc->bot_data); if (res < 0) { SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); return -1; } hmsc->bot_data_length = res; return 0; } /** * @brief SCSI_ReadCapacity10 * Process Read Capacity 10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; if(hmsc->bdev_ops->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } else { hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 24); hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 16); hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 8); hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1); hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >> 24); hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >> 16); hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >> 8); hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size); hmsc->bot_data_length = 8; return 0; } } /** * @brief SCSI_ReadFormatCapacity * Process Read Format Capacity command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; uint16_t blk_size; uint32_t blk_nbr; uint16_t i; for(i=0 ; i < 12 ; i++) { hmsc->bot_data[i] = 0; } if(hmsc->bdev_ops->GetCapacity(lun, &blk_nbr, &blk_size) != 0) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } else { hmsc->bot_data[3] = 0x08; hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1) >> 24); hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1) >> 16); hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1) >> 8); hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1); hmsc->bot_data[8] = 0x02; hmsc->bot_data[9] = (uint8_t)(blk_size >> 16); hmsc->bot_data[10] = (uint8_t)(blk_size >> 8); hmsc->bot_data[11] = (uint8_t)(blk_size); hmsc->bot_data_length = 12; return 0; } } /** * @brief SCSI_ModeSense6 * Process Mode Sense6 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; uint16_t len = sizeof(USBD_MSC_Mode_Sense6_Data); hmsc->bot_data_length = len; while (len) { len--; hmsc->bot_data[len] = USBD_MSC_Mode_Sense6_Data[len]; } return 0; } /** * @brief SCSI_ModeSense10 * Process Mode Sense10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { uint16_t len = sizeof(USBD_MSC_Mode_Sense10_Data); USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->bot_data_length = len; while (len) { len--; hmsc->bot_data[len] = USBD_MSC_Mode_Sense10_Data[len]; } return 0; } static int8_t SCSI_SynchronizeCache(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { // nothing to synchronize, so just return "success" USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->bot_data_length = 0; return 0; } /** * @brief SCSI_RequestSense * Process Request Sense command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { uint8_t i; USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++) { hmsc->bot_data[i] = 0; } hmsc->bot_data[0] = 0x70; hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6; if((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) { hmsc->bot_data[2] = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey; hmsc->bot_data[12] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ; hmsc->bot_data[13] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC; hmsc->scsi_sense_head++; if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH) { hmsc->scsi_sense_head = 0; } } hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN; if (params[4] <= REQUEST_SENSE_DATA_LEN) { hmsc->bot_data_length = params[4]; } return 0; } /** * @brief SCSI_SenseCode * Load the last error code in the error list * @param lun: Logical unit number * @param sKey: Sense Key * @param ASC: Additional Sense Key * @retval none */ void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey; hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8; hmsc->scsi_sense_tail++; if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH) { hmsc->scsi_sense_tail = 0; } } /** * @brief SCSI_StartStopUnit * Process Start Stop Unit command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->bot_data_length = 0; // On Mac OS X, when the device is ejected a SCSI_START_STOP_UNIT command is sent. // Bit 0 of params[4] is the START bit. // If we get a stop, we must really stop the device so that the Mac does not // automatically remount it. hmsc->bdev_ops->StartStopUnit(lun, params[4] & 1); return 0; } /** * @brief SCSI_AllowMediumRemoval * Process Allow Medium Removal command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->bot_data_length = 0; hmsc->bdev_ops->PreventAllowMediumRemoval(lun, params[4]); return 0; } /** * @brief SCSI_Read10 * Process Read10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ { /* case 10 : Ho <> Di */ if ((hmsc->cbw.bmFlags & 0x80) != 0x80) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } if(hmsc->bdev_ops->IsReady(lun) !=0 ) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } hmsc->scsi_blk_addr_in_blks = (params[2] << 24) | \ (params[3] << 16) | \ (params[4] << 8) | \ params[5]; hmsc->scsi_blk_len = (params[7] << 8) | \ params[8]; if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr_in_blks, hmsc->scsi_blk_len) < 0) { return -1; /* error */ } hmsc->bot_state = USBD_BOT_DATA_IN; hmsc->scsi_blk_len *= hmsc->scsi_blk_size; /* cases 4,5 : Hi <> Dn */ if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } } hmsc->bot_data_length = MSC_MEDIA_PACKET; return SCSI_ProcessRead(pdev, lun); } /** * @brief SCSI_Write10 * Process Write10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ { /* case 8 : Hi <> Do */ if ((hmsc->cbw.bmFlags & 0x80) == 0x80) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } /* Check whether Media is ready */ if(hmsc->bdev_ops->IsReady(lun) !=0 ) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } /* Check If media is write-protected */ if(hmsc->bdev_ops->IsWriteProtected(lun) !=0 ) { SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED); return -1; } hmsc->scsi_blk_addr_in_blks = (params[2] << 24) | \ (params[3] << 16) | \ (params[4] << 8) | \ params[5]; hmsc->scsi_blk_len = (params[7] << 8) | \ params[8]; /* check if LBA address is in the right range */ if(SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr_in_blks, hmsc->scsi_blk_len) < 0) { return -1; /* error */ } hmsc->scsi_blk_len *= hmsc->scsi_blk_size; /* cases 3,11,13 : Hn,Ho <> D0 */ if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } /* Prepare EP to receive first data packet */ hmsc->bot_state = USBD_BOT_DATA_OUT; USBD_LL_PrepareReceive (pdev, MSC_OUT_EP, hmsc->bot_data, MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET)); } else /* Write Process ongoing */ { return SCSI_ProcessWrite(pdev, lun); } return 0; } /** * @brief SCSI_Verify10 * Process Verify10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; if ((params[1]& 0x02) == 0x02) { SCSI_SenseCode (pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); return -1; /* Error, Verify Mode Not supported*/ } hmsc->scsi_blk_addr_in_blks = (params[2] << 24) | (params[3] << 16) | (params[4] << 8) | params[5]; hmsc->scsi_blk_len = (params[7] << 8) | params[8]; if(SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr_in_blks, hmsc->scsi_blk_len) < 0) { return -1; /* error */ } hmsc->bot_data_length = 0; return 0; } /** * @brief SCSI_CheckAddressRange * Check address range * @param lun: Logical unit number * @param blk_offset: first block address * @param blk_nbr: number of block to be processed * @retval status */ static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr ) { SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); return -1; } return 0; } /** * @brief SCSI_ProcessRead * Handle Read Process * @param lun: Logical unit number * @retval status */ static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; uint32_t len; len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET); if( hmsc->bdev_ops->Read(lun , hmsc->bot_data, hmsc->scsi_blk_addr_in_blks, len / hmsc->scsi_blk_size) < 0) { SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); return -1; } USBD_LL_Transmit (pdev, MSC_IN_EP, hmsc->bot_data, len); hmsc->scsi_blk_addr_in_blks += len / hmsc->scsi_blk_size; hmsc->scsi_blk_len -= len; /* case 6 : Hi = Di */ hmsc->csw.dDataResidue -= len; if (hmsc->scsi_blk_len == 0) { hmsc->bot_state = USBD_BOT_LAST_DATA_IN; } return 0; } /** * @brief SCSI_ProcessWrite * Handle Write Process * @param lun: Logical unit number * @retval status */ static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun) { uint32_t len; USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET); if(hmsc->bdev_ops->Write(lun , hmsc->bot_data, hmsc->scsi_blk_addr_in_blks, len / hmsc->scsi_blk_size) < 0) { SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, WRITE_FAULT); return -1; } hmsc->scsi_blk_addr_in_blks += len / hmsc->scsi_blk_size; hmsc->scsi_blk_len -= len; /* case 12 : Ho = Do */ hmsc->csw.dDataResidue -= len; if (hmsc->scsi_blk_len == 0) { MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED); } else { /* Prapare EP to Receive next packet */ USBD_LL_PrepareReceive (pdev, MSC_OUT_EP, hmsc->bot_data, MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET)); } return 0; } /** * @} */ /** * @} */ /** * @} */ #endif // MICROPY_HW_USB_MSC /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/core/000077500000000000000000000000001357706137100203615ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbdev/core/inc/000077500000000000000000000000001357706137100211325ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbdev/core/inc/usbd_core.h000066400000000000000000000122521357706137100232520ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_core.h * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief Header file for usbd_core.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USBD_CORE_H #define __USBD_CORE_H /* Includes ------------------------------------------------------------------*/ #include "usbd_conf.h" #include "usbd_def.h" #include "usbd_ioreq.h" #include "usbd_ctlreq.h" /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_CORE * @brief This file is the Header file for usbd_core.c file * @{ */ /** @defgroup USBD_CORE_Exported_Defines * @{ */ /** * @} */ /** @defgroup USBD_CORE_Exported_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBD_CORE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBD_CORE_Exported_Variables * @{ */ #define USBD_SOF USBD_LL_SOF /** * @} */ /** @defgroup USBD_CORE_Exported_FunctionsPrototype * @{ */ USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id); USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, const USBD_ClassTypeDef *pclass); USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup); USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata); USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata); USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed); USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev); /* USBD Low Level Driver */ USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev, int high_speed, const uint8_t *fifo_size); USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps); USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); USBD_StatusTypeDef USBD_LL_SetUSBAddress (USBD_HandleTypeDef *pdev, uint8_t dev_addr); USBD_StatusTypeDef USBD_LL_Transmit (USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size); USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size); uint32_t USBD_LL_GetRxDataSize (USBD_HandleTypeDef *pdev, uint8_t ep_addr); void USBD_LL_Delay (uint32_t Delay); /** * @} */ #endif /* __USBD_CORE_H */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/core/inc/usbd_ctlreq.h000066400000000000000000000046721357706137100236230ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_req.h * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief header file for the usbd_req.c file ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USB_REQUEST_H_ #define __USB_REQUEST_H_ /* Includes ------------------------------------------------------------------*/ #include "usbd_def.h" /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_REQ * @brief header file for the usbd_ioreq.c file * @{ */ /** @defgroup USBD_REQ_Exported_Defines * @{ */ /** * @} */ /** @defgroup USBD_REQ_Exported_Types * @{ */ /** * @} */ /** @defgroup USBD_REQ_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBD_REQ_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBD_REQ_Exported_FunctionsPrototype * @{ */ USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); void USBD_CtlError (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); void USBD_ParseSetupRequest (USBD_SetupReqTypedef *req, uint8_t *pdata); void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len); /** * @} */ #endif /* __USB_REQUEST_H_ */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/core/inc/usbd_def.h000066400000000000000000000240541357706137100230630ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_def.h * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief general defines for the usb device library ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USBD_DEF_H #define __USBD_DEF_H /* Includes ------------------------------------------------------------------*/ #include "usbd_conf.h" /** @addtogroup STM32_USBD_DEVICE_LIBRARY * @{ */ /** @defgroup USB_DEF * @brief general defines for the usb device library file * @{ */ /** @defgroup USB_DEF_Exported_Defines * @{ */ #ifndef NULL #define NULL ((void *)0) #endif #define USB_LEN_DEV_QUALIFIER_DESC 0x0A #define USB_LEN_DEV_DESC 0x12 #define USB_LEN_CFG_DESC 0x09 #define USB_LEN_IF_DESC 0x09 #define USB_LEN_EP_DESC 0x07 #define USB_LEN_OTG_DESC 0x03 #define USB_LEN_LANGID_STR_DESC 0x04 #define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09 #define USBD_IDX_LANGID_STR 0x00 #define USBD_IDX_MFC_STR 0x01 #define USBD_IDX_PRODUCT_STR 0x02 #define USBD_IDX_SERIAL_STR 0x03 #define USBD_IDX_CONFIG_STR 0x04 #define USBD_IDX_INTERFACE_STR 0x05 #define USB_REQ_TYPE_STANDARD 0x00 #define USB_REQ_TYPE_CLASS 0x20 #define USB_REQ_TYPE_VENDOR 0x40 #define USB_REQ_TYPE_MASK 0x60 #define USB_REQ_RECIPIENT_DEVICE 0x00 #define USB_REQ_RECIPIENT_INTERFACE 0x01 #define USB_REQ_RECIPIENT_ENDPOINT 0x02 #define USB_REQ_RECIPIENT_MASK 0x03 #define USB_REQ_GET_STATUS 0x00 #define USB_REQ_CLEAR_FEATURE 0x01 #define USB_REQ_SET_FEATURE 0x03 #define USB_REQ_SET_ADDRESS 0x05 #define USB_REQ_GET_DESCRIPTOR 0x06 #define USB_REQ_SET_DESCRIPTOR 0x07 #define USB_REQ_GET_CONFIGURATION 0x08 #define USB_REQ_SET_CONFIGURATION 0x09 #define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SYNCH_FRAME 0x0C #define USB_DESC_TYPE_DEVICE 1 #define USB_DESC_TYPE_CONFIGURATION 2 #define USB_DESC_TYPE_STRING 3 #define USB_DESC_TYPE_INTERFACE 4 #define USB_DESC_TYPE_ENDPOINT 5 #define USB_DESC_TYPE_DEVICE_QUALIFIER 6 #define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7 #define USB_CONFIG_REMOTE_WAKEUP 2 #define USB_CONFIG_SELF_POWERED 1 #define USB_FEATURE_EP_HALT 0 #define USB_FEATURE_REMOTE_WAKEUP 1 #define USB_FEATURE_TEST_MODE 2 #define USB_HS_MAX_PACKET_SIZE 512 #define USB_FS_MAX_PACKET_SIZE 64 #define USB_MAX_EP0_SIZE 64 /* Device Status */ #define USBD_STATE_DEFAULT 1 #define USBD_STATE_ADDRESSED 2 #define USBD_STATE_CONFIGURED 3 #define USBD_STATE_SUSPENDED 4 /* EP0 State */ #define USBD_EP0_IDLE 0 #define USBD_EP0_SETUP 1 #define USBD_EP0_DATA_IN 2 #define USBD_EP0_DATA_OUT 3 #define USBD_EP0_STATUS_IN 4 #define USBD_EP0_STATUS_OUT 5 #define USBD_EP0_STALL 6 #define USBD_EP_TYPE_CTRL 0 #define USBD_EP_TYPE_ISOC 1 #define USBD_EP_TYPE_BULK 2 #define USBD_EP_TYPE_INTR 3 /** * @} */ /** @defgroup USBD_DEF_Exported_TypesDefinitions * @{ */ typedef struct usb_setup_req { uint8_t bmRequest; uint8_t bRequest; uint16_t wValue; uint16_t wIndex; uint16_t wLength; }USBD_SetupReqTypedef; struct _USBD_HandleTypeDef; typedef struct _Device_cb { uint8_t (*Init) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx); uint8_t (*DeInit) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx); /* Control Endpoints*/ uint8_t (*Setup) (struct _USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); uint8_t (*EP0_TxSent) (struct _USBD_HandleTypeDef *pdev ); uint8_t (*EP0_RxReady) (struct _USBD_HandleTypeDef *pdev ); /* Class Specific Endpoints*/ uint8_t (*DataIn) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); uint8_t (*DataOut) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); uint8_t (*SOF) (struct _USBD_HandleTypeDef *pdev); uint8_t (*IsoINIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); uint8_t (*IsoOUTIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); uint8_t *(*GetHSConfigDescriptor)(struct _USBD_HandleTypeDef *pdev, uint16_t *length); uint8_t *(*GetFSConfigDescriptor)(struct _USBD_HandleTypeDef *pdev, uint16_t *length); uint8_t *(*GetOtherSpeedConfigDescriptor)(struct _USBD_HandleTypeDef *pdev, uint16_t *length); uint8_t *(*GetDeviceQualifierDescriptor)(struct _USBD_HandleTypeDef *pdev, uint16_t *length); } USBD_ClassTypeDef; /* Following USB Device Speed */ typedef enum { USBD_SPEED_HIGH = 0, USBD_SPEED_FULL = 1, USBD_SPEED_LOW = 2, }USBD_SpeedTypeDef; /* Following USB Device status */ typedef enum { USBD_OK = 0, USBD_BUSY, USBD_FAIL, }USBD_StatusTypeDef; struct _USBD_HandleTypeDef; /* USB Device descriptors structure */ typedef struct { uint8_t *(*GetDeviceDescriptor)(struct _USBD_HandleTypeDef *pdev, uint16_t *length); uint8_t *(*GetStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t idx, uint16_t *length); } USBD_DescriptorsTypeDef; /* USB Device handle structure */ typedef struct { uint32_t status; uint32_t total_length; uint32_t rem_length; uint32_t maxpacket; } USBD_EndpointTypeDef; /* USB Device handle structure */ typedef struct _USBD_HandleTypeDef { uint8_t id; uint32_t dev_config; uint32_t dev_default_config; uint32_t dev_config_status; USBD_SpeedTypeDef dev_speed; USBD_EndpointTypeDef ep_in[15]; USBD_EndpointTypeDef ep_out[15]; uint32_t ep0_state; uint32_t ep0_data_len; uint8_t dev_state; uint8_t dev_old_state; uint8_t dev_address; uint8_t dev_connection_status; uint8_t dev_test_mode; uint32_t dev_remote_wakeup; USBD_SetupReqTypedef request; USBD_DescriptorsTypeDef *pDesc; const USBD_ClassTypeDef *pClass; void *pClassData; void *pUserData; void *pData; } USBD_HandleTypeDef; /** * @} */ /** @defgroup USBD_DEF_Exported_Macros * @{ */ #define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) #define LOBYTE(x) ((uint8_t)(x & 0x00FF)) #define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8)) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #if defined ( __GNUC__ ) #ifndef __weak #define __weak __attribute__((weak)) #endif /* __weak */ #ifndef __packed #define __packed __attribute__((__packed__)) #endif /* __packed */ #endif /* __GNUC__ */ /* In HS mode and when the DMA is used, all variables and data structures dealing with the DMA during the transaction process should be 4-bytes aligned */ #if defined (__GNUC__) /* GNU Compiler */ #define __ALIGN_END __attribute__ ((aligned (4))) #define __ALIGN_BEGIN #else #define __ALIGN_END #if defined (__CC_ARM) /* ARM Compiler */ #define __ALIGN_BEGIN __align(4) #elif defined (__ICCARM__) /* IAR Compiler */ #define __ALIGN_BEGIN #elif defined (__TASKING__) /* TASKING Compiler */ #define __ALIGN_BEGIN __align(4) #endif /* __CC_ARM */ #endif /* __GNUC__ */ /** * @} */ /** @defgroup USBD_DEF_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBD_DEF_Exported_FunctionsPrototype * @{ */ /** * @} */ #endif /* __USBD_DEF_H */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/core/inc/usbd_ioreq.h000066400000000000000000000055241357706137100234450ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_ioreq.h * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief header file for the usbd_ioreq.c file ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USBD_IOREQ_H_ #define __USBD_IOREQ_H_ /* Includes ------------------------------------------------------------------*/ #include "usbd_def.h" #include "usbd_core.h" /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_IOREQ * @brief header file for the usbd_ioreq.c file * @{ */ /** @defgroup USBD_IOREQ_Exported_Defines * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Exported_Types * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Exported_FunctionsPrototype * @{ */ USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len); USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len); USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len); USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len); USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev); uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , uint8_t epnum); /** * @} */ #endif /* __USBD_IOREQ_H_ */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/core/src/000077500000000000000000000000001357706137100211505ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbdev/core/src/usbd_core.c000066400000000000000000000262411357706137100232660ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_core.c * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief This file provides all the USBD core functions. ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbd_core.h" /** @addtogroup STM32_USBD_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_CORE * @brief usbd core module * @{ */ /** @defgroup USBD_CORE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBD_CORE_Private_Defines * @{ */ /** * @} */ /** @defgroup USBD_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBD_CORE_Private_FunctionPrototypes * @{ */ /** * @} */ /** @defgroup USBD_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBD_CORE_Private_Functions * @{ */ #if 0 /** * @brief USBD_Init * Initailizes the device stack and load the class driver * @param pdev: device instance * @param core_address: USB OTG core ID * @param pdesc: Descriptor structure address * @param id: Low level core index * @retval None */ USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id) { /* Check whether the USB Host handle is valid */ if(pdev == NULL) { return USBD_FAIL; } /* Unlink previous class*/ if(pdev->pClass != NULL) { pdev->pClass = NULL; } /* Assign USBD Descriptors */ if(pdesc != NULL) { pdev->pDesc = pdesc; } /* Set Device initial State */ pdev->dev_state = USBD_STATE_DEFAULT; pdev->id = id; /* Initialize low level driver */ USBD_LL_Init(pdev, 0); return USBD_OK; } #endif /** * @brief USBD_DeInit * Re-Initialize th device library * @param pdev: device instance * @retval status: status */ USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev) { /* Set Default State */ pdev->dev_state = USBD_STATE_DEFAULT; /* Free Class Resources */ pdev->pClass->DeInit(pdev, pdev->dev_config); /* Stop the low level driver */ USBD_LL_Stop(pdev); /* Initialize low level driver */ USBD_LL_DeInit(pdev); return USBD_OK; } /** * @brief USBD_RegisterClass * Link class driver to Device Core. * @param pDevice : Device Handle * @param pclass: Class handle * @retval USBD Status */ USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, const USBD_ClassTypeDef *pclass) { USBD_StatusTypeDef status = USBD_OK; if(pclass != 0) { /* link the class tgo the USB Device handle */ pdev->pClass = pclass; status = USBD_OK; } else { status = USBD_FAIL; } return status; } /** * @brief USBD_Start * Start the USB Device Core. * @param pdev: Device Handle * @retval USBD Status */ USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev) { /* Start the low level driver */ USBD_LL_Start(pdev); return USBD_OK; } /** * @brief USBD_Stop * Stop the USB Device Core. * @param pdev: Device Handle * @retval USBD Status */ USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev) { /* Free Class Resources */ pdev->pClass->DeInit(pdev, pdev->dev_config); /* Stop the low level driver */ USBD_LL_Stop(pdev); return USBD_OK; } /** * @brief USBD_RunTestMode * Launch test mode process * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev) { return USBD_OK; } /** * @brief USBD_SetClassConfig * Configure device and start the interface * @param pdev: device instance * @param cfgidx: configuration index * @retval status */ USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { USBD_StatusTypeDef ret = USBD_FAIL; if(pdev->pClass != NULL) { /* Set configuration and Start the Class*/ if(pdev->pClass->Init(pdev, cfgidx) == 0) { ret = USBD_OK; } } return ret; } /** * @brief USBD_ClrClassConfig * Clear current configuration * @param pdev: device instance * @param cfgidx: configuration index * @retval status: USBD_StatusTypeDef */ USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { /* Clear configuration and Deinitialize the Class process*/ pdev->pClass->DeInit(pdev, cfgidx); return USBD_OK; } /** * @brief USBD_SetupStage * Handle the setup stage * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup) { USBD_ParseSetupRequest(&pdev->request, psetup); pdev->ep0_state = USBD_EP0_SETUP; pdev->ep0_data_len = pdev->request.wLength; switch (pdev->request.bmRequest & 0x1F) { case USB_REQ_RECIPIENT_DEVICE: USBD_StdDevReq (pdev, &pdev->request); break; case USB_REQ_RECIPIENT_INTERFACE: USBD_StdItfReq(pdev, &pdev->request); break; case USB_REQ_RECIPIENT_ENDPOINT: USBD_StdEPReq(pdev, &pdev->request); break; default: USBD_LL_StallEP(pdev , pdev->request.bmRequest & 0x80); break; } return USBD_OK; } /** * @brief USBD_DataOutStage * Handle data OUT stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata) { USBD_EndpointTypeDef *pep; if(epnum == 0) { pep = &pdev->ep_out[0]; if ( pdev->ep0_state == USBD_EP0_DATA_OUT) { if(pep->rem_length > pep->maxpacket) { pep->rem_length -= pep->maxpacket; USBD_CtlContinueRx (pdev, pdata, MIN(pep->rem_length ,pep->maxpacket)); } else { if((pdev->pClass->EP0_RxReady != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { pdev->pClass->EP0_RxReady(pdev); } USBD_CtlSendStatus(pdev); } } } else if((pdev->pClass->DataOut != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { pdev->pClass->DataOut(pdev, epnum); } return USBD_OK; } /** * @brief USBD_DataInStage * Handle data in stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uint8_t *pdata) { USBD_EndpointTypeDef *pep; if(epnum == 0) { pep = &pdev->ep_in[0]; if ( pdev->ep0_state == USBD_EP0_DATA_IN) { if(pep->rem_length > pep->maxpacket) { pep->rem_length -= pep->maxpacket; USBD_CtlContinueSendData (pdev, pdata, pep->rem_length); } else { /* last packet is MPS multiple, so send ZLP packet */ if((pep->total_length % pep->maxpacket == 0) && (pep->total_length >= pep->maxpacket) && (pep->total_length < pdev->ep0_data_len )) { USBD_CtlContinueSendData(pdev , NULL, 0); pdev->ep0_data_len = 0; } else { if((pdev->pClass->EP0_TxSent != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { pdev->pClass->EP0_TxSent(pdev); } USBD_CtlReceiveStatus(pdev); } } } if (pdev->dev_test_mode == 1) { USBD_RunTestMode(pdev); pdev->dev_test_mode = 0; } } else if((pdev->pClass->DataIn != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { pdev->pClass->DataIn(pdev, epnum); } return USBD_OK; } /** * @brief USBD_LL_Reset * Handle Reset event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev) { /* Open EP0 OUT */ USBD_LL_OpenEP(pdev, 0x00, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE); pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE; /* Open EP0 IN */ USBD_LL_OpenEP(pdev, 0x80, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE); pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE; /* Upon Reset call usr call back */ pdev->dev_state = USBD_STATE_DEFAULT; if (pdev->pClassData) pdev->pClass->DeInit(pdev, pdev->dev_config); return USBD_OK; } /** * @brief USBD_LL_Reset * Handle Reset event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed) { pdev->dev_speed = speed; return USBD_OK; } /** * @brief USBD_Suspend * Handle Suspend event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev) { pdev->dev_old_state = pdev->dev_state; pdev->dev_state = USBD_STATE_SUSPENDED; return USBD_OK; } /** * @brief USBD_Resume * Handle Resume event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev) { pdev->dev_state = pdev->dev_old_state; return USBD_OK; } /** * @brief USBD_SOF * Handle SOF event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev) { if(pdev->dev_state == USBD_STATE_CONFIGURED) { if(pdev->pClass->SOF != NULL) { pdev->pClass->SOF(pdev); } } return USBD_OK; } /** * @brief USBD_IsoINIncomplete * Handle iso in incomplete event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) { return USBD_OK; } /** * @brief USBD_IsoOUTIncomplete * Handle iso out incomplete event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) { return USBD_OK; } /** * @brief USBD_DevConnected * Handle device connection event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev) { return USBD_OK; } /** * @brief USBD_DevDisconnected * Handle device disconnection event * @param pdev: device instance * @retval status */ USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev) { /* Free Class Resources */ pdev->dev_state = USBD_STATE_DEFAULT; pdev->pClass->DeInit(pdev, pdev->dev_config); return USBD_OK; } /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/core/src/usbd_ctlreq.c000066400000000000000000000356761357706137100236440ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_req.c * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief This file provides the standard USB requests following chapter 9. ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbd_ctlreq.h" #include "usbd_ioreq.h" /** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_REQ * @brief USB standard requests module * @{ */ /** @defgroup USBD_REQ_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBD_REQ_Private_Defines * @{ */ /** * @} */ /** @defgroup USBD_REQ_Private_Macros * @{ */ /** * @} */ /** @defgroup USBD_REQ_Private_Variables * @{ */ /** * @} */ /** @defgroup USBD_REQ_Private_FunctionPrototypes * @{ */ static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); static void USBD_SetAddress(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); static void USBD_SetConfig(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); static void USBD_GetConfig(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); static void USBD_GetStatus(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); static void USBD_SetFeature(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); static void USBD_ClrFeature(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); static uint8_t USBD_GetLen(uint8_t *buf); /** * @} */ /** @defgroup USBD_REQ_Private_Functions * @{ */ /** * @brief USBD_StdDevReq * Handle standard usb device requests * @param pdev: device instance * @param req: usb request * @retval status */ USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { USBD_StatusTypeDef ret = USBD_OK; switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: USBD_GetDescriptor (pdev, req) ; break; case USB_REQ_SET_ADDRESS: USBD_SetAddress(pdev, req); break; case USB_REQ_SET_CONFIGURATION: USBD_SetConfig (pdev , req); break; case USB_REQ_GET_CONFIGURATION: USBD_GetConfig (pdev , req); break; case USB_REQ_GET_STATUS: USBD_GetStatus (pdev , req); break; case USB_REQ_SET_FEATURE: USBD_SetFeature (pdev , req); break; case USB_REQ_CLEAR_FEATURE: USBD_ClrFeature (pdev , req); break; default: USBD_CtlError(pdev , req); break; } return ret; } /** * @brief USBD_StdItfReq * Handle standard usb interface requests * @param pdev: USB OTG device instance * @param req: usb request * @retval status */ USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { USBD_StatusTypeDef ret = USBD_OK; switch (pdev->dev_state) { case USBD_STATE_CONFIGURED: if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES) { pdev->pClass->Setup (pdev, req); if((req->wLength == 0)&& (ret == USBD_OK)) { USBD_CtlSendStatus(pdev); } } else { USBD_CtlError(pdev , req); } break; default: USBD_CtlError(pdev , req); break; } return USBD_OK; } /** * @brief USBD_StdEPReq * Handle standard usb endpoint requests * @param pdev: USB OTG device instance * @param req: usb request * @retval status */ USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint8_t ep_addr; USBD_StatusTypeDef ret = USBD_OK; USBD_EndpointTypeDef *pep; ep_addr = LOBYTE(req->wIndex); switch (req->bRequest) { case USB_REQ_SET_FEATURE : switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } } pdev->pClass->Setup (pdev, req); USBD_CtlSendStatus(pdev); break; default: USBD_CtlError(pdev , req); break; } break; case USB_REQ_CLEAR_FEATURE : switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr & 0x7F) != 0x00) { USBD_LL_ClearStallEP(pdev , ep_addr); pdev->pClass->Setup (pdev, req); } USBD_CtlSendStatus(pdev); } break; default: USBD_CtlError(pdev , req); break; } break; case USB_REQ_GET_STATUS: switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr & 0x7F) != 0x00) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: pep = ((ep_addr & 0x80) == 0x80) ? &pdev->ep_in[ep_addr & 0x7F]:\ &pdev->ep_out[ep_addr & 0x7F]; if(USBD_LL_IsStallEP(pdev, ep_addr)) { pep->status = 0x0001; } else { pep->status = 0x0000; } USBD_CtlSendData (pdev, (uint8_t *)&pep->status, 2); break; default: USBD_CtlError(pdev , req); break; } break; default: break; } return ret; } /** * @brief USBD_GetDescriptor * Handle Get Descriptor requests * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint16_t len; uint8_t *pbuf; switch (req->wValue >> 8) { case USB_DESC_TYPE_DEVICE: pbuf = pdev->pDesc->GetDeviceDescriptor(pdev, &len); break; case USB_DESC_TYPE_CONFIGURATION: if(pdev->dev_speed == USBD_SPEED_HIGH ) { pbuf = (uint8_t *)pdev->pClass->GetHSConfigDescriptor(pdev, &len); pbuf[1] = USB_DESC_TYPE_CONFIGURATION; } else { pbuf = (uint8_t *)pdev->pClass->GetFSConfigDescriptor(pdev, &len); pbuf[1] = USB_DESC_TYPE_CONFIGURATION; } break; case USB_DESC_TYPE_STRING: pbuf = pdev->pDesc->GetStrDescriptor(pdev, req->wValue & 0xff, &len); if (pbuf == NULL) { USBD_CtlError(pdev, req); return; } break; case USB_DESC_TYPE_DEVICE_QUALIFIER: if(pdev->dev_speed == USBD_SPEED_HIGH ) { pbuf = (uint8_t *)pdev->pClass->GetDeviceQualifierDescriptor(pdev, &len); break; } else { USBD_CtlError(pdev , req); return; } case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: if(pdev->dev_speed == USBD_SPEED_HIGH ) { pbuf = (uint8_t *)pdev->pClass->GetOtherSpeedConfigDescriptor(pdev, &len); pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; break; } else { USBD_CtlError(pdev , req); return; } default: USBD_CtlError(pdev , req); return; } if((len != 0)&& (req->wLength != 0)) { len = MIN(len , req->wLength); USBD_CtlSendData (pdev, pbuf, len); } } /** * @brief USBD_SetAddress * Set device address * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetAddress(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint8_t dev_addr; if ((req->wIndex == 0) && (req->wLength == 0)) { dev_addr = (uint8_t)(req->wValue) & 0x7F; if (pdev->dev_state == USBD_STATE_CONFIGURED) { USBD_CtlError(pdev , req); } else { pdev->dev_address = dev_addr; USBD_LL_SetUSBAddress(pdev, dev_addr); USBD_CtlSendStatus(pdev); if (dev_addr != 0) { pdev->dev_state = USBD_STATE_ADDRESSED; } else { pdev->dev_state = USBD_STATE_DEFAULT; } } } else { USBD_CtlError(pdev , req); } } /** * @brief USBD_SetConfig * Handle Set device configuration request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetConfig(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint8_t cfgidx; cfgidx = (uint8_t)(req->wValue); if (cfgidx > USBD_MAX_NUM_CONFIGURATION ) { USBD_CtlError(pdev , req); } else { switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if (cfgidx) { pdev->dev_config = cfgidx; pdev->dev_state = USBD_STATE_CONFIGURED; if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL) { USBD_CtlError(pdev , req); return; } USBD_CtlSendStatus(pdev); } else { USBD_CtlSendStatus(pdev); } break; case USBD_STATE_CONFIGURED: if (cfgidx == 0) { pdev->dev_state = USBD_STATE_ADDRESSED; pdev->dev_config = cfgidx; USBD_ClrClassConfig(pdev , cfgidx); USBD_CtlSendStatus(pdev); } else if (cfgidx != pdev->dev_config) { /* Clear old configuration */ USBD_ClrClassConfig(pdev , pdev->dev_config); /* set new configuration */ pdev->dev_config = cfgidx; if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL) { USBD_CtlError(pdev , req); return; } USBD_CtlSendStatus(pdev); } else { USBD_CtlSendStatus(pdev); } break; default: USBD_CtlError(pdev , req); break; } } } /** * @brief USBD_GetConfig * Handle Get device configuration request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_GetConfig(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { if (req->wLength != 1) { USBD_CtlError(pdev , req); } else { switch (pdev->dev_state ) { case USBD_STATE_ADDRESSED: pdev->dev_default_config = 0; USBD_CtlSendData (pdev, (uint8_t *)&pdev->dev_default_config, 1); break; case USBD_STATE_CONFIGURED: USBD_CtlSendData (pdev, (uint8_t *)&pdev->dev_config, 1); break; default: USBD_CtlError(pdev , req); break; } } } /** * @brief USBD_GetStatus * Handle Get Status request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_GetStatus(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: case USBD_STATE_CONFIGURED: #if ( USBD_SELF_POWERED == 1) pdev->dev_config_status = USB_CONFIG_SELF_POWERED; #else pdev->dev_config_status = 0; #endif if (pdev->dev_remote_wakeup) { pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP; } USBD_CtlSendData (pdev, (uint8_t *)& pdev->dev_config_status, 2); break; default : USBD_CtlError(pdev , req); break; } } /** * @brief USBD_SetFeature * Handle Set device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetFeature(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev_remote_wakeup = 1; pdev->pClass->Setup (pdev, req); USBD_CtlSendStatus(pdev); } } /** * @brief USBD_ClrFeature * Handle clear device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_ClrFeature(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev_remote_wakeup = 0; pdev->pClass->Setup (pdev, req); USBD_CtlSendStatus(pdev); } break; default : USBD_CtlError(pdev , req); break; } } /** * @brief USBD_ParseSetupRequest * Copy buffer into setup structure * @param pdev: device instance * @param req: usb request * @retval None */ void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata) { req->bmRequest = *(uint8_t *) (pdata); req->bRequest = *(uint8_t *) (pdata + 1); req->wValue = SWAPBYTE (pdata + 2); req->wIndex = SWAPBYTE (pdata + 4); req->wLength = SWAPBYTE (pdata + 6); } /** * @brief USBD_CtlError * Handle USB low level Error * @param pdev: device instance * @param req: usb request * @retval None */ void USBD_CtlError( USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { USBD_LL_StallEP(pdev , 0x80); USBD_LL_StallEP(pdev , 0); } /** * @brief USBD_GetString * Convert Ascii string into unicode one * @param desc : descriptor buffer * @param unicode : Formatted string buffer (unicode) * @param len : descriptor length * @retval None */ void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len) { uint8_t idx = 0; if (desc != NULL) { *len = USBD_GetLen(desc) * 2 + 2; unicode[idx++] = *len; unicode[idx++] = USB_DESC_TYPE_STRING; while (*desc != '\0') { unicode[idx++] = *desc++; unicode[idx++] = 0x00; } } } /** * @brief USBD_GetLen * return the string length * @param buf : pointer to the ascii string buffer * @retval string length */ static uint8_t USBD_GetLen(uint8_t *buf) { uint8_t len = 0; while (*buf != '\0') { len++; buf++; } return len; } /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbdev/core/src/usbd_ioreq.c000066400000000000000000000123771357706137100234620ustar00rootroot00000000000000/** ****************************************************************************** * @file usbd_ioreq.c * @author MCD Application Team * @version V2.0.0 * @date 18-February-2014 * @brief This file provides the IO requests APIs for control endpoints. ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbd_ioreq.h" /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_IOREQ * @brief control I/O requests module * @{ */ /** @defgroup USBD_IOREQ_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Private_Defines * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Private_Macros * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Private_Variables * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Private_FunctionPrototypes * @{ */ /** * @} */ /** @defgroup USBD_IOREQ_Private_Functions * @{ */ /** * @brief USBD_CtlSendData * send data on the ctl pipe * @param pdev: device instance * @param buff: pointer to data buffer * @param len: length of data to be sent * @retval status */ USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len) { /* Set EP0 State */ pdev->ep0_state = USBD_EP0_DATA_IN; pdev->ep_in[0].total_length = len; pdev->ep_in[0].rem_length = len; /* Start the transfer */ USBD_LL_Transmit (pdev, 0x00, pbuf, len); return USBD_OK; } /** * @brief USBD_CtlContinueSendData * continue sending data on the ctl pipe * @param pdev: device instance * @param buff: pointer to data buffer * @param len: length of data to be sent * @retval status */ USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len) { /* Start the next transfer */ USBD_LL_Transmit (pdev, 0x00, pbuf, len); return USBD_OK; } /** * @brief USBD_CtlPrepareRx * receive data on the ctl pipe * @param pdev: USB OTG device instance * @param buff: pointer to data buffer * @param len: length of data to be received * @retval status */ USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len) { /* Set EP0 State */ pdev->ep0_state = USBD_EP0_DATA_OUT; pdev->ep_out[0].total_length = len; pdev->ep_out[0].rem_length = len; /* Start the transfer */ USBD_LL_PrepareReceive (pdev, 0, pbuf, len); return USBD_OK; } /** * @brief USBD_CtlContinueRx * continue receive data on the ctl pipe * @param pdev: USB OTG device instance * @param buff: pointer to data buffer * @param len: length of data to be received * @retval status */ USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len) { USBD_LL_PrepareReceive (pdev, 0, pbuf, len); return USBD_OK; } /** * @brief USBD_CtlSendStatus * send zero lzngth packet on the ctl pipe * @param pdev: USB OTG device instance * @retval status */ USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev) { /* Set EP0 State */ pdev->ep0_state = USBD_EP0_STATUS_IN; /* Start the transfer */ USBD_LL_Transmit (pdev, 0x00, NULL, 0); return USBD_OK; } /** * @brief USBD_CtlReceiveStatus * receive zero lzngth packet on the ctl pipe * @param pdev: USB OTG device instance * @retval status */ USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev) { /* Set EP0 State */ pdev->ep0_state = USBD_EP0_STATUS_OUT; /* Start the transfer */ USBD_LL_PrepareReceive ( pdev, 0, NULL, 0); return USBD_OK; } /** * @brief USBD_GetRxCount * returns the received data length * @param pdev: USB OTG device instance * epnum: endpoint index * @retval Rx Data blength */ uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , uint8_t ep_addr) { return USBD_LL_GetRxDataSize(pdev, ep_addr); } /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/000077500000000000000000000000001357706137100176305ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/000077500000000000000000000000001357706137100206755ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/AUDIO/000077500000000000000000000000001357706137100215365ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/AUDIO/Inc/000077500000000000000000000000001357706137100222475ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/AUDIO/Inc/usbh_audio.h000066400000000000000000000375311357706137100245530ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_audio.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contains all the prototypes for the usbh_audio.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_AUDIO_H #define __USBH_AUDIO_H /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_AUDIO_CLASS * @{ */ /** @defgroup USBH_AUDIO_CORE * @brief This file is the Header file for usbh_audio.c * @{ */ /** @defgroup USBH_AUDIO_CORE_Exported_Types * @{ */ /* States for AUDIO State Machine */ typedef enum { AUDIO_INIT = 0, AUDIO_IDLE, AUDIO_CS_REQUESTS, AUDIO_SET_DEFAULT_FEATURE_UNIT, AUDIO_SET_INTERFACE, AUDIO_SET_STREAMING_INTERFACE, AUDIO_SET_CUR1, AUDIO_GET_MIN, AUDIO_GET_MAX, AUDIO_GET_RES, AUDIO_GET_CUR1, AUDIO_SET_CUR2, AUDIO_GET_CUR2, AUDIO_SET_CUR3, AUDIO_SET_INTERFACE0, AUDIO_SET_INTERFACE1, AUDIO_SET_INTERFACE2, AUDIO_ISOC_OUT, AUDIO_ISOC_IN, AUDIO_ISOC_POLL, AUDIO_ERROR, } AUDIO_StateTypeDef; typedef enum { AUDIO_REQ_INIT = 1, AUDIO_REQ_IDLE, AUDIO_REQ_SET_DEFAULT_IN_INTERFACE, AUDIO_REQ_SET_DEFAULT_OUT_INTERFACE, AUDIO_REQ_SET_IN_INTERFACE, AUDIO_REQ_SET_OUT_INTERFACE, AUDIO_REQ_CS_REQUESTS, } AUDIO_ReqStateTypeDef; typedef enum { AUDIO_REQ_SET_VOLUME = 1, AUDIO_REQ_SET_MUTE, AUDIO_REQ_GET_CURR_VOLUME, AUDIO_REQ_GET_MIN_VOLUME, AUDIO_REQ_GET_MAX_VOLUME, AUDIO_REQ_GET_VOLUME, AUDIO_REQ_GET_RESOLUTION, AUDIO_REQ_CS_IDLE, } AUDIO_CSReqStateTypeDef; typedef enum { AUDIO_PLAYBACK_INIT = 1, AUDIO_PLAYBACK_SET_EP, AUDIO_PLAYBACK_SET_EP_FREQ, AUDIO_PLAYBACK_PLAY, AUDIO_PLAYBACK_IDLE, } AUDIO_PlayStateTypeDef; typedef enum { VOLUME_UP = 1, VOLUME_DOWN = 2, } AUDIO_VolumeCtrlTypeDef; typedef enum { AUDIO_CONTROL_INIT = 1, AUDIO_CONTROL_CHANGE, AUDIO_CONTROL_IDLE, AUDIO_CONTROL_VOLUME_UP, AUDIO_CONTROL_VOLUME_DOWN, } AUDIO_ControlStateTypeDef; typedef enum { AUDIO_DATA_START_OUT = 1, AUDIO_DATA_OUT, } AUDIO_ProcessingTypeDef; /* Structure for AUDIO process */ typedef struct { uint8_t Channels; uint8_t Bits; uint32_t SampleRate; } AUDIO_FormatTypeDef; typedef struct { uint8_t Ep; uint16_t EpSize; uint8_t AltSettings; uint8_t interface; uint8_t valid; uint16_t Poll; } AUDIO_STREAMING_IN_HandleTypeDef; typedef struct { uint8_t Ep; uint16_t EpSize; uint8_t AltSettings; uint8_t interface; uint8_t valid; uint16_t Poll; } AUDIO_STREAMING_OUT_HandleTypeDef; typedef struct { uint8_t mute; uint32_t volumeMin; uint32_t volumeMax; uint32_t volume; uint32_t resolution; } AUDIO_ControlAttributeTypeDef; typedef struct { uint8_t Ep; uint16_t EpSize; uint8_t interface; uint8_t AltSettings; uint8_t supported; uint8_t Pipe; uint8_t Poll; uint32_t timer ; uint8_t asociated_as; uint8_t asociated_mixer; uint8_t asociated_selector; uint8_t asociated_feature; uint8_t asociated_terminal; uint8_t asociated_channels; uint32_t frequency; uint8_t *buf; uint8_t *cbuf; uint32_t partial_ptr; uint32_t global_ptr; uint16_t frame_length; uint32_t total_length; AUDIO_ControlAttributeTypeDef attribute; } AUDIO_InterfaceStreamPropTypeDef; typedef struct { uint8_t Ep; uint16_t EpSize; uint8_t interface; uint8_t supported; uint8_t Pipe; uint8_t Poll; uint32_t timer ; } AUDIO_InterfaceControlPropTypeDef; #define AUDIO_MAX_AUDIO_STD_INTERFACE 0x05 #define AUDIO_MAX_FREQ_SUPPORTED 0x05 #define AUDIO_MAX_STREAMING_INTERFACE 0x05 #define AUDIO_MAX_NUM_IN_TERMINAL 0x04 #define AUDIO_MAX_NUM_OUT_TERMINAL 0x04 #define AUDIO_MAX_NUM_FEATURE_UNIT 0x04 #define AUDIO_MAX_NUM_MIXER_UNIT 0x04 #define AUDIO_MAX_NUM_SELECTOR_UNIT 0x04 #define HEADPHONE_SUPPORTED 0x01 #define MICROPHONE_SUPPORTED 0x02 #define HEADSET_SUPPORTED 0x03 /*Class-Specific AS(Audio Streaming) Interface Descriptor*/ typedef struct { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubtype; uint8_t bTerminalLink; uint8_t bDelay; uint8_t wFormatTag[2]; } AUDIO_ASGeneralDescTypeDef; /*Class-Specific AS(Audio Streaming) Format Type Descriptor*/ typedef struct { uint8_t bLength; /*At to be deside*/ uint8_t bDescriptorType; uint8_t bDescriptorSubtype; uint8_t bFormatType; uint8_t bNrChannels; uint8_t bSubframeSize; uint8_t bBitResolution; uint8_t bSamFreqType; uint8_t tSamFreq[][3]; } AUDIO_ASFormatTypeDescTypeDef; /*Class-Specific AS(Audio Streaming) Interface Descriptor*/ typedef struct { AUDIO_ASGeneralDescTypeDef *GeneralDesc; AUDIO_ASFormatTypeDescTypeDef *FormatTypeDesc; } AUDIO_ASDescTypeDef; /* 4.3.2 Class-Specific AC Interface Descriptor */ typedef struct { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubtype; uint8_t bcdADC[2]; uint8_t wTotalLength[2]; uint8_t bInCollection; uint8_t baInterfaceNr[]; } AUDIO_HeaderDescTypeDef; /* 4.3.2.1 Input Terminal Descriptor */ typedef struct { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubtype; uint8_t bTerminalID; uint8_t wTerminalType[2]; uint8_t bAssocTerminal; uint8_t bNrChannels; uint8_t wChannelConfig[2]; uint8_t iChannelNames; uint8_t iTerminal; } AUDIO_ITDescTypeDef; /* 4.3.2.2 Output Terminal Descriptor */ typedef struct { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubtype; uint8_t bTerminalID; uint8_t wTerminalType[2]; uint8_t bAssocTerminal; uint8_t bSourceID; uint8_t iTerminal; } AUDIO_OTDescTypeDef; /* 4.3.2.3 Feature Descriptor */ typedef struct { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubtype; uint8_t bUnitID; uint8_t bSourceID; uint8_t bControlSize; uint8_t bmaControls[][2]; } AUDIO_FeatureDescTypeDef; /* 4.3.2.3 Feature Descriptor */ typedef struct { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubtype; uint8_t bUnitID; uint8_t bNrInPins; uint8_t bSourceID0; uint8_t bSourceID1; uint8_t bNrChannels; uint8_t bmChannelsConfig[2]; uint8_t iChannelsNames; uint8_t bmaControls; uint8_t iMixer; } AUDIO_MixerDescTypeDef; /* 4.3.2.3 Feature Descriptor */ typedef struct { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubtype; uint8_t bUnitID; uint8_t bNrInPins; uint8_t bSourceID0; uint8_t iSelector; } AUDIO_SelectorDescTypeDef; /*Class-Specific AC(Audio Control) Interface Descriptor*/ typedef struct { AUDIO_HeaderDescTypeDef *HeaderDesc; AUDIO_ITDescTypeDef *InputTerminalDesc [AUDIO_MAX_NUM_IN_TERMINAL]; AUDIO_OTDescTypeDef *OutputTerminalDesc[AUDIO_MAX_NUM_OUT_TERMINAL]; AUDIO_FeatureDescTypeDef *FeatureUnitDesc [AUDIO_MAX_NUM_FEATURE_UNIT]; AUDIO_MixerDescTypeDef *MixerUnitDesc [AUDIO_MAX_NUM_MIXER_UNIT]; AUDIO_SelectorDescTypeDef *SelectorUnitDesc [AUDIO_MAX_NUM_SELECTOR_UNIT]; } AUDIO_ACDescTypeDef; /*Class-Specific AC : Global descriptor*/ typedef struct { AUDIO_ACDescTypeDef cs_desc; /* Only one control descriptor*/ AUDIO_ASDescTypeDef as_desc[AUDIO_MAX_STREAMING_INTERFACE]; uint16_t ASNum; uint16_t InputTerminalNum; uint16_t OutputTerminalNum; uint16_t FeatureUnitNum; uint16_t SelectorUnitNum; uint16_t MixerUnitNum; } AUDIO_ClassSpecificDescTypedef; typedef struct _AUDIO_Process { AUDIO_ReqStateTypeDef req_state; AUDIO_CSReqStateTypeDef cs_req_state; AUDIO_PlayStateTypeDef play_state; AUDIO_ControlStateTypeDef control_state; AUDIO_ProcessingTypeDef processing_state; AUDIO_STREAMING_IN_HandleTypeDef stream_in[AUDIO_MAX_AUDIO_STD_INTERFACE]; AUDIO_STREAMING_OUT_HandleTypeDef stream_out[AUDIO_MAX_AUDIO_STD_INTERFACE]; AUDIO_ClassSpecificDescTypedef class_desc; AUDIO_InterfaceStreamPropTypeDef headphone; AUDIO_InterfaceStreamPropTypeDef microphone; AUDIO_InterfaceControlPropTypeDef control; uint16_t mem [8]; uint8_t temp_feature; uint8_t temp_channels; } AUDIO_HandleTypeDef; /** * @} */ /** @defgroup USBH_AUDIO_CORE_Exported_Defines * @{ */ /*Audio Interface Subclass Codes*/ #define AC_CLASS 0x01 /* A.2 Audio Interface Subclass Codes */ #define USB_SUBCLASS_AUDIOCONTROL 0x01 #define USB_SUBCLASS_AUDIOSTREAMING 0x02 #define USB_SUBCLASS_MIDISTREAMING 0x03 #define USB_DESC_TYPE_CS_INTERFACE 0x24 #define USB_DESC_TYPE_CS_ENDPOINT 0x25 /* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */ #define UAC_HEADER 0x01 #define UAC_INPUT_TERMINAL 0x02 #define UAC_OUTPUT_TERMINAL 0x03 #define UAC_MIXER_UNIT 0x04 #define UAC_SELECTOR_UNIT 0x05 #define UAC_FEATURE_UNIT 0x06 #define UAC_PROCESSING_UNIT 0x07 #define UAC_EXTENSION_UNIT 0x08 /*Audio Class-Specific Endpoint Descriptor Subtypes*/ #define EP_CONTROL_UNDEFINED 0x00 #define SAMPLING_FREQ_CONTROL 0x01 #define PITCH_CONTROL 0x02 /*Feature unit control selector*/ #define FU_CONTROL_UNDEFINED 0x00 #define MUTE_CONTROL 0x01 #define VOLUME_CONTROL 0x02 #define BASS_CONTROL 0x03 #define MID_CONTROL 0x04 #define TREBLE_CONTROL 0x05 #define GRAPHIC_EQUALIZER_CONTROL 0x06 #define AUTOMATIC_GAIN_CONTROL 0x07 #define DELAY_CONTROL 0x08 #define BASS_BOOST_CONTROL 0x09 #define LOUDNESS_CONTROL 0x0A /*Terminal control selector*/ #define TE_CONTROL_UNDEFINED 0x00 #define COPY_PROTECT_CONTROL 0x01 /* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */ #define UAC_AS_GENERAL 0x01 #define UAC_FORMAT_TYPE 0x02 #define UAC_FORMAT_SPECIFIC 0x03 /* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */ #define UAC_EP_GENERAL 0x01 /* A.9 Audio Class-Specific Request Codes */ #define UAC_SET_ 0x00 #define UAC_GET_ 0x80 #define UAC__CUR 0x1 #define UAC__MIN 0x2 #define UAC__MAX 0x3 #define UAC__RES 0x4 #define UAC__MEM 0x5 #define UAC_SET_CUR (UAC_SET_ | UAC__CUR) #define UAC_GET_CUR (UAC_GET_ | UAC__CUR) #define UAC_SET_MIN (UAC_SET_ | UAC__MIN) #define UAC_GET_MIN (UAC_GET_ | UAC__MIN) #define UAC_SET_MAX (UAC_SET_ | UAC__MAX) #define UAC_GET_MAX (UAC_GET_ | UAC__MAX) #define UAC_SET_RES (UAC_SET_ | UAC__RES) #define UAC_GET_RES (UAC_GET_ | UAC__RES) #define UAC_SET_MEM (UAC_SET_ | UAC__MEM) #define UAC_GET_MEM (UAC_GET_ | UAC__MEM) #define UAC_GET_STAT 0xff /* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */ #define UAC_MS_HEADER 0x01 #define UAC_MIDI_IN_JACK 0x02 #define UAC_MIDI_OUT_JACK 0x03 /* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */ #define UAC_MS_GENERAL 0x01 /* Terminals - 2.1 USB Terminal Types */ #define UAC_TERMINAL_UNDEFINED 0x100 #define UAC_TERMINAL_STREAMING 0x101 #define UAC_TERMINAL_VENDOR_SPEC 0x1FF /** * @} */ /** @defgroup USBH_AUDIO_CORE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_AUDIO_CORE_Exported_Variables * @{ */ extern USBH_ClassTypeDef AUDIO_Class; #define USBH_AUDIO_CLASS &AUDIO_Class /** * @} */ /** @defgroup USBH_AUDIO_CORE_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_AUDIO_SetFrequency (USBH_HandleTypeDef *phost, uint16_t sample_rate, uint8_t channel_num, uint8_t data_width); USBH_StatusTypeDef USBH_AUDIO_Play (USBH_HandleTypeDef *phost, uint8_t *buf, uint32_t length); USBH_StatusTypeDef USBH_AUDIO_Stop (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_AUDIO_Suspend (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_AUDIO_Resume (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_AUDIO_SetVolume (USBH_HandleTypeDef *phost, AUDIO_VolumeCtrlTypeDef volume_ctl); USBH_StatusTypeDef USBH_AUDIO_ChangeOutBuffer (USBH_HandleTypeDef *phost, uint8_t *buf); int32_t USBH_AUDIO_GetOutOffset (USBH_HandleTypeDef *phost); void USBH_AUDIO_FrequencySet(USBH_HandleTypeDef *phost); /** * @} */ #endif /* __USBH_AUDIO_H */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/AUDIO/Src/000077500000000000000000000000001357706137100222655ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/AUDIO/Src/usbh_audio.c000066400000000000000000001771221357706137100245650ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_audio.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the AC Layer Handlers for USB Host AC class. * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_audio.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_AUDIO_CLASS * @{ */ /** @defgroup USBH_AUDIO_CORE * @brief This file includes HID Layer Handlers for USB Host HID class. * @{ */ /** @defgroup USBH_AUDIO_CORE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_AUDIO_CORE_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_AUDIO_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_AUDIO_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_AUDIO_CORE_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_AUDIO_InterfaceInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_InterfaceDeInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_Process(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_SOFProcess(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_ClassRequest(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_CSRequest(USBH_HandleTypeDef *phost, uint8_t feature, uint8_t channel); static USBH_StatusTypeDef USBH_AUDIO_HandleCSRequest(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_FindAudioStreamingIN(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_FindAudioStreamingOUT(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_FindHIDControl(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_ParseCSDescriptors(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_BuildHeadphonePath(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_BuildMicrophonePath(USBH_HandleTypeDef *phost); int32_t USBH_AUDIO_FindLinkedUnitIN(USBH_HandleTypeDef *phost, uint8_t UnitID); int32_t USBH_AUDIO_FindLinkedUnitOUT(USBH_HandleTypeDef *phost, uint8_t UnitID); static USBH_StatusTypeDef ParseCSDescriptors(AUDIO_ClassSpecificDescTypedef *class_desc, uint8_t ac_subclass, uint8_t *pdesc); static USBH_StatusTypeDef USBH_AUDIO_Transmit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AC_SetCur(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length); static USBH_StatusTypeDef USBH_AC_GetCur(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length); static USBH_StatusTypeDef USBH_AC_GetMin(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length); static USBH_StatusTypeDef USBH_AC_GetMax(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length); static USBH_StatusTypeDef USBH_AC_GetRes(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length); static USBH_StatusTypeDef USBH_AUDIO_SetEndpointControls(USBH_HandleTypeDef *phost, uint8_t Ep, uint8_t *buff); static USBH_StatusTypeDef AUDIO_SetVolume (USBH_HandleTypeDef *phost, uint8_t feature, uint8_t channel, uint16_t volume); static USBH_StatusTypeDef USBH_AUDIO_InputStream (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_OutputStream (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_Control (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_AUDIO_SetControlAttribute (USBH_HandleTypeDef *phost, uint8_t attrib); static int32_t USBH_AUDIO_FindLinkedUnit(USBH_HandleTypeDef *phost, uint8_t UnitID); USBH_ClassTypeDef AUDIO_Class = { "AUDIO", AC_CLASS, USBH_AUDIO_InterfaceInit, USBH_AUDIO_InterfaceDeInit, USBH_AUDIO_ClassRequest, USBH_AUDIO_Process, USBH_AUDIO_SOFProcess, NULL, }; /** * @} */ /** @defgroup USBH_AUDIO_CORE_Private_Functions * @{ */ /** * @brief USBH_AUDIO_InterfaceInit * The function init the Audio class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_InterfaceInit (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_FAIL ; USBH_StatusTypeDef out_status, in_status ; AUDIO_HandleTypeDef *AUDIO_Handle; uint8_t interface, index; uint16_t ep_size_out = 0; uint16_t ep_size_in = 0; interface = USBH_FindInterface(phost, AC_CLASS, USB_SUBCLASS_AUDIOCONTROL, 0x00); if(interface == 0xFF) /* Not Valid Interface */ { USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name); status = USBH_FAIL; } else { phost->pActiveClass->pData = (AUDIO_HandleTypeDef *)USBH_malloc (sizeof(AUDIO_HandleTypeDef)); AUDIO_Handle = phost->pActiveClass->pData; USBH_memset(AUDIO_Handle, 0, sizeof(AUDIO_HandleTypeDef)); /* 1st Step: Find Audio Interfaces */ out_status = USBH_AUDIO_FindAudioStreamingIN (phost); in_status = USBH_AUDIO_FindAudioStreamingOUT(phost); if((out_status == USBH_FAIL) && (in_status == USBH_FAIL)) { USBH_DbgLog ("%s class configuration not supported.", phost->pActiveClass->Name); } else { /* 2nd Step: Select Audio Streaming Interfaces with largest endpoint size : default behavior*/ for (index = 0; index < AUDIO_MAX_AUDIO_STD_INTERFACE; index ++) { if( AUDIO_Handle->stream_out[index].valid == 1) { if(ep_size_out < AUDIO_Handle->stream_out[index].EpSize) { ep_size_out = AUDIO_Handle->stream_out[index].EpSize; AUDIO_Handle->headphone.interface = AUDIO_Handle->stream_out[index].interface; AUDIO_Handle->headphone.AltSettings = AUDIO_Handle->stream_out[index].AltSettings; AUDIO_Handle->headphone.Ep = AUDIO_Handle->stream_out[index].Ep; AUDIO_Handle->headphone.EpSize = AUDIO_Handle->stream_out[index].EpSize; AUDIO_Handle->headphone.Poll = AUDIO_Handle->stream_out[index].Poll; AUDIO_Handle->headphone.supported = 1; } } if( AUDIO_Handle->stream_in[index].valid == 1) { if(ep_size_in < AUDIO_Handle->stream_in[index].EpSize) { ep_size_in = AUDIO_Handle->stream_in[index].EpSize; AUDIO_Handle->microphone.interface = AUDIO_Handle->stream_in[index].interface; AUDIO_Handle->microphone.AltSettings = AUDIO_Handle->stream_in[index].AltSettings; AUDIO_Handle->microphone.Ep = AUDIO_Handle->stream_in[index].Ep; AUDIO_Handle->microphone.EpSize = AUDIO_Handle->stream_in[index].EpSize; AUDIO_Handle->microphone.Poll = AUDIO_Handle->stream_out[index].Poll; AUDIO_Handle->microphone.supported = 1; } } } if(USBH_AUDIO_FindHIDControl(phost) == USBH_OK) { AUDIO_Handle->control.supported = 1; } /* 3rd Step: Find and Parse Audio interfaces */ USBH_AUDIO_ParseCSDescriptors (phost); /* 4th Step: Open the Audio streaming pipes*/ if(AUDIO_Handle->headphone.supported == 1) { USBH_AUDIO_BuildHeadphonePath (phost); AUDIO_Handle->headphone.Pipe = USBH_AllocPipe(phost, AUDIO_Handle->headphone.Ep); /* Open pipe for IN endpoint */ USBH_OpenPipe (phost, AUDIO_Handle->headphone.Pipe, AUDIO_Handle->headphone.Ep, phost->device.address, phost->device.speed, USB_EP_TYPE_ISOC, AUDIO_Handle->headphone.EpSize); USBH_LL_SetToggle (phost, AUDIO_Handle->headphone.Pipe, 0); } if(AUDIO_Handle->microphone.supported == 1) { USBH_AUDIO_BuildMicrophonePath (phost); AUDIO_Handle->microphone.Pipe = USBH_AllocPipe(phost, AUDIO_Handle->microphone.Ep); /* Open pipe for IN endpoint */ USBH_OpenPipe (phost, AUDIO_Handle->microphone.Pipe, AUDIO_Handle->microphone.Ep, phost->device.address, phost->device.speed, USB_EP_TYPE_ISOC, AUDIO_Handle->microphone.EpSize); USBH_LL_SetToggle (phost, AUDIO_Handle->microphone.Pipe, 0); } if(AUDIO_Handle->control.supported == 1) { AUDIO_Handle->control.Pipe = USBH_AllocPipe(phost, AUDIO_Handle->control.Ep); /* Open pipe for IN endpoint */ USBH_OpenPipe (phost, AUDIO_Handle->control.Pipe, AUDIO_Handle->control.Ep, phost->device.address, phost->device.speed, USB_EP_TYPE_INTR, AUDIO_Handle->control.EpSize); USBH_LL_SetToggle (phost, AUDIO_Handle->control.Pipe, 0); } AUDIO_Handle->req_state = AUDIO_REQ_INIT; AUDIO_Handle->control_state = AUDIO_CONTROL_INIT; status = USBH_OK; } } return status; } /** * @brief USBH_AUDIO_InterfaceDeInit * The function DeInit the Pipes used for the Audio class. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_InterfaceDeInit (USBH_HandleTypeDef *phost) { AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->microphone.Pipe != 0x00) { USBH_ClosePipe (phost, AUDIO_Handle->microphone.Pipe); USBH_FreePipe (phost, AUDIO_Handle->microphone.Pipe); AUDIO_Handle->microphone.Pipe = 0; /* Reset the pipe as Free */ } if( AUDIO_Handle->headphone.Pipe != 0x00) { USBH_ClosePipe(phost, AUDIO_Handle->headphone.Pipe); USBH_FreePipe (phost, AUDIO_Handle->headphone.Pipe); AUDIO_Handle->headphone.Pipe = 0; /* Reset the pipe as Free */ } if( AUDIO_Handle->control.Pipe != 0x00) { USBH_ClosePipe(phost, AUDIO_Handle->control.Pipe); USBH_FreePipe (phost, AUDIO_Handle->control.Pipe); AUDIO_Handle->control.Pipe = 0; /* Reset the pipe as Free */ } if(phost->pActiveClass->pData) { USBH_free (phost->pActiveClass->pData); phost->pActiveClass->pData = 0; } return USBH_OK ; } /** * @brief USBH_AUDIO_ClassRequest * The function is responsible for handling Standard requests * for Audio class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_ClassRequest(USBH_HandleTypeDef *phost) { AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef req_status = USBH_BUSY; /* Switch AUDIO REQ state machine */ switch (AUDIO_Handle->req_state) { case AUDIO_REQ_INIT: case AUDIO_REQ_SET_DEFAULT_IN_INTERFACE: if(AUDIO_Handle->microphone.supported == 1) { req_status = USBH_SetInterface(phost, AUDIO_Handle->microphone.interface, 0); if(req_status == USBH_OK) { AUDIO_Handle->req_state = AUDIO_REQ_SET_DEFAULT_OUT_INTERFACE; } } else { AUDIO_Handle->req_state = AUDIO_REQ_SET_DEFAULT_OUT_INTERFACE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case AUDIO_REQ_SET_DEFAULT_OUT_INTERFACE: if(AUDIO_Handle->headphone.supported == 1) { req_status = USBH_SetInterface(phost, AUDIO_Handle->headphone.interface, 0); if(req_status == USBH_OK) { AUDIO_Handle->req_state = AUDIO_REQ_CS_REQUESTS; AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_VOLUME; AUDIO_Handle->temp_feature = AUDIO_Handle->headphone.asociated_feature; AUDIO_Handle->temp_channels = AUDIO_Handle->headphone.asociated_channels; } } else { AUDIO_Handle->req_state = AUDIO_REQ_CS_REQUESTS; AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_VOLUME; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case AUDIO_REQ_CS_REQUESTS: if(USBH_AUDIO_HandleCSRequest (phost) == USBH_OK) { AUDIO_Handle->req_state = AUDIO_REQ_SET_IN_INTERFACE; } break; case AUDIO_REQ_SET_IN_INTERFACE: if(AUDIO_Handle->microphone.supported == 1) { req_status = USBH_SetInterface(phost, AUDIO_Handle->microphone.interface, AUDIO_Handle->microphone.AltSettings); if(req_status == USBH_OK) { AUDIO_Handle->req_state = AUDIO_REQ_SET_OUT_INTERFACE; } } else { AUDIO_Handle->req_state = AUDIO_REQ_SET_OUT_INTERFACE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case AUDIO_REQ_SET_OUT_INTERFACE: if(AUDIO_Handle->headphone.supported == 1) { req_status = USBH_SetInterface(phost, AUDIO_Handle->headphone.interface, AUDIO_Handle->headphone.AltSettings); if(req_status == USBH_OK) { AUDIO_Handle->req_state = AUDIO_REQ_IDLE; } } else { AUDIO_Handle->req_state = AUDIO_REQ_IDLE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case AUDIO_REQ_IDLE: AUDIO_Handle->play_state = AUDIO_PLAYBACK_INIT; phost->pUser(phost, HOST_USER_CLASS_ACTIVE); status = USBH_OK; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif default: break; } return status; } /** * @brief USBH_AUDIO_CSRequest * The function is responsible for handling AC Specific requests for a specific feature and channel * for Audio class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_CSRequest(USBH_HandleTypeDef *phost, uint8_t feature, uint8_t channel) { AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef req_status = USBH_BUSY; /* Switch AUDIO REQ state machine */ switch (AUDIO_Handle->cs_req_state) { case AUDIO_REQ_GET_VOLUME: req_status = USBH_AC_GetCur(phost, UAC_FEATURE_UNIT, /* subtype */ feature, /* feature */ VOLUME_CONTROL, /* Selector */ channel, /* channel */ 0x02); /* length */ if(req_status != USBH_BUSY) { AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_MIN_VOLUME; AUDIO_Handle->headphone.attribute.volume = LE16(&(AUDIO_Handle->mem[0])); } break; case AUDIO_REQ_GET_MIN_VOLUME: req_status = USBH_AC_GetMin(phost, UAC_FEATURE_UNIT, /* subtype */ feature, /* feature */ VOLUME_CONTROL, /* Selector */ channel, /* channel */ 0x02); /* length */ if(req_status != USBH_BUSY) { AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_MAX_VOLUME; AUDIO_Handle->headphone.attribute.volumeMin = LE16(&AUDIO_Handle->mem[0]); } break; case AUDIO_REQ_GET_MAX_VOLUME: req_status = USBH_AC_GetMax(phost, UAC_FEATURE_UNIT, /* subtype */ feature, /* feature */ VOLUME_CONTROL, /* Selector */ channel, /* channel */ 0x02); /* length */ if(req_status != USBH_BUSY) { AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_RESOLUTION; AUDIO_Handle->headphone.attribute.volumeMax = LE16(&AUDIO_Handle->mem[0]); if (AUDIO_Handle->headphone.attribute.volumeMax < AUDIO_Handle->headphone.attribute.volumeMin) { AUDIO_Handle->headphone.attribute.volumeMax = 0xFF00; } } break; case AUDIO_REQ_GET_RESOLUTION: req_status = USBH_AC_GetRes(phost, UAC_FEATURE_UNIT, /* subtype */ feature, /* feature */ VOLUME_CONTROL, /* Selector */ channel, /* channel */ 0x02); /* length */ if(req_status != USBH_BUSY) { AUDIO_Handle->cs_req_state = AUDIO_REQ_CS_IDLE; AUDIO_Handle->headphone.attribute.resolution = LE16(&AUDIO_Handle->mem[0]); } break; case AUDIO_REQ_CS_IDLE: status = USBH_OK; default: break; } return status; } /** * @brief USBH_AUDIO_HandleCSRequest * The function is responsible for handling AC Specific requests for a all features * and associated channels for Audio class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_HandleCSRequest(USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef cs_status = USBH_BUSY; AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; cs_status = USBH_AUDIO_CSRequest(phost, AUDIO_Handle->temp_feature, AUDIO_Handle->temp_channels); if(cs_status != USBH_BUSY) { if(AUDIO_Handle->temp_channels == 1) { AUDIO_Handle->temp_feature = AUDIO_Handle->headphone.asociated_feature; AUDIO_Handle->temp_channels = 0; status = USBH_OK; } else { AUDIO_Handle->temp_channels--; } AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_VOLUME; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } return status; } /** * @brief USBH_AUDIO_Process * The function is for managing state machine for Audio data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_Process (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY; AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->headphone.supported == 1) { USBH_AUDIO_OutputStream (phost); } if(AUDIO_Handle->microphone.supported == 1) { USBH_AUDIO_InputStream (phost); } return status; } /** * @brief USBH_AUDIO_SOFProcess * The function is for managing the SOF callback * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_SOFProcess (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief Find IN Audio Streaming interfaces * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_FindAudioStreamingIN(USBH_HandleTypeDef *phost) { uint8_t interface, alt_settings; USBH_StatusTypeDef status = USBH_FAIL ; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; /* Look For AUDIOSTREAMING IN interface */ alt_settings = 0; for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if((phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == AC_CLASS)&& (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass == USB_SUBCLASS_AUDIOSTREAMING)) { if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80)&& (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize > 0)) { AUDIO_Handle->stream_in[alt_settings].Ep = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; AUDIO_Handle->stream_in[alt_settings].EpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; AUDIO_Handle->stream_in[alt_settings].interface = phost->device.CfgDesc.Itf_Desc[interface].bInterfaceNumber; AUDIO_Handle->stream_in[alt_settings].AltSettings = phost->device.CfgDesc.Itf_Desc[interface].bAlternateSetting; AUDIO_Handle->stream_in[alt_settings].Poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bInterval; AUDIO_Handle->stream_in[alt_settings].valid = 1; alt_settings++; } } } if(alt_settings > 0) { status = USBH_OK; } return status; } /** * @brief Find OUT Audio Streaming interfaces * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_FindAudioStreamingOUT(USBH_HandleTypeDef *phost) { uint8_t interface, alt_settings; USBH_StatusTypeDef status = USBH_FAIL ; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; /* Look For AUDIOSTREAMING IN interface */ alt_settings = 0; for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if((phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == AC_CLASS)&& (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass == USB_SUBCLASS_AUDIOSTREAMING)) { if(((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) == 0x00)&& (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize > 0)) { AUDIO_Handle->stream_out[alt_settings].Ep = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; AUDIO_Handle->stream_out[alt_settings].EpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; AUDIO_Handle->stream_out[alt_settings].interface = phost->device.CfgDesc.Itf_Desc[interface].bInterfaceNumber; AUDIO_Handle->stream_out[alt_settings].AltSettings = phost->device.CfgDesc.Itf_Desc[interface].bAlternateSetting; AUDIO_Handle->stream_out[alt_settings].Poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bInterval; AUDIO_Handle->stream_out[alt_settings].valid = 1; alt_settings++; } } } if(alt_settings > 0) { status = USBH_OK; } return status; } /** * @brief Find HID Control interfaces * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_FindHIDControl(USBH_HandleTypeDef *phost) { uint8_t interface; USBH_StatusTypeDef status = USBH_FAIL ; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; /* Look For AUDIOCONTROL interface */ interface = USBH_FindInterface(phost, AC_CLASS, USB_SUBCLASS_AUDIOCONTROL, 0xFF); if(interface != 0xFF) { for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if((phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == 0x03)&& /*HID*/ (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize > 0)) { if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) == 0x80) { AUDIO_Handle->control.Ep = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; AUDIO_Handle->control.EpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; AUDIO_Handle->control.interface = phost->device.CfgDesc.Itf_Desc[interface].bInterfaceNumber; AUDIO_Handle->control.Poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bInterval; AUDIO_Handle->control.supported = 1; status = USBH_OK; break; } } } } return status; } /** * @brief Parse AC and interfaces Descriptors * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_ParseCSDescriptors(USBH_HandleTypeDef *phost) { USBH_DescHeader_t *pdesc ; uint16_t ptr; int8_t itf_index = 0; int8_t itf_number = 0; int8_t alt_setting; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; pdesc = (USBH_DescHeader_t *)(phost->device.CfgDesc_Raw); ptr = USB_LEN_CFG_DESC; AUDIO_Handle->class_desc.FeatureUnitNum = 0; AUDIO_Handle->class_desc.InputTerminalNum = 0; AUDIO_Handle->class_desc.OutputTerminalNum = 0; AUDIO_Handle->class_desc.ASNum = 0; while(ptr < phost->device.CfgDesc.wTotalLength) { pdesc = USBH_GetNextDesc((void *)pdesc, &ptr); switch (pdesc->bDescriptorType) { case USB_DESC_TYPE_INTERFACE: itf_number = *((uint8_t *)pdesc + 2); alt_setting = *((uint8_t *)pdesc + 3); itf_index = USBH_FindInterfaceIndex (phost, itf_number, alt_setting); break; case USB_DESC_TYPE_CS_INTERFACE: if(itf_number <= phost->device.CfgDesc.bNumInterfaces) { ParseCSDescriptors(&AUDIO_Handle->class_desc, phost->device.CfgDesc.Itf_Desc[itf_index].bInterfaceSubClass, (uint8_t *)pdesc); } break; default: break; } } return USBH_OK; } /** * @brief Parse AC interfaces * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef ParseCSDescriptors(AUDIO_ClassSpecificDescTypedef *class_desc, uint8_t ac_subclass, uint8_t *pdesc) { if(ac_subclass == USB_SUBCLASS_AUDIOCONTROL) { switch(pdesc[2]) { case UAC_HEADER: class_desc->cs_desc.HeaderDesc = (AUDIO_HeaderDescTypeDef *)pdesc; break; case UAC_INPUT_TERMINAL: class_desc->cs_desc.InputTerminalDesc[class_desc->InputTerminalNum++] = (AUDIO_ITDescTypeDef*) pdesc; break; case UAC_OUTPUT_TERMINAL: class_desc->cs_desc.OutputTerminalDesc[class_desc->OutputTerminalNum++] = (AUDIO_OTDescTypeDef*) pdesc; break; case UAC_FEATURE_UNIT: class_desc->cs_desc.FeatureUnitDesc[class_desc->FeatureUnitNum++] = (AUDIO_FeatureDescTypeDef*) pdesc; break; case UAC_SELECTOR_UNIT: class_desc->cs_desc.SelectorUnitDesc[class_desc->SelectorUnitNum++] = (AUDIO_SelectorDescTypeDef*) pdesc; break; case UAC_MIXER_UNIT: class_desc->cs_desc.MixerUnitDesc[class_desc->MixerUnitNum++] = (AUDIO_MixerDescTypeDef*) pdesc; break; default: break; } } else if(ac_subclass == USB_SUBCLASS_AUDIOSTREAMING) { switch(pdesc[2]) { case UAC_AS_GENERAL: class_desc->as_desc[class_desc->ASNum].GeneralDesc = (AUDIO_ASGeneralDescTypeDef*) pdesc; break; case UAC_FORMAT_TYPE: class_desc->as_desc[class_desc->ASNum++].FormatTypeDesc = (AUDIO_ASFormatTypeDescTypeDef*) pdesc; break; default: break; } } return USBH_OK; } /** * @brief Link a Unit to next associated one * @param phost: Host handle * @param UnitID: Unit identifer * @retval UnitID, Index and Type of the assicated Unit */ static int32_t USBH_AUDIO_FindLinkedUnit(USBH_HandleTypeDef *phost, uint8_t UnitID) { uint8_t Index; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; /* Find Feature Unit */ for(Index = 0; Index < AUDIO_Handle->class_desc.FeatureUnitNum; Index ++) { if(AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[Index]->bSourceID == UnitID) { UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[Index]->bUnitID; return ((UnitID << 16) | (UAC_FEATURE_UNIT << 8) | Index); } } /* Find Mixer Unit */ for(Index = 0; Index < AUDIO_Handle->class_desc.MixerUnitNum; Index ++) { if((AUDIO_Handle->class_desc.cs_desc.MixerUnitDesc[Index]->bSourceID0 == UnitID)|| (AUDIO_Handle->class_desc.cs_desc.MixerUnitDesc[Index]->bSourceID1 == UnitID)) { UnitID = AUDIO_Handle->class_desc.cs_desc.MixerUnitDesc[Index]->bUnitID; return ((UnitID << 16) | (UAC_MIXER_UNIT << 8) | Index); } } /* Find Selector Unit */ for(Index = 0; Index < AUDIO_Handle->class_desc.SelectorUnitNum; Index ++) { if(AUDIO_Handle->class_desc.cs_desc.SelectorUnitDesc[Index]->bSourceID0 == UnitID) { UnitID = AUDIO_Handle->class_desc.cs_desc.SelectorUnitDesc[Index]->bUnitID; return ((UnitID << 16) | (UAC_SELECTOR_UNIT << 8) | Index); } } /* Find OT Unit */ for(Index = 0; Index < AUDIO_Handle->class_desc.OutputTerminalNum; Index ++) { if(AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[Index]->bSourceID == UnitID) { UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[Index]->bTerminalID; return ((UnitID << 16) | (UAC_OUTPUT_TERMINAL << 8) | Index); } } /* No associated Unit found */ return -1; } /** * @brief Build full path for Microphone device * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_BuildMicrophonePath(USBH_HandleTypeDef *phost) { uint8_t UnitID = 0, Type, Index; uint32_t value; uint8_t terminalIndex; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; /*Find microphone IT*/ for(terminalIndex = 0; terminalIndex < AUDIO_Handle->class_desc.InputTerminalNum; terminalIndex++) { if(LE16(AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->wTerminalType) == 0x201) { UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->bTerminalID; AUDIO_Handle->microphone.asociated_channels = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->bNrChannels; break; } } do { value = USBH_AUDIO_FindLinkedUnit(phost, UnitID); Index = value & 0xFF; Type = (value >> 8) & 0xFF; UnitID = (value >> 16) & 0xFF; switch (Type) { case UAC_FEATURE_UNIT: AUDIO_Handle->microphone.asociated_feature = Index; break; case UAC_MIXER_UNIT: AUDIO_Handle->microphone.asociated_mixer = Index; break; case UAC_SELECTOR_UNIT: AUDIO_Handle->microphone.asociated_selector = Index; break; case UAC_OUTPUT_TERMINAL: AUDIO_Handle->microphone.asociated_terminal = Index; break; } } while ((Type != UAC_OUTPUT_TERMINAL) && (value > 0)); return USBH_OK; } /** * @brief Build full path for Headphone device * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_BuildHeadphonePath(USBH_HandleTypeDef *phost) { uint8_t UnitID = 0, Type, Index; uint32_t value; uint8_t terminalIndex; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; /*Find association betwen audio streaming and microphone*/ for(terminalIndex = 0; terminalIndex < AUDIO_Handle->class_desc.InputTerminalNum; terminalIndex++) { if(LE16(AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->wTerminalType) == 0x101) { UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->bTerminalID; AUDIO_Handle->headphone.asociated_channels = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[terminalIndex]->bNrChannels; break; } } for(Index = 0; Index < AUDIO_Handle->class_desc.ASNum; Index++) { if(AUDIO_Handle->class_desc.as_desc[Index].GeneralDesc->bTerminalLink == UnitID) { AUDIO_Handle->headphone.asociated_as = Index; break; } } do { value = USBH_AUDIO_FindLinkedUnit(phost, UnitID); Index = value & 0xFF; Type = (value >> 8) & 0xFF; UnitID = (value >> 16) & 0xFF; switch (Type) { case UAC_FEATURE_UNIT: AUDIO_Handle->headphone.asociated_feature = Index; break; case UAC_MIXER_UNIT: AUDIO_Handle->headphone.asociated_mixer = Index; break; case UAC_SELECTOR_UNIT: AUDIO_Handle->headphone.asociated_selector = Index; break; case UAC_OUTPUT_TERMINAL: AUDIO_Handle->headphone.asociated_terminal = Index; if(LE16(AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[Index]->wTerminalType) != 0x103) { return USBH_OK; } break; } } while ((Type != UAC_OUTPUT_TERMINAL) && (value > 0)); return USBH_FAIL; } /** * @brief Handle Set Cur request * @param phost: Host handle * @param subtype: subtype index * @param feature: feature index * @param controlSelector: control code * @param channel: channel index * @param length: Command length * @retval USBH Status */ static USBH_StatusTypeDef USBH_AC_SetCur(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length) { uint16_t wValue,wIndex,wLength; uint8_t UnitID,InterfaceNum; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; switch(subtype) { case UAC_INPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; AUDIO_Handle->mem[0] = 0x00; wLength = 1; break; case UAC_FEATURE_UNIT: UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; /*holds the CS(control selector ) and CN (channel number)*/ wValue = (controlSelector << 8) | channel; wLength = length; break; } phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = UAC_SET_CUR; phost->Control.setup.b.wValue.w = wValue; phost->Control.setup.b.wIndex.w = wIndex; phost->Control.setup.b.wLength.w = wLength; return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength )); } /** * @brief Handle Get Cur request * @param phost: Host handle * @param subtype: subtype index * @param feature: feature index * @param controlSelector: control code * @param channel: channel index * @param length: Command length * @retval USBH Status */ static USBH_StatusTypeDef USBH_AC_GetCur(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length) { uint16_t wValue = 0, wIndex = 0,wLength = 0; uint8_t UnitID = 0, InterfaceNum = 0; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; switch(subtype) { case UAC_INPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; AUDIO_Handle->mem[0] = 0x00; wLength = 1; break; case UAC_FEATURE_UNIT: UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; /*holds the CS(control selector ) and CN (channel number)*/ wValue = (controlSelector << 8) | channel; wLength = length; break; case UAC_OUTPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; wLength = 1; break; } phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = UAC_GET_CUR; phost->Control.setup.b.wValue.w = wValue; phost->Control.setup.b.wIndex.w = wIndex; phost->Control.setup.b.wLength.w = wLength; return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength )); } /** * @brief Handle Get Max request * @param phost: Host handle * @param subtype: subtype index * @param feature: feature index * @param controlSelector: control code * @param channel: channel index * @param length: Command length * @retval USBH Status */ static USBH_StatusTypeDef USBH_AC_GetMax(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length) { uint16_t wValue = 0, wIndex = 0, wLength = 0; uint8_t UnitID = 0, InterfaceNum = 0; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; switch(subtype) { case UAC_INPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; AUDIO_Handle->mem[0] = 0x00; wLength = 1; break; case UAC_FEATURE_UNIT: UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; /*holds the CS(control selector ) and CN (channel number)*/ wValue = (controlSelector << 8) | channel; wLength = length; break; case UAC_OUTPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; wLength = 1; break; } phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = UAC_GET_MAX; phost->Control.setup.b.wValue.w = wValue; phost->Control.setup.b.wIndex.w = wIndex; phost->Control.setup.b.wLength.w = wLength; return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength )); } /** * @brief Handle Get Res request * @param phost: Host handle * @param subtype: subtype index * @param feature: feature index * @param controlSelector: control code * @param channel: channel index * @param length: Command length * @retval USBH Status */ static USBH_StatusTypeDef USBH_AC_GetRes(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length) { uint16_t wValue = 0, wIndex = 0, wLength = 0; uint8_t UnitID = 0, InterfaceNum = 0; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; switch(subtype) { case UAC_INPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; AUDIO_Handle->mem[0] = 0x00; wLength = 1; break; case UAC_FEATURE_UNIT: UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; /*holds the CS(control selector ) and CN (channel number)*/ wValue = (controlSelector << 8) | channel; wLength = length; break; case UAC_OUTPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; wLength = 1; break; } phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = UAC_GET_RES; phost->Control.setup.b.wValue.w = wValue; phost->Control.setup.b.wIndex.w = wIndex; phost->Control.setup.b.wLength.w = wLength; return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength )); } /** * @brief Handle Get Min request * @param phost: Host handle * @param subtype: subtype index * @param feature: feature index * @param controlSelector: control code * @param channel: channel index * @param length: Command length * @retval USBH Status */ static USBH_StatusTypeDef USBH_AC_GetMin(USBH_HandleTypeDef *phost, uint8_t subtype, uint8_t feature, uint8_t controlSelector, uint8_t channel, uint16_t length) { uint16_t wValue = 0, wIndex = 0, wLength = 0; uint8_t UnitID = 0, InterfaceNum = 0; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; switch(subtype) { case UAC_INPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.InputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; AUDIO_Handle->mem[0] = 0x00; wLength = 1; break; case UAC_FEATURE_UNIT: UnitID = AUDIO_Handle->class_desc.cs_desc.FeatureUnitDesc[feature]->bUnitID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; /*holds the CS(control selector ) and CN (channel number)*/ wValue = (controlSelector << 8) | channel; wLength = length; break; case UAC_OUTPUT_TERMINAL: UnitID = AUDIO_Handle->class_desc.cs_desc.OutputTerminalDesc[0]->bTerminalID; InterfaceNum = 0; /*Always zero Control Interface */ wIndex = ( UnitID << 8 ) | InterfaceNum ; wValue = (COPY_PROTECT_CONTROL << 8 ) ; wLength = 1; break; } phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = UAC_GET_MIN; phost->Control.setup.b.wValue.w = wValue; phost->Control.setup.b.wIndex.w = wIndex; phost->Control.setup.b.wLength.w = wLength; return(USBH_CtlReq(phost, (uint8_t *)(AUDIO_Handle->mem) , wLength )); } /** * @brief Handle Set Endpoint Controls Request * @param phost: Host handle * @param Ep: Endpoint address * @param buf: pointer to data * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_SetEndpointControls(USBH_HandleTypeDef *phost, uint8_t Ep, uint8_t *buff) { uint16_t wValue, wIndex, wLength; wValue = SAMPLING_FREQ_CONTROL << 8; wIndex = Ep; wLength = 3; /*length of the frequency parameter*/ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_ENDPOINT | \ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = UAC_SET_CUR; phost->Control.setup.b.wValue.w = wValue; phost->Control.setup.b.wIndex.w = wIndex; phost->Control.setup.b.wLength.w = wLength; return(USBH_CtlReq(phost, (uint8_t *)buff, wLength )); } /** * @brief Handle Input stream process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_InputStream (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY ; return status; } /** * @brief Handle HID Control process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_Control (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY ; AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; uint16_t attribute = 0; switch(AUDIO_Handle->control_state) { case AUDIO_CONTROL_INIT: if((phost->Timer & 1) == 0) { AUDIO_Handle->control.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)(AUDIO_Handle->mem), AUDIO_Handle->control.EpSize, AUDIO_Handle->control.Pipe); AUDIO_Handle->temp_feature = AUDIO_Handle->headphone.asociated_feature; AUDIO_Handle->temp_channels = AUDIO_Handle->headphone.asociated_channels; AUDIO_Handle->control_state = AUDIO_CONTROL_CHANGE ; } break; case AUDIO_CONTROL_CHANGE: if(USBH_LL_GetURBState(phost , AUDIO_Handle->control.Pipe) == USBH_URB_DONE) { attribute = LE16(&AUDIO_Handle->mem[0]); if(USBH_AUDIO_SetControlAttribute (phost, attribute) == USBH_BUSY) { break; } } if(( phost->Timer - AUDIO_Handle->control.timer) >= AUDIO_Handle->control.Poll) { AUDIO_Handle->control.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)(AUDIO_Handle->mem), AUDIO_Handle->control.EpSize, AUDIO_Handle->control.Pipe); } break; case AUDIO_CONTROL_VOLUME_UP: if( USBH_AUDIO_SetControlAttribute (phost, 1) == USBH_OK) { AUDIO_Handle->control_state = AUDIO_CONTROL_INIT; status = USBH_OK; } break; case AUDIO_CONTROL_VOLUME_DOWN: if( USBH_AUDIO_SetControlAttribute (phost, 2) == USBH_OK) { AUDIO_Handle->control_state = AUDIO_CONTROL_INIT; status = USBH_OK; } break; case AUDIO_CONTROL_IDLE: default: break; } return status; } /** * @brief Handle Output stream process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_OutputStream (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY ; AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; uint8_t *buff; switch(AUDIO_Handle->play_state) { case AUDIO_PLAYBACK_INIT: if( AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->bSamFreqType == 0) { AUDIO_Handle->play_state = AUDIO_PLAYBACK_SET_EP_FREQ; } else { AUDIO_Handle->play_state = AUDIO_PLAYBACK_SET_EP; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif break; case AUDIO_PLAYBACK_SET_EP_FREQ: buff = (uint8_t*)AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->tSamFreq[0]; status = USBH_AUDIO_SetEndpointControls(phost, AUDIO_Handle->headphone.Ep, buff); if(status == USBH_OK) { AUDIO_Handle->play_state = AUDIO_PLAYBACK_IDLE; } break; case AUDIO_PLAYBACK_SET_EP: buff = (uint8_t *)&AUDIO_Handle->headphone.frequency; status = USBH_AUDIO_SetEndpointControls(phost,AUDIO_Handle->headphone.Ep, buff); if(status == USBH_OK) { AUDIO_Handle->play_state = AUDIO_PLAYBACK_IDLE; USBH_AUDIO_FrequencySet(phost); } break; case AUDIO_PLAYBACK_IDLE: #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif status = USBH_OK; break; case AUDIO_PLAYBACK_PLAY: USBH_AUDIO_Transmit(phost); status = USBH_OK; break; default: break; } return status; } /** * @brief Handle Transmission process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_Transmit (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY ; AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; switch(AUDIO_Handle->processing_state) { case AUDIO_DATA_START_OUT: /* Sync with start of Even Frame */ if((phost->Timer & 1) == 0) { AUDIO_Handle->headphone.timer = phost->Timer; AUDIO_Handle->processing_state = AUDIO_DATA_OUT; USBH_IsocSendData(phost, AUDIO_Handle->headphone.buf, AUDIO_Handle->headphone.frame_length, AUDIO_Handle->headphone.Pipe); AUDIO_Handle->headphone.partial_ptr = AUDIO_Handle->headphone.frame_length; AUDIO_Handle->headphone.global_ptr = AUDIO_Handle->headphone.frame_length; AUDIO_Handle->headphone.cbuf = AUDIO_Handle->headphone.buf; } break; case AUDIO_DATA_OUT: if((USBH_LL_GetURBState(phost , AUDIO_Handle->headphone.Pipe) == USBH_URB_DONE)&& (( phost->Timer - AUDIO_Handle->headphone.timer) >= AUDIO_Handle->headphone.Poll)) { AUDIO_Handle->headphone.timer = phost->Timer; if(AUDIO_Handle->control.supported == 1) { USBH_AUDIO_Control (phost); } if(AUDIO_Handle->headphone.global_ptr <= AUDIO_Handle->headphone.total_length) { USBH_IsocSendData(phost, AUDIO_Handle->headphone.cbuf, AUDIO_Handle->headphone.frame_length, AUDIO_Handle->headphone.Pipe); AUDIO_Handle->headphone.cbuf += AUDIO_Handle->headphone.frame_length; AUDIO_Handle->headphone.partial_ptr += AUDIO_Handle->headphone.frame_length; AUDIO_Handle->headphone.global_ptr += AUDIO_Handle->headphone.frame_length; } else { AUDIO_Handle->headphone.partial_ptr = 0xFFFFFFFF; AUDIO_Handle->play_state = AUDIO_PLAYBACK_IDLE; } } break; } return status; } /** * @brief USBH_AUDIO_SetFrequency * Set Audio sampling parameters * @param phost: Host handle * @param SampleRate: Sample Rate * @param NbrChannels: Number of Channels * @param BitPerSample: Bit Per Sample * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_SetFrequency (USBH_HandleTypeDef *phost, uint16_t SampleRate, uint8_t NbrChannels, uint8_t BitPerSample) { USBH_StatusTypeDef Status = USBH_BUSY; AUDIO_HandleTypeDef *AUDIO_Handle; uint8_t index; uint8_t change_freq = FALSE; uint32_t freq_min, freq_max; uint8_t num_supported_freq; if(phost->gState == HOST_CLASS) { AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_IDLE) { if(AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->bSamFreqType == 0) { freq_min = LE24(AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->tSamFreq[0]); freq_max = LE24(AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->tSamFreq[1]); if(( SampleRate >= freq_min)&& (SampleRate <= freq_max)) { change_freq = TRUE; } } else { num_supported_freq = (AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->bLength - 8)/3; for(index = 0; index < num_supported_freq; index++) { if(SampleRate == LE24(AUDIO_Handle->class_desc.as_desc[AUDIO_Handle->headphone.asociated_as].FormatTypeDesc->tSamFreq[index])) { change_freq = TRUE; break; } } } if(change_freq == TRUE) { AUDIO_Handle->headphone.frequency = SampleRate; AUDIO_Handle->headphone.frame_length = (SampleRate * BitPerSample * NbrChannels) / 8000; AUDIO_Handle->play_state = AUDIO_PLAYBACK_SET_EP; Status = USBH_OK; } } } return Status; } /** * @brief USBH_AUDIO_Play * Start playback process * @param phost: Host handle * @param buf: pointer to raw audio data * @param length: total length of the audio data * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_Play (USBH_HandleTypeDef *phost, uint8_t *buf, uint32_t length) { USBH_StatusTypeDef Status = USBH_FAIL; AUDIO_HandleTypeDef *AUDIO_Handle; if(phost->gState == HOST_CLASS) { AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_IDLE) { AUDIO_Handle->headphone.buf = buf; AUDIO_Handle->headphone.total_length = length; AUDIO_Handle->play_state = AUDIO_PLAYBACK_PLAY; AUDIO_Handle->control_state = AUDIO_CONTROL_INIT; AUDIO_Handle->processing_state = AUDIO_DATA_START_OUT; Status = USBH_OK; } } return Status; } /** * @brief USBH_AUDIO_Pause * Stop the playback process * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_Stop (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef Status = USBH_FAIL; Status = USBH_AUDIO_Suspend(phost); return Status; } /** * @brief USBH_AUDIO_Suspend * Suspend the playback process * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_Suspend (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef Status = USBH_FAIL; AUDIO_HandleTypeDef *AUDIO_Handle; if(phost->gState == HOST_CLASS) { AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_PLAY) { AUDIO_Handle->control_state = AUDIO_CONTROL_IDLE; AUDIO_Handle->play_state = AUDIO_PLAYBACK_IDLE; Status = USBH_OK; } } return Status; } /** * @brief USBH_AUDIO_Resume * Resume the playback process * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_Resume (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef Status = USBH_FAIL; AUDIO_HandleTypeDef *AUDIO_Handle; if(phost->gState == HOST_CLASS) { AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_IDLE) { AUDIO_Handle->control_state = AUDIO_CONTROL_INIT; AUDIO_Handle->play_state = AUDIO_PLAYBACK_PLAY; } } return Status; } /** * @brief USBH_AUDIO_GetOutOffset * return the current buffer pointer for OUT proces * @param phost: Host handle * @retval USBH Status */ int32_t USBH_AUDIO_GetOutOffset (USBH_HandleTypeDef *phost) { AUDIO_HandleTypeDef *AUDIO_Handle; if(phost->gState == HOST_CLASS) { AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_PLAY) { return AUDIO_Handle->headphone.partial_ptr; } } return -1; } /** * @brief USBH_AUDIO_ChangeOutBuffer * Change audio data buffer address * @param phost: Host handle * @param buf: buffer address * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_ChangeOutBuffer (USBH_HandleTypeDef *phost, uint8_t *buf) { USBH_StatusTypeDef Status = USBH_FAIL; AUDIO_HandleTypeDef *AUDIO_Handle; if(phost->gState == HOST_CLASS) { AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_PLAY) { if(AUDIO_Handle->headphone.buf <= buf) { AUDIO_Handle->headphone.cbuf = buf; if ( AUDIO_Handle->headphone.buf == buf) { AUDIO_Handle->headphone.partial_ptr = 0; } Status = USBH_OK; } } } return Status; } /** * @brief USBH_AUDIO_SetControlAttribute * Set Control Attribute * @param phost: Host handle * @param attrib: control attribute * @retval USBH Status */ static USBH_StatusTypeDef USBH_AUDIO_SetControlAttribute (USBH_HandleTypeDef *phost, uint8_t attrib) { USBH_StatusTypeDef status = USBH_BUSY ; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; switch (attrib) { case 0x01: AUDIO_Handle->headphone.attribute.volume += AUDIO_Handle->headphone.attribute.resolution; break; case 0x02: AUDIO_Handle->headphone.attribute.volume -= AUDIO_Handle->headphone.attribute.resolution; break; } if(AUDIO_Handle->headphone.attribute.volume > AUDIO_Handle->headphone.attribute.volumeMax) { AUDIO_Handle->headphone.attribute.volume =AUDIO_Handle->headphone.attribute.volumeMax; } if(AUDIO_Handle->headphone.attribute.volume < AUDIO_Handle->headphone.attribute.volumeMin) { AUDIO_Handle->headphone.attribute.volume =AUDIO_Handle->headphone.attribute.volumeMin; } if(AUDIO_SetVolume (phost, AUDIO_Handle->temp_feature, AUDIO_Handle->temp_channels, AUDIO_Handle->headphone.attribute.volume) != USBH_BUSY) { if(AUDIO_Handle->temp_channels == 1) { AUDIO_Handle->temp_feature = AUDIO_Handle->headphone.asociated_feature; AUDIO_Handle->temp_channels = AUDIO_Handle->headphone.asociated_channels; status = USBH_OK; } else { AUDIO_Handle->temp_channels--; } AUDIO_Handle->cs_req_state = AUDIO_REQ_GET_VOLUME; } return status; } /** * @brief USBH_AUDIO_SetVolume * Set Volume * @param phost: Host handle * @param volume: VOLUME_UP/ VOLUME_DOWN * @retval USBH Status */ USBH_StatusTypeDef USBH_AUDIO_SetVolume (USBH_HandleTypeDef *phost, AUDIO_VolumeCtrlTypeDef volume_ctl) { AUDIO_HandleTypeDef *AUDIO_Handle = phost->pActiveClass->pData; if((volume_ctl == VOLUME_UP) || (volume_ctl == VOLUME_DOWN)) { if(phost->gState == HOST_CLASS) { AUDIO_Handle = phost->pActiveClass->pData; if(AUDIO_Handle->play_state == AUDIO_PLAYBACK_PLAY) { AUDIO_Handle->control_state = (volume_ctl == VOLUME_UP)? AUDIO_CONTROL_VOLUME_UP : AUDIO_CONTROL_VOLUME_DOWN; return USBH_OK; } } } return USBH_FAIL; } /** * @brief AUDIO_SetVolume * Set Volume * @param phost: Host handle * @param feature: feature Unit index * @param channel: channel index * @param volume: new volume * @retval USBH Status */ static USBH_StatusTypeDef AUDIO_SetVolume (USBH_HandleTypeDef *phost, uint8_t feature, uint8_t channel, uint16_t volume) { USBH_StatusTypeDef status = USBH_BUSY ; AUDIO_HandleTypeDef *AUDIO_Handle; AUDIO_Handle = phost->pActiveClass->pData; AUDIO_Handle->mem[0] = volume; status = USBH_AC_SetCur(phost, UAC_FEATURE_UNIT, feature, VOLUME_CONTROL, channel, 2); return status; } /** * @brief The function informs user that Settings have been changed * @param pdev: Selected device * @retval None */ __weak void USBH_AUDIO_FrequencySet(USBH_HandleTypeDef *phost) { } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/CDC/000077500000000000000000000000001357706137100212665ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/CDC/Inc/000077500000000000000000000000001357706137100217775ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/CDC/Inc/usbh_cdc.h000066400000000000000000000445521357706137100237340ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_cdc.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contains all the prototypes for the usbh_cdc.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_CDC_CORE_H #define __USBH_CDC_CORE_H /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_CDC_CLASS * @{ */ /** @defgroup USBH_CDC_CORE * @brief This file is the Header file for USBH_CDC_CORE.c * @{ */ /*Communication Class codes*/ #define USB_CDC_CLASS 0x02 #define COMMUNICATION_INTERFACE_CLASS_CODE 0x02 /*Data Interface Class Codes*/ #define DATA_INTERFACE_CLASS_CODE 0x0A /*Communcation sub class codes*/ #define RESERVED 0x00 #define DIRECT_LINE_CONTROL_MODEL 0x01 #define ABSTRACT_CONTROL_MODEL 0x02 #define TELEPHONE_CONTROL_MODEL 0x03 #define MULTICHANNEL_CONTROL_MODEL 0x04 #define CAPI_CONTROL_MODEL 0x05 #define ETHERNET_NETWORKING_CONTROL_MODEL 0x06 #define ATM_NETWORKING_CONTROL_MODEL 0x07 /*Communication Interface Class Control Protocol Codes*/ #define NO_CLASS_SPECIFIC_PROTOCOL_CODE 0x00 #define COMMON_AT_COMMAND 0x01 #define VENDOR_SPECIFIC 0xFF #define CS_INTERFACE 0x24 #define CDC_PAGE_SIZE_64 0x40 /*Class-Specific Request Codes*/ #define CDC_SEND_ENCAPSULATED_COMMAND 0x00 #define CDC_GET_ENCAPSULATED_RESPONSE 0x01 #define CDC_SET_COMM_FEATURE 0x02 #define CDC_GET_COMM_FEATURE 0x03 #define CDC_CLEAR_COMM_FEATURE 0x04 #define CDC_SET_AUX_LINE_STATE 0x10 #define CDC_SET_HOOK_STATE 0x11 #define CDC_PULSE_SETUP 0x12 #define CDC_SEND_PULSE 0x13 #define CDC_SET_PULSE_TIME 0x14 #define CDC_RING_AUX_JACK 0x15 #define CDC_SET_LINE_CODING 0x20 #define CDC_GET_LINE_CODING 0x21 #define CDC_SET_CONTROL_LINE_STATE 0x22 #define CDC_SEND_BREAK 0x23 #define CDC_SET_RINGER_PARMS 0x30 #define CDC_GET_RINGER_PARMS 0x31 #define CDC_SET_OPERATION_PARMS 0x32 #define CDC_GET_OPERATION_PARMS 0x33 #define CDC_SET_LINE_PARMS 0x34 #define CDC_GET_LINE_PARMS 0x35 #define CDC_DIAL_DIGITS 0x36 #define CDC_SET_UNIT_PARAMETER 0x37 #define CDC_GET_UNIT_PARAMETER 0x38 #define CDC_CLEAR_UNIT_PARAMETER 0x39 #define CDC_GET_PROFILE 0x3A #define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 #define CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41 #define CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42 #define CDC_SET_ETHERNET_PACKET_FILTER 0x43 #define CDC_GET_ETHERNET_STATISTIC 0x44 #define CDC_SET_ATM_DATA_FORMAT 0x50 #define CDC_GET_ATM_DEVICE_STATISTICS 0x51 #define CDC_SET_ATM_DEFAULT_VC 0x52 #define CDC_GET_ATM_VC_STATISTICS 0x53 /* wValue for SetControlLineState*/ #define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002 #define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000 #define CDC_ACTIVATE_SIGNAL_DTR 0x0001 #define CDC_DEACTIVATE_SIGNAL_DTR 0x0000 #define LINE_CODING_STRUCTURE_SIZE 0x07 /** * @} */ /** @defgroup USBH_CDC_CORE_Exported_Types * @{ */ /* States for CDC State Machine */ typedef enum { CDC_IDLE= 0, CDC_SEND_DATA, CDC_SEND_DATA_WAIT, CDC_RECEIVE_DATA, CDC_RECEIVE_DATA_WAIT, } CDC_DataStateTypeDef; typedef enum { CDC_IDLE_STATE= 0, CDC_SET_LINE_CODING_STATE, CDC_GET_LAST_LINE_CODING_STATE, CDC_TRANSFER_DATA, CDC_ERROR_STATE, } CDC_StateTypeDef; /*Line coding structure*/ typedef union _CDC_LineCodingStructure { uint8_t Array[LINE_CODING_STRUCTURE_SIZE]; struct { uint32_t dwDTERate; /*Data terminal rate, in bits per second*/ uint8_t bCharFormat; /*Stop bits 0 - 1 Stop bit 1 - 1.5 Stop bits 2 - 2 Stop bits*/ uint8_t bParityType; /* Parity 0 - None 1 - Odd 2 - Even 3 - Mark 4 - Space*/ uint8_t bDataBits; /* Data bits (5, 6, 7, 8 or 16). */ }b; } CDC_LineCodingTypeDef; /* Header Functional Descriptor -------------------------------------------------------------------------------- Offset| field | Size | Value | Description ------|---------------------|-------|------------|------------------------------ 0 | bFunctionLength | 1 | number | Size of this descriptor. 1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24) 2 | bDescriptorSubtype | 1 | Constant | Identifier (ID) of functional | | | | descriptor. 3 | bcdCDC | 2 | | | | | Number | USB Class Definitions for | | | | Communication Devices Specification | | | | release number in binary-coded | | | | decimal ------|---------------------|-------|------------|------------------------------ */ typedef struct _FunctionalDescriptorHeader { uint8_t bLength; /*Size of this descriptor.*/ uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/ uint8_t bDescriptorSubType; /* Header functional descriptor subtype as*/ uint16_t bcdCDC; /* USB Class Definitions for Communication Devices Specification release number in binary-coded decimal. */ } CDC_HeaderFuncDesc_TypeDef; /* Call Management Functional Descriptor -------------------------------------------------------------------------------- Offset| field | Size | Value | Description ------|---------------------|-------|------------|------------------------------ 0 | bFunctionLength | 1 | number | Size of this descriptor. 1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24) 2 | bDescriptorSubtype | 1 | Constant | Call Management functional | | | | descriptor subtype. 3 | bmCapabilities | 1 | Bitmap | The capabilities that this configuration | | | | supports: | | | | D7..D2: RESERVED (Reset to zero) | | | | D1: 0 - Device sends/receives call | | | | management information only over | | | | the Communication Class | | | | interface. | | | | 1 - Device can send/receive call | \ | | management information over a | | | | Data Class interface. | | | | D0: 0 - Device does not handle call | | | | management itself. | | | | 1 - Device handles call | | | | management itself. | | | | The previous bits, in combination, identify | | | | which call management scenario is used. If bit | | | | D0 is reset to 0, then the value of bit D1 is | | | | ignored. In this case, bit D1 is reset to zero for | | | | future compatibility. 4 | bDataInterface | 1 | Number | Interface number of Data Class interface | | | | optionally used for call management. ------|---------------------|-------|------------|------------------------------ */ typedef struct _CallMgmtFunctionalDescriptor { uint8_t bLength; /*Size of this functional descriptor, in bytes.*/ uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/ uint8_t bDescriptorSubType; /* Call Management functional descriptor subtype*/ uint8_t bmCapabilities; /* bmCapabilities: D0+D1 */ uint8_t bDataInterface; /*bDataInterface: 1*/ } CDC_CallMgmtFuncDesc_TypeDef; /* Abstract Control Management Functional Descriptor -------------------------------------------------------------------------------- Offset| field | Size | Value | Description ------|---------------------|-------|------------|------------------------------ 0 | bFunctionLength | 1 | number | Size of functional descriptor, in bytes. 1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24) 2 | bDescriptorSubtype | 1 | Constant | Abstract Control Management | | | | functional descriptor subtype. 3 | bmCapabilities | 1 | Bitmap | The capabilities that this configuration | | | | supports ((A bit value of zero means that the | | | | request is not supported.) ) D7..D4: RESERVED (Reset to zero) | | | | D3: 1 - Device supports the notification | | | | Network_Connection. | | | | D2: 1 - Device supports the request | | | | Send_Break | | | | D1: 1 - Device supports the request | \ | | combination of Set_Line_Coding, | | | | Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. | | | | D0: 1 - Device supports the request | | | | combination of Set_Comm_Feature, | | | | Clear_Comm_Feature, and Get_Comm_Feature. | | | | The previous bits, in combination, identify | | | | which requests/notifications are supported by | | | | a Communication Class interface with the | | | | SubClass code of Abstract Control Model. ------|---------------------|-------|------------|------------------------------ */ typedef struct _AbstractCntrlMgmtFunctionalDescriptor { uint8_t bLength; /*Size of this functional descriptor, in bytes.*/ uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/ uint8_t bDescriptorSubType; /* Abstract Control Management functional descriptor subtype*/ uint8_t bmCapabilities; /* The capabilities that this configuration supports */ } CDC_AbstCntrlMgmtFuncDesc_TypeDef; /* Union Functional Descriptor -------------------------------------------------------------------------------- Offset| field | Size | Value | Description ------|---------------------|-------|------------|------------------------------ 0 | bFunctionLength | 1 | number | Size of this descriptor. 1 | bDescriptorType | 1 | Constant | CS_INTERFACE (0x24) 2 | bDescriptorSubtype | 1 | Constant | Union functional | | | | descriptor subtype. 3 | bMasterInterface | 1 | Constant | The interface number of the | | | | Communication or Data Class interface 4 | bSlaveInterface0 | 1 | Number | nterface number of first slave or associated | | | | interface in the union. ------|---------------------|-------|------------|------------------------------ */ typedef struct _UnionFunctionalDescriptor { uint8_t bLength; /*Size of this functional descriptor, in bytes*/ uint8_t bDescriptorType; /*CS_INTERFACE (0x24)*/ uint8_t bDescriptorSubType; /* Union functional descriptor SubType*/ uint8_t bMasterInterface; /* The interface number of the Communication or Data Class interface,*/ uint8_t bSlaveInterface0; /*Interface number of first slave*/ } CDC_UnionFuncDesc_TypeDef; typedef struct _USBH_CDCInterfaceDesc { CDC_HeaderFuncDesc_TypeDef CDC_HeaderFuncDesc; CDC_CallMgmtFuncDesc_TypeDef CDC_CallMgmtFuncDesc; CDC_AbstCntrlMgmtFuncDesc_TypeDef CDC_AbstCntrlMgmtFuncDesc; CDC_UnionFuncDesc_TypeDef CDC_UnionFuncDesc; } CDC_InterfaceDesc_Typedef; /* Structure for CDC process */ typedef struct { uint8_t NotifPipe; uint8_t NotifEp; uint8_t buff[8]; uint16_t NotifEpSize; } CDC_CommItfTypedef ; typedef struct { uint8_t InPipe; uint8_t OutPipe; uint8_t OutEp; uint8_t InEp; uint8_t buff[8]; uint16_t OutEpSize; uint16_t InEpSize; } CDC_DataItfTypedef ; /* Structure for CDC process */ typedef struct _CDC_Process { CDC_CommItfTypedef CommItf; CDC_DataItfTypedef DataItf; uint8_t *pTxData; uint8_t *pRxData; uint32_t TxDataLength; uint32_t RxDataLength; CDC_InterfaceDesc_Typedef CDC_Desc; CDC_LineCodingTypeDef LineCoding; CDC_LineCodingTypeDef *pUserLineCoding; CDC_StateTypeDef state; CDC_DataStateTypeDef data_tx_state; CDC_DataStateTypeDef data_rx_state; uint8_t Rx_Poll; } CDC_HandleTypeDef; /** * @} */ /** @defgroup USBH_CDC_CORE_Exported_Defines * @{ */ /** * @} */ /** @defgroup USBH_CDC_CORE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_CDC_CORE_Exported_Variables * @{ */ extern USBH_ClassTypeDef CDC_Class; #define USBH_CDC_CLASS &CDC_Class /** * @} */ /** @defgroup USBH_CDC_CORE_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding); USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding); USBH_StatusTypeDef USBH_CDC_Transmit(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length); USBH_StatusTypeDef USBH_CDC_Receive(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length); uint16_t USBH_CDC_GetLastReceivedDataSize(USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_CDC_Stop(USBH_HandleTypeDef *phost); void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost); void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost); void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost); /** * @} */ #endif /* __USBH_CDC_CORE_H */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/CDC/Src/000077500000000000000000000000001357706137100220155ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/CDC/Src/usbh_cdc.c000066400000000000000000000526561357706137100237510ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_cdc.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the CDC Layer Handlers for USB Host CDC class. * * @verbatim * * =================================================================== * CDC Class Description * =================================================================== * This module manages the MSC class V1.11 following the "Device Class Definition * for Human Interface Devices (CDC) Version 1.11 Jun 27, 2001". * This driver implements the following aspects of the specification: * - The Boot Interface Subclass * - The Mouse and Keyboard protocols * * @endverbatim * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_cdc.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_CDC_CLASS * @{ */ /** @defgroup USBH_CDC_CORE * @brief This file includes CDC Layer Handlers for USB Host CDC class. * @{ */ /** @defgroup USBH_CDC_CORE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_CDC_CORE_Private_Defines * @{ */ #define USBH_CDC_BUFFER_SIZE 1024 /** * @} */ /** @defgroup USBH_CDC_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_CDC_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_CDC_CORE_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_CDC_Process(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_CDC_SOFProcess(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding); static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding); static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost); static void CDC_ProcessReception(USBH_HandleTypeDef *phost); USBH_ClassTypeDef CDC_Class = { "CDC", USB_CDC_CLASS, USBH_CDC_InterfaceInit, USBH_CDC_InterfaceDeInit, USBH_CDC_ClassRequest, USBH_CDC_Process, USBH_CDC_SOFProcess, NULL, }; /** * @} */ /** @defgroup USBH_CDC_CORE_Private_Functions * @{ */ /** * @brief USBH_CDC_InterfaceInit * The function init the CDC class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_CDC_InterfaceInit (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_FAIL ; uint8_t interface; CDC_HandleTypeDef *CDC_Handle; interface = USBH_FindInterface(phost, COMMUNICATION_INTERFACE_CLASS_CODE, ABSTRACT_CONTROL_MODEL, COMMON_AT_COMMAND); if(interface == 0xFF) /* No Valid Interface */ { USBH_DbgLog ("Cannot Find the interface for Communication Interface Class.", phost->pActiveClass->Name); } else { USBH_SelectInterface (phost, interface); phost->pActiveClass->pData = (CDC_HandleTypeDef *)USBH_malloc (sizeof(CDC_HandleTypeDef)); CDC_Handle = phost->pActiveClass->pData; /*Collect the notification endpoint address and length*/ if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) { CDC_Handle->CommItf.NotifEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; CDC_Handle->CommItf.NotifEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; } /*Allocate the length for host channel number in*/ CDC_Handle->CommItf.NotifPipe = USBH_AllocPipe(phost, CDC_Handle->CommItf.NotifEp); /* Open pipe for Notification endpoint */ USBH_OpenPipe (phost, CDC_Handle->CommItf.NotifPipe, CDC_Handle->CommItf.NotifEp, phost->device.address, phost->device.speed, USB_EP_TYPE_INTR, CDC_Handle->CommItf.NotifEpSize); USBH_LL_SetToggle (phost, CDC_Handle->CommItf.NotifPipe, 0); interface = USBH_FindInterface(phost, DATA_INTERFACE_CLASS_CODE, RESERVED, NO_CLASS_SPECIFIC_PROTOCOL_CODE); if(interface == 0xFF) /* No Valid Interface */ { USBH_DbgLog ("Cannot Find the interface for Data Interface Class.", phost->pActiveClass->Name); } else { /*Collect the class specific endpoint address and length*/ if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress & 0x80) { CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; } else { CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress; CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize; } if(phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress & 0x80) { CDC_Handle->DataItf.InEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress; CDC_Handle->DataItf.InEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; } else { CDC_Handle->DataItf.OutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].bEndpointAddress; CDC_Handle->DataItf.OutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[1].wMaxPacketSize; } /*Allocate the length for host channel number out*/ CDC_Handle->DataItf.OutPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.OutEp); /*Allocate the length for host channel number in*/ CDC_Handle->DataItf.InPipe = USBH_AllocPipe(phost, CDC_Handle->DataItf.InEp); /* Open channel for OUT endpoint */ USBH_OpenPipe (phost, CDC_Handle->DataItf.OutPipe, CDC_Handle->DataItf.OutEp, phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, CDC_Handle->DataItf.OutEpSize); /* Open channel for IN endpoint */ USBH_OpenPipe (phost, CDC_Handle->DataItf.InPipe, CDC_Handle->DataItf.InEp, phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, CDC_Handle->DataItf.InEpSize); CDC_Handle->state = CDC_IDLE_STATE; USBH_LL_SetToggle (phost, CDC_Handle->DataItf.OutPipe,0); USBH_LL_SetToggle (phost, CDC_Handle->DataItf.InPipe,0); status = USBH_OK; } } return status; } /** * @brief USBH_CDC_InterfaceDeInit * The function DeInit the Pipes used for the CDC class. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_CDC_InterfaceDeInit (USBH_HandleTypeDef *phost) { CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; if ( CDC_Handle->CommItf.NotifPipe) { USBH_ClosePipe(phost, CDC_Handle->CommItf.NotifPipe); USBH_FreePipe (phost, CDC_Handle->CommItf.NotifPipe); CDC_Handle->CommItf.NotifPipe = 0; /* Reset the Channel as Free */ } if ( CDC_Handle->DataItf.InPipe) { USBH_ClosePipe(phost, CDC_Handle->DataItf.InPipe); USBH_FreePipe (phost, CDC_Handle->DataItf.InPipe); CDC_Handle->DataItf.InPipe = 0; /* Reset the Channel as Free */ } if ( CDC_Handle->DataItf.OutPipe) { USBH_ClosePipe(phost, CDC_Handle->DataItf.OutPipe); USBH_FreePipe (phost, CDC_Handle->DataItf.OutPipe); CDC_Handle->DataItf.OutPipe = 0; /* Reset the Channel as Free */ } if(phost->pActiveClass->pData) { USBH_free (phost->pActiveClass->pData); phost->pActiveClass->pData = 0; } return USBH_OK; } /** * @brief USBH_CDC_ClassRequest * The function is responsible for handling Standard requests * for CDC class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_CDC_ClassRequest (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_FAIL ; CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; /*Issue the get line coding request*/ status = GetLineCoding(phost, &CDC_Handle->LineCoding); if(status == USBH_OK) { phost->pUser(phost, HOST_USER_CLASS_ACTIVE); } return status; } /** * @brief USBH_CDC_Process * The function is for managing state machine for CDC data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_CDC_Process (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef req_status = USBH_OK; CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; switch(CDC_Handle->state) { case CDC_IDLE_STATE: status = USBH_OK; break; case CDC_SET_LINE_CODING_STATE: req_status = SetLineCoding(phost, CDC_Handle->pUserLineCoding); if(req_status == USBH_OK) { CDC_Handle->state = CDC_GET_LAST_LINE_CODING_STATE; } else if(req_status != USBH_BUSY) { CDC_Handle->state = CDC_ERROR_STATE; } break; case CDC_GET_LAST_LINE_CODING_STATE: req_status = GetLineCoding(phost, &(CDC_Handle->LineCoding)); if(req_status == USBH_OK) { CDC_Handle->state = CDC_IDLE_STATE; if((CDC_Handle->LineCoding.b.bCharFormat == CDC_Handle->pUserLineCoding->b.bCharFormat) && (CDC_Handle->LineCoding.b.bDataBits == CDC_Handle->pUserLineCoding->b.bDataBits) && (CDC_Handle->LineCoding.b.bParityType == CDC_Handle->pUserLineCoding->b.bParityType) && (CDC_Handle->LineCoding.b.dwDTERate == CDC_Handle->pUserLineCoding->b.dwDTERate)) { USBH_CDC_LineCodingChanged(phost); } } else if(req_status != USBH_BUSY) { CDC_Handle->state = CDC_ERROR_STATE; } break; case CDC_TRANSFER_DATA: CDC_ProcessTransmission(phost); CDC_ProcessReception(phost); break; case CDC_ERROR_STATE: req_status = USBH_ClrFeature(phost, 0x00); if(req_status == USBH_OK ) { /*Change the state to waiting*/ CDC_Handle->state = CDC_IDLE_STATE ; } break; default: break; } return status; } /** * @brief USBH_CDC_SOFProcess * The function is for managing SOF callback * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_CDC_SOFProcess (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_CDC_Stop * Stop current CDC Transmission * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_CDC_Stop(USBH_HandleTypeDef *phost) { CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; if(phost->gState == HOST_CLASS) { CDC_Handle->state = CDC_IDLE_STATE; USBH_ClosePipe(phost, CDC_Handle->CommItf.NotifPipe); USBH_ClosePipe(phost, CDC_Handle->DataItf.InPipe); USBH_ClosePipe(phost, CDC_Handle->DataItf.OutPipe); } return USBH_OK; } /** * @brief This request allows the host to find out the currently * configured line coding. * @param pdev: Selected device * @retval USBH_StatusTypeDef : USB ctl xfer status */ static USBH_StatusTypeDef GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecoding) { phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \ USB_REQ_RECIPIENT_INTERFACE; phost->Control.setup.b.bRequest = CDC_GET_LINE_CODING; phost->Control.setup.b.wValue.w = 0; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = LINE_CODING_STRUCTURE_SIZE; return USBH_CtlReq(phost, linecoding->Array, LINE_CODING_STRUCTURE_SIZE); } /** * @brief This request allows the host to specify typical asynchronous * line-character formatting properties * This request applies to asynchronous byte stream data class interfaces * and endpoints * @param pdev: Selected device * @retval USBH_StatusTypeDef : USB ctl xfer status */ static USBH_StatusTypeDef SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \ USB_REQ_RECIPIENT_INTERFACE; phost->Control.setup.b.bRequest = CDC_SET_LINE_CODING; phost->Control.setup.b.wValue.w = 0; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = LINE_CODING_STRUCTURE_SIZE; return USBH_CtlReq(phost, linecodin->Array , LINE_CODING_STRUCTURE_SIZE ); } /** * @brief This function prepares the state before issuing the class specific commands * @param None * @retval None */ USBH_StatusTypeDef USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin) { CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; if(phost->gState == HOST_CLASS) { CDC_Handle->state = CDC_SET_LINE_CODING_STATE; CDC_Handle->pUserLineCoding = linecodin; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif } return USBH_OK; } /** * @brief This function prepares the state before issuing the class specific commands * @param None * @retval None */ USBH_StatusTypeDef USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost, CDC_LineCodingTypeDef *linecodin) { CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; if((phost->gState == HOST_CLASS) ||(phost->gState == HOST_CLASS_REQUEST)) { *linecodin = CDC_Handle->LineCoding; return USBH_OK; } else { return USBH_FAIL; } } /** * @brief This function return last recieved data size * @param None * @retval None */ uint16_t USBH_CDC_GetLastReceivedDataSize(USBH_HandleTypeDef *phost) { CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; if(phost->gState == HOST_CLASS) { return USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe);; } else { return 0; } } /** * @brief This function prepares the state before issuing the class specific commands * @param None * @retval None */ USBH_StatusTypeDef USBH_CDC_Transmit(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length) { USBH_StatusTypeDef Status = USBH_BUSY; CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; if((CDC_Handle->state == CDC_IDLE_STATE) || (CDC_Handle->state == CDC_TRANSFER_DATA)) { CDC_Handle->pTxData = pbuff; CDC_Handle->TxDataLength = length; CDC_Handle->state = CDC_TRANSFER_DATA; CDC_Handle->data_tx_state = CDC_SEND_DATA; Status = USBH_OK; } return Status; } /** * @brief This function prepares the state before issuing the class specific commands * @param None * @retval None */ USBH_StatusTypeDef USBH_CDC_Receive(USBH_HandleTypeDef *phost, uint8_t *pbuff, uint32_t length) { USBH_StatusTypeDef Status = USBH_BUSY; CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; if((CDC_Handle->state == CDC_IDLE_STATE) || (CDC_Handle->state == CDC_TRANSFER_DATA)) { CDC_Handle->pRxData = pbuff; CDC_Handle->RxDataLength = length; CDC_Handle->state = CDC_TRANSFER_DATA; CDC_Handle->data_rx_state = CDC_RECEIVE_DATA; Status = USBH_OK; } return Status; } /** * @brief The function is responsible for sending data to the device * @param pdev: Selected device * @retval None */ static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost) { CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; switch(CDC_Handle->data_tx_state) { case CDC_SEND_DATA: if(CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize) { USBH_BulkSendData (phost, CDC_Handle->pTxData, CDC_Handle->DataItf.OutEpSize, CDC_Handle->DataItf.OutPipe, 1); } else { USBH_BulkSendData (phost, CDC_Handle->pTxData, CDC_Handle->TxDataLength, CDC_Handle->DataItf.OutPipe, 1); } CDC_Handle->data_tx_state = CDC_SEND_DATA_WAIT; break; case CDC_SEND_DATA_WAIT: URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.OutPipe); /*Check the status done for transmssion*/ if(URB_Status == USBH_URB_DONE ) { if(CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize) { CDC_Handle->TxDataLength -= CDC_Handle->DataItf.OutEpSize ; CDC_Handle->pTxData += CDC_Handle->DataItf.OutEpSize; } else { CDC_Handle->TxDataLength = 0; } if( CDC_Handle->TxDataLength > 0) { CDC_Handle->data_tx_state = CDC_SEND_DATA; } else { CDC_Handle->data_tx_state = CDC_IDLE; USBH_CDC_TransmitCallback(phost); } } else if( URB_Status == USBH_URB_NOTREADY ) { CDC_Handle->data_tx_state = CDC_SEND_DATA; } break; default: break; } } /** * @brief This function responsible for reception of data from the device * @param pdev: Selected device * @retval None */ static void CDC_ProcessReception(USBH_HandleTypeDef *phost) { CDC_HandleTypeDef *CDC_Handle = phost->pActiveClass->pData; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; uint16_t length; switch(CDC_Handle->data_rx_state) { case CDC_RECEIVE_DATA: USBH_BulkReceiveData (phost, CDC_Handle->pRxData, CDC_Handle->DataItf.InEpSize, CDC_Handle->DataItf.InPipe); CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT; break; case CDC_RECEIVE_DATA_WAIT: URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe); /*Check the status done for reception*/ if(URB_Status == USBH_URB_DONE ) { length = USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe); if(((CDC_Handle->RxDataLength - length) > 0) && (length > CDC_Handle->DataItf.InEpSize)) { CDC_Handle->RxDataLength -= length ; CDC_Handle->pRxData += length; CDC_Handle->data_rx_state = CDC_RECEIVE_DATA; } else { CDC_Handle->data_rx_state = CDC_IDLE; USBH_CDC_ReceiveCallback(phost); } } break; default: break; } } /** * @brief The function informs user that data have been received * @param pdev: Selected device * @retval None */ __weak void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost) { } /** * @brief The function informs user that data have been sent * @param pdev: Selected device * @retval None */ __weak void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost) { } /** * @brief The function informs user that Settings have been changed * @param pdev: Selected device * @retval None */ __weak void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost) { } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/000077500000000000000000000000001357706137100213015ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/HID/Inc/000077500000000000000000000000001357706137100220125ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/HID/Inc/usbh_hid.h000066400000000000000000000247511357706137100237610ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contains all the prototypes for the usbh_hid.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_HID_H #define __USBH_HID_H /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" #include "usbh_hid_mouse.h" #include "usbh_hid_keybd.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_CORE * @brief This file is the Header file for USBH_HID_CORE.c * @{ */ /** @defgroup USBH_HID_CORE_Exported_Types * @{ */ #define HID_MIN_POLL 10 #define HID_REPORT_SIZE 16 #define HID_MAX_USAGE 10 #define HID_MAX_NBR_REPORT_FMT 10 #define HID_QUEUE_SIZE 10 #define HID_ITEM_LONG 0xFE #define HID_ITEM_TYPE_MAIN 0x00 #define HID_ITEM_TYPE_GLOBAL 0x01 #define HID_ITEM_TYPE_LOCAL 0x02 #define HID_ITEM_TYPE_RESERVED 0x03 #define HID_MAIN_ITEM_TAG_INPUT 0x08 #define HID_MAIN_ITEM_TAG_OUTPUT 0x09 #define HID_MAIN_ITEM_TAG_COLLECTION 0x0A #define HID_MAIN_ITEM_TAG_FEATURE 0x0B #define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0C #define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00 #define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01 #define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02 #define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03 #define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04 #define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05 #define HID_GLOBAL_ITEM_TAG_UNIT 0x06 #define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07 #define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08 #define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09 #define HID_GLOBAL_ITEM_TAG_PUSH 0x0A #define HID_GLOBAL_ITEM_TAG_POP 0x0B #define HID_LOCAL_ITEM_TAG_USAGE 0x00 #define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01 #define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05 #define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07 #define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08 #define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09 #define HID_LOCAL_ITEM_TAG_DELIMITER 0x0A /* States for HID State Machine */ typedef enum { HID_INIT= 0, HID_IDLE, HID_SEND_DATA, HID_BUSY, HID_GET_DATA, HID_SYNC, HID_POLL, HID_ERROR, } HID_StateTypeDef; typedef enum { HID_REQ_INIT = 0, HID_REQ_IDLE, HID_REQ_GET_REPORT_DESC, HID_REQ_GET_HID_DESC, HID_REQ_SET_IDLE, HID_REQ_SET_PROTOCOL, HID_REQ_SET_REPORT, } HID_CtlStateTypeDef; typedef enum { HID_MOUSE = 0x01, HID_KEYBOARD = 0x02, HID_UNKNOWN = 0xFF, } HID_TypeTypeDef; typedef struct _HID_ReportData { uint8_t ReportID; uint8_t ReportType; uint16_t UsagePage; uint32_t Usage[HID_MAX_USAGE]; uint32_t NbrUsage; uint32_t UsageMin; uint32_t UsageMax; int32_t LogMin; int32_t LogMax; int32_t PhyMin; int32_t PhyMax; int32_t UnitExp; uint32_t Unit; uint32_t ReportSize; uint32_t ReportCnt; uint32_t Flag; uint32_t PhyUsage; uint32_t AppUsage; uint32_t LogUsage; } HID_ReportDataTypeDef; typedef struct _HID_ReportIDTypeDef { uint8_t Size; /* Report size return by the device id */ uint8_t ReportID; /* Report Id */ uint8_t Type; /* Report Type (INPUT/OUTPUT/FEATURE) */ } HID_ReportIDTypeDef; typedef struct _HID_CollectionTypeDef { uint32_t Usage; uint8_t Type; struct _HID_CollectionTypeDef *NextPtr; } HID_CollectionTypeDef; typedef struct _HID_AppCollectionTypeDef { uint32_t Usage; uint8_t Type; uint8_t NbrReportFmt; HID_ReportDataTypeDef ReportData[HID_MAX_NBR_REPORT_FMT]; } HID_AppCollectionTypeDef; typedef struct _HIDDescriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdHID; /* indicates what endpoint this descriptor is describing */ uint8_t bCountryCode; /* specifies the transfer type. */ uint8_t bNumDescriptors; /* specifies the transfer type. */ uint8_t bReportDescriptorType; /* Maximum Packet Size this endpoint is capable of sending or receiving */ uint16_t wItemLength; /* is used to specify the polling interval of certain transfers. */ } HID_DescTypeDef; typedef struct { uint8_t *buf; uint16_t head; uint16_t tail; uint16_t size; uint8_t lock; } FIFO_TypeDef; /* Structure for HID process */ typedef struct _HID_Process { uint8_t OutPipe; uint8_t InPipe; HID_StateTypeDef state; uint8_t OutEp; uint8_t InEp; HID_CtlStateTypeDef ctl_state; FIFO_TypeDef fifo; uint8_t *pData; uint16_t length; uint8_t ep_addr; uint16_t poll; uint16_t timer; uint8_t DataReady; HID_DescTypeDef HID_Desc; USBH_StatusTypeDef ( * Init)(USBH_HandleTypeDef *phost); } HID_HandleTypeDef; /** * @} */ /** @defgroup USBH_HID_CORE_Exported_Defines * @{ */ #define USB_HID_GET_REPORT 0x01 #define USB_HID_GET_IDLE 0x02 #define USB_HID_GET_PROTOCOL 0x03 #define USB_HID_SET_REPORT 0x09 #define USB_HID_SET_IDLE 0x0A #define USB_HID_SET_PROTOCOL 0x0B /* HID Class Codes */ #define USB_HID_CLASS 0x03 /* Interface Descriptor field values for HID Boot Protocol */ #define HID_BOOT_CODE 0x01 #define HID_KEYBRD_BOOT_CODE 0x01 #define HID_MOUSE_BOOT_CODE 0x02 /** * @} */ /** @defgroup USBH_HID_CORE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_HID_CORE_Exported_Variables * @{ */ extern USBH_ClassTypeDef HID_Class; #define USBH_HID_CLASS &HID_Class /** * @} */ /** @defgroup USBH_HID_CORE_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost, uint8_t reportType, uint8_t reportId, uint8_t* reportBuff, uint8_t reportLen); USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost, uint8_t reportType, uint8_t reportId, uint8_t* reportBuff, uint8_t reportLen); USBH_StatusTypeDef USBH_HID_GetHIDReportDescriptor (USBH_HandleTypeDef *phost, uint16_t length); USBH_StatusTypeDef USBH_HID_GetHIDDescriptor (USBH_HandleTypeDef *phost, uint16_t length); USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost, uint8_t duration, uint8_t reportId); USBH_StatusTypeDef USBH_HID_SetProtocol (USBH_HandleTypeDef *phost, uint8_t protocol); void USBH_HID_EventCallback(USBH_HandleTypeDef *phost); HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost); void fifo_init(FIFO_TypeDef * f, uint8_t * buf, uint16_t size); uint16_t fifo_read(FIFO_TypeDef * f, void * buf, uint16_t nbytes); uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes); /** * @} */ #endif /* __USBH_HID_H */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/Inc/usbh_hid_keybd.h000066400000000000000000000334111357706137100251300ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid_keybd.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contains all the prototypes for the usbh_hid_keybd.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive -----------------------------------------------*/ #ifndef __USBH_HID_KEYBD_H #define __USBH_HID_KEYBD_H /* Includes ------------------------------------------------------------------*/ #include "usbh_hid.h" #include "usbh_hid_keybd.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_KEYBD * @brief This file is the Header file for USBH_HID_KEYBD.c * @{ */ /** @defgroup USBH_HID_KEYBD_Exported_Types * @{ */ #define KEY_NONE 0x00 #define KEY_ERRORROLLOVER 0x01 #define KEY_POSTFAIL 0x02 #define KEY_ERRORUNDEFINED 0x03 #define KEY_A 0x04 #define KEY_B 0x05 #define KEY_C 0x06 #define KEY_D 0x07 #define KEY_E 0x08 #define KEY_F 0x09 #define KEY_G 0x0A #define KEY_H 0x0B #define KEY_I 0x0C #define KEY_J 0x0D #define KEY_K 0x0E #define KEY_L 0x0F #define KEY_M 0x10 #define KEY_N 0x11 #define KEY_O 0x12 #define KEY_P 0x13 #define KEY_Q 0x14 #define KEY_R 0x15 #define KEY_S 0x16 #define KEY_T 0x17 #define KEY_U 0x18 #define KEY_V 0x19 #define KEY_W 0x1A #define KEY_X 0x1B #define KEY_Y 0x1C #define KEY_Z 0x1D #define KEY_1_EXCLAMATION_MARK 0x1E #define KEY_2_AT 0x1F #define KEY_3_NUMBER_SIGN 0x20 #define KEY_4_DOLLAR 0x21 #define KEY_5_PERCENT 0x22 #define KEY_6_CARET 0x23 #define KEY_7_AMPERSAND 0x24 #define KEY_8_ASTERISK 0x25 #define KEY_9_OPARENTHESIS 0x26 #define KEY_0_CPARENTHESIS 0x27 #define KEY_ENTER 0x28 #define KEY_ESCAPE 0x29 #define KEY_BACKSPACE 0x2A #define KEY_TAB 0x2B #define KEY_SPACEBAR 0x2C #define KEY_MINUS_UNDERSCORE 0x2D #define KEY_EQUAL_PLUS 0x2E #define KEY_OBRACKET_AND_OBRACE 0x2F #define KEY_CBRACKET_AND_CBRACE 0x30 #define KEY_BACKSLASH_VERTICAL_BAR 0x31 #define KEY_NONUS_NUMBER_SIGN_TILDE 0x32 #define KEY_SEMICOLON_COLON 0x33 #define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34 #define KEY_GRAVE ACCENT AND TILDE 0x35 #define KEY_COMMA_AND_LESS 0x36 #define KEY_DOT_GREATER 0x37 #define KEY_SLASH_QUESTION 0x38 #define KEY_CAPS LOCK 0x39 #define KEY_F1 0x3A #define KEY_F2 0x3B #define KEY_F3 0x3C #define KEY_F4 0x3D #define KEY_F5 0x3E #define KEY_F6 0x3F #define KEY_F7 0x40 #define KEY_F8 0x41 #define KEY_F9 0x42 #define KEY_F10 0x43 #define KEY_F11 0x44 #define KEY_F12 0x45 #define KEY_PRINTSCREEN 0x46 #define KEY_SCROLL LOCK 0x47 #define KEY_PAUSE 0x48 #define KEY_INSERT 0x49 #define KEY_HOME 0x4A #define KEY_PAGEUP 0x4B #define KEY_DELETE 0x4C #define KEY_END1 0x4D #define KEY_PAGEDOWN 0x4E #define KEY_RIGHTARROW 0x4F #define KEY_LEFTARROW 0x50 #define KEY_DOWNARROW 0x51 #define KEY_UPARROW 0x52 #define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 #define KEY_KEYPAD_SLASH 0x54 #define KEY_KEYPAD_ASTERIKS 0x55 #define KEY_KEYPAD_MINUS 0x56 #define KEY_KEYPAD_PLUS 0x57 #define KEY_KEYPAD_ENTER 0x58 #define KEY_KEYPAD_1_END 0x59 #define KEY_KEYPAD_2_DOWN_ARROW 0x5A #define KEY_KEYPAD_3_PAGEDN 0x5B #define KEY_KEYPAD_4_LEFT_ARROW 0x5C #define KEY_KEYPAD_5 0x5D #define KEY_KEYPAD_6_RIGHT_ARROW 0x5E #define KEY_KEYPAD_7_HOME 0x5F #define KEY_KEYPAD_8_UP_ARROW 0x60 #define KEY_KEYPAD_9_PAGEUP 0x61 #define KEY_KEYPAD_0_INSERT 0x62 #define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63 #define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64 #define KEY_APPLICATION 0x65 #define KEY_POWER 0x66 #define KEY_KEYPAD_EQUAL 0x67 #define KEY_F13 0x68 #define KEY_F14 0x69 #define KEY_F15 0x6A #define KEY_F16 0x6B #define KEY_F17 0x6C #define KEY_F18 0x6D #define KEY_F19 0x6E #define KEY_F20 0x6F #define KEY_F21 0x70 #define KEY_F22 0x71 #define KEY_F23 0x72 #define KEY_F24 0x73 #define KEY_EXECUTE 0x74 #define KEY_HELP 0x75 #define KEY_MENU 0x76 #define KEY_SELECT 0x77 #define KEY_STOP 0x78 #define KEY_AGAIN 0x79 #define KEY_UNDO 0x7A #define KEY_CUT 0x7B #define KEY_COPY 0x7C #define KEY_PASTE 0x7D #define KEY_FIND 0x7E #define KEY_MUTE 0x7F #define KEY_VOLUME_UP 0x80 #define KEY_VOLUME_DOWN 0x81 #define KEY_LOCKING_CAPS_LOCK 0x82 #define KEY_LOCKING_NUM_LOCK 0x83 #define KEY_LOCKING_SCROLL_LOCK 0x84 #define KEY_KEYPAD_COMMA 0x85 #define KEY_KEYPAD_EQUAL_SIGN 0x86 #define KEY_INTERNATIONAL1 0x87 #define KEY_INTERNATIONAL2 0x88 #define KEY_INTERNATIONAL3 0x89 #define KEY_INTERNATIONAL4 0x8A #define KEY_INTERNATIONAL5 0x8B #define KEY_INTERNATIONAL6 0x8C #define KEY_INTERNATIONAL7 0x8D #define KEY_INTERNATIONAL8 0x8E #define KEY_INTERNATIONAL9 0x8F #define KEY_LANG1 0x90 #define KEY_LANG2 0x91 #define KEY_LANG3 0x92 #define KEY_LANG4 0x93 #define KEY_LANG5 0x94 #define KEY_LANG6 0x95 #define KEY_LANG7 0x96 #define KEY_LANG8 0x97 #define KEY_LANG9 0x98 #define KEY_ALTERNATE_ERASE 0x99 #define KEY_SYSREQ 0x9A #define KEY_CANCEL 0x9B #define KEY_CLEAR 0x9C #define KEY_PRIOR 0x9D #define KEY_RETURN 0x9E #define KEY_SEPARATOR 0x9F #define KEY_OUT 0xA0 #define KEY_OPER 0xA1 #define KEY_CLEAR_AGAIN 0xA2 #define KEY_CRSEL 0xA3 #define KEY_EXSEL 0xA4 #define KEY_KEYPAD_00 0xB0 #define KEY_KEYPAD_000 0xB1 #define KEY_THOUSANDS_SEPARATOR 0xB2 #define KEY_DECIMAL_SEPARATOR 0xB3 #define KEY_CURRENCY_UNIT 0xB4 #define KEY_CURRENCY_SUB_UNIT 0xB5 #define KEY_KEYPAD_OPARENTHESIS 0xB6 #define KEY_KEYPAD_CPARENTHESIS 0xB7 #define KEY_KEYPAD_OBRACE 0xB8 #define KEY_KEYPAD_CBRACE 0xB9 #define KEY_KEYPAD_TAB 0xBA #define KEY_KEYPAD_BACKSPACE 0xBB #define KEY_KEYPAD_A 0xBC #define KEY_KEYPAD_B 0xBD #define KEY_KEYPAD_C 0xBE #define KEY_KEYPAD_D 0xBF #define KEY_KEYPAD_E 0xC0 #define KEY_KEYPAD_F 0xC1 #define KEY_KEYPAD_XOR 0xC2 #define KEY_KEYPAD_CARET 0xC3 #define KEY_KEYPAD_PERCENT 0xC4 #define KEY_KEYPAD_LESS 0xC5 #define KEY_KEYPAD_GREATER 0xC6 #define KEY_KEYPAD_AMPERSAND 0xC7 #define KEY_KEYPAD_LOGICAL_AND 0xC8 #define KEY_KEYPAD_VERTICAL_BAR 0xC9 #define KEY_KEYPAD_LOGIACL_OR 0xCA #define KEY_KEYPAD_COLON 0xCB #define KEY_KEYPAD_NUMBER_SIGN 0xCC #define KEY_KEYPAD_SPACE 0xCD #define KEY_KEYPAD_AT 0xCE #define KEY_KEYPAD_EXCLAMATION_MARK 0xCF #define KEY_KEYPAD_MEMORY_STORE 0xD0 #define KEY_KEYPAD_MEMORY_RECALL 0xD1 #define KEY_KEYPAD_MEMORY_CLEAR 0xD2 #define KEY_KEYPAD_MEMORY_ADD 0xD3 #define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4 #define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5 #define KEY_KEYPAD_MEMORY_DIVIDE 0xD6 #define KEY_KEYPAD_PLUSMINUS 0xD7 #define KEY_KEYPAD_CLEAR 0xD8 #define KEY_KEYPAD_CLEAR_ENTRY 0xD9 #define KEY_KEYPAD_BINARY 0xDA #define KEY_KEYPAD_OCTAL 0xDB #define KEY_KEYPAD_DECIMAL 0xDC #define KEY_KEYPAD_HEXADECIMAL 0xDD #define KEY_LEFTCONTROL 0xE0 #define KEY_LEFTSHIFT 0xE1 #define KEY_LEFTALT 0xE2 #define KEY_LEFT_GUI 0xE3 #define KEY_RIGHTCONTROL 0xE4 #define KEY_RIGHTSHIFT 0xE5 #define KEY_RIGHTALT 0xE6 #define KEY_RIGHT_GUI 0xE7 typedef struct { uint8_t state; uint8_t lctrl; uint8_t lshift; uint8_t lalt; uint8_t lgui; uint8_t rctrl; uint8_t rshift; uint8_t ralt; uint8_t rgui; uint8_t keys[6]; } HID_KEYBD_Info_TypeDef; USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost); HID_KEYBD_Info_TypeDef *USBH_HID_GetKeybdInfo(USBH_HandleTypeDef *phost); uint8_t USBH_HID_GetASCIICode(HID_KEYBD_Info_TypeDef *info); /** * @} */ #endif /* __USBH_HID_KEYBD_H */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/Inc/usbh_hid_mouse.h000066400000000000000000000050421357706137100251610ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid_mouse.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contains all the prototypes for the usbh_hid_mouse.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_HID_MOUSE_H #define __USBH_HID_MOUSE_H /* Includes ------------------------------------------------------------------*/ #include "usbh_hid.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_MOUSE * @brief This file is the Header file for USBH_HID_MOUSE.c * @{ */ /** @defgroup USBH_HID_MOUSE_Exported_Types * @{ */ typedef struct _HID_MOUSE_Info { uint8_t x; uint8_t y; uint8_t buttons[3]; } HID_MOUSE_Info_TypeDef; /** * @} */ /** @defgroup USBH_HID_MOUSE_Exported_Defines * @{ */ /** * @} */ /** @defgroup USBH_HID_MOUSE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_HID_MOUSE_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_HID_MOUSE_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost); HID_MOUSE_Info_TypeDef *USBH_HID_GetMouseInfo(USBH_HandleTypeDef *phost); /** * @} */ #endif /* __USBH_HID_MOUSE_H */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/Inc/usbh_hid_parser.h000066400000000000000000000045731357706137100253350ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid_parser.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the header file of the usbh_hid_parser.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ #ifndef _HID_PARSER_H_ #define _HID_PARSER_H_ /* Includes ------------------------------------------------------------------*/ #include "usbh_hid.h" #include "usbh_hid_usage.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_PARSER * @brief This file is the Header file for USBH_HID_PARSER.c * @{ */ /** @defgroup USBH_HID_PARSER_Exported_Types * @{ */ typedef struct { uint8_t *data; uint32_t size; uint8_t shift; uint8_t count; uint8_t sign; uint32_t logical_min; /*min value device can return*/ uint32_t logical_max; /*max value device can return*/ uint32_t physical_min; /*min vale read can report*/ uint32_t physical_max; /*max value read can report*/ uint32_t resolution; } HID_Report_ItemTypedef; uint32_t HID_ReadItem (HID_Report_ItemTypedef *ri, uint8_t ndx); uint32_t HID_WriteItem(HID_Report_ItemTypedef *ri, uint32_t value, uint8_t ndx); /** * @} */ #endif /* _HID_PARSER_H_ */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/Inc/usbh_hid_usage.h000066400000000000000000000243021357706137100251350ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid_keybd.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contain the USAGE page codes ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ #ifndef _HID_USAGE_H_ #define _HID_USAGE_H_ /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_USAGE * @brief This file is the Header file for USBH_HID_USAGE.c * @{ */ /** @defgroup USBH_HID_USAGE_Exported_Types * @{ */ /****************************************************/ /* HID 1.11 usage pages */ /****************************************************/ #define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ /**** Top level pages */ #define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ #define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ #define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ #define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ #define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ #define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ #define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ #define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ #define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ #define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ #define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ #define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ #define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ /* 0E Reserved */ #define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ #define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ /* 11-13 Reserved */ #define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ /* 15-1f Reserved */ /**** END of top level pages */ /* 25-3f Reserved */ #define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ /* 41-7F Reserved */ /*80-83 Monitor pages USB Device Class Definition for Monitor Devices 84-87 Power pages USB Device Class Definition for Power Devices */ /* 88-8B Reserved */ #define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ #define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ #define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ #define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ #define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ #define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ /****************************************************/ /* Usage definitions for the "Generic Decktop" page */ /****************************************************/ #define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ #define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ #define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ /* 03 Reserved */ #define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ #define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ #define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ #define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ #define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ /* 09-2F Reserved */ #define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ #define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ #define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ #define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ #define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ #define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ #define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ #define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ #define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ #define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ #define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ #define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ #define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ #define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ #define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ /* 3F Reserved */ #define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ #define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ #define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ #define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ #define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ #define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ #define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ #define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ /* 48-7F Reserved */ #define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ #define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ #define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ #define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ #define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ #define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ #define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ #define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ #define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ #define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ #define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ #define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ #define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ #define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ #define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ #define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ #define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ #define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ #define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ #define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ /* 94-9F Reserved */ #define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ #define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ #define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ #define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ #define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ #define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ #define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ #define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ #define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ /* A9-AF Reserved */ #define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ #define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ #define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ #define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ #define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ #define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ #define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ #define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ /* B8-FFFF Reserved */ /** * @} */ #endif /* _HID_USAGE_H_ */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/Src/000077500000000000000000000000001357706137100220305ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/HID/Src/usbh_hid.c000066400000000000000000000540531357706137100237700ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the HID Layer Handlers for USB Host HID class. * * @verbatim * * =================================================================== * HID Class Description * =================================================================== * This module manages the MSC class V1.11 following the "Device Class Definition * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001". * This driver implements the following aspects of the specification: * - The Boot Interface Subclass * - The Mouse and Keyboard protocols * * @endverbatim * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_hid.h" #include "usbh_hid_parser.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_CORE * @brief This file includes HID Layer Handlers for USB Host HID class. * @{ */ /** @defgroup USBH_HID_CORE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_HID_CORE_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_HID_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_HID_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_HID_CORE_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_HID_InterfaceInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_HID_InterfaceDeInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost); static void USBH_HID_ParseHIDDesc (HID_DescTypeDef *desc, uint8_t *buf); extern USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost); extern USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost); USBH_ClassTypeDef HID_Class = { "HID", USB_HID_CLASS, USBH_HID_InterfaceInit, USBH_HID_InterfaceDeInit, USBH_HID_ClassRequest, USBH_HID_Process, USBH_HID_SOFProcess, NULL, }; /** * @} */ /** @defgroup USBH_HID_CORE_Private_Functions * @{ */ /** * @brief USBH_HID_InterfaceInit * The function init the HID class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HID_InterfaceInit (USBH_HandleTypeDef *phost) { uint8_t max_ep; uint8_t num = 0; uint8_t interface; USBH_StatusTypeDef status = USBH_FAIL ; HID_HandleTypeDef *HID_Handle; interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, 0xFF); if(interface == 0xFF) /* No Valid Interface */ { status = USBH_FAIL; USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name); } else { USBH_SelectInterface (phost, interface); phost->pActiveClass->pData = (HID_HandleTypeDef *)USBH_malloc (sizeof(HID_HandleTypeDef)); HID_Handle = phost->pActiveClass->pData; HID_Handle->state = HID_ERROR; /*Decode Bootclass Protocl: Mouse or Keyboard*/ if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE) { USBH_UsrLog ("KeyBoard device found!"); HID_Handle->Init = USBH_HID_KeybdInit; } else if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol == HID_MOUSE_BOOT_CODE) { USBH_UsrLog ("Mouse device found!"); HID_Handle->Init = USBH_HID_MouseInit; } else { USBH_UsrLog ("Protocol not supported."); return USBH_FAIL; } HID_Handle->state = HID_INIT; HID_Handle->ctl_state = HID_REQ_INIT; HID_Handle->ep_addr = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress; HID_Handle->length = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize; HID_Handle->poll = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bInterval ; if (HID_Handle->poll < HID_MIN_POLL) { HID_Handle->poll = HID_MIN_POLL; } /* Check fo available number of endpoints */ /* Find the number of EPs in the Interface Descriptor */ /* Choose the lower number in order not to overrun the buffer allocated */ max_ep = ( (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ? phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bNumEndpoints : USBH_MAX_NUM_ENDPOINTS); /* Decode endpoint IN and OUT address from interface descriptor */ for ( ;num < max_ep; num++) { if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress & 0x80) { HID_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress); HID_Handle->InPipe =\ USBH_AllocPipe(phost, HID_Handle->InEp); /* Open pipe for IN endpoint */ USBH_OpenPipe (phost, HID_Handle->InPipe, HID_Handle->InEp, phost->device.address, phost->device.speed, USB_EP_TYPE_INTR, HID_Handle->length); USBH_LL_SetToggle (phost, HID_Handle->InPipe, 0); } else { HID_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress); HID_Handle->OutPipe =\ USBH_AllocPipe(phost, HID_Handle->OutEp); /* Open pipe for OUT endpoint */ USBH_OpenPipe (phost, HID_Handle->OutPipe, HID_Handle->OutEp, phost->device.address, phost->device.speed, USB_EP_TYPE_INTR, HID_Handle->length); USBH_LL_SetToggle (phost, HID_Handle->OutPipe, 0); } } status = USBH_OK; } return status; } /** * @brief USBH_HID_InterfaceDeInit * The function DeInit the Pipes used for the HID class. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_InterfaceDeInit (USBH_HandleTypeDef *phost ) { HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; if(HID_Handle->InPipe != 0x00) { USBH_ClosePipe (phost, HID_Handle->InPipe); USBH_FreePipe (phost, HID_Handle->InPipe); HID_Handle->InPipe = 0; /* Reset the pipe as Free */ } if(HID_Handle->OutPipe != 0x00) { USBH_ClosePipe(phost, HID_Handle->OutPipe); USBH_FreePipe (phost, HID_Handle->OutPipe); HID_Handle->OutPipe = 0; /* Reset the pipe as Free */ } if(phost->pActiveClass->pData) { USBH_free (phost->pActiveClass->pData); } return USBH_OK; } /** * @brief USBH_HID_ClassRequest * The function is responsible for handling Standard requests * for HID class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef classReqStatus = USBH_BUSY; HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; /* Switch HID state machine */ switch (HID_Handle->ctl_state) { case HID_REQ_INIT: case HID_REQ_GET_HID_DESC: /* Get HID Desc */ if (USBH_HID_GetHIDDescriptor (phost, USB_HID_DESC_SIZE)== USBH_OK) { USBH_HID_ParseHIDDesc(&HID_Handle->HID_Desc, phost->device.Data); HID_Handle->ctl_state = HID_REQ_GET_REPORT_DESC; } break; case HID_REQ_GET_REPORT_DESC: /* Get Report Desc */ if (USBH_HID_GetHIDReportDescriptor(phost, HID_Handle->HID_Desc.wItemLength) == USBH_OK) { /* The decriptor is available in phost->device.Data */ HID_Handle->ctl_state = HID_REQ_SET_IDLE; } break; case HID_REQ_SET_IDLE: classReqStatus = USBH_HID_SetIdle (phost, 0, 0); /* set Idle */ if (classReqStatus == USBH_OK) { HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL; } else if(classReqStatus == USBH_NOT_SUPPORTED) { HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL; } break; case HID_REQ_SET_PROTOCOL: /* set protocol */ if (USBH_HID_SetProtocol (phost, 0) == USBH_OK) { HID_Handle->ctl_state = HID_REQ_IDLE; /* all requests performed*/ phost->pUser(phost, HOST_USER_CLASS_ACTIVE); status = USBH_OK; } break; case HID_REQ_IDLE: default: break; } return status; } /** * @brief USBH_HID_Process * The function is for managing state machine for HID data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK; HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; switch (HID_Handle->state) { case HID_INIT: HID_Handle->Init(phost); case HID_IDLE: if(USBH_HID_GetReport (phost, 0x01, 0, HID_Handle->pData, HID_Handle->length) == USBH_OK) { fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length); HID_Handle->state = HID_SYNC; } break; case HID_SYNC: /* Sync with start of Even Frame */ if(phost->Timer & 1) { HID_Handle->state = HID_GET_DATA; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif break; case HID_GET_DATA: USBH_InterruptReceiveData(phost, HID_Handle->pData, HID_Handle->length, HID_Handle->InPipe); HID_Handle->state = HID_POLL; HID_Handle->timer = phost->Timer; HID_Handle->DataReady = 0; break; case HID_POLL: if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_DONE) { if(HID_Handle->DataReady == 0) { fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length); HID_Handle->DataReady = 1; USBH_HID_EventCallback(phost); #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } } else if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_STALL) /* IN Endpoint Stalled */ { /* Issue Clear Feature on interrupt IN endpoint */ if(USBH_ClrFeature(phost, HID_Handle->ep_addr) == USBH_OK) { /* Change state to issue next IN token */ HID_Handle->state = HID_GET_DATA; } } break; default: break; } return status; } /** * @brief USBH_HID_SOFProcess * The function is for managing the SOF Process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost) { HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; if(HID_Handle->state == HID_POLL) { if(( phost->Timer - HID_Handle->timer) >= HID_Handle->poll) { HID_Handle->state = HID_GET_DATA; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } } return USBH_OK; } /** * @brief USBH_Get_HID_ReportDescriptor * Issue report Descriptor command to the device. Once the response * received, parse the report descriptor and update the status. * @param phost: Host handle * @param Length : HID Report Descriptor Length * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_GetHIDReportDescriptor (USBH_HandleTypeDef *phost, uint16_t length) { USBH_StatusTypeDef status; status = USBH_GetDescriptor(phost, USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD, USB_DESC_HID_REPORT, phost->device.Data, length); /* HID report descriptor is available in phost->device.Data. In case of USB Boot Mode devices for In report handling , HID report descriptor parsing is not required. In case, for supporting Non-Boot Protocol devices and output reports, user may parse the report descriptor*/ return status; } /** * @brief USBH_Get_HID_Descriptor * Issue HID Descriptor command to the device. Once the response * received, parse the report descriptor and update the status. * @param phost: Host handle * @param Length : HID Descriptor Length * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_GetHIDDescriptor (USBH_HandleTypeDef *phost, uint16_t length) { USBH_StatusTypeDef status; status = USBH_GetDescriptor( phost, USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD, USB_DESC_HID, phost->device.Data, length); return status; } /** * @brief USBH_Set_Idle * Set Idle State. * @param phost: Host handle * @param duration: Duration for HID Idle request * @param reportId : Targetted report ID for Set Idle request * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_SetIdle (USBH_HandleTypeDef *phost, uint8_t duration, uint8_t reportId) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = USB_HID_SET_IDLE; phost->Control.setup.b.wValue.w = (duration << 8 ) | reportId; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = 0; return USBH_CtlReq(phost, 0 , 0 ); } /** * @brief USBH_HID_Set_Report * Issues Set Report * @param phost: Host handle * @param reportType : Report type to be sent * @param reportId : Targetted report ID for Set Report request * @param reportBuff : Report Buffer * @param reportLen : Length of data report to be send * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_SetReport (USBH_HandleTypeDef *phost, uint8_t reportType, uint8_t reportId, uint8_t* reportBuff, uint8_t reportLen) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = USB_HID_SET_REPORT; phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = reportLen; return USBH_CtlReq(phost, reportBuff , reportLen ); } /** * @brief USBH_HID_GetReport * retreive Set Report * @param phost: Host handle * @param reportType : Report type to be sent * @param reportId : Targetted report ID for Set Report request * @param reportBuff : Report Buffer * @param reportLen : Length of data report to be send * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_GetReport (USBH_HandleTypeDef *phost, uint8_t reportType, uint8_t reportId, uint8_t* reportBuff, uint8_t reportLen) { phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE |\ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = USB_HID_GET_REPORT; phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = reportLen; return USBH_CtlReq(phost, reportBuff , reportLen ); } /** * @brief USBH_Set_Protocol * Set protocol State. * @param phost: Host handle * @param protocol : Set Protocol for HID : boot/report protocol * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_SetProtocol(USBH_HandleTypeDef *phost, uint8_t protocol) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\ USB_REQ_TYPE_CLASS; phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL; phost->Control.setup.b.wValue.w = protocol != 0 ? 0 : 1; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = 0; return USBH_CtlReq(phost, 0 , 0 ); } /** * @brief USBH_ParseHIDDesc * This function Parse the HID descriptor * @param desc: HID Descriptor * @param buf: Buffer where the source descriptor is available * @retval None */ static void USBH_HID_ParseHIDDesc (HID_DescTypeDef *desc, uint8_t *buf) { desc->bLength = *(uint8_t *) (buf + 0); desc->bDescriptorType = *(uint8_t *) (buf + 1); desc->bcdHID = LE16 (buf + 2); desc->bCountryCode = *(uint8_t *) (buf + 4); desc->bNumDescriptors = *(uint8_t *) (buf + 5); desc->bReportDescriptorType = *(uint8_t *) (buf + 6); desc->wItemLength = LE16 (buf + 7); } /** * @brief USBH_HID_GetDeviceType * Return Device function. * @param phost: Host handle * @retval HID function: HID_MOUSE / HID_KEYBOARD */ HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost) { HID_TypeTypeDef type = HID_UNKNOWN; if(phost->gState == HOST_CLASS) { if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol \ == HID_KEYBRD_BOOT_CODE) { type = HID_KEYBOARD; } else if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol \ == HID_MOUSE_BOOT_CODE) { type= HID_MOUSE; } } return type; } /** * @brief fifo_init * Initialize FIFO. * @param f: Fifo address * @param buf: Fifo buffer * @param size: Fifo Size * @retval none */ void fifo_init(FIFO_TypeDef * f, uint8_t * buf, uint16_t size) { f->head = 0; f->tail = 0; f->lock = 0; f->size = size; f->buf = buf; } /** * @brief fifo_read * Read from FIFO. * @param f: Fifo address * @param buf: read buffer * @param nbytes: number of item to read * @retval number of read items */ uint16_t fifo_read(FIFO_TypeDef * f, void * buf, uint16_t nbytes) { uint16_t i; uint8_t * p; p = buf; if(f->lock == 0) { f->lock = 1; for(i=0; i < nbytes; i++) { if( f->tail != f->head ) { *p++ = f->buf[f->tail]; f->tail++; if( f->tail == f->size ) { f->tail = 0; } } else { f->lock = 0; return i; } } } f->lock = 0; return nbytes; } /** * @brief fifo_write * Read from FIFO. * @param f: Fifo address * @param buf: read buffer * @param nbytes: number of item to write * @retval number of written items */ uint16_t fifo_write(FIFO_TypeDef * f, const void * buf, uint16_t nbytes) { uint16_t i; const uint8_t * p; p = buf; if(f->lock == 0) { f->lock = 1; for(i=0; i < nbytes; i++) { if( (f->head + 1 == f->tail) || ( (f->head + 1 == f->size) && (f->tail == 0)) ) { f->lock = 0; return i; } else { f->buf[f->head] = *p++; f->head++; if( f->head == f->size ) { f->head = 0; } } } } f->lock = 0; return nbytes; } /** * @brief The function is a callback about HID Data events * @param phost: Selected device * @retval None */ __weak void USBH_HID_EventCallback(USBH_HandleTypeDef *phost) { } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/Src/usbh_hid_keybd.c000066400000000000000000000353701357706137100251470ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid_keybd.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the application layer for USB Host HID Keyboard handling * QWERTY and AZERTY Keyboard are supported as per the selection in * usbh_hid_keybd.h ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_hid_keybd.h" #include "usbh_hid_parser.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_KEYBD * @brief This file includes HID Layer Handlers for USB Host HID class. * @{ */ /** @defgroup USBH_HID_KEYBD_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_HID_KEYBD_Private_Defines * @{ */ /** * @} */ #ifndef AZERTY_KEYBOARD #define QWERTY_KEYBOARD #endif #define KBD_LEFT_CTRL 0x01 #define KBD_LEFT_SHIFT 0x02 #define KBD_LEFT_ALT 0x04 #define KBD_LEFT_GUI 0x08 #define KBD_RIGHT_CTRL 0x10 #define KBD_RIGHT_SHIFT 0x20 #define KBD_RIGHT_ALT 0x40 #define KBD_RIGHT_GUI 0x80 #define KBR_MAX_NBR_PRESSED 6 /** @defgroup USBH_HID_KEYBD_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_HID_KEYBD_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_HID_KeybdDecode(USBH_HandleTypeDef *phost); /** * @} */ /** @defgroup USBH_HID_KEYBD_Private_Variables * @{ */ HID_KEYBD_Info_TypeDef keybd_info; uint32_t keybd_report_data[2]; static const HID_Report_ItemTypedef imp_0_lctrl={ (uint8_t*)keybd_report_data+0, /*data*/ 1, /*size*/ 0, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; static const HID_Report_ItemTypedef imp_0_lshift={ (uint8_t*)keybd_report_data+0, /*data*/ 1, /*size*/ 1, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; static const HID_Report_ItemTypedef imp_0_lalt={ (uint8_t*)keybd_report_data+0, /*data*/ 1, /*size*/ 2, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; static const HID_Report_ItemTypedef imp_0_lgui={ (uint8_t*)keybd_report_data+0, /*data*/ 1, /*size*/ 3, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; static const HID_Report_ItemTypedef imp_0_rctrl={ (uint8_t*)keybd_report_data+0, /*data*/ 1, /*size*/ 4, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; static const HID_Report_ItemTypedef imp_0_rshift={ (uint8_t*)keybd_report_data+0, /*data*/ 1, /*size*/ 5, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; static const HID_Report_ItemTypedef imp_0_ralt={ (uint8_t*)keybd_report_data+0, /*data*/ 1, /*size*/ 6, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; static const HID_Report_ItemTypedef imp_0_rgui={ (uint8_t*)keybd_report_data+0, /*data*/ 1, /*size*/ 7, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; static const HID_Report_ItemTypedef imp_0_key_array={ (uint8_t*)keybd_report_data+2, /*data*/ 8, /*size*/ 0, /*shift*/ 6, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 101, /*max value read can return*/ 0, /*min vale device can report*/ 101, /*max value device can report*/ 1 /*resolution*/ }; #ifdef QWERTY_KEYBOARD static const int8_t HID_KEYBRD_Key[] = { '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\0', '\r', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\', '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\0', '\n', '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\0', '\0', '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; static const int8_t HID_KEYBRD_ShiftKey[] = { '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; #else static const int8_t HID_KEYBRD_Key[] = { '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1','\0', '/', '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; static const int8_t HID_KEYBRD_ShiftKey[] = { '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', '?', '.', '/', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; #endif static const uint8_t HID_KEYBRD_Codes[] = { 0, 0, 0, 0, 31, 50, 48, 33, 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ 52, 51, 25, 26, 17, 20, 32, 21, 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ 4, 5, 6, 7, 8, 9, 10, 11, 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ 28, 29, 42, 40, 41, 1, 53, 54, 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ 118, 119, 120, 121, 122, 123, 124, 125, 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ 79, 84, 83, 90, 95, 100, 105, 106, 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ 96, 101, 99, 104, 45, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ 0, 0, 0, 0, 0, 107, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ }; /** * @brief USBH_HID_KeybdInit * The function init the HID keyboard. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost) { uint32_t x; HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; keybd_info.lctrl=keybd_info.lshift= 0; keybd_info.lalt=keybd_info.lgui= 0; keybd_info.rctrl=keybd_info.rshift= 0; keybd_info.ralt=keybd_info.rgui=0; for(x=0; x< (sizeof(keybd_report_data)/sizeof(uint32_t)); x++) { keybd_report_data[x]=0; } if(HID_Handle->length > (sizeof(keybd_report_data)/sizeof(uint32_t))) { HID_Handle->length = (sizeof(keybd_report_data)/sizeof(uint32_t)); } HID_Handle->pData = (uint8_t*)keybd_report_data; fifo_init(&HID_Handle->fifo, phost->device.Data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); return USBH_OK; } /** * @brief USBH_HID_GetKeybdInfo * The function return keyboard information. * @param phost: Host handle * @retval keyboard information */ HID_KEYBD_Info_TypeDef *USBH_HID_GetKeybdInfo(USBH_HandleTypeDef *phost) { if(USBH_HID_KeybdDecode(phost) == USBH_OK) { return &keybd_info; } else { return NULL; } } /** * @brief USBH_HID_KeybdDecode * The function decode keyboard data. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HID_KeybdDecode(USBH_HandleTypeDef *phost) { uint8_t x; HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; if(HID_Handle->length == 0) { return USBH_FAIL; } /*Fill report */ if(fifo_read(&HID_Handle->fifo, &keybd_report_data, HID_Handle->length) == HID_Handle->length) { keybd_info.lctrl=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lctrl, 0); keybd_info.lshift=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lshift, 0); keybd_info.lalt=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lalt, 0); keybd_info.lgui=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_lgui, 0); keybd_info.rctrl=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rctrl, 0); keybd_info.rshift=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rshift, 0); keybd_info.ralt=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_ralt, 0); keybd_info.rgui=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_rgui, 0); for(x=0; x < sizeof(keybd_info.keys); x++) { keybd_info.keys[x]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &imp_0_key_array, x); } return USBH_OK; } return USBH_FAIL; } /** * @brief USBH_HID_GetASCIICode * The function decode keyboard data into ASCII characters. * @param phost: Host handle * @param info: Keyboard information * @retval ASCII code */ uint8_t USBH_HID_GetASCIICode(HID_KEYBD_Info_TypeDef *info) { uint8_t output; if((info->lshift == 1) || (info->rshift)) { output = HID_KEYBRD_ShiftKey[HID_KEYBRD_Codes[info->keys[0]]]; } else { output = HID_KEYBRD_Key[HID_KEYBRD_Codes[info->keys[0]]]; } return output; } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/Src/usbh_hid_mouse.c000066400000000000000000000151271357706137100251770ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid_mouse.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the application layer for USB Host HID Mouse Handling. ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_hid_mouse.h" #include "usbh_hid_parser.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_MOUSE * @brief This file includes HID Layer Handlers for USB Host HID class. * @{ */ /** @defgroup USBH_HID_MOUSE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_HID_MOUSE_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_HID_MOUSE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_HID_MOUSE_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_HID_MouseDecode(USBH_HandleTypeDef *phost); /** * @} */ /** @defgroup USBH_HID_MOUSE_Private_Variables * @{ */ HID_MOUSE_Info_TypeDef mouse_info; uint32_t mouse_report_data[1]; /* Structures defining how to access items in a HID mouse report */ /* Access button 1 state. */ static const HID_Report_ItemTypedef prop_b1={ (uint8_t *)mouse_report_data+0, /*data*/ 1, /*size*/ 0, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min value device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; /* Access button 2 state. */ static const HID_Report_ItemTypedef prop_b2={ (uint8_t *)mouse_report_data+0, /*data*/ 1, /*size*/ 1, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min value device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; /* Access button 3 state. */ static const HID_Report_ItemTypedef prop_b3={ (uint8_t *)mouse_report_data+0, /*data*/ 1, /*size*/ 2, /*shift*/ 0, /*count (only for array items)*/ 0, /*signed?*/ 0, /*min value read can return*/ 1, /*max value read can return*/ 0, /*min vale device can report*/ 1, /*max value device can report*/ 1 /*resolution*/ }; /* Access x coordinate change. */ static const HID_Report_ItemTypedef prop_x={ (uint8_t *)mouse_report_data+1, /*data*/ 8, /*size*/ 0, /*shift*/ 0, /*count (only for array items)*/ 1, /*signed?*/ 0, /*min value read can return*/ 0xFFFF,/*max value read can return*/ 0, /*min vale device can report*/ 0xFFFF,/*max value device can report*/ 1 /*resolution*/ }; /* Access y coordinate change. */ static const HID_Report_ItemTypedef prop_y={ (uint8_t *)mouse_report_data+2, /*data*/ 8, /*size*/ 0, /*shift*/ 0, /*count (only for array items)*/ 1, /*signed?*/ 0, /*min value read can return*/ 0xFFFF,/*max value read can return*/ 0, /*min vale device can report*/ 0xFFFF,/*max value device can report*/ 1 /*resolution*/ }; /** * @} */ /** @defgroup USBH_HID_MOUSE_Private_Functions * @{ */ /** * @brief USBH_HID_MouseInit * The function init the HID mouse. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost) { HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; mouse_info.x=0; mouse_info.y=0; mouse_info.buttons[0]=0; mouse_info.buttons[1]=0; mouse_info.buttons[2]=0; mouse_report_data[0]=0; if(HID_Handle->length > sizeof(mouse_report_data)) { HID_Handle->length = sizeof(mouse_report_data); } HID_Handle->pData = (uint8_t *)mouse_report_data; fifo_init(&HID_Handle->fifo, phost->device.Data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); return USBH_OK; } /** * @brief USBH_HID_GetMouseInfo * The function return mouse information. * @param phost: Host handle * @retval mouse information */ HID_MOUSE_Info_TypeDef *USBH_HID_GetMouseInfo(USBH_HandleTypeDef *phost) { if(USBH_HID_MouseDecode(phost)== USBH_OK) { return &mouse_info; } else { return NULL; } } /** * @brief USBH_HID_MouseDecode * The function decode mouse data. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HID_MouseDecode(USBH_HandleTypeDef *phost) { HID_HandleTypeDef *HID_Handle = phost->pActiveClass->pData; if(HID_Handle->length == 0) { return USBH_FAIL; } /*Fill report */ if(fifo_read(&HID_Handle->fifo, &mouse_report_data, HID_Handle->length) == HID_Handle->length) { /*Decode report */ mouse_info.x = (int16_t )HID_ReadItem((HID_Report_ItemTypedef *) &prop_x, 0); mouse_info.y = (int16_t )HID_ReadItem((HID_Report_ItemTypedef *) &prop_y, 0); mouse_info.buttons[0]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b1, 0); mouse_info.buttons[1]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b2, 0); mouse_info.buttons[2]=(uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_b3, 0); return USBH_OK; } return USBH_FAIL; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/HID/Src/usbh_hid_parser.c000066400000000000000000000121441357706137100253370ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_hid_parser.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the HID Layer Handlers for USB Host HID class. ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_hid_parser.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_HID_CLASS * @{ */ /** @defgroup USBH_HID_PARSER * @brief This file includes HID parsers for USB Host HID class. * @{ */ /** @defgroup USBH_HID_PARSER_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_HID_PARSER_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_HID_PARSER_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_HID_PARSER_Private_FunctionPrototypes * @{ */ /** * @} */ /** @defgroup USBH_HID_PARSER_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_HID_PARSER_Private_Functions * @{ */ /** * @brief HID_ReadItem * The function read a report item. * @param ri: report item * @param ndx: report index * @retval status (0 : fail / otherwise: item value) */ uint32_t HID_ReadItem(HID_Report_ItemTypedef *ri, uint8_t ndx) { uint32_t val=0; uint32_t x=0; uint32_t bofs; uint8_t *data=ri->data; uint8_t shift=ri->shift; /* get the logical value of the item */ /* if this is an array, wee may need to offset ri->data.*/ if (ri->count > 0) { /* If app tries to read outside of the array. */ if (ri->count <= ndx) { return(0); } /* calculate bit offset */ bofs = ndx*ri->size; bofs += shift; /* calculate byte offset + shift pair from bit offset. */ data+=bofs/8; shift=(uint8_t)(bofs%8); } /* read data bytes in little endian order */ for(x=0; x < ((ri->size & 0x7) ? (ri->size/8)+1 : (ri->size/8)); x++) { val=(uint32_t)(*data << (x*8)); } val=(val >> shift) & ((1<size)-1); if (val < ri->logical_min || val > ri->logical_max) { return(0); } /* convert logical value to physical value */ /* See if the number is negative or not. */ if ((ri->sign) && (val & (1<<(ri->size-1)))) { /* yes, so sign extend value to 32 bits. */ int vs=(int)((-1 & ~((1<<(ri->size))-1)) | val); if(ri->resolution == 1) { return((uint32_t)vs); } return((uint32_t)(vs*ri->resolution)); } else { if(ri->resolution == 1) { return(val); } return(val*ri->resolution); } } /** * @brief HID_WriteItem * The function write a report item. * @param ri: report item * @param ndx: report index * @retval status (1: fail/ 0 : Ok) */ uint32_t HID_WriteItem(HID_Report_ItemTypedef *ri, uint32_t value, uint8_t ndx) { uint32_t x; uint32_t mask; uint32_t bofs; uint8_t *data=ri->data; uint8_t shift=ri->shift; if (value < ri->physical_min || value > ri->physical_max) { return(1); } /* if this is an array, wee may need to offset ri->data.*/ if (ri->count > 0) { /* If app tries to read outside of the array. */ if (ri->count >= ndx) { return(0); } /* calculate bit offset */ bofs = ndx*ri->size; bofs += shift; /* calculate byte offset + shift pair from bit offset. */ data+=bofs/8; shift=(uint8_t)(bofs%8); } /* Convert physical value to logical value. */ if (ri->resolution != 1) { value=value/ri->resolution; } /* Write logical value to report in little endian order. */ mask=(uint32_t)((1<size)-1); value = (value & mask) << shift; for(x=0; x < ((ri->size & 0x7) ? (ri->size/8)+1 : (ri->size/8)); x++) { *(ri->data+x)=(uint8_t)((*(ri->data+x) & ~(mask>>(x*8))) | ((value>>(x*8)) & (mask>>(x*8)))); } return(0); } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MSC/000077500000000000000000000000001357706137100213175ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/MSC/Inc/000077500000000000000000000000001357706137100220305ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/MSC/Inc/usbh_msc.h000066400000000000000000000122571357706137100240130ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_msc.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contains all the prototypes for the usbh_msc_core.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_MSC_H #define __USBH_MSC_H /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" #include "usbh_msc_bot.h" #include "usbh_msc_scsi.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MSC_CLASS * @{ */ /** @defgroup USBH_MSC_CORE * @brief This file is the Header file for usbh_msc_core.c * @{ */ /** @defgroup USBH_MSC_CORE_Exported_Types * @{ */ typedef enum { MSC_INIT = 0, MSC_IDLE, MSC_TEST_UNIT_READY, MSC_READ_CAPACITY10, MSC_READ_INQUIRY, MSC_REQUEST_SENSE, MSC_READ, MSC_WRITE, MSC_UNRECOVERED_ERROR, MSC_PERIODIC_CHECK, } MSC_StateTypeDef; typedef enum { MSC_OK, MSC_NOT_READY, MSC_ERROR, } MSC_ErrorTypeDef; typedef enum { MSC_REQ_IDLE = 0, MSC_REQ_RESET, MSC_REQ_GET_MAX_LUN, MSC_REQ_ERROR, } MSC_ReqStateTypeDef; #define MAX_SUPPORTED_LUN 2 /* Structure for LUN */ typedef struct { MSC_StateTypeDef state; MSC_ErrorTypeDef error; USBH_StatusTypeDef prev_ready_state; SCSI_CapacityTypeDef capacity; SCSI_SenseTypeDef sense; SCSI_StdInquiryDataTypeDef inquiry; uint8_t state_changed; } MSC_LUNTypeDef; /* Structure for MSC process */ typedef struct _MSC_Process { uint32_t max_lun; uint8_t InPipe; uint8_t OutPipe; uint8_t OutEp; uint8_t InEp; uint16_t OutEpSize; uint16_t InEpSize; MSC_StateTypeDef state; MSC_ErrorTypeDef error; MSC_ReqStateTypeDef req_state; MSC_ReqStateTypeDef prev_req_state; BOT_HandleTypeDef hbot; MSC_LUNTypeDef unit[MAX_SUPPORTED_LUN]; uint16_t current_lun; uint16_t rw_lun; uint32_t timer; } MSC_HandleTypeDef; /** * @} */ /** @defgroup USBH_MSC_CORE_Exported_Defines * @{ */ #define USB_REQ_BOT_RESET 0xFF #define USB_REQ_GET_MAX_LUN 0xFE /* MSC Class Codes */ #define USB_MSC_CLASS 0x08 /* Interface Descriptor field values for HID Boot Protocol */ #define MSC_BOT 0x50 #define MSC_TRANSPARENT 0x06 /** * @} */ /** @defgroup USBH_MSC_CORE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_MSC_CORE_Exported_Variables * @{ */ extern USBH_ClassTypeDef USBH_msc; #define USBH_MSC_CLASS &USBH_msc /** * @} */ /** @defgroup USBH_MSC_CORE_Exported_FunctionsPrototype * @{ */ /* Common APIs */ uint8_t USBH_MSC_IsReady (USBH_HandleTypeDef *phost); /* APIs for LUN */ int8_t USBH_MSC_GetMaxLUN (USBH_HandleTypeDef *phost); uint8_t USBH_MSC_UnitIsReady (USBH_HandleTypeDef *phost, uint8_t lun); USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, MSC_LUNTypeDef *info); USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t length); USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t length); /** * @} */ #endif /* __USBH_MSC_H */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MSC/Inc/usbh_msc_bot.h000066400000000000000000000121711357706137100246520ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_msc_bot.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief Header file for usbh_msc_bot.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_MSC_BOT_H__ #define __USBH_MSC_BOT_H__ /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" #include "usbh_msc_bot.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MSC_CLASS * @{ */ /** @defgroup USBH_MSC_BOT * @brief This file is the Header file for usbh_msc_core.c * @{ */ /** @defgroup USBH_MSC_BOT_Exported_Types * @{ */ typedef enum { BOT_OK = 0, BOT_FAIL = 1, BOT_PHASE_ERROR = 2, BOT_BUSY = 3 } BOT_StatusTypeDef; typedef enum { BOT_CMD_IDLE = 0, BOT_CMD_SEND, BOT_CMD_WAIT, } BOT_CMDStateTypeDef; /* CSW Status Definitions */ typedef enum { BOT_CSW_CMD_PASSED = 0x00, BOT_CSW_CMD_FAILED = 0x01, BOT_CSW_PHASE_ERROR = 0x02, } BOT_CSWStatusTypeDef; typedef enum { BOT_SEND_CBW = 1, BOT_SEND_CBW_WAIT, BOT_DATA_IN, BOT_DATA_IN_WAIT, BOT_DATA_OUT, BOT_DATA_OUT_WAIT, BOT_RECEIVE_CSW, BOT_RECEIVE_CSW_WAIT, BOT_ERROR_IN, BOT_ERROR_OUT, BOT_UNRECOVERED_ERROR } BOT_StateTypeDef; typedef union { struct __CBW { uint32_t Signature; uint32_t Tag; uint32_t DataTransferLength; uint8_t Flags; uint8_t LUN; uint8_t CBLength; uint8_t CB[16]; }field; uint8_t data[31]; } BOT_CBWTypeDef; typedef union { struct __CSW { uint32_t Signature; uint32_t Tag; uint32_t DataResidue; uint8_t Status; }field; uint8_t data[13]; } BOT_CSWTypeDef; typedef struct { uint32_t data[16]; BOT_StateTypeDef state; BOT_StateTypeDef prev_state; BOT_CMDStateTypeDef cmd_state; BOT_CBWTypeDef cbw; uint8_t Reserved1; BOT_CSWTypeDef csw; uint8_t Reserved2[3]; uint8_t *pbuf; } BOT_HandleTypeDef; /** * @} */ /** @defgroup USBH_MSC_BOT_Exported_Defines * @{ */ #define BOT_CBW_SIGNATURE 0x43425355 #define BOT_CBW_TAG 0x20304050 #define BOT_CSW_SIGNATURE 0x53425355 #define BOT_CBW_LENGTH 31 #define BOT_CSW_LENGTH 13 #define BOT_SEND_CSW_DISABLE 0 #define BOT_SEND_CSW_ENABLE 1 #define BOT_DIR_IN 0 #define BOT_DIR_OUT 1 #define BOT_DIR_BOTH 2 #define BOT_PAGE_LENGTH 512 #define BOT_CBW_CB_LENGTH 16 #define USB_REQ_BOT_RESET 0xFF #define USB_REQ_GET_MAX_LUN 0xFE #define MAX_BULK_STALL_COUNT_LIMIT 0x04 /* If STALL is seen on Bulk Endpoint continously, this means that device and Host has phase error Hence a Reset is needed */ /** * @} */ /** @defgroup USBH_MSC_BOT_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_MSC_BOT_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_MSC_BOT_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun); USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun); USBH_StatusTypeDef USBH_MSC_BOT_Error(USBH_HandleTypeDef *phost, uint8_t lun); /** * @} */ #endif //__USBH_MSC_BOT_H__ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MSC/Inc/usbh_msc_scsi.h000066400000000000000000000144621357706137100250340ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_msc_scsi.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief Header file for usbh_msc_scsi.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_MSC_SCSI_H__ #define __USBH_MSC_SCSI_H__ /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MSC_CLASS * @{ */ /** @defgroup USBH_MSC_SCSI * @brief This file is the Header file for usbh_msc_scsi.c * @{ */ // Capacity data. typedef struct { uint32_t block_nbr; uint16_t block_size; } SCSI_CapacityTypeDef; // Sense data. typedef struct { uint8_t key; uint8_t asc; uint8_t ascq; } SCSI_SenseTypeDef; // INQUIRY data. typedef struct { uint8_t PeripheralQualifier; uint8_t DeviceType; uint8_t RemovableMedia; uint8_t vendor_id[9]; uint8_t product_id[17]; uint8_t revision_id[5]; }SCSI_StdInquiryDataTypeDef; /** @defgroup USBH_MSC_SCSI_Exported_Defines * @{ */ #define OPCODE_TEST_UNIT_READY 0x00 #define OPCODE_READ_CAPACITY10 0x25 #define OPCODE_READ10 0x28 #define OPCODE_WRITE10 0x2A #define OPCODE_REQUEST_SENSE 0x03 #define OPCODE_INQUIRY 0x12 #define DATA_LEN_MODE_TEST_UNIT_READY 0 #define DATA_LEN_READ_CAPACITY10 8 #define DATA_LEN_INQUIRY 36 #define DATA_LEN_REQUEST_SENSE 14 #define CBW_CB_LENGTH 16 #define CBW_LENGTH 10 /** @defgroup USBH_MSC_SCSI_Exported_Defines * @{ */ #define SCSI_SENSE_KEY_NO_SENSE 0x00 #define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01 #define SCSI_SENSE_KEY_NOT_READY 0x02 #define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03 #define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04 #define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05 #define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06 #define SCSI_SENSE_KEY_DATA_PROTECT 0x07 #define SCSI_SENSE_KEY_BLANK_CHECK 0x08 #define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09 #define SCSI_SENSE_KEY_COPY_ABORTED 0x0A #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D #define SCSI_SENSE_KEY_MISCOMPARE 0x0E /** * @} */ /** @defgroup USBH_MSC_SCSI_Exported_Defines * @{ */ #define SCSI_ASC_NO_ADDITIONAL_SENSE_INFORMATION 0x00 #define SCSI_ASC_LOGICAL_UNIT_NOT_READY 0x04 #define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24 #define SCSI_ASC_WRITE_PROTECTED 0x27 #define SCSI_ASC_FORMAT_ERROR 0x31 #define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20 #define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28 #define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A /** * @} */ /** @defgroup USBH_MSC_SCSI_Exported_Defines * @{ */ #define SCSI_ASCQ_FORMAT_COMMAND_FAILED 0x01 #define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 #define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07 /** * @} */ /** @defgroup USBH_MSC_SCSI_Exported_Macros * @{ */ /** * @} */ /** @defgroup _Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_MSC_SCSI_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost, uint8_t lun); USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost, uint8_t lun, SCSI_CapacityTypeDef *capacity); USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost, uint8_t lun, SCSI_StdInquiryDataTypeDef *inquiry); USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost, uint8_t lun, SCSI_SenseTypeDef *sense_data); USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t length); USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t length); /** * @} */ #endif //__USBH_MSC_SCSI_H__ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MSC/Src/000077500000000000000000000000001357706137100220465ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/MSC/Src/usbh_msc.c000066400000000000000000000576531357706137100240350ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_msc.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file implements the MSC class driver functions * =================================================================== * MSC Class Description * =================================================================== * This module manages the MSC class V1.0 following the "Universal * Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0 * Sep. 31, 1999". * This driver implements the following aspects of the specification: * - Bulk-Only Transport protocol * - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3)) * * @endverbatim * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_msc.h" #include "usbh_msc_bot.h" #include "usbh_msc_scsi.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MSC_CLASS * @{ */ /** @defgroup USBH_MSC_CORE * @brief This file includes the mass storage related functions * @{ */ /** @defgroup USBH_MSC_CORE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_MSC_CORE_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_MSC_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_MSC_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_MSC_CORE_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_MSC_InterfaceInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MSC_InterfaceDeInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun); USBH_ClassTypeDef USBH_msc = { "MSC", USB_MSC_CLASS, USBH_MSC_InterfaceInit, USBH_MSC_InterfaceDeInit, USBH_MSC_ClassRequest, USBH_MSC_Process, USBH_MSC_SOFProcess, NULL, }; /** * @} */ /** @defgroup USBH_MSC_CORE_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_MSC_CORE_Private_Functions * @{ */ /** * @brief USBH_MSC_InterfaceInit * The function init the MSC class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MSC_InterfaceInit (USBH_HandleTypeDef *phost) { uint8_t interface = 0; USBH_StatusTypeDef status = USBH_FAIL ; MSC_HandleTypeDef *MSC_Handle; interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, MSC_TRANSPARENT, MSC_BOT); if(interface == 0xFF) /* Not Valid Interface */ { USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name); status = USBH_FAIL; } else { USBH_SelectInterface (phost, interface); phost->pActiveClass->pData = (MSC_HandleTypeDef *)USBH_malloc (sizeof(MSC_HandleTypeDef)); MSC_Handle = phost->pActiveClass->pData; if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress & 0x80) { MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress); MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize; } else { MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress); MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize; } if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress & 0x80) { MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress); MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].wMaxPacketSize; } else { MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress); MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].wMaxPacketSize; } MSC_Handle->current_lun = 0; MSC_Handle->rw_lun = 0; MSC_Handle->state = MSC_INIT; MSC_Handle->error = MSC_OK; MSC_Handle->req_state = MSC_REQ_IDLE; MSC_Handle->OutPipe = USBH_AllocPipe(phost, MSC_Handle->OutEp); MSC_Handle->InPipe = USBH_AllocPipe(phost, MSC_Handle->InEp); USBH_MSC_BOT_Init(phost); /* De-Initialize LUNs information */ USBH_memset(MSC_Handle->unit, 0, sizeof(MSC_Handle->unit)); /* Open the new channels */ USBH_OpenPipe (phost, MSC_Handle->OutPipe, MSC_Handle->OutEp, phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, MSC_Handle->OutEpSize); USBH_OpenPipe (phost, MSC_Handle->InPipe, MSC_Handle->InEp, phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, MSC_Handle->InEpSize); USBH_LL_SetToggle (phost, MSC_Handle->InPipe,0); USBH_LL_SetToggle (phost, MSC_Handle->OutPipe,0); status = USBH_OK; } return status; } /** * @brief USBH_MSC_InterfaceDeInit * The function DeInit the Pipes used for the MSC class. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_InterfaceDeInit (USBH_HandleTypeDef *phost) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; if ( MSC_Handle->OutPipe) { USBH_ClosePipe(phost, MSC_Handle->OutPipe); USBH_FreePipe (phost, MSC_Handle->OutPipe); MSC_Handle->OutPipe = 0; /* Reset the Channel as Free */ } if ( MSC_Handle->InPipe) { USBH_ClosePipe(phost, MSC_Handle->InPipe); USBH_FreePipe (phost, MSC_Handle->InPipe); MSC_Handle->InPipe = 0; /* Reset the Channel as Free */ } if(phost->pActiveClass->pData) { USBH_free (phost->pActiveClass->pData); phost->pActiveClass->pData = 0; } return USBH_OK; } /** * @brief USBH_MSC_ClassRequest * The function is responsible for handling Standard requests * for MSC class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; USBH_StatusTypeDef status = USBH_BUSY; uint8_t i; /* Switch MSC REQ state machine */ switch (MSC_Handle->req_state) { case MSC_REQ_IDLE: case MSC_REQ_GET_MAX_LUN: /* Issue GetMaxLUN request */ if(USBH_MSC_BOT_REQ_GetMaxLUN(phost, (uint8_t *)&MSC_Handle->max_lun) == USBH_OK ) { MSC_Handle->max_lun = (uint8_t )(MSC_Handle->max_lun) + 1; USBH_UsrLog ("Number of supported LUN: %lu", (int32_t)(MSC_Handle->max_lun)); for(i = 0; i < MSC_Handle->max_lun; i++) { MSC_Handle->unit[i].prev_ready_state = USBH_FAIL; MSC_Handle->unit[i].state_changed = 0; } status = USBH_OK; } break; case MSC_REQ_ERROR : /* a Clear Feature should be issued here */ if(USBH_ClrFeature(phost, 0x00) == USBH_OK) { MSC_Handle->req_state = MSC_Handle->prev_req_state; } break; default: break; } return status; } /** * @brief USBH_MSC_Process * The function is for managing state machine for MSC data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; USBH_StatusTypeDef error = USBH_BUSY ; USBH_StatusTypeDef scsi_status = USBH_BUSY ; USBH_StatusTypeDef ready_status = USBH_BUSY ; switch (MSC_Handle->state) { case MSC_INIT: if(MSC_Handle->current_lun < MSC_Handle->max_lun) { MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY; /* Switch MSC REQ state machine */ switch (MSC_Handle->unit[MSC_Handle->current_lun].state) { case MSC_INIT: USBH_UsrLog ("LUN #%d: ", MSC_Handle->current_lun); MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_INQUIRY; MSC_Handle->timer = phost->Timer + 10000; case MSC_READ_INQUIRY: scsi_status = USBH_MSC_SCSI_Inquiry(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].inquiry); if( scsi_status == USBH_OK) { USBH_UsrLog ("Inquiry Vendor : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.vendor_id); USBH_UsrLog ("Inquiry Product : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.product_id); USBH_UsrLog ("Inquiry Version : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.revision_id); MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY; } if( scsi_status == USBH_FAIL) { MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; } else if(scsi_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; } break; case MSC_TEST_UNIT_READY: ready_status = USBH_MSC_SCSI_TestUnitReady(phost, MSC_Handle->current_lun); if( ready_status == USBH_OK) { if( MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_OK) { MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1; USBH_UsrLog ("Mass Storage Device ready"); } else { MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0; } MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_CAPACITY10; MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK; MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_OK; } if( ready_status == USBH_FAIL) { /* Media not ready, so try to check again during 10s */ if( MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_FAIL) { MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1; USBH_UsrLog ("Mass Storage Device NOT ready"); } else { MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0; } MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY; MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_FAIL; } else if(ready_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; } break; case MSC_READ_CAPACITY10: scsi_status = USBH_MSC_SCSI_ReadCapacity(phost,MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].capacity) ; if(scsi_status == USBH_OK) { if(MSC_Handle->unit[MSC_Handle->current_lun].state_changed == 1) { USBH_UsrLog ("Mass Storage Device capacity : %lu MB", \ (int32_t)((MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr * MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size)/1024/1024)); USBH_UsrLog ("Block number : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr)); USBH_UsrLog ("Block Size : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size)); } MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK; MSC_Handle->current_lun++; } else if( scsi_status == USBH_FAIL) { MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE; } else if(scsi_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; } break; case MSC_REQUEST_SENSE: scsi_status = USBH_MSC_SCSI_RequestSense(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].sense); if( scsi_status == USBH_OK) { if((MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_UNIT_ATTENTION) || (MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_NOT_READY) ) { if(phost->Timer <= MSC_Handle->timer) { MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY; break; } } USBH_UsrLog ("Sense Key : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.key); USBH_UsrLog ("Additional Sense Code : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.asc); USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.ascq); MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; MSC_Handle->current_lun++; } if( scsi_status == USBH_FAIL) { USBH_UsrLog ("Mass Storage Device NOT ready"); MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_UNRECOVERED_ERROR; } else if(scsi_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE; MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR; } break; case MSC_UNRECOVERED_ERROR: MSC_Handle->current_lun++; break; default: break; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif } else { MSC_Handle->current_lun = 0; MSC_Handle->state = MSC_IDLE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif phost->pUser(phost, HOST_USER_CLASS_ACTIVE); } break; case MSC_IDLE: error = USBH_OK; break; default: break; } return error; } /** * @brief USBH_MSC_SOFProcess * The function is for SOF state * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_MSC_RdWrProcess * The function is for managing state machine for MSC I/O Process * @param phost: Host handle * @param lun: logical Unit Number * @retval USBH Status */ static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; USBH_StatusTypeDef error = USBH_BUSY ; USBH_StatusTypeDef scsi_status = USBH_BUSY ; /* Switch MSC REQ state machine */ switch (MSC_Handle->unit[lun].state) { case MSC_READ: scsi_status = USBH_MSC_SCSI_Read(phost,lun, 0, NULL, 0) ; if(scsi_status == USBH_OK) { MSC_Handle->unit[lun].state = MSC_IDLE; error = USBH_OK; } else if( scsi_status == USBH_FAIL) { MSC_Handle->unit[lun].state = MSC_REQUEST_SENSE; } else if(scsi_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; error = USBH_FAIL; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif break; case MSC_WRITE: scsi_status = USBH_MSC_SCSI_Write(phost,lun, 0, NULL, 0) ; if(scsi_status == USBH_OK) { MSC_Handle->unit[lun].state = MSC_IDLE; error = USBH_OK; } else if( scsi_status == USBH_FAIL) { MSC_Handle->unit[lun].state = MSC_REQUEST_SENSE; } else if(scsi_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; error = USBH_FAIL; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif break; case MSC_REQUEST_SENSE: scsi_status = USBH_MSC_SCSI_RequestSense(phost, lun, &MSC_Handle->unit[lun].sense); if( scsi_status == USBH_OK) { USBH_UsrLog ("Sense Key : %x", MSC_Handle->unit[lun].sense.key); USBH_UsrLog ("Additional Sense Code : %x", MSC_Handle->unit[lun].sense.asc); USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[lun].sense.ascq); MSC_Handle->unit[lun].state = MSC_IDLE; MSC_Handle->unit[lun].error = MSC_ERROR; error = USBH_FAIL; } if( scsi_status == USBH_FAIL) { USBH_UsrLog ("Mass Storage Device NOT ready"); } else if(scsi_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; error = USBH_FAIL; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif break; default: break; } return error; } /** * @brief USBH_MSC_IsReady * The function check if the MSC function is ready * @param phost: Host handle * @retval USBH Status */ uint8_t USBH_MSC_IsReady (USBH_HandleTypeDef *phost) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; if(phost->gState == HOST_CLASS) { return (MSC_Handle->state == MSC_IDLE); } else { return 0; } } /** * @brief USBH_MSC_GetMaxLUN * The function return the Max LUN supported * @param phost: Host handle * @retval logical Unit Number supported */ int8_t USBH_MSC_GetMaxLUN (USBH_HandleTypeDef *phost) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; if ((phost->gState != HOST_CLASS) && (MSC_Handle->state == MSC_IDLE)) { return MSC_Handle->max_lun; } return 0xFF; } /** * @brief USBH_MSC_UnitIsReady * The function check whether a LUN is ready * @param phost: Host handle * @param lun: logical Unit Number * @retval Lun status (0: not ready / 1: ready) */ uint8_t USBH_MSC_UnitIsReady (USBH_HandleTypeDef *phost, uint8_t lun) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; if(phost->gState == HOST_CLASS) { return (MSC_Handle->unit[lun].error == MSC_OK); } else { return 0; } } /** * @brief USBH_MSC_GetLUNInfo * The function return a LUN information * @param phost: Host handle * @param lun: logical Unit Number * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, MSC_LUNTypeDef *info) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; if(phost->gState == HOST_CLASS) { USBH_memcpy(info,&MSC_Handle->unit[lun], sizeof(MSC_LUNTypeDef)); return USBH_OK; } else { return USBH_FAIL; } } /** * @brief USBH_MSC_Read * The function performs a Read operation * @param phost: Host handle * @param lun: logical Unit Number * @param address: sector address * @param pbuf: pointer to data * @param length: number of sector to read * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t length) { uint32_t timeout; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; if ((phost->device.is_connected == 0) || (phost->gState != HOST_CLASS) || (MSC_Handle->unit[lun].state != MSC_IDLE)) { return USBH_FAIL; } MSC_Handle->state = MSC_READ; MSC_Handle->unit[lun].state = MSC_READ; MSC_Handle->rw_lun = lun; USBH_MSC_SCSI_Read(phost, lun, address, pbuf, length); timeout = phost->Timer + (10000 * length); while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { MSC_Handle->state = MSC_IDLE; return USBH_FAIL; } } MSC_Handle->state = MSC_IDLE; return USBH_OK; } /** * @brief USBH_MSC_Write * The function performs a Write operation * @param phost: Host handle * @param lun: logical Unit Number * @param address: sector address * @param pbuf: pointer to data * @param length: number of sector to write * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t length) { uint32_t timeout; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; if ((phost->device.is_connected == 0) || (phost->gState != HOST_CLASS) || (MSC_Handle->unit[lun].state != MSC_IDLE)) { return USBH_FAIL; } MSC_Handle->state = MSC_WRITE; MSC_Handle->unit[lun].state = MSC_WRITE; MSC_Handle->rw_lun = lun; USBH_MSC_SCSI_Write(phost, lun, address, pbuf, length); timeout = phost->Timer + (10000 * length); while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { MSC_Handle->state = MSC_IDLE; return USBH_FAIL; } } MSC_Handle->state = MSC_IDLE; return USBH_OK; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MSC/Src/usbh_msc_bot.c000066400000000000000000000434671357706137100246770ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_msc_bot.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file includes the BOT protocol related functions ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_msc_bot.h" #include "usbh_msc.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MSC_CLASS * @{ */ /** @defgroup USBH_MSC_BOT * @brief This file includes the mass storage related functions * @{ */ /** @defgroup USBH_MSC_BOT_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_MSC_BOT_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_MSC_BOT_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_MSC_BOT_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir); static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost); /** * @} */ /** @defgroup USBH_MSC_BOT_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_MSC_BOT_Private_Functions * @{ */ /** * @brief USBH_MSC_BOT_REQ_Reset * The function the MSC BOT Reset request. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \ USB_REQ_RECIPIENT_INTERFACE; phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET; phost->Control.setup.b.wValue.w = 0; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = 0; return USBH_CtlReq(phost, 0 , 0 ); } /** * @brief USBH_MSC_BOT_REQ_GetMaxLUN * The function the MSC BOT GetMaxLUN request. * @param phost: Host handle * @param Maxlun: pointer to Maxlun variable * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun) { phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \ USB_REQ_RECIPIENT_INTERFACE; phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN; phost->Control.setup.b.wValue.w = 0; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = 1; return USBH_CtlReq(phost, Maxlun , 1 ); } /** * @brief USBH_MSC_BOT_Init * The function Initializes the BOT protocol. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; MSC_Handle->hbot.cbw.field.Signature = BOT_CBW_SIGNATURE; MSC_Handle->hbot.cbw.field.Tag = BOT_CBW_TAG; MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_SEND; return USBH_OK; } /** * @brief USBH_MSC_BOT_Process * The function handle the BOT protocol. * @param phost: Host handle * @param lun: Logical Unit Number * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) { USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef error = USBH_BUSY; BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; uint8_t toggle = 0; switch (MSC_Handle->hbot.state) { case BOT_SEND_CBW: MSC_Handle->hbot.cbw.field.LUN = lun; MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT; USBH_BulkSendData (phost, MSC_Handle->hbot.cbw.data, BOT_CBW_LENGTH, MSC_Handle->OutPipe, 1); break; case BOT_SEND_CBW_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); if(URB_Status == USBH_URB_DONE) { if ( MSC_Handle->hbot.cbw.field.DataTransferLength != 0 ) { /* If there is Data Transfer Stage */ if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H) { /* Data Direction is IN */ MSC_Handle->hbot.state = BOT_DATA_IN; } else { /* Data Direction is OUT */ MSC_Handle->hbot.state = BOT_DATA_OUT; } } else {/* If there is NO Data Transfer Stage */ MSC_Handle->hbot.state = BOT_RECEIVE_CSW; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_NOTREADY) { /* Re-send CBW */ MSC_Handle->hbot.state = BOT_SEND_CBW; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { MSC_Handle->hbot.state = BOT_ERROR_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case BOT_DATA_IN: /* Send first packet */ USBH_BulkReceiveData (phost, MSC_Handle->hbot.pbuf, MSC_Handle->InEpSize , MSC_Handle->InPipe); MSC_Handle->hbot.state = BOT_DATA_IN_WAIT; break; case BOT_DATA_IN_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); if(URB_Status == USBH_URB_DONE) { /* Adjudt Data pointer and data length */ if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize) { MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize; MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize; } else { MSC_Handle->hbot.cbw.field.DataTransferLength = 0; } /* More Data To be Received */ if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0) { /* Send next packet */ USBH_BulkReceiveData (phost, MSC_Handle->hbot.pbuf, MSC_Handle->InEpSize , MSC_Handle->InPipe); } else { /* If value was 0, and successful transfer, then change the state */ MSC_Handle->hbot.state = BOT_RECEIVE_CSW; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } } else if(URB_Status == USBH_URB_STALL) { /* This is Data IN Stage STALL Condition */ MSC_Handle->hbot.state = BOT_ERROR_IN; /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 6.7.2 Host expects to receive data from the device 3. On a STALL condition receiving data, then: The host shall accept the data received. The host shall clear the Bulk-In pipe. 4. The host shall attempt to receive a CSW.*/ #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case BOT_DATA_OUT: USBH_BulkSendData (phost, MSC_Handle->hbot.pbuf, MSC_Handle->OutEpSize , MSC_Handle->OutPipe, 1); MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT; break; case BOT_DATA_OUT_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); if(URB_Status == USBH_URB_DONE) { /* Adjudt Data pointer and data length */ if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize) { MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize; MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize; } else { MSC_Handle->hbot.cbw.field.DataTransferLength = 0; } /* More Data To be Sent */ if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0) { USBH_BulkSendData (phost, MSC_Handle->hbot.pbuf, MSC_Handle->OutEpSize , MSC_Handle->OutPipe, 1); } else { /* If value was 0, and successful transfer, then change the state */ MSC_Handle->hbot.state = BOT_RECEIVE_CSW; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_NOTREADY) { /* Re-send same data */ MSC_Handle->hbot.state = BOT_DATA_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { MSC_Handle->hbot.state = BOT_ERROR_OUT; /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 6.7.3 Ho - Host expects to send data to the device 3. On a STALL condition sending data, then: " The host shall clear the Bulk-Out pipe. 4. The host shall attempt to receive a CSW. */ #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case BOT_RECEIVE_CSW: USBH_BulkReceiveData (phost, MSC_Handle->hbot.csw.data, BOT_CSW_LENGTH , MSC_Handle->InPipe); MSC_Handle->hbot.state = BOT_RECEIVE_CSW_WAIT; break; case BOT_RECEIVE_CSW_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); /* Decode CSW */ if(URB_Status == USBH_URB_DONE) { MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_SEND; CSW_Status = USBH_MSC_DecodeCSW(phost); if(CSW_Status == BOT_CSW_CMD_PASSED) { status = USBH_OK; } else { status = USBH_FAIL; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { MSC_Handle->hbot.state = BOT_ERROR_IN; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case BOT_ERROR_IN: error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN); if (error == USBH_OK) { MSC_Handle->hbot.state = BOT_RECEIVE_CSW; } else if (error == USBH_UNRECOVERED_ERROR) { /* This means that there is a STALL Error limit, Do Reset Recovery */ MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR; } break; case BOT_ERROR_OUT: error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT); if ( error == USBH_OK) { toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe); USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1- toggle); USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0); MSC_Handle->hbot.state = BOT_ERROR_IN; } else if (error == USBH_UNRECOVERED_ERROR) { MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR; } break; case BOT_UNRECOVERED_ERROR: status = USBH_MSC_BOT_REQ_Reset(phost); if ( status == USBH_OK) { MSC_Handle->hbot.state = BOT_SEND_CBW; } break; default: break; } return status; } /** * @brief USBH_MSC_BOT_Abort * The function handle the BOT Abort process. * @param phost: Host handle * @param lun: Logical Unit Number * @param dir: direction (0: out / 1 : in) * @retval USBH Status */ static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir) { USBH_StatusTypeDef status = USBH_FAIL; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; switch (dir) { case BOT_DIR_IN : /* send ClrFeture on Bulk IN endpoint */ status = USBH_ClrFeature(phost, MSC_Handle->InEp); break; case BOT_DIR_OUT : /*send ClrFeature on Bulk OUT endpoint */ status = USBH_ClrFeature(phost, MSC_Handle->OutEp); break; default: break; } return status; } /** * @brief USBH_MSC_BOT_DecodeCSW * This function decodes the CSW received by the device and updates the * same to upper layer. * @param phost: Host handle * @retval USBH Status * @notes * Refer to USB Mass-Storage Class : BOT (www.usb.org) * 6.3.1 Valid CSW Conditions : * The host shall consider the CSW valid when: * 1. dCSWSignature is equal to 53425355h * 2. the CSW is 13 (Dh) bytes in length, * 3. dCSWTag matches the dCBWTag from the corresponding CBW. */ static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost) { MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; BOT_CSWStatusTypeDef status = BOT_CSW_CMD_FAILED; /*Checking if the transfer length is diffrent than 13*/ if(USBH_LL_GetLastXferSize(phost, MSC_Handle->InPipe) != BOT_CSW_LENGTH) { /*(4) Hi > Dn (Host expects to receive data from the device, Device intends to transfer no data) (5) Hi > Di (Host expects to receive data from the device, Device intends to send data to the host) (9) Ho > Dn (Host expects to send data to the device, Device intends to transfer no data) (11) Ho > Do (Host expects to send data to the device, Device intends to receive data from the host)*/ status = BOT_CSW_PHASE_ERROR; } else { /* CSW length is Correct */ /* Check validity of the CSW Signature and CSWStatus */ if(MSC_Handle->hbot.csw.field.Signature == BOT_CSW_SIGNATURE) {/* Check Condition 1. dCSWSignature is equal to 53425355h */ if(MSC_Handle->hbot.csw.field.Tag == MSC_Handle->hbot.cbw.field.Tag) { /* Check Condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ if(MSC_Handle->hbot.csw.field.Status == 0) { /* Refer to USB Mass-Storage Class : BOT (www.usb.org) Hn Host expects no data transfers Hi Host expects to receive data from the device Ho Host expects to send data to the device Dn Device intends to transfer no data Di Device intends to send data to the host Do Device intends to receive data from the host Section 6.7 (1) Hn = Dn (Host expects no data transfers, Device intends to transfer no data) (6) Hi = Di (Host expects to receive data from the device, Device intends to send data to the host) (12) Ho = Do (Host expects to send data to the device, Device intends to receive data from the host) */ status = BOT_CSW_CMD_PASSED; } else if(MSC_Handle->hbot.csw.field.Status == 1) { status = BOT_CSW_CMD_FAILED; } else if(MSC_Handle->hbot.csw.field.Status == 2) { /* Refer to USB Mass-Storage Class : BOT (www.usb.org) Section 6.7 (2) Hn < Di ( Host expects no data transfers, Device intends to send data to the host) (3) Hn < Do ( Host expects no data transfers, Device intends to receive data from the host) (7) Hi < Di ( Host expects to receive data from the device, Device intends to send data to the host) (8) Hi <> Do ( Host expects to receive data from the device, Device intends to receive data from the host) (10) Ho <> Di (Host expects to send data to the device, Di Device intends to send data to the host) (13) Ho < Do (Host expects to send data to the device, Device intends to receive data from the host) */ status = BOT_CSW_PHASE_ERROR; } } /* CSW Tag Matching is Checked */ } /* CSW Signature Correct Checking */ else { /* If the CSW Signature is not valid, We sall return the Phase Error to Upper Layers for Reset Recovery */ status = BOT_CSW_PHASE_ERROR; } } /* CSW Length Check*/ return status; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MSC/Src/usbh_msc_scsi.c000066400000000000000000000314471357706137100250470ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_msc_scsi.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file implements the SCSI commands ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_msc.h" #include "usbh_msc_scsi.h" #include "usbh_msc_bot.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MSC_CLASS * @{ */ /** @defgroup USBH_MSC_SCSI * @brief This file includes the mass storage related functions * @{ */ /** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_MSC_SCSI_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_MSC_SCSI_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes * @{ */ /** * @} */ /** @defgroup USBH_MSC_SCSI_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_MSC_SCSI_Private_Functions * @{ */ /** * @brief USBH_MSC_SCSI_TestUnitReady * Issue TestUnitReady command. * @param phost: Host handle * @param lun: Logical Unit Number * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost, uint8_t lun) { USBH_StatusTypeDef error = USBH_FAIL ; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; switch(MSC_Handle->hbot.cmd_state) { case BOT_CMD_SEND: /*Prepare the CBW and relevent field*/ MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY; MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT; MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_TEST_UNIT_READY; MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; error = USBH_BUSY; break; case BOT_CMD_WAIT: error = USBH_MSC_BOT_Process(phost, lun); break; default: break; } return error; } /** * @brief USBH_MSC_SCSI_ReadCapacity * Issue Read Capacity command. * @param phost: Host handle * @param lun: Logical Unit Number * @param capacity: pointer to the capacity structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost, uint8_t lun, SCSI_CapacityTypeDef *capacity) { USBH_StatusTypeDef error = USBH_BUSY ; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; switch(MSC_Handle->hbot.cmd_state) { case BOT_CMD_SEND: /*Prepare the CBW and relevent field*/ MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_READ_CAPACITY10; MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ_CAPACITY10; MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data; error = USBH_BUSY; break; case BOT_CMD_WAIT: error = USBH_MSC_BOT_Process(phost, lun); if(error == USBH_OK) { /*assign the capacity*/ capacity->block_nbr = MSC_Handle->hbot.pbuf[3] | (MSC_Handle->hbot.pbuf[2] << 8) |\ (MSC_Handle->hbot.pbuf[1] << 16) | (MSC_Handle->hbot.pbuf[0] << 24); /*assign the page length*/ capacity->block_size = MSC_Handle->hbot.pbuf[7] | (MSC_Handle->hbot.pbuf[6] << 8); } break; default: break; } return error; } /** * @brief USBH_MSC_SCSI_Inquiry * Issue Inquiry command. * @param phost: Host handle * @param lun: Logical Unit Number * @param capacity: pointer to the inquiry structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost, uint8_t lun, SCSI_StdInquiryDataTypeDef *inquiry) { USBH_StatusTypeDef error = USBH_FAIL ; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; switch(MSC_Handle->hbot.cmd_state) { case BOT_CMD_SEND: /*Prepare the CBW and relevent field*/ MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_INQUIRY; MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_LENGTH); MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_INQUIRY; MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5); MSC_Handle->hbot.cbw.field.CB[2] = 0; MSC_Handle->hbot.cbw.field.CB[3] = 0; MSC_Handle->hbot.cbw.field.CB[4] = 0x24; MSC_Handle->hbot.cbw.field.CB[5] = 0; MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data; error = USBH_BUSY; break; case BOT_CMD_WAIT: error = USBH_MSC_BOT_Process(phost, lun); if(error == USBH_OK) { USBH_memset(inquiry, 0, sizeof(SCSI_StdInquiryDataTypeDef)); /*assign Inquiry Data */ inquiry->DeviceType = MSC_Handle->hbot.pbuf[0] & 0x1F; inquiry->PeripheralQualifier = MSC_Handle->hbot.pbuf[0] >> 5; inquiry->RemovableMedia = (MSC_Handle->hbot.pbuf[1] & 0x80)== 0x80; USBH_memcpy (inquiry->vendor_id, &MSC_Handle->hbot.pbuf[8], 8); USBH_memcpy (inquiry->product_id, &MSC_Handle->hbot.pbuf[16], 16); USBH_memcpy (inquiry->revision_id, &MSC_Handle->hbot.pbuf[32], 4); } break; default: break; } return error; } /** * @brief USBH_MSC_SCSI_RequestSense * Issue RequestSense command. * @param phost: Host handle * @param lun: Logical Unit Number * @param capacity: pointer to the sense data structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost, uint8_t lun, SCSI_SenseTypeDef *sense_data) { USBH_StatusTypeDef error = USBH_FAIL ; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; switch(MSC_Handle->hbot.cmd_state) { case BOT_CMD_SEND: /*Prepare the CBW and relevent field*/ MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_REQUEST_SENSE; MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_REQUEST_SENSE; MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5); MSC_Handle->hbot.cbw.field.CB[2] = 0; MSC_Handle->hbot.cbw.field.CB[3] = 0; MSC_Handle->hbot.cbw.field.CB[4] = DATA_LEN_REQUEST_SENSE; MSC_Handle->hbot.cbw.field.CB[5] = 0; MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data; error = USBH_BUSY; break; case BOT_CMD_WAIT: error = USBH_MSC_BOT_Process(phost, lun); if(error == USBH_OK) { sense_data->key = MSC_Handle->hbot.pbuf[2] & 0x0F; sense_data->asc = MSC_Handle->hbot.pbuf[12]; sense_data->ascq = MSC_Handle->hbot.pbuf[13]; } break; default: break; } return error; } /** * @brief USBH_MSC_SCSI_Write * Issue write10 command. * @param phost: Host handle * @param lun: Logical Unit Number * @param address: sector address * @param pbuf: pointer to data * @param length: number of sector to write * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t length) { USBH_StatusTypeDef error = USBH_FAIL ; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; switch(MSC_Handle->hbot.cmd_state) { case BOT_CMD_SEND: /*Prepare the CBW and relevent field*/ MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512; MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT; MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_WRITE10; /*logical block address*/ MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]); MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]); MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]); MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]); /*Tranfer length */ MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ; MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ; MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; MSC_Handle->hbot.pbuf = pbuf; error = USBH_BUSY; break; case BOT_CMD_WAIT: error = USBH_MSC_BOT_Process(phost, lun); break; default: break; } return error; } /** * @brief USBH_MSC_SCSI_Read * Issue Read10 command. * @param phost: Host handle * @param lun: Logical Unit Number * @param address: sector address * @param pbuf: pointer to data * @param length: number of sector to read * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t length) { USBH_StatusTypeDef error = USBH_FAIL ; MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData; switch(MSC_Handle->hbot.cmd_state) { case BOT_CMD_SEND: /*Prepare the CBW and relevent field*/ MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512; MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH); MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ10; /*logical block address*/ MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]); MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]); MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]); MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]); /*Tranfer length */ MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ; MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ; MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; MSC_Handle->hbot.pbuf = pbuf; error = USBH_BUSY; break; case BOT_CMD_WAIT: error = USBH_MSC_BOT_Process(phost, lun); break; default: break; } return error; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MTP/000077500000000000000000000000001357706137100213355ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/MTP/Inc/000077500000000000000000000000001357706137100220465ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/MTP/Inc/usbh_mtp.h000066400000000000000000000175511357706137100240510ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_mtp.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contains all the prototypes for the usbh_mtp.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_MTP_CORE_H #define __USBH_MTP_CORE_H /* Includes ------------------------------------------------------------------*/ #include "usbh_mtp_ptp.h" #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MTP_CLASS * @{ */ /** @defgroup USBH_MTP_CORE * @brief This file is the Header file for USBH_MTP_CORE.c * @{ */ /*Communication Class codes*/ #define USB_MTP_CLASS 0x06 /* Still Image Class)*/ #define MTP_MAX_STORAGE_UNITS_NBR PTP_MAX_STORAGE_UNITS_NBR /** * @} */ /** @defgroup USBH_MTP_CORE_Exported_Types * @{ */ typedef enum { MTP_IDLE = 0, MTP_GETDEVICEINFO , MTP_OPENSESSION , MTP_CLOSESESSION , MTP_GETSTORAGEIDS , MTP_GETSTORAGEINFO , } MTP_StateTypeDef; typedef enum { MTP_EVENTS_INIT = 0, MTP_EVENTS_GETDATA , } MTP_EventsStateTypeDef; typedef struct { MTP_EventsStateTypeDef state; uint32_t timer; uint16_t poll; PTP_EventContainerTypedef container; } MTP_EventHandleTypedef; typedef struct { uint32_t CurrentStorageId; uint32_t ObjectFormatCode; uint32_t CurrentObjectHandler; uint8_t ObjectHandlerNbr; uint32_t Objdepth; } MTP_ParamsTypedef; typedef struct { PTP_DeviceInfoTypedef devinfo; PTP_StorageIDsTypedef storids; PTP_StorageInfoTypedef storinfo[MTP_MAX_STORAGE_UNITS_NBR]; PTP_ObjectHandlesTypedef Handles; } MTP_InfoTypedef; /* Structure for MTP process */ typedef struct _MTP_Process { MTP_InfoTypedef info; MTP_ParamsTypedef params; uint8_t DataInPipe; uint8_t DataOutPipe; uint8_t NotificationPipe; uint8_t DataOutEp; uint8_t DataInEp; uint8_t NotificationEp; uint16_t DataOutEpSize; uint16_t DataInEpSize; uint16_t NotificationEpSize; MTP_StateTypeDef state; MTP_EventHandleTypedef events; PTP_HandleTypeDef ptp; uint32_t current_storage_unit; uint32_t is_ready; } MTP_HandleTypeDef; #define MTP_StorageInfoTypedef PTP_StorageInfoTypedef #define MTP_ObjectHandlesTypedef PTP_ObjectHandlesTypedef #define MTP_ObjectInfoTypedef PTP_ObjectInfoTypedef /** * @} */ /** @defgroup USBH_MTP_CORE_Exported_Defines * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Exported_Variables * @{ */ extern USBH_ClassTypeDef MTP_Class; #define USBH_MTP_CLASS &MTP_Class /** * @} */ /** @defgroup USBH_MTP_CORE_Exported_FunctionsPrototype * @{ */ uint8_t USBH_MTP_IsReady (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_MTP_SelectStorage (USBH_HandleTypeDef *phost, uint8_t storage_idx); USBH_StatusTypeDef USBH_MTP_GetNumStorage (USBH_HandleTypeDef *phost, uint8_t *storage_num); USBH_StatusTypeDef USBH_MTP_GetNumObjects (USBH_HandleTypeDef *phost, uint32_t storage_id, uint32_t objectformatcode, uint32_t associationOH, uint32_t* numobs); USBH_StatusTypeDef USBH_MTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint8_t storage_idx, MTP_StorageInfoTypedef *info); USBH_StatusTypeDef USBH_MTP_GetObjectHandles (USBH_HandleTypeDef *phost, uint32_t storage_id, uint32_t objectformatcode, uint32_t associationOH, PTP_ObjectHandlesTypedef* objecthandles); USBH_StatusTypeDef USBH_MTP_GetObjectInfo (USBH_HandleTypeDef *phost, uint32_t handle, PTP_ObjectInfoTypedef* objectinfo); USBH_StatusTypeDef USBH_MTP_DeleteObject (USBH_HandleTypeDef *phost, uint32_t handle, uint32_t objectformatcode); USBH_StatusTypeDef USBH_MTP_GetObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object); USBH_StatusTypeDef USBH_MTP_GetPartialObject(USBH_HandleTypeDef *phost, uint32_t handle, uint32_t offset, uint32_t maxbytes, uint8_t *object, uint32_t *len); USBH_StatusTypeDef USBH_MTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost, uint16_t ofc, uint32_t *propnum, uint16_t *props); USBH_StatusTypeDef USBH_MTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, uint16_t opc, uint16_t ofc, PTP_ObjectPropDescTypeDef *opd); USBH_StatusTypeDef USBH_MTP_GetObjectPropList (USBH_HandleTypeDef *phost, uint32_t handle, MTP_PropertiesTypedef *pprops, uint32_t *nrofprops); USBH_StatusTypeDef USBH_MTP_SendObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object, uint32_t size); USBH_StatusTypeDef USBH_MTP_GetDevicePropDesc (USBH_HandleTypeDef *phost, uint16_t propcode, PTP_DevicePropDescTypdef* devicepropertydesc); void USBH_MTP_EventsCallback(USBH_HandleTypeDef *phost, uint32_t event, uint32_t param); /** * @} */ #endif /* __USBH_MTP_CORE_H */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MTP/Inc/usbh_mtp_ptp.h000066400000000000000000001034571357706137100247350ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_mtp_ptp.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief Header file for usbh_mtp_ptp.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_MTP_PTP_H__ #define __USBH_MTP_PTP_H__ /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MTP_PTP_CLASS * @{ */ /** @defgroup USBH_MTP_PTP * @brief This file is the Header file for usbh_mtp_ptp.c * @{ */ /* Operation Codes */ /* PTP v1.0 operation codes */ #define PTP_OC_Undefined 0x1000 #define PTP_OC_GetDeviceInfo 0x1001 #define PTP_OC_OpenSession 0x1002 #define PTP_OC_CloseSession 0x1003 #define PTP_OC_GetStorageIDs 0x1004 #define PTP_OC_GetStorageInfo 0x1005 #define PTP_OC_GetNumObjects 0x1006 #define PTP_OC_GetObjectHandles 0x1007 #define PTP_OC_GetObjectInfo 0x1008 #define PTP_OC_GetObject 0x1009 #define PTP_OC_GetThumb 0x100A #define PTP_OC_DeleteObject 0x100B #define PTP_OC_SendObjectInfo 0x100C #define PTP_OC_SendObject 0x100D #define PTP_OC_InitiateCapture 0x100E #define PTP_OC_FormatStore 0x100F #define PTP_OC_ResetDevice 0x1010 #define PTP_OC_SelfTest 0x1011 #define PTP_OC_SetObjectProtection 0x1012 #define PTP_OC_PowerDown 0x1013 #define PTP_OC_GetDevicePropDesc 0x1014 #define PTP_OC_GetDevicePropValue 0x1015 #define PTP_OC_SetDevicePropValue 0x1016 #define PTP_OC_ResetDevicePropValue 0x1017 #define PTP_OC_TerminateOpenCapture 0x1018 #define PTP_OC_MoveObject 0x1019 #define PTP_OC_CopyObject 0x101A #define PTP_OC_GetPartialObject 0x101B #define PTP_OC_InitiateOpenCapture 0x101C /* PTP v1.1 operation codes */ #define PTP_OC_StartEnumHandles 0x101D #define PTP_OC_EnumHandles 0x101E #define PTP_OC_StopEnumHandles 0x101F #define PTP_OC_GetVendorExtensionMaps 0x1020 #define PTP_OC_GetVendorDeviceInfo 0x1021 #define PTP_OC_GetResizedImageObject 0x1022 #define PTP_OC_GetFilesystemManifest 0x1023 #define PTP_OC_GetStreamInfo 0x1024 #define PTP_OC_GetStream 0x1025 /* Microsoft / MTP extension codes */ #define PTP_OC_GetObjectPropsSupported 0x9801 #define PTP_OC_GetObjectPropDesc 0x9802 #define PTP_OC_GetObjectPropValue 0x9803 #define PTP_OC_SetObjectPropValue 0x9804 #define PTP_OC_GetObjPropList 0x9805 #define PTP_OC_SetObjPropList 0x9806 #define PTP_OC_GetInterdependendPropdesc 0x9807 #define PTP_OC_SendObjectPropList 0x9808 #define PTP_OC_GetObjectReferences 0x9810 #define PTP_OC_SetObjectReferences 0x9811 #define PTP_OC_UpdateDeviceFirmware 0x9812 #define PTP_OC_Skip 0x9820 /* Response Codes */ /* PTP v1.0 response codes */ #define PTP_RC_Undefined 0x2000 #define PTP_RC_OK 0x2001 #define PTP_RC_GeneralError 0x2002 #define PTP_RC_SessionNotOpen 0x2003 #define PTP_RC_InvalidTransactionID 0x2004 #define PTP_RC_OperationNotSupported 0x2005 #define PTP_RC_ParameterNotSupported 0x2006 #define PTP_RC_IncompleteTransfer 0x2007 #define PTP_RC_InvalidStorageId 0x2008 #define PTP_RC_InvalidObjectHandle 0x2009 #define PTP_RC_DevicePropNotSupported 0x200A #define PTP_RC_InvalidObjectFormatCode 0x200B #define PTP_RC_StoreFull 0x200C #define PTP_RC_ObjectWriteProtected 0x200D #define PTP_RC_StoreReadOnly 0x200E #define PTP_RC_AccessDenied 0x200F #define PTP_RC_NoThumbnailPresent 0x2010 #define PTP_RC_SelfTestFailed 0x2011 #define PTP_RC_PartialDeletion 0x2012 #define PTP_RC_StoreNotAvailable 0x2013 #define PTP_RC_SpecificationByFormatUnsupported 0x2014 #define PTP_RC_NoValidObjectInfo 0x2015 #define PTP_RC_InvalidCodeFormat 0x2016 #define PTP_RC_UnknownVendorCode 0x2017 #define PTP_RC_CaptureAlreadyTerminated 0x2018 #define PTP_RC_DeviceBusy 0x2019 #define PTP_RC_InvalidParentObject 0x201A #define PTP_RC_InvalidDevicePropFormat 0x201B #define PTP_RC_InvalidDevicePropValue 0x201C #define PTP_RC_InvalidParameter 0x201D #define PTP_RC_SessionAlreadyOpened 0x201E #define PTP_RC_TransactionCanceled 0x201F #define PTP_RC_SpecificationOfDestinationUnsupported 0x2020 /* PTP v1.1 response codes */ #define PTP_RC_InvalidEnumHandle 0x2021 #define PTP_RC_NoStreamEnabled 0x2022 #define PTP_RC_InvalidDataSet 0x2023 /* USB container types */ #define PTP_USB_CONTAINER_UNDEFINED 0x0000 #define PTP_USB_CONTAINER_COMMAND 0x0001 #define PTP_USB_CONTAINER_DATA 0x0002 #define PTP_USB_CONTAINER_RESPONSE 0x0003 #define PTP_USB_CONTAINER_EVENT 0x0004 /* PTP/IP definitions */ #define PTPIP_INIT_COMMAND_REQUEST 1 #define PTPIP_INIT_COMMAND_ACK 2 #define PTPIP_INIT_EVENT_REQUEST 3 #define PTPIP_INIT_EVENT_ACK 4 #define PTPIP_INIT_FAIL 5 #define PTPIP_CMD_REQUEST 6 #define PTPIP_CMD_RESPONSE 7 #define PTPIP_EVENT 8 #define PTPIP_START_DATA_PACKET 9 #define PTPIP_DATA_PACKET 10 #define PTPIP_CANCEL_TRANSACTION 11 #define PTPIP_END_DATA_PACKET 12 #define PTPIP_PING 13 #define PTPIP_PONG 14 /* Transaction data phase description */ #define PTP_DP_NODATA 0x0000 /* no data phase */ #define PTP_DP_SENDDATA 0x0001 /* sending data */ #define PTP_DP_GETDATA 0x0002 /* receiving data */ #define PTP_DP_DATA_MASK 0x00ff /* data phase mask */ /** @defgroup USBH_MTP_PTP_Exported_Types * @{ */ typedef enum { PTP_REQ_IDLE = 0, PTP_REQ_SEND = 1, PTP_REQ_WAIT, PTP_REQ_ERROR, } PTP_RequestStateTypeDef; typedef enum { PTP_IDLE = 0, PTP_OP_REQUEST_STATE, PTP_OP_REQUEST_WAIT_STATE, PTP_DATA_OUT_PHASE_STATE, PTP_DATA_OUT_PHASE_WAIT_STATE, PTP_DATA_IN_PHASE_STATE, PTP_DATA_IN_PHASE_WAIT_STATE, PTP_RESPONSE_STATE, PTP_RESPONSE_WAIT_STATE, PTP_ERROR, } PTP_ProcessStateTypeDef; /* PTP request/response/event general PTP container (transport independent) */ typedef struct { uint16_t Code; uint32_t SessionID; uint32_t Transaction_ID; /* params may be of any type of size less or equal to uint32_t */ uint32_t Param1; uint32_t Param2; uint32_t Param3; /* events can only have three parameters */ uint32_t Param4; uint32_t Param5; /* the number of meaningfull parameters */ uint8_t Nparam; } PTP_ContainerTypedef; #define PTP_USB_BULK_HS_MAX_PACKET_LEN_WRITE 1024 #define PTP_USB_BULK_HS_MAX_PACKET_LEN_READ 1024 #define PTP_USB_BULK_HDR_LEN (2*sizeof(uint32_t)+2*sizeof(uint16_t)) #define PTP_USB_BULK_PAYLOAD_LEN_WRITE (PTP_USB_BULK_HS_MAX_PACKET_LEN_WRITE-PTP_USB_BULK_HDR_LEN) #define PTP_USB_BULK_PAYLOAD_LEN_READ (PTP_USB_BULK_HS_MAX_PACKET_LEN_READ-PTP_USB_BULK_HDR_LEN) #define PTP_USB_BULK_REQ_LEN (PTP_USB_BULK_HDR_LEN+5*sizeof(uint32_t)) #define PTP_USB_BULK_REQ_RESP_MAX_LEN 63 typedef struct { uint32_t length; uint16_t type; uint16_t code; uint32_t trans_id; uint32_t param1; uint32_t param2; uint32_t param3; uint32_t param4; uint32_t param5; } PTP_RespContainerTypedef; typedef struct { uint32_t length; uint16_t type; uint16_t code; uint32_t trans_id; uint32_t param1; uint32_t param2; uint32_t param3; uint32_t param4; uint32_t param5; } PTP_OpContainerTypedef; typedef struct { uint32_t length; uint16_t type; uint16_t code; uint32_t trans_id; union { struct { uint32_t param1; uint32_t param2; uint32_t param3; uint32_t param4; uint32_t param5; } params; uint8_t data[PTP_USB_BULK_PAYLOAD_LEN_READ]; }payload; } PTP_DataContainerTypedef; /* PTP USB Asynchronous Event Interrupt Data Format */ typedef struct { uint32_t length; uint16_t type; uint16_t code; uint32_t trans_id; uint32_t param1; uint32_t param2; uint32_t param3; } PTP_EventContainerTypedef; /* Structure for PTP Transport process */ typedef struct { PTP_ProcessStateTypeDef state; PTP_RequestStateTypeDef req_state; PTP_OpContainerTypedef op_container; PTP_DataContainerTypedef data_container; PTP_RespContainerTypedef resp_container; /* ptp transaction ID */ uint32_t transaction_id; /* ptp session ID */ uint32_t session_id; /* device flags */ uint32_t flags; /****** PTP transfer control *******/ /* Data pointer */ uint8_t *data_ptr; /* Data length */ int32_t data_length; /* Data length */ uint32_t data_packet; /* Data length */ uint32_t iteration; /* Packet Index */ uint32_t data_packet_counter; /****** Object transfer control *******/ /* object pointer */ uint8_t *object_ptr; } PTP_HandleTypeDef; /* DeviceInfo data offset */ #define PTP_di_StandardVersion 0 #define PTP_di_VendorExtensionID 2 #define PTP_di_VendorExtensionVersion 6 #define PTP_di_VendorExtensionDesc 8 #define PTP_di_FunctionalMode 8 #define PTP_di_OperationsSupported 10 /* Max info items size */ #define PTP_SUPPORTED_OPERATIONS_NBR 100 #define PTP_SUPPORTED_EVENTS_NBR 100 #define PTP_SUPPORTED_PROPRIETIES_NBR 100 #define PTP_CAPTURE_FORMATS_NBR 100 #define PTP_IMAGE_FORMATS_NBR 100 #define PTP_MAX_STR_SIZE 255 /* PTP device info structure */ typedef struct { uint16_t StandardVersion; uint32_t VendorExtensionID; uint16_t VendorExtensionVersion; uint8_t VendorExtensionDesc[PTP_MAX_STR_SIZE]; uint16_t FunctionalMode; uint32_t OperationsSupported_len; uint16_t OperationsSupported[PTP_SUPPORTED_OPERATIONS_NBR]; uint32_t EventsSupported_len; uint16_t EventsSupported[PTP_SUPPORTED_EVENTS_NBR]; uint32_t DevicePropertiesSupported_len; uint16_t DevicePropertiesSupported[PTP_SUPPORTED_PROPRIETIES_NBR]; uint32_t CaptureFormats_len; uint16_t CaptureFormats[PTP_CAPTURE_FORMATS_NBR]; uint32_t ImageFormats_len; uint16_t ImageFormats[PTP_IMAGE_FORMATS_NBR]; uint8_t Manufacturer[PTP_MAX_STR_SIZE]; uint8_t Model[PTP_MAX_STR_SIZE]; uint8_t DeviceVersion[PTP_MAX_STR_SIZE]; uint8_t SerialNumber[PTP_MAX_STR_SIZE]; } PTP_DeviceInfoTypedef; #define PTP_MAX_STORAGE_UNITS_NBR 5 /* PTP storageIDs structute (returned by GetStorageIDs) */ typedef struct { uint32_t n; uint32_t Storage [PTP_MAX_STORAGE_UNITS_NBR]; } PTP_StorageIDsTypedef; /* PTP StorageInfo structure (returned by GetStorageInfo) */ #define PTP_si_StorageType 0 #define PTP_si_FilesystemType 2 #define PTP_si_AccessCapability 4 #define PTP_si_MaxCapability 6 #define PTP_si_FreeSpaceInBytes 14 #define PTP_si_FreeSpaceInImages 22 #define PTP_si_StorageDescription 26 /* PTP Storage Types */ #define PTP_ST_Undefined 0x0000 #define PTP_ST_FixedROM 0x0001 #define PTP_ST_RemovableROM 0x0002 #define PTP_ST_FixedRAM 0x0003 #define PTP_ST_RemovableRAM 0x0004 /* PTP FilesystemType Values */ #define PTP_FST_Undefined 0x0000 #define PTP_FST_GenericFlat 0x0001 #define PTP_FST_GenericHierarchical 0x0002 #define PTP_FST_DCF 0x0003 /* PTP StorageInfo AccessCapability Values */ #define PTP_AC_ReadWrite 0x0000 #define PTP_AC_ReadOnly 0x0001 #define PTP_AC_ReadOnly_with_Object_Deletion 0x0002 typedef struct { uint16_t StorageType; uint16_t FilesystemType; uint16_t AccessCapability; uint64_t MaxCapability; uint64_t FreeSpaceInBytes; uint32_t FreeSpaceInImages; uint8_t StorageDescription[PTP_MAX_STR_SIZE]; uint8_t VolumeLabel[PTP_MAX_STR_SIZE]; } PTP_StorageInfoTypedef; /* PTP Object Format Codes */ /* ancillary formats */ #define PTP_OFC_Undefined 0x3000 #define PTP_OFC_Defined 0x3800 #define PTP_OFC_Association 0x3001 #define PTP_OFC_Script 0x3002 #define PTP_OFC_Executable 0x3003 #define PTP_OFC_Text 0x3004 #define PTP_OFC_HTML 0x3005 #define PTP_OFC_DPOF 0x3006 #define PTP_OFC_AIFF 0x3007 #define PTP_OFC_WAV 0x3008 #define PTP_OFC_MP3 0x3009 #define PTP_OFC_AVI 0x300A #define PTP_OFC_MPEG 0x300B #define PTP_OFC_ASF 0x300C #define PTP_OFC_QT 0x300D /* guessing */ /* image formats */ #define PTP_OFC_EXIF_JPEG 0x3801 #define PTP_OFC_TIFF_EP 0x3802 #define PTP_OFC_FlashPix 0x3803 #define PTP_OFC_BMP 0x3804 #define PTP_OFC_CIFF 0x3805 #define PTP_OFC_Undefined_0x3806 0x3806 #define PTP_OFC_GIF 0x3807 #define PTP_OFC_JFIF 0x3808 #define PTP_OFC_PCD 0x3809 #define PTP_OFC_PICT 0x380A #define PTP_OFC_PNG 0x380B #define PTP_OFC_Undefined_0x380C 0x380C #define PTP_OFC_TIFF 0x380D #define PTP_OFC_TIFF_IT 0x380E #define PTP_OFC_JP2 0x380F #define PTP_OFC_JPX 0x3810 /* ptp v1.1 has only DNG new */ #define PTP_OFC_DNG 0x3811 /* MTP extensions */ #define PTP_OFC_MTP_MediaCard 0xb211 #define PTP_OFC_MTP_MediaCardGroup 0xb212 #define PTP_OFC_MTP_Encounter 0xb213 #define PTP_OFC_MTP_EncounterBox 0xb214 #define PTP_OFC_MTP_M4A 0xb215 #define PTP_OFC_MTP_ZUNEUNDEFINED 0xb217 /* Unknown file type */ #define PTP_OFC_MTP_Firmware 0xb802 #define PTP_OFC_MTP_WindowsImageFormat 0xb881 #define PTP_OFC_MTP_UndefinedAudio 0xb900 #define PTP_OFC_MTP_WMA 0xb901 #define PTP_OFC_MTP_OGG 0xb902 #define PTP_OFC_MTP_AAC 0xb903 #define PTP_OFC_MTP_AudibleCodec 0xb904 #define PTP_OFC_MTP_FLAC 0xb906 #define PTP_OFC_MTP_SamsungPlaylist 0xb909 #define PTP_OFC_MTP_UndefinedVideo 0xb980 #define PTP_OFC_MTP_WMV 0xb981 #define PTP_OFC_MTP_MP4 0xb982 #define PTP_OFC_MTP_MP2 0xb983 #define PTP_OFC_MTP_3GP 0xb984 #define PTP_OFC_MTP_UndefinedCollection 0xba00 #define PTP_OFC_MTP_AbstractMultimediaAlbum 0xba01 #define PTP_OFC_MTP_AbstractImageAlbum 0xba02 #define PTP_OFC_MTP_AbstractAudioAlbum 0xba03 #define PTP_OFC_MTP_AbstractVideoAlbum 0xba04 #define PTP_OFC_MTP_AbstractAudioVideoPlaylist 0xba05 #define PTP_OFC_MTP_AbstractContactGroup 0xba06 #define PTP_OFC_MTP_AbstractMessageFolder 0xba07 #define PTP_OFC_MTP_AbstractChapteredProduction 0xba08 #define PTP_OFC_MTP_AbstractAudioPlaylist 0xba09 #define PTP_OFC_MTP_AbstractVideoPlaylist 0xba0a #define PTP_OFC_MTP_AbstractMediacast 0xba0b #define PTP_OFC_MTP_WPLPlaylist 0xba10 #define PTP_OFC_MTP_M3UPlaylist 0xba11 #define PTP_OFC_MTP_MPLPlaylist 0xba12 #define PTP_OFC_MTP_ASXPlaylist 0xba13 #define PTP_OFC_MTP_PLSPlaylist 0xba14 #define PTP_OFC_MTP_UndefinedDocument 0xba80 #define PTP_OFC_MTP_AbstractDocument 0xba81 #define PTP_OFC_MTP_XMLDocument 0xba82 #define PTP_OFC_MTP_MSWordDocument 0xba83 #define PTP_OFC_MTP_MHTCompiledHTMLDocument 0xba84 #define PTP_OFC_MTP_MSExcelSpreadsheetXLS 0xba85 #define PTP_OFC_MTP_MSPowerpointPresentationPPT 0xba86 #define PTP_OFC_MTP_UndefinedMessage 0xbb00 #define PTP_OFC_MTP_AbstractMessage 0xbb01 #define PTP_OFC_MTP_UndefinedContact 0xbb80 #define PTP_OFC_MTP_AbstractContact 0xbb81 #define PTP_OFC_MTP_vCard2 0xbb82 #define PTP_OFC_MTP_vCard3 0xbb83 #define PTP_OFC_MTP_UndefinedCalendarItem 0xbe00 #define PTP_OFC_MTP_AbstractCalendarItem 0xbe01 #define PTP_OFC_MTP_vCalendar1 0xbe02 #define PTP_OFC_MTP_vCalendar2 0xbe03 #define PTP_OFC_MTP_UndefinedWindowsExecutable 0xbe80 #define PTP_OFC_MTP_MediaCast 0xbe81 #define PTP_OFC_MTP_Section 0xbe82 /* MTP specific Object Properties */ #define PTP_OPC_StorageID 0xDC01 #define PTP_OPC_ObjectFormat 0xDC02 #define PTP_OPC_ProtectionStatus 0xDC03 #define PTP_OPC_ObjectSize 0xDC04 #define PTP_OPC_AssociationType 0xDC05 #define PTP_OPC_AssociationDesc 0xDC06 #define PTP_OPC_ObjectFileName 0xDC07 #define PTP_OPC_DateCreated 0xDC08 #define PTP_OPC_DateModified 0xDC09 #define PTP_OPC_Keywords 0xDC0A #define PTP_OPC_ParentObject 0xDC0B #define PTP_OPC_AllowedFolderContents 0xDC0C #define PTP_OPC_Hidden 0xDC0D #define PTP_OPC_SystemObject 0xDC0E #define PTP_OPC_PersistantUniqueObjectIdentifier 0xDC41 #define PTP_OPC_SyncID 0xDC42 #define PTP_OPC_PropertyBag 0xDC43 #define PTP_OPC_Name 0xDC44 #define PTP_OPC_CreatedBy 0xDC45 #define PTP_OPC_Artist 0xDC46 #define PTP_OPC_DateAuthored 0xDC47 #define PTP_OPC_Description 0xDC48 #define PTP_OPC_URLReference 0xDC49 #define PTP_OPC_LanguageLocale 0xDC4A #define PTP_OPC_CopyrightInformation 0xDC4B #define PTP_OPC_Source 0xDC4C #define PTP_OPC_OriginLocation 0xDC4D #define PTP_OPC_DateAdded 0xDC4E #define PTP_OPC_NonConsumable 0xDC4F #define PTP_OPC_CorruptOrUnplayable 0xDC50 #define PTP_OPC_ProducerSerialNumber 0xDC51 #define PTP_OPC_RepresentativeSampleFormat 0xDC81 #define PTP_OPC_RepresentativeSampleSize 0xDC82 #define PTP_OPC_RepresentativeSampleHeight 0xDC83 #define PTP_OPC_RepresentativeSampleWidth 0xDC84 #define PTP_OPC_RepresentativeSampleDuration 0xDC85 #define PTP_OPC_RepresentativeSampleData 0xDC86 #define PTP_OPC_Width 0xDC87 #define PTP_OPC_Height 0xDC88 #define PTP_OPC_Duration 0xDC89 #define PTP_OPC_Rating 0xDC8A #define PTP_OPC_Track 0xDC8B #define PTP_OPC_Genre 0xDC8C #define PTP_OPC_Credits 0xDC8D #define PTP_OPC_Lyrics 0xDC8E #define PTP_OPC_SubscriptionContentID 0xDC8F #define PTP_OPC_ProducedBy 0xDC90 #define PTP_OPC_UseCount 0xDC91 #define PTP_OPC_SkipCount 0xDC92 #define PTP_OPC_LastAccessed 0xDC93 #define PTP_OPC_ParentalRating 0xDC94 #define PTP_OPC_MetaGenre 0xDC95 #define PTP_OPC_Composer 0xDC96 #define PTP_OPC_EffectiveRating 0xDC97 #define PTP_OPC_Subtitle 0xDC98 #define PTP_OPC_OriginalReleaseDate 0xDC99 #define PTP_OPC_AlbumName 0xDC9A #define PTP_OPC_AlbumArtist 0xDC9B #define PTP_OPC_Mood 0xDC9C #define PTP_OPC_DRMStatus 0xDC9D #define PTP_OPC_SubDescription 0xDC9E #define PTP_OPC_IsCropped 0xDCD1 #define PTP_OPC_IsColorCorrected 0xDCD2 #define PTP_OPC_ImageBitDepth 0xDCD3 #define PTP_OPC_Fnumber 0xDCD4 #define PTP_OPC_ExposureTime 0xDCD5 #define PTP_OPC_ExposureIndex 0xDCD6 #define PTP_OPC_DisplayName 0xDCE0 #define PTP_OPC_BodyText 0xDCE1 #define PTP_OPC_Subject 0xDCE2 #define PTP_OPC_Priority 0xDCE3 #define PTP_OPC_GivenName 0xDD00 #define PTP_OPC_MiddleNames 0xDD01 #define PTP_OPC_FamilyName 0xDD02 #define PTP_OPC_Prefix 0xDD03 #define PTP_OPC_Suffix 0xDD04 #define PTP_OPC_PhoneticGivenName 0xDD05 #define PTP_OPC_PhoneticFamilyName 0xDD06 #define PTP_OPC_EmailPrimary 0xDD07 #define PTP_OPC_EmailPersonal1 0xDD08 #define PTP_OPC_EmailPersonal2 0xDD09 #define PTP_OPC_EmailBusiness1 0xDD0A #define PTP_OPC_EmailBusiness2 0xDD0B #define PTP_OPC_EmailOthers 0xDD0C #define PTP_OPC_PhoneNumberPrimary 0xDD0D #define PTP_OPC_PhoneNumberPersonal 0xDD0E #define PTP_OPC_PhoneNumberPersonal2 0xDD0F #define PTP_OPC_PhoneNumberBusiness 0xDD10 #define PTP_OPC_PhoneNumberBusiness2 0xDD11 #define PTP_OPC_PhoneNumberMobile 0xDD12 #define PTP_OPC_PhoneNumberMobile2 0xDD13 #define PTP_OPC_FaxNumberPrimary 0xDD14 #define PTP_OPC_FaxNumberPersonal 0xDD15 #define PTP_OPC_FaxNumberBusiness 0xDD16 #define PTP_OPC_PagerNumber 0xDD17 #define PTP_OPC_PhoneNumberOthers 0xDD18 #define PTP_OPC_PrimaryWebAddress 0xDD19 #define PTP_OPC_PersonalWebAddress 0xDD1A #define PTP_OPC_BusinessWebAddress 0xDD1B #define PTP_OPC_InstantMessengerAddress 0xDD1C #define PTP_OPC_InstantMessengerAddress2 0xDD1D #define PTP_OPC_InstantMessengerAddress3 0xDD1E #define PTP_OPC_PostalAddressPersonalFull 0xDD1F #define PTP_OPC_PostalAddressPersonalFullLine1 0xDD20 #define PTP_OPC_PostalAddressPersonalFullLine2 0xDD21 #define PTP_OPC_PostalAddressPersonalFullCity 0xDD22 #define PTP_OPC_PostalAddressPersonalFullRegion 0xDD23 #define PTP_OPC_PostalAddressPersonalFullPostalCode 0xDD24 #define PTP_OPC_PostalAddressPersonalFullCountry 0xDD25 #define PTP_OPC_PostalAddressBusinessFull 0xDD26 #define PTP_OPC_PostalAddressBusinessLine1 0xDD27 #define PTP_OPC_PostalAddressBusinessLine2 0xDD28 #define PTP_OPC_PostalAddressBusinessCity 0xDD29 #define PTP_OPC_PostalAddressBusinessRegion 0xDD2A #define PTP_OPC_PostalAddressBusinessPostalCode 0xDD2B #define PTP_OPC_PostalAddressBusinessCountry 0xDD2C #define PTP_OPC_PostalAddressOtherFull 0xDD2D #define PTP_OPC_PostalAddressOtherLine1 0xDD2E #define PTP_OPC_PostalAddressOtherLine2 0xDD2F #define PTP_OPC_PostalAddressOtherCity 0xDD30 #define PTP_OPC_PostalAddressOtherRegion 0xDD31 #define PTP_OPC_PostalAddressOtherPostalCode 0xDD32 #define PTP_OPC_PostalAddressOtherCountry 0xDD33 #define PTP_OPC_OrganizationName 0xDD34 #define PTP_OPC_PhoneticOrganizationName 0xDD35 #define PTP_OPC_Role 0xDD36 #define PTP_OPC_Birthdate 0xDD37 #define PTP_OPC_MessageTo 0xDD40 #define PTP_OPC_MessageCC 0xDD41 #define PTP_OPC_MessageBCC 0xDD42 #define PTP_OPC_MessageRead 0xDD43 #define PTP_OPC_MessageReceivedTime 0xDD44 #define PTP_OPC_MessageSender 0xDD45 #define PTP_OPC_ActivityBeginTime 0xDD50 #define PTP_OPC_ActivityEndTime 0xDD51 #define PTP_OPC_ActivityLocation 0xDD52 #define PTP_OPC_ActivityRequiredAttendees 0xDD54 #define PTP_OPC_ActivityOptionalAttendees 0xDD55 #define PTP_OPC_ActivityResources 0xDD56 #define PTP_OPC_ActivityAccepted 0xDD57 #define PTP_OPC_Owner 0xDD5D #define PTP_OPC_Editor 0xDD5E #define PTP_OPC_Webmaster 0xDD5F #define PTP_OPC_URLSource 0xDD60 #define PTP_OPC_URLDestination 0xDD61 #define PTP_OPC_TimeBookmark 0xDD62 #define PTP_OPC_ObjectBookmark 0xDD63 #define PTP_OPC_ByteBookmark 0xDD64 #define PTP_OPC_LastBuildDate 0xDD70 #define PTP_OPC_TimetoLive 0xDD71 #define PTP_OPC_MediaGUID 0xDD72 #define PTP_OPC_TotalBitRate 0xDE91 #define PTP_OPC_BitRateType 0xDE92 #define PTP_OPC_SampleRate 0xDE93 #define PTP_OPC_NumberOfChannels 0xDE94 #define PTP_OPC_AudioBitDepth 0xDE95 #define PTP_OPC_ScanDepth 0xDE97 #define PTP_OPC_AudioWAVECodec 0xDE99 #define PTP_OPC_AudioBitRate 0xDE9A #define PTP_OPC_VideoFourCCCodec 0xDE9B #define PTP_OPC_VideoBitRate 0xDE9C #define PTP_OPC_FramesPerThousandSeconds 0xDE9D #define PTP_OPC_KeyFrameDistance 0xDE9E #define PTP_OPC_BufferSize 0xDE9F #define PTP_OPC_EncodingQuality 0xDEA0 #define PTP_OPC_EncodingProfile 0xDEA1 #define PTP_OPC_BuyFlag 0xD901 /* WiFi Provisioning MTP Extension property codes */ #define PTP_OPC_WirelessConfigurationFile 0xB104 /* PTP Association Types */ #define PTP_AT_Undefined 0x0000 #define PTP_AT_GenericFolder 0x0001 #define PTP_AT_Album 0x0002 #define PTP_AT_TimeSequence 0x0003 #define PTP_AT_HorizontalPanoramic 0x0004 #define PTP_AT_VerticalPanoramic 0x0005 #define PTP_AT_2DPanoramic 0x0006 #define PTP_AT_AncillaryData 0x0007 #define PTP_MAX_HANDLER_NBR 0x255 typedef struct { uint32_t n; uint32_t Handler[PTP_MAX_HANDLER_NBR]; } PTP_ObjectHandlesTypedef; #define PTP_oi_StorageID 0 #define PTP_oi_ObjectFormat 4 #define PTP_oi_ProtectionStatus 6 #define PTP_oi_ObjectCompressedSize 8 #define PTP_oi_ThumbFormat 12 #define PTP_oi_ThumbCompressedSize 14 #define PTP_oi_ThumbPixWidth 18 #define PTP_oi_ThumbPixHeight 22 #define PTP_oi_ImagePixWidth 26 #define PTP_oi_ImagePixHeight 30 #define PTP_oi_ImageBitDepth 34 #define PTP_oi_ParentObject 38 #define PTP_oi_AssociationType 42 #define PTP_oi_AssociationDesc 44 #define PTP_oi_SequenceNumber 48 #define PTP_oi_filenamelen 52 #define PTP_oi_Filename 53 typedef struct { uint32_t StorageID; uint16_t ObjectFormat; uint16_t ProtectionStatus; /* In the regular objectinfo this is 32bit, but we keep the general object size here that also arrives via other methods and so use 64bit */ uint64_t ObjectCompressedSize; uint16_t ThumbFormat; uint32_t ThumbCompressedSize; uint32_t ThumbPixWidth; uint32_t ThumbPixHeight; uint32_t ImagePixWidth; uint32_t ImagePixHeight; uint32_t ImageBitDepth; uint32_t ParentObject; uint16_t AssociationType; uint32_t AssociationDesc; uint32_t SequenceNumber; uint8_t Filename[PTP_MAX_STR_SIZE]; uint32_t CaptureDate; uint32_t ModificationDate; uint8_t Keywords[PTP_MAX_STR_SIZE]; } PTP_ObjectInfoTypedef; /* Object Property Describing Dataset (DevicePropDesc) */ typedef union _PTP_PropertyValueTypedef { char str[PTP_MAX_STR_SIZE]; uint8_t u8; int8_t i8; uint16_t u16; int16_t i16; uint32_t u32; int32_t i32; uint64_t u64; int64_t i64; struct array { uint32_t count; union _PTP_PropertyValueTypedef *v; } a; }PTP_PropertyValueTypedef; typedef struct { PTP_PropertyValueTypedef MinimumValue; PTP_PropertyValueTypedef MaximumValue; PTP_PropertyValueTypedef StepSize; } PTP_PropDescRangeFormTypedef; /* Property Describing Dataset, Enum Form */ typedef struct { uint16_t NumberOfValues; PTP_PropertyValueTypedef SupportedValue[PTP_SUPPORTED_PROPRIETIES_NBR]; } PTP_PropDescEnumFormTypedef; /* (MTP) Object Property pack/unpack */ #define PTP_opd_ObjectPropertyCode 0 #define PTP_opd_DataType 2 #define PTP_opd_GetSet 4 #define PTP_opd_FactoryDefaultValue 5 typedef struct { uint16_t ObjectPropertyCode; uint16_t DataType; uint8_t GetSet; PTP_PropertyValueTypedef FactoryDefaultValue; uint32_t GroupCode; uint8_t FormFlag; union { PTP_PropDescEnumFormTypedef Enum; PTP_PropDescRangeFormTypedef Range; } FORM; } PTP_ObjectPropDescTypeDef; /* Metadata lists for MTP operations */ typedef struct { uint16_t property; uint16_t datatype; uint32_t ObjectHandle; PTP_PropertyValueTypedef propval; } MTP_PropertiesTypedef; /* Device Property Form Flag */ #define PTP_DPFF_None 0x00 #define PTP_DPFF_Range 0x01 #define PTP_DPFF_Enumeration 0x02 /* Object Property Codes used by MTP (first 3 are same as DPFF codes) */ #define PTP_OPFF_None 0x00 #define PTP_OPFF_Range 0x01 #define PTP_OPFF_Enumeration 0x02 #define PTP_OPFF_DateTime 0x03 #define PTP_OPFF_FixedLengthArray 0x04 #define PTP_OPFF_RegularExpression 0x05 #define PTP_OPFF_ByteArray 0x06 #define PTP_OPFF_LongString 0xFF /* Device Property pack/unpack */ #define PTP_dpd_DevicePropertyCode 0 #define PTP_dpd_DataType 2 #define PTP_dpd_GetSet 4 #define PTP_dpd_FactoryDefaultValue 5 /* Device Property Describing Dataset (DevicePropDesc) */ typedef struct { uint16_t DevicePropertyCode; uint16_t DataType; uint8_t GetSet; PTP_PropertyValueTypedef FactoryDefaultValue; PTP_PropertyValueTypedef CurrentValue; uint8_t FormFlag; union { PTP_PropDescEnumFormTypedef Enum; PTP_PropDescRangeFormTypedef Range; } FORM; } PTP_DevicePropDescTypdef; /* DataType Codes */ #define PTP_DTC_UNDEF 0x0000 #define PTP_DTC_INT8 0x0001 #define PTP_DTC_UINT8 0x0002 #define PTP_DTC_INT16 0x0003 #define PTP_DTC_UINT16 0x0004 #define PTP_DTC_INT32 0x0005 #define PTP_DTC_UINT32 0x0006 #define PTP_DTC_INT64 0x0007 #define PTP_DTC_UINT64 0x0008 #define PTP_DTC_INT128 0x0009 #define PTP_DTC_UINT128 0x000A #define PTP_DTC_ARRAY_MASK 0x4000 #define PTP_DTC_AINT8 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT8) #define PTP_DTC_AUINT8 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT8) #define PTP_DTC_AINT16 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT16) #define PTP_DTC_AUINT16 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT16) #define PTP_DTC_AINT32 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT32) #define PTP_DTC_AUINT32 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT32) #define PTP_DTC_AINT64 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT64) #define PTP_DTC_AUINT64 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT64) #define PTP_DTC_AINT128 (PTP_DTC_ARRAY_MASK | PTP_DTC_INT128) #define PTP_DTC_AUINT128 (PTP_DTC_ARRAY_MASK | PTP_DTC_UINT128) #define PTP_DTC_STR 0xFFFF /* PTP Event Codes */ #define PTP_EC_Undefined 0x4000 #define PTP_EC_CancelTransaction 0x4001 #define PTP_EC_ObjectAdded 0x4002 #define PTP_EC_ObjectRemoved 0x4003 #define PTP_EC_StoreAdded 0x4004 #define PTP_EC_StoreRemoved 0x4005 #define PTP_EC_DevicePropChanged 0x4006 #define PTP_EC_ObjectInfoChanged 0x4007 #define PTP_EC_DeviceInfoChanged 0x4008 #define PTP_EC_RequestObjectTransfer 0x4009 #define PTP_EC_StoreFull 0x400A #define PTP_EC_DeviceReset 0x400B #define PTP_EC_StorageInfoChanged 0x400C #define PTP_EC_CaptureComplete 0x400D #define PTP_EC_UnreportedStatus 0x400E /** * @} */ /** @defgroup USBH_MTP_PTP_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_MTP_PTP_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_MTP_PTP_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_PTP_Init(USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_PTP_Process (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_PTP_SendRequest (USBH_HandleTypeDef *phost, PTP_ContainerTypedef *req); USBH_StatusTypeDef USBH_PTP_GetResponse (USBH_HandleTypeDef *phost, PTP_ContainerTypedef *req); USBH_StatusTypeDef USBH_PTP_OpenSession (USBH_HandleTypeDef *phost, uint32_t session); USBH_StatusTypeDef USBH_PTP_GetDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info); USBH_StatusTypeDef USBH_PTP_GetStorageIds (USBH_HandleTypeDef *phost, PTP_StorageIDsTypedef *storage_ids); USBH_StatusTypeDef USBH_PTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint32_t storage_id, PTP_StorageInfoTypedef *storage_info); USBH_StatusTypeDef USBH_PTP_GetNumObjects (USBH_HandleTypeDef *phost, uint32_t storage_id, uint32_t objectformatcode, uint32_t associationOH, uint32_t* numobs); USBH_StatusTypeDef USBH_PTP_GetObjectHandles (USBH_HandleTypeDef *phost, uint32_t storage_id, uint32_t objectformatcode, uint32_t associationOH, PTP_ObjectHandlesTypedef* objecthandles); USBH_StatusTypeDef USBH_PTP_GetObjectInfo (USBH_HandleTypeDef *phost, uint32_t handle, PTP_ObjectInfoTypedef* objectinfo); USBH_StatusTypeDef USBH_PTP_DeleteObject (USBH_HandleTypeDef *phost, uint32_t handle, uint32_t objectformatcode); USBH_StatusTypeDef USBH_PTP_GetObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object); USBH_StatusTypeDef USBH_PTP_GetPartialObject(USBH_HandleTypeDef *phost, uint32_t handle, uint32_t offset, uint32_t maxbytes, uint8_t *object, uint32_t *len); USBH_StatusTypeDef USBH_PTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost, uint16_t ofc, uint32_t *propnum, uint16_t *props); USBH_StatusTypeDef USBH_PTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, uint16_t opc, uint16_t ofc, PTP_ObjectPropDescTypeDef *opd); USBH_StatusTypeDef USBH_PTP_GetObjectPropList (USBH_HandleTypeDef *phost, uint32_t handle, MTP_PropertiesTypedef *pprops, uint32_t *nrofprops); USBH_StatusTypeDef USBH_PTP_SendObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object, uint32_t size); USBH_StatusTypeDef USBH_PTP_GetDevicePropDesc (USBH_HandleTypeDef *phost, uint16_t propcode, PTP_DevicePropDescTypdef* devicepropertydesc); /** * @} */ #endif //__USBH_MTP_PTP_H__ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MTP/Src/000077500000000000000000000000001357706137100220645ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/MTP/Src/usbh_mtp.c000066400000000000000000001013621357706137100240540ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_mtp.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the MTP Layer Handlers for USB Host MTP class. * * @verbatim * * =================================================================== * MTP Class Description * =================================================================== * This module manages the MSC class V1.11 following the "Device Class Definition * for Human Interface Devices (MTP) Version 1.11 Jun 27, 2001". * This driver implements the following aspects of the specification: * - The Boot Interface Subclass * - The Mouse and Keyboard protocols * * @endverbatim * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_mtp.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MTP_CLASS * @{ */ /** @defgroup USBH_MTP_CORE * @brief This file includes MTP Layer Handlers for USB Host MTP class. * @{ */ /** @defgroup USBH_MTP_CORE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_MTP_CORE_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_MTP_InterfaceInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_InterfaceDeInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_Process(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_ClassRequest (USBH_HandleTypeDef *phost); static uint8_t MTP_FindCtlEndpoint(USBH_HandleTypeDef *phost); static uint8_t MTP_FindDataOutEndpoint(USBH_HandleTypeDef *phost); static uint8_t MTP_FindDataInEndpoint(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_SOFProcess (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_MTP_Events (USBH_HandleTypeDef *phost); static void MTP_DecodeEvent (USBH_HandleTypeDef *phost) ; USBH_ClassTypeDef MTP_Class = { "MTP", USB_MTP_CLASS, USBH_MTP_InterfaceInit, USBH_MTP_InterfaceDeInit, USBH_MTP_ClassRequest, USBH_MTP_Process, USBH_MTP_SOFProcess, NULL, }; /** * @} */ /** @defgroup USBH_MTP_CORE_Private_Functions * @{ */ /** * @brief USBH_MTP_InterfaceInit * The function init the MTP class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_InterfaceInit (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK ; uint8_t interface, endpoint; MTP_HandleTypeDef *MTP_Handle; interface = USBH_FindInterface(phost, USB_MTP_CLASS, 1, 1); if(interface == 0xFF) /* No Valid Interface */ { status = USBH_FAIL; USBH_DbgLog ("Cannot Find the interface for Still Image Class."); } else { USBH_SelectInterface (phost, interface); endpoint = MTP_FindCtlEndpoint(phost); phost->pActiveClass->pData = (MTP_HandleTypeDef *)USBH_malloc (sizeof(MTP_HandleTypeDef)); MTP_Handle = phost->pActiveClass->pData; if( MTP_Handle == NULL) { status = USBH_FAIL; USBH_DbgLog ("Cannot allocate RAM for MTP Handle"); } /*Collect the control endpoint address and length*/ MTP_Handle->NotificationEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress; MTP_Handle->NotificationEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize; MTP_Handle->NotificationPipe = USBH_AllocPipe(phost, MTP_Handle->NotificationEp); MTP_Handle->events.poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bInterval; /* Open pipe for Notification endpoint */ USBH_OpenPipe (phost, MTP_Handle->NotificationPipe, MTP_Handle->NotificationEp, phost->device.address, phost->device.speed, USB_EP_TYPE_INTR, MTP_Handle->NotificationEpSize); USBH_LL_SetToggle (phost, MTP_Handle->NotificationPipe, 0); endpoint = MTP_FindDataInEndpoint(phost); /*Collect the control endpoint address and length*/ MTP_Handle->DataInEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress; MTP_Handle->DataInEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize; MTP_Handle->DataInPipe = USBH_AllocPipe(phost, MTP_Handle->DataInEp); /* Open pipe for DATA IN endpoint */ USBH_OpenPipe (phost, MTP_Handle->DataInPipe, MTP_Handle->DataInEp, phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, MTP_Handle->DataInEpSize); USBH_LL_SetToggle (phost, MTP_Handle->DataInPipe, 0); endpoint = MTP_FindDataOutEndpoint(phost); /*Collect the DATA OUT endpoint address and length*/ MTP_Handle->DataOutEp = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress; MTP_Handle->DataOutEpSize = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize; MTP_Handle->DataOutPipe = USBH_AllocPipe(phost, MTP_Handle->DataOutEp); /* Open pipe for DATA OUT endpoint */ USBH_OpenPipe (phost, MTP_Handle->DataOutPipe, MTP_Handle->DataOutEp, phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, MTP_Handle->DataOutEpSize); USBH_LL_SetToggle (phost, MTP_Handle->DataOutPipe, 0); MTP_Handle->state = MTP_OPENSESSION; MTP_Handle->is_ready = 0; MTP_Handle->events.state = MTP_EVENTS_INIT; return USBH_PTP_Init(phost); } return status; } /** * @brief Find MTP Ctl interface * @param phost: Host handle * @retval USBH Status */ static uint8_t MTP_FindCtlEndpoint(USBH_HandleTypeDef *phost) { uint8_t interface, endpoint; for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS) { for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ ) { if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80)&& (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&& ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_INTERRUPT) == USBH_EP_INTERRUPT)) { return endpoint; } } } } return 0xFF; /* Invalid Endpoint */ } /** * @brief Find MTP DATA OUT interface * @param phost: Host handle * @retval USBH Status */ static uint8_t MTP_FindDataOutEndpoint(USBH_HandleTypeDef *phost) { uint8_t interface, endpoint; for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS) { for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ ) { if(((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80) == 0)&& (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&& ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_BULK) == USBH_EP_BULK)) { return endpoint; } } } } return 0xFF; /* Invalid Endpoint */ } /** * @brief Find MTP DATA IN interface * @param phost: Host handle * @retval USBH Status */ static uint8_t MTP_FindDataInEndpoint(USBH_HandleTypeDef *phost) { uint8_t interface, endpoint; for (interface = 0; interface < USBH_MAX_NUM_INTERFACES ; interface ++ ) { if(phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass == USB_MTP_CLASS) { for (endpoint = 0; endpoint < USBH_MAX_NUM_ENDPOINTS ; endpoint ++ ) { if((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bEndpointAddress & 0x80)&& (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].wMaxPacketSize > 0)&& ((phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[endpoint].bmAttributes & USBH_EP_BULK) == USBH_EP_BULK)) { return endpoint; } } } } return 0xFF; /* Invalid Endpoint */ } /** * @brief USBH_MTP_InterfaceDeInit * The function DeInit the Pipes used for the MTP class. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_InterfaceDeInit (USBH_HandleTypeDef *phost) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; if (MTP_Handle->DataOutPipe) { USBH_ClosePipe(phost, MTP_Handle->DataOutPipe); USBH_FreePipe (phost, MTP_Handle->DataOutPipe); MTP_Handle->DataOutPipe = 0; /* Reset the Channel as Free */ } if (MTP_Handle->DataInPipe) { USBH_ClosePipe(phost, MTP_Handle->DataInPipe); USBH_FreePipe (phost, MTP_Handle->DataInPipe); MTP_Handle->DataInPipe = 0; /* Reset the Channel as Free */ } if (MTP_Handle->NotificationPipe) { USBH_ClosePipe(phost, MTP_Handle->NotificationPipe); USBH_FreePipe (phost, MTP_Handle->NotificationPipe); MTP_Handle->NotificationPipe = 0; /* Reset the Channel as Free */ } if(phost->pActiveClass->pData) { USBH_free (phost->pActiveClass->pData); phost->pActiveClass->pData = 0; } return USBH_OK; } /** * @brief USBH_MTP_ClassRequest * The function is responsible for handling Standard requests * for MTP class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_ClassRequest (USBH_HandleTypeDef *phost) { return USBH_OK;; } /** * @brief USBH_MTP_Process * The function is for managing state machine for MTP data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_Process (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t idx = 0; switch(MTP_Handle->state) { case MTP_OPENSESSION: status = USBH_PTP_OpenSession (phost, 1); /* Session '0' is not valid */ if(status == USBH_OK) { USBH_UsrLog("MTP Session #0 Opened"); MTP_Handle->state = MTP_GETDEVICEINFO; } break; case MTP_GETDEVICEINFO: status = USBH_PTP_GetDeviceInfo (phost, &(MTP_Handle->info.devinfo)); if(status == USBH_OK) { USBH_DbgLog(">>>>> MTP Device Information"); USBH_DbgLog("Standard version : %x", MTP_Handle->info.devinfo.StandardVersion); USBH_DbgLog("Vendor ExtID : %s", (MTP_Handle->info.devinfo.VendorExtensionID == 6)?"MTP": "NOT SUPPORTED"); USBH_DbgLog("Functional mode : %s", (MTP_Handle->info.devinfo.FunctionalMode == 0) ? "Standard" : "Vendor"); USBH_DbgLog("Number of Supported Operation(s) : %d", MTP_Handle->info.devinfo.OperationsSupported_len); USBH_DbgLog("Number of Supported Events(s) : %d", MTP_Handle->info.devinfo.EventsSupported_len); USBH_DbgLog("Number of Supported Proprieties : %d", MTP_Handle->info.devinfo.DevicePropertiesSupported_len); USBH_DbgLog("Manufacturer : %s", MTP_Handle->info.devinfo.Manufacturer); USBH_DbgLog("Model : %s", MTP_Handle->info.devinfo.Model); USBH_DbgLog("Device version : %s", MTP_Handle->info.devinfo.DeviceVersion); USBH_DbgLog("Serial number : %s", MTP_Handle->info.devinfo.SerialNumber); MTP_Handle->state = MTP_GETSTORAGEIDS; } break; case MTP_GETSTORAGEIDS: status = USBH_PTP_GetStorageIds (phost, &(MTP_Handle->info.storids)); if(status == USBH_OK) { USBH_DbgLog("Number of storage ID items : %d", MTP_Handle->info.storids.n); for (idx = 0; idx < MTP_Handle->info.storids.n; idx ++) { USBH_DbgLog("storage#%d ID : %x", idx, MTP_Handle->info.storids.Storage[idx]); } MTP_Handle->current_storage_unit = 0; MTP_Handle->state = MTP_GETSTORAGEINFO; } break; case MTP_GETSTORAGEINFO: status = USBH_PTP_GetStorageInfo (phost, MTP_Handle->info.storids.Storage[MTP_Handle->current_storage_unit], &((MTP_Handle->info.storinfo)[MTP_Handle->current_storage_unit])); if(status == USBH_OK) { USBH_UsrLog("Volume#%lu: %s [%s]", MTP_Handle->current_storage_unit, MTP_Handle->info.storinfo[MTP_Handle->current_storage_unit].StorageDescription, MTP_Handle->info.storinfo[MTP_Handle->current_storage_unit].VolumeLabel); if(++MTP_Handle->current_storage_unit >= MTP_Handle->info.storids.n) { MTP_Handle->state = MTP_IDLE; MTP_Handle->is_ready = 1; MTP_Handle->current_storage_unit = 0; MTP_Handle->params.CurrentStorageId = MTP_Handle->info.storids.Storage[0]; USBH_UsrLog( "MTP Class initialized."); USBH_UsrLog("%s is default storage unit", MTP_Handle->info.storinfo[0].StorageDescription); phost->pUser(phost, HOST_USER_CLASS_ACTIVE); } } break; case MTP_IDLE: USBH_MTP_Events(phost); default: status = USBH_OK; break; } return status; } /** * @brief USBH_MTP_SOFProcess * The function is for managing SOF callback * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_SOFProcess (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK; return status; } /** * @brief USBH_MTP_IsReady * Select the storage Unit to be used * @param phost: Host handle * @retval USBH Status */ uint8_t USBH_MTP_IsReady (USBH_HandleTypeDef *phost) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; return (MTP_Handle->is_ready); } /** * @brief USBH_MTP_GetNumStorage * Select the storage Unit to be used * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetNumStorage (USBH_HandleTypeDef *phost, uint8_t *storage_num) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; if(MTP_Handle->is_ready > 0) { *storage_num = MTP_Handle->info.storids.n; status = USBH_OK; } return status; } /** * @brief USBH_MTP_SelectStorage * Select the storage Unit to be used * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_SelectStorage (USBH_HandleTypeDef *phost, uint8_t storage_idx) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready)) { MTP_Handle->params.CurrentStorageId = MTP_Handle->info.storids.Storage[storage_idx]; status = USBH_OK; } return status; } /** * @brief USBH_MTP_GetStorageInfo * Get the storage Unit info * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint8_t storage_idx, MTP_StorageInfoTypedef *info) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready)) { *info = MTP_Handle->info.storinfo[storage_idx]; status = USBH_OK; } return status; } /** * @brief USBH_MTP_GetStorageInfo * Get the storage Unit info * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetNumObjects (USBH_HandleTypeDef *phost, uint32_t storage_idx, uint32_t objectformatcode, uint32_t associationOH, uint32_t* numobs) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready)) { while ((status = USBH_PTP_GetNumObjects (phost, MTP_Handle->info.storids.Storage[storage_idx], objectformatcode, associationOH, numobs)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetStorageInfo * Get the storage Unit info * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectHandles (USBH_HandleTypeDef *phost, uint32_t storage_idx, uint32_t objectformatcode, uint32_t associationOH, PTP_ObjectHandlesTypedef* objecthandles) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if((storage_idx < MTP_Handle->info.storids.n) && (MTP_Handle->is_ready)) { while ((status = USBH_PTP_GetObjectHandles (phost, MTP_Handle->info.storids.Storage[storage_idx], objectformatcode, associationOH, objecthandles)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_PTP_GetObjectInfo * Gets objert info * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectInfo (USBH_HandleTypeDef *phost, uint32_t handle, PTP_ObjectInfoTypedef* objectinfo) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObjectInfo (phost, handle, objectinfo)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_DeleteObject * Delete an object. * @param phost: Host handle * @param handle : Object Handle * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_DeleteObject (USBH_HandleTypeDef *phost, uint32_t handle, uint32_t objectformatcode) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_DeleteObject (phost, handle, objectformatcode)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetObject * Gets object * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObject (phost, handle, object)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetPartialObject * Gets object * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetPartialObject(USBH_HandleTypeDef *phost, uint32_t handle, uint32_t offset, uint32_t maxbytes, uint8_t *object, uint32_t *len) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetPartialObject(phost, handle, offset, maxbytes, object, len)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetObjectPropsSupported * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost, uint16_t ofc, uint32_t *propnum, uint16_t *props) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObjectPropsSupported (phost, ofc, propnum, props)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetObjectPropDesc * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, uint16_t opc, uint16_t ofc, PTP_ObjectPropDescTypeDef *opd) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObjectPropDesc (phost, opc, ofc, opd)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_GetObjectPropList * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetObjectPropList (USBH_HandleTypeDef *phost, uint32_t handle, MTP_PropertiesTypedef *pprops, uint32_t *nrofprops) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetObjectPropList (phost, handle, pprops, nrofprops)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief USBH_MTP_SendObject * Send an object * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_SendObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object, uint32_t size) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_SendObject (phost, handle, object, size)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief Handle HID Control process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_Events (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY ; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; switch(MTP_Handle->events.state) { case MTP_EVENTS_INIT: if((phost->Timer & 1) == 0) { MTP_Handle->events.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)&(MTP_Handle->events.container), MTP_Handle->NotificationEpSize, MTP_Handle->NotificationPipe); MTP_Handle->events.state = MTP_EVENTS_GETDATA ; } break; case MTP_EVENTS_GETDATA: if(USBH_LL_GetURBState(phost , MTP_Handle->NotificationPipe) == USBH_URB_DONE) { MTP_DecodeEvent(phost); } if(( phost->Timer - MTP_Handle->events.timer) >= MTP_Handle->events.poll) { MTP_Handle->events.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)&(MTP_Handle->events.container), MTP_Handle->NotificationEpSize, MTP_Handle->NotificationPipe); } break; default: break; } return status; } /** * @brief MTP_DecodeEvent * Decode device event sent by responder * @param phost: Host handle * @retval None */ static void MTP_DecodeEvent (USBH_HandleTypeDef *phost) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint16_t code; uint32_t param1; /* Process the event */ code = MTP_Handle->events.container.code; param1 = MTP_Handle->events.container.param1; switch(code) { case PTP_EC_Undefined: USBH_DbgLog("EVT: PTP_EC_Undefined in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_CancelTransaction: USBH_DbgLog("EVT: PTP_EC_CancelTransaction in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_ObjectAdded: USBH_DbgLog("EVT: PTP_EC_ObjectAdded in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_ObjectRemoved: USBH_DbgLog("EVT: PTP_EC_ObjectRemoved in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_StoreAdded: USBH_DbgLog("EVT: PTP_EC_StoreAdded in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_StoreRemoved: USBH_DbgLog("EVT: PTP_EC_StoreRemoved in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_DevicePropChanged: USBH_DbgLog("EVT: PTP_EC_DevicePropChanged in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_ObjectInfoChanged: USBH_DbgLog("EVT: PTP_EC_ObjectInfoChanged in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_DeviceInfoChanged: USBH_DbgLog("EVT: PTP_EC_DeviceInfoChanged in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_RequestObjectTransfer: USBH_DbgLog("EVT: PTP_EC_RequestObjectTransfer in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_StoreFull: USBH_DbgLog("EVT: PTP_EC_StoreFull in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_DeviceReset: USBH_DbgLog("EVT: PTP_EC_DeviceReset in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_StorageInfoChanged : USBH_DbgLog( "EVT: PTP_EC_StorageInfoChanged in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_CaptureComplete : USBH_DbgLog( "EVT: PTP_EC_CaptureComplete in session %u", MTP_Handle->ptp.session_id); break; case PTP_EC_UnreportedStatus : USBH_DbgLog( "EVT: PTP_EC_UnreportedStatus in session %u", MTP_Handle->ptp.session_id); break; default : USBH_DbgLog( "Received unknown event in session %u", MTP_Handle->ptp.session_id); break; } USBH_MTP_EventsCallback(phost, code, param1); } /** * @brief USBH_MTP_GetDevicePropDesc * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_MTP_GetDevicePropDesc (USBH_HandleTypeDef *phost, uint16_t propcode, PTP_DevicePropDescTypdef* devicepropertydesc) { USBH_StatusTypeDef status = USBH_FAIL; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint32_t timeout = phost->Timer + 5000; if(MTP_Handle->is_ready) { while ((status = USBH_PTP_GetDevicePropDesc (phost, propcode, devicepropertydesc)) == USBH_BUSY) { if((phost->Timer > timeout) || (phost->device.is_connected == 0)) { return USBH_FAIL; } } } return status; } /** * @brief The function informs that host has rceived an event * @param pdev: Selected device * @retval None */ __weak void USBH_MTP_EventsCallback(USBH_HandleTypeDef *phost, uint32_t event, uint32_t param) { } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/MTP/Src/usbh_mtp_ptp.c000066400000000000000000001557131357706137100247500ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_mtp_ptp.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file includes the PTP operations layer ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_mtp_ptp.h" #include "usbh_mtp.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_MTP_CLASS * @{ */ /** @defgroup USBH_MTP_PTP * @brief This file includes the mass storage related functions * @{ */ /** @defgroup USBH_MTP_PTP_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_MTP_PTP_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_MTP_PTP_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_MTP_PTP_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_MTP_PTP_Private_FunctionPrototypes * @{ */ static void PTP_DecodeDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info); static void PTP_GetStorageIDs (USBH_HandleTypeDef *phost, PTP_StorageIDsTypedef *stor_ids); static void PTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint32_t storage_id, PTP_StorageInfoTypedef *stor_info); static void PTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, PTP_ObjectPropDescTypeDef *opd, uint32_t opdlen); static void PTP_DecodeDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info); static void PTP_GetDevicePropValue(USBH_HandleTypeDef *phost, uint32_t *offset, uint32_t total, PTP_PropertyValueTypedef* value, uint16_t datatype); static uint32_t PTP_GetObjectPropList (USBH_HandleTypeDef *phost, MTP_PropertiesTypedef *props, uint32_t len); static void PTP_BufferFullCallback(USBH_HandleTypeDef *phost); static void PTP_GetString(uint8_t *str, uint8_t* data, uint16_t *len); static uint32_t PTP_GetArray16 (uint16_t *array, uint8_t *data, uint32_t offset); static uint32_t PTP_GetArray32 (uint32_t *array, uint8_t *data, uint32_t offset); /** * @} */ /** @defgroup USBH_MTP_PTP_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_MTP_PTP_Private_Functions * @{ */ /** * @brief USBH_PTP_Init * The function Initializes the BOT protocol. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_Init(USBH_HandleTypeDef *phost) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; /* Set state to idle to be ready for operations */ MTP_Handle->ptp.state = PTP_IDLE; MTP_Handle->ptp.req_state = PTP_REQ_SEND; return USBH_OK; } /** * @brief USBH_PTP_Process * The function handle the BOT protocol. * @param phost: Host handle * @param lun: Logical Unit Number * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_Process (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; uint32_t len; switch (MTP_Handle->ptp.state) { case PTP_IDLE: /*Do Nothing */ break; case PTP_OP_REQUEST_STATE: USBH_BulkSendData (phost, (uint8_t*)&(MTP_Handle->ptp.op_container), MTP_Handle->ptp.op_container.length, MTP_Handle->DataOutPipe, 1); MTP_Handle->ptp.state = PTP_OP_REQUEST_WAIT_STATE; break; case PTP_OP_REQUEST_WAIT_STATE: URB_Status = USBH_LL_GetURBState(phost, MTP_Handle->DataOutPipe); if(URB_Status == USBH_URB_DONE) { if(MTP_Handle->ptp.flags == PTP_DP_NODATA) { MTP_Handle->ptp.state = PTP_RESPONSE_STATE; } else if(MTP_Handle->ptp.flags == PTP_DP_SENDDATA) { MTP_Handle->ptp.state = PTP_DATA_OUT_PHASE_STATE; } else if(MTP_Handle->ptp.flags == PTP_DP_GETDATA) { MTP_Handle->ptp.state = PTP_DATA_IN_PHASE_STATE; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_NOTREADY) { /* Re-send Request */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { MTP_Handle->ptp.state = PTP_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case PTP_DATA_OUT_PHASE_STATE: USBH_BulkSendData (phost, MTP_Handle->ptp.data_ptr, MTP_Handle->DataOutEpSize , MTP_Handle->DataOutPipe, 1); MTP_Handle->ptp.state = PTP_DATA_OUT_PHASE_WAIT_STATE; break; case PTP_DATA_OUT_PHASE_WAIT_STATE: URB_Status = USBH_LL_GetURBState(phost, MTP_Handle->DataOutPipe); if(URB_Status == USBH_URB_DONE) { /* Adjudt Data pointer and data length */ if(MTP_Handle->ptp.data_length > MTP_Handle->DataOutEpSize) { MTP_Handle->ptp.data_ptr += MTP_Handle->DataOutEpSize; MTP_Handle->ptp.data_length -= MTP_Handle->DataOutEpSize; MTP_Handle->ptp.data_packet += MTP_Handle->DataOutEpSize; if(MTP_Handle->ptp.data_packet >= PTP_USB_BULK_PAYLOAD_LEN_READ) { PTP_BufferFullCallback (phost); MTP_Handle->ptp.data_packet = 0; MTP_Handle->ptp.iteration++; } } else { MTP_Handle->ptp.data_length = 0; } /* More Data To be Sent */ if(MTP_Handle->ptp.data_length > 0) { USBH_BulkSendData (phost, MTP_Handle->ptp.data_ptr, MTP_Handle->DataOutEpSize , MTP_Handle->DataOutPipe, 1); } else { /* If value was 0, and successful transfer, then change the state */ MTP_Handle->ptp.state = PTP_RESPONSE_STATE; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_NOTREADY) { /* Re-send same data */ MTP_Handle->ptp.state = PTP_DATA_OUT_PHASE_STATE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { MTP_Handle->ptp.state = PTP_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case PTP_DATA_IN_PHASE_STATE: /* Send first packet */ USBH_BulkReceiveData (phost, MTP_Handle->ptp.data_ptr, MTP_Handle->DataInEpSize, MTP_Handle->DataInPipe); MTP_Handle->ptp.state = PTP_DATA_IN_PHASE_WAIT_STATE; break; case PTP_DATA_IN_PHASE_WAIT_STATE: URB_Status = USBH_LL_GetURBState(phost, MTP_Handle->DataInPipe); if(URB_Status == USBH_URB_DONE) { len = USBH_LL_GetLastXferSize (phost, MTP_Handle->DataInPipe); if( MTP_Handle->ptp.data_packet_counter++ == 0) { /* This is the first packet; so retrieve exact data length from payload */ MTP_Handle->ptp.data_length = *(uint32_t*)(MTP_Handle->ptp.data_ptr); MTP_Handle->ptp.iteration = 0; } if((len >= MTP_Handle->DataInEpSize) && (MTP_Handle->ptp.data_length > 0)) { MTP_Handle->ptp.data_ptr += len; MTP_Handle->ptp.data_length -= len; MTP_Handle->ptp.data_packet += len; if(MTP_Handle->ptp.data_packet >= PTP_USB_BULK_PAYLOAD_LEN_READ) { PTP_BufferFullCallback (phost); MTP_Handle->ptp.data_packet = 0; MTP_Handle->ptp.iteration++; } /* Continue receiving data*/ USBH_BulkReceiveData (phost, MTP_Handle->ptp.data_ptr, MTP_Handle->DataInEpSize, MTP_Handle->DataInPipe); } else { MTP_Handle->ptp.data_length -= len; MTP_Handle->ptp.state = PTP_RESPONSE_STATE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } } else if(URB_Status == USBH_URB_STALL) { MTP_Handle->ptp.state = PTP_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case PTP_RESPONSE_STATE: USBH_BulkReceiveData (phost, (uint8_t*)&(MTP_Handle->ptp.resp_container), PTP_USB_BULK_REQ_RESP_MAX_LEN , MTP_Handle->DataInPipe); MTP_Handle->ptp.state = PTP_RESPONSE_WAIT_STATE; break; case PTP_RESPONSE_WAIT_STATE: URB_Status = USBH_LL_GetURBState(phost, MTP_Handle->DataInPipe); if(URB_Status == USBH_URB_DONE) { USBH_PTP_GetResponse (phost, &ptp_container); if(ptp_container.Code == PTP_RC_OK) { status = USBH_OK; } else { status = USBH_FAIL; } MTP_Handle->ptp.req_state = PTP_REQ_SEND; } else if(URB_Status == USBH_URB_STALL) { MTP_Handle->ptp.state = PTP_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case PTP_ERROR: MTP_Handle->ptp.req_state = PTP_REQ_SEND; break; default: break; } return status; } /** * @brief USBH_PTP_OpenSession * Open a new session * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_SendRequest (USBH_HandleTypeDef *phost, PTP_ContainerTypedef *req) { USBH_StatusTypeDef status = USBH_OK; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; /* Clear PTP Data container*/ USBH_memset(&(MTP_Handle->ptp.op_container), 0, sizeof(PTP_OpContainerTypedef)); /* build appropriate USB container */ MTP_Handle->ptp.op_container.length = PTP_USB_BULK_REQ_LEN- (sizeof(uint32_t)*(5-req->Nparam)); MTP_Handle->ptp.op_container.type = PTP_USB_CONTAINER_COMMAND; MTP_Handle->ptp.op_container.code = req->Code; MTP_Handle->ptp.op_container.trans_id = req->Transaction_ID; MTP_Handle->ptp.op_container.param1 = req->Param1; MTP_Handle->ptp.op_container.param2 = req->Param2; MTP_Handle->ptp.op_container.param3 = req->Param3; MTP_Handle->ptp.op_container.param4 = req->Param4; MTP_Handle->ptp.op_container.param5 = req->Param5; return status; } /** * @brief USBH_PTP_OpenSession * Open a new session * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetResponse (USBH_HandleTypeDef *phost, PTP_ContainerTypedef *resp) { USBH_StatusTypeDef status = USBH_OK; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; /* build an appropriate PTPContainer */ resp->Code = MTP_Handle->ptp.resp_container.code; resp->SessionID = MTP_Handle->ptp.session_id; resp->Transaction_ID = MTP_Handle->ptp.resp_container.trans_id; resp->Param1 = MTP_Handle->ptp.resp_container.param1; resp->Param2 = MTP_Handle->ptp.resp_container.param2; resp->Param3 = MTP_Handle->ptp.resp_container.param3; resp->Param4 = MTP_Handle->ptp.resp_container.param4; resp->Param5 = MTP_Handle->ptp.resp_container.param5; return status; } /** * @brief The function informs user that data buffer is full * @param phost: host handle * @retval None */ void PTP_BufferFullCallback(USBH_HandleTypeDef *phost) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; switch (MTP_Handle->ptp.data_container.code) { case PTP_OC_GetDeviceInfo: PTP_DecodeDeviceInfo (phost, &(MTP_Handle->info.devinfo)); break; case PTP_OC_GetPartialObject: case PTP_OC_GetObject: /* first packet is in the PTP data payload buffer */ if(MTP_Handle->ptp.iteration == 0) { /* copy it to object */ USBH_memcpy(MTP_Handle->ptp.object_ptr, MTP_Handle->ptp.data_container.payload.data, PTP_USB_BULK_PAYLOAD_LEN_READ); /* next packet should be directly copied to object */ MTP_Handle->ptp.data_ptr = (MTP_Handle->ptp.object_ptr + PTP_USB_BULK_PAYLOAD_LEN_READ); } break; case PTP_OC_SendObject: /* first packet is in the PTP data payload buffer */ if(MTP_Handle->ptp.iteration == 0) { /* next packet should be directly copied to object */ MTP_Handle->ptp.data_ptr = (MTP_Handle->ptp.object_ptr + PTP_USB_BULK_PAYLOAD_LEN_READ); } break; default: break; } } /** * @brief PTP_GetDeviceInfo * Gets device info dataset and fills deviceinfo structure. * @param phost: Host handle * @param dev_info: Device info structure * @retval None */ static void PTP_DecodeDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint8_t *data = MTP_Handle->ptp.data_container.payload.data; uint32_t totallen; uint16_t len; /* Max device info is PTP_USB_BULK_HS_MAX_PACKET_LEN_READ */ USBH_DbgLog (" MTP device info size exceeds internal buffer size.\ only available data are decoded."); if(MTP_Handle->ptp.iteration == 0) { dev_info->StandardVersion = LE16(&data[PTP_di_StandardVersion]); dev_info->VendorExtensionID = LE32(&data[PTP_di_VendorExtensionID]); dev_info->VendorExtensionVersion = LE16(&data[PTP_di_VendorExtensionVersion]); PTP_GetString(dev_info->VendorExtensionDesc, &data[PTP_di_VendorExtensionDesc], &len); totallen=len*2+1; dev_info->FunctionalMode = LE16(&data[PTP_di_FunctionalMode+totallen]); dev_info->OperationsSupported_len = PTP_GetArray16 ((uint16_t *)&dev_info->OperationsSupported, data, PTP_di_OperationsSupported+totallen); totallen=totallen+dev_info->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t); dev_info->EventsSupported_len = PTP_GetArray16 ((uint16_t *)&dev_info->EventsSupported, data, PTP_di_OperationsSupported+totallen); totallen=totallen+dev_info->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t); dev_info->DevicePropertiesSupported_len = PTP_GetArray16 ((uint16_t *)&dev_info->DevicePropertiesSupported, data, PTP_di_OperationsSupported+totallen); totallen=totallen+dev_info->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t); dev_info->CaptureFormats_len = PTP_GetArray16 ((uint16_t *)&dev_info->CaptureFormats, data, PTP_di_OperationsSupported+totallen); totallen=totallen+dev_info->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t); dev_info->ImageFormats_len = PTP_GetArray16 ((uint16_t *)&dev_info->ImageFormats, data, PTP_di_OperationsSupported+totallen); totallen=totallen+dev_info->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t); PTP_GetString(dev_info->Manufacturer, &data[PTP_di_OperationsSupported+totallen], &len); totallen+=len*2+1; PTP_GetString(dev_info->Model, &data[PTP_di_OperationsSupported+totallen], &len); totallen+=len*2+1; PTP_GetString(dev_info->DeviceVersion, &data[PTP_di_OperationsSupported+totallen], &len); totallen+=len*2+1; PTP_GetString(dev_info->SerialNumber, &data[PTP_di_OperationsSupported+totallen], &len); } } /** * @brief PTP_GetStorageIDs * Gets Storage Ids and fills stor_ids structure. * @param phost: Host handle * @param stor_ids: Storage IDsstructure * @retval None */ static void PTP_GetStorageIDs (USBH_HandleTypeDef *phost, PTP_StorageIDsTypedef *stor_ids) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint8_t *data = MTP_Handle->ptp.data_container.payload.data; stor_ids->n = PTP_GetArray32 (stor_ids->Storage, data, 0); } /** * @brief PTP_GetStorageInfo * Gets Storage Info and fills stor_info structure. * @param phost: Host handle * @param stor_ids: Storage IDsstructure * @retval None */ static void PTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint32_t storage_id, PTP_StorageInfoTypedef *stor_info) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint8_t *data = MTP_Handle->ptp.data_container.payload.data; uint16_t len; stor_info->StorageType=LE16(&data[PTP_si_StorageType]); stor_info->FilesystemType=LE16(&data[PTP_si_FilesystemType]); stor_info->AccessCapability=LE16(&data[PTP_si_AccessCapability]); stor_info->MaxCapability=LE64(&data[PTP_si_MaxCapability]); stor_info->FreeSpaceInBytes=LE64(&data[PTP_si_FreeSpaceInBytes]); stor_info->FreeSpaceInImages=LE32(&data[PTP_si_FreeSpaceInImages]); PTP_GetString(stor_info->StorageDescription, &data[PTP_si_StorageDescription], &len); PTP_GetString(stor_info->VolumeLabel, &data[PTP_si_StorageDescription+len*2+1], &len); } /** * @brief PTP_GetObjectInfo * Gets objectInfo and fills object_info structure. * @param phost: Host handle * @param object_info: object info structure * @retval None */ static void PTP_GetObjectInfo (USBH_HandleTypeDef *phost, PTP_ObjectInfoTypedef *object_info) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint8_t *data = MTP_Handle->ptp.data_container.payload.data; uint16_t filenamelen; object_info->StorageID=LE32(&data[PTP_oi_StorageID]); object_info->ObjectFormat=LE16(&data[PTP_oi_ObjectFormat]); object_info->ProtectionStatus=LE16(&data[PTP_oi_ProtectionStatus]); object_info->ObjectCompressedSize=LE32(&data[PTP_oi_ObjectCompressedSize]); /* For Samsung Galaxy */ if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0)) { data += 4; } object_info->ThumbFormat=LE16(&data[PTP_oi_ThumbFormat]); object_info->ThumbCompressedSize=LE32(&data[PTP_oi_ThumbCompressedSize]); object_info->ThumbPixWidth=LE32(&data[PTP_oi_ThumbPixWidth]); object_info->ThumbPixHeight=LE32(&data[PTP_oi_ThumbPixHeight]); object_info->ImagePixWidth=LE32(&data[PTP_oi_ImagePixWidth]); object_info->ImagePixHeight=LE32(&data[PTP_oi_ImagePixHeight]); object_info->ImageBitDepth=LE32(&data[PTP_oi_ImageBitDepth]); object_info->ParentObject=LE32(&data[PTP_oi_ParentObject]); object_info->AssociationType=LE16(&data[PTP_oi_AssociationType]); object_info->AssociationDesc=LE32(&data[PTP_oi_AssociationDesc]); object_info->SequenceNumber=LE32(&data[PTP_oi_SequenceNumber]); PTP_GetString(object_info->Filename, &data[PTP_oi_filenamelen], &filenamelen); } /** * @brief PTP_GetObjectPropDesc * Gets objectInfo and fills object_info structure. * @param phost: Host handle * @param opd: object prop descriptor structure * @retval None */ static void PTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, PTP_ObjectPropDescTypeDef *opd, uint32_t opdlen) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint8_t *data = MTP_Handle->ptp.data_container.payload.data; uint32_t offset = 0, i; opd->ObjectPropertyCode=LE16(&data[PTP_opd_ObjectPropertyCode]); opd->DataType=LE16(&data[PTP_opd_DataType]); opd->GetSet=*(uint8_t *)(&data[PTP_opd_GetSet]); offset = PTP_opd_FactoryDefaultValue; PTP_GetDevicePropValue (phost, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType); opd->GroupCode=LE32(&data[offset]); offset+=sizeof(uint32_t); opd->FormFlag=*(uint8_t *)(&data[offset]); offset+=sizeof(uint8_t); switch (opd->FormFlag) { case PTP_OPFF_Range: PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType); PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType); PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType); break; case PTP_OPFF_Enumeration: opd->FORM.Enum.NumberOfValues = LE16(&data[offset]); offset+=sizeof(uint16_t); for (i=0 ; i < opd->FORM.Enum.NumberOfValues ; i++) { PTP_GetDevicePropValue(phost, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType); } break; default: break; } } /** * @brief PTP_GetDevicePropValue * Gets objectInfo and fills object_info structure. * @param phost: Host handle * @param opd: object prop descriptor structure * @retval None */ static void PTP_GetDevicePropValue(USBH_HandleTypeDef *phost, uint32_t *offset, uint32_t total, PTP_PropertyValueTypedef* value, uint16_t datatype) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint8_t *data = MTP_Handle->ptp.data_container.payload.data; uint16_t len; switch (datatype) { case PTP_DTC_INT8: value->i8 = *(uint8_t *)&(data[*offset]); *offset += 1; break; case PTP_DTC_UINT8: value->u8 = *(uint8_t *)&(data[*offset]); *offset += 1; break; case PTP_DTC_INT16: value->i16 = LE16(&(data[*offset])); *offset += 2; break; case PTP_DTC_UINT16: value->u16 = LE16(&(data[*offset])); *offset += 2; break; case PTP_DTC_INT32: value->i32 = LE32(&(data[*offset])); *offset += 4; break; case PTP_DTC_UINT32: value->u32 = LE32(&(data[*offset])); *offset += 4; break; case PTP_DTC_INT64: value->i64 = LE64(&(data[*offset])); *offset += 8; break; case PTP_DTC_UINT64: value->u64 = LE64(&(data[*offset])); *offset += 8; break; case PTP_DTC_UINT128: *offset += 16; break; case PTP_DTC_INT128: *offset += 16; break; case PTP_DTC_STR: PTP_GetString((uint8_t *)value->str, (uint8_t *)&(data[*offset]), &len); *offset += len*2+1; break; default: break; } } /** * @brief PTP_GetDevicePropValue * Gets objectInfo and fills object_info structure. * @param phost: Host handle * @param opd: object prop descriptor structure * @retval None */ static uint32_t PTP_GetObjectPropList (USBH_HandleTypeDef *phost, MTP_PropertiesTypedef *props, uint32_t len) { MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; uint8_t *data = MTP_Handle->ptp.data_container.payload.data; uint32_t prop_count; uint32_t offset = 0, i; prop_count = LE32(data); if (prop_count == 0) { return 0; } data += sizeof(uint32_t); len -= sizeof(uint32_t); for (i = 0; i < prop_count; i++) { if (len <= 0) { return 0; } props[i].ObjectHandle = LE32(data); data += sizeof(uint32_t); len -= sizeof(uint32_t); props[i].property = LE16(data); data += sizeof(uint16_t); len -= sizeof(uint16_t); props[i].datatype = LE16(data); data += sizeof(uint16_t); len -= sizeof(uint16_t); offset = 0; PTP_GetDevicePropValue(phost, &offset, len, &props[i].propval, props[i].datatype); data += offset; len -= offset; } return prop_count; } /** * @brief PTP_GetString * Gets SCII String from. * @param str: ascii string * @param data: Device info structure * @retval None */ static void PTP_GetString (uint8_t *str, uint8_t* data, uint16_t *len) { uint16_t strlength; uint16_t idx; *len = data[0]; strlength = 2 * data[0]; data ++; /* Adjust the offset ignoring the String Len */ for (idx = 0; idx < strlength; idx+=2 ) { /* Copy Only the string and ignore the UNICODE ID, hence add the src */ *str = data[idx]; str++; } *str = 0; /* mark end of string */ } /** * @brief PTP_GetString * Gets SCII String from. * @param str: ascii string * @param data: Device info structure * @retval None */ static uint32_t PTP_GetArray16 (uint16_t *array, uint8_t *data, uint32_t offset) { uint32_t size, idx = 0; size=LE32(&data[offset]); while (size > idx) { array[idx] = LE16(&data[offset+(sizeof(uint16_t)*(idx+2))]); idx++; } return size; } /** * @brief PTP_GetString * Gets SCII String from. * @param str: ascii string * @param data: Device info structure * @retval None */ static uint32_t PTP_GetArray32 (uint32_t *array, uint8_t *data, uint32_t offset) { uint32_t size, idx = 0; size=LE32(&data[offset]); while (size > idx) { array[idx] = LE32(&data[offset+(sizeof(uint32_t)*(idx+1))]); idx++; } return size; } /******************************************************************************* PTP Requests *******************************************************************************/ /** * @brief USBH_PTP_OpenSession * Open a new session * @param phost: Host handle * @param session: Session ID (MUST BE > 0) * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_OpenSession (USBH_HandleTypeDef *phost, uint32_t session) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Init session params */ MTP_Handle->ptp.transaction_id = 0x00000000; MTP_Handle->ptp.session_id = session; MTP_Handle->ptp.flags = PTP_DP_NODATA; /* Fill operation request params */ ptp_container.Code = PTP_OC_OpenSession; ptp_container.SessionID = session; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = session; ptp_container.Nparam = 1; /* convert request packet inti USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); break; default: break; } return status; } /** * @brief USBH_PTP_GetDevicePropDesc * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetDevicePropDesc (USBH_HandleTypeDef *phost, uint16_t propcode, PTP_DevicePropDescTypdef* devicepropertydesc) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; uint8_t *data = MTP_Handle->ptp.data_container.payload.data; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetDevicePropDesc; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = propcode; ptp_container.Nparam = 1; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { devicepropertydesc->DevicePropertyCode = LE16(&data[PTP_dpd_DevicePropertyCode]); devicepropertydesc->DataType = LE16(&data[PTP_dpd_DataType]); devicepropertydesc->GetSet = *(uint8_t *)(&data[PTP_dpd_GetSet]); devicepropertydesc->FormFlag = PTP_DPFF_None; } break; default: break; } return status; } /** * @brief USBH_PTP_GetDeviceInfo * Gets device info dataset and fills deviceinfo structure. * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetDeviceInfo (USBH_HandleTypeDef *phost, PTP_DeviceInfoTypedef *dev_info) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetDeviceInfo; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Nparam = 0; /* convert request packet inti USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { PTP_DecodeDeviceInfo (phost, dev_info); } break; default: break; } return status; } /** * @brief USBH_PTP_GetStorageIds * Gets device info dataset and fills deviceinfo structure. * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetStorageIds (USBH_HandleTypeDef *phost, PTP_StorageIDsTypedef *storage_ids) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetStorageIDs; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Nparam = 0; /* convert request packet inti USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { PTP_GetStorageIDs (phost, storage_ids); } break; default: break; } return status; } /** * @brief USBH_PTP_GetDeviceInfo * Gets device info dataset and fills deviceinfo structure. * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetStorageInfo (USBH_HandleTypeDef *phost, uint32_t storage_id, PTP_StorageInfoTypedef *storage_info) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetStorageInfo; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = storage_id; ptp_container.Nparam = 1; /* convert request packet inti USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { PTP_GetStorageInfo (phost, storage_id, storage_info); } break; default: break; } return status; } /** * @brief USBH_PTP_GetNumObjects * Gets device info dataset and fills deviceinfo structure. * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetNumObjects (USBH_HandleTypeDef *phost, uint32_t storage_id, uint32_t objectformatcode, uint32_t associationOH, uint32_t* numobs) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_NODATA; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetNumObjects; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = storage_id; ptp_container.Param2 = objectformatcode; ptp_container.Param3 = associationOH; ptp_container.Nparam = 3; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { *numobs = MTP_Handle->ptp.resp_container.param1; } break; default: break; } return status; } /** * @brief USBH_PTP_GetObjectHandles * Gets device info dataset and fills deviceinfo structure. * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetObjectHandles (USBH_HandleTypeDef *phost, uint32_t storage_id, uint32_t objectformatcode, uint32_t associationOH, PTP_ObjectHandlesTypedef* objecthandles) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetObjectHandles; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = storage_id; ptp_container.Param2 = objectformatcode; ptp_container.Param3 = associationOH; ptp_container.Nparam = 3; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { objecthandles->n = PTP_GetArray32 (objecthandles->Handler, MTP_Handle->ptp.data_container.payload.data, 0); } break; default: break; } return status; } /** * @brief USBH_PTP_GetObjectInfo * Gets objert info * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetObjectInfo (USBH_HandleTypeDef *phost, uint32_t handle, PTP_ObjectInfoTypedef* object_info) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetObjectInfo; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = handle; ptp_container.Nparam = 1; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { PTP_GetObjectInfo (phost, object_info); } break; default: break; } return status; } /** * @brief USBH_PTP_DeleteObject * Delete an object. * @param phost: Host handle * @param handle : Object Handle * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_DeleteObject (USBH_HandleTypeDef *phost, uint32_t handle, uint32_t objectformatcode) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_NODATA; /* Fill operation request params */ ptp_container.Code = PTP_OC_DeleteObject; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = handle; ptp_container.Param2 = objectformatcode; ptp_container.Nparam = 2; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); break; default: break; } return status; } /** * @brief USBH_PTP_GetObject * Gets object * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* set object control params */ MTP_Handle->ptp.object_ptr = object; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetObject; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = handle; ptp_container.Nparam = 1; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { /* first packet is in the PTP data payload buffer */ if(MTP_Handle->ptp.iteration == 0) { /* copy it to object */ USBH_memcpy(MTP_Handle->ptp.object_ptr, MTP_Handle->ptp.data_container.payload.data, PTP_USB_BULK_PAYLOAD_LEN_READ); } } break; default: break; } return status; } /** * @brief USBH_PTP_GetPartialObject * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetPartialObject(USBH_HandleTypeDef *phost, uint32_t handle, uint32_t offset, uint32_t maxbytes, uint8_t *object, uint32_t *len) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* set object control params */ MTP_Handle->ptp.object_ptr = object; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetPartialObject; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = handle; ptp_container.Param2 = offset; ptp_container.Param3 = maxbytes; ptp_container.Nparam = 3; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { *len = MTP_Handle->ptp.resp_container.param1; /* first packet is in the PTP data payload buffer */ if(MTP_Handle->ptp.iteration == 0) { /* copy it to object */ USBH_memcpy(MTP_Handle->ptp.object_ptr, MTP_Handle->ptp.data_container.payload.data, *len); } } break; default: break; } return status; } /** * @brief USBH_PTP_GetObjectPropsSupported * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetObjectPropsSupported (USBH_HandleTypeDef *phost, uint16_t ofc, uint32_t *propnum, uint16_t *props) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetObjectPropsSupported; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = ofc; ptp_container.Nparam = 1; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { *propnum = PTP_GetArray16 (props, MTP_Handle->ptp.data_container.payload.data, 0); } break; default: break; } return status; } /** * @brief USBH_PTP_GetObjectPropDesc * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetObjectPropDesc (USBH_HandleTypeDef *phost, uint16_t opc, uint16_t ofc, PTP_ObjectPropDescTypeDef *opd) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* Fill operation request params */ ptp_container.Code = PTP_OC_GetObjectPropDesc; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = opc; ptp_container.Param2 = ofc; ptp_container.Nparam = 2; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { PTP_GetObjectPropDesc(phost, opd, MTP_Handle->ptp.data_length); } break; default: break; } return status; } /** * @brief USBH_PTP_GetObjectPropList * Gets object partially * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_GetObjectPropList (USBH_HandleTypeDef *phost, uint32_t handle, MTP_PropertiesTypedef *pprops, uint32_t *nrofprops) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_GETDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_length = 0; MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; /* copy first packet of the object into data container */ USBH_memcpy(MTP_Handle->ptp.data_container.payload.data, MTP_Handle->ptp.object_ptr, PTP_USB_BULK_PAYLOAD_LEN_READ); /* Fill operation request params */ ptp_container.Code = PTP_OC_GetObjPropList; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Param1 = handle; ptp_container.Param2 = 0x00000000U; /* 0x00000000U should be "all formats" */ ptp_container.Param3 = 0xFFFFFFFFU; /* 0xFFFFFFFFU should be "all properties" */ ptp_container.Param4 = 0x00000000U; ptp_container.Param5 = 0xFFFFFFFFU; /* Return full tree below the Param1 handle */ ptp_container.Nparam = 5; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); if(status == USBH_OK) { PTP_GetObjectPropList (phost, pprops, MTP_Handle->ptp.data_length); } break; default: break; } return status; } /** * @brief USBH_PTP_SendObject * Send an object * @param phost: Host handle * @param dev_info: Device info structure * @retval USBH Status */ USBH_StatusTypeDef USBH_PTP_SendObject (USBH_HandleTypeDef *phost, uint32_t handle, uint8_t *object, uint32_t size) { USBH_StatusTypeDef status = USBH_BUSY; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; PTP_ContainerTypedef ptp_container; switch(MTP_Handle->ptp.req_state) { case PTP_REQ_SEND: /* Set operation request type */ MTP_Handle->ptp.flags = PTP_DP_SENDDATA; MTP_Handle->ptp.data_ptr = (uint8_t *)&(MTP_Handle->ptp.data_container); MTP_Handle->ptp.data_packet_counter = 0; MTP_Handle->ptp.data_packet = 0; MTP_Handle->ptp.iteration = 0; /* set object control params */ MTP_Handle->ptp.object_ptr = object; MTP_Handle->ptp.data_length = size; /* Fill operation request params */ ptp_container.Code = PTP_OC_SendObject; ptp_container.SessionID = MTP_Handle->ptp.session_id; ptp_container.Transaction_ID = MTP_Handle->ptp.transaction_id ++; ptp_container.Nparam = 0; /* convert request packet into USB raw packet*/ USBH_PTP_SendRequest (phost, &ptp_container); /* Setup State machine and start transfer */ MTP_Handle->ptp.state = PTP_OP_REQUEST_STATE; MTP_Handle->ptp.req_state = PTP_REQ_WAIT; status = USBH_BUSY; break; case PTP_REQ_WAIT: status = USBH_PTP_Process(phost); break; default: break; } return status; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/Template/000077500000000000000000000000001357706137100224505ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/Template/Inc/000077500000000000000000000000001357706137100231615ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/Template/Inc/usbh_template.h000066400000000000000000000050031357706137100261640ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_mtp.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file contains all the prototypes for the usbh_template.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_TEMPLATE_CORE_H #define __USBH_TEMPLATE_CORE_H /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_TEMPLATE_CLASS * @{ */ /** @defgroup USBH_TEMPLATE_CORE * @brief This file is the Header file for USBH_TEMPLATE_CORE.c * @{ */ /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Exported_Types * @{ */ /* States for TEMPLATE State Machine */ /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Exported_Defines * @{ */ /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Exported_Variables * @{ */ extern USBH_ClassTypeDef TEMPLATE_Class; #define USBH_TEMPLATE_CLASS &TEMPLATE_Class /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_TEMPLATE_IOProcess (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_TEMPLATE_Init (USBH_HandleTypeDef *phost); /** * @} */ #endif /* __USBH_TEMPLATE_CORE_H */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Class/Template/Src/000077500000000000000000000000001357706137100231775ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Class/Template/Src/usbh_template.c000066400000000000000000000117341357706137100262050ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_mtp.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file is the MTP Layer Handlers for USB Host MTP class. * * ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_template.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_CLASS * @{ */ /** @addtogroup USBH_TEMPLATE_CLASS * @{ */ /** @defgroup USBH_TEMPLATE_CORE * @brief This file includes TEMPLATE Layer Handlers for USB Host TEMPLATE class. * @{ */ /** @defgroup USBH_TEMPLATE_CORE_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_TEMPLATE_InterfaceInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_TEMPLATE_InterfaceDeInit (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_TEMPLATE_Process(USBH_HandleTypeDef *phost); static USBH_StatusTypeDef USBH_TEMPLATE_ClassRequest (USBH_HandleTypeDef *phost); USBH_ClassTypeDef TEMPLATE_Class = { "TEMPLATE", USB_TEMPLATE_CLASS, USBH_TEMPLATE_InterfaceInit, USBH_TEMPLATE_InterfaceDeInit, USBH_TEMPLATE_ClassRequest, USBH_TEMPLATE_Process }; /** * @} */ /** @defgroup USBH_TEMPLATE_CORE_Private_Functions * @{ */ /** * @brief USBH_TEMPLATE_InterfaceInit * The function init the TEMPLATE class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_TEMPLATE_InterfaceInit (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_TEMPLATE_InterfaceDeInit * The function DeInit the Pipes used for the TEMPLATE class. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_TEMPLATE_InterfaceDeInit (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_TEMPLATE_ClassRequest * The function is responsible for handling Standard requests * for TEMPLATE class. * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_TEMPLATE_ClassRequest (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_TEMPLATE_Process * The function is for managing state machine for TEMPLATE data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_TEMPLATE_Process (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_TEMPLATE_Init * The function Initialize the TEMPLATE function * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_TEMPLATE_Init (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef Status = USBH_BUSY; #if (USBH_USE_OS == 1) osEvent event; event = osMessageGet( phost->class_ready_event, osWaitForever ); if( event.status == osEventMessage ) { if(event.value.v == USBH_CLASS_EVENT) { #else while ((Status == USBH_BUSY) || (Status == USBH_FAIL)) { /* Host background process */ USBH_Process(phost); if(phost->gState == HOST_CLASS) { #endif Status = USBH_OK; } } return Status; } /** * @brief USBH_TEMPLATE_IOProcess * TEMPLATE TEMPLATE process * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_TEMPLATE_IOProcess (USBH_HandleTypeDef *phost) { if (phost->device.is_connected == 1) { if(phost->gState == HOST_CLASS) { USBH_TEMPLATE_Process(phost); } } return USBH_OK; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/000077500000000000000000000000001357706137100205205ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Core/Inc/000077500000000000000000000000001357706137100212315ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Core/Inc/usbh_conf_template.h000066400000000000000000000072211357706137100252450ustar00rootroot00000000000000/** ****************************************************************************** * @file USBH_conf.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief General low level driver configuration ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USBH_CONF__H__ #define __USBH_CONF__H__ #include "stm32f4xx.h" #include #include #include /* Includes ------------------------------------------------------------------*/ /** @addtogroup USBH_OTG_DRIVER * @{ */ /** @defgroup USBH_CONF * @brief usb otg low level driver configuration file * @{ */ /** @defgroup USBH_CONF_Exported_Defines * @{ */ #define USBH_MAX_NUM_ENDPOINTS 2 #define USBH_MAX_NUM_INTERFACES 2 #define USBH_MAX_NUM_CONFIGURATION 1 #define USBH_KEEP_CFG_DESCRIPTOR 1 #define USBH_MAX_NUM_SUPPORTED_CLASS 1 #define USBH_MAX_SIZE_CONFIGURATION 0x200 #define USBH_MAX_DATA_BUFFER 0x200 #define USBH_DEBUG_LEVEL 2 #define USBH_USE_OS 1 /** @defgroup USBH_Exported_Macros * @{ */ /* Memory management macros */ #define USBH_malloc malloc #define USBH_free free #define USBH_memset memset #define USBH_memcpy memcpy /* DEBUG macros */ #if (USBH_DEBUG_LEVEL > 0) #define USBH_UsrLog(...) printf(__VA_ARGS__);\ printf("\n"); #else #define USBH_UsrLog(...) #endif #if (USBH_DEBUG_LEVEL > 1) #define USBH_ErrLog(...) printf("ERROR: ") ;\ printf(__VA_ARGS__);\ printf("\n"); #else #define USBH_ErrLog(...) #endif #if (USBH_DEBUG_LEVEL > 2) #define USBH_DbgLog(...) printf("DEBUG : ") ;\ printf(__VA_ARGS__);\ printf("\n"); #else #define USBH_DbgLog(...) #endif /** * @} */ /** * @} */ /** @defgroup USBH_CONF_Exported_Types * @{ */ /** * @} */ /** @defgroup USBH_CONF_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_CONF_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_CONF_Exported_FunctionsPrototype * @{ */ /** * @} */ #endif //__USBH_CONF__H__ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Inc/usbh_core.h000066400000000000000000000124051357706137100233550ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_core.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief Header file for usbh_core.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_CORE_H #define __USBH_CORE_H /* Includes ------------------------------------------------------------------*/ #include "usbh_conf.h" #include "usbh_def.h" #include "usbh_ioreq.h" #include "usbh_pipes.h" #include "usbh_ctlreq.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_CORE * @brief This file is the Header file for usbh_core.c * @{ */ /** @defgroup USBH_CORE_Exported_Defines * @{ */ /** * @} */ #define HOST_USER_SELECT_CONFIGURATION 1 #define HOST_USER_CLASS_ACTIVE 2 #define HOST_USER_CLASS_SELECTED 3 #define HOST_USER_CONNECTION 4 #define HOST_USER_DISCONNECTION 5 /** * @} */ /** @defgroup USBH_CORE_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_CORE_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_CORE_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id); USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass); USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface); uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, uint8_t Class, uint8_t SubClass, uint8_t Protocol); uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost); uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, uint8_t interface_number, uint8_t alt_settings); USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_Stop (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_Process (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_ReEnumerate (USBH_HandleTypeDef *phost); /* USBH Low Level Driver */ USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_LL_Start (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_LL_Disconnect (USBH_HandleTypeDef *phost); USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost); USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost); uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t ); USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t ); USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost, uint8_t, uint8_t, uint8_t, uint8_t , uint8_t, uint16_t ); USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t ); USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost, uint8_t, uint8_t,uint8_t, uint8_t, uint8_t*, uint16_t, uint8_t ); USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t ); #if (USBH_USE_OS == 1) USBH_StatusTypeDef USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost); #endif USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t , uint8_t ); uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t ); /* USBH Time base */ void USBH_Delay (uint32_t Delay); void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t ); void USBH_LL_IncTimer (USBH_HandleTypeDef *phost); /** * @} */ #endif /* __CORE_H */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Inc/usbh_ctlreq.h000066400000000000000000000100101357706137100237050ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_ctlreq.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief Header file for usbh_ctlreq.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_CTLREQ_H #define __USBH_CTLREQ_H /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_CTLREQ * @brief This file is the * @{ */ /** @defgroup USBH_CTLREQ_Exported_Defines * @{ */ /*Standard Feature Selector for clear feature command*/ #define FEATURE_SELECTOR_ENDPOINT 0X00 #define FEATURE_SELECTOR_DEVICE 0X01 #define INTERFACE_DESC_TYPE 0x04 #define ENDPOINT_DESC_TYPE 0x05 #define INTERFACE_DESC_SIZE 0x09 /** * @} */ /** @defgroup USBH_CTLREQ_Exported_Types * @{ */ /** * @} */ /** @defgroup USBH_CTLREQ_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_CTLREQ_Exported_Variables * @{ */ extern uint8_t USBH_CfgDesc[512]; /** * @} */ /** @defgroup USBH_CTLREQ_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length); USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost, uint8_t req_type, uint16_t value_idx, uint8_t* buff, uint16_t length ); USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length); USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost, uint8_t string_index, uint8_t *buff, uint16_t length); USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost, uint16_t configuration_value); USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost, uint16_t length); USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost, uint8_t DeviceAddress); USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost, uint8_t ep_num, uint8_t altSetting); USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost, uint8_t ep_num); USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr); /** * @} */ #endif /* __USBH_CTLREQ_H */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Inc/usbh_def.h000066400000000000000000000404321357706137100231640ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_def.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief Definitions used in the USB host library ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_DEF * @brief This file is includes USB descriptors * @{ */ #ifndef USBH_DEF_H #define USBH_DEF_H #include "usbh_conf.h" #ifndef NULL #define NULL ((void *)0) #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #define ValBit(VAR,POS) (VAR & (1 << POS)) #define SetBit(VAR,POS) (VAR |= (1 << POS)) #define ClrBit(VAR,POS) (VAR &= ((1 << POS)^255)) #define LE16(addr) (((uint16_t)(*((uint8_t *)(addr))))\ + (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) #define LE16S(addr) (uint16_t)(LE16((addr))) #define LE32(addr) ((((uint32_t)(*(((uint8_t *)(addr)) + 0))) + \ (((uint32_t)(*(((uint8_t *)(addr)) + 1))) << 8) + \ (((uint32_t)(*(((uint8_t *)(addr)) + 2))) << 16) + \ (((uint32_t)(*(((uint8_t *)(addr)) + 3))) << 24))) #define LE64(addr) ((((uint64_t)(*(((uint8_t *)(addr)) + 0))) + \ (((uint64_t)(*(((uint8_t *)(addr)) + 1))) << 8) +\ (((uint64_t)(*(((uint8_t *)(addr)) + 2))) << 16) +\ (((uint64_t)(*(((uint8_t *)(addr)) + 3))) << 24) +\ (((uint64_t)(*(((uint8_t *)(addr)) + 4))) << 32) +\ (((uint64_t)(*(((uint8_t *)(addr)) + 5))) << 40) +\ (((uint64_t)(*(((uint8_t *)(addr)) + 6))) << 48) +\ (((uint64_t)(*(((uint8_t *)(addr)) + 7))) << 56))) #define LE24(addr) ((((uint32_t)(*(((uint8_t *)(addr)) + 0))) + \ (((uint32_t)(*(((uint8_t *)(addr)) + 1))) << 8) + \ (((uint32_t)(*(((uint8_t *)(addr)) + 2))) << 16))) #define LE32S(addr) (int32_t)(LE32((addr))) #define USB_LEN_DESC_HDR 0x02 #define USB_LEN_DEV_DESC 0x12 #define USB_LEN_CFG_DESC 0x09 #define USB_LEN_IF_DESC 0x09 #define USB_LEN_EP_DESC 0x07 #define USB_LEN_OTG_DESC 0x03 #define USB_LEN_SETUP_PKT 0x08 /* bmRequestType :D7 Data Phase Transfer Direction */ #define USB_REQ_DIR_MASK 0x80 #define USB_H2D 0x00 #define USB_D2H 0x80 /* bmRequestType D6..5 Type */ #define USB_REQ_TYPE_STANDARD 0x00 #define USB_REQ_TYPE_CLASS 0x20 #define USB_REQ_TYPE_VENDOR 0x40 #define USB_REQ_TYPE_RESERVED 0x60 /* bmRequestType D4..0 Recipient */ #define USB_REQ_RECIPIENT_DEVICE 0x00 #define USB_REQ_RECIPIENT_INTERFACE 0x01 #define USB_REQ_RECIPIENT_ENDPOINT 0x02 #define USB_REQ_RECIPIENT_OTHER 0x03 /* Table 9-4. Standard Request Codes */ /* bRequest , Value */ #define USB_REQ_GET_STATUS 0x00 #define USB_REQ_CLEAR_FEATURE 0x01 #define USB_REQ_SET_FEATURE 0x03 #define USB_REQ_SET_ADDRESS 0x05 #define USB_REQ_GET_DESCRIPTOR 0x06 #define USB_REQ_SET_DESCRIPTOR 0x07 #define USB_REQ_GET_CONFIGURATION 0x08 #define USB_REQ_SET_CONFIGURATION 0x09 #define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SYNCH_FRAME 0x0C /* Table 9-5. Descriptor Types of USB Specifications */ #define USB_DESC_TYPE_DEVICE 1 #define USB_DESC_TYPE_CONFIGURATION 2 #define USB_DESC_TYPE_STRING 3 #define USB_DESC_TYPE_INTERFACE 4 #define USB_DESC_TYPE_ENDPOINT 5 #define USB_DESC_TYPE_DEVICE_QUALIFIER 6 #define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7 #define USB_DESC_TYPE_INTERFACE_POWER 8 #define USB_DESC_TYPE_HID 0x21 #define USB_DESC_TYPE_HID_REPORT 0x22 #define USB_DEVICE_DESC_SIZE 18 #define USB_CONFIGURATION_DESC_SIZE 9 #define USB_HID_DESC_SIZE 9 #define USB_INTERFACE_DESC_SIZE 9 #define USB_ENDPOINT_DESC_SIZE 7 /* Descriptor Type and Descriptor Index */ /* Use the following values when calling the function USBH_GetDescriptor */ #define USB_DESC_DEVICE ((USB_DESC_TYPE_DEVICE << 8) & 0xFF00) #define USB_DESC_CONFIGURATION ((USB_DESC_TYPE_CONFIGURATION << 8) & 0xFF00) #define USB_DESC_STRING ((USB_DESC_TYPE_STRING << 8) & 0xFF00) #define USB_DESC_INTERFACE ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00) #define USB_DESC_ENDPOINT ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00) #define USB_DESC_DEVICE_QUALIFIER ((USB_DESC_TYPE_DEVICE_QUALIFIER << 8) & 0xFF00) #define USB_DESC_OTHER_SPEED_CONFIGURATION ((USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8) & 0xFF00) #define USB_DESC_INTERFACE_POWER ((USB_DESC_TYPE_INTERFACE_POWER << 8) & 0xFF00) #define USB_DESC_HID_REPORT ((USB_DESC_TYPE_HID_REPORT << 8) & 0xFF00) #define USB_DESC_HID ((USB_DESC_TYPE_HID << 8) & 0xFF00) #define USB_EP_TYPE_CTRL 0x00 #define USB_EP_TYPE_ISOC 0x01 #define USB_EP_TYPE_BULK 0x02 #define USB_EP_TYPE_INTR 0x03 #define USB_EP_DIR_OUT 0x00 #define USB_EP_DIR_IN 0x80 #define USB_EP_DIR_MSK 0x80 #define USBH_MAX_PIPES_NBR 15 #define USBH_DEVICE_ADDRESS_DEFAULT 0 #define USBH_MAX_ERROR_COUNT 2 #define USBH_DEVICE_ADDRESS 1 /** * @} */ #define USBH_CONFIGURATION_DESCRIPTOR_SIZE (USB_CONFIGURATION_DESC_SIZE \ + USB_INTERFACE_DESC_SIZE\ + (USBH_MAX_NUM_ENDPOINTS * USB_ENDPOINT_DESC_SIZE)) #define CONFIG_DESC_wTOTAL_LENGTH (ConfigurationDescriptorData.ConfigDescfield.\ ConfigurationDescriptor.wTotalLength) typedef union { uint16_t w; struct BW { uint8_t msb; uint8_t lsb; } bw; } uint16_t_uint8_t; typedef union _USB_Setup { uint32_t d8[2]; struct _SetupPkt_Struc { uint8_t bmRequestType; uint8_t bRequest; uint16_t_uint8_t wValue; uint16_t_uint8_t wIndex; uint16_t_uint8_t wLength; } b; } USB_Setup_TypeDef; typedef struct _DescHeader { uint8_t bLength; uint8_t bDescriptorType; } USBH_DescHeader_t; typedef struct _DeviceDescriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdUSB; /* USB Specification Number which device complies too */ uint8_t bDeviceClass; uint8_t bDeviceSubClass; uint8_t bDeviceProtocol; /* If equal to Zero, each interface specifies its own class code if equal to 0xFF, the class code is vendor specified. Otherwise field is valid Class Code.*/ uint8_t bMaxPacketSize; uint16_t idVendor; /* Vendor ID (Assigned by USB Org) */ uint16_t idProduct; /* Product ID (Assigned by Manufacturer) */ uint16_t bcdDevice; /* Device Release Number */ uint8_t iManufacturer; /* Index of Manufacturer String Descriptor */ uint8_t iProduct; /* Index of Product String Descriptor */ uint8_t iSerialNumber; /* Index of Serial Number String Descriptor */ uint8_t bNumConfigurations; /* Number of Possible Configurations */ } USBH_DevDescTypeDef; typedef struct _EndpointDescriptor { uint8_t bLength; uint8_t bDescriptorType; uint8_t bEndpointAddress; /* indicates what endpoint this descriptor is describing */ uint8_t bmAttributes; /* specifies the transfer type. */ uint16_t wMaxPacketSize; /* Maximum Packet Size this endpoint is capable of sending or receiving */ uint8_t bInterval; /* is used to specify the polling interval of certain transfers. */ } USBH_EpDescTypeDef; typedef struct _InterfaceDescriptor { uint8_t bLength; uint8_t bDescriptorType; uint8_t bInterfaceNumber; uint8_t bAlternateSetting; /* Value used to select alternative setting */ uint8_t bNumEndpoints; /* Number of Endpoints used for this interface */ uint8_t bInterfaceClass; /* Class Code (Assigned by USB Org) */ uint8_t bInterfaceSubClass; /* Subclass Code (Assigned by USB Org) */ uint8_t bInterfaceProtocol; /* Protocol Code */ uint8_t iInterface; /* Index of String Descriptor Describing this interface */ USBH_EpDescTypeDef Ep_Desc[USBH_MAX_NUM_ENDPOINTS]; } USBH_InterfaceDescTypeDef; typedef struct _ConfigurationDescriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t wTotalLength; /* Total Length of Data Returned */ uint8_t bNumInterfaces; /* Number of Interfaces */ uint8_t bConfigurationValue; /* Value to use as an argument to select this configuration*/ uint8_t iConfiguration; /*Index of String Descriptor Describing this configuration */ uint8_t bmAttributes; /* D7 Bus Powered , D6 Self Powered, D5 Remote Wakeup , D4..0 Reserved (0)*/ uint8_t bMaxPower; /*Maximum Power Consumption */ USBH_InterfaceDescTypeDef Itf_Desc[USBH_MAX_NUM_INTERFACES]; } USBH_CfgDescTypeDef; /* Following USB Host status */ typedef enum { USBH_OK = 0, USBH_BUSY, USBH_FAIL, USBH_NOT_SUPPORTED, USBH_UNRECOVERED_ERROR, USBH_ERROR_SPEED_UNKNOWN, }USBH_StatusTypeDef; /** @defgroup USBH_CORE_Exported_Types * @{ */ typedef enum { USBH_SPEED_HIGH = 0, USBH_SPEED_FULL = 1, USBH_SPEED_LOW = 2, }USBH_SpeedTypeDef; /* Following states are used for gState */ typedef enum { HOST_IDLE =0, HOST_DEV_WAIT_FOR_ATTACHMENT, HOST_DEV_ATTACHED, HOST_DEV_DISCONNECTED, HOST_DETECT_DEVICE_SPEED, HOST_ENUMERATION, HOST_CLASS_REQUEST, HOST_INPUT, HOST_SET_CONFIGURATION, HOST_CHECK_CLASS, HOST_CLASS, HOST_SUSPENDED, HOST_ABORT_STATE, }HOST_StateTypeDef; /* Following states are used for EnumerationState */ typedef enum { ENUM_IDLE = 0, ENUM_GET_FULL_DEV_DESC, ENUM_SET_ADDR, ENUM_GET_CFG_DESC, ENUM_GET_FULL_CFG_DESC, ENUM_GET_MFC_STRING_DESC, ENUM_GET_PRODUCT_STRING_DESC, ENUM_GET_SERIALNUM_STRING_DESC, } ENUM_StateTypeDef; /* Following states are used for CtrlXferStateMachine */ typedef enum { CTRL_IDLE =0, CTRL_SETUP, CTRL_SETUP_WAIT, CTRL_DATA_IN, CTRL_DATA_IN_WAIT, CTRL_DATA_OUT, CTRL_DATA_OUT_WAIT, CTRL_STATUS_IN, CTRL_STATUS_IN_WAIT, CTRL_STATUS_OUT, CTRL_STATUS_OUT_WAIT, CTRL_ERROR, CTRL_STALLED, CTRL_COMPLETE }CTRL_StateTypeDef; /* Following states are used for RequestState */ typedef enum { CMD_IDLE =0, CMD_SEND, CMD_WAIT } CMD_StateTypeDef; typedef enum { USBH_URB_IDLE = 0, USBH_URB_DONE, USBH_URB_NOTREADY, USBH_URB_NYET, USBH_URB_ERROR, USBH_URB_STALL }USBH_URBStateTypeDef; typedef enum { USBH_PORT_EVENT = 1, USBH_URB_EVENT, USBH_CONTROL_EVENT, USBH_CLASS_EVENT, USBH_STATE_CHANGED_EVENT, } USBH_OSEventTypeDef; /* Control request structure */ typedef struct { uint8_t pipe_in; uint8_t pipe_out; uint8_t pipe_size; uint8_t *buff; uint16_t length; uint16_t timer; USB_Setup_TypeDef setup; CTRL_StateTypeDef state; uint8_t errorcount; } USBH_CtrlTypeDef; /* Attached device structure */ typedef struct { #if (USBH_KEEP_CFG_DESCRIPTOR == 1) uint8_t CfgDesc_Raw[USBH_MAX_SIZE_CONFIGURATION]; #endif uint8_t Data[USBH_MAX_DATA_BUFFER]; uint8_t address; uint8_t speed; __IO uint8_t is_connected; uint8_t current_interface; USBH_DevDescTypeDef DevDesc; USBH_CfgDescTypeDef CfgDesc; }USBH_DeviceTypeDef; struct _USBH_HandleTypeDef; /* USB Host Class structure */ typedef struct { const char *Name; uint8_t ClassCode; USBH_StatusTypeDef (*Init) (struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef (*DeInit) (struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef (*Requests) (struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef (*BgndProcess) (struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef (*SOFProcess) (struct _USBH_HandleTypeDef *phost); void* pData; } USBH_ClassTypeDef; /* USB Host handle structure */ typedef struct _USBH_HandleTypeDef { __IO HOST_StateTypeDef gState; /* Host State Machine Value */ ENUM_StateTypeDef EnumState; /* Enumeration state Machine */ CMD_StateTypeDef RequestState; USBH_CtrlTypeDef Control; USBH_DeviceTypeDef device; USBH_ClassTypeDef* pClass[USBH_MAX_NUM_SUPPORTED_CLASS]; USBH_ClassTypeDef* pActiveClass; uint32_t ClassNumber; uint32_t Pipes[15]; __IO uint32_t Timer; uint8_t id; void* pData; void (* pUser )(struct _USBH_HandleTypeDef *pHandle, uint8_t id); #if (USBH_USE_OS == 1) osMessageQId os_event; osThreadId thread; #endif } USBH_HandleTypeDef; #if defined ( __GNUC__ ) #ifndef __weak #define __weak __attribute__((weak)) #endif /* __weak */ #ifndef __packed #define __packed __attribute__((__packed__)) #endif /* __packed */ #endif /* __GNUC__ */ #endif /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Inc/usbh_ioreq.h000066400000000000000000000110441357706137100235420ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_ioreq.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief Header file for usbh_ioreq.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_IOREQ_H #define __USBH_IOREQ_H /* Includes ------------------------------------------------------------------*/ #include "usbh_conf.h" #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_IOREQ * @brief This file is the header file for usbh_ioreq.c * @{ */ /** @defgroup USBH_IOREQ_Exported_Defines * @{ */ #define USBH_PID_SETUP 0 #define USBH_PID_DATA 1 #define USBH_EP_CONTROL 0 #define USBH_EP_ISO 1 #define USBH_EP_BULK 2 #define USBH_EP_INTERRUPT 3 #define USBH_SETUP_PKT_SIZE 8 /** * @} */ /** @defgroup USBH_IOREQ_Exported_Types * @{ */ /** * @} */ /** @defgroup USBH_IOREQ_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_IOREQ_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_IOREQ_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost, uint8_t *buff, uint8_t hc_num); USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t hc_num, uint8_t do_ping ); USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t hc_num); USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t hc_num); USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t hc_num, uint8_t do_ping ); USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost, uint8_t *buff, uint8_t length, uint8_t hc_num); USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost, uint8_t *buff, uint8_t length, uint8_t hc_num); USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost, uint8_t *buff, uint32_t length, uint8_t hc_num); USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost, uint8_t *buff, uint32_t length, uint8_t hc_num); /** * @} */ #endif /* __USBH_IOREQ_H */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Inc/usbh_pipes.h000066400000000000000000000054431357706137100235510ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_PIPES.h * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief Header file for usbh_pipes.c ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive ----------------------------------------------*/ #ifndef __USBH_PIPES_H #define __USBH_PIPES_H /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_PIPES * @brief This file is the header file for usbh_PIPES.c * @{ */ /** @defgroup USBH_PIPES_Exported_Defines * @{ */ /** * @} */ /** @defgroup USBH_PIPES_Exported_Types * @{ */ /** * @} */ /** @defgroup USBH_PIPES_Exported_Macros * @{ */ /** * @} */ /** @defgroup USBH_PIPES_Exported_Variables * @{ */ /** * @} */ /** @defgroup USBH_PIPES_Exported_FunctionsPrototype * @{ */ USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost, uint8_t ch_num, uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps); USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe_num); uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost, uint8_t ep_addr); USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost, uint8_t idx); /** * @} */ #endif /* __USBH_PIPES_H */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Src/000077500000000000000000000000001357706137100212475ustar00rootroot00000000000000micropython-1.12/ports/stm32/usbhost/Core/Src/usbh_conf_template.c000066400000000000000000000173071357706137100252640ustar00rootroot00000000000000/** ****************************************************************************** * @file usb_bsp.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file implements the board support package for the USB host library ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** * @brief USBH_LL_Init * Initialize the Low Level portion of the Host driver. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_LL_Init (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_LL_DeInit * De-Initialize the Low Level portion of the Host driver. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_LL_DeInit (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_LL_Start * Start the Low Level portion of the Host driver. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_LL_Stop * Stop the Low Level portion of the Host driver. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_LL_Stop (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_LL_GetSpeed * Return the USB Host Speed from the Low Level Driver. * @param phost: Host handle * @retval USBH Speeds */ USBH_SpeedTypeDef USBH_LL_GetSpeed (USBH_HandleTypeDef *phost) { USBH_SpeedTypeDef speed = 0; return speed; } /** * @brief USBH_LL_ResetPort * Reset the Host Port of the Low Level Driver. * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost) { return USBH_OK; } /** * @brief USBH_LL_GetLastXferSize * Return the last transfered packet size. * @param phost: Host handle * @param pipe: Pipe index * @retval Packet Size */ uint32_t USBH_LL_GetLastXferSize (USBH_HandleTypeDef *phost, uint8_t pipe) { } /** * @brief USBH_LL_OpenPipe * Open a pipe of the Low Level Driver. * @param phost: Host handle * @param pipe_num: Pipe index * @param epnum: Endpoint Number * @param dev_address: Device USB address * @param speed: Device Speed * @param ep_type: Endpoint Type * @param mps: Endpoint Max Packet Size * @retval USBH Status */ USBH_StatusTypeDef USBH_LL_OpenPipe (USBH_HandleTypeDef *phost, uint8_t pipe_num, uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) { return USBH_OK; } /** * @brief USBH_LL_ClosePipe * Close a pipe of the Low Level Driver. * @param phost: Host handle * @param pipe_num: Pipe index * @retval USBH Status */ USBH_StatusTypeDef USBH_LL_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe) { } /** * @brief USBH_LL_SubmitURB * Submit a new URB to the low level driver. * @param phost: Host handle * @param pipe: Pipe index * This parameter can be a value from 1 to 15 * @param direction : Channel number * This parameter can be one of the these values: * 0 : Output * 1 : Input * @param ep_type : Endpoint Type * This parameter can be one of the these values: * @arg EP_TYPE_CTRL: Control type * @arg EP_TYPE_ISOC: Isochrounous type * @arg EP_TYPE_BULK: Bulk type * @arg EP_TYPE_INTR: Interrupt type * @param token : Endpoint Type * This parameter can be one of the these values: * @arg 0: PID_SETUP * @arg 1: PID_DATA * @param pbuff : pointer to URB data * @param length : Length of URB data * @param do_ping : activate do ping protocol (for high speed only) * This parameter can be one of the these values: * 0 : do ping inactive * 1 : do ping active * @retval Status */ USBH_StatusTypeDef USBH_LL_SubmitURB (USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t direction , uint8_t ep_type, uint8_t token, uint8_t* pbuff, uint16_t length, uint8_t do_ping ) { return USBH_OK; } /** * @brief USBH_LL_GetURBState * Get a URB state from the low level driver. * @param phost: Host handle * @param pipe: Pipe index * This parameter can be a value from 1 to 15 * @retval URB state * This parameter can be one of the these values: * @arg URB_IDLE * @arg URB_DONE * @arg URB_NOTREADY * @arg URB_NYET * @arg URB_ERROR * @arg URB_STALL */ USBH_URBStateTypeDef USBH_LL_GetURBState (USBH_HandleTypeDef *phost, uint8_t pipe) { } /** * @brief USBH_LL_DriverVBUS * Drive VBUS. * @param phost: Host handle * @param state : VBUS state * This parameter can be one of the these values: * 0 : VBUS Active * 1 : VBUS Inactive * @retval Status */ USBH_StatusTypeDef USBH_LL_DriverVBUS (USBH_HandleTypeDef *phost, uint8_t state) { return USBH_OK; } /** * @brief USBH_LL_SetToggle * Set toggle for a pipe. * @param phost: Host handle * @param pipe: Pipe index * @param pipe_num: Pipe index * @param toggle: toggle (0/1) * @retval Status */ USBH_StatusTypeDef USBH_LL_SetToggle (USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle) { return USBH_OK; } /** * @brief USBH_LL_GetToggle * Return the current toggle of a pipe. * @param phost: Host handle * @param pipe: Pipe index * @retval toggle (0/1) */ uint8_t USBH_LL_GetToggle (USBH_HandleTypeDef *phost, uint8_t pipe) { uint8_t toggle = 0; return toggle; } /** * @brief USBH_Delay * Delay routine for the USB Host Library * @param Delay: Delay in ms * @retval None */ void USBH_Delay (uint32_t Delay) { } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Src/usbh_core.c000066400000000000000000000611151357706137100233700ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_core.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file implements the functions for the core state machine process * the enumeration and the control transfer process ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_CORE * @brief TThis file handles the basic enumaration when a device is connected * to the host. * @{ */ /** @defgroup USBH_CORE_Private_Defines * @{ */ #define USBH_ADDRESS_DEFAULT 0 #define USBH_ADDRESS_ASSIGNED 1 #define USBH_MPS_DEFAULT 0x40 /** * @} */ /** @defgroup USBH_CORE_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_CORE_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_CORE_Private_Functions * @{ */ static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost); static void USBH_HandleSof (USBH_HandleTypeDef *phost); static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost); #if (USBH_USE_OS == 1) static void USBH_Process_OS(void const * argument); #endif /** * @brief HCD_Init * Initialize the HOST Core. * @param phost: Host Handle * @param pUsrFunc: User Callback * @retval USBH Status */ USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id) { /* Check whether the USB Host handle is valid */ if(phost == NULL) { USBH_ErrLog("Invalid Host handle"); return USBH_FAIL; } /* Set DRiver ID */ phost->id = id; /* Unlink class*/ phost->pActiveClass = NULL; phost->ClassNumber = 0; /* Restore default states and prepare EP0 */ DeInitStateMachine(phost); /* Assign User process */ if(pUsrFunc != NULL) { phost->pUser = pUsrFunc; } #if (USBH_USE_OS == 1) /* Create USB Host Queue */ osMessageQDef(USBH_Queue, 10, uint16_t); phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL); /*Create USB Host Task */ osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE); phost->thread = osThreadCreate (osThread(USBH_Thread), phost); #endif /* Initialize low level driver */ USBH_LL_Init(phost); return USBH_OK; } /** * @brief HCD_Init * De-Initialize the Host portion of the driver. * @param phost: Host Handle * @retval USBH Status */ USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost) { DeInitStateMachine(phost); if(phost->pData != NULL) { phost->pActiveClass->pData = NULL; USBH_LL_Stop(phost); } return USBH_OK; } /** * @brief DeInitStateMachine * De-Initialize the Host state machine. * @param phost: Host Handle * @retval USBH Status */ static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost) { uint32_t i = 0; /* Clear Pipes flags*/ for ( ; i < USBH_MAX_PIPES_NBR; i++) { phost->Pipes[i] = 0; } for(i = 0; i< USBH_MAX_DATA_BUFFER; i++) { phost->device.Data[i] = 0; } phost->gState = HOST_IDLE; phost->EnumState = ENUM_IDLE; phost->RequestState = CMD_SEND; phost->Timer = 0; phost->Control.state = CTRL_SETUP; phost->Control.pipe_size = USBH_MPS_DEFAULT; phost->Control.errorcount = 0; phost->device.address = USBH_ADDRESS_DEFAULT; phost->device.speed = USBH_SPEED_FULL; return USBH_OK; } /** * @brief USBH_RegisterClass * Link class driver to Host Core. * @param phost : Host Handle * @param pclass: Class handle * @retval USBH Status */ USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass) { USBH_StatusTypeDef status = USBH_OK; if(pclass != 0) { if(phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS) { /* link the class tgo the USB Host handle */ phost->pClass[phost->ClassNumber++] = pclass; status = USBH_OK; } else { USBH_ErrLog("Max Class Number reached"); status = USBH_FAIL; } } else { USBH_ErrLog("Invalid Class handle"); status = USBH_FAIL; } return status; } /** * @brief USBH_SelectInterface * Select current interface. * @param phost: Host Handle * @param interface: Interface number * @retval USBH Status */ USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface) { USBH_StatusTypeDef status = USBH_OK; if(interface < phost->device.CfgDesc.bNumInterfaces) { phost->device.current_interface = interface; USBH_UsrLog ("Switching to Interface (#%d)", interface); USBH_UsrLog ("Class : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass ); USBH_UsrLog ("SubClass : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass ); USBH_UsrLog ("Protocol : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol ); } else { USBH_ErrLog ("Cannot Select This Interface."); status = USBH_FAIL; } return status; } /** * @brief USBH_GetActiveClass * Return Device Class. * @param phost: Host Handle * @param interface: Interface index * @retval Class Code */ uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost) { return (phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass); } /** * @brief USBH_FindInterface * Find the interface index for a specific class. * @param phost: Host Handle * @param Class: Class code * @param SubClass: SubClass code * @param Protocol: Protocol code * @retval interface index in the configuration structure * @note : (1)interface index 0xFF means interface index not found */ uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, uint8_t Class, uint8_t SubClass, uint8_t Protocol) { USBH_InterfaceDescTypeDef *pif ; USBH_CfgDescTypeDef *pcfg ; int8_t if_ix = 0; pif = (USBH_InterfaceDescTypeDef *)0; pcfg = &phost->device.CfgDesc; if((pif->bInterfaceClass == 0xFF) &&(pif->bInterfaceSubClass == 0xFF) && (pif->bInterfaceProtocol == 0xFF)) { return 0xFF; } while (if_ix < USBH_MAX_NUM_INTERFACES) { pif = &pcfg->Itf_Desc[if_ix]; if(((pif->bInterfaceClass == Class) || (Class == 0xFF))&& ((pif->bInterfaceSubClass == SubClass) || (SubClass == 0xFF))&& ((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFF))) { return if_ix; } if_ix++; } return 0xFF; } /** * @brief USBH_FindInterfaceIndex * Find the interface index for a specific class interface and alternate setting number. * @param phost: Host Handle * @param interface_number: interface number * @param alt_settings : alaternate setting number * @retval interface index in the configuration structure * @note : (1)interface index 0xFF means interface index not found */ uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, uint8_t interface_number, uint8_t alt_settings) { USBH_InterfaceDescTypeDef *pif ; USBH_CfgDescTypeDef *pcfg ; int8_t if_ix = 0; pif = (USBH_InterfaceDescTypeDef *)0; pcfg = &phost->device.CfgDesc; while (if_ix < USBH_MAX_NUM_INTERFACES) { pif = &pcfg->Itf_Desc[if_ix]; if((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { return if_ix; } if_ix++; } return 0xFF; } /** * @brief USBH_Start * Start the USB Host Core. * @param phost: Host Handle * @retval USBH Status */ USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost) { /* Start the low level driver */ USBH_LL_Start(phost); /* Activate VBUS on the port */ USBH_LL_DriverVBUS (phost, TRUE); return USBH_OK; } /** * @brief USBH_Stop * Stop the USB Host Core. * @param phost: Host Handle * @retval USBH Status */ USBH_StatusTypeDef USBH_Stop (USBH_HandleTypeDef *phost) { /* Stop and cleanup the low level driver */ USBH_LL_Stop(phost); /* DeActivate VBUS on the port */ USBH_LL_DriverVBUS (phost, FALSE); /* FRee Control Pipes */ USBH_FreePipe (phost, phost->Control.pipe_in); USBH_FreePipe (phost, phost->Control.pipe_out); return USBH_OK; } /** * @brief HCD_ReEnumerate * Perform a new Enumeration phase. * @param phost: Host Handle * @retval USBH Status */ USBH_StatusTypeDef USBH_ReEnumerate (USBH_HandleTypeDef *phost) { /*Stop Host */ USBH_Stop(phost); /*Device has disconnected, so wait for 200 ms */ USBH_Delay(200); /* Set State machines in default state */ DeInitStateMachine(phost); /* Start again the host */ USBH_Start(phost); #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); #endif return USBH_OK; } /** * @brief USBH_Process * Background process of the USB Core. * @param phost: Host Handle * @retval USBH Status */ USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost) { __IO USBH_StatusTypeDef status = USBH_FAIL; uint8_t idx = 0; switch (phost->gState) { case HOST_IDLE : if (phost->device.is_connected) { /* Wait for 200 ms after connection */ phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT; USBH_Delay(200); USBH_LL_ResetPort(phost); #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); #endif } break; case HOST_DEV_WAIT_FOR_ATTACHMENT: break; case HOST_DEV_ATTACHED : USBH_UsrLog("USB Device Attached"); /* Wait for 100 ms after Reset */ USBH_Delay(100); phost->device.speed = USBH_LL_GetSpeed(phost); phost->gState = HOST_ENUMERATION; phost->Control.pipe_out = USBH_AllocPipe (phost, 0x00); phost->Control.pipe_in = USBH_AllocPipe (phost, 0x80); /* Open Control pipes */ USBH_OpenPipe (phost, phost->Control.pipe_in, 0x80, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); /* Open Control pipes */ USBH_OpenPipe (phost, phost->Control.pipe_out, 0x00, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); #endif break; case HOST_ENUMERATION: /* Check for enumeration status */ if ( USBH_HandleEnum(phost) == USBH_OK) { /* The function shall return USBH_OK when full enumeration is complete */ USBH_UsrLog ("Enumeration done."); phost->device.current_interface = 0; if(phost->device.DevDesc.bNumConfigurations == 1) { USBH_UsrLog ("This device has only 1 configuration."); phost->gState = HOST_SET_CONFIGURATION; } else { phost->gState = HOST_INPUT; } } break; case HOST_INPUT: { /* user callback for end of device basic enumeration */ if(phost->pUser != NULL) { phost->pUser(phost, HOST_USER_SELECT_CONFIGURATION); phost->gState = HOST_SET_CONFIGURATION; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } } break; case HOST_SET_CONFIGURATION: /* set configuration */ if (USBH_SetCfg(phost, phost->device.CfgDesc.bConfigurationValue) == USBH_OK) { phost->gState = HOST_CHECK_CLASS; USBH_UsrLog ("Default configuration set."); } break; case HOST_CHECK_CLASS: if(phost->ClassNumber == 0) { USBH_UsrLog ("No Class has been registered."); } else { phost->pActiveClass = NULL; for (idx = 0; idx < USBH_MAX_NUM_SUPPORTED_CLASS ; idx ++) { if(phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass) { phost->pActiveClass = phost->pClass[idx]; } } if(phost->pActiveClass != NULL) { if(phost->pActiveClass->Init(phost)== USBH_OK) { phost->gState = HOST_CLASS_REQUEST; USBH_UsrLog ("%s class started.", phost->pActiveClass->Name); /* Inform user that a class has been activated */ phost->pUser(phost, HOST_USER_CLASS_SELECTED); } else { phost->gState = HOST_ABORT_STATE; USBH_UsrLog ("Device not supporting %s class.", phost->pActiveClass->Name); } } else { phost->gState = HOST_ABORT_STATE; USBH_UsrLog ("No registered class for this device."); } } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif break; case HOST_CLASS_REQUEST: /* process class standard contol requests state machine */ if(phost->pActiveClass != NULL) { status = phost->pActiveClass->Requests(phost); if(status == USBH_OK) { phost->gState = HOST_CLASS; } } else { phost->gState = HOST_ABORT_STATE; USBH_ErrLog ("Invalid Class Driver."); #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } break; case HOST_CLASS: /* process class state machine */ if(phost->pActiveClass != NULL) { phost->pActiveClass->BgndProcess(phost); } break; case HOST_DEV_DISCONNECTED : DeInitStateMachine(phost); /* Re-Initilaize Host for new Enumeration */ if(phost->pActiveClass != NULL) { phost->pActiveClass->DeInit(phost); phost->pActiveClass = NULL; } break; case HOST_ABORT_STATE: default : break; } return USBH_OK; } /** * @brief USBH_HandleEnum * This function includes the complete enumeration process * @param phost: Host Handle * @retval USBH_Status */ static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef Status = USBH_BUSY; switch (phost->EnumState) { case ENUM_IDLE: /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ if ( USBH_Get_DevDesc(phost, 8) == USBH_OK) { phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize; phost->EnumState = ENUM_GET_FULL_DEV_DESC; /* modify control channels configuration for MaxPacket size */ USBH_OpenPipe (phost, phost->Control.pipe_in, 0x80, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); /* Open Control pipes */ USBH_OpenPipe (phost, phost->Control.pipe_out, 0x00, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); } break; case ENUM_GET_FULL_DEV_DESC: /* Get FULL Device Desc */ if ( USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE)== USBH_OK) { USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct ); USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor ); phost->EnumState = ENUM_SET_ADDR; } break; case ENUM_SET_ADDR: /* set address */ if ( USBH_SetAddress(phost, USBH_DEVICE_ADDRESS) == USBH_OK) { USBH_Delay(2); phost->device.address = USBH_DEVICE_ADDRESS; /* user callback for device address assigned */ USBH_UsrLog("Address (#%d) assigned.", phost->device.address); phost->EnumState = ENUM_GET_CFG_DESC; /* modify control channels to update device address */ USBH_OpenPipe (phost, phost->Control.pipe_in, 0x80, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); /* Open Control pipes */ USBH_OpenPipe (phost, phost->Control.pipe_out, 0x00, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); } break; case ENUM_GET_CFG_DESC: /* get standard configuration descriptor */ if ( USBH_Get_CfgDesc(phost, USB_CONFIGURATION_DESC_SIZE) == USBH_OK) { phost->EnumState = ENUM_GET_FULL_CFG_DESC; } break; case ENUM_GET_FULL_CFG_DESC: /* get FULL config descriptor (config, interface, endpoints) */ if (USBH_Get_CfgDesc(phost, phost->device.CfgDesc.wTotalLength) == USBH_OK) { phost->EnumState = ENUM_GET_MFC_STRING_DESC; } break; case ENUM_GET_MFC_STRING_DESC: if (phost->device.DevDesc.iManufacturer != 0) { /* Check that Manufacturer String is available */ if ( USBH_Get_StringDesc(phost, phost->device.DevDesc.iManufacturer, phost->device.Data , 0xff) == USBH_OK) { /* User callback for Manufacturing string */ USBH_UsrLog("Manufacturer : %s", (char *)phost->device.Data); phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } } else { USBH_UsrLog("Manufacturer : N/A"); phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } break; case ENUM_GET_PRODUCT_STRING_DESC: if (phost->device.DevDesc.iProduct != 0) { /* Check that Product string is available */ if ( USBH_Get_StringDesc(phost, phost->device.DevDesc.iProduct, phost->device.Data, 0xff) == USBH_OK) { /* User callback for Product string */ USBH_UsrLog("Product : %s", (char *)phost->device.Data); phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; } } else { USBH_UsrLog("Product : N/A"); phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } break; case ENUM_GET_SERIALNUM_STRING_DESC: if (phost->device.DevDesc.iSerialNumber != 0) { /* Check that Serial number string is available */ if ( USBH_Get_StringDesc(phost, phost->device.DevDesc.iSerialNumber, phost->device.Data, 0xff) == USBH_OK) { /* User callback for Serial number string */ USBH_UsrLog("Serial Number : %s", (char *)phost->device.Data); Status = USBH_OK; } } else { USBH_UsrLog("Serial Number : N/A"); Status = USBH_OK; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } break; default: break; } return Status; } /** * @brief USBH_LL_SetTimer * Set the initial Host Timer tick * @param phost: Host Handle * @retval None */ void USBH_LL_SetTimer (USBH_HandleTypeDef *phost, uint32_t time) { phost->Timer = time; } /** * @brief USBH_LL_IncTimer * Increment Host Timer tick * @param phost: Host Handle * @retval None */ void USBH_LL_IncTimer (USBH_HandleTypeDef *phost) { phost->Timer ++; USBH_HandleSof(phost); } /** * @brief USBH_HandleSof * Call SOF process * @param phost: Host Handle * @retval None */ void USBH_HandleSof (USBH_HandleTypeDef *phost) { if((phost->gState == HOST_CLASS)&&(phost->pActiveClass != NULL)) { phost->pActiveClass->SOFProcess(phost); } } /** * @brief USBH_LL_Connect * Handle USB Host connexion event * @param phost: Host Handle * @retval USBH_Status */ USBH_StatusTypeDef USBH_LL_Connect (USBH_HandleTypeDef *phost) { if(phost->gState == HOST_IDLE ) { phost->device.is_connected = 1; phost->gState = HOST_IDLE ; if(phost->pUser != NULL) { phost->pUser(phost, HOST_USER_CONNECTION); } } else if(phost->gState == HOST_DEV_WAIT_FOR_ATTACHMENT ) { phost->gState = HOST_DEV_ATTACHED ; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); #endif return USBH_OK; } /** * @brief USBH_LL_Disconnect * Handle USB Host disconnexion event * @param phost: Host Handle * @retval USBH_Status */ USBH_StatusTypeDef USBH_LL_Disconnect (USBH_HandleTypeDef *phost) { /*Stop Host */ USBH_LL_Stop(phost); /* FRee Control Pipes */ USBH_FreePipe (phost, phost->Control.pipe_in); USBH_FreePipe (phost, phost->Control.pipe_out); phost->device.is_connected = 0; if(phost->pUser != NULL) { phost->pUser(phost, HOST_USER_DISCONNECTION); } USBH_UsrLog("USB Device disconnected"); /* Start the low level driver */ USBH_LL_Start(phost); phost->gState = HOST_DEV_DISCONNECTED; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0); #endif return USBH_OK; } #if (USBH_USE_OS == 1) /** * @brief USB Host Thread task * @param pvParameters not used * @retval None */ static void USBH_Process_OS(void const * argument) { osEvent event; for(;;) { event = osMessageGet(((USBH_HandleTypeDef *)argument)->os_event, osWaitForever ); if( event.status == osEventMessage ) { USBH_Process((USBH_HandleTypeDef *)argument); } } } /** * @brief USBH_LL_NotifyURBChange * Notify URB state Change * @param phost: Host handle * @retval USBH Status */ USBH_StatusTypeDef USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost) { osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); return USBH_OK; } #endif /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Src/usbh_ctlreq.c000066400000000000000000000651531357706137100237400ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_ctlreq.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file implements the control requests for device enumeration ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_ctlreq.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_CTLREQ * @brief This file implements the standard requests for device enumeration * @{ */ /** @defgroup USBH_CTLREQ_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_CTLREQ_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_CTLREQ_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_CTLREQ_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_CTLREQ_Private_FunctionPrototypes * @{ */ static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost); static void USBH_ParseDevDesc (USBH_DevDescTypeDef* , uint8_t *buf, uint16_t length); static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, uint8_t *buf, uint16_t length); static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf); static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length); static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf); /** * @} */ /** @defgroup USBH_CTLREQ_Private_Functions * @{ */ /** * @brief USBH_Get_DevDesc * Issue Get Device Descriptor command to the device. Once the response * received, it parses the device descriptor and updates the status. * @param phost: Host Handle * @param length: Length of the descriptor * @retval USBH Status */ USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length) { USBH_StatusTypeDef status; if((status = USBH_GetDescriptor(phost, USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, USB_DESC_DEVICE, phost->device.Data, length)) == USBH_OK) { /* Commands successfully sent and Response Received */ USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, length); } return status; } /** * @brief USBH_Get_CfgDesc * Issues Configuration Descriptor to the device. Once the response * received, it parses the configuartion descriptor and updates the * status. * @param phost: Host Handle * @param length: Length of the descriptor * @retval USBH Status */ USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost, uint16_t length) { USBH_StatusTypeDef status; uint8_t *pData; #if (USBH_KEEP_CFG_DESCRIPTOR == 1) pData = phost->device.CfgDesc_Raw; #else pData = phost->device.Data; #endif if((status = USBH_GetDescriptor(phost, USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, USB_DESC_CONFIGURATION, pData, length)) == USBH_OK) { /* Commands successfully sent and Response Received */ USBH_ParseCfgDesc (&phost->device.CfgDesc, pData, length); } return status; } /** * @brief USBH_Get_StringDesc * Issues string Descriptor command to the device. Once the response * received, it parses the string descriptor and updates the status. * @param phost: Host Handle * @param string_index: String index for the descriptor * @param buff: Buffer address for the descriptor * @param length: Length of the descriptor * @retval USBH Status */ USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost, uint8_t string_index, uint8_t *buff, uint16_t length) { USBH_StatusTypeDef status; if((status = USBH_GetDescriptor(phost, USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, USB_DESC_STRING | string_index, phost->device.Data, length)) == USBH_OK) { /* Commands successfully sent and Response Received */ USBH_ParseStringDesc(phost->device.Data,buff, length); } return status; } /** * @brief USBH_GetDescriptor * Issues Descriptor command to the device. Once the response received, * it parses the descriptor and updates the status. * @param phost: Host Handle * @param req_type: Descriptor type * @param value_idx: wValue for the GetDescriptr request * @param buff: Buffer to store the descriptor * @param length: Length of the descriptor * @retval USBH Status */ USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost, uint8_t req_type, uint16_t value_idx, uint8_t* buff, uint16_t length ) { if(phost->RequestState == CMD_SEND) { phost->Control.setup.b.bmRequestType = USB_D2H | req_type; phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR; phost->Control.setup.b.wValue.w = value_idx; if ((value_idx & 0xff00) == USB_DESC_STRING) { phost->Control.setup.b.wIndex.w = 0x0409; } else { phost->Control.setup.b.wIndex.w = 0; } phost->Control.setup.b.wLength.w = length; } return USBH_CtlReq(phost, buff , length ); } /** * @brief USBH_SetAddress * This command sets the address to the connected device * @param phost: Host Handle * @param DeviceAddress: Device address to assign * @retval USBH Status */ USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost, uint8_t DeviceAddress) { if(phost->RequestState == CMD_SEND) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \ USB_REQ_TYPE_STANDARD; phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS; phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = 0; } return USBH_CtlReq(phost, 0 , 0 ); } /** * @brief USBH_SetCfg * The command sets the configuration value to the connected device * @param phost: Host Handle * @param cfg_idx: Configuration value * @retval USBH Status */ USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost, uint16_t cfg_idx) { if(phost->RequestState == CMD_SEND) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\ USB_REQ_TYPE_STANDARD; phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION; phost->Control.setup.b.wValue.w = cfg_idx; phost->Control.setup.b.wIndex.w = 0; phost->Control.setup.b.wLength.w = 0; } return USBH_CtlReq(phost, 0 , 0 ); } /** * @brief USBH_SetInterface * The command sets the Interface value to the connected device * @param phost: Host Handle * @param altSetting: Interface value * @retval USBH Status */ USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost, uint8_t ep_num, uint8_t altSetting) { if(phost->RequestState == CMD_SEND) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \ USB_REQ_TYPE_STANDARD; phost->Control.setup.b.bRequest = USB_REQ_SET_INTERFACE; phost->Control.setup.b.wValue.w = altSetting; phost->Control.setup.b.wIndex.w = ep_num; phost->Control.setup.b.wLength.w = 0; } return USBH_CtlReq(phost, 0 , 0 ); } /** * @brief USBH_ClrFeature * This request is used to clear or disable a specific feature. * @param phost: Host Handle * @param ep_num: endpoint number * @param hc_num: Host channel number * @retval USBH Status */ USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost, uint8_t ep_num) { if(phost->RequestState == CMD_SEND) { phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_ENDPOINT | USB_REQ_TYPE_STANDARD; phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE; phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT; phost->Control.setup.b.wIndex.w = ep_num; phost->Control.setup.b.wLength.w = 0; } return USBH_CtlReq(phost, 0 , 0 ); } /** * @brief USBH_ParseDevDesc * This function Parses the device descriptor * @param dev_desc: device_descriptor destinaton address * @param buf: Buffer where the source descriptor is available * @param length: Length of the descriptor * @retval None */ static void USBH_ParseDevDesc (USBH_DevDescTypeDef* dev_desc, uint8_t *buf, uint16_t length) { dev_desc->bLength = *(uint8_t *) (buf + 0); dev_desc->bDescriptorType = *(uint8_t *) (buf + 1); dev_desc->bcdUSB = LE16 (buf + 2); dev_desc->bDeviceClass = *(uint8_t *) (buf + 4); dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5); dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6); dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7); if (length > 8) { /* For 1st time after device connection, Host may issue only 8 bytes for Device Descriptor Length */ dev_desc->idVendor = LE16 (buf + 8); dev_desc->idProduct = LE16 (buf + 10); dev_desc->bcdDevice = LE16 (buf + 12); dev_desc->iManufacturer = *(uint8_t *) (buf + 14); dev_desc->iProduct = *(uint8_t *) (buf + 15); dev_desc->iSerialNumber = *(uint8_t *) (buf + 16); dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17); } } /** * @brief USBH_ParseCfgDesc * This function Parses the configuration descriptor * @param cfg_desc: Configuration Descriptor address * @param buf: Buffer where the source descriptor is available * @param length: Length of the descriptor * @retval None */ static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc, uint8_t *buf, uint16_t length) { USBH_InterfaceDescTypeDef *pif ; USBH_EpDescTypeDef *pep; USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf; uint16_t ptr; int8_t if_ix = 0; int8_t ep_ix = 0; pdesc = (USBH_DescHeader_t *)buf; /* Parse configuration descriptor */ cfg_desc->bLength = *(uint8_t *) (buf + 0); cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1); cfg_desc->wTotalLength = LE16 (buf + 2); cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4); cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5); cfg_desc->iConfiguration = *(uint8_t *) (buf + 6); cfg_desc->bmAttributes = *(uint8_t *) (buf + 7); cfg_desc->bMaxPower = *(uint8_t *) (buf + 8); if (length > USB_CONFIGURATION_DESC_SIZE) { ptr = USB_LEN_CFG_DESC; pif = (USBH_InterfaceDescTypeDef *)0; while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength)) { pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr); if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) { pif = &cfg_desc->Itf_Desc[if_ix]; USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc); ep_ix = 0; pep = (USBH_EpDescTypeDef *)0; while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)) { pdesc = USBH_GetNextDesc((void* )pdesc, &ptr); if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) { pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix]; USBH_ParseEPDesc (pep, (uint8_t *)pdesc); ep_ix++; } } if_ix++; } } } } /** * @brief USBH_ParseInterfaceDesc * This function Parses the interface descriptor * @param if_descriptor : Interface descriptor destination * @param buf: Buffer where the descriptor data is available * @retval None */ static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf) { if_descriptor->bLength = *(uint8_t *) (buf + 0); if_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); if_descriptor->bInterfaceNumber = *(uint8_t *) (buf + 2); if_descriptor->bAlternateSetting = *(uint8_t *) (buf + 3); if_descriptor->bNumEndpoints = *(uint8_t *) (buf + 4); if_descriptor->bInterfaceClass = *(uint8_t *) (buf + 5); if_descriptor->bInterfaceSubClass = *(uint8_t *) (buf + 6); if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7); if_descriptor->iInterface = *(uint8_t *) (buf + 8); } /** * @brief USBH_ParseEPDesc * This function Parses the endpoint descriptor * @param ep_descriptor: Endpoint descriptor destination address * @param buf: Buffer where the parsed descriptor stored * @retval None */ static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf) { ep_descriptor->bLength = *(uint8_t *) (buf + 0); ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1); ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2); ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3); ep_descriptor->wMaxPacketSize = LE16 (buf + 4); ep_descriptor->bInterval = *(uint8_t *) (buf + 6); } /** * @brief USBH_ParseStringDesc * This function Parses the string descriptor * @param psrc: Source pointer containing the descriptor data * @param pdest: Destination address pointer * @param length: Length of the descriptor * @retval None */ static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length) { uint16_t strlength; uint16_t idx; /* The UNICODE string descriptor is not NULL-terminated. The string length is computed by substracting two from the value of the first byte of the descriptor. */ /* Check which is lower size, the Size of string or the length of bytes read from the device */ if ( psrc[1] == USB_DESC_TYPE_STRING) { /* Make sure the Descriptor is String Type */ /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length); psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */ for (idx = 0; idx < strlength; idx+=2 ) {/* Copy Only the string and ignore the UNICODE ID, hence add the src */ *pdest = psrc[idx]; pdest++; } *pdest = 0; /* mark end of string */ } } /** * @brief USBH_GetNextDesc * This function return the next descriptor header * @param buf: Buffer where the cfg descriptor is available * @param ptr: data popinter inside the cfg descriptor * @retval next header */ USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr) { USBH_DescHeader_t *pnext; *ptr += ((USBH_DescHeader_t *)pbuf)->bLength; pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \ ((USBH_DescHeader_t *)pbuf)->bLength); return(pnext); } /** * @brief USBH_CtlReq * USBH_CtlReq sends a control request and provide the status after * completion of the request * @param phost: Host Handle * @param req: Setup Request Structure * @param buff: data buffer address to store the response * @param length: length of the response * @retval USBH Status */ USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length) { USBH_StatusTypeDef status; status = USBH_BUSY; switch (phost->RequestState) { case CMD_SEND: /* Start a SETUP transfer */ phost->Control.buff = buff; phost->Control.length = length; phost->Control.state = CTRL_SETUP; phost->RequestState = CMD_WAIT; status = USBH_BUSY; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif break; case CMD_WAIT: status = USBH_HandleControl(phost); if (status == USBH_OK) { /* Commands successfully sent and Response Received */ phost->RequestState = CMD_SEND; phost->Control.state =CTRL_IDLE; status = USBH_OK; } else if (status == USBH_FAIL) { /* Failure Mode */ phost->RequestState = CMD_SEND; status = USBH_FAIL; } break; default: break; } return status; } /** * @brief USBH_HandleControl * Handles the USB control transfer state machine * @param phost: Host Handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost) { uint8_t direction; USBH_StatusTypeDef status = USBH_BUSY; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; switch (phost->Control.state) { case CTRL_SETUP: /* send a SETUP packet */ USBH_CtlSendSetup (phost, (uint8_t *)phost->Control.setup.d8 , phost->Control.pipe_out); phost->Control.state = CTRL_SETUP_WAIT; break; case CTRL_SETUP_WAIT: URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out); /* case SETUP packet sent successfully */ if(URB_Status == USBH_URB_DONE) { direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK); /* check if there is a data stage */ if (phost->Control.setup.b.wLength.w != 0 ) { if (direction == USB_D2H) { /* Data Direction is IN */ phost->Control.state = CTRL_DATA_IN; } else { /* Data Direction is OUT */ phost->Control.state = CTRL_DATA_OUT; } } /* No DATA stage */ else { /* If there is No Data Transfer Stage */ if (direction == USB_D2H) { /* Data Direction is IN */ phost->Control.state = CTRL_STATUS_OUT; } else { /* Data Direction is OUT */ phost->Control.state = CTRL_STATUS_IN; } } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if(URB_Status == USBH_URB_ERROR) { phost->Control.state = CTRL_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_DATA_IN: /* Issue an IN token */ phost->Control.timer = phost->Timer; USBH_CtlReceiveData(phost, phost->Control.buff, phost->Control.length, phost->Control.pipe_in); phost->Control.state = CTRL_DATA_IN_WAIT; break; case CTRL_DATA_IN_WAIT: URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); /* check is DATA packet transfered successfully */ if (URB_Status == USBH_URB_DONE) { phost->Control.state = CTRL_STATUS_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } /* manage error cases*/ if (URB_Status == USBH_URB_STALL) { /* In stall case, return to previous machine state*/ status = USBH_NOT_SUPPORTED; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_ERROR) { /* Device error */ phost->Control.state = CTRL_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_DATA_OUT: USBH_CtlSendData (phost, phost->Control.buff, phost->Control.length , phost->Control.pipe_out, 1); phost->Control.timer = phost->Timer; phost->Control.state = CTRL_DATA_OUT_WAIT; break; case CTRL_DATA_OUT_WAIT: URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); if (URB_Status == USBH_URB_DONE) { /* If the Setup Pkt is sent successful, then change the state */ phost->Control.state = CTRL_STATUS_IN; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } /* handle error cases */ else if (URB_Status == USBH_URB_STALL) { /* In stall case, return to previous machine state*/ phost->Control.state = CTRL_STALLED; status = USBH_NOT_SUPPORTED; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_NOTREADY) { /* Nack received from device */ phost->Control.state = CTRL_DATA_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_ERROR) { /* device error */ phost->Control.state = CTRL_ERROR; status = USBH_FAIL; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_STATUS_IN: /* Send 0 bytes out packet */ USBH_CtlReceiveData (phost, 0, 0, phost->Control.pipe_in); phost->Control.timer = phost->Timer; phost->Control.state = CTRL_STATUS_IN_WAIT; break; case CTRL_STATUS_IN_WAIT: URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); if ( URB_Status == USBH_URB_DONE) { /* Control transfers completed, Exit the State Machine */ phost->Control.state = CTRL_COMPLETE; status = USBH_OK; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_ERROR) { phost->Control.state = CTRL_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { /* Control transfers completed, Exit the State Machine */ status = USBH_NOT_SUPPORTED; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_STATUS_OUT: USBH_CtlSendData (phost, 0, 0, phost->Control.pipe_out, 1); phost->Control.timer = phost->Timer; phost->Control.state = CTRL_STATUS_OUT_WAIT; break; case CTRL_STATUS_OUT_WAIT: URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); if (URB_Status == USBH_URB_DONE) { status = USBH_OK; phost->Control.state = CTRL_COMPLETE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_NOTREADY) { phost->Control.state = CTRL_STATUS_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_ERROR) { phost->Control.state = CTRL_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_ERROR: /* After a halt condition is encountered or an error is detected by the host, a control endpoint is allowed to recover by accepting the next Setup PID; i.e., recovery actions via some other pipe are not required for control endpoints. For the Default Control Pipe, a device reset will ultimately be required to clear the halt or error condition if the next Setup PID is not accepted. */ if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT) { /* try to recover control */ USBH_LL_Stop(phost); /* Do the transmission again, starting from SETUP Packet */ phost->Control.state = CTRL_SETUP; phost->RequestState = CMD_SEND; } else { phost->Control.errorcount = 0; USBH_ErrLog("Control error"); status = USBH_FAIL; } break; default: break; } return status; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Src/usbh_ioreq.c000066400000000000000000000302321357706137100235530ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_ioreq.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file handles the issuing of the USB transactions ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_ioreq.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_IOREQ * @brief This file handles the standard protocol processing (USB v2.0) * @{ */ /** @defgroup USBH_IOREQ_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_IOREQ_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_IOREQ_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_IOREQ_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_IOREQ_Private_FunctionPrototypes * @{ */ /** * @} */ /** @defgroup USBH_IOREQ_Private_Functions * @{ */ /** * @brief USBH_CtlSendSetup * Sends the Setup Packet to the Device * @param phost: Host Handle * @param buff: Buffer pointer from which the Data will be send to Device * @param pipe_num: Pipe Number * @retval USBH Status */ USBH_StatusTypeDef USBH_CtlSendSetup (USBH_HandleTypeDef *phost, uint8_t *buff, uint8_t pipe_num) { USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 0, /* Direction : OUT */ USBH_EP_CONTROL, /* EP type */ USBH_PID_SETUP, /* Type setup */ buff, /* data buffer */ USBH_SETUP_PKT_SIZE, /* data length */ 0); return USBH_OK; } /** * @brief USBH_CtlSendData * Sends a data Packet to the Device * @param phost: Host Handle * @param buff: Buffer pointer from which the Data will be sent to Device * @param length: Length of the data to be sent * @param pipe_num: Pipe Number * @retval USBH Status */ USBH_StatusTypeDef USBH_CtlSendData (USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t pipe_num, uint8_t do_ping ) { if(phost->device.speed != USBH_SPEED_HIGH) { do_ping = 0; } USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 0, /* Direction : OUT */ USBH_EP_CONTROL, /* EP type */ USBH_PID_DATA, /* Type Data */ buff, /* data buffer */ length, /* data length */ do_ping); /* do ping (HS Only)*/ return USBH_OK; } /** * @brief USBH_CtlReceiveData * Receives the Device Response to the Setup Packet * @param phost: Host Handle * @param buff: Buffer pointer in which the response needs to be copied * @param length: Length of the data to be received * @param pipe_num: Pipe Number * @retval USBH Status. */ USBH_StatusTypeDef USBH_CtlReceiveData(USBH_HandleTypeDef *phost, uint8_t* buff, uint16_t length, uint8_t pipe_num) { USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 1, /* Direction : IN */ USBH_EP_CONTROL, /* EP type */ USBH_PID_DATA, /* Type Data */ buff, /* data buffer */ length, /* data length */ 0); return USBH_OK; } /** * @brief USBH_BulkSendData * Sends the Bulk Packet to the device * @param phost: Host Handle * @param buff: Buffer pointer from which the Data will be sent to Device * @param length: Length of the data to be sent * @param pipe_num: Pipe Number * @retval USBH Status */ USBH_StatusTypeDef USBH_BulkSendData (USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t pipe_num, uint8_t do_ping ) { if(phost->device.speed != USBH_SPEED_HIGH) { do_ping = 0; } USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 0, /* Direction : IN */ USBH_EP_BULK, /* EP type */ USBH_PID_DATA, /* Type Data */ buff, /* data buffer */ length, /* data length */ do_ping); /* do ping (HS Only)*/ return USBH_OK; } /** * @brief USBH_BulkReceiveData * Receives IN bulk packet from device * @param phost: Host Handle * @param buff: Buffer pointer in which the received data packet to be copied * @param length: Length of the data to be received * @param pipe_num: Pipe Number * @retval USBH Status. */ USBH_StatusTypeDef USBH_BulkReceiveData(USBH_HandleTypeDef *phost, uint8_t *buff, uint16_t length, uint8_t pipe_num) { USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 1, /* Direction : IN */ USBH_EP_BULK, /* EP type */ USBH_PID_DATA, /* Type Data */ buff, /* data buffer */ length, /* data length */ 0); return USBH_OK; } /** * @brief USBH_InterruptReceiveData * Receives the Device Response to the Interrupt IN token * @param phost: Host Handle * @param buff: Buffer pointer in which the response needs to be copied * @param length: Length of the data to be received * @param pipe_num: Pipe Number * @retval USBH Status. */ USBH_StatusTypeDef USBH_InterruptReceiveData(USBH_HandleTypeDef *phost, uint8_t *buff, uint8_t length, uint8_t pipe_num) { USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 1, /* Direction : IN */ USBH_EP_INTERRUPT, /* EP type */ USBH_PID_DATA, /* Type Data */ buff, /* data buffer */ length, /* data length */ 0); return USBH_OK; } /** * @brief USBH_InterruptSendData * Sends the data on Interrupt OUT Endpoint * @param phost: Host Handle * @param buff: Buffer pointer from where the data needs to be copied * @param length: Length of the data to be sent * @param pipe_num: Pipe Number * @retval USBH Status. */ USBH_StatusTypeDef USBH_InterruptSendData(USBH_HandleTypeDef *phost, uint8_t *buff, uint8_t length, uint8_t pipe_num) { USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 0, /* Direction : OUT */ USBH_EP_INTERRUPT, /* EP type */ USBH_PID_DATA, /* Type Data */ buff, /* data buffer */ length, /* data length */ 0); return USBH_OK; } /** * @brief USBH_IsocReceiveData * Receives the Device Response to the Isochronous IN token * @param phost: Host Handle * @param buff: Buffer pointer in which the response needs to be copied * @param length: Length of the data to be received * @param pipe_num: Pipe Number * @retval USBH Status. */ USBH_StatusTypeDef USBH_IsocReceiveData(USBH_HandleTypeDef *phost, uint8_t *buff, uint32_t length, uint8_t pipe_num) { USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 1, /* Direction : IN */ USBH_EP_ISO, /* EP type */ USBH_PID_DATA, /* Type Data */ buff, /* data buffer */ length, /* data length */ 0); return USBH_OK; } /** * @brief USBH_IsocSendData * Sends the data on Isochronous OUT Endpoint * @param phost: Host Handle * @param buff: Buffer pointer from where the data needs to be copied * @param length: Length of the data to be sent * @param pipe_num: Pipe Number * @retval USBH Status. */ USBH_StatusTypeDef USBH_IsocSendData(USBH_HandleTypeDef *phost, uint8_t *buff, uint32_t length, uint8_t pipe_num) { USBH_LL_SubmitURB (phost, /* Driver handle */ pipe_num, /* Pipe index */ 0, /* Direction : OUT */ USBH_EP_ISO, /* EP type */ USBH_PID_DATA, /* Type Data */ buff, /* data buffer */ length, /* data length */ 0); return USBH_OK; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usbhost/Core/Src/usbh_pipes.c000066400000000000000000000106751357706137100235650ustar00rootroot00000000000000/** ****************************************************************************** * @file usbh_pipes.c * @author MCD Application Team * @version V3.0.0 * @date 18-February-2014 * @brief This file implements functions for opening and closing Pipes ****************************************************************************** * @attention * *

© COPYRIGHT 2014 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbh_pipes.h" /** @addtogroup USBH_LIB * @{ */ /** @addtogroup USBH_LIB_CORE * @{ */ /** @defgroup USBH_PIPES * @brief This file includes opening and closing Pipes * @{ */ /** @defgroup USBH_PIPES_Private_Defines * @{ */ /** * @} */ /** @defgroup USBH_PIPES_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBH_PIPES_Private_Macros * @{ */ /** * @} */ /** @defgroup USBH_PIPES_Private_Variables * @{ */ /** * @} */ /** @defgroup USBH_PIPES_Private_Functions * @{ */ static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost); /** * @brief USBH_Open_Pipe * Open a pipe * @param phost: Host Handle * @param pipe_num: Pipe Number * @param dev_address: USB Device address allocated to attached device * @param speed : USB device speed (Full/Low) * @param ep_type: end point type (Bulk/int/ctl) * @param mps: max pkt size * @retval USBH Status */ USBH_StatusTypeDef USBH_OpenPipe (USBH_HandleTypeDef *phost, uint8_t pipe_num, uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) { USBH_LL_OpenPipe(phost, pipe_num, epnum, dev_address, speed, ep_type, mps); return USBH_OK; } /** * @brief USBH_ClosePipe * Close a pipe * @param phost: Host Handle * @param pipe_num: Pipe Number * @retval USBH Status */ USBH_StatusTypeDef USBH_ClosePipe (USBH_HandleTypeDef *phost, uint8_t pipe_num) { USBH_LL_ClosePipe(phost, pipe_num); return USBH_OK; } /** * @brief USBH_Alloc_Pipe * Allocate a new Pipe * @param phost: Host Handle * @param ep_addr: End point for which the Pipe to be allocated * @retval Pipe number */ uint8_t USBH_AllocPipe (USBH_HandleTypeDef *phost, uint8_t ep_addr) { uint16_t pipe; pipe = USBH_GetFreePipe(phost); if (pipe != 0xFFFF) { phost->Pipes[pipe] = 0x8000 | ep_addr; } return pipe; } /** * @brief USBH_Free_Pipe * Free the USB Pipe * @param phost: Host Handle * @param idx: Pipe number to be freed * @retval USBH Status */ USBH_StatusTypeDef USBH_FreePipe (USBH_HandleTypeDef *phost, uint8_t idx) { if(idx < 11) { phost->Pipes[idx] &= 0x7FFF; } return USBH_OK; } /** * @brief USBH_GetFreePipe * @param phost: Host Handle * Get a free Pipe number for allocation to a device endpoint * @retval idx: Free Pipe number */ static uint16_t USBH_GetFreePipe (USBH_HandleTypeDef *phost) { uint8_t idx = 0; for (idx = 0 ; idx < 11 ; idx++) { if ((phost->Pipes[idx] & 0x8000) == 0) { return idx; } } return 0xFFFF; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ micropython-1.12/ports/stm32/usrsw.c000066400000000000000000000125471357706137100175010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "py/mphal.h" #include "extint.h" #include "pin.h" #include "usrsw.h" #if MICROPY_HW_HAS_SWITCH /// \moduleref pyb /// \class Switch - switch object /// /// A Switch object is used to control a push-button switch. /// /// Usage: /// /// sw = pyb.Switch() # create a switch object /// sw() # get state (True if pressed, False otherwise) /// sw.callback(f) # register a callback to be called when the /// # switch is pressed down /// sw.callback(None) # remove the callback /// /// Example: /// /// pyb.Switch().callback(lambda: pyb.LED(1).toggle()) // this function inits the switch GPIO so that it can be used void switch_init0(void) { mp_hal_pin_config(MICROPY_HW_USRSW_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_USRSW_PULL, 0); } int switch_get(void) { int val = ((MICROPY_HW_USRSW_PIN->gpio->IDR & MICROPY_HW_USRSW_PIN->pin_mask) != 0); return val == MICROPY_HW_USRSW_PRESSED; } /******************************************************************************/ // MicroPython bindings typedef struct _pyb_switch_obj_t { mp_obj_base_t base; } pyb_switch_obj_t; STATIC const pyb_switch_obj_t pyb_switch_obj = {{&pyb_switch_type}}; void pyb_switch_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_print_str(print, "Switch()"); } /// \classmethod \constructor() /// Create and return a switch object. STATIC mp_obj_t pyb_switch_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); // No need to clear the callback member: if it's already been set and registered // with extint then we don't want to reset that behaviour. If it hasn't been set, // then no extint will be called until it is set via the callback method. // return static switch object return MP_OBJ_FROM_PTR(&pyb_switch_obj); } /// \method \call() /// Return the switch state: `True` if pressed down, `False` otherwise. mp_obj_t pyb_switch_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { // get switch state mp_arg_check_num(n_args, n_kw, 0, 0, false); return switch_get() ? mp_const_true : mp_const_false; } mp_obj_t pyb_switch_value(mp_obj_t self_in) { (void)self_in; return mp_obj_new_bool(switch_get()); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_switch_value_obj, pyb_switch_value); STATIC mp_obj_t switch_callback(mp_obj_t line) { if (MP_STATE_PORT(pyb_switch_callback) != mp_const_none) { mp_call_function_0(MP_STATE_PORT(pyb_switch_callback)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(switch_callback_obj, switch_callback); /// \method callback(fun) /// Register the given function to be called when the switch is pressed down. /// If `fun` is `None`, then it disables the callback. mp_obj_t pyb_switch_callback(mp_obj_t self_in, mp_obj_t callback) { MP_STATE_PORT(pyb_switch_callback) = callback; // Init the EXTI each time this function is called, since the EXTI // may have been disabled by an exception in the interrupt, or the // user disabling the line explicitly. extint_register(MP_OBJ_FROM_PTR(MICROPY_HW_USRSW_PIN), MICROPY_HW_USRSW_EXTI_MODE, MICROPY_HW_USRSW_PULL, callback == mp_const_none ? mp_const_none : MP_OBJ_FROM_PTR(&switch_callback_obj), true); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_switch_callback_obj, pyb_switch_callback); STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&pyb_switch_value_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&pyb_switch_callback_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table); const mp_obj_type_t pyb_switch_type = { { &mp_type_type }, .name = MP_QSTR_Switch, .print = pyb_switch_print, .make_new = pyb_switch_make_new, .call = pyb_switch_call, .locals_dict = (mp_obj_dict_t*)&pyb_switch_locals_dict, }; #endif // MICROPY_HW_HAS_SWITCH micropython-1.12/ports/stm32/usrsw.h000066400000000000000000000026441357706137100175030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_USRSW_H #define MICROPY_INCLUDED_STM32_USRSW_H void switch_init0(void); int switch_get(void); extern const mp_obj_type_t pyb_switch_type; #endif // MICROPY_INCLUDED_STM32_USRSW_H micropython-1.12/ports/stm32/wdt.c000066400000000000000000000067121357706137100171110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include "wdt.h" #if defined(STM32H7) #define IWDG (IWDG1) #endif typedef struct _pyb_wdt_obj_t { mp_obj_base_t base; } pyb_wdt_obj_t; STATIC const pyb_wdt_obj_t pyb_wdt = {{&pyb_wdt_type}}; STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse arguments enum { ARG_id, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_int_t id = args[ARG_id].u_int; if (id != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "WDT(%d) doesn't exist", id)); } // timeout is in milliseconds mp_int_t timeout = args[ARG_timeout].u_int; // compute prescaler uint32_t prescaler; for (prescaler = 0; prescaler < 6 && timeout >= 512; ++prescaler, timeout /= 2) { } // convert milliseconds to ticks timeout *= 8; // 32kHz / 4 = 8 ticks per millisecond (approx) if (timeout <= 0) { mp_raise_ValueError("WDT timeout too short"); } else if (timeout > 0xfff) { mp_raise_ValueError("WDT timeout too long"); } timeout -= 1; // set the reload register while (IWDG->SR & 2) { } IWDG->KR = 0x5555; IWDG->RLR = timeout; // set the prescaler while (IWDG->SR & 1) { } IWDG->KR = 0x5555; IWDG->PR = prescaler; // start the watch dog IWDG->KR = 0xcccc; return MP_OBJ_FROM_PTR(&pyb_wdt); } STATIC mp_obj_t pyb_wdt_feed(mp_obj_t self_in) { (void)self_in; IWDG->KR = 0xaaaa; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_wdt_feed_obj, pyb_wdt_feed); STATIC const mp_rom_map_elem_t pyb_wdt_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&pyb_wdt_feed_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_wdt_locals_dict, pyb_wdt_locals_dict_table); const mp_obj_type_t pyb_wdt_type = { { &mp_type_type }, .name = MP_QSTR_WDT, .make_new = pyb_wdt_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_wdt_locals_dict, }; micropython-1.12/ports/stm32/wdt.h000066400000000000000000000025451357706137100171160ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32_WDT_H #define MICROPY_INCLUDED_STM32_WDT_H extern const mp_obj_type_t pyb_wdt_type; #endif // MICROPY_INCLUDED_STM32_WDT_H micropython-1.12/ports/teensy/000077500000000000000000000000001357706137100165005ustar00rootroot00000000000000micropython-1.12/ports/teensy/Makefile000066400000000000000000000141151357706137100201420ustar00rootroot00000000000000include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h # include py core make definitions include $(TOP)/py/py.mk # If you set USE_ARDUINO_TOOLCHAIN=1 then this makefile will attempt to use # the toolchain that comes with Teensyduino ifeq ($(USE_ARDUINO_TOOLCHAIN),) USE_ARDUINO_TOOLCHAIN = 0 endif ifeq ($(USE_ARDUINO_TOOLCHAIN),1) ifeq ($(ARDUINO),) $(error USE_ARDUINO_TOOLCHAIN requires that ARDUINO be set) endif endif ifeq ($(USE_ARDUINO_TOOLCHAIN),1) $(info Using ARDUINO toolchain) CROSS_COMPILE = $(ARDUINO)/hardware/tools/arm-none-eabi/bin/arm-none-eabi- else $(info Using toolchain from PATH) CROSS_COMPILE = arm-none-eabi- endif CFLAGS_TEENSY = -DF_CPU=96000000 -DUSB_SERIAL -D__MK20DX256__ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion $(CFLAGS_TEENSY) INC += -I. INC += -I$(TOP) INC += -I$(TOP)/ports/stm32 INC += -I$(BUILD) INC += -Icore CFLAGS = $(INC) -Wall -Wpointer-arith -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) LDFLAGS = -nostdlib -T mk20dx256.ld -msoft-float -mfloat-abi=soft ifeq ($(USE_ARDUINO_TOOLCHAIN),1) LIBGCC_FILE_NAME = $(ARDUINO)/hardware/tools/arm-none-eabi/lib/gcc/arm-none-eabi/4.7.2/thumb2/libgcc.a LIBM_FILE_NAME = $(ARDUINO)/hardware/tools/arm-none-eabi/arm-none-eabi/lib/thumb2/libm.a LIBC_FILE_NAME = $(ARDUINO)/hardware/tools/arm-none-eabi/arm-none-eabi/lib/thumb2/libc.a else LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBM_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-file-name=libm.a) LIBC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-file-name=libc.a) endif #$(info %%%%% LIBGCC_FILE_NAME = $(LIBGCC_FILE_NAME)) #$(info %%%%% LIBM_FILE_NAME = $(LIBM_FILE_NAME)) #$(info %%%%% LIBC_FILE_NAME = $(LIBC_FILE_NAME)) #$(info %%%%% dirname LIBGCC_FILE_NAME = $(dir $(LIBGCC_FILE_NAME))) #$(info %%%%% dirname LIBM_FILE_NAME = $(dir $(LIBM_FILE_NAME))) #$(info %%%%% dirname LIBC_FILE_NAME = $(dir $(LIBC_FILE_NAME))) LIBS = -L $(dir $(LIBM_FILE_NAME)) -lm LIBS += -L $(dir $(LIBC_FILE_NAME)) -lc LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc #Debugging/Optimization ifdef DEBUG CFLAGS += -Og -ggdb else CFLAGS += -Os #-DNDEBUG endif CFLAGS += -fdata-sections -ffunction-sections LDFLAGS += -Wl,--gc-sections USE_FROZEN = 1 USE_MEMZIP = 0 SRC_C = \ hal_ftm.c \ hal_gpio.c \ help.c \ main.c \ lcd.c \ led.c \ modpyb.c \ pin_defs_teensy.c \ reg.c \ teensy_hal.c \ timer.c \ uart.c \ usb.c \ STM_SRC_C = $(addprefix ports/stm32/,\ gccollect.c \ irq.c \ pin.c \ pin_named_pins.c \ ) LIB_SRC_C = $(addprefix lib/,\ libc/string0.c \ mp-readline/readline.c \ utils/pyexec.c \ utils/sys_stdio_mphal.c \ ) SRC_TEENSY = $(addprefix core/,\ mk20dx128.c \ pins_teensy.c \ analog.c \ usb_desc.c \ usb_dev.c \ usb_mem.c \ usb_serial.c \ yield.c \ ) OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(SRC_TEENSY:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ += $(BUILD)/lib/utils/gchelper_m3.o OBJ += $(BUILD)/pins_gen.o all: hex hex: $(BUILD)/micropython.hex ifeq ($(USE_MEMZIP),1) SRC_C += \ lib/memzip/import.c \ lib/memzip/lexermemzip.c \ lib/memzip/memzip.c \ OBJ += $(BUILD)/memzip-files.o MAKE_MEMZIP = $(TOP)/lib/memzip/make-memzip.py ifeq ($(MEMZIP_DIR),) MEMZIP_DIR = memzip_files endif $(BUILD)/memzip-files.o: $(BUILD)/memzip-files.c $(call compile_c) $(BUILD)/memzip-files.c: $(shell find ${MEMZIP_DIR} -type f) @$(ECHO) "Creating $@" $(Q)$(PYTHON) $(MAKE_MEMZIP) --zip-file $(BUILD)/memzip-files.zip --c-file $@ $(MEMZIP_DIR) endif # USE_MEMZIP ifeq ($(USE_FROZEN),1) ifeq ($(FROZEN_DIR),) FROZEN_DIR = memzip_files endif CFLAGS += -DMICROPY_MODULE_FROZEN_STR SRC_C += \ lexerfrozen.c \ $(BUILD)/frozen.c endif # USE_FROZEN ifeq ($(ARDUINO),) post_compile: $(BUILD)/micropython.hex $(ECHO) "Please define ARDUINO (where TeensyDuino is installed)" exit 1 reboot: $(ECHO) "Please define ARDUINO (where TeensyDuino is installed)" exit 1 else TOOLS_PATH = $(ARDUINO)/hardware/tools post_compile: $(BUILD)/micropython.hex $(ECHO) "Preparing $@ for upload" $(Q)$(TOOLS_PATH)/teensy_post_compile -file="$(basename $( $(GEN_PINS_SRC) $(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c $(call compile_c) $(BUILD)/%.pp: $(BUILD)/%.c $(ECHO) "PreProcess $<" $(Q)$(CC) $(CFLAGS) -E -Wp,-C,-dD,-dI -o $@ $< include $(TOP)/py/mkrules.mk micropython-1.12/ports/teensy/README.md000066400000000000000000000045541357706137100177670ustar00rootroot00000000000000# Build Instructions for Teensy 3.1 Currently the Teensy 3.1 port of MicroPython builds under Linux and not under Windows. The tool chain required for the build can be found at . Download the current Linux *.tar.bz2 file. Instructions regarding unpacking the file and moving it to the correct location as well as adding the extracted folders to the enviroment variable can be found at In order to download the firmware image to the teensy, you'll need to use the downloader included with TeensyDuino. The following assumes that you have TeensyDuino installed and set the ARDUINO environment variable pointing to the where Arduino with TeensyDuino is installed. ```bash cd teensy ARDUINO=~/arduino-1.0.5 make ``` To upload MicroPython to the Teensy 3.1. Press the Program button on the Teensy 3.1 ```bash sudo ARDUINO=~/arduino-1.0.5/ make deploy ``` Currently, the Python prompt is through the USB serial interface, i.e. ```bash minicom -D /dev/ttyACM0 ``` ## TIPS ### Install 49-teensy.rules into /etc/udev/rules.d If you install the 49-teensy.rules file from http://www.pjrc.com/teensy/49-teensy.rules into your ```/etc/udev/rules.d``` folder then you won't need to use sudo: ```bash sudo cp ~/Downloads/49-teensy.rules /etc/udev/rules.d sudo udevadm control --reload-rules ``` Unplug and replug the teensy board, and then you can use: ```ARDUINO=~/arduino-1.0.5/ make deploy``` ### Create a GNUmakefile to hold your ARDUINO setting. Create a file call GNUmakefile (note the lowercase m) in the teensy folder with the following contents: ```make $(info Executing GNUmakefile) ARDUINO=${HOME}/arduino-1.0.5 $(info ARDUINO=${ARDUINO}) include Makefile ``` GNUmakefile is not checked into the source code control system, so it will retain your settings when updating your source tree. You can also add additional Makefile customizations this way. ### Tips for OSX Set the ARDUINO environment variable to the location where Arduino with TeensyDuino is installed. ```bash export ARDUINO=~/Downloads/Arduino.app/Contents/Java/ ``` Search /dev/ for USB port name, which will be cu.usbmodem followed by a few numbers. The name of the port maybe different depending on the version of OSX. To access the Python prompt type: ```bash screen 115200 ``` micropython-1.12/ports/teensy/add-memzip.sh000077500000000000000000000012271357706137100210700ustar00rootroot00000000000000#!/bin/bash if [ "$#" != 3 ]; then echo "Usage: add-memzip.sh input.hex output.hex file-directory" exit 1 fi #set -x input_hex=$1 output_hex=$2 memzip_src_dir=$3 input_bin=${input_hex}.bin output_bin=${output_hex}.bin zip_file=${output_hex}.zip zip_base=$(basename ${zip_file}) zip_dir=$(dirname ${zip_file}) abs_zip_dir=$(realpath ${zip_dir}) rm -f ${zip_file} (cd ${memzip_src_dir}; zip -0 -r -D ${abs_zip_dir}/${zip_base} .) objcopy -I ihex -O binary ${input_hex} ${input_bin} cat ${input_bin} ${zip_file} > ${output_bin} objcopy -I binary -O ihex ${output_bin} ${output_hex} echo "Added ${memzip_src_dir} to ${input_hex} creating ${output_hex}" micropython-1.12/ports/teensy/core/000077500000000000000000000000001357706137100174305ustar00rootroot00000000000000micropython-1.12/ports/teensy/core/Arduino.h000066400000000000000000000001111357706137100211730ustar00rootroot00000000000000//#include "WProgram.h" #include "core_pins.h" #include "pins_arduino.h" micropython-1.12/ports/teensy/core/HardwareSerial.h000066400000000000000000000202721357706137100225010ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef HardwareSerial_h #define HardwareSerial_h #include "mk20dx128.h" #include // uncomment to enable 9 bit formats //#define SERIAL_9BIT_SUPPORT #define SERIAL_7E1 0x02 #define SERIAL_7O1 0x03 #define SERIAL_8N1 0x00 #define SERIAL_8N2 0x04 #define SERIAL_8E1 0x06 #define SERIAL_8O1 0x07 #define SERIAL_7E1_RXINV 0x12 #define SERIAL_7O1_RXINV 0x13 #define SERIAL_8N1_RXINV 0x10 #define SERIAL_8N2_RXINV 0x14 #define SERIAL_8E1_RXINV 0x16 #define SERIAL_8O1_RXINV 0x17 #define SERIAL_7E1_TXINV 0x22 #define SERIAL_7O1_TXINV 0x23 #define SERIAL_8N1_TXINV 0x20 #define SERIAL_8N2_TXINV 0x24 #define SERIAL_8E1_TXINV 0x26 #define SERIAL_8O1_TXINV 0x27 #define SERIAL_7E1_RXINV_TXINV 0x32 #define SERIAL_7O1_RXINV_TXINV 0x33 #define SERIAL_8N1_RXINV_TXINV 0x30 #define SERIAL_8N2_RXINV_TXINV 0x34 #define SERIAL_8E1_RXINV_TXINV 0x36 #define SERIAL_8O1_RXINV_TXINV 0x37 #ifdef SERIAL_9BIT_SUPPORT #define SERIAL_9N1 0x84 #define SERIAL_9E1 0x8E #define SERIAL_9O1 0x8F #define SERIAL_9N1_RXINV 0x94 #define SERIAL_9E1_RXINV 0x9E #define SERIAL_9O1_RXINV 0x9F #define SERIAL_9N1_TXINV 0xA4 #define SERIAL_9E1_TXINV 0xAE #define SERIAL_9O1_TXINV 0xAF #define SERIAL_9N1_RXINV_TXINV 0xB4 #define SERIAL_9E1_RXINV_TXINV 0xBE #define SERIAL_9O1_RXINV_TXINV 0xBF #endif // bit0: parity, 0=even, 1=odd // bit1: parity, 0=disable, 1=enable // bit2: mode, 1=9bit, 0=8bit // bit3: mode10: 1=10bit, 0=8bit // bit4: rxinv, 0=normal, 1=inverted // bit5: txinv, 0=normal, 1=inverted // bit6: unused // bit7: actual data goes into 9th bit #define BAUD2DIV(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud)) #define BAUD2DIV3(baud) (((F_BUS * 2) + ((baud) >> 1)) / (baud)) // C language implementation // #ifdef __cplusplus extern "C" { #endif void serial_begin(uint32_t divisor); void serial_format(uint32_t format); void serial_end(void); void serial_set_transmit_pin(uint8_t pin); void serial_putchar(uint32_t c); void serial_write(const void *buf, unsigned int count); void serial_flush(void); int serial_available(void); int serial_getchar(void); int serial_peek(void); void serial_clear(void); void serial_print(const char *p); void serial_phex(uint32_t n); void serial_phex16(uint32_t n); void serial_phex32(uint32_t n); void serial2_begin(uint32_t divisor); void serial2_format(uint32_t format); void serial2_end(void); void serial2_putchar(uint32_t c); void serial2_write(const void *buf, unsigned int count); void serial2_flush(void); int serial2_available(void); int serial2_getchar(void); int serial2_peek(void); void serial2_clear(void); void serial3_begin(uint32_t divisor); void serial3_format(uint32_t format); void serial3_end(void); void serial3_putchar(uint32_t c); void serial3_write(const void *buf, unsigned int count); void serial3_flush(void); int serial3_available(void); int serial3_getchar(void); int serial3_peek(void); void serial3_clear(void); #ifdef __cplusplus } #endif // C++ interface // #ifdef __cplusplus #include "Stream.h" class HardwareSerial : public Stream { public: virtual void begin(uint32_t baud) { serial_begin(BAUD2DIV(baud)); } virtual void begin(uint32_t baud, uint32_t format) { serial_begin(BAUD2DIV(baud)); serial_format(format); } virtual void end(void) { serial_end(); } virtual void transmitterEnable(uint8_t pin) { serial_set_transmit_pin(pin); } virtual int available(void) { return serial_available(); } virtual int peek(void) { return serial_peek(); } virtual int read(void) { return serial_getchar(); } virtual void flush(void) { serial_flush(); } virtual void clear(void) { serial_clear(); } virtual size_t write(uint8_t c) { serial_putchar(c); return 1; } virtual size_t write(unsigned long n) { return write((uint8_t)n); } virtual size_t write(long n) { return write((uint8_t)n); } virtual size_t write(unsigned int n) { return write((uint8_t)n); } virtual size_t write(int n) { return write((uint8_t)n); } virtual size_t write(const uint8_t *buffer, size_t size) { serial_write(buffer, size); return size; } virtual size_t write(const char *str) { size_t len = strlen(str); serial_write((const uint8_t *)str, len); return len; } virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; } }; extern HardwareSerial Serial1; class HardwareSerial2 : public HardwareSerial { public: virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV(baud)); } virtual void begin(uint32_t baud, uint32_t format) { serial2_begin(BAUD2DIV(baud)); serial2_format(format); } virtual void end(void) { serial2_end(); } virtual int available(void) { return serial2_available(); } virtual int peek(void) { return serial2_peek(); } virtual int read(void) { return serial2_getchar(); } virtual void flush(void) { serial2_flush(); } virtual void clear(void) { serial2_clear(); } virtual size_t write(uint8_t c) { serial2_putchar(c); return 1; } virtual size_t write(unsigned long n) { return write((uint8_t)n); } virtual size_t write(long n) { return write((uint8_t)n); } virtual size_t write(unsigned int n) { return write((uint8_t)n); } virtual size_t write(int n) { return write((uint8_t)n); } virtual size_t write(const uint8_t *buffer, size_t size) { serial2_write(buffer, size); return size; } virtual size_t write(const char *str) { size_t len = strlen(str); serial2_write((const uint8_t *)str, len); return len; } virtual size_t write9bit(uint32_t c) { serial2_putchar(c); return 1; } }; extern HardwareSerial2 Serial2; class HardwareSerial3 : public HardwareSerial { public: virtual void begin(uint32_t baud) { serial3_begin(BAUD2DIV3(baud)); } virtual void begin(uint32_t baud, uint32_t format) { serial3_begin(BAUD2DIV3(baud)); serial3_format(format); } virtual void end(void) { serial3_end(); } virtual int available(void) { return serial3_available(); } virtual int peek(void) { return serial3_peek(); } virtual int read(void) { return serial3_getchar(); } virtual void flush(void) { serial3_flush(); } virtual void clear(void) { serial3_clear(); } virtual size_t write(uint8_t c) { serial3_putchar(c); return 1; } virtual size_t write(unsigned long n) { return write((uint8_t)n); } virtual size_t write(long n) { return write((uint8_t)n); } virtual size_t write(unsigned int n) { return write((uint8_t)n); } virtual size_t write(int n) { return write((uint8_t)n); } virtual size_t write(const uint8_t *buffer, size_t size) { serial3_write(buffer, size); return size; } virtual size_t write(const char *str) { size_t len = strlen(str); serial3_write((const uint8_t *)str, len); return len; } virtual size_t write9bit(uint32_t c) { serial3_putchar(c); return 1; } }; extern HardwareSerial3 Serial3; #endif #endif micropython-1.12/ports/teensy/core/analog.c000066400000000000000000000330051357706137100210360ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "core_pins.h" //#include "HardwareSerial.h" static uint8_t calibrating; static uint8_t analog_right_shift = 0; static uint8_t analog_config_bits = 10; static uint8_t analog_num_average = 4; static uint8_t analog_reference_internal = 0; // the alternate clock is connected to OSCERCLK (16 MHz). // datasheet says ADC clock should be 2 to 12 MHz for 16 bit mode // datasheet says ADC clock should be 1 to 18 MHz for 8-12 bit mode #if F_BUS == 60000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 7.5 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz #elif F_BUS == 56000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 7 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz #elif F_BUS == 48000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 24 MHz #elif F_BUS == 40000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 20 MHz #elif F_BUS == 36000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 9 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz #elif F_BUS == 24000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 24 MHz #elif F_BUS == 16000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 16 MHz #elif F_BUS == 8000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz #elif F_BUS == 4000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz #elif F_BUS == 2000000 #define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz #else #error "F_BUS must be 60, 56, 48, 40, 36, 24, 4 or 2 MHz" #endif void analog_init(void) { uint32_t num; VREF_TRM = 0x60; VREF_SC = 0xE1; // enable 1.2 volt ref if (analog_config_bits == 8) { ADC0_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0); ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); #if defined(__MK20DX256__) ADC1_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0); ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); #endif } else if (analog_config_bits == 10) { ADC0_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); #if defined(__MK20DX256__) ADC1_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); #endif } else if (analog_config_bits == 12) { ADC0_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); #if defined(__MK20DX256__) ADC1_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); #endif } else { ADC0_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); #if defined(__MK20DX256__) ADC1_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); #endif } if (analog_reference_internal) { ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref #if defined(__MK20DX256__) ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref #endif } else { ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref #if defined(__MK20DX256__) ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref #endif } num = analog_num_average; if (num <= 1) { ADC0_SC3 = ADC_SC3_CAL; // begin cal #if defined(__MK20DX256__) ADC1_SC3 = ADC_SC3_CAL; // begin cal #endif } else if (num <= 4) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); #if defined(__MK20DX256__) ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); #endif } else if (num <= 8) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); #if defined(__MK20DX256__) ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); #endif } else if (num <= 16) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); #if defined(__MK20DX256__) ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); #endif } else { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); #if defined(__MK20DX256__) ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); #endif } calibrating = 1; } static void wait_for_cal(void) { uint16_t sum; //serial_print("wait_for_cal\n"); #if defined(__MK20DX128__) while (ADC0_SC3 & ADC_SC3_CAL) { // wait } #elif defined(__MK20DX256__) while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) { // wait } #endif __disable_irq(); if (calibrating) { //serial_print("\n"); sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; sum = (sum / 2) | 0x8000; ADC0_PG = sum; //serial_print("ADC0_PG = "); //serial_phex16(sum); //serial_print("\n"); sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0; sum = (sum / 2) | 0x8000; ADC0_MG = sum; //serial_print("ADC0_MG = "); //serial_phex16(sum); //serial_print("\n"); #if defined(__MK20DX256__) sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; sum = (sum / 2) | 0x8000; ADC1_PG = sum; sum = ADC1_CLMS + ADC1_CLM4 + ADC1_CLM3 + ADC1_CLM2 + ADC1_CLM1 + ADC1_CLM0; sum = (sum / 2) | 0x8000; ADC1_MG = sum; #endif calibrating = 0; } __enable_irq(); } // ADCx_SC2[REFSEL] bit selects the voltage reference sources for ADC. // VREFH/VREFL - connected as the primary reference option // 1.2 V VREF_OUT - connected as the VALT reference option #define DEFAULT 0 #define INTERNAL 2 #define INTERNAL1V2 2 #define INTERNAL1V1 2 #define EXTERNAL 0 void analogReference(uint8_t type) { if (type) { // internal reference requested if (!analog_reference_internal) { analog_reference_internal = 1; if (calibrating) { ADC0_SC3 = 0; // cancel cal #if defined(__MK20DX256__) ADC1_SC3 = 0; // cancel cal #endif } analog_init(); } } else { // vcc or external reference requested if (analog_reference_internal) { analog_reference_internal = 0; if (calibrating) { ADC0_SC3 = 0; // cancel cal #if defined(__MK20DX256__) ADC1_SC3 = 0; // cancel cal #endif } analog_init(); } } } void analogReadRes(unsigned int bits) { unsigned int config; if (bits >= 13) { if (bits > 16) bits = 16; config = 16; } else if (bits >= 11) { config = 12; } else if (bits >= 9) { config = 10; } else { config = 8; } analog_right_shift = config - bits; if (config != analog_config_bits) { analog_config_bits = config; if (calibrating) ADC0_SC3 = 0; // cancel cal analog_init(); } } void analogReadAveraging(unsigned int num) { if (calibrating) wait_for_cal(); if (num <= 1) { num = 0; ADC0_SC3 = 0; } else if (num <= 4) { num = 4; ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0); } else if (num <= 8) { num = 8; ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1); } else if (num <= 16) { num = 16; ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2); } else { num = 32; ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3); } analog_num_average = num; } // The SC1A register is used for both software and hardware trigger modes of operation. #if defined(__MK20DX128__) static const uint8_t channel2sc1a[] = { 5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 0, 19, 3, 21, 26, 22, 23 }; #elif defined(__MK20DX256__) static const uint8_t channel2sc1a[] = { 5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 0, 19, 3, 19+128, 26, 18+128, 23, 5+192, 5+128, 4+128, 6+128, 7+128, 4+192 // A15 26 E1 ADC1_SE5a 5+64 // A16 27 C9 ADC1_SE5b 5 // A17 28 C8 ADC1_SE4b 4 // A18 29 C10 ADC1_SE6b 6 // A19 30 C11 ADC1_SE7b 7 // A20 31 E0 ADC1_SE4a 4+64 }; #endif // TODO: perhaps this should store the NVIC priority, so it works recursively? static volatile uint8_t analogReadBusyADC0 = 0; #if defined(__MK20DX256__) static volatile uint8_t analogReadBusyADC1 = 0; #endif int analogRead(uint8_t pin) { int result; uint8_t index, channel; //serial_phex(pin); //serial_print(" "); if (pin <= 13) { index = pin; // 0-13 refer to A0-A13 } else if (pin <= 23) { index = pin - 14; // 14-23 are A0-A9 #if defined(__MK20DX256__) } else if (pin >= 26 && pin <= 31) { index = pin - 9; // 26-31 are A15-A20 #endif } else if (pin >= 34 && pin <= 40) { index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor, // 39 is vref, 40 is unused (A14 on Teensy 3.1) } else { return 0; // all others are invalid } //serial_phex(index); //serial_print(" "); channel = channel2sc1a[index]; //serial_phex(channel); //serial_print(" "); //serial_print("analogRead"); //return 0; if (calibrating) wait_for_cal(); //pin = 5; // PTD1/SE5b, pin 14, analog 0 #if defined(__MK20DX256__) if (channel & 0x80) goto beginADC1; #endif __disable_irq(); startADC0: //serial_print("startADC0\n"); ADC0_SC1A = channel; analogReadBusyADC0 = 1; __enable_irq(); while (1) { __disable_irq(); if ((ADC0_SC1A & ADC_SC1_COCO)) { result = ADC0_RA; analogReadBusyADC0 = 0; __enable_irq(); result >>= analog_right_shift; return result; } // detect if analogRead was used from an interrupt // if so, our analogRead got canceled, so it must // be restarted. if (!analogReadBusyADC0) goto startADC0; __enable_irq(); yield(); } #if defined(__MK20DX256__) beginADC1: __disable_irq(); startADC1: //serial_print("startADC0\n"); // ADC1_CFG2[MUXSEL] bit selects between ADCx_SEn channels a and b. if (channel & 0x40) { ADC1_CFG2 &= ~ADC_CFG2_MUXSEL; } else { ADC1_CFG2 |= ADC_CFG2_MUXSEL; } ADC1_SC1A = channel & 0x3F; analogReadBusyADC1 = 1; __enable_irq(); while (1) { __disable_irq(); if ((ADC1_SC1A & ADC_SC1_COCO)) { result = ADC1_RA; analogReadBusyADC1 = 0; __enable_irq(); result >>= analog_right_shift; return result; } // detect if analogRead was used from an interrupt // if so, our analogRead got canceled, so it must // be restarted. if (!analogReadBusyADC1) goto startADC1; __enable_irq(); yield(); } #endif } void analogWriteDAC0(int val) { #if defined(__MK20DX256__) SIM_SCGC2 |= SIM_SCGC2_DAC0; if (analog_reference_internal) { DAC0_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1 } else { DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2 } if (val < 0) val = 0; // TODO: saturate instruction? else if (val > 4095) val = 4095; *(int16_t *)&(DAC0_DAT0L) = val; #endif } micropython-1.12/ports/teensy/core/avr_functions.h000066400000000000000000000106211357706137100224610ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef _avr_functions_h_ #define _avr_functions_h_ #include #ifdef __cplusplus extern "C" { #endif void eeprom_initialize(void); uint8_t eeprom_read_byte(const uint8_t *addr) __attribute__ ((pure)); uint16_t eeprom_read_word(const uint16_t *addr) __attribute__ ((pure)); uint32_t eeprom_read_dword(const uint32_t *addr) __attribute__ ((pure)); void eeprom_read_block(void *buf, const void *addr, uint32_t len); void eeprom_write_byte(uint8_t *addr, uint8_t value); void eeprom_write_word(uint16_t *addr, uint16_t value); void eeprom_write_dword(uint32_t *addr, uint32_t value); void eeprom_write_block(const void *buf, void *addr, uint32_t len); int eeprom_is_ready(void); #define eeprom_busy_wait() do {} while (!eeprom_is_ready()) static inline float eeprom_read_float(const float *addr) __attribute__((pure, always_inline, unused)); static inline float eeprom_read_float(const float *addr) { union {float f; uint32_t u32;} u; u.u32 = eeprom_read_dword((const uint32_t *)addr); return u.f; } static inline void eeprom_write_float(float *addr, float value) __attribute__((always_inline, unused)); static inline void eeprom_write_float(float *addr, float value) { union {float f; uint32_t u32;} u; u.f = value; eeprom_write_dword((uint32_t *)addr, u.u32); } static inline void eeprom_update_byte(uint8_t *addr, uint8_t value) __attribute__((always_inline, unused)); static inline void eeprom_update_byte(uint8_t *addr, uint8_t value) { eeprom_write_byte(addr, value); } static inline void eeprom_update_word(uint16_t *addr, uint16_t value) __attribute__((always_inline, unused)); static inline void eeprom_update_word(uint16_t *addr, uint16_t value) { eeprom_write_word(addr, value); } static inline void eeprom_update_dword(uint32_t *addr, uint32_t value) __attribute__((always_inline, unused)); static inline void eeprom_update_dword(uint32_t *addr, uint32_t value) { eeprom_write_dword(addr, value); } static inline void eeprom_update_float(float *addr, float value) __attribute__((always_inline, unused)); static inline void eeprom_update_float(float *addr, float value) { union {float f; uint32_t u32;} u; u.f = value; eeprom_write_dword((uint32_t *)addr, u.u32); } static inline void eeprom_update_block(const void *buf, void *addr, uint32_t len) __attribute__((always_inline, unused)); static inline void eeprom_update_block(const void *buf, void *addr, uint32_t len) { eeprom_write_block(buf, addr, len); } char * ultoa(unsigned long val, char *buf, int radix); char * ltoa(long val, char *buf, int radix); static inline char * utoa(unsigned int val, char *buf, int radix) __attribute__((always_inline, unused)); static inline char * utoa(unsigned int val, char *buf, int radix) { return ultoa(val, buf, radix); } static inline char * itoa(int val, char *buf, int radix) __attribute__((always_inline, unused)); static inline char * itoa(int val, char *buf, int radix) { return ltoa(val, buf, radix); } char * dtostrf(float val, int width, unsigned int precision, char *buf); #ifdef __cplusplus } #endif #endif micropython-1.12/ports/teensy/core/core_pins.h000066400000000000000000000655771357706137100216060ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef _core_pins_h_ #define _core_pins_h_ #include "mk20dx128.h" #include "pins_arduino.h" #define HIGH 1 #define LOW 0 #define INPUT 0 #define OUTPUT 1 #define INPUT_PULLUP 2 #define LSBFIRST 0 #define MSBFIRST 1 #define _BV(n) (1<<(n)) #define CHANGE 4 #define FALLING 2 #define RISING 3 // Pin Arduino // 0 B16 RXD // 1 B17 TXD // 2 D0 // 3 A12 FTM1_CH0 // 4 A13 FTM1_CH1 // 5 D7 FTM0_CH7 OC0B/T1 // 6 D4 FTM0_CH4 OC0A // 7 D2 // 8 D3 ICP1 // 9 C3 FTM0_CH2 OC1A // 10 C4 FTM0_CH3 SS/OC1B // 11 C6 MOSI/OC2A // 12 C7 MISO // 13 C5 SCK // 14 D1 // 15 C0 // 16 B0 (FTM1_CH0) // 17 B1 (FTM1_CH1) // 18 B3 SDA // 19 B2 SCL // 20 D5 FTM0_CH5 // 21 D6 FTM0_CH6 // 22 C1 FTM0_CH0 // 23 C2 FTM0_CH1 // 24 A5 (FTM0_CH2) // 25 B19 // 26 E1 // 27 C9 // 28 C8 // 29 C10 // 30 C11 // 31 E0 // 32 B18 // 33 A4 (FTM0_CH1) // (34) analog only // (35) analog only // (36) analog only // (37) analog only // not available to user: // A0 FTM0_CH5 SWD Clock // A1 FTM0_CH6 USB ID // A2 FTM0_CH7 SWD Trace // A3 FTM0_CH0 SWD Data #define CORE_NUM_TOTAL_PINS 34 #define CORE_NUM_DIGITAL 34 #define CORE_NUM_INTERRUPT 34 #if defined(__MK20DX128__) #define CORE_NUM_ANALOG 14 #define CORE_NUM_PWM 10 #elif defined(__MK20DX256__) #define CORE_NUM_ANALOG 21 #define CORE_NUM_PWM 12 #endif #define CORE_PIN0_BIT 16 #define CORE_PIN1_BIT 17 #define CORE_PIN2_BIT 0 #define CORE_PIN3_BIT 12 #define CORE_PIN4_BIT 13 #define CORE_PIN5_BIT 7 #define CORE_PIN6_BIT 4 #define CORE_PIN7_BIT 2 #define CORE_PIN8_BIT 3 #define CORE_PIN9_BIT 3 #define CORE_PIN10_BIT 4 #define CORE_PIN11_BIT 6 #define CORE_PIN12_BIT 7 #define CORE_PIN13_BIT 5 #define CORE_PIN14_BIT 1 #define CORE_PIN15_BIT 0 #define CORE_PIN16_BIT 0 #define CORE_PIN17_BIT 1 #define CORE_PIN18_BIT 3 #define CORE_PIN19_BIT 2 #define CORE_PIN20_BIT 5 #define CORE_PIN21_BIT 6 #define CORE_PIN22_BIT 1 #define CORE_PIN23_BIT 2 #define CORE_PIN24_BIT 5 #define CORE_PIN25_BIT 19 #define CORE_PIN26_BIT 1 #define CORE_PIN27_BIT 9 #define CORE_PIN28_BIT 8 #define CORE_PIN29_BIT 10 #define CORE_PIN30_BIT 11 #define CORE_PIN31_BIT 0 #define CORE_PIN32_BIT 18 #define CORE_PIN33_BIT 4 #define CORE_PIN0_BITMASK (1<<(CORE_PIN0_BIT)) #define CORE_PIN1_BITMASK (1<<(CORE_PIN1_BIT)) #define CORE_PIN2_BITMASK (1<<(CORE_PIN2_BIT)) #define CORE_PIN3_BITMASK (1<<(CORE_PIN3_BIT)) #define CORE_PIN4_BITMASK (1<<(CORE_PIN4_BIT)) #define CORE_PIN5_BITMASK (1<<(CORE_PIN5_BIT)) #define CORE_PIN6_BITMASK (1<<(CORE_PIN6_BIT)) #define CORE_PIN7_BITMASK (1<<(CORE_PIN7_BIT)) #define CORE_PIN8_BITMASK (1<<(CORE_PIN8_BIT)) #define CORE_PIN9_BITMASK (1<<(CORE_PIN9_BIT)) #define CORE_PIN10_BITMASK (1<<(CORE_PIN10_BIT)) #define CORE_PIN11_BITMASK (1<<(CORE_PIN11_BIT)) #define CORE_PIN12_BITMASK (1<<(CORE_PIN12_BIT)) #define CORE_PIN13_BITMASK (1<<(CORE_PIN13_BIT)) #define CORE_PIN14_BITMASK (1<<(CORE_PIN14_BIT)) #define CORE_PIN15_BITMASK (1<<(CORE_PIN15_BIT)) #define CORE_PIN16_BITMASK (1<<(CORE_PIN16_BIT)) #define CORE_PIN17_BITMASK (1<<(CORE_PIN17_BIT)) #define CORE_PIN18_BITMASK (1<<(CORE_PIN18_BIT)) #define CORE_PIN19_BITMASK (1<<(CORE_PIN19_BIT)) #define CORE_PIN20_BITMASK (1<<(CORE_PIN20_BIT)) #define CORE_PIN21_BITMASK (1<<(CORE_PIN21_BIT)) #define CORE_PIN22_BITMASK (1<<(CORE_PIN22_BIT)) #define CORE_PIN23_BITMASK (1<<(CORE_PIN23_BIT)) #define CORE_PIN24_BITMASK (1<<(CORE_PIN24_BIT)) #define CORE_PIN25_BITMASK (1<<(CORE_PIN25_BIT)) #define CORE_PIN26_BITMASK (1<<(CORE_PIN26_BIT)) #define CORE_PIN27_BITMASK (1<<(CORE_PIN27_BIT)) #define CORE_PIN28_BITMASK (1<<(CORE_PIN28_BIT)) #define CORE_PIN29_BITMASK (1<<(CORE_PIN29_BIT)) #define CORE_PIN30_BITMASK (1<<(CORE_PIN30_BIT)) #define CORE_PIN31_BITMASK (1<<(CORE_PIN31_BIT)) #define CORE_PIN32_BITMASK (1<<(CORE_PIN32_BIT)) #define CORE_PIN33_BITMASK (1<<(CORE_PIN33_BIT)) #define CORE_PIN0_PORTREG GPIOB_PDOR #define CORE_PIN1_PORTREG GPIOB_PDOR #define CORE_PIN2_PORTREG GPIOD_PDOR #define CORE_PIN3_PORTREG GPIOA_PDOR #define CORE_PIN4_PORTREG GPIOA_PDOR #define CORE_PIN5_PORTREG GPIOD_PDOR #define CORE_PIN6_PORTREG GPIOD_PDOR #define CORE_PIN7_PORTREG GPIOD_PDOR #define CORE_PIN8_PORTREG GPIOD_PDOR #define CORE_PIN9_PORTREG GPIOC_PDOR #define CORE_PIN10_PORTREG GPIOC_PDOR #define CORE_PIN11_PORTREG GPIOC_PDOR #define CORE_PIN12_PORTREG GPIOC_PDOR #define CORE_PIN13_PORTREG GPIOC_PDOR #define CORE_PIN14_PORTREG GPIOD_PDOR #define CORE_PIN15_PORTREG GPIOC_PDOR #define CORE_PIN16_PORTREG GPIOB_PDOR #define CORE_PIN17_PORTREG GPIOB_PDOR #define CORE_PIN18_PORTREG GPIOB_PDOR #define CORE_PIN19_PORTREG GPIOB_PDOR #define CORE_PIN20_PORTREG GPIOD_PDOR #define CORE_PIN21_PORTREG GPIOD_PDOR #define CORE_PIN22_PORTREG GPIOC_PDOR #define CORE_PIN23_PORTREG GPIOC_PDOR #define CORE_PIN24_PORTREG GPIOA_PDOR #define CORE_PIN25_PORTREG GPIOB_PDOR #define CORE_PIN26_PORTREG GPIOE_PDOR #define CORE_PIN27_PORTREG GPIOC_PDOR #define CORE_PIN28_PORTREG GPIOC_PDOR #define CORE_PIN29_PORTREG GPIOC_PDOR #define CORE_PIN30_PORTREG GPIOC_PDOR #define CORE_PIN31_PORTREG GPIOE_PDOR #define CORE_PIN32_PORTREG GPIOB_PDOR #define CORE_PIN33_PORTREG GPIOA_PDOR #define CORE_PIN0_PORTSET GPIOB_PSOR #define CORE_PIN1_PORTSET GPIOB_PSOR #define CORE_PIN2_PORTSET GPIOD_PSOR #define CORE_PIN3_PORTSET GPIOA_PSOR #define CORE_PIN4_PORTSET GPIOA_PSOR #define CORE_PIN5_PORTSET GPIOD_PSOR #define CORE_PIN6_PORTSET GPIOD_PSOR #define CORE_PIN7_PORTSET GPIOD_PSOR #define CORE_PIN8_PORTSET GPIOD_PSOR #define CORE_PIN9_PORTSET GPIOC_PSOR #define CORE_PIN10_PORTSET GPIOC_PSOR #define CORE_PIN11_PORTSET GPIOC_PSOR #define CORE_PIN12_PORTSET GPIOC_PSOR #define CORE_PIN13_PORTSET GPIOC_PSOR #define CORE_PIN14_PORTSET GPIOD_PSOR #define CORE_PIN15_PORTSET GPIOC_PSOR #define CORE_PIN16_PORTSET GPIOB_PSOR #define CORE_PIN17_PORTSET GPIOB_PSOR #define CORE_PIN18_PORTSET GPIOB_PSOR #define CORE_PIN19_PORTSET GPIOB_PSOR #define CORE_PIN20_PORTSET GPIOD_PSOR #define CORE_PIN21_PORTSET GPIOD_PSOR #define CORE_PIN22_PORTSET GPIOC_PSOR #define CORE_PIN23_PORTSET GPIOC_PSOR #define CORE_PIN24_PORTSET GPIOA_PSOR #define CORE_PIN25_PORTSET GPIOB_PSOR #define CORE_PIN26_PORTSET GPIOE_PSOR #define CORE_PIN27_PORTSET GPIOC_PSOR #define CORE_PIN28_PORTSET GPIOC_PSOR #define CORE_PIN29_PORTSET GPIOC_PSOR #define CORE_PIN30_PORTSET GPIOC_PSOR #define CORE_PIN31_PORTSET GPIOE_PSOR #define CORE_PIN32_PORTSET GPIOB_PSOR #define CORE_PIN33_PORTSET GPIOA_PSOR #define CORE_PIN0_PORTCLEAR GPIOB_PCOR #define CORE_PIN1_PORTCLEAR GPIOB_PCOR #define CORE_PIN2_PORTCLEAR GPIOD_PCOR #define CORE_PIN3_PORTCLEAR GPIOA_PCOR #define CORE_PIN4_PORTCLEAR GPIOA_PCOR #define CORE_PIN5_PORTCLEAR GPIOD_PCOR #define CORE_PIN6_PORTCLEAR GPIOD_PCOR #define CORE_PIN7_PORTCLEAR GPIOD_PCOR #define CORE_PIN8_PORTCLEAR GPIOD_PCOR #define CORE_PIN9_PORTCLEAR GPIOC_PCOR #define CORE_PIN10_PORTCLEAR GPIOC_PCOR #define CORE_PIN11_PORTCLEAR GPIOC_PCOR #define CORE_PIN12_PORTCLEAR GPIOC_PCOR #define CORE_PIN13_PORTCLEAR GPIOC_PCOR #define CORE_PIN14_PORTCLEAR GPIOD_PCOR #define CORE_PIN15_PORTCLEAR GPIOC_PCOR #define CORE_PIN16_PORTCLEAR GPIOB_PCOR #define CORE_PIN17_PORTCLEAR GPIOB_PCOR #define CORE_PIN18_PORTCLEAR GPIOB_PCOR #define CORE_PIN19_PORTCLEAR GPIOB_PCOR #define CORE_PIN20_PORTCLEAR GPIOD_PCOR #define CORE_PIN21_PORTCLEAR GPIOD_PCOR #define CORE_PIN22_PORTCLEAR GPIOC_PCOR #define CORE_PIN23_PORTCLEAR GPIOC_PCOR #define CORE_PIN24_PORTCLEAR GPIOA_PCOR #define CORE_PIN25_PORTCLEAR GPIOB_PCOR #define CORE_PIN26_PORTCLEAR GPIOE_PCOR #define CORE_PIN27_PORTCLEAR GPIOC_PCOR #define CORE_PIN28_PORTCLEAR GPIOC_PCOR #define CORE_PIN29_PORTCLEAR GPIOC_PCOR #define CORE_PIN30_PORTCLEAR GPIOC_PCOR #define CORE_PIN31_PORTCLEAR GPIOE_PCOR #define CORE_PIN32_PORTCLEAR GPIOB_PCOR #define CORE_PIN33_PORTCLEAR GPIOA_PCOR #define CORE_PIN0_DDRREG GPIOB_PDDR #define CORE_PIN1_DDRREG GPIOB_PDDR #define CORE_PIN2_DDRREG GPIOD_PDDR #define CORE_PIN3_DDRREG GPIOA_PDDR #define CORE_PIN4_DDRREG GPIOA_PDDR #define CORE_PIN5_DDRREG GPIOD_PDDR #define CORE_PIN6_DDRREG GPIOD_PDDR #define CORE_PIN7_DDRREG GPIOD_PDDR #define CORE_PIN8_DDRREG GPIOD_PDDR #define CORE_PIN9_DDRREG GPIOC_PDDR #define CORE_PIN10_DDRREG GPIOC_PDDR #define CORE_PIN11_DDRREG GPIOC_PDDR #define CORE_PIN12_DDRREG GPIOC_PDDR #define CORE_PIN13_DDRREG GPIOC_PDDR #define CORE_PIN14_DDRREG GPIOD_PDDR #define CORE_PIN15_DDRREG GPIOC_PDDR #define CORE_PIN16_DDRREG GPIOB_PDDR #define CORE_PIN17_DDRREG GPIOB_PDDR #define CORE_PIN18_DDRREG GPIOB_PDDR #define CORE_PIN19_DDRREG GPIOB_PDDR #define CORE_PIN20_DDRREG GPIOD_PDDR #define CORE_PIN21_DDRREG GPIOD_PDDR #define CORE_PIN22_DDRREG GPIOC_PDDR #define CORE_PIN23_DDRREG GPIOC_PDDR #define CORE_PIN24_DDRREG GPIOA_PDDR #define CORE_PIN25_DDRREG GPIOB_PDDR #define CORE_PIN26_DDRREG GPIOE_PDDR #define CORE_PIN27_DDRREG GPIOC_PDDR #define CORE_PIN28_DDRREG GPIOC_PDDR #define CORE_PIN29_DDRREG GPIOC_PDDR #define CORE_PIN30_DDRREG GPIOC_PDDR #define CORE_PIN31_DDRREG GPIOE_PDDR #define CORE_PIN32_DDRREG GPIOB_PDDR #define CORE_PIN33_DDRREG GPIOA_PDDR #define CORE_PIN0_PINREG GPIOB_PDIR #define CORE_PIN1_PINREG GPIOB_PDIR #define CORE_PIN2_PINREG GPIOD_PDIR #define CORE_PIN3_PINREG GPIOA_PDIR #define CORE_PIN4_PINREG GPIOA_PDIR #define CORE_PIN5_PINREG GPIOD_PDIR #define CORE_PIN6_PINREG GPIOD_PDIR #define CORE_PIN7_PINREG GPIOD_PDIR #define CORE_PIN8_PINREG GPIOD_PDIR #define CORE_PIN9_PINREG GPIOC_PDIR #define CORE_PIN10_PINREG GPIOC_PDIR #define CORE_PIN11_PINREG GPIOC_PDIR #define CORE_PIN12_PINREG GPIOC_PDIR #define CORE_PIN13_PINREG GPIOC_PDIR #define CORE_PIN14_PINREG GPIOD_PDIR #define CORE_PIN15_PINREG GPIOC_PDIR #define CORE_PIN16_PINREG GPIOB_PDIR #define CORE_PIN17_PINREG GPIOB_PDIR #define CORE_PIN18_PINREG GPIOB_PDIR #define CORE_PIN19_PINREG GPIOB_PDIR #define CORE_PIN20_PINREG GPIOD_PDIR #define CORE_PIN21_PINREG GPIOD_PDIR #define CORE_PIN22_PINREG GPIOC_PDIR #define CORE_PIN23_PINREG GPIOC_PDIR #define CORE_PIN24_PINREG GPIOA_PDIR #define CORE_PIN25_PINREG GPIOB_PDIR #define CORE_PIN26_PINREG GPIOE_PDIR #define CORE_PIN27_PINREG GPIOC_PDIR #define CORE_PIN28_PINREG GPIOC_PDIR #define CORE_PIN29_PINREG GPIOC_PDIR #define CORE_PIN30_PINREG GPIOC_PDIR #define CORE_PIN31_PINREG GPIOE_PDIR #define CORE_PIN32_PINREG GPIOB_PDIR #define CORE_PIN33_PINREG GPIOA_PDIR #define CORE_PIN0_CONFIG PORTB_PCR16 #define CORE_PIN1_CONFIG PORTB_PCR17 #define CORE_PIN2_CONFIG PORTD_PCR0 #define CORE_PIN3_CONFIG PORTA_PCR12 #define CORE_PIN4_CONFIG PORTA_PCR13 #define CORE_PIN5_CONFIG PORTD_PCR7 #define CORE_PIN6_CONFIG PORTD_PCR4 #define CORE_PIN7_CONFIG PORTD_PCR2 #define CORE_PIN8_CONFIG PORTD_PCR3 #define CORE_PIN9_CONFIG PORTC_PCR3 #define CORE_PIN10_CONFIG PORTC_PCR4 #define CORE_PIN11_CONFIG PORTC_PCR6 #define CORE_PIN12_CONFIG PORTC_PCR7 #define CORE_PIN13_CONFIG PORTC_PCR5 #define CORE_PIN14_CONFIG PORTD_PCR1 #define CORE_PIN15_CONFIG PORTC_PCR0 #define CORE_PIN16_CONFIG PORTB_PCR0 #define CORE_PIN17_CONFIG PORTB_PCR1 #define CORE_PIN18_CONFIG PORTB_PCR3 #define CORE_PIN19_CONFIG PORTB_PCR2 #define CORE_PIN20_CONFIG PORTD_PCR5 #define CORE_PIN21_CONFIG PORTD_PCR6 #define CORE_PIN22_CONFIG PORTC_PCR1 #define CORE_PIN23_CONFIG PORTC_PCR2 #define CORE_PIN24_CONFIG PORTA_PCR5 #define CORE_PIN25_CONFIG PORTB_PCR19 #define CORE_PIN26_CONFIG PORTE_PCR1 #define CORE_PIN27_CONFIG PORTC_PCR9 #define CORE_PIN28_CONFIG PORTC_PCR8 #define CORE_PIN29_CONFIG PORTC_PCR10 #define CORE_PIN30_CONFIG PORTC_PCR11 #define CORE_PIN31_CONFIG PORTE_PCR0 #define CORE_PIN32_CONFIG PORTB_PCR18 #define CORE_PIN33_CONFIG PORTA_PCR4 #define CORE_ADC0_PIN 14 #define CORE_ADC1_PIN 15 #define CORE_ADC2_PIN 16 #define CORE_ADC3_PIN 17 #define CORE_ADC4_PIN 18 #define CORE_ADC5_PIN 19 #define CORE_ADC6_PIN 20 #define CORE_ADC7_PIN 21 #define CORE_ADC8_PIN 22 #define CORE_ADC9_PIN 23 #define CORE_ADC10_PIN 34 #define CORE_ADC11_PIN 35 #define CORE_ADC12_PIN 36 #define CORE_ADC13_PIN 37 #define CORE_RXD0_PIN 0 #define CORE_TXD0_PIN 1 #define CORE_RXD1_PIN 9 #define CORE_TXD1_PIN 10 #define CORE_RXD2_PIN 7 #define CORE_TXD2_PIN 8 #define CORE_INT0_PIN 0 #define CORE_INT1_PIN 1 #define CORE_INT2_PIN 2 #define CORE_INT3_PIN 3 #define CORE_INT4_PIN 4 #define CORE_INT5_PIN 5 #define CORE_INT6_PIN 6 #define CORE_INT7_PIN 7 #define CORE_INT8_PIN 8 #define CORE_INT9_PIN 9 #define CORE_INT10_PIN 10 #define CORE_INT11_PIN 11 #define CORE_INT12_PIN 12 #define CORE_INT13_PIN 13 #define CORE_INT14_PIN 14 #define CORE_INT15_PIN 15 #define CORE_INT16_PIN 16 #define CORE_INT17_PIN 17 #define CORE_INT18_PIN 18 #define CORE_INT19_PIN 19 #define CORE_INT20_PIN 20 #define CORE_INT21_PIN 21 #define CORE_INT22_PIN 22 #define CORE_INT23_PIN 23 #define CORE_INT24_PIN 24 #define CORE_INT25_PIN 25 #define CORE_INT26_PIN 26 #define CORE_INT27_PIN 27 #define CORE_INT28_PIN 28 #define CORE_INT29_PIN 29 #define CORE_INT30_PIN 30 #define CORE_INT31_PIN 31 #define CORE_INT32_PIN 32 #define CORE_INT33_PIN 33 #define CORE_INT_EVERY_PIN 1 #ifdef __cplusplus extern "C" { #endif void digitalWrite(uint8_t pin, uint8_t val); static inline void digitalWriteFast(uint8_t pin, uint8_t val) __attribute__((always_inline, unused)); static inline void digitalWriteFast(uint8_t pin, uint8_t val) { if (__builtin_constant_p(pin)) { if (val) { if (pin == 0) { CORE_PIN0_PORTSET = CORE_PIN0_BITMASK; } else if (pin == 1) { CORE_PIN1_PORTSET = CORE_PIN1_BITMASK; } else if (pin == 2) { CORE_PIN2_PORTSET = CORE_PIN2_BITMASK; } else if (pin == 3) { CORE_PIN3_PORTSET = CORE_PIN3_BITMASK; } else if (pin == 4) { CORE_PIN4_PORTSET = CORE_PIN4_BITMASK; } else if (pin == 5) { CORE_PIN5_PORTSET = CORE_PIN5_BITMASK; } else if (pin == 6) { CORE_PIN6_PORTSET = CORE_PIN6_BITMASK; } else if (pin == 7) { CORE_PIN7_PORTSET = CORE_PIN7_BITMASK; } else if (pin == 8) { CORE_PIN8_PORTSET = CORE_PIN8_BITMASK; } else if (pin == 9) { CORE_PIN9_PORTSET = CORE_PIN9_BITMASK; } else if (pin == 10) { CORE_PIN10_PORTSET = CORE_PIN10_BITMASK; } else if (pin == 11) { CORE_PIN11_PORTSET = CORE_PIN11_BITMASK; } else if (pin == 12) { CORE_PIN12_PORTSET = CORE_PIN12_BITMASK; } else if (pin == 13) { CORE_PIN13_PORTSET = CORE_PIN13_BITMASK; } else if (pin == 14) { CORE_PIN14_PORTSET = CORE_PIN14_BITMASK; } else if (pin == 15) { CORE_PIN15_PORTSET = CORE_PIN15_BITMASK; } else if (pin == 16) { CORE_PIN16_PORTSET = CORE_PIN16_BITMASK; } else if (pin == 17) { CORE_PIN17_PORTSET = CORE_PIN17_BITMASK; } else if (pin == 18) { CORE_PIN18_PORTSET = CORE_PIN18_BITMASK; } else if (pin == 19) { CORE_PIN19_PORTSET = CORE_PIN19_BITMASK; } else if (pin == 20) { CORE_PIN20_PORTSET = CORE_PIN20_BITMASK; } else if (pin == 21) { CORE_PIN21_PORTSET = CORE_PIN21_BITMASK; } else if (pin == 22) { CORE_PIN22_PORTSET = CORE_PIN22_BITMASK; } else if (pin == 23) { CORE_PIN23_PORTSET = CORE_PIN23_BITMASK; } else if (pin == 24) { CORE_PIN24_PORTSET = CORE_PIN24_BITMASK; } else if (pin == 25) { CORE_PIN25_PORTSET = CORE_PIN25_BITMASK; } else if (pin == 26) { CORE_PIN26_PORTSET = CORE_PIN26_BITMASK; } else if (pin == 27) { CORE_PIN27_PORTSET = CORE_PIN27_BITMASK; } else if (pin == 28) { CORE_PIN28_PORTSET = CORE_PIN28_BITMASK; } else if (pin == 29) { CORE_PIN29_PORTSET = CORE_PIN29_BITMASK; } else if (pin == 30) { CORE_PIN30_PORTSET = CORE_PIN30_BITMASK; } else if (pin == 31) { CORE_PIN31_PORTSET = CORE_PIN31_BITMASK; } else if (pin == 32) { CORE_PIN32_PORTSET = CORE_PIN32_BITMASK; } else if (pin == 33) { CORE_PIN33_PORTSET = CORE_PIN33_BITMASK; } } else { if (pin == 0) { CORE_PIN0_PORTCLEAR = CORE_PIN0_BITMASK; } else if (pin == 1) { CORE_PIN1_PORTCLEAR = CORE_PIN1_BITMASK; } else if (pin == 2) { CORE_PIN2_PORTCLEAR = CORE_PIN2_BITMASK; } else if (pin == 3) { CORE_PIN3_PORTCLEAR = CORE_PIN3_BITMASK; } else if (pin == 4) { CORE_PIN4_PORTCLEAR = CORE_PIN4_BITMASK; } else if (pin == 5) { CORE_PIN5_PORTCLEAR = CORE_PIN5_BITMASK; } else if (pin == 6) { CORE_PIN6_PORTCLEAR = CORE_PIN6_BITMASK; } else if (pin == 7) { CORE_PIN7_PORTCLEAR = CORE_PIN7_BITMASK; } else if (pin == 8) { CORE_PIN8_PORTCLEAR = CORE_PIN8_BITMASK; } else if (pin == 9) { CORE_PIN9_PORTCLEAR = CORE_PIN9_BITMASK; } else if (pin == 10) { CORE_PIN10_PORTCLEAR = CORE_PIN10_BITMASK; } else if (pin == 11) { CORE_PIN11_PORTCLEAR = CORE_PIN11_BITMASK; } else if (pin == 12) { CORE_PIN12_PORTCLEAR = CORE_PIN12_BITMASK; } else if (pin == 13) { CORE_PIN13_PORTCLEAR = CORE_PIN13_BITMASK; } else if (pin == 14) { CORE_PIN14_PORTCLEAR = CORE_PIN14_BITMASK; } else if (pin == 15) { CORE_PIN15_PORTCLEAR = CORE_PIN15_BITMASK; } else if (pin == 16) { CORE_PIN16_PORTCLEAR = CORE_PIN16_BITMASK; } else if (pin == 17) { CORE_PIN17_PORTCLEAR = CORE_PIN17_BITMASK; } else if (pin == 18) { CORE_PIN18_PORTCLEAR = CORE_PIN18_BITMASK; } else if (pin == 19) { CORE_PIN19_PORTCLEAR = CORE_PIN19_BITMASK; } else if (pin == 20) { CORE_PIN20_PORTCLEAR = CORE_PIN20_BITMASK; } else if (pin == 21) { CORE_PIN21_PORTCLEAR = CORE_PIN21_BITMASK; } else if (pin == 22) { CORE_PIN22_PORTCLEAR = CORE_PIN22_BITMASK; } else if (pin == 23) { CORE_PIN23_PORTCLEAR = CORE_PIN23_BITMASK; } else if (pin == 24) { CORE_PIN24_PORTCLEAR = CORE_PIN24_BITMASK; } else if (pin == 25) { CORE_PIN25_PORTCLEAR = CORE_PIN25_BITMASK; } else if (pin == 26) { CORE_PIN26_PORTCLEAR = CORE_PIN26_BITMASK; } else if (pin == 27) { CORE_PIN27_PORTCLEAR = CORE_PIN27_BITMASK; } else if (pin == 28) { CORE_PIN28_PORTCLEAR = CORE_PIN28_BITMASK; } else if (pin == 29) { CORE_PIN29_PORTCLEAR = CORE_PIN29_BITMASK; } else if (pin == 30) { CORE_PIN30_PORTCLEAR = CORE_PIN30_BITMASK; } else if (pin == 31) { CORE_PIN31_PORTCLEAR = CORE_PIN31_BITMASK; } else if (pin == 32) { CORE_PIN32_PORTCLEAR = CORE_PIN32_BITMASK; } else if (pin == 33) { CORE_PIN33_PORTCLEAR = CORE_PIN33_BITMASK; } } } else { if (val) { *portSetRegister(pin) = 1; } else { *portClearRegister(pin) = 1; } } } uint8_t digitalRead(uint8_t pin); static inline uint8_t digitalReadFast(uint8_t pin) __attribute__((always_inline, unused)); static inline uint8_t digitalReadFast(uint8_t pin) { if (__builtin_constant_p(pin)) { if (pin == 0) { return (CORE_PIN0_PINREG & CORE_PIN0_BITMASK) ? 1 : 0; } else if (pin == 1) { return (CORE_PIN1_PINREG & CORE_PIN1_BITMASK) ? 1 : 0; } else if (pin == 2) { return (CORE_PIN2_PINREG & CORE_PIN2_BITMASK) ? 1 : 0; } else if (pin == 3) { return (CORE_PIN3_PINREG & CORE_PIN3_BITMASK) ? 1 : 0; } else if (pin == 4) { return (CORE_PIN4_PINREG & CORE_PIN4_BITMASK) ? 1 : 0; } else if (pin == 5) { return (CORE_PIN5_PINREG & CORE_PIN5_BITMASK) ? 1 : 0; } else if (pin == 6) { return (CORE_PIN6_PINREG & CORE_PIN6_BITMASK) ? 1 : 0; } else if (pin == 7) { return (CORE_PIN7_PINREG & CORE_PIN7_BITMASK) ? 1 : 0; } else if (pin == 8) { return (CORE_PIN8_PINREG & CORE_PIN8_BITMASK) ? 1 : 0; } else if (pin == 9) { return (CORE_PIN9_PINREG & CORE_PIN9_BITMASK) ? 1 : 0; } else if (pin == 10) { return (CORE_PIN10_PINREG & CORE_PIN10_BITMASK) ? 1 : 0; } else if (pin == 11) { return (CORE_PIN11_PINREG & CORE_PIN11_BITMASK) ? 1 : 0; } else if (pin == 12) { return (CORE_PIN12_PINREG & CORE_PIN12_BITMASK) ? 1 : 0; } else if (pin == 13) { return (CORE_PIN13_PINREG & CORE_PIN13_BITMASK) ? 1 : 0; } else if (pin == 14) { return (CORE_PIN14_PINREG & CORE_PIN14_BITMASK) ? 1 : 0; } else if (pin == 15) { return (CORE_PIN15_PINREG & CORE_PIN15_BITMASK) ? 1 : 0; } else if (pin == 16) { return (CORE_PIN16_PINREG & CORE_PIN16_BITMASK) ? 1 : 0; } else if (pin == 17) { return (CORE_PIN17_PINREG & CORE_PIN17_BITMASK) ? 1 : 0; } else if (pin == 18) { return (CORE_PIN18_PINREG & CORE_PIN18_BITMASK) ? 1 : 0; } else if (pin == 19) { return (CORE_PIN19_PINREG & CORE_PIN19_BITMASK) ? 1 : 0; } else if (pin == 20) { return (CORE_PIN20_PINREG & CORE_PIN20_BITMASK) ? 1 : 0; } else if (pin == 21) { return (CORE_PIN21_PINREG & CORE_PIN21_BITMASK) ? 1 : 0; } else if (pin == 22) { return (CORE_PIN22_PINREG & CORE_PIN22_BITMASK) ? 1 : 0; } else if (pin == 23) { return (CORE_PIN23_PINREG & CORE_PIN23_BITMASK) ? 1 : 0; } else if (pin == 24) { return (CORE_PIN24_PINREG & CORE_PIN24_BITMASK) ? 1 : 0; } else if (pin == 25) { return (CORE_PIN25_PINREG & CORE_PIN25_BITMASK) ? 1 : 0; } else if (pin == 26) { return (CORE_PIN26_PINREG & CORE_PIN26_BITMASK) ? 1 : 0; } else if (pin == 27) { return (CORE_PIN27_PINREG & CORE_PIN27_BITMASK) ? 1 : 0; } else if (pin == 28) { return (CORE_PIN28_PINREG & CORE_PIN28_BITMASK) ? 1 : 0; } else if (pin == 29) { return (CORE_PIN29_PINREG & CORE_PIN29_BITMASK) ? 1 : 0; } else if (pin == 30) { return (CORE_PIN30_PINREG & CORE_PIN30_BITMASK) ? 1 : 0; } else if (pin == 31) { return (CORE_PIN31_PINREG & CORE_PIN31_BITMASK) ? 1 : 0; } else if (pin == 32) { return (CORE_PIN32_PINREG & CORE_PIN32_BITMASK) ? 1 : 0; } else if (pin == 33) { return (CORE_PIN33_PINREG & CORE_PIN33_BITMASK) ? 1 : 0; } else { return 0; } } else { return *portInputRegister(pin); } } void pinMode(uint8_t pin, uint8_t mode); void init_pins(void); void analogWrite(uint8_t pin, int val); void analogWriteRes(uint32_t bits); static inline void analogWriteResolution(uint32_t bits) { analogWriteRes(bits); } void analogWriteFrequency(uint8_t pin, uint32_t frequency); void analogWriteDAC0(int val); void attachInterrupt(uint8_t pin, void (*function)(void), int mode); void detachInterrupt(uint8_t pin); void _init_Teensyduino_internal_(void); int analogRead(uint8_t pin); void analogReference(uint8_t type); void analogReadRes(unsigned int bits); static inline void analogReadResolution(unsigned int bits) { analogReadRes(bits); } void analogReadAveraging(unsigned int num); void analog_init(void); #define DEFAULT 0 #define INTERNAL 2 #define INTERNAL1V2 2 #define INTERNAL1V1 2 #define EXTERNAL 0 int touchRead(uint8_t pin); static inline void shiftOut(uint8_t, uint8_t, uint8_t, uint8_t) __attribute__((always_inline, unused)); extern void _shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value) __attribute__((noinline)); extern void shiftOut_lsbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value) __attribute__((noinline)); extern void shiftOut_msbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value) __attribute__((noinline)); static inline void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value) { if (__builtin_constant_p(bitOrder)) { if (bitOrder == LSBFIRST) { shiftOut_lsbFirst(dataPin, clockPin, value); } else { shiftOut_msbFirst(dataPin, clockPin, value); } } else { _shiftOut(dataPin, clockPin, bitOrder, value); } } static inline uint8_t shiftIn(uint8_t, uint8_t, uint8_t) __attribute__((always_inline, unused)); extern uint8_t _shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) __attribute__((noinline)); extern uint8_t shiftIn_lsbFirst(uint8_t dataPin, uint8_t clockPin) __attribute__((noinline)); extern uint8_t shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin) __attribute__((noinline)); static inline uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { if (__builtin_constant_p(bitOrder)) { if (bitOrder == LSBFIRST) { return shiftIn_lsbFirst(dataPin, clockPin); } else { return shiftIn_msbFirst(dataPin, clockPin); } } else { return _shiftIn(dataPin, clockPin, bitOrder); } } void _reboot_Teensyduino_(void) __attribute__((noreturn)); void _restart_Teensyduino_(void) __attribute__((noreturn)); void yield(void); void delay(uint32_t msec); extern volatile uint32_t systick_millis_count; static inline uint32_t millis(void) __attribute__((always_inline, unused)); static inline uint32_t millis(void) { volatile uint32_t ret = systick_millis_count; // single aligned 32 bit is atomic; return ret; } uint32_t micros(void); static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused)); static inline void delayMicroseconds(uint32_t usec) { #if F_CPU == 168000000 uint32_t n = usec * 56; #elif F_CPU == 144000000 uint32_t n = usec * 48; #elif F_CPU == 120000000 uint32_t n = usec * 40; #elif F_CPU == 96000000 uint32_t n = usec << 5; #elif F_CPU == 72000000 uint32_t n = usec * 24; #elif F_CPU == 48000000 uint32_t n = usec << 4; #elif F_CPU == 24000000 uint32_t n = usec << 3; #elif F_CPU == 16000000 uint32_t n = usec << 2; #elif F_CPU == 8000000 uint32_t n = usec << 1; #elif F_CPU == 4000000 uint32_t n = usec; #elif F_CPU == 2000000 uint32_t n = usec >> 1; #endif // changed because a delay of 1 micro Sec @ 2MHz will be 0 if (n == 0) return; __asm__ volatile( "L_%=_delayMicroseconds:" "\n\t" #if F_CPU < 24000000 "nop" "\n\t" #endif "subs %0, #1" "\n\t" "bne L_%=_delayMicroseconds" "\n" : "+r" (n) : ); } #ifdef __cplusplus } #endif #ifdef __cplusplus extern "C" { #endif unsigned long rtc_get(void); void rtc_set(unsigned long t); void rtc_compensate(int adjust); #ifdef __cplusplus } class teensy3_clock_class { public: static unsigned long get(void) __attribute__((always_inline)) { return rtc_get(); } static void set(unsigned long t) __attribute__((always_inline)) { rtc_set(t); } static void compensate(int adj) __attribute__((always_inline)) { rtc_compensate(adj); } }; extern teensy3_clock_class Teensy3Clock; #endif #endif micropython-1.12/ports/teensy/core/mk20dx128.c000066400000000000000000000625351357706137100211470ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "mk20dx128.h" extern unsigned long _stext; extern unsigned long _etext; extern unsigned long _sdata; extern unsigned long _edata; extern unsigned long _sbss; extern unsigned long _ebss; extern unsigned long _estack; //extern void __init_array_start(void); //extern void __init_array_end(void); extern int main (void); void ResetHandler(void); void _init_Teensyduino_internal_(void); void __libc_init_array(void); void fault_isr(void) { while (1) { // keep polling some communication while in fault // mode, so we don't completely die. if (SIM_SCGC4 & SIM_SCGC4_USBOTG) usb_isr(); if (SIM_SCGC4 & SIM_SCGC4_UART0) uart0_status_isr(); if (SIM_SCGC4 & SIM_SCGC4_UART1) uart1_status_isr(); if (SIM_SCGC4 & SIM_SCGC4_UART2) uart2_status_isr(); } } void unused_isr(void) { fault_isr(); } extern volatile uint32_t systick_millis_count; void systick_default_isr(void) { systick_millis_count++; } void nmi_isr(void) __attribute__ ((weak, alias("unused_isr"))); void hard_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); void memmanage_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); void bus_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); void usage_fault_isr(void) __attribute__ ((weak, alias("unused_isr"))); void svcall_isr(void) __attribute__ ((weak, alias("unused_isr"))); void debugmonitor_isr(void) __attribute__ ((weak, alias("unused_isr"))); void pendablesrvreq_isr(void) __attribute__ ((weak, alias("unused_isr"))); void systick_isr(void) __attribute__ ((weak, alias("systick_default_isr"))); void dma_ch0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch1_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch2_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch3_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch4_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch5_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch6_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch7_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch8_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch9_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch10_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch11_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch12_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch13_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch14_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_ch15_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dma_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void mcm_isr(void) __attribute__ ((weak, alias("unused_isr"))); void flash_cmd_isr(void) __attribute__ ((weak, alias("unused_isr"))); void flash_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void low_voltage_isr(void) __attribute__ ((weak, alias("unused_isr"))); void wakeup_isr(void) __attribute__ ((weak, alias("unused_isr"))); void watchdog_isr(void) __attribute__ ((weak, alias("unused_isr"))); void i2c0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void i2c1_isr(void) __attribute__ ((weak, alias("unused_isr"))); void i2c2_isr(void) __attribute__ ((weak, alias("unused_isr"))); void spi0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void spi1_isr(void) __attribute__ ((weak, alias("unused_isr"))); void spi2_isr(void) __attribute__ ((weak, alias("unused_isr"))); void sdhc_isr(void) __attribute__ ((weak, alias("unused_isr"))); void can0_message_isr(void) __attribute__ ((weak, alias("unused_isr"))); void can0_bus_off_isr(void) __attribute__ ((weak, alias("unused_isr"))); void can0_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void can0_tx_warn_isr(void) __attribute__ ((weak, alias("unused_isr"))); void can0_rx_warn_isr(void) __attribute__ ((weak, alias("unused_isr"))); void can0_wakeup_isr(void) __attribute__ ((weak, alias("unused_isr"))); void i2s0_tx_isr(void) __attribute__ ((weak, alias("unused_isr"))); void i2s0_rx_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart0_lon_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart0_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart0_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart1_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart1_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart2_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart2_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart3_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart3_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart4_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart4_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart5_status_isr(void) __attribute__ ((weak, alias("unused_isr"))); void uart5_error_isr(void) __attribute__ ((weak, alias("unused_isr"))); void adc0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void adc1_isr(void) __attribute__ ((weak, alias("unused_isr"))); void cmp0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void cmp1_isr(void) __attribute__ ((weak, alias("unused_isr"))); void cmp2_isr(void) __attribute__ ((weak, alias("unused_isr"))); void ftm0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void ftm1_isr(void) __attribute__ ((weak, alias("unused_isr"))); void ftm2_isr(void) __attribute__ ((weak, alias("unused_isr"))); void ftm3_isr(void) __attribute__ ((weak, alias("unused_isr"))); void cmt_isr(void) __attribute__ ((weak, alias("unused_isr"))); void rtc_alarm_isr(void) __attribute__ ((weak, alias("unused_isr"))); void rtc_seconds_isr(void) __attribute__ ((weak, alias("unused_isr"))); void pit0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void pit1_isr(void) __attribute__ ((weak, alias("unused_isr"))); void pit2_isr(void) __attribute__ ((weak, alias("unused_isr"))); void pit3_isr(void) __attribute__ ((weak, alias("unused_isr"))); void pdb_isr(void) __attribute__ ((weak, alias("unused_isr"))); void usb_isr(void) __attribute__ ((weak, alias("unused_isr"))); void usb_charge_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dac0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void dac1_isr(void) __attribute__ ((weak, alias("unused_isr"))); void tsi0_isr(void) __attribute__ ((weak, alias("unused_isr"))); void mcg_isr(void) __attribute__ ((weak, alias("unused_isr"))); void lptmr_isr(void) __attribute__ ((weak, alias("unused_isr"))); void porta_isr(void) __attribute__ ((weak, alias("unused_isr"))); void portb_isr(void) __attribute__ ((weak, alias("unused_isr"))); void portc_isr(void) __attribute__ ((weak, alias("unused_isr"))); void portd_isr(void) __attribute__ ((weak, alias("unused_isr"))); void porte_isr(void) __attribute__ ((weak, alias("unused_isr"))); void software_isr(void) __attribute__ ((weak, alias("unused_isr"))); // TODO: create AVR-stype ISR() macro, with default linkage to undefined handler // __attribute__ ((section(".vectors"), used)) void (* const gVectors[])(void) = { (void (*)(void))((unsigned long)&_estack), // 0 ARM: Initial Stack Pointer ResetHandler, // 1 ARM: Initial Program Counter nmi_isr, // 2 ARM: Non-maskable Interrupt (NMI) hard_fault_isr, // 3 ARM: Hard Fault memmanage_fault_isr, // 4 ARM: MemManage Fault bus_fault_isr, // 5 ARM: Bus Fault usage_fault_isr, // 6 ARM: Usage Fault fault_isr, // 7 -- fault_isr, // 8 -- fault_isr, // 9 -- fault_isr, // 10 -- svcall_isr, // 11 ARM: Supervisor call (SVCall) debugmonitor_isr, // 12 ARM: Debug Monitor fault_isr, // 13 -- pendablesrvreq_isr, // 14 ARM: Pendable req serv(PendableSrvReq) systick_isr, // 15 ARM: System tick timer (SysTick) #if defined(__MK20DX128__) dma_ch0_isr, // 16 DMA channel 0 transfer complete dma_ch1_isr, // 17 DMA channel 1 transfer complete dma_ch2_isr, // 18 DMA channel 2 transfer complete dma_ch3_isr, // 19 DMA channel 3 transfer complete dma_error_isr, // 20 DMA error interrupt channel unused_isr, // 21 DMA -- flash_cmd_isr, // 22 Flash Memory Command complete flash_error_isr, // 23 Flash Read collision low_voltage_isr, // 24 Low-voltage detect/warning wakeup_isr, // 25 Low Leakage Wakeup watchdog_isr, // 26 Both EWM and WDOG interrupt i2c0_isr, // 27 I2C0 spi0_isr, // 28 SPI0 i2s0_tx_isr, // 29 I2S0 Transmit i2s0_rx_isr, // 30 I2S0 Receive uart0_lon_isr, // 31 UART0 CEA709.1-B (LON) status uart0_status_isr, // 32 UART0 status uart0_error_isr, // 33 UART0 error uart1_status_isr, // 34 UART1 status uart1_error_isr, // 35 UART1 error uart2_status_isr, // 36 UART2 status uart2_error_isr, // 37 UART2 error adc0_isr, // 38 ADC0 cmp0_isr, // 39 CMP0 cmp1_isr, // 40 CMP1 ftm0_isr, // 41 FTM0 ftm1_isr, // 42 FTM1 cmt_isr, // 43 CMT rtc_alarm_isr, // 44 RTC Alarm interrupt rtc_seconds_isr, // 45 RTC Seconds interrupt pit0_isr, // 46 PIT Channel 0 pit1_isr, // 47 PIT Channel 1 pit2_isr, // 48 PIT Channel 2 pit3_isr, // 49 PIT Channel 3 pdb_isr, // 50 PDB Programmable Delay Block usb_isr, // 51 USB OTG usb_charge_isr, // 52 USB Charger Detect tsi0_isr, // 53 TSI0 mcg_isr, // 54 MCG lptmr_isr, // 55 Low Power Timer porta_isr, // 56 Pin detect (Port A) portb_isr, // 57 Pin detect (Port B) portc_isr, // 58 Pin detect (Port C) portd_isr, // 59 Pin detect (Port D) porte_isr, // 60 Pin detect (Port E) software_isr, // 61 Software interrupt #elif defined(__MK20DX256__) dma_ch0_isr, // 16 DMA channel 0 transfer complete dma_ch1_isr, // 17 DMA channel 1 transfer complete dma_ch2_isr, // 18 DMA channel 2 transfer complete dma_ch3_isr, // 19 DMA channel 3 transfer complete dma_ch4_isr, // 20 DMA channel 4 transfer complete dma_ch5_isr, // 21 DMA channel 5 transfer complete dma_ch6_isr, // 22 DMA channel 6 transfer complete dma_ch7_isr, // 23 DMA channel 7 transfer complete dma_ch8_isr, // 24 DMA channel 8 transfer complete dma_ch9_isr, // 25 DMA channel 9 transfer complete dma_ch10_isr, // 26 DMA channel 10 transfer complete dma_ch11_isr, // 27 DMA channel 10 transfer complete dma_ch12_isr, // 28 DMA channel 10 transfer complete dma_ch13_isr, // 29 DMA channel 10 transfer complete dma_ch14_isr, // 30 DMA channel 10 transfer complete dma_ch15_isr, // 31 DMA channel 10 transfer complete dma_error_isr, // 32 DMA error interrupt channel unused_isr, // 33 -- flash_cmd_isr, // 34 Flash Memory Command complete flash_error_isr, // 35 Flash Read collision low_voltage_isr, // 36 Low-voltage detect/warning wakeup_isr, // 37 Low Leakage Wakeup watchdog_isr, // 38 Both EWM and WDOG interrupt unused_isr, // 39 -- i2c0_isr, // 40 I2C0 i2c1_isr, // 41 I2C1 spi0_isr, // 42 SPI0 spi1_isr, // 43 SPI1 unused_isr, // 44 -- can0_message_isr, // 45 CAN OR'ed Message buffer (0-15) can0_bus_off_isr, // 46 CAN Bus Off can0_error_isr, // 47 CAN Error can0_tx_warn_isr, // 48 CAN Transmit Warning can0_rx_warn_isr, // 49 CAN Receive Warning can0_wakeup_isr, // 50 CAN Wake Up i2s0_tx_isr, // 51 I2S0 Transmit i2s0_rx_isr, // 52 I2S0 Receive unused_isr, // 53 -- unused_isr, // 54 -- unused_isr, // 55 -- unused_isr, // 56 -- unused_isr, // 57 -- unused_isr, // 58 -- unused_isr, // 59 -- uart0_lon_isr, // 60 UART0 CEA709.1-B (LON) status uart0_status_isr, // 61 UART0 status uart0_error_isr, // 62 UART0 error uart1_status_isr, // 63 UART1 status uart1_error_isr, // 64 UART1 error uart2_status_isr, // 65 UART2 status uart2_error_isr, // 66 UART2 error unused_isr, // 67 -- unused_isr, // 68 -- unused_isr, // 69 -- unused_isr, // 70 -- unused_isr, // 71 -- unused_isr, // 72 -- adc0_isr, // 73 ADC0 adc1_isr, // 74 ADC1 cmp0_isr, // 75 CMP0 cmp1_isr, // 76 CMP1 cmp2_isr, // 77 CMP2 ftm0_isr, // 78 FTM0 ftm1_isr, // 79 FTM1 ftm2_isr, // 80 FTM2 cmt_isr, // 81 CMT rtc_alarm_isr, // 82 RTC Alarm interrupt rtc_seconds_isr, // 83 RTC Seconds interrupt pit0_isr, // 84 PIT Channel 0 pit1_isr, // 85 PIT Channel 1 pit2_isr, // 86 PIT Channel 2 pit3_isr, // 87 PIT Channel 3 pdb_isr, // 88 PDB Programmable Delay Block usb_isr, // 89 USB OTG usb_charge_isr, // 90 USB Charger Detect unused_isr, // 91 -- unused_isr, // 92 -- unused_isr, // 93 -- unused_isr, // 94 -- unused_isr, // 95 -- unused_isr, // 96 -- dac0_isr, // 97 DAC0 unused_isr, // 98 -- tsi0_isr, // 99 TSI0 mcg_isr, // 100 MCG lptmr_isr, // 101 Low Power Timer unused_isr, // 102 -- porta_isr, // 103 Pin detect (Port A) portb_isr, // 104 Pin detect (Port B) portc_isr, // 105 Pin detect (Port C) portd_isr, // 106 Pin detect (Port D) porte_isr, // 107 Pin detect (Port E) unused_isr, // 108 -- unused_isr, // 109 -- software_isr, // 110 Software interrupt #endif }; //void usb_isr(void) //{ //} __attribute__ ((section(".flashconfig"), used)) const uint8_t flashconfigbytes[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF }; // Automatically initialize the RTC. When the build defines the compile // time, and the user has added a crystal, the RTC will automatically // begin at the time of the first upload. #ifndef TIME_T #define TIME_T 1349049600 // default 1 Oct 2012 (never used, Arduino sets this) #endif extern void rtc_set(unsigned long t); static void startup_default_early_hook(void) { WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE; } static void startup_default_late_hook(void) {} void startup_early_hook(void) __attribute__ ((weak, alias("startup_default_early_hook"))); void startup_late_hook(void) __attribute__ ((weak, alias("startup_default_late_hook"))); __attribute__ ((section(".startup"))) void ResetHandler(void) { uint32_t *src = &_etext; uint32_t *dest = &_sdata; unsigned int i; #if F_CPU <= 2000000 volatile int n; #endif WDOG_UNLOCK = WDOG_UNLOCK_SEQ1; WDOG_UNLOCK = WDOG_UNLOCK_SEQ2; __asm__ volatile ("nop"); __asm__ volatile ("nop"); // programs using the watchdog timer or needing to initialize hardware as // early as possible can implement startup_early_hook() startup_early_hook(); // enable clocks to always-used peripherals #if defined(__MK20DX128__) SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; #elif defined(__MK20DX256__) SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2; SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; #endif // if the RTC oscillator isn't enabled, get it started early if (!(RTC_CR & RTC_CR_OSCE)) { RTC_SR = 0; RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE; } // release I/O pins hold, if we woke up from VLLS mode if (PMC_REGSC & PMC_REGSC_ACKISO) PMC_REGSC |= PMC_REGSC_ACKISO; // since this is a write once register, make it visible to all F_CPU's // so we can into other sleep modes in the future at any speed SMC_PMPROT = SMC_PMPROT_AVLP | SMC_PMPROT_ALLS | SMC_PMPROT_AVLLS; // TODO: do this while the PLL is waiting to lock.... while (dest < &_edata) *dest++ = *src++; dest = &_sbss; while (dest < &_ebss) *dest++ = 0; SCB_VTOR = 0; // use vector table in flash // default all interrupts to medium priority level for (i=0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_PRIORITY(i, 128); // hardware always starts in FEI mode // C1[CLKS] bits are written to 00 // C1[IREFS] bit is written to 1 // C6[PLLS] bit is written to 0 // MCG_SC[FCDIV] defaults to divide by two for internal ref clock // I tried changing MSG_SC to divide by 1, it didn't work for me #if F_CPU <= 2000000 // use the internal oscillator MCG_C1 = MCG_C1_CLKS(1) | MCG_C1_IREFS; // wait for MCGOUT to use oscillator while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(1)) ; for (n=0; n<10; n++) ; // TODO: why do we get 2 mA extra without this delay? MCG_C2 = MCG_C2_IRCS; while (!(MCG_S & MCG_S_IRCST)) ; // now in FBI mode: // C1[CLKS] bits are written to 01 // C1[IREFS] bit is written to 1 // C6[PLLS] is written to 0 // C2[LP] is written to 0 MCG_C2 = MCG_C2_IRCS | MCG_C2_LP; // now in BLPI mode: // C1[CLKS] bits are written to 01 // C1[IREFS] bit is written to 1 // C6[PLLS] bit is written to 0 // C2[LP] bit is written to 1 #else // enable capacitors for crystal OSC0_CR = OSC_SC8P | OSC_SC2P; // enable osc, 8-32 MHz range, low power mode MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS; // switch to crystal as clock source, FLL input = 16 MHz / 512 MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(4); // wait for crystal oscillator to begin while ((MCG_S & MCG_S_OSCINIT0) == 0) ; // wait for FLL to use oscillator while ((MCG_S & MCG_S_IREFST) != 0) ; // wait for MCGOUT to use oscillator while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) ; // now in FBE mode // C1[CLKS] bits are written to 10 // C1[IREFS] bit is written to 0 // C1[FRDIV] must be written to divide xtal to 31.25-39 kHz // C6[PLLS] bit is written to 0 // C2[LP] is written to 0 #if F_CPU <= 16000000 // if the crystal is fast enough, use it directly (no FLL or PLL) MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS | MCG_C2_LP; // BLPE mode: // C1[CLKS] bits are written to 10 // C1[IREFS] bit is written to 0 // C2[LP] bit is written to 1 #else // if we need faster than the crystal, turn on the PLL #if F_CPU == 72000000 MCG_C5 = MCG_C5_PRDIV0(5); // config PLL input for 16 MHz Crystal / 6 = 2.667 Hz #else MCG_C5 = MCG_C5_PRDIV0(3); // config PLL input for 16 MHz Crystal / 4 = 4 MHz #endif #if F_CPU == 168000000 MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(18); // config PLL for 168 MHz output #elif F_CPU == 144000000 MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(12); // config PLL for 144 MHz output #elif F_CPU == 120000000 MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(6); // config PLL for 120 MHz output #elif F_CPU == 72000000 MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(3); // config PLL for 72 MHz output #else MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0); // config PLL for 96 MHz output #endif // wait for PLL to start using xtal as its input while (!(MCG_S & MCG_S_PLLST)) ; // wait for PLL to lock while (!(MCG_S & MCG_S_LOCK0)) ; // now we're in PBE mode #endif #endif // now program the clock dividers #if F_CPU == 168000000 // config divisors: 168 MHz core, 56 MHz bus, 33.6 MHz flash, USB = 168 * 2 / 7 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(4); SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(6) | SIM_CLKDIV2_USBFRAC; #elif F_CPU == 144000000 // config divisors: 144 MHz core, 48 MHz bus, 28.8 MHz flash, USB = 144 / 3 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(4); SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2); #elif F_CPU == 120000000 // config divisors: 120 MHz core, 60 MHz bus, 24 MHz flash, USB = 128 * 2 / 5 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(4); SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(4) | SIM_CLKDIV2_USBFRAC; #elif F_CPU == 96000000 // config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3); SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); #elif F_CPU == 72000000 // config divisors: 72 MHz core, 36 MHz bus, 24 MHz flash, USB = 72 * 2 / 3 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(2); SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC; #elif F_CPU == 48000000 // config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3); SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); #elif F_CPU == 24000000 // config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash, USB = 96 / 2 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3); SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); #elif F_CPU == 16000000 // config divisors: 16 MHz core, 16 MHz bus, 16 MHz flash SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(0); #elif F_CPU == 8000000 // config divisors: 8 MHz core, 8 MHz bus, 8 MHz flash SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(1); #elif F_CPU == 4000000 // config divisors: 4 MHz core, 4 MHz bus, 2 MHz flash // since we are running from external clock 16MHz // fix outdiv too -> cpu 16/4, bus 16/4, flash 16/4 // here we can go into vlpr? // config divisors: 4 MHz core, 4 MHz bus, 4 MHz flash SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3); #elif F_CPU == 2000000 // since we are running from the fast internal reference clock 4MHz // but is divided down by 2 so we actually have a 2MHz, MCG_SC[FCDIV] default is 2 // fix outdiv -> cpu 2/1, bus 2/1, flash 2/2 // config divisors: 2 MHz core, 2 MHz bus, 1 MHz flash SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(1); #else #error "Error, F_CPU must be 168, 144, 120, 96, 72, 48, 24, 16, 8, 4, or 2 MHz" #endif #if F_CPU > 16000000 // switch to PLL as clock source, FLL input = 16 MHz / 512 MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4); // wait for PLL clock to be used while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ; // now we're in PEE mode // USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0 SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6); #else SIM_SOPT2 = SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(3); #endif #if F_CPU <= 2000000 // since we are not going into "stop mode" i removed it SMC_PMCTRL = SMC_PMCTRL_RUNM(2); // VLPR mode :-) #endif // initialize the SysTick counter SYST_RVR = (F_CPU / 1000) - 1; SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE; //init_pins(); __enable_irq(); _init_Teensyduino_internal_(); if (RTC_SR & RTC_SR_TIF) { // TODO: this should probably set the time more agressively, if // we could reliably detect the first reboot after programming. rtc_set(TIME_T); } __libc_init_array(); startup_late_hook(); main(); while (1) ; } char *__brkval = (char *)&_ebss; void * _sbrk(int incr) { char *prev = __brkval; __brkval += incr; return prev; } __attribute__((weak)) int _read(int file, char *ptr, int len) { return 0; } __attribute__((weak)) int _close(int fd) { return -1; } #include __attribute__((weak)) int _fstat(int fd, struct stat *st) { st->st_mode = S_IFCHR; return 0; } __attribute__((weak)) int _isatty(int fd) { return 1; } __attribute__((weak)) int _lseek(int fd, long long offset, int whence) { return -1; } __attribute__((weak)) void _exit(int status) { while (1); } __attribute__((weak)) void __cxa_pure_virtual() { while (1); } __attribute__((weak)) int __cxa_guard_acquire (char *g) { return !(*g); } __attribute__((weak)) void __cxa_guard_release(char *g) { *g = 1; } int nvic_execution_priority(void) { int priority=256; uint32_t primask, faultmask, basepri, ipsr; // full algorithm in ARM DDI0403D, page B1-639 // this isn't quite complete, but hopefully good enough __asm__ volatile("mrs %0, faultmask\n" : "=r" (faultmask)::); if (faultmask) return -1; __asm__ volatile("mrs %0, primask\n" : "=r" (primask)::); if (primask) return 0; __asm__ volatile("mrs %0, ipsr\n" : "=r" (ipsr)::); if (ipsr) { if (ipsr < 16) priority = 0; // could be non-zero else priority = NVIC_GET_PRIORITY(ipsr - 16); } __asm__ volatile("mrs %0, basepri\n" : "=r" (basepri)::); if (basepri > 0 && basepri < priority) priority = basepri; return priority; } micropython-1.12/ports/teensy/core/mk20dx128.h000066400000000000000000004727731357706137100211650ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef _mk20dx128_h_ #define _mk20dx128_h_ //#ifdef F_CPU //#undef F_CPU //#endif //#define F_CPU 168000000 //#define F_CPU 144000000 //#define F_CPU 120000000 //#define F_CPU 96000000 //#define F_CPU 72000000 //#define F_CPU 48000000 //#define F_CPU 24000000 #if (F_CPU == 168000000) #define F_BUS 56000000 #define F_MEM 33600000 #elif (F_CPU == 144000000) #define F_BUS 48000000 #define F_MEM 28800000 #elif (F_CPU == 120000000) #define F_BUS 60000000 #define F_MEM 24000000 #elif (F_CPU == 96000000) #define F_BUS 48000000 #define F_MEM 24000000 #elif (F_CPU == 72000000) #define F_BUS 36000000 #define F_MEM 24000000 #elif (F_CPU == 48000000) #define F_BUS 48000000 #define F_MEM 24000000 #elif (F_CPU == 24000000) #define F_BUS 24000000 #define F_MEM 24000000 #elif (F_CPU == 16000000) #define F_BUS 16000000 #define F_MEM 16000000 #elif (F_CPU == 8000000) #define F_BUS 8000000 #define F_MEM 8000000 #elif (F_CPU == 4000000) #define F_BUS 4000000 #define F_MEM 4000000 #elif (F_CPU == 2000000) #define F_BUS 2000000 #define F_MEM 1000000 #endif #ifndef NULL #define NULL ((void *)0) #endif #include #ifdef __cplusplus extern "C" { #endif // chapter 11: Port control and interrupts (PORT) #define PORTA_PCR0 *(volatile uint32_t *)0x40049000 // Pin Control Register n #define PORT_PCR_ISF (uint32_t)0x01000000 // Interrupt Status Flag #define PORT_PCR_IRQC(n) (uint32_t)(((n) & 15) << 16) // Interrupt Configuration #define PORT_PCR_IRQC_MASK (uint32_t)0x000F0000 #define PORT_PCR_LK (uint32_t)0x00008000 // Lock Register #define PORT_PCR_MUX(n) (uint32_t)(((n) & 7) << 8) // Pin Mux Control #define PORT_PCR_MUX_MASK (uint32_t)0x00000700 #define PORT_PCR_DSE (uint32_t)0x00000040 // Drive Strength Enable #define PORT_PCR_ODE (uint32_t)0x00000020 // Open Drain Enable #define PORT_PCR_PFE (uint32_t)0x00000010 // Passive Filter Enable #define PORT_PCR_SRE (uint32_t)0x00000004 // Slew Rate Enable #define PORT_PCR_PE (uint32_t)0x00000002 // Pull Enable #define PORT_PCR_PS (uint32_t)0x00000001 // Pull Select #define PORTA_PCR1 *(volatile uint32_t *)0x40049004 // Pin Control Register n #define PORTA_PCR2 *(volatile uint32_t *)0x40049008 // Pin Control Register n #define PORTA_PCR3 *(volatile uint32_t *)0x4004900C // Pin Control Register n #define PORTA_PCR4 *(volatile uint32_t *)0x40049010 // Pin Control Register n #define PORTA_PCR5 *(volatile uint32_t *)0x40049014 // Pin Control Register n #define PORTA_PCR6 *(volatile uint32_t *)0x40049018 // Pin Control Register n #define PORTA_PCR7 *(volatile uint32_t *)0x4004901C // Pin Control Register n #define PORTA_PCR8 *(volatile uint32_t *)0x40049020 // Pin Control Register n #define PORTA_PCR9 *(volatile uint32_t *)0x40049024 // Pin Control Register n #define PORTA_PCR10 *(volatile uint32_t *)0x40049028 // Pin Control Register n #define PORTA_PCR11 *(volatile uint32_t *)0x4004902C // Pin Control Register n #define PORTA_PCR12 *(volatile uint32_t *)0x40049030 // Pin Control Register n #define PORTA_PCR13 *(volatile uint32_t *)0x40049034 // Pin Control Register n #define PORTA_PCR14 *(volatile uint32_t *)0x40049038 // Pin Control Register n #define PORTA_PCR15 *(volatile uint32_t *)0x4004903C // Pin Control Register n #define PORTA_PCR16 *(volatile uint32_t *)0x40049040 // Pin Control Register n #define PORTA_PCR17 *(volatile uint32_t *)0x40049044 // Pin Control Register n #define PORTA_PCR18 *(volatile uint32_t *)0x40049048 // Pin Control Register n #define PORTA_PCR19 *(volatile uint32_t *)0x4004904C // Pin Control Register n #define PORTA_PCR20 *(volatile uint32_t *)0x40049050 // Pin Control Register n #define PORTA_PCR21 *(volatile uint32_t *)0x40049054 // Pin Control Register n #define PORTA_PCR22 *(volatile uint32_t *)0x40049058 // Pin Control Register n #define PORTA_PCR23 *(volatile uint32_t *)0x4004905C // Pin Control Register n #define PORTA_PCR24 *(volatile uint32_t *)0x40049060 // Pin Control Register n #define PORTA_PCR25 *(volatile uint32_t *)0x40049064 // Pin Control Register n #define PORTA_PCR26 *(volatile uint32_t *)0x40049068 // Pin Control Register n #define PORTA_PCR27 *(volatile uint32_t *)0x4004906C // Pin Control Register n #define PORTA_PCR28 *(volatile uint32_t *)0x40049070 // Pin Control Register n #define PORTA_PCR29 *(volatile uint32_t *)0x40049074 // Pin Control Register n #define PORTA_PCR30 *(volatile uint32_t *)0x40049078 // Pin Control Register n #define PORTA_PCR31 *(volatile uint32_t *)0x4004907C // Pin Control Register n #define PORTA_GPCLR *(volatile uint32_t *)0x40049080 // Global Pin Control Low Register #define PORTA_GPCHR *(volatile uint32_t *)0x40049084 // Global Pin Control High Register #define PORTA_ISFR *(volatile uint32_t *)0x400490A0 // Interrupt Status Flag Register #define PORTB_PCR0 *(volatile uint32_t *)0x4004A000 // Pin Control Register n #define PORTB_PCR1 *(volatile uint32_t *)0x4004A004 // Pin Control Register n #define PORTB_PCR2 *(volatile uint32_t *)0x4004A008 // Pin Control Register n #define PORTB_PCR3 *(volatile uint32_t *)0x4004A00C // Pin Control Register n #define PORTB_PCR4 *(volatile uint32_t *)0x4004A010 // Pin Control Register n #define PORTB_PCR5 *(volatile uint32_t *)0x4004A014 // Pin Control Register n #define PORTB_PCR6 *(volatile uint32_t *)0x4004A018 // Pin Control Register n #define PORTB_PCR7 *(volatile uint32_t *)0x4004A01C // Pin Control Register n #define PORTB_PCR8 *(volatile uint32_t *)0x4004A020 // Pin Control Register n #define PORTB_PCR9 *(volatile uint32_t *)0x4004A024 // Pin Control Register n #define PORTB_PCR10 *(volatile uint32_t *)0x4004A028 // Pin Control Register n #define PORTB_PCR11 *(volatile uint32_t *)0x4004A02C // Pin Control Register n #define PORTB_PCR12 *(volatile uint32_t *)0x4004A030 // Pin Control Register n #define PORTB_PCR13 *(volatile uint32_t *)0x4004A034 // Pin Control Register n #define PORTB_PCR14 *(volatile uint32_t *)0x4004A038 // Pin Control Register n #define PORTB_PCR15 *(volatile uint32_t *)0x4004A03C // Pin Control Register n #define PORTB_PCR16 *(volatile uint32_t *)0x4004A040 // Pin Control Register n #define PORTB_PCR17 *(volatile uint32_t *)0x4004A044 // Pin Control Register n #define PORTB_PCR18 *(volatile uint32_t *)0x4004A048 // Pin Control Register n #define PORTB_PCR19 *(volatile uint32_t *)0x4004A04C // Pin Control Register n #define PORTB_PCR20 *(volatile uint32_t *)0x4004A050 // Pin Control Register n #define PORTB_PCR21 *(volatile uint32_t *)0x4004A054 // Pin Control Register n #define PORTB_PCR22 *(volatile uint32_t *)0x4004A058 // Pin Control Register n #define PORTB_PCR23 *(volatile uint32_t *)0x4004A05C // Pin Control Register n #define PORTB_PCR24 *(volatile uint32_t *)0x4004A060 // Pin Control Register n #define PORTB_PCR25 *(volatile uint32_t *)0x4004A064 // Pin Control Register n #define PORTB_PCR26 *(volatile uint32_t *)0x4004A068 // Pin Control Register n #define PORTB_PCR27 *(volatile uint32_t *)0x4004A06C // Pin Control Register n #define PORTB_PCR28 *(volatile uint32_t *)0x4004A070 // Pin Control Register n #define PORTB_PCR29 *(volatile uint32_t *)0x4004A074 // Pin Control Register n #define PORTB_PCR30 *(volatile uint32_t *)0x4004A078 // Pin Control Register n #define PORTB_PCR31 *(volatile uint32_t *)0x4004A07C // Pin Control Register n #define PORTB_GPCLR *(volatile uint32_t *)0x4004A080 // Global Pin Control Low Register #define PORTB_GPCHR *(volatile uint32_t *)0x4004A084 // Global Pin Control High Register #define PORTB_ISFR *(volatile uint32_t *)0x4004A0A0 // Interrupt Status Flag Register #define PORTC_PCR0 *(volatile uint32_t *)0x4004B000 // Pin Control Register n #define PORTC_PCR1 *(volatile uint32_t *)0x4004B004 // Pin Control Register n #define PORTC_PCR2 *(volatile uint32_t *)0x4004B008 // Pin Control Register n #define PORTC_PCR3 *(volatile uint32_t *)0x4004B00C // Pin Control Register n #define PORTC_PCR4 *(volatile uint32_t *)0x4004B010 // Pin Control Register n #define PORTC_PCR5 *(volatile uint32_t *)0x4004B014 // Pin Control Register n #define PORTC_PCR6 *(volatile uint32_t *)0x4004B018 // Pin Control Register n #define PORTC_PCR7 *(volatile uint32_t *)0x4004B01C // Pin Control Register n #define PORTC_PCR8 *(volatile uint32_t *)0x4004B020 // Pin Control Register n #define PORTC_PCR9 *(volatile uint32_t *)0x4004B024 // Pin Control Register n #define PORTC_PCR10 *(volatile uint32_t *)0x4004B028 // Pin Control Register n #define PORTC_PCR11 *(volatile uint32_t *)0x4004B02C // Pin Control Register n #define PORTC_PCR12 *(volatile uint32_t *)0x4004B030 // Pin Control Register n #define PORTC_PCR13 *(volatile uint32_t *)0x4004B034 // Pin Control Register n #define PORTC_PCR14 *(volatile uint32_t *)0x4004B038 // Pin Control Register n #define PORTC_PCR15 *(volatile uint32_t *)0x4004B03C // Pin Control Register n #define PORTC_PCR16 *(volatile uint32_t *)0x4004B040 // Pin Control Register n #define PORTC_PCR17 *(volatile uint32_t *)0x4004B044 // Pin Control Register n #define PORTC_PCR18 *(volatile uint32_t *)0x4004B048 // Pin Control Register n #define PORTC_PCR19 *(volatile uint32_t *)0x4004B04C // Pin Control Register n #define PORTC_PCR20 *(volatile uint32_t *)0x4004B050 // Pin Control Register n #define PORTC_PCR21 *(volatile uint32_t *)0x4004B054 // Pin Control Register n #define PORTC_PCR22 *(volatile uint32_t *)0x4004B058 // Pin Control Register n #define PORTC_PCR23 *(volatile uint32_t *)0x4004B05C // Pin Control Register n #define PORTC_PCR24 *(volatile uint32_t *)0x4004B060 // Pin Control Register n #define PORTC_PCR25 *(volatile uint32_t *)0x4004B064 // Pin Control Register n #define PORTC_PCR26 *(volatile uint32_t *)0x4004B068 // Pin Control Register n #define PORTC_PCR27 *(volatile uint32_t *)0x4004B06C // Pin Control Register n #define PORTC_PCR28 *(volatile uint32_t *)0x4004B070 // Pin Control Register n #define PORTC_PCR29 *(volatile uint32_t *)0x4004B074 // Pin Control Register n #define PORTC_PCR30 *(volatile uint32_t *)0x4004B078 // Pin Control Register n #define PORTC_PCR31 *(volatile uint32_t *)0x4004B07C // Pin Control Register n #define PORTC_GPCLR *(volatile uint32_t *)0x4004B080 // Global Pin Control Low Register #define PORTC_GPCHR *(volatile uint32_t *)0x4004B084 // Global Pin Control High Register #define PORTC_ISFR *(volatile uint32_t *)0x4004B0A0 // Interrupt Status Flag Register #define PORTD_PCR0 *(volatile uint32_t *)0x4004C000 // Pin Control Register n #define PORTD_PCR1 *(volatile uint32_t *)0x4004C004 // Pin Control Register n #define PORTD_PCR2 *(volatile uint32_t *)0x4004C008 // Pin Control Register n #define PORTD_PCR3 *(volatile uint32_t *)0x4004C00C // Pin Control Register n #define PORTD_PCR4 *(volatile uint32_t *)0x4004C010 // Pin Control Register n #define PORTD_PCR5 *(volatile uint32_t *)0x4004C014 // Pin Control Register n #define PORTD_PCR6 *(volatile uint32_t *)0x4004C018 // Pin Control Register n #define PORTD_PCR7 *(volatile uint32_t *)0x4004C01C // Pin Control Register n #define PORTD_PCR8 *(volatile uint32_t *)0x4004C020 // Pin Control Register n #define PORTD_PCR9 *(volatile uint32_t *)0x4004C024 // Pin Control Register n #define PORTD_PCR10 *(volatile uint32_t *)0x4004C028 // Pin Control Register n #define PORTD_PCR11 *(volatile uint32_t *)0x4004C02C // Pin Control Register n #define PORTD_PCR12 *(volatile uint32_t *)0x4004C030 // Pin Control Register n #define PORTD_PCR13 *(volatile uint32_t *)0x4004C034 // Pin Control Register n #define PORTD_PCR14 *(volatile uint32_t *)0x4004C038 // Pin Control Register n #define PORTD_PCR15 *(volatile uint32_t *)0x4004C03C // Pin Control Register n #define PORTD_PCR16 *(volatile uint32_t *)0x4004C040 // Pin Control Register n #define PORTD_PCR17 *(volatile uint32_t *)0x4004C044 // Pin Control Register n #define PORTD_PCR18 *(volatile uint32_t *)0x4004C048 // Pin Control Register n #define PORTD_PCR19 *(volatile uint32_t *)0x4004C04C // Pin Control Register n #define PORTD_PCR20 *(volatile uint32_t *)0x4004C050 // Pin Control Register n #define PORTD_PCR21 *(volatile uint32_t *)0x4004C054 // Pin Control Register n #define PORTD_PCR22 *(volatile uint32_t *)0x4004C058 // Pin Control Register n #define PORTD_PCR23 *(volatile uint32_t *)0x4004C05C // Pin Control Register n #define PORTD_PCR24 *(volatile uint32_t *)0x4004C060 // Pin Control Register n #define PORTD_PCR25 *(volatile uint32_t *)0x4004C064 // Pin Control Register n #define PORTD_PCR26 *(volatile uint32_t *)0x4004C068 // Pin Control Register n #define PORTD_PCR27 *(volatile uint32_t *)0x4004C06C // Pin Control Register n #define PORTD_PCR28 *(volatile uint32_t *)0x4004C070 // Pin Control Register n #define PORTD_PCR29 *(volatile uint32_t *)0x4004C074 // Pin Control Register n #define PORTD_PCR30 *(volatile uint32_t *)0x4004C078 // Pin Control Register n #define PORTD_PCR31 *(volatile uint32_t *)0x4004C07C // Pin Control Register n #define PORTD_GPCLR *(volatile uint32_t *)0x4004C080 // Global Pin Control Low Register #define PORTD_GPCHR *(volatile uint32_t *)0x4004C084 // Global Pin Control High Register #define PORTD_ISFR *(volatile uint32_t *)0x4004C0A0 // Interrupt Status Flag Register #define PORTE_PCR0 *(volatile uint32_t *)0x4004D000 // Pin Control Register n #define PORTE_PCR1 *(volatile uint32_t *)0x4004D004 // Pin Control Register n #define PORTE_PCR2 *(volatile uint32_t *)0x4004D008 // Pin Control Register n #define PORTE_PCR3 *(volatile uint32_t *)0x4004D00C // Pin Control Register n #define PORTE_PCR4 *(volatile uint32_t *)0x4004D010 // Pin Control Register n #define PORTE_PCR5 *(volatile uint32_t *)0x4004D014 // Pin Control Register n #define PORTE_PCR6 *(volatile uint32_t *)0x4004D018 // Pin Control Register n #define PORTE_PCR7 *(volatile uint32_t *)0x4004D01C // Pin Control Register n #define PORTE_PCR8 *(volatile uint32_t *)0x4004D020 // Pin Control Register n #define PORTE_PCR9 *(volatile uint32_t *)0x4004D024 // Pin Control Register n #define PORTE_PCR10 *(volatile uint32_t *)0x4004D028 // Pin Control Register n #define PORTE_PCR11 *(volatile uint32_t *)0x4004D02C // Pin Control Register n #define PORTE_PCR12 *(volatile uint32_t *)0x4004D030 // Pin Control Register n #define PORTE_PCR13 *(volatile uint32_t *)0x4004D034 // Pin Control Register n #define PORTE_PCR14 *(volatile uint32_t *)0x4004D038 // Pin Control Register n #define PORTE_PCR15 *(volatile uint32_t *)0x4004D03C // Pin Control Register n #define PORTE_PCR16 *(volatile uint32_t *)0x4004D040 // Pin Control Register n #define PORTE_PCR17 *(volatile uint32_t *)0x4004D044 // Pin Control Register n #define PORTE_PCR18 *(volatile uint32_t *)0x4004D048 // Pin Control Register n #define PORTE_PCR19 *(volatile uint32_t *)0x4004D04C // Pin Control Register n #define PORTE_PCR20 *(volatile uint32_t *)0x4004D050 // Pin Control Register n #define PORTE_PCR21 *(volatile uint32_t *)0x4004D054 // Pin Control Register n #define PORTE_PCR22 *(volatile uint32_t *)0x4004D058 // Pin Control Register n #define PORTE_PCR23 *(volatile uint32_t *)0x4004D05C // Pin Control Register n #define PORTE_PCR24 *(volatile uint32_t *)0x4004D060 // Pin Control Register n #define PORTE_PCR25 *(volatile uint32_t *)0x4004D064 // Pin Control Register n #define PORTE_PCR26 *(volatile uint32_t *)0x4004D068 // Pin Control Register n #define PORTE_PCR27 *(volatile uint32_t *)0x4004D06C // Pin Control Register n #define PORTE_PCR28 *(volatile uint32_t *)0x4004D070 // Pin Control Register n #define PORTE_PCR29 *(volatile uint32_t *)0x4004D074 // Pin Control Register n #define PORTE_PCR30 *(volatile uint32_t *)0x4004D078 // Pin Control Register n #define PORTE_PCR31 *(volatile uint32_t *)0x4004D07C // Pin Control Register n #define PORTE_GPCLR *(volatile uint32_t *)0x4004D080 // Global Pin Control Low Register #define PORTE_GPCHR *(volatile uint32_t *)0x4004D084 // Global Pin Control High Register #define PORTE_ISFR *(volatile uint32_t *)0x4004D0A0 // Interrupt Status Flag Register // Chapter 12: System Integration Module (SIM) #define SIM_SOPT1 *(volatile uint32_t *)0x40047000 // System Options Register 1 #define SIM_SOPT1CFG *(volatile uint32_t *)0x40047004 // SOPT1 Configuration Register #define SIM_SOPT2 *(volatile uint32_t *)0x40048004 // System Options Register 2 #define SIM_SOPT2_USBSRC (uint32_t)0x00040000 // 0=USB_CLKIN, 1=FFL/PLL #define SIM_SOPT2_PLLFLLSEL (uint32_t)0x00010000 // 0=FLL, 1=PLL #define SIM_SOPT2_TRACECLKSEL (uint32_t)0x00001000 // 0=MCGOUTCLK, 1=CPU #define SIM_SOPT2_PTD7PAD (uint32_t)0x00000800 // 0=normal, 1=double drive PTD7 #define SIM_SOPT2_CLKOUTSEL(n) (uint32_t)(((n) & 7) << 5) // Selects the clock to output on the CLKOUT pin. #define SIM_SOPT2_RTCCLKOUTSEL (uint32_t)0x00000010 // RTC clock out select #define SIM_SOPT4 *(volatile uint32_t *)0x4004800C // System Options Register 4 #define SIM_SOPT5 *(volatile uint32_t *)0x40048010 // System Options Register 5 #define SIM_SOPT7 *(volatile uint32_t *)0x40048018 // System Options Register 7 #define SIM_SDID *(const uint32_t *)0x40048024 // System Device Identification Register #define SIM_SCGC2 *(volatile uint32_t *)0x4004802C // System Clock Gating Control Register 2 #define SIM_SCGC2_DAC0 (uint32_t)0x00001000 // DAC0 Clock Gate Control #define SIM_SCGC3 *(volatile uint32_t *)0x40048030 // System Clock Gating Control Register 3 #define SIM_SCGC3_ADC1 (uint32_t)0x08000000 // ADC1 Clock Gate Control #define SIM_SCGC3_FTM2 (uint32_t)0x01000000 // FTM2 Clock Gate Control #define SIM_SCGC4 *(volatile uint32_t *)0x40048034 // System Clock Gating Control Register 4 #define SIM_SCGC4_VREF (uint32_t)0x00100000 // VREF Clock Gate Control #define SIM_SCGC4_CMP (uint32_t)0x00080000 // Comparator Clock Gate Control #define SIM_SCGC4_USBOTG (uint32_t)0x00040000 // USB Clock Gate Control #define SIM_SCGC4_UART2 (uint32_t)0x00001000 // UART2 Clock Gate Control #define SIM_SCGC4_UART1 (uint32_t)0x00000800 // UART1 Clock Gate Control #define SIM_SCGC4_UART0 (uint32_t)0x00000400 // UART0 Clock Gate Control #define SIM_SCGC4_I2C1 (uint32_t)0x00000080 // I2C1 Clock Gate Control #define SIM_SCGC4_I2C0 (uint32_t)0x00000040 // I2C0 Clock Gate Control #define SIM_SCGC4_CMT (uint32_t)0x00000004 // CMT Clock Gate Control #define SIM_SCGC4_EWM (uint32_t)0x00000002 // EWM Clock Gate Control #define SIM_SCGC5 *(volatile uint32_t *)0x40048038 // System Clock Gating Control Register 5 #define SIM_SCGC5_PORTE (uint32_t)0x00002000 // Port E Clock Gate Control #define SIM_SCGC5_PORTD (uint32_t)0x00001000 // Port D Clock Gate Control #define SIM_SCGC5_PORTC (uint32_t)0x00000800 // Port C Clock Gate Control #define SIM_SCGC5_PORTB (uint32_t)0x00000400 // Port B Clock Gate Control #define SIM_SCGC5_PORTA (uint32_t)0x00000200 // Port A Clock Gate Control #define SIM_SCGC5_TSI (uint32_t)0x00000020 // Touch Sense Input TSI Clock Gate Control #define SIM_SCGC5_LPTIMER (uint32_t)0x00000001 // Low Power Timer Access Control #define SIM_SCGC6 *(volatile uint32_t *)0x4004803C // System Clock Gating Control Register 6 #define SIM_SCGC6_RTC (uint32_t)0x20000000 // RTC Access #define SIM_SCGC6_ADC0 (uint32_t)0x08000000 // ADC0 Clock Gate Control #define SIM_SCGC6_FTM1 (uint32_t)0x02000000 // FTM1 Clock Gate Control #define SIM_SCGC6_FTM0 (uint32_t)0x01000000 // FTM0 Clock Gate Control #define SIM_SCGC6_PIT (uint32_t)0x00800000 // PIT Clock Gate Control #define SIM_SCGC6_PDB (uint32_t)0x00400000 // PDB Clock Gate Control #define SIM_SCGC6_USBDCD (uint32_t)0x00200000 // USB DCD Clock Gate Control #define SIM_SCGC6_CRC (uint32_t)0x00040000 // CRC Clock Gate Control #define SIM_SCGC6_I2S (uint32_t)0x00008000 // I2S Clock Gate Control #define SIM_SCGC6_SPI1 (uint32_t)0x00002000 // SPI1 Clock Gate Control #define SIM_SCGC6_SPI0 (uint32_t)0x00001000 // SPI0 Clock Gate Control #define SIM_SCGC6_FLEXCAN0 (uint32_t)0x00000010 // FlexCAN0 Clock Gate Control #define SIM_SCGC6_DMAMUX (uint32_t)0x00000002 // DMA Mux Clock Gate Control #define SIM_SCGC6_FTFL (uint32_t)0x00000001 // Flash Memory Clock Gate Control #define SIM_SCGC7 *(volatile uint32_t *)0x40048040 // System Clock Gating Control Register 7 #define SIM_SCGC7_DMA (uint32_t)0x00000002 // DMA Clock Gate Control #define SIM_CLKDIV1 *(volatile uint32_t *)0x40048044 // System Clock Divider Register 1 #define SIM_CLKDIV1_OUTDIV1(n) (uint32_t)(((n) & 0x0F) << 28) // divide value for the core/system clock #define SIM_CLKDIV1_OUTDIV2(n) (uint32_t)(((n) & 0x0F) << 24) // divide value for the peripheral clock #define SIM_CLKDIV1_OUTDIV4(n) (uint32_t)(((n) & 0x0F) << 16) // divide value for the flash clock #define SIM_CLKDIV2 *(volatile uint32_t *)0x40048048 // System Clock Divider Register 2 #define SIM_CLKDIV2_USBDIV(n) (uint32_t)(((n) & 0x07) << 1) #define SIM_CLKDIV2_USBFRAC (uint32_t)0x01 #define SIM_FCFG1 *(const uint32_t *)0x4004804C // Flash Configuration Register 1 #define SIM_FCFG2 *(const uint32_t *)0x40048050 // Flash Configuration Register 2 #define SIM_UIDH *(const uint32_t *)0x40048054 // Unique Identification Register High #define SIM_UIDMH *(const uint32_t *)0x40048058 // Unique Identification Register Mid-High #define SIM_UIDML *(const uint32_t *)0x4004805C // Unique Identification Register Mid Low #define SIM_UIDL *(const uint32_t *)0x40048060 // Unique Identification Register Low // Chapter 13: Reset Control Module (RCM) #define RCM_SRS0 *(volatile uint8_t *)0x4007F000 // System Reset Status Register 0 #define RCM_SRS1 *(volatile uint8_t *)0x4007F001 // System Reset Status Register 1 #define RCM_RPFC *(volatile uint8_t *)0x4007F004 // Reset Pin Filter Control Register #define RCM_RPFW *(volatile uint8_t *)0x4007F005 // Reset Pin Filter Width Register #define RCM_MR *(volatile uint8_t *)0x4007F007 // Mode Register // Chapter 14: System Mode Controller #define SMC_PMPROT *(volatile uint8_t *)0x4007E000 // Power Mode Protection Register #define SMC_PMPROT_AVLP (uint8_t)0x20 // Allow very low power modes #define SMC_PMPROT_ALLS (uint8_t)0x08 // Allow low leakage stop mode #define SMC_PMPROT_AVLLS (uint8_t)0x02 // Allow very low leakage stop mode #define SMC_PMCTRL *(volatile uint8_t *)0x4007E001 // Power Mode Control Register #define SMC_PMCTRL_LPWUI (uint8_t)0x80 // Low Power Wake Up on Interrupt #define SMC_PMCTRL_RUNM(n) (uint8_t)(((n) & 0x03) << 5) // Run Mode Control #define SMC_PMCTRL_STOPA (uint8_t)0x08 // Stop Aborted #define SMC_PMCTRL_STOPM(n) (uint8_t)((n) & 0x07) // Stop Mode Control #define SMC_VLLSCTRL *(volatile uint8_t *)0x4007E002 // VLLS Control Register #define SMC_VLLSCTRL_PORPO (uint8_t)0x20 // POR Power Option #define SMC_VLLSCTRL_VLLSM(n) (uint8_t)((n) & 0x07) // VLLS Mode Control #define SMC_PMSTAT *(volatile uint8_t *)0x4007E003 // Power Mode Status Register #define SMC_PMSTAT_RUN (uint8_t)0x01 // Current power mode is RUN #define SMC_PMSTAT_STOP (uint8_t)0x02 // Current power mode is STOP #define SMC_PMSTAT_VLPR (uint8_t)0x04 // Current power mode is VLPR #define SMC_PMSTAT_VLPW (uint8_t)0x08 // Current power mode is VLPW #define SMC_PMSTAT_VLPS (uint8_t)0x10 // Current power mode is VLPS #define SMC_PMSTAT_LLS (uint8_t)0x20 // Current power mode is LLS #define SMC_PMSTAT_VLLS (uint8_t)0x40 // Current power mode is VLLS // Chapter 15: Power Management Controller #define PMC_LVDSC1 *(volatile uint8_t *)0x4007D000 // Low Voltage Detect Status And Control 1 register #define PMC_LVDSC1_LVDF (uint8_t)0x80 // Low-Voltage Detect Flag #define PMC_LVDSC1_LVDACK (uint8_t)0x40 // Low-Voltage Detect Acknowledge #define PMC_LVDSC1_LVDIE (uint8_t)0x20 // Low-Voltage Detect Interrupt Enable #define PMC_LVDSC1_LVDRE (uint8_t)0x10 // Low-Voltage Detect Reset Enable #define PMC_LVDSC1_LVDV(n) (uint8_t)((n) & 0x03) // Low-Voltage Detect Voltage Select #define PMC_LVDSC2 *(volatile uint8_t *)0x4007D001 // Low Voltage Detect Status And Control 2 register #define PMC_LVDSC2_LVWF (uint8_t)0x80 // Low-Voltage Warning Flag #define PMC_LVDSC2_LVWACK (uint8_t)0x40 // Low-Voltage Warning Acknowledge #define PMC_LVDSC2_LVWIE (uint8_t)0x20 // Low-Voltage Warning Interrupt Enable #define PMC_LVDSC2_LVWV(n) (uint8_t)((n) & 0x03) // Low-Voltage Warning Voltage Select #define PMC_REGSC *(volatile uint8_t *)0x4007D002 // Regulator Status And Control register #define PMC_REGSC_BGEN (uint8_t)0x10 // Bandgap Enable In VLPx Operation #define PMC_REGSC_ACKISO (uint8_t)0x08 // Acknowledge Isolation #define PMC_REGSC_REGONS (uint8_t)0x04 // Regulator In Run Regulation Status #define PMC_REGSC_BGBE (uint8_t)0x01 // Bandgap Buffer Enable // Chapter 16: Low-Leakage Wakeup Unit (LLWU) #define LLWU_PE1 *(volatile uint8_t *)0x4007C000 // LLWU Pin Enable 1 register #define LLWU_PE2 *(volatile uint8_t *)0x4007C001 // LLWU Pin Enable 2 register #define LLWU_PE3 *(volatile uint8_t *)0x4007C002 // LLWU Pin Enable 3 register #define LLWU_PE4 *(volatile uint8_t *)0x4007C003 // LLWU Pin Enable 4 register #define LLWU_ME *(volatile uint8_t *)0x4007C004 // LLWU Module Enable register #define LLWU_F1 *(volatile uint8_t *)0x4007C005 // LLWU Flag 1 register #define LLWU_F2 *(volatile uint8_t *)0x4007C006 // LLWU Flag 2 register #define LLWU_F3 *(volatile uint8_t *)0x4007C007 // LLWU Flag 3 register #define LLWU_FILT1 *(volatile uint8_t *)0x4007C008 // LLWU Pin Filter 1 register #define LLWU_FILT2 *(volatile uint8_t *)0x4007C009 // LLWU Pin Filter 2 register #define LLWU_RST *(volatile uint8_t *)0x4007C00A // LLWU Reset Enable register // Chapter 17: Miscellaneous Control Module (MCM) #define MCM_PLASC *(volatile uint16_t *)0xE0080008 // Crossbar Switch (AXBS) Slave Configuration #define MCM_PLAMC *(volatile uint16_t *)0xE008000A // Crossbar Switch (AXBS) Master Configuration #define MCM_PLACR *(volatile uint32_t *)0xE008000C // Crossbar Switch (AXBS) Control Register (MK20DX128) #define MCM_PLACR_ARG (uint32_t)0x00000200 // Arbitration select, 0=fixed, 1=round-robin #define MCM_CR *(volatile uint32_t *)0xE008000C // RAM arbitration control register (MK20DX256) #define MCM_CR_SRAMLWP (uint32_t)0x40000000 // SRAM_L write protect #define MCM_CR_SRAMLAP(n) (uint32_t)(((n) & 0x03) << 28) // SRAM_L priority, 0=RR, 1=favor DMA, 2=CPU, 3=DMA #define MCM_CR_SRAMUWP (uint32_t)0x04000000 // SRAM_U write protect #define MCM_CR_SRAMUAP(n) (uint32_t)(((n) & 0x03) << 24) // SRAM_U priority, 0=RR, 1=favor DMA, 2=CPU, 3=DMA // Crossbar Switch (AXBS) - only programmable on MK20DX256 #define AXBS_PRS0 *(volatile uint32_t *)0x40004000 // Priority Registers Slave 0 #define AXBS_CRS0 *(volatile uint32_t *)0x40004010 // Control Register 0 #define AXBS_PRS1 *(volatile uint32_t *)0x40004100 // Priority Registers Slave 1 #define AXBS_CRS1 *(volatile uint32_t *)0x40004110 // Control Register 1 #define AXBS_PRS2 *(volatile uint32_t *)0x40004200 // Priority Registers Slave 2 #define AXBS_CRS2 *(volatile uint32_t *)0x40004210 // Control Register 2 #define AXBS_PRS3 *(volatile uint32_t *)0x40004300 // Priority Registers Slave 3 #define AXBS_CRS3 *(volatile uint32_t *)0x40004310 // Control Register 3 #define AXBS_PRS4 *(volatile uint32_t *)0x40004400 // Priority Registers Slave 4 #define AXBS_CRS4 *(volatile uint32_t *)0x40004410 // Control Register 4 #define AXBS_PRS5 *(volatile uint32_t *)0x40004500 // Priority Registers Slave 5 #define AXBS_CRS5 *(volatile uint32_t *)0x40004510 // Control Register 5 #define AXBS_PRS6 *(volatile uint32_t *)0x40004600 // Priority Registers Slave 6 #define AXBS_CRS6 *(volatile uint32_t *)0x40004610 // Control Register 6 #define AXBS_PRS7 *(volatile uint32_t *)0x40004700 // Priority Registers Slave 7 #define AXBS_CRS7 *(volatile uint32_t *)0x40004710 // Control Register 7 #define AXBS_MGPCR0 *(volatile uint32_t *)0x40004800 // Master 0 General Purpose Control Register #define AXBS_MGPCR1 *(volatile uint32_t *)0x40004900 // Master 1 General Purpose Control Register #define AXBS_MGPCR2 *(volatile uint32_t *)0x40004A00 // Master 2 General Purpose Control Register #define AXBS_MGPCR3 *(volatile uint32_t *)0x40004B00 // Master 3 General Purpose Control Register #define AXBS_MGPCR4 *(volatile uint32_t *)0x40004C00 // Master 4 General Purpose Control Register #define AXBS_MGPCR5 *(volatile uint32_t *)0x40004D00 // Master 5 General Purpose Control Register #define AXBS_MGPCR6 *(volatile uint32_t *)0x40004E00 // Master 6 General Purpose Control Register #define AXBS_MGPCR7 *(volatile uint32_t *)0x40004F00 // Master 7 General Purpose Control Register #define AXBS_CRS_READONLY (uint32_t)0x80000000 #define AXBS_CRS_HALTLOWPRIORITY (uint32_t)0x40000000 #define AXBS_CRS_ARB_FIXED (uint32_t)0x00000000 #define AXBS_CRS_ARB_ROUNDROBIN (uint32_t)0x00010000 #define AXBS_CRS_PARK_FIXED (uint32_t)0x00000000 #define AXBS_CRS_PARK_PREVIOUS (uint32_t)0x00000010 #define AXBS_CRS_PARK_NONE (uint32_t)0x00000020 #define AXBS_CRS_PARK(n) (uint32_t)(((n) & 7) << 0) // Chapter 20: Direct Memory Access Multiplexer (DMAMUX) #define DMAMUX0_CHCFG0 *(volatile uint8_t *)0x40021000 // Channel Configuration register #define DMAMUX0_CHCFG1 *(volatile uint8_t *)0x40021001 // Channel Configuration register #define DMAMUX0_CHCFG2 *(volatile uint8_t *)0x40021002 // Channel Configuration register #define DMAMUX0_CHCFG3 *(volatile uint8_t *)0x40021003 // Channel Configuration register #define DMAMUX0_CHCFG4 *(volatile uint8_t *)0x40021004 // Channel Configuration register #define DMAMUX0_CHCFG5 *(volatile uint8_t *)0x40021005 // Channel Configuration register #define DMAMUX0_CHCFG6 *(volatile uint8_t *)0x40021006 // Channel Configuration register #define DMAMUX0_CHCFG7 *(volatile uint8_t *)0x40021007 // Channel Configuration register #define DMAMUX0_CHCFG8 *(volatile uint8_t *)0x40021008 // Channel Configuration register #define DMAMUX0_CHCFG9 *(volatile uint8_t *)0x40021009 // Channel Configuration register #define DMAMUX0_CHCFG10 *(volatile uint8_t *)0x4002100A // Channel Configuration register #define DMAMUX0_CHCFG11 *(volatile uint8_t *)0x4002100B // Channel Configuration register #define DMAMUX0_CHCFG12 *(volatile uint8_t *)0x4002100C // Channel Configuration register #define DMAMUX0_CHCFG13 *(volatile uint8_t *)0x4002100D // Channel Configuration register #define DMAMUX0_CHCFG14 *(volatile uint8_t *)0x4002100E // Channel Configuration register #define DMAMUX0_CHCFG15 *(volatile uint8_t *)0x4002100F // Channel Configuration register #define DMAMUX_DISABLE 0 #define DMAMUX_TRIG 64 #define DMAMUX_ENABLE 128 #define DMAMUX_SOURCE_UART0_RX 2 #define DMAMUX_SOURCE_UART0_TX 3 #define DMAMUX_SOURCE_UART1_RX 4 #define DMAMUX_SOURCE_UART1_TX 5 #define DMAMUX_SOURCE_UART2_RX 6 #define DMAMUX_SOURCE_UART2_TX 7 #define DMAMUX_SOURCE_I2S0_RX 14 #define DMAMUX_SOURCE_I2S0_TX 15 #define DMAMUX_SOURCE_SPI0_RX 16 #define DMAMUX_SOURCE_SPI0_TX 17 #define DMAMUX_SOURCE_I2C0 22 #define DMAMUX_SOURCE_I2C1 23 #define DMAMUX_SOURCE_FTM0_CH0 24 #define DMAMUX_SOURCE_FTM0_CH1 25 #define DMAMUX_SOURCE_FTM0_CH2 26 #define DMAMUX_SOURCE_FTM0_CH3 27 #define DMAMUX_SOURCE_FTM0_CH4 28 #define DMAMUX_SOURCE_FTM0_CH5 29 #define DMAMUX_SOURCE_FTM0_CH6 30 #define DMAMUX_SOURCE_FTM0_CH7 31 #define DMAMUX_SOURCE_FTM1_CH0 32 #define DMAMUX_SOURCE_FTM1_CH1 33 #define DMAMUX_SOURCE_FTM2_CH0 34 #define DMAMUX_SOURCE_FTM2_CH1 35 #define DMAMUX_SOURCE_ADC0 40 #define DMAMUX_SOURCE_ADC1 41 #define DMAMUX_SOURCE_CMP0 42 #define DMAMUX_SOURCE_CMP1 43 #define DMAMUX_SOURCE_CMP2 44 #define DMAMUX_SOURCE_DAC0 45 #define DMAMUX_SOURCE_CMT 47 #define DMAMUX_SOURCE_PDB 48 #define DMAMUX_SOURCE_PORTA 49 #define DMAMUX_SOURCE_PORTB 50 #define DMAMUX_SOURCE_PORTC 51 #define DMAMUX_SOURCE_PORTD 52 #define DMAMUX_SOURCE_PORTE 53 #define DMAMUX_SOURCE_ALWAYS0 54 #define DMAMUX_SOURCE_ALWAYS1 55 #define DMAMUX_SOURCE_ALWAYS2 56 #define DMAMUX_SOURCE_ALWAYS3 57 #define DMAMUX_SOURCE_ALWAYS4 58 #define DMAMUX_SOURCE_ALWAYS5 59 #define DMAMUX_SOURCE_ALWAYS6 60 #define DMAMUX_SOURCE_ALWAYS7 61 #define DMAMUX_SOURCE_ALWAYS8 62 #define DMAMUX_SOURCE_ALWAYS9 63 // Chapter 21: Direct Memory Access Controller (eDMA) #define DMA_CR *(volatile uint32_t *)0x40008000 // Control Register #define DMA_CR_CX ((uint32_t)(1<<17)) // Cancel Transfer #define DMA_CR_ECX ((uint32_t)(1<<16)) // Error Cancel Transfer #define DMA_CR_EMLM ((uint32_t)0x80) // Enable Minor Loop Mapping #define DMA_CR_CLM ((uint32_t)0x40) // Continuous Link Mode #define DMA_CR_HALT ((uint32_t)0x20) // Halt DMA Operations #define DMA_CR_HOE ((uint32_t)0x10) // Halt On Error #define DMA_CR_ERCA ((uint32_t)0x04) // Enable Round Robin Channel Arbitration #define DMA_CR_EDBG ((uint32_t)0x02) // Enable Debug #define DMA_ES *(volatile uint32_t *)0x40008004 // Error Status Register #define DMA_ERQ *(volatile uint32_t *)0x4000800C // Enable Request Register #define DMA_ERQ_ERQ0 ((uint32_t)1<<0) // Enable DMA Request 0 #define DMA_ERQ_ERQ1 ((uint32_t)1<<1) // Enable DMA Request 1 #define DMA_ERQ_ERQ2 ((uint32_t)1<<2) // Enable DMA Request 2 #define DMA_ERQ_ERQ3 ((uint32_t)1<<3) // Enable DMA Request 3 #define DMA_ERQ_ERQ4 ((uint32_t)1<<4) // Enable DMA Request 4 #define DMA_ERQ_ERQ5 ((uint32_t)1<<5) // Enable DMA Request 5 #define DMA_ERQ_ERQ6 ((uint32_t)1<<6) // Enable DMA Request 6 #define DMA_ERQ_ERQ7 ((uint32_t)1<<7) // Enable DMA Request 7 #define DMA_ERQ_ERQ8 ((uint32_t)1<<8) // Enable DMA Request 8 #define DMA_ERQ_ERQ9 ((uint32_t)1<<9) // Enable DMA Request 9 #define DMA_ERQ_ERQ10 ((uint32_t)1<<10) // Enable DMA Request 10 #define DMA_ERQ_ERQ11 ((uint32_t)1<<11) // Enable DMA Request 11 #define DMA_ERQ_ERQ12 ((uint32_t)1<<12) // Enable DMA Request 12 #define DMA_ERQ_ERQ13 ((uint32_t)1<<13) // Enable DMA Request 13 #define DMA_ERQ_ERQ14 ((uint32_t)1<<14) // Enable DMA Request 14 #define DMA_ERQ_ERQ15 ((uint32_t)1<<15) // Enable DMA Request 15 #define DMA_EEI *(volatile uint32_t *)0x40008014 // Enable Error Interrupt Register #define DMA_EEI_EEI0 ((uint32_t)1<<0) // Enable Error Interrupt 0 #define DMA_EEI_EEI1 ((uint32_t)1<<1) // Enable Error Interrupt 1 #define DMA_EEI_EEI2 ((uint32_t)1<<2) // Enable Error Interrupt 2 #define DMA_EEI_EEI3 ((uint32_t)1<<3) // Enable Error Interrupt 3 #define DMA_EEI_EEI4 ((uint32_t)1<<4) // Enable Error Interrupt 4 #define DMA_EEI_EEI5 ((uint32_t)1<<5) // Enable Error Interrupt 5 #define DMA_EEI_EEI6 ((uint32_t)1<<6) // Enable Error Interrupt 6 #define DMA_EEI_EEI7 ((uint32_t)1<<7) // Enable Error Interrupt 7 #define DMA_EEI_EEI8 ((uint32_t)1<<8) // Enable Error Interrupt 8 #define DMA_EEI_EEI9 ((uint32_t)1<<9) // Enable Error Interrupt 9 #define DMA_EEI_EEI10 ((uint32_t)1<<10) // Enable Error Interrupt 10 #define DMA_EEI_EEI11 ((uint32_t)1<<11) // Enable Error Interrupt 11 #define DMA_EEI_EEI12 ((uint32_t)1<<12) // Enable Error Interrupt 12 #define DMA_EEI_EEI13 ((uint32_t)1<<13) // Enable Error Interrupt 13 #define DMA_EEI_EEI14 ((uint32_t)1<<14) // Enable Error Interrupt 14 #define DMA_EEI_EEI15 ((uint32_t)1<<15) // Enable Error Interrupt 15 #define DMA_CEEI *(volatile uint8_t *)0x40008018 // Clear Enable Error Interrupt Register #define DMA_CEEI_CEEI(n) ((uint8_t)(n & 15)<<0) // Clear Enable Error Interrupt #define DMA_CEEI_CAEE ((uint8_t)1<<6) // Clear All Enable Error Interrupts #define DMA_CEEI_NOP ((uint8_t)1<<7) // NOP #define DMA_SEEI *(volatile uint8_t *)0x40008019 // Set Enable Error Interrupt Register #define DMA_SEEI_SEEI(n) ((uint8_t)(n & 15)<<0) // Set Enable Error Interrupt #define DMA_SEEI_SAEE ((uint8_t)1<<6) // Set All Enable Error Interrupts #define DMA_SEEI_NOP ((uint8_t)1<<7) // NOP #define DMA_CERQ *(volatile uint8_t *)0x4000801A // Clear Enable Request Register #define DMA_CERQ_CERQ(n) ((uint8_t)(n & 15)<<0) // Clear Enable Request #define DMA_CERQ_CAER ((uint8_t)1<<6) // Clear All Enable Requests #define DMA_CERQ_NOP ((uint8_t)1<<7) // NOP #define DMA_SERQ *(volatile uint8_t *)0x4000801B // Set Enable Request Register #define DMA_SERQ_SERQ(n) ((uint8_t)(n & 15)<<0) // Set Enable Request #define DMA_SERQ_SAER ((uint8_t)1<<6) // Set All Enable Requests #define DMA_SERQ_NOP ((uint8_t)1<<7) // NOP #define DMA_CDNE *(volatile uint8_t *)0x4000801C // Clear DONE Status Bit Register #define DMA_CDNE_CDNE(n) ((uint8_t)(n & 15)<<0) // Clear Done Bit #define DMA_CDNE_CADN ((uint8_t)1<<6) // Clear All Done Bits #define DMA_CDNE_NOP ((uint8_t)1<<7) // NOP #define DMA_SSRT *(volatile uint8_t *)0x4000801D // Set START Bit Register #define DMA_SSRT_SSRT(n) ((uint8_t)(n & 15)<<0) // Set Start Bit #define DMA_SSRT_SAST ((uint8_t)1<<6) // Set All Start Bits #define DMA_SSRT_NOP ((uint8_t)1<<7) // NOP #define DMA_CERR *(volatile uint8_t *)0x4000801E // Clear Error Register #define DMA_CERR_CERR(n) ((uint8_t)(n & 15)<<0) // Clear Error Indicator #define DMA_CERR_CAEI ((uint8_t)1<<6) // Clear All Error Indicators #define DMA_CERR_NOP ((uint8_t)1<<7) // NOP #define DMA_CINT *(volatile uint8_t *)0x4000801F // Clear Interrupt Request Register #define DMA_CINT_CINT(n) ((uint8_t)(n & 15)<<0) // Clear Interrupt Request #define DMA_CINT_CAIR ((uint8_t)1<<6) // Clear All Interrupt Requests #define DMA_CINT_NOP ((uint8_t)1<<7) // NOP #define DMA_INT *(volatile uint32_t *)0x40008024 // Interrupt Request Register #define DMA_INT_INT0 ((uint32_t)1<<0) // Interrupt Request 0 #define DMA_INT_INT1 ((uint32_t)1<<1) // Interrupt Request 1 #define DMA_INT_INT2 ((uint32_t)1<<2) // Interrupt Request 2 #define DMA_INT_INT3 ((uint32_t)1<<3) // Interrupt Request 3 #define DMA_INT_INT4 ((uint32_t)1<<4) // Interrupt Request 4 #define DMA_INT_INT5 ((uint32_t)1<<5) // Interrupt Request 5 #define DMA_INT_INT6 ((uint32_t)1<<6) // Interrupt Request 6 #define DMA_INT_INT7 ((uint32_t)1<<7) // Interrupt Request 7 #define DMA_INT_INT8 ((uint32_t)1<<8) // Interrupt Request 8 #define DMA_INT_INT9 ((uint32_t)1<<9) // Interrupt Request 9 #define DMA_INT_INT10 ((uint32_t)1<<10) // Interrupt Request 10 #define DMA_INT_INT11 ((uint32_t)1<<11) // Interrupt Request 11 #define DMA_INT_INT12 ((uint32_t)1<<12) // Interrupt Request 12 #define DMA_INT_INT13 ((uint32_t)1<<13) // Interrupt Request 13 #define DMA_INT_INT14 ((uint32_t)1<<14) // Interrupt Request 14 #define DMA_INT_INT15 ((uint32_t)1<<15) // Interrupt Request 15 #define DMA_ERR *(volatile uint32_t *)0x4000802C // Error Register #define DMA_ERR_ERR0 ((uint32_t)1<<0) // Error in Channel 0 #define DMA_ERR_ERR1 ((uint32_t)1<<1) // Error in Channel 1 #define DMA_ERR_ERR2 ((uint32_t)1<<2) // Error in Channel 2 #define DMA_ERR_ERR3 ((uint32_t)1<<3) // Error in Channel 3 #define DMA_ERR_ERR4 ((uint32_t)1<<4) // Error in Channel 4 #define DMA_ERR_ERR5 ((uint32_t)1<<5) // Error in Channel 5 #define DMA_ERR_ERR6 ((uint32_t)1<<6) // Error in Channel 6 #define DMA_ERR_ERR7 ((uint32_t)1<<7) // Error in Channel 7 #define DMA_ERR_ERR8 ((uint32_t)1<<8) // Error in Channel 8 #define DMA_ERR_ERR9 ((uint32_t)1<<9) // Error in Channel 9 #define DMA_ERR_ERR10 ((uint32_t)1<<10) // Error in Channel 10 #define DMA_ERR_ERR11 ((uint32_t)1<<11) // Error in Channel 11 #define DMA_ERR_ERR12 ((uint32_t)1<<12) // Error in Channel 12 #define DMA_ERR_ERR13 ((uint32_t)1<<13) // Error in Channel 13 #define DMA_ERR_ERR14 ((uint32_t)1<<14) // Error in Channel 14 #define DMA_ERR_ERR15 ((uint32_t)1<<15) // Error in Channel 15 #define DMA_HRS *(volatile uint32_t *)0x40008034 // Hardware Request Status Register #define DMA_HRS_HRS0 ((uint32_t)1<<0) // Hardware Request Status Channel 0 #define DMA_HRS_HRS1 ((uint32_t)1<<1) // Hardware Request Status Channel 1 #define DMA_HRS_HRS2 ((uint32_t)1<<2) // Hardware Request Status Channel 2 #define DMA_HRS_HRS3 ((uint32_t)1<<3) // Hardware Request Status Channel 3 #define DMA_HRS_HRS4 ((uint32_t)1<<4) // Hardware Request Status Channel 4 #define DMA_HRS_HRS5 ((uint32_t)1<<5) // Hardware Request Status Channel 5 #define DMA_HRS_HRS6 ((uint32_t)1<<6) // Hardware Request Status Channel 6 #define DMA_HRS_HRS7 ((uint32_t)1<<7) // Hardware Request Status Channel 7 #define DMA_HRS_HRS8 ((uint32_t)1<<8) // Hardware Request Status Channel 8 #define DMA_HRS_HRS9 ((uint32_t)1<<9) // Hardware Request Status Channel 9 #define DMA_HRS_HRS10 ((uint32_t)1<<10) // Hardware Request Status Channel 10 #define DMA_HRS_HRS11 ((uint32_t)1<<11) // Hardware Request Status Channel 11 #define DMA_HRS_HRS12 ((uint32_t)1<<12) // Hardware Request Status Channel 12 #define DMA_HRS_HRS13 ((uint32_t)1<<13) // Hardware Request Status Channel 13 #define DMA_HRS_HRS14 ((uint32_t)1<<14) // Hardware Request Status Channel 14 #define DMA_HRS_HRS15 ((uint32_t)1<<15) // Hardware Request Status Channel 15 #define DMA_DCHPRI3 *(volatile uint8_t *)0x40008100 // Channel n Priority Register #define DMA_DCHPRI2 *(volatile uint8_t *)0x40008101 // Channel n Priority Register #define DMA_DCHPRI1 *(volatile uint8_t *)0x40008102 // Channel n Priority Register #define DMA_DCHPRI0 *(volatile uint8_t *)0x40008103 // Channel n Priority Register #define DMA_DCHPRI_CHPRI(n) ((uint8_t)(n & 15)<<0) // Channel Arbitration Priority #define DMA_DCHPRI_DPA ((uint8_t)1<<6) // Disable PreEmpt Ability #define DMA_DCHPRI_ECP ((uint8_t)1<<7) // Enable PreEmption #define DMA_DCHPRI7 *(volatile uint8_t *)0x40008104 // Channel n Priority Register #define DMA_DCHPRI6 *(volatile uint8_t *)0x40008105 // Channel n Priority Register #define DMA_DCHPRI5 *(volatile uint8_t *)0x40008106 // Channel n Priority Register #define DMA_DCHPRI4 *(volatile uint8_t *)0x40008107 // Channel n Priority Register #define DMA_DCHPRI11 *(volatile uint8_t *)0x40008108 // Channel n Priority Register #define DMA_DCHPRI10 *(volatile uint8_t *)0x40008109 // Channel n Priority Register #define DMA_DCHPRI9 *(volatile uint8_t *)0x4000810A // Channel n Priority Register #define DMA_DCHPRI8 *(volatile uint8_t *)0x4000810B // Channel n Priority Register #define DMA_DCHPRI15 *(volatile uint8_t *)0x4000810C // Channel n Priority Register #define DMA_DCHPRI14 *(volatile uint8_t *)0x4000810D // Channel n Priority Register #define DMA_DCHPRI13 *(volatile uint8_t *)0x4000810E // Channel n Priority Register #define DMA_DCHPRI12 *(volatile uint8_t *)0x4000810F // Channel n Priority Register #define DMA_TCD_ATTR_SMOD(n) (((n) & 0x1F) << 11) #define DMA_TCD_ATTR_SSIZE(n) (((n) & 0x7) << 8) #define DMA_TCD_ATTR_DMOD(n) (((n) & 0x1F) << 3) #define DMA_TCD_ATTR_DSIZE(n) (((n) & 0x7) << 0) #define DMA_TCD_ATTR_SIZE_8BIT 0 #define DMA_TCD_ATTR_SIZE_16BIT 1 #define DMA_TCD_ATTR_SIZE_32BIT 2 #define DMA_TCD_ATTR_SIZE_16BYTE 4 #define DMA_TCD_ATTR_SIZE_32BYTE 5 #define DMA_TCD_CSR_BWC(n) (((n) & 0x3) << 14) #define DMA_TCD_CSR_MAJORLINKCH(n) (((n) & 0x3) << 8) #define DMA_TCD_CSR_DONE 0x0080 #define DMA_TCD_CSR_ACTIVE 0x0040 #define DMA_TCD_CSR_MAJORELINK 0x0020 #define DMA_TCD_CSR_ESG 0x0010 #define DMA_TCD_CSR_DREQ 0x0008 #define DMA_TCD_CSR_INTHALF 0x0004 #define DMA_TCD_CSR_INTMAJOR 0x0002 #define DMA_TCD_CSR_START 0x0001 #define DMA_TCD_CITER_MASK ((uint16_t)0x7FFF) // Loop count mask #define DMA_TCD_CITER_ELINK ((uint16_t)1<<15) // Enable channel linking on minor-loop complete #define DMA_TCD_BITER_MASK ((uint16_t)0x7FFF) // Loop count mask #define DMA_TCD_BITER_ELINK ((uint16_t)1<<15) // Enable channel linking on minor-loop complete #define DMA_TCD_NBYTES_SMLOE ((uint32_t)1<<31) // Source Minor Loop Offset Enable #define DMA_TCD_NBYTES_DMLOE ((uint32_t)1<<30) // Destination Minor Loop Offset Enable #define DMA_TCD_NBYTES_MLOFFNO_NBYTES(n) ((uint32_t)(n)) // NBytes transfer count when minor loop disabled #define DMA_TCD_NBYTES_MLOFFYES_NBYTES(n) ((uint32_t)(n & 0x1F)) // NBytes transfer count when minor loop enabled #define DMA_TCD_NBYTES_MLOFFYES_MLOFF(n) ((uint32_t)(n & 0xFFFFF)<<10) // Offset #define DMA_TCD0_SADDR *(volatile const void * volatile *)0x40009000 // TCD Source Address #define DMA_TCD0_SOFF *(volatile int16_t *)0x40009004 // TCD Signed Source Address Offset #define DMA_TCD0_ATTR *(volatile uint16_t *)0x40009006 // TCD Transfer Attributes #define DMA_TCD0_NBYTES_MLNO *(volatile uint32_t *)0x40009008 // TCD Minor Byte Count (Minor Loop Disabled) #define DMA_TCD0_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009008 // TCD Signed Minor Loop Offset (Minor Loop Enabled and Offset Disabled) #define DMA_TCD0_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009008 // TCD Signed Minor Loop Offset (Minor Loop and Offset Enabled) #define DMA_TCD0_SLAST *(volatile int32_t *)0x4000900C // TCD Last Source Address Adjustment #define DMA_TCD0_DADDR *(volatile void * volatile *)0x40009010 // TCD Destination Address #define DMA_TCD0_DOFF *(volatile int16_t *)0x40009014 // TCD Signed Destination Address Offset #define DMA_TCD0_CITER_ELINKYES *(volatile uint16_t *)0x40009016 // TCD Current Minor Loop Link, Major Loop Count, Channel Linking Enabled #define DMA_TCD0_CITER_ELINKNO *(volatile uint16_t *)0x40009016 // ?? #define DMA_TCD0_DLASTSGA *(volatile int32_t *)0x40009018 // TCD Last Destination Address Adjustment/Scatter Gather Address #define DMA_TCD0_CSR *(volatile uint16_t *)0x4000901C // TCD Control and Status #define DMA_TCD0_BITER_ELINKYES *(volatile uint16_t *)0x4000901E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Enabled #define DMA_TCD0_BITER_ELINKNO *(volatile uint16_t *)0x4000901E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Disabled #define DMA_TCD1_SADDR *(volatile const void * volatile *)0x40009020 // TCD Source Address #define DMA_TCD1_SOFF *(volatile int16_t *)0x40009024 // TCD Signed Source Address Offset #define DMA_TCD1_ATTR *(volatile uint16_t *)0x40009026 // TCD Transfer Attributes #define DMA_TCD1_NBYTES_MLNO *(volatile uint32_t *)0x40009028 // TCD Minor Byte Count, Minor Loop Disabled #define DMA_TCD1_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009028 // TCD Signed Minor Loop Offset, Minor Loop Enabled and Offset Disabled #define DMA_TCD1_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009028 // TCD Signed Minor Loop Offset, Minor Loop and Offset Enabled #define DMA_TCD1_SLAST *(volatile int32_t *)0x4000902C // TCD Last Source Address Adjustment #define DMA_TCD1_DADDR *(volatile void * volatile *)0x40009030 // TCD Destination Address #define DMA_TCD1_DOFF *(volatile int16_t *)0x40009034 // TCD Signed Destination Address Offset #define DMA_TCD1_CITER_ELINKYES *(volatile uint16_t *)0x40009036 // TCD Current Minor Loop Link, Major Loop Count, Channel Linking Enabled #define DMA_TCD1_CITER_ELINKNO *(volatile uint16_t *)0x40009036 // ?? #define DMA_TCD1_DLASTSGA *(volatile int32_t *)0x40009038 // TCD Last Destination Address Adjustment/Scatter Gather Address #define DMA_TCD1_CSR *(volatile uint16_t *)0x4000903C // TCD Control and Status #define DMA_TCD1_BITER_ELINKYES *(volatile uint16_t *)0x4000903E // TCD Beginning Minor Loop Link, Major Loop Count Channel Linking Enabled #define DMA_TCD1_BITER_ELINKNO *(volatile uint16_t *)0x4000903E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Disabled #define DMA_TCD2_SADDR *(volatile const void * volatile *)0x40009040 // TCD Source Address #define DMA_TCD2_SOFF *(volatile int16_t *)0x40009044 // TCD Signed Source Address Offset #define DMA_TCD2_ATTR *(volatile uint16_t *)0x40009046 // TCD Transfer Attributes #define DMA_TCD2_NBYTES_MLNO *(volatile uint32_t *)0x40009048 // TCD Minor Byte Count, Minor Loop Disabled #define DMA_TCD2_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009048 // TCD Signed Minor Loop Offset, Minor Loop Enabled and Offset Disabled #define DMA_TCD2_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009048 // TCD Signed Minor Loop Offset, Minor Loop and Offset Enabled #define DMA_TCD2_SLAST *(volatile int32_t *)0x4000904C // TCD Last Source Address Adjustment #define DMA_TCD2_DADDR *(volatile void * volatile *)0x40009050 // TCD Destination Address #define DMA_TCD2_DOFF *(volatile int16_t *)0x40009054 // TCD Signed Destination Address Offset #define DMA_TCD2_CITER_ELINKYES *(volatile uint16_t *)0x40009056 // TCD Current Minor Loop Link, Major Loop Count, Channel Linking Enabled #define DMA_TCD2_CITER_ELINKNO *(volatile uint16_t *)0x40009056 // ?? #define DMA_TCD2_DLASTSGA *(volatile int32_t *)0x40009058 // TCD Last Destination Address Adjustment/Scatter Gather Address #define DMA_TCD2_CSR *(volatile uint16_t *)0x4000905C // TCD Control and Status #define DMA_TCD2_BITER_ELINKYES *(volatile uint16_t *)0x4000905E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Enabled #define DMA_TCD2_BITER_ELINKNO *(volatile uint16_t *)0x4000905E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Disabled #define DMA_TCD3_SADDR *(volatile const void * volatile *)0x40009060 // TCD Source Address #define DMA_TCD3_SOFF *(volatile int16_t *)0x40009064 // TCD Signed Source Address Offset #define DMA_TCD3_ATTR *(volatile uint16_t *)0x40009066 // TCD Transfer Attributes #define DMA_TCD3_NBYTES_MLNO *(volatile uint32_t *)0x40009068 // TCD Minor Byte Count, Minor Loop Disabled #define DMA_TCD3_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009068 // TCD Signed Minor Loop Offset, Minor Loop Enabled and Offset Disabled #define DMA_TCD3_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009068 // TCD Signed Minor Loop Offset, Minor Loop and Offset Enabled #define DMA_TCD3_SLAST *(volatile int32_t *)0x4000906C // TCD Last Source Address Adjustment #define DMA_TCD3_DADDR *(volatile void * volatile *)0x40009070 // TCD Destination Address #define DMA_TCD3_DOFF *(volatile int16_t *)0x40009074 // TCD Signed Destination Address Offset #define DMA_TCD3_CITER_ELINKYES *(volatile uint16_t *)0x40009076 // TCD Current Minor Loop Link, Major Loop Count, Channel Linking Enabled #define DMA_TCD3_CITER_ELINKNO *(volatile uint16_t *)0x40009076 // ?? #define DMA_TCD3_DLASTSGA *(volatile int32_t *)0x40009078 // TCD Last Destination Address Adjustment/Scatter Gather Address #define DMA_TCD3_CSR *(volatile uint16_t *)0x4000907C // TCD Control and Status #define DMA_TCD3_BITER_ELINKYES *(volatile uint16_t *)0x4000907E // TCD Beginning Minor Loop Link, Major Loop Count ,Channel Linking Enabled #define DMA_TCD3_BITER_ELINKNO *(volatile uint16_t *)0x4000907E // TCD Beginning Minor Loop Link, Major Loop Count ,Channel Linking Disabled #define DMA_TCD4_SADDR *(volatile const void * volatile *)0x40009080 // TCD Source Addr #define DMA_TCD4_SOFF *(volatile int16_t *)0x40009084 // TCD Signed Source Address Offset #define DMA_TCD4_ATTR *(volatile uint16_t *)0x40009086 // TCD Transfer Attributes #define DMA_TCD4_NBYTES_MLNO *(volatile uint32_t *)0x40009088 // TCD Minor Byte Count #define DMA_TCD4_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009088 // TCD Signed Minor Loop Offset #define DMA_TCD4_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009088 // TCD Signed Minor Loop Offset #define DMA_TCD4_SLAST *(volatile int32_t *)0x4000908C // TCD Last Source Addr Adj. #define DMA_TCD4_DADDR *(volatile void * volatile *)0x40009090 // TCD Destination Address #define DMA_TCD4_DOFF *(volatile int16_t *)0x40009094 // TCD Signed Dest Address Offset #define DMA_TCD4_CITER_ELINKYES *(volatile uint16_t *)0x40009096 // TCD Current Minor Loop Link #define DMA_TCD4_CITER_ELINKNO *(volatile uint16_t *)0x40009096 // ?? #define DMA_TCD4_DLASTSGA *(volatile int32_t *)0x40009098 // TCD Last Destination Addr Adj #define DMA_TCD4_CSR *(volatile uint16_t *)0x4000909C // TCD Control and Status #define DMA_TCD4_BITER_ELINKYES *(volatile uint16_t *)0x4000909E // TCD Beginning Minor Loop Link #define DMA_TCD4_BITER_ELINKNO *(volatile uint16_t *)0x4000909E // TCD Beginning Minor Loop Link #define DMA_TCD5_SADDR *(volatile const void * volatile *)0x400090A0 // TCD Source Addr #define DMA_TCD5_SOFF *(volatile int16_t *)0x400090A4 // TCD Signed Source Address Offset #define DMA_TCD5_ATTR *(volatile uint16_t *)0x400090A6 // TCD Transfer Attributes #define DMA_TCD5_NBYTES_MLNO *(volatile uint32_t *)0x400090A8 // TCD Minor Byte Count #define DMA_TCD5_NBYTES_MLOFFNO *(volatile uint32_t *)0x400090A8 // TCD Signed Minor Loop Offset #define DMA_TCD5_NBYTES_MLOFFYES *(volatile uint32_t *)0x400090A8 // TCD Signed Minor Loop Offset #define DMA_TCD5_SLAST *(volatile int32_t *)0x400090AC // TCD Last Source Addr Adj. #define DMA_TCD5_DADDR *(volatile void * volatile *)0x400090B0 // TCD Destination Address #define DMA_TCD5_DOFF *(volatile int16_t *)0x400090B4 // TCD Signed Dest Address Offset #define DMA_TCD5_CITER_ELINKYES *(volatile uint16_t *)0x400090B6 // TCD Current Minor Loop Link #define DMA_TCD5_CITER_ELINKNO *(volatile uint16_t *)0x400090B6 // ?? #define DMA_TCD5_DLASTSGA *(volatile int32_t *)0x400090B8 // TCD Last Destination Addr Adj #define DMA_TCD5_CSR *(volatile uint16_t *)0x400090BC // TCD Control and Status #define DMA_TCD5_BITER_ELINKYES *(volatile uint16_t *)0x400090BE // TCD Beginning Minor Loop Link #define DMA_TCD5_BITER_ELINKNO *(volatile uint16_t *)0x400090BE // TCD Beginning Minor Loop Link #define DMA_TCD6_SADDR *(volatile const void * volatile *)0x400090C0 // TCD Source Addr #define DMA_TCD6_SOFF *(volatile int16_t *)0x400090C4 // TCD Signed Source Address Offset #define DMA_TCD6_ATTR *(volatile uint16_t *)0x400090C6 // TCD Transfer Attributes #define DMA_TCD6_NBYTES_MLNO *(volatile uint32_t *)0x400090C8 // TCD Minor Byte Count #define DMA_TCD6_NBYTES_MLOFFNO *(volatile uint32_t *)0x400090C8 // TCD Signed Minor Loop Offset #define DMA_TCD6_NBYTES_MLOFFYES *(volatile uint32_t *)0x400090C8 // TCD Signed Minor Loop Offset #define DMA_TCD6_SLAST *(volatile int32_t *)0x400090CC // TCD Last Source Addr Adj. #define DMA_TCD6_DADDR *(volatile void * volatile *)0x400090D0 // TCD Destination Address #define DMA_TCD6_DOFF *(volatile int16_t *)0x400090D4 // TCD Signed Dest Address Offset #define DMA_TCD6_CITER_ELINKYES *(volatile uint16_t *)0x400090D6 // TCD Current Minor Loop Link #define DMA_TCD6_CITER_ELINKNO *(volatile uint16_t *)0x400090D6 // ?? #define DMA_TCD6_DLASTSGA *(volatile int32_t *)0x400090D8 // TCD Last Destination Addr Adj #define DMA_TCD6_CSR *(volatile uint16_t *)0x400090DC // TCD Control and Status #define DMA_TCD6_BITER_ELINKYES *(volatile uint16_t *)0x400090DE // TCD Beginning Minor Loop Link #define DMA_TCD6_BITER_ELINKNO *(volatile uint16_t *)0x400090DE // TCD Beginning Minor Loop Link #define DMA_TCD7_SADDR *(volatile const void * volatile *)0x400090E0 // TCD Source Addr #define DMA_TCD7_SOFF *(volatile int16_t *)0x400090E4 // TCD Signed Source Address Offset #define DMA_TCD7_ATTR *(volatile uint16_t *)0x400090E6 // TCD Transfer Attributes #define DMA_TCD7_NBYTES_MLNO *(volatile uint32_t *)0x400090E8 // TCD Minor Byte Count #define DMA_TCD7_NBYTES_MLOFFNO *(volatile uint32_t *)0x400090E8 // TCD Signed Minor Loop Offset #define DMA_TCD7_NBYTES_MLOFFYES *(volatile uint32_t *)0x400090E8 // TCD Signed Minor Loop Offset #define DMA_TCD7_SLAST *(volatile int32_t *)0x400090EC // TCD Last Source Addr Adj. #define DMA_TCD7_DADDR *(volatile void * volatile *)0x400090F0 // TCD Destination Address #define DMA_TCD7_DOFF *(volatile int16_t *)0x400090F4 // TCD Signed Dest Address Offset #define DMA_TCD7_CITER_ELINKYES *(volatile uint16_t *)0x400090F6 // TCD Current Minor Loop Link #define DMA_TCD7_CITER_ELINKNO *(volatile uint16_t *)0x400090F6 // ?? #define DMA_TCD7_DLASTSGA *(volatile int32_t *)0x400090F8 // TCD Last Destination Addr Adj #define DMA_TCD7_CSR *(volatile uint16_t *)0x400090FC // TCD Control and Status #define DMA_TCD7_BITER_ELINKYES *(volatile uint16_t *)0x400090FE // TCD Beginning Minor Loop Link #define DMA_TCD7_BITER_ELINKNO *(volatile uint16_t *)0x400090FE // TCD Beginning Minor Loop Link #define DMA_TCD8_SADDR *(volatile const void * volatile *)0x40009100 // TCD Source Addr #define DMA_TCD8_SOFF *(volatile int16_t *)0x40009104 // TCD Signed Source Address Offset #define DMA_TCD8_ATTR *(volatile uint16_t *)0x40009106 // TCD Transfer Attributes #define DMA_TCD8_NBYTES_MLNO *(volatile uint32_t *)0x40009108 // TCD Minor Byte Count #define DMA_TCD8_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009108 // TCD Signed Minor Loop Offset #define DMA_TCD8_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009108 // TCD Signed Minor Loop Offset #define DMA_TCD8_SLAST *(volatile int32_t *)0x4000910C // TCD Last Source Addr Adj. #define DMA_TCD8_DADDR *(volatile void * volatile *)0x40009110 // TCD Destination Address #define DMA_TCD8_DOFF *(volatile int16_t *)0x40009114 // TCD Signed Dest Address Offset #define DMA_TCD8_CITER_ELINKYES *(volatile uint16_t *)0x40009116 // TCD Current Minor Loop Link #define DMA_TCD8_CITER_ELINKNO *(volatile uint16_t *)0x40009116 // ?? #define DMA_TCD8_DLASTSGA *(volatile int32_t *)0x40009118 // TCD Last Destination Addr Adj #define DMA_TCD8_CSR *(volatile uint16_t *)0x4000911C // TCD Control and Status #define DMA_TCD8_BITER_ELINKYES *(volatile uint16_t *)0x4000911E // TCD Beginning Minor Loop Link #define DMA_TCD8_BITER_ELINKNO *(volatile uint16_t *)0x4000911E // TCD Beginning Minor Loop Link #define DMA_TCD9_SADDR *(volatile const void * volatile *)0x40009120 // TCD Source Addr #define DMA_TCD9_SOFF *(volatile int16_t *)0x40009124 // TCD Signed Source Address Offset #define DMA_TCD9_ATTR *(volatile uint16_t *)0x40009126 // TCD Transfer Attributes #define DMA_TCD9_NBYTES_MLNO *(volatile uint32_t *)0x40009128 // TCD Minor Byte Count #define DMA_TCD9_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009128 // TCD Signed Minor Loop Offset #define DMA_TCD9_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009128 // TCD Signed Minor Loop Offset #define DMA_TCD9_SLAST *(volatile int32_t *)0x4000912C // TCD Last Source Addr Adj. #define DMA_TCD9_DADDR *(volatile void * volatile *)0x40009130 // TCD Destination Address #define DMA_TCD9_DOFF *(volatile int16_t *)0x40009134 // TCD Signed Dest Address Offset #define DMA_TCD9_CITER_ELINKYES *(volatile uint16_t *)0x40009136 // TCD Current Minor Loop Link #define DMA_TCD9_CITER_ELINKNO *(volatile uint16_t *)0x40009136 // ?? #define DMA_TCD9_DLASTSGA *(volatile int32_t *)0x40009138 // TCD Last Destination Addr Adj #define DMA_TCD9_CSR *(volatile uint16_t *)0x4000913C // TCD Control and Status #define DMA_TCD9_BITER_ELINKYES *(volatile uint16_t *)0x4000913E // TCD Beginning Minor Loop Link #define DMA_TCD9_BITER_ELINKNO *(volatile uint16_t *)0x4000913E // TCD Beginning Minor Loop Link #define DMA_TCD10_SADDR *(volatile const void * volatile *)0x40009140 // TCD Source Addr #define DMA_TCD10_SOFF *(volatile int16_t *)0x40009144 // TCD Signed Source Address Offset #define DMA_TCD10_ATTR *(volatile uint16_t *)0x40009146 // TCD Transfer Attributes #define DMA_TCD10_NBYTES_MLNO *(volatile uint32_t *)0x40009148 // TCD Minor Byte Count #define DMA_TCD10_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009148 // TCD Signed Minor Loop Offset #define DMA_TCD10_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009148 // TCD Signed Minor Loop Offset #define DMA_TCD10_SLAST *(volatile int32_t *)0x4000914C // TCD Last Source Addr Adj. #define DMA_TCD10_DADDR *(volatile void * volatile *)0x40009150 // TCD Destination Address #define DMA_TCD10_DOFF *(volatile int16_t *)0x40009154 // TCD Signed Dest Address Offset #define DMA_TCD10_CITER_ELINKYES *(volatile uint16_t *)0x40009156 // TCD Current Minor Loop Link #define DMA_TCD10_CITER_ELINKNO *(volatile uint16_t *)0x40009156 // ?? #define DMA_TCD10_DLASTSGA *(volatile int32_t *)0x40009158 // TCD Last Destination Addr Adj #define DMA_TCD10_CSR *(volatile uint16_t *)0x4000915C // TCD Control and Status #define DMA_TCD10_BITER_ELINKYES *(volatile uint16_t *)0x4000915E // TCD Beginning Minor Loop Link #define DMA_TCD10_BITER_ELINKNO *(volatile uint16_t *)0x4000915E // TCD Beginning Minor Loop Link #define DMA_TCD11_SADDR *(volatile const void * volatile *)0x40009160 // TCD Source Addr #define DMA_TCD11_SOFF *(volatile int16_t *)0x40009164 // TCD Signed Source Address Offset #define DMA_TCD11_ATTR *(volatile uint16_t *)0x40009166 // TCD Transfer Attributes #define DMA_TCD11_NBYTES_MLNO *(volatile uint32_t *)0x40009168 // TCD Minor Byte Count #define DMA_TCD11_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009168 // TCD Signed Minor Loop Offset #define DMA_TCD11_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009168 // TCD Signed Minor Loop Offset #define DMA_TCD11_SLAST *(volatile int32_t *)0x4000916C // TCD Last Source Addr Adj. #define DMA_TCD11_DADDR *(volatile void * volatile *)0x40009170 // TCD Destination Address #define DMA_TCD11_DOFF *(volatile int16_t *)0x40009174 // TCD Signed Dest Address Offset #define DMA_TCD11_CITER_ELINKYES *(volatile uint16_t *)0x40009176 // TCD Current Minor Loop Link #define DMA_TCD11_CITER_ELINKNO *(volatile uint16_t *)0x40009176 // ?? #define DMA_TCD11_DLASTSGA *(volatile int32_t *)0x40009178 // TCD Last Destination Addr Adj #define DMA_TCD11_CSR *(volatile uint16_t *)0x4000917C // TCD Control and Status #define DMA_TCD11_BITER_ELINKYES *(volatile uint16_t *)0x4000917E // TCD Beginning Minor Loop Link #define DMA_TCD11_BITER_ELINKNO *(volatile uint16_t *)0x4000917E // TCD Beginning Minor Loop Link #define DMA_TCD12_SADDR *(volatile const void * volatile *)0x40009180 // TCD Source Addr #define DMA_TCD12_SOFF *(volatile int16_t *)0x40009184 // TCD Signed Source Address Offset #define DMA_TCD12_ATTR *(volatile uint16_t *)0x40009186 // TCD Transfer Attributes #define DMA_TCD12_NBYTES_MLNO *(volatile uint32_t *)0x40009188 // TCD Minor Byte Count #define DMA_TCD12_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009188 // TCD Signed Minor Loop Offset #define DMA_TCD12_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009188 // TCD Signed Minor Loop Offset #define DMA_TCD12_SLAST *(volatile int32_t *)0x4000918C // TCD Last Source Addr Adj. #define DMA_TCD12_DADDR *(volatile void * volatile *)0x40009190 // TCD Destination Address #define DMA_TCD12_DOFF *(volatile int16_t *)0x40009194 // TCD Signed Dest Address Offset #define DMA_TCD12_CITER_ELINKYES *(volatile uint16_t *)0x40009196 // TCD Current Minor Loop Link #define DMA_TCD12_CITER_ELINKNO *(volatile uint16_t *)0x40009196 // ?? #define DMA_TCD12_DLASTSGA *(volatile int32_t *)0x40009198 // TCD Last Destination Addr Adj #define DMA_TCD12_CSR *(volatile uint16_t *)0x4000919C // TCD Control and Status #define DMA_TCD12_BITER_ELINKYES *(volatile uint16_t *)0x4000919E // TCD Beginning Minor Loop Link #define DMA_TCD12_BITER_ELINKNO *(volatile uint16_t *)0x4000919E // TCD Beginning Minor Loop Link #define DMA_TCD13_SADDR *(volatile const void * volatile *)0x400091A0 // TCD Source Addr #define DMA_TCD13_SOFF *(volatile int16_t *)0x400091A4 // TCD Signed Source Address Offset #define DMA_TCD13_ATTR *(volatile uint16_t *)0x400091A6 // TCD Transfer Attributes #define DMA_TCD13_NBYTES_MLNO *(volatile uint32_t *)0x400091A8 // TCD Minor Byte Count #define DMA_TCD13_NBYTES_MLOFFNO *(volatile uint32_t *)0x400091A8 // TCD Signed Minor Loop Offset #define DMA_TCD13_NBYTES_MLOFFYES *(volatile uint32_t *)0x400091A8 // TCD Signed Minor Loop Offset #define DMA_TCD13_SLAST *(volatile int32_t *)0x400091AC // TCD Last Source Addr Adj. #define DMA_TCD13_DADDR *(volatile void * volatile *)0x400091B0 // TCD Destination Address #define DMA_TCD13_DOFF *(volatile int16_t *)0x400091B4 // TCD Signed Dest Address Offset #define DMA_TCD13_CITER_ELINKYES *(volatile uint16_t *)0x400091B6 // TCD Current Minor Loop Link #define DMA_TCD13_CITER_ELINKNO *(volatile uint16_t *)0x400091B6 // ?? #define DMA_TCD13_DLASTSGA *(volatile int32_t *)0x400091B8 // TCD Last Destination Addr Adj #define DMA_TCD13_CSR *(volatile uint16_t *)0x400091BC // TCD Control and Status #define DMA_TCD13_BITER_ELINKYES *(volatile uint16_t *)0x400091BE // TCD Beginning Minor Loop Link #define DMA_TCD13_BITER_ELINKNO *(volatile uint16_t *)0x400091BE // TCD Beginning Minor Loop Link #define DMA_TCD14_SADDR *(volatile const void * volatile *)0x400091C0 // TCD Source Addr #define DMA_TCD14_SOFF *(volatile int16_t *)0x400091C4 // TCD Signed Source Address Offset #define DMA_TCD14_ATTR *(volatile uint16_t *)0x400091C6 // TCD Transfer Attributes #define DMA_TCD14_NBYTES_MLNO *(volatile uint32_t *)0x400091C8 // TCD Minor Byte Count #define DMA_TCD14_NBYTES_MLOFFNO *(volatile uint32_t *)0x400091C8 // TCD Signed Minor Loop Offset #define DMA_TCD14_NBYTES_MLOFFYES *(volatile uint32_t *)0x400091C8 // TCD Signed Minor Loop Offset #define DMA_TCD14_SLAST *(volatile int32_t *)0x400091CC // TCD Last Source Addr Adj. #define DMA_TCD14_DADDR *(volatile void * volatile *)0x400091D0 // TCD Destination Address #define DMA_TCD14_DOFF *(volatile int16_t *)0x400091D4 // TCD Signed Dest Address Offset #define DMA_TCD14_CITER_ELINKYES *(volatile uint16_t *)0x400091D6 // TCD Current Minor Loop Link #define DMA_TCD14_CITER_ELINKNO *(volatile uint16_t *)0x400091D6 // ?? #define DMA_TCD14_DLASTSGA *(volatile int32_t *)0x400091D8 // TCD Last Destination Addr Adj #define DMA_TCD14_CSR *(volatile uint16_t *)0x400091DC // TCD Control and Status #define DMA_TCD14_BITER_ELINKYES *(volatile uint16_t *)0x400091DE // TCD Beginning Minor Loop Link #define DMA_TCD14_BITER_ELINKNO *(volatile uint16_t *)0x400091DE // TCD Beginning Minor Loop Link #define DMA_TCD15_SADDR *(volatile const void * volatile *)0x400091E0 // TCD Source Addr #define DMA_TCD15_SOFF *(volatile int16_t *)0x400091E4 // TCD Signed Source Address Offset #define DMA_TCD15_ATTR *(volatile uint16_t *)0x400091E6 // TCD Transfer Attributes #define DMA_TCD15_NBYTES_MLNO *(volatile uint32_t *)0x400091E8 // TCD Minor Byte Count #define DMA_TCD15_NBYTES_MLOFFNO *(volatile uint32_t *)0x400091E8 // TCD Signed Minor Loop Offset #define DMA_TCD15_NBYTES_MLOFFYES *(volatile uint32_t *)0x400091E8 // TCD Signed Minor Loop Offset #define DMA_TCD15_SLAST *(volatile int32_t *)0x400091EC // TCD Last Source Addr Adj. #define DMA_TCD15_DADDR *(volatile void * volatile *)0x400091F0 // TCD Destination Address #define DMA_TCD15_DOFF *(volatile int16_t *)0x400091F4 // TCD Signed Dest Address Offset #define DMA_TCD15_CITER_ELINKYES *(volatile uint16_t *)0x400091F6 // TCD Current Minor Loop Link #define DMA_TCD15_CITER_ELINKNO *(volatile uint16_t *)0x400091F6 // ?? #define DMA_TCD15_DLASTSGA *(volatile int32_t *)0x400091F8 // TCD Last Destination Addr Adj #define DMA_TCD15_CSR *(volatile uint16_t *)0x400091FC // TCD Control and Status #define DMA_TCD15_BITER_ELINKYES *(volatile uint16_t *)0x400091FE // TCD Beginning Minor Loop Link #define DMA_TCD15_BITER_ELINKNO *(volatile uint16_t *)0x400091FE // TCD Beginning Minor Loop Link // Chapter 22: External Watchdog Monitor (EWM) #define EWM_CTRL *(volatile uint8_t *)0x40061000 // Control Register #define EWM_SERV *(volatile uint8_t *)0x40061001 // Service Register #define EWM_CMPL *(volatile uint8_t *)0x40061002 // Compare Low Register #define EWM_CMPH *(volatile uint8_t *)0x40061003 // Compare High Register // Chapter 23: Watchdog Timer (WDOG) #define WDOG_STCTRLH *(volatile uint16_t *)0x40052000 // Watchdog Status and Control Register High #define WDOG_STCTRLH_DISTESTWDOG (uint16_t)0x4000 // Allows the WDOG's functional test mode to be disabled permanently. #define WDOG_STCTRLH_BYTESEL(n) (uint16_t)(((n) & 3) << 12) // selects the byte to be tested when the watchdog is in the byte test mode. #define WDOG_STCTRLH_TESTSEL (uint16_t)0x0800 #define WDOG_STCTRLH_TESTWDOG (uint16_t)0x0400 #define WDOG_STCTRLH_WAITEN (uint16_t)0x0080 #define WDOG_STCTRLH_STOPEN (uint16_t)0x0040 #define WDOG_STCTRLH_DBGEN (uint16_t)0x0020 #define WDOG_STCTRLH_ALLOWUPDATE (uint16_t)0x0010 #define WDOG_STCTRLH_WINEN (uint16_t)0x0008 #define WDOG_STCTRLH_IRQRSTEN (uint16_t)0x0004 #define WDOG_STCTRLH_CLKSRC (uint16_t)0x0002 #define WDOG_STCTRLH_WDOGEN (uint16_t)0x0001 #define WDOG_STCTRLL *(volatile uint16_t *)0x40052002 // Watchdog Status and Control Register Low #define WDOG_TOVALH *(volatile uint16_t *)0x40052004 // Watchdog Time-out Value Register High #define WDOG_TOVALL *(volatile uint16_t *)0x40052006 // Watchdog Time-out Value Register Low #define WDOG_WINH *(volatile uint16_t *)0x40052008 // Watchdog Window Register High #define WDOG_WINL *(volatile uint16_t *)0x4005200A // Watchdog Window Register Low #define WDOG_REFRESH *(volatile uint16_t *)0x4005200C // Watchdog Refresh register #define WDOG_UNLOCK *(volatile uint16_t *)0x4005200E // Watchdog Unlock register #define WDOG_UNLOCK_SEQ1 (uint16_t)0xC520 #define WDOG_UNLOCK_SEQ2 (uint16_t)0xD928 #define WDOG_TMROUTH *(volatile uint16_t *)0x40052010 // Watchdog Timer Output Register High #define WDOG_TMROUTL *(volatile uint16_t *)0x40052012 // Watchdog Timer Output Register Low #define WDOG_RSTCNT *(volatile uint16_t *)0x40052014 // Watchdog Reset Count register #define WDOG_PRESC *(volatile uint16_t *)0x40052016 // Watchdog Prescaler register // Chapter 24: Multipurpose Clock Generator (MCG) #define MCG_C1 *(volatile uint8_t *)0x40064000 // MCG Control 1 Register #define MCG_C1_IREFSTEN (uint8_t)0x01 // Internal Reference Stop Enable, Controls whether or not the internal reference clock remains enabled when the MCG enters Stop mode. #define MCG_C1_IRCLKEN (uint8_t)0x02 // Internal Reference Clock Enable, Enables the internal reference clock for use as MCGIRCLK. #define MCG_C1_IREFS (uint8_t)0x04 // Internal Reference Select, Selects the reference clock source for the FLL. #define MCG_C1_FRDIV(n) (uint8_t)(((n) & 0x07) << 3) // FLL External Reference Divider, Selects the amount to divide down the external reference clock for the FLL #define MCG_C1_CLKS(n) (uint8_t)(((n) & 0x03) << 6) // Clock Source Select, Selects the clock source for MCGOUTCLK #define MCG_C2 *(volatile uint8_t *)0x40064001 // MCG Control 2 Register #define MCG_C2_IRCS (uint8_t)0x01 // Internal Reference Clock Select, Selects between the fast or slow internal reference clock source. #define MCG_C2_LP (uint8_t)0x02 // Low Power Select, Controls whether the FLL or PLL is disabled in BLPI and BLPE modes. #define MCG_C2_EREFS (uint8_t)0x04 // External Reference Select, Selects the source for the external reference clock. #define MCG_C2_HGO0 (uint8_t)0x08 // High Gain Oscillator Select, Controls the crystal oscillator mode of operation #define MCG_C2_RANGE0(n) (uint8_t)(((n) & 0x03) << 4) // Frequency Range Select, Selects the frequency range for the crystal oscillator #define MCG_C2_LOCRE0 (uint8_t)0x80 // Loss of Clock Reset Enable, Determines whether an interrupt or a reset request is made following a loss of OSC0 #define MCG_C3 *(volatile uint8_t *)0x40064002 // MCG Control 3 Register #define MCG_C3_SCTRIM(n) (uint8_t)(n) // Slow Internal Reference Clock Trim Setting #define MCG_C4 *(volatile uint8_t *)0x40064003 // MCG Control 4 Register #define MCG_C4_SCFTRIM (uint8_t)0x01 // Slow Internal Reference Clock Fine Trim #define MCG_C4_FCTRIM(n) (uint8_t)(((n) & 0x0F) << 1) // Fast Internal Reference Clock Trim Setting #define MCG_C4_DRST_DRS(n) (uint8_t)(((n) & 0x03) << 5) // DCO Range Select #define MCG_C4_DMX32 (uint8_t)0x80 // DCO Maximum Frequency with 32.768 kHz Reference, controls whether the DCO frequency range is narrowed #define MCG_C5 *(volatile uint8_t *)0x40064004 // MCG Control 5 Register #define MCG_C5_PRDIV0(n) (uint8_t)((n) & 0x1F) // PLL External Reference Divider #define MCG_C5_PLLSTEN0 (uint8_t)0x20 // PLL Stop Enable #define MCG_C5_PLLCLKEN0 (uint8_t)0x40 // PLL Clock Enable #define MCG_C6 *(volatile uint8_t *)0x40064005 // MCG Control 6 Register #define MCG_C6_VDIV0(n) (uint8_t)((n) & 0x1F) // VCO 0 Divider #define MCG_C6_CME0 (uint8_t)0x20 // Clock Monitor Enable #define MCG_C6_PLLS (uint8_t)0x40 // PLL Select, Controls whether the PLL or FLL output is selected as the MCG source when CLKS[1:0]=00. #define MCG_C6_LOLIE0 (uint8_t)0x80 // Loss of Lock Interrrupt Enable #define MCG_S *(volatile uint8_t *)0x40064006 // MCG Status Register #define MCG_S_IRCST (uint8_t)0x01 // Internal Reference Clock Status #define MCG_S_OSCINIT0 (uint8_t)0x02 // OSC Initialization, resets to 0, is set to 1 after the initialization cycles of the crystal oscillator #define MCG_S_CLKST(n) (uint8_t)(((n) & 0x03) << 2) // Clock Mode Status, 0=FLL is selected, 1= Internal ref, 2=External ref, 3=PLL #define MCG_S_CLKST_MASK (uint8_t)0x0C #define MCG_S_IREFST (uint8_t)0x10 // Internal Reference Status #define MCG_S_PLLST (uint8_t)0x20 // PLL Select Status #define MCG_S_LOCK0 (uint8_t)0x40 // Lock Status, 0=PLL Unlocked, 1=PLL Locked #define MCG_S_LOLS0 (uint8_t)0x80 // Loss of Lock Status #define MCG_SC *(volatile uint8_t *)0x40064008 // MCG Status and Control Register #define MCG_SC_LOCS0 (uint8_t)0x01 // OSC0 Loss of Clock Status #define MCG_SC_FCRDIV(n) (uint8_t)(((n) & 0x07) << 1) // Fast Clock Internal Reference Divider #define MCG_SC_FLTPRSRV (uint8_t)0x10 // FLL Filter Preserve Enable #define MCG_SC_ATMF (uint8_t)0x20 // Automatic Trim Machine Fail Flag #define MCG_SC_ATMS (uint8_t)0x40 // Automatic Trim Machine Select #define MCG_SC_ATME (uint8_t)0x80 // Automatic Trim Machine Enable #define MCG_ATCVH *(volatile uint8_t *)0x4006400A // MCG Auto Trim Compare Value High Register #define MCG_ATCVL *(volatile uint8_t *)0x4006400B // MCG Auto Trim Compare Value Low Register #define MCG_C7 *(volatile uint8_t *)0x4006400C // MCG Control 7 Register #define MCG_C8 *(volatile uint8_t *)0x4006400D // MCG Control 8 Register // Chapter 25: Oscillator (OSC) #define OSC0_CR *(volatile uint8_t *)0x40065000 // OSC Control Register #define OSC_SC16P (uint8_t)0x01 // Oscillator 16 pF Capacitor Load Configure #define OSC_SC8P (uint8_t)0x02 // Oscillator 8 pF Capacitor Load Configure #define OSC_SC4P (uint8_t)0x04 // Oscillator 4 pF Capacitor Load Configure #define OSC_SC2P (uint8_t)0x08 // Oscillator 2 pF Capacitor Load Configure #define OSC_EREFSTEN (uint8_t)0x20 // External Reference Stop Enable, Controls whether or not the external reference clock (OSCERCLK) remains enabled when MCU enters Stop mode. #define OSC_ERCLKEN (uint8_t)0x80 // External Reference Enable, Enables external reference clock (OSCERCLK). // Chapter 27: Flash Memory Controller (FMC) #define FMC_PFAPR *(volatile uint32_t *)0x4001F000 // Flash Access Protection #define FMC_PFB0CR *(volatile uint32_t *)0x4001F004 // Flash Control #define FMC_TAGVDW0S0 *(volatile uint32_t *)0x4001F100 // Cache Tag Storage #define FMC_TAGVDW0S1 *(volatile uint32_t *)0x4001F104 // Cache Tag Storage #define FMC_TAGVDW1S0 *(volatile uint32_t *)0x4001F108 // Cache Tag Storage #define FMC_TAGVDW1S1 *(volatile uint32_t *)0x4001F10C // Cache Tag Storage #define FMC_TAGVDW2S0 *(volatile uint32_t *)0x4001F110 // Cache Tag Storage #define FMC_TAGVDW2S1 *(volatile uint32_t *)0x4001F114 // Cache Tag Storage #define FMC_TAGVDW3S0 *(volatile uint32_t *)0x4001F118 // Cache Tag Storage #define FMC_TAGVDW3S1 *(volatile uint32_t *)0x4001F11C // Cache Tag Storage #define FMC_DATAW0S0 *(volatile uint32_t *)0x4001F200 // Cache Data Storage #define FMC_DATAW0S1 *(volatile uint32_t *)0x4001F204 // Cache Data Storage #define FMC_DATAW1S0 *(volatile uint32_t *)0x4001F208 // Cache Data Storage #define FMC_DATAW1S1 *(volatile uint32_t *)0x4001F20C // Cache Data Storage #define FMC_DATAW2S0 *(volatile uint32_t *)0x4001F210 // Cache Data Storage #define FMC_DATAW2S1 *(volatile uint32_t *)0x4001F214 // Cache Data Storage #define FMC_DATAW3S0 *(volatile uint32_t *)0x4001F218 // Cache Data Storage #define FMC_DATAW3S1 *(volatile uint32_t *)0x4001F21C // Cache Data Storage // Chapter 28: Flash Memory Module (FTFL) #define FTFL_FSTAT *(volatile uint8_t *)0x40020000 // Flash Status Register #define FTFL_FSTAT_CCIF (uint8_t)0x80 // Command Complete Interrupt Flag #define FTFL_FSTAT_RDCOLERR (uint8_t)0x40 // Flash Read Collision Error Flag #define FTFL_FSTAT_ACCERR (uint8_t)0x20 // Flash Access Error Flag #define FTFL_FSTAT_FPVIOL (uint8_t)0x10 // Flash Protection Violation Flag #define FTFL_FSTAT_MGSTAT0 (uint8_t)0x01 // Memory Controller Command Completion Status Flag #define FTFL_FCNFG *(volatile uint8_t *)0x40020001 // Flash Configuration Register #define FTFL_FCNFG_CCIE (uint8_t)0x80 // Command Complete Interrupt Enable #define FTFL_FCNFG_RDCOLLIE (uint8_t)0x40 // Read Collision Error Interrupt Enable #define FTFL_FCNFG_ERSAREQ (uint8_t)0x20 // Erase All Request #define FTFL_FCNFG_ERSSUSP (uint8_t)0x10 // Erase Suspend #define FTFL_FCNFG_PFLSH (uint8_t)0x04 // Flash memory configuration #define FTFL_FCNFG_RAMRDY (uint8_t)0x02 // RAM Ready #define FTFL_FCNFG_EEERDY (uint8_t)0x01 // EEPROM Ready #define FTFL_FSEC *(const uint8_t *)0x40020002 // Flash Security Register #define FTFL_FOPT *(const uint8_t *)0x40020003 // Flash Option Register #define FTFL_FCCOB3 *(volatile uint8_t *)0x40020004 // Flash Common Command Object Registers #define FTFL_FCCOB2 *(volatile uint8_t *)0x40020005 #define FTFL_FCCOB1 *(volatile uint8_t *)0x40020006 #define FTFL_FCCOB0 *(volatile uint8_t *)0x40020007 #define FTFL_FCCOB7 *(volatile uint8_t *)0x40020008 #define FTFL_FCCOB6 *(volatile uint8_t *)0x40020009 #define FTFL_FCCOB5 *(volatile uint8_t *)0x4002000A #define FTFL_FCCOB4 *(volatile uint8_t *)0x4002000B #define FTFL_FCCOBB *(volatile uint8_t *)0x4002000C #define FTFL_FCCOBA *(volatile uint8_t *)0x4002000D #define FTFL_FCCOB9 *(volatile uint8_t *)0x4002000E #define FTFL_FCCOB8 *(volatile uint8_t *)0x4002000F #define FTFL_FPROT3 *(volatile uint8_t *)0x40020010 // Program Flash Protection Registers #define FTFL_FPROT2 *(volatile uint8_t *)0x40020011 // Program Flash Protection Registers #define FTFL_FPROT1 *(volatile uint8_t *)0x40020012 // Program Flash Protection Registers #define FTFL_FPROT0 *(volatile uint8_t *)0x40020013 // Program Flash Protection Registers #define FTFL_FEPROT *(volatile uint8_t *)0x40020016 // EEPROM Protection Register #define FTFL_FDPROT *(volatile uint8_t *)0x40020017 // Data Flash Protection Register // Chapter 30: Cyclic Redundancy Check (CRC) #define CRC_CRC *(volatile uint32_t *)0x40032000 // CRC Data register #define CRC_GPOLY *(volatile uint32_t *)0x40032004 // CRC Polynomial register #define CRC_CTRL *(volatile uint32_t *)0x40032008 // CRC Control register // Chapter 31: Analog-to-Digital Converter (ADC) #define ADC0_SC1A *(volatile uint32_t *)0x4003B000 // ADC status and control registers 1 #define ADC0_SC1B *(volatile uint32_t *)0x4003B004 // ADC status and control registers 1 #define ADC_SC1_COCO (uint32_t)0x80 // Conversion complete flag #define ADC_SC1_AIEN (uint32_t)0x40 // Interrupt enable #define ADC_SC1_DIFF (uint32_t)0x20 // Differential mode enable #define ADC_SC1_ADCH(n) (uint32_t)((n) & 0x1F) // Input channel select #define ADC0_CFG1 *(volatile uint32_t *)0x4003B008 // ADC configuration register 1 #define ADC_CFG1_ADLPC (uint32_t)0x80 // Low-power configuration #define ADC_CFG1_ADIV(n) (uint32_t)(((n) & 3) << 5) // Clock divide select, 0=direct, 1=div2, 2=div4, 3=div8 #define ADC_CFG1_ADLSMP (uint32_t)0x10 // Sample time configuration, 0=Short, 1=Long #define ADC_CFG1_MODE(n) (uint32_t)(((n) & 3) << 2) // Conversion mode, 0=8 bit, 1=12 bit, 2=10 bit, 3=16 bit #define ADC_CFG1_ADICLK(n) (uint32_t)(((n) & 3) << 0) // Input clock, 0=bus, 1=bus/2, 2=OSCERCLK, 3=async #define ADC0_CFG2 *(volatile uint32_t *)0x4003B00C // Configuration register 2 #define ADC_CFG2_MUXSEL (uint32_t)0x10 // 0=a channels, 1=b channels #define ADC_CFG2_ADACKEN (uint32_t)0x08 // async clock enable #define ADC_CFG2_ADHSC (uint32_t)0x04 // High speed configuration #define ADC_CFG2_ADLSTS(n) (uint32_t)(((n) & 3) << 0) // Sample time, 0=24 cycles, 1=12 cycles, 2=6 cycles, 3=2 cycles #define ADC0_RA *(volatile uint32_t *)0x4003B010 // ADC data result register #define ADC0_RB *(volatile uint32_t *)0x4003B014 // ADC data result register #define ADC0_CV1 *(volatile uint32_t *)0x4003B018 // Compare value registers #define ADC0_CV2 *(volatile uint32_t *)0x4003B01C // Compare value registers #define ADC0_SC2 *(volatile uint32_t *)0x4003B020 // Status and control register 2 #define ADC_SC2_ADACT (uint32_t)0x80 // Conversion active #define ADC_SC2_ADTRG (uint32_t)0x40 // Conversion trigger select, 0=software, 1=hardware #define ADC_SC2_ACFE (uint32_t)0x20 // Compare function enable #define ADC_SC2_ACFGT (uint32_t)0x10 // Compare function greater than enable #define ADC_SC2_ACREN (uint32_t)0x08 // Compare function range enable #define ADC_SC2_DMAEN (uint32_t)0x04 // DMA enable #define ADC_SC2_REFSEL(n) (uint32_t)(((n) & 3) << 0) // Voltage reference, 0=vcc/external, 1=1.2 volts #define ADC0_SC3 *(volatile uint32_t *)0x4003B024 // Status and control register 3 #define ADC_SC3_CAL (uint32_t)0x80 // Calibration, 1=begin, stays set while cal in progress #define ADC_SC3_CALF (uint32_t)0x40 // Calibration failed flag #define ADC_SC3_ADCO (uint32_t)0x08 // Continuous conversion enable #define ADC_SC3_AVGE (uint32_t)0x04 // Hardware average enable #define ADC_SC3_AVGS(n) (uint32_t)(((n) & 3) << 0) // avg select, 0=4 samples, 1=8 samples, 2=16 samples, 3=32 samples #define ADC0_OFS *(volatile uint32_t *)0x4003B028 // ADC offset correction register #define ADC0_PG *(volatile uint32_t *)0x4003B02C // ADC plus-side gain register #define ADC0_MG *(volatile uint32_t *)0x4003B030 // ADC minus-side gain register #define ADC0_CLPD *(volatile uint32_t *)0x4003B034 // ADC plus-side general calibration value register #define ADC0_CLPS *(volatile uint32_t *)0x4003B038 // ADC plus-side general calibration value register #define ADC0_CLP4 *(volatile uint32_t *)0x4003B03C // ADC plus-side general calibration value register #define ADC0_CLP3 *(volatile uint32_t *)0x4003B040 // ADC plus-side general calibration value register #define ADC0_CLP2 *(volatile uint32_t *)0x4003B044 // ADC plus-side general calibration value register #define ADC0_CLP1 *(volatile uint32_t *)0x4003B048 // ADC plus-side general calibration value register #define ADC0_CLP0 *(volatile uint32_t *)0x4003B04C // ADC plus-side general calibration value register #define ADC0_PGA *(volatile uint32_t *)0x4003B050 // ADC Programmable Gain Amplifier #define ADC_PGA_PGAEN (uint32_t)0x00800000 // Enable #define ADC_PGA_PGALPB (uint32_t)0x00100000 // Low-Power Mode Control, 0=low power, 1=normal #define ADC_PGA_PGAG(n) (uint32_t)(((n) & 15) << 16) // Gain, 0=1X, 1=2X, 2=4X, 3=8X, 4=16X, 5=32X, 6=64X #define ADC0_CLMD *(volatile uint32_t *)0x4003B054 // ADC minus-side general calibration value register #define ADC0_CLMS *(volatile uint32_t *)0x4003B058 // ADC minus-side general calibration value register #define ADC0_CLM4 *(volatile uint32_t *)0x4003B05C // ADC minus-side general calibration value register #define ADC0_CLM3 *(volatile uint32_t *)0x4003B060 // ADC minus-side general calibration value register #define ADC0_CLM2 *(volatile uint32_t *)0x4003B064 // ADC minus-side general calibration value register #define ADC0_CLM1 *(volatile uint32_t *)0x4003B068 // ADC minus-side general calibration value register #define ADC0_CLM0 *(volatile uint32_t *)0x4003B06C // ADC minus-side general calibration value register #define ADC1_SC1A *(volatile uint32_t *)0x400BB000 // ADC status and control registers 1 #define ADC1_SC1B *(volatile uint32_t *)0x400BB004 // ADC status and control registers 1 #define ADC1_CFG1 *(volatile uint32_t *)0x400BB008 // ADC configuration register 1 #define ADC1_CFG2 *(volatile uint32_t *)0x400BB00C // Configuration register 2 #define ADC1_RA *(volatile uint32_t *)0x400BB010 // ADC data result register #define ADC1_RB *(volatile uint32_t *)0x400BB014 // ADC data result register #define ADC1_CV1 *(volatile uint32_t *)0x400BB018 // Compare value registers #define ADC1_CV2 *(volatile uint32_t *)0x400BB01C // Compare value registers #define ADC1_SC2 *(volatile uint32_t *)0x400BB020 // Status and control register 2 #define ADC1_SC3 *(volatile uint32_t *)0x400BB024 // Status and control register 3 #define ADC1_OFS *(volatile uint32_t *)0x400BB028 // ADC offset correction register #define ADC1_PG *(volatile uint32_t *)0x400BB02C // ADC plus-side gain register #define ADC1_MG *(volatile uint32_t *)0x400BB030 // ADC minus-side gain register #define ADC1_CLPD *(volatile uint32_t *)0x400BB034 // ADC plus-side general calibration value register #define ADC1_CLPS *(volatile uint32_t *)0x400BB038 // ADC plus-side general calibration value register #define ADC1_CLP4 *(volatile uint32_t *)0x400BB03C // ADC plus-side general calibration value register #define ADC1_CLP3 *(volatile uint32_t *)0x400BB040 // ADC plus-side general calibration value register #define ADC1_CLP2 *(volatile uint32_t *)0x400BB044 // ADC plus-side general calibration value register #define ADC1_CLP1 *(volatile uint32_t *)0x400BB048 // ADC plus-side general calibration value register #define ADC1_CLP0 *(volatile uint32_t *)0x400BB04C // ADC plus-side general calibration value register #define ADC1_PGA *(volatile uint32_t *)0x400BB050 // ADC Programmable Gain Amplifier #define ADC1_CLMD *(volatile uint32_t *)0x400BB054 // ADC minus-side general calibration value register #define ADC1_CLMS *(volatile uint32_t *)0x400BB058 // ADC minus-side general calibration value register #define ADC1_CLM4 *(volatile uint32_t *)0x400BB05C // ADC minus-side general calibration value register #define ADC1_CLM3 *(volatile uint32_t *)0x400BB060 // ADC minus-side general calibration value register #define ADC1_CLM2 *(volatile uint32_t *)0x400BB064 // ADC minus-side general calibration value register #define ADC1_CLM1 *(volatile uint32_t *)0x400BB068 // ADC minus-side general calibration value register #define ADC1_CLM0 *(volatile uint32_t *)0x400BB06C // ADC minus-side general calibration value register #define DAC0_DAT0L *(volatile uint8_t *)0x400CC000 // DAC Data Low Register #define DAC0_DATH *(volatile uint8_t *)0x400CC001 // DAC Data High Register #define DAC0_DAT1L *(volatile uint8_t *)0x400CC002 // DAC Data Low Register #define DAC0_DAT2L *(volatile uint8_t *)0x400CC004 // DAC Data Low Register #define DAC0_DAT3L *(volatile uint8_t *)0x400CC006 // DAC Data Low Register #define DAC0_DAT4L *(volatile uint8_t *)0x400CC008 // DAC Data Low Register #define DAC0_DAT5L *(volatile uint8_t *)0x400CC00A // DAC Data Low Register #define DAC0_DAT6L *(volatile uint8_t *)0x400CC00C // DAC Data Low Register #define DAC0_DAT7L *(volatile uint8_t *)0x400CC00E // DAC Data Low Register #define DAC0_DAT8L *(volatile uint8_t *)0x400CC010 // DAC Data Low Register #define DAC0_DAT9L *(volatile uint8_t *)0x400CC012 // DAC Data Low Register #define DAC0_DAT10L *(volatile uint8_t *)0x400CC014 // DAC Data Low Register #define DAC0_DAT11L *(volatile uint8_t *)0x400CC016 // DAC Data Low Register #define DAC0_DAT12L *(volatile uint8_t *)0x400CC018 // DAC Data Low Register #define DAC0_DAT13L *(volatile uint8_t *)0x400CC01A // DAC Data Low Register #define DAC0_DAT14L *(volatile uint8_t *)0x400CC01C // DAC Data Low Register #define DAC0_DAT15L *(volatile uint8_t *)0x400CC01E // DAC Data Low Register #define DAC0_SR *(volatile uint8_t *)0x400CC020 // DAC Status Register #define DAC0_C0 *(volatile uint8_t *)0x400CC021 // DAC Control Register #define DAC_C0_DACEN 0x80 // DAC Enable #define DAC_C0_DACRFS 0x40 // DAC Reference Select #define DAC_C0_DACTRGSEL 0x20 // DAC Trigger Select #define DAC_C0_DACSWTRG 0x10 // DAC Software Trigger #define DAC_C0_LPEN 0x08 // DAC Low Power Control #define DAC_C0_DACBWIEN 0x04 // DAC Buffer Watermark Interrupt Enable #define DAC_C0_DACBTIEN 0x02 // DAC Buffer Read Pointer Top Flag Interrupt Enable #define DAC_C0_DACBBIEN 0x01 // DAC Buffer Read Pointer Bottom Flag Interrupt Enable #define DAC0_C1 *(volatile uint8_t *)0x400CC022 // DAC Control Register 1 #define DAC_C1_DMAEN 0x80 // DMA Enable Select #define DAC_C1_DACBFWM(n) (((n) & 3) << 3) // DAC Buffer Watermark Select #define DAC_C1_DACBFMD(n) (((n) & 3) << 0) // DAC Buffer Work Mode Select #define DAC_C1_DACBFEN 0x00 // DAC Buffer Enable #define DAC0_C2 *(volatile uint8_t *)0x400CC023 // DAC Control Register 2 #define DAC_C2_DACBFRP(n) (((n) & 15) << 4) // DAC Buffer Read Pointer #define DAC_C2_DACBFUP(n) (((n) & 15) << 0) // DAC Buffer Upper Limit //#define MCG_C2_RANGE0(n) (uint8_t)(((n) & 0x03) << 4) // Frequency Range Select, Selects the frequency range for the crystal oscillator //#define MCG_C2_LOCRE0 (uint8_t)0x80 // Loss of Clock Reset Enable, Determines whether an interrupt or a reset request is made following a loss of OSC0 // Chapter 32: Comparator (CMP) #define CMP0_CR0 *(volatile uint8_t *)0x40073000 // CMP Control Register 0 #define CMP0_CR1 *(volatile uint8_t *)0x40073001 // CMP Control Register 1 #define CMP0_FPR *(volatile uint8_t *)0x40073002 // CMP Filter Period Register #define CMP0_SCR *(volatile uint8_t *)0x40073003 // CMP Status and Control Register #define CMP0_DACCR *(volatile uint8_t *)0x40073004 // DAC Control Register #define CMP0_MUXCR *(volatile uint8_t *)0x40073005 // MUX Control Register #define CMP1_CR0 *(volatile uint8_t *)0x40073008 // CMP Control Register 0 #define CMP1_CR1 *(volatile uint8_t *)0x40073009 // CMP Control Register 1 #define CMP1_FPR *(volatile uint8_t *)0x4007300A // CMP Filter Period Register #define CMP1_SCR *(volatile uint8_t *)0x4007300B // CMP Status and Control Register #define CMP1_DACCR *(volatile uint8_t *)0x4007300C // DAC Control Register #define CMP1_MUXCR *(volatile uint8_t *)0x4007300D // MUX Control Register // Chapter 33: Voltage Reference (VREFV1) #define VREF_TRM *(volatile uint8_t *)0x40074000 // VREF Trim Register #define VREF_TRM_CHOPEN (uint8_t)0x40 // Chop oscillator enable #define VREF_TRM_TRIM(n) ((n) & 0x3F) // Trim bits #define VREF_SC *(volatile uint8_t *)0x40074001 // VREF Status and Control Register #define VREF_SC_VREFEN (uint8_t)0x80 // Internal Voltage Reference enable #define VREF_SC_REGEN (uint8_t)0x40 // Regulator enable #define VREF_SC_ICOMPEN (uint8_t)0x20 // Second order curvature compensation enable #define VREF_SC_VREFST (uint8_t)0x04 // Internal Voltage Reference stable flag #define VREF_SC_MODE_LV(n) (uint8_t)(((n) & 3) << 0) // Buffer Mode selection: 0=Bandgap on only // 1=High power buffer mode, // 2=Low-power buffer mode // Chapter 34: Programmable Delay Block (PDB) #define PDB0_SC *(volatile uint32_t *)0x40036000 // Status and Control Register #define PDB_SC_LDMOD(n) (((n) & 3) << 18) // Load Mode Select #define PDB_SC_PDBEIE 0x00020000 // Sequence Error Interrupt Enable #define PDB_SC_SWTRIG 0x00010000 // Software Trigger #define PDB_SC_DMAEN 0x00008000 // DMA Enable #define PDB_SC_PRESCALER(n) (((n) & 7) << 12) // Prescaler Divider Select #define PDB_SC_TRGSEL(n) (((n) & 15) << 8) // Trigger Input Source Select #define PDB_SC_PDBEN 0x00000080 // PDB Enable #define PDB_SC_PDBIF 0x00000040 // PDB Interrupt Flag #define PDB_SC_PDBIE 0x00000020 // PDB Interrupt Enable. #define PDB_SC_MULT(n) (((n) & 3) << 2) // Multiplication Factor #define PDB_SC_CONT 0x00000002 // Continuous Mode Enable #define PDB_SC_LDOK 0x00000001 // Load OK #define PDB0_MOD *(volatile uint32_t *)0x40036004 // Modulus Register #define PDB0_CNT *(volatile uint32_t *)0x40036008 // Counter Register #define PDB0_IDLY *(volatile uint32_t *)0x4003600C // Interrupt Delay Register #define PDB0_CH0C1 *(volatile uint32_t *)0x40036010 // Channel n Control Register 1 #define PDB0_CH0S *(volatile uint32_t *)0x40036014 // Channel n Status Register #define PDB0_CH0DLY0 *(volatile uint32_t *)0x40036018 // Channel n Delay 0 Register #define PDB0_CH0DLY1 *(volatile uint32_t *)0x4003601C // Channel n Delay 1 Register #define PDB0_POEN *(volatile uint32_t *)0x40036190 // Pulse-Out n Enable Register #define PDB0_PO0DLY *(volatile uint32_t *)0x40036194 // Pulse-Out n Delay Register #define PDB0_PO1DLY *(volatile uint32_t *)0x40036198 // Pulse-Out n Delay Register // Chapter 35: FlexTimer Module (FTM) #define FTM0_SC *(volatile uint32_t *)0x40038000 // Status And Control #define FTM_SC_TOF 0x80 // Timer Overflow Flag #define FTM_SC_TOIE 0x40 // Timer Overflow Interrupt Enable #define FTM_SC_CPWMS 0x20 // Center-Aligned PWM Select #define FTM_SC_CLKS(n) (((n) & 3) << 3) // Clock Source Selection #define FTM_SC_PS(n) (((n) & 7) << 0) // Prescale Factor Selection #define FTM0_CNT *(volatile uint32_t *)0x40038004 // Counter #define FTM0_MOD *(volatile uint32_t *)0x40038008 // Modulo #define FTM0_C0SC *(volatile uint32_t *)0x4003800C // Channel 0 Status And Control #define FTM0_C0V *(volatile uint32_t *)0x40038010 // Channel 0 Value #define FTM0_C1SC *(volatile uint32_t *)0x40038014 // Channel 1 Status And Control #define FTM0_C1V *(volatile uint32_t *)0x40038018 // Channel 1 Value #define FTM0_C2SC *(volatile uint32_t *)0x4003801C // Channel 2 Status And Control #define FTM0_C2V *(volatile uint32_t *)0x40038020 // Channel 2 Value #define FTM0_C3SC *(volatile uint32_t *)0x40038024 // Channel 3 Status And Control #define FTM0_C3V *(volatile uint32_t *)0x40038028 // Channel 3 Value #define FTM0_C4SC *(volatile uint32_t *)0x4003802C // Channel 4 Status And Control #define FTM0_C4V *(volatile uint32_t *)0x40038030 // Channel 4 Value #define FTM0_C5SC *(volatile uint32_t *)0x40038034 // Channel 5 Status And Control #define FTM0_C5V *(volatile uint32_t *)0x40038038 // Channel 5 Value #define FTM0_C6SC *(volatile uint32_t *)0x4003803C // Channel 6 Status And Control #define FTM0_C6V *(volatile uint32_t *)0x40038040 // Channel 6 Value #define FTM0_C7SC *(volatile uint32_t *)0x40038044 // Channel 7 Status And Control #define FTM0_C7V *(volatile uint32_t *)0x40038048 // Channel 7 Value #define FTM0_CNTIN *(volatile uint32_t *)0x4003804C // Counter Initial Value #define FTM0_STATUS *(volatile uint32_t *)0x40038050 // Capture And Compare Status #define FTM0_MODE *(volatile uint32_t *)0x40038054 // Features Mode Selection #define FTM_MODE_FAULTIE 0x80 // Fault Interrupt Enable #define FTM_MODE_FAULTM(n) (((n) & 3) << 5) // Fault Control Mode #define FTM_MODE_CAPTEST 0x10 // Capture Test Mode Enable #define FTM_MODE_PWMSYNC 0x08 // PWM Synchronization Mode #define FTM_MODE_WPDIS 0x04 // Write Protection Disable #define FTM_MODE_INIT 0x02 // Initialize The Channels Output #define FTM_MODE_FTMEN 0x01 // FTM Enable #define FTM0_SYNC *(volatile uint32_t *)0x40038058 // Synchronization #define FTM_SYNC_SWSYNC 0x80 // #define FTM_SYNC_TRIG2 0x40 // #define FTM_SYNC_TRIG1 0x20 // #define FTM_SYNC_TRIG0 0x10 // #define FTM_SYNC_SYNCHOM 0x08 // #define FTM_SYNC_REINIT 0x04 // #define FTM_SYNC_CNTMAX 0x02 // #define FTM_SYNC_CNTMIN 0x01 // #define FTM0_OUTINIT *(volatile uint32_t *)0x4003805C // Initial State For Channels Output #define FTM0_OUTMASK *(volatile uint32_t *)0x40038060 // Output Mask #define FTM0_COMBINE *(volatile uint32_t *)0x40038064 // Function For Linked Channels #define FTM0_DEADTIME *(volatile uint32_t *)0x40038068 // Deadtime Insertion Control #define FTM0_EXTTRIG *(volatile uint32_t *)0x4003806C // FTM External Trigger #define FTM0_POL *(volatile uint32_t *)0x40038070 // Channels Polarity #define FTM0_FMS *(volatile uint32_t *)0x40038074 // Fault Mode Status #define FTM0_FILTER *(volatile uint32_t *)0x40038078 // Input Capture Filter Control #define FTM0_FLTCTRL *(volatile uint32_t *)0x4003807C // Fault Control #define FTM0_QDCTRL *(volatile uint32_t *)0x40038080 // Quadrature Decoder Control And Status #define FTM0_CONF *(volatile uint32_t *)0x40038084 // Configuration #define FTM0_FLTPOL *(volatile uint32_t *)0x40038088 // FTM Fault Input Polarity #define FTM0_SYNCONF *(volatile uint32_t *)0x4003808C // Synchronization Configuration #define FTM0_INVCTRL *(volatile uint32_t *)0x40038090 // FTM Inverting Control #define FTM0_SWOCTRL *(volatile uint32_t *)0x40038094 // FTM Software Output Control #define FTM0_PWMLOAD *(volatile uint32_t *)0x40038098 // FTM PWM Load #define FTM1_SC *(volatile uint32_t *)0x40039000 // Status And Control #define FTM1_CNT *(volatile uint32_t *)0x40039004 // Counter #define FTM1_MOD *(volatile uint32_t *)0x40039008 // Modulo #define FTM1_C0SC *(volatile uint32_t *)0x4003900C // Channel 0 Status And Control #define FTM1_C0V *(volatile uint32_t *)0x40039010 // Channel 0 Value #define FTM1_C1SC *(volatile uint32_t *)0x40039014 // Channel 1 Status And Control #define FTM1_C1V *(volatile uint32_t *)0x40039018 // Channel 1 Value #define FTM1_CNTIN *(volatile uint32_t *)0x4003904C // Counter Initial Value #define FTM1_STATUS *(volatile uint32_t *)0x40039050 // Capture And Compare Status #define FTM1_MODE *(volatile uint32_t *)0x40039054 // Features Mode Selection #define FTM1_SYNC *(volatile uint32_t *)0x40039058 // Synchronization #define FTM1_OUTINIT *(volatile uint32_t *)0x4003905C // Initial State For Channels Output #define FTM1_OUTMASK *(volatile uint32_t *)0x40039060 // Output Mask #define FTM1_COMBINE *(volatile uint32_t *)0x40039064 // Function For Linked Channels #define FTM1_DEADTIME *(volatile uint32_t *)0x40039068 // Deadtime Insertion Control #define FTM1_EXTTRIG *(volatile uint32_t *)0x4003906C // FTM External Trigger #define FTM1_POL *(volatile uint32_t *)0x40039070 // Channels Polarity #define FTM1_FMS *(volatile uint32_t *)0x40039074 // Fault Mode Status #define FTM1_FILTER *(volatile uint32_t *)0x40039078 // Input Capture Filter Control #define FTM1_FLTCTRL *(volatile uint32_t *)0x4003907C // Fault Control #define FTM1_QDCTRL *(volatile uint32_t *)0x40039080 // Quadrature Decoder Control And Status #define FTM1_CONF *(volatile uint32_t *)0x40039084 // Configuration #define FTM1_FLTPOL *(volatile uint32_t *)0x40039088 // FTM Fault Input Polarity #define FTM1_SYNCONF *(volatile uint32_t *)0x4003908C // Synchronization Configuration #define FTM1_INVCTRL *(volatile uint32_t *)0x40039090 // FTM Inverting Control #define FTM1_SWOCTRL *(volatile uint32_t *)0x40039094 // FTM Software Output Control #define FTM1_PWMLOAD *(volatile uint32_t *)0x40039098 // FTM PWM Load #define FTM2_SC *(volatile uint32_t *)0x400B8000 // Status And Control #define FTM2_CNT *(volatile uint32_t *)0x400B8004 // Counter #define FTM2_MOD *(volatile uint32_t *)0x400B8008 // Modulo #define FTM2_C0SC *(volatile uint32_t *)0x400B800C // Channel 0 Status And Control #define FTM2_C0V *(volatile uint32_t *)0x400B8010 // Channel 0 Value #define FTM2_C1SC *(volatile uint32_t *)0x400B8014 // Channel 1 Status And Control #define FTM2_C1V *(volatile uint32_t *)0x400B8018 // Channel 1 Value #define FTM2_CNTIN *(volatile uint32_t *)0x400B804C // Counter Initial Value #define FTM2_STATUS *(volatile uint32_t *)0x400B8050 // Capture And Compare Status #define FTM2_MODE *(volatile uint32_t *)0x400B8054 // Features Mode Selection #define FTM2_SYNC *(volatile uint32_t *)0x400B8058 // Synchronization #define FTM2_OUTINIT *(volatile uint32_t *)0x400B805C // Initial State For Channels Output #define FTM2_OUTMASK *(volatile uint32_t *)0x400B8060 // Output Mask #define FTM2_COMBINE *(volatile uint32_t *)0x400B8064 // Function For Linked Channels #define FTM2_DEADTIME *(volatile uint32_t *)0x400B8068 // Deadtime Insertion Control #define FTM2_EXTTRIG *(volatile uint32_t *)0x400B806C // FTM External Trigger #define FTM2_POL *(volatile uint32_t *)0x400B8070 // Channels Polarity #define FTM2_FMS *(volatile uint32_t *)0x400B8074 // Fault Mode Status #define FTM2_FILTER *(volatile uint32_t *)0x400B8078 // Input Capture Filter Control #define FTM2_FLTCTRL *(volatile uint32_t *)0x400B807C // Fault Control #define FTM2_QDCTRL *(volatile uint32_t *)0x400B8080 // Quadrature Decoder Control And Status #define FTM2_CONF *(volatile uint32_t *)0x400B8084 // Configuration #define FTM2_FLTPOL *(volatile uint32_t *)0x400B8088 // FTM Fault Input Polarity #define FTM2_SYNCONF *(volatile uint32_t *)0x400B808C // Synchronization Configuration #define FTM2_INVCTRL *(volatile uint32_t *)0x400B8090 // FTM Inverting Control #define FTM2_SWOCTRL *(volatile uint32_t *)0x400B8094 // FTM Software Output Control #define FTM2_PWMLOAD *(volatile uint32_t *)0x400B8098 // FTM PWM Load // Chapter 36: Periodic Interrupt Timer (PIT) #define PIT_MCR *(volatile uint32_t *)0x40037000 // PIT Module Control Register #define PIT_LDVAL0 *(volatile uint32_t *)0x40037100 // Timer Load Value Register #define PIT_CVAL0 *(volatile uint32_t *)0x40037104 // Current Timer Value Register #define PIT_TCTRL0 *(volatile uint32_t *)0x40037108 // Timer Control Register #define PIT_TFLG0 *(volatile uint32_t *)0x4003710C // Timer Flag Register #define PIT_LDVAL1 *(volatile uint32_t *)0x40037110 // Timer Load Value Register #define PIT_CVAL1 *(volatile uint32_t *)0x40037114 // Current Timer Value Register #define PIT_TCTRL1 *(volatile uint32_t *)0x40037118 // Timer Control Register #define PIT_TFLG1 *(volatile uint32_t *)0x4003711C // Timer Flag Register #define PIT_LDVAL2 *(volatile uint32_t *)0x40037120 // Timer Load Value Register #define PIT_CVAL2 *(volatile uint32_t *)0x40037124 // Current Timer Value Register #define PIT_TCTRL2 *(volatile uint32_t *)0x40037128 // Timer Control Register #define PIT_TFLG2 *(volatile uint32_t *)0x4003712C // Timer Flag Register #define PIT_LDVAL3 *(volatile uint32_t *)0x40037130 // Timer Load Value Register #define PIT_CVAL3 *(volatile uint32_t *)0x40037134 // Current Timer Value Register #define PIT_TCTRL3 *(volatile uint32_t *)0x40037138 // Timer Control Register #define PIT_TFLG3 *(volatile uint32_t *)0x4003713C // Timer Flag Register // Chapter 37: Low-Power Timer (LPTMR) #define LPTMR0_CSR *(volatile uint32_t *)0x40040000 // Low Power Timer Control Status Register #define LPTMR0_PSR *(volatile uint32_t *)0x40040004 // Low Power Timer Prescale Register #define LPTMR0_CMR *(volatile uint32_t *)0x40040008 // Low Power Timer Compare Register #define LPTMR0_CNR *(volatile uint32_t *)0x4004000C // Low Power Timer Counter Register // Chapter 38: Carrier Modulator Transmitter (CMT) #define CMT_CGH1 *(volatile uint8_t *)0x40062000 // CMT Carrier Generator High Data Register 1 #define CMT_CGL1 *(volatile uint8_t *)0x40062001 // CMT Carrier Generator Low Data Register 1 #define CMT_CGH2 *(volatile uint8_t *)0x40062002 // CMT Carrier Generator High Data Register 2 #define CMT_CGL2 *(volatile uint8_t *)0x40062003 // CMT Carrier Generator Low Data Register 2 #define CMT_OC *(volatile uint8_t *)0x40062004 // CMT Output Control Register #define CMT_MSC *(volatile uint8_t *)0x40062005 // CMT Modulator Status and Control Register #define CMT_CMD1 *(volatile uint8_t *)0x40062006 // CMT Modulator Data Register Mark High #define CMT_CMD2 *(volatile uint8_t *)0x40062007 // CMT Modulator Data Register Mark Low #define CMT_CMD3 *(volatile uint8_t *)0x40062008 // CMT Modulator Data Register Space High #define CMT_CMD4 *(volatile uint8_t *)0x40062009 // CMT Modulator Data Register Space Low #define CMT_PPS *(volatile uint8_t *)0x4006200A // CMT Primary Prescaler Register #define CMT_DMA *(volatile uint8_t *)0x4006200B // CMT Direct Memory Access Register // Chapter 39: Real Time Clock (RTC) #define RTC_TSR *(volatile uint32_t *)0x4003D000 // RTC Time Seconds Register #define RTC_TPR *(volatile uint32_t *)0x4003D004 // RTC Time Prescaler Register #define RTC_TAR *(volatile uint32_t *)0x4003D008 // RTC Time Alarm Register #define RTC_TCR *(volatile uint32_t *)0x4003D00C // RTC Time Compensation Register #define RTC_TCR_CIC(n) (((n) & 255) << 24) // Compensation Interval Counter #define RTC_TCR_TCV(n) (((n) & 255) << 16) // Time Compensation Value #define RTC_TCR_CIR(n) (((n) & 255) << 8) // Compensation Interval Register #define RTC_TCR_TCR(n) (((n) & 255) << 0) // Time Compensation Register #define RTC_CR *(volatile uint32_t *)0x4003D010 // RTC Control Register #define RTC_CR_SC2P (uint32_t)0x00002000 // #define RTC_CR_SC4P (uint32_t)0x00001000 // #define RTC_CR_SC8P (uint32_t)0x00000800 // #define RTC_CR_SC16P (uint32_t)0x00000400 // #define RTC_CR_CLKO (uint32_t)0x00000200 // #define RTC_CR_OSCE (uint32_t)0x00000100 // #define RTC_CR_UM (uint32_t)0x00000008 // #define RTC_CR_SUP (uint32_t)0x00000004 // #define RTC_CR_WPE (uint32_t)0x00000002 // #define RTC_CR_SWR (uint32_t)0x00000001 // #define RTC_SR *(volatile uint32_t *)0x4003D014 // RTC Status Register #define RTC_SR_TCE (uint32_t)0x00000010 // #define RTC_SR_TAF (uint32_t)0x00000004 // #define RTC_SR_TOF (uint32_t)0x00000002 // #define RTC_SR_TIF (uint32_t)0x00000001 // #define RTC_LR *(volatile uint32_t *)0x4003D018 // RTC Lock Register #define RTC_IER *(volatile uint32_t *)0x4003D01C // RTC Interrupt Enable Register #define RTC_WAR *(volatile uint32_t *)0x4003D800 // RTC Write Access Register #define RTC_RAR *(volatile uint32_t *)0x4003D804 // RTC Read Access Register // Chapter 40: Universal Serial Bus OTG Controller (USBOTG) #define USB0_PERID *(const uint8_t *)0x40072000 // Peripheral ID register #define USB0_IDCOMP *(const uint8_t *)0x40072004 // Peripheral ID Complement register #define USB0_REV *(const uint8_t *)0x40072008 // Peripheral Revision register #define USB0_ADDINFO *(volatile uint8_t *)0x4007200C // Peripheral Additional Info register #define USB0_OTGISTAT *(volatile uint8_t *)0x40072010 // OTG Interrupt Status register #define USB_OTGISTAT_IDCHG (uint8_t)0x80 // #define USB_OTGISTAT_ONEMSEC (uint8_t)0x40 // #define USB_OTGISTAT_LINE_STATE_CHG (uint8_t)0x20 // #define USB_OTGISTAT_SESSVLDCHG (uint8_t)0x08 // #define USB_OTGISTAT_B_SESS_CHG (uint8_t)0x04 // #define USB_OTGISTAT_AVBUSCHG (uint8_t)0x01 // #define USB0_OTGICR *(volatile uint8_t *)0x40072014 // OTG Interrupt Control Register #define USB_OTGICR_IDEN (uint8_t)0x80 // #define USB_OTGICR_ONEMSECEN (uint8_t)0x40 // #define USB_OTGICR_LINESTATEEN (uint8_t)0x20 // #define USB_OTGICR_SESSVLDEN (uint8_t)0x08 // #define USB_OTGICR_BSESSEN (uint8_t)0x04 // #define USB_OTGICR_AVBUSEN (uint8_t)0x01 // #define USB0_OTGSTAT *(volatile uint8_t *)0x40072018 // OTG Status register #define USB_OTGSTAT_ID (uint8_t)0x80 // #define USB_OTGSTAT_ONEMSECEN (uint8_t)0x40 // #define USB_OTGSTAT_LINESTATESTABLE (uint8_t)0x20 // #define USB_OTGSTAT_SESS_VLD (uint8_t)0x08 // #define USB_OTGSTAT_BSESSEND (uint8_t)0x04 // #define USB_OTGSTAT_AVBUSVLD (uint8_t)0x01 // #define USB0_OTGCTL *(volatile uint8_t *)0x4007201C // OTG Control Register #define USB_OTGCTL_DPHIGH (uint8_t)0x80 // #define USB_OTGCTL_DPLOW (uint8_t)0x20 // #define USB_OTGCTL_DMLOW (uint8_t)0x10 // #define USB_OTGCTL_OTGEN (uint8_t)0x04 // #define USB0_ISTAT *(volatile uint8_t *)0x40072080 // Interrupt Status Register #define USB_ISTAT_STALL (uint8_t)0x80 // #define USB_ISTAT_ATTACH (uint8_t)0x40 // #define USB_ISTAT_RESUME (uint8_t)0x20 // #define USB_ISTAT_SLEEP (uint8_t)0x10 // #define USB_ISTAT_TOKDNE (uint8_t)0x08 // #define USB_ISTAT_SOFTOK (uint8_t)0x04 // #define USB_ISTAT_ERROR (uint8_t)0x02 // #define USB_ISTAT_USBRST (uint8_t)0x01 // #define USB0_INTEN *(volatile uint8_t *)0x40072084 // Interrupt Enable Register #define USB_INTEN_STALLEN (uint8_t)0x80 // #define USB_INTEN_ATTACHEN (uint8_t)0x40 // #define USB_INTEN_RESUMEEN (uint8_t)0x20 // #define USB_INTEN_SLEEPEN (uint8_t)0x10 // #define USB_INTEN_TOKDNEEN (uint8_t)0x08 // #define USB_INTEN_SOFTOKEN (uint8_t)0x04 // #define USB_INTEN_ERROREN (uint8_t)0x02 // #define USB_INTEN_USBRSTEN (uint8_t)0x01 // #define USB0_ERRSTAT *(volatile uint8_t *)0x40072088 // Error Interrupt Status Register #define USB_ERRSTAT_BTSERR (uint8_t)0x80 // #define USB_ERRSTAT_DMAERR (uint8_t)0x20 // #define USB_ERRSTAT_BTOERR (uint8_t)0x10 // #define USB_ERRSTAT_DFN8 (uint8_t)0x08 // #define USB_ERRSTAT_CRC16 (uint8_t)0x04 // #define USB_ERRSTAT_CRC5EOF (uint8_t)0x02 // #define USB_ERRSTAT_PIDERR (uint8_t)0x01 // #define USB0_ERREN *(volatile uint8_t *)0x4007208C // Error Interrupt Enable Register #define USB_ERREN_BTSERREN (uint8_t)0x80 // #define USB_ERREN_DMAERREN (uint8_t)0x20 // #define USB_ERREN_BTOERREN (uint8_t)0x10 // #define USB_ERREN_DFN8EN (uint8_t)0x08 // #define USB_ERREN_CRC16EN (uint8_t)0x04 // #define USB_ERREN_CRC5EOFEN (uint8_t)0x02 // #define USB_ERREN_PIDERREN (uint8_t)0x01 // #define USB0_STAT *(volatile uint8_t *)0x40072090 // Status Register #define USB_STAT_TX (uint8_t)0x08 // #define USB_STAT_ODD (uint8_t)0x04 // #define USB_STAT_ENDP(n) (uint8_t)((n) >> 4) // #define USB0_CTL *(volatile uint8_t *)0x40072094 // Control Register #define USB_CTL_JSTATE (uint8_t)0x80 // #define USB_CTL_SE0 (uint8_t)0x40 // #define USB_CTL_TXSUSPENDTOKENBUSY (uint8_t)0x20 // #define USB_CTL_RESET (uint8_t)0x10 // #define USB_CTL_HOSTMODEEN (uint8_t)0x08 // #define USB_CTL_RESUME (uint8_t)0x04 // #define USB_CTL_ODDRST (uint8_t)0x02 // #define USB_CTL_USBENSOFEN (uint8_t)0x01 // #define USB0_ADDR *(volatile uint8_t *)0x40072098 // Address Register #define USB0_BDTPAGE1 *(volatile uint8_t *)0x4007209C // BDT Page Register 1 #define USB0_FRMNUML *(volatile uint8_t *)0x400720A0 // Frame Number Register Low #define USB0_FRMNUMH *(volatile uint8_t *)0x400720A4 // Frame Number Register High #define USB0_TOKEN *(volatile uint8_t *)0x400720A8 // Token Register #define USB0_SOFTHLD *(volatile uint8_t *)0x400720AC // SOF Threshold Register #define USB0_BDTPAGE2 *(volatile uint8_t *)0x400720B0 // BDT Page Register 2 #define USB0_BDTPAGE3 *(volatile uint8_t *)0x400720B4 // BDT Page Register 3 #define USB0_ENDPT0 *(volatile uint8_t *)0x400720C0 // Endpoint Control Register #define USB_ENDPT_HOSTWOHUB (uint8_t)0x80 // host only, enable low speed #define USB_ENDPT_RETRYDIS (uint8_t)0x40 // host only, set to disable NAK retry #define USB_ENDPT_EPCTLDIS (uint8_t)0x10 // 0=control, 1=bulk, interrupt, isync #define USB_ENDPT_EPRXEN (uint8_t)0x08 // enables the endpoint for RX transfers. #define USB_ENDPT_EPTXEN (uint8_t)0x04 // enables the endpoint for TX transfers. #define USB_ENDPT_EPSTALL (uint8_t)0x02 // set to stall endpoint #define USB_ENDPT_EPHSHK (uint8_t)0x01 // enable handshaking during a transaction, generally set unless Isochronous #define USB0_ENDPT1 *(volatile uint8_t *)0x400720C4 // Endpoint Control Register #define USB0_ENDPT2 *(volatile uint8_t *)0x400720C8 // Endpoint Control Register #define USB0_ENDPT3 *(volatile uint8_t *)0x400720CC // Endpoint Control Register #define USB0_ENDPT4 *(volatile uint8_t *)0x400720D0 // Endpoint Control Register #define USB0_ENDPT5 *(volatile uint8_t *)0x400720D4 // Endpoint Control Register #define USB0_ENDPT6 *(volatile uint8_t *)0x400720D8 // Endpoint Control Register #define USB0_ENDPT7 *(volatile uint8_t *)0x400720DC // Endpoint Control Register #define USB0_ENDPT8 *(volatile uint8_t *)0x400720E0 // Endpoint Control Register #define USB0_ENDPT9 *(volatile uint8_t *)0x400720E4 // Endpoint Control Register #define USB0_ENDPT10 *(volatile uint8_t *)0x400720E8 // Endpoint Control Register #define USB0_ENDPT11 *(volatile uint8_t *)0x400720EC // Endpoint Control Register #define USB0_ENDPT12 *(volatile uint8_t *)0x400720F0 // Endpoint Control Register #define USB0_ENDPT13 *(volatile uint8_t *)0x400720F4 // Endpoint Control Register #define USB0_ENDPT14 *(volatile uint8_t *)0x400720F8 // Endpoint Control Register #define USB0_ENDPT15 *(volatile uint8_t *)0x400720FC // Endpoint Control Register #define USB0_USBCTRL *(volatile uint8_t *)0x40072100 // USB Control Register #define USB_USBCTRL_SUSP (uint8_t)0x80 // Places the USB transceiver into the suspend state. #define USB_USBCTRL_PDE (uint8_t)0x40 // Enables the weak pulldowns on the USB transceiver. #define USB0_OBSERVE *(volatile uint8_t *)0x40072104 // USB OTG Observe Register #define USB_OBSERVE_DPPU (uint8_t)0x80 // #define USB_OBSERVE_DPPD (uint8_t)0x40 // #define USB_OBSERVE_DMPD (uint8_t)0x10 // #define USB0_CONTROL *(volatile uint8_t *)0x40072108 // USB OTG Control Register #define USB_CONTROL_DPPULLUPNONOTG (uint8_t)0x10 // Provides control of the DP PULLUP in the USB OTG module, if USB is configured in non-OTG device mode. #define USB0_USBTRC0 *(volatile uint8_t *)0x4007210C // USB Transceiver Control Register 0 #define USB_USBTRC_USBRESET (uint8_t)0x80 // #define USB_USBTRC_USBRESMEN (uint8_t)0x20 // #define USB_USBTRC_SYNC_DET (uint8_t)0x02 // #define USB_USBTRC_USB_RESUME_INT (uint8_t)0x01 // #define USB0_USBFRMADJUST *(volatile uint8_t *)0x40072114 // Frame Adjust Register // Chapter 41: USB Device Charger Detection Module (USBDCD) #define USBDCD_CONTROL *(volatile uint32_t *)0x40035000 // Control register #define USBDCD_CLOCK *(volatile uint32_t *)0x40035004 // Clock register #define USBDCD_STATUS *(volatile uint32_t *)0x40035008 // Status register #define USBDCD_TIMER0 *(volatile uint32_t *)0x40035010 // TIMER0 register #define USBDCD_TIMER1 *(volatile uint32_t *)0x40035014 // TIMER1 register #define USBDCD_TIMER2 *(volatile uint32_t *)0x40035018 // TIMER2 register // Chapter 43: SPI (DSPI) #define SPI0_MCR *(volatile uint32_t *)0x4002C000 // DSPI Module Configuration Register #define SPI_MCR_MSTR (uint32_t)0x80000000 // Master/Slave Mode Select #define SPI_MCR_CONT_SCKE (uint32_t)0x40000000 // #define SPI_MCR_DCONF(n) (((n) & 3) << 28) // #define SPI_MCR_FRZ (uint32_t)0x08000000 // #define SPI_MCR_MTFE (uint32_t)0x04000000 // #define SPI_MCR_ROOE (uint32_t)0x01000000 // #define SPI_MCR_PCSIS(n) (((n) & 0x1F) << 16) // #define SPI_MCR_DOZE (uint32_t)0x00008000 // #define SPI_MCR_MDIS (uint32_t)0x00004000 // #define SPI_MCR_DIS_TXF (uint32_t)0x00002000 // #define SPI_MCR_DIS_RXF (uint32_t)0x00001000 // #define SPI_MCR_CLR_TXF (uint32_t)0x00000800 // #define SPI_MCR_CLR_RXF (uint32_t)0x00000400 // #define SPI_MCR_SMPL_PT(n) (((n) & 3) << 8) // #define SPI_MCR_HALT (uint32_t)0x00000001 // #define SPI0_TCR *(volatile uint32_t *)0x4002C008 // DSPI Transfer Count Register #define SPI0_CTAR0 *(volatile uint32_t *)0x4002C00C // DSPI Clock and Transfer Attributes Register, In Master Mode #define SPI_CTAR_DBR (uint32_t)0x80000000 // Double Baud Rate #define SPI_CTAR_FMSZ(n) (((n) & 15) << 27) // Frame Size (+1) #define SPI_CTAR_CPOL (uint32_t)0x04000000 // Clock Polarity #define SPI_CTAR_CPHA (uint32_t)0x02000000 // Clock Phase #define SPI_CTAR_LSBFE (uint32_t)0x01000000 // LSB First #define SPI_CTAR_PCSSCK(n) (((n) & 3) << 22) // PCS to SCK Delay Prescaler #define SPI_CTAR_PASC(n) (((n) & 3) << 20) // After SCK Delay Prescaler #define SPI_CTAR_PDT(n) (((n) & 3) << 18) // Delay after Transfer Prescaler #define SPI_CTAR_PBR(n) (((n) & 3) << 16) // Baud Rate Prescaler #define SPI_CTAR_CSSCK(n) (((n) & 15) << 12) // PCS to SCK Delay Scaler #define SPI_CTAR_ASC(n) (((n) & 15) << 8) // After SCK Delay Scaler #define SPI_CTAR_DT(n) (((n) & 15) << 4) // Delay After Transfer Scaler #define SPI_CTAR_BR(n) (((n) & 15) << 0) // Baud Rate Scaler #define SPI0_CTAR0_SLAVE *(volatile uint32_t *)0x4002C00C // DSPI Clock and Transfer Attributes Register, In Slave Mode #define SPI0_CTAR1 *(volatile uint32_t *)0x4002C010 // DSPI Clock and Transfer Attributes Register, In Master Mode #define SPI0_SR *(volatile uint32_t *)0x4002C02C // DSPI Status Register #define SPI_SR_TCF (uint32_t)0x80000000 // Transfer Complete Flag #define SPI_SR_TXRXS (uint32_t)0x40000000 // TX and RX Status #define SPI_SR_EOQF (uint32_t)0x10000000 // End of Queue Flag #define SPI_SR_TFUF (uint32_t)0x08000000 // Transmit FIFO Underflow Flag #define SPI_SR_TFFF (uint32_t)0x02000000 // Transmit FIFO Fill Flag #define SPI_SR_RFOF (uint32_t)0x00080000 // Receive FIFO Overflow Flag #define SPI_SR_RFDF (uint32_t)0x00020000 // Receive FIFO Drain Flag #define SPI0_RSER *(volatile uint32_t *)0x4002C030 // DSPI DMA/Interrupt Request Select and Enable Register #define SPI_RSER_TCF_RE (uint32_t)0x80000000 // Transmission Complete Request Enable #define SPI_RSER_EOQF_RE (uint32_t)0x10000000 // DSPI Finished Request Request Enable #define SPI_RSER_TFUF_RE (uint32_t)0x08000000 // Transmit FIFO Underflow Request Enable #define SPI_RSER_TFFF_RE (uint32_t)0x02000000 // Transmit FIFO Fill Request Enable #define SPI_RSER_TFFF_DIRS (uint32_t)0x01000000 // Transmit FIFO FIll Dma or Interrupt Request Select #define SPI_RSER_RFOF_RE (uint32_t)0x00080000 // Receive FIFO Overflow Request Enable #define SPI_RSER_RFDF_RE (uint32_t)0x00020000 // Receive FIFO Drain Request Enable #define SPI_RSER_RFDF_DIRS (uint32_t)0x00010000 // Receive FIFO Drain DMA or Interrupt Request Select #define SPI0_PUSHR *(volatile uint32_t *)0x4002C034 // DSPI PUSH TX FIFO Register In Master Mode #define SPI_PUSHR_CONT (uint32_t)0x80000000 // #define SPI_PUSHR_CTAS(n) (((n) & 7) << 28) // #define SPI_PUSHR_EOQ (uint32_t)0x08000000 // #define SPI_PUSHR_CTCNT (uint32_t)0x04000000 // #define SPI_PUSHR_PCS(n) (((n) & 31) << 16) // #define SPI0_PUSHR_SLAVE *(volatile uint32_t *)0x4002C034 // DSPI PUSH TX FIFO Register In Slave Mode #define SPI0_POPR *(volatile uint32_t *)0x4002C038 // DSPI POP RX FIFO Register #define SPI0_TXFR0 *(volatile uint32_t *)0x4002C03C // DSPI Transmit FIFO Registers #define SPI0_TXFR1 *(volatile uint32_t *)0x4002C040 // DSPI Transmit FIFO Registers #define SPI0_TXFR2 *(volatile uint32_t *)0x4002C044 // DSPI Transmit FIFO Registers #define SPI0_TXFR3 *(volatile uint32_t *)0x4002C048 // DSPI Transmit FIFO Registers #define SPI0_RXFR0 *(volatile uint32_t *)0x4002C07C // DSPI Receive FIFO Registers #define SPI0_RXFR1 *(volatile uint32_t *)0x4002C080 // DSPI Receive FIFO Registers #define SPI0_RXFR2 *(volatile uint32_t *)0x4002C084 // DSPI Receive FIFO Registers #define SPI0_RXFR3 *(volatile uint32_t *)0x4002C088 // DSPI Receive FIFO Registers typedef struct { volatile uint32_t MCR; // 0 volatile uint32_t unused1;// 4 volatile uint32_t TCR; // 8 volatile uint32_t CTAR0; // c volatile uint32_t CTAR1; // 10 volatile uint32_t CTAR2; // 14 volatile uint32_t CTAR3; // 18 volatile uint32_t CTAR4; // 1c volatile uint32_t CTAR5; // 20 volatile uint32_t CTAR6; // 24 volatile uint32_t CTAR7; // 28 volatile uint32_t SR; // 2c volatile uint32_t RSER; // 30 volatile uint32_t PUSHR; // 34 volatile uint32_t POPR; // 38 volatile uint32_t TXFR[16]; // 3c volatile uint32_t RXFR[16]; // 7c } SPI_t; #define SPI0 (*(SPI_t *)0x4002C000) // Chapter 44: Inter-Integrated Circuit (I2C) #define I2C0_A1 *(volatile uint8_t *)0x40066000 // I2C Address Register 1 #define I2C0_F *(volatile uint8_t *)0x40066001 // I2C Frequency Divider register #define I2C0_C1 *(volatile uint8_t *)0x40066002 // I2C Control Register 1 #define I2C_C1_IICEN (uint8_t)0x80 // I2C Enable #define I2C_C1_IICIE (uint8_t)0x40 // I2C Interrupt Enable #define I2C_C1_MST (uint8_t)0x20 // Master Mode Select #define I2C_C1_TX (uint8_t)0x10 // Transmit Mode Select #define I2C_C1_TXAK (uint8_t)0x08 // Transmit Acknowledge Enable #define I2C_C1_RSTA (uint8_t)0x04 // Repeat START #define I2C_C1_WUEN (uint8_t)0x02 // Wakeup Enable #define I2C_C1_DMAEN (uint8_t)0x01 // DMA Enable #define I2C0_S *(volatile uint8_t *)0x40066003 // I2C Status register #define I2C_S_TCF (uint8_t)0x80 // Transfer Complete Flag #define I2C_S_IAAS (uint8_t)0x40 // Addressed As A Slave #define I2C_S_BUSY (uint8_t)0x20 // Bus Busy #define I2C_S_ARBL (uint8_t)0x10 // Arbitration Lost #define I2C_S_RAM (uint8_t)0x08 // Range Address Match #define I2C_S_SRW (uint8_t)0x04 // Slave Read/Write #define I2C_S_IICIF (uint8_t)0x02 // Interrupt Flag #define I2C_S_RXAK (uint8_t)0x01 // Receive Acknowledge #define I2C0_D *(volatile uint8_t *)0x40066004 // I2C Data I/O register #define I2C0_C2 *(volatile uint8_t *)0x40066005 // I2C Control Register 2 #define I2C_C2_GCAEN (uint8_t)0x80 // General Call Address Enable #define I2C_C2_ADEXT (uint8_t)0x40 // Address Extension #define I2C_C2_HDRS (uint8_t)0x20 // High Drive Select #define I2C_C2_SBRC (uint8_t)0x10 // Slave Baud Rate Control #define I2C_C2_RMEN (uint8_t)0x08 // Range Address Matching Enable #define I2C_C2_AD(n) ((n) & 7) // Slave Address, upper 3 bits #define I2C0_FLT *(volatile uint8_t *)0x40066006 // I2C Programmable Input Glitch Filter register #define I2C0_RA *(volatile uint8_t *)0x40066007 // I2C Range Address register #define I2C0_SMB *(volatile uint8_t *)0x40066008 // I2C SMBus Control and Status register #define I2C0_A2 *(volatile uint8_t *)0x40066009 // I2C Address Register 2 #define I2C0_SLTH *(volatile uint8_t *)0x4006600A // I2C SCL Low Timeout Register High #define I2C0_SLTL *(volatile uint8_t *)0x4006600B // I2C SCL Low Timeout Register Low #define I2C1_A1 *(volatile uint8_t *)0x40067000 // I2C Address Register 1 #define I2C1_F *(volatile uint8_t *)0x40067001 // I2C Frequency Divider register #define I2C1_C1 *(volatile uint8_t *)0x40067002 // I2C Control Register 1 #define I2C1_S *(volatile uint8_t *)0x40067003 // I2C Status register #define I2C1_D *(volatile uint8_t *)0x40067004 // I2C Data I/O register #define I2C1_C2 *(volatile uint8_t *)0x40067005 // I2C Control Register 2 #define I2C1_FLT *(volatile uint8_t *)0x40067006 // I2C Programmable Input Glitch Filter register #define I2C1_RA *(volatile uint8_t *)0x40067007 // I2C Range Address register #define I2C1_SMB *(volatile uint8_t *)0x40067008 // I2C SMBus Control and Status register #define I2C1_A2 *(volatile uint8_t *)0x40067009 // I2C Address Register 2 #define I2C1_SLTH *(volatile uint8_t *)0x4006700A // I2C SCL Low Timeout Register High #define I2C1_SLTL *(volatile uint8_t *)0x4006700B // I2C SCL Low Timeout Register Low // Chapter 45: Universal Asynchronous Receiver/Transmitter (UART) #define UART0_BDH *(volatile uint8_t *)0x4006A000 // UART Baud Rate Registers: High #define UART0_BDL *(volatile uint8_t *)0x4006A001 // UART Baud Rate Registers: Low #define UART0_C1 *(volatile uint8_t *)0x4006A002 // UART Control Register 1 #define UART_C1_LOOPS (uint8_t)0x80 // When LOOPS is set, the RxD pin is disconnected from the UART and the transmitter output is internally connected to the receiver input #define UART_C1_UARTSWAI (uint8_t)0x40 // UART Stops in Wait Mode #define UART_C1_RSRC (uint8_t)0x20 // When LOOPS is set, the RSRC field determines the source for the receiver shift register input #define UART_C1_M (uint8_t)0x10 // 9-bit or 8-bit Mode Select #define UART_C1_WAKE (uint8_t)0x08 // Determines which condition wakes the UART #define UART_C1_ILT (uint8_t)0x04 // Idle Line Type Select #define UART_C1_PE (uint8_t)0x02 // Parity Enable #define UART_C1_PT (uint8_t)0x01 // Parity Type, 0=even, 1=odd #define UART0_C2 *(volatile uint8_t *)0x4006A003 // UART Control Register 2 #define UART_C2_TIE (uint8_t)0x80 // Transmitter Interrupt or DMA Transfer Enable. #define UART_C2_TCIE (uint8_t)0x40 // Transmission Complete Interrupt Enable #define UART_C2_RIE (uint8_t)0x20 // Receiver Full Interrupt or DMA Transfer Enable #define UART_C2_ILIE (uint8_t)0x10 // Idle Line Interrupt Enable #define UART_C2_TE (uint8_t)0x08 // Transmitter Enable #define UART_C2_RE (uint8_t)0x04 // Receiver Enable #define UART_C2_RWU (uint8_t)0x02 // Receiver Wakeup Control #define UART_C2_SBK (uint8_t)0x01 // Send Break #define UART0_S1 *(volatile uint8_t *)0x4006A004 // UART Status Register 1 #define UART_S1_TDRE (uint8_t)0x80 // Transmit Data Register Empty Flag #define UART_S1_TC (uint8_t)0x40 // Transmit Complete Flag #define UART_S1_RDRF (uint8_t)0x20 // Receive Data Register Full Flag #define UART_S1_IDLE (uint8_t)0x10 // Idle Line Flag #define UART_S1_OR (uint8_t)0x08 // Receiver Overrun Flag #define UART_S1_NF (uint8_t)0x04 // Noise Flag #define UART_S1_FE (uint8_t)0x02 // Framing Error Flag #define UART_S1_PF (uint8_t)0x01 // Parity Error Flag #define UART0_S2 *(volatile uint8_t *)0x4006A005 // UART Status Register 2 #define UART0_C3 *(volatile uint8_t *)0x4006A006 // UART Control Register 3 #define UART0_D *(volatile uint8_t *)0x4006A007 // UART Data Register #define UART0_MA1 *(volatile uint8_t *)0x4006A008 // UART Match Address Registers 1 #define UART0_MA2 *(volatile uint8_t *)0x4006A009 // UART Match Address Registers 2 #define UART0_C4 *(volatile uint8_t *)0x4006A00A // UART Control Register 4 #define UART0_C5 *(volatile uint8_t *)0x4006A00B // UART Control Register 5 #define UART0_ED *(volatile uint8_t *)0x4006A00C // UART Extended Data Register #define UART0_MODEM *(volatile uint8_t *)0x4006A00D // UART Modem Register #define UART0_IR *(volatile uint8_t *)0x4006A00E // UART Infrared Register #define UART0_PFIFO *(volatile uint8_t *)0x4006A010 // UART FIFO Parameters #define UART_PFIFO_TXFE (uint8_t)0x80 #define UART_PFIFO_RXFE (uint8_t)0x08 #define UART0_CFIFO *(volatile uint8_t *)0x4006A011 // UART FIFO Control Register #define UART_CFIFO_TXFLUSH (uint8_t)0x80 // #define UART_CFIFO_RXFLUSH (uint8_t)0x40 // #define UART_CFIFO_RXOFE (uint8_t)0x04 // #define UART_CFIFO_TXOFE (uint8_t)0x02 // #define UART_CFIFO_RXUFE (uint8_t)0x01 // #define UART0_SFIFO *(volatile uint8_t *)0x4006A012 // UART FIFO Status Register #define UART_SFIFO_TXEMPT (uint8_t)0x80 #define UART_SFIFO_RXEMPT (uint8_t)0x40 #define UART_SFIFO_RXOF (uint8_t)0x04 #define UART_SFIFO_TXOF (uint8_t)0x02 #define UART_SFIFO_RXUF (uint8_t)0x01 #define UART0_TWFIFO *(volatile uint8_t *)0x4006A013 // UART FIFO Transmit Watermark #define UART0_TCFIFO *(volatile uint8_t *)0x4006A014 // UART FIFO Transmit Count #define UART0_RWFIFO *(volatile uint8_t *)0x4006A015 // UART FIFO Receive Watermark #define UART0_RCFIFO *(volatile uint8_t *)0x4006A016 // UART FIFO Receive Count #define UART0_C7816 *(volatile uint8_t *)0x4006A018 // UART 7816 Control Register #define UART0_IE7816 *(volatile uint8_t *)0x4006A019 // UART 7816 Interrupt Enable Register #define UART0_IS7816 *(volatile uint8_t *)0x4006A01A // UART 7816 Interrupt Status Register #define UART0_WP7816T0 *(volatile uint8_t *)0x4006A01B // UART 7816 Wait Parameter Register #define UART0_WP7816T1 *(volatile uint8_t *)0x4006A01B // UART 7816 Wait Parameter Register #define UART0_WN7816 *(volatile uint8_t *)0x4006A01C // UART 7816 Wait N Register #define UART0_WF7816 *(volatile uint8_t *)0x4006A01D // UART 7816 Wait FD Register #define UART0_ET7816 *(volatile uint8_t *)0x4006A01E // UART 7816 Error Threshold Register #define UART0_TL7816 *(volatile uint8_t *)0x4006A01F // UART 7816 Transmit Length Register #define UART0_C6 *(volatile uint8_t *)0x4006A021 // UART CEA709.1-B Control Register 6 #define UART0_PCTH *(volatile uint8_t *)0x4006A022 // UART CEA709.1-B Packet Cycle Time Counter High #define UART0_PCTL *(volatile uint8_t *)0x4006A023 // UART CEA709.1-B Packet Cycle Time Counter Low #define UART0_B1T *(volatile uint8_t *)0x4006A024 // UART CEA709.1-B Beta1 Timer #define UART0_SDTH *(volatile uint8_t *)0x4006A025 // UART CEA709.1-B Secondary Delay Timer High #define UART0_SDTL *(volatile uint8_t *)0x4006A026 // UART CEA709.1-B Secondary Delay Timer Low #define UART0_PRE *(volatile uint8_t *)0x4006A027 // UART CEA709.1-B Preamble #define UART0_TPL *(volatile uint8_t *)0x4006A028 // UART CEA709.1-B Transmit Packet Length #define UART0_IE *(volatile uint8_t *)0x4006A029 // UART CEA709.1-B Interrupt Enable Register #define UART0_WB *(volatile uint8_t *)0x4006A02A // UART CEA709.1-B WBASE #define UART0_S3 *(volatile uint8_t *)0x4006A02B // UART CEA709.1-B Status Register #define UART0_S4 *(volatile uint8_t *)0x4006A02C // UART CEA709.1-B Status Register #define UART0_RPL *(volatile uint8_t *)0x4006A02D // UART CEA709.1-B Received Packet Length #define UART0_RPREL *(volatile uint8_t *)0x4006A02E // UART CEA709.1-B Received Preamble Length #define UART0_CPW *(volatile uint8_t *)0x4006A02F // UART CEA709.1-B Collision Pulse Width #define UART0_RIDT *(volatile uint8_t *)0x4006A030 // UART CEA709.1-B Receive Indeterminate Time #define UART0_TIDT *(volatile uint8_t *)0x4006A031 // UART CEA709.1-B Transmit Indeterminate Time #define UART1_BDH *(volatile uint8_t *)0x4006B000 // UART Baud Rate Registers: High #define UART1_BDL *(volatile uint8_t *)0x4006B001 // UART Baud Rate Registers: Low #define UART1_C1 *(volatile uint8_t *)0x4006B002 // UART Control Register 1 #define UART1_C2 *(volatile uint8_t *)0x4006B003 // UART Control Register 2 #define UART1_S1 *(volatile uint8_t *)0x4006B004 // UART Status Register 1 #define UART1_S2 *(volatile uint8_t *)0x4006B005 // UART Status Register 2 #define UART1_C3 *(volatile uint8_t *)0x4006B006 // UART Control Register 3 #define UART1_D *(volatile uint8_t *)0x4006B007 // UART Data Register #define UART1_MA1 *(volatile uint8_t *)0x4006B008 // UART Match Address Registers 1 #define UART1_MA2 *(volatile uint8_t *)0x4006B009 // UART Match Address Registers 2 #define UART1_C4 *(volatile uint8_t *)0x4006B00A // UART Control Register 4 #define UART1_C5 *(volatile uint8_t *)0x4006B00B // UART Control Register 5 #define UART1_ED *(volatile uint8_t *)0x4006B00C // UART Extended Data Register #define UART1_MODEM *(volatile uint8_t *)0x4006B00D // UART Modem Register #define UART1_IR *(volatile uint8_t *)0x4006B00E // UART Infrared Register #define UART1_PFIFO *(volatile uint8_t *)0x4006B010 // UART FIFO Parameters #define UART1_CFIFO *(volatile uint8_t *)0x4006B011 // UART FIFO Control Register #define UART1_SFIFO *(volatile uint8_t *)0x4006B012 // UART FIFO Status Register #define UART1_TWFIFO *(volatile uint8_t *)0x4006B013 // UART FIFO Transmit Watermark #define UART1_TCFIFO *(volatile uint8_t *)0x4006B014 // UART FIFO Transmit Count #define UART1_RWFIFO *(volatile uint8_t *)0x4006B015 // UART FIFO Receive Watermark #define UART1_RCFIFO *(volatile uint8_t *)0x4006B016 // UART FIFO Receive Count #define UART1_C7816 *(volatile uint8_t *)0x4006B018 // UART 7816 Control Register #define UART1_IE7816 *(volatile uint8_t *)0x4006B019 // UART 7816 Interrupt Enable Register #define UART1_IS7816 *(volatile uint8_t *)0x4006B01A // UART 7816 Interrupt Status Register #define UART1_WP7816T0 *(volatile uint8_t *)0x4006B01B // UART 7816 Wait Parameter Register #define UART1_WP7816T1 *(volatile uint8_t *)0x4006B01B // UART 7816 Wait Parameter Register #define UART1_WN7816 *(volatile uint8_t *)0x4006B01C // UART 7816 Wait N Register #define UART1_WF7816 *(volatile uint8_t *)0x4006B01D // UART 7816 Wait FD Register #define UART1_ET7816 *(volatile uint8_t *)0x4006B01E // UART 7816 Error Threshold Register #define UART1_TL7816 *(volatile uint8_t *)0x4006B01F // UART 7816 Transmit Length Register #define UART1_C6 *(volatile uint8_t *)0x4006B021 // UART CEA709.1-B Control Register 6 #define UART1_PCTH *(volatile uint8_t *)0x4006B022 // UART CEA709.1-B Packet Cycle Time Counter High #define UART1_PCTL *(volatile uint8_t *)0x4006B023 // UART CEA709.1-B Packet Cycle Time Counter Low #define UART1_B1T *(volatile uint8_t *)0x4006B024 // UART CEA709.1-B Beta1 Timer #define UART1_SDTH *(volatile uint8_t *)0x4006B025 // UART CEA709.1-B Secondary Delay Timer High #define UART1_SDTL *(volatile uint8_t *)0x4006B026 // UART CEA709.1-B Secondary Delay Timer Low #define UART1_PRE *(volatile uint8_t *)0x4006B027 // UART CEA709.1-B Preamble #define UART1_TPL *(volatile uint8_t *)0x4006B028 // UART CEA709.1-B Transmit Packet Length #define UART1_IE *(volatile uint8_t *)0x4006B029 // UART CEA709.1-B Interrupt Enable Register #define UART1_WB *(volatile uint8_t *)0x4006B02A // UART CEA709.1-B WBASE #define UART1_S3 *(volatile uint8_t *)0x4006B02B // UART CEA709.1-B Status Register #define UART1_S4 *(volatile uint8_t *)0x4006B02C // UART CEA709.1-B Status Register #define UART1_RPL *(volatile uint8_t *)0x4006B02D // UART CEA709.1-B Received Packet Length #define UART1_RPREL *(volatile uint8_t *)0x4006B02E // UART CEA709.1-B Received Preamble Length #define UART1_CPW *(volatile uint8_t *)0x4006B02F // UART CEA709.1-B Collision Pulse Width #define UART1_RIDT *(volatile uint8_t *)0x4006B030 // UART CEA709.1-B Receive Indeterminate Time #define UART1_TIDT *(volatile uint8_t *)0x4006B031 // UART CEA709.1-B Transmit Indeterminate Time #define UART2_BDH *(volatile uint8_t *)0x4006C000 // UART Baud Rate Registers: High #define UART2_BDL *(volatile uint8_t *)0x4006C001 // UART Baud Rate Registers: Low #define UART2_C1 *(volatile uint8_t *)0x4006C002 // UART Control Register 1 #define UART2_C2 *(volatile uint8_t *)0x4006C003 // UART Control Register 2 #define UART2_S1 *(volatile uint8_t *)0x4006C004 // UART Status Register 1 #define UART2_S2 *(volatile uint8_t *)0x4006C005 // UART Status Register 2 #define UART2_C3 *(volatile uint8_t *)0x4006C006 // UART Control Register 3 #define UART2_D *(volatile uint8_t *)0x4006C007 // UART Data Register #define UART2_MA1 *(volatile uint8_t *)0x4006C008 // UART Match Address Registers 1 #define UART2_MA2 *(volatile uint8_t *)0x4006C009 // UART Match Address Registers 2 #define UART2_C4 *(volatile uint8_t *)0x4006C00A // UART Control Register 4 #define UART2_C5 *(volatile uint8_t *)0x4006C00B // UART Control Register 5 #define UART2_ED *(volatile uint8_t *)0x4006C00C // UART Extended Data Register #define UART2_MODEM *(volatile uint8_t *)0x4006C00D // UART Modem Register #define UART2_IR *(volatile uint8_t *)0x4006C00E // UART Infrared Register #define UART2_PFIFO *(volatile uint8_t *)0x4006C010 // UART FIFO Parameters #define UART2_CFIFO *(volatile uint8_t *)0x4006C011 // UART FIFO Control Register #define UART2_SFIFO *(volatile uint8_t *)0x4006C012 // UART FIFO Status Register #define UART2_TWFIFO *(volatile uint8_t *)0x4006C013 // UART FIFO Transmit Watermark #define UART2_TCFIFO *(volatile uint8_t *)0x4006C014 // UART FIFO Transmit Count #define UART2_RWFIFO *(volatile uint8_t *)0x4006C015 // UART FIFO Receive Watermark #define UART2_RCFIFO *(volatile uint8_t *)0x4006C016 // UART FIFO Receive Count #define UART2_C7816 *(volatile uint8_t *)0x4006C018 // UART 7816 Control Register #define UART2_IE7816 *(volatile uint8_t *)0x4006C019 // UART 7816 Interrupt Enable Register #define UART2_IS7816 *(volatile uint8_t *)0x4006C01A // UART 7816 Interrupt Status Register #define UART2_WP7816T0 *(volatile uint8_t *)0x4006C01B // UART 7816 Wait Parameter Register #define UART2_WP7816T1 *(volatile uint8_t *)0x4006C01B // UART 7816 Wait Parameter Register #define UART2_WN7816 *(volatile uint8_t *)0x4006C01C // UART 7816 Wait N Register #define UART2_WF7816 *(volatile uint8_t *)0x4006C01D // UART 7816 Wait FD Register #define UART2_ET7816 *(volatile uint8_t *)0x4006C01E // UART 7816 Error Threshold Register #define UART2_TL7816 *(volatile uint8_t *)0x4006C01F // UART 7816 Transmit Length Register #define UART2_C6 *(volatile uint8_t *)0x4006C021 // UART CEA709.1-B Control Register 6 #define UART2_PCTH *(volatile uint8_t *)0x4006C022 // UART CEA709.1-B Packet Cycle Time Counter High #define UART2_PCTL *(volatile uint8_t *)0x4006C023 // UART CEA709.1-B Packet Cycle Time Counter Low #define UART2_B1T *(volatile uint8_t *)0x4006C024 // UART CEA709.1-B Beta1 Timer #define UART2_SDTH *(volatile uint8_t *)0x4006C025 // UART CEA709.1-B Secondary Delay Timer High #define UART2_SDTL *(volatile uint8_t *)0x4006C026 // UART CEA709.1-B Secondary Delay Timer Low #define UART2_PRE *(volatile uint8_t *)0x4006C027 // UART CEA709.1-B Preamble #define UART2_TPL *(volatile uint8_t *)0x4006C028 // UART CEA709.1-B Transmit Packet Length #define UART2_IE *(volatile uint8_t *)0x4006C029 // UART CEA709.1-B Interrupt Enable Register #define UART2_WB *(volatile uint8_t *)0x4006C02A // UART CEA709.1-B WBASE #define UART2_S3 *(volatile uint8_t *)0x4006C02B // UART CEA709.1-B Status Register #define UART2_S4 *(volatile uint8_t *)0x4006C02C // UART CEA709.1-B Status Register #define UART2_RPL *(volatile uint8_t *)0x4006C02D // UART CEA709.1-B Received Packet Length #define UART2_RPREL *(volatile uint8_t *)0x4006C02E // UART CEA709.1-B Received Preamble Length #define UART2_CPW *(volatile uint8_t *)0x4006C02F // UART CEA709.1-B Collision Pulse Width #define UART2_RIDT *(volatile uint8_t *)0x4006C030 // UART CEA709.1-B Receive Indeterminate Time #define UART2_TIDT *(volatile uint8_t *)0x4006C031 // UART CEA709.1-B Transmit Indeterminate Time // Chapter 46: Synchronous Audio Interface (SAI) #define I2S0_TCSR *(volatile uint32_t *)0x4002F000 // SAI Transmit Control Register #define I2S_TCSR_TE (uint32_t)0x80000000 // Transmitter Enable #define I2S_TCSR_STOPE (uint32_t)0x40000000 // Transmitter Enable in Stop mode #define I2S_TCSR_DBGE (uint32_t)0x20000000 // Transmitter Enable in Debug mode #define I2S_TCSR_BCE (uint32_t)0x10000000 // Bit Clock Enable #define I2S_TCSR_FR (uint32_t)0x02000000 // FIFO Reset #define I2S_TCSR_SR (uint32_t)0x01000000 // Software Reset #define I2S_TCSR_WSF (uint32_t)0x00100000 // Word Start Flag #define I2S_TCSR_SEF (uint32_t)0x00080000 // Sync Error Flag #define I2S_TCSR_FEF (uint32_t)0x00040000 // FIFO Error Flag (underrun) #define I2S_TCSR_FWF (uint32_t)0x00020000 // FIFO Warning Flag (empty) #define I2S_TCSR_FRF (uint32_t)0x00010000 // FIFO Request Flag (Data Ready) #define I2S_TCSR_WSIE (uint32_t)0x00001000 // Word Start Interrupt Enable #define I2S_TCSR_SEIE (uint32_t)0x00000800 // Sync Error Interrupt Enable #define I2S_TCSR_FEIE (uint32_t)0x00000400 // FIFO Error Interrupt Enable #define I2S_TCSR_FWIE (uint32_t)0x00000200 // FIFO Warning Interrupt Enable #define I2S_TCSR_FRIE (uint32_t)0x00000100 // FIFO Request Interrupt Enable #define I2S_TCSR_FWDE (uint32_t)0x00000002 // FIFO Warning DMA Enable #define I2S_TCSR_FRDE (uint32_t)0x00000001 // FIFO Request DMA Enable #define I2S0_TCR1 *(volatile uint32_t *)0x4002F004 // SAI Transmit Configuration 1 Register #define I2S_TCR1_TFW(n) ((uint32_t)n & 0x03) // Transmit FIFO watermark #define I2S0_TCR2 *(volatile uint32_t *)0x4002F008 // SAI Transmit Configuration 2 Register #define I2S_TCR2_DIV(n) ((uint32_t)n & 0xff) // Bit clock divide by (DIV+1)*2 #define I2S_TCR2_BCD ((uint32_t)1<<24) // Bit clock direction #define I2S_TCR2_BCP ((uint32_t)1<<25) // Bit clock polarity #define I2S_TCR2_MSEL(n) ((uint32_t)(n & 3)<<26) // MCLK select, 0=bus clock, 1=I2S0_MCLK #define I2S_TCR2_BCI ((uint32_t)1<<28) // Bit clock input #define I2S_TCR2_BCS ((uint32_t)1<<29) // Bit clock swap #define I2S_TCR2_SYNC(n) ((uint32_t)(n & 3)<<30) // 0=async 1=sync with receiver #define I2S0_TCR3 *(volatile uint32_t *)0x4002F00C // SAI Transmit Configuration 3 Register #define I2S_TCR3_WDFL(n) ((uint32_t)n & 0x0f) // word flag configuration #define I2S_TCR3_TCE ((uint32_t)0x10000) // transmit channel enable #define I2S0_TCR4 *(volatile uint32_t *)0x4002F010 // SAI Transmit Configuration 4 Register #define I2S_TCR4_FSD ((uint32_t)1) // Frame Sync Direction #define I2S_TCR4_FSP ((uint32_t)2) // Frame Sync Polarity #define I2S_TCR4_FSE ((uint32_t)8) // Frame Sync Early #define I2S_TCR4_MF ((uint32_t)0x10) // MSB First #define I2S_TCR4_SYWD(n) ((uint32_t)(n & 0x1f)<<8) // Sync Width #define I2S_TCR4_FRSZ(n) ((uint32_t)(n & 0x0f)<<16) // Frame Size #define I2S0_TCR5 *(volatile uint32_t *)0x4002F014 // SAI Transmit Configuration 5 Register #define I2S_TCR5_FBT(n) ((uint32_t)(n & 0x1f)<<8) // First Bit Shifted #define I2S_TCR5_W0W(n) ((uint32_t)(n & 0x1f)<<16) // Word 0 Width #define I2S_TCR5_WNW(n) ((uint32_t)(n & 0x1f)<<24) // Word N Width #define I2S0_TDR0 *(volatile uint32_t *)0x4002F020 // SAI Transmit Data Register #define I2S0_TDR1 *(volatile uint32_t *)0x4002F024 // SAI Transmit Data Register #define I2S0_TFR0 *(volatile uint32_t *)0x4002F040 // SAI Transmit FIFO Register #define I2S0_TFR1 *(volatile uint32_t *)0x4002F044 // SAI Transmit FIFO Register #define I2S_TFR_RFP(n) ((uint32_t)n & 7) // read FIFO pointer #define I2S_TFR_WFP(n) ((uint32_t)(n & 7)<<16) // write FIFO pointer #define I2S0_TMR *(volatile uint32_t *)0x4002F060 // SAI Transmit Mask Register #define I2S_TMR_TWM(n) ((uint32_t)n & 0xFFFFFFFF) #define I2S0_RCSR *(volatile uint32_t *)0x4002F080 // SAI Receive Control Register #define I2S_RCSR_RE (uint32_t)0x80000000 // Receiver Enable #define I2S_RCSR_STOPE (uint32_t)0x40000000 // Receiver Enable in Stop mode #define I2S_RCSR_DBGE (uint32_t)0x20000000 // Receiver Enable in Debug mode #define I2S_RCSR_BCE (uint32_t)0x10000000 // Bit Clock Enable #define I2S_RCSR_FR (uint32_t)0x02000000 // FIFO Reset #define I2S_RCSR_SR (uint32_t)0x01000000 // Software Reset #define I2S_RCSR_WSF (uint32_t)0x00100000 // Word Start Flag #define I2S_RCSR_SEF (uint32_t)0x00080000 // Sync Error Flag #define I2S_RCSR_FEF (uint32_t)0x00040000 // FIFO Error Flag (underrun) #define I2S_RCSR_FWF (uint32_t)0x00020000 // FIFO Warning Flag (empty) #define I2S_RCSR_FRF (uint32_t)0x00010000 // FIFO Request Flag (Data Ready) #define I2S_RCSR_WSIE (uint32_t)0x00001000 // Word Start Interrupt Enable #define I2S_RCSR_SEIE (uint32_t)0x00000800 // Sync Error Interrupt Enable #define I2S_RCSR_FEIE (uint32_t)0x00000400 // FIFO Error Interrupt Enable #define I2S_RCSR_FWIE (uint32_t)0x00000200 // FIFO Warning Interrupt Enable #define I2S_RCSR_FRIE (uint32_t)0x00000100 // FIFO Request Interrupt Enable #define I2S_RCSR_FWDE (uint32_t)0x00000002 // FIFO Warning DMA Enable #define I2S_RCSR_FRDE (uint32_t)0x00000001 // FIFO Request DMA Enable #define I2S0_RCR1 *(volatile uint32_t *)0x4002F084 // SAI Receive Configuration 1 Register #define I2S_RCR1_RFW(n) ((uint32_t)n & 0x03) // Receive FIFO watermark #define I2S0_RCR2 *(volatile uint32_t *)0x4002F088 // SAI Receive Configuration 2 Register #define I2S_RCR2_DIV(n) ((uint32_t)n & 0xff) // Bit clock divide by (DIV+1)*2 #define I2S_RCR2_BCD ((uint32_t)1<<24) // Bit clock direction #define I2S_RCR2_BCP ((uint32_t)1<<25) // Bit clock polarity #define I2S_RCR2_MSEL(n) ((uint32_t)(n & 3)<<26) // MCLK select, 0=bus clock, 1=I2S0_MCLK #define I2S_RCR2_BCI ((uint32_t)1<<28) // Bit clock input #define I2S_RCR2_BCS ((uint32_t)1<<29) // Bit clock swap #define I2S_RCR2_SYNC(n) ((uint32_t)(n & 3)<<30) // 0=async 1=sync with receiver #define I2S0_RCR3 *(volatile uint32_t *)0x4002F08C // SAI Receive Configuration 3 Register #define I2S_RCR3_WDFL(n) ((uint32_t)n & 0x0f) // word flag configuration #define I2S_RCR3_RCE ((uint32_t)0x10000) // receive channel enable #define I2S0_RCR4 *(volatile uint32_t *)0x4002F090 // SAI Receive Configuration 4 Register #define I2S_RCR4_FSD ((uint32_t)1) // Frame Sync Direction #define I2S_RCR4_FSP ((uint32_t)2) // Frame Sync Polarity #define I2S_RCR4_FSE ((uint32_t)8) // Frame Sync Early #define I2S_RCR4_MF ((uint32_t)0x10) // MSB First #define I2S_RCR4_SYWD(n) ((uint32_t)(n & 0x1f)<<8) // Sync Width #define I2S_RCR4_FRSZ(n) ((uint32_t)(n & 0x0f)<<16) // Frame Size #define I2S0_RCR5 *(volatile uint32_t *)0x4002F094 // SAI Receive Configuration 5 Register #define I2S_RCR5_FBT(n) ((uint32_t)(n & 0x1f)<<8) // First Bit Shifted #define I2S_RCR5_W0W(n) ((uint32_t)(n & 0x1f)<<16) // Word 0 Width #define I2S_RCR5_WNW(n) ((uint32_t)(n & 0x1f)<<24) // Word N Width #define I2S0_RDR0 *(volatile uint32_t *)0x4002F0A0 // SAI Receive Data Register #define I2S0_RDR1 *(volatile uint32_t *)0x4002F0A4 // SAI Receive Data Register #define I2S0_RFR0 *(volatile uint32_t *)0x4002F0C0 // SAI Receive FIFO Register #define I2S0_RFR1 *(volatile uint32_t *)0x4002F0C4 // SAI Receive FIFO Register #define I2S_RFR_RFP(n) ((uint32_t)n & 7) // read FIFO pointer #define I2S_RFR_WFP(n) ((uint32_t)(n & 7)<<16) // write FIFO pointer #define I2S0_RMR *(volatile uint32_t *)0x4002F0E0 // SAI Receive Mask Register #define I2S_RMR_RWM(n) ((uint32_t)n & 0xFFFFFFFF) #define I2S0_MCR *(volatile uint32_t *)0x4002F100 // SAI MCLK Control Register #define I2S_MCR_DUF ((uint32_t)1<<31) // Divider Update Flag #define I2S_MCR_MOE ((uint32_t)1<<30) // MCLK Output Enable #define I2S_MCR_MICS(n) ((uint32_t)(n & 3)<<24) // MCLK Input Clock Select #define I2S0_MDR *(volatile uint32_t *)0x4002F104 // SAI MCLK Divide Register #define I2S_MDR_FRACT(n) ((uint32_t)(n & 0xff)<<12) // MCLK Fraction #define I2S_MDR_DIVIDE(n) ((uint32_t)(n & 0xfff)) // MCLK Divide // Chapter 47: General-Purpose Input/Output (GPIO) #define GPIOA_PDOR *(volatile uint32_t *)0x400FF000 // Port Data Output Register #define GPIOA_PSOR *(volatile uint32_t *)0x400FF004 // Port Set Output Register #define GPIOA_PCOR *(volatile uint32_t *)0x400FF008 // Port Clear Output Register #define GPIOA_PTOR *(volatile uint32_t *)0x400FF00C // Port Toggle Output Register #define GPIOA_PDIR *(volatile uint32_t *)0x400FF010 // Port Data Input Register #define GPIOA_PDDR *(volatile uint32_t *)0x400FF014 // Port Data Direction Register #define GPIOB_PDOR *(volatile uint32_t *)0x400FF040 // Port Data Output Register #define GPIOB_PSOR *(volatile uint32_t *)0x400FF044 // Port Set Output Register #define GPIOB_PCOR *(volatile uint32_t *)0x400FF048 // Port Clear Output Register #define GPIOB_PTOR *(volatile uint32_t *)0x400FF04C // Port Toggle Output Register #define GPIOB_PDIR *(volatile uint32_t *)0x400FF050 // Port Data Input Register #define GPIOB_PDDR *(volatile uint32_t *)0x400FF054 // Port Data Direction Register #define GPIOC_PDOR *(volatile uint32_t *)0x400FF080 // Port Data Output Register #define GPIOC_PSOR *(volatile uint32_t *)0x400FF084 // Port Set Output Register #define GPIOC_PCOR *(volatile uint32_t *)0x400FF088 // Port Clear Output Register #define GPIOC_PTOR *(volatile uint32_t *)0x400FF08C // Port Toggle Output Register #define GPIOC_PDIR *(volatile uint32_t *)0x400FF090 // Port Data Input Register #define GPIOC_PDDR *(volatile uint32_t *)0x400FF094 // Port Data Direction Register #define GPIOD_PDOR *(volatile uint32_t *)0x400FF0C0 // Port Data Output Register #define GPIOD_PSOR *(volatile uint32_t *)0x400FF0C4 // Port Set Output Register #define GPIOD_PCOR *(volatile uint32_t *)0x400FF0C8 // Port Clear Output Register #define GPIOD_PTOR *(volatile uint32_t *)0x400FF0CC // Port Toggle Output Register #define GPIOD_PDIR *(volatile uint32_t *)0x400FF0D0 // Port Data Input Register #define GPIOD_PDDR *(volatile uint32_t *)0x400FF0D4 // Port Data Direction Register #define GPIOE_PDOR *(volatile uint32_t *)0x400FF100 // Port Data Output Register #define GPIOE_PSOR *(volatile uint32_t *)0x400FF104 // Port Set Output Register #define GPIOE_PCOR *(volatile uint32_t *)0x400FF108 // Port Clear Output Register #define GPIOE_PTOR *(volatile uint32_t *)0x400FF10C // Port Toggle Output Register #define GPIOE_PDIR *(volatile uint32_t *)0x400FF110 // Port Data Input Register #define GPIOE_PDDR *(volatile uint32_t *)0x400FF114 // Port Data Direction Register // Chapter 48: Touch sense input (TSI) #define TSI0_GENCS *(volatile uint32_t *)0x40045000 // General Control and Status Register #define TSI_GENCS_LPCLKS (uint32_t)0x10000000 // #define TSI_GENCS_LPSCNITV(n) (((n) & 15) << 24) // #define TSI_GENCS_NSCN(n) (((n) & 31) << 19) // #define TSI_GENCS_PS(n) (((n) & 7) << 16) // #define TSI_GENCS_EOSF (uint32_t)0x00008000 // #define TSI_GENCS_OUTRGF (uint32_t)0x00004000 // #define TSI_GENCS_EXTERF (uint32_t)0x00002000 // #define TSI_GENCS_OVRF (uint32_t)0x00001000 // #define TSI_GENCS_SCNIP (uint32_t)0x00000200 // #define TSI_GENCS_SWTS (uint32_t)0x00000100 // #define TSI_GENCS_TSIEN (uint32_t)0x00000080 // #define TSI_GENCS_TSIIE (uint32_t)0x00000040 // #define TSI_GENCS_ERIE (uint32_t)0x00000020 // #define TSI_GENCS_ESOR (uint32_t)0x00000010 // #define TSI_GENCS_STM (uint32_t)0x00000002 // #define TSI_GENCS_STPE (uint32_t)0x00000001 // #define TSI0_SCANC *(volatile uint32_t *)0x40045004 // SCAN Control Register #define TSI_SCANC_REFCHRG(n) (((n) & 15) << 24) // #define TSI_SCANC_EXTCHRG(n) (((n) & 7) << 16) // #define TSI_SCANC_SMOD(n) (((n) & 255) << 8) // #define TSI_SCANC_AMCLKS(n) (((n) & 3) << 3) // #define TSI_SCANC_AMPSC(n) (((n) & 7) << 0) // #define TSI0_PEN *(volatile uint32_t *)0x40045008 // Pin Enable Register #define TSI0_WUCNTR *(volatile uint32_t *)0x4004500C // Wake-Up Channel Counter Register #define TSI0_CNTR1 *(volatile uint32_t *)0x40045100 // Counter Register #define TSI0_CNTR3 *(volatile uint32_t *)0x40045104 // Counter Register #define TSI0_CNTR5 *(volatile uint32_t *)0x40045108 // Counter Register #define TSI0_CNTR7 *(volatile uint32_t *)0x4004510C // Counter Register #define TSI0_CNTR9 *(volatile uint32_t *)0x40045110 // Counter Register #define TSI0_CNTR11 *(volatile uint32_t *)0x40045114 // Counter Register #define TSI0_CNTR13 *(volatile uint32_t *)0x40045118 // Counter Register #define TSI0_CNTR15 *(volatile uint32_t *)0x4004511C // Counter Register #define TSI0_THRESHOLD *(volatile uint32_t *)0x40045120 // Low Power Channel Threshold Register // Nested Vectored Interrupt Controller, Table 3-4 & ARMv7 ref, appendix B3.4 (page 750) #define NVIC_ENABLE_IRQ(n) (*((volatile uint32_t *)0xE000E100 + (n >> 5)) = (1 << (n & 31))) #define NVIC_DISABLE_IRQ(n) (*((volatile uint32_t *)0xE000E180 + (n >> 5)) = (1 << (n & 31))) #define NVIC_SET_PENDING(n) (*((volatile uint32_t *)0xE000E200 + (n >> 5)) = (1 << (n & 31))) #define NVIC_CLEAR_PENDING(n) (*((volatile uint32_t *)0xE000E280 + (n >> 5)) = (1 << (n & 31))) #define NVIC_ISER0 *(volatile uint32_t *)0xE000E100 #define NVIC_ISER1 *(volatile uint32_t *)0xE000E104 #define NVIC_ICER0 *(volatile uint32_t *)0xE000E180 #define NVIC_ICER1 *(volatile uint32_t *)0xE000E184 // 0 = highest priority // Cortex-M4: 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240 // Cortex-M0: 0,64,128,192 #define NVIC_SET_PRIORITY(irqnum, priority) (*((volatile uint8_t *)0xE000E400 + (irqnum)) = (uint8_t)(priority)) #define NVIC_GET_PRIORITY(irqnum) (*((uint8_t *)0xE000E400 + (irqnum))) #if defined(__MK20DX128__) #define IRQ_DMA_CH0 0 #define IRQ_DMA_CH1 1 #define IRQ_DMA_CH2 2 #define IRQ_DMA_CH3 3 #define IRQ_DMA_ERROR 4 #define IRQ_FTFL_COMPLETE 6 #define IRQ_FTFL_COLLISION 7 #define IRQ_LOW_VOLTAGE 8 #define IRQ_LLWU 9 #define IRQ_WDOG 10 #define IRQ_I2C0 11 #define IRQ_SPI0 12 #define IRQ_I2S0_TX 13 #define IRQ_I2S0_RX 14 #define IRQ_UART0_LON 15 #define IRQ_UART0_STATUS 16 #define IRQ_UART0_ERROR 17 #define IRQ_UART1_STATUS 18 #define IRQ_UART1_ERROR 19 #define IRQ_UART2_STATUS 20 #define IRQ_UART2_ERROR 21 #define IRQ_ADC0 22 #define IRQ_CMP0 23 #define IRQ_CMP1 24 #define IRQ_FTM0 25 #define IRQ_FTM1 26 #define IRQ_CMT 27 #define IRQ_RTC_ALARM 28 #define IRQ_RTC_SECOND 29 #define IRQ_PIT_CH0 30 #define IRQ_PIT_CH1 31 #define IRQ_PIT_CH2 32 #define IRQ_PIT_CH3 33 #define IRQ_PDB 34 #define IRQ_USBOTG 35 #define IRQ_USBDCD 36 #define IRQ_TSI 37 #define IRQ_MCG 38 #define IRQ_LPTMR 39 #define IRQ_PORTA 40 #define IRQ_PORTB 41 #define IRQ_PORTC 42 #define IRQ_PORTD 43 #define IRQ_PORTE 44 #define IRQ_SOFTWARE 45 #define NVIC_NUM_INTERRUPTS 46 #elif defined(__MK20DX256__) #define IRQ_DMA_CH0 0 #define IRQ_DMA_CH1 1 #define IRQ_DMA_CH2 2 #define IRQ_DMA_CH3 3 #define IRQ_DMA_CH4 4 #define IRQ_DMA_CH5 5 #define IRQ_DMA_CH6 6 #define IRQ_DMA_CH7 7 #define IRQ_DMA_CH8 8 #define IRQ_DMA_CH9 9 #define IRQ_DMA_CH10 10 #define IRQ_DMA_CH11 11 #define IRQ_DMA_CH12 12 #define IRQ_DMA_CH13 13 #define IRQ_DMA_CH14 14 #define IRQ_DMA_CH15 15 #define IRQ_DMA_ERROR 16 #define IRQ_FTFL_COMPLETE 18 #define IRQ_FTFL_COLLISION 19 #define IRQ_LOW_VOLTAGE 20 #define IRQ_LLWU 21 #define IRQ_WDOG 22 #define IRQ_I2C0 24 #define IRQ_I2C1 25 #define IRQ_SPI0 26 #define IRQ_SPI1 27 #define IRQ_CAN_MESSAGE 29 #define IRQ_CAN_BUS_OFF 30 #define IRQ_CAN_ERROR 31 #define IRQ_CAN_TX_WARN 32 #define IRQ_CAN_RX_WARN 33 #define IRQ_CAN_WAKEUP 34 #define IRQ_I2S0_TX 35 #define IRQ_I2S0_RX 36 #define IRQ_UART0_LON 44 #define IRQ_UART0_STATUS 45 #define IRQ_UART0_ERROR 46 #define IRQ_UART1_STATUS 47 #define IRQ_UART1_ERROR 48 #define IRQ_UART2_STATUS 49 #define IRQ_UART2_ERROR 50 #define IRQ_ADC0 57 #define IRQ_ADC1 58 #define IRQ_CMP0 59 #define IRQ_CMP1 60 #define IRQ_CMP2 61 #define IRQ_FTM0 62 #define IRQ_FTM1 63 #define IRQ_FTM2 64 #define IRQ_CMT 65 #define IRQ_RTC_ALARM 66 #define IRQ_RTC_SECOND 67 #define IRQ_PIT_CH0 68 #define IRQ_PIT_CH1 69 #define IRQ_PIT_CH2 70 #define IRQ_PIT_CH3 71 #define IRQ_PDB 72 #define IRQ_USBOTG 73 #define IRQ_USBDCD 74 #define IRQ_DAC0 81 #define IRQ_TSI 83 #define IRQ_MCG 84 #define IRQ_LPTMR 85 #define IRQ_PORTA 87 #define IRQ_PORTB 88 #define IRQ_PORTC 89 #define IRQ_PORTD 90 #define IRQ_PORTE 91 #define IRQ_SOFTWARE 94 #define NVIC_NUM_INTERRUPTS 95 #endif #define __disable_irq() __asm__ volatile("CPSID i"); #define __enable_irq() __asm__ volatile("CPSIE i"); // System Control Space (SCS), ARMv7 ref manual, B3.2, page 708 #define SCB_CPUID *(const uint32_t *)0xE000ED00 // CPUID Base Register #define SCB_ICSR *(volatile uint32_t *)0xE000ED04 // Interrupt Control and State #define SCB_ICSR_PENDSTSET (uint32_t)0x04000000 #define SCB_VTOR *(volatile uint32_t *)0xE000ED08 // Vector Table Offset #define SCB_AIRCR *(volatile uint32_t *)0xE000ED0C // Application Interrupt and Reset Control #define SCB_SCR *(volatile uint32_t *)0xE000ED10 // System Control Register #define SCB_CCR *(volatile uint32_t *)0xE000ED14 // Configuration and Control #define SCB_SHPR1 *(volatile uint32_t *)0xE000ED18 // System Handler Priority Register 1 #define SCB_SHPR2 *(volatile uint32_t *)0xE000ED1C // System Handler Priority Register 2 #define SCB_SHPR3 *(volatile uint32_t *)0xE000ED20 // System Handler Priority Register 3 #define SCB_SHCSR *(volatile uint32_t *)0xE000ED24 // System Handler Control and State #define SCB_CFSR *(volatile uint32_t *)0xE000ED28 // Configurable Fault Status Register #define SCB_HFSR *(volatile uint32_t *)0xE000ED2C // HardFault Status #define SCB_DFSR *(volatile uint32_t *)0xE000ED30 // Debug Fault Status #define SCB_MMFAR *(volatile uint32_t *)0xE000ED34 // MemManage Fault Address #define SYST_CSR *(volatile uint32_t *)0xE000E010 // SysTick Control and Status #define SYST_CSR_COUNTFLAG (uint32_t)0x00010000 #define SYST_CSR_CLKSOURCE (uint32_t)0x00000004 #define SYST_CSR_TICKINT (uint32_t)0x00000002 #define SYST_CSR_ENABLE (uint32_t)0x00000001 #define SYST_RVR *(volatile uint32_t *)0xE000E014 // SysTick Reload Value Register #define SYST_CVR *(volatile uint32_t *)0xE000E018 // SysTick Current Value Register #define SYST_CALIB *(const uint32_t *)0xE000E01C // SysTick Calibration Value #define ARM_DEMCR *(volatile uint32_t *)0xE000EDFC // Debug Exception and Monitor Control #define ARM_DEMCR_TRCENA (1 << 24) // Enable debugging & monitoring blocks #define ARM_DWT_CTRL *(volatile uint32_t *)0xE0001000 // DWT control register #define ARM_DWT_CTRL_CYCCNTENA (1 << 0) // Enable cycle count #define ARM_DWT_CYCCNT *(volatile uint32_t *)0xE0001004 // Cycle count register extern int nvic_execution_priority(void); extern void nmi_isr(void); extern void hard_fault_isr(void); extern void memmanage_fault_isr(void); extern void bus_fault_isr(void); extern void usage_fault_isr(void); extern void svcall_isr(void); extern void debugmonitor_isr(void); extern void pendablesrvreq_isr(void); extern void systick_isr(void); extern void dma_ch0_isr(void); extern void dma_ch1_isr(void); extern void dma_ch2_isr(void); extern void dma_ch3_isr(void); extern void dma_ch4_isr(void); extern void dma_ch5_isr(void); extern void dma_ch6_isr(void); extern void dma_ch7_isr(void); extern void dma_ch8_isr(void); extern void dma_ch9_isr(void); extern void dma_ch10_isr(void); extern void dma_ch11_isr(void); extern void dma_ch12_isr(void); extern void dma_ch13_isr(void); extern void dma_ch14_isr(void); extern void dma_ch15_isr(void); extern void dma_error_isr(void); extern void mcm_isr(void); extern void flash_cmd_isr(void); extern void flash_error_isr(void); extern void low_voltage_isr(void); extern void wakeup_isr(void); extern void watchdog_isr(void); extern void i2c0_isr(void); extern void i2c1_isr(void); extern void i2c2_isr(void); extern void spi0_isr(void); extern void spi1_isr(void); extern void spi2_isr(void); extern void sdhc_isr(void); extern void can0_message_isr(void); extern void can0_bus_off_isr(void); extern void can0_error_isr(void); extern void can0_tx_warn_isr(void); extern void can0_rx_warn_isr(void); extern void can0_wakeup_isr(void); extern void i2s0_tx_isr(void); extern void i2s0_rx_isr(void); extern void uart0_lon_isr(void); extern void uart0_status_isr(void); extern void uart0_error_isr(void); extern void uart1_status_isr(void); extern void uart1_error_isr(void); extern void uart2_status_isr(void); extern void uart2_error_isr(void); extern void uart3_status_isr(void); extern void uart3_error_isr(void); extern void uart4_status_isr(void); extern void uart4_error_isr(void); extern void uart5_status_isr(void); extern void uart5_error_isr(void); extern void adc0_isr(void); extern void adc1_isr(void); extern void cmp0_isr(void); extern void cmp1_isr(void); extern void cmp2_isr(void); extern void ftm0_isr(void); extern void ftm1_isr(void); extern void ftm2_isr(void); extern void ftm3_isr(void); extern void cmt_isr(void); extern void rtc_alarm_isr(void); extern void rtc_seconds_isr(void); extern void pit0_isr(void); extern void pit1_isr(void); extern void pit2_isr(void); extern void pit3_isr(void); extern void pdb_isr(void); extern void usb_isr(void); extern void usb_charge_isr(void); extern void dac0_isr(void); extern void dac1_isr(void); extern void tsi0_isr(void); extern void mcg_isr(void); extern void lptmr_isr(void); extern void porta_isr(void); extern void portb_isr(void); extern void portc_isr(void); extern void portd_isr(void); extern void porte_isr(void); extern void software_isr(void); #ifdef __cplusplus } #endif #endif micropython-1.12/ports/teensy/core/pins_arduino.h000066400000000000000000000101211357706137100222660ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef pins_macros_for_arduino_compatibility_h #define pins_macros_for_arduino_compatibility_h #include const static uint8_t A0 = 14; const static uint8_t A1 = 15; const static uint8_t A2 = 16; const static uint8_t A3 = 17; const static uint8_t A4 = 18; const static uint8_t A5 = 19; const static uint8_t A6 = 20; const static uint8_t A7 = 21; const static uint8_t A8 = 22; const static uint8_t A9 = 23; const static uint8_t A10 = 34; const static uint8_t A11 = 35; const static uint8_t A12 = 36; const static uint8_t A13 = 37; const static uint8_t A14 = 40; const static uint8_t A15 = 26; const static uint8_t A16 = 27; const static uint8_t A17 = 28; const static uint8_t A18 = 29; const static uint8_t A19 = 30; const static uint8_t A20 = 31; const static uint8_t SS = 10; const static uint8_t MOSI = 11; const static uint8_t MISO = 12; const static uint8_t SCK = 13; const static uint8_t LED_BUILTIN = 13; const static uint8_t SDA = 18; const static uint8_t SCL = 19; #define NUM_DIGITAL_PINS 34 #define NUM_ANALOG_INPUTS 14 #define analogInputToDigitalPin(p) (((p) < 10) ? (p) + 14 : -1) #define digitalPinHasPWM(p) (((p) >= 3 && (p) <= 6) || (p) == 9 || (p) == 10 || ((p) >= 20 && (p) <= 23)) #define NOT_AN_INTERRUPT -1 #define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1) struct digital_pin_bitband_and_config_table_struct { volatile uint32_t *reg; volatile uint32_t *config; }; extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[]; // compatibility macros #define digitalPinToPort(pin) (pin) #define digitalPinToBitMask(pin) (1) #define portOutputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 0)) #define portSetRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 32)) #define portClearRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 64)) #define portToggleRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 96)) #define portInputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 128)) #define portModeRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 160)) #define portConfigRegister(pin) ((volatile uint32_t *)(digital_pin_to_info_PGM[(pin)].config)) #define digitalPinToPortReg(pin) (portOutputRegister(pin)) #define digitalPinToBit(pin) (1) #define NOT_ON_TIMER 0 static inline uint8_t digitalPinToTimer(uint8_t) __attribute__((always_inline, unused)); static inline uint8_t digitalPinToTimer(uint8_t pin) { if (pin >= 3 && pin <= 6) return pin - 2; if (pin >= 9 && pin <= 10) return pin - 4; if (pin >= 20 && pin <= 23) return pin - 13; return NOT_ON_TIMER; } #endif micropython-1.12/ports/teensy/core/pins_teensy.c000066400000000000000000000562631357706137100221500ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "core_pins.h" #include "pins_arduino.h" #include "HardwareSerial.h" #if 0 // moved to pins_arduino.h struct digital_pin_bitband_and_config_table_struct { volatile uint32_t *reg; volatile uint32_t *config; }; const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[]; // compatibility macros #define digitalPinToPort(pin) (pin) #define digitalPinToBitMask(pin) (1) #define portOutputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 0)) #define portSetRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 32)) #define portClearRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 64)) #define portToggleRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 96)) #define portInputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 128)) #define portModeRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 160)) #define portConfigRegister(pin) ((volatile uint32_t *)(digital_pin_to_info_PGM[(pin)].config)) #endif //#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) //#define analogInPinToBit(P) (P) #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) //#define GPIO_SET_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 1) //#define GPIO_CLR_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 0) const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[] = { {GPIO_BITBAND_PTR(CORE_PIN0_PORTREG, CORE_PIN0_BIT), &CORE_PIN0_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN1_PORTREG, CORE_PIN1_BIT), &CORE_PIN1_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN2_PORTREG, CORE_PIN2_BIT), &CORE_PIN2_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN3_PORTREG, CORE_PIN3_BIT), &CORE_PIN3_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN4_PORTREG, CORE_PIN4_BIT), &CORE_PIN4_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN5_PORTREG, CORE_PIN5_BIT), &CORE_PIN5_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN6_PORTREG, CORE_PIN6_BIT), &CORE_PIN6_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN7_PORTREG, CORE_PIN7_BIT), &CORE_PIN7_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN8_PORTREG, CORE_PIN8_BIT), &CORE_PIN8_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN9_PORTREG, CORE_PIN9_BIT), &CORE_PIN9_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN10_PORTREG, CORE_PIN10_BIT), &CORE_PIN10_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN11_PORTREG, CORE_PIN11_BIT), &CORE_PIN11_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN12_PORTREG, CORE_PIN12_BIT), &CORE_PIN12_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN13_PORTREG, CORE_PIN13_BIT), &CORE_PIN13_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN14_PORTREG, CORE_PIN14_BIT), &CORE_PIN14_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN15_PORTREG, CORE_PIN15_BIT), &CORE_PIN15_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN16_PORTREG, CORE_PIN16_BIT), &CORE_PIN16_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN17_PORTREG, CORE_PIN17_BIT), &CORE_PIN17_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN18_PORTREG, CORE_PIN18_BIT), &CORE_PIN18_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN19_PORTREG, CORE_PIN19_BIT), &CORE_PIN19_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN20_PORTREG, CORE_PIN20_BIT), &CORE_PIN20_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN21_PORTREG, CORE_PIN21_BIT), &CORE_PIN21_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN22_PORTREG, CORE_PIN22_BIT), &CORE_PIN22_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN23_PORTREG, CORE_PIN23_BIT), &CORE_PIN23_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN24_PORTREG, CORE_PIN24_BIT), &CORE_PIN24_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN25_PORTREG, CORE_PIN25_BIT), &CORE_PIN25_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN26_PORTREG, CORE_PIN26_BIT), &CORE_PIN26_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN27_PORTREG, CORE_PIN27_BIT), &CORE_PIN27_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN28_PORTREG, CORE_PIN28_BIT), &CORE_PIN28_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN29_PORTREG, CORE_PIN29_BIT), &CORE_PIN29_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN30_PORTREG, CORE_PIN30_BIT), &CORE_PIN30_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN31_PORTREG, CORE_PIN31_BIT), &CORE_PIN31_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN32_PORTREG, CORE_PIN32_BIT), &CORE_PIN32_CONFIG}, {GPIO_BITBAND_PTR(CORE_PIN33_PORTREG, CORE_PIN33_BIT), &CORE_PIN33_CONFIG} }; typedef void (*voidFuncPtr)(void); volatile static voidFuncPtr intFunc[CORE_NUM_DIGITAL]; void init_pin_interrupts(void) { //SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO NVIC_ENABLE_IRQ(IRQ_PORTA); NVIC_ENABLE_IRQ(IRQ_PORTB); NVIC_ENABLE_IRQ(IRQ_PORTC); NVIC_ENABLE_IRQ(IRQ_PORTD); NVIC_ENABLE_IRQ(IRQ_PORTE); // TODO: maybe these should be set to a lower priority // so if the user puts lots of slow code on attachInterrupt // fast interrupts will still be serviced quickly? } void attachInterrupt(uint8_t pin, void (*function)(void), int mode) { volatile uint32_t *config; uint32_t cfg, mask; if (pin >= CORE_NUM_DIGITAL) return; switch (mode) { case CHANGE: mask = 0x0B; break; case RISING: mask = 0x09; break; case FALLING: mask = 0x0A; break; case LOW: mask = 0x08; break; case HIGH: mask = 0x0C; break; default: return; } mask = (mask << 16) | 0x01000000; config = portConfigRegister(pin); __disable_irq(); cfg = *config; cfg &= ~0x000F0000; // disable any previous interrupt *config = cfg; intFunc[pin] = function; // set the function pointer cfg |= mask; *config = cfg; // enable the new interrupt __enable_irq(); } void detachInterrupt(uint8_t pin) { volatile uint32_t *config; config = portConfigRegister(pin); __disable_irq(); *config = ((*config & ~0x000F0000) | 0x01000000); intFunc[pin] = NULL; __enable_irq(); } void porta_isr(void) { uint32_t isfr = PORTA_ISFR; PORTA_ISFR = isfr; if ((isfr & CORE_PIN3_BITMASK) && intFunc[3]) intFunc[3](); if ((isfr & CORE_PIN4_BITMASK) && intFunc[4]) intFunc[4](); if ((isfr & CORE_PIN24_BITMASK) && intFunc[24]) intFunc[24](); if ((isfr & CORE_PIN33_BITMASK) && intFunc[33]) intFunc[33](); } void portb_isr(void) { uint32_t isfr = PORTB_ISFR; PORTB_ISFR = isfr; if ((isfr & CORE_PIN0_BITMASK) && intFunc[0]) intFunc[0](); if ((isfr & CORE_PIN1_BITMASK) && intFunc[1]) intFunc[1](); if ((isfr & CORE_PIN16_BITMASK) && intFunc[16]) intFunc[16](); if ((isfr & CORE_PIN17_BITMASK) && intFunc[17]) intFunc[17](); if ((isfr & CORE_PIN18_BITMASK) && intFunc[18]) intFunc[18](); if ((isfr & CORE_PIN19_BITMASK) && intFunc[19]) intFunc[19](); if ((isfr & CORE_PIN25_BITMASK) && intFunc[25]) intFunc[25](); if ((isfr & CORE_PIN32_BITMASK) && intFunc[32]) intFunc[32](); } void portc_isr(void) { // TODO: these are inefficent. Use CLZ somehow.... uint32_t isfr = PORTC_ISFR; PORTC_ISFR = isfr; if ((isfr & CORE_PIN9_BITMASK) && intFunc[9]) intFunc[9](); if ((isfr & CORE_PIN10_BITMASK) && intFunc[10]) intFunc[10](); if ((isfr & CORE_PIN11_BITMASK) && intFunc[11]) intFunc[11](); if ((isfr & CORE_PIN12_BITMASK) && intFunc[12]) intFunc[12](); if ((isfr & CORE_PIN13_BITMASK) && intFunc[13]) intFunc[13](); if ((isfr & CORE_PIN15_BITMASK) && intFunc[15]) intFunc[15](); if ((isfr & CORE_PIN22_BITMASK) && intFunc[22]) intFunc[22](); if ((isfr & CORE_PIN23_BITMASK) && intFunc[23]) intFunc[23](); if ((isfr & CORE_PIN27_BITMASK) && intFunc[27]) intFunc[27](); if ((isfr & CORE_PIN28_BITMASK) && intFunc[28]) intFunc[28](); if ((isfr & CORE_PIN29_BITMASK) && intFunc[29]) intFunc[29](); if ((isfr & CORE_PIN30_BITMASK) && intFunc[30]) intFunc[30](); } void portd_isr(void) { uint32_t isfr = PORTD_ISFR; PORTD_ISFR = isfr; if ((isfr & CORE_PIN2_BITMASK) && intFunc[2]) intFunc[2](); if ((isfr & CORE_PIN5_BITMASK) && intFunc[5]) intFunc[5](); if ((isfr & CORE_PIN6_BITMASK) && intFunc[6]) intFunc[6](); if ((isfr & CORE_PIN7_BITMASK) && intFunc[7]) intFunc[7](); if ((isfr & CORE_PIN8_BITMASK) && intFunc[8]) intFunc[8](); if ((isfr & CORE_PIN14_BITMASK) && intFunc[14]) intFunc[14](); if ((isfr & CORE_PIN20_BITMASK) && intFunc[20]) intFunc[20](); if ((isfr & CORE_PIN21_BITMASK) && intFunc[21]) intFunc[21](); } void porte_isr(void) { uint32_t isfr = PORTE_ISFR; PORTE_ISFR = isfr; if ((isfr & CORE_PIN26_BITMASK) && intFunc[26]) intFunc[26](); if ((isfr & CORE_PIN31_BITMASK) && intFunc[31]) intFunc[31](); } unsigned long rtc_get(void) { return RTC_TSR; } void rtc_set(unsigned long t) { RTC_SR = 0; RTC_TPR = 0; RTC_TSR = t; RTC_SR = RTC_SR_TCE; } // adjust is the amount of crystal error to compensate, 1 = 0.1192 ppm // For example, adjust = -100 is slows the clock by 11.92 ppm // void rtc_compensate(int adjust) { uint32_t comp, interval, tcr; // This simple approach tries to maximize the interval. // Perhaps minimizing TCR would be better, so the // compensation is distributed more evenly across // many seconds, rather than saving it all up and then // altering one second up to +/- 0.38% if (adjust >= 0) { comp = adjust; interval = 256; while (1) { tcr = comp * interval; if (tcr < 128*256) break; if (--interval == 1) break; } tcr = tcr >> 8; } else { comp = -adjust; interval = 256; while (1) { tcr = comp * interval; if (tcr < 129*256) break; if (--interval == 1) break; } tcr = tcr >> 8; tcr = 256 - tcr; } RTC_TCR = ((interval - 1) << 8) | tcr; } #if 0 // TODO: build system should define this // so RTC is automatically initialized to approx correct time // at least when the program begins running right after upload #ifndef TIME_T #define TIME_T 1350160272 #endif void init_rtc(void) { serial_print("init_rtc\n"); //SIM_SCGC6 |= SIM_SCGC6_RTC; // enable the RTC crystal oscillator, for approx 12pf crystal if (!(RTC_CR & RTC_CR_OSCE)) { serial_print("start RTC oscillator\n"); RTC_SR = 0; RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE; } // should wait for crystal to stabilize..... serial_print("SR="); serial_phex32(RTC_SR); serial_print("\n"); serial_print("CR="); serial_phex32(RTC_CR); serial_print("\n"); serial_print("TSR="); serial_phex32(RTC_TSR); serial_print("\n"); serial_print("TCR="); serial_phex32(RTC_TCR); serial_print("\n"); if (RTC_SR & RTC_SR_TIF) { // enable the RTC RTC_SR = 0; RTC_TPR = 0; RTC_TSR = TIME_T; RTC_SR = RTC_SR_TCE; } } #endif extern void usb_init(void); // create a default PWM at the same 488.28 Hz as Arduino Uno #if F_BUS == 60000000 #define DEFAULT_FTM_MOD (61440 - 1) #define DEFAULT_FTM_PRESCALE 1 #elif F_BUS == 56000000 #define DEFAULT_FTM_MOD (57344 - 1) #define DEFAULT_FTM_PRESCALE 1 #elif F_BUS == 48000000 #define DEFAULT_FTM_MOD (49152 - 1) #define DEFAULT_FTM_PRESCALE 1 #elif F_BUS == 40000000 #define DEFAULT_FTM_MOD (40960 - 1) #define DEFAULT_FTM_PRESCALE 1 #elif F_BUS == 36000000 #define DEFAULT_FTM_MOD (36864 - 1) #define DEFAULT_FTM_PRESCALE 1 #elif F_BUS == 24000000 #define DEFAULT_FTM_MOD (49152 - 1) #define DEFAULT_FTM_PRESCALE 0 #elif F_BUS == 16000000 #define DEFAULT_FTM_MOD (32768 - 1) #define DEFAULT_FTM_PRESCALE 0 #elif F_BUS == 8000000 #define DEFAULT_FTM_MOD (16384 - 1) #define DEFAULT_FTM_PRESCALE 0 #elif F_BUS == 4000000 #define DEFAULT_FTM_MOD (8192 - 1) #define DEFAULT_FTM_PRESCALE 0 #elif F_BUS == 2000000 #define DEFAULT_FTM_MOD (4096 - 1) #define DEFAULT_FTM_PRESCALE 0 #endif //void init_pins(void) void _init_Teensyduino_internal_(void) { init_pin_interrupts(); //SIM_SCGC6 |= SIM_SCGC6_FTM0; // TODO: use bitband for atomic read-mod-write //SIM_SCGC6 |= SIM_SCGC6_FTM1; FTM0_CNT = 0; FTM0_MOD = DEFAULT_FTM_MOD; FTM0_C0SC = 0x28; // MSnB:MSnA = 10, ELSnB:ELSnA = 10 FTM0_C1SC = 0x28; FTM0_C2SC = 0x28; FTM0_C3SC = 0x28; FTM0_C4SC = 0x28; FTM0_C5SC = 0x28; FTM0_C6SC = 0x28; FTM0_C7SC = 0x28; FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE); FTM1_CNT = 0; FTM1_MOD = DEFAULT_FTM_MOD; FTM1_C0SC = 0x28; FTM1_C1SC = 0x28; FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE); #if defined(__MK20DX256__) FTM2_CNT = 0; FTM2_MOD = DEFAULT_FTM_MOD; FTM2_C0SC = 0x28; FTM2_C1SC = 0x28; FTM2_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE); #endif analog_init(); //delay(100); // TODO: this is not necessary, right? delay(4); usb_init(); } static uint8_t analog_write_res = 8; // SOPT4 is SIM select clocks? // FTM is clocked by the bus clock, either 24 or 48 MHz // input capture can be FTM1_CH0, CMP0 or CMP1 or USB start of frame // 24 MHz with reload 49152 to match Arduino's speed = 488.28125 Hz void analogWrite(uint8_t pin, int val) { uint32_t cval, max; #if defined(__MK20DX256__) if (pin == A14) { uint8_t res = analog_write_res; if (res < 12) { val <<= 12 - res; } else if (res > 12) { val >>= res - 12; } analogWriteDAC0(val); return; } #endif max = 1 << analog_write_res; if (val <= 0) { digitalWrite(pin, LOW); pinMode(pin, OUTPUT); // TODO: implement OUTPUT_LOW return; } else if (val >= max) { digitalWrite(pin, HIGH); pinMode(pin, OUTPUT); // TODO: implement OUTPUT_HIGH return; } //serial_print("analogWrite\n"); //serial_print("val = "); //serial_phex32(val); //serial_print("\n"); //serial_print("analog_write_res = "); //serial_phex(analog_write_res); //serial_print("\n"); if (pin == 3 || pin == 4) { cval = ((uint32_t)val * (uint32_t)(FTM1_MOD + 1)) >> analog_write_res; #if defined(__MK20DX256__) } else if (pin == 25 || pin == 32) { cval = ((uint32_t)val * (uint32_t)(FTM2_MOD + 1)) >> analog_write_res; #endif } else { cval = ((uint32_t)val * (uint32_t)(FTM0_MOD + 1)) >> analog_write_res; } //serial_print("cval = "); //serial_phex32(cval); //serial_print("\n"); switch (pin) { case 3: // PTA12, FTM1_CH0 FTM1_C0V = cval; CORE_PIN3_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 4: // PTA13, FTM1_CH1 FTM1_C1V = cval; CORE_PIN4_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 5: // PTD7, FTM0_CH7 FTM0_C7V = cval; CORE_PIN5_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 6: // PTD4, FTM0_CH4 FTM0_C4V = cval; CORE_PIN6_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 9: // PTC3, FTM0_CH2 FTM0_C2V = cval; CORE_PIN9_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 10: // PTC4, FTM0_CH3 FTM0_C3V = cval; CORE_PIN10_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 20: // PTD5, FTM0_CH5 FTM0_C5V = cval; CORE_PIN20_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 21: // PTD6, FTM0_CH6 FTM0_C6V = cval; CORE_PIN21_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 22: // PTC1, FTM0_CH0 FTM0_C0V = cval; CORE_PIN22_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 23: // PTC2, FTM0_CH1 FTM0_C1V = cval; CORE_PIN23_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; break; #if defined(__MK20DX256__) case 32: // PTB18, FTM2_CH0 FTM2_C0V = cval; CORE_PIN32_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; break; case 25: // PTB19, FTM1_CH1 FTM2_C1V = cval; CORE_PIN25_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; break; #endif default: digitalWrite(pin, (val > 127) ? HIGH : LOW); pinMode(pin, OUTPUT); } } void analogWriteRes(uint32_t bits) { if (bits < 1) { bits = 1; } else if (bits > 16) { bits = 16; } analog_write_res = bits; } void analogWriteFrequency(uint8_t pin, uint32_t frequency) { uint32_t minfreq, prescale, mod; //serial_print("analogWriteFrequency: pin = "); //serial_phex(pin); //serial_print(", freq = "); //serial_phex32(frequency); //serial_print("\n"); for (prescale = 0; prescale < 7; prescale++) { minfreq = (F_BUS >> 16) >> prescale; if (frequency > minfreq) break; } //serial_print("F_BUS = "); //serial_phex32(F_BUS >> prescale); //serial_print("\n"); //serial_print("prescale = "); //serial_phex(prescale); //serial_print("\n"); //mod = ((F_BUS >> prescale) / frequency) - 1; mod = (((F_BUS >> prescale) + (frequency >> 1)) / frequency) - 1; if (mod > 65535) mod = 65535; //serial_print("mod = "); //serial_phex32(mod); //serial_print("\n"); if (pin == 3 || pin == 4) { FTM1_SC = 0; FTM1_CNT = 0; FTM1_MOD = mod; FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(prescale); } else if (pin == 5 || pin == 6 || pin == 9 || pin == 10 || (pin >= 20 && pin <= 23)) { FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = mod; FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(prescale); } } // TODO: startup code needs to initialize all pins to GPIO mode, input by default void digitalWrite(uint8_t pin, uint8_t val) { if (pin >= CORE_NUM_DIGITAL) return; if (*portModeRegister(pin)) { if (val) { *portSetRegister(pin) = 1; } else { *portClearRegister(pin) = 1; } } else { volatile uint32_t *config = portConfigRegister(pin); if (val) { // TODO use bitband for atomic read-mod-write *config |= (PORT_PCR_PE | PORT_PCR_PS); //*config = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; } else { // TODO use bitband for atomic read-mod-write *config &= ~(PORT_PCR_PE); //*config = PORT_PCR_MUX(1); } } } uint8_t digitalRead(uint8_t pin) { if (pin >= CORE_NUM_DIGITAL) return 0; return *portInputRegister(pin); } void pinMode(uint8_t pin, uint8_t mode) { volatile uint32_t *config; if (pin >= CORE_NUM_DIGITAL) return; config = portConfigRegister(pin); if (mode == OUTPUT) { *portModeRegister(pin) = 1; *config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); } else { *portModeRegister(pin) = 0; if (mode == INPUT) { *config = PORT_PCR_MUX(1); } else { *config = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; // pullup } } } void _shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value) { if (bitOrder == LSBFIRST) { shiftOut_lsbFirst(dataPin, clockPin, value); } else { shiftOut_msbFirst(dataPin, clockPin, value); } } void shiftOut_lsbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value) { uint8_t mask; for (mask=0x01; mask; mask <<= 1) { digitalWrite(dataPin, value & mask); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } } void shiftOut_msbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value) { uint8_t mask; for (mask=0x80; mask; mask >>= 1) { digitalWrite(dataPin, value & mask); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } } uint8_t _shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { if (bitOrder == LSBFIRST) { return shiftIn_lsbFirst(dataPin, clockPin); } else { return shiftIn_msbFirst(dataPin, clockPin); } } uint8_t shiftIn_lsbFirst(uint8_t dataPin, uint8_t clockPin) { uint8_t mask, value=0; for (mask=0x01; mask; mask <<= 1) { digitalWrite(clockPin, HIGH); if (digitalRead(dataPin)) value |= mask; digitalWrite(clockPin, LOW); } return value; } uint8_t shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin) { uint8_t mask, value=0; for (mask=0x80; mask; mask >>= 1) { digitalWrite(clockPin, HIGH); if (digitalRead(dataPin)) value |= mask; digitalWrite(clockPin, LOW); } return value; } // the systick interrupt is supposed to increment this at 1 kHz rate volatile uint32_t systick_millis_count = 0; //uint32_t systick_current, systick_count, systick_istatus; // testing only uint32_t micros(void) { uint32_t count, current, istatus; __disable_irq(); current = SYST_CVR; count = systick_millis_count; istatus = SCB_ICSR; // bit 26 indicates if systick exception pending __enable_irq(); //systick_current = current; //systick_count = count; //systick_istatus = istatus & SCB_ICSR_PENDSTSET ? 1 : 0; if ((istatus & SCB_ICSR_PENDSTSET) && current > 50) count++; current = ((F_CPU / 1000) - 1) - current; return count * 1000 + current / (F_CPU / 1000000); } void delay(uint32_t ms) { uint32_t start = micros(); if (ms > 0) { while (1) { if ((micros() - start) >= 1000) { ms--; if (ms == 0) return; start += 1000; } yield(); } } } // TODO: verify these result in correct timeouts... #if F_CPU == 168000000 #define PULSEIN_LOOPS_PER_USEC 25 #elif F_CPU == 144000000 #define PULSEIN_LOOPS_PER_USEC 21 #elif F_CPU == 120000000 #define PULSEIN_LOOPS_PER_USEC 18 #elif F_CPU == 96000000 #define PULSEIN_LOOPS_PER_USEC 14 #elif F_CPU == 72000000 #define PULSEIN_LOOPS_PER_USEC 10 #elif F_CPU == 48000000 #define PULSEIN_LOOPS_PER_USEC 7 #elif F_CPU == 24000000 #define PULSEIN_LOOPS_PER_USEC 4 #elif F_CPU == 16000000 #define PULSEIN_LOOPS_PER_USEC 1 #elif F_CPU == 8000000 #define PULSEIN_LOOPS_PER_USEC 1 #elif F_CPU == 4000000 #define PULSEIN_LOOPS_PER_USEC 1 #elif F_CPU == 2000000 #define PULSEIN_LOOPS_PER_USEC 1 #endif uint32_t pulseIn_high(volatile uint8_t *reg, uint32_t timeout) { uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC; uint32_t usec_start, usec_stop; // wait for any previous pulse to end while (*reg) { if (--timeout_count == 0) return 0; } // wait for the pulse to start while (!*reg) { if (--timeout_count == 0) return 0; } usec_start = micros(); // wait for the pulse to stop while (*reg) { if (--timeout_count == 0) return 0; } usec_stop = micros(); return usec_stop - usec_start; } uint32_t pulseIn_low(volatile uint8_t *reg, uint32_t timeout) { uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC; uint32_t usec_start, usec_stop; // wait for any previous pulse to end while (!*reg) { if (--timeout_count == 0) return 0; } // wait for the pulse to start while (*reg) { if (--timeout_count == 0) return 0; } usec_start = micros(); // wait for the pulse to stop while (!*reg) { if (--timeout_count == 0) return 0; } usec_stop = micros(); return usec_stop - usec_start; } // TODO: an inline version should handle the common case where state is const uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout) { if (pin >= CORE_NUM_DIGITAL) return 0; if (state) return pulseIn_high(portInputRegister(pin), timeout); return pulseIn_low(portInputRegister(pin), timeout);; } micropython-1.12/ports/teensy/core/usb_desc.c000066400000000000000000001302051357706137100213640ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #if F_CPU >= 20000000 #include "usb_desc.h" #include "usb_names.h" #include "mk20dx128.h" #include "avr_functions.h" // USB Descriptors are binary data which the USB host reads to // automatically detect a USB device's capabilities. The format // and meaning of every field is documented in numerous USB // standards. When working with USB descriptors, despite the // complexity of the standards and poor writing quality in many // of those documents, remember descriptors are nothing more // than constant binary data that tells the USB host what the // device can do. Computers will load drivers based on this data. // Those drivers then communicate on the endpoints specified by // the descriptors. // To configure a new combination of interfaces or make minor // changes to existing configuration (eg, change the name or ID // numbers), usually you would edit "usb_desc.h". This file // is meant to be configured by the header, so generally it is // only edited to add completely new USB interfaces or features. // ************************************************************** // USB Device // ************************************************************** #define LSB(n) ((n) & 255) #define MSB(n) (((n) >> 8) & 255) // USB Device Descriptor. The USB host reads this first, to learn // what type of device is connected. static uint8_t device_descriptor[] = { 18, // bLength 1, // bDescriptorType 0x00, 0x02, // bcdUSB #ifdef DEVICE_CLASS DEVICE_CLASS, // bDeviceClass #else 0, #endif #ifdef DEVICE_SUBCLASS DEVICE_SUBCLASS, // bDeviceSubClass #else 0, #endif #ifdef DEVICE_PROTOCOL DEVICE_PROTOCOL, // bDeviceProtocol #else 0, #endif EP0_SIZE, // bMaxPacketSize0 LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct 0x00, 0x01, // bcdDevice 1, // iManufacturer 2, // iProduct 3, // iSerialNumber 1 // bNumConfigurations }; // These descriptors must NOT be "const", because the USB DMA // has trouble accessing flash memory with enough bandwidth // while the processor is executing from flash. // ************************************************************** // HID Report Descriptors // ************************************************************** // Each HID interface needs a special report descriptor that tells // the meaning and format of the data. #ifdef KEYBOARD_INTERFACE // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 static uint8_t keyboard_report_desc[] = { 0x05, 0x01, // Usage Page (Generic Desktop), 0x09, 0x06, // Usage (Keyboard), 0xA1, 0x01, // Collection (Application), 0x75, 0x01, // Report Size (1), 0x95, 0x08, // Report Count (8), 0x05, 0x07, // Usage Page (Key Codes), 0x19, 0xE0, // Usage Minimum (224), 0x29, 0xE7, // Usage Maximum (231), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x01, // Logical Maximum (1), 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte 0x95, 0x08, // Report Count (8), 0x75, 0x01, // Report Size (1), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x01, // Logical Maximum (1), 0x05, 0x0C, // Usage Page (Consumer), 0x09, 0xE9, // Usage (Volume Increment), 0x09, 0xEA, // Usage (Volume Decrement), 0x09, 0xE2, // Usage (Mute), 0x09, 0xCD, // Usage (Play/Pause), 0x09, 0xB5, // Usage (Scan Next Track), 0x09, 0xB6, // Usage (Scan Previous Track), 0x09, 0xB7, // Usage (Stop), 0x09, 0xB8, // Usage (Eject), 0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys 0x95, 0x05, // Report Count (5), 0x75, 0x01, // Report Size (1), 0x05, 0x08, // Usage Page (LEDs), 0x19, 0x01, // Usage Minimum (1), 0x29, 0x05, // Usage Maximum (5), 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report 0x95, 0x01, // Report Count (1), 0x75, 0x03, // Report Size (3), 0x91, 0x03, // Output (Constant), ;LED report padding 0x95, 0x06, // Report Count (6), 0x75, 0x08, // Report Size (8), 0x15, 0x00, // Logical Minimum (0), 0x25, 0x7F, // Logical Maximum(104), 0x05, 0x07, // Usage Page (Key Codes), 0x19, 0x00, // Usage Minimum (0), 0x29, 0x7F, // Usage Maximum (104), 0x81, 0x00, // Input (Data, Array), ;Normal keys 0xc0 // End Collection }; #endif #ifdef MOUSE_INTERFACE // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension static uint8_t mouse_report_desc[] = { 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) 0x85, 0x01, // REPORT_ID (1) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (Button #1) 0x29, 0x08, // Usage Maximum (Button #8) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x95, 0x08, // Report Count (8) 0x75, 0x01, // Report Size (1) 0x81, 0x02, // Input (Data, Variable, Absolute) 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x09, 0x38, // Usage (Wheel) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x75, 0x08, // Report Size (8), 0x95, 0x03, // Report Count (3), 0x81, 0x06, // Input (Data, Variable, Relative) 0xC0, // End Collection 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) 0x85, 0x02, // REPORT_ID (2) 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x7F, // Logical Maximum (32767) 0x75, 0x10, // Report Size (16), 0x95, 0x02, // Report Count (2), 0x81, 0x02, // Input (Data, Variable, Absolute) 0xC0 // End Collection }; #endif #ifdef JOYSTICK_INTERFACE static uint8_t joystick_report_desc[] = { 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x04, // Usage (Joystick) 0xA1, 0x01, // Collection (Application) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x20, // Report Count (32) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (Button #1) 0x29, 0x20, // Usage Maximum (Button #32) 0x81, 0x02, // Input (variable,absolute) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x07, // Logical Maximum (7) 0x35, 0x00, // Physical Minimum (0) 0x46, 0x3B, 0x01, // Physical Maximum (315) 0x75, 0x04, // Report Size (4) 0x95, 0x01, // Report Count (1) 0x65, 0x14, // Unit (20) 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x39, // Usage (Hat switch) 0x81, 0x42, // Input (variable,absolute,null_state) 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection () 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x03, // Logical Maximum (1023) 0x75, 0x0A, // Report Size (10) 0x95, 0x04, // Report Count (4) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x09, 0x32, // Usage (Z) 0x09, 0x35, // Usage (Rz) 0x81, 0x02, // Input (variable,absolute) 0xC0, // End Collection 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x03, // Logical Maximum (1023) 0x75, 0x0A, // Report Size (10) 0x95, 0x02, // Report Count (2) 0x09, 0x36, // Usage (Slider) 0x09, 0x36, // Usage (Slider) 0x81, 0x02, // Input (variable,absolute) 0xC0 // End Collection }; #endif #ifdef SEREMU_INTERFACE static uint8_t seremu_report_desc[] = { 0x06, 0xC9, 0xFF, // Usage Page 0xFFC9 (vendor defined) 0x09, 0x04, // Usage 0x04 0xA1, 0x5C, // Collection 0x5C 0x75, 0x08, // report size = 8 bits (global) 0x15, 0x00, // logical minimum = 0 (global) 0x26, 0xFF, 0x00, // logical maximum = 255 (global) 0x95, SEREMU_TX_SIZE, // report count (global) 0x09, 0x75, // usage (local) 0x81, 0x02, // Input 0x95, SEREMU_RX_SIZE, // report count (global) 0x09, 0x76, // usage (local) 0x91, 0x02, // Output 0x95, 0x04, // report count (global) 0x09, 0x76, // usage (local) 0xB1, 0x02, // Feature 0xC0 // end collection }; #endif #ifdef RAWHID_INTERFACE static uint8_t rawhid_report_desc[] = { 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), 0xA1, 0x01, // Collection 0x01 0x75, 0x08, // report size = 8 bits 0x15, 0x00, // logical minimum = 0 0x26, 0xFF, 0x00, // logical maximum = 255 0x95, RAWHID_TX_SIZE, // report count 0x09, 0x01, // usage 0x81, 0x02, // Input (array) 0x95, RAWHID_RX_SIZE, // report count 0x09, 0x02, // usage 0x91, 0x02, // Output (array) 0xC0 // end collection }; #endif #ifdef FLIGHTSIM_INTERFACE static uint8_t flightsim_report_desc[] = { 0x06, 0x1C, 0xFF, // Usage page = 0xFF1C 0x0A, 0x39, 0xA7, // Usage = 0xA739 0xA1, 0x01, // Collection 0x01 0x75, 0x08, // report size = 8 bits 0x15, 0x00, // logical minimum = 0 0x26, 0xFF, 0x00, // logical maximum = 255 0x95, FLIGHTSIM_TX_SIZE, // report count 0x09, 0x01, // usage 0x81, 0x02, // Input (array) 0x95, FLIGHTSIM_RX_SIZE, // report count 0x09, 0x02, // usage 0x91, 0x02, // Output (array) 0xC0 // end collection }; #endif // ************************************************************** // USB Configuration // ************************************************************** // USB Configuration Descriptor. This huge descriptor tells all // of the devices capbilities. static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 9, // bLength; 2, // bDescriptorType; LSB(CONFIG_DESC_SIZE), // wTotalLength MSB(CONFIG_DESC_SIZE), NUM_INTERFACE, // bNumInterfaces 1, // bConfigurationValue 0, // iConfiguration 0xC0, // bmAttributes 50, // bMaxPower #ifdef CDC_IAD_DESCRIPTOR // interface association descriptor, USB ECN, Table 9-Z 8, // bLength 11, // bDescriptorType CDC_STATUS_INTERFACE, // bFirstInterface 2, // bInterfaceCount 0x02, // bFunctionClass 0x02, // bFunctionSubClass 0x01, // bFunctionProtocol 4, // iFunction #endif #ifdef CDC_DATA_INTERFACE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType CDC_STATUS_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 1, // bNumEndpoints 0x02, // bInterfaceClass 0x02, // bInterfaceSubClass 0x01, // bInterfaceProtocol 0, // iInterface // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 5, // bFunctionLength 0x24, // bDescriptorType 0x00, // bDescriptorSubtype 0x10, 0x01, // bcdCDC // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 5, // bFunctionLength 0x24, // bDescriptorType 0x01, // bDescriptorSubtype 0x01, // bmCapabilities 1, // bDataInterface // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 4, // bFunctionLength 0x24, // bDescriptorType 0x02, // bDescriptorSubtype 0x06, // bmCapabilities // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 5, // bFunctionLength 0x24, // bDescriptorType 0x06, // bDescriptorSubtype CDC_STATUS_INTERFACE, // bMasterInterface CDC_DATA_INTERFACE, // bSlaveInterface0 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType CDC_ACM_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) CDC_ACM_SIZE, 0, // wMaxPacketSize 64, // bInterval // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType CDC_DATA_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 2, // bNumEndpoints 0x0A, // bInterfaceClass 0x00, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0, // iInterface // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType CDC_RX_ENDPOINT, // bEndpointAddress 0x02, // bmAttributes (0x02=bulk) CDC_RX_SIZE, 0, // wMaxPacketSize 0, // bInterval // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType CDC_TX_ENDPOINT | 0x80, // bEndpointAddress 0x02, // bmAttributes (0x02=bulk) CDC_TX_SIZE, 0, // wMaxPacketSize 0, // bInterval #endif // CDC_DATA_INTERFACE #ifdef MIDI_INTERFACE // Standard MS Interface Descriptor, 9, // bLength 4, // bDescriptorType MIDI_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 2, // bNumEndpoints 0x01, // bInterfaceClass (0x01 = Audio) 0x03, // bInterfaceSubClass (0x03 = MIDI) 0x00, // bInterfaceProtocol (unused for MIDI) 0, // iInterface // MIDI MS Interface Header, USB MIDI 6.1.2.1, page 21, Table 6-2 7, // bLength 0x24, // bDescriptorType = CS_INTERFACE 0x01, // bDescriptorSubtype = MS_HEADER 0x00, 0x01, // bcdMSC = revision 01.00 0x41, 0x00, // wTotalLength // MIDI IN Jack Descriptor, B.4.3, Table B-7 (embedded), page 40 6, // bLength 0x24, // bDescriptorType = CS_INTERFACE 0x02, // bDescriptorSubtype = MIDI_IN_JACK 0x01, // bJackType = EMBEDDED 1, // bJackID, ID = 1 0, // iJack // MIDI IN Jack Descriptor, B.4.3, Table B-8 (external), page 40 6, // bLength 0x24, // bDescriptorType = CS_INTERFACE 0x02, // bDescriptorSubtype = MIDI_IN_JACK 0x02, // bJackType = EXTERNAL 2, // bJackID, ID = 2 0, // iJack // MIDI OUT Jack Descriptor, B.4.4, Table B-9, page 41 9, 0x24, // bDescriptorType = CS_INTERFACE 0x03, // bDescriptorSubtype = MIDI_OUT_JACK 0x01, // bJackType = EMBEDDED 3, // bJackID, ID = 3 1, // bNrInputPins = 1 pin 2, // BaSourceID(1) = 2 1, // BaSourcePin(1) = first pin 0, // iJack // MIDI OUT Jack Descriptor, B.4.4, Table B-10, page 41 9, 0x24, // bDescriptorType = CS_INTERFACE 0x03, // bDescriptorSubtype = MIDI_OUT_JACK 0x02, // bJackType = EXTERNAL 4, // bJackID, ID = 4 1, // bNrInputPins = 1 pin 1, // BaSourceID(1) = 1 1, // BaSourcePin(1) = first pin 0, // iJack // Standard Bulk OUT Endpoint Descriptor, B.5.1, Table B-11, pae 42 9, // bLength 5, // bDescriptorType = ENDPOINT MIDI_RX_ENDPOINT, // bEndpointAddress 0x02, // bmAttributes (0x02=bulk) MIDI_RX_SIZE, 0, // wMaxPacketSize 0, // bInterval 0, // bRefresh 0, // bSynchAddress // Class-specific MS Bulk OUT Endpoint Descriptor, B.5.2, Table B-12, page 42 5, // bLength 0x25, // bDescriptorSubtype = CS_ENDPOINT 0x01, // bJackType = MS_GENERAL 1, // bNumEmbMIDIJack = 1 jack 1, // BaAssocJackID(1) = jack ID #1 // Standard Bulk IN Endpoint Descriptor, B.5.1, Table B-11, pae 42 9, // bLength 5, // bDescriptorType = ENDPOINT MIDI_TX_ENDPOINT | 0x80, // bEndpointAddress 0x02, // bmAttributes (0x02=bulk) MIDI_TX_SIZE, 0, // wMaxPacketSize 0, // bInterval 0, // bRefresh 0, // bSynchAddress // Class-specific MS Bulk IN Endpoint Descriptor, B.5.2, Table B-12, page 42 5, // bLength 0x25, // bDescriptorSubtype = CS_ENDPOINT 0x01, // bJackType = MS_GENERAL 1, // bNumEmbMIDIJack = 1 jack 3, // BaAssocJackID(1) = jack ID #3 #endif // MIDI_INTERFACE #ifdef KEYBOARD_INTERFACE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType KEYBOARD_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 1, // bNumEndpoints 0x03, // bInterfaceClass (0x03 = HID) 0x01, // bInterfaceSubClass (0x01 = Boot) 0x01, // bInterfaceProtocol (0x01 = Keyboard) 0, // iInterface // HID interface descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType LSB(sizeof(keyboard_report_desc)), // wDescriptorLength MSB(sizeof(keyboard_report_desc)), // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) KEYBOARD_SIZE, 0, // wMaxPacketSize KEYBOARD_INTERVAL, // bInterval #endif // KEYBOARD_INTERFACE #ifdef MOUSE_INTERFACE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType MOUSE_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 1, // bNumEndpoints 0x03, // bInterfaceClass (0x03 = HID) 0x00, // bInterfaceSubClass (0x01 = Boot) 0x00, // bInterfaceProtocol (0x02 = Mouse) 0, // iInterface // HID interface descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType LSB(sizeof(mouse_report_desc)), // wDescriptorLength MSB(sizeof(mouse_report_desc)), // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType MOUSE_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) MOUSE_SIZE, 0, // wMaxPacketSize MOUSE_INTERVAL, // bInterval #endif // MOUSE_INTERFACE #ifdef RAWHID_INTERFACE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType RAWHID_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 2, // bNumEndpoints 0x03, // bInterfaceClass (0x03 = HID) 0x00, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0, // iInterface // HID interface descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType LSB(sizeof(rawhid_report_desc)), // wDescriptorLength MSB(sizeof(rawhid_report_desc)), // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType RAWHID_TX_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) RAWHID_TX_SIZE, 0, // wMaxPacketSize RAWHID_TX_INTERVAL, // bInterval // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType RAWHID_RX_ENDPOINT, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) RAWHID_RX_SIZE, 0, // wMaxPacketSize RAWHID_RX_INTERVAL, // bInterval #endif // RAWHID_INTERFACE #ifdef FLIGHTSIM_INTERFACE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType FLIGHTSIM_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 2, // bNumEndpoints 0x03, // bInterfaceClass (0x03 = HID) 0x00, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0, // iInterface // HID interface descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType LSB(sizeof(flightsim_report_desc)), // wDescriptorLength MSB(sizeof(flightsim_report_desc)), // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType FLIGHTSIM_TX_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) FLIGHTSIM_TX_SIZE, 0, // wMaxPacketSize FLIGHTSIM_TX_INTERVAL, // bInterval // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType FLIGHTSIM_RX_ENDPOINT, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) FLIGHTSIM_RX_SIZE, 0, // wMaxPacketSize FLIGHTSIM_RX_INTERVAL, // bInterval #endif // FLIGHTSIM_INTERFACE #ifdef SEREMU_INTERFACE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType SEREMU_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 2, // bNumEndpoints 0x03, // bInterfaceClass (0x03 = HID) 0x00, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0, // iInterface // HID interface descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType LSB(sizeof(seremu_report_desc)), // wDescriptorLength MSB(sizeof(seremu_report_desc)), // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType SEREMU_TX_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) SEREMU_TX_SIZE, 0, // wMaxPacketSize SEREMU_TX_INTERVAL, // bInterval // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType SEREMU_RX_ENDPOINT, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) SEREMU_RX_SIZE, 0, // wMaxPacketSize SEREMU_RX_INTERVAL, // bInterval #endif // SEREMU_INTERFACE #ifdef JOYSTICK_INTERFACE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType JOYSTICK_INTERFACE, // bInterfaceNumber 0, // bAlternateSetting 1, // bNumEndpoints 0x03, // bInterfaceClass (0x03 = HID) 0x00, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0, // iInterface // HID interface descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType LSB(sizeof(joystick_report_desc)), // wDescriptorLength MSB(sizeof(joystick_report_desc)), // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 7, // bLength 5, // bDescriptorType JOYSTICK_ENDPOINT | 0x80, // bEndpointAddress 0x03, // bmAttributes (0x03=intr) JOYSTICK_SIZE, 0, // wMaxPacketSize JOYSTICK_INTERVAL, // bInterval #endif // JOYSTICK_INTERFACE }; // ************************************************************** // String Descriptors // ************************************************************** // The descriptors above can provide human readable strings, // referenced by index numbers. These descriptors are the // actual string data /* defined in usb_names.h struct usb_string_descriptor_struct { uint8_t bLength; uint8_t bDescriptorType; uint16_t wString[]; }; */ extern struct usb_string_descriptor_struct usb_string_manufacturer_name __attribute__ ((weak, alias("usb_string_manufacturer_name_default"))); extern struct usb_string_descriptor_struct usb_string_product_name __attribute__ ((weak, alias("usb_string_product_name_default"))); extern struct usb_string_descriptor_struct usb_string_serial_number __attribute__ ((weak, alias("usb_string_serial_number_default"))); struct usb_string_descriptor_struct string0 = { 4, 3, {0x0409} }; struct usb_string_descriptor_struct usb_string_manufacturer_name_default = { 2 + MANUFACTURER_NAME_LEN * 2, 3, MANUFACTURER_NAME }; struct usb_string_descriptor_struct usb_string_product_name_default = { 2 + PRODUCT_NAME_LEN * 2, 3, PRODUCT_NAME }; struct usb_string_descriptor_struct usb_string_serial_number_default = { 12, 3, {0,0,0,0,0,0,0,0,0,0} }; void usb_init_serialnumber(void) { char buf[11]; uint32_t i, num; __disable_irq(); FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL; FTFL_FCCOB0 = 0x41; FTFL_FCCOB1 = 15; FTFL_FSTAT = FTFL_FSTAT_CCIF; while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait num = *(uint32_t *)&FTFL_FCCOB7; __enable_irq(); // add extra zero to work around OS-X CDC-ACM driver bug if (num < 10000000) num = num * 10; ultoa(num, buf, 10); for (i=0; i<10; i++) { char c = buf[i]; if (!c) break; usb_string_serial_number_default.wString[i] = c; } usb_string_serial_number_default.bLength = i * 2 + 2; } // ************************************************************** // Descriptors List // ************************************************************** // This table provides access to all the descriptor data above. const usb_descriptor_list_t usb_descriptor_list[] = { //wValue, wIndex, address, length {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, {0x0200, 0x0000, config_descriptor, sizeof(config_descriptor)}, #ifdef SEREMU_INTERFACE {0x2200, SEREMU_INTERFACE, seremu_report_desc, sizeof(seremu_report_desc)}, {0x2100, SEREMU_INTERFACE, config_descriptor+SEREMU_DESC_OFFSET, 9}, #endif #ifdef KEYBOARD_INTERFACE {0x2200, KEYBOARD_INTERFACE, keyboard_report_desc, sizeof(keyboard_report_desc)}, {0x2100, KEYBOARD_INTERFACE, config_descriptor+KEYBOARD_DESC_OFFSET, 9}, #endif #ifdef MOUSE_INTERFACE {0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)}, {0x2100, MOUSE_INTERFACE, config_descriptor+MOUSE_DESC_OFFSET, 9}, #endif #ifdef JOYSTICK_INTERFACE {0x2200, JOYSTICK_INTERFACE, joystick_report_desc, sizeof(joystick_report_desc)}, {0x2100, JOYSTICK_INTERFACE, config_descriptor+JOYSTICK_DESC_OFFSET, 9}, #endif #ifdef RAWHID_INTERFACE {0x2200, RAWHID_INTERFACE, rawhid_report_desc, sizeof(rawhid_report_desc)}, {0x2100, RAWHID_INTERFACE, config_descriptor+RAWHID_DESC_OFFSET, 9}, #endif #ifdef FLIGHTSIM_INTERFACE {0x2200, FLIGHTSIM_INTERFACE, flightsim_report_desc, sizeof(flightsim_report_desc)}, {0x2100, FLIGHTSIM_INTERFACE, config_descriptor+FLIGHTSIM_DESC_OFFSET, 9}, #endif {0x0300, 0x0000, (const uint8_t *)&string0, 0}, {0x0301, 0x0409, (const uint8_t *)&usb_string_manufacturer_name, 0}, {0x0302, 0x0409, (const uint8_t *)&usb_string_product_name, 0}, {0x0303, 0x0409, (const uint8_t *)&usb_string_serial_number, 0}, //{0x0301, 0x0409, (const uint8_t *)&string1, 0}, //{0x0302, 0x0409, (const uint8_t *)&string2, 0}, //{0x0303, 0x0409, (const uint8_t *)&string3, 0}, {0, 0, NULL, 0} }; // ************************************************************** // Endpoint Configuration // ************************************************************** #if 0 // 0x00 = not used // 0x19 = Recieve only // 0x15 = Transmit only // 0x1D = Transmit & Recieve // const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS] = { 0x00, 0x15, 0x19, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #endif const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS] = { #if (defined(ENDPOINT1_CONFIG) && NUM_ENDPOINTS >= 1) ENDPOINT1_CONFIG, #elif (NUM_ENDPOINTS >= 1) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT2_CONFIG) && NUM_ENDPOINTS >= 2) ENDPOINT2_CONFIG, #elif (NUM_ENDPOINTS >= 2) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT3_CONFIG) && NUM_ENDPOINTS >= 3) ENDPOINT3_CONFIG, #elif (NUM_ENDPOINTS >= 3) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT4_CONFIG) && NUM_ENDPOINTS >= 4) ENDPOINT4_CONFIG, #elif (NUM_ENDPOINTS >= 4) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT5_CONFIG) && NUM_ENDPOINTS >= 5) ENDPOINT5_CONFIG, #elif (NUM_ENDPOINTS >= 5) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT6_CONFIG) && NUM_ENDPOINTS >= 6) ENDPOINT6_CONFIG, #elif (NUM_ENDPOINTS >= 6) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT7_CONFIG) && NUM_ENDPOINTS >= 7) ENDPOINT7_CONFIG, #elif (NUM_ENDPOINTS >= 7) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT8_CONFIG) && NUM_ENDPOINTS >= 8) ENDPOINT8_CONFIG, #elif (NUM_ENDPOINTS >= 8) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT9_CONFIG) && NUM_ENDPOINTS >= 9) ENDPOINT9_CONFIG, #elif (NUM_ENDPOINTS >= 9) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT10_CONFIG) && NUM_ENDPOINTS >= 10) ENDPOINT10_CONFIG, #elif (NUM_ENDPOINTS >= 10) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT11_CONFIG) && NUM_ENDPOINTS >= 11) ENDPOINT11_CONFIG, #elif (NUM_ENDPOINTS >= 11) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT12_CONFIG) && NUM_ENDPOINTS >= 12) ENDPOINT12_CONFIG, #elif (NUM_ENDPOINTS >= 12) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT13_CONFIG) && NUM_ENDPOINTS >= 13) ENDPOINT13_CONFIG, #elif (NUM_ENDPOINTS >= 13) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT14_CONFIG) && NUM_ENDPOINTS >= 14) ENDPOINT14_CONFIG, #elif (NUM_ENDPOINTS >= 14) ENDPOINT_UNUSED, #endif #if (defined(ENDPOINT15_CONFIG) && NUM_ENDPOINTS >= 15) ENDPOINT15_CONFIG, #elif (NUM_ENDPOINTS >= 15) ENDPOINT_UNUSED, #endif }; #endif // F_CPU >= 20 MHz micropython-1.12/ports/teensy/core/usb_desc.h000066400000000000000000000275541357706137100214050ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef _usb_desc_h_ #define _usb_desc_h_ #if F_CPU >= 20000000 // This header is NOT meant to be included when compiling // user sketches in Arduino. The low-level functions // provided by usb_dev.c are meant to be called only by // code which provides higher-level interfaces to the user. #include #include #define ENDPOINT_UNUSED 0x00 #define ENDPOINT_TRANSIMIT_ONLY 0x15 #define ENDPOINT_RECEIVE_ONLY 0x19 #define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D /* To modify a USB Type to have different interfaces, start in this file. Delete the XYZ_INTERFACE lines for any interfaces you wish to remove, and copy them from another USB Type for any you want to add. Give each interface a unique number, and edit NUM_INTERFACE to reflect the number of interfaces. Within each interface, make sure it uses a unique set of endpoints. Edit NUM_ENDPOINTS to be at least the largest endpoint number used. Then edit the ENDPOINT*_CONFIG lines so each endpoint is configured the proper way (transmit, receive, or both). The CONFIG_DESC_SIZE and any XYZ_DESC_OFFSET numbers must be edited to the correct sizes. See usb_desc.c for the giant array of bytes. Someday these may be done automatically..... (but how?) If you are using existing interfaces, the code in each file should automatically adapt to the changes you specify. If you need to create a new type of interface, you'll need to write the code which sends and receives packets, and presents an API to the user. Finally, edit usb_inst.cpp, which creats instances of the C++ objects for each combination. Some operating systems, especially Windows, may cache USB device info. Changes to the device name may not update on the same computer unless the vendor or product ID numbers change, or the "bcdDevice" revision code is increased. If these instructions are missing steps or could be improved, please let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports */ #if defined(USB_SERIAL) #define VENDOR_ID 0x16C0 #define PRODUCT_ID 0x0483 #define DEVICE_CLASS 2 // 2 = Communication Class #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} #define MANUFACTURER_NAME_LEN 11 #define PRODUCT_NAME {'U','S','B',' ','S','e','r','i','a','l'} #define PRODUCT_NAME_LEN 10 #define EP0_SIZE 64 #define NUM_ENDPOINTS 4 #define NUM_USB_BUFFERS 12 #define NUM_INTERFACE 2 #define CDC_STATUS_INTERFACE 0 #define CDC_DATA_INTERFACE 1 #define CDC_ACM_ENDPOINT 2 #define CDC_RX_ENDPOINT 3 #define CDC_TX_ENDPOINT 4 #define CDC_ACM_SIZE 16 #define CDC_RX_SIZE 64 #define CDC_TX_SIZE 64 #define CONFIG_DESC_SIZE (9+9+5+5+4+5+7+9+7+7) #define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY #elif defined(USB_HID) #define VENDOR_ID 0x16C0 #define PRODUCT_ID 0x0482 #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} #define MANUFACTURER_NAME_LEN 11 #define PRODUCT_NAME {'K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'} #define PRODUCT_NAME_LEN 23 #define EP0_SIZE 64 #define NUM_ENDPOINTS 5 #define NUM_USB_BUFFERS 24 #define NUM_INTERFACE 4 #define SEREMU_INTERFACE 2 // Serial emulation #define SEREMU_TX_ENDPOINT 1 #define SEREMU_TX_SIZE 64 #define SEREMU_TX_INTERVAL 1 #define SEREMU_RX_ENDPOINT 2 #define SEREMU_RX_SIZE 32 #define SEREMU_RX_INTERVAL 2 #define KEYBOARD_INTERFACE 0 // Keyboard #define KEYBOARD_ENDPOINT 3 #define KEYBOARD_SIZE 8 #define KEYBOARD_INTERVAL 1 #define MOUSE_INTERFACE 1 // Mouse #define MOUSE_ENDPOINT 5 #define MOUSE_SIZE 8 #define MOUSE_INTERVAL 1 #define JOYSTICK_INTERFACE 3 // Joystick #define JOYSTICK_ENDPOINT 4 #define JOYSTICK_SIZE 16 #define JOYSTICK_INTERVAL 2 #define KEYBOARD_DESC_OFFSET (9 + 9) #define MOUSE_DESC_OFFSET (9 + 9+9+7 + 9) #define SEREMU_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 9) #define JOYSTICK_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9) #define CONFIG_DESC_SIZE (9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9+9+7) #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY #elif defined(USB_SERIAL_HID) #define VENDOR_ID 0x16C0 #define PRODUCT_ID 0x0487 #define DEVICE_CLASS 0xEF #define DEVICE_SUBCLASS 0x02 #define DEVICE_PROTOCOL 0x01 #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} #define MANUFACTURER_NAME_LEN 11 #define PRODUCT_NAME {'S','e','r','i','a','l','/','K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'} #define PRODUCT_NAME_LEN 30 #define EP0_SIZE 64 #define NUM_ENDPOINTS 6 #define NUM_USB_BUFFERS 30 #define NUM_INTERFACE 5 #define CDC_IAD_DESCRIPTOR 1 #define CDC_STATUS_INTERFACE 0 #define CDC_DATA_INTERFACE 1 // Serial #define CDC_ACM_ENDPOINT 2 #define CDC_RX_ENDPOINT 3 #define CDC_TX_ENDPOINT 4 #define CDC_ACM_SIZE 16 #define CDC_RX_SIZE 64 #define CDC_TX_SIZE 64 #define KEYBOARD_INTERFACE 2 // Keyboard #define KEYBOARD_ENDPOINT 1 #define KEYBOARD_SIZE 8 #define KEYBOARD_INTERVAL 1 #define MOUSE_INTERFACE 3 // Mouse #define MOUSE_ENDPOINT 5 #define MOUSE_SIZE 8 #define MOUSE_INTERVAL 2 #define JOYSTICK_INTERFACE 4 // Joystick #define JOYSTICK_ENDPOINT 6 #define JOYSTICK_SIZE 16 #define JOYSTICK_INTERVAL 1 #define KEYBOARD_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9) #define MOUSE_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9) #define JOYSTICK_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9) #define CONFIG_DESC_SIZE (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7) #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY #elif defined(USB_MIDI) #define VENDOR_ID 0x16C0 #define PRODUCT_ID 0x0485 #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} #define MANUFACTURER_NAME_LEN 11 #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I'} #define PRODUCT_NAME_LEN 11 #define EP0_SIZE 64 #define NUM_ENDPOINTS 4 #define NUM_USB_BUFFERS 16 #define NUM_INTERFACE 2 #define SEREMU_INTERFACE 1 // Serial emulation #define SEREMU_TX_ENDPOINT 1 #define SEREMU_TX_SIZE 64 #define SEREMU_TX_INTERVAL 1 #define SEREMU_RX_ENDPOINT 2 #define SEREMU_RX_SIZE 32 #define SEREMU_RX_INTERVAL 2 #define MIDI_INTERFACE 0 // MIDI #define MIDI_TX_ENDPOINT 3 #define MIDI_TX_SIZE 64 #define MIDI_RX_ENDPOINT 4 #define MIDI_RX_SIZE 64 #define SEREMU_DESC_OFFSET (9 + 9+7+6+6+9+9+9+5+9+5 + 9) #define CONFIG_DESC_SIZE (9 + 9+7+6+6+9+9+9+5+9+5 + 9+9+7+7) #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY #elif defined(USB_RAWHID) #define VENDOR_ID 0x16C0 #define PRODUCT_ID 0x0486 #define RAWHID_USAGE_PAGE 0xFFAB // recommended: 0xFF00 to 0xFFFF #define RAWHID_USAGE 0x0200 // recommended: 0x0100 to 0xFFFF #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} #define MANUFACTURER_NAME_LEN 11 #define PRODUCT_NAME {'T','e','e','n','s','y','d','u','i','n','o',' ','R','a','w','H','I','D'} #define PRODUCT_NAME_LEN 18 #define EP0_SIZE 64 #define NUM_ENDPOINTS 6 #define NUM_USB_BUFFERS 12 #define NUM_INTERFACE 2 #define RAWHID_INTERFACE 0 // RawHID #define RAWHID_TX_ENDPOINT 3 #define RAWHID_TX_SIZE 64 #define RAWHID_TX_INTERVAL 1 #define RAWHID_RX_ENDPOINT 4 #define RAWHID_RX_SIZE 64 #define RAWHID_RX_INTERVAL 1 #define SEREMU_INTERFACE 1 // Serial emulation #define SEREMU_TX_ENDPOINT 1 #define SEREMU_TX_SIZE 64 #define SEREMU_TX_INTERVAL 1 #define SEREMU_RX_ENDPOINT 2 #define SEREMU_RX_SIZE 32 #define SEREMU_RX_INTERVAL 2 #define RAWHID_DESC_OFFSET (9 + 9) #define SEREMU_DESC_OFFSET (9 + 9+9+7+7 + 9) #define CONFIG_DESC_SIZE (9 + 9+9+7+7 + 9+9+7+7) #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY #elif defined(USB_FLIGHTSIM) #define VENDOR_ID 0x16C0 #define PRODUCT_ID 0x0488 #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} #define MANUFACTURER_NAME_LEN 11 #define PRODUCT_NAME {'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'} #define PRODUCT_NAME_LEN 26 #define EP0_SIZE 64 #define NUM_ENDPOINTS 4 #define NUM_USB_BUFFERS 20 #define NUM_INTERFACE 2 #define FLIGHTSIM_INTERFACE 0 // Flight Sim Control #define FLIGHTSIM_TX_ENDPOINT 3 #define FLIGHTSIM_TX_SIZE 64 #define FLIGHTSIM_TX_INTERVAL 1 #define FLIGHTSIM_RX_ENDPOINT 4 #define FLIGHTSIM_RX_SIZE 64 #define FLIGHTSIM_RX_INTERVAL 1 #define SEREMU_INTERFACE 1 // Serial emulation #define SEREMU_TX_ENDPOINT 1 #define SEREMU_TX_SIZE 64 #define SEREMU_TX_INTERVAL 1 #define SEREMU_RX_ENDPOINT 2 #define SEREMU_RX_SIZE 32 #define SEREMU_RX_INTERVAL 2 #define FLIGHTSIM_DESC_OFFSET (9 + 9) #define SEREMU_DESC_OFFSET (9 + 9+9+7+7 + 9) #define CONFIG_DESC_SIZE (9 + 9+9+7+7 + 9+9+7+7) #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY #endif // NUM_ENDPOINTS = number of non-zero endpoints (0 to 15) extern const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS]; typedef struct { uint16_t wValue; uint16_t wIndex; const uint8_t *addr; uint16_t length; } usb_descriptor_list_t; extern const usb_descriptor_list_t usb_descriptor_list[]; #endif // F_CPU >= 20 MHz #endif micropython-1.12/ports/teensy/core/usb_dev.c000066400000000000000000000614651357706137100212370ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #if F_CPU >= 20000000 #include "mk20dx128.h" //#include "HardwareSerial.h" #include "usb_dev.h" #include "usb_mem.h" // buffer descriptor table typedef struct { uint32_t desc; void * addr; } bdt_t; __attribute__ ((section(".usbdescriptortable"), used)) static bdt_t table[(NUM_ENDPOINTS+1)*4]; static usb_packet_t *rx_first[NUM_ENDPOINTS]; static usb_packet_t *rx_last[NUM_ENDPOINTS]; static usb_packet_t *tx_first[NUM_ENDPOINTS]; static usb_packet_t *tx_last[NUM_ENDPOINTS]; uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS]; static uint8_t tx_state[NUM_ENDPOINTS]; #define TX_STATE_BOTH_FREE_EVEN_FIRST 0 #define TX_STATE_BOTH_FREE_ODD_FIRST 1 #define TX_STATE_EVEN_FREE 2 #define TX_STATE_ODD_FREE 3 #define TX_STATE_NONE_FREE_EVEN_FIRST 4 #define TX_STATE_NONE_FREE_ODD_FIRST 5 #define BDT_OWN 0x80 #define BDT_DATA1 0x40 #define BDT_DATA0 0x00 #define BDT_DTS 0x08 #define BDT_STALL 0x04 #define BDT_PID(n) (((n) >> 2) & 15) #define BDT_DESC(count, data) (BDT_OWN | BDT_DTS \ | ((data) ? BDT_DATA1 : BDT_DATA0) \ | ((count) << 16)) #define TX 1 #define RX 0 #define ODD 1 #define EVEN 0 #define DATA0 0 #define DATA1 1 #define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd)) #define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) static union { struct { union { struct { uint8_t bmRequestType; uint8_t bRequest; }; uint16_t wRequestAndType; }; uint16_t wValue; uint16_t wIndex; uint16_t wLength; }; struct { uint32_t word1; uint32_t word2; }; } setup; #define GET_STATUS 0 #define CLEAR_FEATURE 1 #define SET_FEATURE 3 #define SET_ADDRESS 5 #define GET_DESCRIPTOR 6 #define SET_DESCRIPTOR 7 #define GET_CONFIGURATION 8 #define SET_CONFIGURATION 9 #define GET_INTERFACE 10 #define SET_INTERFACE 11 #define SYNCH_FRAME 12 // SETUP always uses a DATA0 PID for the data field of the SETUP transaction. // transactions in the data phase start with DATA1 and toggle (figure 8-12, USB1.1) // Status stage uses a DATA1 PID. static uint8_t ep0_rx0_buf[EP0_SIZE] __attribute__ ((aligned (4))); static uint8_t ep0_rx1_buf[EP0_SIZE] __attribute__ ((aligned (4))); static const uint8_t *ep0_tx_ptr = NULL; static uint16_t ep0_tx_len; static uint8_t ep0_tx_bdt_bank = 0; static uint8_t ep0_tx_data_toggle = 0; uint8_t usb_rx_memory_needed = 0; volatile uint8_t usb_configuration = 0; volatile uint8_t usb_reboot_timer = 0; static void endpoint0_stall(void) { USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; } static void endpoint0_transmit(const void *data, uint32_t len) { #if 0 serial_print("tx0:"); serial_phex32((uint32_t)data); serial_print(","); serial_phex16(len); serial_print(ep0_tx_bdt_bank ? ", odd" : ", even"); serial_print(ep0_tx_data_toggle ? ", d1\n" : ", d0\n"); #endif table[index(0, TX, ep0_tx_bdt_bank)].addr = (void *)data; table[index(0, TX, ep0_tx_bdt_bank)].desc = BDT_DESC(len, ep0_tx_data_toggle); ep0_tx_data_toggle ^= 1; ep0_tx_bdt_bank ^= 1; } static uint8_t reply_buffer[8]; static void usb_setup(void) { const uint8_t *data = NULL; uint32_t datalen = 0; const usb_descriptor_list_t *list; uint32_t size; volatile uint8_t *reg; uint8_t epconf; const uint8_t *cfg; int i; switch (setup.wRequestAndType) { case 0x0500: // SET_ADDRESS break; case 0x0900: // SET_CONFIGURATION //serial_print("configure\n"); usb_configuration = setup.wValue; reg = &USB0_ENDPT1; cfg = usb_endpoint_config_table; // clear all BDT entries, free any allocated memory... for (i=4; i < (NUM_ENDPOINTS+1)*4; i++) { if (table[i].desc & BDT_OWN) { usb_free((usb_packet_t *)((uint8_t *)(table[i].addr) - 8)); } } // free all queued packets for (i=0; i < NUM_ENDPOINTS; i++) { usb_packet_t *p, *n; p = rx_first[i]; while (p) { n = p->next; usb_free(p); p = n; } rx_first[i] = NULL; rx_last[i] = NULL; p = tx_first[i]; while (p) { n = p->next; usb_free(p); p = n; } tx_first[i] = NULL; tx_last[i] = NULL; usb_rx_byte_count_data[i] = 0; switch (tx_state[i]) { case TX_STATE_EVEN_FREE: case TX_STATE_NONE_FREE_EVEN_FIRST: tx_state[i] = TX_STATE_BOTH_FREE_EVEN_FIRST; break; case TX_STATE_ODD_FREE: case TX_STATE_NONE_FREE_ODD_FIRST: tx_state[i] = TX_STATE_BOTH_FREE_ODD_FIRST; break; default: break; } } usb_rx_memory_needed = 0; for (i=1; i <= NUM_ENDPOINTS; i++) { epconf = *cfg++; *reg = epconf; reg += 4; if (epconf & USB_ENDPT_EPRXEN) { usb_packet_t *p; p = usb_malloc(); if (p) { table[index(i, RX, EVEN)].addr = p->buf; table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); } else { table[index(i, RX, EVEN)].desc = 0; usb_rx_memory_needed++; } p = usb_malloc(); if (p) { table[index(i, RX, ODD)].addr = p->buf; table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); } else { table[index(i, RX, ODD)].desc = 0; usb_rx_memory_needed++; } } table[index(i, TX, EVEN)].desc = 0; table[index(i, TX, ODD)].desc = 0; } break; case 0x0880: // GET_CONFIGURATION reply_buffer[0] = usb_configuration; datalen = 1; data = reply_buffer; break; case 0x0080: // GET_STATUS (device) reply_buffer[0] = 0; reply_buffer[1] = 0; datalen = 2; data = reply_buffer; break; case 0x0082: // GET_STATUS (endpoint) if (setup.wIndex > NUM_ENDPOINTS) { // TODO: do we need to handle IN vs OUT here? endpoint0_stall(); return; } reply_buffer[0] = 0; reply_buffer[1] = 0; if (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4) & 0x02) reply_buffer[0] = 1; data = reply_buffer; datalen = 2; break; case 0x0102: // CLEAR_FEATURE (endpoint) i = setup.wIndex & 0x7F; if (i > NUM_ENDPOINTS || setup.wValue != 0) { // TODO: do we need to handle IN vs OUT here? endpoint0_stall(); return; } (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02; // TODO: do we need to clear the data toggle here? break; case 0x0302: // SET_FEATURE (endpoint) i = setup.wIndex & 0x7F; if (i > NUM_ENDPOINTS || setup.wValue != 0) { // TODO: do we need to handle IN vs OUT here? endpoint0_stall(); return; } (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) |= 0x02; // TODO: do we need to clear the data toggle here? break; case 0x0680: // GET_DESCRIPTOR case 0x0681: //serial_print("desc:"); //serial_phex16(setup.wValue); //serial_print("\n"); for (list = usb_descriptor_list; 1; list++) { if (list->addr == NULL) break; //if (setup.wValue == list->wValue && //(setup.wIndex == list->wIndex) || ((setup.wValue >> 8) == 3)) { if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) { data = list->addr; if ((setup.wValue >> 8) == 3) { // for string descriptors, use the descriptor's // length field, allowing runtime configured // length. datalen = *(list->addr); } else { datalen = list->length; } #if 0 serial_print("Desc found, "); serial_phex32((uint32_t)data); serial_print(","); serial_phex16(datalen); serial_print(","); serial_phex(data[0]); serial_phex(data[1]); serial_phex(data[2]); serial_phex(data[3]); serial_phex(data[4]); serial_phex(data[5]); serial_print("\n"); #endif goto send; } } //serial_print("desc: not found\n"); endpoint0_stall(); return; #if defined(CDC_STATUS_INTERFACE) case 0x2221: // CDC_SET_CONTROL_LINE_STATE usb_cdc_line_rtsdtr = setup.wValue; //serial_print("set control line state\n"); break; case 0x2321: // CDC_SEND_BREAK break; case 0x2021: // CDC_SET_LINE_CODING //serial_print("set coding, waiting...\n"); return; #endif // TODO: this does not work... why? #if defined(SEREMU_INTERFACE) || defined(KEYBOARD_INTERFACE) case 0x0921: // HID SET_REPORT //serial_print(":)\n"); return; case 0x0A21: // HID SET_IDLE break; // case 0xC940: #endif default: endpoint0_stall(); return; } send: //serial_print("setup send "); //serial_phex32(data); //serial_print(","); //serial_phex16(datalen); //serial_print("\n"); if (datalen > setup.wLength) datalen = setup.wLength; size = datalen; if (size > EP0_SIZE) size = EP0_SIZE; endpoint0_transmit(data, size); data += size; datalen -= size; if (datalen == 0 && size < EP0_SIZE) return; size = datalen; if (size > EP0_SIZE) size = EP0_SIZE; endpoint0_transmit(data, size); data += size; datalen -= size; if (datalen == 0 && size < EP0_SIZE) return; ep0_tx_ptr = data; ep0_tx_len = datalen; } //A bulk endpoint's toggle sequence is initialized to DATA0 when the endpoint //experiences any configuration event (configuration events are explained in //Sections 9.1.1.5 and 9.4.5). //Configuring a device or changing an alternate setting causes all of the status //and configuration values associated with endpoints in the affected interfaces //to be set to their default values. This includes setting the data toggle of //any endpoint using data toggles to the value DATA0. //For endpoints using data toggle, regardless of whether an endpoint has the //Halt feature set, a ClearFeature(ENDPOINT_HALT) request always results in the //data toggle being reinitialized to DATA0. // #define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) static void usb_control(uint32_t stat) { bdt_t *b; uint32_t pid, size; uint8_t *buf; const uint8_t *data; b = stat2bufferdescriptor(stat); pid = BDT_PID(b->desc); //count = b->desc >> 16; buf = b->addr; //serial_print("pid:"); //serial_phex(pid); //serial_print(", count:"); //serial_phex(count); //serial_print("\n"); switch (pid) { case 0x0D: // Setup received from host //serial_print("PID=Setup\n"); //if (count != 8) ; // panic? // grab the 8 byte setup info setup.word1 = *(uint32_t *)(buf); setup.word2 = *(uint32_t *)(buf + 4); // give the buffer back b->desc = BDT_DESC(EP0_SIZE, DATA1); //table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 1); //table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 1); // clear any leftover pending IN transactions ep0_tx_ptr = NULL; if (ep0_tx_data_toggle) { } //if (table[index(0, TX, EVEN)].desc & 0x80) { //serial_print("leftover tx even\n"); //} //if (table[index(0, TX, ODD)].desc & 0x80) { //serial_print("leftover tx odd\n"); //} table[index(0, TX, EVEN)].desc = 0; table[index(0, TX, ODD)].desc = 0; // first IN after Setup is always DATA1 ep0_tx_data_toggle = 1; #if 0 serial_print("bmRequestType:"); serial_phex(setup.bmRequestType); serial_print(", bRequest:"); serial_phex(setup.bRequest); serial_print(", wValue:"); serial_phex16(setup.wValue); serial_print(", wIndex:"); serial_phex16(setup.wIndex); serial_print(", len:"); serial_phex16(setup.wLength); serial_print("\n"); #endif // actually "do" the setup request usb_setup(); // unfreeze the USB, now that we're ready USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit break; case 0x01: // OUT transaction received from host case 0x02: //serial_print("PID=OUT\n"); #ifdef CDC_STATUS_INTERFACE if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) { int i; uint8_t *dst = (uint8_t *)usb_cdc_line_coding; //serial_print("set line coding "); for (i=0; i<7; i++) { //serial_phex(*buf); *dst++ = *buf++; } //serial_phex32(usb_cdc_line_coding[0]); //serial_print("\n"); if (usb_cdc_line_coding[0] == 134) usb_reboot_timer = 15; endpoint0_transmit(NULL, 0); } #endif #ifdef KEYBOARD_INTERFACE if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) { keyboard_leds = buf[0]; endpoint0_transmit(NULL, 0); } #endif #ifdef SEREMU_INTERFACE if (setup.word1 == 0x03000921 && setup.word2 == ((4<<16)|SEREMU_INTERFACE) && buf[0] == 0xA9 && buf[1] == 0x45 && buf[2] == 0xC2 && buf[3] == 0x6B) { usb_reboot_timer = 5; endpoint0_transmit(NULL, 0); } #endif // give the buffer back b->desc = BDT_DESC(EP0_SIZE, DATA1); break; case 0x09: // IN transaction completed to host //serial_print("PID=IN:"); //serial_phex(stat); //serial_print("\n"); // send remaining data, if any... data = ep0_tx_ptr; if (data) { size = ep0_tx_len; if (size > EP0_SIZE) size = EP0_SIZE; endpoint0_transmit(data, size); data += size; ep0_tx_len -= size; ep0_tx_ptr = (ep0_tx_len > 0 || size == EP0_SIZE) ? data : NULL; } if (setup.bRequest == 5 && setup.bmRequestType == 0) { setup.bRequest = 0; //serial_print("set address: "); //serial_phex16(setup.wValue); //serial_print("\n"); USB0_ADDR = setup.wValue; } break; //default: //serial_print("PID=unknown:"); //serial_phex(pid); //serial_print("\n"); } USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit } usb_packet_t *usb_rx(uint32_t endpoint) { usb_packet_t *ret; endpoint--; if (endpoint >= NUM_ENDPOINTS) return NULL; __disable_irq(); ret = rx_first[endpoint]; if (ret) { rx_first[endpoint] = ret->next; usb_rx_byte_count_data[endpoint] -= ret->len; } __enable_irq(); //serial_print("rx, epidx="); //serial_phex(endpoint); //serial_print(", packet="); //serial_phex32(ret); //serial_print("\n"); return ret; } static uint32_t usb_queue_byte_count(const usb_packet_t *p) { uint32_t count=0; __disable_irq(); for ( ; p; p = p->next) { count += p->len; } __enable_irq(); return count; } // TODO: make this an inline function... /* uint32_t usb_rx_byte_count(uint32_t endpoint) { endpoint--; if (endpoint >= NUM_ENDPOINTS) return 0; return usb_rx_byte_count_data[endpoint]; //return usb_queue_byte_count(rx_first[endpoint]); } */ uint32_t usb_tx_byte_count(uint32_t endpoint) { endpoint--; if (endpoint >= NUM_ENDPOINTS) return 0; return usb_queue_byte_count(tx_first[endpoint]); } uint32_t usb_tx_packet_count(uint32_t endpoint) { const usb_packet_t *p; uint32_t count=0; endpoint--; if (endpoint >= NUM_ENDPOINTS) return 0; __disable_irq(); for (p = tx_first[endpoint]; p; p = p->next) count++; __enable_irq(); return count; } // Called from usb_free, but only when usb_rx_memory_needed > 0, indicating // receive endpoints are starving for memory. The intention is to give // endpoints needing receive memory priority over the user's code, which is // likely calling usb_malloc to obtain memory for transmitting. When the // user is creating data very quickly, their consumption could starve reception // without this prioritization. The packet buffer (input) is assigned to the // first endpoint needing memory. // void usb_rx_memory(usb_packet_t *packet) { unsigned int i; const uint8_t *cfg; cfg = usb_endpoint_config_table; //serial_print("rx_mem:"); __disable_irq(); for (i=1; i <= NUM_ENDPOINTS; i++) { if (*cfg++ & USB_ENDPT_EPRXEN) { if (table[index(i, RX, EVEN)].desc == 0) { table[index(i, RX, EVEN)].addr = packet->buf; table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); usb_rx_memory_needed--; __enable_irq(); //serial_phex(i); //serial_print(",even\n"); return; } if (table[index(i, RX, ODD)].desc == 0) { table[index(i, RX, ODD)].addr = packet->buf; table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); usb_rx_memory_needed--; __enable_irq(); //serial_phex(i); //serial_print(",odd\n"); return; } } } __enable_irq(); // we should never reach this point. If we get here, it means // usb_rx_memory_needed was set greater than zero, but no memory // was actually needed. usb_rx_memory_needed = 0; usb_free(packet); return; } //#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd)) //#define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) void usb_tx(uint32_t endpoint, usb_packet_t *packet) { bdt_t *b = &table[index(endpoint, TX, EVEN)]; uint8_t next; endpoint--; if (endpoint >= NUM_ENDPOINTS) return; __disable_irq(); //serial_print("txstate="); //serial_phex(tx_state[endpoint]); //serial_print("\n"); switch (tx_state[endpoint]) { case TX_STATE_BOTH_FREE_EVEN_FIRST: next = TX_STATE_ODD_FREE; break; case TX_STATE_BOTH_FREE_ODD_FIRST: b++; next = TX_STATE_EVEN_FREE; break; case TX_STATE_EVEN_FREE: next = TX_STATE_NONE_FREE_ODD_FIRST; break; case TX_STATE_ODD_FREE: b++; next = TX_STATE_NONE_FREE_EVEN_FIRST; break; default: if (tx_first[endpoint] == NULL) { tx_first[endpoint] = packet; } else { tx_last[endpoint]->next = packet; } tx_last[endpoint] = packet; __enable_irq(); return; } tx_state[endpoint] = next; b->addr = packet->buf; b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0); __enable_irq(); } void _reboot_Teensyduino_(void) { // TODO: initialize R0 with a code.... __asm__ volatile("bkpt"); } void usb_isr(void) { uint8_t status, stat, t; //serial_print("isr"); //status = USB0_ISTAT; //serial_phex(status); //serial_print("\n"); restart: status = USB0_ISTAT; if ((status & USB_INTEN_SOFTOKEN /* 04 */ )) { if (usb_configuration) { t = usb_reboot_timer; if (t) { usb_reboot_timer = --t; if (!t) _reboot_Teensyduino_(); } #ifdef CDC_DATA_INTERFACE t = usb_cdc_transmit_flush_timer; if (t) { usb_cdc_transmit_flush_timer = --t; if (t == 0) usb_serial_flush_callback(); } #endif #ifdef SEREMU_INTERFACE t = usb_seremu_transmit_flush_timer; if (t) { usb_seremu_transmit_flush_timer = --t; if (t == 0) usb_seremu_flush_callback(); } #endif #ifdef MIDI_INTERFACE usb_midi_flush_output(); #endif #ifdef FLIGHTSIM_INTERFACE usb_flightsim_flush_callback(); #endif } USB0_ISTAT = USB_INTEN_SOFTOKEN; } if ((status & USB_ISTAT_TOKDNE /* 08 */ )) { uint8_t endpoint; stat = USB0_STAT; //serial_print("token: ep="); //serial_phex(stat >> 4); //serial_print(stat & 0x08 ? ",tx" : ",rx"); //serial_print(stat & 0x04 ? ",odd\n" : ",even\n"); endpoint = stat >> 4; if (endpoint == 0) { usb_control(stat); } else { bdt_t *b = stat2bufferdescriptor(stat); usb_packet_t *packet = (usb_packet_t *)((uint8_t *)(b->addr) - 8); #if 0 serial_print("ep:"); serial_phex(endpoint); serial_print(", pid:"); serial_phex(BDT_PID(b->desc)); serial_print(((uint32_t)b & 8) ? ", odd" : ", even"); serial_print(", count:"); serial_phex(b->desc >> 16); serial_print("\n"); #endif endpoint--; // endpoint is index to zero-based arrays if (stat & 0x08) { // transmit usb_free(packet); packet = tx_first[endpoint]; if (packet) { //serial_print("tx packet\n"); tx_first[endpoint] = packet->next; b->addr = packet->buf; switch (tx_state[endpoint]) { case TX_STATE_BOTH_FREE_EVEN_FIRST: tx_state[endpoint] = TX_STATE_ODD_FREE; break; case TX_STATE_BOTH_FREE_ODD_FIRST: tx_state[endpoint] = TX_STATE_EVEN_FREE; break; case TX_STATE_EVEN_FREE: tx_state[endpoint] = TX_STATE_NONE_FREE_ODD_FIRST; break; case TX_STATE_ODD_FREE: tx_state[endpoint] = TX_STATE_NONE_FREE_EVEN_FIRST; break; default: break; } b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0); } else { //serial_print("tx no packet\n"); switch (tx_state[endpoint]) { case TX_STATE_BOTH_FREE_EVEN_FIRST: case TX_STATE_BOTH_FREE_ODD_FIRST: break; case TX_STATE_EVEN_FREE: tx_state[endpoint] = TX_STATE_BOTH_FREE_EVEN_FIRST; break; case TX_STATE_ODD_FREE: tx_state[endpoint] = TX_STATE_BOTH_FREE_ODD_FIRST; break; default: tx_state[endpoint] = ((uint32_t)b & 8) ? TX_STATE_ODD_FREE : TX_STATE_EVEN_FREE; break; } } } else { // receive packet->len = b->desc >> 16; if (packet->len > 0) { packet->index = 0; packet->next = NULL; if (rx_first[endpoint] == NULL) { //serial_print("rx 1st, epidx="); //serial_phex(endpoint); //serial_print(", packet="); //serial_phex32((uint32_t)packet); //serial_print("\n"); rx_first[endpoint] = packet; } else { //serial_print("rx Nth, epidx="); //serial_phex(endpoint); //serial_print(", packet="); //serial_phex32((uint32_t)packet); //serial_print("\n"); rx_last[endpoint]->next = packet; } rx_last[endpoint] = packet; usb_rx_byte_count_data[endpoint] += packet->len; // TODO: implement a per-endpoint maximum # of allocated packets // so a flood of incoming data on 1 endpoint doesn't starve // the others if the user isn't reading it regularly packet = usb_malloc(); if (packet) { b->addr = packet->buf; b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0); } else { //serial_print("starving "); //serial_phex(endpoint + 1); //serial_print(((uint32_t)b & 8) ? ",odd\n" : ",even\n"); b->desc = 0; usb_rx_memory_needed++; } } else { b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0); } } } USB0_ISTAT = USB_ISTAT_TOKDNE; goto restart; } if (status & USB_ISTAT_USBRST /* 01 */ ) { //serial_print("reset\n"); // initialize BDT toggle bits USB0_CTL = USB_CTL_ODDRST; ep0_tx_bdt_bank = 0; // set up buffers to receive Setup and OUT packets table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 0); table[index(0, RX, EVEN)].addr = ep0_rx0_buf; table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 0); table[index(0, RX, ODD)].addr = ep0_rx1_buf; table[index(0, TX, EVEN)].desc = 0; table[index(0, TX, ODD)].desc = 0; // activate endpoint 0 USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; // clear all ending interrupts USB0_ERRSTAT = 0xFF; USB0_ISTAT = 0xFF; // set the address to zero during enumeration USB0_ADDR = 0; // enable other interrupts USB0_ERREN = 0xFF; USB0_INTEN = USB_INTEN_TOKDNEEN | USB_INTEN_SOFTOKEN | USB_INTEN_STALLEN | USB_INTEN_ERROREN | USB_INTEN_USBRSTEN | USB_INTEN_SLEEPEN; // is this necessary? USB0_CTL = USB_CTL_USBENSOFEN; return; } if ((status & USB_ISTAT_STALL /* 80 */ )) { //serial_print("stall:\n"); USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; USB0_ISTAT = USB_ISTAT_STALL; } if ((status & USB_ISTAT_ERROR /* 02 */ )) { uint8_t err = USB0_ERRSTAT; USB0_ERRSTAT = err; //serial_print("err:"); //serial_phex(err); //serial_print("\n"); USB0_ISTAT = USB_ISTAT_ERROR; } if ((status & USB_ISTAT_SLEEP /* 10 */ )) { //serial_print("sleep\n"); USB0_ISTAT = USB_ISTAT_SLEEP; } } void usb_init(void) { int i; //serial_begin(BAUD2DIV(115200)); //serial_print("usb_init\n"); usb_init_serialnumber(); for (i=0; i <= NUM_ENDPOINTS*4; i++) { table[i].desc = 0; table[i].addr = 0; } // this basically follows the flowchart in the Kinetis // Quick Reference User Guide, Rev. 1, 03/2012, page 141 // assume 48 MHz clock already running // SIM - enable clock SIM_SCGC4 |= SIM_SCGC4_USBOTG; // reset USB module USB0_USBTRC0 = USB_USBTRC_USBRESET; while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end // set desc table base addr USB0_BDTPAGE1 = ((uint32_t)table) >> 8; USB0_BDTPAGE2 = ((uint32_t)table) >> 16; USB0_BDTPAGE3 = ((uint32_t)table) >> 24; // clear all ISR flags USB0_ISTAT = 0xFF; USB0_ERRSTAT = 0xFF; USB0_OTGISTAT = 0xFF; USB0_USBTRC0 |= 0x40; // undocumented bit // enable USB USB0_CTL = USB_CTL_USBENSOFEN; USB0_USBCTRL = 0; // enable reset interrupt USB0_INTEN = USB_INTEN_USBRSTEN; // enable interrupt in NVIC... NVIC_SET_PRIORITY(IRQ_USBOTG, 112); NVIC_ENABLE_IRQ(IRQ_USBOTG); // enable d+ pullup USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; } #else // F_CPU < 20 MHz void usb_init(void) { } #endif // F_CPU >= 20 MHz micropython-1.12/ports/teensy/core/usb_dev.h000066400000000000000000000064221357706137100212340ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef _usb_dev_h_ #define _usb_dev_h_ #if F_CPU >= 20000000 // This header is NOT meant to be included when compiling // user sketches in Arduino. The low-level functions // provided by usb_dev.c are meant to be called only by // code which provides higher-level interfaces to the user. #include "usb_mem.h" #include "usb_desc.h" #ifdef __cplusplus extern "C" { #endif void usb_init(void); void usb_init_serialnumber(void); void usb_isr(void); usb_packet_t *usb_rx(uint32_t endpoint); uint32_t usb_tx_byte_count(uint32_t endpoint); uint32_t usb_tx_packet_count(uint32_t endpoint); void usb_tx(uint32_t endpoint, usb_packet_t *packet); void usb_tx_isr(uint32_t endpoint, usb_packet_t *packet); extern volatile uint8_t usb_configuration; extern uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS]; static inline uint32_t usb_rx_byte_count(uint32_t endpoint) __attribute__((always_inline)); static inline uint32_t usb_rx_byte_count(uint32_t endpoint) { endpoint--; if (endpoint >= NUM_ENDPOINTS) return 0; return usb_rx_byte_count_data[endpoint]; } #ifdef CDC_DATA_INTERFACE extern uint32_t usb_cdc_line_coding[2]; extern volatile uint8_t usb_cdc_line_rtsdtr; extern volatile uint8_t usb_cdc_transmit_flush_timer; extern void usb_serial_flush_callback(void); #endif #ifdef SEREMU_INTERFACE extern volatile uint8_t usb_seremu_transmit_flush_timer; extern void usb_seremu_flush_callback(void); #endif #ifdef KEYBOARD_INTERFACE extern uint8_t keyboard_modifier_keys; extern uint8_t keyboard_keys[6]; extern uint8_t keyboard_protocol; extern uint8_t keyboard_idle_config; extern uint8_t keyboard_idle_count; extern volatile uint8_t keyboard_leds; #endif #ifdef MIDI_INTERFACE extern void usb_midi_flush_output(void); #endif #ifdef FLIGHTSIM_INTERFACE extern void usb_flightsim_flush_callback(void); #endif #ifdef __cplusplus } #endif #endif // F_CPU >= 20 MHz #endif micropython-1.12/ports/teensy/core/usb_mem.c000066400000000000000000000064571357706137100212370ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #if F_CPU >= 20000000 #include "mk20dx128.h" //#include "HardwareSerial.h" #include "usb_dev.h" #include "usb_mem.h" __attribute__ ((section(".usbbuffers"), used)) unsigned char usb_buffer_memory[NUM_USB_BUFFERS * sizeof(usb_packet_t)]; static uint32_t usb_buffer_available = 0xFFFFFFFF; // use bitmask and CLZ instruction to implement fast free list // http://www.archivum.info/gnu.gcc.help/2006-08/00148/Re-GCC-Inline-Assembly.html // http://gcc.gnu.org/ml/gcc/2012-06/msg00015.html // __builtin_clz() usb_packet_t * usb_malloc(void) { unsigned int n, avail; uint8_t *p; __disable_irq(); avail = usb_buffer_available; n = __builtin_clz(avail); // clz = count leading zeros if (n >= NUM_USB_BUFFERS) { __enable_irq(); return NULL; } //serial_print("malloc:"); //serial_phex(n); //serial_print("\n"); usb_buffer_available = avail & ~(0x80000000 >> n); __enable_irq(); p = usb_buffer_memory + (n * sizeof(usb_packet_t)); //serial_print("malloc:"); //serial_phex32((int)p); //serial_print("\n"); *(uint32_t *)p = 0; *(uint32_t *)(p + 4) = 0; return (usb_packet_t *)p; } // for the receive endpoints to request memory extern uint8_t usb_rx_memory_needed; extern void usb_rx_memory(usb_packet_t *packet); void usb_free(usb_packet_t *p) { unsigned int n, mask; //serial_print("free:"); n = ((uint8_t *)p - usb_buffer_memory) / sizeof(usb_packet_t); if (n >= NUM_USB_BUFFERS) return; //serial_phex(n); //serial_print("\n"); // if any endpoints are starving for memory to receive // packets, give this memory to them immediately! if (usb_rx_memory_needed && usb_configuration) { //serial_print("give to rx:"); //serial_phex32((int)p); //serial_print("\n"); usb_rx_memory(p); return; } mask = (0x80000000 >> n); __disable_irq(); usb_buffer_available |= mask; __enable_irq(); //serial_print("free:"); //serial_phex32((int)p); //serial_print("\n"); } #endif // F_CPU >= 20 MHz micropython-1.12/ports/teensy/core/usb_mem.h000066400000000000000000000033701357706137100212330ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef _usb_mem_h_ #define _usb_mem_h_ #include typedef struct usb_packet_struct { uint16_t len; uint16_t index; struct usb_packet_struct *next; uint8_t buf[64]; } usb_packet_t; #ifdef __cplusplus extern "C" { #endif usb_packet_t * usb_malloc(void); void usb_free(usb_packet_t *p); #ifdef __cplusplus } #endif #endif micropython-1.12/ports/teensy/core/usb_names.h000066400000000000000000000037621357706137100215650ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef _usb_names_h_ #define _usb_names_h_ // These definitions are intended to allow users to override the default // USB manufacturer, product and serial number strings. #include #ifdef __cplusplus extern "C" { #endif struct usb_string_descriptor_struct { uint8_t bLength; uint8_t bDescriptorType; uint16_t wString[]; }; extern struct usb_string_descriptor_struct usb_string_manufacturer_name; extern struct usb_string_descriptor_struct usb_string_product_name; extern struct usb_string_descriptor_struct usb_string_serial_number; #ifdef __cplusplus } #endif #endif micropython-1.12/ports/teensy/core/usb_serial.c000066400000000000000000000157741357706137100217420ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "usb_dev.h" #include "usb_serial.h" #include "core_pins.h" // for yield() //#include "HardwareSerial.h" #include // for memcpy() // defined by usb_dev.h -> usb_desc.h #if defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE) uint32_t usb_cdc_line_coding[2]; volatile uint8_t usb_cdc_line_rtsdtr=0; volatile uint8_t usb_cdc_transmit_flush_timer=0; static usb_packet_t *rx_packet=NULL; static usb_packet_t *tx_packet=NULL; static volatile uint8_t tx_noautoflush=0; #define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */ // get the next character, or -1 if nothing received int usb_serial_getchar(void) { unsigned int i; int c; if (!rx_packet) { if (!usb_configuration) return -1; rx_packet = usb_rx(CDC_RX_ENDPOINT); if (!rx_packet) return -1; } i = rx_packet->index; c = rx_packet->buf[i++]; if (i >= rx_packet->len) { usb_free(rx_packet); rx_packet = NULL; } else { rx_packet->index = i; } return c; } // peek at the next character, or -1 if nothing received int usb_serial_peekchar(void) { if (!rx_packet) { if (!usb_configuration) return -1; rx_packet = usb_rx(CDC_RX_ENDPOINT); if (!rx_packet) return -1; } if (!rx_packet) return -1; return rx_packet->buf[rx_packet->index]; } // number of bytes available in the receive buffer int usb_serial_available(void) { int count; count = usb_rx_byte_count(CDC_RX_ENDPOINT); if (rx_packet) count += rx_packet->len - rx_packet->index; return count; } // read a block of bytes to a buffer int usb_serial_read(void *buffer, uint32_t size) { uint8_t *p = (uint8_t *)buffer; uint32_t qty, count=0; while (size) { if (!usb_configuration) break; if (!rx_packet) { rx: rx_packet = usb_rx(CDC_RX_ENDPOINT); if (!rx_packet) break; if (rx_packet->len == 0) { usb_free(rx_packet); goto rx; } } qty = rx_packet->len - rx_packet->index; if (qty > size) qty = size; memcpy(p, rx_packet->buf + rx_packet->index, qty); p += qty; count += qty; size -= qty; rx_packet->index += qty; if (rx_packet->index >= rx_packet->len) { usb_free(rx_packet); rx_packet = NULL; } } return count; } // discard any buffered input void usb_serial_flush_input(void) { usb_packet_t *rx; if (!usb_configuration) return; if (rx_packet) { usb_free(rx_packet); rx_packet = NULL; } while (1) { rx = usb_rx(CDC_RX_ENDPOINT); if (!rx) break; usb_free(rx); } } // Maximum number of transmit packets to queue so we don't starve other endpoints for memory #define TX_PACKET_LIMIT 8 // When the PC isn't listening, how long do we wait before discarding data? If this is // too short, we risk losing data during the stalls that are common with ordinary desktop // software. If it's too long, we stall the user's program when no software is running. #define TX_TIMEOUT_MSEC 70 #if F_CPU == 168000000 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1100) #elif F_CPU == 144000000 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 932) #elif F_CPU == 120000000 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 764) #elif F_CPU == 96000000 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596) #elif F_CPU == 72000000 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 512) #elif F_CPU == 48000000 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428) #elif F_CPU == 24000000 #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262) #endif // When we've suffered the transmit timeout, don't wait again until the computer // begins accepting data. If no software is running to receive, we'll just discard // data as rapidly as Serial.print() can generate it, until there's something to // actually receive it. static uint8_t transmit_previous_timeout=0; // transmit a character. 0 returned on success, -1 on error int usb_serial_putchar(uint8_t c) { return usb_serial_write(&c, 1); } int usb_serial_write(const void *buffer, uint32_t size) { uint32_t len; uint32_t wait_count; const uint8_t *src = (const uint8_t *)buffer; uint8_t *dest; tx_noautoflush = 1; while (size > 0) { if (!tx_packet) { wait_count = 0; while (1) { if (!usb_configuration) { tx_noautoflush = 0; return -1; } if (usb_tx_packet_count(CDC_TX_ENDPOINT) < TX_PACKET_LIMIT) { tx_noautoflush = 1; tx_packet = usb_malloc(); if (tx_packet) break; tx_noautoflush = 0; } if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) { transmit_previous_timeout = 1; return -1; } yield(); } } transmit_previous_timeout = 0; len = CDC_TX_SIZE - tx_packet->index; if (len > size) len = size; dest = tx_packet->buf + tx_packet->index; tx_packet->index += len; size -= len; while (len-- > 0) *dest++ = *src++; if (tx_packet->index >= CDC_TX_SIZE) { tx_packet->len = CDC_TX_SIZE; usb_tx(CDC_TX_ENDPOINT, tx_packet); tx_packet = NULL; } usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT; } tx_noautoflush = 0; return 0; } void usb_serial_flush_output(void) { if (!usb_configuration) return; tx_noautoflush = 1; if (tx_packet) { usb_cdc_transmit_flush_timer = 0; tx_packet->len = tx_packet->index; usb_tx(CDC_TX_ENDPOINT, tx_packet); tx_packet = NULL; } else { usb_packet_t *tx = usb_malloc(); if (tx) { usb_cdc_transmit_flush_timer = 0; usb_tx(CDC_TX_ENDPOINT, tx); } else { usb_cdc_transmit_flush_timer = 1; } } tx_noautoflush = 0; } void usb_serial_flush_callback(void) { if (tx_noautoflush) return; if (tx_packet) { tx_packet->len = tx_packet->index; usb_tx(CDC_TX_ENDPOINT, tx_packet); tx_packet = NULL; } else { usb_packet_t *tx = usb_malloc(); if (tx) { usb_tx(CDC_TX_ENDPOINT, tx); } else { usb_cdc_transmit_flush_timer = 1; } } } #endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE micropython-1.12/ports/teensy/core/usb_serial.h000066400000000000000000000125101357706137100217300ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef USBserial_h_ #define USBserial_h_ #if defined(USB_SERIAL) || defined(USB_SERIAL_HID) #include #if F_CPU >= 20000000 // C language implementation #ifdef __cplusplus extern "C" { #endif int usb_serial_getchar(void); int usb_serial_peekchar(void); int usb_serial_available(void); int usb_serial_read(void *buffer, uint32_t size); void usb_serial_flush_input(void); int usb_serial_putchar(uint8_t c); int usb_serial_write(const void *buffer, uint32_t size); void usb_serial_flush_output(void); extern uint32_t usb_cdc_line_coding[2]; extern volatile uint8_t usb_cdc_line_rtsdtr; extern volatile uint8_t usb_cdc_transmit_flush_timer; extern volatile uint8_t usb_configuration; #ifdef __cplusplus } #endif #define USB_SERIAL_DTR 0x01 #define USB_SERIAL_RTS 0x02 // C++ interface #ifdef __cplusplus #include "Stream.h" class usb_serial_class : public Stream { public: void begin(long) { /* TODO: call a function that tries to wait for enumeration */ }; void end() { /* TODO: flush output and shut down USB port */ }; virtual int available() { return usb_serial_available(); } virtual int read() { return usb_serial_getchar(); } virtual int peek() { return usb_serial_peekchar(); } virtual void flush() { usb_serial_flush_output(); } // TODO: actually wait for data to leave USB... virtual size_t write(uint8_t c) { return usb_serial_putchar(c); } virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial_write(buffer, size); } size_t write(unsigned long n) { return write((uint8_t)n); } size_t write(long n) { return write((uint8_t)n); } size_t write(unsigned int n) { return write((uint8_t)n); } size_t write(int n) { return write((uint8_t)n); } using Print::write; void send_now(void) { usb_serial_flush_output(); } uint32_t baud(void) { return usb_cdc_line_coding[0]; } uint8_t stopbits(void) { uint8_t b = usb_cdc_line_coding[1]; if (!b) b = 1; return b; } uint8_t paritytype(void) { return usb_cdc_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even uint8_t numbits(void) { return usb_cdc_line_coding[1] >> 16; } uint8_t dtr(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; } uint8_t rts(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; } operator bool() { return usb_configuration && (usb_cdc_line_rtsdtr & (USB_SERIAL_DTR | USB_SERIAL_RTS)); } size_t readBytes(char *buffer, size_t length) { size_t count=0; unsigned long startMillis = millis(); do { count += usb_serial_read(buffer + count, length - count); if (count >= length) return count; } while(millis() - startMillis < _timeout); setReadError(); return count; } }; extern usb_serial_class Serial; #endif // __cplusplus #else // F_CPU < 20 MHz // Allow Arduino programs using Serial to compile, but Serial will do nothing. #ifdef __cplusplus #include "Stream.h" class usb_serial_class : public Stream { public: void begin(long) { }; void end() { }; virtual int available() { return 0; } virtual int read() { return -1; } virtual int peek() { return -1; } virtual void flush() { } virtual size_t write(uint8_t c) { return 1; } virtual size_t write(const uint8_t *buffer, size_t size) { return size; } size_t write(unsigned long n) { return 1; } size_t write(long n) { return 1; } size_t write(unsigned int n) { return 1; } size_t write(int n) { return 1; } using Print::write; void send_now(void) { } uint32_t baud(void) { return 0; } uint8_t stopbits(void) { return 1; } uint8_t paritytype(void) { return 0; } uint8_t numbits(void) { return 8; } uint8_t dtr(void) { return 1; } uint8_t rts(void) { return 1; } operator bool() { return true; } }; extern usb_serial_class Serial; #endif // __cplusplus #endif // F_CPU #endif // USB_SERIAL || USB_SERIAL_HID #endif // USBserial_h_ micropython-1.12/ports/teensy/core/yield.c000066400000000000000000000027441357706137100207110ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ void yield(void) __attribute__ ((weak)); void yield(void) {}; micropython-1.12/ports/teensy/hal_ftm.c000066400000000000000000000137041357706137100202630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "teensy_hal.h" void HAL_FTM_Base_Init(FTM_HandleTypeDef *hftm) { /* Check the parameters */ FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); assert_param(IS_FTM_PRESCALERSHIFT(hftm->Init.PrescalerShift)); assert_param(IS_FTM_COUNTERMODE(hftm->Init.CounterMode)); assert_param(IS_FTM_PERIOD(hftm->Init.Period)); hftm->State = HAL_FTM_STATE_BUSY; FTMx->MODE = FTM_MODE_WPDIS; FTMx->SC = 0; FTMx->MOD = hftm->Init.Period; uint32_t sc = FTM_SC_PS(hftm->Init.PrescalerShift); if (hftm->Init.CounterMode == FTM_COUNTERMODE_CENTER) { sc |= FTM_SC_CPWMS; } FTMx->SC = sc; hftm->State = HAL_FTM_STATE_READY; } void HAL_FTM_Base_Start(FTM_HandleTypeDef *hftm) { FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); hftm->State = HAL_FTM_STATE_BUSY; FTMx->CNT = 0; FTMx->SC &= ~FTM_SC_CLKS(3); FTMx->SC |= FTM_SC_CLKS(1); hftm->State = HAL_FTM_STATE_READY; } void HAL_FTM_Base_Start_IT(FTM_HandleTypeDef *hftm) { FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); hftm->State = HAL_FTM_STATE_BUSY; FTMx->CNT = 0; FTMx->SC |= FTM_SC_CLKS(1) | FTM_SC_TOIE; hftm->State = HAL_FTM_STATE_READY; } void HAL_FTM_Base_DeInit(FTM_HandleTypeDef *hftm) { assert_param(IS_FTM_INSTANCE(hftm->Instance)); hftm->State = HAL_FTM_STATE_BUSY; __HAL_FTM_DISABLE_TOF_IT(hftm); hftm->State = HAL_FTM_STATE_RESET; } void HAL_FTM_OC_Init(FTM_HandleTypeDef *hftm) { HAL_FTM_Base_Init(hftm); } void HAL_FTM_OC_ConfigChannel(FTM_HandleTypeDef *hftm, FTM_OC_InitTypeDef* sConfig, uint32_t channel) { FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); assert_param(IS_FTM_CHANNEL(channel)); assert_param(IS_FTM_OC_MODE(sConfig->OCMode)); assert_param(IS_FTM_OC_PULSE(sConfig->Pulse)); assert_param(IS_FTM_OC_POLARITY(sConfig->OCPolarity)); hftm->State = HAL_FTM_STATE_BUSY; FTMx->channel[channel].CSC = sConfig->OCMode; FTMx->channel[channel].CV = sConfig->Pulse; if (sConfig->OCPolarity & 1) { FTMx->POL |= (1 << channel); } else { FTMx->POL &= ~(1 << channel); } hftm->State = HAL_FTM_STATE_READY; } void HAL_FTM_OC_Start(FTM_HandleTypeDef *hftm, uint32_t channel) { // Nothing else to do } void HAL_FTM_OC_Start_IT(FTM_HandleTypeDef *hftm, uint32_t channel) { FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); FTMx->channel[channel].CSC |= FTM_CSC_CHIE; } void HAL_FTM_OC_DeInit(FTM_HandleTypeDef *hftm) { HAL_FTM_Base_DeInit(hftm); } void HAL_FTM_PWM_Init(FTM_HandleTypeDef *hftm) { HAL_FTM_Base_Init(hftm); } void HAL_FTM_PWM_ConfigChannel(FTM_HandleTypeDef *hftm, FTM_OC_InitTypeDef* sConfig, uint32_t channel) { FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); assert_param(IS_FTM_CHANNEL(channel)); assert_param(IS_FTM_PWM_MODE(sConfig->OCMode)); assert_param(IS_FTM_OC_PULSE(sConfig->Pulse)); assert_param(IS_FTM_OC_POLARITY(sConfig->OCPolarity)); hftm->State = HAL_FTM_STATE_BUSY; FTMx->channel[channel].CSC = sConfig->OCMode; FTMx->channel[channel].CV = sConfig->Pulse; if (sConfig->OCPolarity & 1) { FTMx->POL |= (1 << channel); } else { FTMx->POL &= ~(1 << channel); } hftm->State = HAL_FTM_STATE_READY; } void HAL_FTM_PWM_Start(FTM_HandleTypeDef *hftm, uint32_t channel) { // Nothing else to do } void HAL_FTM_PWM_Start_IT(FTM_HandleTypeDef *hftm, uint32_t channel) { FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); FTMx->channel[channel].CSC |= FTM_CSC_CHIE; } void HAL_FTM_PWM_DeInit(FTM_HandleTypeDef *hftm) { HAL_FTM_Base_DeInit(hftm); } void HAL_FTM_IC_Init(FTM_HandleTypeDef *hftm) { HAL_FTM_Base_Init(hftm); } void HAL_FTM_IC_ConfigChannel(FTM_HandleTypeDef *hftm, FTM_IC_InitTypeDef* sConfig, uint32_t channel) { FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); assert_param(IS_FTM_CHANNEL(channel)); assert_param(IS_FTM_IC_POLARITY(sConfig->ICPolarity)); hftm->State = HAL_FTM_STATE_BUSY; FTMx->channel[channel].CSC = sConfig->ICPolarity; hftm->State = HAL_FTM_STATE_READY; } void HAL_FTM_IC_Start(FTM_HandleTypeDef *hftm, uint32_t channel) { //FTM_TypeDef *FTMx = hftm->Instance; //assert_param(IS_FTM_INSTANCE(FTMx)); // Nothing else to do } void HAL_FTM_IC_Start_IT(FTM_HandleTypeDef *hftm, uint32_t channel) { FTM_TypeDef *FTMx = hftm->Instance; assert_param(IS_FTM_INSTANCE(FTMx)); FTMx->channel[channel].CSC |= FTM_CSC_CHIE; } void HAL_FTM_IC_DeInit(FTM_HandleTypeDef *hftm) { HAL_FTM_Base_DeInit(hftm); } micropython-1.12/ports/teensy/hal_ftm.h000066400000000000000000000200751357706137100202670ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_TEENSY_HAL_FTM_H #define MICROPY_INCLUDED_TEENSY_HAL_FTM_H #define FTM0 ((FTM_TypeDef *)&FTM0_SC) #define FTM1 ((FTM_TypeDef *)&FTM1_SC) #define FTM2 ((FTM_TypeDef *)&FTM2_SC) typedef struct { volatile uint32_t CSC; // Channel x Status And Control volatile uint32_t CV; // Channel x Value } FTM_ChannelTypeDef; typedef struct { volatile uint32_t SC; // Status And Control volatile uint32_t CNT; // Counter volatile uint32_t MOD; // Modulo FTM_ChannelTypeDef channel[8]; volatile uint32_t CNTIN; // Counter Initial Value volatile uint32_t STATUS; // Capture And Compare Status volatile uint32_t MODE; // Features Mode Selection volatile uint32_t SYNC; // Synchronization volatile uint32_t OUTINIT; // Initial State For Channels Output volatile uint32_t OUTMASK; // Output Mask volatile uint32_t COMBINE; // Function For Linked Channels volatile uint32_t DEADTIME; // Deadtime Insertion Control volatile uint32_t EXTTRIG; // FTM External Trigger volatile uint32_t POL; // Channels Polarity volatile uint32_t FMS; // Fault Mode Status volatile uint32_t FILTER; // Input Capture Filter Control volatile uint32_t FLTCTRL; // Fault Control volatile uint32_t QDCTRL; // Quadrature Decoder Control And Status volatile uint32_t CONF; // Configuration volatile uint32_t FLTPOL; // FTM Fault Input Polarity volatile uint32_t SYNCONF; // Synchronization Configuration volatile uint32_t INVCTRL; // FTM Inverting Control volatile uint32_t SWOCTRL; // FTM Software Output Control volatile uint32_t PWMLOAD; // FTM PWM Load } FTM_TypeDef; typedef struct { uint32_t PrescalerShift; // Sets the prescaler to 1 << PrescalerShift uint32_t CounterMode; // One of FTM_COUNTERMODE_xxx uint32_t Period; // Specifies the Period for determining timer overflow } FTM_Base_InitTypeDef; typedef struct { uint32_t OCMode; // One of FTM_OCMODE_xxx uint32_t Pulse; // Specifies initial pulse width (0-0xffff) uint32_t OCPolarity; // One of FTM_OCPOLRITY_xxx } FTM_OC_InitTypeDef; typedef struct { uint32_t ICPolarity; // Specifies Rising/Falling/Both } FTM_IC_InitTypeDef; #define IS_FTM_INSTANCE(INSTANCE) (((INSTANCE) == FTM0) || \ ((INSTANCE) == FTM1) || \ ((INSTANCE) == FTM2)) #define IS_FTM_PRESCALERSHIFT(PRESCALERSHIFT) (((PRESCALERSHIFT) & ~7) == 0) #define FTM_COUNTERMODE_UP (0) #define FTM_COUNTERMODE_CENTER (FTM_SC_CPWMS) #define IS_FTM_COUNTERMODE(MODE) (((MODE) == FTM_COUNTERMODE_UP) ||\ ((MODE) == FTM_COUNTERMODE_CENTER)) #define IS_FTM_PERIOD(PERIOD) (((PERIOD) & 0xFFFF0000) == 0) #define FTM_CSC_CHF 0x80 #define FTM_CSC_CHIE 0x40 #define FTM_CSC_MSB 0x20 #define FTM_CSC_MSA 0x10 #define FTM_CSC_ELSB 0x08 #define FTM_CSC_ELSA 0x04 #define FTM_CSC_DMA 0x01 #define FTM_OCMODE_TIMING (0) #define FTM_OCMODE_ACTIVE (FTM_CSC_MSA | FTM_CSC_ELSB | FTM_CSC_ELSA) #define FTM_OCMODE_INACTIVE (FTM_CSC_MSA | FTM_CSC_ELSB) #define FTM_OCMODE_TOGGLE (FTM_CSC_MSA | FTM_CSC_ELSA) #define FTM_OCMODE_PWM1 (FTM_CSC_MSB | FTM_CSC_ELSB) #define FTM_OCMODE_PWM2 (FTM_CSC_MSB | FTM_CSC_ELSA) #define IS_FTM_OC_MODE(mode) ((mode) == FTM_OCMODE_TIMING || \ (mode) == FTM_OCMODE_ACTIVE || \ (mode) == FTM_OCMODE_INACTIVE || \ (mode) == FTM_OCMODE_TOGGLE ) #define IS_FTM_PWM_MODE(mode) ((mode) == FTM_OCMODE_PWM1 || \ (mode) == FTM_OCMODE_PWM2) #define IS_FTM_CHANNEL(channel) (((channel) & ~7) == 0) #define IS_FTM_PULSE(pulse) (((pulse) & ~0xffff) == 0) #define FTM_OCPOLARITY_HIGH (0) #define FTM_OCPOLARITY_LOW (1) #define IS_FTM_OC_POLARITY(polarity) ((polarity) == FTM_OCPOLARITY_HIGH || \ (polarity) == FTM_OCPOLARITY_LOW) #define FTM_ICPOLARITY_RISING (FTM_CSC_ELSA) #define FTM_ICPOLARITY_FALLING (FTM_CSC_ELSB) #define FTM_ICPOLARITY_BOTH (FTM_CSC_ELSA | FTM_CSC_ELSB) #define IS_FTM_IC_POLARITY(polarity) ((polarity) == FTM_ICPOLARITY_RISING || \ (polarity) == FTM_ICPOLARITY_FALLING || \ (polarity) == FTM_ICPOLARITY_BOTH) typedef enum { HAL_FTM_STATE_RESET = 0x00, HAL_FTM_STATE_READY = 0x01, HAL_FTM_STATE_BUSY = 0x02, } HAL_FTM_State; typedef struct { FTM_TypeDef *Instance; FTM_Base_InitTypeDef Init; HAL_FTM_State State; } FTM_HandleTypeDef; #define __HAL_FTM_GET_TOF_FLAG(HANDLE) (((HANDLE)->Instance->SC & FTM_SC_TOF) != 0) #define __HAL_FTM_CLEAR_TOF_FLAG(HANDLE) ((HANDLE)->Instance->SC &= ~FTM_SC_TOF) #define __HAL_FTM_GET_TOF_IT(HANDLE) (((HANDLE)->Instance->SC & FTM_SC_TOIE) != 0) #define __HAL_FTM_ENABLE_TOF_IT(HANDLE) ((HANDLE)->Instance->SC |= FTM_SC_TOIE) #define __HAL_FTM_DISABLE_TOF_IT(HANDLE) ((HANDLE)->Instance->SC &= ~FTM_SC_TOIE) #define __HAL_FTM_GET_CH_FLAG(HANDLE, CH) (((HANDLE)->Instance->channel[CH].CSC & FTM_CSC_CHF) != 0) #define __HAL_FTM_CLEAR_CH_FLAG(HANDLE, CH) ((HANDLE)->Instance->channel[CH].CSC &= ~FTM_CSC_CHF) #define __HAL_FTM_GET_CH_IT(HANDLE, CH) (((HANDLE)->Instance->channel[CH].CSC & FTM_CSC_CHIE) != 0) #define __HAL_FTM_ENABLE_CH_IT(HANDLE, CH) ((HANDLE)->Instance->channel[CH].CSC |= FTM_CSC_CHIE) #define __HAL_FTM_DISABLE_CH_IT(HANDLE, CH) ((HANDLE)->Instance->channel[CH].CSC &= ~FTM_CSC_CHIE) void HAL_FTM_Base_Init(FTM_HandleTypeDef *hftm); void HAL_FTM_Base_Start(FTM_HandleTypeDef *hftm); void HAL_FTM_Base_Start_IT(FTM_HandleTypeDef *hftm); void HAL_FTM_Base_DeInit(FTM_HandleTypeDef *hftm); void HAL_FTM_OC_Init(FTM_HandleTypeDef *hftm); void HAL_FTM_OC_ConfigChannel(FTM_HandleTypeDef *hftm, FTM_OC_InitTypeDef* sConfig, uint32_t channel); void HAL_FTM_OC_Start(FTM_HandleTypeDef *hftm, uint32_t channel); void HAL_FTM_OC_Start_IT(FTM_HandleTypeDef *hftm, uint32_t channel); void HAL_FTM_OC_DeInit(FTM_HandleTypeDef *hftm); void HAL_FTM_PWM_Init(FTM_HandleTypeDef *hftm); void HAL_FTM_PWM_ConfigChannel(FTM_HandleTypeDef *hftm, FTM_OC_InitTypeDef* sConfig, uint32_t channel); void HAL_FTM_PWM_Start(FTM_HandleTypeDef *hftm, uint32_t channel); void HAL_FTM_PWM_Start_IT(FTM_HandleTypeDef *hftm, uint32_t channel); void HAL_FTM_PWM_DeInit(FTM_HandleTypeDef *hftm); void HAL_FTM_IC_Init(FTM_HandleTypeDef *hftm); void HAL_FTM_IC_ConfigChannel(FTM_HandleTypeDef *hftm, FTM_IC_InitTypeDef* sConfig, uint32_t channel); void HAL_FTM_IC_Start(FTM_HandleTypeDef *hftm, uint32_t channel); void HAL_FTM_IC_Start_IT(FTM_HandleTypeDef *hftm, uint32_t channel); void HAL_FTM_IC_DeInit(FTM_HandleTypeDef *hftm); #endif // MICROPY_INCLUDED_TEENSY_HAL_FTM_H micropython-1.12/ports/teensy/hal_gpio.c000066400000000000000000000102731357706137100204310ustar00rootroot00000000000000#include #include #include "teensy_hal.h" #define GPIO_NUMBER 32 void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) { /* Check the parameters */ assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); /* Configure the port pins */ for (uint32_t position = 0; position < GPIO_NUMBER; position++) { uint32_t bitmask = 1 << position; if ((GPIO_Init->Pin & bitmask) == 0) { continue; } volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(GPIOx, position); /*--------------------- GPIO Mode Configuration ------------------------*/ /* In case of Alternate function mode selection */ if ((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) { /* Check the Alternate function parameter */ assert_param(IS_GPIO_AF(GPIO_Init->Alternate)); } else if (GPIO_Init->Mode == GPIO_MODE_ANALOG) { GPIO_Init->Alternate = 0; } else { GPIO_Init->Alternate = 1; } /* Configure Alternate function mapped with the current IO */ *port_pcr &= ~PORT_PCR_MUX_MASK; *port_pcr |= PORT_PCR_MUX(GPIO_Init->Alternate); /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ if (GPIO_Init->Mode == GPIO_MODE_INPUT || GPIO_Init->Mode == GPIO_MODE_ANALOG) { GPIOx->PDDR &= ~bitmask; } else { GPIOx->PDDR |= bitmask; } /* In case of Output or Alternate function mode selection */ if ((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) { /* Check the Speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); *port_pcr |= PORT_PCR_DSE; /* Configure the IO Speed */ if (GPIO_Init->Speed > GPIO_SPEED_FREQ_MEDIUM) { *port_pcr &= ~PORT_PCR_SRE; } else { *port_pcr |= PORT_PCR_SRE; } /* Configure the IO Output Type */ if (GPIO_Init->Mode & GPIO_OUTPUT_TYPE) { *port_pcr |= PORT_PCR_ODE; // OD } else { *port_pcr &= ~PORT_PCR_ODE; // PP } } else { *port_pcr &= ~PORT_PCR_DSE; } /* Activate the Pull-up or Pull down resistor for the current IO */ if (GPIO_Init->Pull == GPIO_NOPULL) { *port_pcr &= ~PORT_PCR_PE; } else { *port_pcr |= PORT_PCR_PE; if (GPIO_Init->Pull == GPIO_PULLDOWN) { *port_pcr &= ~PORT_PCR_PS; } else { *port_pcr |= PORT_PCR_PS; } } #if 0 /*--------------------- EXTI Mode Configuration ------------------------*/ /* Configure the External Interrupt or event for the current IO */ if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) { /* Enable SYSCFG Clock */ __SYSCFG_CLK_ENABLE(); temp = ((uint32_t)0x0F) << (4 * (position & 0x03)); SYSCFG->EXTICR[position >> 2] &= ~temp; SYSCFG->EXTICR[position >> 2] |= ((uint32_t)(__HAL_GET_GPIO_SOURCE(GPIOx)) << (4 * (position & 0x03))); /* Clear EXTI line configuration */ EXTI->IMR &= ~((uint32_t)iocurrent); EXTI->EMR &= ~((uint32_t)iocurrent); if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) { EXTI->IMR |= iocurrent; } if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) { EXTI->EMR |= iocurrent; } /* Clear Rising Falling edge configuration */ EXTI->RTSR &= ~((uint32_t)iocurrent); EXTI->FTSR &= ~((uint32_t)iocurrent); if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) { EXTI->RTSR |= iocurrent; } if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) { EXTI->FTSR |= iocurrent; } } #endif } } micropython-1.12/ports/teensy/help.c000066400000000000000000000065111357706137100175770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" const char teensy_help_text[] = "Welcome to MicroPython!\n" "\n" "For online help please visit http://micropython.org/help/.\n" "\n" "Quick overview of commands for the board:\n" " pyb.info() -- print some general information\n" " pyb.gc() -- run the garbage collector\n" " pyb.delay(n) -- wait for n milliseconds\n" " pyb.Switch() -- create a switch object\n" " Switch methods: (), callback(f)\n" " pyb.LED(n) -- create an LED object for LED n (n=1,2,3,4)\n" " LED methods: on(), off(), toggle(), intensity()\n" " pyb.Pin(pin) -- get a pin, eg pyb.Pin('X1')\n" " pyb.Pin(pin, m, [p]) -- get a pin and configure it for IO mode m, pull mode p\n" " Pin methods: init(..), value([v]), high(), low()\n" " pyb.ExtInt(pin, m, p, callback) -- create an external interrupt object\n" " pyb.ADC(pin) -- make an analog object from a pin\n" " ADC methods: read(), read_timed(buf, freq)\n" " pyb.DAC(port) -- make a DAC object\n" " DAC methods: triangle(freq), write(n), write_timed(buf, freq)\n" " pyb.RTC() -- make an RTC object; methods: datetime([val])\n" " pyb.rng() -- get a 30-bit hardware random number\n" " pyb.Servo(n) -- create Servo object for servo n (n=1,2,3,4)\n" " Servo methods: calibration(..), angle([x, [t]]), speed([x, [t]])\n" " pyb.Accel() -- create an Accelerometer object\n" " Accelerometer methods: x(), y(), z(), tilt(), filtered_xyz()\n" "\n" "Pins are numbered X1-X12, X17-X22, Y1-Y12, or by their MCU name\n" "Pin IO modes are: pyb.Pin.IN, pyb.Pin.OUT_PP, pyb.Pin.OUT_OD\n" "Pin pull modes are: pyb.Pin.PULL_NONE, pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN\n" "Additional serial bus objects: pyb.I2C(n), pyb.SPI(n), pyb.UART(n)\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" " CTRL-B -- on a blank line, enter normal REPL mode\n" " CTRL-C -- interrupt a running program\n" " CTRL-D -- on a blank line, do a soft reset of the board\n" "\n" "For further help on a specific object, type help(obj)\n" ; micropython-1.12/ports/teensy/lcd.c000066400000000000000000000003311357706137100174030ustar00rootroot00000000000000#include "py/obj.h" #include "../stm32/lcd.h" void lcd_init(void) { } void lcd_print_str(const char *str) { (void)str; } void lcd_print_strn(const char *str, unsigned int len) { (void)str; (void)len; } micropython-1.12/ports/teensy/led.c000066400000000000000000000100661357706137100174130ustar00rootroot00000000000000#include #include "Arduino.h" #include "py/runtime.h" #include "py/mphal.h" #include "led.h" #include "pin.h" #include "genhdr/pins.h" typedef struct _pyb_led_obj_t { mp_obj_base_t base; mp_uint_t led_id; const pin_obj_t *led_pin; } pyb_led_obj_t; STATIC const pyb_led_obj_t pyb_led_obj[] = { {{&pyb_led_type}, 1, &MICROPY_HW_LED1}, #if defined(MICROPY_HW_LED2) {{&pyb_led_type}, 2, &MICROPY_HW_LED2}, #if defined(MICROPY_HW_LED3) {{&pyb_led_type}, 3, &MICROPY_HW_LED3}, #if defined(MICROPY_HW_LED4) {{&pyb_led_type}, 4, &MICROPY_HW_LED4}, #endif #endif #endif }; #define NUM_LEDS MP_ARRAY_SIZE(pyb_led_obj) void led_init(void) { /* GPIO structure */ GPIO_InitTypeDef GPIO_InitStructure; /* Configure I/O speed, mode, output type and pull */ GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStructure.Mode = MICROPY_HW_LED_OTYPE; GPIO_InitStructure.Pull = GPIO_NOPULL; /* Turn off LEDs and initialize */ for (int led = 0; led < NUM_LEDS; led++) { const pin_obj_t *led_pin = pyb_led_obj[led].led_pin; MICROPY_HW_LED_OFF(led_pin); GPIO_InitStructure.Pin = led_pin->pin_mask; HAL_GPIO_Init(led_pin->gpio, &GPIO_InitStructure); } } void led_state(pyb_led_t led, int state) { if (led < 1 || led > NUM_LEDS) { return; } const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin; //printf("led_state(%d,%d)\n", led, state); if (state == 0) { // turn LED off MICROPY_HW_LED_OFF(led_pin); } else { // turn LED on MICROPY_HW_LED_ON(led_pin); } } void led_toggle(pyb_led_t led) { if (led < 1 || led > NUM_LEDS) { return; } const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin; GPIO_TypeDef *gpio = led_pin->gpio; // We don't know if we're turning the LED on or off, but we don't really // care. Just invert the state. if (gpio->PDOR & led_pin->pin_mask) { // pin is high, make it low gpio->PCOR = led_pin->pin_mask; } else { // pin is low, make it high gpio->PSOR = led_pin->pin_mask; } } /******************************************************************************/ /* MicroPython bindings */ void led_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_led_obj_t *self = self_in; (void)kind; mp_printf(print, "", self->led_id); } STATIC mp_obj_t led_obj_make_new(const mp_obj_type_t *type, uint n_args, uint n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); // get led number mp_int_t led_id = mp_obj_get_int(args[0]); // check led number if (!(1 <= led_id && led_id <= NUM_LEDS)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "LED %d does not exist", led_id)); } // return static led object return (mp_obj_t)&pyb_led_obj[led_id - 1]; } mp_obj_t led_obj_on(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_state(self->led_id, 1); return mp_const_none; } mp_obj_t led_obj_off(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_state(self->led_id, 0); return mp_const_none; } mp_obj_t led_obj_toggle(mp_obj_t self_in) { pyb_led_obj_t *self = self_in; led_toggle(self->led_id); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on); STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off); STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_toggle_obj, led_obj_toggle); STATIC const mp_rom_map_elem_t led_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&led_obj_on_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&led_obj_off_obj) }, { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj) }, }; STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table); const mp_obj_type_t pyb_led_type = { { &mp_type_type }, .name = MP_QSTR_LED, .print = led_obj_print, .make_new = led_obj_make_new, .locals_dict = (mp_obj_t)&led_locals_dict, }; micropython-1.12/ports/teensy/led.h000066400000000000000000000004651357706137100174220ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_TEENSY_LED_H #define MICROPY_INCLUDED_TEENSY_LED_H typedef enum { PYB_LED_BUILTIN = 1, } pyb_led_t; void led_init(void); void led_state(pyb_led_t led, int state); void led_toggle(pyb_led_t led); extern const mp_obj_type_t pyb_led_type; #endif // MICROPY_INCLUDED_TEENSY_LED_H micropython-1.12/ports/teensy/lexerfrozen.c000066400000000000000000000004241357706137100212070ustar00rootroot00000000000000#include #include "py/lexer.h" #include "py/runtime.h" #include "py/mperrno.h" mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } micropython-1.12/ports/teensy/lexermemzip.h000066400000000000000000000003171357706137100212130ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_TEENSY_LEXERMEMZIP_H #define MICROPY_INCLUDED_TEENSY_LEXERMEMZIP_H mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename); #endif // MICROPY_INCLUDED_TEENSY_LEXERMEMZIP_H micropython-1.12/ports/teensy/main.c000066400000000000000000000233311357706137100175720ustar00rootroot00000000000000#include #include #include #include #include "py/lexer.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" #include "py/mphal.h" #include "gccollect.h" #include "lib/utils/pyexec.h" #include "lib/mp-readline/readline.h" #include "lexermemzip.h" #include "Arduino.h" #include "servo.h" #include "led.h" #include "uart.h" #include "pin.h" extern uint32_t _heap_start; void flash_error(int n) { for (int i = 0; i < n; i++) { led_state(PYB_LED_BUILTIN, 1); delay(250); led_state(PYB_LED_BUILTIN, 0); delay(250); } } void NORETURN __fatal_error(const char *msg) { for (volatile uint delay = 0; delay < 10000000; delay++) { } led_state(1, 1); led_state(2, 1); led_state(3, 1); led_state(4, 1); mp_hal_stdout_tx_strn("\nFATAL ERROR:\n", 14); mp_hal_stdout_tx_strn(msg, strlen(msg)); for (uint i = 0;;) { led_toggle(((i++) & 3) + 1); for (volatile uint delay = 0; delay < 10000000; delay++) { } if (i >= 16) { // to conserve power __WFI(); } } } void nlr_jump_fail(void *val) { printf("FATAL: uncaught exception %p\n", val); __fatal_error(""); } void __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion failed: %s, file %s, line %d\n", expr, file, line); __fatal_error(""); } mp_obj_t pyb_analog_read(mp_obj_t pin_obj) { uint pin = mp_obj_get_int(pin_obj); int val = analogRead(pin); return MP_OBJ_NEW_SMALL_INT(val); } mp_obj_t pyb_analog_write(mp_obj_t pin_obj, mp_obj_t val_obj) { uint pin = mp_obj_get_int(pin_obj); int val = mp_obj_get_int(val_obj); analogWrite(pin, val); return mp_const_none; } mp_obj_t pyb_analog_write_resolution(mp_obj_t res_obj) { int res = mp_obj_get_int(res_obj); analogWriteResolution(res); return mp_const_none; } mp_obj_t pyb_analog_write_frequency(mp_obj_t pin_obj, mp_obj_t freq_obj) { uint pin = mp_obj_get_int(pin_obj); int freq = mp_obj_get_int(freq_obj); analogWriteFrequency(pin, freq); return mp_const_none; } #if 0 // get lots of info about the board static mp_obj_t pyb_info(void) { // get and print unique id; 96 bits { byte *id = (byte*)0x40048058; printf("ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]); } // get and print clock speeds printf("CPU=%u\nBUS=%u\nMEM=%u\n", F_CPU, F_BUS, F_MEM); // to print info about memory { printf("_sdata=%p\n", &_sdata); printf("_edata=%p\n", &_edata); printf("_sbss=%p\n", &_sbss); printf("_ebss=%p\n", &_ebss); printf("_estack=%p\n", &_estack); printf("_etext=%p\n", &_etext); printf("_heap_start=%p\n", &_heap_start); } // GC info { gc_info_t info; gc_info(&info); printf("GC:\n"); printf(" %u total\n", info.total); printf(" %u used %u free\n", info.used, info.free); printf(" 1=%u 2=%u m=%u\n", info.num_1block, info.num_2block, info.max_block); } #if 0 // free space on flash { DWORD nclst; FATFS *fatfs; f_getfree("0:", &nclst, &fatfs); printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512)); } #endif return mp_const_none; } #endif #define RAM_START (0x1FFF8000) // fixed for chip #define HEAP_END (0x20006000) // tunable #define RAM_END (0x20008000) // fixed for chip #if 0 void gc_helper_get_regs_and_clean_stack(mp_uint_t *regs, mp_uint_t heap_end); mp_obj_t pyb_gc(void) { gc_collect(); return mp_const_none; } mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) { //assert(1 <= n_args && n_args <= 2); uint pin = mp_obj_get_int(args[0]); if (pin > CORE_NUM_DIGITAL) { goto pin_error; } if (n_args == 1) { // get pin pinMode(pin, INPUT); return MP_OBJ_NEW_SMALL_INT(digitalRead(pin)); } // set pin pinMode(pin, OUTPUT); digitalWrite(pin, mp_obj_is_true(args[1])); return mp_const_none; pin_error: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %d does not exist", pin)); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio); #if 0 mp_obj_t pyb_hid_send_report(mp_obj_t arg) { mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4); uint8_t data[4]; data[0] = mp_obj_get_int(items[0]); data[1] = mp_obj_get_int(items[1]); data[2] = mp_obj_get_int(items[2]); data[3] = mp_obj_get_int(items[3]); usb_hid_send_report(data); return mp_const_none; } #endif #endif // 0 STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL; STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL; STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL; mp_obj_t pyb_source_dir(mp_obj_t source_dir) { if (mp_obj_is_str(source_dir)) { pyb_config_source_dir = source_dir; } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(pyb_source_dir_obj, pyb_source_dir); mp_obj_t pyb_main(mp_obj_t main) { if (mp_obj_is_str(main)) { pyb_config_main = main; } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(pyb_main_obj, pyb_main); STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) { if (mp_obj_is_str(usb_mode)) { pyb_config_usb_mode = usb_mode; } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode); #if 0 mp_obj_t pyb_delay(mp_obj_t count) { delay(mp_obj_get_int(count)); return mp_const_none; } mp_obj_t pyb_led(mp_obj_t state) { led_state(PYB_LED_BUILTIN, mp_obj_is_true(state)); return state; } #endif // 0 #if 0 char *strdup(const char *str) { uint32_t len = strlen(str); char *s2 = m_new(char, len + 1); memcpy(s2, str, len); s2[len] = 0; return s2; } #endif int main(void) { // TODO: Put this in a more common initialization function. // Turn on STKALIGN which keeps the stack 8-byte aligned for interrupts // (per EABI) #define SCB_CCR_STKALIGN (1 << 9) SCB_CCR |= SCB_CCR_STKALIGN; mp_stack_ctrl_init(); mp_stack_set_limit(10240); pinMode(LED_BUILTIN, OUTPUT); led_init(); // int first_soft_reset = true; soft_reset: led_state(PYB_LED_BUILTIN, 1); // GC init gc_init(&_heap_start, (void*)HEAP_END); // MicroPython init mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) mp_obj_list_init(mp_sys_argv, 0); readline_init0(); pin_init0(); #if 0 // add some functions to the python namespace { mp_store_name(MP_QSTR_help, mp_make_function_n(0, pyb_help)); mp_obj_t m = mp_obj_new_module(MP_QSTR_pyb); mp_store_attr(m, MP_QSTR_info, mp_make_function_n(0, pyb_info)); mp_store_attr(m, MP_QSTR_source_dir, mp_make_function_n(1, pyb_source_dir)); mp_store_attr(m, MP_QSTR_main, mp_make_function_n(1, pyb_main)); mp_store_attr(m, MP_QSTR_gc, mp_make_function_n(0, pyb_gc)); mp_store_attr(m, MP_QSTR_delay, mp_make_function_n(1, pyb_delay)); mp_store_attr(m, MP_QSTR_led, mp_make_function_n(1, pyb_led)); mp_store_attr(m, MP_QSTR_LED, (mp_obj_t)&pyb_led_type); mp_store_attr(m, MP_QSTR_analogRead, mp_make_function_n(1, pyb_analog_read)); mp_store_attr(m, MP_QSTR_analogWrite, mp_make_function_n(2, pyb_analog_write)); mp_store_attr(m, MP_QSTR_analogWriteResolution, mp_make_function_n(1, pyb_analog_write_resolution)); mp_store_attr(m, MP_QSTR_analogWriteFrequency, mp_make_function_n(2, pyb_analog_write_frequency)); mp_store_attr(m, MP_QSTR_gpio, (mp_obj_t)&pyb_gpio_obj); mp_store_attr(m, MP_QSTR_Servo, mp_make_function_n(0, pyb_Servo)); mp_store_name(MP_QSTR_pyb, m); } #endif #if MICROPY_MODULE_FROZEN pyexec_frozen_module("boot.py"); #else if (!pyexec_file_if_exists("/boot.py")) { flash_error(4); } #endif // Turn bootup LED off led_state(PYB_LED_BUILTIN, 0); // run main script #if MICROPY_MODULE_FROZEN pyexec_frozen_module("main.py"); #else { vstr_t *vstr = vstr_new(16); vstr_add_str(vstr, "/"); if (pyb_config_main == MP_OBJ_NULL) { vstr_add_str(vstr, "main.py"); } else { vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main)); } if (!pyexec_file_if_exists(vstr_null_terminated_str(vstr))) { flash_error(3); } vstr_free(vstr); } #endif // enter REPL // REPL mode can change, or it can request a soft reset for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } printf("MPY: soft reboot\n"); // first_soft_reset = false; goto soft_reset; } // stub out __libc_init_array. It's called by mk20dx128.c and is used to call // global C++ constructors. Since this is a C-only projects, we don't need to // call constructors. void __libc_init_array(void) { } // ultoa is used by usb_init_serialnumber. Normally ultoa would be provided // by nonstd.c from the teensy core, but it conflicts with some of the // MicroPython functions in string0.c, so we provide ultoa here. char * ultoa(unsigned long val, char *buf, int radix) { unsigned digit; int i=0, j; char t; while (1) { digit = val % radix; buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10); val /= radix; if (val == 0) break; i++; } buf[i + 1] = 0; for (j=0; j < i; j++, i--) { t = buf[j]; buf[j] = buf[i]; buf[i] = t; } return buf; } micropython-1.12/ports/teensy/make-pins.py000077500000000000000000000330071357706137100207440ustar00rootroot00000000000000#!/usr/bin/env python """Creates the pin file for the Teensy.""" from __future__ import print_function import argparse import sys import csv SUPPORTED_FN = { 'FTM' : ['CH0', 'CH1', 'CH2', 'CH3', 'CH4', 'CH5', 'CH6', 'CH7', 'QD_PHA', 'QD_PHB'], 'I2C' : ['SDA', 'SCL'], 'UART' : ['RX', 'TX', 'CTS', 'RTS'], 'SPI' : ['NSS', 'SCK', 'MISO', 'MOSI'] } def parse_port_pin(name_str): """Parses a string and returns a (port-num, pin-num) tuple.""" if len(name_str) < 4: raise ValueError("Expecting pin name to be at least 4 charcters.") if name_str[0:2] != 'PT': raise ValueError("Expecting pin name to start with PT") if name_str[2] not in ('A', 'B', 'C', 'D', 'E', 'Z'): raise ValueError("Expecting pin port to be between A and E or Z") port = ord(name_str[2]) - ord('A') pin_str = name_str[3:].split('/')[0] if not pin_str.isdigit(): raise ValueError("Expecting numeric pin number.") return (port, int(pin_str)) def split_name_num(name_num): num = None for num_idx in range(len(name_num) - 1, -1, -1): if not name_num[num_idx].isdigit(): name = name_num[0:num_idx + 1] num_str = name_num[num_idx + 1:] if len(num_str) > 0: num = int(num_str) break return name, num class AlternateFunction(object): """Holds the information associated with a pins alternate function.""" def __init__(self, idx, af_str): self.idx = idx self.af_str = af_str self.func = '' self.fn_num = None self.pin_type = '' self.supported = False af_words = af_str.split('_', 1) self.func, self.fn_num = split_name_num(af_words[0]) if len(af_words) > 1: self.pin_type = af_words[1] if self.func in SUPPORTED_FN: pin_types = SUPPORTED_FN[self.func] if self.pin_type in pin_types: self.supported = True def is_supported(self): return self.supported def ptr(self): """Returns the numbered function (i.e. USART6) for this AF.""" if self.fn_num is None: return self.func return '{:s}{:d}'.format(self.func, self.fn_num) def mux_name(self): return 'AF{:d}_{:s}'.format(self.idx, self.ptr()) def print(self): """Prints the C representation of this AF.""" if self.supported: print(' AF', end='') else: print(' //', end='') fn_num = self.fn_num if fn_num is None: fn_num = 0 print('({:2d}, {:8s}, {:2d}, {:10s}, {:8s}), // {:s}'.format(self.idx, self.func, fn_num, self.pin_type, self.ptr(), self.af_str)) def qstr_list(self): return [self.mux_name()] class Pin(object): """Holds the information associated with a pin.""" def __init__(self, port, pin): self.port = port self.pin = pin self.alt_fn = [] self.alt_fn_count = 0 self.adc_num = 0 self.adc_channel = 0 self.board_pin = False def port_letter(self): return chr(self.port + ord('A')) def cpu_pin_name(self): return '{:s}{:d}'.format(self.port_letter(), self.pin) def is_board_pin(self): return self.board_pin def set_is_board_pin(self): self.board_pin = True def parse_adc(self, adc_str): if (adc_str[:3] != 'ADC'): return (adc,channel) = adc_str.split('_') for idx in range(3, len(adc)): adc_num = int(adc[idx]) # 1, 2, or 3 self.adc_num |= (1 << (adc_num - 1)) self.adc_channel = int(channel[2:]) def parse_af(self, af_idx, af_strs_in): if len(af_strs_in) == 0: return # If there is a slash, then the slash separates 2 aliases for the # same alternate function. af_strs = af_strs_in.split('/') for af_str in af_strs: alt_fn = AlternateFunction(af_idx, af_str) self.alt_fn.append(alt_fn) if alt_fn.is_supported(): self.alt_fn_count += 1 def alt_fn_name(self, null_if_0=False): if null_if_0 and self.alt_fn_count == 0: return 'NULL' return 'pin_{:s}_af'.format(self.cpu_pin_name()) def adc_num_str(self): str = '' for adc_num in range(1,4): if self.adc_num & (1 << (adc_num - 1)): if len(str) > 0: str += ' | ' str += 'PIN_ADC' str += chr(ord('0') + adc_num) if len(str) == 0: str = '0' return str def print(self): if self.alt_fn_count == 0: print("// ", end='') print('const pin_af_obj_t {:s}[] = {{'.format(self.alt_fn_name())) for alt_fn in self.alt_fn: alt_fn.print() if self.alt_fn_count == 0: print("// ", end='') print('};') print('') print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s}, {:s}, {:d});'.format( self.cpu_pin_name(), self.port_letter(), self.pin, self.alt_fn_count, self.alt_fn_name(null_if_0=True), self.adc_num_str(), self.adc_channel)) print('') def print_header(self, hdr_file): hdr_file.write('extern const pin_obj_t pin_{:s};\n'. format(self.cpu_pin_name())) if self.alt_fn_count > 0: hdr_file.write('extern const pin_af_obj_t pin_{:s}_af[];\n'. format(self.cpu_pin_name())) def qstr_list(self): result = [] for alt_fn in self.alt_fn: if alt_fn.is_supported(): result += alt_fn.qstr_list() return result class NamedPin(object): def __init__(self, name, pin): self._name = name self._pin = pin def pin(self): return self._pin def name(self): return self._name class Pins(object): def __init__(self): self.cpu_pins = [] # list of NamedPin objects self.board_pins = [] # list of NamedPin objects def find_pin(self, port_num, pin_num): for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.port == port_num and pin.pin == pin_num: return pin def parse_af_file(self, filename, pinname_col, af_col): with open(filename, 'r') as csvfile: rows = csv.reader(csvfile) for row in rows: try: (port_num, pin_num) = parse_port_pin(row[pinname_col]) except: continue pin = Pin(port_num, pin_num) for af_idx in range(af_col, len(row)): if af_idx >= af_col: pin.parse_af(af_idx - af_col, row[af_idx]) self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin)) def parse_board_file(self, filename): with open(filename, 'r') as csvfile: rows = csv.reader(csvfile) for row in rows: try: (port_num, pin_num) = parse_port_pin(row[1]) except: continue pin = self.find_pin(port_num, pin_num) if pin: pin.set_is_board_pin() self.board_pins.append(NamedPin(row[0], pin)) def print_named(self, label, named_pins): print('STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label)) for named_pin in named_pins: pin = named_pin.pin() if pin.is_board_pin(): print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},'.format(named_pin.name(), pin.cpu_pin_name())) print('};') print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label)); def print(self): for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): pin.print() self.print_named('cpu', self.cpu_pins) print('') self.print_named('board', self.board_pins) def print_adc(self, adc_num): print(''); print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num)) for channel in range(16): adc_found = False for named_pin in self.cpu_pins: pin = named_pin.pin() if (pin.is_board_pin() and (pin.adc_num & (1 << (adc_num - 1))) and (pin.adc_channel == channel)): print(' &pin_{:s}, // {:d}'.format(pin.cpu_pin_name(), channel)) adc_found = True break if not adc_found: print(' NULL, // {:d}'.format(channel)) print('};') def print_header(self, hdr_filename): with open(hdr_filename, 'wt') as hdr_file: for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): pin.print_header(hdr_file) hdr_file.write('extern const pin_obj_t * const pin_adc1[];\n') hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n') hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n') def print_qstr(self, qstr_filename): with open(qstr_filename, 'wt') as qstr_file: qstr_set = set([]) for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): qstr_set |= set(pin.qstr_list()) qstr_set |= set([named_pin.name()]) for named_pin in self.board_pins: qstr_set |= set([named_pin.name()]) for qstr in sorted(qstr_set): print('Q({})'.format(qstr), file=qstr_file) def print_af_hdr(self, af_const_filename): with open(af_const_filename, 'wt') as af_const_file: af_hdr_set = set([]) mux_name_width = 0 for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): for af in pin.alt_fn: if af.is_supported(): mux_name = af.mux_name() af_hdr_set |= set([mux_name]) if len(mux_name) > mux_name_width: mux_name_width = len(mux_name) for mux_name in sorted(af_hdr_set): key = 'MP_OBJ_NEW_QSTR(MP_QSTR_{}),'.format(mux_name) val = 'MP_OBJ_NEW_SMALL_INT(GPIO_{})'.format(mux_name) print(' { %-*s %s },' % (mux_name_width + 26, key, val), file=af_const_file) def print_af_py(self, af_py_filename): with open(af_py_filename, 'wt') as af_py_file: print('PINS_AF = (', file=af_py_file); for named_pin in self.board_pins: print(" ('%s', " % named_pin.name(), end='', file=af_py_file) for af in named_pin.pin().alt_fn: if af.is_supported(): print("(%d, '%s'), " % (af.idx, af.af_str), end='', file=af_py_file) print('),', file=af_py_file) print(')', file=af_py_file) def main(): parser = argparse.ArgumentParser( prog="make-pins.py", usage="%(prog)s [options] [command]", description="Generate board specific pin file" ) parser.add_argument( "-a", "--af", dest="af_filename", help="Specifies the alternate function file for the chip", default="mk20dx256_af.csv" ) parser.add_argument( "--af-const", dest="af_const_filename", help="Specifies header file for alternate function constants.", default="build/pins_af_const.h" ) parser.add_argument( "--af-py", dest="af_py_filename", help="Specifies the filename for the python alternate function mappings.", default="build/pins_af.py" ) parser.add_argument( "-b", "--board", dest="board_filename", help="Specifies the board file", ) parser.add_argument( "-p", "--prefix", dest="prefix_filename", help="Specifies beginning portion of generated pins file", default="mk20dx256_prefix.c" ) parser.add_argument( "-q", "--qstr", dest="qstr_filename", help="Specifies name of generated qstr header file", default="build/pins_qstr.h" ) parser.add_argument( "-r", "--hdr", dest="hdr_filename", help="Specifies name of generated pin header file", default="build/pins.h" ) args = parser.parse_args(sys.argv[1:]) pins = Pins() print('// This file was automatically generated by make-pins.py') print('//') if args.af_filename: print('// --af {:s}'.format(args.af_filename)) pins.parse_af_file(args.af_filename, 4, 3) if args.board_filename: print('// --board {:s}'.format(args.board_filename)) pins.parse_board_file(args.board_filename) if args.prefix_filename: print('// --prefix {:s}'.format(args.prefix_filename)) print('') with open(args.prefix_filename, 'r') as prefix_file: print(prefix_file.read()) pins.print() pins.print_adc(1) pins.print_adc(2) pins.print_adc(3) pins.print_header(args.hdr_filename) pins.print_qstr(args.qstr_filename) pins.print_af_hdr(args.af_const_filename) pins.print_af_py(args.af_py_filename) if __name__ == "__main__": main() micropython-1.12/ports/teensy/memzip_files/000077500000000000000000000000001357706137100211635ustar00rootroot00000000000000micropython-1.12/ports/teensy/memzip_files/boot.py000066400000000000000000000005101357706137100224740ustar00rootroot00000000000000import pyb print("Executing boot.py") def pins(): for pin_name in dir(pyb.Pin.board): pin = pyb.Pin(pin_name) print('{:10s} {:s}'.format(pin_name, str(pin))) def af(): for pin_name in dir(pyb.Pin.board): pin = pyb.Pin(pin_name) print('{:10s} {:s}'.format(pin_name, str(pin.af_list()))) micropython-1.12/ports/teensy/memzip_files/main.py000066400000000000000000000002171357706137100224610ustar00rootroot00000000000000import pyb print("Executing main.py") led = pyb.LED(1) led.on() pyb.delay(100) led.off() pyb.delay(100) led.on() pyb.delay(100) led.off() micropython-1.12/ports/teensy/mk20dx256.ld000066400000000000000000000124651357706137100203730ustar00rootroot00000000000000/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K RAM (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 64K } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; /* INCLUDE common.ld */ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ SECTIONS { .text : { . = 0; KEEP(*(.vectors)) *(.startup*) /* TODO: does linker detect startup overflow onto flashconfig? */ . = 0x400; KEEP(*(.flashconfig*)) *(.text*) *(.rodata*) . = ALIGN(4); KEEP(*(.init)) . = ALIGN(4); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; } > FLASH = 0xFF .ARM.exidx : { __exidx_start = .; *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = .; } > FLASH _etext = .; .usbdescriptortable (NOLOAD) : { /* . = ORIGIN(RAM); */ . = ALIGN(512); *(.usbdescriptortable*) } > RAM .dmabuffers (NOLOAD) : { . = ALIGN(4); *(.dmabuffers*) } > RAM .usbbuffers (NOLOAD) : { . = ALIGN(4); *(.usbbuffers*) } > RAM /* used by the startup to initialize data */ _sidata = LOADADDR(.data); .data : AT (_etext) { . = ALIGN(4); _sdata = .; _ram_start = .; *(.data*) . = ALIGN(4); _edata = .; } > RAM /* * _staticfs is the place in flash where the static filesystem which * is concatenated to the .hex file will wind up. */ _staticfs = LOADADDR(.data) + SIZEOF(.data); .noinit (NOLOAD) : { *(.noinit*) } > RAM .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; __bss_end = .; } > RAM /* this is to define the start of the heap, and make sure we have a minimum size */ .heap : { . = ALIGN(4); _heap_start = .; /* define a global symbol at heap start */ . = . + _minimum_heap_size; } >RAM /* this just checks there is enough RAM for the stack */ .stack : { . = ALIGN(4); . = . + _minimum_stack_size; . = ALIGN(4); } >RAM _estack = ORIGIN(RAM) + LENGTH(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_end = ORIGIN(RAM) + 0xe000; } micropython-1.12/ports/teensy/mk20dx256_af.csv000066400000000000000000000107301357706137100212260ustar00rootroot00000000000000Pin,Name,Default,ALT0,ALT1,ALT2,ALT3,ALT4,ALT5,ALT6,ALT7,EzPort 1,PTE0,ADC1_SE4a,ADC1_SE4a,PTE0,SPI1_PCS1,UART1_TX,,,I2C1_SDA,RTC_CLKOUT, 2,PTE1/LLWU_P0,ADC1_SE5a,ADC1_SE5a,PTE1/LLWU_P0,SPI1_SOUT,UART1_RX,,,I2C1_SCL,SPI1_SIN, 3,VDD,VDD,VDD,,,,,,,, 4,VSS,VSS,VSS,,,,,,,, 5,USB0_DP,USB0_DP,USB0_DP,,,,,,,, 6,USB0_DM,USB0_DM,USB0_DM,,,,,,,, 7,VOUT33,VOUT33,VOUT33,,,,,,,, 8,VREGIN,VREGIN,VREGIN,,,,,,,, 9,PGA0_DP/ADC0_DP0/ADC1_DP3,PGA0_DP/ADC0_DP0/ADC1_DP3,PGA0_DP/ADC0_DP0/ADC1_DP3,PTZ0,,,,,,, 10,PGA0_DM/ADC0_DM0/ADC1_DM3,PGA0_DM/ADC0_DM0/ADC1_DM3,PGA0_DM/ADC0_DM0/ADC1_DM3,PTZ1,,,,,,, 11,PGA1_DP/ADC1_DP0/ADC0_DP3,PGA1_DP/ADC1_DP0/ADC0_DP3,PGA1_DP/ADC1_DP0/ADC0_DP3,PTZ2,,,,,,, 12,PGA1_DM/ADC1_DM0/ADC0_DM3,PGA1_DM/ADC1_DM0/ADC0_DM3,PGA1_DM/ADC1_DM0/ADC0_DM3,PTZ3,,,,,,, 13,VDDA,VDDA,VDDA,,,,,,,, 14,VREFH,VREFH,VREFH,,,,,,,, 15,VREFL,VREFL,VREFL,,,,,,,, 16,VSSA,VSSA,VSSA,,,,,,,, 17,VREF_OUT/CMP1_IN5/CMP0_IN5/ADC1_SE18,VREF_OUT/CMP1_IN5/CMP0_IN5/ADC1_SE18,VREF_OUT/CMP1_IN5/CMP0_IN5/ADC1_SE18,PTZ4,,,,,,, 18,DAC0_OUT/CMP1_IN3/ADC0_SE23,DAC0_OUT/CMP1_IN3/ADC0_SE23,DAC0_OUT/CMP1_IN3/ADC0_SE23,PTZ5,,,,,,, 19,XTAL32,XTAL32,XTAL32,,,,,,,, 20,EXTAL32,EXTAL32,EXTAL32,,,,,,,, 21,VBAT,VBAT,VBAT,,,,,,,, 22,PTA0,JTAG_TCLK/SWD_CLK/EZP_CLK,TSI0_CH1,PTA0,UART0_CTS_b/UART0_COL_b,FTM0_CH5,,,,JTAG_TCLK/SWD_CLK,EZP_CLK 23,PTA1,JTAG_TDI/EZP_DI,TSI0_CH2,PTA1,UART0_RX,FTM0_CH6,,,,JTAG_TDI,EZP_DI 24,PTA2,JTAG_TDO/TRACE_SWO/EZP_DO,TSI0_CH3,PTA2,UART0_TX,FTM0_CH7,,,,JTAG_TDO/TRACE_SWO,EZP_DO 25,PTA3,JTAG_TMS/SWD_DIO,TSI0_CH4,PTA3,UART0_RTS_b,FTM0_CH0,,,,JTAG_TMS/SWD_DIO, 26,PTA4/LLWU_P3,NMI_b/EZP_CS_b,TSI0_CH5,PTA4/LLWU_P3,,FTM0_CH1,,,NMI_b,EZP_CS_b, 27,PTA5,DISABLED,,PTA5,USB_CLKIN,FTM0_CH2,,CMP2_OUT,I2S0_TX_BCLK,JTAG_TRST_b, 28,PTA12,CMP2_IN0,CMP2_IN0,PTA12,CAN0_TX,FTM1_CH0,,,I2S0_TXD0,FTM1_QD_PHA, 29,PTA13/LLWU_P4,CMP2_IN1,CMP2_IN1,PTA13/LLWU_P4,CAN0_RX,FTM1_CH1,,,I2S0_TX_FS,FTM1_QD_PHB, 30,VDD,VDD,VDD,,,,,,,, 31,VSS,VSS,VSS,,,,,,,, 32,PTA18,EXTAL0,EXTAL0,PTA18,,FTM0_FLT2,FTM_CLKIN0,,,, 33,PTA19,XTAL0,XTAL0,PTA19,,FTM1_FLT0,FTM_CLKIN1,,LPTMR0_ALT1,, 34,RESET_b,RESET_b,RESET_b,,,,,,,, 35,PTB0/LLWU_P5,ADC0_SE8/ADC1_SE8/TSI0_CH0,ADC0_SE8/ADC1_SE8/TSI0_CH0,PTB0/LLWU_P5,I2C0_SCL,FTM1_CH0,,,FTM1_QD_PHA,, 36,PTB1,ADC0_SE9/ADC1_SE9/TSI0_CH6,ADC0_SE9/ADC1_SE9/TSI0_CH6,PTB1,I2C0_SDA,FTM1_CH1,,,FTM1_QD_PHB,, 37,PTB2,ADC0_SE12/TSI0_CH7,ADC0_SE12/TSI0_CH7,PTB2,I2C0_SCL,UART0_RTS_b,,,FTM0_FLT3,, 38,PTB3,ADC0_SE13/TSI0_CH8,ADC0_SE13/TSI0_CH8,PTB3,I2C0_SDA,UART0_CTS_b/UART0_COL_b,,,FTM0_FLT0,, 39,PTB16,TSI0_CH9,TSI0_CH9,PTB16,SPI1_SOUT,UART0_RX,,FB_AD17,EWM_IN,, 40,PTB17,TSI0_CH10,TSI0_CH10,PTB17,SPI1_SIN,UART0_TX,,FB_AD16,EWM_OUT_b,, 41,PTB18,TSI0_CH11,TSI0_CH11,PTB18,CAN0_TX,FTM2_CH0,I2S0_TX_BCLK,FB_AD15,FTM2_QD_PHA,, 42,PTB19,TSI0_CH12,TSI0_CH12,PTB19,CAN0_RX,FTM2_CH1,I2S0_TX_FS,FB_OE_b,FTM2_QD_PHB,, 43,PTC0,ADC0_SE14/TSI0_CH13,ADC0_SE14/TSI0_CH13,PTC0,SPI0_PCS4,PDB0_EXTRG,,FB_AD14,I2S0_TXD1,, 44,PTC1/LLWU_P6,ADC0_SE15/TSI0_CH14,ADC0_SE15/TSI0_CH14,PTC1/LLWU_P6,SPI0_PCS3,UART1_RTS_b,FTM0_CH0,FB_AD13,I2S0_TXD0,, 45,PTC2,ADC0_SE4b/CMP1_IN0/TSI0_CH15,ADC0_SE4b/CMP1_IN0/TSI0_CH15,PTC2,SPI0_PCS2,UART1_CTS_b,FTM0_CH1,FB_AD12,I2S0_TX_FS,, 46,PTC3/LLWU_P7,CMP1_IN1,CMP1_IN1,PTC3/LLWU_P7,SPI0_PCS1,UART1_RX,FTM0_CH2,CLKOUT,I2S0_TX_BCLK,, 47,VSS,VSS,VSS,,,,,,,, 48,VDD,VDD,VDD,,,,,,,, 49,PTC4/LLWU_P8,DISABLED,,PTC4/LLWU_P8,SPI0_PCS0,UART1_TX,FTM0_CH3,FB_AD11,CMP1_OUT,, 50,PTC5/LLWU_P9,DISABLED,,PTC5/LLWU_P9,SPI0_SCK,LPTMR0_ALT2,I2S0_RXD0,FB_AD10,CMP0_OUT,, 51,PTC6/LLWU_P10,CMP0_IN0,CMP0_IN0,PTC6/LLWU_P10,SPI0_SOUT,PDB0_EXTRG,I2S0_RX_BCLK,FB_AD9,I2S0_MCLK,, 52,PTC7,CMP0_IN1,CMP0_IN1,PTC7,SPI0_SIN,USB_SOF_OUT,I2S0_RX_FS,FB_AD8,,, 53,PTC8,ADC1_SE4b/CMP0_IN2,ADC1_SE4b/CMP0_IN2,PTC8,,,I2S0_MCLK,FB_AD7,,, 54,PTC9,ADC1_SE5b/CMP0_IN3,ADC1_SE5b/CMP0_IN3,PTC9,,,I2S0_RX_BCLK,FB_AD6,FTM2_FLT0,, 55,PTC10,ADC1_SE6b,ADC1_SE6b,PTC10,I2C1_SCL,,I2S0_RX_FS,FB_AD5,,, 56,PTC11/LLWU_P11,ADC1_SE7b,ADC1_SE7b,PTC11/LLWU_P11,I2C1_SDA,,I2S0_RXD1,FB_RW_b,,, 57,PTD0/LLWU_P12,DISABLED,,PTD0/LLWU_P12,SPI0_PCS0,UART2_RTS_b,,FB_ALE/FB_CS1_b/FB_TS_b,,, 58,PTD1,ADC0_SE5b,ADC0_SE5b,PTD1,SPI0_SCK,UART2_CTS_b,,FB_CS0_b,,, 59,PTD2/LLWU_P13,DISABLED,,PTD2/LLWU_P13,SPI0_SOUT,UART2_RX,,FB_AD4,,, 60,PTD3,DISABLED,,PTD3,SPI0_SIN,UART2_TX,,FB_AD3,,, 61,PTD4/LLWU_P14,DISABLED,,PTD4/LLWU_P14,SPI0_PCS1,UART0_RTS_b,FTM0_CH4,FB_AD2,EWM_IN,, 62,PTD5,ADC0_SE6b,ADC0_SE6b,PTD5,SPI0_PCS2,UART0_CTS_b/UART0_COL_b,FTM0_CH5,FB_AD1,EWM_OUT_b,, 63,PTD6/LLWU_P15,ADC0_SE7b,ADC0_SE7b,PTD6/LLWU_P15,SPI0_PCS3,UART0_RX,FTM0_CH6,FB_AD0,FTM0_FLT0f,, 64,PTD7,DISABLED,,PTD7,CMT_IRO,UART0_TX,FTM0_CH7,,FTM0_FLT1,, micropython-1.12/ports/teensy/mk20dx256_prefix.c000066400000000000000000000015211357706137100215620ustar00rootroot00000000000000// stm32fxx-prefix.c becomes the initial portion of the generated pins file. #include #include #include "py/obj.h" #include "teensy_hal.h" #include "pin.h" #define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ { \ { &pin_af_type }, \ .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \ .idx = (af_idx), \ .fn = AF_FN_ ## af_fn, \ .unit = (af_unit), \ .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ .reg = (af_ptr) \ } #define PIN(p_port, p_pin, p_num_af, p_af, p_adc_num, p_adc_channel) \ { \ { &pin_type }, \ .name = MP_QSTR_ ## p_port ## p_pin, \ .port = PORT_ ## p_port, \ .pin = (p_pin), \ .num_af = (p_num_af), \ .pin_mask = (1 << (p_pin)), \ .gpio = GPIO ## p_port, \ .af = p_af, \ .adc_num = p_adc_num, \ .adc_channel = p_adc_channel, \ } micropython-1.12/ports/teensy/modpyb.c000066400000000000000000000313051357706137100201400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "Arduino.h" #include "py/obj.h" #include "py/gc.h" #include "py/mphal.h" #include "lib/utils/pyexec.h" #include "gccollect.h" #include "irq.h" #include "systick.h" #include "led.h" #include "pin.h" #include "timer.h" #include "extint.h" #include "usrsw.h" #include "rng.h" //#include "rtc.h" //#include "i2c.h" //#include "spi.h" #include "uart.h" #include "adc.h" #include "storage.h" #include "sdcard.h" #include "accel.h" #include "servo.h" #include "dac.h" #include "usb.h" #include "portmodules.h" /// \module pyb - functions related to the pyboard /// /// The `pyb` module contains specific functions related to the pyboard. /// \function bootloader() /// Activate the bootloader without BOOT* pins. STATIC mp_obj_t pyb_bootloader(void) { printf("bootloader command not current supported\n"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_bootloader_obj, pyb_bootloader); /// \function info([dump_alloc_table]) /// Print out lots of information about the board. STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) { // get and print unique id; 96 bits { byte *id = (byte*)0x40048058; printf("ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]); } // get and print clock speeds printf("CPU=%u\nBUS=%u\nMEM=%u\n", F_CPU, F_BUS, F_MEM); // to print info about memory { printf("_etext=%p\n", &_etext); printf("_sidata=%p\n", &_sidata); printf("_sdata=%p\n", &_sdata); printf("_edata=%p\n", &_edata); printf("_sbss=%p\n", &_sbss); printf("_ebss=%p\n", &_ebss); printf("_estack=%p\n", &_estack); printf("_ram_start=%p\n", &_ram_start); printf("_heap_start=%p\n", &_heap_start); printf("_heap_end=%p\n", &_heap_end); printf("_ram_end=%p\n", &_ram_end); } // qstr info { uint n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); printf("qstr:\n n_pool=%u\n n_qstr=%u\n n_str_data_bytes=%u\n n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); } // GC info { gc_info_t info; gc_info(&info); printf("GC:\n"); printf(" " UINT_FMT " total\n", info.total); printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); } if (n_args == 1) { // arg given means dump gc allocation table gc_dump_alloc_table(); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info); /// \function unique_id() /// Returns a string of 12 bytes (96 bits), which is the unique ID for the MCU. STATIC mp_obj_t pyb_unique_id(void) { byte *id = (byte*)0x40048058; return mp_obj_new_bytes(id, 12); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_unique_id_obj, pyb_unique_id); /// \function freq() /// Return a tuple of clock frequencies: (SYSCLK, HCLK, PCLK1, PCLK2). // TODO should also be able to set frequency via this function STATIC mp_obj_t pyb_freq(void) { mp_obj_t tuple[3] = { mp_obj_new_int(F_CPU), mp_obj_new_int(F_BUS), mp_obj_new_int(F_MEM), }; return mp_obj_new_tuple(3, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_freq_obj, pyb_freq); /// \function sync() /// Sync all file systems. STATIC mp_obj_t pyb_sync(void) { printf("sync not currently implemented\n"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_sync_obj, pyb_sync); /// \function millis() /// Returns the number of milliseconds since the board was last reset. /// /// The result is always a MicroPython smallint (31-bit signed number), so /// after 2^30 milliseconds (about 12.4 days) this will start to return /// negative numbers. STATIC mp_obj_t pyb_millis(void) { // We want to "cast" the 32 bit unsigned into a small-int. This means // copying the MSB down 1 bit (extending the sign down), which is // equivalent to just using the MP_OBJ_NEW_SMALL_INT macro. return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis); /// \function elapsed_millis(start) /// Returns the number of milliseconds which have elapsed since `start`. /// /// This function takes care of counter wrap, and always returns a positive /// number. This means it can be used to measure periods upto about 12.4 days. /// /// Example: /// start = pyb.millis() /// while pyb.elapsed_millis(start) < 1000: /// # Perform some operation STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) { uint32_t startMillis = mp_obj_get_int(start); uint32_t currMillis = mp_hal_ticks_ms(); return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis); /// \function micros() /// Returns the number of microseconds since the board was last reset. /// /// The result is always a MicroPython smallint (31-bit signed number), so /// after 2^30 microseconds (about 17.8 minutes) this will start to return /// negative numbers. STATIC mp_obj_t pyb_micros(void) { // We want to "cast" the 32 bit unsigned into a small-int. This means // copying the MSB down 1 bit (extending the sign down), which is // equivalent to just using the MP_OBJ_NEW_SMALL_INT macro. return MP_OBJ_NEW_SMALL_INT(micros()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros); /// \function elapsed_micros(start) /// Returns the number of microseconds which have elapsed since `start`. /// /// This function takes care of counter wrap, and always returns a positive /// number. This means it can be used to measure periods upto about 17.8 minutes. /// /// Example: /// start = pyb.micros() /// while pyb.elapsed_micros(start) < 1000: /// # Perform some operation STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) { uint32_t startMicros = mp_obj_get_int(start); uint32_t currMicros = micros(); return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros); /// \function delay(ms) /// Delay for the given number of milliseconds. STATIC mp_obj_t pyb_delay(mp_obj_t ms_in) { mp_int_t ms = mp_obj_get_int(ms_in); if (ms >= 0) { mp_hal_delay_ms(ms); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_delay_obj, pyb_delay); /// \function udelay(us) /// Delay for the given number of microseconds. STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) { mp_int_t usec = mp_obj_get_int(usec_in); delayMicroseconds(usec); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay); STATIC mp_obj_t pyb_stop(void) { printf("stop not currently implemented\n"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_stop_obj, pyb_stop); STATIC mp_obj_t pyb_standby(void) { printf("standby not currently implemented\n"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby); /// \function have_cdc() /// Return True if USB is connected as a serial device, False otherwise. STATIC mp_obj_t pyb_have_cdc(void ) { return mp_obj_new_bool(usb_vcp_is_connected()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc); /// \function hid((buttons, x, y, z)) /// Takes a 4-tuple (or list) and sends it to the USB host (the PC) to /// signal a HID mouse-motion event. STATIC mp_obj_t pyb_hid_send_report(mp_obj_t arg) { #if 1 printf("hid_send_report not currently implemented\n"); #else mp_obj_t *items; mp_obj_get_array_fixed_n(arg, 4, &items); uint8_t data[4]; data[0] = mp_obj_get_int(items[0]); data[1] = mp_obj_get_int(items[1]); data[2] = mp_obj_get_int(items[2]); data[3] = mp_obj_get_int(items[3]); usb_hid_send_report(data); #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj, pyb_hid_send_report); MP_DECLARE_CONST_FUN_OBJ_1(pyb_source_dir_obj); // defined in main.c MP_DECLARE_CONST_FUN_OBJ_1(pyb_main_obj); // defined in main.c MP_DECLARE_CONST_FUN_OBJ_1(pyb_usb_mode_obj); // defined in main.c STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) }, { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&pyb_bootloader_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_info_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&pyb_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_repl_info), MP_ROM_PTR(&pyb_set_repl_info_obj) }, { MP_ROM_QSTR(MP_QSTR_wfi), MP_ROM_PTR(&pyb_wfi_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&pyb_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_standby), MP_ROM_PTR(&pyb_standby_obj) }, { MP_ROM_QSTR(MP_QSTR_source_dir), MP_ROM_PTR(&pyb_source_dir_obj) }, { MP_ROM_QSTR(MP_QSTR_main), MP_ROM_PTR(&pyb_main_obj) }, { MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&pyb_usb_mode_obj) }, { MP_ROM_QSTR(MP_QSTR_have_cdc), MP_ROM_PTR(&pyb_have_cdc_obj) }, { MP_ROM_QSTR(MP_QSTR_hid), MP_ROM_PTR(&pyb_hid_send_report_obj) }, { MP_ROM_QSTR(MP_QSTR_millis), MP_ROM_PTR(&pyb_millis_obj) }, { MP_ROM_QSTR(MP_QSTR_elapsed_millis), MP_ROM_PTR(&pyb_elapsed_millis_obj) }, { MP_ROM_QSTR(MP_QSTR_micros), MP_ROM_PTR(&pyb_micros_obj) }, { MP_ROM_QSTR(MP_QSTR_elapsed_micros), MP_ROM_PTR(&pyb_elapsed_micros_obj) }, { MP_ROM_QSTR(MP_QSTR_delay), MP_ROM_PTR(&pyb_delay_obj) }, { MP_ROM_QSTR(MP_QSTR_udelay), MP_ROM_PTR(&pyb_udelay_obj) }, { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&pyb_sync_obj) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) }, //#if MICROPY_HW_ENABLE_RNG // { MP_ROM_QSTR(MP_QSTR_rng), MP_ROM_PTR(&pyb_rng_get_obj) }, //#endif //#if MICROPY_HW_ENABLE_RTC // { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) }, //#endif { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, // { MP_ROM_QSTR(MP_QSTR_ExtInt), MP_ROM_PTR(&extint_type) }, #if MICROPY_HW_ENABLE_SERVO { MP_ROM_QSTR(MP_QSTR_pwm), MP_ROM_PTR(&pyb_pwm_set_obj) }, { MP_ROM_QSTR(MP_QSTR_servo), MP_ROM_PTR(&pyb_servo_set_obj) }, { MP_ROM_QSTR(MP_QSTR_Servo), MP_ROM_PTR(&pyb_servo_type) }, #endif #if MICROPY_HW_HAS_SWITCH { MP_ROM_QSTR(MP_QSTR_Switch), MP_ROM_PTR(&pyb_switch_type) }, #endif //#if MICROPY_HW_HAS_SDCARD // { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sdcard_obj) }, //#endif { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pyb_led_type) }, // { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&pyb_i2c_type) }, // { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, // { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) }, // { MP_ROM_QSTR(MP_QSTR_ADCAll), MP_ROM_PTR(&pyb_adc_all_type) }, //#if MICROPY_HW_ENABLE_DAC // { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&pyb_dac_type) }, //#endif //#if MICROPY_HW_HAS_MMA7660 // { MP_ROM_QSTR(MP_QSTR_Accel), MP_ROM_PTR(&pyb_accel_type) }, //#endif }; STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table); const mp_obj_module_t pyb_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&pyb_module_globals, }; micropython-1.12/ports/teensy/mpconfigport.h000066400000000000000000000111051357706137100213560ustar00rootroot00000000000000#include // options to control how MicroPython is built #define MICROPY_ALLOC_PATH_MAX (128) #define MICROPY_EMIT_THUMB (1) #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_OPT_COMPUTED_GOTO (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT teensy_help_text #define MICROPY_PY_IO (0) #define MICROPY_PY_FROZENSET (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_CMATH (1) #define MICROPY_TIMER_REG (0) #define MICROPY_REG (MICROPY_TIMER_REG) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t os_module; extern const struct _mp_obj_module_t pyb_module; extern const struct _mp_obj_module_t time_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_pyb), MP_ROM_PTR(&pyb_module) }, \ // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_pyb), MP_ROM_PTR(&pyb_module) }, \ #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ mp_obj_t pin_class_mapper; \ mp_obj_t pin_class_map_dict; \ struct _pyb_uart_obj_t *pyb_stdio_uart; \ // type definitions for the specific machine #define UINT_FMT "%u" #define INT_FMT "%d" typedef int32_t mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // We have inlined IRQ functions for efficiency (they are generally // 1 machine instruction). // // Note on IRQ state: you should not need to know the specific // value of the state variable, but rather just pass the return // value from disable_irq back to enable_irq. If you really need // to know the machine-specific values, see irq.h. #ifndef __disable_irq #define __disable_irq() __asm__ volatile("CPSID i"); #endif __attribute__(( always_inline )) static inline uint32_t __get_PRIMASK(void) { uint32_t result; __asm volatile ("MRS %0, primask" : "=r" (result)); return(result); } __attribute__(( always_inline )) static inline void __set_PRIMASK(uint32_t priMask) { __asm volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); } __attribute__(( always_inline )) static inline void enable_irq(mp_uint_t state) { __set_PRIMASK(state); } __attribute__(( always_inline )) static inline mp_uint_t disable_irq(void) { mp_uint_t state = __get_PRIMASK(); __disable_irq(); return state; } #define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) // We need to provide a declaration/definition of alloca() #include // The following would be from a board specific file, if one existed #define MICROPY_HW_BOARD_NAME "Teensy-3.1" #define MICROPY_HW_MCU_NAME "MK20DX256" #define MICROPY_HW_HAS_SWITCH (0) #define MICROPY_HW_HAS_SDCARD (0) #define MICROPY_HW_HAS_MMA7660 (0) #define MICROPY_HW_HAS_LIS3DSH (0) #define MICROPY_HW_HAS_LCD (0) #define MICROPY_HW_ENABLE_RNG (0) #define MICROPY_HW_ENABLE_RTC (0) #define MICROPY_HW_ENABLE_TIMER (0) #define MICROPY_HW_ENABLE_SERVO (0) #define MICROPY_HW_ENABLE_DAC (0) #define MICROPY_HW_ENABLE_I2C1 (0) #define MICROPY_HW_ENABLE_SPI1 (0) #define MICROPY_HW_ENABLE_SPI3 (0) #define MICROPY_HW_ENABLE_CC3K (0) #define MICROPY_HW_LED1 (pin_C5) #define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) #define MICROPY_HW_LED_ON(pin) (pin->gpio->PSOR = pin->pin_mask) #define MICROPY_HW_LED_OFF(pin) (pin->gpio->PCOR = pin->pin_mask) #if 0 // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) #endif #define MICROPY_MATH_SQRT_ASM (1) #define MICROPY_MPHALPORT_H "teensy_hal.h" #define MICROPY_PIN_DEFS_PORT_H "pin_defs_teensy.h" micropython-1.12/ports/teensy/pin_defs_teensy.c000066400000000000000000000037431357706137100220310ustar00rootroot00000000000000#include #include #include "py/runtime.h" #include "py/mphal.h" #include "pin.h" // Returns the pin mode. This value returned by this macro should be one of: // GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD, // GPIO_MODE_AF_PP, GPIO_MODE_AF_OD, or GPIO_MODE_ANALOG. uint32_t pin_get_mode(const pin_obj_t *pin) { if (pin->gpio == NULL) { // Analog only pin return GPIO_MODE_ANALOG; } volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin); uint32_t pcr = *port_pcr; uint32_t af = (pcr & PORT_PCR_MUX_MASK) >> 8; if (af == 0) { return GPIO_MODE_ANALOG; } if (af == 1) { if (pin->gpio->PDDR & (1 << pin->pin)) { if (pcr & PORT_PCR_ODE) { return GPIO_MODE_OUTPUT_OD; } return GPIO_MODE_OUTPUT_PP; } return GPIO_MODE_INPUT; } if (pcr & PORT_PCR_ODE) { return GPIO_MODE_AF_OD; } return GPIO_MODE_AF_PP; } // Returns the pin pullup/pulldown. The value returned by this macro should // be one of GPIO_NOPULL, GPIO_PULLUP, or GPIO_PULLDOWN. uint32_t pin_get_pull(const pin_obj_t *pin) { if (pin->gpio == NULL) { // Analog only pin return GPIO_NOPULL; } volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin); uint32_t pcr = *port_pcr; uint32_t af = (pcr & PORT_PCR_MUX_MASK) >> 8; // pull is only valid for digital modes (hence the af > 0 test) if (af > 0 && (pcr & PORT_PCR_PE) != 0) { if (pcr & PORT_PCR_PS) { return GPIO_PULLUP; } return GPIO_PULLDOWN; } return GPIO_NOPULL; } // Returns the af (alternate function) index currently set for a pin. uint32_t pin_get_af(const pin_obj_t *pin) { if (pin->gpio == NULL) { // Analog only pin return 0; } volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin); return (*port_pcr & PORT_PCR_MUX_MASK) >> 8; } micropython-1.12/ports/teensy/pin_defs_teensy.h000066400000000000000000000013131357706137100220250ustar00rootroot00000000000000enum { PORT_A, PORT_B, PORT_C, PORT_D, PORT_E, PORT_Z, }; enum { AF_FN_FTM, AF_FN_I2C, AF_FN_UART, AF_FN_SPI }; enum { AF_PIN_TYPE_FTM_CH0 = 0, AF_PIN_TYPE_FTM_CH1, AF_PIN_TYPE_FTM_CH2, AF_PIN_TYPE_FTM_CH3, AF_PIN_TYPE_FTM_CH4, AF_PIN_TYPE_FTM_CH5, AF_PIN_TYPE_FTM_CH6, AF_PIN_TYPE_FTM_CH7, AF_PIN_TYPE_FTM_QD_PHA, AF_PIN_TYPE_FTM_QD_PHB, AF_PIN_TYPE_I2C_SDA = 0, AF_PIN_TYPE_I2C_SCL, AF_PIN_TYPE_SPI_MOSI = 0, AF_PIN_TYPE_SPI_MISO, AF_PIN_TYPE_SPI_SCK, AF_PIN_TYPE_SPI_NSS, AF_PIN_TYPE_UART_TX = 0, AF_PIN_TYPE_UART_RX, AF_PIN_TYPE_UART_CTS, AF_PIN_TYPE_UART_RTS, }; typedef GPIO_TypeDef pin_gpio_t; micropython-1.12/ports/teensy/qstrdefsport.h000066400000000000000000000000371357706137100214110ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/teensy/reg.c000066400000000000000000000023761357706137100174310ustar00rootroot00000000000000#include #include #include "py/runtime.h" #include "reg.h" #if MICROPY_REG mp_obj_t reg_cmd(void *base, reg_t *reg, mp_uint_t num_regs, uint n_args, const mp_obj_t *args) { if (n_args == 0) { // dump all regs for (mp_uint_t reg_idx = 0; reg_idx < num_regs; reg_idx++, reg++) { printf(" %-8s @0x%08x = 0x%08lx\n", reg->name, (mp_uint_t)base + reg->offset, *(uint32_t *)((uint8_t *)base + reg->offset)); } return mp_const_none; } mp_uint_t addr = 0; if (mp_obj_is_str(args[0])) { const char *name = mp_obj_str_get_str(args[0]); mp_uint_t reg_idx; for (reg_idx = 0; reg_idx < num_regs; reg_idx++, reg++) { if (strcmp(name, reg->name) == 0) { break; } } if (reg_idx >= num_regs) { printf("Unknown register: '%s'\n", name); return mp_const_none; } addr = (mp_uint_t)base + reg->offset; } else { addr = (mp_uint_t)base + mp_obj_get_int(args[0]); } if (n_args < 2) { // get printf("0x%08lx\n", *(uint32_t *)addr); } else { *(uint32_t *)addr = mp_obj_get_int(args[1]); } return mp_const_none; } #endif micropython-1.12/ports/teensy/reg.h000066400000000000000000000005321357706137100174260ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_TEENSY_REG_H #define MICROPY_INCLUDED_TEENSY_REG_H typedef struct { const char *name; mp_uint_t offset; } reg_t; #define REG_ENTRY(st, name) { #name, offsetof(st, name) } mp_obj_t reg_cmd(void *base, reg_t *reg, mp_uint_t num_reg, uint n_args, const mp_obj_t *args); #endif // MICROPY_INCLUDED_TEENSY_REG_H micropython-1.12/ports/teensy/servo.c000066400000000000000000000206441357706137100200100ustar00rootroot00000000000000#include #include "misc.h" #include "mpconfig.h" #include "qstr.h" #include "nlr.h" #include "obj.h" #include "servo.h" #include "Arduino.h" #define MAX_SERVOS 12 #define INVALID_SERVO -1 #define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo #define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo #define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached #define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds #define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE \ | PDB_SC_CONT | PDB_SC_PRESCALER(2) | PDB_SC_MULT(0)) #define PDB_PRESCALE 4 #define usToTicks(us) ((us) * (F_BUS / 1000) / PDB_PRESCALE / 1000) #define ticksToUs(ticks) ((ticks) * PDB_PRESCALE * 1000 / (F_BUS / 1000)) static uint16_t servo_active_mask = 0; static uint16_t servo_allocated_mask = 0; static uint8_t servo_pin[MAX_SERVOS]; static uint16_t servo_ticks[MAX_SERVOS]; typedef struct _pyb_servo_obj_t { mp_obj_base_t base; uint servo_id; uint min_usecs; uint max_usecs; } pyb_servo_obj_t; #define clamp(v, min_val, max_val) ((v) < (min_val) ? (min_val) : (v) > (max_val) ? (max_val) : (v)) static float map_uint_to_float(uint x, uint in_min, uint in_max, float out_min, float out_max) { return (float)(x - in_min) * (out_max - out_min) / (float)(in_max - in_min) + (float)out_min; } static uint map_float_to_uint(float x, float in_min, float in_max, uint out_min, uint out_max) { return (int)((x - in_min) * (float)(out_max - out_min) / (in_max - in_min) + (float)out_min); } static mp_obj_t servo_obj_attach(mp_obj_t self_in, mp_obj_t pin_obj) { pyb_servo_obj_t *self = self_in; uint pin = mp_obj_get_int(pin_obj); if (pin > CORE_NUM_DIGITAL) { goto pin_error; } pinMode(pin, OUTPUT); servo_pin[self->servo_id] = pin; servo_active_mask |= (1 << self->servo_id); if (!(SIM_SCGC6 & SIM_SCGC6_PDB)) { SIM_SCGC6 |= SIM_SCGC6_PDB; // TODO: use bitband for atomic bitset PDB0_MOD = 0xFFFF; PDB0_CNT = 0; PDB0_IDLY = 0; PDB0_SC = PDB_CONFIG; // TODO: maybe this should be a higher priority than most // other interrupts (init all to some default?) PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; } NVIC_ENABLE_IRQ(IRQ_PDB); return mp_const_none; pin_error: nlr_raise(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %d does not exist", pin)); } static mp_obj_t servo_obj_detach(mp_obj_t self_in) { //pyb_servo_obj_t *self = self_in; return mp_const_none; } static mp_obj_t servo_obj_pin(mp_obj_t self_in) { pyb_servo_obj_t *self = self_in; return MP_OBJ_NEW_SMALL_INT(servo_pin[self->servo_id]); } static mp_obj_t servo_obj_min_usecs(int n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = args[0]; if (n_args == 1) { // get min return MP_OBJ_NEW_SMALL_INT(self->min_usecs); } // Set min self->min_usecs = mp_obj_get_int(args[1]); return mp_const_none; } static mp_obj_t servo_obj_max_usecs(int n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = args[0]; if (n_args == 1) { // get max return MP_OBJ_NEW_SMALL_INT(self->max_usecs); } // Set max self->max_usecs = mp_obj_get_int(args[1]); return mp_const_none; } static mp_obj_t servo_obj_angle(int n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = args[0]; if (n_args == 1) { // get float angle = map_uint_to_float(servo_ticks[self->servo_id], usToTicks(self->min_usecs), usToTicks(self->max_usecs), 0.0, 180.0); return mp_obj_new_float(angle); } // Set float angle = mp_obj_get_float(args[1]); if (angle < 0.0F) { angle = 0.0F; } if (angle > 180.0F) { angle = 180.0F; } servo_ticks[self->servo_id] = map_float_to_uint(angle, 0.0F, 180.0F, usToTicks(self->min_usecs), usToTicks(self->max_usecs)); return mp_const_none; } static mp_obj_t servo_obj_usecs(int n_args, const mp_obj_t *args) { pyb_servo_obj_t *self = args[0]; uint usecs; if (n_args == 1) { // get return MP_OBJ_NEW_SMALL_INT(ticksToUs(servo_ticks[self->servo_id])); } // Set usecs = mp_obj_get_int(args[1]); if (self->min_usecs < self->max_usecs) { usecs = clamp(usecs, self->min_usecs, self->max_usecs); } else { usecs = clamp(usecs, self->max_usecs, self->min_usecs); } servo_ticks[self->servo_id] = usToTicks(usecs); return mp_const_none; } static mp_obj_t servo_obj_attached(mp_obj_t self_in) { pyb_servo_obj_t *self = self_in; uint attached = (servo_active_mask & (1 << self->servo_id)) != 0; return MP_OBJ_NEW_SMALL_INT(attached); } static void servo_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { pyb_servo_obj_t *self = self_in; (void)kind; print(env, "", self->servo_id); } static MP_DEFINE_CONST_FUN_OBJ_2(servo_obj_attach_obj, servo_obj_attach); static MP_DEFINE_CONST_FUN_OBJ_1(servo_obj_detach_obj, servo_obj_detach); static MP_DEFINE_CONST_FUN_OBJ_1(servo_obj_pin_obj, servo_obj_pin); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_min_usecs_obj, 1, 2, servo_obj_min_usecs); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_max_usecs_obj, 1, 2, servo_obj_max_usecs); static MP_DEFINE_CONST_FUN_OBJ_1(servo_obj_attached_obj, servo_obj_attached); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_angle_obj, 1, 2, servo_obj_angle); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(servo_obj_usecs_obj, 1, 2, servo_obj_usecs); static const mp_method_t servo_methods[] = { { "attach", &servo_obj_attach_obj }, { "detach", &servo_obj_detach_obj }, { "pin", &servo_obj_pin_obj }, { "min_usecs", &servo_obj_min_usecs_obj }, { "max_usecs", &servo_obj_max_usecs_obj }, { "attached", &servo_obj_attached_obj }, { "angle", &servo_obj_angle_obj }, { "usecs", &servo_obj_usecs_obj }, { NULL, NULL }, }; /* * Notes: * * ISR needs to know pin #, ticks */ static const mp_obj_type_t servo_obj_type = { { &mp_type_type }, .name = MP_QSTR_Servo, .print = servo_obj_print, .methods = servo_methods, }; /* servo = pyb.Servo(pin, [min_uecs, [max_usecs]]) */ mp_obj_t pyb_Servo(void) { uint16_t mask; pyb_servo_obj_t *self = m_new_obj(pyb_servo_obj_t); self->base.type = &servo_obj_type; self->min_usecs = MIN_PULSE_WIDTH; self->max_usecs = MAX_PULSE_WIDTH; /* Find an unallocated servo id */ self->servo_id = 0; for (mask=1; mask < (1<servo_id] = usToTicks(DEFAULT_PULSE_WIDTH); return self; } self->servo_id++; } m_del_obj(pyb_servo_obj_t, self); mp_raise_ValueError("No available servo ids"); return mp_const_none; } void pdb_isr(void) { static int8_t channel = 0, channel_high = MAX_SERVOS; static uint32_t tick_accum = 0; uint32_t ticks; int32_t wait_ticks; // first, if any channel was left high from the previous // run, now is the time to shut it off if (servo_active_mask & (1 << channel_high)) { digitalWrite(servo_pin[channel_high], LOW); channel_high = MAX_SERVOS; } // search for the next channel to turn on while (channel < MAX_SERVOS) { if (servo_active_mask & (1 << channel)) { digitalWrite(servo_pin[channel], HIGH); channel_high = channel; ticks = servo_ticks[channel]; tick_accum += ticks; PDB0_IDLY += ticks; PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; channel++; return; } channel++; } // when all channels have output, wait for the // minimum refresh interval wait_ticks = usToTicks(REFRESH_INTERVAL) - tick_accum; if (wait_ticks < usToTicks(100)) wait_ticks = usToTicks(100); else if (wait_ticks > 60000) wait_ticks = 60000; tick_accum += wait_ticks; PDB0_IDLY += wait_ticks; PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; // if this wait is enough to satisfy the refresh // interval, next time begin again at channel zero if (tick_accum >= usToTicks(REFRESH_INTERVAL)) { tick_accum = 0; channel = 0; } } micropython-1.12/ports/teensy/servo.h000066400000000000000000000004341357706137100200100ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_TEENSY_SERVO_H #define MICROPY_INCLUDED_TEENSY_SERVO_H void servo_init(void); extern const mp_obj_type_t pyb_servo_type; MP_DECLARE_CONST_FUN_OBJ_2(pyb_servo_set_obj); MP_DECLARE_CONST_FUN_OBJ_2(pyb_pwm_set_obj); #endif // MICROPY_INCLUDED_TEENSY_SERVO_H micropython-1.12/ports/teensy/std.h000066400000000000000000000013161357706137100174440ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_TEENSY_STD_H #define MICROPY_INCLUDED_TEENSY_STD_H typedef unsigned int size_t; void __assert_func(void); void *malloc(size_t n); void free(void *ptr); void *realloc(void *ptr, size_t n); void *memcpy(void *dest, const void *src, size_t n); void *memmove(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); size_t strlen(const char *str); int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); char *strcpy(char *dest, const char *src); char *strcat(char *dest, const char *src); int printf(const char *fmt, ...); int snprintf(char *str, size_t size, const char *fmt, ...); #endif // MICROPY_INCLUDED_TEENSY_STD_H micropython-1.12/ports/teensy/teensy_hal.c000066400000000000000000000042131357706137100207770ustar00rootroot00000000000000#include #include #include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" #include "usb.h" #include "uart.h" #include "Arduino.h" mp_uint_t mp_hal_ticks_ms(void) { return millis(); } void mp_hal_delay_ms(mp_uint_t ms) { delay(ms); } void mp_hal_set_interrupt_char(int c) { // The teensy 3.1 usb stack doesn't currently have the notion of generating // an exception when a certain character is received. That just means that // you can't press Control-C and get your python script to stop. } uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if (poll_flags & MP_STREAM_POLL_RD) { if (usb_vcp_rx_num()) { ret |= MP_STREAM_POLL_RD; } if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { ret |= MP_STREAM_POLL_RD; } } return ret; } int mp_hal_stdin_rx_chr(void) { for (;;) { byte c; if (usb_vcp_recv_byte(&c) != 0) { return c; } else if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart)); } __WFI(); } } void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } void mp_hal_stdout_tx_strn(const char *str, size_t len) { if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len); } if (usb_vcp_is_enabled()) { usb_vcp_send_strn(str, len); } } void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { // send stdout to UART and USB CDC VCP if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len); uart_tx_strn_cooked(MP_STATE_PORT(pyb_stdio_uart), str, len); } if (usb_vcp_is_enabled()) { usb_vcp_send_strn_cooked(str, len); } } void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { } void extint_register_pin(const void *pin, uint32_t mode, int hard_irq, mp_obj_t callback_obj) { mp_raise_NotImplementedError(NULL); } micropython-1.12/ports/teensy/teensy_hal.h000066400000000000000000000102321357706137100210020ustar00rootroot00000000000000#include #include "hal_ftm.h" #ifdef USE_FULL_ASSERT #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) void assert_failed(uint8_t* file, uint32_t line); #else #define assert_param(expr) ((void)0) #endif /* USE_FULL_ASSERT */ #define HAL_NVIC_EnableIRQ(irq) NVIC_ENABLE_IRQ(irq) #define GPIOA ((GPIO_TypeDef *)&GPIOA_PDOR) #define GPIOB ((GPIO_TypeDef *)&GPIOB_PDOR) #define GPIOC ((GPIO_TypeDef *)&GPIOC_PDOR) #define GPIOD ((GPIO_TypeDef *)&GPIOD_PDOR) #define GPIOE ((GPIO_TypeDef *)&GPIOE_PDOR) #define GPIOZ ((GPIO_TypeDef *)NULL) #define I2C0 ((I2C_TypeDef *)0x40066000) #define I2C1 ((I2C_TypeDef *)0x40067000) #undef SPI0 #define SPI0 ((SPI_TypeDef *)0x4002C000) #define SPI1 ((SPI_TypeDef *)0x4002D000) #define UART0 ((UART_TypeDef *)&UART0_BDH) #define UART1 ((UART_TypeDef *)&UART1_BDH) #define UART2 ((UART_TypeDef *)&UART2_BDH) typedef struct { uint32_t dummy; } I2C_TypeDef; typedef struct { uint32_t dummy; } UART_TypeDef; typedef struct { uint32_t dummy; } SPI_TypeDef; typedef struct { volatile uint32_t PDOR; // Output register volatile uint32_t PSOR; // Set output register volatile uint32_t PCOR; // Clear output register volatile uint32_t PTOR; // Toggle output register volatile uint32_t PDIR; // Data Input register volatile uint32_t PDDR; // Data Direction register } GPIO_TypeDef; #define GPIO_OUTPUT_TYPE ((uint32_t)0x00000010) // Indicates OD #define GPIO_MODE_INPUT ((uint32_t)0x00000000) #define GPIO_MODE_OUTPUT_PP ((uint32_t)0x00000001) #define GPIO_MODE_OUTPUT_OD ((uint32_t)0x00000011) #define GPIO_MODE_AF_PP ((uint32_t)0x00000002) #define GPIO_MODE_AF_OD ((uint32_t)0x00000012) #define GPIO_MODE_ANALOG ((uint32_t)0x00000003) #define GPIO_MODE_IT_RISING ((uint32_t)1) #define GPIO_MODE_IT_FALLING ((uint32_t)2) #define IS_GPIO_MODE(MODE) (((MODE) == GPIO_MODE_INPUT) ||\ ((MODE) == GPIO_MODE_OUTPUT_PP) ||\ ((MODE) == GPIO_MODE_OUTPUT_OD) ||\ ((MODE) == GPIO_MODE_AF_PP) ||\ ((MODE) == GPIO_MODE_AF_OD) ||\ ((MODE) == GPIO_MODE_ANALOG)) #define GPIO_NOPULL ((uint32_t)0) #define GPIO_PULLUP ((uint32_t)1) #define GPIO_PULLDOWN ((uint32_t)2) #define IS_GPIO_PULL(PULL) (((PULL) == GPIO_NOPULL) || ((PULL) == GPIO_PULLUP) || \ ((PULL) == GPIO_PULLDOWN)) #define GPIO_SPEED_FREQ_LOW ((uint32_t)0) #define GPIO_SPEED_FREQ_MEDIUM ((uint32_t)1) #define GPIO_SPEED_FREQ_HIGH ((uint32_t)2) #define GPIO_SPEED_FREQ_VERY_HIGH ((uint32_t)3) #define IS_GPIO_AF(af) ((af) >= 0 && (af) <= 7) typedef struct { uint32_t Pin; uint32_t Mode; uint32_t Pull; uint32_t Speed; uint32_t Alternate; } GPIO_InitTypeDef; #define GPIO_PORT_TO_PORT_NUM(GPIOx) \ ((&GPIOx->PDOR - &GPIOA_PDOR) / (&GPIOB_PDOR - &GPIOA_PDOR)) #define GPIO_PIN_TO_PORT_PCR(GPIOx, pin) \ (&PORTA_PCR0 + (GPIO_PORT_TO_PORT_NUM(GPIOx) * 0x400) + (pin)) #define GPIO_AF2_I2C0 2 #define GPIO_AF2_I2C1 2 #define GPIO_AF2_SPI0 2 #define GPIO_AF3_FTM0 3 #define GPIO_AF3_FTM1 3 #define GPIO_AF3_FTM2 3 #define GPIO_AF3_UART0 3 #define GPIO_AF3_UART1 3 #define GPIO_AF3_UART2 3 #define GPIO_AF4_FTM0 4 #define GPIO_AF6_FTM1 6 #define GPIO_AF6_FTM2 6 #define GPIO_AF6_I2C1 6 #define GPIO_AF7_FTM1 7 __attribute__(( always_inline )) static inline void __WFI(void) { __asm volatile ("wfi"); } void mp_hal_set_interrupt_char(int c); void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio); void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *init); struct _pin_obj_t; #define mp_hal_pin_obj_t const struct _pin_obj_t* #define mp_hal_pin_high(p) (((p)->gpio->PSOR) = (p)->pin_mask) #define mp_hal_pin_low(p) (((p)->gpio->PCOR) = (p)->pin_mask) #define mp_hal_pin_read(p) (((p)->gpio->PDIR >> (p)->pin) & 1) #define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) micropython-1.12/ports/teensy/teensy_pins.csv000066400000000000000000000007561357706137100215650ustar00rootroot00000000000000D0,PTB16 D1,PTB17 D2,PTD0 D3,PTA12 D4,PTA13 D5,PTD7 D6,PTD4 D7,PTD2 D8,PTD3 D9,PTC3 D10,PTC4 D11,PTC6 D12,PTC7 D13,PTC5 D14,PTD1 D15,PTC0 D16,PTB0 D17,PTB1 D18,PTB3 D19,PTB2 D20,PTD5 D21,PTD6 D22,PTC1 D23,PTC2 D24,PTA5 D25,PTB19 D26,PTE1 D27,PTC9 D28,PTC8 D29,PTC10 D30,PTC11 D31,PTE0 D32,PTB18 D33,PTA4 A0,PTD1 A1,PTC0 A2,PTB0 A3,PTB1 A4,PTB3 A5,PTB2 A6,PTD5 A7,PTD6 A8,PTC1 A9,PTC2 A10,PTZ0 A11,PTZ1 A12,PTZ2 A13,PTZ3 A14,PTZ5 A15,PTE1 A16,PTC9 A17,PTC8 A18,PTC10 A19,PTC11 A20,PTE0 LED,PTC5 micropython-1.12/ports/teensy/timer.c000066400000000000000000001124761357706137100177770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" #include "pin.h" #include "reg.h" #include "timer.h" typedef enum { CHANNEL_MODE_PWM_NORMAL, CHANNEL_MODE_PWM_INVERTED, CHANNEL_MODE_OC_TIMING, CHANNEL_MODE_OC_ACTIVE, CHANNEL_MODE_OC_INACTIVE, CHANNEL_MODE_OC_TOGGLE, // CHANNEL_MODE_OC_FORCED_ACTIVE, // CHANNEL_MODE_OC_FORCED_INACTIVE, CHANNEL_MODE_IC, } pyb_channel_mode; STATIC const struct { qstr name; uint32_t oc_mode; } channel_mode_info[] = { { MP_QSTR_PWM, FTM_OCMODE_PWM1 }, { MP_QSTR_PWM_INVERTED, FTM_OCMODE_PWM2 }, { MP_QSTR_OC_TIMING, FTM_OCMODE_TIMING }, { MP_QSTR_OC_ACTIVE, FTM_OCMODE_ACTIVE }, { MP_QSTR_OC_INACTIVE, FTM_OCMODE_INACTIVE }, { MP_QSTR_OC_TOGGLE, FTM_OCMODE_TOGGLE }, // { MP_QSTR_OC_FORCED_ACTIVE, FTM_OCMODE_FORCED_ACTIVE }, // { MP_QSTR_OC_FORCED_INACTIVE, FTM_OCMODE_FORCED_INACTIVE }, { MP_QSTR_IC, 0 }, }; struct _pyb_timer_obj_t; typedef struct _pyb_timer_channel_obj_t { mp_obj_base_t base; struct _pyb_timer_obj_t *timer; uint8_t channel; uint8_t mode; mp_obj_t callback; struct _pyb_timer_channel_obj_t *next; } pyb_timer_channel_obj_t; typedef struct _pyb_timer_obj_t { mp_obj_base_t base; uint8_t tim_id; uint8_t irqn; mp_obj_t callback; FTM_HandleTypeDef ftm; pyb_timer_channel_obj_t *channel; } pyb_timer_obj_t; // Used to do callbacks to Python code on interrupt STATIC pyb_timer_obj_t *pyb_timer_obj_all[3]; #define PYB_TIMER_OBJ_ALL_NUM MP_ARRAY_SIZE(pyb_timer_obj_all) STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in); STATIC mp_obj_t pyb_timer_callback(mp_obj_t self_in, mp_obj_t callback); STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback); void timer_init0(void) { for (uint i = 0; i < PYB_TIMER_OBJ_ALL_NUM; i++) { pyb_timer_obj_all[i] = NULL; } } // unregister all interrupt sources void timer_deinit(void) { for (uint i = 0; i < PYB_TIMER_OBJ_ALL_NUM; i++) { pyb_timer_obj_t *tim = pyb_timer_obj_all[i]; if (tim != NULL) { pyb_timer_deinit(tim); } } } mp_uint_t get_prescaler_shift(mp_int_t prescaler) { mp_uint_t prescaler_shift; for (prescaler_shift = 0; prescaler_shift < 8; prescaler_shift++) { if (prescaler == (1 << prescaler_shift)) { return prescaler_shift; } } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "prescaler must be a power of 2 between 1 and 128, not %d", prescaler)); } /******************************************************************************/ /* MicroPython bindings */ STATIC const mp_obj_type_t pyb_timer_channel_type; // Helper function for determining the period used for calculating percent STATIC uint32_t compute_period(pyb_timer_obj_t *self) { // In center mode, compare == period corresponds to 100% // In edge mode, compare == (period + 1) corresponds to 100% FTM_TypeDef *FTMx = self->ftm.Instance; uint32_t period = (FTMx->MOD & 0xffff); if ((FTMx->SC & FTM_SC_CPWMS) == 0) { // Edge mode period++; } return period; } // Helper function to compute PWM value from timer period and percent value. // 'val' can be an int or a float between 0 and 100 (out of range values are // clamped). STATIC uint32_t compute_pwm_value_from_percent(uint32_t period, mp_obj_t percent_in) { uint32_t cmp; if (0) { #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_type(percent_in, &mp_type_float)) { float percent = mp_obj_get_float(percent_in); if (percent <= 0.0) { cmp = 0; } else if (percent >= 100.0) { cmp = period; } else { cmp = percent / 100.0 * ((float)period); } #endif } else { mp_int_t percent = mp_obj_get_int(percent_in); if (percent <= 0) { cmp = 0; } else if (percent >= 100) { cmp = period; } else { cmp = ((uint32_t)percent * period) / 100; } } return cmp; } // Helper function to compute percentage from timer perion and PWM value. STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) { #if MICROPY_PY_BUILTINS_FLOAT float percent = (float)cmp * 100.0 / (float)period; if (cmp >= period) { percent = 100.0; } else { percent = (float)cmp * 100.0 / (float)period; } return mp_obj_new_float(percent); #else mp_int_t percent; if (cmp >= period) { percent = 100; } else { percent = cmp * 100 / period; } return mp_obj_new_int(percent); #endif } STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_timer_obj_t *self = self_in; if (self->ftm.State == HAL_FTM_STATE_RESET) { mp_printf(print, "Timer(%u)", self->tim_id); } else { mp_printf(print, "Timer(%u, prescaler=%u, period=%u, mode=%s)", self->tim_id, 1 << (self->ftm.Instance->SC & 7), self->ftm.Instance->MOD & 0xffff, self->ftm.Init.CounterMode == FTM_COUNTERMODE_UP ? "UP" : "CENTER"); } } /// \method init(*, freq, prescaler, period) /// Initialise the timer. Initialisation must be either by frequency (in Hz) /// or by prescaler and period: /// /// tim.init(freq=100) # set the timer to trigger at 100Hz /// tim.init(prescaler=83, period=999) # set the prescaler and period directly /// /// Keyword arguments: /// /// - `freq` - specifies the periodic frequency of the timer. You migh also /// view this as the frequency with which the timer goes through /// one complete cycle. /// /// - `prescaler` 1, 2, 4, 8 16 32, 64 or 128 - specifies the value to be loaded into the /// timer's prescaler. The timer clock source is divided by /// (`prescaler`) to arrive at the timer clock. /// /// - `period` [0-0xffff] - Specifies the value to be loaded into the timer's /// Modulo Register (MOD). This determines the period of the timer (i.e. /// when the counter cycles). The timer counter will roll-over after /// `period` timer clock cycles. In center mode, a compare register > 0x7fff /// doesn't seem to work properly, so keep this in mind. /// /// - `mode` can be one of: /// - `Timer.UP` - configures the timer to count from 0 to MOD (default) /// - `Timer.CENTER` - confgures the timer to count from 0 to MOD and /// then back down to 0. /// /// - `callback` - as per Timer.callback() /// /// You must either specify freq or both of period and prescaler. STATIC const mp_arg_t pyb_timer_init_args[] = { { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = FTM_COUNTERMODE_UP} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; #define PYB_TIMER_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_timer_init_args) STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // parse args mp_arg_val_t vals[PYB_TIMER_INIT_NUM_ARGS]; mp_arg_parse_all(n_args, args, kw_args, PYB_TIMER_INIT_NUM_ARGS, pyb_timer_init_args, vals); FTM_HandleTypeDef *ftm = &self->ftm; // set the TIM configuration values FTM_Base_InitTypeDef *init = &ftm->Init; if (vals[0].u_int != 0xffffffff) { // set prescaler and period from frequency if (vals[0].u_int == 0) { mp_raise_ValueError("can't have 0 frequency"); } uint32_t period = MAX(1, F_BUS / vals[0].u_int); uint32_t prescaler_shift = 0; while (period > 0xffff && prescaler_shift < 7) { period >>= 1; prescaler_shift++; } if (period > 0xffff) { period = 0xffff; } init->PrescalerShift = prescaler_shift; init->Period = period; } else if (vals[1].u_int != 0xffffffff && vals[2].u_int != 0xffffffff) { // set prescaler and period directly init->PrescalerShift = get_prescaler_shift(vals[1].u_int); init->Period = vals[2].u_int; if (!IS_FTM_PERIOD(init->Period)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "period must be between 0 and 65535, not %d", init->Period)); } } else { mp_raise_TypeError("must specify either freq, or prescaler and period"); } init->CounterMode = vals[3].u_int; if (!IS_FTM_COUNTERMODE(init->CounterMode)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "invalid counter mode: %d", init->CounterMode)); } // Currently core/mk20dx128.c sets SIM_SCGC6_FTM0, SIM_SCGC6_FTM1, SIM_SCGC3_FTM2 // so we don't need to do it here. NVIC_SET_PRIORITY(self->irqn, 0xe); // next-to lowest priority HAL_FTM_Base_Init(ftm); if (vals[4].u_obj == mp_const_none) { HAL_FTM_Base_Start(ftm); } else { pyb_timer_callback(self, vals[4].u_obj); } return mp_const_none; } /// \classmethod \constructor(id, ...) /// Construct a new timer object of the given id. If additional /// arguments are given, then the timer is initialised by `init(...)`. /// `id` can be 1 to 14, excluding 3. STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // create new Timer object pyb_timer_obj_t *tim = m_new_obj(pyb_timer_obj_t); memset(tim, 0, sizeof(*tim)); tim->base.type = &pyb_timer_type; tim->callback = mp_const_none; tim->channel = NULL; // get FTM number tim->tim_id = mp_obj_get_int(args[0]); switch (tim->tim_id) { case 0: tim->ftm.Instance = FTM0; tim->irqn = IRQ_FTM0; break; case 1: tim->ftm.Instance = FTM1; tim->irqn = IRQ_FTM1; break; case 2: tim->ftm.Instance = FTM2; tim->irqn = IRQ_FTM2; break; default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer %d does not exist", tim->tim_id)); } if (n_args > 1 || n_kw > 0) { // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_timer_init_helper(tim, n_args - 1, args + 1, &kw_args); } // set the global variable for interrupt callbacks if (tim->tim_id < PYB_TIMER_OBJ_ALL_NUM) { pyb_timer_obj_all[tim->tim_id] = tim; } return (mp_obj_t)tim; } STATIC mp_obj_t pyb_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_timer_init_helper(args[0], n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init); /// \method deinit() /// Deinitialises the timer. /// /// Disables the callback (and the associated irq). /// Disables any channel callbacks (and the associated irq). /// Stops the timer, and disables the timer peripheral. STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) { pyb_timer_obj_t *self = self_in; // Disable the base interrupt pyb_timer_callback(self_in, mp_const_none); pyb_timer_channel_obj_t *chan = self->channel; self->channel = NULL; // Disable the channel interrupts while (chan != NULL) { pyb_timer_channel_callback(chan, mp_const_none); pyb_timer_channel_obj_t *prev_chan = chan; chan = chan->next; prev_chan->next = NULL; } HAL_FTM_Base_DeInit(&self->ftm); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit); /// \method channel(channel, mode, ...) /// /// If only a channel number is passed, then a previously initialized channel /// object is returned (or `None` if there is no previous channel). /// /// Othwerwise, a TimerChannel object is initialized and returned. /// /// Each channel can be configured to perform pwm, output compare, or /// input capture. All channels share the same underlying timer, which means /// that they share the same timer clock. /// /// Keyword arguments: /// /// - `mode` can be one of: /// - `Timer.PWM` - configure the timer in PWM mode (active high). /// - `Timer.PWM_INVERTED` - configure the timer in PWM mode (active low). /// - `Timer.OC_TIMING` - indicates that no pin is driven. /// - `Timer.OC_ACTIVE` - the pin will be made active when a compare /// match occurs (active is determined by polarity) /// - `Timer.OC_INACTIVE` - the pin will be made inactive when a compare /// match occurs. /// - `Timer.OC_TOGGLE` - the pin will be toggled when an compare match occurs. /// - `Timer.IC` - configure the timer in Input Capture mode. /// /// - `callback` - as per TimerChannel.callback() /// /// - `pin` None (the default) or a Pin object. If specified (and not None) /// this will cause the alternate function of the the indicated pin /// to be configured for this timer channel. An error will be raised if /// the pin doesn't support any alternate functions for this timer channel. /// /// Keyword arguments for Timer.PWM modes: /// /// - `pulse_width` - determines the initial pulse width value to use. /// - `pulse_width_percent` - determines the initial pulse width percentage to use. /// /// Keyword arguments for Timer.OC modes: /// /// - `compare` - determines the initial value of the compare register. /// /// - `polarity` can be one of: /// - `Timer.HIGH` - output is active high /// - `Timer.LOW` - output is acive low /// /// Optional keyword arguments for Timer.IC modes: /// /// - `polarity` can be one of: /// - `Timer.RISING` - captures on rising edge. /// - `Timer.FALLING` - captures on falling edge. /// - `Timer.BOTH` - captures on both edges. /// /// PWM Example: /// /// timer = pyb.Timer(0, prescaler=128, period=37500, counter_mode=pyb.Timer.COUNTER_MODE_CENTER) /// ch0 = t0.channel(0, pyb.Timer.PWM, pin=pyb.Pin.board.D22, pulse_width=(t0.period() + 1) // 4) /// ch1 = t0.channel(1, pyb.Timer.PWM, pin=pyb.Pin.board.D23, pulse_width=(t0.period() + 1) // 2) STATIC const mp_arg_t pyb_timer_channel_args[] = { { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_pulse_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_pulse_width_percent, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_compare, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, }; #define PYB_TIMER_CHANNEL_NUM_ARGS MP_ARRAY_SIZE(pyb_timer_channel_args) STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { pyb_timer_obj_t *self = args[0]; mp_int_t channel = mp_obj_get_int(args[1]); if (channel < 0 || channel > 7) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid channel (%d)", channel)); } pyb_timer_channel_obj_t *chan = self->channel; pyb_timer_channel_obj_t *prev_chan = NULL; while (chan != NULL) { if (chan->channel == channel) { break; } prev_chan = chan; chan = chan->next; } // If only the channel number is given return the previously allocated // channel (or None if no previous channel). if (n_args == 2) { if (chan) { return chan; } return mp_const_none; } // If there was already a channel, then remove it from the list. Note that // the order we do things here is important so as to appear atomic to // the IRQ handler. if (chan) { // Turn off any IRQ associated with the channel. pyb_timer_channel_callback(chan, mp_const_none); // Unlink the channel from the list. if (prev_chan) { prev_chan->next = chan->next; } self->channel = chan->next; chan->next = NULL; } // Allocate and initialize a new channel mp_arg_val_t vals[PYB_TIMER_CHANNEL_NUM_ARGS]; mp_arg_parse_all(n_args - 3, args + 3, kw_args, PYB_TIMER_CHANNEL_NUM_ARGS, pyb_timer_channel_args, vals); chan = m_new_obj(pyb_timer_channel_obj_t); memset(chan, 0, sizeof(*chan)); chan->base.type = &pyb_timer_channel_type; chan->timer = self; chan->channel = channel; chan->mode = mp_obj_get_int(args[2]); chan->callback = vals[0].u_obj; mp_obj_t pin_obj = vals[1].u_obj; if (pin_obj != mp_const_none) { if (!mp_obj_is_type(pin_obj, &pin_type)) { mp_raise_ValueError("pin argument needs to be be a Pin type"); } const pin_obj_t *pin = pin_obj; const pin_af_obj_t *af = pin_find_af(pin, AF_FN_FTM, self->tim_id); if (af == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s doesn't have an af for TIM%d", qstr_str(pin->name), self->tim_id)); } // pin.init(mode=AF_PP, af=idx) const mp_obj_t args[6] = { (mp_obj_t)&pin_init_obj, pin_obj, MP_OBJ_NEW_QSTR(MP_QSTR_mode), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP), MP_OBJ_NEW_QSTR(MP_QSTR_af), MP_OBJ_NEW_SMALL_INT(af->idx) }; mp_call_method_n_kw(0, 2, args); } // Link the channel to the timer before we turn the channel on. // Note that this needs to appear atomic to the IRQ handler (the write // to self->channel is atomic, so we're good, but I thought I'd mention // in case this was ever changed in the future). chan->next = self->channel; self->channel = chan; switch (chan->mode) { case CHANNEL_MODE_PWM_NORMAL: case CHANNEL_MODE_PWM_INVERTED: { FTM_OC_InitTypeDef oc_config; oc_config.OCMode = channel_mode_info[chan->mode].oc_mode; if (vals[3].u_obj != mp_const_none) { // pulse width ratio given uint32_t period = compute_period(self); oc_config.Pulse = compute_pwm_value_from_percent(period, vals[3].u_obj); } else { // use absolute pulse width value (defaults to 0 if nothing given) oc_config.Pulse = vals[2].u_int; } oc_config.OCPolarity = FTM_OCPOLARITY_HIGH; HAL_FTM_PWM_ConfigChannel(&self->ftm, &oc_config, channel); if (chan->callback == mp_const_none) { HAL_FTM_PWM_Start(&self->ftm, channel); } else { HAL_FTM_PWM_Start_IT(&self->ftm, channel); } break; } case CHANNEL_MODE_OC_TIMING: case CHANNEL_MODE_OC_ACTIVE: case CHANNEL_MODE_OC_INACTIVE: case CHANNEL_MODE_OC_TOGGLE: { FTM_OC_InitTypeDef oc_config; oc_config.OCMode = channel_mode_info[chan->mode].oc_mode; oc_config.Pulse = vals[4].u_int; oc_config.OCPolarity = vals[5].u_int; if (oc_config.OCPolarity == 0xffffffff) { oc_config.OCPolarity = FTM_OCPOLARITY_HIGH; } if (!IS_FTM_OC_POLARITY(oc_config.OCPolarity)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid polarity (%d)", oc_config.OCPolarity)); } HAL_FTM_OC_ConfigChannel(&self->ftm, &oc_config, channel); if (chan->callback == mp_const_none) { HAL_FTM_OC_Start(&self->ftm, channel); } else { HAL_FTM_OC_Start_IT(&self->ftm, channel); } break; } case CHANNEL_MODE_IC: { FTM_IC_InitTypeDef ic_config; ic_config.ICPolarity = vals[5].u_int; if (ic_config.ICPolarity == 0xffffffff) { ic_config.ICPolarity = FTM_ICPOLARITY_RISING; } if (!IS_FTM_IC_POLARITY(ic_config.ICPolarity)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid polarity (%d)", ic_config.ICPolarity)); } HAL_FTM_IC_ConfigChannel(&self->ftm, &ic_config, chan->channel); if (chan->callback == mp_const_none) { HAL_FTM_IC_Start(&self->ftm, channel); } else { HAL_FTM_IC_Start_IT(&self->ftm, channel); } break; } default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid mode (%d)", chan->mode)); } return chan; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel); /// \method counter([value]) /// Get or set the timer counter. STATIC mp_obj_t pyb_timer_counter(size_t n_args, const mp_obj_t *args) { pyb_timer_obj_t *self = args[0]; if (n_args == 1) { // get return mp_obj_new_int(self->ftm.Instance->CNT); } // set - In order to write to CNT we need to set CNTIN self->ftm.Instance->CNTIN = mp_obj_get_int(args[1]); self->ftm.Instance->CNT = 0; // write any value to load CNTIN into CNT return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_counter_obj, 1, 2, pyb_timer_counter); /// \method prescaler([value]) /// Get or set the prescaler for the timer. STATIC mp_obj_t pyb_timer_prescaler(size_t n_args, const mp_obj_t *args) { pyb_timer_obj_t *self = args[0]; if (n_args == 1) { // get return mp_obj_new_int(1 << (self->ftm.Instance->SC & 7)); } // set mp_uint_t prescaler_shift = get_prescaler_shift(mp_obj_get_int(args[1])); mp_uint_t sc = self->ftm.Instance->SC; sc &= ~7; sc |= FTM_SC_PS(prescaler_shift); self->ftm.Instance->SC = sc; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_prescaler_obj, 1, 2, pyb_timer_prescaler); /// \method period([value]) /// Get or set the period of the timer. STATIC mp_obj_t pyb_timer_period(size_t n_args, const mp_obj_t *args) { pyb_timer_obj_t *self = args[0]; if (n_args == 1) { // get return mp_obj_new_int(self->ftm.Instance->MOD & 0xffff); } // set mp_int_t period = mp_obj_get_int(args[1]) & 0xffff; self->ftm.Instance->CNT = 0; self->ftm.Instance->MOD = period; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_period_obj, 1, 2, pyb_timer_period); /// \method callback(fun) /// Set the function to be called when the timer triggers. /// `fun` is passed 1 argument, the timer object. /// If `fun` is `None` then the callback will be disabled. STATIC mp_obj_t pyb_timer_callback(mp_obj_t self_in, mp_obj_t callback) { pyb_timer_obj_t *self = self_in; if (callback == mp_const_none) { // stop interrupt (but not timer) __HAL_FTM_DISABLE_TOF_IT(&self->ftm); self->callback = mp_const_none; } else if (mp_obj_is_callable(callback)) { self->callback = callback; HAL_NVIC_EnableIRQ(self->irqn); // start timer, so that it interrupts on overflow HAL_FTM_Base_Start_IT(&self->ftm); } else { mp_raise_ValueError("callback must be None or a callable object"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_timer_callback_obj, pyb_timer_callback); #if MICROPY_TIMER_REG reg_t timer_reg[] = { REG_ENTRY(FTM_TypeDef, SC), REG_ENTRY(FTM_TypeDef, CNT), REG_ENTRY(FTM_TypeDef, MOD), REG_ENTRY(FTM_TypeDef, CNTIN), REG_ENTRY(FTM_TypeDef, STATUS), REG_ENTRY(FTM_TypeDef, MODE), REG_ENTRY(FTM_TypeDef, SYNC), REG_ENTRY(FTM_TypeDef, OUTINIT), REG_ENTRY(FTM_TypeDef, OUTMASK), REG_ENTRY(FTM_TypeDef, COMBINE), REG_ENTRY(FTM_TypeDef, DEADTIME), REG_ENTRY(FTM_TypeDef, EXTTRIG), REG_ENTRY(FTM_TypeDef, POL), REG_ENTRY(FTM_TypeDef, FMS), REG_ENTRY(FTM_TypeDef, FILTER), REG_ENTRY(FTM_TypeDef, FLTCTRL), REG_ENTRY(FTM_TypeDef, QDCTRL), REG_ENTRY(FTM_TypeDef, CONF), REG_ENTRY(FTM_TypeDef, FLTPOL), REG_ENTRY(FTM_TypeDef, SYNCONF), REG_ENTRY(FTM_TypeDef, INVCTRL), REG_ENTRY(FTM_TypeDef, SWOCTRL), REG_ENTRY(FTM_TypeDef, PWMLOAD), }; mp_obj_t pyb_timer_reg(uint n_args, const mp_obj_t *args) { pyb_timer_obj_t *self = args[0]; return reg_cmd(self->ftm.Instance, timer_reg, MP_ARRAY_SIZE(timer_reg), n_args - 1, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_reg_obj, 1, 3, pyb_timer_reg); #endif // MICROPY_TIMER_REG STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_timer_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_timer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&pyb_timer_channel_obj) }, { MP_ROM_QSTR(MP_QSTR_counter), MP_ROM_PTR(&pyb_timer_counter_obj) }, { MP_ROM_QSTR(MP_QSTR_prescaler), MP_ROM_PTR(&pyb_timer_prescaler_obj) }, { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&pyb_timer_period_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&pyb_timer_callback_obj) }, #if MICROPY_TIMER_REG { MP_ROM_QSTR(MP_QSTR_reg), MP_ROM_PTR(&pyb_timer_reg_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_UP), MP_ROM_INT(FTM_COUNTERMODE_UP) }, { MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(FTM_COUNTERMODE_CENTER) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_INT(CHANNEL_MODE_PWM_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_PWM_INVERTED), MP_ROM_INT(CHANNEL_MODE_PWM_INVERTED) }, { MP_ROM_QSTR(MP_QSTR_OC_TIMING), MP_ROM_INT(CHANNEL_MODE_OC_TIMING) }, { MP_ROM_QSTR(MP_QSTR_OC_ACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_ACTIVE) }, { MP_ROM_QSTR(MP_QSTR_OC_INACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_INACTIVE) }, { MP_ROM_QSTR(MP_QSTR_OC_TOGGLE), MP_ROM_INT(CHANNEL_MODE_OC_TOGGLE) }, { MP_ROM_QSTR(MP_QSTR_IC), MP_ROM_INT(CHANNEL_MODE_IC) }, { MP_ROM_QSTR(MP_QSTR_HIGH), MP_ROM_INT(FTM_OCPOLARITY_HIGH) }, { MP_ROM_QSTR(MP_QSTR_LOW), MP_ROM_INT(FTM_OCPOLARITY_LOW) }, { MP_ROM_QSTR(MP_QSTR_RISING), MP_ROM_INT(FTM_ICPOLARITY_RISING) }, { MP_ROM_QSTR(MP_QSTR_FALLING), MP_ROM_INT(FTM_ICPOLARITY_FALLING) }, { MP_ROM_QSTR(MP_QSTR_BOTH), MP_ROM_INT(FTM_ICPOLARITY_BOTH) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table); const mp_obj_type_t pyb_timer_type = { { &mp_type_type }, .name = MP_QSTR_Timer, .print = pyb_timer_print, .make_new = pyb_timer_make_new, .locals_dict = (mp_obj_t)&pyb_timer_locals_dict, }; /// \moduleref pyb /// \class TimerChannel - setup a channel for a timer. /// /// Timer channels are used to generate/capture a signal using a timer. /// /// TimerChannel objects are created using the Timer.channel() method. STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_timer_channel_obj_t *self = self_in; mp_printf(print, "TimerChannel(timer=%u, channel=%u, mode=%s)", self->timer->tim_id, self->channel, qstr_str(channel_mode_info[self->mode].name)); } /// \method capture([value]) /// Get or set the capture value associated with a channel. /// capture, compare, and pulse_width are all aliases for the same function. /// capture is the logical name to use when the channel is in input capture mode. /// \method compare([value]) /// Get or set the compare value associated with a channel. /// capture, compare, and pulse_width are all aliases for the same function. /// compare is the logical name to use when the channel is in output compare mode. /// \method pulse_width([value]) /// Get or set the pulse width value associated with a channel. /// capture, compare, and pulse_width are all aliases for the same function. /// pulse_width is the logical name to use when the channel is in PWM mode. /// /// In edge aligned mode, a pulse_width of `period + 1` corresponds to a duty cycle of 100% /// In center aligned mode, a pulse width of `period` corresponds to a duty cycle of 100% STATIC mp_obj_t pyb_timer_channel_capture_compare(size_t n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *self = args[0]; FTM_TypeDef *FTMx = self->timer->ftm.Instance; if (n_args == 1) { // get return mp_obj_new_int(FTMx->channel[self->channel].CV & 0xffff); } mp_int_t pw = mp_obj_get_int(args[1]); // set FTMx->channel[self->channel].CV = pw & 0xffff; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_capture_compare_obj, 1, 2, pyb_timer_channel_capture_compare); /// \method pulse_width_percent([value]) /// Get or set the pulse width percentage associated with a channel. The value /// is a number between 0 and 100 and sets the percentage of the timer period /// for which the pulse is active. The value can be an integer or /// floating-point number for more accuracy. For example, a value of 25 gives /// a duty cycle of 25%. STATIC mp_obj_t pyb_timer_channel_pulse_width_percent(size_t n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *self = args[0]; FTM_TypeDef *FTMx = self->timer->ftm.Instance; uint32_t period = compute_period(self->timer); if (n_args == 1) { // get uint32_t cmp = FTMx->channel[self->channel].CV & 0xffff; return compute_percent_from_pwm_value(period, cmp); } else { // set uint32_t cmp = compute_pwm_value_from_percent(period, args[1]); FTMx->channel[self->channel].CV = cmp & 0xffff; return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_pulse_width_percent_obj, 1, 2, pyb_timer_channel_pulse_width_percent); /// \method callback(fun) /// Set the function to be called when the timer channel triggers. /// `fun` is passed 1 argument, the timer object. /// If `fun` is `None` then the callback will be disabled. STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback) { pyb_timer_channel_obj_t *self = self_in; if (callback == mp_const_none) { // stop interrupt (but not timer) __HAL_FTM_DISABLE_CH_IT(&self->timer->ftm, self->channel); self->callback = mp_const_none; } else if (mp_obj_is_callable(callback)) { self->callback = callback; HAL_NVIC_EnableIRQ(self->timer->irqn); // start timer, so that it interrupts on overflow switch (self->mode) { case CHANNEL_MODE_PWM_NORMAL: case CHANNEL_MODE_PWM_INVERTED: HAL_FTM_PWM_Start_IT(&self->timer->ftm, self->channel); break; case CHANNEL_MODE_OC_TIMING: case CHANNEL_MODE_OC_ACTIVE: case CHANNEL_MODE_OC_INACTIVE: case CHANNEL_MODE_OC_TOGGLE: HAL_FTM_OC_Start_IT(&self->timer->ftm, self->channel); break; case CHANNEL_MODE_IC: HAL_FTM_IC_Start_IT(&self->timer->ftm, self->channel); break; } } else { mp_raise_ValueError("callback must be None or a callable object"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_timer_channel_callback_obj, pyb_timer_channel_callback); #if MICROPY_TIMER_REG reg_t timer_channel_reg[] = { REG_ENTRY(FTM_ChannelTypeDef, CSC), REG_ENTRY(FTM_ChannelTypeDef, CV), }; mp_obj_t pyb_timer_channel_reg(uint n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *self = args[0]; return reg_cmd(&self->timer->ftm.Instance->channel[self->channel], timer_channel_reg, MP_ARRAY_SIZE(timer_channel_reg), n_args - 1, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_reg_obj, 1, 3, pyb_timer_channel_reg); #endif STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&pyb_timer_channel_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_pulse_width), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) }, { MP_ROM_QSTR(MP_QSTR_pulse_width_percent), MP_ROM_PTR(&pyb_timer_channel_pulse_width_percent_obj) }, { MP_ROM_QSTR(MP_QSTR_capture), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) }, { MP_ROM_QSTR(MP_QSTR_compare), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) }, #if MICROPY_TIMER_REG { MP_ROM_QSTR(MP_QSTR_reg), MP_ROM_PTR(&pyb_timer_channel_reg_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table); STATIC const mp_obj_type_t pyb_timer_channel_type = { { &mp_type_type }, .name = MP_QSTR_TimerChannel, .print = pyb_timer_channel_print, .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict, }; STATIC bool ftm_handle_irq_callback(pyb_timer_obj_t *self, mp_uint_t channel, mp_obj_t callback) { // execute callback if it's set if (callback == mp_const_none) { return false; } bool handled = false; // When executing code within a handler we must lock the GC to prevent // any memory allocations. We must also catch any exceptions. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_1(callback, self); nlr_pop(); handled = true; } else { // Uncaught exception; disable the callback so it doesn't run again. self->callback = mp_const_none; if (channel == 0xffffffff) { printf("Uncaught exception in Timer(" UINT_FMT ") interrupt handler\n", self->tim_id); } else { printf("Uncaught exception in Timer(" UINT_FMT ") channel " UINT_FMT " interrupt handler\n", self->tim_id, channel); } mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } gc_unlock(); return handled; } STATIC void ftm_irq_handler(uint tim_id) { if (tim_id >= PYB_TIMER_OBJ_ALL_NUM) { return; } // get the timer object pyb_timer_obj_t *self = pyb_timer_obj_all[tim_id]; if (self == NULL) { // timer object has not been set, so we can't do anything printf("No timer object for id=%d\n", tim_id); return; } FTM_HandleTypeDef *hftm = &self->ftm; bool handled = false; // Check for timer (versus timer channel) interrupt. if (__HAL_FTM_GET_TOF_IT(hftm) && __HAL_FTM_GET_TOF_FLAG(hftm)) { __HAL_FTM_CLEAR_TOF_FLAG(hftm); if (ftm_handle_irq_callback(self, 0xffffffff, self->callback)) { handled = true; } else { __HAL_FTM_DISABLE_TOF_IT(&self->ftm); printf("No callback for Timer %d TOF (now disabled)\n", tim_id); } } uint32_t processed = 0; // Check to see if a timer channel interrupt is pending pyb_timer_channel_obj_t *chan = self->channel; while (chan != NULL) { processed |= (1 << chan->channel); if (__HAL_FTM_GET_CH_IT(&self->ftm, chan->channel) && __HAL_FTM_GET_CH_FLAG(&self->ftm, chan->channel)) { __HAL_FTM_CLEAR_CH_FLAG(&self->ftm, chan->channel); if (ftm_handle_irq_callback(self, chan->channel, chan->callback)) { handled = true; } else { __HAL_FTM_DISABLE_CH_IT(&self->ftm, chan->channel); printf("No callback for Timer %d channel %u (now disabled)\n", self->tim_id, chan->channel); } } chan = chan->next; } if (!handled) { // An interrupt occurred for a channel we didn't process. Find it and // turn it off. for (mp_uint_t channel = 0; channel < 8; channel++) { if ((processed & (1 << channel)) == 0) { if (__HAL_FTM_GET_CH_FLAG(&self->ftm, channel) != 0) { __HAL_FTM_CLEAR_CH_FLAG(&self->ftm, channel); __HAL_FTM_DISABLE_CH_IT(&self->ftm, channel); printf("Unhandled interrupt Timer %d channel %u (now disabled)\n", tim_id, channel); } } } } } void ftm0_isr(void) { ftm_irq_handler(0); } void ftm1_isr(void) { ftm_irq_handler(1); } void ftm2_isr(void) { ftm_irq_handler(2); } micropython-1.12/ports/teensy/timer.h000066400000000000000000000026501357706137100177740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_TEENSY_TIMER_H #define MICROPY_INCLUDED_TEENSY_TIMER_H extern const mp_obj_type_t pyb_timer_type; void timer_init0(void); void timer_deinit(void); #endif // MICROPY_INCLUDED_TEENSY_TIMER_H micropython-1.12/ports/teensy/uart.c000066400000000000000000000375251357706137100176330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "bufhelper.h" #include "uart.h" /// \moduleref pyb /// \class UART - duplex serial communication bus /// /// UART implements the standard UART/USART duplex serial communications protocol. At /// the physical level it consists of 2 lines: RX and TX. /// /// See usage model of I2C. UART is very similar. Main difference is /// parameters to init the UART bus: /// /// from pyb import UART /// /// uart = UART(1, 9600) # init with given baudrate /// uart.init(9600, bits=8, stop=1, parity=None) # init with given parameters /// /// Bits can be 8 or 9, stop can be 1 or 2, parity can be None, 0 (even), 1 (odd). /// /// Extra method: /// /// uart.any() # returns True if any characters waiting struct _pyb_uart_obj_t { mp_obj_base_t base; pyb_uart_t uart_id; bool is_enabled; // UART_HandleTypeDef uart; }; pyb_uart_obj_t *pyb_uart_global_debug = NULL; // assumes Init parameters have been set up correctly bool uart_init2(pyb_uart_obj_t *uart_obj) { #if 0 USART_TypeDef *UARTx = NULL; uint32_t GPIO_Pin = 0; uint8_t GPIO_AF_UARTx = 0; GPIO_TypeDef* GPIO_Port = NULL; switch (uart_obj->uart_id) { // USART1 is on PA9/PA10 (CK on PA8), PB6/PB7 case PYB_UART_1: UARTx = USART1; GPIO_AF_UARTx = GPIO_AF7_USART1; #if defined (PYBV4) || defined(PYBV10) GPIO_Port = GPIOB; GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7; #else GPIO_Port = GPIOA; GPIO_Pin = GPIO_PIN_9 | GPIO_PIN_10; #endif __USART1_CLK_ENABLE(); break; // USART2 is on PA2/PA3 (CK on PA4), PD5/PD6 (CK on PD7) case PYB_UART_2: UARTx = USART2; GPIO_AF_UARTx = GPIO_AF7_USART2; GPIO_Port = GPIOA; GPIO_Pin = GPIO_PIN_2 | GPIO_PIN_3; __USART2_CLK_ENABLE(); break; // USART3 is on PB10/PB11 (CK on PB12), PC10/PC11 (CK on PC12), PD8/PD9 (CK on PD10) case PYB_UART_3: UARTx = USART3; GPIO_AF_UARTx = GPIO_AF7_USART3; #if defined(PYBV3) || defined(PYBV4) | defined(PYBV10) GPIO_Port = GPIOB; GPIO_Pin = GPIO_PIN_10 | GPIO_PIN_11; #else GPIO_Port = GPIOD; GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9; #endif __USART3_CLK_ENABLE(); break; // UART4 is on PA0/PA1, PC10/PC11 case PYB_UART_4: UARTx = UART4; GPIO_AF_UARTx = GPIO_AF8_UART4; GPIO_Port = GPIOA; GPIO_Pin = GPIO_PIN_0 | GPIO_PIN_1; __UART4_CLK_ENABLE(); break; // USART6 is on PC6/PC7 (CK on PC8) case PYB_UART_6: UARTx = USART6; GPIO_AF_UARTx = GPIO_AF8_USART6; GPIO_Port = GPIOC; GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7; __USART6_CLK_ENABLE(); break; default: return false; } // init GPIO GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = GPIO_Pin; GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Alternate = GPIO_AF_UARTx; HAL_GPIO_Init(GPIO_Port, &GPIO_InitStructure); // init UARTx uart_obj->uart.Instance = UARTx; HAL_UART_Init(&uart_obj->uart); uart_obj->is_enabled = true; #endif return true; } bool uart_init(pyb_uart_obj_t *uart_obj, uint32_t baudrate) { #if 0 UART_HandleTypeDef *uh = &uart_obj->uart; memset(uh, 0, sizeof(*uh)); uh->Init.BaudRate = baudrate; uh->Init.WordLength = UART_WORDLENGTH_8B; uh->Init.StopBits = UART_STOPBITS_1; uh->Init.Parity = UART_PARITY_NONE; uh->Init.Mode = UART_MODE_TX_RX; uh->Init.HwFlowCtl = UART_HWCONTROL_NONE; uh->Init.OverSampling = UART_OVERSAMPLING_16; #endif return uart_init2(uart_obj); } mp_uint_t uart_rx_any(pyb_uart_obj_t *uart_obj) { #if 0 return __HAL_UART_GET_FLAG(&uart_obj->uart, UART_FLAG_RXNE); #else return 0; #endif } int uart_rx_char(pyb_uart_obj_t *uart_obj) { uint8_t ch; #if 0 if (HAL_UART_Receive(&uart_obj->uart, &ch, 1, 0) != HAL_OK) { ch = 0; } #else ch = 'A'; #endif return ch; } void uart_tx_char(pyb_uart_obj_t *uart_obj, int c) { #if 0 uint8_t ch = c; HAL_UART_Transmit(&uart_obj->uart, &ch, 1, 100000); #endif } void uart_tx_str(pyb_uart_obj_t *uart_obj, const char *str) { #if 0 HAL_UART_Transmit(&uart_obj->uart, (uint8_t*)str, strlen(str), 100000); #endif } void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len) { #if 0 HAL_UART_Transmit(&uart_obj->uart, (uint8_t*)str, len, 100000); #endif } void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len) { for (const char *top = str + len; str < top; str++) { if (*str == '\n') { uart_tx_char(uart_obj, '\r'); } uart_tx_char(uart_obj, *str); } } /******************************************************************************/ /* MicroPython bindings */ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = self_in; if (!self->is_enabled) { mp_printf(print, "UART(%lu)", self->uart_id); } else { #if 0 mp_printf(print, "UART(%lu, baudrate=%u, bits=%u, stop=%u", self->uart_id, self->uart.Init.BaudRate, self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9, self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2); if (self->uart.Init.Parity == UART_PARITY_NONE) { mp_print_str(print, ", parity=None)"); } else { mp_printf(print, ", parity=%u)", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1); } #endif } } /// \method init(baudrate, *, bits=8, stop=1, parity=None) /// /// Initialise the SPI bus with the given parameters: /// /// - `baudrate` is the clock rate. /// - `bits` is the number of bits per byte, 8 or 9. /// - `stop` is the number of stop bits, 1 or 2. /// - `parity` is the parity, `None`, 0 (even) or 1 (odd). STATIC const mp_arg_t pyb_uart_init_args[] = { { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; #define PYB_UART_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_init_args) STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // parse args mp_arg_val_t vals[PYB_UART_INIT_NUM_ARGS]; mp_arg_parse_all(n_args, args, kw_args, PYB_UART_INIT_NUM_ARGS, pyb_uart_init_args, vals); #if 0 // set the UART configuration values memset(&self->uart, 0, sizeof(self->uart)); UART_InitTypeDef *init = &self->uart.Init; init->BaudRate = vals[0].u_int; init->WordLength = vals[1].u_int == 8 ? UART_WORDLENGTH_8B : UART_WORDLENGTH_9B; switch (vals[2].u_int) { case 1: init->StopBits = UART_STOPBITS_1; break; default: init->StopBits = UART_STOPBITS_2; break; } if (vals[3].u_obj == mp_const_none) { init->Parity = UART_PARITY_NONE; } else { mp_int_t parity = mp_obj_get_int(vals[3].u_obj); init->Parity = (parity & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN; } init->Mode = UART_MODE_TX_RX; init->HwFlowCtl = UART_HWCONTROL_NONE; init->OverSampling = UART_OVERSAMPLING_16; // init UART (if it fails, it's because the port doesn't exist) if (!uart_init2(self)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART port %d does not exist", self->uart_id)); } #endif return mp_const_none; } /// \classmethod \constructor(bus, ...) /// /// Construct a UART object on the given bus. `bus` can be 1-6, or 'XA', 'XB', 'YA', or 'YB'. /// With no additional parameters, the UART object is created but not /// initialised (it has the settings from the last initialisation of /// the bus, if any). If extra arguments are given, the bus is initialised. /// See `init` for parameters of initialisation. /// /// The physical pins of the UART busses are: /// /// - `UART(4)` is on `XA`: `(TX, RX) = (X1, X2) = (PA0, PA1)` /// - `UART(1)` is on `XB`: `(TX, RX) = (X9, X10) = (PB6, PB7)` /// - `UART(6)` is on `YA`: `(TX, RX) = (Y1, Y2) = (PC6, PC7)` /// - `UART(3)` is on `YB`: `(TX, RX) = (Y9, Y10) = (PB10, PB11)` /// - `UART(2)` is on: `(TX, RX) = (X3, X4) = (PA2, PA3)` STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, uint n_args, uint n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // create object pyb_uart_obj_t *o = m_new_obj(pyb_uart_obj_t); o->base.type = &pyb_uart_type; // work out port o->uart_id = 0; #if 0 if (mp_obj_is_str(args[0])) { const char *port = mp_obj_str_get_str(args[0]); if (0) { #if defined(PYBV10) } else if (strcmp(port, "XA") == 0) { o->uart_id = PYB_UART_XA; } else if (strcmp(port, "XB") == 0) { o->uart_id = PYB_UART_XB; } else if (strcmp(port, "YA") == 0) { o->uart_id = PYB_UART_YA; } else if (strcmp(port, "YB") == 0) { o->uart_id = PYB_UART_YB; #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART port %s does not exist", port)); } } else { o->uart_id = mp_obj_get_int(args[0]); } #endif if (n_args > 1 || n_kw > 0) { // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); pyb_uart_init_helper(o, n_args - 1, args + 1, &kw_args); } return o; } STATIC mp_obj_t pyb_uart_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { return pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); /// \method deinit() /// Turn off the UART bus. STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { //pyb_uart_obj_t *self = self_in; // TODO return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit); /// \method any() /// Return `True` if any characters waiting, else `False`. STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; if (uart_rx_any(self)) { return mp_const_true; } else { return mp_const_false; } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any); /// \method send(send, *, timeout=5000) /// Send data on the bus: /// /// - `send` is the data to send (an integer to send, or a buffer object). /// - `timeout` is the timeout in milliseconds to wait for the send. /// /// Return value: `None`. STATIC const mp_arg_t pyb_uart_send_args[] = { { MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; #define PYB_UART_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_send_args) STATIC mp_obj_t pyb_uart_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide pyb_uart_obj_t *self = args[0]; // parse args mp_arg_val_t vals[PYB_UART_SEND_NUM_ARGS]; mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_UART_SEND_NUM_ARGS, pyb_uart_send_args, vals); #if 0 // get the buffer to send from mp_buffer_info_t bufinfo; uint8_t data[1]; pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data); // send the data HAL_StatusTypeDef status = HAL_UART_Transmit(&self->uart, bufinfo.buf, bufinfo.len, vals[1].u_int); if (status != HAL_OK) { // TODO really need a HardwareError object, or something nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_UART_Transmit failed with code %d", status)); } #else (void)self; #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_send_obj, 1, pyb_uart_send); /// \method recv(recv, *, timeout=5000) /// /// Receive data on the bus: /// /// - `recv` can be an integer, which is the number of bytes to receive, /// or a mutable buffer, which will be filled with received bytes. /// - `timeout` is the timeout in milliseconds to wait for the receive. /// /// Return value: if `recv` is an integer then a new buffer of the bytes received, /// otherwise the same buffer that was passed in to `recv`. #if 0 STATIC const mp_arg_t pyb_uart_recv_args[] = { { MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; #define PYB_UART_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_recv_args) #endif STATIC mp_obj_t pyb_uart_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // TODO assumes transmission size is 8-bits wide pyb_uart_obj_t *self = args[0]; #if 0 // parse args mp_arg_val_t vals[PYB_UART_RECV_NUM_ARGS]; mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_UART_RECV_NUM_ARGS, pyb_uart_recv_args, vals); // get the buffer to receive into mp_buffer_info_t bufinfo; mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &bufinfo); // receive the data HAL_StatusTypeDef status = HAL_UART_Receive(&self->uart, bufinfo.buf, bufinfo.len, vals[1].u_int); if (status != HAL_OK) { // TODO really need a HardwareError object, or something nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_UART_Receive failed with code %d", status)); } // return the received data if (o_ret == MP_OBJ_NULL) { return vals[0].u_obj; } else { return mp_obj_str_builder_end(o_ret); } #else (void)self; return mp_const_none; #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_recv_obj, 1, pyb_uart_recv); STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_uart_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_uart_recv_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); const mp_obj_type_t pyb_uart_type = { { &mp_type_type }, .name = MP_QSTR_UART, .print = pyb_uart_print, .make_new = pyb_uart_make_new, .locals_dict = (mp_obj_t)&pyb_uart_locals_dict, }; micropython-1.12/ports/teensy/uart.h000066400000000000000000000006561357706137100176330ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_TEENSY_UART_H #define MICROPY_INCLUDED_TEENSY_UART_H typedef enum { PYB_UART_NONE = 0, } pyb_uart_t; typedef struct _pyb_uart_obj_t pyb_uart_obj_t; extern const mp_obj_type_t pyb_uart_type; mp_uint_t uart_rx_any(pyb_uart_obj_t *uart_obj); int uart_rx_char(pyb_uart_obj_t *uart_obj); void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); #endif // MICROPY_INCLUDED_TEENSY_UART_H micropython-1.12/ports/teensy/usb.c000066400000000000000000000015351357706137100174410ustar00rootroot00000000000000#include #include "py/runtime.h" #include "Arduino.h" #include "usb.h" #include "usb_serial.h" bool usb_vcp_is_connected(void) { return usb_configuration && (usb_cdc_line_rtsdtr & (USB_SERIAL_DTR | USB_SERIAL_RTS)); } bool usb_vcp_is_enabled(void) { return true; } int usb_vcp_rx_num(void) { return usb_serial_available(); } int usb_vcp_recv_byte(uint8_t *ptr) { int ch = usb_serial_getchar(); if (ch < 0) { return 0; } *ptr = ch; return 1; } void usb_vcp_send_str(const char* str) { usb_vcp_send_strn(str, strlen(str)); } void usb_vcp_send_strn(const char* str, int len) { usb_serial_write(str, len); } void usb_vcp_send_strn_cooked(const char *str, int len) { for (const char *top = str + len; str < top; str++) { if (*str == '\n') { usb_serial_putchar('\r'); } usb_serial_putchar(*str); } } micropython-1.12/ports/teensy/usb.h000066400000000000000000000006101357706137100174370ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_TEENSY_USB_H #define MICROPY_INCLUDED_TEENSY_USB_H bool usb_vcp_is_connected(void); bool usb_vcp_is_enabled(void); int usb_vcp_rx_num(void); int usb_vcp_recv_byte(uint8_t *ptr); void usb_vcp_send_str(const char* str); void usb_vcp_send_strn(const char* str, int len); void usb_vcp_send_strn_cooked(const char *str, int len); #endif // MICROPY_INCLUDED_TEENSY_USB_H micropython-1.12/ports/unix/000077500000000000000000000000001357706137100161545ustar00rootroot00000000000000micropython-1.12/ports/unix/.gitignore000066400000000000000000000001721357706137100201440ustar00rootroot00000000000000micropython micropython_fast micropython_minimal micropython_coverage micropython_nanbox micropython_freedos* *.py *.gcov micropython-1.12/ports/unix/Makefile000066400000000000000000000230741357706137100176220ustar00rootroot00000000000000-include mpconfigport.mk include ../../py/mkenv.mk # use FROZEN_MANIFEST for new projects, others are legacy FROZEN_MANIFEST ?= manifest.py FROZEN_DIR = FROZEN_MPY_DIR = # define main target PROG = micropython # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # OS name, for simple autoconfig UNAME_S := $(shell uname -s) # include py core make definitions include $(TOP)/py/py.mk GIT_SUBMODULES = lib/axtls lib/berkeley-db-1.xx lib/libffi INC += -I. INC += -I$(TOP) INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror CWARN += -Wpointer-arith -Wuninitialized CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG CFLAGS += -g COPT = -O0 else COPT = -Os -fdata-sections -ffunction-sections -DNDEBUG # _FORTIFY_SOURCE is a feature in gcc/glibc which is intended to provide extra # security for detecting buffer overflows. Some distros (Ubuntu at the very least) # have it enabled by default. # # gcc already optimizes some printf calls to call puts and/or putchar. When # _FORTIFY_SOURCE is enabled and compiling with -O1 or greater, then some # printf calls will also be optimized to call __printf_chk (in glibc). Any # printfs which get redirected to __printf_chk are then no longer synchronized # with printfs that go through mp_printf. # # In MicroPython, we don't want to use the runtime library's printf but rather # go through mp_printf, so that stdout is properly tied into streams, etc. # This means that we either need to turn off _FORTIFY_SOURCE or provide our # own implementation of __printf_chk. We've chosen to turn off _FORTIFY_SOURCE. # It should also be noted that the use of printf in MicroPython is typically # quite limited anyways (primarily for debug and some error reporting, etc # in the unix version). # # Information about _FORTIFY_SOURCE seems to be rather scarce. The best I could # find was this: https://securityblog.redhat.com/2014/03/26/fortify-and-you/ # Original patchset was introduced by # https://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html . # # Turning off _FORTIFY_SOURCE is only required when compiling with -O1 or greater CFLAGS += -U _FORTIFY_SOURCE endif # On OSX, 'gcc' is a symlink to clang unless a real gcc is installed. # The unix port of MicroPython on OSX must be compiled with clang, # while cross-compile ports require gcc, so we test here for OSX and # if necessary override the value of 'CC' set in py/mkenv.mk ifeq ($(UNAME_S),Darwin) ifeq ($(MICROPY_FORCE_32BIT),1) CC = clang -m32 else CC = clang endif # Use clang syntax for map file LDFLAGS_ARCH = -Wl,-map,$@.map -Wl,-dead_strip else # Use gcc syntax for map file LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) # Flags to link with pthread library LIBPTHREAD = -lpthread ifeq ($(MICROPY_FORCE_32BIT),1) # Note: you may need to install i386 versions of dependency packages, # starting with linux-libc-dev:i386 ifeq ($(MICROPY_PY_FFI),1) ifeq ($(UNAME_S),Linux) CFLAGS_MOD += -I/usr/include/i686-linux-gnu endif endif endif ifeq ($(MICROPY_USE_READLINE),1) INC += -I$(TOP)/lib/mp-readline CFLAGS_MOD += -DMICROPY_USE_READLINE=1 LIB_SRC_C_EXTRA += mp-readline/readline.c endif ifeq ($(MICROPY_PY_TERMIOS),1) CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1 SRC_MOD += modtermios.c endif ifeq ($(MICROPY_PY_SOCKET),1) CFLAGS_MOD += -DMICROPY_PY_SOCKET=1 SRC_MOD += modusocket.c endif ifeq ($(MICROPY_PY_THREAD),1) CFLAGS_MOD += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 LDFLAGS_MOD += $(LIBPTHREAD) endif ifeq ($(MICROPY_PY_FFI),1) ifeq ($(MICROPY_STANDALONE),1) LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include) ifeq ($(MICROPY_FORCE_32BIT),1) LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib32/libffi.a else LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib/libffi.a endif else LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) endif ifeq ($(UNAME_S),Linux) LIBFFI_LDFLAGS_MOD += -ldl endif CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1 LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD) SRC_MOD += modffi.c endif ifeq ($(MICROPY_PY_JNI),1) # Path for 64-bit OpenJDK, should be adjusted for other JDKs CFLAGS_MOD += -I/usr/lib/jvm/java-7-openjdk-amd64/include -DMICROPY_PY_JNI=1 SRC_MOD += modjni.c endif # source files SRC_C = \ main.c \ gccollect.c \ unix_mphal.c \ mpthreadport.c \ input.c \ file.c \ modmachine.c \ modos.c \ moduos_vfs.c \ modtime.c \ moduselect.c \ alloc.c \ coverage.c \ fatfs_port.c \ $(SRC_MOD) LIB_SRC_C = $(addprefix lib/,\ $(LIB_SRC_C_EXTRA) \ timeutils/timeutils.c \ ) OBJ = $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(LIB_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),) # To use frozen code create a manifest.py file with a description of files to # freeze, then invoke make with FROZEN_MANIFEST=manifest.py (be sure to build from scratch). CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY CFLAGS += -DMPZ_DIG_SIZE=16 # force 16 bits to work on both 32 and 64 bit archs MPY_CROSS_FLAGS += -mcache-lookup-bc endif ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),) CFLAGS += -DMICROPY_MODULE_FROZEN_STR endif include $(TOP)/py/mkrules.mk .PHONY: test test: $(PROG) $(TOP)/tests/run-tests $(eval DIRNAME=ports/$(notdir $(CURDIR))) cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests # install micropython in /usr/local/bin TARGET = micropython PREFIX = $(DESTDIR)/usr/local BINDIR = $(PREFIX)/bin install: micropython install -d $(BINDIR) install $(TARGET) $(BINDIR)/$(TARGET) # uninstall micropython uninstall: -rm $(BINDIR)/$(TARGET) # build synthetically fast interpreter for benchmarking fast: $(MAKE) COPT="-O2 -DNDEBUG -fno-crossjumping" CFLAGS_EXTRA='-DMP_CONFIGFILE=""' BUILD=build-fast PROG=micropython_fast FROZEN_MANIFEST= # build a minimal interpreter minimal: $(MAKE) COPT="-Os -DNDEBUG" CFLAGS_EXTRA='-DMP_CONFIGFILE=""' \ BUILD=build-minimal PROG=micropython_minimal FROZEN_MANIFEST= \ MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_SOCKET=0 MICROPY_PY_THREAD=0 \ MICROPY_PY_TERMIOS=0 MICROPY_PY_USSL=0 \ MICROPY_USE_READLINE=0 # build interpreter with nan-boxing as object model nanbox: $(MAKE) \ CFLAGS_EXTRA='-DMP_CONFIGFILE=""' \ BUILD=build-nanbox \ PROG=micropython_nanbox \ MICROPY_FORCE_32BIT=1 freedos: $(MAKE) \ CC=i586-pc-msdosdjgpp-gcc \ STRIP=i586-pc-msdosdjgpp-strip \ SIZE=i586-pc-msdosdjgpp-size \ CFLAGS_EXTRA='-DMP_CONFIGFILE="" -DMICROPY_NLR_SETJMP -Dtgamma=gamma -DMICROPY_EMIT_X86=0 -DMICROPY_NO_ALLOCA=1 -DMICROPY_PY_USELECT_POSIX=0' \ BUILD=build-freedos \ PROG=micropython_freedos \ MICROPY_PY_SOCKET=0 \ MICROPY_PY_FFI=0 \ MICROPY_PY_JNI=0 \ MICROPY_PY_BTREE=0 \ MICROPY_PY_THREAD=0 \ MICROPY_PY_USSL=0 # build an interpreter for coverage testing and do the testing coverage: $(MAKE) \ COPT="-O0" CFLAGS_EXTRA='$(CFLAGS_EXTRA) -DMP_CONFIGFILE="" \ -fprofile-arcs -ftest-coverage \ -Wdouble-promotion -Wformat -Wmissing-declarations -Wmissing-prototypes -Wsign-compare \ -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ -DMICROPY_UNIX_COVERAGE' \ LDFLAGS_EXTRA='-fprofile-arcs -ftest-coverage' \ MICROPY_VFS_FAT=1 MICROPY_VFS_LFS1=1 MICROPY_VFS_LFS2=1 \ FROZEN_MANIFEST=manifest_coverage.py \ BUILD=build-coverage PROG=micropython_coverage coverage_test: coverage $(eval DIRNAME=ports/$(notdir $(CURDIR))) cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests -d thread cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --emit native cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --via-mpy -d basics float micropython cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --via-mpy --emit native -d basics float micropython cat $(TOP)/tests/basics/0prelim.py | ./micropython_coverage | grep -q 'abc' gcov -o build-coverage/py $(TOP)/py/*.c gcov -o build-coverage/extmod $(TOP)/extmod/*.c # Value of configure's --host= option (required for cross-compilation). # Deduce it from CROSS_COMPILE by default, but can be overridden. ifneq ($(CROSS_COMPILE),) CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE)) else CROSS_COMPILE_HOST = endif deplibs: libffi axtls libffi: $(BUILD)/lib/libffi/include/ffi.h $(TOP)/lib/libffi/configure: $(TOP)/lib/libffi/autogen.sh cd $(TOP)/lib/libffi; ./autogen.sh # install-exec-recursive & install-data-am targets are used to avoid building # docs and depending on makeinfo $(BUILD)/lib/libffi/include/ffi.h: $(TOP)/lib/libffi/configure mkdir -p $(BUILD)/lib/libffi; cd $(BUILD)/lib/libffi; \ $(abspath $(TOP))/lib/libffi/configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \ $(MAKE) install-exec-recursive; $(MAKE) -C include install-data-am axtls: $(TOP)/lib/axtls/README $(TOP)/lib/axtls/README: @echo "You cloned without --recursive, fetching submodules for you." (cd $(TOP); git submodule update --init --recursive) micropython-1.12/ports/unix/alloc.c000066400000000000000000000070321357706137100174140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Fabian Vogt * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/mpstate.h" #include "py/gc.h" #if MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC) #if defined(__OpenBSD__) || defined(__MACH__) #define MAP_ANONYMOUS MAP_ANON #endif // The memory allocated here is not on the GC heap (and it may contain pointers // that need to be GC'd) so we must somehow trace this memory. We do it by // keeping a linked list of all mmap'd regions, and tracing them explicitly. typedef struct _mmap_region_t { void *ptr; size_t len; struct _mmap_region_t *next; } mmap_region_t; void mp_unix_alloc_exec(size_t min_size, void **ptr, size_t *size) { // size needs to be a multiple of the page size *size = (min_size + 0xfff) & (~0xfff); *ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (*ptr == MAP_FAILED) { *ptr = NULL; } // add new link to the list of mmap'd regions mmap_region_t *rg = m_new_obj(mmap_region_t); rg->ptr = *ptr; rg->len = min_size; rg->next = MP_STATE_VM(mmap_region_head); MP_STATE_VM(mmap_region_head) = rg; } void mp_unix_free_exec(void *ptr, size_t size) { munmap(ptr, size); // unlink the mmap'd region from the list for (mmap_region_t **rg = (mmap_region_t**)&MP_STATE_VM(mmap_region_head); *rg != NULL; *rg = (*rg)->next) { if ((*rg)->ptr == ptr) { mmap_region_t *next = (*rg)->next; m_del_obj(mmap_region_t, *rg); *rg = next; return; } } } void mp_unix_mark_exec(void) { for (mmap_region_t *rg = MP_STATE_VM(mmap_region_head); rg != NULL; rg = rg->next) { gc_collect_root(rg->ptr, rg->len / sizeof(mp_uint_t)); } } #if MICROPY_FORCE_PLAT_ALLOC_EXEC // Provide implementation of libffi ffi_closure_* functions in terms // of the functions above. On a normal Linux system, this save a lot // of code size. void *ffi_closure_alloc(size_t size, void **code); void ffi_closure_free(void *ptr); void *ffi_closure_alloc(size_t size, void **code) { size_t dummy; mp_unix_alloc_exec(size, code, &dummy); return *code; } void ffi_closure_free(void *ptr) { (void)ptr; // TODO } #endif #endif // MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC) micropython-1.12/ports/unix/coverage-frzmpy/000077500000000000000000000000001357706137100212745ustar00rootroot00000000000000micropython-1.12/ports/unix/coverage-frzmpy/frzmpy1.py000066400000000000000000000000211357706137100232470ustar00rootroot00000000000000print('frzmpy1') micropython-1.12/ports/unix/coverage-frzmpy/frzmpy2.py000066400000000000000000000000301357706137100232500ustar00rootroot00000000000000raise ZeroDivisionError micropython-1.12/ports/unix/coverage-frzmpy/frzmpy_pkg1/000077500000000000000000000000001357706137100235455ustar00rootroot00000000000000micropython-1.12/ports/unix/coverage-frzmpy/frzmpy_pkg1/__init__.py000066400000000000000000000001131357706137100256510ustar00rootroot00000000000000# test frozen package with __init__.py print('frzmpy_pkg1.__init__') x = 1 micropython-1.12/ports/unix/coverage-frzmpy/frzmpy_pkg2/000077500000000000000000000000001357706137100235465ustar00rootroot00000000000000micropython-1.12/ports/unix/coverage-frzmpy/frzmpy_pkg2/mod.py000066400000000000000000000001301357706137100246710ustar00rootroot00000000000000# test frozen package without __init__.py print('frzmpy_pkg2.mod') class Foo: x = 1 micropython-1.12/ports/unix/coverage-frzmpy/frzqstr.py000066400000000000000000000001161357706137100233570ustar00rootroot00000000000000# Checks for regression on MP_QSTR_NULL def returns_NULL(): return "NULL" micropython-1.12/ports/unix/coverage-frzstr/000077500000000000000000000000001357706137100212775ustar00rootroot00000000000000micropython-1.12/ports/unix/coverage-frzstr/frzstr1.py000066400000000000000000000000211357706137100232550ustar00rootroot00000000000000print('frzstr1') micropython-1.12/ports/unix/coverage-frzstr/frzstr_pkg1/000077500000000000000000000000001357706137100235535ustar00rootroot00000000000000micropython-1.12/ports/unix/coverage-frzstr/frzstr_pkg1/__init__.py000066400000000000000000000001131357706137100256570ustar00rootroot00000000000000# test frozen package with __init__.py print('frzstr_pkg1.__init__') x = 1 micropython-1.12/ports/unix/coverage-frzstr/frzstr_pkg2/000077500000000000000000000000001357706137100235545ustar00rootroot00000000000000micropython-1.12/ports/unix/coverage-frzstr/frzstr_pkg2/mod.py000066400000000000000000000001301357706137100246770ustar00rootroot00000000000000# test frozen package without __init__.py print('frzstr_pkg2.mod') class Foo: x = 1 micropython-1.12/ports/unix/coverage.c000066400000000000000000000436671357706137100201330ustar00rootroot00000000000000#include #include #include "py/obj.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/gc.h" #include "py/repl.h" #include "py/mpz.h" #include "py/builtin.h" #include "py/emit.h" #include "py/formatfloat.h" #include "py/ringbuf.h" #include "py/stream.h" #include "py/binary.h" #include "py/bc.h" #if defined(MICROPY_UNIX_COVERAGE) // stream testing object typedef struct _mp_obj_streamtest_t { mp_obj_base_t base; uint8_t *buf; size_t len; size_t pos; int error_code; } mp_obj_streamtest_t; STATIC mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); o->buf = m_new(uint8_t, bufinfo.len); memcpy(o->buf, bufinfo.buf, bufinfo.len); o->len = bufinfo.len; o->pos = 0; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf); STATIC mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); o->error_code = mp_obj_get_int(err_in); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error); STATIC mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); if (o->pos < o->len) { if (size > o->len - o->pos) { size = o->len - o->pos; } memcpy(buf, o->buf + o->pos, size); o->pos += size; return size; } else if (o->error_code == 0) { return 0; } else { *errcode = o->error_code; return MP_STREAM_ERROR; } } STATIC mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); (void)buf; (void)size; *errcode = o->error_code; return MP_STREAM_ERROR; } STATIC mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); (void)arg; (void)request; (void)errcode; if (o->error_code != 0) { *errcode = o->error_code; return MP_STREAM_ERROR; } return 0; } STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_set_buf), MP_ROM_PTR(&stest_set_buf_obj) }, { MP_ROM_QSTR(MP_QSTR_set_error), MP_ROM_PTR(&stest_set_error_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_read1), MP_ROM_PTR(&mp_stream_read1_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, }; STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); STATIC const mp_stream_p_t fileio_stream_p = { .read = stest_read, .write = stest_write, .ioctl = stest_ioctl, }; STATIC const mp_obj_type_t mp_type_stest_fileio = { { &mp_type_type }, .protocol = &fileio_stream_p, .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, }; // stream read returns non-blocking error STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { (void)o_in; (void)buf; (void)size; *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, }; STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2); STATIC const mp_stream_p_t textio_stream_p2 = { .read = stest_read2, .write = NULL, .is_text = true, }; STATIC const mp_obj_type_t mp_type_stest_textio2 = { { &mp_type_type }, .protocol = &textio_stream_p2, .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict2, }; // str/bytes objects without a valid hash STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte*)"0123456789"}; STATIC const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte*)"0123456789"}; // function to run extra tests for things that can't be checked by scripts STATIC mp_obj_t extra_coverage(void) { // mp_printf (used by ports that don't have a native printf) { mp_printf(&mp_plat_print, "# mp_printf\n"); mp_printf(&mp_plat_print, "%d %+d % d\n", -123, 123, 123); // sign mp_printf(&mp_plat_print, "%05d\n", -123); // negative number with zero padding mp_printf(&mp_plat_print, "%ld\n", 123); // long mp_printf(&mp_plat_print, "%lx\n", 0x123); // long hex mp_printf(&mp_plat_print, "%X\n", 0x1abcdef); // capital hex mp_printf(&mp_plat_print, "%.2s %.3s\n", "abc", "abc"); // fixed string precision mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools #ifndef NDEBUG mp_printf(&mp_plat_print, "%s\n", NULL); // null string #else mp_printf(&mp_plat_print, "(null)\n"); // without debugging mp_printf won't check for null #endif mp_printf(&mp_plat_print, "%d\n", 0x80000000); // should print signed mp_printf(&mp_plat_print, "%u\n", 0x80000000); // should print unsigned mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned mp_printf(&mp_plat_print, "%X\n", 0x80000000); // should print unsigned mp_printf(&mp_plat_print, "abc\n%"); // string ends in middle of format specifier mp_printf(&mp_plat_print, "%%\n"); // literal % character } // GC { mp_printf(&mp_plat_print, "# GC\n"); // calling gc_free while GC is locked gc_lock(); gc_free(NULL); gc_unlock(); // using gc_realloc to resize to 0, which means free the memory void *p = gc_alloc(4, false); mp_printf(&mp_plat_print, "%p\n", gc_realloc(p, 0, false)); // calling gc_nbytes with a non-heap pointer mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL)); } // vstr { mp_printf(&mp_plat_print, "# vstr\n"); vstr_t *vstr = vstr_new(16); vstr_hint_size(vstr, 32); vstr_add_str(vstr, "ts"); vstr_ins_byte(vstr, 1, 'e'); vstr_ins_char(vstr, 3, 't'); vstr_ins_char(vstr, 10, 's'); mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); vstr_cut_head_bytes(vstr, 2); mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); vstr_cut_tail_bytes(vstr, 10); mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); vstr_printf(vstr, "t%cst", 'e'); mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); vstr_cut_out_bytes(vstr, 3, 10); mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf); VSTR_FIXED(fix, 4); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { vstr_add_str(&fix, "large"); nlr_pop(); } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } fix.len = fix.alloc; if (nlr_push(&nlr) == 0) { vstr_null_terminated_str(&fix); nlr_pop(); } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } } // repl autocomplete { mp_printf(&mp_plat_print, "# repl\n"); const char *str; size_t len = mp_repl_autocomplete("__n", 3, &mp_plat_print, &str); mp_printf(&mp_plat_print, "%.*s\n", (int)len, str); mp_store_global(MP_QSTR_sys, mp_import_name(MP_QSTR_sys, mp_const_none, MP_OBJ_NEW_SMALL_INT(0))); mp_repl_autocomplete("sys.", 4, &mp_plat_print, &str); len = mp_repl_autocomplete("sys.impl", 8, &mp_plat_print, &str); mp_printf(&mp_plat_print, "%.*s\n", (int)len, str); } // attrtuple { mp_printf(&mp_plat_print, "# attrtuple\n"); static const qstr fields[] = {MP_QSTR_start, MP_QSTR_stop, MP_QSTR_step}; static const mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(2), MP_OBJ_NEW_SMALL_INT(3)}; mp_obj_print_helper(&mp_plat_print, mp_obj_new_attrtuple(fields, 3, items), PRINT_REPR); mp_printf(&mp_plat_print, "\n"); } // str { mp_printf(&mp_plat_print, "# str\n"); // intern string mp_printf(&mp_plat_print, "%d\n", mp_obj_is_qstr(mp_obj_str_intern(mp_obj_new_str("intern me", 9)))); } // bytearray { mp_printf(&mp_plat_print, "# bytearray\n"); // create a bytearray via mp_obj_new_bytearray mp_buffer_info_t bufinfo; mp_get_buffer_raise(mp_obj_new_bytearray(4, "data"), &bufinfo, MP_BUFFER_RW); mp_printf(&mp_plat_print, "%.*s\n", bufinfo.len, bufinfo.buf); } // mpz { mp_printf(&mp_plat_print, "# mpz\n"); mp_uint_t value; mpz_t mpz; mpz_init_zero(&mpz); // mpz_as_uint_checked, with success mpz_set_from_int(&mpz, 12345678); mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value)); mp_printf(&mp_plat_print, "%d\n", (int)value); // mpz_as_uint_checked, with negative arg mpz_set_from_int(&mpz, -1); mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value)); // mpz_as_uint_checked, with overflowing arg mpz_set_from_int(&mpz, 1); mpz_shl_inpl(&mpz, &mpz, 70); mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value)); // mpz_set_from_float with inf as argument mpz_set_from_float(&mpz, 1.0 / 0.0); mpz_as_uint_checked(&mpz, &value); mp_printf(&mp_plat_print, "%d\n", (int)value); // mpz_set_from_float with 0 as argument mpz_set_from_float(&mpz, 0); mpz_as_uint_checked(&mpz, &value); mp_printf(&mp_plat_print, "%d\n", (int)value); // mpz_set_from_float with 0fun_bc = &fun_bc; code_state->ip = (const byte*)"\x00"; // just needed for an invalid opcode code_state->sp = &code_state->state[0]; code_state->exc_sp_idx = 0; code_state->old_globals = NULL; mp_vm_return_kind_t ret = mp_execute_bytecode(code_state, MP_OBJ_NULL); mp_printf(&mp_plat_print, "%d %d\n", ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError); } // scheduler { mp_printf(&mp_plat_print, "# scheduler\n"); // lock scheduler mp_sched_lock(); // schedule multiple callbacks; last one should fail for (int i = 0; i < 5; ++i) { mp_printf(&mp_plat_print, "sched(%d)=%d\n", i, mp_sched_schedule(MP_OBJ_FROM_PTR(&mp_builtin_print_obj), MP_OBJ_NEW_SMALL_INT(i))); } // test nested locking/unlocking mp_sched_lock(); mp_sched_unlock(); // shouldn't do anything while scheduler is locked mp_handle_pending(); // unlock scheduler mp_sched_unlock(); mp_printf(&mp_plat_print, "unlocked\n"); // drain pending callbacks while (mp_sched_num_pending()) { mp_handle_pending(); } } // ringbuf { byte buf[100]; ringbuf_t ringbuf = {buf, sizeof(buf), 0, 0}; mp_printf(&mp_plat_print, "# ringbuf\n"); // Single-byte put/get with empty ringbuf. mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); ringbuf_put(&ringbuf, 22); mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_get(&ringbuf)); mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); // Two-byte put/get with empty ringbuf. ringbuf_put16(&ringbuf, 0xaa55); mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); // Two-byte put with full ringbuf. for (int i = 0; i < 99; ++i) { ringbuf_put(&ringbuf, i); } mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb)); // Two-byte put with one byte free. ringbuf_get(&ringbuf); mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x3377)); ringbuf_get(&ringbuf); mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0xcc99)); for (int i = 0; i < 97; ++i) { ringbuf_get(&ringbuf); } mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); // Two-byte put with wrap around on first byte: ringbuf.iput = 0; ringbuf.iget = 0; for (int i = 0; i < 99; ++i) { ringbuf_put(&ringbuf, i); ringbuf_get(&ringbuf); } mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb)); mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); // Two-byte put with wrap around on second byte: ringbuf.iput = 0; ringbuf.iget = 0; for (int i = 0; i < 98; ++i) { ringbuf_put(&ringbuf, i); ringbuf_get(&ringbuf); } mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x22ff)); mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); // Two-byte get from empty ringbuf. ringbuf.iput = 0; ringbuf.iget = 0; mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf)); // Two-byte get from ringbuf with one byte available. ringbuf.iput = 0; ringbuf.iget = 0; ringbuf_put(&ringbuf, 0xaa); mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf)); } mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t); s->base.type = &mp_type_stest_fileio; s->buf = NULL; s->len = 0; s->pos = 0; s->error_code = 0; mp_obj_streamtest_t *s2 = m_new_obj(mp_obj_streamtest_t); s2->base.type = &mp_type_stest_textio2; // return a tuple of data for testing on the Python side mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj, MP_OBJ_FROM_PTR(s), MP_OBJ_FROM_PTR(s2)}; return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items); } MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage); #endif micropython-1.12/ports/unix/fatfs_port.c000066400000000000000000000001071357706137100204650ustar00rootroot00000000000000#include "lib/oofatfs/ff.h" DWORD get_fattime(void) { return 0; } micropython-1.12/ports/unix/fdfile.h000066400000000000000000000030631357706137100175600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_UNIX_FDFILE_H #define MICROPY_INCLUDED_UNIX_FDFILE_H #include "py/obj.h" typedef struct _mp_obj_fdfile_t { mp_obj_base_t base; int fd; } mp_obj_fdfile_t; extern const mp_obj_type_t mp_type_fileio; extern const mp_obj_type_t mp_type_textio; #endif // MICROPY_INCLUDED_UNIX_FDFILE_H micropython-1.12/ports/unix/file.c000066400000000000000000000230171357706137100172420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/builtin.h" #include "py/mphal.h" #include "fdfile.h" #if MICROPY_PY_IO && !MICROPY_VFS #ifdef _WIN32 #define fsync _commit #endif #ifdef MICROPY_CPYTHON_COMPAT STATIC void check_fd_is_open(const mp_obj_fdfile_t *o) { if (o->fd < 0) { mp_raise_ValueError("I/O operation on closed file"); } } #else #define check_fd_is_open(o) #endif extern const mp_obj_type_t mp_type_fileio; extern const mp_obj_type_t mp_type_textio; STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", mp_obj_get_type_str(self_in), self->fd); } STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); mp_int_t r = read(o->fd, buf, size); if (r == -1) { *errcode = errno; return MP_STREAM_ERROR; } return r; } STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); #if MICROPY_PY_OS_DUPTERM if (o->fd <= STDERR_FILENO) { mp_hal_stdout_tx_strn(buf, size); return size; } #endif mp_int_t r = write(o->fd, buf, size); while (r == -1 && errno == EINTR) { if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } r = write(o->fd, buf, size); } if (r == -1) { *errcode = errno; return MP_STREAM_ERROR; } return r; } STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); switch (request) { case MP_STREAM_SEEK: { struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg; off_t off = lseek(o->fd, s->offset, s->whence); if (off == (off_t)-1) { *errcode = errno; return MP_STREAM_ERROR; } s->offset = off; return 0; } case MP_STREAM_FLUSH: if (fsync(o->fd) < 0) { *errcode = errno; return MP_STREAM_ERROR; } return 0; case MP_STREAM_CLOSE: close(o->fd); #ifdef MICROPY_CPYTHON_COMPAT o->fd = -1; #endif return 0; case MP_STREAM_GET_FILENO: return o->fd; default: *errcode = EINVAL; return MP_STREAM_ERROR; } } STATIC mp_obj_t fdfile___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; return mp_stream_close(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fdfile___exit___obj, 4, 4, fdfile___exit__); STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) { mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in); check_fd_is_open(self); return MP_OBJ_NEW_SMALL_INT(self->fd); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno); // Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO, // but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor STATIC const mp_arg_t file_open_args[] = { { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} }, { MP_QSTR_buffering, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; #define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) STATIC mp_obj_t fdfile_open(const mp_obj_type_t *type, mp_arg_val_t *args) { mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t); const char *mode_s = mp_obj_str_get_str(args[1].u_obj); int mode_rw = 0, mode_x = 0; while (*mode_s) { switch (*mode_s++) { case 'r': mode_rw = O_RDONLY; break; case 'w': mode_rw = O_WRONLY; mode_x = O_CREAT | O_TRUNC; break; case 'a': mode_rw = O_WRONLY; mode_x = O_CREAT | O_APPEND; break; case '+': mode_rw = O_RDWR; break; #if MICROPY_PY_IO_FILEIO // If we don't have io.FileIO, then files are in text mode implicitly case 'b': type = &mp_type_fileio; break; case 't': type = &mp_type_textio; break; #endif } } o->base.type = type; mp_obj_t fid = args[0].u_obj; if (mp_obj_is_small_int(fid)) { o->fd = MP_OBJ_SMALL_INT_VALUE(fid); return MP_OBJ_FROM_PTR(o); } const char *fname = mp_obj_str_get_str(fid); int fd = open(fname, mode_x | mode_rw, 0644); if (fd == -1) { mp_raise_OSError(errno); } o->fd = fd; return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t fdfile_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; mp_arg_parse_all_kw_array(n_args, n_kw, args, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals); return fdfile_open(type, arg_vals); } STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&fdfile_fileno_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&fdfile___exit___obj) }, }; STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); #if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t fileio_stream_p = { .read = fdfile_read, .write = fdfile_write, .ioctl = fdfile_ioctl, }; const mp_obj_type_t mp_type_fileio = { { &mp_type_type }, .name = MP_QSTR_FileIO, .print = fdfile_print, .make_new = fdfile_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &fileio_stream_p, .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, }; #endif STATIC const mp_stream_p_t textio_stream_p = { .read = fdfile_read, .write = fdfile_write, .ioctl = fdfile_ioctl, .is_text = true, }; const mp_obj_type_t mp_type_textio = { { &mp_type_type }, .name = MP_QSTR_TextIOWrapper, .print = fdfile_print, .make_new = fdfile_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &textio_stream_p, .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, }; // Factory function for I/O stream classes mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { // TODO: analyze buffering args and instantiate appropriate type mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; mp_arg_parse_all(n_args, args, kwargs, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals); return fdfile_open(&mp_type_textio, arg_vals); } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&mp_type_textio}, .fd = STDIN_FILENO }; const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&mp_type_textio}, .fd = STDOUT_FILENO }; const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&mp_type_textio}, .fd = STDERR_FILENO }; #endif // MICROPY_PY_IO && !MICROPY_VFS micropython-1.12/ports/unix/gccollect.c000066400000000000000000000130071357706137100202600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpstate.h" #include "py/gc.h" #if MICROPY_ENABLE_GC // Even if we have specific support for an architecture, it is // possible to force use of setjmp-based implementation. #if !MICROPY_GCREGS_SETJMP // We capture here callee-save registers, i.e. ones which may contain // interesting values held there by our callers. It doesn't make sense // to capture caller-saved registers, because they, well, put on the // stack already by the caller. #if defined(__x86_64__) typedef mp_uint_t regs_t[6]; STATIC void gc_helper_get_regs(regs_t arr) { register long rbx asm ("rbx"); register long rbp asm ("rbp"); register long r12 asm ("r12"); register long r13 asm ("r13"); register long r14 asm ("r14"); register long r15 asm ("r15"); #ifdef __clang__ // TODO: // This is dirty workaround for Clang. It tries to get around // uncompliant (wrt to GCC) behavior of handling register variables. // Application of this patch here is random, and done only to unbreak // MacOS build. Better, cross-arch ways to deal with Clang issues should // be found. asm("" : "=r"(rbx)); asm("" : "=r"(rbp)); asm("" : "=r"(r12)); asm("" : "=r"(r13)); asm("" : "=r"(r14)); asm("" : "=r"(r15)); #endif arr[0] = rbx; arr[1] = rbp; arr[2] = r12; arr[3] = r13; arr[4] = r14; arr[5] = r15; } #elif defined(__i386__) typedef mp_uint_t regs_t[4]; STATIC void gc_helper_get_regs(regs_t arr) { register long ebx asm ("ebx"); register long esi asm ("esi"); register long edi asm ("edi"); register long ebp asm ("ebp"); #ifdef __clang__ // TODO: // This is dirty workaround for Clang. It tries to get around // uncompliant (wrt to GCC) behavior of handling register variables. // Application of this patch here is random, and done only to unbreak // MacOS build. Better, cross-arch ways to deal with Clang issues should // be found. asm("" : "=r"(ebx)); asm("" : "=r"(esi)); asm("" : "=r"(edi)); asm("" : "=r"(ebp)); #endif arr[0] = ebx; arr[1] = esi; arr[2] = edi; arr[3] = ebp; } #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) typedef mp_uint_t regs_t[10]; STATIC void gc_helper_get_regs(regs_t arr) { register long r4 asm ("r4"); register long r5 asm ("r5"); register long r6 asm ("r6"); register long r7 asm ("r7"); register long r8 asm ("r8"); register long r9 asm ("r9"); register long r10 asm ("r10"); register long r11 asm ("r11"); register long r12 asm ("r12"); register long r13 asm ("r13"); arr[0] = r4; arr[1] = r5; arr[2] = r6; arr[3] = r7; arr[4] = r8; arr[5] = r9; arr[6] = r10; arr[7] = r11; arr[8] = r12; arr[9] = r13; } #else // If we don't have architecture-specific optimized support, // just fall back to setjmp-based implementation. #undef MICROPY_GCREGS_SETJMP #define MICROPY_GCREGS_SETJMP (1) #endif // Arch-specific selection #endif // !MICROPY_GCREGS_SETJMP // If MICROPY_GCREGS_SETJMP was requested explicitly, or if // we enabled it as a fallback above. #if MICROPY_GCREGS_SETJMP #include typedef jmp_buf regs_t; STATIC void gc_helper_get_regs(regs_t arr) { setjmp(arr); } #endif // MICROPY_GCREGS_SETJMP // this function is used by mpthreadport.c MP_NOINLINE void gc_collect_regs_and_stack(void); // Explicitly mark this as noinline to make sure the regs variable // is effectively at the top of the stack: otherwise, in builds where // LTO is enabled and a lot of inlining takes place we risk a stack // layout where regs is lower on the stack than pointers which have // just been allocated but not yet marked, and get incorrectly sweeped. MP_NOINLINE void gc_collect_regs_and_stack(void) { regs_t regs; gc_helper_get_regs(regs); // GC stack (and regs because we captured them) void **regs_ptr = (void**)(void*)®s; gc_collect_root(regs_ptr, ((uintptr_t)MP_STATE_THREAD(stack_top) - (uintptr_t)®s) / sizeof(uintptr_t)); } void gc_collect(void) { //gc_dump_info(); gc_collect_start(); gc_collect_regs_and_stack(); #if MICROPY_PY_THREAD mp_thread_gc_others(); #endif #if MICROPY_EMIT_NATIVE mp_unix_mark_exec(); #endif gc_collect_end(); //printf("-----\n"); //gc_dump_info(); } #endif //MICROPY_ENABLE_GC micropython-1.12/ports/unix/input.c000066400000000000000000000072301357706137100174610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/mpstate.h" #include "py/mphal.h" #include "input.h" #if MICROPY_USE_READLINE == 1 #include "lib/mp-readline/readline.h" #endif #if MICROPY_USE_READLINE == 0 char *prompt(char *p) { // simple read string static char buf[256]; fputs(p, stdout); char *s = fgets(buf, sizeof(buf), stdin); if (!s) { return NULL; } int l = strlen(buf); if (buf[l - 1] == '\n') { buf[l - 1] = 0; } else { l++; } char *line = malloc(l); memcpy(line, buf, l); return line; } #endif void prompt_read_history(void) { #if MICROPY_USE_READLINE_HISTORY #if MICROPY_USE_READLINE == 1 readline_init0(); // will clear history pointers char *home = getenv("HOME"); if (home != NULL) { vstr_t vstr; vstr_init(&vstr, 50); vstr_printf(&vstr, "%s/.micropython.history", home); int fd = open(vstr_null_terminated_str(&vstr), O_RDONLY); if (fd != -1) { vstr_reset(&vstr); for (;;) { char c; int sz = read(fd, &c, 1); if (sz < 0) { break; } if (sz == 0 || c == '\n') { readline_push_history(vstr_null_terminated_str(&vstr)); if (sz == 0) { break; } vstr_reset(&vstr); } else { vstr_add_byte(&vstr, c); } } close(fd); } vstr_clear(&vstr); } #endif #endif } void prompt_write_history(void) { #if MICROPY_USE_READLINE_HISTORY #if MICROPY_USE_READLINE == 1 char *home = getenv("HOME"); if (home != NULL) { vstr_t vstr; vstr_init(&vstr, 50); vstr_printf(&vstr, "%s/.micropython.history", home); int fd = open(vstr_null_terminated_str(&vstr), O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd != -1) { for (int i = MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist)) - 1; i >= 0; i--) { const char *line = MP_STATE_PORT(readline_hist)[i]; if (line != NULL) { int res; res = write(fd, line, strlen(line)); res = write(fd, "\n", 1); (void)res; } } close(fd); } } #endif #endif } micropython-1.12/ports/unix/input.h000066400000000000000000000003161357706137100174640ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_UNIX_INPUT_H #define MICROPY_INCLUDED_UNIX_INPUT_H char *prompt(char *p); void prompt_read_history(void); void prompt_write_history(void); #endif // MICROPY_INCLUDED_UNIX_INPUT_H micropython-1.12/ports/unix/main.c000066400000000000000000000567461357706137100172660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "py/compile.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/repl.h" #include "py/gc.h" #include "py/stackctrl.h" #include "py/mphal.h" #include "py/mpthread.h" #include "extmod/misc.h" #include "extmod/vfs.h" #include "extmod/vfs_posix.h" #include "genhdr/mpversion.h" #include "input.h" // Command line options, with their defaults STATIC bool compile_only = false; STATIC uint emit_opt = MP_EMIT_OPT_NONE; #if MICROPY_ENABLE_GC // Heap size of GC heap (if enabled) // Make it larger on a 64 bit machine, because pointers are larger. long heap_size = 1024*1024 * (sizeof(mp_uint_t) / 4); #endif STATIC void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; ssize_t dummy = write(STDERR_FILENO, str, len); mp_uos_dupterm_tx_strn(str, len); (void)dummy; } const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; #define FORCED_EXIT (0x100) // If exc is SystemExit, return value where FORCED_EXIT bit set, // and lower 8 bits are SystemExit value. For all other exceptions, // return 1. STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { // check for SystemExit if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // None is an exit value of 0; an int is its value; anything else is 1 mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); mp_int_t val = 0; if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { val = 1; } return FORCED_EXIT | (val & 255); } // Report all other exceptions mp_obj_print_exception(&mp_stderr_print, MP_OBJ_FROM_PTR(exc)); return 1; } #define LEX_SRC_STR (1) #define LEX_SRC_VSTR (2) #define LEX_SRC_FILENAME (3) #define LEX_SRC_STDIN (4) // Returns standard error codes: 0 for success, 1 for all other errors, // except if FORCED_EXIT bit is set then script raised SystemExit and the // value of the exit is in the lower 8 bits of the return value STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_input_kind_t input_kind, bool is_repl) { mp_hal_set_interrupt_char(CHAR_CTRL_C); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { // create lexer based on source kind mp_lexer_t *lex; if (source_kind == LEX_SRC_STR) { const char *line = source; lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); } else if (source_kind == LEX_SRC_VSTR) { const vstr_t *vstr = source; lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false); } else if (source_kind == LEX_SRC_FILENAME) { lex = mp_lexer_new_from_file((const char*)source); } else { // LEX_SRC_STDIN lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); } qstr source_name = lex->source_name; #if MICROPY_PY___FILE__ if (input_kind == MP_PARSE_FILE_INPUT) { mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); } #endif mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); #if defined(MICROPY_UNIX_COVERAGE) // allow to print the parse tree in the coverage build if (mp_verbose_flag >= 3) { printf("----------------\n"); mp_parse_node_print(parse_tree.root, 0); printf("----------------\n"); } #endif mp_obj_t module_fun = mp_compile(&parse_tree, source_name, is_repl); if (!compile_only) { // execute it mp_call_function_0(module_fun); // check for pending exception if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } } mp_hal_set_interrupt_char(-1); nlr_pop(); return 0; } else { // uncaught exception mp_hal_set_interrupt_char(-1); return handle_uncaught_exception(nlr.ret_val); } } #if MICROPY_USE_READLINE == 1 #include "lib/mp-readline/readline.h" #else STATIC char *strjoin(const char *s1, int sep_char, const char *s2) { int l1 = strlen(s1); int l2 = strlen(s2); char *s = malloc(l1 + l2 + 2); memcpy(s, s1, l1); if (sep_char != 0) { s[l1] = sep_char; l1 += 1; } memcpy(s + l1, s2, l2); s[l1 + l2] = 0; return s; } #endif STATIC int do_repl(void) { mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_PY_SYS_PLATFORM " version\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); #if MICROPY_USE_READLINE == 1 // use MicroPython supplied readline vstr_t line; vstr_init(&line, 16); for (;;) { mp_hal_stdio_mode_raw(); input_restart: vstr_reset(&line); int ret = readline(&line, ">>> "); mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; if (ret == CHAR_CTRL_C) { // cancel input mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (ret == CHAR_CTRL_D) { // EOF printf("\n"); mp_hal_stdio_mode_orig(); vstr_clear(&line); return 0; } else if (ret == CHAR_CTRL_E) { // paste mode mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); vstr_reset(&line); for (;;) { char c = mp_hal_stdin_rx_chr(); if (c == CHAR_CTRL_C) { // cancel everything mp_hal_stdout_tx_str("\n"); goto input_restart; } else if (c == CHAR_CTRL_D) { // end of input mp_hal_stdout_tx_str("\n"); break; } else { // add char to buffer and echo vstr_add_byte(&line, c); if (c == '\r') { mp_hal_stdout_tx_str("\n=== "); } else { mp_hal_stdout_tx_strn(&c, 1); } } } parse_input_kind = MP_PARSE_FILE_INPUT; } else if (line.len == 0) { if (ret != 0) { printf("\n"); } goto input_restart; } else { // got a line with non-zero length, see if it needs continuing while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { vstr_add_byte(&line, '\n'); ret = readline(&line, "... "); if (ret == CHAR_CTRL_C) { // cancel everything printf("\n"); goto input_restart; } else if (ret == CHAR_CTRL_D) { // stop entering compound statement break; } } } mp_hal_stdio_mode_orig(); ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); if (ret & FORCED_EXIT) { return ret; } } #else // use simple readline for (;;) { char *line = prompt(">>> "); if (line == NULL) { // EOF return 0; } while (mp_repl_continue_with_input(line)) { char *line2 = prompt("... "); if (line2 == NULL) { break; } char *line3 = strjoin(line, '\n', line2); free(line); free(line2); line = line3; } int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); if (ret & FORCED_EXIT) { return ret; } free(line); } #endif } STATIC int do_file(const char *file) { return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); } STATIC int do_str(const char *str) { return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); } STATIC int usage(char **argv) { printf( "usage: %s [] [-X ] [-c ] []\n" "Options:\n" "-v : verbose (trace various operations); can be multiple\n" "-O[N] : apply bytecode optimizations of level N\n" "\n" "Implementation specific options (-X):\n", argv[0] ); int impl_opts_cnt = 0; printf( " compile-only -- parse and compile only\n" #if MICROPY_EMIT_NATIVE " emit={bytecode,native,viper} -- set the default code emitter\n" #else " emit=bytecode -- set the default code emitter\n" #endif ); impl_opts_cnt++; #if MICROPY_ENABLE_GC printf( " heapsize=[w][K|M] -- set the heap size for the GC (default %ld)\n" , heap_size); impl_opts_cnt++; #endif if (impl_opts_cnt == 0) { printf(" (none)\n"); } return 1; } // Process options which set interpreter init options STATIC void pre_process_options(int argc, char **argv) { for (int a = 1; a < argc; a++) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-X") == 0) { if (a + 1 >= argc) { exit(usage(argv)); } if (0) { } else if (strcmp(argv[a + 1], "compile-only") == 0) { compile_only = true; } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { emit_opt = MP_EMIT_OPT_BYTECODE; #if MICROPY_EMIT_NATIVE } else if (strcmp(argv[a + 1], "emit=native") == 0) { emit_opt = MP_EMIT_OPT_NATIVE_PYTHON; } else if (strcmp(argv[a + 1], "emit=viper") == 0) { emit_opt = MP_EMIT_OPT_VIPER; #endif #if MICROPY_ENABLE_GC } else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) { char *end; heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0); // Don't bring unneeded libc dependencies like tolower() // If there's 'w' immediately after number, adjust it for // target word size. Note that it should be *before* size // suffix like K or M, to avoid confusion with kilowords, // etc. the size is still in bytes, just can be adjusted // for word size (taking 32bit as baseline). bool word_adjust = false; if ((*end | 0x20) == 'w') { word_adjust = true; end++; } if ((*end | 0x20) == 'k') { heap_size *= 1024; } else if ((*end | 0x20) == 'm') { heap_size *= 1024 * 1024; } else { // Compensate for ++ below --end; } if (*++end != 0) { goto invalid_arg; } if (word_adjust) { heap_size = heap_size * BYTES_PER_WORD / 4; } // If requested size too small, we'll crash anyway if (heap_size < 700) { goto invalid_arg; } #endif } else { invalid_arg: printf("Invalid option\n"); exit(usage(argv)); } a++; } } } } STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { for (int i = start_arg; i < argc; i++) { mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); } } #ifdef _WIN32 #define PATHLIST_SEP_CHAR ';' #else #define PATHLIST_SEP_CHAR ':' #endif MP_NOINLINE int main_(int argc, char **argv); int main(int argc, char **argv) { #if MICROPY_PY_THREAD mp_thread_init(); #endif // We should capture stack top ASAP after start, and it should be // captured guaranteedly before any other stack variables are allocated. // For this, actual main (renamed main_) should not be inlined into // this function. main_() itself may have other functions inlined (with // their own stack variables), that's why we need this main/main_ split. mp_stack_ctrl_init(); return main_(argc, argv); } MP_NOINLINE int main_(int argc, char **argv) { #ifdef SIGPIPE // Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing // to peer-closed socket will lead to sudden termination of MicroPython // process. SIGPIPE is particularly nasty, because unix shell doesn't // print anything for it, so the above looks like completely sudden and // silent termination for unknown reason. Ignoring SIGPIPE is also what // CPython does. Note that this may lead to problems using MicroPython // scripts as pipe filters, but again, that's what CPython does. So, // scripts which want to follow unix shell pipe semantics (where SIGPIPE // means "pipe was requested to terminate, it's not an error"), should // catch EPIPE themselves. signal(SIGPIPE, SIG_IGN); #endif mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); pre_process_options(argc, argv); #if MICROPY_ENABLE_GC char *heap = malloc(heap_size); gc_init(heap, heap + heap_size); #endif #if MICROPY_ENABLE_PYSTACK static mp_obj_t pystack[1024]; mp_pystack_init(pystack, &pystack[MP_ARRAY_SIZE(pystack)]); #endif mp_init(); #if MICROPY_EMIT_NATIVE // Set default emitter options MP_STATE_VM(default_emit_opt) = emit_opt; #else (void)emit_opt; #endif #if MICROPY_VFS_POSIX { // Mount the host FS at the root of our internal VFS mp_obj_t args[2] = { mp_type_vfs_posix.make_new(&mp_type_vfs_posix, 0, 0, NULL), MP_OBJ_NEW_QSTR(MP_QSTR__slash_), }; mp_vfs_mount(2, args, (mp_map_t*)&mp_const_empty_map); MP_STATE_VM(vfs_cur) = MP_STATE_VM(vfs_mount_table); } #endif char *home = getenv("HOME"); char *path = getenv("MICROPYPATH"); if (path == NULL) { #ifdef MICROPY_PY_SYS_PATH_DEFAULT path = MICROPY_PY_SYS_PATH_DEFAULT; #else path = "~/.micropython/lib:/usr/lib/micropython"; #endif } size_t path_num = 1; // [0] is for current dir (or base dir of the script) if (*path == ':') { path_num++; } for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) { path_num++; if (p != NULL) { p++; } } mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num); mp_obj_t *path_items; mp_obj_list_get(mp_sys_path, &path_num, &path_items); path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_); { char *p = path; for (mp_uint_t i = 1; i < path_num; i++) { char *p1 = strchr(p, PATHLIST_SEP_CHAR); if (p1 == NULL) { p1 = p + strlen(p); } if (p[0] == '~' && p[1] == '/' && home != NULL) { // Expand standalone ~ to $HOME int home_l = strlen(home); vstr_t vstr; vstr_init(&vstr, home_l + (p1 - p - 1) + 1); vstr_add_strn(&vstr, home, home_l); vstr_add_strn(&vstr, p + 1, p1 - p - 1); path_items[i] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } else { path_items[i] = mp_obj_new_str_via_qstr(p, p1 - p); } p = p1 + 1; } } mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); #if defined(MICROPY_UNIX_COVERAGE) { MP_DECLARE_CONST_FUN_OBJ_0(extra_coverage_obj); mp_store_global(QSTR_FROM_STR_STATIC("extra_coverage"), MP_OBJ_FROM_PTR(&extra_coverage_obj)); } #endif // Here is some example code to create a class and instance of that class. // First is the Python, then the C code. // // class TestClass: // pass // test_obj = TestClass() // test_obj.attr = 42 // // mp_obj_t test_class_type, test_class_instance; // test_class_type = mp_obj_new_type(QSTR_FROM_STR_STATIC("TestClass"), mp_const_empty_tuple, mp_obj_new_dict(0)); // mp_store_name(QSTR_FROM_STR_STATIC("test_obj"), test_class_instance = mp_call_function_0(test_class_type)); // mp_store_attr(test_class_instance, QSTR_FROM_STR_STATIC("attr"), mp_obj_new_int(42)); /* printf("bytes:\n"); printf(" total %d\n", m_get_total_bytes_allocated()); printf(" cur %d\n", m_get_current_bytes_allocated()); printf(" peak %d\n", m_get_peak_bytes_allocated()); */ const int NOTHING_EXECUTED = -2; int ret = NOTHING_EXECUTED; bool inspect = false; for (int a = 1; a < argc; a++) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-i") == 0) { inspect = true; } else if (strcmp(argv[a], "-c") == 0) { if (a + 1 >= argc) { return usage(argv); } ret = do_str(argv[a + 1]); if (ret & FORCED_EXIT) { break; } a += 1; } else if (strcmp(argv[a], "-m") == 0) { if (a + 1 >= argc) { return usage(argv); } mp_obj_t import_args[4]; import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1])); import_args[1] = import_args[2] = mp_const_none; // Ask __import__ to handle imported module specially - set its __name__ // to __main__, and also return this leaf module, not top-level package // containing it. import_args[3] = mp_const_false; // TODO: https://docs.python.org/3/using/cmdline.html#cmdoption-m : // "the first element of sys.argv will be the full path to // the module file (while the module file is being located, // the first element will be set to "-m")." set_sys_argv(argv, argc, a + 1); mp_obj_t mod; nlr_buf_t nlr; bool subpkg_tried = false; reimport: if (nlr_push(&nlr) == 0) { mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); nlr_pop(); } else { // uncaught exception return handle_uncaught_exception(nlr.ret_val) & 0xff; } if (mp_obj_is_package(mod) && !subpkg_tried) { subpkg_tried = true; vstr_t vstr; int len = strlen(argv[a + 1]); vstr_init(&vstr, len + sizeof(".__main__")); vstr_add_strn(&vstr, argv[a + 1], len); vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1); import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); goto reimport; } ret = 0; break; } else if (strcmp(argv[a], "-X") == 0) { a += 1; #if MICROPY_DEBUG_PRINTERS } else if (strcmp(argv[a], "-v") == 0) { mp_verbose_flag++; #endif } else if (strncmp(argv[a], "-O", 2) == 0) { if (unichar_isdigit(argv[a][2])) { MP_STATE_VM(mp_optimise_value) = argv[a][2] & 0xf; } else { MP_STATE_VM(mp_optimise_value) = 0; for (char *p = argv[a] + 1; *p && *p == 'O'; p++, MP_STATE_VM(mp_optimise_value)++); } } else { return usage(argv); } } else { char *pathbuf = malloc(PATH_MAX); char *basedir = realpath(argv[a], pathbuf); if (basedir == NULL) { mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], argv[a], errno, strerror(errno)); // CPython exits with 2 in such case ret = 2; break; } // Set base dir of the script as first entry in sys.path char *p = strrchr(basedir, '/'); path_items[0] = mp_obj_new_str_via_qstr(basedir, p - basedir); free(pathbuf); set_sys_argv(argv, argc, a); ret = do_file(argv[a]); break; } } if (ret == NOTHING_EXECUTED || inspect) { if (isatty(0)) { prompt_read_history(); ret = do_repl(); prompt_write_history(); } else { ret = execute_from_lexer(LEX_SRC_STDIN, NULL, MP_PARSE_FILE_INPUT, false); } } #if MICROPY_PY_SYS_SETTRACE MP_STATE_THREAD(prof_trace_callback) = MP_OBJ_NULL; #endif #if MICROPY_PY_SYS_ATEXIT // Beware, the sys.settrace callback should be disabled before running sys.atexit. if (mp_obj_is_callable(MP_STATE_VM(sys_exitfunc))) { mp_call_function_0(MP_STATE_VM(sys_exitfunc)); } #endif #if MICROPY_PY_MICROPYTHON_MEM_INFO if (mp_verbose_flag) { mp_micropython_mem_info(0, NULL); } #endif #if MICROPY_PY_THREAD mp_thread_deinit(); #endif #if defined(MICROPY_UNIX_COVERAGE) gc_sweep_all(); #endif mp_deinit(); #if MICROPY_ENABLE_GC && !defined(NDEBUG) // We don't really need to free memory since we are about to exit the // process, but doing so helps to find memory leaks. free(heap); #endif //printf("total bytes = %d\n", m_get_total_bytes_allocated()); return ret & 0xff; } #if !MICROPY_VFS uint mp_import_stat(const char *path) { struct stat st; if (stat(path, &st) == 0) { if (S_ISDIR(st.st_mode)) { return MP_IMPORT_STAT_DIR; } else if (S_ISREG(st.st_mode)) { return MP_IMPORT_STAT_FILE; } } return MP_IMPORT_STAT_NO_EXIST; } #endif void nlr_jump_fail(void *val) { printf("FATAL: uncaught NLR %p\n", val); exit(1); } micropython-1.12/ports/unix/manifest.py000066400000000000000000000001521357706137100203320ustar00rootroot00000000000000freeze_as_mpy('$(MPY_DIR)/tools', 'upip.py') freeze_as_mpy('$(MPY_DIR)/tools', 'upip_utarfile.py', opt=3) micropython-1.12/ports/unix/manifest_coverage.py000066400000000000000000000001021357706137100222000ustar00rootroot00000000000000freeze_as_str('coverage-frzstr') freeze_as_mpy('coverage-frzmpy') micropython-1.12/ports/unix/modffi.c000066400000000000000000000404441357706137100175720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include "py/runtime.h" #include "py/binary.h" #include "py/mperrno.h" /* * modffi uses character codes to encode a value type, based on "struct" * module type codes, with some extensions and overridings. * * Extra/overridden typecodes: * v - void, can be used only as return type * P - const void*, pointer to read-only memory * p - void*, meaning pointer to a writable memory (note that this * clashes with struct's "p" as "Pascal string"). * s - as argument, the same as "p", as return value, causes string * to be allocated and returned, instead of pointer value. * O - mp_obj_t, passed as is (mostly useful as a callback param) * * TODO: * C - callback function * * Note: all constraint specified by typecode can be not enforced at this time, * but may be later. */ typedef struct _mp_obj_opaque_t { mp_obj_base_t base; void *val; } mp_obj_opaque_t; typedef struct _mp_obj_ffimod_t { mp_obj_base_t base; void *handle; } mp_obj_ffimod_t; typedef struct _mp_obj_ffivar_t { mp_obj_base_t base; void *var; char type; // ffi_type *type; } mp_obj_ffivar_t; typedef struct _mp_obj_ffifunc_t { mp_obj_base_t base; void *func; char rettype; const char *argtypes; ffi_cif cif; ffi_type *params[]; } mp_obj_ffifunc_t; typedef struct _mp_obj_fficallback_t { mp_obj_base_t base; void *func; ffi_closure *clo; char rettype; ffi_cif cif; ffi_type *params[]; } mp_obj_fficallback_t; //STATIC const mp_obj_type_t opaque_type; STATIC const mp_obj_type_t ffimod_type; STATIC const mp_obj_type_t ffifunc_type; STATIC const mp_obj_type_t fficallback_type; STATIC const mp_obj_type_t ffivar_type; STATIC ffi_type *char2ffi_type(char c) { switch (c) { case 'b': return &ffi_type_schar; case 'B': return &ffi_type_uchar; case 'h': return &ffi_type_sshort; case 'H': return &ffi_type_ushort; case 'i': return &ffi_type_sint; case 'I': return &ffi_type_uint; case 'l': return &ffi_type_slong; case 'L': return &ffi_type_ulong; case 'q': return &ffi_type_sint64; case 'Q': return &ffi_type_uint64; #if MICROPY_PY_BUILTINS_FLOAT case 'f': return &ffi_type_float; case 'd': return &ffi_type_double; #endif case 'O': // mp_obj_t case 'C': // (*)() case 'P': // const void* case 'p': // void* case 's': return &ffi_type_pointer; case 'v': return &ffi_type_void; default: return NULL; } } STATIC ffi_type *get_ffi_type(mp_obj_t o_in) { if (mp_obj_is_str(o_in)) { const char *s = mp_obj_str_get_str(o_in); ffi_type *t = char2ffi_type(*s); if (t != NULL) { return t; } } // TODO: Support actual libffi type objects mp_raise_TypeError("Unknown type"); } STATIC mp_obj_t return_ffi_value(ffi_arg val, char type) { switch (type) { case 's': { const char *s = (const char *)(intptr_t)val; if (!s) { return mp_const_none; } return mp_obj_new_str(s, strlen(s)); } case 'v': return mp_const_none; #if MICROPY_PY_BUILTINS_FLOAT case 'f': { union { ffi_arg ffi; float flt; } val_union = { .ffi = val }; return mp_obj_new_float(val_union.flt); } case 'd': { double *p = (double*)&val; return mp_obj_new_float(*p); } #endif case 'O': return (mp_obj_t)(intptr_t)val; default: return mp_obj_new_int(val); } } // FFI module STATIC void ffimod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->handle); } STATIC mp_obj_t ffimod_close(mp_obj_t self_in) { mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); dlclose(self->handle); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(ffimod_close_obj, ffimod_close); STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in) { const char *rettype = mp_obj_str_get_str(rettype_in); const char *argtypes = mp_obj_str_get_str(argtypes_in); mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(argtypes_in)); mp_obj_ffifunc_t *o = m_new_obj_var(mp_obj_ffifunc_t, ffi_type*, nparams); o->base.type = &ffifunc_type; o->func = func; o->rettype = *rettype; o->argtypes = argtypes; mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(argtypes_in, &iter_buf); mp_obj_t item; int i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { o->params[i++] = get_ffi_type(item); } int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); if (res != FFI_OK) { mp_raise_ValueError("Error in ffi_prep_cif"); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t ffimod_func(size_t n_args, const mp_obj_t *args) { (void)n_args; // always 4 mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(args[0]); const char *symname = mp_obj_str_get_str(args[2]); void *sym = dlsym(self->handle, symname); if (sym == NULL) { mp_raise_OSError(MP_ENOENT); } return make_func(args[1], sym, args[3]); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ffimod_func_obj, 4, 4, ffimod_func); STATIC mp_obj_t mod_ffi_func(mp_obj_t rettype, mp_obj_t addr_in, mp_obj_t argtypes) { void *addr = (void*)MP_OBJ_TO_PTR(mp_obj_int_get_truncated(addr_in)); return make_func(rettype, addr, argtypes); } MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_func_obj, mod_ffi_func); STATIC void call_py_func(ffi_cif *cif, void *ret, void** args, void *func) { mp_obj_t pyargs[cif->nargs]; for (uint i = 0; i < cif->nargs; i++) { pyargs[i] = mp_obj_new_int(*(mp_int_t*)args[i]); } mp_obj_t res = mp_call_function_n_kw(MP_OBJ_FROM_PTR(func), cif->nargs, 0, pyargs); if (res != mp_const_none) { *(ffi_arg*)ret = mp_obj_int_get_truncated(res); } } STATIC mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t paramtypes_in) { const char *rettype = mp_obj_str_get_str(rettype_in); mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(paramtypes_in)); mp_obj_fficallback_t *o = m_new_obj_var(mp_obj_fficallback_t, ffi_type*, nparams); o->base.type = &fficallback_type; o->clo = ffi_closure_alloc(sizeof(ffi_closure), &o->func); o->rettype = *rettype; mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(paramtypes_in, &iter_buf); mp_obj_t item; int i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { o->params[i++] = get_ffi_type(item); } int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); if (res != FFI_OK) { mp_raise_ValueError("Error in ffi_prep_cif"); } res = ffi_prep_closure_loc(o->clo, &o->cif, call_py_func, MP_OBJ_TO_PTR(func_in), o->func); if (res != FFI_OK) { mp_raise_ValueError("ffi_prep_closure_loc"); } return MP_OBJ_FROM_PTR(o); } MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_callback_obj, mod_ffi_callback); STATIC mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symname_in) { mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); const char *rettype = mp_obj_str_get_str(vartype_in); const char *symname = mp_obj_str_get_str(symname_in); void *sym = dlsym(self->handle, symname); if (sym == NULL) { mp_raise_OSError(MP_ENOENT); } mp_obj_ffivar_t *o = m_new_obj(mp_obj_ffivar_t); o->base.type = &ffivar_type; o->var = sym; o->type = *rettype; return MP_OBJ_FROM_PTR(o); } MP_DEFINE_CONST_FUN_OBJ_3(ffimod_var_obj, ffimod_var); STATIC mp_obj_t ffimod_addr(mp_obj_t self_in, mp_obj_t symname_in) { mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); const char *symname = mp_obj_str_get_str(symname_in); void *sym = dlsym(self->handle, symname); if (sym == NULL) { mp_raise_OSError(MP_ENOENT); } return mp_obj_new_int((uintptr_t)sym); } MP_DEFINE_CONST_FUN_OBJ_2(ffimod_addr_obj, ffimod_addr); STATIC mp_obj_t ffimod_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)n_args; (void)n_kw; const char *fname = NULL; if (args[0] != mp_const_none) { fname = mp_obj_str_get_str(args[0]); } void *mod = dlopen(fname, RTLD_NOW | RTLD_LOCAL); if (mod == NULL) { mp_raise_OSError(errno); } mp_obj_ffimod_t *o = m_new_obj(mp_obj_ffimod_t); o->base.type = type; o->handle = mod; return MP_OBJ_FROM_PTR(o); } STATIC const mp_rom_map_elem_t ffimod_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_func), MP_ROM_PTR(&ffimod_func_obj) }, { MP_ROM_QSTR(MP_QSTR_var), MP_ROM_PTR(&ffimod_var_obj) }, { MP_ROM_QSTR(MP_QSTR_addr), MP_ROM_PTR(&ffimod_addr_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&ffimod_close_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ffimod_locals_dict, ffimod_locals_dict_table); STATIC const mp_obj_type_t ffimod_type = { { &mp_type_type }, .name = MP_QSTR_ffimod, .print = ffimod_print, .make_new = ffimod_make_new, .locals_dict = (mp_obj_dict_t*)&ffimod_locals_dict, }; // FFI function STATIC void ffifunc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->func); } STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)n_kw; mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in); assert(n_kw == 0); assert(n_args == self->cif.nargs); ffi_arg values[n_args]; void *valueptrs[n_args]; const char *argtype = self->argtypes; for (uint i = 0; i < n_args; i++, argtype++) { mp_obj_t a = args[i]; if (*argtype == 'O') { values[i] = (ffi_arg)(intptr_t)a; #if MICROPY_PY_BUILTINS_FLOAT } else if (*argtype == 'f') { float *p = (float*)&values[i]; *p = mp_obj_get_float(a); } else if (*argtype == 'd') { double *p = (double*)&values[i]; *p = mp_obj_get_float(a); #endif } else if (a == mp_const_none) { values[i] = 0; } else if (mp_obj_is_int(a)) { values[i] = mp_obj_int_get_truncated(a); } else if (mp_obj_is_str(a)) { const char *s = mp_obj_str_get_str(a); values[i] = (ffi_arg)(intptr_t)s; } else if (((mp_obj_base_t*)MP_OBJ_TO_PTR(a))->type->buffer_p.get_buffer != NULL) { mp_obj_base_t *o = (mp_obj_base_t*)MP_OBJ_TO_PTR(a); mp_buffer_info_t bufinfo; int ret = o->type->buffer_p.get_buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? if (ret != 0) { goto error; } values[i] = (ffi_arg)(intptr_t)bufinfo.buf; } else if (mp_obj_is_type(a, &fficallback_type)) { mp_obj_fficallback_t *p = MP_OBJ_TO_PTR(a); values[i] = (ffi_arg)(intptr_t)p->func; } else { goto error; } valueptrs[i] = &values[i]; } // If ffi_arg is not big enough to hold a double, then we must pass along a // pointer to a memory location of the correct size. // TODO check if this needs to be done for other types which don't fit into // ffi_arg. #if MICROPY_PY_BUILTINS_FLOAT if (sizeof(ffi_arg) == 4 && self->rettype == 'd') { double retval; ffi_call(&self->cif, self->func, &retval, valueptrs); return mp_obj_new_float(retval); } else #endif { ffi_arg retval; ffi_call(&self->cif, self->func, &retval, valueptrs); return return_ffi_value(retval, self->rettype); } error: mp_raise_TypeError("Don't know how to pass object to native function"); } STATIC const mp_obj_type_t ffifunc_type = { { &mp_type_type }, .name = MP_QSTR_ffifunc, .print = ffifunc_print, .call = ffifunc_call, }; // FFI callback for Python function STATIC void fficallback_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_fficallback_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->func); } STATIC const mp_obj_type_t fficallback_type = { { &mp_type_type }, .name = MP_QSTR_fficallback, .print = fficallback_print, }; // FFI variable STATIC void ffivar_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); // Variable value printed as cast to int mp_printf(print, "", self->var, *(int*)self->var); } STATIC mp_obj_t ffivar_get(mp_obj_t self_in) { mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); return mp_binary_get_val_array(self->type, self->var, 0); } MP_DEFINE_CONST_FUN_OBJ_1(ffivar_get_obj, ffivar_get); STATIC mp_obj_t ffivar_set(mp_obj_t self_in, mp_obj_t val_in) { mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); mp_binary_set_val_array(self->type, self->var, 0, val_in); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(ffivar_set_obj, ffivar_set); STATIC const mp_rom_map_elem_t ffivar_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&ffivar_get_obj) }, { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&ffivar_set_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ffivar_locals_dict, ffivar_locals_dict_table); STATIC const mp_obj_type_t ffivar_type = { { &mp_type_type }, .name = MP_QSTR_ffivar, .print = ffivar_print, .locals_dict = (mp_obj_dict_t*)&ffivar_locals_dict, }; // Generic opaque storage object (unused) /* STATIC const mp_obj_type_t opaque_type = { { &mp_type_type }, .name = MP_QSTR_opaqueval, // .print = opaque_print, }; */ STATIC mp_obj_t mod_ffi_open(size_t n_args, const mp_obj_t *args) { return ffimod_make_new(&ffimod_type, n_args, 0, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_ffi_open_obj, 1, 2, mod_ffi_open); STATIC mp_obj_t mod_ffi_as_bytearray(mp_obj_t ptr, mp_obj_t size) { return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void*)(uintptr_t)mp_obj_int_get_truncated(ptr)); } MP_DEFINE_CONST_FUN_OBJ_2(mod_ffi_as_bytearray_obj, mod_ffi_as_bytearray); STATIC const mp_rom_map_elem_t mp_module_ffi_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ffi) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_ffi_open_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&mod_ffi_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_func), MP_ROM_PTR(&mod_ffi_func_obj) }, { MP_ROM_QSTR(MP_QSTR_as_bytearray), MP_ROM_PTR(&mod_ffi_as_bytearray_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_ffi_globals, mp_module_ffi_globals_table); const mp_obj_module_t mp_module_ffi = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_ffi_globals, }; micropython-1.12/ports/unix/modjni.c000066400000000000000000000563501357706137100176110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/runtime.h" #include "py/binary.h" #include #define JJ(call, ...) (*env)->call(env, __VA_ARGS__) #define JJ1(call) (*env)->call(env) #define MATCH(s, static) (!strncmp(s, static, sizeof(static) - 1)) static JavaVM *jvm; static JNIEnv *env; static jclass Class_class; static jclass String_class; static jmethodID Class_getName_mid; static jmethodID Class_getField_mid; static jmethodID Class_getMethods_mid; static jmethodID Class_getConstructors_mid; static jmethodID Method_getName_mid; static jmethodID Object_toString_mid; static jclass List_class; static jmethodID List_get_mid; static jmethodID List_set_mid; static jmethodID List_size_mid; static jclass IndexException_class; STATIC const mp_obj_type_t jobject_type; STATIC const mp_obj_type_t jmethod_type; STATIC mp_obj_t new_jobject(jobject jo); STATIC mp_obj_t new_jclass(jclass jc); STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args); STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out); typedef struct _mp_obj_jclass_t { mp_obj_base_t base; jclass cls; } mp_obj_jclass_t; typedef struct _mp_obj_jobject_t { mp_obj_base_t base; jobject obj; } mp_obj_jobject_t; typedef struct _mp_obj_jmethod_t { mp_obj_base_t base; jobject obj; jmethodID meth; qstr name; bool is_static; } mp_obj_jmethod_t; // Utility functions STATIC bool is_object_type(const char *jtypesig) { while (*jtypesig != ' ' && *jtypesig) { if (*jtypesig == '.') { return true; } jtypesig++; } return false; } STATIC void check_exception(void) { jobject exc = JJ1(ExceptionOccurred); if (exc) { //JJ1(ExceptionDescribe); mp_obj_t py_e = new_jobject(exc); JJ1(ExceptionClear); if (JJ(IsInstanceOf, exc, IndexException_class)) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, py_e)); } nlr_raise(mp_obj_new_exception_arg1(&mp_type_Exception, py_e)); } } STATIC void print_jobject(const mp_print_t *print, jobject obj) { jobject str_o = JJ(CallObjectMethod, obj, Object_toString_mid); const char *str = JJ(GetStringUTFChars, str_o, NULL); mp_printf(print, str); JJ(ReleaseStringUTFChars, str_o, str); } // jclass STATIC void jclass_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_jclass_t *self = MP_OBJ_TO_PTR(self_in); if (kind == PRINT_REPR) { mp_printf(print, "cls); } print_jobject(print, self->cls); if (kind == PRINT_REPR) { mp_printf(print, "\">"); } } STATIC void jclass_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_jclass_t *self = MP_OBJ_TO_PTR(self_in); const char *attr = qstr_str(attr_in); jstring field_name = JJ(NewStringUTF, attr); jobject field = JJ(CallObjectMethod, self->cls, Class_getField_mid, field_name); if (!JJ1(ExceptionCheck)) { jfieldID field_id = JJ(FromReflectedField, field); jobject obj = JJ(GetStaticObjectField, self->cls, field_id); dest[0] = new_jobject(obj); return; } //JJ1(ExceptionDescribe); JJ1(ExceptionClear); mp_obj_jmethod_t *o = m_new_obj(mp_obj_jmethod_t); o->base.type = &jmethod_type; o->name = attr_in; o->meth = NULL; o->obj = self->cls; o->is_static = true; dest[0] = MP_OBJ_FROM_PTR(o); } } STATIC mp_obj_t jclass_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { if (n_kw != 0) { mp_raise_TypeError("kwargs not supported"); } mp_obj_jclass_t *self = MP_OBJ_TO_PTR(self_in); jarray methods = JJ(CallObjectMethod, self->cls, Class_getConstructors_mid); return call_method(self->cls, NULL, methods, true, n_args, args); } STATIC const mp_rom_map_elem_t jclass_locals_dict_table[] = { // { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&ffivar_get_obj) }, // { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&ffivar_set_obj) }, }; STATIC MP_DEFINE_CONST_DICT(jclass_locals_dict, jclass_locals_dict_table); STATIC const mp_obj_type_t jclass_type = { { &mp_type_type }, .name = MP_QSTR_jclass, .print = jclass_print, .attr = jclass_attr, .call = jclass_call, .locals_dict = (mp_obj_dict_t*)&jclass_locals_dict, }; STATIC mp_obj_t new_jclass(jclass jc) { mp_obj_jclass_t *o = m_new_obj(mp_obj_jclass_t); o->base.type = &jclass_type; o->cls = jc; return MP_OBJ_FROM_PTR(o); } // jobject STATIC void jobject_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in); if (kind == PRINT_REPR) { mp_printf(print, "obj); } print_jobject(print, self->obj); if (kind == PRINT_REPR) { mp_printf(print, "\">"); } } STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in); const char *attr = qstr_str(attr_in); jclass obj_class = JJ(GetObjectClass, self->obj); jstring field_name = JJ(NewStringUTF, attr); jobject field = JJ(CallObjectMethod, obj_class, Class_getField_mid, field_name); JJ(DeleteLocalRef, field_name); JJ(DeleteLocalRef, obj_class); if (!JJ1(ExceptionCheck)) { jfieldID field_id = JJ(FromReflectedField, field); JJ(DeleteLocalRef, field); jobject obj = JJ(GetObjectField, self->obj, field_id); dest[0] = new_jobject(obj); return; } //JJ1(ExceptionDescribe); JJ1(ExceptionClear); mp_obj_jmethod_t *o = m_new_obj(mp_obj_jmethod_t); o->base.type = &jmethod_type; o->name = attr_in; o->meth = NULL; o->obj = self->obj; o->is_static = false; dest[0] = MP_OBJ_FROM_PTR(o); } } STATIC void get_jclass_name(jobject obj, char *buf) { jclass obj_class = JJ(GetObjectClass, obj); jstring name = JJ(CallObjectMethod, obj_class, Class_getName_mid); jint len = JJ(GetStringLength, name); JJ(GetStringUTFRegion, name, 0, len, buf); check_exception(); } STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t idx = mp_obj_get_int(index); char class_name[64]; get_jclass_name(self->obj, class_name); //printf("class: %s\n", class_name); if (class_name[0] == '[') { if (class_name[1] == 'L' || class_name[1] == '[') { if (value == MP_OBJ_NULL) { // delete assert(0); } else if (value == MP_OBJ_SENTINEL) { // load jobject el = JJ(GetObjectArrayElement, self->obj, idx); return new_jobject(el); } else { // store jvalue jval; const char *t = class_name + 1; py2jvalue(&t, value, &jval); JJ(SetObjectArrayElement, self->obj, idx, jval.l); return mp_const_none; } } mp_raise_NotImplementedError(NULL); } if (!JJ(IsInstanceOf, self->obj, List_class)) { return MP_OBJ_NULL; } if (value == MP_OBJ_NULL) { // delete assert(0); } else if (value == MP_OBJ_SENTINEL) { // load jobject el = JJ(CallObjectMethod, self->obj, List_get_mid, idx); check_exception(); return new_jobject(el); } else { // store assert(0); } return MP_OBJ_NULL; } STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: case MP_UNARY_OP_LEN: { jint len = JJ(CallIntMethod, self->obj, List_size_mid); if (op == MP_UNARY_OP_BOOL) { return mp_obj_new_bool(len != 0); } return MP_OBJ_NEW_SMALL_INT(len); } default: return MP_OBJ_NULL; // op not supported } } // TODO: subscr_load_adaptor & subscr_getiter convenience functions // should be moved to common location for reuse. STATIC mp_obj_t subscr_load_adaptor(mp_obj_t self_in, mp_obj_t index_in) { return mp_obj_subscr(self_in, index_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(subscr_load_adaptor_obj, subscr_load_adaptor); // .getiter special method which returns iterator which works in terms // of object subscription. STATIC mp_obj_t subscr_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { mp_obj_t dest[2] = {MP_OBJ_FROM_PTR(&subscr_load_adaptor_obj), self_in}; return mp_obj_new_getitem_iter(dest, iter_buf); } STATIC const mp_obj_type_t jobject_type = { { &mp_type_type }, .name = MP_QSTR_jobject, .print = jobject_print, .unary_op = jobject_unary_op, .attr = jobject_attr, .subscr = jobject_subscr, .getiter = subscr_getiter, // .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, }; STATIC mp_obj_t new_jobject(jobject jo) { if (jo == NULL) { return mp_const_none; } else if (JJ(IsInstanceOf, jo, String_class)) { const char *s = JJ(GetStringUTFChars, jo, NULL); mp_obj_t ret = mp_obj_new_str(s, strlen(s)); JJ(ReleaseStringUTFChars, jo, s); return ret; } else if (JJ(IsInstanceOf, jo, Class_class)) { return new_jclass(jo); } else { mp_obj_jobject_t *o = m_new_obj(mp_obj_jobject_t); o->base.type = &jobject_type; o->obj = jo; return MP_OBJ_FROM_PTR(o); } } // jmethod STATIC void jmethod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_jmethod_t *self = MP_OBJ_TO_PTR(self_in); // Variable value printed as cast to int mp_printf(print, "", qstr_str(self->name)); } #define IMATCH(s, static) ((!strncmp(s, static, sizeof(static) - 1)) && (s += sizeof(static) - 1)) #define CHECK_TYPE(java_type_name) \ if (strncmp(arg_type, java_type_name, sizeof(java_type_name) - 1) != 0) { \ return false; \ } \ arg_type += sizeof(java_type_name) - 1; STATIC const char *strprev(const char *s, char c) { while (*s != c) { s--; } return s; } STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) { const char *arg_type = *jtypesig; mp_obj_type_t *type = mp_obj_get_type(arg); if (type == &mp_type_str) { if (IMATCH(arg_type, "java.lang.String") || IMATCH(arg_type, "java.lang.Object")) { out->l = JJ(NewStringUTF, mp_obj_str_get_str(arg)); } else { return false; } } else if (type == &mp_type_int) { if (IMATCH(arg_type, "int") || IMATCH(arg_type, "long")) { // TODO: Java long is 64-bit actually out->j = mp_obj_get_int(arg); } else { return false; } } else if (type == &jobject_type) { bool is_object = false; const char *expected_type = arg_type; while (1) { if (isalpha(*arg_type)) { } else if (*arg_type == '.') { is_object = true; } else { break; } arg_type++; } if (!is_object) { return false; } mp_obj_jobject_t *jo = MP_OBJ_TO_PTR(arg); if (!MATCH(expected_type, "java.lang.Object")) { char class_name[64]; get_jclass_name(jo->obj, class_name); //printf("Arg class: %s\n", class_name); if (strcmp(class_name, expected_type) != 0) { return false; } } out->l = jo->obj; } else if (type == &mp_type_bool) { if (IMATCH(arg_type, "boolean")) { out->z = arg == mp_const_true; } else { return false; } } else if (arg == mp_const_none) { //printf("TODO: Check java arg type!!\n"); while (isalpha(*arg_type) || *arg_type == '.') { arg_type++; } out->l = NULL; } else { mp_raise_TypeError("arg type not supported"); } *jtypesig = arg_type; return true; } #if 0 // jvalue is known to be union of jobject and friends. And yet from C's // perspective, it's aggregate object which may require passing via stack // instead of registers. Work that around by passing jobject and typecasting // it. STATIC mp_obj_t jvalue2py(const char *jtypesig, jobject arg) { if (arg == NULL || MATCH(jtypesig, "void")) { return mp_const_none; } else if (MATCH(jtypesig, "boolean")) { return mp_obj_new_bool((bool)arg); } else if (MATCH(jtypesig, "int")) { return mp_obj_new_int((mp_int_t)arg); } else if (is_object_type(jtypesig)) { // Non-primitive, object type return new_jobject(arg); } printf("Unknown return type: %s\n", jtypesig); return MP_OBJ_NULL; } #endif STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args) { jvalue jargs[n_args]; // printf("methods=%p\n", methods); jsize num_methods = JJ(GetArrayLength, methods); for (int i = 0; i < num_methods; i++) { jobject meth = JJ(GetObjectArrayElement, methods, i); jobject name_o = JJ(CallObjectMethod, meth, Object_toString_mid); const char *decl = JJ(GetStringUTFChars, name_o, NULL); const char *arg_types = strchr(decl, '(') + 1; //const char *arg_types_end = strchr(arg_types, ')'); // printf("method[%d]=%p %s\n", i, meth, decl); const char *meth_name = NULL; const char *ret_type = NULL; if (!is_constr) { meth_name = strprev(arg_types, '.') + 1; ret_type = strprev(meth_name, ' ') - 1; ret_type = strprev(ret_type, ' ') + 1; int name_len = strlen(name); if (strncmp(name, meth_name, name_len/*arg_types - meth_name - 1*/) || meth_name[name_len] != '('/*(*/) { goto next_method; } } // printf("method[%d]=%p %s\n", i, meth, decl); // printf("!!!%s\n", arg_types); // printf("name=%p meth_name=%s\n", name, meth_name); bool found = true; for (size_t j = 0; j < n_args && *arg_types != ')'; j++) { if (!py2jvalue(&arg_types, args[j], &jargs[j])) { goto next_method; } if (*arg_types == ',') { arg_types++; } } if (*arg_types != ')') { goto next_method; } if (found) { // printf("found!\n"); jmethodID method_id = JJ(FromReflectedMethod, meth); if (is_constr) { JJ(ReleaseStringUTFChars, name_o, decl); jobject res = JJ(NewObjectA, obj, method_id, jargs); return new_jobject(res); } else { mp_obj_t ret; if (MATCH(ret_type, "void")) { JJ(CallVoidMethodA, obj, method_id, jargs); check_exception(); ret = mp_const_none; } else if (MATCH(ret_type, "int")) { jint res = JJ(CallIntMethodA, obj, method_id, jargs); check_exception(); ret = mp_obj_new_int(res); } else if (MATCH(ret_type, "boolean")) { jboolean res = JJ(CallBooleanMethodA, obj, method_id, jargs); check_exception(); ret = mp_obj_new_bool(res); } else if (is_object_type(ret_type)) { jobject res = JJ(CallObjectMethodA, obj, method_id, jargs); check_exception(); ret = new_jobject(res); } else { JJ(ReleaseStringUTFChars, name_o, decl); mp_raise_TypeError("cannot handle return type"); } JJ(ReleaseStringUTFChars, name_o, decl); JJ(DeleteLocalRef, name_o); JJ(DeleteLocalRef, meth); return ret; } } next_method: JJ(ReleaseStringUTFChars, name_o, decl); JJ(DeleteLocalRef, name_o); JJ(DeleteLocalRef, meth); } mp_raise_TypeError("method not found"); } STATIC mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { if (n_kw != 0) { mp_raise_TypeError("kwargs not supported"); } mp_obj_jmethod_t *self = MP_OBJ_TO_PTR(self_in); const char *name = qstr_str(self->name); // jstring meth_name = JJ(NewStringUTF, name); jclass obj_class = self->obj; if (!self->is_static) { obj_class = JJ(GetObjectClass, self->obj); } jarray methods = JJ(CallObjectMethod, obj_class, Class_getMethods_mid); return call_method(self->obj, name, methods, false, n_args, args); } STATIC const mp_obj_type_t jmethod_type = { { &mp_type_type }, .name = MP_QSTR_jmethod, .print = jmethod_print, .call = jmethod_call, // .attr = jobject_attr, // .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, }; #ifdef __ANDROID__ #define LIBJVM_SO "libdvm.so" #else #define LIBJVM_SO "libjvm.so" #endif STATIC void create_jvm(void) { JavaVMInitArgs args; JavaVMOption options; options.optionString = "-Djava.class.path=."; args.version = JNI_VERSION_1_6; args.nOptions = 1; args.options = &options; args.ignoreUnrecognized = 0; if (env) { return; } void *libjvm = dlopen(LIBJVM_SO, RTLD_NOW | RTLD_GLOBAL); if (!libjvm) { mp_raise_msg(&mp_type_OSError, "unable to load libjvm.so, use LD_LIBRARY_PATH"); } int (*_JNI_CreateJavaVM)(void*, void**, void*) = dlsym(libjvm, "JNI_CreateJavaVM"); int st = _JNI_CreateJavaVM(&jvm, (void**)&env, &args); if (st < 0 || !env) { mp_raise_msg(&mp_type_OSError, "unable to create JVM"); } Class_class = JJ(FindClass, "java/lang/Class"); jclass method_class = JJ(FindClass, "java/lang/reflect/Method"); String_class = JJ(FindClass, "java/lang/String"); jclass Object_class = JJ(FindClass, "java/lang/Object"); Object_toString_mid = JJ(GetMethodID, Object_class, "toString", "()Ljava/lang/String;"); Class_getName_mid = (*env)->GetMethodID(env, Class_class, "getName", "()Ljava/lang/String;"); Class_getField_mid = (*env)->GetMethodID(env, Class_class, "getField", "(Ljava/lang/String;)Ljava/lang/reflect/Field;"); Class_getMethods_mid = (*env)->GetMethodID(env, Class_class, "getMethods", "()[Ljava/lang/reflect/Method;"); Class_getConstructors_mid = (*env)->GetMethodID(env, Class_class, "getConstructors", "()[Ljava/lang/reflect/Constructor;"); Method_getName_mid = (*env)->GetMethodID(env, method_class, "getName", "()Ljava/lang/String;"); List_class = JJ(FindClass, "java/util/List"); List_get_mid = JJ(GetMethodID, List_class, "get", "(I)Ljava/lang/Object;"); List_set_mid = JJ(GetMethodID, List_class, "set", "(ILjava/lang/Object;)Ljava/lang/Object;"); List_size_mid = JJ(GetMethodID, List_class, "size", "()I"); IndexException_class = JJ(FindClass, "java/lang/IndexOutOfBoundsException"); } STATIC mp_obj_t mod_jni_cls(mp_obj_t cls_name_in) { const char *cls_name = mp_obj_str_get_str(cls_name_in); if (!env) { create_jvm(); } jclass cls = JJ(FindClass, cls_name); mp_obj_jclass_t *o = m_new_obj(mp_obj_jclass_t); o->base.type = &jclass_type; o->cls = cls; return MP_OBJ_FROM_PTR(o); } MP_DEFINE_CONST_FUN_OBJ_1(mod_jni_cls_obj, mod_jni_cls); STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { if (!env) { create_jvm(); } mp_int_t size = mp_obj_get_int(size_in); jobject res = NULL; if (mp_obj_is_type(type_in, &jclass_type)) { mp_obj_jclass_t *jcls = MP_OBJ_TO_PTR(type_in); res = JJ(NewObjectArray, size, jcls->cls, NULL); } else if (mp_obj_is_str(type_in)) { const char *type = mp_obj_str_get_str(type_in); switch (*type) { case 'Z': res = JJ(NewBooleanArray, size); break; case 'B': res = JJ(NewByteArray, size); break; case 'C': res = JJ(NewCharArray, size); break; case 'S': res = JJ(NewShortArray, size); break; case 'I': res = JJ(NewIntArray, size); break; case 'J': res = JJ(NewLongArray, size); break; case 'F': res = JJ(NewFloatArray, size); break; case 'D': res = JJ(NewDoubleArray, size); break; } } return new_jobject(res); } MP_DEFINE_CONST_FUN_OBJ_2(mod_jni_array_obj, mod_jni_array); STATIC mp_obj_t mod_jni_env(void) { return mp_obj_new_int((mp_int_t)(uintptr_t)env); } MP_DEFINE_CONST_FUN_OBJ_0(mod_jni_env_obj, mod_jni_env); STATIC const mp_rom_map_elem_t mp_module_jni_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_jni) }, { MP_ROM_QSTR(MP_QSTR_cls), MP_ROM_PTR(&mod_jni_cls_obj) }, { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mod_jni_array_obj) }, { MP_ROM_QSTR(MP_QSTR_env), MP_ROM_PTR(&mod_jni_env_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_jni_globals, mp_module_jni_globals_table); const mp_obj_module_t mp_module_jni = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_jni_globals, }; micropython-1.12/ports/unix/modmachine.c000066400000000000000000000067451357706137100204400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/obj.h" #include "extmod/machine_mem.h" #include "extmod/machine_pinbase.h" #include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" #if MICROPY_PLAT_DEV_MEM #include #include #include #define MICROPY_PAGE_SIZE 4096 #define MICROPY_PAGE_MASK (MICROPY_PAGE_SIZE - 1) #endif #if MICROPY_PY_MACHINE uintptr_t mod_machine_mem_get_addr(mp_obj_t addr_o, uint align) { uintptr_t addr = mp_obj_int_get_truncated(addr_o); if ((addr & (align - 1)) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align)); } #if MICROPY_PLAT_DEV_MEM { // Not thread-safe static int fd; static uintptr_t last_base = (uintptr_t)-1; static uintptr_t map_page; if (!fd) { int _fd = open("/dev/mem", O_RDWR | O_SYNC); if (_fd == -1) { mp_raise_OSError(errno); } fd = _fd; } uintptr_t cur_base = addr & ~MICROPY_PAGE_MASK; if (cur_base != last_base) { map_page = (uintptr_t)mmap(NULL, MICROPY_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, cur_base); last_base = cur_base; } addr = map_page + (addr & MICROPY_PAGE_MASK); } #endif return addr; } STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, #if MICROPY_PY_MACHINE_PULSE { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t mp_module_machine = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; #endif // MICROPY_PY_MACHINE micropython-1.12/ports/unix/modos.c000066400000000000000000000201741357706137100174450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2018 Paul Sokolovsky * Copyright (c) 2014-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include "py/mpconfig.h" #include "py/runtime.h" #include "py/objtuple.h" #include "py/mphal.h" #include "extmod/vfs.h" #include "extmod/misc.h" #ifdef __ANDROID__ #define USE_STATFS 1 #endif STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) { struct stat sb; const char *path = mp_obj_str_get_str(path_in); int res = stat(path, &sb); RAISE_ERRNO(res, errno); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.st_mode); t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.st_ino); t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.st_dev); t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.st_nlink); t->items[4] = MP_OBJ_NEW_SMALL_INT(sb.st_uid); t->items[5] = MP_OBJ_NEW_SMALL_INT(sb.st_gid); t->items[6] = mp_obj_new_int_from_uint(sb.st_size); t->items[7] = MP_OBJ_NEW_SMALL_INT(sb.st_atime); t->items[8] = MP_OBJ_NEW_SMALL_INT(sb.st_mtime); t->items[9] = MP_OBJ_NEW_SMALL_INT(sb.st_ctime); return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_stat_obj, mod_os_stat); #if MICROPY_PY_OS_STATVFS #if USE_STATFS #include #define STRUCT_STATVFS struct statfs #define STATVFS statfs #define F_FAVAIL sb.f_ffree #define F_NAMEMAX sb.f_namelen #define F_FLAG sb.f_flags #else #include #define STRUCT_STATVFS struct statvfs #define STATVFS statvfs #define F_FAVAIL sb.f_favail #define F_NAMEMAX sb.f_namemax #define F_FLAG sb.f_flag #endif STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) { STRUCT_STATVFS sb; const char *path = mp_obj_str_get_str(path_in); int res = STATVFS(path, &sb); RAISE_ERRNO(res, errno); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.f_bsize); t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.f_frsize); t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.f_blocks); t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.f_bfree); t->items[4] = MP_OBJ_NEW_SMALL_INT(sb.f_bavail); t->items[5] = MP_OBJ_NEW_SMALL_INT(sb.f_files); t->items[6] = MP_OBJ_NEW_SMALL_INT(sb.f_ffree); t->items[7] = MP_OBJ_NEW_SMALL_INT(F_FAVAIL); t->items[8] = MP_OBJ_NEW_SMALL_INT(F_FLAG); t->items[9] = MP_OBJ_NEW_SMALL_INT(F_NAMEMAX); return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_statvfs_obj, mod_os_statvfs); #endif STATIC mp_obj_t mod_os_remove(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); // Note that POSIX requires remove() to be able to delete a directory // too (act as rmdir()). This is POSIX extenstion to ANSI C semantics // of that function. But Python remove() follows ANSI C, and explicitly // required to raise exception on attempt to remove a directory. Thus, // call POSIX unlink() here. int r = unlink(path); RAISE_ERRNO(r, errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_remove_obj, mod_os_remove); STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) { const char *cmd = mp_obj_str_get_str(cmd_in); int r = system(cmd); RAISE_ERRNO(r, errno); return MP_OBJ_NEW_SMALL_INT(r); } MP_DEFINE_CONST_FUN_OBJ_1(mod_os_system_obj, mod_os_system); STATIC mp_obj_t mod_os_getenv(mp_obj_t var_in) { const char *s = getenv(mp_obj_str_get_str(var_in)); if (s == NULL) { return mp_const_none; } return mp_obj_new_str(s, strlen(s)); } MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_obj, mod_os_getenv); STATIC mp_obj_t mod_os_mkdir(mp_obj_t path_in) { // TODO: Accept mode param const char *path = mp_obj_str_get_str(path_in); #ifdef _WIN32 int r = mkdir(path); #else int r = mkdir(path, 0777); #endif RAISE_ERRNO(r, errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_mkdir_obj, mod_os_mkdir); typedef struct _mp_obj_listdir_t { mp_obj_base_t base; mp_fun_1_t iternext; DIR *dir; } mp_obj_listdir_t; STATIC mp_obj_t listdir_next(mp_obj_t self_in) { mp_obj_listdir_t *self = MP_OBJ_TO_PTR(self_in); if (self->dir == NULL) { goto done; } struct dirent *dirent = readdir(self->dir); if (dirent == NULL) { closedir(self->dir); self->dir = NULL; done: return MP_OBJ_STOP_ITERATION; } mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); t->items[0] = mp_obj_new_str(dirent->d_name, strlen(dirent->d_name)); #ifdef _DIRENT_HAVE_D_TYPE #ifdef DTTOIF t->items[1] = MP_OBJ_NEW_SMALL_INT(DTTOIF(dirent->d_type)); #else if (dirent->d_type == DT_DIR) { t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); } else if (dirent->d_type == DT_REG) { t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG); } else { t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type); } #endif #else // DT_UNKNOWN should have 0 value on any reasonable system t->items[1] = MP_OBJ_NEW_SMALL_INT(0); #endif #ifdef _DIRENT_HAVE_D_INO t->items[2] = MP_OBJ_NEW_SMALL_INT(dirent->d_ino); #else t->items[2] = MP_OBJ_NEW_SMALL_INT(0); #endif return MP_OBJ_FROM_PTR(t); } STATIC mp_obj_t mod_os_ilistdir(size_t n_args, const mp_obj_t *args) { const char *path = "."; if (n_args > 0) { path = mp_obj_str_get_str(args[0]); } mp_obj_listdir_t *o = m_new_obj(mp_obj_listdir_t); o->base.type = &mp_type_polymorph_iter; o->dir = opendir(path); o->iternext = listdir_next; return MP_OBJ_FROM_PTR(o); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_ilistdir_obj, 0, 1, mod_os_ilistdir); STATIC mp_obj_t mod_os_errno(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return MP_OBJ_NEW_SMALL_INT(errno); } errno = mp_obj_get_int(args[0]); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_errno_obj, 0, 1, mod_os_errno); STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mod_os_errno_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mod_os_stat_obj) }, #if MICROPY_PY_OS_STATVFS { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mod_os_statvfs_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mod_os_system_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mod_os_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mod_os_ilistdir_obj) }, #if MICROPY_PY_OS_DUPTERM { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_os_globals, mp_module_os_globals_table); const mp_obj_module_t mp_module_os = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_os_globals, }; micropython-1.12/ports/unix/modtermios.c000066400000000000000000000127611357706137100205110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/objlist.h" #include "py/runtime.h" #include "py/mphal.h" STATIC mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) { struct termios term; int fd = mp_obj_get_int(fd_in); int res = tcgetattr(fd, &term); RAISE_ERRNO(res, errno); mp_obj_list_t *r = MP_OBJ_TO_PTR(mp_obj_new_list(7, NULL)); r->items[0] = MP_OBJ_NEW_SMALL_INT(term.c_iflag); r->items[1] = MP_OBJ_NEW_SMALL_INT(term.c_oflag); r->items[2] = MP_OBJ_NEW_SMALL_INT(term.c_cflag); r->items[3] = MP_OBJ_NEW_SMALL_INT(term.c_lflag); r->items[4] = MP_OBJ_NEW_SMALL_INT(cfgetispeed(&term)); r->items[5] = MP_OBJ_NEW_SMALL_INT(cfgetospeed(&term)); mp_obj_list_t *cc = MP_OBJ_TO_PTR(mp_obj_new_list(NCCS, NULL)); r->items[6] = MP_OBJ_FROM_PTR(cc); for (int i = 0; i < NCCS; i++) { if (i == VMIN || i == VTIME) { cc->items[i] = MP_OBJ_NEW_SMALL_INT(term.c_cc[i]); } else { // https://docs.python.org/3/library/termios.html says value is *string*, // but no way unicode chars could be there, if c_cc is defined to be a // a "char". But it's type is actually cc_t, which can be anything. // TODO: For now, we still deal with it like that. cc->items[i] = mp_obj_new_bytes((byte*)&term.c_cc[i], 1); } } return MP_OBJ_FROM_PTR(r); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_tcgetattr_obj, mod_termios_tcgetattr); STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t attrs_in) { struct termios term; int fd = mp_obj_get_int(fd_in); int when = mp_obj_get_int(when_in); if (when == 0) { // We don't export TCSANOW and friends to save on code space. Then // common lazy sense says that passing 0 should be godo enough, and // it is e.g. for glibc. But for other libc's it's not, so set just // treat 0 as defauling to TCSANOW. when = TCSANOW; } assert(mp_obj_is_type(attrs_in, &mp_type_list)); mp_obj_list_t *attrs = MP_OBJ_TO_PTR(attrs_in); term.c_iflag = mp_obj_get_int(attrs->items[0]); term.c_oflag = mp_obj_get_int(attrs->items[1]); term.c_cflag = mp_obj_get_int(attrs->items[2]); term.c_lflag = mp_obj_get_int(attrs->items[3]); mp_obj_list_t *cc = MP_OBJ_TO_PTR(attrs->items[6]); for (int i = 0; i < NCCS; i++) { if (i == VMIN || i == VTIME) { term.c_cc[i] = mp_obj_get_int(cc->items[i]); } else { term.c_cc[i] = *mp_obj_str_get_str(cc->items[i]); } } int res = cfsetispeed(&term, mp_obj_get_int(attrs->items[4])); RAISE_ERRNO(res, errno); res = cfsetospeed(&term, mp_obj_get_int(attrs->items[5])); RAISE_ERRNO(res, errno); res = tcsetattr(fd, when, &term); RAISE_ERRNO(res, errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_termios_tcsetattr_obj, mod_termios_tcsetattr); STATIC mp_obj_t mod_termios_setraw(mp_obj_t fd_in) { struct termios term; int fd = mp_obj_get_int(fd_in); int res = tcgetattr(fd, &term); RAISE_ERRNO(res, errno); term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); term.c_oflag = 0; term.c_cflag = (term.c_cflag & ~(CSIZE | PARENB)) | CS8; term.c_lflag = 0; term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; res = tcsetattr(fd, TCSAFLUSH, &term); RAISE_ERRNO(res, errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_setraw_obj, mod_termios_setraw); STATIC const mp_rom_map_elem_t mp_module_termios_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_termios) }, { MP_ROM_QSTR(MP_QSTR_tcgetattr), MP_ROM_PTR(&mod_termios_tcgetattr_obj) }, { MP_ROM_QSTR(MP_QSTR_tcsetattr), MP_ROM_PTR(&mod_termios_tcsetattr_obj) }, { MP_ROM_QSTR(MP_QSTR_setraw), MP_ROM_PTR(&mod_termios_setraw_obj) }, #define C(name) { MP_ROM_QSTR(MP_QSTR_ ## name), MP_ROM_INT(name) } C(TCSANOW), C(B9600), #ifdef B57600 C(B57600), #endif #ifdef B115200 C(B115200), #endif #undef C }; STATIC MP_DEFINE_CONST_DICT(mp_module_termios_globals, mp_module_termios_globals_table); const mp_obj_module_t mp_module_termios = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_termios_globals, }; micropython-1.12/ports/unix/modtime.c000066400000000000000000000147211357706137100177630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2017 Paul Sokolovsky * Copyright (c) 2014-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_UTIME #include #include #include #include #include #include #include "py/runtime.h" #include "py/smallint.h" #include "py/mphal.h" #include "extmod/utime_mphal.h" #ifdef _WIN32 static inline int msec_sleep_tv(struct timeval *tv) { msec_sleep(tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0); return 0; } #define sleep_select(a,b,c,d,e) msec_sleep_tv((e)) #else #define sleep_select select #endif // mingw32 defines CLOCKS_PER_SEC as ((clock_t)) but preprocessor does not handle casts #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) #define MP_REMOVE_BRACKETSA(x) #define MP_REMOVE_BRACKETSB(x) MP_REMOVE_BRACKETSA x #define MP_REMOVE_BRACKETSC(x) MP_REMOVE_BRACKETSB x #define MP_CLOCKS_PER_SEC MP_REMOVE_BRACKETSC(CLOCKS_PER_SEC) #else #define MP_CLOCKS_PER_SEC CLOCKS_PER_SEC #endif #if defined(MP_CLOCKS_PER_SEC) #define CLOCK_DIV (MP_CLOCKS_PER_SEC / 1000.0F) #else #error Unsupported clock() implementation #endif STATIC mp_obj_t mod_time_time(void) { #if MICROPY_PY_BUILTINS_FLOAT struct timeval tv; gettimeofday(&tv, NULL); mp_float_t val = tv.tv_sec + (mp_float_t)tv.tv_usec / 1000000; return mp_obj_new_float(val); #else return mp_obj_new_int((mp_int_t)time(NULL)); #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time); // Note: this is deprecated since CPy3.3, but pystone still uses it. STATIC mp_obj_t mod_time_clock(void) { #if MICROPY_PY_BUILTINS_FLOAT // float cannot represent full range of int32 precisely, so we pre-divide // int to reduce resolution, and then actually do float division hoping // to preserve integer part resolution. return mp_obj_new_float((float)(clock() / 1000) / CLOCK_DIV); #else return mp_obj_new_int((mp_int_t)clock()); #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock); STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { #if MICROPY_PY_BUILTINS_FLOAT struct timeval tv; mp_float_t val = mp_obj_get_float(arg); double ipart; tv.tv_usec = round(modf(val, &ipart) * 1000000); tv.tv_sec = ipart; int res; while (1) { MP_THREAD_GIL_EXIT(); res = sleep_select(0, NULL, NULL, NULL, &tv); MP_THREAD_GIL_ENTER(); #if MICROPY_SELECT_REMAINING_TIME // TODO: This assumes Linux behavior of modifying tv to the remaining // time. if (res != -1 || errno != EINTR) { break; } mp_handle_pending(); //printf("select: EINTR: %ld:%ld\n", tv.tv_sec, tv.tv_usec); #else break; #endif } RAISE_ERRNO(res, errno); #else // TODO: Handle EINTR MP_THREAD_GIL_EXIT(); sleep(mp_obj_get_int(arg)); MP_THREAD_GIL_ENTER(); #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_obj, mod_time_sleep); STATIC mp_obj_t mod_time_localtime(size_t n_args, const mp_obj_t *args) { time_t t; if (n_args == 0) { t = time(NULL); } else { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t val = mp_obj_get_float(args[0]); t = (time_t)MICROPY_FLOAT_C_FUN(trunc)(val); #else t = mp_obj_get_int(args[0]); #endif } struct tm *tm = localtime(&t); mp_obj_t ret = mp_obj_new_tuple(9, NULL); mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(ret); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(tm->tm_year + 1900); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(tm->tm_mon + 1); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(tm->tm_mday); tuple->items[3] = MP_OBJ_NEW_SMALL_INT(tm->tm_hour); tuple->items[4] = MP_OBJ_NEW_SMALL_INT(tm->tm_min); tuple->items[5] = MP_OBJ_NEW_SMALL_INT(tm->tm_sec); int wday = tm->tm_wday - 1; if (wday < 0) { wday = 6; } tuple->items[6] = MP_OBJ_NEW_SMALL_INT(wday); tuple->items[7] = MP_OBJ_NEW_SMALL_INT(tm->tm_yday + 1); tuple->items[8] = MP_OBJ_NEW_SMALL_INT(tm->tm_isdst); return ret; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_localtime_obj, 0, 1, mod_time_localtime); STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_clock), MP_ROM_PTR(&mod_time_clock_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mod_time_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mod_time_time_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&mod_time_localtime_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table); const mp_obj_module_t mp_module_time = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_time_globals, }; #endif // MICROPY_PY_UTIME micropython-1.12/ports/unix/moduos_vfs.c000066400000000000000000000071461357706137100205140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "extmod/vfs.h" #include "extmod/vfs_posix.h" #include "extmod/vfs_fat.h" #include "extmod/vfs_lfs.h" #if MICROPY_VFS // These are defined in modos.c MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_errno_obj); MP_DECLARE_CONST_FUN_OBJ_1(mod_os_getenv_obj); MP_DECLARE_CONST_FUN_OBJ_1(mod_os_system_obj); STATIC const mp_rom_map_elem_t uos_vfs_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos_vfs) }, { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) }, { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mod_os_errno_obj) }, { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, { MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mod_os_system_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename),MP_ROM_PTR(&mp_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove #if MICROPY_PY_OS_DUPTERM { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, #endif #if MICROPY_VFS_POSIX { MP_ROM_QSTR(MP_QSTR_VfsPosix), MP_ROM_PTR(&mp_type_vfs_posix) }, #endif #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif #if MICROPY_VFS_LFS1 { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, #endif #if MICROPY_VFS_LFS2 { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, #endif }; STATIC MP_DEFINE_CONST_DICT(uos_vfs_module_globals, uos_vfs_module_globals_table); const mp_obj_module_t mp_module_uos_vfs = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&uos_vfs_module_globals, }; #endif // MICROPY_VFS micropython-1.12/ports/unix/moduselect.c000066400000000000000000000254451357706137100204760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2015-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_USELECT_POSIX #include #include #include #include "py/runtime.h" #include "py/stream.h" #include "py/obj.h" #include "py/objlist.h" #include "py/objtuple.h" #include "py/mphal.h" #include "fdfile.h" #define DEBUG 0 #if MICROPY_PY_SOCKET extern const mp_obj_type_t mp_type_socket; #endif // Flags for poll() #define FLAG_ONESHOT (1) /// \class Poll - poll class typedef struct _mp_obj_poll_t { mp_obj_base_t base; unsigned short alloc; unsigned short len; struct pollfd *entries; mp_obj_t *obj_map; short iter_cnt; short iter_idx; int flags; // callee-owned tuple mp_obj_t ret_tuple; } mp_obj_poll_t; STATIC int get_fd(mp_obj_t fdlike) { if (mp_obj_is_obj(fdlike)) { const mp_stream_p_t *stream_p = mp_get_stream_raise(fdlike, MP_STREAM_OP_IOCTL); int err; mp_uint_t res = stream_p->ioctl(fdlike, MP_STREAM_GET_FILENO, 0, &err); if (res != MP_STREAM_ERROR) { return res; } } return mp_obj_get_int(fdlike); } /// \method register(obj[, eventmask]) STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); bool is_fd = mp_obj_is_int(args[1]); int fd = get_fd(args[1]); mp_uint_t flags; if (n_args == 3) { flags = mp_obj_get_int(args[2]); } else { flags = POLLIN | POLLOUT; } struct pollfd *free_slot = NULL; struct pollfd *entry = self->entries; for (int i = 0; i < self->len; i++, entry++) { int entry_fd = entry->fd; if (entry_fd == fd) { entry->events = flags; return mp_const_false; } if (entry_fd == -1) { free_slot = entry; } } if (free_slot == NULL) { if (self->len >= self->alloc) { self->entries = m_renew(struct pollfd, self->entries, self->alloc, self->alloc + 4); if (self->obj_map) { self->obj_map = m_renew(mp_obj_t, self->obj_map, self->alloc, self->alloc + 4); } self->alloc += 4; } free_slot = &self->entries[self->len++]; } if (!is_fd) { if (self->obj_map == NULL) { self->obj_map = m_new0(mp_obj_t, self->alloc); } self->obj_map[free_slot - self->entries] = args[1]; } free_slot->fd = fd; free_slot->events = flags; free_slot->revents = 0; return mp_const_true; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); /// \method unregister(obj) STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); struct pollfd *entries = self->entries; int fd = get_fd(obj_in); for (int i = self->len - 1; i >= 0; i--) { if (entries->fd == fd) { entries->fd = -1; if (self->obj_map) { self->obj_map[entries - self->entries] = MP_OBJ_NULL; } break; } entries++; } // TODO raise KeyError if obj didn't exist in map return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister); /// \method modify(obj, eventmask) STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); struct pollfd *entries = self->entries; int fd = get_fd(obj_in); for (int i = self->len - 1; i >= 0; i--) { if (entries->fd == fd) { entries->events = mp_obj_get_int(eventmask_in); return mp_const_none; } entries++; } // obj doesn't exist in poller mp_raise_OSError(MP_ENOENT); } MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); STATIC int poll_poll_internal(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); // work out timeout (it's given already in ms) int timeout = -1; int flags = 0; if (n_args >= 2) { if (args[1] != mp_const_none) { mp_int_t timeout_i = mp_obj_get_int(args[1]); if (timeout_i >= 0) { timeout = timeout_i; } } if (n_args >= 3) { flags = mp_obj_get_int(args[2]); } } self->flags = flags; int n_ready = poll(self->entries, self->len, timeout); RAISE_ERRNO(n_ready, errno); return n_ready; } /// \method poll([timeout]) /// Timeout is in milliseconds. STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { int n_ready = poll_poll_internal(n_args, args); if (n_ready == 0) { return mp_const_empty_tuple; } mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL)); int ret_i = 0; struct pollfd *entries = self->entries; for (int i = 0; i < self->len; i++, entries++) { if (entries->revents != 0) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); // If there's an object stored, return it, otherwise raw fd if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) { t->items[0] = self->obj_map[i]; } else { t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd); } t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents); ret_list->items[ret_i++] = MP_OBJ_FROM_PTR(t); if (self->flags & FLAG_ONESHOT) { entries->events = 0; } } } return MP_OBJ_FROM_PTR(ret_list); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll); STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); if (self->ret_tuple == MP_OBJ_NULL) { self->ret_tuple = mp_obj_new_tuple(2, NULL); } int n_ready = poll_poll_internal(n_args, args); self->iter_cnt = n_ready; self->iter_idx = 0; return args[0]; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll); STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); if (self->iter_cnt == 0) { return MP_OBJ_STOP_ITERATION; } self->iter_cnt--; struct pollfd *entries = self->entries + self->iter_idx; for (int i = self->iter_idx; i < self->len; i++, entries++) { self->iter_idx++; if (entries->revents != 0) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple); // If there's an object stored, return it, otherwise raw fd if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) { t->items[0] = self->obj_map[i]; } else { t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd); } t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents); if (self->flags & FLAG_ONESHOT) { entries->events = 0; } return MP_OBJ_FROM_PTR(t); } } assert(!"inconsistent number of poll active entries"); self->iter_cnt = 0; return MP_OBJ_STOP_ITERATION; } #if DEBUG STATIC mp_obj_t poll_dump(mp_obj_t self_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); struct pollfd *entries = self->entries; for (int i = self->len - 1; i >= 0; i--) { printf("fd: %d ev: %x rev: %x", entries->fd, entries->events, entries->revents); if (self->obj_map) { printf(" obj: %p", self->obj_map[entries - self->entries]); } printf("\n"); entries++; } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(poll_dump_obj, poll_dump); #endif STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) }, { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) }, { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) }, { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) }, { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) }, #if DEBUG { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&poll_dump_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); STATIC const mp_obj_type_t mp_type_poll = { { &mp_type_type }, .name = MP_QSTR_poll, .getiter = mp_identity_getiter, .iternext = poll_iternext, .locals_dict = (void*)&poll_locals_dict, }; STATIC mp_obj_t select_poll(size_t n_args, const mp_obj_t *args) { int alloc = 4; if (n_args > 0) { alloc = mp_obj_get_int(args[0]); } mp_obj_poll_t *poll = m_new_obj(mp_obj_poll_t); poll->base.type = &mp_type_poll; poll->entries = m_new(struct pollfd, alloc); poll->alloc = alloc; poll->len = 0; poll->obj_map = NULL; poll->iter_cnt = 0; poll->ret_tuple = MP_OBJ_NULL; return MP_OBJ_FROM_PTR(poll); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_poll_obj, 0, 1, select_poll); STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uselect) }, { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) }, { MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(POLLIN) }, { MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(POLLOUT) }, { MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(POLLERR) }, { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(POLLHUP) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table); const mp_obj_module_t mp_module_uselect = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_select_globals, }; #endif // MICROPY_PY_USELECT_POSIX micropython-1.12/ports/unix/modusocket.c000066400000000000000000000560061357706137100205040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2018 Paul Sokolovsky * Copyright (c) 2014-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "py/objtuple.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/builtin.h" #include "py/mphal.h" /* The idea of this module is to implement reasonable minimum of socket-related functions to write typical clients and servers. The module named "usocket" on purpose, to allow to make Python-level module more (or fully) compatible with CPython "socket", e.g.: ---- socket.py ---- from usocket import * from socket_more_funcs import * from socket_more_funcs2 import * ------------------- I.e. this module should stay lean, and more functions (if needed) should be add to separate modules (C or Python level). */ // This type must "inherit" from mp_obj_fdfile_t, i.e. matching subset of // fields should have the same layout. typedef struct _mp_obj_socket_t { mp_obj_base_t base; int fd; bool blocking; } mp_obj_socket_t; const mp_obj_type_t mp_type_socket; // Helper functions static inline mp_obj_t mp_obj_from_sockaddr(const struct sockaddr *addr, socklen_t len) { return mp_obj_new_bytes((const byte *)addr, len); } STATIC mp_obj_socket_t *socket_new(int fd) { mp_obj_socket_t *o = m_new_obj(mp_obj_socket_t); o->base.type = &mp_type_socket; o->fd = fd; o->blocking = true; return o; } STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "<_socket %d>", self->fd); } STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in); mp_int_t r = read(o->fd, buf, size); if (r == -1) { int err = errno; // On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO // timed out, and need to convert that to ETIMEDOUT. if (err == EAGAIN && o->blocking) { err = MP_ETIMEDOUT; } *errcode = err; return MP_STREAM_ERROR; } return r; } STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in); mp_int_t r = write(o->fd, buf, size); if (r == -1) { int err = errno; // On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO // timed out, and need to convert that to ETIMEDOUT. if (err == EAGAIN && o->blocking) { err = MP_ETIMEDOUT; } *errcode = err; return MP_STREAM_ERROR; } return r; } STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(o_in); (void)arg; switch (request) { case MP_STREAM_CLOSE: // There's a POSIX drama regarding return value of close in general, // and EINTR error in particular. See e.g. // http://lwn.net/Articles/576478/ // http://austingroupbugs.net/view.php?id=529 // The rationale MicroPython follows is that close() just releases // file descriptor. If you're interested to catch I/O errors before // closing fd, fsync() it. close(self->fd); return 0; case MP_STREAM_GET_FILENO: return self->fd; default: *errcode = MP_EINVAL; return MP_STREAM_ERROR; } } STATIC mp_obj_t socket_fileno(mp_obj_t self_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(self->fd); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno); STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); int err = errno; if (r == -1 && self->blocking && err == EINPROGRESS) { // EINPROGRESS on a blocking socket means the operation timed out err = MP_ETIMEDOUT; } RAISE_ERRNO(r, err); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); RAISE_ERRNO(r, errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); int r = listen(self->fd, MP_OBJ_SMALL_INT_VALUE(backlog_in)); RAISE_ERRNO(r, errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); STATIC mp_obj_t socket_accept(mp_obj_t self_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); // sockaddr_storage isn't stack-friendly (129 bytes or so) //struct sockaddr_storage addr; byte addr[32]; socklen_t addr_len = sizeof(addr); int fd = accept(self->fd, (struct sockaddr*)&addr, &addr_len); int err = errno; if (fd == -1 && self->blocking && err == EAGAIN) { // EAGAIN on a blocking socket means the operation timed out err = MP_ETIMEDOUT; } RAISE_ERRNO(fd, err); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); t->items[0] = MP_OBJ_FROM_PTR(socket_new(fd)); t->items[1] = mp_obj_new_bytearray(addr_len, &addr); return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); // Note: besides flag param, this differs from read() in that // this does not swallow blocking errors (EAGAIN, EWOULDBLOCK) - // these would be thrown as exceptions. STATIC mp_obj_t socket_recv(size_t n_args, const mp_obj_t *args) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); int sz = MP_OBJ_SMALL_INT_VALUE(args[1]); int flags = 0; if (n_args > 2) { flags = MP_OBJ_SMALL_INT_VALUE(args[2]); } byte *buf = m_new(byte, sz); int out_sz = recv(self->fd, buf, sz, flags); RAISE_ERRNO(out_sz, errno); mp_obj_t ret = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz); m_del(char, buf, sz); return ret; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_obj, 2, 3, socket_recv); STATIC mp_obj_t socket_recvfrom(size_t n_args, const mp_obj_t *args) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); int sz = MP_OBJ_SMALL_INT_VALUE(args[1]); int flags = 0; if (n_args > 2) { flags = MP_OBJ_SMALL_INT_VALUE(args[2]); } struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); byte *buf = m_new(byte, sz); int out_sz = recvfrom(self->fd, buf, sz, flags, (struct sockaddr*)&addr, &addr_len); RAISE_ERRNO(out_sz, errno); mp_obj_t buf_o = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz); m_del(char, buf, sz); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); t->items[0] = buf_o; t->items[1] = mp_obj_from_sockaddr((struct sockaddr*)&addr, addr_len); return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recvfrom_obj, 2, 3, socket_recvfrom); // Note: besides flag param, this differs from write() in that // this does not swallow blocking errors (EAGAIN, EWOULDBLOCK) - // these would be thrown as exceptions. STATIC mp_obj_t socket_send(size_t n_args, const mp_obj_t *args) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); int flags = 0; if (n_args > 2) { flags = MP_OBJ_SMALL_INT_VALUE(args[2]); } mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); int out_sz = send(self->fd, bufinfo.buf, bufinfo.len, flags); RAISE_ERRNO(out_sz, errno); return MP_OBJ_NEW_SMALL_INT(out_sz); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_send_obj, 2, 3, socket_send); STATIC mp_obj_t socket_sendto(size_t n_args, const mp_obj_t *args) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); int flags = 0; mp_obj_t dst_addr = args[2]; if (n_args > 3) { flags = MP_OBJ_SMALL_INT_VALUE(args[2]); dst_addr = args[3]; } mp_buffer_info_t bufinfo, addr_bi; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(dst_addr, &addr_bi, MP_BUFFER_READ); int out_sz = sendto(self->fd, bufinfo.buf, bufinfo.len, flags, (struct sockaddr *)addr_bi.buf, addr_bi.len); RAISE_ERRNO(out_sz, errno); return MP_OBJ_NEW_SMALL_INT(out_sz); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_sendto_obj, 3, 4, socket_sendto); STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { (void)n_args; // always 4 mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); int level = MP_OBJ_SMALL_INT_VALUE(args[1]); int option = mp_obj_get_int(args[2]); const void *optval; socklen_t optlen; int val; if (mp_obj_is_int(args[3])) { val = mp_obj_int_get_truncated(args[3]); optval = &val; optlen = sizeof(val); } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); optval = bufinfo.buf; optlen = bufinfo.len; } int r = setsockopt(self->fd, level, option, optval, optlen); RAISE_ERRNO(r, errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); int val = mp_obj_is_true(flag_in); int flags = fcntl(self->fd, F_GETFL, 0); RAISE_ERRNO(flags, errno); if (val) { flags &= ~O_NONBLOCK; } else { flags |= O_NONBLOCK; } flags = fcntl(self->fd, F_SETFL, flags); RAISE_ERRNO(flags, errno); self->blocking = val; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); struct timeval tv = {0,}; bool new_blocking = true; // Timeout of None means no timeout, which in POSIX is signified with 0 timeout, // and that's how 'tv' is initialized above if (timeout_in != mp_const_none) { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t val = mp_obj_get_float(timeout_in); double ipart; tv.tv_usec = round(modf(val, &ipart) * 1000000); tv.tv_sec = ipart; #else tv.tv_sec = mp_obj_get_int(timeout_in); #endif // For SO_RCVTIMEO/SO_SNDTIMEO, zero timeout means infinity, but // for Python API it means non-blocking. if (tv.tv_sec == 0 && tv.tv_usec == 0) { new_blocking = false; } } if (new_blocking) { int r; r = setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); RAISE_ERRNO(r, errno); r = setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval)); RAISE_ERRNO(r, errno); } if (self->blocking != new_blocking) { socket_setblocking(self_in, mp_obj_new_bool(new_blocking)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { // TODO: CPython explicitly says that closing returned object doesn't close // the original socket (Python2 at all says that fd is dup()ed). But we // save on the bloat. mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_t *new_args = alloca(n_args * sizeof(mp_obj_t)); memcpy(new_args + 1, args + 1, (n_args - 1) * sizeof(mp_obj_t)); new_args[0] = MP_OBJ_NEW_SMALL_INT(self->fd); return mp_builtin_open(n_args, new_args, (mp_map_t*)&mp_const_empty_map); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile); STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; (void)n_kw; int family = AF_INET; int type = SOCK_STREAM; int proto = 0; if (n_args > 0) { assert(mp_obj_is_small_int(args[0])); family = MP_OBJ_SMALL_INT_VALUE(args[0]); if (n_args > 1) { assert(mp_obj_is_small_int(args[1])); type = MP_OBJ_SMALL_INT_VALUE(args[1]); if (n_args > 2) { assert(mp_obj_is_small_int(args[2])); proto = MP_OBJ_SMALL_INT_VALUE(args[2]); } } } int fd = socket(family, type, proto); RAISE_ERRNO(fd, errno); return MP_OBJ_FROM_PTR(socket_new(fd)); } STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_obj) }, { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, }; STATIC MP_DEFINE_CONST_DICT(usocket_locals_dict, usocket_locals_dict_table); STATIC const mp_stream_p_t usocket_stream_p = { .read = socket_read, .write = socket_write, .ioctl = socket_ioctl, }; const mp_obj_type_t mp_type_socket = { { &mp_type_type }, .name = MP_QSTR_socket, .print = socket_print, .make_new = socket_make_new, .getiter = NULL, .iternext = NULL, .protocol = &usocket_stream_p, .locals_dict = (mp_obj_dict_t*)&usocket_locals_dict, }; #define BINADDR_MAX_LEN sizeof(struct in6_addr) STATIC mp_obj_t mod_socket_inet_pton(mp_obj_t family_in, mp_obj_t addr_in) { int family = mp_obj_get_int(family_in); byte binaddr[BINADDR_MAX_LEN]; int r = inet_pton(family, mp_obj_str_get_str(addr_in), binaddr); RAISE_ERRNO(r, errno); if (r == 0) { mp_raise_OSError(MP_EINVAL); } int binaddr_len = 0; switch (family) { case AF_INET: binaddr_len = sizeof(struct in_addr); break; case AF_INET6: binaddr_len = sizeof(struct in6_addr); break; } return mp_obj_new_bytes(binaddr, binaddr_len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_pton_obj, mod_socket_inet_pton); STATIC mp_obj_t mod_socket_inet_ntop(mp_obj_t family_in, mp_obj_t binaddr_in) { int family = mp_obj_get_int(family_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(binaddr_in, &bufinfo, MP_BUFFER_READ); vstr_t vstr; vstr_init_len(&vstr, family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN); if (inet_ntop(family, bufinfo.buf, vstr.buf, vstr.len) == NULL) { mp_raise_OSError(errno); } vstr.len = strlen(vstr.buf); return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_socket_inet_ntop_obj, mod_socket_inet_ntop); STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { // TODO: Implement 5th and 6th args const char *host = mp_obj_str_get_str(args[0]); const char *serv = NULL; struct addrinfo hints; char buf[6]; memset(&hints, 0, sizeof(hints)); // getaddrinfo accepts port in string notation, so however // it may seem stupid, we need to convert int to str if (mp_obj_is_small_int(args[1])) { unsigned port = (unsigned short)MP_OBJ_SMALL_INT_VALUE(args[1]); snprintf(buf, sizeof(buf), "%u", port); serv = buf; hints.ai_flags = AI_NUMERICSERV; #ifdef __UCLIBC_MAJOR__ #if __UCLIBC_MAJOR__ == 0 && (__UCLIBC_MINOR__ < 9 || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 32)) // "warning" requires -Wno-cpp which is a relatively new gcc option, so we choose not to use it. //#warning Working around uClibc bug with numeric service name // Older versions og uClibc have bugs when numeric ports in service // arg require also hints.ai_socktype (or hints.ai_protocol) != 0 // This actually was fixed in 0.9.32.1, but uClibc doesn't allow to // test for that. // http://git.uclibc.org/uClibc/commit/libc/inet/getaddrinfo.c?id=bc3be18145e4d5 // Note that this is crude workaround, precluding UDP socket addresses // to be returned. TODO: set only if not set by Python args. hints.ai_socktype = SOCK_STREAM; #endif #endif } else { serv = mp_obj_str_get_str(args[1]); } if (n_args > 2) { hints.ai_family = MP_OBJ_SMALL_INT_VALUE(args[2]); if (n_args > 3) { hints.ai_socktype = MP_OBJ_SMALL_INT_VALUE(args[3]); } } struct addrinfo *addr_list; int res = getaddrinfo(host, serv, &hints, &addr_list); if (res != 0) { // CPython: socket.gaierror nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res)); } assert(addr_list); mp_obj_t list = mp_obj_new_list(0, NULL); for (struct addrinfo *addr = addr_list; addr; addr = addr->ai_next) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(addr->ai_family); t->items[1] = MP_OBJ_NEW_SMALL_INT(addr->ai_socktype); t->items[2] = MP_OBJ_NEW_SMALL_INT(addr->ai_protocol); // "canonname will be a string representing the canonical name of the host // if AI_CANONNAME is part of the flags argument; else canonname will be empty." ?? if (addr->ai_canonname) { t->items[3] = MP_OBJ_NEW_QSTR(qstr_from_str(addr->ai_canonname)); } else { t->items[3] = mp_const_none; } t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr); mp_obj_list_append(list, MP_OBJ_FROM_PTR(t)); } freeaddrinfo(addr_list); return list; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 4, mod_socket_getaddrinfo); STATIC mp_obj_t mod_socket_sockaddr(mp_obj_t sockaddr_in) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(sockaddr_in, &bufinfo, MP_BUFFER_READ); switch (((struct sockaddr*)bufinfo.buf)->sa_family) { case AF_INET: { struct sockaddr_in *sa = (struct sockaddr_in*)bufinfo.buf; mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET); t->items[1] = mp_obj_new_bytes((byte*)&sa->sin_addr, sizeof(sa->sin_addr)); t->items[2] = MP_OBJ_NEW_SMALL_INT(ntohs(sa->sin_port)); return MP_OBJ_FROM_PTR(t); } case AF_INET6: { struct sockaddr_in6 *sa = (struct sockaddr_in6*)bufinfo.buf; mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET6); t->items[1] = mp_obj_new_bytes((byte*)&sa->sin6_addr, sizeof(sa->sin6_addr)); t->items[2] = MP_OBJ_NEW_SMALL_INT(ntohs(sa->sin6_port)); t->items[3] = MP_OBJ_NEW_SMALL_INT(ntohl(sa->sin6_flowinfo)); t->items[4] = MP_OBJ_NEW_SMALL_INT(ntohl(sa->sin6_scope_id)); return MP_OBJ_FROM_PTR(t); } default: { struct sockaddr *sa = (struct sockaddr*)bufinfo.buf; mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(sa->sa_family); t->items[1] = mp_obj_new_bytes((byte*)sa->sa_data, bufinfo.len - offsetof(struct sockaddr, sa_data)); return MP_OBJ_FROM_PTR(t); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_sockaddr_obj, mod_socket_sockaddr); STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_type_socket) }, { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_socket_getaddrinfo_obj) }, { MP_ROM_QSTR(MP_QSTR_inet_pton), MP_ROM_PTR(&mod_socket_inet_pton_obj) }, { MP_ROM_QSTR(MP_QSTR_inet_ntop), MP_ROM_PTR(&mod_socket_inet_ntop_obj) }, { MP_ROM_QSTR(MP_QSTR_sockaddr), MP_ROM_PTR(&mod_socket_sockaddr_obj) }, #define C(name) { MP_ROM_QSTR(MP_QSTR_ ## name), MP_ROM_INT(name) } C(AF_UNIX), C(AF_INET), C(AF_INET6), C(SOCK_STREAM), C(SOCK_DGRAM), C(SOCK_RAW), C(MSG_DONTROUTE), C(MSG_DONTWAIT), C(SOL_SOCKET), C(SO_BROADCAST), C(SO_ERROR), C(SO_KEEPALIVE), C(SO_LINGER), C(SO_REUSEADDR), #undef C }; STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table); const mp_obj_module_t mp_module_socket = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_socket_globals, }; micropython-1.12/ports/unix/mpconfigport.h000066400000000000000000000275341357706137100210470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // options to control how MicroPython is built #define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_PERSISTENT_CODE_LOAD (1) #if !defined(MICROPY_EMIT_X64) && defined(__x86_64__) #define MICROPY_EMIT_X64 (1) #endif #if !defined(MICROPY_EMIT_X86) && defined(__i386__) #define MICROPY_EMIT_X86 (1) #endif #if !defined(MICROPY_EMIT_THUMB) && defined(__thumb2__) #define MICROPY_EMIT_THUMB (1) #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) #endif // Some compilers define __thumb2__ and __arm__ at the same time, let // autodetected thumb2 emitter have priority. #if !defined(MICROPY_EMIT_ARM) && defined(__arm__) && !defined(__thumb2__) #define MICROPY_EMIT_ARM (1) #endif #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_RETURN_IF_EXPR (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) #define MICROPY_MEM_STATS (1) #define MICROPY_DEBUG_PRINTERS (1) // Printing debug to stderr may give tests which // check stdout a chance to pass, etc. #define MICROPY_DEBUG_PRINTER (&mp_stderr_print) #define MICROPY_READER_POSIX (1) #define MICROPY_USE_READLINE_HISTORY (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_EMACS_KEYS (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_HELPER_LEXER_UNIX (1) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_OPT_COMPUTED_GOTO (1) #ifndef MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (1) #endif #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_BUILTINS_ROUND_INT (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_ATEXIT (1) #if MICROPY_PY_SYS_SETTRACE #define MICROPY_PERSISTENT_CODE_SAVE (1) #define MICROPY_COMP_CONST (0) #endif #if defined(__APPLE__) && defined(__MACH__) #define MICROPY_PY_SYS_PLATFORM "darwin" #else #define MICROPY_PY_SYS_PLATFORM "linux" #endif #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_SYS_EXC_INFO (1) #define MICROPY_PY_COLLECTIONS_DEQUE (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) #endif #define MICROPY_PY_MATH_ISCLOSE (MICROPY_PY_MATH_SPECIAL_FUNCTIONS) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO_IOBASE (1) #define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_GC_COLLECT_RETVAL (1) #ifndef MICROPY_STACKLESS #define MICROPY_STACKLESS (0) #define MICROPY_STACKLESS_STRICT (0) #endif #define MICROPY_PY_OS_STATVFS (1) #define MICROPY_PY_UTIME (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UTIMEQ (1) #define MICROPY_PY_UHASHLIB (1) #if MICROPY_PY_USSL #define MICROPY_PY_UHASHLIB_MD5 (1) #define MICROPY_PY_UHASHLIB_SHA1 (1) #define MICROPY_PY_UCRYPTOLIB (1) #endif #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UBINASCII_CRC32 (1) #define MICROPY_PY_URANDOM (1) #ifndef MICROPY_PY_USELECT_POSIX #define MICROPY_PY_USELECT_POSIX (1) #endif #define MICROPY_PY_UWEBSOCKET (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr #define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ // Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc. // names in exception messages (may require more RAM). #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) #define MICROPY_WARNINGS (1) #define MICROPY_ERROR_PRINTER (&mp_stderr_print) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) extern const struct _mp_print_t mp_stderr_print; // Define to 1 to use undertested inefficient GC helper implementation // (if more efficient arch-specific one is not available). #ifndef MICROPY_GCREGS_SETJMP #ifdef __mips__ #define MICROPY_GCREGS_SETJMP (1) #else #define MICROPY_GCREGS_SETJMP (0) #endif #endif #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_ASYNC_KBD_INTR (1) extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_os; extern const struct _mp_obj_module_t mp_module_uos_vfs; extern const struct _mp_obj_module_t mp_module_uselect; extern const struct _mp_obj_module_t mp_module_time; extern const struct _mp_obj_module_t mp_module_termios; extern const struct _mp_obj_module_t mp_module_socket; extern const struct _mp_obj_module_t mp_module_ffi; extern const struct _mp_obj_module_t mp_module_jni; #if MICROPY_PY_UOS_VFS #define MICROPY_PY_UOS_DEF { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos_vfs) }, #else #define MICROPY_PY_UOS_DEF { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, #endif #if MICROPY_PY_FFI #define MICROPY_PY_FFI_DEF { MP_ROM_QSTR(MP_QSTR_ffi), MP_ROM_PTR(&mp_module_ffi) }, #else #define MICROPY_PY_FFI_DEF #endif #if MICROPY_PY_JNI #define MICROPY_PY_JNI_DEF { MP_ROM_QSTR(MP_QSTR_jni), MP_ROM_PTR(&mp_module_jni) }, #else #define MICROPY_PY_JNI_DEF #endif #if MICROPY_PY_UTIME #define MICROPY_PY_UTIME_DEF { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) }, #else #define MICROPY_PY_UTIME_DEF #endif #if MICROPY_PY_TERMIOS #define MICROPY_PY_TERMIOS_DEF { MP_ROM_QSTR(MP_QSTR_termios), MP_ROM_PTR(&mp_module_termios) }, #else #define MICROPY_PY_TERMIOS_DEF #endif #if MICROPY_PY_SOCKET #define MICROPY_PY_SOCKET_DEF { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_socket) }, #else #define MICROPY_PY_SOCKET_DEF #endif #if MICROPY_PY_USELECT_POSIX #define MICROPY_PY_USELECT_DEF { MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) }, #else #define MICROPY_PY_USELECT_DEF #endif #define MICROPY_PORT_BUILTIN_MODULES \ MICROPY_PY_FFI_DEF \ MICROPY_PY_JNI_DEF \ MICROPY_PY_UTIME_DEF \ MICROPY_PY_SOCKET_DEF \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ MICROPY_PY_UOS_DEF \ MICROPY_PY_USELECT_DEF \ MICROPY_PY_TERMIOS_DEF \ // type definitions for the specific machine // For size_t and ssize_t #include // assume that if we already defined the obj repr then we also defined types #ifndef MICROPY_OBJ_REPR #ifdef __LP64__ typedef long mp_int_t; // must be pointer size typedef unsigned long mp_uint_t; // must be pointer size #else // These are definitions for machines where sizeof(int) == sizeof(void*), // regardless of actual size. typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size #endif #endif // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; #else typedef long mp_off_t; #endif void mp_unix_alloc_exec(size_t min_size, void** ptr, size_t *size); void mp_unix_free_exec(void *ptr, size_t size); void mp_unix_mark_exec(void); #define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size) #define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size) #ifndef MICROPY_FORCE_PLAT_ALLOC_EXEC // Use MP_PLAT_ALLOC_EXEC for any executable memory allocation, including for FFI // (overriding libffi own implementation) #define MICROPY_FORCE_PLAT_ALLOC_EXEC (1) #endif #if MICROPY_PY_OS_DUPTERM #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #else #define MP_PLAT_PRINT_STRN(str, len) do { ssize_t ret = write(1, str, len); (void)ret; } while (0) #endif #ifdef __linux__ // Can access physical memory using /dev/mem #define MICROPY_PLAT_DEV_MEM (1) #endif // Assume that select() call, interrupted with a signal, and erroring // with EINTR, updates remaining timeout value. #define MICROPY_SELECT_REMAINING_TIME (1) #ifdef __ANDROID__ #include #if __ANDROID_API__ < 4 // Bionic libc in Android 1.5 misses these 2 functions #define MP_NEED_LOG2 (1) #define nan(x) NAN #endif #endif #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[50]; \ void *mmap_region_head; \ // We need to provide a declaration/definition of alloca() // unless support for it is disabled. #if !defined(MICROPY_NO_ALLOCA) || MICROPY_NO_ALLOCA == 0 #ifdef __FreeBSD__ #include #else #include #endif #endif // From "man readdir": "Under glibc, programs can check for the availability // of the fields [in struct dirent] not defined in POSIX.1 by testing whether // the macros [...], _DIRENT_HAVE_D_TYPE are defined." // Other libc's don't define it, but proactively assume that dirent->d_type // is available on a modern *nix system. #ifndef _DIRENT_HAVE_D_TYPE #define _DIRENT_HAVE_D_TYPE (1) #endif // This macro is not provided by glibc but we need it so ports that don't have // dirent->d_ino can disable the use of this field. #ifndef _DIRENT_HAVE_D_INO #define _DIRENT_HAVE_D_INO (1) #endif #ifndef __APPLE__ // For debugging purposes, make printf() available to any source file. #include #endif micropython-1.12/ports/unix/mpconfigport.mk000066400000000000000000000021501357706137100212120ustar00rootroot00000000000000# Enable/disable modules and 3rd-party libs to be included in interpreter # Build 32-bit binaries on a 64-bit host MICROPY_FORCE_32BIT = 0 # This variable can take the following values: # 0 - no readline, just simple stdin input # 1 - use MicroPython version of readline MICROPY_USE_READLINE = 1 # btree module using Berkeley DB 1.xx MICROPY_PY_BTREE = 1 # _thread module using pthreads MICROPY_PY_THREAD = 1 # Subset of CPython termios module MICROPY_PY_TERMIOS = 1 # Subset of CPython socket module MICROPY_PY_SOCKET = 1 # ffi module requires libffi (libffi-dev Debian package) MICROPY_PY_FFI = 1 # ussl module requires one of the TLS libraries below MICROPY_PY_USSL = 1 # axTLS has minimal size but implements only a subset of modern TLS # functionality, so may have problems with some servers. MICROPY_SSL_AXTLS = 1 # mbedTLS is more up to date and complete implementation, but also # more bloated. MICROPY_SSL_MBEDTLS = 0 # jni module requires JVM/JNI MICROPY_PY_JNI = 0 # Avoid using system libraries, use copies bundled with MicroPython # as submodules (currently affects only libffi). MICROPY_STANDALONE = 0 micropython-1.12/ports/unix/mpconfigport_coverage.h000066400000000000000000000057111357706137100227130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Default unix config while intended to be comprehensive, may still not enable // all the features, this config should enable more (testable) options. #define MICROPY_VFS (1) #define MICROPY_PY_UOS_VFS (1) #include #define MICROPY_OPT_MATH_FACTORIAL (1) #define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_READER_VFS (1) #define MICROPY_WARNINGS_CATEGORY (1) #define MICROPY_MODULE_GETATTR (1) #define MICROPY_PY_DELATTR_SETATTR (1) #define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (1) #define MICROPY_PY_BUILTINS_NEXT2 (1) #define MICROPY_PY_BUILTINS_RANGE_BINOP (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_SYS_GETSIZEOF (1) #define MICROPY_PY_MATH_FACTORIAL (1) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #define MICROPY_PY_IO_BUFFEREDWRITER (1) #define MICROPY_PY_IO_RESOURCE_STREAM (1) #define MICROPY_PY_URE_DEBUG (1) #define MICROPY_PY_URE_MATCH_GROUPS (1) #define MICROPY_PY_URE_MATCH_SPAN_START_END (1) #define MICROPY_PY_URE_SUB (1) #define MICROPY_VFS_POSIX (1) #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1) #define MICROPY_PY_UCRYPTOLIB (1) #define MICROPY_PY_UCRYPTOLIB_CTR (1) // TODO these should be generic, not bound to fatfs #define mp_type_fileio mp_type_vfs_posix_fileio #define mp_type_textio mp_type_vfs_posix_textio // use vfs's functions for import stat and builtin open #define mp_import_stat mp_vfs_import_stat #define mp_builtin_open mp_vfs_open #define mp_builtin_open_obj mp_vfs_open_obj micropython-1.12/ports/unix/mpconfigport_fast.h000066400000000000000000000031551357706137100220550ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // This config file is intended to configure artificially fast uPy build for // synthetic benchmarking, at the expense of features supported and memory // usage. This config is not intended to be used in production. #include #define MICROPY_PY___FILE__ (0) // 91 is a magic number proposed by @dpgeorge, which make pystone run ~ at tie // with CPython 3.4. #define MICROPY_MODULE_DICT_SIZE (91) micropython-1.12/ports/unix/mpconfigport_freedos.h000066400000000000000000000030331357706137100225420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // options to control how MicroPython is built #include #undef MICROPY_STREAMS_NON_BLOCK #define MICROPY_STREAMS_NON_BLOCK (0) #undef MICROPY_PY_SYS_PLATFORM #define MICROPY_PY_SYS_PLATFORM "freedos" // djgpp dirent struct does not have d_ino field #undef _DIRENT_HAVE_D_INO #define MICROPY_USE_INTERNAL_ERRNO (1) micropython-1.12/ports/unix/mpconfigport_minimal.h000066400000000000000000000126241357706137100225470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // options to control how MicroPython is built #define MICROPY_ALLOC_QSTR_CHUNK_INIT (64) #define MICROPY_ALLOC_PARSE_RULE_INIT (8) #define MICROPY_ALLOC_PARSE_RULE_INC (8) #define MICROPY_ALLOC_PARSE_RESULT_INIT (8) #define MICROPY_ALLOC_PARSE_RESULT_INC (8) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) #define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_ENABLE_GC (1) #define MICROPY_GC_ALLOC_THRESHOLD (0) #define MICROPY_ENABLE_FINALISER (0) #define MICROPY_STACK_CHECK (0) #define MICROPY_COMP_CONST (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_READER_POSIX (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (1) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_WARNINGS (0) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_STREAMS_NON_BLOCK (0) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #define MICROPY_CAN_OVERRIDE_BUILTINS (0) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_PY_BUILTINS_BYTEARRAY (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) #define MICROPY_PY_BUILTINS_COMPILE (0) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_SLICE (0) #define MICROPY_PY_BUILTINS_STR_COUNT (0) #define MICROPY_PY_BUILTINS_STR_OP_MODULO (0) #define MICROPY_PY_BUILTINS_STR_UNICODE (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_BUILTINS_MIN_MAX (0) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (0) #define MICROPY_PY_GC (0) #define MICROPY_PY_GC_COLLECT_RETVAL (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_EXIT (0) #define MICROPY_PY_SYS_PLATFORM "linux" #define MICROPY_PY_SYS_MAXSIZE (0) #define MICROPY_PY_SYS_STDFILES (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_UCTYPES (0) #define MICROPY_PY_UTIME (0) #define MICROPY_PY_UZLIB (0) #define MICROPY_PY_UJSON (0) #define MICROPY_PY_URE (0) #define MICROPY_PY_UHEAPQ (0) #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_UBINASCII (0) extern const struct _mp_obj_module_t mp_module_os; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \ #define MICROPY_PORT_ROOT_POINTERS \ ////////////////////////////////////////// // Do not change anything beyond this line ////////////////////////////////////////// // Define to 1 to use undertested inefficient GC helper implementation // (if more efficient arch-specific one is not available). #ifndef MICROPY_GCREGS_SETJMP #ifdef __mips__ #define MICROPY_GCREGS_SETJMP (1) #else #define MICROPY_GCREGS_SETJMP (0) #endif #endif // type definitions for the specific machine #ifdef __LP64__ typedef long mp_int_t; // must be pointer size typedef unsigned long mp_uint_t; // must be pointer size #else // These are definitions for machines where sizeof(int) == sizeof(void*), // regardless for actual size. typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size #endif // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; #else typedef long mp_off_t; #endif // We need to provide a declaration/definition of alloca() #ifdef __FreeBSD__ #include #else #include #endif micropython-1.12/ports/unix/mpconfigport_nanbox.h000066400000000000000000000031251357706137100224020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // select nan-boxing object model #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) // native emitters don't work with nan-boxing #define MICROPY_EMIT_X86 (0) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_ARM (0) #include typedef int64_t mp_int_t; typedef uint64_t mp_uint_t; #define UINT_FMT "%llu" #define INT_FMT "%lld" #include micropython-1.12/ports/unix/mphalport.h000066400000000000000000000044271357706137100203420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #ifndef CHAR_CTRL_C #define CHAR_CTRL_C (3) #endif void mp_hal_set_interrupt_char(char c); #define mp_hal_stdio_poll unused // this is not implemented, nor needed void mp_hal_stdio_mode_raw(void); void mp_hal_stdio_mode_orig(void); #if MICROPY_USE_READLINE == 1 && MICROPY_PY_BUILTINS_INPUT #include "py/misc.h" #include "lib/mp-readline/readline.h" // For built-in input() we need to wrap the standard readline() to enable raw mode #define mp_hal_readline mp_hal_readline static inline int mp_hal_readline(vstr_t *vstr, const char *p) { mp_hal_stdio_mode_raw(); int ret = readline(vstr, p); mp_hal_stdio_mode_orig(); return ret; } #endif // TODO: POSIX et al. define usleep() as guaranteedly capable only of 1s sleep: // "The useconds argument shall be less than one million." static inline void mp_hal_delay_ms(mp_uint_t ms) { usleep((ms) * 1000); } static inline void mp_hal_delay_us(mp_uint_t us) { usleep(us); } #define mp_hal_ticks_cpu() 0 #define RAISE_ERRNO(err_flag, error_val) \ { if (err_flag == -1) \ { mp_raise_OSError(error_val); } } micropython-1.12/ports/unix/mpthreadport.c000066400000000000000000000204311357706137100210310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/mpthread.h" #include "py/gc.h" #if MICROPY_PY_THREAD #include #include #include #include // this structure forms a linked list, one node per active thread typedef struct _thread_t { pthread_t id; // system id of thread int ready; // whether the thread is ready and running void *arg; // thread Python args, a GC root pointer struct _thread_t *next; } thread_t; STATIC pthread_key_t tls_key; // the mutex controls access to the linked list STATIC pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER; STATIC thread_t *thread; // this is used to synchronise the signal handler of the thread // it's needed because we can't use any pthread calls in a signal handler #if defined(__APPLE__) STATIC char thread_signal_done_name[25]; STATIC sem_t *thread_signal_done_p; #else STATIC sem_t thread_signal_done; #endif // this signal handler is used to scan the regs and stack of a thread STATIC void mp_thread_gc(int signo, siginfo_t *info, void *context) { (void)info; // unused (void)context; // unused if (signo == SIGUSR1) { void gc_collect_regs_and_stack(void); gc_collect_regs_and_stack(); // We have access to the context (regs, stack) of the thread but it seems // that we don't need the extra information, enough is captured by the // gc_collect_regs_and_stack function above //gc_collect_root((void**)context, sizeof(ucontext_t) / sizeof(uintptr_t)); #if MICROPY_ENABLE_PYSTACK void **ptrs = (void**)(void*)MP_STATE_THREAD(pystack_start); gc_collect_root(ptrs, (MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start)) / sizeof(void*)); #endif #if defined (__APPLE__) sem_post(thread_signal_done_p); #else sem_post(&thread_signal_done); #endif } } void mp_thread_init(void) { pthread_key_create(&tls_key, NULL); pthread_setspecific(tls_key, &mp_state_ctx.thread); // create first entry in linked list of all threads thread = malloc(sizeof(thread_t)); thread->id = pthread_self(); thread->ready = 1; thread->arg = NULL; thread->next = NULL; #if defined(__APPLE__) snprintf(thread_signal_done_name, sizeof(thread_signal_done_name), "micropython_sem_%d", (int)thread->id); thread_signal_done_p = sem_open(thread_signal_done_name, O_CREAT | O_EXCL, 0666, 0); #else sem_init(&thread_signal_done, 0, 0); #endif // enable signal handler for garbage collection struct sigaction sa; sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = mp_thread_gc; sigemptyset(&sa.sa_mask); sigaction(SIGUSR1, &sa, NULL); } void mp_thread_deinit(void) { pthread_mutex_lock(&thread_mutex); while (thread->next != NULL) { thread_t *th = thread; thread = thread->next; pthread_cancel(th->id); free(th); } pthread_mutex_unlock(&thread_mutex); #if defined(__APPLE__) sem_close(thread_signal_done_p); sem_unlink(thread_signal_done_name); #endif assert(thread->id == pthread_self()); free(thread); } // This function scans all pointers that are external to the current thread. // It does this by signalling all other threads and getting them to scan their // own registers and stack. Note that there may still be some edge cases left // with race conditions and root-pointer scanning: a given thread may manipulate // the global root pointers (in mp_state_ctx) while another thread is doing a // garbage collection and tracing these pointers. void mp_thread_gc_others(void) { pthread_mutex_lock(&thread_mutex); for (thread_t *th = thread; th != NULL; th = th->next) { gc_collect_root(&th->arg, 1); if (th->id == pthread_self()) { continue; } if (!th->ready) { continue; } pthread_kill(th->id, SIGUSR1); #if defined(__APPLE__) sem_wait(thread_signal_done_p); #else sem_wait(&thread_signal_done); #endif } pthread_mutex_unlock(&thread_mutex); } mp_state_thread_t *mp_thread_get_state(void) { return (mp_state_thread_t*)pthread_getspecific(tls_key); } void mp_thread_set_state(void *state) { pthread_setspecific(tls_key, state); } void mp_thread_start(void) { pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_lock(&thread_mutex); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == pthread_self()) { th->ready = 1; break; } } pthread_mutex_unlock(&thread_mutex); } void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { // default stack size is 8k machine-words if (*stack_size == 0) { *stack_size = 8192 * BYTES_PER_WORD; } // minimum stack size is set by pthreads if (*stack_size < PTHREAD_STACK_MIN) { *stack_size = PTHREAD_STACK_MIN; } // set thread attributes pthread_attr_t attr; int ret = pthread_attr_init(&attr); if (ret != 0) { goto er; } ret = pthread_attr_setstacksize(&attr, *stack_size); if (ret != 0) { goto er; } ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (ret != 0) { goto er; } pthread_mutex_lock(&thread_mutex); // create thread pthread_t id; ret = pthread_create(&id, &attr, entry, arg); if (ret != 0) { pthread_mutex_unlock(&thread_mutex); goto er; } // adjust stack_size to provide room to recover from hitting the limit // this value seems to be about right for both 32-bit and 64-bit builds *stack_size -= 8192; // add thread to linked list of all threads thread_t *th = malloc(sizeof(thread_t)); th->id = id; th->ready = 0; th->arg = arg; th->next = thread; thread = th; pthread_mutex_unlock(&thread_mutex); return; er: mp_raise_OSError(ret); } void mp_thread_finish(void) { pthread_mutex_lock(&thread_mutex); thread_t *prev = NULL; for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == pthread_self()) { if (prev == NULL) { thread = th->next; } else { prev->next = th->next; } free(th); break; } prev = th; } pthread_mutex_unlock(&thread_mutex); } void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { pthread_mutex_init(mutex, NULL); } int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { int ret; if (wait) { ret = pthread_mutex_lock(mutex); if (ret == 0) { return 1; } } else { ret = pthread_mutex_trylock(mutex); if (ret == 0) { return 1; } else if (ret == EBUSY) { return 0; } } return -ret; } void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { pthread_mutex_unlock(mutex); // TODO check return value } #endif // MICROPY_PY_THREAD micropython-1.12/ports/unix/mpthreadport.h000066400000000000000000000025731357706137100210450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include typedef pthread_mutex_t mp_thread_mutex_t; void mp_thread_init(void); void mp_thread_deinit(void); void mp_thread_gc_others(void); micropython-1.12/ports/unix/qstrdefsport.h000066400000000000000000000023171357706137100210700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ micropython-1.12/ports/unix/unix_mphal.c000066400000000000000000000147321357706137100204730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/mphal.h" #include "py/runtime.h" #include "extmod/misc.h" #ifndef _WIN32 #include STATIC void sighandler(int signum) { if (signum == SIGINT) { #if MICROPY_ASYNC_KBD_INTR mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); sigset_t mask; sigemptyset(&mask); // On entry to handler, its signal is blocked, and unblocked on // normal exit. As we instead perform longjmp, unblock it manually. sigprocmask(SIG_SETMASK, &mask, NULL); nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); #else if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) { // this is the second time we are called, so die straight away exit(1); } mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); #endif } } #endif void mp_hal_set_interrupt_char(char c) { // configure terminal settings to (not) let ctrl-C through if (c == CHAR_CTRL_C) { #ifndef _WIN32 // enable signal handler struct sigaction sa; sa.sa_flags = 0; sa.sa_handler = sighandler; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); #endif } else { #ifndef _WIN32 // disable signal handler struct sigaction sa; sa.sa_flags = 0; sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); #endif } } #if MICROPY_USE_READLINE == 1 #include static struct termios orig_termios; void mp_hal_stdio_mode_raw(void) { // save and set terminal settings tcgetattr(0, &orig_termios); static struct termios termios; termios = orig_termios; termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); termios.c_cflag = (termios.c_cflag & ~(CSIZE | PARENB)) | CS8; termios.c_lflag = 0; termios.c_cc[VMIN] = 1; termios.c_cc[VTIME] = 0; tcsetattr(0, TCSAFLUSH, &termios); } void mp_hal_stdio_mode_orig(void) { // restore terminal settings tcsetattr(0, TCSAFLUSH, &orig_termios); } #endif #if MICROPY_PY_OS_DUPTERM static int call_dupterm_read(size_t idx) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t read_m[3]; mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_read, read_m); read_m[2] = MP_OBJ_NEW_SMALL_INT(1); mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); if (res == mp_const_none) { return -2; } mp_buffer_info_t bufinfo; mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); if (bufinfo.len == 0) { mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n"); MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL; return -1; } nlr_pop(); return *(byte*)bufinfo.buf; } else { // Temporarily disable dupterm to avoid infinite recursion mp_obj_t save_term = MP_STATE_VM(dupterm_objs[idx]); MP_STATE_VM(dupterm_objs[idx]) = NULL; mp_printf(&mp_plat_print, "dupterm: "); mp_obj_print_exception(&mp_plat_print, nlr.ret_val); MP_STATE_VM(dupterm_objs[idx]) = save_term; } return -1; } #endif int mp_hal_stdin_rx_chr(void) { unsigned char c; #if MICROPY_PY_OS_DUPTERM // TODO only support dupterm one slot at the moment if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) { int c; do { c = call_dupterm_read(0); } while (c == -2); if (c == -1) { goto main_term; } if (c == '\n') { c = '\r'; } return c; } else { main_term:; #endif int ret = read(0, &c, 1); if (ret == 0) { c = 4; // EOF, ctrl-D } else if (c == '\n') { c = '\r'; } return c; #if MICROPY_PY_OS_DUPTERM } #endif } void mp_hal_stdout_tx_strn(const char *str, size_t len) { int ret = write(1, str, len); mp_uos_dupterm_tx_strn(str, len); (void)ret; // to suppress compiler warning } // cooked is same as uncooked because the terminal does some postprocessing void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { mp_hal_stdout_tx_strn(str, len); } void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } mp_uint_t mp_hal_ticks_ms(void) { #if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec tv; clock_gettime(CLOCK_MONOTONIC, &tv); return tv.tv_sec * 1000 + tv.tv_nsec / 1000000; #else struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000 + tv.tv_usec / 1000; #endif } mp_uint_t mp_hal_ticks_us(void) { #if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec tv; clock_gettime(CLOCK_MONOTONIC, &tv); return tv.tv_sec * 1000000 + tv.tv_nsec / 1000; #else struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000 + tv.tv_usec; #endif } micropython-1.12/ports/windows/000077500000000000000000000000001357706137100166635ustar00rootroot00000000000000micropython-1.12/ports/windows/.appveyor.yml000066400000000000000000000050431357706137100213330ustar00rootroot00000000000000environment: # Python version used MICROPY_CPYTHON3: c:/python34/python.exe init: # Set build version number to commit to be travis-like - ps: Update-AppveyorBuild -Version $env:appveyor_repo_commit.substring(0,8) configuration: - Debug - Release platform: - x86 - x64 before_build: - ps: | @" "@ | Set-Content build.proj build: project: build.proj parallel: true verbosity: normal test_script: - ps: | cd (Join-Path $env:APPVEYOR_BUILD_FOLDER 'tests') & $env:MICROPY_CPYTHON3 run-tests & $env:MICROPY_CPYTHON3 run-tests --via-mpy -d basics float micropython # After the build/test phase for the MSVC build completes, # build and test with mingw-w64, release versions only. after_test: - ps: | if ($env:configuration -eq 'Debug') { return } $env:MSYSTEM = if ($platform -eq 'x86') {'MINGW32'} else {'MINGW64'} $env:CHERE_INVOKING = 'enabled_from_arguments' cd (Join-Path $env:APPVEYOR_BUILD_FOLDER 'ports/windows') C:\msys64\usr\bin\bash.exe -l -c "make -B -j4 V=1" if ($LASTEXITCODE -ne 0) { throw "$env:MSYSTEM build exited with code $LASTEXITCODE" } cd (Join-Path $env:APPVEYOR_BUILD_FOLDER 'mpy-cross') # Building of mpy-cross hasn't been fixed across all possible windows/WSL/... # variations and the STRIP step tries to strip mpy-cross whereas that should be # mpy-cross.exe. Workaround for now by skipping actual strip and size commands. C:\msys64\usr\bin\bash.exe -l -c "make -B -j4 V=1 STRIP=echo SIZE=echo" if ($LASTEXITCODE -ne 0) { throw "$env:MSYSTEM mpy_cross build exited with code $LASTEXITCODE" } cd (Join-Path $env:APPVEYOR_BUILD_FOLDER 'tests') $testArgs = @('run-tests') foreach ($skipTest in @('math_fun', 'float2int_double', 'float_parse', 'math_domain_special')) { $testArgs = $testArgs + '-e' + $skipTest } & $env:MICROPY_CPYTHON3 $testArgs if ($LASTEXITCODE -ne 0) { throw "$env:MSYSTEM tests exited with code $LASTEXITCODE" } & $env:MICROPY_CPYTHON3 ($testArgs + @('--via-mpy', '-d', 'basics', 'float', 'micropython')) if ($LASTEXITCODE -ne 0) { throw "$env:MSYSTEM mpy-cross tests exited with code $LASTEXITCODE" } skip_tags: true deploy: off nuget: disable_publish_on_pr: true micropython-1.12/ports/windows/.gitignore000066400000000000000000000001161357706137100206510ustar00rootroot00000000000000*.user *.*sdf *.suo *.sln *.exe *.pdb *.ilk *.filters /build/* .vs/* *.VC.*db micropython-1.12/ports/windows/Makefile000066400000000000000000000023441357706137100203260ustar00rootroot00000000000000include ../../py/mkenv.mk -include mpconfigport.mk # define main target PROG = micropython.exe # qstr definitions (must come before including py.mk) QSTR_DEFS = ../unix/qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk INC += -I. INC += -I$(TOP) INC += -I$(BUILD) # compiler settings CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) LDFLAGS = $(LDFLAGS_MOD) -lm $(LDFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG CFLAGS += -g COPT = -O0 else COPT = -Os #-DNDEBUG endif # source files SRC_C = \ lib/utils/printf.c \ ports/unix/main.c \ ports/unix/file.c \ ports/unix/input.c \ ports/unix/modos.c \ ports/unix/modmachine.c \ ports/unix/modtime.c \ ports/unix/gccollect.c \ windows_mphal.c \ realpath.c \ init.c \ sleep.c \ fmode.c \ $(SRC_MOD) OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) ifeq ($(MICROPY_USE_READLINE),1) CFLAGS_MOD += -DMICROPY_USE_READLINE=1 SRC_C += lib/mp-readline/readline.c endif LIB += -lws2_32 # List of sources for qstr extraction SRC_QSTR += $(SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += include $(TOP)/py/mkrules.mk micropython-1.12/ports/windows/README.md000066400000000000000000000045561357706137100201540ustar00rootroot00000000000000This is the experimental, community-supported Windows port of MicroPython. It is based on Unix port, and expected to remain so. The port requires additional testing, debugging, and patches. Please consider to contribute. Building on Debian/Ubuntu Linux system --------------------------------------- sudo apt-get install gcc-mingw-w64 make CROSS_COMPILE=i686-w64-mingw32- If for some reason the mingw-w64 crosscompiler is not available, you can try mingw32 instead, but it comes with a really old gcc which may produce some spurious errors (you may need to disable -Werror): sudo apt-get install mingw32 mingw32-binutils mingw32-runtime make CROSS_COMPILE=i586-mingw32msvc- Building under Cygwin --------------------- Install following packages using cygwin's setup.exe: * mingw64-i686-gcc-core * mingw64-x86_64-gcc-core * make Build using: make CROSS_COMPILE=i686-w64-mingw32- Or for 64bit: make CROSS_COMPILE=x86_64-w64-mingw32- Building using MS Visual Studio 2013 (or higher) ------------------------------------------------ In the IDE, open `micropython.vcxproj` and build. To build from the command line: msbuild micropython.vcxproj __Stack usage__ The msvc compiler is quite stack-hungry which might result in a "maximum recursion depth exceeded" RuntimeError for code with lots of nested function calls. There are several ways to deal with this: - increase the threshold used for detection by altering the argument to `mp_stack_set_limit` in `ports/unix/main.c` - disable detection all together by setting `MICROPY_STACK_CHECK` to "0" in `ports/windows/mpconfigport.h` - disable the /GL compiler flag by setting `WholeProgramOptimization` to "false" See [issue 2927](https://github.com/micropython/micropython/issues/2927) for more information. Running on Linux using Wine --------------------------- The default build (MICROPY_USE_READLINE=1) uses extended Windows console functions and thus should be ran using the `wineconsole` tool. Depending on the Wine build configuration, you may also want to select the curses backend which has the look&feel of a standard Unix console: wineconsole --backend=curses ./micropython.exe For more info, see https://www.winehq.org/docs/wineusr-guide/cui-programs . If built without line editing and history capabilities (MICROPY_USE_READLINE=0), the resulting binary can be run using the standard `wine` tool. micropython-1.12/ports/windows/fmode.c000066400000000000000000000033031357706137100201200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "fmode.h" #include "py/mpconfig.h" #include #include // Workaround for setting file translation mode: we must distinguish toolsets // since mingw has no _set_fmode, and altering msvc's _fmode directly has no effect STATIC int set_fmode_impl(int mode) { #ifndef _MSC_VER _fmode = mode; return 0; #else return _set_fmode(mode); #endif } void set_fmode_binary(void) { set_fmode_impl(O_BINARY); } void set_fmode_text(void) { set_fmode_impl(O_TEXT); } micropython-1.12/ports/windows/fmode.h000066400000000000000000000031661357706137100201340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_WINDOWS_FMODE_H #define MICROPY_INCLUDED_WINDOWS_FMODE_H // Treat files opened by open() as binary. No line ending translation is done. void set_fmode_binary(void); // Treat files opened by open() as text. // When reading from the file \r\n will be converted to \n. // When writing to the file \n will be converted into \r\n. void set_fmode_text(void); #endif // MICROPY_INCLUDED_WINDOWS_FMODE_H micropython-1.12/ports/windows/init.c000066400000000000000000000051761357706137100200030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #ifdef _MSC_VER #include #endif #include "sleep.h" #include "fmode.h" extern BOOL WINAPI console_sighandler(DWORD evt); #ifdef _MSC_VER void invalid_param_handler(const wchar_t *expr, const wchar_t *fun, const wchar_t *file, unsigned int line, uintptr_t p) { } #endif void init() { #ifdef _MSC_VER // Disable the 'Debug Error!' dialog for assertions failures and the likes, // instead write messages to the debugger output and terminate. _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); // Disable 'invalid parameter handling' which is for instance invoked when // passing invalid file descriptors to functions like lseek() and make the // functions called behave properly by setting errno to EBADF/EINVAL/.. _set_invalid_parameter_handler(invalid_param_handler); #endif SetConsoleCtrlHandler(console_sighandler, TRUE); init_sleep(); #ifdef __MINGW32__ putenv("PRINTF_EXPONENT_DIGITS=2"); #elif _MSC_VER < 1900 // This is only necessary for Visual Studio versions 2013 and below: // https://msdn.microsoft.com/en-us/library/bb531344(v=vs.140).aspx _set_output_format(_TWO_DIGIT_EXPONENT); #endif set_fmode_binary(); } void deinit() { SetConsoleCtrlHandler(console_sighandler, FALSE); deinit_sleep(); } micropython-1.12/ports/windows/init.h000066400000000000000000000025571357706137100200100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_WINDOWS_INIT_H #define MICROPY_INCLUDED_WINDOWS_INIT_H void init(void); void deinit(void); #endif // MICROPY_INCLUDED_WINDOWS_INIT_H micropython-1.12/ports/windows/micropython.vcxproj000066400000000000000000000133071357706137100226570ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 {740F3C30-EB6C-4B59-9C50-AE4D5A4A9D12} micropython Application $(DefaultPlatformToolset) Application $(DefaultPlatformToolset) Application $(DefaultPlatformToolset) Application $(DefaultPlatformToolset) msvc/user.props micropython-1.12/ports/windows/mpconfigport.h000066400000000000000000000223421357706137100215460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // options to control how MicroPython is built // By default use MicroPython version of readline #ifndef MICROPY_USE_READLINE #define MICROPY_USE_READLINE (1) #endif #define MICROPY_ALLOC_PATH_MAX (260) //see minwindef.h for msvc or limits.h for mingw #define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_RETURN_IF_EXPR (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_ENABLE_PYSTACK (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) #define MICROPY_MEM_STATS (1) #define MICROPY_DEBUG_PRINTER (&mp_stderr_print) #define MICROPY_DEBUG_PRINTERS (1) #define MICROPY_READER_POSIX (1) #define MICROPY_USE_READLINE_HISTORY (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_EMACS_KEYS (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_HELPER_LEXER_UNIX (1) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_PLATFORM "win32" #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_SYS_EXC_INFO (1) #define MICROPY_PY_COLLECTIONS_DEQUE (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) #define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_GC_COLLECT_RETVAL (1) #define MICROPY_MODULE_FROZEN_STR (0) #define MICROPY_STACKLESS (0) #define MICROPY_STACKLESS_STRICT (0) #define MICROPY_PY_UTIME (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URE (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UTIMEQ (1) #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UBINASCII_CRC32 (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr #define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) #define MICROPY_ERROR_PRINTER (&mp_stderr_print) #define MICROPY_WARNINGS (1) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) extern const struct _mp_print_t mp_stderr_print; #ifdef _MSC_VER #define MICROPY_GCREGS_SETJMP (1) #define MICROPY_USE_INTERNAL_PRINTF (0) #endif #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_PORT_INIT_FUNC init() #define MICROPY_PORT_DEINIT_FUNC deinit() // type definitions for the specific machine #if defined( __MINGW32__ ) && defined( __LP64__ ) typedef long mp_int_t; // must be pointer size typedef unsigned long mp_uint_t; // must be pointer size #elif defined ( __MINGW32__ ) && defined( _WIN64 ) #include typedef __int64 mp_int_t; typedef unsigned __int64 mp_uint_t; #define MP_SSIZE_MAX __INT64_MAX__ #elif defined ( _MSC_VER ) && defined( _WIN64 ) typedef __int64 mp_int_t; typedef unsigned __int64 mp_uint_t; #else // These are definitions for machines where sizeof(int) == sizeof(void*), // regardless for actual size. typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size #endif // Just assume Windows is little-endian - mingw32 gcc doesn't // define standard endianness macros. #define MP_ENDIANNESS_LITTLE (1) // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; #else typedef long mp_off_t; #endif #if MICROPY_PY_OS_DUPTERM #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) void mp_hal_dupterm_tx_strn(const char *str, size_t len); #else #include #define MP_PLAT_PRINT_STRN(str, len) do { int ret = write(1, str, len); (void)ret; } while (0) #define mp_hal_dupterm_tx_strn(s, l) #endif #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, extern const struct _mp_obj_module_t mp_module_os; extern const struct _mp_obj_module_t mp_module_time; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) }, \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \ #if MICROPY_USE_READLINE == 1 #define MICROPY_PORT_ROOT_POINTERS \ char *readline_hist[50]; #endif #define MP_STATE_PORT MP_STATE_VM #define MICROPY_MPHALPORT_H "windows_mphal.h" // We need to provide a declaration/definition of alloca() #include #include "realpath.h" #include "init.h" #include "sleep.h" #ifdef __GNUC__ #define MP_NOINLINE __attribute__((noinline)) #endif // MSVC specifics #ifdef _MSC_VER // Sanity check #if ( _MSC_VER < 1800 ) #error Can only build with Visual Studio 2013 toolset #endif // CL specific overrides from mpconfig #define NORETURN __declspec(noreturn) #define MP_WEAK #define MP_NOINLINE __declspec(noinline) #define MP_LIKELY(x) (x) #define MP_UNLIKELY(x) (x) #define MICROPY_PORT_CONSTANTS { "dummy", 0 } //can't have zero-sized array #ifdef _WIN64 #define MP_SSIZE_MAX _I64_MAX #else #define MP_SSIZE_MAX _I32_MAX #endif // CL specific definitions #ifndef __cplusplus #define restrict #define inline __inline #define alignof(t) __alignof(t) #endif #define PATH_MAX MICROPY_ALLOC_PATH_MAX #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #ifdef _WIN64 #define SSIZE_MAX _I64_MAX typedef __int64 ssize_t; #else #define SSIZE_MAX _I32_MAX typedef int ssize_t; #endif typedef mp_off_t off_t; // Put static/global variables in sections with a known name // This used to be required for GC, not the case anymore but keep it as it makes the map file easier to inspect // For this to work this header must be included by all sources, which is the case normally #define MICROPY_PORT_DATASECTION "upydata" #define MICROPY_PORT_BSSSECTION "upybss" #pragma data_seg(MICROPY_PORT_DATASECTION) #pragma bss_seg(MICROPY_PORT_BSSSECTION) // System headers (needed e.g. for nlr.h) #include //for NULL #include //for assert #endif micropython-1.12/ports/windows/mpconfigport.mk000066400000000000000000000005711357706137100217260ustar00rootroot00000000000000# Enable/disable modules and 3rd-party libs to be included in interpreter # Build 32-bit binaries on a 64-bit host MICROPY_FORCE_32BIT = 0 # This variable can take the following values: # 0 - no readline, just simple stdin input # 1 - use MicroPython version of readline MICROPY_USE_READLINE = 1 # ffi module requires libffi (libffi-dev Debian package) MICROPY_PY_FFI = 0 micropython-1.12/ports/windows/msvc/000077500000000000000000000000001357706137100176335ustar00rootroot00000000000000micropython-1.12/ports/windows/msvc/common.props000066400000000000000000000052471357706137100222200ustar00rootroot00000000000000 $(PyOutDir) $(PyIntDir) $(PyBuildDir)copycookie$(Configuration)$(Platform) MultiByte $(PyIncDirs);%(AdditionalIncludeDirectories) _USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) false Level1 false true false true true true $(PyTargetDir)%(FileName)%(Extension) micropython-1.12/ports/windows/msvc/debug.props000066400000000000000000000006451357706137100220130ustar00rootroot00000000000000 true false micropython-1.12/ports/windows/msvc/dirent.c000066400000000000000000000066621357706137100212760ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "dirent.h" #include "extmod/vfs.h" #include #include typedef struct DIR { HANDLE findHandle; WIN32_FIND_DATA findData; struct dirent result; } DIR; DIR *opendir(const char *name) { if (!name || !*name) { errno = ENOENT; return NULL; } DIR *dir = malloc(sizeof(DIR)); if (!dir) { errno = ENOMEM; return NULL; } dir->result.d_ino = 0; dir->result.d_name = NULL; dir->findHandle = INVALID_HANDLE_VALUE; const size_t nameLen = strlen(name); char *path = malloc(nameLen + 3); // allocate enough for adding "/*" if (!path) { free(dir); errno = ENOMEM; return NULL; } strcpy(path, name); // assure path ends with wildcard const char lastChar = path[nameLen - 1]; if (lastChar != '*') { const char *appendWC = (lastChar != '/' && lastChar != '\\') ? "/*" : "*"; strcat(path, appendWC); } // init dir->findHandle = FindFirstFile(path, &dir->findData); free(path); if (dir->findHandle == INVALID_HANDLE_VALUE) { free(dir); errno = ENOENT; return NULL; } return dir; } int closedir(DIR *dir) { if (dir) { FindClose(dir->findHandle); free(dir); return 0; } else { errno = EBADF; return -1; } } struct dirent *readdir(DIR *dir) { if (!dir) { errno = EBADF; return NULL; } // first pass d_name is NULL so use result from FindFirstFile in opendir, else use FindNextFile if (!dir->result.d_name || FindNextFile(dir->findHandle, &dir->findData)) { dir->result.d_name = dir->findData.cFileName; dir->result.d_type = dir->findData.dwFileAttributes; return &dir->result; } return NULL; } int dttoif(int d_type) { if (d_type == INVALID_FILE_ATTRIBUTES) { return 0; } // Could be a couple of things (symlink, junction, ...) and non-trivial to // figure out so just report it as unknown. Should we ever want this then // the proper code can be found in msvc's std::filesystem implementation. if (d_type & FILE_ATTRIBUTE_REPARSE_POINT) { return 0; } return (d_type & FILE_ATTRIBUTE_DIRECTORY) ? MP_S_IFDIR : MP_S_IFREG; } micropython-1.12/ports/windows/msvc/dirent.h000066400000000000000000000035571357706137100213030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_WINDOWS_MSVC_DIRENT_H #define MICROPY_INCLUDED_WINDOWS_MSVC_DIRENT_H // dirent.h implementation for msvc // for ino_t #include #define _DIRENT_HAVE_D_TYPE (1) #define DTTOIF dttoif // opaque DIR structure typedef struct DIR DIR; // the dirent structure // d_ino is always 0 - if ever needed use GetFileInformationByHandle // d_type can be converted using DTTOIF, into 0 (unknown) or MP_S_IFDIR or MP_S_IFREG typedef struct dirent { ino_t d_ino; int d_type; char *d_name; } dirent; DIR *opendir(const char *name); int closedir(DIR *dir); struct dirent *readdir(DIR *dir); int dttoif(int d_type); #endif // MICROPY_INCLUDED_WINDOWS_MSVC_DIRENT_H micropython-1.12/ports/windows/msvc/genhdr.targets000066400000000000000000000160151357706137100225000ustar00rootroot00000000000000 $(PyBuildDir)genhdr\ $(PyBaseDir)py\ $(PyBaseDir)ports\unix\qstrdefsport.h $(PySrcDir)qstrdefs.h $(DestDir)qstrdefscollected.h $(DestDir)qstrdefs.generated.h python cl.exe $([System.IO.Path]::Combine(`$(CLToolPath)`, `$(CLToolExe)`)) $([System.String]::new('%(FullPath)').Replace('$(PyBaseDir)', '$(DestDir)qstr\')) $([System.IO.Path]::ChangeExtension('%(OutFile)', '.pp')) $([System.IO.Path]::GetDirectoryName('%(OutFile)')) True True @(QstrDependencies->AnyHaveMetadataValue('Changed', 'True')) @(PyQstrSourceFiles->AnyHaveMetadataValue('Changed', 'True')) $(DestDir)moduledefs.h $(DestFile).tmp $([System.String]::new('%(FullPath)').Replace('$(PyBaseDir)', '')) $(QstrGen).tmp $(DestDir)mpversion.h $(DestFile).tmp micropython-1.12/ports/windows/msvc/gettimeofday.c000066400000000000000000000040321357706137100224570ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include typedef union { unsigned __int64 tm; // time in 100 nanoseconds interval FILETIME ft; } FT; int gettimeofday(struct timeval *tp, struct timezone *tz) { if (tp == NULL) { return 0; } // UTC time FT ft; ZeroMemory(&ft, sizeof(ft)); GetSystemTimeAsFileTime(&ft.ft); // to microseconds ft.tm /= 10; // convert to unix format // number of microseconds intervals between the 1st january 1601 and the 1st january 1970 (369 years + 89 leap days) const unsigned __int64 deltaEpoch = 11644473600000000ull; const unsigned __int64 microSecondsToSeconds = 1000000ull; tp->tv_usec = ft.tm % microSecondsToSeconds; tp->tv_sec = (ft.tm - deltaEpoch) / microSecondsToSeconds; // see man gettimeofday: timezone is deprecated and expected to be NULL (void)tz; return 0; } micropython-1.12/ports/windows/msvc/paths.props000066400000000000000000000043331357706137100220420ustar00rootroot00000000000000 True $([System.IO.Path]::GetFullPath(`$(MSBuildThisFileDirectory)..\..\..`))\ $(PyBaseDir)ports\windows\ $(PyWinDir)build\ $(PyWinDir) $(PyIncDirs);$(PyBaseDir);$(PyWinDir);$(PyBuildDir);$(PyWinDir)msvc $(Platform) $(Configuration) $(PyBuildDir)$(PyConfiguration)$(PyPlatform)\ $(PyOutDir)obj\ micropython-1.12/ports/windows/msvc/release.props000066400000000000000000000012341357706137100223400ustar00rootroot00000000000000 false true true true true micropython-1.12/ports/windows/msvc/sources.props000066400000000000000000000026651357706137100224140ustar00rootroot00000000000000 micropython-1.12/ports/windows/msvc/sys/000077500000000000000000000000001357706137100204515ustar00rootroot00000000000000micropython-1.12/ports/windows/msvc/sys/time.h000066400000000000000000000026131357706137100215620ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_WINDOWS_MSVC_SYS_TIME_H #define MICROPY_INCLUDED_WINDOWS_MSVC_SYS_TIME_H // Get the definitions for timeval etc #include #endif // MICROPY_INCLUDED_WINDOWS_MSVC_SYS_TIME_H micropython-1.12/ports/windows/msvc/unistd.h000066400000000000000000000030741357706137100213160ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_WINDOWS_MSVC_UNISTD_H #define MICROPY_INCLUDED_WINDOWS_MSVC_UNISTD_H // There's no unistd.h, but this is the equivalent #include #define F_OK 0 #define W_OK 2 #define R_OK 4 #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 #define SEEK_CUR 1 #define SEEK_END 2 #define SEEK_SET 0 #endif // MICROPY_INCLUDED_WINDOWS_MSVC_UNISTD_H micropython-1.12/ports/windows/realpath.c000066400000000000000000000043461357706137100206360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include // Make sure a path only has forward slashes. char *to_unix_path(char *p) { if (p != NULL) { char *pp = p; while (*pp != 0) { if (*pp == '\\') *pp = '/'; ++pp; } } return p; } // Implement realpath() using _fullpath and make it use the same error codes as realpath() on unix. // Also have it return a path with forward slashes only as some code relies on this, // but _fullpath() returns backward slashes no matter what. char *realpath(const char *path, char *resolved_path) { char *ret = NULL; if (path == NULL) { errno = EINVAL; } else if (access(path, R_OK) == 0) { ret = resolved_path; if (ret == NULL) ret = malloc(_MAX_PATH); if (ret == NULL) { errno = ENOMEM; } else { ret = _fullpath(ret, path, _MAX_PATH); if (ret == NULL) errno = EIO; } } return to_unix_path(ret); } micropython-1.12/ports/windows/realpath.h000066400000000000000000000026251357706137100206410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_WINDOWS_REALPATH_H #define MICROPY_INCLUDED_WINDOWS_REALPATH_H extern char *realpath(const char *path, char *resolved_path); #endif // MICROPY_INCLUDED_WINDOWS_REALPATH_H micropython-1.12/ports/windows/sleep.c000066400000000000000000000044761357706137100201520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include HANDLE waitTimer = NULL; void init_sleep(void) { waitTimer = CreateWaitableTimer(NULL, TRUE, NULL); } void deinit_sleep(void) { if (waitTimer != NULL) { CloseHandle(waitTimer); waitTimer = NULL; } } int usleep_impl(__int64 usec) { if (waitTimer == NULL) { errno = EAGAIN; return -1; } if (usec < 0 || usec > LLONG_MAX / 10) { errno = EINVAL; return -1; } LARGE_INTEGER ft; ft.QuadPart = -10 * usec; // 100 nanosecond interval, negative value = relative time if (SetWaitableTimer(waitTimer, &ft, 0, NULL, NULL, 0) == 0) { errno = EINVAL; return -1; } if (WaitForSingleObject(waitTimer, INFINITE) != WAIT_OBJECT_0) { errno = EAGAIN; return -1; } return 0; } #ifdef _MSC_VER // mingw and the likes provide their own usleep() int usleep(__int64 usec) { return usleep_impl(usec); } #endif void msec_sleep(double msec) { const double usec = msec * 1000.0; usleep_impl(usec > (double)LLONG_MAX ? LLONG_MAX : (__int64)usec); } micropython-1.12/ports/windows/sleep.h000066400000000000000000000027071357706137100201520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_WINDOWS_SLEEP_H #define MICROPY_INCLUDED_WINDOWS_SLEEP_H void init_sleep(void); void deinit_sleep(void); void msec_sleep(double msec); #ifdef _MSC_VER int usleep(__int64 usec); #endif #endif // MICROPY_INCLUDED_WINDOWS_SLEEP_H micropython-1.12/ports/windows/windows_mphal.c000066400000000000000000000165221357706137100217100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #include "py/mphal.h" #include #include #include HANDLE std_in = NULL; HANDLE con_out = NULL; DWORD orig_mode = 0; STATIC void assure_stdin_handle() { if (!std_in) { std_in = GetStdHandle(STD_INPUT_HANDLE); assert(std_in != INVALID_HANDLE_VALUE); } } STATIC void assure_conout_handle() { if (!con_out) { con_out = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); assert(con_out != INVALID_HANDLE_VALUE); } } void mp_hal_stdio_mode_raw(void) { assure_stdin_handle(); GetConsoleMode(std_in, &orig_mode); DWORD mode = orig_mode; mode &= ~ENABLE_ECHO_INPUT; mode &= ~ENABLE_LINE_INPUT; mode &= ~ENABLE_PROCESSED_INPUT; SetConsoleMode(std_in, mode); } void mp_hal_stdio_mode_orig(void) { assure_stdin_handle(); SetConsoleMode(std_in, orig_mode); } // Handler to be installed by SetConsoleCtrlHandler, currently used only to handle Ctrl-C. // This handler has to be installed just once (this has to be done elswhere in init code). // Previous versions of the mp_hal code would install a handler whenever Ctrl-C input is // allowed and remove the handler again when it is not. That is not necessary though (1), // and it might introduce problems (2) because console notifications are delivered to the // application in a separate thread. // (1) mp_hal_set_interrupt_char effectively enables/disables processing of Ctrl-C via the // ENABLE_PROCESSED_INPUT flag so in raw mode console_sighandler won't be called. // (2) if mp_hal_set_interrupt_char would remove the handler while Ctrl-C was issued earlier, // the thread created for handling it might not be running yet so we'd miss the notification. BOOL WINAPI console_sighandler(DWORD evt) { if (evt == CTRL_C_EVENT) { if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) { // this is the second time we are called, so die straight away exit(1); } mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); return TRUE; } return FALSE; } void mp_hal_set_interrupt_char(char c) { assure_stdin_handle(); if (c == CHAR_CTRL_C) { DWORD mode; GetConsoleMode(std_in, &mode); mode |= ENABLE_PROCESSED_INPUT; SetConsoleMode(std_in, mode); } else { DWORD mode; GetConsoleMode(std_in, &mode); mode &= ~ENABLE_PROCESSED_INPUT; SetConsoleMode(std_in, mode); } } void mp_hal_move_cursor_back(uint pos) { if (!pos) { return; } assure_conout_handle(); CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(con_out, &info); info.dwCursorPosition.X -= (short)pos; // Move up a line if needed. while (info.dwCursorPosition.X < 0) { info.dwCursorPosition.X = info.dwSize.X + info.dwCursorPosition.X; info.dwCursorPosition.Y -= 1; } // Caller requested to move out of the screen. That's not possible so just clip, // it's the caller's responsibility to not let this happen. if (info.dwCursorPosition.Y < 0) { info.dwCursorPosition.X = 0; info.dwCursorPosition.Y = 0; } SetConsoleCursorPosition(con_out, info.dwCursorPosition); } void mp_hal_erase_line_from_cursor(uint n_chars_to_erase) { assure_conout_handle(); CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(con_out, &info); DWORD written; FillConsoleOutputCharacter(con_out, ' ', n_chars_to_erase, info.dwCursorPosition, &written); FillConsoleOutputAttribute(con_out, info.wAttributes, n_chars_to_erase, info.dwCursorPosition, &written); } typedef struct item_t { WORD vkey; const char *seq; } item_t; // map virtual key codes to VT100 escape sequences STATIC item_t keyCodeMap[] = { {VK_UP, "[A"}, {VK_DOWN, "[B"}, {VK_RIGHT, "[C"}, {VK_LEFT, "[D"}, {VK_HOME, "[H"}, {VK_END, "[F"}, {VK_DELETE, "[3~"}, {0, ""} //sentinel }; STATIC const char *cur_esc_seq = NULL; STATIC int esc_seq_process_vk(int vk) { for (item_t *p = keyCodeMap; p->vkey != 0; ++p) { if (p->vkey == vk) { cur_esc_seq = p->seq; return 27; // ESC, start of escape sequence } } return 0; // nothing found } STATIC int esc_seq_chr() { if (cur_esc_seq) { const char c = *cur_esc_seq++; if (c) { return c; } cur_esc_seq = NULL; } return 0; } int mp_hal_stdin_rx_chr(void) { // currently processing escape seq? const int ret = esc_seq_chr(); if (ret) { return ret; } // poll until key which we handle is pressed assure_stdin_handle(); DWORD num_read; INPUT_RECORD rec; for (;;) { if (!ReadConsoleInput(std_in, &rec, 1, &num_read) || !num_read) { return CHAR_CTRL_C; // EOF, ctrl-D } if (rec.EventType != KEY_EVENT || !rec.Event.KeyEvent.bKeyDown) { // only want key down events continue; } const char c = rec.Event.KeyEvent.uChar.AsciiChar; if (c) { // plain ascii char, return it return c; } const int ret = esc_seq_process_vk(rec.Event.KeyEvent.wVirtualKeyCode); if (ret) { return ret; } } } void mp_hal_stdout_tx_strn(const char *str, size_t len) { write(1, str, len); } void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { mp_hal_stdout_tx_strn(str, len); } void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } mp_uint_t mp_hal_ticks_ms(void) { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000 + tv.tv_usec / 1000; } mp_uint_t mp_hal_ticks_us(void) { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000 + tv.tv_usec; } mp_uint_t mp_hal_ticks_cpu(void) { LARGE_INTEGER value; QueryPerformanceCounter(&value); #ifdef _WIN64 return value.QuadPart; #else return value.LowPart; #endif } micropython-1.12/ports/windows/windows_mphal.h000066400000000000000000000027211357706137100217110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "sleep.h" #include "ports/unix/mphalport.h" #define MICROPY_HAL_HAS_VT100 (0) void mp_hal_move_cursor_back(unsigned int pos); void mp_hal_erase_line_from_cursor(unsigned int n_chars_to_erase); #undef mp_hal_ticks_cpu mp_uint_t mp_hal_ticks_cpu(void); micropython-1.12/ports/zephyr/000077500000000000000000000000001357706137100165125ustar00rootroot00000000000000micropython-1.12/ports/zephyr/.gitignore000066400000000000000000000000101357706137100204710ustar00rootroot00000000000000outdir/ micropython-1.12/ports/zephyr/CMakeLists.txt000066400000000000000000000015541357706137100212570ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.8) include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) project(NONE) target_sources(app PRIVATE src/zephyr_start.c src/zephyr_getchar.c) add_library(libmicropython STATIC IMPORTED) set_target_properties(libmicropython PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libmicropython.a) target_link_libraries(app PUBLIC libmicropython) zephyr_get_include_directories_for_lang_as_string(C includes) zephyr_get_system_include_directories_for_lang_as_string(C system_includes) zephyr_get_compile_definitions_for_lang_as_string(C definitions) zephyr_get_compile_options_for_lang_as_string(C options) add_custom_target( outputexports COMMAND echo CC="${CMAKE_C_COMPILER}" COMMAND echo AR="${CMAKE_AR}" COMMAND echo Z_CFLAGS=${system_includes} ${includes} ${definitions} ${options} VERBATIM USES_TERMINAL ) micropython-1.12/ports/zephyr/Kbuild000066400000000000000000000001051357706137100176430ustar00rootroot00000000000000#subdir-ccflags-y += -I$(SOURCE_DIR)/../mylib/include obj-y += src/ micropython-1.12/ports/zephyr/Makefile000066400000000000000000000064661357706137100201660ustar00rootroot00000000000000# # This is the main Makefile, which uses MicroPython build system, # but Zephyr arch-specific toolchain and target-specific flags. # This Makefile builds MicroPython as a library, and then calls # recursively Makefile.zephyr to build complete application binary # using Zephyr build system. # # To build a "minimal" configuration, use "make-minimal" wrapper. BOARD ?= qemu_x86 CONF_FILE = prj_$(BOARD)_merged.conf OUTDIR_PREFIX = $(BOARD) # Default heap size is 16KB, which is on conservative side, to let # it build for smaller boards, but it won't be enough for larger # applications, and will need to be increased. MICROPY_HEAP_SIZE = 16384 FROZEN_DIR = scripts # Default target all: include ../../py/mkenv.mk include $(TOP)/py/py.mk # Zephyr (generated) config files - must be defined before include below Z_EXPORTS = outdir/$(OUTDIR_PREFIX)/Makefile.export ifneq ($(MAKECMDGOALS), clean) include $(Z_EXPORTS) endif INC += -I. INC += -I$(TOP) INC += -I$(BUILD) INC += -I$(ZEPHYR_BASE)/net/ip INC += -I$(ZEPHYR_BASE)/net/ip/contiki INC += -I$(ZEPHYR_BASE)/net/ip/contiki/os SRC_C = main.c \ help.c \ modusocket.c \ modutime.c \ modzephyr.c \ modzsensor.c \ modmachine.c \ machine_i2c.c \ machine_pin.c \ uart_core.c \ lib/utils/stdout_helpers.c \ lib/utils/printf.c \ lib/utils/pyexec.c \ lib/utils/interrupt_char.c \ lib/mp-readline/readline.c \ $(SRC_MOD) # List of sources for qstr extraction SRC_QSTR += $(SRC_C) OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) CFLAGS = $(Z_CFLAGS) \ -std=gnu99 -fomit-frame-pointer -DNDEBUG -DMICROPY_HEAP_SIZE=$(MICROPY_HEAP_SIZE) $(CFLAGS_EXTRA) $(INC) include $(TOP)/py/mkrules.mk GENERIC_TARGETS = all zephyr run qemu qemugdb flash debug debugserver \ ram_report rom_report KCONFIG_TARGETS = \ initconfig config nconfig menuconfig xconfig gconfig \ oldconfig silentoldconfig defconfig savedefconfig \ allnoconfig allyesconfig alldefconfig randconfig \ listnewconfig olddefconfig CLEAN_TARGETS = pristine mrproper $(GENERIC_TARGETS): $(LIBMICROPYTHON) $(CLEAN_TARGETS): clean $(GENERIC_TARGETS) $(KCONFIG_TARGETS) $(CLEAN_TARGETS): $(MAKE) -C outdir/$(BOARD) $@ $(LIBMICROPYTHON): | $(Z_EXPORTS) build/genhdr/qstr.i.last: | $(Z_EXPORTS) # If we recreate libmicropython, also cause zephyr.bin relink LIBMICROPYTHON_EXTRA_CMD = -$(RM) -f outdir/$(OUTDIR_PREFIX)/zephyr.lnk # MicroPython's global clean cleans everything, fast CLEAN_EXTRA = outdir libmicropython.a prj_*_merged.conf # Clean Zephyr things in Zephyr way z_clean: $(MAKE) -f Makefile.zephyr BOARD=$(BOARD) clean # This rule is for prj_$(BOARD)_merged.conf, not $(CONF_FILE), which # can be overriden. # prj_$(BOARD).conf is optional, that's why it's resolved with $(wildcard) # function. prj_$(BOARD)_merged.conf: prj_base.conf $(wildcard prj_$(BOARD).conf) $(PYTHON) makeprj.py prj_base.conf prj_$(BOARD).conf $@ test: cd $(TOP)/tests && ./run-tests --target minimal --device "execpty:make -C ../ports/zephyr run BOARD=$(BOARD) QEMU_PTY=1" cmake: outdir/$(BOARD)/Makefile outdir/$(BOARD)/Makefile: $(CONF_FILE) mkdir -p outdir/$(BOARD) && cmake -DBOARD=$(BOARD) -DCONF_FILE=$(CONF_FILE) -Boutdir/$(BOARD) -H. $(Z_EXPORTS): outdir/$(BOARD)/Makefile make --no-print-directory -C outdir/$(BOARD) outputexports CMAKE_COMMAND=: >$@ make -C outdir/$(BOARD) syscall_macros_h_target syscall_list_h_target kobj_types_h_target micropython-1.12/ports/zephyr/Makefile.zephyr000066400000000000000000000017131357706137100214740ustar00rootroot00000000000000# # Copyright (c) 2016 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # KERNEL_TYPE = micro # BOARD must be passed on command line from main Makefile #BOARD = CONF_FILE = prj.conf QEMU_NET = 1 #export SOURCE_DIR = $(ZEPHYR_BASE)/samples/static_lib/hello_world export LDFLAGS_zephyr += -L$(CURDIR) export ALL_LIBS += micropython include ${ZEPHYR_BASE}/Makefile.inc ifeq ($(QEMU_NET), 1) include ${ZEPHYR_BASE}/samples/net/common/Makefile.ipstack endif micropython-1.12/ports/zephyr/README.md000066400000000000000000000101501357706137100177660ustar00rootroot00000000000000MicroPython port to Zephyr RTOS =============================== This is an work-in-progress port of MicroPython to Zephyr RTOS (http://zephyrproject.org). This port requires Zephyr version 1.8 or higher. All boards supported by Zephyr (with standard level of features support, like UART console) should work with MicroPython (but not all were tested). Features supported at this time: * REPL (interactive prompt) over Zephyr UART console. * `utime` module for time measurements and delays. * `machine.Pin` class for GPIO control. * `machine.I2C` class for I2C control. * `usocket` module for networking (IPv4/IPv6). * "Frozen modules" support to allow to bundle Python modules together with firmware. Including complete applications, including with run-on-boot capability. Over time, bindings for various Zephyr subsystems may be added. Building -------- Follow to Zephyr web site for Getting Started instruction of installing Zephyr SDK, getting Zephyr source code, and setting up development environment. (Direct link: https://www.zephyrproject.org/doc/getting_started/getting_started.html). You may want to build Zephyr's own sample applications to make sure your setup is correct. To build MicroPython port, in the port subdirectory (zephyr/), run: make BOARD= If you don't specify BOARD, the default is `qemu_x86` (x86 target running in QEMU emulator). Consult Zephyr documentation above for the list of supported boards. Running ------- To run the resulting firmware in QEMU (for BOARDs like qemu_x86, qemu_cortex_m3): make run With the default configuration, networking is now enabled, so you need to follow instructions in https://wiki.zephyrproject.org/view/Networking-with-Qemu to setup host side of TAP/SLIP networking. If you get error like: could not connect serial device to character backend 'unix:/tmp/slip.sock' it's a sign that you didn't followed instructions above. If you would like to just run it quickly without extra setup, see "minimal" build below. For deploying/flashing a firmware on a real board, follow Zephyr documentation for a given board, including known issues for that board (if any). (Mind again that networking is enabled for the default build, so you should know if there're any special requirements in that regard, cf. for example QEMU networking requirements above; real hardware boards generally should not have any special requirements, unless there're known issues). Quick example ------------- To blink an LED: import time from machine import Pin LED = Pin(("GPIO_1", 21), Pin.OUT) while True: LED.value(1) time.sleep(0.5) LED.value(0) time.sleep(0.5) The above code uses an LED location for a FRDM-K64F board (port B, pin 21; following Zephyr conventions port are identified by "GPIO_x", where *x* starts from 0). You will need to adjust it for another board (using board's reference materials). To execute the above sample, copy it to clipboard, in MicroPython REPL enter "paste mode" using Ctrl+E, paste clipboard, press Ctrl+D to finish paste mode and start execution. Example of using I2C to scan for I2C slaves: from machine import I2C i2c = I2C("I2C_0") i2c.scan() Minimal build ------------- MicroPython is committed to maintain minimal binary size for Zephyr port below 128KB, as long as Zephyr project is committed to maintain stable minimal size of their kernel (which they appear to be). Note that at such size, there is no support for any Zephyr features beyond REPL over UART, and only very minimal set of builtin Python modules is available. Thus, this build is more suitable for code size control and quick demonstrations on smaller systems. It's also suitable for careful enabling of features one by one to achieve needed functionality and code size. This is in the contrast to the "default" build, which may get more and more features enabled over time. To make a minimal build: ./make-minimal BOARD= To run a minimal build in QEMU without requiring TAP networking setup run the following after you built image with the previous command: ./make-minimal BOARD= run micropython-1.12/ports/zephyr/help.c000066400000000000000000000032541357706137100176120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" const char zephyr_help_text[] = "Welcome to MicroPython!\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" " CTRL-B -- on a blank line, enter normal REPL mode\n" " CTRL-C -- interrupt a running program\n" " CTRL-D -- on a blank line, do a soft reset of the board\n" " CTRL-E -- on a blank line, enter paste mode\n" "\n" "For further help on a specific object, type help(obj)\n" ; micropython-1.12/ports/zephyr/machine_i2c.c000066400000000000000000000111611357706137100210170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014, 2015 Damien P. George * Copyright (c) 2019, NXP * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" #include "py/mperrno.h" #include "extmod/machine_i2c.h" STATIC const mp_obj_type_t machine_hard_i2c_type; typedef struct _machine_hard_i2c_obj_t { mp_obj_base_t base; struct device *dev; bool restart; } machine_hard_i2c_obj_t; STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hard_i2c_obj_t *self = self_in; mp_printf(print, "%s", self->dev->config->name); } mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); const char *dev_name = mp_obj_str_get_str(args[ARG_id].u_obj); struct device *dev = device_get_binding(dev_name); if (dev == NULL) { mp_raise_ValueError("device not found"); } if ((args[ARG_scl].u_obj != MP_OBJ_NULL) || (args[ARG_sda].u_obj != MP_OBJ_NULL)) { mp_raise_NotImplementedError("explicit choice of scl/sda is not implemented"); } if ((args[ARG_freq].u_obj != MP_OBJ_NULL)) { mp_raise_NotImplementedError("explicit choice of freq is not implemented"); } if ((args[ARG_timeout].u_obj != MP_OBJ_NULL)) { mp_raise_NotImplementedError("explicit choice of timeout is not implemented"); } machine_hard_i2c_obj_t *self = m_new_obj(machine_hard_i2c_obj_t); self->base.type = &machine_hard_i2c_type; self->dev = dev; self->restart = false; return MP_OBJ_FROM_PTR(self); } STATIC int machine_hard_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) { machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)self_in; struct i2c_msg msg; int ret; msg.buf = (u8_t*)buf; msg.len = len; msg.flags = 0; if (flags & MP_MACHINE_I2C_FLAG_READ) { msg.flags |= I2C_MSG_READ; } else { msg.flags |= I2C_MSG_WRITE; } if (self->restart) { msg.flags |= I2C_MSG_RESTART; } if (flags & MP_MACHINE_I2C_FLAG_STOP) { msg.flags |= I2C_MSG_STOP; self->restart = false; } else { self->restart = true; } ret = i2c_transfer(self->dev, &msg, 1, addr); return (ret < 0) ? -MP_EIO : len; } STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { .transfer = mp_machine_i2c_transfer_adaptor, .transfer_single = machine_hard_i2c_transfer_single, }; STATIC const mp_obj_type_t machine_hard_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, .print = machine_hard_i2c_print, .make_new = machine_hard_i2c_make_new, .protocol = &machine_hard_i2c_p, .locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict, }; micropython-1.12/ports/zephyr/machine_pin.c000066400000000000000000000160241357706137100211330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014, 2015 Damien P. George * Copyright (c) 2016 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" #include "modmachine.h" const mp_obj_base_t machine_pin_obj_template = {&machine_pin_type}; STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pin_obj_t *self = self_in; mp_printf(print, "", self->port, self->pin); } // pin.init(mode, pull=None, *, value) STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_pull, ARG_value }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get io mode uint mode = args[ARG_mode].u_int; // get pull mode uint pull = GPIO_PUD_NORMAL; if (args[ARG_pull].u_obj != mp_const_none) { pull = mp_obj_get_int(args[ARG_pull].u_obj); } int ret = gpio_pin_configure(self->port, self->pin, mode | pull); if (ret) { mp_raise_ValueError("invalid pin"); } // get initial value if (args[ARG_value].u_obj != MP_OBJ_NULL) { (void)gpio_pin_write(self->port, self->pin, mp_obj_is_true(args[ARG_value].u_obj)); } return mp_const_none; } // constructor(drv_name, pin, ...) mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get the wanted port if (!mp_obj_is_type(args[0], &mp_type_tuple)) { mp_raise_ValueError("Pin id must be tuple of (\"GPIO_x\", pin#)"); } mp_obj_t *items; mp_obj_get_array_fixed_n(args[0], 2, &items); const char *drv_name = mp_obj_str_get_str(items[0]); int wanted_pin = mp_obj_get_int(items[1]); struct device *wanted_port = device_get_binding(drv_name); if (!wanted_port) { mp_raise_ValueError("invalid port"); } machine_pin_obj_t *pin = m_new_obj(machine_pin_obj_t); pin->base = machine_pin_obj_template; pin->port = wanted_port; pin->pin = wanted_pin; if (n_args > 1 || n_kw > 0) { // pin mode given, so configure this GPIO mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); machine_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); } return (mp_obj_t)pin; } // fast method for getting/setting pin value STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); machine_pin_obj_t *self = self_in; if (n_args == 0) { u32_t pin_val; (void)gpio_pin_read(self->port, self->pin, &pin_val); return MP_OBJ_NEW_SMALL_INT(pin_val); } else { (void)gpio_pin_write(self->port, self->pin, mp_obj_is_true(args[0])); return mp_const_none; } } // pin.init(mode, pull) STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); } MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); // pin.value([value]) STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { return machine_pin_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); STATIC mp_obj_t machine_pin_off(mp_obj_t self_in) { machine_pin_obj_t *self = self_in; (void)gpio_pin_write(self->port, self->pin, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_off_obj, machine_pin_off); STATIC mp_obj_t machine_pin_on(mp_obj_t self_in) { machine_pin_obj_t *self = self_in; (void)gpio_pin_write(self->port, self->pin, 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on); STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; machine_pin_obj_t *self = self_in; switch (request) { case MP_PIN_READ: { u32_t pin_val; gpio_pin_read(self->port, self->pin, &pin_val); return pin_val; } case MP_PIN_WRITE: { gpio_pin_write(self->port, self->pin, arg); return 0; } } return -1; } STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) }, // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_DIR_IN) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_DIR_OUT) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PUD_PULL_UP) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PUD_PULL_DOWN) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); STATIC const mp_pin_p_t machine_pin_pin_p = { .ioctl = machine_pin_ioctl, }; const mp_obj_type_t machine_pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, .print = machine_pin_print, .make_new = mp_pin_make_new, .call = machine_pin_call, .protocol = &machine_pin_pin_p, .locals_dict = (mp_obj_t)&machine_pin_locals_dict, }; micropython-1.12/ports/zephyr/main.c000066400000000000000000000114561357706137100176110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016-2017 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #ifdef CONFIG_NETWORKING #include #endif #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" #include "py/gc.h" #include "py/stackctrl.h" #include "lib/utils/pyexec.h" #include "lib/mp-readline/readline.h" #ifdef TEST #include "lib/upytesthelper/upytesthelper.h" #include "lib/tinytest/tinytest.c" #include "lib/upytesthelper/upytesthelper.c" #include TEST #endif static char heap[MICROPY_HEAP_SIZE]; void init_zephyr(void) { // We now rely on CONFIG_NET_APP_SETTINGS to set up bootstrap // network addresses. #if 0 #ifdef CONFIG_NETWORKING if (net_if_get_default() == NULL) { // If there's no default networking interface, // there's nothing to configure. return; } #endif #ifdef CONFIG_NET_IPV4 static struct in_addr in4addr_my = {{{192, 0, 2, 1}}}; net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my, NET_ADDR_MANUAL, 0); static struct in_addr in4netmask_my = {{{255, 255, 255, 0}}}; net_if_ipv4_set_netmask(net_if_get_default(), &in4netmask_my); static struct in_addr in4gw_my = {{{192, 0, 2, 2}}}; net_if_ipv4_set_gw(net_if_get_default(), &in4gw_my); #endif #ifdef CONFIG_NET_IPV6 // 2001:db8::1 static struct in6_addr in6addr_my = {{{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}}; net_if_ipv6_addr_add(net_if_get_default(), &in6addr_my, NET_ADDR_MANUAL, 0); #endif #endif } int real_main(void) { mp_stack_ctrl_init(); // Make MicroPython's stack limit somewhat smaller than full stack available mp_stack_set_limit(CONFIG_MAIN_STACK_SIZE - 512); init_zephyr(); #ifdef TEST static const char *argv[] = {"test"}; upytest_set_heap(heap, heap + sizeof(heap)); int r = tinytest_main(1, argv, groups); printf("status: %d\n", r); #endif soft_reset: #if MICROPY_ENABLE_GC gc_init(heap, heap + sizeof(heap)); #endif mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) mp_obj_list_init(mp_sys_argv, 0); #if MICROPY_MODULE_FROZEN pyexec_frozen_module("main.py"); #endif for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } printf("soft reboot\n"); goto soft_reset; return 0; } void gc_collect(void) { // WARNING: This gc_collect implementation doesn't try to get root // pointers from CPU registers, and thus may function incorrectly. void *dummy; gc_collect_start(); gc_collect_root(&dummy, ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); gc_collect_end(); //gc_dump_info(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); NORETURN void nlr_jump_fail(void *val) { while (1); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error("Assertion failed"); } #endif micropython-1.12/ports/zephyr/make-bin-testsuite000077500000000000000000000014741357706137100221600ustar00rootroot00000000000000#!/bin/sh # # This is a wrapper for make to build a binary with builtin testsuite. # It should be run just like make (i.e. extra vars can be passed on the # command line, etc.), e.g.: # # ./make-bin-testsuite BOARD=qemu_cortex_m3 # ./make-bin-testsuite BOARD=qemu_cortex_m3 run # (cd ../../tests; ./run-tests --write-exp) (cd ../../tests; ./run-tests --list-tests --target=minimal \ -e async -e intbig -e int_big -e builtin_help -e memstats -e bytes_compare3 -e class_reverse_op \ -e /set -e frozenset -e complex -e const -e native -e viper \ -e 'float_divmod\.' -e float_parse_doubleprec -e float/true_value -e float/types \ | ../tools/tinytest-codegen.py --stdin) > bin-testsuite.c make \ CFLAGS_EXTRA='-DMP_CONFIGFILE="" -DTEST=\"bin-testsuite.c\" -DNO_FORKING' \ "$@" micropython-1.12/ports/zephyr/make-minimal000077500000000000000000000006311357706137100210010ustar00rootroot00000000000000#!/bin/sh # # This is a wrapper for make to build a "minimal" Zephyr port. # It should be run just like make (i.e. extra vars can be passed on the # command line, etc.), e.g.: # # ./make-minimal BOARD=qemu_cortex_m3 # ./make-minimal BOARD=qemu_cortex_m3 run # make \ CONF_FILE=prj_minimal.conf \ CFLAGS_EXTRA='-DMP_CONFIGFILE=""' \ FROZEN_DIR= \ QEMU_NET=0 \ "$@" micropython-1.12/ports/zephyr/makeprj.py000066400000000000000000000012201357706137100205100ustar00rootroot00000000000000#!/usr/bin/env python3 import sys import os import hashlib def hash_file(fname): if not os.path.exists(fname): return b"" hasher = hashlib.md5() with open(fname, "rb") as f: hasher.update(f.read()) return hasher.digest() old_digest = hash_file(sys.argv[3]) with open(sys.argv[3] + ".tmp", "wb") as f: f.write(open(sys.argv[1], "rb").read()) if os.path.exists(sys.argv[2]): f.write(open(sys.argv[2], "rb").read()) new_digest = hash_file(sys.argv[3] + ".tmp") if new_digest != old_digest: print("Replacing") os.rename(sys.argv[3] + ".tmp", sys.argv[3]) else: os.remove(sys.argv[3] + ".tmp") micropython-1.12/ports/zephyr/modmachine.c000066400000000000000000000055471357706137100207750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * Copyright (c) 2016 Paul Sokolovsky * Copyright (c) 2016 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/obj.h" #include "py/runtime.h" #include "extmod/machine_mem.h" #include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "modmachine.h" #if MICROPY_PY_MACHINE STATIC mp_obj_t machine_reset(void) { sys_reboot(SYS_REBOOT_COLD); // Won't get here, Zephyr has infiniloop on its side return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); STATIC mp_obj_t machine_reset_cause(void) { printf("Warning: %s is not implemented\n", __func__); return MP_OBJ_NEW_SMALL_INT(42); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, #ifdef CONFIG_REBOOT { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, // reset causes /*{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) },*/ }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); const mp_obj_module_t mp_module_machine = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&machine_module_globals, }; #endif // MICROPY_PY_MACHINE micropython-1.12/ports/zephyr/modmachine.h000066400000000000000000000005711357706137100207720ustar00rootroot00000000000000#ifndef MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H #define MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H #include "py/obj.h" extern const mp_obj_type_t machine_pin_type; MP_DECLARE_CONST_FUN_OBJ_0(machine_info_obj); typedef struct _machine_pin_obj_t { mp_obj_base_t base; struct device *port; uint32_t pin; } machine_pin_obj_t; #endif // MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H micropython-1.12/ports/zephyr/modusocket.c000066400000000000000000000357421357706137100210460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #ifdef MICROPY_PY_USOCKET #include "py/runtime.h" #include "py/stream.h" #include #include // Zephyr's generated version header #include #include #include #include #ifdef CONFIG_NET_SOCKETS #include #endif #define DEBUG_PRINT 0 #if DEBUG_PRINT // print debugging info #define DEBUG_printf printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif typedef struct _socket_obj_t { mp_obj_base_t base; int ctx; #define STATE_NEW 0 #define STATE_CONNECTING 1 #define STATE_CONNECTED 2 #define STATE_PEER_CLOSED 3 int8_t state; } socket_obj_t; STATIC const mp_obj_type_t socket_type; // Helper functions #define RAISE_ERRNO(x) { int _err = x; if (_err < 0) mp_raise_OSError(-_err); } #define RAISE_SOCK_ERRNO(x) { if ((int)(x) == -1) mp_raise_OSError(errno); } STATIC void socket_check_closed(socket_obj_t *socket) { if (socket->ctx == -1) { // already closed mp_raise_OSError(EBADF); } } STATIC void parse_inet_addr(socket_obj_t *socket, mp_obj_t addr_in, struct sockaddr *sockaddr) { // We employ the fact that port and address offsets are the same for IPv4 & IPv6 struct sockaddr_in *sockaddr_in = (struct sockaddr_in*)sockaddr; mp_obj_t *addr_items; mp_obj_get_array_fixed_n(addr_in, 2, &addr_items); sockaddr_in->sin_family = net_context_get_family((void*)socket->ctx); RAISE_ERRNO(net_addr_pton(sockaddr_in->sin_family, mp_obj_str_get_str(addr_items[0]), &sockaddr_in->sin_addr)); sockaddr_in->sin_port = htons(mp_obj_get_int(addr_items[1])); } STATIC mp_obj_t format_inet_addr(struct sockaddr *addr, mp_obj_t port) { // We employ the fact that port and address offsets are the same for IPv4 & IPv6 struct sockaddr_in6 *sockaddr_in6 = (struct sockaddr_in6*)addr; char buf[40]; net_addr_ntop(addr->sa_family, &sockaddr_in6->sin6_addr, buf, sizeof(buf)); mp_obj_tuple_t *tuple = mp_obj_new_tuple(addr->sa_family == AF_INET ? 2 : 4, NULL); tuple->items[0] = mp_obj_new_str(buf, strlen(buf)); // We employ the fact that port offset is the same for IPv4 & IPv6 // not filled in //tuple->items[1] = mp_obj_new_int(ntohs(((struct sockaddr_in*)addr)->sin_port)); tuple->items[1] = port; if (addr->sa_family == AF_INET6) { tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); // flow_info tuple->items[3] = MP_OBJ_NEW_SMALL_INT(sockaddr_in6->sin6_scope_id); } return MP_OBJ_FROM_PTR(tuple); } socket_obj_t *socket_new(void) { socket_obj_t *socket = m_new_obj_with_finaliser(socket_obj_t); socket->base.type = (mp_obj_t)&socket_type; socket->state = STATE_NEW; return socket; } // Methods STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { socket_obj_t *self = self_in; if (self->ctx == -1) { mp_printf(print, ""); } else { struct net_context *ctx = (void*)self->ctx; mp_printf(print, "", ctx, net_context_get_type(ctx)); } } STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 4, false); socket_obj_t *socket = socket_new(); int family = AF_INET; int socktype = SOCK_STREAM; int proto = -1; if (n_args >= 1) { family = mp_obj_get_int(args[0]); if (n_args >= 2) { socktype = mp_obj_get_int(args[1]); if (n_args >= 3) { proto = mp_obj_get_int(args[2]); } } } if (proto == -1) { proto = IPPROTO_TCP; if (socktype != SOCK_STREAM) { proto = IPPROTO_UDP; } } socket->ctx = zsock_socket(family, socktype, proto); RAISE_SOCK_ERRNO(socket->ctx); return MP_OBJ_FROM_PTR(socket); } STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { socket_obj_t *socket = self_in; socket_check_closed(socket); struct sockaddr sockaddr; parse_inet_addr(socket, addr_in, &sockaddr); int res = zsock_bind(socket->ctx, &sockaddr, sizeof(sockaddr)); RAISE_SOCK_ERRNO(res); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { socket_obj_t *socket = self_in; socket_check_closed(socket); struct sockaddr sockaddr; parse_inet_addr(socket, addr_in, &sockaddr); int res = zsock_connect(socket->ctx, &sockaddr, sizeof(sockaddr)); RAISE_SOCK_ERRNO(res); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { socket_obj_t *socket = self_in; socket_check_closed(socket); mp_int_t backlog = mp_obj_get_int(backlog_in); int res = zsock_listen(socket->ctx, backlog); RAISE_SOCK_ERRNO(res); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); STATIC mp_obj_t socket_accept(mp_obj_t self_in) { socket_obj_t *socket = self_in; socket_check_closed(socket); struct sockaddr sockaddr; socklen_t addrlen = sizeof(sockaddr); int ctx = zsock_accept(socket->ctx, &sockaddr, &addrlen); socket_obj_t *socket2 = socket_new(); socket2->ctx = ctx; mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = MP_OBJ_FROM_PTR(socket2); // TODO client->items[1] = mp_const_none; return MP_OBJ_FROM_PTR(client); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); STATIC mp_uint_t sock_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { socket_obj_t *socket = self_in; if (socket->ctx == -1) { // already closed *errcode = EBADF; return MP_STREAM_ERROR; } ssize_t len = zsock_send(socket->ctx, buf, size, 0); if (len == -1) { *errcode = errno; return MP_STREAM_ERROR; } return len; } STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); int err = 0; mp_uint_t len = sock_write(self_in, bufinfo.buf, bufinfo.len, &err); if (len == MP_STREAM_ERROR) { mp_raise_OSError(err); } return mp_obj_new_int_from_uint(len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *errcode) { socket_obj_t *socket = self_in; if (socket->ctx == -1) { // already closed *errcode = EBADF; return MP_STREAM_ERROR; } ssize_t recv_len = zsock_recv(socket->ctx, buf, max_len, 0); if (recv_len == -1) { *errcode = errno; return MP_STREAM_ERROR; } return recv_len; } STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mp_int_t max_len = mp_obj_get_int(len_in); vstr_t vstr; // +1 to accommodate for trailing \0 vstr_init_len(&vstr, max_len + 1); int err; mp_uint_t len = sock_read(self_in, vstr.buf, max_len, &err); if (len == MP_STREAM_ERROR) { vstr_clear(&vstr); mp_raise_OSError(err); } if (len == 0) { vstr_clear(&vstr); return mp_const_empty_bytes; } vstr.len = len; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { (void)n_args; // always 4 mp_warning(MP_WARN_CAT(RuntimeWarning), "setsockopt() not implemented"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { (void)n_args; return args[0]; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile); STATIC mp_uint_t sock_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { socket_obj_t *socket = o_in; (void)arg; switch (request) { case MP_STREAM_CLOSE: if (socket->ctx != -1) { int res = zsock_close(socket->ctx); RAISE_SOCK_ERRNO(res); if (res == -1) { *errcode = errno; return MP_STREAM_ERROR; } socket->ctx = -1; } return 0; default: *errcode = MP_EINVAL; return MP_STREAM_ERROR; } } STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) }, }; STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); STATIC const mp_stream_p_t socket_stream_p = { .read = sock_read, .write = sock_write, .ioctl = sock_ioctl, }; STATIC const mp_obj_type_t socket_type = { { &mp_type_type }, .name = MP_QSTR_socket, .print = socket_print, .make_new = socket_make_new, .protocol = &socket_stream_p, .locals_dict = (mp_obj_t)&socket_locals_dict, }; // // getaddrinfo() implementation // typedef struct _getaddrinfo_state_t { mp_obj_t result; struct k_sem sem; mp_obj_t port; int status; } getaddrinfo_state_t; void dns_resolve_cb(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data) { getaddrinfo_state_t *state = user_data; DEBUG_printf("dns status: %d\n", status); if (info == NULL) { if (status == DNS_EAI_ALLDONE) { status = 0; } state->status = status; k_sem_give(&state->sem); return; } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(info->ai_family); // info->ai_socktype not filled tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM); // info->ai_protocol not filled tuple->items[2] = MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = format_inet_addr(&info->ai_addr, state->port); mp_obj_list_append(state->result, MP_OBJ_FROM_PTR(tuple)); } STATIC mp_obj_t mod_getaddrinfo(size_t n_args, const mp_obj_t *args) { mp_obj_t host_in = args[0], port_in = args[1]; const char *host = mp_obj_str_get_str(host_in); mp_int_t family = 0; if (n_args > 2) { family = mp_obj_get_int(args[2]); } getaddrinfo_state_t state; // Just validate that it's int (void)mp_obj_get_int(port_in); state.port = port_in; state.result = mp_obj_new_list(0, NULL); k_sem_init(&state.sem, 0, UINT_MAX); for (int i = 2; i--;) { int type = (family != AF_INET6 ? DNS_QUERY_TYPE_A : DNS_QUERY_TYPE_AAAA); RAISE_ERRNO(dns_get_addr_info(host, type, NULL, dns_resolve_cb, &state, 3000)); k_sem_take(&state.sem, K_FOREVER); if (family != 0) { break; } family = AF_INET6; } // Raise error only if there's nothing to return, otherwise // it may be IPv4 vs IPv6 differences. mp_int_t len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(state.result)); if (state.status != 0 && len == 0) { mp_raise_OSError(state.status); } return state.result; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_getaddrinfo_obj, 2, 3, mod_getaddrinfo); STATIC mp_obj_t pkt_get_info(void) { struct k_mem_slab *rx, *tx; struct net_buf_pool *rx_data, *tx_data; net_pkt_get_info(&rx, &tx, &rx_data, &tx_data); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(k_mem_slab_num_free_get(rx)); t->items[1] = MP_OBJ_NEW_SMALL_INT(k_mem_slab_num_free_get(tx)); t->items[2] = MP_OBJ_NEW_SMALL_INT(rx_data->avail_count); t->items[3] = MP_OBJ_NEW_SMALL_INT(tx_data->avail_count); return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(pkt_get_info_obj, pkt_get_info); STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, // objects { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, // class constants { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(AF_INET) }, { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(AF_INET6) }, { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SOCK_STREAM) }, { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SOCK_DGRAM) }, { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(1) }, { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(2) }, { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_getaddrinfo_obj) }, { MP_ROM_QSTR(MP_QSTR_pkt_get_info), MP_ROM_PTR(&pkt_get_info_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); const mp_obj_module_t mp_module_usocket = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, }; #endif // MICROPY_PY_USOCKET micropython-1.12/ports/zephyr/modutime.c000066400000000000000000000054441357706137100205100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_UTIME #include #include "py/runtime.h" #include "py/smallint.h" #include "py/mphal.h" #include "extmod/utime_mphal.h" STATIC mp_obj_t mod_time_time(void) { /* The absence of FP support is deliberate. The Zephyr port uses * single precision floats so the fraction component will start to * lose precision on devices with a long uptime. */ return mp_obj_new_int(k_uptime_get() / 1000); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time); STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mod_time_time_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table); const mp_obj_module_t mp_module_time = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_time_globals, }; #endif // MICROPY_PY_UTIME micropython-1.12/ports/zephyr/modzephyr.c000066400000000000000000000066361357706137100207120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_PY_ZEPHYR #include #include #include #include "py/runtime.h" STATIC mp_obj_t mod_is_preempt_thread(void) { return mp_obj_new_bool(k_is_preempt_thread()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_is_preempt_thread_obj, mod_is_preempt_thread); STATIC mp_obj_t mod_current_tid(void) { return MP_OBJ_NEW_SMALL_INT(k_current_get()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_current_tid_obj, mod_current_tid); #ifdef CONFIG_THREAD_STACK_INFO extern k_tid_t const _main_thread; extern k_tid_t const _idle_thread; static void thread_stack_dump(const struct k_thread *thread, void *user_data) { const char *th_name = k_thread_name_get((k_tid_t)thread); if (th_name == NULL) { static char tid[9]; snprintf(tid, sizeof(tid), "%08x", (int)thread); th_name = tid; } stack_analyze(th_name, (char*)thread->stack_info.start, thread->stack_info.size); } STATIC mp_obj_t mod_stacks_analyze(void) { k_thread_foreach(thread_stack_dump, NULL); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_stacks_analyze_obj, mod_stacks_analyze); #endif #ifdef CONFIG_NET_SHELL //int net_shell_cmd_iface(int argc, char *argv[]); STATIC mp_obj_t mod_shell_net_iface(void) { net_shell_cmd_iface(0, NULL); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_shell_net_iface_obj, mod_shell_net_iface); #endif // CONFIG_NET_SHELL STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_zephyr) }, { MP_ROM_QSTR(MP_QSTR_is_preempt_thread), MP_ROM_PTR(&mod_is_preempt_thread_obj) }, { MP_ROM_QSTR(MP_QSTR_current_tid), MP_ROM_PTR(&mod_current_tid_obj) }, #ifdef CONFIG_THREAD_STACK_INFO { MP_ROM_QSTR(MP_QSTR_stacks_analyze), MP_ROM_PTR(&mod_stacks_analyze_obj) }, #endif #ifdef CONFIG_NET_SHELL { MP_ROM_QSTR(MP_QSTR_shell_net_iface), MP_ROM_PTR(&mod_shell_net_iface_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table); const mp_obj_module_t mp_module_zephyr = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_time_globals, }; #endif // MICROPY_PY_ZEPHYR micropython-1.12/ports/zephyr/modzsensor.c000066400000000000000000000117031357706137100210630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #include #include #if MICROPY_PY_ZSENSOR typedef struct _mp_obj_sensor_t { mp_obj_base_t base; struct device *dev; } mp_obj_sensor_t; STATIC mp_obj_t sensor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_obj_sensor_t *o = m_new_obj(mp_obj_sensor_t); o->base.type = type; o->dev = device_get_binding(mp_obj_str_get_str(args[0])); if (o->dev == NULL) { mp_raise_ValueError("dev not found"); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t sensor_measure(mp_obj_t self_in) { mp_obj_sensor_t *self = MP_OBJ_TO_PTR(self_in); int st = sensor_sample_fetch(self->dev); if (st != 0) { mp_raise_OSError(-st); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(sensor_measure_obj, sensor_measure); STATIC void sensor_get_internal(mp_obj_t self_in, mp_obj_t channel_in, struct sensor_value *res) { mp_obj_sensor_t *self = MP_OBJ_TO_PTR(self_in); int st = sensor_channel_get(self->dev, mp_obj_get_int(channel_in), res); if (st != 0) { mp_raise_OSError(-st); } } STATIC mp_obj_t sensor_get_float(mp_obj_t self_in, mp_obj_t channel_in) { struct sensor_value val; sensor_get_internal(self_in, channel_in, &val); return mp_obj_new_float(val.val1 + (mp_float_t)val.val2 / 1000000); } MP_DEFINE_CONST_FUN_OBJ_2(sensor_get_float_obj, sensor_get_float); STATIC mp_obj_t sensor_get_micros(mp_obj_t self_in, mp_obj_t channel_in) { struct sensor_value val; sensor_get_internal(self_in, channel_in, &val); return MP_OBJ_NEW_SMALL_INT(val.val1 * 1000000 + val.val2); } MP_DEFINE_CONST_FUN_OBJ_2(sensor_get_micros_obj, sensor_get_micros); STATIC mp_obj_t sensor_get_millis(mp_obj_t self_in, mp_obj_t channel_in) { struct sensor_value val; sensor_get_internal(self_in, channel_in, &val); return MP_OBJ_NEW_SMALL_INT(val.val1 * 1000 + val.val2 / 1000); } MP_DEFINE_CONST_FUN_OBJ_2(sensor_get_millis_obj, sensor_get_millis); STATIC mp_obj_t sensor_get_int(mp_obj_t self_in, mp_obj_t channel_in) { struct sensor_value val; sensor_get_internal(self_in, channel_in, &val); return MP_OBJ_NEW_SMALL_INT(val.val1); } MP_DEFINE_CONST_FUN_OBJ_2(sensor_get_int_obj, sensor_get_int); STATIC const mp_rom_map_elem_t sensor_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_measure), MP_ROM_PTR(&sensor_measure_obj) }, { MP_ROM_QSTR(MP_QSTR_get_float), MP_ROM_PTR(&sensor_get_float_obj) }, { MP_ROM_QSTR(MP_QSTR_get_micros), MP_ROM_PTR(&sensor_get_micros_obj) }, { MP_ROM_QSTR(MP_QSTR_get_millis), MP_ROM_PTR(&sensor_get_millis_obj) }, { MP_ROM_QSTR(MP_QSTR_get_int), MP_ROM_PTR(&sensor_get_int_obj) }, }; STATIC MP_DEFINE_CONST_DICT(sensor_locals_dict, sensor_locals_dict_table); STATIC const mp_obj_type_t sensor_type = { { &mp_type_type }, .name = MP_QSTR_Sensor, .make_new = sensor_make_new, .locals_dict = (void*)&sensor_locals_dict, }; STATIC const mp_rom_map_elem_t mp_module_zsensor_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_zsensor) }, { MP_ROM_QSTR(MP_QSTR_Sensor), MP_ROM_PTR(&sensor_type) }, #define C(name) { MP_ROM_QSTR(MP_QSTR_ ## name), MP_ROM_INT(SENSOR_CHAN_ ## name) } C(ACCEL_X), C(ACCEL_Y), C(ACCEL_Z), C(GYRO_X), C(GYRO_Y), C(GYRO_Z), C(MAGN_X), C(MAGN_Y), C(MAGN_Z), C(DIE_TEMP), C(PRESS), C(PROX), C(HUMIDITY), C(LIGHT), C(ALTITUDE), #undef C }; STATIC MP_DEFINE_CONST_DICT(mp_module_zsensor_globals, mp_module_zsensor_globals_table); const mp_obj_module_t mp_module_zsensor = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_zsensor_globals, }; #endif //MICROPY_PY_UHASHLIB micropython-1.12/ports/zephyr/mpconfigport.h000066400000000000000000000123761357706137100214030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include // Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles #include "autoconf.h" // Included here to get basic Zephyr environment (macros, etc.) #include // Usually passed from Makefile #ifndef MICROPY_HEAP_SIZE #define MICROPY_HEAP_SIZE (16 * 1024) #endif #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_MIN_MAX (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_BUILTINS_RANGE_ATTRS (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_STR_COUNT (0) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT zephyr_help_text #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hard_i2c_make_new #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_PY_STRUCT (0) #ifdef CONFIG_NETWORKING // If we have networking, we likely want errno comfort #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_USOCKET (1) #endif #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UTIME (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_ZEPHYR (1) #define MICROPY_PY_ZSENSOR (1) #define MICROPY_PY_SYS_MODULES (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_PY_BUILTINS_COMPLEX (0) // Saving extra crumbs to make sure binary fits in 128K #define MICROPY_COMP_CONST_FOLDING (0) #define MICROPY_COMP_CONST (0) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) #define MICROPY_PY_SYS_PLATFORM "zephyr" #ifdef CONFIG_BOARD #define MICROPY_HW_BOARD_NAME "zephyr-" CONFIG_BOARD #else #define MICROPY_HW_BOARD_NAME "zephyr-generic" #endif #ifdef CONFIG_SOC #define MICROPY_HW_MCU_NAME CONFIG_SOC #else #define MICROPY_HW_MCU_NAME "unknown-cpu" #endif #define MICROPY_MODULE_FROZEN_STR (1) typedef int mp_int_t; // must be pointer size typedef unsigned mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_time; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_zephyr; extern const struct _mp_obj_module_t mp_module_zsensor; #if MICROPY_PY_USOCKET #define MICROPY_PY_USOCKET_DEF { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) }, #else #define MICROPY_PY_USOCKET_DEF #endif #if MICROPY_PY_UTIME #define MICROPY_PY_UTIME_DEF { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) }, #else #define MICROPY_PY_UTIME_DEF #endif #if MICROPY_PY_ZEPHYR #define MICROPY_PY_ZEPHYR_DEF { MP_ROM_QSTR(MP_QSTR_zephyr), MP_ROM_PTR(&mp_module_zephyr) }, #else #define MICROPY_PY_ZEPHYR_DEF #endif #if MICROPY_PY_ZSENSOR #define MICROPY_PY_ZSENSOR_DEF { MP_ROM_QSTR(MP_QSTR_zsensor), MP_ROM_PTR(&mp_module_zsensor) }, #else #define MICROPY_PY_ZSENSOR_DEF #endif #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \ MICROPY_PY_USOCKET_DEF \ MICROPY_PY_UTIME_DEF \ MICROPY_PY_ZEPHYR_DEF \ MICROPY_PY_ZSENSOR_DEF \ // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ micropython-1.12/ports/zephyr/mpconfigport_bin_testsuite.h000066400000000000000000000025401357706137100243340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "mpconfigport.h" #ifdef TEST #include "lib/upytesthelper/upytesthelper.h" #define MP_PLAT_PRINT_STRN(str, len) upytest_output(str, len) #endif micropython-1.12/ports/zephyr/mpconfigport_minimal.h000066400000000000000000000062321357706137100231030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include // Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles #include "autoconf.h" // Included here to get basic Zephyr environment (macros, etc.) #include // Usually passed from Makefile #ifndef MICROPY_HEAP_SIZE #define MICROPY_HEAP_SIZE (16 * 1024) #endif #define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FILTER (0) #define MICROPY_PY_BUILTINS_MIN_MAX (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_BUILTINS_RANGE_ATTRS (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_SLICE (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS_MODULES (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_PY_BUILTINS_COMPLEX (0) // Saving extra crumbs to make sure binary fits in 128K #define MICROPY_COMP_CONST_FOLDING (0) #define MICROPY_COMP_CONST (0) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) #ifdef CONFIG_BOARD #define MICROPY_HW_BOARD_NAME "zephyr-" CONFIG_BOARD #else #define MICROPY_HW_BOARD_NAME "zephyr-generic" #endif #ifdef CONFIG_SOC #define MICROPY_HW_MCU_NAME CONFIG_SOC #else #define MICROPY_HW_MCU_NAME "unknown-cpu" #endif typedef int mp_int_t; // must be pointer size typedef unsigned mp_uint_t; // must be pointer size typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; micropython-1.12/ports/zephyr/mphalport.h000066400000000000000000000017611357706137100206760ustar00rootroot00000000000000#include #include "lib/utils/interrupt_char.h" static inline mp_uint_t mp_hal_ticks_us(void) { return SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32()) / 1000; } static inline mp_uint_t mp_hal_ticks_ms(void) { return k_uptime_get(); } static inline mp_uint_t mp_hal_ticks_cpu(void) { // ticks_cpu() is defined as using the highest-resolution timing source // in the system. This is usually a CPU clock, but doesn't have to be, // here we just use Zephyr hi-res timer. return k_cycle_get_32(); } static inline void mp_hal_delay_us(mp_uint_t delay) { k_busy_wait(delay); } static inline void mp_hal_delay_ms(mp_uint_t delay) { k_sleep(delay); } #define mp_hal_delay_us_fast(us) (mp_hal_delay_us(us)) #define mp_hal_pin_od_low(p) (mp_raise_NotImplementedError("mp_hal_pin_od_low")) #define mp_hal_pin_od_high(p) (mp_raise_NotImplementedError("mp_hal_pin_od_high")) #define mp_hal_pin_open_drain(p) (mp_raise_NotImplementedError("mp_hal_pin_open_drain")) micropython-1.12/ports/zephyr/prj_96b_carbon.conf000066400000000000000000000000561357706137100221610ustar00rootroot00000000000000# TODO: Enable networking CONFIG_NETWORKING=y micropython-1.12/ports/zephyr/prj_base.conf000066400000000000000000000030461357706137100211510ustar00rootroot00000000000000CONFIG_BUILD_OUTPUT_BIN=y CONFIG_REBOOT=y CONFIG_STDOUT_CONSOLE=y CONFIG_CONSOLE_HANDLER=y CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS=y CONFIG_CONSOLE_SUBSYS=y CONFIG_CONSOLE_GETCHAR=y CONFIG_CONSOLE_GETCHAR_BUFSIZE=128 CONFIG_CONSOLE_PUTCHAR_BUFSIZE=128 CONFIG_NEWLIB_LIBC=y CONFIG_FLOAT=y CONFIG_MAIN_STACK_SIZE=4736 # Enable sensor subsystem (doesn't add code if not used). # Specific sensors should be enabled per-board. CONFIG_SENSOR=y # Networking config CONFIG_NETWORKING=y CONFIG_NET_IPV4=y CONFIG_NET_IPV6=y CONFIG_NET_UDP=y CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_CONFIG_SETTINGS=y CONFIG_NET_CONFIG_INIT_TIMEOUT=3 CONFIG_NET_CONFIG_NEED_IPV6=y CONFIG_NET_CONFIG_NEED_IPV4=y # DNS CONFIG_DNS_RESOLVER=y CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2 CONFIG_DNS_SERVER_IP_ADDRESSES=y # Static IP addresses CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" CONFIG_DNS_SERVER1="192.0.2.2" # DHCP configuration. Until DHCP address is assigned, # static configuration above is used instead. CONFIG_NET_DHCPV4=y # Diagnostics and debugging # Required for zephyr.stack_analyze() CONFIG_INIT_STACKS=y CONFIG_THREAD_MONITOR=y CONFIG_THREAD_NAME=y CONFIG_THREAD_STACK_INFO=y # Required for usocket.pkt_get_info() CONFIG_NET_BUF_POOL_USAGE=y # Required for usocket.shell_*() #CONFIG_NET_SHELL=y # Uncomment to enable "INFO" level net_buf logging #CONFIG_NET_LOG=y #CONFIG_NET_DEBUG_NET_BUF=y # Change to 4 for "DEBUG" level #CONFIG_SYS_LOG_NET_LEVEL=3 micropython-1.12/ports/zephyr/prj_disco_l475_iot1.conf000066400000000000000000000001151357706137100230410ustar00rootroot00000000000000# Sensors CONFIG_HTS221=y CONFIG_LIS3MDL=y CONFIG_LPS22HB=y CONFIG_LSM6DSL=y micropython-1.12/ports/zephyr/prj_frdm_k64f.conf000066400000000000000000000002511357706137100220140ustar00rootroot00000000000000# Networking drivers CONFIG_NET_L2_ETHERNET=y # Hardware features CONFIG_I2C=y # Sensor drivers CONFIG_FXOS8700=y CONFIG_FXOS8700_MODE_HYBRID=y CONFIG_FXOS8700_TEMP=y micropython-1.12/ports/zephyr/prj_frdm_kw41z.conf000066400000000000000000000001721357706137100222240ustar00rootroot00000000000000# Hardware features CONFIG_I2C=y # Sensor drivers CONFIG_FXOS8700=y CONFIG_FXOS8700_MODE_HYBRID=y CONFIG_FXOS8700_TEMP=y micropython-1.12/ports/zephyr/prj_minimal.conf000066400000000000000000000005251357706137100216640ustar00rootroot00000000000000CONFIG_NEWLIB_LIBC=y CONFIG_FLOAT=y CONFIG_MAIN_STACK_SIZE=4096 CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_CONSOLE_SUBSYS=y CONFIG_CONSOLE_GETCHAR=y CONFIG_CONSOLE_GETCHAR_BUFSIZE=32 CONFIG_CONSOLE_PUTCHAR_BUFSIZE=32 # TODO: Disable once https://github.com/zephyrproject-rtos/zephyr/pull/13731 is merged #CONFIG_CONSOLE=n #CONFIG_UART_CONSOLE=n micropython-1.12/ports/zephyr/prj_qemu_cortex_m3.conf000066400000000000000000000002541357706137100231670ustar00rootroot00000000000000# Interrupt-driven UART console has emulation artifacts under QEMU, # disable it CONFIG_CONSOLE_SUBSYS=n # Networking drivers # SLIP driver for QEMU CONFIG_NET_SLIP_TAP=y micropython-1.12/ports/zephyr/prj_qemu_x86.conf000066400000000000000000000002541357706137100217110ustar00rootroot00000000000000# Interrupt-driven UART console has emulation artifacts under QEMU, # disable it CONFIG_CONSOLE_SUBSYS=n # Networking drivers # SLIP driver for QEMU CONFIG_NET_SLIP_TAP=y micropython-1.12/ports/zephyr/src/000077500000000000000000000000001357706137100173015ustar00rootroot00000000000000micropython-1.12/ports/zephyr/src/Makefile000066400000000000000000000011671357706137100207460ustar00rootroot00000000000000# # Copyright (c) 2016 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # obj-y += zephyr_start.o zephyr_getchar.o micropython-1.12/ports/zephyr/src/zephyr_getchar.c000066400000000000000000000034601357706137100224660ustar00rootroot00000000000000/* * Copyright (c) 2016 Linaro * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "zephyr_getchar.h" extern int mp_interrupt_char; void mp_keyboard_interrupt(void); static struct k_sem uart_sem; #define UART_BUFSIZE 256 static uint8_t uart_ringbuf[UART_BUFSIZE]; static uint8_t i_get, i_put; static int console_irq_input_hook(uint8_t ch) { int i_next = (i_put + 1) & (UART_BUFSIZE - 1); if (i_next == i_get) { printk("UART buffer overflow - char dropped\n"); return 1; } if (ch == mp_interrupt_char) { mp_keyboard_interrupt(); return 1; } else { uart_ringbuf[i_put] = ch; i_put = i_next; } //printk("%x\n", ch); k_sem_give(&uart_sem); k_yield(); return 1; } uint8_t zephyr_getchar(void) { k_sem_take(&uart_sem, K_FOREVER); unsigned int key = irq_lock(); uint8_t c = uart_ringbuf[i_get++]; i_get &= UART_BUFSIZE - 1; irq_unlock(key); return c; } void zephyr_getchar_init(void) { k_sem_init(&uart_sem, 0, UINT_MAX); uart_console_in_debug_hook_install(console_irq_input_hook); // All NULLs because we're interested only in the callback above uart_register_input(NULL, NULL, NULL); } micropython-1.12/ports/zephyr/src/zephyr_getchar.h000066400000000000000000000012461357706137100224730ustar00rootroot00000000000000/* * Copyright (c) 2016 Linaro * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include void zephyr_getchar_init(void); uint8_t zephyr_getchar(void); micropython-1.12/ports/zephyr/src/zephyr_start.c000066400000000000000000000026411357706137100222060ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "zephyr_getchar.h" int real_main(void); void main(void) { #ifdef CONFIG_CONSOLE_SUBSYS console_init(); #else zephyr_getchar_init(); #endif real_main(); } micropython-1.12/ports/zephyr/uart_core.c000066400000000000000000000040431357706137100206420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Linaro Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpconfig.h" #include "src/zephyr_getchar.h" // Zephyr headers #include #include /* * Core UART functions to implement for a port */ // Receive single character int mp_hal_stdin_rx_chr(void) { #ifdef CONFIG_CONSOLE_SUBSYS return console_getchar(); #else return zephyr_getchar(); #endif } // Send string of given length void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { #ifdef CONFIG_CONSOLE_SUBSYS while (len--) { char c = *str++; while (console_putchar(c) == -1) { k_sleep(1); } } #else static struct device *uart_console_dev; if (uart_console_dev == NULL) { uart_console_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME); } while (len--) { uart_poll_out(uart_console_dev, *str++); } #endif } micropython-1.12/ports/zephyr/z_config.mk000066400000000000000000000007151357706137100206440ustar00rootroot00000000000000srctree = $(ZEPHYR_BASE) include $(Z_DOTCONFIG) override ARCH = $(subst $(DQUOTE),,$(CONFIG_ARCH)) SOC_NAME = $(subst $(DQUOTE),,$(CONFIG_SOC)) SOC_SERIES = $(subst $(DQUOTE),,$(CONFIG_SOC_SERIES)) SOC_FAMILY = $(subst $(DQUOTE),,$(CONFIG_SOC_FAMILY)) ifeq ($(SOC_SERIES),) SOC_PATH = $(SOC_NAME) else SOC_PATH = $(SOC_FAMILY)/$(SOC_SERIES) endif KBUILD_CFLAGS := -c include $(ZEPHYR_BASE)/scripts/Kbuild.include include $(ZEPHYR_BASE)/arch/$(ARCH)/Makefile micropython-1.12/py/000077500000000000000000000000001357706137100144525ustar00rootroot00000000000000micropython-1.12/py/argcheck.c000066400000000000000000000134421357706137100163710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" void mp_arg_check_num_sig(size_t n_args, size_t n_kw, uint32_t sig) { // TODO maybe take the function name as an argument so we can print nicer error messages // The reverse of MP_OBJ_FUN_MAKE_SIG bool takes_kw = sig & 1; size_t n_args_min = sig >> 17; size_t n_args_max = (sig >> 1) & 0xffff; if (n_kw && !takes_kw) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { mp_raise_TypeError("function doesn't take keyword arguments"); } } if (n_args_min == n_args_max) { if (n_args != n_args_min) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", n_args_min, n_args)); } } } else { if (n_args < n_args_min) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function missing %d required positional arguments", n_args_min - n_args)); } } else if (n_args > n_args_max) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function expected at most %d arguments, got %d", n_args_max, n_args)); } } } } void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals) { size_t pos_found = 0, kws_found = 0; for (size_t i = 0; i < n_allowed; i++) { mp_obj_t given_arg; if (i < n_pos) { if (allowed[i].flags & MP_ARG_KW_ONLY) { goto extra_positional; } pos_found++; given_arg = pos[i]; } else { mp_map_elem_t *kw = mp_map_lookup(kws, MP_OBJ_NEW_QSTR(allowed[i].qst), MP_MAP_LOOKUP); if (kw == NULL) { if (allowed[i].flags & MP_ARG_REQUIRED) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%q' argument required", allowed[i].qst)); } } out_vals[i] = allowed[i].defval; continue; } else { kws_found++; given_arg = kw->value; } } if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_BOOL) { out_vals[i].u_bool = mp_obj_is_true(given_arg); } else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_INT) { out_vals[i].u_int = mp_obj_get_int(given_arg); } else { assert((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_OBJ); out_vals[i].u_obj = given_arg; } } if (pos_found < n_pos) { extra_positional: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { // TODO better error message mp_raise_TypeError("extra positional arguments given"); } } if (kws_found < kws->used) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { // TODO better error message mp_raise_TypeError("extra keyword arguments given"); } } } void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals) { mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_pos); mp_arg_parse_all(n_pos, args, &kw_args, n_allowed, allowed, out_vals); } NORETURN void mp_arg_error_terse_mismatch(void) { mp_raise_TypeError("argument num/types mismatch"); } #if MICROPY_CPYTHON_COMPAT NORETURN void mp_arg_error_unimpl_kw(void) { mp_raise_NotImplementedError("keyword argument(s) not yet implemented - use normal args instead"); } #endif micropython-1.12/py/asmarm.c000066400000000000000000000275401357706137100161060ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Fabian Vogt * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpconfig.h" // wrapper around everything in this file #if MICROPY_EMIT_ARM #include "py/asmarm.h" #define SIGNED_FIT24(x) (((x) & 0xff800000) == 0) || (((x) & 0xff000000) == 0xff000000) void asm_arm_end_pass(asm_arm_t *as) { if (as->base.pass == MP_ASM_PASS_EMIT) { #if defined(__linux__) && defined(__GNUC__) char *start = mp_asm_base_get_code(&as->base); char *end = start + mp_asm_base_get_code_size(&as->base); __builtin___clear_cache(start, end); #elif defined(__arm__) // flush I- and D-cache asm volatile( "0:" "mrc p15, 0, r15, c7, c10, 3\n" "bne 0b\n" "mov r0, #0\n" "mcr p15, 0, r0, c7, c7, 0\n" : : : "r0", "cc"); #endif } } // Insert word into instruction flow STATIC void emit(asm_arm_t *as, uint op) { uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4); if (c != NULL) { *(uint32_t*)c = op; } } // Insert word into instruction flow, add "ALWAYS" condition code STATIC void emit_al(asm_arm_t *as, uint op) { emit(as, op | ASM_ARM_CC_AL); } // Basic instructions without condition code STATIC uint asm_arm_op_push(uint reglist) { // stmfd sp!, {reglist} return 0x92d0000 | (reglist & 0xFFFF); } STATIC uint asm_arm_op_pop(uint reglist) { // ldmfd sp!, {reglist} return 0x8bd0000 | (reglist & 0xFFFF); } STATIC uint asm_arm_op_mov_reg(uint rd, uint rn) { // mov rd, rn return 0x1a00000 | (rd << 12) | rn; } STATIC uint asm_arm_op_mov_imm(uint rd, uint imm) { // mov rd, #imm return 0x3a00000 | (rd << 12) | imm; } STATIC uint asm_arm_op_mvn_imm(uint rd, uint imm) { // mvn rd, #imm return 0x3e00000 | (rd << 12) | imm; } STATIC uint asm_arm_op_add_imm(uint rd, uint rn, uint imm) { // add rd, rn, #imm return 0x2800000 | (rn << 16) | (rd << 12) | (imm & 0xFF); } STATIC uint asm_arm_op_add_reg(uint rd, uint rn, uint rm) { // add rd, rn, rm return 0x0800000 | (rn << 16) | (rd << 12) | rm; } STATIC uint asm_arm_op_sub_imm(uint rd, uint rn, uint imm) { // sub rd, rn, #imm return 0x2400000 | (rn << 16) | (rd << 12) | (imm & 0xFF); } STATIC uint asm_arm_op_sub_reg(uint rd, uint rn, uint rm) { // sub rd, rn, rm return 0x0400000 | (rn << 16) | (rd << 12) | rm; } STATIC uint asm_arm_op_mul_reg(uint rd, uint rm, uint rs) { // mul rd, rm, rs assert(rd != rm); return 0x0000090 | (rd << 16) | (rs << 8) | rm; } STATIC uint asm_arm_op_and_reg(uint rd, uint rn, uint rm) { // and rd, rn, rm return 0x0000000 | (rn << 16) | (rd << 12) | rm; } STATIC uint asm_arm_op_eor_reg(uint rd, uint rn, uint rm) { // eor rd, rn, rm return 0x0200000 | (rn << 16) | (rd << 12) | rm; } STATIC uint asm_arm_op_orr_reg(uint rd, uint rn, uint rm) { // orr rd, rn, rm return 0x1800000 | (rn << 16) | (rd << 12) | rm; } void asm_arm_bkpt(asm_arm_t *as) { // bkpt #0 emit_al(as, 0x1200070); } // locals: // - stored on the stack in ascending order // - numbered 0 through num_locals-1 // - SP points to first local // // | SP // v // l0 l1 l2 ... l(n-1) // ^ ^ // | low address | high address in RAM void asm_arm_entry(asm_arm_t *as, int num_locals) { assert(num_locals >= 0); as->stack_adjust = 0; as->push_reglist = 1 << ASM_ARM_REG_R1 | 1 << ASM_ARM_REG_R2 | 1 << ASM_ARM_REG_R3 | 1 << ASM_ARM_REG_R4 | 1 << ASM_ARM_REG_R5 | 1 << ASM_ARM_REG_R6 | 1 << ASM_ARM_REG_R7 | 1 << ASM_ARM_REG_R8; // Only adjust the stack if there are more locals than usable registers if (num_locals > 3) { as->stack_adjust = num_locals * 4; // Align stack to 8 bytes if (num_locals & 1) { as->stack_adjust += 4; } } emit_al(as, asm_arm_op_push(as->push_reglist | 1 << ASM_ARM_REG_LR)); if (as->stack_adjust > 0) { emit_al(as, asm_arm_op_sub_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust)); } } void asm_arm_exit(asm_arm_t *as) { if (as->stack_adjust > 0) { emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust)); } emit_al(as, asm_arm_op_pop(as->push_reglist | (1 << ASM_ARM_REG_PC))); } void asm_arm_push(asm_arm_t *as, uint reglist) { emit_al(as, asm_arm_op_push(reglist)); } void asm_arm_pop(asm_arm_t *as, uint reglist) { emit_al(as, asm_arm_op_pop(reglist)); } void asm_arm_mov_reg_reg(asm_arm_t *as, uint reg_dest, uint reg_src) { emit_al(as, asm_arm_op_mov_reg(reg_dest, reg_src)); } size_t asm_arm_mov_reg_i32(asm_arm_t *as, uint rd, int imm) { // Insert immediate into code and jump over it emit_al(as, 0x59f0000 | (rd << 12)); // ldr rd, [pc] emit_al(as, 0xa000000); // b pc size_t loc = mp_asm_base_get_code_pos(&as->base); emit(as, imm); return loc; } void asm_arm_mov_reg_i32_optimised(asm_arm_t *as, uint rd, int imm) { // TODO: There are more variants of immediate values if ((imm & 0xFF) == imm) { emit_al(as, asm_arm_op_mov_imm(rd, imm)); } else if (imm < 0 && imm >= -256) { // mvn is "move not", not "move negative" emit_al(as, asm_arm_op_mvn_imm(rd, ~imm)); } else { asm_arm_mov_reg_i32(as, rd, imm); } } void asm_arm_mov_local_reg(asm_arm_t *as, int local_num, uint rd) { // str rd, [sp, #local_num*4] emit_al(as, 0x58d0000 | (rd << 12) | (local_num << 2)); } void asm_arm_mov_reg_local(asm_arm_t *as, uint rd, int local_num) { // ldr rd, [sp, #local_num*4] emit_al(as, 0x59d0000 | (rd << 12) | (local_num << 2)); } void asm_arm_cmp_reg_i8(asm_arm_t *as, uint rd, int imm) { // cmp rd, #imm emit_al(as, 0x3500000 | (rd << 16) | (imm & 0xFF)); } void asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn) { // cmp rd, rn emit_al(as, 0x1500000 | (rd << 16) | rn); } void asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond) { emit(as, asm_arm_op_mov_imm(rd, 1) | cond); // movCOND rd, #1 emit(as, asm_arm_op_mov_imm(rd, 0) | (cond ^ (1 << 28))); // mov!COND rd, #0 } void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { // add rd, rn, rm emit_al(as, asm_arm_op_add_reg(rd, rn, rm)); } void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { // sub rd, rn, rm emit_al(as, asm_arm_op_sub_reg(rd, rn, rm)); } void asm_arm_mul_reg_reg_reg(asm_arm_t *as, uint rd, uint rs, uint rm) { // rs and rm are swapped because of restriction rd!=rm // mul rd, rm, rs emit_al(as, asm_arm_op_mul_reg(rd, rm, rs)); } void asm_arm_and_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { // and rd, rn, rm emit_al(as, asm_arm_op_and_reg(rd, rn, rm)); } void asm_arm_eor_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { // eor rd, rn, rm emit_al(as, asm_arm_op_eor_reg(rd, rn, rm)); } void asm_arm_orr_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { // orr rd, rn, rm emit_al(as, asm_arm_op_orr_reg(rd, rn, rm)); } void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num) { // add rd, sp, #local_num*4 emit_al(as, asm_arm_op_add_imm(rd, ASM_ARM_REG_SP, local_num << 2)); } void asm_arm_mov_reg_pcrel(asm_arm_t *as, uint reg_dest, uint label) { assert(label < as->base.max_num_labels); mp_uint_t dest = as->base.label_offsets[label]; mp_int_t rel = dest - as->base.code_offset; rel -= 12 + 8; // adjust for load of rel, and then PC+8 prefetch of add_reg_reg_reg // To load rel int reg_dest, insert immediate into code and jump over it emit_al(as, 0x59f0000 | (reg_dest << 12)); // ldr rd, [pc] emit_al(as, 0xa000000); // b pc emit(as, rel); // Do reg_dest += PC asm_arm_add_reg_reg_reg(as, reg_dest, reg_dest, ASM_ARM_REG_PC); } void asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs) { // mov rd, rd, lsl rs emit_al(as, 0x1a00010 | (rd << 12) | (rs << 8) | rd); } void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs) { // mov rd, rd, asr rs emit_al(as, 0x1a00050 | (rd << 12) | (rs << 8) | rd); } void asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { // ldr rd, [rn, #off] emit_al(as, 0x5900000 | (rn << 16) | (rd << 12) | byte_offset); } void asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn) { // ldrh rd, [rn] emit_al(as, 0x1d000b0 | (rn << 16) | (rd << 12)); } void asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn) { // ldrb rd, [rn] emit_al(as, 0x5d00000 | (rn << 16) | (rd << 12)); } void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset) { // str rd, [rm, #off] emit_al(as, 0x5800000 | (rm << 16) | (rd << 12) | byte_offset); } void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm) { // strh rd, [rm] emit_al(as, 0x1c000b0 | (rm << 16) | (rd << 12)); } void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm) { // strb rd, [rm] emit_al(as, 0x5c00000 | (rm << 16) | (rd << 12)); } void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { // str rd, [rm, rn, lsl #2] emit_al(as, 0x7800100 | (rm << 16) | (rd << 12) | rn); } void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { // strh doesn't support scaled register index emit_al(as, 0x1a00080 | (ASM_ARM_REG_R8 << 12) | rn); // mov r8, rn, lsl #1 emit_al(as, 0x18000b0 | (rm << 16) | (rd << 12) | ASM_ARM_REG_R8); // strh rd, [rm, r8] } void asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { // strb rd, [rm, rn] emit_al(as, 0x7c00000 | (rm << 16) | (rd << 12) | rn); } void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label) { assert(label < as->base.max_num_labels); mp_uint_t dest = as->base.label_offsets[label]; mp_int_t rel = dest - as->base.code_offset; rel -= 8; // account for instruction prefetch, PC is 8 bytes ahead of this instruction rel >>= 2; // in ARM mode the branch target is 32-bit aligned, so the 2 LSB are omitted if (SIGNED_FIT24(rel)) { emit(as, cond | 0xa000000 | (rel & 0xffffff)); } else { printf("asm_arm_bcc: branch does not fit in 24 bits\n"); } } void asm_arm_b_label(asm_arm_t *as, uint label) { asm_arm_bcc_label(as, ASM_ARM_CC_AL, label); } void asm_arm_bl_ind(asm_arm_t *as, uint fun_id, uint reg_temp) { // The table offset should fit into the ldr instruction assert(fun_id < (0x1000 / 4)); emit_al(as, asm_arm_op_mov_reg(ASM_ARM_REG_LR, ASM_ARM_REG_PC)); // mov lr, pc emit_al(as, 0x597f000 | (fun_id << 2)); // ldr pc, [r7, #fun_id*4] } void asm_arm_bx_reg(asm_arm_t *as, uint reg_src) { emit_al(as, 0x012fff10 | reg_src); } #endif // MICROPY_EMIT_ARM micropython-1.12/py/asmarm.h000066400000000000000000000223471357706137100161130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Fabian Vogt * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_ASMARM_H #define MICROPY_INCLUDED_PY_ASMARM_H #include "py/misc.h" #include "py/asmbase.h" #define ASM_ARM_REG_R0 (0) #define ASM_ARM_REG_R1 (1) #define ASM_ARM_REG_R2 (2) #define ASM_ARM_REG_R3 (3) #define ASM_ARM_REG_R4 (4) #define ASM_ARM_REG_R5 (5) #define ASM_ARM_REG_R6 (6) #define ASM_ARM_REG_R7 (7) #define ASM_ARM_REG_R8 (8) #define ASM_ARM_REG_R9 (9) #define ASM_ARM_REG_R10 (10) #define ASM_ARM_REG_R11 (11) #define ASM_ARM_REG_R12 (12) #define ASM_ARM_REG_R13 (13) #define ASM_ARM_REG_R14 (14) #define ASM_ARM_REG_R15 (15) #define ASM_ARM_REG_SP (ASM_ARM_REG_R13) #define ASM_ARM_REG_LR (ASM_ARM_REG_R14) #define ASM_ARM_REG_PC (ASM_ARM_REG_R15) #define ASM_ARM_CC_EQ (0x0 << 28) #define ASM_ARM_CC_NE (0x1 << 28) #define ASM_ARM_CC_CS (0x2 << 28) #define ASM_ARM_CC_CC (0x3 << 28) #define ASM_ARM_CC_MI (0x4 << 28) #define ASM_ARM_CC_PL (0x5 << 28) #define ASM_ARM_CC_VS (0x6 << 28) #define ASM_ARM_CC_VC (0x7 << 28) #define ASM_ARM_CC_HI (0x8 << 28) #define ASM_ARM_CC_LS (0x9 << 28) #define ASM_ARM_CC_GE (0xa << 28) #define ASM_ARM_CC_LT (0xb << 28) #define ASM_ARM_CC_GT (0xc << 28) #define ASM_ARM_CC_LE (0xd << 28) #define ASM_ARM_CC_AL (0xe << 28) typedef struct _asm_arm_t { mp_asm_base_t base; uint push_reglist; uint stack_adjust; } asm_arm_t; void asm_arm_end_pass(asm_arm_t *as); void asm_arm_entry(asm_arm_t *as, int num_locals); void asm_arm_exit(asm_arm_t *as); void asm_arm_bkpt(asm_arm_t *as); // mov void asm_arm_mov_reg_reg(asm_arm_t *as, uint reg_dest, uint reg_src); size_t asm_arm_mov_reg_i32(asm_arm_t *as, uint rd, int imm); void asm_arm_mov_reg_i32_optimised(asm_arm_t *as, uint rd, int imm); void asm_arm_mov_local_reg(asm_arm_t *as, int local_num, uint rd); void asm_arm_mov_reg_local(asm_arm_t *as, uint rd, int local_num); void asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond); // compare void asm_arm_cmp_reg_i8(asm_arm_t *as, uint rd, int imm); void asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn); // arithmetic void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_mul_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_and_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_eor_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_orr_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num); void asm_arm_mov_reg_pcrel(asm_arm_t *as, uint reg_dest, uint label); void asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs); void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs); // memory void asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset); void asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn); void asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn); void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset); void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm); void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm); // store to array void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); void asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); // stack void asm_arm_push(asm_arm_t *as, uint reglist); void asm_arm_pop(asm_arm_t *as, uint reglist); // control flow void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label); void asm_arm_b_label(asm_arm_t *as, uint label); void asm_arm_bl_ind(asm_arm_t *as, uint fun_id, uint reg_temp); void asm_arm_bx_reg(asm_arm_t *as, uint reg_src); // Holds a pointer to mp_fun_table #define ASM_ARM_REG_FUN_TABLE ASM_ARM_REG_R7 #if GENERIC_ASM_API // The following macros provide a (mostly) arch-independent API to // generate native code, and are used by the native emitter. #define ASM_WORD_SIZE (4) #define REG_RET ASM_ARM_REG_R0 #define REG_ARG_1 ASM_ARM_REG_R0 #define REG_ARG_2 ASM_ARM_REG_R1 #define REG_ARG_3 ASM_ARM_REG_R2 #define REG_ARG_4 ASM_ARM_REG_R3 #define REG_TEMP0 ASM_ARM_REG_R0 #define REG_TEMP1 ASM_ARM_REG_R1 #define REG_TEMP2 ASM_ARM_REG_R2 #define REG_LOCAL_1 ASM_ARM_REG_R4 #define REG_LOCAL_2 ASM_ARM_REG_R5 #define REG_LOCAL_3 ASM_ARM_REG_R6 #define REG_LOCAL_NUM (3) // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_ARM_REG_FUN_TABLE #define ASM_T asm_arm_t #define ASM_END_PASS asm_arm_end_pass #define ASM_ENTRY asm_arm_entry #define ASM_EXIT asm_arm_exit #define ASM_JUMP asm_arm_b_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ asm_arm_cmp_reg_i8(as, reg, 0); \ asm_arm_bcc_label(as, ASM_ARM_CC_EQ, label); \ } while (0) #define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \ do { \ asm_arm_cmp_reg_i8(as, reg, 0); \ asm_arm_bcc_label(as, ASM_ARM_CC_NE, label); \ } while (0) #define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \ do { \ asm_arm_cmp_reg_reg(as, reg1, reg2); \ asm_arm_bcc_label(as, ASM_ARM_CC_EQ, label); \ } while (0) #define ASM_JUMP_REG(as, reg) asm_arm_bx_reg((as), (reg)) #define ASM_CALL_IND(as, idx) asm_arm_bl_ind(as, idx, ASM_ARM_REG_R3) #define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_arm_mov_local_reg((as), (local_num), (reg_src)) #define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_arm_mov_reg_i32_optimised((as), (reg_dest), (imm)) #define ASM_MOV_REG_IMM_FIX_U16(as, reg_dest, imm) asm_arm_mov_reg_i32((as), (reg_dest), (imm)) #define ASM_MOV_REG_IMM_FIX_WORD(as, reg_dest, imm) asm_arm_mov_reg_i32((as), (reg_dest), (imm)) #define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_arm_mov_reg_local((as), (reg_dest), (local_num)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_arm_mov_reg_reg((as), (reg_dest), (reg_src)) #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_arm_mov_reg_local_addr((as), (reg_dest), (local_num)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_arm_mov_reg_pcrel((as), (reg_dest), (label)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift)) #define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift)) #define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_arm_orr_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_arm_eor_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_arm_and_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_arm_add_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_arm_sub_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_arm_mul_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 0) #define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset)) #define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_arm_ldrb_reg_reg((as), (reg_dest), (reg_base)) #define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_arm_ldrh_reg_reg((as), (reg_dest), (reg_base)) #define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 0) #define ASM_STORE_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0) #define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_str_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset)) #define ASM_STORE8_REG_REG(as, reg_value, reg_base) asm_arm_strb_reg_reg((as), (reg_value), (reg_base)) #define ASM_STORE16_REG_REG(as, reg_value, reg_base) asm_arm_strh_reg_reg((as), (reg_value), (reg_base)) #define ASM_STORE32_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0) #endif // GENERIC_ASM_API #endif // MICROPY_INCLUDED_PY_ASMARM_H micropython-1.12/py/asmbase.c000066400000000000000000000073001357706137100162310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "py/misc.h" #include "py/asmbase.h" #if MICROPY_EMIT_MACHINE_CODE void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels) { as->max_num_labels = max_num_labels; as->label_offsets = m_new(size_t, max_num_labels); } void mp_asm_base_deinit(mp_asm_base_t *as, bool free_code) { if (free_code) { MP_PLAT_FREE_EXEC(as->code_base, as->code_size); } m_del(size_t, as->label_offsets, as->max_num_labels); } void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) { if (pass < MP_ASM_PASS_EMIT) { // Reset labels so we can detect backwards jumps (and verify unique assignment) memset(as->label_offsets, -1, as->max_num_labels * sizeof(size_t)); } else { // allocating executable RAM is platform specific MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size); assert(as->code_base != NULL); } as->pass = pass; as->code_offset = 0; } // all functions must go through this one to emit bytes // if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number // of bytes needed and returns NULL, and callers should not store any data uint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write) { uint8_t *c = NULL; if (as->pass == MP_ASM_PASS_EMIT) { assert(as->code_offset + num_bytes_to_write <= as->code_size); c = as->code_base + as->code_offset; } as->code_offset += num_bytes_to_write; return c; } void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) { assert(label < as->max_num_labels); if (as->pass < MP_ASM_PASS_EMIT) { // assign label offset assert(as->label_offsets[label] == (size_t)-1); as->label_offsets[label] = as->code_offset; } else { // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT assert(as->label_offsets[label] == as->code_offset); } } // align must be a multiple of 2 void mp_asm_base_align(mp_asm_base_t* as, unsigned int align) { as->code_offset = (as->code_offset + align - 1) & (~(align - 1)); } // this function assumes a little endian machine void mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val) { uint8_t *c = mp_asm_base_get_cur_to_write_bytes(as, bytesize); if (c != NULL) { for (unsigned int i = 0; i < bytesize; i++) { *c++ = val; val >>= 8; } } } #endif // MICROPY_EMIT_MACHINE_CODE micropython-1.12/py/asmbase.h000066400000000000000000000047441357706137100162470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_ASMBASE_H #define MICROPY_INCLUDED_PY_ASMBASE_H #include #include #define MP_ASM_PASS_COMPUTE (1) #define MP_ASM_PASS_EMIT (2) typedef struct _mp_asm_base_t { int pass; size_t code_offset; size_t code_size; uint8_t *code_base; size_t max_num_labels; size_t *label_offsets; } mp_asm_base_t; void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels); void mp_asm_base_deinit(mp_asm_base_t *as, bool free_code); void mp_asm_base_start_pass(mp_asm_base_t *as, int pass); uint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write); void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label); void mp_asm_base_align(mp_asm_base_t* as, unsigned int align); void mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val); static inline size_t mp_asm_base_get_code_pos(mp_asm_base_t *as) { return as->code_offset; } static inline size_t mp_asm_base_get_code_size(mp_asm_base_t *as) { return as->code_size; } static inline void *mp_asm_base_get_code(mp_asm_base_t *as) { #if defined(MP_PLAT_COMMIT_EXEC) return MP_PLAT_COMMIT_EXEC(as->code_base, as->code_size, NULL); #else return as->code_base; #endif } #endif // MICROPY_INCLUDED_PY_ASMBASE_H micropython-1.12/py/asmthumb.c000066400000000000000000000364371357706137100164530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpconfig.h" // wrapper around everything in this file #if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB #include "py/mpstate.h" #include "py/persistentcode.h" #include "py/mphal.h" #include "py/asmthumb.h" #define UNSIGNED_FIT5(x) ((uint32_t)(x) < 32) #define UNSIGNED_FIT7(x) ((uint32_t)(x) < 128) #define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0) #define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0) #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) #define SIGNED_FIT9(x) (((x) & 0xffffff00) == 0) || (((x) & 0xffffff00) == 0xffffff00) #define SIGNED_FIT12(x) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800) #define SIGNED_FIT23(x) (((x) & 0xffc00000) == 0) || (((x) & 0xffc00000) == 0xffc00000) // Note: these actually take an imm12 but the high-bit is not encoded here #define OP_ADD_W_RRI_HI(reg_src) (0xf200 | (reg_src)) #define OP_ADD_W_RRI_LO(reg_dest, imm11) ((imm11 << 4 & 0x7000) | reg_dest << 8 | (imm11 & 0xff)) #define OP_SUB_W_RRI_HI(reg_src) (0xf2a0 | (reg_src)) #define OP_SUB_W_RRI_LO(reg_dest, imm11) ((imm11 << 4 & 0x7000) | reg_dest << 8 | (imm11 & 0xff)) #define OP_LDR_W_HI(reg_base) (0xf8d0 | (reg_base)) #define OP_LDR_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12)) static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) { return mp_asm_base_get_cur_to_write_bytes(&as->base, n); } void asm_thumb_end_pass(asm_thumb_t *as) { (void)as; // could check labels are resolved... #if __ICACHE_PRESENT == 1 if (as->base.pass == MP_ASM_PASS_EMIT) { // flush D-cache, so the code emitted is stored in memory MP_HAL_CLEAN_DCACHE(as->base.code_base, as->base.code_size); // invalidate I-cache SCB_InvalidateICache(); } #endif } /* STATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) { byte *c = asm_thumb_get_cur_to_write_bytes(as, 1); c[0] = b1; } */ /* #define IMM32_L0(x) ((x) & 0xff) #define IMM32_L1(x) (((x) >> 8) & 0xff) #define IMM32_L2(x) (((x) >> 16) & 0xff) #define IMM32_L3(x) (((x) >> 24) & 0xff) STATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) { byte *c = asm_thumb_get_cur_to_write_bytes(as, 4); c[0] = IMM32_L0(w32); c[1] = IMM32_L1(w32); c[2] = IMM32_L2(w32); c[3] = IMM32_L3(w32); } */ // rlolist is a bit map indicating desired lo-registers #define OP_PUSH_RLIST(rlolist) (0xb400 | (rlolist)) #define OP_PUSH_RLIST_LR(rlolist) (0xb400 | 0x0100 | (rlolist)) #define OP_POP_RLIST(rlolist) (0xbc00 | (rlolist)) #define OP_POP_RLIST_PC(rlolist) (0xbc00 | 0x0100 | (rlolist)) // The number of words must fit in 7 unsigned bits #define OP_ADD_SP(num_words) (0xb000 | (num_words)) #define OP_SUB_SP(num_words) (0xb080 | (num_words)) // locals: // - stored on the stack in ascending order // - numbered 0 through num_locals-1 // - SP points to first local // // | SP // v // l0 l1 l2 ... l(n-1) // ^ ^ // | low address | high address in RAM void asm_thumb_entry(asm_thumb_t *as, int num_locals) { assert(num_locals >= 0); // If this Thumb machine code is run from ARM state then add a prelude // to switch to Thumb state for the duration of the function. #if MICROPY_DYNAMIC_COMPILER || MICROPY_EMIT_ARM || (defined(__arm__) && !defined(__thumb2__)) #if MICROPY_DYNAMIC_COMPILER if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_ARMV6) #endif { asm_thumb_op32(as, 0x4010, 0xe92d); // push {r4, lr} asm_thumb_op32(as, 0xe009, 0xe28f); // add lr, pc, 8 + 1 asm_thumb_op32(as, 0xff3e, 0xe12f); // blx lr asm_thumb_op32(as, 0x4010, 0xe8bd); // pop {r4, lr} asm_thumb_op32(as, 0xff1e, 0xe12f); // bx lr } #endif // work out what to push and how many extra spaces to reserve on stack // so that we have enough for all locals and it's aligned an 8-byte boundary // we push extra regs (r1, r2, r3) to help do the stack adjustment // we probably should just always subtract from sp, since this would be more efficient // for push rlist, lowest numbered register at the lowest address uint reglist; uint stack_adjust; // don't pop r0 because it's used for return value switch (num_locals) { case 0: reglist = 0xf2; stack_adjust = 0; break; case 1: reglist = 0xf2; stack_adjust = 0; break; case 2: reglist = 0xfe; stack_adjust = 0; break; case 3: reglist = 0xfe; stack_adjust = 0; break; default: reglist = 0xfe; stack_adjust = ((num_locals - 3) + 1) & (~1); break; } asm_thumb_op16(as, OP_PUSH_RLIST_LR(reglist)); if (stack_adjust > 0) { if (UNSIGNED_FIT7(stack_adjust)) { asm_thumb_op16(as, OP_SUB_SP(stack_adjust)); } else { asm_thumb_op32(as, OP_SUB_W_RRI_HI(ASM_THUMB_REG_SP), OP_SUB_W_RRI_LO(ASM_THUMB_REG_SP, stack_adjust * 4)); } } as->push_reglist = reglist; as->stack_adjust = stack_adjust; } void asm_thumb_exit(asm_thumb_t *as) { if (as->stack_adjust > 0) { if (UNSIGNED_FIT7(as->stack_adjust)) { asm_thumb_op16(as, OP_ADD_SP(as->stack_adjust)); } else { asm_thumb_op32(as, OP_ADD_W_RRI_HI(ASM_THUMB_REG_SP), OP_ADD_W_RRI_LO(ASM_THUMB_REG_SP, as->stack_adjust * 4)); } } asm_thumb_op16(as, OP_POP_RLIST_PC(as->push_reglist)); } STATIC mp_uint_t get_label_dest(asm_thumb_t *as, uint label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; } void asm_thumb_op16(asm_thumb_t *as, uint op) { byte *c = asm_thumb_get_cur_to_write_bytes(as, 2); if (c != NULL) { // little endian c[0] = op; c[1] = op >> 8; } } void asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2) { byte *c = asm_thumb_get_cur_to_write_bytes(as, 4); if (c != NULL) { // little endian, op1 then op2 c[0] = op1; c[1] = op1 >> 8; c[2] = op2; c[3] = op2 >> 8; } } #define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest)) void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src) { assert(rlo_dest < ASM_THUMB_REG_R8); assert(rlo_src < ASM_THUMB_REG_R8); asm_thumb_op16(as, OP_FORMAT_4(op, rlo_dest, rlo_src)); } void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) { uint op_lo; if (reg_src < 8) { op_lo = reg_src << 3; } else { op_lo = 0x40 | ((reg_src - 8) << 3); } if (reg_dest < 8) { op_lo |= reg_dest; } else { op_lo |= 0x80 | (reg_dest - 8); } // mov reg_dest, reg_src asm_thumb_op16(as, 0x4600 | op_lo); } // if loading lo half with movw, the i16 value will be zero extended into the r32 register! size_t asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) { assert(reg_dest < ASM_THUMB_REG_R15); size_t loc = mp_asm_base_get_code_pos(&as->base); // mov[wt] reg_dest, #i16_src asm_thumb_op32(as, mov_op | ((i16_src >> 1) & 0x0400) | ((i16_src >> 12) & 0xf), ((i16_src << 4) & 0x7000) | (reg_dest << 8) | (i16_src & 0xff)); return loc; } #define OP_B_N(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff)) bool asm_thumb_b_n_label(asm_thumb_t *as, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction asm_thumb_op16(as, OP_B_N(rel)); return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT12(rel); } #define OP_BCC_N(cond, byte_offset) (0xd000 | ((cond) << 8) | (((byte_offset) >> 1) & 0x00ff)) // all these bit arithmetics need coverage testing! #define OP_BCC_W_HI(cond, byte_offset) (0xf000 | ((cond) << 6) | (((byte_offset) >> 10) & 0x0400) | (((byte_offset) >> 14) & 0x003f)) #define OP_BCC_W_LO(byte_offset) (0x8000 | ((byte_offset) & 0x2000) | (((byte_offset) >> 1) & 0x0fff)) bool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction if (!wide) { asm_thumb_op16(as, OP_BCC_N(cond, rel)); return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT9(rel); } else { asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel)); return true; } } #define OP_BL_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff)) #define OP_BL_LO(byte_offset) (0xf800 | (((byte_offset) >> 1) & 0x07ff)) bool asm_thumb_bl_label(asm_thumb_t *as, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction asm_thumb_op32(as, OP_BL_HI(rel), OP_BL_LO(rel)); return as->base.pass != MP_ASM_PASS_EMIT || SIGNED_FIT23(rel); } size_t asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32) { // movw, movt does it in 8 bytes // ldr [pc, #], dw does it in 6 bytes, but we might not reach to end of code for dw size_t loc = mp_asm_base_get_code_pos(&as->base); asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, reg_dest, i32); asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVT, reg_dest, i32 >> 16); return loc; } void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) { if (reg_dest < 8 && UNSIGNED_FIT8(i32)) { asm_thumb_mov_rlo_i8(as, reg_dest, i32); } else if (UNSIGNED_FIT16(i32)) { asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, reg_dest, i32); } else { asm_thumb_mov_reg_i32(as, reg_dest, i32); } } #define OP_STR_TO_SP_OFFSET(rlo_dest, word_offset) (0x9000 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff)) #define OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset) (0x9800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff)) void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num, uint rlo_src) { assert(rlo_src < ASM_THUMB_REG_R8); int word_offset = local_num; assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_STR_TO_SP_OFFSET(rlo_src, word_offset)); } void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) { assert(rlo_dest < ASM_THUMB_REG_R8); int word_offset = local_num; assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset)); } #define OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset) (0xa800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff)) void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num) { assert(rlo_dest < ASM_THUMB_REG_R8); int word_offset = local_num; assert(as->base.pass < MP_ASM_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset)); } void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; rel -= 4 + 4; // adjust for mov_reg_i16 and then PC+4 prefetch of add_reg_reg rel |= 1; // to stay in Thumb state when jumping to this address asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, rlo_dest, rel); // 4 bytes asm_thumb_add_reg_reg(as, rlo_dest, ASM_THUMB_REG_R15); // 2 bytes } static inline void asm_thumb_ldr_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) { asm_thumb_op32(as, OP_LDR_W_HI(reg_base), OP_LDR_W_LO(reg_dest, word_offset * 4)); } void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) { if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(word_offset)) { asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_base, word_offset); } else { asm_thumb_ldr_reg_reg_i12(as, reg_dest, reg_base, word_offset); } } // this could be wrong, because it should have a range of +/- 16MiB... #define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff)) #define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff)) void asm_thumb_b_label(asm_thumb_t *as, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction if (dest != (mp_uint_t)-1 && rel <= -4) { // is a backwards jump, so we know the size of the jump on the first pass // calculate rel assuming 12 bit relative jump if (SIGNED_FIT12(rel)) { asm_thumb_op16(as, OP_B_N(rel)); } else { goto large_jump; } } else { // is a forwards jump, so need to assume it's large large_jump: asm_thumb_op32(as, OP_BW_HI(rel), OP_BW_LO(rel)); } } void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction if (dest != (mp_uint_t)-1 && rel <= -4) { // is a backwards jump, so we know the size of the jump on the first pass // calculate rel assuming 9 bit relative jump if (SIGNED_FIT9(rel)) { asm_thumb_op16(as, OP_BCC_N(cond, rel)); } else { goto large_jump; } } else { // is a forwards jump, so need to assume it's large large_jump: asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel)); } } #define OP_BLX(reg) (0x4780 | ((reg) << 3)) #define OP_SVC(arg) (0xdf00 | (arg)) void asm_thumb_bl_ind(asm_thumb_t *as, uint fun_id, uint reg_temp) { // Load ptr to function from table, indexed by fun_id, then call it asm_thumb_ldr_reg_reg_i12_optimised(as, reg_temp, ASM_THUMB_REG_FUN_TABLE, fun_id); asm_thumb_op16(as, OP_BLX(reg_temp)); } #endif // MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB micropython-1.12/py/asmthumb.h000066400000000000000000000405201357706137100164440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_ASMTHUMB_H #define MICROPY_INCLUDED_PY_ASMTHUMB_H #include #include "py/misc.h" #include "py/asmbase.h" #define ASM_THUMB_REG_R0 (0) #define ASM_THUMB_REG_R1 (1) #define ASM_THUMB_REG_R2 (2) #define ASM_THUMB_REG_R3 (3) #define ASM_THUMB_REG_R4 (4) #define ASM_THUMB_REG_R5 (5) #define ASM_THUMB_REG_R6 (6) #define ASM_THUMB_REG_R7 (7) #define ASM_THUMB_REG_R8 (8) #define ASM_THUMB_REG_R9 (9) #define ASM_THUMB_REG_R10 (10) #define ASM_THUMB_REG_R11 (11) #define ASM_THUMB_REG_R12 (12) #define ASM_THUMB_REG_R13 (13) #define ASM_THUMB_REG_R14 (14) #define ASM_THUMB_REG_R15 (15) #define ASM_THUMB_REG_SP (ASM_THUMB_REG_R13) #define ASM_THUMB_REG_LR (REG_R14) #define ASM_THUMB_CC_EQ (0x0) #define ASM_THUMB_CC_NE (0x1) #define ASM_THUMB_CC_CS (0x2) #define ASM_THUMB_CC_CC (0x3) #define ASM_THUMB_CC_MI (0x4) #define ASM_THUMB_CC_PL (0x5) #define ASM_THUMB_CC_VS (0x6) #define ASM_THUMB_CC_VC (0x7) #define ASM_THUMB_CC_HI (0x8) #define ASM_THUMB_CC_LS (0x9) #define ASM_THUMB_CC_GE (0xa) #define ASM_THUMB_CC_LT (0xb) #define ASM_THUMB_CC_GT (0xc) #define ASM_THUMB_CC_LE (0xd) typedef struct _asm_thumb_t { mp_asm_base_t base; uint32_t push_reglist; uint32_t stack_adjust; } asm_thumb_t; void asm_thumb_end_pass(asm_thumb_t *as); void asm_thumb_entry(asm_thumb_t *as, int num_locals); void asm_thumb_exit(asm_thumb_t *as); // argument order follows ARM, in general dest is first // note there is a difference between movw and mov.w, and many others! #define ASM_THUMB_OP_IT (0xbf00) #define ASM_THUMB_OP_ITE_EQ (0xbf0c) #define ASM_THUMB_OP_ITE_CS (0xbf2c) #define ASM_THUMB_OP_ITE_MI (0xbf4c) #define ASM_THUMB_OP_ITE_VS (0xbf6c) #define ASM_THUMB_OP_ITE_HI (0xbf8c) #define ASM_THUMB_OP_ITE_GE (0xbfac) #define ASM_THUMB_OP_ITE_GT (0xbfcc) #define ASM_THUMB_OP_NOP (0xbf00) #define ASM_THUMB_OP_WFI (0xbf30) #define ASM_THUMB_OP_CPSID_I (0xb672) // cpsid i, disable irq #define ASM_THUMB_OP_CPSIE_I (0xb662) // cpsie i, enable irq void asm_thumb_op16(asm_thumb_t *as, uint op); void asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2); static inline void asm_thumb_it_cc(asm_thumb_t *as, uint cc, uint mask) { asm_thumb_op16(as, ASM_THUMB_OP_IT | (cc << 4) | mask); } // FORMAT 1: move shifted register #define ASM_THUMB_FORMAT_1_LSL (0x0000) #define ASM_THUMB_FORMAT_1_LSR (0x0800) #define ASM_THUMB_FORMAT_1_ASR (0x1000) #define ASM_THUMB_FORMAT_1_ENCODE(op, rlo_dest, rlo_src, offset) \ ((op) | ((offset) << 6) | ((rlo_src) << 3) | (rlo_dest)) static inline void asm_thumb_format_1(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, uint offset) { assert(rlo_dest < ASM_THUMB_REG_R8); assert(rlo_src < ASM_THUMB_REG_R8); asm_thumb_op16(as, ASM_THUMB_FORMAT_1_ENCODE(op, rlo_dest, rlo_src, offset)); } // FORMAT 2: add/subtract #define ASM_THUMB_FORMAT_2_ADD (0x1800) #define ASM_THUMB_FORMAT_2_SUB (0x1a00) #define ASM_THUMB_FORMAT_2_REG_OPERAND (0x0000) #define ASM_THUMB_FORMAT_2_IMM_OPERAND (0x0400) #define ASM_THUMB_FORMAT_2_ENCODE(op, rlo_dest, rlo_src, src_b) \ ((op) | ((src_b) << 6) | ((rlo_src) << 3) | (rlo_dest)) static inline void asm_thumb_format_2(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, int src_b) { assert(rlo_dest < ASM_THUMB_REG_R8); assert(rlo_src < ASM_THUMB_REG_R8); asm_thumb_op16(as, ASM_THUMB_FORMAT_2_ENCODE(op, rlo_dest, rlo_src, src_b)); } static inline void asm_thumb_add_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b) { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_ADD | ASM_THUMB_FORMAT_2_REG_OPERAND, rlo_dest, rlo_src_a, rlo_src_b); } static inline void asm_thumb_add_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, int i3_src) { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_ADD | ASM_THUMB_FORMAT_2_IMM_OPERAND, rlo_dest, rlo_src_a, i3_src); } static inline void asm_thumb_sub_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b) { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_SUB | ASM_THUMB_FORMAT_2_REG_OPERAND, rlo_dest, rlo_src_a, rlo_src_b); } static inline void asm_thumb_sub_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, int i3_src) { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_SUB | ASM_THUMB_FORMAT_2_IMM_OPERAND, rlo_dest, rlo_src_a, i3_src); } // FORMAT 3: move/compare/add/subtract immediate // These instructions all do zero extension of the i8 value #define ASM_THUMB_FORMAT_3_MOV (0x2000) #define ASM_THUMB_FORMAT_3_CMP (0x2800) #define ASM_THUMB_FORMAT_3_ADD (0x3000) #define ASM_THUMB_FORMAT_3_SUB (0x3800) #define ASM_THUMB_FORMAT_3_ENCODE(op, rlo, i8) ((op) | ((rlo) << 8) | (i8)) static inline void asm_thumb_format_3(asm_thumb_t *as, uint op, uint rlo, int i8) { assert(rlo < ASM_THUMB_REG_R8); asm_thumb_op16(as, ASM_THUMB_FORMAT_3_ENCODE(op, rlo, i8)); } static inline void asm_thumb_mov_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_MOV, rlo, i8); } static inline void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_CMP, rlo, i8); } static inline void asm_thumb_add_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_ADD, rlo, i8); } static inline void asm_thumb_sub_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_SUB, rlo, i8); } // FORMAT 4: ALU operations #define ASM_THUMB_FORMAT_4_AND (0x4000) #define ASM_THUMB_FORMAT_4_EOR (0x4040) #define ASM_THUMB_FORMAT_4_LSL (0x4080) #define ASM_THUMB_FORMAT_4_LSR (0x40c0) #define ASM_THUMB_FORMAT_4_ASR (0x4100) #define ASM_THUMB_FORMAT_4_ADC (0x4140) #define ASM_THUMB_FORMAT_4_SBC (0x4180) #define ASM_THUMB_FORMAT_4_ROR (0x41c0) #define ASM_THUMB_FORMAT_4_TST (0x4200) #define ASM_THUMB_FORMAT_4_NEG (0x4240) #define ASM_THUMB_FORMAT_4_CMP (0x4280) #define ASM_THUMB_FORMAT_4_CMN (0x42c0) #define ASM_THUMB_FORMAT_4_ORR (0x4300) #define ASM_THUMB_FORMAT_4_MUL (0x4340) #define ASM_THUMB_FORMAT_4_BIC (0x4380) #define ASM_THUMB_FORMAT_4_MVN (0x43c0) void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src); static inline void asm_thumb_cmp_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src) { asm_thumb_format_4(as, ASM_THUMB_FORMAT_4_CMP, rlo_dest, rlo_src); } // FORMAT 5: hi register operations (add, cmp, mov, bx) // For add/cmp/mov, at least one of the args must be a high register #define ASM_THUMB_FORMAT_5_ADD (0x4400) #define ASM_THUMB_FORMAT_5_BX (0x4700) #define ASM_THUMB_FORMAT_5_ENCODE(op, r_dest, r_src) \ ((op) | ((r_dest) << 4 & 0x0080) | ((r_src) << 3) | ((r_dest) & 0x0007)) static inline void asm_thumb_format_5(asm_thumb_t *as, uint op, uint r_dest, uint r_src) { asm_thumb_op16(as, ASM_THUMB_FORMAT_5_ENCODE(op, r_dest, r_src)); } static inline void asm_thumb_add_reg_reg(asm_thumb_t *as, uint r_dest, uint r_src) { asm_thumb_format_5(as, ASM_THUMB_FORMAT_5_ADD, r_dest, r_src); } static inline void asm_thumb_bx_reg(asm_thumb_t *as, uint r_src) { asm_thumb_format_5(as, ASM_THUMB_FORMAT_5_BX, 0, r_src); } // FORMAT 9: load/store with immediate offset // For word transfers the offset must be aligned, and >>2 // FORMAT 10: load/store halfword // The offset must be aligned, and >>1 // The load is zero extended into the register #define ASM_THUMB_FORMAT_9_STR (0x6000) #define ASM_THUMB_FORMAT_9_LDR (0x6800) #define ASM_THUMB_FORMAT_9_WORD_TRANSFER (0x0000) #define ASM_THUMB_FORMAT_9_BYTE_TRANSFER (0x1000) #define ASM_THUMB_FORMAT_10_STRH (0x8000) #define ASM_THUMB_FORMAT_10_LDRH (0x8800) #define ASM_THUMB_FORMAT_9_10_ENCODE(op, rlo_dest, rlo_base, offset) \ ((op) | (((offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest)) static inline void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint offset) { asm_thumb_op16(as, ASM_THUMB_FORMAT_9_10_ENCODE(op, rlo_dest, rlo_base, offset)); } static inline void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset) { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_src, rlo_base, word_offset); } static inline void asm_thumb_strb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint byte_offset) { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER, rlo_src, rlo_base, byte_offset); } static inline void asm_thumb_strh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint byte_offset) { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_10_STRH, rlo_src, rlo_base, byte_offset); } static inline void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset) { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_dest, rlo_base, word_offset); } static inline void asm_thumb_ldrb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint byte_offset) { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER , rlo_dest, rlo_base, byte_offset); } static inline void asm_thumb_ldrh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint byte_offset) { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_10_LDRH, rlo_dest, rlo_base, byte_offset); } // TODO convert these to above format style #define ASM_THUMB_OP_MOVW (0xf240) #define ASM_THUMB_OP_MOVT (0xf2c0) void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src); size_t asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src); // these return true if the destination is in range, false otherwise bool asm_thumb_b_n_label(asm_thumb_t *as, uint label); bool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide); bool asm_thumb_bl_label(asm_thumb_t *as, uint label); size_t asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32_src); // convenience void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32_src); // convenience void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src); // convenience void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label); void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint byte_offset); // convenience void asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience: picks narrow or wide branch void asm_thumb_bcc_label(asm_thumb_t *as, int cc, uint label); // convenience: picks narrow or wide branch void asm_thumb_bl_ind(asm_thumb_t *as, uint fun_id, uint reg_temp); // convenience // Holds a pointer to mp_fun_table #define ASM_THUMB_REG_FUN_TABLE ASM_THUMB_REG_R7 #if GENERIC_ASM_API // The following macros provide a (mostly) arch-independent API to // generate native code, and are used by the native emitter. #define ASM_WORD_SIZE (4) #define REG_RET ASM_THUMB_REG_R0 #define REG_ARG_1 ASM_THUMB_REG_R0 #define REG_ARG_2 ASM_THUMB_REG_R1 #define REG_ARG_3 ASM_THUMB_REG_R2 #define REG_ARG_4 ASM_THUMB_REG_R3 // rest of args go on stack #define REG_TEMP0 ASM_THUMB_REG_R0 #define REG_TEMP1 ASM_THUMB_REG_R1 #define REG_TEMP2 ASM_THUMB_REG_R2 #define REG_LOCAL_1 ASM_THUMB_REG_R4 #define REG_LOCAL_2 ASM_THUMB_REG_R5 #define REG_LOCAL_3 ASM_THUMB_REG_R6 #define REG_LOCAL_NUM (3) #define REG_FUN_TABLE ASM_THUMB_REG_FUN_TABLE #define ASM_T asm_thumb_t #define ASM_END_PASS asm_thumb_end_pass #define ASM_ENTRY asm_thumb_entry #define ASM_EXIT asm_thumb_exit #define ASM_JUMP asm_thumb_b_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ asm_thumb_cmp_rlo_i8(as, reg, 0); \ asm_thumb_bcc_label(as, ASM_THUMB_CC_EQ, label); \ } while (0) #define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \ do { \ asm_thumb_cmp_rlo_i8(as, reg, 0); \ asm_thumb_bcc_label(as, ASM_THUMB_CC_NE, label); \ } while (0) #define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \ do { \ asm_thumb_cmp_rlo_rlo(as, reg1, reg2); \ asm_thumb_bcc_label(as, ASM_THUMB_CC_EQ, label); \ } while (0) #define ASM_JUMP_REG(as, reg) asm_thumb_bx_reg((as), (reg)) #define ASM_CALL_IND(as, idx) asm_thumb_bl_ind(as, idx, ASM_THUMB_REG_R3) #define ASM_MOV_LOCAL_REG(as, local_num, reg) asm_thumb_mov_local_reg((as), (local_num), (reg)) #define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_thumb_mov_reg_i32_optimised((as), (reg_dest), (imm)) #define ASM_MOV_REG_IMM_FIX_U16(as, reg_dest, imm) asm_thumb_mov_reg_i16((as), ASM_THUMB_OP_MOVW, (reg_dest), (imm)) #define ASM_MOV_REG_IMM_FIX_WORD(as, reg_dest, imm) asm_thumb_mov_reg_i32((as), (reg_dest), (imm)) #define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_thumb_mov_reg_local((as), (reg_dest), (local_num)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_thumb_mov_reg_reg((as), (reg_dest), (reg_src)) #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_thumb_mov_reg_local_addr((as), (reg_dest), (local_num)) #define ASM_MOV_REG_PCREL(as, rlo_dest, label) asm_thumb_mov_reg_pcrel((as), (rlo_dest), (label)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSL, (reg_dest), (reg_shift)) #define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ASR, (reg_dest), (reg_shift)) #define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ORR, (reg_dest), (reg_src)) #define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_EOR, (reg_dest), (reg_src)) #define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_AND, (reg_dest), (reg_src)) #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_thumb_add_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_thumb_sub_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_MUL, (reg_dest), (reg_src)) #define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) #define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_ldr_reg_reg_i12_optimised((as), (reg_dest), (reg_base), (word_offset)) #define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrb_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) #define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrh_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) #define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) #define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0) #define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), (word_offset)) #define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_thumb_strb_rlo_rlo_i5((as), (reg_src), (reg_base), 0) #define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_thumb_strh_rlo_rlo_i5((as), (reg_src), (reg_base), 0) #define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0) #endif // GENERIC_ASM_API #endif // MICROPY_INCLUDED_PY_ASMTHUMB_H micropython-1.12/py/asmx64.c000066400000000000000000000552721357706137100157530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/mpconfig.h" // wrapper around everything in this file #if MICROPY_EMIT_X64 #include "py/asmx64.h" /* all offsets are measured in multiples of 8 bytes */ #define WORD_SIZE (8) #define OPCODE_NOP (0x90) #define OPCODE_PUSH_R64 (0x50) /* +rq */ #define OPCODE_PUSH_I64 (0x68) #define OPCODE_PUSH_M64 (0xff) /* /6 */ #define OPCODE_POP_R64 (0x58) /* +rq */ #define OPCODE_RET (0xc3) #define OPCODE_MOV_I8_TO_R8 (0xb0) /* +rb */ #define OPCODE_MOV_I64_TO_R64 (0xb8) /* +rq */ #define OPCODE_MOV_I32_TO_RM32 (0xc7) #define OPCODE_MOV_R8_TO_RM8 (0x88) /* /r */ #define OPCODE_MOV_R64_TO_RM64 (0x89) /* /r */ #define OPCODE_MOV_RM64_TO_R64 (0x8b) /* /r */ #define OPCODE_MOVZX_RM8_TO_R64 (0xb6) /* 0x0f 0xb6/r */ #define OPCODE_MOVZX_RM16_TO_R64 (0xb7) /* 0x0f 0xb7/r */ #define OPCODE_LEA_MEM_TO_R64 (0x8d) /* /r */ #define OPCODE_AND_R64_TO_RM64 (0x21) /* /r */ #define OPCODE_OR_R64_TO_RM64 (0x09) /* /r */ #define OPCODE_XOR_R64_TO_RM64 (0x31) /* /r */ #define OPCODE_ADD_R64_TO_RM64 (0x01) /* /r */ #define OPCODE_ADD_I32_TO_RM32 (0x81) /* /0 */ #define OPCODE_ADD_I8_TO_RM32 (0x83) /* /0 */ #define OPCODE_SUB_R64_FROM_RM64 (0x29) #define OPCODE_SUB_I32_FROM_RM64 (0x81) /* /5 */ #define OPCODE_SUB_I8_FROM_RM64 (0x83) /* /5 */ //#define OPCODE_SHL_RM32_BY_I8 (0xc1) /* /4 */ //#define OPCODE_SHR_RM32_BY_I8 (0xc1) /* /5 */ //#define OPCODE_SAR_RM32_BY_I8 (0xc1) /* /7 */ #define OPCODE_SHL_RM64_CL (0xd3) /* /4 */ #define OPCODE_SAR_RM64_CL (0xd3) /* /7 */ //#define OPCODE_CMP_I32_WITH_RM32 (0x81) /* /7 */ //#define OPCODE_CMP_I8_WITH_RM32 (0x83) /* /7 */ #define OPCODE_CMP_R64_WITH_RM64 (0x39) /* /r */ //#define OPCODE_CMP_RM32_WITH_R32 (0x3b) #define OPCODE_TEST_R8_WITH_RM8 (0x84) /* /r */ #define OPCODE_TEST_R64_WITH_RM64 (0x85) /* /r */ #define OPCODE_JMP_REL8 (0xeb) #define OPCODE_JMP_REL32 (0xe9) #define OPCODE_JMP_RM64 (0xff) /* /4 */ #define OPCODE_JCC_REL8 (0x70) /* | jcc type */ #define OPCODE_JCC_REL32_A (0x0f) #define OPCODE_JCC_REL32_B (0x80) /* | jcc type */ #define OPCODE_SETCC_RM8_A (0x0f) #define OPCODE_SETCC_RM8_B (0x90) /* | jcc type, /0 */ #define OPCODE_CALL_REL32 (0xe8) #define OPCODE_CALL_RM32 (0xff) /* /2 */ #define OPCODE_LEAVE (0xc9) #define MODRM_R64(x) (((x) & 0x7) << 3) #define MODRM_RM_DISP0 (0x00) #define MODRM_RM_DISP8 (0x40) #define MODRM_RM_DISP32 (0x80) #define MODRM_RM_REG (0xc0) #define MODRM_RM_R64(x) ((x) & 0x7) #define OP_SIZE_PREFIX (0x66) #define REX_PREFIX (0x40) #define REX_W (0x08) // width #define REX_R (0x04) // register #define REX_X (0x02) // index #define REX_B (0x01) // base #define REX_W_FROM_R64(r64) ((r64) >> 0 & 0x08) #define REX_R_FROM_R64(r64) ((r64) >> 1 & 0x04) #define REX_X_FROM_R64(r64) ((r64) >> 2 & 0x02) #define REX_B_FROM_R64(r64) ((r64) >> 3 & 0x01) #define IMM32_L0(x) ((x) & 0xff) #define IMM32_L1(x) (((x) >> 8) & 0xff) #define IMM32_L2(x) (((x) >> 16) & 0xff) #define IMM32_L3(x) (((x) >> 24) & 0xff) #define IMM64_L4(x) (((x) >> 32) & 0xff) #define IMM64_L5(x) (((x) >> 40) & 0xff) #define IMM64_L6(x) (((x) >> 48) & 0xff) #define IMM64_L7(x) (((x) >> 56) & 0xff) #define UNSIGNED_FIT8(x) (((x) & 0xffffffffffffff00) == 0) #define UNSIGNED_FIT32(x) (((x) & 0xffffffff00000000) == 0) #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) static inline byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int n) { return mp_asm_base_get_cur_to_write_bytes(&as->base, n); } STATIC void asm_x64_write_byte_1(asm_x64_t *as, byte b1) { byte* c = asm_x64_get_cur_to_write_bytes(as, 1); if (c != NULL) { c[0] = b1; } } STATIC void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) { byte* c = asm_x64_get_cur_to_write_bytes(as, 2); if (c != NULL) { c[0] = b1; c[1] = b2; } } STATIC void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) { byte* c = asm_x64_get_cur_to_write_bytes(as, 3); if (c != NULL) { c[0] = b1; c[1] = b2; c[2] = b3; } } STATIC void asm_x64_write_word32(asm_x64_t *as, int w32) { byte* c = asm_x64_get_cur_to_write_bytes(as, 4); if (c != NULL) { c[0] = IMM32_L0(w32); c[1] = IMM32_L1(w32); c[2] = IMM32_L2(w32); c[3] = IMM32_L3(w32); } } STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) { byte* c = asm_x64_get_cur_to_write_bytes(as, 8); if (c != NULL) { c[0] = IMM32_L0(w64); c[1] = IMM32_L1(w64); c[2] = IMM32_L2(w64); c[3] = IMM32_L3(w64); c[4] = IMM64_L4(w64); c[5] = IMM64_L5(w64); c[6] = IMM64_L6(w64); c[7] = IMM64_L7(w64); } } /* unused STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) { byte* c; assert(offset + 4 <= as->code_size); c = as->code_base + offset; c[0] = IMM32_L0(w32); c[1] = IMM32_L1(w32); c[2] = IMM32_L2(w32); c[3] = IMM32_L3(w32); } */ STATIC void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int disp_offset) { uint8_t rm_disp; if (disp_offset == 0 && (disp_r64 & 7) != ASM_X64_REG_RBP) { rm_disp = MODRM_RM_DISP0; } else if (SIGNED_FIT8(disp_offset)) { rm_disp = MODRM_RM_DISP8; } else { rm_disp = MODRM_RM_DISP32; } asm_x64_write_byte_1(as, MODRM_R64(r64) | rm_disp | MODRM_RM_R64(disp_r64)); if ((disp_r64 & 7) == ASM_X64_REG_RSP) { // Special case for rsp and r12, they need a SIB byte asm_x64_write_byte_1(as, 0x24); } if (rm_disp == MODRM_RM_DISP8) { asm_x64_write_byte_1(as, IMM32_L0(disp_offset)); } else if (rm_disp == MODRM_RM_DISP32) { asm_x64_write_word32(as, disp_offset); } } STATIC void asm_x64_generic_r64_r64(asm_x64_t *as, int dest_r64, int src_r64, int op) { asm_x64_write_byte_3(as, REX_PREFIX | REX_W | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), op, MODRM_R64(src_r64) | MODRM_RM_REG | MODRM_RM_R64(dest_r64)); } void asm_x64_nop(asm_x64_t *as) { asm_x64_write_byte_1(as, OPCODE_NOP); } void asm_x64_push_r64(asm_x64_t *as, int src_r64) { if (src_r64 < 8) { asm_x64_write_byte_1(as, OPCODE_PUSH_R64 | src_r64); } else { asm_x64_write_byte_2(as, REX_PREFIX | REX_B, OPCODE_PUSH_R64 | (src_r64 & 7)); } } /* void asm_x64_push_i32(asm_x64_t *as, int src_i32) { asm_x64_write_byte_1(as, OPCODE_PUSH_I64); asm_x64_write_word32(as, src_i32); // will be sign extended to 64 bits } */ /* void asm_x64_push_disp(asm_x64_t *as, int src_r64, int src_offset) { assert(src_r64 < 8); asm_x64_write_byte_1(as, OPCODE_PUSH_M64); asm_x64_write_r64_disp(as, 6, src_r64, src_offset); } */ void asm_x64_pop_r64(asm_x64_t *as, int dest_r64) { if (dest_r64 < 8) { asm_x64_write_byte_1(as, OPCODE_POP_R64 | dest_r64); } else { asm_x64_write_byte_2(as, REX_PREFIX | REX_B, OPCODE_POP_R64 | (dest_r64 & 7)); } } STATIC void asm_x64_ret(asm_x64_t *as) { asm_x64_write_byte_1(as, OPCODE_RET); } void asm_x64_mov_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) { asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_MOV_R64_TO_RM64); } void asm_x64_mov_r8_to_mem8(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) { if (src_r64 < 8 && dest_r64 < 8) { asm_x64_write_byte_1(as, OPCODE_MOV_R8_TO_RM8); } else { asm_x64_write_byte_2(as, REX_PREFIX | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), OPCODE_MOV_R8_TO_RM8); } asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp); } void asm_x64_mov_r16_to_mem16(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) { if (src_r64 < 8 && dest_r64 < 8) { asm_x64_write_byte_2(as, OP_SIZE_PREFIX, OPCODE_MOV_R64_TO_RM64); } else { asm_x64_write_byte_3(as, OP_SIZE_PREFIX, REX_PREFIX | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), OPCODE_MOV_R64_TO_RM64); } asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp); } void asm_x64_mov_r32_to_mem32(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) { if (src_r64 < 8 && dest_r64 < 8) { asm_x64_write_byte_1(as, OPCODE_MOV_R64_TO_RM64); } else { asm_x64_write_byte_2(as, REX_PREFIX | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), OPCODE_MOV_R64_TO_RM64); } asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp); } void asm_x64_mov_r64_to_mem64(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) { // use REX prefix for 64 bit operation asm_x64_write_byte_2(as, REX_PREFIX | REX_W | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), OPCODE_MOV_R64_TO_RM64); asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp); } void asm_x64_mov_mem8_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) { assert(src_r64 < 8); if (dest_r64 < 8) { asm_x64_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM8_TO_R64); } else { asm_x64_write_byte_3(as, REX_PREFIX | REX_R, 0x0f, OPCODE_MOVZX_RM8_TO_R64); } asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp); } void asm_x64_mov_mem16_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) { assert(src_r64 < 8); if (dest_r64 < 8) { asm_x64_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM16_TO_R64); } else { asm_x64_write_byte_3(as, REX_PREFIX | REX_R, 0x0f, OPCODE_MOVZX_RM16_TO_R64); } asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp); } void asm_x64_mov_mem32_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) { assert(src_r64 < 8); if (dest_r64 < 8) { asm_x64_write_byte_1(as, OPCODE_MOV_RM64_TO_R64); } else { asm_x64_write_byte_2(as, REX_PREFIX | REX_R, OPCODE_MOV_RM64_TO_R64); } asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp); } void asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) { // use REX prefix for 64 bit operation asm_x64_write_byte_2(as, REX_PREFIX | REX_W | REX_R_FROM_R64(dest_r64) | REX_B_FROM_R64(src_r64), OPCODE_MOV_RM64_TO_R64); asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp); } STATIC void asm_x64_lea_disp_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) { // use REX prefix for 64 bit operation assert(src_r64 < 8); assert(dest_r64 < 8); asm_x64_write_byte_2(as, REX_PREFIX | REX_W, OPCODE_LEA_MEM_TO_R64); asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp); } /* void asm_x64_mov_i8_to_r8(asm_x64_t *as, int src_i8, int dest_r64) { assert(dest_r64 < 8); asm_x64_write_byte_2(as, OPCODE_MOV_I8_TO_R8 | dest_r64, src_i8); } */ size_t asm_x64_mov_i32_to_r64(asm_x64_t *as, int src_i32, int dest_r64) { // cpu defaults to i32 to r64, with zero extension if (dest_r64 < 8) { asm_x64_write_byte_1(as, OPCODE_MOV_I64_TO_R64 | dest_r64); } else { asm_x64_write_byte_2(as, REX_PREFIX | REX_B, OPCODE_MOV_I64_TO_R64 | (dest_r64 & 7)); } size_t loc = mp_asm_base_get_code_pos(&as->base); asm_x64_write_word32(as, src_i32); return loc; } void asm_x64_mov_i64_to_r64(asm_x64_t *as, int64_t src_i64, int dest_r64) { // cpu defaults to i32 to r64 // to mov i64 to r64 need to use REX prefix asm_x64_write_byte_2(as, REX_PREFIX | REX_W | (dest_r64 < 8 ? 0 : REX_B), OPCODE_MOV_I64_TO_R64 | (dest_r64 & 7)); asm_x64_write_word64(as, src_i64); } void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r64) { // TODO use movzx, movsx if possible if (UNSIGNED_FIT32(src_i64)) { // 5 bytes asm_x64_mov_i32_to_r64(as, src_i64 & 0xffffffff, dest_r64); } else { // 10 bytes asm_x64_mov_i64_to_r64(as, src_i64, dest_r64); } } void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) { asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_AND_R64_TO_RM64); } void asm_x64_or_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) { asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_OR_R64_TO_RM64); } void asm_x64_xor_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) { asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_XOR_R64_TO_RM64); } void asm_x64_shl_r64_cl(asm_x64_t* as, int dest_r64) { asm_x64_generic_r64_r64(as, dest_r64, 4, OPCODE_SHL_RM64_CL); } void asm_x64_sar_r64_cl(asm_x64_t* as, int dest_r64) { asm_x64_generic_r64_r64(as, dest_r64, 7, OPCODE_SAR_RM64_CL); } void asm_x64_add_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) { asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_ADD_R64_TO_RM64); } void asm_x64_sub_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) { asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_SUB_R64_FROM_RM64); } void asm_x64_mul_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) { // imul reg64, reg/mem64 -- 0x0f 0xaf /r asm_x64_write_byte_1(as, REX_PREFIX | REX_W | REX_R_FROM_R64(dest_r64) | REX_B_FROM_R64(src_r64)); asm_x64_write_byte_3(as, 0x0f, 0xaf, MODRM_R64(dest_r64) | MODRM_RM_REG | MODRM_RM_R64(src_r64)); } /* void asm_x64_sub_i32_from_r32(asm_x64_t *as, int src_i32, int dest_r32) { if (SIGNED_FIT8(src_i32)) { // defaults to 32 bit operation asm_x64_write_byte_2(as, OPCODE_SUB_I8_FROM_RM64, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(dest_r32)); asm_x64_write_byte_1(as, src_i32 & 0xff); } else { // defaults to 32 bit operation asm_x64_write_byte_2(as, OPCODE_SUB_I32_FROM_RM64, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(dest_r32)); asm_x64_write_word32(as, src_i32); } } */ STATIC void asm_x64_sub_r64_i32(asm_x64_t *as, int dest_r64, int src_i32) { assert(dest_r64 < 8); if (SIGNED_FIT8(src_i32)) { // use REX prefix for 64 bit operation asm_x64_write_byte_3(as, REX_PREFIX | REX_W, OPCODE_SUB_I8_FROM_RM64, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(dest_r64)); asm_x64_write_byte_1(as, src_i32 & 0xff); } else { // use REX prefix for 64 bit operation asm_x64_write_byte_3(as, REX_PREFIX | REX_W, OPCODE_SUB_I32_FROM_RM64, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(dest_r64)); asm_x64_write_word32(as, src_i32); } } /* void asm_x64_shl_r32_by_imm(asm_x64_t *as, int r32, int imm) { asm_x64_write_byte_2(as, OPCODE_SHL_RM32_BY_I8, MODRM_R64(4) | MODRM_RM_REG | MODRM_RM_R64(r32)); asm_x64_write_byte_1(as, imm); } void asm_x64_shr_r32_by_imm(asm_x64_t *as, int r32, int imm) { asm_x64_write_byte_2(as, OPCODE_SHR_RM32_BY_I8, MODRM_R64(5) | MODRM_RM_REG | MODRM_RM_R64(r32)); asm_x64_write_byte_1(as, imm); } void asm_x64_sar_r32_by_imm(asm_x64_t *as, int r32, int imm) { asm_x64_write_byte_2(as, OPCODE_SAR_RM32_BY_I8, MODRM_R64(7) | MODRM_RM_REG | MODRM_RM_R64(r32)); asm_x64_write_byte_1(as, imm); } */ void asm_x64_cmp_r64_with_r64(asm_x64_t *as, int src_r64_a, int src_r64_b) { asm_x64_generic_r64_r64(as, src_r64_b, src_r64_a, OPCODE_CMP_R64_WITH_RM64); } /* void asm_x64_cmp_i32_with_r32(asm_x64_t *as, int src_i32, int src_r32) { if (SIGNED_FIT8(src_i32)) { asm_x64_write_byte_2(as, OPCODE_CMP_I8_WITH_RM32, MODRM_R64(7) | MODRM_RM_REG | MODRM_RM_R64(src_r32)); asm_x64_write_byte_1(as, src_i32 & 0xff); } else { asm_x64_write_byte_2(as, OPCODE_CMP_I32_WITH_RM32, MODRM_R64(7) | MODRM_RM_REG | MODRM_RM_R64(src_r32)); asm_x64_write_word32(as, src_i32); } } */ void asm_x64_test_r8_with_r8(asm_x64_t *as, int src_r64_a, int src_r64_b) { assert(src_r64_a < 8); assert(src_r64_b < 8); asm_x64_write_byte_2(as, OPCODE_TEST_R8_WITH_RM8, MODRM_R64(src_r64_a) | MODRM_RM_REG | MODRM_RM_R64(src_r64_b)); } void asm_x64_test_r64_with_r64(asm_x64_t *as, int src_r64_a, int src_r64_b) { asm_x64_generic_r64_r64(as, src_r64_b, src_r64_a, OPCODE_TEST_R64_WITH_RM64); } void asm_x64_setcc_r8(asm_x64_t *as, int jcc_type, int dest_r8) { assert(dest_r8 < 8); asm_x64_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R64(0) | MODRM_RM_REG | MODRM_RM_R64(dest_r8)); } void asm_x64_jmp_reg(asm_x64_t *as, int src_r64) { assert(src_r64 < 8); asm_x64_write_byte_2(as, OPCODE_JMP_RM64, MODRM_R64(4) | MODRM_RM_REG | MODRM_RM_R64(src_r64)); } STATIC mp_uint_t get_label_dest(asm_x64_t *as, mp_uint_t label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; } void asm_x64_jmp_label(asm_x64_t *as, mp_uint_t label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; if (dest != (mp_uint_t)-1 && rel < 0) { // is a backwards jump, so we know the size of the jump on the first pass // calculate rel assuming 8 bit relative jump rel -= 2; if (SIGNED_FIT8(rel)) { asm_x64_write_byte_2(as, OPCODE_JMP_REL8, rel & 0xff); } else { rel += 2; goto large_jump; } } else { // is a forwards jump, so need to assume it's large large_jump: rel -= 5; asm_x64_write_byte_1(as, OPCODE_JMP_REL32); asm_x64_write_word32(as, rel); } } void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; if (dest != (mp_uint_t)-1 && rel < 0) { // is a backwards jump, so we know the size of the jump on the first pass // calculate rel assuming 8 bit relative jump rel -= 2; if (SIGNED_FIT8(rel)) { asm_x64_write_byte_2(as, OPCODE_JCC_REL8 | jcc_type, rel & 0xff); } else { rel += 2; goto large_jump; } } else { // is a forwards jump, so need to assume it's large large_jump: rel -= 6; asm_x64_write_byte_2(as, OPCODE_JCC_REL32_A, OPCODE_JCC_REL32_B | jcc_type); asm_x64_write_word32(as, rel); } } void asm_x64_entry(asm_x64_t *as, int num_locals) { assert(num_locals >= 0); asm_x64_push_r64(as, ASM_X64_REG_RBP); asm_x64_push_r64(as, ASM_X64_REG_RBX); asm_x64_push_r64(as, ASM_X64_REG_R12); asm_x64_push_r64(as, ASM_X64_REG_R13); num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE); as->num_locals = num_locals; } void asm_x64_exit(asm_x64_t *as) { asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, -as->num_locals * WORD_SIZE); asm_x64_pop_r64(as, ASM_X64_REG_R13); asm_x64_pop_r64(as, ASM_X64_REG_R12); asm_x64_pop_r64(as, ASM_X64_REG_RBX); asm_x64_pop_r64(as, ASM_X64_REG_RBP); asm_x64_ret(as); } // locals: // - stored on the stack in ascending order // - numbered 0 through as->num_locals-1 // - RSP points to the first local // // | RSP // v // l0 l1 l2 ... l(n-1) // ^ ^ // | low address | high address in RAM // STATIC int asm_x64_local_offset_from_rsp(asm_x64_t *as, int local_num) { (void)as; // Stack is full descending, RSP points to local0 return local_num * WORD_SIZE; } void asm_x64_mov_local_to_r64(asm_x64_t *as, int src_local_num, int dest_r64) { asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, src_local_num), dest_r64); } void asm_x64_mov_r64_to_local(asm_x64_t *as, int src_r64, int dest_local_num) { asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, dest_local_num)); } void asm_x64_mov_local_addr_to_r64(asm_x64_t *as, int local_num, int dest_r64) { int offset = asm_x64_local_offset_from_rsp(as, local_num); if (offset == 0) { asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RSP); } else { asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RSP, offset, dest_r64); } } void asm_x64_mov_reg_pcrel(asm_x64_t *as, int dest_r64, mp_uint_t label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - (as->base.code_offset + 7); asm_x64_write_byte_3(as, REX_PREFIX | REX_W | REX_R_FROM_R64(dest_r64), OPCODE_LEA_MEM_TO_R64, MODRM_R64(dest_r64) | MODRM_RM_R64(5)); asm_x64_write_word32(as, rel); } /* void asm_x64_push_local(asm_x64_t *as, int local_num) { asm_x64_push_disp(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, local_num)); } void asm_x64_push_local_addr(asm_x64_t *as, int local_num, int temp_r64) { asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RSP); asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_rsp(as, local_num), temp_r64); asm_x64_push_r64(as, temp_r64); } */ /* can't use these because code might be relocated when resized void asm_x64_call(asm_x64_t *as, void* func) { asm_x64_sub_i32_from_r32(as, 8, ASM_X64_REG_RSP); asm_x64_write_byte_1(as, OPCODE_CALL_REL32); asm_x64_write_word32(as, func - (void*)(as->code_cur + 4)); asm_x64_mov_r64_r64(as, ASM_X64_REG_RSP, ASM_X64_REG_RBP); } void asm_x64_call_i1(asm_x64_t *as, void* func, int i1) { asm_x64_sub_i32_from_r32(as, 8, ASM_X64_REG_RSP); asm_x64_sub_i32_from_r32(as, 12, ASM_X64_REG_RSP); asm_x64_push_i32(as, i1); asm_x64_write_byte_1(as, OPCODE_CALL_REL32); asm_x64_write_word32(as, func - (void*)(as->code_cur + 4)); asm_x64_add_i32_to_r32(as, 16, ASM_X64_REG_RSP); asm_x64_mov_r64_r64(as, ASM_X64_REG_RSP, ASM_X64_REG_RBP); } */ void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r64) { assert(temp_r64 < 8); asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_FUN_TABLE, fun_id * WORD_SIZE, temp_r64); asm_x64_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R64(2) | MODRM_RM_REG | MODRM_RM_R64(temp_r64)); } #endif // MICROPY_EMIT_X64 micropython-1.12/py/asmx64.h000066400000000000000000000240351357706137100157510ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_ASMX64_H #define MICROPY_INCLUDED_PY_ASMX64_H #include "py/mpconfig.h" #include "py/misc.h" #include "py/asmbase.h" // AMD64 calling convention is: // - args pass in: RDI, RSI, RDX, RCX, R08, R09 // - return value in RAX // - stack must be aligned on a 16-byte boundary before all calls // - RAX, RCX, RDX, RSI, RDI, R08, R09, R10, R11 are caller-save // - RBX, RBP, R12, R13, R14, R15 are callee-save // In the functions below, argument order follows x86 docs and generally // the destination is the first argument. // NOTE: this is a change from the old convention used in this file and // some functions still use the old (reverse) convention. #define ASM_X64_REG_RAX (0) #define ASM_X64_REG_RCX (1) #define ASM_X64_REG_RDX (2) #define ASM_X64_REG_RBX (3) #define ASM_X64_REG_RSP (4) #define ASM_X64_REG_RBP (5) #define ASM_X64_REG_RSI (6) #define ASM_X64_REG_RDI (7) #define ASM_X64_REG_R08 (8) #define ASM_X64_REG_R09 (9) #define ASM_X64_REG_R10 (10) #define ASM_X64_REG_R11 (11) #define ASM_X64_REG_R12 (12) #define ASM_X64_REG_R13 (13) #define ASM_X64_REG_R14 (14) #define ASM_X64_REG_R15 (15) // condition codes, used for jcc and setcc (despite their j-name!) #define ASM_X64_CC_JB (0x2) // below, unsigned #define ASM_X64_CC_JZ (0x4) #define ASM_X64_CC_JE (0x4) #define ASM_X64_CC_JNZ (0x5) #define ASM_X64_CC_JNE (0x5) #define ASM_X64_CC_JL (0xc) // less, signed #define ASM_X64_CC_JGE (0xd) // greater or equal, signed #define ASM_X64_CC_JLE (0xe) // less or equal, signed #define ASM_X64_CC_JG (0xf) // greater, signed typedef struct _asm_x64_t { mp_asm_base_t base; int num_locals; } asm_x64_t; static inline void asm_x64_end_pass(asm_x64_t *as) { (void)as; } void asm_x64_nop(asm_x64_t* as); void asm_x64_push_r64(asm_x64_t* as, int src_r64); void asm_x64_pop_r64(asm_x64_t* as, int dest_r64); void asm_x64_mov_r64_r64(asm_x64_t* as, int dest_r64, int src_r64); size_t asm_x64_mov_i32_to_r64(asm_x64_t *as, int src_i32, int dest_r64); void asm_x64_mov_i64_to_r64(asm_x64_t* as, int64_t src_i64, int dest_r64); void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r64); void asm_x64_mov_r8_to_mem8(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp); void asm_x64_mov_r16_to_mem16(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp); void asm_x64_mov_r32_to_mem32(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp); void asm_x64_mov_r64_to_mem64(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp); void asm_x64_mov_mem8_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64); void asm_x64_mov_mem16_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64); void asm_x64_mov_mem32_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64); void asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64); void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64); void asm_x64_or_r64_r64(asm_x64_t *as, int dest_r64, int src_r64); void asm_x64_xor_r64_r64(asm_x64_t *as, int dest_r64, int src_r64); void asm_x64_shl_r64_cl(asm_x64_t* as, int dest_r64); void asm_x64_sar_r64_cl(asm_x64_t* as, int dest_r64); void asm_x64_add_r64_r64(asm_x64_t* as, int dest_r64, int src_r64); void asm_x64_sub_r64_r64(asm_x64_t* as, int dest_r64, int src_r64); void asm_x64_mul_r64_r64(asm_x64_t* as, int dest_r64, int src_r64); void asm_x64_cmp_r64_with_r64(asm_x64_t* as, int src_r64_a, int src_r64_b); void asm_x64_test_r8_with_r8(asm_x64_t* as, int src_r64_a, int src_r64_b); void asm_x64_test_r64_with_r64(asm_x64_t *as, int src_r64_a, int src_r64_b); void asm_x64_setcc_r8(asm_x64_t* as, int jcc_type, int dest_r8); void asm_x64_jmp_reg(asm_x64_t *as, int src_r64); void asm_x64_jmp_label(asm_x64_t* as, mp_uint_t label); void asm_x64_jcc_label(asm_x64_t* as, int jcc_type, mp_uint_t label); void asm_x64_entry(asm_x64_t* as, int num_locals); void asm_x64_exit(asm_x64_t* as); void asm_x64_mov_local_to_r64(asm_x64_t* as, int src_local_num, int dest_r64); void asm_x64_mov_r64_to_local(asm_x64_t* as, int src_r64, int dest_local_num); void asm_x64_mov_local_addr_to_r64(asm_x64_t* as, int local_num, int dest_r64); void asm_x64_mov_reg_pcrel(asm_x64_t *as, int dest_r64, mp_uint_t label); void asm_x64_call_ind(asm_x64_t* as, size_t fun_id, int temp_r32); // Holds a pointer to mp_fun_table #define ASM_X64_REG_FUN_TABLE ASM_X64_REG_RBP #if GENERIC_ASM_API // The following macros provide a (mostly) arch-independent API to // generate native code, and are used by the native emitter. #define ASM_WORD_SIZE (8) #define REG_RET ASM_X64_REG_RAX #define REG_ARG_1 ASM_X64_REG_RDI #define REG_ARG_2 ASM_X64_REG_RSI #define REG_ARG_3 ASM_X64_REG_RDX #define REG_ARG_4 ASM_X64_REG_RCX #define REG_ARG_5 ASM_X64_REG_R08 // caller-save #define REG_TEMP0 ASM_X64_REG_RAX #define REG_TEMP1 ASM_X64_REG_RDI #define REG_TEMP2 ASM_X64_REG_RSI // callee-save #define REG_LOCAL_1 ASM_X64_REG_RBX #define REG_LOCAL_2 ASM_X64_REG_R12 #define REG_LOCAL_3 ASM_X64_REG_R13 #define REG_LOCAL_NUM (3) // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_X64_REG_FUN_TABLE #define ASM_T asm_x64_t #define ASM_END_PASS asm_x64_end_pass #define ASM_ENTRY asm_x64_entry #define ASM_EXIT asm_x64_exit #define ASM_JUMP asm_x64_jmp_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ if (bool_test) { \ asm_x64_test_r8_with_r8((as), (reg), (reg)); \ } else { \ asm_x64_test_r64_with_r64((as), (reg), (reg)); \ } \ asm_x64_jcc_label(as, ASM_X64_CC_JZ, label); \ } while (0) #define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \ do { \ if (bool_test) { \ asm_x64_test_r8_with_r8((as), (reg), (reg)); \ } else { \ asm_x64_test_r64_with_r64((as), (reg), (reg)); \ } \ asm_x64_jcc_label(as, ASM_X64_CC_JNZ, label); \ } while (0) #define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \ do { \ asm_x64_cmp_r64_with_r64(as, reg1, reg2); \ asm_x64_jcc_label(as, ASM_X64_CC_JE, label); \ } while (0) #define ASM_JUMP_REG(as, reg) asm_x64_jmp_reg((as), (reg)) #define ASM_CALL_IND(as, idx) asm_x64_call_ind(as, idx, ASM_X64_REG_RAX) #define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x64_mov_r64_to_local((as), (reg_src), (local_num)) #define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x64_mov_i64_to_r64_optimised((as), (imm), (reg_dest)) #define ASM_MOV_REG_IMM_FIX_U16(as, reg_dest, imm) asm_x64_mov_i32_to_r64((as), (imm), (reg_dest)) #define ASM_MOV_REG_IMM_FIX_WORD(as, reg_dest, imm) asm_x64_mov_i32_to_r64((as), (imm), (reg_dest)) #define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_x64_mov_local_to_r64((as), (local_num), (reg_dest)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x64_mov_r64_r64((as), (reg_dest), (reg_src)) #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x64_mov_local_addr_to_r64((as), (local_num), (reg_dest)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_x64_mov_reg_pcrel((as), (reg_dest), (label)) #define ASM_LSL_REG(as, reg) asm_x64_shl_r64_cl((as), (reg)) #define ASM_ASR_REG(as, reg) asm_x64_sar_r64_cl((as), (reg)) #define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_x64_or_r64_r64((as), (reg_dest), (reg_src)) #define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_x64_xor_r64_r64((as), (reg_dest), (reg_src)) #define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_x64_and_r64_r64((as), (reg_dest), (reg_src)) #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_x64_add_r64_r64((as), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x64_sub_r64_r64((as), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_x64_mul_r64_r64((as), (reg_dest), (reg_src)) #define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem64_to_r64((as), (reg_base), 0, (reg_dest)) #define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x64_mov_mem64_to_r64((as), (reg_base), 8 * (word_offset), (reg_dest)) #define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem8_to_r64zx((as), (reg_base), 0, (reg_dest)) #define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 0, (reg_dest)) #define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem32_to_r64zx((as), (reg_base), 0, (reg_dest)) #define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 0) #define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 8 * (word_offset)) #define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x64_mov_r8_to_mem8((as), (reg_src), (reg_base), 0) #define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x64_mov_r16_to_mem16((as), (reg_src), (reg_base), 0) #define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x64_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) #endif // GENERIC_ASM_API #endif // MICROPY_INCLUDED_PY_ASMX64_H micropython-1.12/py/asmx86.c000066400000000000000000000453201357706137100157500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/mpconfig.h" // wrapper around everything in this file #if MICROPY_EMIT_X86 #include "py/asmx86.h" /* all offsets are measured in multiples of 4 bytes */ #define WORD_SIZE (4) #define OPCODE_NOP (0x90) #define OPCODE_PUSH_R32 (0x50) //#define OPCODE_PUSH_I32 (0x68) //#define OPCODE_PUSH_M32 (0xff) /* /6 */ #define OPCODE_POP_R32 (0x58) #define OPCODE_RET (0xc3) //#define OPCODE_MOV_I8_TO_R8 (0xb0) /* +rb */ #define OPCODE_MOV_I32_TO_R32 (0xb8) //#define OPCODE_MOV_I32_TO_RM32 (0xc7) #define OPCODE_MOV_R8_TO_RM8 (0x88) /* /r */ #define OPCODE_MOV_R32_TO_RM32 (0x89) /* /r */ #define OPCODE_MOV_RM32_TO_R32 (0x8b) /* /r */ #define OPCODE_MOVZX_RM8_TO_R32 (0xb6) /* 0x0f 0xb6/r */ #define OPCODE_MOVZX_RM16_TO_R32 (0xb7) /* 0x0f 0xb7/r */ #define OPCODE_LEA_MEM_TO_R32 (0x8d) /* /r */ #define OPCODE_AND_R32_TO_RM32 (0x21) /* /r */ #define OPCODE_OR_R32_TO_RM32 (0x09) /* /r */ #define OPCODE_XOR_R32_TO_RM32 (0x31) /* /r */ #define OPCODE_ADD_R32_TO_RM32 (0x01) #define OPCODE_ADD_I32_TO_RM32 (0x81) /* /0 */ #define OPCODE_ADD_I8_TO_RM32 (0x83) /* /0 */ #define OPCODE_SUB_R32_FROM_RM32 (0x29) #define OPCODE_SUB_I32_FROM_RM32 (0x81) /* /5 */ #define OPCODE_SUB_I8_FROM_RM32 (0x83) /* /5 */ //#define OPCODE_SHL_RM32_BY_I8 (0xc1) /* /4 */ //#define OPCODE_SHR_RM32_BY_I8 (0xc1) /* /5 */ //#define OPCODE_SAR_RM32_BY_I8 (0xc1) /* /7 */ #define OPCODE_SHL_RM32_CL (0xd3) /* /4 */ #define OPCODE_SAR_RM32_CL (0xd3) /* /7 */ //#define OPCODE_CMP_I32_WITH_RM32 (0x81) /* /7 */ //#define OPCODE_CMP_I8_WITH_RM32 (0x83) /* /7 */ #define OPCODE_CMP_R32_WITH_RM32 (0x39) //#define OPCODE_CMP_RM32_WITH_R32 (0x3b) #define OPCODE_TEST_R8_WITH_RM8 (0x84) /* /r */ #define OPCODE_TEST_R32_WITH_RM32 (0x85) /* /r */ #define OPCODE_JMP_REL8 (0xeb) #define OPCODE_JMP_REL32 (0xe9) #define OPCODE_JMP_RM32 (0xff) /* /4 */ #define OPCODE_JCC_REL8 (0x70) /* | jcc type */ #define OPCODE_JCC_REL32_A (0x0f) #define OPCODE_JCC_REL32_B (0x80) /* | jcc type */ #define OPCODE_SETCC_RM8_A (0x0f) #define OPCODE_SETCC_RM8_B (0x90) /* | jcc type, /0 */ #define OPCODE_CALL_REL32 (0xe8) #define OPCODE_CALL_RM32 (0xff) /* /2 */ #define OPCODE_LEAVE (0xc9) #define MODRM_R32(x) ((x) << 3) #define MODRM_RM_DISP0 (0x00) #define MODRM_RM_DISP8 (0x40) #define MODRM_RM_DISP32 (0x80) #define MODRM_RM_REG (0xc0) #define MODRM_RM_R32(x) (x) #define OP_SIZE_PREFIX (0x66) #define IMM32_L0(x) ((x) & 0xff) #define IMM32_L1(x) (((x) >> 8) & 0xff) #define IMM32_L2(x) (((x) >> 16) & 0xff) #define IMM32_L3(x) (((x) >> 24) & 0xff) #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) STATIC void asm_x86_write_byte_1(asm_x86_t *as, byte b1) { byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 1); if (c != NULL) { c[0] = b1; } } STATIC void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) { byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2); if (c != NULL) { c[0] = b1; c[1] = b2; } } STATIC void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) { byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3); if (c != NULL) { c[0] = b1; c[1] = b2; c[2] = b3; } } STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) { byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4); if (c != NULL) { c[0] = IMM32_L0(w32); c[1] = IMM32_L1(w32); c[2] = IMM32_L2(w32); c[3] = IMM32_L3(w32); } } STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) { uint8_t rm_disp; if (disp_offset == 0 && disp_r32 != ASM_X86_REG_EBP) { rm_disp = MODRM_RM_DISP0; } else if (SIGNED_FIT8(disp_offset)) { rm_disp = MODRM_RM_DISP8; } else { rm_disp = MODRM_RM_DISP32; } asm_x86_write_byte_1(as, MODRM_R32(r32) | rm_disp | MODRM_RM_R32(disp_r32)); if (disp_r32 == ASM_X86_REG_ESP) { // Special case for esp, it needs a SIB byte asm_x86_write_byte_1(as, 0x24); } if (rm_disp == MODRM_RM_DISP8) { asm_x86_write_byte_1(as, IMM32_L0(disp_offset)); } else if (rm_disp == MODRM_RM_DISP32) { asm_x86_write_word32(as, disp_offset); } } STATIC void asm_x86_generic_r32_r32(asm_x86_t *as, int dest_r32, int src_r32, int op) { asm_x86_write_byte_2(as, op, MODRM_R32(src_r32) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); } #if 0 STATIC void asm_x86_nop(asm_x86_t *as) { asm_x86_write_byte_1(as, OPCODE_NOP); } #endif STATIC void asm_x86_push_r32(asm_x86_t *as, int src_r32) { asm_x86_write_byte_1(as, OPCODE_PUSH_R32 | src_r32); } #if 0 void asm_x86_push_i32(asm_x86_t *as, int src_i32) { asm_x86_write_byte_1(as, OPCODE_PUSH_I32); asm_x86_write_word32(as, src_i32); } void asm_x86_push_disp(asm_x86_t *as, int src_r32, int src_offset) { asm_x86_write_byte_1(as, OPCODE_PUSH_M32); asm_x86_write_r32_disp(as, 6, src_r32, src_offset); } #endif STATIC void asm_x86_pop_r32(asm_x86_t *as, int dest_r32) { asm_x86_write_byte_1(as, OPCODE_POP_R32 | dest_r32); } STATIC void asm_x86_ret(asm_x86_t *as) { asm_x86_write_byte_1(as, OPCODE_RET); } void asm_x86_mov_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_MOV_R32_TO_RM32); } void asm_x86_mov_r8_to_mem8(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp) { asm_x86_write_byte_1(as, OPCODE_MOV_R8_TO_RM8); asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp); } void asm_x86_mov_r16_to_mem16(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp) { asm_x86_write_byte_2(as, OP_SIZE_PREFIX, OPCODE_MOV_R32_TO_RM32); asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp); } void asm_x86_mov_r32_to_mem32(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp) { asm_x86_write_byte_1(as, OPCODE_MOV_R32_TO_RM32); asm_x86_write_r32_disp(as, src_r32, dest_r32, dest_disp); } void asm_x86_mov_mem8_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) { asm_x86_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM8_TO_R32); asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp); } void asm_x86_mov_mem16_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) { asm_x86_write_byte_2(as, 0x0f, OPCODE_MOVZX_RM16_TO_R32); asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp); } void asm_x86_mov_mem32_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) { asm_x86_write_byte_1(as, OPCODE_MOV_RM32_TO_R32); asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp); } STATIC void asm_x86_lea_disp_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) { asm_x86_write_byte_1(as, OPCODE_LEA_MEM_TO_R32); asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp); } #if 0 void asm_x86_mov_i8_to_r8(asm_x86_t *as, int src_i8, int dest_r32) { asm_x86_write_byte_2(as, OPCODE_MOV_I8_TO_R8 | dest_r32, src_i8); } #endif size_t asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32) { asm_x86_write_byte_1(as, OPCODE_MOV_I32_TO_R32 | dest_r32); size_t loc = mp_asm_base_get_code_pos(&as->base); asm_x86_write_word32(as, src_i32); return loc; } void asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_AND_R32_TO_RM32); } void asm_x86_or_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_OR_R32_TO_RM32); } void asm_x86_xor_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_XOR_R32_TO_RM32); } void asm_x86_shl_r32_cl(asm_x86_t* as, int dest_r32) { asm_x86_generic_r32_r32(as, dest_r32, 4, OPCODE_SHL_RM32_CL); } void asm_x86_sar_r32_cl(asm_x86_t* as, int dest_r32) { asm_x86_generic_r32_r32(as, dest_r32, 7, OPCODE_SAR_RM32_CL); } void asm_x86_add_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_ADD_R32_TO_RM32); } STATIC void asm_x86_add_i32_to_r32(asm_x86_t *as, int src_i32, int dest_r32) { if (SIGNED_FIT8(src_i32)) { asm_x86_write_byte_2(as, OPCODE_ADD_I8_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); asm_x86_write_byte_1(as, src_i32 & 0xff); } else { asm_x86_write_byte_2(as, OPCODE_ADD_I32_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); asm_x86_write_word32(as, src_i32); } } void asm_x86_sub_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_SUB_R32_FROM_RM32); } STATIC void asm_x86_sub_r32_i32(asm_x86_t *as, int dest_r32, int src_i32) { if (SIGNED_FIT8(src_i32)) { // defaults to 32 bit operation asm_x86_write_byte_2(as, OPCODE_SUB_I8_FROM_RM32, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); asm_x86_write_byte_1(as, src_i32 & 0xff); } else { // defaults to 32 bit operation asm_x86_write_byte_2(as, OPCODE_SUB_I32_FROM_RM32, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); asm_x86_write_word32(as, src_i32); } } void asm_x86_mul_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { // imul reg32, reg/mem32 -- 0x0f 0xaf /r asm_x86_write_byte_3(as, 0x0f, 0xaf, MODRM_R32(dest_r32) | MODRM_RM_REG | MODRM_RM_R32(src_r32)); } #if 0 /* shifts not tested */ void asm_x86_shl_r32_by_imm(asm_x86_t *as, int r32, int imm) { asm_x86_write_byte_2(as, OPCODE_SHL_RM32_BY_I8, MODRM_R32(4) | MODRM_RM_REG | MODRM_RM_R32(r32)); asm_x86_write_byte_1(as, imm); } void asm_x86_shr_r32_by_imm(asm_x86_t *as, int r32, int imm) { asm_x86_write_byte_2(as, OPCODE_SHR_RM32_BY_I8, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(r32)); asm_x86_write_byte_1(as, imm); } void asm_x86_sar_r32_by_imm(asm_x86_t *as, int r32, int imm) { asm_x86_write_byte_2(as, OPCODE_SAR_RM32_BY_I8, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(r32)); asm_x86_write_byte_1(as, imm); } #endif void asm_x86_cmp_r32_with_r32(asm_x86_t *as, int src_r32_a, int src_r32_b) { asm_x86_generic_r32_r32(as, src_r32_b, src_r32_a, OPCODE_CMP_R32_WITH_RM32); } #if 0 void asm_x86_cmp_i32_with_r32(asm_x86_t *as, int src_i32, int src_r32) { if (SIGNED_FIT8(src_i32)) { asm_x86_write_byte_2(as, OPCODE_CMP_I8_WITH_RM32, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(src_r32)); asm_x86_write_byte_1(as, src_i32 & 0xff); } else { asm_x86_write_byte_2(as, OPCODE_CMP_I32_WITH_RM32, MODRM_R32(7) | MODRM_RM_REG | MODRM_RM_R32(src_r32)); asm_x86_write_word32(as, src_i32); } } #endif void asm_x86_test_r8_with_r8(asm_x86_t *as, int src_r32_a, int src_r32_b) { asm_x86_write_byte_2(as, OPCODE_TEST_R8_WITH_RM8, MODRM_R32(src_r32_a) | MODRM_RM_REG | MODRM_RM_R32(src_r32_b)); } void asm_x86_test_r32_with_r32(asm_x86_t *as, int src_r32_a, int src_r32_b) { asm_x86_generic_r32_r32(as, src_r32_b, src_r32_a, OPCODE_TEST_R32_WITH_RM32); } void asm_x86_setcc_r8(asm_x86_t *as, mp_uint_t jcc_type, int dest_r8) { asm_x86_write_byte_3(as, OPCODE_SETCC_RM8_A, OPCODE_SETCC_RM8_B | jcc_type, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r8)); } void asm_x86_jmp_reg(asm_x86_t *as, int src_r32) { asm_x86_write_byte_2(as, OPCODE_JMP_RM32, MODRM_R32(4) | MODRM_RM_REG | MODRM_RM_R32(src_r32)); } STATIC mp_uint_t get_label_dest(asm_x86_t *as, mp_uint_t label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; } void asm_x86_jmp_label(asm_x86_t *as, mp_uint_t label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; if (dest != (mp_uint_t)-1 && rel < 0) { // is a backwards jump, so we know the size of the jump on the first pass // calculate rel assuming 8 bit relative jump rel -= 2; if (SIGNED_FIT8(rel)) { asm_x86_write_byte_2(as, OPCODE_JMP_REL8, rel & 0xff); } else { rel += 2; goto large_jump; } } else { // is a forwards jump, so need to assume it's large large_jump: rel -= 5; asm_x86_write_byte_1(as, OPCODE_JMP_REL32); asm_x86_write_word32(as, rel); } } void asm_x86_jcc_label(asm_x86_t *as, mp_uint_t jcc_type, mp_uint_t label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; if (dest != (mp_uint_t)-1 && rel < 0) { // is a backwards jump, so we know the size of the jump on the first pass // calculate rel assuming 8 bit relative jump rel -= 2; if (SIGNED_FIT8(rel)) { asm_x86_write_byte_2(as, OPCODE_JCC_REL8 | jcc_type, rel & 0xff); } else { rel += 2; goto large_jump; } } else { // is a forwards jump, so need to assume it's large large_jump: rel -= 6; asm_x86_write_byte_2(as, OPCODE_JCC_REL32_A, OPCODE_JCC_REL32_B | jcc_type); asm_x86_write_word32(as, rel); } } void asm_x86_entry(asm_x86_t *as, int num_locals) { assert(num_locals >= 0); asm_x86_push_r32(as, ASM_X86_REG_EBP); asm_x86_push_r32(as, ASM_X86_REG_EBX); asm_x86_push_r32(as, ASM_X86_REG_ESI); asm_x86_push_r32(as, ASM_X86_REG_EDI); num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, num_locals * WORD_SIZE); as->num_locals = num_locals; } void asm_x86_exit(asm_x86_t *as) { asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, -as->num_locals * WORD_SIZE); asm_x86_pop_r32(as, ASM_X86_REG_EDI); asm_x86_pop_r32(as, ASM_X86_REG_ESI); asm_x86_pop_r32(as, ASM_X86_REG_EBX); asm_x86_pop_r32(as, ASM_X86_REG_EBP); asm_x86_ret(as); } STATIC int asm_x86_arg_offset_from_esp(asm_x86_t *as, size_t arg_num) { // Above esp are: locals, 4 saved registers, return eip, arguments return (as->num_locals + 4 + 1 + arg_num) * WORD_SIZE; } #if 0 void asm_x86_push_arg(asm_x86_t *as, int src_arg_num) { asm_x86_push_disp(as, ASM_X86_REG_ESP, asm_x86_arg_offset_from_esp(as, src_arg_num)); } #endif void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32) { asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_ESP, asm_x86_arg_offset_from_esp(as, src_arg_num), dest_r32); } #if 0 void asm_x86_mov_r32_to_arg(asm_x86_t *as, int src_r32, int dest_arg_num) { asm_x86_mov_r32_to_mem32(as, src_r32, ASM_X86_REG_ESP, asm_x86_arg_offset_from_esp(as, dest_arg_num)); } #endif // locals: // - stored on the stack in ascending order // - numbered 0 through as->num_locals-1 // - ESP points to the first local // // | ESP // v // l0 l1 l2 ... l(n-1) // ^ ^ // | low address | high address in RAM // STATIC int asm_x86_local_offset_from_esp(asm_x86_t *as, int local_num) { (void)as; // Stack is full descending, ESP points to local0 return local_num * WORD_SIZE; } void asm_x86_mov_local_to_r32(asm_x86_t *as, int src_local_num, int dest_r32) { asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_ESP, asm_x86_local_offset_from_esp(as, src_local_num), dest_r32); } void asm_x86_mov_r32_to_local(asm_x86_t *as, int src_r32, int dest_local_num) { asm_x86_mov_r32_to_mem32(as, src_r32, ASM_X86_REG_ESP, asm_x86_local_offset_from_esp(as, dest_local_num)); } void asm_x86_mov_local_addr_to_r32(asm_x86_t *as, int local_num, int dest_r32) { int offset = asm_x86_local_offset_from_esp(as, local_num); if (offset == 0) { asm_x86_mov_r32_r32(as, dest_r32, ASM_X86_REG_ESP); } else { asm_x86_lea_disp_to_r32(as, ASM_X86_REG_ESP, offset, dest_r32); } } void asm_x86_mov_reg_pcrel(asm_x86_t *as, int dest_r32, mp_uint_t label) { asm_x86_write_byte_1(as, OPCODE_CALL_REL32); asm_x86_write_word32(as, 0); mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; asm_x86_pop_r32(as, dest_r32); // PC rel is usually a forward reference, so need to assume it's large asm_x86_write_byte_2(as, OPCODE_ADD_I32_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); asm_x86_write_word32(as, rel); } #if 0 void asm_x86_push_local(asm_x86_t *as, int local_num) { asm_x86_push_disp(as, ASM_X86_REG_ESP, asm_x86_local_offset_from_esp(as, local_num)); } void asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32) { asm_x86_mov_r32_r32(as, temp_r32, ASM_X86_REG_ESP); asm_x86_add_i32_to_r32(as, asm_x86_local_offset_from_esp(as, local_num), temp_r32); asm_x86_push_r32(as, temp_r32); } #endif void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r32) { // TODO align stack on 16-byte boundary before the call assert(n_args <= 5); if (n_args > 4) { asm_x86_push_r32(as, ASM_X86_REG_ARG_5); } if (n_args > 3) { asm_x86_push_r32(as, ASM_X86_REG_ARG_4); } if (n_args > 2) { asm_x86_push_r32(as, ASM_X86_REG_ARG_3); } if (n_args > 1) { asm_x86_push_r32(as, ASM_X86_REG_ARG_2); } if (n_args > 0) { asm_x86_push_r32(as, ASM_X86_REG_ARG_1); } // Load the pointer to the function and make the call asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_FUN_TABLE, fun_id * WORD_SIZE, temp_r32); asm_x86_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R32(2) | MODRM_RM_REG | MODRM_RM_R32(temp_r32)); // the caller must clean up the stack if (n_args > 0) { asm_x86_add_i32_to_r32(as, WORD_SIZE * n_args, ASM_X86_REG_ESP); } } #endif // MICROPY_EMIT_X86 micropython-1.12/py/asmx86.h000066400000000000000000000237401357706137100157570ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_ASMX86_H #define MICROPY_INCLUDED_PY_ASMX86_H #include "py/mpconfig.h" #include "py/misc.h" #include "py/asmbase.h" // x86 cdecl calling convention is: // - args passed on the stack in reverse order // - return value in EAX // - caller cleans up the stack after a call // - stack must be aligned to 16-byte boundary before all calls // - EAX, ECX, EDX are caller-save // - EBX, ESI, EDI, EBP, ESP, EIP are callee-save // In the functions below, argument order follows x86 docs and generally // the destination is the first argument. // NOTE: this is a change from the old convention used in this file and // some functions still use the old (reverse) convention. #define ASM_X86_REG_EAX (0) #define ASM_X86_REG_ECX (1) #define ASM_X86_REG_EDX (2) #define ASM_X86_REG_EBX (3) #define ASM_X86_REG_ESP (4) #define ASM_X86_REG_EBP (5) #define ASM_X86_REG_ESI (6) #define ASM_X86_REG_EDI (7) // x86 passes values on the stack, but the emitter is register based, so we need // to define registers that can temporarily hold the function arguments. They // need to be defined here so that asm_x86_call_ind can push them onto the stack // before the call. #define ASM_X86_REG_ARG_1 ASM_X86_REG_EAX #define ASM_X86_REG_ARG_2 ASM_X86_REG_ECX #define ASM_X86_REG_ARG_3 ASM_X86_REG_EDX #define ASM_X86_REG_ARG_4 ASM_X86_REG_EBX #define ASM_X86_REG_ARG_5 ASM_X86_REG_ESI // condition codes, used for jcc and setcc (despite their j-name!) #define ASM_X86_CC_JB (0x2) // below, unsigned #define ASM_X86_CC_JZ (0x4) #define ASM_X86_CC_JE (0x4) #define ASM_X86_CC_JNZ (0x5) #define ASM_X86_CC_JNE (0x5) #define ASM_X86_CC_JL (0xc) // less, signed #define ASM_X86_CC_JGE (0xd) // greater or equal, signed #define ASM_X86_CC_JLE (0xe) // less or equal, signed #define ASM_X86_CC_JG (0xf) // greater, signed typedef struct _asm_x86_t { mp_asm_base_t base; int num_locals; } asm_x86_t; static inline void asm_x86_end_pass(asm_x86_t *as) { (void)as; } void asm_x86_mov_r32_r32(asm_x86_t* as, int dest_r32, int src_r32); size_t asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32); void asm_x86_mov_r8_to_mem8(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp); void asm_x86_mov_r16_to_mem16(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp); void asm_x86_mov_r32_to_mem32(asm_x86_t *as, int src_r32, int dest_r32, int dest_disp); void asm_x86_mov_mem8_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32); void asm_x86_mov_mem16_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32); void asm_x86_mov_mem32_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32); void asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32); void asm_x86_or_r32_r32(asm_x86_t *as, int dest_r32, int src_r32); void asm_x86_xor_r32_r32(asm_x86_t *as, int dest_r32, int src_r32); void asm_x86_shl_r32_cl(asm_x86_t* as, int dest_r32); void asm_x86_sar_r32_cl(asm_x86_t* as, int dest_r32); void asm_x86_add_r32_r32(asm_x86_t* as, int dest_r32, int src_r32); void asm_x86_sub_r32_r32(asm_x86_t* as, int dest_r32, int src_r32); void asm_x86_mul_r32_r32(asm_x86_t* as, int dest_r32, int src_r32); void asm_x86_cmp_r32_with_r32(asm_x86_t* as, int src_r32_a, int src_r32_b); void asm_x86_test_r8_with_r8(asm_x86_t* as, int src_r32_a, int src_r32_b); void asm_x86_test_r32_with_r32(asm_x86_t* as, int src_r32_a, int src_r32_b); void asm_x86_setcc_r8(asm_x86_t* as, mp_uint_t jcc_type, int dest_r8); void asm_x86_jmp_reg(asm_x86_t *as, int src_r86); void asm_x86_jmp_label(asm_x86_t* as, mp_uint_t label); void asm_x86_jcc_label(asm_x86_t* as, mp_uint_t jcc_type, mp_uint_t label); void asm_x86_entry(asm_x86_t* as, int num_locals); void asm_x86_exit(asm_x86_t* as); void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32); void asm_x86_mov_local_to_r32(asm_x86_t* as, int src_local_num, int dest_r32); void asm_x86_mov_r32_to_local(asm_x86_t* as, int src_r32, int dest_local_num); void asm_x86_mov_local_addr_to_r32(asm_x86_t* as, int local_num, int dest_r32); void asm_x86_mov_reg_pcrel(asm_x86_t *as, int dest_r64, mp_uint_t label); void asm_x86_call_ind(asm_x86_t* as, size_t fun_id, mp_uint_t n_args, int temp_r32); // Holds a pointer to mp_fun_table #define ASM_X86_REG_FUN_TABLE ASM_X86_REG_EBP #if GENERIC_ASM_API // The following macros provide a (mostly) arch-independent API to // generate native code, and are used by the native emitter. #define ASM_WORD_SIZE (4) #define REG_RET ASM_X86_REG_EAX #define REG_ARG_1 ASM_X86_REG_ARG_1 #define REG_ARG_2 ASM_X86_REG_ARG_2 #define REG_ARG_3 ASM_X86_REG_ARG_3 #define REG_ARG_4 ASM_X86_REG_ARG_4 #define REG_ARG_5 ASM_X86_REG_ARG_5 // caller-save, so can be used as temporaries #define REG_TEMP0 ASM_X86_REG_EAX #define REG_TEMP1 ASM_X86_REG_ECX #define REG_TEMP2 ASM_X86_REG_EDX // callee-save, so can be used as locals #define REG_LOCAL_1 ASM_X86_REG_EBX #define REG_LOCAL_2 ASM_X86_REG_ESI #define REG_LOCAL_3 ASM_X86_REG_EDI #define REG_LOCAL_NUM (3) // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_X86_REG_FUN_TABLE #define ASM_T asm_x86_t #define ASM_END_PASS asm_x86_end_pass #define ASM_ENTRY asm_x86_entry #define ASM_EXIT asm_x86_exit #define ASM_JUMP asm_x86_jmp_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ if (bool_test) { \ asm_x86_test_r8_with_r8(as, reg, reg); \ } else { \ asm_x86_test_r32_with_r32(as, reg, reg); \ } \ asm_x86_jcc_label(as, ASM_X86_CC_JZ, label); \ } while (0) #define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \ do { \ if (bool_test) { \ asm_x86_test_r8_with_r8(as, reg, reg); \ } else { \ asm_x86_test_r32_with_r32(as, reg, reg); \ } \ asm_x86_jcc_label(as, ASM_X86_CC_JNZ, label); \ } while (0) #define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \ do { \ asm_x86_cmp_r32_with_r32(as, reg1, reg2); \ asm_x86_jcc_label(as, ASM_X86_CC_JE, label); \ } while (0) #define ASM_JUMP_REG(as, reg) asm_x86_jmp_reg((as), (reg)) #define ASM_CALL_IND(as, idx) asm_x86_call_ind(as, idx, mp_f_n_args[idx], ASM_X86_REG_EAX) #define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x86_mov_r32_to_local((as), (reg_src), (local_num)) #define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32((as), (imm), (reg_dest)) #define ASM_MOV_REG_IMM_FIX_U16(as, reg_dest, imm) asm_x86_mov_i32_to_r32((as), (imm), (reg_dest)) #define ASM_MOV_REG_IMM_FIX_WORD(as, reg_dest, imm) asm_x86_mov_i32_to_r32((as), (imm), (reg_dest)) #define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_x86_mov_local_to_r32((as), (local_num), (reg_dest)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x86_mov_r32_r32((as), (reg_dest), (reg_src)) #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x86_mov_local_addr_to_r32((as), (local_num), (reg_dest)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_x86_mov_reg_pcrel((as), (reg_dest), (label)) #define ASM_LSL_REG(as, reg) asm_x86_shl_r32_cl((as), (reg)) #define ASM_ASR_REG(as, reg) asm_x86_sar_r32_cl((as), (reg)) #define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_x86_or_r32_r32((as), (reg_dest), (reg_src)) #define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_x86_xor_r32_r32((as), (reg_dest), (reg_src)) #define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_x86_and_r32_r32((as), (reg_dest), (reg_src)) #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_x86_add_r32_r32((as), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x86_sub_r32_r32((as), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_x86_mul_r32_r32((as), (reg_dest), (reg_src)) #define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest)) #define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x86_mov_mem32_to_r32((as), (reg_base), 4 * (word_offset), (reg_dest)) #define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem8_to_r32zx((as), (reg_base), 0, (reg_dest)) #define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 0, (reg_dest)) #define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest)) #define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) #define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (word_offset)) #define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x86_mov_r8_to_mem8((as), (reg_src), (reg_base), 0) #define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x86_mov_r16_to_mem16((as), (reg_src), (reg_base), 0) #define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) #endif // GENERIC_ASM_API #endif // MICROPY_INCLUDED_PY_ASMX86_H micropython-1.12/py/asmxtensa.c000066400000000000000000000226221357706137100166250ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpconfig.h" // wrapper around everything in this file #if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN #include "py/asmxtensa.h" #define WORD_SIZE (4) #define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)) #define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)) void asm_xtensa_end_pass(asm_xtensa_t *as) { as->num_const = as->cur_const; as->cur_const = 0; #if 0 // make a hex dump of the machine code if (as->base.pass == MP_ASM_PASS_EMIT) { uint8_t *d = as->base.code_base; printf("XTENSA ASM:"); for (int i = 0; i < ((as->base.code_size + 15) & ~15); ++i) { if (i % 16 == 0) { printf("\n%08x:", (uint32_t)&d[i]); } if (i % 2 == 0) { printf(" "); } printf("%02x", d[i]); } printf("\n"); } #endif } void asm_xtensa_entry(asm_xtensa_t *as, int num_locals) { // jump over the constants asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4); mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte as->const_table = (uint32_t*)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); // adjust the stack-pointer to store a0, a12, a13, a14, a15 and locals, 16-byte aligned as->stack_adjust = (((ASM_XTENSA_NUM_REGS_SAVED + num_locals) * WORD_SIZE) + 15) & ~15; if (SIGNED_FIT8(-as->stack_adjust)) { asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, -as->stack_adjust); } else { asm_xtensa_op_movi(as, ASM_XTENSA_REG_A9, as->stack_adjust); asm_xtensa_op_sub(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A9); } // save return value (a0) and callee-save registers (a12, a13, a14, a15) asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0); for (int i = 1; i < ASM_XTENSA_NUM_REGS_SAVED; ++i) { asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A11 + i, ASM_XTENSA_REG_A1, i); } } void asm_xtensa_exit(asm_xtensa_t *as) { // restore registers for (int i = ASM_XTENSA_NUM_REGS_SAVED - 1; i >= 1; --i) { asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A11 + i, ASM_XTENSA_REG_A1, i); } asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0); // restore stack-pointer and return if (SIGNED_FIT8(as->stack_adjust)) { asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, as->stack_adjust); } else { asm_xtensa_op_movi(as, ASM_XTENSA_REG_A9, as->stack_adjust); asm_xtensa_op_add_n(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A9); } asm_xtensa_op_ret_n(as); } void asm_xtensa_entry_win(asm_xtensa_t *as, int num_locals) { // jump over the constants asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4); mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte as->const_table = (uint32_t*)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); as->stack_adjust = 32 + ((((ASM_XTENSA_NUM_REGS_SAVED_WIN + num_locals) * WORD_SIZE) + 15) & ~15); asm_xtensa_op_entry(as, ASM_XTENSA_REG_A1, as->stack_adjust); asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0); } void asm_xtensa_exit_win(asm_xtensa_t *as) { asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0); asm_xtensa_op_retw_n(as); } STATIC uint32_t get_label_dest(asm_xtensa_t *as, uint label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; } void asm_xtensa_op16(asm_xtensa_t *as, uint16_t op) { uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2); if (c != NULL) { c[0] = op; c[1] = op >> 8; } } void asm_xtensa_op24(asm_xtensa_t *as, uint32_t op) { uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3); if (c != NULL) { c[0] = op; c[1] = op >> 8; c[2] = op >> 16; } } void asm_xtensa_j_label(asm_xtensa_t *as, uint label) { uint32_t dest = get_label_dest(as, label); int32_t rel = dest - as->base.code_offset - 4; // we assume rel, as a signed int, fits in 18-bits asm_xtensa_op_j(as, rel); } void asm_xtensa_bccz_reg_label(asm_xtensa_t *as, uint cond, uint reg, uint label) { uint32_t dest = get_label_dest(as, label); int32_t rel = dest - as->base.code_offset - 4; if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT12(rel)) { printf("ERROR: xtensa bccz out of range\n"); } asm_xtensa_op_bccz(as, cond, reg, rel); } void asm_xtensa_bcc_reg_reg_label(asm_xtensa_t *as, uint cond, uint reg1, uint reg2, uint label) { uint32_t dest = get_label_dest(as, label); int32_t rel = dest - as->base.code_offset - 4; if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) { printf("ERROR: xtensa bcc out of range\n"); } asm_xtensa_op_bcc(as, cond, reg1, reg2, rel); } // convenience function; reg_dest must be different from reg_src[12] void asm_xtensa_setcc_reg_reg_reg(asm_xtensa_t *as, uint cond, uint reg_dest, uint reg_src1, uint reg_src2) { asm_xtensa_op_movi_n(as, reg_dest, 1); asm_xtensa_op_bcc(as, cond, reg_src1, reg_src2, 1); asm_xtensa_op_movi_n(as, reg_dest, 0); } size_t asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32) { // load the constant uint32_t const_table_offset = (uint8_t*)as->const_table - as->base.code_base; size_t loc = const_table_offset + as->cur_const * WORD_SIZE; asm_xtensa_op_l32r(as, reg_dest, as->base.code_offset, loc); // store the constant in the table if (as->const_table != NULL) { as->const_table[as->cur_const] = i32; } ++as->cur_const; return loc; } void asm_xtensa_mov_reg_i32_optimised(asm_xtensa_t *as, uint reg_dest, uint32_t i32) { if (SIGNED_FIT12(i32)) { asm_xtensa_op_movi(as, reg_dest, i32); } else { asm_xtensa_mov_reg_i32(as, reg_dest, i32); } } void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src) { asm_xtensa_op_s32i(as, reg_src, ASM_XTENSA_REG_A1, local_num); } void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num) { asm_xtensa_op_l32i(as, reg_dest, ASM_XTENSA_REG_A1, local_num); } void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num) { uint off = local_num * WORD_SIZE; if (SIGNED_FIT8(off)) { asm_xtensa_op_addi(as, reg_dest, ASM_XTENSA_REG_A1, off); } else { asm_xtensa_op_movi(as, reg_dest, off); asm_xtensa_op_add_n(as, reg_dest, reg_dest, ASM_XTENSA_REG_A1); } } void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label) { // Get relative offset from PC uint32_t dest = get_label_dest(as, label); int32_t rel = dest - as->base.code_offset; rel -= 3 + 3; // account for 3 bytes of movi instruction, 3 bytes call0 adjustment asm_xtensa_op_movi(as, reg_dest, rel); // imm has 12-bit range // Use call0 to get PC+3 into a0 // call0 destination must be aligned on 4 bytes: // - code_offset&3=0: off=0, pad=1 // - code_offset&3=1: off=0, pad=0 // - code_offset&3=2: off=1, pad=3 // - code_offset&3=3: off=1, pad=2 uint32_t off = as->base.code_offset >> 1 & 1; uint32_t pad = (5 - as->base.code_offset) & 3; asm_xtensa_op_call0(as, off); mp_asm_base_get_cur_to_write_bytes(&as->base, pad); // Add PC to relative offset asm_xtensa_op_add_n(as, reg_dest, reg_dest, ASM_XTENSA_REG_A0); } void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx) { if (idx < 16) { asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx); } else { asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_FUN_TABLE, idx); } asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0); } void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) { if (idx < 16) { asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx); } else { asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx); } asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8); } #endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN micropython-1.12/py/asmxtensa.h000066400000000000000000000422671357706137100166410ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_ASMXTENSA_H #define MICROPY_INCLUDED_PY_ASMXTENSA_H #include "py/misc.h" #include "py/asmbase.h" // calling conventions: // up to 6 args in a2-a7 // return value in a2 // PC stored in a0 // stack pointer is a1, stack full descending, is aligned to 16 bytes // callee save: a1, a12, a13, a14, a15 // caller save: a3 // With windowed registers, size 8: // - a0: return PC // - a1: stack pointer, full descending, aligned to 16 bytes // - a2-a7: incoming args, and essentially callee save // - a2: return value // - a8-a15: caller save temporaries // - a10-a15: input args to called function // - a10: return value of called function // note: a0-a7 are saved automatically via window shift of called function #define ASM_XTENSA_REG_A0 (0) #define ASM_XTENSA_REG_A1 (1) #define ASM_XTENSA_REG_A2 (2) #define ASM_XTENSA_REG_A3 (3) #define ASM_XTENSA_REG_A4 (4) #define ASM_XTENSA_REG_A5 (5) #define ASM_XTENSA_REG_A6 (6) #define ASM_XTENSA_REG_A7 (7) #define ASM_XTENSA_REG_A8 (8) #define ASM_XTENSA_REG_A9 (9) #define ASM_XTENSA_REG_A10 (10) #define ASM_XTENSA_REG_A11 (11) #define ASM_XTENSA_REG_A12 (12) #define ASM_XTENSA_REG_A13 (13) #define ASM_XTENSA_REG_A14 (14) #define ASM_XTENSA_REG_A15 (15) // for bccz #define ASM_XTENSA_CCZ_EQ (0) #define ASM_XTENSA_CCZ_NE (1) // for bcc and setcc #define ASM_XTENSA_CC_NONE (0) #define ASM_XTENSA_CC_EQ (1) #define ASM_XTENSA_CC_LT (2) #define ASM_XTENSA_CC_LTU (3) #define ASM_XTENSA_CC_ALL (4) #define ASM_XTENSA_CC_BC (5) #define ASM_XTENSA_CC_ANY (8) #define ASM_XTENSA_CC_NE (9) #define ASM_XTENSA_CC_GE (10) #define ASM_XTENSA_CC_GEU (11) #define ASM_XTENSA_CC_NALL (12) #define ASM_XTENSA_CC_BS (13) // macros for encoding instructions (little endian versions) #define ASM_XTENSA_ENCODE_RRR(op0, op1, op2, r, s, t) \ ((((uint32_t)op2) << 20) | (((uint32_t)op1) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0)) #define ASM_XTENSA_ENCODE_RRI4(op0, op1, r, s, t, imm4) \ (((imm4) << 20) | ((op1) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0)) #define ASM_XTENSA_ENCODE_RRI8(op0, r, s, t, imm8) \ ((((uint32_t)imm8) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0)) #define ASM_XTENSA_ENCODE_RI16(op0, t, imm16) \ (((imm16) << 8) | ((t) << 4) | (op0)) #define ASM_XTENSA_ENCODE_RSR(op0, op1, op2, rs, t) \ (((op2) << 20) | ((op1) << 16) | ((rs) << 8) | ((t) << 4) | (op0)) #define ASM_XTENSA_ENCODE_CALL(op0, n, offset) \ (((offset) << 6) | ((n) << 4) | (op0)) #define ASM_XTENSA_ENCODE_CALLX(op0, op1, op2, r, s, m, n) \ ((((uint32_t)op2) << 20) | (((uint32_t)op1) << 16) | ((r) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0)) #define ASM_XTENSA_ENCODE_BRI8(op0, r, s, m, n, imm8) \ (((imm8) << 16) | ((r) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0)) #define ASM_XTENSA_ENCODE_BRI12(op0, s, m, n, imm12) \ (((imm12) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0)) #define ASM_XTENSA_ENCODE_RRRN(op0, r, s, t) \ (((r) << 12) | ((s) << 8) | ((t) << 4) | (op0)) #define ASM_XTENSA_ENCODE_RI7(op0, s, imm7) \ ((((imm7) & 0xf) << 12) | ((s) << 8) | ((imm7) & 0x70) | (op0)) // Number of registers saved on the stack upon entry to function #define ASM_XTENSA_NUM_REGS_SAVED (5) #define ASM_XTENSA_NUM_REGS_SAVED_WIN (1) typedef struct _asm_xtensa_t { mp_asm_base_t base; uint32_t cur_const; uint32_t num_const; uint32_t *const_table; uint32_t stack_adjust; } asm_xtensa_t; void asm_xtensa_end_pass(asm_xtensa_t *as); void asm_xtensa_entry(asm_xtensa_t *as, int num_locals); void asm_xtensa_exit(asm_xtensa_t *as); void asm_xtensa_entry_win(asm_xtensa_t *as, int num_locals); void asm_xtensa_exit_win(asm_xtensa_t *as); void asm_xtensa_op16(asm_xtensa_t *as, uint16_t op); void asm_xtensa_op24(asm_xtensa_t *as, uint32_t op); // raw instructions static inline void asm_xtensa_op_entry(asm_xtensa_t *as, uint reg_src, int32_t num_bytes) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_BRI12(6, reg_src, 0, 3, (num_bytes / 8) & 0xfff)); } static inline void asm_xtensa_op_add_n(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(10, reg_dest, reg_src_a, reg_src_b)); } static inline void asm_xtensa_op_addi(asm_xtensa_t *as, uint reg_dest, uint reg_src, int imm8) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 12, reg_src, reg_dest, imm8 & 0xff)); } static inline void asm_xtensa_op_and(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 1, reg_dest, reg_src_a, reg_src_b)); } static inline void asm_xtensa_op_bcc(asm_xtensa_t *as, uint cond, uint reg_src1, uint reg_src2, int32_t rel8) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(7, cond, reg_src1, reg_src2, rel8 & 0xff)); } static inline void asm_xtensa_op_bccz(asm_xtensa_t *as, uint cond, uint reg_src, int32_t rel12) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_BRI12(6, reg_src, cond, 1, rel12 & 0xfff)); } static inline void asm_xtensa_op_call0(asm_xtensa_t *as, int32_t rel18) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALL(5, 0, rel18 & 0x3ffff)); } static inline void asm_xtensa_op_callx0(asm_xtensa_t *as, uint reg) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALLX(0, 0, 0, 0, reg, 3, 0)); } static inline void asm_xtensa_op_callx8(asm_xtensa_t *as, uint reg) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALLX(0, 0, 0, 0, reg, 3, 2)); } static inline void asm_xtensa_op_j(asm_xtensa_t *as, int32_t rel18) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALL(6, 0, rel18 & 0x3ffff)); } static inline void asm_xtensa_op_jx(asm_xtensa_t *as, uint reg) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALLX(0, 0, 0, 0, reg, 2, 2)); } static inline void asm_xtensa_op_l8ui(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint byte_offset) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 0, reg_base, reg_dest, byte_offset & 0xff)); } static inline void asm_xtensa_op_l16ui(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint half_word_offset) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 1, reg_base, reg_dest, half_word_offset & 0xff)); } static inline void asm_xtensa_op_l32i(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 2, reg_base, reg_dest, word_offset & 0xff)); } static inline void asm_xtensa_op_l32i_n(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(8, word_offset & 0xf, reg_base, reg_dest)); } static inline void asm_xtensa_op_l32r(asm_xtensa_t *as, uint reg_dest, uint32_t op_off, uint32_t dest_off) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RI16(1, reg_dest, ((dest_off - ((op_off + 3) & ~3)) >> 2) & 0xffff)); } static inline void asm_xtensa_op_mov_n(asm_xtensa_t *as, uint reg_dest, uint reg_src) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(13, 0, reg_src, reg_dest)); } static inline void asm_xtensa_op_movi(asm_xtensa_t *as, uint reg_dest, int32_t imm12) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 10, (imm12 >> 8) & 0xf, reg_dest, imm12 & 0xff)); } static inline void asm_xtensa_op_movi_n(asm_xtensa_t *as, uint reg_dest, int imm4) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RI7(12, reg_dest, imm4)); } static inline void asm_xtensa_op_mull(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 2, 8, reg_dest, reg_src_a, reg_src_b)); } static inline void asm_xtensa_op_or(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 2, reg_dest, reg_src_a, reg_src_b)); } static inline void asm_xtensa_op_ret_n(asm_xtensa_t *as) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(13, 15, 0, 0)); } static inline void asm_xtensa_op_retw_n(asm_xtensa_t *as) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(13, 15, 0, 1)); } static inline void asm_xtensa_op_s8i(asm_xtensa_t *as, uint reg_src, uint reg_base, uint byte_offset) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 4, reg_base, reg_src, byte_offset & 0xff)); } static inline void asm_xtensa_op_s16i(asm_xtensa_t *as, uint reg_src, uint reg_base, uint half_word_offset) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 5, reg_base, reg_src, half_word_offset & 0xff)); } static inline void asm_xtensa_op_s32i(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 6, reg_base, reg_src, word_offset & 0xff)); } static inline void asm_xtensa_op_s32i_n(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(9, word_offset & 0xf, reg_base, reg_src)); } static inline void asm_xtensa_op_sll(asm_xtensa_t *as, uint reg_dest, uint reg_src) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 1, 10, reg_dest, reg_src, 0)); } static inline void asm_xtensa_op_sra(asm_xtensa_t *as, uint reg_dest, uint reg_src) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 1, 11, reg_dest, 0, reg_src)); } static inline void asm_xtensa_op_ssl(asm_xtensa_t *as, uint reg_src) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 1, reg_src, 0)); } static inline void asm_xtensa_op_ssr(asm_xtensa_t *as, uint reg_src) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 0, reg_src, 0)); } static inline void asm_xtensa_op_sub(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 12, reg_dest, reg_src_a, reg_src_b)); } static inline void asm_xtensa_op_xor(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 3, reg_dest, reg_src_a, reg_src_b)); } // convenience functions void asm_xtensa_j_label(asm_xtensa_t *as, uint label); void asm_xtensa_bccz_reg_label(asm_xtensa_t *as, uint cond, uint reg, uint label); void asm_xtensa_bcc_reg_reg_label(asm_xtensa_t *as, uint cond, uint reg1, uint reg2, uint label); void asm_xtensa_setcc_reg_reg_reg(asm_xtensa_t *as, uint cond, uint reg_dest, uint reg_src1, uint reg_src2); size_t asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32); void asm_xtensa_mov_reg_i32_optimised(asm_xtensa_t *as, uint reg_dest, uint32_t i32); void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src); void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num); void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num); void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label); void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx); void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); // Holds a pointer to mp_fun_table #define ASM_XTENSA_REG_FUN_TABLE ASM_XTENSA_REG_A15 #define ASM_XTENSA_REG_FUN_TABLE_WIN ASM_XTENSA_REG_A7 #if GENERIC_ASM_API // The following macros provide a (mostly) arch-independent API to // generate native code, and are used by the native emitter. #define ASM_WORD_SIZE (4) #if !GENERIC_ASM_API_WIN // Configuration for non-windowed calls #define REG_RET ASM_XTENSA_REG_A2 #define REG_ARG_1 ASM_XTENSA_REG_A2 #define REG_ARG_2 ASM_XTENSA_REG_A3 #define REG_ARG_3 ASM_XTENSA_REG_A4 #define REG_ARG_4 ASM_XTENSA_REG_A5 #define REG_ARG_5 ASM_XTENSA_REG_A6 #define REG_TEMP0 ASM_XTENSA_REG_A2 #define REG_TEMP1 ASM_XTENSA_REG_A3 #define REG_TEMP2 ASM_XTENSA_REG_A4 #define REG_LOCAL_1 ASM_XTENSA_REG_A12 #define REG_LOCAL_2 ASM_XTENSA_REG_A13 #define REG_LOCAL_3 ASM_XTENSA_REG_A14 #define REG_LOCAL_NUM (3) #define ASM_NUM_REGS_SAVED ASM_XTENSA_NUM_REGS_SAVED #define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE #define ASM_ENTRY(as, nlocal) asm_xtensa_entry((as), (nlocal)) #define ASM_EXIT(as) asm_xtensa_exit((as)) #define ASM_CALL_IND(as, idx) asm_xtensa_call_ind((as), (idx)) #else // Configuration for windowed calls with window size 8 #define REG_PARENT_RET ASM_XTENSA_REG_A2 #define REG_PARENT_ARG_1 ASM_XTENSA_REG_A2 #define REG_PARENT_ARG_2 ASM_XTENSA_REG_A3 #define REG_PARENT_ARG_3 ASM_XTENSA_REG_A4 #define REG_PARENT_ARG_4 ASM_XTENSA_REG_A5 #define REG_RET ASM_XTENSA_REG_A10 #define REG_ARG_1 ASM_XTENSA_REG_A10 #define REG_ARG_2 ASM_XTENSA_REG_A11 #define REG_ARG_3 ASM_XTENSA_REG_A12 #define REG_ARG_4 ASM_XTENSA_REG_A13 #define REG_TEMP0 ASM_XTENSA_REG_A10 #define REG_TEMP1 ASM_XTENSA_REG_A11 #define REG_TEMP2 ASM_XTENSA_REG_A12 #define REG_LOCAL_1 ASM_XTENSA_REG_A4 #define REG_LOCAL_2 ASM_XTENSA_REG_A5 #define REG_LOCAL_3 ASM_XTENSA_REG_A6 #define REG_LOCAL_NUM (3) #define ASM_NUM_REGS_SAVED ASM_XTENSA_NUM_REGS_SAVED_WIN #define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE_WIN #define ASM_ENTRY(as, nlocal) asm_xtensa_entry_win((as), (nlocal)) #define ASM_EXIT(as) asm_xtensa_exit_win((as)) #define ASM_CALL_IND(as, idx) asm_xtensa_call_ind_win((as), (idx)) #endif #define ASM_T asm_xtensa_t #define ASM_END_PASS asm_xtensa_end_pass #define ASM_JUMP asm_xtensa_j_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ asm_xtensa_bccz_reg_label(as, ASM_XTENSA_CCZ_EQ, reg, label) #define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \ asm_xtensa_bccz_reg_label(as, ASM_XTENSA_CCZ_NE, reg, label) #define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \ asm_xtensa_bcc_reg_reg_label(as, ASM_XTENSA_CC_EQ, reg1, reg2, label) #define ASM_JUMP_REG(as, reg) asm_xtensa_op_jx((as), (reg)) #define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_xtensa_mov_local_reg((as), ASM_NUM_REGS_SAVED + (local_num), (reg_src)) #define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_xtensa_mov_reg_i32_optimised((as), (reg_dest), (imm)) #define ASM_MOV_REG_IMM_FIX_U16(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm)) #define ASM_MOV_REG_IMM_FIX_WORD(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm)) #define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_xtensa_mov_reg_local((as), (reg_dest), ASM_NUM_REGS_SAVED + (local_num)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mov_n((as), (reg_dest), (reg_src)) #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_xtensa_mov_reg_local_addr((as), (reg_dest), ASM_NUM_REGS_SAVED + (local_num)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_xtensa_mov_reg_pcrel((as), (reg_dest), (label)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) \ do { \ asm_xtensa_op_ssl((as), (reg_shift)); \ asm_xtensa_op_sll((as), (reg_dest), (reg_dest)); \ } while (0) #define ASM_ASR_REG_REG(as, reg_dest, reg_shift) \ do { \ asm_xtensa_op_ssr((as), (reg_shift)); \ asm_xtensa_op_sra((as), (reg_dest), (reg_dest)); \ } while (0) #define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_or((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_xor((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_and((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_add_n((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_sub((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mull((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), (word_offset)) #define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l8ui((as), (reg_dest), (reg_base), 0) #define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), 0) #define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), 0) #define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_op_s32i_n((as), (reg_dest), (reg_base), (word_offset)) #define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s8i((as), (reg_src), (reg_base), 0) #define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s16i((as), (reg_src), (reg_base), 0) #define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s32i_n((as), (reg_src), (reg_base), 0) #endif // GENERIC_ASM_API #endif // MICROPY_INCLUDED_PY_ASMXTENSA_H micropython-1.12/py/bc.c000066400000000000000000000324331357706137100152070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/bc0.h" #include "py/bc.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #else // don't print debugging info #define DEBUG_PRINT (0) #define DEBUG_printf(...) (void)0 #endif #if !MICROPY_PERSISTENT_CODE mp_uint_t mp_decode_uint(const byte **ptr) { mp_uint_t unum = 0; byte val; const byte *p = *ptr; do { val = *p++; unum = (unum << 7) | (val & 0x7f); } while ((val & 0x80) != 0); *ptr = p; return unum; } // This function is used to help reduce stack usage at the caller, for the case when // the caller doesn't need to increase the ptr argument. If ptr is a local variable // and the caller uses mp_decode_uint(&ptr) instead of this function, then the compiler // must allocate a slot on the stack for ptr, and this slot cannot be reused for // anything else in the function because the pointer may have been stored in a global // and reused later in the function. mp_uint_t mp_decode_uint_value(const byte *ptr) { return mp_decode_uint(&ptr); } // This function is used to help reduce stack usage at the caller, for the case when // the caller doesn't need the actual value and just wants to skip over it. const byte *mp_decode_uint_skip(const byte *ptr) { while ((*ptr++) & 0x80) { } return ptr; } #endif STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) { #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE // generic message, used also for other argument issues (void)f; (void)expected; (void)given; mp_arg_error_terse_mismatch(); #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL (void)f; nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", expected, given)); #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%q() takes %d positional arguments but %d were given", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(f)), expected, given)); #endif } #if DEBUG_PRINT STATIC void dump_args(const mp_obj_t *a, size_t sz) { DEBUG_printf("%p: ", a); for (size_t i = 0; i < sz; i++) { DEBUG_printf("%p ", a[i]); } DEBUG_printf("\n"); } #else #define dump_args(...) (void)0 #endif // On entry code_state should be allocated somewhere (stack/heap) and // contain the following valid entries: // - code_state->fun_bc should contain a pointer to the function object // - code_state->ip should contain the offset in bytes from the pointer // code_state->fun_bc->bytecode to the entry n_state (0 for bytecode, non-zero for native) void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) { // This function is pretty complicated. It's main aim is to be efficient in speed and RAM // usage for the common case of positional only args. // get the function object that we want to set up (could be bytecode or native code) mp_obj_fun_bc_t *self = code_state->fun_bc; // ip comes in as an offset into bytecode, so turn it into a true pointer code_state->ip = self->bytecode + (size_t)code_state->ip; #if MICROPY_STACKLESS code_state->prev = NULL; #endif #if MICROPY_PY_SYS_SETTRACE code_state->prev_state = NULL; code_state->frame = NULL; #endif // Get cached n_state (rather than decode it again) size_t n_state = code_state->n_state; // Decode prelude size_t n_state_unused, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args; MP_BC_PRELUDE_SIG_DECODE_INTO(code_state->ip, n_state_unused, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args); (void)n_state_unused; (void)n_exc_stack_unused; code_state->sp = &code_state->state[0] - 1; code_state->exc_sp_idx = 0; // zero out the local stack to begin with memset(code_state->state, 0, n_state * sizeof(*code_state->state)); const mp_obj_t *kwargs = args + n_args; // var_pos_kw_args points to the stack where the var-args tuple, and var-kw dict, should go (if they are needed) mp_obj_t *var_pos_kw_args = &code_state->state[n_state - 1 - n_pos_args - n_kwonly_args]; // check positional arguments if (n_args > n_pos_args) { // given more than enough arguments if ((scope_flags & MP_SCOPE_FLAG_VARARGS) == 0) { fun_pos_args_mismatch(self, n_pos_args, n_args); } // put extra arguments in varargs tuple *var_pos_kw_args-- = mp_obj_new_tuple(n_args - n_pos_args, args + n_pos_args); n_args = n_pos_args; } else { if ((scope_flags & MP_SCOPE_FLAG_VARARGS) != 0) { DEBUG_printf("passing empty tuple as *args\n"); *var_pos_kw_args-- = mp_const_empty_tuple; } // Apply processing and check below only if we don't have kwargs, // otherwise, kw handling code below has own extensive checks. if (n_kw == 0 && (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) == 0) { if (n_args >= (size_t)(n_pos_args - n_def_pos_args)) { // given enough arguments, but may need to use some default arguments for (size_t i = n_args; i < n_pos_args; i++) { code_state->state[n_state - 1 - i] = self->extra_args[i - (n_pos_args - n_def_pos_args)]; } } else { fun_pos_args_mismatch(self, n_pos_args - n_def_pos_args, n_args); } } } // copy positional args into state for (size_t i = 0; i < n_args; i++) { code_state->state[n_state - 1 - i] = args[i]; } // check keyword arguments if (n_kw != 0 || (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) { DEBUG_printf("Initial args: "); dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args); mp_obj_t dict = MP_OBJ_NULL; if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) { dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0? *var_pos_kw_args = dict; } // get pointer to arg_names array const mp_obj_t *arg_names = (const mp_obj_t*)self->const_table; for (size_t i = 0; i < n_kw; i++) { // the keys in kwargs are expected to be qstr objects mp_obj_t wanted_arg_name = kwargs[2 * i]; for (size_t j = 0; j < n_pos_args + n_kwonly_args; j++) { if (wanted_arg_name == arg_names[j]) { if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function got multiple values for argument '%q'", MP_OBJ_QSTR_VALUE(wanted_arg_name))); } code_state->state[n_state - 1 - j] = kwargs[2 * i + 1]; goto continue2; } } // Didn't find name match with positional args if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("unexpected keyword argument"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unexpected keyword argument '%q'", MP_OBJ_QSTR_VALUE(wanted_arg_name))); } } mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]); continue2:; } DEBUG_printf("Args with kws flattened: "); dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args); // fill in defaults for positional args mp_obj_t *d = &code_state->state[n_state - n_pos_args]; mp_obj_t *s = &self->extra_args[n_def_pos_args - 1]; for (size_t i = n_def_pos_args; i > 0; i--, d++, s--) { if (*d == MP_OBJ_NULL) { *d = *s; } } DEBUG_printf("Args after filling default positional: "); dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args); // Check that all mandatory positional args are specified while (d < &code_state->state[n_state]) { if (*d++ == MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function missing required positional argument #%d", &code_state->state[n_state] - d)); } } // Check that all mandatory keyword args are specified // Fill in default kw args if we have them for (size_t i = 0; i < n_kwonly_args; i++) { if (code_state->state[n_state - 1 - n_pos_args - i] == MP_OBJ_NULL) { mp_map_elem_t *elem = NULL; if ((scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) { elem = mp_map_lookup(&((mp_obj_dict_t*)MP_OBJ_TO_PTR(self->extra_args[n_def_pos_args]))->map, arg_names[n_pos_args + i], MP_MAP_LOOKUP); } if (elem != NULL) { code_state->state[n_state - 1 - n_pos_args - i] = elem->value; } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function missing required keyword argument '%q'", MP_OBJ_QSTR_VALUE(arg_names[n_pos_args + i]))); } } } } else { // no keyword arguments given if (n_kwonly_args != 0) { mp_raise_TypeError("function missing keyword-only argument"); } if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) { *var_pos_kw_args = mp_obj_new_dict(0); } } // read the size part of the prelude const byte *ip = code_state->ip; MP_BC_PRELUDE_SIZE_DECODE(ip); // jump over code info (source file and line-number mapping) ip += n_info; // bytecode prelude: initialise closed over variables for (; n_cell; --n_cell) { size_t local_num = *ip++; code_state->state[n_state - 1 - local_num] = mp_obj_new_cell(code_state->state[n_state - 1 - local_num]); } #if !MICROPY_PERSISTENT_CODE // so bytecode is aligned ip = MP_ALIGN(ip, sizeof(mp_uint_t)); #endif // now that we skipped over the prelude, set the ip for the VM code_state->ip = ip; DEBUG_printf("Calling: n_pos_args=%d, n_kwonly_args=%d\n", n_pos_args, n_kwonly_args); dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args); dump_args(code_state->state, n_state); } #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE // The following table encodes the number of bytes that a specific opcode // takes up. Some opcodes have an extra byte, defined by MP_BC_MASK_EXTRA_BYTE. // There are 4 special opcodes that have an extra byte only when // MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE is enabled (and they take a qstr): // MP_BC_LOAD_NAME // MP_BC_LOAD_GLOBAL // MP_BC_LOAD_ATTR // MP_BC_STORE_ATTR uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint) { uint f = MP_BC_FORMAT(*ip); const byte *ip_start = ip; if (f == MP_BC_FORMAT_QSTR) { if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { if (*ip == MP_BC_LOAD_NAME || *ip == MP_BC_LOAD_GLOBAL || *ip == MP_BC_LOAD_ATTR || *ip == MP_BC_STORE_ATTR) { ip += 1; } } ip += 3; } else { int extra_byte = (*ip & MP_BC_MASK_EXTRA_BYTE) == 0; ip += 1; if (f == MP_BC_FORMAT_VAR_UINT) { if (count_var_uint) { while ((*ip++ & 0x80) != 0) { } } } else if (f == MP_BC_FORMAT_OFFSET) { ip += 2; } ip += extra_byte; } *opcode_size = ip - ip_start; return f; } #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE micropython-1.12/py/bc.h000066400000000000000000000301621357706137100152110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_BC_H #define MICROPY_INCLUDED_PY_BC_H #include "py/runtime.h" #include "py/objfun.h" // bytecode layout: // // func signature : var uint // contains six values interleaved bit-wise as: xSSSSEAA [xFSSKAED repeated] // x = extension another byte follows // S = n_state - 1 number of entries in Python value stack // E = n_exc_stack number of entries in exception stack // F = scope_flags four bits of flags, MP_SCOPE_FLAG_xxx // A = n_pos_args number of arguments this function takes // K = n_kwonly_args number of keyword-only arguments this function takes // D = n_def_pos_args number of default positional arguments // // prelude size : var uint // contains two values interleaved bit-wise as: xIIIIIIC repeated // x = extension another byte follows // I = n_info number of bytes in source info section // C = n_cells number of bytes/cells in closure section // // source info section: // simple_name : var qstr // source_file : var qstr // // // closure section: // local_num0 : byte // ... : byte // local_numN : byte N = n_cells-1 // // only needed if bytecode contains pointers // // // // // constant table layout: // // argname0 : obj (qstr) // ... : obj (qstr) // argnameN : obj (qstr) N = num_pos_args + num_kwonly_args // const0 : obj // constN : obj #define MP_BC_PRELUDE_SIG_ENCODE(S, E, scope, out_byte, out_env) \ do { \ /*// Get values to store in prelude */ \ size_t F = scope->scope_flags & MP_SCOPE_FLAG_ALL_SIG; \ size_t A = scope->num_pos_args; \ size_t K = scope->num_kwonly_args; \ size_t D = scope->num_def_pos_args; \ \ /* Adjust S to shrink range, to compress better */ \ S -= 1; \ \ /* Encode prelude */ \ /* xSSSSEAA */ \ uint8_t z = (S & 0xf) << 3 | (E & 1) << 2 | (A & 3); \ S >>= 4; \ E >>= 1; \ A >>= 2; \ while (S | E | F | A | K | D) { \ out_byte(out_env, 0x80 | z); \ /* xFSSKAED */ \ z = (F & 1) << 6 | (S & 3) << 4 | (K & 1) << 3 \ | (A & 1) << 2 | (E & 1) << 1 | (D & 1); \ S >>= 2; \ E >>= 1; \ F >>= 1; \ A >>= 1; \ K >>= 1; \ D >>= 1; \ } \ out_byte(out_env, z); \ } while (0) #define MP_BC_PRELUDE_SIG_DECODE_INTO(ip, S, E, F, A, K, D) \ do { \ uint8_t z = *(ip)++; \ /* xSSSSEAA */ \ S = (z >> 3) & 0xf; \ E = (z >> 2) & 0x1; \ F = 0; \ A = z & 0x3; \ K = 0; \ D = 0; \ for (unsigned n = 0; z & 0x80; ++n) { \ z = *(ip)++; \ /* xFSSKAED */ \ S |= (z & 0x30) << (2 * n); \ E |= (z & 0x02) << n; \ F |= ((z & 0x40) >> 6) << n; \ A |= (z & 0x4) << n; \ K |= ((z & 0x08) >> 3) << n; \ D |= (z & 0x1) << n; \ } \ S += 1; \ } while (0) #define MP_BC_PRELUDE_SIG_DECODE(ip) \ size_t n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args; \ MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args) #define MP_BC_PRELUDE_SIZE_ENCODE(I, C, out_byte, out_env) \ do { \ /* Encode bit-wise as: xIIIIIIC */ \ uint8_t z = 0; \ do { \ z = (I & 0x3f) << 1 | (C & 1); \ C >>= 1; \ I >>= 6; \ if (C | I) { \ z |= 0x80; \ } \ out_byte(out_env, z); \ } while (C | I); \ } while (0) #define MP_BC_PRELUDE_SIZE_DECODE_INTO(ip, I, C) \ do { \ uint8_t z; \ C = 0; \ I = 0; \ for (unsigned n = 0;; ++n) { \ z = *(ip)++; \ /* xIIIIIIC */ \ C |= (z & 1) << n; \ I |= ((z & 0x7e) >> 1) << (6 * n); \ if (!(z & 0x80)) { \ break; \ } \ } \ } while (0) #define MP_BC_PRELUDE_SIZE_DECODE(ip) \ size_t n_info, n_cell; \ MP_BC_PRELUDE_SIZE_DECODE_INTO(ip, n_info, n_cell) // Sentinel value for mp_code_state_t.exc_sp_idx #define MP_CODE_STATE_EXC_SP_IDX_SENTINEL ((uint16_t)-1) // To convert mp_code_state_t.exc_sp_idx to/from a pointer to mp_exc_stack_t #define MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp) ((exc_sp) + 1 - (exc_stack)) #define MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, exc_sp_idx) ((exc_stack) + (exc_sp_idx) - 1) typedef struct _mp_bytecode_prelude_t { uint n_state; uint n_exc_stack; uint scope_flags; uint n_pos_args; uint n_kwonly_args; uint n_def_pos_args; qstr qstr_block_name; qstr qstr_source_file; const byte *line_info; const byte *opcodes; } mp_bytecode_prelude_t; // Exception stack entry typedef struct _mp_exc_stack_t { const byte *handler; // bit 0 is currently unused // bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY mp_obj_t *val_sp; // Saved exception mp_obj_base_t *prev_exc; } mp_exc_stack_t; typedef struct _mp_code_state_t { // The fun_bc entry points to the underlying function object that is being executed. // It is needed to access the start of bytecode and the const_table. // It is also needed to prevent the GC from reclaiming the bytecode during execution, // because the ip pointer below will always point to the interior of the bytecode. mp_obj_fun_bc_t *fun_bc; const byte *ip; mp_obj_t *sp; uint16_t n_state; uint16_t exc_sp_idx; mp_obj_dict_t *old_globals; #if MICROPY_STACKLESS struct _mp_code_state_t *prev; #endif #if MICROPY_PY_SYS_SETTRACE struct _mp_code_state_t *prev_state; struct _mp_obj_frame_t *frame; #endif // Variable-length mp_obj_t state[0]; // Variable-length, never accessed by name, only as (void*)(state + n_state) //mp_exc_stack_t exc_state[0]; } mp_code_state_t; mp_uint_t mp_decode_uint(const byte **ptr); mp_uint_t mp_decode_uint_value(const byte *ptr); const byte *mp_decode_uint_skip(const byte *ptr); mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc); mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args); void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args); void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table); void mp_bytecode_print2(const byte *code, size_t len, const mp_uint_t *const_table); const byte *mp_bytecode_print_str(const byte *ip); #define mp_bytecode_print_inst(code, const_table) mp_bytecode_print2(code, 1, const_table) // Helper macros to access pointer with least significant bits holding flags #define MP_TAGPTR_PTR(x) ((void*)((uintptr_t)(x) & ~((uintptr_t)3))) #define MP_TAGPTR_TAG0(x) ((uintptr_t)(x) & 1) #define MP_TAGPTR_TAG1(x) ((uintptr_t)(x) & 2) #define MP_TAGPTR_MAKE(ptr, tag) ((void*)((uintptr_t)(ptr) | (tag))) #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint); #endif static inline size_t mp_bytecode_get_source_line(const byte *line_info, size_t bc_offset) { size_t source_line = 1; size_t c; while ((c = *line_info)) { size_t b, l; if ((c & 0x80) == 0) { // 0b0LLBBBBB encoding b = c & 0x1f; l = c >> 5; line_info += 1; } else { // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) b = c & 0xf; l = ((c << 4) & 0x700) | line_info[1]; line_info += 2; } if (bc_offset >= b) { bc_offset -= b; source_line += l; } else { // found source line corresponding to bytecode offset break; } } return source_line; } #endif // MICROPY_INCLUDED_PY_BC_H micropython-1.12/py/bc0.h000066400000000000000000000223511357706137100152720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_BC0_H #define MICROPY_INCLUDED_PY_BC0_H // MicroPython bytecode opcodes, grouped based on the format of the opcode #define MP_BC_MASK_FORMAT (0xf0) #define MP_BC_MASK_EXTRA_BYTE (0x9e) #define MP_BC_FORMAT_BYTE (0) #define MP_BC_FORMAT_QSTR (1) #define MP_BC_FORMAT_VAR_UINT (2) #define MP_BC_FORMAT_OFFSET (3) // Nibbles in magic number are: BB BB BB BB BB BO VV QU #define MP_BC_FORMAT(op) ((0x000003a4 >> (2 * ((op) >> 4))) & 3) // Load, Store, Delete, Import, Make, Build, Unpack, Call, Jump, Exception, For, sTack, Return, Yield, Op #define MP_BC_BASE_RESERVED (0x00) // ---------------- #define MP_BC_BASE_QSTR_O (0x10) // LLLLLLSSSDDII--- #define MP_BC_BASE_VINT_E (0x20) // MMLLLLSSDDBBBBBB #define MP_BC_BASE_VINT_O (0x30) // UUMMCCCC-------- #define MP_BC_BASE_JUMP_E (0x40) // J-JJJJJEEEEF---- #define MP_BC_BASE_BYTE_O (0x50) // LLLLSSDTTTTTEEFF #define MP_BC_BASE_BYTE_E (0x60) // --BREEEYYI------ #define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // LLLLLLLLLLLLLLLL // (0x80) // LLLLLLLLLLLLLLLL // (0x90) // LLLLLLLLLLLLLLLL // (0xa0) // LLLLLLLLLLLLLLLL #define MP_BC_LOAD_FAST_MULTI (0xb0) // LLLLLLLLLLLLLLLL #define MP_BC_STORE_FAST_MULTI (0xc0) // SSSSSSSSSSSSSSSS #define MP_BC_UNARY_OP_MULTI (0xd0) // OOOOOOO #define MP_BC_BINARY_OP_MULTI (0xd7) // OOOOOOOOO // (0xe0) // OOOOOOOOOOOOOOOO // (0xf0) // OOOOOOOOOO------ #define MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM (64) #define MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS (16) #define MP_BC_LOAD_FAST_MULTI_NUM (16) #define MP_BC_STORE_FAST_MULTI_NUM (16) #define MP_BC_UNARY_OP_MULTI_NUM (MP_UNARY_OP_NUM_BYTECODE) #define MP_BC_BINARY_OP_MULTI_NUM (MP_BINARY_OP_NUM_BYTECODE) #define MP_BC_LOAD_CONST_FALSE (MP_BC_BASE_BYTE_O + 0x00) #define MP_BC_LOAD_CONST_NONE (MP_BC_BASE_BYTE_O + 0x01) #define MP_BC_LOAD_CONST_TRUE (MP_BC_BASE_BYTE_O + 0x02) #define MP_BC_LOAD_CONST_SMALL_INT (MP_BC_BASE_VINT_E + 0x02) // signed var-int #define MP_BC_LOAD_CONST_STRING (MP_BC_BASE_QSTR_O + 0x00) // qstr #define MP_BC_LOAD_CONST_OBJ (MP_BC_BASE_VINT_E + 0x03) // ptr #define MP_BC_LOAD_NULL (MP_BC_BASE_BYTE_O + 0x03) #define MP_BC_LOAD_FAST_N (MP_BC_BASE_VINT_E + 0x04) // uint #define MP_BC_LOAD_DEREF (MP_BC_BASE_VINT_E + 0x05) // uint #define MP_BC_LOAD_NAME (MP_BC_BASE_QSTR_O + 0x01) // qstr #define MP_BC_LOAD_GLOBAL (MP_BC_BASE_QSTR_O + 0x02) // qstr #define MP_BC_LOAD_ATTR (MP_BC_BASE_QSTR_O + 0x03) // qstr #define MP_BC_LOAD_METHOD (MP_BC_BASE_QSTR_O + 0x04) // qstr #define MP_BC_LOAD_SUPER_METHOD (MP_BC_BASE_QSTR_O + 0x05) // qstr #define MP_BC_LOAD_BUILD_CLASS (MP_BC_BASE_BYTE_O + 0x04) #define MP_BC_LOAD_SUBSCR (MP_BC_BASE_BYTE_O + 0x05) #define MP_BC_STORE_FAST_N (MP_BC_BASE_VINT_E + 0x06) // uint #define MP_BC_STORE_DEREF (MP_BC_BASE_VINT_E + 0x07) // uint #define MP_BC_STORE_NAME (MP_BC_BASE_QSTR_O + 0x06) // qstr #define MP_BC_STORE_GLOBAL (MP_BC_BASE_QSTR_O + 0x07) // qstr #define MP_BC_STORE_ATTR (MP_BC_BASE_QSTR_O + 0x08) // qstr #define MP_BC_STORE_SUBSCR (MP_BC_BASE_BYTE_O + 0x06) #define MP_BC_DELETE_FAST (MP_BC_BASE_VINT_E + 0x08) // uint #define MP_BC_DELETE_DEREF (MP_BC_BASE_VINT_E + 0x09) // uint #define MP_BC_DELETE_NAME (MP_BC_BASE_QSTR_O + 0x09) // qstr #define MP_BC_DELETE_GLOBAL (MP_BC_BASE_QSTR_O + 0x0a) // qstr #define MP_BC_DUP_TOP (MP_BC_BASE_BYTE_O + 0x07) #define MP_BC_DUP_TOP_TWO (MP_BC_BASE_BYTE_O + 0x08) #define MP_BC_POP_TOP (MP_BC_BASE_BYTE_O + 0x09) #define MP_BC_ROT_TWO (MP_BC_BASE_BYTE_O + 0x0a) #define MP_BC_ROT_THREE (MP_BC_BASE_BYTE_O + 0x0b) #define MP_BC_JUMP (MP_BC_BASE_JUMP_E + 0x02) // rel byte code offset, 16-bit signed, in excess #define MP_BC_POP_JUMP_IF_TRUE (MP_BC_BASE_JUMP_E + 0x03) // rel byte code offset, 16-bit signed, in excess #define MP_BC_POP_JUMP_IF_FALSE (MP_BC_BASE_JUMP_E + 0x04) // rel byte code offset, 16-bit signed, in excess #define MP_BC_JUMP_IF_TRUE_OR_POP (MP_BC_BASE_JUMP_E + 0x05) // rel byte code offset, 16-bit signed, in excess #define MP_BC_JUMP_IF_FALSE_OR_POP (MP_BC_BASE_JUMP_E + 0x06) // rel byte code offset, 16-bit signed, in excess #define MP_BC_UNWIND_JUMP (MP_BC_BASE_JUMP_E + 0x00) // rel byte code offset, 16-bit signed, in excess; then a byte #define MP_BC_SETUP_WITH (MP_BC_BASE_JUMP_E + 0x07) // rel byte code offset, 16-bit unsigned #define MP_BC_SETUP_EXCEPT (MP_BC_BASE_JUMP_E + 0x08) // rel byte code offset, 16-bit unsigned #define MP_BC_SETUP_FINALLY (MP_BC_BASE_JUMP_E + 0x09) // rel byte code offset, 16-bit unsigned #define MP_BC_POP_EXCEPT_JUMP (MP_BC_BASE_JUMP_E + 0x0a) // rel byte code offset, 16-bit unsigned #define MP_BC_FOR_ITER (MP_BC_BASE_JUMP_E + 0x0b) // rel byte code offset, 16-bit unsigned #define MP_BC_WITH_CLEANUP (MP_BC_BASE_BYTE_O + 0x0c) #define MP_BC_END_FINALLY (MP_BC_BASE_BYTE_O + 0x0d) #define MP_BC_GET_ITER (MP_BC_BASE_BYTE_O + 0x0e) #define MP_BC_GET_ITER_STACK (MP_BC_BASE_BYTE_O + 0x0f) #define MP_BC_BUILD_TUPLE (MP_BC_BASE_VINT_E + 0x0a) // uint #define MP_BC_BUILD_LIST (MP_BC_BASE_VINT_E + 0x0b) // uint #define MP_BC_BUILD_MAP (MP_BC_BASE_VINT_E + 0x0c) // uint #define MP_BC_STORE_MAP (MP_BC_BASE_BYTE_E + 0x02) #define MP_BC_BUILD_SET (MP_BC_BASE_VINT_E + 0x0d) // uint #define MP_BC_BUILD_SLICE (MP_BC_BASE_VINT_E + 0x0e) // uint #define MP_BC_STORE_COMP (MP_BC_BASE_VINT_E + 0x0f) // uint #define MP_BC_UNPACK_SEQUENCE (MP_BC_BASE_VINT_O + 0x00) // uint #define MP_BC_UNPACK_EX (MP_BC_BASE_VINT_O + 0x01) // uint #define MP_BC_RETURN_VALUE (MP_BC_BASE_BYTE_E + 0x03) #define MP_BC_RAISE_LAST (MP_BC_BASE_BYTE_E + 0x04) #define MP_BC_RAISE_OBJ (MP_BC_BASE_BYTE_E + 0x05) #define MP_BC_RAISE_FROM (MP_BC_BASE_BYTE_E + 0x06) #define MP_BC_YIELD_VALUE (MP_BC_BASE_BYTE_E + 0x07) #define MP_BC_YIELD_FROM (MP_BC_BASE_BYTE_E + 0x08) #define MP_BC_MAKE_FUNCTION (MP_BC_BASE_VINT_O + 0x02) // uint #define MP_BC_MAKE_FUNCTION_DEFARGS (MP_BC_BASE_VINT_O + 0x03) // uint #define MP_BC_MAKE_CLOSURE (MP_BC_BASE_VINT_E + 0x00) // uint; extra byte #define MP_BC_MAKE_CLOSURE_DEFARGS (MP_BC_BASE_VINT_E + 0x01) // uint; extra byte #define MP_BC_CALL_FUNCTION (MP_BC_BASE_VINT_O + 0x04) // uint #define MP_BC_CALL_FUNCTION_VAR_KW (MP_BC_BASE_VINT_O + 0x05) // uint #define MP_BC_CALL_METHOD (MP_BC_BASE_VINT_O + 0x06) // uint #define MP_BC_CALL_METHOD_VAR_KW (MP_BC_BASE_VINT_O + 0x07) // uint #define MP_BC_IMPORT_NAME (MP_BC_BASE_QSTR_O + 0x0b) // qstr #define MP_BC_IMPORT_FROM (MP_BC_BASE_QSTR_O + 0x0c) // qstr #define MP_BC_IMPORT_STAR (MP_BC_BASE_BYTE_E + 0x09) #endif // MICROPY_INCLUDED_PY_BC0_H micropython-1.12/py/binary.c000066400000000000000000000313021357706137100161010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2017 Paul Sokolovsky * Copyright (c) 2014-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/binary.h" #include "py/smallint.h" #include "py/objint.h" #include "py/runtime.h" // Helpers to work with binary-encoded data #ifndef alignof #define alignof(type) offsetof(struct { char c; type t; }, t) #endif size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) { size_t size = 0; int align = 1; switch (struct_type) { case '<': case '>': switch (val_type) { case 'b': case 'B': size = 1; break; case 'h': case 'H': size = 2; break; case 'i': case 'I': size = 4; break; case 'l': case 'L': size = 4; break; case 'q': case 'Q': size = 8; break; case 'P': case 'O': case 'S': size = sizeof(void*); break; case 'f': size = sizeof(float); break; case 'd': size = sizeof(double); break; } break; case '@': { // TODO: // The simplest heuristic for alignment is to align by value // size, but that doesn't work for "bigger than int" types, // for example, long long may very well have long alignment // So, we introduce separate alignment handling, but having // formal support for that is different from actually supporting // particular (or any) ABI. switch (val_type) { case BYTEARRAY_TYPECODE: case 'b': case 'B': align = size = 1; break; case 'h': case 'H': align = alignof(short); size = sizeof(short); break; case 'i': case 'I': align = alignof(int); size = sizeof(int); break; case 'l': case 'L': align = alignof(long); size = sizeof(long); break; case 'q': case 'Q': align = alignof(long long); size = sizeof(long long); break; case 'P': case 'O': case 'S': align = alignof(void*); size = sizeof(void*); break; case 'f': align = alignof(float); size = sizeof(float); break; case 'd': align = alignof(double); size = sizeof(double); break; } } } if (size == 0) { mp_raise_ValueError("bad typecode"); } if (palign != NULL) { *palign = align; } return size; } mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index) { mp_int_t val = 0; switch (typecode) { case 'b': val = ((signed char*)p)[index]; break; case BYTEARRAY_TYPECODE: case 'B': val = ((unsigned char*)p)[index]; break; case 'h': val = ((short*)p)[index]; break; case 'H': val = ((unsigned short*)p)[index]; break; case 'i': return mp_obj_new_int(((int*)p)[index]); case 'I': return mp_obj_new_int_from_uint(((unsigned int*)p)[index]); case 'l': return mp_obj_new_int(((long*)p)[index]); case 'L': return mp_obj_new_int_from_uint(((unsigned long*)p)[index]); #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE case 'q': return mp_obj_new_int_from_ll(((long long*)p)[index]); case 'Q': return mp_obj_new_int_from_ull(((unsigned long long*)p)[index]); #endif #if MICROPY_PY_BUILTINS_FLOAT case 'f': return mp_obj_new_float(((float*)p)[index]); case 'd': return mp_obj_new_float(((double*)p)[index]); #endif // Extension to CPython: array of objects case 'O': return ((mp_obj_t*)p)[index]; // Extension to CPython: array of pointers case 'P': return mp_obj_new_int((mp_int_t)(uintptr_t)((void**)p)[index]); } return MP_OBJ_NEW_SMALL_INT(val); } // The long long type is guaranteed to hold at least 64 bits, and size is at // most 8 (for q and Q), so we will always be able to parse the given data // and fit it into a long long. long long mp_binary_get_int(size_t size, bool is_signed, bool big_endian, const byte *src) { int delta; if (!big_endian) { delta = -1; src += size - 1; } else { delta = 1; } long long val = 0; if (is_signed && *src & 0x80) { val = -1; } for (uint i = 0; i < size; i++) { val <<= 8; val |= *src; src += delta; } return val; } #define is_signed(typecode) (typecode > 'Z') mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr) { byte *p = *ptr; size_t align; size_t size = mp_binary_get_size(struct_type, val_type, &align); if (struct_type == '@') { // Align p relative to p_base p = p_base + (uintptr_t)MP_ALIGN(p - p_base, align); #if MP_ENDIANNESS_LITTLE struct_type = '<'; #else struct_type = '>'; #endif } *ptr = p + size; long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p); if (val_type == 'O') { return (mp_obj_t)(mp_uint_t)val; } else if (val_type == 'S') { const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val; return mp_obj_new_str(s_val, strlen(s_val)); #if MICROPY_PY_BUILTINS_FLOAT } else if (val_type == 'f') { union { uint32_t i; float f; } fpu = {val}; return mp_obj_new_float(fpu.f); } else if (val_type == 'd') { union { uint64_t i; double f; } fpu = {val}; return mp_obj_new_float(fpu.f); #endif } else if (is_signed(val_type)) { if ((long long)MP_SMALL_INT_MIN <= val && val <= (long long)MP_SMALL_INT_MAX) { return mp_obj_new_int((mp_int_t)val); } else { return mp_obj_new_int_from_ll(val); } } else { if ((unsigned long long)val <= (unsigned long long)MP_SMALL_INT_MAX) { return mp_obj_new_int_from_uint((mp_uint_t)val); } else { return mp_obj_new_int_from_ull(val); } } } void mp_binary_set_int(size_t val_sz, bool big_endian, byte *dest, mp_uint_t val) { if (MP_ENDIANNESS_LITTLE && !big_endian) { memcpy(dest, &val, val_sz); } else if (MP_ENDIANNESS_BIG && big_endian) { // only copy the least-significant val_sz bytes memcpy(dest, (byte*)&val + sizeof(mp_uint_t) - val_sz, val_sz); } else { const byte *src; if (MP_ENDIANNESS_LITTLE) { src = (const byte*)&val + val_sz; } else { src = (const byte*)&val + sizeof(mp_uint_t); } while (val_sz--) { *dest++ = *--src; } } } void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr) { byte *p = *ptr; size_t align; size_t size = mp_binary_get_size(struct_type, val_type, &align); if (struct_type == '@') { // Align p relative to p_base p = p_base + (uintptr_t)MP_ALIGN(p - p_base, align); if (MP_ENDIANNESS_LITTLE) { struct_type = '<'; } else { struct_type = '>'; } } *ptr = p + size; mp_uint_t val; switch (val_type) { case 'O': val = (mp_uint_t)val_in; break; #if MICROPY_PY_BUILTINS_FLOAT case 'f': { union { uint32_t i; float f; } fp_sp; fp_sp.f = mp_obj_get_float(val_in); val = fp_sp.i; break; } case 'd': { union { uint64_t i64; uint32_t i32[2]; double f; } fp_dp; fp_dp.f = mp_obj_get_float(val_in); if (BYTES_PER_WORD == 8) { val = fp_dp.i64; } else { int be = struct_type == '>'; mp_binary_set_int(sizeof(uint32_t), be, p, fp_dp.i32[MP_ENDIANNESS_BIG ^ be]); p += sizeof(uint32_t); val = fp_dp.i32[MP_ENDIANNESS_LITTLE ^ be]; } break; } #endif default: #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE if (mp_obj_is_type(val_in, &mp_type_int)) { mp_obj_int_to_bytes_impl(val_in, struct_type == '>', size, p); return; } else #endif { val = mp_obj_get_int(val_in); // zero/sign extend if needed if (BYTES_PER_WORD < 8 && size > sizeof(val)) { int c = (is_signed(val_type) && (mp_int_t)val < 0) ? 0xff : 0x00; memset(p, c, size); if (struct_type == '>') { p += size - sizeof(val); } } } } mp_binary_set_int(MIN((size_t)size, sizeof(val)), struct_type == '>', p, val); } void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_in) { switch (typecode) { #if MICROPY_PY_BUILTINS_FLOAT case 'f': ((float*)p)[index] = mp_obj_get_float(val_in); break; case 'd': ((double*)p)[index] = mp_obj_get_float(val_in); break; #endif // Extension to CPython: array of objects case 'O': ((mp_obj_t*)p)[index] = val_in; break; default: #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE if (mp_obj_is_type(val_in, &mp_type_int)) { size_t size = mp_binary_get_size('@', typecode, NULL); mp_obj_int_to_bytes_impl(val_in, MP_ENDIANNESS_BIG, size, (uint8_t*)p + index * size); return; } #endif mp_binary_set_val_array_from_int(typecode, p, index, mp_obj_get_int(val_in)); } } void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_int_t val) { switch (typecode) { case 'b': ((signed char*)p)[index] = val; break; case BYTEARRAY_TYPECODE: case 'B': ((unsigned char*)p)[index] = val; break; case 'h': ((short*)p)[index] = val; break; case 'H': ((unsigned short*)p)[index] = val; break; case 'i': ((int*)p)[index] = val; break; case 'I': ((unsigned int*)p)[index] = val; break; case 'l': ((long*)p)[index] = val; break; case 'L': ((unsigned long*)p)[index] = val; break; #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE case 'q': ((long long*)p)[index] = val; break; case 'Q': ((unsigned long long*)p)[index] = val; break; #endif #if MICROPY_PY_BUILTINS_FLOAT case 'f': ((float*)p)[index] = val; break; case 'd': ((double*)p)[index] = val; break; #endif // Extension to CPython: array of pointers case 'P': ((void**)p)[index] = (void*)(uintptr_t)val; break; } } micropython-1.12/py/binary.h000066400000000000000000000044341357706137100161140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * Copyright (c) 2014-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_BINARY_H #define MICROPY_INCLUDED_PY_BINARY_H #include "py/obj.h" // Use special typecode to differentiate repr() of bytearray vs array.array('B') // (underlyingly they're same). Can't use 0 here because that's used to detect // type-specification errors due to end-of-string. #define BYTEARRAY_TYPECODE 1 size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign); mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index); void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_in); void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_int_t val); mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr); void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr); long long mp_binary_get_int(size_t size, bool is_signed, bool big_endian, const byte *src); void mp_binary_set_int(size_t val_sz, bool big_endian, byte *dest, mp_uint_t val); #endif // MICROPY_INCLUDED_PY_BINARY_H micropython-1.12/py/builtin.h000066400000000000000000000133651357706137100163010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_BUILTIN_H #define MICROPY_INCLUDED_PY_BUILTIN_H #include "py/obj.h" mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args); mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_abs_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_all_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_any_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_bin_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_callable_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_chr_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj); MP_DECLARE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_globals_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hash_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hex_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_id_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_iter_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_len_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_locals_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_max_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_min_obj); #if MICROPY_PY_BUILTINS_NEXT2 MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_next_obj); #else MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_next_obj); #endif MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_oct_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_ord_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_print_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_repr_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj); // Defined by a port, but declared here for simplicity MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_namedtuple_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_op_contains_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_op_getitem_obj); MP_DECLARE_CONST_FUN_OBJ_3(mp_op_setitem_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_op_delitem_obj); extern const mp_obj_module_t mp_module___main__; extern const mp_obj_module_t mp_module_builtins; extern const mp_obj_module_t mp_module_uarray; extern const mp_obj_module_t mp_module_collections; extern const mp_obj_module_t mp_module_io; extern const mp_obj_module_t mp_module_math; extern const mp_obj_module_t mp_module_cmath; extern const mp_obj_module_t mp_module_micropython; extern const mp_obj_module_t mp_module_ustruct; extern const mp_obj_module_t mp_module_sys; extern const mp_obj_module_t mp_module_gc; extern const mp_obj_module_t mp_module_thread; extern const mp_obj_dict_t mp_module_builtins_globals; // extmod modules extern const mp_obj_module_t mp_module_uerrno; extern const mp_obj_module_t mp_module_uctypes; extern const mp_obj_module_t mp_module_uzlib; extern const mp_obj_module_t mp_module_ujson; extern const mp_obj_module_t mp_module_ure; extern const mp_obj_module_t mp_module_uheapq; extern const mp_obj_module_t mp_module_uhashlib; extern const mp_obj_module_t mp_module_ucryptolib; extern const mp_obj_module_t mp_module_ubinascii; extern const mp_obj_module_t mp_module_urandom; extern const mp_obj_module_t mp_module_uselect; extern const mp_obj_module_t mp_module_ussl; extern const mp_obj_module_t mp_module_utimeq; extern const mp_obj_module_t mp_module_machine; extern const mp_obj_module_t mp_module_lwip; extern const mp_obj_module_t mp_module_uwebsocket; extern const mp_obj_module_t mp_module_webrepl; extern const mp_obj_module_t mp_module_framebuf; extern const mp_obj_module_t mp_module_btree; extern const mp_obj_module_t mp_module_ubluetooth; extern const char MICROPY_PY_BUILTINS_HELP_TEXT[]; #endif // MICROPY_INCLUDED_PY_BUILTIN_H micropython-1.12/py/builtinevex.c000066400000000000000000000133611357706137100171600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/objfun.h" #include "py/compile.h" #include "py/runtime.h" #include "py/builtin.h" #if MICROPY_PY_BUILTINS_COMPILE typedef struct _mp_obj_code_t { mp_obj_base_t base; mp_obj_t module_fun; } mp_obj_code_t; STATIC const mp_obj_type_t mp_type_code = { { &mp_type_type }, .name = MP_QSTR_code, }; STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { // save context and set new context mp_obj_dict_t *old_globals = mp_globals_get(); mp_obj_dict_t *old_locals = mp_locals_get(); mp_globals_set(globals); mp_locals_set(locals); // a bit of a hack: fun_bc will re-set globals, so need to make sure it's // the correct one if (mp_obj_is_type(self->module_fun, &mp_type_fun_bc)) { mp_obj_fun_bc_t *fun_bc = MP_OBJ_TO_PTR(self->module_fun); fun_bc->globals = globals; } // execute code nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t ret = mp_call_function_0(self->module_fun); nlr_pop(); mp_globals_set(old_globals); mp_locals_set(old_locals); return ret; } else { // exception; restore context and re-raise same exception mp_globals_set(old_globals); mp_locals_set(old_locals); nlr_jump(nlr.ret_val); } } STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) { (void)n_args; // get the source size_t str_len; const char *str = mp_obj_str_get_data(args[0], &str_len); // get the filename qstr filename = mp_obj_str_get_qstr(args[1]); // create the lexer mp_lexer_t *lex = mp_lexer_new_from_str_len(filename, str, str_len, 0); // get the compile mode qstr mode = mp_obj_str_get_qstr(args[2]); mp_parse_input_kind_t parse_input_kind; switch (mode) { case MP_QSTR_single: parse_input_kind = MP_PARSE_SINGLE_INPUT; break; case MP_QSTR_exec: parse_input_kind = MP_PARSE_FILE_INPUT; break; case MP_QSTR_eval: parse_input_kind = MP_PARSE_EVAL_INPUT; break; default: mp_raise_ValueError("bad compile mode"); } mp_obj_code_t *code = m_new_obj(mp_obj_code_t); code->base.type = &mp_type_code; code->module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL); return MP_OBJ_FROM_PTR(code); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_compile); #endif // MICROPY_PY_BUILTINS_COMPILE #if MICROPY_PY_BUILTINS_EVAL_EXEC STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) { // work out the context mp_obj_dict_t *globals = mp_globals_get(); mp_obj_dict_t *locals = mp_locals_get(); for (size_t i = 1; i < 3 && i < n_args; ++i) { if (args[i] != mp_const_none) { if (!mp_obj_is_type(args[i], &mp_type_dict)) { mp_raise_TypeError(NULL); } locals = MP_OBJ_TO_PTR(args[i]); if (i == 1) { globals = locals; } } } #if MICROPY_PY_BUILTINS_COMPILE if (mp_obj_is_type(args[0], &mp_type_code)) { return code_execute(MP_OBJ_TO_PTR(args[0]), globals, locals); } #endif size_t str_len; const char *str = mp_obj_str_get_data(args[0], &str_len); // create the lexer // MP_PARSE_SINGLE_INPUT is used to indicate a file input mp_lexer_t *lex; if (MICROPY_PY_BUILTINS_EXECFILE && parse_input_kind == MP_PARSE_SINGLE_INPUT) { lex = mp_lexer_new_from_file(str); parse_input_kind = MP_PARSE_FILE_INPUT; } else { lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0); } return mp_parse_compile_execute(lex, parse_input_kind, globals, locals); } STATIC mp_obj_t mp_builtin_eval(size_t n_args, const mp_obj_t *args) { return eval_exec_helper(n_args, args, MP_PARSE_EVAL_INPUT); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj, 1, 3, mp_builtin_eval); STATIC mp_obj_t mp_builtin_exec(size_t n_args, const mp_obj_t *args) { return eval_exec_helper(n_args, args, MP_PARSE_FILE_INPUT); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec); #endif // MICROPY_PY_BUILTINS_EVAL_EXEC #if MICROPY_PY_BUILTINS_EXECFILE STATIC mp_obj_t mp_builtin_execfile(size_t n_args, const mp_obj_t *args) { // MP_PARSE_SINGLE_INPUT is used to indicate a file input return eval_exec_helper(n_args, args, MP_PARSE_SINGLE_INPUT); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj, 1, 3, mp_builtin_execfile); #endif micropython-1.12/py/builtinhelp.c000066400000000000000000000133121357706137100171350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/builtin.h" #include "py/objmodule.h" #if MICROPY_PY_BUILTINS_HELP const char mp_help_default_text[] = "Welcome to MicroPython!\n" "\n" "For online docs please visit http://docs.micropython.org/\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" " CTRL-B -- on a blank line, enter normal REPL mode\n" " CTRL-C -- interrupt a running program\n" " CTRL-D -- on a blank line, exit or do a soft reset\n" " CTRL-E -- on a blank line, enter paste mode\n" "\n" "For further help on a specific object, type help(obj)\n" ; STATIC void mp_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) { mp_print_str(MP_PYTHON_PRINTER, " "); mp_obj_print(name_o, PRINT_STR); mp_print_str(MP_PYTHON_PRINTER, " -- "); mp_obj_print(value, PRINT_STR); mp_print_str(MP_PYTHON_PRINTER, "\n"); } #if MICROPY_PY_BUILTINS_HELP_MODULES STATIC void mp_help_add_from_map(mp_obj_t list, const mp_map_t *map) { for (size_t i = 0; i < map->alloc; i++) { if (mp_map_slot_is_filled(map, i)) { mp_obj_list_append(list, map->table[i].key); } } } #if MICROPY_MODULE_FROZEN STATIC void mp_help_add_from_names(mp_obj_t list, const char *name) { while (*name) { size_t l = strlen(name); // name should end in '.py' and we strip it off mp_obj_list_append(list, mp_obj_new_str(name, l - 3)); name += l + 1; } } #endif STATIC void mp_help_print_modules(void) { mp_obj_t list = mp_obj_new_list(0, NULL); mp_help_add_from_map(list, &mp_builtin_module_map); #if MICROPY_MODULE_FROZEN_STR extern const char mp_frozen_str_names[]; mp_help_add_from_names(list, mp_frozen_str_names); #endif #if MICROPY_MODULE_FROZEN_MPY extern const char mp_frozen_mpy_names[]; mp_help_add_from_names(list, mp_frozen_mpy_names); #endif // sort the list so it's printed in alphabetical order mp_obj_list_sort(1, &list, (mp_map_t*)&mp_const_empty_map); // print the list of modules in a column-first order #define NUM_COLUMNS (4) #define COLUMN_WIDTH (18) size_t len; mp_obj_t *items; mp_obj_list_get(list, &len, &items); unsigned int num_rows = (len + NUM_COLUMNS - 1) / NUM_COLUMNS; for (unsigned int i = 0; i < num_rows; ++i) { unsigned int j = i; for (;;) { int l = mp_print_str(MP_PYTHON_PRINTER, mp_obj_str_get_str(items[j])); j += num_rows; if (j >= len) { break; } int gap = COLUMN_WIDTH - l; while (gap < 1) { gap += COLUMN_WIDTH; } while (gap--) { mp_print_str(MP_PYTHON_PRINTER, " "); } } mp_print_str(MP_PYTHON_PRINTER, "\n"); } #if MICROPY_ENABLE_EXTERNAL_IMPORT // let the user know there may be other modules available from the filesystem mp_print_str(MP_PYTHON_PRINTER, "Plus any modules on the filesystem\n"); #endif } #endif STATIC void mp_help_print_obj(const mp_obj_t obj) { #if MICROPY_PY_BUILTINS_HELP_MODULES if (obj == MP_OBJ_NEW_QSTR(MP_QSTR_modules)) { mp_help_print_modules(); return; } #endif mp_obj_type_t *type = mp_obj_get_type(obj); // try to print something sensible about the given object mp_print_str(MP_PYTHON_PRINTER, "object "); mp_obj_print(obj, PRINT_STR); mp_printf(MP_PYTHON_PRINTER, " is of type %q\n", type->name); mp_map_t *map = NULL; if (type == &mp_type_module) { map = &mp_obj_module_get_globals(obj)->map; } else { if (type == &mp_type_type) { type = MP_OBJ_TO_PTR(obj); } if (type->locals_dict != NULL) { map = &type->locals_dict->map; } } if (map != NULL) { for (uint i = 0; i < map->alloc; i++) { if (map->table[i].key != MP_OBJ_NULL) { mp_help_print_info_about_object(map->table[i].key, map->table[i].value); } } } } STATIC mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // print a general help message mp_print_str(MP_PYTHON_PRINTER, MICROPY_PY_BUILTINS_HELP_TEXT); } else { // try to print something sensible about the given object mp_help_print_obj(args[0]); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, mp_builtin_help); #endif // MICROPY_PY_BUILTINS_HELP micropython-1.12/py/builtinimport.c000066400000000000000000000463511357706137100175300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/compile.h" #include "py/objmodule.h" #include "py/persistentcode.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/frozenmod.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_PRINT (0) #define DEBUG_printf(...) (void)0 #endif #if MICROPY_ENABLE_EXTERNAL_IMPORT #define PATH_SEP_CHAR '/' bool mp_obj_is_package(mp_obj_t module) { mp_obj_t dest[2]; mp_load_method_maybe(module, MP_QSTR___path__, dest); return dest[0] != MP_OBJ_NULL; } // Stat either frozen or normal module by a given path // (whatever is available, if at all). STATIC mp_import_stat_t mp_import_stat_any(const char *path) { #if MICROPY_MODULE_FROZEN mp_import_stat_t st = mp_frozen_stat(path); if (st != MP_IMPORT_STAT_NO_EXIST) { return st; } #endif return mp_import_stat(path); } STATIC mp_import_stat_t stat_file_py_or_mpy(vstr_t *path) { mp_import_stat_t stat = mp_import_stat_any(vstr_null_terminated_str(path)); if (stat == MP_IMPORT_STAT_FILE) { return stat; } #if MICROPY_PERSISTENT_CODE_LOAD vstr_ins_byte(path, path->len - 2, 'm'); stat = mp_import_stat_any(vstr_null_terminated_str(path)); if (stat == MP_IMPORT_STAT_FILE) { return stat; } #endif return MP_IMPORT_STAT_NO_EXIST; } STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) { mp_import_stat_t stat = mp_import_stat_any(vstr_null_terminated_str(path)); DEBUG_printf("stat %s: %d\n", vstr_str(path), stat); if (stat == MP_IMPORT_STAT_DIR) { return stat; } // not a directory, add .py and try as a file vstr_add_str(path, ".py"); return stat_file_py_or_mpy(path); } STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) { #if MICROPY_PY_SYS // extract the list of paths size_t path_num; mp_obj_t *path_items; mp_obj_list_get(mp_sys_path, &path_num, &path_items); if (path_num == 0) { #endif // mp_sys_path is empty, so just use the given file name vstr_add_strn(dest, file_str, file_len); return stat_dir_or_file(dest); #if MICROPY_PY_SYS } else { // go through each path looking for a directory or file for (size_t i = 0; i < path_num; i++) { vstr_reset(dest); size_t p_len; const char *p = mp_obj_str_get_data(path_items[i], &p_len); if (p_len > 0) { vstr_add_strn(dest, p, p_len); vstr_add_char(dest, PATH_SEP_CHAR); } vstr_add_strn(dest, file_str, file_len); mp_import_stat_t stat = stat_dir_or_file(dest); if (stat != MP_IMPORT_STAT_NO_EXIST) { return stat; } } // could not find a directory or file return MP_IMPORT_STAT_NO_EXIST; } #endif } #if MICROPY_MODULE_FROZEN_STR || MICROPY_ENABLE_COMPILER STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex) { #if MICROPY_PY___FILE__ qstr source_name = lex->source_name; mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); #endif // parse, compile and execute the module in its context mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj); mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals); } #endif #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_MODULE_FROZEN_MPY STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code, const char* source_name) { (void)source_name; #if MICROPY_PY___FILE__ mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(qstr_from_str(source_name))); #endif // execute the module in its context mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj); // save context mp_obj_dict_t *volatile old_globals = mp_globals_get(); mp_obj_dict_t *volatile old_locals = mp_locals_get(); // set new context mp_globals_set(mod_globals); mp_locals_set(mod_globals); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t module_fun = mp_make_function_from_raw_code(raw_code, MP_OBJ_NULL, MP_OBJ_NULL); mp_call_function_0(module_fun); // finish nlr block, restore context nlr_pop(); mp_globals_set(old_globals); mp_locals_set(old_locals); } else { // exception; restore context and re-raise same exception mp_globals_set(old_globals); mp_locals_set(old_locals); nlr_jump(nlr.ret_val); } } #endif STATIC void do_load(mp_obj_t module_obj, vstr_t *file) { #if MICROPY_MODULE_FROZEN || MICROPY_ENABLE_COMPILER || (MICROPY_PERSISTENT_CODE_LOAD && MICROPY_HAS_FILE_READER) char *file_str = vstr_null_terminated_str(file); #endif // If we support frozen modules (either as str or mpy) then try to find the // requested filename in the list of frozen module filenames. #if MICROPY_MODULE_FROZEN void *modref; int frozen_type = mp_find_frozen_module(file_str, file->len, &modref); #endif // If we support frozen str modules and the compiler is enabled, and we // found the filename in the list of frozen files, then load and execute it. #if MICROPY_MODULE_FROZEN_STR if (frozen_type == MP_FROZEN_STR) { do_load_from_lexer(module_obj, modref); return; } #endif // If we support frozen mpy modules and we found a corresponding file (and // its data) in the list of frozen files, execute it. #if MICROPY_MODULE_FROZEN_MPY if (frozen_type == MP_FROZEN_MPY) { do_execute_raw_code(module_obj, modref, file_str); return; } #endif // If we support loading .mpy files then check if the file extension is of // the correct format and, if so, load and execute the file. #if MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD if (file_str[file->len - 3] == 'm') { mp_raw_code_t *raw_code = mp_raw_code_load_file(file_str); do_execute_raw_code(module_obj, raw_code, file_str); return; } #endif // If we can compile scripts then load the file and compile and execute it. #if MICROPY_ENABLE_COMPILER { mp_lexer_t *lex = mp_lexer_new_from_file(file_str); do_load_from_lexer(module_obj, lex); return; } #else // If we get here then the file was not frozen and we can't compile scripts. mp_raise_msg(&mp_type_ImportError, "script compilation not supported"); #endif } STATIC void chop_component(const char *start, const char **end) { const char *p = *end; while (p > start) { if (*--p == '.') { *end = p; return; } } *end = p; } mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #if DEBUG_PRINT DEBUG_printf("__import__:\n"); for (size_t i = 0; i < n_args; i++) { DEBUG_printf(" "); mp_obj_print(args[i], PRINT_REPR); DEBUG_printf("\n"); } #endif mp_obj_t module_name = args[0]; mp_obj_t fromtuple = mp_const_none; mp_int_t level = 0; if (n_args >= 4) { fromtuple = args[3]; if (n_args >= 5) { level = MP_OBJ_SMALL_INT_VALUE(args[4]); if (level < 0) { mp_raise_ValueError(NULL); } } } size_t mod_len; const char *mod_str = mp_obj_str_get_data(module_name, &mod_len); if (level != 0) { // What we want to do here is to take name of current module, // chop trailing components, and concatenate with passed-in // module name, thus resolving relative import name into absolute. // This even appears to be correct per // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name // "Relative imports use a module's __name__ attribute to determine that // module's position in the package hierarchy." level--; mp_obj_t this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__)); assert(this_name_q != MP_OBJ_NULL); #if MICROPY_CPYTHON_COMPAT if (MP_OBJ_QSTR_VALUE(this_name_q) == MP_QSTR___main__) { // This is a module run by -m command-line switch, get its real name from backup attribute this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); } #endif mp_map_t *globals_map = &mp_globals_get()->map; mp_map_elem_t *elem = mp_map_lookup(globals_map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP); bool is_pkg = (elem != NULL); #if DEBUG_PRINT DEBUG_printf("Current module/package: "); mp_obj_print(this_name_q, PRINT_REPR); DEBUG_printf(", is_package: %d", is_pkg); DEBUG_printf("\n"); #endif size_t this_name_l; const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l); const char *p = this_name + this_name_l; if (!is_pkg) { // We have module, but relative imports are anchored at package, so // go there. chop_component(this_name, &p); } while (level--) { chop_component(this_name, &p); } // We must have some component left over to import from if (p == this_name) { mp_raise_ValueError("cannot perform relative import"); } uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len); char *new_mod = mp_local_alloc(new_mod_l); memcpy(new_mod, this_name, p - this_name); if (mod_len != 0) { new_mod[p - this_name] = '.'; memcpy(new_mod + (p - this_name) + 1, mod_str, mod_len); } qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l); mp_local_free(new_mod); DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q)); module_name = MP_OBJ_NEW_QSTR(new_mod_q); mod_str = qstr_str(new_mod_q); mod_len = new_mod_l; } if (mod_len == 0) { mp_raise_ValueError(NULL); } // check if module already exists qstr module_name_qstr = mp_obj_str_get_qstr(module_name); mp_obj_t module_obj = mp_module_get(module_name_qstr); if (module_obj != MP_OBJ_NULL) { DEBUG_printf("Module already loaded\n"); // If it's not a package, return module right away char *p = strchr(mod_str, '.'); if (p == NULL) { return module_obj; } // If fromlist is not empty, return leaf module if (fromtuple != mp_const_none) { return module_obj; } // Otherwise, we need to return top-level package qstr pkg_name = qstr_from_strn(mod_str, p - mod_str); return mp_module_get(pkg_name); } DEBUG_printf("Module not yet loaded\n"); uint last = 0; VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX) module_obj = MP_OBJ_NULL; mp_obj_t top_module_obj = MP_OBJ_NULL; mp_obj_t outer_module_obj = MP_OBJ_NULL; uint i; for (i = 1; i <= mod_len; i++) { if (i == mod_len || mod_str[i] == '.') { // create a qstr for the module name up to this depth qstr mod_name = qstr_from_strn(mod_str, i); DEBUG_printf("Processing module: %s\n", qstr_str(mod_name)); DEBUG_printf("Previous path: =%.*s=\n", vstr_len(&path), vstr_str(&path)); // find the file corresponding to the module name mp_import_stat_t stat; if (vstr_len(&path) == 0) { // first module in the dotted-name; search for a directory or file stat = find_file(mod_str, i, &path); } else { // latter module in the dotted-name; append to path vstr_add_char(&path, PATH_SEP_CHAR); vstr_add_strn(&path, mod_str + last, i - last); stat = stat_dir_or_file(&path); } DEBUG_printf("Current path: %.*s\n", vstr_len(&path), vstr_str(&path)); if (stat == MP_IMPORT_STAT_NO_EXIST) { module_obj = MP_OBJ_NULL; #if MICROPY_MODULE_WEAK_LINKS // check if there is a weak link to this module if (i == mod_len) { module_obj = mp_module_search_umodule(mod_str); if (module_obj != MP_OBJ_NULL) { // found weak linked module mp_module_call_init(mod_name, module_obj); } } #endif if (module_obj == MP_OBJ_NULL) { // couldn't find the file, so fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_ImportError, "module not found"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "no module named '%q'", mod_name)); } } } else { // found the file, so get the module module_obj = mp_module_get(mod_name); } if (module_obj == MP_OBJ_NULL) { // module not already loaded, so load it! module_obj = mp_obj_new_module(mod_name); // if args[3] (fromtuple) has magic value False, set up // this module for command-line "-m" option (set module's // name to __main__ instead of real name). Do this only // for *modules* however - packages never have their names // replaced, instead they're -m'ed using a special __main__ // submodule in them. (This all apparently is done to not // touch package name itself, which is important for future // imports). if (i == mod_len && fromtuple == mp_const_false && stat != MP_IMPORT_STAT_DIR) { mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj); mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); #if MICROPY_CPYTHON_COMPAT // Store module as "__main__" in the dictionary of loaded modules (returned by sys.modules). mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj); // Store real name in "__main__" attribute. Chosen semi-randonly, to reuse existing qstr's. mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name)); #endif } if (stat == MP_IMPORT_STAT_DIR) { DEBUG_printf("%.*s is dir\n", vstr_len(&path), vstr_str(&path)); // https://docs.python.org/3/reference/import.html // "Specifically, any module that contains a __path__ attribute is considered a package." mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path))); size_t orig_path_len = path.len; vstr_add_char(&path, PATH_SEP_CHAR); vstr_add_str(&path, "__init__.py"); if (stat_file_py_or_mpy(&path) != MP_IMPORT_STAT_FILE) { //mp_warning("%s is imported as namespace package", vstr_str(&path)); } else { do_load(module_obj, &path); } path.len = orig_path_len; } else { // MP_IMPORT_STAT_FILE do_load(module_obj, &path); // This should be the last component in the import path. If there are // remaining components then it's an ImportError because the current path // (the module that was just loaded) is not a package. This will be caught // on the next iteration because the file will not exist. } } if (outer_module_obj != MP_OBJ_NULL) { qstr s = qstr_from_strn(mod_str + last, i - last); mp_store_attr(outer_module_obj, s, module_obj); } outer_module_obj = module_obj; if (top_module_obj == MP_OBJ_NULL) { top_module_obj = module_obj; } last = i + 1; } } // If fromlist is not empty, return leaf module if (fromtuple != mp_const_none) { return module_obj; } // Otherwise, we need to return top-level package return top_module_obj; } #else // MICROPY_ENABLE_EXTERNAL_IMPORT mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { // Check that it's not a relative import if (n_args >= 5 && MP_OBJ_SMALL_INT_VALUE(args[4]) != 0) { mp_raise_NotImplementedError("relative import"); } // Check if module already exists, and return it if it does qstr module_name_qstr = mp_obj_str_get_qstr(args[0]); mp_obj_t module_obj = mp_module_get(module_name_qstr); if (module_obj != MP_OBJ_NULL) { return module_obj; } #if MICROPY_MODULE_WEAK_LINKS // Check if there is a weak link to this module module_obj = mp_module_search_umodule(qstr_str(module_name_qstr)); if (module_obj != MP_OBJ_NULL) { // Found weak-linked module mp_module_call_init(module_name_qstr, module_obj); return module_obj; } #endif // Couldn't find the module, so fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_ImportError, "module not found"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "no module named '%q'", module_name_qstr)); } } #endif // MICROPY_ENABLE_EXTERNAL_IMPORT MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__); micropython-1.12/py/compile.c000066400000000000000000004350361357706137100162610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/scope.h" #include "py/emit.h" #include "py/compile.h" #include "py/runtime.h" #include "py/asmbase.h" #include "py/persistentcode.h" #if MICROPY_ENABLE_COMPILER // TODO need to mangle __attr names #define INVALID_LABEL (0xffff) typedef enum { // define rules with a compile function #define DEF_RULE(rule, comp, kind, ...) PN_##rule, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC PN_const_object, // special node for a constant, generic Python object // define rules without a compile function #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) PN_##rule, #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC } pn_kind_t; #define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE #if NEED_METHOD_TABLE // we need a method table to do the lookup for the emitter functions #define EMIT(fun) (comp->emit_method_table->fun(comp->emit)) #define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__)) #define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.local(comp->emit, qst, local_num, MP_EMIT_IDOP_LOCAL_FAST)) #define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst, MP_EMIT_IDOP_GLOBAL_GLOBAL)) #else // if we only have the bytecode emitter enabled then we can do a direct call to the functions #define EMIT(fun) (mp_emit_bc_##fun(comp->emit)) #define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__)) #define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_local(comp->emit, qst, local_num, MP_EMIT_IDOP_LOCAL_FAST)) #define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst, MP_EMIT_IDOP_GLOBAL_GLOBAL)) #endif #if MICROPY_EMIT_NATIVE && MICROPY_DYNAMIC_COMPILER #define NATIVE_EMITTER(f) emit_native_table[mp_dynamic_compiler.native_arch]->emit_##f #define NATIVE_EMITTER_TABLE emit_native_table[mp_dynamic_compiler.native_arch] STATIC const emit_method_table_t *emit_native_table[] = { NULL, &emit_native_x86_method_table, &emit_native_x64_method_table, &emit_native_arm_method_table, &emit_native_thumb_method_table, &emit_native_thumb_method_table, &emit_native_thumb_method_table, &emit_native_thumb_method_table, &emit_native_thumb_method_table, &emit_native_xtensa_method_table, &emit_native_xtensawin_method_table, }; #elif MICROPY_EMIT_NATIVE // define a macro to access external native emitter #if MICROPY_EMIT_X64 #define NATIVE_EMITTER(f) emit_native_x64_##f #elif MICROPY_EMIT_X86 #define NATIVE_EMITTER(f) emit_native_x86_##f #elif MICROPY_EMIT_THUMB #define NATIVE_EMITTER(f) emit_native_thumb_##f #elif MICROPY_EMIT_ARM #define NATIVE_EMITTER(f) emit_native_arm_##f #elif MICROPY_EMIT_XTENSA #define NATIVE_EMITTER(f) emit_native_xtensa_##f #elif MICROPY_EMIT_XTENSAWIN #define NATIVE_EMITTER(f) emit_native_xtensawin_##f #else #error "unknown native emitter" #endif #define NATIVE_EMITTER_TABLE &NATIVE_EMITTER(method_table) #endif #if MICROPY_EMIT_INLINE_ASM && MICROPY_DYNAMIC_COMPILER #define ASM_EMITTER(f) emit_asm_table[mp_dynamic_compiler.native_arch]->asm_##f #define ASM_EMITTER_TABLE emit_asm_table[mp_dynamic_compiler.native_arch] STATIC const emit_inline_asm_method_table_t *emit_asm_table[] = { NULL, NULL, NULL, &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, &emit_inline_xtensa_method_table, NULL, }; #elif MICROPY_EMIT_INLINE_ASM // define macros for inline assembler #if MICROPY_EMIT_INLINE_THUMB #define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb #define ASM_EMITTER(f) emit_inline_thumb_##f #elif MICROPY_EMIT_INLINE_XTENSA #define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa #define ASM_EMITTER(f) emit_inline_xtensa_##f #else #error "unknown asm emitter" #endif #define ASM_EMITTER_TABLE &ASM_EMITTER(method_table) #endif #define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm)) #define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__)) // elements in this struct are ordered to make it compact typedef struct _compiler_t { qstr source_file; uint8_t is_repl; uint8_t pass; // holds enum type pass_kind_t uint8_t have_star; // try to keep compiler clean from nlr mp_obj_t compile_error; // set to an exception object if there's an error size_t compile_error_line; // set to best guess of line of error uint next_label; uint16_t num_dict_params; uint16_t num_default_params; uint16_t break_label; // highest bit set indicates we are breaking out of a for loop uint16_t continue_label; uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT uint16_t break_continue_except_level; scope_t *scope_head; scope_t *scope_cur; emit_t *emit; // current emitter #if NEED_METHOD_TABLE const emit_method_table_t *emit_method_table; // current emit method table #endif #if MICROPY_EMIT_INLINE_ASM emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm #endif } compiler_t; STATIC void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) { // if the line of the error is unknown then try to update it from the pn if (comp->compile_error_line == 0 && MP_PARSE_NODE_IS_STRUCT(pn)) { comp->compile_error_line = ((mp_parse_node_struct_t*)pn)->source_line; } } STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) { // only register the error if there has been no other error if (comp->compile_error == MP_OBJ_NULL) { comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg); compile_error_set_line(comp, pn); } } STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra); STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind); STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map); STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn); STATIC uint comp_next_label(compiler_t *comp) { return comp->next_label++; } #if MICROPY_EMIT_NATIVE STATIC void reserve_labels_for_native(compiler_t *comp, int n) { if (comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) { comp->next_label += n; } } #else #define reserve_labels_for_native(comp, n) #endif STATIC void compile_increase_except_level(compiler_t *comp, uint label, int kind) { EMIT_ARG(setup_block, label, kind); comp->cur_except_level += 1; if (comp->cur_except_level > comp->scope_cur->exc_stack_size) { comp->scope_cur->exc_stack_size = comp->cur_except_level; } } STATIC void compile_decrease_except_level(compiler_t *comp) { assert(comp->cur_except_level > 0); comp->cur_except_level -= 1; EMIT(end_finally); reserve_labels_for_native(comp, 1); } STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) { scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options); scope->parent = comp->scope_cur; scope->next = NULL; if (comp->scope_head == NULL) { comp->scope_head = scope; } else { scope_t *s = comp->scope_head; while (s->next != NULL) { s = s->next; } s->next = scope; } return scope; } typedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn); STATIC void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_list_kind, apply_list_fun_t f) { if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { f(comp, pns->nodes[i]); } } else if (!MP_PARSE_NODE_IS_NULL(pn)) { f(comp, pn); } } STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) { int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { compile_node(comp, pns->nodes[i]); if (comp->compile_error != MP_OBJ_NULL) { // add line info for the error in case it didn't have a line number compile_error_set_line(comp, pns->nodes[i]); return; } } } STATIC void compile_load_id(compiler_t *comp, qstr qst) { if (comp->pass == MP_PASS_SCOPE) { mp_emit_common_get_id_for_load(comp->scope_cur, qst); } else { #if NEED_METHOD_TABLE mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst); #else mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_load_id_ops, comp->scope_cur, qst); #endif } } STATIC void compile_store_id(compiler_t *comp, qstr qst) { if (comp->pass == MP_PASS_SCOPE) { mp_emit_common_get_id_for_modification(comp->scope_cur, qst); } else { #if NEED_METHOD_TABLE mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst); #else mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_store_id_ops, comp->scope_cur, qst); #endif } } STATIC void compile_delete_id(compiler_t *comp, qstr qst) { if (comp->pass == MP_PASS_SCOPE) { mp_emit_common_get_id_for_modification(comp->scope_cur, qst); } else { #if NEED_METHOD_TABLE mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst); #else mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_delete_id_ops, comp->scope_cur, qst); #endif } } STATIC void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) { int total = 0; if (!MP_PARSE_NODE_IS_NULL(pn)) { compile_node(comp, pn); total += 1; } if (pns_list != NULL) { int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list); for (int i = 0; i < n; i++) { compile_node(comp, pns_list->nodes[i]); } total += n; } EMIT_ARG(build, total, MP_EMIT_BUILD_TUPLE); } STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) { // a simple tuple expression c_tuple(comp, MP_PARSE_NODE_NULL, pns); } STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) { if (mp_parse_node_is_const_false(pn)) { if (jump_if == false) { EMIT_ARG(jump, label); } return; } else if (mp_parse_node_is_const_true(pn)) { if (jump_if == true) { EMIT_ARG(jump, label); } return; } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) { if (jump_if == false) { and_or_logic1:; uint label2 = comp_next_label(comp); for (int i = 0; i < n - 1; i++) { c_if_cond(comp, pns->nodes[i], !jump_if, label2); } c_if_cond(comp, pns->nodes[n - 1], jump_if, label); EMIT_ARG(label_assign, label2); } else { and_or_logic2: for (int i = 0; i < n; i++) { c_if_cond(comp, pns->nodes[i], jump_if, label); } } return; } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) { if (jump_if == false) { goto and_or_logic2; } else { goto and_or_logic1; } } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) { c_if_cond(comp, pns->nodes[0], !jump_if, label); return; } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_atom_paren) { // cond is something in parenthesis if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty tuple, acts as false for the condition if (jump_if == false) { EMIT_ARG(jump, label); } } else { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)); // non-empty tuple, acts as true for the condition if (jump_if == true) { EMIT_ARG(jump, label); } } return; } } // nothing special, fall back to default compiling for node and jump compile_node(comp, pn); EMIT_ARG(pop_jump_if, jump_if, label); } typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t; STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind); STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) { if (assign_kind != ASSIGN_AUG_STORE) { compile_node(comp, pns->nodes[0]); } if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) { int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1); if (assign_kind != ASSIGN_AUG_STORE) { for (int i = 0; i < n - 1; i++) { compile_node(comp, pns1->nodes[i]); } } assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1])); pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1]; } if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) { if (assign_kind == ASSIGN_AUG_STORE) { EMIT(rot_three); EMIT_ARG(subscr, MP_EMIT_SUBSCR_STORE); } else { compile_node(comp, pns1->nodes[0]); if (assign_kind == ASSIGN_AUG_LOAD) { EMIT(dup_top_two); EMIT_ARG(subscr, MP_EMIT_SUBSCR_LOAD); } else { EMIT_ARG(subscr, MP_EMIT_SUBSCR_STORE); } } return; } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) { assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); if (assign_kind == ASSIGN_AUG_LOAD) { EMIT(dup_top); EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_LOAD); } else { if (assign_kind == ASSIGN_AUG_STORE) { EMIT(rot_two); } EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_STORE); } return; } } compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression"); } // we need to allow for a caller passing in 1 initial node (node_head) followed by an array of nodes (nodes_tail) STATIC void c_assign_tuple(compiler_t *comp, mp_parse_node_t node_head, uint num_tail, mp_parse_node_t *nodes_tail) { uint num_head = (node_head == MP_PARSE_NODE_NULL) ? 0 : 1; // look for star expression uint have_star_index = -1; if (num_head != 0 && MP_PARSE_NODE_IS_STRUCT_KIND(node_head, PN_star_expr)) { EMIT_ARG(unpack_ex, 0, num_tail); have_star_index = 0; } for (uint i = 0; i < num_tail; i++) { if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) { if (have_star_index == (uint)-1) { EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1); have_star_index = num_head + i; } else { compile_syntax_error(comp, nodes_tail[i], "multiple *x in assignment"); return; } } } if (have_star_index == (uint)-1) { EMIT_ARG(unpack_sequence, num_head + num_tail); } if (num_head != 0) { if (0 == have_star_index) { c_assign(comp, ((mp_parse_node_struct_t*)node_head)->nodes[0], ASSIGN_STORE); } else { c_assign(comp, node_head, ASSIGN_STORE); } } for (uint i = 0; i < num_tail; i++) { if (num_head + i == have_star_index) { c_assign(comp, ((mp_parse_node_struct_t*)nodes_tail[i])->nodes[0], ASSIGN_STORE); } else { c_assign(comp, nodes_tail[i], ASSIGN_STORE); } } } // assigns top of stack to pn STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) { assert(!MP_PARSE_NODE_IS_NULL(pn)); if (MP_PARSE_NODE_IS_LEAF(pn)) { if (MP_PARSE_NODE_IS_ID(pn)) { qstr arg = MP_PARSE_NODE_LEAF_ARG(pn); switch (assign_kind) { case ASSIGN_STORE: case ASSIGN_AUG_STORE: compile_store_id(comp, arg); break; case ASSIGN_AUG_LOAD: default: compile_load_id(comp, arg); break; } } else { goto cannot_assign; } } else { // pn must be a struct mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; switch (MP_PARSE_NODE_STRUCT_KIND(pns)) { case PN_atom_expr_normal: // lhs is an index or attribute c_assign_atom_expr(comp, pns, assign_kind); break; case PN_testlist_star_expr: case PN_exprlist: // lhs is a tuple if (assign_kind != ASSIGN_STORE) { goto cannot_assign; } c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes); break; case PN_atom_paren: // lhs is something in parenthesis if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty tuple goto cannot_assign; } else { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)); if (assign_kind != ASSIGN_STORE) { goto cannot_assign; } pns = (mp_parse_node_struct_t*)pns->nodes[0]; goto testlist_comp; } break; case PN_atom_bracket: // lhs is something in brackets if (assign_kind != ASSIGN_STORE) { goto cannot_assign; } if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty list, assignment allowed c_assign_tuple(comp, MP_PARSE_NODE_NULL, 0, NULL); } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { pns = (mp_parse_node_struct_t*)pns->nodes[0]; goto testlist_comp; } else { // brackets around 1 item c_assign_tuple(comp, pns->nodes[0], 0, NULL); } break; default: goto cannot_assign; } return; testlist_comp: // lhs is a sequence if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) { // sequence of one item, with trailing comma assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0])); c_assign_tuple(comp, pns->nodes[0], 0, NULL); } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) { // sequence of many items uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2); c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes); } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) { goto cannot_assign; } else { // sequence with 2 items goto sequence_with_2_items; } } else { // sequence with 2 items sequence_with_2_items: c_assign_tuple(comp, MP_PARSE_NODE_NULL, 2, pns->nodes); } return; } return; cannot_assign: compile_syntax_error(comp, pn, "can't assign to expression"); } // stuff for lambda and comprehensions and generators: // if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults // if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults // if both exist, the tuple is above the dictionary (ie the first pop gets the tuple) STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) { assert(n_pos_defaults >= 0); assert(n_kw_defaults >= 0); // set flags if (n_kw_defaults > 0) { this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS; } this_scope->num_def_pos_args = n_pos_defaults; #if MICROPY_EMIT_NATIVE // When creating a function/closure it will take a reference to the current globals comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_REFGLOBALS | MP_SCOPE_FLAG_HASCONSTS; #endif // make closed over variables, if any // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython) int nfree = 0; if (comp->scope_cur->kind != SCOPE_MODULE) { for (int i = 0; i < comp->scope_cur->id_info_len; i++) { id_info_t *id = &comp->scope_cur->id_info[i]; if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) { for (int j = 0; j < this_scope->id_info_len; j++) { id_info_t *id2 = &this_scope->id_info[j]; if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) { // in MicroPython we load closures using LOAD_FAST EMIT_LOAD_FAST(id->qst, id->local_num); nfree += 1; } } } } } // make the function/closure if (nfree == 0) { EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults); } else { EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults); } } STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) { // For efficiency of the code below we extract the parse-node kind here int pn_kind; if (MP_PARSE_NODE_IS_ID(pn)) { pn_kind = -1; } else { assert(MP_PARSE_NODE_IS_STRUCT(pn)); pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn); } if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) { comp->have_star = true; /* don't need to distinguish bare from named star mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // bare star } else { // named star } */ } else if (pn_kind == PN_typedargslist_dbl_star || pn_kind == PN_varargslist_dbl_star) { // named double star // TODO do we need to do anything with this? } else { mp_parse_node_t pn_id; mp_parse_node_t pn_equal; if (pn_kind == -1) { // this parameter is just an id pn_id = pn; pn_equal = MP_PARSE_NODE_NULL; } else if (pn_kind == PN_typedargslist_name) { // this parameter has a colon and/or equal specifier mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; pn_id = pns->nodes[0]; //pn_colon = pns->nodes[1]; // unused pn_equal = pns->nodes[2]; } else { assert(pn_kind == PN_varargslist_name); // should be // this parameter has an equal specifier mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; pn_id = pns->nodes[0]; pn_equal = pns->nodes[1]; } if (MP_PARSE_NODE_IS_NULL(pn_equal)) { // this parameter does not have a default value // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid) if (!comp->have_star && comp->num_default_params != 0) { compile_syntax_error(comp, pn, "non-default argument follows default argument"); return; } } else { // this parameter has a default value // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why if (comp->have_star) { comp->num_dict_params += 1; // in MicroPython we put the default dict parameters into a dictionary using the bytecode if (comp->num_dict_params == 1) { // in MicroPython we put the default positional parameters into a tuple using the bytecode // we need to do this here before we start building the map for the default keywords if (comp->num_default_params > 0) { EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE); } else { EMIT(load_null); // sentinel indicating empty default positional args } // first default dict param, so make the map EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP); } // compile value then key, then store it to the dict compile_node(comp, pn_equal); EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id)); EMIT(store_map); } else { comp->num_default_params += 1; compile_node(comp, pn_equal); } } } } STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) { // When we call compile_funcdef_lambdef_param below it can compile an arbitrary // expression for default arguments, which may contain a lambda. The lambda will // call here in a nested way, so we must save and restore the relevant state. bool orig_have_star = comp->have_star; uint16_t orig_num_dict_params = comp->num_dict_params; uint16_t orig_num_default_params = comp->num_default_params; // compile default parameters comp->have_star = false; comp->num_dict_params = 0; comp->num_default_params = 0; apply_to_single_or_list(comp, pn_params, pn_list_kind, compile_funcdef_lambdef_param); if (comp->compile_error != MP_OBJ_NULL) { return; } // in MicroPython we put the default positional parameters into a tuple using the bytecode // the default keywords args may have already made the tuple; if not, do it now if (comp->num_default_params > 0 && comp->num_dict_params == 0) { EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE); EMIT(load_null); // sentinel indicating empty default keyword args } // make the function close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params); // restore state comp->have_star = orig_have_star; comp->num_dict_params = orig_num_dict_params; comp->num_default_params = orig_num_default_params; } // leaves function object on stack // returns function name STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this function scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options); // store the function scope so the compiling function can use it at each pass pns->nodes[4] = (mp_parse_node_t)s; } // get the scope for this function scope_t *fscope = (scope_t*)pns->nodes[4]; // compile the function definition compile_funcdef_lambdef(comp, fscope, pns->nodes[1], PN_typedargslist); // return its name (the 'f' in "def f(...):") return fscope->simple_name; } // leaves class object on stack // returns class name STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this class scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options); // store the class scope so the compiling function can use it at each pass pns->nodes[3] = (mp_parse_node_t)s; } EMIT(load_build_class); // scope for this class scope_t *cscope = (scope_t*)pns->nodes[3]; // compile the class close_over_variables_etc(comp, cscope, 0, 0); // get its name EMIT_ARG(load_const_str, cscope->simple_name); // nodes[1] has parent classes, if any // empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling mp_parse_node_t parents = pns->nodes[1]; if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) { parents = MP_PARSE_NODE_NULL; } compile_trailer_paren_helper(comp, parents, false, 2); // return its name (the 'C' in class C(...):") return cscope->simple_name; } // returns true if it was a built-in decorator (even if the built-in had an error) STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) { if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) { return false; } if (name_len != 2) { compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator"); return true; } qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]); if (attr == MP_QSTR_bytecode) { *emit_options = MP_EMIT_OPT_BYTECODE; #if MICROPY_EMIT_NATIVE } else if (attr == MP_QSTR_native) { *emit_options = MP_EMIT_OPT_NATIVE_PYTHON; } else if (attr == MP_QSTR_viper) { *emit_options = MP_EMIT_OPT_VIPER; #endif #if MICROPY_EMIT_INLINE_ASM #if MICROPY_DYNAMIC_COMPILER } else if (attr == MP_QSTR_asm_thumb) { *emit_options = MP_EMIT_OPT_ASM; } else if (attr == MP_QSTR_asm_xtensa) { *emit_options = MP_EMIT_OPT_ASM; #else } else if (attr == ASM_DECORATOR_QSTR) { *emit_options = MP_EMIT_OPT_ASM; #endif #endif } else { compile_syntax_error(comp, name_nodes[1], "invalid micropython decorator"); } #if MICROPY_DYNAMIC_COMPILER if (*emit_options == MP_EMIT_OPT_NATIVE_PYTHON || *emit_options == MP_EMIT_OPT_VIPER) { if (emit_native_table[mp_dynamic_compiler.native_arch] == NULL) { compile_syntax_error(comp, name_nodes[1], "invalid arch"); } } else if (*emit_options == MP_EMIT_OPT_ASM) { if (emit_asm_table[mp_dynamic_compiler.native_arch] == NULL) { compile_syntax_error(comp, name_nodes[1], "invalid arch"); } } #endif return true; } STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) { // get the list of decorators mp_parse_node_t *nodes; int n = mp_parse_node_extract_list(&pns->nodes[0], PN_decorators, &nodes); // inherit emit options for this function/class definition uint emit_options = comp->scope_cur->emit_options; // compile each decorator int num_built_in_decorators = 0; for (int i = 0; i < n; i++) { assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i]; // nodes[0] contains the decorator function, which is a dotted name mp_parse_node_t *name_nodes; int name_len = mp_parse_node_extract_list(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes); // check for built-in decorators if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) { // this was a built-in num_built_in_decorators += 1; } else { // not a built-in, compile normally // compile the decorator function compile_node(comp, name_nodes[0]); for (int j = 1; j < name_len; j++) { assert(MP_PARSE_NODE_IS_ID(name_nodes[j])); // should be EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[j]), MP_EMIT_ATTR_LOAD); } // nodes[1] contains arguments to the decorator function, if any if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) { // call the decorator function with the arguments in nodes[1] compile_node(comp, pns_decorator->nodes[1]); } } } // compile the body (funcdef, async funcdef or classdef) and get its name mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1]; qstr body_name = 0; if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) { body_name = compile_funcdef_helper(comp, pns_body, emit_options); #if MICROPY_PY_ASYNC_AWAIT } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_async_funcdef) { assert(MP_PARSE_NODE_IS_STRUCT(pns_body->nodes[0])); mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns_body->nodes[0]; body_name = compile_funcdef_helper(comp, pns0, emit_options); scope_t *fscope = (scope_t*)pns0->nodes[4]; fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; #endif } else { assert(MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef); // should be body_name = compile_classdef_helper(comp, pns_body, emit_options); } // call each decorator for (int i = 0; i < n - num_built_in_decorators; i++) { EMIT_ARG(call_function, 1, 0, 0); } // store func/class object into name compile_store_id(comp, body_name); } STATIC void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) { qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options); // store function object into function name compile_store_id(comp, fname); } STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_ID(pn)) { compile_delete_id(comp, MP_PARSE_NODE_LEAF_ARG(pn)); } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_expr_normal)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; compile_node(comp, pns->nodes[0]); // base of the atom_expr_normal node if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) { int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1); for (int i = 0; i < n - 1; i++) { compile_node(comp, pns1->nodes[i]); } assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1])); pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1]; } if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) { compile_node(comp, pns1->nodes[0]); EMIT_ARG(subscr, MP_EMIT_SUBSCR_DELETE); } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) { assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_DELETE); } else { goto cannot_delete; } } else { goto cannot_delete; } } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) { pn = ((mp_parse_node_struct_t*)pn)->nodes[0]; if (MP_PARSE_NODE_IS_NULL(pn)) { goto cannot_delete; } else { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) { // sequence of one item, with trailing comma assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0])); c_del_stmt(comp, pns->nodes[0]); } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) { // sequence of many items int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1); c_del_stmt(comp, pns->nodes[0]); for (int i = 0; i < n; i++) { c_del_stmt(comp, pns1->nodes[i]); } } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) { goto cannot_delete; } else { // sequence with 2 items goto sequence_with_2_items; } } else { // sequence with 2 items sequence_with_2_items: c_del_stmt(comp, pns->nodes[0]); c_del_stmt(comp, pns->nodes[1]); } } } else { // some arbitrary statement that we can't delete (eg del 1) goto cannot_delete; } return; cannot_delete: compile_syntax_error(comp, (mp_parse_node_t)pn, "can't delete expression"); } STATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt); } STATIC void compile_break_cont_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { uint16_t label; if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_break_stmt) { label = comp->break_label; } else { label = comp->continue_label; } if (label == INVALID_LABEL) { compile_syntax_error(comp, (mp_parse_node_t)pns, "'break'/'continue' outside loop"); } assert(comp->cur_except_level >= comp->break_continue_except_level); EMIT_ARG(unwind_jump, label, comp->cur_except_level - comp->break_continue_except_level); } STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->scope_cur->kind != SCOPE_FUNCTION) { compile_syntax_error(comp, (mp_parse_node_t)pns, "'return' outside function"); return; } if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // no argument to 'return', so return None EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); } else if (MICROPY_COMP_RETURN_IF_EXPR && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) { // special case when returning an if-expression; to match CPython optimisation mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0]; mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1]; uint l_fail = comp_next_label(comp); c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition compile_node(comp, pns_test_if_expr->nodes[0]); // success value EMIT(return_value); EMIT_ARG(label_assign, l_fail); compile_node(comp, pns_test_if_else->nodes[1]); // failure value } else { compile_node(comp, pns->nodes[0]); } EMIT(return_value); } STATIC void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); EMIT(pop_top); } STATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // raise EMIT_ARG(raise_varargs, 0); } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) { // raise x from y pns = (mp_parse_node_struct_t*)pns->nodes[0]; compile_node(comp, pns->nodes[0]); compile_node(comp, pns->nodes[1]); EMIT_ARG(raise_varargs, 2); } else { // raise x compile_node(comp, pns->nodes[0]); EMIT_ARG(raise_varargs, 1); } } // q_base holds the base of the name // eg a -> q_base=a // a.b.c -> q_base=a STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) { bool is_as = false; if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; // a name of the form x as y; unwrap it *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]); pn = pns->nodes[0]; is_as = true; } if (MP_PARSE_NODE_IS_NULL(pn)) { // empty name (eg, from . import x) *q_base = MP_QSTR_; EMIT_ARG(import, MP_QSTR_, MP_EMIT_IMPORT_NAME); // import the empty string } else if (MP_PARSE_NODE_IS_ID(pn)) { // just a simple name qstr q_full = MP_PARSE_NODE_LEAF_ARG(pn); if (!is_as) { *q_base = q_full; } EMIT_ARG(import, q_full, MP_EMIT_IMPORT_NAME); } else { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_name)); // should be mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; { // a name of the form a.b.c if (!is_as) { *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); } int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); int len = n - 1; for (int i = 0; i < n; i++) { len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); } char *q_ptr = mp_local_alloc(len); char *str_dest = q_ptr; for (int i = 0; i < n; i++) { if (i > 0) { *str_dest++ = '.'; } size_t str_src_len; const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len); memcpy(str_dest, str_src, str_src_len); str_dest += str_src_len; } qstr q_full = qstr_from_strn(q_ptr, len); mp_local_free(q_ptr); EMIT_ARG(import, q_full, MP_EMIT_IMPORT_NAME); if (is_as) { for (int i = 1; i < n; i++) { EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), MP_EMIT_ATTR_LOAD); } } } } } STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) { EMIT_ARG(load_const_small_int, 0); // level 0 import EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything qstr q_base; do_import_name(comp, pn, &q_base); compile_store_id(comp, q_base); } STATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) { apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name); } STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { mp_parse_node_t pn_import_source = pns->nodes[0]; // extract the preceding .'s (if any) for a relative import, to compute the import level uint import_level = 0; do { mp_parse_node_t pn_rel; if (MP_PARSE_NODE_IS_TOKEN(pn_import_source) || MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_one_or_more_period_or_ellipsis)) { // This covers relative imports with dots only like "from .. import" pn_rel = pn_import_source; pn_import_source = MP_PARSE_NODE_NULL; } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_import_from_2b)) { // This covers relative imports starting with dot(s) like "from .foo import" mp_parse_node_struct_t *pns_2b = (mp_parse_node_struct_t*)pn_import_source; pn_rel = pns_2b->nodes[0]; pn_import_source = pns_2b->nodes[1]; assert(!MP_PARSE_NODE_IS_NULL(pn_import_source)); // should not be } else { // Not a relative import break; } // get the list of . and/or ...'s mp_parse_node_t *nodes; int n = mp_parse_node_extract_list(&pn_rel, PN_one_or_more_period_or_ellipsis, &nodes); // count the total number of .'s for (int i = 0; i < n; i++) { if (MP_PARSE_NODE_IS_TOKEN_KIND(nodes[i], MP_TOKEN_DEL_PERIOD)) { import_level++; } else { // should be an MP_TOKEN_ELLIPSIS import_level += 3; } } } while (0); if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) { #if MICROPY_CPYTHON_COMPAT if (comp->scope_cur->kind != SCOPE_MODULE) { compile_syntax_error(comp, (mp_parse_node_t)pns, "import * not at module level"); return; } #endif EMIT_ARG(load_const_small_int, import_level); // build the "fromlist" tuple EMIT_ARG(load_const_str, MP_QSTR__star_); EMIT_ARG(build, 1, MP_EMIT_BUILD_TUPLE); // do the import qstr dummy_q; do_import_name(comp, pn_import_source, &dummy_q); EMIT_ARG(import, MP_QSTRnull, MP_EMIT_IMPORT_STAR); } else { EMIT_ARG(load_const_small_int, import_level); // build the "fromlist" tuple mp_parse_node_t *pn_nodes; int n = mp_parse_node_extract_list(&pns->nodes[1], PN_import_as_names, &pn_nodes); for (int i = 0; i < n; i++) { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name)); mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i]; qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id EMIT_ARG(load_const_str, id2); } EMIT_ARG(build, n, MP_EMIT_BUILD_TUPLE); // do the import qstr dummy_q; do_import_name(comp, pn_import_source, &dummy_q); for (int i = 0; i < n; i++) { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name)); mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i]; qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id EMIT_ARG(import, id2, MP_EMIT_IMPORT_FROM); if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) { compile_store_id(comp, id2); } else { compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1])); } } EMIT(pop_top); } } STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) { if (id_info->kind != ID_INFO_KIND_UNDECIDED && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) { compile_syntax_error(comp, pn, "identifier redefined as global"); return; } id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT; // if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL id_info = scope_find_global(comp->scope_cur, id_info->qst); if (id_info != NULL) { id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT; } } STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) { if (id_info->kind == ID_INFO_KIND_UNDECIDED) { id_info->kind = ID_INFO_KIND_GLOBAL_IMPLICIT; scope_check_to_close_over(comp->scope_cur, id_info); if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { compile_syntax_error(comp, pn, "no binding for nonlocal found"); } } else if (id_info->kind != ID_INFO_KIND_FREE) { compile_syntax_error(comp, pn, "identifier redefined as nonlocal"); } } STATIC void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->pass == MP_PASS_SCOPE) { bool is_global = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_global_stmt; if (!is_global && comp->scope_cur->kind == SCOPE_MODULE) { compile_syntax_error(comp, (mp_parse_node_t)pns, "can't declare nonlocal in outer code"); return; } mp_parse_node_t *nodes; int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes); for (int i = 0; i < n; i++) { qstr qst = MP_PARSE_NODE_LEAF_ARG(nodes[i]); id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, ID_INFO_KIND_UNDECIDED); if (is_global) { compile_declare_global(comp, (mp_parse_node_t)pns, id_info); } else { compile_declare_nonlocal(comp, (mp_parse_node_t)pns, id_info); } } } } STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // with optimisations enabled we don't compile assertions if (MP_STATE_VM(mp_optimise_value) != 0) { return; } uint l_end = comp_next_label(comp); c_if_cond(comp, pns->nodes[0], true, l_end); EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { // assertion message compile_node(comp, pns->nodes[1]); EMIT_ARG(call_function, 1, 0, 0); } EMIT_ARG(raise_varargs, 1); EMIT_ARG(label_assign, l_end); } STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { uint l_end = comp_next_label(comp); // optimisation: don't emit anything when "if False" if (!mp_parse_node_is_const_false(pns->nodes[0])) { uint l_fail = comp_next_label(comp); c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition compile_node(comp, pns->nodes[1]); // if block // optimisation: skip everything else when "if True" if (mp_parse_node_is_const_true(pns->nodes[0])) { goto done; } if ( // optimisation: don't jump over non-existent elif/else blocks !(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3])) // optimisation: don't jump if last instruction was return && !EMIT(last_emit_was_return_value) ) { // jump over elif/else blocks EMIT_ARG(jump, l_end); } EMIT_ARG(label_assign, l_fail); } // compile elif blocks (if any) mp_parse_node_t *pn_elif; int n_elif = mp_parse_node_extract_list(&pns->nodes[2], PN_if_stmt_elif_list, &pn_elif); for (int i = 0; i < n_elif; i++) { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_elif[i], PN_if_stmt_elif)); // should be mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pn_elif[i]; // optimisation: don't emit anything when "if False" if (!mp_parse_node_is_const_false(pns_elif->nodes[0])) { uint l_fail = comp_next_label(comp); c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition compile_node(comp, pns_elif->nodes[1]); // elif block // optimisation: skip everything else when "elif True" if (mp_parse_node_is_const_true(pns_elif->nodes[0])) { goto done; } // optimisation: don't jump if last instruction was return if (!EMIT(last_emit_was_return_value)) { EMIT_ARG(jump, l_end); } EMIT_ARG(label_assign, l_fail); } } // compile else block compile_node(comp, pns->nodes[3]); // can be null done: EMIT_ARG(label_assign, l_end); } #define START_BREAK_CONTINUE_BLOCK \ uint16_t old_break_label = comp->break_label; \ uint16_t old_continue_label = comp->continue_label; \ uint16_t old_break_continue_except_level = comp->break_continue_except_level; \ uint break_label = comp_next_label(comp); \ uint continue_label = comp_next_label(comp); \ comp->break_label = break_label; \ comp->continue_label = continue_label; \ comp->break_continue_except_level = comp->cur_except_level; #define END_BREAK_CONTINUE_BLOCK \ comp->break_label = old_break_label; \ comp->continue_label = old_continue_label; \ comp->break_continue_except_level = old_break_continue_except_level; STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { START_BREAK_CONTINUE_BLOCK if (!mp_parse_node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False" uint top_label = comp_next_label(comp); if (!mp_parse_node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for "while True" EMIT_ARG(jump, continue_label); } EMIT_ARG(label_assign, top_label); compile_node(comp, pns->nodes[1]); // body EMIT_ARG(label_assign, continue_label); c_if_cond(comp, pns->nodes[0], true, top_label); // condition } // break/continue apply to outer loop (if any) in the else block END_BREAK_CONTINUE_BLOCK compile_node(comp, pns->nodes[2]); // else EMIT_ARG(label_assign, break_label); } // This function compiles an optimised for-loop of the form: // for in range(, , ): // // else: // // must be an identifier and must be a small-int. // // Semantics of for-loop require: // - final failing value should not be stored in the loop variable // - if the loop never runs, the loop variable should never be assigned // - assignments to , or in the body do not alter the loop // ( is a constant for us, so no need to worry about it changing) // // If is a small-int, then the stack during the for-loop contains just // the current value of . Otherwise, the stack contains then the // current value of . STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) { START_BREAK_CONTINUE_BLOCK uint top_label = comp_next_label(comp); uint entry_label = comp_next_label(comp); // put the end value on the stack if it's not a small-int constant bool end_on_stack = !MP_PARSE_NODE_IS_SMALL_INT(pn_end); if (end_on_stack) { compile_node(comp, pn_end); } // compile: start compile_node(comp, pn_start); EMIT_ARG(jump, entry_label); EMIT_ARG(label_assign, top_label); // duplicate next value and store it to var EMIT(dup_top); c_assign(comp, pn_var, ASSIGN_STORE); // compile body compile_node(comp, pn_body); EMIT_ARG(label_assign, continue_label); // compile: var + step compile_node(comp, pn_step); EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD); EMIT_ARG(label_assign, entry_label); // compile: if var end: goto top if (end_on_stack) { EMIT(dup_top_two); EMIT(rot_two); } else { EMIT(dup_top); compile_node(comp, pn_end); } assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step)); if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) { EMIT_ARG(binary_op, MP_BINARY_OP_LESS); } else { EMIT_ARG(binary_op, MP_BINARY_OP_MORE); } EMIT_ARG(pop_jump_if, true, top_label); // break/continue apply to outer loop (if any) in the else block END_BREAK_CONTINUE_BLOCK // Compile the else block. We must pop the iterator variables before // executing the else code because it may contain break/continue statements. uint end_label = 0; if (!MP_PARSE_NODE_IS_NULL(pn_else)) { // discard final value of "var", and possible "end" value EMIT(pop_top); if (end_on_stack) { EMIT(pop_top); } compile_node(comp, pn_else); end_label = comp_next_label(comp); EMIT_ARG(jump, end_label); EMIT_ARG(adjust_stack_size, 1 + end_on_stack); } EMIT_ARG(label_assign, break_label); // discard final value of var that failed the loop condition EMIT(pop_top); // discard value if it's on the stack if (end_on_stack) { EMIT(pop_top); } if (!MP_PARSE_NODE_IS_NULL(pn_else)) { EMIT_ARG(label_assign, end_label); } } STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // this bit optimises: for in range(...), turning it into an explicitly incremented variable // this is actually slower, but uses no heap memory // for viper it will be much, much faster if (/*comp->scope_cur->emit_options == MP_EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_atom_expr_normal)) { mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pns_it->nodes[1]) == PN_trailer_paren) { mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0]; mp_parse_node_t *args; int n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args); mp_parse_node_t pn_range_start; mp_parse_node_t pn_range_end; mp_parse_node_t pn_range_step; bool optimize = false; if (1 <= n_args && n_args <= 3) { optimize = true; if (n_args == 1) { pn_range_start = mp_parse_node_new_small_int(0); pn_range_end = args[0]; pn_range_step = mp_parse_node_new_small_int(1); } else if (n_args == 2) { pn_range_start = args[0]; pn_range_end = args[1]; pn_range_step = mp_parse_node_new_small_int(1); } else { pn_range_start = args[0]; pn_range_end = args[1]; pn_range_step = args[2]; // the step must be a non-zero constant integer to do the optimisation if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step) || MP_PARSE_NODE_LEAF_SMALL_INT(pn_range_step) == 0) { optimize = false; } } // arguments must be able to be compiled as standard expressions if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_start)) { int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_range_start); if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) { optimize = false; } } if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_end)) { int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_range_end); if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) { optimize = false; } } } if (optimize) { compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]); return; } } } START_BREAK_CONTINUE_BLOCK comp->break_label |= MP_EMIT_BREAK_FROM_FOR; uint pop_label = comp_next_label(comp); compile_node(comp, pns->nodes[1]); // iterator EMIT_ARG(get_iter, true); EMIT_ARG(label_assign, continue_label); EMIT_ARG(for_iter, pop_label); c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable compile_node(comp, pns->nodes[2]); // body if (!EMIT(last_emit_was_return_value)) { EMIT_ARG(jump, continue_label); } EMIT_ARG(label_assign, pop_label); EMIT(for_iter_end); // break/continue apply to outer loop (if any) in the else block END_BREAK_CONTINUE_BLOCK compile_node(comp, pns->nodes[3]); // else (may be empty) EMIT_ARG(label_assign, break_label); } STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) { // setup code uint l1 = comp_next_label(comp); uint success_label = comp_next_label(comp); compile_increase_except_level(comp, l1, MP_EMIT_SETUP_BLOCK_EXCEPT); compile_node(comp, pn_body); // body EMIT_ARG(pop_except_jump, success_label, false); // jump over exception handler EMIT_ARG(label_assign, l1); // start of exception handler EMIT(start_except_handler); // at this point the top of the stack contains the exception instance that was raised uint l2 = comp_next_label(comp); for (int i = 0; i < n_except; i++) { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i]; qstr qstr_exception_local = 0; uint end_finally_label = comp_next_label(comp); #if MICROPY_PY_SYS_SETTRACE EMIT_ARG(set_source_line, pns_except->source_line); #endif if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) { // this is a catch all exception handler if (i + 1 != n_except) { compile_syntax_error(comp, pn_excepts[i], "default 'except' must be last"); compile_decrease_except_level(comp); return; } } else { // this exception handler requires a match to a certain type of exception mp_parse_node_t pns_exception_expr = pns_except->nodes[0]; if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) { mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr; if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) { // handler binds the exception to a local pns_exception_expr = pns3->nodes[0]; qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]); } } EMIT(dup_top); compile_node(comp, pns_exception_expr); EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH); EMIT_ARG(pop_jump_if, false, end_finally_label); } // either discard or store the exception instance if (qstr_exception_local == 0) { EMIT(pop_top); } else { compile_store_id(comp, qstr_exception_local); } // If the exception is bound to a variable then the of the // exception handler is wrapped in a try-finally so that the name can // be deleted (per Python semantics) even if the has an exception. // In such a case the generated code for the exception handler is: // try: // // finally: // = None // del uint l3 = 0; if (qstr_exception_local != 0) { l3 = comp_next_label(comp); compile_increase_except_level(comp, l3, MP_EMIT_SETUP_BLOCK_FINALLY); } compile_node(comp, pns_except->nodes[1]); // the if (qstr_exception_local != 0) { EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT_ARG(label_assign, l3); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); compile_store_id(comp, qstr_exception_local); compile_delete_id(comp, qstr_exception_local); compile_decrease_except_level(comp); } EMIT_ARG(pop_except_jump, l2, true); EMIT_ARG(label_assign, end_finally_label); EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance } compile_decrease_except_level(comp); EMIT(end_except_handler); EMIT_ARG(label_assign, success_label); compile_node(comp, pn_else); // else block, can be null EMIT_ARG(label_assign, l2); } STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) { uint l_finally_block = comp_next_label(comp); compile_increase_except_level(comp, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY); if (n_except == 0) { assert(MP_PARSE_NODE_IS_NULL(pn_else)); EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state compile_node(comp, pn_body); EMIT_ARG(adjust_stack_size, -3); } else { compile_try_except(comp, pn_body, n_except, pn_except, pn_else); } EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT_ARG(label_assign, l_finally_block); compile_node(comp, pn_finally); compile_decrease_except_level(comp); } STATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should be { mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) { // just try-finally compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]); } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) { // try-except and possibly else and/or finally mp_parse_node_t *pn_excepts; int n_except = mp_parse_node_extract_list(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts); if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) { // no finally compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]); } else { // have finally compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((mp_parse_node_struct_t*)pns2->nodes[2])->nodes[0]); } } else { // just try-except mp_parse_node_t *pn_excepts; int n_except = mp_parse_node_extract_list(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts); compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL); } } } STATIC void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) { if (n == 0) { // no more pre-bits, compile the body of the with compile_node(comp, body); } else { uint l_end = comp_next_label(comp); if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) { // this pre-bit is of the form "a as b" mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0]; compile_node(comp, pns->nodes[0]); compile_increase_except_level(comp, l_end, MP_EMIT_SETUP_BLOCK_WITH); c_assign(comp, pns->nodes[1], ASSIGN_STORE); } else { // this pre-bit is just an expression compile_node(comp, nodes[0]); compile_increase_except_level(comp, l_end, MP_EMIT_SETUP_BLOCK_WITH); EMIT(pop_top); } // compile additional pre-bits and the body compile_with_stmt_helper(comp, n - 1, nodes + 1, body); // finish this with block EMIT_ARG(with_cleanup, l_end); reserve_labels_for_native(comp, 3); // used by native's with_cleanup compile_decrease_except_level(comp); } } STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit) mp_parse_node_t *nodes; int n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes); assert(n > 0); // compile in a nested fashion compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]); } STATIC void compile_yield_from(compiler_t *comp) { EMIT_ARG(get_iter, false); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT_ARG(yield, MP_EMIT_YIELD_FROM); reserve_labels_for_native(comp, 3); } #if MICROPY_PY_ASYNC_AWAIT STATIC void compile_await_object_method(compiler_t *comp, qstr method) { EMIT_ARG(load_method, method, false); EMIT_ARG(call_method, 0, 0, 0); compile_yield_from(comp); } STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // comp->break_label |= MP_EMIT_BREAK_FROM_FOR; qstr context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]); uint while_else_label = comp_next_label(comp); uint try_exception_label = comp_next_label(comp); uint try_else_label = comp_next_label(comp); uint try_finally_label = comp_next_label(comp); compile_node(comp, pns->nodes[1]); // iterator compile_await_object_method(comp, MP_QSTR___aiter__); compile_store_id(comp, context); START_BREAK_CONTINUE_BLOCK EMIT_ARG(label_assign, continue_label); compile_increase_except_level(comp, try_exception_label, MP_EMIT_SETUP_BLOCK_EXCEPT); compile_load_id(comp, context); compile_await_object_method(comp, MP_QSTR___anext__); c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable EMIT_ARG(pop_except_jump, try_else_label, false); EMIT_ARG(label_assign, try_exception_label); EMIT(start_except_handler); EMIT(dup_top); EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration); EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH); EMIT_ARG(pop_jump_if, false, try_finally_label); EMIT(pop_top); // pop exception instance EMIT_ARG(pop_except_jump, while_else_label, true); EMIT_ARG(label_assign, try_finally_label); EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack compile_decrease_except_level(comp); EMIT(end_except_handler); EMIT_ARG(label_assign, try_else_label); compile_node(comp, pns->nodes[2]); // body EMIT_ARG(jump, continue_label); // break/continue apply to outer loop (if any) in the else block END_BREAK_CONTINUE_BLOCK EMIT_ARG(label_assign, while_else_label); compile_node(comp, pns->nodes[3]); // else EMIT_ARG(label_assign, break_label); } STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) { if (n == 0) { // no more pre-bits, compile the body of the with compile_node(comp, body); } else { uint l_finally_block = comp_next_label(comp); uint l_aexit_no_exc = comp_next_label(comp); uint l_ret_unwind_jump = comp_next_label(comp); uint l_end = comp_next_label(comp); if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) { // this pre-bit is of the form "a as b" mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0]; compile_node(comp, pns->nodes[0]); EMIT(dup_top); compile_await_object_method(comp, MP_QSTR___aenter__); c_assign(comp, pns->nodes[1], ASSIGN_STORE); } else { // this pre-bit is just an expression compile_node(comp, nodes[0]); EMIT(dup_top); compile_await_object_method(comp, MP_QSTR___aenter__); EMIT(pop_top); } // To keep the Python stack size down, and because we can't access values on // this stack further down than 3 elements (via rot_three), we don't preload // __aexit__ (as per normal with) but rather wait until we need it below. // Start the try-finally statement compile_increase_except_level(comp, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY); // Compile any additional pre-bits of the "async with", and also the body EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state compile_async_with_stmt_helper(comp, n - 1, nodes + 1, body); EMIT_ARG(adjust_stack_size, -3); // We have now finished the "try" block and fall through to the "finally" // At this point, after the with body has executed, we have 3 cases: // 1. no exception, we just fall through to this point; stack: (..., ctx_mgr) // 2. exception propagating out, we get to the finally block; stack: (..., ctx_mgr, exc) // 3. return or unwind jump, we get to the finally block; stack: (..., ctx_mgr, X, INT) // Handle case 1: call __aexit__ // Stack: (..., ctx_mgr) EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // to tell end_finally there's no exception EMIT(rot_two); EMIT_ARG(jump, l_aexit_no_exc); // jump to code below to call __aexit__ // Start of "finally" block // At this point we have case 2 or 3, we detect which one by the TOS being an exception or not EMIT_ARG(label_assign, l_finally_block); // Detect if TOS an exception or not EMIT(dup_top); EMIT_LOAD_GLOBAL(MP_QSTR_BaseException); EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH); EMIT_ARG(pop_jump_if, false, l_ret_unwind_jump); // if not an exception then we have case 3 // Handle case 2: call __aexit__ and either swallow or re-raise the exception // Stack: (..., ctx_mgr, exc) EMIT(dup_top); EMIT(rot_three); EMIT(rot_two); EMIT_ARG(load_method, MP_QSTR___aexit__, false); EMIT(rot_three); EMIT(rot_three); EMIT(dup_top); #if MICROPY_CPYTHON_COMPAT EMIT_ARG(attr, MP_QSTR___class__, MP_EMIT_ATTR_LOAD); // get type(exc) #else compile_load_id(comp, MP_QSTR_type); EMIT(rot_two); EMIT_ARG(call_function, 1, 0, 0); // get type(exc) #endif EMIT(rot_two); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // dummy traceback value // Stack: (..., exc, __aexit__, ctx_mgr, type(exc), exc, None) EMIT_ARG(call_method, 3, 0, 0); compile_yield_from(comp); EMIT_ARG(pop_jump_if, false, l_end); EMIT(pop_top); // pop exception EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // replace with None to swallow exception EMIT_ARG(jump, l_end); EMIT_ARG(adjust_stack_size, 2); // Handle case 3: call __aexit__ // Stack: (..., ctx_mgr, X, INT) EMIT_ARG(label_assign, l_ret_unwind_jump); EMIT(rot_three); EMIT(rot_three); EMIT_ARG(label_assign, l_aexit_no_exc); EMIT_ARG(load_method, MP_QSTR___aexit__, false); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT(dup_top); EMIT(dup_top); EMIT_ARG(call_method, 3, 0, 0); compile_yield_from(comp); EMIT(pop_top); EMIT_ARG(adjust_stack_size, -1); // End of "finally" block // Stack can have one of three configurations: // a. (..., None) - from either case 1, or case 2 with swallowed exception // b. (..., exc) - from case 2 with re-raised exception // c. (..., X, INT) - from case 3 EMIT_ARG(label_assign, l_end); compile_decrease_except_level(comp); } } STATIC void compile_async_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit) mp_parse_node_t *nodes; int n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes); assert(n > 0); // compile in a nested fashion compile_async_with_stmt_helper(comp, n, nodes, pns->nodes[1]); } STATIC void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[0])); mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0]; if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_funcdef) { // async def compile_funcdef(comp, pns0); scope_t *fscope = (scope_t*)pns0->nodes[4]; fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; } else if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_for_stmt) { // async for compile_async_for_stmt(comp, pns0); } else { // async with assert(MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_with_stmt); compile_async_with_stmt(comp, pns0); } } #endif STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) { // for REPL, evaluate then print the expression compile_load_id(comp, MP_QSTR___repl_print__); compile_node(comp, pns->nodes[0]); EMIT_ARG(call_function, 1, 0, 0); EMIT(pop_top); } else { // for non-REPL, evaluate then discard the expression if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) { // do nothing with a lonely constant } else { compile_node(comp, pns->nodes[0]); // just an expression EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack } } } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; int kind = MP_PARSE_NODE_STRUCT_KIND(pns1); if (kind == PN_expr_stmt_augassign) { c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign compile_node(comp, pns1->nodes[1]); // rhs assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0])); mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]); mp_binary_op_t op = MP_BINARY_OP_INPLACE_OR + (tok - MP_TOKEN_DEL_PIPE_EQUAL); EMIT_ARG(binary_op, op); c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign } else if (kind == PN_expr_stmt_assign_list) { int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1; compile_node(comp, pns1->nodes[rhs]); // rhs // following CPython, we store left-most first if (rhs > 0) { EMIT(dup_top); } c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store for (int i = 0; i < rhs; i++) { if (i + 1 < rhs) { EMIT(dup_top); } c_assign(comp, pns1->nodes[i], ASSIGN_STORE); // middle store } } else { plain_assign: #if MICROPY_COMP_DOUBLE_TUPLE_ASSIGN if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)) { mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0]; pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; uint32_t n_pns0 = MP_PARSE_NODE_STRUCT_NUM_NODES(pns0); // Can only optimise a tuple-to-tuple assignment when all of the following hold: // - equal number of items in LHS and RHS tuples // - 2 or 3 items in the tuples // - there are no star expressions in the LHS tuple if (n_pns0 == MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) && (n_pns0 == 2 #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN || n_pns0 == 3 #endif ) && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr) && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr) #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN && (n_pns0 == 2 || !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) #endif ) { // Optimisation for a, b = c, d or a, b, c = d, e, f compile_node(comp, pns1->nodes[0]); // rhs compile_node(comp, pns1->nodes[1]); // rhs #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN if (n_pns0 == 3) { compile_node(comp, pns1->nodes[2]); // rhs EMIT(rot_three); } #endif EMIT(rot_two); c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN if (n_pns0 == 3) { c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store } #endif return; } } #endif compile_node(comp, pns->nodes[1]); // rhs c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store } } else { goto plain_assign; } } STATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else)); mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1]; uint l_fail = comp_next_label(comp); uint l_end = comp_next_label(comp); c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition compile_node(comp, pns->nodes[0]); // success value EMIT_ARG(jump, l_end); EMIT_ARG(label_assign, l_fail); EMIT_ARG(adjust_stack_size, -1); // adjust stack size compile_node(comp, pns_test_if_else->nodes[1]); // failure value EMIT_ARG(label_assign, l_end); } STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this lambda scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options); // store the lambda scope so the compiling function (this one) can use it at each pass pns->nodes[2] = (mp_parse_node_t)s; } // get the scope for this lambda scope_t *this_scope = (scope_t*)pns->nodes[2]; // compile the lambda definition compile_funcdef_lambdef(comp, this_scope, pns->nodes[0], PN_varargslist); } STATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) { bool cond = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test; uint l_end = comp_next_label(comp); int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < n; i += 1) { compile_node(comp, pns->nodes[i]); if (i + 1 < n) { EMIT_ARG(jump_if_or_pop, cond, l_end); } } EMIT_ARG(label_assign, l_end); } STATIC void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); EMIT_ARG(unary_op, MP_UNARY_OP_NOT); } STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) { int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); bool multi = (num_nodes > 3); uint l_fail = 0; if (multi) { l_fail = comp_next_label(comp); } for (int i = 1; i + 1 < num_nodes; i += 2) { compile_node(comp, pns->nodes[i + 1]); if (i + 2 < num_nodes) { EMIT(dup_top); EMIT(rot_three); } if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) { mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]); mp_binary_op_t op; if (tok == MP_TOKEN_KW_IN) { op = MP_BINARY_OP_IN; } else { op = MP_BINARY_OP_LESS + (tok - MP_TOKEN_OP_LESS); } EMIT_ARG(binary_op, op); } else { assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])); // should be mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i]; int kind = MP_PARSE_NODE_STRUCT_KIND(pns2); if (kind == PN_comp_op_not_in) { EMIT_ARG(binary_op, MP_BINARY_OP_NOT_IN); } else { assert(kind == PN_comp_op_is); // should be if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) { EMIT_ARG(binary_op, MP_BINARY_OP_IS); } else { EMIT_ARG(binary_op, MP_BINARY_OP_IS_NOT); } } } if (i + 2 < num_nodes) { EMIT_ARG(jump_if_or_pop, false, l_fail); } } if (multi) { uint l_end = comp_next_label(comp); EMIT_ARG(jump, l_end); EMIT_ARG(label_assign, l_fail); EMIT_ARG(adjust_stack_size, 1); EMIT(rot_two); EMIT(pop_top); EMIT_ARG(label_assign, l_end); } } STATIC void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_syntax_error(comp, (mp_parse_node_t)pns, "*x must be assignment target"); } STATIC void compile_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns) { MP_STATIC_ASSERT(MP_BINARY_OP_OR + PN_xor_expr - PN_expr == MP_BINARY_OP_XOR); MP_STATIC_ASSERT(MP_BINARY_OP_OR + PN_and_expr - PN_expr == MP_BINARY_OP_AND); mp_binary_op_t binary_op = MP_BINARY_OP_OR + MP_PARSE_NODE_STRUCT_KIND(pns) - PN_expr; int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); for (int i = 1; i < num_nodes; ++i) { compile_node(comp, pns->nodes[i]); EMIT_ARG(binary_op, binary_op); } } STATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) { int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); for (int i = 1; i + 1 < num_nodes; i += 2) { compile_node(comp, pns->nodes[i + 1]); mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]); mp_binary_op_t op = MP_BINARY_OP_LSHIFT + (tok - MP_TOKEN_OP_DBL_LESS); EMIT_ARG(binary_op, op); } } STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[1]); mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); mp_unary_op_t op; if (tok == MP_TOKEN_OP_TILDE) { op = MP_UNARY_OP_INVERT; } else { assert(tok == MP_TOKEN_OP_PLUS || tok == MP_TOKEN_OP_MINUS); op = MP_UNARY_OP_POSITIVE + (tok - MP_TOKEN_OP_PLUS); } EMIT_ARG(unary_op, op); } STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) { // compile the subject of the expression compile_node(comp, pns->nodes[0]); // compile_atom_expr_await may call us with a NULL node if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { return; } // get the array of trailers (known to be an array of PARSE_NODE_STRUCT) size_t num_trail = 1; mp_parse_node_struct_t **pns_trail = (mp_parse_node_struct_t**)&pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_atom_expr_trailers) { num_trail = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_trail[0]); pns_trail = (mp_parse_node_struct_t**)&pns_trail[0]->nodes[0]; } // the current index into the array of trailers size_t i = 0; // handle special super() call if (comp->scope_cur->kind == SCOPE_FUNCTION && MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren && MP_PARSE_NODE_IS_NULL(pns_trail[0]->nodes[0])) { // at this point we have matched "super()" within a function // load the class for super to search for a parent compile_load_id(comp, MP_QSTR___class__); // look for first argument to function (assumes it's "self") bool found = false; id_info_t *id = &comp->scope_cur->id_info[0]; for (size_t n = comp->scope_cur->id_info_len; n > 0; --n, ++id) { if (id->flags & ID_FLAG_IS_PARAM) { // first argument found; load it compile_load_id(comp, id->qst); found = true; break; } } if (!found) { compile_syntax_error(comp, (mp_parse_node_t)pns_trail[0], "super() can't find self"); // really a TypeError return; } if (num_trail >= 3 && MP_PARSE_NODE_STRUCT_KIND(pns_trail[1]) == PN_trailer_period && MP_PARSE_NODE_STRUCT_KIND(pns_trail[2]) == PN_trailer_paren) { // optimisation for method calls super().f(...), to eliminate heap allocation mp_parse_node_struct_t *pns_period = pns_trail[1]; mp_parse_node_struct_t *pns_paren = pns_trail[2]; EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), true); compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0); i = 3; } else { // a super() call EMIT_ARG(call_function, 2, 0, 0); i = 1; } #if MICROPY_COMP_CONST_LITERAL && MICROPY_PY_COLLECTIONS_ORDEREDDICT // handle special OrderedDict constructor } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_OrderedDict && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren && MP_PARSE_NODE_IS_STRUCT_KIND(pns_trail[0]->nodes[0], PN_atom_brace)) { // at this point we have matched "OrderedDict({...})" EMIT_ARG(call_function, 0, 0, 0); mp_parse_node_struct_t *pns_dict = (mp_parse_node_struct_t*)pns_trail[0]->nodes[0]; compile_atom_brace_helper(comp, pns_dict, false); i = 1; #endif } // compile the remaining trailers for (; i < num_trail; i++) { if (i + 1 < num_trail && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i]) == PN_trailer_period && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i + 1]) == PN_trailer_paren) { // optimisation for method calls a.f(...), following PyPy mp_parse_node_struct_t *pns_period = pns_trail[i]; mp_parse_node_struct_t *pns_paren = pns_trail[i + 1]; EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false); compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0); i += 1; } else { // node is one of: trailer_paren, trailer_bracket, trailer_period compile_node(comp, (mp_parse_node_t)pns_trail[i]); } } } STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power EMIT_ARG(binary_op, MP_BINARY_OP_POWER); } STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) { // function to call is on top of stack // get the list of arguments mp_parse_node_t *args; int n_args = mp_parse_node_extract_list(&pn_arglist, PN_arglist, &args); // compile the arguments // Rather than calling compile_node on the list, we go through the list of args // explicitly here so that we can count the number of arguments and give sensible // error messages. int n_positional = n_positional_extra; uint n_keyword = 0; uint star_flags = 0; mp_parse_node_struct_t *star_args_node = NULL, *dblstar_args_node = NULL; for (int i = 0; i < n_args; i++) { if (MP_PARSE_NODE_IS_STRUCT(args[i])) { mp_parse_node_struct_t *pns_arg = (mp_parse_node_struct_t*)args[i]; if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_star) { if (star_flags & MP_EMIT_STAR_FLAG_SINGLE) { compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple *x"); return; } star_flags |= MP_EMIT_STAR_FLAG_SINGLE; star_args_node = pns_arg; } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_dbl_star) { if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) { compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple **x"); return; } star_flags |= MP_EMIT_STAR_FLAG_DOUBLE; dblstar_args_node = pns_arg; } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) { if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_comp_for)) { if (!MP_PARSE_NODE_IS_ID(pns_arg->nodes[0])) { compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "LHS of keyword arg must be an id"); return; } EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0])); compile_node(comp, pns_arg->nodes[1]); n_keyword += 1; } else { compile_comprehension(comp, pns_arg, SCOPE_GEN_EXPR); n_positional++; } } else { goto normal_argument; } } else { normal_argument: if (star_flags) { compile_syntax_error(comp, args[i], "non-keyword arg after */**"); return; } if (n_keyword > 0) { compile_syntax_error(comp, args[i], "non-keyword arg after keyword arg"); return; } compile_node(comp, args[i]); n_positional++; } } // compile the star/double-star arguments if we had them // if we had one but not the other then we load "null" as a place holder if (star_flags != 0) { if (star_args_node == NULL) { EMIT(load_null); } else { compile_node(comp, star_args_node->nodes[0]); } if (dblstar_args_node == NULL) { EMIT(load_null); } else { compile_node(comp, dblstar_args_node->nodes[0]); } } // emit the function/method call if (is_method_call) { EMIT_ARG(call_method, n_positional, n_keyword, star_flags); } else { EMIT_ARG(call_function, n_positional, n_keyword, star_flags); } } // pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) { assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2); assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1]; if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this comprehension scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options); // store the comprehension scope so the compiling function (this one) can use it at each pass pns_comp_for->nodes[3] = (mp_parse_node_t)s; } // get the scope for this comprehension scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3]; // compile the comprehension close_over_variables_etc(comp, this_scope, 0, 0); compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator if (kind == SCOPE_GEN_EXPR) { EMIT_ARG(get_iter, false); } EMIT_ARG(call_function, 1, 0, 0); } STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // an empty tuple c_tuple(comp, MP_PARSE_NODE_NULL, NULL); } else { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)); pns = (mp_parse_node_struct_t*)pns->nodes[0]; assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1])); if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) { // tuple of one item, with trailing comma assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0])); c_tuple(comp, pns->nodes[0], NULL); } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) { // tuple of many items c_tuple(comp, pns->nodes[0], pns2); } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) { // generator expression compile_comprehension(comp, pns, SCOPE_GEN_EXPR); } else { // tuple with 2 items goto tuple_with_2_items; } } else { // tuple with 2 items tuple_with_2_items: c_tuple(comp, MP_PARSE_NODE_NULL, pns); } } } STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty list EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST); } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0]; if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) { mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) { // list of one item, with trailing comma assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0])); compile_node(comp, pns2->nodes[0]); EMIT_ARG(build, 1, MP_EMIT_BUILD_LIST); } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) { // list of many items compile_node(comp, pns2->nodes[0]); compile_generic_all_nodes(comp, pns3); EMIT_ARG(build, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3), MP_EMIT_BUILD_LIST); } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) { // list comprehension compile_comprehension(comp, pns2, SCOPE_LIST_COMP); } else { // list with 2 items goto list_with_2_items; } } else { // list with 2 items list_with_2_items: compile_node(comp, pns2->nodes[0]); compile_node(comp, pns2->nodes[1]); EMIT_ARG(build, 2, MP_EMIT_BUILD_LIST); } } else { // list with 1 item compile_node(comp, pns->nodes[0]); EMIT_ARG(build, 1, MP_EMIT_BUILD_LIST); } } STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map) { mp_parse_node_t pn = pns->nodes[0]; if (MP_PARSE_NODE_IS_NULL(pn)) { // empty dict if (create_map) { EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP); } } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { pns = (mp_parse_node_struct_t*)pn; if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) { // dict with one element if (create_map) { EMIT_ARG(build, 1, MP_EMIT_BUILD_MAP); } compile_node(comp, pn); EMIT(store_map); } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) { assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) { // dict/set with multiple elements // get tail elements (2nd, 3rd, ...) mp_parse_node_t *nodes; int n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes); // first element sets whether it's a dict or set bool is_dict; if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) { // a dictionary if (create_map) { EMIT_ARG(build, 1 + n, MP_EMIT_BUILD_MAP); } compile_node(comp, pns->nodes[0]); EMIT(store_map); is_dict = true; } else { // a set compile_node(comp, pns->nodes[0]); // 1st value of set is_dict = false; } // process rest of elements for (int i = 0; i < n; i++) { mp_parse_node_t pn_i = nodes[i]; bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn_i, PN_dictorsetmaker_item); compile_node(comp, pn_i); if (is_dict) { if (!is_key_value) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax"); } else { compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dict"); } return; } EMIT(store_map); } else { if (is_key_value) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax"); } else { compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set"); } return; } } } #if MICROPY_PY_BUILTINS_SET // if it's a set, build it if (!is_dict) { EMIT_ARG(build, 1 + n, MP_EMIT_BUILD_SET); } #endif } else { assert(MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for); // should be // dict/set comprehension if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) { // a dictionary comprehension compile_comprehension(comp, pns, SCOPE_DICT_COMP); } else { // a set comprehension compile_comprehension(comp, pns, SCOPE_SET_COMP); } } } else { // set with one element goto set_with_one_element; } } else { // set with one element set_with_one_element: #if MICROPY_PY_BUILTINS_SET compile_node(comp, pn); EMIT_ARG(build, 1, MP_EMIT_BUILD_SET); #else assert(0); #endif } } STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_atom_brace_helper(comp, pns, true); } STATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_trailer_paren_helper(comp, pns->nodes[0], false, 0); } STATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { // object who's index we want is on top of stack compile_node(comp, pns->nodes[0]); // the index EMIT_ARG(subscr, MP_EMIT_SUBSCR_LOAD); } STATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) { // object who's attribute we want is on top of stack EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]), MP_EMIT_ATTR_LOAD); // attribute to get } #if MICROPY_PY_BUILTINS_SLICE STATIC void compile_subscript(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_2) { compile_node(comp, pns->nodes[0]); // start of slice assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be pns = (mp_parse_node_struct_t*)pns->nodes[1]; } else { // pns is a PN_subscript_3, load None for start of slice EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); } assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be mp_parse_node_t pn = pns->nodes[0]; if (MP_PARSE_NODE_IS_NULL(pn)) { // [?:] EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE); } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { pns = (mp_parse_node_struct_t*)pn; if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) { EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); pn = pns->nodes[0]; if (MP_PARSE_NODE_IS_NULL(pn)) { // [?::] EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE); } else { // [?::x] compile_node(comp, pn); EMIT_ARG(build, 3, MP_EMIT_BUILD_SLICE); } } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) { compile_node(comp, pns->nodes[0]); assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be pns = (mp_parse_node_struct_t*)pns->nodes[1]; assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // [?:x:] EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE); } else { // [?:x:x] compile_node(comp, pns->nodes[0]); EMIT_ARG(build, 3, MP_EMIT_BUILD_SLICE); } } else { // [?:x] compile_node(comp, pn); EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE); } } else { // [?:x] compile_node(comp, pn); EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE); } } #endif // MICROPY_PY_BUILTINS_SLICE STATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) { // if this is called then we are compiling a dict key:value pair compile_node(comp, pns->nodes[1]); // value compile_node(comp, pns->nodes[0]); // key } STATIC void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) { qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options); // store class object into class name compile_store_id(comp, cname); } STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) { compile_syntax_error(comp, (mp_parse_node_t)pns, "'yield' outside function"); return; } if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT_ARG(yield, MP_EMIT_YIELD_VALUE); reserve_labels_for_native(comp, 1); } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) { pns = (mp_parse_node_struct_t*)pns->nodes[0]; compile_node(comp, pns->nodes[0]); compile_yield_from(comp); } else { compile_node(comp, pns->nodes[0]); EMIT_ARG(yield, MP_EMIT_YIELD_VALUE); reserve_labels_for_native(comp, 1); } } #if MICROPY_PY_ASYNC_AWAIT STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) { compile_syntax_error(comp, (mp_parse_node_t)pns, "'await' outside function"); return; } compile_atom_expr_normal(comp, pns); compile_yield_from(comp); } #endif STATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) { #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D // nodes are 32-bit pointers, but need to extract 64-bit object return (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32); #else return (mp_obj_t)pns->nodes[0]; #endif } STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(load_const_obj, get_const_object(pns)); } typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*); STATIC const compile_function_t compile_function[] = { // only define rules with a compile function #define c(f) compile_##f #define DEF_RULE(rule, comp, kind, ...) comp, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef c #undef DEF_RULE #undef DEF_RULE_NC compile_const_object, }; STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_NULL(pn)) { // pass } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn); #if MICROPY_DYNAMIC_COMPILER mp_uint_t sign_mask = -((mp_uint_t)1 << (mp_dynamic_compiler.small_int_bits - 1)); if ((arg & sign_mask) == 0 || (arg & sign_mask) == sign_mask) { // integer fits in target runtime's small-int EMIT_ARG(load_const_small_int, arg); } else { // integer doesn't fit, so create a multi-precision int object // (but only create the actual object on the last pass) if (comp->pass != MP_PASS_EMIT) { EMIT_ARG(load_const_obj, mp_const_none); } else { EMIT_ARG(load_const_obj, mp_obj_new_int_from_ll(arg)); } } #else EMIT_ARG(load_const_small_int, arg); #endif } else if (MP_PARSE_NODE_IS_LEAF(pn)) { uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn); switch (MP_PARSE_NODE_LEAF_KIND(pn)) { case MP_PARSE_NODE_ID: compile_load_id(comp, arg); break; case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg); break; case MP_PARSE_NODE_BYTES: // only create and load the actual bytes object on the last pass if (comp->pass != MP_PASS_EMIT) { EMIT_ARG(load_const_obj, mp_const_none); } else { size_t len; const byte *data = qstr_data(arg, &len); EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len)); } break; case MP_PARSE_NODE_TOKEN: default: if (arg == MP_TOKEN_NEWLINE) { // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline) // or when single_input lets through a NEWLINE (user enters a blank line) // do nothing } else { EMIT_ARG(load_const_tok, arg); } break; } } else { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; EMIT_ARG(set_source_line, pns->source_line); assert(MP_PARSE_NODE_STRUCT_KIND(pns) <= PN_const_object); compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)]; f(comp, pns); } } #if MICROPY_EMIT_NATIVE STATIC int compile_viper_type_annotation(compiler_t *comp, mp_parse_node_t pn_annotation) { int native_type = MP_NATIVE_TYPE_OBJ; if (MP_PARSE_NODE_IS_NULL(pn_annotation)) { // No annotation, type defaults to object } else if (MP_PARSE_NODE_IS_ID(pn_annotation)) { qstr type_name = MP_PARSE_NODE_LEAF_ARG(pn_annotation); native_type = mp_native_type_from_qstr(type_name); if (native_type < 0) { comp->compile_error = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, "unknown type '%q'", type_name); native_type = 0; } } else { compile_syntax_error(comp, pn_annotation, "annotation must be an identifier"); } return native_type; } #endif STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star) { (void)pn_dbl_star; // check that **kw is last if ((comp->scope_cur->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) { compile_syntax_error(comp, pn, "invalid syntax"); return; } qstr param_name = MP_QSTRnull; uint param_flag = ID_FLAG_IS_PARAM; mp_parse_node_struct_t *pns = NULL; if (MP_PARSE_NODE_IS_ID(pn)) { param_name = MP_PARSE_NODE_LEAF_ARG(pn); if (comp->have_star) { // comes after a star, so counts as a keyword-only parameter comp->scope_cur->num_kwonly_args += 1; } else { // comes before a star, so counts as a positional parameter comp->scope_cur->num_pos_args += 1; } } else { assert(MP_PARSE_NODE_IS_STRUCT(pn)); pns = (mp_parse_node_struct_t*)pn; if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) { // named parameter with possible annotation param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); if (comp->have_star) { // comes after a star, so counts as a keyword-only parameter comp->scope_cur->num_kwonly_args += 1; } else { // comes before a star, so counts as a positional parameter comp->scope_cur->num_pos_args += 1; } } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) { if (comp->have_star) { // more than one star compile_syntax_error(comp, pn, "invalid syntax"); return; } comp->have_star = true; param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM; if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // bare star // TODO see http://www.python.org/dev/peps/pep-3102/ //assert(comp->scope_cur->num_dict_params == 0); pns = NULL; } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) { // named star comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS; param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); pns = NULL; } else { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)); // should be // named star with possible annotation comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS; pns = (mp_parse_node_struct_t*)pns->nodes[0]; param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); } } else { // double star with possible annotation assert(MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star); // should be param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM; comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS; } } if (param_name != MP_QSTRnull) { id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, ID_INFO_KIND_UNDECIDED); if (id_info->kind != ID_INFO_KIND_UNDECIDED) { compile_syntax_error(comp, pn, "argument name reused"); return; } id_info->kind = ID_INFO_KIND_LOCAL; id_info->flags = param_flag; #if MICROPY_EMIT_NATIVE if (comp->scope_cur->emit_options == MP_EMIT_OPT_VIPER && pn_name == PN_typedargslist_name && pns != NULL) { id_info->flags |= compile_viper_type_annotation(comp, pns->nodes[1]) << ID_FLAG_VIPER_TYPE_POS; } #else (void)pns; #endif } } STATIC void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) { compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star); } STATIC void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) { compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star); } STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pns_comp_for, mp_parse_node_t pn_inner_expr, int for_depth) { uint l_top = comp_next_label(comp); uint l_end = comp_next_label(comp); EMIT_ARG(label_assign, l_top); EMIT_ARG(for_iter, l_end); c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE); mp_parse_node_t pn_iter = pns_comp_for->nodes[2]; tail_recursion: if (MP_PARSE_NODE_IS_NULL(pn_iter)) { // no more nested if/for; compile inner expression compile_node(comp, pn_inner_expr); if (comp->scope_cur->kind == SCOPE_GEN_EXPR) { EMIT_ARG(yield, MP_EMIT_YIELD_VALUE); reserve_labels_for_native(comp, 1); EMIT(pop_top); } else { EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5); } } else if (MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_if) { // if condition mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter; c_if_cond(comp, pns_comp_if->nodes[0], false, l_top); pn_iter = pns_comp_if->nodes[1]; goto tail_recursion; } else { assert(MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_for); // should be // for loop mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter; compile_node(comp, pns_comp_for2->nodes[1]); EMIT_ARG(get_iter, true); compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1); } EMIT_ARG(jump, l_top); EMIT_ARG(label_assign, l_end); EMIT(for_iter_end); } STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) { #if MICROPY_ENABLE_DOC_STRING // see http://www.python.org/dev/peps/pep-0257/ // look for the first statement if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) { // a statement; fall through } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) { // file input; find the first non-newline node mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { pn = pns->nodes[i]; if (!(MP_PARSE_NODE_IS_LEAF(pn) && MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN && MP_PARSE_NODE_LEAF_ARG(pn) == MP_TOKEN_NEWLINE)) { // not a newline, so this is the first statement; finish search break; } } // if we didn't find a non-newline then it's okay to fall through; pn will be a newline and so doc-string test below will fail gracefully } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) { // a list of statements; get the first one pn = ((mp_parse_node_struct_t*)pn)->nodes[0]; } else { return; } // check the first statement for a doc string if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING) || (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object) && mp_obj_is_str(get_const_object((mp_parse_node_struct_t*)pns->nodes[0])))) { // compile the doc string compile_node(comp, pns->nodes[0]); // store the doc string compile_store_id(comp, MP_QSTR___doc__); } } #else (void)comp; (void)pn; #endif } STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { comp->pass = pass; comp->scope_cur = scope; comp->next_label = 0; EMIT_ARG(start_pass, pass, scope); reserve_labels_for_native(comp, 6); // used by native's start_pass if (comp->pass == MP_PASS_SCOPE) { // reset maximum stack sizes in scope // they will be computed in this first pass scope->stack_size = 0; scope->exc_stack_size = 0; } // compile if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) { assert(scope->kind == SCOPE_MODULE); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; compile_node(comp, pns->nodes[0]); // compile the expression EMIT(return_value); } else if (scope->kind == SCOPE_MODULE) { if (!comp->is_repl) { check_for_doc_string(comp, scope->pn); } compile_node(comp, scope->pn); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT(return_value); } else if (scope->kind == SCOPE_FUNCTION) { assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef); // work out number of parameters, keywords and default parameters, and add them to the id_info array // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) if (comp->pass == MP_PASS_SCOPE) { comp->have_star = false; apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param); #if MICROPY_EMIT_NATIVE if (scope->emit_options == MP_EMIT_OPT_VIPER) { // Compile return type; pns->nodes[2] is return/whole function annotation scope->scope_flags |= compile_viper_type_annotation(comp, pns->nodes[2]) << MP_SCOPE_FLAG_VIPERRET_POS; } #endif // MICROPY_EMIT_NATIVE } compile_node(comp, pns->nodes[3]); // 3 is function body // emit return if it wasn't the last opcode if (!EMIT(last_emit_was_return_value)) { EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT(return_value); } } else if (scope->kind == SCOPE_LAMBDA) { assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3); // Set the source line number for the start of the lambda EMIT_ARG(set_source_line, pns->source_line); // work out number of parameters, keywords and default parameters, and add them to the id_info array // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) if (comp->pass == MP_PASS_SCOPE) { comp->have_star = false; apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param); } compile_node(comp, pns->nodes[1]); // 1 is lambda body // if the lambda is a generator, then we return None, not the result of the expression of the lambda if (scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { EMIT(pop_top); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); } EMIT(return_value); } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) { // a bit of a hack at the moment assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2); assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1]; // We need a unique name for the comprehension argument (the iterator). // CPython uses .0, but we should be able to use anything that won't // clash with a user defined variable. Best to use an existing qstr, // so we use the blank qstr. qstr qstr_arg = MP_QSTR_; if (comp->pass == MP_PASS_SCOPE) { scope_find_or_add_id(comp->scope_cur, qstr_arg, ID_INFO_KIND_LOCAL); scope->num_pos_args = 1; } // Set the source line number for the start of the comprehension EMIT_ARG(set_source_line, pns->source_line); if (scope->kind == SCOPE_LIST_COMP) { EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST); } else if (scope->kind == SCOPE_DICT_COMP) { EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP); #if MICROPY_PY_BUILTINS_SET } else if (scope->kind == SCOPE_SET_COMP) { EMIT_ARG(build, 0, MP_EMIT_BUILD_SET); #endif } // There are 4 slots on the stack for the iterator, and the first one is // NULL to indicate that the second one points to the iterator object. if (scope->kind == SCOPE_GEN_EXPR) { MP_STATIC_ASSERT(MP_OBJ_ITER_BUF_NSLOTS == 4); EMIT(load_null); compile_load_id(comp, qstr_arg); EMIT(load_null); EMIT(load_null); } else { compile_load_id(comp, qstr_arg); EMIT_ARG(get_iter, true); } compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0); if (scope->kind == SCOPE_GEN_EXPR) { EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); } EMIT(return_value); } else { assert(scope->kind == SCOPE_CLASS); assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef); if (comp->pass == MP_PASS_SCOPE) { scope_find_or_add_id(scope, MP_QSTR___class__, ID_INFO_KIND_LOCAL); } #if MICROPY_PY_SYS_SETTRACE EMIT_ARG(set_source_line, pns->source_line); #endif compile_load_id(comp, MP_QSTR___name__); compile_store_id(comp, MP_QSTR___module__); EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name compile_store_id(comp, MP_QSTR___qualname__); check_for_doc_string(comp, pns->nodes[2]); compile_node(comp, pns->nodes[2]); // 2 is class body id_info_t *id = scope_find(scope, MP_QSTR___class__); assert(id != NULL); if (id->kind == ID_INFO_KIND_LOCAL) { EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); } else { EMIT_LOAD_FAST(MP_QSTR___class__, id->local_num); } EMIT(return_value); } EMIT(end_pass); // make sure we match all the exception levels assert(comp->cur_except_level == 0); } #if MICROPY_EMIT_INLINE_ASM // requires 3 passes: SCOPE, CODE_SIZE, EMIT STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) { comp->pass = pass; comp->scope_cur = scope; comp->next_label = 0; if (scope->kind != SCOPE_FUNCTION) { compile_syntax_error(comp, MP_PARSE_NODE_NULL, "inline assembler must be a function"); return; } if (comp->pass > MP_PASS_SCOPE) { EMIT_INLINE_ASM_ARG(start_pass, comp->pass, &comp->compile_error); } // get the function definition parse node assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef); //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name // parameters are in pns->nodes[1] if (comp->pass == MP_PASS_CODE_SIZE) { mp_parse_node_t *pn_params; int n_params = mp_parse_node_extract_list(&pns->nodes[1], PN_typedargslist, &pn_params); scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params); if (comp->compile_error != MP_OBJ_NULL) { goto inline_asm_error; } } // pns->nodes[2] is function return annotation mp_uint_t type_sig = MP_NATIVE_TYPE_INT; mp_parse_node_t pn_annotation = pns->nodes[2]; if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) { // nodes[2] can be null or a test-expr if (MP_PARSE_NODE_IS_ID(pn_annotation)) { qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation); switch (ret_type) { case MP_QSTR_object: type_sig = MP_NATIVE_TYPE_OBJ; break; case MP_QSTR_bool: type_sig = MP_NATIVE_TYPE_BOOL; break; case MP_QSTR_int: type_sig = MP_NATIVE_TYPE_INT; break; case MP_QSTR_uint: type_sig = MP_NATIVE_TYPE_UINT; break; default: compile_syntax_error(comp, pn_annotation, "unknown type"); return; } } else { compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier"); } } mp_parse_node_t pn_body = pns->nodes[3]; // body mp_parse_node_t *nodes; int num = mp_parse_node_extract_list(&pn_body, PN_suite_block_stmts, &nodes); for (int i = 0; i < num; i++) { assert(MP_PARSE_NODE_IS_STRUCT(nodes[i])); mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i]; if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_pass_stmt) { // no instructions continue; } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_expr_stmt) { // not an instruction; error not_an_instruction: compile_syntax_error(comp, nodes[i], "expecting an assembler instruction"); return; } // check structure of parse node assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0])); if (!MP_PARSE_NODE_IS_NULL(pns2->nodes[1])) { goto not_an_instruction; } pns2 = (mp_parse_node_struct_t*)pns2->nodes[0]; if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_atom_expr_normal) { goto not_an_instruction; } if (!MP_PARSE_NODE_IS_ID(pns2->nodes[0])) { goto not_an_instruction; } if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren)) { goto not_an_instruction; } // parse node looks like an instruction // get instruction name and args qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]); pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren mp_parse_node_t *pn_arg; int n_args = mp_parse_node_extract_list(&pns2->nodes[0], PN_arglist, &pn_arg); // emit instructions if (op == MP_QSTR_label) { if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) { compile_syntax_error(comp, nodes[i], "'label' requires 1 argument"); return; } uint lab = comp_next_label(comp); if (pass > MP_PASS_SCOPE) { if (!EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]))) { compile_syntax_error(comp, nodes[i], "label redefined"); return; } } } else if (op == MP_QSTR_align) { if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) { compile_syntax_error(comp, nodes[i], "'align' requires 1 argument"); return; } if (pass > MP_PASS_SCOPE) { mp_asm_base_align((mp_asm_base_t*)comp->emit_inline_asm, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0])); } } else if (op == MP_QSTR_data) { if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) { compile_syntax_error(comp, nodes[i], "'data' requires at least 2 arguments"); return; } if (pass > MP_PASS_SCOPE) { mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]); for (uint j = 1; j < n_args; j++) { if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[j])) { compile_syntax_error(comp, nodes[i], "'data' requires integer arguments"); return; } mp_asm_base_data((mp_asm_base_t*)comp->emit_inline_asm, bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j])); } } } else { if (pass > MP_PASS_SCOPE) { EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg); } } if (comp->compile_error != MP_OBJ_NULL) { pns = pns2; // this is the parse node that had the error goto inline_asm_error; } } if (comp->pass > MP_PASS_SCOPE) { EMIT_INLINE_ASM_ARG(end_pass, type_sig); if (comp->pass == MP_PASS_EMIT) { void *f = mp_asm_base_get_code((mp_asm_base_t*)comp->emit_inline_asm); mp_emit_glue_assign_native(comp->scope_cur->raw_code, MP_CODE_NATIVE_ASM, f, mp_asm_base_get_code_size((mp_asm_base_t*)comp->emit_inline_asm), NULL, #if MICROPY_PERSISTENT_CODE_SAVE 0, 0, 0, 0, NULL, #endif comp->scope_cur->num_pos_args, 0, type_sig); } } if (comp->compile_error != MP_OBJ_NULL) { // inline assembler had an error; set line for its exception inline_asm_error: comp->compile_error_line = pns->source_line; } } #endif STATIC void scope_compute_things(scope_t *scope) { // in MicroPython we put the *x parameter after all other parameters (except **y) if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) { id_info_t *id_param = NULL; for (int i = scope->id_info_len - 1; i >= 0; i--) { id_info_t *id = &scope->id_info[i]; if (id->flags & ID_FLAG_IS_STAR_PARAM) { if (id_param != NULL) { // swap star param with last param id_info_t temp = *id_param; *id_param = *id; *id = temp; } break; } else if (id_param == NULL && id->flags == ID_FLAG_IS_PARAM) { id_param = id; } } } // in functions, turn implicit globals into explicit globals // compute the index of each local scope->num_locals = 0; for (int i = 0; i < scope->id_info_len; i++) { id_info_t *id = &scope->id_info[i]; if (scope->kind == SCOPE_CLASS && id->qst == MP_QSTR___class__) { // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL continue; } if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT; } #if MICROPY_EMIT_NATIVE if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) { // This function makes a reference to a global variable if (scope->emit_options == MP_EMIT_OPT_VIPER && mp_native_type_from_qstr(id->qst) >= MP_NATIVE_TYPE_INT) { // A casting operator in viper mode, not a real global reference } else { scope->scope_flags |= MP_SCOPE_FLAG_REFGLOBALS; } } #endif // params always count for 1 local, even if they are a cell if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) { id->local_num = scope->num_locals++; } } // compute the index of cell vars for (int i = 0; i < scope->id_info_len; i++) { id_info_t *id = &scope->id_info[i]; // in MicroPython the cells come right after the fast locals // parameters are not counted here, since they remain at the start // of the locals, even if they are cell vars if (id->kind == ID_INFO_KIND_CELL && !(id->flags & ID_FLAG_IS_PARAM)) { id->local_num = scope->num_locals; scope->num_locals += 1; } } // compute the index of free vars // make sure they are in the order of the parent scope if (scope->parent != NULL) { int num_free = 0; for (int i = 0; i < scope->parent->id_info_len; i++) { id_info_t *id = &scope->parent->id_info[i]; if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) { for (int j = 0; j < scope->id_info_len; j++) { id_info_t *id2 = &scope->id_info[j]; if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) { assert(!(id2->flags & ID_FLAG_IS_PARAM)); // free vars should not be params // in MicroPython the frees come first, before the params id2->local_num = num_free; num_free += 1; } } } } // in MicroPython shift all other locals after the free locals if (num_free > 0) { for (int i = 0; i < scope->id_info_len; i++) { id_info_t *id = &scope->id_info[i]; if (id->kind != ID_INFO_KIND_FREE || (id->flags & ID_FLAG_IS_PARAM)) { id->local_num += num_free; } } scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function scope->num_locals += num_free; } } } #if !MICROPY_PERSISTENT_CODE_SAVE STATIC #endif mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) { // put compiler state on the stack, it's relatively small compiler_t comp_state = {0}; compiler_t *comp = &comp_state; comp->source_file = source_file; comp->is_repl = is_repl; comp->break_label = INVALID_LABEL; comp->continue_label = INVALID_LABEL; // create the module scope #if MICROPY_EMIT_NATIVE const uint emit_opt = MP_STATE_VM(default_emit_opt); #else const uint emit_opt = MP_EMIT_OPT_NONE; #endif scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, parse_tree->root, emit_opt); // create standard emitter; it's used at least for MP_PASS_SCOPE emit_t *emit_bc = emit_bc_new(); // compile pass 1 comp->emit = emit_bc; #if MICROPY_EMIT_NATIVE comp->emit_method_table = &emit_bc_method_table; #endif uint max_num_labels = 0; for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) { #if MICROPY_EMIT_INLINE_ASM if (s->emit_options == MP_EMIT_OPT_ASM) { compile_scope_inline_asm(comp, s, MP_PASS_SCOPE); } else #endif { compile_scope(comp, s, MP_PASS_SCOPE); // Check if any implicitly declared variables should be closed over for (size_t i = 0; i < s->id_info_len; ++i) { id_info_t *id = &s->id_info[i]; if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { scope_check_to_close_over(s, id); } } } // update maximim number of labels needed if (comp->next_label > max_num_labels) { max_num_labels = comp->next_label; } } // compute some things related to scope and identifiers for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) { scope_compute_things(s); } // set max number of labels now that it's calculated emit_bc_set_max_num_labels(emit_bc, max_num_labels); // compile pass 2 and 3 #if MICROPY_EMIT_NATIVE emit_t *emit_native = NULL; #endif for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) { #if MICROPY_EMIT_INLINE_ASM if (s->emit_options == MP_EMIT_OPT_ASM) { // inline assembly if (comp->emit_inline_asm == NULL) { comp->emit_inline_asm = ASM_EMITTER(new)(max_num_labels); } comp->emit = NULL; comp->emit_inline_asm_method_table = ASM_EMITTER_TABLE; compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE); #if MICROPY_EMIT_INLINE_XTENSA // Xtensa requires an extra pass to compute size of l32r const table // TODO this can be improved by calculating it during SCOPE pass // but that requires some other structural changes to the asm emitters #if MICROPY_DYNAMIC_COMPILER if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_XTENSA) #endif { compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE); } #endif if (comp->compile_error == MP_OBJ_NULL) { compile_scope_inline_asm(comp, s, MP_PASS_EMIT); } } else #endif { // choose the emit type switch (s->emit_options) { #if MICROPY_EMIT_NATIVE case MP_EMIT_OPT_NATIVE_PYTHON: case MP_EMIT_OPT_VIPER: if (emit_native == NULL) { emit_native = NATIVE_EMITTER(new)(&comp->compile_error, &comp->next_label, max_num_labels); } comp->emit_method_table = NATIVE_EMITTER_TABLE; comp->emit = emit_native; break; #endif // MICROPY_EMIT_NATIVE default: comp->emit = emit_bc; #if MICROPY_EMIT_NATIVE comp->emit_method_table = &emit_bc_method_table; #endif break; } // need a pass to compute stack size compile_scope(comp, s, MP_PASS_STACK_SIZE); // second last pass: compute code size if (comp->compile_error == MP_OBJ_NULL) { compile_scope(comp, s, MP_PASS_CODE_SIZE); } // final pass: emit code if (comp->compile_error == MP_OBJ_NULL) { compile_scope(comp, s, MP_PASS_EMIT); } } } if (comp->compile_error != MP_OBJ_NULL) { // if there is no line number for the error then use the line // number for the start of this scope compile_error_set_line(comp, comp->scope_cur->pn); // add a traceback to the exception using relevant source info mp_obj_exception_add_traceback(comp->compile_error, comp->source_file, comp->compile_error_line, comp->scope_cur->simple_name); } // free the emitters emit_bc_free(emit_bc); #if MICROPY_EMIT_NATIVE if (emit_native != NULL) { NATIVE_EMITTER(free)(emit_native); } #endif #if MICROPY_EMIT_INLINE_ASM if (comp->emit_inline_asm != NULL) { ASM_EMITTER(free)(comp->emit_inline_asm); } #endif // free the parse tree mp_parse_tree_clear(parse_tree); // free the scopes mp_raw_code_t *outer_raw_code = module_scope->raw_code; for (scope_t *s = module_scope; s;) { scope_t *next = s->next; scope_free(s); s = next; } if (comp->compile_error != MP_OBJ_NULL) { nlr_raise(comp->compile_error); } else { return outer_raw_code; } } mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) { mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, is_repl); // return function that executes the outer module return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL); } #endif // MICROPY_ENABLE_COMPILER micropython-1.12/py/compile.h000066400000000000000000000037001357706137100162530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_COMPILE_H #define MICROPY_INCLUDED_PY_COMPILE_H #include "py/lexer.h" #include "py/parse.h" #include "py/emitglue.h" // the compiler will raise an exception if an error occurred // the compiler will clear the parse tree before it returns mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl); #if MICROPY_PERSISTENT_CODE_SAVE // this has the same semantics as mp_compile mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl); #endif // this is implemented in runtime.c mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals); #endif // MICROPY_INCLUDED_PY_COMPILE_H micropython-1.12/py/dynruntime.h000066400000000000000000000243141357706137100170250ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_DYNRUNTIME_H #define MICROPY_INCLUDED_PY_DYNRUNTIME_H // This header file contains definitions to dynamically implement the static // MicroPython runtime API defined in py/obj.h and py/runtime.h. #include "py/nativeglue.h" #include "py/objstr.h" #undef MP_ROM_QSTR #undef MP_OBJ_QSTR_VALUE #undef MP_OBJ_NEW_QSTR #undef mp_const_none #undef mp_const_false #undef mp_const_true #undef mp_const_empty_tuple #undef nlr_raise /******************************************************************************/ // Memory allocation #define m_malloc(n) (m_malloc_dyn((n))) #define m_free(ptr) (m_free_dyn((ptr))) #define m_realloc(ptr, new_num_bytes) (m_realloc_dyn((ptr), (new_num_bytes))) static inline void *m_malloc_dyn(size_t n) { // TODO won't raise on OOM return mp_fun_table.realloc_(NULL, n, false); } static inline void m_free_dyn(void *ptr) { mp_fun_table.realloc_(ptr, 0, false); } static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { // TODO won't raise on OOM return mp_fun_table.realloc_(ptr, new_num_bytes, true); } /******************************************************************************/ // Printing #define mp_plat_print (*mp_fun_table.plat_print) #define mp_printf(p, ...) (mp_fun_table.printf_((p), __VA_ARGS__)) #define mp_vprintf(p, fmt, args) (mp_fun_table.vprintf_((p), (fmt), (args))) /******************************************************************************/ // Types and objects #define MP_OBJ_NEW_QSTR(x) MP_OBJ_NEW_QSTR_ ## x #define mp_type_type (*mp_fun_table.type_type) #define mp_type_str (*mp_fun_table.type_str) #define mp_type_list (*mp_fun_table.type_list) #define mp_type_EOFError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_EOFError))) #define mp_type_IndexError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_IndexError))) #define mp_type_KeyError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_KeyError))) #define mp_type_NotImplementedError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_NotImplementedError))) #define mp_type_RuntimeError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_RuntimeError))) #define mp_type_TypeError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_TypeError))) #define mp_type_ValueError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_ValueError))) #define mp_stream_read_obj (*mp_fun_table.stream_read_obj) #define mp_stream_readinto_obj (*mp_fun_table.stream_readinto_obj) #define mp_stream_unbuffered_readline_obj (*mp_fun_table.stream_unbuffered_readline_obj) #define mp_stream_write_obj (*mp_fun_table.stream_write_obj) #define mp_const_none ((mp_obj_t)mp_fun_table.const_none) #define mp_const_false ((mp_obj_t)mp_fun_table.const_false) #define mp_const_true ((mp_obj_t)mp_fun_table.const_true) #define mp_const_empty_tuple (mp_fun_table.new_tuple(0, NULL)) #define mp_obj_new_bool(b) ((b) ? (mp_obj_t)mp_fun_table.const_true : (mp_obj_t)mp_fun_table.const_false) #define mp_obj_new_int(i) (mp_fun_table.native_to_obj(i, MP_NATIVE_TYPE_INT)) #define mp_obj_new_int_from_uint(i) (mp_fun_table.native_to_obj(i, MP_NATIVE_TYPE_UINT)) #define mp_obj_new_str(data, len) (mp_fun_table.obj_new_str((data), (len))) #define mp_obj_new_str_of_type(t, d, l) (mp_obj_new_str_of_type_dyn((t), (d), (l))) #define mp_obj_new_bytes(data, len) (mp_fun_table.obj_new_bytes((data), (len))) #define mp_obj_new_bytearray_by_ref(n, i) (mp_fun_table.obj_new_bytearray_by_ref((n), (i))) #define mp_obj_new_tuple(n, items) (mp_fun_table.new_tuple((n), (items))) #define mp_obj_new_list(n, items) (mp_fun_table.new_list((n), (items))) #define mp_obj_get_type(o) (mp_fun_table.obj_get_type((o))) #define mp_obj_get_int(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_INT)) #define mp_obj_get_int_truncated(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_UINT)) #define mp_obj_str_get_str(s) ((void*)mp_fun_table.native_from_obj(s, MP_NATIVE_TYPE_PTR)) #define mp_obj_str_get_data(o, len) (mp_obj_str_get_data_dyn((o), (len))) #define mp_get_buffer_raise(o, bufinfo, fl) (mp_fun_table.get_buffer_raise((o), (bufinfo), (fl))) #define mp_get_stream_raise(s, flags) (mp_fun_table.get_stream_raise((s), (flags))) #define mp_obj_len(o) (mp_obj_len_dyn(o)) #define mp_obj_subscr(base, index, val) (mp_fun_table.obj_subscr((base), (index), (val))) #define mp_obj_list_append(list, item) (mp_fun_table.list_append((list), (item))) static inline mp_obj_t mp_obj_new_str_of_type_dyn(const mp_obj_type_t *type, const byte* data, size_t len) { if (type == &mp_type_str) { return mp_obj_new_str((const char*)data, len); } else { return mp_obj_new_bytes(data, len); } } static inline void *mp_obj_str_get_data_dyn(mp_obj_t o, size_t *l) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(o, &bufinfo, MP_BUFFER_READ); *l = bufinfo.len; return bufinfo.buf; } static inline mp_obj_t mp_obj_len_dyn(mp_obj_t o) { // If bytes implemented MP_UNARY_OP_LEN could use: mp_unary_op(MP_UNARY_OP_LEN, o) return mp_fun_table.call_function_n_kw(mp_fun_table.load_name(MP_QSTR_len), 1, &o); } /******************************************************************************/ // General runtime functions #define mp_load_name(qst) (mp_fun_table.load_name(qst)) #define mp_load_global(qst) (mp_fun_table.load_global(qst)) #define mp_store_global(qst, obj) (mp_fun_table.store_global((qst), (obj))) #define mp_unary_op(op, obj) (mp_fun_table.unary_op((op), (obj))) #define mp_binary_op(op, lhs, rhs) (mp_fun_table.binary_op((op), (lhs), (rhs))) #define mp_make_function_from_raw_code(rc, def_args, def_kw_args) \ (mp_fun_table.make_function_from_raw_code((rc), (def_args), (def_kw_args))) #define mp_call_function_n_kw(fun, n_args, n_kw, args) \ (mp_fun_table.call_function_n_kw((fun), (n_args) | ((n_kw) << 8), args)) #define mp_arg_check_num(n_args, n_kw, n_args_min, n_args_max, takes_kw) \ (mp_fun_table.arg_check_num_sig((n_args), (n_kw), MP_OBJ_FUN_MAKE_SIG((n_args_min), (n_args_max), (takes_kw)))) #define MP_DYNRUNTIME_INIT_ENTRY \ mp_obj_t old_globals = mp_fun_table.swap_globals(self->globals); \ mp_raw_code_t rc; \ rc.kind = MP_CODE_NATIVE_VIPER; \ rc.scope_flags = 0; \ rc.const_table = (void*)self->const_table; \ (void)rc; #define MP_DYNRUNTIME_INIT_EXIT \ mp_fun_table.swap_globals(old_globals); \ return mp_const_none; #define MP_DYNRUNTIME_MAKE_FUNCTION(f) \ (mp_make_function_from_raw_code((rc.fun_data = (f), &rc), MP_OBJ_NULL, MP_OBJ_NULL)) /******************************************************************************/ // Exceptions #define mp_obj_new_exception(o) ((mp_obj_t)(o)) // Assumes returned object will be raised, will create instance then #define mp_obj_new_exception_arg1(e_type, arg) (mp_obj_new_exception_arg1_dyn((e_type), (arg))) #define nlr_raise(o) (mp_raise_dyn(o)) #define mp_raise_msg(type, msg) (mp_fun_table.raise_msg((type), (msg))) #define mp_raise_OSError(er) (mp_raise_OSError_dyn(er)) #define mp_raise_NotImplementedError(msg) (mp_raise_msg(&mp_type_NotImplementedError, (msg))) #define mp_raise_TypeError(msg) (mp_raise_msg(&mp_type_TypeError, (msg))) #define mp_raise_ValueError(msg) (mp_raise_msg(&mp_type_ValueError, (msg))) static inline mp_obj_t mp_obj_new_exception_arg1_dyn(const mp_obj_type_t *exc_type, mp_obj_t arg) { mp_obj_t args[1] = { arg }; return mp_call_function_n_kw(MP_OBJ_FROM_PTR(exc_type), 1, 0, &args[0]); } static NORETURN inline void mp_raise_dyn(mp_obj_t o) { mp_fun_table.raise(o); for (;;) { } } static inline void mp_raise_OSError_dyn(int er) { mp_obj_t args[1] = { MP_OBJ_NEW_SMALL_INT(er) }; nlr_raise(mp_call_function_n_kw(mp_load_global(MP_QSTR_OSError), 1, 0, &args[0])); } /******************************************************************************/ // Floating point #define mp_obj_new_float_from_f(f) (mp_fun_table.obj_new_float_from_f((f))) #define mp_obj_new_float_from_d(d) (mp_fun_table.obj_new_float_from_d((d))) #define mp_obj_get_float_to_f(o) (mp_fun_table.obj_get_float_to_f((o))) #define mp_obj_get_float_to_d(o) (mp_fun_table.obj_get_float_to_d((o))) #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #define mp_obj_new_float(f) (mp_obj_new_float_from_f((f))) #define mp_obj_get_float(o) (mp_obj_get_float_to_f((o))) #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #define mp_obj_new_float(f) (mp_obj_new_float_from_d((f))) #define mp_obj_get_float(o) (mp_obj_get_float_to_d((o))) #endif #endif // MICROPY_INCLUDED_PY_DYNRUNTIME_H micropython-1.12/py/dynruntime.mk000066400000000000000000000065341357706137100172110ustar00rootroot00000000000000# Makefile fragment for generating native .mpy files from C source # MPY_DIR must be set to the top of the MicroPython source tree BUILD ?= build ECHO = @echo RM = /bin/rm MKDIR = /bin/mkdir PYTHON = python3 MPY_CROSS = $(MPY_DIR)/mpy-cross/mpy-cross MPY_TOOL = $(PYTHON) $(MPY_DIR)/tools/mpy-tool.py MPY_LD = $(PYTHON) $(MPY_DIR)/tools/mpy_ld.py Q = @ ifeq ("$(origin V)", "command line") ifeq ($(V),1) Q = MPY_LD += '-vvv' endif endif ARCH_UPPER = $(shell echo $(ARCH) | tr '[:lower:]' '[:upper:]') CONFIG_H = $(BUILD)/$(MOD).config.h CFLAGS += -I. -I$(MPY_DIR) CFLAGS += -std=c99 CFLAGS += -Os CFLAGS += -Wall -Werror -DNDEBUG CFLAGS += -DNO_QSTR CFLAGS += -DMP_CONFIGFILE='<$(CONFIG_H)>' CFLAGS += -fpic -fno-common CFLAGS += -U _FORTIFY_SOURCE # prevent use of __*_chk libc functions #CFLAGS += -fdata-sections -ffunction-sections MPY_CROSS_FLAGS += -march=$(ARCH) SRC_O += $(addprefix $(BUILD)/, $(patsubst %.c,%.o,$(filter %.c,$(SRC)))) SRC_MPY += $(addprefix $(BUILD)/, $(patsubst %.py,%.mpy,$(filter %.py,$(SRC)))) ################################################################################ # Architecture configuration ifeq ($(ARCH),x86) # x86 CROSS = CFLAGS += -m32 -fno-stack-protector MPY_CROSS_FLAGS += -mcache-lookup-bc MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),x64) # x64 CROSS = CFLAGS += -fno-stack-protector MPY_CROSS_FLAGS += -mcache-lookup-bc MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),armv7m) # thumb CROSS = arm-none-eabi- CFLAGS += -mthumb -mcpu=cortex-m3 MICROPY_FLOAT_IMPL ?= none else ifeq ($(ARCH),armv7emsp) # thumb CROSS = arm-none-eabi- CFLAGS += -mthumb -mcpu=cortex-m4 CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard MICROPY_FLOAT_IMPL ?= float else ifeq ($(ARCH),armv7emdp) # thumb CROSS = arm-none-eabi- CFLAGS += -mthumb -mcpu=cortex-m7 CFLAGS += -mfpu=fpv5-d16 -mfloat-abi=hard MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),xtensa) # xtensa CROSS = xtensa-lx106-elf- CFLAGS += -mforce-l32 MICROPY_FLOAT_IMPL ?= none else ifeq ($(ARCH),xtensawin) # xtensawin CROSS = xtensa-esp32-elf- CFLAGS += MICROPY_FLOAT_IMPL ?= float else $(error architecture '$(ARCH)' not supported) endif MICROPY_FLOAT_IMPL_UPPER = $(shell echo $(MICROPY_FLOAT_IMPL) | tr '[:lower:]' '[:upper:]') CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_$(MICROPY_FLOAT_IMPL_UPPER) CFLAGS += $(CFLAGS_EXTRA) ################################################################################ # Build rules .PHONY: all clean all: $(MOD).mpy clean: $(RM) -rf $(BUILD) $(CLEAN_EXTRA) # Create build destination directories first BUILD_DIRS = $(sort $(dir $(CONFIG_H) $(SRC_O) $(SRC_MPY))) $(CONFIG_H) $(SRC_O) $(SRC_MPY): | $(BUILD_DIRS) $(BUILD_DIRS): $(Q)$(MKDIR) -p $@ # Preprocess all source files to generate $(CONFIG_H) $(CONFIG_H): $(SRC) $(ECHO) "GEN $@" $(Q)$(MPY_LD) --arch $(ARCH) --preprocess -o $@ $^ # Build .o from .c source files $(BUILD)/%.o: %.c $(CONFIG_H) Makefile $(ECHO) "CC $<" $(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $< # Build .mpy from .py source files $(BUILD)/%.mpy: %.py $(ECHO) "MPY $<" $(Q)$(MPY_CROSS) $(MPY_CROSS_FLAGS) -o $@ $< # Build native .mpy from object files $(BUILD)/$(MOD).native.mpy: $(SRC_O) $(ECHO) "LINK $<" $(Q)$(MPY_LD) --arch $(ARCH) --qstrs $(CONFIG_H) -o $@ $^ # Build final .mpy from all intermediate .mpy files $(MOD).mpy: $(BUILD)/$(MOD).native.mpy $(SRC_MPY) $(ECHO) "GEN $@" $(Q)$(MPY_TOOL) --merge -o $@ $^ micropython-1.12/py/emit.h000066400000000000000000000324531357706137100155700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_EMIT_H #define MICROPY_INCLUDED_PY_EMIT_H #include "py/lexer.h" #include "py/scope.h" /* Notes on passes: * We don't know exactly the opcodes in pass 1 because they depend on the * closing over of variables (LOAD_CLOSURE, BUILD_TUPLE, MAKE_CLOSURE), which * depends on determining the scope of variables in each function, and this * is not known until the end of pass 1. * As a consequence, we don't know the maximum stack size until the end of pass 2. * This is problematic for some emitters (x64) since they need to know the maximum * stack size to compile the entry to the function, and this affects code size. */ typedef enum { MP_PASS_SCOPE = 1, // work out id's and their kind, and number of labels MP_PASS_STACK_SIZE = 2, // work out maximum stack size MP_PASS_CODE_SIZE = 3, // work out code size and label offsets MP_PASS_EMIT = 4, // emit code } pass_kind_t; #define MP_EMIT_STAR_FLAG_SINGLE (0x01) #define MP_EMIT_STAR_FLAG_DOUBLE (0x02) #define MP_EMIT_BREAK_FROM_FOR (0x8000) // Kind for emit_id_ops->local() #define MP_EMIT_IDOP_LOCAL_FAST (0) #define MP_EMIT_IDOP_LOCAL_DEREF (1) // Kind for emit_id_ops->global() #define MP_EMIT_IDOP_GLOBAL_NAME (0) #define MP_EMIT_IDOP_GLOBAL_GLOBAL (1) // Kind for emit->import() #define MP_EMIT_IMPORT_NAME (0) #define MP_EMIT_IMPORT_FROM (1) #define MP_EMIT_IMPORT_STAR (2) // Kind for emit->subscr() #define MP_EMIT_SUBSCR_LOAD (0) #define MP_EMIT_SUBSCR_STORE (1) #define MP_EMIT_SUBSCR_DELETE (2) // Kind for emit->attr() #define MP_EMIT_ATTR_LOAD (0) #define MP_EMIT_ATTR_STORE (1) #define MP_EMIT_ATTR_DELETE (2) // Kind for emit->setup_block() #define MP_EMIT_SETUP_BLOCK_WITH (0) #define MP_EMIT_SETUP_BLOCK_EXCEPT (1) #define MP_EMIT_SETUP_BLOCK_FINALLY (2) // Kind for emit->build() #define MP_EMIT_BUILD_TUPLE (0) #define MP_EMIT_BUILD_LIST (1) #define MP_EMIT_BUILD_MAP (2) #define MP_EMIT_BUILD_SET (3) #define MP_EMIT_BUILD_SLICE (4) // Kind for emit->yield() #define MP_EMIT_YIELD_VALUE (0) #define MP_EMIT_YIELD_FROM (1) typedef struct _emit_t emit_t; typedef struct _mp_emit_method_table_id_ops_t { void (*local)(emit_t *emit, qstr qst, mp_uint_t local_num, int kind); void (*global)(emit_t *emit, qstr qst, int kind); } mp_emit_method_table_id_ops_t; typedef struct _emit_method_table_t { #if MICROPY_DYNAMIC_COMPILER emit_t *(*emit_new)(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); void (*emit_free)(emit_t *emit); #endif void (*start_pass)(emit_t *emit, pass_kind_t pass, scope_t *scope); void (*end_pass)(emit_t *emit); bool (*last_emit_was_return_value)(emit_t *emit); void (*adjust_stack_size)(emit_t *emit, mp_int_t delta); void (*set_source_line)(emit_t *emit, mp_uint_t line); mp_emit_method_table_id_ops_t load_id; mp_emit_method_table_id_ops_t store_id; mp_emit_method_table_id_ops_t delete_id; void (*label_assign)(emit_t *emit, mp_uint_t l); void (*import)(emit_t *emit, qstr qst, int kind); void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok); void (*load_const_small_int)(emit_t *emit, mp_int_t arg); void (*load_const_str)(emit_t *emit, qstr qst); void (*load_const_obj)(emit_t *emit, mp_obj_t obj); void (*load_null)(emit_t *emit); void (*load_method)(emit_t *emit, qstr qst, bool is_super); void (*load_build_class)(emit_t *emit); void (*subscr)(emit_t *emit, int kind); void (*attr)(emit_t *emit, qstr qst, int kind); void (*dup_top)(emit_t *emit); void (*dup_top_two)(emit_t *emit); void (*pop_top)(emit_t *emit); void (*rot_two)(emit_t *emit); void (*rot_three)(emit_t *emit); void (*jump)(emit_t *emit, mp_uint_t label); void (*pop_jump_if)(emit_t *emit, bool cond, mp_uint_t label); void (*jump_if_or_pop)(emit_t *emit, bool cond, mp_uint_t label); void (*unwind_jump)(emit_t *emit, mp_uint_t label, mp_uint_t except_depth); void (*setup_block)(emit_t *emit, mp_uint_t label, int kind); void (*with_cleanup)(emit_t *emit, mp_uint_t label); void (*end_finally)(emit_t *emit); void (*get_iter)(emit_t *emit, bool use_stack); void (*for_iter)(emit_t *emit, mp_uint_t label); void (*for_iter_end)(emit_t *emit); void (*pop_except_jump)(emit_t *emit, mp_uint_t label, bool within_exc_handler); void (*unary_op)(emit_t *emit, mp_unary_op_t op); void (*binary_op)(emit_t *emit, mp_binary_op_t op); void (*build)(emit_t *emit, mp_uint_t n_args, int kind); void (*store_map)(emit_t *emit); void (*store_comp)(emit_t *emit, scope_kind_t kind, mp_uint_t set_stack_index); void (*unpack_sequence)(emit_t *emit, mp_uint_t n_args); void (*unpack_ex)(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right); void (*make_function)(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); void (*make_closure)(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); void (*call_function)(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags); void (*call_method)(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags); void (*return_value)(emit_t *emit); void (*raise_varargs)(emit_t *emit, mp_uint_t n_args); void (*yield)(emit_t *emit, int kind); // these methods are used to control entry to/exit from an exception handler // they may or may not emit code void (*start_except_handler)(emit_t *emit); void (*end_except_handler)(emit_t *emit); } emit_method_table_t; static inline void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) { scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT); } void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst); void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst); extern const emit_method_table_t emit_bc_method_table; extern const emit_method_table_t emit_native_x64_method_table; extern const emit_method_table_t emit_native_x86_method_table; extern const emit_method_table_t emit_native_thumb_method_table; extern const emit_method_table_t emit_native_arm_method_table; extern const emit_method_table_t emit_native_xtensa_method_table; extern const emit_method_table_t emit_native_xtensawin_method_table; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops; emit_t *emit_bc_new(void); emit_t *emit_native_x64_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_x86_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_thumb_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_arm_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_xtensa_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_xtensawin_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); void emit_bc_set_max_num_labels(emit_t* emit, mp_uint_t max_num_labels); void emit_bc_free(emit_t *emit); void emit_native_x64_free(emit_t *emit); void emit_native_x86_free(emit_t *emit); void emit_native_thumb_free(emit_t *emit); void emit_native_arm_free(emit_t *emit); void emit_native_xtensa_free(emit_t *emit); void emit_native_xtensawin_free(emit_t *emit); void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope); void mp_emit_bc_end_pass(emit_t *emit); bool mp_emit_bc_last_emit_was_return_value(emit_t *emit); void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta); void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t line); void mp_emit_bc_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind); void mp_emit_bc_load_global(emit_t *emit, qstr qst, int kind); void mp_emit_bc_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind); void mp_emit_bc_store_global(emit_t *emit, qstr qst, int kind); void mp_emit_bc_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind); void mp_emit_bc_delete_global(emit_t *emit, qstr qst, int kind); void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l); void mp_emit_bc_import(emit_t *emit, qstr qst, int kind); void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok); void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg); void mp_emit_bc_load_const_str(emit_t *emit, qstr qst); void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj); void mp_emit_bc_load_null(emit_t *emit); void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super); void mp_emit_bc_load_build_class(emit_t *emit); void mp_emit_bc_subscr(emit_t *emit, int kind); void mp_emit_bc_attr(emit_t *emit, qstr qst, int kind); void mp_emit_bc_dup_top(emit_t *emit); void mp_emit_bc_dup_top_two(emit_t *emit); void mp_emit_bc_pop_top(emit_t *emit); void mp_emit_bc_rot_two(emit_t *emit); void mp_emit_bc_rot_three(emit_t *emit); void mp_emit_bc_jump(emit_t *emit, mp_uint_t label); void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label); void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label); void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth); void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind); void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label); void mp_emit_bc_end_finally(emit_t *emit); void mp_emit_bc_get_iter(emit_t *emit, bool use_stack); void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label); void mp_emit_bc_for_iter_end(emit_t *emit); void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler); void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op); void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op); void mp_emit_bc_build(emit_t *emit, mp_uint_t n_args, int kind); void mp_emit_bc_store_map(emit_t *emit); void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t list_stack_index); void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right); void mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); void mp_emit_bc_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); void mp_emit_bc_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags); void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags); void mp_emit_bc_return_value(emit_t *emit); void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_yield(emit_t *emit, int kind); void mp_emit_bc_start_except_handler(emit_t *emit); void mp_emit_bc_end_except_handler(emit_t *emit); typedef struct _emit_inline_asm_t emit_inline_asm_t; typedef struct _emit_inline_asm_method_table_t { #if MICROPY_DYNAMIC_COMPILER emit_inline_asm_t *(*asm_new)(mp_uint_t max_num_labels); void (*asm_free)(emit_inline_asm_t *emit); #endif void (*start_pass)(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot); void (*end_pass)(emit_inline_asm_t *emit, mp_uint_t type_sig); mp_uint_t (*count_params)(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params); bool (*label)(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id); void (*op)(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args); } emit_inline_asm_method_table_t; extern const emit_inline_asm_method_table_t emit_inline_thumb_method_table; extern const emit_inline_asm_method_table_t emit_inline_xtensa_method_table; emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels); emit_inline_asm_t *emit_inline_xtensa_new(mp_uint_t max_num_labels); void emit_inline_thumb_free(emit_inline_asm_t *emit); void emit_inline_xtensa_free(emit_inline_asm_t *emit); #if MICROPY_WARNINGS void mp_emitter_warning(pass_kind_t pass, const char *msg); #else #define mp_emitter_warning(pass, msg) #endif #endif // MICROPY_INCLUDED_PY_EMIT_H micropython-1.12/py/emitbc.c000066400000000000000000001053571357706137100160740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/mpstate.h" #include "py/emit.h" #include "py/bc0.h" #if MICROPY_ENABLE_COMPILER #define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7) #define DUMMY_DATA_SIZE (BYTES_FOR_INT) struct _emit_t { // Accessed as mp_obj_t, so must be aligned as such, and we rely on the // memory allocator returning a suitably aligned pointer. // Should work for cases when mp_obj_t is 64-bit on a 32-bit machine. byte dummy_data[DUMMY_DATA_SIZE]; pass_kind_t pass : 8; mp_uint_t last_emit_was_return_value : 8; int stack_size; scope_t *scope; mp_uint_t last_source_line_offset; mp_uint_t last_source_line; mp_uint_t max_num_labels; mp_uint_t *label_offsets; size_t code_info_offset; size_t code_info_size; size_t bytecode_offset; size_t bytecode_size; byte *code_base; // stores both byte code and code info size_t n_info; size_t n_cell; #if MICROPY_PERSISTENT_CODE uint16_t ct_cur_obj; uint16_t ct_num_obj; uint16_t ct_cur_raw_code; #endif mp_uint_t *const_table; }; emit_t *emit_bc_new(void) { emit_t *emit = m_new0(emit_t, 1); return emit; } void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels) { emit->max_num_labels = max_num_labels; emit->label_offsets = m_new(mp_uint_t, emit->max_num_labels); } void emit_bc_free(emit_t *emit) { m_del(mp_uint_t, emit->label_offsets, emit->max_num_labels); m_del_obj(emit_t, emit); } typedef byte *(*emit_allocator_t)(emit_t *emit, int nbytes); STATIC void emit_write_uint(emit_t *emit, emit_allocator_t allocator, mp_uint_t val) { // We store each 7 bits in a separate byte, and that's how many bytes needed byte buf[BYTES_FOR_INT]; byte *p = buf + sizeof(buf); // We encode in little-ending order, but store in big-endian, to help decoding do { *--p = val & 0x7f; val >>= 7; } while (val != 0); byte *c = allocator(emit, buf + sizeof(buf) - p); while (p != buf + sizeof(buf) - 1) { *c++ = *p++ | 0x80; } *c = *p; } // all functions must go through this one to emit code info STATIC byte *emit_get_cur_to_write_code_info(emit_t *emit, int num_bytes_to_write) { //printf("emit %d\n", num_bytes_to_write); if (emit->pass < MP_PASS_EMIT) { emit->code_info_offset += num_bytes_to_write; return emit->dummy_data; } else { assert(emit->code_info_offset + num_bytes_to_write <= emit->code_info_size); byte *c = emit->code_base + emit->code_info_offset; emit->code_info_offset += num_bytes_to_write; return c; } } STATIC void emit_write_code_info_byte(emit_t* emit, byte val) { *emit_get_cur_to_write_code_info(emit, 1) = val; } STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) { #if MICROPY_PERSISTENT_CODE assert((qst >> 16) == 0); byte *c = emit_get_cur_to_write_code_info(emit, 2); c[0] = qst; c[1] = qst >> 8; #else emit_write_uint(emit, emit_get_cur_to_write_code_info, qst); #endif } #if MICROPY_ENABLE_SOURCE_LINE STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) { assert(bytes_to_skip > 0 || lines_to_skip > 0); //printf(" %d %d\n", bytes_to_skip, lines_to_skip); while (bytes_to_skip > 0 || lines_to_skip > 0) { mp_uint_t b, l; if (lines_to_skip <= 6 || bytes_to_skip > 0xf) { // use 0b0LLBBBBB encoding b = MIN(bytes_to_skip, 0x1f); if (b < bytes_to_skip) { // we can't skip any lines until we skip all the bytes l = 0; } else { l = MIN(lines_to_skip, 0x3); } *emit_get_cur_to_write_code_info(emit, 1) = b | (l << 5); } else { // use 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) b = MIN(bytes_to_skip, 0xf); l = MIN(lines_to_skip, 0x7ff); byte *ci = emit_get_cur_to_write_code_info(emit, 2); ci[0] = 0x80 | b | ((l >> 4) & 0x70); ci[1] = l; } bytes_to_skip -= b; lines_to_skip -= l; } } #endif // all functions must go through this one to emit byte code STATIC byte *emit_get_cur_to_write_bytecode(emit_t *emit, int num_bytes_to_write) { //printf("emit %d\n", num_bytes_to_write); if (emit->pass < MP_PASS_EMIT) { emit->bytecode_offset += num_bytes_to_write; return emit->dummy_data; } else { assert(emit->bytecode_offset + num_bytes_to_write <= emit->bytecode_size); byte *c = emit->code_base + emit->code_info_size + emit->bytecode_offset; emit->bytecode_offset += num_bytes_to_write; return c; } } STATIC void emit_write_bytecode_raw_byte(emit_t *emit, byte b1) { byte *c = emit_get_cur_to_write_bytecode(emit, 1); c[0] = b1; } STATIC void emit_write_bytecode_byte(emit_t *emit, int stack_adj, byte b1) { mp_emit_bc_adjust_stack_size(emit, stack_adj); byte *c = emit_get_cur_to_write_bytecode(emit, 1); c[0] = b1; } // Similar to emit_write_bytecode_uint(), just some extra handling to encode sign STATIC void emit_write_bytecode_byte_int(emit_t *emit, int stack_adj, byte b1, mp_int_t num) { emit_write_bytecode_byte(emit, stack_adj, b1); // We store each 7 bits in a separate byte, and that's how many bytes needed byte buf[BYTES_FOR_INT]; byte *p = buf + sizeof(buf); // We encode in little-ending order, but store in big-endian, to help decoding do { *--p = num & 0x7f; num >>= 7; } while (num != 0 && num != -1); // Make sure that highest bit we stored (mask 0x40) matches sign // of the number. If not, store extra byte just to encode sign if (num == -1 && (*p & 0x40) == 0) { *--p = 0x7f; } else if (num == 0 && (*p & 0x40) != 0) { *--p = 0; } byte *c = emit_get_cur_to_write_bytecode(emit, buf + sizeof(buf) - p); while (p != buf + sizeof(buf) - 1) { *c++ = *p++ | 0x80; } *c = *p; } STATIC void emit_write_bytecode_byte_uint(emit_t *emit, int stack_adj, byte b, mp_uint_t val) { emit_write_bytecode_byte(emit, stack_adj, b); emit_write_uint(emit, emit_get_cur_to_write_bytecode, val); } #if MICROPY_PERSISTENT_CODE STATIC void emit_write_bytecode_byte_const(emit_t *emit, int stack_adj, byte b, mp_uint_t n, mp_uint_t c) { if (emit->pass == MP_PASS_EMIT) { emit->const_table[n] = c; } emit_write_bytecode_byte_uint(emit, stack_adj, b, n); } #endif STATIC void emit_write_bytecode_byte_qstr(emit_t* emit, int stack_adj, byte b, qstr qst) { #if MICROPY_PERSISTENT_CODE assert((qst >> 16) == 0); mp_emit_bc_adjust_stack_size(emit, stack_adj); byte *c = emit_get_cur_to_write_bytecode(emit, 3); c[0] = b; c[1] = qst; c[2] = qst >> 8; #else emit_write_bytecode_byte_uint(emit, stack_adj, b, qst); #endif } STATIC void emit_write_bytecode_byte_obj(emit_t *emit, int stack_adj, byte b, mp_obj_t obj) { #if MICROPY_PERSISTENT_CODE emit_write_bytecode_byte_const(emit, stack_adj, b, emit->scope->num_pos_args + emit->scope->num_kwonly_args + emit->ct_cur_obj++, (mp_uint_t)obj); #else // aligns the pointer so it is friendly to GC emit_write_bytecode_byte(emit, stack_adj, b); emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(mp_obj_t)); mp_obj_t *c = (mp_obj_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_obj_t)); // Verify thar c is already uint-aligned assert(c == MP_ALIGN(c, sizeof(mp_obj_t))); *c = obj; #endif } STATIC void emit_write_bytecode_byte_raw_code(emit_t *emit, int stack_adj, byte b, mp_raw_code_t *rc) { #if MICROPY_PERSISTENT_CODE emit_write_bytecode_byte_const(emit, stack_adj, b, emit->scope->num_pos_args + emit->scope->num_kwonly_args + emit->ct_num_obj + emit->ct_cur_raw_code++, (mp_uint_t)(uintptr_t)rc); #else // aligns the pointer so it is friendly to GC emit_write_bytecode_byte(emit, stack_adj, b); emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(void*)); void **c = (void**)emit_get_cur_to_write_bytecode(emit, sizeof(void*)); // Verify thar c is already uint-aligned assert(c == MP_ALIGN(c, sizeof(void*))); *c = rc; #endif #if MICROPY_PY_SYS_SETTRACE rc->line_of_definition = emit->last_source_line; #endif } // unsigned labels are relative to ip following this instruction, stored as 16 bits STATIC void emit_write_bytecode_byte_unsigned_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { mp_emit_bc_adjust_stack_size(emit, stack_adj); mp_uint_t bytecode_offset; if (emit->pass < MP_PASS_EMIT) { bytecode_offset = 0; } else { bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 3; } byte *c = emit_get_cur_to_write_bytecode(emit, 3); c[0] = b1; c[1] = bytecode_offset; c[2] = bytecode_offset >> 8; } // signed labels are relative to ip following this instruction, stored as 16 bits, in excess STATIC void emit_write_bytecode_byte_signed_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { mp_emit_bc_adjust_stack_size(emit, stack_adj); int bytecode_offset; if (emit->pass < MP_PASS_EMIT) { bytecode_offset = 0; } else { bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 3 + 0x8000; } byte *c = emit_get_cur_to_write_bytecode(emit, 3); c[0] = b1; c[1] = bytecode_offset; c[2] = bytecode_offset >> 8; } void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->pass = pass; emit->stack_size = 0; emit->last_emit_was_return_value = false; emit->scope = scope; emit->last_source_line_offset = 0; emit->last_source_line = 1; #ifndef NDEBUG // With debugging enabled labels are checked for unique assignment if (pass < MP_PASS_EMIT && emit->label_offsets != NULL) { memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(mp_uint_t)); } #endif emit->bytecode_offset = 0; emit->code_info_offset = 0; // Write local state size, exception stack size, scope flags and number of arguments { mp_uint_t n_state = scope->num_locals + scope->stack_size; if (n_state == 0) { // Need at least 1 entry in the state, in the case an exception is // propagated through this function, the exception is returned in // the highest slot in the state (fastn[0], see vm.c). n_state = 1; } #if MICROPY_DEBUG_VM_STACK_OVERFLOW // An extra slot in the stack is needed to detect VM stack overflow n_state += 1; #endif size_t n_exc_stack = scope->exc_stack_size; MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, scope, emit_write_code_info_byte, emit); } // Write number of cells and size of the source code info if (pass >= MP_PASS_CODE_SIZE) { MP_BC_PRELUDE_SIZE_ENCODE(emit->n_info, emit->n_cell, emit_write_code_info_byte, emit); } emit->n_info = emit->code_info_offset; // Write the name and source file of this function. emit_write_code_info_qstr(emit, scope->simple_name); emit_write_code_info_qstr(emit, scope->source_file); #if MICROPY_PERSISTENT_CODE emit->ct_cur_obj = 0; emit->ct_cur_raw_code = 0; #endif if (pass == MP_PASS_EMIT) { // Write argument names (needed to resolve positional args passed as // keywords). We store them as full word-sized objects for efficient access // in mp_setup_code_state this is the start of the prelude and is guaranteed // to be aligned on a word boundary. // For a given argument position (indexed by i) we need to find the // corresponding id_info which is a parameter, as it has the correct // qstr name to use as the argument name. Note that it's not a simple // 1-1 mapping (ie i!=j in general) because of possible closed-over // variables. In the case that the argument i has no corresponding // parameter we use "*" as its name (since no argument can ever be named // "*"). We could use a blank qstr but "*" is better for debugging. // Note: there is some wasted RAM here for the case of storing a qstr // for each closed-over variable, and maybe there is a better way to do // it, but that would require changes to mp_setup_code_state. for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) { qstr qst = MP_QSTR__star_; for (int j = 0; j < scope->id_info_len; ++j) { id_info_t *id = &scope->id_info[j]; if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) { qst = id->qst; break; } } emit->const_table[i] = (mp_uint_t)MP_OBJ_NEW_QSTR(qst); } } } void mp_emit_bc_end_pass(emit_t *emit) { if (emit->pass == MP_PASS_SCOPE) { return; } // check stack is back to zero size assert(emit->stack_size == 0); emit_write_code_info_byte(emit, 0); // end of line number info // Calculate size of source code info section emit->n_info = emit->code_info_offset - emit->n_info; // Emit closure section of prelude emit->n_cell = 0; for (size_t i = 0; i < emit->scope->id_info_len; ++i) { id_info_t *id = &emit->scope->id_info[i]; if (id->kind == ID_INFO_KIND_CELL) { assert(id->local_num <= 255); emit_write_code_info_byte(emit, id->local_num); // write the local which should be converted to a cell ++emit->n_cell; } } #if MICROPY_PERSISTENT_CODE assert(emit->pass <= MP_PASS_STACK_SIZE || (emit->ct_num_obj == emit->ct_cur_obj)); emit->ct_num_obj = emit->ct_cur_obj; #endif if (emit->pass == MP_PASS_CODE_SIZE) { #if !MICROPY_PERSISTENT_CODE // so bytecode is aligned emit->code_info_offset = (size_t)MP_ALIGN(emit->code_info_offset, sizeof(mp_uint_t)); #endif // calculate size of total code-info + bytecode, in bytes emit->code_info_size = emit->code_info_offset; emit->bytecode_size = emit->bytecode_offset; emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size); #if MICROPY_PERSISTENT_CODE emit->const_table = m_new0(mp_uint_t, emit->scope->num_pos_args + emit->scope->num_kwonly_args + emit->ct_cur_obj + emit->ct_cur_raw_code); #else emit->const_table = m_new0(mp_uint_t, emit->scope->num_pos_args + emit->scope->num_kwonly_args); #endif } else if (emit->pass == MP_PASS_EMIT) { mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base, #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS emit->code_info_size + emit->bytecode_size, #endif emit->const_table, #if MICROPY_PERSISTENT_CODE_SAVE emit->ct_cur_obj, emit->ct_cur_raw_code, #endif emit->scope->scope_flags); } } bool mp_emit_bc_last_emit_was_return_value(emit_t *emit) { return emit->last_emit_was_return_value; } void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) { if (emit->pass == MP_PASS_SCOPE) { return; } assert((mp_int_t)emit->stack_size + delta >= 0); emit->stack_size += delta; if (emit->stack_size > emit->scope->stack_size) { emit->scope->stack_size = emit->stack_size; } emit->last_emit_was_return_value = false; } void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { //printf("source: line %d -> %d offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->bytecode_offset); #if MICROPY_ENABLE_SOURCE_LINE if (MP_STATE_VM(mp_optimise_value) >= 3) { // If we compile with -O3, don't store line numbers. return; } if (source_line > emit->last_source_line) { mp_uint_t bytes_to_skip = emit->bytecode_offset - emit->last_source_line_offset; mp_uint_t lines_to_skip = source_line - emit->last_source_line; emit_write_code_info_bytes_lines(emit, bytes_to_skip, lines_to_skip); emit->last_source_line_offset = emit->bytecode_offset; emit->last_source_line = source_line; } #else (void)emit; (void)source_line; #endif } void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) { mp_emit_bc_adjust_stack_size(emit, 0); if (emit->pass == MP_PASS_SCOPE) { return; } assert(l < emit->max_num_labels); if (emit->pass < MP_PASS_EMIT) { // assign label offset assert(emit->label_offsets[l] == (mp_uint_t)-1); emit->label_offsets[l] = emit->bytecode_offset; } else { // ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT assert(emit->label_offsets[l] == emit->bytecode_offset); } } void mp_emit_bc_import(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_BC_IMPORT_NAME + MP_EMIT_IMPORT_NAME == MP_BC_IMPORT_NAME); MP_STATIC_ASSERT(MP_BC_IMPORT_NAME + MP_EMIT_IMPORT_FROM == MP_BC_IMPORT_FROM); int stack_adj = kind == MP_EMIT_IMPORT_FROM ? 1 : -1; if (kind == MP_EMIT_IMPORT_STAR) { emit_write_bytecode_byte(emit, stack_adj, MP_BC_IMPORT_STAR); } else { emit_write_bytecode_byte_qstr(emit, stack_adj, MP_BC_IMPORT_NAME + kind, qst); } } void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) { MP_STATIC_ASSERT(MP_BC_LOAD_CONST_FALSE + (MP_TOKEN_KW_NONE - MP_TOKEN_KW_FALSE) == MP_BC_LOAD_CONST_NONE); MP_STATIC_ASSERT(MP_BC_LOAD_CONST_FALSE + (MP_TOKEN_KW_TRUE - MP_TOKEN_KW_FALSE) == MP_BC_LOAD_CONST_TRUE); if (tok == MP_TOKEN_ELLIPSIS) { emit_write_bytecode_byte_obj(emit, 1, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); } else { emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_CONST_FALSE + (tok - MP_TOKEN_KW_FALSE)); } } void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) { if (-MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS <= arg && arg < MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS) { emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_CONST_SMALL_INT_MULTI + MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS + arg); } else { emit_write_bytecode_byte_int(emit, 1, MP_BC_LOAD_CONST_SMALL_INT, arg); } } void mp_emit_bc_load_const_str(emit_t *emit, qstr qst) { emit_write_bytecode_byte_qstr(emit, 1, MP_BC_LOAD_CONST_STRING, qst); } void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj) { emit_write_bytecode_byte_obj(emit, 1, MP_BC_LOAD_CONST_OBJ, obj); } void mp_emit_bc_load_null(emit_t *emit) { emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_NULL); } void mp_emit_bc_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { MP_STATIC_ASSERT(MP_BC_LOAD_FAST_N + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_LOAD_FAST_N); MP_STATIC_ASSERT(MP_BC_LOAD_FAST_N + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_LOAD_DEREF); (void)qst; if (kind == MP_EMIT_IDOP_LOCAL_FAST && local_num <= 15) { emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_FAST_MULTI + local_num); } else { emit_write_bytecode_byte_uint(emit, 1, MP_BC_LOAD_FAST_N + kind, local_num); } } void mp_emit_bc_load_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_BC_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_LOAD_NAME); MP_STATIC_ASSERT(MP_BC_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_LOAD_GLOBAL); (void)qst; emit_write_bytecode_byte_qstr(emit, 1, MP_BC_LOAD_NAME + kind, qst); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { emit_write_bytecode_raw_byte(emit, 0); } } void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super) { int stack_adj = 1 - 2 * is_super; emit_write_bytecode_byte_qstr(emit, stack_adj, is_super ? MP_BC_LOAD_SUPER_METHOD : MP_BC_LOAD_METHOD, qst); } void mp_emit_bc_load_build_class(emit_t *emit) { emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_BUILD_CLASS); } void mp_emit_bc_subscr(emit_t *emit, int kind) { if (kind == MP_EMIT_SUBSCR_LOAD) { emit_write_bytecode_byte(emit, -1, MP_BC_LOAD_SUBSCR); } else { if (kind == MP_EMIT_SUBSCR_DELETE) { mp_emit_bc_load_null(emit); mp_emit_bc_rot_three(emit); } emit_write_bytecode_byte(emit, -3, MP_BC_STORE_SUBSCR); } } void mp_emit_bc_attr(emit_t *emit, qstr qst, int kind) { if (kind == MP_EMIT_ATTR_LOAD) { emit_write_bytecode_byte_qstr(emit, 0, MP_BC_LOAD_ATTR, qst); } else { if (kind == MP_EMIT_ATTR_DELETE) { mp_emit_bc_load_null(emit); mp_emit_bc_rot_two(emit); } emit_write_bytecode_byte_qstr(emit, -2, MP_BC_STORE_ATTR, qst); } if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { emit_write_bytecode_raw_byte(emit, 0); } } void mp_emit_bc_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { MP_STATIC_ASSERT(MP_BC_STORE_FAST_N + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_STORE_FAST_N); MP_STATIC_ASSERT(MP_BC_STORE_FAST_N + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_STORE_DEREF); (void)qst; if (kind == MP_EMIT_IDOP_LOCAL_FAST && local_num <= 15) { emit_write_bytecode_byte(emit, -1, MP_BC_STORE_FAST_MULTI + local_num); } else { emit_write_bytecode_byte_uint(emit, -1, MP_BC_STORE_FAST_N + kind, local_num); } } void mp_emit_bc_store_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_BC_STORE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_STORE_NAME); MP_STATIC_ASSERT(MP_BC_STORE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_STORE_GLOBAL); emit_write_bytecode_byte_qstr(emit, -1, MP_BC_STORE_NAME + kind, qst); } void mp_emit_bc_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { MP_STATIC_ASSERT(MP_BC_DELETE_FAST + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_DELETE_FAST); MP_STATIC_ASSERT(MP_BC_DELETE_FAST + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_DELETE_DEREF); (void)qst; emit_write_bytecode_byte_uint(emit, 0, MP_BC_DELETE_FAST + kind, local_num); } void mp_emit_bc_delete_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_BC_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_DELETE_NAME); MP_STATIC_ASSERT(MP_BC_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_DELETE_GLOBAL); emit_write_bytecode_byte_qstr(emit, 0, MP_BC_DELETE_NAME + kind, qst); } void mp_emit_bc_dup_top(emit_t *emit) { emit_write_bytecode_byte(emit, 1, MP_BC_DUP_TOP); } void mp_emit_bc_dup_top_two(emit_t *emit) { emit_write_bytecode_byte(emit, 2, MP_BC_DUP_TOP_TWO); } void mp_emit_bc_pop_top(emit_t *emit) { emit_write_bytecode_byte(emit, -1, MP_BC_POP_TOP); } void mp_emit_bc_rot_two(emit_t *emit) { emit_write_bytecode_byte(emit, 0, MP_BC_ROT_TWO); } void mp_emit_bc_rot_three(emit_t *emit) { emit_write_bytecode_byte(emit, 0, MP_BC_ROT_THREE); } void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) { emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_JUMP, label); } void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) { if (cond) { emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_POP_JUMP_IF_TRUE, label); } else { emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_POP_JUMP_IF_FALSE, label); } } void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) { if (cond) { emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_JUMP_IF_TRUE_OR_POP, label); } else { emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_JUMP_IF_FALSE_OR_POP, label); } } void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) { if (except_depth == 0) { if (label & MP_EMIT_BREAK_FROM_FOR) { // need to pop the iterator if we are breaking out of a for loop emit_write_bytecode_raw_byte(emit, MP_BC_POP_TOP); // also pop the iter_buf for (size_t i = 0; i < MP_OBJ_ITER_BUF_NSLOTS - 1; ++i) { emit_write_bytecode_raw_byte(emit, MP_BC_POP_TOP); } } emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); } else { emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); emit_write_bytecode_raw_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth); } } void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) { MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_WITH == MP_BC_SETUP_WITH); MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_EXCEPT == MP_BC_SETUP_EXCEPT); MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_FINALLY == MP_BC_SETUP_FINALLY); // The SETUP_WITH opcode pops ctx_mgr from the top of the stack // and then pushes 3 entries: __exit__, ctx_mgr, as_value. int stack_adj = kind == MP_EMIT_SETUP_BLOCK_WITH ? 2 : 0; emit_write_bytecode_byte_unsigned_label(emit, stack_adj, MP_BC_SETUP_WITH + kind, label); } void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) { mp_emit_bc_load_const_tok(emit, MP_TOKEN_KW_NONE); mp_emit_bc_label_assign(emit, label); // The +2 is to ensure we have enough stack space to call the __exit__ method emit_write_bytecode_byte(emit, 2, MP_BC_WITH_CLEANUP); // Cancel the +2 above, plus the +2 from mp_emit_bc_setup_block(MP_EMIT_SETUP_BLOCK_WITH) mp_emit_bc_adjust_stack_size(emit, -4); } void mp_emit_bc_end_finally(emit_t *emit) { emit_write_bytecode_byte(emit, -1, MP_BC_END_FINALLY); } void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) { int stack_adj = use_stack ? MP_OBJ_ITER_BUF_NSLOTS - 1 : 0; emit_write_bytecode_byte(emit, stack_adj, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER); } void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) { emit_write_bytecode_byte_unsigned_label(emit, 1, MP_BC_FOR_ITER, label); } void mp_emit_bc_for_iter_end(emit_t *emit) { mp_emit_bc_adjust_stack_size(emit, -MP_OBJ_ITER_BUF_NSLOTS); } void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { (void)within_exc_handler; emit_write_bytecode_byte_unsigned_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label); } void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) { emit_write_bytecode_byte(emit, 0, MP_BC_UNARY_OP_MULTI + op); } void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) { bool invert = false; if (op == MP_BINARY_OP_NOT_IN) { invert = true; op = MP_BINARY_OP_IN; } else if (op == MP_BINARY_OP_IS_NOT) { invert = true; op = MP_BINARY_OP_IS; } emit_write_bytecode_byte(emit, -1, MP_BC_BINARY_OP_MULTI + op); if (invert) { emit_write_bytecode_byte(emit, 0, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NOT); } } void mp_emit_bc_build(emit_t *emit, mp_uint_t n_args, int kind) { MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_TUPLE == MP_BC_BUILD_TUPLE); MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_LIST == MP_BC_BUILD_LIST); MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_MAP == MP_BC_BUILD_MAP); MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_SET == MP_BC_BUILD_SET); MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_SLICE == MP_BC_BUILD_SLICE); int stack_adj = kind == MP_EMIT_BUILD_MAP ? 1 : 1 - n_args; emit_write_bytecode_byte_uint(emit, stack_adj, MP_BC_BUILD_TUPLE + kind, n_args); } void mp_emit_bc_store_map(emit_t *emit) { emit_write_bytecode_byte(emit, -2, MP_BC_STORE_MAP); } void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_stack_index) { int t; int n; if (kind == SCOPE_LIST_COMP) { n = 0; t = 0; } else if (!MICROPY_PY_BUILTINS_SET || kind == SCOPE_DICT_COMP) { n = 1; t = 1; } else if (MICROPY_PY_BUILTINS_SET) { n = 0; t = 2; } // the lower 2 bits of the opcode argument indicate the collection type emit_write_bytecode_byte_uint(emit, -1 - n, MP_BC_STORE_COMP, ((collection_stack_index + n) << 2) | t); } void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) { emit_write_bytecode_byte_uint(emit, -1 + n_args, MP_BC_UNPACK_SEQUENCE, n_args); } void mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) { emit_write_bytecode_byte_uint(emit, -1 + n_left + n_right + 1, MP_BC_UNPACK_EX, n_left | (n_right << 8)); } void mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { emit_write_bytecode_byte_raw_code(emit, 1, MP_BC_MAKE_FUNCTION, scope->raw_code); } else { emit_write_bytecode_byte_raw_code(emit, -1, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code); } } void mp_emit_bc_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { int stack_adj = -n_closed_over + 1; emit_write_bytecode_byte_raw_code(emit, stack_adj, MP_BC_MAKE_CLOSURE, scope->raw_code); emit_write_bytecode_raw_byte(emit, n_closed_over); } else { assert(n_closed_over <= 255); int stack_adj = -2 - (mp_int_t)n_closed_over + 1; emit_write_bytecode_byte_raw_code(emit, stack_adj, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code); emit_write_bytecode_raw_byte(emit, n_closed_over); } } STATIC void emit_bc_call_function_method_helper(emit_t *emit, int stack_adj, mp_uint_t bytecode_base, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { if (star_flags) { stack_adj -= (int)n_positional + 2 * (int)n_keyword + 2; emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base + 1, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints? } else { stack_adj -= (int)n_positional + 2 * (int)n_keyword; emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints? } } void mp_emit_bc_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { emit_bc_call_function_method_helper(emit, 0, MP_BC_CALL_FUNCTION, n_positional, n_keyword, star_flags); } void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { emit_bc_call_function_method_helper(emit, -1, MP_BC_CALL_METHOD, n_positional, n_keyword, star_flags); } void mp_emit_bc_return_value(emit_t *emit) { emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE); emit->last_emit_was_return_value = true; } void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 1 == MP_BC_RAISE_OBJ); MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 2 == MP_BC_RAISE_FROM); assert(n_args <= 2); emit_write_bytecode_byte(emit, -n_args, MP_BC_RAISE_LAST + n_args); } void mp_emit_bc_yield(emit_t *emit, int kind) { MP_STATIC_ASSERT(MP_BC_YIELD_VALUE + 1 == MP_BC_YIELD_FROM); emit_write_bytecode_byte(emit, -kind, MP_BC_YIELD_VALUE + kind); emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; } void mp_emit_bc_start_except_handler(emit_t *emit) { mp_emit_bc_adjust_stack_size(emit, 4); // stack adjust for the exception instance, +3 for possible UNWIND_JUMP state } void mp_emit_bc_end_except_handler(emit_t *emit) { mp_emit_bc_adjust_stack_size(emit, -3); // stack adjust } #if MICROPY_EMIT_NATIVE const emit_method_table_t emit_bc_method_table = { #if MICROPY_DYNAMIC_COMPILER NULL, NULL, #endif mp_emit_bc_start_pass, mp_emit_bc_end_pass, mp_emit_bc_last_emit_was_return_value, mp_emit_bc_adjust_stack_size, mp_emit_bc_set_source_line, { mp_emit_bc_load_local, mp_emit_bc_load_global, }, { mp_emit_bc_store_local, mp_emit_bc_store_global, }, { mp_emit_bc_delete_local, mp_emit_bc_delete_global, }, mp_emit_bc_label_assign, mp_emit_bc_import, mp_emit_bc_load_const_tok, mp_emit_bc_load_const_small_int, mp_emit_bc_load_const_str, mp_emit_bc_load_const_obj, mp_emit_bc_load_null, mp_emit_bc_load_method, mp_emit_bc_load_build_class, mp_emit_bc_subscr, mp_emit_bc_attr, mp_emit_bc_dup_top, mp_emit_bc_dup_top_two, mp_emit_bc_pop_top, mp_emit_bc_rot_two, mp_emit_bc_rot_three, mp_emit_bc_jump, mp_emit_bc_pop_jump_if, mp_emit_bc_jump_if_or_pop, mp_emit_bc_unwind_jump, mp_emit_bc_setup_block, mp_emit_bc_with_cleanup, mp_emit_bc_end_finally, mp_emit_bc_get_iter, mp_emit_bc_for_iter, mp_emit_bc_for_iter_end, mp_emit_bc_pop_except_jump, mp_emit_bc_unary_op, mp_emit_bc_binary_op, mp_emit_bc_build, mp_emit_bc_store_map, mp_emit_bc_store_comp, mp_emit_bc_unpack_sequence, mp_emit_bc_unpack_ex, mp_emit_bc_make_function, mp_emit_bc_make_closure, mp_emit_bc_call_function, mp_emit_bc_call_method, mp_emit_bc_return_value, mp_emit_bc_raise_varargs, mp_emit_bc_yield, mp_emit_bc_start_except_handler, mp_emit_bc_end_except_handler, }; #else const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops = { mp_emit_bc_load_local, mp_emit_bc_load_global, }; const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops = { mp_emit_bc_store_local, mp_emit_bc_store_global, }; const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops = { mp_emit_bc_delete_local, mp_emit_bc_delete_global, }; #endif #endif //MICROPY_ENABLE_COMPILER micropython-1.12/py/emitcommon.c000066400000000000000000000050551357706137100167720ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/emit.h" #if MICROPY_ENABLE_COMPILER void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) { // name adding/lookup id_info_t *id = scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT); if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { // rebind as a local variable id->kind = ID_INFO_KIND_LOCAL; } } void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst) { // assumes pass is greater than 1, ie that all identifiers are defined in the scope id_info_t *id = scope_find(scope, qst); assert(id != NULL); // call the emit backend with the correct code if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { emit_method_table->global(emit, qst, MP_EMIT_IDOP_GLOBAL_NAME); } else if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) { emit_method_table->global(emit, qst, MP_EMIT_IDOP_GLOBAL_GLOBAL); } else if (id->kind == ID_INFO_KIND_LOCAL) { emit_method_table->local(emit, qst, id->local_num, MP_EMIT_IDOP_LOCAL_FAST); } else { assert(id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE); emit_method_table->local(emit, qst, id->local_num, MP_EMIT_IDOP_LOCAL_DEREF); } } #endif // MICROPY_ENABLE_COMPILER micropython-1.12/py/emitglue.c000066400000000000000000000161121357706137100164320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // This code glues the code emitters to the runtime. #include #include #include #include #include "py/emitglue.h" #include "py/runtime0.h" #include "py/bc.h" #include "py/profile.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define WRITE_CODE (1) #define DEBUG_printf DEBUG_printf #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__) #else // don't print debugging info #define DEBUG_printf(...) (void)0 #define DEBUG_OP_printf(...) (void)0 #endif #if MICROPY_DEBUG_PRINTERS mp_uint_t mp_verbose_flag = 0; #endif mp_raw_code_t *mp_emit_glue_new_raw_code(void) { mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1); rc->kind = MP_CODE_RESERVED; #if MICROPY_PY_SYS_SETTRACE rc->line_of_definition = 0; #endif return rc; } void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS size_t len, #endif const mp_uint_t *const_table, #if MICROPY_PERSISTENT_CODE_SAVE uint16_t n_obj, uint16_t n_raw_code, #endif mp_uint_t scope_flags) { rc->kind = MP_CODE_BYTECODE; rc->scope_flags = scope_flags; rc->fun_data = code; rc->const_table = const_table; #if MICROPY_PERSISTENT_CODE_SAVE rc->fun_data_len = len; rc->n_obj = n_obj; rc->n_raw_code = n_raw_code; #endif #if MICROPY_PY_SYS_SETTRACE mp_bytecode_prelude_t *prelude = &rc->prelude; mp_prof_extract_prelude(code, prelude); #endif #ifdef DEBUG_PRINT #if !MICROPY_DEBUG_PRINTERS const size_t len = 0; #endif DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags); #endif #if MICROPY_DEBUG_PRINTERS if (mp_verbose_flag >= 2) { mp_bytecode_print(rc, code, len, const_table); } #endif } #if MICROPY_EMIT_MACHINE_CODE void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, #if MICROPY_PERSISTENT_CODE_SAVE uint16_t prelude_offset, uint16_t n_obj, uint16_t n_raw_code, uint16_t n_qstr, mp_qstr_link_entry_t *qstr_link, #endif mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig) { assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM); rc->kind = kind; rc->scope_flags = scope_flags; rc->n_pos_args = n_pos_args; rc->fun_data = fun_data; rc->const_table = const_table; rc->type_sig = type_sig; #if MICROPY_PERSISTENT_CODE_SAVE rc->fun_data_len = fun_len; rc->prelude_offset = prelude_offset; rc->n_obj = n_obj; rc->n_raw_code = n_raw_code; rc->n_qstr= n_qstr; rc->qstr_link = qstr_link; #endif #ifdef DEBUG_PRINT DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " flags=%x\n", kind, fun_data, fun_len, n_pos_args, (uint)scope_flags); for (mp_uint_t i = 0; i < fun_len; i++) { if (i > 0 && i % 16 == 0) { DEBUG_printf("\n"); } DEBUG_printf(" %02x", ((byte*)fun_data)[i]); } DEBUG_printf("\n"); #ifdef WRITE_CODE FILE *fp_write_code = fopen("out-code", "wb"); fwrite(fun_data, fun_len, 1, fp_write_code); fclose(fp_write_code); #endif #else (void)fun_len; #endif } #endif mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) { DEBUG_OP_printf("make_function_from_raw_code %p\n", rc); assert(rc != NULL); // def_args must be MP_OBJ_NULL or a tuple assert(def_args == MP_OBJ_NULL || mp_obj_is_type(def_args, &mp_type_tuple)); // def_kw_args must be MP_OBJ_NULL or a dict assert(def_kw_args == MP_OBJ_NULL || mp_obj_is_type(def_kw_args, &mp_type_dict)); // make the function, depending on the raw code kind mp_obj_t fun; switch (rc->kind) { #if MICROPY_EMIT_NATIVE case MP_CODE_NATIVE_PY: case MP_CODE_NATIVE_VIPER: fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->fun_data, rc->const_table); // Check for a generator function, and if so change the type of the object if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { ((mp_obj_base_t*)MP_OBJ_TO_PTR(fun))->type = &mp_type_native_gen_wrap; } break; #endif #if MICROPY_EMIT_INLINE_ASM case MP_CODE_NATIVE_ASM: fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->fun_data, rc->type_sig); break; #endif default: // rc->kind should always be set and BYTECODE is the only remaining case assert(rc->kind == MP_CODE_BYTECODE); fun = mp_obj_new_fun_bc(def_args, def_kw_args, rc->fun_data, rc->const_table); // check for generator functions and if so change the type of the object if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { ((mp_obj_base_t*)MP_OBJ_TO_PTR(fun))->type = &mp_type_gen_wrap; } #if MICROPY_PY_SYS_SETTRACE mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t *)MP_OBJ_TO_PTR(fun); self_fun->rc = rc; #endif break; } return fun; } mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args) { DEBUG_OP_printf("make_closure_from_raw_code %p " UINT_FMT " %p\n", rc, n_closed_over, args); // make function object mp_obj_t ffun; if (n_closed_over & 0x100) { // default positional and keyword args given ffun = mp_make_function_from_raw_code(rc, args[0], args[1]); } else { // default positional and keyword args not given ffun = mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL); } // wrap function in closure object return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2)); } micropython-1.12/py/emitglue.h000066400000000000000000000075061357706137100164460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_EMITGLUE_H #define MICROPY_INCLUDED_PY_EMITGLUE_H #include "py/obj.h" #include "py/bc.h" // These variables and functions glue the code emitters to the runtime. // These must fit in 8 bits; see scope.h enum { MP_EMIT_OPT_NONE, MP_EMIT_OPT_BYTECODE, MP_EMIT_OPT_NATIVE_PYTHON, MP_EMIT_OPT_VIPER, MP_EMIT_OPT_ASM, }; typedef enum { MP_CODE_UNUSED, MP_CODE_RESERVED, MP_CODE_BYTECODE, MP_CODE_NATIVE_PY, MP_CODE_NATIVE_VIPER, MP_CODE_NATIVE_ASM, } mp_raw_code_kind_t; typedef struct _mp_qstr_link_entry_t { uint16_t off; uint16_t qst; } mp_qstr_link_entry_t; typedef struct _mp_raw_code_t { mp_uint_t kind : 3; // of type mp_raw_code_kind_t mp_uint_t scope_flags : 7; mp_uint_t n_pos_args : 11; const void *fun_data; const mp_uint_t *const_table; #if MICROPY_PERSISTENT_CODE_SAVE size_t fun_data_len; uint16_t n_obj; uint16_t n_raw_code; #if MICROPY_PY_SYS_SETTRACE mp_bytecode_prelude_t prelude; // line_of_definition is a Python source line where the raw_code was // created e.g. MP_BC_MAKE_FUNCTION. This is different from lineno info // stored in prelude, which provides line number for first statement of // a function. Required to properly implement "call" trace event. mp_uint_t line_of_definition; #endif #if MICROPY_EMIT_MACHINE_CODE uint16_t prelude_offset; uint16_t n_qstr; mp_qstr_link_entry_t *qstr_link; #endif #endif #if MICROPY_EMIT_MACHINE_CODE mp_uint_t type_sig; // for viper, compressed as 2-bit types; ret is MSB, then arg0, arg1, etc #endif } mp_raw_code_t; mp_raw_code_t *mp_emit_glue_new_raw_code(void); void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS size_t len, #endif const mp_uint_t *const_table, #if MICROPY_PERSISTENT_CODE_SAVE uint16_t n_obj, uint16_t n_raw_code, #endif mp_uint_t scope_flags); void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, #if MICROPY_PERSISTENT_CODE_SAVE uint16_t prelude_offset, uint16_t n_obj, uint16_t n_raw_code, uint16_t n_qstr, mp_qstr_link_entry_t *qstr_link, #endif mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig); mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args); mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args); #endif // MICROPY_INCLUDED_PY_EMITGLUE_H micropython-1.12/py/emitinlinethumb.c000066400000000000000000001010611357706137100200120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/emit.h" #include "py/asmthumb.h" #if MICROPY_EMIT_INLINE_THUMB typedef enum { // define rules with a compile function #define DEF_RULE(rule, comp, kind, ...) PN_##rule, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC PN_const_object, // special node for a constant, generic Python object // define rules without a compile function #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) PN_##rule, #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC } pn_kind_t; struct _emit_inline_asm_t { asm_thumb_t as; uint16_t pass; mp_obj_t *error_slot; mp_uint_t max_num_labels; qstr *label_lookup; }; STATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, const char *msg) { *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg); } STATIC void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) { *emit->error_slot = exc; } emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) { emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t); memset(&emit->as, 0, sizeof(emit->as)); mp_asm_base_init(&emit->as.base, max_num_labels); emit->max_num_labels = max_num_labels; emit->label_lookup = m_new(qstr, max_num_labels); return emit; } void emit_inline_thumb_free(emit_inline_asm_t *emit) { m_del(qstr, emit->label_lookup, emit->max_num_labels); mp_asm_base_deinit(&emit->as.base, false); m_del_obj(emit_inline_asm_t, emit); } STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) { emit->pass = pass; emit->error_slot = error_slot; if (emit->pass == MP_PASS_CODE_SIZE) { memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr)); } mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE); asm_thumb_entry(&emit->as, 0); } STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) { asm_thumb_exit(&emit->as); asm_thumb_end_pass(&emit->as); } STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) { if (n_params > 4) { emit_inline_thumb_error_msg(emit, "can only have up to 4 parameters to Thumb assembly"); return 0; } for (mp_uint_t i = 0; i < n_params; i++) { if (!MP_PARSE_NODE_IS_ID(pn_params[i])) { emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3"); return 0; } const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i])); if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) { emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3"); return 0; } } return n_params; } STATIC bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) { assert(label_num < emit->max_num_labels); if (emit->pass == MP_PASS_CODE_SIZE) { // check for duplicate label on first pass for (uint i = 0; i < emit->max_num_labels; i++) { if (emit->label_lookup[i] == label_id) { return false; } } } emit->label_lookup[label_num] = label_id; mp_asm_base_label_assign(&emit->as.base, label_num); return true; } typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t; STATIC const reg_name_t reg_name_table[] = { {0, "r0\0"}, {1, "r1\0"}, {2, "r2\0"}, {3, "r3\0"}, {4, "r4\0"}, {5, "r5\0"}, {6, "r6\0"}, {7, "r7\0"}, {8, "r8\0"}, {9, "r9\0"}, {10, "r10"}, {11, "r11"}, {12, "r12"}, {13, "r13"}, {14, "r14"}, {15, "r15"}, {10, "sl\0"}, {11, "fp\0"}, {13, "sp\0"}, {14, "lr\0"}, {15, "pc\0"}, }; #define MAX_SPECIAL_REGISTER_NAME_LENGTH 7 typedef struct _special_reg_name_t { byte reg; char name[MAX_SPECIAL_REGISTER_NAME_LENGTH + 1]; } special_reg_name_t; STATIC const special_reg_name_t special_reg_name_table[] = { {5, "IPSR"}, {17, "BASEPRI"}, }; // return empty string in case of error, so we can attempt to parse the string // without a special check if it was in fact a string STATIC const char *get_arg_str(mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_ID(pn)) { qstr qst = MP_PARSE_NODE_LEAF_ARG(pn); return qstr_str(qst); } else { return ""; } } STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_uint_t max_reg) { const char *reg_str = get_arg_str(pn); for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) { const reg_name_t *r = ®_name_table[i]; if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) { if (r->reg > max_reg) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects at most r%d", op, max_reg)); return 0; } else { return r->reg; } } } emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a register", op)); return 0; } STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { const char *reg_str = get_arg_str(pn); for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(special_reg_name_table); i++) { const special_reg_name_t *r = &special_reg_name_table[i]; if (strcmp(r->name, reg_str) == 0) { return r->reg; } } emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a special register", op)); return 0; } #if MICROPY_EMIT_INLINE_THUMB_FLOAT STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { const char *reg_str = get_arg_str(pn); if (reg_str[0] == 's' && reg_str[1] != '\0') { mp_uint_t regno = 0; for (++reg_str; *reg_str; ++reg_str) { mp_uint_t v = *reg_str; if (!('0' <= v && v <= '9')) { goto malformed; } regno = 10 * regno + v - '0'; } if (regno > 31) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects at most r%d", op, 31)); return 0; } else { return regno; } } malformed: emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an FPU register", op)); return 0; } #endif STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { // a register list looks like {r0, r1, r2} and is parsed as a Python set if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_brace)) { goto bad_arg; } mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 1); // should always be pn = pns->nodes[0]; mp_uint_t reglist = 0; if (MP_PARSE_NODE_IS_ID(pn)) { // set with one element reglist |= 1 << get_arg_reg(emit, op, pn, 15); } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { pns = (mp_parse_node_struct_t*)pn; if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) { assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) { // set with multiple elements // get first element of set (we rely on get_arg_reg to catch syntax errors) reglist |= 1 << get_arg_reg(emit, op, pns->nodes[0], 15); // get tail elements (2nd, 3rd, ...) mp_parse_node_t *nodes; int n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes); // process rest of elements for (int i = 0; i < n; i++) { reglist |= 1 << get_arg_reg(emit, op, nodes[i], 15); } } else { goto bad_arg; } } else { goto bad_arg; } } else { goto bad_arg; } return reglist; bad_arg: emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects {r0, r1, ...}", op)); return 0; } STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint32_t fit_mask) { mp_obj_t o; if (!mp_parse_node_get_int_maybe(pn, &o)) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an integer", op)); return 0; } uint32_t i = mp_obj_get_int_truncated(o); if ((i & (~fit_mask)) != 0) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' integer 0x%x doesn't fit in mask 0x%x", op, i, fit_mask)); return 0; } return i; } STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_parse_node_t *pn_base, mp_parse_node_t *pn_offset) { if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_bracket)) { goto bad_arg; } mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { goto bad_arg; } pns = (mp_parse_node_struct_t*)pns->nodes[0]; if (MP_PARSE_NODE_STRUCT_NUM_NODES(pns) != 2) { goto bad_arg; } *pn_base = pns->nodes[0]; *pn_offset = pns->nodes[1]; return true; bad_arg: emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an address of the form [a, b]", op)); return false; } STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { if (!MP_PARSE_NODE_IS_ID(pn)) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a label", op)); return 0; } qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn); for (uint i = 0; i < emit->max_num_labels; i++) { if (emit->label_lookup[i] == label_qstr) { return i; } } // only need to have the labels on the last pass if (emit->pass == MP_PASS_EMIT) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "label '%q' not defined", label_qstr)); } return 0; } typedef struct _cc_name_t { byte cc; byte name[2]; } cc_name_t; STATIC const cc_name_t cc_name_table[] = { { ASM_THUMB_CC_EQ, "eq" }, { ASM_THUMB_CC_NE, "ne" }, { ASM_THUMB_CC_CS, "cs" }, { ASM_THUMB_CC_CC, "cc" }, { ASM_THUMB_CC_MI, "mi" }, { ASM_THUMB_CC_PL, "pl" }, { ASM_THUMB_CC_VS, "vs" }, { ASM_THUMB_CC_VC, "vc" }, { ASM_THUMB_CC_HI, "hi" }, { ASM_THUMB_CC_LS, "ls" }, { ASM_THUMB_CC_GE, "ge" }, { ASM_THUMB_CC_LT, "lt" }, { ASM_THUMB_CC_GT, "gt" }, { ASM_THUMB_CC_LE, "le" }, }; typedef struct _format_4_op_t { byte op; char name[3]; } format_4_op_t; #define X(x) (((x) >> 4) & 0xff) // only need 1 byte to distinguish these ops STATIC const format_4_op_t format_4_op_table[] = { { X(ASM_THUMB_FORMAT_4_EOR), "eor" }, { X(ASM_THUMB_FORMAT_4_LSL), "lsl" }, { X(ASM_THUMB_FORMAT_4_LSR), "lsr" }, { X(ASM_THUMB_FORMAT_4_ASR), "asr" }, { X(ASM_THUMB_FORMAT_4_ADC), "adc" }, { X(ASM_THUMB_FORMAT_4_SBC), "sbc" }, { X(ASM_THUMB_FORMAT_4_ROR), "ror" }, { X(ASM_THUMB_FORMAT_4_TST), "tst" }, { X(ASM_THUMB_FORMAT_4_NEG), "neg" }, { X(ASM_THUMB_FORMAT_4_CMP), "cmp" }, { X(ASM_THUMB_FORMAT_4_CMN), "cmn" }, { X(ASM_THUMB_FORMAT_4_ORR), "orr" }, { X(ASM_THUMB_FORMAT_4_MUL), "mul" }, { X(ASM_THUMB_FORMAT_4_BIC), "bic" }, { X(ASM_THUMB_FORMAT_4_MVN), "mvn" }, }; #undef X // name is actually a qstr, which should fit in 16 bits typedef struct _format_9_10_op_t { uint16_t op; uint16_t name; } format_9_10_op_t; #define X(x) (x) STATIC const format_9_10_op_t format_9_10_op_table[] = { { X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_ldr }, { X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_ldrb }, { X(ASM_THUMB_FORMAT_10_LDRH), MP_QSTR_ldrh }, { X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_str }, { X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_strb }, { X(ASM_THUMB_FORMAT_10_STRH), MP_QSTR_strh }, }; #undef X #if MICROPY_EMIT_INLINE_THUMB_FLOAT // actual opcodes are: 0xee00 | op.hi_nibble, 0x0a00 | op.lo_nibble typedef struct _format_vfp_op_t { byte op; char name[3]; } format_vfp_op_t; STATIC const format_vfp_op_t format_vfp_op_table[] = { { 0x30, "add" }, { 0x34, "sub" }, { 0x20, "mul" }, { 0x80, "div" }, }; #endif // shorthand alias for whether we allow ARMv7-M instructions #define ARMV7M MICROPY_EMIT_INLINE_THUMB_ARMV7M STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) { // TODO perhaps make two tables: // one_args = // "b", LAB, asm_thumb_b_n, // "bgt", LAB, asm_thumb_bgt_n, // two_args = // "movs", RLO, I8, asm_thumb_movs_reg_i8 // "movw", REG, REG, asm_thumb_movw_reg_i16 // three_args = // "subs", RLO, RLO, I3, asm_thumb_subs_reg_reg_i3 size_t op_len; const char *op_str = (const char*)qstr_data(op, &op_len); #if MICROPY_EMIT_INLINE_THUMB_FLOAT if (op_str[0] == 'v') { // floating point operations if (n_args == 2) { mp_uint_t op_code = 0x0ac0, op_code_hi; if (op == MP_QSTR_vcmp) { op_code_hi = 0xeeb4; op_vfp_twoargs:; mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]); mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[1]); asm_thumb_op32(&emit->as, op_code_hi | ((vd & 1) << 6), op_code | ((vd & 0x1e) << 11) | ((vm & 1) << 5) | (vm & 0x1e) >> 1); } else if (op == MP_QSTR_vsqrt) { op_code_hi = 0xeeb1; goto op_vfp_twoargs; } else if (op == MP_QSTR_vneg) { op_code_hi = 0xeeb1; op_code = 0x0a40; goto op_vfp_twoargs; } else if (op == MP_QSTR_vcvt_f32_s32) { op_code_hi = 0xeeb8; // int to float goto op_vfp_twoargs; } else if (op == MP_QSTR_vcvt_s32_f32) { op_code_hi = 0xeebd; // float to int goto op_vfp_twoargs; } else if (op == MP_QSTR_vmrs) { mp_uint_t reg_dest; const char *reg_str0 = get_arg_str(pn_args[0]); if (strcmp(reg_str0, "APSR_nzcv") == 0) { reg_dest = 15; } else { reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); } const char *reg_str1 = get_arg_str(pn_args[1]); if (strcmp(reg_str1, "FPSCR") == 0) { // FP status to ARM reg asm_thumb_op32(&emit->as, 0xeef1, 0x0a10 | (reg_dest << 12)); } else { goto unknown_op; } } else if (op == MP_QSTR_vmov) { op_code_hi = 0xee00; mp_uint_t r_arm, vm; const char *reg_str = get_arg_str(pn_args[0]); if (reg_str[0] == 'r') { r_arm = get_arg_reg(emit, op_str, pn_args[0], 15); vm = get_arg_vfpreg(emit, op_str, pn_args[1]); op_code_hi |= 0x10; } else { vm = get_arg_vfpreg(emit, op_str, pn_args[0]); r_arm = get_arg_reg(emit, op_str, pn_args[1], 15); } asm_thumb_op32(&emit->as, op_code_hi | ((vm & 0x1e) >> 1), 0x0a10 | (r_arm << 12) | ((vm & 1) << 7)); } else if (op == MP_QSTR_vldr) { op_code_hi = 0xed90; op_vldr_vstr:; mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]); mp_parse_node_t pn_base, pn_offset; if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) { mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7); mp_uint_t i8; i8 = get_arg_i(emit, op_str, pn_offset, 0x3fc) >> 2; asm_thumb_op32(&emit->as, op_code_hi | rlo_base | ((vd & 1) << 6), 0x0a00 | ((vd & 0x1e) << 11) | i8); } } else if (op == MP_QSTR_vstr) { op_code_hi = 0xed80; goto op_vldr_vstr; } else { goto unknown_op; } } else if (n_args == 3) { // search table for arith ops for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_vfp_op_table); i++) { if (strncmp(op_str + 1, format_vfp_op_table[i].name, 3) == 0 && op_str[4] == '\0') { mp_uint_t op_code_hi = 0xee00 | (format_vfp_op_table[i].op & 0xf0); mp_uint_t op_code = 0x0a00 | ((format_vfp_op_table[i].op & 0x0f) << 4); mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]); mp_uint_t vn = get_arg_vfpreg(emit, op_str, pn_args[1]); mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[2]); asm_thumb_op32(&emit->as, op_code_hi | ((vd & 1) << 6) | (vn >> 1), op_code | (vm >> 1) | ((vm & 1) << 5) | ((vd & 0x1e) << 11) | ((vn & 1) << 7)); return; } } goto unknown_op; } else { goto unknown_op; } } else #endif if (n_args == 0) { if (op == MP_QSTR_nop) { asm_thumb_op16(&emit->as, ASM_THUMB_OP_NOP); } else if (op == MP_QSTR_wfi) { asm_thumb_op16(&emit->as, ASM_THUMB_OP_WFI); } else { goto unknown_op; } } else if (n_args == 1) { if (op == MP_QSTR_b) { int label_num = get_arg_label(emit, op_str, pn_args[0]); if (!asm_thumb_b_n_label(&emit->as, label_num)) { goto branch_not_in_range; } } else if (op == MP_QSTR_bl) { int label_num = get_arg_label(emit, op_str, pn_args[0]); if (!asm_thumb_bl_label(&emit->as, label_num)) { goto branch_not_in_range; } } else if (op == MP_QSTR_bx) { mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15); asm_thumb_op16(&emit->as, 0x4700 | (r << 3)); } else if (op_str[0] == 'b' && (op_len == 3 || (op_len == 5 && op_str[3] == '_' && (op_str[4] == 'n' || (ARMV7M && op_str[4] == 'w'))))) { mp_uint_t cc = -1; for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) { if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) { cc = cc_name_table[i].cc; } } if (cc == (mp_uint_t)-1) { goto unknown_op; } int label_num = get_arg_label(emit, op_str, pn_args[0]); if (!asm_thumb_bcc_nw_label(&emit->as, cc, label_num, op_len == 5 && op_str[4] == 'w')) { goto branch_not_in_range; } } else if (ARMV7M && op_str[0] == 'i' && op_str[1] == 't') { const char *arg_str = get_arg_str(pn_args[0]); mp_uint_t cc = -1; for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) { if (arg_str[0] == cc_name_table[i].name[0] && arg_str[1] == cc_name_table[i].name[1] && arg_str[2] == '\0') { cc = cc_name_table[i].cc; break; } } if (cc == (mp_uint_t)-1) { goto unknown_op; } const char *os = op_str + 2; while (*os != '\0') { os++; } if (os > op_str + 5) { goto unknown_op; } mp_uint_t it_mask = 8; while (--os >= op_str + 2) { it_mask >>= 1; if (*os == 't') { it_mask |= (cc & 1) << 3; } else if (*os == 'e') { it_mask |= ((~cc) & 1) << 3; } else { goto unknown_op; } } asm_thumb_it_cc(&emit->as, cc, it_mask); } else if (op == MP_QSTR_cpsid) { // TODO check pn_args[0] == i asm_thumb_op16(&emit->as, ASM_THUMB_OP_CPSID_I); } else if (op == MP_QSTR_cpsie) { // TODO check pn_args[0] == i asm_thumb_op16(&emit->as, ASM_THUMB_OP_CPSIE_I); } else if (op == MP_QSTR_push) { mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]); if ((reglist & 0xff00) == 0) { asm_thumb_op16(&emit->as, 0xb400 | reglist); } else { if (!ARMV7M) { goto unknown_op; } asm_thumb_op32(&emit->as, 0xe92d, reglist); } } else if (op == MP_QSTR_pop) { mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]); if ((reglist & 0xff00) == 0) { asm_thumb_op16(&emit->as, 0xbc00 | reglist); } else { if (!ARMV7M) { goto unknown_op; } asm_thumb_op32(&emit->as, 0xe8bd, reglist); } } else { goto unknown_op; } } else if (n_args == 2) { if (MP_PARSE_NODE_IS_ID(pn_args[1])) { // second arg is a register (or should be) mp_uint_t op_code, op_code_hi; if (op == MP_QSTR_mov) { mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); mp_uint_t reg_src = get_arg_reg(emit, op_str, pn_args[1], 15); asm_thumb_mov_reg_reg(&emit->as, reg_dest, reg_src); } else if (ARMV7M && op == MP_QSTR_clz) { op_code_hi = 0xfab0; op_code = 0xf080; mp_uint_t rd, rm; op_clz_rbit: rd = get_arg_reg(emit, op_str, pn_args[0], 15); rm = get_arg_reg(emit, op_str, pn_args[1], 15); asm_thumb_op32(&emit->as, op_code_hi | rm, op_code | (rd << 8) | rm); } else if (ARMV7M && op == MP_QSTR_rbit) { op_code_hi = 0xfa90; op_code = 0xf0a0; goto op_clz_rbit; } else if (ARMV7M && op == MP_QSTR_mrs){ mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 12); mp_uint_t reg_src = get_arg_special_reg(emit, op_str, pn_args[1]); asm_thumb_op32(&emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src); } else { if (op == MP_QSTR_and_) { op_code = ASM_THUMB_FORMAT_4_AND; mp_uint_t reg_dest, reg_src; op_format_4: reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7); reg_src = get_arg_reg(emit, op_str, pn_args[1], 7); asm_thumb_format_4(&emit->as, op_code, reg_dest, reg_src); return; } // search table for ALU ops for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_4_op_table); i++) { if (strncmp(op_str, format_4_op_table[i].name, 3) == 0 && op_str[3] == '\0') { op_code = 0x4000 | (format_4_op_table[i].op << 4); goto op_format_4; } } goto unknown_op; } } else { // second arg is not a register mp_uint_t op_code; if (op == MP_QSTR_mov) { op_code = ASM_THUMB_FORMAT_3_MOV; mp_uint_t rlo_dest, i8_src; op_format_3: rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7); i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff); asm_thumb_format_3(&emit->as, op_code, rlo_dest, i8_src); } else if (op == MP_QSTR_cmp) { op_code = ASM_THUMB_FORMAT_3_CMP; goto op_format_3; } else if (op == MP_QSTR_add) { op_code = ASM_THUMB_FORMAT_3_ADD; goto op_format_3; } else if (op == MP_QSTR_sub) { op_code = ASM_THUMB_FORMAT_3_SUB; goto op_format_3; } else if (ARMV7M && op == MP_QSTR_movw) { op_code = ASM_THUMB_OP_MOVW; mp_uint_t reg_dest; op_movw_movt: reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff); asm_thumb_mov_reg_i16(&emit->as, op_code, reg_dest, i_src); } else if (ARMV7M && op == MP_QSTR_movt) { op_code = ASM_THUMB_OP_MOVT; goto op_movw_movt; } else if (ARMV7M && op == MP_QSTR_movwt) { // this is a convenience instruction mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); uint32_t i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff); asm_thumb_mov_reg_i16(&emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff); asm_thumb_mov_reg_i16(&emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff); } else if (ARMV7M && op == MP_QSTR_ldrex) { mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15); mp_parse_node_t pn_base, pn_offset; if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) { mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15); mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2; asm_thumb_op32(&emit->as, 0xe850 | r_base, 0x0f00 | (r_dest << 12) | i8); } } else { // search table for ldr/str instructions for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_9_10_op_table); i++) { if (op == format_9_10_op_table[i].name) { op_code = format_9_10_op_table[i].op; mp_parse_node_t pn_base, pn_offset; mp_uint_t rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7); if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) { mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7); mp_uint_t i5; if (op_code & ASM_THUMB_FORMAT_9_BYTE_TRANSFER) { i5 = get_arg_i(emit, op_str, pn_offset, 0x1f); } else if (op_code & ASM_THUMB_FORMAT_10_STRH) { // also catches LDRH i5 = get_arg_i(emit, op_str, pn_offset, 0x3e) >> 1; } else { i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2; } asm_thumb_format_9_10(&emit->as, op_code, rlo_dest, rlo_base, i5); return; } break; } } goto unknown_op; } } } else if (n_args == 3) { mp_uint_t op_code; if (op == MP_QSTR_lsl) { op_code = ASM_THUMB_FORMAT_1_LSL; mp_uint_t rlo_dest, rlo_src, i5; op_format_1: rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7); rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7); i5 = get_arg_i(emit, op_str, pn_args[2], 0x1f); asm_thumb_format_1(&emit->as, op_code, rlo_dest, rlo_src, i5); } else if (op == MP_QSTR_lsr) { op_code = ASM_THUMB_FORMAT_1_LSR; goto op_format_1; } else if (op == MP_QSTR_asr) { op_code = ASM_THUMB_FORMAT_1_ASR; goto op_format_1; } else if (op == MP_QSTR_add) { op_code = ASM_THUMB_FORMAT_2_ADD; mp_uint_t rlo_dest, rlo_src; op_format_2: rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7); rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7); int src_b; if (MP_PARSE_NODE_IS_ID(pn_args[2])) { op_code |= ASM_THUMB_FORMAT_2_REG_OPERAND; src_b = get_arg_reg(emit, op_str, pn_args[2], 7); } else { op_code |= ASM_THUMB_FORMAT_2_IMM_OPERAND; src_b = get_arg_i(emit, op_str, pn_args[2], 0x7); } asm_thumb_format_2(&emit->as, op_code, rlo_dest, rlo_src, src_b); } else if (ARMV7M && op == MP_QSTR_sdiv) { op_code = 0xfb90; // sdiv high part mp_uint_t rd, rn, rm; op_sdiv_udiv: rd = get_arg_reg(emit, op_str, pn_args[0], 15); rn = get_arg_reg(emit, op_str, pn_args[1], 15); rm = get_arg_reg(emit, op_str, pn_args[2], 15); asm_thumb_op32(&emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm); } else if (ARMV7M && op == MP_QSTR_udiv) { op_code = 0xfbb0; // udiv high part goto op_sdiv_udiv; } else if (op == MP_QSTR_sub) { op_code = ASM_THUMB_FORMAT_2_SUB; goto op_format_2; } else if (ARMV7M && op == MP_QSTR_strex) { mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15); mp_uint_t r_src = get_arg_reg(emit, op_str, pn_args[1], 15); mp_parse_node_t pn_base, pn_offset; if (get_arg_addr(emit, op_str, pn_args[2], &pn_base, &pn_offset)) { mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15); mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2; asm_thumb_op32(&emit->as, 0xe840 | r_base, (r_src << 12) | (r_dest << 8) | i8); } } else { goto unknown_op; } } else { goto unknown_op; } return; unknown_op: emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "unsupported Thumb instruction '%s' with %d arguments", op_str, n_args)); return; branch_not_in_range: emit_inline_thumb_error_msg(emit, "branch not in range"); return; } const emit_inline_asm_method_table_t emit_inline_thumb_method_table = { #if MICROPY_DYNAMIC_COMPILER emit_inline_thumb_new, emit_inline_thumb_free, #endif emit_inline_thumb_start_pass, emit_inline_thumb_end_pass, emit_inline_thumb_count_params, emit_inline_thumb_label, emit_inline_thumb_op, }; #endif // MICROPY_EMIT_INLINE_THUMB micropython-1.12/py/emitinlinextensa.c000066400000000000000000000305721357706137100202050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/emit.h" #include "py/asmxtensa.h" #if MICROPY_EMIT_INLINE_XTENSA struct _emit_inline_asm_t { asm_xtensa_t as; uint16_t pass; mp_obj_t *error_slot; mp_uint_t max_num_labels; qstr *label_lookup; }; STATIC void emit_inline_xtensa_error_msg(emit_inline_asm_t *emit, const char *msg) { *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg); } STATIC void emit_inline_xtensa_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) { *emit->error_slot = exc; } emit_inline_asm_t *emit_inline_xtensa_new(mp_uint_t max_num_labels) { emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t); memset(&emit->as, 0, sizeof(emit->as)); mp_asm_base_init(&emit->as.base, max_num_labels); emit->max_num_labels = max_num_labels; emit->label_lookup = m_new(qstr, max_num_labels); return emit; } void emit_inline_xtensa_free(emit_inline_asm_t *emit) { m_del(qstr, emit->label_lookup, emit->max_num_labels); mp_asm_base_deinit(&emit->as.base, false); m_del_obj(emit_inline_asm_t, emit); } STATIC void emit_inline_xtensa_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) { emit->pass = pass; emit->error_slot = error_slot; if (emit->pass == MP_PASS_CODE_SIZE) { memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr)); } mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE); asm_xtensa_entry(&emit->as, 0); } STATIC void emit_inline_xtensa_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) { asm_xtensa_exit(&emit->as); asm_xtensa_end_pass(&emit->as); } STATIC mp_uint_t emit_inline_xtensa_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) { if (n_params > 4) { emit_inline_xtensa_error_msg(emit, "can only have up to 4 parameters to Xtensa assembly"); return 0; } for (mp_uint_t i = 0; i < n_params; i++) { if (!MP_PARSE_NODE_IS_ID(pn_params[i])) { emit_inline_xtensa_error_msg(emit, "parameters must be registers in sequence a2 to a5"); return 0; } const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i])); if (!(strlen(p) == 2 && p[0] == 'a' && p[1] == '2' + i)) { emit_inline_xtensa_error_msg(emit, "parameters must be registers in sequence a2 to a5"); return 0; } } return n_params; } STATIC bool emit_inline_xtensa_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) { assert(label_num < emit->max_num_labels); if (emit->pass == MP_PASS_CODE_SIZE) { // check for duplicate label on first pass for (uint i = 0; i < emit->max_num_labels; i++) { if (emit->label_lookup[i] == label_id) { return false; } } } emit->label_lookup[label_num] = label_id; mp_asm_base_label_assign(&emit->as.base, label_num); return true; } typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t; STATIC const reg_name_t reg_name_table[] = { {0, "a0\0"}, {1, "a1\0"}, {2, "a2\0"}, {3, "a3\0"}, {4, "a4\0"}, {5, "a5\0"}, {6, "a6\0"}, {7, "a7\0"}, {8, "a8\0"}, {9, "a9\0"}, {10, "a10"}, {11, "a11"}, {12, "a12"}, {13, "a13"}, {14, "a14"}, {15, "a15"}, }; // return empty string in case of error, so we can attempt to parse the string // without a special check if it was in fact a string STATIC const char *get_arg_str(mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_ID(pn)) { qstr qst = MP_PARSE_NODE_LEAF_ARG(pn); return qstr_str(qst); } else { return ""; } } STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { const char *reg_str = get_arg_str(pn); for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) { const reg_name_t *r = ®_name_table[i]; if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) { return r->reg; } } emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a register", op)); return 0; } STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, int min, int max) { mp_obj_t o; if (!mp_parse_node_get_int_maybe(pn, &o)) { emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an integer", op)); return 0; } uint32_t i = mp_obj_get_int_truncated(o); if (min != max && ((int)i < min || (int)i > max)) { emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' integer %d isn't within range %d..%d", op, i, min, max)); return 0; } return i; } STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { if (!MP_PARSE_NODE_IS_ID(pn)) { emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a label", op)); return 0; } qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn); for (uint i = 0; i < emit->max_num_labels; i++) { if (emit->label_lookup[i] == label_qstr) { return i; } } // only need to have the labels on the last pass if (emit->pass == MP_PASS_EMIT) { emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "label '%q' not defined", label_qstr)); } return 0; } #define RRR (0) #define RRI8 (1) #define RRI8_B (2) typedef struct _opcode_table_3arg_t { uint16_t name; // actually a qstr, which should fit in 16 bits uint8_t type; uint8_t a0 : 4; uint8_t a1 : 4; } opcode_table_3arg_t; STATIC const opcode_table_3arg_t opcode_table_3arg[] = { // arithmetic opcodes: reg, reg, reg {MP_QSTR_and_, RRR, 0, 1}, {MP_QSTR_or_, RRR, 0, 2}, {MP_QSTR_xor, RRR, 0, 3}, {MP_QSTR_add, RRR, 0, 8}, {MP_QSTR_sub, RRR, 0, 12}, {MP_QSTR_mull, RRR, 2, 8}, // load/store/addi opcodes: reg, reg, imm // upper nibble of type encodes the range of the immediate arg {MP_QSTR_l8ui, RRI8 | 0x10, 2, 0}, {MP_QSTR_l16ui, RRI8 | 0x30, 2, 1}, {MP_QSTR_l32i, RRI8 | 0x50, 2, 2}, {MP_QSTR_s8i, RRI8 | 0x10, 2, 4}, {MP_QSTR_s16i, RRI8 | 0x30, 2, 5}, {MP_QSTR_s32i, RRI8 | 0x50, 2, 6}, {MP_QSTR_l16si, RRI8 | 0x30, 2, 9}, {MP_QSTR_addi, RRI8 | 0x00, 2, 12}, // branch opcodes: reg, reg, label {MP_QSTR_ball, RRI8_B, ASM_XTENSA_CC_ALL, 0}, {MP_QSTR_bany, RRI8_B, ASM_XTENSA_CC_ANY, 0}, {MP_QSTR_bbc, RRI8_B, ASM_XTENSA_CC_BC, 0}, {MP_QSTR_bbs, RRI8_B, ASM_XTENSA_CC_BS, 0}, {MP_QSTR_beq, RRI8_B, ASM_XTENSA_CC_EQ, 0}, {MP_QSTR_bge, RRI8_B, ASM_XTENSA_CC_GE, 0}, {MP_QSTR_bgeu, RRI8_B, ASM_XTENSA_CC_GEU, 0}, {MP_QSTR_blt, RRI8_B, ASM_XTENSA_CC_LT, 0}, {MP_QSTR_bnall, RRI8_B, ASM_XTENSA_CC_NALL, 0}, {MP_QSTR_bne, RRI8_B, ASM_XTENSA_CC_NE, 0}, {MP_QSTR_bnone, RRI8_B, ASM_XTENSA_CC_NONE, 0}, }; STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) { size_t op_len; const char *op_str = (const char*)qstr_data(op, &op_len); if (n_args == 0) { if (op == MP_QSTR_ret_n) { asm_xtensa_op_ret_n(&emit->as); } else { goto unknown_op; } } else if (n_args == 1) { if (op == MP_QSTR_callx0) { uint r0 = get_arg_reg(emit, op_str, pn_args[0]); asm_xtensa_op_callx0(&emit->as, r0); } else if (op == MP_QSTR_j) { int label = get_arg_label(emit, op_str, pn_args[0]); asm_xtensa_j_label(&emit->as, label); } else if (op == MP_QSTR_jx) { uint r0 = get_arg_reg(emit, op_str, pn_args[0]); asm_xtensa_op_jx(&emit->as, r0); } else { goto unknown_op; } } else if (n_args == 2) { uint r0 = get_arg_reg(emit, op_str, pn_args[0]); if (op == MP_QSTR_beqz) { int label = get_arg_label(emit, op_str, pn_args[1]); asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_EQ, r0, label); } else if (op == MP_QSTR_bnez) { int label = get_arg_label(emit, op_str, pn_args[1]); asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_NE, r0, label); } else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) { // we emit mov.n for both "mov" and "mov_n" opcodes uint r1 = get_arg_reg(emit, op_str, pn_args[1]); asm_xtensa_op_mov_n(&emit->as, r0, r1); } else if (op == MP_QSTR_movi) { // for convenience we emit l32r if the integer doesn't fit in movi uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0); asm_xtensa_mov_reg_i32(&emit->as, r0, imm); } else { goto unknown_op; } } else if (n_args == 3) { // search table for 3 arg instructions for (uint i = 0; i < MP_ARRAY_SIZE(opcode_table_3arg); i++) { const opcode_table_3arg_t *o = &opcode_table_3arg[i]; if (op == o->name) { uint r0 = get_arg_reg(emit, op_str, pn_args[0]); uint r1 = get_arg_reg(emit, op_str, pn_args[1]); if (o->type == RRR) { uint r2 = get_arg_reg(emit, op_str, pn_args[2]); asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, o->a0, o->a1, r0, r1, r2)); } else if (o->type == RRI8_B) { int label = get_arg_label(emit, op_str, pn_args[2]); asm_xtensa_bcc_reg_reg_label(&emit->as, o->a0, r0, r1, label); } else { int shift, min, max; if ((o->type & 0xf0) == 0) { shift = 0; min = -128; max = 127; } else { shift = (o->type & 0xf0) >> 5; min = 0; max = 0xff << shift; } uint32_t imm = get_arg_i(emit, op_str, pn_args[2], min, max); asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRI8(o->a0, o->a1, r1, r0, (imm >> shift) & 0xff)); } return; } } goto unknown_op; } else { goto unknown_op; } return; unknown_op: emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "unsupported Xtensa instruction '%s' with %d arguments", op_str, n_args)); return; /* branch_not_in_range: emit_inline_xtensa_error_msg(emit, "branch not in range"); return; */ } const emit_inline_asm_method_table_t emit_inline_xtensa_method_table = { #if MICROPY_DYNAMIC_COMPILER emit_inline_xtensa_new, emit_inline_xtensa_free, #endif emit_inline_xtensa_start_pass, emit_inline_xtensa_end_pass, emit_inline_xtensa_count_params, emit_inline_xtensa_label, emit_inline_xtensa_op, }; #endif // MICROPY_EMIT_INLINE_XTENSA micropython-1.12/py/emitnarm.c000066400000000000000000000007151357706137100164350ustar00rootroot00000000000000// ARM specific stuff #include "py/mpconfig.h" #if MICROPY_EMIT_ARM // This is defined so that the assembler exports generic assembler API macros #define GENERIC_ASM_API (1) #include "py/asmarm.h" // Word indices of REG_LOCAL_x in nlr_buf_t #define NLR_BUF_IDX_LOCAL_1 (3) // r4 #define NLR_BUF_IDX_LOCAL_2 (4) // r5 #define NLR_BUF_IDX_LOCAL_3 (5) // r6 #define N_ARM (1) #define EXPORT_FUN(name) emit_native_arm_##name #include "py/emitnative.c" #endif micropython-1.12/py/emitnative.c000066400000000000000000003564151357706137100170010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Essentially normal Python has 1 type: Python objects // Viper has more than 1 type, and is just a more complicated (a superset of) Python. // If you declare everything in Viper as a Python object (ie omit type decls) then // it should in principle be exactly the same as Python native. // Having types means having more opcodes, like binary_op_nat_nat, binary_op_nat_obj etc. // In practice we won't have a VM but rather do this in asm which is actually very minimal. // Because it breaks strict Python equivalence it should be a completely separate // decorator. It breaks equivalence because overflow on integers wraps around. // It shouldn't break equivalence if you don't use the new types, but since the // type decls might be used in normal Python for other reasons, it's probably safest, // cleanest and clearest to make it a separate decorator. // Actually, it does break equivalence because integers default to native integers, // not Python objects. // for x in l[0:8]: can be compiled into a native loop if l has pointer type #include #include #include #include "py/emit.h" #include "py/nativeglue.h" #include "py/objstr.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif // wrapper around everything in this file #if N_X64 || N_X86 || N_THUMB || N_ARM || N_XTENSA || N_XTENSAWIN // C stack layout for native functions: // 0: nlr_buf_t [optional] // emit->code_state_start: mp_code_state_t // emit->stack_start: Python object stack | emit->n_state // locals (reversed, L0 at end) | // // C stack layout for native generator functions: // 0=emit->stack_start: nlr_buf_t // // Then REG_GENERATOR_STATE points to: // 0=emit->code_state_start: mp_code_state_t // emit->stack_start: Python object stack | emit->n_state // locals (reversed, L0 at end) | // // C stack layout for viper functions: // 0: nlr_buf_t [optional] // emit->code_state_start: fun_obj, old_globals [optional] // emit->stack_start: Python object stack | emit->n_state // locals (reversed, L0 at end) | // (L0-L2 may be in regs instead) // Native emitter needs to know the following sizes and offsets of C structs (on the target): #if MICROPY_DYNAMIC_COMPILER #define SIZEOF_NLR_BUF (2 + mp_dynamic_compiler.nlr_buf_num_regs + 1) // the +1 is conservative in case MICROPY_ENABLE_PYSTACK enabled #else #define SIZEOF_NLR_BUF (sizeof(nlr_buf_t) / sizeof(uintptr_t)) #endif #define SIZEOF_CODE_STATE (sizeof(mp_code_state_t) / sizeof(uintptr_t)) #define OFFSETOF_CODE_STATE_STATE (offsetof(mp_code_state_t, state) / sizeof(uintptr_t)) #define OFFSETOF_CODE_STATE_FUN_BC (offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t)) #define OFFSETOF_CODE_STATE_IP (offsetof(mp_code_state_t, ip) / sizeof(uintptr_t)) #define OFFSETOF_CODE_STATE_SP (offsetof(mp_code_state_t, sp) / sizeof(uintptr_t)) #define OFFSETOF_OBJ_FUN_BC_GLOBALS (offsetof(mp_obj_fun_bc_t, globals) / sizeof(uintptr_t)) #define OFFSETOF_OBJ_FUN_BC_BYTECODE (offsetof(mp_obj_fun_bc_t, bytecode) / sizeof(uintptr_t)) #define OFFSETOF_OBJ_FUN_BC_CONST_TABLE (offsetof(mp_obj_fun_bc_t, const_table) / sizeof(uintptr_t)) // If not already defined, set parent args to same as child call registers #ifndef REG_PARENT_RET #define REG_PARENT_RET REG_RET #define REG_PARENT_ARG_1 REG_ARG_1 #define REG_PARENT_ARG_2 REG_ARG_2 #define REG_PARENT_ARG_3 REG_ARG_3 #define REG_PARENT_ARG_4 REG_ARG_4 #endif // Word index of nlr_buf_t.ret_val #define NLR_BUF_IDX_RET_VAL (1) // Whether the viper function needs access to fun_obj #define NEED_FUN_OBJ(emit) ((emit)->scope->exc_stack_size > 0 \ || ((emit)->scope->scope_flags & (MP_SCOPE_FLAG_REFGLOBALS | MP_SCOPE_FLAG_HASCONSTS))) // Whether the native/viper function needs to be wrapped in an exception handler #define NEED_GLOBAL_EXC_HANDLER(emit) ((emit)->scope->exc_stack_size > 0 \ || ((emit)->scope->scope_flags & (MP_SCOPE_FLAG_GENERATOR | MP_SCOPE_FLAG_REFGLOBALS))) // Whether registers can be used to store locals (only true if there are no // exception handlers, because otherwise an nlr_jump will restore registers to // their state at the start of the function and updates to locals will be lost) #define CAN_USE_REGS_FOR_LOCALS(emit) ((emit)->scope->exc_stack_size == 0 && !(emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR)) // Indices within the local C stack for various variables #define LOCAL_IDX_EXC_VAL(emit) (NLR_BUF_IDX_RET_VAL) #define LOCAL_IDX_EXC_HANDLER_PC(emit) (NLR_BUF_IDX_LOCAL_1) #define LOCAL_IDX_EXC_HANDLER_UNWIND(emit) (NLR_BUF_IDX_LOCAL_2) #define LOCAL_IDX_RET_VAL(emit) (NLR_BUF_IDX_LOCAL_3) #define LOCAL_IDX_FUN_OBJ(emit) ((emit)->code_state_start + OFFSETOF_CODE_STATE_FUN_BC) #define LOCAL_IDX_OLD_GLOBALS(emit) ((emit)->code_state_start + OFFSETOF_CODE_STATE_IP) #define LOCAL_IDX_GEN_PC(emit) ((emit)->code_state_start + OFFSETOF_CODE_STATE_IP) #define LOCAL_IDX_LOCAL_VAR(emit, local_num) ((emit)->stack_start + (emit)->n_state - 1 - (local_num)) #define REG_GENERATOR_STATE (REG_LOCAL_3) #define EMIT_NATIVE_VIPER_TYPE_ERROR(emit, ...) do { \ *emit->error_slot = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, __VA_ARGS__); \ } while (0) typedef enum { STACK_VALUE, STACK_REG, STACK_IMM, } stack_info_kind_t; // these enums must be distinct and the bottom 4 bits // must correspond to the correct MP_NATIVE_TYPE_xxx value typedef enum { VTYPE_PYOBJ = 0x00 | MP_NATIVE_TYPE_OBJ, VTYPE_BOOL = 0x00 | MP_NATIVE_TYPE_BOOL, VTYPE_INT = 0x00 | MP_NATIVE_TYPE_INT, VTYPE_UINT = 0x00 | MP_NATIVE_TYPE_UINT, VTYPE_PTR = 0x00 | MP_NATIVE_TYPE_PTR, VTYPE_PTR8 = 0x00 | MP_NATIVE_TYPE_PTR8, VTYPE_PTR16 = 0x00 | MP_NATIVE_TYPE_PTR16, VTYPE_PTR32 = 0x00 | MP_NATIVE_TYPE_PTR32, VTYPE_PTR_NONE = 0x50 | MP_NATIVE_TYPE_PTR, VTYPE_UNBOUND = 0x60 | MP_NATIVE_TYPE_OBJ, VTYPE_BUILTIN_CAST = 0x70 | MP_NATIVE_TYPE_OBJ, } vtype_kind_t; STATIC qstr vtype_to_qstr(vtype_kind_t vtype) { switch (vtype) { case VTYPE_PYOBJ: return MP_QSTR_object; case VTYPE_BOOL: return MP_QSTR_bool; case VTYPE_INT: return MP_QSTR_int; case VTYPE_UINT: return MP_QSTR_uint; case VTYPE_PTR: return MP_QSTR_ptr; case VTYPE_PTR8: return MP_QSTR_ptr8; case VTYPE_PTR16: return MP_QSTR_ptr16; case VTYPE_PTR32: return MP_QSTR_ptr32; case VTYPE_PTR_NONE: default: return MP_QSTR_None; } } typedef struct _stack_info_t { vtype_kind_t vtype; stack_info_kind_t kind; union { int u_reg; mp_int_t u_imm; } data; } stack_info_t; #define UNWIND_LABEL_UNUSED (0x7fff) #define UNWIND_LABEL_DO_FINAL_UNWIND (0x7ffe) typedef struct _exc_stack_entry_t { uint16_t label : 15; uint16_t is_finally : 1; uint16_t unwind_label : 15; uint16_t is_active : 1; } exc_stack_entry_t; struct _emit_t { mp_obj_t *error_slot; uint *label_slot; uint exit_label; int pass; bool do_viper_types; mp_uint_t local_vtype_alloc; vtype_kind_t *local_vtype; mp_uint_t stack_info_alloc; stack_info_t *stack_info; vtype_kind_t saved_stack_vtype; size_t exc_stack_alloc; size_t exc_stack_size; exc_stack_entry_t *exc_stack; int prelude_offset; int start_offset; int n_state; uint16_t code_state_start; uint16_t stack_start; int stack_size; uint16_t n_cell; uint16_t const_table_cur_obj; uint16_t const_table_num_obj; uint16_t const_table_cur_raw_code; mp_uint_t *const_table; #if MICROPY_PERSISTENT_CODE_SAVE uint16_t qstr_link_cur; mp_qstr_link_entry_t *qstr_link; #endif bool last_emit_was_return_value; scope_t *scope; ASM_T *as; }; STATIC const uint8_t reg_local_table[REG_LOCAL_NUM] = {REG_LOCAL_1, REG_LOCAL_2, REG_LOCAL_3}; STATIC void emit_native_global_exc_entry(emit_t *emit); STATIC void emit_native_global_exc_exit(emit_t *emit); STATIC void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj); emit_t *EXPORT_FUN(new)(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels) { emit_t *emit = m_new0(emit_t, 1); emit->error_slot = error_slot; emit->label_slot = label_slot; emit->stack_info_alloc = 8; emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc); emit->exc_stack_alloc = 8; emit->exc_stack = m_new(exc_stack_entry_t, emit->exc_stack_alloc); emit->as = m_new0(ASM_T, 1); mp_asm_base_init(&emit->as->base, max_num_labels); return emit; } void EXPORT_FUN(free)(emit_t *emit) { mp_asm_base_deinit(&emit->as->base, false); m_del_obj(ASM_T, emit->as); m_del(exc_stack_entry_t, emit->exc_stack, emit->exc_stack_alloc); m_del(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc); m_del(stack_info_t, emit->stack_info, emit->stack_info_alloc); m_del_obj(emit_t, emit); } STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg); STATIC void emit_native_mov_reg_const(emit_t *emit, int reg_dest, int const_val) { ASM_LOAD_REG_REG_OFFSET(emit->as, reg_dest, REG_FUN_TABLE, const_val); } STATIC void emit_native_mov_state_reg(emit_t *emit, int local_num, int reg_src) { if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { ASM_STORE_REG_REG_OFFSET(emit->as, reg_src, REG_GENERATOR_STATE, local_num); } else { ASM_MOV_LOCAL_REG(emit->as, local_num, reg_src); } } STATIC void emit_native_mov_reg_state(emit_t *emit, int reg_dest, int local_num) { if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { ASM_LOAD_REG_REG_OFFSET(emit->as, reg_dest, REG_GENERATOR_STATE, local_num); } else { ASM_MOV_REG_LOCAL(emit->as, reg_dest, local_num); } } STATIC void emit_native_mov_reg_state_addr(emit_t *emit, int reg_dest, int local_num) { if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { ASM_MOV_REG_IMM(emit->as, reg_dest, local_num * ASM_WORD_SIZE); ASM_ADD_REG_REG(emit->as, reg_dest, REG_GENERATOR_STATE); } else { ASM_MOV_REG_LOCAL_ADDR(emit->as, reg_dest, local_num); } } STATIC void emit_native_mov_reg_qstr(emit_t *emit, int arg_reg, qstr qst) { #if MICROPY_PERSISTENT_CODE_SAVE size_t loc = ASM_MOV_REG_IMM_FIX_U16(emit->as, arg_reg, qst); size_t link_idx = emit->qstr_link_cur++; if (emit->pass == MP_PASS_EMIT) { emit->qstr_link[link_idx].off = loc << 2 | 1; emit->qstr_link[link_idx].qst = qst; } #else ASM_MOV_REG_IMM(emit->as, arg_reg, qst); #endif } STATIC void emit_native_mov_reg_qstr_obj(emit_t *emit, int reg_dest, qstr qst) { #if MICROPY_PERSISTENT_CODE_SAVE size_t loc = ASM_MOV_REG_IMM_FIX_WORD(emit->as, reg_dest, (mp_uint_t)MP_OBJ_NEW_QSTR(qst)); size_t link_idx = emit->qstr_link_cur++; if (emit->pass == MP_PASS_EMIT) { emit->qstr_link[link_idx].off = loc << 2 | 2; emit->qstr_link[link_idx].qst = qst; } #else ASM_MOV_REG_IMM(emit->as, reg_dest, (mp_uint_t)MP_OBJ_NEW_QSTR(qst)); #endif } #define emit_native_mov_state_imm_via(emit, local_num, imm, reg_temp) \ do { \ ASM_MOV_REG_IMM((emit)->as, (reg_temp), (imm)); \ emit_native_mov_state_reg((emit), (local_num), (reg_temp)); \ } while (false) STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope); emit->pass = pass; emit->do_viper_types = scope->emit_options == MP_EMIT_OPT_VIPER; emit->stack_size = 0; #if N_PRELUDE_AS_BYTES_OBJ emit->const_table_cur_obj = emit->do_viper_types ? 0 : 1; // reserve first obj for prelude bytes obj #else emit->const_table_cur_obj = 0; #endif emit->const_table_cur_raw_code = 0; #if MICROPY_PERSISTENT_CODE_SAVE emit->qstr_link_cur = 0; #endif emit->last_emit_was_return_value = false; emit->scope = scope; // allocate memory for keeping track of the types of locals if (emit->local_vtype_alloc < scope->num_locals) { emit->local_vtype = m_renew(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc, scope->num_locals); emit->local_vtype_alloc = scope->num_locals; } // set default type for arguments mp_uint_t num_args = emit->scope->num_pos_args + emit->scope->num_kwonly_args; if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) { num_args += 1; } if (scope->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) { num_args += 1; } for (mp_uint_t i = 0; i < num_args; i++) { emit->local_vtype[i] = VTYPE_PYOBJ; } // Set viper type for arguments if (emit->do_viper_types) { for (int i = 0; i < emit->scope->id_info_len; ++i) { id_info_t *id = &emit->scope->id_info[i]; if (id->flags & ID_FLAG_IS_PARAM) { assert(id->local_num < emit->local_vtype_alloc); emit->local_vtype[id->local_num] = id->flags >> ID_FLAG_VIPER_TYPE_POS; } } } // local variables begin unbound, and have unknown type for (mp_uint_t i = num_args; i < emit->local_vtype_alloc; i++) { emit->local_vtype[i] = VTYPE_UNBOUND; } // values on stack begin unbound for (mp_uint_t i = 0; i < emit->stack_info_alloc; i++) { emit->stack_info[i].kind = STACK_VALUE; emit->stack_info[i].vtype = VTYPE_UNBOUND; } mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE); // generate code for entry to function // Work out start of code state (mp_code_state_t or reduced version for viper) emit->code_state_start = 0; if (NEED_GLOBAL_EXC_HANDLER(emit)) { emit->code_state_start = SIZEOF_NLR_BUF; } if (emit->do_viper_types) { // Work out size of state (locals plus stack) // n_state counts all stack and locals, even those in registers emit->n_state = scope->num_locals + scope->stack_size; int num_locals_in_regs = 0; if (CAN_USE_REGS_FOR_LOCALS(emit)) { num_locals_in_regs = scope->num_locals; if (num_locals_in_regs > REG_LOCAL_NUM) { num_locals_in_regs = REG_LOCAL_NUM; } // Need a spot for REG_LOCAL_3 if 4 or more args (see below) if (scope->num_pos_args >= 4) { --num_locals_in_regs; } } // Work out where the locals and Python stack start within the C stack if (NEED_GLOBAL_EXC_HANDLER(emit)) { // Reserve 2 words for function object and old globals emit->stack_start = emit->code_state_start + 2; } else if (scope->scope_flags & MP_SCOPE_FLAG_HASCONSTS) { // Reserve 1 word for function object, to access const table emit->stack_start = emit->code_state_start + 1; } else { emit->stack_start = emit->code_state_start + 0; } // Entry to function ASM_ENTRY(emit->as, emit->stack_start + emit->n_state - num_locals_in_regs); #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1); #endif // Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_LOCAL_3, 0); // Store function object (passed as first arg) to stack if needed if (NEED_FUN_OBJ(emit)) { ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1); } // Put n_args in REG_ARG_1, n_kw in REG_ARG_2, args array in REG_LOCAL_3 #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_1); asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_2); asm_x86_mov_arg_to_r32(emit->as, 3, REG_LOCAL_3); #else ASM_MOV_REG_REG(emit->as, REG_ARG_1, REG_PARENT_ARG_2); ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_PARENT_ARG_3); ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_PARENT_ARG_4); #endif // Check number of args matches this function, and call mp_arg_check_num_sig if not ASM_JUMP_IF_REG_NONZERO(emit->as, REG_ARG_2, *emit->label_slot + 4, true); ASM_MOV_REG_IMM(emit->as, REG_ARG_3, scope->num_pos_args); ASM_JUMP_IF_REG_EQ(emit->as, REG_ARG_1, REG_ARG_3, *emit->label_slot + 5); mp_asm_base_label_assign(&emit->as->base, *emit->label_slot + 4); ASM_MOV_REG_IMM(emit->as, REG_ARG_3, MP_OBJ_FUN_MAKE_SIG(scope->num_pos_args, scope->num_pos_args, false)); ASM_CALL_IND(emit->as, MP_F_ARG_CHECK_NUM_SIG); mp_asm_base_label_assign(&emit->as->base, *emit->label_slot + 5); // Store arguments into locals (reg or stack), converting to native if needed for (int i = 0; i < emit->scope->num_pos_args; i++) { int r = REG_ARG_1; ASM_LOAD_REG_REG_OFFSET(emit->as, REG_ARG_1, REG_LOCAL_3, i); if (emit->local_vtype[i] != VTYPE_PYOBJ) { emit_call_with_imm_arg(emit, MP_F_CONVERT_OBJ_TO_NATIVE, emit->local_vtype[i], REG_ARG_2); r = REG_RET; } // REG_LOCAL_3 points to the args array so be sure not to overwrite it if it's still needed if (i < REG_LOCAL_NUM && CAN_USE_REGS_FOR_LOCALS(emit) && (i != 2 || emit->scope->num_pos_args == 3)) { ASM_MOV_REG_REG(emit->as, reg_local_table[i], r); } else { emit_native_mov_state_reg(emit, LOCAL_IDX_LOCAL_VAR(emit, i), r); } } // Get 3rd local from the stack back into REG_LOCAL_3 if this reg couldn't be written to above if (emit->scope->num_pos_args >= 4 && CAN_USE_REGS_FOR_LOCALS(emit)) { ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_3, LOCAL_IDX_LOCAL_VAR(emit, 2)); } emit_native_global_exc_entry(emit); } else { // work out size of state (locals plus stack) emit->n_state = scope->num_locals + scope->stack_size; if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { emit->code_state_start = 0; emit->stack_start = SIZEOF_CODE_STATE; #if N_PRELUDE_AS_BYTES_OBJ // Load index of prelude bytes object in const_table mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)(emit->scope->num_pos_args + emit->scope->num_kwonly_args + 1)); #else mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_offset); #endif mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->start_offset); ASM_ENTRY(emit->as, SIZEOF_NLR_BUF); // Put address of code_state into REG_GENERATOR_STATE #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 0, REG_GENERATOR_STATE); #else ASM_MOV_REG_REG(emit->as, REG_GENERATOR_STATE, REG_PARENT_ARG_1); #endif // Put throw value into LOCAL_IDX_EXC_VAL slot, for yield/yield-from #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2); #endif ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_PARENT_ARG_2); // Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, LOCAL_IDX_FUN_OBJ(emit)); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_OBJ_FUN_BC_CONST_TABLE); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_TEMP0, emit->scope->num_pos_args + emit->scope->num_kwonly_args); } else { // The locals and stack start after the code_state structure emit->stack_start = emit->code_state_start + SIZEOF_CODE_STATE; // Allocate space on C-stack for code_state structure, which includes state ASM_ENTRY(emit->as, emit->stack_start + emit->n_state); // Prepare incoming arguments for call to mp_setup_code_state #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1); asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2); asm_x86_mov_arg_to_r32(emit->as, 2, REG_PARENT_ARG_3); asm_x86_mov_arg_to_r32(emit->as, 3, REG_PARENT_ARG_4); #endif // Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_LOCAL_3, emit->scope->num_pos_args + emit->scope->num_kwonly_args); // Set code_state.fun_bc ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1); // Set code_state.ip (offset from start of this function to prelude info) #if N_PRELUDE_AS_BYTES_OBJ // Prelude is a bytes object in const_table; store ip = prelude->data - fun_bc->bytecode ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, emit->scope->num_pos_args + emit->scope->num_kwonly_args + 1); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, offsetof(mp_obj_str_t, data) / sizeof(uintptr_t)); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_PARENT_ARG_1, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_BYTECODE); ASM_SUB_REG_REG(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1); emit_native_mov_state_reg(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, REG_LOCAL_3); #else // TODO this encoding may change size in the final pass, need to make it fixed emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, emit->prelude_offset, REG_PARENT_ARG_1); #endif // Set code_state.n_state (only works on little endian targets due to n_state being uint16_t) emit_native_mov_state_imm_via(emit, emit->code_state_start + offsetof(mp_code_state_t, n_state) / sizeof(uintptr_t), emit->n_state, REG_ARG_1); // Put address of code_state into first arg ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, emit->code_state_start); // Copy next 3 args if needed #if REG_ARG_2 != REG_PARENT_ARG_2 ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_PARENT_ARG_2); #endif #if REG_ARG_3 != REG_PARENT_ARG_3 ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_PARENT_ARG_3); #endif #if REG_ARG_4 != REG_PARENT_ARG_4 ASM_MOV_REG_REG(emit->as, REG_ARG_4, REG_PARENT_ARG_4); #endif // Call mp_setup_code_state to prepare code_state structure #if N_THUMB asm_thumb_bl_ind(emit->as, MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4); #elif N_ARM asm_arm_bl_ind(emit->as, MP_F_SETUP_CODE_STATE, ASM_ARM_REG_R4); #else ASM_CALL_IND(emit->as, MP_F_SETUP_CODE_STATE); #endif } emit_native_global_exc_entry(emit); // cache some locals in registers, but only if no exception handlers if (CAN_USE_REGS_FOR_LOCALS(emit)) { for (int i = 0; i < REG_LOCAL_NUM && i < scope->num_locals; ++i) { ASM_MOV_REG_LOCAL(emit->as, reg_local_table[i], LOCAL_IDX_LOCAL_VAR(emit, i)); } } // set the type of closed over variables for (mp_uint_t i = 0; i < scope->id_info_len; i++) { id_info_t *id = &scope->id_info[i]; if (id->kind == ID_INFO_KIND_CELL) { emit->local_vtype[id->local_num] = VTYPE_PYOBJ; } } if (pass == MP_PASS_EMIT) { // write argument names as qstr objects // see comment in corresponding part of emitbc.c about the logic here for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) { qstr qst = MP_QSTR__star_; for (int j = 0; j < scope->id_info_len; ++j) { id_info_t *id = &scope->id_info[j]; if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) { qst = id->qst; break; } } emit->const_table[i] = (mp_uint_t)MP_OBJ_NEW_QSTR(qst); } } } } static inline void emit_native_write_code_info_byte(emit_t *emit, byte val) { mp_asm_base_data(&emit->as->base, 1, val); } STATIC void emit_native_end_pass(emit_t *emit) { emit_native_global_exc_exit(emit); if (!emit->do_viper_types) { emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base); size_t n_state = emit->n_state; size_t n_exc_stack = 0; // exc-stack not needed for native code MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, emit->scope, emit_native_write_code_info_byte, emit); #if MICROPY_PERSISTENT_CODE size_t n_info = 4; #else size_t n_info = 1; #endif MP_BC_PRELUDE_SIZE_ENCODE(n_info, emit->n_cell, emit_native_write_code_info_byte, emit); #if MICROPY_PERSISTENT_CODE mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name); mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name >> 8); mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file); mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file >> 8); #else mp_asm_base_data(&emit->as->base, 1, 1); #endif // bytecode prelude: initialise closed over variables size_t cell_start = mp_asm_base_get_code_pos(&emit->as->base); for (int i = 0; i < emit->scope->id_info_len; i++) { id_info_t *id = &emit->scope->id_info[i]; if (id->kind == ID_INFO_KIND_CELL) { assert(id->local_num <= 255); mp_asm_base_data(&emit->as->base, 1, id->local_num); // write the local which should be converted to a cell } } emit->n_cell = mp_asm_base_get_code_pos(&emit->as->base) - cell_start; #if N_PRELUDE_AS_BYTES_OBJ // Prelude bytes object is after qstr arg names and mp_fun_table size_t table_off = emit->scope->num_pos_args + emit->scope->num_kwonly_args + 1; if (emit->pass == MP_PASS_EMIT) { void *buf = emit->as->base.code_base + emit->prelude_offset; size_t n = emit->as->base.code_offset - emit->prelude_offset; emit->const_table[table_off] = (uintptr_t)mp_obj_new_bytes(buf, n); } #endif } ASM_END_PASS(emit->as); // check stack is back to zero size assert(emit->stack_size == 0); assert(emit->exc_stack_size == 0); // Deal with const table accounting assert(emit->pass <= MP_PASS_STACK_SIZE || (emit->const_table_num_obj == emit->const_table_cur_obj)); emit->const_table_num_obj = emit->const_table_cur_obj; if (emit->pass == MP_PASS_CODE_SIZE) { size_t const_table_alloc = 1 + emit->const_table_num_obj + emit->const_table_cur_raw_code; size_t nqstr = 0; if (!emit->do_viper_types) { // Add room for qstr names of arguments nqstr = emit->scope->num_pos_args + emit->scope->num_kwonly_args; const_table_alloc += nqstr; } emit->const_table = m_new(mp_uint_t, const_table_alloc); #if !MICROPY_DYNAMIC_COMPILER // Store mp_fun_table pointer just after qstrs // (but in dynamic-compiler mode eliminate dependency on mp_fun_table) emit->const_table[nqstr] = (mp_uint_t)(uintptr_t)&mp_fun_table; #endif #if MICROPY_PERSISTENT_CODE_SAVE size_t qstr_link_alloc = emit->qstr_link_cur; if (qstr_link_alloc > 0) { emit->qstr_link = m_new(mp_qstr_link_entry_t, qstr_link_alloc); } #endif } if (emit->pass == MP_PASS_EMIT) { void *f = mp_asm_base_get_code(&emit->as->base); mp_uint_t f_len = mp_asm_base_get_code_size(&emit->as->base); mp_emit_glue_assign_native(emit->scope->raw_code, emit->do_viper_types ? MP_CODE_NATIVE_VIPER : MP_CODE_NATIVE_PY, f, f_len, emit->const_table, #if MICROPY_PERSISTENT_CODE_SAVE emit->prelude_offset, emit->const_table_cur_obj, emit->const_table_cur_raw_code, emit->qstr_link_cur, emit->qstr_link, #endif emit->scope->num_pos_args, emit->scope->scope_flags, 0); } } STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) { return emit->last_emit_was_return_value; } STATIC void ensure_extra_stack(emit_t *emit, size_t delta) { if (emit->stack_size + delta > emit->stack_info_alloc) { size_t new_alloc = (emit->stack_size + delta + 8) & ~3; emit->stack_info = m_renew(stack_info_t, emit->stack_info, emit->stack_info_alloc, new_alloc); emit->stack_info_alloc = new_alloc; } } STATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) { assert((mp_int_t)emit->stack_size + stack_size_delta >= 0); assert((mp_int_t)emit->stack_size + stack_size_delta <= (mp_int_t)emit->stack_info_alloc); emit->stack_size += stack_size_delta; if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) { emit->scope->stack_size = emit->stack_size; } #ifdef DEBUG_PRINT DEBUG_printf(" adjust_stack; stack_size=%d+%d; stack now:", emit->stack_size - stack_size_delta, stack_size_delta); for (int i = 0; i < emit->stack_size; i++) { stack_info_t *si = &emit->stack_info[i]; DEBUG_printf(" (v=%d k=%d %d)", si->vtype, si->kind, si->data.u_reg); } DEBUG_printf("\n"); #endif } STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) { DEBUG_printf("adjust_stack_size(" INT_FMT ")\n", delta); if (delta > 0) { ensure_extra_stack(emit, delta); } // If we are adjusting the stack in a positive direction (pushing) then we // need to fill in values for the stack kind and vtype of the newly-pushed // entries. These should be set to "value" (ie not reg or imm) because we // should only need to adjust the stack due to a jump to this part in the // code (and hence we have settled the stack before the jump). for (mp_int_t i = 0; i < delta; i++) { stack_info_t *si = &emit->stack_info[emit->stack_size + i]; si->kind = STACK_VALUE; // TODO we don't know the vtype to use here. At the moment this is a // hack to get the case of multi comparison working. if (delta == 1) { si->vtype = emit->saved_stack_vtype; } else { si->vtype = VTYPE_PYOBJ; } } adjust_stack(emit, delta); } STATIC void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) { (void)emit; (void)source_line; } // this must be called at start of emit functions STATIC void emit_native_pre(emit_t *emit) { emit->last_emit_was_return_value = false; } // depth==0 is top, depth==1 is before top, etc STATIC stack_info_t *peek_stack(emit_t *emit, mp_uint_t depth) { return &emit->stack_info[emit->stack_size - 1 - depth]; } // depth==0 is top, depth==1 is before top, etc STATIC vtype_kind_t peek_vtype(emit_t *emit, mp_uint_t depth) { if (emit->do_viper_types) { return peek_stack(emit, depth)->vtype; } else { // Type is always PYOBJ even if the intermediate stored value is not return VTYPE_PYOBJ; } } // pos=1 is TOS, pos=2 is next, etc // use pos=0 for no skipping STATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) { skip_stack_pos = emit->stack_size - skip_stack_pos; for (int i = 0; i < emit->stack_size; i++) { if (i != skip_stack_pos) { stack_info_t *si = &emit->stack_info[i]; if (si->kind == STACK_REG && si->data.u_reg == reg_needed) { si->kind = STACK_VALUE; emit_native_mov_state_reg(emit, emit->stack_start + i, si->data.u_reg); } } } } STATIC void need_reg_all(emit_t *emit) { for (int i = 0; i < emit->stack_size; i++) { stack_info_t *si = &emit->stack_info[i]; if (si->kind == STACK_REG) { si->kind = STACK_VALUE; emit_native_mov_state_reg(emit, emit->stack_start + i, si->data.u_reg); } } } STATIC vtype_kind_t load_reg_stack_imm(emit_t *emit, int reg_dest, const stack_info_t *si, bool convert_to_pyobj) { if (!convert_to_pyobj && emit->do_viper_types) { ASM_MOV_REG_IMM(emit->as, reg_dest, si->data.u_imm); return si->vtype; } else { if (si->vtype == VTYPE_PYOBJ) { ASM_MOV_REG_IMM(emit->as, reg_dest, si->data.u_imm); } else if (si->vtype == VTYPE_BOOL) { emit_native_mov_reg_const(emit, reg_dest, MP_F_CONST_FALSE_OBJ + si->data.u_imm); } else if (si->vtype == VTYPE_INT || si->vtype == VTYPE_UINT) { ASM_MOV_REG_IMM(emit->as, reg_dest, (uintptr_t)MP_OBJ_NEW_SMALL_INT(si->data.u_imm)); } else if (si->vtype == VTYPE_PTR_NONE) { emit_native_mov_reg_const(emit, reg_dest, MP_F_CONST_NONE_OBJ); } else { mp_raise_NotImplementedError("conversion to object"); } return VTYPE_PYOBJ; } } STATIC void need_stack_settled(emit_t *emit) { DEBUG_printf(" need_stack_settled; stack_size=%d\n", emit->stack_size); for (int i = 0; i < emit->stack_size; i++) { stack_info_t *si = &emit->stack_info[i]; if (si->kind == STACK_REG) { DEBUG_printf(" reg(%u) to local(%u)\n", si->data.u_reg, emit->stack_start + i); si->kind = STACK_VALUE; emit_native_mov_state_reg(emit, emit->stack_start + i, si->data.u_reg); } } for (int i = 0; i < emit->stack_size; i++) { stack_info_t *si = &emit->stack_info[i]; if (si->kind == STACK_IMM) { DEBUG_printf(" imm(" INT_FMT ") to local(%u)\n", si->data.u_imm, emit->stack_start + i); si->kind = STACK_VALUE; si->vtype = load_reg_stack_imm(emit, REG_TEMP0, si, false); emit_native_mov_state_reg(emit, emit->stack_start + i, REG_TEMP0); } } } // pos=1 is TOS, pos=2 is next, etc STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int reg_dest) { need_reg_single(emit, reg_dest, pos); stack_info_t *si = &emit->stack_info[emit->stack_size - pos]; *vtype = si->vtype; switch (si->kind) { case STACK_VALUE: emit_native_mov_reg_state(emit, reg_dest, emit->stack_start + emit->stack_size - pos); break; case STACK_REG: if (si->data.u_reg != reg_dest) { ASM_MOV_REG_REG(emit->as, reg_dest, si->data.u_reg); } break; case STACK_IMM: *vtype = load_reg_stack_imm(emit, reg_dest, si, false); break; } } // does an efficient X=pop(); discard(); push(X) // needs a (non-temp) register in case the poped element was stored in the stack STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) { stack_info_t *si = &emit->stack_info[emit->stack_size - 2]; si[0] = si[1]; if (si->kind == STACK_VALUE) { // if folded element was on the stack we need to put it in a register emit_native_mov_reg_state(emit, reg_dest, emit->stack_start + emit->stack_size - 1); si->kind = STACK_REG; si->data.u_reg = reg_dest; } adjust_stack(emit, -1); } // If stacked value is in a register and the register is not r1 or r2, then // *reg_dest is set to that register. Otherwise the value is put in *reg_dest. STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest, int not_r1, int not_r2) { emit->last_emit_was_return_value = false; stack_info_t *si = peek_stack(emit, 0); if (si->kind == STACK_REG && si->data.u_reg != not_r1 && si->data.u_reg != not_r2) { *vtype = si->vtype; *reg_dest = si->data.u_reg; need_reg_single(emit, *reg_dest, 1); } else { emit_access_stack(emit, 1, vtype, *reg_dest); } adjust_stack(emit, -1); } STATIC void emit_pre_pop_discard(emit_t *emit) { emit->last_emit_was_return_value = false; adjust_stack(emit, -1); } STATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) { emit->last_emit_was_return_value = false; emit_access_stack(emit, 1, vtype, reg_dest); adjust_stack(emit, -1); } STATIC void emit_pre_pop_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb) { emit_pre_pop_reg(emit, vtypea, rega); emit_pre_pop_reg(emit, vtypeb, regb); } STATIC void emit_pre_pop_reg_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb, vtype_kind_t *vtypec, int regc) { emit_pre_pop_reg(emit, vtypea, rega); emit_pre_pop_reg(emit, vtypeb, regb); emit_pre_pop_reg(emit, vtypec, regc); } STATIC void emit_post(emit_t *emit) { (void)emit; } STATIC void emit_post_top_set_vtype(emit_t *emit, vtype_kind_t new_vtype) { stack_info_t *si = &emit->stack_info[emit->stack_size - 1]; si->vtype = new_vtype; } STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) { ensure_extra_stack(emit, 1); stack_info_t *si = &emit->stack_info[emit->stack_size]; si->vtype = vtype; si->kind = STACK_REG; si->data.u_reg = reg; adjust_stack(emit, 1); } STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) { ensure_extra_stack(emit, 1); stack_info_t *si = &emit->stack_info[emit->stack_size]; si->vtype = vtype; si->kind = STACK_IMM; si->data.u_imm = imm; adjust_stack(emit, 1); } STATIC void emit_post_push_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb) { emit_post_push_reg(emit, vtypea, rega); emit_post_push_reg(emit, vtypeb, regb); } STATIC void emit_post_push_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc) { emit_post_push_reg(emit, vtypea, rega); emit_post_push_reg(emit, vtypeb, regb); emit_post_push_reg(emit, vtypec, regc); } STATIC void emit_post_push_reg_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc, vtype_kind_t vtyped, int regd) { emit_post_push_reg(emit, vtypea, rega); emit_post_push_reg(emit, vtypeb, regb); emit_post_push_reg(emit, vtypec, regc); emit_post_push_reg(emit, vtyped, regd); } STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind) { need_reg_all(emit); ASM_CALL_IND(emit->as, fun_kind); } STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) { need_reg_all(emit); ASM_MOV_REG_IMM(emit->as, arg_reg, arg_val); ASM_CALL_IND(emit->as, fun_kind); } STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) { need_reg_all(emit); ASM_MOV_REG_IMM(emit->as, arg_reg1, arg_val1); ASM_MOV_REG_IMM(emit->as, arg_reg2, arg_val2); ASM_CALL_IND(emit->as, fun_kind); } STATIC void emit_call_with_qstr_arg(emit_t *emit, mp_fun_kind_t fun_kind, qstr qst, int arg_reg) { need_reg_all(emit); emit_native_mov_reg_qstr(emit, arg_reg, qst); ASM_CALL_IND(emit->as, fun_kind); } // vtype of all n_pop objects is VTYPE_PYOBJ // Will convert any items that are not VTYPE_PYOBJ to this type and put them back on the stack. // If any conversions of non-immediate values are needed, then it uses REG_ARG_1, REG_ARG_2 and REG_RET. // Otherwise, it does not use any temporary registers (but may use reg_dest before loading it with stack pointer). STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_pop) { need_reg_all(emit); // First, store any immediate values to their respective place on the stack. for (mp_uint_t i = 0; i < n_pop; i++) { stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i]; // must push any imm's to stack // must convert them to VTYPE_PYOBJ for viper code if (si->kind == STACK_IMM) { si->kind = STACK_VALUE; si->vtype = load_reg_stack_imm(emit, reg_dest, si, true); emit_native_mov_state_reg(emit, emit->stack_start + emit->stack_size - 1 - i, reg_dest); } // verify that this value is on the stack assert(si->kind == STACK_VALUE); } // Second, convert any non-VTYPE_PYOBJ to that type. for (mp_uint_t i = 0; i < n_pop; i++) { stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i]; if (si->vtype != VTYPE_PYOBJ) { mp_uint_t local_num = emit->stack_start + emit->stack_size - 1 - i; emit_native_mov_reg_state(emit, REG_ARG_1, local_num); emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, si->vtype, REG_ARG_2); // arg2 = type emit_native_mov_state_reg(emit, local_num, REG_RET); si->vtype = VTYPE_PYOBJ; DEBUG_printf(" convert_native_to_obj(local_num=" UINT_FMT ")\n", local_num); } } // Adujust the stack for a pop of n_pop items, and load the stack pointer into reg_dest. adjust_stack(emit, -n_pop); emit_native_mov_reg_state_addr(emit, reg_dest, emit->stack_start + emit->stack_size); } // vtype of all n_push objects is VTYPE_PYOBJ STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_push) { need_reg_all(emit); ensure_extra_stack(emit, n_push); for (mp_uint_t i = 0; i < n_push; i++) { emit->stack_info[emit->stack_size + i].kind = STACK_VALUE; emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ; } emit_native_mov_reg_state_addr(emit, reg_dest, emit->stack_start + emit->stack_size); adjust_stack(emit, n_push); } STATIC void emit_native_push_exc_stack(emit_t *emit, uint label, bool is_finally) { if (emit->exc_stack_size + 1 > emit->exc_stack_alloc) { size_t new_alloc = emit->exc_stack_alloc + 4; emit->exc_stack = m_renew(exc_stack_entry_t, emit->exc_stack, emit->exc_stack_alloc, new_alloc); emit->exc_stack_alloc = new_alloc; } exc_stack_entry_t *e = &emit->exc_stack[emit->exc_stack_size++]; e->label = label; e->is_finally = is_finally; e->unwind_label = UNWIND_LABEL_UNUSED; e->is_active = true; ASM_MOV_REG_PCREL(emit->as, REG_RET, label); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_RET); } STATIC void emit_native_leave_exc_stack(emit_t *emit, bool start_of_handler) { assert(emit->exc_stack_size > 0); // Get current exception handler and deactivate it exc_stack_entry_t *e = &emit->exc_stack[emit->exc_stack_size - 1]; e->is_active = false; // Find next innermost active exception handler, to restore as current handler for (--e; e >= emit->exc_stack && !e->is_active; --e) { } // Update the PC of the new exception handler if (e < emit->exc_stack) { // No active handler, clear handler PC to zero if (start_of_handler) { // Optimisation: PC is already cleared by global exc handler return; } ASM_XOR_REG_REG(emit->as, REG_RET, REG_RET); } else { // Found new active handler, get its PC ASM_MOV_REG_PCREL(emit->as, REG_RET, e->label); } ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_RET); } STATIC exc_stack_entry_t *emit_native_pop_exc_stack(emit_t *emit) { assert(emit->exc_stack_size > 0); exc_stack_entry_t *e = &emit->exc_stack[--emit->exc_stack_size]; assert(e->is_active == false); return e; } STATIC void emit_load_reg_with_ptr(emit_t *emit, int reg, mp_uint_t ptr, size_t table_off) { if (!emit->do_viper_types) { // Skip qstr names of arguments table_off += emit->scope->num_pos_args + emit->scope->num_kwonly_args; } if (emit->pass == MP_PASS_EMIT) { emit->const_table[table_off] = ptr; } emit_native_mov_reg_state(emit, REG_TEMP0, LOCAL_IDX_FUN_OBJ(emit)); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_OBJ_FUN_BC_CONST_TABLE); ASM_LOAD_REG_REG_OFFSET(emit->as, reg, REG_TEMP0, table_off); } STATIC void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj) { // First entry is for mp_fun_table size_t table_off = 1 + emit->const_table_cur_obj++; emit_load_reg_with_ptr(emit, reg, (mp_uint_t)obj, table_off); } STATIC void emit_load_reg_with_raw_code(emit_t *emit, int reg, mp_raw_code_t *rc) { // First entry is for mp_fun_table, then constant objects size_t table_off = 1 + emit->const_table_num_obj + emit->const_table_cur_raw_code++; emit_load_reg_with_ptr(emit, reg, (mp_uint_t)rc, table_off); } STATIC void emit_native_label_assign(emit_t *emit, mp_uint_t l) { DEBUG_printf("label_assign(" UINT_FMT ")\n", l); bool is_finally = false; if (emit->exc_stack_size > 0) { exc_stack_entry_t *e = &emit->exc_stack[emit->exc_stack_size - 1]; is_finally = e->is_finally && e->label == l; } if (is_finally) { // Label is at start of finally handler: store TOS into exception slot vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_TEMP0); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); } emit_native_pre(emit); // need to commit stack because we can jump here from elsewhere need_stack_settled(emit); mp_asm_base_label_assign(&emit->as->base, l); emit_post(emit); if (is_finally) { // Label is at start of finally handler: pop exception stack emit_native_leave_exc_stack(emit, false); } } STATIC void emit_native_global_exc_entry(emit_t *emit) { // Note: 4 labels are reserved for this function, starting at *emit->label_slot emit->exit_label = *emit->label_slot; if (NEED_GLOBAL_EXC_HANDLER(emit)) { mp_uint_t nlr_label = *emit->label_slot + 1; mp_uint_t start_label = *emit->label_slot + 2; mp_uint_t global_except_label = *emit->label_slot + 3; if (!(emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR)) { // Set new globals emit_native_mov_reg_state(emit, REG_ARG_1, LOCAL_IDX_FUN_OBJ(emit)); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_ARG_1, REG_ARG_1, OFFSETOF_OBJ_FUN_BC_GLOBALS); emit_call(emit, MP_F_NATIVE_SWAP_GLOBALS); // Save old globals (or NULL if globals didn't change) emit_native_mov_state_reg(emit, LOCAL_IDX_OLD_GLOBALS(emit), REG_RET); } if (emit->scope->exc_stack_size == 0) { if (!(emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR)) { // Optimisation: if globals didn't change don't push the nlr context ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, start_label, false); } // Wrap everything in an nlr context ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 0); emit_call(emit, MP_F_NLR_PUSH); #if N_NLR_SETJMP ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 2); emit_call(emit, MP_F_SETJMP); #endif ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, start_label, true); } else { // Clear the unwind state ASM_XOR_REG_REG(emit->as, REG_TEMP0, REG_TEMP0); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_TEMP0); // Put PC of start code block into REG_LOCAL_1 ASM_MOV_REG_PCREL(emit->as, REG_LOCAL_1, start_label); // Wrap everything in an nlr context emit_native_label_assign(emit, nlr_label); ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_2, LOCAL_IDX_EXC_HANDLER_UNWIND(emit)); ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 0); emit_call(emit, MP_F_NLR_PUSH); #if N_NLR_SETJMP ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 2); emit_call(emit, MP_F_SETJMP); #endif ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_LOCAL_2); ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, global_except_label, true); // Clear PC of current code block, and jump there to resume execution ASM_XOR_REG_REG(emit->as, REG_TEMP0, REG_TEMP0); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_TEMP0); ASM_JUMP_REG(emit->as, REG_LOCAL_1); // Global exception handler: check for valid exception handler emit_native_label_assign(emit, global_except_label); #if N_NLR_SETJMP // Reload REG_FUN_TABLE, since it may be clobbered by longjmp emit_native_mov_reg_state(emit, REG_LOCAL_1, LOCAL_IDX_FUN_OBJ(emit)); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_1, REG_LOCAL_1, offsetof(mp_obj_fun_bc_t, const_table) / sizeof(uintptr_t)); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_LOCAL_1, emit->scope->num_pos_args + emit->scope->num_kwonly_args); #endif ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_1, LOCAL_IDX_EXC_HANDLER_PC(emit)); ASM_JUMP_IF_REG_NONZERO(emit->as, REG_LOCAL_1, nlr_label, false); } if (!(emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR)) { // Restore old globals emit_native_mov_reg_state(emit, REG_ARG_1, LOCAL_IDX_OLD_GLOBALS(emit)); emit_call(emit, MP_F_NATIVE_SWAP_GLOBALS); } if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { // Store return value in state[0] ASM_MOV_REG_LOCAL(emit->as, REG_TEMP0, LOCAL_IDX_EXC_VAL(emit)); ASM_STORE_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, OFFSETOF_CODE_STATE_STATE); // Load return kind ASM_MOV_REG_IMM(emit->as, REG_PARENT_RET, MP_VM_RETURN_EXCEPTION); ASM_EXIT(emit->as); } else { // Re-raise exception out to caller ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); emit_call(emit, MP_F_NATIVE_RAISE); } // Label for start of function emit_native_label_assign(emit, start_label); if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { emit_native_mov_reg_state(emit, REG_TEMP0, LOCAL_IDX_GEN_PC(emit)); ASM_JUMP_REG(emit->as, REG_TEMP0); emit->start_offset = mp_asm_base_get_code_pos(&emit->as->base); // This is the first entry of the generator // Check LOCAL_IDX_EXC_VAL for any injected value ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); emit_call(emit, MP_F_NATIVE_RAISE); } } } STATIC void emit_native_global_exc_exit(emit_t *emit) { // Label for end of function emit_native_label_assign(emit, emit->exit_label); if (NEED_GLOBAL_EXC_HANDLER(emit)) { // Get old globals if (!(emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR)) { emit_native_mov_reg_state(emit, REG_ARG_1, LOCAL_IDX_OLD_GLOBALS(emit)); if (emit->scope->exc_stack_size == 0) { // Optimisation: if globals didn't change then don't restore them and don't do nlr_pop ASM_JUMP_IF_REG_ZERO(emit->as, REG_ARG_1, emit->exit_label + 1, false); } // Restore old globals emit_call(emit, MP_F_NATIVE_SWAP_GLOBALS); } // Pop the nlr context emit_call(emit, MP_F_NLR_POP); if (!(emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR)) { if (emit->scope->exc_stack_size == 0) { // Destination label for above optimisation emit_native_label_assign(emit, emit->exit_label + 1); } } // Load return value ASM_MOV_REG_LOCAL(emit->as, REG_PARENT_RET, LOCAL_IDX_RET_VAL(emit)); } ASM_EXIT(emit->as); } STATIC void emit_native_import_name(emit_t *emit, qstr qst) { DEBUG_printf("import_name %s\n", qstr_str(qst)); // get arguments from stack: arg2 = fromlist, arg3 = level // If using viper types these arguments must be converted to proper objects, and // to accomplish this viper types are turned off for the emit_pre_pop_reg_reg call. bool orig_do_viper_types = emit->do_viper_types; emit->do_viper_types = false; vtype_kind_t vtype_fromlist; vtype_kind_t vtype_level; emit_pre_pop_reg_reg(emit, &vtype_fromlist, REG_ARG_2, &vtype_level, REG_ARG_3); assert(vtype_fromlist == VTYPE_PYOBJ); assert(vtype_level == VTYPE_PYOBJ); emit->do_viper_types = orig_do_viper_types; emit_call_with_qstr_arg(emit, MP_F_IMPORT_NAME, qst, REG_ARG_1); // arg1 = import name emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_import_from(emit_t *emit, qstr qst) { DEBUG_printf("import_from %s\n", qstr_str(qst)); emit_native_pre(emit); vtype_kind_t vtype_module; emit_access_stack(emit, 1, &vtype_module, REG_ARG_1); // arg1 = module assert(vtype_module == VTYPE_PYOBJ); emit_call_with_qstr_arg(emit, MP_F_IMPORT_FROM, qst, REG_ARG_2); // arg2 = import name emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_import_star(emit_t *emit) { DEBUG_printf("import_star\n"); vtype_kind_t vtype_module; emit_pre_pop_reg(emit, &vtype_module, REG_ARG_1); // arg1 = module assert(vtype_module == VTYPE_PYOBJ); emit_call(emit, MP_F_IMPORT_ALL); emit_post(emit); } STATIC void emit_native_import(emit_t *emit, qstr qst, int kind) { if (kind == MP_EMIT_IMPORT_NAME) { emit_native_import_name(emit, qst); } else if (kind == MP_EMIT_IMPORT_FROM) { emit_native_import_from(emit, qst); } else { emit_native_import_star(emit); } } STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) { DEBUG_printf("load_const_tok(tok=%u)\n", tok); if (tok == MP_TOKEN_ELLIPSIS) { #if MICROPY_PERSISTENT_CODE_SAVE emit_native_load_const_obj(emit, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); #else emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); #endif } else { emit_native_pre(emit); if (tok == MP_TOKEN_KW_NONE) { emit_post_push_imm(emit, VTYPE_PTR_NONE, 0); } else { emit_post_push_imm(emit, VTYPE_BOOL, tok == MP_TOKEN_KW_FALSE ? 0 : 1); } } } STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) { DEBUG_printf("load_const_small_int(int=" INT_FMT ")\n", arg); emit_native_pre(emit); emit_post_push_imm(emit, VTYPE_INT, arg); } STATIC void emit_native_load_const_str(emit_t *emit, qstr qst) { emit_native_pre(emit); // TODO: Eventually we want to be able to work with raw pointers in viper to // do native array access. For now we just load them as any other object. /* if (emit->do_viper_types) { // load a pointer to the asciiz string? emit_post_push_imm(emit, VTYPE_PTR, (mp_uint_t)qstr_str(qst)); } else */ { need_reg_single(emit, REG_TEMP0, 0); emit_native_mov_reg_qstr_obj(emit, REG_TEMP0, qst); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_TEMP0); } } STATIC void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj) { emit->scope->scope_flags |= MP_SCOPE_FLAG_HASCONSTS; emit_native_pre(emit); need_reg_single(emit, REG_RET, 0); emit_load_reg_with_object(emit, REG_RET, obj); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_load_null(emit_t *emit) { emit_native_pre(emit); emit_post_push_imm(emit, VTYPE_PYOBJ, 0); } STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { DEBUG_printf("load_fast(%s, " UINT_FMT ")\n", qstr_str(qst), local_num); vtype_kind_t vtype = emit->local_vtype[local_num]; if (vtype == VTYPE_UNBOUND) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "local '%q' used before type known", qst); } emit_native_pre(emit); if (local_num < REG_LOCAL_NUM && CAN_USE_REGS_FOR_LOCALS(emit)) { emit_post_push_reg(emit, vtype, reg_local_table[local_num]); } else { need_reg_single(emit, REG_TEMP0, 0); emit_native_mov_reg_state(emit, REG_TEMP0, LOCAL_IDX_LOCAL_VAR(emit, local_num)); emit_post_push_reg(emit, vtype, REG_TEMP0); } } STATIC void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { DEBUG_printf("load_deref(%s, " UINT_FMT ")\n", qstr_str(qst), local_num); need_reg_single(emit, REG_RET, 0); emit_native_load_fast(emit, qst, local_num); vtype_kind_t vtype; int reg_base = REG_RET; emit_pre_pop_reg_flexible(emit, &vtype, ®_base, -1, -1); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_RET, reg_base, 1); // closed over vars are always Python objects emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { if (kind == MP_EMIT_IDOP_LOCAL_FAST) { emit_native_load_fast(emit, qst, local_num); } else { emit_native_load_deref(emit, qst, local_num); } } STATIC void emit_native_load_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_F_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_F_LOAD_NAME); MP_STATIC_ASSERT(MP_F_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_F_LOAD_GLOBAL); emit_native_pre(emit); if (kind == MP_EMIT_IDOP_GLOBAL_NAME) { DEBUG_printf("load_name(%s)\n", qstr_str(qst)); } else { DEBUG_printf("load_global(%s)\n", qstr_str(qst)); if (emit->do_viper_types) { // check for builtin casting operators int native_type = mp_native_type_from_qstr(qst); if (native_type >= MP_NATIVE_TYPE_BOOL) { emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, native_type); return; } } } emit_call_with_qstr_arg(emit, MP_F_LOAD_NAME + kind, qst, REG_ARG_1); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_load_attr(emit_t *emit, qstr qst) { // depends on type of subject: // - integer, function, pointer to integers: error // - pointer to structure: get member, quite easy // - Python object: call mp_load_attr, and needs to be typed to convert result vtype_kind_t vtype_base; emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base assert(vtype_base == VTYPE_PYOBJ); emit_call_with_qstr_arg(emit, MP_F_LOAD_ATTR, qst, REG_ARG_2); // arg2 = attribute name emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_load_method(emit_t *emit, qstr qst, bool is_super) { if (is_super) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, 3); // arg2 = dest ptr emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, 2); // arg2 = dest ptr emit_call_with_qstr_arg(emit, MP_F_LOAD_SUPER_METHOD, qst, REG_ARG_1); // arg1 = method name } else { vtype_kind_t vtype_base; emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base assert(vtype_base == VTYPE_PYOBJ); emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr emit_call_with_qstr_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name } } STATIC void emit_native_load_build_class(emit_t *emit) { emit_native_pre(emit); emit_call(emit, MP_F_LOAD_BUILD_CLASS); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_load_subscr(emit_t *emit) { DEBUG_printf("load_subscr\n"); // need to compile: base[index] // pop: index, base // optimise case where index is an immediate vtype_kind_t vtype_base = peek_vtype(emit, 1); if (vtype_base == VTYPE_PYOBJ) { // standard Python subscr // TODO factor this implicit cast code with other uses of it vtype_kind_t vtype_index = peek_vtype(emit, 0); if (vtype_index == VTYPE_PYOBJ) { emit_pre_pop_reg(emit, &vtype_index, REG_ARG_2); } else { emit_pre_pop_reg(emit, &vtype_index, REG_ARG_1); emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype_index, REG_ARG_2); // arg2 = type ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET); } emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_SENTINEL, REG_ARG_3); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { // viper load // TODO The different machine architectures have very different // capabilities and requirements for loads, so probably best to // write a completely separate load-optimiser for each one. stack_info_t *top = peek_stack(emit, 0); if (top->vtype == VTYPE_INT && top->kind == STACK_IMM) { // index is an immediate mp_int_t index_value = top->data.u_imm; emit_pre_pop_discard(emit); // discard index int reg_base = REG_ARG_1; int reg_index = REG_ARG_2; emit_pre_pop_reg_flexible(emit, &vtype_base, ®_base, reg_index, reg_index); switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory // TODO optimise to use thumb ldrb r1, [r2, r3] if (index_value != 0) { // index is non-zero #if N_THUMB if (index_value > 0 && index_value < 32) { asm_thumb_ldrb_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); break; } #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; } ASM_LOAD8_REG_REG(emit->as, REG_RET, reg_base); // load from (base+index) break; } case VTYPE_PTR16: { // pointer to 16-bit memory if (index_value != 0) { // index is a non-zero immediate #if N_THUMB if (index_value > 0 && index_value < 32) { asm_thumb_ldrh_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); break; } #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; } ASM_LOAD16_REG_REG(emit->as, REG_RET, reg_base); // load from (base+2*index) break; } case VTYPE_PTR32: { // pointer to 32-bit memory if (index_value != 0) { // index is a non-zero immediate #if N_THUMB if (index_value > 0 && index_value < 32) { asm_thumb_ldr_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); break; } #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base reg_base = reg_index; } ASM_LOAD32_REG_REG(emit->as, REG_RET, reg_base); // load from (base+4*index) break; } default: EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't load from '%q'", vtype_to_qstr(vtype_base)); } } else { // index is not an immediate vtype_kind_t vtype_index; int reg_index = REG_ARG_2; emit_pre_pop_reg_flexible(emit, &vtype_index, ®_index, REG_ARG_1, REG_ARG_1); emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); if (vtype_index != VTYPE_INT && vtype_index != VTYPE_UINT) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't load with '%q' index", vtype_to_qstr(vtype_index)); } switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory // TODO optimise to use thumb ldrb r1, [r2, r3] ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD8_REG_REG(emit->as, REG_RET, REG_ARG_1); // store value to (base+index) break; } case VTYPE_PTR16: { // pointer to 16-bit memory ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD16_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+2*index) break; } case VTYPE_PTR32: { // pointer to word-size memory ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD32_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+4*index) break; } default: EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't load from '%q'", vtype_to_qstr(vtype_base)); } } emit_post_push_reg(emit, VTYPE_INT, REG_RET); } } STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { vtype_kind_t vtype; if (local_num < REG_LOCAL_NUM && CAN_USE_REGS_FOR_LOCALS(emit)) { emit_pre_pop_reg(emit, &vtype, reg_local_table[local_num]); } else { emit_pre_pop_reg(emit, &vtype, REG_TEMP0); emit_native_mov_state_reg(emit, LOCAL_IDX_LOCAL_VAR(emit, local_num), REG_TEMP0); } emit_post(emit); // check types if (emit->local_vtype[local_num] == VTYPE_UNBOUND) { // first time this local is assigned, so give it a type of the object stored in it emit->local_vtype[local_num] = vtype; } else if (emit->local_vtype[local_num] != vtype) { // type of local is not the same as object stored in it EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "local '%q' has type '%q' but source is '%q'", qst, vtype_to_qstr(emit->local_vtype[local_num]), vtype_to_qstr(vtype)); } } STATIC void emit_native_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { DEBUG_printf("store_deref(%s, " UINT_FMT ")\n", qstr_str(qst), local_num); need_reg_single(emit, REG_TEMP0, 0); need_reg_single(emit, REG_TEMP1, 0); emit_native_load_fast(emit, qst, local_num); vtype_kind_t vtype; int reg_base = REG_TEMP0; emit_pre_pop_reg_flexible(emit, &vtype, ®_base, -1, -1); int reg_src = REG_TEMP1; emit_pre_pop_reg_flexible(emit, &vtype, ®_src, reg_base, reg_base); ASM_STORE_REG_REG_OFFSET(emit->as, reg_src, reg_base, 1); emit_post(emit); } STATIC void emit_native_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { if (kind == MP_EMIT_IDOP_LOCAL_FAST) { emit_native_store_fast(emit, qst, local_num); } else { emit_native_store_deref(emit, qst, local_num); } } STATIC void emit_native_store_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_F_STORE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_F_STORE_NAME); MP_STATIC_ASSERT(MP_F_STORE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_F_STORE_GLOBAL); if (kind == MP_EMIT_IDOP_GLOBAL_NAME) { // mp_store_name, but needs conversion of object (maybe have mp_viper_store_name(obj, type)) vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_2); assert(vtype == VTYPE_PYOBJ); } else { vtype_kind_t vtype = peek_vtype(emit, 0); if (vtype == VTYPE_PYOBJ) { emit_pre_pop_reg(emit, &vtype, REG_ARG_2); } else { emit_pre_pop_reg(emit, &vtype, REG_ARG_1); emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype, REG_ARG_2); // arg2 = type ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET); } } emit_call_with_qstr_arg(emit, MP_F_STORE_NAME + kind, qst, REG_ARG_1); // arg1 = name emit_post(emit); } STATIC void emit_native_store_attr(emit_t *emit, qstr qst) { vtype_kind_t vtype_base, vtype_val; emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value assert(vtype_base == VTYPE_PYOBJ); assert(vtype_val == VTYPE_PYOBJ); emit_call_with_qstr_arg(emit, MP_F_STORE_ATTR, qst, REG_ARG_2); // arg2 = attribute name emit_post(emit); } STATIC void emit_native_store_subscr(emit_t *emit) { DEBUG_printf("store_subscr\n"); // need to compile: base[index] = value // pop: index, base, value // optimise case where index is an immediate vtype_kind_t vtype_base = peek_vtype(emit, 1); if (vtype_base == VTYPE_PYOBJ) { // standard Python subscr vtype_kind_t vtype_index = peek_vtype(emit, 0); vtype_kind_t vtype_value = peek_vtype(emit, 2); if (vtype_index != VTYPE_PYOBJ || vtype_value != VTYPE_PYOBJ) { // need to implicitly convert non-objects to objects // TODO do this properly emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, 3); adjust_stack(emit, 3); } emit_pre_pop_reg_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1, &vtype_value, REG_ARG_3); emit_call(emit, MP_F_OBJ_SUBSCR); } else { // viper store // TODO The different machine architectures have very different // capabilities and requirements for stores, so probably best to // write a completely separate store-optimiser for each one. stack_info_t *top = peek_stack(emit, 0); if (top->vtype == VTYPE_INT && top->kind == STACK_IMM) { // index is an immediate mp_int_t index_value = top->data.u_imm; emit_pre_pop_discard(emit); // discard index vtype_kind_t vtype_value; int reg_base = REG_ARG_1; int reg_index = REG_ARG_2; int reg_value = REG_ARG_3; emit_pre_pop_reg_flexible(emit, &vtype_base, ®_base, reg_index, reg_value); #if N_X86 // special case: x86 needs byte stores to be from lower 4 regs (REG_ARG_3 is EDX) emit_pre_pop_reg(emit, &vtype_value, reg_value); #else emit_pre_pop_reg_flexible(emit, &vtype_value, ®_value, reg_base, reg_index); #endif if (vtype_value != VTYPE_BOOL && vtype_value != VTYPE_INT && vtype_value != VTYPE_UINT) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't store '%q'", vtype_to_qstr(vtype_value)); } switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory // TODO optimise to use thumb strb r1, [r2, r3] if (index_value != 0) { // index is non-zero #if N_THUMB if (index_value > 0 && index_value < 32) { asm_thumb_strb_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); break; } #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value); #if N_ARM asm_arm_strb_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); return; #endif ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; } ASM_STORE8_REG_REG(emit->as, reg_value, reg_base); // store value to (base+index) break; } case VTYPE_PTR16: { // pointer to 16-bit memory if (index_value != 0) { // index is a non-zero immediate #if N_THUMB if (index_value > 0 && index_value < 32) { asm_thumb_strh_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); break; } #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; } ASM_STORE16_REG_REG(emit->as, reg_value, reg_base); // store value to (base+2*index) break; } case VTYPE_PTR32: { // pointer to 32-bit memory if (index_value != 0) { // index is a non-zero immediate #if N_THUMB if (index_value > 0 && index_value < 32) { asm_thumb_str_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); break; } #endif #if N_ARM ASM_MOV_REG_IMM(emit->as, reg_index, index_value); asm_arm_str_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); return; #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base reg_base = reg_index; } ASM_STORE32_REG_REG(emit->as, reg_value, reg_base); // store value to (base+4*index) break; } default: EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't store to '%q'", vtype_to_qstr(vtype_base)); } } else { // index is not an immediate vtype_kind_t vtype_index, vtype_value; int reg_index = REG_ARG_2; int reg_value = REG_ARG_3; emit_pre_pop_reg_flexible(emit, &vtype_index, ®_index, REG_ARG_1, reg_value); emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); if (vtype_index != VTYPE_INT && vtype_index != VTYPE_UINT) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't store with '%q' index", vtype_to_qstr(vtype_index)); } #if N_X86 // special case: x86 needs byte stores to be from lower 4 regs (REG_ARG_3 is EDX) emit_pre_pop_reg(emit, &vtype_value, reg_value); #else emit_pre_pop_reg_flexible(emit, &vtype_value, ®_value, REG_ARG_1, reg_index); #endif if (vtype_value != VTYPE_BOOL && vtype_value != VTYPE_INT && vtype_value != VTYPE_UINT) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't store '%q'", vtype_to_qstr(vtype_value)); } switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory // TODO optimise to use thumb strb r1, [r2, r3] #if N_ARM asm_arm_strb_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); break; #endif ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE8_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+index) break; } case VTYPE_PTR16: { // pointer to 16-bit memory #if N_ARM asm_arm_strh_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); break; #endif ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE16_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+2*index) break; } case VTYPE_PTR32: { // pointer to 32-bit memory #if N_ARM asm_arm_str_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); break; #endif ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE32_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+4*index) break; } default: EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't store to '%q'", vtype_to_qstr(vtype_base)); } } } } STATIC void emit_native_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { if (kind == MP_EMIT_IDOP_LOCAL_FAST) { // TODO: This is not compliant implementation. We could use MP_OBJ_SENTINEL // to mark deleted vars but then every var would need to be checked on // each access. Very inefficient, so just set value to None to enable GC. emit_native_load_const_tok(emit, MP_TOKEN_KW_NONE); emit_native_store_fast(emit, qst, local_num); } else { // TODO implement me! } } STATIC void emit_native_delete_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_F_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_F_DELETE_NAME); MP_STATIC_ASSERT(MP_F_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_F_DELETE_GLOBAL); emit_native_pre(emit); emit_call_with_qstr_arg(emit, MP_F_DELETE_NAME + kind, qst, REG_ARG_1); emit_post(emit); } STATIC void emit_native_delete_attr(emit_t *emit, qstr qst) { vtype_kind_t vtype_base; emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base assert(vtype_base == VTYPE_PYOBJ); ASM_XOR_REG_REG(emit->as, REG_ARG_3, REG_ARG_3); // arg3 = value (null for delete) emit_call_with_qstr_arg(emit, MP_F_STORE_ATTR, qst, REG_ARG_2); // arg2 = attribute name emit_post(emit); } STATIC void emit_native_delete_subscr(emit_t *emit) { vtype_kind_t vtype_index, vtype_base; emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base assert(vtype_index == VTYPE_PYOBJ); assert(vtype_base == VTYPE_PYOBJ); emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3); } STATIC void emit_native_subscr(emit_t *emit, int kind) { if (kind == MP_EMIT_SUBSCR_LOAD) { emit_native_load_subscr(emit); } else if (kind == MP_EMIT_SUBSCR_STORE) { emit_native_store_subscr(emit); } else { emit_native_delete_subscr(emit); } } STATIC void emit_native_attr(emit_t *emit, qstr qst, int kind) { if (kind == MP_EMIT_ATTR_LOAD) { emit_native_load_attr(emit, qst); } else if (kind == MP_EMIT_ATTR_STORE) { emit_native_store_attr(emit, qst); } else { emit_native_delete_attr(emit, qst); } } STATIC void emit_native_dup_top(emit_t *emit) { DEBUG_printf("dup_top\n"); vtype_kind_t vtype; int reg = REG_TEMP0; emit_pre_pop_reg_flexible(emit, &vtype, ®, -1, -1); emit_post_push_reg_reg(emit, vtype, reg, vtype, reg); } STATIC void emit_native_dup_top_two(emit_t *emit) { vtype_kind_t vtype0, vtype1; emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1); emit_post_push_reg_reg_reg_reg(emit, vtype1, REG_TEMP1, vtype0, REG_TEMP0, vtype1, REG_TEMP1, vtype0, REG_TEMP0); } STATIC void emit_native_pop_top(emit_t *emit) { DEBUG_printf("pop_top\n"); emit_pre_pop_discard(emit); emit_post(emit); } STATIC void emit_native_rot_two(emit_t *emit) { DEBUG_printf("rot_two\n"); vtype_kind_t vtype0, vtype1; emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1); emit_post_push_reg_reg(emit, vtype0, REG_TEMP0, vtype1, REG_TEMP1); } STATIC void emit_native_rot_three(emit_t *emit) { DEBUG_printf("rot_three\n"); vtype_kind_t vtype0, vtype1, vtype2; emit_pre_pop_reg_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1, &vtype2, REG_TEMP2); emit_post_push_reg_reg_reg(emit, vtype0, REG_TEMP0, vtype2, REG_TEMP2, vtype1, REG_TEMP1); } STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) { DEBUG_printf("jump(label=" UINT_FMT ")\n", label); emit_native_pre(emit); // need to commit stack because we are jumping elsewhere need_stack_settled(emit); ASM_JUMP(emit->as, label); emit_post(emit); } STATIC void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bool pop) { vtype_kind_t vtype = peek_vtype(emit, 0); if (vtype == VTYPE_PYOBJ) { emit_pre_pop_reg(emit, &vtype, REG_ARG_1); if (!pop) { adjust_stack(emit, 1); } emit_call(emit, MP_F_OBJ_IS_TRUE); } else { emit_pre_pop_reg(emit, &vtype, REG_RET); if (!pop) { adjust_stack(emit, 1); } if (!(vtype == VTYPE_BOOL || vtype == VTYPE_INT || vtype == VTYPE_UINT)) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't implicitly convert '%q' to 'bool'", vtype_to_qstr(vtype)); } } // For non-pop need to save the vtype so that emit_native_adjust_stack_size // can use it. This is a bit of a hack. if (!pop) { emit->saved_stack_vtype = vtype; } // need to commit stack because we may jump elsewhere need_stack_settled(emit); // Emit the jump if (cond) { ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label, vtype == VTYPE_PYOBJ); } else { ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label, vtype == VTYPE_PYOBJ); } if (!pop) { adjust_stack(emit, -1); } emit_post(emit); } STATIC void emit_native_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) { DEBUG_printf("pop_jump_if(cond=%u, label=" UINT_FMT ")\n", cond, label); emit_native_jump_helper(emit, cond, label, true); } STATIC void emit_native_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) { DEBUG_printf("jump_if_or_pop(cond=%u, label=" UINT_FMT ")\n", cond, label); emit_native_jump_helper(emit, cond, label, false); } STATIC void emit_native_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) { if (except_depth > 0) { exc_stack_entry_t *first_finally = NULL; exc_stack_entry_t *prev_finally = NULL; exc_stack_entry_t *e = &emit->exc_stack[emit->exc_stack_size - 1]; for (; except_depth > 0; --except_depth, --e) { if (e->is_finally && e->is_active) { // Found an active finally handler if (first_finally == NULL) { first_finally = e; } if (prev_finally != NULL) { // Mark prev finally as needed to unwind a jump prev_finally->unwind_label = e->label; } prev_finally = e; } } if (prev_finally == NULL) { // No finally, handle the jump ourselves // First, restore the exception handler address for the jump if (e < emit->exc_stack) { ASM_XOR_REG_REG(emit->as, REG_RET, REG_RET); } else { ASM_MOV_REG_PCREL(emit->as, REG_RET, e->label); } ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_RET); } else { // Last finally should do our jump for us // Mark finally as needing to decide the type of jump prev_finally->unwind_label = UNWIND_LABEL_DO_FINAL_UNWIND; ASM_MOV_REG_PCREL(emit->as, REG_RET, label & ~MP_EMIT_BREAK_FROM_FOR); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_RET); // Cancel any active exception (see also emit_native_pop_except_jump) emit_native_mov_reg_const(emit, REG_RET, MP_F_CONST_NONE_OBJ); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_RET); // Jump to the innermost active finally label = first_finally->label; } } emit_native_jump(emit, label & ~MP_EMIT_BREAK_FROM_FOR); } STATIC void emit_native_setup_with(emit_t *emit, mp_uint_t label) { // the context manager is on the top of the stack // stack: (..., ctx_mgr) // get __exit__ method vtype_kind_t vtype; emit_access_stack(emit, 1, &vtype, REG_ARG_1); // arg1 = ctx_mgr assert(vtype == VTYPE_PYOBJ); emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr emit_call_with_qstr_arg(emit, MP_F_LOAD_METHOD, MP_QSTR___exit__, REG_ARG_2); // stack: (..., ctx_mgr, __exit__, self) emit_pre_pop_reg(emit, &vtype, REG_ARG_3); // self emit_pre_pop_reg(emit, &vtype, REG_ARG_2); // __exit__ emit_pre_pop_reg(emit, &vtype, REG_ARG_1); // ctx_mgr emit_post_push_reg(emit, vtype, REG_ARG_2); // __exit__ emit_post_push_reg(emit, vtype, REG_ARG_3); // self // stack: (..., __exit__, self) // REG_ARG_1=ctx_mgr // get __enter__ method emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr emit_call_with_qstr_arg(emit, MP_F_LOAD_METHOD, MP_QSTR___enter__, REG_ARG_2); // arg2 = method name // stack: (..., __exit__, self, __enter__, self) // call __enter__ method emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 2); // pointer to items, including meth and self emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, 0, REG_ARG_1, 0, REG_ARG_2); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // push return value of __enter__ // stack: (..., __exit__, self, as_value) // need to commit stack because we may jump elsewhere need_stack_settled(emit); emit_native_push_exc_stack(emit, label, true); emit_native_dup_top(emit); // stack: (..., __exit__, self, as_value, as_value) } STATIC void emit_native_setup_block(emit_t *emit, mp_uint_t label, int kind) { if (kind == MP_EMIT_SETUP_BLOCK_WITH) { emit_native_setup_with(emit, label); } else { // Set up except and finally emit_native_pre(emit); need_stack_settled(emit); emit_native_push_exc_stack(emit, label, kind == MP_EMIT_SETUP_BLOCK_FINALLY); emit_post(emit); } } STATIC void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { // Note: 3 labels are reserved for this function, starting at *emit->label_slot // stack: (..., __exit__, self, as_value) emit_native_pre(emit); emit_native_leave_exc_stack(emit, false); adjust_stack(emit, -1); // stack: (..., __exit__, self) // Label for case where __exit__ is called from an unwind jump emit_native_label_assign(emit, *emit->label_slot + 2); // call __exit__ emit_post_push_imm(emit, VTYPE_PTR_NONE, 0); emit_post_push_imm(emit, VTYPE_PTR_NONE, 0); emit_post_push_imm(emit, VTYPE_PTR_NONE, 0); emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 5); emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, 3, REG_ARG_1, 0, REG_ARG_2); // Replace exc with None and finish emit_native_jump(emit, *emit->label_slot); // nlr_catch // Don't use emit_native_label_assign because this isn't a real finally label mp_asm_base_label_assign(&emit->as->base, label); // Leave with's exception handler emit_native_leave_exc_stack(emit, true); // Adjust stack counter for: __exit__, self (implicitly discard as_value which is above self) emit_native_adjust_stack_size(emit, 2); // stack: (..., __exit__, self) ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); // get exc // Check if exc is None and jump to non-exc handler if it is emit_native_mov_reg_const(emit, REG_ARG_2, MP_F_CONST_NONE_OBJ); ASM_JUMP_IF_REG_EQ(emit->as, REG_ARG_1, REG_ARG_2, *emit->label_slot + 2); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_ARG_2, REG_ARG_1, 0); // get type(exc) emit_post_push_reg(emit, VTYPE_PYOBJ, REG_ARG_2); // push type(exc) emit_post_push_reg(emit, VTYPE_PYOBJ, REG_ARG_1); // push exc value emit_post_push_imm(emit, VTYPE_PTR_NONE, 0); // traceback info // Stack: (..., __exit__, self, type(exc), exc, traceback) // call __exit__ method emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 5); emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, 3, REG_ARG_1, 0, REG_ARG_2); // Stack: (...) // If REG_RET is true then we need to replace exception with None (swallow exception) if (REG_ARG_1 != REG_RET) { ASM_MOV_REG_REG(emit->as, REG_ARG_1, REG_RET); } emit_call(emit, MP_F_OBJ_IS_TRUE); ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, *emit->label_slot + 1, true); // Replace exception with None emit_native_label_assign(emit, *emit->label_slot); emit_native_mov_reg_const(emit, REG_TEMP0, MP_F_CONST_NONE_OBJ); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); // end of with cleanup nlr_catch block emit_native_label_assign(emit, *emit->label_slot + 1); // Exception is in nlr_buf.ret_val slot } STATIC void emit_native_end_finally(emit_t *emit) { // logic: // exc = pop_stack // if exc == None: pass // else: raise exc // the check if exc is None is done in the MP_F_NATIVE_RAISE stub emit_native_pre(emit); ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); emit_call(emit, MP_F_NATIVE_RAISE); // Get state for this finally and see if we need to unwind exc_stack_entry_t *e = emit_native_pop_exc_stack(emit); if (e->unwind_label != UNWIND_LABEL_UNUSED) { ASM_MOV_REG_LOCAL(emit->as, REG_RET, LOCAL_IDX_EXC_HANDLER_UNWIND(emit)); ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, *emit->label_slot, false); if (e->unwind_label == UNWIND_LABEL_DO_FINAL_UNWIND) { ASM_JUMP_REG(emit->as, REG_RET); } else { emit_native_jump(emit, e->unwind_label); } emit_native_label_assign(emit, *emit->label_slot); } emit_post(emit); } STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) { // perhaps the difficult one, as we want to rewrite for loops using native code // in cases where we iterate over a Python object, can we use normal runtime calls? vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_1); assert(vtype == VTYPE_PYOBJ); if (use_stack) { emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, MP_OBJ_ITER_BUF_NSLOTS); emit_call(emit, MP_F_NATIVE_GETITER); } else { // mp_getiter will allocate the iter_buf on the heap ASM_MOV_REG_IMM(emit->as, REG_ARG_2, 0); emit_call(emit, MP_F_NATIVE_GETITER); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } } STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) { emit_native_pre(emit); emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, MP_OBJ_ITER_BUF_NSLOTS); adjust_stack(emit, MP_OBJ_ITER_BUF_NSLOTS); emit_call(emit, MP_F_NATIVE_ITERNEXT); #if MICROPY_DEBUG_MP_OBJ_SENTINELS ASM_MOV_REG_IMM(emit->as, REG_TEMP1, (mp_uint_t)MP_OBJ_STOP_ITERATION); ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label); #else MP_STATIC_ASSERT(MP_OBJ_STOP_ITERATION == 0); ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label, false); #endif emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_for_iter_end(emit_t *emit) { // adjust stack counter (we get here from for_iter ending, which popped the value for us) emit_native_pre(emit); adjust_stack(emit, -MP_OBJ_ITER_BUF_NSLOTS); emit_post(emit); } STATIC void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { if (within_exc_handler) { // Cancel any active exception so subsequent handlers don't see it emit_native_mov_reg_const(emit, REG_TEMP0, MP_F_CONST_NONE_OBJ); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); } else { emit_native_leave_exc_stack(emit, false); } emit_native_jump(emit, label); } STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) { vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_2); if (vtype == VTYPE_PYOBJ) { emit_call_with_imm_arg(emit, MP_F_UNARY_OP, op, REG_ARG_1); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { adjust_stack(emit, 1); EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "unary op %q not implemented", mp_unary_op_method_name[op]); } } STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { DEBUG_printf("binary_op(" UINT_FMT ")\n", op); vtype_kind_t vtype_lhs = peek_vtype(emit, 1); vtype_kind_t vtype_rhs = peek_vtype(emit, 0); if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) { // for integers, inplace and normal ops are equivalent, so use just normal ops if (MP_BINARY_OP_INPLACE_OR <= op && op <= MP_BINARY_OP_INPLACE_POWER) { op += MP_BINARY_OP_OR - MP_BINARY_OP_INPLACE_OR; } #if N_X64 || N_X86 // special cases for x86 and shifting if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_RSHIFT) { #if N_X64 emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X64_REG_RCX, &vtype_lhs, REG_RET); #else emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X86_REG_ECX, &vtype_lhs, REG_RET); #endif if (op == MP_BINARY_OP_LSHIFT) { ASM_LSL_REG(emit->as, REG_RET); } else { ASM_ASR_REG(emit->as, REG_RET); } emit_post_push_reg(emit, VTYPE_INT, REG_RET); return; } #endif // special cases for floor-divide and module because we dispatch to helper functions if (op == MP_BINARY_OP_FLOOR_DIVIDE || op == MP_BINARY_OP_MODULO) { emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_2, &vtype_lhs, REG_ARG_1); if (op == MP_BINARY_OP_FLOOR_DIVIDE) { emit_call(emit, MP_F_SMALL_INT_FLOOR_DIVIDE); } else { emit_call(emit, MP_F_SMALL_INT_MODULO); } emit_post_push_reg(emit, VTYPE_INT, REG_RET); return; } int reg_rhs = REG_ARG_3; emit_pre_pop_reg_flexible(emit, &vtype_rhs, ®_rhs, REG_RET, REG_ARG_2); emit_pre_pop_reg(emit, &vtype_lhs, REG_ARG_2); #if !(N_X64 || N_X86) if (op == MP_BINARY_OP_LSHIFT) { ASM_LSL_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (op == MP_BINARY_OP_RSHIFT) { ASM_ASR_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else #endif if (op == MP_BINARY_OP_OR) { ASM_OR_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (op == MP_BINARY_OP_XOR) { ASM_XOR_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (op == MP_BINARY_OP_AND) { ASM_AND_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (op == MP_BINARY_OP_ADD) { ASM_ADD_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (op == MP_BINARY_OP_SUBTRACT) { ASM_SUB_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (op == MP_BINARY_OP_MULTIPLY) { ASM_MUL_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (MP_BINARY_OP_LESS <= op && op <= MP_BINARY_OP_NOT_EQUAL) { // comparison ops are (in enum order): // MP_BINARY_OP_LESS // MP_BINARY_OP_MORE // MP_BINARY_OP_EQUAL // MP_BINARY_OP_LESS_EQUAL // MP_BINARY_OP_MORE_EQUAL // MP_BINARY_OP_NOT_EQUAL need_reg_single(emit, REG_RET, 0); #if N_X64 asm_x64_xor_r64_r64(emit->as, REG_RET, REG_RET); asm_x64_cmp_r64_with_r64(emit->as, reg_rhs, REG_ARG_2); static byte ops[6] = { ASM_X64_CC_JL, ASM_X64_CC_JG, ASM_X64_CC_JE, ASM_X64_CC_JLE, ASM_X64_CC_JGE, ASM_X64_CC_JNE, }; asm_x64_setcc_r8(emit->as, ops[op - MP_BINARY_OP_LESS], REG_RET); #elif N_X86 asm_x86_xor_r32_r32(emit->as, REG_RET, REG_RET); asm_x86_cmp_r32_with_r32(emit->as, reg_rhs, REG_ARG_2); static byte ops[6] = { ASM_X86_CC_JL, ASM_X86_CC_JG, ASM_X86_CC_JE, ASM_X86_CC_JLE, ASM_X86_CC_JGE, ASM_X86_CC_JNE, }; asm_x86_setcc_r8(emit->as, ops[op - MP_BINARY_OP_LESS], REG_RET); #elif N_THUMB asm_thumb_cmp_rlo_rlo(emit->as, REG_ARG_2, reg_rhs); static uint16_t ops[6] = { ASM_THUMB_OP_ITE_GE, ASM_THUMB_OP_ITE_GT, ASM_THUMB_OP_ITE_EQ, ASM_THUMB_OP_ITE_GT, ASM_THUMB_OP_ITE_GE, ASM_THUMB_OP_ITE_EQ, }; static byte ret[6] = { 0, 1, 1, 0, 1, 0, }; asm_thumb_op16(emit->as, ops[op - MP_BINARY_OP_LESS]); asm_thumb_mov_rlo_i8(emit->as, REG_RET, ret[op - MP_BINARY_OP_LESS]); asm_thumb_mov_rlo_i8(emit->as, REG_RET, ret[op - MP_BINARY_OP_LESS] ^ 1); #elif N_ARM asm_arm_cmp_reg_reg(emit->as, REG_ARG_2, reg_rhs); static uint ccs[6] = { ASM_ARM_CC_LT, ASM_ARM_CC_GT, ASM_ARM_CC_EQ, ASM_ARM_CC_LE, ASM_ARM_CC_GE, ASM_ARM_CC_NE, }; asm_arm_setcc_reg(emit->as, REG_RET, ccs[op - MP_BINARY_OP_LESS]); #elif N_XTENSA || N_XTENSAWIN static uint8_t ccs[6] = { ASM_XTENSA_CC_LT, 0x80 | ASM_XTENSA_CC_LT, // for GT we'll swap args ASM_XTENSA_CC_EQ, 0x80 | ASM_XTENSA_CC_GE, // for LE we'll swap args ASM_XTENSA_CC_GE, ASM_XTENSA_CC_NE, }; uint8_t cc = ccs[op - MP_BINARY_OP_LESS]; if ((cc & 0x80) == 0) { asm_xtensa_setcc_reg_reg_reg(emit->as, cc, REG_RET, REG_ARG_2, reg_rhs); } else { asm_xtensa_setcc_reg_reg_reg(emit->as, cc & ~0x80, REG_RET, reg_rhs, REG_ARG_2); } #else #error not implemented #endif emit_post_push_reg(emit, VTYPE_BOOL, REG_RET); } else { // TODO other ops not yet implemented adjust_stack(emit, 1); EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "binary op %q not implemented", mp_binary_op_method_name[op]); } } else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) { emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2); bool invert = false; if (op == MP_BINARY_OP_NOT_IN) { invert = true; op = MP_BINARY_OP_IN; } else if (op == MP_BINARY_OP_IS_NOT) { invert = true; op = MP_BINARY_OP_IS; } emit_call_with_imm_arg(emit, MP_F_BINARY_OP, op, REG_ARG_1); if (invert) { ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET); emit_call_with_imm_arg(emit, MP_F_UNARY_OP, MP_UNARY_OP_NOT, REG_ARG_1); } emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { adjust_stack(emit, -1); EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "can't do binary op between '%q' and '%q'", vtype_to_qstr(vtype_lhs), vtype_to_qstr(vtype_rhs)); } } #if MICROPY_PY_BUILTINS_SLICE STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args); #endif STATIC void emit_native_build(emit_t *emit, mp_uint_t n_args, int kind) { // for viper: call runtime, with types of args // if wrapped in byte_array, or something, allocates memory and fills it MP_STATIC_ASSERT(MP_F_BUILD_TUPLE + MP_EMIT_BUILD_TUPLE == MP_F_BUILD_TUPLE); MP_STATIC_ASSERT(MP_F_BUILD_TUPLE + MP_EMIT_BUILD_LIST == MP_F_BUILD_LIST); MP_STATIC_ASSERT(MP_F_BUILD_TUPLE + MP_EMIT_BUILD_MAP == MP_F_BUILD_MAP); MP_STATIC_ASSERT(MP_F_BUILD_TUPLE + MP_EMIT_BUILD_SET == MP_F_BUILD_SET); #if MICROPY_PY_BUILTINS_SLICE if (kind == MP_EMIT_BUILD_SLICE) { emit_native_build_slice(emit, n_args); return; } #endif emit_native_pre(emit); if (kind == MP_EMIT_BUILD_TUPLE || kind == MP_EMIT_BUILD_LIST || kind == MP_EMIT_BUILD_SET) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items } emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE + kind, n_args, REG_ARG_1); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple/list/map/set } STATIC void emit_native_store_map(emit_t *emit) { vtype_kind_t vtype_key, vtype_value, vtype_map; emit_pre_pop_reg_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3, &vtype_map, REG_ARG_1); // key, value, map assert(vtype_key == VTYPE_PYOBJ); assert(vtype_value == VTYPE_PYOBJ); assert(vtype_map == VTYPE_PYOBJ); emit_call(emit, MP_F_STORE_MAP); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map } #if MICROPY_PY_BUILTINS_SLICE STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) { DEBUG_printf("build_slice %d\n", n_args); if (n_args == 2) { vtype_kind_t vtype_start, vtype_stop; emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop assert(vtype_start == VTYPE_PYOBJ); assert(vtype_stop == VTYPE_PYOBJ); emit_native_mov_reg_const(emit, REG_ARG_3, MP_F_CONST_NONE_OBJ); // arg3 = step } else { assert(n_args == 3); vtype_kind_t vtype_start, vtype_stop, vtype_step; emit_pre_pop_reg_reg_reg(emit, &vtype_step, REG_ARG_3, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop, arg3 = step assert(vtype_start == VTYPE_PYOBJ); assert(vtype_stop == VTYPE_PYOBJ); assert(vtype_step == VTYPE_PYOBJ); } emit_call(emit, MP_F_NEW_SLICE); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } #endif STATIC void emit_native_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_index) { mp_fun_kind_t f; if (kind == SCOPE_LIST_COMP) { vtype_kind_t vtype_item; emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); assert(vtype_item == VTYPE_PYOBJ); f = MP_F_LIST_APPEND; #if MICROPY_PY_BUILTINS_SET } else if (kind == SCOPE_SET_COMP) { vtype_kind_t vtype_item; emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); assert(vtype_item == VTYPE_PYOBJ); f = MP_F_STORE_SET; #endif } else { // SCOPE_DICT_COMP vtype_kind_t vtype_key, vtype_value; emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3); assert(vtype_key == VTYPE_PYOBJ); assert(vtype_value == VTYPE_PYOBJ); f = MP_F_STORE_MAP; } vtype_kind_t vtype_collection; emit_access_stack(emit, collection_index, &vtype_collection, REG_ARG_1); assert(vtype_collection == VTYPE_PYOBJ); emit_call(emit, f); emit_post(emit); } STATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) { DEBUG_printf("unpack_sequence %d\n", n_args); vtype_kind_t vtype_base; emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq assert(vtype_base == VTYPE_PYOBJ); emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_args); // arg3 = dest ptr emit_call_with_imm_arg(emit, MP_F_UNPACK_SEQUENCE, n_args, REG_ARG_2); // arg2 = n_args } STATIC void emit_native_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) { DEBUG_printf("unpack_ex %d %d\n", n_left, n_right); vtype_kind_t vtype_base; emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq assert(vtype_base == VTYPE_PYOBJ); emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right + 1); // arg3 = dest ptr emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, n_left | (n_right << 8), REG_ARG_2); // arg2 = n_left + n_right } STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { // call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them emit_native_pre(emit); if (n_pos_defaults == 0 && n_kw_defaults == 0) { need_reg_all(emit); ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL); ASM_MOV_REG_IMM(emit->as, REG_ARG_3, (mp_uint_t)MP_OBJ_NULL); } else { vtype_kind_t vtype_def_tuple, vtype_def_dict; emit_pre_pop_reg_reg(emit, &vtype_def_dict, REG_ARG_3, &vtype_def_tuple, REG_ARG_2); assert(vtype_def_tuple == VTYPE_PYOBJ); assert(vtype_def_dict == VTYPE_PYOBJ); need_reg_all(emit); } emit_load_reg_with_raw_code(emit, REG_ARG_1, scope->raw_code); ASM_CALL_IND(emit->as, MP_F_MAKE_FUNCTION_FROM_RAW_CODE); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { emit_native_pre(emit); if (n_pos_defaults == 0 && n_kw_defaults == 0) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_closed_over); ASM_MOV_REG_IMM(emit->as, REG_ARG_2, n_closed_over); } else { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_closed_over + 2); ASM_MOV_REG_IMM(emit->as, REG_ARG_2, 0x100 | n_closed_over); } emit_load_reg_with_raw_code(emit, REG_ARG_1, scope->raw_code); ASM_CALL_IND(emit->as, MP_F_MAKE_CLOSURE_FROM_RAW_CODE); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { DEBUG_printf("call_function(n_pos=" UINT_FMT ", n_kw=" UINT_FMT ", star_flags=" UINT_FMT ")\n", n_positional, n_keyword, star_flags); // TODO: in viper mode, call special runtime routine with type info for args, // and wanted type info for return, to remove need for boxing/unboxing emit_native_pre(emit); vtype_kind_t vtype_fun = peek_vtype(emit, n_positional + 2 * n_keyword); if (vtype_fun == VTYPE_BUILTIN_CAST) { // casting operator assert(n_positional == 1 && n_keyword == 0); assert(!star_flags); DEBUG_printf(" cast to %d\n", vtype_fun); vtype_kind_t vtype_cast = peek_stack(emit, 1)->data.u_imm; switch (peek_vtype(emit, 0)) { case VTYPE_PYOBJ: { vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_1); emit_pre_pop_discard(emit); emit_call_with_imm_arg(emit, MP_F_CONVERT_OBJ_TO_NATIVE, vtype_cast, REG_ARG_2); // arg2 = type emit_post_push_reg(emit, vtype_cast, REG_RET); break; } case VTYPE_BOOL: case VTYPE_INT: case VTYPE_UINT: case VTYPE_PTR: case VTYPE_PTR8: case VTYPE_PTR16: case VTYPE_PTR32: case VTYPE_PTR_NONE: emit_fold_stack_top(emit, REG_ARG_1); emit_post_top_set_vtype(emit, vtype_cast); break; default: // this can happen when casting a cast: int(int) mp_raise_NotImplementedError("casting"); } } else { assert(vtype_fun == VTYPE_PYOBJ); if (star_flags) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 3); // pointer to args emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW_VAR, 0, REG_ARG_1, n_positional | (n_keyword << 8), REG_ARG_2); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { if (n_positional != 0 || n_keyword != 0) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args } emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } } } STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { if (star_flags) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 4); // pointer to args emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW_VAR, 1, REG_ARG_1, n_positional | (n_keyword << 8), REG_ARG_2); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { emit_native_pre(emit); emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 2 + n_positional + 2 * n_keyword); // pointer to items, including meth and self emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, n_positional, REG_ARG_1, n_keyword, REG_ARG_2); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } } STATIC void emit_native_return_value(emit_t *emit) { DEBUG_printf("return_value\n"); if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { // Save pointer to current stack position for caller to access return value emit_get_stack_pointer_to_reg_for_pop(emit, REG_TEMP0, 1); emit_native_mov_state_reg(emit, OFFSETOF_CODE_STATE_SP, REG_TEMP0); // Put return type in return value slot ASM_MOV_REG_IMM(emit->as, REG_TEMP0, MP_VM_RETURN_NORMAL); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_TEMP0); // Do the unwinding jump to get to the return handler emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size); emit->last_emit_was_return_value = true; return; } if (emit->do_viper_types) { vtype_kind_t return_vtype = emit->scope->scope_flags >> MP_SCOPE_FLAG_VIPERRET_POS; if (peek_vtype(emit, 0) == VTYPE_PTR_NONE) { emit_pre_pop_discard(emit); if (return_vtype == VTYPE_PYOBJ) { emit_native_mov_reg_const(emit, REG_PARENT_RET, MP_F_CONST_NONE_OBJ); } else { ASM_MOV_REG_IMM(emit->as, REG_ARG_1, 0); } } else { vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, return_vtype == VTYPE_PYOBJ ? REG_PARENT_RET : REG_ARG_1); if (vtype != return_vtype) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "return expected '%q' but got '%q'", vtype_to_qstr(return_vtype), vtype_to_qstr(vtype)); } } if (return_vtype != VTYPE_PYOBJ) { emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, return_vtype, REG_ARG_2); #if REG_RET != REG_PARENT_RET ASM_MOV_REG_REG(emit->as, REG_PARENT_RET, REG_RET); #endif } } else { vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_PARENT_RET); assert(vtype == VTYPE_PYOBJ); } if (NEED_GLOBAL_EXC_HANDLER(emit)) { // Save return value for the global exception handler to use ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_PARENT_RET); } emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size); emit->last_emit_was_return_value = true; } STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { (void)n_args; assert(n_args == 1); vtype_kind_t vtype_exc; emit_pre_pop_reg(emit, &vtype_exc, REG_ARG_1); // arg1 = object to raise if (vtype_exc != VTYPE_PYOBJ) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "must raise an object"); } // TODO probably make this 1 call to the runtime (which could even call convert, native_raise(obj, type)) emit_call(emit, MP_F_NATIVE_RAISE); } STATIC void emit_native_yield(emit_t *emit, int kind) { // Note: 1 (yield) or 3 (yield from) labels are reserved for this function, starting at *emit->label_slot if (emit->do_viper_types) { mp_raise_NotImplementedError("native yield"); } emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; need_stack_settled(emit); if (kind == MP_EMIT_YIELD_FROM) { // Top of yield-from loop, conceptually implementing: // for item in generator: // yield item // Jump to start of loop emit_native_jump(emit, *emit->label_slot + 2); // Label for top of loop emit_native_label_assign(emit, *emit->label_slot + 1); } // Save pointer to current stack position for caller to access yielded value emit_get_stack_pointer_to_reg_for_pop(emit, REG_TEMP0, 1); emit_native_mov_state_reg(emit, OFFSETOF_CODE_STATE_SP, REG_TEMP0); // Put return type in return value slot ASM_MOV_REG_IMM(emit->as, REG_TEMP0, MP_VM_RETURN_YIELD); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_TEMP0); // Save re-entry PC ASM_MOV_REG_PCREL(emit->as, REG_TEMP0, *emit->label_slot); emit_native_mov_state_reg(emit, LOCAL_IDX_GEN_PC(emit), REG_TEMP0); // Jump to exit handler ASM_JUMP(emit->as, emit->exit_label); // Label re-entry point mp_asm_base_label_assign(&emit->as->base, *emit->label_slot); // Re-open any active exception handler if (emit->exc_stack_size > 0) { // Find innermost active exception handler, to restore as current handler exc_stack_entry_t *e = &emit->exc_stack[emit->exc_stack_size - 1]; for (; e >= emit->exc_stack; --e) { if (e->is_active) { // Found active handler, get its PC ASM_MOV_REG_PCREL(emit->as, REG_RET, e->label); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_RET); } } } emit_native_adjust_stack_size(emit, 1); // send_value if (kind == MP_EMIT_YIELD_VALUE) { // Check LOCAL_IDX_EXC_VAL for any injected value ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); emit_call(emit, MP_F_NATIVE_RAISE); } else { // Label loop entry emit_native_label_assign(emit, *emit->label_slot + 2); // Get the next item from the delegate generator vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_2); // send_value emit_access_stack(emit, 1, &vtype, REG_ARG_1); // generator ASM_MOV_REG_LOCAL(emit->as, REG_ARG_3, LOCAL_IDX_EXC_VAL(emit)); // throw_value emit_post_push_reg(emit, VTYPE_PYOBJ, REG_ARG_3); emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 1); // ret_value emit_call(emit, MP_F_NATIVE_YIELD_FROM); // If returned non-zero then generator continues ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, *emit->label_slot + 1, true); // Pop exhausted gen, replace with ret_value emit_native_adjust_stack_size(emit, 1); // ret_value emit_fold_stack_top(emit, REG_ARG_1); } } STATIC void emit_native_start_except_handler(emit_t *emit) { // Protected block has finished so leave the current exception handler emit_native_leave_exc_stack(emit, true); // Get and push nlr_buf.ret_val ASM_MOV_REG_LOCAL(emit->as, REG_TEMP0, LOCAL_IDX_EXC_VAL(emit)); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_TEMP0); } STATIC void emit_native_end_except_handler(emit_t *emit) { adjust_stack(emit, -1); // pop the exception (end_finally didn't use it) } const emit_method_table_t EXPORT_FUN(method_table) = { #if MICROPY_DYNAMIC_COMPILER EXPORT_FUN(new), EXPORT_FUN(free), #endif emit_native_start_pass, emit_native_end_pass, emit_native_last_emit_was_return_value, emit_native_adjust_stack_size, emit_native_set_source_line, { emit_native_load_local, emit_native_load_global, }, { emit_native_store_local, emit_native_store_global, }, { emit_native_delete_local, emit_native_delete_global, }, emit_native_label_assign, emit_native_import, emit_native_load_const_tok, emit_native_load_const_small_int, emit_native_load_const_str, emit_native_load_const_obj, emit_native_load_null, emit_native_load_method, emit_native_load_build_class, emit_native_subscr, emit_native_attr, emit_native_dup_top, emit_native_dup_top_two, emit_native_pop_top, emit_native_rot_two, emit_native_rot_three, emit_native_jump, emit_native_pop_jump_if, emit_native_jump_if_or_pop, emit_native_unwind_jump, emit_native_setup_block, emit_native_with_cleanup, emit_native_end_finally, emit_native_get_iter, emit_native_for_iter, emit_native_for_iter_end, emit_native_pop_except_jump, emit_native_unary_op, emit_native_binary_op, emit_native_build, emit_native_store_map, emit_native_store_comp, emit_native_unpack_sequence, emit_native_unpack_ex, emit_native_make_function, emit_native_make_closure, emit_native_call_function, emit_native_call_method, emit_native_return_value, emit_native_raise_varargs, emit_native_yield, emit_native_start_except_handler, emit_native_end_except_handler, }; #endif micropython-1.12/py/emitnthumb.c000066400000000000000000000007271357706137100170000ustar00rootroot00000000000000// thumb specific stuff #include "py/mpconfig.h" #if MICROPY_EMIT_THUMB // this is defined so that the assembler exports generic assembler API macros #define GENERIC_ASM_API (1) #include "py/asmthumb.h" // Word indices of REG_LOCAL_x in nlr_buf_t #define NLR_BUF_IDX_LOCAL_1 (3) // r4 #define NLR_BUF_IDX_LOCAL_2 (4) // r5 #define NLR_BUF_IDX_LOCAL_3 (5) // r6 #define N_THUMB (1) #define EXPORT_FUN(name) emit_native_thumb_##name #include "py/emitnative.c" #endif micropython-1.12/py/emitnx64.c000066400000000000000000000007201357706137100162730ustar00rootroot00000000000000// x64 specific stuff #include "py/mpconfig.h" #if MICROPY_EMIT_X64 // This is defined so that the assembler exports generic assembler API macros #define GENERIC_ASM_API (1) #include "py/asmx64.h" // Word indices of REG_LOCAL_x in nlr_buf_t #define NLR_BUF_IDX_LOCAL_1 (5) // rbx #define NLR_BUF_IDX_LOCAL_2 (6) // r12 #define NLR_BUF_IDX_LOCAL_3 (7) // r13 #define N_X64 (1) #define EXPORT_FUN(name) emit_native_x64_##name #include "py/emitnative.c" #endif micropython-1.12/py/emitnx86.c000066400000000000000000000037531357706137100163100ustar00rootroot00000000000000// x86 specific stuff #include "py/mpconfig.h" #include "py/nativeglue.h" #if MICROPY_EMIT_X86 // This is defined so that the assembler exports generic assembler API macros #define GENERIC_ASM_API (1) #include "py/asmx86.h" // Word indices of REG_LOCAL_x in nlr_buf_t #define NLR_BUF_IDX_LOCAL_1 (5) // ebx #define NLR_BUF_IDX_LOCAL_2 (7) // esi #define NLR_BUF_IDX_LOCAL_3 (6) // edi // x86 needs a table to know how many args a given function has STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_CONVERT_OBJ_TO_NATIVE] = 2, [MP_F_CONVERT_NATIVE_TO_OBJ] = 2, [MP_F_NATIVE_SWAP_GLOBALS] = 1, [MP_F_LOAD_NAME] = 1, [MP_F_LOAD_GLOBAL] = 1, [MP_F_LOAD_BUILD_CLASS] = 0, [MP_F_LOAD_ATTR] = 2, [MP_F_LOAD_METHOD] = 3, [MP_F_LOAD_SUPER_METHOD] = 2, [MP_F_STORE_NAME] = 2, [MP_F_STORE_GLOBAL] = 2, [MP_F_STORE_ATTR] = 3, [MP_F_OBJ_SUBSCR] = 3, [MP_F_OBJ_IS_TRUE] = 1, [MP_F_UNARY_OP] = 2, [MP_F_BINARY_OP] = 3, [MP_F_BUILD_TUPLE] = 2, [MP_F_BUILD_LIST] = 2, [MP_F_BUILD_MAP] = 1, [MP_F_BUILD_SET] = 2, [MP_F_STORE_SET] = 2, [MP_F_LIST_APPEND] = 2, [MP_F_STORE_MAP] = 3, [MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3, [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3, [MP_F_CALL_METHOD_N_KW] = 3, [MP_F_CALL_METHOD_N_KW_VAR] = 3, [MP_F_NATIVE_GETITER] = 2, [MP_F_NATIVE_ITERNEXT] = 1, [MP_F_NLR_PUSH] = 1, [MP_F_NLR_POP] = 0, [MP_F_NATIVE_RAISE] = 1, [MP_F_IMPORT_NAME] = 3, [MP_F_IMPORT_FROM] = 2, [MP_F_IMPORT_ALL] = 1, [MP_F_NEW_SLICE] = 3, [MP_F_UNPACK_SEQUENCE] = 3, [MP_F_UNPACK_EX] = 3, [MP_F_DELETE_NAME] = 1, [MP_F_DELETE_GLOBAL] = 1, [MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3, [MP_F_ARG_CHECK_NUM_SIG] = 3, [MP_F_SETUP_CODE_STATE] = 4, [MP_F_SMALL_INT_FLOOR_DIVIDE] = 2, [MP_F_SMALL_INT_MODULO] = 2, [MP_F_NATIVE_YIELD_FROM] = 3, [MP_F_SETJMP] = 1, }; #define N_X86 (1) #define EXPORT_FUN(name) emit_native_x86_##name #include "py/emitnative.c" #endif micropython-1.12/py/emitnxtensa.c000066400000000000000000000007401357706137100171560ustar00rootroot00000000000000// Xtensa specific stuff #include "py/mpconfig.h" #if MICROPY_EMIT_XTENSA // this is defined so that the assembler exports generic assembler API macros #define GENERIC_ASM_API (1) #include "py/asmxtensa.h" // Word indices of REG_LOCAL_x in nlr_buf_t #define NLR_BUF_IDX_LOCAL_1 (8) // a12 #define NLR_BUF_IDX_LOCAL_2 (9) // a13 #define NLR_BUF_IDX_LOCAL_3 (10) // a14 #define N_XTENSA (1) #define EXPORT_FUN(name) emit_native_xtensa_##name #include "py/emitnative.c" #endif micropython-1.12/py/emitnxtensawin.c000066400000000000000000000011261357706137100176730ustar00rootroot00000000000000// Xtensa-Windowed specific stuff #include "py/mpconfig.h" #if MICROPY_EMIT_XTENSAWIN // this is defined so that the assembler exports generic assembler API macros #define GENERIC_ASM_API (1) #define GENERIC_ASM_API_WIN (1) #include "py/asmxtensa.h" // Word indices of REG_LOCAL_x in nlr_buf_t #define NLR_BUF_IDX_LOCAL_1 (2 + 4) // a4 #define NLR_BUF_IDX_LOCAL_2 (2 + 5) // a5 #define NLR_BUF_IDX_LOCAL_3 (2 + 6) // a6 #define N_NLR_SETJMP (1) #define N_PRELUDE_AS_BYTES_OBJ (1) #define N_XTENSAWIN (1) #define EXPORT_FUN(name) emit_native_xtensawin_##name #include "py/emitnative.c" #endif micropython-1.12/py/formatfloat.c000066400000000000000000000310441357706137100171360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE #include #include #include #include #include "py/formatfloat.h" /*********************************************************************** Routine for converting a arbitrary floating point number into a string. The code in this funcion was inspired from Fred Bayer's pdouble.c. Since pdouble.c was released as Public Domain, I'm releasing this code as public domain as well. The original code can be found in https://github.com/dhylands/format-float Dave Hylands ***********************************************************************/ #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT // 1 sign bit, 8 exponent bits, and 23 mantissa bits. // exponent values 0 and 255 are reserved, exponent can be 1 to 254. // exponent is stored with a bias of 127. // The min and max floats are on the order of 1x10^37 and 1x10^-37 #define FPTYPE float #define FPCONST(x) x##F #define FPROUND_TO_ONE 0.9999995F #define FPDECEXP 32 #define FPMIN_BUF_SIZE 6 // +9e+99 #define FLT_SIGN_MASK 0x80000000 #define FLT_EXP_MASK 0x7F800000 #define FLT_MAN_MASK 0x007FFFFF union floatbits { float f; uint32_t u; }; static inline int fp_signbit(float x) { union floatbits fb = {x}; return fb.u & FLT_SIGN_MASK; } #define fp_isnan(x) isnan(x) #define fp_isinf(x) isinf(x) static inline int fp_iszero(float x) { union floatbits fb = {x}; return fb.u == 0; } static inline int fp_isless1(float x) { union floatbits fb = {x}; return fb.u < 0x3f800000; } #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #define FPTYPE double #define FPCONST(x) x #define FPROUND_TO_ONE 0.999999999995 #define FPDECEXP 256 #define FPMIN_BUF_SIZE 7 // +9e+199 #define fp_signbit(x) signbit(x) #define fp_isnan(x) isnan(x) #define fp_isinf(x) isinf(x) #define fp_iszero(x) (x == 0) #define fp_isless1(x) (x < 1.0) #endif static const FPTYPE g_pos_pow[] = { #if FPDECEXP > 32 1e256, 1e128, 1e64, #endif 1e32, 1e16, 1e8, 1e4, 1e2, 1e1 }; static const FPTYPE g_neg_pow[] = { #if FPDECEXP > 32 1e-256, 1e-128, 1e-64, #endif 1e-32, 1e-16, 1e-8, 1e-4, 1e-2, 1e-1 }; int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) { char *s = buf; if (buf_size <= FPMIN_BUF_SIZE) { // FPMIN_BUF_SIZE is the minimum size needed to store any FP number. // If the buffer does not have enough room for this (plus null terminator) // then don't try to format the float. if (buf_size >= 2) { *s++ = '?'; } if (buf_size >= 1) { *s = '\0'; } return buf_size >= 2; } if (fp_signbit(f) && !fp_isnan(f)) { *s++ = '-'; f = -f; } else { if (sign) { *s++ = sign; } } // buf_remaining contains bytes available for digits and exponent. // It is buf_size minus room for the sign and null byte. int buf_remaining = buf_size - 1 - (s - buf); { char uc = fmt & 0x20; if (fp_isinf(f)) { *s++ = 'I' ^ uc; *s++ = 'N' ^ uc; *s++ = 'F' ^ uc; goto ret; } else if (fp_isnan(f)) { *s++ = 'N' ^ uc; *s++ = 'A' ^ uc; *s++ = 'N' ^ uc; ret: *s = '\0'; return s - buf; } } if (prec < 0) { prec = 6; } char e_char = 'E' | (fmt & 0x20); // e_char will match case of fmt fmt |= 0x20; // Force fmt to be lowercase char org_fmt = fmt; if (fmt == 'g' && prec == 0) { prec = 1; } int e, e1; int dec = 0; char e_sign = '\0'; int num_digits = 0; const FPTYPE *pos_pow = g_pos_pow; const FPTYPE *neg_pow = g_neg_pow; if (fp_iszero(f)) { e = 0; if (fmt == 'f') { // Truncate precision to prevent buffer overflow if (prec + 2 > buf_remaining) { prec = buf_remaining - 2; } num_digits = prec + 1; } else { // Truncate precision to prevent buffer overflow if (prec + 6 > buf_remaining) { prec = buf_remaining - 6; } if (fmt == 'e') { e_sign = '+'; } } } else if (fp_isless1(f)) { // We need to figure out what an integer digit will be used // in case 'f' is used (or we revert other format to it below). // As we just tested number to be <1, this is obviously 0, // but we can round it up to 1 below. char first_dig = '0'; if (f >= FPROUND_TO_ONE) { first_dig = '1'; } // Build negative exponent for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) { if (*neg_pow > f) { e += e1; f *= *pos_pow; } } char e_sign_char = '-'; if (fp_isless1(f) && f >= FPROUND_TO_ONE) { f = FPCONST(1.0); if (e == 0) { e_sign_char = '+'; } } else if (fp_isless1(f)) { e++; f *= FPCONST(10.0); } // If the user specified 'g' format, and e is <= 4, then we'll switch // to the fixed format ('f') if (fmt == 'f' || (fmt == 'g' && e <= 4)) { fmt = 'f'; dec = -1; *s++ = first_dig; if (org_fmt == 'g') { prec += (e - 1); } // truncate precision to prevent buffer overflow if (prec + 2 > buf_remaining) { prec = buf_remaining - 2; } num_digits = prec; if (num_digits) { *s++ = '.'; while (--e && num_digits) { *s++ = '0'; num_digits--; } } } else { // For e & g formats, we'll be printing the exponent, so set the // sign. e_sign = e_sign_char; dec = 0; if (prec > (buf_remaining - FPMIN_BUF_SIZE)) { prec = buf_remaining - FPMIN_BUF_SIZE; if (fmt == 'g') { prec++; } } } } else { // Build positive exponent for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) { if (*pos_pow <= f) { e += e1; f *= *neg_pow; } } // It can be that f was right on the edge of an entry in pos_pow needs to be reduced if ((int)f >= 10) { e += 1; f *= FPCONST(0.1); } // If the user specified fixed format (fmt == 'f') and e makes the // number too big to fit into the available buffer, then we'll // switch to the 'e' format. if (fmt == 'f') { if (e >= buf_remaining) { fmt = 'e'; } else if ((e + prec + 2) > buf_remaining) { prec = buf_remaining - e - 2; if (prec < 0) { // This means no decimal point, so we can add one back // for the decimal. prec++; } } } if (fmt == 'e' && prec > (buf_remaining - FPMIN_BUF_SIZE)) { prec = buf_remaining - FPMIN_BUF_SIZE; } if (fmt == 'g'){ // Truncate precision to prevent buffer overflow if (prec + (FPMIN_BUF_SIZE - 1) > buf_remaining) { prec = buf_remaining - (FPMIN_BUF_SIZE - 1); } } // If the user specified 'g' format, and e is < prec, then we'll switch // to the fixed format. if (fmt == 'g' && e < prec) { fmt = 'f'; prec -= (e + 1); } if (fmt == 'f') { dec = e; num_digits = prec + e + 1; } else { e_sign = '+'; } } if (prec < 0) { // This can happen when the prec is trimmed to prevent buffer overflow prec = 0; } // We now have num.f as a floating point number between >= 1 and < 10 // (or equal to zero), and e contains the absolute value of the power of // 10 exponent. and (dec + 1) == the number of dgits before the decimal. // For e, prec is # digits after the decimal // For f, prec is # digits after the decimal // For g, prec is the max number of significant digits // // For e & g there will be a single digit before the decimal // for f there will be e digits before the decimal if (fmt == 'e') { num_digits = prec + 1; } else if (fmt == 'g') { if (prec == 0) { prec = 1; } num_digits = prec; } // Print the digits of the mantissa for (int i = 0; i < num_digits; ++i, --dec) { int32_t d = (int32_t)f; if (d < 0) { *s++ = '0'; } else { *s++ = '0' + d; } if (dec == 0 && prec > 0) { *s++ = '.'; } f -= (FPTYPE)d; f *= FPCONST(10.0); } // Round // If we print non-exponential format (i.e. 'f'), but a digit we're going // to round by (e) is too far away, then there's nothing to round. if ((org_fmt != 'f' || e <= num_digits) && f >= FPCONST(5.0)) { char *rs = s; rs--; while (1) { if (*rs == '.') { rs--; continue; } if (*rs < '0' || *rs > '9') { // + or - rs++; // So we sit on the digit to the right of the sign break; } if (*rs < '9') { (*rs)++; break; } *rs = '0'; if (rs == buf) { break; } rs--; } if (*rs == '0') { // We need to insert a 1 if (rs[1] == '.' && fmt != 'f') { // We're going to round 9.99 to 10.00 // Move the decimal point rs[0] = '.'; rs[1] = '0'; if (e_sign == '-') { e--; if (e == 0) { e_sign = '+'; } } else { e++; } } else { // Need at extra digit at the end to make room for the leading '1' s++; } char *ss = s; while (ss > rs) { *ss = ss[-1]; ss--; } *rs = '1'; } } // verify that we did not overrun the input buffer so far assert((size_t)(s + 1 - buf) <= buf_size); if (org_fmt == 'g' && prec > 0) { // Remove trailing zeros and a trailing decimal point while (s[-1] == '0') { s--; } if (s[-1] == '.') { s--; } } // Append the exponent if (e_sign) { *s++ = e_char; *s++ = e_sign; if (FPMIN_BUF_SIZE == 7 && e >= 100) { *s++ = '0' + (e / 100); } *s++ = '0' + ((e / 10) % 10); *s++ = '0' + (e % 10); } *s = '\0'; // verify that we did not overrun the input buffer assert((size_t)(s + 1 - buf) <= buf_size); return s - buf; } #endif // MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE micropython-1.12/py/formatfloat.h000066400000000000000000000027551357706137100171520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_FORMATFLOAT_H #define MICROPY_INCLUDED_PY_FORMATFLOAT_H #include "py/mpconfig.h" #if MICROPY_PY_BUILTINS_FLOAT int mp_format_float(mp_float_t f, char *buf, size_t bufSize, char fmt, int prec, char sign); #endif #endif // MICROPY_INCLUDED_PY_FORMATFLOAT_H micropython-1.12/py/frozenmod.c000066400000000000000000000107671357706137100166340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Paul Sokolovsky * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/lexer.h" #include "py/frozenmod.h" #if MICROPY_MODULE_FROZEN_STR #ifndef MICROPY_MODULE_FROZEN_LEXER #define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str_len #else mp_lexer_t *MICROPY_MODULE_FROZEN_LEXER(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len); #endif extern const char mp_frozen_str_names[]; extern const uint32_t mp_frozen_str_sizes[]; extern const char mp_frozen_str_content[]; // On input, *len contains size of name, on output - size of content const char *mp_find_frozen_str(const char *str, size_t *len) { const char *name = mp_frozen_str_names; size_t offset = 0; for (int i = 0; *name != 0; i++) { size_t l = strlen(name); if (l == *len && !memcmp(str, name, l)) { *len = mp_frozen_str_sizes[i]; return mp_frozen_str_content + offset; } name += l + 1; offset += mp_frozen_str_sizes[i] + 1; } return NULL; } STATIC mp_lexer_t *mp_lexer_frozen_str(const char *str, size_t len) { size_t name_len = len; const char *content = mp_find_frozen_str(str, &len); if (content == NULL) { return NULL; } qstr source = qstr_from_strn(str, name_len); mp_lexer_t *lex = MICROPY_MODULE_FROZEN_LEXER(source, content, len, 0); return lex; } #endif #if MICROPY_MODULE_FROZEN_MPY #include "py/emitglue.h" extern const char mp_frozen_mpy_names[]; extern const mp_raw_code_t *const mp_frozen_mpy_content[]; STATIC const mp_raw_code_t *mp_find_frozen_mpy(const char *str, size_t len) { const char *name = mp_frozen_mpy_names; for (size_t i = 0; *name != 0; i++) { size_t l = strlen(name); if (l == len && !memcmp(str, name, l)) { return mp_frozen_mpy_content[i]; } name += l + 1; } return NULL; } #endif #if MICROPY_MODULE_FROZEN STATIC mp_import_stat_t mp_frozen_stat_helper(const char *name, const char *str) { size_t len = strlen(str); for (int i = 0; *name != 0; i++) { size_t l = strlen(name); if (l >= len && !memcmp(str, name, len)) { if (name[len] == 0) { return MP_IMPORT_STAT_FILE; } else if (name[len] == '/') { return MP_IMPORT_STAT_DIR; } } name += l + 1; } return MP_IMPORT_STAT_NO_EXIST; } mp_import_stat_t mp_frozen_stat(const char *str) { mp_import_stat_t stat; #if MICROPY_MODULE_FROZEN_STR stat = mp_frozen_stat_helper(mp_frozen_str_names, str); if (stat != MP_IMPORT_STAT_NO_EXIST) { return stat; } #endif #if MICROPY_MODULE_FROZEN_MPY stat = mp_frozen_stat_helper(mp_frozen_mpy_names, str); if (stat != MP_IMPORT_STAT_NO_EXIST) { return stat; } #endif return MP_IMPORT_STAT_NO_EXIST; } int mp_find_frozen_module(const char *str, size_t len, void **data) { #if MICROPY_MODULE_FROZEN_STR mp_lexer_t *lex = mp_lexer_frozen_str(str, len); if (lex != NULL) { *data = lex; return MP_FROZEN_STR; } #endif #if MICROPY_MODULE_FROZEN_MPY const mp_raw_code_t *rc = mp_find_frozen_mpy(str, len); if (rc != NULL) { *data = (void*)rc; return MP_FROZEN_MPY; } #endif return MP_FROZEN_NONE; } #endif micropython-1.12/py/frozenmod.h000066400000000000000000000031741357706137100166330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Paul Sokolovsky * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_FROZENMOD_H #define MICROPY_INCLUDED_PY_FROZENMOD_H #include "py/lexer.h" enum { MP_FROZEN_NONE, MP_FROZEN_STR, MP_FROZEN_MPY, }; int mp_find_frozen_module(const char *str, size_t len, void **data); const char *mp_find_frozen_str(const char *str, size_t *len); mp_import_stat_t mp_frozen_stat(const char *str); #endif // MICROPY_INCLUDED_PY_FROZENMOD_H micropython-1.12/py/gc.c000066400000000000000000001021521357706137100152100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/gc.h" #include "py/runtime.h" #if MICROPY_ENABLE_GC #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_PRINT (0) #define DEBUG_printf(...) (void)0 #endif // make this 1 to dump the heap each time it changes #define EXTENSIVE_HEAP_PROFILING (0) // make this 1 to zero out swept memory to more eagerly // detect untraced object still in use #define CLEAR_ON_SWEEP (0) #define WORDS_PER_BLOCK ((MICROPY_BYTES_PER_GC_BLOCK) / BYTES_PER_WORD) #define BYTES_PER_BLOCK (MICROPY_BYTES_PER_GC_BLOCK) // ATB = allocation table byte // 0b00 = FREE -- free block // 0b01 = HEAD -- head of a chain of blocks // 0b10 = TAIL -- in the tail of a chain of blocks // 0b11 = MARK -- marked head block #define AT_FREE (0) #define AT_HEAD (1) #define AT_TAIL (2) #define AT_MARK (3) #define BLOCKS_PER_ATB (4) #define ATB_MASK_0 (0x03) #define ATB_MASK_1 (0x0c) #define ATB_MASK_2 (0x30) #define ATB_MASK_3 (0xc0) #define ATB_0_IS_FREE(a) (((a) & ATB_MASK_0) == 0) #define ATB_1_IS_FREE(a) (((a) & ATB_MASK_1) == 0) #define ATB_2_IS_FREE(a) (((a) & ATB_MASK_2) == 0) #define ATB_3_IS_FREE(a) (((a) & ATB_MASK_3) == 0) #define BLOCK_SHIFT(block) (2 * ((block) & (BLOCKS_PER_ATB - 1))) #define ATB_GET_KIND(block) ((MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] >> BLOCK_SHIFT(block)) & 3) #define ATB_ANY_TO_FREE(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] &= (~(AT_MARK << BLOCK_SHIFT(block))); } while (0) #define ATB_FREE_TO_HEAD(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_HEAD << BLOCK_SHIFT(block)); } while (0) #define ATB_FREE_TO_TAIL(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_TAIL << BLOCK_SHIFT(block)); } while (0) #define ATB_HEAD_TO_MARK(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0) #define ATB_MARK_TO_HEAD(block) do { MP_STATE_MEM(gc_alloc_table_start)[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0) #define BLOCK_FROM_PTR(ptr) (((byte*)(ptr) - MP_STATE_MEM(gc_pool_start)) / BYTES_PER_BLOCK) #define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (uintptr_t)MP_STATE_MEM(gc_pool_start))) #define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB) #if MICROPY_ENABLE_FINALISER // FTB = finaliser table byte // if set, then the corresponding block may have a finaliser #define BLOCKS_PER_FTB (8) #define FTB_GET(block) ((MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] >> ((block) & 7)) & 1) #define FTB_SET(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] |= (1 << ((block) & 7)); } while (0) #define FTB_CLEAR(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0) #endif #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL #define GC_ENTER() mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1) #define GC_EXIT() mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex)) #else #define GC_ENTER() #define GC_EXIT() #endif // TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool void gc_init(void *start, void *end) { // align end pointer on block boundary end = (void*)((uintptr_t)end & (~(BYTES_PER_BLOCK - 1))); DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte*)end - (byte*)start); // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes): // T = A + F + P // F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB // P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK) size_t total_byte_len = (byte*)end - (byte*)start; #if MICROPY_ENABLE_FINALISER MP_STATE_MEM(gc_alloc_table_byte_len) = total_byte_len * BITS_PER_BYTE / (BITS_PER_BYTE + BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK); #else MP_STATE_MEM(gc_alloc_table_byte_len) = total_byte_len / (1 + BITS_PER_BYTE / 2 * BYTES_PER_BLOCK); #endif MP_STATE_MEM(gc_alloc_table_start) = (byte*)start; #if MICROPY_ENABLE_FINALISER size_t gc_finaliser_table_byte_len = (MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; MP_STATE_MEM(gc_finaliser_table_start) = MP_STATE_MEM(gc_alloc_table_start) + MP_STATE_MEM(gc_alloc_table_byte_len); #endif size_t gc_pool_block_len = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; MP_STATE_MEM(gc_pool_start) = (byte*)end - gc_pool_block_len * BYTES_PER_BLOCK; MP_STATE_MEM(gc_pool_end) = end; #if MICROPY_ENABLE_FINALISER assert(MP_STATE_MEM(gc_pool_start) >= MP_STATE_MEM(gc_finaliser_table_start) + gc_finaliser_table_byte_len); #endif // clear ATBs memset(MP_STATE_MEM(gc_alloc_table_start), 0, MP_STATE_MEM(gc_alloc_table_byte_len)); #if MICROPY_ENABLE_FINALISER // clear FTBs memset(MP_STATE_MEM(gc_finaliser_table_start), 0, gc_finaliser_table_byte_len); #endif // set last free ATB index to start of heap MP_STATE_MEM(gc_last_free_atb_index) = 0; // unlock the GC MP_STATE_MEM(gc_lock_depth) = 0; // allow auto collection MP_STATE_MEM(gc_auto_collect_enabled) = 1; #if MICROPY_GC_ALLOC_THRESHOLD // by default, maxuint for gc threshold, effectively turning gc-by-threshold off MP_STATE_MEM(gc_alloc_threshold) = (size_t)-1; MP_STATE_MEM(gc_alloc_amount) = 0; #endif #if MICROPY_PY_THREAD mp_thread_mutex_init(&MP_STATE_MEM(gc_mutex)); #endif DEBUG_printf("GC layout:\n"); DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(gc_alloc_table_start), MP_STATE_MEM(gc_alloc_table_byte_len), MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB); #if MICROPY_ENABLE_FINALISER DEBUG_printf(" finaliser table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(gc_finaliser_table_start), gc_finaliser_table_byte_len, gc_finaliser_table_byte_len * BLOCKS_PER_FTB); #endif DEBUG_printf(" pool at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(gc_pool_start), gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len); } void gc_lock(void) { GC_ENTER(); MP_STATE_MEM(gc_lock_depth)++; GC_EXIT(); } void gc_unlock(void) { GC_ENTER(); MP_STATE_MEM(gc_lock_depth)--; GC_EXIT(); } bool gc_is_locked(void) { return MP_STATE_MEM(gc_lock_depth) != 0; } // ptr should be of type void* #define VERIFY_PTR(ptr) ( \ ((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \ && ptr >= (void*)MP_STATE_MEM(gc_pool_start) /* must be above start of pool */ \ && ptr < (void*)MP_STATE_MEM(gc_pool_end) /* must be below end of pool */ \ ) #ifndef TRACE_MARK #if DEBUG_PRINT #define TRACE_MARK(block, ptr) DEBUG_printf("gc_mark(%p)\n", ptr) #else #define TRACE_MARK(block, ptr) #endif #endif // Take the given block as the topmost block on the stack. Check all it's // children: mark the unmarked child blocks and put those newly marked // blocks on the stack. When all children have been checked, pop off the // topmost block on the stack and repeat with that one. STATIC void gc_mark_subtree(size_t block) { // Start with the block passed in the argument. size_t sp = 0; for (;;) { // work out number of consecutive blocks in the chain starting with this one size_t n_blocks = 0; do { n_blocks += 1; } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL); // check this block's children void **ptrs = (void**)PTR_FROM_BLOCK(block); for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void*); i > 0; i--, ptrs++) { void *ptr = *ptrs; if (VERIFY_PTR(ptr)) { // Mark and push this pointer size_t childblock = BLOCK_FROM_PTR(ptr); if (ATB_GET_KIND(childblock) == AT_HEAD) { // an unmarked head, mark it, and push it on gc stack TRACE_MARK(childblock, ptr); ATB_HEAD_TO_MARK(childblock); if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { MP_STATE_MEM(gc_stack)[sp++] = childblock; } else { MP_STATE_MEM(gc_stack_overflow) = 1; } } } } // Are there any blocks on the stack? if (sp == 0) { break; // No, stack is empty, we're done. } // pop the next block off the stack block = MP_STATE_MEM(gc_stack)[--sp]; } } STATIC void gc_deal_with_stack_overflow(void) { while (MP_STATE_MEM(gc_stack_overflow)) { MP_STATE_MEM(gc_stack_overflow) = 0; // scan entire memory looking for blocks which have been marked but not their children for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { // trace (again) if mark bit set if (ATB_GET_KIND(block) == AT_MARK) { gc_mark_subtree(block); } } } } STATIC void gc_sweep(void) { #if MICROPY_PY_GC_COLLECT_RETVAL MP_STATE_MEM(gc_collected) = 0; #endif // free unmarked heads and their tails int free_tail = 0; for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { switch (ATB_GET_KIND(block)) { case AT_HEAD: #if MICROPY_ENABLE_FINALISER if (FTB_GET(block)) { mp_obj_base_t *obj = (mp_obj_base_t*)PTR_FROM_BLOCK(block); if (obj->type != NULL) { // if the object has a type then see if it has a __del__ method mp_obj_t dest[2]; mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest); if (dest[0] != MP_OBJ_NULL) { // load_method returned a method, execute it in a protected environment #if MICROPY_ENABLE_SCHEDULER mp_sched_lock(); #endif mp_call_function_1_protected(dest[0], dest[1]); #if MICROPY_ENABLE_SCHEDULER mp_sched_unlock(); #endif } } // clear finaliser flag FTB_CLEAR(block); } #endif free_tail = 1; DEBUG_printf("gc_sweep(%p)\n", PTR_FROM_BLOCK(block)); #if MICROPY_PY_GC_COLLECT_RETVAL MP_STATE_MEM(gc_collected)++; #endif // fall through to free the head case AT_TAIL: if (free_tail) { ATB_ANY_TO_FREE(block); #if CLEAR_ON_SWEEP memset((void*)PTR_FROM_BLOCK(block), 0, BYTES_PER_BLOCK); #endif } break; case AT_MARK: ATB_MARK_TO_HEAD(block); free_tail = 0; break; } } } void gc_collect_start(void) { GC_ENTER(); MP_STATE_MEM(gc_lock_depth)++; #if MICROPY_GC_ALLOC_THRESHOLD MP_STATE_MEM(gc_alloc_amount) = 0; #endif MP_STATE_MEM(gc_stack_overflow) = 0; // Trace root pointers. This relies on the root pointers being organised // correctly in the mp_state_ctx structure. We scan nlr_top, dict_locals, // dict_globals, then the root pointer section of mp_state_vm. void **ptrs = (void**)(void*)&mp_state_ctx; size_t root_start = offsetof(mp_state_ctx_t, thread.dict_locals); size_t root_end = offsetof(mp_state_ctx_t, vm.qstr_last_chunk); gc_collect_root(ptrs + root_start / sizeof(void*), (root_end - root_start) / sizeof(void*)); #if MICROPY_ENABLE_PYSTACK // Trace root pointers from the Python stack. ptrs = (void**)(void*)MP_STATE_THREAD(pystack_start); gc_collect_root(ptrs, (MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start)) / sizeof(void*)); #endif } void gc_collect_root(void **ptrs, size_t len) { for (size_t i = 0; i < len; i++) { void *ptr = ptrs[i]; if (VERIFY_PTR(ptr)) { size_t block = BLOCK_FROM_PTR(ptr); if (ATB_GET_KIND(block) == AT_HEAD) { // An unmarked head: mark it, and mark all its children TRACE_MARK(block, ptr); ATB_HEAD_TO_MARK(block); gc_mark_subtree(block); } } } } void gc_collect_end(void) { gc_deal_with_stack_overflow(); gc_sweep(); MP_STATE_MEM(gc_last_free_atb_index) = 0; MP_STATE_MEM(gc_lock_depth)--; GC_EXIT(); } void gc_sweep_all(void) { GC_ENTER(); MP_STATE_MEM(gc_lock_depth)++; MP_STATE_MEM(gc_stack_overflow) = 0; gc_collect_end(); } void gc_info(gc_info_t *info) { GC_ENTER(); info->total = MP_STATE_MEM(gc_pool_end) - MP_STATE_MEM(gc_pool_start); info->used = 0; info->free = 0; info->max_free = 0; info->num_1block = 0; info->num_2block = 0; info->max_block = 0; bool finish = false; for (size_t block = 0, len = 0, len_free = 0; !finish;) { size_t kind = ATB_GET_KIND(block); switch (kind) { case AT_FREE: info->free += 1; len_free += 1; len = 0; break; case AT_HEAD: info->used += 1; len = 1; break; case AT_TAIL: info->used += 1; len += 1; break; case AT_MARK: // shouldn't happen break; } block++; finish = (block == MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB); // Get next block type if possible if (!finish) { kind = ATB_GET_KIND(block); } if (finish || kind == AT_FREE || kind == AT_HEAD) { if (len == 1) { info->num_1block += 1; } else if (len == 2) { info->num_2block += 1; } if (len > info->max_block) { info->max_block = len; } if (finish || kind == AT_HEAD) { if (len_free > info->max_free) { info->max_free = len_free; } len_free = 0; } } } info->used *= BYTES_PER_BLOCK; info->free *= BYTES_PER_BLOCK; GC_EXIT(); } void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { bool has_finaliser = alloc_flags & GC_ALLOC_FLAG_HAS_FINALISER; size_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK; DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks); // check for 0 allocation if (n_blocks == 0) { return NULL; } GC_ENTER(); // check if GC is locked if (MP_STATE_MEM(gc_lock_depth) > 0) { GC_EXIT(); return NULL; } size_t i; size_t end_block; size_t start_block; size_t n_free; int collected = !MP_STATE_MEM(gc_auto_collect_enabled); #if MICROPY_GC_ALLOC_THRESHOLD if (!collected && MP_STATE_MEM(gc_alloc_amount) >= MP_STATE_MEM(gc_alloc_threshold)) { GC_EXIT(); gc_collect(); collected = 1; GC_ENTER(); } #endif for (;;) { // look for a run of n_blocks available blocks n_free = 0; for (i = MP_STATE_MEM(gc_last_free_atb_index); i < MP_STATE_MEM(gc_alloc_table_byte_len); i++) { byte a = MP_STATE_MEM(gc_alloc_table_start)[i]; if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; } if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; } if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; } if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; } } GC_EXIT(); // nothing found! if (collected) { return NULL; } DEBUG_printf("gc_alloc(" UINT_FMT "): no free mem, triggering GC\n", n_bytes); gc_collect(); collected = 1; GC_ENTER(); } // found, ending at block i inclusive found: // get starting and end blocks, both inclusive end_block = i; start_block = i - n_free + 1; // Set last free ATB index to block after last block we found, for start of // next scan. To reduce fragmentation, we only do this if we were looking // for a single free block, which guarantees that there are no free blocks // before this one. Also, whenever we free or shink a block we must check // if this index needs adjusting (see gc_realloc and gc_free). if (n_free == 1) { MP_STATE_MEM(gc_last_free_atb_index) = (i + 1) / BLOCKS_PER_ATB; } // mark first block as used head ATB_FREE_TO_HEAD(start_block); // mark rest of blocks as used tail // TODO for a run of many blocks can make this more efficient for (size_t bl = start_block + 1; bl <= end_block; bl++) { ATB_FREE_TO_TAIL(bl); } // get pointer to first block // we must create this pointer before unlocking the GC so a collection can find it void *ret_ptr = (void*)(MP_STATE_MEM(gc_pool_start) + start_block * BYTES_PER_BLOCK); DEBUG_printf("gc_alloc(%p)\n", ret_ptr); #if MICROPY_GC_ALLOC_THRESHOLD MP_STATE_MEM(gc_alloc_amount) += n_blocks; #endif GC_EXIT(); #if MICROPY_GC_CONSERVATIVE_CLEAR // be conservative and zero out all the newly allocated blocks memset((byte*)ret_ptr, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK); #else // zero out the additional bytes of the newly allocated blocks // This is needed because the blocks may have previously held pointers // to the heap and will not be set to something else if the caller // doesn't actually use the entire block. As such they will continue // to point to the heap and may prevent other blocks from being reclaimed. memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes); #endif #if MICROPY_ENABLE_FINALISER if (has_finaliser) { // clear type pointer in case it is never set ((mp_obj_base_t*)ret_ptr)->type = NULL; // set mp_obj flag only if it has a finaliser GC_ENTER(); FTB_SET(start_block); GC_EXIT(); } #else (void)has_finaliser; #endif #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(); #endif return ret_ptr; } /* void *gc_alloc(mp_uint_t n_bytes) { return _gc_alloc(n_bytes, false); } void *gc_alloc_with_finaliser(mp_uint_t n_bytes) { return _gc_alloc(n_bytes, true); } */ // force the freeing of a piece of memory // TODO: freeing here does not call finaliser void gc_free(void *ptr) { GC_ENTER(); if (MP_STATE_MEM(gc_lock_depth) > 0) { // TODO how to deal with this error? GC_EXIT(); return; } DEBUG_printf("gc_free(%p)\n", ptr); if (ptr == NULL) { GC_EXIT(); } else { // get the GC block number corresponding to this pointer assert(VERIFY_PTR(ptr)); size_t block = BLOCK_FROM_PTR(ptr); assert(ATB_GET_KIND(block) == AT_HEAD); #if MICROPY_ENABLE_FINALISER FTB_CLEAR(block); #endif // set the last_free pointer to this block if it's earlier in the heap if (block / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) { MP_STATE_MEM(gc_last_free_atb_index) = block / BLOCKS_PER_ATB; } // free head and all of its tail blocks do { ATB_ANY_TO_FREE(block); block += 1; } while (ATB_GET_KIND(block) == AT_TAIL); GC_EXIT(); #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(); #endif } } size_t gc_nbytes(const void *ptr) { GC_ENTER(); if (VERIFY_PTR(ptr)) { size_t block = BLOCK_FROM_PTR(ptr); if (ATB_GET_KIND(block) == AT_HEAD) { // work out number of consecutive blocks in the chain starting with this on size_t n_blocks = 0; do { n_blocks += 1; } while (ATB_GET_KIND(block + n_blocks) == AT_TAIL); GC_EXIT(); return n_blocks * BYTES_PER_BLOCK; } } // invalid pointer GC_EXIT(); return 0; } #if 0 // old, simple realloc that didn't expand memory in place void *gc_realloc(void *ptr, mp_uint_t n_bytes) { mp_uint_t n_existing = gc_nbytes(ptr); if (n_bytes <= n_existing) { return ptr; } else { bool has_finaliser; if (ptr == NULL) { has_finaliser = false; } else { #if MICROPY_ENABLE_FINALISER has_finaliser = FTB_GET(BLOCK_FROM_PTR((mp_uint_t)ptr)); #else has_finaliser = false; #endif } void *ptr2 = gc_alloc(n_bytes, has_finaliser); if (ptr2 == NULL) { return ptr2; } memcpy(ptr2, ptr, n_existing); gc_free(ptr); return ptr2; } } #else // Alternative gc_realloc impl void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // check for pure allocation if (ptr_in == NULL) { return gc_alloc(n_bytes, false); } // check for pure free if (n_bytes == 0) { gc_free(ptr_in); return NULL; } void *ptr = ptr_in; GC_ENTER(); if (MP_STATE_MEM(gc_lock_depth) > 0) { GC_EXIT(); return NULL; } // get the GC block number corresponding to this pointer assert(VERIFY_PTR(ptr)); size_t block = BLOCK_FROM_PTR(ptr); assert(ATB_GET_KIND(block) == AT_HEAD); // compute number of new blocks that are requested size_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; // Get the total number of consecutive blocks that are already allocated to // this chunk of memory, and then count the number of free blocks following // it. Stop if we reach the end of the heap, or if we find enough extra // free blocks to satisfy the realloc. Note that we need to compute the // total size of the existing memory chunk so we can correctly and // efficiently shrink it (see below for shrinking code). size_t n_free = 0; size_t n_blocks = 1; // counting HEAD block size_t max_block = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; for (size_t bl = block + n_blocks; bl < max_block; bl++) { byte block_type = ATB_GET_KIND(bl); if (block_type == AT_TAIL) { n_blocks++; continue; } if (block_type == AT_FREE) { n_free++; if (n_blocks + n_free >= new_blocks) { // stop as soon as we find enough blocks for n_bytes break; } continue; } break; } // return original ptr if it already has the requested number of blocks if (new_blocks == n_blocks) { GC_EXIT(); return ptr_in; } // check if we can shrink the allocated area if (new_blocks < n_blocks) { // free unneeded tail blocks for (size_t bl = block + new_blocks, count = n_blocks - new_blocks; count > 0; bl++, count--) { ATB_ANY_TO_FREE(bl); } // set the last_free pointer to end of this block if it's earlier in the heap if ((block + new_blocks) / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) { MP_STATE_MEM(gc_last_free_atb_index) = (block + new_blocks) / BLOCKS_PER_ATB; } GC_EXIT(); #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(); #endif return ptr_in; } // check if we can expand in place if (new_blocks <= n_blocks + n_free) { // mark few more blocks as used tail for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) { assert(ATB_GET_KIND(bl) == AT_FREE); ATB_FREE_TO_TAIL(bl); } GC_EXIT(); #if MICROPY_GC_CONSERVATIVE_CLEAR // be conservative and zero out all the newly allocated blocks memset((byte*)ptr_in + n_blocks * BYTES_PER_BLOCK, 0, (new_blocks - n_blocks) * BYTES_PER_BLOCK); #else // zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc) memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes); #endif #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(); #endif return ptr_in; } #if MICROPY_ENABLE_FINALISER bool ftb_state = FTB_GET(block); #else bool ftb_state = false; #endif GC_EXIT(); if (!allow_move) { // not allowed to move memory block so return failure return NULL; } // can't resize inplace; try to find a new contiguous chain void *ptr_out = gc_alloc(n_bytes, ftb_state); // check that the alloc succeeded if (ptr_out == NULL) { return NULL; } DEBUG_printf("gc_realloc(%p -> %p)\n", ptr_in, ptr_out); memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK); gc_free(ptr_in); return ptr_out; } #endif // Alternative gc_realloc impl void gc_dump_info(void) { gc_info_t info; gc_info(&info); mp_printf(&mp_plat_print, "GC: total: %u, used: %u, free: %u\n", (uint)info.total, (uint)info.used, (uint)info.free); mp_printf(&mp_plat_print, " No. of 1-blocks: %u, 2-blocks: %u, max blk sz: %u, max free sz: %u\n", (uint)info.num_1block, (uint)info.num_2block, (uint)info.max_block, (uint)info.max_free); } void gc_dump_alloc_table(void) { GC_ENTER(); static const size_t DUMP_BYTES_PER_LINE = 64; #if !EXTENSIVE_HEAP_PROFILING // When comparing heap output we don't want to print the starting // pointer of the heap because it changes from run to run. mp_printf(&mp_plat_print, "GC memory layout; from %p:", MP_STATE_MEM(gc_pool_start)); #endif for (size_t bl = 0; bl < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; bl++) { if (bl % DUMP_BYTES_PER_LINE == 0) { // a new line of blocks { // check if this line contains only free blocks size_t bl2 = bl; while (bl2 < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB && ATB_GET_KIND(bl2) == AT_FREE) { bl2++; } if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) { // there are at least 2 lines containing only free blocks, so abbreviate their printing mp_printf(&mp_plat_print, "\n (%u lines all free)", (uint)(bl2 - bl) / DUMP_BYTES_PER_LINE); bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1)); if (bl >= MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB) { // got to end of heap break; } } } // print header for new line of blocks // (the cast to uint32_t is for 16-bit ports) //mp_printf(&mp_plat_print, "\n%05x: ", (uint)(PTR_FROM_BLOCK(bl) & (uint32_t)0xfffff)); mp_printf(&mp_plat_print, "\n%05x: ", (uint)((bl * BYTES_PER_BLOCK) & (uint32_t)0xfffff)); } int c = ' '; switch (ATB_GET_KIND(bl)) { case AT_FREE: c = '.'; break; /* this prints out if the object is reachable from BSS or STACK (for unix only) case AT_HEAD: { c = 'h'; void **ptrs = (void**)(void*)&mp_state_ctx; mp_uint_t len = offsetof(mp_state_ctx_t, vm.stack_top) / sizeof(mp_uint_t); for (mp_uint_t i = 0; i < len; i++) { mp_uint_t ptr = (mp_uint_t)ptrs[i]; if (VERIFY_PTR(ptr) && BLOCK_FROM_PTR(ptr) == bl) { c = 'B'; break; } } if (c == 'h') { ptrs = (void**)&c; len = ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&c) / sizeof(mp_uint_t); for (mp_uint_t i = 0; i < len; i++) { mp_uint_t ptr = (mp_uint_t)ptrs[i]; if (VERIFY_PTR(ptr) && BLOCK_FROM_PTR(ptr) == bl) { c = 'S'; break; } } } break; } */ /* this prints the uPy object type of the head block */ case AT_HEAD: { void **ptr = (void**)(MP_STATE_MEM(gc_pool_start) + bl * BYTES_PER_BLOCK); if (*ptr == &mp_type_tuple) { c = 'T'; } else if (*ptr == &mp_type_list) { c = 'L'; } else if (*ptr == &mp_type_dict) { c = 'D'; } else if (*ptr == &mp_type_str || *ptr == &mp_type_bytes) { c = 'S'; } #if MICROPY_PY_BUILTINS_BYTEARRAY else if (*ptr == &mp_type_bytearray) { c = 'A'; } #endif #if MICROPY_PY_ARRAY else if (*ptr == &mp_type_array) { c = 'A'; } #endif #if MICROPY_PY_BUILTINS_FLOAT else if (*ptr == &mp_type_float) { c = 'F'; } #endif else if (*ptr == &mp_type_fun_bc) { c = 'B'; } else if (*ptr == &mp_type_module) { c = 'M'; } else { c = 'h'; #if 0 // This code prints "Q" for qstr-pool data, and "q" for qstr-str // data. It can be useful to see how qstrs are being allocated, // but is disabled by default because it is very slow. for (qstr_pool_t *pool = MP_STATE_VM(last_pool); c == 'h' && pool != NULL; pool = pool->prev) { if ((qstr_pool_t*)ptr == pool) { c = 'Q'; break; } for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) { if ((const byte*)ptr == *q) { c = 'q'; break; } } } #endif } break; } case AT_TAIL: c = '='; break; case AT_MARK: c = 'm'; break; } mp_printf(&mp_plat_print, "%c", c); } mp_print_str(&mp_plat_print, "\n"); GC_EXIT(); } #if 0 // For testing the GC functions void gc_test(void) { mp_uint_t len = 500; mp_uint_t *heap = malloc(len); gc_init(heap, heap + len / sizeof(mp_uint_t)); void *ptrs[100]; { mp_uint_t **p = gc_alloc(16, false); p[0] = gc_alloc(64, false); p[1] = gc_alloc(1, false); p[2] = gc_alloc(1, false); p[3] = gc_alloc(1, false); mp_uint_t ***p2 = gc_alloc(16, false); p2[0] = p; p2[1] = p; ptrs[0] = p2; } for (int i = 0; i < 25; i+=2) { mp_uint_t *p = gc_alloc(i, false); printf("p=%p\n", p); if (i & 3) { //ptrs[i] = p; } } printf("Before GC:\n"); gc_dump_alloc_table(); printf("Starting GC...\n"); gc_collect_start(); gc_collect_root(ptrs, sizeof(ptrs) / sizeof(void*)); gc_collect_end(); printf("After GC:\n"); gc_dump_alloc_table(); } #endif #endif // MICROPY_ENABLE_GC micropython-1.12/py/gc.h000066400000000000000000000046161357706137100152230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_GC_H #define MICROPY_INCLUDED_PY_GC_H #include #include "py/mpconfig.h" #include "py/misc.h" void gc_init(void *start, void *end); // These lock/unlock functions can be nested. // They can be used to prevent the GC from allocating/freeing. void gc_lock(void); void gc_unlock(void); bool gc_is_locked(void); // A given port must implement gc_collect by using the other collect functions. void gc_collect(void); void gc_collect_start(void); void gc_collect_root(void **ptrs, size_t len); void gc_collect_end(void); // Use this function to sweep the whole heap and run all finalisers void gc_sweep_all(void); enum { GC_ALLOC_FLAG_HAS_FINALISER = 1, }; void *gc_alloc(size_t n_bytes, unsigned int alloc_flags); void gc_free(void *ptr); // does not call finaliser size_t gc_nbytes(const void *ptr); void *gc_realloc(void *ptr, size_t n_bytes, bool allow_move); typedef struct _gc_info_t { size_t total; size_t used; size_t free; size_t max_free; size_t num_1block; size_t num_2block; size_t max_block; } gc_info_t; void gc_info(gc_info_t *info); void gc_dump_info(void); void gc_dump_alloc_table(void); #endif // MICROPY_INCLUDED_PY_GC_H micropython-1.12/py/grammar.h000066400000000000000000000547521357706137100162660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // rules for writing rules: // - zero_or_more is implemented using opt_rule around a one_or_more rule // - don't put opt_rule in arguments of or rule; instead, wrap the call to this or rule in opt_rule // # Start symbols for the grammar: // # single_input is a single interactive statement; // # file_input is a module or sequence of commands read from an input file; // # eval_input is the input for the eval() functions. // # NB: compound_stmt in single_input is followed by extra NEWLINE! --> not in MicroPython // single_input: NEWLINE | simple_stmt | compound_stmt // file_input: (NEWLINE | stmt)* ENDMARKER // eval_input: testlist NEWLINE* ENDMARKER DEF_RULE_NC(single_input, or(3), tok(NEWLINE), rule(simple_stmt), rule(compound_stmt)) DEF_RULE(file_input, c(generic_all_nodes), and_ident(1), opt_rule(file_input_2)) DEF_RULE(file_input_2, c(generic_all_nodes), one_or_more, rule(file_input_3)) DEF_RULE_NC(file_input_3, or(2), tok(NEWLINE), rule(stmt)) DEF_RULE_NC(eval_input, and_ident(2), rule(testlist), opt_rule(eval_input_2)) DEF_RULE_NC(eval_input_2, and(1), tok(NEWLINE)) // decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE // decorators: decorator+ // decorated: decorators (classdef | funcdef | async_funcdef) // funcdef: 'def' NAME parameters ['->' test] ':' suite // async_funcdef: 'async' funcdef // parameters: '(' [typedargslist] ')' // typedargslist: tfpdef ['=' test] (',' tfpdef ['=' test])* [',' ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]] | '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef // tfpdef: NAME [':' test] // varargslist: vfpdef ['=' test] (',' vfpdef ['=' test])* [',' ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef // vfpdef: NAME DEF_RULE_NC(decorator, and(4), tok(OP_AT), rule(dotted_name), opt_rule(trailer_paren), tok(NEWLINE)) DEF_RULE_NC(decorators, one_or_more, rule(decorator)) DEF_RULE(decorated, c(decorated), and_ident(2), rule(decorators), rule(decorated_body)) #if MICROPY_PY_ASYNC_AWAIT DEF_RULE_NC(decorated_body, or(3), rule(classdef), rule(funcdef), rule(async_funcdef)) DEF_RULE_NC(async_funcdef, and(2), tok(KW_ASYNC), rule(funcdef)) #else DEF_RULE_NC(decorated_body, or(2), rule(classdef), rule(funcdef)) #endif DEF_RULE(funcdef, c(funcdef), and_blank(8), tok(KW_DEF), tok(NAME), tok(DEL_PAREN_OPEN), opt_rule(typedargslist), tok(DEL_PAREN_CLOSE), opt_rule(funcdefrettype), tok(DEL_COLON), rule(suite)) DEF_RULE_NC(funcdefrettype, and_ident(2), tok(DEL_MINUS_MORE), rule(test)) // note: typedargslist lets through more than is allowed, compiler does further checks DEF_RULE_NC(typedargslist, list_with_end, rule(typedargslist_item), tok(DEL_COMMA)) DEF_RULE_NC(typedargslist_item, or(3), rule(typedargslist_name), rule(typedargslist_star), rule(typedargslist_dbl_star)) DEF_RULE_NC(typedargslist_name, and_ident(3), tok(NAME), opt_rule(typedargslist_colon), opt_rule(typedargslist_equal)) DEF_RULE_NC(typedargslist_star, and(2), tok(OP_STAR), opt_rule(tfpdef)) DEF_RULE_NC(typedargslist_dbl_star, and(3), tok(OP_DBL_STAR), tok(NAME), opt_rule(typedargslist_colon)) DEF_RULE_NC(typedargslist_colon, and_ident(2), tok(DEL_COLON), rule(test)) DEF_RULE_NC(typedargslist_equal, and_ident(2), tok(DEL_EQUAL), rule(test)) DEF_RULE_NC(tfpdef, and(2), tok(NAME), opt_rule(typedargslist_colon)) // note: varargslist lets through more than is allowed, compiler does further checks DEF_RULE_NC(varargslist, list_with_end, rule(varargslist_item), tok(DEL_COMMA)) DEF_RULE_NC(varargslist_item, or(3), rule(varargslist_name), rule(varargslist_star), rule(varargslist_dbl_star)) DEF_RULE_NC(varargslist_name, and_ident(2), tok(NAME), opt_rule(varargslist_equal)) DEF_RULE_NC(varargslist_star, and(2), tok(OP_STAR), opt_rule(vfpdef)) DEF_RULE_NC(varargslist_dbl_star, and(2), tok(OP_DBL_STAR), tok(NAME)) DEF_RULE_NC(varargslist_equal, and_ident(2), tok(DEL_EQUAL), rule(test)) DEF_RULE_NC(vfpdef, and_ident(1), tok(NAME)) // stmt: compound_stmt | simple_stmt DEF_RULE_NC(stmt, or(2), rule(compound_stmt), rule(simple_stmt)) // simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE DEF_RULE_NC(simple_stmt, and_ident(2), rule(simple_stmt_2), tok(NEWLINE)) DEF_RULE(simple_stmt_2, c(generic_all_nodes), list_with_end, rule(small_stmt), tok(DEL_SEMICOLON)) // small_stmt: expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt // expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) // testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] // augassign: '+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=' // # For normal assignments, additional restrictions enforced by the interpreter DEF_RULE_NC(small_stmt, or(8), rule(del_stmt), rule(pass_stmt), rule(flow_stmt), rule(import_stmt), rule(global_stmt), rule(nonlocal_stmt), rule(assert_stmt), rule(expr_stmt)) DEF_RULE(expr_stmt, c(expr_stmt), and(2), rule(testlist_star_expr), opt_rule(expr_stmt_2)) DEF_RULE_NC(expr_stmt_2, or(2), rule(expr_stmt_augassign), rule(expr_stmt_assign_list)) DEF_RULE_NC(expr_stmt_augassign, and_ident(2), rule(augassign), rule(expr_stmt_6)) DEF_RULE_NC(expr_stmt_assign_list, one_or_more, rule(expr_stmt_assign)) DEF_RULE_NC(expr_stmt_assign, and_ident(2), tok(DEL_EQUAL), rule(expr_stmt_6)) DEF_RULE_NC(expr_stmt_6, or(2), rule(yield_expr), rule(testlist_star_expr)) DEF_RULE(testlist_star_expr, c(generic_tuple), list_with_end, rule(testlist_star_expr_2), tok(DEL_COMMA)) DEF_RULE_NC(testlist_star_expr_2, or(2), rule(star_expr), rule(test)) DEF_RULE_NC(augassign, or(13), tok(DEL_PLUS_EQUAL), tok(DEL_MINUS_EQUAL), tok(DEL_STAR_EQUAL), tok(DEL_AT_EQUAL), tok(DEL_SLASH_EQUAL), tok(DEL_PERCENT_EQUAL), tok(DEL_AMPERSAND_EQUAL), tok(DEL_PIPE_EQUAL), tok(DEL_CARET_EQUAL), tok(DEL_DBL_LESS_EQUAL), tok(DEL_DBL_MORE_EQUAL), tok(DEL_DBL_STAR_EQUAL), tok(DEL_DBL_SLASH_EQUAL)) // del_stmt: 'del' exprlist // pass_stmt: 'pass' // flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt // break_stmt: 'break' // continue_stmt: 'continue' // return_stmt: 'return' [testlist] // yield_stmt: yield_expr // raise_stmt: 'raise' [test ['from' test]] DEF_RULE(del_stmt, c(del_stmt), and(2), tok(KW_DEL), rule(exprlist)) DEF_RULE(pass_stmt, c(generic_all_nodes), and(1), tok(KW_PASS)) DEF_RULE_NC(flow_stmt, or(5), rule(break_stmt), rule(continue_stmt), rule(return_stmt), rule(raise_stmt), rule(yield_stmt)) DEF_RULE(break_stmt, c(break_cont_stmt), and(1), tok(KW_BREAK)) DEF_RULE(continue_stmt, c(break_cont_stmt), and(1), tok(KW_CONTINUE)) DEF_RULE(return_stmt, c(return_stmt), and(2), tok(KW_RETURN), opt_rule(testlist)) DEF_RULE(yield_stmt, c(yield_stmt), and(1), rule(yield_expr)) DEF_RULE(raise_stmt, c(raise_stmt), and(2), tok(KW_RAISE), opt_rule(raise_stmt_arg)) DEF_RULE_NC(raise_stmt_arg, and_ident(2), rule(test), opt_rule(raise_stmt_from)) DEF_RULE_NC(raise_stmt_from, and_ident(2), tok(KW_FROM), rule(test)) // import_stmt: import_name | import_from // import_name: 'import' dotted_as_names // import_from: 'from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ('*' | '(' import_as_names ')' | import_as_names) // import_as_name: NAME ['as' NAME] // dotted_as_name: dotted_name ['as' NAME] // import_as_names: import_as_name (',' import_as_name)* [','] // dotted_as_names: dotted_as_name (',' dotted_as_name)* // dotted_name: NAME ('.' NAME)* // global_stmt: 'global' NAME (',' NAME)* // nonlocal_stmt: 'nonlocal' NAME (',' NAME)* // assert_stmt: 'assert' test [',' test] DEF_RULE_NC(import_stmt, or(2), rule(import_name), rule(import_from)) DEF_RULE(import_name, c(import_name), and(2), tok(KW_IMPORT), rule(dotted_as_names)) DEF_RULE(import_from, c(import_from), and(4), tok(KW_FROM), rule(import_from_2), tok(KW_IMPORT), rule(import_from_3)) DEF_RULE_NC(import_from_2, or(2), rule(dotted_name), rule(import_from_2b)) DEF_RULE_NC(import_from_2b, and_ident(2), rule(one_or_more_period_or_ellipsis), opt_rule(dotted_name)) DEF_RULE_NC(import_from_3, or(3), tok(OP_STAR), rule(import_as_names_paren), rule(import_as_names)) DEF_RULE_NC(import_as_names_paren, and_ident(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE)) DEF_RULE_NC(one_or_more_period_or_ellipsis, one_or_more, rule(period_or_ellipsis)) DEF_RULE_NC(period_or_ellipsis, or(2), tok(DEL_PERIOD), tok(ELLIPSIS)) DEF_RULE_NC(import_as_name, and(2), tok(NAME), opt_rule(as_name)) DEF_RULE_NC(dotted_as_name, and_ident(2), rule(dotted_name), opt_rule(as_name)) DEF_RULE_NC(as_name, and_ident(2), tok(KW_AS), tok(NAME)) DEF_RULE_NC(import_as_names, list_with_end, rule(import_as_name), tok(DEL_COMMA)) DEF_RULE_NC(dotted_as_names, list, rule(dotted_as_name), tok(DEL_COMMA)) DEF_RULE_NC(dotted_name, list, tok(NAME), tok(DEL_PERIOD)) DEF_RULE(global_stmt, c(global_nonlocal_stmt), and(2), tok(KW_GLOBAL), rule(name_list)) DEF_RULE(nonlocal_stmt, c(global_nonlocal_stmt), and(2), tok(KW_NONLOCAL), rule(name_list)) DEF_RULE_NC(name_list, list, tok(NAME), tok(DEL_COMMA)) DEF_RULE(assert_stmt, c(assert_stmt), and(3), tok(KW_ASSERT), rule(test), opt_rule(assert_stmt_extra)) DEF_RULE_NC(assert_stmt_extra, and_ident(2), tok(DEL_COMMA), rule(test)) // compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt // if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] // while_stmt: 'while' test ':' suite ['else' ':' suite] // for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] // try_stmt: 'try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite) // # NB compile.c makes sure that the default except clause is last // except_clause: 'except' [test ['as' NAME]] // with_stmt: 'with' with_item (',' with_item)* ':' suite // with_item: test ['as' expr] // suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT // async_stmt: 'async' (funcdef | with_stmt | for_stmt) #if MICROPY_PY_ASYNC_AWAIT DEF_RULE_NC(compound_stmt, or(9), rule(if_stmt), rule(while_stmt), rule(for_stmt), rule(try_stmt), rule(with_stmt), rule(funcdef), rule(classdef), rule(decorated), rule(async_stmt)) DEF_RULE(async_stmt, c(async_stmt), and(2), tok(KW_ASYNC), rule(async_stmt_2)) DEF_RULE_NC(async_stmt_2, or(3), rule(funcdef), rule(with_stmt), rule(for_stmt)) #else DEF_RULE_NC(compound_stmt, or(8), rule(if_stmt), rule(while_stmt), rule(for_stmt), rule(try_stmt), rule(with_stmt), rule(funcdef), rule(classdef), rule(decorated)) #endif DEF_RULE(if_stmt, c(if_stmt), and(6), tok(KW_IF), rule(test), tok(DEL_COLON), rule(suite), opt_rule(if_stmt_elif_list), opt_rule(else_stmt)) DEF_RULE_NC(if_stmt_elif_list, one_or_more, rule(if_stmt_elif)) DEF_RULE_NC(if_stmt_elif, and(4), tok(KW_ELIF), rule(test), tok(DEL_COLON), rule(suite)) DEF_RULE(while_stmt, c(while_stmt), and(5), tok(KW_WHILE), rule(test), tok(DEL_COLON), rule(suite), opt_rule(else_stmt)) DEF_RULE(for_stmt, c(for_stmt), and(7), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(testlist), tok(DEL_COLON), rule(suite), opt_rule(else_stmt)) DEF_RULE(try_stmt, c(try_stmt), and(4), tok(KW_TRY), tok(DEL_COLON), rule(suite), rule(try_stmt_2)) DEF_RULE_NC(try_stmt_2, or(2), rule(try_stmt_except_and_more), rule(try_stmt_finally)) DEF_RULE_NC(try_stmt_except_and_more, and_ident(3), rule(try_stmt_except_list), opt_rule(else_stmt), opt_rule(try_stmt_finally)) DEF_RULE_NC(try_stmt_except, and(4), tok(KW_EXCEPT), opt_rule(try_stmt_as_name), tok(DEL_COLON), rule(suite)) DEF_RULE_NC(try_stmt_as_name, and_ident(2), rule(test), opt_rule(as_name)) DEF_RULE_NC(try_stmt_except_list, one_or_more, rule(try_stmt_except)) DEF_RULE_NC(try_stmt_finally, and(3), tok(KW_FINALLY), tok(DEL_COLON), rule(suite)) DEF_RULE_NC(else_stmt, and_ident(3), tok(KW_ELSE), tok(DEL_COLON), rule(suite)) DEF_RULE(with_stmt, c(with_stmt), and(4), tok(KW_WITH), rule(with_stmt_list), tok(DEL_COLON), rule(suite)) DEF_RULE_NC(with_stmt_list, list, rule(with_item), tok(DEL_COMMA)) DEF_RULE_NC(with_item, and_ident(2), rule(test), opt_rule(with_item_as)) DEF_RULE_NC(with_item_as, and_ident(2), tok(KW_AS), rule(expr)) DEF_RULE_NC(suite, or(2), rule(suite_block), rule(simple_stmt)) DEF_RULE_NC(suite_block, and_ident(4), tok(NEWLINE), tok(INDENT), rule(suite_block_stmts), tok(DEDENT)) DEF_RULE(suite_block_stmts, c(generic_all_nodes), one_or_more, rule(stmt)) // test: or_test ['if' or_test 'else' test] | lambdef // test_nocond: or_test | lambdef_nocond // lambdef: 'lambda' [varargslist] ':' test // lambdef_nocond: 'lambda' [varargslist] ':' test_nocond DEF_RULE_NC(test, or(2), rule(lambdef), rule(test_if_expr)) DEF_RULE(test_if_expr, c(test_if_expr), and_ident(2), rule(or_test), opt_rule(test_if_else)) DEF_RULE_NC(test_if_else, and(4), tok(KW_IF), rule(or_test), tok(KW_ELSE), rule(test)) DEF_RULE_NC(test_nocond, or(2), rule(lambdef_nocond), rule(or_test)) DEF_RULE(lambdef, c(lambdef), and_blank(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test)) DEF_RULE(lambdef_nocond, c(lambdef), and_blank(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test_nocond)) // or_test: and_test ('or' and_test)* // and_test: not_test ('and' not_test)* // not_test: 'not' not_test | comparison // comparison: expr (comp_op expr)* // comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'in'|'not' 'in'|'is'|'is' 'not' // star_expr: '*' expr // expr: xor_expr ('|' xor_expr)* // xor_expr: and_expr ('^' and_expr)* // and_expr: shift_expr ('&' shift_expr)* // shift_expr: arith_expr (('<<'|'>>') arith_expr)* // arith_expr: term (('+'|'-') term)* // term: factor (('*'|'@'|'/'|'%'|'//') factor)* // factor: ('+'|'-'|'~') factor | power // power: atom_expr ['**' factor] // atom_expr: 'await' atom trailer* | atom trailer* DEF_RULE(or_test, c(or_and_test), list, rule(and_test), tok(KW_OR)) DEF_RULE(and_test, c(or_and_test), list, rule(not_test), tok(KW_AND)) DEF_RULE_NC(not_test, or(2), rule(not_test_2), rule(comparison)) DEF_RULE(not_test_2, c(not_test_2), and(2), tok(KW_NOT), rule(not_test)) DEF_RULE(comparison, c(comparison), list, rule(expr), rule(comp_op)) DEF_RULE_NC(comp_op, or(9), tok(OP_LESS), tok(OP_MORE), tok(OP_DBL_EQUAL), tok(OP_LESS_EQUAL), tok(OP_MORE_EQUAL), tok(OP_NOT_EQUAL), tok(KW_IN), rule(comp_op_not_in), rule(comp_op_is)) DEF_RULE_NC(comp_op_not_in, and(2), tok(KW_NOT), tok(KW_IN)) DEF_RULE_NC(comp_op_is, and(2), tok(KW_IS), opt_rule(comp_op_is_not)) DEF_RULE_NC(comp_op_is_not, and(1), tok(KW_NOT)) DEF_RULE(star_expr, c(star_expr), and(2), tok(OP_STAR), rule(expr)) DEF_RULE(expr, c(binary_op), list, rule(xor_expr), tok(OP_PIPE)) DEF_RULE(xor_expr, c(binary_op), list, rule(and_expr), tok(OP_CARET)) DEF_RULE(and_expr, c(binary_op), list, rule(shift_expr), tok(OP_AMPERSAND)) DEF_RULE(shift_expr, c(term), list, rule(arith_expr), rule(shift_op)) DEF_RULE_NC(shift_op, or(2), tok(OP_DBL_LESS), tok(OP_DBL_MORE)) DEF_RULE(arith_expr, c(term), list, rule(term), rule(arith_op)) DEF_RULE_NC(arith_op, or(2), tok(OP_PLUS), tok(OP_MINUS)) DEF_RULE(term, c(term), list, rule(factor), rule(term_op)) DEF_RULE_NC(term_op, or(5), tok(OP_STAR), tok(OP_AT), tok(OP_SLASH), tok(OP_PERCENT), tok(OP_DBL_SLASH)) DEF_RULE_NC(factor, or(2), rule(factor_2), rule(power)) DEF_RULE(factor_2, c(factor_2), and_ident(2), rule(factor_op), rule(factor)) DEF_RULE_NC(factor_op, or(3), tok(OP_PLUS), tok(OP_MINUS), tok(OP_TILDE)) DEF_RULE(power, c(power), and_ident(2), rule(atom_expr), opt_rule(power_dbl_star)) #if MICROPY_PY_ASYNC_AWAIT DEF_RULE_NC(atom_expr, or(2), rule(atom_expr_await), rule(atom_expr_normal)) DEF_RULE(atom_expr_await, c(atom_expr_await), and(3), tok(KW_AWAIT), rule(atom), opt_rule(atom_expr_trailers)) #else DEF_RULE_NC(atom_expr, or(1), rule(atom_expr_normal)) #endif DEF_RULE(atom_expr_normal, c(atom_expr_normal), and_ident(2), rule(atom), opt_rule(atom_expr_trailers)) DEF_RULE_NC(atom_expr_trailers, one_or_more, rule(trailer)) DEF_RULE_NC(power_dbl_star, and_ident(2), tok(OP_DBL_STAR), rule(factor)) // atom: '(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False' // testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) // trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME DEF_RULE_NC(atom, or(12), tok(NAME), tok(INTEGER), tok(FLOAT_OR_IMAG), tok(STRING), tok(BYTES), tok(ELLIPSIS), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace)) DEF_RULE(atom_paren, c(atom_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(atom_2b), tok(DEL_PAREN_CLOSE)) DEF_RULE_NC(atom_2b, or(2), rule(yield_expr), rule(testlist_comp)) DEF_RULE(atom_bracket, c(atom_bracket), and(3), tok(DEL_BRACKET_OPEN), opt_rule(testlist_comp), tok(DEL_BRACKET_CLOSE)) DEF_RULE(atom_brace, c(atom_brace), and(3), tok(DEL_BRACE_OPEN), opt_rule(dictorsetmaker), tok(DEL_BRACE_CLOSE)) DEF_RULE_NC(testlist_comp, and_ident(2), rule(testlist_comp_2), opt_rule(testlist_comp_3)) DEF_RULE_NC(testlist_comp_2, or(2), rule(star_expr), rule(test)) DEF_RULE_NC(testlist_comp_3, or(2), rule(comp_for), rule(testlist_comp_3b)) DEF_RULE_NC(testlist_comp_3b, and_ident(2), tok(DEL_COMMA), opt_rule(testlist_comp_3c)) DEF_RULE_NC(testlist_comp_3c, list_with_end, rule(testlist_comp_2), tok(DEL_COMMA)) DEF_RULE_NC(trailer, or(3), rule(trailer_paren), rule(trailer_bracket), rule(trailer_period)) DEF_RULE(trailer_paren, c(trailer_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE)) DEF_RULE(trailer_bracket, c(trailer_bracket), and(3), tok(DEL_BRACKET_OPEN), rule(subscriptlist), tok(DEL_BRACKET_CLOSE)) DEF_RULE(trailer_period, c(trailer_period), and(2), tok(DEL_PERIOD), tok(NAME)) // subscriptlist: subscript (',' subscript)* [','] // subscript: test | [test] ':' [test] [sliceop] // sliceop: ':' [test] #if MICROPY_PY_BUILTINS_SLICE DEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(subscript), tok(DEL_COMMA)) DEF_RULE_NC(subscript, or(2), rule(subscript_3), rule(subscript_2)) DEF_RULE(subscript_2, c(subscript), and_ident(2), rule(test), opt_rule(subscript_3)) DEF_RULE(subscript_3, c(subscript), and(2), tok(DEL_COLON), opt_rule(subscript_3b)) DEF_RULE_NC(subscript_3b, or(2), rule(subscript_3c), rule(subscript_3d)) DEF_RULE_NC(subscript_3c, and(2), tok(DEL_COLON), opt_rule(test)) DEF_RULE_NC(subscript_3d, and_ident(2), rule(test), opt_rule(sliceop)) DEF_RULE_NC(sliceop, and(2), tok(DEL_COLON), opt_rule(test)) #else DEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COMMA)) #endif // exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] // testlist: test (',' test)* [','] // dictorsetmaker: (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [','])) DEF_RULE_NC(exprlist, list_with_end, rule(exprlist_2), tok(DEL_COMMA)) DEF_RULE_NC(exprlist_2, or(2), rule(star_expr), rule(expr)) DEF_RULE(testlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COMMA)) // TODO dictorsetmaker lets through more than is allowed DEF_RULE_NC(dictorsetmaker, and_ident(2), rule(dictorsetmaker_item), opt_rule(dictorsetmaker_tail)) #if MICROPY_PY_BUILTINS_SET DEF_RULE(dictorsetmaker_item, c(dictorsetmaker_item), and_ident(2), rule(test), opt_rule(dictorsetmaker_colon)) DEF_RULE_NC(dictorsetmaker_colon, and_ident(2), tok(DEL_COLON), rule(test)) #else DEF_RULE(dictorsetmaker_item, c(dictorsetmaker_item), and(3), rule(test), tok(DEL_COLON), rule(test)) #endif DEF_RULE_NC(dictorsetmaker_tail, or(2), rule(comp_for), rule(dictorsetmaker_list)) DEF_RULE_NC(dictorsetmaker_list, and(2), tok(DEL_COMMA), opt_rule(dictorsetmaker_list2)) DEF_RULE_NC(dictorsetmaker_list2, list_with_end, rule(dictorsetmaker_item), tok(DEL_COMMA)) // classdef: 'class' NAME ['(' [arglist] ')'] ':' suite DEF_RULE(classdef, c(classdef), and_blank(5), tok(KW_CLASS), tok(NAME), opt_rule(classdef_2), tok(DEL_COLON), rule(suite)) DEF_RULE_NC(classdef_2, and_ident(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE)) // arglist: (argument ',')* (argument [','] | '*' test (',' argument)* [',' '**' test] | '**' test) // TODO arglist lets through more than is allowed, compiler needs to do further verification DEF_RULE_NC(arglist, list_with_end, rule(arglist_2), tok(DEL_COMMA)) DEF_RULE_NC(arglist_2, or(3), rule(arglist_star), rule(arglist_dbl_star), rule(argument)) DEF_RULE_NC(arglist_star, and(2), tok(OP_STAR), rule(test)) DEF_RULE_NC(arglist_dbl_star, and(2), tok(OP_DBL_STAR), rule(test)) // # The reason that keywords are test nodes instead of NAME is that using NAME // # results in an ambiguity. ast.c makes sure it's a NAME. // argument: test [comp_for] | test '=' test # Really [keyword '='] test // comp_iter: comp_for | comp_if // comp_for: 'for' exprlist 'in' or_test [comp_iter] // comp_if: 'if' test_nocond [comp_iter] DEF_RULE_NC(argument, and_ident(2), rule(test), opt_rule(argument_2)) DEF_RULE_NC(argument_2, or(2), rule(comp_for), rule(argument_3)) DEF_RULE_NC(argument_3, and_ident(2), tok(DEL_EQUAL), rule(test)) DEF_RULE_NC(comp_iter, or(2), rule(comp_for), rule(comp_if)) DEF_RULE_NC(comp_for, and_blank(5), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(or_test), opt_rule(comp_iter)) DEF_RULE_NC(comp_if, and(3), tok(KW_IF), rule(test_nocond), opt_rule(comp_iter)) // # not used in grammar, but may appear in "node" passed from Parser to Compiler // encoding_decl: NAME // yield_expr: 'yield' [yield_arg] // yield_arg: 'from' test | testlist DEF_RULE(yield_expr, c(yield_expr), and(2), tok(KW_YIELD), opt_rule(yield_arg)) DEF_RULE_NC(yield_arg, or(2), rule(yield_arg_from), rule(testlist)) DEF_RULE_NC(yield_arg_from, and(2), tok(KW_FROM), rule(test)) micropython-1.12/py/lexer.c000066400000000000000000000641701357706137100157450ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/reader.h" #include "py/lexer.h" #include "py/runtime.h" #if MICROPY_ENABLE_COMPILER #define TAB_SIZE (8) // TODO seems that CPython allows NULL byte in the input stream // don't know if that's intentional or not, but we don't allow it #define MP_LEXER_EOF ((unichar)MP_READER_EOF) #define CUR_CHAR(lex) ((lex)->chr0) STATIC bool is_end(mp_lexer_t *lex) { return lex->chr0 == MP_LEXER_EOF; } STATIC bool is_physical_newline(mp_lexer_t *lex) { return lex->chr0 == '\n'; } STATIC bool is_char(mp_lexer_t *lex, byte c) { return lex->chr0 == c; } STATIC bool is_char_or(mp_lexer_t *lex, byte c1, byte c2) { return lex->chr0 == c1 || lex->chr0 == c2; } STATIC bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) { return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3; } STATIC bool is_char_following(mp_lexer_t *lex, byte c) { return lex->chr1 == c; } STATIC bool is_char_following_or(mp_lexer_t *lex, byte c1, byte c2) { return lex->chr1 == c1 || lex->chr1 == c2; } STATIC bool is_char_following_following_or(mp_lexer_t *lex, byte c1, byte c2) { return lex->chr2 == c1 || lex->chr2 == c2; } STATIC bool is_char_and(mp_lexer_t *lex, byte c1, byte c2) { return lex->chr0 == c1 && lex->chr1 == c2; } STATIC bool is_whitespace(mp_lexer_t *lex) { return unichar_isspace(lex->chr0); } STATIC bool is_letter(mp_lexer_t *lex) { return unichar_isalpha(lex->chr0); } STATIC bool is_digit(mp_lexer_t *lex) { return unichar_isdigit(lex->chr0); } STATIC bool is_following_digit(mp_lexer_t *lex) { return unichar_isdigit(lex->chr1); } STATIC bool is_following_base_char(mp_lexer_t *lex) { const unichar chr1 = lex->chr1 | 0x20; return chr1 == 'b' || chr1 == 'o' || chr1 == 'x'; } STATIC bool is_following_odigit(mp_lexer_t *lex) { return lex->chr1 >= '0' && lex->chr1 <= '7'; } STATIC bool is_string_or_bytes(mp_lexer_t *lex) { return is_char_or(lex, '\'', '\"') || (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"')) || ((is_char_and(lex, 'r', 'b') || is_char_and(lex, 'b', 'r')) && is_char_following_following_or(lex, '\'', '\"')); } // to easily parse utf-8 identifiers we allow any raw byte with high bit set STATIC bool is_head_of_identifier(mp_lexer_t *lex) { return is_letter(lex) || lex->chr0 == '_' || lex->chr0 >= 0x80; } STATIC bool is_tail_of_identifier(mp_lexer_t *lex) { return is_head_of_identifier(lex) || is_digit(lex); } STATIC void next_char(mp_lexer_t *lex) { if (lex->chr0 == '\n') { // a new line ++lex->line; lex->column = 1; } else if (lex->chr0 == '\t') { // a tab lex->column = (((lex->column - 1 + TAB_SIZE) / TAB_SIZE) * TAB_SIZE) + 1; } else { // a character worth one column ++lex->column; } lex->chr0 = lex->chr1; lex->chr1 = lex->chr2; lex->chr2 = lex->reader.readbyte(lex->reader.data); if (lex->chr1 == '\r') { // CR is a new line, converted to LF lex->chr1 = '\n'; if (lex->chr2 == '\n') { // CR LF is a single new line, throw out the extra LF lex->chr2 = lex->reader.readbyte(lex->reader.data); } } // check if we need to insert a newline at end of file if (lex->chr2 == MP_LEXER_EOF && lex->chr1 != MP_LEXER_EOF && lex->chr1 != '\n') { lex->chr2 = '\n'; } } STATIC void indent_push(mp_lexer_t *lex, size_t indent) { if (lex->num_indent_level >= lex->alloc_indent_level) { lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC); lex->alloc_indent_level += MICROPY_ALLOC_LEXEL_INDENT_INC; } lex->indent_level[lex->num_indent_level++] = indent; } STATIC size_t indent_top(mp_lexer_t *lex) { return lex->indent_level[lex->num_indent_level - 1]; } STATIC void indent_pop(mp_lexer_t *lex) { lex->num_indent_level -= 1; } // some tricky operator encoding: // = begin with , if this opchar matches then begin here // e = end with , if this opchar matches then end // c = continue with , if this opchar matches then continue matching // this means if the start of two ops are the same then they are equal til the last char STATIC const char *const tok_enc = "()[]{},:;~" // singles " >= >> >>= "*e=c*e=" // * *= ** **= "+e=" // + += "-e=e>" // - -= -> "&e=" // & &= "|e=" // | |= "/e=c/e=" // / /= // //= "%e=" // % %= "^e=" // ^ ^= "@e=" // @ @= "=e=" // = == "!."; // start of special cases: != . ... // TODO static assert that number of tokens is less than 256 so we can safely make this table with byte sized entries STATIC const uint8_t tok_enc_kind[] = { MP_TOKEN_DEL_PAREN_OPEN, MP_TOKEN_DEL_PAREN_CLOSE, MP_TOKEN_DEL_BRACKET_OPEN, MP_TOKEN_DEL_BRACKET_CLOSE, MP_TOKEN_DEL_BRACE_OPEN, MP_TOKEN_DEL_BRACE_CLOSE, MP_TOKEN_DEL_COMMA, MP_TOKEN_DEL_COLON, MP_TOKEN_DEL_SEMICOLON, MP_TOKEN_OP_TILDE, MP_TOKEN_OP_LESS, MP_TOKEN_OP_LESS_EQUAL, MP_TOKEN_OP_DBL_LESS, MP_TOKEN_DEL_DBL_LESS_EQUAL, MP_TOKEN_OP_MORE, MP_TOKEN_OP_MORE_EQUAL, MP_TOKEN_OP_DBL_MORE, MP_TOKEN_DEL_DBL_MORE_EQUAL, MP_TOKEN_OP_STAR, MP_TOKEN_DEL_STAR_EQUAL, MP_TOKEN_OP_DBL_STAR, MP_TOKEN_DEL_DBL_STAR_EQUAL, MP_TOKEN_OP_PLUS, MP_TOKEN_DEL_PLUS_EQUAL, MP_TOKEN_OP_MINUS, MP_TOKEN_DEL_MINUS_EQUAL, MP_TOKEN_DEL_MINUS_MORE, MP_TOKEN_OP_AMPERSAND, MP_TOKEN_DEL_AMPERSAND_EQUAL, MP_TOKEN_OP_PIPE, MP_TOKEN_DEL_PIPE_EQUAL, MP_TOKEN_OP_SLASH, MP_TOKEN_DEL_SLASH_EQUAL, MP_TOKEN_OP_DBL_SLASH, MP_TOKEN_DEL_DBL_SLASH_EQUAL, MP_TOKEN_OP_PERCENT, MP_TOKEN_DEL_PERCENT_EQUAL, MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL, MP_TOKEN_OP_AT, MP_TOKEN_DEL_AT_EQUAL, MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL, }; // must have the same order as enum in lexer.h // must be sorted according to strcmp STATIC const char *const tok_kw[] = { "False", "None", "True", "__debug__", "and", "as", "assert", #if MICROPY_PY_ASYNC_AWAIT "async", "await", #endif "break", "class", "continue", "def", "del", "elif", "else", "except", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass", "raise", "return", "try", "while", "with", "yield", }; // This is called with CUR_CHAR() before first hex digit, and should return with // it pointing to last hex digit // num_digits must be greater than zero STATIC bool get_hex(mp_lexer_t *lex, size_t num_digits, mp_uint_t *result) { mp_uint_t num = 0; while (num_digits-- != 0) { next_char(lex); unichar c = CUR_CHAR(lex); if (!unichar_isxdigit(c)) { return false; } num = (num << 4) + unichar_xdigit_value(c); } *result = num; return true; } STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw) { // get first quoting character char quote_char = '\''; if (is_char(lex, '\"')) { quote_char = '\"'; } next_char(lex); // work out if it's a single or triple quoted literal size_t num_quotes; if (is_char_and(lex, quote_char, quote_char)) { // triple quotes next_char(lex); next_char(lex); num_quotes = 3; } else { // single quotes num_quotes = 1; } size_t n_closing = 0; while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\n')) && n_closing < num_quotes) { if (is_char(lex, quote_char)) { n_closing += 1; vstr_add_char(&lex->vstr, CUR_CHAR(lex)); } else { n_closing = 0; if (is_char(lex, '\\')) { next_char(lex); unichar c = CUR_CHAR(lex); if (is_raw) { // raw strings allow escaping of quotes, but the backslash is also emitted vstr_add_char(&lex->vstr, '\\'); } else { switch (c) { // note: "c" can never be MP_LEXER_EOF because next_char // always inserts a newline at the end of the input stream case '\n': c = MP_LEXER_EOF; break; // backslash escape the newline, just ignore it case '\\': break; case '\'': break; case '"': break; case 'a': c = 0x07; break; case 'b': c = 0x08; break; case 't': c = 0x09; break; case 'n': c = 0x0a; break; case 'v': c = 0x0b; break; case 'f': c = 0x0c; break; case 'r': c = 0x0d; break; case 'u': case 'U': if (lex->tok_kind == MP_TOKEN_BYTES) { // b'\u1234' == b'\\u1234' vstr_add_char(&lex->vstr, '\\'); break; } // Otherwise fall through. case 'x': { mp_uint_t num = 0; if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) { // not enough hex chars for escape sequence lex->tok_kind = MP_TOKEN_INVALID; } c = num; break; } case 'N': // Supporting '\N{LATIN SMALL LETTER A}' == 'a' would require keeping the // entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly // 3MB of text; even gzip-compressed and with minimal structure, it'll take // roughly half a meg of storage. This form of Unicode escape may be added // later on, but it's definitely not a priority right now. -- CJA 20140607 mp_raise_NotImplementedError("unicode name escapes"); break; default: if (c >= '0' && c <= '7') { // Octal sequence, 1-3 chars size_t digits = 3; mp_uint_t num = c - '0'; while (is_following_odigit(lex) && --digits != 0) { next_char(lex); num = num * 8 + (CUR_CHAR(lex) - '0'); } c = num; } else { // unrecognised escape character; CPython lets this through verbatim as '\' and then the character vstr_add_char(&lex->vstr, '\\'); } break; } } if (c != MP_LEXER_EOF) { if (MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) { if (c < 0x110000 && lex->tok_kind == MP_TOKEN_STRING) { vstr_add_char(&lex->vstr, c); } else if (c < 0x100 && lex->tok_kind == MP_TOKEN_BYTES) { vstr_add_byte(&lex->vstr, c); } else { // unicode character out of range // this raises a generic SyntaxError; could provide more info lex->tok_kind = MP_TOKEN_INVALID; } } else { // without unicode everything is just added as an 8-bit byte if (c < 0x100) { vstr_add_byte(&lex->vstr, c); } else { // 8-bit character out of range // this raises a generic SyntaxError; could provide more info lex->tok_kind = MP_TOKEN_INVALID; } } } } else { // Add the "character" as a byte so that we remain 8-bit clean. // This way, strings are parsed correctly whether or not they contain utf-8 chars. vstr_add_byte(&lex->vstr, CUR_CHAR(lex)); } } next_char(lex); } // check we got the required end quotes if (n_closing < num_quotes) { lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN; } // cut off the end quotes from the token text vstr_cut_tail_bytes(&lex->vstr, n_closing); } STATIC bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) { bool had_physical_newline = false; while (!is_end(lex)) { if (is_physical_newline(lex)) { if (stop_at_newline && lex->nested_bracket_level == 0) { break; } had_physical_newline = true; next_char(lex); } else if (is_whitespace(lex)) { next_char(lex); } else if (is_char(lex, '#')) { next_char(lex); while (!is_end(lex) && !is_physical_newline(lex)) { next_char(lex); } // had_physical_newline will be set on next loop } else if (is_char_and(lex, '\\', '\n')) { // line-continuation, so don't set had_physical_newline next_char(lex); next_char(lex); } else { break; } } return had_physical_newline; } void mp_lexer_to_next(mp_lexer_t *lex) { // start new token text vstr_reset(&lex->vstr); // skip white space and comments bool had_physical_newline = skip_whitespace(lex, false); // set token source information lex->tok_line = lex->line; lex->tok_column = lex->column; if (lex->emit_dent < 0) { lex->tok_kind = MP_TOKEN_DEDENT; lex->emit_dent += 1; } else if (lex->emit_dent > 0) { lex->tok_kind = MP_TOKEN_INDENT; lex->emit_dent -= 1; } else if (had_physical_newline && lex->nested_bracket_level == 0) { lex->tok_kind = MP_TOKEN_NEWLINE; size_t num_spaces = lex->column - 1; if (num_spaces == indent_top(lex)) { } else if (num_spaces > indent_top(lex)) { indent_push(lex, num_spaces); lex->emit_dent += 1; } else { while (num_spaces < indent_top(lex)) { indent_pop(lex); lex->emit_dent -= 1; } if (num_spaces != indent_top(lex)) { lex->tok_kind = MP_TOKEN_DEDENT_MISMATCH; } } } else if (is_end(lex)) { lex->tok_kind = MP_TOKEN_END; } else if (is_string_or_bytes(lex)) { // a string or bytes literal // Python requires adjacent string/bytes literals to be automatically // concatenated. We do it here in the tokeniser to make efficient use of RAM, // because then the lexer's vstr can be used to accumulate the string literal, // in contrast to creating a parse tree of strings and then joining them later // in the compiler. It's also more compact in code size to do it here. // MP_TOKEN_END is used to indicate that this is the first string token lex->tok_kind = MP_TOKEN_END; // Loop to accumulate string/bytes literals do { // parse type codes bool is_raw = false; mp_token_kind_t kind = MP_TOKEN_STRING; int n_char = 0; if (is_char(lex, 'u')) { n_char = 1; } else if (is_char(lex, 'b')) { kind = MP_TOKEN_BYTES; n_char = 1; if (is_char_following(lex, 'r')) { is_raw = true; n_char = 2; } } else if (is_char(lex, 'r')) { is_raw = true; n_char = 1; if (is_char_following(lex, 'b')) { kind = MP_TOKEN_BYTES; n_char = 2; } } // Set or check token kind if (lex->tok_kind == MP_TOKEN_END) { lex->tok_kind = kind; } else if (lex->tok_kind != kind) { // Can't concatenate string with bytes break; } // Skip any type code characters if (n_char != 0) { next_char(lex); if (n_char == 2) { next_char(lex); } } // Parse the literal parse_string_literal(lex, is_raw); // Skip whitespace so we can check if there's another string following skip_whitespace(lex, true); } while (is_string_or_bytes(lex)); } else if (is_head_of_identifier(lex)) { lex->tok_kind = MP_TOKEN_NAME; // get first char (add as byte to remain 8-bit clean and support utf-8) vstr_add_byte(&lex->vstr, CUR_CHAR(lex)); next_char(lex); // get tail chars while (!is_end(lex) && is_tail_of_identifier(lex)) { vstr_add_byte(&lex->vstr, CUR_CHAR(lex)); next_char(lex); } // Check if the name is a keyword. // We also check for __debug__ here and convert it to its value. This is // so the parser gives a syntax error on, eg, x.__debug__. Otherwise, we // need to check for this special token in many places in the compiler. const char *s = vstr_null_terminated_str(&lex->vstr); for (size_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) { int cmp = strcmp(s, tok_kw[i]); if (cmp == 0) { lex->tok_kind = MP_TOKEN_KW_FALSE + i; if (lex->tok_kind == MP_TOKEN_KW___DEBUG__) { lex->tok_kind = (MP_STATE_VM(mp_optimise_value) == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE); } break; } else if (cmp < 0) { // Table is sorted and comparison was less-than, so stop searching break; } } } else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) { bool forced_integer = false; if (is_char(lex, '.')) { lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG; } else { lex->tok_kind = MP_TOKEN_INTEGER; if (is_char(lex, '0') && is_following_base_char(lex)) { forced_integer = true; } } // get first char vstr_add_char(&lex->vstr, CUR_CHAR(lex)); next_char(lex); // get tail chars while (!is_end(lex)) { if (!forced_integer && is_char_or(lex, 'e', 'E')) { lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG; vstr_add_char(&lex->vstr, 'e'); next_char(lex); if (is_char(lex, '+') || is_char(lex, '-')) { vstr_add_char(&lex->vstr, CUR_CHAR(lex)); next_char(lex); } } else if (is_letter(lex) || is_digit(lex) || is_char(lex, '.')) { if (is_char_or3(lex, '.', 'j', 'J')) { lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG; } vstr_add_char(&lex->vstr, CUR_CHAR(lex)); next_char(lex); } else if (is_char(lex, '_')) { next_char(lex); } else { break; } } } else { // search for encoded delimiter or operator const char *t = tok_enc; size_t tok_enc_index = 0; for (; *t != 0 && !is_char(lex, *t); t += 1) { if (*t == 'e' || *t == 'c') { t += 1; } tok_enc_index += 1; } next_char(lex); if (*t == 0) { // didn't match any delimiter or operator characters lex->tok_kind = MP_TOKEN_INVALID; } else if (*t == '!') { // "!=" is a special case because "!" is not a valid operator if (is_char(lex, '=')) { next_char(lex); lex->tok_kind = MP_TOKEN_OP_NOT_EQUAL; } else { lex->tok_kind = MP_TOKEN_INVALID; } } else if (*t == '.') { // "." and "..." are special cases because ".." is not a valid operator if (is_char_and(lex, '.', '.')) { next_char(lex); next_char(lex); lex->tok_kind = MP_TOKEN_ELLIPSIS; } else { lex->tok_kind = MP_TOKEN_DEL_PERIOD; } } else { // matched a delimiter or operator character // get the maximum characters for a valid token t += 1; size_t t_index = tok_enc_index; while (*t == 'c' || *t == 'e') { t_index += 1; if (is_char(lex, t[1])) { next_char(lex); tok_enc_index = t_index; if (*t == 'e') { break; } } else if (*t == 'c') { break; } t += 2; } // set token kind lex->tok_kind = tok_enc_kind[tok_enc_index]; // compute bracket level for implicit line joining if (lex->tok_kind == MP_TOKEN_DEL_PAREN_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACKET_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACE_OPEN) { lex->nested_bracket_level += 1; } else if (lex->tok_kind == MP_TOKEN_DEL_PAREN_CLOSE || lex->tok_kind == MP_TOKEN_DEL_BRACKET_CLOSE || lex->tok_kind == MP_TOKEN_DEL_BRACE_CLOSE) { lex->nested_bracket_level -= 1; } } } } mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) { mp_lexer_t *lex = m_new_obj(mp_lexer_t); lex->source_name = src_name; lex->reader = reader; lex->line = 1; lex->column = (size_t)-2; // account for 3 dummy bytes lex->emit_dent = 0; lex->nested_bracket_level = 0; lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT; lex->num_indent_level = 1; lex->indent_level = m_new(uint16_t, lex->alloc_indent_level); vstr_init(&lex->vstr, 32); // store sentinel for first indentation level lex->indent_level[0] = 0; // load lexer with start of file, advancing lex->column to 1 // start with dummy bytes and use next_char() for proper EOL/EOF handling lex->chr0 = lex->chr1 = lex->chr2 = 0; next_char(lex); next_char(lex); next_char(lex); // preload first token mp_lexer_to_next(lex); // Check that the first token is in the first column. If it's not then we // convert the token kind to INDENT so that the parser gives a syntax error. if (lex->tok_column != 1) { lex->tok_kind = MP_TOKEN_INDENT; } return lex; } mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len) { mp_reader_t reader; mp_reader_new_mem(&reader, (const byte*)str, len, free_len); return mp_lexer_new(src_name, reader); } #if MICROPY_READER_POSIX || MICROPY_READER_VFS mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_reader_t reader; mp_reader_new_file(&reader, filename); return mp_lexer_new(qstr_from_str(filename), reader); } #if MICROPY_HELPER_LEXER_UNIX mp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd) { mp_reader_t reader; mp_reader_new_file_from_fd(&reader, fd, close_fd); return mp_lexer_new(filename, reader); } #endif #endif void mp_lexer_free(mp_lexer_t *lex) { if (lex) { lex->reader.close(lex->reader.data); vstr_clear(&lex->vstr); m_del(uint16_t, lex->indent_level, lex->alloc_indent_level); m_del_obj(mp_lexer_t, lex); } } #if 0 // This function is used to print the current token and should only be // needed to debug the lexer, so it's not available via a config option. void mp_lexer_show_token(const mp_lexer_t *lex) { printf("(" UINT_FMT ":" UINT_FMT ") kind:%u str:%p len:%zu", lex->tok_line, lex->tok_column, lex->tok_kind, lex->vstr.buf, lex->vstr.len); if (lex->vstr.len > 0) { const byte *i = (const byte *)lex->vstr.buf; const byte *j = (const byte *)i + lex->vstr.len; printf(" "); while (i < j) { unichar c = utf8_get_char(i); i = utf8_next_char(i); if (unichar_isprint(c)) { printf("%c", (int)c); } else { printf("?"); } } } printf("\n"); } #endif #endif // MICROPY_ENABLE_COMPILER micropython-1.12/py/lexer.h000066400000000000000000000134611357706137100157470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_LEXER_H #define MICROPY_INCLUDED_PY_LEXER_H #include #include "py/mpconfig.h" #include "py/qstr.h" #include "py/reader.h" /* lexer.h -- simple tokeniser for MicroPython * * Uses (byte) length instead of null termination. * Tokens are the same - UTF-8 with (byte) length. */ typedef enum _mp_token_kind_t { MP_TOKEN_END, MP_TOKEN_INVALID, MP_TOKEN_DEDENT_MISMATCH, MP_TOKEN_LONELY_STRING_OPEN, MP_TOKEN_NEWLINE, MP_TOKEN_INDENT, MP_TOKEN_DEDENT, MP_TOKEN_NAME, MP_TOKEN_INTEGER, MP_TOKEN_FLOAT_OR_IMAG, MP_TOKEN_STRING, MP_TOKEN_BYTES, MP_TOKEN_ELLIPSIS, MP_TOKEN_KW_FALSE, MP_TOKEN_KW_NONE, MP_TOKEN_KW_TRUE, MP_TOKEN_KW___DEBUG__, MP_TOKEN_KW_AND, MP_TOKEN_KW_AS, MP_TOKEN_KW_ASSERT, #if MICROPY_PY_ASYNC_AWAIT MP_TOKEN_KW_ASYNC, MP_TOKEN_KW_AWAIT, #endif MP_TOKEN_KW_BREAK, MP_TOKEN_KW_CLASS, MP_TOKEN_KW_CONTINUE, MP_TOKEN_KW_DEF, MP_TOKEN_KW_DEL, MP_TOKEN_KW_ELIF, MP_TOKEN_KW_ELSE, MP_TOKEN_KW_EXCEPT, MP_TOKEN_KW_FINALLY, MP_TOKEN_KW_FOR, MP_TOKEN_KW_FROM, MP_TOKEN_KW_GLOBAL, MP_TOKEN_KW_IF, MP_TOKEN_KW_IMPORT, MP_TOKEN_KW_IN, MP_TOKEN_KW_IS, MP_TOKEN_KW_LAMBDA, MP_TOKEN_KW_NONLOCAL, MP_TOKEN_KW_NOT, MP_TOKEN_KW_OR, MP_TOKEN_KW_PASS, MP_TOKEN_KW_RAISE, MP_TOKEN_KW_RETURN, MP_TOKEN_KW_TRY, MP_TOKEN_KW_WHILE, MP_TOKEN_KW_WITH, MP_TOKEN_KW_YIELD, MP_TOKEN_OP_TILDE, // Order of these 6 matches corresponding mp_binary_op_t operator MP_TOKEN_OP_LESS, MP_TOKEN_OP_MORE, MP_TOKEN_OP_DBL_EQUAL, MP_TOKEN_OP_LESS_EQUAL, MP_TOKEN_OP_MORE_EQUAL, MP_TOKEN_OP_NOT_EQUAL, // Order of these 13 matches corresponding mp_binary_op_t operator MP_TOKEN_OP_PIPE, MP_TOKEN_OP_CARET, MP_TOKEN_OP_AMPERSAND, MP_TOKEN_OP_DBL_LESS, MP_TOKEN_OP_DBL_MORE, MP_TOKEN_OP_PLUS, MP_TOKEN_OP_MINUS, MP_TOKEN_OP_STAR, MP_TOKEN_OP_AT, MP_TOKEN_OP_DBL_SLASH, MP_TOKEN_OP_SLASH, MP_TOKEN_OP_PERCENT, MP_TOKEN_OP_DBL_STAR, // Order of these 13 matches corresponding mp_binary_op_t operator MP_TOKEN_DEL_PIPE_EQUAL, MP_TOKEN_DEL_CARET_EQUAL, MP_TOKEN_DEL_AMPERSAND_EQUAL, MP_TOKEN_DEL_DBL_LESS_EQUAL, MP_TOKEN_DEL_DBL_MORE_EQUAL, MP_TOKEN_DEL_PLUS_EQUAL, MP_TOKEN_DEL_MINUS_EQUAL, MP_TOKEN_DEL_STAR_EQUAL, MP_TOKEN_DEL_AT_EQUAL, MP_TOKEN_DEL_DBL_SLASH_EQUAL, MP_TOKEN_DEL_SLASH_EQUAL, MP_TOKEN_DEL_PERCENT_EQUAL, MP_TOKEN_DEL_DBL_STAR_EQUAL, MP_TOKEN_DEL_PAREN_OPEN, MP_TOKEN_DEL_PAREN_CLOSE, MP_TOKEN_DEL_BRACKET_OPEN, MP_TOKEN_DEL_BRACKET_CLOSE, MP_TOKEN_DEL_BRACE_OPEN, MP_TOKEN_DEL_BRACE_CLOSE, MP_TOKEN_DEL_COMMA, MP_TOKEN_DEL_COLON, MP_TOKEN_DEL_PERIOD, MP_TOKEN_DEL_SEMICOLON, MP_TOKEN_DEL_EQUAL, MP_TOKEN_DEL_MINUS_MORE, } mp_token_kind_t; // this data structure is exposed for efficiency // public members are: source_name, tok_line, tok_column, tok_kind, vstr typedef struct _mp_lexer_t { qstr source_name; // name of source mp_reader_t reader; // stream source unichar chr0, chr1, chr2; // current cached characters from source size_t line; // current source line size_t column; // current source column mp_int_t emit_dent; // non-zero when there are INDENT/DEDENT tokens to emit mp_int_t nested_bracket_level; // >0 when there are nested brackets over multiple lines size_t alloc_indent_level; size_t num_indent_level; uint16_t *indent_level; size_t tok_line; // token source line size_t tok_column; // token source column mp_token_kind_t tok_kind; // token kind vstr_t vstr; // token data } mp_lexer_t; mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader); mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len); void mp_lexer_free(mp_lexer_t *lex); void mp_lexer_to_next(mp_lexer_t *lex); /******************************************************************/ // platform specific import function; must be implemented for a specific port // TODO tidy up, rename, or put elsewhere typedef enum { MP_IMPORT_STAT_NO_EXIST, MP_IMPORT_STAT_DIR, MP_IMPORT_STAT_FILE, } mp_import_stat_t; mp_import_stat_t mp_import_stat(const char *path); mp_lexer_t *mp_lexer_new_from_file(const char *filename); #if MICROPY_HELPER_LEXER_UNIX mp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd); #endif #endif // MICROPY_INCLUDED_PY_LEXER_H micropython-1.12/py/makemoduledefs.py000066400000000000000000000064071357706137100200200ustar00rootroot00000000000000#!/usr/bin/env python # This pre-processor parses provided objects' c files for # MP_REGISTER_MODULE(module_name, obj_module, enabled_define) # These are used to generate a header with the required entries for # "mp_rom_map_elem_t mp_builtin_module_table[]" in py/objmodule.c from __future__ import print_function import re import io import os import argparse pattern = re.compile( r"[\n;]\s*MP_REGISTER_MODULE\((.*?),\s*(.*?),\s*(.*?)\);", flags=re.DOTALL ) def find_c_file(obj_file, vpath): """ Search vpaths for the c file that matches the provided object_file. :param str obj_file: object file to find the matching c file for :param List[str] vpath: List of base paths, similar to gcc vpath :return: str path to c file or None """ c_file = None relative_c_file = os.path.splitext(obj_file)[0] + ".c" relative_c_file = relative_c_file.lstrip('/\\') for p in vpath: possible_c_file = os.path.join(p, relative_c_file) if os.path.exists(possible_c_file): c_file = possible_c_file break return c_file def find_module_registrations(c_file): """ Find any MP_REGISTER_MODULE definitions in the provided c file. :param str c_file: path to c file to check :return: List[(module_name, obj_module, enabled_define)] """ global pattern if c_file is None: # No c file to match the object file, skip return set() with io.open(c_file, encoding='utf-8') as c_file_obj: return set(re.findall(pattern, c_file_obj.read())) def generate_module_table_header(modules): """ Generate header with module table entries for builtin modules. :param List[(module_name, obj_module, enabled_define)] modules: module defs :return: None """ # Print header file for all external modules. mod_defs = [] print("// Automatically generated by makemoduledefs.py.\n") for module_name, obj_module, enabled_define in modules: mod_def = "MODULE_DEF_{}".format(module_name.upper()) mod_defs.append(mod_def) print(( "#if ({enabled_define})\n" " extern const struct _mp_obj_module_t {obj_module};\n" " #define {mod_def} {{ MP_ROM_QSTR({module_name}), MP_ROM_PTR(&{obj_module}) }},\n" "#else\n" " #define {mod_def}\n" "#endif\n" ).format(module_name=module_name, obj_module=obj_module, enabled_define=enabled_define, mod_def=mod_def) ) print("\n#define MICROPY_REGISTERED_MODULES \\") for mod_def in mod_defs: print(" {mod_def} \\".format(mod_def=mod_def)) print("// MICROPY_REGISTERED_MODULES") def main(): parser = argparse.ArgumentParser() parser.add_argument("--vpath", default=".", help="comma separated list of folders to search for c files in") parser.add_argument("files", nargs="*", help="list of c files to search") args = parser.parse_args() vpath = [p.strip() for p in args.vpath.split(',')] modules = set() for obj_file in args.files: c_file = find_c_file(obj_file, vpath) modules |= find_module_registrations(c_file) generate_module_table_header(sorted(modules)) if __name__ == '__main__': main() micropython-1.12/py/makeqstrdata.py000066400000000000000000000214611357706137100175110ustar00rootroot00000000000000""" Process raw qstr file and output qstr data with length, hash and data bytes. This script works with Python 2.6, 2.7, 3.3 and 3.4. """ from __future__ import print_function import re import sys # Python 2/3 compatibility: # - iterating through bytes is different # - codepoint2name lives in a different module import platform if platform.python_version_tuple()[0] == '2': bytes_cons = lambda val, enc=None: bytearray(val) from htmlentitydefs import codepoint2name elif platform.python_version_tuple()[0] == '3': bytes_cons = bytes from html.entities import codepoint2name # end compatibility code codepoint2name[ord('-')] = 'hyphen'; # add some custom names to map characters that aren't in HTML codepoint2name[ord(' ')] = 'space' codepoint2name[ord('\'')] = 'squot' codepoint2name[ord(',')] = 'comma' codepoint2name[ord('.')] = 'dot' codepoint2name[ord(':')] = 'colon' codepoint2name[ord(';')] = 'semicolon' codepoint2name[ord('/')] = 'slash' codepoint2name[ord('%')] = 'percent' codepoint2name[ord('#')] = 'hash' codepoint2name[ord('(')] = 'paren_open' codepoint2name[ord(')')] = 'paren_close' codepoint2name[ord('[')] = 'bracket_open' codepoint2name[ord(']')] = 'bracket_close' codepoint2name[ord('{')] = 'brace_open' codepoint2name[ord('}')] = 'brace_close' codepoint2name[ord('*')] = 'star' codepoint2name[ord('!')] = 'bang' codepoint2name[ord('\\')] = 'backslash' codepoint2name[ord('+')] = 'plus' codepoint2name[ord('$')] = 'dollar' codepoint2name[ord('=')] = 'equals' codepoint2name[ord('?')] = 'question' codepoint2name[ord('@')] = 'at_sign' codepoint2name[ord('^')] = 'caret' codepoint2name[ord('|')] = 'pipe' codepoint2name[ord('~')] = 'tilde' # static qstrs, should be sorted static_qstr_list = [ "", "__dir__", # Put __dir__ after empty qstr for builtin dir() to work "\n", " ", "*", "/", "", "_", "__call__", "__class__", "__delitem__", "__enter__", "__exit__", "__getattr__", "__getitem__", "__hash__", "__init__", "__int__", "__iter__", "__len__", "__main__", "__module__", "__name__", "__new__", "__next__", "__qualname__", "__repr__", "__setitem__", "__str__", "ArithmeticError", "AssertionError", "AttributeError", "BaseException", "EOFError", "Ellipsis", "Exception", "GeneratorExit", "ImportError", "IndentationError", "IndexError", "KeyError", "KeyboardInterrupt", "LookupError", "MemoryError", "NameError", "NoneType", "NotImplementedError", "OSError", "OverflowError", "RuntimeError", "StopIteration", "SyntaxError", "SystemExit", "TypeError", "ValueError", "ZeroDivisionError", "abs", "all", "any", "append", "args", "bool", "builtins", "bytearray", "bytecode", "bytes", "callable", "chr", "classmethod", "clear", "close", "const", "copy", "count", "dict", "dir", "divmod", "end", "endswith", "eval", "exec", "extend", "find", "format", "from_bytes", "get", "getattr", "globals", "hasattr", "hash", "id", "index", "insert", "int", "isalpha", "isdigit", "isinstance", "islower", "isspace", "issubclass", "isupper", "items", "iter", "join", "key", "keys", "len", "list", "little", "locals", "lower", "lstrip", "main", "map", "micropython", "next", "object", "open", "ord", "pop", "popitem", "pow", "print", "range", "read", "readinto", "readline", "remove", "replace", "repr", "reverse", "rfind", "rindex", "round", "rsplit", "rstrip", "self", "send", "sep", "set", "setattr", "setdefault", "sort", "sorted", "split", "start", "startswith", "staticmethod", "step", "stop", "str", "strip", "sum", "super", "throw", "to_bytes", "tuple", "type", "update", "upper", "utf-8", "value", "values", "write", "zip", ] # this must match the equivalent function in qstr.c def compute_hash(qstr, bytes_hash): hash = 5381 for b in qstr: hash = (hash * 33) ^ b # Make sure that valid hash is never zero, zero means "hash not computed" return (hash & ((1 << (8 * bytes_hash)) - 1)) or 1 def qstr_escape(qst): def esc_char(m): c = ord(m.group(0)) try: name = codepoint2name[c] except KeyError: name = '0x%02x' % c return "_" + name + '_' return re.sub(r'[^A-Za-z0-9_]', esc_char, qst) def parse_input_headers(infiles): qcfgs = {} qstrs = {} # add static qstrs for qstr in static_qstr_list: # work out the corresponding qstr name ident = qstr_escape(qstr) # don't add duplicates assert ident not in qstrs # add the qstr to the list, with order number to retain original order in file order = len(qstrs) - 300000 qstrs[ident] = (order, ident, qstr) # read the qstrs in from the input files for infile in infiles: with open(infile, 'rt') as f: for line in f: line = line.strip() # is this a config line? match = re.match(r'^QCFG\((.+), (.+)\)', line) if match: value = match.group(2) if value[0] == '(' and value[-1] == ')': # strip parenthesis from config value value = value[1:-1] qcfgs[match.group(1)] = value continue # is this a QSTR line? match = re.match(r'^Q\((.*)\)$', line) if not match: continue # get the qstr value qstr = match.group(1) # special cases to specify control characters if qstr == '\\n': qstr = '\n' elif qstr == '\\r\\n': qstr = '\r\n' # work out the corresponding qstr name ident = qstr_escape(qstr) # don't add duplicates if ident in qstrs: continue # add the qstr to the list, with order number to retain original order in file order = len(qstrs) # but put special method names like __add__ at the top of list, so # that their id's fit into a byte if ident == "": # Sort empty qstr above all still order = -200000 elif ident == "__dir__": # Put __dir__ after empty qstr for builtin dir() to work order = -190000 elif ident.startswith("__"): order -= 100000 qstrs[ident] = (order, ident, qstr) if not qcfgs: sys.stderr.write("ERROR: Empty preprocessor output - check for errors above\n") sys.exit(1) return qcfgs, qstrs def make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr): qbytes = bytes_cons(qstr, 'utf8') qlen = len(qbytes) qhash = compute_hash(qbytes, cfg_bytes_hash) if all(32 <= ord(c) <= 126 and c != '\\' and c != '"' for c in qstr): # qstr is all printable ASCII so render it as-is (for easier debugging) qdata = qstr else: # qstr contains non-printable codes so render entire thing as hex pairs qdata = ''.join(('\\x%02x' % b) for b in qbytes) if qlen >= (1 << (8 * cfg_bytes_len)): print('qstr is too long:', qstr) assert False qlen_str = ('\\x%02x' * cfg_bytes_len) % tuple(((qlen >> (8 * i)) & 0xff) for i in range(cfg_bytes_len)) qhash_str = ('\\x%02x' * cfg_bytes_hash) % tuple(((qhash >> (8 * i)) & 0xff) for i in range(cfg_bytes_hash)) return '(const byte*)"%s%s" "%s"' % (qhash_str, qlen_str, qdata) def print_qstr_data(qcfgs, qstrs): # get config variables cfg_bytes_len = int(qcfgs['BYTES_IN_LEN']) cfg_bytes_hash = int(qcfgs['BYTES_IN_HASH']) # print out the starter of the generated C header file print('// This file was automatically generated by makeqstrdata.py') print('') # add NULL qstr with no hash or data print('QDEF(MP_QSTRnull, (const byte*)"%s%s" "")' % ('\\x00' * cfg_bytes_hash, '\\x00' * cfg_bytes_len)) # go through each qstr and print it out for order, ident, qstr in sorted(qstrs.values(), key=lambda x: x[0]): qbytes = make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr) print('QDEF(MP_QSTR_%s, %s)' % (ident, qbytes)) def do_work(infiles): qcfgs, qstrs = parse_input_headers(infiles) print_qstr_data(qcfgs, qstrs) if __name__ == "__main__": do_work(sys.argv[1:]) micropython-1.12/py/makeqstrdefs.py000066400000000000000000000060421357706137100175170ustar00rootroot00000000000000""" This script processes the output from the C preprocessor and extracts all qstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'. This script works with Python 2.6, 2.7, 3.3 and 3.4. """ from __future__ import print_function import re import sys import io import os def write_out(fname, output): if output: for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]: fname = fname.replace(m, r) with open(args.output_dir + "/" + fname + ".qstr", "w") as f: f.write("\n".join(output) + "\n") def process_file(f): re_line = re.compile(r"#[line]*\s\d+\s\"([^\"]+)\"") re_qstr = re.compile(r'MP_QSTR_[_a-zA-Z0-9]+') output = [] last_fname = None for line in f: if line.isspace(): continue # match gcc-like output (# n "file") and msvc-like output (#line n "file") if line.startswith(('# ', '#line')): m = re_line.match(line) assert m is not None fname = m.group(1) if not fname.endswith(".c"): continue if fname != last_fname: write_out(last_fname, output) output = [] last_fname = fname continue for match in re_qstr.findall(line): name = match.replace('MP_QSTR_', '') output.append('Q(' + name + ')') write_out(last_fname, output) return "" def cat_together(): import glob import hashlib hasher = hashlib.md5() all_lines = [] outf = open(args.output_dir + "/out", "wb") for fname in glob.glob(args.output_dir + "/*.qstr"): with open(fname, "rb") as f: lines = f.readlines() all_lines += lines all_lines.sort() all_lines = b"\n".join(all_lines) outf.write(all_lines) outf.close() hasher.update(all_lines) new_hash = hasher.hexdigest() #print(new_hash) old_hash = None try: with open(args.output_file + ".hash") as f: old_hash = f.read() except IOError: pass if old_hash != new_hash: print("QSTR updated") try: # rename below might fail if file exists os.remove(args.output_file) except: pass os.rename(args.output_dir + "/out", args.output_file) with open(args.output_file + ".hash", "w") as f: f.write(new_hash) else: print("QSTR not updated") if __name__ == "__main__": if len(sys.argv) != 5: print('usage: %s command input_filename output_dir output_file' % sys.argv[0]) sys.exit(2) class Args: pass args = Args() args.command = sys.argv[1] args.input_filename = sys.argv[2] args.output_dir = sys.argv[3] args.output_file = sys.argv[4] try: os.makedirs(args.output_dir) except OSError: pass if args.command == "split": with io.open(args.input_filename, encoding='utf-8') as infile: process_file(infile) if args.command == "cat": cat_together() micropython-1.12/py/makeversionhdr.py000066400000000000000000000056761357706137100200630ustar00rootroot00000000000000""" Generate header file with macros defining MicroPython version info. This script works with Python 2.6, 2.7, 3.3 and 3.4. """ from __future__ import print_function import sys import os import datetime import subprocess def get_version_info_from_git(): # Python 2.6 doesn't have check_output, so check for that try: subprocess.check_output subprocess.check_call except AttributeError: return None # Note: git describe doesn't work if no tag is available try: git_tag = subprocess.check_output(["git", "describe", "--dirty", "--always"], stderr=subprocess.STDOUT, universal_newlines=True).strip() except subprocess.CalledProcessError as er: if er.returncode == 128: # git exit code of 128 means no repository found return None git_tag = "" except OSError: return None try: git_hash = subprocess.check_output(["git", "rev-parse", "--short", "HEAD"], stderr=subprocess.STDOUT, universal_newlines=True).strip() except subprocess.CalledProcessError: git_hash = "unknown" except OSError: return None try: # Check if there are any modified files. subprocess.check_call(["git", "diff", "--no-ext-diff", "--quiet", "--exit-code"], stderr=subprocess.STDOUT) # Check if there are any staged files. subprocess.check_call(["git", "diff-index", "--cached", "--quiet", "HEAD", "--"], stderr=subprocess.STDOUT) except subprocess.CalledProcessError: git_hash += "-dirty" except OSError: return None return git_tag, git_hash def get_version_info_from_docs_conf(): with open(os.path.join(os.path.dirname(sys.argv[0]), "..", "docs", "conf.py")) as f: for line in f: if line.startswith("version = release = '"): ver = line.strip().split(" = ")[2].strip("'") git_tag = "v" + ver return git_tag, "" return None def make_version_header(filename): # Get version info using git, with fallback to docs/conf.py info = get_version_info_from_git() if info is None: info = get_version_info_from_docs_conf() git_tag, git_hash = info # Generate the file with the git and version info file_data = """\ // This file was generated by py/makeversionhdr.py #define MICROPY_GIT_TAG "%s" #define MICROPY_GIT_HASH "%s" #define MICROPY_BUILD_DATE "%s" """ % (git_tag, git_hash, datetime.date.today().strftime("%Y-%m-%d")) # Check if the file contents changed from last time write_file = True if os.path.isfile(filename): with open(filename, 'r') as f: existing_data = f.read() if existing_data == file_data: write_file = False # Only write the file if we need to if write_file: print("GEN %s" % filename) with open(filename, 'w') as f: f.write(file_data) if __name__ == "__main__": make_version_header(sys.argv[1]) micropython-1.12/py/malloc.c000066400000000000000000000163131357706137100160710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpconfig.h" #include "py/misc.h" #include "py/mpstate.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif #if MICROPY_MEM_STATS #if !MICROPY_MALLOC_USES_ALLOCATED_SIZE #error MICROPY_MEM_STATS requires MICROPY_MALLOC_USES_ALLOCATED_SIZE #endif #define UPDATE_PEAK() { if (MP_STATE_MEM(current_bytes_allocated) > MP_STATE_MEM(peak_bytes_allocated)) MP_STATE_MEM(peak_bytes_allocated) = MP_STATE_MEM(current_bytes_allocated); } #endif #if MICROPY_ENABLE_GC #include "py/gc.h" // We redirect standard alloc functions to GC heap - just for the rest of // this module. In the rest of MicroPython source, system malloc can be // freely accessed - for interfacing with system and 3rd-party libs for // example. On the other hand, some (e.g. bare-metal) ports may use GC // heap as system heap, so, to avoid warnings, we do undef's first. #undef malloc #undef free #undef realloc #define malloc(b) gc_alloc((b), false) #define malloc_with_finaliser(b) gc_alloc((b), true) #define free gc_free #define realloc(ptr, n) gc_realloc(ptr, n, true) #define realloc_ext(ptr, n, mv) gc_realloc(ptr, n, mv) #else // GC is disabled. Use system malloc/realloc/free. #if MICROPY_ENABLE_FINALISER #error MICROPY_ENABLE_FINALISER requires MICROPY_ENABLE_GC #endif STATIC void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) { if (allow_move) { return realloc(ptr, n_bytes); } else { // We are asked to resize, but without moving the memory region pointed to // by ptr. Unless the underlying memory manager has special provision for // this behaviour there is nothing we can do except fail to resize. return NULL; } } #endif // MICROPY_ENABLE_GC void *m_malloc(size_t num_bytes) { void *ptr = malloc(num_bytes); if (ptr == NULL && num_bytes != 0) { m_malloc_fail(num_bytes); } #if MICROPY_MEM_STATS MP_STATE_MEM(total_bytes_allocated) += num_bytes; MP_STATE_MEM(current_bytes_allocated) += num_bytes; UPDATE_PEAK(); #endif DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); return ptr; } void *m_malloc_maybe(size_t num_bytes) { void *ptr = malloc(num_bytes); #if MICROPY_MEM_STATS MP_STATE_MEM(total_bytes_allocated) += num_bytes; MP_STATE_MEM(current_bytes_allocated) += num_bytes; UPDATE_PEAK(); #endif DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); return ptr; } #if MICROPY_ENABLE_FINALISER void *m_malloc_with_finaliser(size_t num_bytes) { void *ptr = malloc_with_finaliser(num_bytes); if (ptr == NULL && num_bytes != 0) { m_malloc_fail(num_bytes); } #if MICROPY_MEM_STATS MP_STATE_MEM(total_bytes_allocated) += num_bytes; MP_STATE_MEM(current_bytes_allocated) += num_bytes; UPDATE_PEAK(); #endif DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); return ptr; } #endif void *m_malloc0(size_t num_bytes) { void *ptr = m_malloc(num_bytes); // If this config is set then the GC clears all memory, so we don't need to. #if !MICROPY_GC_CONSERVATIVE_CLEAR memset(ptr, 0, num_bytes); #endif return ptr; } #if MICROPY_MALLOC_USES_ALLOCATED_SIZE void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) { #else void *m_realloc(void *ptr, size_t new_num_bytes) { #endif void *new_ptr = realloc(ptr, new_num_bytes); if (new_ptr == NULL && new_num_bytes != 0) { m_malloc_fail(new_num_bytes); } #if MICROPY_MEM_STATS // At first thought, "Total bytes allocated" should only grow, // after all, it's *total*. But consider for example 2K block // shrunk to 1K and then grown to 2K again. It's still 2K // allocated total. If we process only positive increments, // we'll count 3K. size_t diff = new_num_bytes - old_num_bytes; MP_STATE_MEM(total_bytes_allocated) += diff; MP_STATE_MEM(current_bytes_allocated) += diff; UPDATE_PEAK(); #endif #if MICROPY_MALLOC_USES_ALLOCATED_SIZE DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr); #else DEBUG_printf("realloc %p, %d : %p\n", ptr, new_num_bytes, new_ptr); #endif return new_ptr; } #if MICROPY_MALLOC_USES_ALLOCATED_SIZE void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes, bool allow_move) { #else void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move) { #endif void *new_ptr = realloc_ext(ptr, new_num_bytes, allow_move); #if MICROPY_MEM_STATS // At first thought, "Total bytes allocated" should only grow, // after all, it's *total*. But consider for example 2K block // shrunk to 1K and then grown to 2K again. It's still 2K // allocated total. If we process only positive increments, // we'll count 3K. // Also, don't count failed reallocs. if (!(new_ptr == NULL && new_num_bytes != 0)) { size_t diff = new_num_bytes - old_num_bytes; MP_STATE_MEM(total_bytes_allocated) += diff; MP_STATE_MEM(current_bytes_allocated) += diff; UPDATE_PEAK(); } #endif #if MICROPY_MALLOC_USES_ALLOCATED_SIZE DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr); #else DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, new_num_bytes, new_ptr); #endif return new_ptr; } #if MICROPY_MALLOC_USES_ALLOCATED_SIZE void m_free(void *ptr, size_t num_bytes) { #else void m_free(void *ptr) { #endif free(ptr); #if MICROPY_MEM_STATS MP_STATE_MEM(current_bytes_allocated) -= num_bytes; #endif #if MICROPY_MALLOC_USES_ALLOCATED_SIZE DEBUG_printf("free %p, %d\n", ptr, num_bytes); #else DEBUG_printf("free %p\n", ptr); #endif } #if MICROPY_MEM_STATS size_t m_get_total_bytes_allocated(void) { return MP_STATE_MEM(total_bytes_allocated); } size_t m_get_current_bytes_allocated(void) { return MP_STATE_MEM(current_bytes_allocated); } size_t m_get_peak_bytes_allocated(void) { return MP_STATE_MEM(peak_bytes_allocated); } #endif micropython-1.12/py/map.c000066400000000000000000000370451357706137100154040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/mpconfig.h" #include "py/misc.h" #include "py/runtime.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #else // don't print debugging info #define DEBUG_PRINT (0) #define DEBUG_printf(...) (void)0 #endif // Fixed empty map. Useful when need to call kw-receiving functions // without any keywords from C, etc. const mp_map_t mp_const_empty_map = { .all_keys_are_qstrs = 0, .is_fixed = 1, .is_ordered = 1, .used = 0, .alloc = 0, .table = NULL, }; // This table of sizes is used to control the growth of hash tables. // The first set of sizes are chosen so the allocation fits exactly in a // 4-word GC block, and it's not so important for these small values to be // prime. The latter sizes are prime and increase at an increasing rate. STATIC const uint16_t hash_allocation_sizes[] = { 0, 2, 4, 6, 8, 10, 12, // +2 17, 23, 29, 37, 47, 59, 73, // *1.25 97, 127, 167, 223, 293, 389, 521, 691, 919, 1223, 1627, 2161, // *1.33 3229, 4831, 7243, 10861, 16273, 24407, 36607, 54907, // *1.5 }; STATIC size_t get_hash_alloc_greater_or_equal_to(size_t x) { for (size_t i = 0; i < MP_ARRAY_SIZE(hash_allocation_sizes); i++) { if (hash_allocation_sizes[i] >= x) { return hash_allocation_sizes[i]; } } // ran out of primes in the table! // return something sensible, at least make it odd return (x + x / 2) | 1; } /******************************************************************************/ /* map */ void mp_map_init(mp_map_t *map, size_t n) { if (n == 0) { map->alloc = 0; map->table = NULL; } else { map->alloc = n; map->table = m_new0(mp_map_elem_t, map->alloc); } map->used = 0; map->all_keys_are_qstrs = 1; map->is_fixed = 0; map->is_ordered = 0; } void mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table) { map->alloc = n; map->used = n; map->all_keys_are_qstrs = 1; map->is_fixed = 1; map->is_ordered = 1; map->table = (mp_map_elem_t*)table; } // Differentiate from mp_map_clear() - semantics is different void mp_map_deinit(mp_map_t *map) { if (!map->is_fixed) { m_del(mp_map_elem_t, map->table, map->alloc); } map->used = map->alloc = 0; } void mp_map_clear(mp_map_t *map) { if (!map->is_fixed) { m_del(mp_map_elem_t, map->table, map->alloc); } map->alloc = 0; map->used = 0; map->all_keys_are_qstrs = 1; map->is_fixed = 0; map->table = NULL; } STATIC void mp_map_rehash(mp_map_t *map) { size_t old_alloc = map->alloc; size_t new_alloc = get_hash_alloc_greater_or_equal_to(map->alloc + 1); DEBUG_printf("mp_map_rehash(%p): " UINT_FMT " -> " UINT_FMT "\n", map, old_alloc, new_alloc); mp_map_elem_t *old_table = map->table; mp_map_elem_t *new_table = m_new0(mp_map_elem_t, new_alloc); // If we reach this point, table resizing succeeded, now we can edit the old map. map->alloc = new_alloc; map->used = 0; map->all_keys_are_qstrs = 1; map->table = new_table; for (size_t i = 0; i < old_alloc; i++) { if (old_table[i].key != MP_OBJ_NULL && old_table[i].key != MP_OBJ_SENTINEL) { mp_map_lookup(map, old_table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = old_table[i].value; } } m_del(mp_map_elem_t, old_table, old_alloc); } // MP_MAP_LOOKUP behaviour: // - returns NULL if not found, else the slot it was found in with key,value non-null // MP_MAP_LOOKUP_ADD_IF_NOT_FOUND behaviour: // - returns slot, with key non-null and value=MP_OBJ_NULL if it was added // MP_MAP_LOOKUP_REMOVE_IF_FOUND behaviour: // - returns NULL if not found, else the slot if was found in with key null and value non-null mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) { // If the map is a fixed array then we must only be called for a lookup assert(!map->is_fixed || lookup_kind == MP_MAP_LOOKUP); // Work out if we can compare just pointers bool compare_only_ptrs = map->all_keys_are_qstrs; if (compare_only_ptrs) { if (mp_obj_is_qstr(index)) { // Index is a qstr, so can just do ptr comparison. } else if (mp_obj_is_type(index, &mp_type_str)) { // Index is a non-interned string. // We can either intern the string, or force a full equality comparison. // We chose the latter, since interning costs time and potentially RAM, // and it won't necessarily benefit subsequent calls because these calls // most likely won't pass the newly-interned string. compare_only_ptrs = false; } else if (lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { // If we are not adding, then we can return straight away a failed // lookup because we know that the index will never be found. return NULL; } } // if the map is an ordered array then we must do a brute force linear search if (map->is_ordered) { for (mp_map_elem_t *elem = &map->table[0], *top = &map->table[map->used]; elem < top; elem++) { if (elem->key == index || (!compare_only_ptrs && mp_obj_equal(elem->key, index))) { #if MICROPY_PY_COLLECTIONS_ORDEREDDICT if (MP_UNLIKELY(lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND)) { // remove the found element by moving the rest of the array down mp_obj_t value = elem->value; --map->used; memmove(elem, elem + 1, (top - elem - 1) * sizeof(*elem)); // put the found element after the end so the caller can access it if needed elem = &map->table[map->used]; elem->key = MP_OBJ_NULL; elem->value = value; } #endif return elem; } } #if MICROPY_PY_COLLECTIONS_ORDEREDDICT if (MP_LIKELY(lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)) { return NULL; } if (map->used == map->alloc) { // TODO: Alloc policy map->alloc += 4; map->table = m_renew(mp_map_elem_t, map->table, map->used, map->alloc); mp_seq_clear(map->table, map->used, map->alloc, sizeof(*map->table)); } mp_map_elem_t *elem = map->table + map->used++; elem->key = index; if (!mp_obj_is_qstr(index)) { map->all_keys_are_qstrs = 0; } return elem; #else return NULL; #endif } // map is a hash table (not an ordered array), so do a hash lookup if (map->alloc == 0) { if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { mp_map_rehash(map); } else { return NULL; } } // get hash of index, with fast path for common case of qstr mp_uint_t hash; if (mp_obj_is_qstr(index)) { hash = qstr_hash(MP_OBJ_QSTR_VALUE(index)); } else { hash = MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, index)); } size_t pos = hash % map->alloc; size_t start_pos = pos; mp_map_elem_t *avail_slot = NULL; for (;;) { mp_map_elem_t *slot = &map->table[pos]; if (slot->key == MP_OBJ_NULL) { // found NULL slot, so index is not in table if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { map->used += 1; if (avail_slot == NULL) { avail_slot = slot; } avail_slot->key = index; avail_slot->value = MP_OBJ_NULL; if (!mp_obj_is_qstr(index)) { map->all_keys_are_qstrs = 0; } return avail_slot; } else { return NULL; } } else if (slot->key == MP_OBJ_SENTINEL) { // found deleted slot, remember for later if (avail_slot == NULL) { avail_slot = slot; } } else if (slot->key == index || (!compare_only_ptrs && mp_obj_equal(slot->key, index))) { // found index // Note: CPython does not replace the index; try x={True:'true'};x[1]='one';x if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) { // delete element in this slot map->used--; if (map->table[(pos + 1) % map->alloc].key == MP_OBJ_NULL) { // optimisation if next slot is empty slot->key = MP_OBJ_NULL; } else { slot->key = MP_OBJ_SENTINEL; } // keep slot->value so that caller can access it if needed } return slot; } // not yet found, keep searching in this table pos = (pos + 1) % map->alloc; if (pos == start_pos) { // search got back to starting position, so index is not in table if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { if (avail_slot != NULL) { // there was an available slot, so use that map->used++; avail_slot->key = index; avail_slot->value = MP_OBJ_NULL; if (!mp_obj_is_qstr(index)) { map->all_keys_are_qstrs = 0; } return avail_slot; } else { // not enough room in table, rehash it mp_map_rehash(map); // restart the search for the new element start_pos = pos = hash % map->alloc; } } else { return NULL; } } } } /******************************************************************************/ /* set */ #if MICROPY_PY_BUILTINS_SET void mp_set_init(mp_set_t *set, size_t n) { set->alloc = n; set->used = 0; set->table = m_new0(mp_obj_t, set->alloc); } STATIC void mp_set_rehash(mp_set_t *set) { size_t old_alloc = set->alloc; mp_obj_t *old_table = set->table; set->alloc = get_hash_alloc_greater_or_equal_to(set->alloc + 1); set->used = 0; set->table = m_new0(mp_obj_t, set->alloc); for (size_t i = 0; i < old_alloc; i++) { if (old_table[i] != MP_OBJ_NULL && old_table[i] != MP_OBJ_SENTINEL) { mp_set_lookup(set, old_table[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } } m_del(mp_obj_t, old_table, old_alloc); } mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) { // Note: lookup_kind can be MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND which // is handled by using bitwise operations. if (set->alloc == 0) { if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { mp_set_rehash(set); } else { return MP_OBJ_NULL; } } mp_uint_t hash = MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, index)); size_t pos = hash % set->alloc; size_t start_pos = pos; mp_obj_t *avail_slot = NULL; for (;;) { mp_obj_t elem = set->table[pos]; if (elem == MP_OBJ_NULL) { // found NULL slot, so index is not in table if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { if (avail_slot == NULL) { avail_slot = &set->table[pos]; } set->used++; *avail_slot = index; return index; } else { return MP_OBJ_NULL; } } else if (elem == MP_OBJ_SENTINEL) { // found deleted slot, remember for later if (avail_slot == NULL) { avail_slot = &set->table[pos]; } } else if (mp_obj_equal(elem, index)) { // found index if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND) { // delete element set->used--; if (set->table[(pos + 1) % set->alloc] == MP_OBJ_NULL) { // optimisation if next slot is empty set->table[pos] = MP_OBJ_NULL; } else { set->table[pos] = MP_OBJ_SENTINEL; } } return elem; } // not yet found, keep searching in this table pos = (pos + 1) % set->alloc; if (pos == start_pos) { // search got back to starting position, so index is not in table if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { if (avail_slot != NULL) { // there was an available slot, so use that set->used++; *avail_slot = index; return index; } else { // not enough room in table, rehash it mp_set_rehash(set); // restart the search for the new element start_pos = pos = hash % set->alloc; } } else { return MP_OBJ_NULL; } } } } mp_obj_t mp_set_remove_first(mp_set_t *set) { for (size_t pos = 0; pos < set->alloc; pos++) { if (mp_set_slot_is_filled(set, pos)) { mp_obj_t elem = set->table[pos]; // delete element set->used--; if (set->table[(pos + 1) % set->alloc] == MP_OBJ_NULL) { // optimisation if next slot is empty set->table[pos] = MP_OBJ_NULL; } else { set->table[pos] = MP_OBJ_SENTINEL; } return elem; } } return MP_OBJ_NULL; } void mp_set_clear(mp_set_t *set) { m_del(mp_obj_t, set->table, set->alloc); set->alloc = 0; set->used = 0; set->table = NULL; } #endif // MICROPY_PY_BUILTINS_SET #if defined(DEBUG_PRINT) && DEBUG_PRINT void mp_map_dump(mp_map_t *map) { for (size_t i = 0; i < map->alloc; i++) { if (map->table[i].key != MP_OBJ_NULL) { mp_obj_print(map->table[i].key, PRINT_REPR); } else { DEBUG_printf("(nil)"); } DEBUG_printf(": %p\n", map->table[i].value); } DEBUG_printf("---\n"); } #endif micropython-1.12/py/misc.h000066400000000000000000000221101357706137100155520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_MISC_H #define MICROPY_INCLUDED_PY_MISC_H // a mini library of useful types and functions /** types *******************************************************/ #include #include #include typedef unsigned char byte; typedef unsigned int uint; /** generic ops *************************************************/ #ifndef MIN #define MIN(x, y) ((x) < (y) ? (x) : (y)) #endif #ifndef MAX #define MAX(x, y) ((x) > (y) ? (x) : (y)) #endif // Classical double-indirection stringification of preprocessor macro's value #define MP_STRINGIFY_HELPER(x) #x #define MP_STRINGIFY(x) MP_STRINGIFY_HELPER(x) // Static assertion macro #define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)])) /** memory allocation ******************************************/ // TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element) #define m_new(type, num) ((type*)(m_malloc(sizeof(type) * (num)))) #define m_new_maybe(type, num) ((type*)(m_malloc_maybe(sizeof(type) * (num)))) #define m_new0(type, num) ((type*)(m_malloc0(sizeof(type) * (num)))) #define m_new_obj(type) (m_new(type, 1)) #define m_new_obj_maybe(type) (m_new_maybe(type, 1)) #define m_new_obj_var(obj_type, var_type, var_num) ((obj_type*)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num))) #define m_new_obj_var_maybe(obj_type, var_type, var_num) ((obj_type*)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num))) #if MICROPY_ENABLE_FINALISER #define m_new_obj_with_finaliser(type) ((type*)(m_malloc_with_finaliser(sizeof(type)))) #define m_new_obj_var_with_finaliser(type, var_type, var_num) ((type*)m_malloc_with_finaliser(sizeof(type) + sizeof(var_type) * (var_num))) #else #define m_new_obj_with_finaliser(type) m_new_obj(type) #define m_new_obj_var_with_finaliser(type, var_type, var_num) m_new_obj_var(type, var_type, var_num) #endif #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num)))) #define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type*)(m_realloc_maybe((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num), (allow_move)))) #define m_del(type, ptr, num) m_free(ptr, sizeof(type) * (num)) #define m_del_var(obj_type, var_type, var_num, ptr) (m_free(ptr, sizeof(obj_type) + sizeof(var_type) * (var_num))) #else #define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (new_num)))) #define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type*)(m_realloc_maybe((ptr), sizeof(type) * (new_num), (allow_move)))) #define m_del(type, ptr, num) ((void)(num), m_free(ptr)) #define m_del_var(obj_type, var_type, var_num, ptr) ((void)(var_num), m_free(ptr)) #endif #define m_del_obj(type, ptr) (m_del(type, ptr, 1)) void *m_malloc(size_t num_bytes); void *m_malloc_maybe(size_t num_bytes); void *m_malloc_with_finaliser(size_t num_bytes); void *m_malloc0(size_t num_bytes); #if MICROPY_MALLOC_USES_ALLOCATED_SIZE void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes); void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes, bool allow_move); void m_free(void *ptr, size_t num_bytes); #else void *m_realloc(void *ptr, size_t new_num_bytes); void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move); void m_free(void *ptr); #endif NORETURN void m_malloc_fail(size_t num_bytes); #if MICROPY_MEM_STATS size_t m_get_total_bytes_allocated(void); size_t m_get_current_bytes_allocated(void); size_t m_get_peak_bytes_allocated(void); #endif /** array helpers ***********************************************/ // get the number of elements in a fixed-size array #define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) // align ptr to the nearest multiple of "alignment" #define MP_ALIGN(ptr, alignment) (void*)(((uintptr_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1)) /** unichar / UTF-8 *********************************************/ #if MICROPY_PY_BUILTINS_STR_UNICODE // with unicode enabled we need a type which can fit chars up to 0x10ffff typedef uint32_t unichar; #else // without unicode enabled we can only need to fit chars up to 0xff // (on 16-bit archs uint is 16-bits and more efficient than uint32_t) typedef uint unichar; #endif #if MICROPY_PY_BUILTINS_STR_UNICODE unichar utf8_get_char(const byte *s); const byte *utf8_next_char(const byte *s); size_t utf8_charlen(const byte *str, size_t len); #else static inline unichar utf8_get_char(const byte *s) { return *s; } static inline const byte *utf8_next_char(const byte *s) { return s + 1; } static inline size_t utf8_charlen(const byte *str, size_t len) { (void)str; return len; } #endif bool unichar_isspace(unichar c); bool unichar_isalpha(unichar c); bool unichar_isprint(unichar c); bool unichar_isdigit(unichar c); bool unichar_isxdigit(unichar c); bool unichar_isident(unichar c); bool unichar_isupper(unichar c); bool unichar_islower(unichar c); unichar unichar_tolower(unichar c); unichar unichar_toupper(unichar c); mp_uint_t unichar_xdigit_value(unichar c); #define UTF8_IS_NONASCII(ch) ((ch) & 0x80) #define UTF8_IS_CONT(ch) (((ch) & 0xC0) == 0x80) /** variable string *********************************************/ typedef struct _vstr_t { size_t alloc; size_t len; char *buf; bool fixed_buf : 1; } vstr_t; // convenience macro to declare a vstr with a fixed size buffer on the stack #define VSTR_FIXED(vstr, alloc) vstr_t vstr; char vstr##_buf[(alloc)]; vstr_init_fixed_buf(&vstr, (alloc), vstr##_buf); void vstr_init(vstr_t *vstr, size_t alloc); void vstr_init_len(vstr_t *vstr, size_t len); void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf); struct _mp_print_t; void vstr_init_print(vstr_t *vstr, size_t alloc, struct _mp_print_t *print); void vstr_clear(vstr_t *vstr); vstr_t *vstr_new(size_t alloc); void vstr_free(vstr_t *vstr); static inline void vstr_reset(vstr_t *vstr) { vstr->len = 0; } static inline char *vstr_str(vstr_t *vstr) { return vstr->buf; } static inline size_t vstr_len(vstr_t *vstr) { return vstr->len; } void vstr_hint_size(vstr_t *vstr, size_t size); char *vstr_extend(vstr_t *vstr, size_t size); char *vstr_add_len(vstr_t *vstr, size_t len); char *vstr_null_terminated_str(vstr_t *vstr); void vstr_add_byte(vstr_t *vstr, byte v); void vstr_add_char(vstr_t *vstr, unichar chr); void vstr_add_str(vstr_t *vstr, const char *str); void vstr_add_strn(vstr_t *vstr, const char *str, size_t len); void vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b); void vstr_ins_char(vstr_t *vstr, size_t char_pos, unichar chr); void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut); void vstr_cut_tail_bytes(vstr_t *vstr, size_t bytes_to_cut); void vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut); void vstr_printf(vstr_t *vstr, const char *fmt, ...); /** non-dynamic size-bounded variable buffer/string *************/ #define CHECKBUF(buf, max_size) char buf[max_size + 1]; size_t buf##_len = max_size; char *buf##_p = buf; #define CHECKBUF_RESET(buf, max_size) buf##_len = max_size; buf##_p = buf; #define CHECKBUF_APPEND(buf, src, src_len) \ { size_t l = MIN(src_len, buf##_len); \ memcpy(buf##_p, src, l); \ buf##_len -= l; \ buf##_p += l; } #define CHECKBUF_APPEND_0(buf) { *buf##_p = 0; } #define CHECKBUF_LEN(buf) (buf##_p - buf) #ifdef va_start void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap); #endif // Debugging helpers int DEBUG_printf(const char *fmt, ...); extern mp_uint_t mp_verbose_flag; /** float internals *************/ #if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #define MP_FLOAT_EXP_BITS (11) #define MP_FLOAT_FRAC_BITS (52) #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #define MP_FLOAT_EXP_BITS (8) #define MP_FLOAT_FRAC_BITS (23) #endif #define MP_FLOAT_EXP_BIAS ((1 << (MP_FLOAT_EXP_BITS - 1)) - 1) #endif // MICROPY_PY_BUILTINS_FLOAT #endif // MICROPY_INCLUDED_PY_MISC_H micropython-1.12/py/mkenv.mk000066400000000000000000000033621357706137100161270ustar00rootroot00000000000000ifneq ($(lastword a b),b) $(error These Makefiles require make 3.81 or newer) endif # Set TOP to be the path to get from the current directory (where make was # invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns # the name of this makefile relative to where make was invoked. # # We assume that this file is in the py directory so we use $(dir ) twice # to get to the top of the tree. THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) TOP := $(patsubst %/py/mkenv.mk,%,$(THIS_MAKEFILE)) # Turn on increased build verbosity by defining BUILD_VERBOSE in your main # Makefile or in your environment. You can also use V=1 on the make command # line. ifeq ("$(origin V)", "command line") BUILD_VERBOSE=$(V) endif ifndef BUILD_VERBOSE BUILD_VERBOSE = 0 endif ifeq ($(BUILD_VERBOSE),0) Q = @ else Q = endif # Since this is a new feature, advertise it ifeq ($(BUILD_VERBOSE),0) $(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) endif # default settings; can be overridden in main Makefile PY_SRC ?= $(TOP)/py BUILD ?= build RM = rm ECHO = @echo CP = cp MKDIR = mkdir SED = sed CAT = cat TOUCH = touch PYTHON = python3 AS = $(CROSS_COMPILE)as CC = $(CROSS_COMPILE)gcc CXX = $(CROSS_COMPILE)g++ GDB = $(CROSS_COMPILE)gdb LD = $(CROSS_COMPILE)ld OBJCOPY = $(CROSS_COMPILE)objcopy SIZE = $(CROSS_COMPILE)size STRIP = $(CROSS_COMPILE)strip AR = $(CROSS_COMPILE)ar ifeq ($(MICROPY_FORCE_32BIT),1) CC += -m32 CXX += -m32 LD += -m32 endif MAKE_MANIFEST = $(PYTHON) $(TOP)/tools/makemanifest.py MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py MPY_CROSS = $(TOP)/mpy-cross/mpy-cross MPY_TOOL = $(PYTHON) $(TOP)/tools/mpy-tool.py MPY_LIB_DIR = $(TOP)/../micropython-lib all: .PHONY: all .DELETE_ON_ERROR: MKENV_INCLUDED = 1 micropython-1.12/py/mkrules.mk000066400000000000000000000171271357706137100164750ustar00rootroot00000000000000ifneq ($(MKENV_INCLUDED),1) # We assume that mkenv is in the same directory as this file. THIS_MAKEFILE = $(lastword $(MAKEFILE_LIST)) include $(dir $(THIS_MAKEFILE))mkenv.mk endif # This file expects that OBJ contains a list of all of the object files. # The directory portion of each object file is used to locate the source # and should not contain any ..'s but rather be relative to the top of the # tree. # # So for example, py/map.c would have an object file name py/map.o # The object files will go into the build directory and mantain the same # directory structure as the source tree. So the final dependency will look # like this: # # build/py/map.o: py/map.c # # We set vpath to point to the top of the tree so that the source files # can be located. By following this scheme, it allows a single build rule # to be used to compile all .c files. vpath %.S . $(TOP) $(USER_C_MODULES) $(BUILD)/%.o: %.S $(ECHO) "CC $<" $(Q)$(CC) $(CFLAGS) -c -o $@ $< vpath %.s . $(TOP) $(USER_C_MODULES) $(BUILD)/%.o: %.s $(ECHO) "AS $<" $(Q)$(AS) -o $@ $< define compile_c $(ECHO) "CC $<" $(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< @# The following fixes the dependency file. @# See http://make.paulandlesley.org/autodep.html for details. @# Regex adjusted from the above to play better with Windows paths, etc. @$(CP) $(@:.o=.d) $(@:.o=.P); \ $(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ $(RM) -f $(@:.o=.d) endef vpath %.c . $(TOP) $(USER_C_MODULES) $(BUILD)/%.o: %.c $(call compile_c) QSTR_GEN_EXTRA_CFLAGS += -DNO_QSTR QSTR_GEN_EXTRA_CFLAGS += -I$(BUILD)/tmp vpath %.c . $(TOP) $(USER_C_MODULES) $(BUILD)/%.pp: %.c $(ECHO) "PreProcess $<" $(Q)$(CPP) $(CFLAGS) -Wp,-C,-dD,-dI -o $@ $< # The following rule uses | to create an order only prerequisite. Order only # prerequisites only get built if they don't exist. They don't cause timestamp # checking to be performed. # # We don't know which source files actually need the generated.h (since # it is #included from str.h). The compiler generated dependencies will cause # the right .o's to get recompiled if the generated.h file changes. Adding # an order-only dependency to all of the .o's will cause the generated .h # to get built before we try to compile any of them. $(OBJ): | $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/mpversion.h # The logic for qstr regeneration is: # - if anything in QSTR_GLOBAL_DEPENDENCIES is newer, then process all source files ($^) # - else, if list of newer prerequisites ($?) is not empty, then process just these ($?) # - else, process all source files ($^) [this covers "make -B" which can set $? to empty] # See more information about this process in docs/develop/qstr.rst. $(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(QSTR_GLOBAL_REQUIREMENTS) $(ECHO) "GEN $@" $(Q)$(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) >$(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr.split: $(HEADER_BUILD)/qstr.i.last $(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED) $(Q)$(TOUCH) $@ $(QSTR_DEFS_COLLECTED): $(HEADER_BUILD)/qstr.split $(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py cat $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED) # $(sort $(var)) removes duplicates # # The net effect of this, is it causes the objects to depend on the # object directories (but only for existence), and the object directories # will be created if they don't exist. OBJ_DIRS = $(sort $(dir $(OBJ))) $(OBJ): | $(OBJ_DIRS) $(OBJ_DIRS): $(MKDIR) -p $@ $(HEADER_BUILD): $(MKDIR) -p $@ ifneq ($(FROZEN_MANIFEST),) # to build frozen_content.c from a manifest $(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h $(Q)$(MAKE_MANIFEST) -o $@ -v "MPY_DIR=$(TOP)" -v "MPY_LIB_DIR=$(MPY_LIB_DIR)" -v "PORT_DIR=$(shell pwd)" -v "BOARD_DIR=$(BOARD_DIR)" -b "$(BUILD)" $(if $(MPY_CROSS_FLAGS),-f"$(MPY_CROSS_FLAGS)",) $(FROZEN_MANIFEST) ifneq ($(FROZEN_DIR),) $(error FROZEN_DIR cannot be used in conjunction with FROZEN_MANIFEST) endif ifneq ($(FROZEN_MPY_DIR),) $(error FROZEN_MPY_DIR cannot be used in conjunction with FROZEN_MANIFEST) endif endif ifneq ($(FROZEN_DIR),) $(info Warning: FROZEN_DIR is deprecated in favour of FROZEN_MANIFEST) $(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DEPS) $(ECHO) "GEN $@" $(Q)$(MAKE_FROZEN) $(FROZEN_DIR) > $@ endif ifneq ($(FROZEN_MPY_DIR),) $(info Warning: FROZEN_MPY_DIR is deprecated in favour of FROZEN_MANIFEST) # make a list of all the .py files that need compiling and freezing FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)/==') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) # to build .mpy files from .py files $(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py @$(ECHO) "MPY $<" $(Q)$(MKDIR) -p $(dir $@) $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $< # to build frozen_mpy.c from all .mpy files $(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h @$(ECHO) "GEN $@" $(Q)$(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@ endif ifneq ($(PROG),) # Build a standalone executable (unix does this) all: $(PROG) $(PROG): $(OBJ) $(ECHO) "LINK $@" # Do not pass COPT here - it's *C* compiler optimizations. For example, # we may want to compile using Thumb, but link with non-Thumb libc. $(Q)$(CC) -o $@ $^ $(LIB) $(LDFLAGS) ifndef DEBUG $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG) endif $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $(PROG) clean: clean-prog clean-prog: $(RM) -f $(PROG) $(RM) -f $(PROG).map .PHONY: clean-prog endif submodules: $(ECHO) "Updating submodules: $(GIT_SUBMODULES)" ifneq ($(GIT_SUBMODULES),) $(Q)git submodule update --init $(addprefix $(TOP)/,$(GIT_SUBMODULES)) endif .PHONY: submodules LIBMICROPYTHON = libmicropython.a # We can execute extra commands after library creation using # LIBMICROPYTHON_EXTRA_CMD. This may be needed e.g. to integrate # with 3rd-party projects which don't have proper dependency # tracking. Then LIBMICROPYTHON_EXTRA_CMD can e.g. touch some # other file to cause needed effect, e.g. relinking with new lib. lib $(LIBMICROPYTHON): $(OBJ) $(AR) rcs $(LIBMICROPYTHON) $^ $(LIBMICROPYTHON_EXTRA_CMD) clean: $(RM) -rf $(BUILD) $(CLEAN_EXTRA) .PHONY: clean # Clean every non-git file from FROZEN_DIR/FROZEN_MPY_DIR, but making a backup. # We run rmdir below to avoid empty backup dir (it will silently fail if backup # is non-empty). clean-frozen: if [ -n "$(FROZEN_MPY_DIR)" ]; then \ backup_dir=$(FROZEN_MPY_DIR).$$(date +%Y%m%dT%H%M%S); mkdir $$backup_dir; \ cd $(FROZEN_MPY_DIR); git status --ignored -u all -s . | awk ' {print $$2}' \ | xargs --no-run-if-empty cp --parents -t ../$$backup_dir; \ rmdir ../$$backup_dir 2>/dev/null || true; \ git clean -d -f .; \ fi if [ -n "$(FROZEN_DIR)" ]; then \ backup_dir=$(FROZEN_DIR).$$(date +%Y%m%dT%H%M%S); mkdir $$backup_dir; \ cd $(FROZEN_DIR); git status --ignored -u all -s . | awk ' {print $$2}' \ | xargs --no-run-if-empty cp --parents -t ../$$backup_dir; \ rmdir ../$$backup_dir 2>/dev/null || true; \ git clean -d -f .; \ fi .PHONY: clean-frozen print-cfg: $(ECHO) "PY_SRC = $(PY_SRC)" $(ECHO) "BUILD = $(BUILD)" $(ECHO) "OBJ = $(OBJ)" .PHONY: print-cfg print-def: @$(ECHO) "The following defines are built into the $(CC) compiler" $(TOUCH) __empty__.c @$(CC) -E -Wp,-dM __empty__.c @$(RM) -f __empty__.c -include $(OBJ:.o=.P) micropython-1.12/py/modarray.c000066400000000000000000000033711357706137100164400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" #if MICROPY_PY_ARRAY STATIC const mp_rom_map_elem_t mp_module_array_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uarray) }, { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mp_type_array) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_array_globals, mp_module_array_globals_table); const mp_obj_module_t mp_module_uarray = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_array_globals, }; MP_REGISTER_MODULE(MP_QSTR_uarray, mp_module_uarray, MICROPY_PY_ARRAY); #endif micropython-1.12/py/modbuiltins.c000066400000000000000000000750201357706137100171530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/smallint.h" #include "py/objint.h" #include "py/objstr.h" #include "py/objtype.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/stream.h" #if MICROPY_PY_BUILTINS_FLOAT #include #endif #if MICROPY_PY_IO extern struct _mp_dummy_t mp_sys_stdout_obj; // type is irrelevant, just need pointer #endif // args[0] is function from class body // args[1] is class name // args[2:] are base objects STATIC mp_obj_t mp_builtin___build_class__(size_t n_args, const mp_obj_t *args) { assert(2 <= n_args); // set the new classes __locals__ object mp_obj_dict_t *old_locals = mp_locals_get(); mp_obj_t class_locals = mp_obj_new_dict(0); mp_locals_set(MP_OBJ_TO_PTR(class_locals)); // call the class code mp_obj_t cell = mp_call_function_0(args[0]); // restore old __locals__ object mp_locals_set(old_locals); // get the class type (meta object) from the base objects mp_obj_t meta; if (n_args == 2) { // no explicit bases, so use 'type' meta = MP_OBJ_FROM_PTR(&mp_type_type); } else { // use type of first base object meta = MP_OBJ_FROM_PTR(mp_obj_get_type(args[2])); } // TODO do proper metaclass resolution for multiple base objects // create the new class using a call to the meta object mp_obj_t meta_args[3]; meta_args[0] = args[1]; // class name meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // tuple of bases meta_args[2] = class_locals; // dict of members mp_obj_t new_class = mp_call_function_n_kw(meta, 3, 0, meta_args); // store into cell if neede if (cell != mp_const_none) { mp_obj_cell_set(cell, new_class); } return new_class; } MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__); STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) { return mp_unary_op(MP_UNARY_OP_ABS, o_in); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs); STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) { mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(o_in, &iter_buf); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (!mp_obj_is_true(item)) { return mp_const_false; } } return mp_const_true; } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all); STATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) { mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(o_in, &iter_buf); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (mp_obj_is_true(item)) { return mp_const_true; } } return mp_const_false; } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any); STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) { mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in }; return mp_obj_str_format(MP_ARRAY_SIZE(args), args, NULL); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin); STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) { if (mp_obj_is_callable(o_in)) { return mp_const_true; } else { return mp_const_false; } } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable); STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { #if MICROPY_PY_BUILTINS_STR_UNICODE mp_uint_t c = mp_obj_get_int(o_in); uint8_t str[4]; int len = 0; if (c < 0x80) { *str = c; len = 1; } else if (c < 0x800) { str[0] = (c >> 6) | 0xC0; str[1] = (c & 0x3F) | 0x80; len = 2; } else if (c < 0x10000) { str[0] = (c >> 12) | 0xE0; str[1] = ((c >> 6) & 0x3F) | 0x80; str[2] = (c & 0x3F) | 0x80; len = 3; } else if (c < 0x110000) { str[0] = (c >> 18) | 0xF0; str[1] = ((c >> 12) & 0x3F) | 0x80; str[2] = ((c >> 6) & 0x3F) | 0x80; str[3] = (c & 0x3F) | 0x80; len = 4; } else { mp_raise_ValueError("chr() arg not in range(0x110000)"); } return mp_obj_new_str_via_qstr((char*)str, len); #else mp_int_t ord = mp_obj_get_int(o_in); if (0 <= ord && ord <= 0xff) { uint8_t str[1] = {ord}; return mp_obj_new_str_via_qstr((char*)str, 1); } else { mp_raise_ValueError("chr() arg not in range(256)"); } #endif } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr); STATIC mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) { mp_obj_t dir = mp_obj_new_list(0, NULL); if (n_args == 0) { // Make a list of names in the local namespace mp_obj_dict_t *dict = mp_locals_get(); for (size_t i = 0; i < dict->map.alloc; i++) { if (mp_map_slot_is_filled(&dict->map, i)) { mp_obj_list_append(dir, dict->map.table[i].key); } } } else { // n_args == 1 // Make a list of names in the given object // Implemented by probing all possible qstrs with mp_load_method_maybe size_t nqstr = QSTR_TOTAL(); for (size_t i = MP_QSTR_ + 1; i < nqstr; ++i) { mp_obj_t dest[2]; mp_load_method_protected(args[0], i, dest, false); if (dest[0] != MP_OBJ_NULL) { #if MICROPY_PY_ALL_SPECIAL_METHODS // Support for __dir__: see if we can dispatch to this special method // This relies on MP_QSTR__dir__ being first after MP_QSTR_ if (i == MP_QSTR___dir__ && dest[1] != MP_OBJ_NULL) { return mp_call_method_n_kw(0, 0, dest); } #endif mp_obj_list_append(dir, MP_OBJ_NEW_QSTR(i)); } } } return dir; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj, 0, 1, mp_builtin_dir); STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { return mp_binary_op(MP_BINARY_OP_DIVMOD, o1_in, o2_in); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj, mp_builtin_divmod); STATIC mp_obj_t mp_builtin_hash(mp_obj_t o_in) { // result is guaranteed to be a (small) int return mp_unary_op(MP_UNARY_OP_HASH, o_in); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash); STATIC mp_obj_t mp_builtin_hex(mp_obj_t o_in) { #if MICROPY_PY_BUILTINS_STR_OP_MODULO return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_x), o_in); #else mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_x_brace_close_), o_in }; return mp_obj_str_format(MP_ARRAY_SIZE(args), args, NULL); #endif } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hex_obj, mp_builtin_hex); #if MICROPY_PY_BUILTINS_INPUT #include "py/mphal.h" #include "lib/mp-readline/readline.h" // A port can define mp_hal_readline if they want to use a custom function here #ifndef mp_hal_readline #define mp_hal_readline readline #endif STATIC mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) { if (n_args == 1) { mp_obj_print(args[0], PRINT_STR); } vstr_t line; vstr_init(&line, 16); int ret = mp_hal_readline(&line, ""); if (ret == CHAR_CTRL_C) { nlr_raise(mp_obj_new_exception(&mp_type_KeyboardInterrupt)); } if (line.len == 0 && ret == CHAR_CTRL_D) { nlr_raise(mp_obj_new_exception(&mp_type_EOFError)); } return mp_obj_new_str_from_vstr(&mp_type_str, &line); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj, 0, 1, mp_builtin_input); #endif STATIC mp_obj_t mp_builtin_iter(mp_obj_t o_in) { return mp_getiter(o_in, NULL); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter); #if MICROPY_PY_BUILTINS_MIN_MAX STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs, mp_uint_t op) { mp_map_elem_t *key_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_key), MP_MAP_LOOKUP); mp_map_elem_t *default_elem; mp_obj_t key_fn = key_elem == NULL ? MP_OBJ_NULL : key_elem->value; if (n_args == 1) { // given an iterable mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(args[0], &iter_buf); mp_obj_t best_key = MP_OBJ_NULL; mp_obj_t best_obj = MP_OBJ_NULL; mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { mp_obj_t key = key_fn == MP_OBJ_NULL ? item : mp_call_function_1(key_fn, item); if (best_obj == MP_OBJ_NULL || (mp_binary_op(op, key, best_key) == mp_const_true)) { best_key = key; best_obj = item; } } if (best_obj == MP_OBJ_NULL) { default_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_default), MP_MAP_LOOKUP); if (default_elem != NULL) { best_obj = default_elem->value; } else { mp_raise_ValueError("arg is an empty sequence"); } } return best_obj; } else { // given many args mp_obj_t best_key = MP_OBJ_NULL; mp_obj_t best_obj = MP_OBJ_NULL; for (size_t i = 0; i < n_args; i++) { mp_obj_t key = key_fn == MP_OBJ_NULL ? args[i] : mp_call_function_1(key_fn, args[i]); if (best_obj == MP_OBJ_NULL || (mp_binary_op(op, key, best_key) == mp_const_true)) { best_key = key; best_obj = args[i]; } } return best_obj; } } STATIC mp_obj_t mp_builtin_max(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_builtin_min_max(n_args, args, kwargs, MP_BINARY_OP_MORE); } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_max_obj, 1, mp_builtin_max); STATIC mp_obj_t mp_builtin_min(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_builtin_min_max(n_args, args, kwargs, MP_BINARY_OP_LESS); } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_min_obj, 1, mp_builtin_min); #endif #if MICROPY_PY_BUILTINS_NEXT2 STATIC mp_obj_t mp_builtin_next(size_t n_args, const mp_obj_t *args) { if (n_args == 1) { mp_obj_t ret = mp_iternext_allow_raise(args[0]); if (ret == MP_OBJ_STOP_ITERATION) { nlr_raise(mp_obj_new_exception(&mp_type_StopIteration)); } else { return ret; } } else { mp_obj_t ret = mp_iternext(args[0]); return ret == MP_OBJ_STOP_ITERATION ? args[1] : ret; } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_next_obj, 1, 2, mp_builtin_next); #else STATIC mp_obj_t mp_builtin_next(mp_obj_t o) { mp_obj_t ret = mp_iternext_allow_raise(o); if (ret == MP_OBJ_STOP_ITERATION) { nlr_raise(mp_obj_new_exception(&mp_type_StopIteration)); } else { return ret; } } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next); #endif STATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) { #if MICROPY_PY_BUILTINS_STR_OP_MODULO return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_o), o_in); #else mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_o_brace_close_), o_in }; return mp_obj_str_format(MP_ARRAY_SIZE(args), args, NULL); #endif } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct); STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { size_t len; const byte *str = (const byte*)mp_obj_str_get_data(o_in, &len); #if MICROPY_PY_BUILTINS_STR_UNICODE if (mp_obj_is_str(o_in)) { len = utf8_charlen(str, len); if (len == 1) { return mp_obj_new_int(utf8_get_char(str)); } } else #endif { // a bytes object, or a str without unicode support (don't sign extend the char) if (len == 1) { return MP_OBJ_NEW_SMALL_INT(str[0]); } } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("ord expects a character"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", (int)len)); } } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord); STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) { switch (n_args) { case 2: return mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]); default: #if !MICROPY_PY_BUILTINS_POW3 mp_raise_msg(&mp_type_NotImplementedError, "3-arg pow() not supported"); #elif MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_MPZ return mp_binary_op(MP_BINARY_OP_MODULO, mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]), args[2]); #else return mp_obj_int_pow3(args[0], args[1], args[2]); #endif } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow); STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sep, ARG_end, ARG_file }; static const mp_arg_t allowed_args[] = { { MP_QSTR_sep, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__space_)} }, { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__0x0a_)} }, #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES { MP_QSTR_file, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_sys_stdout_obj)} }, #endif }; // parse args (a union is used to reduce the amount of C stack that is needed) union { mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; size_t len[2]; } u; mp_arg_parse_all(0, NULL, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, u.args); #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES mp_get_stream_raise(u.args[ARG_file].u_obj, MP_STREAM_OP_WRITE); mp_print_t print = {MP_OBJ_TO_PTR(u.args[ARG_file].u_obj), mp_stream_write_adaptor}; #endif // extract the objects first because we are going to use the other part of the union mp_obj_t sep = u.args[ARG_sep].u_obj; mp_obj_t end = u.args[ARG_end].u_obj; const char *sep_data = mp_obj_str_get_data(sep, &u.len[0]); const char *end_data = mp_obj_str_get_data(end, &u.len[1]); for (size_t i = 0; i < n_args; i++) { if (i > 0) { #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES mp_stream_write_adaptor(print.data, sep_data, u.len[0]); #else mp_print_strn(&mp_plat_print, sep_data, u.len[0], 0, 0, 0); #endif } #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES mp_obj_print_helper(&print, pos_args[i], PRINT_STR); #else mp_obj_print_helper(&mp_plat_print, pos_args[i], PRINT_STR); #endif } #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES mp_stream_write_adaptor(print.data, end_data, u.len[1]); #else mp_print_strn(&mp_plat_print, end_data, u.len[1], 0, 0, 0); #endif return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print); STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { if (o != mp_const_none) { mp_obj_print_helper(MP_PYTHON_PRINTER, o, PRINT_REPR); mp_print_str(MP_PYTHON_PRINTER, "\n"); #if MICROPY_CAN_OVERRIDE_BUILTINS // Set "_" special variable mp_obj_t dest[2] = {MP_OBJ_SENTINEL, o}; mp_type_module.attr(MP_OBJ_FROM_PTR(&mp_module_builtins), MP_QSTR__, dest); #endif } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print__); STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 16, &print); mp_obj_print_helper(&print, o_in, PRINT_REPR); return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { mp_obj_t o_in = args[0]; if (mp_obj_is_int(o_in)) { if (n_args <= 1) { return o_in; } #if !MICROPY_PY_BUILTINS_ROUND_INT mp_raise_NotImplementedError(NULL); #else mp_int_t num_dig = mp_obj_get_int(args[1]); if (num_dig >= 0) { return o_in; } mp_obj_t mult = mp_binary_op(MP_BINARY_OP_POWER, MP_OBJ_NEW_SMALL_INT(10), MP_OBJ_NEW_SMALL_INT(-num_dig)); mp_obj_t half_mult = mp_binary_op(MP_BINARY_OP_FLOOR_DIVIDE, mult, MP_OBJ_NEW_SMALL_INT(2)); mp_obj_t modulo = mp_binary_op(MP_BINARY_OP_MODULO, o_in, mult); mp_obj_t rounded = mp_binary_op(MP_BINARY_OP_SUBTRACT, o_in, modulo); if (mp_obj_is_true(mp_binary_op(MP_BINARY_OP_MORE, half_mult, modulo))) { return rounded; } else if (mp_obj_is_true(mp_binary_op(MP_BINARY_OP_MORE, modulo, half_mult))) { return mp_binary_op(MP_BINARY_OP_ADD, rounded, mult); } else { // round to even number mp_obj_t floor = mp_binary_op(MP_BINARY_OP_FLOOR_DIVIDE, o_in, mult); if (mp_obj_is_true(mp_binary_op(MP_BINARY_OP_AND, floor, MP_OBJ_NEW_SMALL_INT(1)))) { return mp_binary_op(MP_BINARY_OP_ADD, rounded, mult); } else { return rounded; } } #endif } #if MICROPY_PY_BUILTINS_FLOAT mp_float_t val = mp_obj_get_float(o_in); if (n_args > 1) { mp_int_t num_dig = mp_obj_get_int(args[1]); mp_float_t mult = MICROPY_FLOAT_C_FUN(pow)(10, num_dig); // TODO may lead to overflow mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val * mult) / mult; return mp_obj_new_float(rounded); } mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val); return mp_obj_new_int_from_float(rounded); #else mp_int_t r = mp_obj_get_int(o_in); return mp_obj_new_int(r); #endif } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj, 1, 2, mp_builtin_round); STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) { mp_obj_t value; switch (n_args) { case 1: value = MP_OBJ_NEW_SMALL_INT(0); break; default: value = args[1]; break; } mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(args[0], &iter_buf); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { value = mp_binary_op(MP_BINARY_OP_ADD, value, item); } return value; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum); STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { if (n_args > 1) { mp_raise_TypeError("must use keyword argument for key function"); } mp_obj_t self = mp_type_list.make_new(&mp_type_list, 1, 0, args); mp_obj_list_sort(1, &self, kwargs); return self; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted); // See mp_load_attr() if making any changes static inline mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval) { mp_obj_t dest[2]; // use load_method, raising or not raising exception ((defval == MP_OBJ_NULL) ? mp_load_method : mp_load_method_maybe)(base, attr, dest); if (dest[0] == MP_OBJ_NULL) { return defval; } else if (dest[1] == MP_OBJ_NULL) { // load_method returned just a normal attribute return dest[0]; } else { // load_method returned a method, so build a bound method object return mp_obj_new_bound_meth(dest[0], dest[1]); } } STATIC mp_obj_t mp_builtin_getattr(size_t n_args, const mp_obj_t *args) { mp_obj_t defval = MP_OBJ_NULL; if (n_args > 2) { defval = args[2]; } return mp_load_attr_default(args[0], mp_obj_str_get_qstr(args[1]), defval); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr); STATIC mp_obj_t mp_builtin_setattr(mp_obj_t base, mp_obj_t attr, mp_obj_t value) { mp_store_attr(base, mp_obj_str_get_qstr(attr), value); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj, mp_builtin_setattr); #if MICROPY_CPYTHON_COMPAT STATIC mp_obj_t mp_builtin_delattr(mp_obj_t base, mp_obj_t attr) { return mp_builtin_setattr(base, attr, MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj, mp_builtin_delattr); #endif STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) { qstr attr = mp_obj_str_get_qstr(attr_in); mp_obj_t dest[2]; mp_load_method_protected(object_in, attr, dest, false); return mp_obj_new_bool(dest[0] != MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj, mp_builtin_hasattr); STATIC mp_obj_t mp_builtin_globals(void) { return MP_OBJ_FROM_PTR(mp_globals_get()); } MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_globals_obj, mp_builtin_globals); STATIC mp_obj_t mp_builtin_locals(void) { return MP_OBJ_FROM_PTR(mp_locals_get()); } MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_builtin_locals); // These are defined in terms of MicroPython API functions right away MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_obj_id); MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_obj_len); STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_builtins) }, // built-in core functions { MP_ROM_QSTR(MP_QSTR___build_class__), MP_ROM_PTR(&mp_builtin___build_class___obj) }, { MP_ROM_QSTR(MP_QSTR___import__), MP_ROM_PTR(&mp_builtin___import___obj) }, { MP_ROM_QSTR(MP_QSTR___repl_print__), MP_ROM_PTR(&mp_builtin___repl_print___obj) }, // built-in types { MP_ROM_QSTR(MP_QSTR_bool), MP_ROM_PTR(&mp_type_bool) }, { MP_ROM_QSTR(MP_QSTR_bytes), MP_ROM_PTR(&mp_type_bytes) }, #if MICROPY_PY_BUILTINS_BYTEARRAY { MP_ROM_QSTR(MP_QSTR_bytearray), MP_ROM_PTR(&mp_type_bytearray) }, #endif #if MICROPY_PY_BUILTINS_COMPLEX { MP_ROM_QSTR(MP_QSTR_complex), MP_ROM_PTR(&mp_type_complex) }, #endif { MP_ROM_QSTR(MP_QSTR_dict), MP_ROM_PTR(&mp_type_dict) }, #if MICROPY_PY_BUILTINS_ENUMERATE { MP_ROM_QSTR(MP_QSTR_enumerate), MP_ROM_PTR(&mp_type_enumerate) }, #endif #if MICROPY_PY_BUILTINS_FILTER { MP_ROM_QSTR(MP_QSTR_filter), MP_ROM_PTR(&mp_type_filter) }, #endif #if MICROPY_PY_BUILTINS_FLOAT { MP_ROM_QSTR(MP_QSTR_float), MP_ROM_PTR(&mp_type_float) }, #endif #if MICROPY_PY_BUILTINS_SET && MICROPY_PY_BUILTINS_FROZENSET { MP_ROM_QSTR(MP_QSTR_frozenset), MP_ROM_PTR(&mp_type_frozenset) }, #endif { MP_ROM_QSTR(MP_QSTR_int), MP_ROM_PTR(&mp_type_int) }, { MP_ROM_QSTR(MP_QSTR_list), MP_ROM_PTR(&mp_type_list) }, { MP_ROM_QSTR(MP_QSTR_map), MP_ROM_PTR(&mp_type_map) }, #if MICROPY_PY_BUILTINS_MEMORYVIEW { MP_ROM_QSTR(MP_QSTR_memoryview), MP_ROM_PTR(&mp_type_memoryview) }, #endif { MP_ROM_QSTR(MP_QSTR_object), MP_ROM_PTR(&mp_type_object) }, #if MICROPY_PY_BUILTINS_PROPERTY { MP_ROM_QSTR(MP_QSTR_property), MP_ROM_PTR(&mp_type_property) }, #endif { MP_ROM_QSTR(MP_QSTR_range), MP_ROM_PTR(&mp_type_range) }, #if MICROPY_PY_BUILTINS_REVERSED { MP_ROM_QSTR(MP_QSTR_reversed), MP_ROM_PTR(&mp_type_reversed) }, #endif #if MICROPY_PY_BUILTINS_SET { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mp_type_set) }, #endif #if MICROPY_PY_BUILTINS_SLICE { MP_ROM_QSTR(MP_QSTR_slice), MP_ROM_PTR(&mp_type_slice) }, #endif { MP_ROM_QSTR(MP_QSTR_str), MP_ROM_PTR(&mp_type_str) }, { MP_ROM_QSTR(MP_QSTR_super), MP_ROM_PTR(&mp_type_super) }, { MP_ROM_QSTR(MP_QSTR_tuple), MP_ROM_PTR(&mp_type_tuple) }, { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&mp_type_type) }, { MP_ROM_QSTR(MP_QSTR_zip), MP_ROM_PTR(&mp_type_zip) }, { MP_ROM_QSTR(MP_QSTR_classmethod), MP_ROM_PTR(&mp_type_classmethod) }, { MP_ROM_QSTR(MP_QSTR_staticmethod), MP_ROM_PTR(&mp_type_staticmethod) }, // built-in objects { MP_ROM_QSTR(MP_QSTR_Ellipsis), MP_ROM_PTR(&mp_const_ellipsis_obj) }, #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED { MP_ROM_QSTR(MP_QSTR_NotImplemented), MP_ROM_PTR(&mp_const_notimplemented_obj) }, #endif // built-in user functions { MP_ROM_QSTR(MP_QSTR_abs), MP_ROM_PTR(&mp_builtin_abs_obj) }, { MP_ROM_QSTR(MP_QSTR_all), MP_ROM_PTR(&mp_builtin_all_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&mp_builtin_any_obj) }, { MP_ROM_QSTR(MP_QSTR_bin), MP_ROM_PTR(&mp_builtin_bin_obj) }, { MP_ROM_QSTR(MP_QSTR_callable), MP_ROM_PTR(&mp_builtin_callable_obj) }, #if MICROPY_PY_BUILTINS_COMPILE { MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mp_builtin_compile_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_chr), MP_ROM_PTR(&mp_builtin_chr_obj) }, #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_delattr), MP_ROM_PTR(&mp_builtin_delattr_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_dir), MP_ROM_PTR(&mp_builtin_dir_obj) }, { MP_ROM_QSTR(MP_QSTR_divmod), MP_ROM_PTR(&mp_builtin_divmod_obj) }, #if MICROPY_PY_BUILTINS_EVAL_EXEC { MP_ROM_QSTR(MP_QSTR_eval), MP_ROM_PTR(&mp_builtin_eval_obj) }, { MP_ROM_QSTR(MP_QSTR_exec), MP_ROM_PTR(&mp_builtin_exec_obj) }, #endif #if MICROPY_PY_BUILTINS_EXECFILE { MP_ROM_QSTR(MP_QSTR_execfile), MP_ROM_PTR(&mp_builtin_execfile_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_getattr), MP_ROM_PTR(&mp_builtin_getattr_obj) }, { MP_ROM_QSTR(MP_QSTR_setattr), MP_ROM_PTR(&mp_builtin_setattr_obj) }, { MP_ROM_QSTR(MP_QSTR_globals), MP_ROM_PTR(&mp_builtin_globals_obj) }, { MP_ROM_QSTR(MP_QSTR_hasattr), MP_ROM_PTR(&mp_builtin_hasattr_obj) }, { MP_ROM_QSTR(MP_QSTR_hash), MP_ROM_PTR(&mp_builtin_hash_obj) }, #if MICROPY_PY_BUILTINS_HELP { MP_ROM_QSTR(MP_QSTR_help), MP_ROM_PTR(&mp_builtin_help_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_hex), MP_ROM_PTR(&mp_builtin_hex_obj) }, { MP_ROM_QSTR(MP_QSTR_id), MP_ROM_PTR(&mp_builtin_id_obj) }, #if MICROPY_PY_BUILTINS_INPUT { MP_ROM_QSTR(MP_QSTR_input), MP_ROM_PTR(&mp_builtin_input_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_isinstance), MP_ROM_PTR(&mp_builtin_isinstance_obj) }, { MP_ROM_QSTR(MP_QSTR_issubclass), MP_ROM_PTR(&mp_builtin_issubclass_obj) }, { MP_ROM_QSTR(MP_QSTR_iter), MP_ROM_PTR(&mp_builtin_iter_obj) }, { MP_ROM_QSTR(MP_QSTR_len), MP_ROM_PTR(&mp_builtin_len_obj) }, { MP_ROM_QSTR(MP_QSTR_locals), MP_ROM_PTR(&mp_builtin_locals_obj) }, #if MICROPY_PY_BUILTINS_MIN_MAX { MP_ROM_QSTR(MP_QSTR_max), MP_ROM_PTR(&mp_builtin_max_obj) }, { MP_ROM_QSTR(MP_QSTR_min), MP_ROM_PTR(&mp_builtin_min_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_next), MP_ROM_PTR(&mp_builtin_next_obj) }, { MP_ROM_QSTR(MP_QSTR_oct), MP_ROM_PTR(&mp_builtin_oct_obj) }, { MP_ROM_QSTR(MP_QSTR_ord), MP_ROM_PTR(&mp_builtin_ord_obj) }, { MP_ROM_QSTR(MP_QSTR_pow), MP_ROM_PTR(&mp_builtin_pow_obj) }, { MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&mp_builtin_print_obj) }, { MP_ROM_QSTR(MP_QSTR_repr), MP_ROM_PTR(&mp_builtin_repr_obj) }, { MP_ROM_QSTR(MP_QSTR_round), MP_ROM_PTR(&mp_builtin_round_obj) }, { MP_ROM_QSTR(MP_QSTR_sorted), MP_ROM_PTR(&mp_builtin_sorted_obj) }, { MP_ROM_QSTR(MP_QSTR_sum), MP_ROM_PTR(&mp_builtin_sum_obj) }, // built-in exceptions { MP_ROM_QSTR(MP_QSTR_BaseException), MP_ROM_PTR(&mp_type_BaseException) }, { MP_ROM_QSTR(MP_QSTR_ArithmeticError), MP_ROM_PTR(&mp_type_ArithmeticError) }, { MP_ROM_QSTR(MP_QSTR_AssertionError), MP_ROM_PTR(&mp_type_AssertionError) }, { MP_ROM_QSTR(MP_QSTR_AttributeError), MP_ROM_PTR(&mp_type_AttributeError) }, { MP_ROM_QSTR(MP_QSTR_EOFError), MP_ROM_PTR(&mp_type_EOFError) }, { MP_ROM_QSTR(MP_QSTR_Exception), MP_ROM_PTR(&mp_type_Exception) }, { MP_ROM_QSTR(MP_QSTR_GeneratorExit), MP_ROM_PTR(&mp_type_GeneratorExit) }, { MP_ROM_QSTR(MP_QSTR_ImportError), MP_ROM_PTR(&mp_type_ImportError) }, { MP_ROM_QSTR(MP_QSTR_IndentationError), MP_ROM_PTR(&mp_type_IndentationError) }, { MP_ROM_QSTR(MP_QSTR_IndexError), MP_ROM_PTR(&mp_type_IndexError) }, { MP_ROM_QSTR(MP_QSTR_KeyboardInterrupt), MP_ROM_PTR(&mp_type_KeyboardInterrupt) }, { MP_ROM_QSTR(MP_QSTR_KeyError), MP_ROM_PTR(&mp_type_KeyError) }, { MP_ROM_QSTR(MP_QSTR_LookupError), MP_ROM_PTR(&mp_type_LookupError) }, { MP_ROM_QSTR(MP_QSTR_MemoryError), MP_ROM_PTR(&mp_type_MemoryError) }, { MP_ROM_QSTR(MP_QSTR_NameError), MP_ROM_PTR(&mp_type_NameError) }, { MP_ROM_QSTR(MP_QSTR_NotImplementedError), MP_ROM_PTR(&mp_type_NotImplementedError) }, { MP_ROM_QSTR(MP_QSTR_OSError), MP_ROM_PTR(&mp_type_OSError) }, { MP_ROM_QSTR(MP_QSTR_OverflowError), MP_ROM_PTR(&mp_type_OverflowError) }, { MP_ROM_QSTR(MP_QSTR_RuntimeError), MP_ROM_PTR(&mp_type_RuntimeError) }, #if MICROPY_PY_ASYNC_AWAIT { MP_ROM_QSTR(MP_QSTR_StopAsyncIteration), MP_ROM_PTR(&mp_type_StopAsyncIteration) }, #endif { MP_ROM_QSTR(MP_QSTR_StopIteration), MP_ROM_PTR(&mp_type_StopIteration) }, { MP_ROM_QSTR(MP_QSTR_SyntaxError), MP_ROM_PTR(&mp_type_SyntaxError) }, { MP_ROM_QSTR(MP_QSTR_SystemExit), MP_ROM_PTR(&mp_type_SystemExit) }, { MP_ROM_QSTR(MP_QSTR_TypeError), MP_ROM_PTR(&mp_type_TypeError) }, #if MICROPY_PY_BUILTINS_STR_UNICODE { MP_ROM_QSTR(MP_QSTR_UnicodeError), MP_ROM_PTR(&mp_type_UnicodeError) }, #endif { MP_ROM_QSTR(MP_QSTR_ValueError), MP_ROM_PTR(&mp_type_ValueError) }, #if MICROPY_EMIT_NATIVE { MP_ROM_QSTR(MP_QSTR_ViperTypeError), MP_ROM_PTR(&mp_type_ViperTypeError) }, #endif { MP_ROM_QSTR(MP_QSTR_ZeroDivisionError), MP_ROM_PTR(&mp_type_ZeroDivisionError) }, // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/ // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation // Extra builtins as defined by a port MICROPY_PORT_BUILTINS }; MP_DEFINE_CONST_DICT(mp_module_builtins_globals, mp_module_builtins_globals_table); const mp_obj_module_t mp_module_builtins = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_builtins_globals, }; micropython-1.12/py/modcmath.c000066400000000000000000000161161357706137100164170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_BUILTINS_COMPLEX && MICROPY_PY_CMATH #include // phase(z): returns the phase of the number z in the range (-pi, +pi] STATIC mp_obj_t mp_cmath_phase(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase); // polar(z): returns the polar form of z as a tuple STATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); mp_obj_t tuple[2] = { mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)), mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real)), }; return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar); // rect(r, phi): returns the complex number with modulus r and phase phi STATIC mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) { mp_float_t r = mp_obj_get_float(r_obj); mp_float_t phi = mp_obj_get_float(phi_obj); return mp_obj_new_complex(r * MICROPY_FLOAT_C_FUN(cos)(phi), r * MICROPY_FLOAT_C_FUN(sin)(phi)); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect); // exp(z): return the exponential of z STATIC mp_obj_t mp_cmath_exp(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); mp_float_t exp_real = MICROPY_FLOAT_C_FUN(exp)(real); return mp_obj_new_complex(exp_real * MICROPY_FLOAT_C_FUN(cos)(imag), exp_real * MICROPY_FLOAT_C_FUN(sin)(imag)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp); // log(z): return the natural logarithm of z, with branch cut along the negative real axis // TODO can take second argument, being the base STATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log)(real*real + imag*imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log); #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS // log10(z): return the base-10 logarithm of z, with branch cut along the negative real axis STATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log10)(real*real + imag*imag), 0.4342944819032518 * MICROPY_FLOAT_C_FUN(atan2)(imag, real)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10); #endif // sqrt(z): return the square-root of z STATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(pow)(real*real + imag*imag, 0.25); mp_float_t theta = 0.5 * MICROPY_FLOAT_C_FUN(atan2)(imag, real); return mp_obj_new_complex(sqrt_abs * MICROPY_FLOAT_C_FUN(cos)(theta), sqrt_abs * MICROPY_FLOAT_C_FUN(sin)(theta)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt); // cos(z): return the cosine of z STATIC mp_obj_t mp_cmath_cos(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), -MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos); // sin(z): return the sine of z STATIC mp_obj_t mp_cmath_sin(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sin_obj, mp_cmath_sin); STATIC const mp_rom_map_elem_t mp_module_cmath_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cmath) }, { MP_ROM_QSTR(MP_QSTR_e), mp_const_float_e }, { MP_ROM_QSTR(MP_QSTR_pi), mp_const_float_pi }, { MP_ROM_QSTR(MP_QSTR_phase), MP_ROM_PTR(&mp_cmath_phase_obj) }, { MP_ROM_QSTR(MP_QSTR_polar), MP_ROM_PTR(&mp_cmath_polar_obj) }, { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&mp_cmath_rect_obj) }, { MP_ROM_QSTR(MP_QSTR_exp), MP_ROM_PTR(&mp_cmath_exp_obj) }, { MP_ROM_QSTR(MP_QSTR_log), MP_ROM_PTR(&mp_cmath_log_obj) }, #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_log10), MP_ROM_PTR(&mp_cmath_log10_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_sqrt), MP_ROM_PTR(&mp_cmath_sqrt_obj) }, //{ MP_ROM_QSTR(MP_QSTR_acos), MP_ROM_PTR(&mp_cmath_acos_obj) }, //{ MP_ROM_QSTR(MP_QSTR_asin), MP_ROM_PTR(&mp_cmath_asin_obj) }, //{ MP_ROM_QSTR(MP_QSTR_atan), MP_ROM_PTR(&mp_cmath_atan_obj) }, { MP_ROM_QSTR(MP_QSTR_cos), MP_ROM_PTR(&mp_cmath_cos_obj) }, { MP_ROM_QSTR(MP_QSTR_sin), MP_ROM_PTR(&mp_cmath_sin_obj) }, //{ MP_ROM_QSTR(MP_QSTR_tan), MP_ROM_PTR(&mp_cmath_tan_obj) }, //{ MP_ROM_QSTR(MP_QSTR_acosh), MP_ROM_PTR(&mp_cmath_acosh_obj) }, //{ MP_ROM_QSTR(MP_QSTR_asinh), MP_ROM_PTR(&mp_cmath_asinh_obj) }, //{ MP_ROM_QSTR(MP_QSTR_atanh), MP_ROM_PTR(&mp_cmath_atanh_obj) }, //{ MP_ROM_QSTR(MP_QSTR_cosh), MP_ROM_PTR(&mp_cmath_cosh_obj) }, //{ MP_ROM_QSTR(MP_QSTR_sinh), MP_ROM_PTR(&mp_cmath_sinh_obj) }, //{ MP_ROM_QSTR(MP_QSTR_tanh), MP_ROM_PTR(&mp_cmath_tanh_obj) }, //{ MP_ROM_QSTR(MP_QSTR_isfinite), MP_ROM_PTR(&mp_cmath_isfinite_obj) }, //{ MP_ROM_QSTR(MP_QSTR_isinf), MP_ROM_PTR(&mp_cmath_isinf_obj) }, //{ MP_ROM_QSTR(MP_QSTR_isnan), MP_ROM_PTR(&mp_cmath_isnan_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_cmath_globals, mp_module_cmath_globals_table); const mp_obj_module_t mp_module_cmath = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_cmath_globals, }; #endif // MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_CMATH micropython-1.12/py/modcollections.c000066400000000000000000000037561357706137100176470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" #if MICROPY_PY_COLLECTIONS STATIC const mp_rom_map_elem_t mp_module_collections_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ucollections) }, #if MICROPY_PY_COLLECTIONS_DEQUE { MP_ROM_QSTR(MP_QSTR_deque), MP_ROM_PTR(&mp_type_deque) }, #endif { MP_ROM_QSTR(MP_QSTR_namedtuple), MP_ROM_PTR(&mp_namedtuple_obj) }, #if MICROPY_PY_COLLECTIONS_ORDEREDDICT { MP_ROM_QSTR(MP_QSTR_OrderedDict), MP_ROM_PTR(&mp_type_ordereddict) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_collections_globals, mp_module_collections_globals_table); const mp_obj_module_t mp_module_collections = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_collections_globals, }; #endif // MICROPY_PY_COLLECTIONS micropython-1.12/py/modgc.c000066400000000000000000000102271357706137100157110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #include "py/obj.h" #include "py/gc.h" #if MICROPY_PY_GC && MICROPY_ENABLE_GC // collect(): run a garbage collection STATIC mp_obj_t py_gc_collect(void) { gc_collect(); #if MICROPY_PY_GC_COLLECT_RETVAL return MP_OBJ_NEW_SMALL_INT(MP_STATE_MEM(gc_collected)); #else return mp_const_none; #endif } MP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect); // disable(): disable the garbage collector STATIC mp_obj_t gc_disable(void) { MP_STATE_MEM(gc_auto_collect_enabled) = 0; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable); // enable(): enable the garbage collector STATIC mp_obj_t gc_enable(void) { MP_STATE_MEM(gc_auto_collect_enabled) = 1; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable); STATIC mp_obj_t gc_isenabled(void) { return mp_obj_new_bool(MP_STATE_MEM(gc_auto_collect_enabled)); } MP_DEFINE_CONST_FUN_OBJ_0(gc_isenabled_obj, gc_isenabled); // mem_free(): return the number of bytes of available heap RAM STATIC mp_obj_t gc_mem_free(void) { gc_info_t info; gc_info(&info); return MP_OBJ_NEW_SMALL_INT(info.free); } MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free); // mem_alloc(): return the number of bytes of heap RAM that are allocated STATIC mp_obj_t gc_mem_alloc(void) { gc_info_t info; gc_info(&info); return MP_OBJ_NEW_SMALL_INT(info.used); } MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_alloc_obj, gc_mem_alloc); #if MICROPY_GC_ALLOC_THRESHOLD STATIC mp_obj_t gc_threshold(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { if (MP_STATE_MEM(gc_alloc_threshold) == (size_t)-1) { return MP_OBJ_NEW_SMALL_INT(-1); } return mp_obj_new_int(MP_STATE_MEM(gc_alloc_threshold) * MICROPY_BYTES_PER_GC_BLOCK); } mp_int_t val = mp_obj_get_int(args[0]); if (val < 0) { MP_STATE_MEM(gc_alloc_threshold) = (size_t)-1; } else { MP_STATE_MEM(gc_alloc_threshold) = val / MICROPY_BYTES_PER_GC_BLOCK; } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gc_threshold_obj, 0, 1, gc_threshold); #endif STATIC const mp_rom_map_elem_t mp_module_gc_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gc) }, { MP_ROM_QSTR(MP_QSTR_collect), MP_ROM_PTR(&gc_collect_obj) }, { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&gc_disable_obj) }, { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&gc_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_isenabled), MP_ROM_PTR(&gc_isenabled_obj) }, { MP_ROM_QSTR(MP_QSTR_mem_free), MP_ROM_PTR(&gc_mem_free_obj) }, { MP_ROM_QSTR(MP_QSTR_mem_alloc), MP_ROM_PTR(&gc_mem_alloc_obj) }, #if MICROPY_GC_ALLOC_THRESHOLD { MP_ROM_QSTR(MP_QSTR_threshold), MP_ROM_PTR(&gc_threshold_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_gc_globals, mp_module_gc_globals_table); const mp_obj_module_t mp_module_gc = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_gc_globals, }; #endif micropython-1.12/py/modio.c000066400000000000000000000226621357706137100157350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/builtin.h" #include "py/stream.h" #include "py/binary.h" #include "py/objarray.h" #include "py/objstringio.h" #include "py/frozenmod.h" #if MICROPY_PY_IO extern const mp_obj_type_t mp_type_fileio; extern const mp_obj_type_t mp_type_textio; #if MICROPY_PY_IO_IOBASE STATIC const mp_obj_type_t mp_type_iobase; STATIC const mp_obj_base_t iobase_singleton = {&mp_type_iobase}; STATIC mp_obj_t iobase_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type; (void)n_args; (void)n_kw; (void)args; return MP_OBJ_FROM_PTR(&iobase_singleton); } STATIC mp_uint_t iobase_read_write(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode, qstr qst) { mp_obj_t dest[3]; mp_load_method(obj, qst, dest); mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, size, buf}; dest[2] = MP_OBJ_FROM_PTR(&ar); mp_obj_t ret = mp_call_method_n_kw(1, 0, dest); if (ret == mp_const_none) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } else { return mp_obj_get_int(ret); } } STATIC mp_uint_t iobase_read(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) { return iobase_read_write(obj, buf, size, errcode, MP_QSTR_readinto); } STATIC mp_uint_t iobase_write(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode) { return iobase_read_write(obj, (void*)buf, size, errcode, MP_QSTR_write); } STATIC mp_uint_t iobase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_t dest[4]; mp_load_method(obj, MP_QSTR_ioctl, dest); dest[2] = mp_obj_new_int_from_uint(request); dest[3] = mp_obj_new_int_from_uint(arg); mp_int_t ret = mp_obj_get_int(mp_call_method_n_kw(2, 0, dest)); if (ret >= 0) { return ret; } else { *errcode = -ret; return MP_STREAM_ERROR; } } STATIC const mp_stream_p_t iobase_p = { .read = iobase_read, .write = iobase_write, .ioctl = iobase_ioctl, }; STATIC const mp_obj_type_t mp_type_iobase = { { &mp_type_type }, .name = MP_QSTR_IOBase, .make_new = iobase_make_new, .protocol = &iobase_p, }; #endif // MICROPY_PY_IO_IOBASE #if MICROPY_PY_IO_BUFFEREDWRITER typedef struct _mp_obj_bufwriter_t { mp_obj_base_t base; mp_obj_t stream; size_t alloc; size_t len; byte buf[0]; } mp_obj_bufwriter_t; STATIC mp_obj_t bufwriter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 2, false); size_t alloc = mp_obj_get_int(args[1]); mp_obj_bufwriter_t *o = m_new_obj_var(mp_obj_bufwriter_t, byte, alloc); o->base.type = type; o->stream = args[0]; o->alloc = alloc; o->len = 0; return o; } STATIC mp_uint_t bufwriter_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_bufwriter_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t org_size = size; while (size > 0) { mp_uint_t rem = self->alloc - self->len; if (size < rem) { memcpy(self->buf + self->len, buf, size); self->len += size; return org_size; } // Buffer flushing policy here is to flush entire buffer all the time. // This allows e.g. to have a block device as backing storage and write // entire block to it. memcpy below is not ideal and could be optimized // in some cases. But the way it is now it at least ensures that buffer // is word-aligned, to guard against obscure cases when it matters, e.g. // https://github.com/micropython/micropython/issues/1863 memcpy(self->buf + self->len, buf, rem); buf = (byte*)buf + rem; size -= rem; mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->alloc, errcode); (void)out_sz; if (*errcode != 0) { return MP_STREAM_ERROR; } // TODO: try to recover from a case of non-blocking stream, e.g. move // remaining chunk to the beginning of buffer. assert(out_sz == self->alloc); self->len = 0; } return org_size; } STATIC mp_obj_t bufwriter_flush(mp_obj_t self_in) { mp_obj_bufwriter_t *self = MP_OBJ_TO_PTR(self_in); if (self->len != 0) { int err; mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->len, &err); (void)out_sz; // TODO: try to recover from a case of non-blocking stream, e.g. move // remaining chunk to the beginning of buffer. assert(out_sz == self->len); self->len = 0; if (err != 0) { mp_raise_OSError(err); } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bufwriter_flush_obj, bufwriter_flush); STATIC const mp_rom_map_elem_t bufwriter_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&bufwriter_flush_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bufwriter_locals_dict, bufwriter_locals_dict_table); STATIC const mp_stream_p_t bufwriter_stream_p = { .write = bufwriter_write, }; STATIC const mp_obj_type_t bufwriter_type = { { &mp_type_type }, .name = MP_QSTR_BufferedWriter, .make_new = bufwriter_make_new, .protocol = &bufwriter_stream_p, .locals_dict = (mp_obj_dict_t*)&bufwriter_locals_dict, }; #endif // MICROPY_PY_IO_BUFFEREDWRITER #if MICROPY_PY_IO_RESOURCE_STREAM STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) { VSTR_FIXED(path_buf, MICROPY_ALLOC_PATH_MAX); size_t len; // As an extension to pkg_resources.resource_stream(), we support // package parameter being None, the path_in is interpreted as a // raw path. if (package_in != mp_const_none) { // Pass "True" as sentinel value in fromlist to force returning of leaf module mp_obj_t pkg = mp_import_name(mp_obj_str_get_qstr(package_in), mp_const_true, MP_OBJ_NEW_SMALL_INT(0)); mp_obj_t dest[2]; mp_load_method_maybe(pkg, MP_QSTR___path__, dest); if (dest[0] == MP_OBJ_NULL) { mp_raise_TypeError(NULL); } const char *path = mp_obj_str_get_data(dest[0], &len); vstr_add_strn(&path_buf, path, len); vstr_add_byte(&path_buf, '/'); } const char *path = mp_obj_str_get_data(path_in, &len); vstr_add_strn(&path_buf, path, len); len = path_buf.len; const char *data = mp_find_frozen_str(path_buf.buf, &len); if (data != NULL) { mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t); o->base.type = &mp_type_bytesio; o->vstr = m_new_obj(vstr_t); vstr_init_fixed_buf(o->vstr, len + 1, (char*)data); o->vstr->len = len; o->pos = 0; return MP_OBJ_FROM_PTR(o); } mp_obj_t path_out = mp_obj_new_str(path_buf.buf, path_buf.len); return mp_builtin_open(1, &path_out, (mp_map_t*)&mp_const_empty_map); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(resource_stream_obj, resource_stream); #endif STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uio) }, // Note: mp_builtin_open_obj should be defined by port, it's not // part of the core. { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, #if MICROPY_PY_IO_IOBASE { MP_ROM_QSTR(MP_QSTR_IOBase), MP_ROM_PTR(&mp_type_iobase) }, #endif #if MICROPY_PY_IO_RESOURCE_STREAM { MP_ROM_QSTR(MP_QSTR_resource_stream), MP_ROM_PTR(&resource_stream_obj) }, #endif #if MICROPY_PY_IO_FILEIO { MP_ROM_QSTR(MP_QSTR_FileIO), MP_ROM_PTR(&mp_type_fileio) }, #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_TextIOWrapper), MP_ROM_PTR(&mp_type_textio) }, #endif #endif { MP_ROM_QSTR(MP_QSTR_StringIO), MP_ROM_PTR(&mp_type_stringio) }, #if MICROPY_PY_IO_BYTESIO { MP_ROM_QSTR(MP_QSTR_BytesIO), MP_ROM_PTR(&mp_type_bytesio) }, #endif #if MICROPY_PY_IO_BUFFEREDWRITER { MP_ROM_QSTR(MP_QSTR_BufferedWriter), MP_ROM_PTR(&bufwriter_type) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_io_globals, mp_module_io_globals_table); const mp_obj_module_t mp_module_io = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_io_globals, }; #endif micropython-1.12/py/modmath.c000066400000000000000000000355151357706137100162600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH #include // M_PI is not part of the math.h standard and may not be defined // And by defining our own we can ensure it uses the correct const format. #define MP_PI MICROPY_FLOAT_CONST(3.14159265358979323846) STATIC NORETURN void math_error(void) { mp_raise_ValueError("math domain error"); } STATIC mp_obj_t math_generic_1(mp_obj_t x_obj, mp_float_t (*f)(mp_float_t)) { mp_float_t x = mp_obj_get_float(x_obj); mp_float_t ans = f(x); if ((isnan(ans) && !isnan(x)) || (isinf(ans) && !isinf(x))) { math_error(); } return mp_obj_new_float(ans); } STATIC mp_obj_t math_generic_2(mp_obj_t x_obj, mp_obj_t y_obj, mp_float_t (*f)(mp_float_t, mp_float_t)) { mp_float_t x = mp_obj_get_float(x_obj); mp_float_t y = mp_obj_get_float(y_obj); mp_float_t ans = f(x, y); if ((isnan(ans) && !isnan(x) && !isnan(y)) || (isinf(ans) && !isinf(x))) { math_error(); } return mp_obj_new_float(ans); } #define MATH_FUN_1(py_name, c_name) \ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { \ return math_generic_1(x_obj, MICROPY_FLOAT_C_FUN(c_name)); \ } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); #define MATH_FUN_1_TO_BOOL(py_name, c_name) \ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_bool(c_name(mp_obj_get_float(x_obj))); } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); #define MATH_FUN_1_TO_INT(py_name, c_name) \ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int_from_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); #define MATH_FUN_2(py_name, c_name) \ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \ return math_generic_2(x_obj, y_obj, MICROPY_FLOAT_C_FUN(c_name)); \ } \ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name); #define MATH_FUN_2_FLT_INT(py_name, c_name) \ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \ return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_int(y_obj))); \ } \ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name); #if MP_NEED_LOG2 #undef log2 #undef log2f // 1.442695040888963407354163704 is 1/_M_LN2 mp_float_t MICROPY_FLOAT_C_FUN(log2)(mp_float_t x) { return MICROPY_FLOAT_C_FUN(log)(x) * MICROPY_FLOAT_CONST(1.442695040888963407354163704); } #endif // sqrt(x): returns the square root of x MATH_FUN_1(sqrt, sqrt) // pow(x, y): returns x to the power of y MATH_FUN_2(pow, pow) // exp(x) MATH_FUN_1(exp, exp) #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS // expm1(x) MATH_FUN_1(expm1, expm1) // log2(x) MATH_FUN_1(log2, log2) // log10(x) MATH_FUN_1(log10, log10) // cosh(x) MATH_FUN_1(cosh, cosh) // sinh(x) MATH_FUN_1(sinh, sinh) // tanh(x) MATH_FUN_1(tanh, tanh) // acosh(x) MATH_FUN_1(acosh, acosh) // asinh(x) MATH_FUN_1(asinh, asinh) // atanh(x) MATH_FUN_1(atanh, atanh) #endif // cos(x) MATH_FUN_1(cos, cos) // sin(x) MATH_FUN_1(sin, sin) // tan(x) MATH_FUN_1(tan, tan) // acos(x) MATH_FUN_1(acos, acos) // asin(x) MATH_FUN_1(asin, asin) // atan(x) MATH_FUN_1(atan, atan) // atan2(y, x) MATH_FUN_2(atan2, atan2) // ceil(x) MATH_FUN_1_TO_INT(ceil, ceil) // copysign(x, y) STATIC mp_float_t MICROPY_FLOAT_C_FUN(copysign_func)(mp_float_t x, mp_float_t y) { return MICROPY_FLOAT_C_FUN(copysign)(x, y); } MATH_FUN_2(copysign, copysign_func) // fabs(x) STATIC mp_float_t MICROPY_FLOAT_C_FUN(fabs_func)(mp_float_t x) { return MICROPY_FLOAT_C_FUN(fabs)(x); } MATH_FUN_1(fabs, fabs_func) // floor(x) MATH_FUN_1_TO_INT(floor, floor) //TODO: delegate to x.__floor__() if x is not a float // fmod(x, y) MATH_FUN_2(fmod, fmod) // isfinite(x) MATH_FUN_1_TO_BOOL(isfinite, isfinite) // isinf(x) MATH_FUN_1_TO_BOOL(isinf, isinf) // isnan(x) MATH_FUN_1_TO_BOOL(isnan, isnan) // trunc(x) MATH_FUN_1_TO_INT(trunc, trunc) // ldexp(x, exp) MATH_FUN_2_FLT_INT(ldexp, ldexp) #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS // erf(x): return the error function of x MATH_FUN_1(erf, erf) // erfc(x): return the complementary error function of x MATH_FUN_1(erfc, erfc) // gamma(x): return the gamma function of x MATH_FUN_1(gamma, tgamma) // lgamma(x): return the natural logarithm of the gamma function of x MATH_FUN_1(lgamma, lgamma) #endif //TODO: fsum #if MICROPY_PY_MATH_ISCLOSE STATIC mp_obj_t mp_math_isclose(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_a, ARG_b, ARG_rel_tol, ARG_abs_tol }; static const mp_arg_t allowed_args[] = { {MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ}, {MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ}, {MP_QSTR_rel_tol, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, {MP_QSTR_abs_tol, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(0)}}, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); const mp_float_t a = mp_obj_get_float(args[ARG_a].u_obj); const mp_float_t b = mp_obj_get_float(args[ARG_b].u_obj); const mp_float_t rel_tol = args[ARG_rel_tol].u_obj == MP_OBJ_NULL ? (mp_float_t)1e-9 : mp_obj_get_float(args[ARG_rel_tol].u_obj); const mp_float_t abs_tol = mp_obj_get_float(args[ARG_abs_tol].u_obj); if (rel_tol < (mp_float_t)0.0 || abs_tol < (mp_float_t)0.0) { math_error(); } if (a == b) { return mp_const_true; } const mp_float_t difference = MICROPY_FLOAT_C_FUN(fabs)(a - b); if (isinf(difference)) { // Either a or b is inf return mp_const_false; } if ((difference <= abs_tol) || (difference <= MICROPY_FLOAT_C_FUN(fabs)(rel_tol * a)) || (difference <= MICROPY_FLOAT_C_FUN(fabs)(rel_tol * b))) { return mp_const_true; } return mp_const_false; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_math_isclose_obj, 2, mp_math_isclose); #endif // Function that takes a variable number of arguments // log(x[, base]) STATIC mp_obj_t mp_math_log(size_t n_args, const mp_obj_t *args) { mp_float_t x = mp_obj_get_float(args[0]); if (x <= (mp_float_t)0.0) { math_error(); } mp_float_t l = MICROPY_FLOAT_C_FUN(log)(x); if (n_args == 1) { return mp_obj_new_float(l); } else { mp_float_t base = mp_obj_get_float(args[1]); if (base <= (mp_float_t)0.0) { math_error(); } else if (base == (mp_float_t)1.0) { mp_raise_msg(&mp_type_ZeroDivisionError, "divide by zero"); } return mp_obj_new_float(l / MICROPY_FLOAT_C_FUN(log)(base)); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_math_log_obj, 1, 2, mp_math_log); // Functions that return a tuple // frexp(x): converts a floating-point number to fractional and integral components STATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) { int int_exponent = 0; mp_float_t significand = MICROPY_FLOAT_C_FUN(frexp)(mp_obj_get_float(x_obj), &int_exponent); mp_obj_t tuple[2]; tuple[0] = mp_obj_new_float(significand); tuple[1] = mp_obj_new_int(int_exponent); return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_frexp_obj, mp_math_frexp); // modf(x) STATIC mp_obj_t mp_math_modf(mp_obj_t x_obj) { mp_float_t int_part = 0.0; mp_float_t fractional_part = MICROPY_FLOAT_C_FUN(modf)(mp_obj_get_float(x_obj), &int_part); mp_obj_t tuple[2]; tuple[0] = mp_obj_new_float(fractional_part); tuple[1] = mp_obj_new_float(int_part); return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf); // Angular conversions // radians(x) STATIC mp_obj_t mp_math_radians(mp_obj_t x_obj) { return mp_obj_new_float(mp_obj_get_float(x_obj) * (MP_PI / MICROPY_FLOAT_CONST(180.0))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians); // degrees(x) STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) { return mp_obj_new_float(mp_obj_get_float(x_obj) * (MICROPY_FLOAT_CONST(180.0) / MP_PI)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees); #if MICROPY_PY_MATH_FACTORIAL #if MICROPY_OPT_MATH_FACTORIAL // factorial(x): slightly efficient recursive implementation STATIC mp_obj_t mp_math_factorial_inner(mp_uint_t start, mp_uint_t end) { if (start == end) { return mp_obj_new_int(start); } else if (end - start == 1) { return mp_binary_op(MP_BINARY_OP_MULTIPLY, MP_OBJ_NEW_SMALL_INT(start), MP_OBJ_NEW_SMALL_INT(end)); } else if (end - start == 2) { mp_obj_t left = MP_OBJ_NEW_SMALL_INT(start); mp_obj_t middle = MP_OBJ_NEW_SMALL_INT(start + 1); mp_obj_t right = MP_OBJ_NEW_SMALL_INT(end); mp_obj_t tmp = mp_binary_op(MP_BINARY_OP_MULTIPLY, left, middle); return mp_binary_op(MP_BINARY_OP_MULTIPLY, tmp, right); } else { mp_uint_t middle = start + ((end - start) >> 1); mp_obj_t left = mp_math_factorial_inner(start, middle); mp_obj_t right = mp_math_factorial_inner(middle + 1, end); return mp_binary_op(MP_BINARY_OP_MULTIPLY, left, right); } } STATIC mp_obj_t mp_math_factorial(mp_obj_t x_obj) { mp_int_t max = mp_obj_get_int(x_obj); if (max < 0) { mp_raise_msg(&mp_type_ValueError, "negative factorial"); } else if (max == 0) { return MP_OBJ_NEW_SMALL_INT(1); } return mp_math_factorial_inner(1, max); } #else // factorial(x): squared difference implementation // based on http://www.luschny.de/math/factorial/index.html STATIC mp_obj_t mp_math_factorial(mp_obj_t x_obj) { mp_int_t max = mp_obj_get_int(x_obj); if (max < 0) { mp_raise_msg(&mp_type_ValueError, "negative factorial"); } else if (max <= 1) { return MP_OBJ_NEW_SMALL_INT(1); } mp_int_t h = max >> 1; mp_int_t q = h * h; mp_int_t r = q << 1; if (max & 1) { r *= max; } mp_obj_t prod = MP_OBJ_NEW_SMALL_INT(r); for (mp_int_t num = 1; num < max - 2; num += 2) { q -= num; prod = mp_binary_op(MP_BINARY_OP_MULTIPLY, prod, MP_OBJ_NEW_SMALL_INT(q)); } return prod; } #endif STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_factorial_obj, mp_math_factorial); #endif STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_math) }, { MP_ROM_QSTR(MP_QSTR_e), mp_const_float_e }, { MP_ROM_QSTR(MP_QSTR_pi), mp_const_float_pi }, { MP_ROM_QSTR(MP_QSTR_sqrt), MP_ROM_PTR(&mp_math_sqrt_obj) }, { MP_ROM_QSTR(MP_QSTR_pow), MP_ROM_PTR(&mp_math_pow_obj) }, { MP_ROM_QSTR(MP_QSTR_exp), MP_ROM_PTR(&mp_math_exp_obj) }, #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_expm1), MP_ROM_PTR(&mp_math_expm1_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_log), MP_ROM_PTR(&mp_math_log_obj) }, #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_log2), MP_ROM_PTR(&mp_math_log2_obj) }, { MP_ROM_QSTR(MP_QSTR_log10), MP_ROM_PTR(&mp_math_log10_obj) }, { MP_ROM_QSTR(MP_QSTR_cosh), MP_ROM_PTR(&mp_math_cosh_obj) }, { MP_ROM_QSTR(MP_QSTR_sinh), MP_ROM_PTR(&mp_math_sinh_obj) }, { MP_ROM_QSTR(MP_QSTR_tanh), MP_ROM_PTR(&mp_math_tanh_obj) }, { MP_ROM_QSTR(MP_QSTR_acosh), MP_ROM_PTR(&mp_math_acosh_obj) }, { MP_ROM_QSTR(MP_QSTR_asinh), MP_ROM_PTR(&mp_math_asinh_obj) }, { MP_ROM_QSTR(MP_QSTR_atanh), MP_ROM_PTR(&mp_math_atanh_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_cos), MP_ROM_PTR(&mp_math_cos_obj) }, { MP_ROM_QSTR(MP_QSTR_sin), MP_ROM_PTR(&mp_math_sin_obj) }, { MP_ROM_QSTR(MP_QSTR_tan), MP_ROM_PTR(&mp_math_tan_obj) }, { MP_ROM_QSTR(MP_QSTR_acos), MP_ROM_PTR(&mp_math_acos_obj) }, { MP_ROM_QSTR(MP_QSTR_asin), MP_ROM_PTR(&mp_math_asin_obj) }, { MP_ROM_QSTR(MP_QSTR_atan), MP_ROM_PTR(&mp_math_atan_obj) }, { MP_ROM_QSTR(MP_QSTR_atan2), MP_ROM_PTR(&mp_math_atan2_obj) }, { MP_ROM_QSTR(MP_QSTR_ceil), MP_ROM_PTR(&mp_math_ceil_obj) }, { MP_ROM_QSTR(MP_QSTR_copysign), MP_ROM_PTR(&mp_math_copysign_obj) }, { MP_ROM_QSTR(MP_QSTR_fabs), MP_ROM_PTR(&mp_math_fabs_obj) }, { MP_ROM_QSTR(MP_QSTR_floor), MP_ROM_PTR(&mp_math_floor_obj) }, { MP_ROM_QSTR(MP_QSTR_fmod), MP_ROM_PTR(&mp_math_fmod_obj) }, { MP_ROM_QSTR(MP_QSTR_frexp), MP_ROM_PTR(&mp_math_frexp_obj) }, { MP_ROM_QSTR(MP_QSTR_ldexp), MP_ROM_PTR(&mp_math_ldexp_obj) }, { MP_ROM_QSTR(MP_QSTR_modf), MP_ROM_PTR(&mp_math_modf_obj) }, { MP_ROM_QSTR(MP_QSTR_isfinite), MP_ROM_PTR(&mp_math_isfinite_obj) }, { MP_ROM_QSTR(MP_QSTR_isinf), MP_ROM_PTR(&mp_math_isinf_obj) }, { MP_ROM_QSTR(MP_QSTR_isnan), MP_ROM_PTR(&mp_math_isnan_obj) }, #if MICROPY_PY_MATH_ISCLOSE { MP_ROM_QSTR(MP_QSTR_isclose), MP_ROM_PTR(&mp_math_isclose_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_trunc), MP_ROM_PTR(&mp_math_trunc_obj) }, { MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&mp_math_radians_obj) }, { MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&mp_math_degrees_obj) }, #if MICROPY_PY_MATH_FACTORIAL { MP_ROM_QSTR(MP_QSTR_factorial), MP_ROM_PTR(&mp_math_factorial_obj) }, #endif #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_erf), MP_ROM_PTR(&mp_math_erf_obj) }, { MP_ROM_QSTR(MP_QSTR_erfc), MP_ROM_PTR(&mp_math_erfc_obj) }, { MP_ROM_QSTR(MP_QSTR_gamma), MP_ROM_PTR(&mp_math_gamma_obj) }, { MP_ROM_QSTR(MP_QSTR_lgamma), MP_ROM_PTR(&mp_math_lgamma_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_math_globals, mp_module_math_globals_table); const mp_obj_module_t mp_module_math = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_math_globals, }; #endif // MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH micropython-1.12/py/modmicropython.c000066400000000000000000000172701357706137100177000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/builtin.h" #include "py/stackctrl.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" // Various builtins specific to MicroPython runtime, // living in micropython module #if MICROPY_ENABLE_COMPILER STATIC mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return MP_OBJ_NEW_SMALL_INT(MP_STATE_VM(mp_optimise_value)); } else { MP_STATE_VM(mp_optimise_value) = mp_obj_get_int(args[0]); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_opt_level_obj, 0, 1, mp_micropython_opt_level); #endif #if MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_MEM_STATS STATIC mp_obj_t mp_micropython_mem_total(void) { return MP_OBJ_NEW_SMALL_INT(m_get_total_bytes_allocated()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total); STATIC mp_obj_t mp_micropython_mem_current(void) { return MP_OBJ_NEW_SMALL_INT(m_get_current_bytes_allocated()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_current_obj, mp_micropython_mem_current); STATIC mp_obj_t mp_micropython_mem_peak(void) { return MP_OBJ_NEW_SMALL_INT(m_get_peak_bytes_allocated()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_peak_obj, mp_micropython_mem_peak); #endif mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args) { (void)args; #if MICROPY_MEM_STATS mp_printf(&mp_plat_print, "mem: total=" UINT_FMT ", current=" UINT_FMT ", peak=" UINT_FMT "\n", (mp_uint_t)m_get_total_bytes_allocated(), (mp_uint_t)m_get_current_bytes_allocated(), (mp_uint_t)m_get_peak_bytes_allocated()); #endif #if MICROPY_STACK_CHECK mp_printf(&mp_plat_print, "stack: " UINT_FMT " out of " UINT_FMT "\n", mp_stack_usage(), (mp_uint_t)MP_STATE_THREAD(stack_limit)); #else mp_printf(&mp_plat_print, "stack: " UINT_FMT "\n", mp_stack_usage()); #endif #if MICROPY_ENABLE_GC gc_dump_info(); if (n_args == 1) { // arg given means dump gc allocation table gc_dump_alloc_table(); } #else (void)n_args; #endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_mem_info_obj, 0, 1, mp_micropython_mem_info); STATIC mp_obj_t mp_micropython_qstr_info(size_t n_args, const mp_obj_t *args) { (void)args; size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); mp_printf(&mp_plat_print, "qstr pool: n_pool=%u, n_qstr=%u, n_str_data_bytes=%u, n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); if (n_args == 1) { // arg given means dump qstr data qstr_dump_data(); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_qstr_info_obj, 0, 1, mp_micropython_qstr_info); #endif // MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_PY_MICROPYTHON_STACK_USE STATIC mp_obj_t mp_micropython_stack_use(void) { return MP_OBJ_NEW_SMALL_INT(mp_stack_usage()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_stack_use_obj, mp_micropython_stack_use); #endif #if MICROPY_ENABLE_PYSTACK STATIC mp_obj_t mp_micropython_pystack_use(void) { return MP_OBJ_NEW_SMALL_INT(mp_pystack_usage()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_pystack_use_obj, mp_micropython_pystack_use); #endif #if MICROPY_ENABLE_GC STATIC mp_obj_t mp_micropython_heap_lock(void) { gc_lock(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_lock_obj, mp_micropython_heap_lock); STATIC mp_obj_t mp_micropython_heap_unlock(void) { gc_unlock(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_unlock_obj, mp_micropython_heap_unlock); #endif #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0) STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_emergency_exception_buf); #endif #if MICROPY_KBD_EXCEPTION STATIC mp_obj_t mp_micropython_kbd_intr(mp_obj_t int_chr_in) { mp_hal_set_interrupt_char(mp_obj_get_int(int_chr_in)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_micropython_kbd_intr_obj, mp_micropython_kbd_intr); #endif #if MICROPY_ENABLE_SCHEDULER STATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) { if (!mp_sched_schedule(function, arg)) { mp_raise_msg(&mp_type_RuntimeError, "schedule queue full"); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_micropython_schedule_obj, mp_micropython_schedule); #endif STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_micropython) }, { MP_ROM_QSTR(MP_QSTR_const), MP_ROM_PTR(&mp_identity_obj) }, #if MICROPY_ENABLE_COMPILER { MP_ROM_QSTR(MP_QSTR_opt_level), MP_ROM_PTR(&mp_micropython_opt_level_obj) }, #endif #if MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_MEM_STATS { MP_ROM_QSTR(MP_QSTR_mem_total), MP_ROM_PTR(&mp_micropython_mem_total_obj) }, { MP_ROM_QSTR(MP_QSTR_mem_current), MP_ROM_PTR(&mp_micropython_mem_current_obj) }, { MP_ROM_QSTR(MP_QSTR_mem_peak), MP_ROM_PTR(&mp_micropython_mem_peak_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_mem_info), MP_ROM_PTR(&mp_micropython_mem_info_obj) }, { MP_ROM_QSTR(MP_QSTR_qstr_info), MP_ROM_PTR(&mp_micropython_qstr_info_obj) }, #endif #if MICROPY_PY_MICROPYTHON_STACK_USE { MP_ROM_QSTR(MP_QSTR_stack_use), MP_ROM_PTR(&mp_micropython_stack_use_obj) }, #endif #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0) { MP_ROM_QSTR(MP_QSTR_alloc_emergency_exception_buf), MP_ROM_PTR(&mp_alloc_emergency_exception_buf_obj) }, #endif #if MICROPY_ENABLE_PYSTACK { MP_ROM_QSTR(MP_QSTR_pystack_use), MP_ROM_PTR(&mp_micropython_pystack_use_obj) }, #endif #if MICROPY_ENABLE_GC { MP_ROM_QSTR(MP_QSTR_heap_lock), MP_ROM_PTR(&mp_micropython_heap_lock_obj) }, { MP_ROM_QSTR(MP_QSTR_heap_unlock), MP_ROM_PTR(&mp_micropython_heap_unlock_obj) }, #endif #if MICROPY_KBD_EXCEPTION { MP_ROM_QSTR(MP_QSTR_kbd_intr), MP_ROM_PTR(&mp_micropython_kbd_intr_obj) }, #endif #if MICROPY_ENABLE_SCHEDULER { MP_ROM_QSTR(MP_QSTR_schedule), MP_ROM_PTR(&mp_micropython_schedule_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_micropython_globals, mp_module_micropython_globals_table); const mp_obj_module_t mp_module_micropython = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_micropython_globals, }; micropython-1.12/py/modstruct.c000066400000000000000000000220441357706137100166440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/builtin.h" #include "py/objtuple.h" #include "py/binary.h" #include "py/parsenum.h" #if MICROPY_PY_STRUCT /* This module implements most of character typecodes from CPython, with some extensions: O - (Pointer to) an arbitrary Python object. This is useful for callback data, etc. Note that you must keep reference to passed object in your Python application, otherwise it may be garbage-collected, and then when you get back this value from callback it may be invalid (and lead to crash). S - Pointer to a string (returned as a Python string). Note the difference from "Ns", - the latter says "in this place of structure is character data of up to N bytes length", while "S" means "in this place of a structure is a pointer to zero-terminated character data". */ STATIC char get_fmt_type(const char **fmt) { char t = **fmt; switch (t) { case '!': t = '>'; break; case '@': case '=': case '<': case '>': break; default: return '@'; } // Skip type char (*fmt)++; return t; } STATIC mp_uint_t get_fmt_num(const char **p) { const char *num = *p; uint len = 1; while (unichar_isdigit(*++num)) { len++; } mp_uint_t val = (mp_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10, NULL)); *p = num; return val; } STATIC size_t calc_size_items(const char *fmt, size_t *total_sz) { char fmt_type = get_fmt_type(&fmt); size_t total_cnt = 0; size_t size; for (size = 0; *fmt; fmt++) { mp_uint_t cnt = 1; if (unichar_isdigit(*fmt)) { cnt = get_fmt_num(&fmt); } if (*fmt == 's') { total_cnt += 1; size += cnt; } else { total_cnt += cnt; size_t align; size_t sz = mp_binary_get_size(fmt_type, *fmt, &align); while (cnt--) { // Apply alignment size = (size + align - 1) & ~(align - 1); size += sz; } } } *total_sz = size; return total_cnt; } STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { const char *fmt = mp_obj_str_get_str(fmt_in); size_t size; calc_size_items(fmt, &size); return MP_OBJ_NEW_SMALL_INT(size); } MP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize); STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { // unpack requires that the buffer be exactly the right size. // unpack_from requires that the buffer be "big enough". // Since we implement unpack and unpack_from using the same function // we relax the "exact" requirement, and only implement "big enough". const char *fmt = mp_obj_str_get_str(args[0]); size_t total_sz; size_t num_items = calc_size_items(fmt, &total_sz); char fmt_type = get_fmt_type(&fmt); mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_items, NULL)); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); byte *p = bufinfo.buf; byte *end_p = &p[bufinfo.len]; mp_int_t offset = 0; if (n_args > 2) { // offset arg provided offset = mp_obj_get_int(args[2]); if (offset < 0) { // negative offsets are relative to the end of the buffer offset = bufinfo.len + offset; if (offset < 0) { mp_raise_ValueError("buffer too small"); } } p += offset; } byte *p_base = p; // Check that the input buffer is big enough to unpack all the values if (p + total_sz > end_p) { mp_raise_ValueError("buffer too small"); } for (size_t i = 0; i < num_items;) { mp_uint_t cnt = 1; if (unichar_isdigit(*fmt)) { cnt = get_fmt_num(&fmt); } mp_obj_t item; if (*fmt == 's') { item = mp_obj_new_bytes(p, cnt); p += cnt; res->items[i++] = item; } else { while (cnt--) { item = mp_binary_get_val(fmt_type, *fmt, p_base, &p); res->items[i++] = item; } } fmt++; } return MP_OBJ_FROM_PTR(res); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_unpack_from_obj, 2, 3, struct_unpack_from); // This function assumes there is enough room in p to store all the values STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, const mp_obj_t *args) { const char *fmt = mp_obj_str_get_str(fmt_in); char fmt_type = get_fmt_type(&fmt); byte *p_base = p; size_t i; for (i = 0; i < n_args;) { mp_uint_t cnt = 1; if (*fmt == '\0') { // more arguments given than used by format string; CPython raises struct.error here break; } if (unichar_isdigit(*fmt)) { cnt = get_fmt_num(&fmt); } if (*fmt == 's') { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ); mp_uint_t to_copy = cnt; if (bufinfo.len < to_copy) { to_copy = bufinfo.len; } memcpy(p, bufinfo.buf, to_copy); memset(p + to_copy, 0, cnt - to_copy); p += cnt; } else { // If we run out of args then we just finish; CPython would raise struct.error while (cnt-- && i < n_args) { mp_binary_set_val(fmt_type, *fmt, args[i++], p_base, &p); } } fmt++; } } STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { // TODO: "The arguments must match the values required by the format exactly." mp_int_t size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0])); vstr_t vstr; vstr_init_len(&vstr, size); byte *p = (byte*)vstr.buf; memset(p, 0, size); struct_pack_into_internal(args[0], p, n_args - 1, &args[1]); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack); STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); mp_int_t offset = mp_obj_get_int(args[2]); if (offset < 0) { // negative offsets are relative to the end of the buffer offset = (mp_int_t)bufinfo.len + offset; if (offset < 0) { mp_raise_ValueError("buffer too small"); } } byte *p = (byte *)bufinfo.buf; byte *end_p = &p[bufinfo.len]; p += offset; // Check that the output buffer is big enough to hold all the values mp_int_t sz = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0])); if (p + sz > end_p) { mp_raise_ValueError("buffer too small"); } struct_pack_into_internal(args[0], p, n_args - 3, &args[3]); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_into_obj, 3, MP_OBJ_FUN_ARGS_MAX, struct_pack_into); STATIC const mp_rom_map_elem_t mp_module_struct_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ustruct) }, { MP_ROM_QSTR(MP_QSTR_calcsize), MP_ROM_PTR(&struct_calcsize_obj) }, { MP_ROM_QSTR(MP_QSTR_pack), MP_ROM_PTR(&struct_pack_obj) }, { MP_ROM_QSTR(MP_QSTR_pack_into), MP_ROM_PTR(&struct_pack_into_obj) }, { MP_ROM_QSTR(MP_QSTR_unpack), MP_ROM_PTR(&struct_unpack_from_obj) }, { MP_ROM_QSTR(MP_QSTR_unpack_from), MP_ROM_PTR(&struct_unpack_from_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_struct_globals, mp_module_struct_globals_table); const mp_obj_module_t mp_module_ustruct = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_struct_globals, }; #endif micropython-1.12/py/modsys.c000066400000000000000000000212671357706137100161440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/builtin.h" #include "py/objlist.h" #include "py/objtuple.h" #include "py/objstr.h" #include "py/objint.h" #include "py/objtype.h" #include "py/stream.h" #include "py/smallint.h" #include "py/runtime.h" #include "py/persistentcode.h" #if MICROPY_PY_SYS_SETTRACE #include "py/objmodule.h" #include "py/profile.h" #endif #if MICROPY_PY_SYS // defined per port; type of these is irrelevant, just need pointer extern struct _mp_dummy_t mp_sys_stdin_obj; extern struct _mp_dummy_t mp_sys_stdout_obj; extern struct _mp_dummy_t mp_sys_stderr_obj; #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, mp_stream_write_adaptor}; #endif // version - Python language version that this implementation conforms to, as a string STATIC const MP_DEFINE_STR_OBJ(version_obj, "3.4.0"); // version_info - Python language version that this implementation conforms to, as a tuple of ints #define I(n) MP_OBJ_NEW_SMALL_INT(n) // TODO: CPython is now at 5-element array, but save 2 els so far... STATIC const mp_obj_tuple_t mp_sys_version_info_obj = {{&mp_type_tuple}, 3, {I(3), I(4), I(0)}}; // sys.implementation object // this holds the MicroPython version STATIC const mp_obj_tuple_t mp_sys_implementation_version_info_obj = { {&mp_type_tuple}, 3, { I(MICROPY_VERSION_MAJOR), I(MICROPY_VERSION_MINOR), I(MICROPY_VERSION_MICRO) } }; #if MICROPY_PERSISTENT_CODE_LOAD #define SYS_IMPLEMENTATION_ELEMS \ MP_ROM_QSTR(MP_QSTR_micropython), \ MP_ROM_PTR(&mp_sys_implementation_version_info_obj), \ MP_ROM_INT(MPY_FILE_HEADER_INT) #else #define SYS_IMPLEMENTATION_ELEMS \ MP_ROM_QSTR(MP_QSTR_micropython), \ MP_ROM_PTR(&mp_sys_implementation_version_info_obj) #endif #if MICROPY_PY_ATTRTUPLE STATIC const qstr impl_fields[] = { MP_QSTR_name, MP_QSTR_version, #if MICROPY_PERSISTENT_CODE_LOAD MP_QSTR_mpy, #endif }; STATIC MP_DEFINE_ATTRTUPLE( mp_sys_implementation_obj, impl_fields, 2 + MICROPY_PERSISTENT_CODE_LOAD, SYS_IMPLEMENTATION_ELEMS ); #else STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = { {&mp_type_tuple}, 2 + MICROPY_PERSISTENT_CODE_LOAD, { SYS_IMPLEMENTATION_ELEMS } }; #endif #undef I #ifdef MICROPY_PY_SYS_PLATFORM // platform - the platform that MicroPython is running on STATIC const MP_DEFINE_STR_OBJ(platform_obj, MICROPY_PY_SYS_PLATFORM); #endif // exit([retval]): raise SystemExit, with optional argument given to the exception STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) { mp_obj_t exc; if (n_args == 0) { exc = mp_obj_new_exception(&mp_type_SystemExit); } else { exc = mp_obj_new_exception_arg1(&mp_type_SystemExit, args[0]); } nlr_raise(exc); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit); STATIC mp_obj_t mp_sys_print_exception(size_t n_args, const mp_obj_t *args) { #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES void *stream_obj = &mp_sys_stdout_obj; if (n_args > 1) { mp_get_stream_raise(args[1], MP_STREAM_OP_WRITE); stream_obj = MP_OBJ_TO_PTR(args[1]); } mp_print_t print = {stream_obj, mp_stream_write_adaptor}; mp_obj_print_exception(&print, args[0]); #else (void)n_args; mp_obj_print_exception(&mp_plat_print, args[0]); #endif return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_print_exception_obj, 1, 2, mp_sys_print_exception); #if MICROPY_PY_SYS_EXC_INFO STATIC mp_obj_t mp_sys_exc_info(void) { mp_obj_t cur_exc = MP_OBJ_FROM_PTR(MP_STATE_VM(cur_exception)); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); if (cur_exc == MP_OBJ_NULL) { t->items[0] = mp_const_none; t->items[1] = mp_const_none; t->items[2] = mp_const_none; return MP_OBJ_FROM_PTR(t); } t->items[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(cur_exc)); t->items[1] = cur_exc; t->items[2] = mp_const_none; return MP_OBJ_FROM_PTR(t); } MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info); #endif #if MICROPY_PY_SYS_GETSIZEOF STATIC mp_obj_t mp_sys_getsizeof(mp_obj_t obj) { return mp_unary_op(MP_UNARY_OP_SIZEOF, obj); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof); #endif #if MICROPY_PY_SYS_ATEXIT // atexit(callback): Callback is called when sys.exit is called. STATIC mp_obj_t mp_sys_atexit(mp_obj_t obj) { mp_obj_t old = MP_STATE_VM(sys_exitfunc); MP_STATE_VM(sys_exitfunc) = obj; return old; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_atexit_obj, mp_sys_atexit); #endif #if MICROPY_PY_SYS_SETTRACE // settrace(tracefunc): Set the system’s trace function. STATIC mp_obj_t mp_sys_settrace(mp_obj_t obj) { return mp_prof_settrace(obj); } MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_settrace_obj, mp_sys_settrace); #endif // MICROPY_PY_SYS_SETTRACE STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) }, { MP_ROM_QSTR(MP_QSTR_path), MP_ROM_PTR(&MP_STATE_VM(mp_sys_path_obj)) }, { MP_ROM_QSTR(MP_QSTR_argv), MP_ROM_PTR(&MP_STATE_VM(mp_sys_argv_obj)) }, { MP_ROM_QSTR(MP_QSTR_version), MP_ROM_PTR(&version_obj) }, { MP_ROM_QSTR(MP_QSTR_version_info), MP_ROM_PTR(&mp_sys_version_info_obj) }, { MP_ROM_QSTR(MP_QSTR_implementation), MP_ROM_PTR(&mp_sys_implementation_obj) }, #ifdef MICROPY_PY_SYS_PLATFORM { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_obj) }, #endif #if MP_ENDIANNESS_LITTLE { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_little) }, #else { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_big) }, #endif #if MICROPY_PY_SYS_MAXSIZE #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE // Maximum mp_int_t value is not representable as small int, so we have // little choice but to use MP_SMALL_INT_MAX. Apps also should be careful // to not try to compare sys.maxsize to some literal number (as this // number might not fit in available int size), but instead count number // of "one" bits in sys.maxsize. { MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_INT(MP_SMALL_INT_MAX) }, #else { MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_PTR(&mp_maxsize_obj) }, #endif #endif #if MICROPY_PY_SYS_EXIT { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mp_sys_exit_obj) }, #endif #if MICROPY_PY_SYS_SETTRACE { MP_ROM_QSTR(MP_QSTR_settrace), MP_ROM_PTR(&mp_sys_settrace_obj) }, #endif #if MICROPY_PY_SYS_STDFILES { MP_ROM_QSTR(MP_QSTR_stdin), MP_ROM_PTR(&mp_sys_stdin_obj) }, { MP_ROM_QSTR(MP_QSTR_stdout), MP_ROM_PTR(&mp_sys_stdout_obj) }, { MP_ROM_QSTR(MP_QSTR_stderr), MP_ROM_PTR(&mp_sys_stderr_obj) }, #endif #if MICROPY_PY_SYS_MODULES { MP_ROM_QSTR(MP_QSTR_modules), MP_ROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)) }, #endif #if MICROPY_PY_SYS_EXC_INFO { MP_ROM_QSTR(MP_QSTR_exc_info), MP_ROM_PTR(&mp_sys_exc_info_obj) }, #endif #if MICROPY_PY_SYS_GETSIZEOF { MP_ROM_QSTR(MP_QSTR_getsizeof), MP_ROM_PTR(&mp_sys_getsizeof_obj) }, #endif /* * Extensions to CPython */ { MP_ROM_QSTR(MP_QSTR_print_exception), MP_ROM_PTR(&mp_sys_print_exception_obj) }, #if MICROPY_PY_SYS_ATEXIT { MP_ROM_QSTR(MP_QSTR_atexit), MP_ROM_PTR(&mp_sys_atexit_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table); const mp_obj_module_t mp_module_sys = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_sys_globals, }; #endif micropython-1.12/py/modthread.c000066400000000000000000000247521357706137100165770ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/stackctrl.h" #if MICROPY_PY_THREAD #include "py/mpthread.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_PRINT (0) #define DEBUG_printf(...) (void)0 #endif /****************************************************************/ // Lock object STATIC const mp_obj_type_t mp_type_thread_lock; typedef struct _mp_obj_thread_lock_t { mp_obj_base_t base; mp_thread_mutex_t mutex; volatile bool locked; } mp_obj_thread_lock_t; STATIC mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) { mp_obj_thread_lock_t *self = m_new_obj(mp_obj_thread_lock_t); self->base.type = &mp_type_thread_lock; mp_thread_mutex_init(&self->mutex); self->locked = false; return self; } STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(args[0]); bool wait = true; if (n_args > 1) { wait = mp_obj_get_int(args[1]); // TODO support timeout arg } MP_THREAD_GIL_EXIT(); int ret = mp_thread_mutex_lock(&self->mutex, wait); MP_THREAD_GIL_ENTER(); if (ret == 0) { return mp_const_false; } else if (ret == 1) { self->locked = true; return mp_const_true; } else { mp_raise_OSError(-ret); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock_acquire_obj, 1, 3, thread_lock_acquire); STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in); if (!self->locked) { mp_raise_msg(&mp_type_RuntimeError, NULL); } self->locked = false; MP_THREAD_GIL_EXIT(); mp_thread_mutex_unlock(&self->mutex); MP_THREAD_GIL_ENTER(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_release_obj, thread_lock_release); STATIC mp_obj_t thread_lock_locked(mp_obj_t self_in) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(self->locked); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_locked_obj, thread_lock_locked); STATIC mp_obj_t thread_lock___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; // unused return thread_lock_release(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock___exit___obj, 4, 4, thread_lock___exit__); STATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_acquire), MP_ROM_PTR(&thread_lock_acquire_obj) }, { MP_ROM_QSTR(MP_QSTR_release), MP_ROM_PTR(&thread_lock_release_obj) }, { MP_ROM_QSTR(MP_QSTR_locked), MP_ROM_PTR(&thread_lock_locked_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&thread_lock_acquire_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&thread_lock___exit___obj) }, }; STATIC MP_DEFINE_CONST_DICT(thread_lock_locals_dict, thread_lock_locals_dict_table); STATIC const mp_obj_type_t mp_type_thread_lock = { { &mp_type_type }, .name = MP_QSTR_lock, .locals_dict = (mp_obj_dict_t*)&thread_lock_locals_dict, }; /****************************************************************/ // _thread module STATIC size_t thread_stack_size = 0; STATIC mp_obj_t mod_thread_get_ident(void) { return mp_obj_new_int_from_uint((uintptr_t)mp_thread_get_state()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_get_ident_obj, mod_thread_get_ident); STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) { mp_obj_t ret = mp_obj_new_int_from_uint(thread_stack_size); if (n_args == 0) { thread_stack_size = 0; } else { thread_stack_size = mp_obj_get_int(args[0]); } return ret; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size); typedef struct _thread_entry_args_t { mp_obj_dict_t *dict_locals; mp_obj_dict_t *dict_globals; size_t stack_size; mp_obj_t fun; size_t n_args; size_t n_kw; mp_obj_t args[]; } thread_entry_args_t; STATIC void *thread_entry(void *args_in) { // Execution begins here for a new thread. We do not have the GIL. thread_entry_args_t *args = (thread_entry_args_t*)args_in; mp_state_thread_t ts; mp_thread_set_state(&ts); mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan mp_stack_set_limit(args->stack_size); #if MICROPY_ENABLE_PYSTACK // TODO threading and pystack is not fully supported, for now just make a small stack mp_obj_t mini_pystack[128]; mp_pystack_init(mini_pystack, &mini_pystack[128]); #endif // set locals and globals from the calling context mp_locals_set(args->dict_locals); mp_globals_set(args->dict_globals); MP_THREAD_GIL_ENTER(); // signal that we are set up and running mp_thread_start(); // TODO set more thread-specific state here: // mp_pending_exception? (root pointer) // cur_exception (root pointer) DEBUG_printf("[thread] start ts=%p args=%p stack=%p\n", &ts, &args, MP_STATE_THREAD(stack_top)); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_n_kw(args->fun, args->n_args, args->n_kw, args->args); nlr_pop(); } else { // uncaught exception // check for SystemExit mp_obj_base_t *exc = (mp_obj_base_t*)nlr.ret_val; if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // swallow exception silently } else { // print exception out mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in thread started by "); mp_obj_print_helper(MICROPY_ERROR_PRINTER, args->fun, PRINT_REPR); mp_printf(MICROPY_ERROR_PRINTER, "\n"); mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(exc)); } } DEBUG_printf("[thread] finish ts=%p\n", &ts); // signal that we are finished mp_thread_finish(); MP_THREAD_GIL_EXIT(); return NULL; } STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) { // This structure holds the Python function and arguments for thread entry. // We copy all arguments into this structure to keep ownership of them. // We must be very careful about root pointers because this pointer may // disappear from our address space before the thread is created. thread_entry_args_t *th_args; // get positional arguments size_t pos_args_len; mp_obj_t *pos_args_items; mp_obj_get_array(args[1], &pos_args_len, &pos_args_items); // check for keyword arguments if (n_args == 2) { // just position arguments th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len); th_args->n_kw = 0; } else { // positional and keyword arguments if (mp_obj_get_type(args[2]) != &mp_type_dict) { mp_raise_TypeError("expecting a dict for keyword args"); } mp_map_t *map = &((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[2]))->map; th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used); th_args->n_kw = map->used; // copy across the keyword arguments for (size_t i = 0, n = pos_args_len; i < map->alloc; ++i) { if (mp_map_slot_is_filled(map, i)) { th_args->args[n++] = map->table[i].key; th_args->args[n++] = map->table[i].value; } } } // copy agross the positional arguments th_args->n_args = pos_args_len; memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t)); // pass our locals and globals into the new thread th_args->dict_locals = mp_locals_get(); th_args->dict_globals = mp_globals_get(); // set the stack size to use th_args->stack_size = thread_stack_size; // set the function for thread entry th_args->fun = args[0]; // spawn the thread! mp_thread_create(thread_entry, th_args, &th_args->stack_size); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread); STATIC mp_obj_t mod_thread_exit(void) { nlr_raise(mp_obj_new_exception(&mp_type_SystemExit)); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit); STATIC mp_obj_t mod_thread_allocate_lock(void) { return MP_OBJ_FROM_PTR(mp_obj_new_thread_lock()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_allocate_lock_obj, mod_thread_allocate_lock); STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__thread) }, { MP_ROM_QSTR(MP_QSTR_LockType), MP_ROM_PTR(&mp_type_thread_lock) }, { MP_ROM_QSTR(MP_QSTR_get_ident), MP_ROM_PTR(&mod_thread_get_ident_obj) }, { MP_ROM_QSTR(MP_QSTR_stack_size), MP_ROM_PTR(&mod_thread_stack_size_obj) }, { MP_ROM_QSTR(MP_QSTR_start_new_thread), MP_ROM_PTR(&mod_thread_start_new_thread_obj) }, { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mod_thread_exit_obj) }, { MP_ROM_QSTR(MP_QSTR_allocate_lock), MP_ROM_PTR(&mod_thread_allocate_lock_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_thread_globals, mp_module_thread_globals_table); const mp_obj_module_t mp_module_thread = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_thread_globals, }; #endif // MICROPY_PY_THREAD micropython-1.12/py/moduerrno.c000066400000000000000000000074471357706137100166440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" #include "py/mperrno.h" #if MICROPY_PY_UERRNO // This list can be defined per port in mpconfigport.h to tailor it to a // specific port's needs. If it's not defined then we provide a default. #ifndef MICROPY_PY_UERRNO_LIST #define MICROPY_PY_UERRNO_LIST \ X(EPERM) \ X(ENOENT) \ X(EIO) \ X(EBADF) \ X(EAGAIN) \ X(ENOMEM) \ X(EACCES) \ X(EEXIST) \ X(ENODEV) \ X(EISDIR) \ X(EINVAL) \ X(EOPNOTSUPP) \ X(EADDRINUSE) \ X(ECONNABORTED) \ X(ECONNRESET) \ X(ENOBUFS) \ X(ENOTCONN) \ X(ETIMEDOUT) \ X(ECONNREFUSED) \ X(EHOSTUNREACH) \ X(EALREADY) \ X(EINPROGRESS) \ #endif #if MICROPY_PY_UERRNO_ERRORCODE STATIC const mp_rom_map_elem_t errorcode_table[] = { #define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) }, MICROPY_PY_UERRNO_LIST #undef X }; STATIC const mp_obj_dict_t errorcode_dict = { .base = {&mp_type_dict}, .map = { .all_keys_are_qstrs = 0, // keys are integers .is_fixed = 1, .is_ordered = 1, .used = MP_ARRAY_SIZE(errorcode_table), .alloc = MP_ARRAY_SIZE(errorcode_table), .table = (mp_map_elem_t*)(mp_rom_map_elem_t*)errorcode_table, }, }; #endif STATIC const mp_rom_map_elem_t mp_module_uerrno_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uerrno) }, #if MICROPY_PY_UERRNO_ERRORCODE { MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) }, #endif #define X(e) { MP_ROM_QSTR(MP_QSTR_## e), MP_ROM_INT(MP_ ## e) }, MICROPY_PY_UERRNO_LIST #undef X }; STATIC MP_DEFINE_CONST_DICT(mp_module_uerrno_globals, mp_module_uerrno_globals_table); const mp_obj_module_t mp_module_uerrno = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_uerrno_globals, }; qstr mp_errno_to_str(mp_obj_t errno_val) { #if MICROPY_PY_UERRNO_ERRORCODE // We have the errorcode dict so can do a lookup using the hash map mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP); if (elem == NULL) { return MP_QSTRnull; } else { return MP_OBJ_QSTR_VALUE(elem->value); } #else // We don't have the errorcode dict so do a simple search in the modules dict for (size_t i = 0; i < MP_ARRAY_SIZE(mp_module_uerrno_globals_table); ++i) { if (errno_val == mp_module_uerrno_globals_table[i].value) { return MP_OBJ_QSTR_VALUE(mp_module_uerrno_globals_table[i].key); } } return MP_QSTRnull; #endif } #endif //MICROPY_PY_UERRNO micropython-1.12/py/mpconfig.h000066400000000000000000001425001357706137100164270ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_MPCONFIG_H #define MICROPY_INCLUDED_PY_MPCONFIG_H // Current version of MicroPython #define MICROPY_VERSION_MAJOR 1 #define MICROPY_VERSION_MINOR 12 #define MICROPY_VERSION_MICRO 0 // Combined version as a 32-bit number for convenience #define MICROPY_VERSION ( \ MICROPY_VERSION_MAJOR << 16 \ | MICROPY_VERSION_MINOR << 8 \ | MICROPY_VERSION_MICRO) // String version #define MICROPY_VERSION_STRING \ MP_STRINGIFY(MICROPY_VERSION_MAJOR) "." \ MP_STRINGIFY(MICROPY_VERSION_MINOR) "." \ MP_STRINGIFY(MICROPY_VERSION_MICRO) // This file contains default configuration settings for MicroPython. // You can override any of the options below using mpconfigport.h file // located in a directory of your port. // mpconfigport.h is a file containing configuration settings for a // particular port. mpconfigport.h is actually a default name for // such config, and it can be overridden using MP_CONFIGFILE preprocessor // define (you can do that by passing CFLAGS_EXTRA='-DMP_CONFIGFILE=""' // argument to make when using standard MicroPython makefiles). // This is useful to have more than one config per port, for example, // release vs debug configs, etc. Note that if you switch from one config // to another, you must rebuild from scratch using "-B" switch to make. #ifdef MP_CONFIGFILE #include MP_CONFIGFILE #else #include #endif // Any options not explicitly set in mpconfigport.h will get default // values below. /*****************************************************************************/ /* Object representation */ // A MicroPython object is a machine word having the following form: // - xxxx...xxx1 : a small int, bits 1 and above are the value // - xxxx...xx10 : a qstr, bits 2 and above are the value // - xxxx...xx00 : a pointer to an mp_obj_base_t (unless a fake object) #define MICROPY_OBJ_REPR_A (0) // A MicroPython object is a machine word having the following form: // - xxxx...xx01 : a small int, bits 2 and above are the value // - xxxx...xx11 : a qstr, bits 2 and above are the value // - xxxx...xxx0 : a pointer to an mp_obj_base_t (unless a fake object) #define MICROPY_OBJ_REPR_B (1) // A MicroPython object is a machine word having the following form (called R): // - iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int with 31-bit signed value // - 01111111 1qqqqqqq qqqqqqqq qqqqq110 str with 20-bit qstr value // - s1111111 10000000 00000000 00000010 +/- inf // - s1111111 1xxxxxxx xxxxxxxx xxxxx010 nan, x != 0 // - seeeeeee efffffff ffffffff ffffff10 30-bit fp, e != 0xff // - pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment) // Str and float stored as O = R + 0x80800000, retrieved as R = O - 0x80800000. // This makes strs easier to encode/decode as they have zeros in the top 9 bits. // This scheme only works with 32-bit word size and float enabled. #define MICROPY_OBJ_REPR_C (2) // A MicroPython object is a 64-bit word having the following form (called R): // - seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 64-bit fp, e != 0x7ff // - s1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000 +/- inf // - 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 normalised nan // - 01111111 11111101 iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int // - 01111111 11111110 00000000 00000000 qqqqqqqq qqqqqqqq qqqqqqqq qqqqqqq1 str // - 01111111 11111100 00000000 00000000 pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment) // Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000. // This makes pointers have all zeros in the top 32 bits. // Small-ints and strs have 1 as LSB to make sure they don't look like pointers // to the garbage collector. #define MICROPY_OBJ_REPR_D (3) #ifndef MICROPY_OBJ_REPR #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) #endif /*****************************************************************************/ /* Memory allocation policy */ // Number of bytes in memory allocation/GC block. Any size allocated will be // rounded up to be multiples of this. #ifndef MICROPY_BYTES_PER_GC_BLOCK #define MICROPY_BYTES_PER_GC_BLOCK (4 * BYTES_PER_WORD) #endif // Number of words allocated (in BSS) to the GC stack (minimum is 1) #ifndef MICROPY_ALLOC_GC_STACK_SIZE #define MICROPY_ALLOC_GC_STACK_SIZE (64) #endif // The C-type to use for entries in the GC stack. By default it allows the // heap to be as large as the address space, but the bit-width of this type can // be reduced to save memory when the heap is small enough. The type must be // big enough to index all blocks in the heap, which is set by // heap-size-in-bytes / MICROPY_BYTES_PER_GC_BLOCK. #ifndef MICROPY_GC_STACK_ENTRY_TYPE #define MICROPY_GC_STACK_ENTRY_TYPE size_t #endif // Be conservative and always clear to zero newly (re)allocated memory in the GC. // This helps eliminate stray pointers that hold on to memory that's no longer // used. It decreases performance due to unnecessary memory clearing. // A memory manager which always clears memory can set this to 0. // TODO Do analysis to understand why some memory is not properly cleared and // find a more efficient way to clear it. #ifndef MICROPY_GC_CONSERVATIVE_CLEAR #define MICROPY_GC_CONSERVATIVE_CLEAR (MICROPY_ENABLE_GC) #endif // Support automatic GC when reaching allocation threshold, // configurable by gc.threshold(). #ifndef MICROPY_GC_ALLOC_THRESHOLD #define MICROPY_GC_ALLOC_THRESHOLD (1) #endif // Number of bytes to allocate initially when creating new chunks to store // interned string data. Smaller numbers lead to more chunks being needed // and more wastage at the end of the chunk. Larger numbers lead to wasted // space at the end when no more strings need interning. #ifndef MICROPY_ALLOC_QSTR_CHUNK_INIT #define MICROPY_ALLOC_QSTR_CHUNK_INIT (128) #endif // Initial amount for lexer indentation level #ifndef MICROPY_ALLOC_LEXER_INDENT_INIT #define MICROPY_ALLOC_LEXER_INDENT_INIT (10) #endif // Increment for lexer indentation level #ifndef MICROPY_ALLOC_LEXEL_INDENT_INC #define MICROPY_ALLOC_LEXEL_INDENT_INC (8) #endif // Initial amount for parse rule stack #ifndef MICROPY_ALLOC_PARSE_RULE_INIT #define MICROPY_ALLOC_PARSE_RULE_INIT (64) #endif // Increment for parse rule stack #ifndef MICROPY_ALLOC_PARSE_RULE_INC #define MICROPY_ALLOC_PARSE_RULE_INC (16) #endif // Initial amount for parse result stack #ifndef MICROPY_ALLOC_PARSE_RESULT_INIT #define MICROPY_ALLOC_PARSE_RESULT_INIT (32) #endif // Increment for parse result stack #ifndef MICROPY_ALLOC_PARSE_RESULT_INC #define MICROPY_ALLOC_PARSE_RESULT_INC (16) #endif // Strings this length or less will be interned by the parser #ifndef MICROPY_ALLOC_PARSE_INTERN_STRING_LEN #define MICROPY_ALLOC_PARSE_INTERN_STRING_LEN (10) #endif // Number of bytes to allocate initially when creating new chunks to store // parse nodes. Small leads to fragmentation, large leads to excess use. #ifndef MICROPY_ALLOC_PARSE_CHUNK_INIT #define MICROPY_ALLOC_PARSE_CHUNK_INIT (128) #endif // Initial amount for ids in a scope #ifndef MICROPY_ALLOC_SCOPE_ID_INIT #define MICROPY_ALLOC_SCOPE_ID_INIT (4) #endif // Increment for ids in a scope #ifndef MICROPY_ALLOC_SCOPE_ID_INC #define MICROPY_ALLOC_SCOPE_ID_INC (6) #endif // Maximum length of a path in the filesystem // So we can allocate a buffer on the stack for path manipulation in import #ifndef MICROPY_ALLOC_PATH_MAX #define MICROPY_ALLOC_PATH_MAX (512) #endif // Initial size of module dict #ifndef MICROPY_MODULE_DICT_SIZE #define MICROPY_MODULE_DICT_SIZE (1) #endif // Whether realloc/free should be passed allocated memory region size // You must enable this if MICROPY_MEM_STATS is enabled #ifndef MICROPY_MALLOC_USES_ALLOCATED_SIZE #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (0) #endif // Number of bytes used to store qstr length // Dictates hard limit on maximum Python identifier length, but 1 byte // (limit of 255 bytes in an identifier) should be enough for everyone #ifndef MICROPY_QSTR_BYTES_IN_LEN #define MICROPY_QSTR_BYTES_IN_LEN (1) #endif // Number of bytes used to store qstr hash #ifndef MICROPY_QSTR_BYTES_IN_HASH #define MICROPY_QSTR_BYTES_IN_HASH (2) #endif // Avoid using C stack when making Python function calls. C stack still // may be used if there's no free heap. #ifndef MICROPY_STACKLESS #define MICROPY_STACKLESS (0) #endif // Never use C stack when making Python function calls. This may break // testsuite as will subtly change which exception is thrown in case // of too deep recursion and other similar cases. #ifndef MICROPY_STACKLESS_STRICT #define MICROPY_STACKLESS_STRICT (0) #endif // Don't use alloca calls. As alloca() is not part of ANSI C, this // workaround option is provided for compilers lacking this de-facto // standard function. The way it works is allocating from heap, and // relying on garbage collection to free it eventually. This is of // course much less optimal than real alloca(). #if defined(MICROPY_NO_ALLOCA) && MICROPY_NO_ALLOCA #undef alloca #define alloca(x) m_malloc(x) #endif /*****************************************************************************/ /* MicroPython emitters */ // Whether to support loading of persistent code #ifndef MICROPY_PERSISTENT_CODE_LOAD #define MICROPY_PERSISTENT_CODE_LOAD (0) #endif // Whether to support saving of persistent code #ifndef MICROPY_PERSISTENT_CODE_SAVE #define MICROPY_PERSISTENT_CODE_SAVE (0) #endif // Whether generated code can persist independently of the VM/runtime instance // This is enabled automatically when needed by other features #ifndef MICROPY_PERSISTENT_CODE #define MICROPY_PERSISTENT_CODE (MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE || MICROPY_MODULE_FROZEN_MPY) #endif // Whether to emit x64 native code #ifndef MICROPY_EMIT_X64 #define MICROPY_EMIT_X64 (0) #endif // Whether to emit x86 native code #ifndef MICROPY_EMIT_X86 #define MICROPY_EMIT_X86 (0) #endif // Whether to emit thumb native code #ifndef MICROPY_EMIT_THUMB #define MICROPY_EMIT_THUMB (0) #endif // Whether to enable the thumb inline assembler #ifndef MICROPY_EMIT_INLINE_THUMB #define MICROPY_EMIT_INLINE_THUMB (0) #endif // Whether to enable ARMv7-M instruction support in the Thumb2 inline assembler #ifndef MICROPY_EMIT_INLINE_THUMB_ARMV7M #define MICROPY_EMIT_INLINE_THUMB_ARMV7M (1) #endif // Whether to enable float support in the Thumb2 inline assembler #ifndef MICROPY_EMIT_INLINE_THUMB_FLOAT #define MICROPY_EMIT_INLINE_THUMB_FLOAT (1) #endif // Whether to emit ARM native code #ifndef MICROPY_EMIT_ARM #define MICROPY_EMIT_ARM (0) #endif // Whether to emit Xtensa native code #ifndef MICROPY_EMIT_XTENSA #define MICROPY_EMIT_XTENSA (0) #endif // Whether to enable the Xtensa inline assembler #ifndef MICROPY_EMIT_INLINE_XTENSA #define MICROPY_EMIT_INLINE_XTENSA (0) #endif // Whether to emit Xtensa-Windowed native code #ifndef MICROPY_EMIT_XTENSAWIN #define MICROPY_EMIT_XTENSAWIN (0) #endif // Convenience definition for whether any native emitter is enabled #define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN) // Select prelude-as-bytes-object for certain emitters #define MICROPY_EMIT_NATIVE_PRELUDE_AS_BYTES_OBJ (MICROPY_EMIT_XTENSAWIN) // Convenience definition for whether any inline assembler emitter is enabled #define MICROPY_EMIT_INLINE_ASM (MICROPY_EMIT_INLINE_THUMB || MICROPY_EMIT_INLINE_XTENSA) // Convenience definition for whether any native or inline assembler emitter is enabled #define MICROPY_EMIT_MACHINE_CODE (MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM) /*****************************************************************************/ /* Compiler configuration */ // Whether to include the compiler #ifndef MICROPY_ENABLE_COMPILER #define MICROPY_ENABLE_COMPILER (1) #endif // Whether the compiler is dynamically configurable (ie at runtime) // This will disable the ability to execute native/viper code #ifndef MICROPY_DYNAMIC_COMPILER #define MICROPY_DYNAMIC_COMPILER (0) #endif // Configure dynamic compiler macros #if MICROPY_DYNAMIC_COMPILER #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC (mp_dynamic_compiler.opt_cache_map_lookup_in_bytecode) #define MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC (mp_dynamic_compiler.py_builtins_str_unicode) #else #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE #define MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC MICROPY_PY_BUILTINS_STR_UNICODE #endif // Whether to enable constant folding; eg 1+2 rewritten as 3 #ifndef MICROPY_COMP_CONST_FOLDING #define MICROPY_COMP_CONST_FOLDING (1) #endif // Whether to enable optimisations for constant literals, eg OrderedDict #ifndef MICROPY_COMP_CONST_LITERAL #define MICROPY_COMP_CONST_LITERAL (1) #endif // Whether to enable lookup of constants in modules; eg module.CONST #ifndef MICROPY_COMP_MODULE_CONST #define MICROPY_COMP_MODULE_CONST (0) #endif // Whether to enable constant optimisation; id = const(value) #ifndef MICROPY_COMP_CONST #define MICROPY_COMP_CONST (1) #endif // Whether to enable optimisation of: a, b = c, d // Costs 124 bytes (Thumb2) #ifndef MICROPY_COMP_DOUBLE_TUPLE_ASSIGN #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #endif // Whether to enable optimisation of: a, b, c = d, e, f // Requires MICROPY_COMP_DOUBLE_TUPLE_ASSIGN and costs 68 bytes (Thumb2) #ifndef MICROPY_COMP_TRIPLE_TUPLE_ASSIGN #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #endif // Whether to enable optimisation of: return a if b else c // Costs about 80 bytes (Thumb2) and saves 2 bytes of bytecode for each use #ifndef MICROPY_COMP_RETURN_IF_EXPR #define MICROPY_COMP_RETURN_IF_EXPR (0) #endif /*****************************************************************************/ /* Internal debugging stuff */ // Whether to collect memory allocation stats #ifndef MICROPY_MEM_STATS #define MICROPY_MEM_STATS (0) #endif // The mp_print_t printer used for debugging output #ifndef MICROPY_DEBUG_PRINTER #define MICROPY_DEBUG_PRINTER (&mp_plat_print) #endif // Whether to build functions that print debugging info: // mp_bytecode_print // mp_parse_node_print #ifndef MICROPY_DEBUG_PRINTERS #define MICROPY_DEBUG_PRINTERS (0) #endif // Whether to enable all debugging outputs (it will be extremely verbose) #ifndef MICROPY_DEBUG_VERBOSE #define MICROPY_DEBUG_VERBOSE (0) #endif // Whether to enable debugging versions of MP_OBJ_NULL/STOP_ITERATION/SENTINEL #ifndef MICROPY_DEBUG_MP_OBJ_SENTINELS #define MICROPY_DEBUG_MP_OBJ_SENTINELS (0) #endif // Whether to enable a simple VM stack overflow check #ifndef MICROPY_DEBUG_VM_STACK_OVERFLOW #define MICROPY_DEBUG_VM_STACK_OVERFLOW (0) #endif /*****************************************************************************/ /* Optimisations */ // Whether to use computed gotos in the VM, or a switch // Computed gotos are roughly 10% faster, and increase VM code size by a little // Note: enabling this will use the gcc-specific extensions of ranged designated // initialisers and addresses of labels, which are not part of the C99 standard. #ifndef MICROPY_OPT_COMPUTED_GOTO #define MICROPY_OPT_COMPUTED_GOTO (0) #endif // Whether to cache result of map lookups in LOAD_NAME, LOAD_GLOBAL, LOAD_ATTR, // STORE_ATTR bytecodes. Uses 1 byte extra RAM for each of these opcodes and // uses a bit of extra code ROM, but greatly improves lookup speed. #ifndef MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #endif // Whether to use fast versions of bitwise operations (and, or, xor) when the // arguments are both positive. Increases Thumb2 code size by about 250 bytes. #ifndef MICROPY_OPT_MPZ_BITWISE #define MICROPY_OPT_MPZ_BITWISE (0) #endif // Whether math.factorial is large, fast and recursive (1) or small and slow (0). #ifndef MICROPY_OPT_MATH_FACTORIAL #define MICROPY_OPT_MATH_FACTORIAL (0) #endif /*****************************************************************************/ /* Python internal features */ // Whether to enable import of external modules // When disabled, only importing of built-in modules is supported // When enabled, a port must implement mp_import_stat (among other things) #ifndef MICROPY_ENABLE_EXTERNAL_IMPORT #define MICROPY_ENABLE_EXTERNAL_IMPORT (1) #endif // Whether to use the POSIX reader for importing files #ifndef MICROPY_READER_POSIX #define MICROPY_READER_POSIX (0) #endif // Whether to use the VFS reader for importing files #ifndef MICROPY_READER_VFS #define MICROPY_READER_VFS (0) #endif // Whether any readers have been defined #ifndef MICROPY_HAS_FILE_READER #define MICROPY_HAS_FILE_READER (MICROPY_READER_POSIX || MICROPY_READER_VFS) #endif // Hook for the VM at the start of the opcode loop (can contain variable // definitions usable by the other hook functions) #ifndef MICROPY_VM_HOOK_INIT #define MICROPY_VM_HOOK_INIT #endif // Hook for the VM during the opcode loop (but only after jump opcodes) #ifndef MICROPY_VM_HOOK_LOOP #define MICROPY_VM_HOOK_LOOP #endif // Hook for the VM just before return opcode is finished being interpreted #ifndef MICROPY_VM_HOOK_RETURN #define MICROPY_VM_HOOK_RETURN #endif // Whether to include the garbage collector #ifndef MICROPY_ENABLE_GC #define MICROPY_ENABLE_GC (0) #endif // Whether to enable finalisers in the garbage collector (ie call __del__) #ifndef MICROPY_ENABLE_FINALISER #define MICROPY_ENABLE_FINALISER (0) #endif // Whether to enable a separate allocator for the Python stack. // If enabled then the code must call mp_pystack_init before mp_init. #ifndef MICROPY_ENABLE_PYSTACK #define MICROPY_ENABLE_PYSTACK (0) #endif // Number of bytes that memory returned by mp_pystack_alloc will be aligned by. #ifndef MICROPY_PYSTACK_ALIGN #define MICROPY_PYSTACK_ALIGN (8) #endif // Whether to check C stack usage. C stack used for calling Python functions, // etc. Not checking means segfault on overflow. #ifndef MICROPY_STACK_CHECK #define MICROPY_STACK_CHECK (0) #endif // Whether to have an emergency exception buffer #ifndef MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) #endif #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF # ifndef MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE # define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) // 0 - implies dynamic allocation # endif #endif // Whether to provide the mp_kbd_exception object, and micropython.kbd_intr function #ifndef MICROPY_KBD_EXCEPTION #define MICROPY_KBD_EXCEPTION (0) #endif // Prefer to raise KeyboardInterrupt asynchronously (from signal or interrupt // handler) - if supported by a particular port. #ifndef MICROPY_ASYNC_KBD_INTR #define MICROPY_ASYNC_KBD_INTR (0) #endif // Whether to include REPL helper function #ifndef MICROPY_HELPER_REPL #define MICROPY_HELPER_REPL (0) #endif // Whether to include emacs-style readline behavior in REPL #ifndef MICROPY_REPL_EMACS_KEYS #define MICROPY_REPL_EMACS_KEYS (0) #endif // Whether to implement auto-indent in REPL #ifndef MICROPY_REPL_AUTO_INDENT #define MICROPY_REPL_AUTO_INDENT (0) #endif // Whether port requires event-driven REPL functions #ifndef MICROPY_REPL_EVENT_DRIVEN #define MICROPY_REPL_EVENT_DRIVEN (0) #endif // Whether to include lexer helper function for unix #ifndef MICROPY_HELPER_LEXER_UNIX #define MICROPY_HELPER_LEXER_UNIX (0) #endif // Long int implementation #define MICROPY_LONGINT_IMPL_NONE (0) #define MICROPY_LONGINT_IMPL_LONGLONG (1) #define MICROPY_LONGINT_IMPL_MPZ (2) #ifndef MICROPY_LONGINT_IMPL #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #endif #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG typedef long long mp_longint_impl_t; #endif // Whether to include information in the byte code to determine source // line number (increases RAM usage, but doesn't slow byte code execution) #ifndef MICROPY_ENABLE_SOURCE_LINE #define MICROPY_ENABLE_SOURCE_LINE (0) #endif // Whether to include doc strings (increases RAM usage) #ifndef MICROPY_ENABLE_DOC_STRING #define MICROPY_ENABLE_DOC_STRING (0) #endif // Exception messages are short static strings #define MICROPY_ERROR_REPORTING_TERSE (1) // Exception messages provide basic error details #define MICROPY_ERROR_REPORTING_NORMAL (2) // Exception messages provide full info, e.g. object names #define MICROPY_ERROR_REPORTING_DETAILED (3) #ifndef MICROPY_ERROR_REPORTING #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) #endif // Whether issue warnings during compiling/execution #ifndef MICROPY_WARNINGS #define MICROPY_WARNINGS (0) #endif // Whether to support warning categories #ifndef MICROPY_WARNINGS_CATEGORY #define MICROPY_WARNINGS_CATEGORY (0) #endif // This macro is used when printing runtime warnings and errors #ifndef MICROPY_ERROR_PRINTER #define MICROPY_ERROR_PRINTER (&mp_plat_print) #endif // Float and complex implementation #define MICROPY_FLOAT_IMPL_NONE (0) #define MICROPY_FLOAT_IMPL_FLOAT (1) #define MICROPY_FLOAT_IMPL_DOUBLE (2) #ifndef MICROPY_FLOAT_IMPL #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #endif #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #define MICROPY_PY_BUILTINS_FLOAT (1) #define MICROPY_FLOAT_CONST(x) x##F #define MICROPY_FLOAT_C_FUN(fun) fun##f typedef float mp_float_t; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #define MICROPY_PY_BUILTINS_FLOAT (1) #define MICROPY_FLOAT_CONST(x) x #define MICROPY_FLOAT_C_FUN(fun) fun typedef double mp_float_t; #else #define MICROPY_PY_BUILTINS_FLOAT (0) #endif #ifndef MICROPY_PY_BUILTINS_COMPLEX #define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT) #endif // Whether to provide a high-quality hash for float and complex numbers. // Otherwise the default is a very simple but correct hashing function. #ifndef MICROPY_FLOAT_HIGH_QUALITY_HASH #define MICROPY_FLOAT_HIGH_QUALITY_HASH (0) #endif // Enable features which improve CPython compatibility // but may lead to more code size/memory usage. // TODO: Originally intended as generic category to not // add bunch of once-off options. May need refactoring later #ifndef MICROPY_CPYTHON_COMPAT #define MICROPY_CPYTHON_COMPAT (1) #endif // Perform full checks as done by CPython. Disabling this // may produce incorrect results, if incorrect data is fed, // but should not lead to MicroPython crashes or similar // grave issues (in other words, only user app should be, // affected, not system). #ifndef MICROPY_FULL_CHECKS #define MICROPY_FULL_CHECKS (1) #endif // Whether POSIX-semantics non-blocking streams are supported #ifndef MICROPY_STREAMS_NON_BLOCK #define MICROPY_STREAMS_NON_BLOCK (0) #endif // Whether to provide stream functions with POSIX-like signatures // (useful for porting existing libraries to MicroPython). #ifndef MICROPY_STREAMS_POSIX_API #define MICROPY_STREAMS_POSIX_API (0) #endif // Whether to call __init__ when importing builtin modules for the first time #ifndef MICROPY_MODULE_BUILTIN_INIT #define MICROPY_MODULE_BUILTIN_INIT (0) #endif // Whether to support module-level __getattr__ (see PEP 562) #ifndef MICROPY_MODULE_GETATTR #define MICROPY_MODULE_GETATTR (0) #endif // Whether module weak links are supported #ifndef MICROPY_MODULE_WEAK_LINKS #define MICROPY_MODULE_WEAK_LINKS (0) #endif // Whether frozen modules are supported in the form of strings #ifndef MICROPY_MODULE_FROZEN_STR #define MICROPY_MODULE_FROZEN_STR (0) #endif // Whether frozen modules are supported in the form of .mpy files #ifndef MICROPY_MODULE_FROZEN_MPY #define MICROPY_MODULE_FROZEN_MPY (0) #endif // Convenience macro for whether frozen modules are supported #ifndef MICROPY_MODULE_FROZEN #define MICROPY_MODULE_FROZEN (MICROPY_MODULE_FROZEN_STR || MICROPY_MODULE_FROZEN_MPY) #endif // Whether you can override builtins in the builtins module #ifndef MICROPY_CAN_OVERRIDE_BUILTINS #define MICROPY_CAN_OVERRIDE_BUILTINS (0) #endif // Whether to check that the "self" argument of a builtin method has the // correct type. Such an explicit check is only needed if a builtin // method escapes to Python land without a first argument, eg // list.append([], 1). Without this check such calls will have undefined // behaviour (usually segfault) if the first argument is the wrong type. #ifndef MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1) #endif // Whether to use internally defined errno's (otherwise system provided ones) #ifndef MICROPY_USE_INTERNAL_ERRNO #define MICROPY_USE_INTERNAL_ERRNO (0) #endif // Whether to use internally defined *printf() functions (otherwise external ones) #ifndef MICROPY_USE_INTERNAL_PRINTF #define MICROPY_USE_INTERNAL_PRINTF (1) #endif // Support for internal scheduler #ifndef MICROPY_ENABLE_SCHEDULER #define MICROPY_ENABLE_SCHEDULER (0) #endif // Maximum number of entries in the scheduler #ifndef MICROPY_SCHEDULER_DEPTH #define MICROPY_SCHEDULER_DEPTH (4) #endif // Support for generic VFS sub-system #ifndef MICROPY_VFS #define MICROPY_VFS (0) #endif // Support for VFS POSIX component, to mount a POSIX filesystem within VFS #ifndef MICROPY_VFS #define MICROPY_VFS_POSIX (0) #endif // Support for VFS FAT component, to mount a FAT filesystem within VFS #ifndef MICROPY_VFS #define MICROPY_VFS_FAT (0) #endif /*****************************************************************************/ /* Fine control over Python builtins, classes, modules, etc */ // Whether to support multiple inheritance of Python classes. Multiple // inheritance makes some C functions inherently recursive, and adds a bit of // code overhead. #ifndef MICROPY_MULTIPLE_INHERITANCE #define MICROPY_MULTIPLE_INHERITANCE (1) #endif // Whether to implement attributes on functions #ifndef MICROPY_PY_FUNCTION_ATTRS #define MICROPY_PY_FUNCTION_ATTRS (0) #endif // Whether to support the descriptors __get__, __set__, __delete__ // This costs some code size and makes load/store/delete of instance // attributes slower for the classes that use this feature #ifndef MICROPY_PY_DESCRIPTORS #define MICROPY_PY_DESCRIPTORS (0) #endif // Whether to support class __delattr__ and __setattr__ methods // This costs some code size and makes store/delete of instance // attributes slower for the classes that use this feature #ifndef MICROPY_PY_DELATTR_SETATTR #define MICROPY_PY_DELATTR_SETATTR (0) #endif // Support for async/await/async for/async with #ifndef MICROPY_PY_ASYNC_AWAIT #define MICROPY_PY_ASYNC_AWAIT (1) #endif // Non-standard .pend_throw() method for generators, allowing for // Future-like behavior with respect to exception handling: an // exception set with .pend_throw() will activate on the next call // to generator's .send() or .__next__(). (This is useful to implement // async schedulers.) #ifndef MICROPY_PY_GENERATOR_PEND_THROW #define MICROPY_PY_GENERATOR_PEND_THROW (1) #endif // Issue a warning when comparing str and bytes objects #ifndef MICROPY_PY_STR_BYTES_CMP_WARN #define MICROPY_PY_STR_BYTES_CMP_WARN (0) #endif // Whether str object is proper unicode #ifndef MICROPY_PY_BUILTINS_STR_UNICODE #define MICROPY_PY_BUILTINS_STR_UNICODE (0) #endif // Whether to check for valid UTF-8 when converting bytes to str #ifndef MICROPY_PY_BUILTINS_STR_UNICODE_CHECK #define MICROPY_PY_BUILTINS_STR_UNICODE_CHECK (MICROPY_PY_BUILTINS_STR_UNICODE) #endif // Whether str.center() method provided #ifndef MICROPY_PY_BUILTINS_STR_CENTER #define MICROPY_PY_BUILTINS_STR_CENTER (0) #endif // Whether str.count() method provided #ifndef MICROPY_PY_BUILTINS_STR_COUNT #define MICROPY_PY_BUILTINS_STR_COUNT (1) #endif // Whether str % (...) formatting operator provided #ifndef MICROPY_PY_BUILTINS_STR_OP_MODULO #define MICROPY_PY_BUILTINS_STR_OP_MODULO (1) #endif // Whether str.partition()/str.rpartition() method provided #ifndef MICROPY_PY_BUILTINS_STR_PARTITION #define MICROPY_PY_BUILTINS_STR_PARTITION (0) #endif // Whether str.splitlines() method provided #ifndef MICROPY_PY_BUILTINS_STR_SPLITLINES #define MICROPY_PY_BUILTINS_STR_SPLITLINES (0) #endif // Whether to support bytearray object #ifndef MICROPY_PY_BUILTINS_BYTEARRAY #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #endif // Whether to support dict.fromkeys() class method #ifndef MICROPY_PY_BUILTINS_DICT_FROMKEYS #define MICROPY_PY_BUILTINS_DICT_FROMKEYS (1) #endif // Whether to support memoryview object #ifndef MICROPY_PY_BUILTINS_MEMORYVIEW #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) #endif // Whether to support memoryview.itemsize attribute #ifndef MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE #define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (0) #endif // Whether to support set object #ifndef MICROPY_PY_BUILTINS_SET #define MICROPY_PY_BUILTINS_SET (1) #endif // Whether to support slice subscript operators and slice object #ifndef MICROPY_PY_BUILTINS_SLICE #define MICROPY_PY_BUILTINS_SLICE (1) #endif // Whether to support slice attribute read access, // i.e. slice.start, slice.stop, slice.step #ifndef MICROPY_PY_BUILTINS_SLICE_ATTRS #define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) #endif // Whether to support frozenset object #ifndef MICROPY_PY_BUILTINS_FROZENSET #define MICROPY_PY_BUILTINS_FROZENSET (0) #endif // Whether to support property object #ifndef MICROPY_PY_BUILTINS_PROPERTY #define MICROPY_PY_BUILTINS_PROPERTY (1) #endif // Whether to implement the start/stop/step attributes (readback) on // the "range" builtin type. Rarely used, and costs ~60 bytes (x86). #ifndef MICROPY_PY_BUILTINS_RANGE_ATTRS #define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) #endif // Whether to support binary ops [only (in)equality is defined] between range // objects. With this option disabled all range objects that are not exactly // the same object will compare as not-equal. With it enabled the semantics // match CPython and ranges are equal if they yield the same sequence of items. #ifndef MICROPY_PY_BUILTINS_RANGE_BINOP #define MICROPY_PY_BUILTINS_RANGE_BINOP (0) #endif // Support for callling next() with second argument #ifndef MICROPY_PY_BUILTINS_NEXT2 #define MICROPY_PY_BUILTINS_NEXT2 (0) #endif // Whether to support rounding of integers (incl bignum); eg round(123,-1)=120 #ifndef MICROPY_PY_BUILTINS_ROUND_INT #define MICROPY_PY_BUILTINS_ROUND_INT (0) #endif // Whether to support timeout exceptions (like socket.timeout) #ifndef MICROPY_PY_BUILTINS_TIMEOUTERROR #define MICROPY_PY_BUILTINS_TIMEOUTERROR (0) #endif // Whether to support complete set of special methods for user // classes, or only the most used ones. "Inplace" methods are // controlled by MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS below. // "Reverse" methods are controlled by // MICROPY_PY_REVERSE_SPECIAL_METHODS below. #ifndef MICROPY_PY_ALL_SPECIAL_METHODS #define MICROPY_PY_ALL_SPECIAL_METHODS (0) #endif // Whether to support all inplace arithmetic operarion methods // (__imul__, etc.) #ifndef MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS #define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (0) #endif // Whether to support reverse arithmetic operarion methods // (__radd__, etc.). Additionally gated by // MICROPY_PY_ALL_SPECIAL_METHODS. #ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS #define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) #endif // Whether to support compile function #ifndef MICROPY_PY_BUILTINS_COMPILE #define MICROPY_PY_BUILTINS_COMPILE (0) #endif // Whether to support enumerate function(type) #ifndef MICROPY_PY_BUILTINS_ENUMERATE #define MICROPY_PY_BUILTINS_ENUMERATE (1) #endif // Whether to support eval and exec functions // By default they are supported if the compiler is enabled #ifndef MICROPY_PY_BUILTINS_EVAL_EXEC #define MICROPY_PY_BUILTINS_EVAL_EXEC (MICROPY_ENABLE_COMPILER) #endif // Whether to support the Python 2 execfile function #ifndef MICROPY_PY_BUILTINS_EXECFILE #define MICROPY_PY_BUILTINS_EXECFILE (0) #endif // Whether to support filter function(type) #ifndef MICROPY_PY_BUILTINS_FILTER #define MICROPY_PY_BUILTINS_FILTER (1) #endif // Whether to support reversed function(type) #ifndef MICROPY_PY_BUILTINS_REVERSED #define MICROPY_PY_BUILTINS_REVERSED (1) #endif // Whether to define "NotImplemented" special constant #ifndef MICROPY_PY_BUILTINS_NOTIMPLEMENTED #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0) #endif // Whether to provide the built-in input() function. The implementation of this // uses mp-readline, so can only be enabled if the port uses this readline. #ifndef MICROPY_PY_BUILTINS_INPUT #define MICROPY_PY_BUILTINS_INPUT (0) #endif // Whether to support min/max functions #ifndef MICROPY_PY_BUILTINS_MIN_MAX #define MICROPY_PY_BUILTINS_MIN_MAX (1) #endif // Support for calls to pow() with 3 integer arguments #ifndef MICROPY_PY_BUILTINS_POW3 #define MICROPY_PY_BUILTINS_POW3 (0) #endif // Whether to provide the help function #ifndef MICROPY_PY_BUILTINS_HELP #define MICROPY_PY_BUILTINS_HELP (0) #endif // Use this to configure the help text shown for help(). It should be a // variable with the type "const char*". A sensible default is provided. #ifndef MICROPY_PY_BUILTINS_HELP_TEXT #define MICROPY_PY_BUILTINS_HELP_TEXT mp_help_default_text #endif // Add the ability to list the available modules when executing help('modules') #ifndef MICROPY_PY_BUILTINS_HELP_MODULES #define MICROPY_PY_BUILTINS_HELP_MODULES (0) #endif // Whether to set __file__ for imported modules #ifndef MICROPY_PY___FILE__ #define MICROPY_PY___FILE__ (1) #endif // Whether to provide mem-info related functions in micropython module #ifndef MICROPY_PY_MICROPYTHON_MEM_INFO #define MICROPY_PY_MICROPYTHON_MEM_INFO (0) #endif // Whether to provide "micropython.stack_use" function #ifndef MICROPY_PY_MICROPYTHON_STACK_USE #define MICROPY_PY_MICROPYTHON_STACK_USE (MICROPY_PY_MICROPYTHON_MEM_INFO) #endif // Whether to provide "array" module. Note that large chunk of the // underlying code is shared with "bytearray" builtin type, so to // get real savings, it should be disabled too. #ifndef MICROPY_PY_ARRAY #define MICROPY_PY_ARRAY (1) #endif // Whether to support slice assignments for array (and bytearray). // This is rarely used, but adds ~0.5K of code. #ifndef MICROPY_PY_ARRAY_SLICE_ASSIGN #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) #endif // Whether to support attrtuple type (MicroPython extension) // It provides space-efficient tuples with attribute access #ifndef MICROPY_PY_ATTRTUPLE #define MICROPY_PY_ATTRTUPLE (1) #endif // Whether to provide "collections" module #ifndef MICROPY_PY_COLLECTIONS #define MICROPY_PY_COLLECTIONS (1) #endif // Whether to provide "ucollections.deque" type #ifndef MICROPY_PY_COLLECTIONS_DEQUE #define MICROPY_PY_COLLECTIONS_DEQUE (0) #endif // Whether to provide "collections.OrderedDict" type #ifndef MICROPY_PY_COLLECTIONS_ORDEREDDICT #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) #endif // Whether to provide the _asdict function for namedtuple #ifndef MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT #define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (0) #endif // Whether to provide "math" module #ifndef MICROPY_PY_MATH #define MICROPY_PY_MATH (1) #endif // Whether to provide special math functions: math.{erf,erfc,gamma,lgamma} #ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0) #endif // Whether to provide math.factorial function #ifndef MICROPY_PY_MATH_FACTORIAL #define MICROPY_PY_MATH_FACTORIAL (0) #endif // Whether to provide math.isclose function #ifndef MICROPY_PY_MATH_ISCLOSE #define MICROPY_PY_MATH_ISCLOSE (0) #endif // Whether to provide "cmath" module #ifndef MICROPY_PY_CMATH #define MICROPY_PY_CMATH (0) #endif // Whether to provide "gc" module #ifndef MICROPY_PY_GC #define MICROPY_PY_GC (1) #endif // Whether to return number of collected objects from gc.collect() #ifndef MICROPY_PY_GC_COLLECT_RETVAL #define MICROPY_PY_GC_COLLECT_RETVAL (0) #endif // Whether to provide "io" module #ifndef MICROPY_PY_IO #define MICROPY_PY_IO (1) #endif // Whether to provide "io.IOBase" class to support user streams #ifndef MICROPY_PY_IO_IOBASE #define MICROPY_PY_IO_IOBASE (0) #endif // Whether to provide "uio.resource_stream()" function with // the semantics of CPython's pkg_resources.resource_stream() // (allows to access binary resources in frozen source packages). // Note that the same functionality can be achieved in "pure // Python" by prepocessing binary resources into Python source // and bytecode-freezing it (with a simple helper module available // e.g. in micropython-lib). #ifndef MICROPY_PY_IO_RESOURCE_STREAM #define MICROPY_PY_IO_RESOURCE_STREAM (0) #endif // Whether to provide "io.FileIO" class #ifndef MICROPY_PY_IO_FILEIO #define MICROPY_PY_IO_FILEIO (0) #endif // Whether to provide "io.BytesIO" class #ifndef MICROPY_PY_IO_BYTESIO #define MICROPY_PY_IO_BYTESIO (1) #endif // Whether to provide "io.BufferedWriter" class #ifndef MICROPY_PY_IO_BUFFEREDWRITER #define MICROPY_PY_IO_BUFFEREDWRITER (0) #endif // Whether to provide "struct" module #ifndef MICROPY_PY_STRUCT #define MICROPY_PY_STRUCT (1) #endif // Whether to provide "sys" module #ifndef MICROPY_PY_SYS #define MICROPY_PY_SYS (1) #endif // Whether to provide "sys.maxsize" constant #ifndef MICROPY_PY_SYS_MAXSIZE #define MICROPY_PY_SYS_MAXSIZE (0) #endif // Whether to provide "sys.modules" dictionary #ifndef MICROPY_PY_SYS_MODULES #define MICROPY_PY_SYS_MODULES (1) #endif // Whether to provide "sys.exc_info" function // Avoid enabling this, this function is Python2 heritage #ifndef MICROPY_PY_SYS_EXC_INFO #define MICROPY_PY_SYS_EXC_INFO (0) #endif // Whether to provide "sys.exit" function #ifndef MICROPY_PY_SYS_EXIT #define MICROPY_PY_SYS_EXIT (1) #endif // Whether to provide "sys.atexit" function (MicroPython extension) #ifndef MICROPY_PY_SYS_ATEXIT #define MICROPY_PY_SYS_ATEXIT (0) #endif // Whether to provide "sys.settrace" function #ifndef MICROPY_PY_SYS_SETTRACE #define MICROPY_PY_SYS_SETTRACE (0) #endif // Whether to provide "sys.getsizeof" function #ifndef MICROPY_PY_SYS_GETSIZEOF #define MICROPY_PY_SYS_GETSIZEOF (0) #endif // Whether to provide sys.{stdin,stdout,stderr} objects #ifndef MICROPY_PY_SYS_STDFILES #define MICROPY_PY_SYS_STDFILES (0) #endif // Whether to provide sys.{stdin,stdout,stderr}.buffer object // This is implemented per-port #ifndef MICROPY_PY_SYS_STDIO_BUFFER #define MICROPY_PY_SYS_STDIO_BUFFER (0) #endif // Whether to provide "uerrno" module #ifndef MICROPY_PY_UERRNO #define MICROPY_PY_UERRNO (0) #endif // Whether to provide the uerrno.errorcode dict #ifndef MICROPY_PY_UERRNO_ERRORCODE #define MICROPY_PY_UERRNO_ERRORCODE (1) #endif // Whether to provide "uselect" module (baremetal implementation) #ifndef MICROPY_PY_USELECT #define MICROPY_PY_USELECT (0) #endif // Whether to provide "utime" module functions implementation // in terms of mp_hal_* functions. #ifndef MICROPY_PY_UTIME_MP_HAL #define MICROPY_PY_UTIME_MP_HAL (0) #endif // Period of values returned by utime.ticks_ms(), ticks_us(), ticks_cpu() // functions. Should be power of two. All functions above use the same // period, so if underlying hardware/API has different periods, the // minimum of them should be used. The value below is the maximum value // this parameter can take (corresponding to 30 bit tick values on 32-bit // system). #ifndef MICROPY_PY_UTIME_TICKS_PERIOD #define MICROPY_PY_UTIME_TICKS_PERIOD (MP_SMALL_INT_POSITIVE_MASK + 1) #endif // Whether to provide "_thread" module #ifndef MICROPY_PY_THREAD #define MICROPY_PY_THREAD (0) #endif // Whether to make the VM/runtime thread-safe using a global lock // If not enabled then thread safety must be provided at the Python level #ifndef MICROPY_PY_THREAD_GIL #define MICROPY_PY_THREAD_GIL (MICROPY_PY_THREAD) #endif // Number of VM jump-loops to do before releasing the GIL. // Set this to 0 to disable the divisor. #ifndef MICROPY_PY_THREAD_GIL_VM_DIVISOR #define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) #endif // Extended modules #ifndef MICROPY_PY_UCTYPES #define MICROPY_PY_UCTYPES (0) #endif // Whether to provide SHORT, INT, LONG, etc. types in addition to // exact-bitness types like INT16, INT32, etc. #ifndef MICROPY_PY_UCTYPES_NATIVE_C_TYPES #define MICROPY_PY_UCTYPES_NATIVE_C_TYPES (1) #endif #ifndef MICROPY_PY_UZLIB #define MICROPY_PY_UZLIB (0) #endif #ifndef MICROPY_PY_UJSON #define MICROPY_PY_UJSON (0) #endif #ifndef MICROPY_PY_URE #define MICROPY_PY_URE (0) #endif #ifndef MICROPY_PY_URE_DEBUG #define MICROPY_PY_URE_DEBUG (0) #endif #ifndef MICROPY_PY_URE_MATCH_GROUPS #define MICROPY_PY_URE_MATCH_GROUPS (0) #endif #ifndef MICROPY_PY_URE_MATCH_SPAN_START_END #define MICROPY_PY_URE_MATCH_SPAN_START_END (0) #endif #ifndef MICROPY_PY_URE_SUB #define MICROPY_PY_URE_SUB (0) #endif #ifndef MICROPY_PY_UHEAPQ #define MICROPY_PY_UHEAPQ (0) #endif // Optimized heap queue for relative timestamps #ifndef MICROPY_PY_UTIMEQ #define MICROPY_PY_UTIMEQ (0) #endif #ifndef MICROPY_PY_UHASHLIB #define MICROPY_PY_UHASHLIB (0) #endif #ifndef MICROPY_PY_UHASHLIB_MD5 #define MICROPY_PY_UHASHLIB_MD5 (0) #endif #ifndef MICROPY_PY_UHASHLIB_SHA1 #define MICROPY_PY_UHASHLIB_SHA1 (0) #endif #ifndef MICROPY_PY_UHASHLIB_SHA256 #define MICROPY_PY_UHASHLIB_SHA256 (1) #endif #ifndef MICROPY_PY_UCRYPTOLIB #define MICROPY_PY_UCRYPTOLIB (0) #endif // Depends on MICROPY_PY_UCRYPTOLIB #ifndef MICROPY_PY_UCRYPTOLIB_CTR #define MICROPY_PY_UCRYPTOLIB_CTR (0) #endif #ifndef MICROPY_PY_UCRYPTOLIB_CONSTS #define MICROPY_PY_UCRYPTOLIB_CONSTS (0) #endif #ifndef MICROPY_PY_UBINASCII #define MICROPY_PY_UBINASCII (0) #endif // Depends on MICROPY_PY_UZLIB #ifndef MICROPY_PY_UBINASCII_CRC32 #define MICROPY_PY_UBINASCII_CRC32 (0) #endif #ifndef MICROPY_PY_URANDOM #define MICROPY_PY_URANDOM (0) #endif // Whether to include: randrange, randint, choice, random, uniform #ifndef MICROPY_PY_URANDOM_EXTRA_FUNCS #define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) #endif #ifndef MICROPY_PY_MACHINE #define MICROPY_PY_MACHINE (0) #endif // Whether to include: time_pulse_us #ifndef MICROPY_PY_MACHINE_PULSE #define MICROPY_PY_MACHINE_PULSE (0) #endif #ifndef MICROPY_PY_MACHINE_I2C #define MICROPY_PY_MACHINE_I2C (0) #endif #ifndef MICROPY_PY_MACHINE_SPI #define MICROPY_PY_MACHINE_SPI (0) #endif #ifndef MICROPY_PY_USSL #define MICROPY_PY_USSL (0) // Whether to add finaliser code to ussl objects #define MICROPY_PY_USSL_FINALISER (0) #endif #ifndef MICROPY_PY_UWEBSOCKET #define MICROPY_PY_UWEBSOCKET (0) #endif #ifndef MICROPY_PY_FRAMEBUF #define MICROPY_PY_FRAMEBUF (0) #endif #ifndef MICROPY_PY_BTREE #define MICROPY_PY_BTREE (0) #endif /*****************************************************************************/ /* Hooks for a port to add builtins */ // Additional builtin function definitions - see modbuiltins.c:mp_module_builtins_globals_table for format. #ifndef MICROPY_PORT_BUILTINS #define MICROPY_PORT_BUILTINS #endif // Additional builtin module definitions - see objmodule.c:mp_builtin_module_table for format. #ifndef MICROPY_PORT_BUILTIN_MODULES #define MICROPY_PORT_BUILTIN_MODULES #endif // Additional constant definitions for the compiler - see compile.c:mp_constants_table. #ifndef MICROPY_PORT_CONSTANTS #define MICROPY_PORT_CONSTANTS #endif // Any root pointers for GC scanning - see mpstate.c #ifndef MICROPY_PORT_ROOT_POINTERS #define MICROPY_PORT_ROOT_POINTERS #endif /*****************************************************************************/ /* Miscellaneous settings */ // All uPy objects in ROM must be aligned on at least a 4 byte boundary // so that the small-int/qstr/pointer distinction can be made. For machines // that don't do this (eg 16-bit CPU), define the following macro to something // like __attribute__((aligned(4))). #ifndef MICROPY_OBJ_BASE_ALIGNMENT #define MICROPY_OBJ_BASE_ALIGNMENT #endif // On embedded platforms, these will typically enable/disable irqs. #ifndef MICROPY_BEGIN_ATOMIC_SECTION #define MICROPY_BEGIN_ATOMIC_SECTION() (0) #endif #ifndef MICROPY_END_ATOMIC_SECTION #define MICROPY_END_ATOMIC_SECTION(state) (void)(state) #endif // Allow to override static modifier for global objects, e.g. to use with // object code analysis tools which don't support static symbols. #ifndef STATIC #define STATIC static #endif // Number of bytes in a word #ifndef BYTES_PER_WORD #define BYTES_PER_WORD (sizeof(mp_uint_t)) #endif #define BITS_PER_BYTE (8) #define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD) // mp_int_t value with most significant bit set #define WORD_MSBIT_HIGH (((mp_uint_t)1) << (BYTES_PER_WORD * 8 - 1)) // Make sure both MP_ENDIANNESS_LITTLE and MP_ENDIANNESS_BIG are // defined and that they are the opposite of each other. #if defined(MP_ENDIANNESS_LITTLE) #define MP_ENDIANNESS_BIG (!MP_ENDIANNESS_LITTLE) #elif defined(MP_ENDIANNESS_BIG) #define MP_ENDIANNESS_LITTLE (!MP_ENDIANNESS_BIG) #else // Endianness not defined by port so try to autodetect it. #if defined(__BYTE_ORDER__) #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define MP_ENDIANNESS_LITTLE (1) #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define MP_ENDIANNESS_LITTLE (0) #endif #else #include #if defined(__BYTE_ORDER) #if __BYTE_ORDER == __LITTLE_ENDIAN #define MP_ENDIANNESS_LITTLE (1) #elif __BYTE_ORDER == __BIG_ENDIAN #define MP_ENDIANNESS_LITTLE (0) #endif #endif #endif #ifndef MP_ENDIANNESS_LITTLE #error endianness not defined and cannot detect it #endif #define MP_ENDIANNESS_BIG (!MP_ENDIANNESS_LITTLE) #endif // Make a pointer to RAM callable (eg set lower bit for Thumb code) // (This scheme won't work if we want to mix Thumb and normal ARM code.) #ifndef MICROPY_MAKE_POINTER_CALLABLE #define MICROPY_MAKE_POINTER_CALLABLE(p) (p) #endif // If these MP_PLAT_*_EXEC macros are overridden then the memory allocated by them // must be somehow reachable for marking by the GC, since the native code // generators store pointers to GC managed memory in the code. #ifndef MP_PLAT_ALLOC_EXEC #define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) do { *ptr = m_new(byte, min_size); *size = min_size; } while (0) #endif #ifndef MP_PLAT_FREE_EXEC #define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size) #endif // This macro is used to do all output (except when MICROPY_PY_IO is defined) #ifndef MP_PLAT_PRINT_STRN #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #endif #ifndef MP_SSIZE_MAX #define MP_SSIZE_MAX SSIZE_MAX #endif // printf format spec to use for mp_int_t and friends #ifndef INT_FMT #if defined(__LP64__) // Archs where mp_int_t == long, long != int #define UINT_FMT "%lu" #define INT_FMT "%ld" #elif defined(_WIN64) #define UINT_FMT "%llu" #define INT_FMT "%lld" #else // Archs where mp_int_t == int #define UINT_FMT "%u" #define INT_FMT "%d" #endif #endif //INT_FMT // Modifier for function which doesn't return #ifndef NORETURN #define NORETURN __attribute__((noreturn)) #endif // Modifier for weak functions #ifndef MP_WEAK #define MP_WEAK __attribute__((weak)) #endif // Modifier for functions which should be never inlined #ifndef MP_NOINLINE #define MP_NOINLINE __attribute__((noinline)) #endif // Modifier for functions which should be always inlined #ifndef MP_ALWAYSINLINE #define MP_ALWAYSINLINE __attribute__((always_inline)) #endif // Condition is likely to be true, to help branch prediction #ifndef MP_LIKELY #define MP_LIKELY(x) __builtin_expect((x), 1) #endif // Condition is likely to be false, to help branch prediction #ifndef MP_UNLIKELY #define MP_UNLIKELY(x) __builtin_expect((x), 0) #endif // To annotate that code is unreachable #ifndef MP_UNREACHABLE #if defined(__GNUC__) #define MP_UNREACHABLE __builtin_unreachable(); #else #define MP_UNREACHABLE for (;;); #endif #endif #ifndef MP_HTOBE16 #if MP_ENDIANNESS_LITTLE # define MP_HTOBE16(x) ((uint16_t)( (((x) & 0xff) << 8) | (((x) >> 8) & 0xff) )) # define MP_BE16TOH(x) MP_HTOBE16(x) #else # define MP_HTOBE16(x) (x) # define MP_BE16TOH(x) (x) #endif #endif #ifndef MP_HTOBE32 #if MP_ENDIANNESS_LITTLE # define MP_HTOBE32(x) ((uint32_t)( (((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) >> 8) & 0xff00) | (((x) >> 24) & 0xff) )) # define MP_BE32TOH(x) MP_HTOBE32(x) #else # define MP_HTOBE32(x) (x) # define MP_BE32TOH(x) (x) #endif #endif // Warning categories are by default implemented as strings, though // hook is left for a port to define them as something else. #if MICROPY_WARNINGS_CATEGORY # ifndef MP_WARN_CAT # define MP_WARN_CAT(x) #x # endif #else # undef MP_WARN_CAT # define MP_WARN_CAT(x) (NULL) #endif // Feature dependency check. #if MICROPY_PY_SYS_SETTRACE #if !MICROPY_PERSISTENT_CODE_SAVE #error "MICROPY_PY_SYS_SETTRACE requires MICROPY_PERSISTENT_CODE_SAVE to be enabled" #endif #if MICROPY_COMP_CONST #error "MICROPY_PY_SYS_SETTRACE requires MICROPY_COMP_CONST to be disabled" #endif #endif #endif // MICROPY_INCLUDED_PY_MPCONFIG_H micropython-1.12/py/mperrno.h000066400000000000000000000141371357706137100163130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_MPERRNO_H #define MICROPY_INCLUDED_PY_MPERRNO_H #include "py/mpconfig.h" #if MICROPY_USE_INTERNAL_ERRNO // MP_Exxx errno's are defined directly as numeric values // (Linux constants are used as a reference) #define MP_EPERM (1) // Operation not permitted #define MP_ENOENT (2) // No such file or directory #define MP_ESRCH (3) // No such process #define MP_EINTR (4) // Interrupted system call #define MP_EIO (5) // I/O error #define MP_ENXIO (6) // No such device or address #define MP_E2BIG (7) // Argument list too long #define MP_ENOEXEC (8) // Exec format error #define MP_EBADF (9) // Bad file number #define MP_ECHILD (10) // No child processes #define MP_EAGAIN (11) // Try again #define MP_ENOMEM (12) // Out of memory #define MP_EACCES (13) // Permission denied #define MP_EFAULT (14) // Bad address #define MP_ENOTBLK (15) // Block device required #define MP_EBUSY (16) // Device or resource busy #define MP_EEXIST (17) // File exists #define MP_EXDEV (18) // Cross-device link #define MP_ENODEV (19) // No such device #define MP_ENOTDIR (20) // Not a directory #define MP_EISDIR (21) // Is a directory #define MP_EINVAL (22) // Invalid argument #define MP_ENFILE (23) // File table overflow #define MP_EMFILE (24) // Too many open files #define MP_ENOTTY (25) // Not a typewriter #define MP_ETXTBSY (26) // Text file busy #define MP_EFBIG (27) // File too large #define MP_ENOSPC (28) // No space left on device #define MP_ESPIPE (29) // Illegal seek #define MP_EROFS (30) // Read-only file system #define MP_EMLINK (31) // Too many links #define MP_EPIPE (32) // Broken pipe #define MP_EDOM (33) // Math argument out of domain of func #define MP_ERANGE (34) // Math result not representable #define MP_EWOULDBLOCK MP_EAGAIN // Operation would block #define MP_EOPNOTSUPP (95) // Operation not supported on transport endpoint #define MP_EAFNOSUPPORT (97) // Address family not supported by protocol #define MP_EADDRINUSE (98) // Address already in use #define MP_ECONNABORTED (103) // Software caused connection abort #define MP_ECONNRESET (104) // Connection reset by peer #define MP_ENOBUFS (105) // No buffer space available #define MP_EISCONN (106) // Transport endpoint is already connected #define MP_ENOTCONN (107) // Transport endpoint is not connected #define MP_ETIMEDOUT (110) // Connection timed out #define MP_ECONNREFUSED (111) // Connection refused #define MP_EHOSTUNREACH (113) // No route to host #define MP_EALREADY (114) // Operation already in progress #define MP_EINPROGRESS (115) // Operation now in progress #else // MP_Exxx errno's are defined in terms of system supplied ones #include #define MP_EPERM EPERM #define MP_ENOENT ENOENT #define MP_ESRCH ESRCH #define MP_EINTR EINTR #define MP_EIO EIO #define MP_ENXIO ENXIO #define MP_E2BIG E2BIG #define MP_ENOEXEC ENOEXEC #define MP_EBADF EBADF #define MP_ECHILD ECHILD #define MP_EAGAIN EAGAIN #define MP_ENOMEM ENOMEM #define MP_EACCES EACCES #define MP_EFAULT EFAULT #define MP_ENOTBLK ENOTBLK #define MP_EBUSY EBUSY #define MP_EEXIST EEXIST #define MP_EXDEV EXDEV #define MP_ENODEV ENODEV #define MP_ENOTDIR ENOTDIR #define MP_EISDIR EISDIR #define MP_EINVAL EINVAL #define MP_ENFILE ENFILE #define MP_EMFILE EMFILE #define MP_ENOTTY ENOTTY #define MP_ETXTBSY ETXTBSY #define MP_EFBIG EFBIG #define MP_ENOSPC ENOSPC #define MP_ESPIPE ESPIPE #define MP_EROFS EROFS #define MP_EMLINK EMLINK #define MP_EPIPE EPIPE #define MP_EDOM EDOM #define MP_ERANGE ERANGE #define MP_EWOULDBLOCK EWOULDBLOCK #define MP_EOPNOTSUPP EOPNOTSUPP #define MP_EAFNOSUPPORT EAFNOSUPPORT #define MP_EADDRINUSE EADDRINUSE #define MP_ECONNABORTED ECONNABORTED #define MP_ECONNRESET ECONNRESET #define MP_ENOBUFS ENOBUFS #define MP_EISCONN EISCONN #define MP_ENOTCONN ENOTCONN #define MP_ETIMEDOUT ETIMEDOUT #define MP_ECONNREFUSED ECONNREFUSED #define MP_EHOSTUNREACH EHOSTUNREACH #define MP_EALREADY EALREADY #define MP_EINPROGRESS EINPROGRESS #endif #if MICROPY_PY_UERRNO #include "py/obj.h" qstr mp_errno_to_str(mp_obj_t errno_val); #endif #endif // MICROPY_INCLUDED_PY_MPERRNO_H micropython-1.12/py/mphal.h000066400000000000000000000050101357706137100157200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_MPHAL_H #define MICROPY_INCLUDED_PY_MPHAL_H #include "py/mpconfig.h" #ifdef MICROPY_MPHALPORT_H #include MICROPY_MPHALPORT_H #else #include #endif #ifndef mp_hal_stdio_poll uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags); #endif #ifndef mp_hal_stdin_rx_chr int mp_hal_stdin_rx_chr(void); #endif #ifndef mp_hal_stdout_tx_str void mp_hal_stdout_tx_str(const char *str); #endif #ifndef mp_hal_stdout_tx_strn void mp_hal_stdout_tx_strn(const char *str, size_t len); #endif #ifndef mp_hal_stdout_tx_strn_cooked void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len); #endif #ifndef mp_hal_delay_ms void mp_hal_delay_ms(mp_uint_t ms); #endif #ifndef mp_hal_delay_us void mp_hal_delay_us(mp_uint_t us); #endif #ifndef mp_hal_ticks_ms mp_uint_t mp_hal_ticks_ms(void); #endif #ifndef mp_hal_ticks_us mp_uint_t mp_hal_ticks_us(void); #endif #ifndef mp_hal_ticks_cpu mp_uint_t mp_hal_ticks_cpu(void); #endif // If port HAL didn't define its own pin API, use generic // "virtual pin" API from the core. #ifndef mp_hal_pin_obj_t #define mp_hal_pin_obj_t mp_obj_t #define mp_hal_get_pin_obj(pin) (pin) #define mp_hal_pin_read(pin) mp_virtual_pin_read(pin) #define mp_hal_pin_write(pin, v) mp_virtual_pin_write(pin, v) #include "extmod/virtpin.h" #endif #endif // MICROPY_INCLUDED_PY_MPHAL_H micropython-1.12/py/mpprint.c000066400000000000000000000425411357706137100163150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "py/mphal.h" #include "py/mpprint.h" #include "py/obj.h" #include "py/objint.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FLOAT #include "py/formatfloat.h" #endif static const char pad_spaces[] = " "; static const char pad_zeroes[] = "0000000000000000"; STATIC void plat_print_strn(void *env, const char *str, size_t len) { (void)env; MP_PLAT_PRINT_STRN(str, len); } const mp_print_t mp_plat_print = {NULL, plat_print_strn}; int mp_print_str(const mp_print_t *print, const char *str) { size_t len = strlen(str); if (len) { print->print_strn(print->data, str, len); } return len; } int mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flags, char fill, int width) { int left_pad = 0; int right_pad = 0; int pad = width - len; int pad_size; int total_chars_printed = 0; const char *pad_chars; if (!fill || fill == ' ') { pad_chars = pad_spaces; pad_size = sizeof(pad_spaces) - 1; } else if (fill == '0') { pad_chars = pad_zeroes; pad_size = sizeof(pad_zeroes) - 1; } else { // Other pad characters are fairly unusual, so we'll take the hit // and output them 1 at a time. pad_chars = &fill; pad_size = 1; } if (flags & PF_FLAG_CENTER_ADJUST) { left_pad = pad / 2; right_pad = pad - left_pad; } else if (flags & PF_FLAG_LEFT_ADJUST) { right_pad = pad; } else { left_pad = pad; } if (left_pad > 0) { total_chars_printed += left_pad; while (left_pad > 0) { int p = left_pad; if (p > pad_size) { p = pad_size; } print->print_strn(print->data, pad_chars, p); left_pad -= p; } } if (len) { print->print_strn(print->data, str, len); total_chars_printed += len; } if (right_pad > 0) { total_chars_printed += right_pad; while (right_pad > 0) { int p = right_pad; if (p > pad_size) { p = pad_size; } print->print_strn(print->data, pad_chars, p); right_pad -= p; } } return total_chars_printed; } // 32-bits is 10 digits, add 3 for commas, 1 for sign, 1 for terminating null // We can use 16 characters for 32-bit and 32 characters for 64-bit #define INT_BUF_SIZE (sizeof(mp_int_t) * 4) // Our mp_vprintf function below does not support the '#' format modifier to // print the prefix of a non-base-10 number, so we don't need code for this. #define SUPPORT_INT_BASE_PREFIX (0) // This function is used exclusively by mp_vprintf to format ints. // It needs to be a separate function to mp_print_mp_int, since converting to a mp_int looses the MSB. STATIC int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) { char sign = 0; if (sgn) { if ((mp_int_t)x < 0) { sign = '-'; x = -x; } else if (flags & PF_FLAG_SHOW_SIGN) { sign = '+'; } else if (flags & PF_FLAG_SPACE_SIGN) { sign = ' '; } } char buf[INT_BUF_SIZE]; char *b = buf + INT_BUF_SIZE; if (x == 0) { *(--b) = '0'; } else { do { int c = x % base; x /= base; if (c >= 10) { c += base_char - 10; } else { c += '0'; } *(--b) = c; } while (b > buf && x != 0); } #if SUPPORT_INT_BASE_PREFIX char prefix_char = '\0'; if (flags & PF_FLAG_SHOW_PREFIX) { if (base == 2) { prefix_char = base_char + 'b' - 'a'; } else if (base == 8) { prefix_char = base_char + 'o' - 'a'; } else if (base == 16) { prefix_char = base_char + 'x' - 'a'; } } #endif int len = 0; if (flags & PF_FLAG_PAD_AFTER_SIGN) { if (sign) { len += mp_print_strn(print, &sign, 1, flags, fill, 1); width--; } #if SUPPORT_INT_BASE_PREFIX if (prefix_char) { len += mp_print_strn(print, "0", 1, flags, fill, 1); len += mp_print_strn(print, &prefix_char, 1, flags, fill, 1); width -= 2; } #endif } else { #if SUPPORT_INT_BASE_PREFIX if (prefix_char && b > &buf[1]) { *(--b) = prefix_char; *(--b) = '0'; } #endif if (sign && b > buf) { *(--b) = sign; } } len += mp_print_strn(print, b, buf + INT_BUF_SIZE - b, flags, fill, width); return len; } int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec) { // These are the only values for "base" that are required to be supported by this // function, since Python only allows the user to format integers in these bases. // If needed this function could be generalised to handle other values. assert(base == 2 || base == 8 || base == 10 || base == 16); if (!mp_obj_is_int(x)) { // This will convert booleans to int, or raise an error for // non-integer types. x = MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(x)); } if ((flags & (PF_FLAG_LEFT_ADJUST | PF_FLAG_CENTER_ADJUST)) == 0 && fill == '0') { if (prec > width) { width = prec; } prec = 0; } char prefix_buf[4]; char *prefix = prefix_buf; if (mp_obj_int_sign(x) >= 0) { if (flags & PF_FLAG_SHOW_SIGN) { *prefix++ = '+'; } else if (flags & PF_FLAG_SPACE_SIGN) { *prefix++ = ' '; } } if (flags & PF_FLAG_SHOW_PREFIX) { if (base == 2) { *prefix++ = '0'; *prefix++ = base_char + 'b' - 'a'; } else if (base == 8) { *prefix++ = '0'; if (flags & PF_FLAG_SHOW_OCTAL_LETTER) { *prefix++ = base_char + 'o' - 'a'; } } else if (base == 16) { *prefix++ = '0'; *prefix++ = base_char + 'x' - 'a'; } } *prefix = '\0'; int prefix_len = prefix - prefix_buf; prefix = prefix_buf; char comma = '\0'; if (flags & PF_FLAG_SHOW_COMMA) { comma = ','; } // The size of this buffer is rather arbitrary. If it's not large // enough, a dynamic one will be allocated. char stack_buf[sizeof(mp_int_t) * 4]; char *buf = stack_buf; size_t buf_size = sizeof(stack_buf); size_t fmt_size = 0; char *str; if (prec > 1) { flags |= PF_FLAG_PAD_AFTER_SIGN; } char sign = '\0'; if (flags & PF_FLAG_PAD_AFTER_SIGN) { // We add the pad in this function, so since the pad goes after // the sign & prefix, we format without a prefix str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, x, base, NULL, base_char, comma); if (*str == '-') { sign = *str++; fmt_size--; } } else { str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, x, base, prefix, base_char, comma); } int spaces_before = 0; int spaces_after = 0; if (prec > 1) { // If prec was specified, then prec specifies the width to zero-pad the // the number to. This zero-padded number then gets left or right // aligned in width characters. int prec_width = fmt_size; // The digits if (prec_width < prec) { prec_width = prec; } if (flags & PF_FLAG_PAD_AFTER_SIGN) { if (sign) { prec_width++; } prec_width += prefix_len; } if (prec_width < width) { if (flags & PF_FLAG_LEFT_ADJUST) { spaces_after = width - prec_width; } else { spaces_before = width - prec_width; } } fill = '0'; flags &= ~PF_FLAG_LEFT_ADJUST; } int len = 0; if (spaces_before) { len += mp_print_strn(print, "", 0, 0, ' ', spaces_before); } if (flags & PF_FLAG_PAD_AFTER_SIGN) { // pad after sign implies pad after prefix as well. if (sign) { len += mp_print_strn(print, &sign, 1, 0, 0, 1); width--; } if (prefix_len) { len += mp_print_strn(print, prefix, prefix_len, 0, 0, 1); width -= prefix_len; } } if (prec > 1) { width = prec; } len += mp_print_strn(print, str, fmt_size, flags, fill, width); if (spaces_after) { len += mp_print_strn(print, "", 0, 0, ' ', spaces_after); } if (buf != stack_buf) { m_del(char, buf, buf_size); } return len; } #if MICROPY_PY_BUILTINS_FLOAT int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec) { char buf[32]; char sign = '\0'; int chrs = 0; if (flags & PF_FLAG_SHOW_SIGN) { sign = '+'; } else if (flags & PF_FLAG_SPACE_SIGN) { sign = ' '; } int len = mp_format_float(f, buf, sizeof(buf), fmt, prec, sign); char *s = buf; if ((flags & PF_FLAG_ADD_PERCENT) && (size_t)(len + 1) < sizeof(buf)) { buf[len++] = '%'; buf[len] = '\0'; } // buf[0] < '0' returns true if the first character is space, + or - if ((flags & PF_FLAG_PAD_AFTER_SIGN) && buf[0] < '0') { // We have a sign character s++; chrs += mp_print_strn(print, &buf[0], 1, 0, 0, 1); width--; len--; } chrs += mp_print_strn(print, s, len, flags, fill, width); return chrs; } #endif int mp_printf(const mp_print_t *print, const char *fmt, ...) { va_list ap; va_start(ap, fmt); int ret = mp_vprintf(print, fmt, ap); va_end(ap); return ret; } int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { int chrs = 0; for (;;) { { const char *f = fmt; while (*f != '\0' && *f != '%') { ++f; // XXX UTF8 advance char } if (f > fmt) { print->print_strn(print->data, fmt, f - fmt); chrs += f - fmt; fmt = f; } } if (*fmt == '\0') { break; } // move past % character ++fmt; // parse flags, if they exist int flags = 0; char fill = ' '; while (*fmt != '\0') { if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST; else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN; else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN; else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ; else if (*fmt == '0') { flags |= PF_FLAG_PAD_AFTER_SIGN; fill = '0'; } else break; ++fmt; } // parse width, if it exists int width = 0; for (; '0' <= *fmt && *fmt <= '9'; ++fmt) { width = width * 10 + *fmt - '0'; } // parse precision, if it exists int prec = -1; if (*fmt == '.') { ++fmt; if (*fmt == '*') { ++fmt; prec = va_arg(args, int); } else { prec = 0; for (; '0' <= *fmt && *fmt <= '9'; ++fmt) { prec = prec * 10 + *fmt - '0'; } } if (prec < 0) { prec = 0; } } // parse long specifiers (only for LP64 model where they make a difference) #ifndef __LP64__ const #endif bool long_arg = false; if (*fmt == 'l') { ++fmt; #ifdef __LP64__ long_arg = true; #endif } if (*fmt == '\0') { break; } switch (*fmt) { case 'b': if (va_arg(args, int)) { chrs += mp_print_strn(print, "true", 4, flags, fill, width); } else { chrs += mp_print_strn(print, "false", 5, flags, fill, width); } break; case 'c': { char str = va_arg(args, int); chrs += mp_print_strn(print, &str, 1, flags, fill, width); break; } case 'q': { qstr qst = va_arg(args, qstr); size_t len; const char *str = (const char*)qstr_data(qst, &len); if (prec < 0) { prec = len; } chrs += mp_print_strn(print, str, prec, flags, fill, width); break; } case 's': { const char *str = va_arg(args, const char*); #ifndef NDEBUG // With debugging enabled, catch printing of null string pointers if (prec != 0 && str == NULL) { chrs += mp_print_strn(print, "(null)", 6, flags, fill, width); break; } #endif if (prec < 0) { prec = strlen(str); } chrs += mp_print_strn(print, str, prec, flags, fill, width); break; } case 'd': { mp_int_t val; if (long_arg) { val = va_arg(args, long int); } else { val = va_arg(args, int); } chrs += mp_print_int(print, val, 1, 10, 'a', flags, fill, width); break; } case 'u': case 'x': case 'X': { int base = 16 - ((*fmt + 1) & 6); // maps char u/x/X to base 10/16/16 char fmt_c = (*fmt & 0xf0) - 'P' + 'A'; // maps char u/x/X to char a/a/A mp_uint_t val; if (long_arg) { val = va_arg(args, unsigned long int); } else { val = va_arg(args, unsigned int); } chrs += mp_print_int(print, val, 0, base, fmt_c, flags, fill, width); break; } case 'p': case 'P': // don't bother to handle upcase for 'P' // Use unsigned long int to work on both ILP32 and LP64 systems chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags, fill, width); break; #if MICROPY_PY_BUILTINS_FLOAT case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': { #if ((MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT) || (MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE)) mp_float_t f = va_arg(args, double); chrs += mp_print_float(print, f, *fmt, flags, fill, width, prec); #else #error Unknown MICROPY FLOAT IMPL #endif break; } #endif // Because 'l' is eaten above, another 'l' means %ll. We need to support // this length specifier for OBJ_REPR_D (64-bit NaN boxing). // TODO Either enable this unconditionally, or provide a specific config var. #if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) || defined(_WIN64) case 'l': { unsigned long long int arg_value = va_arg(args, unsigned long long int); ++fmt; if (*fmt == 'u' || *fmt == 'd') { chrs += mp_print_int(print, arg_value, *fmt == 'd', 10, 'a', flags, fill, width); break; } assert(!"unsupported fmt char"); } #endif default: // if it's not %% then it's an unsupported format character assert(*fmt == '%' || !"unsupported fmt char"); print->print_strn(print->data, fmt, 1); chrs += 1; break; } ++fmt; } return chrs; } micropython-1.12/py/mpprint.h000066400000000000000000000055431357706137100163230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_MPPRINT_H #define MICROPY_INCLUDED_PY_MPPRINT_H #include "py/mpconfig.h" #define PF_FLAG_LEFT_ADJUST (0x001) #define PF_FLAG_SHOW_SIGN (0x002) #define PF_FLAG_SPACE_SIGN (0x004) #define PF_FLAG_NO_TRAILZ (0x008) #define PF_FLAG_SHOW_PREFIX (0x010) #define PF_FLAG_SHOW_COMMA (0x020) #define PF_FLAG_PAD_AFTER_SIGN (0x040) #define PF_FLAG_CENTER_ADJUST (0x080) #define PF_FLAG_ADD_PERCENT (0x100) #define PF_FLAG_SHOW_OCTAL_LETTER (0x200) #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES # define MP_PYTHON_PRINTER &mp_sys_stdout_print #else # define MP_PYTHON_PRINTER &mp_plat_print #endif typedef void (*mp_print_strn_t)(void *data, const char *str, size_t len); typedef struct _mp_print_t { void *data; mp_print_strn_t print_strn; } mp_print_t; // All (non-debug) prints go through one of the two interfaces below. // 1) Wrapper for platform print function, which wraps MP_PLAT_PRINT_STRN. extern const mp_print_t mp_plat_print; #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES // 2) Wrapper for printing to sys.stdout. extern const mp_print_t mp_sys_stdout_print; #endif int mp_print_str(const mp_print_t *print, const char *str); int mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flags, char fill, int width); #if MICROPY_PY_BUILTINS_FLOAT int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec); #endif int mp_printf(const mp_print_t *print, const char *fmt, ...); #ifdef va_start int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args); #endif #endif // MICROPY_INCLUDED_PY_MPPRINT_H micropython-1.12/py/mpstate.c000066400000000000000000000025261357706137100163000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #if MICROPY_DYNAMIC_COMPILER mp_dynamic_compiler_t mp_dynamic_compiler = {0}; #endif mp_state_ctx_t mp_state_ctx; micropython-1.12/py/mpstate.h000066400000000000000000000212171357706137100163030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_MPSTATE_H #define MICROPY_INCLUDED_PY_MPSTATE_H #include #include "py/mpconfig.h" #include "py/mpthread.h" #include "py/misc.h" #include "py/nlr.h" #include "py/obj.h" #include "py/objlist.h" #include "py/objexcept.h" // This file contains structures defining the state of the MicroPython // memory system, runtime and virtual machine. The state is a global // variable, but in the future it is hoped that the state can become local. // This structure contains dynamic configuration for the compiler. #if MICROPY_DYNAMIC_COMPILER typedef struct mp_dynamic_compiler_t { uint8_t small_int_bits; // must be <= host small_int_bits bool opt_cache_map_lookup_in_bytecode; bool py_builtins_str_unicode; uint8_t native_arch; uint8_t nlr_buf_num_regs; } mp_dynamic_compiler_t; extern mp_dynamic_compiler_t mp_dynamic_compiler; #endif // These are the values for sched_state #define MP_SCHED_IDLE (1) #define MP_SCHED_LOCKED (-1) #define MP_SCHED_PENDING (0) // 0 so it's a quick check in the VM typedef struct _mp_sched_item_t { mp_obj_t func; mp_obj_t arg; } mp_sched_item_t; // This structure hold information about the memory allocation system. typedef struct _mp_state_mem_t { #if MICROPY_MEM_STATS size_t total_bytes_allocated; size_t current_bytes_allocated; size_t peak_bytes_allocated; #endif byte *gc_alloc_table_start; size_t gc_alloc_table_byte_len; #if MICROPY_ENABLE_FINALISER byte *gc_finaliser_table_start; #endif byte *gc_pool_start; byte *gc_pool_end; int gc_stack_overflow; MICROPY_GC_STACK_ENTRY_TYPE gc_stack[MICROPY_ALLOC_GC_STACK_SIZE]; uint16_t gc_lock_depth; // This variable controls auto garbage collection. If set to 0 then the // GC won't automatically run when gc_alloc can't find enough blocks. But // you can still allocate/free memory and also explicitly call gc_collect. uint16_t gc_auto_collect_enabled; #if MICROPY_GC_ALLOC_THRESHOLD size_t gc_alloc_amount; size_t gc_alloc_threshold; #endif size_t gc_last_free_atb_index; #if MICROPY_PY_GC_COLLECT_RETVAL size_t gc_collected; #endif #if MICROPY_PY_THREAD // This is a global mutex used to make the GC thread-safe. mp_thread_mutex_t gc_mutex; #endif } mp_state_mem_t; // This structure hold runtime and VM information. It includes a section // which contains root pointers that must be scanned by the GC. typedef struct _mp_state_vm_t { // // CONTINUE ROOT POINTER SECTION // This must start at the start of this structure and follows // the state in the mp_state_thread_t structure, continuing // the root pointer section from there. // qstr_pool_t *last_pool; // non-heap memory for creating an exception if we can't allocate RAM mp_obj_exception_t mp_emergency_exception_obj; // memory for exception arguments if we can't allocate RAM #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF #if MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE > 0 // statically allocated buf (needs to be aligned to mp_obj_t) mp_obj_t mp_emergency_exception_buf[MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE / sizeof(mp_obj_t)]; #else // dynamically allocated buf byte *mp_emergency_exception_buf; #endif #endif #if MICROPY_KBD_EXCEPTION // exception object of type KeyboardInterrupt mp_obj_exception_t mp_kbd_exception; #endif // dictionary with loaded modules (may be exposed as sys.modules) mp_obj_dict_t mp_loaded_modules_dict; // pending exception object (MP_OBJ_NULL if not pending) volatile mp_obj_t mp_pending_exception; #if MICROPY_ENABLE_SCHEDULER mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]; #endif // current exception being handled, for sys.exc_info() #if MICROPY_PY_SYS_EXC_INFO mp_obj_base_t *cur_exception; #endif #if MICROPY_PY_SYS_ATEXIT // exposed through sys.atexit function mp_obj_t sys_exitfunc; #endif // dictionary for the __main__ module mp_obj_dict_t dict_main; // these two lists must be initialised per port, after the call to mp_init mp_obj_list_t mp_sys_path_obj; mp_obj_list_t mp_sys_argv_obj; // dictionary for overridden builtins #if MICROPY_CAN_OVERRIDE_BUILTINS mp_obj_dict_t *mp_module_builtins_override_dict; #endif // include any root pointers defined by a port MICROPY_PORT_ROOT_POINTERS // root pointers for extmod #if MICROPY_REPL_EVENT_DRIVEN vstr_t *repl_line; #endif #if MICROPY_PY_OS_DUPTERM mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]; #endif #if MICROPY_PY_LWIP_SLIP mp_obj_t lwip_slip_stream; #endif #if MICROPY_VFS struct _mp_vfs_mount_t *vfs_cur; struct _mp_vfs_mount_t *vfs_mount_table; #endif #if MICROPY_PY_BLUETOOTH mp_obj_t bluetooth; #endif // // END ROOT POINTER SECTION //////////////////////////////////////////////////////////// // pointer and sizes to store interned string data // (qstr_last_chunk can be root pointer but is also stored in qstr pool) byte *qstr_last_chunk; size_t qstr_last_alloc; size_t qstr_last_used; #if MICROPY_PY_THREAD // This is a global mutex used to make qstr interning thread-safe. mp_thread_mutex_t qstr_mutex; #endif #if MICROPY_ENABLE_COMPILER mp_uint_t mp_optimise_value; #if MICROPY_EMIT_NATIVE uint8_t default_emit_opt; // one of MP_EMIT_OPT_xxx #endif #endif // size of the emergency exception buf, if it's dynamically allocated #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0 mp_int_t mp_emergency_exception_buf_size; #endif #if MICROPY_ENABLE_SCHEDULER volatile int16_t sched_state; uint8_t sched_len; uint8_t sched_idx; #endif #if MICROPY_PY_THREAD_GIL // This is a global mutex used to make the VM/runtime thread-safe. mp_thread_mutex_t gil_mutex; #endif } mp_state_vm_t; // This structure holds state that is specific to a given thread. // Everything in this structure is scanned for root pointers. typedef struct _mp_state_thread_t { // Stack top at the start of program char *stack_top; #if MICROPY_STACK_CHECK size_t stack_limit; #endif #if MICROPY_ENABLE_PYSTACK uint8_t *pystack_start; uint8_t *pystack_end; uint8_t *pystack_cur; #endif //////////////////////////////////////////////////////////// // START ROOT POINTER SECTION // Everything that needs GC scanning must start here, and // is followed by state in the mp_state_vm_t structure. // mp_obj_dict_t *dict_locals; mp_obj_dict_t *dict_globals; nlr_buf_t *nlr_top; #if MICROPY_PY_SYS_SETTRACE mp_obj_t prof_trace_callback; bool prof_callback_is_executing; struct _mp_code_state_t *current_code_state; #endif } mp_state_thread_t; // This structure combines the above 3 structures. // The order of the entries are important for root pointer scanning in the GC to work. typedef struct _mp_state_ctx_t { mp_state_thread_t thread; mp_state_vm_t vm; mp_state_mem_t mem; } mp_state_ctx_t; extern mp_state_ctx_t mp_state_ctx; #define MP_STATE_VM(x) (mp_state_ctx.vm.x) #define MP_STATE_MEM(x) (mp_state_ctx.mem.x) #if MICROPY_PY_THREAD extern mp_state_thread_t *mp_thread_get_state(void); #define MP_STATE_THREAD(x) (mp_thread_get_state()->x) #else #define MP_STATE_THREAD(x) (mp_state_ctx.thread.x) #endif #endif // MICROPY_INCLUDED_PY_MPSTATE_H micropython-1.12/py/mpthread.h000066400000000000000000000043421357706137100164320ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_MPTHREAD_H #define MICROPY_INCLUDED_PY_MPTHREAD_H #include "py/mpconfig.h" #if MICROPY_PY_THREAD #ifdef MICROPY_MPTHREADPORT_H #include MICROPY_MPTHREADPORT_H #else #include #endif struct _mp_state_thread_t; struct _mp_state_thread_t *mp_thread_get_state(void); void mp_thread_set_state(void *state); void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size); void mp_thread_start(void); void mp_thread_finish(void); void mp_thread_mutex_init(mp_thread_mutex_t *mutex); int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait); void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex); #endif // MICROPY_PY_THREAD #if MICROPY_PY_THREAD && MICROPY_PY_THREAD_GIL #include "py/mpstate.h" #define MP_THREAD_GIL_ENTER() mp_thread_mutex_lock(&MP_STATE_VM(gil_mutex), 1) #define MP_THREAD_GIL_EXIT() mp_thread_mutex_unlock(&MP_STATE_VM(gil_mutex)) #else #define MP_THREAD_GIL_ENTER() #define MP_THREAD_GIL_EXIT() #endif #endif // MICROPY_INCLUDED_PY_MPTHREAD_H micropython-1.12/py/mpz.c000066400000000000000000001370401357706137100154310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/mpz.h" #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ #define DIG_SIZE (MPZ_DIG_SIZE) #define DIG_MASK ((MPZ_LONG_1 << DIG_SIZE) - 1) #define DIG_MSB (MPZ_LONG_1 << (DIG_SIZE - 1)) #define DIG_BASE (MPZ_LONG_1 << DIG_SIZE) /* mpz is an arbitrary precision integer type with a public API. mpn functions act on non-negative integers represented by an array of generalised digits (eg a word per digit). You also need to specify separately the length of the array. There is no public API for mpn. Rather, the functions are used by mpz to implement its features. Integer values are stored little endian (first digit is first in memory). Definition of normalise: ? */ STATIC size_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) { for (--idig; idig >= oidig && *idig == 0; --idig) { } return idig + 1 - oidig; } /* compares i with j returns sign(i - j) assumes i, j are normalised */ STATIC int mpn_cmp(const mpz_dig_t *idig, size_t ilen, const mpz_dig_t *jdig, size_t jlen) { if (ilen < jlen) { return -1; } if (ilen > jlen) { return 1; } for (idig += ilen, jdig += ilen; ilen > 0; --ilen) { mpz_dbl_dig_signed_t cmp = (mpz_dbl_dig_t)*(--idig) - (mpz_dbl_dig_t)*(--jdig); if (cmp < 0) { return -1; } if (cmp > 0) { return 1; } } return 0; } /* computes i = j << n returns number of digits in i assumes enough memory in i; assumes normalised j; assumes n > 0 can have i, j pointing to same memory */ STATIC size_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) { mp_uint_t n_whole = (n + DIG_SIZE - 1) / DIG_SIZE; mp_uint_t n_part = n % DIG_SIZE; if (n_part == 0) { n_part = DIG_SIZE; } // start from the high end of the digit arrays idig += jlen + n_whole - 1; jdig += jlen - 1; // shift the digits mpz_dbl_dig_t d = 0; for (size_t i = jlen; i > 0; i--, idig--, jdig--) { d |= *jdig; *idig = (d >> (DIG_SIZE - n_part)) & DIG_MASK; d <<= DIG_SIZE; } // store remaining bits *idig = (d >> (DIG_SIZE - n_part)) & DIG_MASK; idig -= n_whole - 1; memset(idig, 0, (n_whole - 1) * sizeof(mpz_dig_t)); // work out length of result jlen += n_whole; while (jlen != 0 && idig[jlen - 1] == 0) { jlen--; } // return length of result return jlen; } /* computes i = j >> n returns number of digits in i assumes enough memory in i; assumes normalised j; assumes n > 0 can have i, j pointing to same memory */ STATIC size_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) { mp_uint_t n_whole = n / DIG_SIZE; mp_uint_t n_part = n % DIG_SIZE; if (n_whole >= jlen) { return 0; } jdig += n_whole; jlen -= n_whole; for (size_t i = jlen; i > 0; i--, idig++, jdig++) { mpz_dbl_dig_t d = *jdig; if (i > 1) { d |= (mpz_dbl_dig_t)jdig[1] << DIG_SIZE; } d >>= n_part; *idig = d & DIG_MASK; } if (idig[-1] == 0) { jlen--; } return jlen; } /* computes i = j + k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen can have i, j, k pointing to same memory */ STATIC size_t mpn_add(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; mpz_dbl_dig_t carry = 0; jlen -= klen; for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { carry += (mpz_dbl_dig_t)*jdig + (mpz_dbl_dig_t)*kdig; *idig = carry & DIG_MASK; carry >>= DIG_SIZE; } for (; jlen > 0; --jlen, ++idig, ++jdig) { carry += *jdig; *idig = carry & DIG_MASK; carry >>= DIG_SIZE; } if (carry != 0) { *idig++ = carry; } return idig - oidig; } /* computes i = j - k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes j >= k can have i, j, k pointing to same memory */ STATIC size_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; mpz_dbl_dig_signed_t borrow = 0; jlen -= klen; for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { borrow += (mpz_dbl_dig_t)*jdig - (mpz_dbl_dig_t)*kdig; *idig = borrow & DIG_MASK; borrow >>= DIG_SIZE; } for (; jlen > 0; --jlen, ++idig, ++jdig) { borrow += *jdig; *idig = borrow & DIG_MASK; borrow >>= DIG_SIZE; } return mpn_remove_trailing_zeros(oidig, idig); } #if MICROPY_OPT_MPZ_BITWISE /* computes i = j & k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen (jlen argument not needed) can have i, j, k pointing to same memory */ STATIC size_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { *idig = *jdig & *kdig; } return mpn_remove_trailing_zeros(oidig, idig); } #endif /* i = -((-j) & (-k)) = ~((~j + 1) & (~k + 1)) + 1 i = (j & (-k)) = (j & (~k + 1)) = ( j & (~k + 1)) i = ((-j) & k) = ((~j + 1) & k) = ((~j + 1) & k ) computes general form: i = (im ^ (((j ^ jm) + jc) & ((k ^ km) + kc))) + ic where Xm = Xc == 0 ? 0 : DIG_MASK returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes length j >= length k can have i, j, k pointing to same memory */ STATIC size_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK; mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK; mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK; for (; jlen > 0; ++idig, ++jdig) { carryj += *jdig ^ jmask; carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask; carryi += ((carryj & carryk) ^ imask) & DIG_MASK; *idig = carryi & DIG_MASK; carryk >>= DIG_SIZE; carryj >>= DIG_SIZE; carryi >>= DIG_SIZE; } if (0 != carryi) { *idig++ = carryi; } return mpn_remove_trailing_zeros(oidig, idig); } #if MICROPY_OPT_MPZ_BITWISE /* computes i = j | k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen can have i, j, k pointing to same memory */ STATIC size_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; jlen -= klen; for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { *idig = *jdig | *kdig; } for (; jlen > 0; --jlen, ++idig, ++jdig) { *idig = *jdig; } return idig - oidig; } #endif /* i = -((-j) | (-k)) = ~((~j + 1) | (~k + 1)) + 1 i = -(j | (-k)) = -(j | (~k + 1)) = ~( j | (~k + 1)) + 1 i = -((-j) | k) = -((~j + 1) | k) = ~((~j + 1) | k ) + 1 computes general form: i = ~(((j ^ jm) + jc) | ((k ^ km) + kc)) + 1 where Xm = Xc == 0 ? 0 : DIG_MASK returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes length j >= length k can have i, j, k pointing to same memory */ #if MICROPY_OPT_MPZ_BITWISE STATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; mpz_dbl_dig_t carryi = 1; mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK; mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK; for (; jlen > 0; ++idig, ++jdig) { carryj += *jdig ^ jmask; carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask; carryi += ((carryj | carryk) ^ DIG_MASK) & DIG_MASK; *idig = carryi & DIG_MASK; carryk >>= DIG_SIZE; carryj >>= DIG_SIZE; carryi >>= DIG_SIZE; } // At least one of j,k must be negative so the above for-loop runs at least // once. For carryi to be non-zero here it must be equal to 1 at the end of // each iteration of the loop. So the accumulation of carryi must overflow // each time, ie carryi += 0xff..ff. So carryj|carryk must be 0 in the // DIG_MASK bits on each iteration. But considering all cases of signs of // j,k one sees that this is not possible. assert(carryi == 0); return mpn_remove_trailing_zeros(oidig, idig); } #else STATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK; mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK; mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK; for (; jlen > 0; ++idig, ++jdig) { carryj += *jdig ^ jmask; carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask; carryi += ((carryj | carryk) ^ imask) & DIG_MASK; *idig = carryi & DIG_MASK; carryk >>= DIG_SIZE; carryj >>= DIG_SIZE; carryi >>= DIG_SIZE; } // See comment in above mpn_or_neg for why carryi must be 0. assert(carryi == 0); return mpn_remove_trailing_zeros(oidig, idig); } #endif #if MICROPY_OPT_MPZ_BITWISE /* computes i = j ^ k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen can have i, j, k pointing to same memory */ STATIC size_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; jlen -= klen; for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { *idig = *jdig ^ *kdig; } for (; jlen > 0; --jlen, ++idig, ++jdig) { *idig = *jdig; } return mpn_remove_trailing_zeros(oidig, idig); } #endif /* i = (-j) ^ (-k) = ~(j - 1) ^ ~(k - 1) = (j - 1) ^ (k - 1) i = -(j ^ (-k)) = -(j ^ ~(k - 1)) = ~(j ^ ~(k - 1)) + 1 = (j ^ (k - 1)) + 1 i = -((-j) ^ k) = -(~(j - 1) ^ k) = ~(~(j - 1) ^ k) + 1 = ((j - 1) ^ k) + 1 computes general form: i = ((j - 1 + jc) ^ (k - 1 + kc)) + ic returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes length j >= length k can have i, j, k pointing to same memory */ STATIC size_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; for (; jlen > 0; ++idig, ++jdig) { carryj += *jdig + DIG_MASK; carryk += (--klen <= --jlen) ? (*kdig++ + DIG_MASK) : DIG_MASK; carryi += (carryj ^ carryk) & DIG_MASK; *idig = carryi & DIG_MASK; carryk >>= DIG_SIZE; carryj >>= DIG_SIZE; carryi >>= DIG_SIZE; } if (0 != carryi) { *idig++ = carryi; } return mpn_remove_trailing_zeros(oidig, idig); } /* computes i = i * d1 + d2 returns number of digits in i assumes enough memory in i; assumes normalised i; assumes dmul != 0 */ STATIC size_t mpn_mul_dig_add_dig(mpz_dig_t *idig, size_t ilen, mpz_dig_t dmul, mpz_dig_t dadd) { mpz_dig_t *oidig = idig; mpz_dbl_dig_t carry = dadd; for (; ilen > 0; --ilen, ++idig) { carry += (mpz_dbl_dig_t)*idig * (mpz_dbl_dig_t)dmul; // will never overflow so long as DIG_SIZE <= 8*sizeof(mpz_dbl_dig_t)/2 *idig = carry & DIG_MASK; carry >>= DIG_SIZE; } if (carry != 0) { *idig++ = carry; } return idig - oidig; } /* computes i = j * k returns number of digits in i assumes enough memory in i; assumes i is zeroed; assumes normalised j, k can have j, k point to same memory */ STATIC size_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; size_t ilen = 0; for (; klen > 0; --klen, ++idig, ++kdig) { mpz_dig_t *id = idig; mpz_dbl_dig_t carry = 0; size_t jl = jlen; for (mpz_dig_t *jd = jdig; jl > 0; --jl, ++jd, ++id) { carry += (mpz_dbl_dig_t)*id + (mpz_dbl_dig_t)*jd * (mpz_dbl_dig_t)*kdig; // will never overflow so long as DIG_SIZE <= 8*sizeof(mpz_dbl_dig_t)/2 *id = carry & DIG_MASK; carry >>= DIG_SIZE; } if (carry != 0) { *id++ = carry; } ilen = id - oidig; } return ilen; } /* natural_div - quo * den + new_num = old_num (ie num is replaced with rem) assumes den != 0 assumes num_dig has enough memory to be extended by 1 digit assumes quo_dig has enough memory (as many digits as num) assumes quo_dig is filled with zeros */ STATIC void mpn_div(mpz_dig_t *num_dig, size_t *num_len, const mpz_dig_t *den_dig, size_t den_len, mpz_dig_t *quo_dig, size_t *quo_len) { mpz_dig_t *orig_num_dig = num_dig; mpz_dig_t *orig_quo_dig = quo_dig; mpz_dig_t norm_shift = 0; mpz_dbl_dig_t lead_den_digit; // handle simple cases { int cmp = mpn_cmp(num_dig, *num_len, den_dig, den_len); if (cmp == 0) { *num_len = 0; quo_dig[0] = 1; *quo_len = 1; return; } else if (cmp < 0) { // numerator remains the same *quo_len = 0; return; } } // We need to normalise the denominator (leading bit of leading digit is 1) // so that the division routine works. Since the denominator memory is // read-only we do the normalisation on the fly, each time a digit of the // denominator is needed. We need to know is how many bits to shift by. // count number of leading zeros in leading digit of denominator { mpz_dig_t d = den_dig[den_len - 1]; while ((d & DIG_MSB) == 0) { d <<= 1; ++norm_shift; } } // now need to shift numerator by same amount as denominator // first, increase length of numerator in case we need more room to shift num_dig[*num_len] = 0; ++(*num_len); for (mpz_dig_t *num = num_dig, carry = 0; num < num_dig + *num_len; ++num) { mpz_dig_t n = *num; *num = ((n << norm_shift) | carry) & DIG_MASK; carry = (mpz_dbl_dig_t)n >> (DIG_SIZE - norm_shift); } // cache the leading digit of the denominator lead_den_digit = (mpz_dbl_dig_t)den_dig[den_len - 1] << norm_shift; if (den_len >= 2) { lead_den_digit |= (mpz_dbl_dig_t)den_dig[den_len - 2] >> (DIG_SIZE - norm_shift); } // point num_dig to last digit in numerator num_dig += *num_len - 1; // calculate number of digits in quotient *quo_len = *num_len - den_len; // point to last digit to store for quotient quo_dig += *quo_len - 1; // keep going while we have enough digits to divide while (*num_len > den_len) { mpz_dbl_dig_t quo = ((mpz_dbl_dig_t)*num_dig << DIG_SIZE) | num_dig[-1]; // get approximate quotient quo /= lead_den_digit; // Multiply quo by den and subtract from num to get remainder. // We have different code here to handle different compile-time // configurations of mpz: // // 1. DIG_SIZE is stricly less than half the number of bits // available in mpz_dbl_dig_t. In this case we can use a // slightly more optimal (in time and space) routine that // uses the extra bits in mpz_dbl_dig_signed_t to store a // sign bit. // // 2. DIG_SIZE is exactly half the number of bits available in // mpz_dbl_dig_t. In this (common) case we need to be careful // not to overflow the borrow variable. And the shifting of // borrow needs some special logic (it's a shift right with // round up). // const mpz_dig_t *d = den_dig; mpz_dbl_dig_t d_norm = 0; mpz_dbl_dig_t borrow = 0; for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) { d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE); mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK); #if DIG_SIZE < MPZ_DBL_DIG_SIZE / 2 borrow += (mpz_dbl_dig_t)*n - x; // will overflow if DIG_SIZE >= MPZ_DBL_DIG_SIZE/2 *n = borrow & DIG_MASK; borrow = (mpz_dbl_dig_signed_t)borrow >> DIG_SIZE; #else // DIG_SIZE == MPZ_DBL_DIG_SIZE / 2 if (x >= *n || *n - x <= borrow) { borrow += x - (mpz_dbl_dig_t)*n; *n = (-borrow) & DIG_MASK; borrow = (borrow >> DIG_SIZE) + ((borrow & DIG_MASK) == 0 ? 0 : 1); // shift-right with round-up } else { *n = ((mpz_dbl_dig_t)*n - x - borrow) & DIG_MASK; borrow = 0; } #endif } #if DIG_SIZE < MPZ_DBL_DIG_SIZE / 2 // Borrow was negative in the above for-loop, make it positive for next if-block. borrow = -borrow; #endif // At this point we have either: // // 1. quo was the correct value and the most-sig-digit of num is exactly // cancelled by borrow (borrow == *num_dig). In this case there is // nothing more to do. // // 2. quo was too large, we subtracted too many den from num, and the // most-sig-digit of num is 1 less than borrow (borrow == *num_dig + 1). // In this case we must reduce quo and add back den to num until the // carry from this operation cancels out the borrow. // borrow -= *num_dig; for (; borrow != 0; --quo) { d = den_dig; d_norm = 0; mpz_dbl_dig_t carry = 0; for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) { d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE); carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK); *n = carry & DIG_MASK; carry >>= DIG_SIZE; } borrow -= carry; } // store this digit of the quotient *quo_dig = quo & DIG_MASK; --quo_dig; // move down to next digit of numerator --num_dig; --(*num_len); } // unnormalise numerator (remainder now) for (mpz_dig_t *num = orig_num_dig + *num_len - 1, carry = 0; num >= orig_num_dig; --num) { mpz_dig_t n = *num; *num = ((n >> norm_shift) | carry) & DIG_MASK; carry = (mpz_dbl_dig_t)n << (DIG_SIZE - norm_shift); } // strip trailing zeros while (*quo_len > 0 && orig_quo_dig[*quo_len - 1] == 0) { --(*quo_len); } while (*num_len > 0 && orig_num_dig[*num_len - 1] == 0) { --(*num_len); } } #define MIN_ALLOC (2) void mpz_init_zero(mpz_t *z) { z->neg = 0; z->fixed_dig = 0; z->alloc = 0; z->len = 0; z->dig = NULL; } void mpz_init_from_int(mpz_t *z, mp_int_t val) { mpz_init_zero(z); mpz_set_from_int(z, val); } void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, size_t alloc, mp_int_t val) { z->neg = 0; z->fixed_dig = 1; z->alloc = alloc; z->len = 0; z->dig = dig; mpz_set_from_int(z, val); } void mpz_deinit(mpz_t *z) { if (z != NULL && !z->fixed_dig) { m_del(mpz_dig_t, z->dig, z->alloc); } } #if 0 these functions are unused mpz_t *mpz_zero(void) { mpz_t *z = m_new_obj(mpz_t); mpz_init_zero(z); return z; } mpz_t *mpz_from_int(mp_int_t val) { mpz_t *z = mpz_zero(); mpz_set_from_int(z, val); return z; } mpz_t *mpz_from_ll(long long val, bool is_signed) { mpz_t *z = mpz_zero(); mpz_set_from_ll(z, val, is_signed); return z; } #if MICROPY_PY_BUILTINS_FLOAT mpz_t *mpz_from_float(mp_float_t val) { mpz_t *z = mpz_zero(); mpz_set_from_float(z, val); return z; } #endif mpz_t *mpz_from_str(const char *str, size_t len, bool neg, unsigned int base) { mpz_t *z = mpz_zero(); mpz_set_from_str(z, str, len, neg, base); return z; } #endif STATIC void mpz_free(mpz_t *z) { if (z != NULL) { m_del(mpz_dig_t, z->dig, z->alloc); m_del_obj(mpz_t, z); } } STATIC void mpz_need_dig(mpz_t *z, size_t need) { if (need < MIN_ALLOC) { need = MIN_ALLOC; } if (z->dig == NULL || z->alloc < need) { // if z has fixed digit buffer there's not much we can do as the caller will // be expecting a buffer with at least "need" bytes (but it shouldn't happen) assert(!z->fixed_dig); z->dig = m_renew(mpz_dig_t, z->dig, z->alloc, need); z->alloc = need; } } STATIC mpz_t *mpz_clone(const mpz_t *src) { assert(src->alloc != 0); mpz_t *z = m_new_obj(mpz_t); z->neg = src->neg; z->fixed_dig = 0; z->alloc = src->alloc; z->len = src->len; z->dig = m_new(mpz_dig_t, z->alloc); memcpy(z->dig, src->dig, src->alloc * sizeof(mpz_dig_t)); return z; } /* sets dest = src can have dest, src the same */ void mpz_set(mpz_t *dest, const mpz_t *src) { mpz_need_dig(dest, src->len); dest->neg = src->neg; dest->len = src->len; memcpy(dest->dig, src->dig, src->len * sizeof(mpz_dig_t)); } void mpz_set_from_int(mpz_t *z, mp_int_t val) { if (val == 0) { z->len = 0; return; } mpz_need_dig(z, MPZ_NUM_DIG_FOR_INT); mp_uint_t uval; if (val < 0) { z->neg = 1; uval = -val; } else { z->neg = 0; uval = val; } z->len = 0; while (uval > 0) { z->dig[z->len++] = uval & DIG_MASK; uval >>= DIG_SIZE; } } void mpz_set_from_ll(mpz_t *z, long long val, bool is_signed) { mpz_need_dig(z, MPZ_NUM_DIG_FOR_LL); unsigned long long uval; if (is_signed && val < 0) { z->neg = 1; uval = -val; } else { z->neg = 0; uval = val; } z->len = 0; while (uval > 0) { z->dig[z->len++] = uval & DIG_MASK; uval >>= DIG_SIZE; } } #if MICROPY_PY_BUILTINS_FLOAT void mpz_set_from_float(mpz_t *z, mp_float_t src) { #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE typedef uint64_t mp_float_int_t; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT typedef uint32_t mp_float_int_t; #endif union { mp_float_t f; #if MP_ENDIANNESS_LITTLE struct { mp_float_int_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p; #else struct { mp_float_int_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p; #endif } u = {src}; z->neg = u.p.sgn; if (u.p.exp == 0) { // value == 0 || value < 1 mpz_set_from_int(z, 0); } else if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) { // u.p.frc == 0 indicates inf, else NaN // should be handled by caller mpz_set_from_int(z, 0); } else { const int adj_exp = (int)u.p.exp - MP_FLOAT_EXP_BIAS; if (adj_exp < 0) { // value < 1 , truncates to 0 mpz_set_from_int(z, 0); } else if (adj_exp == 0) { // 1 <= value < 2 , so truncates to 1 mpz_set_from_int(z, 1); } else { // 2 <= value const int dig_cnt = (adj_exp + 1 + (DIG_SIZE - 1)) / DIG_SIZE; const unsigned int rem = adj_exp % DIG_SIZE; int dig_ind, shft; mp_float_int_t frc = u.p.frc | ((mp_float_int_t)1 << MP_FLOAT_FRAC_BITS); if (adj_exp < MP_FLOAT_FRAC_BITS) { shft = 0; dig_ind = 0; frc >>= MP_FLOAT_FRAC_BITS - adj_exp; } else { shft = (rem - MP_FLOAT_FRAC_BITS) % DIG_SIZE; dig_ind = (adj_exp - MP_FLOAT_FRAC_BITS) / DIG_SIZE; } mpz_need_dig(z, dig_cnt); z->len = dig_cnt; if (dig_ind != 0) { memset(z->dig, 0, dig_ind * sizeof(mpz_dig_t)); } if (shft != 0) { z->dig[dig_ind++] = (frc << shft) & DIG_MASK; frc >>= DIG_SIZE - shft; } #if DIG_SIZE < (MP_FLOAT_FRAC_BITS + 1) while (dig_ind != dig_cnt) { z->dig[dig_ind++] = frc & DIG_MASK; frc >>= DIG_SIZE; } #else if (dig_ind != dig_cnt) { z->dig[dig_ind] = frc; } #endif } } } #endif // returns number of bytes from str that were processed size_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigned int base) { assert(base <= 36); const char *cur = str; const char *top = str + len; mpz_need_dig(z, len * 8 / DIG_SIZE + 1); if (neg) { z->neg = 1; } else { z->neg = 0; } z->len = 0; for (; cur < top; ++cur) { // XXX UTF8 next char //mp_uint_t v = char_to_numeric(cur#); // XXX UTF8 get char mp_uint_t v = *cur; if ('0' <= v && v <= '9') { v -= '0'; } else if ('A' <= v && v <= 'Z') { v -= 'A' - 10; } else if ('a' <= v && v <= 'z') { v -= 'a' - 10; } else { break; } if (v >= base) { break; } z->len = mpn_mul_dig_add_dig(z->dig, z->len, base, v); } return cur - str; } void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf) { int delta = 1; if (big_endian) { buf += len - 1; delta = -1; } mpz_need_dig(z, (len * 8 + DIG_SIZE - 1) / DIG_SIZE); mpz_dig_t d = 0; int num_bits = 0; z->neg = 0; z->len = 0; while (len) { while (len && num_bits < DIG_SIZE) { d |= *buf << num_bits; num_bits += 8; buf += delta; len--; } z->dig[z->len++] = d & DIG_MASK; // Need this #if because it's C undefined behavior to do: uint32_t >> 32 #if DIG_SIZE != 8 && DIG_SIZE != 16 && DIG_SIZE != 32 d >>= DIG_SIZE; #else d = 0; #endif num_bits -= DIG_SIZE; } z->len = mpn_remove_trailing_zeros(z->dig, z->dig + z->len); } #if 0 these functions are unused bool mpz_is_pos(const mpz_t *z) { return z->len > 0 && z->neg == 0; } bool mpz_is_odd(const mpz_t *z) { return z->len > 0 && (z->dig[0] & 1) != 0; } bool mpz_is_even(const mpz_t *z) { return z->len == 0 || (z->dig[0] & 1) == 0; } #endif int mpz_cmp(const mpz_t *z1, const mpz_t *z2) { // to catch comparison of -0 with +0 if (z1->len == 0 && z2->len == 0) { return 0; } int cmp = (int)z2->neg - (int)z1->neg; if (cmp != 0) { return cmp; } cmp = mpn_cmp(z1->dig, z1->len, z2->dig, z2->len); if (z1->neg != 0) { cmp = -cmp; } return cmp; } #if 0 // obsolete // compares mpz with an integer that fits within DIG_SIZE bits mp_int_t mpz_cmp_sml_int(const mpz_t *z, mp_int_t sml_int) { mp_int_t cmp; if (z->neg == 0) { if (sml_int < 0) return 1; if (sml_int == 0) { if (z->len == 0) return 0; return 1; } if (z->len == 0) return -1; assert(sml_int < (1 << DIG_SIZE)); if (z->len != 1) return 1; cmp = z->dig[0] - sml_int; } else { if (sml_int > 0) return -1; if (sml_int == 0) { if (z->len == 0) return 0; return -1; } if (z->len == 0) return 1; assert(sml_int > -(1 << DIG_SIZE)); if (z->len != 1) return -1; cmp = -z->dig[0] - sml_int; } if (cmp < 0) return -1; if (cmp > 0) return 1; return 0; } #endif #if 0 these functions are unused /* returns abs(z) */ mpz_t *mpz_abs(const mpz_t *z) { // TODO: handle case of z->alloc=0 mpz_t *z2 = mpz_clone(z); z2->neg = 0; return z2; } /* returns -z */ mpz_t *mpz_neg(const mpz_t *z) { // TODO: handle case of z->alloc=0 mpz_t *z2 = mpz_clone(z); z2->neg = 1 - z2->neg; return z2; } /* returns lhs + rhs can have lhs, rhs the same */ mpz_t *mpz_add(const mpz_t *lhs, const mpz_t *rhs) { mpz_t *z = mpz_zero(); mpz_add_inpl(z, lhs, rhs); return z; } /* returns lhs - rhs can have lhs, rhs the same */ mpz_t *mpz_sub(const mpz_t *lhs, const mpz_t *rhs) { mpz_t *z = mpz_zero(); mpz_sub_inpl(z, lhs, rhs); return z; } /* returns lhs * rhs can have lhs, rhs the same */ mpz_t *mpz_mul(const mpz_t *lhs, const mpz_t *rhs) { mpz_t *z = mpz_zero(); mpz_mul_inpl(z, lhs, rhs); return z; } /* returns lhs ** rhs can have lhs, rhs the same */ mpz_t *mpz_pow(const mpz_t *lhs, const mpz_t *rhs) { mpz_t *z = mpz_zero(); mpz_pow_inpl(z, lhs, rhs); return z; } /* computes new integers in quo and rem such that: quo * rhs + rem = lhs 0 <= rem < rhs can have lhs, rhs the same */ void mpz_divmod(const mpz_t *lhs, const mpz_t *rhs, mpz_t **quo, mpz_t **rem) { *quo = mpz_zero(); *rem = mpz_zero(); mpz_divmod_inpl(*quo, *rem, lhs, rhs); } #endif /* computes dest = abs(z) can have dest, z the same */ void mpz_abs_inpl(mpz_t *dest, const mpz_t *z) { if (dest != z) { mpz_set(dest, z); } dest->neg = 0; } /* computes dest = -z can have dest, z the same */ void mpz_neg_inpl(mpz_t *dest, const mpz_t *z) { if (dest != z) { mpz_set(dest, z); } dest->neg = 1 - dest->neg; } /* computes dest = ~z (= -z - 1) can have dest, z the same */ void mpz_not_inpl(mpz_t *dest, const mpz_t *z) { if (dest != z) { mpz_set(dest, z); } if (dest->len == 0) { mpz_need_dig(dest, 1); dest->dig[0] = 1; dest->len = 1; dest->neg = 1; } else if (dest->neg) { dest->neg = 0; mpz_dig_t k = 1; dest->len = mpn_sub(dest->dig, dest->dig, dest->len, &k, 1); } else { mpz_need_dig(dest, dest->len + 1); mpz_dig_t k = 1; dest->len = mpn_add(dest->dig, dest->dig, dest->len, &k, 1); dest->neg = 1; } } /* computes dest = lhs << rhs can have dest, lhs the same */ void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs) { if (lhs->len == 0 || rhs == 0) { mpz_set(dest, lhs); } else { mpz_need_dig(dest, lhs->len + (rhs + DIG_SIZE - 1) / DIG_SIZE); dest->len = mpn_shl(dest->dig, lhs->dig, lhs->len, rhs); dest->neg = lhs->neg; } } /* computes dest = lhs >> rhs can have dest, lhs the same */ void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs) { if (lhs->len == 0 || rhs == 0) { mpz_set(dest, lhs); } else { mpz_need_dig(dest, lhs->len); dest->len = mpn_shr(dest->dig, lhs->dig, lhs->len, rhs); dest->neg = lhs->neg; if (dest->neg) { // arithmetic shift right, rounding to negative infinity mp_uint_t n_whole = rhs / DIG_SIZE; mp_uint_t n_part = rhs % DIG_SIZE; mpz_dig_t round_up = 0; for (size_t i = 0; i < lhs->len && i < n_whole; i++) { if (lhs->dig[i] != 0) { round_up = 1; break; } } if (n_whole < lhs->len && (lhs->dig[n_whole] & ((1 << n_part) - 1)) != 0) { round_up = 1; } if (round_up) { if (dest->len == 0) { // dest == 0, so need to add 1 by hand (answer will be -1) dest->dig[0] = 1; dest->len = 1; } else { // dest > 0, so can use mpn_add to add 1 dest->len = mpn_add(dest->dig, dest->dig, dest->len, &round_up, 1); } } } } } /* computes dest = lhs + rhs can have dest, lhs, rhs the same */ void mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; } if (lhs->neg == rhs->neg) { mpz_need_dig(dest, lhs->len + 1); dest->len = mpn_add(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); } else { mpz_need_dig(dest, lhs->len); dest->len = mpn_sub(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); } dest->neg = lhs->neg; } /* computes dest = lhs - rhs can have dest, lhs, rhs the same */ void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { bool neg = false; if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; neg = true; } if (lhs->neg != rhs->neg) { mpz_need_dig(dest, lhs->len + 1); dest->len = mpn_add(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); } else { mpz_need_dig(dest, lhs->len); dest->len = mpn_sub(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); } if (neg) { dest->neg = 1 - lhs->neg; } else { dest->neg = lhs->neg; } } /* computes dest = lhs & rhs can have dest, lhs, rhs the same */ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { // make sure lhs has the most digits if (lhs->len < rhs->len) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; } #if MICROPY_OPT_MPZ_BITWISE if ((0 == lhs->neg) && (0 == rhs->neg)) { mpz_need_dig(dest, lhs->len); dest->len = mpn_and(dest->dig, lhs->dig, rhs->dig, rhs->len); dest->neg = 0; } else { mpz_need_dig(dest, lhs->len + 1); dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, lhs->neg == rhs->neg, 0 != lhs->neg, 0 != rhs->neg); dest->neg = lhs->neg & rhs->neg; } #else mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg)); dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, (lhs->neg == rhs->neg) ? lhs->neg : 0, lhs->neg, rhs->neg); dest->neg = lhs->neg & rhs->neg; #endif } /* computes dest = lhs | rhs can have dest, lhs, rhs the same */ void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { // make sure lhs has the most digits if (lhs->len < rhs->len) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; } #if MICROPY_OPT_MPZ_BITWISE if ((0 == lhs->neg) && (0 == rhs->neg)) { mpz_need_dig(dest, lhs->len); dest->len = mpn_or(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); dest->neg = 0; } else { mpz_need_dig(dest, lhs->len + 1); dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 0 != lhs->neg, 0 != rhs->neg); dest->neg = 1; } #else mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg)); dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, (lhs->neg || rhs->neg), lhs->neg, rhs->neg); dest->neg = lhs->neg | rhs->neg; #endif } /* computes dest = lhs ^ rhs can have dest, lhs, rhs the same */ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { // make sure lhs has the most digits if (lhs->len < rhs->len) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; } #if MICROPY_OPT_MPZ_BITWISE if (lhs->neg == rhs->neg) { mpz_need_dig(dest, lhs->len); if (lhs->neg == 0) { dest->len = mpn_xor(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); } else { dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 0, 0, 0); } dest->neg = 0; } else { mpz_need_dig(dest, lhs->len + 1); dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 1, 0 == lhs->neg, 0 == rhs->neg); dest->neg = 1; } #else mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg)); dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, (lhs->neg != rhs->neg), 0 == lhs->neg, 0 == rhs->neg); dest->neg = lhs->neg ^ rhs->neg; #endif } /* computes dest = lhs * rhs can have dest, lhs, rhs the same */ void mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { if (lhs->len == 0 || rhs->len == 0) { mpz_set_from_int(dest, 0); return; } mpz_t *temp = NULL; if (lhs == dest) { lhs = temp = mpz_clone(lhs); if (rhs == dest) { rhs = lhs; } } else if (rhs == dest) { rhs = temp = mpz_clone(rhs); } mpz_need_dig(dest, lhs->len + rhs->len); // min mem l+r-1, max mem l+r memset(dest->dig, 0, dest->alloc * sizeof(mpz_dig_t)); dest->len = mpn_mul(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); if (lhs->neg == rhs->neg) { dest->neg = 0; } else { dest->neg = 1; } mpz_free(temp); } /* computes dest = lhs ** rhs can have dest, lhs, rhs the same */ void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { if (lhs->len == 0 || rhs->neg != 0) { mpz_set_from_int(dest, 0); return; } if (rhs->len == 0) { mpz_set_from_int(dest, 1); return; } mpz_t *x = mpz_clone(lhs); mpz_t *n = mpz_clone(rhs); mpz_set_from_int(dest, 1); while (n->len > 0) { if ((n->dig[0] & 1) != 0) { mpz_mul_inpl(dest, dest, x); } n->len = mpn_shr(n->dig, n->dig, n->len, 1); if (n->len == 0) { break; } mpz_mul_inpl(x, x, x); } mpz_free(x); mpz_free(n); } /* computes dest = (lhs ** rhs) % mod can have dest, lhs, rhs the same; mod can't be the same as dest */ void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t *mod) { if (lhs->len == 0 || rhs->neg != 0 || (mod->len == 1 && mod->dig[0] == 1)) { mpz_set_from_int(dest, 0); return; } mpz_set_from_int(dest, 1); if (rhs->len == 0) { return; } mpz_t *x = mpz_clone(lhs); mpz_t *n = mpz_clone(rhs); mpz_t quo; mpz_init_zero(&quo); while (n->len > 0) { if ((n->dig[0] & 1) != 0) { mpz_mul_inpl(dest, dest, x); mpz_divmod_inpl(&quo, dest, dest, mod); } n->len = mpn_shr(n->dig, n->dig, n->len, 1); if (n->len == 0) { break; } mpz_mul_inpl(x, x, x); mpz_divmod_inpl(&quo, x, x, mod); } mpz_deinit(&quo); mpz_free(x); mpz_free(n); } #if 0 these functions are unused /* computes gcd(z1, z2) based on Knuth's modified gcd algorithm (I think?) gcd(z1, z2) >= 0 gcd(0, 0) = 0 gcd(z, 0) = abs(z) */ mpz_t *mpz_gcd(const mpz_t *z1, const mpz_t *z2) { if (z1->len == 0) { // TODO: handle case of z2->alloc=0 mpz_t *a = mpz_clone(z2); a->neg = 0; return a; } else if (z2->len == 0) { mpz_t *a = mpz_clone(z1); a->neg = 0; return a; } mpz_t *a = mpz_clone(z1); mpz_t *b = mpz_clone(z2); mpz_t c; mpz_init_zero(&c); a->neg = 0; b->neg = 0; for (;;) { if (mpz_cmp(a, b) < 0) { if (a->len == 0) { mpz_free(a); mpz_deinit(&c); return b; } mpz_t *t = a; a = b; b = t; } if (!(b->len >= 2 || (b->len == 1 && b->dig[0] > 1))) { // compute b > 0; could be mpz_cmp_small_int(b, 1) > 0 break; } mpz_set(&c, b); do { mpz_add_inpl(&c, &c, &c); } while (mpz_cmp(&c, a) <= 0); c.len = mpn_shr(c.dig, c.dig, c.len, 1); mpz_sub_inpl(a, a, &c); } mpz_deinit(&c); if (b->len == 1 && b->dig[0] == 1) { // compute b == 1; could be mpz_cmp_small_int(b, 1) == 0 mpz_free(a); return b; } else { mpz_free(b); return a; } } /* computes lcm(z1, z2) = abs(z1) / gcd(z1, z2) * abs(z2) lcm(z1, z1) >= 0 lcm(0, 0) = 0 lcm(z, 0) = 0 */ mpz_t *mpz_lcm(const mpz_t *z1, const mpz_t *z2) { if (z1->len == 0 || z2->len == 0) { return mpz_zero(); } mpz_t *gcd = mpz_gcd(z1, z2); mpz_t *quo = mpz_zero(); mpz_t *rem = mpz_zero(); mpz_divmod_inpl(quo, rem, z1, gcd); mpz_mul_inpl(rem, quo, z2); mpz_free(gcd); mpz_free(quo); rem->neg = 0; return rem; } #endif /* computes new integers in quo and rem such that: quo * rhs + rem = lhs 0 <= rem < rhs can have lhs, rhs the same assumes rhs != 0 (undefined behaviour if it is) */ void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs) { assert(!mpz_is_zero(rhs)); mpz_need_dig(dest_quo, lhs->len + 1); // +1 necessary? memset(dest_quo->dig, 0, (lhs->len + 1) * sizeof(mpz_dig_t)); dest_quo->len = 0; mpz_need_dig(dest_rem, lhs->len + 1); // +1 necessary? mpz_set(dest_rem, lhs); mpn_div(dest_rem->dig, &dest_rem->len, rhs->dig, rhs->len, dest_quo->dig, &dest_quo->len); // check signs and do Python style modulo if (lhs->neg != rhs->neg) { dest_quo->neg = 1; if (!mpz_is_zero(dest_rem)) { mpz_t mpzone; mpz_init_from_int(&mpzone, -1); mpz_add_inpl(dest_quo, dest_quo, &mpzone); mpz_add_inpl(dest_rem, dest_rem, rhs); } } } #if 0 these functions are unused /* computes floor(lhs / rhs) can have lhs, rhs the same */ mpz_t *mpz_div(const mpz_t *lhs, const mpz_t *rhs) { mpz_t *quo = mpz_zero(); mpz_t rem; mpz_init_zero(&rem); mpz_divmod_inpl(quo, &rem, lhs, rhs); mpz_deinit(&rem); return quo; } /* computes lhs % rhs ( >= 0) can have lhs, rhs the same */ mpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs) { mpz_t quo; mpz_init_zero(&quo); mpz_t *rem = mpz_zero(); mpz_divmod_inpl(&quo, rem, lhs, rhs); mpz_deinit(&quo); return rem; } #endif // must return actual int value if it fits in mp_int_t mp_int_t mpz_hash(const mpz_t *z) { mp_uint_t val = 0; mpz_dig_t *d = z->dig + z->len; while (d-- > z->dig) { val = (val << DIG_SIZE) | *d; } if (z->neg != 0) { val = -val; } return val; } bool mpz_as_int_checked(const mpz_t *i, mp_int_t *value) { mp_uint_t val = 0; mpz_dig_t *d = i->dig + i->len; while (d-- > i->dig) { if (val > (~(WORD_MSBIT_HIGH) >> DIG_SIZE)) { // will overflow return false; } val = (val << DIG_SIZE) | *d; } if (i->neg != 0) { val = -val; } *value = val; return true; } bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) { if (i->neg != 0) { // can't represent signed values return false; } mp_uint_t val = 0; mpz_dig_t *d = i->dig + i->len; while (d-- > i->dig) { if (val > (~(WORD_MSBIT_HIGH) >> (DIG_SIZE - 1))) { // will overflow return false; } val = (val << DIG_SIZE) | *d; } *value = val; return true; } // writes at most len bytes to buf (so buf should be zeroed before calling) void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) { byte *b = buf; if (big_endian) { b += len; } mpz_dig_t *zdig = z->dig; int bits = 0; mpz_dbl_dig_t d = 0; mpz_dbl_dig_t carry = 1; for (size_t zlen = z->len; zlen > 0; --zlen) { bits += DIG_SIZE; d = (d << DIG_SIZE) | *zdig++; for (; bits >= 8; bits -= 8, d >>= 8) { mpz_dig_t val = d; if (z->neg) { val = (~val & 0xff) + carry; carry = val >> 8; } if (big_endian) { *--b = val; if (b == buf) { return; } } else { *b++ = val; if (b == buf + len) { return; } } } } } #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mpz_as_float(const mpz_t *i) { mp_float_t val = 0; mpz_dig_t *d = i->dig + i->len; while (d-- > i->dig) { val = val * DIG_BASE + *d; } if (i->neg != 0) { val = -val; } return val; } #endif #if 0 this function is unused char *mpz_as_str(const mpz_t *i, unsigned int base) { char *s = m_new(char, mp_int_format_size(mpz_max_num_bits(i), base, NULL, '\0')); mpz_as_str_inpl(i, base, NULL, 'a', '\0', s); return s; } #endif // assumes enough space in str as calculated by mp_int_format_size // base must be between 2 and 32 inclusive // returns length of string, not including null byte size_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, char base_char, char comma, char *str) { assert(str != NULL); assert(2 <= base && base <= 32); size_t ilen = i->len; char *s = str; if (ilen == 0) { if (prefix) { while (*prefix) *s++ = *prefix++; } *s++ = '0'; *s = '\0'; return s - str; } // make a copy of mpz digits, so we can do the div/mod calculation mpz_dig_t *dig = m_new(mpz_dig_t, ilen); memcpy(dig, i->dig, ilen * sizeof(mpz_dig_t)); // convert char *last_comma = str; bool done; do { mpz_dig_t *d = dig + ilen; mpz_dbl_dig_t a = 0; // compute next remainder while (--d >= dig) { a = (a << DIG_SIZE) | *d; *d = a / base; a %= base; } // convert to character a += '0'; if (a > '9') { a += base_char - '9' - 1; } *s++ = a; // check if number is zero done = true; for (d = dig; d < dig + ilen; ++d) { if (*d != 0) { done = false; break; } } if (comma && (s - last_comma) == 3) { *s++ = comma; last_comma = s; } } while (!done); // free the copy of the digits array m_del(mpz_dig_t, dig, ilen); if (prefix) { const char *p = &prefix[strlen(prefix)]; while (p > prefix) { *s++ = *--p; } } if (i->neg != 0) { *s++ = '-'; } // reverse string for (char *u = str, *v = s - 1; u < v; ++u, --v) { char temp = *u; *u = *v; *v = temp; } *s = '\0'; // null termination return s - str; } #endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ micropython-1.12/py/mpz.h000066400000000000000000000136041357706137100154350ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_MPZ_H #define MICROPY_INCLUDED_PY_MPZ_H #include #include "py/mpconfig.h" #include "py/misc.h" // This mpz module implements arbitrary precision integers. // // The storage for each digit is defined by mpz_dig_t. The actual number of // bits in mpz_dig_t that are used is defined by MPZ_DIG_SIZE. The machine must // also provide a type that is twice as wide as mpz_dig_t, in both signed and // unsigned versions. // // MPZ_DIG_SIZE can be between 4 and 8*sizeof(mpz_dig_t), but it makes most // sense to have it as large as possible. If MPZ_DIG_SIZE is not already // defined then it is auto-detected below, depending on the machine. The types // are then set based on the value of MPZ_DIG_SIZE (although they can be freely // changed so long as the constraints mentioned above are met). #ifndef MPZ_DIG_SIZE #if defined(__x86_64__) || defined(_WIN64) // 64-bit machine, using 32-bit storage for digits #define MPZ_DIG_SIZE (32) #else // default: 32-bit machine, using 16-bit storage for digits #define MPZ_DIG_SIZE (16) #endif #endif #if MPZ_DIG_SIZE > 16 #define MPZ_DBL_DIG_SIZE (64) typedef uint32_t mpz_dig_t; typedef uint64_t mpz_dbl_dig_t; typedef int64_t mpz_dbl_dig_signed_t; #elif MPZ_DIG_SIZE > 8 #define MPZ_DBL_DIG_SIZE (32) typedef uint16_t mpz_dig_t; typedef uint32_t mpz_dbl_dig_t; typedef int32_t mpz_dbl_dig_signed_t; #elif MPZ_DIG_SIZE > 4 #define MPZ_DBL_DIG_SIZE (16) typedef uint8_t mpz_dig_t; typedef uint16_t mpz_dbl_dig_t; typedef int16_t mpz_dbl_dig_signed_t; #else #define MPZ_DBL_DIG_SIZE (8) typedef uint8_t mpz_dig_t; typedef uint8_t mpz_dbl_dig_t; typedef int8_t mpz_dbl_dig_signed_t; #endif #ifdef _WIN64 #ifdef __MINGW32__ #define MPZ_LONG_1 1LL #else #define MPZ_LONG_1 1i64 #endif #else #define MPZ_LONG_1 1L #endif // these define the maximum storage needed to hold an int or long long #define MPZ_NUM_DIG_FOR_INT ((sizeof(mp_int_t) * 8 + MPZ_DIG_SIZE - 1) / MPZ_DIG_SIZE) #define MPZ_NUM_DIG_FOR_LL ((sizeof(long long) * 8 + MPZ_DIG_SIZE - 1) / MPZ_DIG_SIZE) typedef struct _mpz_t { size_t neg : 1; size_t fixed_dig : 1; size_t alloc : 8 * sizeof(size_t) - 2; size_t len; mpz_dig_t *dig; } mpz_t; // convenience macro to declare an mpz with a digit array from the stack, initialised by an integer #define MPZ_CONST_INT(z, val) mpz_t z; mpz_dig_t z ## _digits[MPZ_NUM_DIG_FOR_INT]; mpz_init_fixed_from_int(&z, z_digits, MPZ_NUM_DIG_FOR_INT, val); void mpz_init_zero(mpz_t *z); void mpz_init_from_int(mpz_t *z, mp_int_t val); void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, size_t dig_alloc, mp_int_t val); void mpz_deinit(mpz_t *z); void mpz_set(mpz_t *dest, const mpz_t *src); void mpz_set_from_int(mpz_t *z, mp_int_t src); void mpz_set_from_ll(mpz_t *z, long long i, bool is_signed); #if MICROPY_PY_BUILTINS_FLOAT void mpz_set_from_float(mpz_t *z, mp_float_t src); #endif size_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigned int base); void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf); static inline bool mpz_is_zero(const mpz_t *z) { return z->len == 0; } static inline bool mpz_is_neg(const mpz_t *z) { return z->len != 0 && z->neg != 0; } int mpz_cmp(const mpz_t *lhs, const mpz_t *rhs); void mpz_abs_inpl(mpz_t *dest, const mpz_t *z); void mpz_neg_inpl(mpz_t *dest, const mpz_t *z); void mpz_not_inpl(mpz_t *dest, const mpz_t *z); void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs); void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs); void mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t *mod); void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs); static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_SIZE; } mp_int_t mpz_hash(const mpz_t *z); bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value); bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value); void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf); #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mpz_as_float(const mpz_t *z); #endif size_t mpz_as_str_inpl(const mpz_t *z, unsigned int base, const char *prefix, char base_char, char comma, char *str); #endif // MICROPY_INCLUDED_PY_MPZ_H micropython-1.12/py/nativeglue.c000066400000000000000000000241251357706137100167650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/runtime.h" #include "py/smallint.h" #include "py/nativeglue.h" #include "py/gc.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif #if MICROPY_EMIT_NATIVE int mp_native_type_from_qstr(qstr qst) { switch (qst) { case MP_QSTR_object: return MP_NATIVE_TYPE_OBJ; case MP_QSTR_bool: return MP_NATIVE_TYPE_BOOL; case MP_QSTR_int: return MP_NATIVE_TYPE_INT; case MP_QSTR_uint: return MP_NATIVE_TYPE_UINT; case MP_QSTR_ptr: return MP_NATIVE_TYPE_PTR; case MP_QSTR_ptr8: return MP_NATIVE_TYPE_PTR8; case MP_QSTR_ptr16: return MP_NATIVE_TYPE_PTR16; case MP_QSTR_ptr32: return MP_NATIVE_TYPE_PTR32; default: return -1; } } // convert a MicroPython object to a valid native value based on type mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type) { DEBUG_printf("mp_native_from_obj(%p, " UINT_FMT ")\n", obj, type); switch (type & 0xf) { case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj; case MP_NATIVE_TYPE_BOOL: return mp_obj_is_true(obj); case MP_NATIVE_TYPE_INT: case MP_NATIVE_TYPE_UINT: return mp_obj_get_int_truncated(obj); default: { // cast obj to a pointer mp_buffer_info_t bufinfo; if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_READ)) { return (mp_uint_t)bufinfo.buf; } else { // assume obj is an integer that represents an address return mp_obj_get_int_truncated(obj); } } } } #endif #if MICROPY_EMIT_MACHINE_CODE // convert a native value to a MicroPython object based on type mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) { DEBUG_printf("mp_native_to_obj(" UINT_FMT ", " UINT_FMT ")\n", val, type); switch (type & 0xf) { case MP_NATIVE_TYPE_OBJ: return (mp_obj_t)val; case MP_NATIVE_TYPE_BOOL: return mp_obj_new_bool(val); case MP_NATIVE_TYPE_INT: return mp_obj_new_int(val); case MP_NATIVE_TYPE_UINT: return mp_obj_new_int_from_uint(val); default: // a pointer // we return just the value of the pointer as an integer return mp_obj_new_int_from_uint(val); } } #endif #if MICROPY_EMIT_NATIVE && !MICROPY_DYNAMIC_COMPILER #if !MICROPY_PY_BUILTINS_SET mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) { (void)n_args; (void)items; mp_raise_msg(&mp_type_RuntimeError, "set unsupported"); } void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) { (void)self_in; (void)item; mp_raise_msg(&mp_type_RuntimeError, "set unsupported"); } #endif #if !MICROPY_PY_BUILTINS_SLICE mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) { (void)ostart; (void)ostop; (void)ostep; mp_raise_msg(&mp_type_RuntimeError, "slice unsupported"); } #endif STATIC mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) { if (new_globals == NULL) { // Globals were the originally the same so don't restore them return NULL; } mp_obj_dict_t *old_globals = mp_globals_get(); if (old_globals == new_globals) { // Don't set globals if they are the same, and return NULL to indicate this return NULL; } mp_globals_set(new_globals); return old_globals; } // wrapper that accepts n_args and n_kw in one argument // (native emitter can only pass at most 3 arguments to a function) STATIC mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) { return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args); } // wrapper that makes raise obj and raises it // END_FINALLY opcode requires that we don't raise if o==None STATIC void mp_native_raise(mp_obj_t o) { if (o != MP_OBJ_NULL && o != mp_const_none) { nlr_raise(mp_make_raise_obj(o)); } } // wrapper that handles iterator buffer STATIC mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) { if (iter == NULL) { return mp_getiter(obj, NULL); } else { obj = mp_getiter(obj, iter); if (obj != MP_OBJ_FROM_PTR(iter)) { // Iterator didn't use the stack so indicate that with MP_OBJ_NULL. iter->base.type = MP_OBJ_NULL; iter->buf[0] = obj; } return NULL; } } // wrapper that handles iterator buffer STATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) { mp_obj_t obj; if (iter->base.type == MP_OBJ_NULL) { obj = iter->buf[0]; } else { obj = MP_OBJ_FROM_PTR(iter); } return mp_iternext(obj); } STATIC bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value) { mp_vm_return_kind_t ret_kind; nlr_buf_t nlr_buf; mp_obj_t throw_value = *ret_value; if (nlr_push(&nlr_buf) == 0) { if (throw_value != MP_OBJ_NULL) { send_value = MP_OBJ_NULL; } ret_kind = mp_resume(gen, send_value, throw_value, ret_value); nlr_pop(); } else { ret_kind = MP_VM_RETURN_EXCEPTION; *ret_value = nlr_buf.ret_val; } if (ret_kind == MP_VM_RETURN_YIELD) { return true; } else if (ret_kind == MP_VM_RETURN_NORMAL) { if (*ret_value == MP_OBJ_STOP_ITERATION) { *ret_value = mp_const_none; } } else { assert(ret_kind == MP_VM_RETURN_EXCEPTION); if (!mp_obj_exception_match(*ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { nlr_raise(*ret_value); } *ret_value = mp_obj_exception_get_value(*ret_value); } if (throw_value != MP_OBJ_NULL && mp_obj_exception_match(throw_value, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { nlr_raise(mp_make_raise_obj(throw_value)); } return false; } #if MICROPY_PY_BUILTINS_FLOAT STATIC mp_obj_t mp_obj_new_float_from_f(float f) { return mp_obj_new_float((mp_float_t)f); } STATIC mp_obj_t mp_obj_new_float_from_d(double d) { return mp_obj_new_float((mp_float_t)d); } STATIC float mp_obj_get_float_to_f(mp_obj_t o) { return (float)mp_obj_get_float(o); } STATIC double mp_obj_get_float_to_d(mp_obj_t o) { return (double)mp_obj_get_float(o); } #else STATIC mp_obj_t mp_obj_new_float_from_f(float f) { (void)f; mp_raise_msg(&mp_type_RuntimeError, "float unsupported"); } STATIC mp_obj_t mp_obj_new_float_from_d(double d) { (void)d; mp_raise_msg(&mp_type_RuntimeError, "float unsupported"); } STATIC float mp_obj_get_float_to_f(mp_obj_t o) { (void)o; mp_raise_msg(&mp_type_RuntimeError, "float unsupported"); } STATIC double mp_obj_get_float_to_d(mp_obj_t o) { (void)o; mp_raise_msg(&mp_type_RuntimeError, "float unsupported"); } #endif // these must correspond to the respective enum in runtime0.h const mp_fun_table_t mp_fun_table = { &mp_const_none_obj, &mp_const_false_obj, &mp_const_true_obj, mp_native_from_obj, mp_native_to_obj, mp_native_swap_globals, mp_load_name, mp_load_global, mp_load_build_class, mp_load_attr, mp_load_method, mp_load_super_method, mp_store_name, mp_store_global, mp_store_attr, mp_obj_subscr, mp_obj_is_true, mp_unary_op, mp_binary_op, mp_obj_new_tuple, mp_obj_new_list, mp_obj_new_dict, mp_obj_new_set, mp_obj_set_store, mp_obj_list_append, mp_obj_dict_store, mp_make_function_from_raw_code, mp_native_call_function_n_kw, mp_call_method_n_kw, mp_call_method_n_kw_var, mp_native_getiter, mp_native_iternext, #if MICROPY_NLR_SETJMP nlr_push_tail, #else nlr_push, #endif nlr_pop, mp_native_raise, mp_import_name, mp_import_from, mp_import_all, mp_obj_new_slice, mp_unpack_sequence, mp_unpack_ex, mp_delete_name, mp_delete_global, mp_make_closure_from_raw_code, mp_arg_check_num_sig, mp_setup_code_state, mp_small_int_floor_divide, mp_small_int_modulo, mp_native_yield_from, #if MICROPY_NLR_SETJMP setjmp, #else NULL, #endif // Additional entries for dynamic runtime, starts at index 50 memset, memmove, gc_realloc, mp_printf, mp_vprintf, mp_raise_msg, mp_obj_get_type, mp_obj_new_str, mp_obj_new_bytes, mp_obj_new_bytearray_by_ref, mp_obj_new_float_from_f, mp_obj_new_float_from_d, mp_obj_get_float_to_f, mp_obj_get_float_to_d, mp_get_buffer_raise, mp_get_stream_raise, &mp_plat_print, &mp_type_type, &mp_type_str, &mp_type_list, &mp_type_dict, &mp_type_fun_builtin_0, &mp_type_fun_builtin_1, &mp_type_fun_builtin_2, &mp_type_fun_builtin_3, &mp_type_fun_builtin_var, &mp_stream_read_obj, &mp_stream_readinto_obj, &mp_stream_unbuffered_readline_obj, &mp_stream_write_obj, }; #endif // MICROPY_EMIT_NATIVE micropython-1.12/py/nativeglue.h000066400000000000000000000167111357706137100167740ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_NATIVEGLUE_H #define MICROPY_INCLUDED_PY_NATIVEGLUE_H #include #include "py/obj.h" #include "py/persistentcode.h" #include "py/stream.h" typedef enum { MP_F_CONST_NONE_OBJ = 0, MP_F_CONST_FALSE_OBJ, MP_F_CONST_TRUE_OBJ, MP_F_CONVERT_OBJ_TO_NATIVE, MP_F_CONVERT_NATIVE_TO_OBJ, MP_F_NATIVE_SWAP_GLOBALS, MP_F_LOAD_NAME, MP_F_LOAD_GLOBAL, MP_F_LOAD_BUILD_CLASS, MP_F_LOAD_ATTR, MP_F_LOAD_METHOD, MP_F_LOAD_SUPER_METHOD, MP_F_STORE_NAME, MP_F_STORE_GLOBAL, MP_F_STORE_ATTR, MP_F_OBJ_SUBSCR, MP_F_OBJ_IS_TRUE, MP_F_UNARY_OP, MP_F_BINARY_OP, MP_F_BUILD_TUPLE, MP_F_BUILD_LIST, MP_F_BUILD_MAP, MP_F_BUILD_SET, MP_F_STORE_SET, MP_F_LIST_APPEND, MP_F_STORE_MAP, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, MP_F_NATIVE_CALL_FUNCTION_N_KW, MP_F_CALL_METHOD_N_KW, MP_F_CALL_METHOD_N_KW_VAR, MP_F_NATIVE_GETITER, MP_F_NATIVE_ITERNEXT, MP_F_NLR_PUSH, MP_F_NLR_POP, MP_F_NATIVE_RAISE, MP_F_IMPORT_NAME, MP_F_IMPORT_FROM, MP_F_IMPORT_ALL, MP_F_NEW_SLICE, MP_F_UNPACK_SEQUENCE, MP_F_UNPACK_EX, MP_F_DELETE_NAME, MP_F_DELETE_GLOBAL, MP_F_MAKE_CLOSURE_FROM_RAW_CODE, MP_F_ARG_CHECK_NUM_SIG, MP_F_SETUP_CODE_STATE, MP_F_SMALL_INT_FLOOR_DIVIDE, MP_F_SMALL_INT_MODULO, MP_F_NATIVE_YIELD_FROM, MP_F_SETJMP, MP_F_NUMBER_OF, } mp_fun_kind_t; typedef struct _mp_fun_table_t { mp_const_obj_t const_none; mp_const_obj_t const_false; mp_const_obj_t const_true; mp_uint_t (*native_from_obj)(mp_obj_t obj, mp_uint_t type); mp_obj_t (*native_to_obj)(mp_uint_t val, mp_uint_t type); mp_obj_dict_t *(*swap_globals)(mp_obj_dict_t *new_globals); mp_obj_t (*load_name)(qstr qst); mp_obj_t (*load_global)(qstr qst); mp_obj_t (*load_build_class)(void); mp_obj_t (*load_attr)(mp_obj_t base, qstr attr); void (*load_method)(mp_obj_t base, qstr attr, mp_obj_t *dest); void (*load_super_method)(qstr attr, mp_obj_t *dest); void (*store_name)(qstr qst, mp_obj_t obj); void (*store_global)(qstr qst, mp_obj_t obj); void (*store_attr)(mp_obj_t base, qstr attr, mp_obj_t val); mp_obj_t (*obj_subscr)(mp_obj_t base, mp_obj_t index, mp_obj_t val); bool (*obj_is_true)(mp_obj_t arg); mp_obj_t (*unary_op)(mp_unary_op_t op, mp_obj_t arg); mp_obj_t (*binary_op)(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs); mp_obj_t (*new_tuple)(size_t n, const mp_obj_t *items); mp_obj_t (*new_list)(size_t n, mp_obj_t *items); mp_obj_t (*new_dict)(size_t n_args); mp_obj_t (*new_set)(size_t n_args, mp_obj_t *items); void (*set_store)(mp_obj_t self_in, mp_obj_t item); mp_obj_t (*list_append)(mp_obj_t self_in, mp_obj_t arg); mp_obj_t (*dict_store)(mp_obj_t self_in, mp_obj_t key, mp_obj_t value); mp_obj_t (*make_function_from_raw_code)(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args); mp_obj_t (*call_function_n_kw)(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args); mp_obj_t (*call_method_n_kw)(size_t n_args, size_t n_kw, const mp_obj_t *args); mp_obj_t (*call_method_n_kw_var)(bool have_self, size_t n_args_n_kw, const mp_obj_t *args); mp_obj_t (*getiter)(mp_obj_t obj, mp_obj_iter_buf_t *iter); mp_obj_t (*iternext)(mp_obj_iter_buf_t *iter); unsigned int (*nlr_push)(nlr_buf_t *); void (*nlr_pop)(void); void (*raise)(mp_obj_t o); mp_obj_t (*import_name)(qstr name, mp_obj_t fromlist, mp_obj_t level); mp_obj_t (*import_from)(mp_obj_t module, qstr name); void (*import_all)(mp_obj_t module); mp_obj_t (*new_slice)(mp_obj_t start, mp_obj_t stop, mp_obj_t step); void (*unpack_sequence)(mp_obj_t seq, size_t num, mp_obj_t *items); void (*unpack_ex)(mp_obj_t seq, size_t num, mp_obj_t *items); void (*delete_name)(qstr qst); void (*delete_global)(qstr qst); mp_obj_t (*make_closure_from_raw_code)(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args); void (*arg_check_num_sig)(size_t n_args, size_t n_kw, uint32_t sig); void (*setup_code_state)(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args); mp_int_t (*small_int_floor_divide)(mp_int_t num, mp_int_t denom); mp_int_t (*small_int_modulo)(mp_int_t dividend, mp_int_t divisor); bool (*yield_from)(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value); void *setjmp; // Additional entries for dynamic runtime, starts at index 50 void *(*memset_)(void *s, int c, size_t n); void *(*memmove_)(void *dest, const void *src, size_t n); void *(*realloc_)(void *ptr, size_t n_bytes, bool allow_move); int (*printf_)(const mp_print_t *print, const char *fmt, ...); int (*vprintf_)(const mp_print_t *print, const char *fmt, va_list args); #if defined(__GNUC__) NORETURN // Only certain compilers support no-return attributes in function pointer declarations #endif void (*raise_msg)(const mp_obj_type_t *exc_type, const char *msg); mp_obj_type_t *(*obj_get_type)(mp_const_obj_t o_in); mp_obj_t (*obj_new_str)(const char* data, size_t len); mp_obj_t (*obj_new_bytes)(const byte* data, size_t len); mp_obj_t (*obj_new_bytearray_by_ref)(size_t n, void *items); mp_obj_t (*obj_new_float_from_f)(float f); mp_obj_t (*obj_new_float_from_d)(double d); float (*obj_get_float_to_f)(mp_obj_t o); double (*obj_get_float_to_d)(mp_obj_t o); void (*get_buffer_raise)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); const mp_stream_p_t *(*get_stream_raise)(mp_obj_t self_in, int flags); const mp_print_t *plat_print; const mp_obj_type_t *type_type; const mp_obj_type_t *type_str; const mp_obj_type_t *type_list; const mp_obj_type_t *type_dict; const mp_obj_type_t *type_fun_builtin_0; const mp_obj_type_t *type_fun_builtin_1; const mp_obj_type_t *type_fun_builtin_2; const mp_obj_type_t *type_fun_builtin_3; const mp_obj_type_t *type_fun_builtin_var; const mp_obj_fun_builtin_var_t *stream_read_obj; const mp_obj_fun_builtin_var_t *stream_readinto_obj; const mp_obj_fun_builtin_var_t *stream_unbuffered_readline_obj; const mp_obj_fun_builtin_var_t *stream_write_obj; } mp_fun_table_t; extern const mp_fun_table_t mp_fun_table; #endif // MICROPY_INCLUDED_PY_NATIVEGLUE_H micropython-1.12/py/nlr.c000066400000000000000000000037601357706137100154170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #if !MICROPY_NLR_SETJMP // When not using setjmp, nlr_push_tail is called from inline asm so needs special care #if MICROPY_NLR_X86 && MICROPY_NLR_OS_WINDOWS // On these 32-bit platforms make sure nlr_push_tail doesn't have a leading underscore unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail"); #else // LTO can't see inside inline asm functions so explicitly mark nlr_push_tail as used __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); #endif #endif unsigned int nlr_push_tail(nlr_buf_t *nlr) { nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); nlr->prev = *top; MP_NLR_SAVE_PYSTACK(nlr); *top = nlr; return 0; // normal return } void nlr_pop(void) { nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); *top = (*top)->prev; } micropython-1.12/py/nlr.h000066400000000000000000000135321357706137100154220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_NLR_H #define MICROPY_INCLUDED_PY_NLR_H // non-local return // exception handling, basically a stack of setjmp/longjmp buffers #include #include #include "py/mpconfig.h" #define MICROPY_NLR_NUM_REGS_X86 (6) #define MICROPY_NLR_NUM_REGS_X64 (8) #define MICROPY_NLR_NUM_REGS_X64_WIN (10) #define MICROPY_NLR_NUM_REGS_ARM_THUMB (10) #define MICROPY_NLR_NUM_REGS_ARM_THUMB_FP (10 + 6) #define MICROPY_NLR_NUM_REGS_XTENSA (10) #define MICROPY_NLR_NUM_REGS_XTENSAWIN (17) // If MICROPY_NLR_SETJMP is not enabled then auto-detect the machine arch #if !MICROPY_NLR_SETJMP // A lot of nlr-related things need different treatment on Windows #if defined(_WIN32) || defined(__CYGWIN__) #define MICROPY_NLR_OS_WINDOWS 1 #else #define MICROPY_NLR_OS_WINDOWS 0 #endif #if defined(__i386__) #define MICROPY_NLR_X86 (1) #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_X86) #elif defined(__x86_64__) #define MICROPY_NLR_X64 (1) #if MICROPY_NLR_OS_WINDOWS #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_X64_WIN) #else #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_X64) #endif #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) #define MICROPY_NLR_THUMB (1) #if defined(__SOFTFP__) #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_ARM_THUMB) #else // With hardware FP registers s16-s31 are callee save so in principle // should be saved and restored by the NLR code. gcc only uses s16-s21 // so only save/restore those as an optimisation. #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_ARM_THUMB_FP) #endif #elif defined(__xtensa__) #define MICROPY_NLR_XTENSA (1) #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_XTENSA) #elif defined(__powerpc__) #define MICROPY_NLR_POWERPC (1) // this could be less but using 128 for safety #define MICROPY_NLR_NUM_REGS (128) #else #define MICROPY_NLR_SETJMP (1) //#warning "No native NLR support for this arch, using setjmp implementation" #endif #endif #if MICROPY_NLR_SETJMP #include #endif typedef struct _nlr_buf_t nlr_buf_t; struct _nlr_buf_t { // the entries here must all be machine word size nlr_buf_t *prev; void *ret_val; // always a concrete object (an exception instance) #if MICROPY_NLR_SETJMP jmp_buf jmpbuf; #else void *regs[MICROPY_NLR_NUM_REGS]; #endif #if MICROPY_ENABLE_PYSTACK void *pystack; #endif }; // Helper macros to save/restore the pystack state #if MICROPY_ENABLE_PYSTACK #define MP_NLR_SAVE_PYSTACK(nlr_buf) (nlr_buf)->pystack = MP_STATE_THREAD(pystack_cur) #define MP_NLR_RESTORE_PYSTACK(nlr_buf) MP_STATE_THREAD(pystack_cur) = (nlr_buf)->pystack #else #define MP_NLR_SAVE_PYSTACK(nlr_buf) (void)nlr_buf #define MP_NLR_RESTORE_PYSTACK(nlr_buf) (void)nlr_buf #endif // Helper macro to use at the start of a specific nlr_jump implementation #define MP_NLR_JUMP_HEAD(val, top) \ nlr_buf_t **_top_ptr = &MP_STATE_THREAD(nlr_top); \ nlr_buf_t *top = *_top_ptr; \ if (top == NULL) { \ nlr_jump_fail(val); \ } \ top->ret_val = val; \ MP_NLR_RESTORE_PYSTACK(top); \ *_top_ptr = top->prev; \ #if MICROPY_NLR_SETJMP // nlr_push() must be defined as a macro, because "The stack context will be // invalidated if the function which called setjmp() returns." // For this case it is safe to call nlr_push_tail() first. #define nlr_push(buf) (nlr_push_tail(buf), setjmp((buf)->jmpbuf)) #else unsigned int nlr_push(nlr_buf_t *); #endif unsigned int nlr_push_tail(nlr_buf_t *top); void nlr_pop(void); NORETURN void nlr_jump(void *val); // This must be implemented by a port. It's called by nlr_jump // if no nlr buf has been pushed. It must not return, but rather // should bail out with a fatal error. NORETURN void nlr_jump_fail(void *val); // use nlr_raise instead of nlr_jump so that debugging is easier #ifndef MICROPY_DEBUG_NLR #define nlr_raise(val) nlr_jump(MP_OBJ_TO_PTR(val)) #else #include "mpstate.h" #define nlr_raise(val) \ do { \ /*printf("nlr_raise: nlr_top=%p\n", MP_STATE_THREAD(nlr_top)); \ fflush(stdout);*/ \ void *_val = MP_OBJ_TO_PTR(val); \ assert(_val != NULL); \ assert(mp_obj_is_exception_instance(val)); \ nlr_jump(_val); \ } while (0) #if !MICROPY_NLR_SETJMP #define nlr_push(val) \ assert(MP_STATE_THREAD(nlr_top) != val),nlr_push(val) /* #define nlr_push(val) \ printf("nlr_push: before: nlr_top=%p, val=%p\n", MP_STATE_THREAD(nlr_top), val),assert(MP_STATE_THREAD(nlr_top) != val),nlr_push(val) */ #endif #endif #endif // MICROPY_INCLUDED_PY_NLR_H micropython-1.12/py/nlrpowerpc.c000066400000000000000000000063601357706137100170160ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019, Michael Neuling, IBM Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #if MICROPY_NLR_POWERPC #undef nlr_push // Saving all ABI non-vol registers here unsigned int nlr_push(nlr_buf_t *nlr) { __asm__ volatile( "li 4, 0x4eed ; " // Store canary "std 4, 0x00(%0) ;" "std 0, 0x08(%0) ;" "std 1, 0x10(%0) ;" "std 2, 0x18(%0) ;" "std 14, 0x20(%0) ;" "std 15, 0x28(%0) ;" "std 16, 0x30(%0) ;" "std 17, 0x38(%0) ;" "std 18, 0x40(%0) ;" "std 19, 0x48(%0) ;" "std 20, 0x50(%0) ;" "std 21, 0x58(%0) ;" "std 22, 0x60(%0) ;" "std 23, 0x68(%0) ;" "std 24, 0x70(%0) ;" "std 25, 0x78(%0) ;" "std 26, 0x80(%0) ;" "std 27, 0x88(%0) ;" "std 28, 0x90(%0) ;" "std 29, 0x98(%0) ;" "std 30, 0xA0(%0) ;" "std 31, 0xA8(%0) ;" "mfcr 4 ; " "std 4, 0xB0(%0) ;" "mflr 4 ;" "std 4, 0xB8(%0) ;" "li 4, nlr_push_tail@l ;" "oris 4, 4, nlr_push_tail@h ;" "mtctr 4 ;" "mr 3, %1 ; " "bctr ;" : : "r"(&nlr->regs), "r"(nlr) : ); return 0; } NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm__ volatile( "ld 3, 0x0(%0) ;" "cmpdi 3, 0x4eed ; " // Check canary "bne . ; " "ld 0, 0x08(%0) ;" "ld 1, 0x10(%0) ;" "ld 2, 0x18(%0) ;" "ld 14, 0x20(%0) ;" "ld 15, 0x28(%0) ;" "ld 16, 0x30(%0) ;" "ld 17, 0x38(%0) ;" "ld 18, 0x40(%0) ;" "ld 19, 0x48(%0) ;" "ld 20, 0x50(%0) ;" "ld 21, 0x58(%0) ;" "ld 22, 0x60(%0) ;" "ld 23, 0x68(%0) ;" "ld 24, 0x70(%0) ;" "ld 25, 0x78(%0) ;" "ld 26, 0x80(%0) ;" "ld 27, 0x88(%0) ;" "ld 28, 0x90(%0) ;" "ld 29, 0x98(%0) ;" "ld 30, 0xA0(%0) ;" "ld 31, 0xA8(%0) ;" "ld 3, 0xB0(%0) ;" "mtcr 3 ;" "ld 3, 0xB8(%0) ;" "mtlr 3 ; " "li 3, 1;" "blr ;" : : "r"(&top->regs) : ); MP_UNREACHABLE; } #endif // MICROPY_NLR_POWERPC micropython-1.12/py/nlrsetjmp.c000066400000000000000000000030421357706137100166330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #if MICROPY_NLR_SETJMP void nlr_jump(void *val) { nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top); nlr_buf_t *top = *top_ptr; if (top == NULL) { nlr_jump_fail(val); } top->ret_val = val; MP_NLR_RESTORE_PYSTACK(top); *top_ptr = top->prev; longjmp(top->jmpbuf, 1); } #endif micropython-1.12/py/nlrthumb.c000066400000000000000000000131301357706137100164470ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #if MICROPY_NLR_THUMB #undef nlr_push // We only need the functions here if we are on arm/thumb, and we are not // using setjmp/longjmp. // // For reference, arm/thumb callee save regs are: // r4-r11, r13=sp __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { __asm volatile ( "str r4, [r0, #12] \n" // store r4 into nlr_buf "str r5, [r0, #16] \n" // store r5 into nlr_buf "str r6, [r0, #20] \n" // store r6 into nlr_buf "str r7, [r0, #24] \n" // store r7 into nlr_buf #if !defined(__thumb2__) "mov r1, r8 \n" "str r1, [r0, #28] \n" // store r8 into nlr_buf "mov r1, r9 \n" "str r1, [r0, #32] \n" // store r9 into nlr_buf "mov r1, r10 \n" "str r1, [r0, #36] \n" // store r10 into nlr_buf "mov r1, r11 \n" "str r1, [r0, #40] \n" // store r11 into nlr_buf "mov r1, r13 \n" "str r1, [r0, #44] \n" // store r13=sp into nlr_buf "mov r1, lr \n" "str r1, [r0, #8] \n" // store lr into nlr_buf #else "str r8, [r0, #28] \n" // store r8 into nlr_buf "str r9, [r0, #32] \n" // store r9 into nlr_buf "str r10, [r0, #36] \n" // store r10 into nlr_buf "str r11, [r0, #40] \n" // store r11 into nlr_buf "str r13, [r0, #44] \n" // store r13=sp into nlr_buf #if MICROPY_NLR_NUM_REGS == 16 "vstr d8, [r0, #48] \n" // store s16-s17 into nlr_buf "vstr d9, [r0, #56] \n" // store s18-s19 into nlr_buf "vstr d10, [r0, #64] \n" // store s20-s21 into nlr_buf #endif "str lr, [r0, #8] \n" // store lr into nlr_buf #endif #if !defined(__thumb2__) "ldr r1, nlr_push_tail_var \n" "bx r1 \n" // do the rest in C ".align 2 \n" "nlr_push_tail_var: .word nlr_push_tail \n" #else #if defined(__APPLE__) || defined(__MACH__) "b _nlr_push_tail \n" // do the rest in C #else "b nlr_push_tail \n" // do the rest in C #endif #endif ); #if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) // Older versions of gcc give an error when naked functions don't return a value // Additionally exclude Clang as it also defines __GNUC__ but doesn't need this statement return 0; #endif } NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "mov r0, %0 \n" // r0 points to nlr_buf "ldr r4, [r0, #12] \n" // load r4 from nlr_buf "ldr r5, [r0, #16] \n" // load r5 from nlr_buf "ldr r6, [r0, #20] \n" // load r6 from nlr_buf "ldr r7, [r0, #24] \n" // load r7 from nlr_buf #if !defined(__thumb2__) "ldr r1, [r0, #28] \n" // load r8 from nlr_buf "mov r8, r1 \n" "ldr r1, [r0, #32] \n" // load r9 from nlr_buf "mov r9, r1 \n" "ldr r1, [r0, #36] \n" // load r10 from nlr_buf "mov r10, r1 \n" "ldr r1, [r0, #40] \n" // load r11 from nlr_buf "mov r11, r1 \n" "ldr r1, [r0, #44] \n" // load r13=sp from nlr_buf "mov r13, r1 \n" "ldr r1, [r0, #8] \n" // load lr from nlr_buf "mov lr, r1 \n" #else "ldr r8, [r0, #28] \n" // load r8 from nlr_buf "ldr r9, [r0, #32] \n" // load r9 from nlr_buf "ldr r10, [r0, #36] \n" // load r10 from nlr_buf "ldr r11, [r0, #40] \n" // load r11 from nlr_buf "ldr r13, [r0, #44] \n" // load r13=sp from nlr_buf #if MICROPY_NLR_NUM_REGS == 16 "vldr d8, [r0, #48] \n" // load s16-s17 from nlr_buf "vldr d9, [r0, #56] \n" // load s18-s19 from nlr_buf "vldr d10, [r0, #64] \n" // load s20-s21 from nlr_buf #endif "ldr lr, [r0, #8] \n" // load lr from nlr_buf #endif "movs r0, #1 \n" // return 1, non-local return "bx lr \n" // return : // output operands : "r"(top) // input operands : // clobbered registers ); MP_UNREACHABLE } #endif // MICROPY_NLR_THUMB micropython-1.12/py/nlrx64.c000066400000000000000000000106011357706137100157510ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #if MICROPY_NLR_X64 #undef nlr_push // x86-64 callee-save registers are: // rbx, rbp, rsp, r12, r13, r14, r15 __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); unsigned int nlr_push(nlr_buf_t *nlr) { (void)nlr; #if MICROPY_NLR_OS_WINDOWS __asm volatile ( "movq (%rsp), %rax \n" // load return %rip "movq %rax, 16(%rcx) \n" // store %rip into nlr_buf "movq %rbp, 24(%rcx) \n" // store %rbp into nlr_buf "movq %rsp, 32(%rcx) \n" // store %rsp into nlr_buf "movq %rbx, 40(%rcx) \n" // store %rbx into nlr_buf "movq %r12, 48(%rcx) \n" // store %r12 into nlr_buf "movq %r13, 56(%rcx) \n" // store %r13 into nlr_buf "movq %r14, 64(%rcx) \n" // store %r14 into nlr_buf "movq %r15, 72(%rcx) \n" // store %r15 into nlr_buf "movq %rdi, 80(%rcx) \n" // store %rdr into nlr_buf "movq %rsi, 88(%rcx) \n" // store %rsi into nlr_buf "jmp nlr_push_tail \n" // do the rest in C ); #else __asm volatile ( #if defined(__APPLE__) || defined(__MACH__) "pop %rbp \n" // undo function's prelude #endif "movq (%rsp), %rax \n" // load return %rip "movq %rax, 16(%rdi) \n" // store %rip into nlr_buf "movq %rbp, 24(%rdi) \n" // store %rbp into nlr_buf "movq %rsp, 32(%rdi) \n" // store %rsp into nlr_buf "movq %rbx, 40(%rdi) \n" // store %rbx into nlr_buf "movq %r12, 48(%rdi) \n" // store %r12 into nlr_buf "movq %r13, 56(%rdi) \n" // store %r13 into nlr_buf "movq %r14, 64(%rdi) \n" // store %r14 into nlr_buf "movq %r15, 72(%rdi) \n" // store %r15 into nlr_buf #if defined(__APPLE__) || defined(__MACH__) "jmp _nlr_push_tail \n" // do the rest in C #else "jmp nlr_push_tail \n" // do the rest in C #endif ); #endif return 0; // needed to silence compiler warning } NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "movq %0, %%rcx \n" // %rcx points to nlr_buf #if MICROPY_NLR_OS_WINDOWS "movq 88(%%rcx), %%rsi \n" // load saved %rsi "movq 80(%%rcx), %%rdi \n" // load saved %rdr #endif "movq 72(%%rcx), %%r15 \n" // load saved %r15 "movq 64(%%rcx), %%r14 \n" // load saved %r14 "movq 56(%%rcx), %%r13 \n" // load saved %r13 "movq 48(%%rcx), %%r12 \n" // load saved %r12 "movq 40(%%rcx), %%rbx \n" // load saved %rbx "movq 32(%%rcx), %%rsp \n" // load saved %rsp "movq 24(%%rcx), %%rbp \n" // load saved %rbp "movq 16(%%rcx), %%rax \n" // load saved %rip "movq %%rax, (%%rsp) \n" // store saved %rip to stack "xorq %%rax, %%rax \n" // clear return register "inc %%al \n" // increase to make 1, non-local return "ret \n" // return : // output operands : "r"(top) // input operands : // clobbered registers ); MP_UNREACHABLE } #endif // MICROPY_NLR_X64 micropython-1.12/py/nlrx86.c000066400000000000000000000072631357706137100157670ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #if MICROPY_NLR_X86 #undef nlr_push // For reference, x86 callee save regs are: // ebx, esi, edi, ebp, esp, eip #if MICROPY_NLR_OS_WINDOWS unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail"); #else __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); #endif #if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8 // Since gcc 8.0 the naked attribute is supported #define USE_NAKED (1) #define UNDO_PRELUDE (0) #elif defined(__ZEPHYR__) || defined(__ANDROID__) // Zephyr and Android use a different calling convention by default #define USE_NAKED (0) #define UNDO_PRELUDE (0) #else #define USE_NAKED (0) #define UNDO_PRELUDE (1) #endif #if USE_NAKED __attribute__((naked)) #endif unsigned int nlr_push(nlr_buf_t *nlr) { #if !USE_NAKED (void)nlr; #endif __asm volatile ( #if UNDO_PRELUDE "pop %ebp \n" // undo function's prelude #endif "mov 4(%esp), %edx \n" // load nlr_buf "mov (%esp), %eax \n" // load return %eip "mov %eax, 8(%edx) \n" // store %eip into nlr_buf "mov %ebp, 12(%edx) \n" // store %ebp into nlr_buf "mov %esp, 16(%edx) \n" // store %esp into nlr_buf "mov %ebx, 20(%edx) \n" // store %ebx into nlr_buf "mov %edi, 24(%edx) \n" // store %edi into nlr_buf "mov %esi, 28(%edx) \n" // store %esi into nlr_buf "jmp nlr_push_tail \n" // do the rest in C ); #if !USE_NAKED return 0; // needed to silence compiler warning #endif } NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "mov %0, %%edx \n" // %edx points to nlr_buf "mov 28(%%edx), %%esi \n" // load saved %esi "mov 24(%%edx), %%edi \n" // load saved %edi "mov 20(%%edx), %%ebx \n" // load saved %ebx "mov 16(%%edx), %%esp \n" // load saved %esp "mov 12(%%edx), %%ebp \n" // load saved %ebp "mov 8(%%edx), %%eax \n" // load saved %eip "mov %%eax, (%%esp) \n" // store saved %eip to stack "xor %%eax, %%eax \n" // clear return register "inc %%al \n" // increase to make 1, non-local return "ret \n" // return : // output operands : "r"(top) // input operands : // clobbered registers ); MP_UNREACHABLE } #endif // MICROPY_NLR_X86 micropython-1.12/py/nlrxtensa.c000066400000000000000000000054521357706137100166420ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpstate.h" #if MICROPY_NLR_XTENSA #undef nlr_push // Xtensa calling conventions: // a0 = return address // a1 = stack pointer // a2 = first arg, return value // a3-a7 = rest of args unsigned int nlr_push(nlr_buf_t *nlr) { __asm volatile ( "s32i.n a0, a2, 8 \n" // save regs... "s32i.n a1, a2, 12 \n" "s32i.n a8, a2, 16 \n" "s32i.n a9, a2, 20 \n" "s32i.n a10, a2, 24 \n" "s32i.n a11, a2, 28 \n" "s32i.n a12, a2, 32 \n" "s32i.n a13, a2, 36 \n" "s32i.n a14, a2, 40 \n" "s32i.n a15, a2, 44 \n" "j nlr_push_tail \n" // do the rest in C ); return 0; // needed to silence compiler warning } NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "mov.n a2, %0 \n" // a2 points to nlr_buf "l32i.n a0, a2, 8 \n" // restore regs... "l32i.n a1, a2, 12 \n" "l32i.n a8, a2, 16 \n" "l32i.n a9, a2, 20 \n" "l32i.n a10, a2, 24 \n" "l32i.n a11, a2, 28 \n" "l32i.n a12, a2, 32 \n" "l32i.n a13, a2, 36 \n" "l32i.n a14, a2, 40 \n" "l32i.n a15, a2, 44 \n" "movi.n a2, 1 \n" // return 1, non-local return "ret.n \n" // return : // output operands : "r"(top) // input operands : // clobbered registers ); MP_UNREACHABLE } #endif // MICROPY_NLR_XTENSA micropython-1.12/py/obj.c000066400000000000000000000431521357706137100153750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/obj.h" #include "py/objtype.h" #include "py/objint.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/stream.h" // for mp_obj_print mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { if (mp_obj_is_small_int(o_in)) { return (mp_obj_type_t*)&mp_type_int; } else if (mp_obj_is_qstr(o_in)) { return (mp_obj_type_t*)&mp_type_str; #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_float(o_in)) { return (mp_obj_type_t*)&mp_type_float; #endif } else { const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in); return (mp_obj_type_t*)o->type; } } const char *mp_obj_get_type_str(mp_const_obj_t o_in) { return qstr_str(mp_obj_get_type(o_in)->name); } void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { // There can be data structures nested too deep, or just recursive MP_STACK_CHECK(); #ifndef NDEBUG if (o_in == MP_OBJ_NULL) { mp_print_str(print, "(nil)"); return; } #endif mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->print != NULL) { type->print((mp_print_t*)print, o_in, kind); } else { mp_printf(print, "<%q>", type->name); } } void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_print_helper(MP_PYTHON_PRINTER, o_in, kind); } // helper function to print an exception with traceback void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) { if (mp_obj_is_exception_instance(exc)) { size_t n, *values; mp_obj_exception_get_traceback(exc, &n, &values); if (n > 0) { assert(n % 3 == 0); mp_print_str(print, "Traceback (most recent call last):\n"); for (int i = n - 3; i >= 0; i -= 3) { #if MICROPY_ENABLE_SOURCE_LINE mp_printf(print, " File \"%q\", line %d", values[i], (int)values[i + 1]); #else mp_printf(print, " File \"%q\"", values[i]); #endif // the block name can be NULL if it's unknown qstr block = values[i + 2]; if (block == MP_QSTRnull) { mp_print_str(print, "\n"); } else { mp_printf(print, ", in %q\n", block); } } } } mp_obj_print_helper(print, exc, PRINT_EXC); mp_print_str(print, "\n"); } bool mp_obj_is_true(mp_obj_t arg) { if (arg == mp_const_false) { return 0; } else if (arg == mp_const_true) { return 1; } else if (arg == mp_const_none) { return 0; } else if (mp_obj_is_small_int(arg)) { if (arg == MP_OBJ_NEW_SMALL_INT(0)) { return 0; } else { return 1; } } else { mp_obj_type_t *type = mp_obj_get_type(arg); if (type->unary_op != NULL) { mp_obj_t result = type->unary_op(MP_UNARY_OP_BOOL, arg); if (result != MP_OBJ_NULL) { return result == mp_const_true; } } mp_obj_t len = mp_obj_len_maybe(arg); if (len != MP_OBJ_NULL) { // obj has a length, truth determined if len != 0 return len != MP_OBJ_NEW_SMALL_INT(0); } else { // any other obj is true per Python semantics return 1; } } } bool mp_obj_is_callable(mp_obj_t o_in) { mp_call_fun_t call = mp_obj_get_type(o_in)->call; if (call != mp_obj_instance_call) { return call != NULL; } return mp_obj_instance_is_callable(o_in); } // This function implements the '==' operator (and so the inverse of '!='). // // From the Python language reference: // (https://docs.python.org/3/reference/expressions.html#not-in) // "The objects need not have the same type. If both are numbers, they are converted // to a common type. Otherwise, the == and != operators always consider objects of // different types to be unequal." // // This means that False==0 and True==1 are true expressions. // // Furthermore, from the v3.4.2 code for object.c: "Practical amendments: If rich // comparison returns NotImplemented, == and != are decided by comparing the object // pointer." bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { // Float (and complex) NaN is never equal to anything, not even itself, // so we must have a special check here to cover those cases. if (o1 == o2 #if MICROPY_PY_BUILTINS_FLOAT && !mp_obj_is_float(o1) #endif #if MICROPY_PY_BUILTINS_COMPLEX && !mp_obj_is_type(o1, &mp_type_complex) #endif ) { return true; } if (o1 == mp_const_none || o2 == mp_const_none) { return false; } // fast path for small ints if (mp_obj_is_small_int(o1)) { if (mp_obj_is_small_int(o2)) { // both SMALL_INT, and not equal if we get here return false; } else { mp_obj_t temp = o2; o2 = o1; o1 = temp; // o2 is now the SMALL_INT, o1 is not // fall through to generic op } } // fast path for strings if (mp_obj_is_str(o1)) { if (mp_obj_is_str(o2)) { // both strings, use special function return mp_obj_str_equal(o1, o2); } else { // a string is never equal to anything else goto str_cmp_err; } } else if (mp_obj_is_str(o2)) { // o1 is not a string (else caught above), so the objects are not equal str_cmp_err: #if MICROPY_PY_STR_BYTES_CMP_WARN if (mp_obj_is_type(o1, &mp_type_bytes) || mp_obj_is_type(o2, &mp_type_bytes)) { mp_warning(MP_WARN_CAT(BytesWarning), "Comparison between bytes and str"); } #endif return false; } // generic type, call binary_op(MP_BINARY_OP_EQUAL) mp_obj_type_t *type = mp_obj_get_type(o1); if (type->binary_op != NULL) { mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { return r == mp_const_true ? true : false; } } // equality not implemented, and objects are not the same object, so // they are defined as not equal return false; } mp_int_t mp_obj_get_int(mp_const_obj_t arg) { // This function essentially performs implicit type conversion to int // Note that Python does NOT provide implicit type conversion from // float to int in the core expression language, try some_list[1.0]. if (arg == mp_const_false) { return 0; } else if (arg == mp_const_true) { return 1; } else if (mp_obj_is_small_int(arg)) { return MP_OBJ_SMALL_INT_VALUE(arg); } else if (mp_obj_is_type(arg, &mp_type_int)) { return mp_obj_int_get_checked(arg); } else { mp_obj_t res = mp_unary_op(MP_UNARY_OP_INT, (mp_obj_t)arg); return mp_obj_int_get_checked(res); } } mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg) { if (mp_obj_is_int(arg)) { return mp_obj_int_get_truncated(arg); } else { return mp_obj_get_int(arg); } } // returns false if arg is not of integral type // returns true and sets *value if it is of integral type // can throw OverflowError if arg is of integral type, but doesn't fit in a mp_int_t bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) { if (arg == mp_const_false) { *value = 0; } else if (arg == mp_const_true) { *value = 1; } else if (mp_obj_is_small_int(arg)) { *value = MP_OBJ_SMALL_INT_VALUE(arg); } else if (mp_obj_is_type(arg, &mp_type_int)) { *value = mp_obj_int_get_checked(arg); } else { return false; } return true; } #if MICROPY_PY_BUILTINS_FLOAT bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) { mp_float_t val; if (arg == mp_const_false) { val = 0; } else if (arg == mp_const_true) { val = 1; } else if (mp_obj_is_small_int(arg)) { val = MP_OBJ_SMALL_INT_VALUE(arg); #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE } else if (mp_obj_is_type(arg, &mp_type_int)) { val = mp_obj_int_as_float_impl(arg); #endif } else if (mp_obj_is_float(arg)) { val = mp_obj_float_get(arg); } else { return false; } *value = val; return true; } mp_float_t mp_obj_get_float(mp_obj_t arg) { mp_float_t val; if (!mp_obj_get_float_maybe(arg, &val)) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("can't convert to float"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); } } return val; } #if MICROPY_PY_BUILTINS_COMPLEX void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { if (arg == mp_const_false) { *real = 0; *imag = 0; } else if (arg == mp_const_true) { *real = 1; *imag = 0; } else if (mp_obj_is_small_int(arg)) { *real = MP_OBJ_SMALL_INT_VALUE(arg); *imag = 0; #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE } else if (mp_obj_is_type(arg, &mp_type_int)) { *real = mp_obj_int_as_float_impl(arg); *imag = 0; #endif } else if (mp_obj_is_float(arg)) { *real = mp_obj_float_get(arg); *imag = 0; } else if (mp_obj_is_type(arg, &mp_type_complex)) { mp_obj_complex_get(arg, real, imag); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("can't convert to complex"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); } } } #endif #endif // note: returned value in *items may point to the interior of a GC block void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items) { if (mp_obj_is_type(o, &mp_type_tuple)) { mp_obj_tuple_get(o, len, items); } else if (mp_obj_is_type(o, &mp_type_list)) { mp_obj_list_get(o, len, items); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("expected tuple/list"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' isn't a tuple or list", mp_obj_get_type_str(o))); } } } // note: returned value in *items may point to the interior of a GC block void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items) { size_t seq_len; mp_obj_get_array(o, &seq_len, items); if (seq_len != len) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_ValueError("tuple/list has wrong length"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "requested length %d but object has length %d", (int)len, (int)seq_len)); } } } // is_slice determines whether the index is a slice index size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice) { mp_int_t i; if (mp_obj_is_small_int(index)) { i = MP_OBJ_SMALL_INT_VALUE(index); } else if (!mp_obj_get_int_maybe(index, &i)) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("indices must be integers"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%q indices must be integers, not %s", type->name, mp_obj_get_type_str(index))); } } if (i < 0) { i += len; } if (is_slice) { if (i < 0) { i = 0; } else if ((mp_uint_t)i > len) { i = len; } } else { if (i < 0 || (mp_uint_t)i >= len) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_IndexError, "index out of range"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "%q index out of range", type->name)); } } } // By this point 0 <= i <= len and so fits in a size_t return (size_t)i; } mp_obj_t mp_obj_id(mp_obj_t o_in) { mp_int_t id = (mp_int_t)o_in; if (!mp_obj_is_obj(o_in)) { return mp_obj_new_int(id); } else if (id >= 0) { // Many OSes and CPUs have affinity for putting "user" memories // into low half of address space, and "system" into upper half. // We're going to take advantage of that and return small int // (signed) for such "user" addresses. return MP_OBJ_NEW_SMALL_INT(id); } else { // If that didn't work, well, let's return long int, just as // a (big) positive value, so it will never clash with the range // of small int returned in previous case. return mp_obj_new_int_from_uint((mp_uint_t)id); } } // will raise a TypeError if object has no length mp_obj_t mp_obj_len(mp_obj_t o_in) { mp_obj_t len = mp_obj_len_maybe(o_in); if (len == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object has no len"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); } } else { return len; } } // may return MP_OBJ_NULL mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { if ( #if !MICROPY_PY_BUILTINS_STR_UNICODE // It's simple - unicode is slow, non-unicode is fast mp_obj_is_str(o_in) || #endif mp_obj_is_type(o_in, &mp_type_bytes)) { GET_STR_LEN(o_in, l); return MP_OBJ_NEW_SMALL_INT(l); } else { mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->unary_op != NULL) { return type->unary_op(MP_UNARY_OP_LEN, o_in); } else { return MP_OBJ_NULL; } } } mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(base); if (type->subscr != NULL) { mp_obj_t ret = type->subscr(base, index, value); if (ret != MP_OBJ_NULL) { return ret; } // TODO: call base classes here? } if (value == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object doesn't support item deletion"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object doesn't support item deletion", mp_obj_get_type_str(base))); } } else if (value == MP_OBJ_SENTINEL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object isn't subscriptable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object isn't subscriptable", mp_obj_get_type_str(base))); } } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object doesn't support item assignment"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object doesn't support item assignment", mp_obj_get_type_str(base))); } } } // Return input argument. Useful as .getiter for objects which are // their own iterators, etc. mp_obj_t mp_identity(mp_obj_t self) { return self; } MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity); mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) { (void)iter_buf; return self; } bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { mp_obj_type_t *type = mp_obj_get_type(obj); if (type->buffer_p.get_buffer == NULL) { return false; } int ret = type->buffer_p.get_buffer(obj, bufinfo, flags); if (ret != 0) { return false; } return true; } void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { if (!mp_get_buffer(obj, bufinfo, flags)) { mp_raise_TypeError("object with buffer protocol required"); } } mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in) { switch (op) { case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); default: return MP_OBJ_NULL; // op not supported } } micropython-1.12/py/obj.h000066400000000000000000001154331357706137100154040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJ_H #define MICROPY_INCLUDED_PY_OBJ_H #include "py/mpconfig.h" #include "py/misc.h" #include "py/qstr.h" #include "py/mpprint.h" #include "py/runtime0.h" // This is the definition of the opaque MicroPython object type. // All concrete objects have an encoding within this type and the // particular encoding is specified by MICROPY_OBJ_REPR. #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D typedef uint64_t mp_obj_t; typedef uint64_t mp_const_obj_t; #else typedef void *mp_obj_t; typedef const void *mp_const_obj_t; #endif // This mp_obj_type_t struct is a concrete MicroPython object which holds info // about a type. See below for actual definition of the struct. typedef struct _mp_obj_type_t mp_obj_type_t; // Anything that wants to be a concrete MicroPython object must have mp_obj_base_t // as its first member (small ints, qstr objs and inline floats are not concrete). struct _mp_obj_base_t { const mp_obj_type_t *type MICROPY_OBJ_BASE_ALIGNMENT; }; typedef struct _mp_obj_base_t mp_obj_base_t; // These fake objects are used to indicate certain things in arguments or return // values, and should only be used when explicitly allowed. // // - MP_OBJ_NULL : used to indicate the absence of an object, or unsupported operation. // - MP_OBJ_STOP_ITERATION : used instead of throwing a StopIteration, for efficiency. // - MP_OBJ_SENTINEL : used for various internal purposes where one needs // an object which is unique from all other objects, including MP_OBJ_NULL. // // For debugging purposes they are all different. For non-debug mode, we alias // as many as we can to MP_OBJ_NULL because it's cheaper to load/compare 0. #if MICROPY_DEBUG_MP_OBJ_SENTINELS #define MP_OBJ_NULL (MP_OBJ_FROM_PTR((void*)0)) #define MP_OBJ_STOP_ITERATION (MP_OBJ_FROM_PTR((void*)4)) #define MP_OBJ_SENTINEL (MP_OBJ_FROM_PTR((void*)8)) #else #define MP_OBJ_NULL (MP_OBJ_FROM_PTR((void*)0)) #define MP_OBJ_STOP_ITERATION (MP_OBJ_FROM_PTR((void*)0)) #define MP_OBJ_SENTINEL (MP_OBJ_FROM_PTR((void*)4)) #endif // These macros/inline functions operate on objects and depend on the // particular object representation. They are used to query, pack and // unpack small ints, qstrs and full object pointers. #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 1) != 0); } #define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1) #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 1) | 1)) static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 2); } #define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 2) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2)) #if MICROPY_PY_BUILTINS_FLOAT #define mp_const_float_e MP_ROM_PTR(&mp_const_float_e_obj) #define mp_const_float_pi MP_ROM_PTR(&mp_const_float_pi_obj) extern const struct _mp_obj_float_t mp_const_float_e_obj; extern const struct _mp_obj_float_t mp_const_float_pi_obj; #define mp_obj_is_float(o) mp_obj_is_type((o), &mp_type_float) mp_float_t mp_obj_float_get(mp_obj_t self_in); mp_obj_t mp_obj_new_float(mp_float_t value); #endif static inline bool mp_obj_is_obj(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 0); } #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 1); } #define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 2) #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 2) | 1)) static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 3); } #define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 2) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 3)) #if MICROPY_PY_BUILTINS_FLOAT #define mp_const_float_e MP_ROM_PTR(&mp_const_float_e_obj) #define mp_const_float_pi MP_ROM_PTR(&mp_const_float_pi_obj) extern const struct _mp_obj_float_t mp_const_float_e_obj; extern const struct _mp_obj_float_t mp_const_float_pi_obj; #define mp_obj_is_float(o) mp_obj_is_type((o), &mp_type_float) mp_float_t mp_obj_float_get(mp_obj_t self_in); mp_obj_t mp_obj_new_float(mp_float_t value); #endif static inline bool mp_obj_is_obj(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 1) == 0); } #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 1) != 0); } #define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1) #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 1) | 1)) #if MICROPY_PY_BUILTINS_FLOAT #define mp_const_float_e MP_ROM_PTR((mp_obj_t)(((0x402df854 & ~3) | 2) + 0x80800000)) #define mp_const_float_pi MP_ROM_PTR((mp_obj_t)(((0x40490fdb & ~3) | 2) + 0x80800000)) static inline bool mp_obj_is_float(mp_const_obj_t o) { return (((mp_uint_t)(o)) & 3) == 2 && (((mp_uint_t)(o)) & 0xff800007) != 0x00000006; } static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { union { mp_float_t f; mp_uint_t u; } num = {.u = ((mp_uint_t)o - 0x80800000) & ~3}; return num.f; } static inline mp_obj_t mp_obj_new_float(mp_float_t f) { union { mp_float_t f; mp_uint_t u; } num = {.f = f}; return (mp_obj_t)(((num.u & ~0x3) | 2) + 0x80800000); } #endif static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return (((mp_uint_t)(o)) & 0xff800007) == 0x00000006; } #define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 3) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 0x00000006)) static inline bool mp_obj_is_obj(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 0); } #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D static inline bool mp_obj_is_small_int(mp_const_obj_t o) { return ((((uint64_t)(o)) & 0xffff000000000000) == 0x0001000000000000); } #define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)((o) << 16)) >> 17) #define MP_OBJ_NEW_SMALL_INT(small_int) (((((uint64_t)(small_int)) & 0x7fffffffffff) << 1) | 0x0001000000000001) static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return ((((uint64_t)(o)) & 0xffff000000000000) == 0x0002000000000000); } #define MP_OBJ_QSTR_VALUE(o) ((((uint32_t)(o)) >> 1) & 0xffffffff) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 1) | 0x0002000000000001)) #if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_DOUBLE #error MICROPY_OBJ_REPR_D requires MICROPY_FLOAT_IMPL_DOUBLE #endif #define mp_const_float_e {((mp_obj_t)((uint64_t)0x4005bf0a8b145769 + 0x8004000000000000))} #define mp_const_float_pi {((mp_obj_t)((uint64_t)0x400921fb54442d18 + 0x8004000000000000))} static inline bool mp_obj_is_float(mp_const_obj_t o) { return ((uint64_t)(o) & 0xfffc000000000000) != 0; } static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { union { mp_float_t f; uint64_t r; } num = {.r = o - 0x8004000000000000}; return num.f; } static inline mp_obj_t mp_obj_new_float(mp_float_t f) { union { mp_float_t f; uint64_t r; } num = {.f = f}; return num.r + 0x8004000000000000; } #endif static inline bool mp_obj_is_obj(mp_const_obj_t o) { return ((((uint64_t)(o)) & 0xffff000000000000) == 0x0000000000000000); } #define MP_OBJ_TO_PTR(o) ((void*)(uintptr_t)(o)) #define MP_OBJ_FROM_PTR(p) ((mp_obj_t)((uintptr_t)(p))) // rom object storage needs special handling to widen 32-bit pointer to 64-bits typedef union _mp_rom_obj_t { uint64_t u64; struct { const void *lo, *hi; } u32; } mp_rom_obj_t; #define MP_ROM_INT(i) {MP_OBJ_NEW_SMALL_INT(i)} #define MP_ROM_QSTR(q) {MP_OBJ_NEW_QSTR(q)} #if MP_ENDIANNESS_LITTLE #define MP_ROM_PTR(p) {.u32 = {.lo = (p), .hi = NULL}} #else #define MP_ROM_PTR(p) {.u32 = {.lo = NULL, .hi = (p)}} #endif #endif // Macros to convert between mp_obj_t and concrete object types. // These are identity operations in MicroPython, but ability to override // these operations are provided to experiment with other methods of // object representation and memory management. // Cast mp_obj_t to object pointer #ifndef MP_OBJ_TO_PTR #define MP_OBJ_TO_PTR(o) ((void*)o) #endif // Cast object pointer to mp_obj_t #ifndef MP_OBJ_FROM_PTR #define MP_OBJ_FROM_PTR(p) ((mp_obj_t)p) #endif // Macros to create objects that are stored in ROM. #ifndef MP_ROM_INT typedef mp_const_obj_t mp_rom_obj_t; #define MP_ROM_INT(i) MP_OBJ_NEW_SMALL_INT(i) #define MP_ROM_QSTR(q) MP_OBJ_NEW_QSTR(q) #define MP_ROM_PTR(p) (p) /* for testing typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; #define MP_ROM_INT(i) {MP_OBJ_NEW_SMALL_INT(i)} #define MP_ROM_QSTR(q) {MP_OBJ_NEW_QSTR(q)} #define MP_ROM_PTR(p) {.o = p} */ #endif // These macros are used to declare and define constant function objects // You can put "static" in front of the definitions to make them local #define MP_DECLARE_CONST_FUN_OBJ_0(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name #define MP_DECLARE_CONST_FUN_OBJ_1(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name #define MP_DECLARE_CONST_FUN_OBJ_2(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name #define MP_DECLARE_CONST_FUN_OBJ_3(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name #define MP_DECLARE_CONST_FUN_OBJ_VAR(obj_name) extern const mp_obj_fun_builtin_var_t obj_name #define MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name) extern const mp_obj_fun_builtin_var_t obj_name #define MP_DECLARE_CONST_FUN_OBJ_KW(obj_name) extern const mp_obj_fun_builtin_var_t obj_name #define MP_OBJ_FUN_ARGS_MAX (0xffff) // to set maximum value in n_args_max below #define MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, takes_kw) ((uint32_t)((((uint32_t)(n_args_min)) << 17) | (((uint32_t)(n_args_max)) << 1) | ((takes_kw) ? 1 : 0))) #define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ {{&mp_type_fun_builtin_0}, .fun._0 = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ {{&mp_type_fun_builtin_1}, .fun._1 = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ {{&mp_type_fun_builtin_2}, .fun._2 = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ {{&mp_type_fun_builtin_3}, .fun._3 = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, false), .fun.var = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, false), .fun.var = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, true), .fun.kw = fun_name} // These macros are used to define constant map/dict objects // You can put "static" in front of the definition to make it local #define MP_DEFINE_CONST_MAP(map_name, table_name) \ const mp_map_t map_name = { \ .all_keys_are_qstrs = 1, \ .is_fixed = 1, \ .is_ordered = 1, \ .used = MP_ARRAY_SIZE(table_name), \ .alloc = MP_ARRAY_SIZE(table_name), \ .table = (mp_map_elem_t*)(mp_rom_map_elem_t*)table_name, \ } #define MP_DEFINE_CONST_DICT(dict_name, table_name) \ const mp_obj_dict_t dict_name = { \ .base = {&mp_type_dict}, \ .map = { \ .all_keys_are_qstrs = 1, \ .is_fixed = 1, \ .is_ordered = 1, \ .used = MP_ARRAY_SIZE(table_name), \ .alloc = MP_ARRAY_SIZE(table_name), \ .table = (mp_map_elem_t*)(mp_rom_map_elem_t*)table_name, \ }, \ } // These macros are used to declare and define constant staticmethond and classmethod objects // You can put "static" in front of the definitions to make them local #define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_rom_obj_static_class_method_t obj_name #define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_rom_obj_static_class_method_t obj_name #define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_rom_obj_static_class_method_t obj_name = {{&mp_type_staticmethod}, fun_name} #define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_rom_obj_static_class_method_t obj_name = {{&mp_type_classmethod}, fun_name} // Declare a module as a builtin, processed by makemoduledefs.py // param module_name: MP_QSTR_ // param obj_module: mp_obj_module_t instance // prarm enabled_define: used as `#if (enabled_define) around entry` #define MP_REGISTER_MODULE(module_name, obj_module, enabled_define) // Underlying map/hash table implementation (not dict object or map function) typedef struct _mp_map_elem_t { mp_obj_t key; mp_obj_t value; } mp_map_elem_t; typedef struct _mp_rom_map_elem_t { mp_rom_obj_t key; mp_rom_obj_t value; } mp_rom_map_elem_t; // TODO maybe have a truncated mp_map_t for fixed tables, since alloc=used // put alloc last in the structure, so the truncated version does not need it // this would save 1 ROM word for all ROM objects that have a locals_dict // would also need a trucated dict structure typedef struct _mp_map_t { size_t all_keys_are_qstrs : 1; size_t is_fixed : 1; // a fixed array that can't be modified; must also be ordered size_t is_ordered : 1; // an ordered array size_t used : (8 * sizeof(size_t) - 3); size_t alloc; mp_map_elem_t *table; } mp_map_t; // mp_set_lookup requires these constants to have the values they do typedef enum _mp_map_lookup_kind_t { MP_MAP_LOOKUP = 0, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND = 1, MP_MAP_LOOKUP_REMOVE_IF_FOUND = 2, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND = 3, // only valid for mp_set_lookup } mp_map_lookup_kind_t; extern const mp_map_t mp_const_empty_map; static inline bool mp_map_slot_is_filled(const mp_map_t *map, size_t pos) { return ((map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL); } void mp_map_init(mp_map_t *map, size_t n); void mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table); mp_map_t *mp_map_new(size_t n); void mp_map_deinit(mp_map_t *map); void mp_map_free(mp_map_t *map); mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind); void mp_map_clear(mp_map_t *map); void mp_map_dump(mp_map_t *map); // Underlying set implementation (not set object) typedef struct _mp_set_t { size_t alloc; size_t used; mp_obj_t *table; } mp_set_t; static inline bool mp_set_slot_is_filled(const mp_set_t *set, size_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); } void mp_set_init(mp_set_t *set, size_t n); mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind); mp_obj_t mp_set_remove_first(mp_set_t *set); void mp_set_clear(mp_set_t *set); // Type definitions for methods typedef mp_obj_t (*mp_fun_0_t)(void); typedef mp_obj_t (*mp_fun_1_t)(mp_obj_t); typedef mp_obj_t (*mp_fun_2_t)(mp_obj_t, mp_obj_t); typedef mp_obj_t (*mp_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t); typedef mp_obj_t (*mp_fun_var_t)(size_t n, const mp_obj_t *); // mp_fun_kw_t takes mp_map_t* (and not const mp_map_t*) to ease passing // this arg to mp_map_lookup(). typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); typedef enum { PRINT_STR = 0, PRINT_REPR = 1, PRINT_EXC = 2, // Special format for printing exception in unhandled exception message PRINT_JSON = 3, PRINT_RAW = 4, // Special format for printing bytes as an undercorated string PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses } mp_print_kind_t; typedef struct _mp_obj_iter_buf_t { mp_obj_base_t base; mp_obj_t buf[3]; } mp_obj_iter_buf_t; // The number of slots that an mp_obj_iter_buf_t needs on the Python value stack. // It's rounded up in case mp_obj_base_t is smaller than mp_obj_t (eg for OBJ_REPR_D). #define MP_OBJ_ITER_BUF_NSLOTS ((sizeof(mp_obj_iter_buf_t) + sizeof(mp_obj_t) - 1) / sizeof(mp_obj_t)) typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind); typedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args); typedef mp_obj_t (*mp_unary_op_fun_t)(mp_unary_op_t op, mp_obj_t); typedef mp_obj_t (*mp_binary_op_fun_t)(mp_binary_op_t op, mp_obj_t, mp_obj_t); typedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); // Buffer protocol typedef struct _mp_buffer_info_t { // if we'd bother to support various versions of structure // (with different number of fields), we can distinguish // them with ver = sizeof(struct). Cons: overkill for *micro*? //int ver; // ? void *buf; // can be NULL if len == 0 size_t len; // in bytes int typecode; // as per binary.h // Rationale: to load arbitrary-sized sprites directly to LCD // Cons: a bit adhoc usecase // int stride; } mp_buffer_info_t; #define MP_BUFFER_READ (1) #define MP_BUFFER_WRITE (2) #define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE) typedef struct _mp_buffer_p_t { mp_int_t (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); } mp_buffer_p_t; bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); struct _mp_obj_type_t { // A type is an object so must start with this entry, which points to mp_type_type. mp_obj_base_t base; // Flags associated with this type. uint16_t flags; // The name of this type, a qstr. uint16_t name; // Corresponds to __repr__ and __str__ special methods. mp_print_fun_t print; // Corresponds to __new__ and __init__ special methods, to make an instance of the type. mp_make_new_fun_t make_new; // Corresponds to __call__ special method, ie T(...). mp_call_fun_t call; // Implements unary and binary operations. // Can return MP_OBJ_NULL if the operation is not supported. mp_unary_op_fun_t unary_op; mp_binary_op_fun_t binary_op; // Implements load, store and delete attribute. // // dest[0] = MP_OBJ_NULL means load // return: for fail, do nothing // for attr, dest[0] = value // for method, dest[0] = method, dest[1] = self // // dest[0,1] = {MP_OBJ_SENTINEL, MP_OBJ_NULL} means delete // dest[0,1] = {MP_OBJ_SENTINEL, object} means store // return: for fail, do nothing // for success set dest[0] = MP_OBJ_NULL mp_attr_fun_t attr; // Implements load, store and delete subscripting: // - value = MP_OBJ_SENTINEL means load // - value = MP_OBJ_NULL means delete // - all other values mean store the value // Can return MP_OBJ_NULL if operation not supported. mp_subscr_fun_t subscr; // Corresponds to __iter__ special method. // Can use the given mp_obj_iter_buf_t to store iterator object, // otherwise can return a pointer to an object on the heap. mp_getiter_fun_t getiter; // Corresponds to __next__ special method. May return MP_OBJ_STOP_ITERATION // as an optimisation instead of raising StopIteration() with no args. mp_fun_1_t iternext; // Implements the buffer protocol if supported by this type. mp_buffer_p_t buffer_p; // One of disjoint protocols (interfaces), like mp_stream_p_t, etc. const void *protocol; // A pointer to the parents of this type: // - 0 parents: pointer is NULL (object is implicitly the single parent) // - 1 parent: a pointer to the type of that parent // - 2 or more parents: pointer to a tuple object containing the parent types const void *parent; // A dict mapping qstrs to objects local methods/constants/etc. struct _mp_obj_dict_t *locals_dict; }; // Constant types, globally accessible extern const mp_obj_type_t mp_type_type; extern const mp_obj_type_t mp_type_object; extern const mp_obj_type_t mp_type_NoneType; extern const mp_obj_type_t mp_type_bool; extern const mp_obj_type_t mp_type_int; extern const mp_obj_type_t mp_type_str; extern const mp_obj_type_t mp_type_bytes; extern const mp_obj_type_t mp_type_bytearray; extern const mp_obj_type_t mp_type_memoryview; extern const mp_obj_type_t mp_type_float; extern const mp_obj_type_t mp_type_complex; extern const mp_obj_type_t mp_type_tuple; extern const mp_obj_type_t mp_type_list; extern const mp_obj_type_t mp_type_map; // map (the python builtin, not the dict implementation detail) extern const mp_obj_type_t mp_type_enumerate; extern const mp_obj_type_t mp_type_filter; extern const mp_obj_type_t mp_type_deque; extern const mp_obj_type_t mp_type_dict; extern const mp_obj_type_t mp_type_ordereddict; extern const mp_obj_type_t mp_type_range; extern const mp_obj_type_t mp_type_set; extern const mp_obj_type_t mp_type_frozenset; extern const mp_obj_type_t mp_type_slice; extern const mp_obj_type_t mp_type_zip; extern const mp_obj_type_t mp_type_array; extern const mp_obj_type_t mp_type_super; extern const mp_obj_type_t mp_type_gen_wrap; extern const mp_obj_type_t mp_type_native_gen_wrap; extern const mp_obj_type_t mp_type_gen_instance; extern const mp_obj_type_t mp_type_fun_builtin_0; extern const mp_obj_type_t mp_type_fun_builtin_1; extern const mp_obj_type_t mp_type_fun_builtin_2; extern const mp_obj_type_t mp_type_fun_builtin_3; extern const mp_obj_type_t mp_type_fun_builtin_var; extern const mp_obj_type_t mp_type_fun_bc; extern const mp_obj_type_t mp_type_module; extern const mp_obj_type_t mp_type_staticmethod; extern const mp_obj_type_t mp_type_classmethod; extern const mp_obj_type_t mp_type_property; extern const mp_obj_type_t mp_type_stringio; extern const mp_obj_type_t mp_type_bytesio; extern const mp_obj_type_t mp_type_reversed; extern const mp_obj_type_t mp_type_polymorph_iter; // Exceptions extern const mp_obj_type_t mp_type_BaseException; extern const mp_obj_type_t mp_type_ArithmeticError; extern const mp_obj_type_t mp_type_AssertionError; extern const mp_obj_type_t mp_type_AttributeError; extern const mp_obj_type_t mp_type_EOFError; extern const mp_obj_type_t mp_type_Exception; extern const mp_obj_type_t mp_type_GeneratorExit; extern const mp_obj_type_t mp_type_ImportError; extern const mp_obj_type_t mp_type_IndentationError; extern const mp_obj_type_t mp_type_IndexError; extern const mp_obj_type_t mp_type_KeyboardInterrupt; extern const mp_obj_type_t mp_type_KeyError; extern const mp_obj_type_t mp_type_LookupError; extern const mp_obj_type_t mp_type_MemoryError; extern const mp_obj_type_t mp_type_NameError; extern const mp_obj_type_t mp_type_NotImplementedError; extern const mp_obj_type_t mp_type_OSError; extern const mp_obj_type_t mp_type_TimeoutError; extern const mp_obj_type_t mp_type_OverflowError; extern const mp_obj_type_t mp_type_RuntimeError; extern const mp_obj_type_t mp_type_StopAsyncIteration; extern const mp_obj_type_t mp_type_StopIteration; extern const mp_obj_type_t mp_type_SyntaxError; extern const mp_obj_type_t mp_type_SystemExit; extern const mp_obj_type_t mp_type_TypeError; extern const mp_obj_type_t mp_type_UnicodeError; extern const mp_obj_type_t mp_type_ValueError; extern const mp_obj_type_t mp_type_ViperTypeError; extern const mp_obj_type_t mp_type_ZeroDivisionError; // Constant objects, globally accessible // The macros are for convenience only #define mp_const_none (MP_OBJ_FROM_PTR(&mp_const_none_obj)) #define mp_const_false (MP_OBJ_FROM_PTR(&mp_const_false_obj)) #define mp_const_true (MP_OBJ_FROM_PTR(&mp_const_true_obj)) #define mp_const_empty_bytes (MP_OBJ_FROM_PTR(&mp_const_empty_bytes_obj)) #define mp_const_empty_tuple (MP_OBJ_FROM_PTR(&mp_const_empty_tuple_obj)) #define mp_const_notimplemented (MP_OBJ_FROM_PTR(&mp_const_notimplemented_obj)) extern const struct _mp_obj_none_t mp_const_none_obj; extern const struct _mp_obj_bool_t mp_const_false_obj; extern const struct _mp_obj_bool_t mp_const_true_obj; extern const struct _mp_obj_str_t mp_const_empty_bytes_obj; extern const struct _mp_obj_tuple_t mp_const_empty_tuple_obj; extern const struct _mp_obj_singleton_t mp_const_ellipsis_obj; extern const struct _mp_obj_singleton_t mp_const_notimplemented_obj; extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj; // General API for objects // These macros are derived from more primitive ones and are used to // check for more specific object types. // Note: these are kept as macros because inline functions sometimes use much // more code space than the equivalent macros, depending on the compiler. #define mp_obj_is_type(o, t) (mp_obj_is_obj(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type == (t))) // this does not work for checking int, str or fun; use below macros for that #define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_type(o, &mp_type_int)) #define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_type(o, &mp_type_str)) #define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->binary_op == mp_obj_str_binary_op)) #define mp_obj_is_fun(o) (mp_obj_is_obj(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function)) mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); static inline mp_obj_t mp_obj_new_bool(mp_int_t x) { return x ? mp_const_true : mp_const_false; } mp_obj_t mp_obj_new_cell(mp_obj_t obj); mp_obj_t mp_obj_new_int(mp_int_t value); mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value); mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base); mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_obj_t mp_obj_new_str(const char* data, size_t len); mp_obj_t mp_obj_new_str_via_qstr(const char* data, size_t len); mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); mp_obj_t mp_obj_new_bytes(const byte* data, size_t len); mp_obj_t mp_obj_new_bytearray(size_t n, void *items); mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items); #if MICROPY_PY_BUILTINS_FLOAT mp_obj_t mp_obj_new_int_from_float(mp_float_t val); mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag); #endif mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type); mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg); mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args); mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg); mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!) mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table); mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data, const mp_uint_t *const_table); mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig); mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun); mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed, const mp_obj_t *closed); mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items); mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items); mp_obj_t mp_obj_new_dict(size_t n_args); mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items); mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step); mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self); mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf); mp_obj_t mp_obj_new_module(qstr module_name); mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items); mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in); const char *mp_obj_get_type_str(mp_const_obj_t o_in); bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type); void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); void mp_obj_print(mp_obj_t o, mp_print_kind_t kind); void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc); bool mp_obj_is_true(mp_obj_t arg); bool mp_obj_is_callable(mp_obj_t o_in); bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); static inline bool mp_obj_is_integer(mp_const_obj_t o) { return mp_obj_is_int(o) || mp_obj_is_type(o, &mp_type_bool); } // returns true if o is bool, small int or long int mp_int_t mp_obj_get_int(mp_const_obj_t arg); mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg); bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value); #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_get_float(mp_obj_t self_in); bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value); void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); #endif void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items); // *items may point inside a GC block void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items); // *items may point inside a GC block size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice); mp_obj_t mp_obj_id(mp_obj_t o_in); mp_obj_t mp_obj_len(mp_obj_t o_in); mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val); mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in); // cell mp_obj_t mp_obj_cell_get(mp_obj_t self_in); void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj); // int // For long int, returns value truncated to mp_int_t mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in); // Will raise exception if value doesn't fit into mp_int_t mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); // exception #define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new) bool mp_obj_is_exception_type(mp_obj_t self_in); bool mp_obj_is_exception_instance(mp_obj_t self_in); bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type); void mp_obj_exception_clear_traceback(mp_obj_t self_in); void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block); void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values); mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in); mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args); mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in); void mp_init_emergency_exception_buf(void); // str bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2); qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len); mp_obj_t mp_obj_str_intern(mp_obj_t str); mp_obj_t mp_obj_str_intern_checked(mp_obj_t obj); void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes); #if MICROPY_PY_BUILTINS_FLOAT // float #if MICROPY_FLOAT_HIGH_QUALITY_HASH mp_int_t mp_float_hash(mp_float_t val); #else static inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; } #endif mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported // complex void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); mp_obj_t mp_obj_complex_binary_op(mp_binary_op_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NULL if op not supported #else #define mp_obj_is_float(o) (false) #endif // tuple void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items); void mp_obj_tuple_del(mp_obj_t self_in); mp_int_t mp_obj_tuple_hash(mp_obj_t self_in); // list mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value); void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items); void mp_obj_list_set_len(mp_obj_t self_in, size_t len); void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); // dict typedef struct _mp_obj_dict_t { mp_obj_base_t base; mp_map_t map; } mp_obj_dict_t; void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args); size_t mp_obj_dict_len(mp_obj_t self_in); mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index); mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value); mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key); static inline mp_map_t *mp_obj_dict_get_map(mp_obj_t dict) { return &((mp_obj_dict_t*)MP_OBJ_TO_PTR(dict))->map; } // set void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item); // slice void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step); // functions typedef struct _mp_obj_fun_builtin_fixed_t { mp_obj_base_t base; union { mp_fun_0_t _0; mp_fun_1_t _1; mp_fun_2_t _2; mp_fun_3_t _3; } fun; } mp_obj_fun_builtin_fixed_t; typedef struct _mp_obj_fun_builtin_var_t { mp_obj_base_t base; uint32_t sig; // see MP_OBJ_FUN_MAKE_SIG union { mp_fun_var_t var; mp_fun_kw_t kw; } fun; } mp_obj_fun_builtin_var_t; qstr mp_obj_fun_get_name(mp_const_obj_t fun); qstr mp_obj_code_get_name(const byte *code_info); mp_obj_t mp_identity(mp_obj_t self); MP_DECLARE_CONST_FUN_OBJ_1(mp_identity_obj); mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf); // module typedef struct _mp_obj_module_t { mp_obj_base_t base; mp_obj_dict_t *globals; } mp_obj_module_t; static inline mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t module) { return ((mp_obj_module_t*)MP_OBJ_TO_PTR(module))->globals; } // check if given module object is a package bool mp_obj_is_package(mp_obj_t module); // staticmethod and classmethod types; defined here so we can make const versions // this structure is used for instances of both staticmethod and classmethod typedef struct _mp_obj_static_class_method_t { mp_obj_base_t base; mp_obj_t fun; } mp_obj_static_class_method_t; typedef struct _mp_rom_obj_static_class_method_t { mp_obj_base_t base; mp_rom_obj_t fun; } mp_rom_obj_static_class_method_t; // property const mp_obj_t *mp_obj_property_get(mp_obj_t self_in); // sequence helpers // slice indexes resolved to particular sequence typedef struct { mp_uint_t start; mp_uint_t stop; mp_int_t step; } mp_bound_slice_t; void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest); #if MICROPY_PY_BUILTINS_SLICE bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes); #endif #define mp_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t)) #define mp_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); } bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2); bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp_obj_t *items2, size_t len2); mp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args); mp_obj_t mp_seq_count_obj(const mp_obj_t *items, size_t len, mp_obj_t value); mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes); // Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems #define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte*)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz)) #define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_sz) \ /*printf("memcpy(%p, %p, %d)\n", dest + beg, slice, slice_len * (item_sz));*/ \ memcpy(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz)); \ /*printf("memmove(%p, %p, %d)\n", dest + (beg + slice_len), dest + end, (dest_len - end) * (item_sz));*/ \ memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), (dest_len - end) * (item_sz)); // Note: dest and slice regions may overlap #define mp_seq_replace_slice_grow_inplace(dest, dest_len, beg, end, slice, slice_len, len_adj, item_sz) \ /*printf("memmove(%p, %p, %d)\n", dest + beg + len_adj, dest + beg, (dest_len - beg) * (item_sz));*/ \ memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), ((dest_len) + (len_adj) - ((beg) + (slice_len))) * (item_sz)); \ memmove(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz)); // Provide translation for legacy API #define MP_OBJ_IS_SMALL_INT mp_obj_is_small_int #define MP_OBJ_IS_QSTR mp_obj_is_qstr #define MP_OBJ_IS_OBJ mp_obj_is_obj #define MP_OBJ_IS_INT mp_obj_is_int #define MP_OBJ_IS_TYPE mp_obj_is_type #define MP_OBJ_IS_STR mp_obj_is_str #define MP_OBJ_IS_STR_OR_BYTES mp_obj_is_str_or_bytes #define MP_OBJ_IS_FUN mp_obj_is_fun #define MP_MAP_SLOT_IS_FILLED mp_map_slot_is_filled #define MP_SET_SLOT_IS_FILLED mp_set_slot_is_filled #endif // MICROPY_INCLUDED_PY_OBJ_H micropython-1.12/py/objarray.c000066400000000000000000000610131357706137100164300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/binary.h" #include "py/objstr.h" #include "py/objarray.h" #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW // About memoryview object: We want to reuse as much code as possible from // array, and keep the memoryview object 4 words in size so it fits in 1 GC // block. Also, memoryview must keep a pointer to the base of the buffer so // that the buffer is not GC'd if the original parent object is no longer // around (we are assuming that all memoryview'able objects return a pointer // which points to the start of a GC chunk). Given the above constraints we // do the following: // - typecode high bit is set if the buffer is read-write (else read-only) // - free is the offset in elements to the first item in the memoryview // - len is the length in elements // - items points to the start of the original buffer // Note that we don't handle the case where the original buffer might change // size due to a resize of the original parent object. #if MICROPY_PY_BUILTINS_MEMORYVIEW #define TYPECODE_MASK (0x7f) #define memview_offset free #else // make (& TYPECODE_MASK) a null operation if memorview not enabled #define TYPECODE_MASK (~(size_t)0) // memview_offset should not be accessed if memoryview is not enabled, // so not defined to catch errors #endif STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf); STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg); STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in); STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); /******************************************************************************/ // array #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in); if (o->typecode == BYTEARRAY_TYPECODE) { mp_print_str(print, "bytearray(b"); mp_str_print_quoted(print, o->items, o->len, true); } else { mp_printf(print, "array('%c'", o->typecode); if (o->len > 0) { mp_print_str(print, ", ["); for (size_t i = 0; i < o->len; i++) { if (i > 0) { mp_print_str(print, ", "); } mp_obj_print_helper(print, mp_binary_get_val_array(o->typecode, o->items, i), PRINT_REPR); } mp_print_str(print, "]"); } } mp_print_str(print, ")"); } #endif #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY STATIC mp_obj_array_t *array_new(char typecode, size_t n) { int typecode_size = mp_binary_get_size('@', typecode, NULL); mp_obj_array_t *o = m_new_obj(mp_obj_array_t); #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array; #elif MICROPY_PY_BUILTINS_BYTEARRAY o->base.type = &mp_type_bytearray; #else o->base.type = &mp_type_array; #endif o->typecode = typecode; o->free = 0; o->len = n; o->items = m_new(byte, typecode_size * o->len); return o; } #endif #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { // bytearrays can be raw-initialised from anything with the buffer protocol // other arrays can only be raw-initialised from bytes and bytearray objects mp_buffer_info_t bufinfo; if (((MICROPY_PY_BUILTINS_BYTEARRAY && typecode == BYTEARRAY_TYPECODE) || (MICROPY_PY_ARRAY && (mp_obj_is_type(initializer, &mp_type_bytes) || (MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(initializer, &mp_type_bytearray))))) && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) { // construct array from raw bytes // we round-down the len to make it a multiple of sz (CPython raises error) size_t sz = mp_binary_get_size('@', typecode, NULL); size_t len = bufinfo.len / sz; mp_obj_array_t *o = array_new(typecode, len); memcpy(o->items, bufinfo.buf, len * sz); return MP_OBJ_FROM_PTR(o); } size_t len; // Try to create array of exact len if initializer len is known mp_obj_t len_in = mp_obj_len_maybe(initializer); if (len_in == MP_OBJ_NULL) { len = 0; } else { len = MP_OBJ_SMALL_INT_VALUE(len_in); } mp_obj_array_t *array = array_new(typecode, len); mp_obj_t iterable = mp_getiter(initializer, NULL); mp_obj_t item; size_t i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (len == 0) { array_append(MP_OBJ_FROM_PTR(array), item); } else { mp_binary_set_val_array(typecode, array->items, i++, item); } } return MP_OBJ_FROM_PTR(array); } #endif #if MICROPY_PY_ARRAY STATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 1, 2, false); // get typecode const char *typecode = mp_obj_str_get_str(args[0]); if (n_args == 1) { // 1 arg: make an empty array return MP_OBJ_FROM_PTR(array_new(*typecode, 0)); } else { // 2 args: construct the array from the given object return array_construct(*typecode, args[1]); } } #endif #if MICROPY_PY_BUILTINS_BYTEARRAY STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; // Can take 2nd/3rd arg if constructs from str mp_arg_check_num(n_args, n_kw, 0, 3, false); if (n_args == 0) { // no args: construct an empty bytearray return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0)); } else if (mp_obj_is_int(args[0])) { // 1 arg, an integer: construct a blank bytearray of that length mp_uint_t len = mp_obj_get_int(args[0]); mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len); memset(o->items, 0, len); return MP_OBJ_FROM_PTR(o); } else { // 1 arg: construct the bytearray from that return array_construct(BYTEARRAY_TYPECODE, args[0]); } } #endif #if MICROPY_PY_BUILTINS_MEMORYVIEW mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items) { mp_obj_array_t *self = m_new_obj(mp_obj_array_t); self->base.type = &mp_type_memoryview; self->typecode = typecode; self->memview_offset = 0; self->len = nitems; self->items = items; return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; // TODO possibly allow memoryview constructor to take start/stop so that one // can do memoryview(b, 4, 8) instead of memoryview(b)[4:8] (uses less RAM) mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); mp_obj_array_t *self = MP_OBJ_TO_PTR(mp_obj_new_memoryview(bufinfo.typecode, bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL), bufinfo.buf)); // test if the object can be written to if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) { self->typecode |= MP_OBJ_ARRAY_TYPECODE_FLAG_RW; // indicate writable buffer } return MP_OBJ_FROM_PTR(self); } #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { return; } if (attr == MP_QSTR_itemsize) { mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); dest[0] = MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL)); } } #endif #endif STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->len != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(o->len); default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in); switch (op) { case MP_BINARY_OP_ADD: { // allow to add anything that has the buffer protocol (extension to CPython) mp_buffer_info_t lhs_bufinfo; mp_buffer_info_t rhs_bufinfo; array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(rhs_in, &rhs_bufinfo, MP_BUFFER_READ); size_t sz = mp_binary_get_size('@', lhs_bufinfo.typecode, NULL); // convert byte count to element count (in case rhs is not multiple of sz) size_t rhs_len = rhs_bufinfo.len / sz; // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len); mp_seq_cat((byte*)res->items, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_len * sz, byte); return MP_OBJ_FROM_PTR(res); } case MP_BINARY_OP_INPLACE_ADD: { #if MICROPY_PY_BUILTINS_MEMORYVIEW if (lhs->base.type == &mp_type_memoryview) { return MP_OBJ_NULL; // op not supported } #endif array_extend(lhs_in, rhs_in); return lhs_in; } case MP_BINARY_OP_CONTAINS: { #if MICROPY_PY_BUILTINS_BYTEARRAY // Can search string only in bytearray mp_buffer_info_t lhs_bufinfo; mp_buffer_info_t rhs_bufinfo; if (mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) { if (!mp_obj_is_type(lhs_in, &mp_type_bytearray)) { return mp_const_false; } array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ); return mp_obj_new_bool( find_subbytes(lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len, 1) != NULL); } #endif // Otherwise, can only look for a scalar numeric value in an array if (mp_obj_is_int(rhs_in) || mp_obj_is_float(rhs_in)) { mp_raise_NotImplementedError(NULL); } return mp_const_false; } case MP_BINARY_OP_EQUAL: { mp_buffer_info_t lhs_bufinfo; mp_buffer_info_t rhs_bufinfo; array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ); if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) { return mp_const_false; } return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len)); } default: return MP_OBJ_NULL; // op not supported } } #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { // self is not a memoryview, so we don't need to use (& TYPECODE_MASK) assert((MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(self_in, &mp_type_bytearray)) || (MICROPY_PY_ARRAY && mp_obj_is_type(self_in, &mp_type_array))); mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); if (self->free == 0) { size_t item_sz = mp_binary_get_size('@', self->typecode, NULL); // TODO: alloc policy self->free = 8; self->items = m_renew(byte, self->items, item_sz * self->len, item_sz * (self->len + self->free)); mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz); } mp_binary_set_val_array(self->typecode, self->items, self->len, arg); // only update length/free if set succeeded self->len++; self->free--; return mp_const_none; // return None, as per CPython } STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_append_obj, array_append); STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { // self is not a memoryview, so we don't need to use (& TYPECODE_MASK) assert((MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(self_in, &mp_type_bytearray)) || (MICROPY_PY_ARRAY && mp_obj_is_type(self_in, &mp_type_array))); mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); // allow to extend by anything that has the buffer protocol (extension to CPython) mp_buffer_info_t arg_bufinfo; mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ); size_t sz = mp_binary_get_size('@', self->typecode, NULL); // convert byte count to element count size_t len = arg_bufinfo.len / sz; // make sure we have enough room to extend // TODO: alloc policy; at the moment we go conservative if (self->free < len) { self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz); self->free = 0; } else { self->free -= len; } // extend mp_seq_copy((byte*)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte); self->len += len; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_extend_obj, array_extend); #endif STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item // TODO implement // TODO: confirmed that both bytearray and array.array support // slice deletion return MP_OBJ_NULL; // op not supported } else { mp_obj_array_t *o = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index_in, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) { mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported"); } if (value != MP_OBJ_SENTINEL) { #if MICROPY_PY_ARRAY_SLICE_ASSIGN // Assign size_t src_len; void *src_items; size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); if (mp_obj_is_obj(value) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(value))->type->subscr == array_subscr) { // value is array, bytearray or memoryview mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value); if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) { compat_error: mp_raise_ValueError("lhs and rhs should be compatible"); } src_len = src_slice->len; src_items = src_slice->items; #if MICROPY_PY_BUILTINS_MEMORYVIEW if (mp_obj_is_type(value, &mp_type_memoryview)) { src_items = (uint8_t*)src_items + (src_slice->memview_offset * item_sz); } #endif } else if (mp_obj_is_type(value, &mp_type_bytes)) { if (item_sz != 1) { goto compat_error; } mp_buffer_info_t bufinfo; mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ); src_len = bufinfo.len; src_items = bufinfo.buf; } else { mp_raise_NotImplementedError("array/bytes required on right side"); } // TODO: check src/dst compat mp_int_t len_adj = src_len - (slice.stop - slice.start); uint8_t* dest_items = o->items; #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { if (!(o->typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW)) { // store to read-only memoryview not allowed return MP_OBJ_NULL; } if (len_adj != 0) { goto compat_error; } dest_items += o->memview_offset * item_sz; } #endif if (len_adj > 0) { if (len_adj > o->free) { // TODO: alloc policy; at the moment we go conservative o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz); o->free = len_adj; dest_items = o->items; } mp_seq_replace_slice_grow_inplace(dest_items, o->len, slice.start, slice.stop, src_items, src_len, len_adj, item_sz); } else { mp_seq_replace_slice_no_grow(dest_items, o->len, slice.start, slice.stop, src_items, src_len, item_sz); // Clear "freed" elements at the end of list // TODO: This is actually only needed for typecode=='O' mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz); // TODO: alloc policy after shrinking } o->free -= len_adj; o->len += len_adj; return mp_const_none; #else return MP_OBJ_NULL; // op not supported #endif } mp_obj_array_t *res; size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); assert(sz > 0); #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { res = m_new_obj(mp_obj_array_t); *res = *o; res->memview_offset += slice.start; res->len = slice.stop - slice.start; } else #endif { res = array_new(o->typecode, slice.stop - slice.start); memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz); } return MP_OBJ_FROM_PTR(res); } else #endif { size_t index = mp_get_index(o->base.type, o->len, index_in, false); #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { index += o->memview_offset; if (value != MP_OBJ_SENTINEL && !(o->typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW)) { // store to read-only memoryview return MP_OBJ_NULL; } } #endif if (value == MP_OBJ_SENTINEL) { // load return mp_binary_get_val_array(o->typecode & TYPECODE_MASK, o->items, index); } else { // store mp_binary_set_val_array(o->typecode & TYPECODE_MASK, o->items, index, value); return mp_const_none; } } } } STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in); size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); bufinfo->buf = o->items; bufinfo->len = o->len * sz; bufinfo->typecode = o->typecode & TYPECODE_MASK; #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { if (!(o->typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW) && (flags & MP_BUFFER_WRITE)) { // read-only memoryview return 1; } bufinfo->buf = (uint8_t*)bufinfo->buf + (size_t)o->memview_offset * sz; } #else (void)flags; #endif return 0; } #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY STATIC const mp_rom_map_elem_t array_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&array_append_obj) }, { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&array_extend_obj) }, #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table); #endif #if MICROPY_PY_ARRAY const mp_obj_type_t mp_type_array = { { &mp_type_type }, .name = MP_QSTR_array, .print = array_print, .make_new = array_make_new, .getiter = array_iterator_new, .unary_op = array_unary_op, .binary_op = array_binary_op, .subscr = array_subscr, .buffer_p = { .get_buffer = array_get_buffer }, .locals_dict = (mp_obj_dict_t*)&array_locals_dict, }; #endif #if MICROPY_PY_BUILTINS_BYTEARRAY const mp_obj_type_t mp_type_bytearray = { { &mp_type_type }, .name = MP_QSTR_bytearray, .print = array_print, .make_new = bytearray_make_new, .getiter = array_iterator_new, .unary_op = array_unary_op, .binary_op = array_binary_op, .subscr = array_subscr, .buffer_p = { .get_buffer = array_get_buffer }, .locals_dict = (mp_obj_dict_t*)&array_locals_dict, }; #endif #if MICROPY_PY_BUILTINS_MEMORYVIEW const mp_obj_type_t mp_type_memoryview = { { &mp_type_type }, .name = MP_QSTR_memoryview, .make_new = memoryview_make_new, .getiter = array_iterator_new, .unary_op = array_unary_op, .binary_op = array_binary_op, #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE .attr = memoryview_attr, #endif .subscr = array_subscr, .buffer_p = { .get_buffer = array_get_buffer }, }; #endif /* unused size_t mp_obj_array_len(mp_obj_t self_in) { return ((mp_obj_array_t *)self_in)->len; } */ #if MICROPY_PY_BUILTINS_BYTEARRAY mp_obj_t mp_obj_new_bytearray(size_t n, void *items) { mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n); memcpy(o->items, items, n); return MP_OBJ_FROM_PTR(o); } // Create bytearray which references specified memory area mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items) { mp_obj_array_t *o = m_new_obj(mp_obj_array_t); o->base.type = &mp_type_bytearray; o->typecode = BYTEARRAY_TYPECODE; o->free = 0; o->len = n; o->items = items; return MP_OBJ_FROM_PTR(o); } #endif /******************************************************************************/ // array iterator typedef struct _mp_obj_array_it_t { mp_obj_base_t base; mp_obj_array_t *array; size_t offset; size_t cur; } mp_obj_array_it_t; STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) { mp_obj_array_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->cur < self->array->len) { return mp_binary_get_val_array(self->array->typecode & TYPECODE_MASK, self->array->items, self->offset + self->cur++); } else { return MP_OBJ_STOP_ITERATION; } } STATIC const mp_obj_type_t array_it_type = { { &mp_type_type }, .name = MP_QSTR_iterator, .getiter = mp_identity_getiter, .iternext = array_it_iternext, }; STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_array_t *array = MP_OBJ_TO_PTR(array_in); mp_obj_array_it_t *o = (mp_obj_array_it_t*)iter_buf; o->base.type = &array_it_type; o->array = array; o->offset = 0; o->cur = 0; #if MICROPY_PY_BUILTINS_MEMORYVIEW if (array->base.type == &mp_type_memoryview) { o->offset = array->memview_offset; } #endif return MP_OBJ_FROM_PTR(o); } #endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW micropython-1.12/py/objarray.h000066400000000000000000000043301357706137100164340ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJARRAY_H #define MICROPY_INCLUDED_PY_OBJARRAY_H #include "py/obj.h" // Used only for memoryview types, set in "typecode" to indicate a writable memoryview #define MP_OBJ_ARRAY_TYPECODE_FLAG_RW (0x80) // This structure is used for all of bytearray, array.array, memoryview // objects. Note that memoryview has different meaning for some fields, // see comment at the beginning of objarray.c. typedef struct _mp_obj_array_t { mp_obj_base_t base; size_t typecode : 8; // free is number of unused elements after len used elements // alloc size = len + free // But for memoryview, 'free' is reused as offset (in elements) into the // parent object. (Union is not used to not go into a complication of // union-of-bitfields with different toolchains). See comments in // objarray.c. size_t free : (8 * sizeof(size_t) - 8); size_t len; // in elements void *items; } mp_obj_array_t; #endif // MICROPY_INCLUDED_PY_OBJARRAY_H micropython-1.12/py/objattrtuple.c000066400000000000000000000064161357706137100173440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/objtuple.h" #if MICROPY_PY_ATTRTUPLE || MICROPY_PY_COLLECTIONS // this helper function is used by collections.namedtuple #if !MICROPY_PY_COLLECTIONS STATIC #endif void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o) { mp_print_str(print, "("); for (size_t i = 0; i < o->len; i++) { if (i > 0) { mp_print_str(print, ", "); } mp_printf(print, "%q=", fields[i]); mp_obj_print_helper(print, o->items[i], PRINT_REPR); } mp_print_str(print, ")"); } #endif #if MICROPY_PY_ATTRTUPLE STATIC void mp_obj_attrtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_tuple_t *o = MP_OBJ_TO_PTR(o_in); const qstr *fields = (const qstr*)MP_OBJ_TO_PTR(o->items[o->len]); mp_obj_attrtuple_print_helper(print, fields, o); } STATIC void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); size_t len = self->len; const qstr *fields = (const qstr*)MP_OBJ_TO_PTR(self->items[len]); for (size_t i = 0; i < len; i++) { if (fields[i] == attr) { dest[0] = self->items[i]; return; } } } } mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items) { mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n + 1); o->base.type = &mp_type_attrtuple; o->len = n; for (size_t i = 0; i < n; i++) { o->items[i] = items[i]; } o->items[n] = MP_OBJ_FROM_PTR(fields); return MP_OBJ_FROM_PTR(o); } const mp_obj_type_t mp_type_attrtuple = { { &mp_type_type }, .name = MP_QSTR_tuple, // reuse tuple to save on a qstr .print = mp_obj_attrtuple_print, .unary_op = mp_obj_tuple_unary_op, .binary_op = mp_obj_tuple_binary_op, .attr = mp_obj_attrtuple_attr, .subscr = mp_obj_tuple_subscr, .getiter = mp_obj_tuple_getiter, }; #endif // MICROPY_PY_ATTRTUPLE micropython-1.12/py/objbool.c000066400000000000000000000056251357706137100162540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" typedef struct _mp_obj_bool_t { mp_obj_base_t base; bool value; } mp_obj_bool_t; STATIC void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_bool_t *self = MP_OBJ_TO_PTR(self_in); if (MICROPY_PY_UJSON && kind == PRINT_JSON) { if (self->value) { mp_print_str(print, "true"); } else { mp_print_str(print, "false"); } } else { if (self->value) { mp_print_str(print, "True"); } else { mp_print_str(print, "False"); } } } STATIC mp_obj_t bool_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); if (n_args == 0) { return mp_const_false; } else { return mp_obj_new_bool(mp_obj_is_true(args[0])); } } STATIC mp_obj_t bool_unary_op(mp_unary_op_t op, mp_obj_t o_in) { if (op == MP_UNARY_OP_LEN) { return MP_OBJ_NULL; } mp_obj_bool_t *self = MP_OBJ_TO_PTR(o_in); return mp_unary_op(op, MP_OBJ_NEW_SMALL_INT(self->value)); } STATIC mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_bool_t *self = MP_OBJ_TO_PTR(lhs_in); return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(self->value), rhs_in); } const mp_obj_type_t mp_type_bool = { { &mp_type_type }, .name = MP_QSTR_bool, .print = bool_print, .make_new = bool_make_new, .unary_op = bool_unary_op, .binary_op = bool_binary_op, }; const mp_obj_bool_t mp_const_false_obj = {{&mp_type_bool}, false}; const mp_obj_bool_t mp_const_true_obj = {{&mp_type_bool}, true}; micropython-1.12/py/objboundmeth.c000066400000000000000000000077461357706137100173140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" #include "py/runtime.h" typedef struct _mp_obj_bound_meth_t { mp_obj_base_t base; mp_obj_t meth; mp_obj_t self; } mp_obj_bound_meth_t; #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED STATIC void bound_meth_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_bound_meth_t *o = MP_OBJ_TO_PTR(o_in); mp_printf(print, "self, PRINT_REPR); mp_print_str(print, "."); mp_obj_print_helper(print, o->meth, PRINT_REPR); mp_print_str(print, ">"); } #endif mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, size_t n_kw, const mp_obj_t *args) { // need to insert self before all other args and then call meth size_t n_total = n_args + 2 * n_kw; mp_obj_t *args2 = NULL; #if MICROPY_ENABLE_PYSTACK args2 = mp_pystack_alloc(sizeof(mp_obj_t) * (1 + n_total)); #else mp_obj_t *free_args2 = NULL; if (n_total > 4) { // try to use heap to allocate temporary args array args2 = m_new_maybe(mp_obj_t, 1 + n_total); free_args2 = args2; } if (args2 == NULL) { // (fallback to) use stack to allocate temporary args array args2 = alloca(sizeof(mp_obj_t) * (1 + n_total)); } #endif args2[0] = self; memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t)); mp_obj_t res = mp_call_function_n_kw(meth, n_args + 1, n_kw, args2); #if MICROPY_ENABLE_PYSTACK mp_pystack_free(args2); #else if (free_args2 != NULL) { m_del(mp_obj_t, free_args2, 1 + n_total); } #endif return res; } STATIC mp_obj_t bound_meth_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_bound_meth_t *self = MP_OBJ_TO_PTR(self_in); return mp_call_method_self_n_kw(self->meth, self->self, n_args, n_kw, args); } #if MICROPY_PY_FUNCTION_ATTRS STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } // Delegate the load to the method object mp_obj_bound_meth_t *self = MP_OBJ_TO_PTR(self_in); mp_load_method_maybe(self->meth, attr, dest); } #endif STATIC const mp_obj_type_t mp_type_bound_meth = { { &mp_type_type }, .name = MP_QSTR_bound_method, #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED .print = bound_meth_print, #endif .call = bound_meth_call, #if MICROPY_PY_FUNCTION_ATTRS .attr = bound_meth_attr, #endif }; mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) { mp_obj_bound_meth_t *o = m_new_obj(mp_obj_bound_meth_t); o->base.type = &mp_type_bound_meth; o->meth = meth; o->self = self; return MP_OBJ_FROM_PTR(o); } micropython-1.12/py/objcell.c000066400000000000000000000046121357706137100162330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" typedef struct _mp_obj_cell_t { mp_obj_base_t base; mp_obj_t obj; } mp_obj_cell_t; mp_obj_t mp_obj_cell_get(mp_obj_t self_in) { mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in); return self->obj; } void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) { mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in); self->obj = obj; } #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_cell_t *o = MP_OBJ_TO_PTR(o_in); mp_printf(print, "obj); if (o->obj == MP_OBJ_NULL) { mp_print_str(print, "(nil)"); } else { mp_obj_print_helper(print, o->obj, PRINT_REPR); } mp_print_str(print, ">"); } #endif STATIC const mp_obj_type_t mp_type_cell = { { &mp_type_type }, .name = MP_QSTR_, // cell representation is just value in < > #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED .print = cell_print, #endif }; mp_obj_t mp_obj_new_cell(mp_obj_t obj) { mp_obj_cell_t *o = m_new_obj(mp_obj_cell_t); o->base.type = &mp_type_cell; o->obj = obj; return MP_OBJ_FROM_PTR(o); } micropython-1.12/py/objclosure.c000066400000000000000000000072451357706137100167750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" #include "py/runtime.h" typedef struct _mp_obj_closure_t { mp_obj_base_t base; mp_obj_t fun; size_t n_closed; mp_obj_t closed[]; } mp_obj_closure_t; STATIC mp_obj_t closure_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_closure_t *self = MP_OBJ_TO_PTR(self_in); // need to concatenate closed-over-vars and args size_t n_total = self->n_closed + n_args + 2 * n_kw; if (n_total <= 5) { // use stack to allocate temporary args array mp_obj_t args2[5]; memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t)); memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); return mp_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2); } else { // use heap to allocate temporary args array mp_obj_t *args2 = m_new(mp_obj_t, n_total); memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t)); memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); mp_obj_t res = mp_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2); m_del(mp_obj_t, args2, n_total); return res; } } #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED STATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_closure_t *o = MP_OBJ_TO_PTR(o_in); mp_print_str(print, "fun, PRINT_REPR); mp_printf(print, " at %p, n_closed=%u ", o, (int)o->n_closed); for (size_t i = 0; i < o->n_closed; i++) { if (o->closed[i] == MP_OBJ_NULL) { mp_print_str(print, "(nil)"); } else { mp_obj_print_helper(print, o->closed[i], PRINT_REPR); } mp_print_str(print, " "); } mp_print_str(print, ">"); } #endif const mp_obj_type_t closure_type = { { &mp_type_type }, .name = MP_QSTR_closure, #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED .print = closure_print, #endif .call = closure_call, }; mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed_over, const mp_obj_t *closed) { mp_obj_closure_t *o = m_new_obj_var(mp_obj_closure_t, mp_obj_t, n_closed_over); o->base.type = &closure_type; o->fun = fun; o->n_closed = n_closed_over; memcpy(o->closed, closed, n_closed_over * sizeof(mp_obj_t)); return MP_OBJ_FROM_PTR(o); } micropython-1.12/py/objcomplex.c000066400000000000000000000220561357706137100167650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/parsenum.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_COMPLEX #include #include "py/formatfloat.h" typedef struct _mp_obj_complex_t { mp_obj_base_t base; mp_float_t real; mp_float_t imag; } mp_obj_complex_t; STATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in); #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT char buf[16]; #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C const int precision = 6; #else const int precision = 7; #endif #else char buf[32]; const int precision = 16; #endif if (o->real == 0) { mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\0'); mp_printf(print, "%sj", buf); } else { mp_format_float(o->real, buf, sizeof(buf), 'g', precision, '\0'); mp_printf(print, "(%s", buf); if (o->imag >= 0 || isnan(o->imag)) { mp_print_str(print, "+"); } mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\0'); mp_printf(print, "%sj)", buf); } } STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 2, false); switch (n_args) { case 0: return mp_obj_new_complex(0, 0); case 1: if (mp_obj_is_str(args[0])) { // a string, parse it size_t l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_decimal(s, l, true, true, NULL); } else if (mp_obj_is_type(args[0], &mp_type_complex)) { // a complex, just return it return args[0]; } else { // something else, try to cast it to a complex return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); } case 2: default: { mp_float_t real, imag; if (mp_obj_is_type(args[0], &mp_type_complex)) { mp_obj_complex_get(args[0], &real, &imag); } else { real = mp_obj_get_float(args[0]); imag = 0; } if (mp_obj_is_type(args[1], &mp_type_complex)) { mp_float_t real2, imag2; mp_obj_complex_get(args[1], &real2, &imag2); real -= imag2; imag += real2; } else { imag += mp_obj_get_float(args[1]); } return mp_obj_new_complex(real, imag); } } } STATIC mp_obj_t complex_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->real != 0 || o->imag != 0); case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(o->real) ^ mp_float_hash(o->imag)); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag); case MP_UNARY_OP_ABS: return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(o->real*o->real + o->imag*o->imag)); default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t complex_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_complex_t *lhs = MP_OBJ_TO_PTR(lhs_in); return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in); } STATIC void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } mp_obj_complex_t *self = MP_OBJ_TO_PTR(self_in); if (attr == MP_QSTR_real) { dest[0] = mp_obj_new_float(self->real); } else if (attr == MP_QSTR_imag) { dest[0] = mp_obj_new_float(self->imag); } } const mp_obj_type_t mp_type_complex = { { &mp_type_type }, .name = MP_QSTR_complex, .print = complex_print, .make_new = complex_make_new, .unary_op = complex_unary_op, .binary_op = complex_binary_op, .attr = complex_attr, }; mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) { mp_obj_complex_t *o = m_new_obj(mp_obj_complex_t); o->base.type = &mp_type_complex; o->real = real; o->imag = imag; return MP_OBJ_FROM_PTR(o); } void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) { assert(mp_obj_is_type(self_in, &mp_type_complex)); mp_obj_complex_t *self = MP_OBJ_TO_PTR(self_in); *real = self->real; *imag = self->imag; } mp_obj_t mp_obj_complex_binary_op(mp_binary_op_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in) { mp_float_t rhs_real, rhs_imag; mp_obj_get_complex(rhs_in, &rhs_real, &rhs_imag); // can be any type, this function will convert to float (if possible) switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: lhs_real += rhs_real; lhs_imag += rhs_imag; break; case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_real -= rhs_real; lhs_imag -= rhs_imag; break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: { mp_float_t real; multiply: real = lhs_real * rhs_real - lhs_imag * rhs_imag; lhs_imag = lhs_real * rhs_imag + lhs_imag * rhs_real; lhs_real = real; break; } case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: mp_raise_TypeError("can't truncate-divide a complex number"); case MP_BINARY_OP_TRUE_DIVIDE: case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_imag == 0) { if (rhs_real == 0) { mp_raise_msg(&mp_type_ZeroDivisionError, "complex divide by zero"); } lhs_real /= rhs_real; lhs_imag /= rhs_real; } else if (rhs_real == 0) { mp_float_t real = lhs_imag / rhs_imag; lhs_imag = -lhs_real / rhs_imag; lhs_real = real; } else { mp_float_t rhs_len_sq = rhs_real*rhs_real + rhs_imag*rhs_imag; rhs_real /= rhs_len_sq; rhs_imag /= -rhs_len_sq; goto multiply; } break; case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: { // z1**z2 = exp(z2*ln(z1)) // = exp(z2*(ln(|z1|)+i*arg(z1))) // = exp( (x2*ln1 - y2*arg1) + i*(y2*ln1 + x2*arg1) ) // = exp(x3 + i*y3) // = exp(x3)*(cos(y3) + i*sin(y3)) mp_float_t abs1 = MICROPY_FLOAT_C_FUN(sqrt)(lhs_real*lhs_real + lhs_imag*lhs_imag); if (abs1 == 0) { if (rhs_imag == 0 && rhs_real >= 0) { lhs_real = (rhs_real == 0); } else { mp_raise_msg(&mp_type_ZeroDivisionError, "0.0 to a complex power"); } } else { mp_float_t ln1 = MICROPY_FLOAT_C_FUN(log)(abs1); mp_float_t arg1 = MICROPY_FLOAT_C_FUN(atan2)(lhs_imag, lhs_real); mp_float_t x3 = rhs_real * ln1 - rhs_imag * arg1; mp_float_t y3 = rhs_imag * ln1 + rhs_real * arg1; mp_float_t exp_x3 = MICROPY_FLOAT_C_FUN(exp)(x3); lhs_real = exp_x3 * MICROPY_FLOAT_C_FUN(cos)(y3); lhs_imag = exp_x3 * MICROPY_FLOAT_C_FUN(sin)(y3); } break; } case MP_BINARY_OP_EQUAL: return mp_obj_new_bool(lhs_real == rhs_real && lhs_imag == rhs_imag); default: return MP_OBJ_NULL; // op not supported } return mp_obj_new_complex(lhs_real, lhs_imag); } #endif micropython-1.12/py/objdeque.c000066400000000000000000000120641357706137100164170ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include // for ssize_t #include #include "py/mpconfig.h" #if MICROPY_PY_COLLECTIONS_DEQUE #include "py/runtime.h" typedef struct _mp_obj_deque_t { mp_obj_base_t base; size_t alloc; size_t i_get; size_t i_put; mp_obj_t *items; uint32_t flags; #define FLAG_CHECK_OVERFLOW 1 } mp_obj_deque_t; STATIC mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 3, false); /* Initialization from existing sequence is not supported, so an empty tuple must be passed as such. */ if (args[0] != mp_const_empty_tuple) { mp_raise_ValueError(NULL); } // Protect against -1 leading to zero-length allocation and bad array access mp_int_t maxlen = mp_obj_get_int(args[1]); if (maxlen < 0) { mp_raise_ValueError(NULL); } mp_obj_deque_t *o = m_new_obj(mp_obj_deque_t); o->base.type = type; o->alloc = maxlen + 1; o->i_get = o->i_put = 0; o->items = m_new0(mp_obj_t, o->alloc); if (n_args > 2) { o->flags = mp_obj_get_int(args[2]); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t deque_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->i_get != self->i_put); case MP_UNARY_OP_LEN: { ssize_t len = self->i_put - self->i_get; if (len < 0) { len += self->alloc; } return MP_OBJ_NEW_SMALL_INT(len); } #if MICROPY_PY_SYS_GETSIZEOF case MP_UNARY_OP_SIZEOF: { size_t sz = sizeof(*self) + sizeof(mp_obj_t) * self->alloc; return MP_OBJ_NEW_SMALL_INT(sz); } #endif default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) { mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); size_t new_i_put = self->i_put + 1; if (new_i_put == self->alloc) { new_i_put = 0; } if (self->flags & FLAG_CHECK_OVERFLOW && new_i_put == self->i_get) { mp_raise_msg(&mp_type_IndexError, "full"); } self->items[self->i_put] = arg; self->i_put = new_i_put; if (self->i_get == new_i_put) { if (++self->i_get == self->alloc) { self->i_get = 0; } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(deque_append_obj, mp_obj_deque_append); STATIC mp_obj_t deque_popleft(mp_obj_t self_in) { mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); if (self->i_get == self->i_put) { mp_raise_msg(&mp_type_IndexError, "empty"); } mp_obj_t ret = self->items[self->i_get]; self->items[self->i_get] = MP_OBJ_NULL; if (++self->i_get == self->alloc) { self->i_get = 0; } return ret; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(deque_popleft_obj, deque_popleft); #if 0 STATIC mp_obj_t deque_clear(mp_obj_t self_in) { mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); self->i_get = self->i_put = 0; mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(deque_clear_obj, deque_clear); #endif STATIC const mp_rom_map_elem_t deque_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&deque_append_obj) }, #if 0 { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&deque_clear_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_popleft), MP_ROM_PTR(&deque_popleft_obj) }, }; STATIC MP_DEFINE_CONST_DICT(deque_locals_dict, deque_locals_dict_table); const mp_obj_type_t mp_type_deque = { { &mp_type_type }, .name = MP_QSTR_deque, .make_new = deque_make_new, .unary_op = deque_unary_op, .locals_dict = (mp_obj_dict_t*)&deque_locals_dict, }; #endif // MICROPY_PY_COLLECTIONS_DEQUE micropython-1.12/py/objdict.c000066400000000000000000000543001357706137100162360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/builtin.h" #include "py/objtype.h" #include "py/objstr.h" #define mp_obj_is_dict_type(o) (mp_obj_is_obj(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->make_new == dict_make_new) STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); // This is a helper function to iterate through a dictionary. The state of // the iteration is held in *cur and should be initialised with zero for the // first call. Will return NULL when no more elements are available. STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) { size_t max = dict->map.alloc; mp_map_t *map = &dict->map; for (size_t i = *cur; i < max; i++) { if (mp_map_slot_is_filled(map, i)) { *cur = i + 1; return &(map->table[i]); } } return NULL; } STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); bool first = true; if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) { kind = PRINT_REPR; } if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) { mp_printf(print, "%q(", self->base.type->name); } mp_print_str(print, "{"); size_t cur = 0; mp_map_elem_t *next = NULL; while ((next = dict_iter_next(self, &cur)) != NULL) { if (!first) { mp_print_str(print, ", "); } first = false; bool add_quote = MICROPY_PY_UJSON && kind == PRINT_JSON && !mp_obj_is_str_or_bytes(next->key); if (add_quote) { mp_print_str(print, "\""); } mp_obj_print_helper(print, next->key, kind); if (add_quote) { mp_print_str(print, "\""); } mp_print_str(print, ": "); mp_obj_print_helper(print, next->value, kind); } mp_print_str(print, "}"); if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) { mp_print_str(print, ")"); } } STATIC mp_obj_t dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_t dict_out = mp_obj_new_dict(0); mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out); dict->base.type = type; #if MICROPY_PY_COLLECTIONS_ORDEREDDICT if (type == &mp_type_ordereddict) { dict->map.is_ordered = 1; } #endif if (n_args > 0 || n_kw > 0) { mp_obj_t args2[2] = {dict_out, args[0]}; // args[0] is always valid, even if it's not a positional arg mp_map_t kwargs; mp_map_init_fixed_table(&kwargs, n_kw, args + n_args); dict_update(n_args + 1, args2, &kwargs); // dict_update will check that n_args + 1 == 1 or 2 } return dict_out; } STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->map.used != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->map.used); #if MICROPY_PY_SYS_GETSIZEOF case MP_UNARY_OP_SIZEOF: { size_t sz = sizeof(*self) + sizeof(*self->map.table) * self->map.alloc; return MP_OBJ_NEW_SMALL_INT(sz); } #endif default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in); switch (op) { case MP_BINARY_OP_CONTAINS: { mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP); return mp_obj_new_bool(elem != NULL); } case MP_BINARY_OP_EQUAL: { #if MICROPY_PY_COLLECTIONS_ORDEREDDICT if (MP_UNLIKELY(mp_obj_is_type(lhs_in, &mp_type_ordereddict) && mp_obj_is_type(rhs_in, &mp_type_ordereddict))) { // Iterate through both dictionaries simultaneously and compare keys and values. mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in); size_t c1 = 0, c2 = 0; mp_map_elem_t *e1 = dict_iter_next(o, &c1), *e2 = dict_iter_next(rhs, &c2); for (; e1 != NULL && e2 != NULL; e1 = dict_iter_next(o, &c1), e2 = dict_iter_next(rhs, &c2)) { if (!mp_obj_equal(e1->key, e2->key) || !mp_obj_equal(e1->value, e2->value)) { return mp_const_false; } } return e1 == NULL && e2 == NULL ? mp_const_true : mp_const_false; } else #endif if (mp_obj_is_type(rhs_in, &mp_type_dict)) { mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in); if (o->map.used != rhs->map.used) { return mp_const_false; } size_t cur = 0; mp_map_elem_t *next = NULL; while ((next = dict_iter_next(o, &cur)) != NULL) { mp_map_elem_t *elem = mp_map_lookup(&rhs->map, next->key, MP_MAP_LOOKUP); if (elem == NULL || !mp_obj_equal(next->value, elem->value)) { return mp_const_false; } } return mp_const_true; } else { // dict is not equal to instance of any other type return mp_const_false; } } default: // op not supported return MP_OBJ_NULL; } } // Note: Make sure this is inlined in load part of dict_subscr() below. mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP); if (elem == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, index)); } else { return elem->value; } } STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete mp_obj_dict_delete(self_in, index); return mp_const_none; } else if (value == MP_OBJ_SENTINEL) { // load mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP); if (elem == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, index)); } else { return elem->value; } } else { // store mp_obj_dict_store(self_in, index, value); return mp_const_none; } } /******************************************************************************/ /* dict methods */ STATIC void mp_ensure_not_fixed(const mp_obj_dict_t *dict) { if (dict->map.is_fixed) { mp_raise_TypeError(NULL); } } STATIC mp_obj_t dict_clear(mp_obj_t self_in) { mp_check_self(mp_obj_is_dict_type(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_ensure_not_fixed(self); mp_map_clear(&self->map); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear); STATIC mp_obj_t dict_copy(mp_obj_t self_in) { mp_check_self(mp_obj_is_dict_type(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t other_out = mp_obj_new_dict(self->map.alloc); mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out); other->base.type = self->base.type; other->map.used = self->map.used; other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs; other->map.is_fixed = 0; other->map.is_ordered = self->map.is_ordered; memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t)); return other_out; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy); #if MICROPY_PY_BUILTINS_DICT_FROMKEYS // this is a classmethod STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) { mp_obj_t iter = mp_getiter(args[1], NULL); mp_obj_t value = mp_const_none; mp_obj_t next = MP_OBJ_NULL; if (n_args > 2) { value = args[2]; } // optimisation to allocate result based on len of argument mp_obj_t self_out; mp_obj_t len = mp_obj_len_maybe(args[1]); if (len == MP_OBJ_NULL) { /* object's type doesn't have a __len__ slot */ self_out = mp_obj_new_dict(0); } else { self_out = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len)); } mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_out); while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } return self_out; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_fun_obj, 2, 3, dict_fromkeys); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromkeys_fun_obj)); #endif STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) { mp_check_self(mp_obj_is_dict_type(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); if (lookup_kind != MP_MAP_LOOKUP) { mp_ensure_not_fixed(self); } mp_map_elem_t *elem = mp_map_lookup(&self->map, args[1], lookup_kind); mp_obj_t value; if (elem == NULL || elem->value == MP_OBJ_NULL) { if (n_args == 2) { if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, args[1])); } else { value = mp_const_none; } } else { value = args[2]; } if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { elem->value = value; } } else { value = elem->value; if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) { elem->value = MP_OBJ_NULL; // so that GC can collect the deleted value } } return value; } STATIC mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) { return dict_get_helper(n_args, args, MP_MAP_LOOKUP); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get); STATIC mp_obj_t dict_pop(size_t n_args, const mp_obj_t *args) { return dict_get_helper(n_args, args, MP_MAP_LOOKUP_REMOVE_IF_FOUND); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop); STATIC mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) { return dict_get_helper(n_args, args, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setdefault); STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { mp_check_self(mp_obj_is_dict_type(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_ensure_not_fixed(self); size_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); if (next == NULL) { mp_raise_msg(&mp_type_KeyError, "popitem(): dictionary is empty"); } self->map.used--; mp_obj_t items[] = {next->key, next->value}; next->key = MP_OBJ_SENTINEL; // must mark key as sentinel to indicate that it was deleted next->value = MP_OBJ_NULL; mp_obj_t tuple = mp_obj_new_tuple(2, items); return tuple; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem); STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { mp_check_self(mp_obj_is_dict_type(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); mp_ensure_not_fixed(self); mp_arg_check_num(n_args, kwargs->used, 1, 2, true); if (n_args == 2) { // given a positional argument if (mp_obj_is_dict_type(args[1])) { // update from other dictionary (make sure other is not self) if (args[1] != args[0]) { size_t cur = 0; mp_map_elem_t *elem = NULL; while ((elem = dict_iter_next((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[1]), &cur)) != NULL) { mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value; } } } else { // update from a generic iterable of pairs mp_obj_t iter = mp_getiter(args[1], NULL); mp_obj_t next = MP_OBJ_NULL; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_t inneriter = mp_getiter(next, NULL); mp_obj_t key = mp_iternext(inneriter); mp_obj_t value = mp_iternext(inneriter); mp_obj_t stop = mp_iternext(inneriter); if (key == MP_OBJ_STOP_ITERATION || value == MP_OBJ_STOP_ITERATION || stop != MP_OBJ_STOP_ITERATION) { mp_raise_ValueError("dict update sequence has wrong length"); } else { mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } } } } // update the dict with any keyword args for (size_t i = 0; i < kwargs->alloc; i++) { if (mp_map_slot_is_filled(kwargs, i)) { mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value; } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(dict_update_obj, 1, dict_update); /******************************************************************************/ /* dict views */ STATIC const mp_obj_type_t dict_view_type; STATIC const mp_obj_type_t dict_view_it_type; typedef enum _mp_dict_view_kind_t { MP_DICT_VIEW_ITEMS, MP_DICT_VIEW_KEYS, MP_DICT_VIEW_VALUES, } mp_dict_view_kind_t; STATIC const char *const mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"}; typedef struct _mp_obj_dict_view_it_t { mp_obj_base_t base; mp_dict_view_kind_t kind; mp_obj_t dict; size_t cur; } mp_obj_dict_view_it_t; typedef struct _mp_obj_dict_view_t { mp_obj_base_t base; mp_obj_t dict; mp_dict_view_kind_t kind; } mp_obj_dict_view_t; STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &dict_view_it_type)); mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur); if (next == NULL) { return MP_OBJ_STOP_ITERATION; } else { switch (self->kind) { case MP_DICT_VIEW_ITEMS: default: { mp_obj_t items[] = {next->key, next->value}; return mp_obj_new_tuple(2, items); } case MP_DICT_VIEW_KEYS: return next->key; case MP_DICT_VIEW_VALUES: return next->value; } } } STATIC const mp_obj_type_t dict_view_it_type = { { &mp_type_type }, .name = MP_QSTR_iterator, .getiter = mp_identity_getiter, .iternext = dict_view_it_iternext, }; STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_check_self(mp_obj_is_type(view_in, &dict_view_type)); mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in); mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf; o->base.type = &dict_view_it_type; o->kind = view->kind; o->dict = view->dict; o->cur = 0; return MP_OBJ_FROM_PTR(o); } STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_check_self(mp_obj_is_type(self_in, &dict_view_type)); mp_obj_dict_view_t *self = MP_OBJ_TO_PTR(self_in); bool first = true; mp_print_str(print, mp_dict_view_names[self->kind]); mp_print_str(print, "(["); mp_obj_iter_buf_t iter_buf; mp_obj_t self_iter = dict_view_getiter(self_in, &iter_buf); mp_obj_t next = MP_OBJ_NULL; while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) { if (!first) { mp_print_str(print, ", "); } first = false; mp_obj_print_helper(print, next, PRINT_REPR); } mp_print_str(print, "])"); } STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // only supported for the 'keys' kind until sets and dicts are refactored mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(lhs_in); if (o->kind != MP_DICT_VIEW_KEYS) { return MP_OBJ_NULL; // op not supported } if (op != MP_BINARY_OP_CONTAINS) { return MP_OBJ_NULL; // op not supported } return dict_binary_op(op, o->dict, rhs_in); } STATIC const mp_obj_type_t dict_view_type = { { &mp_type_type }, .name = MP_QSTR_dict_view, .print = dict_view_print, .binary_op = dict_view_binary_op, .getiter = dict_view_getiter, }; STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) { mp_obj_dict_view_t *o = m_new_obj(mp_obj_dict_view_t); o->base.type = &dict_view_type; o->dict = dict; o->kind = kind; return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) { mp_check_self(mp_obj_is_dict_type(self_in)); return mp_obj_new_dict_view(self_in, kind); } STATIC mp_obj_t dict_items(mp_obj_t self_in) { return dict_view(self_in, MP_DICT_VIEW_ITEMS); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items); STATIC mp_obj_t dict_keys(mp_obj_t self_in) { return dict_view(self_in, MP_DICT_VIEW_KEYS); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys); STATIC mp_obj_t dict_values(mp_obj_t self_in) { return dict_view(self_in, MP_DICT_VIEW_VALUES); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values); /******************************************************************************/ /* dict iterator */ STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_check_self(mp_obj_is_dict_type(self_in)); mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf; o->base.type = &dict_view_it_type; o->kind = MP_DICT_VIEW_KEYS; o->dict = self_in; o->cur = 0; return MP_OBJ_FROM_PTR(o); } /******************************************************************************/ /* dict constructors & public C API */ STATIC const mp_rom_map_elem_t dict_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&dict_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&dict_copy_obj) }, #if MICROPY_PY_BUILTINS_DICT_FROMKEYS { MP_ROM_QSTR(MP_QSTR_fromkeys), MP_ROM_PTR(&dict_fromkeys_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&dict_get_obj) }, { MP_ROM_QSTR(MP_QSTR_items), MP_ROM_PTR(&dict_items_obj) }, { MP_ROM_QSTR(MP_QSTR_keys), MP_ROM_PTR(&dict_keys_obj) }, { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&dict_pop_obj) }, { MP_ROM_QSTR(MP_QSTR_popitem), MP_ROM_PTR(&dict_popitem_obj) }, { MP_ROM_QSTR(MP_QSTR_setdefault), MP_ROM_PTR(&dict_setdefault_obj) }, { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&dict_update_obj) }, { MP_ROM_QSTR(MP_QSTR_values), MP_ROM_PTR(&dict_values_obj) }, { MP_ROM_QSTR(MP_QSTR___getitem__), MP_ROM_PTR(&mp_op_getitem_obj) }, { MP_ROM_QSTR(MP_QSTR___setitem__), MP_ROM_PTR(&mp_op_setitem_obj) }, { MP_ROM_QSTR(MP_QSTR___delitem__), MP_ROM_PTR(&mp_op_delitem_obj) }, }; STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table); const mp_obj_type_t mp_type_dict = { { &mp_type_type }, .name = MP_QSTR_dict, .print = dict_print, .make_new = dict_make_new, .unary_op = dict_unary_op, .binary_op = dict_binary_op, .subscr = dict_subscr, .getiter = dict_getiter, .locals_dict = (mp_obj_dict_t*)&dict_locals_dict, }; #if MICROPY_PY_COLLECTIONS_ORDEREDDICT const mp_obj_type_t mp_type_ordereddict = { { &mp_type_type }, .name = MP_QSTR_OrderedDict, .print = dict_print, .make_new = dict_make_new, .unary_op = dict_unary_op, .binary_op = dict_binary_op, .subscr = dict_subscr, .getiter = dict_getiter, .parent = &mp_type_dict, .locals_dict = (mp_obj_dict_t*)&dict_locals_dict, }; #endif void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args) { dict->base.type = &mp_type_dict; mp_map_init(&dict->map, n_args); } mp_obj_t mp_obj_new_dict(size_t n_args) { mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t); mp_obj_dict_init(o, n_args); return MP_OBJ_FROM_PTR(o); } size_t mp_obj_dict_len(mp_obj_t self_in) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); return self->map.used; } mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { mp_check_self(mp_obj_is_dict_type(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_ensure_not_fixed(self); mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; return self_in; } mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) { mp_obj_t args[2] = {self_in, key}; dict_get_helper(2, args, MP_MAP_LOOKUP_REMOVE_IF_FOUND); return self_in; } micropython-1.12/py/objenumerate.c000066400000000000000000000062141357706137100173010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_BUILTINS_ENUMERATE typedef struct _mp_obj_enumerate_t { mp_obj_base_t base; mp_obj_t iter; mp_int_t cur; } mp_obj_enumerate_t; STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in); STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { #if MICROPY_CPYTHON_COMPAT static const mp_arg_t allowed_args[] = { { MP_QSTR_iterable, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_start, MP_ARG_INT, {.u_int = 0} }, }; // parse args struct { mp_arg_val_t iterable, start; } arg_vals; mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&arg_vals); // create enumerate object mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t); o->base.type = type; o->iter = mp_getiter(arg_vals.iterable.u_obj, NULL); o->cur = arg_vals.start.u_int; #else mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t); o->base.type = type; o->iter = mp_getiter(args[0], NULL); o->cur = n_args > 1 ? mp_obj_get_int(args[1]) : 0; #endif return MP_OBJ_FROM_PTR(o); } const mp_obj_type_t mp_type_enumerate = { { &mp_type_type }, .name = MP_QSTR_enumerate, .make_new = enumerate_make_new, .iternext = enumerate_iternext, .getiter = mp_identity_getiter, }; STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_enumerate)); mp_obj_enumerate_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t next = mp_iternext(self->iter); if (next == MP_OBJ_STOP_ITERATION) { return MP_OBJ_STOP_ITERATION; } else { mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(self->cur++), next}; return mp_obj_new_tuple(2, items); } } #endif // MICROPY_PY_BUILTINS_ENUMERATE micropython-1.12/py/objexcept.c000066400000000000000000000525761357706137100166200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/objlist.h" #include "py/objstr.h" #include "py/objtuple.h" #include "py/objtype.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mperrno.h" // Number of items per traceback entry (file, line, block) #define TRACEBACK_ENTRY_LEN (3) // Optionally allocated buffer for storing some traceback, the tuple argument, // and possible string object and data, for when the heap is locked. #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF // When used the layout of the emergency exception buffer is: // - traceback entry (file, line, block) // - traceback entry (file, line, block) // - mp_obj_tuple_t object // - n_args * mp_obj_t for tuple // - mp_obj_str_t object // - string data #define EMG_BUF_TRACEBACK_OFFSET (0) #define EMG_BUF_TRACEBACK_SIZE (2 * TRACEBACK_ENTRY_LEN * sizeof(size_t)) #define EMG_BUF_TUPLE_OFFSET (EMG_BUF_TRACEBACK_OFFSET + EMG_BUF_TRACEBACK_SIZE) #define EMG_BUF_TUPLE_SIZE(n_args) (sizeof(mp_obj_tuple_t) + n_args * sizeof(mp_obj_t)) #define EMG_BUF_STR_OFFSET (EMG_BUF_TUPLE_OFFSET + EMG_BUF_TUPLE_SIZE(1)) # if MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE > 0 #define mp_emergency_exception_buf_size MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE void mp_init_emergency_exception_buf(void) { // Nothing to do since the buffer was declared statically. We put this // definition here so that the calling code can call this function // regardless of how its configured (makes the calling code a bit cleaner). } #else #define mp_emergency_exception_buf_size MP_STATE_VM(mp_emergency_exception_buf_size) void mp_init_emergency_exception_buf(void) { mp_emergency_exception_buf_size = 0; MP_STATE_VM(mp_emergency_exception_buf) = NULL; } mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { mp_int_t size = mp_obj_get_int(size_in); void *buf = NULL; if (size > 0) { buf = m_new(byte, size); } int old_size = mp_emergency_exception_buf_size; void *old_buf = MP_STATE_VM(mp_emergency_exception_buf); // Update the 2 variables atomically so that an interrupt can't occur // between the assignments. mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_emergency_exception_buf_size = size; MP_STATE_VM(mp_emergency_exception_buf) = buf; MICROPY_END_ATOMIC_SECTION(atomic_state); if (old_buf != NULL) { m_del(byte, old_buf, old_size); } return mp_const_none; } #endif #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_exception_t *o = MP_OBJ_TO_PTR(o_in); mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS; bool is_subclass = kind & PRINT_EXC_SUBCLASS; if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) { mp_print_str(print, qstr_str(o->base.type->name)); } if (k == PRINT_EXC) { mp_print_str(print, ": "); } if (k == PRINT_STR || k == PRINT_EXC) { if (o->args == NULL || o->args->len == 0) { mp_print_str(print, ""); return; } else if (o->args->len == 1) { #if MICROPY_PY_UERRNO // try to provide a nice OSError error message if (o->base.type == &mp_type_OSError && mp_obj_is_small_int(o->args->items[0])) { qstr qst = mp_errno_to_str(o->args->items[0]); if (qst != MP_QSTRnull) { mp_printf(print, "[Errno " INT_FMT "] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst); return; } } #endif mp_obj_print_helper(print, o->args->items[0], PRINT_STR); return; } } mp_obj_tuple_print(print, MP_OBJ_FROM_PTR(o->args), kind); } mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false); // Try to allocate memory for the exception, with fallback to emergency exception object mp_obj_exception_t *o_exc = m_new_obj_maybe(mp_obj_exception_t); if (o_exc == NULL) { o_exc = &MP_STATE_VM(mp_emergency_exception_obj); } // Populate the exception object o_exc->base.type = type; o_exc->traceback_data = NULL; mp_obj_tuple_t *o_tuple; if (n_args == 0) { // No args, can use the empty tuple straightaway o_tuple = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; } else { // Try to allocate memory for the tuple containing the args o_tuple = m_new_obj_var_maybe(mp_obj_tuple_t, mp_obj_t, n_args); #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF // If we are called by mp_obj_new_exception_msg_varg then it will have // reserved room (after the traceback data) for a tuple with 1 element. // Otherwise we are free to use the whole buffer after the traceback data. if (o_tuple == NULL && mp_emergency_exception_buf_size >= EMG_BUF_TUPLE_OFFSET + EMG_BUF_TUPLE_SIZE(n_args)) { o_tuple = (mp_obj_tuple_t*) ((uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + EMG_BUF_TUPLE_OFFSET); } #endif if (o_tuple == NULL) { // No memory for a tuple, fallback to an empty tuple o_tuple = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; } else { // Have memory for a tuple so populate it o_tuple->base.type = &mp_type_tuple; o_tuple->len = n_args; memcpy(o_tuple->items, args, n_args * sizeof(mp_obj_t)); } } // Store the tuple of args in the exception object o_exc->args = o_tuple; return MP_OBJ_FROM_PTR(o_exc); } // Get exception "value" - that is, first argument, or None mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) { mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); if (self->args->len == 0) { return mp_const_none; } else { return self->args->items[0]; } } void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); if (dest[0] != MP_OBJ_NULL) { // store/delete attribute if (attr == MP_QSTR___traceback__ && dest[1] == mp_const_none) { // We allow 'exc.__traceback__ = None' assignment as low-level // optimization of pre-allocating exception instance and raising // it repeatedly - this avoids memory allocation during raise. // However, uPy will keep adding traceback entries to such // exception instance, so before throwing it, traceback should // be cleared like above. self->traceback_len = 0; dest[0] = MP_OBJ_NULL; // indicate success } return; } if (attr == MP_QSTR_args) { dest[0] = MP_OBJ_FROM_PTR(self->args); } else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) { dest[0] = mp_obj_exception_get_value(self_in); } } const mp_obj_type_t mp_type_BaseException = { { &mp_type_type }, .name = MP_QSTR_BaseException, .print = mp_obj_exception_print, .make_new = mp_obj_exception_make_new, .attr = mp_obj_exception_attr, }; // List of all exceptions, arranged as in the table at: // http://docs.python.org/3/library/exceptions.html MP_DEFINE_EXCEPTION(SystemExit, BaseException) MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException) MP_DEFINE_EXCEPTION(GeneratorExit, BaseException) MP_DEFINE_EXCEPTION(Exception, BaseException) #if MICROPY_PY_ASYNC_AWAIT MP_DEFINE_EXCEPTION(StopAsyncIteration, Exception) #endif MP_DEFINE_EXCEPTION(StopIteration, Exception) MP_DEFINE_EXCEPTION(ArithmeticError, Exception) //MP_DEFINE_EXCEPTION(FloatingPointError, ArithmeticError) MP_DEFINE_EXCEPTION(OverflowError, ArithmeticError) MP_DEFINE_EXCEPTION(ZeroDivisionError, ArithmeticError) MP_DEFINE_EXCEPTION(AssertionError, Exception) MP_DEFINE_EXCEPTION(AttributeError, Exception) //MP_DEFINE_EXCEPTION(BufferError, Exception) //MP_DEFINE_EXCEPTION(EnvironmentError, Exception) use OSError instead MP_DEFINE_EXCEPTION(EOFError, Exception) MP_DEFINE_EXCEPTION(ImportError, Exception) //MP_DEFINE_EXCEPTION(IOError, Exception) use OSError instead MP_DEFINE_EXCEPTION(LookupError, Exception) MP_DEFINE_EXCEPTION(IndexError, LookupError) MP_DEFINE_EXCEPTION(KeyError, LookupError) MP_DEFINE_EXCEPTION(MemoryError, Exception) MP_DEFINE_EXCEPTION(NameError, Exception) /* MP_DEFINE_EXCEPTION(UnboundLocalError, NameError) */ MP_DEFINE_EXCEPTION(OSError, Exception) #if MICROPY_PY_BUILTINS_TIMEOUTERROR MP_DEFINE_EXCEPTION(TimeoutError, OSError) #endif /* MP_DEFINE_EXCEPTION(BlockingIOError, OSError) MP_DEFINE_EXCEPTION(ChildProcessError, OSError) MP_DEFINE_EXCEPTION(ConnectionError, OSError) MP_DEFINE_EXCEPTION(BrokenPipeError, ConnectionError) MP_DEFINE_EXCEPTION(ConnectionAbortedError, ConnectionError) MP_DEFINE_EXCEPTION(ConnectionRefusedError, ConnectionError) MP_DEFINE_EXCEPTION(ConnectionResetError, ConnectionError) MP_DEFINE_EXCEPTION(InterruptedError, OSError) MP_DEFINE_EXCEPTION(IsADirectoryError, OSError) MP_DEFINE_EXCEPTION(NotADirectoryError, OSError) MP_DEFINE_EXCEPTION(PermissionError, OSError) MP_DEFINE_EXCEPTION(ProcessLookupError, OSError) MP_DEFINE_EXCEPTION(FileExistsError, OSError) MP_DEFINE_EXCEPTION(FileNotFoundError, OSError) MP_DEFINE_EXCEPTION(ReferenceError, Exception) */ MP_DEFINE_EXCEPTION(RuntimeError, Exception) MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError) MP_DEFINE_EXCEPTION(SyntaxError, Exception) MP_DEFINE_EXCEPTION(IndentationError, SyntaxError) /* MP_DEFINE_EXCEPTION(TabError, IndentationError) */ //MP_DEFINE_EXCEPTION(SystemError, Exception) MP_DEFINE_EXCEPTION(TypeError, Exception) #if MICROPY_EMIT_NATIVE MP_DEFINE_EXCEPTION(ViperTypeError, TypeError) #endif MP_DEFINE_EXCEPTION(ValueError, Exception) #if MICROPY_PY_BUILTINS_STR_UNICODE MP_DEFINE_EXCEPTION(UnicodeError, ValueError) //TODO: Implement more UnicodeError subclasses which take arguments #endif /* MP_DEFINE_EXCEPTION(Warning, Exception) MP_DEFINE_EXCEPTION(DeprecationWarning, Warning) MP_DEFINE_EXCEPTION(PendingDeprecationWarning, Warning) MP_DEFINE_EXCEPTION(RuntimeWarning, Warning) MP_DEFINE_EXCEPTION(SyntaxWarning, Warning) MP_DEFINE_EXCEPTION(UserWarning, Warning) MP_DEFINE_EXCEPTION(FutureWarning, Warning) MP_DEFINE_EXCEPTION(ImportWarning, Warning) MP_DEFINE_EXCEPTION(UnicodeWarning, Warning) MP_DEFINE_EXCEPTION(BytesWarning, Warning) MP_DEFINE_EXCEPTION(ResourceWarning, Warning) */ mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) { return mp_obj_new_exception_args(exc_type, 0, NULL); } // "Optimized" version for common(?) case of having 1 exception arg mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { return mp_obj_new_exception_args(exc_type, 1, &arg); } mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args) { assert(exc_type->make_new == mp_obj_exception_make_new); return exc_type->make_new(exc_type, n_args, 0, args); } mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg) { // Check that the given type is an exception type assert(exc_type->make_new == mp_obj_exception_make_new); // Try to allocate memory for the message mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF // If memory allocation failed and there is an emergency buffer then try to use // that buffer to store the string object, reserving room at the start for the // traceback and 1-tuple. if (o_str == NULL && mp_emergency_exception_buf_size >= EMG_BUF_STR_OFFSET + sizeof(mp_obj_str_t)) { o_str = (mp_obj_str_t*)((uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + EMG_BUF_STR_OFFSET); } #endif if (o_str == NULL) { // No memory for the string object so create the exception with no args return mp_obj_exception_make_new(exc_type, 0, 0, NULL); } // Create the string object and call mp_obj_exception_make_new to create the exception o_str->base.type = &mp_type_str; o_str->len = strlen(msg); o_str->data = (const byte*)msg; o_str->hash = qstr_compute_hash(o_str->data, o_str->len); mp_obj_t arg = MP_OBJ_FROM_PTR(o_str); return mp_obj_exception_make_new(exc_type, 1, 0, &arg); } // The following struct and function implement a simple printer that conservatively // allocates memory and truncates the output data if no more memory can be obtained. // It leaves room for a null byte at the end of the buffer. struct _exc_printer_t { bool allow_realloc; size_t alloc; size_t len; byte *buf; }; STATIC void exc_add_strn(void *data, const char *str, size_t len) { struct _exc_printer_t *pr = data; if (pr->len + len >= pr->alloc) { // Not enough room for data plus a null byte so try to grow the buffer if (pr->allow_realloc) { size_t new_alloc = pr->alloc + len + 16; byte *new_buf = m_renew_maybe(byte, pr->buf, pr->alloc, new_alloc, true); if (new_buf == NULL) { pr->allow_realloc = false; len = pr->alloc - pr->len - 1; } else { pr->alloc = new_alloc; pr->buf = new_buf; } } else { len = pr->alloc - pr->len - 1; } } memcpy(pr->buf + pr->len, str, len); pr->len += len; } mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) { assert(fmt != NULL); // Check that the given type is an exception type assert(exc_type->make_new == mp_obj_exception_make_new); // Try to allocate memory for the message mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); size_t o_str_alloc = strlen(fmt) + 1; byte *o_str_buf = m_new_maybe(byte, o_str_alloc); bool used_emg_buf = false; #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF // If memory allocation failed and there is an emergency buffer then try to use // that buffer to store the string object and its data (at least 16 bytes for // the string data), reserving room at the start for the traceback and 1-tuple. if ((o_str == NULL || o_str_buf == NULL) && mp_emergency_exception_buf_size >= EMG_BUF_STR_OFFSET + sizeof(mp_obj_str_t) + 16) { used_emg_buf = true; o_str = (mp_obj_str_t*)((uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + EMG_BUF_STR_OFFSET); o_str_buf = (byte*)&o_str[1]; o_str_alloc = (uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - o_str_buf; } #endif if (o_str == NULL) { // No memory for the string object so create the exception with no args return mp_obj_exception_make_new(exc_type, 0, 0, NULL); } if (o_str_buf == NULL) { // No memory for the string buffer: assume that the fmt string is in ROM // and use that data as the data of the string o_str->len = o_str_alloc - 1; // will be equal to strlen(fmt) o_str->data = (const byte*)fmt; } else { // We have some memory to format the string struct _exc_printer_t exc_pr = {!used_emg_buf, o_str_alloc, 0, o_str_buf}; mp_print_t print = {&exc_pr, exc_add_strn}; va_list ap; va_start(ap, fmt); mp_vprintf(&print, fmt, ap); va_end(ap); exc_pr.buf[exc_pr.len] = '\0'; o_str->len = exc_pr.len; o_str->data = exc_pr.buf; } // Create the string object and call mp_obj_exception_make_new to create the exception o_str->base.type = &mp_type_str; o_str->hash = qstr_compute_hash(o_str->data, o_str->len); mp_obj_t arg = MP_OBJ_FROM_PTR(o_str); return mp_obj_exception_make_new(exc_type, 1, 0, &arg); } // return true if the given object is an exception type bool mp_obj_is_exception_type(mp_obj_t self_in) { if (mp_obj_is_type(self_in, &mp_type_type)) { // optimisation when self_in is a builtin exception mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); if (self->make_new == mp_obj_exception_make_new) { return true; } } return mp_obj_is_subclass_fast(self_in, MP_OBJ_FROM_PTR(&mp_type_BaseException)); } // return true if the given object is an instance of an exception type bool mp_obj_is_exception_instance(mp_obj_t self_in) { return mp_obj_is_exception_type(MP_OBJ_FROM_PTR(mp_obj_get_type(self_in))); } // Return true if exception (type or instance) is a subclass of given // exception type. Assumes exc_type is a subclass of BaseException, as // defined by mp_obj_is_exception_type(exc_type). bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) { // if exc is an instance of an exception, then extract and use its type if (mp_obj_is_exception_instance(exc)) { exc = MP_OBJ_FROM_PTR(mp_obj_get_type(exc)); } return mp_obj_is_subclass_fast(exc, exc_type); } // traceback handling functions #define GET_NATIVE_EXCEPTION(self, self_in) \ /* make sure self_in is an exception instance */ \ assert(mp_obj_is_exception_instance(self_in)); \ mp_obj_exception_t *self; \ if (mp_obj_is_native_exception_instance(self_in)) { \ self = MP_OBJ_TO_PTR(self_in); \ } else { \ self = MP_OBJ_TO_PTR(((mp_obj_instance_t*)MP_OBJ_TO_PTR(self_in))->subobj[0]); \ } void mp_obj_exception_clear_traceback(mp_obj_t self_in) { GET_NATIVE_EXCEPTION(self, self_in); // just set the traceback to the null object // we don't want to call any memory management functions here self->traceback_data = NULL; } void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block) { GET_NATIVE_EXCEPTION(self, self_in); // append this traceback info to traceback data // if memory allocation fails (eg because gc is locked), just return if (self->traceback_data == NULL) { self->traceback_data = m_new_maybe(size_t, TRACEBACK_ENTRY_LEN); if (self->traceback_data == NULL) { #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF if (mp_emergency_exception_buf_size >= EMG_BUF_TRACEBACK_OFFSET + EMG_BUF_TRACEBACK_SIZE) { // There is room in the emergency buffer for traceback data size_t *tb = (size_t*)((uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + EMG_BUF_TRACEBACK_OFFSET); self->traceback_data = tb; self->traceback_alloc = EMG_BUF_TRACEBACK_SIZE / sizeof(size_t); } else { // Can't allocate and no room in emergency buffer return; } #else // Can't allocate return; #endif } else { // Allocated the traceback data on the heap self->traceback_alloc = TRACEBACK_ENTRY_LEN; } self->traceback_len = 0; } else if (self->traceback_len + TRACEBACK_ENTRY_LEN > self->traceback_alloc) { #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF if (self->traceback_data == (size_t*)MP_STATE_VM(mp_emergency_exception_buf)) { // Can't resize the emergency buffer return; } #endif // be conservative with growing traceback data size_t *tb_data = m_renew_maybe(size_t, self->traceback_data, self->traceback_alloc, self->traceback_alloc + TRACEBACK_ENTRY_LEN, true); if (tb_data == NULL) { return; } self->traceback_data = tb_data; self->traceback_alloc += TRACEBACK_ENTRY_LEN; } size_t *tb_data = &self->traceback_data[self->traceback_len]; self->traceback_len += TRACEBACK_ENTRY_LEN; tb_data[0] = file; tb_data[1] = line; tb_data[2] = block; } void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values) { GET_NATIVE_EXCEPTION(self, self_in); if (self->traceback_data == NULL) { *n = 0; *values = NULL; } else { *n = self->traceback_len; *values = self->traceback_data; } } micropython-1.12/py/objexcept.h000066400000000000000000000041211357706137100166040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJEXCEPT_H #define MICROPY_INCLUDED_PY_OBJEXCEPT_H #include "py/obj.h" #include "py/objtuple.h" typedef struct _mp_obj_exception_t { mp_obj_base_t base; size_t traceback_alloc : (8 * sizeof(size_t) / 2); size_t traceback_len : (8 * sizeof(size_t) / 2); size_t *traceback_data; mp_obj_tuple_t *args; } mp_obj_exception_t; void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); #define MP_DEFINE_EXCEPTION(exc_name, base_name) \ const mp_obj_type_t mp_type_ ## exc_name = { \ { &mp_type_type }, \ .name = MP_QSTR_ ## exc_name, \ .print = mp_obj_exception_print, \ .make_new = mp_obj_exception_make_new, \ .attr = mp_obj_exception_attr, \ .parent = &mp_type_ ## base_name, \ }; #endif // MICROPY_INCLUDED_PY_OBJEXCEPT_H micropython-1.12/py/objfilter.c000066400000000000000000000047311357706137100166030ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FILTER typedef struct _mp_obj_filter_t { mp_obj_base_t base; mp_obj_t fun; mp_obj_t iter; } mp_obj_filter_t; STATIC mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 2, false); mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t); o->base.type = type; o->fun = args[0]; o->iter = mp_getiter(args[1], NULL); return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t filter_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_filter)); mp_obj_filter_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t next; while ((next = mp_iternext(self->iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_t val; if (self->fun != mp_const_none) { val = mp_call_function_n_kw(self->fun, 1, 0, &next); } else { val = next; } if (mp_obj_is_true(val)) { return next; } } return MP_OBJ_STOP_ITERATION; } const mp_obj_type_t mp_type_filter = { { &mp_type_type }, .name = MP_QSTR_filter, .make_new = filter_make_new, .getiter = mp_identity_getiter, .iternext = filter_iternext, }; #endif // MICROPY_PY_BUILTINS_FILTER micropython-1.12/py/objfloat.c000066400000000000000000000262741357706137100164310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/parsenum.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FLOAT #include #include "py/formatfloat.h" #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D // M_E and M_PI are not part of the math.h standard and may not be defined #ifndef M_E #define M_E (2.7182818284590452354) #endif #ifndef M_PI #define M_PI (3.14159265358979323846) #endif typedef struct _mp_obj_float_t { mp_obj_base_t base; mp_float_t value; } mp_obj_float_t; const mp_obj_float_t mp_const_float_e_obj = {{&mp_type_float}, M_E}; const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI}; #endif #if MICROPY_FLOAT_HIGH_QUALITY_HASH // must return actual integer value if it fits in mp_int_t mp_int_t mp_float_hash(mp_float_t src) { #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE typedef uint64_t mp_float_uint_t; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT typedef uint32_t mp_float_uint_t; #endif union { mp_float_t f; #if MP_ENDIANNESS_LITTLE struct { mp_float_uint_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p; #else struct { mp_float_uint_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p; #endif mp_float_uint_t i; } u = {.f = src}; mp_int_t val; const int adj_exp = (int)u.p.exp - MP_FLOAT_EXP_BIAS; if (adj_exp < 0) { // value < 1; must be sure to handle 0.0 correctly (ie return 0) val = u.i; } else { // if adj_exp is max then: u.p.frc==0 indicates inf, else NaN // else: 1 <= value mp_float_uint_t frc = u.p.frc | ((mp_float_uint_t)1 << MP_FLOAT_FRAC_BITS); if (adj_exp <= MP_FLOAT_FRAC_BITS) { // number may have a fraction; xor the integer part with the fractional part val = (frc >> (MP_FLOAT_FRAC_BITS - adj_exp)) ^ (frc & (((mp_float_uint_t)1 << (MP_FLOAT_FRAC_BITS - adj_exp)) - 1)); } else if ((unsigned int)adj_exp < BITS_PER_BYTE * sizeof(mp_int_t) - 1) { // the number is a (big) whole integer and will fit in val's signed-width val = (mp_int_t)frc << (adj_exp - MP_FLOAT_FRAC_BITS); } else { // integer part will overflow val's width so just use what bits we can val = frc; } } if (u.p.sgn) { val = -(mp_uint_t)val; } return val; } #endif STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_float_t o_val = mp_obj_float_get(o_in); #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT char buf[16]; #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C const int precision = 6; #else const int precision = 7; #endif #else char buf[32]; const int precision = 16; #endif mp_format_float(o_val, buf, sizeof(buf), 'g', precision, '\0'); mp_print_str(print, buf); if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) { // Python floats always have decimal point (unless inf or nan) mp_print_str(print, ".0"); } } STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: return mp_obj_new_float(0); case 1: default: { mp_buffer_info_t bufinfo; if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) { // a textual representation, parse it return mp_parse_num_decimal(bufinfo.buf, bufinfo.len, false, false, NULL); } else if (mp_obj_is_float(args[0])) { // a float, just return it return args[0]; } else { // something else, try to cast it to a float return mp_obj_new_float(mp_obj_get_float(args[0])); } } } } STATIC mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_float_t val = mp_obj_float_get(o_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(val != 0); case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(val)); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-val); case MP_UNARY_OP_ABS: { if (signbit(val)) { return mp_obj_new_float(-val); } else { return o_in; } } default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_float_t lhs_val = mp_obj_float_get(lhs_in); #if MICROPY_PY_BUILTINS_COMPLEX if (mp_obj_is_type(rhs_in, &mp_type_complex)) { return mp_obj_complex_binary_op(op, lhs_val, 0, rhs_in); } else #endif { return mp_obj_float_binary_op(op, lhs_val, rhs_in); } } const mp_obj_type_t mp_type_float = { { &mp_type_type }, .name = MP_QSTR_float, .print = float_print, .make_new = float_make_new, .unary_op = float_unary_op, .binary_op = float_binary_op, }; #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D mp_obj_t mp_obj_new_float(mp_float_t value) { mp_obj_float_t *o = m_new(mp_obj_float_t, 1); o->base.type = &mp_type_float; o->value = value; return MP_OBJ_FROM_PTR(o); } mp_float_t mp_obj_float_get(mp_obj_t self_in) { assert(mp_obj_is_float(self_in)); mp_obj_float_t *self = MP_OBJ_TO_PTR(self_in); return self->value; } #endif STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) { // logic here follows that of CPython // https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations // x == (x//y)*y + (x%y) // divmod(x, y) == (x//y, x%y) mp_float_t mod = MICROPY_FLOAT_C_FUN(fmod)(*x, *y); mp_float_t div = (*x - mod) / *y; // Python specs require that mod has same sign as second operand if (mod == 0.0) { mod = MICROPY_FLOAT_C_FUN(copysign)(0.0, *y); } else { if ((mod < 0.0) != (*y < 0.0)) { mod += *y; div -= 1.0; } } mp_float_t floordiv; if (div == 0.0) { // if division is zero, take the correct sign of zero floordiv = MICROPY_FLOAT_C_FUN(copysign)(0.0, *x / *y); } else { // Python specs require that x == (x//y)*y + (x%y) floordiv = MICROPY_FLOAT_C_FUN(floor)(div); if (div - floordiv > 0.5) { floordiv += 1.0; } } // return results *x = floordiv; *y = mod; } mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t rhs_in) { mp_float_t rhs_val; if (!mp_obj_get_float_maybe(rhs_in, &rhs_val)) { return MP_OBJ_NULL; // op not supported } switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break; case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break; case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { zero_division_error: mp_raise_msg(&mp_type_ZeroDivisionError, "divide by zero"); } // Python specs require that x == (x//y)*y + (x%y) so we must // call divmod to compute the correct floor division, which // returns the floor divide in lhs_val. mp_obj_float_divmod(&lhs_val, &rhs_val); break; case MP_BINARY_OP_TRUE_DIVIDE: case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_val == 0) { goto zero_division_error; } lhs_val /= rhs_val; break; case MP_BINARY_OP_MODULO: case MP_BINARY_OP_INPLACE_MODULO: if (rhs_val == 0) { goto zero_division_error; } lhs_val = MICROPY_FLOAT_C_FUN(fmod)(lhs_val, rhs_val); // Python specs require that mod has same sign as second operand if (lhs_val == 0.0) { lhs_val = MICROPY_FLOAT_C_FUN(copysign)(0.0, rhs_val); } else { if ((lhs_val < 0.0) != (rhs_val < 0.0)) { lhs_val += rhs_val; } } break; case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: if (lhs_val == 0 && rhs_val < 0 && !isinf(rhs_val)) { goto zero_division_error; } if (lhs_val < 0 && rhs_val != MICROPY_FLOAT_C_FUN(floor)(rhs_val)) { #if MICROPY_PY_BUILTINS_COMPLEX return mp_obj_complex_binary_op(MP_BINARY_OP_POWER, lhs_val, 0, rhs_in); #else mp_raise_ValueError("complex values not supported"); #endif } lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val); break; case MP_BINARY_OP_DIVMOD: { if (rhs_val == 0) { goto zero_division_error; } mp_obj_float_divmod(&lhs_val, &rhs_val); mp_obj_t tuple[2] = { mp_obj_new_float(lhs_val), mp_obj_new_float(rhs_val), }; return mp_obj_new_tuple(2, tuple); } case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); case MP_BINARY_OP_EQUAL: return mp_obj_new_bool(lhs_val == rhs_val); case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); default: return MP_OBJ_NULL; // op not supported } return mp_obj_new_float(lhs_val); } #endif // MICROPY_PY_BUILTINS_FLOAT micropython-1.12/py/objfun.c000066400000000000000000000450051357706137100161050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objtuple.h" #include "py/objfun.h" #include "py/runtime.h" #include "py/bc.h" #include "py/stackctrl.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #else // don't print debugging info #define DEBUG_PRINT (0) #define DEBUG_printf(...) (void)0 #endif // Note: the "name" entry in mp_obj_type_t for a function type must be // MP_QSTR_function because it is used to determine if an object is of generic // function type. /******************************************************************************/ /* builtin functions */ STATIC mp_obj_t fun_builtin_0_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)args; assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_0)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_check_num(n_args, n_kw, 0, 0, false); return self->fun._0(); } const mp_obj_type_t mp_type_fun_builtin_0 = { { &mp_type_type }, .name = MP_QSTR_function, .call = fun_builtin_0_call, .unary_op = mp_generic_unary_op, }; STATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_1)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_check_num(n_args, n_kw, 1, 1, false); return self->fun._1(args[0]); } const mp_obj_type_t mp_type_fun_builtin_1 = { { &mp_type_type }, .name = MP_QSTR_function, .call = fun_builtin_1_call, .unary_op = mp_generic_unary_op, }; STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_2)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_check_num(n_args, n_kw, 2, 2, false); return self->fun._2(args[0], args[1]); } const mp_obj_type_t mp_type_fun_builtin_2 = { { &mp_type_type }, .name = MP_QSTR_function, .call = fun_builtin_2_call, .unary_op = mp_generic_unary_op, }; STATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_3)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_check_num(n_args, n_kw, 3, 3, false); return self->fun._3(args[0], args[1], args[2]); } const mp_obj_type_t mp_type_fun_builtin_3 = { { &mp_type_type }, .name = MP_QSTR_function, .call = fun_builtin_3_call, .unary_op = mp_generic_unary_op, }; STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_var)); mp_obj_fun_builtin_var_t *self = MP_OBJ_TO_PTR(self_in); // check number of arguments mp_arg_check_num_sig(n_args, n_kw, self->sig); if (self->sig & 1) { // function allows keywords // we create a map directly from the given args array mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); return self->fun.kw(n_args, args, &kw_args); } else { // function takes a variable number of arguments, but no keywords return self->fun.var(n_args, args); } } const mp_obj_type_t mp_type_fun_builtin_var = { { &mp_type_type }, .name = MP_QSTR_function, .call = fun_builtin_var_call, .unary_op = mp_generic_unary_op, }; /******************************************************************************/ /* byte code functions */ qstr mp_obj_code_get_name(const byte *code_info) { MP_BC_PRELUDE_SIZE_DECODE(code_info); #if MICROPY_PERSISTENT_CODE return code_info[0] | (code_info[1] << 8); #else return mp_decode_uint_value(code_info); #endif } #if MICROPY_EMIT_NATIVE STATIC const mp_obj_type_t mp_type_fun_native; #endif qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) { const mp_obj_fun_bc_t *fun = MP_OBJ_TO_PTR(fun_in); #if MICROPY_EMIT_NATIVE if (fun->base.type == &mp_type_fun_native || fun->base.type == &mp_type_native_gen_wrap) { // TODO native functions don't have name stored return MP_QSTR_; } #endif const byte *bc = fun->bytecode; MP_BC_PRELUDE_SIG_DECODE(bc); return mp_obj_code_get_name(bc); } #if MICROPY_CPYTHON_COMPAT STATIC void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(o_in); mp_printf(print, "", mp_obj_fun_get_name(o_in), o); } #endif #if DEBUG_PRINT STATIC void dump_args(const mp_obj_t *a, size_t sz) { DEBUG_printf("%p: ", a); for (size_t i = 0; i < sz; i++) { DEBUG_printf("%p ", a[i]); } DEBUG_printf("\n"); } #else #define dump_args(...) (void)0 #endif // With this macro you can tune the maximum number of function state bytes // that will be allocated on the stack. Any function that needs more // than this will try to use the heap, with fallback to stack allocation. #define VM_MAX_STATE_ON_STACK (11 * sizeof(mp_uint_t)) #define DECODE_CODESTATE_SIZE(bytecode, n_state_out_var, state_size_out_var) \ { \ const uint8_t *ip = bytecode; \ size_t n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_args; \ MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state_out_var, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_args); \ \ /* state size in bytes */ \ state_size_out_var = n_state_out_var * sizeof(mp_obj_t) \ + n_exc_stack * sizeof(mp_exc_stack_t); \ } #define INIT_CODESTATE(code_state, _fun_bc, _n_state, n_args, n_kw, args) \ code_state->fun_bc = _fun_bc; \ code_state->ip = 0; \ code_state->n_state = _n_state; \ mp_setup_code_state(code_state, n_args, n_kw, args); \ code_state->old_globals = mp_globals_get(); #if MICROPY_STACKLESS mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { MP_STACK_CHECK(); mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); size_t n_state, state_size; DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size); mp_code_state_t *code_state; #if MICROPY_ENABLE_PYSTACK code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size); #else // If we use m_new_obj_var(), then on no memory, MemoryError will be // raised. But this is not correct exception for a function call, // RuntimeError should be raised instead. So, we use m_new_obj_var_maybe(), // return NULL, then vm.c takes the needed action (either raise // RuntimeError or fallback to stack allocation). code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); if (!code_state) { return NULL; } #endif INIT_CODESTATE(code_state, self, n_state, n_args, n_kw, args); // execute the byte code with the correct globals context mp_globals_set(self->globals); return code_state; } #endif STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { MP_STACK_CHECK(); DEBUG_printf("Input n_args: " UINT_FMT ", n_kw: " UINT_FMT "\n", n_args, n_kw); DEBUG_printf("Input pos args: "); dump_args(args, n_args); DEBUG_printf("Input kw args: "); dump_args(args + n_args, n_kw * 2); mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); size_t n_state, state_size; DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size); // allocate state for locals and stack mp_code_state_t *code_state = NULL; #if MICROPY_ENABLE_PYSTACK code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size); #else if (state_size > VM_MAX_STATE_ON_STACK) { code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); #if MICROPY_DEBUG_VM_STACK_OVERFLOW if (code_state != NULL) { memset(code_state->state, 0, state_size); } #endif } if (code_state == NULL) { code_state = alloca(sizeof(mp_code_state_t) + state_size); #if MICROPY_DEBUG_VM_STACK_OVERFLOW memset(code_state->state, 0, state_size); #endif state_size = 0; // indicate that we allocated using alloca } #endif INIT_CODESTATE(code_state, self, n_state, n_args, n_kw, args); // execute the byte code with the correct globals context mp_globals_set(self->globals); mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode(code_state, MP_OBJ_NULL); mp_globals_set(code_state->old_globals); #if MICROPY_DEBUG_VM_STACK_OVERFLOW if (vm_return_kind == MP_VM_RETURN_NORMAL) { if (code_state->sp < code_state->state) { mp_printf(MICROPY_DEBUG_PRINTER, "VM stack underflow: " INT_FMT "\n", code_state->sp - code_state->state); assert(0); } } const byte *bytecode_ptr = self->bytecode; size_t n_state_unused, n_exc_stack_unused, scope_flags_unused; size_t n_pos_args, n_kwonly_args, n_def_args_unused; MP_BC_PRELUDE_SIG_DECODE_INTO(bytecode_ptr, n_state_unused, n_exc_stack_unused, scope_flags_unused, n_pos_args, n_kwonly_args, n_def_args_unused); // We can't check the case when an exception is returned in state[0] // and there are no arguments, because in this case our detection slot may have // been overwritten by the returned exception (which is allowed). if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && n_pos_args + n_kwonly_args == 0)) { // Just check to see that we have at least 1 null object left in the state. bool overflow = true; for (size_t i = 0; i < n_state - n_pos_args - n_kwonly_args; ++i) { if (code_state->state[i] == MP_OBJ_NULL) { overflow = false; break; } } if (overflow) { mp_printf(MICROPY_DEBUG_PRINTER, "VM stack overflow state=%p n_state+1=" UINT_FMT "\n", code_state->state, n_state); assert(0); } } #endif mp_obj_t result; if (vm_return_kind == MP_VM_RETURN_NORMAL) { // return value is in *sp result = *code_state->sp; } else { // must be an exception because normal functions can't yield assert(vm_return_kind == MP_VM_RETURN_EXCEPTION); // returned exception is in state[0] result = code_state->state[0]; } #if MICROPY_ENABLE_PYSTACK mp_pystack_free(code_state); #else // free the state if it was allocated on the heap if (state_size != 0) { m_del_var(mp_code_state_t, byte, state_size, code_state); } #endif if (vm_return_kind == MP_VM_RETURN_NORMAL) { return result; } else { // MP_VM_RETURN_EXCEPTION nlr_raise(result); } } #if MICROPY_PY_FUNCTION_ATTRS void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } if (attr == MP_QSTR___name__) { dest[0] = MP_OBJ_NEW_QSTR(mp_obj_fun_get_name(self_in)); } } #endif const mp_obj_type_t mp_type_fun_bc = { { &mp_type_type }, .name = MP_QSTR_function, #if MICROPY_CPYTHON_COMPAT .print = fun_bc_print, #endif .call = fun_bc_call, .unary_op = mp_generic_unary_op, #if MICROPY_PY_FUNCTION_ATTRS .attr = mp_obj_fun_bc_attr, #endif }; mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table) { size_t n_def_args = 0; size_t n_extra_args = 0; mp_obj_tuple_t *def_args = MP_OBJ_TO_PTR(def_args_in); if (def_args_in != MP_OBJ_NULL) { assert(mp_obj_is_type(def_args_in, &mp_type_tuple)); n_def_args = def_args->len; n_extra_args = def_args->len; } if (def_kw_args != MP_OBJ_NULL) { n_extra_args += 1; } mp_obj_fun_bc_t *o = m_new_obj_var(mp_obj_fun_bc_t, mp_obj_t, n_extra_args); o->base.type = &mp_type_fun_bc; o->globals = mp_globals_get(); o->bytecode = code; o->const_table = const_table; if (def_args != NULL) { memcpy(o->extra_args, def_args->items, n_def_args * sizeof(mp_obj_t)); } if (def_kw_args != MP_OBJ_NULL) { o->extra_args[n_def_args] = def_kw_args; } return MP_OBJ_FROM_PTR(o); } /******************************************************************************/ /* native functions */ #if MICROPY_EMIT_NATIVE STATIC mp_obj_t fun_native_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { MP_STACK_CHECK(); mp_obj_fun_bc_t *self = self_in; mp_call_fun_t fun = MICROPY_MAKE_POINTER_CALLABLE((void*)self->bytecode); return fun(self_in, n_args, n_kw, args); } STATIC const mp_obj_type_t mp_type_fun_native = { { &mp_type_type }, .name = MP_QSTR_function, .call = fun_native_call, .unary_op = mp_generic_unary_op, }; mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data, const mp_uint_t *const_table) { mp_obj_fun_bc_t *o = mp_obj_new_fun_bc(def_args_in, def_kw_args, (const byte*)fun_data, const_table); o->base.type = &mp_type_fun_native; return o; } #endif // MICROPY_EMIT_NATIVE /******************************************************************************/ /* inline assembler functions */ #if MICROPY_EMIT_INLINE_ASM typedef struct _mp_obj_fun_asm_t { mp_obj_base_t base; size_t n_args; const void *fun_data; // GC must be able to trace this pointer mp_uint_t type_sig; } mp_obj_fun_asm_t; typedef mp_uint_t (*inline_asm_fun_0_t)(void); typedef mp_uint_t (*inline_asm_fun_1_t)(mp_uint_t); typedef mp_uint_t (*inline_asm_fun_2_t)(mp_uint_t, mp_uint_t); typedef mp_uint_t (*inline_asm_fun_3_t)(mp_uint_t, mp_uint_t, mp_uint_t); typedef mp_uint_t (*inline_asm_fun_4_t)(mp_uint_t, mp_uint_t, mp_uint_t, mp_uint_t); // convert a MicroPython object to a sensible value for inline asm STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { // TODO for byte_array, pass pointer to the array if (mp_obj_is_small_int(obj)) { return MP_OBJ_SMALL_INT_VALUE(obj); } else if (obj == mp_const_none) { return 0; } else if (obj == mp_const_false) { return 0; } else if (obj == mp_const_true) { return 1; } else if (mp_obj_is_type(obj, &mp_type_int)) { return mp_obj_int_get_truncated(obj); } else if (mp_obj_is_str(obj)) { // pointer to the string (it's probably constant though!) size_t l; return (mp_uint_t)mp_obj_str_get_data(obj, &l); } else { mp_obj_type_t *type = mp_obj_get_type(obj); #if MICROPY_PY_BUILTINS_FLOAT if (type == &mp_type_float) { // convert float to int (could also pass in float registers) return (mp_int_t)mp_obj_float_get(obj); } else #endif if (type == &mp_type_tuple || type == &mp_type_list) { // pointer to start of tuple (could pass length, but then could use len(x) for that) size_t len; mp_obj_t *items; mp_obj_get_array(obj, &len, &items); return (mp_uint_t)items; } else { mp_buffer_info_t bufinfo; if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_READ)) { // supports the buffer protocol, return a pointer to the data return (mp_uint_t)bufinfo.buf; } else { // just pass along a pointer to the object return (mp_uint_t)obj; } } } } STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_fun_asm_t *self = self_in; mp_arg_check_num(n_args, n_kw, self->n_args, self->n_args, false); const void *fun = MICROPY_MAKE_POINTER_CALLABLE(self->fun_data); mp_uint_t ret; if (n_args == 0) { ret = ((inline_asm_fun_0_t)fun)(); } else if (n_args == 1) { ret = ((inline_asm_fun_1_t)fun)(convert_obj_for_inline_asm(args[0])); } else if (n_args == 2) { ret = ((inline_asm_fun_2_t)fun)(convert_obj_for_inline_asm(args[0]), convert_obj_for_inline_asm(args[1])); } else if (n_args == 3) { ret = ((inline_asm_fun_3_t)fun)(convert_obj_for_inline_asm(args[0]), convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[2])); } else { // compiler allows at most 4 arguments assert(n_args == 4); ret = ((inline_asm_fun_4_t)fun)( convert_obj_for_inline_asm(args[0]), convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[2]), convert_obj_for_inline_asm(args[3]) ); } return mp_native_to_obj(ret, self->type_sig); } STATIC const mp_obj_type_t mp_type_fun_asm = { { &mp_type_type }, .name = MP_QSTR_function, .call = fun_asm_call, .unary_op = mp_generic_unary_op, }; mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig) { mp_obj_fun_asm_t *o = m_new_obj(mp_obj_fun_asm_t); o->base.type = &mp_type_fun_asm; o->n_args = n_args; o->fun_data = fun_data; o->type_sig = type_sig; return o; } #endif // MICROPY_EMIT_INLINE_ASM micropython-1.12/py/objfun.h000066400000000000000000000041451357706137100161120ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJFUN_H #define MICROPY_INCLUDED_PY_OBJFUN_H #include "py/obj.h" typedef struct _mp_obj_fun_bc_t { mp_obj_base_t base; mp_obj_dict_t *globals; // the context within which this function was defined const byte *bytecode; // bytecode for the function const mp_uint_t *const_table; // constant table #if MICROPY_PY_SYS_SETTRACE const struct _mp_raw_code_t *rc; #endif // the following extra_args array is allocated space to take (in order): // - values of positional default args (if any) // - a single slot for default kw args dict (if it has them) // - a single slot for var args tuple (if it takes them) // - a single slot for kw args dict (if it takes them) mp_obj_t extra_args[]; } mp_obj_fun_bc_t; void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); #endif // MICROPY_INCLUDED_PY_OBJFUN_H micropython-1.12/py/objgenerator.c000066400000000000000000000333461357706137100173100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/bc.h" #include "py/objstr.h" #include "py/objgenerator.h" #include "py/objfun.h" #include "py/stackctrl.h" // Instance of GeneratorExit exception - needed by generator.close() const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj}; /******************************************************************************/ /* generator wrapper */ typedef struct _mp_obj_gen_instance_t { mp_obj_base_t base; // mp_const_none: Not-running, no exception. // MP_OBJ_NULL: Running, no exception. // other: Not running, pending exception. mp_obj_t pend_exc; mp_code_state_t code_state; } mp_obj_gen_instance_t; STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { // A generating function is just a bytecode function with type mp_type_gen_wrap mp_obj_fun_bc_t *self_fun = MP_OBJ_TO_PTR(self_in); // bytecode prelude: get state size and exception stack size const uint8_t *ip = self_fun->bytecode; MP_BC_PRELUDE_SIG_DECODE(ip); // allocate the generator object, with room for local stack and exception stack mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t)); o->base.type = &mp_type_gen_instance; o->pend_exc = mp_const_none; o->code_state.fun_bc = self_fun; o->code_state.ip = 0; o->code_state.n_state = n_state; mp_setup_code_state(&o->code_state, n_args, n_kw, args); return MP_OBJ_FROM_PTR(o); } const mp_obj_type_t mp_type_gen_wrap = { { &mp_type_type }, .name = MP_QSTR_generator, .call = gen_wrap_call, .unary_op = mp_generic_unary_op, #if MICROPY_PY_FUNCTION_ATTRS .attr = mp_obj_fun_bc_attr, #endif }; /******************************************************************************/ // native generator wrapper #if MICROPY_EMIT_NATIVE STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { // The state for a native generating function is held in the same struct as a bytecode function mp_obj_fun_bc_t *self_fun = MP_OBJ_TO_PTR(self_in); // Determine start of prelude, and extract n_state from it uintptr_t prelude_offset = ((uintptr_t*)self_fun->bytecode)[0]; #if MICROPY_EMIT_NATIVE_PRELUDE_AS_BYTES_OBJ // Prelude is in bytes object in const_table, at index prelude_offset mp_obj_str_t *prelude_bytes = MP_OBJ_TO_PTR(self_fun->const_table[prelude_offset]); prelude_offset = (const byte*)prelude_bytes->data - self_fun->bytecode; #endif const uint8_t *ip = self_fun->bytecode + prelude_offset; size_t n_state, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_args; MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_args); size_t n_exc_stack = 0; // Allocate the generator object, with room for local stack and exception stack mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t)); o->base.type = &mp_type_gen_instance; // Parse the input arguments and set up the code state o->pend_exc = mp_const_none; o->code_state.fun_bc = self_fun; o->code_state.ip = (const byte*)prelude_offset; o->code_state.n_state = n_state; mp_setup_code_state(&o->code_state, n_args, n_kw, args); // Indicate we are a native function, which doesn't use this variable o->code_state.exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_SENTINEL; // Prepare the generator instance for execution uintptr_t start_offset = ((uintptr_t*)self_fun->bytecode)[1]; o->code_state.ip = MICROPY_MAKE_POINTER_CALLABLE((void*)(self_fun->bytecode + start_offset)); return MP_OBJ_FROM_PTR(o); } const mp_obj_type_t mp_type_native_gen_wrap = { { &mp_type_type }, .name = MP_QSTR_generator, .call = native_gen_wrap_call, .unary_op = mp_generic_unary_op, #if MICROPY_PY_FUNCTION_ATTRS .attr = mp_obj_fun_bc_attr, #endif }; #endif // MICROPY_EMIT_NATIVE /******************************************************************************/ /* generator instance */ STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self); } mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { MP_STACK_CHECK(); mp_check_self(mp_obj_is_type(self_in, &mp_type_gen_instance)); mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); if (self->code_state.ip == 0) { // Trying to resume already stopped generator *ret_val = MP_OBJ_STOP_ITERATION; return MP_VM_RETURN_NORMAL; } // Ensure the generator cannot be reentered during execution if (self->pend_exc == MP_OBJ_NULL) { mp_raise_ValueError("generator already executing"); } #if MICROPY_PY_GENERATOR_PEND_THROW // If exception is pending (set using .pend_throw()), process it now. if (self->pend_exc != mp_const_none) { throw_value = self->pend_exc; } #endif // If the generator is started, allow sending a value. if (self->code_state.sp == self->code_state.state - 1) { if (send_value != mp_const_none) { mp_raise_TypeError("can't send non-None value to a just-started generator"); } } else { *self->code_state.sp = send_value; } // Mark as running self->pend_exc = MP_OBJ_NULL; // Set up the correct globals context for the generator and execute it self->code_state.old_globals = mp_globals_get(); mp_globals_set(self->code_state.fun_bc->globals); mp_vm_return_kind_t ret_kind; #if MICROPY_EMIT_NATIVE if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) { // A native generator, with entry point 2 words into the "bytecode" pointer typedef uintptr_t (*mp_fun_native_gen_t)(void*, mp_obj_t); mp_fun_native_gen_t fun = MICROPY_MAKE_POINTER_CALLABLE((const void*)(self->code_state.fun_bc->bytecode + 2 * sizeof(uintptr_t))); ret_kind = fun((void*)&self->code_state, throw_value); } else #endif { // A bytecode generator ret_kind = mp_execute_bytecode(&self->code_state, throw_value); } mp_globals_set(self->code_state.old_globals); // Mark as not running self->pend_exc = mp_const_none; switch (ret_kind) { case MP_VM_RETURN_NORMAL: default: // Explicitly mark generator as completed. If we don't do this, // subsequent next() may re-execute statements after last yield // again and again, leading to side effects. self->code_state.ip = 0; *ret_val = *self->code_state.sp; break; case MP_VM_RETURN_YIELD: *ret_val = *self->code_state.sp; #if MICROPY_PY_GENERATOR_PEND_THROW *self->code_state.sp = mp_const_none; #endif break; case MP_VM_RETURN_EXCEPTION: { self->code_state.ip = 0; *ret_val = self->code_state.state[0]; // PEP479: if StopIteration is raised inside a generator it is replaced with RuntimeError if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(*ret_val)), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { *ret_val = mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator raised StopIteration"); } break; } } return ret_kind; } STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, send_value, throw_value, &ret)) { case MP_VM_RETURN_NORMAL: default: // Optimize return w/o value in case generator is used in for loop if (ret == mp_const_none || ret == MP_OBJ_STOP_ITERATION) { return MP_OBJ_STOP_ITERATION; } else { nlr_raise(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret)); } case MP_VM_RETURN_YIELD: return ret; case MP_VM_RETURN_EXCEPTION: nlr_raise(ret); } } STATIC mp_obj_t gen_instance_iternext(mp_obj_t self_in) { return gen_resume_and_raise(self_in, mp_const_none, MP_OBJ_NULL); } STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) { mp_obj_t ret = gen_resume_and_raise(self_in, send_value, MP_OBJ_NULL); if (ret == MP_OBJ_STOP_ITERATION) { nlr_raise(mp_obj_new_exception(&mp_type_StopIteration)); } else { return ret; } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send); STATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) { // The signature of this function is: throw(type[, value[, traceback]]) // CPython will pass all given arguments through the call chain and process them // at the point they are used (native generators will handle them differently to // user-defined generators with a throw() method). To save passing multiple // values, MicroPython instead does partial processing here to reduce it down to // one argument and passes that through: // - if only args[1] is given, or args[2] is given but is None, args[1] is // passed through (in the standard case it is an exception class or instance) // - if args[2] is given and not None it is passed through (in the standard // case it would be an exception instance and args[1] its corresponding class) // - args[3] is always ignored mp_obj_t exc = args[1]; if (n_args > 2 && args[2] != mp_const_none) { exc = args[2]; } mp_obj_t ret = gen_resume_and_raise(args[0], mp_const_none, exc); if (ret == MP_OBJ_STOP_ITERATION) { nlr_raise(mp_obj_new_exception(&mp_type_StopIteration)); } else { return ret; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_instance_throw); STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, mp_const_none, MP_OBJ_FROM_PTR(&mp_const_GeneratorExit_obj), &ret)) { case MP_VM_RETURN_YIELD: mp_raise_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"); // Swallow GeneratorExit (== successful close), and re-raise any other case MP_VM_RETURN_EXCEPTION: // ret should always be an instance of an exception class if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(ret)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { return mp_const_none; } nlr_raise(ret); default: // The only choice left is MP_VM_RETURN_NORMAL which is successful close return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close); #if MICROPY_PY_GENERATOR_PEND_THROW STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); if (self->pend_exc == MP_OBJ_NULL) { mp_raise_ValueError("generator already executing"); } mp_obj_t prev = self->pend_exc; self->pend_exc = exc_in; return prev; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_pend_throw_obj, gen_instance_pend_throw); #endif STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&gen_instance_close_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&gen_instance_send_obj) }, { MP_ROM_QSTR(MP_QSTR_throw), MP_ROM_PTR(&gen_instance_throw_obj) }, #if MICROPY_PY_GENERATOR_PEND_THROW { MP_ROM_QSTR(MP_QSTR_pend_throw), MP_ROM_PTR(&gen_instance_pend_throw_obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table); const mp_obj_type_t mp_type_gen_instance = { { &mp_type_type }, .name = MP_QSTR_generator, .print = gen_instance_print, .unary_op = mp_generic_unary_op, .getiter = mp_identity_getiter, .iternext = gen_instance_iternext, .locals_dict = (mp_obj_dict_t*)&gen_instance_locals_dict, }; micropython-1.12/py/objgenerator.h000066400000000000000000000027641357706137100173150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJGENERATOR_H #define MICROPY_INCLUDED_PY_OBJGENERATOR_H #include "py/obj.h" #include "py/runtime.h" mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_val, mp_obj_t throw_val, mp_obj_t *ret_val); #endif // MICROPY_INCLUDED_PY_OBJGENERATOR_H micropython-1.12/py/objgetitemiter.c000066400000000000000000000055261357706137100176430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" // this is a wrapper object that turns something that has a __getitem__ method into an iterator typedef struct _mp_obj_getitem_iter_t { mp_obj_base_t base; mp_obj_t args[3]; } mp_obj_getitem_iter_t; STATIC mp_obj_t it_iternext(mp_obj_t self_in) { mp_obj_getitem_iter_t *self = MP_OBJ_TO_PTR(self_in); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { // try to get next item mp_obj_t value = mp_call_method_n_kw(1, 0, self->args); self->args[2] = MP_OBJ_NEW_SMALL_INT(MP_OBJ_SMALL_INT_VALUE(self->args[2]) + 1); nlr_pop(); return value; } else { // an exception was raised mp_obj_type_t *t = (mp_obj_type_t*)((mp_obj_base_t*)nlr.ret_val)->type; if (t == &mp_type_StopIteration || t == &mp_type_IndexError) { // return MP_OBJ_STOP_ITERATION instead of raising return MP_OBJ_STOP_ITERATION; } else { // re-raise exception nlr_jump(nlr.ret_val); } } } STATIC const mp_obj_type_t it_type = { { &mp_type_type }, .name = MP_QSTR_iterator, .getiter = mp_identity_getiter, .iternext = it_iternext, }; // args are those returned from mp_load_method_maybe (ie either an attribute or a method) mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_getitem_iter_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_getitem_iter_t *o = (mp_obj_getitem_iter_t*)iter_buf; o->base.type = &it_type; o->args[0] = args[0]; o->args[1] = args[1]; o->args[2] = MP_OBJ_NEW_SMALL_INT(0); return MP_OBJ_FROM_PTR(o); } micropython-1.12/py/objint.c000066400000000000000000000366741357706137100161230ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/parsenum.h" #include "py/smallint.h" #include "py/objint.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/binary.h" #if MICROPY_PY_BUILTINS_FLOAT #include #endif // This dispatcher function is expected to be independent of the implementation of long int STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 2, false); switch (n_args) { case 0: return MP_OBJ_NEW_SMALL_INT(0); case 1: if (mp_obj_is_int(args[0])) { // already an int (small or long), just return it return args[0]; } else if (mp_obj_is_str_or_bytes(args[0])) { // a string, parse it size_t l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, 0, NULL); #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_float(args[0])) { return mp_obj_new_int_from_float(mp_obj_float_get(args[0])); #endif } else { return mp_unary_op(MP_UNARY_OP_INT, args[0]); } case 2: default: { // should be a string, parse it size_t l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL); } } } #if MICROPY_PY_BUILTINS_FLOAT typedef enum { MP_FP_CLASS_FIT_SMALLINT, MP_FP_CLASS_FIT_LONGINT, MP_FP_CLASS_OVERFLOW } mp_fp_as_int_class_t; STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) { union { mp_float_t f; #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT uint32_t i; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE uint32_t i[2]; #endif } u = {val}; uint32_t e; #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT e = u.i; #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE e = u.i[MP_ENDIANNESS_LITTLE]; #endif #define MP_FLOAT_SIGN_SHIFT_I32 ((MP_FLOAT_FRAC_BITS + MP_FLOAT_EXP_BITS) % 32) #define MP_FLOAT_EXP_SHIFT_I32 (MP_FLOAT_FRAC_BITS % 32) if (e & (1U << MP_FLOAT_SIGN_SHIFT_I32)) { #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE e |= u.i[MP_ENDIANNESS_BIG] != 0; #endif if ((e & ~(1 << MP_FLOAT_SIGN_SHIFT_I32)) == 0) { // handle case of -0 (when sign is set but rest of bits are zero) e = 0; } else { e += ((1 << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32; } } else { e &= ~((1 << MP_FLOAT_EXP_SHIFT_I32) - 1); } // 8 * sizeof(uintptr_t) counts the number of bits for a small int // TODO provide a way to configure this properly if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 3) << MP_FLOAT_EXP_SHIFT_I32)) { return MP_FP_CLASS_FIT_SMALLINT; } #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG if (e <= (((sizeof(long long) * BITS_PER_BYTE) + MP_FLOAT_EXP_BIAS - 2) << MP_FLOAT_EXP_SHIFT_I32)) { return MP_FP_CLASS_FIT_LONGINT; } #endif #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ return MP_FP_CLASS_FIT_LONGINT; #else return MP_FP_CLASS_OVERFLOW; #endif } #undef MP_FLOAT_SIGN_SHIFT_I32 #undef MP_FLOAT_EXP_SHIFT_I32 mp_obj_t mp_obj_new_int_from_float(mp_float_t val) { int cl = fpclassify(val); if (cl == FP_INFINITE) { mp_raise_msg(&mp_type_OverflowError, "can't convert inf to int"); } else if (cl == FP_NAN) { mp_raise_ValueError("can't convert NaN to int"); } else { mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val); if (icl == MP_FP_CLASS_FIT_SMALLINT) { return MP_OBJ_NEW_SMALL_INT((mp_int_t)val); #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ } else { mp_obj_int_t *o = mp_obj_int_new_mpz(); mpz_set_from_float(&o->mpz, val); return MP_OBJ_FROM_PTR(o); } #else #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG } else if (icl == MP_FP_CLASS_FIT_LONGINT) { return mp_obj_new_int_from_ll((long long)val); #endif } else { mp_raise_ValueError("float too big"); } #endif } } #endif #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG typedef mp_longint_impl_t fmt_int_t; typedef unsigned long long fmt_uint_t; #else typedef mp_int_t fmt_int_t; typedef mp_uint_t fmt_uint_t; #endif void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; // The size of this buffer is rather arbitrary. If it's not large // enough, a dynamic one will be allocated. char stack_buf[sizeof(fmt_int_t) * 4]; char *buf = stack_buf; size_t buf_size = sizeof(stack_buf); size_t fmt_size; char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0'); mp_print_str(print, str); if (buf != stack_buf) { m_del(char, buf, buf_size); } } STATIC const uint8_t log_base2_floor[] = { 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, /* if needed, these are the values for higher bases 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5 */ }; size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma) { assert(2 <= base && base <= 16); size_t num_digits = num_bits / log_base2_floor[base - 1] + 1; size_t num_commas = comma ? num_digits / 3 : 0; size_t prefix_len = prefix ? strlen(prefix) : 0; return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte } // This routine expects you to pass in a buffer and size (in *buf and *buf_size). // If, for some reason, this buffer is too small, then it will allocate a // buffer and return the allocated buffer and size in *buf and *buf_size. It // is the callers responsibility to free this allocated buffer. // // The resulting formatted string will be returned from this function and the // formatted size will be in *fmt_size. char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { fmt_int_t num; #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE // Only have small ints; get the integer value to format. num = MP_OBJ_SMALL_INT_VALUE(self_in); #else if (mp_obj_is_small_int(self_in)) { // A small int; get the integer value to format. num = MP_OBJ_SMALL_INT_VALUE(self_in); } else { assert(mp_obj_is_type(self_in, &mp_type_int)); // Not a small int. #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG const mp_obj_int_t *self = self_in; // Get the value to format; mp_obj_get_int truncates to mp_int_t. num = self->val; #else // Delegate to the implementation for the long int. return mp_obj_int_formatted_impl(buf, buf_size, fmt_size, self_in, base, prefix, base_char, comma); #endif } #endif char sign = '\0'; if (num < 0) { num = -num; sign = '-'; } size_t needed_size = mp_int_format_size(sizeof(fmt_int_t) * 8, base, prefix, comma); if (needed_size > *buf_size) { *buf = m_new(char, needed_size); *buf_size = needed_size; } char *str = *buf; char *b = str + needed_size; *(--b) = '\0'; char *last_comma = b; if (num == 0) { *(--b) = '0'; } else { do { // The cast to fmt_uint_t is because num is positive and we want unsigned arithmetic int c = (fmt_uint_t)num % base; num = (fmt_uint_t)num / base; if (c >= 10) { c += base_char - 10; } else { c += '0'; } *(--b) = c; if (comma && num != 0 && b > str && (last_comma - b) == 3) { *(--b) = comma; last_comma = b; } } while (b > str && num != 0); } if (prefix) { size_t prefix_len = strlen(prefix); char *p = b - prefix_len; if (p > str) { b = p; while (*prefix) { *p++ = *prefix++; } } } if (sign && b > str) { *(--b) = sign; } *fmt_size = *buf + needed_size - b - 1; return b; } #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE int mp_obj_int_sign(mp_obj_t self_in) { mp_int_t val = mp_obj_get_int(self_in); if (val < 0) { return -1; } else if (val > 0) { return 1; } else { return 0; } } // This is called for operations on SMALL_INT that are not handled by mp_unary_op mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { return MP_OBJ_NULL; // op not supported } // This is called for operations on SMALL_INT that are not handled by mp_binary_op mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in); } // This is called only with strings whose value doesn't fit in SMALL_INT mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) { mp_raise_msg(&mp_type_OverflowError, "long int not supported in this build"); return mp_const_none; } // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT) mp_obj_t mp_obj_new_int_from_ll(long long val) { mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT) mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) { mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) { // SMALL_INT accepts only signed numbers, so make sure the input // value fits completely in the small-int positive range. if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) { return MP_OBJ_NEW_SMALL_INT(value); } mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } mp_obj_t mp_obj_new_int(mp_int_t value) { if (MP_SMALL_INT_FITS(value)) { return MP_OBJ_NEW_SMALL_INT(value); } mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) { return MP_OBJ_SMALL_INT_VALUE(self_in); } mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { return MP_OBJ_SMALL_INT_VALUE(self_in); } #endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE // This dispatcher function is expected to be independent of the implementation of long int // It handles the extra cases for integer-like arithmetic mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { if (rhs_in == mp_const_false) { // false acts as 0 return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(0)); } else if (rhs_in == mp_const_true) { // true acts as 0 return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(1)); } else if (op == MP_BINARY_OP_MULTIPLY) { if (mp_obj_is_str_or_bytes(rhs_in) || mp_obj_is_type(rhs_in, &mp_type_tuple) || mp_obj_is_type(rhs_in, &mp_type_list)) { // multiply is commutative for these types, so delegate to them return mp_binary_op(op, rhs_in, lhs_in); } } return MP_OBJ_NULL; // op not supported } // this is a classmethod STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) { // TODO: Support signed param (assumes signed=False at the moment) (void)n_args; // get the buffer info mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); const byte* buf = (const byte*)bufinfo.buf; int delta = 1; if (args[2] == MP_OBJ_NEW_QSTR(MP_QSTR_little)) { buf += bufinfo.len - 1; delta = -1; } mp_uint_t value = 0; size_t len = bufinfo.len; for (; len--; buf += delta) { #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE if (value > (MP_SMALL_INT_MAX >> 8)) { // Result will overflow a small-int so construct a big-int return mp_obj_int_from_bytes_impl(args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little), bufinfo.len, bufinfo.buf); } #endif value = (value << 8) | *buf; } return mp_obj_new_int_from_uint(value); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 3, 4, int_from_bytes); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, MP_ROM_PTR(&int_from_bytes_fun_obj)); STATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *args) { // TODO: Support signed param (assumes signed=False) (void)n_args; mp_int_t len = mp_obj_get_int(args[1]); if (len < 0) { mp_raise_ValueError(NULL); } bool big_endian = args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little); vstr_t vstr; vstr_init_len(&vstr, len); byte *data = (byte*)vstr.buf; memset(data, 0, len); #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE if (!mp_obj_is_small_int(args[0])) { mp_obj_int_to_bytes_impl(args[0], big_endian, len, data); } else #endif { mp_int_t val = MP_OBJ_SMALL_INT_VALUE(args[0]); size_t l = MIN((size_t)len, sizeof(val)); mp_binary_set_int(l, big_endian, data + (big_endian ? (len - l) : 0), val); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_to_bytes_obj, 3, 4, int_to_bytes); STATIC const mp_rom_map_elem_t int_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_from_bytes), MP_ROM_PTR(&int_from_bytes_obj) }, { MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) }, }; STATIC MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table); const mp_obj_type_t mp_type_int = { { &mp_type_type }, .name = MP_QSTR_int, .print = mp_obj_int_print, .make_new = mp_obj_int_make_new, .unary_op = mp_obj_int_unary_op, .binary_op = mp_obj_int_binary_op, .locals_dict = (mp_obj_dict_t*)&int_locals_dict, }; micropython-1.12/py/objint.h000066400000000000000000000055621357706137100161200ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJINT_H #define MICROPY_INCLUDED_PY_OBJINT_H #include "py/mpz.h" #include "py/obj.h" typedef struct _mp_obj_int_t { mp_obj_base_t base; #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG mp_longint_impl_t val; #elif MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ mpz_t mpz; #endif } mp_obj_int_t; extern const mp_obj_int_t mp_maxsize_obj; #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in); #endif size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma); mp_obj_int_t *mp_obj_int_new_mpz(void); void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma); char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma); mp_int_t mp_obj_int_hash(mp_obj_t self_in); mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf); void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf); int mp_obj_int_sign(mp_obj_t self_in); mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in); mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus); #endif // MICROPY_INCLUDED_PY_OBJINT_H micropython-1.12/py/objint_longlong.c000066400000000000000000000223301357706137100200020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/smallint.h" #include "py/objint.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FLOAT #include #endif #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG #if MICROPY_PY_SYS_MAXSIZE // Export value for sys.maxsize const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX}; #endif mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) { int delta = 1; if (!big_endian) { buf += len - 1; delta = -1; } mp_longint_impl_t value = 0; for (; len--; buf += delta) { value = (value << 8) | *buf; } return mp_obj_new_int_from_ll(value); } void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { assert(mp_obj_is_type(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; long long val = self->val; if (big_endian) { byte *b = buf + len; while (b > buf) { *--b = val; val >>= 8; } } else { for (; len > 0; --len) { *buf++ = val; val >>= 8; } } } int mp_obj_int_sign(mp_obj_t self_in) { mp_longint_impl_t val; if (mp_obj_is_small_int(self_in)) { val = MP_OBJ_SMALL_INT_VALUE(self_in); } else { mp_obj_int_t *self = self_in; val = self->val; } if (val < 0) { return -1; } else if (val > 0) { return 1; } else { return 0; } } mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_int_t *o = o_in; switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->val != 0); // truncate value to fit in mp_int_t, which gives the same hash as // small int if the value fits without truncation case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_int_t)o->val); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_int_from_ll(-o->val); case MP_UNARY_OP_INVERT: return mp_obj_new_int_from_ll(~o->val); case MP_UNARY_OP_ABS: { mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in); if (self->val >= 0) { return o_in; } self = mp_obj_new_int_from_ll(self->val); // TODO could overflow long long self->val = -self->val; return MP_OBJ_FROM_PTR(self); } default: return MP_OBJ_NULL; // op not supported } } mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { long long lhs_val; long long rhs_val; if (mp_obj_is_small_int(lhs_in)) { lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in); } else { assert(mp_obj_is_type(lhs_in, &mp_type_int)); lhs_val = ((mp_obj_int_t*)lhs_in)->val; } if (mp_obj_is_small_int(rhs_in)) { rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in); } else if (mp_obj_is_type(rhs_in, &mp_type_int)) { rhs_val = ((mp_obj_int_t*)rhs_in)->val; } else { // delegate to generic function to check for extra cases return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in); } switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: return mp_obj_new_int_from_ll(lhs_val + rhs_val); case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: return mp_obj_new_int_from_ll(lhs_val - rhs_val); case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: return mp_obj_new_int_from_ll(lhs_val * rhs_val); case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { goto zero_division; } return mp_obj_new_int_from_ll(lhs_val / rhs_val); case MP_BINARY_OP_MODULO: case MP_BINARY_OP_INPLACE_MODULO: if (rhs_val == 0) { goto zero_division; } return mp_obj_new_int_from_ll(lhs_val % rhs_val); case MP_BINARY_OP_AND: case MP_BINARY_OP_INPLACE_AND: return mp_obj_new_int_from_ll(lhs_val & rhs_val); case MP_BINARY_OP_OR: case MP_BINARY_OP_INPLACE_OR: return mp_obj_new_int_from_ll(lhs_val | rhs_val); case MP_BINARY_OP_XOR: case MP_BINARY_OP_INPLACE_XOR: return mp_obj_new_int_from_ll(lhs_val ^ rhs_val); case MP_BINARY_OP_LSHIFT: case MP_BINARY_OP_INPLACE_LSHIFT: return mp_obj_new_int_from_ll(lhs_val << (int)rhs_val); case MP_BINARY_OP_RSHIFT: case MP_BINARY_OP_INPLACE_RSHIFT: return mp_obj_new_int_from_ll(lhs_val >> (int)rhs_val); case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: { if (rhs_val < 0) { #if MICROPY_PY_BUILTINS_FLOAT return mp_obj_float_binary_op(op, lhs_val, rhs_in); #else mp_raise_ValueError("negative power with no float support"); #endif } long long ans = 1; while (rhs_val > 0) { if (rhs_val & 1) { ans *= lhs_val; } if (rhs_val == 1) { break; } rhs_val /= 2; lhs_val *= lhs_val; } return mp_obj_new_int_from_ll(ans); } case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); case MP_BINARY_OP_EQUAL: return mp_obj_new_bool(lhs_val == rhs_val); default: return MP_OBJ_NULL; // op not supported } zero_division: mp_raise_msg(&mp_type_ZeroDivisionError, "divide by zero"); } mp_obj_t mp_obj_new_int(mp_int_t value) { if (MP_SMALL_INT_FITS(value)) { return MP_OBJ_NEW_SMALL_INT(value); } return mp_obj_new_int_from_ll(value); } mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) { // SMALL_INT accepts only signed numbers, so make sure the input // value fits completely in the small-int positive range. if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) { return MP_OBJ_NEW_SMALL_INT(value); } return mp_obj_new_int_from_ll(value); } mp_obj_t mp_obj_new_int_from_ll(long long val) { mp_obj_int_t *o = m_new_obj(mp_obj_int_t); o->base.type = &mp_type_int; o->val = val; return o; } mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) { // TODO raise an exception if the unsigned long long won't fit if (val >> (sizeof(unsigned long long) * 8 - 1) != 0) { mp_raise_msg(&mp_type_OverflowError, "ulonglong too large"); } mp_obj_int_t *o = m_new_obj(mp_obj_int_t); o->base.type = &mp_type_int; o->val = val; return o; } mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) { // TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated // TODO check overflow mp_obj_int_t *o = m_new_obj(mp_obj_int_t); o->base.type = &mp_type_int; char *endptr; o->val = strtoll(*str, &endptr, base); *str = endptr; return o; } mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) { if (mp_obj_is_small_int(self_in)) { return MP_OBJ_SMALL_INT_VALUE(self_in); } else { const mp_obj_int_t *self = self_in; return self->val; } } mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { // TODO: Check overflow return mp_obj_int_get_truncated(self_in); } #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; return self->val; } #endif #endif micropython-1.12/py/objint_mpz.c000066400000000000000000000353151357706137100170000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/parsenumbase.h" #include "py/smallint.h" #include "py/objint.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_FLOAT #include #endif #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ #if MICROPY_PY_SYS_MAXSIZE // Export value for sys.maxsize #define DIG_MASK ((MPZ_LONG_1 << MPZ_DIG_SIZE) - 1) STATIC const mpz_dig_t maxsize_dig[] = { #define NUM_DIG 1 (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) & DIG_MASK, #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) > DIG_MASK #undef NUM_DIG #define NUM_DIG 2 (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 1) & DIG_MASK, #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 1) > DIG_MASK #undef NUM_DIG #define NUM_DIG 3 (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 2) & DIG_MASK, #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 2) > DIG_MASK #undef NUM_DIG #define NUM_DIG 4 (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 3) & DIG_MASK, #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 3) > DIG_MASK #error cannot encode MP_SSIZE_MAX as mpz #endif #endif #endif #endif }; const mp_obj_int_t mp_maxsize_obj = { {&mp_type_int}, {.fixed_dig = 1, .len = NUM_DIG, .alloc = NUM_DIG, .dig = (mpz_dig_t*)maxsize_dig} }; #undef DIG_MASK #undef NUM_DIG #endif mp_obj_int_t *mp_obj_int_new_mpz(void) { mp_obj_int_t *o = m_new_obj(mp_obj_int_t); o->base.type = &mp_type_int; mpz_init_zero(&o->mpz); return o; } // This routine expects you to pass in a buffer and size (in *buf and buf_size). // If, for some reason, this buffer is too small, then it will allocate a // buffer and return the allocated buffer and size in *buf and *buf_size. It // is the callers responsibility to free this allocated buffer. // // The resulting formatted string will be returned from this function and the // formatted size will be in *fmt_size. // // This particular routine should only be called for the mpz representation of the int. char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { assert(mp_obj_is_type(self_in, &mp_type_int)); const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); size_t needed_size = mp_int_format_size(mpz_max_num_bits(&self->mpz), base, prefix, comma); if (needed_size > *buf_size) { *buf = m_new(char, needed_size); *buf_size = needed_size; } char *str = *buf; *fmt_size = mpz_as_str_inpl(&self->mpz, base, prefix, base_char, comma, str); return str; } mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) { mp_obj_int_t *o = mp_obj_int_new_mpz(); mpz_set_from_bytes(&o->mpz, big_endian, len, buf); return MP_OBJ_FROM_PTR(o); } void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { assert(mp_obj_is_type(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); memset(buf, 0, len); mpz_as_bytes(&self->mpz, big_endian, len, buf); } int mp_obj_int_sign(mp_obj_t self_in) { if (mp_obj_is_small_int(self_in)) { mp_int_t val = MP_OBJ_SMALL_INT_VALUE(self_in); if (val < 0) { return -1; } else if (val > 0) { return 1; } else { return 0; } } mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); if (self->mpz.len == 0) { return 0; } else if (self->mpz.neg == 0) { return 1; } else { return -1; } } mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_int_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(!mpz_is_zero(&o->mpz)); case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mpz_hash(&o->mpz)); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_neg_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); } case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_not_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); } case MP_UNARY_OP_ABS: { mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in); if (self->mpz.neg == 0) { return o_in; } mp_obj_int_t *self2 = mp_obj_int_new_mpz(); mpz_abs_inpl(&self2->mpz, &self->mpz); return MP_OBJ_FROM_PTR(self2); } default: return MP_OBJ_NULL; // op not supported } } mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { const mpz_t *zlhs; const mpz_t *zrhs; mpz_t z_int; mpz_dig_t z_int_dig[MPZ_NUM_DIG_FOR_INT]; // lhs could be a small int (eg small-int + mpz) if (mp_obj_is_small_int(lhs_in)) { mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(lhs_in)); zlhs = &z_int; } else { assert(mp_obj_is_type(lhs_in, &mp_type_int)); zlhs = &((mp_obj_int_t*)MP_OBJ_TO_PTR(lhs_in))->mpz; } // if rhs is small int, then lhs was not (otherwise mp_binary_op handles it) if (mp_obj_is_small_int(rhs_in)) { mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(rhs_in)); zrhs = &z_int; } else if (mp_obj_is_type(rhs_in, &mp_type_int)) { zrhs = &((mp_obj_int_t*)MP_OBJ_TO_PTR(rhs_in))->mpz; #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_float(rhs_in)) { return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in); #if MICROPY_PY_BUILTINS_COMPLEX } else if (mp_obj_is_type(rhs_in, &mp_type_complex)) { return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in); #endif #endif } else { // delegate to generic function to check for extra cases return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in); } #if MICROPY_PY_BUILTINS_FLOAT if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) { if (mpz_is_zero(zrhs)) { goto zero_division_error; } mp_float_t flhs = mpz_as_float(zlhs); mp_float_t frhs = mpz_as_float(zrhs); return mp_obj_new_float(flhs / frhs); } else #endif if (op >= MP_BINARY_OP_INPLACE_OR && op < MP_BINARY_OP_CONTAINS) { mp_obj_int_t *res = mp_obj_int_new_mpz(); switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: mpz_add_inpl(&res->mpz, zlhs, zrhs); break; case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: mpz_sub_inpl(&res->mpz, zlhs, zrhs); break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: mpz_mul_inpl(&res->mpz, zlhs, zrhs); break; case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: { if (mpz_is_zero(zrhs)) { zero_division_error: mp_raise_msg(&mp_type_ZeroDivisionError, "divide by zero"); } mpz_t rem; mpz_init_zero(&rem); mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs); mpz_deinit(&rem); break; } case MP_BINARY_OP_MODULO: case MP_BINARY_OP_INPLACE_MODULO: { if (mpz_is_zero(zrhs)) { goto zero_division_error; } mpz_t quo; mpz_init_zero(&quo); mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs); mpz_deinit(&quo); break; } case MP_BINARY_OP_AND: case MP_BINARY_OP_INPLACE_AND: mpz_and_inpl(&res->mpz, zlhs, zrhs); break; case MP_BINARY_OP_OR: case MP_BINARY_OP_INPLACE_OR: mpz_or_inpl(&res->mpz, zlhs, zrhs); break; case MP_BINARY_OP_XOR: case MP_BINARY_OP_INPLACE_XOR: mpz_xor_inpl(&res->mpz, zlhs, zrhs); break; case MP_BINARY_OP_LSHIFT: case MP_BINARY_OP_INPLACE_LSHIFT: case MP_BINARY_OP_RSHIFT: case MP_BINARY_OP_INPLACE_RSHIFT: { mp_int_t irhs = mp_obj_int_get_checked(rhs_in); if (irhs < 0) { mp_raise_ValueError("negative shift count"); } if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) { mpz_shl_inpl(&res->mpz, zlhs, irhs); } else { mpz_shr_inpl(&res->mpz, zlhs, irhs); } break; } case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: if (mpz_is_neg(zrhs)) { #if MICROPY_PY_BUILTINS_FLOAT return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in); #else mp_raise_ValueError("negative power with no float support"); #endif } mpz_pow_inpl(&res->mpz, zlhs, zrhs); break; default: { assert(op == MP_BINARY_OP_DIVMOD); if (mpz_is_zero(zrhs)) { goto zero_division_error; } mp_obj_int_t *quo = mp_obj_int_new_mpz(); mpz_divmod_inpl(&quo->mpz, &res->mpz, zlhs, zrhs); mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)}; return mp_obj_new_tuple(2, tuple); } } return MP_OBJ_FROM_PTR(res); } else { int cmp = mpz_cmp(zlhs, zrhs); switch (op) { case MP_BINARY_OP_LESS: return mp_obj_new_bool(cmp < 0); case MP_BINARY_OP_MORE: return mp_obj_new_bool(cmp > 0); case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(cmp <= 0); case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(cmp >= 0); case MP_BINARY_OP_EQUAL: return mp_obj_new_bool(cmp == 0); default: return MP_OBJ_NULL; // op not supported } } } #if MICROPY_PY_BUILTINS_POW3 STATIC mpz_t *mp_mpz_for_int(mp_obj_t arg, mpz_t *temp) { if (mp_obj_is_small_int(arg)) { mpz_init_from_int(temp, MP_OBJ_SMALL_INT_VALUE(arg)); return temp; } else { mp_obj_int_t *arp_p = MP_OBJ_TO_PTR(arg); return &(arp_p->mpz); } } mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) { if (!mp_obj_is_int(base) || !mp_obj_is_int(exponent) || !mp_obj_is_int(modulus)) { mp_raise_TypeError("pow() with 3 arguments requires integers"); } else { mp_obj_t result = mp_obj_new_int_from_ull(0); // Use the _from_ull version as this forces an mpz int mp_obj_int_t *res_p = (mp_obj_int_t *) MP_OBJ_TO_PTR(result); mpz_t l_temp, r_temp, m_temp; mpz_t *lhs = mp_mpz_for_int(base, &l_temp); mpz_t *rhs = mp_mpz_for_int(exponent, &r_temp); mpz_t *mod = mp_mpz_for_int(modulus, &m_temp); mpz_pow3_inpl(&(res_p->mpz), lhs, rhs, mod); if (lhs == &l_temp) { mpz_deinit(lhs); } if (rhs == &r_temp) { mpz_deinit(rhs); } if (mod == &m_temp) { mpz_deinit(mod); } return result; } } #endif mp_obj_t mp_obj_new_int(mp_int_t value) { if (MP_SMALL_INT_FITS(value)) { return MP_OBJ_NEW_SMALL_INT(value); } return mp_obj_new_int_from_ll(value); } mp_obj_t mp_obj_new_int_from_ll(long long val) { mp_obj_int_t *o = mp_obj_int_new_mpz(); mpz_set_from_ll(&o->mpz, val, true); return MP_OBJ_FROM_PTR(o); } mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) { mp_obj_int_t *o = mp_obj_int_new_mpz(); mpz_set_from_ll(&o->mpz, val, false); return MP_OBJ_FROM_PTR(o); } mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) { // SMALL_INT accepts only signed numbers, so make sure the input // value fits completely in the small-int positive range. if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) { return MP_OBJ_NEW_SMALL_INT(value); } return mp_obj_new_int_from_ull(value); } mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) { mp_obj_int_t *o = mp_obj_int_new_mpz(); size_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base); *str += n; return MP_OBJ_FROM_PTR(o); } mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) { if (mp_obj_is_small_int(self_in)) { return MP_OBJ_SMALL_INT_VALUE(self_in); } else { const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); // hash returns actual int value if it fits in mp_int_t return mpz_hash(&self->mpz); } } mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { if (mp_obj_is_small_int(self_in)) { return MP_OBJ_SMALL_INT_VALUE(self_in); } else { const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t value; if (mpz_as_int_checked(&self->mpz, &value)) { return value; } else { // overflow mp_raise_msg(&mp_type_OverflowError, "overflow converting long int to machine word"); } } } #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); return mpz_as_float(&self->mpz); } #endif #endif micropython-1.12/py/objlist.c000066400000000000000000000472541357706137100163000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objlist.h" #include "py/runtime.h" #include "py/stackctrl.h" STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf); STATIC mp_obj_list_t *list_new(size_t n); STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in); STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args); // TODO: Move to mpconfig.h #define LIST_MIN_ALLOC 4 /******************************************************************************/ /* list */ STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_list_t *o = MP_OBJ_TO_PTR(o_in); if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) { kind = PRINT_REPR; } mp_print_str(print, "["); for (size_t i = 0; i < o->len; i++) { if (i > 0) { mp_print_str(print, ", "); } mp_obj_print_helper(print, o->items[i], kind); } mp_print_str(print, "]"); } STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { mp_obj_t iter = mp_getiter(iterable, NULL); mp_obj_t item; while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_obj_list_append(list, item); } return list; } STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: // return a new, empty list return mp_obj_new_list(0, NULL); case 1: default: { // make list from iterable // TODO: optimize list/tuple mp_obj_t list = mp_obj_new_list(0, NULL); return list_extend_from_iter(list, args[0]); } } } STATIC mp_obj_t list_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len); #if MICROPY_PY_SYS_GETSIZEOF case MP_UNARY_OP_SIZEOF: { size_t sz = sizeof(*self) + sizeof(mp_obj_t) * self->alloc; return MP_OBJ_NEW_SMALL_INT(sz); } #endif default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_list_t *o = MP_OBJ_TO_PTR(lhs); switch (op) { case MP_BINARY_OP_ADD: { if (!mp_obj_is_type(rhs, &mp_type_list)) { return MP_OBJ_NULL; // op not supported } mp_obj_list_t *p = MP_OBJ_TO_PTR(rhs); mp_obj_list_t *s = list_new(o->len + p->len); mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t); return MP_OBJ_FROM_PTR(s); } case MP_BINARY_OP_INPLACE_ADD: { list_extend(lhs, rhs); return lhs; } case MP_BINARY_OP_MULTIPLY: { mp_int_t n; if (!mp_obj_get_int_maybe(rhs, &n)) { return MP_OBJ_NULL; // op not supported } if (n < 0) { n = 0; } mp_obj_list_t *s = list_new(o->len * n); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); return MP_OBJ_FROM_PTR(s); } case MP_BINARY_OP_EQUAL: case MP_BINARY_OP_LESS: case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: { if (!mp_obj_is_type(rhs, &mp_type_list)) { if (op == MP_BINARY_OP_EQUAL) { return mp_const_false; } return MP_OBJ_NULL; // op not supported } mp_obj_list_t *another = MP_OBJ_TO_PTR(rhs); bool res = mp_seq_cmp_objs(op, o->items, o->len, another->items, another->len); return mp_obj_new_bool(res); } default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { mp_raise_NotImplementedError(NULL); } mp_int_t len_adj = slice.start - slice.stop; //printf("Len adj: %d\n", len_adj); assert(len_adj <= 0); mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items/*NULL*/, 0, sizeof(*self->items)); // Clear "freed" elements at the end of list mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); self->len += len_adj; return mp_const_none; } #endif mp_obj_t args[2] = {self_in, index}; list_pop(2, args); return mp_const_none; } else if (value == MP_OBJ_SENTINEL) { // load mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { return mp_seq_extract_slice(self->len, self->items, &slice); } mp_obj_list_t *res = list_new(slice.stop - slice.start); mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); return MP_OBJ_FROM_PTR(res); } #endif size_t index_val = mp_get_index(self->base.type, self->len, index, false); return self->items[index_val]; } else { #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); size_t value_len; mp_obj_t *value_items; mp_obj_get_array(value, &value_len, &value_items); mp_bound_slice_t slice_out; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) { mp_raise_NotImplementedError(NULL); } mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start); //printf("Len adj: %d\n", len_adj); if (len_adj > 0) { if (self->len + len_adj > self->alloc) { // TODO: Might optimize memory copies here by checking if block can // be grown inplace or not self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj); self->alloc = self->len + len_adj; } mp_seq_replace_slice_grow_inplace(self->items, self->len, slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items)); } else { mp_seq_replace_slice_no_grow(self->items, self->len, slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items)); // Clear "freed" elements at the end of list mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); // TODO: apply allocation policy re: alloc_size } self->len += len_adj; return mp_const_none; } #endif mp_obj_list_store(self_in, index, value); return mp_const_none; } } STATIC mp_obj_t list_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { return mp_obj_new_list_iterator(o_in, 0, iter_buf); } mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); if (self->len >= self->alloc) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2); self->alloc *= 2; mp_seq_clear(self->items, self->len + 1, self->alloc, sizeof(*self->items)); } self->items[self->len++] = arg; return mp_const_none; // return None, as per CPython } STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); if (mp_obj_is_type(arg_in, &mp_type_list)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_list_t *arg = MP_OBJ_TO_PTR(arg_in); if (self->len + arg->len > self->alloc) { // TODO: use alloc policy for "4" self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4); self->alloc = self->len + arg->len + 4; mp_seq_clear(self->items, self->len + arg->len, self->alloc, sizeof(*self->items)); } memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len); self->len += arg->len; } else { list_extend_from_iter(self_in, arg_in); } return mp_const_none; // return None, as per CPython } STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_type(args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]); if (self->len == 0) { mp_raise_msg(&mp_type_IndexError, "pop from empty list"); } size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); mp_obj_t ret = self->items[index]; self->len -= 1; memmove(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t)); // Clear stale pointer from slot which just got freed to prevent GC issues self->items[self->len] = MP_OBJ_NULL; if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2); self->alloc /= 2; } return ret; } STATIC void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj_t binop_less_result) { MP_STACK_CHECK(); while (head < tail) { mp_obj_t *h = head - 1; mp_obj_t *t = tail; mp_obj_t v = key_fn == MP_OBJ_NULL ? tail[0] : mp_call_function_1(key_fn, tail[0]); // get pivot using key_fn for (;;) { do ++h; while (h < t && mp_binary_op(MP_BINARY_OP_LESS, key_fn == MP_OBJ_NULL ? h[0] : mp_call_function_1(key_fn, h[0]), v) == binop_less_result); do --t; while (h < t && mp_binary_op(MP_BINARY_OP_LESS, v, key_fn == MP_OBJ_NULL ? t[0] : mp_call_function_1(key_fn, t[0])) == binop_less_result); if (h >= t) break; mp_obj_t x = h[0]; h[0] = t[0]; t[0] = x; } mp_obj_t x = h[0]; h[0] = tail[0]; tail[0] = x; // do the smaller recursive call first, to keep stack within O(log(N)) if (t - head < tail - h - 1) { mp_quicksort(head, t, key_fn, binop_less_result); head = h + 1; } else { mp_quicksort(h + 1, tail, key_fn, binop_less_result); tail = t; } } } // TODO Python defines sort to be stable but ours is not mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_reverse, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; // parse args struct { mp_arg_val_t key, reverse; } args; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); mp_check_self(mp_obj_is_type(pos_args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(pos_args[0]); if (self->len > 1) { mp_quicksort(self->items, self->items + self->len - 1, args.key.u_obj == mp_const_none ? MP_OBJ_NULL : args.key.u_obj, args.reverse.u_bool ? mp_const_false : mp_const_true); } return mp_const_none; } STATIC mp_obj_t list_clear(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); self->len = 0; self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC); self->alloc = LIST_MIN_ALLOC; mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items)); return mp_const_none; } STATIC mp_obj_t list_copy(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_list(self->len, self->items); } STATIC mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); return mp_seq_count_obj(self->items, self->len, value); } STATIC mp_obj_t list_index(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_type(args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]); return mp_seq_index_obj(self->items, self->len, n_args, args); } STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); // insert has its own strange index logic mp_int_t index = MP_OBJ_SMALL_INT_VALUE(idx); if (index < 0) { index += self->len; } if (index < 0) { index = 0; } if ((size_t)index > self->len) { index = self->len; } mp_obj_list_append(self_in, mp_const_none); for (mp_int_t i = self->len-1; i > index; i--) { self->items[i] = self->items[i-1]; } self->items[index] = obj; return mp_const_none; } mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); mp_obj_t args[] = {self_in, value}; args[1] = list_index(2, args); list_pop(2, args); return mp_const_none; } STATIC mp_obj_t list_reverse(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t len = self->len; for (mp_int_t i = 0; i < len/2; i++) { mp_obj_t a = self->items[i]; self->items[i] = self->items[len-i-1]; self->items[len-i-1] = a; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append); STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_extend_obj, list_extend); STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_clear_obj, list_clear); STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_copy_obj, list_copy); STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_count_obj, list_count); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_index_obj, 2, 4, list_index); STATIC MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop); STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, mp_obj_list_remove); STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 1, mp_obj_list_sort); STATIC const mp_rom_map_elem_t list_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&list_append_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&list_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&list_copy_obj) }, { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&list_count_obj) }, { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&list_extend_obj) }, { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&list_index_obj) }, { MP_ROM_QSTR(MP_QSTR_insert), MP_ROM_PTR(&list_insert_obj) }, { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&list_pop_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&list_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_reverse), MP_ROM_PTR(&list_reverse_obj) }, { MP_ROM_QSTR(MP_QSTR_sort), MP_ROM_PTR(&list_sort_obj) }, }; STATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table); const mp_obj_type_t mp_type_list = { { &mp_type_type }, .name = MP_QSTR_list, .print = list_print, .make_new = list_make_new, .unary_op = list_unary_op, .binary_op = list_binary_op, .subscr = list_subscr, .getiter = list_getiter, .locals_dict = (mp_obj_dict_t*)&list_locals_dict, }; void mp_obj_list_init(mp_obj_list_t *o, size_t n) { o->base.type = &mp_type_list; o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n; o->len = n; o->items = m_new(mp_obj_t, o->alloc); mp_seq_clear(o->items, n, o->alloc, sizeof(*o->items)); } STATIC mp_obj_list_t *list_new(size_t n) { mp_obj_list_t *o = m_new_obj(mp_obj_list_t); mp_obj_list_init(o, n); return o; } mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items) { mp_obj_list_t *o = list_new(n); if (items != NULL) { for (size_t i = 0; i < n; i++) { o->items[i] = items[i]; } } return MP_OBJ_FROM_PTR(o); } void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); *len = self->len; *items = self->items; } void mp_obj_list_set_len(mp_obj_t self_in, size_t len) { // trust that the caller knows what it's doing // TODO realloc if len got much smaller than alloc mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); self->len = len; } void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); size_t i = mp_get_index(self->base.type, self->len, index, false); self->items[i] = value; } /******************************************************************************/ /* list iterator */ typedef struct _mp_obj_list_it_t { mp_obj_base_t base; mp_fun_1_t iternext; mp_obj_t list; size_t cur; } mp_obj_list_it_t; STATIC mp_obj_t list_it_iternext(mp_obj_t self_in) { mp_obj_list_it_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); if (self->cur < list->len) { mp_obj_t o_out = list->items[self->cur]; self->cur += 1; return o_out; } else { return MP_OBJ_STOP_ITERATION; } } mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_list_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_list_it_t *o = (mp_obj_list_it_t*)iter_buf; o->base.type = &mp_type_polymorph_iter; o->iternext = list_it_iternext; o->list = list; o->cur = cur; return MP_OBJ_FROM_PTR(o); } micropython-1.12/py/objlist.h000066400000000000000000000030161357706137100162710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJLIST_H #define MICROPY_INCLUDED_PY_OBJLIST_H #include "py/obj.h" typedef struct _mp_obj_list_t { mp_obj_base_t base; size_t alloc; size_t len; mp_obj_t *items; } mp_obj_list_t; void mp_obj_list_init(mp_obj_list_t *o, size_t n); #endif // MICROPY_INCLUDED_PY_OBJLIST_H micropython-1.12/py/objmap.c000066400000000000000000000051311357706137100160660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" typedef struct _mp_obj_map_t { mp_obj_base_t base; size_t n_iters; mp_obj_t fun; mp_obj_t iters[]; } mp_obj_map_t; STATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, MP_OBJ_FUN_ARGS_MAX, false); mp_obj_map_t *o = m_new_obj_var(mp_obj_map_t, mp_obj_t, n_args - 1); o->base.type = type; o->n_iters = n_args - 1; o->fun = args[0]; for (size_t i = 0; i < n_args - 1; i++) { o->iters[i] = mp_getiter(args[i + 1], NULL); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t map_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_map)); mp_obj_map_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters); for (size_t i = 0; i < self->n_iters; i++) { mp_obj_t next = mp_iternext(self->iters[i]); if (next == MP_OBJ_STOP_ITERATION) { m_del(mp_obj_t, nextses, self->n_iters); return MP_OBJ_STOP_ITERATION; } nextses[i] = next; } return mp_call_function_n_kw(self->fun, self->n_iters, 0, nextses); } const mp_obj_type_t mp_type_map = { { &mp_type_type }, .name = MP_QSTR_map, .make_new = map_make_new, .getiter = mp_identity_getiter, .iternext = map_iternext, }; micropython-1.12/py/objmodule.c000066400000000000000000000247441357706137100166110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2014-2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/objmodule.h" #include "py/runtime.h" #include "py/builtin.h" #include "genhdr/moduledefs.h" STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); const char *module_name = ""; mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP); if (elem != NULL) { module_name = mp_obj_str_get_str(elem->value); } #if MICROPY_PY___FILE__ // If we store __file__ to imported modules then try to lookup this // symbol to give more information about the module. elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP); if (elem != NULL) { mp_printf(print, "", module_name, mp_obj_str_get_str(elem->value)); return; } #endif mp_printf(print, "", module_name); } STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); if (dest[0] == MP_OBJ_NULL) { // load attribute mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { dest[0] = elem->value; #if MICROPY_MODULE_GETATTR } else if (attr != MP_QSTR___getattr__) { elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___getattr__), MP_MAP_LOOKUP); if (elem != NULL) { dest[0] = mp_call_function_1(elem->value, MP_OBJ_NEW_QSTR(attr)); } #endif } } else { // delete/store attribute mp_obj_dict_t *dict = self->globals; if (dict->map.is_fixed) { #if MICROPY_CAN_OVERRIDE_BUILTINS if (dict == &mp_module_builtins_globals) { if (MP_STATE_VM(mp_module_builtins_override_dict) == NULL) { MP_STATE_VM(mp_module_builtins_override_dict) = MP_OBJ_TO_PTR(mp_obj_new_dict(1)); } dict = MP_STATE_VM(mp_module_builtins_override_dict); } else #endif { // can't delete or store to fixed map return; } } if (dest[1] == MP_OBJ_NULL) { // delete attribute mp_obj_dict_delete(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr)); } else { // store attribute mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr), dest[1]); } dest[0] = MP_OBJ_NULL; // indicate success } } const mp_obj_type_t mp_type_module = { { &mp_type_type }, .name = MP_QSTR_module, .print = module_print, .attr = module_attr, }; mp_obj_t mp_obj_new_module(qstr module_name) { mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; mp_map_elem_t *el = mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); // We could error out if module already exists, but let C extensions // add new members to existing modules. if (el->value != MP_OBJ_NULL) { return el->value; } // create new module object mp_obj_module_t *o = m_new_obj(mp_obj_module_t); o->base.type = &mp_type_module; o->globals = MP_OBJ_TO_PTR(mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE)); // store __name__ entry in the module mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(module_name)); // store the new module into the slot in the global dict holding all modules el->value = MP_OBJ_FROM_PTR(o); // return the new module return MP_OBJ_FROM_PTR(o); } /******************************************************************************/ // Global module table and related functions STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = { { MP_ROM_QSTR(MP_QSTR___main__), MP_ROM_PTR(&mp_module___main__) }, { MP_ROM_QSTR(MP_QSTR_builtins), MP_ROM_PTR(&mp_module_builtins) }, { MP_ROM_QSTR(MP_QSTR_micropython), MP_ROM_PTR(&mp_module_micropython) }, #if MICROPY_PY_IO { MP_ROM_QSTR(MP_QSTR_uio), MP_ROM_PTR(&mp_module_io) }, #endif #if MICROPY_PY_COLLECTIONS { MP_ROM_QSTR(MP_QSTR_ucollections), MP_ROM_PTR(&mp_module_collections) }, #endif #if MICROPY_PY_STRUCT { MP_ROM_QSTR(MP_QSTR_ustruct), MP_ROM_PTR(&mp_module_ustruct) }, #endif #if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_MATH { MP_ROM_QSTR(MP_QSTR_math), MP_ROM_PTR(&mp_module_math) }, #endif #if MICROPY_PY_BUILTINS_COMPLEX && MICROPY_PY_CMATH { MP_ROM_QSTR(MP_QSTR_cmath), MP_ROM_PTR(&mp_module_cmath) }, #endif #endif #if MICROPY_PY_SYS { MP_ROM_QSTR(MP_QSTR_sys), MP_ROM_PTR(&mp_module_sys) }, #endif #if MICROPY_PY_GC && MICROPY_ENABLE_GC { MP_ROM_QSTR(MP_QSTR_gc), MP_ROM_PTR(&mp_module_gc) }, #endif #if MICROPY_PY_THREAD { MP_ROM_QSTR(MP_QSTR__thread), MP_ROM_PTR(&mp_module_thread) }, #endif // extmod modules #if MICROPY_PY_UERRNO { MP_ROM_QSTR(MP_QSTR_uerrno), MP_ROM_PTR(&mp_module_uerrno) }, #endif #if MICROPY_PY_UCTYPES { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) }, #endif #if MICROPY_PY_UZLIB { MP_ROM_QSTR(MP_QSTR_uzlib), MP_ROM_PTR(&mp_module_uzlib) }, #endif #if MICROPY_PY_UJSON { MP_ROM_QSTR(MP_QSTR_ujson), MP_ROM_PTR(&mp_module_ujson) }, #endif #if MICROPY_PY_URE { MP_ROM_QSTR(MP_QSTR_ure), MP_ROM_PTR(&mp_module_ure) }, #endif #if MICROPY_PY_UHEAPQ { MP_ROM_QSTR(MP_QSTR_uheapq), MP_ROM_PTR(&mp_module_uheapq) }, #endif #if MICROPY_PY_UTIMEQ { MP_ROM_QSTR(MP_QSTR_utimeq), MP_ROM_PTR(&mp_module_utimeq) }, #endif #if MICROPY_PY_UHASHLIB { MP_ROM_QSTR(MP_QSTR_uhashlib), MP_ROM_PTR(&mp_module_uhashlib) }, #endif #if MICROPY_PY_UCRYPTOLIB { MP_ROM_QSTR(MP_QSTR_ucryptolib), MP_ROM_PTR(&mp_module_ucryptolib) }, #endif #if MICROPY_PY_UBINASCII { MP_ROM_QSTR(MP_QSTR_ubinascii), MP_ROM_PTR(&mp_module_ubinascii) }, #endif #if MICROPY_PY_URANDOM { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_module_urandom) }, #endif #if MICROPY_PY_USELECT { MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) }, #endif #if MICROPY_PY_USSL { MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) }, #endif #if MICROPY_PY_LWIP { MP_ROM_QSTR(MP_QSTR_lwip), MP_ROM_PTR(&mp_module_lwip) }, #endif #if MICROPY_PY_UWEBSOCKET { MP_ROM_QSTR(MP_QSTR_uwebsocket), MP_ROM_PTR(&mp_module_uwebsocket) }, #endif #if MICROPY_PY_WEBREPL { MP_ROM_QSTR(MP_QSTR__webrepl), MP_ROM_PTR(&mp_module_webrepl) }, #endif #if MICROPY_PY_FRAMEBUF { MP_ROM_QSTR(MP_QSTR_framebuf), MP_ROM_PTR(&mp_module_framebuf) }, #endif #if MICROPY_PY_BTREE { MP_ROM_QSTR(MP_QSTR_btree), MP_ROM_PTR(&mp_module_btree) }, #endif #if MICROPY_PY_BLUETOOTH { MP_ROM_QSTR(MP_QSTR_ubluetooth), MP_ROM_PTR(&mp_module_ubluetooth) }, #endif // extra builtin modules as defined by a port MICROPY_PORT_BUILTIN_MODULES #ifdef MICROPY_REGISTERED_MODULES // builtin modules declared with MP_REGISTER_MODULE() MICROPY_REGISTERED_MODULES #endif }; MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table); // returns MP_OBJ_NULL if not found mp_obj_t mp_module_get(qstr module_name) { mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; // lookup module mp_map_elem_t *el = mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); if (el == NULL) { // module not found, look for builtin module names el = mp_map_lookup((mp_map_t*)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); if (el == NULL) { return MP_OBJ_NULL; } mp_module_call_init(module_name, el->value); } // module found, return it return el->value; } void mp_module_register(qstr qst, mp_obj_t module) { mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module; } #if MICROPY_MODULE_WEAK_LINKS // Search for u"foo" in built-in modules, return MP_OBJ_NULL if not found mp_obj_t mp_module_search_umodule(const char *module_str) { for (size_t i = 0; i < MP_ARRAY_SIZE(mp_builtin_module_table); ++i) { const mp_map_elem_t *entry = (const mp_map_elem_t*)&mp_builtin_module_table[i]; const char *key = qstr_str(MP_OBJ_QSTR_VALUE(entry->key)); if (key[0] == 'u' && strcmp(&key[1], module_str) == 0) { return (mp_obj_t)entry->value; } } return MP_OBJ_NULL; } #endif #if MICROPY_MODULE_BUILTIN_INIT void mp_module_call_init(qstr module_name, mp_obj_t module_obj) { // Look for __init__ and call it if it exists mp_obj_t dest[2]; mp_load_method_maybe(module_obj, MP_QSTR___init__, dest); if (dest[0] != MP_OBJ_NULL) { mp_call_method_n_kw(0, 0, dest); // Register module so __init__ is not called again. // If a module can be referenced by more than one name (eg due to weak links) // then __init__ will still be called for each distinct import, and it's then // up to the particular module to make sure it's __init__ code only runs once. mp_module_register(module_name, module_obj); } } #endif micropython-1.12/py/objmodule.h000066400000000000000000000035161357706137100166100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJMODULE_H #define MICROPY_INCLUDED_PY_OBJMODULE_H #include "py/obj.h" extern const mp_map_t mp_builtin_module_map; extern const mp_map_t mp_builtin_module_weak_links_map; mp_obj_t mp_module_get(qstr module_name); void mp_module_register(qstr qstr, mp_obj_t module); mp_obj_t mp_module_search_umodule(const char *module_str); #if MICROPY_MODULE_BUILTIN_INIT void mp_module_call_init(qstr module_name, mp_obj_t module_obj); #else static inline void mp_module_call_init(qstr module_name, mp_obj_t module_obj) { (void)module_name; (void)module_obj; } #endif #endif // MICROPY_INCLUDED_PY_OBJMODULE_H micropython-1.12/py/objnamedtuple.c000066400000000000000000000163611357706137100174560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/objtuple.h" #include "py/runtime.h" #include "py/objstr.h" #include "py/objnamedtuple.h" #if MICROPY_PY_COLLECTIONS size_t mp_obj_namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) { for (size_t i = 0; i < type->n_fields; i++) { if (type->fields[i] == name) { return i; } } return (size_t)-1; } #if MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT STATIC mp_obj_t namedtuple_asdict(mp_obj_t self_in) { mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in); const qstr *fields = ((mp_obj_namedtuple_type_t*)self->tuple.base.type)->fields; mp_obj_t dict = mp_obj_new_dict(self->tuple.len); //make it an OrderedDict mp_obj_dict_t *dictObj = MP_OBJ_TO_PTR(dict); dictObj->base.type = &mp_type_ordereddict; dictObj->map.is_ordered = 1; for (size_t i = 0; i < self->tuple.len; ++i) { mp_obj_dict_store(dict, MP_OBJ_NEW_QSTR(fields[i]), self->tuple.items[i]); } return dict; } MP_DEFINE_CONST_FUN_OBJ_1(namedtuple_asdict_obj, namedtuple_asdict); #endif STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_namedtuple_t *o = MP_OBJ_TO_PTR(o_in); mp_printf(print, "%q", o->tuple.base.type->name); const qstr *fields = ((mp_obj_namedtuple_type_t*)o->tuple.base.type)->fields; mp_obj_attrtuple_print_helper(print, fields, &o->tuple); } STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT if (attr == MP_QSTR__asdict) { dest[0] = MP_OBJ_FROM_PTR(&namedtuple_asdict_obj); dest[1] = self_in; return; } #endif size_t id = mp_obj_namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr); if (id == (size_t)-1) { return; } dest[0] = self->tuple.items[id]; } else { // delete/store attribute // provide more detailed error message than we'd get by just returning mp_raise_msg(&mp_type_AttributeError, "can't set attribute"); } } STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { const mp_obj_namedtuple_type_t *type = (const mp_obj_namedtuple_type_t*)type_in; size_t num_fields = type->n_fields; if (n_args + n_kw != num_fields) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", num_fields, n_args + n_kw)); } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%q() takes %d positional arguments but %d were given", type->base.name, num_fields, n_args + n_kw)); } } // Create a tuple and set the type to this namedtuple mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_fields, NULL)); tuple->base.type = type_in; // Copy the positional args into the first slots of the namedtuple memcpy(&tuple->items[0], args, sizeof(mp_obj_t) * n_args); // Fill in the remaining slots with the keyword args memset(&tuple->items[n_args], 0, sizeof(mp_obj_t) * n_kw); for (size_t i = n_args; i < n_args + 2 * n_kw; i += 2) { qstr kw = mp_obj_str_get_qstr(args[i]); size_t id = mp_obj_namedtuple_find_field(type, kw); if (id == (size_t)-1) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unexpected keyword argument '%q'", kw)); } } if (tuple->items[id] != MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function got multiple values for argument '%q'", kw)); } } tuple->items[id] = args[i + 1]; } return MP_OBJ_FROM_PTR(tuple); } mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields) { mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields); memset(&o->base, 0, sizeof(o->base)); o->n_fields = n_fields; for (size_t i = 0; i < n_fields; i++) { o->fields[i] = mp_obj_str_get_qstr(fields[i]); } return o; } STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) { mp_obj_namedtuple_type_t *o = mp_obj_new_namedtuple_base(n_fields, fields); o->base.base.type = &mp_type_type; o->base.name = name; o->base.print = namedtuple_print; o->base.make_new = namedtuple_make_new; o->base.unary_op = mp_obj_tuple_unary_op; o->base.binary_op = mp_obj_tuple_binary_op; o->base.attr = namedtuple_attr; o->base.subscr = mp_obj_tuple_subscr; o->base.getiter = mp_obj_tuple_getiter; o->base.parent = &mp_type_tuple; return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) { qstr name = mp_obj_str_get_qstr(name_in); size_t n_fields; mp_obj_t *fields; #if MICROPY_CPYTHON_COMPAT if (mp_obj_is_str(fields_in)) { fields_in = mp_obj_str_split(1, &fields_in); } #endif mp_obj_get_array(fields_in, &n_fields, &fields); return mp_obj_new_namedtuple_type(name, n_fields, fields); } MP_DEFINE_CONST_FUN_OBJ_2(mp_namedtuple_obj, new_namedtuple_type); #endif // MICROPY_PY_COLLECTIONS micropython-1.12/py/objnamedtuple.h000066400000000000000000000033761357706137100174650ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H #define MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H #include "py/objtuple.h" typedef struct _mp_obj_namedtuple_type_t { mp_obj_type_t base; size_t n_fields; qstr fields[]; } mp_obj_namedtuple_type_t; typedef struct _mp_obj_namedtuple_t { mp_obj_tuple_t tuple; } mp_obj_namedtuple_t; size_t mp_obj_namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name); mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields); #endif // MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H micropython-1.12/py/objnone.c000066400000000000000000000034421357706137100162530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" typedef struct _mp_obj_none_t { mp_obj_base_t base; } mp_obj_none_t; STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)self_in; if (MICROPY_PY_UJSON && kind == PRINT_JSON) { mp_print_str(print, "null"); } else { mp_print_str(print, "None"); } } const mp_obj_type_t mp_type_NoneType = { { &mp_type_type }, .name = MP_QSTR_NoneType, .print = none_print, .unary_op = mp_generic_unary_op, }; const mp_obj_none_t mp_const_none_obj = {{&mp_type_NoneType}}; micropython-1.12/py/objobject.c000066400000000000000000000062771357706137100165730ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/objtype.h" #include "py/runtime.h" typedef struct _mp_obj_object_t { mp_obj_base_t base; } mp_obj_object_t; STATIC mp_obj_t object_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)args; mp_arg_check_num(n_args, n_kw, 0, 0, false); mp_obj_object_t *o = m_new_obj(mp_obj_object_t); o->base.type = type; return MP_OBJ_FROM_PTR(o); } #if MICROPY_CPYTHON_COMPAT STATIC mp_obj_t object___init__(mp_obj_t self) { (void)self; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__); STATIC mp_obj_t object___new__(mp_obj_t cls) { if (!mp_obj_is_type(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) { mp_raise_TypeError("__new__ arg must be a user-type"); } // This executes only "__new__" part of instance creation. // TODO: This won't work well for classes with native bases. // TODO: This is a hack, should be resolved along the lines of // https://github.com/micropython/micropython/issues/606#issuecomment-43685883 const mp_obj_type_t *native_base; return MP_OBJ_FROM_PTR(mp_obj_new_instance(MP_OBJ_TO_PTR(cls), &native_base)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object___new___fun_obj)); STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&object___init___obj) }, #endif #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR___new__), MP_ROM_PTR(&object___new___obj) }, #endif }; STATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table); #endif const mp_obj_type_t mp_type_object = { { &mp_type_type }, .name = MP_QSTR_object, .make_new = object_make_new, #if MICROPY_CPYTHON_COMPAT .locals_dict = (mp_obj_dict_t*)&object_locals_dict, #endif }; micropython-1.12/py/objpolyiter.c000066400000000000000000000040771357706137100171700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" // This is universal iterator type which calls "iternext" method stored in // particular object instance. (So, each instance of this time can have its // own iteration behavior.) Having this type saves to define type objects // for various internal iterator objects. // Any instance should have these 2 fields at the beginning typedef struct _mp_obj_polymorph_iter_t { mp_obj_base_t base; mp_fun_1_t iternext; } mp_obj_polymorph_iter_t; STATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) { mp_obj_polymorph_iter_t *self = MP_OBJ_TO_PTR(self_in); // Redirect call to object instance's iternext method return self->iternext(self_in); } const mp_obj_type_t mp_type_polymorph_iter = { { &mp_type_type }, .name = MP_QSTR_iterator, .getiter = mp_identity_getiter, .iternext = polymorph_it_iternext, }; micropython-1.12/py/objproperty.c000066400000000000000000000101351357706137100171750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_BUILTINS_PROPERTY typedef struct _mp_obj_property_t { mp_obj_base_t base; mp_obj_t proxy[3]; // getter, setter, deleter } mp_obj_property_t; STATIC mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { enum { ARG_fget, ARG_fset, ARG_fdel, ARG_doc }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_doc, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, }; mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); mp_obj_property_t *o = m_new_obj(mp_obj_property_t); o->base.type = type; o->proxy[0] = vals[ARG_fget].u_obj; o->proxy[1] = vals[ARG_fset].u_obj; o->proxy[2] = vals[ARG_fdel].u_obj; // vals[ARG_doc] is silently discarded return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t property_getter(mp_obj_t self_in, mp_obj_t getter) { mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in); p2->proxy[0] = getter; return MP_OBJ_FROM_PTR(p2); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_getter_obj, property_getter); STATIC mp_obj_t property_setter(mp_obj_t self_in, mp_obj_t setter) { mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in); p2->proxy[1] = setter; return MP_OBJ_FROM_PTR(p2); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_setter_obj, property_setter); STATIC mp_obj_t property_deleter(mp_obj_t self_in, mp_obj_t deleter) { mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in); p2->proxy[2] = deleter; return MP_OBJ_FROM_PTR(p2); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_deleter_obj, property_deleter); STATIC const mp_rom_map_elem_t property_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_getter), MP_ROM_PTR(&property_getter_obj) }, { MP_ROM_QSTR(MP_QSTR_setter), MP_ROM_PTR(&property_setter_obj) }, { MP_ROM_QSTR(MP_QSTR_deleter), MP_ROM_PTR(&property_deleter_obj) }, }; STATIC MP_DEFINE_CONST_DICT(property_locals_dict, property_locals_dict_table); const mp_obj_type_t mp_type_property = { { &mp_type_type }, .name = MP_QSTR_property, .make_new = property_make_new, .locals_dict = (mp_obj_dict_t*)&property_locals_dict, }; const mp_obj_t *mp_obj_property_get(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_property)); mp_obj_property_t *self = MP_OBJ_TO_PTR(self_in); return self->proxy; } #endif // MICROPY_PY_BUILTINS_PROPERTY micropython-1.12/py/objrange.c000066400000000000000000000165001357706137100164070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" /******************************************************************************/ /* range iterator */ typedef struct _mp_obj_range_it_t { mp_obj_base_t base; // TODO make these values generic objects or something mp_int_t cur; mp_int_t stop; mp_int_t step; } mp_obj_range_it_t; STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) { mp_obj_range_it_t *o = MP_OBJ_TO_PTR(o_in); if ((o->step > 0 && o->cur < o->stop) || (o->step < 0 && o->cur > o->stop)) { mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(o->cur); o->cur += o->step; return o_out; } else { return MP_OBJ_STOP_ITERATION; } } STATIC const mp_obj_type_t range_it_type = { { &mp_type_type }, .name = MP_QSTR_iterator, .getiter = mp_identity_getiter, .iternext = range_it_iternext, }; STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_range_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_range_it_t *o = (mp_obj_range_it_t*)iter_buf; o->base.type = &range_it_type; o->cur = cur; o->stop = stop; o->step = step; return MP_OBJ_FROM_PTR(o); } /******************************************************************************/ /* range */ typedef struct _mp_obj_range_t { mp_obj_base_t base; // TODO make these values generic objects or something mp_int_t start; mp_int_t stop; mp_int_t step; } mp_obj_range_t; STATIC void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "range(" INT_FMT ", " INT_FMT "", self->start, self->stop); if (self->step == 1) { mp_print_str(print, ")"); } else { mp_printf(print, ", " INT_FMT ")", self->step); } } STATIC mp_obj_t range_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 3, false); mp_obj_range_t *o = m_new_obj(mp_obj_range_t); o->base.type = type; o->start = 0; o->step = 1; if (n_args == 1) { o->stop = mp_obj_get_int(args[0]); } else { o->start = mp_obj_get_int(args[0]); o->stop = mp_obj_get_int(args[1]); if (n_args == 3) { o->step = mp_obj_get_int(args[2]); if (o->step == 0) { mp_raise_ValueError("zero step"); } } } return MP_OBJ_FROM_PTR(o); } STATIC mp_int_t range_len(mp_obj_range_t *self) { // When computing length, need to take into account step!=1 and step<0. mp_int_t len = self->stop - self->start + self->step; if (self->step > 0) { len -= 1; } else { len += 1; } len = len / self->step; if (len < 0) { len = 0; } return len; } STATIC mp_obj_t range_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t len = range_len(self); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len > 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len); default: return MP_OBJ_NULL; // op not supported } } #if MICROPY_PY_BUILTINS_RANGE_BINOP STATIC mp_obj_t range_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { if (!mp_obj_is_type(rhs_in, &mp_type_range) || op != MP_BINARY_OP_EQUAL) { return MP_OBJ_NULL; // op not supported } mp_obj_range_t *lhs = MP_OBJ_TO_PTR(lhs_in); mp_obj_range_t *rhs = MP_OBJ_TO_PTR(rhs_in); mp_int_t lhs_len = range_len(lhs); mp_int_t rhs_len = range_len(rhs); return mp_obj_new_bool( lhs_len == rhs_len && (lhs_len == 0 || (lhs->start == rhs->start && (lhs_len == 1 || lhs->step == rhs->step))) ); } #endif STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_SENTINEL) { // load mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t len = range_len(self); #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_bound_slice_t slice; mp_seq_get_fast_slice_indexes(len, index, &slice); mp_obj_range_t *o = m_new_obj(mp_obj_range_t); o->base.type = &mp_type_range; o->start = self->start + slice.start * self->step; o->stop = self->start + slice.stop * self->step; o->step = slice.step * self->step; if (slice.step < 0) { // Negative slice steps have inclusive stop, so adjust for exclusive o->stop -= self->step; } return MP_OBJ_FROM_PTR(o); } #endif size_t index_val = mp_get_index(self->base.type, len, index, false); return MP_OBJ_NEW_SMALL_INT(self->start + index_val * self->step); } else { return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t range_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in); return mp_obj_new_range_iterator(o->start, o->stop, o->step, iter_buf); } #if MICROPY_PY_BUILTINS_RANGE_ATTRS STATIC void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in); if (attr == MP_QSTR_start) { dest[0] = mp_obj_new_int(o->start); } else if (attr == MP_QSTR_stop) { dest[0] = mp_obj_new_int(o->stop); } else if (attr == MP_QSTR_step) { dest[0] = mp_obj_new_int(o->step); } } #endif const mp_obj_type_t mp_type_range = { { &mp_type_type }, .name = MP_QSTR_range, .print = range_print, .make_new = range_make_new, .unary_op = range_unary_op, #if MICROPY_PY_BUILTINS_RANGE_BINOP .binary_op = range_binary_op, #endif .subscr = range_subscr, .getiter = range_getiter, #if MICROPY_PY_BUILTINS_RANGE_ATTRS .attr = range_attr, #endif }; micropython-1.12/py/objreversed.c000066400000000000000000000055561357706137100171430ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #if MICROPY_PY_BUILTINS_REVERSED typedef struct _mp_obj_reversed_t { mp_obj_base_t base; mp_obj_t seq; // sequence object that we are reversing mp_uint_t cur_index; // current index, plus 1; 0=no more, 1=last one (index 0) } mp_obj_reversed_t; STATIC mp_obj_t reversed_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); // check if __reversed__ exists, and if so delegate to it mp_obj_t dest[2]; mp_load_method_maybe(args[0], MP_QSTR___reversed__, dest); if (dest[0] != MP_OBJ_NULL) { return mp_call_method_n_kw(0, 0, dest); } mp_obj_reversed_t *o = m_new_obj(mp_obj_reversed_t); o->base.type = type; o->seq = args[0]; o->cur_index = mp_obj_get_int(mp_obj_len(args[0])); // start at the end of the sequence return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_reversed)); mp_obj_reversed_t *self = MP_OBJ_TO_PTR(self_in); // "raise" stop iteration if we are at the end (the start) of the sequence if (self->cur_index == 0) { return MP_OBJ_STOP_ITERATION; } // pre-decrement and index sequence self->cur_index -= 1; return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL); } const mp_obj_type_t mp_type_reversed = { { &mp_type_type }, .name = MP_QSTR_reversed, .make_new = reversed_make_new, .getiter = mp_identity_getiter, .iternext = reversed_iternext, }; #endif // MICROPY_PY_BUILTINS_REVERSED micropython-1.12/py/objset.c000066400000000000000000000513261357706137100161130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/runtime.h" #include "py/builtin.h" #if MICROPY_PY_BUILTINS_SET typedef struct _mp_obj_set_t { mp_obj_base_t base; mp_set_t set; } mp_obj_set_t; typedef struct _mp_obj_set_it_t { mp_obj_base_t base; mp_fun_1_t iternext; mp_obj_set_t *set; size_t cur; } mp_obj_set_it_t; STATIC bool is_set_or_frozenset(mp_obj_t o) { return mp_obj_is_type(o, &mp_type_set) #if MICROPY_PY_BUILTINS_FROZENSET || mp_obj_is_type(o, &mp_type_frozenset) #endif ; } // This macro is shorthand for mp_check_self to verify the argument is a set. #define check_set(o) mp_check_self(mp_obj_is_type(o, &mp_type_set)) // This macro is shorthand for mp_check_self to verify the argument is a // set or frozenset for methods that operate on both of these types. #define check_set_or_frozenset(o) mp_check_self(is_set_or_frozenset(o)) STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_BUILTINS_FROZENSET bool is_frozen = mp_obj_is_type(self_in, &mp_type_frozenset); #endif if (self->set.used == 0) { #if MICROPY_PY_BUILTINS_FROZENSET if (is_frozen) { mp_print_str(print, "frozen"); } #endif mp_print_str(print, "set()"); return; } bool first = true; #if MICROPY_PY_BUILTINS_FROZENSET if (is_frozen) { mp_print_str(print, "frozenset("); } #endif mp_print_str(print, "{"); for (size_t i = 0; i < self->set.alloc; i++) { if (mp_set_slot_is_filled(&self->set, i)) { if (!first) { mp_print_str(print, ", "); } first = false; mp_obj_print_helper(print, self->set.table[i], PRINT_REPR); } } mp_print_str(print, "}"); #if MICROPY_PY_BUILTINS_FROZENSET if (is_frozen) { mp_print_str(print, ")"); } #endif } STATIC mp_obj_t set_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: { // create a new, empty set mp_obj_set_t *set = MP_OBJ_TO_PTR(mp_obj_new_set(0, NULL)); // set actual set/frozenset type set->base.type = type; return MP_OBJ_FROM_PTR(set); } case 1: default: { // can only be 0 or 1 arg // 1 argument, an iterable from which we make a new set mp_obj_t set = mp_obj_new_set(0, NULL); mp_obj_t iterable = mp_getiter(args[0], NULL); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { mp_obj_set_store(set, item); } // Set actual set/frozenset type ((mp_obj_set_t*)MP_OBJ_TO_PTR(set))->base.type = type; return set; } } } STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) { mp_obj_set_it_t *self = MP_OBJ_TO_PTR(self_in); size_t max = self->set->set.alloc; mp_set_t *set = &self->set->set; for (size_t i = self->cur; i < max; i++) { if (mp_set_slot_is_filled(set, i)) { self->cur = i + 1; return set->table[i]; } } return MP_OBJ_STOP_ITERATION; } STATIC mp_obj_t set_getiter(mp_obj_t set_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_set_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_set_it_t *o = (mp_obj_set_it_t*)iter_buf; o->base.type = &mp_type_polymorph_iter; o->iternext = set_it_iternext; o->set = (mp_obj_set_t *)MP_OBJ_TO_PTR(set_in); o->cur = 0; return MP_OBJ_FROM_PTR(o); } /******************************************************************************/ /* set methods */ STATIC mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add); STATIC mp_obj_t set_clear(mp_obj_t self_in) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_set_clear(&self->set); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear); STATIC mp_obj_t set_copy(mp_obj_t self_in) { check_set_or_frozenset(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_set_t *other = m_new_obj(mp_obj_set_t); other->base.type = self->base.type; mp_set_init(&other->set, self->set.alloc); other->set.used = self->set.used; memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t)); return MP_OBJ_FROM_PTR(other); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy); STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard); STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) { mp_obj_t self; if (update) { check_set(args[0]); self = args[0]; } else { self = set_copy(args[0]); } for (size_t i = 1; i < n_args; i++) { mp_obj_t other = args[i]; if (self == other) { set_clear(self); } else { mp_set_t *self_set = &((mp_obj_set_t*)MP_OBJ_TO_PTR(self))->set; mp_obj_t iter = mp_getiter(other, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_set_lookup(self_set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND); } } } return self; } STATIC mp_obj_t set_diff(size_t n_args, const mp_obj_t *args) { return set_diff_int(n_args, args, false); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_obj, 1, set_diff); STATIC mp_obj_t set_diff_update(size_t n_args, const mp_obj_t *args) { set_diff_int(n_args, args, true); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_update_obj, 1, set_diff_update); STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) { if (update) { check_set(self_in); } else { check_set_or_frozenset(self_in); } if (self_in == other) { return update ? mp_const_none : set_copy(self_in); } mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_set_t *out = MP_OBJ_TO_PTR(mp_obj_new_set(0, NULL)); mp_obj_t iter = mp_getiter(other, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) { set_add(MP_OBJ_FROM_PTR(out), next); } } if (update) { m_del(mp_obj_t, self->set.table, self->set.alloc); self->set.alloc = out->set.alloc; self->set.used = out->set.used; self->set.table = out->set.table; } return update ? mp_const_none : MP_OBJ_FROM_PTR(out); } STATIC mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) { return set_intersect_int(self_in, other, false); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_obj, set_intersect); STATIC mp_obj_t set_intersect_update(mp_obj_t self_in, mp_obj_t other) { return set_intersect_int(self_in, other, true); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update); STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) { check_set_or_frozenset(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_iter_buf_t iter_buf; mp_obj_t iter = mp_getiter(other, &iter_buf); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) { return mp_const_false; } } return mp_const_true; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_isdisjoint_obj, set_isdisjoint); STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool proper) { mp_obj_set_t *self; bool cleanup_self = false; if (is_set_or_frozenset(self_in)) { self = MP_OBJ_TO_PTR(self_in); } else { self = MP_OBJ_TO_PTR(set_make_new(&mp_type_set, 1, 0, &self_in)); cleanup_self = true; } mp_obj_set_t *other; bool cleanup_other = false; if (is_set_or_frozenset(other_in)) { other = MP_OBJ_TO_PTR(other_in); } else { other = MP_OBJ_TO_PTR(set_make_new(&mp_type_set, 1, 0, &other_in)); cleanup_other = true; } mp_obj_t out = mp_const_true; if (proper && self->set.used == other->set.used) { out = mp_const_false; } else { mp_obj_iter_buf_t iter_buf; mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self), &iter_buf); mp_obj_t next; while ((next = set_it_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) { out = mp_const_false; break; } } } // TODO: Should free objects altogether if (cleanup_self) { set_clear(MP_OBJ_FROM_PTR(self)); } if (cleanup_other) { set_clear(MP_OBJ_FROM_PTR(other)); } return out; } STATIC mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(self_in, other_in, false); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issubset_obj, set_issubset); STATIC mp_obj_t set_issubset_proper(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(self_in, other_in, true); } STATIC mp_obj_t set_issuperset(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(other_in, self_in, false); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issuperset_obj, set_issuperset); STATIC mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(other_in, self_in, true); } STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) { assert(is_set_or_frozenset(other_in)); check_set_or_frozenset(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_set_t *other = MP_OBJ_TO_PTR(other_in); if (self->set.used != other->set.used) { return mp_const_false; } return set_issubset(self_in, other_in); } STATIC mp_obj_t set_pop(mp_obj_t self_in) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t obj = mp_set_remove_first(&self->set); if (obj == MP_OBJ_NULL) { mp_raise_msg(&mp_type_KeyError, "pop from an empty set"); } return obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop); STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, item)); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove); STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) { check_set_or_frozenset(self_in); // can be frozenset due to call from set_symmetric_difference mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t iter = mp_getiter(other_in, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update); STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) { mp_obj_t self_out = set_copy(self_in); set_symmetric_difference_update(self_out, other_in); return self_out; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference); STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) { mp_obj_t iter = mp_getiter(other_in, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } } STATIC mp_obj_t set_update(size_t n_args, const mp_obj_t *args) { check_set(args[0]); for (size_t i = 1; i < n_args; i++) { set_update_int(MP_OBJ_TO_PTR(args[0]), args[i]); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update); STATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) { check_set_or_frozenset(self_in); mp_obj_t self = set_copy(self_in); set_update_int(MP_OBJ_TO_PTR(self), other_in); return self; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union); STATIC mp_obj_t set_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->set.used != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->set.used); #if MICROPY_PY_BUILTINS_FROZENSET case MP_UNARY_OP_HASH: if (mp_obj_is_type(self_in, &mp_type_frozenset)) { // start hash with unique value mp_int_t hash = (mp_int_t)(uintptr_t)&mp_type_frozenset; size_t max = self->set.alloc; mp_set_t *set = &self->set; for (size_t i = 0; i < max; i++) { if (mp_set_slot_is_filled(set, i)) { hash += MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, set->table[i])); } } return MP_OBJ_NEW_SMALL_INT(hash); } #endif default: return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_t args[] = {lhs, rhs}; #if MICROPY_PY_BUILTINS_FROZENSET bool update = mp_obj_is_type(lhs, &mp_type_set); #else bool update = true; #endif if (op != MP_BINARY_OP_CONTAINS && !is_set_or_frozenset(rhs)) { // For all ops except containment the RHS must be a set/frozenset return MP_OBJ_NULL; } switch (op) { case MP_BINARY_OP_OR: return set_union(lhs, rhs); case MP_BINARY_OP_XOR: return set_symmetric_difference(lhs, rhs); case MP_BINARY_OP_AND: return set_intersect(lhs, rhs); case MP_BINARY_OP_SUBTRACT: return set_diff(2, args); case MP_BINARY_OP_INPLACE_OR: if (update) { set_update(2, args); return lhs; } else { return set_union(lhs, rhs); } case MP_BINARY_OP_INPLACE_XOR: if (update) { set_symmetric_difference_update(lhs, rhs); return lhs; } else { return set_symmetric_difference(lhs, rhs); } case MP_BINARY_OP_INPLACE_AND: rhs = set_intersect_int(lhs, rhs, update); if (update) { return lhs; } else { return rhs; } case MP_BINARY_OP_INPLACE_SUBTRACT: return set_diff_int(2, args, update); case MP_BINARY_OP_LESS: return set_issubset_proper(lhs, rhs); case MP_BINARY_OP_MORE: return set_issuperset_proper(lhs, rhs); case MP_BINARY_OP_EQUAL: return set_equal(lhs, rhs); case MP_BINARY_OP_LESS_EQUAL: return set_issubset(lhs, rhs); case MP_BINARY_OP_MORE_EQUAL: return set_issuperset(lhs, rhs); case MP_BINARY_OP_CONTAINS: { mp_obj_set_t *o = MP_OBJ_TO_PTR(lhs); mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP); return mp_obj_new_bool(elem != MP_OBJ_NULL); } default: return MP_OBJ_NULL; // op not supported } } /******************************************************************************/ /* set constructors & public C API */ STATIC const mp_rom_map_elem_t set_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&set_add_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&set_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&set_copy_obj) }, { MP_ROM_QSTR(MP_QSTR_discard), MP_ROM_PTR(&set_discard_obj) }, { MP_ROM_QSTR(MP_QSTR_difference), MP_ROM_PTR(&set_diff_obj) }, { MP_ROM_QSTR(MP_QSTR_difference_update), MP_ROM_PTR(&set_diff_update_obj) }, { MP_ROM_QSTR(MP_QSTR_intersection), MP_ROM_PTR(&set_intersect_obj) }, { MP_ROM_QSTR(MP_QSTR_intersection_update), MP_ROM_PTR(&set_intersect_update_obj) }, { MP_ROM_QSTR(MP_QSTR_isdisjoint), MP_ROM_PTR(&set_isdisjoint_obj) }, { MP_ROM_QSTR(MP_QSTR_issubset), MP_ROM_PTR(&set_issubset_obj) }, { MP_ROM_QSTR(MP_QSTR_issuperset), MP_ROM_PTR(&set_issuperset_obj) }, { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&set_pop_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&set_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_symmetric_difference), MP_ROM_PTR(&set_symmetric_difference_obj) }, { MP_ROM_QSTR(MP_QSTR_symmetric_difference_update), MP_ROM_PTR(&set_symmetric_difference_update_obj) }, { MP_ROM_QSTR(MP_QSTR_union), MP_ROM_PTR(&set_union_obj) }, { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&set_update_obj) }, { MP_ROM_QSTR(MP_QSTR___contains__), MP_ROM_PTR(&mp_op_contains_obj) }, }; STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table); const mp_obj_type_t mp_type_set = { { &mp_type_type }, .name = MP_QSTR_set, .print = set_print, .make_new = set_make_new, .unary_op = set_unary_op, .binary_op = set_binary_op, .getiter = set_getiter, .locals_dict = (mp_obj_dict_t*)&set_locals_dict, }; #if MICROPY_PY_BUILTINS_FROZENSET STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&set_copy_obj) }, { MP_ROM_QSTR(MP_QSTR_difference), MP_ROM_PTR(&set_diff_obj) }, { MP_ROM_QSTR(MP_QSTR_intersection), MP_ROM_PTR(&set_intersect_obj) }, { MP_ROM_QSTR(MP_QSTR_isdisjoint), MP_ROM_PTR(&set_isdisjoint_obj) }, { MP_ROM_QSTR(MP_QSTR_issubset), MP_ROM_PTR(&set_issubset_obj) }, { MP_ROM_QSTR(MP_QSTR_issuperset), MP_ROM_PTR(&set_issuperset_obj) }, { MP_ROM_QSTR(MP_QSTR_symmetric_difference), MP_ROM_PTR(&set_symmetric_difference_obj) }, { MP_ROM_QSTR(MP_QSTR_union), MP_ROM_PTR(&set_union_obj) }, { MP_ROM_QSTR(MP_QSTR___contains__), MP_ROM_PTR(&mp_op_contains_obj) }, }; STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table); const mp_obj_type_t mp_type_frozenset = { { &mp_type_type }, .name = MP_QSTR_frozenset, .print = set_print, .make_new = set_make_new, .unary_op = set_unary_op, .binary_op = set_binary_op, .getiter = set_getiter, .locals_dict = (mp_obj_dict_t*)&frozenset_locals_dict, }; #endif mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) { mp_obj_set_t *o = m_new_obj(mp_obj_set_t); o->base.type = &mp_type_set; mp_set_init(&o->set, n_args); for (size_t i = 0; i < n_args; i++) { mp_set_lookup(&o->set, items[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } return MP_OBJ_FROM_PTR(o); } void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) { mp_check_self(mp_obj_is_type(self_in, &mp_type_set)); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } #endif // MICROPY_PY_BUILTINS_SET micropython-1.12/py/objsingleton.c000066400000000000000000000041161357706137100173150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" /******************************************************************************/ /* singleton objects defined by Python */ typedef struct _mp_obj_singleton_t { mp_obj_base_t base; qstr name; } mp_obj_singleton_t; STATIC void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_singleton_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "%q", self->name); } const mp_obj_type_t mp_type_singleton = { { &mp_type_type }, .name = MP_QSTR_, .print = singleton_print, }; const mp_obj_singleton_t mp_const_ellipsis_obj = {{&mp_type_singleton}, MP_QSTR_Ellipsis}; #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED const mp_obj_singleton_t mp_const_notimplemented_obj = {{&mp_type_singleton}, MP_QSTR_NotImplemented}; #endif micropython-1.12/py/objslice.c000066400000000000000000000062601357706137100164140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/obj.h" /******************************************************************************/ /* slice object */ #if MICROPY_PY_BUILTINS_SLICE typedef struct _mp_obj_slice_t { mp_obj_base_t base; mp_obj_t start; mp_obj_t stop; mp_obj_t step; } mp_obj_slice_t; STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_slice_t *o = MP_OBJ_TO_PTR(o_in); mp_print_str(print, "slice("); mp_obj_print_helper(print, o->start, PRINT_REPR); mp_print_str(print, ", "); mp_obj_print_helper(print, o->stop, PRINT_REPR); mp_print_str(print, ", "); mp_obj_print_helper(print, o->step, PRINT_REPR); mp_print_str(print, ")"); } #if MICROPY_PY_BUILTINS_SLICE_ATTRS STATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in); if (attr == MP_QSTR_start) { dest[0] = self->start; } else if (attr == MP_QSTR_stop) { dest[0] = self->stop; } else if (attr == MP_QSTR_step) { dest[0] = self->step; } } #endif const mp_obj_type_t mp_type_slice = { { &mp_type_type }, .name = MP_QSTR_slice, .print = slice_print, #if MICROPY_PY_BUILTINS_SLICE_ATTRS .attr = slice_attr, #endif }; mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) { mp_obj_slice_t *o = m_new_obj(mp_obj_slice_t); o->base.type = &mp_type_slice; o->start = ostart; o->stop = ostop; o->step = ostep; return MP_OBJ_FROM_PTR(o); } void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step) { assert(mp_obj_is_type(self_in, &mp_type_slice)); mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in); *start = self->start; *stop = self->stop; *step = self->step; } #endif micropython-1.12/py/objstr.c000066400000000000000000002276661357706137100161440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/unicode.h" #include "py/objstr.h" #include "py/objlist.h" #include "py/runtime.h" #include "py/stackctrl.h" #if MICROPY_PY_BUILTINS_STR_OP_MODULO STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict); #endif STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in); /******************************************************************************/ /* str */ void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes) { // this escapes characters, but it will be very slow to print (calling print many times) bool has_single_quote = false; bool has_double_quote = false; for (const byte *s = str_data, *top = str_data + str_len; !has_double_quote && s < top; s++) { if (*s == '\'') { has_single_quote = true; } else if (*s == '"') { has_double_quote = true; } } int quote_char = '\''; if (has_single_quote && !has_double_quote) { quote_char = '"'; } mp_printf(print, "%c", quote_char); for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) { if (*s == quote_char) { mp_printf(print, "\\%c", quote_char); } else if (*s == '\\') { mp_print_str(print, "\\\\"); } else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) { // In strings, anything which is not ascii control character // is printed as is, this includes characters in range 0x80-0xff // (which can be non-Latin letters, etc.) mp_printf(print, "%c", *s); } else if (*s == '\n') { mp_print_str(print, "\\n"); } else if (*s == '\r') { mp_print_str(print, "\\r"); } else if (*s == '\t') { mp_print_str(print, "\\t"); } else { mp_printf(print, "\\x%02x", *s); } } mp_printf(print, "%c", quote_char); } #if MICROPY_PY_UJSON void mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len) { // for JSON spec, see http://www.ietf.org/rfc/rfc4627.txt // if we are given a valid utf8-encoded string, we will print it in a JSON-conforming way mp_print_str(print, "\""); for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) { if (*s == '"' || *s == '\\') { mp_printf(print, "\\%c", *s); } else if (*s >= 32) { // this will handle normal and utf-8 encoded chars mp_printf(print, "%c", *s); } else if (*s == '\n') { mp_print_str(print, "\\n"); } else if (*s == '\r') { mp_print_str(print, "\\r"); } else if (*s == '\t') { mp_print_str(print, "\\t"); } else { // this will handle control chars mp_printf(print, "\\u%04x", *s); } } mp_print_str(print, "\""); } #endif STATIC void str_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { GET_STR_DATA_LEN(self_in, str_data, str_len); #if MICROPY_PY_UJSON if (kind == PRINT_JSON) { mp_str_print_json(print, str_data, str_len); return; } #endif #if !MICROPY_PY_BUILTINS_STR_UNICODE bool is_bytes = mp_obj_is_type(self_in, &mp_type_bytes); #else bool is_bytes = true; #endif if (kind == PRINT_RAW || (!MICROPY_PY_BUILTINS_STR_UNICODE && kind == PRINT_STR && !is_bytes)) { mp_printf(print, "%.*s", str_len, str_data); } else { if (is_bytes) { mp_print_str(print, "b"); } mp_str_print_quoted(print, str_data, str_len, is_bytes); } } mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { #if MICROPY_CPYTHON_COMPAT if (n_kw != 0) { mp_arg_error_unimpl_kw(); } #endif mp_arg_check_num(n_args, n_kw, 0, 3, false); switch (n_args) { case 0: return MP_OBJ_NEW_QSTR(MP_QSTR_); case 1: { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 16, &print); mp_obj_print_helper(&print, args[0], PRINT_STR); return mp_obj_new_str_from_vstr(type, &vstr); } default: // 2 or 3 args // TODO: validate 2nd/3rd args if (mp_obj_is_type(args[0], &mp_type_bytes)) { GET_STR_DATA_LEN(args[0], str_data, str_len); GET_STR_HASH(args[0], str_hash); if (str_hash == 0) { str_hash = qstr_compute_hash(str_data, str_len); } #if MICROPY_PY_BUILTINS_STR_UNICODE_CHECK if (!utf8_check(str_data, str_len)) { mp_raise_msg(&mp_type_UnicodeError, NULL); } #endif // Check if a qstr with this data already exists qstr q = qstr_find_strn((const char*)str_data, str_len); if (q != MP_QSTRnull) { return MP_OBJ_NEW_QSTR(q); } mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_copy(type, NULL, str_len)); o->data = str_data; o->hash = str_hash; return MP_OBJ_FROM_PTR(o); } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); #if MICROPY_PY_BUILTINS_STR_UNICODE_CHECK if (!utf8_check(bufinfo.buf, bufinfo.len)) { mp_raise_msg(&mp_type_UnicodeError, NULL); } #endif return mp_obj_new_str(bufinfo.buf, bufinfo.len); } } } STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; #if MICROPY_CPYTHON_COMPAT if (n_kw != 0) { mp_arg_error_unimpl_kw(); } #else (void)n_kw; #endif if (n_args == 0) { return mp_const_empty_bytes; } if (mp_obj_is_str(args[0])) { if (n_args < 2 || n_args > 3) { goto wrong_args; } GET_STR_DATA_LEN(args[0], str_data, str_len); GET_STR_HASH(args[0], str_hash); if (str_hash == 0) { str_hash = qstr_compute_hash(str_data, str_len); } mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_copy(&mp_type_bytes, NULL, str_len)); o->data = str_data; o->hash = str_hash; return MP_OBJ_FROM_PTR(o); } if (n_args > 1) { goto wrong_args; } if (mp_obj_is_small_int(args[0])) { mp_int_t len = MP_OBJ_SMALL_INT_VALUE(args[0]); if (len < 0) { mp_raise_ValueError(NULL); } vstr_t vstr; vstr_init_len(&vstr, len); memset(vstr.buf, 0, len); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } // check if argument has the buffer protocol mp_buffer_info_t bufinfo; if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) { return mp_obj_new_bytes(bufinfo.buf, bufinfo.len); } vstr_t vstr; // Try to create array of exact len if initializer len is known mp_obj_t len_in = mp_obj_len_maybe(args[0]); if (len_in == MP_OBJ_NULL) { vstr_init(&vstr, 16); } else { mp_int_t len = MP_OBJ_SMALL_INT_VALUE(len_in); vstr_init(&vstr, len); } mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(args[0], &iter_buf); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { mp_int_t val = mp_obj_get_int(item); #if MICROPY_FULL_CHECKS if (val < 0 || val > 255) { mp_raise_ValueError("bytes value out of range"); } #endif vstr_add_byte(&vstr, val); } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); wrong_args: mp_raise_TypeError("wrong number of arguments"); } // like strstr but with specified length and allows \0 bytes // TODO replace with something more efficient/standard const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction) { if (hlen >= nlen) { size_t str_index, str_index_end; if (direction > 0) { str_index = 0; str_index_end = hlen - nlen; } else { str_index = hlen - nlen; str_index_end = 0; } for (;;) { if (memcmp(&haystack[str_index], needle, nlen) == 0) { //found return haystack + str_index; } if (str_index == str_index_end) { //not found break; } str_index += direction; } } return NULL; } // Note: this function is used to check if an object is a str or bytes, which // works because both those types use it as their binary_op method. Revisit // mp_obj_is_str_or_bytes if this fact changes. mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // check for modulo if (op == MP_BINARY_OP_MODULO) { #if MICROPY_PY_BUILTINS_STR_OP_MODULO mp_obj_t *args = &rhs_in; size_t n_args = 1; mp_obj_t dict = MP_OBJ_NULL; if (mp_obj_is_type(rhs_in, &mp_type_tuple)) { // TODO: Support tuple subclasses? mp_obj_tuple_get(rhs_in, &n_args, &args); } else if (mp_obj_is_type(rhs_in, &mp_type_dict)) { dict = rhs_in; } return str_modulo_format(lhs_in, n_args, args, dict); #else return MP_OBJ_NULL; #endif } // from now on we need lhs type and data, so extract them mp_obj_type_t *lhs_type = mp_obj_get_type(lhs_in); GET_STR_DATA_LEN(lhs_in, lhs_data, lhs_len); // check for multiply if (op == MP_BINARY_OP_MULTIPLY) { mp_int_t n; if (!mp_obj_get_int_maybe(rhs_in, &n)) { return MP_OBJ_NULL; // op not supported } if (n <= 0) { if (lhs_type == &mp_type_str) { return MP_OBJ_NEW_QSTR(MP_QSTR_); // empty str } else { return mp_const_empty_bytes; } } vstr_t vstr; vstr_init_len(&vstr, lhs_len * n); mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, vstr.buf); return mp_obj_new_str_from_vstr(lhs_type, &vstr); } // From now on all operations allow: // - str with str // - bytes with bytes // - bytes with bytearray // - bytes with array.array // To do this efficiently we use the buffer protocol to extract the raw // data for the rhs, but only if the lhs is a bytes object. // // NOTE: CPython does not allow comparison between bytes ard array.array // (even if the array is of type 'b'), even though it allows addition of // such types. We are not compatible with this (we do allow comparison // of bytes with anything that has the buffer protocol). It would be // easy to "fix" this with a bit of extra logic below, but it costs code // size and execution time so we don't. const byte *rhs_data; size_t rhs_len; if (lhs_type == mp_obj_get_type(rhs_in)) { GET_STR_DATA_LEN(rhs_in, rhs_data_, rhs_len_); rhs_data = rhs_data_; rhs_len = rhs_len_; } else if (lhs_type == &mp_type_bytes) { mp_buffer_info_t bufinfo; if (!mp_get_buffer(rhs_in, &bufinfo, MP_BUFFER_READ)) { return MP_OBJ_NULL; // op not supported } rhs_data = bufinfo.buf; rhs_len = bufinfo.len; } else { // LHS is str and RHS has an incompatible type // (except if operation is EQUAL, but that's handled by mp_obj_equal) bad_implicit_conversion(rhs_in); } switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: { if (lhs_len == 0 && mp_obj_get_type(rhs_in) == lhs_type) { return rhs_in; } if (rhs_len == 0) { return lhs_in; } vstr_t vstr; vstr_init_len(&vstr, lhs_len + rhs_len); memcpy(vstr.buf, lhs_data, lhs_len); memcpy(vstr.buf + lhs_len, rhs_data, rhs_len); return mp_obj_new_str_from_vstr(lhs_type, &vstr); } case MP_BINARY_OP_CONTAINS: return mp_obj_new_bool(find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len, 1) != NULL); //case MP_BINARY_OP_NOT_EQUAL: // This is never passed here case MP_BINARY_OP_EQUAL: // This will be passed only for bytes, str is dealt with in mp_obj_equal() case MP_BINARY_OP_LESS: case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs_data, lhs_len, rhs_data, rhs_len)); default: return MP_OBJ_NULL; // op not supported } } #if !MICROPY_PY_BUILTINS_STR_UNICODE // objstrunicode defines own version const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len, mp_obj_t index, bool is_slice) { size_t index_val = mp_get_index(type, self_len, index, is_slice); return self_data + index_val; } #endif // This is used for both bytes and 8-bit strings. This is not used for unicode strings. STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(self_in); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { // load #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self_len, index, &slice)) { mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported"); } return mp_obj_new_str_of_type(type, self_data + slice.start, slice.stop - slice.start); } #endif size_t index_val = mp_get_index(type, self_len, index, false); // If we have unicode enabled the type will always be bytes, so take the short cut. if (MICROPY_PY_BUILTINS_STR_UNICODE || type == &mp_type_bytes) { return MP_OBJ_NEW_SMALL_INT(self_data[index_val]); } else { return mp_obj_new_str_via_qstr((char*)&self_data[index_val], 1); } } else { return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { mp_check_self(mp_obj_is_str_or_bytes(self_in)); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); // get separation string GET_STR_DATA_LEN(self_in, sep_str, sep_len); // process args size_t seq_len; mp_obj_t *seq_items; if (!mp_obj_is_type(arg, &mp_type_list) && !mp_obj_is_type(arg, &mp_type_tuple)) { // arg is not a list nor a tuple, try to convert it to a list // TODO: Try to optimize? arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg); } mp_obj_get_array(arg, &seq_len, &seq_items); // count required length size_t required_len = 0; for (size_t i = 0; i < seq_len; i++) { if (mp_obj_get_type(seq_items[i]) != self_type) { mp_raise_TypeError( "join expects a list of str/bytes objects consistent with self object"); } if (i > 0) { required_len += sep_len; } GET_STR_LEN(seq_items[i], l); required_len += l; } // make joined string vstr_t vstr; vstr_init_len(&vstr, required_len); byte *data = (byte*)vstr.buf; for (size_t i = 0; i < seq_len; i++) { if (i > 0) { memcpy(data, sep_str, sep_len); data += sep_len; } GET_STR_DATA_LEN(seq_items[i], s, l); memcpy(data, s, l); data += l; } // return joined string return mp_obj_new_str_from_vstr(self_type, &vstr); } MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); mp_int_t splits = -1; mp_obj_t sep = mp_const_none; if (n_args > 1) { sep = args[1]; if (n_args > 2) { splits = mp_obj_get_int(args[2]); } } mp_obj_t res = mp_obj_new_list(0, NULL); GET_STR_DATA_LEN(args[0], s, len); const byte *top = s + len; if (sep == mp_const_none) { // sep not given, so separate on whitespace // Initial whitespace is not counted as split, so we pre-do it while (s < top && unichar_isspace(*s)) s++; while (s < top && splits != 0) { const byte *start = s; while (s < top && !unichar_isspace(*s)) s++; mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, s - start)); if (s >= top) { break; } while (s < top && unichar_isspace(*s)) s++; if (splits > 0) { splits--; } } if (s < top) { mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, s, top - s)); } } else { // sep given if (mp_obj_get_type(sep) != self_type) { bad_implicit_conversion(sep); } size_t sep_len; const char *sep_str = mp_obj_str_get_data(sep, &sep_len); if (sep_len == 0) { mp_raise_ValueError("empty separator"); } for (;;) { const byte *start = s; for (;;) { if (splits == 0 || s + sep_len > top) { s = top; break; } else if (memcmp(s, sep_str, sep_len) == 0) { break; } s++; } mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, s - start)); if (s >= top) { break; } s += sep_len; if (splits > 0) { splits--; } } } return res; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, mp_obj_str_split); #if MICROPY_PY_BUILTINS_STR_SPLITLINES STATIC mp_obj_t str_splitlines(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_keepends }; static const mp_arg_t allowed_args[] = { { MP_QSTR_keepends, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); const mp_obj_type_t *self_type = mp_obj_get_type(pos_args[0]); mp_obj_t res = mp_obj_new_list(0, NULL); GET_STR_DATA_LEN(pos_args[0], s, len); const byte *top = s + len; while (s < top) { const byte *start = s; size_t match = 0; while (s < top) { if (*s == '\n') { match = 1; break; } else if (*s == '\r') { if (s[1] == '\n') { match = 2; } else { match = 1; } break; } s++; } size_t sub_len = s - start; if (args[ARG_keepends].u_bool) { sub_len += match; } mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, sub_len)); s += match; } return res; } MP_DEFINE_CONST_FUN_OBJ_KW(str_splitlines_obj, 1, str_splitlines); #endif STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { if (n_args < 3) { // If we don't have split limit, it doesn't matter from which side // we split. return mp_obj_str_split(n_args, args); } const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); mp_obj_t sep = args[1]; GET_STR_DATA_LEN(args[0], s, len); mp_int_t splits = mp_obj_get_int(args[2]); if (splits < 0) { // Negative limit means no limit, so delegate to split(). return mp_obj_str_split(n_args, args); } mp_int_t org_splits = splits; // Preallocate list to the max expected # of elements, as we // will fill it from the end. mp_obj_list_t *res = MP_OBJ_TO_PTR(mp_obj_new_list(splits + 1, NULL)); mp_int_t idx = splits; if (sep == mp_const_none) { mp_raise_NotImplementedError("rsplit(None,n)"); } else { size_t sep_len; const char *sep_str = mp_obj_str_get_data(sep, &sep_len); if (sep_len == 0) { mp_raise_ValueError("empty separator"); } const byte *beg = s; const byte *last = s + len; for (;;) { s = last - sep_len; for (;;) { if (splits == 0 || s < beg) { break; } else if (memcmp(s, sep_str, sep_len) == 0) { break; } s--; } if (s < beg || splits == 0) { res->items[idx] = mp_obj_new_str_of_type(self_type, beg, last - beg); break; } res->items[idx--] = mp_obj_new_str_of_type(self_type, s + sep_len, last - s - sep_len); last = s; splits--; } if (idx != 0) { // We split less parts than split limit, now go cleanup surplus size_t used = org_splits + 1 - idx; memmove(res->items, &res->items[idx], used * sizeof(mp_obj_t)); mp_seq_clear(res->items, used, res->alloc, sizeof(*res->items)); res->len = used; } } return MP_OBJ_FROM_PTR(res); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit); STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); mp_check_self(mp_obj_is_str_or_bytes(args[0])); // check argument type if (mp_obj_get_type(args[1]) != self_type) { bad_implicit_conversion(args[1]); } GET_STR_DATA_LEN(args[0], haystack, haystack_len); GET_STR_DATA_LEN(args[1], needle, needle_len); const byte *start = haystack; const byte *end = haystack + haystack_len; if (n_args >= 3 && args[2] != mp_const_none) { start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true); } if (n_args >= 4 && args[3] != mp_const_none) { end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true); } if (end < start) { goto out_error; } const byte *p = find_subbytes(start, end - start, needle, needle_len, direction); if (p == NULL) { out_error: // not found if (is_index) { mp_raise_ValueError("substring not found"); } else { return MP_OBJ_NEW_SMALL_INT(-1); } } else { // found #if MICROPY_PY_BUILTINS_STR_UNICODE if (self_type == &mp_type_str) { return MP_OBJ_NEW_SMALL_INT(utf8_ptr_to_index(haystack, p)); } #endif return MP_OBJ_NEW_SMALL_INT(p - haystack); } } STATIC mp_obj_t str_find(size_t n_args, const mp_obj_t *args) { return str_finder(n_args, args, 1, false); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find); STATIC mp_obj_t str_rfind(size_t n_args, const mp_obj_t *args) { return str_finder(n_args, args, -1, false); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind); STATIC mp_obj_t str_index(size_t n_args, const mp_obj_t *args) { return str_finder(n_args, args, 1, true); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index); STATIC mp_obj_t str_rindex(size_t n_args, const mp_obj_t *args) { return str_finder(n_args, args, -1, true); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex); // TODO: (Much) more variety in args STATIC mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); GET_STR_DATA_LEN(args[0], str, str_len); size_t prefix_len; const char *prefix = mp_obj_str_get_data(args[1], &prefix_len); const byte *start = str; if (n_args > 2) { start = str_index_to_ptr(self_type, str, str_len, args[2], true); } if (prefix_len + (start - str) > str_len) { return mp_const_false; } return mp_obj_new_bool(memcmp(start, prefix, prefix_len) == 0); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith); STATIC mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) { GET_STR_DATA_LEN(args[0], str, str_len); size_t suffix_len; const char *suffix = mp_obj_str_get_data(args[1], &suffix_len); if (n_args > 2) { mp_raise_NotImplementedError("start/end indices"); } if (suffix_len > str_len) { return mp_const_false; } return mp_obj_new_bool(memcmp(str + (str_len - suffix_len), suffix, suffix_len) == 0); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith); enum { LSTRIP, RSTRIP, STRIP }; STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_str_or_bytes(args[0])); const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); const byte *chars_to_del; uint chars_to_del_len; static const byte whitespace[] = " \t\n\r\v\f"; if (n_args == 1) { chars_to_del = whitespace; chars_to_del_len = sizeof(whitespace) - 1; } else { if (mp_obj_get_type(args[1]) != self_type) { bad_implicit_conversion(args[1]); } GET_STR_DATA_LEN(args[1], s, l); chars_to_del = s; chars_to_del_len = l; } GET_STR_DATA_LEN(args[0], orig_str, orig_str_len); size_t first_good_char_pos = 0; bool first_good_char_pos_set = false; size_t last_good_char_pos = 0; size_t i = 0; int delta = 1; if (type == RSTRIP) { i = orig_str_len - 1; delta = -1; } for (size_t len = orig_str_len; len > 0; len--) { if (find_subbytes(chars_to_del, chars_to_del_len, &orig_str[i], 1, 1) == NULL) { if (!first_good_char_pos_set) { first_good_char_pos_set = true; first_good_char_pos = i; if (type == LSTRIP) { last_good_char_pos = orig_str_len - 1; break; } else if (type == RSTRIP) { first_good_char_pos = 0; last_good_char_pos = i; break; } } last_good_char_pos = i; } i += delta; } if (!first_good_char_pos_set) { // string is all whitespace, return '' if (self_type == &mp_type_str) { return MP_OBJ_NEW_QSTR(MP_QSTR_); } else { return mp_const_empty_bytes; } } assert(last_good_char_pos >= first_good_char_pos); //+1 to accommodate the last character size_t stripped_len = last_good_char_pos - first_good_char_pos + 1; if (stripped_len == orig_str_len) { // If nothing was stripped, don't bother to dup original string // TODO: watch out for this case when we'll get to bytearray.strip() assert(first_good_char_pos == 0); return args[0]; } return mp_obj_new_str_of_type(self_type, orig_str + first_good_char_pos, stripped_len); } STATIC mp_obj_t str_strip(size_t n_args, const mp_obj_t *args) { return str_uni_strip(STRIP, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip); STATIC mp_obj_t str_lstrip(size_t n_args, const mp_obj_t *args) { return str_uni_strip(LSTRIP, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip); STATIC mp_obj_t str_rstrip(size_t n_args, const mp_obj_t *args) { return str_uni_strip(RSTRIP, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip); #if MICROPY_PY_BUILTINS_STR_CENTER STATIC mp_obj_t str_center(mp_obj_t str_in, mp_obj_t width_in) { GET_STR_DATA_LEN(str_in, str, str_len); mp_uint_t width = mp_obj_get_int(width_in); if (str_len >= width) { return str_in; } vstr_t vstr; vstr_init_len(&vstr, width); memset(vstr.buf, ' ', width); int left = (width - str_len) / 2; memcpy(vstr.buf + left, str, str_len); return mp_obj_new_str_from_vstr(mp_obj_get_type(str_in), &vstr); } MP_DEFINE_CONST_FUN_OBJ_2(str_center_obj, str_center); #endif // Takes an int arg, but only parses unsigned numbers, and only changes // *num if at least one digit was parsed. STATIC const char *str_to_int(const char *str, const char *top, int *num) { if (str < top && '0' <= *str && *str <= '9') { *num = 0; do { *num = *num * 10 + (*str - '0'); str++; } while (str < top && '0' <= *str && *str <= '9'); } return str; } STATIC bool isalignment(char ch) { return ch && strchr("<>=^", ch) != NULL; } STATIC bool istype(char ch) { return ch && strchr("bcdeEfFgGnosxX%", ch) != NULL; } STATIC bool arg_looks_integer(mp_obj_t arg) { return mp_obj_is_type(arg, &mp_type_bool) || mp_obj_is_int(arg); } STATIC bool arg_looks_numeric(mp_obj_t arg) { return arg_looks_integer(arg) #if MICROPY_PY_BUILTINS_FLOAT || mp_obj_is_float(arg) #endif ; } #if MICROPY_PY_BUILTINS_STR_OP_MODULO STATIC mp_obj_t arg_as_int(mp_obj_t arg) { #if MICROPY_PY_BUILTINS_FLOAT if (mp_obj_is_float(arg)) { return mp_obj_new_int_from_float(mp_obj_float_get(arg)); } #endif return arg; } #endif #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE STATIC NORETURN void terse_str_format_value_error(void) { mp_raise_ValueError("bad format string"); } #else // define to nothing to improve coverage #define terse_str_format_value_error() #endif STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 16, &print); for (; str < top; str++) { if (*str == '}') { str++; if (str < top && *str == '}') { vstr_add_byte(&vstr, '}'); continue; } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError("single '}' encountered in format string"); } } if (*str != '{') { vstr_add_byte(&vstr, *str); continue; } str++; if (str < top && *str == '{') { vstr_add_byte(&vstr, '{'); continue; } // replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}" const char *field_name = NULL; const char *field_name_top = NULL; char conversion = '\0'; const char *format_spec = NULL; if (str < top && *str != '}' && *str != '!' && *str != ':') { field_name = (const char *)str; while (str < top && *str != '}' && *str != '!' && *str != ':') { ++str; } field_name_top = (const char *)str; } // conversion ::= "r" | "s" if (str < top && *str == '!') { str++; if (str < top && (*str == 'r' || *str == 's')) { conversion = *str++; } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) { mp_raise_ValueError("bad conversion specifier"); } else { if (str >= top) { mp_raise_ValueError( "end of format while looking for conversion specifier"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unknown conversion specifier %c", *str)); } } } } if (str < top && *str == ':') { str++; // {:} is the same as {}, which is the same as {!s} // This makes a difference when passing in a True or False // '{}'.format(True) returns 'True' // '{:d}'.format(True) returns '1' // So we treat {:} as {} and this later gets treated to be {!s} if (*str != '}') { format_spec = str; for (int nest = 1; str < top;) { if (*str == '{') { ++nest; } else if (*str == '}') { if (--nest == 0) { break; } } ++str; } } } if (str >= top) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError("unmatched '{' in format"); } } if (*str != '}') { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError("expected ':' after format specifier"); } } mp_obj_t arg = mp_const_none; if (field_name) { int index = 0; if (MP_LIKELY(unichar_isdigit(*field_name))) { if (*arg_i > 0) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError( "can't switch from automatic field numbering to manual field specification"); } } field_name = str_to_int(field_name, field_name_top, &index); if ((uint)index >= n_args - 1) { mp_raise_msg(&mp_type_IndexError, "tuple index out of range"); } arg = args[index + 1]; *arg_i = -1; } else { const char *lookup; for (lookup = field_name; lookup < field_name_top && *lookup != '.' && *lookup != '['; lookup++); mp_obj_t field_q = mp_obj_new_str_via_qstr(field_name, lookup - field_name); // should it be via qstr? field_name = lookup; mp_map_elem_t *key_elem = mp_map_lookup(kwargs, field_q, MP_MAP_LOOKUP); if (key_elem == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, field_q)); } arg = key_elem->value; } if (field_name < field_name_top) { mp_raise_NotImplementedError("attributes not supported yet"); } } else { if (*arg_i < 0) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError( "can't switch from manual field specification to automatic field numbering"); } } if ((uint)*arg_i >= n_args - 1) { mp_raise_msg(&mp_type_IndexError, "tuple index out of range"); } arg = args[(*arg_i) + 1]; (*arg_i)++; } if (!format_spec && !conversion) { conversion = 's'; } if (conversion) { mp_print_kind_t print_kind; if (conversion == 's') { print_kind = PRINT_STR; } else { assert(conversion == 'r'); print_kind = PRINT_REPR; } vstr_t arg_vstr; mp_print_t arg_print; vstr_init_print(&arg_vstr, 16, &arg_print); mp_obj_print_helper(&arg_print, arg, print_kind); arg = mp_obj_new_str_from_vstr(&mp_type_str, &arg_vstr); } char fill = '\0'; char align = '\0'; int width = -1; int precision = -1; char type = '\0'; int flags = 0; if (format_spec) { // The format specifier (from http://docs.python.org/2/library/string.html#formatspec) // // [[fill]align][sign][#][0][width][,][.precision][type] // fill ::= // align ::= "<" | ">" | "=" | "^" // sign ::= "+" | "-" | " " // width ::= integer // precision ::= integer // type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" // recursively call the formatter to format any nested specifiers MP_STACK_CHECK(); vstr_t format_spec_vstr = mp_obj_str_format_helper(format_spec, str, arg_i, n_args, args, kwargs); const char *s = vstr_null_terminated_str(&format_spec_vstr); const char *stop = s + format_spec_vstr.len; if (isalignment(*s)) { align = *s++; } else if (*s && isalignment(s[1])) { fill = *s++; align = *s++; } if (*s == '+' || *s == '-' || *s == ' ') { if (*s == '+') { flags |= PF_FLAG_SHOW_SIGN; } else if (*s == ' ') { flags |= PF_FLAG_SPACE_SIGN; } s++; } if (*s == '#') { flags |= PF_FLAG_SHOW_PREFIX; s++; } if (*s == '0') { if (!align) { align = '='; } if (!fill) { fill = '0'; } } s = str_to_int(s, stop, &width); if (*s == ',') { flags |= PF_FLAG_SHOW_COMMA; s++; } if (*s == '.') { s++; s = str_to_int(s, stop, &precision); } if (istype(*s)) { type = *s++; } if (*s) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError("invalid format specifier"); } } vstr_clear(&format_spec_vstr); } if (!align) { if (arg_looks_numeric(arg)) { align = '>'; } else { align = '<'; } } if (!fill) { fill = ' '; } if (flags & (PF_FLAG_SHOW_SIGN | PF_FLAG_SPACE_SIGN)) { if (type == 's') { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError("sign not allowed in string format specifier"); } } if (type == 'c') { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError( "sign not allowed with integer format specifier 'c'"); } } } switch (align) { case '<': flags |= PF_FLAG_LEFT_ADJUST; break; case '=': flags |= PF_FLAG_PAD_AFTER_SIGN; break; case '^': flags |= PF_FLAG_CENTER_ADJUST; break; } if (arg_looks_integer(arg)) { switch (type) { case 'b': mp_print_mp_int(&print, arg, 2, 'a', flags, fill, width, 0); continue; case 'c': { char ch = mp_obj_get_int(arg); mp_print_strn(&print, &ch, 1, flags, fill, width); continue; } case '\0': // No explicit format type implies 'd' case 'n': // I don't think we support locales in uPy so use 'd' case 'd': mp_print_mp_int(&print, arg, 10, 'a', flags, fill, width, 0); continue; case 'o': if (flags & PF_FLAG_SHOW_PREFIX) { flags |= PF_FLAG_SHOW_OCTAL_LETTER; } mp_print_mp_int(&print, arg, 8, 'a', flags, fill, width, 0); continue; case 'X': case 'x': mp_print_mp_int(&print, arg, 16, type - ('X' - 'A'), flags, fill, width, 0); continue; case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case '%': // The floating point formatters all work with anything that // looks like an integer break; default: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unknown format code '%c' for object of type '%s'", type, mp_obj_get_type_str(arg))); } } } // NOTE: no else here. We need the e, f, g etc formats for integer // arguments (from above if) to take this if. if (arg_looks_numeric(arg)) { if (!type) { // Even though the docs say that an unspecified type is the same // as 'g', there is one subtle difference, when the exponent // is one less than the precision. // // '{:10.1}'.format(0.0) ==> '0e+00' // '{:10.1g}'.format(0.0) ==> '0' // // TODO: Figure out how to deal with this. // // A proper solution would involve adding a special flag // or something to format_float, and create a format_double // to deal with doubles. In order to fix this when using // sprintf, we'd need to use the e format and tweak the // returned result to strip trailing zeros like the g format // does. // // {:10.3} and {:10.2e} with 1.23e2 both produce 1.23e+02 // but with 1.e2 you get 1e+02 and 1.00e+02 // // Stripping the trailing 0's (like g) does would make the // e format give us the right format. // // CPython sources say: // Omitted type specifier. Behaves in the same way as repr(x) // and str(x) if no precision is given, else like 'g', but with // at least one digit after the decimal point. */ type = 'g'; } if (type == 'n') { type = 'g'; } switch (type) { #if MICROPY_PY_BUILTINS_FLOAT case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': mp_print_float(&print, mp_obj_get_float(arg), type, flags, fill, width, precision); break; case '%': flags |= PF_FLAG_ADD_PERCENT; #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #define F100 100.0F #else #define F100 100.0 #endif mp_print_float(&print, mp_obj_get_float(arg) * F100, 'f', flags, fill, width, precision); #undef F100 break; #endif default: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unknown format code '%c' for object of type '%s'", type, mp_obj_get_type_str(arg))); } } } else { // arg doesn't look like a number if (align == '=') { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError( "'=' alignment not allowed in string format specifier"); } } switch (type) { case '\0': // no explicit format type implies 's' case 's': { size_t slen; const char *s = mp_obj_str_get_data(arg, &slen); if (precision < 0) { precision = slen; } if (slen > (size_t)precision) { slen = precision; } mp_print_strn(&print, s, slen, flags, fill, width); break; } default: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unknown format code '%c' for object of type '%s'", type, mp_obj_get_type_str(arg))); } } } } return vstr; } mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { mp_check_self(mp_obj_is_str_or_bytes(args[0])); GET_STR_DATA_LEN(args[0], str, len); int arg_i = 0; vstr_t vstr = mp_obj_str_format_helper((const char*)str, (const char*)str + len, &arg_i, n_args, args, kwargs); return mp_obj_new_str_from_vstr(mp_obj_get_type(args[0]), &vstr); } MP_DEFINE_CONST_FUN_OBJ_KW(str_format_obj, 1, mp_obj_str_format); #if MICROPY_PY_BUILTINS_STR_OP_MODULO STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict) { mp_check_self(mp_obj_is_str_or_bytes(pattern)); GET_STR_DATA_LEN(pattern, str, len); const byte *start_str = str; bool is_bytes = mp_obj_is_type(pattern, &mp_type_bytes); size_t arg_i = 0; vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 16, &print); for (const byte *top = str + len; str < top; str++) { mp_obj_t arg = MP_OBJ_NULL; if (*str != '%') { vstr_add_byte(&vstr, *str); continue; } if (++str >= top) { goto incomplete_format; } if (*str == '%') { vstr_add_byte(&vstr, '%'); continue; } // Dictionary value lookup if (*str == '(') { if (dict == MP_OBJ_NULL) { mp_raise_TypeError("format needs a dict"); } arg_i = 1; // we used up the single dict argument const byte *key = ++str; while (*str != ')') { if (str >= top) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError("incomplete format key"); } } ++str; } mp_obj_t k_obj = mp_obj_new_str_via_qstr((const char*)key, str - key); arg = mp_obj_dict_get(dict, k_obj); str++; } int flags = 0; char fill = ' '; int alt = 0; while (str < top) { if (*str == '-') flags |= PF_FLAG_LEFT_ADJUST; else if (*str == '+') flags |= PF_FLAG_SHOW_SIGN; else if (*str == ' ') flags |= PF_FLAG_SPACE_SIGN; else if (*str == '#') alt = PF_FLAG_SHOW_PREFIX; else if (*str == '0') { flags |= PF_FLAG_PAD_AFTER_SIGN; fill = '0'; } else break; str++; } // parse width, if it exists int width = 0; if (str < top) { if (*str == '*') { if (arg_i >= n_args) { goto not_enough_args; } width = mp_obj_get_int(args[arg_i++]); str++; } else { str = (const byte*)str_to_int((const char*)str, (const char*)top, &width); } } int prec = -1; if (str < top && *str == '.') { if (++str < top) { if (*str == '*') { if (arg_i >= n_args) { goto not_enough_args; } prec = mp_obj_get_int(args[arg_i++]); str++; } else { prec = 0; str = (const byte*)str_to_int((const char*)str, (const char*)top, &prec); } } } if (str >= top) { incomplete_format: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { mp_raise_ValueError("incomplete format"); } } // Tuple value lookup if (arg == MP_OBJ_NULL) { if (arg_i >= n_args) { not_enough_args: mp_raise_TypeError("format string needs more arguments"); } arg = args[arg_i++]; } switch (*str) { case 'c': if (mp_obj_is_str(arg)) { size_t slen; const char *s = mp_obj_str_get_data(arg, &slen); if (slen != 1) { mp_raise_TypeError("%%c needs int or char"); } mp_print_strn(&print, s, 1, flags, ' ', width); } else if (arg_looks_integer(arg)) { char ch = mp_obj_get_int(arg); mp_print_strn(&print, &ch, 1, flags, ' ', width); } else { mp_raise_TypeError("integer needed"); } break; case 'd': case 'i': case 'u': mp_print_mp_int(&print, arg_as_int(arg), 10, 'a', flags, fill, width, prec); break; #if MICROPY_PY_BUILTINS_FLOAT case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': mp_print_float(&print, mp_obj_get_float(arg), *str, flags, fill, width, prec); break; #endif case 'o': if (alt) { flags |= (PF_FLAG_SHOW_PREFIX | PF_FLAG_SHOW_OCTAL_LETTER); } mp_print_mp_int(&print, arg, 8, 'a', flags, fill, width, prec); break; case 'r': case 's': { vstr_t arg_vstr; mp_print_t arg_print; vstr_init_print(&arg_vstr, 16, &arg_print); mp_print_kind_t print_kind = (*str == 'r' ? PRINT_REPR : PRINT_STR); if (print_kind == PRINT_STR && is_bytes && mp_obj_is_type(arg, &mp_type_bytes)) { // If we have something like b"%s" % b"1", bytes arg should be // printed undecorated. print_kind = PRINT_RAW; } mp_obj_print_helper(&arg_print, arg, print_kind); uint vlen = arg_vstr.len; if (prec < 0) { prec = vlen; } if (vlen > (uint)prec) { vlen = prec; } mp_print_strn(&print, arg_vstr.buf, vlen, flags, ' ', width); vstr_clear(&arg_vstr); break; } case 'X': case 'x': mp_print_mp_int(&print, arg, 16, *str - ('X' - 'A'), flags | alt, fill, width, prec); break; default: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unsupported format character '%c' (0x%x) at index %d", *str, *str, str - start_str)); } } } if (arg_i != n_args) { mp_raise_TypeError("format string didn't convert all arguments"); } return mp_obj_new_str_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr); } #endif // The implementation is optimized, returning the original string if there's // nothing to replace. STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_str_or_bytes(args[0])); mp_int_t max_rep = -1; if (n_args == 4) { max_rep = mp_obj_get_int(args[3]); if (max_rep == 0) { return args[0]; } else if (max_rep < 0) { max_rep = -1; } } // if max_rep is still -1 by this point we will need to do all possible replacements // check argument types const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); if (mp_obj_get_type(args[1]) != self_type) { bad_implicit_conversion(args[1]); } if (mp_obj_get_type(args[2]) != self_type) { bad_implicit_conversion(args[2]); } // extract string data GET_STR_DATA_LEN(args[0], str, str_len); GET_STR_DATA_LEN(args[1], old, old_len); GET_STR_DATA_LEN(args[2], new, new_len); // old won't exist in str if it's longer, so nothing to replace if (old_len > str_len) { return args[0]; } // data for the replaced string byte *data = NULL; vstr_t vstr; // do 2 passes over the string: // first pass computes the required length of the replaced string // second pass does the replacements for (;;) { size_t replaced_str_index = 0; size_t num_replacements_done = 0; const byte *old_occurrence; const byte *offset_ptr = str; size_t str_len_remain = str_len; if (old_len == 0) { // if old_str is empty, copy new_str to start of replaced string // copy the replacement string if (data != NULL) { memcpy(data, new, new_len); } replaced_str_index += new_len; num_replacements_done++; } while (num_replacements_done != (size_t)max_rep && str_len_remain > 0 && (old_occurrence = find_subbytes(offset_ptr, str_len_remain, old, old_len, 1)) != NULL) { if (old_len == 0) { old_occurrence += 1; } // copy from just after end of last occurrence of to-be-replaced string to right before start of next occurrence if (data != NULL) { memcpy(data + replaced_str_index, offset_ptr, old_occurrence - offset_ptr); } replaced_str_index += old_occurrence - offset_ptr; // copy the replacement string if (data != NULL) { memcpy(data + replaced_str_index, new, new_len); } replaced_str_index += new_len; offset_ptr = old_occurrence + old_len; str_len_remain = str + str_len - offset_ptr; num_replacements_done++; } // copy from just after end of last occurrence of to-be-replaced string to end of old string if (data != NULL) { memcpy(data + replaced_str_index, offset_ptr, str_len_remain); } replaced_str_index += str_len_remain; if (data == NULL) { // first pass if (num_replacements_done == 0) { // no substr found, return original string return args[0]; } else { // substr found, allocate new string vstr_init_len(&vstr, replaced_str_index); data = (byte*)vstr.buf; assert(data != NULL); } } else { // second pass, we are done break; } } return mp_obj_new_str_from_vstr(self_type, &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace); #if MICROPY_PY_BUILTINS_STR_COUNT STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); mp_check_self(mp_obj_is_str_or_bytes(args[0])); // check argument type if (mp_obj_get_type(args[1]) != self_type) { bad_implicit_conversion(args[1]); } GET_STR_DATA_LEN(args[0], haystack, haystack_len); GET_STR_DATA_LEN(args[1], needle, needle_len); const byte *start = haystack; const byte *end = haystack + haystack_len; if (n_args >= 3 && args[2] != mp_const_none) { start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true); } if (n_args >= 4 && args[3] != mp_const_none) { end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true); } // if needle_len is zero then we count each gap between characters as an occurrence if (needle_len == 0) { return MP_OBJ_NEW_SMALL_INT(utf8_charlen(start, end - start) + 1); } // count the occurrences mp_int_t num_occurrences = 0; for (const byte *haystack_ptr = start; haystack_ptr + needle_len <= end;) { if (memcmp(haystack_ptr, needle, needle_len) == 0) { num_occurrences++; haystack_ptr += needle_len; } else { haystack_ptr = utf8_next_char(haystack_ptr); } } return MP_OBJ_NEW_SMALL_INT(num_occurrences); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count); #endif #if MICROPY_PY_BUILTINS_STR_PARTITION STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { mp_check_self(mp_obj_is_str_or_bytes(self_in)); mp_obj_type_t *self_type = mp_obj_get_type(self_in); if (self_type != mp_obj_get_type(arg)) { bad_implicit_conversion(arg); } GET_STR_DATA_LEN(self_in, str, str_len); GET_STR_DATA_LEN(arg, sep, sep_len); if (sep_len == 0) { mp_raise_ValueError("empty separator"); } mp_obj_t result[3]; if (self_type == &mp_type_str) { result[0] = MP_OBJ_NEW_QSTR(MP_QSTR_); result[1] = MP_OBJ_NEW_QSTR(MP_QSTR_); result[2] = MP_OBJ_NEW_QSTR(MP_QSTR_); } else { result[0] = mp_const_empty_bytes; result[1] = mp_const_empty_bytes; result[2] = mp_const_empty_bytes; } if (direction > 0) { result[0] = self_in; } else { result[2] = self_in; } const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction); if (position_ptr != NULL) { size_t position = position_ptr - str; result[0] = mp_obj_new_str_of_type(self_type, str, position); result[1] = arg; result[2] = mp_obj_new_str_of_type(self_type, str + position + sep_len, str_len - position - sep_len); } return mp_obj_new_tuple(3, result); } STATIC mp_obj_t str_partition(mp_obj_t self_in, mp_obj_t arg) { return str_partitioner(self_in, arg, 1); } MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition); STATIC mp_obj_t str_rpartition(mp_obj_t self_in, mp_obj_t arg) { return str_partitioner(self_in, arg, -1); } MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition); #endif // Supposedly not too critical operations, so optimize for code size STATIC mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, self_data, self_len); vstr_t vstr; vstr_init_len(&vstr, self_len); byte *data = (byte*)vstr.buf; for (size_t i = 0; i < self_len; i++) { *data++ = op(*self_data++); } return mp_obj_new_str_from_vstr(mp_obj_get_type(self_in), &vstr); } STATIC mp_obj_t str_lower(mp_obj_t self_in) { return str_caseconv(unichar_tolower, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower); STATIC mp_obj_t str_upper(mp_obj_t self_in) { return str_caseconv(unichar_toupper, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper); STATIC mp_obj_t str_uni_istype(bool (*f)(unichar), mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, self_data, self_len); if (self_len == 0) { return mp_const_false; // default to False for empty str } if (f != unichar_isupper && f != unichar_islower) { for (size_t i = 0; i < self_len; i++) { if (!f(*self_data++)) { return mp_const_false; } } } else { bool contains_alpha = false; for (size_t i = 0; i < self_len; i++) { // only check alphanumeric characters if (unichar_isalpha(*self_data++)) { contains_alpha = true; if (!f(*(self_data - 1))) { // -1 because we already incremented above return mp_const_false; } } } if (!contains_alpha) { return mp_const_false; } } return mp_const_true; } STATIC mp_obj_t str_isspace(mp_obj_t self_in) { return str_uni_istype(unichar_isspace, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace); STATIC mp_obj_t str_isalpha(mp_obj_t self_in) { return str_uni_istype(unichar_isalpha, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha); STATIC mp_obj_t str_isdigit(mp_obj_t self_in) { return str_uni_istype(unichar_isdigit, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit); STATIC mp_obj_t str_isupper(mp_obj_t self_in) { return str_uni_istype(unichar_isupper, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper); STATIC mp_obj_t str_islower(mp_obj_t self_in) { return str_uni_istype(unichar_islower, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower); #if MICROPY_CPYTHON_COMPAT // These methods are superfluous in the presence of str() and bytes() // constructors. // TODO: should accept kwargs too STATIC mp_obj_t bytes_decode(size_t n_args, const mp_obj_t *args) { mp_obj_t new_args[2]; if (n_args == 1) { new_args[0] = args[0]; new_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8); args = new_args; n_args++; } return mp_obj_str_make_new(&mp_type_str, n_args, 0, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode); // TODO: should accept kwargs too STATIC mp_obj_t str_encode(size_t n_args, const mp_obj_t *args) { mp_obj_t new_args[2]; if (n_args == 1) { new_args[0] = args[0]; new_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8); args = new_args; n_args++; } return bytes_make_new(NULL, n_args, 0, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode); #endif mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { if (flags == MP_BUFFER_READ) { GET_STR_DATA_LEN(self_in, str_data, str_len); bufinfo->buf = (void*)str_data; bufinfo->len = str_len; bufinfo->typecode = 'B'; // bytes should be unsigned, so should unicode byte-access return 0; } else { // can't write to a string return 1; } } STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = { #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) }, #if !MICROPY_PY_BUILTINS_STR_UNICODE // If we have separate unicode type, then here we have methods only // for bytes type, and it should not have encode() methods. Otherwise, // we have non-compliant-but-practical bytestring type, which shares // method table with bytes, so they both have encode() and decode() // methods (which should do type checking at runtime). { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) }, #endif #endif { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&str_find_obj) }, { MP_ROM_QSTR(MP_QSTR_rfind), MP_ROM_PTR(&str_rfind_obj) }, { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&str_index_obj) }, { MP_ROM_QSTR(MP_QSTR_rindex), MP_ROM_PTR(&str_rindex_obj) }, { MP_ROM_QSTR(MP_QSTR_join), MP_ROM_PTR(&str_join_obj) }, { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&str_split_obj) }, #if MICROPY_PY_BUILTINS_STR_SPLITLINES { MP_ROM_QSTR(MP_QSTR_splitlines), MP_ROM_PTR(&str_splitlines_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_rsplit), MP_ROM_PTR(&str_rsplit_obj) }, { MP_ROM_QSTR(MP_QSTR_startswith), MP_ROM_PTR(&str_startswith_obj) }, { MP_ROM_QSTR(MP_QSTR_endswith), MP_ROM_PTR(&str_endswith_obj) }, { MP_ROM_QSTR(MP_QSTR_strip), MP_ROM_PTR(&str_strip_obj) }, { MP_ROM_QSTR(MP_QSTR_lstrip), MP_ROM_PTR(&str_lstrip_obj) }, { MP_ROM_QSTR(MP_QSTR_rstrip), MP_ROM_PTR(&str_rstrip_obj) }, { MP_ROM_QSTR(MP_QSTR_format), MP_ROM_PTR(&str_format_obj) }, { MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&str_replace_obj) }, #if MICROPY_PY_BUILTINS_STR_COUNT { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&str_count_obj) }, #endif #if MICROPY_PY_BUILTINS_STR_PARTITION { MP_ROM_QSTR(MP_QSTR_partition), MP_ROM_PTR(&str_partition_obj) }, { MP_ROM_QSTR(MP_QSTR_rpartition), MP_ROM_PTR(&str_rpartition_obj) }, #endif #if MICROPY_PY_BUILTINS_STR_CENTER { MP_ROM_QSTR(MP_QSTR_center), MP_ROM_PTR(&str_center_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_lower), MP_ROM_PTR(&str_lower_obj) }, { MP_ROM_QSTR(MP_QSTR_upper), MP_ROM_PTR(&str_upper_obj) }, { MP_ROM_QSTR(MP_QSTR_isspace), MP_ROM_PTR(&str_isspace_obj) }, { MP_ROM_QSTR(MP_QSTR_isalpha), MP_ROM_PTR(&str_isalpha_obj) }, { MP_ROM_QSTR(MP_QSTR_isdigit), MP_ROM_PTR(&str_isdigit_obj) }, { MP_ROM_QSTR(MP_QSTR_isupper), MP_ROM_PTR(&str_isupper_obj) }, { MP_ROM_QSTR(MP_QSTR_islower), MP_ROM_PTR(&str_islower_obj) }, }; STATIC MP_DEFINE_CONST_DICT(str8_locals_dict, str8_locals_dict_table); #if !MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); const mp_obj_type_t mp_type_str = { { &mp_type_type }, .name = MP_QSTR_str, .print = str_print, .make_new = mp_obj_str_make_new, .binary_op = mp_obj_str_binary_op, .subscr = bytes_subscr, .getiter = mp_obj_new_str_iterator, .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, .locals_dict = (mp_obj_dict_t*)&str8_locals_dict, }; #endif // Reuses most of methods from str const mp_obj_type_t mp_type_bytes = { { &mp_type_type }, .name = MP_QSTR_bytes, .print = str_print, .make_new = bytes_make_new, .binary_op = mp_obj_str_binary_op, .subscr = bytes_subscr, .getiter = mp_obj_new_bytes_iterator, .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, .locals_dict = (mp_obj_dict_t*)&str8_locals_dict, }; // The zero-length bytes object, with data that includes a null-terminating byte const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, (const byte*)""}; // Create a str/bytes object using the given data. New memory is allocated and // the data is copied across. This function should only be used if the type is bytes, // or if the type is str and the string data is known to be not interned. mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte* data, size_t len) { mp_obj_str_t *o = m_new_obj(mp_obj_str_t); o->base.type = type; o->len = len; if (data) { o->hash = qstr_compute_hash(data, len); byte *p = m_new(byte, len + 1); o->data = p; memcpy(p, data, len * sizeof(byte)); p[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings } return MP_OBJ_FROM_PTR(o); } // Create a str/bytes object using the given data. If the type is str and the string // data is already interned, then a qstr object is returned. Otherwise new memory is // allocated for the object and the data is copied across. mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len) { if (type == &mp_type_str) { return mp_obj_new_str((const char*)data, len); } else { return mp_obj_new_bytes(data, len); } } // Create a str using a qstr to store the data; may use existing or new qstr. mp_obj_t mp_obj_new_str_via_qstr(const char* data, size_t len) { return MP_OBJ_NEW_QSTR(qstr_from_strn(data, len)); } // Create a str/bytes object from the given vstr. The vstr buffer is resized to // the exact length required and then reused for the str/bytes object. The vstr // is cleared and can safely be passed to vstr_free if it was heap allocated. mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { // if not a bytes object, look if a qstr with this data already exists if (type == &mp_type_str) { qstr q = qstr_find_strn(vstr->buf, vstr->len); if (q != MP_QSTRnull) { vstr_clear(vstr); vstr->alloc = 0; return MP_OBJ_NEW_QSTR(q); } } // make a new str/bytes object mp_obj_str_t *o = m_new_obj(mp_obj_str_t); o->base.type = type; o->len = vstr->len; o->hash = qstr_compute_hash((byte*)vstr->buf, vstr->len); if (vstr->len + 1 == vstr->alloc) { o->data = (byte*)vstr->buf; } else { o->data = (byte*)m_renew(char, vstr->buf, vstr->alloc, vstr->len + 1); } ((byte*)o->data)[o->len] = '\0'; // add null byte vstr->buf = NULL; vstr->alloc = 0; return MP_OBJ_FROM_PTR(o); } mp_obj_t mp_obj_new_str(const char* data, size_t len) { qstr q = qstr_find_strn(data, len); if (q != MP_QSTRnull) { // qstr with this data already exists return MP_OBJ_NEW_QSTR(q); } else { // no existing qstr, don't make one return mp_obj_new_str_copy(&mp_type_str, (const byte*)data, len); } } mp_obj_t mp_obj_str_intern(mp_obj_t str) { GET_STR_DATA_LEN(str, data, len); return mp_obj_new_str_via_qstr((const char*)data, len); } mp_obj_t mp_obj_str_intern_checked(mp_obj_t obj) { size_t len; const char *data = mp_obj_str_get_data(obj, &len); return mp_obj_new_str_via_qstr((const char*)data, len); } mp_obj_t mp_obj_new_bytes(const byte* data, size_t len) { return mp_obj_new_str_copy(&mp_type_bytes, data, len); } bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) { if (mp_obj_is_qstr(s1) && mp_obj_is_qstr(s2)) { return s1 == s2; } else { GET_STR_HASH(s1, h1); GET_STR_HASH(s2, h2); // If any of hashes is 0, it means it's not valid if (h1 != 0 && h2 != 0 && h1 != h2) { return false; } GET_STR_DATA_LEN(s1, d1, l1); GET_STR_DATA_LEN(s2, d2, l2); if (l1 != l2) { return false; } return memcmp(d1, d2, l1) == 0; } } STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("can't convert to str implicitly"); } else { const qstr src_name = mp_obj_get_type(self_in)->name; nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert '%q' object to %q implicitly", src_name, src_name == MP_QSTR_str ? MP_QSTR_bytes : MP_QSTR_str)); } } // use this if you will anyway convert the string to a qstr // will be more efficient for the case where it's already a qstr qstr mp_obj_str_get_qstr(mp_obj_t self_in) { if (mp_obj_is_qstr(self_in)) { return MP_OBJ_QSTR_VALUE(self_in); } else if (mp_obj_is_type(self_in, &mp_type_str)) { mp_obj_str_t *self = MP_OBJ_TO_PTR(self_in); return qstr_from_strn((char*)self->data, self->len); } else { bad_implicit_conversion(self_in); } } // only use this function if you need the str data to be zero terminated // at the moment all strings are zero terminated to help with C ASCIIZ compatibility const char *mp_obj_str_get_str(mp_obj_t self_in) { if (mp_obj_is_str_or_bytes(self_in)) { GET_STR_DATA_LEN(self_in, s, l); (void)l; // len unused return (const char*)s; } else { bad_implicit_conversion(self_in); } } const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len) { if (mp_obj_is_str_or_bytes(self_in)) { GET_STR_DATA_LEN(self_in, s, l); *len = l; return (const char*)s; } else { bad_implicit_conversion(self_in); } } #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len) { if (mp_obj_is_qstr(self_in)) { return qstr_data(MP_OBJ_QSTR_VALUE(self_in), len); } else { *len = ((mp_obj_str_t*)self_in)->len; return ((mp_obj_str_t*)self_in)->data; } } #endif /******************************************************************************/ /* str iterator */ typedef struct _mp_obj_str8_it_t { mp_obj_base_t base; mp_fun_1_t iternext; mp_obj_t str; size_t cur; } mp_obj_str8_it_t; #if !MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in); GET_STR_DATA_LEN(self->str, str, len); if (self->cur < len) { mp_obj_t o_out = mp_obj_new_str_via_qstr((const char*)str + self->cur, 1); self->cur += 1; return o_out; } else { return MP_OBJ_STOP_ITERATION; } } STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_str8_it_t *o = (mp_obj_str8_it_t*)iter_buf; o->base.type = &mp_type_polymorph_iter; o->iternext = str_it_iternext; o->str = str; o->cur = 0; return MP_OBJ_FROM_PTR(o); } #endif STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) { mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in); GET_STR_DATA_LEN(self->str, str, len); if (self->cur < len) { mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(str[self->cur]); self->cur += 1; return o_out; } else { return MP_OBJ_STOP_ITERATION; } } mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_str8_it_t *o = (mp_obj_str8_it_t*)iter_buf; o->base.type = &mp_type_polymorph_iter; o->iternext = bytes_it_iternext; o->str = str; o->cur = 0; return MP_OBJ_FROM_PTR(o); } micropython-1.12/py/objstr.h000066400000000000000000000124621357706137100161330ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJSTR_H #define MICROPY_INCLUDED_PY_OBJSTR_H #include "py/obj.h" typedef struct _mp_obj_str_t { mp_obj_base_t base; mp_uint_t hash; // len == number of bytes used in data, alloc = len + 1 because (at the moment) we also append a null byte size_t len; const byte *data; } mp_obj_str_t; #define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str} // use this macro to extract the string hash // warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data #define GET_STR_HASH(str_obj_in, str_hash) \ mp_uint_t str_hash; if (mp_obj_is_qstr(str_obj_in)) \ { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->hash; } // use this macro to extract the string length #define GET_STR_LEN(str_obj_in, str_len) \ size_t str_len; if (mp_obj_is_qstr(str_obj_in)) \ { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->len; } // use this macro to extract the string data and length #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len); #define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \ size_t str_len; const byte *str_data = mp_obj_str_get_data_no_check(str_obj_in, &str_len); #else #define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \ const byte *str_data; size_t str_len; if (mp_obj_is_qstr(str_obj_in)) \ { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \ else { str_len = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->len; str_data = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->data; } #endif mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args); void mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len); mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args); mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte* data, size_t len); mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len); mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len, mp_obj_t index, bool is_slice); const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj); MP_DECLARE_CONST_FUN_OBJ_2(str_join_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj); MP_DECLARE_CONST_FUN_OBJ_KW(str_splitlines_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj); MP_DECLARE_CONST_FUN_OBJ_KW(str_format_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj); MP_DECLARE_CONST_FUN_OBJ_2(str_partition_obj); MP_DECLARE_CONST_FUN_OBJ_2(str_rpartition_obj); MP_DECLARE_CONST_FUN_OBJ_2(str_center_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_lower_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_upper_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_isspace_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_isalpha_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_isdigit_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_isupper_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_islower_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj); #endif // MICROPY_INCLUDED_PY_OBJSTR_H micropython-1.12/py/objstringio.c000066400000000000000000000222421357706137100171510ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objstr.h" #include "py/objstringio.h" #include "py/runtime.h" #include "py/stream.h" #if MICROPY_PY_IO #if MICROPY_CPYTHON_COMPAT STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) { if (o->vstr == NULL) { mp_raise_ValueError("I/O operation on closed file"); } } #else #define check_stringio_is_open(o) #endif STATIC void stringio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, self->base.type == &mp_type_stringio ? "" : "", self); } STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { (void)errcode; mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in); check_stringio_is_open(o); if (o->vstr->len <= o->pos) { // read to EOF, or seeked to EOF or beyond return 0; } mp_uint_t remaining = o->vstr->len - o->pos; if (size > remaining) { size = remaining; } memcpy(buf, o->vstr->buf + o->pos, size); o->pos += size; return size; } STATIC void stringio_copy_on_write(mp_obj_stringio_t *o) { const void *buf = o->vstr->buf; o->vstr->buf = m_new(char, o->vstr->len); o->vstr->fixed_buf = false; o->ref_obj = MP_OBJ_NULL; memcpy(o->vstr->buf, buf, o->vstr->len); } STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { (void)errcode; mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in); check_stringio_is_open(o); if (o->vstr->fixed_buf) { stringio_copy_on_write(o); } mp_uint_t new_pos = o->pos + size; if (new_pos < size) { // Writing bytes will overflow o->pos beyond limit of mp_uint_t. *errcode = MP_EFBIG; return MP_STREAM_ERROR; } mp_uint_t org_len = o->vstr->len; if (new_pos > o->vstr->alloc) { // Take all what's already allocated... o->vstr->len = o->vstr->alloc; // ... and add more vstr_add_len(o->vstr, new_pos - o->vstr->alloc); } // If there was a seek past EOF, clear the hole if (o->pos > org_len) { memset(o->vstr->buf + org_len, 0, o->pos - org_len); } memcpy(o->vstr->buf + o->pos, buf, size); o->pos = new_pos; if (new_pos > o->vstr->len) { o->vstr->len = new_pos; } return size; } STATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in); switch (request) { case MP_STREAM_SEEK: { struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg; mp_uint_t ref = 0; switch (s->whence) { case MP_SEEK_CUR: ref = o->pos; break; case MP_SEEK_END: ref = o->vstr->len; break; } mp_uint_t new_pos = ref + s->offset; // For MP_SEEK_SET, offset is unsigned if (s->whence != MP_SEEK_SET && s->offset < 0) { if (new_pos > ref) { // Negative offset from SEEK_CUR or SEEK_END went past 0. // CPython sets position to 0, POSIX returns an EINVAL error new_pos = 0; } } else if (new_pos < ref) { // positive offset went beyond the limit of mp_uint_t *errcode = MP_EINVAL; // replace with MP_EOVERFLOW when defined return MP_STREAM_ERROR; } s->offset = o->pos = new_pos; return 0; } case MP_STREAM_FLUSH: return 0; case MP_STREAM_CLOSE: #if MICROPY_CPYTHON_COMPAT vstr_free(o->vstr); o->vstr = NULL; #else vstr_clear(o->vstr); o->vstr->alloc = 0; o->vstr->len = 0; o->pos = 0; #endif return 0; default: *errcode = MP_EINVAL; return MP_STREAM_ERROR; } } #define STREAM_TO_CONTENT_TYPE(o) (((o)->base.type == &mp_type_stringio) ? &mp_type_str : &mp_type_bytes) STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) { mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in); check_stringio_is_open(self); // TODO: Try to avoid copying string return mp_obj_new_str_of_type(STREAM_TO_CONTENT_TYPE(self), (byte*)self->vstr->buf, self->vstr->len); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue); STATIC mp_obj_t stringio___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; return mp_stream_close(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio___exit__); STATIC mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type) { mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t); o->base.type = type; o->pos = 0; o->ref_obj = MP_OBJ_NULL; return o; } STATIC mp_obj_t stringio_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)n_kw; // TODO check n_kw==0 mp_uint_t sz = 16; bool initdata = false; mp_buffer_info_t bufinfo; mp_obj_stringio_t *o = stringio_new(type_in); if (n_args > 0) { if (mp_obj_is_int(args[0])) { sz = mp_obj_get_int(args[0]); } else { mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); if (mp_obj_is_str_or_bytes(args[0])) { o->vstr = m_new_obj(vstr_t); vstr_init_fixed_buf(o->vstr, bufinfo.len, bufinfo.buf); o->vstr->len = bufinfo.len; o->ref_obj = args[0]; return MP_OBJ_FROM_PTR(o); } sz = bufinfo.len; initdata = true; } } o->vstr = vstr_new(sz); if (initdata) { stringio_write(MP_OBJ_FROM_PTR(o), bufinfo.buf, bufinfo.len, NULL); // Cur ptr is always at the beginning of buffer at the construction o->pos = 0; } return MP_OBJ_FROM_PTR(o); } STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_getvalue), MP_ROM_PTR(&stringio_getvalue_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&stringio___exit___obj) }, }; STATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table); STATIC const mp_stream_p_t stringio_stream_p = { .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, .is_text = true, }; const mp_obj_type_t mp_type_stringio = { { &mp_type_type }, .name = MP_QSTR_StringIO, .print = stringio_print, .make_new = stringio_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &stringio_stream_p, .locals_dict = (mp_obj_dict_t*)&stringio_locals_dict, }; #if MICROPY_PY_IO_BYTESIO STATIC const mp_stream_p_t bytesio_stream_p = { .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, }; const mp_obj_type_t mp_type_bytesio = { { &mp_type_type }, .name = MP_QSTR_BytesIO, .print = stringio_print, .make_new = stringio_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &bytesio_stream_p, .locals_dict = (mp_obj_dict_t*)&stringio_locals_dict, }; #endif #endif micropython-1.12/py/objstringio.h000066400000000000000000000031441357706137100171560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJSTRINGIO_H #define MICROPY_INCLUDED_PY_OBJSTRINGIO_H #include "py/obj.h" typedef struct _mp_obj_stringio_t { mp_obj_base_t base; vstr_t *vstr; // StringIO has single pointer used for both reading and writing mp_uint_t pos; // Underlying object buffered by this StringIO mp_obj_t ref_obj; } mp_obj_stringio_t; #endif // MICROPY_INCLUDED_PY_OBJSTRINGIO_H micropython-1.12/py/objstrunicode.c000066400000000000000000000277151357706137100175040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objstr.h" #include "py/objlist.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); /******************************************************************************/ /* str */ STATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint str_len) { // this escapes characters, but it will be very slow to print (calling print many times) bool has_single_quote = false; bool has_double_quote = false; for (const byte *s = str_data, *top = str_data + str_len; !has_double_quote && s < top; s++) { if (*s == '\'') { has_single_quote = true; } else if (*s == '"') { has_double_quote = true; } } unichar quote_char = '\''; if (has_single_quote && !has_double_quote) { quote_char = '"'; } mp_printf(print, "%c", quote_char); const byte *s = str_data, *top = str_data + str_len; while (s < top) { unichar ch; ch = utf8_get_char(s); s = utf8_next_char(s); if (ch == quote_char) { mp_printf(print, "\\%c", quote_char); } else if (ch == '\\') { mp_print_str(print, "\\\\"); } else if (32 <= ch && ch <= 126) { mp_printf(print, "%c", ch); } else if (ch == '\n') { mp_print_str(print, "\\n"); } else if (ch == '\r') { mp_print_str(print, "\\r"); } else if (ch == '\t') { mp_print_str(print, "\\t"); } else if (ch < 0x100) { mp_printf(print, "\\x%02x", ch); } else if (ch < 0x10000) { mp_printf(print, "\\u%04x", ch); } else { mp_printf(print, "\\U%08x", ch); } } mp_printf(print, "%c", quote_char); } STATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { GET_STR_DATA_LEN(self_in, str_data, str_len); #if MICROPY_PY_UJSON if (kind == PRINT_JSON) { mp_str_print_json(print, str_data, str_len); return; } #endif if (kind == PRINT_STR) { mp_printf(print, "%.*s", str_len, str_data); } else { uni_print_quoted(print, str_data, str_len); } } STATIC mp_obj_t uni_unary_op(mp_unary_op_t op, mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, str_data, str_len); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(str_len != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(utf8_charlen(str_data, str_len)); default: return MP_OBJ_NULL; // op not supported } } // Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or // be capped to the first/last character of the string, depending on is_slice. const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len, mp_obj_t index, bool is_slice) { // All str functions also handle bytes objects, and they call str_index_to_ptr(), // so it must handle bytes. if (type == &mp_type_bytes) { // Taken from objstr.c:str_index_to_ptr() size_t index_val = mp_get_index(type, self_len, index, is_slice); return self_data + index_val; } mp_int_t i; // Copied from mp_get_index; I don't want bounds checking, just give me // the integer as-is. (I can't bounds-check without scanning the whole // string; an out-of-bounds index will be caught in the loops below.) if (mp_obj_is_small_int(index)) { i = MP_OBJ_SMALL_INT_VALUE(index); } else if (!mp_obj_get_int_maybe(index, &i)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "string indices must be integers, not %s", mp_obj_get_type_str(index))); } const byte *s, *top = self_data + self_len; if (i < 0) { // Negative indexing is performed by counting from the end of the string. for (s = top - 1; i; --s) { if (s < self_data) { if (is_slice) { return self_data; } mp_raise_msg(&mp_type_IndexError, "string index out of range"); } if (!UTF8_IS_CONT(*s)) { ++i; } } ++s; } else { // Positive indexing, correspondingly, counts from the start of the string. // It's assumed that negative indexing will generally be used with small // absolute values (eg str[-1], not str[-1000000]), which means it'll be // more efficient this way. s = self_data; while (1) { // First check out-of-bounds if (s >= top) { if (is_slice) { return top; } mp_raise_msg(&mp_type_IndexError, "string index out of range"); } // Then check completion if (i-- == 0) { break; } // Then skip UTF-8 char ++s; while (UTF8_IS_CONT(*s)) { ++s; } } } return s; } STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(self_in); assert(type == &mp_type_str); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { // load #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_obj_t ostart, ostop, ostep; mp_obj_slice_get(index, &ostart, &ostop, &ostep); if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported"); } const byte *pstart, *pstop; if (ostart != mp_const_none) { pstart = str_index_to_ptr(type, self_data, self_len, ostart, true); } else { pstart = self_data; } if (ostop != mp_const_none) { // pstop will point just after the stop character. This depends on // the \0 at the end of the string. pstop = str_index_to_ptr(type, self_data, self_len, ostop, true); } else { pstop = self_data + self_len; } if (pstop < pstart) { return MP_OBJ_NEW_QSTR(MP_QSTR_); } return mp_obj_new_str_of_type(type, (const byte *)pstart, pstop - pstart); } #endif const byte *s = str_index_to_ptr(type, self_data, self_len, index, false); int len = 1; if (UTF8_IS_NONASCII(*s)) { // Count the number of 1 bits (after the first) for (char mask = 0x40; *s & mask; mask >>= 1) { ++len; } } return mp_obj_new_str_via_qstr((const char*)s, len); // This will create a one-character string } else { return MP_OBJ_NULL; // op not supported } } STATIC const mp_rom_map_elem_t struni_locals_dict_table[] = { #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_encode), MP_ROM_PTR(&str_encode_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&str_find_obj) }, { MP_ROM_QSTR(MP_QSTR_rfind), MP_ROM_PTR(&str_rfind_obj) }, { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&str_index_obj) }, { MP_ROM_QSTR(MP_QSTR_rindex), MP_ROM_PTR(&str_rindex_obj) }, { MP_ROM_QSTR(MP_QSTR_join), MP_ROM_PTR(&str_join_obj) }, { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&str_split_obj) }, #if MICROPY_PY_BUILTINS_STR_SPLITLINES { MP_ROM_QSTR(MP_QSTR_splitlines), MP_ROM_PTR(&str_splitlines_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_rsplit), MP_ROM_PTR(&str_rsplit_obj) }, { MP_ROM_QSTR(MP_QSTR_startswith), MP_ROM_PTR(&str_startswith_obj) }, { MP_ROM_QSTR(MP_QSTR_endswith), MP_ROM_PTR(&str_endswith_obj) }, { MP_ROM_QSTR(MP_QSTR_strip), MP_ROM_PTR(&str_strip_obj) }, { MP_ROM_QSTR(MP_QSTR_lstrip), MP_ROM_PTR(&str_lstrip_obj) }, { MP_ROM_QSTR(MP_QSTR_rstrip), MP_ROM_PTR(&str_rstrip_obj) }, { MP_ROM_QSTR(MP_QSTR_format), MP_ROM_PTR(&str_format_obj) }, { MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&str_replace_obj) }, #if MICROPY_PY_BUILTINS_STR_COUNT { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&str_count_obj) }, #endif #if MICROPY_PY_BUILTINS_STR_PARTITION { MP_ROM_QSTR(MP_QSTR_partition), MP_ROM_PTR(&str_partition_obj) }, { MP_ROM_QSTR(MP_QSTR_rpartition), MP_ROM_PTR(&str_rpartition_obj) }, #endif #if MICROPY_PY_BUILTINS_STR_CENTER { MP_ROM_QSTR(MP_QSTR_center), MP_ROM_PTR(&str_center_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_lower), MP_ROM_PTR(&str_lower_obj) }, { MP_ROM_QSTR(MP_QSTR_upper), MP_ROM_PTR(&str_upper_obj) }, { MP_ROM_QSTR(MP_QSTR_isspace), MP_ROM_PTR(&str_isspace_obj) }, { MP_ROM_QSTR(MP_QSTR_isalpha), MP_ROM_PTR(&str_isalpha_obj) }, { MP_ROM_QSTR(MP_QSTR_isdigit), MP_ROM_PTR(&str_isdigit_obj) }, { MP_ROM_QSTR(MP_QSTR_isupper), MP_ROM_PTR(&str_isupper_obj) }, { MP_ROM_QSTR(MP_QSTR_islower), MP_ROM_PTR(&str_islower_obj) }, }; STATIC MP_DEFINE_CONST_DICT(struni_locals_dict, struni_locals_dict_table); const mp_obj_type_t mp_type_str = { { &mp_type_type }, .name = MP_QSTR_str, .print = uni_print, .make_new = mp_obj_str_make_new, .unary_op = uni_unary_op, .binary_op = mp_obj_str_binary_op, .subscr = str_subscr, .getiter = mp_obj_new_str_iterator, .buffer_p = { .get_buffer = mp_obj_str_get_buffer }, .locals_dict = (mp_obj_dict_t*)&struni_locals_dict, }; /******************************************************************************/ /* str iterator */ typedef struct _mp_obj_str_it_t { mp_obj_base_t base; mp_fun_1_t iternext; mp_obj_t str; size_t cur; } mp_obj_str_it_t; STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { mp_obj_str_it_t *self = MP_OBJ_TO_PTR(self_in); GET_STR_DATA_LEN(self->str, str, len); if (self->cur < len) { const byte *cur = str + self->cur; const byte *end = utf8_next_char(str + self->cur); mp_obj_t o_out = mp_obj_new_str_via_qstr((const char*)cur, end - cur); self->cur += end - cur; return o_out; } else { return MP_OBJ_STOP_ITERATION; } } STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_str_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_str_it_t *o = (mp_obj_str_it_t*)iter_buf; o->base.type = &mp_type_polymorph_iter; o->iternext = str_it_iternext; o->str = str; o->cur = 0; return MP_OBJ_FROM_PTR(o); } #endif // MICROPY_PY_BUILTINS_STR_UNICODE micropython-1.12/py/objtuple.c000066400000000000000000000250701357706137100164460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objtuple.h" #include "py/runtime.h" // type check is done on getiter method to allow tuple, namedtuple, attrtuple #define mp_obj_is_tuple_compatible(o) (mp_obj_get_type(o)->getiter == mp_obj_tuple_getiter) /******************************************************************************/ /* tuple */ void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_tuple_t *o = MP_OBJ_TO_PTR(o_in); if (MICROPY_PY_UJSON && kind == PRINT_JSON) { mp_print_str(print, "["); } else { mp_print_str(print, "("); kind = PRINT_REPR; } for (size_t i = 0; i < o->len; i++) { if (i > 0) { mp_print_str(print, ", "); } mp_obj_print_helper(print, o->items[i], kind); } if (MICROPY_PY_UJSON && kind == PRINT_JSON) { mp_print_str(print, "]"); } else { if (o->len == 1) { mp_print_str(print, ","); } mp_print_str(print, ")"); } } STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: // return a empty tuple return mp_const_empty_tuple; case 1: default: { // 1 argument, an iterable from which we make a new tuple if (mp_obj_is_type(args[0], &mp_type_tuple)) { return args[0]; } // TODO optimise for cases where we know the length of the iterator size_t alloc = 4; size_t len = 0; mp_obj_t *items = m_new(mp_obj_t, alloc); mp_obj_t iterable = mp_getiter(args[0], NULL); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (len >= alloc) { items = m_renew(mp_obj_t, items, alloc, alloc * 2); alloc *= 2; } items[len++] = item; } mp_obj_t tuple = mp_obj_new_tuple(len, items); m_del(mp_obj_t, items, alloc); return tuple; } } } // Don't pass MP_BINARY_OP_NOT_EQUAL here STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { mp_check_self(mp_obj_is_tuple_compatible(self_in)); mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); if (another_type->getiter != mp_obj_tuple_getiter) { // Slow path for user subclasses another_in = mp_instance_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple)); if (another_in == MP_OBJ_NULL) { if (op == MP_BINARY_OP_EQUAL) { return mp_const_false; } return MP_OBJ_NULL; } } mp_obj_tuple_t *another = MP_OBJ_TO_PTR(another_in); return mp_obj_new_bool(mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len)); } mp_obj_t mp_obj_tuple_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0); case MP_UNARY_OP_HASH: { // start hash with pointer to empty tuple, to make it fairly unique mp_int_t hash = (mp_int_t)mp_const_empty_tuple; for (size_t i = 0; i < self->len; i++) { hash += MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, self->items[i])); } return MP_OBJ_NEW_SMALL_INT(hash); } case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len); default: return MP_OBJ_NULL; // op not supported } } mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_tuple_t *o = MP_OBJ_TO_PTR(lhs); switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: { if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(rhs)), MP_OBJ_FROM_PTR(&mp_type_tuple))) { return MP_OBJ_NULL; // op not supported } mp_obj_tuple_t *p = MP_OBJ_TO_PTR(rhs); mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(o->len + p->len, NULL)); mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t); return MP_OBJ_FROM_PTR(s); } case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: { mp_int_t n; if (!mp_obj_get_int_maybe(rhs, &n)) { return MP_OBJ_NULL; // op not supported } if (n <= 0) { return mp_const_empty_tuple; } mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(o->len * n, NULL)); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); return MP_OBJ_FROM_PTR(s); } case MP_BINARY_OP_EQUAL: case MP_BINARY_OP_LESS: case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: return tuple_cmp_helper(op, lhs, rhs); default: return MP_OBJ_NULL; // op not supported } } mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_SENTINEL) { // load mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported"); } mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(slice.stop - slice.start, NULL)); mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); return MP_OBJ_FROM_PTR(res); } #endif size_t index_value = mp_get_index(self->base.type, self->len, index, false); return self->items[index_value]; } else { return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) { mp_check_self(mp_obj_is_type(self_in, &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); return mp_seq_count_obj(self->items, self->len, value); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count); STATIC mp_obj_t tuple_index(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_type(args[0], &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(args[0]); return mp_seq_index_obj(self->items, self->len, n_args, args); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(tuple_index_obj, 2, 4, tuple_index); STATIC const mp_rom_map_elem_t tuple_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&tuple_count_obj) }, { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&tuple_index_obj) }, }; STATIC MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table); const mp_obj_type_t mp_type_tuple = { { &mp_type_type }, .name = MP_QSTR_tuple, .print = mp_obj_tuple_print, .make_new = mp_obj_tuple_make_new, .unary_op = mp_obj_tuple_unary_op, .binary_op = mp_obj_tuple_binary_op, .subscr = mp_obj_tuple_subscr, .getiter = mp_obj_tuple_getiter, .locals_dict = (mp_obj_dict_t*)&tuple_locals_dict, }; // the zero-length tuple const mp_obj_tuple_t mp_const_empty_tuple_obj = {{&mp_type_tuple}, 0}; mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) { if (n == 0) { return mp_const_empty_tuple; } mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n); o->base.type = &mp_type_tuple; o->len = n; if (items) { for (size_t i = 0; i < n; i++) { o->items[i] = items[i]; } } return MP_OBJ_FROM_PTR(o); } void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) { assert(mp_obj_is_tuple_compatible(self_in)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); *len = self->len; *items = &self->items[0]; } void mp_obj_tuple_del(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); m_del_var(mp_obj_tuple_t, mp_obj_t, self->len, self); } /******************************************************************************/ /* tuple iterator */ typedef struct _mp_obj_tuple_it_t { mp_obj_base_t base; mp_fun_1_t iternext; mp_obj_tuple_t *tuple; size_t cur; } mp_obj_tuple_it_t; STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) { mp_obj_tuple_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->cur < self->tuple->len) { mp_obj_t o_out = self->tuple->items[self->cur]; self->cur += 1; return o_out; } else { return MP_OBJ_STOP_ITERATION; } } mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_tuple_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_tuple_it_t *o = (mp_obj_tuple_it_t*)iter_buf; o->base.type = &mp_type_polymorph_iter; o->iternext = tuple_it_iternext; o->tuple = MP_OBJ_TO_PTR(o_in); o->cur = 0; return MP_OBJ_FROM_PTR(o); } micropython-1.12/py/objtuple.h000066400000000000000000000047271357706137100164610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJTUPLE_H #define MICROPY_INCLUDED_PY_OBJTUPLE_H #include "py/obj.h" typedef struct _mp_obj_tuple_t { mp_obj_base_t base; size_t len; mp_obj_t items[]; } mp_obj_tuple_t; typedef struct _mp_rom_obj_tuple_t { mp_obj_base_t base; size_t len; mp_rom_obj_t items[]; } mp_rom_obj_tuple_t; void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); mp_obj_t mp_obj_tuple_unary_op(mp_unary_op_t op, mp_obj_t self_in); mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs); mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value); mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf); extern const mp_obj_type_t mp_type_attrtuple; #define MP_DEFINE_ATTRTUPLE(tuple_obj_name, fields, nitems, ...) \ const mp_rom_obj_tuple_t tuple_obj_name = { \ .base = {&mp_type_attrtuple}, \ .len = nitems, \ .items = { __VA_ARGS__ , MP_ROM_PTR((void*)fields) } \ } #if MICROPY_PY_COLLECTIONS void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o); #endif mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items); #endif // MICROPY_INCLUDED_PY_OBJTUPLE_H micropython-1.12/py/objtype.c000066400000000000000000001545011357706137100163000ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2018 Damien P. George * Copyright (c) 2014-2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/objtype.h" #include "py/runtime.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_PRINT (0) #define DEBUG_printf(...) (void)0 #endif #define ENABLE_SPECIAL_ACCESSORS \ (MICROPY_PY_DESCRIPTORS || MICROPY_PY_DELATTR_SETATTR || MICROPY_PY_BUILTINS_PROPERTY) #define TYPE_FLAG_IS_SUBCLASSED (0x0001) #define TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); /******************************************************************************/ // instance object STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) { int count = 0; for (;;) { if (type == &mp_type_object) { // Not a "real" type, end search here. return count; } else if (mp_obj_is_native_type(type)) { // Native types don't have parents (at least not from our perspective) so end. *last_native_base = type; return count + 1; } else if (type->parent == NULL) { // No parents so end search here. return count; #if MICROPY_MULTIPLE_INHERITANCE } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) { // Multiple parents, search through them all recursively. const mp_obj_tuple_t *parent_tuple = type->parent; const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len; for (; item < top; ++item) { assert(mp_obj_is_type(*item, &mp_type_type)); const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(*item); count += instance_count_native_bases(bt, last_native_base); } return count; #endif } else { // A single parent, use iteration to continue the search. type = type->parent; } } } // This wrapper function is allows a subclass of a native type to call the // __init__() method (corresponding to type->make_new) of the native type. STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(args[0]); const mp_obj_type_t *native_base = NULL; instance_count_native_bases(self->base.type, &native_base); self->subobj[0] = native_base->make_new(native_base, n_args - 1, 0, args + 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(native_base_init_wrapper_obj, 1, MP_OBJ_FUN_ARGS_MAX, native_base_init_wrapper); #if !MICROPY_CPYTHON_COMPAT STATIC #endif mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *class, const mp_obj_type_t **native_base) { size_t num_native_bases = instance_count_native_bases(class, native_base); assert(num_native_bases < 2); mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, num_native_bases); o->base.type = class; mp_map_init(&o->members, 0); // Initialise the native base-class slot (should be 1 at most) with a valid // object. It doesn't matter which object, so long as it can be uniquely // distinguished from a native class that is initialised. if (num_native_bases != 0) { o->subobj[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj); } return o; } // TODO // This implements depth-first left-to-right MRO, which is not compliant with Python3 MRO // http://python-history.blogspot.com/2010/06/method-resolution-order.html // https://www.python.org/download/releases/2.3/mro/ // // will keep lookup->dest[0]'s value (should be MP_OBJ_NULL on invocation) if attribute // is not found // will set lookup->dest[0] to MP_OBJ_SENTINEL if special method was found in a native // type base via slot id (as specified by lookup->meth_offset). As there can be only one // native base, it's known that it applies to instance->subobj[0]. In most cases, we also // don't need to know which type it was - because instance->subobj[0] is of that type. // The only exception is when object is not yet constructed, then we need to know base // native type to construct its instance->subobj[0] from. But this case is handled via // instance_count_native_bases(), which returns a native base which it saw. struct class_lookup_data { mp_obj_instance_t *obj; qstr attr; size_t meth_offset; mp_obj_t *dest; bool is_type; }; STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_type_t *type) { assert(lookup->dest[0] == MP_OBJ_NULL); assert(lookup->dest[1] == MP_OBJ_NULL); for (;;) { DEBUG_printf("mp_obj_class_lookup: Looking up %s in %s\n", qstr_str(lookup->attr), qstr_str(type->name)); // Optimize special method lookup for native types // This avoids extra method_name => slot lookup. On the other hand, // this should not be applied to class types, as will result in extra // lookup either. if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) { if (*(void**)((char*)type + lookup->meth_offset) != NULL) { DEBUG_printf("mp_obj_class_lookup: Matched special meth slot (off=%d) for %s\n", lookup->meth_offset, qstr_str(lookup->attr)); lookup->dest[0] = MP_OBJ_SENTINEL; return; } } if (type->locals_dict != NULL) { // search locals_dict (the set of methods/attributes) assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now mp_map_t *locals_map = &type->locals_dict->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(lookup->attr), MP_MAP_LOOKUP); if (elem != NULL) { if (lookup->is_type) { // If we look up a class method, we need to return original type for which we // do a lookup, not a (base) type in which we found the class method. const mp_obj_type_t *org_type = (const mp_obj_type_t*)lookup->obj; mp_convert_member_lookup(MP_OBJ_NULL, org_type, elem->value, lookup->dest); } else { mp_obj_instance_t *obj = lookup->obj; mp_obj_t obj_obj; if (obj != NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) { // If we're dealing with native base class, then it applies to native sub-object obj_obj = obj->subobj[0]; } else { obj_obj = MP_OBJ_FROM_PTR(obj); } mp_convert_member_lookup(obj_obj, type, elem->value, lookup->dest); } #if DEBUG_PRINT DEBUG_printf("mp_obj_class_lookup: Returning: "); mp_obj_print_helper(MICROPY_DEBUG_PRINTER, lookup->dest[0], PRINT_REPR); if (lookup->dest[1] != MP_OBJ_NULL) { // Don't try to repr() lookup->dest[1], as we can be called recursively DEBUG_printf(" <%s @%p>", mp_obj_get_type_str(lookup->dest[1]), MP_OBJ_TO_PTR(lookup->dest[1])); } DEBUG_printf("\n"); #endif return; } } // Previous code block takes care about attributes defined in .locals_dict, // but some attributes of native types may be handled using .load_attr method, // so make sure we try to lookup those too. if (lookup->obj != NULL && !lookup->is_type && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) { mp_load_method_maybe(lookup->obj->subobj[0], lookup->attr, lookup->dest); if (lookup->dest[0] != MP_OBJ_NULL) { return; } } // attribute not found, keep searching base classes if (type->parent == NULL) { DEBUG_printf("mp_obj_class_lookup: No more parents\n"); return; #if MICROPY_MULTIPLE_INHERITANCE } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) { const mp_obj_tuple_t *parent_tuple = type->parent; const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len - 1; for (; item < top; ++item) { assert(mp_obj_is_type(*item, &mp_type_type)); mp_obj_type_t *bt = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item); if (bt == &mp_type_object) { // Not a "real" type continue; } mp_obj_class_lookup(lookup, bt); if (lookup->dest[0] != MP_OBJ_NULL) { return; } } // search last base (simple tail recursion elimination) assert(mp_obj_is_type(*item, &mp_type_type)); type = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item); #endif } else { type = type->parent; } if (type == &mp_type_object) { // Not a "real" type return; } } } STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__; mp_obj_t member[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { .obj = self, .attr = meth, .meth_offset = offsetof(mp_obj_type_t, print), .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) { // If there's no __str__, fall back to __repr__ lookup.attr = MP_QSTR___repr__; lookup.meth_offset = 0; mp_obj_class_lookup(&lookup, self->base.type); } if (member[0] == MP_OBJ_SENTINEL) { // Handle Exception subclasses specially if (mp_obj_is_native_exception_instance(self->subobj[0])) { if (kind != PRINT_STR) { mp_print_str(print, qstr_str(self->base.type->name)); } mp_obj_print_helper(print, self->subobj[0], kind | PRINT_EXC_SUBCLASS); } else { mp_obj_print_helper(print, self->subobj[0], kind); } return; } if (member[0] != MP_OBJ_NULL) { mp_obj_t r = mp_call_function_1(member[0], self_in); mp_obj_print_helper(print, r, PRINT_STR); return; } // TODO: CPython prints fully-qualified type name mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self); } mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_instance_type(self)); // look for __new__ function mp_obj_t init_fn[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { .obj = NULL, .attr = MP_QSTR___new__, .meth_offset = offsetof(mp_obj_type_t, make_new), .dest = init_fn, .is_type = false, }; mp_obj_class_lookup(&lookup, self); const mp_obj_type_t *native_base = NULL; mp_obj_instance_t *o; if (init_fn[0] == MP_OBJ_NULL || init_fn[0] == MP_OBJ_SENTINEL) { // Either there is no __new__() method defined or there is a native // constructor. In both cases create a blank instance. o = mp_obj_new_instance(self, &native_base); // Since type->make_new() implements both __new__() and __init__() in // one go, of which the latter may be overridden by the Python subclass, // we defer (see the end of this function) the call of the native // constructor to give a chance for the Python __init__() method to call // said native constructor. } else { // Call Python class __new__ function with all args to create an instance mp_obj_t new_ret; if (n_args == 0 && n_kw == 0) { mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)}; new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2); } else { mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw); args2[0] = MP_OBJ_FROM_PTR(self); memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); new_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2); m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw); } // https://docs.python.org/3.4/reference/datamodel.html#object.__new__ // "If __new__() does not return an instance of cls, then the new // instance's __init__() method will not be invoked." if (mp_obj_get_type(new_ret) != self) { return new_ret; } // The instance returned by __new__() becomes the new object o = MP_OBJ_TO_PTR(new_ret); } // now call Python class __init__ function with all args // This method has a chance to call super().__init__() to construct a // possible native base class. init_fn[0] = init_fn[1] = MP_OBJ_NULL; lookup.obj = o; lookup.attr = MP_QSTR___init__; lookup.meth_offset = 0; mp_obj_class_lookup(&lookup, self); if (init_fn[0] != MP_OBJ_NULL) { mp_obj_t init_ret; if (n_args == 0 && n_kw == 0) { init_ret = mp_call_method_n_kw(0, 0, init_fn); } else { mp_obj_t *args2 = m_new(mp_obj_t, 2 + n_args + 2 * n_kw); args2[0] = init_fn[0]; args2[1] = init_fn[1]; memcpy(args2 + 2, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); init_ret = mp_call_method_n_kw(n_args, n_kw, args2); m_del(mp_obj_t, args2, 2 + n_args + 2 * n_kw); } if (init_ret != mp_const_none) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("__init__() should return None"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); } } } // If the type had a native base that was not explicitly initialised // (constructed) by the Python __init__() method then construct it now. if (native_base != NULL && o->subobj[0] == MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj)) { o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args); } return MP_OBJ_FROM_PTR(o); } // Qstrs for special methods are guaranteed to have a small value, so we use byte // type to represent them. const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = { [MP_UNARY_OP_BOOL] = MP_QSTR___bool__, [MP_UNARY_OP_LEN] = MP_QSTR___len__, [MP_UNARY_OP_HASH] = MP_QSTR___hash__, [MP_UNARY_OP_INT] = MP_QSTR___int__, #if MICROPY_PY_ALL_SPECIAL_METHODS [MP_UNARY_OP_POSITIVE] = MP_QSTR___pos__, [MP_UNARY_OP_NEGATIVE] = MP_QSTR___neg__, [MP_UNARY_OP_INVERT] = MP_QSTR___invert__, [MP_UNARY_OP_ABS] = MP_QSTR___abs__, #endif #if MICROPY_PY_SYS_GETSIZEOF [MP_UNARY_OP_SIZEOF] = MP_QSTR___sizeof__, #endif }; STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_SYS_GETSIZEOF if (MP_UNLIKELY(op == MP_UNARY_OP_SIZEOF)) { // TODO: This doesn't count inherited objects (self->subobj) const mp_obj_type_t *native_base; size_t num_native_bases = instance_count_native_bases(mp_obj_get_type(self_in), &native_base); size_t sz = sizeof(*self) + sizeof(*self->subobj) * num_native_bases + sizeof(*self->members.table) * self->members.alloc; return MP_OBJ_NEW_SMALL_INT(sz); } #endif qstr op_name = mp_unary_op_method_name[op]; /* Still try to lookup native slot if (op_name == 0) { return MP_OBJ_NULL; } */ mp_obj_t member[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { .obj = self, .attr = op_name, .meth_offset = offsetof(mp_obj_type_t, unary_op), .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_SENTINEL) { return mp_unary_op(op, self->subobj[0]); } else if (member[0] != MP_OBJ_NULL) { mp_obj_t val = mp_call_function_1(member[0], self_in); switch (op) { case MP_UNARY_OP_HASH: // __hash__ must return a small int val = MP_OBJ_NEW_SMALL_INT(mp_obj_get_int_truncated(val)); break; case MP_UNARY_OP_INT: // Must return int if (!mp_obj_is_int(val)) { mp_raise_TypeError(NULL); } break; default: // No need to do anything ; } return val; } else { if (op == MP_UNARY_OP_HASH) { lookup.attr = MP_QSTR___eq__; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_NULL) { // https://docs.python.org/3/reference/datamodel.html#object.__hash__ // "User-defined classes have __eq__() and __hash__() methods by default; // with them, all objects compare unequal (except with themselves) and // x.__hash__() returns an appropriate value such that x == y implies // both that x is y and hash(x) == hash(y)." return MP_OBJ_NEW_SMALL_INT((mp_uint_t)self_in); } // "A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None. // When the __hash__() method of a class is None, instances of the class will raise an appropriate TypeError" } return MP_OBJ_NULL; // op not supported } } // Binary-op enum values not listed here will have the default value of 0 in the // table, corresponding to MP_QSTRnull, and are therefore unsupported (a lookup will // fail). They can be added at the expense of code size for the qstr. // Qstrs for special methods are guaranteed to have a small value, so we use byte // type to represent them. const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = { [MP_BINARY_OP_LESS] = MP_QSTR___lt__, [MP_BINARY_OP_MORE] = MP_QSTR___gt__, [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__, [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__, [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__, // MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result [MP_BINARY_OP_CONTAINS] = MP_QSTR___contains__, // If an inplace method is not found a normal method will be used as a fallback [MP_BINARY_OP_INPLACE_ADD] = MP_QSTR___iadd__, [MP_BINARY_OP_INPLACE_SUBTRACT] = MP_QSTR___isub__, #if MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS [MP_BINARY_OP_INPLACE_MULTIPLY] = MP_QSTR___imul__, [MP_BINARY_OP_INPLACE_MAT_MULTIPLY] = MP_QSTR___imatmul__, [MP_BINARY_OP_INPLACE_FLOOR_DIVIDE] = MP_QSTR___ifloordiv__, [MP_BINARY_OP_INPLACE_TRUE_DIVIDE] = MP_QSTR___itruediv__, [MP_BINARY_OP_INPLACE_MODULO] = MP_QSTR___imod__, [MP_BINARY_OP_INPLACE_POWER] = MP_QSTR___ipow__, [MP_BINARY_OP_INPLACE_OR] = MP_QSTR___ior__, [MP_BINARY_OP_INPLACE_XOR] = MP_QSTR___ixor__, [MP_BINARY_OP_INPLACE_AND] = MP_QSTR___iand__, [MP_BINARY_OP_INPLACE_LSHIFT] = MP_QSTR___ilshift__, [MP_BINARY_OP_INPLACE_RSHIFT] = MP_QSTR___irshift__, #endif [MP_BINARY_OP_ADD] = MP_QSTR___add__, [MP_BINARY_OP_SUBTRACT] = MP_QSTR___sub__, #if MICROPY_PY_ALL_SPECIAL_METHODS [MP_BINARY_OP_MULTIPLY] = MP_QSTR___mul__, [MP_BINARY_OP_MAT_MULTIPLY] = MP_QSTR___matmul__, [MP_BINARY_OP_FLOOR_DIVIDE] = MP_QSTR___floordiv__, [MP_BINARY_OP_TRUE_DIVIDE] = MP_QSTR___truediv__, [MP_BINARY_OP_MODULO] = MP_QSTR___mod__, [MP_BINARY_OP_DIVMOD] = MP_QSTR___divmod__, [MP_BINARY_OP_POWER] = MP_QSTR___pow__, [MP_BINARY_OP_OR] = MP_QSTR___or__, [MP_BINARY_OP_XOR] = MP_QSTR___xor__, [MP_BINARY_OP_AND] = MP_QSTR___and__, [MP_BINARY_OP_LSHIFT] = MP_QSTR___lshift__, [MP_BINARY_OP_RSHIFT] = MP_QSTR___rshift__, #endif #if MICROPY_PY_REVERSE_SPECIAL_METHODS [MP_BINARY_OP_REVERSE_ADD] = MP_QSTR___radd__, [MP_BINARY_OP_REVERSE_SUBTRACT] = MP_QSTR___rsub__, #if MICROPY_PY_ALL_SPECIAL_METHODS [MP_BINARY_OP_REVERSE_MULTIPLY] = MP_QSTR___rmul__, [MP_BINARY_OP_REVERSE_MAT_MULTIPLY] = MP_QSTR___rmatmul__, [MP_BINARY_OP_REVERSE_FLOOR_DIVIDE] = MP_QSTR___rfloordiv__, [MP_BINARY_OP_REVERSE_TRUE_DIVIDE] = MP_QSTR___rtruediv__, [MP_BINARY_OP_REVERSE_MODULO] = MP_QSTR___rmod__, [MP_BINARY_OP_REVERSE_POWER] = MP_QSTR___rpow__, [MP_BINARY_OP_REVERSE_OR] = MP_QSTR___ror__, [MP_BINARY_OP_REVERSE_XOR] = MP_QSTR___rxor__, [MP_BINARY_OP_REVERSE_AND] = MP_QSTR___rand__, [MP_BINARY_OP_REVERSE_LSHIFT] = MP_QSTR___rlshift__, [MP_BINARY_OP_REVERSE_RSHIFT] = MP_QSTR___rrshift__, #endif #endif }; STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // Note: For ducktyping, CPython does not look in the instance members or use // __getattr__ or __getattribute__. It only looks in the class dictionary. mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in); retry:; qstr op_name = mp_binary_op_method_name[op]; /* Still try to lookup native slot if (op_name == 0) { return MP_OBJ_NULL; } */ mp_obj_t dest[3] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { .obj = lhs, .attr = op_name, .meth_offset = offsetof(mp_obj_type_t, binary_op), .dest = dest, .is_type = false, }; mp_obj_class_lookup(&lookup, lhs->base.type); mp_obj_t res; if (dest[0] == MP_OBJ_SENTINEL) { res = mp_binary_op(op, lhs->subobj[0], rhs_in); } else if (dest[0] != MP_OBJ_NULL) { dest[2] = rhs_in; res = mp_call_method_n_kw(1, 0, dest); } else { // If this was an inplace method, fallback to normal method // https://docs.python.org/3/reference/datamodel.html#object.__iadd__ : // "If a specific method is not defined, the augmented assignment // falls back to the normal methods." if (op >= MP_BINARY_OP_INPLACE_OR && op <= MP_BINARY_OP_INPLACE_POWER) { op -= MP_BINARY_OP_INPLACE_OR - MP_BINARY_OP_OR; goto retry; } return MP_OBJ_NULL; // op not supported } #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED // NotImplemented means "try other fallbacks (like calling __rop__ // instead of __op__) and if nothing works, raise TypeError". As // MicroPython doesn't implement any fallbacks, signal to raise // TypeError right away. if (res == mp_const_notimplemented) { return MP_OBJ_NULL; // op not supported } #endif return res; } STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // logic: look in instance members then class locals assert(mp_obj_is_instance_type(mp_obj_get_type(self_in))); mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { // object member, always treated as a value dest[0] = elem->value; return; } #if MICROPY_CPYTHON_COMPAT if (attr == MP_QSTR___dict__) { // Create a new dict with a copy of the instance's map items. // This creates, unlike CPython, a 'read-only' __dict__: modifying // it will not result in modifications to the actual instance members. mp_map_t *map = &self->members; mp_obj_t attr_dict = mp_obj_new_dict(map->used); for (size_t i = 0; i < map->alloc; ++i) { if (mp_map_slot_is_filled(map, i)) { mp_obj_dict_store(attr_dict, map->table[i].key, map->table[i].value); } } dest[0] = attr_dict; return; } #endif struct class_lookup_data lookup = { .obj = self, .attr = attr, .meth_offset = 0, .dest = dest, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); mp_obj_t member = dest[0]; if (member != MP_OBJ_NULL) { if (!(self->base.type->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { // Class doesn't have any special accessors to check so return straightaway return; } #if MICROPY_PY_BUILTINS_PROPERTY if (mp_obj_is_type(member, &mp_type_property)) { // object member is a property; delegate the load to the property // Note: This is an optimisation for code size and execution time. // The proper way to do it is have the functionality just below // in a __get__ method of the property object, and then it would // be called by the descriptor code down below. But that way // requires overhead for the nested mp_call's and overhead for // the code. const mp_obj_t *proxy = mp_obj_property_get(member); if (proxy[0] == mp_const_none) { mp_raise_msg(&mp_type_AttributeError, "unreadable attribute"); } else { dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in); } return; } #endif #if MICROPY_PY_DESCRIPTORS // found a class attribute; if it has a __get__ method then call it with the // class instance and class as arguments and return the result // Note that this is functionally correct but very slow: each load_attr // requires an extra mp_load_method_maybe to check for the __get__. mp_obj_t attr_get_method[4]; mp_load_method_maybe(member, MP_QSTR___get__, attr_get_method); if (attr_get_method[0] != MP_OBJ_NULL) { attr_get_method[2] = self_in; attr_get_method[3] = MP_OBJ_FROM_PTR(mp_obj_get_type(self_in)); dest[0] = mp_call_method_n_kw(2, 0, attr_get_method); } #endif return; } // try __getattr__ if (attr != MP_QSTR___getattr__) { #if MICROPY_PY_DELATTR_SETATTR // If the requested attr is __setattr__/__delattr__ then don't delegate the lookup // to __getattr__. If we followed CPython's behaviour then __setattr__/__delattr__ // would have already been found in the "object" base class. if (attr == MP_QSTR___setattr__ || attr == MP_QSTR___delattr__) { return; } #endif mp_obj_t dest2[3]; mp_load_method_maybe(self_in, MP_QSTR___getattr__, dest2); if (dest2[0] != MP_OBJ_NULL) { // __getattr__ exists, call it and return its result dest2[2] = MP_OBJ_NEW_QSTR(attr); dest[0] = mp_call_method_n_kw(1, 0, dest2); return; } } } STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); if (!(self->base.type->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { // Class doesn't have any special accessors so skip their checks goto skip_special_accessors; } #if MICROPY_PY_BUILTINS_PROPERTY || MICROPY_PY_DESCRIPTORS // With property and/or descriptors enabled we need to do a lookup // first in the class dict for the attribute to see if the store should // be delegated. mp_obj_t member[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { .obj = self, .attr = attr, .meth_offset = 0, .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] != MP_OBJ_NULL) { #if MICROPY_PY_BUILTINS_PROPERTY if (mp_obj_is_type(member[0], &mp_type_property)) { // attribute exists and is a property; delegate the store/delete // Note: This is an optimisation for code size and execution time. // The proper way to do it is have the functionality just below in // a __set__/__delete__ method of the property object, and then it // would be called by the descriptor code down below. But that way // requires overhead for the nested mp_call's and overhead for // the code. const mp_obj_t *proxy = mp_obj_property_get(member[0]); mp_obj_t dest[2] = {self_in, value}; if (value == MP_OBJ_NULL) { // delete attribute if (proxy[2] == mp_const_none) { // TODO better error message? return false; } else { mp_call_function_n_kw(proxy[2], 1, 0, dest); return true; } } else { // store attribute if (proxy[1] == mp_const_none) { // TODO better error message? return false; } else { mp_call_function_n_kw(proxy[1], 2, 0, dest); return true; } } } #endif #if MICROPY_PY_DESCRIPTORS // found a class attribute; if it has a __set__/__delete__ method then // call it with the class instance (and value) as arguments if (value == MP_OBJ_NULL) { // delete attribute mp_obj_t attr_delete_method[3]; mp_load_method_maybe(member[0], MP_QSTR___delete__, attr_delete_method); if (attr_delete_method[0] != MP_OBJ_NULL) { attr_delete_method[2] = self_in; mp_call_method_n_kw(1, 0, attr_delete_method); return true; } } else { // store attribute mp_obj_t attr_set_method[4]; mp_load_method_maybe(member[0], MP_QSTR___set__, attr_set_method); if (attr_set_method[0] != MP_OBJ_NULL) { attr_set_method[2] = self_in; attr_set_method[3] = value; mp_call_method_n_kw(2, 0, attr_set_method); return true; } } #endif } #endif #if MICROPY_PY_DELATTR_SETATTR if (value == MP_OBJ_NULL) { // delete attribute // try __delattr__ first mp_obj_t attr_delattr_method[3]; mp_load_method_maybe(self_in, MP_QSTR___delattr__, attr_delattr_method); if (attr_delattr_method[0] != MP_OBJ_NULL) { // __delattr__ exists, so call it attr_delattr_method[2] = MP_OBJ_NEW_QSTR(attr); mp_call_method_n_kw(1, 0, attr_delattr_method); return true; } } else { // store attribute // try __setattr__ first mp_obj_t attr_setattr_method[4]; mp_load_method_maybe(self_in, MP_QSTR___setattr__, attr_setattr_method); if (attr_setattr_method[0] != MP_OBJ_NULL) { // __setattr__ exists, so call it attr_setattr_method[2] = MP_OBJ_NEW_QSTR(attr); attr_setattr_method[3] = value; mp_call_method_n_kw(2, 0, attr_setattr_method); return true; } } #endif skip_special_accessors: if (value == MP_OBJ_NULL) { // delete attribute mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND); return elem != NULL; } else { // store attribute mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; return true; } } STATIC void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { mp_obj_instance_load_attr(self_in, attr, dest); } else { if (mp_obj_instance_store_attr(self_in, attr, dest[1])) { dest[0] = MP_OBJ_NULL; // indicate success } } } STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t member[4] = {MP_OBJ_NULL, MP_OBJ_NULL, index, value}; struct class_lookup_data lookup = { .obj = self, .meth_offset = offsetof(mp_obj_type_t, subscr), .dest = member, .is_type = false, }; if (value == MP_OBJ_NULL) { // delete item lookup.attr = MP_QSTR___delitem__; } else if (value == MP_OBJ_SENTINEL) { // load item lookup.attr = MP_QSTR___getitem__; } else { // store item lookup.attr = MP_QSTR___setitem__; } mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_SENTINEL) { return mp_obj_subscr(self->subobj[0], index, value); } else if (member[0] != MP_OBJ_NULL) { size_t n_args = value == MP_OBJ_NULL || value == MP_OBJ_SENTINEL ? 1 : 2; mp_obj_t ret = mp_call_method_n_kw(n_args, 0, member); if (value == MP_OBJ_SENTINEL) { return ret; } else { return mp_const_none; } } else { return MP_OBJ_NULL; // op not supported } } STATIC mp_obj_t mp_obj_instance_get_call(mp_obj_t self_in, mp_obj_t *member) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR___call__, .meth_offset = offsetof(mp_obj_type_t, call), .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); return member[0]; } bool mp_obj_instance_is_callable(mp_obj_t self_in) { mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL}; return mp_obj_instance_get_call(self_in, member) != MP_OBJ_NULL; } mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL}; mp_obj_t call = mp_obj_instance_get_call(self_in, member); if (call == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object not callable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object isn't callable", mp_obj_get_type_str(self_in))); } } mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); if (call == MP_OBJ_SENTINEL) { return mp_call_function_n_kw(self->subobj[0], n_args, n_kw, args); } return mp_call_method_self_n_kw(member[0], member[1], n_args, n_kw, args); } STATIC mp_obj_t instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t member[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR___iter__, .meth_offset = offsetof(mp_obj_type_t, getiter), .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_NULL) { return MP_OBJ_NULL; } else if (member[0] == MP_OBJ_SENTINEL) { mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); return type->getiter(self->subobj[0], iter_buf); } else { return mp_call_method_n_kw(0, 0, member); } } STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t member[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { .obj = self, .attr = MP_QSTR_, // don't actually look for a method .meth_offset = offsetof(mp_obj_type_t, buffer_p.get_buffer), .dest = member, .is_type = false, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_SENTINEL) { mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); return type->buffer_p.get_buffer(self->subobj[0], bufinfo, flags); } else { return 1; // object does not support buffer protocol } } /******************************************************************************/ // type object // - the struct is mp_obj_type_t and is defined in obj.h so const types can be made // - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object // - creating a new class (a new type) creates a new mp_obj_type_t #if ENABLE_SPECIAL_ACCESSORS STATIC bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { #if MICROPY_PY_DELATTR_SETATTR if (key == MP_OBJ_NEW_QSTR(MP_QSTR___setattr__) || key == MP_OBJ_NEW_QSTR(MP_QSTR___delattr__)) { return true; } #endif #if MICROPY_PY_BUILTINS_PROPERTY if (mp_obj_is_type(value, &mp_type_property)) { return true; } #endif #if MICROPY_PY_DESCRIPTORS static const uint8_t to_check[] = { MP_QSTR___get__, MP_QSTR___set__, MP_QSTR___delete__, }; for (size_t i = 0; i < MP_ARRAY_SIZE(to_check); ++i) { mp_obj_t dest_temp[2]; mp_load_method_protected(value, to_check[i], dest_temp, true); if (dest_temp[0] != MP_OBJ_NULL) { return true; } } #endif return false; } #endif STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->name); } STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 1, 3, false); switch (n_args) { case 1: return MP_OBJ_FROM_PTR(mp_obj_get_type(args[0])); case 3: // args[0] = name // args[1] = bases tuple // args[2] = locals dict return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]); default: mp_raise_TypeError("type takes 1 or 3 arguments"); } } STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { // instantiate an instance of a class mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); if (self->make_new == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("cannot create instance"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%q' instances", self->name)); } } // make new instance mp_obj_t o = self->make_new(self, n_args, n_kw, args); // return new instance return o; } STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { assert(mp_obj_is_type(self_in, &mp_type_type)); mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); if (dest[0] == MP_OBJ_NULL) { // load attribute #if MICROPY_CPYTHON_COMPAT if (attr == MP_QSTR___name__) { dest[0] = MP_OBJ_NEW_QSTR(self->name); return; } if (attr == MP_QSTR___bases__) { if (self == &mp_type_object) { dest[0] = mp_const_empty_tuple; return; } mp_obj_t parent_obj = self->parent ? MP_OBJ_FROM_PTR(self->parent) : MP_OBJ_FROM_PTR(&mp_type_object); #if MICROPY_MULTIPLE_INHERITANCE if (mp_obj_is_type(parent_obj, &mp_type_tuple)) { dest[0] = parent_obj; return; } #endif dest[0] = mp_obj_new_tuple(1, &parent_obj); return; } #endif struct class_lookup_data lookup = { .obj = (mp_obj_instance_t*)self, .attr = attr, .meth_offset = 0, .dest = dest, .is_type = true, }; mp_obj_class_lookup(&lookup, self); } else { // delete/store attribute if (self->locals_dict != NULL) { assert(self->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now mp_map_t *locals_map = &self->locals_dict->map; if (locals_map->is_fixed) { // can't apply delete/store to a fixed map return; } if (dest[1] == MP_OBJ_NULL) { // delete attribute mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND); if (elem != NULL) { dest[0] = MP_OBJ_NULL; // indicate success } } else { #if ENABLE_SPECIAL_ACCESSORS // Check if we add any special accessor methods with this store if (!(self->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { if (check_for_special_accessors(MP_OBJ_NEW_QSTR(attr), dest[1])) { if (self->flags & TYPE_FLAG_IS_SUBCLASSED) { // This class is already subclassed so can't have special accessors added mp_raise_msg(&mp_type_AttributeError, "can't add special method to already-subclassed class"); } self->flags |= TYPE_FLAG_HAS_SPECIAL_ACCESSORS; } } #endif // store attribute mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); elem->value = dest[1]; dest[0] = MP_OBJ_NULL; // indicate success } } } } const mp_obj_type_t mp_type_type = { { &mp_type_type }, .name = MP_QSTR_type, .print = type_print, .make_new = type_make_new, .call = type_call, .unary_op = mp_generic_unary_op, .attr = type_attr, }; mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { // Verify input objects have expected type if (!mp_obj_is_type(bases_tuple, &mp_type_tuple)) { mp_raise_TypeError(NULL); } if (!mp_obj_is_type(locals_dict, &mp_type_dict)) { mp_raise_TypeError(NULL); } // TODO might need to make a copy of locals_dict; at least that's how CPython does it // Basic validation of base classes uint16_t base_flags = 0; size_t bases_len; mp_obj_t *bases_items; mp_obj_tuple_get(bases_tuple, &bases_len, &bases_items); for (size_t i = 0; i < bases_len; i++) { if (!mp_obj_is_type(bases_items[i], &mp_type_type)) { mp_raise_TypeError(NULL); } mp_obj_type_t *t = MP_OBJ_TO_PTR(bases_items[i]); // TODO: Verify with CPy, tested on function type if (t->make_new == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("type isn't an acceptable base type"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "type '%q' isn't an acceptable base type", t->name)); } } #if ENABLE_SPECIAL_ACCESSORS if (mp_obj_is_instance_type(t)) { t->flags |= TYPE_FLAG_IS_SUBCLASSED; base_flags |= t->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS; } #endif } mp_obj_type_t *o = m_new0(mp_obj_type_t, 1); o->base.type = &mp_type_type; o->flags = base_flags; o->name = name; o->print = instance_print; o->make_new = mp_obj_instance_make_new; o->call = mp_obj_instance_call; o->unary_op = instance_unary_op; o->binary_op = instance_binary_op; o->attr = mp_obj_instance_attr; o->subscr = instance_subscr; o->getiter = instance_getiter; //o->iternext = ; not implemented o->buffer_p.get_buffer = instance_get_buffer; if (bases_len > 0) { // Inherit protocol from a base class. This allows to define an // abstract base class which would translate C-level protocol to // Python method calls, and any subclass inheriting from it will // support this feature. o->protocol = ((mp_obj_type_t*)MP_OBJ_TO_PTR(bases_items[0]))->protocol; if (bases_len >= 2) { #if MICROPY_MULTIPLE_INHERITANCE o->parent = MP_OBJ_TO_PTR(bases_tuple); #else mp_raise_NotImplementedError("multiple inheritance not supported"); #endif } else { o->parent = MP_OBJ_TO_PTR(bases_items[0]); } } o->locals_dict = MP_OBJ_TO_PTR(locals_dict); #if ENABLE_SPECIAL_ACCESSORS // Check if the class has any special accessor methods if (!(o->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { for (size_t i = 0; i < o->locals_dict->map.alloc; i++) { if (mp_map_slot_is_filled(&o->locals_dict->map, i)) { const mp_map_elem_t *elem = &o->locals_dict->map.table[i]; if (check_for_special_accessors(elem->key, elem->value)) { o->flags |= TYPE_FLAG_HAS_SPECIAL_ACCESSORS; break; } } } } #endif const mp_obj_type_t *native_base; size_t num_native_bases = instance_count_native_bases(o, &native_base); if (num_native_bases > 1) { mp_raise_TypeError("multiple bases have instance lay-out conflict"); } mp_map_t *locals_map = &o->locals_dict->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP); if (elem != NULL) { // __new__ slot exists; check if it is a function if (mp_obj_is_fun(elem->value)) { // __new__ is a function, wrap it in a staticmethod decorator elem->value = static_class_method_make_new(&mp_type_staticmethod, 1, 0, &elem->value); } } return MP_OBJ_FROM_PTR(o); } /******************************************************************************/ // super object typedef struct _mp_obj_super_t { mp_obj_base_t base; mp_obj_t type; mp_obj_t obj; } mp_obj_super_t; STATIC void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in); mp_print_str(print, "type, PRINT_STR); mp_print_str(print, ", "); mp_obj_print_helper(print, self->obj, PRINT_STR); mp_print_str(print, ">"); } STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; // 0 arguments are turned into 2 in the compiler // 1 argument is not yet implemented mp_arg_check_num(n_args, n_kw, 2, 2, false); if (!mp_obj_is_type(args[0], &mp_type_type)) { mp_raise_TypeError(NULL); } mp_obj_super_t *o = m_new_obj(mp_obj_super_t); *o = (mp_obj_super_t){{type_in}, args[0], args[1]}; return MP_OBJ_FROM_PTR(o); } STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } assert(mp_obj_is_type(self_in, &mp_type_super)); mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in); assert(mp_obj_is_type(self->type, &mp_type_type)); mp_obj_type_t *type = MP_OBJ_TO_PTR(self->type); struct class_lookup_data lookup = { .obj = MP_OBJ_TO_PTR(self->obj), .attr = attr, .meth_offset = 0, .dest = dest, .is_type = false, }; // Allow a call super().__init__() to reach any native base classes if (attr == MP_QSTR___init__) { lookup.meth_offset = offsetof(mp_obj_type_t, make_new); } if (type->parent == NULL) { // no parents, do nothing #if MICROPY_MULTIPLE_INHERITANCE } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) { const mp_obj_tuple_t *parent_tuple = type->parent; size_t len = parent_tuple->len; const mp_obj_t *items = parent_tuple->items; for (size_t i = 0; i < len; i++) { assert(mp_obj_is_type(items[i], &mp_type_type)); if (MP_OBJ_TO_PTR(items[i]) == &mp_type_object) { // The "object" type will be searched at the end of this function, // and we don't want to lookup native methods in object. continue; } mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i])); if (dest[0] != MP_OBJ_NULL) { break; } } #endif } else if (type->parent != &mp_type_object) { mp_obj_class_lookup(&lookup, type->parent); } if (dest[0] != MP_OBJ_NULL) { if (dest[0] == MP_OBJ_SENTINEL) { // Looked up native __init__ so defer to it dest[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj); dest[1] = self->obj; } return; } // Reset meth_offset so we don't look up any native methods in object, // because object never takes up the native base-class slot. lookup.meth_offset = 0; mp_obj_class_lookup(&lookup, &mp_type_object); } const mp_obj_type_t mp_type_super = { { &mp_type_type }, .name = MP_QSTR_super, .print = super_print, .make_new = super_make_new, .attr = super_attr, }; void mp_load_super_method(qstr attr, mp_obj_t *dest) { mp_obj_super_t super = {{&mp_type_super}, dest[1], dest[2]}; mp_load_method(MP_OBJ_FROM_PTR(&super), attr, dest); } /******************************************************************************/ // subclassing and built-ins specific to types // object and classinfo should be type objects // (but the function will fail gracefully if they are not) bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { for (;;) { if (object == classinfo) { return true; } // not equivalent classes, keep searching base classes // object should always be a type object, but just return false if it's not if (!mp_obj_is_type(object, &mp_type_type)) { return false; } const mp_obj_type_t *self = MP_OBJ_TO_PTR(object); if (self->parent == NULL) { // type has no parents return false; #if MICROPY_MULTIPLE_INHERITANCE } else if (((mp_obj_base_t*)self->parent)->type == &mp_type_tuple) { // get the base objects (they should be type objects) const mp_obj_tuple_t *parent_tuple = self->parent; const mp_obj_t *item = parent_tuple->items; const mp_obj_t *top = item + parent_tuple->len - 1; // iterate through the base objects for (; item < top; ++item) { if (mp_obj_is_subclass_fast(*item, classinfo)) { return true; } } // search last base (simple tail recursion elimination) object = *item; #endif } else { // type has 1 parent object = MP_OBJ_FROM_PTR(self->parent); } } } STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { size_t len; mp_obj_t *items; if (mp_obj_is_type(classinfo, &mp_type_type)) { len = 1; items = &classinfo; } else if (mp_obj_is_type(classinfo, &mp_type_tuple)) { mp_obj_tuple_get(classinfo, &len, &items); } else { mp_raise_TypeError("issubclass() arg 2 must be a class or a tuple of classes"); } for (size_t i = 0; i < len; i++) { // We explicitly check for 'object' here since no-one explicitly derives from it if (items[i] == MP_OBJ_FROM_PTR(&mp_type_object) || mp_obj_is_subclass_fast(object, items[i])) { return mp_const_true; } } return mp_const_false; } STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { if (!mp_obj_is_type(object, &mp_type_type)) { mp_raise_TypeError("issubclass() arg 1 must be a class"); } return mp_obj_is_subclass(object, classinfo); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass); STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) { return mp_obj_is_subclass(MP_OBJ_FROM_PTR(mp_obj_get_type(object)), classinfo); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance); mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type) { mp_obj_type_t *self_type = mp_obj_get_type(self_in); if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self_type), native_type)) { return MP_OBJ_NULL; } mp_obj_instance_t *self = (mp_obj_instance_t*)MP_OBJ_TO_PTR(self_in); return self->subobj[0]; } /******************************************************************************/ // staticmethod and classmethod types (probably should go in a different file) STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(self == &mp_type_staticmethod || self == &mp_type_classmethod); mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t); *o = (mp_obj_static_class_method_t){{self}, args[0]}; return MP_OBJ_FROM_PTR(o); } const mp_obj_type_t mp_type_staticmethod = { { &mp_type_type }, .name = MP_QSTR_staticmethod, .make_new = static_class_method_make_new, }; const mp_obj_type_t mp_type_classmethod = { { &mp_type_type }, .name = MP_QSTR_classmethod, .make_new = static_class_method_make_new, }; micropython-1.12/py/objtype.h000066400000000000000000000045431357706137100163050ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_OBJTYPE_H #define MICROPY_INCLUDED_PY_OBJTYPE_H #include "py/obj.h" // instance object // creating an instance of a class makes one of these objects typedef struct _mp_obj_instance_t { mp_obj_base_t base; mp_map_t members; mp_obj_t subobj[]; // TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them } mp_obj_instance_t; #if MICROPY_CPYTHON_COMPAT // this is needed for object.__new__ mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *cls, const mp_obj_type_t **native_base); #endif // these need to be exposed so mp_obj_is_callable can work correctly bool mp_obj_instance_is_callable(mp_obj_t self_in); mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); #define mp_obj_is_instance_type(type) ((type)->make_new == mp_obj_instance_make_new) #define mp_obj_is_native_type(type) ((type)->make_new != mp_obj_instance_make_new) // this needs to be exposed for the above macros to work correctly mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); #endif // MICROPY_INCLUDED_PY_OBJTYPE_H micropython-1.12/py/objzip.c000066400000000000000000000052001357706137100161100ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objtuple.h" #include "py/runtime.h" typedef struct _mp_obj_zip_t { mp_obj_base_t base; size_t n_iters; mp_obj_t iters[]; } mp_obj_zip_t; STATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false); mp_obj_zip_t *o = m_new_obj_var(mp_obj_zip_t, mp_obj_t, n_args); o->base.type = type; o->n_iters = n_args; for (size_t i = 0; i < n_args; i++) { o->iters[i] = mp_getiter(args[i], NULL); } return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t zip_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_zip)); mp_obj_zip_t *self = MP_OBJ_TO_PTR(self_in); if (self->n_iters == 0) { return MP_OBJ_STOP_ITERATION; } mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->n_iters, NULL)); for (size_t i = 0; i < self->n_iters; i++) { mp_obj_t next = mp_iternext(self->iters[i]); if (next == MP_OBJ_STOP_ITERATION) { mp_obj_tuple_del(MP_OBJ_FROM_PTR(tuple)); return MP_OBJ_STOP_ITERATION; } tuple->items[i] = next; } return MP_OBJ_FROM_PTR(tuple); } const mp_obj_type_t mp_type_zip = { { &mp_type_type }, .name = MP_QSTR_zip, .make_new = zip_make_new, .getiter = mp_identity_getiter, .iternext = zip_iternext, }; micropython-1.12/py/opmethods.c000066400000000000000000000042751357706137100166300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/obj.h" #include "py/builtin.h" STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { mp_obj_type_t *type = mp_obj_get_type(self_in); return type->subscr(self_in, key_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem); STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) { mp_obj_type_t *type = mp_obj_get_type(self_in); return type->subscr(self_in, key_in, value_in); } MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem); STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) { mp_obj_type_t *type = mp_obj_get_type(self_in); return type->subscr(self_in, key_in, MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_delitem_obj, op_delitem); STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_type_t *type = mp_obj_get_type(lhs_in); return type->binary_op(MP_BINARY_OP_CONTAINS, lhs_in, rhs_in); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains); micropython-1.12/py/parse.c000066400000000000000000001321301357706137100157300ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include // for ssize_t #include #include #include "py/lexer.h" #include "py/parse.h" #include "py/parsenum.h" #include "py/runtime.h" #include "py/objint.h" #include "py/objstr.h" #include "py/builtin.h" #if MICROPY_ENABLE_COMPILER #define RULE_ACT_ARG_MASK (0x0f) #define RULE_ACT_KIND_MASK (0x30) #define RULE_ACT_ALLOW_IDENT (0x40) #define RULE_ACT_ADD_BLANK (0x80) #define RULE_ACT_OR (0x10) #define RULE_ACT_AND (0x20) #define RULE_ACT_LIST (0x30) #define RULE_ARG_KIND_MASK (0xf000) #define RULE_ARG_ARG_MASK (0x0fff) #define RULE_ARG_TOK (0x1000) #define RULE_ARG_RULE (0x2000) #define RULE_ARG_OPT_RULE (0x3000) // (un)comment to use rule names; for debugging //#define USE_RULE_NAME (1) enum { // define rules with a compile function #define DEF_RULE(rule, comp, kind, ...) RULE_##rule, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC RULE_const_object, // special node for a constant, generic Python object // define rules without a compile function #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) RULE_##rule, #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC }; // Define an array of actions corresponding to each rule STATIC const uint8_t rule_act_table[] = { #define or(n) (RULE_ACT_OR | n) #define and(n) (RULE_ACT_AND | n) #define and_ident(n) (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT) #define and_blank(n) (RULE_ACT_AND | n | RULE_ACT_ADD_BLANK) #define one_or_more (RULE_ACT_LIST | 2) #define list (RULE_ACT_LIST | 1) #define list_with_end (RULE_ACT_LIST | 3) #define DEF_RULE(rule, comp, kind, ...) kind, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC 0, // RULE_const_object #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) kind, #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC #undef or #undef and #undef and_ident #undef and_blank #undef one_or_more #undef list #undef list_with_end }; // Define the argument data for each rule, as a combined array STATIC const uint16_t rule_arg_combined_table[] = { #define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t) #define rule(r) (RULE_ARG_RULE | RULE_##r) #define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r) #define DEF_RULE(rule, comp, kind, ...) __VA_ARGS__, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) __VA_ARGS__, #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC #undef tok #undef rule #undef opt_rule }; // Macro to create a list of N identifiers where N is the number of variable arguments to the macro #define RULE_EXPAND(x) x #define RULE_PADDING(rule, ...) RULE_PADDING2(rule, __VA_ARGS__, RULE_PADDING_IDS(rule)) #define RULE_PADDING2(rule, ...) RULE_EXPAND(RULE_PADDING3(rule, __VA_ARGS__)) #define RULE_PADDING3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) __VA_ARGS__ #define RULE_PADDING_IDS(r) PAD13_##r, PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r, // Use an enum to create constants specifying how much room a rule takes in rule_arg_combined_table enum { #define DEF_RULE(rule, comp, kind, ...) RULE_PADDING(rule, __VA_ARGS__) #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) RULE_PADDING(rule, __VA_ARGS__) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC }; // Macro to compute the start of a rule in rule_arg_combined_table #define RULE_ARG_OFFSET(rule, ...) RULE_ARG_OFFSET2(rule, __VA_ARGS__, RULE_ARG_OFFSET_IDS(rule)) #define RULE_ARG_OFFSET2(rule, ...) RULE_EXPAND(RULE_ARG_OFFSET3(rule, __VA_ARGS__)) #define RULE_ARG_OFFSET3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) _14 #define RULE_ARG_OFFSET_IDS(r) PAD13_##r, PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r, PAD0_##r, // Use the above enum values to create a table of offsets for each rule's arg // data, which indexes rule_arg_combined_table. The offsets require 9 bits of // storage but only the lower 8 bits are stored here. The 9th bit is computed // in get_rule_arg using the FIRST_RULE_WITH_OFFSET_ABOVE_255 constant. STATIC const uint8_t rule_arg_offset_table[] = { #define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC 0, // RULE_const_object #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff, #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC }; // Define a constant that's used to determine the 9th bit of the values in rule_arg_offset_table static const size_t FIRST_RULE_WITH_OFFSET_ABOVE_255 = #define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule : #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule : #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC 0; #if USE_RULE_NAME // Define an array of rule names corresponding to each rule STATIC const char *const rule_name_table[] = { #define DEF_RULE(rule, comp, kind, ...) #rule, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC "", // RULE_const_object #define DEF_RULE(rule, comp, kind, ...) #define DEF_RULE_NC(rule, kind, ...) #rule, #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC }; #endif typedef struct _rule_stack_t { size_t src_line : 8 * sizeof(size_t) - 8; // maximum bits storing source line number size_t rule_id : 8; // this must be large enough to fit largest rule number size_t arg_i; // this dictates the maximum nodes in a "list" of things } rule_stack_t; typedef struct _mp_parse_chunk_t { size_t alloc; union { size_t used; struct _mp_parse_chunk_t *next; } union_; byte data[]; } mp_parse_chunk_t; typedef struct _parser_t { size_t rule_stack_alloc; size_t rule_stack_top; rule_stack_t *rule_stack; size_t result_stack_alloc; size_t result_stack_top; mp_parse_node_t *result_stack; mp_lexer_t *lexer; mp_parse_tree_t tree; mp_parse_chunk_t *cur_chunk; #if MICROPY_COMP_CONST mp_map_t consts; #endif } parser_t; STATIC const uint16_t *get_rule_arg(uint8_t r_id) { size_t off = rule_arg_offset_table[r_id]; if (r_id >= FIRST_RULE_WITH_OFFSET_ABOVE_255) { off |= 0x100; } return &rule_arg_combined_table[off]; } STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) { // use a custom memory allocator to store parse nodes sequentially in large chunks mp_parse_chunk_t *chunk = parser->cur_chunk; if (chunk != NULL && chunk->union_.used + num_bytes > chunk->alloc) { // not enough room at end of previously allocated chunk so try to grow mp_parse_chunk_t *new_data = (mp_parse_chunk_t*)m_renew_maybe(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc, sizeof(mp_parse_chunk_t) + chunk->alloc + num_bytes, false); if (new_data == NULL) { // could not grow existing memory; shrink it to fit previous (void)m_renew_maybe(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc, sizeof(mp_parse_chunk_t) + chunk->union_.used, false); chunk->alloc = chunk->union_.used; chunk->union_.next = parser->tree.chunk; parser->tree.chunk = chunk; chunk = NULL; } else { // could grow existing memory chunk->alloc += num_bytes; } } if (chunk == NULL) { // no previous chunk, allocate a new chunk size_t alloc = MICROPY_ALLOC_PARSE_CHUNK_INIT; if (alloc < num_bytes) { alloc = num_bytes; } chunk = (mp_parse_chunk_t*)m_new(byte, sizeof(mp_parse_chunk_t) + alloc); chunk->alloc = alloc; chunk->union_.used = 0; parser->cur_chunk = chunk; } byte *ret = chunk->data + chunk->union_.used; chunk->union_.used += num_bytes; return ret; } STATIC void push_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t arg_i) { if (parser->rule_stack_top >= parser->rule_stack_alloc) { rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC); parser->rule_stack = rs; parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC; } rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++]; rs->src_line = src_line; rs->rule_id = rule_id; rs->arg_i = arg_i; } STATIC void push_rule_from_arg(parser_t *parser, size_t arg) { assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE); size_t rule_id = arg & RULE_ARG_ARG_MASK; push_rule(parser, parser->lexer->tok_line, rule_id, 0); } STATIC uint8_t pop_rule(parser_t *parser, size_t *arg_i, size_t *src_line) { parser->rule_stack_top -= 1; uint8_t rule_id = parser->rule_stack[parser->rule_stack_top].rule_id; *arg_i = parser->rule_stack[parser->rule_stack_top].arg_i; *src_line = parser->rule_stack[parser->rule_stack_top].src_line; return rule_id; } bool mp_parse_node_is_const_false(mp_parse_node_t pn) { return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0); } bool mp_parse_node_is_const_true(mp_parse_node_t pn) { return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) != 0); } bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) { if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { *o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn)); return true; } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D // nodes are 32-bit pointers, but need to extract 64-bit object *o = (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32); #else *o = (mp_obj_t)pns->nodes[0]; #endif return mp_obj_is_int(*o); } else { return false; } } int mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes) { if (MP_PARSE_NODE_IS_NULL(*pn)) { *nodes = NULL; return 0; } else if (MP_PARSE_NODE_IS_LEAF(*pn)) { *nodes = pn; return 1; } else { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn); if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) { *nodes = pn; return 1; } else { *nodes = pns->nodes; return MP_PARSE_NODE_STRUCT_NUM_NODES(pns); } } } #if MICROPY_DEBUG_PRINTERS void mp_parse_node_print(mp_parse_node_t pn, size_t indent) { if (MP_PARSE_NODE_IS_STRUCT(pn)) { printf("[% 4d] ", (int)((mp_parse_node_struct_t*)pn)->source_line); } else { printf(" "); } for (size_t i = 0; i < indent; i++) { printf(" "); } if (MP_PARSE_NODE_IS_NULL(pn)) { printf("NULL\n"); } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn); printf("int(" INT_FMT ")\n", arg); } else if (MP_PARSE_NODE_IS_LEAF(pn)) { uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn); switch (MP_PARSE_NODE_LEAF_KIND(pn)) { case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break; case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break; case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break; default: assert(MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN); printf("tok(%u)\n", (uint)arg); break; } } else { // node must be a mp_parse_node_struct_t mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) { #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D printf("literal const(%016llx)\n", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32)); #else printf("literal const(%p)\n", (mp_obj_t)pns->nodes[0]); #endif } else { size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); #if USE_RULE_NAME printf("%s(%u) (n=%u)\n", rule_name_table[MP_PARSE_NODE_STRUCT_KIND(pns)], (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n); #else printf("rule(%u) (n=%u)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n); #endif for (size_t i = 0; i < n; i++) { mp_parse_node_print(pns->nodes[i], indent + 2); } } } } #endif // MICROPY_DEBUG_PRINTERS /* STATIC void result_stack_show(parser_t *parser) { printf("result stack, most recent first\n"); for (ssize_t i = parser->result_stack_top - 1; i >= 0; i--) { mp_parse_node_print(parser->result_stack[i], 0); } } */ STATIC mp_parse_node_t pop_result(parser_t *parser) { assert(parser->result_stack_top > 0); return parser->result_stack[--parser->result_stack_top]; } STATIC mp_parse_node_t peek_result(parser_t *parser, size_t pos) { assert(parser->result_stack_top > pos); return parser->result_stack[parser->result_stack_top - 1 - pos]; } STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) { if (parser->result_stack_top >= parser->result_stack_alloc) { mp_parse_node_t *stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC); parser->result_stack = stack; parser->result_stack_alloc += MICROPY_ALLOC_PARSE_RESULT_INC; } parser->result_stack[parser->result_stack_top++] = pn; } STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) { mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t)); pn->source_line = src_line; #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D // nodes are 32-bit pointers, but need to store 64-bit object pn->kind_num_nodes = RULE_const_object | (2 << 8); pn->nodes[0] = (uint64_t)obj; pn->nodes[1] = (uint64_t)obj >> 32; #else pn->kind_num_nodes = RULE_const_object | (1 << 8); pn->nodes[0] = (uintptr_t)obj; #endif return (mp_parse_node_t)pn; } STATIC mp_parse_node_t mp_parse_node_new_small_int_checked(parser_t *parser, mp_obj_t o_val) { (void)parser; mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_val); #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D // A parse node is only 32-bits and the small-int value must fit in 31-bits if (((val ^ (val << 1)) & 0xffffffff80000000) != 0) { return make_node_const_object(parser, 0, o_val); } #endif return mp_parse_node_new_small_int(val); } STATIC void push_result_token(parser_t *parser, uint8_t rule_id) { mp_parse_node_t pn; mp_lexer_t *lex = parser->lexer; if (lex->tok_kind == MP_TOKEN_NAME) { qstr id = qstr_from_strn(lex->vstr.buf, lex->vstr.len); #if MICROPY_COMP_CONST // if name is a standalone identifier, look it up in the table of dynamic constants mp_map_elem_t *elem; if (rule_id == RULE_atom && (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) { if (mp_obj_is_small_int(elem->value)) { pn = mp_parse_node_new_small_int_checked(parser, elem->value); } else { pn = make_node_const_object(parser, lex->tok_line, elem->value); } } else { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id); } #else (void)rule_id; pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id); #endif } else if (lex->tok_kind == MP_TOKEN_INTEGER) { mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex); if (mp_obj_is_small_int(o)) { pn = mp_parse_node_new_small_int_checked(parser, o); } else { pn = make_node_const_object(parser, lex->tok_line, o); } } else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) { mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex); pn = make_node_const_object(parser, lex->tok_line, o); } else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) { // Don't automatically intern all strings/bytes. doc strings (which are usually large) // will be discarded by the compiler, and so we shouldn't intern them. qstr qst = MP_QSTRnull; if (lex->vstr.len <= MICROPY_ALLOC_PARSE_INTERN_STRING_LEN) { // intern short strings qst = qstr_from_strn(lex->vstr.buf, lex->vstr.len); } else { // check if this string is already interned qst = qstr_find_strn(lex->vstr.buf, lex->vstr.len); } if (qst != MP_QSTRnull) { // qstr exists, make a leaf node pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst); } else { // not interned, make a node holding a pointer to the string/bytes object mp_obj_t o = mp_obj_new_str_copy( lex->tok_kind == MP_TOKEN_STRING ? &mp_type_str : &mp_type_bytes, (const byte*)lex->vstr.buf, lex->vstr.len); pn = make_node_const_object(parser, lex->tok_line, o); } } else { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind); } push_result_node(parser, pn); } #if MICROPY_COMP_MODULE_CONST STATIC const mp_rom_map_elem_t mp_constants_table[] = { #if MICROPY_PY_UERRNO { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, #endif #if MICROPY_PY_UCTYPES { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) }, #endif // Extra constants as defined by a port MICROPY_PORT_CONSTANTS }; STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table); #endif STATIC void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args); #if MICROPY_COMP_CONST_FOLDING STATIC bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *num_args) { if (rule_id == RULE_or_test || rule_id == RULE_and_test) { // folding for binary logical ops: or and size_t copy_to = *num_args; for (size_t i = copy_to; i > 0;) { mp_parse_node_t pn = peek_result(parser, --i); parser->result_stack[parser->result_stack_top - copy_to] = pn; if (i == 0) { // always need to keep the last value break; } if (rule_id == RULE_or_test) { if (mp_parse_node_is_const_true(pn)) { // break; } else if (!mp_parse_node_is_const_false(pn)) { copy_to -= 1; } } else { // RULE_and_test if (mp_parse_node_is_const_false(pn)) { break; } else if (!mp_parse_node_is_const_true(pn)) { copy_to -= 1; } } } copy_to -= 1; // copy_to now contains number of args to pop // pop and discard all the short-circuited expressions for (size_t i = 0; i < copy_to; ++i) { pop_result(parser); } *num_args -= copy_to; // we did a complete folding if there's only 1 arg left return *num_args == 1; } else if (rule_id == RULE_not_test_2) { // folding for unary logical op: not mp_parse_node_t pn = peek_result(parser, 0); if (mp_parse_node_is_const_false(pn)) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_TRUE); } else if (mp_parse_node_is_const_true(pn)) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_FALSE); } else { return false; } pop_result(parser); push_result_node(parser, pn); return true; } return false; } STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4 // it does not do partial folding, eg 1 + 2 + x -> 3 + x mp_obj_t arg0; if (rule_id == RULE_expr || rule_id == RULE_xor_expr || rule_id == RULE_and_expr) { // folding for binary ops: | ^ & mp_parse_node_t pn = peek_result(parser, num_args - 1); if (!mp_parse_node_get_int_maybe(pn, &arg0)) { return false; } mp_binary_op_t op; if (rule_id == RULE_expr) { op = MP_BINARY_OP_OR; } else if (rule_id == RULE_xor_expr) { op = MP_BINARY_OP_XOR; } else { op = MP_BINARY_OP_AND; } for (ssize_t i = num_args - 2; i >= 0; --i) { pn = peek_result(parser, i); mp_obj_t arg1; if (!mp_parse_node_get_int_maybe(pn, &arg1)) { return false; } arg0 = mp_binary_op(op, arg0, arg1); } } else if (rule_id == RULE_shift_expr || rule_id == RULE_arith_expr || rule_id == RULE_term) { // folding for binary ops: << >> + - * @ / % // mp_parse_node_t pn = peek_result(parser, num_args - 1); if (!mp_parse_node_get_int_maybe(pn, &arg0)) { return false; } for (ssize_t i = num_args - 2; i >= 1; i -= 2) { pn = peek_result(parser, i - 1); mp_obj_t arg1; if (!mp_parse_node_get_int_maybe(pn, &arg1)) { return false; } mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, i)); if (tok == MP_TOKEN_OP_AT || tok == MP_TOKEN_OP_SLASH || tok == MP_TOKEN_OP_DBL_STAR) { // Can't fold @ or / or ** return false; } mp_binary_op_t op = MP_BINARY_OP_LSHIFT + (tok - MP_TOKEN_OP_DBL_LESS); int rhs_sign = mp_obj_int_sign(arg1); if (op <= MP_BINARY_OP_RSHIFT) { // << and >> can't have negative rhs if (rhs_sign < 0) { return false; } } else if (op >= MP_BINARY_OP_FLOOR_DIVIDE) { // % and // can't have zero rhs if (rhs_sign == 0) { return false; } } arg0 = mp_binary_op(op, arg0, arg1); } } else if (rule_id == RULE_factor_2) { // folding for unary ops: + - ~ mp_parse_node_t pn = peek_result(parser, 0); if (!mp_parse_node_get_int_maybe(pn, &arg0)) { return false; } mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, 1)); mp_unary_op_t op; if (tok == MP_TOKEN_OP_TILDE) { op = MP_UNARY_OP_INVERT; } else { assert(tok == MP_TOKEN_OP_PLUS || tok == MP_TOKEN_OP_MINUS); // should be op = MP_UNARY_OP_POSITIVE + (tok - MP_TOKEN_OP_PLUS); } arg0 = mp_unary_op(op, arg0); #if MICROPY_COMP_CONST } else if (rule_id == RULE_expr_stmt) { mp_parse_node_t pn1 = peek_result(parser, 0); if (!MP_PARSE_NODE_IS_NULL(pn1) && !(MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_augassign) || MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_assign_list))) { // this node is of the form = mp_parse_node_t pn0 = peek_result(parser, 1); if (MP_PARSE_NODE_IS_ID(pn0) && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_atom_expr_normal) && MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t*)pn1)->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn1)->nodes[0]) == MP_QSTR_const && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t*)pn1)->nodes[1], RULE_trailer_paren) ) { // code to assign dynamic constants: id = const(value) // get the id qstr id = MP_PARSE_NODE_LEAF_ARG(pn0); // get the value mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pn1)->nodes[1])->nodes[0]; mp_obj_t value; if (!mp_parse_node_get_int_maybe(pn_value, &value)) { mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, "constant must be an integer"); mp_obj_exception_add_traceback(exc, parser->lexer->source_name, ((mp_parse_node_struct_t*)pn1)->source_line, MP_QSTRnull); nlr_raise(exc); } // store the value in the table of dynamic constants mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); assert(elem->value == MP_OBJ_NULL); elem->value = value; // If the constant starts with an underscore then treat it as a private // variable and don't emit any code to store the value to the id. if (qstr_str(id)[0] == '_') { pop_result(parser); // pop const(value) pop_result(parser); // pop id push_result_rule(parser, 0, RULE_pass_stmt, 0); // replace with "pass" return true; } // replace const(value) with value pop_result(parser); push_result_node(parser, pn_value); // finished folding this assignment, but we still want it to be part of the tree return false; } } return false; #endif #if MICROPY_COMP_MODULE_CONST } else if (rule_id == RULE_atom_expr_normal) { mp_parse_node_t pn0 = peek_result(parser, 1); mp_parse_node_t pn1 = peek_result(parser, 0); if (!(MP_PARSE_NODE_IS_ID(pn0) && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_trailer_period))) { return false; } // id1.id2 // look it up in constant table, see if it can be replaced with an integer mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pn1; assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0); qstr q_attr = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]); mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&mp_constants_map, MP_OBJ_NEW_QSTR(q_base), MP_MAP_LOOKUP); if (elem == NULL) { return false; } mp_obj_t dest[2]; mp_load_method_maybe(elem->value, q_attr, dest); if (!(dest[0] != MP_OBJ_NULL && mp_obj_is_int(dest[0]) && dest[1] == MP_OBJ_NULL)) { return false; } arg0 = dest[0]; #endif } else { return false; } // success folding this rule for (size_t i = num_args; i > 0; i--) { pop_result(parser); } if (mp_obj_is_small_int(arg0)) { push_result_node(parser, mp_parse_node_new_small_int_checked(parser, arg0)); } else { // TODO reuse memory for parse node struct? push_result_node(parser, make_node_const_object(parser, 0, arg0)); } return true; } #endif STATIC void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args) { // optimise away parenthesis around an expression if possible if (rule_id == RULE_atom_paren) { // there should be just 1 arg for this rule mp_parse_node_t pn = peek_result(parser, 0); if (MP_PARSE_NODE_IS_NULL(pn)) { // need to keep parenthesis for () } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_testlist_comp)) { // need to keep parenthesis for (a, b, ...) } else { // parenthesis around a single expression, so it's just the expression return; } } #if MICROPY_COMP_CONST_FOLDING if (fold_logical_constants(parser, rule_id, &num_args)) { // we folded this rule so return straight away return; } if (fold_constants(parser, rule_id, num_args)) { // we folded this rule so return straight away return; } #endif mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args); pn->source_line = src_line; pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8); for (size_t i = num_args; i > 0; i--) { pn->nodes[i - 1] = pop_result(parser); } push_result_node(parser, (mp_parse_node_t)pn); } mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { // initialise parser and allocate memory for its stacks parser_t parser; parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT; parser.rule_stack_top = 0; parser.rule_stack = m_new(rule_stack_t, parser.rule_stack_alloc); parser.result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT; parser.result_stack_top = 0; parser.result_stack = m_new(mp_parse_node_t, parser.result_stack_alloc); parser.lexer = lex; parser.tree.chunk = NULL; parser.cur_chunk = NULL; #if MICROPY_COMP_CONST mp_map_init(&parser.consts, 0); #endif // work out the top-level rule to use, and push it on the stack size_t top_level_rule; switch (input_kind) { case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break; case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break; default: top_level_rule = RULE_file_input; } push_rule(&parser, lex->tok_line, top_level_rule, 0); // parse! bool backtrack = false; for (;;) { next_rule: if (parser.rule_stack_top == 0) { break; } // Pop the next rule to process it size_t i; // state for the current rule size_t rule_src_line; // source line for the first token matched by the current rule uint8_t rule_id = pop_rule(&parser, &i, &rule_src_line); uint8_t rule_act = rule_act_table[rule_id]; const uint16_t *rule_arg = get_rule_arg(rule_id); size_t n = rule_act & RULE_ACT_ARG_MASK; #if 0 // debugging printf("depth=" UINT_FMT " ", parser.rule_stack_top); for (int j = 0; j < parser.rule_stack_top; ++j) { printf(" "); } printf("%s n=" UINT_FMT " i=" UINT_FMT " bt=%d\n", rule_name_table[rule_id], n, i, backtrack); #endif switch (rule_act & RULE_ACT_KIND_MASK) { case RULE_ACT_OR: if (i > 0 && !backtrack) { goto next_rule; } else { backtrack = false; } for (; i < n; ++i) { uint16_t kind = rule_arg[i] & RULE_ARG_KIND_MASK; if (kind == RULE_ARG_TOK) { if (lex->tok_kind == (rule_arg[i] & RULE_ARG_ARG_MASK)) { push_result_token(&parser, rule_id); mp_lexer_to_next(lex); goto next_rule; } } else { assert(kind == RULE_ARG_RULE); if (i + 1 < n) { push_rule(&parser, rule_src_line, rule_id, i + 1); // save this or-rule } push_rule_from_arg(&parser, rule_arg[i]); // push child of or-rule goto next_rule; } } backtrack = true; break; case RULE_ACT_AND: { // failed, backtrack if we can, else syntax error if (backtrack) { assert(i > 0); if ((rule_arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) { // an optional rule that failed, so continue with next arg push_result_node(&parser, MP_PARSE_NODE_NULL); backtrack = false; } else { // a mandatory rule that failed, so propagate backtrack if (i > 1) { // already eaten tokens so can't backtrack goto syntax_error; } else { goto next_rule; } } } // progress through the rule for (; i < n; ++i) { if ((rule_arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { // need to match a token mp_token_kind_t tok_kind = rule_arg[i] & RULE_ARG_ARG_MASK; if (lex->tok_kind == tok_kind) { // matched token if (tok_kind == MP_TOKEN_NAME) { push_result_token(&parser, rule_id); } mp_lexer_to_next(lex); } else { // failed to match token if (i > 0) { // already eaten tokens so can't backtrack goto syntax_error; } else { // this rule failed, so backtrack backtrack = true; goto next_rule; } } } else { push_rule(&parser, rule_src_line, rule_id, i + 1); // save this and-rule push_rule_from_arg(&parser, rule_arg[i]); // push child of and-rule goto next_rule; } } assert(i == n); // matched the rule, so now build the corresponding parse_node #if !MICROPY_ENABLE_DOC_STRING // this code discards lonely statements, such as doc strings if (input_kind != MP_PARSE_SINGLE_INPUT && rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) { mp_parse_node_t p = peek_result(&parser, 1); if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p)) || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_const_object)) { pop_result(&parser); // MP_PARSE_NODE_NULL pop_result(&parser); // const expression (leaf or RULE_const_object) // Pushing the "pass" rule here will overwrite any RULE_const_object // entry that was on the result stack, allowing the GC to reclaim // the memory from the const object when needed. push_result_rule(&parser, rule_src_line, RULE_pass_stmt, 0); break; } } #endif // count number of arguments for the parse node i = 0; size_t num_not_nil = 0; for (size_t x = n; x > 0;) { --x; if ((rule_arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { mp_token_kind_t tok_kind = rule_arg[x] & RULE_ARG_ARG_MASK; if (tok_kind == MP_TOKEN_NAME) { // only tokens which were names are pushed to stack i += 1; num_not_nil += 1; } } else { // rules are always pushed if (peek_result(&parser, i) != MP_PARSE_NODE_NULL) { num_not_nil += 1; } i += 1; } } if (num_not_nil == 1 && (rule_act & RULE_ACT_ALLOW_IDENT)) { // this rule has only 1 argument and should not be emitted mp_parse_node_t pn = MP_PARSE_NODE_NULL; for (size_t x = 0; x < i; ++x) { mp_parse_node_t pn2 = pop_result(&parser); if (pn2 != MP_PARSE_NODE_NULL) { pn = pn2; } } push_result_node(&parser, pn); } else { // this rule must be emitted if (rule_act & RULE_ACT_ADD_BLANK) { // and add an extra blank node at the end (used by the compiler to store data) push_result_node(&parser, MP_PARSE_NODE_NULL); i += 1; } push_result_rule(&parser, rule_src_line, rule_id, i); } break; } default: { assert((rule_act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST); // n=2 is: item item* // n=1 is: item (sep item)* // n=3 is: item (sep item)* [sep] bool had_trailing_sep; if (backtrack) { list_backtrack: had_trailing_sep = false; if (n == 2) { if (i == 1) { // fail on item, first time round; propagate backtrack goto next_rule; } else { // fail on item, in later rounds; finish with this rule backtrack = false; } } else { if (i == 1) { // fail on item, first time round; propagate backtrack goto next_rule; } else if ((i & 1) == 1) { // fail on item, in later rounds; have eaten tokens so can't backtrack if (n == 3) { // list allows trailing separator; finish parsing list had_trailing_sep = true; backtrack = false; } else { // list doesn't allowing trailing separator; fail goto syntax_error; } } else { // fail on separator; finish parsing list backtrack = false; } } } else { for (;;) { size_t arg = rule_arg[i & 1 & n]; if ((arg & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { if (lex->tok_kind == (arg & RULE_ARG_ARG_MASK)) { if (i & 1 & n) { // separators which are tokens are not pushed to result stack } else { push_result_token(&parser, rule_id); } mp_lexer_to_next(lex); // got element of list, so continue parsing list i += 1; } else { // couldn't get element of list i += 1; backtrack = true; goto list_backtrack; } } else { assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE); push_rule(&parser, rule_src_line, rule_id, i + 1); // save this list-rule push_rule_from_arg(&parser, arg); // push child of list-rule goto next_rule; } } } assert(i >= 1); // compute number of elements in list, result in i i -= 1; if ((n & 1) && (rule_arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { // don't count separators when they are tokens i = (i + 1) / 2; } if (i == 1) { // list matched single item if (had_trailing_sep) { // if there was a trailing separator, make a list of a single item push_result_rule(&parser, rule_src_line, rule_id, i); } else { // just leave single item on stack (ie don't wrap in a list) } } else { push_result_rule(&parser, rule_src_line, rule_id, i); } break; } } } #if MICROPY_COMP_CONST mp_map_deinit(&parser.consts); #endif // truncate final chunk and link into chain of chunks if (parser.cur_chunk != NULL) { (void)m_renew_maybe(byte, parser.cur_chunk, sizeof(mp_parse_chunk_t) + parser.cur_chunk->alloc, sizeof(mp_parse_chunk_t) + parser.cur_chunk->union_.used, false); parser.cur_chunk->alloc = parser.cur_chunk->union_.used; parser.cur_chunk->union_.next = parser.tree.chunk; parser.tree.chunk = parser.cur_chunk; } if ( lex->tok_kind != MP_TOKEN_END // check we are at the end of the token stream || parser.result_stack_top == 0 // check that we got a node (can fail on empty input) ) { syntax_error:; mp_obj_t exc; if (lex->tok_kind == MP_TOKEN_INDENT) { exc = mp_obj_new_exception_msg(&mp_type_IndentationError, "unexpected indent"); } else if (lex->tok_kind == MP_TOKEN_DEDENT_MISMATCH) { exc = mp_obj_new_exception_msg(&mp_type_IndentationError, "unindent doesn't match any outer indent level"); } else { exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax"); } // add traceback to give info about file name and location // we don't have a 'block' name, so just pass the NULL qstr to indicate this mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTRnull); nlr_raise(exc); } // get the root parse node that we created assert(parser.result_stack_top == 1); parser.tree.root = parser.result_stack[0]; // free the memory that we don't need anymore m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc); m_del(mp_parse_node_t, parser.result_stack, parser.result_stack_alloc); // we also free the lexer on behalf of the caller mp_lexer_free(lex); return parser.tree; } void mp_parse_tree_clear(mp_parse_tree_t *tree) { mp_parse_chunk_t *chunk = tree->chunk; while (chunk != NULL) { mp_parse_chunk_t *next = chunk->union_.next; m_del(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc); chunk = next; } } #endif // MICROPY_ENABLE_COMPILER micropython-1.12/py/parse.h000066400000000000000000000110401357706137100157310ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_PARSE_H #define MICROPY_INCLUDED_PY_PARSE_H #include #include #include "py/obj.h" struct _mp_lexer_t; // a mp_parse_node_t is: // - 0000...0000: no node // - xxxx...xxx1: a small integer; bits 1 and above are the signed value, 2's complement // - xxxx...xx00: pointer to mp_parse_node_struct_t // - xx...xx0010: an identifier; bits 4 and above are the qstr // - xx...xx0110: a string; bits 4 and above are the qstr holding the value // - xx...xx1010: a string of bytes; bits 4 and above are the qstr holding the value // - xx...xx1110: a token; bits 4 and above are mp_token_kind_t #define MP_PARSE_NODE_NULL (0) #define MP_PARSE_NODE_SMALL_INT (0x1) #define MP_PARSE_NODE_ID (0x02) #define MP_PARSE_NODE_STRING (0x06) #define MP_PARSE_NODE_BYTES (0x0a) #define MP_PARSE_NODE_TOKEN (0x0e) typedef uintptr_t mp_parse_node_t; // must be pointer size typedef struct _mp_parse_node_struct_t { uint32_t source_line; // line number in source file uint32_t kind_num_nodes; // parse node kind, and number of nodes mp_parse_node_t nodes[]; // nodes } mp_parse_node_struct_t; // macros for mp_parse_node_t usage // some of these evaluate their argument more than once #define MP_PARSE_NODE_IS_NULL(pn) ((pn) == MP_PARSE_NODE_NULL) #define MP_PARSE_NODE_IS_LEAF(pn) ((pn) & 3) #define MP_PARSE_NODE_IS_STRUCT(pn) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 3) == 0) #define MP_PARSE_NODE_IS_STRUCT_KIND(pn, k) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 3) == 0 && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)(pn)) == (k)) #define MP_PARSE_NODE_IS_SMALL_INT(pn) (((pn) & 0x1) == MP_PARSE_NODE_SMALL_INT) #define MP_PARSE_NODE_IS_ID(pn) (((pn) & 0x0f) == MP_PARSE_NODE_ID) #define MP_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0x0f) == MP_PARSE_NODE_TOKEN) #define MP_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (MP_PARSE_NODE_TOKEN | ((k) << 4))) #define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0x0f) #define MP_PARSE_NODE_LEAF_ARG(pn) (((uintptr_t)(pn)) >> 4) #define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((mp_int_t)(intptr_t)(pn)) >> 1) #define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff) #define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8) static inline mp_parse_node_t mp_parse_node_new_small_int(mp_int_t val) { return (mp_parse_node_t)(MP_PARSE_NODE_SMALL_INT | ((mp_uint_t)val << 1)); } static inline mp_parse_node_t mp_parse_node_new_leaf(size_t kind, mp_int_t arg) { return (mp_parse_node_t)(kind | ((mp_uint_t)arg << 4)); } bool mp_parse_node_is_const_false(mp_parse_node_t pn); bool mp_parse_node_is_const_true(mp_parse_node_t pn); bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o); int mp_parse_node_extract_list(mp_parse_node_t *pn, size_t pn_kind, mp_parse_node_t **nodes); void mp_parse_node_print(mp_parse_node_t pn, size_t indent); typedef enum { MP_PARSE_SINGLE_INPUT, MP_PARSE_FILE_INPUT, MP_PARSE_EVAL_INPUT, } mp_parse_input_kind_t; typedef struct _mp_parse_t { mp_parse_node_t root; struct _mp_parse_chunk_t *chunk; } mp_parse_tree_t; // the parser will raise an exception if an error occurred // the parser will free the lexer before it returns mp_parse_tree_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind); void mp_parse_tree_clear(mp_parse_tree_t *tree); #endif // MICROPY_INCLUDED_PY_PARSE_H micropython-1.12/py/parsenum.c000066400000000000000000000272711357706137100164610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/parsenumbase.h" #include "py/parsenum.h" #include "py/smallint.h" #if MICROPY_PY_BUILTINS_FLOAT #include #endif STATIC NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) { // if lex!=NULL then the parser called us and we need to convert the // exception's type from ValueError to SyntaxError and add traceback info if (lex != NULL) { ((mp_obj_base_t*)MP_OBJ_TO_PTR(exc))->type = &mp_type_SyntaxError; mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTRnull); } nlr_raise(exc); } mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, mp_lexer_t *lex) { const byte *restrict str = (const byte *)str_; const byte *restrict top = str + len; bool neg = false; mp_obj_t ret_val; // check radix base if ((base != 0 && base < 2) || base > 36) { // this won't be reached if lex!=NULL mp_raise_ValueError("int() arg 2 must be >= 2 and <= 36"); } // skip leading space for (; str < top && unichar_isspace(*str); str++) { } // parse optional sign if (str < top) { if (*str == '+') { str++; } else if (*str == '-') { str++; neg = true; } } // parse optional base prefix str += mp_parse_num_base((const char*)str, top - str, &base); // string should be an integer number mp_int_t int_val = 0; const byte *restrict str_val_start = str; for (; str < top; str++) { // get next digit as a value mp_uint_t dig = *str; if ('0' <= dig && dig <= '9') { dig -= '0'; } else if (dig == '_') { continue; } else { dig |= 0x20; // make digit lower-case if ('a' <= dig && dig <= 'z') { dig -= 'a' - 10; } else { // unknown character break; } } if (dig >= (mp_uint_t)base) { break; } // add next digi and check for overflow if (mp_small_int_mul_overflow(int_val, base)) { goto overflow; } int_val = int_val * base + dig; if (!MP_SMALL_INT_FITS(int_val)) { goto overflow; } } // negate value if needed if (neg) { int_val = -int_val; } // create the small int ret_val = MP_OBJ_NEW_SMALL_INT(int_val); have_ret_val: // check we parsed something if (str == str_val_start) { goto value_error; } // skip trailing space for (; str < top && unichar_isspace(*str); str++) { } // check we reached the end of the string if (str != top) { goto value_error; } // return the object return ret_val; overflow: // reparse using long int { const char *s2 = (const char*)str_val_start; ret_val = mp_obj_new_int_from_str_len(&s2, top - str_val_start, neg, base); str = (const byte*)s2; goto have_ret_val; } value_error: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_ValueError, "invalid syntax for integer"); raise_exc(exc, lex); } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) { mp_obj_t exc = mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid syntax for integer with base %d", base); raise_exc(exc, lex); } else { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 50, &print); mp_printf(&print, "invalid syntax for integer with base %d: ", base); mp_str_print_quoted(&print, str_val_start, top - str_val_start, true); mp_obj_t exc = mp_obj_new_exception_arg1(&mp_type_ValueError, mp_obj_new_str_from_vstr(&mp_type_str, &vstr)); raise_exc(exc, lex); } } typedef enum { PARSE_DEC_IN_INTG, PARSE_DEC_IN_FRAC, PARSE_DEC_IN_EXP, } parse_dec_in_t; mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) { #if MICROPY_PY_BUILTINS_FLOAT // DEC_VAL_MAX only needs to be rough and is used to retain precision while not overflowing // SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float // EXACT_POWER_OF_10 is the largest value of x so that 10^x can be stored exactly in a float // Note: EXACT_POWER_OF_10 is at least floor(log_5(2^mantissa_length)). Indeed, 10^n = 2^n * 5^n // so we only have to store the 5^n part in the mantissa (the 2^n part will go into the float's // exponent). #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #define DEC_VAL_MAX 1e20F #define SMALL_NORMAL_VAL (1e-37F) #define SMALL_NORMAL_EXP (-37) #define EXACT_POWER_OF_10 (9) #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #define DEC_VAL_MAX 1e200 #define SMALL_NORMAL_VAL (1e-307) #define SMALL_NORMAL_EXP (-307) #define EXACT_POWER_OF_10 (22) #endif const char *top = str + len; mp_float_t dec_val = 0; bool dec_neg = false; bool imag = false; // skip leading space for (; str < top && unichar_isspace(*str); str++) { } // parse optional sign if (str < top) { if (*str == '+') { str++; } else if (*str == '-') { str++; dec_neg = true; } } const char *str_val_start = str; // determine what the string is if (str < top && (str[0] | 0x20) == 'i') { // string starts with 'i', should be 'inf' or 'infinity' (case insensitive) if (str + 2 < top && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') { // inf str += 3; dec_val = INFINITY; if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') { // infinity str += 5; } } } else if (str < top && (str[0] | 0x20) == 'n') { // string starts with 'n', should be 'nan' (case insensitive) if (str + 2 < top && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') { // NaN str += 3; dec_val = MICROPY_FLOAT_C_FUN(nan)(""); } } else { // string should be a decimal number parse_dec_in_t in = PARSE_DEC_IN_INTG; bool exp_neg = false; int exp_val = 0; int exp_extra = 0; while (str < top) { unsigned int dig = *str++; if ('0' <= dig && dig <= '9') { dig -= '0'; if (in == PARSE_DEC_IN_EXP) { // don't overflow exp_val when adding next digit, instead just truncate // it and the resulting float will still be correct, either inf or 0.0 // (use INT_MAX/2 to allow adding exp_extra at the end without overflow) if (exp_val < (INT_MAX / 2 - 9) / 10) { exp_val = 10 * exp_val + dig; } } else { if (dec_val < DEC_VAL_MAX) { // dec_val won't overflow so keep accumulating dec_val = 10 * dec_val + dig; if (in == PARSE_DEC_IN_FRAC) { --exp_extra; } } else { // dec_val might overflow and we anyway can't represent more digits // of precision, so ignore the digit and just adjust the exponent if (in == PARSE_DEC_IN_INTG) { ++exp_extra; } } } } else if (in == PARSE_DEC_IN_INTG && dig == '.') { in = PARSE_DEC_IN_FRAC; } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) { in = PARSE_DEC_IN_EXP; if (str < top) { if (str[0] == '+') { str++; } else if (str[0] == '-') { str++; exp_neg = true; } } if (str == top) { goto value_error; } } else if (allow_imag && (dig | 0x20) == 'j') { imag = true; break; } else if (dig == '_') { continue; } else { // unknown character str--; break; } } // work out the exponent if (exp_neg) { exp_val = -exp_val; } // apply the exponent, making sure it's not a subnormal value exp_val += exp_extra; if (exp_val < SMALL_NORMAL_EXP) { exp_val -= SMALL_NORMAL_EXP; dec_val *= SMALL_NORMAL_VAL; } // At this point, we need to multiply the mantissa by its base 10 exponent. If possible, // we would rather manipulate numbers that have an exact representation in IEEE754. It // turns out small positive powers of 10 do, whereas small negative powers of 10 don't. // So in that case, we'll yield a division of exact values rather than a multiplication // of slightly erroneous values. if (exp_val < 0 && exp_val >= -EXACT_POWER_OF_10) { dec_val /= MICROPY_FLOAT_C_FUN(pow)(10, -exp_val); } else { dec_val *= MICROPY_FLOAT_C_FUN(pow)(10, exp_val); } } // negate value if needed if (dec_neg) { dec_val = -dec_val; } // check we parsed something if (str == str_val_start) { goto value_error; } // skip trailing space for (; str < top && unichar_isspace(*str); str++) { } // check we reached the end of the string if (str != top) { goto value_error; } // return the object #if MICROPY_PY_BUILTINS_COMPLEX if (imag) { return mp_obj_new_complex(0, dec_val); } else if (force_complex) { return mp_obj_new_complex(dec_val, 0); } #else if (imag || force_complex) { raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, "complex values not supported"), lex); } #endif else { return mp_obj_new_float(dec_val); } value_error: raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid syntax for number"), lex); #else raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, "decimal numbers not supported"), lex); #endif } micropython-1.12/py/parsenum.h000066400000000000000000000032451357706137100164610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_PARSENUM_H #define MICROPY_INCLUDED_PY_PARSENUM_H #include "py/mpconfig.h" #include "py/lexer.h" #include "py/obj.h" // these functions raise a SyntaxError if lex!=NULL, else a ValueError mp_obj_t mp_parse_num_integer(const char *restrict str, size_t len, int base, mp_lexer_t *lex); mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex); #endif // MICROPY_INCLUDED_PY_PARSENUM_H micropython-1.12/py/parsenumbase.c000066400000000000000000000045431357706137100173110ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" #include "py/misc.h" #include "py/parsenumbase.h" // find real radix base, and strip preceding '0x', '0o' and '0b' // puts base in *base, and returns number of bytes to skip the prefix size_t mp_parse_num_base(const char *str, size_t len, int *base) { const byte *p = (const byte*)str; if (len <= 1) { goto no_prefix; } unichar c = *(p++); if ((*base == 0 || *base == 16) && c == '0') { c = *(p++); if ((c | 32) == 'x') { *base = 16; } else if (*base == 0 && (c | 32) == 'o') { *base = 8; } else if (*base == 0 && (c | 32) == 'b') { *base = 2; } else { if (*base == 0) { *base = 10; } p -= 2; } } else if (*base == 8 && c == '0') { c = *(p++); if ((c | 32) != 'o') { p -= 2; } } else if (*base == 2 && c == '0') { c = *(p++); if ((c | 32) != 'b') { p -= 2; } } else { p--; no_prefix: if (*base == 0) { *base = 10; } } return p - (const byte*)str; } micropython-1.12/py/parsenumbase.h000066400000000000000000000026601357706137100173140ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_PARSENUMBASE_H #define MICROPY_INCLUDED_PY_PARSENUMBASE_H #include "py/mpconfig.h" size_t mp_parse_num_base(const char *str, size_t len, int *base); #endif // MICROPY_INCLUDED_PY_PARSENUMBASE_H micropython-1.12/py/persistentcode.c000066400000000000000000000655711357706137100176670ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/reader.h" #include "py/nativeglue.h" #include "py/persistentcode.h" #include "py/bc0.h" #include "py/objstr.h" #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE #include "py/smallint.h" #define QSTR_LAST_STATIC MP_QSTR_zip #if MICROPY_DYNAMIC_COMPILER #define MPY_FEATURE_ARCH_DYNAMIC mp_dynamic_compiler.native_arch #else #define MPY_FEATURE_ARCH_DYNAMIC MPY_FEATURE_ARCH #endif #if MICROPY_PERSISTENT_CODE_LOAD || (MICROPY_PERSISTENT_CODE_SAVE && !MICROPY_DYNAMIC_COMPILER) // The bytecode will depend on the number of bits in a small-int, and // this function computes that (could make it a fixed constant, but it // would need to be defined in mpconfigport.h). STATIC int mp_small_int_bits(void) { mp_int_t i = MP_SMALL_INT_MAX; int n = 1; while (i != 0) { i >>= 1; ++n; } return n; } #endif #define QSTR_WINDOW_SIZE (32) typedef struct _qstr_window_t { uint16_t idx; // indexes the head of the window uint16_t window[QSTR_WINDOW_SIZE]; } qstr_window_t; // Push a qstr to the head of the window, and the tail qstr is overwritten STATIC void qstr_window_push(qstr_window_t *qw, qstr qst) { qw->idx = (qw->idx + 1) % QSTR_WINDOW_SIZE; qw->window[qw->idx] = qst; } // Pull an existing qstr from within the window to the head of the window STATIC qstr qstr_window_pull(qstr_window_t *qw, size_t idx) { qstr qst = qw->window[idx]; if (idx > qw->idx) { memmove(&qw->window[idx], &qw->window[idx + 1], (QSTR_WINDOW_SIZE - idx - 1) * sizeof(uint16_t)); qw->window[QSTR_WINDOW_SIZE - 1] = qw->window[0]; idx = 0; } memmove(&qw->window[idx], &qw->window[idx + 1], (qw->idx - idx) * sizeof(uint16_t)); qw->window[qw->idx] = qst; return qst; } #if MICROPY_PERSISTENT_CODE_LOAD // Access a qstr at the given index, relative to the head of the window (0=head) STATIC qstr qstr_window_access(qstr_window_t *qw, size_t idx) { return qstr_window_pull(qw, (qw->idx + QSTR_WINDOW_SIZE - idx) % QSTR_WINDOW_SIZE); } #endif #if MICROPY_PERSISTENT_CODE_SAVE // Insert a qstr at the head of the window, either by pulling an existing one or pushing a new one STATIC size_t qstr_window_insert(qstr_window_t *qw, qstr qst) { for (size_t idx = 0; idx < QSTR_WINDOW_SIZE; ++idx) { if (qw->window[idx] == qst) { qstr_window_pull(qw, idx); return (qw->idx + QSTR_WINDOW_SIZE - idx) % QSTR_WINDOW_SIZE; } } qstr_window_push(qw, qst); return QSTR_WINDOW_SIZE; } #endif typedef struct _bytecode_prelude_t { uint n_state; uint n_exc_stack; uint scope_flags; uint n_pos_args; uint n_kwonly_args; uint n_def_pos_args; uint code_info_size; } bytecode_prelude_t; // ip will point to start of opcodes // return value will point to simple_name, source_file qstrs STATIC byte *extract_prelude(const byte **ip, bytecode_prelude_t *prelude) { MP_BC_PRELUDE_SIG_DECODE(*ip); prelude->n_state = n_state; prelude->n_exc_stack = n_exc_stack; prelude->scope_flags = scope_flags; prelude->n_pos_args = n_pos_args; prelude->n_kwonly_args = n_kwonly_args; prelude->n_def_pos_args = n_def_pos_args; MP_BC_PRELUDE_SIZE_DECODE(*ip); byte *ip_info = (byte*)*ip; *ip += n_info; *ip += n_cell; return ip_info; } #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE #if MICROPY_PERSISTENT_CODE_LOAD #include "py/parsenum.h" STATIC int read_byte(mp_reader_t *reader); STATIC size_t read_uint(mp_reader_t *reader, byte **out); #if MICROPY_EMIT_MACHINE_CODE typedef struct _reloc_info_t { mp_reader_t *reader; mp_uint_t *const_table; } reloc_info_t; #if MICROPY_EMIT_THUMB STATIC void asm_thumb_rewrite_mov(uint8_t *pc, uint16_t val) { // high part *(uint16_t*)pc = (*(uint16_t*)pc & 0xfbf0) | (val >> 1 & 0x0400) | (val >> 12); // low part *(uint16_t*)(pc + 2) = (*(uint16_t*)(pc + 2) & 0x0f00) | (val << 4 & 0x7000) | (val & 0x00ff); } #endif STATIC void arch_link_qstr(uint8_t *pc, bool is_obj, qstr qst) { mp_uint_t val = qst; if (is_obj) { val = (mp_uint_t)MP_OBJ_NEW_QSTR(qst); } #if MICROPY_EMIT_X86 || MICROPY_EMIT_X64 || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN pc[0] = val & 0xff; pc[1] = (val >> 8) & 0xff; pc[2] = (val >> 16) & 0xff; pc[3] = (val >> 24) & 0xff; #elif MICROPY_EMIT_THUMB if (is_obj) { // qstr object, movw and movt asm_thumb_rewrite_mov(pc, val); // movw asm_thumb_rewrite_mov(pc + 4, val >> 16); // movt } else { // qstr number, movw instruction asm_thumb_rewrite_mov(pc, val); // movw } #endif } void mp_native_relocate(void *ri_in, uint8_t *text, uintptr_t reloc_text) { // Relocate native code reloc_info_t *ri = ri_in; uint8_t op; uintptr_t *addr_to_adjust = NULL; while ((op = read_byte(ri->reader)) != 0xff) { if (op & 1) { // Point to new location to make adjustments size_t addr = read_uint(ri->reader, NULL); if ((addr & 1) == 0) { // Point to somewhere in text addr_to_adjust = &((uintptr_t*)text)[addr >> 1]; } else { // Point to somewhere in rodata addr_to_adjust = &((uintptr_t*)ri->const_table[1])[addr >> 1]; } } op >>= 1; uintptr_t dest; size_t n = 1; if (op <= 5) { if (op & 1) { // Read in number of adjustments to make n = read_uint(ri->reader, NULL); } op >>= 1; if (op == 0) { // Destination is text dest = reloc_text; } else { // Destination is rodata (op=1) or bss (op=1 if no rodata, else op=2) dest = ri->const_table[op]; } } else if (op == 6) { // Destination is mp_fun_table itself dest = (uintptr_t)&mp_fun_table; } else { // Destination is an entry in mp_fun_table dest = ((uintptr_t*)&mp_fun_table)[op - 7]; } while (n--) { *addr_to_adjust++ += dest; } } } #endif STATIC int read_byte(mp_reader_t *reader) { return reader->readbyte(reader->data); } STATIC void read_bytes(mp_reader_t *reader, byte *buf, size_t len) { while (len-- > 0) { *buf++ = reader->readbyte(reader->data); } } STATIC size_t read_uint(mp_reader_t *reader, byte **out) { size_t unum = 0; for (;;) { byte b = reader->readbyte(reader->data); if (out != NULL) { **out = b; ++*out; } unum = (unum << 7) | (b & 0x7f); if ((b & 0x80) == 0) { break; } } return unum; } STATIC qstr load_qstr(mp_reader_t *reader, qstr_window_t *qw) { size_t len = read_uint(reader, NULL); if (len == 0) { // static qstr return read_byte(reader); } if (len & 1) { // qstr in window return qstr_window_access(qw, len >> 1); } len >>= 1; char *str = m_new(char, len); read_bytes(reader, (byte*)str, len); qstr qst = qstr_from_strn(str, len); m_del(char, str, len); qstr_window_push(qw, qst); return qst; } STATIC mp_obj_t load_obj(mp_reader_t *reader) { byte obj_type = read_byte(reader); if (obj_type == 'e') { return MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj); } else { size_t len = read_uint(reader, NULL); vstr_t vstr; vstr_init_len(&vstr, len); read_bytes(reader, (byte*)vstr.buf, len); if (obj_type == 's' || obj_type == 'b') { return mp_obj_new_str_from_vstr(obj_type == 's' ? &mp_type_str : &mp_type_bytes, &vstr); } else if (obj_type == 'i') { return mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } else { assert(obj_type == 'f' || obj_type == 'c'); return mp_parse_num_decimal(vstr.buf, vstr.len, obj_type == 'c', false, NULL); } } } STATIC void load_prelude_qstrs(mp_reader_t *reader, qstr_window_t *qw, byte *ip) { qstr simple_name = load_qstr(reader, qw); ip[0] = simple_name; ip[1] = simple_name >> 8; qstr source_file = load_qstr(reader, qw); ip[2] = source_file; ip[3] = source_file >> 8; } STATIC void load_prelude(mp_reader_t *reader, qstr_window_t *qw, byte **ip, bytecode_prelude_t *prelude) { // Read in the prelude header byte *ip_read = *ip; read_uint(reader, &ip_read); // read in n_state/etc (is effectively a var-uint) read_uint(reader, &ip_read); // read in n_info/n_cell (is effectively a var-uint) // Prelude header has been read into *ip, now decode and extract values from it extract_prelude((const byte**)ip, prelude); // Load qstrs in prelude load_prelude_qstrs(reader, qw, ip_read); ip_read += 4; // Read remaining code info read_bytes(reader, ip_read, *ip - ip_read); } STATIC void load_bytecode(mp_reader_t *reader, qstr_window_t *qw, byte *ip, byte *ip_top) { while (ip < ip_top) { *ip = read_byte(reader); size_t sz; uint f = mp_opcode_format(ip, &sz, false); ++ip; --sz; if (f == MP_BC_FORMAT_QSTR) { qstr qst = load_qstr(reader, qw); *ip++ = qst; *ip++ = qst >> 8; sz -= 2; } else if (f == MP_BC_FORMAT_VAR_UINT) { while ((*ip++ = read_byte(reader)) & 0x80) { } } read_bytes(reader, ip, sz); ip += sz; } } STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { // Load function kind and data length size_t kind_len = read_uint(reader, NULL); int kind = (kind_len & 3) + MP_CODE_BYTECODE; size_t fun_data_len = kind_len >> 2; #if !MICROPY_EMIT_MACHINE_CODE if (kind != MP_CODE_BYTECODE) { mp_raise_ValueError("incompatible .mpy file"); } #endif uint8_t *fun_data = NULL; bytecode_prelude_t prelude = {0}; #if MICROPY_EMIT_MACHINE_CODE size_t prelude_offset = 0; mp_uint_t type_sig = 0; size_t n_qstr_link = 0; #endif if (kind == MP_CODE_BYTECODE) { // Allocate memory for the bytecode fun_data = m_new(uint8_t, fun_data_len); // Load prelude byte *ip = fun_data; load_prelude(reader, qw, &ip, &prelude); // Load bytecode load_bytecode(reader, qw, ip, fun_data + fun_data_len); #if MICROPY_EMIT_MACHINE_CODE } else { // Allocate memory for native data and load it size_t fun_alloc; MP_PLAT_ALLOC_EXEC(fun_data_len, (void**)&fun_data, &fun_alloc); read_bytes(reader, fun_data, fun_data_len); if (kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER) { // Parse qstr link table and link native code n_qstr_link = read_uint(reader, NULL); for (size_t i = 0; i < n_qstr_link; ++i) { size_t off = read_uint(reader, NULL); qstr qst = load_qstr(reader, qw); uint8_t *dest = fun_data + (off >> 2); if ((off & 3) == 0) { // Generic 16-bit link dest[0] = qst & 0xff; dest[1] = (qst >> 8) & 0xff; } else if ((off & 3) == 3) { // Generic, aligned qstr-object link *(mp_obj_t*)dest = MP_OBJ_NEW_QSTR(qst); } else { // Architecture-specific link arch_link_qstr(dest, (off & 3) == 2, qst); } } } if (kind == MP_CODE_NATIVE_PY) { // Extract prelude for later use prelude_offset = read_uint(reader, NULL); const byte *ip = fun_data + prelude_offset; byte *ip_info = extract_prelude(&ip, &prelude); // Load qstrs in prelude load_prelude_qstrs(reader, qw, ip_info); } else { // Load basic scope info for viper and asm prelude.scope_flags = read_uint(reader, NULL); prelude.n_pos_args = 0; prelude.n_kwonly_args = 0; if (kind == MP_CODE_NATIVE_ASM) { prelude.n_pos_args = read_uint(reader, NULL); type_sig = read_uint(reader, NULL); } } #endif } size_t n_obj = 0; size_t n_raw_code = 0; mp_uint_t *const_table = NULL; if (kind != MP_CODE_NATIVE_ASM) { // Load constant table for bytecode, native and viper // Number of entries in constant table n_obj = read_uint(reader, NULL); n_raw_code = read_uint(reader, NULL); // Allocate constant table size_t n_alloc = prelude.n_pos_args + prelude.n_kwonly_args + n_obj + n_raw_code; #if MICROPY_EMIT_MACHINE_CODE if (kind != MP_CODE_BYTECODE) { ++n_alloc; // additional entry for mp_fun_table if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) { ++n_alloc; // additional entry for rodata } if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) { ++n_alloc; // additional entry for BSS } } #endif const_table = m_new(mp_uint_t, n_alloc); mp_uint_t *ct = const_table; // Load function argument names (initial entries in const_table) // (viper has n_pos_args=n_kwonly_args=0 so doesn't load any qstrs here) for (size_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) { *ct++ = (mp_uint_t)MP_OBJ_NEW_QSTR(load_qstr(reader, qw)); } #if MICROPY_EMIT_MACHINE_CODE if (kind != MP_CODE_BYTECODE) { // Populate mp_fun_table entry *ct++ = (mp_uint_t)(uintptr_t)&mp_fun_table; // Allocate and load rodata if needed if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) { size_t size = read_uint(reader, NULL); uint8_t *rodata = m_new(uint8_t, size); read_bytes(reader, rodata, size); *ct++ = (uintptr_t)rodata; } // Allocate BSS if needed if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) { size_t size = read_uint(reader, NULL); uint8_t *bss = m_new0(uint8_t, size); *ct++ = (uintptr_t)bss; } } #endif // Load constant objects and raw code children for (size_t i = 0; i < n_obj; ++i) { *ct++ = (mp_uint_t)load_obj(reader); } for (size_t i = 0; i < n_raw_code; ++i) { *ct++ = (mp_uint_t)(uintptr_t)load_raw_code(reader, qw); } } // Create raw_code and return it mp_raw_code_t *rc = mp_emit_glue_new_raw_code(); if (kind == MP_CODE_BYTECODE) { // Assign bytecode to raw code object mp_emit_glue_assign_bytecode(rc, fun_data, #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS fun_data_len, #endif const_table, #if MICROPY_PERSISTENT_CODE_SAVE n_obj, n_raw_code, #endif prelude.scope_flags); #if MICROPY_EMIT_MACHINE_CODE } else { // Relocate and commit code to executable address space reloc_info_t ri = {reader, const_table}; #if defined(MP_PLAT_COMMIT_EXEC) void *opt_ri = (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) ? &ri : NULL; fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len, opt_ri); #else if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) { mp_native_relocate(&ri, fun_data, (uintptr_t)fun_data); } #endif // Assign native code to raw code object mp_emit_glue_assign_native(rc, kind, fun_data, fun_data_len, const_table, #if MICROPY_PERSISTENT_CODE_SAVE prelude_offset, n_obj, n_raw_code, n_qstr_link, NULL, #endif prelude.n_pos_args, prelude.scope_flags, type_sig); #endif } return rc; } mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) { byte header[4]; read_bytes(reader, header, sizeof(header)); if (header[0] != 'M' || header[1] != MPY_VERSION || MPY_FEATURE_DECODE_FLAGS(header[2]) != MPY_FEATURE_FLAGS || header[3] > mp_small_int_bits() || read_uint(reader, NULL) > QSTR_WINDOW_SIZE) { mp_raise_ValueError("incompatible .mpy file"); } if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) { byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); if (!MPY_FEATURE_ARCH_TEST(arch)) { mp_raise_ValueError("incompatible .mpy arch"); } } qstr_window_t qw; qw.idx = 0; mp_raw_code_t *rc = load_raw_code(reader, &qw); reader->close(reader->data); return rc; } mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) { mp_reader_t reader; mp_reader_new_mem(&reader, buf, len, 0); return mp_raw_code_load(&reader); } #if MICROPY_HAS_FILE_READER mp_raw_code_t *mp_raw_code_load_file(const char *filename) { mp_reader_t reader; mp_reader_new_file(&reader, filename); return mp_raw_code_load(&reader); } #endif // MICROPY_HAS_FILE_READER #endif // MICROPY_PERSISTENT_CODE_LOAD #if MICROPY_PERSISTENT_CODE_SAVE #include "py/objstr.h" STATIC void mp_print_bytes(mp_print_t *print, const byte *data, size_t len) { print->print_strn(print->data, (const char*)data, len); } #define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7) STATIC void mp_print_uint(mp_print_t *print, size_t n) { byte buf[BYTES_FOR_INT]; byte *p = buf + sizeof(buf); *--p = n & 0x7f; n >>= 7; for (; n != 0; n >>= 7) { *--p = 0x80 | (n & 0x7f); } print->print_strn(print->data, (char*)p, buf + sizeof(buf) - p); } STATIC void save_qstr(mp_print_t *print, qstr_window_t *qw, qstr qst) { if (qst <= QSTR_LAST_STATIC) { // encode static qstr byte buf[2] = {0, qst & 0xff}; mp_print_bytes(print, buf, 2); return; } size_t idx = qstr_window_insert(qw, qst); if (idx < QSTR_WINDOW_SIZE) { // qstr found in window, encode index to it mp_print_uint(print, idx << 1 | 1); return; } size_t len; const byte *str = qstr_data(qst, &len); mp_print_uint(print, len << 1); mp_print_bytes(print, str, len); } STATIC void save_obj(mp_print_t *print, mp_obj_t o) { if (mp_obj_is_str_or_bytes(o)) { byte obj_type; if (mp_obj_is_str(o)) { obj_type = 's'; } else { obj_type = 'b'; } size_t len; const char *str = mp_obj_str_get_data(o, &len); mp_print_bytes(print, &obj_type, 1); mp_print_uint(print, len); mp_print_bytes(print, (const byte*)str, len); } else if (MP_OBJ_TO_PTR(o) == &mp_const_ellipsis_obj) { byte obj_type = 'e'; mp_print_bytes(print, &obj_type, 1); } else { // we save numbers using a simplistic text representation // TODO could be improved byte obj_type; if (mp_obj_is_type(o, &mp_type_int)) { obj_type = 'i'; #if MICROPY_PY_BUILTINS_COMPLEX } else if (mp_obj_is_type(o, &mp_type_complex)) { obj_type = 'c'; #endif } else { assert(mp_obj_is_float(o)); obj_type = 'f'; } vstr_t vstr; mp_print_t pr; vstr_init_print(&vstr, 10, &pr); mp_obj_print_helper(&pr, o, PRINT_REPR); mp_print_bytes(print, &obj_type, 1); mp_print_uint(print, vstr.len); mp_print_bytes(print, (const byte*)vstr.buf, vstr.len); vstr_clear(&vstr); } } STATIC void save_prelude_qstrs(mp_print_t *print, qstr_window_t *qw, const byte *ip) { save_qstr(print, qw, ip[0] | (ip[1] << 8)); // simple_name save_qstr(print, qw, ip[2] | (ip[3] << 8)); // source_file } STATIC void save_bytecode(mp_print_t *print, qstr_window_t *qw, const byte *ip, const byte *ip_top) { while (ip < ip_top) { size_t sz; uint f = mp_opcode_format(ip, &sz, true); if (f == MP_BC_FORMAT_QSTR) { mp_print_bytes(print, ip, 1); qstr qst = ip[1] | (ip[2] << 8); save_qstr(print, qw, qst); ip += 3; sz -= 3; } mp_print_bytes(print, ip, sz); ip += sz; } } STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *qstr_window) { // Save function kind and data length mp_print_uint(print, (rc->fun_data_len << 2) | (rc->kind - MP_CODE_BYTECODE)); bytecode_prelude_t prelude; if (rc->kind == MP_CODE_BYTECODE) { // Extract prelude const byte *ip = rc->fun_data; const byte *ip_info = extract_prelude(&ip, &prelude); // Save prelude mp_print_bytes(print, rc->fun_data, ip_info - (const byte*)rc->fun_data); save_prelude_qstrs(print, qstr_window, ip_info); ip_info += 4; mp_print_bytes(print, ip_info, ip - ip_info); // Save bytecode const byte *ip_top = (const byte*)rc->fun_data + rc->fun_data_len; save_bytecode(print, qstr_window, ip, ip_top); #if MICROPY_EMIT_MACHINE_CODE } else { // Save native code mp_print_bytes(print, rc->fun_data, rc->fun_data_len); if (rc->kind == MP_CODE_NATIVE_PY || rc->kind == MP_CODE_NATIVE_VIPER) { // Save qstr link table for native code mp_print_uint(print, rc->n_qstr); for (size_t i = 0; i < rc->n_qstr; ++i) { mp_print_uint(print, rc->qstr_link[i].off); save_qstr(print, qstr_window, rc->qstr_link[i].qst); } } if (rc->kind == MP_CODE_NATIVE_PY) { // Save prelude size mp_print_uint(print, rc->prelude_offset); // Extract prelude and save qstrs in prelude const byte *ip = (const byte*)rc->fun_data + rc->prelude_offset; const byte *ip_info = extract_prelude(&ip, &prelude); save_prelude_qstrs(print, qstr_window, ip_info); } else { // Save basic scope info for viper and asm mp_print_uint(print, rc->scope_flags & MP_SCOPE_FLAG_ALL_SIG); prelude.n_pos_args = 0; prelude.n_kwonly_args = 0; if (rc->kind == MP_CODE_NATIVE_ASM) { mp_print_uint(print, rc->n_pos_args); mp_print_uint(print, rc->type_sig); } } #endif } if (rc->kind != MP_CODE_NATIVE_ASM) { // Save constant table for bytecode, native and viper // Number of entries in constant table mp_print_uint(print, rc->n_obj); mp_print_uint(print, rc->n_raw_code); const mp_uint_t *const_table = rc->const_table; // Save function argument names (initial entries in const_table) // (viper has n_pos_args=n_kwonly_args=0 so doesn't save any qstrs here) for (size_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) { mp_obj_t o = (mp_obj_t)*const_table++; save_qstr(print, qstr_window, MP_OBJ_QSTR_VALUE(o)); } if (rc->kind != MP_CODE_BYTECODE) { // Skip saving mp_fun_table entry ++const_table; } // Save constant objects and raw code children for (size_t i = 0; i < rc->n_obj; ++i) { save_obj(print, (mp_obj_t)*const_table++); } for (size_t i = 0; i < rc->n_raw_code; ++i) { save_raw_code(print, (mp_raw_code_t*)(uintptr_t)*const_table++, qstr_window); } } } STATIC bool mp_raw_code_has_native(mp_raw_code_t *rc) { if (rc->kind != MP_CODE_BYTECODE) { return true; } const byte *ip = rc->fun_data; bytecode_prelude_t prelude; extract_prelude(&ip, &prelude); const mp_uint_t *const_table = rc->const_table + prelude.n_pos_args + prelude.n_kwonly_args + rc->n_obj; for (size_t i = 0; i < rc->n_raw_code; ++i) { if (mp_raw_code_has_native((mp_raw_code_t*)(uintptr_t)*const_table++)) { return true; } } return false; } void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) { // header contains: // byte 'M' // byte version // byte feature flags // byte number of bits in a small int // uint size of qstr window byte header[4] = { 'M', MPY_VERSION, MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS_DYNAMIC), #if MICROPY_DYNAMIC_COMPILER mp_dynamic_compiler.small_int_bits, #else mp_small_int_bits(), #endif }; if (mp_raw_code_has_native(rc)) { header[2] |= MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC); } mp_print_bytes(print, header, sizeof(header)); mp_print_uint(print, QSTR_WINDOW_SIZE); qstr_window_t qw; qw.idx = 0; memset(qw.window, 0, sizeof(qw.window)); save_raw_code(print, rc, &qw); } // here we define mp_raw_code_save_file depending on the port // TODO abstract this away properly #if defined(__i386__) || defined(__x86_64__) || defined(_WIN32) || defined(__unix__) #include #include #include STATIC void fd_print_strn(void *env, const char *str, size_t len) { int fd = (intptr_t)env; ssize_t ret = write(fd, str, len); (void)ret; } void mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename) { int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); mp_print_t fd_print = {(void*)(intptr_t)fd, fd_print_strn}; mp_raw_code_save(rc, &fd_print); close(fd); } #else #error mp_raw_code_save_file not implemented for this platform #endif #endif // MICROPY_PERSISTENT_CODE_SAVE micropython-1.12/py/persistentcode.h000066400000000000000000000104341357706137100176600ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_PERSISTENTCODE_H #define MICROPY_INCLUDED_PY_PERSISTENTCODE_H #include "py/mpprint.h" #include "py/reader.h" #include "py/emitglue.h" // The current version of .mpy files #define MPY_VERSION 5 // Macros to encode/decode flags to/from the feature byte #define MPY_FEATURE_ENCODE_FLAGS(flags) (flags) #define MPY_FEATURE_DECODE_FLAGS(feat) ((feat) & 3) // Macros to encode/decode native architecture to/from the feature byte #define MPY_FEATURE_ENCODE_ARCH(arch) ((arch) << 2) #define MPY_FEATURE_DECODE_ARCH(feat) ((feat) >> 2) // The feature flag bits encode the compile-time config options that // affect the generate bytecode. #define MPY_FEATURE_FLAGS ( \ ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) << 0) \ | ((MICROPY_PY_BUILTINS_STR_UNICODE) << 1) \ ) // This is a version of the flags that can be configured at runtime. #define MPY_FEATURE_FLAGS_DYNAMIC ( \ ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) << 0) \ | ((MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) << 1) \ ) // Define the host architecture #if MICROPY_EMIT_X86 #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X86) #elif MICROPY_EMIT_X64 #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X64) #elif MICROPY_EMIT_THUMB #if defined(__thumb2__) #if defined(__ARM_FP) && (__ARM_FP & 8) == 8 #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7EMDP) #elif defined(__ARM_FP) && (__ARM_FP & 4) == 4 #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7EMSP) #else #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7EM) #endif #else #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7M) #endif #define MPY_FEATURE_ARCH_TEST(x) (MP_NATIVE_ARCH_ARMV6M <= (x) && (x) <= MPY_FEATURE_ARCH) #elif MICROPY_EMIT_ARM #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV6) #elif MICROPY_EMIT_XTENSA #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSA) #elif MICROPY_EMIT_XTENSAWIN #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSAWIN) #else #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_NONE) #endif #ifndef MPY_FEATURE_ARCH_TEST #define MPY_FEATURE_ARCH_TEST(x) ((x) == MPY_FEATURE_ARCH) #endif // 16-bit little-endian integer with the second and third bytes of supported .mpy files #define MPY_FILE_HEADER_INT (MPY_VERSION \ | (MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH)) << 8) enum { MP_NATIVE_ARCH_NONE = 0, MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64, MP_NATIVE_ARCH_ARMV6, MP_NATIVE_ARCH_ARMV6M, MP_NATIVE_ARCH_ARMV7M, MP_NATIVE_ARCH_ARMV7EM, MP_NATIVE_ARCH_ARMV7EMSP, MP_NATIVE_ARCH_ARMV7EMDP, MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN, }; mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader); mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len); mp_raw_code_t *mp_raw_code_load_file(const char *filename); void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print); void mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename); void mp_native_relocate(void *reloc, uint8_t *text, uintptr_t reloc_text); #endif // MICROPY_INCLUDED_PY_PERSISTENTCODE_H micropython-1.12/py/profile.c000066400000000000000000000765521357706137100162750ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) SatoshiLabs * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/profile.h" #include "py/bc0.h" #include "py/gc.h" #if MICROPY_PY_SYS_SETTRACE #define prof_trace_cb MP_STATE_THREAD(prof_trace_callback) STATIC uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) { const mp_bytecode_prelude_t *prelude = &rc->prelude; return mp_bytecode_get_source_line(prelude->line_info, bc); } void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude) { const byte *ip = bytecode; MP_BC_PRELUDE_SIG_DECODE(ip); prelude->n_state = n_state; prelude->n_exc_stack = n_exc_stack; prelude->scope_flags = scope_flags; prelude->n_pos_args = n_pos_args; prelude->n_kwonly_args = n_kwonly_args; prelude->n_def_pos_args = n_def_pos_args; MP_BC_PRELUDE_SIZE_DECODE(ip); prelude->line_info = ip + 4; prelude->opcodes = ip + n_info + n_cell; qstr block_name = ip[0] | (ip[1] << 8); qstr source_file = ip[2] | (ip[3] << 8); prelude->qstr_block_name = block_name; prelude->qstr_source_file = source_file; } /******************************************************************************/ // code object STATIC void code_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_code_t *o = MP_OBJ_TO_PTR(o_in); const mp_raw_code_t *rc = o->rc; const mp_bytecode_prelude_t *prelude = &rc->prelude; mp_printf(print, "", prelude->qstr_block_name, o, prelude->qstr_source_file, rc->line_of_definition ); } STATIC mp_obj_tuple_t* code_consts(const mp_raw_code_t *rc) { const mp_bytecode_prelude_t *prelude = &rc->prelude; int start = prelude->n_pos_args + prelude->n_kwonly_args + rc->n_obj; int stop = prelude->n_pos_args + prelude->n_kwonly_args + rc->n_obj + rc->n_raw_code; mp_obj_tuple_t *consts = MP_OBJ_TO_PTR(mp_obj_new_tuple(stop - start + 1, NULL)); size_t const_no = 0; for (int i = start; i < stop; ++i) { mp_obj_t code = mp_obj_new_code((const mp_raw_code_t*)MP_OBJ_TO_PTR(rc->const_table[i])); if (code == MP_OBJ_NULL) { m_malloc_fail(sizeof(mp_obj_code_t)); } consts->items[const_no++] = code; } consts->items[const_no++] = mp_const_none; return consts; } STATIC mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) { // const mp_bytecode_prelude_t *prelude = &rc->prelude; uint start = 0; uint stop = rc->fun_data_len - start; uint last_lineno = mp_prof_bytecode_lineno(rc, start); uint lasti = 0; const uint buffer_chunk_size = (stop-start) >> 2; // heuristic magic uint buffer_size = buffer_chunk_size; byte *buffer = m_new(byte, buffer_size); uint buffer_index = 0; for (uint i = start; i < stop; ++i) { uint lineno = mp_prof_bytecode_lineno(rc, i); size_t line_diff = lineno - last_lineno; if (line_diff > 0) { uint instr_diff = (i - start) - lasti; assert(instr_diff < 256); assert(line_diff < 256); if (buffer_index + 2 > buffer_size) { buffer = m_renew(byte, buffer, buffer_size, buffer_size + buffer_chunk_size); buffer_size = buffer_size + buffer_chunk_size; } last_lineno = lineno; lasti = i - start; buffer[buffer_index++] = instr_diff; buffer[buffer_index++] = line_diff; } } mp_obj_t o = mp_obj_new_bytes(buffer, buffer_index); m_del(byte, buffer, buffer_size); return o; } STATIC void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } mp_obj_code_t *o = MP_OBJ_TO_PTR(self_in); const mp_raw_code_t *rc = o->rc; const mp_bytecode_prelude_t *prelude = &rc->prelude; switch(attr) { case MP_QSTR_co_code: dest[0] = mp_obj_new_bytes( (void*)prelude->opcodes, rc->fun_data_len - (prelude->opcodes - (const byte*)rc->fun_data) ); break; case MP_QSTR_co_consts: dest[0] = MP_OBJ_FROM_PTR(code_consts(rc)); break; case MP_QSTR_co_filename: dest[0] = MP_OBJ_NEW_QSTR(prelude->qstr_source_file); break; case MP_QSTR_co_firstlineno: dest[0] = MP_OBJ_NEW_SMALL_INT(mp_prof_bytecode_lineno(rc, 0)); break; case MP_QSTR_co_name: dest[0] = MP_OBJ_NEW_QSTR(prelude->qstr_block_name); break; case MP_QSTR_co_names: dest[0] = MP_OBJ_FROM_PTR(o->dict_locals); break; case MP_QSTR_co_lnotab: if (!o->lnotab) { o->lnotab = raw_code_lnotab(rc); } dest[0] = o->lnotab; break; } } const mp_obj_type_t mp_type_code = { { &mp_type_type }, .name = MP_QSTR_code, .print = code_print, .unary_op = mp_generic_unary_op, .attr = code_attr, }; mp_obj_t mp_obj_new_code(const mp_raw_code_t *rc) { mp_obj_code_t *o = m_new_obj_maybe(mp_obj_code_t); if (o == NULL) { return MP_OBJ_NULL; } o->base.type = &mp_type_code; o->rc = rc; o->dict_locals = mp_locals_get(); // this is a wrong! how to do this properly? o->lnotab = MP_OBJ_NULL; return MP_OBJ_FROM_PTR(o); } /******************************************************************************/ // frame object STATIC void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_frame_t *frame = MP_OBJ_TO_PTR(o_in); mp_obj_code_t *code = frame->code; const mp_raw_code_t *rc = code->rc; const mp_bytecode_prelude_t *prelude = &rc->prelude; mp_printf(print, "", frame, prelude->qstr_source_file, frame->lineno, prelude->qstr_block_name ); } STATIC void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } mp_obj_frame_t *o = MP_OBJ_TO_PTR(self_in); switch(attr) { case MP_QSTR_f_back: dest[0] = mp_const_none; if (o->code_state->prev_state) { dest[0] = MP_OBJ_FROM_PTR(o->code_state->prev_state->frame); } break; case MP_QSTR_f_code: dest[0] = MP_OBJ_FROM_PTR(o->code); break; case MP_QSTR_f_globals: dest[0] = MP_OBJ_FROM_PTR(o->code_state->fun_bc->globals); break; case MP_QSTR_f_lasti: dest[0] = MP_OBJ_NEW_SMALL_INT(o->lasti); break; case MP_QSTR_f_lineno: dest[0] = MP_OBJ_NEW_SMALL_INT(o->lineno); break; } } const mp_obj_type_t mp_type_frame = { { &mp_type_type }, .name = MP_QSTR_frame, .print = frame_print, .unary_op = mp_generic_unary_op, .attr = frame_attr, }; mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state) { if (gc_is_locked()) { return MP_OBJ_NULL; } mp_obj_frame_t *o = m_new_obj_maybe(mp_obj_frame_t); if (o == NULL) { return MP_OBJ_NULL; } mp_obj_code_t *code = o->code = MP_OBJ_TO_PTR(mp_obj_new_code(code_state->fun_bc->rc)); if (code == NULL) { return MP_OBJ_NULL; } const mp_raw_code_t *rc = code->rc; const mp_bytecode_prelude_t *prelude = &rc->prelude; o->code_state = code_state; o->base.type = &mp_type_frame; o->back = NULL; o->code = code; o->lasti = code_state->ip - prelude->opcodes; o->lineno = mp_prof_bytecode_lineno(rc, o->lasti); o->trace_opcodes = false; o->callback = MP_OBJ_NULL; return MP_OBJ_FROM_PTR(o); } /******************************************************************************/ // Trace logic typedef struct { struct _mp_obj_frame_t * frame; mp_obj_t event; mp_obj_t arg; } prof_callback_args_t; STATIC mp_obj_t mp_prof_callback_invoke(mp_obj_t callback, prof_callback_args_t *args) { assert(mp_obj_is_callable(callback)); mp_prof_is_executing = true; mp_obj_t a[3] = {MP_OBJ_FROM_PTR(args->frame), args->event, args->arg}; mp_obj_t top = mp_call_function_n_kw(callback, 3, 0, a); mp_prof_is_executing = false; if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } return top; } mp_obj_t mp_prof_settrace(mp_obj_t callback) { if (mp_obj_is_callable(callback)) { prof_trace_cb = callback; } else { prof_trace_cb = MP_OBJ_NULL; } return mp_const_none; } mp_obj_t mp_prof_frame_enter(mp_code_state_t *code_state) { assert(!mp_prof_is_executing); mp_obj_frame_t *frame = MP_OBJ_TO_PTR(mp_obj_new_frame(code_state)); if (frame == NULL) { // Couldn't allocate a frame object return MP_OBJ_NULL; } if (code_state->prev_state && code_state->frame == NULL) { // We are entering not-yet-traced frame // which means it's a CALL event (not a GENERATOR) // so set the function definition line. const mp_raw_code_t *rc = code_state->fun_bc->rc; frame->lineno = rc->line_of_definition; if (!rc->line_of_definition) { frame->lineno = mp_prof_bytecode_lineno(rc, 0); } } code_state->frame = frame; if (!prof_trace_cb) { return MP_OBJ_NULL; } mp_obj_t top; prof_callback_args_t _args, *args=&_args; args->frame = code_state->frame; // SETTRACE event CALL args->event = MP_OBJ_NEW_QSTR(MP_QSTR_call); args->arg = mp_const_none; top = mp_prof_callback_invoke(prof_trace_cb, args); code_state->frame->callback = mp_obj_is_callable(top) ? top : MP_OBJ_NULL; // Invalidate the last executed line number so the LINE trace can trigger after this CALL. frame->lineno = 0; return top; } mp_obj_t mp_prof_frame_update(const mp_code_state_t *code_state) { mp_obj_frame_t *frame = code_state->frame; if (frame == NULL) { // Frame was not allocated (eg because there was no memory available) return MP_OBJ_NULL; } mp_obj_frame_t *o = frame; mp_obj_code_t *code = o->code; const mp_raw_code_t *rc = code->rc; const mp_bytecode_prelude_t *prelude = &rc->prelude; assert(o->code_state == code_state); o->lasti = code_state->ip - prelude->opcodes; o->lineno = mp_prof_bytecode_lineno(rc, o->lasti); return MP_OBJ_FROM_PTR(o); } mp_obj_t mp_prof_instr_tick(mp_code_state_t *code_state, bool is_exception) { // Detect execution recursion assert(!mp_prof_is_executing); assert(code_state->frame); assert(mp_obj_get_type(code_state->frame) == &mp_type_frame); // Detect data recursion assert(code_state != code_state->prev_state); mp_obj_t top = mp_const_none; mp_obj_t callback = code_state->frame->callback; prof_callback_args_t _args, *args=&_args; args->frame = code_state->frame; args->event = mp_const_none; args->arg = mp_const_none; // Call event's are handled inside mp_prof_frame_enter // SETTRACE event EXCEPTION if (is_exception) { args->event = MP_OBJ_NEW_QSTR(MP_QSTR_exception); top = mp_prof_callback_invoke(callback, args); return top; } // SETTRACE event LINE const mp_raw_code_t *rc = code_state->fun_bc->rc; const mp_bytecode_prelude_t *prelude = &rc->prelude; size_t prev_line_no = args->frame->lineno; size_t current_line_no = mp_prof_bytecode_lineno(rc, code_state->ip - prelude->opcodes); if (prev_line_no != current_line_no) { args->frame->lineno = current_line_no; args->event = MP_OBJ_NEW_QSTR(MP_QSTR_line); top = mp_prof_callback_invoke(callback, args); } // SETTRACE event RETURN const byte *ip = code_state->ip; if (*ip == MP_BC_RETURN_VALUE || *ip == MP_BC_YIELD_VALUE) { args->event = MP_OBJ_NEW_QSTR(MP_QSTR_return); top = mp_prof_callback_invoke(callback, args); if (code_state->prev_state && *ip == MP_BC_RETURN_VALUE) { code_state->frame->callback = MP_OBJ_NULL; } } // SETTRACE event OPCODE // TODO: frame.f_trace_opcodes=True if (false) { args->event = MP_OBJ_NEW_QSTR(MP_QSTR_opcode); } return top; } /******************************************************************************/ // DEBUG // This section is for debugging the settrace feature itself, and is not intended // to be included in production/release builds. The code structure for this block // was taken from py/showbc.c and should not be used as a reference. To enable // this debug feature enable MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE in py/profile.h. #if MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE #include "runtime0.h" #define DECODE_UINT { \ unum = 0; \ do { \ unum = (unum << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0); \ } #define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0) #define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0) #define DECODE_QSTR \ qst = ip[0] | ip[1] << 8; \ ip += 2; #define DECODE_PTR \ DECODE_UINT; \ ptr = (const byte*)const_table[unum] #define DECODE_OBJ \ DECODE_UINT; \ obj = (mp_obj_t)const_table[unum] typedef struct _mp_dis_instruction_t { mp_uint_t qstr_opname; mp_uint_t arg; mp_obj_t argobj; mp_obj_t argobjex_cache; } mp_dis_instruction_t; STATIC const byte *mp_prof_opcode_decode(const byte *ip, const mp_uint_t *const_table, mp_dis_instruction_t *instruction) { mp_uint_t unum; const byte* ptr; mp_obj_t obj; qstr qst; instruction->qstr_opname = MP_QSTR_; instruction->arg = 0; instruction->argobj= mp_const_none; instruction->argobjex_cache = mp_const_none; switch (*ip++) { case MP_BC_LOAD_CONST_FALSE: instruction->qstr_opname = MP_QSTR_LOAD_CONST_FALSE; break; case MP_BC_LOAD_CONST_NONE: instruction->qstr_opname = MP_QSTR_LOAD_CONST_NONE; break; case MP_BC_LOAD_CONST_TRUE: instruction->qstr_opname = MP_QSTR_LOAD_CONST_TRUE; break; case MP_BC_LOAD_CONST_SMALL_INT: { mp_int_t num = 0; if ((ip[0] & 0x40) != 0) { // Number is negative num--; } do { num = (num << 7) | (*ip & 0x7f); } while ((*ip++ & 0x80) != 0); instruction->qstr_opname = MP_QSTR_LOAD_CONST_SMALL_INT; instruction->arg = num; break; } case MP_BC_LOAD_CONST_STRING: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_LOAD_CONST_STRING; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_LOAD_CONST_OBJ: DECODE_OBJ; instruction->qstr_opname = MP_QSTR_LOAD_CONST_OBJ; instruction->arg = unum; instruction->argobj= obj; break; case MP_BC_LOAD_NULL: instruction->qstr_opname = MP_QSTR_LOAD_NULL; break; case MP_BC_LOAD_FAST_N: DECODE_UINT; instruction->qstr_opname = MP_QSTR_LOAD_FAST_N; instruction->arg = unum; break; case MP_BC_LOAD_DEREF: DECODE_UINT; instruction->qstr_opname = MP_QSTR_LOAD_DEREF; instruction->arg = unum; break; case MP_BC_LOAD_NAME: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_LOAD_NAME; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++); } break; case MP_BC_LOAD_GLOBAL: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_LOAD_GLOBAL; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++); } break; case MP_BC_LOAD_ATTR: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_LOAD_ATTR; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++); } break; case MP_BC_LOAD_METHOD: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_LOAD_METHOD; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_LOAD_SUPER_METHOD: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_LOAD_SUPER_METHOD; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_LOAD_BUILD_CLASS: instruction->qstr_opname = MP_QSTR_LOAD_BUILD_CLASS; break; case MP_BC_LOAD_SUBSCR: instruction->qstr_opname = MP_QSTR_LOAD_SUBSCR; break; case MP_BC_STORE_FAST_N: DECODE_UINT; instruction->qstr_opname = MP_QSTR_STORE_FAST_N; instruction->arg = unum; break; case MP_BC_STORE_DEREF: DECODE_UINT; instruction->qstr_opname = MP_QSTR_STORE_DEREF; instruction->arg = unum; break; case MP_BC_STORE_NAME: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_STORE_NAME; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_STORE_GLOBAL: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_STORE_GLOBAL; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_STORE_ATTR: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_STORE_ATTR; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++); } break; case MP_BC_STORE_SUBSCR: instruction->qstr_opname = MP_QSTR_STORE_SUBSCR; break; case MP_BC_DELETE_FAST: DECODE_UINT; instruction->qstr_opname = MP_QSTR_DELETE_FAST; instruction->arg = unum; break; case MP_BC_DELETE_DEREF: DECODE_UINT; instruction->qstr_opname = MP_QSTR_DELETE_DEREF; instruction->arg = unum; break; case MP_BC_DELETE_NAME: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_DELETE_NAME; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_DELETE_GLOBAL: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_DELETE_GLOBAL; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_DUP_TOP: instruction->qstr_opname = MP_QSTR_DUP_TOP; break; case MP_BC_DUP_TOP_TWO: instruction->qstr_opname = MP_QSTR_DUP_TOP_TWO; break; case MP_BC_POP_TOP: instruction->qstr_opname = MP_QSTR_POP_TOP; break; case MP_BC_ROT_TWO: instruction->qstr_opname = MP_QSTR_ROT_TWO; break; case MP_BC_ROT_THREE: instruction->qstr_opname = MP_QSTR_ROT_THREE; break; case MP_BC_JUMP: DECODE_SLABEL; instruction->qstr_opname = MP_QSTR_JUMP; instruction->arg = unum; break; case MP_BC_POP_JUMP_IF_TRUE: DECODE_SLABEL; instruction->qstr_opname = MP_QSTR_POP_JUMP_IF_TRUE; instruction->arg = unum; break; case MP_BC_POP_JUMP_IF_FALSE: DECODE_SLABEL; instruction->qstr_opname = MP_QSTR_POP_JUMP_IF_FALSE; instruction->arg = unum; break; case MP_BC_JUMP_IF_TRUE_OR_POP: DECODE_SLABEL; instruction->qstr_opname = MP_QSTR_JUMP_IF_TRUE_OR_POP; instruction->arg = unum; break; case MP_BC_JUMP_IF_FALSE_OR_POP: DECODE_SLABEL; instruction->qstr_opname = MP_QSTR_JUMP_IF_FALSE_OR_POP; instruction->arg = unum; break; case MP_BC_SETUP_WITH: DECODE_ULABEL; // loop-like labels are always forward instruction->qstr_opname = MP_QSTR_SETUP_WITH; instruction->arg = unum; break; case MP_BC_WITH_CLEANUP: instruction->qstr_opname = MP_QSTR_WITH_CLEANUP; break; case MP_BC_UNWIND_JUMP: DECODE_SLABEL; instruction->qstr_opname = MP_QSTR_UNWIND_JUMP; instruction->arg = unum; break; case MP_BC_SETUP_EXCEPT: DECODE_ULABEL; // except labels are always forward instruction->qstr_opname = MP_QSTR_SETUP_EXCEPT; instruction->arg = unum; break; case MP_BC_SETUP_FINALLY: DECODE_ULABEL; // except labels are always forward instruction->qstr_opname = MP_QSTR_SETUP_FINALLY; instruction->arg = unum; break; case MP_BC_END_FINALLY: // if TOS is an exception, reraises the exception (3 values on TOS) // if TOS is an integer, does something else // if TOS is None, just pops it and continues // else error instruction->qstr_opname = MP_QSTR_END_FINALLY; break; case MP_BC_GET_ITER: instruction->qstr_opname = MP_QSTR_GET_ITER; break; case MP_BC_GET_ITER_STACK: instruction->qstr_opname = MP_QSTR_GET_ITER_STACK; break; case MP_BC_FOR_ITER: DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward instruction->qstr_opname = MP_QSTR_FOR_ITER; instruction->arg = unum; break; case MP_BC_BUILD_TUPLE: DECODE_UINT; instruction->qstr_opname = MP_QSTR_BUILD_TUPLE; instruction->arg = unum; break; case MP_BC_BUILD_LIST: DECODE_UINT; instruction->qstr_opname = MP_QSTR_BUILD_LIST; instruction->arg = unum; break; case MP_BC_BUILD_MAP: DECODE_UINT; instruction->qstr_opname = MP_QSTR_BUILD_MAP; instruction->arg = unum; break; case MP_BC_STORE_MAP: instruction->qstr_opname = MP_QSTR_STORE_MAP; break; case MP_BC_BUILD_SET: DECODE_UINT; instruction->qstr_opname = MP_QSTR_BUILD_SET; instruction->arg = unum; break; #if MICROPY_PY_BUILTINS_SLICE case MP_BC_BUILD_SLICE: DECODE_UINT; instruction->qstr_opname = MP_QSTR_BUILD_SLICE; instruction->arg = unum; break; #endif case MP_BC_STORE_COMP: DECODE_UINT; instruction->qstr_opname = MP_QSTR_STORE_COMP; instruction->arg = unum; break; case MP_BC_UNPACK_SEQUENCE: DECODE_UINT; instruction->qstr_opname = MP_QSTR_UNPACK_SEQUENCE; instruction->arg = unum; break; case MP_BC_UNPACK_EX: DECODE_UINT; instruction->qstr_opname = MP_QSTR_UNPACK_EX; instruction->arg = unum; break; case MP_BC_MAKE_FUNCTION: DECODE_PTR; instruction->qstr_opname = MP_QSTR_MAKE_FUNCTION; instruction->arg = unum; instruction->argobj= mp_obj_new_int_from_ull((uint64_t)ptr); break; case MP_BC_MAKE_FUNCTION_DEFARGS: DECODE_PTR; instruction->qstr_opname = MP_QSTR_MAKE_FUNCTION_DEFARGS; instruction->arg = unum; instruction->argobj= mp_obj_new_int_from_ull((uint64_t)ptr); break; case MP_BC_MAKE_CLOSURE: { DECODE_PTR; mp_uint_t n_closed_over = *ip++; instruction->qstr_opname = MP_QSTR_MAKE_CLOSURE; instruction->arg = unum; instruction->argobj= mp_obj_new_int_from_ull((uint64_t)ptr); instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(n_closed_over); break; } case MP_BC_MAKE_CLOSURE_DEFARGS: { DECODE_PTR; mp_uint_t n_closed_over = *ip++; instruction->qstr_opname = MP_QSTR_MAKE_CLOSURE_DEFARGS; instruction->arg = unum; instruction->argobj= mp_obj_new_int_from_ull((uint64_t)ptr); instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(n_closed_over); break; } case MP_BC_CALL_FUNCTION: DECODE_UINT; instruction->qstr_opname = MP_QSTR_CALL_FUNCTION; instruction->arg = unum & 0xff; instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff); break; case MP_BC_CALL_FUNCTION_VAR_KW: DECODE_UINT; instruction->qstr_opname = MP_QSTR_CALL_FUNCTION_VAR_KW; instruction->arg = unum & 0xff; instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff); break; case MP_BC_CALL_METHOD: DECODE_UINT; instruction->qstr_opname = MP_QSTR_CALL_METHOD; instruction->arg = unum & 0xff; instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff); break; case MP_BC_CALL_METHOD_VAR_KW: DECODE_UINT; instruction->qstr_opname = MP_QSTR_CALL_METHOD_VAR_KW; instruction->arg = unum & 0xff; instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff); break; case MP_BC_RETURN_VALUE: instruction->qstr_opname = MP_QSTR_RETURN_VALUE; break; case MP_BC_RAISE_LAST: instruction->qstr_opname = MP_QSTR_RAISE_LAST; break; case MP_BC_RAISE_OBJ: instruction->qstr_opname = MP_QSTR_RAISE_OBJ; break; case MP_BC_RAISE_FROM: instruction->qstr_opname = MP_QSTR_RAISE_FROM; break; case MP_BC_YIELD_VALUE: instruction->qstr_opname = MP_QSTR_YIELD_VALUE; break; case MP_BC_YIELD_FROM: instruction->qstr_opname = MP_QSTR_YIELD_FROM; break; case MP_BC_IMPORT_NAME: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_IMPORT_NAME; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_IMPORT_FROM: DECODE_QSTR; instruction->qstr_opname = MP_QSTR_IMPORT_FROM; instruction->arg = qst; instruction->argobj= MP_OBJ_NEW_QSTR(qst); break; case MP_BC_IMPORT_STAR: instruction->qstr_opname = MP_QSTR_IMPORT_STAR; break; default: if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) { instruction->qstr_opname = MP_QSTR_LOAD_CONST_SMALL_INT; instruction->arg = (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16; } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) { instruction->qstr_opname = MP_QSTR_LOAD_FAST; instruction->arg = (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI; } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) { instruction->qstr_opname = MP_QSTR_STORE_FAST; instruction->arg = (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI; } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE) { instruction->qstr_opname = MP_QSTR_UNARY_OP; instruction->arg = (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI; } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE) { mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI; instruction->qstr_opname = MP_QSTR_BINARY_OP; instruction->arg = op; } else { mp_printf(&mp_plat_print, "code %p, opcode 0x%02x not implemented\n", ip-1, ip[-1]); assert(0); return ip; } break; } return ip; } void mp_prof_print_instr(const byte* ip, mp_code_state_t *code_state) { mp_dis_instruction_t _instruction, *instruction = &_instruction; mp_prof_opcode_decode(ip, code_state->fun_bc->rc->const_table, instruction); const mp_raw_code_t *rc = code_state->fun_bc->rc; const mp_bytecode_prelude_t *prelude = &rc->prelude; mp_uint_t offset = ip - prelude->opcodes; mp_printf(&mp_plat_print, "instr"); /* long path */ if (1) { mp_printf(&mp_plat_print, "@0x%p:%q:%q+0x%04x:%d", ip, prelude->qstr_source_file, prelude->qstr_block_name, offset, mp_prof_bytecode_lineno(rc, offset) ); } /* bytecode */ if (0) { mp_printf(&mp_plat_print, " %02x %02x %02x %02x", ip[0], ip[1], ip[2], ip[3]); } mp_printf(&mp_plat_print, " 0x%02x %q [%d]", *ip, instruction->qstr_opname, instruction->arg); if (instruction->argobj != mp_const_none) { mp_printf(&mp_plat_print, " $"); mp_obj_print_helper(&mp_plat_print, instruction->argobj, PRINT_REPR); } if (instruction->argobjex_cache != mp_const_none) { mp_printf(&mp_plat_print, " #"); mp_obj_print_helper(&mp_plat_print, instruction->argobjex_cache, PRINT_REPR); } mp_printf(&mp_plat_print, "\n"); } #endif // MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE #endif // MICROPY_PY_SYS_SETTRACE micropython-1.12/py/profile.h000066400000000000000000000055771357706137100163010ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) SatoshiLabs * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_PROFILING_H #define MICROPY_INCLUDED_PY_PROFILING_H #include "py/emitglue.h" #if MICROPY_PY_SYS_SETTRACE #define mp_prof_is_executing MP_STATE_THREAD(prof_callback_is_executing) typedef struct _mp_obj_code_t { mp_obj_base_t base; const mp_raw_code_t *rc; mp_obj_dict_t *dict_locals; mp_obj_t lnotab; } mp_obj_code_t; typedef struct _mp_obj_frame_t { mp_obj_base_t base; const mp_code_state_t *code_state; struct _mp_obj_frame_t *back; mp_obj_t callback; mp_obj_code_t *code; mp_uint_t lasti; mp_uint_t lineno; bool trace_opcodes; } mp_obj_frame_t; void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude); mp_obj_t mp_obj_new_code(const mp_raw_code_t *rc); mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state); // This is the implementation for the sys.settrace mp_obj_t mp_prof_settrace(mp_obj_t callback); mp_obj_t mp_prof_frame_enter(mp_code_state_t *code_state); mp_obj_t mp_prof_frame_update(const mp_code_state_t *code_state); // For every VM instruction tick this function deduces events from the state mp_obj_t mp_prof_instr_tick(mp_code_state_t *code_state, bool is_exception); // This section is for debugging the settrace feature itself, and is not intended // to be included in production/release builds. #define MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE 0 #if MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE void mp_prof_print_instr(const byte* ip, mp_code_state_t *code_state); #define MP_PROF_INSTR_DEBUG_PRINT(current_ip) mp_prof_print_instr((current_ip), code_state) #else #define MP_PROF_INSTR_DEBUG_PRINT(current_ip) #endif #endif // MICROPY_PY_SYS_SETTRACE #endif // MICROPY_INCLUDED_PY_PROFILING_H micropython-1.12/py/py.mk000066400000000000000000000162071357706137100154410ustar00rootroot00000000000000# where py object files go (they have a name prefix to prevent filename clashes) PY_BUILD = $(BUILD)/py # where autogenerated header files go HEADER_BUILD = $(BUILD)/genhdr # file containing qstr defs for the core Python bit PY_QSTR_DEFS = $(PY_SRC)/qstrdefs.h # If qstr autogeneration is not disabled we specify the output header # for all collected qstrings. ifneq ($(QSTR_AUTOGEN_DISABLE),1) QSTR_DEFS_COLLECTED = $(HEADER_BUILD)/qstrdefs.collected.h endif # Any files listed by these variables will cause a full regeneration of qstrs # DEPENDENCIES: included in qstr processing; REQUIREMENTS: not included QSTR_GLOBAL_DEPENDENCIES += $(PY_SRC)/mpconfig.h mpconfigport.h QSTR_GLOBAL_REQUIREMENTS += $(HEADER_BUILD)/mpversion.h # some code is performance bottleneck and compiled with other optimization options CSUPEROPT = -O3 # External modules written in C. ifneq ($(USER_C_MODULES),) # pre-define USERMOD variables as expanded so that variables are immediate # expanded as they're added to them SRC_USERMOD := CFLAGS_USERMOD := LDFLAGS_USERMOD := $(foreach module, $(wildcard $(USER_C_MODULES)/*/micropython.mk), \ $(eval USERMOD_DIR = $(patsubst %/,%,$(dir $(module))))\ $(info Including User C Module from $(USERMOD_DIR))\ $(eval include $(module))\ ) SRC_MOD += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD)) CFLAGS_MOD += $(CFLAGS_USERMOD) LDFLAGS_MOD += $(LDFLAGS_USERMOD) endif # py object files PY_CORE_O_BASENAME = $(addprefix py/,\ mpstate.o \ nlr.o \ nlrx86.o \ nlrx64.o \ nlrthumb.o \ nlrpowerpc.o \ nlrxtensa.o \ nlrsetjmp.o \ malloc.o \ gc.o \ pystack.o \ qstr.o \ vstr.o \ mpprint.o \ unicode.o \ mpz.o \ reader.o \ lexer.o \ parse.o \ scope.o \ compile.o \ emitcommon.o \ emitbc.o \ asmbase.o \ asmx64.o \ emitnx64.o \ asmx86.o \ emitnx86.o \ asmthumb.o \ emitnthumb.o \ emitinlinethumb.o \ asmarm.o \ emitnarm.o \ asmxtensa.o \ emitnxtensa.o \ emitinlinextensa.o \ emitnxtensawin.o \ formatfloat.o \ parsenumbase.o \ parsenum.o \ emitglue.o \ persistentcode.o \ runtime.o \ runtime_utils.o \ scheduler.o \ nativeglue.o \ ringbuf.o \ stackctrl.o \ argcheck.o \ warning.o \ profile.o \ map.o \ obj.o \ objarray.o \ objattrtuple.o \ objbool.o \ objboundmeth.o \ objcell.o \ objclosure.o \ objcomplex.o \ objdeque.o \ objdict.o \ objenumerate.o \ objexcept.o \ objfilter.o \ objfloat.o \ objfun.o \ objgenerator.o \ objgetitemiter.o \ objint.o \ objint_longlong.o \ objint_mpz.o \ objlist.o \ objmap.o \ objmodule.o \ objobject.o \ objpolyiter.o \ objproperty.o \ objnone.o \ objnamedtuple.o \ objrange.o \ objreversed.o \ objset.o \ objsingleton.o \ objslice.o \ objstr.o \ objstrunicode.o \ objstringio.o \ objtuple.o \ objtype.o \ objzip.o \ opmethods.o \ sequence.o \ stream.o \ binary.o \ builtinimport.o \ builtinevex.o \ builtinhelp.o \ modarray.o \ modbuiltins.o \ modcollections.o \ modgc.o \ modio.o \ modmath.o \ modcmath.o \ modmicropython.o \ modstruct.o \ modsys.o \ moduerrno.o \ modthread.o \ vm.o \ bc.o \ showbc.o \ repl.o \ smallint.o \ frozenmod.o \ ) PY_EXTMOD_O_BASENAME = \ extmod/moductypes.o \ extmod/modujson.o \ extmod/modure.o \ extmod/moduzlib.o \ extmod/moduheapq.o \ extmod/modutimeq.o \ extmod/moduhashlib.o \ extmod/moducryptolib.o \ extmod/modubinascii.o \ extmod/virtpin.o \ extmod/machine_mem.o \ extmod/machine_pinbase.o \ extmod/machine_signal.o \ extmod/machine_pulse.o \ extmod/machine_i2c.o \ extmod/machine_spi.o \ extmod/modbluetooth.o \ extmod/modussl_axtls.o \ extmod/modussl_mbedtls.o \ extmod/modurandom.o \ extmod/moduselect.o \ extmod/moduwebsocket.o \ extmod/modwebrepl.o \ extmod/modframebuf.o \ extmod/vfs.o \ extmod/vfs_blockdev.o \ extmod/vfs_reader.o \ extmod/vfs_posix.o \ extmod/vfs_posix_file.o \ extmod/vfs_fat.o \ extmod/vfs_fat_diskio.o \ extmod/vfs_fat_file.o \ extmod/vfs_lfs.o \ extmod/utime_mphal.o \ extmod/uos_dupterm.o \ lib/embed/abort_.o \ lib/utils/printf.o \ # prepend the build destination prefix to the py object files PY_CORE_O = $(addprefix $(BUILD)/, $(PY_CORE_O_BASENAME)) PY_EXTMOD_O = $(addprefix $(BUILD)/, $(PY_EXTMOD_O_BASENAME)) # this is a convenience variable for ports that want core, extmod and frozen code PY_O = $(PY_CORE_O) $(PY_EXTMOD_O) # object file for frozen code specified via a manifest ifneq ($(FROZEN_MANIFEST),) PY_O += $(BUILD)/$(BUILD)/frozen_content.o endif # object file for frozen files ifneq ($(FROZEN_DIR),) PY_O += $(BUILD)/$(BUILD)/frozen.o endif # object file for frozen bytecode (frozen .mpy files) ifneq ($(FROZEN_MPY_DIR),) PY_O += $(BUILD)/$(BUILD)/frozen_mpy.o endif # Sources that may contain qstrings SRC_QSTR_IGNORE = py/nlr% SRC_QSTR += $(SRC_MOD) $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) $(PY_EXTMOD_O_BASENAME:.o=.c) # Anything that depends on FORCE will be considered out-of-date FORCE: .PHONY: FORCE $(HEADER_BUILD)/mpversion.h: FORCE | $(HEADER_BUILD) $(Q)$(PYTHON) $(PY_SRC)/makeversionhdr.py $@ # mpconfigport.mk is optional, but changes to it may drastically change # overall config, so they need to be caught MPCONFIGPORT_MK = $(wildcard mpconfigport.mk) # qstr data # Adding an order only dependency on $(HEADER_BUILD) causes $(HEADER_BUILD) to get # created before we run the script to generate the .h # Note: we need to protect the qstr names from the preprocessor, so we wrap # the lines in "" and then unwrap after the preprocessor is finished. # See more information about this process in docs/develop/qstr.rst. $(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) $(PY_SRC)/makeqstrdata.py mpconfigport.h $(MPCONFIGPORT_MK) $(PY_SRC)/mpconfig.h | $(HEADER_BUILD) $(ECHO) "GEN $@" $(Q)$(CAT) $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | $(SED) 's/^\"\(Q(.*)\)\"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h $(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@ # build a list of registered modules for py/objmodule.c. $(HEADER_BUILD)/moduledefs.h: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)/mpversion.h @$(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makemoduledefs.py --vpath="., $(TOP), $(USER_C_MODULES)" $(SRC_QSTR) > $@ SRC_QSTR += $(HEADER_BUILD)/moduledefs.h # Force nlr code to always be compiled with space-saving optimisation so # that the function preludes are of a minimal and predictable form. $(PY_BUILD)/nlr%.o: CFLAGS += -Os # optimising gc for speed; 5ms down to 4ms on pybv2 $(PY_BUILD)/gc.o: CFLAGS += $(CSUPEROPT) # optimising vm for speed, adds only a small amount to code size but makes a huge difference to speed (20% faster) $(PY_BUILD)/vm.o: CFLAGS += $(CSUPEROPT) # Optimizing vm.o for modern deeply pipelined CPUs with branch predictors # may require disabling tail jump optimization. This will make sure that # each opcode has its own dispatching jump which will improve branch # branch predictor efficiency. # https://marc.info/?l=lua-l&m=129778596120851 # http://hg.python.org/cpython/file/b127046831e2/Python/ceval.c#l828 # http://www.emulators.com/docs/nx25_nostradamus.htm #-fno-crossjumping # Include rules for extmod related code include $(TOP)/extmod/extmod.mk micropython-1.12/py/pystack.c000066400000000000000000000041671357706137100163040ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #if MICROPY_ENABLE_PYSTACK void mp_pystack_init(void *start, void *end) { MP_STATE_THREAD(pystack_start) = start; MP_STATE_THREAD(pystack_end) = end; MP_STATE_THREAD(pystack_cur) = start; } void *mp_pystack_alloc(size_t n_bytes) { n_bytes = (n_bytes + (MICROPY_PYSTACK_ALIGN - 1)) & ~(MICROPY_PYSTACK_ALIGN - 1); #if MP_PYSTACK_DEBUG n_bytes += MICROPY_PYSTACK_ALIGN; #endif if (MP_STATE_THREAD(pystack_cur) + n_bytes > MP_STATE_THREAD(pystack_end)) { // out of memory in the pystack nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError, MP_OBJ_NEW_QSTR(MP_QSTR_pystack_space_exhausted))); } void *ptr = MP_STATE_THREAD(pystack_cur); MP_STATE_THREAD(pystack_cur) += n_bytes; #if MP_PYSTACK_DEBUG *(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN) = n_bytes; #endif return ptr; } #endif micropython-1.12/py/pystack.h000066400000000000000000000077671357706137100163220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_PYSTACK_H #define MICROPY_INCLUDED_PY_PYSTACK_H #include "py/mpstate.h" // Enable this debugging option to check that the amount of memory freed is // consistent with amounts that were previously allocated. #define MP_PYSTACK_DEBUG (0) #if MICROPY_ENABLE_PYSTACK void mp_pystack_init(void *start, void *end); void *mp_pystack_alloc(size_t n_bytes); // This function can free multiple continuous blocks at once: just pass the // pointer to the block that was allocated first and it and all subsequently // allocated blocks will be freed. static inline void mp_pystack_free(void *ptr) { assert((uint8_t*)ptr >= MP_STATE_THREAD(pystack_start)); assert((uint8_t*)ptr <= MP_STATE_THREAD(pystack_cur)); #if MP_PYSTACK_DEBUG size_t n_bytes_to_free = MP_STATE_THREAD(pystack_cur) - (uint8_t*)ptr; size_t n_bytes = *(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN); while (n_bytes < n_bytes_to_free) { n_bytes += *(size_t*)(MP_STATE_THREAD(pystack_cur) - n_bytes - MICROPY_PYSTACK_ALIGN); } if (n_bytes != n_bytes_to_free) { mp_printf(&mp_plat_print, "mp_pystack_free() failed: %u != %u\n", (uint)n_bytes_to_free, (uint)*(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN)); assert(0); } #endif MP_STATE_THREAD(pystack_cur) = (uint8_t*)ptr; } static inline void mp_pystack_realloc(void *ptr, size_t n_bytes) { mp_pystack_free(ptr); mp_pystack_alloc(n_bytes); } static inline size_t mp_pystack_usage(void) { return MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start); } static inline size_t mp_pystack_limit(void) { return MP_STATE_THREAD(pystack_end) - MP_STATE_THREAD(pystack_start); } #endif #if !MICROPY_ENABLE_PYSTACK #define mp_local_alloc(n_bytes) alloca(n_bytes) static inline void mp_local_free(void *ptr) { (void)ptr; } static inline void *mp_nonlocal_alloc(size_t n_bytes) { return m_new(uint8_t, n_bytes); } static inline void *mp_nonlocal_realloc(void *ptr, size_t old_n_bytes, size_t new_n_bytes) { return m_renew(uint8_t, ptr, old_n_bytes, new_n_bytes); } static inline void mp_nonlocal_free(void *ptr, size_t n_bytes) { m_del(uint8_t, ptr, n_bytes); } #else static inline void *mp_local_alloc(size_t n_bytes) { return mp_pystack_alloc(n_bytes); } static inline void mp_local_free(void *ptr) { mp_pystack_free(ptr); } static inline void *mp_nonlocal_alloc(size_t n_bytes) { return mp_pystack_alloc(n_bytes); } static inline void *mp_nonlocal_realloc(void *ptr, size_t old_n_bytes, size_t new_n_bytes) { (void)old_n_bytes; mp_pystack_realloc(ptr, new_n_bytes); return ptr; } static inline void mp_nonlocal_free(void *ptr, size_t n_bytes) { (void)n_bytes; mp_pystack_free(ptr); } #endif #endif // MICROPY_INCLUDED_PY_PYSTACK_H micropython-1.12/py/qstr.c000066400000000000000000000273711357706137100156210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/mpstate.h" #include "py/qstr.h" #include "py/gc.h" #include "py/runtime.h" // NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings) // ultimately we will replace this with a static hash table of some kind // also probably need to include the length in the string data, to allow null bytes in the string #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_printf DEBUG_printf #else // don't print debugging info #define DEBUG_printf(...) (void)0 #endif // A qstr is an index into the qstr pool. // The data for a qstr contains (hash, length, data): // - hash (configurable number of bytes) // - length (configurable number of bytes) // - data ("length" number of bytes) // - \0 terminated (so they can be printed using printf) #if MICROPY_QSTR_BYTES_IN_HASH == 1 #define Q_HASH_MASK (0xff) #define Q_GET_HASH(q) ((mp_uint_t)(q)[0]) #define Q_SET_HASH(q, hash) do { (q)[0] = (hash); } while (0) #elif MICROPY_QSTR_BYTES_IN_HASH == 2 #define Q_HASH_MASK (0xffff) #define Q_GET_HASH(q) ((mp_uint_t)(q)[0] | ((mp_uint_t)(q)[1] << 8)) #define Q_SET_HASH(q, hash) do { (q)[0] = (hash); (q)[1] = (hash) >> 8; } while (0) #else #error unimplemented qstr hash decoding #endif #define Q_GET_ALLOC(q) (MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + Q_GET_LENGTH(q) + 1) #define Q_GET_DATA(q) ((q) + MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN) #if MICROPY_QSTR_BYTES_IN_LEN == 1 #define Q_GET_LENGTH(q) ((q)[MICROPY_QSTR_BYTES_IN_HASH]) #define Q_SET_LENGTH(q, len) do { (q)[MICROPY_QSTR_BYTES_IN_HASH] = (len); } while (0) #elif MICROPY_QSTR_BYTES_IN_LEN == 2 #define Q_GET_LENGTH(q) ((q)[MICROPY_QSTR_BYTES_IN_HASH] | ((q)[MICROPY_QSTR_BYTES_IN_HASH + 1] << 8)) #define Q_SET_LENGTH(q, len) do { (q)[MICROPY_QSTR_BYTES_IN_HASH] = (len); (q)[MICROPY_QSTR_BYTES_IN_HASH + 1] = (len) >> 8; } while (0) #else #error unimplemented qstr length decoding #endif #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL #define QSTR_ENTER() mp_thread_mutex_lock(&MP_STATE_VM(qstr_mutex), 1) #define QSTR_EXIT() mp_thread_mutex_unlock(&MP_STATE_VM(qstr_mutex)) #else #define QSTR_ENTER() #define QSTR_EXIT() #endif // Initial number of entries for qstr pool, set so that the first dynamically // allocated pool is twice this size. The value here must be <= MP_QSTRnumber_of. #define MICROPY_ALLOC_QSTR_ENTRIES_INIT (10) // this must match the equivalent function in makeqstrdata.py mp_uint_t qstr_compute_hash(const byte *data, size_t len) { // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html mp_uint_t hash = 5381; for (const byte *top = data + len; data < top; data++) { hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data } hash &= Q_HASH_MASK; // Make sure that valid hash is never zero, zero means "hash not computed" if (hash == 0) { hash++; } return hash; } const qstr_pool_t mp_qstr_const_pool = { NULL, // no previous pool 0, // no previous pool MICROPY_ALLOC_QSTR_ENTRIES_INIT, MP_QSTRnumber_of, // corresponds to number of strings in array just below { #ifndef NO_QSTR #define QDEF(id, str) str, #include "genhdr/qstrdefs.generated.h" #undef QDEF #endif }, }; #ifdef MICROPY_QSTR_EXTRA_POOL extern const qstr_pool_t MICROPY_QSTR_EXTRA_POOL; #define CONST_POOL MICROPY_QSTR_EXTRA_POOL #else #define CONST_POOL mp_qstr_const_pool #endif void qstr_init(void) { MP_STATE_VM(last_pool) = (qstr_pool_t*)&CONST_POOL; // we won't modify the const_pool since it has no allocated room left MP_STATE_VM(qstr_last_chunk) = NULL; #if MICROPY_PY_THREAD mp_thread_mutex_init(&MP_STATE_VM(qstr_mutex)); #endif } STATIC const byte *find_qstr(qstr q) { // search pool for this qstr // total_prev_len==0 in the final pool, so the loop will always terminate qstr_pool_t *pool = MP_STATE_VM(last_pool); while (q < pool->total_prev_len) { pool = pool->prev; } return pool->qstrs[q - pool->total_prev_len]; } // qstr_mutex must be taken while in this function STATIC qstr qstr_add(const byte *q_ptr) { DEBUG_printf("QSTR: add hash=%d len=%d data=%.*s\n", Q_GET_HASH(q_ptr), Q_GET_LENGTH(q_ptr), Q_GET_LENGTH(q_ptr), Q_GET_DATA(q_ptr)); // make sure we have room in the pool for a new qstr if (MP_STATE_VM(last_pool)->len >= MP_STATE_VM(last_pool)->alloc) { size_t new_alloc = MP_STATE_VM(last_pool)->alloc * 2; #ifdef MICROPY_QSTR_EXTRA_POOL // Put a lower bound on the allocation size in case the extra qstr pool has few entries new_alloc = MAX(MICROPY_ALLOC_QSTR_ENTRIES_INIT, new_alloc); #endif qstr_pool_t *pool = m_new_obj_var_maybe(qstr_pool_t, const char*, new_alloc); if (pool == NULL) { QSTR_EXIT(); m_malloc_fail(new_alloc); } pool->prev = MP_STATE_VM(last_pool); pool->total_prev_len = MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len; pool->alloc = new_alloc; pool->len = 0; MP_STATE_VM(last_pool) = pool; DEBUG_printf("QSTR: allocate new pool of size %d\n", MP_STATE_VM(last_pool)->alloc); } // add the new qstr MP_STATE_VM(last_pool)->qstrs[MP_STATE_VM(last_pool)->len++] = q_ptr; // return id for the newly-added qstr return MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len - 1; } qstr qstr_find_strn(const char *str, size_t str_len) { // work out hash of str mp_uint_t str_hash = qstr_compute_hash((const byte*)str, str_len); // search pools for the data for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) { for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) { if (Q_GET_HASH(*q) == str_hash && Q_GET_LENGTH(*q) == str_len && memcmp(Q_GET_DATA(*q), str, str_len) == 0) { return pool->total_prev_len + (q - pool->qstrs); } } } // not found; return null qstr return 0; } qstr qstr_from_str(const char *str) { return qstr_from_strn(str, strlen(str)); } qstr qstr_from_strn(const char *str, size_t len) { QSTR_ENTER(); qstr q = qstr_find_strn(str, len); if (q == 0) { // qstr does not exist in interned pool so need to add it // check that len is not too big if (len >= (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN))) { QSTR_EXIT(); mp_raise_msg(&mp_type_RuntimeError, "name too long"); } // compute number of bytes needed to intern this string size_t n_bytes = MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1; if (MP_STATE_VM(qstr_last_chunk) != NULL && MP_STATE_VM(qstr_last_used) + n_bytes > MP_STATE_VM(qstr_last_alloc)) { // not enough room at end of previously interned string so try to grow byte *new_p = m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_alloc) + n_bytes, false); if (new_p == NULL) { // could not grow existing memory; shrink it to fit previous (void)m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_used), false); MP_STATE_VM(qstr_last_chunk) = NULL; } else { // could grow existing memory MP_STATE_VM(qstr_last_alloc) += n_bytes; } } if (MP_STATE_VM(qstr_last_chunk) == NULL) { // no existing memory for the interned string so allocate a new chunk size_t al = n_bytes; if (al < MICROPY_ALLOC_QSTR_CHUNK_INIT) { al = MICROPY_ALLOC_QSTR_CHUNK_INIT; } MP_STATE_VM(qstr_last_chunk) = m_new_maybe(byte, al); if (MP_STATE_VM(qstr_last_chunk) == NULL) { // failed to allocate a large chunk so try with exact size MP_STATE_VM(qstr_last_chunk) = m_new_maybe(byte, n_bytes); if (MP_STATE_VM(qstr_last_chunk) == NULL) { QSTR_EXIT(); m_malloc_fail(n_bytes); } al = n_bytes; } MP_STATE_VM(qstr_last_alloc) = al; MP_STATE_VM(qstr_last_used) = 0; } // allocate memory from the chunk for this new interned string's data byte *q_ptr = MP_STATE_VM(qstr_last_chunk) + MP_STATE_VM(qstr_last_used); MP_STATE_VM(qstr_last_used) += n_bytes; // store the interned strings' data mp_uint_t hash = qstr_compute_hash((const byte*)str, len); Q_SET_HASH(q_ptr, hash); Q_SET_LENGTH(q_ptr, len); memcpy(q_ptr + MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN, str, len); q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\0'; q = qstr_add(q_ptr); } QSTR_EXIT(); return q; } mp_uint_t qstr_hash(qstr q) { const byte *qd = find_qstr(q); return Q_GET_HASH(qd); } size_t qstr_len(qstr q) { const byte *qd = find_qstr(q); return Q_GET_LENGTH(qd); } const char *qstr_str(qstr q) { const byte *qd = find_qstr(q); return (const char*)Q_GET_DATA(qd); } const byte *qstr_data(qstr q, size_t *len) { const byte *qd = find_qstr(q); *len = Q_GET_LENGTH(qd); return Q_GET_DATA(qd); } void qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, size_t *n_total_bytes) { QSTR_ENTER(); *n_pool = 0; *n_qstr = 0; *n_str_data_bytes = 0; *n_total_bytes = 0; for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL && pool != &CONST_POOL; pool = pool->prev) { *n_pool += 1; *n_qstr += pool->len; for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) { *n_str_data_bytes += Q_GET_ALLOC(*q); } #if MICROPY_ENABLE_GC *n_total_bytes += gc_nbytes(pool); // this counts actual bytes used in heap #else *n_total_bytes += sizeof(qstr_pool_t) + sizeof(qstr) * pool->alloc; #endif } *n_total_bytes += *n_str_data_bytes; QSTR_EXIT(); } #if MICROPY_PY_MICROPYTHON_MEM_INFO void qstr_dump_data(void) { QSTR_ENTER(); for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL && pool != &CONST_POOL; pool = pool->prev) { for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) { mp_printf(&mp_plat_print, "Q(%s)\n", Q_GET_DATA(*q)); } } QSTR_EXIT(); } #endif micropython-1.12/py/qstr.h000066400000000000000000000053521357706137100156210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_QSTR_H #define MICROPY_INCLUDED_PY_QSTR_H #include "py/mpconfig.h" #include "py/misc.h" // See qstrdefs.h for a list of qstr's that are available as constants. // Reference them as MP_QSTR_xxxx. // // Note: it would be possible to define MP_QSTR_xxx as qstr_from_str_static("xxx") // for qstrs that are referenced this way, but you don't want to have them in ROM. // first entry in enum will be MP_QSTRnull=0, which indicates invalid/no qstr enum { #ifndef NO_QSTR #define QDEF(id, str) id, #include "genhdr/qstrdefs.generated.h" #undef QDEF #endif MP_QSTRnumber_of, // no underscore so it can't clash with any of the above }; typedef size_t qstr; typedef struct _qstr_pool_t { struct _qstr_pool_t *prev; size_t total_prev_len; size_t alloc; size_t len; const byte *qstrs[]; } qstr_pool_t; #define QSTR_FROM_STR_STATIC(s) (qstr_from_strn((s), strlen(s))) #define QSTR_TOTAL() (MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len) void qstr_init(void); mp_uint_t qstr_compute_hash(const byte *data, size_t len); qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTRnull if not found qstr qstr_from_str(const char *str); qstr qstr_from_strn(const char *str, size_t len); mp_uint_t qstr_hash(qstr q); const char *qstr_str(qstr q); size_t qstr_len(qstr q); const byte *qstr_data(qstr q, size_t *len); void qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, size_t *n_total_bytes); void qstr_dump_data(void); #endif // MICROPY_INCLUDED_PY_QSTR_H micropython-1.12/py/qstrdefs.h000066400000000000000000000035571357706137100164700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/mpconfig.h" // All the qstr definitions in this file are available as constants. // That is, they are in ROM and you can reference them simply as MP_QSTR_xxxx. // qstr configuration passed to makeqstrdata.py of the form QCFG(key, value) QCFG(BYTES_IN_LEN, MICROPY_QSTR_BYTES_IN_LEN) QCFG(BYTES_IN_HASH, MICROPY_QSTR_BYTES_IN_HASH) Q() Q(*) Q(_) Q(/) #if MICROPY_PY_BUILTINS_STR_OP_MODULO Q(%#o) Q(%#x) #else Q({:#o}) Q({:#x}) #endif Q({:#b}) Q( ) Q(\n) Q(maximum recursion depth exceeded) Q() Q() Q() Q() Q() Q() Q() Q() Q(utf-8) #if MICROPY_ENABLE_PYSTACK Q(pystack exhausted) #endif micropython-1.12/py/reader.c000066400000000000000000000101201357706137100160520ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/runtime.h" #include "py/mperrno.h" #include "py/reader.h" typedef struct _mp_reader_mem_t { size_t free_len; // if >0 mem is freed on close by: m_free(beg, free_len) const byte *beg; const byte *cur; const byte *end; } mp_reader_mem_t; STATIC mp_uint_t mp_reader_mem_readbyte(void *data) { mp_reader_mem_t *reader = (mp_reader_mem_t*)data; if (reader->cur < reader->end) { return *reader->cur++; } else { return MP_READER_EOF; } } STATIC void mp_reader_mem_close(void *data) { mp_reader_mem_t *reader = (mp_reader_mem_t*)data; if (reader->free_len > 0) { m_del(char, (char*)reader->beg, reader->free_len); } m_del_obj(mp_reader_mem_t, reader); } void mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t free_len) { mp_reader_mem_t *rm = m_new_obj(mp_reader_mem_t); rm->free_len = free_len; rm->beg = buf; rm->cur = buf; rm->end = buf + len; reader->data = rm; reader->readbyte = mp_reader_mem_readbyte; reader->close = mp_reader_mem_close; } #if MICROPY_READER_POSIX #include #include #include typedef struct _mp_reader_posix_t { bool close_fd; int fd; size_t len; size_t pos; byte buf[20]; } mp_reader_posix_t; STATIC mp_uint_t mp_reader_posix_readbyte(void *data) { mp_reader_posix_t *reader = (mp_reader_posix_t*)data; if (reader->pos >= reader->len) { if (reader->len == 0) { return MP_READER_EOF; } else { int n = read(reader->fd, reader->buf, sizeof(reader->buf)); if (n <= 0) { reader->len = 0; return MP_READER_EOF; } reader->len = n; reader->pos = 0; } } return reader->buf[reader->pos++]; } STATIC void mp_reader_posix_close(void *data) { mp_reader_posix_t *reader = (mp_reader_posix_t*)data; if (reader->close_fd) { close(reader->fd); } m_del_obj(mp_reader_posix_t, reader); } void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd) { mp_reader_posix_t *rp = m_new_obj(mp_reader_posix_t); rp->close_fd = close_fd; rp->fd = fd; int n = read(rp->fd, rp->buf, sizeof(rp->buf)); if (n == -1) { if (close_fd) { close(fd); } mp_raise_OSError(errno); } rp->len = n; rp->pos = 0; reader->data = rp; reader->readbyte = mp_reader_posix_readbyte; reader->close = mp_reader_posix_close; } #if !MICROPY_VFS_POSIX // If MICROPY_VFS_POSIX is defined then this function is provided by the VFS layer void mp_reader_new_file(mp_reader_t *reader, const char *filename) { int fd = open(filename, O_RDONLY, 0644); if (fd < 0) { mp_raise_OSError(errno); } mp_reader_new_file_from_fd(reader, fd, true); } #endif #endif micropython-1.12/py/reader.h000066400000000000000000000037131357706137100160710ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_READER_H #define MICROPY_INCLUDED_PY_READER_H #include "py/obj.h" // the readbyte function must return the next byte in the input stream // it must return MP_READER_EOF if end of stream // it can be called again after returning MP_READER_EOF, and in that case must return MP_READER_EOF #define MP_READER_EOF ((mp_uint_t)(-1)) typedef struct _mp_reader_t { void *data; mp_uint_t (*readbyte)(void *data); void (*close)(void *data); } mp_reader_t; void mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t free_len); void mp_reader_new_file(mp_reader_t *reader, const char *filename); void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd); #endif // MICROPY_INCLUDED_PY_READER_H micropython-1.12/py/repl.c000066400000000000000000000230131357706137100155570ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/obj.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/repl.h" #if MICROPY_HELPER_REPL STATIC bool str_startswith_word(const char *str, const char *head) { size_t i; for (i = 0; str[i] && head[i]; i++) { if (str[i] != head[i]) { return false; } } return head[i] == '\0' && (str[i] == '\0' || !unichar_isident(str[i])); } bool mp_repl_continue_with_input(const char *input) { // check for blank input if (input[0] == '\0') { return false; } // check if input starts with a certain keyword bool starts_with_compound_keyword = input[0] == '@' || str_startswith_word(input, "if") || str_startswith_word(input, "while") || str_startswith_word(input, "for") || str_startswith_word(input, "try") || str_startswith_word(input, "with") || str_startswith_word(input, "def") || str_startswith_word(input, "class") #if MICROPY_PY_ASYNC_AWAIT || str_startswith_word(input, "async") #endif ; // check for unmatched open bracket, quote or escape quote #define Q_NONE (0) #define Q_1_SINGLE (1) #define Q_1_DOUBLE (2) #define Q_3_SINGLE (3) #define Q_3_DOUBLE (4) int n_paren = 0; int n_brack = 0; int n_brace = 0; int in_quote = Q_NONE; const char *i; for (i = input; *i; i++) { if (*i == '\'') { if ((in_quote == Q_NONE || in_quote == Q_3_SINGLE) && i[1] == '\'' && i[2] == '\'') { i += 2; in_quote = Q_3_SINGLE - in_quote; } else if (in_quote == Q_NONE || in_quote == Q_1_SINGLE) { in_quote = Q_1_SINGLE - in_quote; } } else if (*i == '"') { if ((in_quote == Q_NONE || in_quote == Q_3_DOUBLE) && i[1] == '"' && i[2] == '"') { i += 2; in_quote = Q_3_DOUBLE - in_quote; } else if (in_quote == Q_NONE || in_quote == Q_1_DOUBLE) { in_quote = Q_1_DOUBLE - in_quote; } } else if (*i == '\\' && (i[1] == '\'' || i[1] == '"' || i[1] == '\\')) { if (in_quote != Q_NONE) { i++; } } else if (in_quote == Q_NONE) { switch (*i) { case '(': n_paren += 1; break; case ')': n_paren -= 1; break; case '[': n_brack += 1; break; case ']': n_brack -= 1; break; case '{': n_brace += 1; break; case '}': n_brace -= 1; break; default: break; } } } // continue if unmatched 3-quotes if (in_quote == Q_3_SINGLE || in_quote == Q_3_DOUBLE) { return true; } // continue if unmatched brackets, but only if not in a 1-quote if ((n_paren > 0 || n_brack > 0 || n_brace > 0) && in_quote == Q_NONE) { return true; } // continue if last character was backslash (for line continuation) if (i[-1] == '\\') { return true; } // continue if compound keyword and last line was not empty if (starts_with_compound_keyword && i[-1] != '\n') { return true; } // otherwise, don't continue return false; } size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print, const char **compl_str) { // scan backwards to find start of "a.b.c" chain const char *org_str = str; const char *top = str + len; for (const char *s = top; --s >= str;) { if (!(unichar_isalpha(*s) || unichar_isdigit(*s) || *s == '_' || *s == '.')) { ++s; str = s; break; } } size_t nqstr = QSTR_TOTAL(); // begin search in outer global dict which is accessed from __main__ mp_obj_t obj = MP_OBJ_FROM_PTR(&mp_module___main__); mp_obj_t dest[2]; for (;;) { // get next word in string to complete const char *s_start = str; while (str < top && *str != '.') { ++str; } size_t s_len = str - s_start; if (str < top) { // a complete word, lookup in current object qstr q = qstr_find_strn(s_start, s_len); if (q == MP_QSTRnull) { // lookup will fail return 0; } mp_load_method_protected(obj, q, dest, true); obj = dest[0]; // attribute, method, or MP_OBJ_NULL if nothing found if (obj == MP_OBJ_NULL) { // lookup failed return 0; } // skip '.' to move to next word ++str; } else { // end of string, do completion on this partial name // look for matches const char *match_str = NULL; size_t match_len = 0; qstr q_first = 0, q_last = 0; for (qstr q = MP_QSTR_ + 1; q < nqstr; ++q) { size_t d_len; const char *d_str = (const char*)qstr_data(q, &d_len); if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { mp_load_method_protected(obj, q, dest, true); if (dest[0] != MP_OBJ_NULL) { if (match_str == NULL) { match_str = d_str; match_len = d_len; } else { // search for longest common prefix of match_str and d_str // (assumes these strings are null-terminated) for (size_t j = s_len; j <= match_len && j <= d_len; ++j) { if (match_str[j] != d_str[j]) { match_len = j; break; } } } if (q_first == 0) { q_first = q; } q_last = q; } } } // nothing found if (q_first == 0) { // If there're no better alternatives, and if it's first word // in the line, try to complete "import". if (s_start == org_str) { static const char import_str[] = "import "; if (memcmp(s_start, import_str, s_len) == 0) { *compl_str = import_str + s_len; return sizeof(import_str) - 1 - s_len; } } return 0; } // 1 match found, or multiple matches with a common prefix if (q_first == q_last || match_len > s_len) { *compl_str = match_str + s_len; return match_len - s_len; } // multiple matches found, print them out #define WORD_SLOT_LEN (16) #define MAX_LINE_LEN (4 * WORD_SLOT_LEN) int line_len = MAX_LINE_LEN; // force a newline for first word for (qstr q = q_first; q <= q_last; ++q) { size_t d_len; const char *d_str = (const char*)qstr_data(q, &d_len); if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { mp_load_method_protected(obj, q, dest, true); if (dest[0] != MP_OBJ_NULL) { int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len; if (gap < 2) { gap += WORD_SLOT_LEN; } if (line_len + gap + d_len <= MAX_LINE_LEN) { // TODO optimise printing of gap? for (int j = 0; j < gap; ++j) { mp_print_str(print, " "); } mp_print_str(print, d_str); line_len += gap + d_len; } else { mp_printf(print, "\n%s", d_str); line_len = d_len; } } } } mp_print_str(print, "\n"); return (size_t)(-1); // indicate many matches } } } #endif // MICROPY_HELPER_REPL micropython-1.12/py/repl.h000066400000000000000000000031021357706137100155610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_REPL_H #define MICROPY_INCLUDED_PY_REPL_H #include "py/mpconfig.h" #include "py/misc.h" #include "py/mpprint.h" #if MICROPY_HELPER_REPL bool mp_repl_continue_with_input(const char *input); size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print, const char **compl_str); #endif #endif // MICROPY_INCLUDED_PY_REPL_H micropython-1.12/py/ringbuf.c000066400000000000000000000042061357706137100162540ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Jim Mussared * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "ringbuf.h" int ringbuf_get16(ringbuf_t *r) { int v = ringbuf_peek16(r); if (v == -1) { return v; } r->iget += 2; if (r->iget >= r->size) { r->iget -= r->size; } return v; } int ringbuf_peek16(ringbuf_t *r) { if (r->iget == r->iput) { return -1; } uint32_t iget_a = r->iget + 1; if (iget_a == r->size) { iget_a = 0; } if (iget_a == r->iput) { return -1; } return (r->buf[r->iget] << 8) | (r->buf[iget_a]); } int ringbuf_put16(ringbuf_t *r, uint16_t v) { uint32_t iput_a = r->iput + 1; if (iput_a == r->size) { iput_a = 0; } if (iput_a == r->iget) { return -1; } uint32_t iput_b = iput_a + 1; if (iput_b == r->size) { iput_b = 0; } if (iput_b == r->iget) { return -1; } r->buf[r->iput] = (v >> 8) & 0xff; r->buf[iput_a] = v & 0xff; r->iput = iput_b; return 0; } micropython-1.12/py/ringbuf.h000066400000000000000000000052021357706137100162560ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_RINGBUF_H #define MICROPY_INCLUDED_PY_RINGBUF_H #include #include typedef struct _ringbuf_t { uint8_t *buf; uint16_t size; uint16_t iget; uint16_t iput; } ringbuf_t; // Static initialization: // byte buf_array[N]; // ringbuf_t buf = {buf_array, sizeof(buf_array)}; // Dynamic initialization. This needs to become findable as a root pointer! #define ringbuf_alloc(r, sz) \ { \ (r)->buf = m_new(uint8_t, sz); \ (r)->size = sz; \ (r)->iget = (r)->iput = 0; \ } static inline int ringbuf_get(ringbuf_t *r) { if (r->iget == r->iput) { return -1; } uint8_t v = r->buf[r->iget++]; if (r->iget >= r->size) { r->iget = 0; } return v; } static inline int ringbuf_put(ringbuf_t *r, uint8_t v) { uint32_t iput_new = r->iput + 1; if (iput_new >= r->size) { iput_new = 0; } if (iput_new == r->iget) { return -1; } r->buf[r->iput] = v; r->iput = iput_new; return 0; } static inline size_t ringbuf_free(ringbuf_t *r) { return (r->size + r->iget - r->iput - 1) % r->size; } static inline size_t ringbuf_avail(ringbuf_t *r) { return (r->size + r->iput - r->iget) % r->size; } // Note: big-endian. No-op if not enough room available for both bytes. int ringbuf_get16(ringbuf_t *r); int ringbuf_peek16(ringbuf_t *r); int ringbuf_put16(ringbuf_t *r, uint16_t v); #endif // MICROPY_INCLUDED_PY_RINGBUF_H micropython-1.12/py/runtime.c000066400000000000000000001627401357706137100163130ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/parsenum.h" #include "py/compile.h" #include "py/objstr.h" #include "py/objtuple.h" #include "py/objlist.h" #include "py/objmodule.h" #include "py/objgenerator.h" #include "py/smallint.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/stackctrl.h" #include "py/gc.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__) #else // don't print debugging info #define DEBUG_printf(...) (void)0 #define DEBUG_OP_printf(...) (void)0 #endif const mp_obj_module_t mp_module___main__ = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&MP_STATE_VM(dict_main), }; void mp_init(void) { qstr_init(); // no pending exceptions to start with MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; #if MICROPY_ENABLE_SCHEDULER MP_STATE_VM(sched_state) = MP_SCHED_IDLE; MP_STATE_VM(sched_idx) = 0; MP_STATE_VM(sched_len) = 0; #endif #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF mp_init_emergency_exception_buf(); #endif #if MICROPY_KBD_EXCEPTION // initialise the exception object for raising KeyboardInterrupt MP_STATE_VM(mp_kbd_exception).base.type = &mp_type_KeyboardInterrupt; MP_STATE_VM(mp_kbd_exception).traceback_alloc = 0; MP_STATE_VM(mp_kbd_exception).traceback_len = 0; MP_STATE_VM(mp_kbd_exception).traceback_data = NULL; MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; #endif // call port specific initialization if any #ifdef MICROPY_PORT_INIT_FUNC MICROPY_PORT_INIT_FUNC; #endif #if MICROPY_ENABLE_COMPILER // optimization disabled by default MP_STATE_VM(mp_optimise_value) = 0; #if MICROPY_EMIT_NATIVE MP_STATE_VM(default_emit_opt) = MP_EMIT_OPT_NONE; #endif #endif // init global module dict mp_obj_dict_init(&MP_STATE_VM(mp_loaded_modules_dict), 3); // initialise the __main__ module mp_obj_dict_init(&MP_STATE_VM(dict_main), 1); mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(dict_main)), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New()) mp_locals_set(&MP_STATE_VM(dict_main)); mp_globals_set(&MP_STATE_VM(dict_main)); #if MICROPY_CAN_OVERRIDE_BUILTINS // start with no extensions to builtins MP_STATE_VM(mp_module_builtins_override_dict) = NULL; #endif #if MICROPY_PY_OS_DUPTERM for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) { MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL; } #endif #if MICROPY_VFS // initialise the VFS sub-system MP_STATE_VM(vfs_cur) = NULL; MP_STATE_VM(vfs_mount_table) = NULL; #endif #if MICROPY_PY_SYS_ATEXIT MP_STATE_VM(sys_exitfunc) = mp_const_none; #endif #if MICROPY_PY_SYS_SETTRACE MP_STATE_THREAD(prof_trace_callback) = MP_OBJ_NULL; MP_STATE_THREAD(prof_callback_is_executing) = false; MP_STATE_THREAD(current_code_state) = NULL; #endif #if MICROPY_PY_BLUETOOTH MP_STATE_VM(bluetooth) = MP_OBJ_NULL; #endif #if MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); #endif MP_THREAD_GIL_ENTER(); } void mp_deinit(void) { MP_THREAD_GIL_EXIT(); //mp_obj_dict_free(&dict_main); //mp_map_deinit(&MP_STATE_VM(mp_loaded_modules_map)); // call port specific deinitialization if any #ifdef MICROPY_PORT_DEINIT_FUNC MICROPY_PORT_DEINIT_FUNC; #endif } mp_obj_t mp_load_name(qstr qst) { // logic: search locals, globals, builtins DEBUG_OP_printf("load name %s\n", qstr_str(qst)); // If we're at the outer scope (locals == globals), dispatch to load_global right away if (mp_locals_get() != mp_globals_get()) { mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP); if (elem != NULL) { return elem->value; } } return mp_load_global(qst); } mp_obj_t mp_load_global(qstr qst) { // logic: search globals, builtins DEBUG_OP_printf("load global %s\n", qstr_str(qst)); mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP); if (elem == NULL) { #if MICROPY_CAN_OVERRIDE_BUILTINS if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) { // lookup in additional dynamic table of builtins first elem = mp_map_lookup(&MP_STATE_VM(mp_module_builtins_override_dict)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP); if (elem != NULL) { return elem->value; } } #endif elem = mp_map_lookup((mp_map_t*)&mp_module_builtins_globals.map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP); if (elem == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_NameError, "name not defined"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%q' isn't defined", qst)); } } } return elem->value; } mp_obj_t mp_load_build_class(void) { DEBUG_OP_printf("load_build_class\n"); #if MICROPY_CAN_OVERRIDE_BUILTINS if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) { // lookup in additional dynamic table of builtins first mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_VM(mp_module_builtins_override_dict)->map, MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), MP_MAP_LOOKUP); if (elem != NULL) { return elem->value; } } #endif return MP_OBJ_FROM_PTR(&mp_builtin___build_class___obj); } void mp_store_name(qstr qst, mp_obj_t obj) { DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qst), obj); mp_obj_dict_store(MP_OBJ_FROM_PTR(mp_locals_get()), MP_OBJ_NEW_QSTR(qst), obj); } void mp_delete_name(qstr qst) { DEBUG_OP_printf("delete name %s\n", qstr_str(qst)); // TODO convert KeyError to NameError if qst not found mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_locals_get()), MP_OBJ_NEW_QSTR(qst)); } void mp_store_global(qstr qst, mp_obj_t obj) { DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qst), obj); mp_obj_dict_store(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst), obj); } void mp_delete_global(qstr qst) { DEBUG_OP_printf("delete global %s\n", qstr_str(qst)); // TODO convert KeyError to NameError if qst not found mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst)); } mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { DEBUG_OP_printf("unary " UINT_FMT " %q %p\n", op, mp_unary_op_method_name[op], arg); if (op == MP_UNARY_OP_NOT) { // "not x" is the negative of whether "x" is true per Python semantics return mp_obj_new_bool(mp_obj_is_true(arg) == 0); } else if (mp_obj_is_small_int(arg)) { mp_int_t val = MP_OBJ_SMALL_INT_VALUE(arg); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(val != 0); case MP_UNARY_OP_HASH: return arg; case MP_UNARY_OP_POSITIVE: case MP_UNARY_OP_INT: return arg; case MP_UNARY_OP_NEGATIVE: // check for overflow if (val == MP_SMALL_INT_MIN) { return mp_obj_new_int(-val); } else { return MP_OBJ_NEW_SMALL_INT(-val); } case MP_UNARY_OP_ABS: if (val >= 0) { return arg; } else if (val == MP_SMALL_INT_MIN) { // check for overflow return mp_obj_new_int(-val); } else { return MP_OBJ_NEW_SMALL_INT(-val); } default: assert(op == MP_UNARY_OP_INVERT); return MP_OBJ_NEW_SMALL_INT(~val); } } else if (op == MP_UNARY_OP_HASH && mp_obj_is_str_or_bytes(arg)) { // fast path for hashing str/bytes GET_STR_HASH(arg, h); if (h == 0) { GET_STR_DATA_LEN(arg, data, len); h = qstr_compute_hash(data, len); } return MP_OBJ_NEW_SMALL_INT(h); } else { mp_obj_type_t *type = mp_obj_get_type(arg); if (type->unary_op != NULL) { mp_obj_t result = type->unary_op(op, arg); if (result != MP_OBJ_NULL) { return result; } } // With MP_UNARY_OP_INT, mp_unary_op() becomes a fallback for mp_obj_get_int(). // In this case provide a more focused error message to not confuse, e.g. chr(1.0) if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { if (op == MP_UNARY_OP_INT) { mp_raise_TypeError("can't convert to int"); } else { mp_raise_TypeError("unsupported type for operator"); } } else { if (op == MP_UNARY_OP_INT) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg))); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported type for %q: '%s'", mp_unary_op_method_name[op], mp_obj_get_type_str(arg))); } } } } mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { DEBUG_OP_printf("binary " UINT_FMT " %q %p %p\n", op, mp_binary_op_method_name[op], lhs, rhs); // TODO correctly distinguish inplace operators for mutable objects // lookup logic that CPython uses for +=: // check for implemented += // then check for implemented + // then check for implemented seq.inplace_concat // then check for implemented seq.concat // then fail // note that list does not implement + or +=, so that inplace_concat is reached first for += // deal with is if (op == MP_BINARY_OP_IS) { return mp_obj_new_bool(lhs == rhs); } // deal with == and != for all types if (op == MP_BINARY_OP_EQUAL || op == MP_BINARY_OP_NOT_EQUAL) { if (mp_obj_equal(lhs, rhs)) { if (op == MP_BINARY_OP_EQUAL) { return mp_const_true; } else { return mp_const_false; } } else { if (op == MP_BINARY_OP_EQUAL) { return mp_const_false; } else { return mp_const_true; } } } // deal with exception_match for all types if (op == MP_BINARY_OP_EXCEPTION_MATCH) { // rhs must be issubclass(rhs, BaseException) if (mp_obj_is_exception_type(rhs)) { if (mp_obj_exception_match(lhs, rhs)) { return mp_const_true; } else { return mp_const_false; } } else if (mp_obj_is_type(rhs, &mp_type_tuple)) { mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(rhs); for (size_t i = 0; i < tuple->len; i++) { rhs = tuple->items[i]; if (!mp_obj_is_exception_type(rhs)) { goto unsupported_op; } if (mp_obj_exception_match(lhs, rhs)) { return mp_const_true; } } return mp_const_false; } goto unsupported_op; } if (mp_obj_is_small_int(lhs)) { mp_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs); if (mp_obj_is_small_int(rhs)) { mp_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs); // This is a binary operation: lhs_val op rhs_val // We need to be careful to handle overflow; see CERT INT32-C // Operations that can overflow: // + result always fits in mp_int_t, then handled by SMALL_INT check // - result always fits in mp_int_t, then handled by SMALL_INT check // * checked explicitly // / if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check // % if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check // << checked explicitly switch (op) { case MP_BINARY_OP_OR: case MP_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break; case MP_BINARY_OP_XOR: case MP_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break; case MP_BINARY_OP_AND: case MP_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break; case MP_BINARY_OP_LSHIFT: case MP_BINARY_OP_INPLACE_LSHIFT: { if (rhs_val < 0) { // negative shift not allowed mp_raise_ValueError("negative shift count"); } else if (rhs_val >= (mp_int_t)BITS_PER_WORD || lhs_val > (MP_SMALL_INT_MAX >> rhs_val) || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) { // left-shift will overflow, so use higher precision integer lhs = mp_obj_new_int_from_ll(lhs_val); goto generic_binary_op; } else { // use standard precision lhs_val <<= rhs_val; } break; } case MP_BINARY_OP_RSHIFT: case MP_BINARY_OP_INPLACE_RSHIFT: if (rhs_val < 0) { // negative shift not allowed mp_raise_ValueError("negative shift count"); } else { // standard precision is enough for right-shift if (rhs_val >= (mp_int_t)BITS_PER_WORD) { // Shifting to big amounts is underfined behavior // in C and is CPU-dependent; propagate sign bit. rhs_val = BITS_PER_WORD - 1; } lhs_val >>= rhs_val; } break; case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break; case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: { // If long long type exists and is larger than mp_int_t, then // we can use the following code to perform overflow-checked multiplication. // Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow. #if 0 // compute result using long long precision long long res = (long long)lhs_val * (long long)rhs_val; if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) { // result overflowed SMALL_INT, so return higher precision integer return mp_obj_new_int_from_ll(res); } else { // use standard precision lhs_val = (mp_int_t)res; } #endif if (mp_small_int_mul_overflow(lhs_val, rhs_val)) { // use higher precision lhs = mp_obj_new_int_from_ll(lhs_val); goto generic_binary_op; } else { // use standard precision return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val); } } case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { goto zero_division; } lhs_val = mp_small_int_floor_divide(lhs_val, rhs_val); break; #if MICROPY_PY_BUILTINS_FLOAT case MP_BINARY_OP_TRUE_DIVIDE: case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_val == 0) { goto zero_division; } return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val); #endif case MP_BINARY_OP_MODULO: case MP_BINARY_OP_INPLACE_MODULO: { if (rhs_val == 0) { goto zero_division; } lhs_val = mp_small_int_modulo(lhs_val, rhs_val); break; } case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: if (rhs_val < 0) { #if MICROPY_PY_BUILTINS_FLOAT return mp_obj_float_binary_op(op, lhs_val, rhs); #else mp_raise_ValueError("negative power with no float support"); #endif } else { mp_int_t ans = 1; while (rhs_val > 0) { if (rhs_val & 1) { if (mp_small_int_mul_overflow(ans, lhs_val)) { goto power_overflow; } ans *= lhs_val; } if (rhs_val == 1) { break; } rhs_val /= 2; if (mp_small_int_mul_overflow(lhs_val, lhs_val)) { goto power_overflow; } lhs_val *= lhs_val; } lhs_val = ans; } break; power_overflow: // use higher precision lhs = mp_obj_new_int_from_ll(MP_OBJ_SMALL_INT_VALUE(lhs)); goto generic_binary_op; case MP_BINARY_OP_DIVMOD: { if (rhs_val == 0) { goto zero_division; } // to reduce stack usage we don't pass a temp array of the 2 items mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(lhs_val, rhs_val)); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(lhs_val, rhs_val)); return MP_OBJ_FROM_PTR(tuple); } case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); default: goto unsupported_op; } // This is an inlined version of mp_obj_new_int, for speed if (MP_SMALL_INT_FITS(lhs_val)) { return MP_OBJ_NEW_SMALL_INT(lhs_val); } else { return mp_obj_new_int_from_ll(lhs_val); } #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_float(rhs)) { mp_obj_t res = mp_obj_float_binary_op(op, lhs_val, rhs); if (res == MP_OBJ_NULL) { goto unsupported_op; } else { return res; } #if MICROPY_PY_BUILTINS_COMPLEX } else if (mp_obj_is_type(rhs, &mp_type_complex)) { mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs); if (res == MP_OBJ_NULL) { goto unsupported_op; } else { return res; } #endif #endif } } // Convert MP_BINARY_OP_IN to MP_BINARY_OP_CONTAINS with swapped args. if (op == MP_BINARY_OP_IN) { op = MP_BINARY_OP_CONTAINS; mp_obj_t temp = lhs; lhs = rhs; rhs = temp; } // generic binary_op supplied by type mp_obj_type_t *type; generic_binary_op: type = mp_obj_get_type(lhs); if (type->binary_op != NULL) { mp_obj_t result = type->binary_op(op, lhs, rhs); if (result != MP_OBJ_NULL) { return result; } } #if MICROPY_PY_REVERSE_SPECIAL_METHODS if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_POWER) { mp_obj_t t = rhs; rhs = lhs; lhs = t; op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR; goto generic_binary_op; } else if (op >= MP_BINARY_OP_REVERSE_OR) { // Convert __rop__ back to __op__ for error message mp_obj_t t = rhs; rhs = lhs; lhs = t; op -= MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR; } #endif if (op == MP_BINARY_OP_CONTAINS) { // If type didn't support containment then explicitly walk the iterator. // mp_getiter will raise the appropriate exception if lhs is not iterable. mp_obj_iter_buf_t iter_buf; mp_obj_t iter = mp_getiter(lhs, &iter_buf); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { if (mp_obj_equal(next, rhs)) { return mp_const_true; } } return mp_const_false; } unsupported_op: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("unsupported type for operator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported types for %q: '%s', '%s'", mp_binary_op_method_name[op], mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs))); } zero_division: mp_raise_msg(&mp_type_ZeroDivisionError, "divide by zero"); } mp_obj_t mp_call_function_0(mp_obj_t fun) { return mp_call_function_n_kw(fun, 0, 0, NULL); } mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg) { return mp_call_function_n_kw(fun, 1, 0, &arg); } mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) { mp_obj_t args[2]; args[0] = arg1; args[1] = arg2; return mp_call_function_n_kw(fun, 2, 0, args); } // args contains, eg: arg0 arg1 key0 value0 key1 value1 mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { // TODO improve this: fun object can specify its type and we parse here the arguments, // passing to the function arrays of fixed and keyword arguments DEBUG_OP_printf("calling function %p(n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", fun_in, n_args, n_kw, args); // get the type mp_obj_type_t *type = mp_obj_get_type(fun_in); // do the call if (type->call != NULL) { return type->call(fun_in, n_args, n_kw, args); } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object not callable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object isn't callable", mp_obj_get_type_str(fun_in))); } } // args contains: fun self/NULL arg(0) ... arg(n_args-2) arg(n_args-1) kw_key(0) kw_val(0) ... kw_key(n_kw-1) kw_val(n_kw-1) // if n_args==0 and n_kw==0 then there are only fun and self/NULL mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args) { DEBUG_OP_printf("call method (fun=%p, self=%p, n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", args[0], args[1], n_args, n_kw, args); int adjust = (args[1] == MP_OBJ_NULL) ? 0 : 1; return mp_call_function_n_kw(args[0], n_args + adjust, n_kw, args + 2 - adjust); } // This function only needs to be exposed externally when in stackless mode. #if !MICROPY_STACKLESS STATIC #endif void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args) { mp_obj_t fun = *args++; mp_obj_t self = MP_OBJ_NULL; if (have_self) { self = *args++; // may be MP_OBJ_NULL } uint n_args = n_args_n_kw & 0xff; uint n_kw = (n_args_n_kw >> 8) & 0xff; mp_obj_t pos_seq = args[n_args + 2 * n_kw]; // may be MP_OBJ_NULL mp_obj_t kw_dict = args[n_args + 2 * n_kw + 1]; // may be MP_OBJ_NULL DEBUG_OP_printf("call method var (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p, seq=%p, dict=%p)\n", fun, self, n_args, n_kw, args, pos_seq, kw_dict); // We need to create the following array of objects: // args[0 .. n_args] unpacked(pos_seq) args[n_args .. n_args + 2 * n_kw] unpacked(kw_dict) // TODO: optimize one day to avoid constructing new arg array? Will be hard. // The new args array mp_obj_t *args2; uint args2_alloc; uint args2_len = 0; // Try to get a hint for the size of the kw_dict uint kw_dict_len = 0; if (kw_dict != MP_OBJ_NULL && mp_obj_is_type(kw_dict, &mp_type_dict)) { kw_dict_len = mp_obj_dict_len(kw_dict); } // Extract the pos_seq sequence to the new args array. // Note that it can be arbitrary iterator. if (pos_seq == MP_OBJ_NULL) { // no sequence // allocate memory for the new array of args args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len); args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t)); // copy the self if (self != MP_OBJ_NULL) { args2[args2_len++] = self; } // copy the fixed pos args mp_seq_copy(args2 + args2_len, args, n_args, mp_obj_t); args2_len += n_args; } else if (mp_obj_is_type(pos_seq, &mp_type_tuple) || mp_obj_is_type(pos_seq, &mp_type_list)) { // optimise the case of a tuple and list // get the items size_t len; mp_obj_t *items; mp_obj_get_array(pos_seq, &len, &items); // allocate memory for the new array of args args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len); args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t)); // copy the self if (self != MP_OBJ_NULL) { args2[args2_len++] = self; } // copy the fixed and variable position args mp_seq_cat(args2 + args2_len, args, n_args, items, len, mp_obj_t); args2_len += n_args + len; } else { // generic iterator // allocate memory for the new array of args args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len) + 3; args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t)); // copy the self if (self != MP_OBJ_NULL) { args2[args2_len++] = self; } // copy the fixed position args mp_seq_copy(args2 + args2_len, args, n_args, mp_obj_t); args2_len += n_args; // extract the variable position args from the iterator mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(pos_seq, &iter_buf); mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (args2_len >= args2_alloc) { args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), args2_alloc * 2 * sizeof(mp_obj_t)); args2_alloc *= 2; } args2[args2_len++] = item; } } // The size of the args2 array now is the number of positional args. uint pos_args_len = args2_len; // Copy the fixed kw args. mp_seq_copy(args2 + args2_len, args + n_args, 2 * n_kw, mp_obj_t); args2_len += 2 * n_kw; // Extract (key,value) pairs from kw_dict dictionary and append to args2. // Note that it can be arbitrary iterator. if (kw_dict == MP_OBJ_NULL) { // pass } else if (mp_obj_is_type(kw_dict, &mp_type_dict)) { // dictionary mp_map_t *map = mp_obj_dict_get_map(kw_dict); assert(args2_len + 2 * map->used <= args2_alloc); // should have enough, since kw_dict_len is in this case hinted correctly above for (size_t i = 0; i < map->alloc; i++) { if (mp_map_slot_is_filled(map, i)) { // the key must be a qstr, so intern it if it's a string mp_obj_t key = map->table[i].key; if (!mp_obj_is_qstr(key)) { key = mp_obj_str_intern_checked(key); } args2[args2_len++] = key; args2[args2_len++] = map->table[i].value; } } } else { // generic mapping: // - call keys() to get an iterable of all keys in the mapping // - call __getitem__ for each key to get the corresponding value // get the keys iterable mp_obj_t dest[3]; mp_load_method(kw_dict, MP_QSTR_keys, dest); mp_obj_t iterable = mp_getiter(mp_call_method_n_kw(0, 0, dest), NULL); mp_obj_t key; while ((key = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { // expand size of args array if needed if (args2_len + 1 >= args2_alloc) { uint new_alloc = args2_alloc * 2; if (new_alloc < 4) { new_alloc = 4; } args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), new_alloc * sizeof(mp_obj_t)); args2_alloc = new_alloc; } // the key must be a qstr, so intern it if it's a string if (!mp_obj_is_qstr(key)) { key = mp_obj_str_intern_checked(key); } // get the value corresponding to the key mp_load_method(kw_dict, MP_QSTR___getitem__, dest); dest[2] = key; mp_obj_t value = mp_call_method_n_kw(1, 0, dest); // store the key/value pair in the argument array args2[args2_len++] = key; args2[args2_len++] = value; } } out_args->fun = fun; out_args->args = args2; out_args->n_args = pos_args_len; out_args->n_kw = (args2_len - pos_args_len) / 2; out_args->n_alloc = args2_alloc; } mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args) { mp_call_args_t out_args; mp_call_prepare_args_n_kw_var(have_self, n_args_n_kw, args, &out_args); mp_obj_t res = mp_call_function_n_kw(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args); mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t)); return res; } // unpacked items are stored in reverse order into the array pointed to by items void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) { size_t seq_len; if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) { mp_obj_t *seq_items; mp_obj_get_array(seq_in, &seq_len, &seq_items); if (seq_len < num) { goto too_short; } else if (seq_len > num) { goto too_long; } for (size_t i = 0; i < num; i++) { items[i] = seq_items[num - 1 - i]; } } else { mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(seq_in, &iter_buf); for (seq_len = 0; seq_len < num; seq_len++) { mp_obj_t el = mp_iternext(iterable); if (el == MP_OBJ_STOP_ITERATION) { goto too_short; } items[num - 1 - seq_len] = el; } if (mp_iternext(iterable) != MP_OBJ_STOP_ITERATION) { goto too_long; } } return; too_short: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_ValueError("wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", (int)seq_len)); } too_long: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_ValueError("wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", (int)num)); } } // unpacked items are stored in reverse order into the array pointed to by items void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) { size_t num_left = num_in & 0xff; size_t num_right = (num_in >> 8) & 0xff; DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right); size_t seq_len; if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) { // Make the seq variable volatile so the compiler keeps a reference to it, // since if it's a tuple then seq_items points to the interior of the GC cell // and mp_obj_new_list may trigger a GC which doesn't trace this and reclaims seq. volatile mp_obj_t seq = seq_in; mp_obj_t *seq_items; mp_obj_get_array(seq, &seq_len, &seq_items); if (seq_len < num_left + num_right) { goto too_short; } for (size_t i = 0; i < num_right; i++) { items[i] = seq_items[seq_len - 1 - i]; } items[num_right] = mp_obj_new_list(seq_len - num_left - num_right, seq_items + num_left); for (size_t i = 0; i < num_left; i++) { items[num_right + 1 + i] = seq_items[num_left - 1 - i]; } seq = MP_OBJ_NULL; } else { // Generic iterable; this gets a bit messy: we unpack known left length to the // items destination array, then the rest to a dynamically created list. Once the // iterable is exhausted, we take from this list for the right part of the items. // TODO Improve to waste less memory in the dynamically created list. mp_obj_t iterable = mp_getiter(seq_in, NULL); mp_obj_t item; for (seq_len = 0; seq_len < num_left; seq_len++) { item = mp_iternext(iterable); if (item == MP_OBJ_STOP_ITERATION) { goto too_short; } items[num_left + num_right + 1 - 1 - seq_len] = item; } mp_obj_list_t *rest = MP_OBJ_TO_PTR(mp_obj_new_list(0, NULL)); while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { mp_obj_list_append(MP_OBJ_FROM_PTR(rest), item); } if (rest->len < num_right) { goto too_short; } items[num_right] = MP_OBJ_FROM_PTR(rest); for (size_t i = 0; i < num_right; i++) { items[num_right - 1 - i] = rest->items[rest->len - num_right + i]; } mp_obj_list_set_len(MP_OBJ_FROM_PTR(rest), rest->len - num_right); } return; too_short: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_ValueError("wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", (int)seq_len)); } } mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) { DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr)); // use load_method mp_obj_t dest[2]; mp_load_method(base, attr, dest); if (dest[1] == MP_OBJ_NULL) { // load_method returned just a normal attribute return dest[0]; } else { // load_method returned a method, so build a bound method object return mp_obj_new_bound_meth(dest[0], dest[1]); } } #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG // The following "checked fun" type is local to the mp_convert_member_lookup // function, and serves to check that the first argument to a builtin function // has the correct type. typedef struct _mp_obj_checked_fun_t { mp_obj_base_t base; const mp_obj_type_t *type; mp_obj_t fun; } mp_obj_checked_fun_t; STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_checked_fun_t *self = MP_OBJ_TO_PTR(self_in); if (n_args > 0) { const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]); if (arg0_type != self->type) { if (MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED) { mp_raise_TypeError("argument has wrong type"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "argument should be a '%q' not a '%q'", self->type->name, arg0_type->name)); } } } return mp_call_function_n_kw(self->fun, n_args, n_kw, args); } STATIC const mp_obj_type_t mp_type_checked_fun = { { &mp_type_type }, .name = MP_QSTR_function, .call = checked_fun_call, }; STATIC mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun) { mp_obj_checked_fun_t *o = m_new_obj(mp_obj_checked_fun_t); o->base.type = &mp_type_checked_fun; o->type = type; o->fun = fun; return MP_OBJ_FROM_PTR(o); } #endif // MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG // Given a member that was extracted from an instance, convert it correctly // and put the result in the dest[] array for a possible method call. // Conversion means dealing with static/class methods, callables, and values. // see http://docs.python.org/3/howto/descriptor.html void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest) { if (mp_obj_is_type(member, &mp_type_staticmethod)) { // return just the function dest[0] = ((mp_obj_static_class_method_t*)MP_OBJ_TO_PTR(member))->fun; } else if (mp_obj_is_type(member, &mp_type_classmethod)) { // return a bound method, with self being the type of this object // this type should be the type of the original instance, not the base // type (which is what is passed in the 'type' argument to this function) if (self != MP_OBJ_NULL) { type = mp_obj_get_type(self); } dest[0] = ((mp_obj_static_class_method_t*)MP_OBJ_TO_PTR(member))->fun; dest[1] = MP_OBJ_FROM_PTR(type); } else if (mp_obj_is_type(member, &mp_type_type)) { // Don't try to bind types (even though they're callable) dest[0] = member; } else if (mp_obj_is_fun(member) || (mp_obj_is_obj(member) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type->name == MP_QSTR_closure || ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type->name == MP_QSTR_generator))) { // only functions, closures and generators objects can be bound to self #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG const mp_obj_type_t *m_type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type; if (self == MP_OBJ_NULL && (m_type == &mp_type_fun_builtin_0 || m_type == &mp_type_fun_builtin_1 || m_type == &mp_type_fun_builtin_2 || m_type == &mp_type_fun_builtin_3 || m_type == &mp_type_fun_builtin_var)) { // we extracted a builtin method without a first argument, so we must // wrap this function in a type checker dest[0] = mp_obj_new_checked_fun(type, member); } else #endif { // return a bound method, with self being this object dest[0] = member; dest[1] = self; } } else { // class member is a value, so just return that value dest[0] = member; } } // no attribute found, returns: dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL // normal attribute found, returns: dest[0] == , dest[1] == MP_OBJ_NULL // method attribute found, returns: dest[0] == , dest[1] == void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) { // clear output to indicate no attribute/method found yet dest[0] = MP_OBJ_NULL; dest[1] = MP_OBJ_NULL; // get the type mp_obj_type_t *type = mp_obj_get_type(obj); // look for built-in names #if MICROPY_CPYTHON_COMPAT if (attr == MP_QSTR___class__) { // a.__class__ is equivalent to type(a) dest[0] = MP_OBJ_FROM_PTR(type); } else #endif if (attr == MP_QSTR___next__ && type->iternext != NULL) { dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj); dest[1] = obj; } else if (type->attr != NULL) { // this type can do its own load, so call it type->attr(obj, attr, dest); } else if (type->locals_dict != NULL) { // generic method lookup // this is a lookup in the object (ie not class or type) assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now mp_map_t *locals_map = &type->locals_dict->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { mp_convert_member_lookup(obj, type, elem->value, dest); } } } void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { DEBUG_OP_printf("load method %p.%s\n", base, qstr_str(attr)); mp_load_method_maybe(base, attr, dest); if (dest[0] == MP_OBJ_NULL) { // no attribute/method called attr if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_AttributeError, "no such attribute"); } else { // following CPython, we give a more detailed error message for type objects if (mp_obj_is_type(base, &mp_type_type)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "type object '%q' has no attribute '%q'", ((mp_obj_type_t*)MP_OBJ_TO_PTR(base))->name, attr)); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%q'", mp_obj_get_type_str(base), attr)); } } } } // Acts like mp_load_method_maybe but catches AttributeError, and all other exceptions if requested void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_load_method_maybe(obj, attr, dest); nlr_pop(); } else { if (!catch_all_exc && !mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_AttributeError))) { // Re-raise the exception nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); } } } void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value); mp_obj_type_t *type = mp_obj_get_type(base); if (type->attr != NULL) { mp_obj_t dest[2] = {MP_OBJ_SENTINEL, value}; type->attr(base, attr, dest); if (dest[0] == MP_OBJ_NULL) { // success return; } } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_AttributeError, "no such attribute"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%q'", mp_obj_get_type_str(base), attr)); } } mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { assert(o_in); mp_obj_type_t *type = mp_obj_get_type(o_in); // Check for native getiter which is the identity. We handle this case explicitly // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used. if (type->getiter == mp_identity_getiter) { return o_in; } // if caller did not provide a buffer then allocate one on the heap if (iter_buf == NULL) { iter_buf = m_new_obj(mp_obj_iter_buf_t); } // check for native getiter (corresponds to __iter__) if (type->getiter != NULL) { mp_obj_t iter = type->getiter(o_in, iter_buf); if (iter != MP_OBJ_NULL) { return iter; } } // check for __getitem__ mp_obj_t dest[2]; mp_load_method_maybe(o_in, MP_QSTR___getitem__, dest); if (dest[0] != MP_OBJ_NULL) { // __getitem__ exists, create and return an iterator return mp_obj_new_getitem_iter(dest, iter_buf); } // object not iterable if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object not iterable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object isn't iterable", mp_obj_get_type_str(o_in))); } } // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raise StopIteration() // may also raise StopIteration() mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->iternext != NULL) { return type->iternext(o_in); } else { // check for __next__ method mp_obj_t dest[2]; mp_load_method_maybe(o_in, MP_QSTR___next__, dest); if (dest[0] != MP_OBJ_NULL) { // __next__ exists, call it and return its result return mp_call_method_n_kw(0, 0, dest); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object not an iterator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object isn't an iterator", mp_obj_get_type_str(o_in))); } } } } // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration() (or any subclass thereof) // may raise other exceptions mp_obj_t mp_iternext(mp_obj_t o_in) { MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->iternext != NULL) { return type->iternext(o_in); } else { // check for __next__ method mp_obj_t dest[2]; mp_load_method_maybe(o_in, MP_QSTR___next__, dest); if (dest[0] != MP_OBJ_NULL) { // __next__ exists, call it and return its result nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t ret = mp_call_method_n_kw(0, 0, dest); nlr_pop(); return ret; } else { if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { return MP_OBJ_STOP_ITERATION; } else { nlr_jump(nlr.ret_val); } } } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("object not an iterator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object isn't an iterator", mp_obj_get_type_str(o_in))); } } } } // TODO: Unclear what to do with StopIterarion exception here. mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { assert((send_value != MP_OBJ_NULL) ^ (throw_value != MP_OBJ_NULL)); mp_obj_type_t *type = mp_obj_get_type(self_in); if (type == &mp_type_gen_instance) { return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val); } if (type->iternext != NULL && send_value == mp_const_none) { mp_obj_t ret = type->iternext(self_in); *ret_val = ret; if (ret != MP_OBJ_STOP_ITERATION) { return MP_VM_RETURN_YIELD; } else { // Emulate raise StopIteration() // Special case, handled in vm.c return MP_VM_RETURN_NORMAL; } } mp_obj_t dest[3]; // Reserve slot for send() arg // Python instance iterator protocol if (send_value == mp_const_none) { mp_load_method_maybe(self_in, MP_QSTR___next__, dest); if (dest[0] != MP_OBJ_NULL) { *ret_val = mp_call_method_n_kw(0, 0, dest); return MP_VM_RETURN_YIELD; } } // Either python instance generator protocol, or native object // generator protocol. if (send_value != MP_OBJ_NULL) { mp_load_method(self_in, MP_QSTR_send, dest); dest[2] = send_value; *ret_val = mp_call_method_n_kw(1, 0, dest); return MP_VM_RETURN_YIELD; } assert(throw_value != MP_OBJ_NULL); { if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(throw_value)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { mp_load_method_maybe(self_in, MP_QSTR_close, dest); if (dest[0] != MP_OBJ_NULL) { // TODO: Exceptions raised in close() are not propagated, // printed to sys.stderr *ret_val = mp_call_method_n_kw(0, 0, dest); // We assume one can't "yield" from close() return MP_VM_RETURN_NORMAL; } } else { mp_load_method_maybe(self_in, MP_QSTR_throw, dest); if (dest[0] != MP_OBJ_NULL) { dest[2] = throw_value; *ret_val = mp_call_method_n_kw(1, 0, dest); // If .throw() method returned, we assume it's value to yield // - any exception would be thrown with nlr_raise(). return MP_VM_RETURN_YIELD; } } // If there's nowhere to throw exception into, then we assume that object // is just incapable to handle it, so any exception thrown into it // will be propagated up. This behavior is approved by test_pep380.py // test_delegation_of_close_to_non_generator(), // test_delegating_throw_to_non_generator() if (mp_obj_exception_match(throw_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { // PEP479: if StopIteration is raised inside a generator it is replaced with RuntimeError *ret_val = mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator raised StopIteration"); } else { *ret_val = mp_make_raise_obj(throw_value); } return MP_VM_RETURN_EXCEPTION; } } mp_obj_t mp_make_raise_obj(mp_obj_t o) { DEBUG_printf("raise %p\n", o); if (mp_obj_is_exception_type(o)) { // o is an exception type (it is derived from BaseException (or is BaseException)) // create and return a new exception instance by calling o // TODO could have an option to disable traceback, then builtin exceptions (eg TypeError) // could have const instances in ROM which we return here instead return mp_call_function_n_kw(o, 0, 0, NULL); } else if (mp_obj_is_exception_instance(o)) { // o is an instance of an exception, so use it as the exception return o; } else { // o cannot be used as an exception, so return a type error (which will be raised by the caller) return mp_obj_new_exception_msg(&mp_type_TypeError, "exceptions must derive from BaseException"); } } mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) { DEBUG_printf("import name '%s' level=%d\n", qstr_str(name), MP_OBJ_SMALL_INT_VALUE(level)); // build args array mp_obj_t args[5]; args[0] = MP_OBJ_NEW_QSTR(name); args[1] = mp_const_none; // TODO should be globals args[2] = mp_const_none; // TODO should be locals args[3] = fromlist; args[4] = level; #if MICROPY_CAN_OVERRIDE_BUILTINS // Lookup __import__ and call that if it exists mp_obj_dict_t *bo_dict = MP_STATE_VM(mp_module_builtins_override_dict); if (bo_dict != NULL) { mp_map_elem_t *import = mp_map_lookup(&bo_dict->map, MP_OBJ_NEW_QSTR(MP_QSTR___import__), MP_MAP_LOOKUP); if (import != NULL) { return mp_call_function_n_kw(import->value, 5, 0, args); } } #endif return mp_builtin___import__(5, args); } mp_obj_t mp_import_from(mp_obj_t module, qstr name) { DEBUG_printf("import from %p %s\n", module, qstr_str(name)); mp_obj_t dest[2]; mp_load_method_maybe(module, name, dest); if (dest[1] != MP_OBJ_NULL) { // Hopefully we can't import bound method from an object import_error: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "cannot import name %q", name)); } if (dest[0] != MP_OBJ_NULL) { return dest[0]; } #if MICROPY_ENABLE_EXTERNAL_IMPORT // See if it's a package, then can try FS import if (!mp_obj_is_package(module)) { goto import_error; } mp_load_method_maybe(module, MP_QSTR___name__, dest); size_t pkg_name_len; const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len); const uint dot_name_len = pkg_name_len + 1 + qstr_len(name); char *dot_name = mp_local_alloc(dot_name_len); memcpy(dot_name, pkg_name, pkg_name_len); dot_name[pkg_name_len] = '.'; memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name)); qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len); mp_local_free(dot_name); // For fromlist, pass sentinel "non empty" value to force returning of leaf module return mp_import_name(dot_name_q, mp_const_true, MP_OBJ_NEW_SMALL_INT(0)); #else // Package import not supported with external imports disabled goto import_error; #endif } void mp_import_all(mp_obj_t module) { DEBUG_printf("import all %p\n", module); // TODO: Support __all__ mp_map_t *map = &mp_obj_module_get_globals(module)->map; for (size_t i = 0; i < map->alloc; i++) { if (mp_map_slot_is_filled(map, i)) { // Entry in module global scope may be generated programmatically // (and thus be not a qstr for longer names). Avoid turning it in // qstr if it has '_' and was used exactly to save memory. const char *name = mp_obj_str_get_str(map->table[i].key); if (*name != '_') { qstr qname = mp_obj_str_get_qstr(map->table[i].key); mp_store_name(qname, map->table[i].value); } } } } #if MICROPY_ENABLE_COMPILER mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { // save context mp_obj_dict_t *volatile old_globals = mp_globals_get(); mp_obj_dict_t *volatile old_locals = mp_locals_get(); // set new context mp_globals_set(globals); mp_locals_set(locals); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, parse_input_kind); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); mp_obj_t ret; if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) { // for compile only, return value is the module function ret = module_fun; } else { // execute module function and get return value ret = mp_call_function_0(module_fun); } // finish nlr block, restore context and return value nlr_pop(); mp_globals_set(old_globals); mp_locals_set(old_locals); return ret; } else { // exception; restore context and re-raise same exception mp_globals_set(old_globals); mp_locals_set(old_locals); nlr_jump(nlr.ret_val); } } #endif // MICROPY_ENABLE_COMPILER NORETURN void m_malloc_fail(size_t num_bytes) { DEBUG_printf("memory allocation failed, allocating %u bytes\n", (uint)num_bytes); #if MICROPY_ENABLE_GC if (gc_is_locked()) { mp_raise_msg(&mp_type_MemoryError, "memory allocation failed, heap is locked"); } #endif nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "memory allocation failed, allocating %u bytes", (uint)num_bytes)); } NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg) { if (msg == NULL) { nlr_raise(mp_obj_new_exception(exc_type)); } else { nlr_raise(mp_obj_new_exception_msg(exc_type, msg)); } } NORETURN void mp_raise_ValueError(const char *msg) { mp_raise_msg(&mp_type_ValueError, msg); } NORETURN void mp_raise_TypeError(const char *msg) { mp_raise_msg(&mp_type_TypeError, msg); } NORETURN void mp_raise_OSError(int errno_) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_))); } NORETURN void mp_raise_NotImplementedError(const char *msg) { mp_raise_msg(&mp_type_NotImplementedError, msg); } #if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK NORETURN void mp_raise_recursion_depth(void) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError, MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded))); } #endif micropython-1.12/py/runtime.h000066400000000000000000000171441357706137100163150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_RUNTIME_H #define MICROPY_INCLUDED_PY_RUNTIME_H #include "py/mpstate.h" #include "py/pystack.h" typedef enum { MP_VM_RETURN_NORMAL, MP_VM_RETURN_YIELD, MP_VM_RETURN_EXCEPTION, } mp_vm_return_kind_t; typedef enum { MP_ARG_BOOL = 0x001, MP_ARG_INT = 0x002, MP_ARG_OBJ = 0x003, MP_ARG_KIND_MASK = 0x0ff, MP_ARG_REQUIRED = 0x100, MP_ARG_KW_ONLY = 0x200, } mp_arg_flag_t; typedef union _mp_arg_val_t { bool u_bool; mp_int_t u_int; mp_obj_t u_obj; mp_rom_obj_t u_rom_obj; } mp_arg_val_t; typedef struct _mp_arg_t { uint16_t qst; uint16_t flags; mp_arg_val_t defval; } mp_arg_t; // Tables mapping operator enums to qstrs, defined in objtype.c extern const byte mp_unary_op_method_name[]; extern const byte mp_binary_op_method_name[]; void mp_init(void); void mp_deinit(void); void mp_handle_pending(void); void mp_handle_pending_tail(mp_uint_t atomic_state); #if MICROPY_ENABLE_SCHEDULER void mp_sched_lock(void); void mp_sched_unlock(void); static inline unsigned int mp_sched_num_pending(void) { return MP_STATE_VM(sched_len); } bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg); #endif // extra printing method specifically for mp_obj_t's which are integral type int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec); void mp_arg_check_num_sig(size_t n_args, size_t n_kw, uint32_t sig); static inline void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) { mp_arg_check_num_sig(n_args, n_kw, MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, takes_kw)); } void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); NORETURN void mp_arg_error_terse_mismatch(void); NORETURN void mp_arg_error_unimpl_kw(void); static inline mp_obj_dict_t *mp_locals_get(void) { return MP_STATE_THREAD(dict_locals); } static inline void mp_locals_set(mp_obj_dict_t *d) { MP_STATE_THREAD(dict_locals) = d; } static inline mp_obj_dict_t *mp_globals_get(void) { return MP_STATE_THREAD(dict_globals); } static inline void mp_globals_set(mp_obj_dict_t *d) { MP_STATE_THREAD(dict_globals) = d; } mp_obj_t mp_load_name(qstr qst); mp_obj_t mp_load_global(qstr qst); mp_obj_t mp_load_build_class(void); void mp_store_name(qstr qst, mp_obj_t obj); void mp_store_global(qstr qst, mp_obj_t obj); void mp_delete_name(qstr qst); void mp_delete_global(qstr qst); mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg); mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs); mp_obj_t mp_call_function_0(mp_obj_t fun); mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg); mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2); mp_obj_t mp_call_function_n_kw(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args); mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args); mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args); mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, size_t n_kw, const mp_obj_t *args); // Call function and catch/dump exception - for Python callbacks from C code // (return MP_OBJ_NULL in case of exception). mp_obj_t mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg); mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2); typedef struct _mp_call_args_t { mp_obj_t fun; size_t n_args, n_kw, n_alloc; mp_obj_t *args; } mp_call_args_t; #if MICROPY_STACKLESS // Takes arguments which are the most general mix of Python arg types, and // prepares argument array suitable for passing to ->call() method of a // function object (and mp_call_function_n_kw()). // (Only needed in stackless mode.) void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args); #endif void mp_unpack_sequence(mp_obj_t seq, size_t num, mp_obj_t *items); void mp_unpack_ex(mp_obj_t seq, size_t num, mp_obj_t *items); mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value); mp_obj_t mp_load_attr(mp_obj_t base, qstr attr); void mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest); void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest); void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest); void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc); void mp_load_super_method(qstr attr, mp_obj_t *dest); void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val); mp_obj_t mp_getiter(mp_obj_t o, mp_obj_iter_buf_t *iter_buf); mp_obj_t mp_iternext_allow_raise(mp_obj_t o); // may return MP_OBJ_STOP_ITERATION instead of raising StopIteration() mp_obj_t mp_iternext(mp_obj_t o); // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration(...) mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val); mp_obj_t mp_make_raise_obj(mp_obj_t o); mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level); mp_obj_t mp_import_from(mp_obj_t module, qstr name); void mp_import_all(mp_obj_t module); NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg); NORETURN void mp_raise_ValueError(const char *msg); NORETURN void mp_raise_TypeError(const char *msg); NORETURN void mp_raise_NotImplementedError(const char *msg); NORETURN void mp_raise_OSError(int errno_); NORETURN void mp_raise_recursion_depth(void); #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG #undef mp_check_self #define mp_check_self(pred) #else // A port may define to raise TypeError for example #ifndef mp_check_self #define mp_check_self(pred) assert(pred) #endif #endif // helper functions for native/viper code int mp_native_type_from_qstr(qstr qst); mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type); mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type); #define mp_sys_path (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_path_obj))) #define mp_sys_argv (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_argv_obj))) #if MICROPY_WARNINGS #ifndef mp_warning void mp_warning(const char *category, const char *msg, ...); #endif #else #define mp_warning(...) #endif #endif // MICROPY_INCLUDED_PY_RUNTIME_H micropython-1.12/py/runtime0.h000066400000000000000000000140051357706137100163660ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_RUNTIME0_H #define MICROPY_INCLUDED_PY_RUNTIME0_H // The first four must fit in 8 bits, see emitbc.c // The remaining must fit in 16 bits, see scope.h #define MP_SCOPE_FLAG_ALL_SIG (0x0f) #define MP_SCOPE_FLAG_GENERATOR (0x01) #define MP_SCOPE_FLAG_VARKEYWORDS (0x02) #define MP_SCOPE_FLAG_VARARGS (0x04) #define MP_SCOPE_FLAG_DEFKWARGS (0x08) #define MP_SCOPE_FLAG_REFGLOBALS (0x10) // used only if native emitter enabled #define MP_SCOPE_FLAG_HASCONSTS (0x20) // used only if native emitter enabled #define MP_SCOPE_FLAG_VIPERRET_POS (6) // 3 bits used for viper return type, to pass from compiler to native emitter #define MP_SCOPE_FLAG_VIPERRELOC (0x10) // used only when loading viper from .mpy #define MP_SCOPE_FLAG_VIPERRODATA (0x20) // used only when loading viper from .mpy #define MP_SCOPE_FLAG_VIPERBSS (0x40) // used only when loading viper from .mpy // types for native (viper) function signature #define MP_NATIVE_TYPE_OBJ (0x00) #define MP_NATIVE_TYPE_BOOL (0x01) #define MP_NATIVE_TYPE_INT (0x02) #define MP_NATIVE_TYPE_UINT (0x03) #define MP_NATIVE_TYPE_PTR (0x04) #define MP_NATIVE_TYPE_PTR8 (0x05) #define MP_NATIVE_TYPE_PTR16 (0x06) #define MP_NATIVE_TYPE_PTR32 (0x07) // Bytecode and runtime boundaries for unary ops #define MP_UNARY_OP_NUM_BYTECODE (MP_UNARY_OP_NOT + 1) #define MP_UNARY_OP_NUM_RUNTIME (MP_UNARY_OP_SIZEOF + 1) // Bytecode and runtime boundaries for binary ops #define MP_BINARY_OP_NUM_BYTECODE (MP_BINARY_OP_POWER + 1) #if MICROPY_PY_REVERSE_SPECIAL_METHODS #define MP_BINARY_OP_NUM_RUNTIME (MP_BINARY_OP_REVERSE_POWER + 1) #else #define MP_BINARY_OP_NUM_RUNTIME (MP_BINARY_OP_CONTAINS + 1) #endif typedef enum { // These ops may appear in the bytecode. Changing this group // in any way requires changing the bytecode version. MP_UNARY_OP_POSITIVE, MP_UNARY_OP_NEGATIVE, MP_UNARY_OP_INVERT, MP_UNARY_OP_NOT, // Following ops cannot appear in the bytecode MP_UNARY_OP_BOOL, // __bool__ MP_UNARY_OP_LEN, // __len__ MP_UNARY_OP_HASH, // __hash__; must return a small int MP_UNARY_OP_ABS, // __abs__ MP_UNARY_OP_INT, // __int__ MP_UNARY_OP_SIZEOF, // for sys.getsizeof() } mp_unary_op_t; typedef enum { // The following 9+13+13 ops are used in bytecode and changing // them requires changing the bytecode version. // 9 relational operations, should return a bool; order of first 6 matches corresponding mp_token_kind_t MP_BINARY_OP_LESS, MP_BINARY_OP_MORE, MP_BINARY_OP_EQUAL, MP_BINARY_OP_LESS_EQUAL, MP_BINARY_OP_MORE_EQUAL, MP_BINARY_OP_NOT_EQUAL, MP_BINARY_OP_IN, MP_BINARY_OP_IS, MP_BINARY_OP_EXCEPTION_MATCH, // 13 inplace arithmetic operations; order matches corresponding mp_token_kind_t MP_BINARY_OP_INPLACE_OR, MP_BINARY_OP_INPLACE_XOR, MP_BINARY_OP_INPLACE_AND, MP_BINARY_OP_INPLACE_LSHIFT, MP_BINARY_OP_INPLACE_RSHIFT, MP_BINARY_OP_INPLACE_ADD, MP_BINARY_OP_INPLACE_SUBTRACT, MP_BINARY_OP_INPLACE_MULTIPLY, MP_BINARY_OP_INPLACE_MAT_MULTIPLY, MP_BINARY_OP_INPLACE_FLOOR_DIVIDE, MP_BINARY_OP_INPLACE_TRUE_DIVIDE, MP_BINARY_OP_INPLACE_MODULO, MP_BINARY_OP_INPLACE_POWER, // 13 normal arithmetic operations; order matches corresponding mp_token_kind_t MP_BINARY_OP_OR, MP_BINARY_OP_XOR, MP_BINARY_OP_AND, MP_BINARY_OP_LSHIFT, MP_BINARY_OP_RSHIFT, MP_BINARY_OP_ADD, MP_BINARY_OP_SUBTRACT, MP_BINARY_OP_MULTIPLY, MP_BINARY_OP_MAT_MULTIPLY, MP_BINARY_OP_FLOOR_DIVIDE, MP_BINARY_OP_TRUE_DIVIDE, MP_BINARY_OP_MODULO, MP_BINARY_OP_POWER, // Operations below this line don't appear in bytecode, they // just identify special methods. // This is not emitted by the compiler but is supported by the runtime. // It must follow immediately after MP_BINARY_OP_POWER. MP_BINARY_OP_DIVMOD, // The runtime will convert MP_BINARY_OP_IN to this operator with swapped args. // A type should implement this containment operator instead of MP_BINARY_OP_IN. MP_BINARY_OP_CONTAINS, // 13 MP_BINARY_OP_REVERSE_* operations must be in the same order as MP_BINARY_OP_*, // and be the last ones supported by the runtime. MP_BINARY_OP_REVERSE_OR, MP_BINARY_OP_REVERSE_XOR, MP_BINARY_OP_REVERSE_AND, MP_BINARY_OP_REVERSE_LSHIFT, MP_BINARY_OP_REVERSE_RSHIFT, MP_BINARY_OP_REVERSE_ADD, MP_BINARY_OP_REVERSE_SUBTRACT, MP_BINARY_OP_REVERSE_MULTIPLY, MP_BINARY_OP_REVERSE_MAT_MULTIPLY, MP_BINARY_OP_REVERSE_FLOOR_DIVIDE, MP_BINARY_OP_REVERSE_TRUE_DIVIDE, MP_BINARY_OP_REVERSE_MODULO, MP_BINARY_OP_REVERSE_POWER, // These 2 are not supported by the runtime and must be synthesised by the emitter MP_BINARY_OP_NOT_IN, MP_BINARY_OP_IS_NOT, } mp_binary_op_t; #endif // MICROPY_INCLUDED_PY_RUNTIME0_H micropython-1.12/py/runtime_utils.c000066400000000000000000000037011357706137100175220ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2015 Josef Gajdusek * Copyright (c) 2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" mp_obj_t mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t ret = mp_call_function_1(fun, arg); nlr_pop(); return ret; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); return MP_OBJ_NULL; } } mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t ret = mp_call_function_2(fun, arg1, arg2); nlr_pop(); return ret; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); return MP_OBJ_NULL; } } micropython-1.12/py/scheduler.c000066400000000000000000000112661357706137100166020ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" #if MICROPY_ENABLE_SCHEDULER #define IDX_MASK(i) ((i) & (MICROPY_SCHEDULER_DEPTH - 1)) static inline bool mp_sched_full(void) { MP_STATIC_ASSERT(MICROPY_SCHEDULER_DEPTH <= 255); // MICROPY_SCHEDULER_DEPTH must fit in 8 bits MP_STATIC_ASSERT((IDX_MASK(MICROPY_SCHEDULER_DEPTH) == 0)); // MICROPY_SCHEDULER_DEPTH must be a power of 2 return mp_sched_num_pending() == MICROPY_SCHEDULER_DEPTH; } static inline bool mp_sched_empty(void) { return mp_sched_num_pending() == 0; } // A variant of this is inlined in the VM at the pending exception check void mp_handle_pending(void) { if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_obj_t obj = MP_STATE_VM(mp_pending_exception); if (obj != MP_OBJ_NULL) { MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; if (!mp_sched_num_pending()) { MP_STATE_VM(sched_state) = MP_SCHED_IDLE; } MICROPY_END_ATOMIC_SECTION(atomic_state); nlr_raise(obj); } mp_handle_pending_tail(atomic_state); } } // This function should only be called be mp_sched_handle_pending, // or by the VM's inlined version of that function. void mp_handle_pending_tail(mp_uint_t atomic_state) { MP_STATE_VM(sched_state) = MP_SCHED_LOCKED; if (!mp_sched_empty()) { mp_sched_item_t item = MP_STATE_VM(sched_queue)[MP_STATE_VM(sched_idx)]; MP_STATE_VM(sched_idx) = IDX_MASK(MP_STATE_VM(sched_idx) + 1); --MP_STATE_VM(sched_len); MICROPY_END_ATOMIC_SECTION(atomic_state); mp_call_function_1_protected(item.func, item.arg); } else { MICROPY_END_ATOMIC_SECTION(atomic_state); } mp_sched_unlock(); } void mp_sched_lock(void) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); if (MP_STATE_VM(sched_state) < 0) { --MP_STATE_VM(sched_state); } else { MP_STATE_VM(sched_state) = MP_SCHED_LOCKED; } MICROPY_END_ATOMIC_SECTION(atomic_state); } void mp_sched_unlock(void) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); if (++MP_STATE_VM(sched_state) == 0) { // vm became unlocked if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL || mp_sched_num_pending()) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } else { MP_STATE_VM(sched_state) = MP_SCHED_IDLE; } } MICROPY_END_ATOMIC_SECTION(atomic_state); } bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); bool ret; if (!mp_sched_full()) { if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } uint8_t iput = IDX_MASK(MP_STATE_VM(sched_idx) + MP_STATE_VM(sched_len)++); MP_STATE_VM(sched_queue)[iput].func = function; MP_STATE_VM(sched_queue)[iput].arg = arg; ret = true; } else { // schedule queue is full ret = false; } MICROPY_END_ATOMIC_SECTION(atomic_state); return ret; } #else // MICROPY_ENABLE_SCHEDULER // A variant of this is inlined in the VM at the pending exception check void mp_handle_pending(void) { if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } } #endif // MICROPY_ENABLE_SCHEDULER micropython-1.12/py/scope.c000066400000000000000000000126631357706137100157370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/scope.h" #if MICROPY_ENABLE_COMPILER // these low numbered qstrs should fit in 8 bits STATIC const uint8_t scope_simple_name_table[] = { [SCOPE_MODULE] = MP_QSTR__lt_module_gt_, [SCOPE_LAMBDA] = MP_QSTR__lt_lambda_gt_, [SCOPE_LIST_COMP] = MP_QSTR__lt_listcomp_gt_, [SCOPE_DICT_COMP] = MP_QSTR__lt_dictcomp_gt_, [SCOPE_SET_COMP] = MP_QSTR__lt_setcomp_gt_, [SCOPE_GEN_EXPR] = MP_QSTR__lt_genexpr_gt_, }; scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, mp_uint_t emit_options) { scope_t *scope = m_new0(scope_t, 1); scope->kind = kind; scope->pn = pn; scope->source_file = source_file; if (kind == SCOPE_FUNCTION || kind == SCOPE_CLASS) { assert(MP_PARSE_NODE_IS_STRUCT(pn)); scope->simple_name = MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn)->nodes[0]); } else { scope->simple_name = scope_simple_name_table[kind]; } scope->raw_code = mp_emit_glue_new_raw_code(); scope->emit_options = emit_options; scope->id_info_alloc = MICROPY_ALLOC_SCOPE_ID_INIT; scope->id_info = m_new(id_info_t, scope->id_info_alloc); return scope; } void scope_free(scope_t *scope) { m_del(id_info_t, scope->id_info, scope->id_info_alloc); m_del(scope_t, scope, 1); } id_info_t *scope_find_or_add_id(scope_t *scope, qstr qst, scope_kind_t kind) { id_info_t *id_info = scope_find(scope, qst); if (id_info != NULL) { return id_info; } // make sure we have enough memory if (scope->id_info_len >= scope->id_info_alloc) { scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc + MICROPY_ALLOC_SCOPE_ID_INC); scope->id_info_alloc += MICROPY_ALLOC_SCOPE_ID_INC; } // add new id to end of array of all ids; this seems to match CPython // important thing is that function arguments are first, but that is // handled by the compiler because it adds arguments before compiling the body id_info = &scope->id_info[scope->id_info_len++]; id_info->kind = kind; id_info->flags = 0; id_info->local_num = 0; id_info->qst = qst; return id_info; } id_info_t *scope_find(scope_t *scope, qstr qst) { for (mp_uint_t i = 0; i < scope->id_info_len; i++) { if (scope->id_info[i].qst == qst) { return &scope->id_info[i]; } } return NULL; } id_info_t *scope_find_global(scope_t *scope, qstr qst) { while (scope->parent != NULL) { scope = scope->parent; } return scope_find(scope, qst); } STATIC void scope_close_over_in_parents(scope_t *scope, qstr qst) { assert(scope->parent != NULL); // we should have at least 1 parent for (scope_t *s = scope->parent;; s = s->parent) { assert(s->parent != NULL); // we should not get to the outer scope id_info_t *id = scope_find_or_add_id(s, qst, ID_INFO_KIND_UNDECIDED); if (id->kind == ID_INFO_KIND_UNDECIDED) { // variable not previously declared in this scope, so declare it as free and keep searching parents id->kind = ID_INFO_KIND_FREE; } else { // variable is declared in this scope, so finish if (id->kind == ID_INFO_KIND_LOCAL) { // variable local to this scope, close it over id->kind = ID_INFO_KIND_CELL; } else { // ID_INFO_KIND_FREE: variable already closed over in a parent scope // ID_INFO_KIND_CELL: variable already closed over in this scope assert(id->kind == ID_INFO_KIND_FREE || id->kind == ID_INFO_KIND_CELL); } return; } } } void scope_check_to_close_over(scope_t *scope, id_info_t *id) { if (scope->parent != NULL) { for (scope_t *s = scope->parent; s->parent != NULL; s = s->parent) { id_info_t *id2 = scope_find(s, id->qst); if (id2 != NULL) { if (id2->kind == ID_INFO_KIND_LOCAL || id2->kind == ID_INFO_KIND_CELL || id2->kind == ID_INFO_KIND_FREE) { id->kind = ID_INFO_KIND_FREE; scope_close_over_in_parents(scope, id->qst); } break; } } } } #endif // MICROPY_ENABLE_COMPILER micropython-1.12/py/scope.h000066400000000000000000000066241357706137100157440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_SCOPE_H #define MICROPY_INCLUDED_PY_SCOPE_H #include "py/parse.h" #include "py/emitglue.h" enum { ID_INFO_KIND_UNDECIDED, ID_INFO_KIND_GLOBAL_IMPLICIT, ID_INFO_KIND_GLOBAL_EXPLICIT, ID_INFO_KIND_LOCAL, // in a function f, written and only referenced by f ID_INFO_KIND_CELL, // in a function f, read/written by children of f ID_INFO_KIND_FREE, // in a function f, belongs to the parent of f }; enum { ID_FLAG_IS_PARAM = 0x01, ID_FLAG_IS_STAR_PARAM = 0x02, ID_FLAG_IS_DBL_STAR_PARAM = 0x04, ID_FLAG_VIPER_TYPE_POS = 4, }; typedef struct _id_info_t { uint8_t kind; uint8_t flags; // when it's an ID_INFO_KIND_LOCAL this is the unique number of the local // whet it's an ID_INFO_KIND_CELL/FREE this is the unique number of the closed over variable uint16_t local_num; qstr qst; } id_info_t; #define SCOPE_IS_FUNC_LIKE(s) ((s) >= SCOPE_LAMBDA) // scope is a "block" in Python parlance typedef enum { SCOPE_MODULE, SCOPE_CLASS, SCOPE_LAMBDA, SCOPE_LIST_COMP, SCOPE_DICT_COMP, SCOPE_SET_COMP, SCOPE_GEN_EXPR, SCOPE_FUNCTION, } scope_kind_t; typedef struct _scope_t { scope_kind_t kind; struct _scope_t *parent; struct _scope_t *next; mp_parse_node_t pn; mp_raw_code_t *raw_code; uint16_t source_file; // a qstr uint16_t simple_name; // a qstr uint16_t scope_flags; // see runtime0.h uint16_t emit_options; // see emitglue.h uint16_t num_pos_args; uint16_t num_kwonly_args; uint16_t num_def_pos_args; uint16_t num_locals; uint16_t stack_size; // maximum size of the locals stack uint16_t exc_stack_size; // maximum size of the exception stack uint16_t id_info_alloc; uint16_t id_info_len; id_info_t *id_info; } scope_t; scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, mp_uint_t emit_options); void scope_free(scope_t *scope); id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, scope_kind_t kind); id_info_t *scope_find(scope_t *scope, qstr qstr); id_info_t *scope_find_global(scope_t *scope, qstr qstr); void scope_check_to_close_over(scope_t *scope, id_info_t *id); #endif // MICROPY_INCLUDED_PY_SCOPE_H micropython-1.12/py/sequence.c000066400000000000000000000204571357706137100164360ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/runtime.h" // Helpers for sequence types #define SWAP(type, var1, var2) { type t = var2; var2 = var1; var1 = t; } // Implements backend of sequence * integer operation. Assumes elements are // memory-adjacent in sequence. void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest) { for (size_t i = 0; i < times; i++) { size_t copy_sz = item_sz * len; memcpy(dest, items, copy_sz); dest = (char*)dest + copy_sz; } } #if MICROPY_PY_BUILTINS_SLICE bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) { mp_obj_t ostart, ostop, ostep; mp_int_t start, stop; mp_obj_slice_get(slice, &ostart, &ostop, &ostep); if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { indexes->step = mp_obj_get_int(ostep); if (indexes->step == 0) { mp_raise_ValueError("slice step cannot be zero"); } } else { indexes->step = 1; } if (ostart == mp_const_none) { if (indexes->step > 0) { start = 0; } else { start = len - 1; } } else { start = mp_obj_get_int(ostart); } if (ostop == mp_const_none) { if (indexes->step > 0) { stop = len; } else { stop = 0; } } else { stop = mp_obj_get_int(ostop); if (stop >= 0 && indexes->step < 0) { stop += 1; } } // Unlike subscription, out-of-bounds slice indexes are never error if (start < 0) { start = len + start; if (start < 0) { if (indexes->step < 0) { start = -1; } else { start = 0; } } } else if (indexes->step > 0 && (mp_uint_t)start > len) { start = len; } else if (indexes->step < 0 && (mp_uint_t)start >= len) { start = len - 1; } if (stop < 0) { stop = len + stop; if (stop < 0) { stop = -1; } if (indexes->step < 0) { stop += 1; } } else if ((mp_uint_t)stop > len) { stop = len; } // CPython returns empty sequence in such case, or point for assignment is at start if (indexes->step > 0 && start > stop) { stop = start; } else if (indexes->step < 0 && start < stop) { stop = start + 1; } indexes->start = start; indexes->stop = stop; return indexes->step == 1; } #endif mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes) { (void)len; // TODO can we remove len from the arg list? mp_int_t start = indexes->start, stop = indexes->stop; mp_int_t step = indexes->step; mp_obj_t res = mp_obj_new_list(0, NULL); if (step < 0) { while (start >= stop) { mp_obj_list_append(res, seq[start]); start += step; } } else { while (start < stop) { mp_obj_list_append(res, seq[start]); start += step; } } return res; } // Special-case comparison function for sequences of bytes // Don't pass MP_BINARY_OP_NOT_EQUAL here bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2) { if (op == MP_BINARY_OP_EQUAL && len1 != len2) { return false; } // Let's deal only with > & >= if (op == MP_BINARY_OP_LESS || op == MP_BINARY_OP_LESS_EQUAL) { SWAP(const byte*, data1, data2); SWAP(size_t, len1, len2); if (op == MP_BINARY_OP_LESS) { op = MP_BINARY_OP_MORE; } else { op = MP_BINARY_OP_MORE_EQUAL; } } size_t min_len = len1 < len2 ? len1 : len2; int res = memcmp(data1, data2, min_len); if (op == MP_BINARY_OP_EQUAL) { // If we are checking for equality, here's the answer return res == 0; } if (res < 0) { return false; } if (res > 0) { return true; } // If we had tie in the last element... // ... and we have lists of different lengths... if (len1 != len2) { if (len1 < len2) { // ... then longer list length wins (we deal only with >) return false; } } else if (op == MP_BINARY_OP_MORE) { // Otherwise, if we have strict relation, equality means failure return false; } return true; } // Special-case comparison function for sequences of mp_obj_t // Don't pass MP_BINARY_OP_NOT_EQUAL here bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp_obj_t *items2, size_t len2) { if (op == MP_BINARY_OP_EQUAL && len1 != len2) { return false; } // Let's deal only with > & >= if (op == MP_BINARY_OP_LESS || op == MP_BINARY_OP_LESS_EQUAL) { SWAP(const mp_obj_t *, items1, items2); SWAP(size_t, len1, len2); if (op == MP_BINARY_OP_LESS) { op = MP_BINARY_OP_MORE; } else { op = MP_BINARY_OP_MORE_EQUAL; } } size_t len = len1 < len2 ? len1 : len2; for (size_t i = 0; i < len; i++) { // If current elements equal, can't decide anything - go on if (mp_obj_equal(items1[i], items2[i])) { continue; } // Othewise, if they are not equal, we can have final decision based on them if (op == MP_BINARY_OP_EQUAL) { // In particular, if we are checking for equality, here're the answer return false; } // Otherwise, application of relation op gives the answer return (mp_binary_op(op, items1[i], items2[i]) == mp_const_true); } // If we had tie in the last element... // ... and we have lists of different lengths... if (len1 != len2) { if (len1 < len2) { // ... then longer list length wins (we deal only with >) return false; } } else if (op == MP_BINARY_OP_MORE) { // Otherwise, if we have strict relation, sequence equality means failure return false; } return true; } // Special-case of index() which searches for mp_obj_t mp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args) { mp_obj_type_t *type = mp_obj_get_type(args[0]); mp_obj_t value = args[1]; size_t start = 0; size_t stop = len; if (n_args >= 3) { start = mp_get_index(type, len, args[2], true); if (n_args >= 4) { stop = mp_get_index(type, len, args[3], true); } } for (size_t i = start; i < stop; i++) { if (mp_obj_equal(items[i], value)) { // Common sense says this cannot overflow small int return MP_OBJ_NEW_SMALL_INT(i); } } mp_raise_ValueError("object not in sequence"); } mp_obj_t mp_seq_count_obj(const mp_obj_t *items, size_t len, mp_obj_t value) { size_t count = 0; for (size_t i = 0; i < len; i++) { if (mp_obj_equal(items[i], value)) { count++; } } // Common sense says this cannot overflow small int return MP_OBJ_NEW_SMALL_INT(count); } micropython-1.12/py/showbc.c000066400000000000000000000416031357706137100161070ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/bc0.h" #include "py/bc.h" #if MICROPY_DEBUG_PRINTERS // redirect all printfs in this file to the platform print stream #define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__) #define DECODE_UINT { \ unum = 0; \ do { \ unum = (unum << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0); \ } #define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0) #define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0) #if MICROPY_PERSISTENT_CODE #define DECODE_QSTR \ qst = ip[0] | ip[1] << 8; \ ip += 2; #define DECODE_PTR \ DECODE_UINT; \ unum = mp_showbc_const_table[unum] #define DECODE_OBJ \ DECODE_UINT; \ unum = mp_showbc_const_table[unum] #else #define DECODE_QSTR { \ qst = 0; \ do { \ qst = (qst << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0); \ } #define DECODE_PTR do { \ ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \ unum = (uintptr_t)*(void**)ip; \ ip += sizeof(void*); \ } while (0) #define DECODE_OBJ do { \ ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \ unum = (mp_uint_t)*(mp_obj_t*)ip; \ ip += sizeof(mp_obj_t); \ } while (0) #endif const byte *mp_showbc_code_start; const mp_uint_t *mp_showbc_const_table; void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const mp_uint_t *const_table) { mp_showbc_code_start = ip; // Decode prelude MP_BC_PRELUDE_SIG_DECODE(ip); MP_BC_PRELUDE_SIZE_DECODE(ip); const byte *code_info = ip; #if MICROPY_PERSISTENT_CODE qstr block_name = code_info[0] | (code_info[1] << 8); qstr source_file = code_info[2] | (code_info[3] << 8); code_info += 4; #else qstr block_name = mp_decode_uint(&code_info); qstr source_file = mp_decode_uint(&code_info); #endif printf("File %s, code block '%s' (descriptor: %p, bytecode @%p " UINT_FMT " bytes)\n", qstr_str(source_file), qstr_str(block_name), descr, mp_showbc_code_start, len); // raw bytecode dump size_t prelude_size = ip - mp_showbc_code_start + n_info + n_cell; printf("Raw bytecode (code_info_size=" UINT_FMT ", bytecode_size=" UINT_FMT "):\n", prelude_size, len - prelude_size); for (mp_uint_t i = 0; i < len; i++) { if (i > 0 && i % 16 == 0) { printf("\n"); } printf(" %02x", mp_showbc_code_start[i]); } printf("\n"); // bytecode prelude: arg names (as qstr objects) printf("arg names:"); for (mp_uint_t i = 0; i < n_pos_args + n_kwonly_args; i++) { printf(" %s", qstr_str(MP_OBJ_QSTR_VALUE(const_table[i]))); } printf("\n"); printf("(N_STATE %u)\n", (unsigned)n_state); printf("(N_EXC_STACK %u)\n", (unsigned)n_exc_stack); // skip over code_info ip += n_info; // bytecode prelude: initialise closed over variables for (size_t i = 0; i < n_cell; ++i) { uint local_num = *ip++; printf("(INIT_CELL %u)\n", local_num); } // print out line number info { mp_int_t bc = 0; mp_uint_t source_line = 1; printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); for (const byte* ci = code_info; *ci;) { if ((ci[0] & 0x80) == 0) { // 0b0LLBBBBB encoding bc += ci[0] & 0x1f; source_line += ci[0] >> 5; ci += 1; } else { // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) bc += ci[0] & 0xf; source_line += ((ci[0] << 4) & 0x700) | ci[1]; ci += 2; } printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); } } mp_bytecode_print2(ip, len - prelude_size, const_table); } const byte *mp_bytecode_print_str(const byte *ip) { mp_uint_t unum; qstr qst; switch (*ip++) { case MP_BC_LOAD_CONST_FALSE: printf("LOAD_CONST_FALSE"); break; case MP_BC_LOAD_CONST_NONE: printf("LOAD_CONST_NONE"); break; case MP_BC_LOAD_CONST_TRUE: printf("LOAD_CONST_TRUE"); break; case MP_BC_LOAD_CONST_SMALL_INT: { mp_int_t num = 0; if ((ip[0] & 0x40) != 0) { // Number is negative num--; } do { num = (num << 7) | (*ip & 0x7f); } while ((*ip++ & 0x80) != 0); printf("LOAD_CONST_SMALL_INT " INT_FMT, num); break; } case MP_BC_LOAD_CONST_STRING: DECODE_QSTR; printf("LOAD_CONST_STRING '%s'", qstr_str(qst)); break; case MP_BC_LOAD_CONST_OBJ: DECODE_OBJ; printf("LOAD_CONST_OBJ %p=", MP_OBJ_TO_PTR(unum)); mp_obj_print_helper(&mp_plat_print, (mp_obj_t)unum, PRINT_REPR); break; case MP_BC_LOAD_NULL: printf("LOAD_NULL"); break; case MP_BC_LOAD_FAST_N: DECODE_UINT; printf("LOAD_FAST_N " UINT_FMT, unum); break; case MP_BC_LOAD_DEREF: DECODE_UINT; printf("LOAD_DEREF " UINT_FMT, unum); break; case MP_BC_LOAD_NAME: DECODE_QSTR; printf("LOAD_NAME %s", qstr_str(qst)); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { printf(" (cache=%u)", *ip++); } break; case MP_BC_LOAD_GLOBAL: DECODE_QSTR; printf("LOAD_GLOBAL %s", qstr_str(qst)); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { printf(" (cache=%u)", *ip++); } break; case MP_BC_LOAD_ATTR: DECODE_QSTR; printf("LOAD_ATTR %s", qstr_str(qst)); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { printf(" (cache=%u)", *ip++); } break; case MP_BC_LOAD_METHOD: DECODE_QSTR; printf("LOAD_METHOD %s", qstr_str(qst)); break; case MP_BC_LOAD_SUPER_METHOD: DECODE_QSTR; printf("LOAD_SUPER_METHOD %s", qstr_str(qst)); break; case MP_BC_LOAD_BUILD_CLASS: printf("LOAD_BUILD_CLASS"); break; case MP_BC_LOAD_SUBSCR: printf("LOAD_SUBSCR"); break; case MP_BC_STORE_FAST_N: DECODE_UINT; printf("STORE_FAST_N " UINT_FMT, unum); break; case MP_BC_STORE_DEREF: DECODE_UINT; printf("STORE_DEREF " UINT_FMT, unum); break; case MP_BC_STORE_NAME: DECODE_QSTR; printf("STORE_NAME %s", qstr_str(qst)); break; case MP_BC_STORE_GLOBAL: DECODE_QSTR; printf("STORE_GLOBAL %s", qstr_str(qst)); break; case MP_BC_STORE_ATTR: DECODE_QSTR; printf("STORE_ATTR %s", qstr_str(qst)); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { printf(" (cache=%u)", *ip++); } break; case MP_BC_STORE_SUBSCR: printf("STORE_SUBSCR"); break; case MP_BC_DELETE_FAST: DECODE_UINT; printf("DELETE_FAST " UINT_FMT, unum); break; case MP_BC_DELETE_DEREF: DECODE_UINT; printf("DELETE_DEREF " UINT_FMT, unum); break; case MP_BC_DELETE_NAME: DECODE_QSTR; printf("DELETE_NAME %s", qstr_str(qst)); break; case MP_BC_DELETE_GLOBAL: DECODE_QSTR; printf("DELETE_GLOBAL %s", qstr_str(qst)); break; case MP_BC_DUP_TOP: printf("DUP_TOP"); break; case MP_BC_DUP_TOP_TWO: printf("DUP_TOP_TWO"); break; case MP_BC_POP_TOP: printf("POP_TOP"); break; case MP_BC_ROT_TWO: printf("ROT_TWO"); break; case MP_BC_ROT_THREE: printf("ROT_THREE"); break; case MP_BC_JUMP: DECODE_SLABEL; printf("JUMP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_POP_JUMP_IF_TRUE: DECODE_SLABEL; printf("POP_JUMP_IF_TRUE " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_POP_JUMP_IF_FALSE: DECODE_SLABEL; printf("POP_JUMP_IF_FALSE " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_JUMP_IF_TRUE_OR_POP: DECODE_SLABEL; printf("JUMP_IF_TRUE_OR_POP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_JUMP_IF_FALSE_OR_POP: DECODE_SLABEL; printf("JUMP_IF_FALSE_OR_POP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_SETUP_WITH: DECODE_ULABEL; // loop-like labels are always forward printf("SETUP_WITH " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_WITH_CLEANUP: printf("WITH_CLEANUP"); break; case MP_BC_UNWIND_JUMP: DECODE_SLABEL; printf("UNWIND_JUMP " UINT_FMT " %d", (mp_uint_t)(ip + unum - mp_showbc_code_start), *ip); ip += 1; break; case MP_BC_SETUP_EXCEPT: DECODE_ULABEL; // except labels are always forward printf("SETUP_EXCEPT " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_SETUP_FINALLY: DECODE_ULABEL; // except labels are always forward printf("SETUP_FINALLY " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_END_FINALLY: // if TOS is an exception, reraises the exception (3 values on TOS) // if TOS is an integer, does something else // if TOS is None, just pops it and continues // else error printf("END_FINALLY"); break; case MP_BC_GET_ITER: printf("GET_ITER"); break; case MP_BC_GET_ITER_STACK: printf("GET_ITER_STACK"); break; case MP_BC_FOR_ITER: DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward printf("FOR_ITER " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_POP_EXCEPT_JUMP: DECODE_ULABEL; // these labels are always forward printf("POP_EXCEPT_JUMP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start)); break; case MP_BC_BUILD_TUPLE: DECODE_UINT; printf("BUILD_TUPLE " UINT_FMT, unum); break; case MP_BC_BUILD_LIST: DECODE_UINT; printf("BUILD_LIST " UINT_FMT, unum); break; case MP_BC_BUILD_MAP: DECODE_UINT; printf("BUILD_MAP " UINT_FMT, unum); break; case MP_BC_STORE_MAP: printf("STORE_MAP"); break; case MP_BC_BUILD_SET: DECODE_UINT; printf("BUILD_SET " UINT_FMT, unum); break; #if MICROPY_PY_BUILTINS_SLICE case MP_BC_BUILD_SLICE: DECODE_UINT; printf("BUILD_SLICE " UINT_FMT, unum); break; #endif case MP_BC_STORE_COMP: DECODE_UINT; printf("STORE_COMP " UINT_FMT, unum); break; case MP_BC_UNPACK_SEQUENCE: DECODE_UINT; printf("UNPACK_SEQUENCE " UINT_FMT, unum); break; case MP_BC_UNPACK_EX: DECODE_UINT; printf("UNPACK_EX " UINT_FMT, unum); break; case MP_BC_MAKE_FUNCTION: DECODE_PTR; printf("MAKE_FUNCTION %p", (void*)(uintptr_t)unum); break; case MP_BC_MAKE_FUNCTION_DEFARGS: DECODE_PTR; printf("MAKE_FUNCTION_DEFARGS %p", (void*)(uintptr_t)unum); break; case MP_BC_MAKE_CLOSURE: { DECODE_PTR; mp_uint_t n_closed_over = *ip++; printf("MAKE_CLOSURE %p " UINT_FMT, (void*)(uintptr_t)unum, n_closed_over); break; } case MP_BC_MAKE_CLOSURE_DEFARGS: { DECODE_PTR; mp_uint_t n_closed_over = *ip++; printf("MAKE_CLOSURE_DEFARGS %p " UINT_FMT, (void*)(uintptr_t)unum, n_closed_over); break; } case MP_BC_CALL_FUNCTION: DECODE_UINT; printf("CALL_FUNCTION n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff); break; case MP_BC_CALL_FUNCTION_VAR_KW: DECODE_UINT; printf("CALL_FUNCTION_VAR_KW n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff); break; case MP_BC_CALL_METHOD: DECODE_UINT; printf("CALL_METHOD n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff); break; case MP_BC_CALL_METHOD_VAR_KW: DECODE_UINT; printf("CALL_METHOD_VAR_KW n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff); break; case MP_BC_RETURN_VALUE: printf("RETURN_VALUE"); break; case MP_BC_RAISE_LAST: printf("RAISE_LAST"); break; case MP_BC_RAISE_OBJ: printf("RAISE_OBJ"); break; case MP_BC_RAISE_FROM: printf("RAISE_FROM"); break; case MP_BC_YIELD_VALUE: printf("YIELD_VALUE"); break; case MP_BC_YIELD_FROM: printf("YIELD_FROM"); break; case MP_BC_IMPORT_NAME: DECODE_QSTR; printf("IMPORT_NAME '%s'", qstr_str(qst)); break; case MP_BC_IMPORT_FROM: DECODE_QSTR; printf("IMPORT_FROM '%s'", qstr_str(qst)); break; case MP_BC_IMPORT_STAR: printf("IMPORT_STAR"); break; default: if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) { printf("LOAD_CONST_SMALL_INT " INT_FMT, (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16); } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) { printf("LOAD_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI); } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) { printf("STORE_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI); } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE) { printf("UNARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI); } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE) { mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI; printf("BINARY_OP " UINT_FMT " %s", op, qstr_str(mp_binary_op_method_name[op])); } else { printf("code %p, byte code 0x%02x not implemented\n", ip - 1, ip[-1]); assert(0); return ip; } break; } return ip; } void mp_bytecode_print2(const byte *ip, size_t len, const mp_uint_t *const_table) { mp_showbc_code_start = ip; mp_showbc_const_table = const_table; while (ip < len + mp_showbc_code_start) { printf("%02u ", (uint)(ip - mp_showbc_code_start)); ip = mp_bytecode_print_str(ip); printf("\n"); } } #endif // MICROPY_DEBUG_PRINTERS micropython-1.12/py/smallint.c000066400000000000000000000052011357706137100164370ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/smallint.h" bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) { // Check for multiply overflow; see CERT INT32-C if (x > 0) { // x is positive if (y > 0) { // x and y are positive if (x > (MP_SMALL_INT_MAX / y)) { return true; } } else { // x positive, y nonpositive if (y < (MP_SMALL_INT_MIN / x)) { return true; } } // x positive, y nonpositive } else { // x is nonpositive if (y > 0) { // x is nonpositive, y is positive if (x < (MP_SMALL_INT_MIN / y)) { return true; } } else { // x and y are nonpositive if (x != 0 && y < (MP_SMALL_INT_MAX / x)) { return true; } } // End if x and y are nonpositive } // End if x is nonpositive return false; } mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) { // Python specs require that mod has same sign as second operand dividend %= divisor; if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) { dividend += divisor; } return dividend; } mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom) { if (num >= 0) { if (denom < 0) { num += -denom - 1; } } else { if (denom >= 0) { num += -denom + 1; } } return num / denom; } micropython-1.12/py/smallint.h000066400000000000000000000055251357706137100164550ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_SMALLINT_H #define MICROPY_INCLUDED_PY_SMALLINT_H #include "py/mpconfig.h" #include "py/misc.h" // Functions for small integer arithmetic #ifndef MP_SMALL_INT_MIN // In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C #define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)WORD_MSBIT_HIGH) >> 1)) #define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0) // Mask to truncate mp_int_t to positive value #define MP_SMALL_INT_POSITIVE_MASK ~(WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1)) #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B #define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)WORD_MSBIT_HIGH) >> 2)) #define MP_SMALL_INT_FITS(n) ((((n) & MP_SMALL_INT_MIN) == 0) || (((n) & MP_SMALL_INT_MIN) == MP_SMALL_INT_MIN)) // Mask to truncate mp_int_t to positive value #define MP_SMALL_INT_POSITIVE_MASK ~(WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1) | (WORD_MSBIT_HIGH >> 2)) #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D #define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffff800000000000) >> 1)) #define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffff800000000000) == 0) // Mask to truncate mp_int_t to positive value #define MP_SMALL_INT_POSITIVE_MASK ~(0xffff800000000000 | (0xffff800000000000 >> 1)) #endif #endif #define MP_SMALL_INT_MAX ((mp_int_t)(~(MP_SMALL_INT_MIN))) bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y); mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor); mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom); #endif // MICROPY_INCLUDED_PY_SMALLINT_H micropython-1.12/py/stackctrl.c000066400000000000000000000035621357706137100166160ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "py/runtime.h" #include "py/stackctrl.h" void mp_stack_ctrl_init(void) { volatile int stack_dummy; MP_STATE_THREAD(stack_top) = (char*)&stack_dummy; } void mp_stack_set_top(void *top) { MP_STATE_THREAD(stack_top) = top; } mp_uint_t mp_stack_usage(void) { // Assumes descending stack volatile int stack_dummy; return MP_STATE_THREAD(stack_top) - (char*)&stack_dummy; } #if MICROPY_STACK_CHECK void mp_stack_set_limit(mp_uint_t limit) { MP_STATE_THREAD(stack_limit) = limit; } void mp_stack_check(void) { if (mp_stack_usage() >= MP_STATE_THREAD(stack_limit)) { mp_raise_recursion_depth(); } } #endif // MICROPY_STACK_CHECK micropython-1.12/py/stackctrl.h000066400000000000000000000032231357706137100166150ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_STACKCTRL_H #define MICROPY_INCLUDED_PY_STACKCTRL_H #include "py/mpconfig.h" void mp_stack_ctrl_init(void); void mp_stack_set_top(void *top); mp_uint_t mp_stack_usage(void); #if MICROPY_STACK_CHECK void mp_stack_set_limit(mp_uint_t limit); void mp_stack_check(void); #define MP_STACK_CHECK() mp_stack_check() #else #define mp_stack_set_limit(limit) #define MP_STACK_CHECK() #endif #endif // MICROPY_INCLUDED_PY_STACKCTRL_H micropython-1.12/py/stream.c000066400000000000000000000471061357706137100161210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2014-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/objstr.h" #include "py/stream.h" #include "py/runtime.h" // This file defines generic Python stream read/write methods which // dispatch to the underlying stream interface of an object. // TODO: should be in mpconfig.h #define DEFAULT_BUFFER_SIZE 256 STATIC mp_obj_t stream_readall(mp_obj_t self_in); #define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes) // Returns error condition in *errcode, if non-zero, return value is number of bytes written // before error condition occurred. If *errcode == 0, returns total bytes written (which will // be equal to input size). mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode, byte flags) { byte *buf = buf_; typedef mp_uint_t (*io_func_t)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); io_func_t io_func; const mp_stream_p_t *stream_p = mp_get_stream(stream); if (flags & MP_STREAM_RW_WRITE) { io_func = (io_func_t)stream_p->write; } else { io_func = stream_p->read; } *errcode = 0; mp_uint_t done = 0; while (size > 0) { mp_uint_t out_sz = io_func(stream, buf, size, errcode); // For read, out_sz == 0 means EOF. For write, it's unspecified // what it means, but we don't make any progress, so returning // is still the best option. if (out_sz == 0) { return done; } if (out_sz == MP_STREAM_ERROR) { // If we read something before getting EAGAIN, don't leak it if (mp_is_nonblocking_error(*errcode) && done != 0) { *errcode = 0; } return done; } if (flags & MP_STREAM_RW_ONCE) { return out_sz; } buf += out_sz; size -= out_sz; done += out_sz; } return done; } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { mp_obj_type_t *type = mp_obj_get_type(self_in); const mp_stream_p_t *stream_p = type->protocol; if (stream_p == NULL || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) || ((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) { // CPython: io.UnsupportedOperation, OSError subclass mp_raise_msg(&mp_type_OSError, "stream operation not supported"); } return stream_p; } STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) { // What to do if sz < -1? Python docs don't specify this case. // CPython does a readall, but here we silently let negatives through, // and they will cause a MemoryError. mp_int_t sz; if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) { return stream_readall(args[0]); } const mp_stream_p_t *stream_p = mp_get_stream(args[0]); #if MICROPY_PY_BUILTINS_STR_UNICODE if (stream_p->is_text) { // We need to read sz number of unicode characters. Because we don't have any // buffering, and because the stream API can only read bytes, we must read here // in units of bytes and must never over read. If we want sz chars, then reading // sz bytes will never over-read, so we follow this approach, in a loop to keep // reading until we have exactly enough chars. This will be 1 read for text // with ASCII-only chars, and about 2 reads for text with a couple of non-ASCII // chars. For text with lots of non-ASCII chars, it'll be pretty inefficient // in time and memory. vstr_t vstr; vstr_init(&vstr, sz); mp_uint_t more_bytes = sz; mp_uint_t last_buf_offset = 0; while (more_bytes > 0) { char *p = vstr_add_len(&vstr, more_bytes); int error; mp_uint_t out_sz = mp_stream_read_exactly(args[0], p, more_bytes, &error); if (error != 0) { vstr_cut_tail_bytes(&vstr, more_bytes); if (mp_is_nonblocking_error(error)) { // With non-blocking streams, we read as much as we can. // If we read nothing, return None, just like read(). // Otherwise, return data read so far. // TODO what if we have read only half a non-ASCII char? if (vstr.len == 0) { vstr_clear(&vstr); return mp_const_none; } break; } mp_raise_OSError(error); } if (out_sz < more_bytes) { // Finish reading. // TODO what if we have read only half a non-ASCII char? vstr_cut_tail_bytes(&vstr, more_bytes - out_sz); if (out_sz == 0) { break; } } // count chars from bytes just read for (mp_uint_t off = last_buf_offset;;) { byte b = vstr.buf[off]; int n; if (!UTF8_IS_NONASCII(b)) { // 1-byte ASCII char n = 1; } else if ((b & 0xe0) == 0xc0) { // 2-byte char n = 2; } else if ((b & 0xf0) == 0xe0) { // 3-byte char n = 3; } else if ((b & 0xf8) == 0xf0) { // 4-byte char n = 4; } else { // TODO n = 5; } if (off + n <= vstr.len) { // got a whole char in n bytes off += n; sz -= 1; last_buf_offset = off; if (off >= vstr.len) { more_bytes = sz; break; } } else { // didn't get a whole char, so work out how many extra bytes are needed for // this partial char, plus bytes for additional chars that we want more_bytes = (off + n - vstr.len) + (sz - 1); break; } } } return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } #endif vstr_t vstr; vstr_init_len(&vstr, sz); int error; mp_uint_t out_sz = mp_stream_rw(args[0], vstr.buf, sz, &error, flags); if (error != 0) { vstr_clear(&vstr); if (mp_is_nonblocking_error(error)) { // https://docs.python.org/3.4/library/io.html#io.RawIOBase.read // "If the object is in non-blocking mode and no bytes are available, // None is returned." // This is actually very weird, as naive truth check will treat // this as EOF. return mp_const_none; } mp_raise_OSError(error); } else { vstr.len = out_sz; return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); } } STATIC mp_obj_t stream_read(size_t n_args, const mp_obj_t *args) { return stream_read_generic(n_args, args, MP_STREAM_RW_READ); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read); STATIC mp_obj_t stream_read1(size_t n_args, const mp_obj_t *args) { return stream_read_generic(n_args, args, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj, 1, 2, stream_read1); mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len, byte flags) { int error; mp_uint_t out_sz = mp_stream_rw(self_in, (void*)buf, len, &error, flags); if (error != 0) { if (mp_is_nonblocking_error(error)) { // http://docs.python.org/3/library/io.html#io.RawIOBase.write // "None is returned if the raw stream is set not to block and // no single byte could be readily written to it." return mp_const_none; } mp_raise_OSError(error); } else { return MP_OBJ_NEW_SMALL_INT(out_sz); } } // This is used to adapt a stream object to an mp_print_t interface void mp_stream_write_adaptor(void *self, const char *buf, size_t len) { mp_stream_write(MP_OBJ_FROM_PTR(self), buf, len, MP_STREAM_RW_WRITE); } STATIC mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); size_t max_len = (size_t)-1; size_t off = 0; if (n_args == 3) { max_len = mp_obj_get_int_truncated(args[2]); } else if (n_args == 4) { off = mp_obj_get_int_truncated(args[2]); max_len = mp_obj_get_int_truncated(args[3]); if (off > bufinfo.len) { off = bufinfo.len; } } bufinfo.len -= off; return mp_stream_write(args[0], (byte*)bufinfo.buf + off, MIN(bufinfo.len, max_len), MP_STREAM_RW_WRITE); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj, 2, 4, stream_write_method); STATIC mp_obj_t stream_write1_method(mp_obj_t self_in, mp_obj_t arg) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); return mp_stream_write(self_in, bufinfo.buf, bufinfo.len, MP_STREAM_RW_WRITE | MP_STREAM_RW_ONCE); } MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write1_obj, stream_write1_method); STATIC mp_obj_t stream_readinto(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); // CPython extension: if 2nd arg is provided, that's max len to read, // instead of full buffer. Similar to // https://docs.python.org/3/library/socket.html#socket.socket.recv_into mp_uint_t len = bufinfo.len; if (n_args > 2) { len = mp_obj_get_int(args[2]); if (len > bufinfo.len) { len = bufinfo.len; } } int error; mp_uint_t out_sz = mp_stream_read_exactly(args[0], bufinfo.buf, len, &error); if (error != 0) { if (mp_is_nonblocking_error(error)) { return mp_const_none; } mp_raise_OSError(error); } else { return MP_OBJ_NEW_SMALL_INT(out_sz); } } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj, 2, 3, stream_readinto); STATIC mp_obj_t stream_readall(mp_obj_t self_in) { const mp_stream_p_t *stream_p = mp_get_stream(self_in); mp_uint_t total_size = 0; vstr_t vstr; vstr_init(&vstr, DEFAULT_BUFFER_SIZE); char *p = vstr.buf; mp_uint_t current_read = DEFAULT_BUFFER_SIZE; while (true) { int error; mp_uint_t out_sz = stream_p->read(self_in, p, current_read, &error); if (out_sz == MP_STREAM_ERROR) { if (mp_is_nonblocking_error(error)) { // With non-blocking streams, we read as much as we can. // If we read nothing, return None, just like read(). // Otherwise, return data read so far. if (total_size == 0) { return mp_const_none; } break; } mp_raise_OSError(error); } if (out_sz == 0) { break; } total_size += out_sz; if (out_sz < current_read) { current_read -= out_sz; p += out_sz; } else { p = vstr_extend(&vstr, DEFAULT_BUFFER_SIZE); current_read = DEFAULT_BUFFER_SIZE; } } vstr.len = total_size; return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); } // Unbuffered, inefficient implementation of readline() for raw I/O files. STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) { const mp_stream_p_t *stream_p = mp_get_stream(args[0]); mp_int_t max_size = -1; if (n_args > 1) { max_size = MP_OBJ_SMALL_INT_VALUE(args[1]); } vstr_t vstr; if (max_size != -1) { vstr_init(&vstr, max_size); } else { vstr_init(&vstr, 16); } while (max_size == -1 || max_size-- != 0) { char *p = vstr_add_len(&vstr, 1); int error; mp_uint_t out_sz = stream_p->read(args[0], p, 1, &error); if (out_sz == MP_STREAM_ERROR) { if (mp_is_nonblocking_error(error)) { if (vstr.len == 1) { // We just incremented it, but otherwise we read nothing // and immediately got EAGAIN. This case is not well // specified in // https://docs.python.org/3/library/io.html#io.IOBase.readline // unlike similar case for read(). But we follow the latter's // behavior - return None. vstr_clear(&vstr); return mp_const_none; } else { goto done; } } mp_raise_OSError(error); } if (out_sz == 0) { done: // Back out previously added byte // Consider, what's better - read a char and get OutOfMemory (so read // char is lost), or allocate first as we do. vstr_cut_tail_bytes(&vstr, 1); break; } if (*p == '\n') { break; } } return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline); // TODO take an optional extra argument (what does it do exactly?) STATIC mp_obj_t stream_unbuffered_readlines(mp_obj_t self) { mp_obj_t lines = mp_obj_new_list(0, NULL); for (;;) { mp_obj_t line = stream_unbuffered_readline(1, &self); if (!mp_obj_is_true(line)) { break; } mp_obj_list_append(lines, line); } return lines; } MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj, stream_unbuffered_readlines); mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) { mp_obj_t l_in = stream_unbuffered_readline(1, &self); if (mp_obj_is_true(l_in)) { return l_in; } return MP_OBJ_STOP_ITERATION; } mp_obj_t mp_stream_close(mp_obj_t stream) { const mp_stream_p_t *stream_p = mp_get_stream(stream); int error; mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error); if (res == MP_STREAM_ERROR) { mp_raise_OSError(error); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_close_obj, mp_stream_close); STATIC mp_obj_t stream_seek(size_t n_args, const mp_obj_t *args) { struct mp_stream_seek_t seek_s; // TODO: Could be uint64 seek_s.offset = mp_obj_get_int(args[1]); seek_s.whence = SEEK_SET; if (n_args == 3) { seek_s.whence = mp_obj_get_int(args[2]); } // In POSIX, it's error to seek before end of stream, we enforce it here. if (seek_s.whence == SEEK_SET && seek_s.offset < 0) { mp_raise_OSError(MP_EINVAL); } const mp_stream_p_t *stream_p = mp_get_stream(args[0]); int error; mp_uint_t res = stream_p->ioctl(args[0], MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error); if (res == MP_STREAM_ERROR) { mp_raise_OSError(error); } // TODO: Could be uint64 return mp_obj_new_int_from_uint(seek_s.offset); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj, 2, 3, stream_seek); STATIC mp_obj_t stream_tell(mp_obj_t self) { mp_obj_t offset = MP_OBJ_NEW_SMALL_INT(0); mp_obj_t whence = MP_OBJ_NEW_SMALL_INT(SEEK_CUR); const mp_obj_t args[3] = {self, offset, whence}; return stream_seek(3, args); } MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_tell_obj, stream_tell); STATIC mp_obj_t stream_flush(mp_obj_t self) { const mp_stream_p_t *stream_p = mp_get_stream(self); int error; mp_uint_t res = stream_p->ioctl(self, MP_STREAM_FLUSH, 0, &error); if (res == MP_STREAM_ERROR) { mp_raise_OSError(error); } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_flush_obj, stream_flush); STATIC mp_obj_t stream_ioctl(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; uintptr_t val = 0; if (n_args > 2) { if (mp_get_buffer(args[2], &bufinfo, MP_BUFFER_WRITE)) { val = (uintptr_t)bufinfo.buf; } else { val = mp_obj_get_int_truncated(args[2]); } } const mp_stream_p_t *stream_p = mp_get_stream(args[0]); int error; mp_uint_t res = stream_p->ioctl(args[0], mp_obj_get_int(args[1]), val, &error); if (res == MP_STREAM_ERROR) { mp_raise_OSError(error); } return mp_obj_new_int(res); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj, 2, 3, stream_ioctl); #if MICROPY_STREAMS_POSIX_API /* * POSIX-like functions * * These functions have POSIX-compatible signature (except for "void *stream" * first argument instead of "int fd"). They are useful to port existing * POSIX-compatible software to work with MicroPython streams. */ // errno-like variable. If any of the functions below returned with error // status, this variable will contain error no. int mp_stream_errno; ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { mp_obj_base_t* o = stream; const mp_stream_p_t *stream_p = o->type->protocol; mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &mp_stream_errno); if (out_sz == MP_STREAM_ERROR) { return -1; } else { return out_sz; } } ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { mp_obj_base_t* o = stream; const mp_stream_p_t *stream_p = o->type->protocol; mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &mp_stream_errno); if (out_sz == MP_STREAM_ERROR) { return -1; } else { return out_sz; } } off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { const mp_obj_base_t* o = stream; const mp_stream_p_t *stream_p = o->type->protocol; struct mp_stream_seek_t seek_s; seek_s.offset = offset; seek_s.whence = whence; mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &mp_stream_errno); if (res == MP_STREAM_ERROR) { return -1; } return seek_s.offset; } int mp_stream_posix_fsync(void *stream) { mp_obj_base_t* o = stream; const mp_stream_p_t *stream_p = o->type->protocol; mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &mp_stream_errno); if (res == MP_STREAM_ERROR) { return -1; } return res; } #endif micropython-1.12/py/stream.h000066400000000000000000000132161357706137100161210ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_STREAM_H #define MICROPY_INCLUDED_PY_STREAM_H #include "py/obj.h" #include "py/mperrno.h" #define MP_STREAM_ERROR ((mp_uint_t)-1) // Stream ioctl request codes #define MP_STREAM_FLUSH (1) #define MP_STREAM_SEEK (2) #define MP_STREAM_POLL (3) #define MP_STREAM_CLOSE (4) #define MP_STREAM_TIMEOUT (5) // Get/set timeout (single op) #define MP_STREAM_GET_OPTS (6) // Get stream options #define MP_STREAM_SET_OPTS (7) // Set stream options #define MP_STREAM_GET_DATA_OPTS (8) // Get data/message options #define MP_STREAM_SET_DATA_OPTS (9) // Set data/message options #define MP_STREAM_GET_FILENO (10) // Get fileno of underlying file // These poll ioctl values are compatible with Linux #define MP_STREAM_POLL_RD (0x0001) #define MP_STREAM_POLL_WR (0x0004) #define MP_STREAM_POLL_ERR (0x0008) #define MP_STREAM_POLL_HUP (0x0010) #define MP_STREAM_POLL_NVAL (0x0020) // Argument structure for MP_STREAM_SEEK struct mp_stream_seek_t { // If whence == MP_SEEK_SET, offset should be treated as unsigned. // This allows dealing with full-width stream sizes (16, 32, 64, // etc. bits). For other seek types, should be treated as signed. mp_off_t offset; int whence; }; // seek ioctl "whence" values #define MP_SEEK_SET (0) #define MP_SEEK_CUR (1) #define MP_SEEK_END (2) // Stream protocol typedef struct _mp_stream_p_t { // On error, functions should return MP_STREAM_ERROR and fill in *errcode (values // are implementation-dependent, but will be exposed to user, e.g. via exception). mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); mp_uint_t (*write)(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode); mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode); mp_uint_t is_text : 1; // default is bytes, set this for text stream } mp_stream_p_t; MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_stream_write1_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_close_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_tell_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_flush_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj); // these are for mp_get_stream_raise and can be or'd together #define MP_STREAM_OP_READ (1) #define MP_STREAM_OP_WRITE (2) #define MP_STREAM_OP_IOCTL (4) // Object is assumed to have a non-NULL stream protocol with valid r/w/ioctl methods static inline const mp_stream_p_t *mp_get_stream(mp_const_obj_t self) { return (const mp_stream_p_t*)((const mp_obj_base_t*)MP_OBJ_TO_PTR(self))->type->protocol; } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags); mp_obj_t mp_stream_close(mp_obj_t stream); // Iterator which uses mp_stream_unbuffered_readline_obj mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self); mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len, byte flags); // C-level helper functions #define MP_STREAM_RW_READ 0 #define MP_STREAM_RW_WRITE 2 #define MP_STREAM_RW_ONCE 1 mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf, mp_uint_t size, int *errcode, byte flags); #define mp_stream_write_exactly(stream, buf, size, err) mp_stream_rw(stream, (byte*)buf, size, err, MP_STREAM_RW_WRITE) #define mp_stream_read_exactly(stream, buf, size, err) mp_stream_rw(stream, buf, size, err, MP_STREAM_RW_READ) void mp_stream_write_adaptor(void *self, const char *buf, size_t len); #if MICROPY_STREAMS_POSIX_API // Functions with POSIX-compatible signatures // "stream" is assumed to be a pointer to a concrete object with the stream protocol ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len); ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len); off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence); int mp_stream_posix_fsync(void *stream); #endif #if MICROPY_STREAMS_NON_BLOCK #define mp_is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK) #else #define mp_is_nonblocking_error(errno) (0) #endif #endif // MICROPY_INCLUDED_PY_STREAM_H micropython-1.12/py/unicode.c000066400000000000000000000130351357706137100162460ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/unicode.h" // attribute flags #define FL_PRINT (0x01) #define FL_SPACE (0x02) #define FL_DIGIT (0x04) #define FL_ALPHA (0x08) #define FL_UPPER (0x10) #define FL_LOWER (0x20) #define FL_XDIGIT (0x40) // shorthand character attributes #define AT_PR (FL_PRINT) #define AT_SP (FL_SPACE | FL_PRINT) #define AT_DI (FL_DIGIT | FL_PRINT | FL_XDIGIT) #define AT_AL (FL_ALPHA | FL_PRINT) #define AT_UP (FL_UPPER | FL_ALPHA | FL_PRINT) #define AT_LO (FL_LOWER | FL_ALPHA | FL_PRINT) #define AT_UX (FL_UPPER | FL_ALPHA | FL_PRINT | FL_XDIGIT) #define AT_LX (FL_LOWER | FL_ALPHA | FL_PRINT | FL_XDIGIT) // table of attributes for ascii characters STATIC const uint8_t attr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, AT_SP, AT_SP, AT_SP, AT_SP, AT_SP, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AT_SP, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_DI, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_UX, AT_UX, AT_UX, AT_UX, AT_UX, AT_UX, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_UP, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_PR, AT_LX, AT_LX, AT_LX, AT_LX, AT_LX, AT_LX, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_LO, AT_PR, AT_PR, AT_PR, AT_PR, 0 }; #if MICROPY_PY_BUILTINS_STR_UNICODE unichar utf8_get_char(const byte *s) { unichar ord = *s++; if (!UTF8_IS_NONASCII(ord)) return ord; ord &= 0x7F; for (unichar mask = 0x40; ord & mask; mask >>= 1) { ord &= ~mask; } while (UTF8_IS_CONT(*s)) { ord = (ord << 6) | (*s++ & 0x3F); } return ord; } const byte *utf8_next_char(const byte *s) { ++s; while (UTF8_IS_CONT(*s)) { ++s; } return s; } mp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr) { mp_uint_t i = 0; while (ptr > s) { if (!UTF8_IS_CONT(*--ptr)) { i++; } } return i; } size_t utf8_charlen(const byte *str, size_t len) { size_t charlen = 0; for (const byte *top = str + len; str < top; ++str) { if (!UTF8_IS_CONT(*str)) { ++charlen; } } return charlen; } #endif // Be aware: These unichar_is* functions are actually ASCII-only! bool unichar_isspace(unichar c) { return c < 128 && (attr[c] & FL_SPACE) != 0; } bool unichar_isalpha(unichar c) { return c < 128 && (attr[c] & FL_ALPHA) != 0; } /* unused bool unichar_isprint(unichar c) { return c < 128 && (attr[c] & FL_PRINT) != 0; } */ bool unichar_isdigit(unichar c) { return c < 128 && (attr[c] & FL_DIGIT) != 0; } bool unichar_isxdigit(unichar c) { return c < 128 && (attr[c] & FL_XDIGIT) != 0; } bool unichar_isident(unichar c) { return c < 128 && ((attr[c] & (FL_ALPHA | FL_DIGIT)) != 0 || c == '_'); } bool unichar_isupper(unichar c) { return c < 128 && (attr[c] & FL_UPPER) != 0; } bool unichar_islower(unichar c) { return c < 128 && (attr[c] & FL_LOWER) != 0; } unichar unichar_tolower(unichar c) { if (unichar_isupper(c)) { return c + 0x20; } return c; } unichar unichar_toupper(unichar c) { if (unichar_islower(c)) { return c - 0x20; } return c; } mp_uint_t unichar_xdigit_value(unichar c) { // c is assumed to be hex digit mp_uint_t n = c - '0'; if (n > 9) { n &= ~('a' - 'A'); n -= ('A' - ('9' + 1)); } return n; } #if MICROPY_PY_BUILTINS_STR_UNICODE bool utf8_check(const byte *p, size_t len) { uint8_t need = 0; const byte *end = p + len; for (; p < end; p++) { byte c = *p; if (need) { if (UTF8_IS_CONT(c)) { need--; } else { // mismatch return 0; } } else { if (c >= 0xc0) { if (c >= 0xf8) { // mismatch return 0; } need = (0xe5 >> ((c >> 3) & 0x6)) & 3; } else if (c >= 0x80) { // mismatch return 0; } } } return need == 0; // no pending fragments allowed } #endif micropython-1.12/py/unicode.h000066400000000000000000000027271357706137100162610ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_PY_UNICODE_H #define MICROPY_INCLUDED_PY_UNICODE_H #include "py/mpconfig.h" #include "py/misc.h" mp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr); bool utf8_check(const byte *p, size_t len); #endif // MICROPY_INCLUDED_PY_UNICODE_H micropython-1.12/py/vm.c000066400000000000000000002003321357706137100152400ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2014-2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "py/emitglue.h" #include "py/objtype.h" #include "py/runtime.h" #include "py/bc0.h" #include "py/bc.h" #include "py/profile.h" #if 0 #define TRACE(ip) printf("sp=%d ", (int)(sp - &code_state->state[0] + 1)); mp_bytecode_print2(ip, 1, code_state->fun_bc->const_table); #else #define TRACE(ip) #endif // Value stack grows up (this makes it incompatible with native C stack, but // makes sure that arguments to functions are in natural order arg1..argN // (Python semantics mandates left-to-right evaluation order, including for // function arguments). Stack pointer is pre-incremented and points at the // top element. // Exception stack also grows up, top element is also pointed at. #define DECODE_UINT \ mp_uint_t unum = 0; \ do { \ unum = (unum << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0) #define DECODE_ULABEL size_t ulab = (ip[0] | (ip[1] << 8)); ip += 2 #define DECODE_SLABEL size_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2 #if MICROPY_PERSISTENT_CODE #define DECODE_QSTR \ qstr qst = ip[0] | ip[1] << 8; \ ip += 2; #define DECODE_PTR \ DECODE_UINT; \ void *ptr = (void*)(uintptr_t)code_state->fun_bc->const_table[unum] #define DECODE_OBJ \ DECODE_UINT; \ mp_obj_t obj = (mp_obj_t)code_state->fun_bc->const_table[unum] #else #define DECODE_QSTR qstr qst = 0; \ do { \ qst = (qst << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0) #define DECODE_PTR \ ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \ void *ptr = *(void**)ip; \ ip += sizeof(void*) #define DECODE_OBJ \ ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \ mp_obj_t obj = *(mp_obj_t*)ip; \ ip += sizeof(mp_obj_t) #endif #define PUSH(val) *++sp = (val) #define POP() (*sp--) #define TOP() (*sp) #define SET_TOP(val) *sp = (val) #if MICROPY_PY_SYS_EXC_INFO #define CLEAR_SYS_EXC_INFO() MP_STATE_VM(cur_exception) = NULL; #else #define CLEAR_SYS_EXC_INFO() #endif #define PUSH_EXC_BLOCK(with_or_finally) do { \ DECODE_ULABEL; /* except labels are always forward */ \ ++exc_sp; \ exc_sp->handler = ip + ulab; \ exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1)); \ exc_sp->prev_exc = NULL; \ } while (0) #define POP_EXC_BLOCK() \ exc_sp--; /* pop back to previous exception handler */ \ CLEAR_SYS_EXC_INFO() /* just clear sys.exc_info(), not compliant, but it shouldn't be used in 1st place */ #define CANCEL_ACTIVE_FINALLY(sp) do { \ if (mp_obj_is_small_int(sp[-1])) { \ /* Stack: (..., prev_dest_ip, prev_cause, dest_ip) */ \ /* Cancel the unwind through the previous finally, replace with current one */ \ sp[-2] = sp[0]; \ sp -= 2; \ } else { \ assert(sp[-1] == mp_const_none || mp_obj_is_exception_instance(sp[-1])); \ /* Stack: (..., None/exception, dest_ip) */ \ /* Silence the finally's exception value (may be None or an exception) */ \ sp[-1] = sp[0]; \ --sp; \ } \ } while (0) #if MICROPY_PY_SYS_SETTRACE #define FRAME_SETUP() do { \ assert(code_state != code_state->prev_state); \ MP_STATE_THREAD(current_code_state) = code_state; \ assert(code_state != code_state->prev_state); \ } while(0) #define FRAME_ENTER() do { \ assert(code_state != code_state->prev_state); \ code_state->prev_state = MP_STATE_THREAD(current_code_state); \ assert(code_state != code_state->prev_state); \ if (!mp_prof_is_executing) { \ mp_prof_frame_enter(code_state); \ } \ } while(0) #define FRAME_LEAVE() do { \ assert(code_state != code_state->prev_state); \ MP_STATE_THREAD(current_code_state) = code_state->prev_state; \ assert(code_state != code_state->prev_state); \ } while(0) #define FRAME_UPDATE() do { \ assert(MP_STATE_THREAD(current_code_state) == code_state); \ if (!mp_prof_is_executing) { \ code_state->frame = MP_OBJ_TO_PTR(mp_prof_frame_update(code_state)); \ } \ } while(0) #define TRACE_TICK(current_ip, current_sp, is_exception) do { \ assert(code_state != code_state->prev_state); \ assert(MP_STATE_THREAD(current_code_state) == code_state); \ if (!mp_prof_is_executing && code_state->frame && MP_STATE_THREAD(prof_trace_callback)) { \ MP_PROF_INSTR_DEBUG_PRINT(code_state->ip); \ } \ if (!mp_prof_is_executing && code_state->frame && code_state->frame->callback) { \ mp_prof_instr_tick(code_state, is_exception); \ } \ } while(0) #else // MICROPY_PY_SYS_SETTRACE #define FRAME_SETUP() #define FRAME_ENTER() #define FRAME_LEAVE() #define FRAME_UPDATE() #define TRACE_TICK(current_ip, current_sp, is_exception) #endif // MICROPY_PY_SYS_SETTRACE #if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE static inline mp_map_elem_t *mp_map_cached_lookup(mp_map_t *map, qstr qst, uint8_t *idx_cache) { size_t idx = *idx_cache; mp_obj_t key = MP_OBJ_NEW_QSTR(qst); mp_map_elem_t *elem = NULL; if (idx < map->alloc && map->table[idx].key == key) { elem = &map->table[idx]; } else { elem = mp_map_lookup(map, key, MP_MAP_LOOKUP); if (elem != NULL) { *idx_cache = (elem - &map->table[0]) & 0xff; } } return elem; } #endif // fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc) // sp points to bottom of stack which grows up // returns: // MP_VM_RETURN_NORMAL, sp valid, return value in *sp // MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp // MP_VM_RETURN_EXCEPTION, exception in state[0] mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) { #define SELECTIVE_EXC_IP (0) #if SELECTIVE_EXC_IP #define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */ #define MARK_EXC_IP_GLOBAL() #else #define MARK_EXC_IP_SELECTIVE() #define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */ #endif #if MICROPY_OPT_COMPUTED_GOTO #include "py/vmentrytable.h" #define DISPATCH() do { \ TRACE(ip); \ MARK_EXC_IP_GLOBAL(); \ TRACE_TICK(ip, sp, false); \ goto *entry_table[*ip++]; \ } while (0) #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check #define ENTRY(op) entry_##op #define ENTRY_DEFAULT entry_default #else #define DISPATCH() goto dispatch_loop #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check #define ENTRY(op) case op #define ENTRY_DEFAULT default #endif // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser // sees that it's possible for us to jump from the dispatch loop to the exception // handler. Without this, the code may have a different stack layout in the dispatch // loop and the exception handler, leading to very obscure bugs. #define RAISE(o) do { nlr_pop(); nlr.ret_val = MP_OBJ_TO_PTR(o); goto exception_handler; } while (0) #if MICROPY_STACKLESS run_code_state: ; #endif FRAME_ENTER(); #if MICROPY_STACKLESS run_code_state_from_return: ; #endif FRAME_SETUP(); // Pointers which are constant for particular invocation of mp_execute_bytecode() mp_obj_t * /*const*/ fastn; mp_exc_stack_t * /*const*/ exc_stack; { size_t n_state = code_state->n_state; fastn = &code_state->state[n_state - 1]; exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); } // variables that are visible to the exception handler (declared volatile) mp_exc_stack_t *volatile exc_sp = MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, code_state->exc_sp_idx); // stack grows up, exc_sp points to top of stack #if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR // This needs to be volatile and outside the VM loop so it persists across handling // of any exceptions. Otherwise it's possible that the VM never gives up the GIL. volatile int gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR; #endif // outer exception handling loop for (;;) { nlr_buf_t nlr; outer_dispatch_loop: if (nlr_push(&nlr) == 0) { // local variables that are not visible to the exception handler const byte *ip = code_state->ip; mp_obj_t *sp = code_state->sp; mp_obj_t obj_shared; MICROPY_VM_HOOK_INIT // If we have exception to inject, now that we finish setting up // execution context, raise it. This works as if MP_BC_RAISE_OBJ // bytecode was executed. // Injecting exc into yield from generator is a special case, // handled by MP_BC_YIELD_FROM itself if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) { mp_obj_t exc = inject_exc; inject_exc = MP_OBJ_NULL; exc = mp_make_raise_obj(exc); RAISE(exc); } // loop to execute byte code for (;;) { dispatch_loop: #if MICROPY_OPT_COMPUTED_GOTO DISPATCH(); #else TRACE(ip); MARK_EXC_IP_GLOBAL(); TRACE_TICK(ip, sp, false); switch (*ip++) { #endif ENTRY(MP_BC_LOAD_CONST_FALSE): PUSH(mp_const_false); DISPATCH(); ENTRY(MP_BC_LOAD_CONST_NONE): PUSH(mp_const_none); DISPATCH(); ENTRY(MP_BC_LOAD_CONST_TRUE): PUSH(mp_const_true); DISPATCH(); ENTRY(MP_BC_LOAD_CONST_SMALL_INT): { mp_int_t num = 0; if ((ip[0] & 0x40) != 0) { // Number is negative num--; } do { num = (num << 7) | (*ip & 0x7f); } while ((*ip++ & 0x80) != 0); PUSH(MP_OBJ_NEW_SMALL_INT(num)); DISPATCH(); } ENTRY(MP_BC_LOAD_CONST_STRING): { DECODE_QSTR; PUSH(MP_OBJ_NEW_QSTR(qst)); DISPATCH(); } ENTRY(MP_BC_LOAD_CONST_OBJ): { DECODE_OBJ; PUSH(obj); DISPATCH(); } ENTRY(MP_BC_LOAD_NULL): PUSH(MP_OBJ_NULL); DISPATCH(); ENTRY(MP_BC_LOAD_FAST_N): { DECODE_UINT; obj_shared = fastn[-unum]; load_check: if (obj_shared == MP_OBJ_NULL) { local_name_error: { MARK_EXC_IP_SELECTIVE(); mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment"); RAISE(obj); } } PUSH(obj_shared); DISPATCH(); } ENTRY(MP_BC_LOAD_DEREF): { DECODE_UINT; obj_shared = mp_obj_cell_get(fastn[-unum]); goto load_check; } #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE ENTRY(MP_BC_LOAD_NAME): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; PUSH(mp_load_name(qst)); DISPATCH(); } #else ENTRY(MP_BC_LOAD_NAME): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_map_elem_t *elem = mp_map_cached_lookup(&mp_locals_get()->map, qst, (uint8_t*)ip); mp_obj_t obj; if (elem != NULL) { obj = elem->value; } else { obj = mp_load_name(qst); } PUSH(obj); ip++; DISPATCH(); } #endif #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE ENTRY(MP_BC_LOAD_GLOBAL): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; PUSH(mp_load_global(qst)); DISPATCH(); } #else ENTRY(MP_BC_LOAD_GLOBAL): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_map_elem_t *elem = mp_map_cached_lookup(&mp_globals_get()->map, qst, (uint8_t*)ip); mp_obj_t obj; if (elem != NULL) { obj = elem->value; } else { obj = mp_load_global(qst); } PUSH(obj); ip++; DISPATCH(); } #endif #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE ENTRY(MP_BC_LOAD_ATTR): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; SET_TOP(mp_load_attr(TOP(), qst)); DISPATCH(); } #else ENTRY(MP_BC_LOAD_ATTR): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_obj_t top = TOP(); mp_map_elem_t *elem = NULL; if (mp_obj_is_instance_type(mp_obj_get_type(top))) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(top); elem = mp_map_cached_lookup(&self->members, qst, (uint8_t*)ip); } mp_obj_t obj; if (elem != NULL) { obj = elem->value; } else { obj = mp_load_attr(top, qst); } SET_TOP(obj); ip++; DISPATCH(); } #endif ENTRY(MP_BC_LOAD_METHOD): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_load_method(*sp, qst, sp); sp += 1; DISPATCH(); } ENTRY(MP_BC_LOAD_SUPER_METHOD): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; sp -= 1; mp_load_super_method(qst, sp - 1); DISPATCH(); } ENTRY(MP_BC_LOAD_BUILD_CLASS): MARK_EXC_IP_SELECTIVE(); PUSH(mp_load_build_class()); DISPATCH(); ENTRY(MP_BC_LOAD_SUBSCR): { MARK_EXC_IP_SELECTIVE(); mp_obj_t index = POP(); SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL)); DISPATCH(); } ENTRY(MP_BC_STORE_FAST_N): { DECODE_UINT; fastn[-unum] = POP(); DISPATCH(); } ENTRY(MP_BC_STORE_DEREF): { DECODE_UINT; mp_obj_cell_set(fastn[-unum], POP()); DISPATCH(); } ENTRY(MP_BC_STORE_NAME): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_store_name(qst, POP()); DISPATCH(); } ENTRY(MP_BC_STORE_GLOBAL): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_store_global(qst, POP()); DISPATCH(); } #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE ENTRY(MP_BC_STORE_ATTR): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_store_attr(sp[0], qst, sp[-1]); sp -= 2; DISPATCH(); } #else // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in // self->members then it can't be a property or have descriptors. A // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND // in the fast-path below, because that store could override a property. ENTRY(MP_BC_STORE_ATTR): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_map_elem_t *elem = NULL; mp_obj_t top = TOP(); if (mp_obj_is_instance_type(mp_obj_get_type(top)) && sp[-1] != MP_OBJ_NULL) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(top); elem = mp_map_cached_lookup(&self->members, qst, (uint8_t*)ip); } if (elem != NULL) { elem->value = sp[-1]; } else { mp_store_attr(sp[0], qst, sp[-1]); } sp -= 2; ip++; DISPATCH(); } #endif ENTRY(MP_BC_STORE_SUBSCR): MARK_EXC_IP_SELECTIVE(); mp_obj_subscr(sp[-1], sp[0], sp[-2]); sp -= 3; DISPATCH(); ENTRY(MP_BC_DELETE_FAST): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; if (fastn[-unum] == MP_OBJ_NULL) { goto local_name_error; } fastn[-unum] = MP_OBJ_NULL; DISPATCH(); } ENTRY(MP_BC_DELETE_DEREF): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) { goto local_name_error; } mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL); DISPATCH(); } ENTRY(MP_BC_DELETE_NAME): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_delete_name(qst); DISPATCH(); } ENTRY(MP_BC_DELETE_GLOBAL): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_delete_global(qst); DISPATCH(); } ENTRY(MP_BC_DUP_TOP): { mp_obj_t top = TOP(); PUSH(top); DISPATCH(); } ENTRY(MP_BC_DUP_TOP_TWO): sp += 2; sp[0] = sp[-2]; sp[-1] = sp[-3]; DISPATCH(); ENTRY(MP_BC_POP_TOP): sp -= 1; DISPATCH(); ENTRY(MP_BC_ROT_TWO): { mp_obj_t top = sp[0]; sp[0] = sp[-1]; sp[-1] = top; DISPATCH(); } ENTRY(MP_BC_ROT_THREE): { mp_obj_t top = sp[0]; sp[0] = sp[-1]; sp[-1] = sp[-2]; sp[-2] = top; DISPATCH(); } ENTRY(MP_BC_JUMP): { DECODE_SLABEL; ip += slab; DISPATCH_WITH_PEND_EXC_CHECK(); } ENTRY(MP_BC_POP_JUMP_IF_TRUE): { DECODE_SLABEL; if (mp_obj_is_true(POP())) { ip += slab; } DISPATCH_WITH_PEND_EXC_CHECK(); } ENTRY(MP_BC_POP_JUMP_IF_FALSE): { DECODE_SLABEL; if (!mp_obj_is_true(POP())) { ip += slab; } DISPATCH_WITH_PEND_EXC_CHECK(); } ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): { DECODE_SLABEL; if (mp_obj_is_true(TOP())) { ip += slab; } else { sp--; } DISPATCH_WITH_PEND_EXC_CHECK(); } ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): { DECODE_SLABEL; if (mp_obj_is_true(TOP())) { sp--; } else { ip += slab; } DISPATCH_WITH_PEND_EXC_CHECK(); } ENTRY(MP_BC_SETUP_WITH): { MARK_EXC_IP_SELECTIVE(); // stack: (..., ctx_mgr) mp_obj_t obj = TOP(); mp_load_method(obj, MP_QSTR___exit__, sp); mp_load_method(obj, MP_QSTR___enter__, sp + 2); mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2); sp += 1; PUSH_EXC_BLOCK(1); PUSH(ret); // stack: (..., __exit__, ctx_mgr, as_value) DISPATCH(); } ENTRY(MP_BC_WITH_CLEANUP): { MARK_EXC_IP_SELECTIVE(); // Arriving here, there's "exception control block" on top of stack, // and __exit__ method (with self) underneath it. Bytecode calls __exit__, // and "deletes" it off stack, shifting "exception control block" // to its place. // The bytecode emitter ensures that there is enough space on the Python // value stack to hold the __exit__ method plus an additional 4 entries. if (TOP() == mp_const_none) { // stack: (..., __exit__, ctx_mgr, None) sp[1] = mp_const_none; sp[2] = mp_const_none; sp -= 2; mp_call_method_n_kw(3, 0, sp); SET_TOP(mp_const_none); } else if (mp_obj_is_small_int(TOP())) { // Getting here there are two distinct cases: // - unwind return, stack: (..., __exit__, ctx_mgr, ret_val, SMALL_INT(-1)) // - unwind jump, stack: (..., __exit__, ctx_mgr, dest_ip, SMALL_INT(num_exc)) // For both cases we do exactly the same thing. mp_obj_t data = sp[-1]; mp_obj_t cause = sp[0]; sp[-1] = mp_const_none; sp[0] = mp_const_none; sp[1] = mp_const_none; mp_call_method_n_kw(3, 0, sp - 3); sp[-3] = data; sp[-2] = cause; sp -= 2; // we removed (__exit__, ctx_mgr) } else { assert(mp_obj_is_exception_instance(TOP())); // stack: (..., __exit__, ctx_mgr, exc_instance) // Need to pass (exc_type, exc_instance, None) as arguments to __exit__. sp[1] = sp[0]; sp[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(sp[0])); sp[2] = mp_const_none; sp -= 2; mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp); if (mp_obj_is_true(ret_value)) { // We need to silence/swallow the exception. This is done // by popping the exception and the __exit__ handler and // replacing it with None, which signals END_FINALLY to just // execute the finally handler normally. SET_TOP(mp_const_none); } else { // We need to re-raise the exception. We pop __exit__ handler // by copying the exception instance down to the new top-of-stack. sp[0] = sp[3]; } } DISPATCH(); } ENTRY(MP_BC_UNWIND_JUMP): { MARK_EXC_IP_SELECTIVE(); DECODE_SLABEL; PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump PUSH((mp_obj_t)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack) unwind_jump:; mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind while ((unum & 0x7f) > 0) { unum -= 1; assert(exc_sp >= exc_stack); if (MP_TAGPTR_TAG1(exc_sp->val_sp)) { if (exc_sp->handler > ip) { // Found a finally handler that isn't active; run it. // Getting here the stack looks like: // (..., X, dest_ip) // where X is pointed to by exc_sp->val_sp and in the case // of a "with" block contains the context manager info. assert(&sp[-1] == MP_TAGPTR_PTR(exc_sp->val_sp)); // We're going to run "finally" code as a coroutine // (not calling it recursively). Set up a sentinel // on the stack so it can return back to us when it is // done (when WITH_CLEANUP or END_FINALLY reached). // The sentinel is the number of exception handlers left to // unwind, which is a non-negative integer. PUSH(MP_OBJ_NEW_SMALL_INT(unum)); ip = exc_sp->handler; goto dispatch_loop; } else { // Found a finally handler that is already active; cancel it. CANCEL_ACTIVE_FINALLY(sp); } } POP_EXC_BLOCK(); } ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump if (unum != 0) { // pop the exhausted iterator sp -= MP_OBJ_ITER_BUF_NSLOTS; } DISPATCH_WITH_PEND_EXC_CHECK(); } ENTRY(MP_BC_SETUP_EXCEPT): ENTRY(MP_BC_SETUP_FINALLY): { MARK_EXC_IP_SELECTIVE(); #if SELECTIVE_EXC_IP PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0); #else PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0); #endif DISPATCH(); } ENTRY(MP_BC_END_FINALLY): MARK_EXC_IP_SELECTIVE(); // if TOS is None, just pops it and continues // if TOS is an integer, finishes coroutine and returns control to caller // if TOS is an exception, reraises the exception assert(exc_sp >= exc_stack); POP_EXC_BLOCK(); if (TOP() == mp_const_none) { sp--; } else if (mp_obj_is_small_int(TOP())) { // We finished "finally" coroutine and now dispatch back // to our caller, based on TOS value mp_int_t cause = MP_OBJ_SMALL_INT_VALUE(POP()); if (cause < 0) { // A negative cause indicates unwind return goto unwind_return; } else { // Otherwise it's an unwind jump and we must push as a raw // number the number of exception handlers to unwind PUSH((mp_obj_t)cause); goto unwind_jump; } } else { assert(mp_obj_is_exception_instance(TOP())); RAISE(TOP()); } DISPATCH(); ENTRY(MP_BC_GET_ITER): MARK_EXC_IP_SELECTIVE(); SET_TOP(mp_getiter(TOP(), NULL)); DISPATCH(); // An iterator for a for-loop takes MP_OBJ_ITER_BUF_NSLOTS slots on // the Python value stack. These slots are either used to store the // iterator object itself, or the first slot is MP_OBJ_NULL and // the second slot holds a reference to the iterator object. ENTRY(MP_BC_GET_ITER_STACK): { MARK_EXC_IP_SELECTIVE(); mp_obj_t obj = TOP(); mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp; sp += MP_OBJ_ITER_BUF_NSLOTS - 1; obj = mp_getiter(obj, iter_buf); if (obj != MP_OBJ_FROM_PTR(iter_buf)) { // Iterator didn't use the stack so indicate that with MP_OBJ_NULL. sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] = MP_OBJ_NULL; sp[-MP_OBJ_ITER_BUF_NSLOTS + 2] = obj; } DISPATCH(); } ENTRY(MP_BC_FOR_ITER): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward code_state->sp = sp; mp_obj_t obj; if (sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] == MP_OBJ_NULL) { obj = sp[-MP_OBJ_ITER_BUF_NSLOTS + 2]; } else { obj = MP_OBJ_FROM_PTR(&sp[-MP_OBJ_ITER_BUF_NSLOTS + 1]); } mp_obj_t value = mp_iternext_allow_raise(obj); if (value == MP_OBJ_STOP_ITERATION) { sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator ip += ulab; // jump to after for-block } else { PUSH(value); // push the next iteration value #if MICROPY_PY_SYS_SETTRACE // LINE event should trigger for every iteration so invalidate last trigger if (code_state->frame) { code_state->frame->lineno = 0; } #endif } DISPATCH(); } ENTRY(MP_BC_POP_EXCEPT_JUMP): { assert(exc_sp >= exc_stack); POP_EXC_BLOCK(); DECODE_ULABEL; ip += ulab; DISPATCH_WITH_PEND_EXC_CHECK(); } ENTRY(MP_BC_BUILD_TUPLE): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; sp -= unum - 1; SET_TOP(mp_obj_new_tuple(unum, sp)); DISPATCH(); } ENTRY(MP_BC_BUILD_LIST): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; sp -= unum - 1; SET_TOP(mp_obj_new_list(unum, sp)); DISPATCH(); } ENTRY(MP_BC_BUILD_MAP): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; PUSH(mp_obj_new_dict(unum)); DISPATCH(); } ENTRY(MP_BC_STORE_MAP): MARK_EXC_IP_SELECTIVE(); sp -= 2; mp_obj_dict_store(sp[0], sp[2], sp[1]); DISPATCH(); #if MICROPY_PY_BUILTINS_SET ENTRY(MP_BC_BUILD_SET): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; sp -= unum - 1; SET_TOP(mp_obj_new_set(unum, sp)); DISPATCH(); } #endif #if MICROPY_PY_BUILTINS_SLICE ENTRY(MP_BC_BUILD_SLICE): { MARK_EXC_IP_SELECTIVE(); mp_obj_t step = mp_const_none; if (*ip++ == 3) { // 3-argument slice includes step step = POP(); } mp_obj_t stop = POP(); mp_obj_t start = TOP(); SET_TOP(mp_obj_new_slice(start, stop, step)); DISPATCH(); } #endif ENTRY(MP_BC_STORE_COMP): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; mp_obj_t obj = sp[-(unum >> 2)]; if ((unum & 3) == 0) { mp_obj_list_append(obj, sp[0]); sp--; } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) { mp_obj_dict_store(obj, sp[0], sp[-1]); sp -= 2; #if MICROPY_PY_BUILTINS_SET } else { mp_obj_set_store(obj, sp[0]); sp--; #endif } DISPATCH(); } ENTRY(MP_BC_UNPACK_SEQUENCE): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; mp_unpack_sequence(sp[0], unum, sp); sp += unum - 1; DISPATCH(); } ENTRY(MP_BC_UNPACK_EX): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; mp_unpack_ex(sp[0], unum, sp); sp += (unum & 0xff) + ((unum >> 8) & 0xff); DISPATCH(); } ENTRY(MP_BC_MAKE_FUNCTION): { DECODE_PTR; PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL)); DISPATCH(); } ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): { DECODE_PTR; // Stack layout: def_tuple def_dict <- TOS mp_obj_t def_dict = POP(); SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict)); DISPATCH(); } ENTRY(MP_BC_MAKE_CLOSURE): { DECODE_PTR; size_t n_closed_over = *ip++; // Stack layout: closed_overs <- TOS sp -= n_closed_over - 1; SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp)); DISPATCH(); } ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): { DECODE_PTR; size_t n_closed_over = *ip++; // Stack layout: def_tuple def_dict closed_overs <- TOS sp -= 2 + n_closed_over - 1; SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp)); DISPATCH(); } ENTRY(MP_BC_CALL_FUNCTION): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_UINT; // unum & 0xff == n_positional // (unum >> 8) & 0xff == n_keyword sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe); #if MICROPY_STACKLESS if (mp_obj_get_type(*sp) == &mp_type_fun_bc) { code_state->ip = ip; code_state->sp = sp; code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1); #if !MICROPY_ENABLE_PYSTACK if (new_state == NULL) { // Couldn't allocate codestate on heap: in the strict case raise // an exception, otherwise just fall through to stack allocation. #if MICROPY_STACKLESS_STRICT deep_recursion_error: mp_raise_recursion_depth(); #endif } else #endif { new_state->prev = code_state; code_state = new_state; nlr_pop(); goto run_code_state; } } #endif SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1)); DISPATCH(); } ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_UINT; // unum & 0xff == n_positional // (unum >> 8) & 0xff == n_keyword // We have following stack layout here: // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2; #if MICROPY_STACKLESS if (mp_obj_get_type(*sp) == &mp_type_fun_bc) { code_state->ip = ip; code_state->sp = sp; code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); mp_call_args_t out_args; mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args); mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args); #if !MICROPY_ENABLE_PYSTACK // Freeing args at this point does not follow a LIFO order so only do it if // pystack is not enabled. For pystack, they are freed when code_state is. mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t)); #endif #if !MICROPY_ENABLE_PYSTACK if (new_state == NULL) { // Couldn't allocate codestate on heap: in the strict case raise // an exception, otherwise just fall through to stack allocation. #if MICROPY_STACKLESS_STRICT goto deep_recursion_error; #endif } else #endif { new_state->prev = code_state; code_state = new_state; nlr_pop(); goto run_code_state; } } #endif SET_TOP(mp_call_method_n_kw_var(false, unum, sp)); DISPATCH(); } ENTRY(MP_BC_CALL_METHOD): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_UINT; // unum & 0xff == n_positional // (unum >> 8) & 0xff == n_keyword sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1; #if MICROPY_STACKLESS if (mp_obj_get_type(*sp) == &mp_type_fun_bc) { code_state->ip = ip; code_state->sp = sp; code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); size_t n_args = unum & 0xff; size_t n_kw = (unum >> 8) & 0xff; int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1; mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust); #if !MICROPY_ENABLE_PYSTACK if (new_state == NULL) { // Couldn't allocate codestate on heap: in the strict case raise // an exception, otherwise just fall through to stack allocation. #if MICROPY_STACKLESS_STRICT goto deep_recursion_error; #endif } else #endif { new_state->prev = code_state; code_state = new_state; nlr_pop(); goto run_code_state; } } #endif SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp)); DISPATCH(); } ENTRY(MP_BC_CALL_METHOD_VAR_KW): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_UINT; // unum & 0xff == n_positional // (unum >> 8) & 0xff == n_keyword // We have following stack layout here: // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3; #if MICROPY_STACKLESS if (mp_obj_get_type(*sp) == &mp_type_fun_bc) { code_state->ip = ip; code_state->sp = sp; code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); mp_call_args_t out_args; mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args); mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args); #if !MICROPY_ENABLE_PYSTACK // Freeing args at this point does not follow a LIFO order so only do it if // pystack is not enabled. For pystack, they are freed when code_state is. mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t)); #endif #if !MICROPY_ENABLE_PYSTACK if (new_state == NULL) { // Couldn't allocate codestate on heap: in the strict case raise // an exception, otherwise just fall through to stack allocation. #if MICROPY_STACKLESS_STRICT goto deep_recursion_error; #endif } else #endif { new_state->prev = code_state; code_state = new_state; nlr_pop(); goto run_code_state; } } #endif SET_TOP(mp_call_method_n_kw_var(true, unum, sp)); DISPATCH(); } ENTRY(MP_BC_RETURN_VALUE): MARK_EXC_IP_SELECTIVE(); unwind_return: // Search for and execute finally handlers that aren't already active while (exc_sp >= exc_stack) { if (MP_TAGPTR_TAG1(exc_sp->val_sp)) { if (exc_sp->handler > ip) { // Found a finally handler that isn't active; run it. // Getting here the stack looks like: // (..., X, [iter0, iter1, ...,] ret_val) // where X is pointed to by exc_sp->val_sp and in the case // of a "with" block contains the context manager info. // There may be 0 or more for-iterators between X and the // return value, and these must be removed before control can // pass to the finally code. We simply copy the ret_value down // over these iterators, if they exist. If they don't then the // following is a null operation. mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp); finally_sp[1] = sp[0]; sp = &finally_sp[1]; // We're going to run "finally" code as a coroutine // (not calling it recursively). Set up a sentinel // on a stack so it can return back to us when it is // done (when WITH_CLEANUP or END_FINALLY reached). PUSH(MP_OBJ_NEW_SMALL_INT(-1)); ip = exc_sp->handler; goto dispatch_loop; } else { // Found a finally handler that is already active; cancel it. CANCEL_ACTIVE_FINALLY(sp); } } POP_EXC_BLOCK(); } nlr_pop(); code_state->sp = sp; assert(exc_sp == exc_stack - 1); MICROPY_VM_HOOK_RETURN #if MICROPY_STACKLESS if (code_state->prev != NULL) { mp_obj_t res = *sp; mp_globals_set(code_state->old_globals); mp_code_state_t *new_code_state = code_state->prev; #if MICROPY_ENABLE_PYSTACK // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var // (The latter is implicitly freed when using pystack due to its LIFO nature.) // The sizeof in the following statement does not include the size of the variable // part of the struct. This arg is anyway not used if pystack is enabled. mp_nonlocal_free(code_state, sizeof(mp_code_state_t)); #endif code_state = new_code_state; *code_state->sp = res; goto run_code_state_from_return; } #endif FRAME_LEAVE(); return MP_VM_RETURN_NORMAL; ENTRY(MP_BC_RAISE_LAST): { MARK_EXC_IP_SELECTIVE(); // search for the inner-most previous exception, to reraise it mp_obj_t obj = MP_OBJ_NULL; for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; --e) { if (e->prev_exc != NULL) { obj = MP_OBJ_FROM_PTR(e->prev_exc); break; } } if (obj == MP_OBJ_NULL) { obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "no active exception to reraise"); } RAISE(obj); } ENTRY(MP_BC_RAISE_OBJ): { MARK_EXC_IP_SELECTIVE(); mp_obj_t obj = mp_make_raise_obj(TOP()); RAISE(obj); } ENTRY(MP_BC_RAISE_FROM): { MARK_EXC_IP_SELECTIVE(); mp_warning(NULL, "exception chaining not supported"); sp--; // ignore (pop) "from" argument mp_obj_t obj = mp_make_raise_obj(TOP()); RAISE(obj); } ENTRY(MP_BC_YIELD_VALUE): yield: nlr_pop(); code_state->ip = ip; code_state->sp = sp; code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); FRAME_LEAVE(); return MP_VM_RETURN_YIELD; ENTRY(MP_BC_YIELD_FROM): { MARK_EXC_IP_SELECTIVE(); //#define EXC_MATCH(exc, type) mp_obj_is_type(exc, type) #define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type) #define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { mp_obj_t raise_t = mp_make_raise_obj(t); RAISE(raise_t); } mp_vm_return_kind_t ret_kind; mp_obj_t send_value = POP(); mp_obj_t t_exc = MP_OBJ_NULL; mp_obj_t ret_value; code_state->sp = sp; // Save sp because it's needed if mp_resume raises StopIteration if (inject_exc != MP_OBJ_NULL) { t_exc = inject_exc; inject_exc = MP_OBJ_NULL; ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value); } else { ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value); } if (ret_kind == MP_VM_RETURN_YIELD) { ip--; PUSH(ret_value); goto yield; } else if (ret_kind == MP_VM_RETURN_NORMAL) { // Pop exhausted gen sp--; if (ret_value == MP_OBJ_STOP_ITERATION) { // Optimize StopIteration // TODO: get StopIteration's value PUSH(mp_const_none); } else { PUSH(ret_value); } // If we injected GeneratorExit downstream, then even // if it was swallowed, we re-raise GeneratorExit GENERATOR_EXIT_IF_NEEDED(t_exc); DISPATCH(); } else { assert(ret_kind == MP_VM_RETURN_EXCEPTION); assert(!EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))); // Pop exhausted gen sp--; RAISE(ret_value); } } ENTRY(MP_BC_IMPORT_NAME): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_obj_t obj = POP(); SET_TOP(mp_import_name(qst, obj, TOP())); DISPATCH(); } ENTRY(MP_BC_IMPORT_FROM): { FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_obj_t obj = mp_import_from(TOP(), qst); PUSH(obj); DISPATCH(); } ENTRY(MP_BC_IMPORT_STAR): MARK_EXC_IP_SELECTIVE(); mp_import_all(POP()); DISPATCH(); #if MICROPY_OPT_COMPUTED_GOTO ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI): PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS)); DISPATCH(); ENTRY(MP_BC_LOAD_FAST_MULTI): obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]]; goto load_check; ENTRY(MP_BC_STORE_FAST_MULTI): fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP(); DISPATCH(); ENTRY(MP_BC_UNARY_OP_MULTI): MARK_EXC_IP_SELECTIVE(); SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP())); DISPATCH(); ENTRY(MP_BC_BINARY_OP_MULTI): { MARK_EXC_IP_SELECTIVE(); mp_obj_t rhs = POP(); mp_obj_t lhs = TOP(); SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs)); DISPATCH(); } ENTRY_DEFAULT: MARK_EXC_IP_SELECTIVE(); #else ENTRY_DEFAULT: if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM) { PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS)); DISPATCH(); } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + MP_BC_LOAD_FAST_MULTI_NUM) { obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]]; goto load_check; } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + MP_BC_STORE_FAST_MULTI_NUM) { fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP(); DISPATCH(); } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_BC_UNARY_OP_MULTI_NUM) { SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP())); DISPATCH(); } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BC_BINARY_OP_MULTI_NUM) { mp_obj_t rhs = POP(); mp_obj_t lhs = TOP(); SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs)); DISPATCH(); } else #endif { mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "opcode"); nlr_pop(); code_state->state[0] = obj; FRAME_LEAVE(); return MP_VM_RETURN_EXCEPTION; } #if !MICROPY_OPT_COMPUTED_GOTO } // switch #endif pending_exception_check: MICROPY_VM_HOOK_LOOP #if MICROPY_ENABLE_SCHEDULER // This is an inlined variant of mp_handle_pending if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { MARK_EXC_IP_SELECTIVE(); mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_obj_t obj = MP_STATE_VM(mp_pending_exception); if (obj != MP_OBJ_NULL) { MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; if (!mp_sched_num_pending()) { MP_STATE_VM(sched_state) = MP_SCHED_IDLE; } MICROPY_END_ATOMIC_SECTION(atomic_state); RAISE(obj); } mp_handle_pending_tail(atomic_state); } #else // This is an inlined variant of mp_handle_pending if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { MARK_EXC_IP_SELECTIVE(); mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; RAISE(obj); } #endif #if MICROPY_PY_THREAD_GIL #if MICROPY_PY_THREAD_GIL_VM_DIVISOR if (--gil_divisor == 0) #endif { #if MICROPY_PY_THREAD_GIL_VM_DIVISOR gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR; #endif #if MICROPY_ENABLE_SCHEDULER // can only switch threads if the scheduler is unlocked if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) #endif { MP_THREAD_GIL_EXIT(); MP_THREAD_GIL_ENTER(); } } #endif } // for loop } else { exception_handler: // exception occurred #if MICROPY_PY_SYS_EXC_INFO MP_STATE_VM(cur_exception) = nlr.ret_val; #endif #if SELECTIVE_EXC_IP // with selective ip, we store the ip 1 byte past the opcode, so move ptr back code_state->ip -= 1; #endif if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { if (code_state->ip) { // check if it's a StopIteration within a for block if (*code_state->ip == MP_BC_FOR_ITER) { const byte *ip = code_state->ip + 1; DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward code_state->ip = ip + ulab; // jump to after for-block code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator goto outer_dispatch_loop; // continue with dispatch loop } else if (*code_state->ip == MP_BC_YIELD_FROM) { // StopIteration inside yield from call means return a value of // yield from, so inject exception's value as yield from's result // (Instead of stack pop then push we just replace exhausted gen with value) *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); code_state->ip++; // yield from is over, move to next instruction goto outer_dispatch_loop; // continue with dispatch loop } } } #if MICROPY_PY_SYS_SETTRACE // Exceptions are traced here if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_Exception))) { TRACE_TICK(code_state->ip, code_state->sp, true /* yes, it's an exception */); } #endif #if MICROPY_STACKLESS unwind_loop: #endif // Set traceback info (file and line number) where the exception occurred, but not for: // - constant GeneratorExit object, because it's const // - exceptions re-raised by END_FINALLY // - exceptions re-raised explicitly by "raise" if (nlr.ret_val != &mp_const_GeneratorExit_obj && *code_state->ip != MP_BC_END_FINALLY && *code_state->ip != MP_BC_RAISE_LAST) { const byte *ip = code_state->fun_bc->bytecode; MP_BC_PRELUDE_SIG_DECODE(ip); MP_BC_PRELUDE_SIZE_DECODE(ip); const byte *bytecode_start = ip + n_info + n_cell; #if !MICROPY_PERSISTENT_CODE // so bytecode is aligned bytecode_start = MP_ALIGN(bytecode_start, sizeof(mp_uint_t)); #endif size_t bc = code_state->ip - bytecode_start; #if MICROPY_PERSISTENT_CODE qstr block_name = ip[0] | (ip[1] << 8); qstr source_file = ip[2] | (ip[3] << 8); ip += 4; #else qstr block_name = mp_decode_uint_value(ip); ip = mp_decode_uint_skip(ip); qstr source_file = mp_decode_uint_value(ip); ip = mp_decode_uint_skip(ip); #endif size_t source_line = mp_bytecode_get_source_line(ip, bc); mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name); } while (exc_sp >= exc_stack && exc_sp->handler <= code_state->ip) { // nested exception assert(exc_sp >= exc_stack); // TODO make a proper message for nested exception // at the moment we are just raising the very last exception (the one that caused the nested exception) // move up to previous exception handler POP_EXC_BLOCK(); } if (exc_sp >= exc_stack) { // catch exception and pass to byte code code_state->ip = exc_sp->handler; mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp); // save this exception in the stack so it can be used in a reraise, if needed exc_sp->prev_exc = nlr.ret_val; // push exception object so it can be handled by bytecode PUSH(MP_OBJ_FROM_PTR(nlr.ret_val)); code_state->sp = sp; #if MICROPY_STACKLESS } else if (code_state->prev != NULL) { mp_globals_set(code_state->old_globals); mp_code_state_t *new_code_state = code_state->prev; #if MICROPY_ENABLE_PYSTACK // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var // (The latter is implicitly freed when using pystack due to its LIFO nature.) // The sizeof in the following statement does not include the size of the variable // part of the struct. This arg is anyway not used if pystack is enabled. mp_nonlocal_free(code_state, sizeof(mp_code_state_t)); #endif code_state = new_code_state; size_t n_state = code_state->n_state; fastn = &code_state->state[n_state - 1]; exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); // variables that are visible to the exception handler (declared volatile) exc_sp = MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, code_state->exc_sp_idx); // stack grows up, exc_sp points to top of stack goto unwind_loop; #endif } else { // propagate exception to higher level // Note: ip and sp don't have usable values at this point code_state->state[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // put exception here because sp is invalid FRAME_LEAVE(); return MP_VM_RETURN_EXCEPTION; } } } } micropython-1.12/py/vmentrytable.h000066400000000000000000000140771357706137100173500ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #if __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winitializer-overrides" #endif // __clang__ static const void *const entry_table[256] = { [0 ... 255] = &&entry_default, [MP_BC_LOAD_CONST_FALSE] = &&entry_MP_BC_LOAD_CONST_FALSE, [MP_BC_LOAD_CONST_NONE] = &&entry_MP_BC_LOAD_CONST_NONE, [MP_BC_LOAD_CONST_TRUE] = &&entry_MP_BC_LOAD_CONST_TRUE, [MP_BC_LOAD_CONST_SMALL_INT] = &&entry_MP_BC_LOAD_CONST_SMALL_INT, [MP_BC_LOAD_CONST_STRING] = &&entry_MP_BC_LOAD_CONST_STRING, [MP_BC_LOAD_CONST_OBJ] = &&entry_MP_BC_LOAD_CONST_OBJ, [MP_BC_LOAD_NULL] = &&entry_MP_BC_LOAD_NULL, [MP_BC_LOAD_FAST_N] = &&entry_MP_BC_LOAD_FAST_N, [MP_BC_LOAD_DEREF] = &&entry_MP_BC_LOAD_DEREF, [MP_BC_LOAD_NAME] = &&entry_MP_BC_LOAD_NAME, [MP_BC_LOAD_GLOBAL] = &&entry_MP_BC_LOAD_GLOBAL, [MP_BC_LOAD_ATTR] = &&entry_MP_BC_LOAD_ATTR, [MP_BC_LOAD_METHOD] = &&entry_MP_BC_LOAD_METHOD, [MP_BC_LOAD_SUPER_METHOD] = &&entry_MP_BC_LOAD_SUPER_METHOD, [MP_BC_LOAD_BUILD_CLASS] = &&entry_MP_BC_LOAD_BUILD_CLASS, [MP_BC_LOAD_SUBSCR] = &&entry_MP_BC_LOAD_SUBSCR, [MP_BC_STORE_FAST_N] = &&entry_MP_BC_STORE_FAST_N, [MP_BC_STORE_DEREF] = &&entry_MP_BC_STORE_DEREF, [MP_BC_STORE_NAME] = &&entry_MP_BC_STORE_NAME, [MP_BC_STORE_GLOBAL] = &&entry_MP_BC_STORE_GLOBAL, [MP_BC_STORE_ATTR] = &&entry_MP_BC_STORE_ATTR, [MP_BC_STORE_SUBSCR] = &&entry_MP_BC_STORE_SUBSCR, [MP_BC_DELETE_FAST] = &&entry_MP_BC_DELETE_FAST, [MP_BC_DELETE_DEREF] = &&entry_MP_BC_DELETE_DEREF, [MP_BC_DELETE_NAME] = &&entry_MP_BC_DELETE_NAME, [MP_BC_DELETE_GLOBAL] = &&entry_MP_BC_DELETE_GLOBAL, [MP_BC_DUP_TOP] = &&entry_MP_BC_DUP_TOP, [MP_BC_DUP_TOP_TWO] = &&entry_MP_BC_DUP_TOP_TWO, [MP_BC_POP_TOP] = &&entry_MP_BC_POP_TOP, [MP_BC_ROT_TWO] = &&entry_MP_BC_ROT_TWO, [MP_BC_ROT_THREE] = &&entry_MP_BC_ROT_THREE, [MP_BC_JUMP] = &&entry_MP_BC_JUMP, [MP_BC_POP_JUMP_IF_TRUE] = &&entry_MP_BC_POP_JUMP_IF_TRUE, [MP_BC_POP_JUMP_IF_FALSE] = &&entry_MP_BC_POP_JUMP_IF_FALSE, [MP_BC_JUMP_IF_TRUE_OR_POP] = &&entry_MP_BC_JUMP_IF_TRUE_OR_POP, [MP_BC_JUMP_IF_FALSE_OR_POP] = &&entry_MP_BC_JUMP_IF_FALSE_OR_POP, [MP_BC_SETUP_WITH] = &&entry_MP_BC_SETUP_WITH, [MP_BC_WITH_CLEANUP] = &&entry_MP_BC_WITH_CLEANUP, [MP_BC_UNWIND_JUMP] = &&entry_MP_BC_UNWIND_JUMP, [MP_BC_SETUP_EXCEPT] = &&entry_MP_BC_SETUP_EXCEPT, [MP_BC_SETUP_FINALLY] = &&entry_MP_BC_SETUP_FINALLY, [MP_BC_END_FINALLY] = &&entry_MP_BC_END_FINALLY, [MP_BC_GET_ITER] = &&entry_MP_BC_GET_ITER, [MP_BC_GET_ITER_STACK] = &&entry_MP_BC_GET_ITER_STACK, [MP_BC_FOR_ITER] = &&entry_MP_BC_FOR_ITER, [MP_BC_POP_EXCEPT_JUMP] = &&entry_MP_BC_POP_EXCEPT_JUMP, [MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE, [MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST, [MP_BC_BUILD_MAP] = &&entry_MP_BC_BUILD_MAP, [MP_BC_STORE_MAP] = &&entry_MP_BC_STORE_MAP, #if MICROPY_PY_BUILTINS_SET [MP_BC_BUILD_SET] = &&entry_MP_BC_BUILD_SET, #endif #if MICROPY_PY_BUILTINS_SLICE [MP_BC_BUILD_SLICE] = &&entry_MP_BC_BUILD_SLICE, #endif [MP_BC_STORE_COMP] = &&entry_MP_BC_STORE_COMP, [MP_BC_UNPACK_SEQUENCE] = &&entry_MP_BC_UNPACK_SEQUENCE, [MP_BC_UNPACK_EX] = &&entry_MP_BC_UNPACK_EX, [MP_BC_MAKE_FUNCTION] = &&entry_MP_BC_MAKE_FUNCTION, [MP_BC_MAKE_FUNCTION_DEFARGS] = &&entry_MP_BC_MAKE_FUNCTION_DEFARGS, [MP_BC_MAKE_CLOSURE] = &&entry_MP_BC_MAKE_CLOSURE, [MP_BC_MAKE_CLOSURE_DEFARGS] = &&entry_MP_BC_MAKE_CLOSURE_DEFARGS, [MP_BC_CALL_FUNCTION] = &&entry_MP_BC_CALL_FUNCTION, [MP_BC_CALL_FUNCTION_VAR_KW] = &&entry_MP_BC_CALL_FUNCTION_VAR_KW, [MP_BC_CALL_METHOD] = &&entry_MP_BC_CALL_METHOD, [MP_BC_CALL_METHOD_VAR_KW] = &&entry_MP_BC_CALL_METHOD_VAR_KW, [MP_BC_RETURN_VALUE] = &&entry_MP_BC_RETURN_VALUE, [MP_BC_RAISE_LAST] = &&entry_MP_BC_RAISE_LAST, [MP_BC_RAISE_OBJ] = &&entry_MP_BC_RAISE_OBJ, [MP_BC_RAISE_FROM] = &&entry_MP_BC_RAISE_FROM, [MP_BC_YIELD_VALUE] = &&entry_MP_BC_YIELD_VALUE, [MP_BC_YIELD_FROM] = &&entry_MP_BC_YIELD_FROM, [MP_BC_IMPORT_NAME] = &&entry_MP_BC_IMPORT_NAME, [MP_BC_IMPORT_FROM] = &&entry_MP_BC_IMPORT_FROM, [MP_BC_IMPORT_STAR] = &&entry_MP_BC_IMPORT_STAR, [MP_BC_LOAD_CONST_SMALL_INT_MULTI ... MP_BC_LOAD_CONST_SMALL_INT_MULTI + MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM - 1] = &&entry_MP_BC_LOAD_CONST_SMALL_INT_MULTI, [MP_BC_LOAD_FAST_MULTI ... MP_BC_LOAD_FAST_MULTI + MP_BC_LOAD_FAST_MULTI_NUM - 1] = &&entry_MP_BC_LOAD_FAST_MULTI, [MP_BC_STORE_FAST_MULTI ... MP_BC_STORE_FAST_MULTI + MP_BC_STORE_FAST_MULTI_NUM - 1] = &&entry_MP_BC_STORE_FAST_MULTI, [MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + MP_BC_UNARY_OP_MULTI_NUM - 1] = &&entry_MP_BC_UNARY_OP_MULTI, [MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + MP_BC_BINARY_OP_MULTI_NUM - 1] = &&entry_MP_BC_BINARY_OP_MULTI, }; #if __clang__ #pragma clang diagnostic pop #endif // __clang__ micropython-1.12/py/vstr.c000066400000000000000000000165701357706137100156250ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/mpconfig.h" #include "py/runtime.h" #include "py/mpprint.h" // returned value is always at least 1 greater than argument #define ROUND_ALLOC(a) (((a) & ((~0U) - 7)) + 8) // Init the vstr so it allocs exactly given number of bytes. Set length to zero. void vstr_init(vstr_t *vstr, size_t alloc) { if (alloc < 1) { alloc = 1; } vstr->alloc = alloc; vstr->len = 0; vstr->buf = m_new(char, vstr->alloc); vstr->fixed_buf = false; } // Init the vstr so it allocs exactly enough ram to hold a null-terminated // string of the given length, and set the length. void vstr_init_len(vstr_t *vstr, size_t len) { vstr_init(vstr, len + 1); vstr->len = len; } void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) { vstr->alloc = alloc; vstr->len = 0; vstr->buf = buf; vstr->fixed_buf = true; } void vstr_init_print(vstr_t *vstr, size_t alloc, mp_print_t *print) { vstr_init(vstr, alloc); print->data = vstr; print->print_strn = (mp_print_strn_t)vstr_add_strn; } void vstr_clear(vstr_t *vstr) { if (!vstr->fixed_buf) { m_del(char, vstr->buf, vstr->alloc); } vstr->buf = NULL; } vstr_t *vstr_new(size_t alloc) { vstr_t *vstr = m_new_obj(vstr_t); vstr_init(vstr, alloc); return vstr; } void vstr_free(vstr_t *vstr) { if (vstr != NULL) { if (!vstr->fixed_buf) { m_del(char, vstr->buf, vstr->alloc); } m_del_obj(vstr_t, vstr); } } // Extend vstr strictly by requested size, return pointer to newly added chunk. char *vstr_extend(vstr_t *vstr, size_t size) { if (vstr->fixed_buf) { // We can't reallocate, and the caller is expecting the space to // be there, so the only safe option is to raise an exception. mp_raise_msg(&mp_type_RuntimeError, NULL); } char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size); char *p = new_buf + vstr->alloc; vstr->alloc += size; vstr->buf = new_buf; return p; } STATIC void vstr_ensure_extra(vstr_t *vstr, size_t size) { if (vstr->len + size > vstr->alloc) { if (vstr->fixed_buf) { // We can't reallocate, and the caller is expecting the space to // be there, so the only safe option is to raise an exception. mp_raise_msg(&mp_type_RuntimeError, NULL); } size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16); char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc); vstr->alloc = new_alloc; vstr->buf = new_buf; } } void vstr_hint_size(vstr_t *vstr, size_t size) { vstr_ensure_extra(vstr, size); } char *vstr_add_len(vstr_t *vstr, size_t len) { vstr_ensure_extra(vstr, len); char *buf = vstr->buf + vstr->len; vstr->len += len; return buf; } // Doesn't increase len, just makes sure there is a null byte at the end char *vstr_null_terminated_str(vstr_t *vstr) { // If there's no more room, add single byte if (vstr->alloc == vstr->len) { vstr_extend(vstr, 1); } vstr->buf[vstr->len] = '\0'; return vstr->buf; } void vstr_add_byte(vstr_t *vstr, byte b) { byte *buf = (byte*)vstr_add_len(vstr, 1); buf[0] = b; } void vstr_add_char(vstr_t *vstr, unichar c) { #if MICROPY_PY_BUILTINS_STR_UNICODE // TODO: Can this be simplified and deduplicated? // Is it worth just calling vstr_add_len(vstr, 4)? if (c < 0x80) { byte *buf = (byte*)vstr_add_len(vstr, 1); *buf = (byte)c; } else if (c < 0x800) { byte *buf = (byte*)vstr_add_len(vstr, 2); buf[0] = (c >> 6) | 0xC0; buf[1] = (c & 0x3F) | 0x80; } else if (c < 0x10000) { byte *buf = (byte*)vstr_add_len(vstr, 3); buf[0] = (c >> 12) | 0xE0; buf[1] = ((c >> 6) & 0x3F) | 0x80; buf[2] = (c & 0x3F) | 0x80; } else { assert(c < 0x110000); byte *buf = (byte*)vstr_add_len(vstr, 4); buf[0] = (c >> 18) | 0xF0; buf[1] = ((c >> 12) & 0x3F) | 0x80; buf[2] = ((c >> 6) & 0x3F) | 0x80; buf[3] = (c & 0x3F) | 0x80; } #else vstr_add_byte(vstr, c); #endif } void vstr_add_str(vstr_t *vstr, const char *str) { vstr_add_strn(vstr, str, strlen(str)); } void vstr_add_strn(vstr_t *vstr, const char *str, size_t len) { vstr_ensure_extra(vstr, len); memmove(vstr->buf + vstr->len, str, len); vstr->len += len; } STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) { size_t l = vstr->len; if (byte_pos > l) { byte_pos = l; } if (byte_len > 0) { // ensure room for the new bytes vstr_ensure_extra(vstr, byte_len); // copy up the string to make room for the new bytes memmove(vstr->buf + byte_pos + byte_len, vstr->buf + byte_pos, l - byte_pos); // increase the length vstr->len += byte_len; } return vstr->buf + byte_pos; } void vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b) { char *s = vstr_ins_blank_bytes(vstr, byte_pos, 1); *s = b; } void vstr_ins_char(vstr_t *vstr, size_t char_pos, unichar chr) { // TODO UNICODE char *s = vstr_ins_blank_bytes(vstr, char_pos, 1); *s = chr; } void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) { vstr_cut_out_bytes(vstr, 0, bytes_to_cut); } void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) { if (len > vstr->len) { vstr->len = 0; } else { vstr->len -= len; } } void vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut) { if (byte_pos >= vstr->len) { return; } else if (byte_pos + bytes_to_cut >= vstr->len) { vstr->len = byte_pos; } else { memmove(vstr->buf + byte_pos, vstr->buf + byte_pos + bytes_to_cut, vstr->len - byte_pos - bytes_to_cut); vstr->len -= bytes_to_cut; } } void vstr_printf(vstr_t *vstr, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vstr_vprintf(vstr, fmt, ap); va_end(ap); } void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap) { mp_print_t print = {vstr, (mp_print_strn_t)vstr_add_strn}; mp_vprintf(&print, fmt, ap); } micropython-1.12/py/warning.c000066400000000000000000000036101357706137100162630ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2015-2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "py/emit.h" #include "py/runtime.h" #if MICROPY_WARNINGS void mp_warning(const char *category, const char *msg, ...) { if (category == NULL) { category = "Warning"; } mp_print_str(MICROPY_ERROR_PRINTER, category); mp_print_str(MICROPY_ERROR_PRINTER, ": "); va_list args; va_start(args, msg); mp_vprintf(MICROPY_ERROR_PRINTER, msg, args); mp_print_str(MICROPY_ERROR_PRINTER, "\n"); va_end(args); } void mp_emitter_warning(pass_kind_t pass, const char *msg) { if (pass == MP_PASS_CODE_SIZE) { mp_warning(NULL, msg); } } #endif // MICROPY_WARNINGS micropython-1.12/tests/000077500000000000000000000000001357706137100151645ustar00rootroot00000000000000micropython-1.12/tests/README000066400000000000000000000017531357706137100160520ustar00rootroot00000000000000This directory contains tests for various functionality areas of MicroPython. To run all stable tests, run "run-tests" script in this directory. Tests of capabilities not supported on all platforms should be written to check for the capability being present. If it is not, the test should merely output 'SKIP' followed by the line terminator, and call sys.exit() to raise SystemExit, instead of attempting to test the missing capability. The testing framework (run-tests in this directory, test_main.c in qemu_arm) recognizes this as a skipped test. There are a few features for which this mechanism cannot be used to condition a test. The run-tests script uses small scripts in the feature_check directory to check whether each such feature is present, and skips the relevant tests if not. When creating new tests, anything that relies on float support should go in the float/ subdirectory. Anything that relies on import x, where x is not a built-in module, should go in the import/ subdirectory. micropython-1.12/tests/basics/000077500000000000000000000000001357706137100164305ustar00rootroot00000000000000micropython-1.12/tests/basics/0prelim.py000066400000000000000000000001161357706137100203500ustar00rootroot00000000000000# all tests need print to work! make sure it does work print(1) print('abc') micropython-1.12/tests/basics/andor.py000066400000000000000000000001731357706137100201060ustar00rootroot00000000000000# test short circuit expressions outside if conditionals print(() or 1) print((1,) or 1) print(() and 1) print((1,) and 1) micropython-1.12/tests/basics/array1.py000066400000000000000000000014201357706137100201760ustar00rootroot00000000000000try: import uarray as array except ImportError: try: import array except ImportError: print("SKIP") raise SystemExit a = array.array('B', [1, 2, 3]) print(a, len(a)) i = array.array('I', [1, 2, 3]) print(i, len(i)) print(a[0]) print(i[-1]) a = array.array('l', [-1]) print(len(a), a[0]) a1 = array.array('l', [1, 2, 3]) a2 = array.array('L', [1, 2, 3]) print(a2[1]) print(a1 == a2) # Empty arrays print(len(array.array('h'))) print(array.array('i')) # bool operator acting on arrays print(bool(array.array('i'))) print(bool(array.array('i', [1]))) # containment, with incorrect type print('12' in array.array('B', b'12')) print([] in array.array('B', b'12')) # bad typecode try: array.array('X') except ValueError: print("ValueError") micropython-1.12/tests/basics/array_add.py000066400000000000000000000005121357706137100207260ustar00rootroot00000000000000# test array + array try: import uarray as array except ImportError: try: import array except ImportError: print("SKIP") raise SystemExit a1 = array.array('I', [1]) a2 = array.array('I', [2]) print(a1 + a2) a1 += array.array('I', [3, 4]) print(a1) a1.extend(array.array('I', [5])) print(a1) micropython-1.12/tests/basics/array_construct.py000066400000000000000000000010471357706137100222260ustar00rootroot00000000000000# test construction of array.array from different objects try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit # tuple, list print(array('b', (1, 2))) print(array('h', [1, 2])) # raw copy from bytes, bytearray print(array('h', b'22')) # should be byteorder-neutral print(array('h', bytearray(2))) print(array('i', bytearray(4))) # convert from other arrays print(array('H', array('b', [1, 2]))) print(array('b', array('I', [1, 2]))) micropython-1.12/tests/basics/array_construct2.py000066400000000000000000000004261357706137100223100ustar00rootroot00000000000000try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit # construct from something with unknown length (requires generators) print(array('i', (i for i in range(10)))) micropython-1.12/tests/basics/array_construct_endian.py000066400000000000000000000004341357706137100235430ustar00rootroot00000000000000# test construction of array.array from different objects try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit # raw copy from bytes, bytearray print(array('h', b'12')) micropython-1.12/tests/basics/array_intbig.py000066400000000000000000000010171357706137100214530ustar00rootroot00000000000000# test array types QqLl that require big-ints try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit print(array('L', [0, 2**32-1])) print(array('l', [-2**31, 0, 2**31-1])) print(array('q')) print(array('Q')) print(array('q', [0])) print(array('Q', [0])) print(array('q', [-2**63, -1, 0, 1, 2, 2**63-1])) print(array('Q', [0, 1, 2, 2**64-1])) print(bytes(array('q', [-1]))) print(bytes(array('Q', [2**64-1]))) micropython-1.12/tests/basics/array_micropython.py000066400000000000000000000005221357706137100225520ustar00rootroot00000000000000# test MicroPython-specific features of array.array try: import uarray as array except ImportError: try: import array except ImportError: print("SKIP") raise SystemExit # arrays of objects a = array.array('O') a.append(1) print(a[0]) # arrays of pointers a = array.array('P') a.append(1) print(a[0]) micropython-1.12/tests/basics/array_micropython.py.exp000066400000000000000000000000041357706137100233400ustar00rootroot000000000000001 1 micropython-1.12/tests/basics/assign1.py000066400000000000000000000001311357706137100203420ustar00rootroot00000000000000# test assignments a = 1 print(a) a = b = 2 print(a, b) a = b = c = 3 print(a, b, c) micropython-1.12/tests/basics/async_await.py000066400000000000000000000004561357706137100213110ustar00rootroot00000000000000# test basic await expression # adapted from PEP0492 async def abinary(n): print(n) if n <= 0: return 1 l = await abinary(n - 1) r = await abinary(n - 1) return l + 1 + r o = abinary(4) try: while True: o.send(None) except StopIteration: print('finished') micropython-1.12/tests/basics/async_await.py.exp000066400000000000000000000001071357706137100220750ustar00rootroot000000000000004 3 2 1 0 0 1 0 0 2 1 0 0 1 0 0 3 2 1 0 0 1 0 0 2 1 0 0 1 0 0 finished micropython-1.12/tests/basics/async_await2.py000066400000000000000000000011141357706137100213630ustar00rootroot00000000000000# test await expression import sys if sys.implementation.name == 'micropython': # uPy allows normal generators to be awaitables coroutine = lambda f: f else: import types coroutine = types.coroutine @coroutine def wait(value): print('wait value:', value) msg = yield 'message from wait({})'.format(value) print('wait got back:', msg) return 10 async def f(): x = await wait(1)**2 print('x =', x) coro = f() print('return from send:', coro.send(None)) try: coro.send('message from main') except StopIteration: print('got StopIteration') micropython-1.12/tests/basics/async_await2.py.exp000066400000000000000000000001601357706137100221560ustar00rootroot00000000000000wait value: 1 return from send: message from wait(1) wait got back: message from main x = 100 got StopIteration micropython-1.12/tests/basics/async_def.py000066400000000000000000000003451357706137100207370ustar00rootroot00000000000000# test async def def dec(f): print('decorator') return f # test definition with a decorator @dec async def foo(): print('foo') coro = foo() try: coro.send(None) except StopIteration: print('StopIteration') micropython-1.12/tests/basics/async_def.py.exp000066400000000000000000000000341357706137100215250ustar00rootroot00000000000000decorator foo StopIteration micropython-1.12/tests/basics/async_for.py000066400000000000000000000011411357706137100207620ustar00rootroot00000000000000# test basic async for execution # example taken from PEP0492 class AsyncIteratorWrapper: def __init__(self, obj): print('init') self._it = iter(obj) async def __aiter__(self): print('aiter') return self async def __anext__(self): print('anext') try: value = next(self._it) except StopIteration: raise StopAsyncIteration return value async def coro(): async for letter in AsyncIteratorWrapper('abc'): print(letter) o = coro() try: o.send(None) except StopIteration: print('finished') micropython-1.12/tests/basics/async_for.py.exp000066400000000000000000000000621357706137100215560ustar00rootroot00000000000000init aiter anext a anext b anext c anext finished micropython-1.12/tests/basics/async_for2.py000066400000000000000000000020001357706137100210370ustar00rootroot00000000000000# test waiting within "async for" aiter/anext functions import sys if sys.implementation.name == 'micropython': # uPy allows normal generators to be awaitables coroutine = lambda f: f else: import types coroutine = types.coroutine @coroutine def f(x): print('f start:', x) yield x + 1 yield x + 2 return x + 3 class ARange: def __init__(self, high): print('init') self.cur = 0 self.high = high async def __aiter__(self): print('aiter') print('f returned:', await f(10)) return self async def __anext__(self): print('anext') print('f returned:', await f(20)) if self.cur < self.high: val = self.cur self.cur += 1 return val else: raise StopAsyncIteration async def coro(): async for x in ARange(4): print('x', x) o = coro() try: while True: print('coro yielded:', o.send(None)) except StopIteration: print('finished') micropython-1.12/tests/basics/async_for2.py.exp000066400000000000000000000006601357706137100216440ustar00rootroot00000000000000init aiter f start: 10 coro yielded: 11 coro yielded: 12 f returned: 13 anext f start: 20 coro yielded: 21 coro yielded: 22 f returned: 23 x 0 anext f start: 20 coro yielded: 21 coro yielded: 22 f returned: 23 x 1 anext f start: 20 coro yielded: 21 coro yielded: 22 f returned: 23 x 2 anext f start: 20 coro yielded: 21 coro yielded: 22 f returned: 23 x 3 anext f start: 20 coro yielded: 21 coro yielded: 22 f returned: 23 finished micropython-1.12/tests/basics/async_with.py000066400000000000000000000013561357706137100211570ustar00rootroot00000000000000# test simple async with execution class AContext: async def __aenter__(self): print('enter') return 1 async def __aexit__(self, exc_type, exc, tb): print('exit', exc_type, exc) async def f(): async with AContext(): print('body') o = f() try: o.send(None) except StopIteration: print('finished') async def g(): async with AContext() as ac: print(ac) raise ValueError('error') o = g() try: o.send(None) except ValueError: print('ValueError') # test raising BaseException to make sure it is handled by the async-with async def h(): async with AContext(): raise BaseException o = h() try: o.send(None) except BaseException: print('BaseException') micropython-1.12/tests/basics/async_with.py.exp000066400000000000000000000002101357706137100217360ustar00rootroot00000000000000enter body exit None None finished enter 1 exit error ValueError enter exit BaseException micropython-1.12/tests/basics/async_with2.py000066400000000000000000000015261357706137100212400ustar00rootroot00000000000000# test waiting within async with enter/exit functions import sys if sys.implementation.name == 'micropython': # uPy allows normal generators to be awaitables coroutine = lambda f: f else: import types coroutine = types.coroutine @coroutine def f(x): print('f start:', x) yield x + 1 yield x + 2 return x + 3 class AContext: async def __aenter__(self): print('enter') print('f returned:', await f(10)) async def __aexit__(self, exc_type, exc, tb): print('exit', exc_type, exc) print('f returned:', await f(20)) async def coro(): async with AContext(): print('body start') print('body f returned:', await f(30)) print('body end') o = coro() try: while True: print('coro yielded:', o.send(None)) except StopIteration: print('finished') micropython-1.12/tests/basics/async_with2.py.exp000066400000000000000000000003561357706137100220330ustar00rootroot00000000000000enter f start: 10 coro yielded: 11 coro yielded: 12 f returned: 13 body start f start: 30 coro yielded: 31 coro yielded: 32 body f returned: 33 body end exit None None f start: 20 coro yielded: 21 coro yielded: 22 f returned: 23 finished micropython-1.12/tests/basics/async_with_break.py000066400000000000000000000022231357706137100223150ustar00rootroot00000000000000# test async with, escaped by a break class AContext: async def __aenter__(self): print('enter') return 1 async def __aexit__(self, exc_type, exc, tb): print('exit', exc_type, exc) async def f1(): while 1: async with AContext(): print('body') break print('no 1') print('no 2') o = f1() try: print(o.send(None)) except StopIteration: print('finished') async def f2(): while 1: try: async with AContext(): print('body') break print('no 1') finally: print('finally') print('no 2') o = f2() try: print(o.send(None)) except StopIteration: print('finished') async def f3(): while 1: try: try: async with AContext(): print('body') break print('no 1') finally: print('finally inner') finally: print('finally outer') print('no 2') o = f3() try: print(o.send(None)) except StopIteration: print('finished') micropython-1.12/tests/basics/async_with_break.py.exp000066400000000000000000000002151357706137100231070ustar00rootroot00000000000000enter body exit None None finished enter body exit None None finally finished enter body exit None None finally inner finally outer finished micropython-1.12/tests/basics/async_with_return.py000066400000000000000000000015671357706137100225620ustar00rootroot00000000000000# test async with, escaped by a return class AContext: async def __aenter__(self): print('enter') return 1 async def __aexit__(self, exc_type, exc, tb): print('exit', exc_type, exc) async def f1(): async with AContext(): print('body') return o = f1() try: o.send(None) except StopIteration: print('finished') async def f2(): try: async with AContext(): print('body') return finally: print('finally') o = f2() try: o.send(None) except StopIteration: print('finished') async def f3(): try: try: async with AContext(): print('body') return finally: print('finally inner') finally: print('finally outer') o = f3() try: o.send(None) except StopIteration: print('finished') micropython-1.12/tests/basics/async_with_return.py.exp000066400000000000000000000002151357706137100233420ustar00rootroot00000000000000enter body exit None None finished enter body exit None None finally finished enter body exit None None finally inner finally outer finished micropython-1.12/tests/basics/attrtuple1.py000066400000000000000000000005541357706137100211130ustar00rootroot00000000000000# test attrtuple # we can't test this type directly so we use sys.implementation object import sys t = sys.implementation # It can be just a normal tuple on small ports try: t.name except AttributeError: print("SKIP") raise SystemExit # test printing of attrtuple print(str(t).find("version=") > 0) # test read attr print(isinstance(t.name, str)) micropython-1.12/tests/basics/bool1.py000066400000000000000000000003661357706137100200230ustar00rootroot00000000000000# tests for bool objects # basic logic print(not False) print(not True) print(False and True) print(False or True) # unary operators print(+True) print(-True) # unsupported unary op try: len(False) except TypeError: print('TypeError') micropython-1.12/tests/basics/boundmeth1.py000066400000000000000000000011261357706137100210500ustar00rootroot00000000000000# tests basics of bound methods # uPy and CPython differ when printing a bound method, so just print the type print(type(repr([].append))) class A: def f(self): return 0 def g(self, a): return a def h(self, a, b, c, d, e, f): return a + b + c + d + e + f # bound method with no extra args m = A().f print(m()) # bound method with 1 extra arg m = A().g print(m(1)) # bound method with lots of extra args m = A().h print(m(1, 2, 3, 4, 5, 6)) # can't assign attributes to a bound method try: A().f.x = 1 except AttributeError: print('AttributeError') micropython-1.12/tests/basics/break.py000066400000000000000000000002601357706137100200640ustar00rootroot00000000000000while True: break for i in range(4): print('one', i) if i > 2: break print('two', i) for i in [1, 2, 3, 4]: if i == 3: break print(i) micropython-1.12/tests/basics/builtin_abs.py000066400000000000000000000001241357706137100212720ustar00rootroot00000000000000# test builtin abs print(abs(False)) print(abs(True)) print(abs(1)) print(abs(-1)) micropython-1.12/tests/basics/builtin_abs_intbig.py000066400000000000000000000005251357706137100226330ustar00rootroot00000000000000# test builtin abs # bignum print(abs(123456789012345678901234567890)) print(abs(-123456789012345678901234567890)) # edge cases for 32 and 64 bit archs (small int overflow when negating) print(abs(-0x3fffffff - 1)) print(abs(-0x3fffffffffffffff - 1)) # edge case for nan-boxing with 47-bit small int i = -0x3fffffffffff print(abs(i - 1)) micropython-1.12/tests/basics/builtin_allany.py000066400000000000000000000004021357706137100220040ustar00rootroot00000000000000# test builtin "all" and "any" tests = ( (), [], [False], [True], [False, True], [True, False], [False, False], [True, True], range(10), ) for test in tests: print(all(test)) for test in tests: print(any(test)) micropython-1.12/tests/basics/builtin_bin.py000066400000000000000000000002441357706137100213000ustar00rootroot00000000000000# test builtin bin function print(bin(1)) print(bin(-1)) print(bin(15)) print(bin(-15)) print(bin(12345)) print(bin(0b10101)) print(bin(0b10101010101010101010)) micropython-1.12/tests/basics/builtin_bin_intbig.py000066400000000000000000000000761357706137100226370ustar00rootroot00000000000000# test builtin bin function print(bin(12345678901234567890)) micropython-1.12/tests/basics/builtin_callable.py000066400000000000000000000015321357706137100222700ustar00rootroot00000000000000# test builtin callable # primitives should not be callable print(callable(None)) print(callable(1)) print(callable([])) print(callable("dfsd")) # modules should not be callabe import sys print(callable(sys)) # builtins should be callable print(callable(callable)) # lambdas should be callable print(callable(lambda:None)) # user defined functions should be callable def f(): pass print(callable(f)) # types should be callable, but not instances class A: pass print(callable(A)) print(callable(A())) # instances with __call__ method should be callable class B: def __call__(self): pass print(callable(B())) # this checks internal use of callable when extracting members from an instance class C: def f(self): return "A.f" class D: g = C() # g is a value and is not callable print(callable(D().g)) print(D().g.f()) micropython-1.12/tests/basics/builtin_chr.py000066400000000000000000000002131357706137100213000ustar00rootroot00000000000000# test builtin chr (whether or not we support unicode) print(chr(65)) try: chr(0x110000) except ValueError: print("ValueError") micropython-1.12/tests/basics/builtin_compile.py000066400000000000000000000016111357706137100221570ustar00rootroot00000000000000# test compile builtin def have_compile(): try: compile return True except NameError: return False def test(): global x c = compile("print(x)", "file", "exec") try: exec(c) except NameError: print("NameError") # global variable for compiled code to access x = 1 exec(c) exec(c, {"x":2}) exec(c, {}, {"x":3}) # single/eval mode exec(compile('print(1 + 1)', 'file', 'single')) print(eval(compile('1 + 1', 'file', 'eval'))) # bad mode try: compile('1', 'file', '') except ValueError: print("ValueError") # exception within compiled code try: exec(compile('noexist', 'file', 'exec')) except NameError: print("NameError") print(x) # check 'x' still exists as a global if have_compile(): test() else: print("SKIP") raise SystemExit micropython-1.12/tests/basics/builtin_delattr.py000066400000000000000000000004401357706137100221650ustar00rootroot00000000000000# test builtin delattr try: delattr except: print("SKIP") raise SystemExit class A: pass a = A() a.x = 1 print(a.x) delattr(a, 'x') try: a.x except AttributeError: print('AttributeError') try: delattr(a, 'x') except AttributeError: print('AttributeError') micropython-1.12/tests/basics/builtin_dir.py000066400000000000000000000011711357706137100213060ustar00rootroot00000000000000# test builtin dir # dir of locals print('__name__' in dir()) # dir of module import sys print('version' in dir(sys)) # dir of type print('append' in dir(list)) class Foo: def __init__(self): self.x = 1 foo = Foo() print('__init__' in dir(foo)) print('x' in dir(foo)) # dir of subclass class A: def a(): pass class B(A): def b(): pass d = dir(B()) print(d.count('a'), d.count('b')) # dir of class with multiple bases and a common parent class C(A): def c(): pass class D(B, C): def d(): pass d = dir(D()) print(d.count('a'), d.count('b'), d.count('c'), d.count('d')) micropython-1.12/tests/basics/builtin_divmod.py000066400000000000000000000003501357706137100220100ustar00rootroot00000000000000# test builtin divmod print(divmod(0, 2)) print(divmod(3, 4)) print(divmod(20, 3)) try: divmod(1, 0) except ZeroDivisionError: print("ZeroDivisionError") try: divmod('a', 'b') except TypeError: print("TypeError") micropython-1.12/tests/basics/builtin_divmod_intbig.py000066400000000000000000000003471357706137100233520ustar00rootroot00000000000000# test builtin divmod try: divmod(1 << 65, 0) except ZeroDivisionError: print("ZeroDivisionError") # bignum l = (1 << 65) + 123 print(divmod(3, l)) print(divmod(l, 5)) print(divmod(l + 3, l)) print(divmod(l * 20, l + 2)) micropython-1.12/tests/basics/builtin_ellipsis.py000066400000000000000000000001251357706137100223520ustar00rootroot00000000000000# tests that .../Ellipsis exists print(...) print(Ellipsis) print(... == Ellipsis) micropython-1.12/tests/basics/builtin_enumerate.py000066400000000000000000000011741357706137100225200ustar00rootroot00000000000000try: enumerate except: print("SKIP") raise SystemExit print(list(enumerate([]))) print(list(enumerate([1, 2, 3]))) print(list(enumerate([1, 2, 3], 5))) print(list(enumerate([1, 2, 3], -5))) print(list(enumerate(range(100)))) # specifying args with keywords print(list(enumerate([1, 2, 3], start=1))) print(list(enumerate(iterable=[1, 2, 3]))) print(list(enumerate(iterable=[1, 2, 3], start=1))) # check handling of extra positional args (exercises some logic in mp_arg_parse_all) # don't print anything because it doesn't error with MICROPY_CPYTHON_COMPAT disabled try: enumerate([], 1, 2) except TypeError: pass micropython-1.12/tests/basics/builtin_eval.py000066400000000000000000000003401357706137100214540ustar00rootroot00000000000000# builtin eval try: eval except NameError: print("SKIP") raise SystemExit eval('1 + 2') eval('1 + 2\n') eval('1 + 2\n\n#comment\n') x = 4 eval('x') eval('lambda x: x + 10')(-5) y = 6 eval('lambda: y * 2')() micropython-1.12/tests/basics/builtin_eval_error.py000066400000000000000000000002661357706137100226740ustar00rootroot00000000000000# test if eval raises SyntaxError try: eval except NameError: print("SKIP") raise SystemExit try: print(eval("[1,,]")) except SyntaxError: print("SyntaxError") micropython-1.12/tests/basics/builtin_exec.py000066400000000000000000000013601357706137100214540ustar00rootroot00000000000000# test builtin exec try: exec except NameError: print("SKIP") raise SystemExit print(exec("def foo(): return 42")) print(foo()) d = {} exec("def bar(): return 84", d) print(d["bar"]()) # passing None/dict as args to globals/locals foo = 11 exec('print(foo)') exec('print(foo)', None) exec('print(foo)', {'foo':3}, None) exec('print(foo)', None, {'foo':3}) exec('print(foo)', None, {'bar':3}) exec('print(foo)', {'bar':3}, locals()) try: exec('print(foo)', {'bar':3}, None) except NameError: print('NameError') # invalid arg passed to globals try: exec('print(1)', 'foo') except TypeError: print('TypeError') # invalid arg passed to locals try: exec('print(1)', None, 123) except TypeError: print('TypeError') micropython-1.12/tests/basics/builtin_filter.py000066400000000000000000000002331357706137100220130ustar00rootroot00000000000000try: filter except: print("SKIP") raise SystemExit print(list(filter(lambda x: x & 1, range(-3, 4)))) print(list(filter(None, range(-3, 4)))) micropython-1.12/tests/basics/builtin_getattr.py000066400000000000000000000004651357706137100222070ustar00rootroot00000000000000class A: var = 132 def __init__(self): self.var2 = 34 def meth(self, i): return 42 + i a = A() print(getattr(a, "var")) print(getattr(a, "var2")) print(getattr(a, "meth")(5)) print(getattr(a, "_none_such", 123)) print(getattr(list, "foo", 456)) print(getattr(a, "va" + "r2")) micropython-1.12/tests/basics/builtin_hasattr.py000066400000000000000000000014371357706137100222030ustar00rootroot00000000000000class A: var = 132 def __init__(self): self.var2 = 34 def meth(self, i): return 42 + i a = A() print(hasattr(a, "var")) print(hasattr(a, "var2")) print(hasattr(a, "meth")) print(hasattr(a, "_none_such")) print(hasattr(list, "foo")) class C: def __getattr__(self, attr): if attr == "exists": return attr elif attr == "raise": raise Exception(123) raise AttributeError c = C() print(hasattr(c, "exists")) print(hasattr(c, "doesnt_exist")) # ensure that non-AttributeError exceptions propagate out of hasattr try: hasattr(c, "raise") except Exception as er: print(er) try: hasattr(1, b'123') except TypeError: print('TypeError') try: hasattr(1, 123) except TypeError: print('TypeError') micropython-1.12/tests/basics/builtin_hash.py000066400000000000000000000015741357706137100214620ustar00rootroot00000000000000# test builtin hash function print(hash(False)) print(hash(True)) print({():1}) # hash tuple print({(1,):1}) # hash non-empty tuple print(hash in {hash:1}) # hash function try: hash([]) except TypeError: print("TypeError") class A: def __hash__(self): return 123 def __repr__(self): return "a instance" print(hash(A())) print({A():1}) # all user-classes have default __hash__ class B: pass hash(B()) # if __eq__ is defined then default __hash__ is not used class C: def __eq__(self, another): return True try: hash(C()) except TypeError: print("TypeError") # __hash__ must return an int class D: def __hash__(self): return None try: hash(D()) except TypeError: print("TypeError") # __hash__ returning a bool should be converted to an int class E: def __hash__(self): return True print(hash(E())) micropython-1.12/tests/basics/builtin_hash_gen.py000066400000000000000000000001631357706137100223040ustar00rootroot00000000000000# test builtin hash function, on generators def gen(): yield print(type(hash(gen))) print(type(hash(gen()))) micropython-1.12/tests/basics/builtin_hash_intbig.py000066400000000000000000000006431357706137100230120ustar00rootroot00000000000000# test builtin hash function print({1 << 66:1}) # hash big int print({-(1 << 66):2}) # hash negative big int # __hash__ returning a large number should be truncated class F: def __hash__(self): return 1 << 70 | 1 print(hash(F()) != 0) # this had a particular error with internal integer arithmetic of hash function print(hash(6699999999999999999999999999999999999999999999999999999999999999999999) != 0) micropython-1.12/tests/basics/builtin_help.py000066400000000000000000000005541357706137100214640ustar00rootroot00000000000000# test builtin help function try: help except NameError: print("SKIP") raise SystemExit help() # no args help(help) # help for a function help(int) # help for a class help(1) # help for an instance import micropython help(micropython) # help for a module help('modules') # list available modules print('done') # so last bit of output is predictable micropython-1.12/tests/basics/builtin_help.py.exp000066400000000000000000000005421357706137100222540ustar00rootroot00000000000000######## object is of type function object is of type type from_bytes -- to_bytes -- object 1 is of type int from_bytes -- to_bytes -- object is of type module __name__ -- micropython const -- opt_level -- ######## done micropython-1.12/tests/basics/builtin_hex.py000066400000000000000000000002001357706137100213040ustar00rootroot00000000000000# test builtin hex function print(hex(1)) print(hex(-1)) print(hex(15)) print(hex(-15)) print(hex(12345)) print(hex(0x12345)) micropython-1.12/tests/basics/builtin_hex_intbig.py000066400000000000000000000001411357706137100226440ustar00rootroot00000000000000# test builtin hex function print(hex(12345678901234567890)) print(hex(0x12345678901234567890)) micropython-1.12/tests/basics/builtin_id.py000066400000000000000000000003421357706137100211230ustar00rootroot00000000000000print(id(1) == id(2)) print(id(None) == id(None)) # This can't be true per Python semantics, just CPython implementation detail #print(id([]) == id([])) l = [1, 2] print(id(l) == id(l)) f = lambda:None print(id(f) == id(f)) micropython-1.12/tests/basics/builtin_issubclass.py000066400000000000000000000003531357706137100227040ustar00rootroot00000000000000# test builtin issubclass class A: pass print(issubclass(A, A)) print(issubclass(A, (A,))) try: issubclass(A, 1) except TypeError: print('TypeError') try: issubclass('a', 1) except TypeError: print('TypeError') micropython-1.12/tests/basics/builtin_len1.py000066400000000000000000000002311357706137100213630ustar00rootroot00000000000000# builtin len print(len(())) print(len((1,))) print(len((1, 2))) print(len([])) x = [1, 2, 3] print(len(x)) f = len print(f({})) print(f({1:2, 3:4})) micropython-1.12/tests/basics/builtin_locals.py000066400000000000000000000002701357706137100220040ustar00rootroot00000000000000# test builtin locals() x = 123 print(locals()['x']) class A: y = 1 def f(self): pass print('x' in locals()) print(locals()['y']) print('f' in locals()) micropython-1.12/tests/basics/builtin_map.py000066400000000000000000000002631357706137100213060ustar00rootroot00000000000000print(list(map(lambda x: x & 1, range(-3, 4)))) print(list(map(abs, range(-3, 4)))) print(list(map(tuple, [[i] for i in range(-3, 4)]))) print(list(map(pow, range(4), range(4)))) micropython-1.12/tests/basics/builtin_minmax.py000066400000000000000000000020331357706137100220170ustar00rootroot00000000000000# test builtin min and max functions try: min max except: print("SKIP") raise SystemExit print(min(0,1)) print(min(1,0)) print(min(0,-1)) print(min(-1,0)) print(max(0,1)) print(max(1,0)) print(max(0,-1)) print(max(-1,0)) print(min([1,2,4,0,-1,2])) print(max([1,2,4,0,-1,2])) # test with key function lst = [2, 1, 3, 4] print(min(lst, key=lambda x:x)) print(min(lst, key=lambda x:-x)) print(min(1, 2, 3, 4, key=lambda x:-x)) print(min(4, 3, 2, 1, key=lambda x:-x)) print(max(lst, key=lambda x:x)) print(max(lst, key=lambda x:-x)) print(max(1, 2, 3, 4, key=lambda x:-x)) print(max(4, 3, 2, 1, key=lambda x:-x)) # need at least 1 item in the iterable try: min([]) except ValueError: print("ValueError") # 'default' tests print(min([1, 2, 3, 4, 5], default=-1)) print(min([], default=-1)) print(max([1, 2, 3, 4, 5], default=-1)) print(max([], default=-1)) # make sure it works with lazy iterables # can't use Python generators here, as they're not supported # byy native codegenerator. print(min(enumerate([]), default=-10)) micropython-1.12/tests/basics/builtin_next_arg2.py000066400000000000000000000011101357706137100224120ustar00rootroot00000000000000# test next(iter, default) try: next(iter([]), 42) except TypeError: # 2-argument version not supported print('SKIP') raise SystemExit print(next(iter([]), 42)) print(next(iter(range(0)), 42)) print(next((x for x in [0] if x == 1), 43)) def gen(): yield 1 yield 2 g = gen() print(next(g, 42)) print(next(g, 43)) print(next(g, 44)) class Gen: def __init__(self): self.b = False def __next__(self): if self.b: raise StopIteration self.b = True return self.b g = Gen() print(next(g, 44)) print(next(g, 45)) micropython-1.12/tests/basics/builtin_oct.py000066400000000000000000000002001357706137100213050ustar00rootroot00000000000000# test builtin oct function print(oct(1)) print(oct(-1)) print(oct(15)) print(oct(-15)) print(oct(12345)) print(oct(0o12345)) micropython-1.12/tests/basics/builtin_oct_intbig.py000066400000000000000000000001411357706137100226450ustar00rootroot00000000000000# test builtin oct function print(oct(12345678901234567890)) print(oct(0o12345670123456701234)) micropython-1.12/tests/basics/builtin_ord.py000066400000000000000000000006451357706137100213210ustar00rootroot00000000000000# test builtin ord (whether or not we support unicode) print(ord('a')) try: ord('') except TypeError: print("TypeError") # bytes also work in ord print(ord(b'a')) print(ord(b'\x00')) print(ord(b'\x01')) print(ord(b'\x7f')) print(ord(b'\x80')) print(ord(b'\xff')) try: ord(b'') except TypeError: print("TypeError") # argument must be a string try: ord(1) except TypeError: print('TypeError') micropython-1.12/tests/basics/builtin_override.py000066400000000000000000000013711357706137100223510ustar00rootroot00000000000000# test overriding builtins import builtins # override generic builtin try: builtins.abs = lambda x: x + 1 except AttributeError: print("SKIP") raise SystemExit print(abs(1)) # __build_class__ is handled in a special way orig_build_class = __build_class__ builtins.__build_class__ = lambda x, y: ('class', y) class A: pass print(A) builtins.__build_class__ = orig_build_class # __import__ is handled in a special way def custom_import(name, globals, locals, fromlist, level): print('import', name, fromlist, level) class M: a = 1 b = 2 return M builtins.__import__ = custom_import __import__('A', None, None, None, 0) import a import a.b from a import a from a.b import a, b from .a import a from ..a import a, b micropython-1.12/tests/basics/builtin_pow.py000066400000000000000000000002001357706137100213250ustar00rootroot00000000000000# test builtin pow() with integral values # 2 arg version print(pow(0, 1)) print(pow(1, 0)) print(pow(-2, 3)) print(pow(3, 8)) micropython-1.12/tests/basics/builtin_pow3.py000066400000000000000000000010511357706137100214150ustar00rootroot00000000000000# test builtin pow() with integral values # 3 arg version try: print(pow(3, 4, 7)) except NotImplementedError: print("SKIP") raise SystemExit # test some edge cases print(pow(1, 1, 1)) print(pow(0, 1, 1)) print(pow(1, 0, 1)) print(pow(1, 0, 2)) # 3 arg pow is defined to only work on integers try: print(pow("x", 5, 6)) except TypeError: print("TypeError expected") try: print(pow(4, "y", 6)) except TypeError: print("TypeError expected") try: print(pow(4, 5, "z")) except TypeError: print("TypeError expected") micropython-1.12/tests/basics/builtin_pow3_intbig.py000066400000000000000000000017601357706137100227600ustar00rootroot00000000000000# test builtin pow() with integral values # 3 arg version try: print(pow(3, 4, 7)) except NotImplementedError: print("SKIP") raise SystemExit print(pow(555557, 1000002, 1000003)) # Tests for 3 arg pow with large values # This value happens to be prime x = 0xd48a1e2a099b1395895527112937a391d02d4a208bce5d74b281cf35a57362502726f79a632f063a83c0eba66196712d963aa7279ab8a504110a668c0fc38a7983c51e6ee7a85cae87097686ccdc359ee4bbf2c583bce524e3f7836bded1c771a4efcb25c09460a862fc98e18f7303df46aaeb34da46b0c4d61d5cd78350f3edb60e6bc4befa712a849 y = 0x3accf60bb1a5365e4250d1588eb0fe6cd81ad495e9063f90880229f2a625e98c59387238670936afb2cafc5b79448e4414d6cd5e9901aa845aa122db58ddd7b9f2b17414600a18c47494ed1f3d49d005a5 print(hex(pow(2, 200, x))) # Should not overflow, just 1 << 200 print(hex(pow(2, x-1, x))) # Should be 1, since x is prime print(hex(pow(y, x-1, x))) # Should be 1, since x is prime print(hex(pow(y, y-1, x))) # Should be a 'big value' print(hex(pow(y, y-1, y))) # Should be a 'big value' micropython-1.12/tests/basics/builtin_print.py000066400000000000000000000004361357706137100216670ustar00rootroot00000000000000# test builtin print function print() print(None) print('') print(1) print(1, 2) print(sep='') print(sep='x') print(end='') print(end='x\n') print(1, sep='') print(1, end='') print(1, sep='', end='') print(1, 2, sep='') print(1, 2, end='') print(1, 2, sep='', end='') print([{1:2}]) micropython-1.12/tests/basics/builtin_property.py000066400000000000000000000035571357706137100224260ustar00rootroot00000000000000# test builtin property try: property except: print("SKIP") raise SystemExit # create a property object explicitly property() property(1, 2, 3) # use its accessor methods p = property() p.getter(1) p.setter(2) p.deleter(3) # basic use as a decorator class A: def __init__(self, x): self._x = x @property def x(self): print("x get") return self._x a = A(1) print(a.x) try: a.x = 2 except AttributeError: print("AttributeError") # explicit use within a class class B: def __init__(self, x): self._x = x def xget(self): print("x get") return self._x def xset(self, value): print("x set") self._x = value def xdel(self): print("x del") x = property(xget, xset, xdel) b = B(3) print(b.x) b.x = 4 print(b.x) del b.x # full use as a decorator class C: def __init__(self, x): self._x = x @property def x(self): print("x get") return self._x @x.setter def x(self, value): print("x set") self._x = value @x.deleter def x(self): print("x del") c = C(5) print(c.x) c.x = 6 print(c.x) del c.x # a property that has no get, set or del class D: prop = property() d = D() try: d.prop except AttributeError: print('AttributeError') try: d.prop = 1 except AttributeError: print('AttributeError') try: del d.prop except AttributeError: print('AttributeError') # properties take keyword arguments class E: p = property(lambda self: 42, doc="This is truth.") # not tested for because the other keyword arguments are not accepted # q = property(fget=lambda self: 21, doc="Half the truth.") print(E().p) # a property as an instance member should not be delegated to class F: def __init__(self): self.prop_member = property() print(type(F().prop_member)) micropython-1.12/tests/basics/builtin_property_inherit.py000066400000000000000000000020171357706137100241360ustar00rootroot00000000000000# test builtin property combined with inheritance try: property except: print("SKIP") raise SystemExit # test property in a base class works for derived classes class A: @property def x(self): print('A x') return 123 class B(A): pass class C(B): pass class D: pass class E(C, D): pass print(A().x) print(B().x) print(C().x) print(E().x) # test that we can add a property to base class after creation class F: pass F.foo = property(lambda self: print('foo get')) class G(F): pass F().foo G().foo # should be able to add a property to already-subclassed class because it already has one F.bar = property(lambda self: print('bar get')) F().bar G().bar # test case where class (H here) is already subclassed before adding attributes class H: pass class I(H): pass # should be able to add a normal member to already-subclassed class H.val = 2 print(I().val) # should be able to add a property to the derived class I.baz = property(lambda self: print('baz get')) I().baz micropython-1.12/tests/basics/builtin_range.py000066400000000000000000000021511357706137100216230ustar00rootroot00000000000000# test builtin range type # print print(range(4)) # bool print(bool(range(0))) print(bool(range(10))) # len print(len(range(0))) print(len(range(4))) print(len(range(1, 4))) print(len(range(1, 4, 2))) print(len(range(1, 4, -1))) print(len(range(4, 1, -1))) print(len(range(4, 1, -2))) # subscr print(range(4)[0]) print(range(4)[1]) print(range(4)[-1]) # slice print(range(4)[0:]) print(range(4)[1:]) print(range(4)[1:2]) print(range(4)[1:3]) print(range(4)[1::2]) print(range(4)[1:-2:2]) print(range(1, 4)[:]) print(range(1, 4)[0:]) print(range(1, 4)[1:]) print(range(1, 4)[:-1]) print(range(7, -2, -4)[:]) print(range(1, 100, 5)[5:15:3]) print(range(1, 100, 5)[15:5:-3]) print(range(100, 1, -5)[5:15:3]) print(range(100, 1, -5)[15:5:-3]) # for this case uPy gives a different stop value but the listed elements are still correct print(list(range(7, -2, -4)[2:-2:])) # zero step try: range(1, 2, 0) except ValueError: print("ValueError") # bad unary op try: -range(1) except TypeError: print("TypeError") # bad subscription (can't store) try: range(1)[0] = 1 except TypeError: print("TypeError") micropython-1.12/tests/basics/builtin_range_attrs.py000066400000000000000000000005031357706137100230370ustar00rootroot00000000000000# test attributes of builtin range type try: range(0).start except AttributeError: print("SKIP") raise SystemExit # attrs print(range(1, 2, 3).start) print(range(1, 2, 3).stop) print(range(1, 2, 3).step) # bad attr (can't store) try: range(4).start = 0 except AttributeError: print('AttributeError') micropython-1.12/tests/basics/builtin_range_binop.py000066400000000000000000000014431357706137100230150ustar00rootroot00000000000000# test binary operations on range objects; (in)equality only # this "feature test" actually tests the implementation but is the best we can do if range(1) != range(1): print("SKIP") raise SystemExit # basic (in)equality print(range(1) == range(1)) print(range(1) != range(1)) print(range(1) != range(2)) # empty range print(range(0) == range(0)) print(range(1, 0) == range(0)) print(range(1, 4, -1) == range(6, 3)) # 1 element range print(range(1, 4, 10) == range(1, 4, 10)) print(range(1, 4, 10) == range(1, 4, 20)) print(range(1, 4, 10) == range(1, 8, 20)) # more than 1 element print(range(0, 3, 2) == range(0, 3, 2)) print(range(0, 3, 2) == range(0, 4, 2)) print(range(0, 3, 2) == range(0, 5, 2)) # unsupported binary op try: range(1) + 10 except TypeError: print('TypeError') micropython-1.12/tests/basics/builtin_reversed.py000066400000000000000000000013231357706137100223460ustar00rootroot00000000000000# test the builtin reverse() function try: reversed except: print("SKIP") raise SystemExit # list print(list(reversed([]))) print(list(reversed([1]))) print(list(reversed([1, 2, 3]))) # tuple print(list(reversed(()))) print(list(reversed((1, 2, 3)))) # string for c in reversed('ab'): print(c) # bytes for b in reversed(b'1234'): print(b) # range for i in reversed(range(3)): print(i) # user object class A: def __init__(self): pass def __len__(self): return 3 def __getitem__(self, pos): return pos + 1 for a in reversed(A()): print(a) # user object with __reversed__ class B: def __reversed__(self): return [1, 2, 3] print(reversed(B())) micropython-1.12/tests/basics/builtin_round.py000066400000000000000000000001671357706137100216630ustar00rootroot00000000000000# test round() with integral values tests = [ False, True, 0, 1, -1, 10 ] for t in tests: print(round(t)) micropython-1.12/tests/basics/builtin_round_int.py000066400000000000000000000006531357706137100225350ustar00rootroot00000000000000# test round() with integer values and second arg # rounding integers is an optional feature so test for it try: round(1, -1) except NotImplementedError: print('SKIP') raise SystemExit tests = [ (1, False), (1, True), (124, -1), (125, -1), (126, -1), (5, -1), (15, -1), (25, -1), (12345, 0), (12345, -1), (12345, 1), (-1234, 0), (-1234, -1), (-1234, 1), ] for t in tests: print(round(*t)) micropython-1.12/tests/basics/builtin_round_intbig.py000066400000000000000000000005331357706137100232140ustar00rootroot00000000000000# test round() with large integer values and second arg # rounding integers is an optional feature so test for it try: round(1, -1) except NotImplementedError: print('SKIP') raise SystemExit i = 2**70 tests = [ (i, 0), (i, -1), (i, -10), (i, 1), (-i, 0), (-i, -1), (-i, -10), (-i, 1), ] for t in tests: print(round(*t)) micropython-1.12/tests/basics/builtin_setattr.py000066400000000000000000000006641357706137100222240ustar00rootroot00000000000000class A: var = 132 def __init__(self): self.var2 = 34 a = A() setattr(a, "var", 123) setattr(a, "var2", 56) print(a.var) print(a.var2) try: setattr(a, b'var3', 1) except TypeError: print('TypeError') # try setattr on a built-in function try: setattr(int, 'to_bytes', 1) except (AttributeError, TypeError): # uPy raises AttributeError, CPython raises TypeError print('AttributeError/TypeError') micropython-1.12/tests/basics/builtin_slice.py000066400000000000000000000002501357706137100216240ustar00rootroot00000000000000# test builtin slice # print slice class A: def __getitem__(self, idx): print(idx) return idx s = A()[1:2:3] # check type print(type(s) is slice) micropython-1.12/tests/basics/builtin_sorted.py000066400000000000000000000004361357706137100220330ustar00rootroot00000000000000# test builtin sorted try: sorted set except: print("SKIP") raise SystemExit print(sorted(set(range(100)))) print(sorted(set(range(100)), key=lambda x: x + 100*(x % 2))) # need to use keyword argument try: sorted([], None) except TypeError: print("TypeError") micropython-1.12/tests/basics/builtin_sum.py000066400000000000000000000002441357706137100213340ustar00rootroot00000000000000# test builtin "sum" tests = ( (), [], [0], [1], [0, 1, 2], range(10), ) for test in tests: print(sum(test)) print(sum(test, -2)) micropython-1.12/tests/basics/builtin_type.py000066400000000000000000000007541357706137100215170ustar00rootroot00000000000000# test builtin type print(type(int)) try: type() except TypeError: print('TypeError') try: type(1, 2) except TypeError: print('TypeError') # second arg should be a tuple try: type('abc', None, None) except TypeError: print('TypeError') # third arg should be a dict try: type('abc', (), None) except TypeError: print('TypeError') # elements of second arg (the bases) should be types try: type('abc', (1,), {}) except TypeError: print('TypeError') micropython-1.12/tests/basics/builtin_zip.py000066400000000000000000000002051357706137100213270ustar00rootroot00000000000000try: zip set except NameError: print("SKIP") raise SystemExit print(list(zip())) print(list(zip([1], set([2, 3])))) micropython-1.12/tests/basics/bytearray1.py000066400000000000000000000012301357706137100210610ustar00rootroot00000000000000print(bytearray(4)) a = bytearray([1, 2, 200]) print(type(a)) print(a[0], a[2]) print(a[-1]) print(a) a[2] = 255 print(a[-1]) a.append(10) print(len(a)) s = 0 for i in a: s += i print(s) print(a[1:]) print(a[:-1]) print(a[2:3]) print(str(bytearray(b"123"), "utf-8")) # Comparisons print(bytearray([1]) == bytearray([1])) print(bytearray([1]) == bytearray([2])) print(bytearray([1]) == b"1") print(b"1" == bytearray([1])) print(bytearray() == bytearray()) # comparison with other type should return False print(bytearray() == 1) # TODO: other comparisons # __contains__ b = bytearray(b"\0foo\0") print(b"foo" in b) print(b"foo\x01" in b) print(b"" in b) micropython-1.12/tests/basics/bytearray_add.py000066400000000000000000000004261357706137100216160ustar00rootroot00000000000000# test bytearray + bytearray b = bytearray(2) b[0] = 1 b[1] = 2 print(b + bytearray(2)) # inplace add b += bytearray(3) print(b) # extend b.extend(bytearray(4)) print(b) # this inplace add tests the code when the buffer doesn't need to be increased b = bytearray() b += b'' micropython-1.12/tests/basics/bytearray_append.py000066400000000000000000000003531357706137100223340ustar00rootroot00000000000000# test bytearray.append method a = bytearray(4) print(a) # append should append a single byte a.append(2) print(a) # a should not be modified if append fails try: a.append(None) except TypeError: print('TypeError') print(a) micropython-1.12/tests/basics/bytearray_construct.py000066400000000000000000000003231357706137100231060ustar00rootroot00000000000000# test construction of bytearray from different objects print(bytearray(b'123')) print(bytearray('1234', 'utf-8')) print(bytearray('12345', 'utf-8', 'strict')) print(bytearray((1, 2))) print(bytearray([1, 2])) micropython-1.12/tests/basics/bytearray_construct_array.py000066400000000000000000000004721357706137100243110ustar00rootroot00000000000000# test construction of bytearray from different objects try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit # arrays print(bytearray(array('b', [1, 2]))) print(bytearray(array('h', [0x101, 0x202]))) micropython-1.12/tests/basics/bytearray_construct_endian.py000066400000000000000000000004621357706137100244300ustar00rootroot00000000000000# test construction of bytearray from different objects try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit # arrays print(bytearray(array('h', [1, 2]))) print(bytearray(array('I', [1, 2]))) micropython-1.12/tests/basics/bytearray_decode.py000066400000000000000000000002141357706137100223040ustar00rootroot00000000000000try: print(bytearray(b'').decode()) print(bytearray(b'abc').decode()) except AttributeError: print("SKIP") raise SystemExit micropython-1.12/tests/basics/bytearray_intbig.py000066400000000000000000000000461357706137100223400ustar00rootroot00000000000000print(bytearray(2**65 - (2**65 - 1))) micropython-1.12/tests/basics/bytearray_slice_assign.py000066400000000000000000000023171357706137100235320ustar00rootroot00000000000000try: bytearray()[:] = bytearray() except TypeError: print("SKIP") raise SystemExit # test slices; only 2 argument version supported by MicroPython at the moment x = bytearray(range(10)) # Assignment l = bytearray(x) l[1:3] = bytearray([10, 20]) print(l) l = bytearray(x) l[1:3] = bytearray([10]) print(l) l = bytearray(x) l[1:3] = bytearray() print(l) l = bytearray(x) #del l[1:3] print(l) l = bytearray(x) l[:3] = bytearray([10, 20]) print(l) l = bytearray(x) l[:3] = bytearray() print(l) l = bytearray(x) #del l[:3] print(l) l = bytearray(x) l[:-3] = bytearray([10, 20]) print(l) l = bytearray(x) l[:-3] = bytearray() print(l) l = bytearray(x) #del l[:-3] print(l) # slice assignment that extends the array b = bytearray(2) b[2:] = bytearray(10) print(b) b = bytearray(10) b[:-1] = bytearray(500) print(len(b), b[0], b[-1]) # extension with self on RHS b = bytearray(x) b[4:] = b print(b) # Assignment of bytes to array slice b = bytearray(2) b[1:1] = b"12345" print(b) # Growth of bytearray via slice extension b = bytearray(b'12345678') b.append(57) # expand and add a bit of unused space at end of the bytearray for i in range(400): b[-1:] = b'ab' # grow slowly into the unused space print(len(b), b) micropython-1.12/tests/basics/bytes.py000066400000000000000000000022241357706137100201300ustar00rootroot00000000000000# literals print(b'123') print(br'123') print(rb'123') print(b'\u1234') # construction print(bytes()) print(bytes(b'abc')) # make sure empty bytes is converted correctly print(str(bytes(), 'utf-8')) a = b"123" print(a) print(str(a)) print(repr(a)) print(a[0], a[2]) print(a[-1]) print(str(a, "utf-8")) print(str(a, "utf-8", "ignore")) try: str(a, "utf-8", "ignore", "toomuch") except TypeError: print("TypeError") s = 0 for i in a: s += i print(s) print(bytes("abc", "utf-8")) print(bytes("abc", "utf-8", "replace")) try: bytes("abc") except TypeError: print("TypeError") try: bytes("abc", "utf-8", "replace", "toomuch") except TypeError: print("TypeError") print(bytes(3)) print(bytes([3, 2, 1])) print(bytes(range(5))) # Make sure bytes are not mistreated as unicode x = b"\xff\x8e\xfe}\xfd\x7f" print(len(x)) print(x[0], x[1], x[2], x[3]) # Make sure init values are not mistreated as unicode chars # For sequence of known len print(bytes([128, 255])) # For sequence of unknown len print(bytes(iter([128, 255]))) # Shouldn't be able to make bytes with negative length try: bytes(-1) except ValueError: print('ValueError') micropython-1.12/tests/basics/bytes_add.py000066400000000000000000000002301357706137100207330ustar00rootroot00000000000000# test bytes + other print(b"123" + b"456") print(b"123" + b"") # RHS is empty, can be optimised print(b"" + b"123") # LHS is empty, can be optimised micropython-1.12/tests/basics/bytes_add_array.py000066400000000000000000000004471357706137100221430ustar00rootroot00000000000000# test bytes + other try: import uarray as array except ImportError: try: import array except ImportError: print("SKIP") raise SystemExit # should be byteorder-neutral print(b"123" + array.array('h', [0x1515])) print(b"\x01\x02" + array.array('b', [1, 2])) micropython-1.12/tests/basics/bytes_add_bytearray.py000066400000000000000000000001701357706137100230200ustar00rootroot00000000000000# test bytes + bytearray print(b"123" + bytearray(2)) print(b"" + bytearray(1)) # LHS is empty but can't be optimised micropython-1.12/tests/basics/bytes_add_endian.py000066400000000000000000000003251357706137100222560ustar00rootroot00000000000000# test bytes + other try: import uarray as array except ImportError: try: import array except ImportError: print("SKIP") raise SystemExit print(b"123" + array.array('i', [1])) micropython-1.12/tests/basics/bytes_compare.py000066400000000000000000000016301357706137100216360ustar00rootroot00000000000000print(b"" == b"") print(b"" > b"") print(b"" < b"") print(b"" == b"1") print(b"1" == b"") print("==") print(b"" > b"1") print(b"1" > b"") print(b"" < b"1") print(b"1" < b"") print(b"" >= b"1") print(b"1" >= b"") print(b"" <= b"1") print(b"1" <= b"") print(b"1" == b"1") print(b"1" != b"1") print(b"1" == b"2") print(b"1" == b"10") print(b"1" > b"1") print(b"1" > b"2") print(b"2" > b"1") print(b"10" > b"1") print(b"1/" > b"1") print(b"1" > b"10") print(b"1" > b"1/") print(b"1" < b"1") print(b"2" < b"1") print(b"1" < b"2") print(b"1" < b"10") print(b"1" < b"1/") print(b"10" < b"1") print(b"1/" < b"1") print(b"1" >= b"1") print(b"1" >= b"2") print(b"2" >= b"1") print(b"10" >= b"1") print(b"1/" >= b"1") print(b"1" >= b"10") print(b"1" >= b"1/") print(b"1" <= b"1") print(b"2" <= b"1") print(b"1" <= b"2") print(b"1" <= b"10") print(b"1" <= b"1/") print(b"10" <= b"1") print(b"1/" <= b"1") print(b'o' == b'\n') micropython-1.12/tests/basics/bytes_compare2.py000066400000000000000000000000211357706137100217110ustar00rootroot00000000000000print(b"1" == 1) micropython-1.12/tests/basics/bytes_compare3.py000066400000000000000000000007611357706137100217250ustar00rootroot00000000000000# Based on MicroPython config option, comparison of str and bytes # or vice versa may issue a runtime warning. On CPython, if run as # "python3 -b", only comparison of str to bytes issues a warning, # not the other way around (while exactly comparison of bytes to # str would be the most common error, as in sock.recv(3) == "GET"). # Update: the issue above with CPython apparently happens in REPL, # when run as a script, both lines issue a warning. print("123" == b"123") print(b"123" == "123") micropython-1.12/tests/basics/bytes_compare3.py.exp000066400000000000000000000000361357706137100225130ustar00rootroot00000000000000######## False ######## False micropython-1.12/tests/basics/bytes_compare_array.py000066400000000000000000000004371357706137100230400ustar00rootroot00000000000000try: import uarray as array except ImportError: try: import array except ImportError: print("SKIP") raise SystemExit print(array.array('b', [1, 2]) in b'\x01\x02\x03') # CPython gives False here #print(b"\x01\x02\x03" == array.array("B", [1, 2, 3])) micropython-1.12/tests/basics/bytes_compare_bytearray.py000066400000000000000000000002121357706137100237130ustar00rootroot00000000000000print(b"123" == bytearray(b"123")) print(b'123' < bytearray(b"124")) print(b'123' > bytearray(b"122")) print(bytearray(b"23") in b"1234") micropython-1.12/tests/basics/bytes_construct.py000066400000000000000000000006251357706137100222370ustar00rootroot00000000000000# test construction of bytes from different objects # tuple, list print(bytes((1, 2))) print(bytes([1, 2])) # constructor value out of range try: bytes([-1]) except ValueError: print('ValueError') # constructor value out of range try: bytes([256]) except ValueError: print('ValueError') # error in construction try: a = bytes([1, 2, 3], 1) except TypeError: print('TypeError') micropython-1.12/tests/basics/bytes_construct_array.py000066400000000000000000000004561357706137100234370ustar00rootroot00000000000000# test construction of bytes from different objects try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit # arrays print(bytes(array('b', [1, 2]))) print(bytes(array('h', [0x101, 0x202]))) micropython-1.12/tests/basics/bytes_construct_bytearray.py000066400000000000000000000001101357706137100243060ustar00rootroot00000000000000# test construction of bytes from bytearray print(bytes(bytearray(4))) micropython-1.12/tests/basics/bytes_construct_endian.py000066400000000000000000000004471357706137100235570ustar00rootroot00000000000000# test construction of bytes from different objects try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit # arrays print(bytes(array('h', [1, 2]))) print(bytes(array('I', [1, 2]))) micropython-1.12/tests/basics/bytes_construct_intbig.py000066400000000000000000000001621357706137100235670ustar00rootroot00000000000000# test construction of bytes from different objects # long ints print(ord(bytes([14953042807679334000 & 0xff]))) micropython-1.12/tests/basics/bytes_count.py000066400000000000000000000024261357706137100213440ustar00rootroot00000000000000try: bytes.count except AttributeError: print("SKIP") raise SystemExit print(b"".count(b"")) print(b"".count(b"a")) print(b"a".count(b"")) print(b"a".count(b"a")) print(b"a".count(b"b")) print(b"b".count(b"a")) print(b"aaa".count(b"")) print(b"aaa".count(b"a")) print(b"aaa".count(b"aa")) print(b"aaa".count(b"aaa")) print(b"aaa".count(b"aaaa")) print(b"aaaa".count(b"")) print(b"aaaa".count(b"a")) print(b"aaaa".count(b"aa")) print(b"aaaa".count(b"aaa")) print(b"aaaa".count(b"aaaa")) print(b"aaaa".count(b"aaaaa")) print(b"aaa".count(b"", 1)) print(b"aaa".count(b"", 2)) print(b"aaa".count(b"", 3)) print(b"aaa".count(b"", 1, 2)) print(b"asdfasdfaaa".count(b"asdf", -100)) print(b"asdfasdfaaa".count(b"asdf", -8)) print(b"asdf".count(b's', True)) print(b"asdf".count(b'a', True)) print(b"asdf".count(b'a', False)) print(b"asdf".count(b'a', 1 == 2)) print(b"hello world".count(b'l')) print(b"hello world".count(b'l', 5)) print(b"hello world".count(b'l', 3)) print(b"hello world".count(b'z', 3, 6)) print(b"aaaa".count(b'a')) print(b"aaaa".count(b'a', 0, 3)) print(b"aaaa".count(b'a', 0, 4)) print(b"aaaa".count(b'a', 0, 5)) print(b"aaaa".count(b'a', 1, 5)) print(b"aaaa".count(b'a', -1, 5)) print(b"abbabba".count(b"abba")) def t(): return True print(b"0000".count(b'0', t())) micropython-1.12/tests/basics/bytes_find.py000066400000000000000000000015721357706137100211350ustar00rootroot00000000000000print(b"hello world".find(b"ll")) print(b"hello world".find(b"ll", None)) print(b"hello world".find(b"ll", 1)) print(b"hello world".find(b"ll", 1, None)) print(b"hello world".find(b"ll", None, None)) print(b"hello world".find(b"ll", 1, -1)) print(b"hello world".find(b"ll", 1, 1)) print(b"hello world".find(b"ll", 1, 2)) print(b"hello world".find(b"ll", 1, 3)) print(b"hello world".find(b"ll", 1, 4)) print(b"hello world".find(b"ll", 1, 5)) print(b"hello world".find(b"ll", -100)) print(b"0000".find(b'0')) print(b"0000".find(b'0', 0)) print(b"0000".find(b'0', 1)) print(b"0000".find(b'0', 2)) print(b"0000".find(b'0', 3)) print(b"0000".find(b'0', 4)) print(b"0000".find(b'0', 5)) print(b"0000".find(b'-1', 3)) print(b"0000".find(b'1', 3)) print(b"0000".find(b'1', 4)) print(b"0000".find(b'1', 5)) # Non-ascii values (make sure not treated as unicode-like) print(b"\x80abc".find(b"a", 1)) micropython-1.12/tests/basics/bytes_format_modulo.py000066400000000000000000000003361357706137100230610ustar00rootroot00000000000000# This test requires CPython3.5 try: b'' % () except TypeError: print("SKIP") raise SystemExit print(b"%%" % ()) print(b"=%d=" % 1) print(b"=%d=%d=" % (1, 2)) print(b"=%s=" % b"str") print(b"=%r=" % b"str") micropython-1.12/tests/basics/bytes_format_modulo.py.exp000066400000000000000000000000521357706137100236470ustar00rootroot00000000000000b'%' b'=1=' b'=1=2=' b'=str=' b"=b'str'=" micropython-1.12/tests/basics/bytes_gen.py000066400000000000000000000001621357706137100207600ustar00rootroot00000000000000# construct a bytes object from a generator def gen(): for i in range(4): yield i print(bytes(gen())) micropython-1.12/tests/basics/bytes_large.py000066400000000000000000000014601357706137100213030ustar00rootroot00000000000000b1 = b"long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes long bytes" b2 = b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" b"concatenated bytes" micropython-1.12/tests/basics/bytes_mult.py000066400000000000000000000003671357706137100211770ustar00rootroot00000000000000# basic multiplication print(b'0' * 5) # check negative, 0, positive; lhs and rhs multiplication for i in (-4, -2, 0, 2, 4): print(i * b'12') print(b'12' * i) # check that we don't modify existing object a = b'123' c = a * 3 print(a, c) micropython-1.12/tests/basics/bytes_partition.py000066400000000000000000000015041357706137100222210ustar00rootroot00000000000000try: str.partition except AttributeError: print("SKIP") raise SystemExit print(b"asdf".partition(b'g')) print(b"asdf".partition(b'a')) print(b"asdf".partition(b's')) print(b"asdf".partition(b'f')) print(b"asdf".partition(b'd')) print(b"asdf".partition(b'asd')) print(b"asdf".partition(b'sdf')) print(b"asdf".partition(b'as')) print(b"asdf".partition(b'df')) print(b"asdf".partition(b'asdf')) print(b"asdf".partition(b'asdfa')) print(b"asdf".partition(b'fasdf')) print(b"asdf".partition(b'fasdfa')) print(b"abba".partition(b'a')) print(b"abba".partition(b'b')) try: print(b"asdf".partition(1)) except TypeError: print("Raised TypeError") else: print("Did not raise TypeError") try: print(b"asdf".partition(b'')) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") micropython-1.12/tests/basics/bytes_replace.py000066400000000000000000000007041357706137100216240ustar00rootroot00000000000000print(b"".replace(b"a", b"b")) print(b"aaa".replace(b"a", b"b", 0)) print(b"aaa".replace(b"a", b"b", -5)) print(b"asdfasdf".replace(b"a", b"b")) print(b"aabbaabbaabbaa".replace(b"aa", b"cc", 3)) print(b"a".replace(b"aa", b"bb")) print(b"testingtesting".replace(b"ing", b"")) print(b"testINGtesting".replace(b"ing", b"ING!")) print(b"".replace(b"", b"1")) print(b"A".replace(b"", b"1")) print(b"AB".replace(b"", b"1")) print(b"AB".replace(b"", b"12")) micropython-1.12/tests/basics/bytes_split.py000066400000000000000000000013601357706137100213430ustar00rootroot00000000000000# default separator (whitespace) print(b"a b".split()) print(b" a b ".split(None)) print(b" a b ".split(None, 1)) print(b" a b ".split(None, 2)) print(b" a b c ".split(None, 1)) print(b" a b c ".split(None, 0)) print(b" a b c ".split(None, -1)) # empty separator should fail try: b"abc".split(b'') except ValueError: print("ValueError") # non-empty separator print(b"abc".split(b"a")) print(b"abc".split(b"b")) print(b"abc".split(b"c")) print(b"abc".split(b"z")) print(b"abc".split(b"ab")) print(b"abc".split(b"bc")) print(b"abc".split(b"abc")) print(b"abc".split(b"abcd")) print(b"abcabc".split(b"bc")) print(b"abcabc".split(b"bc", 0)) print(b"abcabc".split(b"bc", 1)) print(b"abcabc".split(b"bc", 2)) micropython-1.12/tests/basics/bytes_strip.py000066400000000000000000000006511357706137100213530ustar00rootroot00000000000000print(b"".strip()) print(b" \t\n\r\v\f".strip()) print(b" T E S T".strip()) print(b"abcabc".strip(b"ce")) print(b"aaa".strip(b"b")) print(b"abc efg ".strip(b"g a")) print(b' spacious '.lstrip()) print(b'www.example.com'.lstrip(b'cmowz.')) print(b' spacious '.rstrip()) print(b'mississippi'.rstrip(b'ipz')) # Test that stripping unstrippable string returns original object s = b"abc" print(id(s.strip()) == id(s)) micropython-1.12/tests/basics/bytes_subscr.py000066400000000000000000000003151357706137100215100ustar00rootroot00000000000000# test [...] of bytes print(b'123'[0]) print(b'123'[1]) print(b'123'[-1]) try: b'123'[1] = 4 except TypeError: print('TypeError') try: del b'123'[1] except TypeError: print('TypeError') micropython-1.12/tests/basics/class1.py000066400000000000000000000005321357706137100201700ustar00rootroot00000000000000# basic class def go(): class C: def f(): print(1) def g(self): print(2) def set(self, value): self.value = value def print(self): print(self.value) C.f() C() C().g() o = C() o.set(3) o.print() C.set(o, 4) C.print(o) go() micropython-1.12/tests/basics/class2.py000066400000000000000000000005521357706137100201730ustar00rootroot00000000000000# class with __init__ class C1: def __init__(self): self.x = 1 c1 = C1() print(type(c1) == C1) print(c1.x) class C2: def __init__(self, x): self.x = x c2 = C2(4) print(type(c2) == C2) print(c2.x) # __init__ should return None class C3: def __init__(self): return 10 try: C3() except TypeError: print('TypeError') micropython-1.12/tests/basics/class3.py000066400000000000000000000005171357706137100201750ustar00rootroot00000000000000# inheritance class A: def a(): print('A.a() called') class B(A): pass print(type(A)) print(type(B)) print(issubclass(A, A)) print(issubclass(A, B)) print(issubclass(B, A)) print(issubclass(B, B)) print(isinstance(A(), A)) print(isinstance(A(), B)) print(isinstance(B(), A)) print(isinstance(B(), B)) A.a() B.a() micropython-1.12/tests/basics/class_bases.py000066400000000000000000000015661357706137100212740ustar00rootroot00000000000000# test for type.__bases__ implementation if not hasattr(object, '__bases__'): print("SKIP") raise SystemExit class A: pass class B(object): pass class C(B): pass class D(C, A): pass # Check the attribute exists print(hasattr(A, '__bases__')) print(hasattr(B, '__bases__')) print(hasattr(C, '__bases__')) print(hasattr(D, '__bases__')) # Check it is always a tuple print(type(A.__bases__) == tuple) print(type(B.__bases__) == tuple) print(type(C.__bases__) == tuple) print(type(D.__bases__) == tuple) # Check size print(len(A.__bases__) == 1) print(len(B.__bases__) == 1) print(len(C.__bases__) == 1) print(len(D.__bases__) == 2) # Check values print(A.__bases__[0] == object) print(B.__bases__[0] == object) print(C.__bases__[0] == B) print(D.__bases__[0] == C) print(D.__bases__[1] == A) # Object has an empty tuple print(object.__bases__ == tuple()) micropython-1.12/tests/basics/class_bind_self.py000066400000000000000000000023231357706137100221140ustar00rootroot00000000000000# test for correct binding of self when accessing attr of an instance class A: def __init__(self, arg): self.val = arg def __str__(self): return 'A.__str__ ' + str(self.val) def __call__(self, arg): return 'A.__call__', arg def foo(self, arg): return 'A.foo', self.val, arg def make_closure(x_in): x = x_in def closure(y): return x, y is c return closure class C: # these act like methods and bind self def f1(self, arg): return 'C.f1', self is c, arg f2 = lambda self, arg: ('C.f2', self is c, arg) f3 = make_closure('f3') # closure def f4(self, arg): # generator yield self is c, arg # these act like simple variables and don't bind self f5 = int # builtin type f6 = abs # builtin function f7 = A # user type f8 = A(8) # user instance which is callable f9 = A(9).foo # user bound method c = C() print(c.f1(1)) print(c.f2(2)) print(c.f3()) print(next(c.f4(4))) print(c.f5(5)) #print(c.f6(-6)) not working in uPy print(c.f7(7)) print(c.f8(8)) print(c.f9(9)) # not working in uPy #class C(list): # # this acts like a method and binds self # f1 = list.extend #c = C() #c.f1([3, 1, 2]) #print(c) micropython-1.12/tests/basics/class_binop.py000066400000000000000000000012571357706137100213030ustar00rootroot00000000000000class foo(object): def __init__(self, value): self.x = value def __eq__(self, other): print('eq') return self.x == other.x def __lt__(self, other): print('lt') return self.x < other.x def __gt__(self, other): print('gt') return self.x > other.x def __le__(self, other): print('le') return self.x <= other.x def __ge__(self, other): print('ge') return self.x >= other.x for i in range(3): for j in range(3): print(foo(i) == foo(j)) print(foo(i) < foo(j)) print(foo(i) > foo(j)) print(foo(i) <= foo(j)) print(foo(i) >= foo(j)) micropython-1.12/tests/basics/class_call.py000066400000000000000000000003611357706137100211020ustar00rootroot00000000000000class C1: def __call__(self, val): print('call', val) return 'item' class C2: def __getattr__(self, k): pass c1 = C1() print(c1(1)) c2 = C2() try: print(c2(1)) except TypeError: print("TypeError") micropython-1.12/tests/basics/class_contains.py000066400000000000000000000005761357706137100220150ustar00rootroot00000000000000# A contains everything class A: def __contains__(self, key): return True a = A() print(True in a) print(1 in a) print(() in a) # B contains given things class B: def __init__(self, items): self.items = items def __contains__(self, key): return key in self.items b = B([]) print(1 in b) b = B([1, 2]) print(1 in b) print(2 in b) print(3 in b) micropython-1.12/tests/basics/class_delattr_setattr.py000066400000000000000000000027641357706137100234050ustar00rootroot00000000000000# test __delattr__ and __setattr__ # feature test for __setattr__/__delattr__ try: class Test(): def __delattr__(self, attr): pass del Test().noexist except AttributeError: print('SKIP') raise SystemExit # this class just prints the calls to see if they were executed class A(): def __getattr__(self, attr): print('get', attr) return 1 def __setattr__(self, attr, val): print('set', attr, val) def __delattr__(self, attr): print('del', attr) a = A() # check basic behaviour print(getattr(a, 'foo')) setattr(a, 'bar', 2) delattr(a, 'baz') # check meta behaviour getattr(a, '__getattr__') # should not call A.__getattr__ getattr(a, '__setattr__') # should not call A.__getattr__ getattr(a, '__delattr__') # should not call A.__getattr__ setattr(a, '__setattr__', 1) # should call A.__setattr__ delattr(a, '__delattr__') # should call A.__delattr__ # this class acts like a dictionary class B: def __init__(self, d): # store the dict in the class, not instance, so # we don't get infinite recursion in __getattr_ B.d = d def __getattr__(self, attr): if attr in B.d: return B.d[attr] else: raise AttributeError(attr) def __setattr__(self, attr, value): B.d[attr] = value def __delattr__(self, attr): del B.d[attr] a = B({"a":1, "b":2}) print(a.a, a.b) a.a = 3 print(a.a, a.b) del a.a try: print(a.a) except AttributeError: print("AttributeError") micropython-1.12/tests/basics/class_descriptor.py000066400000000000000000000011531357706137100223450ustar00rootroot00000000000000class Descriptor: def __get__(self, obj, cls): print('get') print(type(obj) is Main) print(cls is Main) return 'result' def __set__(self, obj, val): print('set') print(type(obj) is Main) print(val) def __delete__(self, obj): print('delete') print(type(obj) is Main) class Main: Forward = Descriptor() m = Main() try: m.__class__ except AttributeError: print("SKIP") raise SystemExit r = m.Forward if 'Descriptor' in repr(r.__class__): print('SKIP') raise SystemExit print(r) m.Forward = 'a' del m.Forward micropython-1.12/tests/basics/class_emptybases.py000066400000000000000000000000241357706137100223370ustar00rootroot00000000000000class A(): pass micropython-1.12/tests/basics/class_getattr.py000066400000000000000000000006611357706137100216440ustar00rootroot00000000000000# test that __getattr__ and instance members don't override builtins class C: def __init__(self): self.__add__ = lambda: print('member __add__') def __add__(self, x): print('__add__') def __getattr__(self, attr): print('__getattr__', attr) return None c = C() c.add # should call __getattr__ c.__add__() # should load __add__ instance directly c + 1 # should call __add__ method directly micropython-1.12/tests/basics/class_inherit1.py000066400000000000000000000005101357706137100217060ustar00rootroot00000000000000class A: def __init__(self, x): print('A init', x) self.x = x def f(self): print(self.x, self.y) class B(A): def __init__(self, x, y): A.__init__(self, x) print('B init', x, y) self.y = y def g(self): print(self.x, self.y) A(1) b = B(1, 2) b.f() b.g() micropython-1.12/tests/basics/class_inherit_mul.py000066400000000000000000000011701357706137100225050ustar00rootroot00000000000000# test multiple inheritance of user classes class A: def __init__(self, x): print('A init', x) self.x = x def f(self): print(self.x) def f2(self): print(self.x) class B: def __init__(self, x): print('B init', x) self.x = x def f(self): print(self.x) def f3(self): print(self.x) class Sub(A, B): def __init__(self): A.__init__(self, 1) B.__init__(self, 2) print('Sub init') def g(self): print(self.x) print(issubclass(Sub, A)) print(issubclass(Sub, B)) o = Sub() print(o.x) o.f() o.f2() o.f3() micropython-1.12/tests/basics/class_inplace_op.py000066400000000000000000000015471357706137100223070ustar00rootroot00000000000000# Case 1: Immutable object (e.g. number-like) # __iadd__ should not be defined, will be emulated using __add__ class A: def __init__(self, v): self.v = v def __add__(self, o): return A(self.v + o.v) def __repr__(self): return "A({})".format(self.v) a = A(5) b = a a += A(3) print(a) # Should be original a's value, i.e. A(5) print(b) # Case 2: Mutable object (e.g. list-like) # __iadd__ should be defined class L: def __init__(self, v): self.v = v def __add__(self, o): # Should not be caled in this test print("L.__add__") return L(self.v + o.v) def __iadd__(self, o): self.v += o.v return self def __repr__(self): return "L({})".format(self.v) c = L([1, 2]) d = c c += L([3, 4]) print(c) # Should be updated c's value, i.e. L([1, 2, 3, 4]) print(d) micropython-1.12/tests/basics/class_instance_override.py000066400000000000000000000002511357706137100236700ustar00rootroot00000000000000# test that we can override a class method with an instance method class A: def foo(self): return 1 a = A() print(a.foo()) a.foo = lambda:2 print(a.foo()) micropython-1.12/tests/basics/class_item.py000066400000000000000000000006631357706137100211320ustar00rootroot00000000000000# test class with __getitem__, __setitem__, __delitem__ methods class C: def __getitem__(self, item): print('get', item) return 'item' def __setitem__(self, item, value): print('set', item, value) def __delitem__(self, item): print('del', item) c = C() print(c[1]) c[1] = 2 del c[3] # index not supported class A: pass a = A() try: a[1] except TypeError: print('TypeError') micropython-1.12/tests/basics/class_misc.py000066400000000000000000000001771357706137100211270ustar00rootroot00000000000000# converting user instance to buffer class C: pass c = C() try: d = bytes(c) except TypeError: print('TypeError') micropython-1.12/tests/basics/class_new.py000066400000000000000000000023461357706137100207650ustar00rootroot00000000000000try: # If we don't expose object.__new__ (small ports), there's # nothing to test. object.__new__ except AttributeError: print("SKIP") raise SystemExit class A: def __new__(cls): print("A.__new__") return super(cls, A).__new__(cls) def __init__(self): print("A.__init__") def meth(self): print('A.meth') #print(A.__new__) #print(A.__init__) a = A() a.meth() a = A.__new__(A) a.meth() #print(a.meth) #print(a.__init__) #print(a.__new__) # __new__ should automatically be a staticmethod, so this should work a = a.__new__(A) a.meth() # __new__ returns not an instance of the class (None here), __init__ # should not be called class B: def __new__(self, v1, v2): print("B.__new__", v1, v2) def __init__(self, v1, v2): # Should not be called in this test print("B.__init__", v1, v2) print("B inst:", B(1, 2)) # Variation of the above, __new__ returns an instance of another class, # __init__ should not be called class Dummy: pass class C: def __new__(cls): print("C.__new__") return Dummy() def __init__(self): # Should not be called in this test print("C.__init__") c = C() print(isinstance(c, Dummy)) micropython-1.12/tests/basics/class_notimpl.py000066400000000000000000000015771357706137100216630ustar00rootroot00000000000000# Test that returning of NotImplemented from binary op methods leads to # TypeError. try: NotImplemented except NameError: print("SKIP") raise SystemExit class C: def __init__(self, value): self.value = value def __str__(self): return "C({})".format(self.value) def __add__(self, rhs): print(self, '+', rhs) return NotImplemented def __sub__(self, rhs): print(self, '-', rhs) return NotImplemented def __lt__(self, rhs): print(self, '<', rhs) return NotImplemented def __neg__(self): print('-', self) return NotImplemented c = C(0) try: c + 1 except TypeError: print("TypeError") try: c - 2 except TypeError: print("TypeError") try: c < 1 except TypeError: print("TypeError") # NotImplemented isn't handled specially in unary methods print(-c) micropython-1.12/tests/basics/class_number.py000066400000000000000000000004121357706137100214540ustar00rootroot00000000000000# test class with __add__ and __sub__ methods class C: def __init__(self, value): self.value = value def __add__(self, rhs): print(self.value, '+', rhs) def __sub__(self, rhs): print(self.value, '-', rhs) c = C(0) c + 1 c - 2 micropython-1.12/tests/basics/class_reverse_op.py000066400000000000000000000005111357706137100223350ustar00rootroot00000000000000class A: def __init__(self, v): self.v = v def __add__(self, o): if isinstance(o, A): return A(self.v + o.v) return A(self.v + o) def __radd__(self, o): return A(self.v + o) def __repr__(self): return "A({})".format(self.v) print(A(3) + 1) print(2 + A(5)) micropython-1.12/tests/basics/class_staticclassmethod.py000066400000000000000000000014041357706137100237040ustar00rootroot00000000000000# test static and class methods class C: @staticmethod def f(rhs): print('f', rhs) @classmethod def g(self, rhs): print('g', rhs) # builtin wrapped in staticmethod @staticmethod def __sub__(rhs): print('sub', rhs) # builtin wrapped in classmethod @classmethod def __add__(self, rhs): print('add', rhs) # subscript special methods wrapped in staticmethod @staticmethod def __getitem__(item): print('static get', item) return 'item' @staticmethod def __setitem__(item, value): print('static set', item, value) @staticmethod def __delitem__(item): print('static del', item) c = C() c.f(0) c.g(0) c - 1 c + 2 print(c[1]) c[1] = 2 del c[3] micropython-1.12/tests/basics/class_store.py000066400000000000000000000002661357706137100213270ustar00rootroot00000000000000# store to class vs instance class C: pass c = C() c.x = 1 print(c.x) C.x = 2 C.y = 3 print(c.x, c.y) print(C.x, C.y) print(C().x, C().y) c = C() print(c.x) c.x = 4 print(c.x) micropython-1.12/tests/basics/class_store_class.py000066400000000000000000000027201357706137100225110ustar00rootroot00000000000000# Inspired by urlparse.py from CPython 3.3 stdlib # There was a bug in MicroPython that under some conditions class stored # in instance attribute later was returned "bound" as if it was a method, # which caused class constructor to receive extra argument. try: from collections import namedtuple except ImportError: try: from ucollections import namedtuple except ImportError: print("SKIP") raise SystemExit _DefragResultBase = namedtuple('DefragResult', [ 'foo', 'bar' ]) class _ResultMixinStr(object): def encode(self): return self._encoded_counterpart(*(x.encode() for x in self)) class _ResultMixinBytes(object): def decode(self): return self._decoded_counterpart(*(x.decode() for x in self)) class DefragResult(_DefragResultBase, _ResultMixinStr): pass class DefragResultBytes(_DefragResultBase, _ResultMixinBytes): pass DefragResult._encoded_counterpart = DefragResultBytes DefragResultBytes._decoded_counterpart = DefragResult # Due to differences in type and native subclass printing, # the best thing we can do here is to just test that no exceptions # happen #print(DefragResult, DefragResult._encoded_counterpart) #print(DefragResultBytes, DefragResultBytes._decoded_counterpart) o1 = DefragResult("a", "b") #print(o1, type(o1)) o2 = DefragResultBytes("a", "b") #print(o2, type(o2)) #print(o1._encoded_counterpart) _o1 = o1.encode() print(_o1[0], _o1[1]) #print(_o1, type(_o1)) print("All's ok") micropython-1.12/tests/basics/class_str.py000066400000000000000000000014321357706137100207770ustar00rootroot00000000000000class C1: def __init__(self, value): self.value = value def __str__(self): return "str".format(self.value) class C2: def __init__(self, value): self.value = value def __repr__(self): return "repr".format(self.value) class C3: def __init__(self, value): self.value = value def __str__(self): return "str".format(self.value) def __repr__(self): return "repr".format(self.value) c1 = C1(1) print(c1) c2 = C2(2) print(c2) s11 = str(c1) print(s11) # This will use builtin repr(), which uses id(), which is of course different # between CPython and MicroPython s12 = repr(c1) print("C1 object at" in s12) s21 = str(c2) print(s21) s22 = repr(c2) print(s22) c3 = C3(1) print(c3) micropython-1.12/tests/basics/class_super.py000066400000000000000000000017711357706137100213330ustar00rootroot00000000000000class Base: def __init__(self): self.a = 1 def meth(self): print("in Base meth", self.a) class Sub(Base): def meth(self): print("in Sub meth") return super().meth() a = Sub() a.meth() # printing super class A: def p(self): print(str(super())[:18]) A().p() # test compiler's handling of long expressions with super class A: bar = 123 def foo(self): print('A foo') return [1, 2, 3] class B(A): def foo(self): print('B foo') print(super().bar) # accessing attribute after super() return super().foo().count(2) # calling a subsequent method print(B().foo()) # first arg to super must be a type try: super(1, 1) except TypeError: print('TypeError') # store/delete of super attribute not allowed assert hasattr(super(B, B()), 'foo') try: super(B, B()).foo = 1 except AttributeError: print('AttributeError') try: del super(B, B()).foo except AttributeError: print('AttributeError') micropython-1.12/tests/basics/class_super_aslocal.py000066400000000000000000000002321357706137100230200ustar00rootroot00000000000000# test using the name "super" as a local variable class A: def foo(self): super = [1, 2] super.pop() print(super) A().foo() micropython-1.12/tests/basics/class_super_closure.py000066400000000000000000000010501357706137100230550ustar00rootroot00000000000000# test that no-arg super() works when self is closed over class A: def __init__(self): self.val = 4 def foo(self): # we access a member of self to check that self is correct return list(range(self.val)) class B(A): def foo(self): # self is closed over because it's referenced in the list comprehension # and then super() must detect this and load from the closure cell return [self.bar(i) for i in super().foo()] def bar(self, x): return 2 * x print(A().foo()) print(B().foo()) micropython-1.12/tests/basics/class_super_multinherit.py000066400000000000000000000003521357706137100237510ustar00rootroot00000000000000# test super with multiple inheritance class A: def foo(self): print('A.foo') class B: def foo(self): print('B.foo') class C(A, B): def foo(self): print('C.foo') super().foo() C().foo() micropython-1.12/tests/basics/class_super_object.py000066400000000000000000000007001357706137100226500ustar00rootroot00000000000000# Calling object.__init__() via super().__init__ try: # If we don't expose object.__init__ (small ports), there's # nothing to test. object.__init__ except AttributeError: print("SKIP") raise SystemExit class Test(object): def __init__(self): super().__init__() print("Test.__init__") t = Test() class Test2: def __init__(self): super().__init__() print("Test2.__init__") t = Test2() micropython-1.12/tests/basics/class_use_other.py000066400000000000000000000002461357706137100221660ustar00rootroot00000000000000# check that we can use an instance of B in a method of A class A: def store(a, b): a.value = b class B: pass b = B() A.store(b, 1) print(b.value) micropython-1.12/tests/basics/closure1.py000066400000000000000000000003271357706137100205410ustar00rootroot00000000000000# closures def f(x): y = 2 * x def g(z): return y + z return g print(f(1)(1)) x = f(2) y = f(3) print(x(1), x(2), x(3)) print(y(1), y(2), y(3)) print(x(1), x(2), x(3)) print(y(1), y(2), y(3)) micropython-1.12/tests/basics/closure2.py000066400000000000000000000003651357706137100205440ustar00rootroot00000000000000# closures; closing over an argument def f(x): y = 2 * x def g(z): return x + y + z return g print(f(1)(1)) x = f(2) y = f(3) print(x(1), x(2), x(3)) print(y(1), y(2), y(3)) print(x(1), x(2), x(3)) print(y(1), y(2), y(3)) micropython-1.12/tests/basics/closure_defargs.py000066400000000000000000000002321357706137100221460ustar00rootroot00000000000000# test closure with default args def f(): a = 1 def bar(b = 10, c = 20): print(a + b + c) bar() bar(2) bar(2, 3) print(f()) micropython-1.12/tests/basics/closure_manyvars.py000066400000000000000000000002571357706137100224020ustar00rootroot00000000000000# test closure with lots of closed over variables def f(): a, b, c, d, e, f, g, h = [i for i in range(8)] def x(): print(a, b, c, d, e, f, g, h) x() f() micropython-1.12/tests/basics/closure_namedarg.py000066400000000000000000000001771357706137100223210ustar00rootroot00000000000000# test passing named arg to closed-over function def f(): x = 1 def g(z): print(x, z) return g f()(z=42) micropython-1.12/tests/basics/compare_multi.py000066400000000000000000000001101357706137100216320ustar00rootroot00000000000000print(1 < 2 < 3) print(1 < 2 < 3 < 4) print(1 > 2 < 3) print(1 < 2 > 3) micropython-1.12/tests/basics/comprehension1.py000066400000000000000000000006451357706137100217410ustar00rootroot00000000000000def f(): # list comprehension print([a + 1 for a in range(5)]) print([(a, b) for a in range(3) for b in range(2)]) print([a * 2 for a in range(7) if a > 3]) print([a for a in [1, 3, 5]]) print([a for a in [a for a in range(4)]]) # dict comprehension d = {a : 2 * a for a in range(5)} print(d[0], d[1], d[2], d[3], d[4]) # set comprehension # see set_comprehension.py f() micropython-1.12/tests/basics/containment.py000066400000000000000000000024561357706137100213300ustar00rootroot00000000000000# sets, see set_containment for i in 1, 2: for o in {1:2}, {1:2}.keys(): print("{} in {}: {}".format(i, o, i in o)) print("{} not in {}: {}".format(i, o, i not in o)) haystack = "supercalifragilistc" for needle in [haystack[i:] for i in range(len(haystack))]: print(needle, "in", haystack, "::", needle in haystack) print(needle, "not in", haystack, "::", needle not in haystack) print(haystack, "in", needle, "::", haystack in needle) print(haystack, "not in", needle, "::", haystack not in needle) for needle in [haystack[:i+1] for i in range(len(haystack))]: print(needle, "in", haystack, "::", needle in haystack) print(needle, "not in", haystack, "::", needle not in haystack) print(haystack, "in", needle, "::", haystack in needle) print(haystack, "not in", needle, "::", haystack not in needle) # containment of bytes/ints in bytes print(b'' in b'123') print(b'0' in b'123', b'1' in b'123') print(48 in b'123', 49 in b'123') # containment of int in str is an error try: 1 in '123' except TypeError: print('TypeError') # until here, the tests would work without the 'second attempt' iteration thing. for i in 1, 2: for o in [], [1], [1, 2]: print("{} in {}: {}".format(i, o, i in o)) print("{} not in {}: {}".format(i, o, i not in o)) micropython-1.12/tests/basics/continue.py000066400000000000000000000003721357706137100206300ustar00rootroot00000000000000for i in range(4): print('one', i) if i > 2: continue print('two', i) for i in range(4): print('one', i) if i < 2: continue print('two', i) for i in [1, 2, 3, 4]: if i == 3: continue print(i) micropython-1.12/tests/basics/decorator.py000066400000000000000000000004041357706137100207620ustar00rootroot00000000000000# test decorators def dec(f): print('dec') return f def dec_arg(x): print(x) return lambda f:f # plain decorator @dec def f(): pass # decorator with arg @dec_arg('dec_arg') def g(): pass # decorator of class @dec class A: pass micropython-1.12/tests/basics/del_attr.py000066400000000000000000000011531357706137100206000ustar00rootroot00000000000000class C: def f(): pass # del a class attribute del C.f try: print(C.x) except AttributeError: print("AttributeError") try: del C.f except AttributeError: print("AttributeError") # del an instance attribute c = C() c.x = 1 print(c.x) del c.x try: print(c.x) except AttributeError: print("AttributeError") try: del c.x except AttributeError: print("AttributeError") # try to del an attribute of a built-in class try: del int.to_bytes except (AttributeError, TypeError): # uPy raises AttributeError, CPython raises TypeError print('AttributeError/TypeError') micropython-1.12/tests/basics/del_deref.py000066400000000000000000000005401357706137100207120ustar00rootroot00000000000000def f(): x = 1 y = 2 def g(): nonlocal x print(y) try: print(x) except NameError: print("NameError") def h(): nonlocal x print(y) try: del x except NameError: print("NameError") print(x, y) del x g() h() f() micropython-1.12/tests/basics/del_global.py000066400000000000000000000013341357706137100210670ustar00rootroot00000000000000# del global def do_del(): global x del x x = 1 print(x) do_del() try: print(x) except NameError: print("NameError") try: do_del() except: # NameError: # FIXME uPy returns KeyError for this print("NameError") # delete globals using a list a = 1 del (a,) try: print(a) except NameError: print("NameError") a = 2 b = 3 del (a, b) try: print(a) except NameError: print("NameError") try: print(b) except NameError: print("NameError") a = 1 b = 2 c = 3 del (a, b, c) try: print(a) except NameError: print("NameError") try: print(b) except NameError: print("NameError") try: print(c) except NameError: print("NameError") a = 1 b = 2 c = 3 del (a, (b, c)) micropython-1.12/tests/basics/del_local.py000066400000000000000000000005711357706137100207230ustar00rootroot00000000000000# delete local then try to reference it def f(): x = 1 y = 2 print(x, y) del x print(y) try: print(x) except NameError: print("NameError"); f() # delete local then try to delete it again def g(): x = 3 y = 4 print(x, y) del x print(y) try: del x except NameError: print("NameError"); g() micropython-1.12/tests/basics/del_name.py000066400000000000000000000003451357706137100205500ustar00rootroot00000000000000# del name x = 1 print(x) del x try: print(x) except NameError: print("NameError") try: del x except: # NameError: # FIXME uPy returns KeyError for this print("NameError") class C: def f(): pass micropython-1.12/tests/basics/del_subscr.py000066400000000000000000000002711357706137100211270ustar00rootroot00000000000000l = [1, 2, 3] print(l) del l[0] print(l) del l[-1] print(l) d = {1:2, 3:4, 5:6} del d[1] del d[3] print(d) del d[5] print(d) # delete nested subscr d = {0:{0:0}} del d[0][0] print(d) micropython-1.12/tests/basics/deque1.py000066400000000000000000000020311357706137100201620ustar00rootroot00000000000000try: try: from ucollections import deque except ImportError: from collections import deque except ImportError: print("SKIP") raise SystemExit d = deque((), 2) print(len(d)) print(bool(d)) try: d.popleft() except IndexError: print("IndexError") print(d.append(1)) print(len(d)) print(bool(d)) print(d.popleft()) print(len(d)) d.append(2) print(d.popleft()) d.append(3) d.append(4) print(len(d)) print(d.popleft(), d.popleft()) try: d.popleft() except IndexError: print("IndexError") d.append(5) d.append(6) d.append(7) print(len(d)) print(d.popleft(), d.popleft()) print(len(d)) try: d.popleft() except IndexError: print("IndexError") # Case where get index wraps around when appending to full deque d = deque((), 2) d.append(1) d.append(2) d.append(3) d.append(4) d.append(5) print(d.popleft(), d.popleft()) # Negative maxlen is not allowed try: deque((), -1) except ValueError: print("ValueError") # Unsupported unary op try: ~d except TypeError: print("TypeError") micropython-1.12/tests/basics/deque2.py000066400000000000000000000021321357706137100201650ustar00rootroot00000000000000# Tests for deques with "check overflow" flag and other extensions # wrt to CPython. try: try: from ucollections import deque except ImportError: from collections import deque except ImportError: print("SKIP") raise SystemExit # Initial sequence is not supported try: deque([1, 2, 3], 10) except ValueError: print("ValueError") # Not even empty list, only empty tuple try: deque([], 10) except ValueError: print("ValueError") # Only fixed-size deques are supported, so length arg is mandatory try: deque(()) except TypeError: print("TypeError") d = deque((), 2, True) try: d.popleft() except IndexError: print("IndexError") print(d.append(1)) print(d.popleft()) d.append(2) print(d.popleft()) d.append(3) d.append(4) print(d.popleft(), d.popleft()) try: d.popleft() except IndexError as e: print(repr(e)) d.append(5) d.append(6) print(len(d)) try: d.append(7) except IndexError as e: print(repr(e)) print(len(d)) print(d.popleft(), d.popleft()) print(len(d)) try: d.popleft() except IndexError as e: print(repr(e)) micropython-1.12/tests/basics/deque2.py.exp000066400000000000000000000002001357706137100207520ustar00rootroot00000000000000ValueError ValueError TypeError IndexError None 1 2 3 4 IndexError('empty',) 2 IndexError('full',) 2 5 6 0 IndexError('empty',) micropython-1.12/tests/basics/dict1.py000066400000000000000000000012301357706137100200020ustar00rootroot00000000000000# basic dictionary d = {} print(d) d[2] = 123 print(d) d = {1:2} d[3] = 3 print(len(d), d[1], d[3]) d[1] = 0 print(len(d), d[1], d[3]) print(str(d) == '{1: 0, 3: 3}' or str(d) == '{3: 3, 1: 0}') x = 1 while x < 100: d[x] = x x += 1 print(d[50]) # equality operator on dicts of different size print({} == {1:1}) # equality operator on dicts of same size but with different keys print({1:1} == {2:1}) # value not found try: {}[0] except KeyError as er: print('KeyError', er, er.args) # unsupported unary op try: +{} except TypeError: print('TypeError') # unsupported binary op try: {} + {} except TypeError: print('TypeError') micropython-1.12/tests/basics/dict2.py000066400000000000000000000003411357706137100200050ustar00rootroot00000000000000# using strings as keys in dict d = {'1': 1, '2': 2} print(d['1'], d['2']) d['3'] = 3 print(d['1'], d['2'], d['3']) d['2'] = 222 print(d['1'], d['2'], d['3']) d2 = dict(d) print('2' in d2) print(id(d) != id(d2), d == d2) micropython-1.12/tests/basics/dict_clear.py000066400000000000000000000001051357706137100210670ustar00rootroot00000000000000d = {1: 2, 3: 4} print(len(d)) d.clear() print(d) d[2] = 42 print(d) micropython-1.12/tests/basics/dict_construct.py000066400000000000000000000002761357706137100220360ustar00rootroot00000000000000# dict constructor d = dict() print(d) d = dict({1:2}) print(d) d = dict(a=1) print(d) d = dict({1:2}, a=3) print(d[1], d['a']) d = dict([(1, 2)], a=3, b=4) print(d[1], d['a'], d['b']) micropython-1.12/tests/basics/dict_copy.py000066400000000000000000000001441357706137100207560ustar00rootroot00000000000000a = {i: 2*i for i in range(100)} b = a.copy() for i in range(100): print(i, b[i]) print(len(b)) micropython-1.12/tests/basics/dict_del.py000066400000000000000000000010431357706137100205470ustar00rootroot00000000000000for n in range(20): print('testing dict with {} items'.format(n)) for i in range(n): # create dict d = dict() for j in range(n): d[str(j)] = j print(len(d)) # delete an item del d[str(i)] print(len(d)) # check items for j in range(n): if str(j) in d: if j == i: print(j, 'in d, but it should not be') else: if j != i: print(j, 'not in d, but it should be') micropython-1.12/tests/basics/dict_fixed.py000066400000000000000000000015341357706137100211070ustar00rootroot00000000000000# test that fixed dictionaries cannot be modified try: import uerrno except ImportError: print("SKIP") raise SystemExit # Save a copy of uerrno.errorcode, so we can check later # that it hasn't been modified. errorcode_copy = uerrno.errorcode.copy() try: uerrno.errorcode.popitem() except TypeError: print("TypeError") try: uerrno.errorcode.pop(0) except TypeError: print("TypeError") try: uerrno.errorcode.setdefault(0, 0) except TypeError: print("TypeError") try: uerrno.errorcode.update([(1, 2)]) except TypeError: print("TypeError") try: del uerrno.errorcode[1] except TypeError: print("TypeError") try: uerrno.errorcode[1] = 'foo' except TypeError: print("TypeError") try: uerrno.errorcode.clear() except TypeError: print("TypeError") assert uerrno.errorcode == errorcode_copy micropython-1.12/tests/basics/dict_fixed.py.exp000066400000000000000000000001061357706137100216740ustar00rootroot00000000000000TypeError TypeError TypeError TypeError TypeError TypeError TypeError micropython-1.12/tests/basics/dict_from_iter.py000066400000000000000000000004031357706137100217700ustar00rootroot00000000000000print(dict([(1, "foo")])) d = dict([("foo", "foo2"), ("bar", "baz")]) print(sorted(d.keys())) print(sorted(d.values())) try: dict(((1,),)) except ValueError: print("ValueError") try: dict(((1, 2, 3),)) except ValueError: print("ValueError") micropython-1.12/tests/basics/dict_fromkeys.py000066400000000000000000000002211357706137100216370ustar00rootroot00000000000000d = dict.fromkeys([1, 2, 3, 4]) l = list(d.keys()) l.sort() print(l) d = dict.fromkeys([1, 2, 3, 4], 42) l = list(d.values()) l.sort() print(l) micropython-1.12/tests/basics/dict_fromkeys2.py000066400000000000000000000003011357706137100217200ustar00rootroot00000000000000try: reversed except: print("SKIP") raise SystemExit # argument to fromkeys has no __len__ d = dict.fromkeys(reversed(range(1))) #d = dict.fromkeys((x for x in range(1))) print(d) micropython-1.12/tests/basics/dict_get.py000066400000000000000000000001011357706137100205540ustar00rootroot00000000000000for d in {}, {42:2}: print(d.get(42)) print(d.get(42,2)) micropython-1.12/tests/basics/dict_intern.py000066400000000000000000000004531357706137100213060ustar00rootroot00000000000000# check that interned strings are compared against non-interned strings di = {"key1": "value"} # lookup interned string k = "key1" print(k in di) # lookup non-interned string k2 = "key" + "1" print(k == k2) print(k2 in di) # lookup non-interned string print("".join(['k', 'e', 'y', '1']) in di) micropython-1.12/tests/basics/dict_iterator.py000066400000000000000000000001231357706137100216320ustar00rootroot00000000000000d = {1: 2, 3: 4} els = [] for i in d: els.append((i, d[i])) print(sorted(els)) micropython-1.12/tests/basics/dict_pop.py000066400000000000000000000003551357706137100206060ustar00rootroot00000000000000d = {1: 2, 3: 4} print(d.pop(3), d) print(d) print(d.pop(1, 42), d) print(d.pop(1, 42), d) print(d.pop(1, None), d) try: print(d.pop(1), "!!!",) except KeyError: print("Raised KeyError") else: print("Did not rise KeyError!") micropython-1.12/tests/basics/dict_popitem.py000066400000000000000000000003771357706137100214710ustar00rootroot00000000000000els = [] d = {1:2,3:4} a = d.popitem() print(len(d)) els.append(a) a = d.popitem() print(len(d)) els.append(a) try: print(d.popitem(), "!!!",) except KeyError: print("Raised KeyError") else: print("Did not raise KeyError") print(sorted(els)) micropython-1.12/tests/basics/dict_setdefault.py000066400000000000000000000002771357706137100221530ustar00rootroot00000000000000d = {} print(d.setdefault(1)) print(d.setdefault(1)) print(d.setdefault(5, 42)) print(d.setdefault(5, 1)) print(d[1]) print(d[5]) d.pop(5) print(d.setdefault(5, 1)) print(d[1]) print(d[5]) micropython-1.12/tests/basics/dict_specialmeth.py000066400000000000000000000001731357706137100223040ustar00rootroot00000000000000# dict object with special methods d = {} d.__setitem__('2', 'two') print(d.__getitem__('2')) d.__delitem__('2') print(d) micropython-1.12/tests/basics/dict_update.py000066400000000000000000000003471357706137100212730ustar00rootroot00000000000000d = {1:2, 3:4} print(len(d)) d.update(["ab"]) print(d[1]) print(d[3]) print(d["a"]) print(len(d)) d.update([(1,4)]) print(d[1]) print(len(d)) # using keywords d.update(a=5) print(d['a']) d.update([(1,5)], b=6) print(d[1], d['b']) micropython-1.12/tests/basics/dict_views.py000066400000000000000000000006321357706137100211430ustar00rootroot00000000000000d = {1: 2} for m in d.items, d.values, d.keys: print(m()) print(list(m())) # print a view with more than one item print({1:1, 2:1}.values()) # unsupported binary op on a dict values view try: {1:1}.values() + 1 except TypeError: print('TypeError') # unsupported binary op on a dict keys view try: {1:1}.keys() + 1 except TypeError: print('TypeError') # set operations still to come micropython-1.12/tests/basics/equal.py000066400000000000000000000020231357706137100201060ustar00rootroot00000000000000# test equality print(None == None) print(False == None) print(False == False) print(False == True) print(() == ()) print(() == []) print([] == []) print(() == {}) print({} == ()) print(() == None) print(() == False) print(() == print) print([] == None) print([] == False) print([] == print) print({} == None) print({} == False) print({} == print) print(1 == 1) print(1 == 2) print(1 == ()) print(1 == []) print(1 == {}) print(1 == 'a') print('a' == 'a') print('a' == 'ab') print('a' == 1) print('a' == ()) # same as above but with != print(None != None) print(False != None) print(False != False) print(False != True) print(() != ()) print(() != []) print([] != []) print(() != {}) print({} != ()) print(() != None) print(() != False) print(() != print) print([] != None) print([] != False) print([] != print) print({} != None) print({} != False) print({} != print) print(1 != 1) print(1 != 2) print(1 != ()) print(1 != []) print(1 != {}) print(1 != 'a') print('a' != 'a') print('a' != 'ab') print('a' != 1) print('a' != ()) micropython-1.12/tests/basics/equal_class.py000066400000000000000000000004471357706137100213030ustar00rootroot00000000000000# test equality for classes/instances to other types class A: pass class B: pass class C(A): pass print(A == None) print(None == A) print(A == A) print(A() == A) print(A() == A()) print(A == B) print(A() == B) print(A() == B()) print(A == C) print(A() == C) print(A() == C()) micropython-1.12/tests/basics/errno1.py000066400000000000000000000007001357706137100202050ustar00rootroot00000000000000# test errno's and uerrno module try: import uerrno except ImportError: print("SKIP") raise SystemExit # check that constants exist and are integers print(type(uerrno.EIO)) # check that errors are rendered in a nice way msg = str(OSError(uerrno.EIO)) print(msg[:7], msg[-5:]) # check that unknown errno is still rendered print(str(OSError(9999))) # this tests a failed constant lookup in errno errno = uerrno print(errno.__name__) micropython-1.12/tests/basics/errno1.py.exp000066400000000000000000000000501357706137100207760ustar00rootroot00000000000000 [Errno ] EIO 9999 uerrno micropython-1.12/tests/basics/except_match_tuple.py000066400000000000000000000004741357706137100226640ustar00rootroot00000000000000# test exception matching against a tuple try: fail except (Exception,): print('except 1') try: fail except (Exception, Exception): print('except 2') try: fail except (TypeError, NameError): print('except 3') try: fail except (TypeError, ValueError, Exception): print('except 4') micropython-1.12/tests/basics/exception1.py000066400000000000000000000003621357706137100210620ustar00rootroot00000000000000print(repr(IndexError())) print(str(IndexError())) print(str(IndexError("foo"))) a = IndexError(1, "test", [100, 200]) print(repr(a)) print(str(a)) print(a.args) s = StopIteration() print(s.value) s = StopIteration(1, 2, 3) print(s.value) micropython-1.12/tests/basics/exception_chain.py000066400000000000000000000002561357706137100221450ustar00rootroot00000000000000# Exception chaining is not supported, but check that basic # exception works as expected. try: raise Exception from None except Exception: print("Caught Exception") micropython-1.12/tests/basics/exception_chain.py.exp000066400000000000000000000000731357706137100227350ustar00rootroot00000000000000Warning: exception chaining not supported Caught Exception micropython-1.12/tests/basics/exceptpoly.py000066400000000000000000000033511357706137100212000ustar00rootroot00000000000000try: raise ArithmeticError except Exception: print("Caught ArithmeticError via Exception") try: raise ArithmeticError except ArithmeticError: print("Caught ArithmeticError") try: raise AssertionError except Exception: print("Caught AssertionError via Exception") try: raise AssertionError except AssertionError: print("Caught AssertionError") try: raise AttributeError except Exception: print("Caught AttributeError via Exception") try: raise AttributeError except AttributeError: print("Caught AttributeError") try: raise EOFError except Exception: print("Caught EOFError via Exception") try: raise EOFError except EOFError: print("Caught EOFError") try: raise Exception except BaseException: print("Caught Exception via BaseException") try: raise Exception except Exception: print("Caught Exception") try: raise ImportError except Exception: print("Caught ImportError via Exception") try: raise ImportError except ImportError: print("Caught ImportError") try: raise IndentationError except SyntaxError: print("Caught IndentationError via SyntaxError") try: raise IndentationError except IndentationError: print("Caught IndentationError") try: raise IndexError except LookupError: print("Caught IndexError via LookupError") try: raise IndexError except IndexError: print("Caught IndexError") try: raise KeyError except LookupError: print("Caught KeyError via LookupError") try: raise KeyError except KeyError: print("Caught KeyError") try: raise LookupError except Exception: print("Caught LookupError via Exception") try: raise LookupError except LookupError: print("Caught LookupError") micropython-1.12/tests/basics/exceptpoly2.py000066400000000000000000000033751357706137100212700ustar00rootroot00000000000000try: raise MemoryError except Exception: print("Caught MemoryError via Exception") try: raise MemoryError except MemoryError: print("Caught MemoryError") try: raise NameError except Exception: print("Caught NameError via Exception") try: raise NameError except NameError: print("Caught NameError") try: raise NotImplementedError except RuntimeError: print("Caught NotImplementedError via RuntimeError") try: raise NotImplementedError except NotImplementedError: print("Caught NotImplementedError") try: raise OSError except Exception: print("Caught OSError via Exception") try: raise OSError except OSError: print("Caught OSError") try: raise OverflowError except ArithmeticError: print("Caught OverflowError via ArithmeticError") try: raise OverflowError except OverflowError: print("Caught OverflowError") try: raise RuntimeError except Exception: print("Caught RuntimeError via Exception") try: raise RuntimeError except RuntimeError: print("Caught RuntimeError") try: raise SyntaxError except Exception: print("Caught SyntaxError via Exception") try: raise SyntaxError except SyntaxError: print("Caught SyntaxError") try: raise TypeError except Exception: print("Caught TypeError via Exception") try: raise TypeError except TypeError: print("Caught TypeError") try: raise ValueError except Exception: print("Caught ValueError via Exception") try: raise ValueError except ValueError: print("Caught ValueError") try: raise ZeroDivisionError except ArithmeticError: print("Caught ZeroDivisionError via ArithmeticError") try: raise ZeroDivisionError except ZeroDivisionError: print("Caught ZeroDivisionError") micropython-1.12/tests/basics/floordivide.py000066400000000000000000000003431357706137100213100ustar00rootroot00000000000000# check modulo matches python definition # This tests compiler version print(123 // 7) print(-123 // 7) print(123 // -7) print(-123 // -7) a = 10000001 b = 10000000 print(a // b) print(a // -b) print(-a // b) print(-a // -b) micropython-1.12/tests/basics/floordivide_intbig.py000066400000000000000000000004061357706137100226440ustar00rootroot00000000000000# check modulo matches python definition a = 987654321987987987987987987987 b = 19 print(a // b) print(a // -b) print(-a // b) print(-a // -b) a = 10000000000000000000000000000000000000000000 b = 100 print(a // b) print(a // -b) print(-a // b) print(-a // -b) micropython-1.12/tests/basics/for1.py000066400000000000000000000005471357706137100176570ustar00rootroot00000000000000# basic for loop def f(): for x in range(2): for y in range(2): for z in range(2): print(x, y, z) f() # range with negative step for i in range(3, -1, -1): print(i) a = -1 # range with non-constant step - we optimize constant steps, so this # will be executed differently for i in range(3, -1, a): print(i) micropython-1.12/tests/basics/for2.py000066400000000000000000000002411357706137100176470ustar00rootroot00000000000000i = 'init' for i in range(0): pass print(i) # should not have been modified for i in range(10): pass print(i) # should be last successful value of loop micropython-1.12/tests/basics/for3.py000066400000000000000000000004051357706137100176520ustar00rootroot00000000000000# test assigning to iterator within the loop for i in range(2): print(i) i = 2 # test assigning to range parameter within the loop # (since we optimise for loops, this needs checking, currently it fails) n = 2 for i in range(n): print(i) n = 0 micropython-1.12/tests/basics/for_break.py000066400000000000000000000007551357706137100207430ustar00rootroot00000000000000# Testcase for break in a for [within bunch of other code] # https://github.com/micropython/micropython/issues/635 def foo(): seq = [1, 2, 3] v = 100 i = 5 while i > 0: print(i) for a in seq: if a == 2: break i -= 1 foo() # break from within nested for loop def bar(): l = [1, 2, 3] for e1 in l: print(e1) for e2 in l: print(e1, e2) if e2 == 2: break bar() micropython-1.12/tests/basics/for_else.py000066400000000000000000000013141357706137100205770ustar00rootroot00000000000000# test for-else statement # test optimised range with simple else for i in range(2): print(i) else: print('else') # test optimised range with break over else for i in range(2): print(i) break else: print('else') # test nested optimised range with continue in the else for i in range(4): print(i) for j in range(4): pass else: continue break # test optimised range with non-constant end value N = 2 for i in range(N): print(i) else: print('else') # test generic iterator with simple else for i in [0, 1]: print(i) else: print('else') # test generic iterator with break over else for i in [0, 1]: print(i) break else: print('else') micropython-1.12/tests/basics/for_range.py000066400000000000000000000024461357706137100207520ustar00rootroot00000000000000# test for+range, mostly to check optimisation of this pair # apply args using * for x in range(*(1, 3)): print(x) for x in range(1, *(6, 2)): print(x) # zero step try: for x in range(1, 2, 0): pass except ValueError: print('ValueError') # apply args using ** try: for x in range(**{'end':1}): print(x) except TypeError: print('TypeError') try: for x in range(0, **{'end':1}): print(x) except TypeError: print('TypeError') try: for x in range(0, 1, **{'step':1}): print(x) except TypeError: print('TypeError') # keyword args try: for x in range(end=1): print(x) except TypeError: print('TypeError') try: for x in range(0, end=1): print(x) except TypeError: print('TypeError') try: for x in range(start=0, end=1): print(x) except TypeError: print('TypeError') try: for x in range(0, 1, step=1): print(x) except TypeError: print('TypeError') # argument is a comprehension try: for x in range(0 for i in []): print(x) except TypeError: print('TypeError') try: for x in range(0, (0 for i in [])): print(x) except TypeError: print('TypeError') try: for x in range(0, 1, (0 for i in [])): print(x) except TypeError: print('TypeError') micropython-1.12/tests/basics/for_return.py000066400000000000000000000001471357706137100211710ustar00rootroot00000000000000# test returning from within a for loop def f(): for i in [1, 2, 3]: return i print(f()) micropython-1.12/tests/basics/frozenset1.py000066400000000000000000000004011357706137100210750ustar00rootroot00000000000000# basic sets try: frozenset except NameError: print("SKIP") raise SystemExit s = frozenset() print(s) s = frozenset({1}) print(s) s = frozenset({3, 4, 3, 1}) print(sorted(s)) # frozensets are hashable unlike sets print({frozenset("1"): 2}) micropython-1.12/tests/basics/frozenset_add.py000066400000000000000000000004071357706137100216320ustar00rootroot00000000000000try: frozenset except NameError: print("SKIP") raise SystemExit s = frozenset({1, 2, 3, 4}) try: print(s.add(5)) except AttributeError: print("AttributeError") try: print(s.update([5])) except AttributeError: print("AttributeError") micropython-1.12/tests/basics/frozenset_binop.py000066400000000000000000000023131357706137100222070ustar00rootroot00000000000000try: frozenset except NameError: print("SKIP") raise SystemExit sets = [ frozenset(), frozenset({1}), frozenset({1, 2}), frozenset({1, 2, 3}), frozenset({2, 3}), frozenset({2, 3, 5}), frozenset({5}), frozenset({7}) ] for s in sets: for t in sets: print(sorted(s), '|', sorted(t), '=', sorted(s | t)) print(sorted(s), '^', sorted(t), '=', sorted(s ^ t)) print(sorted(s), '&', sorted(t), '=', sorted(s & t)) print(sorted(s), '-', sorted(t), '=', sorted(s - t)) u = s.copy() u |= t print(sorted(s), "|=", sorted(t), '-->', sorted(u)) u = s.copy() u ^= t print(sorted(s), "^=", sorted(t), '-->', sorted(u)) u = s.copy() u &= t print(sorted(s), "&=", sorted(t), "-->", sorted(u)) u = s.copy() u -= t print(sorted(s), "-=", sorted(t), "-->", sorted(u)) print(sorted(s), '==', sorted(t), '=', s == t) print(sorted(s), '!=', sorted(t), '=', s != t) print(sorted(s), '>', sorted(t), '=', s > t) print(sorted(s), '>=', sorted(t), '=', s >= t) print(sorted(s), '<', sorted(t), '=', s < t) print(sorted(s), '<=', sorted(t), '=', s <= t) micropython-1.12/tests/basics/frozenset_copy.py000066400000000000000000000002511357706137100220510ustar00rootroot00000000000000try: frozenset except NameError: print("SKIP") raise SystemExit s = frozenset({1, 2, 3, 4}) t = s.copy() print(type(t)) for i in s, t: print(sorted(i)) micropython-1.12/tests/basics/frozenset_difference.py000066400000000000000000000006621357706137100231770ustar00rootroot00000000000000try: frozenset except NameError: print("SKIP") raise SystemExit l = [1, 2, 3, 4] s = frozenset(l) outs = [s.difference(), s.difference(frozenset({1})), s.difference(frozenset({1}), [1, 2]), s.difference(frozenset({1}), {1, 2}, {2, 3})] for out in outs: print(type(out), sorted(out)) s = frozenset(l) try: print(s.difference_update({1})) except AttributeError: print("AttributeError") micropython-1.12/tests/basics/frozenset_set.py000066400000000000000000000005431357706137100216760ustar00rootroot00000000000000try: frozenset except NameError: print("SKIP") raise SystemExit # Examples from https://docs.python.org/3/library/stdtypes.html#set # "Instances of set are compared to instances of frozenset based on their # members. For example:" print(set('abc') == frozenset('abc')) # This doesn't work in uPy #print(set('abc') in set([frozenset('abc')])) micropython-1.12/tests/basics/fun1.py000066400000000000000000000000601357706137100176470ustar00rootroot00000000000000# calling a function def f(): print(1) f() micropython-1.12/tests/basics/fun2.py000066400000000000000000000001541357706137100176540ustar00rootroot00000000000000# calling a function from a function def f(x): print(x + 1) def g(x): f(2 * x) f(4 * x) g(3) micropython-1.12/tests/basics/fun3.py000066400000000000000000000002171357706137100176550ustar00rootroot00000000000000# function with large number of arguments def fun(a, b, c, d, e, f, g): return a + b + c * d + e * f * g print(fun(1, 2, 3, 4, 5, 6, 7)) micropython-1.12/tests/basics/fun_annotations.py000066400000000000000000000001131357706137100222020ustar00rootroot00000000000000def foo(x: int, y: list) -> dict: return {x: y} print(foo(1, [2, 3])) micropython-1.12/tests/basics/fun_calldblstar.py000066400000000000000000000005771357706137100221520ustar00rootroot00000000000000# test calling a function with keywords given by **dict def f(a, b): print(a, b) f(1, **{'b':2}) f(1, **{'b':val for val in range(1)}) try: f(1, **{len:2}) except TypeError: print('TypeError') # test calling a method with keywords given by **dict class A: def f(self, a, b): print(a, b) a = A() a.f(1, **{'b':2}) a.f(1, **{'b':val for val in range(1)}) micropython-1.12/tests/basics/fun_calldblstar2.py000066400000000000000000000007751357706137100222340ustar00rootroot00000000000000# test passing a string object as the key for a keyword argument try: exec except NameError: print("SKIP") raise SystemExit # they key in this dict is a string object and is not interned args = {'thisisaverylongargumentname': 123} # when this string is executed it will intern the keyword argument exec("def foo(*,thisisaverylongargumentname=1):\n print(thisisaverylongargumentname)") # test default arg foo() # the string from the dict should match the interned keyword argument foo(**args) micropython-1.12/tests/basics/fun_calldblstar3.py000066400000000000000000000006051357706137100222250ustar00rootroot00000000000000# test passing a user-defined mapping as the argument to ** def foo(**kw): print(sorted(kw.items())) class Mapping: def keys(self): # the long string checks the case of string interning return ['a', 'b', 'c', 'abcdefghijklmnopqrst'] def __getitem__(self, key): if key == 'a': return 1 else: return 2 foo(**Mapping()) micropython-1.12/tests/basics/fun_callstar.py000066400000000000000000000010741357706137100214610ustar00rootroot00000000000000# function calls with *pos def foo(a, b, c): print(a, b, c) foo(*(1, 2, 3)) foo(1, *(2, 3)) foo(1, 2, *(3,)) foo(1, 2, 3, *()) # Another sequence type foo(1, 2, *[100]) # Iterator foo(*range(3)) # pos then iterator foo(1, *range(2, 4)) # an iterator with many elements def foo(*rest): print(rest) foo(*range(10)) # method calls with *pos class A: def foo(self, a, b, c): print(a, b, c) a = A() a.foo(*(1, 2, 3)) a.foo(1, *(2, 3)) a.foo(1, 2, *(3,)) a.foo(1, 2, 3, *()) # Another sequence type a.foo(1, 2, *[100]) # Iterator a.foo(*range(3)) micropython-1.12/tests/basics/fun_callstardblstar.py000066400000000000000000000006041357706137100230330ustar00rootroot00000000000000# test calling a function with *tuple and **dict def f(a, b, c, d): print(a, b, c, d) f(*(1, 2), **{'c':3, 'd':4}) f(*(1, 2), **{['c', 'd'][i]:(3 + i) for i in range(2)}) # test calling a method with *tuple and **dict class A: def f(self, a, b, c, d): print(a, b, c, d) a = A() a.f(*(1, 2), **{'c':3, 'd':4}) a.f(*(1, 2), **{['c', 'd'][i]:(3 + i) for i in range(2)}) micropython-1.12/tests/basics/fun_defargs.py000066400000000000000000000007011357706137100212630ustar00rootroot00000000000000# testing default args to a function def fun1(val=5): print(val) fun1() fun1(10) def fun2(p1, p2=100, p3="foo"): print(p1, p2, p3) fun2(1) fun2(1, None) fun2(0, "bar", 200) try: fun2() except TypeError: print("TypeError") try: fun2(1, 2, 3, 4) except TypeError: print("TypeError") # lambda as default arg (exposes nested behaviour in compiler) def f(x=lambda:1): return x() print(f()) print(f(f)) print(f(lambda:2)) micropython-1.12/tests/basics/fun_defargs2.py000066400000000000000000000004031357706137100213440ustar00rootroot00000000000000# overriding default arguments def foo(a, b=3): print(a, b) # override with positional foo(1, 333) # override with keyword foo(1, b=333) # override with keyword foo(a=2, b=333) def foo2(a=1, b=2): print(a, b) # default and keyword foo2(b='two') micropython-1.12/tests/basics/fun_error.py000066400000000000000000000016271357706137100210110ustar00rootroot00000000000000# test errors from bad function calls # function doesn't take keyword args try: [].append(x=1) except TypeError: print('TypeError') # function with variable number of positional args given too few try: round() except TypeError: print('TypeError') # function with variable number of positional args given too many try: round(1, 2, 3) except TypeError: print('TypeError') # function with fixed number of positional args given wrong number try: [].append(1, 2) except TypeError: print('TypeError') # function with keyword args given extra positional args try: [].sort(1) except TypeError: print('TypeError') # function with keyword args given extra keyword args try: [].sort(noexist=1) except TypeError: print('TypeError') # kw given for positional, but a different positional is missing try: def f(x, y): pass f(x=1) except TypeError: print('TypeError') micropython-1.12/tests/basics/fun_error2.py000066400000000000000000000003451357706137100210670ustar00rootroot00000000000000# test errors from bad function calls try: enumerate except: print("SKIP") raise SystemExit # function with keyword args not given a specific keyword arg try: enumerate() except TypeError: print('TypeError') micropython-1.12/tests/basics/fun_kwargs.py000066400000000000000000000006571357706137100211600ustar00rootroot00000000000000def f1(a): print(a) f1(123) f1(a=123) try: f1(b=123) except TypeError: print("TypeError") def f2(a, b): print(a, b) f2(1, 2) f2(a=3, b=4) f2(b=5, a=6) f2(7, b=8) try: f2(9, a=10) except TypeError: print("TypeError") def f3(a, b, *args): print(a, b, args) f3(1, b=3) try: f3(1, a=3) except TypeError: print("TypeError") try: f3(1, 2, 3, 4, a=5) except TypeError: print("TypeError") micropython-1.12/tests/basics/fun_kwonly.py000066400000000000000000000015731357706137100212030ustar00rootroot00000000000000# to test keyword-only arguments # simplest case def f(*, a): print(a) f(a=1) # with 2 keyword-only args def f(*, a, b): print(a, b) f(a=1, b=2) f(b=1, a=2) # positional followed by bare star def f(a, *, b, c): print(a, b, c) f(1, b=3, c=4) f(1, c=3, b=4) f(1, **{'b':'3', 'c':4}) try: f(1) except TypeError: print("TypeError") try: f(1, b=2) except TypeError: print("TypeError") try: f(1, c=2) except TypeError: print("TypeError") # with **kw def f(a, *, b, **kw): print(a, b, kw) f(1, b=2) f(1, b=2, c=3) # with named star def f(*a, b, c): print(a, b, c) f(b=1, c=2) f(c=1, b=2) # with positional and named star def f(a, *b, c): print(a, b, c) f(1, c=2) f(1, 2, c=3) f(a=1, c=3) # lambda as kw-only arg (exposes nested behaviour in compiler) def f(*, x=lambda:1): return x() print(f()) print(f(x=f)) print(f(x=lambda:2)) micropython-1.12/tests/basics/fun_kwonlydef.py000066400000000000000000000012701357706137100216540ustar00rootroot00000000000000# test function args, keyword only with default value # a single arg with a default def f1(*, a=1): print(a) f1() f1(a=2) # 1 arg default, 1 not def f2(*, a=1, b): print(a, b) f2(b=2) f2(a=2, b=3) # 1 positional, 1 arg default, 1 not def f3(a, *, b=2, c): print(a, b, c) f3(1, c=3) f3(1, b=3, c=4) f3(1, **{'c':3}) f3(1, **{'b':'3', 'c':4}) # many args, not all with defaults def f4(*, a=1, b, c=3, d, e=5, f): print(a, b, c, d, e, f) f4(b=2, d=4, f=6) f4(a=11, b=2, d=4, f=6) f4(a=11, b=2, c=33, d=4, e=55, f=6) f4(f=6, e=55, d=4, c=33, b=2, a=11) # positional with default, then keyword only def f5(a, b=4, *c, d=8): print(a, b, c, d) f5(1) f5(1, d=9) f5(1, b=44, d=9) micropython-1.12/tests/basics/fun_kwvarargs.py000066400000000000000000000004651357706137100216660ustar00rootroot00000000000000def f1(**kwargs): print(kwargs) f1() f1(a=1) def f2(a, **kwargs): print(a, kwargs) f2(1) f2(1, b=2) def f3(a, *vargs, **kwargs): print(a, vargs, kwargs) f3(1) f3(1, 2) f3(1, b=2) f3(1, 2, b=3) def f4(*vargs, **kwargs): print(vargs, kwargs) f4(*(1, 2)) f4(kw_arg=3) f4(*(1, 2), kw_arg=3) micropython-1.12/tests/basics/fun_largestate.py000066400000000000000000000045411357706137100220110ustar00rootroot00000000000000# test large function (stack) state # this function creates 127 locals def f(): x0 = 1 x1 = 1 x2 = 1 x3 = 1 x4 = 1 x5 = 1 x6 = 1 x7 = 1 x8 = 1 x9 = 1 x10 = 1 x11 = 1 x12 = 1 x13 = 1 x14 = 1 x15 = 1 x16 = 1 x17 = 1 x18 = 1 x19 = 1 x20 = 1 x21 = 1 x22 = 1 x23 = 1 x24 = 1 x25 = 1 x26 = 1 x27 = 1 x28 = 1 x29 = 1 x30 = 1 x31 = 1 x32 = 1 x33 = 1 x34 = 1 x35 = 1 x36 = 1 x37 = 1 x38 = 1 x39 = 1 x40 = 1 x41 = 1 x42 = 1 x43 = 1 x44 = 1 x45 = 1 x46 = 1 x47 = 1 x48 = 1 x49 = 1 x50 = 1 x51 = 1 x52 = 1 x53 = 1 x54 = 1 x55 = 1 x56 = 1 x57 = 1 x58 = 1 x59 = 1 x60 = 1 x61 = 1 x62 = 1 x63 = 1 x64 = 1 x65 = 1 x66 = 1 x67 = 1 x68 = 1 x69 = 1 x70 = 1 x71 = 1 x72 = 1 x73 = 1 x74 = 1 x75 = 1 x76 = 1 x77 = 1 x78 = 1 x79 = 1 x80 = 1 x81 = 1 x82 = 1 x83 = 1 x84 = 1 x85 = 1 x86 = 1 x87 = 1 x88 = 1 x89 = 1 x90 = 1 x91 = 1 x92 = 1 x93 = 1 x94 = 1 x95 = 1 x96 = 1 x97 = 1 x98 = 1 x99 = 1 x100 = 1 x101 = 1 x102 = 1 x103 = 1 x104 = 1 x105 = 1 x106 = 1 x107 = 1 x108 = 1 x109 = 1 x110 = 1 x111 = 1 x112 = 1 x113 = 1 x114 = 1 x115 = 1 x116 = 1 x117 = 1 x118 = 1 x119 = 1 x120 = 1 x121 = 1 x122 = 1 x123 = 1 x124 = 1 x125 = 1 x126 = 1 f() # this function pushes 128 elements onto the function stack def g(): x = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,] g() # this function exercises load_fast_n and store_fast_n opcodes def h(): x0 = 1 x1 = x0 x2 = x1 x3 = x2 x4 = x3 x5 = x4 x6 = x5 x7 = x6 x8 = x7 x9 = x8 x10 = x9 x11 = x10 x12 = x11 x13 = x12 x14 = x13 x15 = x14 x16 = x15 x17 = x16 h() micropython-1.12/tests/basics/fun_name.py000066400000000000000000000011351357706137100205720ustar00rootroot00000000000000def Fun(): pass class A: def __init__(self): pass def Fun(self): pass try: print(Fun.__name__) print(A.__init__.__name__) print(A.Fun.__name__) print(A().Fun.__name__) except AttributeError: print('SKIP') raise SystemExit # __name__ of a bound native method is not implemented in uPy # the test here is to make sure it doesn't crash try: str((1).to_bytes.__name__) except AttributeError: pass # name of a function that has closed over variables def outer(): x = 1 def inner(): return x return inner print(outer.__name__) micropython-1.12/tests/basics/fun_str.py000066400000000000000000000000741357706137100204630ustar00rootroot00000000000000# test str of function def f(): pass print(str(f)[:8]) micropython-1.12/tests/basics/fun_varargs.py000066400000000000000000000010561357706137100213210ustar00rootroot00000000000000# function with just varargs def f1(*args): print(args) f1() f1(1) f1(1, 2) # function with 1 arg, then varargs def f2(a, *args): print(a, args) f2(1) f2(1, 2) f2(1, 2, 3) # function with 2 args, then varargs def f3(a, b, *args): print(a, b, args) f3(1, 2) f3(1, 2, 3) f3(1, 2, 3, 4) # function with 1 default arg, then varargs def f4(a=0, *args): print(a, args) f4() f4(1) f4(1, 2) f4(1, 2, 3) # function with 1 arg, 1 default arg, then varargs def f5(a, b=0, *args): print(a, b, args) f5(1) f5(1, 2) f5(1, 2, 3) f5(1, 2, 3, 4) micropython-1.12/tests/basics/gc1.py000066400000000000000000000013771357706137100174640ustar00rootroot00000000000000# basic tests for gc module try: import gc except ImportError: print("SKIP") raise SystemExit print(gc.isenabled()) gc.disable() print(gc.isenabled()) gc.enable() print(gc.isenabled()) gc.collect() if hasattr(gc, 'mem_free'): # uPy has these extra functions # just test they execute and return an int assert type(gc.mem_free()) is int assert type(gc.mem_alloc()) is int if hasattr(gc, 'threshold'): # uPy has this extra function # check execution and returns assert(gc.threshold(1) is None) assert(gc.threshold() == 0) assert(gc.threshold(-1) is None) assert(gc.threshold() == -1) # Setting a low threshold should trigger collection at the list alloc gc.threshold(1) [[], []] gc.threshold(-1) micropython-1.12/tests/basics/gen_yield_from.py000066400000000000000000000007431357706137100217700ustar00rootroot00000000000000# Case of terminating subgen using return with value def gen(): yield 1 yield 2 return 3 def gen2(): print("here1") print((yield from gen())) print("here2") g = gen2() print(list(g)) # StopIteration from within a Python function, within a native iterator (map), within a yield from def gen7(x): if x < 3: return x else: raise StopIteration(444) def gen8(): print((yield from map(gen7, range(100)))) g = gen8() print(list(g)) micropython-1.12/tests/basics/gen_yield_from_close.py000066400000000000000000000042541357706137100231560ustar00rootroot00000000000000def gen(): yield 1 yield 2 yield 3 yield 4 def gen2(): yield -1 print((yield from gen())) yield 10 yield 11 g = gen2() print(next(g)) print(next(g)) g.close() try: print(next(g)) except StopIteration: print("StopIteration") # Now variation of same test, but with leaf generator # swallowing GeneratorExit exception - its upstream gen # generator should still receive one. def gen3(): yield 1 try: yield 2 except GeneratorExit: print("leaf caught GeneratorExit and swallowed it") return yield 3 yield 4 def gen4(): yield -1 try: print((yield from gen3())) except GeneratorExit: print("delegating caught GeneratorExit") raise yield 10 yield 11 g = gen4() print(next(g)) print(next(g)) print(next(g)) g.close() try: print(next(g)) except StopIteration: print("StopIteration") # Yet another variation - leaf generator gets GeneratorExit, # and reraises a new GeneratorExit. This still should close chain properly. def gen5(): yield 1 try: yield 2 except GeneratorExit: print("leaf caught GeneratorExit and reraised GeneratorExit") raise GeneratorExit(123) yield 3 yield 4 def gen6(): yield -1 try: print((yield from gen5())) except GeneratorExit: print("delegating caught GeneratorExit") raise yield 10 yield 11 g = gen6() print(next(g)) print(next(g)) print(next(g)) g.close() try: print(next(g)) except StopIteration: print("StopIteration") # case where generator ignores the close request and yields instead def gen7(): try: yield 123 except GeneratorExit: yield 456 g = gen7() print(next(g)) try: g.close() except RuntimeError: print('RuntimeError') # case where close is propagated up to a built-in iterator def gen8(): g = range(2) yield from g g = gen8() print(next(g)) g.close() # case with a user-defined close method class Iter: def __iter__(self): return self def __next__(self): return 1 def close(self): print('close') def gen9(): yield from Iter() g = gen9() print(next(g)) g.close() micropython-1.12/tests/basics/gen_yield_from_ducktype.py000066400000000000000000000020121357706137100236670ustar00rootroot00000000000000class MyGen: def __init__(self): self.v = 0 def __iter__(self): return self def __next__(self): self.v += 1 if self.v > 5: raise StopIteration return self.v def gen(): yield from MyGen() def gen2(): yield from gen() print(list(gen())) print(list(gen2())) class Incrementer: def __iter__(self): return self def __next__(self): return self.send(None) def send(self, val): if val is None: return "Incrementer initialized" return val + 1 def gen3(): yield from Incrementer() g = gen3() print(next(g)) print(g.send(5)) print(g.send(100)) # # Test proper handling of StopIteration vs other exceptions # class MyIter: def __iter__(self): return self def __next__(self): raise StopIteration(42) def gen4(): global ret ret = yield from MyIter() 1//0 ret = None try: print(list(gen4())) except ZeroDivisionError: print("ZeroDivisionError") print(ret) micropython-1.12/tests/basics/gen_yield_from_exc.py000066400000000000000000000003251357706137100226230ustar00rootroot00000000000000def gen(): yield 1 yield 2 raise ValueError def gen2(): try: print((yield from gen())) except ValueError: print("caught ValueError from downstream") g = gen2() print(list(g)) micropython-1.12/tests/basics/gen_yield_from_executing.py000066400000000000000000000003751357706137100240440ustar00rootroot00000000000000# yielding from an already executing generator is not allowed def f(): yield 1 # g here is already executing so this will raise an exception yield from g g = f() print(next(g)) try: next(g) except ValueError: print('ValueError') micropython-1.12/tests/basics/gen_yield_from_iter.py000066400000000000000000000002611357706137100230060ustar00rootroot00000000000000def gen(): yield from (1, 2, 3) def gen2(): yield from gen() def gen3(): yield from (4, 5) yield 6 print(list(gen())) print(list(gen2())) print(list(gen3())) micropython-1.12/tests/basics/gen_yield_from_send.py000066400000000000000000000003271357706137100227770ustar00rootroot00000000000000def gen(): print("sent:", (yield 1)) yield 2 def gen2(): print((yield from gen())) g = gen2() next(g) print("yielded:", g.send("val")) try: next(g) except StopIteration: print("StopIteration") micropython-1.12/tests/basics/gen_yield_from_stopped.py000066400000000000000000000004751357706137100235300ustar00rootroot00000000000000# Yielding from stopped generator is ok and results in None def gen(): return 1 # This yield is just to make this a generator yield f = gen() def run(): print((yield from f)) print((yield from f)) print((yield from f)) try: next(run()) except StopIteration: print("StopIteration") micropython-1.12/tests/basics/gen_yield_from_throw.py000066400000000000000000000020401357706137100232030ustar00rootroot00000000000000def gen(): try: yield 1 except ValueError as e: print("got ValueError from upstream!", repr(e.args)) yield "str1" raise TypeError def gen2(): print((yield from gen())) g = gen2() print(next(g)) print(g.throw(ValueError)) try: print(next(g)) except TypeError: print("got TypeError from downstream!") # passing None as second argument to throw g = gen2() print(next(g)) print(g.throw(ValueError, None)) try: print(next(g)) except TypeError: print("got TypeError from downstream!") # passing an exception instance as second argument to throw g = gen2() print(next(g)) print(g.throw(ValueError, ValueError(123))) try: print(next(g)) except TypeError: print("got TypeError from downstream!") # thrown value is caught and then generator returns normally def gen(): try: yield 123 except ValueError: print('ValueError') # return normally after catching thrown exception def gen2(): yield from gen() yield 789 g = gen2() print(next(g)) print(g.throw(ValueError)) micropython-1.12/tests/basics/gen_yield_from_throw2.py000066400000000000000000000006711357706137100232750ustar00rootroot00000000000000# outer generator ignores a thrown GeneratorExit (this is allowed) def gen(): try: yield 123 except GeneratorExit: print('GeneratorExit') def gen2(): try: yield from gen() except GeneratorExit: print('GeneratorExit outer') yield 789 # thrown a class g = gen2() print(next(g)) print(g.throw(GeneratorExit)) # thrown an instance g = gen2() print(next(g)) print(g.throw(GeneratorExit())) micropython-1.12/tests/basics/gen_yield_from_throw3.py000066400000000000000000000020061357706137100232700ustar00rootroot00000000000000# yield-from a user-defined generator with a throw() method class Iter: def __iter__(self): return self def __next__(self): return 1 def throw(self, x): print('throw', x) return 456 def gen(): yield from Iter() # calling close() should not call throw() g = gen() print(next(g)) g.close() # can throw a non-exception object g = gen() print(next(g)) print(g.throw(123)) # throwing an exception class just injects that class g = gen() print(next(g)) print(g.throw(ZeroDivisionError)) # this user-defined generator doesn't have a throw() method class Iter2: def __iter__(self): return self def __next__(self): return 1 def gen2(): yield from Iter2() # the thrown ValueError is not intercepted by the user class g = gen2() print(next(g)) try: g.throw(ValueError) except: print('ValueError') # the thrown 123 is not an exception so raises a TypeError g = gen2() print(next(g)) try: g.throw(123) except TypeError: print('TypeError') micropython-1.12/tests/basics/generator1.py000066400000000000000000000006461357706137100210570ustar00rootroot00000000000000def f(x): print('a') y = x print('b') while y > 0: print('c') y -= 1 print('d') yield y print('e') print('f') return None for val in f(3): print(val) #gen = f(3) #print(gen) #print(gen.__next__()) #print(gen.__next__()) #print(gen.__next__()) #print(gen.__next__()) # test printing, but only the first chars that match CPython print(repr(f(0))[0:17]) micropython-1.12/tests/basics/generator2.py000066400000000000000000000000701357706137100210470ustar00rootroot00000000000000gen = (i for i in range(10)) for i in gen: print(i) micropython-1.12/tests/basics/generator_args.py000066400000000000000000000005421357706137100220050ustar00rootroot00000000000000# Handling of "complicated" arg forms to generators # https://github.com/micropython/micropython/issues/397 def gen(v=5): for i in range(v): yield i print(list(gen())) print(list(gen(v=10))) def g(*args, **kwargs): for i in args: yield i for k, v in kwargs.items(): yield (k, v) print(list(g(1, 2, 3, foo="bar"))) micropython-1.12/tests/basics/generator_close.py000066400000000000000000000020021357706137100221470ustar00rootroot00000000000000def gen1(): yield 1 yield 2 # Test that it's possible to close just created gen g = gen1() print(g.close()) try: next(g) except StopIteration: print("StopIteration") # Test that it's possible to close gen in progress g = gen1() print(next(g)) print(g.close()) try: next(g) print("No StopIteration") except StopIteration: print("StopIteration") # Test that it's possible to close finished gen g = gen1() print(list(g)) print(g.close()) try: next(g) print("No StopIteration") except StopIteration: print("StopIteration") # Throwing GeneratorExit in response to close() is ok def gen2(): try: yield 1 yield 2 except: print('raising GeneratorExit') raise GeneratorExit g = gen2() next(g) print(g.close()) # Any other exception is propagated to the .close() caller def gen3(): try: yield 1 yield 2 except: raise ValueError g = gen3() next(g) try: print(g.close()) except ValueError: print("ValueError") micropython-1.12/tests/basics/generator_closure.py000066400000000000000000000012711357706137100225250ustar00rootroot00000000000000# a generator that closes over outer variables def f(): x = 1 # closed over by g def g(): yield x yield x + 1 return g() for i in f(): print(i) # a generator that has its variables closed over def f(): x = 1 # closed over by g def g(): return x + 1 yield g() x = 2 yield g() for i in f(): print(i) # using comprehensions, the inner generator closes over y generator_of_generators = (((x, y) for x in range(2)) for y in range(3)) for i in generator_of_generators: for j in i: print(j) # test that printing of closed-over generators doesn't lead to segfaults def genc(): foo = 1 repr(lambda: (yield foo)) genc() micropython-1.12/tests/basics/generator_exc.py000066400000000000000000000016131357706137100216300ustar00rootroot00000000000000# Test proper handling of exceptions within generator across yield def gen(): try: yield 1 raise ValueError except ValueError: print("Caught") yield 2 for i in gen(): print(i) # Test throwing exceptions out of generator def gen2(): yield 1 raise ValueError yield 2 yield 3 g = gen2() print(next(g)) try: print(next(g)) except ValueError: print("ValueError") try: print(next(g)) except StopIteration: print("StopIteration") # Test throwing exception into generator def gen3(): yield 1 try: yield 2 except ValueError: print("ValueError received") yield 3 yield 4 yield 5 g = gen3() print(next(g)) print(next(g)) print("out of throw:", g.throw(ValueError)) print(next(g)) try: print("out of throw2:", g.throw(ValueError)) except ValueError: print("Boomerang ValueError caught") micropython-1.12/tests/basics/generator_name.py000066400000000000000000000003721357706137100217720ustar00rootroot00000000000000# test __name__ on generator functions def Fun(): yield class A: def Fun(self): yield try: print(Fun.__name__) print(A.Fun.__name__) print(A().Fun.__name__) except AttributeError: print('SKIP') raise SystemExit micropython-1.12/tests/basics/generator_pend_throw.py000066400000000000000000000034361357706137100232270ustar00rootroot00000000000000def gen(): i = 0 while 1: yield i i += 1 g = gen() try: g.pend_throw except AttributeError: print("SKIP") raise SystemExit # Verify that an injected exception will be raised from next(). print(next(g)) print(next(g)) g.pend_throw(ValueError()) v = None try: v = next(g) except Exception as e: print("raised", repr(e)) print("ret was:", v) # Verify that pend_throw works on an unstarted coroutine. g = gen() g.pend_throw(OSError()) try: next(g) except Exception as e: print("raised", repr(e)) # Verify that you can't resume the coroutine from within the running coroutine. def gen_next(): next(g) yield 1 g = gen_next() try: next(g) except Exception as e: print("raised", repr(e)) # Verify that you can't pend_throw from within the running coroutine. def gen_pend_throw(): g.pend_throw(ValueError()) yield 1 g = gen_pend_throw() try: next(g) except Exception as e: print("raised", repr(e)) # Verify that the pend_throw exception can be ignored. class CancelledError(Exception): pass def gen_cancelled(): for i in range(5): try: yield i except CancelledError: print('ignore CancelledError') g = gen_cancelled() print(next(g)) g.pend_throw(CancelledError()) print(next(g)) # ...but not if the generator hasn't started. g = gen_cancelled() g.pend_throw(CancelledError()) try: next(g) except Exception as e: print("raised", repr(e)) # Verify that calling pend_throw returns the previous exception. g = gen() next(g) print(repr(g.pend_throw(CancelledError()))) print(repr(g.pend_throw(OSError))) # Verify that you can pend_throw(None) to cancel a previous pend_throw. g = gen() next(g) g.pend_throw(CancelledError()) print(repr(g.pend_throw(None))) print(next(g)) micropython-1.12/tests/basics/generator_pend_throw.py.exp000066400000000000000000000003661357706137100240210ustar00rootroot000000000000000 1 raised ValueError() ret was: None raised OSError() raised ValueError('generator already executing',) raised ValueError('generator already executing',) 0 ignore CancelledError 1 raised CancelledError() None CancelledError() CancelledError() 1 micropython-1.12/tests/basics/generator_pep479.py000066400000000000000000000015511357706137100221020ustar00rootroot00000000000000# tests for correct PEP479 behaviour (introduced in Python 3.5) # basic case: StopIteration is converted into a RuntimeError def gen(): yield 1 raise StopIteration g = gen() print(next(g)) try: next(g) except RuntimeError: print('RuntimeError') # trying to continue a failed generator now raises StopIteration try: next(g) except StopIteration: print('StopIteration') # throwing a StopIteration which is uncaught will be converted into a RuntimeError def gen(): yield 1 yield 2 g = gen() print(next(g)) try: g.throw(StopIteration) except RuntimeError: print('RuntimeError') # throwing a StopIteration through yield from, will be converted to a RuntimeError def gen(): yield from range(2) print('should not get here') g = gen() print(next(g)) try: g.throw(StopIteration) except RuntimeError: print('RuntimeError') micropython-1.12/tests/basics/generator_pep479.py.exp000066400000000000000000000000731357706137100226730ustar00rootroot000000000000001 RuntimeError StopIteration 1 RuntimeError 0 RuntimeError micropython-1.12/tests/basics/generator_return.py000066400000000000000000000004351357706137100223710ustar00rootroot00000000000000def gen(): yield 1 return 42 g = gen() print(next(g)) try: print(next(g)) except StopIteration as e: print(type(e), e.args) # trying next again should raise StopIteration with no arguments try: print(next(g)) except StopIteration as e: print(type(e), e.args) micropython-1.12/tests/basics/generator_send.py000066400000000000000000000007701357706137100220050ustar00rootroot00000000000000def f(): n = 0 while True: n = yield n + 1 print(n) g = f() try: g.send(1) except TypeError: print("caught") print(g.send(None)) print(g.send(100)) print(g.send(200)) def f2(): print("entering") for i in range(3): print(i) yield print("returning 1") print("returning 2") g = f2() g.send(None) g.send(1) g.send(1) try: g.send(1) except StopIteration: print("caught") try: g.send(1) except StopIteration: print("caught") micropython-1.12/tests/basics/generator_throw.py000066400000000000000000000020271357706137100222140ustar00rootroot00000000000000# case where generator doesn't intercept the thrown/injected exception def gen(): yield 123 yield 456 g = gen() print(next(g)) try: g.throw(KeyError) except KeyError: print('got KeyError from downstream!') # case where a thrown exception is caught and stops the generator def gen(): try: yield 1 yield 2 except: pass g = gen() print(next(g)) try: g.throw(ValueError) except StopIteration: print('got StopIteration') # generator ignores a thrown GeneratorExit (this is allowed) def gen(): try: yield 123 except GeneratorExit as e: print('GeneratorExit', repr(e.args)) yield 456 # thrown a class g = gen() print(next(g)) print(g.throw(GeneratorExit)) # thrown an instance g = gen() print(next(g)) print(g.throw(GeneratorExit())) # thrown an instance with None as second arg g = gen() print(next(g)) print(g.throw(GeneratorExit(), None)) # thrown a class and instance g = gen() print(next(g)) print(g.throw(GeneratorExit, GeneratorExit(123))) micropython-1.12/tests/basics/getattr.py000066400000000000000000000010071357706137100204520ustar00rootroot00000000000000# test __getattr__ class A: def __init__(self, d): self.d = d def __getattr__(self, attr): return self.d[attr] a = A({'a':1, 'b':2}) print(a.a, a.b) # test that any exception raised in __getattr__ propagates out class A: def __getattr__(self, attr): if attr == "value": raise ValueError(123) else: raise AttributeError(456) a = A() try: a.value except ValueError as er: print(er) try: a.attr except AttributeError as er: print(er) micropython-1.12/tests/basics/getitem.py000066400000000000000000000013041357706137100204360ustar00rootroot00000000000000# create a class that has a __getitem__ method class A: def __getitem__(self, index): print('getitem', index) if index > 10: raise StopIteration # test __getitem__ A()[0] A()[1] # iterate using a for loop for i in A(): pass # iterate manually it = iter(A()) try: while True: next(it) except StopIteration: pass # this class raises an IndexError to stop the iteration class A: def __getitem__(self, i): raise IndexError print(list(A())) # this class raises a non-StopIteration exception on iteration class A: def __getitem__(self, i): raise TypeError try: for i in A(): pass except TypeError: print("TypeError") micropython-1.12/tests/basics/globals_del.py000066400000000000000000000007321357706137100212530ustar00rootroot00000000000000""" 1 """ def _f(): pass FunctionType = type(_f) LambdaType = type(lambda: None) CodeType = None MappingProxyType = None SimpleNamespace = None def _g(): yield 1 GeneratorType = type(_g()) class _C: def _m(self): pass MethodType = type(_C()._m) BuiltinFunctionType = type(len) BuiltinMethodType = type([].append) del _f # print only the first 8 chars, since we have different str rep to CPython print(str(FunctionType)[:8]) print(str(BuiltinFunctionType)[:8]) micropython-1.12/tests/basics/ifcond.py000066400000000000000000000022161357706137100202450ustar00rootroot00000000000000# test if conditions which are optimised by the compiler if 0: print(5) else: print(6) if 1: print(7) if 2: print(8) if -1: print(9) elif 1: print(10) if 0: print(11) else: print(12) if 0: print(13) elif 1: print(14) if 0: print(15) elif 0: print(16) else: print(17) if not False: print('a') if not True: print('a') else: print('b') if False: print('a') else: print('b') if True: print('a') if (1,): print('a') if not (1,): print('a') else: print('b') f2 = 0 def f(t1, t2, f1): if False: print(1) if True: print(1) if (): print(1) if (1,): print(1) if (1, 2): print(1) if t1 and t2: print(1) if (t1 and t2): # parsed differently to above print(1) if not (t1 and f1): print(1) if t1 or t2: print(1) if (t1 or t2): # parse differently to above print(1) if f1 or t1: print(1) if not (f1 or f2): print(1) if t1 and f1 or t1 and t2: print(1) if (f1 or t1) and (f2 or t2): print(1) f(True, 1, False) micropython-1.12/tests/basics/ifexpr.py000066400000000000000000000001661357706137100203020ustar00rootroot00000000000000# test if-expressions print(1 if 0 else 2) print(3 if 1 else 4) def f(x): print('a' if x else 'b') f([]) f([1]) micropython-1.12/tests/basics/int1.py000066400000000000000000000030551357706137100176600ustar00rootroot00000000000000print(int(False)) print(int(True)) print(int(0)) print(int(1)) print(int(+1)) print(int(-1)) print(int('0')) print(int('+0')) print(int('-0')) print(int('1')) print(int('+1')) print(int('-1')) print(int('01')) print(int('9')) print(int('10')) print(int('+10')) print(int('-10')) print(int('12')) print(int('-12')) print(int('99')) print(int('100')) print(int('314')) print(int(' 314')) print(int('314 ')) print(int(' \t\t 314 \t\t ')) print(int(' 1 ')) print(int(' -3 ')) print(int('0', 10)) print(int('1', 10)) print(int(' \t 1 \t ', 10)) print(int('11', 10)) print(int('11', 16)) print(int('11', 8)) print(int('11', 2)) print(int('11', 36)) print(int('xyz', 36)) print(int('0o123', 0)) print(int('8388607')) print(int('0x123', 16)) print(int('0X123', 16)) print(int('0A', 16)) print(int('0o123', 8)) print(int('0O123', 8)) print(int('0123', 8)) print(int('0b100', 2)) print(int('0B100', 2)) print(int('0100', 2)) print(int(' \t 0o12', 8)) print(int('0o12 \t ', 8)) print(int(b"12", 10)) print(int(b"12")) def test(value, base): try: print(int(value, base)) except ValueError: print('ValueError') test('x', 0) test('1x', 0) test(' 1x', 0) test(' 1' + chr(2) + ' ', 0) test('', 0) test(' ', 0) test(' \t\t ', 0) test('0x', 16) test('0x', 0) test('0o', 8) test('0o', 0) test('0b', 2) test('0b', 0) test('0b2', 2) test('0o8', 8) test('0xg', 16) test('1 1', 16) test('123', 37) # check that we don't parse this as a floating point number print(0x1e+1) # can't convert list to int try: int([]) except TypeError: print("TypeError") micropython-1.12/tests/basics/int2.py000066400000000000000000000001701357706137100176540ustar00rootroot00000000000000# test basic int operations # test conversion of bool on RHS of binary op a = False print(1 + a) a = True print(1 + a) micropython-1.12/tests/basics/int_big1.py000066400000000000000000000055031357706137100205010ustar00rootroot00000000000000# to test arbitrariy precision integers x = 1000000000000000000000000000000 xn = -1000000000000000000000000000000 y = 2000000000000000000000000000000 # printing print(x) print(y) print('%#X' % (x - x)) # print prefix print('{:#,}'.format(x)) # print with commas # addition print(x + 1) print(x + y) print(x + xn == 0) print(bool(x + xn)) # subtraction print(x - 1) print(x - y) print(y - x) print(x - x == 0) print(bool(x - x)) # multiplication print(x * 2) print(x * y) # integer division print(x // 2) print(y // x) # bit inversion print(~x) print(~(-x)) # left shift x = 0x10000000000000000000000 for i in range(32): x = x << 1 print(x) # right shift x = 0x10000000000000000000000 for i in range(32): x = x >> 1 print(x) # left shift of a negative number for i in range(8): print(-10000000000000000000000000 << i) print(-10000000000000000000000001 << i) print(-10000000000000000000000002 << i) print(-10000000000000000000000003 << i) print(-10000000000000000000000004 << i) # right shift of a negative number for i in range(8): print(-10000000000000000000000000 >> i) print(-10000000000000000000000001 >> i) print(-10000000000000000000000002 >> i) print(-10000000000000000000000003 >> i) print(-10000000000000000000000004 >> i) # conversion from string print(int("123456789012345678901234567890")) print(int("-123456789012345678901234567890")) print(int("123456789012345678901234567890abcdef", 16)) print(int("123456789012345678901234567890ABCDEF", 16)) print(int("1234567890abcdefghijklmnopqrstuvwxyz", 36)) # invalid characters in string try: print(int("123456789012345678901234567890abcdef")) except ValueError: print('ValueError'); try: print(int("123456789012345678901234567890\x01")) except ValueError: print('ValueError'); # test constant integer with more than 255 chars x = 0x84ce72aa8699df436059f052ac51b6398d2511e49631bcb7e71f89c499b9ee425dfbc13a5f6d408471b054f2655617cbbaf7937b7c80cd8865cf02c8487d30d2b0fbd8b2c4e102e16d828374bbc47b93852f212d5043c3ea720f086178ff798cc4f63f787b9c2e419efa033e7644ea7936f54462dc21a6c4580725f7f0e7d1aaaaaaa print(x) # test parsing ints just on threshold of small to big # for 32 bit archs x = 1073741823 # small x = -1073741823 # small x = 1073741824 # big x = -1073741824 # big # for nan-boxing with 47-bit small ints print(int('0x3fffffffffff', 16)) # small print(int('-0x3fffffffffff', 16)) # small print(int('0x400000000000', 16)) # big print(int('-0x400000000000', 16)) # big # for 64 bit archs x = 4611686018427387903 # small x = -4611686018427387903 # small x = 4611686018427387904 # big x = -4611686018427387904 # big # sys.maxsize is a constant mpz, so test it's compatible with dynamic ones import sys print(sys.maxsize + 1 - 1 == sys.maxsize) # test extraction of big int value via mp_obj_get_int_maybe x = 1 << 70 print('a' * (x + 4 - x)) micropython-1.12/tests/basics/int_big_add.py000066400000000000000000000004141357706137100212240ustar00rootroot00000000000000# tests transition from small to large int representation by addition # 31-bit overflow i = 0x3fffffff print(i + i) print(-i + -i) # 47-bit overflow i = 0x3fffffffffff print(i + i) print(-i + -i) # 63-bit overflow i = 0x3fffffffffffffff print(i + i) print(-i + -i) micropython-1.12/tests/basics/int_big_and.py000066400000000000000000000017331357706137100212430ustar00rootroot00000000000000print(0 & (1 << 80)) print(0 & (1 << 80) == 0) print(bool(0 & (1 << 80))) a = 0xfffffffffffffffffffffffffffff print(a & (1 << 80)) print((a & (1 << 80)) >> 80) print((a & (1 << 80)) >> 80 == 1) # test negative on rhs a = 123456789012345678901234567890 print(a & -1) print(a & -2) print(a & -2345678901234567890123456789) print(a & (-a)) print(a & (-a - 1)) print(a & (-a + 1)) # test negative on lhs a = 123456789012345678901234567890 print(-1 & a) print(-2 & a) print(-2345678901234567890123456789 & a) print((-a) & a) print((-a) & 0xffffffff) print((-a) & 0xffffffffffffffffffffffffffffffff) print((-a) & 2) print((-(1 << 70)) & 2) # test negative on lhs and rhs mpz = 1 << 70 a = 123456789012345678901234567890 print(-1 & (-a)) print(-2 & (-a)) print(-2345678901234567890123456789 & (-a)) print((-a) & (-a)) print((-a) & (-0xffffffff)) print((-a) & (-0xffffffffffffffffffffffffffffffff)) print((-1) & (-0xffffffffffffffffffffffffffffffff)) print((-a) & (-2)) print((-mpz) & (-2)) micropython-1.12/tests/basics/int_big_and2.py000066400000000000000000000042111357706137100213170ustar00rootroot00000000000000# test + + print( 97989513389222316022151446562729620153292831887555425160965597396 & 23716683549865351578586448630079789776107310103486834795830390982) print( 53817081128841898634258263553430908085326601592682411889506742059 & 37042558948907407488299113387826240429667200950043601129661240876) print( 26167512042587370698808974207700979337713004510730289760097826496 & 98456276326770292376138852628141531773120376436197321310863125849) print( 21085380307304977067262070503651827226504797285572981274069266136 & 15928222825828272388778130358888206480162413547887287646273147570) print( 40827393422334167255488276244226338235131323044408420081160772273 & 63815443187857978125545555033672525708399848575557475462799643340) print( 5181013159871685724135944379095645225188360725917119022722046448 & 59734090450462480092384049604830976376887859531148103803093112493) print( 283894311 & 86526825689187217371383854139783231460931720533100376593106943447) print( 40019818573920230246248826511203818792007462193311949166285967147 & 9487909752) # test - - print( -97989513389222316022151446562729620153292831887555425160965597396 & -23716683549865351578586448630079789776107310103486834795830390982) print( -53817081128841898634258263553430908085326601592682411889506742059 & -37042558948907407488299113387826240429667200950043601129661240876) print( -26167512042587370698808974207700979337713004510730289760097826496 & -98456276326770292376138852628141531773120376436197321310863125849) print( -21085380307304977067262070503651827226504797285572981274069266136 & -15928222825828272388778130358888206480162413547887287646273147570) print( -40827393422334167255488276244226338235131323044408420081160772273 & -63815443187857978125545555033672525708399848575557475462799643340) print( -5181013159871685724135944379095645225188360725917119022722046448 & -59734090450462480092384049604830976376887859531148103803093112493) print( -283894311 & -86526825689187217371383854139783231460931720533100376593106943447) print( -40019818573920230246248826511203818792007462193311949166285967147 & -9487909752) micropython-1.12/tests/basics/int_big_and3.py000066400000000000000000000042111357706137100213200ustar00rootroot00000000000000# test - + print( -97989513389222316022151446562729620153292831887555425160965597396 & 23716683549865351578586448630079789776107310103486834795830390982) print( -53817081128841898634258263553430908085326601592682411889506742059 & 37042558948907407488299113387826240429667200950043601129661240876) print( -26167512042587370698808974207700979337713004510730289760097826496 & 98456276326770292376138852628141531773120376436197321310863125849) print( -21085380307304977067262070503651827226504797285572981274069266136 & 15928222825828272388778130358888206480162413547887287646273147570) print( -40827393422334167255488276244226338235131323044408420081160772273 & 63815443187857978125545555033672525708399848575557475462799643340) print( -5181013159871685724135944379095645225188360725917119022722046448 & 59734090450462480092384049604830976376887859531148103803093112493) print( -283894311 & 86526825689187217371383854139783231460931720533100376593106943447) print( -40019818573920230246248826511203818792007462193311949166285967147 & 9487909752) # test + - print( 97989513389222316022151446562729620153292831887555425160965597396 & -23716683549865351578586448630079789776107310103486834795830390982) print( 53817081128841898634258263553430908085326601592682411889506742059 & -37042558948907407488299113387826240429667200950043601129661240876) print( 26167512042587370698808974207700979337713004510730289760097826496 & -98456276326770292376138852628141531773120376436197321310863125849) print( 21085380307304977067262070503651827226504797285572981274069266136 & -15928222825828272388778130358888206480162413547887287646273147570) print( 40827393422334167255488276244226338235131323044408420081160772273 & -63815443187857978125545555033672525708399848575557475462799643340) print( 5181013159871685724135944379095645225188360725917119022722046448 & -59734090450462480092384049604830976376887859531148103803093112493) print( 283894311 & -86526825689187217371383854139783231460931720533100376593106943447) print( 40019818573920230246248826511203818792007462193311949166285967147 & -9487909752) micropython-1.12/tests/basics/int_big_cmp.py000066400000000000000000000001721357706137100212540ustar00rootroot00000000000000# test bignum comparisons i = 1 << 65 print(i == 0) print(i != 0) print(i < 0) print(i > 0) print(i <= 0) print(i >= 0) micropython-1.12/tests/basics/int_big_div.py000066400000000000000000000006271357706137100212640ustar00rootroot00000000000000for lhs in (1000000000000000000000000, 10000000000100000000000000, 10012003400000000000000007, 12349083434598210349871029923874109871234789): for rhs in range(1, 555): print(lhs // rhs) # these check an edge case on 64-bit machines where two mpz limbs # are used and the most significant one has the MSB set x = 0x8000000000000000 print((x + 1) // x) x = 0x86c60128feff5330 print((x + 1) // x) micropython-1.12/tests/basics/int_big_error.py000066400000000000000000000013151357706137100216260ustar00rootroot00000000000000# test errors operating on bignum i = 1 << 65 try: i << -1 except ValueError: print("ValueError") try: len(i) except TypeError: print("TypeError") try: 1 in i except TypeError: print("TypeError") # overflow because arg of bytearray is being converted to machine int try: bytearray(i) except OverflowError: print('OverflowError') # to test conversion of negative mpz to machine int # (we know << will convert to machine int, even though it fails to do the shift) try: i << (-(i >> 40)) except ValueError: print('ValueError') try: i // 0 except ZeroDivisionError: print('ZeroDivisionError') try: i % 0 except ZeroDivisionError: print('ZeroDivisionError') micropython-1.12/tests/basics/int_big_lshift.py000066400000000000000000000013611357706137100217670ustar00rootroot00000000000000# tests transition from small to large int representation by left-shift operation for i in range(1, 17): for shift in range(70): print(i, '<<', shift, '=', i << shift) # test bit-shifting negative integers for i in range(8): print(-100000000000000000000000000000 << i) print(-100000000000000000000000000001 << i) print(-100000000000000000000000000002 << i) print(-100000000000000000000000000003 << i) print(-100000000000000000000000000004 << i) print(-100000000000000000000000000000 >> i) print(-100000000000000000000000000001 >> i) print(-100000000000000000000000000002 >> i) print(-100000000000000000000000000003 >> i) print(-100000000000000000000000000004 >> i) # shl by zero print((1<<70) << 0) micropython-1.12/tests/basics/int_big_mod.py000066400000000000000000000006611357706137100212570ustar00rootroot00000000000000# test % operation on big integers delta = 100000000000000000000000000000012345 for i in range(11): for j in range(11): x = delta * (i - 5) y = delta * (j - 5) if y != 0: print(x % y) # these check an edge case on 64-bit machines where two mpz limbs # are used and the most significant one has the MSB set x = 0x8000000000000000 print((x + 1) % x) x = 0x86c60128feff5330 print((x + 1) % x) micropython-1.12/tests/basics/int_big_mul.py000066400000000000000000000007051357706137100212740ustar00rootroot00000000000000# tests transition from small to large int representation by multiplication for rhs in range(2, 11): lhs = 1 for k in range(100): res = lhs * rhs print(lhs, '*', rhs, '=', res) lhs = res # below tests pos/neg combinations that overflow small int # 31-bit overflow i = 1 << 20 print(i * i) print(i * -i) print(-i * i) print(-i * -i) # 63-bit overflow i = 1 << 40 print(i * i) print(i * -i) print(-i * i) print(-i * -i) micropython-1.12/tests/basics/int_big_or.py000066400000000000000000000013521357706137100211160ustar00rootroot00000000000000print(0 | (1 << 80)) a = 0xfffffffffffffffffffffffffffff print(a | (1 << 200)) # test + + print(0 | (1 << 80)) print((1 << 80) | (1 << 80)) print((1 << 80) | 0) a = 0xfffffffffffffffffffffffffffff print(a | (1 << 100)) print(a | (1 << 200)) print(a | a == 0) print(bool(a | a)) # test - + print((-1 << 80) | (1 << 80)) print((-1 << 80) | 0) print((-a) | (1 << 100)) print((-a) | (1 << 200)) print((-a) | a == 0) print(bool((-a) | a)) # test + - print(0 | (-1 << 80)) print((1 << 80) | (-1 << 80)) print(a | (-1 << 100)) print(a | (-1 << 200)) print(a | (-a) == 0) print(bool(a | (-a))) # test - - print((-1 << 80) | (-1 << 80)) print((-a) | (-1 << 100)) print((-a) | (-1 << 200)) print((-a) | (-a) == 0) print(bool((-a) | (-a))) micropython-1.12/tests/basics/int_big_or2.py000066400000000000000000000042101357706137100211740ustar00rootroot00000000000000# test + + print( 97989513389222316022151446562729620153292831887555425160965597396 | 23716683549865351578586448630079789776107310103486834795830390982) print( 53817081128841898634258263553430908085326601592682411889506742059 | 37042558948907407488299113387826240429667200950043601129661240876) print( 26167512042587370698808974207700979337713004510730289760097826496 | 98456276326770292376138852628141531773120376436197321310863125849) print( 21085380307304977067262070503651827226504797285572981274069266136 | 15928222825828272388778130358888206480162413547887287646273147570) print( 40827393422334167255488276244226338235131323044408420081160772273 | 63815443187857978125545555033672525708399848575557475462799643340) print( 5181013159871685724135944379095645225188360725917119022722046448 | 59734090450462480092384049604830976376887859531148103803093112493) print( 283894311 | 86526825689187217371383854139783231460931720533100376593106943447) print( 40019818573920230246248826511203818792007462193311949166285967147 | 9487909752) # test - - print( -97989513389222316022151446562729620153292831887555425160965597396 | -23716683549865351578586448630079789776107310103486834795830390982) print( -53817081128841898634258263553430908085326601592682411889506742059 | -37042558948907407488299113387826240429667200950043601129661240876) print( -26167512042587370698808974207700979337713004510730289760097826496 | -98456276326770292376138852628141531773120376436197321310863125849) print( -21085380307304977067262070503651827226504797285572981274069266136 | -15928222825828272388778130358888206480162413547887287646273147570) print( -40827393422334167255488276244226338235131323044408420081160772273 | -63815443187857978125545555033672525708399848575557475462799643340) print( -5181013159871685724135944379095645225188360725917119022722046448 | -59734090450462480092384049604830976376887859531148103803093112493) print( -283894311 | -86526825689187217371383854139783231460931720533100376593106943447) print( -40019818573920230246248826511203818792007462193311949166285967147 | -9487909752) micropython-1.12/tests/basics/int_big_or3.py000066400000000000000000000042111357706137100211760ustar00rootroot00000000000000# test - + print( -97989513389222316022151446562729620153292831887555425160965597396 | 23716683549865351578586448630079789776107310103486834795830390982) print( -53817081128841898634258263553430908085326601592682411889506742059 | 37042558948907407488299113387826240429667200950043601129661240876) print( -26167512042587370698808974207700979337713004510730289760097826496 | 98456276326770292376138852628141531773120376436197321310863125849) print( -21085380307304977067262070503651827226504797285572981274069266136 | 15928222825828272388778130358888206480162413547887287646273147570) print( -40827393422334167255488276244226338235131323044408420081160772273 | 63815443187857978125545555033672525708399848575557475462799643340) print( -5181013159871685724135944379095645225188360725917119022722046448 | 59734090450462480092384049604830976376887859531148103803093112493) print( -283894311 | 86526825689187217371383854139783231460931720533100376593106943447) print( -40019818573920230246248826511203818792007462193311949166285967147 | 9487909752) # test + - print( 97989513389222316022151446562729620153292831887555425160965597396 | -23716683549865351578586448630079789776107310103486834795830390982) print( 53817081128841898634258263553430908085326601592682411889506742059 | -37042558948907407488299113387826240429667200950043601129661240876) print( 26167512042587370698808974207700979337713004510730289760097826496 | -98456276326770292376138852628141531773120376436197321310863125849) print( 21085380307304977067262070503651827226504797285572981274069266136 | -15928222825828272388778130358888206480162413547887287646273147570) print( 40827393422334167255488276244226338235131323044408420081160772273 | -63815443187857978125545555033672525708399848575557475462799643340) print( 5181013159871685724135944379095645225188360725917119022722046448 | -59734090450462480092384049604830976376887859531148103803093112493) print( 283894311 | -86526825689187217371383854139783231460931720533100376593106943447) print( 40019818573920230246248826511203818792007462193311949166285967147 | -9487909752) micropython-1.12/tests/basics/int_big_pow.py000066400000000000000000000001321357706137100212760ustar00rootroot00000000000000# test bignum power i = 1 << 65 print(0 ** i) print(i ** 0) print(i ** 1) print(i ** 2) micropython-1.12/tests/basics/int_big_rshift.py000066400000000000000000000002431357706137100217730ustar00rootroot00000000000000i = 123456789012345678901234567890 print(i >> 1) print(i >> 1000) # result needs rounding up i = -(1 << 70) print(i >> 80) i = -0xffffffffffffffff print(i >> 32) micropython-1.12/tests/basics/int_big_unary.py000066400000000000000000000001321357706137100216270ustar00rootroot00000000000000# test bignum unary operations i = 1 << 65 print(bool(i)) print(+i) print(-i) print(~i) micropython-1.12/tests/basics/int_big_xor.py000066400000000000000000000013401357706137100213030ustar00rootroot00000000000000# test + + print(0 ^ (1 << 80)) print((1 << 80) ^ (1 << 80)) print((1 << 80) ^ 0) a = 0xfffffffffffffffffffffffffffff print(a ^ (1 << 100)) print(a ^ (1 << 200)) print(a ^ a == 0) print(bool(a ^ a)) # test - + print((-1 << 80) ^ (1 << 80)) print((-1 << 80) ^ 0) print((-a) ^ (1 << 100)) print((-a) ^ (1 << 200)) print((-a) ^ a == 0) print(bool((-a) ^ a)) i = -1 print(i ^ 0xffffffffffffffff) # carry overflows to higher digit # test + - print(0 ^ (-1 << 80)) print((1 << 80) ^ (-1 << 80)) print(a ^ (-1 << 100)) print(a ^ (-1 << 200)) print(a ^ (-a) == 0) print(bool(a ^ (-a))) # test - - print((-1 << 80) ^ (-1 << 80)) print((-a) ^ (-1 << 100)) print((-a) ^ (-1 << 200)) print((-a) ^ (-a) == 0) print(bool((-a) ^ (-a))) micropython-1.12/tests/basics/int_big_xor2.py000066400000000000000000000042111357706137100213650ustar00rootroot00000000000000# test + + print( 97989513389222316022151446562729620153292831887555425160965597396 ^ 23716683549865351578586448630079789776107310103486834795830390982) print( 53817081128841898634258263553430908085326601592682411889506742059 ^ 37042558948907407488299113387826240429667200950043601129661240876) print( 26167512042587370698808974207700979337713004510730289760097826496 ^ 98456276326770292376138852628141531773120376436197321310863125849) print( 21085380307304977067262070503651827226504797285572981274069266136 ^ 15928222825828272388778130358888206480162413547887287646273147570) print( 40827393422334167255488276244226338235131323044408420081160772273 ^ 63815443187857978125545555033672525708399848575557475462799643340) print( 5181013159871685724135944379095645225188360725917119022722046448 ^ 59734090450462480092384049604830976376887859531148103803093112493) print( 283894311 ^ 86526825689187217371383854139783231460931720533100376593106943447) print( 40019818573920230246248826511203818792007462193311949166285967147 ^ 9487909752) # test - - print( -97989513389222316022151446562729620153292831887555425160965597396 ^ -23716683549865351578586448630079789776107310103486834795830390982) print( -53817081128841898634258263553430908085326601592682411889506742059 ^ -37042558948907407488299113387826240429667200950043601129661240876) print( -26167512042587370698808974207700979337713004510730289760097826496 ^ -98456276326770292376138852628141531773120376436197321310863125849) print( -21085380307304977067262070503651827226504797285572981274069266136 ^ -15928222825828272388778130358888206480162413547887287646273147570) print( -40827393422334167255488276244226338235131323044408420081160772273 ^ -63815443187857978125545555033672525708399848575557475462799643340) print( -5181013159871685724135944379095645225188360725917119022722046448 ^ -59734090450462480092384049604830976376887859531148103803093112493) print( -283894311 ^ -86526825689187217371383854139783231460931720533100376593106943447) print( -40019818573920230246248826511203818792007462193311949166285967147 ^ -9487909752) micropython-1.12/tests/basics/int_big_xor3.py000066400000000000000000000042111357706137100213660ustar00rootroot00000000000000# test - + print( -97989513389222316022151446562729620153292831887555425160965597396 ^ 23716683549865351578586448630079789776107310103486834795830390982) print( -53817081128841898634258263553430908085326601592682411889506742059 ^ 37042558948907407488299113387826240429667200950043601129661240876) print( -26167512042587370698808974207700979337713004510730289760097826496 ^ 98456276326770292376138852628141531773120376436197321310863125849) print( -21085380307304977067262070503651827226504797285572981274069266136 ^ 15928222825828272388778130358888206480162413547887287646273147570) print( -40827393422334167255488276244226338235131323044408420081160772273 ^ 63815443187857978125545555033672525708399848575557475462799643340) print( -5181013159871685724135944379095645225188360725917119022722046448 ^ 59734090450462480092384049604830976376887859531148103803093112493) print( -283894311 ^ 86526825689187217371383854139783231460931720533100376593106943447) print( -40019818573920230246248826511203818792007462193311949166285967147 ^ 9487909752) # test + - print( 97989513389222316022151446562729620153292831887555425160965597396 ^ -23716683549865351578586448630079789776107310103486834795830390982) print( 53817081128841898634258263553430908085326601592682411889506742059 ^ -37042558948907407488299113387826240429667200950043601129661240876) print( 26167512042587370698808974207700979337713004510730289760097826496 ^ -98456276326770292376138852628141531773120376436197321310863125849) print( 21085380307304977067262070503651827226504797285572981274069266136 ^ -15928222825828272388778130358888206480162413547887287646273147570) print( 40827393422334167255488276244226338235131323044408420081160772273 ^ -63815443187857978125545555033672525708399848575557475462799643340) print( 5181013159871685724135944379095645225188360725917119022722046448 ^ -59734090450462480092384049604830976376887859531148103803093112493) print( 283894311 ^ -86526825689187217371383854139783231460931720533100376593106943447) print( 40019818573920230246248826511203818792007462193311949166285967147 ^ -9487909752) micropython-1.12/tests/basics/int_big_zeroone.py000066400000000000000000000012111357706137100221510ustar00rootroot00000000000000# test [0,-0,1,-1] edge cases of bignum long_zero = (2**64) >> 65 long_neg_zero = -long_zero long_one = long_zero + 1 long_neg_one = -long_one cases = [long_zero, long_neg_zero, long_one, long_neg_one] print(cases) print([-c for c in cases]) print([~c for c in cases]) print([c >> 1 for c in cases]) print([c << 1 for c in cases]) # comparison of 0/-0/+0 print(long_zero == 0) print(long_neg_zero == 0) print(long_one - 1 == 0) print(long_neg_one + 1 == 0) print(long_zero < 1) print(long_zero < -1) print(long_zero > 1) print(long_zero > -1) print(long_neg_zero < 1) print(long_neg_zero < -1) print(long_neg_zero > 1) print(long_neg_zero > -1) micropython-1.12/tests/basics/int_bytes.py000066400000000000000000000013741357706137100210070ustar00rootroot00000000000000print((10).to_bytes(1, "little")) print((111111).to_bytes(4, "little")) print((100).to_bytes(10, "little")) print(int.from_bytes(b"\x00\x01\0\0\0\0\0\0", "little")) print(int.from_bytes(b"\x01\0\0\0\0\0\0\0", "little")) print(int.from_bytes(b"\x00\x01\0\0\0\0\0\0", "little")) # check that extra zero bytes don't change the internal int value print(int.from_bytes(bytes(20), "little") == 0) print(int.from_bytes(b"\x01" + bytes(20), "little") == 1) # big-endian conversion print((10).to_bytes(1, "big")) print((100).to_bytes(10, "big")) print(int.from_bytes(b"\0\0\0\0\0\0\0\0\0\x01", "big")) print(int.from_bytes(b"\x01\0", "big")) # negative number of bytes should raise an error try: (1).to_bytes(-1, "little") except ValueError: print("ValueError") micropython-1.12/tests/basics/int_bytes_intbig.py000066400000000000000000000006011357706137100223330ustar00rootroot00000000000000print((2**64).to_bytes(9, "little")) print((2**64).to_bytes(9, "big")) b = bytes(range(20)) il = int.from_bytes(b, "little") ib = int.from_bytes(b, "big") print(il) print(ib) print(il.to_bytes(20, "little")) print(ib.to_bytes(20, "big")) # check that extra zero bytes don't change the internal int value print(int.from_bytes(b + bytes(10), "little") == int.from_bytes(b, "little")) micropython-1.12/tests/basics/int_constfolding.py000066400000000000000000000010101357706137100223350ustar00rootroot00000000000000# tests int constant folding in compiler # positive print(+1) print(+100) # negation print(-1) print(-(-1)) # 1's complement print(~0) print(~1) print(~-1) # addition print(1 + 2) # subtraction print(1 - 2) print(2 - 1) # multiplication print(1 * 2) print(123 * 456) # floor div and modulo print(123 // 7, 123 % 7) print(-123 // 7, -123 % 7) print(123 // -7, 123 % -7) print(-123 // -7, -123 % -7) # won't fold so an exception can be raised at runtime try: 1 << -1 except ValueError: print('ValueError') micropython-1.12/tests/basics/int_constfolding_intbig.py000066400000000000000000000010401357706137100236740ustar00rootroot00000000000000# tests int constant folding in compiler # negation print(-0x3fffffff) # 32-bit edge case print(-0x3fffffffffffffff) # 64-bit edge case print(-(-0x3fffffff - 1)) # 32-bit edge case print(-(-0x3fffffffffffffff - 1)) # 64-bit edge case # 1's complement print(~0x3fffffff) # 32-bit edge case print(~0x3fffffffffffffff) # 64-bit edge case print(~(-0x3fffffff - 1)) # 32-bit edge case print(~(-0x3fffffffffffffff - 1)) # 64-bit edge case # zero big-num on rhs print(1 + ((1 << 65) - (1 << 65))) # negative big-num on rhs print(1 + (-(1 << 65))) micropython-1.12/tests/basics/int_divmod.py000066400000000000000000000003121357706137100211320ustar00rootroot00000000000000# test integer floor division and modulo # test all combination of +/-/0 cases for i in range(-2, 3): for j in range(-4, 5): if j != 0: print(i, j, i // j, i % j, divmod(i, j)) micropython-1.12/tests/basics/int_divmod_intbig.py000066400000000000000000000002471357706137100224750ustar00rootroot00000000000000# test integer floor division and modulo # this tests bignum modulo a = 987654321987987987987987987987 b = 19 print(a % b) print(a % -b) print(-a % b) print(-a % -b) micropython-1.12/tests/basics/int_divzero.py000066400000000000000000000002221357706137100213320ustar00rootroot00000000000000try: 1 // 0 except ZeroDivisionError: print("ZeroDivisionError") try: 1 % 0 except ZeroDivisionError: print("ZeroDivisionError") micropython-1.12/tests/basics/int_intbig.py000066400000000000000000000012351357706137100211310ustar00rootroot00000000000000# This tests long ints for 32-bit machine a = 0x1ffffffff b = 0x100000000 print(a) print(b) print(a + b) print(a - b) print(b - a) # overflows long long implementation #print(a * b) print(a // b) print(a % b) print("&", a & b) print(a | b) print(a ^ b) print(a << 3) print(a >> 1) a += b print(a) a -= 123456 print(a) a *= 257 print(a) a //= 257 print(a) a %= b print(a) a ^= b print(a) a |= b print(a) a &= b print("&=", a) a <<= 5 print(a) a >>= 1 print(a) # Test referential integrity of long ints a = 0x1ffffffff b = a a += 1 print(a) print(b) # Bitwise ops on 64-bit a = 0x1ffffffffffffffff b = 0x10000000000000000 print("&", a & b) print(a | b) print(a ^ b) micropython-1.12/tests/basics/int_small.py000066400000000000000000000027601357706137100207710ustar00rootroot00000000000000# This tests small int range for 32-bit machine # Small ints are variable-length encoded in MicroPython, so first # test that encoding works as expected. print(0) print(1) print(-1) # Value is split in 7-bit "subwords", and taking into account that all # ints in Python are signed, there're 6 bits of magnitude. So, around 2^6 # there's "turning point" print(63) print(64) print(65) print(-63) print(-64) print(-65) # Maximum values of small ints on 32-bit platform print(1073741823) # Per python semantics, lexical integer is without a sign (i.e. positive) # and '-' is unary minus operation applied to it. That's why -1073741824 # (min two-complement's negative value) is not allowed. print(-1073741823) # Operations tests # compile-time constexprs print(1 + 3) print(3 - 2) print(2 * 3) print(1 & 3) print(1 | 2) print(1 ^ 3) print(+3) print(-3) print(~3) a = 0x3fffff print(a) a *= 0x10 print(a) a *= 0x10 print(a) a += 0xff print(a) # This would overflow #a += 1 a = -0x3fffff print(a) a *= 0x10 print(a) a *= 0x10 print(a) a -= 0xff print(a) # This still doesn't overflow a -= 1 print(a) # This would overflow #a -= 1 # negative shifts are not allowed try: a << -1 except ValueError: print("ValueError") try: a >> -1 except ValueError: print("ValueError") # Shifts to big amounts are undefined behavior in C and is CPU-specific # These are compile-time constexprs print(1 >> 32) print(1 >> 64) print(1 >> 128) # These are runtime calcs a = 1 print(a >> 32) print(a >> 64) print(a >> 128) micropython-1.12/tests/basics/io_buffered_writer.py000066400000000000000000000010471357706137100226510ustar00rootroot00000000000000import uio as io try: io.BytesIO io.BufferedWriter except AttributeError: print('SKIP') raise SystemExit bts = io.BytesIO() buf = io.BufferedWriter(bts, 8) buf.write(b"foobar") print(bts.getvalue()) buf.write(b"foobar") # CPython has different flushing policy, so value below is different print(bts.getvalue()) buf.flush() print(bts.getvalue()) buf.flush() print(bts.getvalue()) # special case when alloc is a factor of total buffer length bts = io.BytesIO() buf = io.BufferedWriter(bts, 1) buf.write(b"foo") print(bts.getvalue()) micropython-1.12/tests/basics/io_buffered_writer.py.exp000066400000000000000000000000671357706137100234450ustar00rootroot00000000000000b'' b'foobarfo' b'foobarfoobar' b'foobarfoobar' b'foo' micropython-1.12/tests/basics/io_bytesio_cow.py000066400000000000000000000005111357706137100220140ustar00rootroot00000000000000# Make sure that write operations on io.BytesIO don't # change original object it was constructed from. try: import uio as io except ImportError: import io b = b"foobar" a = io.BytesIO(b) a.write(b"1") print(b) print(a.getvalue()) b = bytearray(b"foobar") a = io.BytesIO(b) a.write(b"1") print(b) print(a.getvalue()) micropython-1.12/tests/basics/io_bytesio_ext.py000066400000000000000000000006231357706137100220300ustar00rootroot00000000000000# Extended stream operations on io.BytesIO try: import uio as io except ImportError: import io a = io.BytesIO(b"foobar") a.seek(10) print(a.read(10)) a = io.BytesIO() print(a.seek(8)) a.write(b"123") print(a.getvalue()) print(a.seek(0, 1)) print(a.seek(-1, 2)) a.write(b"0") print(a.getvalue()) a.flush() print(a.getvalue()) a.seek(0) arr = bytearray(10) print(a.readinto(arr)) print(arr) micropython-1.12/tests/basics/io_bytesio_ext2.py000066400000000000000000000005161357706137100221130ustar00rootroot00000000000000try: import uio as io except ImportError: import io a = io.BytesIO(b"foobar") try: a.seek(-10) except Exception as e: # CPython throws ValueError, but MicroPython has consistent stream # interface, so BytesIO raises the same error as a real file, which # is OSError(EINVAL). print(type(e), e.args[0] > 0) micropython-1.12/tests/basics/io_bytesio_ext2.py.exp000066400000000000000000000000271357706137100227030ustar00rootroot00000000000000 True micropython-1.12/tests/basics/io_iobase.py000066400000000000000000000005271357706137100207370ustar00rootroot00000000000000try: import uio as io except: import io try: io.IOBase except AttributeError: print('SKIP') raise SystemExit class MyIO(io.IOBase): def write(self, buf): # CPython and uPy pass in different types for buf (str vs bytearray) print('write', len(buf)) return len(buf) print('test', file=MyIO()) micropython-1.12/tests/basics/io_stringio1.py000066400000000000000000000014741357706137100214160ustar00rootroot00000000000000try: import uio as io except ImportError: import io a = io.StringIO() print('io.StringIO' in repr(a)) print(a.getvalue()) print(a.read()) a = io.StringIO("foobar") print(a.getvalue()) print(a.read()) print(a.read()) a = io.StringIO() a.write("foo") print(a.getvalue()) a = io.StringIO("foo") a.write("12") print(a.getvalue()) a = io.StringIO("foo") a.write("123") print(a.getvalue()) a = io.StringIO("foo") a.write("1234") print(a.getvalue()) a = io.StringIO() a.write("foo") print(a.read()) a = io.StringIO() a.close() for f in [a.read, a.getvalue, lambda:a.write("")]: # CPython throws for operations on closed I/O, MicroPython makes # the underlying string empty unless MICROPY_CPYTHON_COMPAT defined try: f() print("ValueError") except ValueError: print("ValueError") micropython-1.12/tests/basics/io_stringio_with.py000066400000000000000000000002331357706137100223600ustar00rootroot00000000000000try: import uio as io except ImportError: import io # test __enter__/__exit__ with io.StringIO() as b: b.write("foo") print(b.getvalue()) micropython-1.12/tests/basics/io_write_ext.py000066400000000000000000000007241357706137100215060ustar00rootroot00000000000000# This tests extended (MicroPython-specific) form of write: # write(buf, len) and write(buf, offset, len) import uio try: uio.BytesIO except AttributeError: print('SKIP') raise SystemExit buf = uio.BytesIO() buf.write(b"foo", 2) print(buf.getvalue()) buf.write(b"foo", 100) print(buf.getvalue()) buf.write(b"foobar", 1, 3) print(buf.getvalue()) buf.write(b"foobar", 1, 100) print(buf.getvalue()) buf.write(b"foobar", 100, 100) print(buf.getvalue()) micropython-1.12/tests/basics/io_write_ext.py.exp000066400000000000000000000000751357706137100223000ustar00rootroot00000000000000b'fo' b'fofoo' b'fofoooob' b'fofooooboobar' b'fofooooboobar' micropython-1.12/tests/basics/is_isnot.py000066400000000000000000000003351357706137100206320ustar00rootroot00000000000000print(1 is 1) print(1 is 2) print(1 is not 1) print(1 is not 2) print([1, 2] is [1, 2]) a = [1, 2] b = a print(b is a) # TODO: strings require special "is" handling, postponed # until qstr refactor. #print("a" is "a") micropython-1.12/tests/basics/iter0.py000066400000000000000000000003161357706137100200250ustar00rootroot00000000000000# builtin type that is not iterable try: for i in 1: pass except TypeError: print('TypeError') # builtin type that is iterable, calling __next__ explicitly print(iter(range(4)).__next__()) micropython-1.12/tests/basics/iter1.py000066400000000000000000000031641357706137100200320ustar00rootroot00000000000000# test user defined iterators # this class is not iterable class NotIterable: pass try: for i in NotIterable(): pass except TypeError: print('TypeError') # this class has no __next__ implementation class NotIterable: def __iter__(self): return self try: print(all(NotIterable())) except TypeError: print('TypeError') class MyStopIteration(StopIteration): pass class myiter: def __init__(self, i): self.i = i def __iter__(self): return self def __next__(self): if self.i <= 0: # stop in the usual way raise StopIteration elif self.i == 10: # stop with an argument raise StopIteration(42) elif self.i == 20: # raise a non-stop exception raise TypeError elif self.i == 30: # raise a user-defined stop iteration print('raising MyStopIteration') raise MyStopIteration else: # return the next value self.i -= 1 return self.i for i in myiter(5): print(i) for i in myiter(12): print(i) try: for i in myiter(22): print(i) except TypeError: print('raised TypeError') try: for i in myiter(5): print(i) raise StopIteration except StopIteration: print('raised StopIteration') for i in myiter(32): print(i) # repeat some of the above tests but use tuple() to walk the iterator (tests mp_iternext) print(tuple(myiter(5))) print(tuple(myiter(12))) print(tuple(myiter(32))) try: tuple(myiter(22)) except TypeError: print('raised TypeError') micropython-1.12/tests/basics/iter2.py000066400000000000000000000007521357706137100200330ustar00rootroot00000000000000# user defined iterator used in something other than a for loop class MyStopIteration(StopIteration): pass class myiter: def __init__(self, i): self.i = i def __iter__(self): return self def __next__(self): if self.i == 0: raise StopIteration elif self.i == 1: raise StopIteration(1) elif self.i == 2: raise MyStopIteration print(list(myiter(0))) print(list(myiter(1))) print(list(myiter(2))) micropython-1.12/tests/basics/iter_of_iter.py000066400000000000000000000002421357706137100214520ustar00rootroot00000000000000i = iter(iter((1, 2, 3))) print(list(i)) i = iter(iter([1, 2, 3])) print(list(i)) i = iter(iter({1:2, 3:4, 5:6})) print(sorted(i)) # set, see set_iter_of_iter.py micropython-1.12/tests/basics/lambda1.py000066400000000000000000000000641357706137100203030ustar00rootroot00000000000000# lambda f = lambda x, y: x + 3 * y print(f(3, 5)) micropython-1.12/tests/basics/lambda_defargs.py000066400000000000000000000003101357706137100217070ustar00rootroot00000000000000# test default args with lambda f = lambda x=1: x print(f(), f(2), f(x=3)) y = 'y' f = lambda x=y: x print(f()) f = lambda x, y=[]: (x, y) f(0)[1].append(1) print(f(1), f(x=2), f(3, 4), f(4, y=5)) micropython-1.12/tests/basics/lexer.py000066400000000000000000000025621357706137100201260ustar00rootroot00000000000000# test the lexer try: eval exec except NameError: print("SKIP") raise SystemExit # __debug__ is a special symbol print(type(__debug__)) # short input exec("") exec("\n") exec("\n\n") exec("\r") exec("\r\r") exec("\t") exec("\r\n") exec("\nprint(1)") exec("\rprint(2)") exec("\r\nprint(3)") exec("\n5") exec("\r6") exec("\r\n7") print(eval("1")) print(eval("12")) print(eval("123")) print(eval("1\n")) print(eval("12\n")) print(eval("123\n")) print(eval("1\r")) print(eval("12\r")) print(eval("123\r")) # line continuation print(eval("'123' \\\r '456'")) print(eval("'123' \\\n '456'")) print(eval("'123' \\\r\n '456'")) print(eval("'123'\\\r'456'")) print(eval("'123'\\\n'456'")) print(eval("'123'\\\r\n'456'")) # backslash used to escape a line-break in a string print('a\ b') # lots of indentation def a(x): if x: if x: if x: if x: if x: if x: if x: if x: if x: if x: if x: if x: if x: if x: if x: print(x) a(1) # badly formed hex escape sequences try: exec(r"'\x0'") except SyntaxError: print("SyntaxError") try: exec(r"b'\x0'") except SyntaxError: print("SyntaxError") try: exec(r"'\u000'") except SyntaxError: print("SyntaxError") try: exec(r"'\U0000000'") except SyntaxError: print("SyntaxError") micropython-1.12/tests/basics/list1.py000066400000000000000000000004731357706137100200420ustar00rootroot00000000000000# basic list functionality x = [1, 2, 3 * 4] print(x) x[0] = 4 print(x) x[1] += -4 print(x) x.append(5) print(x) f = x.append f(4) print(x) x.extend([100, 200]) print(x) x.extend(range(3)) print(x) x += [2, 1] print(x) # unsupported type on RHS of add try: [] + None except TypeError: print('TypeError') micropython-1.12/tests/basics/list_clear.py000066400000000000000000000000671357706137100211260ustar00rootroot00000000000000# tests list.clear x = [1, 2, 3, 4] x.clear() print(x) micropython-1.12/tests/basics/list_compare.py000066400000000000000000000016751357706137100214740ustar00rootroot00000000000000print([] == []) print([] > []) print([] < []) print([] == [1]) print([1] == []) print([] > [1]) print([1] > []) print([] < [1]) print([1] < []) print([] >= [1]) print([1] >= []) print([] <= [1]) print([1] <= []) print([1] == [1]) print([1] != [1]) print([1] == [2]) print([1] == [1, 0]) print([1] > [1]) print([1] > [2]) print([2] > [1]) print([1, 0] > [1]) print([1, -1] > [1]) print([1] > [1, 0]) print([1] > [1, -1]) print([1] < [1]) print([2] < [1]) print([1] < [2]) print([1] < [1, 0]) print([1] < [1, -1]) print([1, 0] < [1]) print([1, -1] < [1]) print([1] >= [1]) print([1] >= [2]) print([2] >= [1]) print([1, 0] >= [1]) print([1, -1] >= [1]) print([1] >= [1, 0]) print([1] >= [1, -1]) print([1] <= [1]) print([2] <= [1]) print([1] <= [2]) print([1] <= [1, 0]) print([1] <= [1, -1]) print([1, 0] <= [1]) print([1, -1] <= [1]) print([] == {}) print([] != {}) print([1] == (1,)) try: print([] < {}) except TypeError: print("TypeError") micropython-1.12/tests/basics/list_copy.py000066400000000000000000000001341357706137100210050ustar00rootroot00000000000000# list copy tests a = [1, 2, []] b = a.copy() a[-1].append(1) a.append(4) print(a) print(b) micropython-1.12/tests/basics/list_count.py000066400000000000000000000001521357706137100211630ustar00rootroot00000000000000# list count tests a = [1, 2, 3] a = a + a + a b = [0, 0, a, 0, a, 0] print(a.count(2)) print(b.count(a)) micropython-1.12/tests/basics/list_extend.py000066400000000000000000000005021357706137100213210ustar00rootroot00000000000000# test list.__iadd__ and list.extend (they are equivalent) l = [1, 2] l.extend([]) print(l) l.extend([3]) print(l) l.extend([4, 5]) print(l) l.extend(range(6, 10)) print(l) l.extend("abc") print(l) l = [1, 2] l += [] print(l) l += [3] print(l) l += [4, 5] print(l) l += range(6, 10) print(l) l += "abc" print(l) micropython-1.12/tests/basics/list_index.py000066400000000000000000000012471357706137100211500ustar00rootroot00000000000000a = [1, 2, 3] print(a.index(1)) print(a.index(2)) print(a.index(3)) print(a.index(3, 2)) print(a.index(1, -100)) print(a.index(1, False)) try: print(a.index(1, True)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print(a.index(3, 2, 2)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") a = a + a b = [0, 0, a] print(a.index(2)) print(b.index(a)) print(a.index(2, 2)) try: a.index(2, 2, 2) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") # 3rd argument to index greater than length of list print([1, 2].index(1, 0, 4)) micropython-1.12/tests/basics/list_insert.py000066400000000000000000000001671357706137100213450ustar00rootroot00000000000000a = [1, 2, 3] a.insert(1, 42) print(a) a.insert(-1, -1) print(a) a.insert(99, 99) print(a) a.insert(-99, -99) print(a) micropython-1.12/tests/basics/list_mult.py000066400000000000000000000005201357706137100210130ustar00rootroot00000000000000# basic multiplication print([0] * 5) # check negative, 0, positive; lhs and rhs multiplication for i in (-4, -2, 0, 2, 4): print(i * [1, 2]) print([1, 2] * i) # check that we don't modify existing list a = [1, 2, 3] c = a * 3 print(a, c) # unsupported type on RHS try: [] * None except TypeError: print('TypeError') micropython-1.12/tests/basics/list_pop.py000066400000000000000000000005331357706137100206340ustar00rootroot00000000000000# list poppin' a = [1, 2, 3] print(a.pop()) print(a.pop()) print(a.pop()) try: print(a.pop()) except IndexError: print("IndexError raised") else: raise AssertionError("No IndexError raised") # popping such that list storage shrinks (tests implementation detail of uPy) l = list(range(20)) for i in range(len(l)): l.pop() print(l) micropython-1.12/tests/basics/list_remove.py000066400000000000000000000002541357706137100213330ustar00rootroot00000000000000a = [1, 2, 3] print(a.remove(2)) print(a) try: a.remove(2) except ValueError: print("Raised ValueError") else: raise AssertionError("Did not raise ValueError") micropython-1.12/tests/basics/list_reverse.py000066400000000000000000000001051357706137100215040ustar00rootroot00000000000000a = [] for i in range(100): a.append(i) a.reverse() print(a) micropython-1.12/tests/basics/list_slice.py000066400000000000000000000006501357706137100211350ustar00rootroot00000000000000# test list slices, getting values x = list(range(10)) print(x[1:]) print(x[:-1]) print(x[2:3]) a = 2 b = 4 c = 3 print(x[:]) print(x[::]) print(x[::c]) print(x[:b]) print(x[:b:]) print(x[:b:c]) print(x[a]) print(x[a:]) print(x[a::]) print(x[a::c]) print(x[a:b]) print(x[a:b:]) print(x[a:b:c]) # these should not raise IndexError print([][1:]) print([][-1:]) try: [][::0] except ValueError: print('ValueError') micropython-1.12/tests/basics/list_slice_3arg.py000066400000000000000000000011711357706137100220500ustar00rootroot00000000000000x = list(range(10)) print(x[::-1]) print(x[::2]) print(x[::-2]) x = list(range(9)) print(x[::-1]) print(x[::2]) print(x[::-2]) x = list(range(5)) print(x[:0:-1]) print(x[:1:-1]) print(x[:2:-1]) print(x[0::-1]) print(x[1::-1]) print(x[2::-1]) x = list(range(5)) print(x[0:0:-1]) print(x[4:4:-1]) print(x[5:5:-1]) x = list(range(10)) print(x[-1:-1:-1]) print(x[-1:-2:-1]) print(x[-1:-11:-1]) print(x[-10:-11:-1]) print(x[:-15:-1]) # test negative indices that are out-of-bounds print([][::-1]) print([1][::-1]) print([][0:-10:-1]) print([1][0:-10:-1]) print([][:-20:-1]) print([1][:-20:-1]) print([][-20::-1]) print([1][-20::-1]) micropython-1.12/tests/basics/list_slice_assign.py000066400000000000000000000011551357706137100225020ustar00rootroot00000000000000# test slices; only 2 argument version supported by MicroPython at the moment x = list(range(10)) # Assignment l = list(x) l[1:3] = [10, 20] print(l) l = list(x) l[1:3] = [10] print(l) l = list(x) l[1:3] = [] print(l) l = list(x) del l[1:3] print(l) l = list(x) l[:3] = [10, 20] print(l) l = list(x) l[:3] = [] print(l) l = list(x) del l[:3] print(l) l = list(x) l[:-3] = [10, 20] print(l) l = list(x) l[:-3] = [] print(l) l = list(x) del l[:-3] print(l) # assign a tuple l = [1, 2, 3] l[0:1] = (10, 11, 12) print(l) # RHS of slice must be an iterable try: [][0:1] = 123 except TypeError: print('TypeError') micropython-1.12/tests/basics/list_slice_assign_grow.py000066400000000000000000000006461357706137100235440ustar00rootroot00000000000000x = list(range(2)) l = list(x) l[0:0] = [10] print(l) l = list(x) l[:0] = [10, 20] print(l) l = list(x) l[0:0] = [10, 20, 30, 40] print(l) l = list(x) l[1:1] = [10, 20, 30, 40] print(l) l = list(x) l[2:] = [10, 20, 30, 40] print(l) # Weird cases l = list(x) l[1:0] = [10, 20, 30, 40] print(l) l = list(x) l[100:100] = [10, 20, 30, 40] print(l) # growing by using itself on RHS l = list(range(10)) l[4:] = l print(l) micropython-1.12/tests/basics/list_sort.py000066400000000000000000000017131357706137100210260ustar00rootroot00000000000000l = [1, 3, 2, 5] print(l) print(sorted(l)) l.sort() print(l) print(l == sorted(l)) print(sorted(l, key=lambda x: -x)) l.sort(key=lambda x: -x) print(l) print(l == sorted(l, key=lambda x: -x)) print(sorted(l, key=lambda x: -x, reverse=True)) l.sort(key=lambda x: -x, reverse=True) print(l) print(l == sorted(l, key=lambda x: -x, reverse=True)) print(sorted(l, reverse=True)) l.sort(reverse=True) print(l) print(l == sorted(l, reverse=True)) print(sorted(l, reverse=False)) l.sort(reverse=False) print(l) print(l == sorted(l, reverse=False)) # test large lists (should not stack overflow) l = list(range(200)) l.sort() print(l[0], l[-1]) l.sort(reverse=True) print(l[0], l[-1]) # test user-defined ordering class A: def __init__(self, x): self.x = x def __lt__(self, other): return self.x > other.x def __repr__(self): return str(self.x) l = [A(5), A(2), A(1), A(3), A(4)] print(l) l.sort() print(l) l.sort(reverse=True) print(l) micropython-1.12/tests/basics/list_sum.py000066400000000000000000000000731357706137100206410ustar00rootroot00000000000000# list addition a = [1,2,3] b = [4,5,6] c = a + b print(c) micropython-1.12/tests/basics/logic_constfolding.py000066400000000000000000000006721357706137100226550ustar00rootroot00000000000000# tests logical constant folding in parser def f_true(): print('f_true') return True def f_false(): print('f_false') return False print(0 or False) print(1 or foo) print(f_false() or 1 or foo) print(f_false() or 1 or f_true()) print(0 and foo) print(1 and True) print(f_true() and 0 and foo) print(f_true() and 1 and f_false()) print(not 0) print(not False) print(not 1) print(not True) print(not not 0) print(not not 1) micropython-1.12/tests/basics/memoryerror.py000066400000000000000000000004151357706137100213640ustar00rootroot00000000000000# test out-of-memory with malloc l = list(range(1000)) try: 1000000000 * l except MemoryError: print('MemoryError') print(len(l), l[0], l[-1]) # test out-of-memory with realloc try: [].extend(range(1000000000)) except MemoryError: print('MemoryError') micropython-1.12/tests/basics/memoryerror.py.exp000066400000000000000000000000431357706137100221540ustar00rootroot00000000000000MemoryError 1000 0 999 MemoryError micropython-1.12/tests/basics/memoryview1.py000066400000000000000000000035531357706137100212740ustar00rootroot00000000000000# test memoryview try: memoryview except: print("SKIP") raise SystemExit try: import uarray as array except ImportError: try: import array except ImportError: print("SKIP") raise SystemExit # test reading from bytes b = b'1234' m = memoryview(b) print(len(m)) print(m[0], m[1], m[-1]) print(list(m)) # test writing to bytes try: m[0] = 1 except TypeError: print("TypeError") try: m[0:2] = b'00' except TypeError: print("TypeError") # test writing to bytearray b = bytearray(b) m = memoryview(b) m[0] = 1 print(b) print(list(m)) # test slice m = memoryview(b'1234') print(list(m[1:])) print(list(m[1:-1])) # this tests get_buffer of memoryview m = memoryview(bytearray(2)) print(bytearray(m)) print(list(memoryview(memoryview(b'1234')))) # read-only memoryview a = array.array('i', [1, 2, 3, 4]) m = memoryview(a) print(list(m)) print(list(m[1:-1])) m[2] = 6 print(a) # test slice assignment between memoryviews b1 = bytearray(b'1234') b2 = bytearray(b'5678') b3 = bytearray(b'5678') m1 = memoryview(b1) m2 = memoryview(b2) m3 = memoryview(b3) m2[1:3] = m1[0:2] print(b2) b3[1:3] = m1[0:2] print(b3) m1[2:4] = b3[1:3] print(b1) try: m2[1:3] = b1[0:4] except ValueError: print("ValueError") try: m2[1:3] = m1[0:4] except ValueError: print("ValueError") try: m2[0:4] = m1[1:3] except ValueError: print("ValueError") # test memoryview of arrays with items sized larger than 1 a1 = array.array('i', [0]*5) m4 = memoryview(a1) a2 = array.array('i', [3]*5) m5 = memoryview(a2) m4[1:3] = m5[1:3] print(a1) try: m4[1:3] = m2[1:3] except ValueError: print("ValueError") # invalid assignment on RHS try: memoryview(array.array('i'))[0:2] = b'1234' except ValueError: print('ValueError') # invalid attribute try: memoryview(b'a').noexist except AttributeError: print('AttributeError') micropython-1.12/tests/basics/memoryview2.py000066400000000000000000000011151357706137100212650ustar00rootroot00000000000000# test memoryview accessing maximum values for signed/unsigned elements try: memoryview except: print("SKIP") raise SystemExit try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit print(list(memoryview(b'\x7f\x80\x81\xff'))) print(list(memoryview(array('b', [0x7f, -0x80])))) print(list(memoryview(array('B', [0x7f, 0x80, 0x81, 0xff])))) print(list(memoryview(array('h', [0x7f00, -0x8000])))) print(list(memoryview(array('H', [0x7f00, 0x8000, 0x8100, 0xffff])))) micropython-1.12/tests/basics/memoryview_gc.py000066400000000000000000000006421357706137100216600ustar00rootroot00000000000000# test memoryview retains pointer to original object/buffer try: memoryview except: print("SKIP") raise SystemExit b = bytearray(10) m = memoryview(b)[1:] for i in range(len(m)): m[i] = i # reclaim b, but hopefully not the buffer b = None import gc gc.collect() # allocate lots of memory for i in range(100000): [42, 42, 42, 42] # check that the memoryview is still what we want print(list(m)) micropython-1.12/tests/basics/memoryview_intbig.py000066400000000000000000000007071357706137100225450ustar00rootroot00000000000000# test memoryview accessing maximum values for signed/unsigned elements try: memoryview except: print("SKIP") raise SystemExit try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit print(list(memoryview(array('i', [0x7f000000, -0x80000000])))) print(list(memoryview(array('I', [0x7f000000, 0x80000000, 0x81000000, 0xffffffff])))) micropython-1.12/tests/basics/memoryview_itemsize.py000066400000000000000000000011101357706137100231070ustar00rootroot00000000000000try: memoryview(b'a').itemsize except: print("SKIP") raise SystemExit try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit for code in ['b', 'h', 'i', 'q', 'f', 'd']: print(memoryview(array(code)).itemsize) # 'l' varies depending on word size of the machine print(memoryview(array('l')).itemsize in (4, 8)) # shouldn't be able to store to the itemsize attribute try: memoryview(b'a').itemsize = 1 except AttributeError: print('AttributeError') micropython-1.12/tests/basics/module1.py000066400000000000000000000003461357706137100203530ustar00rootroot00000000000000# test behaviour of module objects # this module should always exist import __main__ # print module print(repr(__main__).startswith(">' # OK: 2 & (3 << 1) = 2 & 6 = 2 # BAD: (2 & 3) << 1 = 2 << 1 = 4 print(2 & 3 << 1) # OK: 6 & (4 >> 1) = 6 & 2 = 2 # BAD: (6 & 4) >> 1 = 2 >> 1 = 1 print(6 & 4 >> 1) # '+', '-' # OK: 1 << (1 + 1) = 1 << 2 = 4 # BAD: (1 << 1) + 1 = 2 + 1 = 3 print(1 << 1 + 1) # '*', '/', '//', '%' # OK: 2 + (2 * 2) = 2 + 4 = 6 # BAD: (2 + 2) * 2 = 4 * 2 = 8 print(2 + 2 * 2) # '+x', '-x', '~x' # '**' # OK: -(2**2) = -4 # BAD: (-2)**2 = 4 print(-2**2) # OK: 2**(-1) = 0.5 print(2**-0) # (expr...) print((2 + 2) * 2) micropython-1.12/tests/basics/ordereddict1.py000066400000000000000000000010351357706137100213520ustar00rootroot00000000000000try: from collections import OrderedDict except ImportError: try: from ucollections import OrderedDict except ImportError: print("SKIP") raise SystemExit d = OrderedDict([(10, 20), ("b", 100), (1, 2)]) print(len(d)) print(list(d.keys())) print(list(d.values())) del d["b"] print(len(d)) print(list(d.keys())) print(list(d.values())) # access remaining elements after deleting print(d[10], d[1]) # add an element after deleting d["abc"] = 123 print(len(d)) print(list(d.keys())) print(list(d.values())) micropython-1.12/tests/basics/ordereddict_eq.py000066400000000000000000000010351357706137100217560ustar00rootroot00000000000000try: from collections import OrderedDict except ImportError: try: from ucollections import OrderedDict except ImportError: print("SKIP") raise SystemExit x = OrderedDict() y = OrderedDict() x['a'] = 1 x['b'] = 2 y['a'] = 1 y['b'] = 2 print(x) print(y) print(x == y) z = OrderedDict() z['b'] = 2 z['a'] = 1 print(y) print(z) print(y == z) del z['b'] z['b'] = 2 print(y) print(z) print(y == z) del x['a'] del y['a'] print(x) print(y) print(x == y) del z['b'] del y['b'] print(y) print(z) print(y == z) micropython-1.12/tests/basics/ordereddict_eq.py.exp000066400000000000000000000004411357706137100225510ustar00rootroot00000000000000OrderedDict({'a': 1, 'b': 2}) OrderedDict({'a': 1, 'b': 2}) True OrderedDict({'a': 1, 'b': 2}) OrderedDict({'b': 2, 'a': 1}) False OrderedDict({'a': 1, 'b': 2}) OrderedDict({'a': 1, 'b': 2}) True OrderedDict({'b': 2}) OrderedDict({'b': 2}) True OrderedDict({}) OrderedDict({'a': 1}) False micropython-1.12/tests/basics/parser.py000066400000000000000000000011121357706137100202710ustar00rootroot00000000000000# parser tests try: compile except NameError: print("SKIP") raise SystemExit # completely empty string # uPy and CPy differ for this case #try: # compile("", "stdin", "single") #except SyntaxError: # print("SyntaxError") try: compile("", "stdin", "eval") except SyntaxError: print("SyntaxError") compile("", "stdin", "exec") # empty continued line try: compile("\\\n", "stdin", "single") except SyntaxError: print("SyntaxError") try: compile("\\\n", "stdin", "eval") except SyntaxError: print("SyntaxError") compile("\\\n", "stdin", "exec") micropython-1.12/tests/basics/parser.py.exp000066400000000000000000000000441357706137100210670ustar00rootroot00000000000000SyntaxError SyntaxError SyntaxError micropython-1.12/tests/basics/python34.py000066400000000000000000000024031357706137100204710ustar00rootroot00000000000000# tests that differ when running under Python 3.4 vs 3.5/3.6/3.7 try: exec except NameError: print("SKIP") raise SystemExit # from basics/fun_kwvarargs.py # test evaluation order of arguments (in 3.4 it's backwards, 3.5 it's fixed) def f4(*vargs, **kwargs): print(vargs, kwargs) def print_ret(x): print(x) return x f4(*print_ret(['a', 'b']), kw_arg=print_ret(None)) # test evaluation order of dictionary key/value pair (in 3.4 it's backwards) {print_ret(1):print_ret(2)} # from basics/syntaxerror.py def test_syntax(code): try: exec(code) except SyntaxError: print("SyntaxError") test_syntax("f(*a, *b)") # can't have multiple * (in 3.5 we can) test_syntax("f(**a, **b)") # can't have multiple ** (in 3.5 we can) test_syntax("f(*a, b)") # can't have positional after * test_syntax("f(**a, b)") # can't have positional after ** test_syntax("() = []") # can't assign to empty tuple (in 3.6 we can) test_syntax("del ()") # can't delete empty tuple (in 3.6 we can) # from basics/sys1.py # uPy prints version 3.4 import sys print(sys.version[:3]) print(sys.version_info[0], sys.version_info[1]) # from basics/exception1.py # in 3.7 no comma is printed if there is only 1 arg (in 3.4-3.6 one is printed) print(repr(IndexError("foo"))) micropython-1.12/tests/basics/python34.py.exp000066400000000000000000000002231357706137100212620ustar00rootroot00000000000000None ['a', 'b'] ('a', 'b') {'kw_arg': None} 2 1 SyntaxError SyntaxError SyntaxError SyntaxError SyntaxError SyntaxError 3.4 3 4 IndexError('foo',) micropython-1.12/tests/basics/python36.py000066400000000000000000000003351357706137100204750ustar00rootroot00000000000000# tests for things that only Python 3.6 supports # underscores in numeric literals print(100_000) print(0b1010_0101) print(0xff_ff) # underscore supported by int constructor print(int('1_2_3')) print(int('0o1_2_3', 8)) micropython-1.12/tests/basics/python36.py.exp000066400000000000000000000000301357706137100212600ustar00rootroot00000000000000100000 165 65535 123 83 micropython-1.12/tests/basics/return1.py000066400000000000000000000002201357706137100203740ustar00rootroot00000000000000# test return statement def f(): return print(f()) def g(): return 1 print(g()) def f(x): return 1 if x else 2 print(f(0), f(1)) micropython-1.12/tests/basics/scope.py000066400000000000000000000013311357706137100201110ustar00rootroot00000000000000# test scoping rules # explicit global variable a = 1 def f(): global a global a, a # should be able to redefine as global a = 2 f() print(a) # explicit nonlocal variable def f(): a = 1 def g(): nonlocal a nonlocal a, a # should be able to redefine as nonlocal a = 2 g() return a print(f()) # nonlocal at inner-inner level (h) def f(): x = 1 def g(): def h(): nonlocal x return x return h return g print(f()()()) # nonlocal declared at outer level (g), and referenced by inner level (h) def f(): x = 1 def g(): nonlocal x def h(): return x return h return g print(f()()()) micropython-1.12/tests/basics/scope_implicit.py000066400000000000000000000013251357706137100220060ustar00rootroot00000000000000# test implicit scoping rules # implicit nonlocal, with variable defined after closure def f(): def g(): return x # implicit nonlocal x = 3 # variable defined after function that closes over it return g print(f()()) # implicit nonlocal at inner level, with variable defined after closure def f(): def g(): def h(): return x # implicit nonlocal return h x = 4 # variable defined after function that closes over it return g print(f()()()) # local variable which should not be implicitly made nonlocal def f(): x = 0 def g(): x # local because next statement assigns to it x = 1 g() try: f() except NameError: print('NameError') micropython-1.12/tests/basics/self_type_check.py000066400000000000000000000007201357706137100221300ustar00rootroot00000000000000# make sure type of first arg (self) to a builtin method is checked list.append try: list.append() except TypeError as e: print("TypeError") try: list.append(1) except TypeError as e: print("TypeError") try: list.append(1, 2) except TypeError as e: print("TypeError") l = [] list.append(l, 2) print(l) try: getattr(list, "append")(1, 2) except TypeError as e: print("TypeError") l = [] getattr(list, "append")(l, 2) print(l) micropython-1.12/tests/basics/seq_unpack.py000066400000000000000000000011561357706137100211360ustar00rootroot00000000000000# Basics a, b = 1, 2 print(a, b) a, b = (1, 2) print(a, b) (a, b) = 1, 2 print(a, b) (a, b) = (1, 2) print(a, b) # Tuples/lists are optimized a, b = [1, 2] print(a, b) [a, b] = 100, 200 print(a, b) # optimised 3-way swap a = 1 b = 2 c = 3 a, b, c = b, c, a print(a, b, c) try: a, b, c = (1, 2) except ValueError: print("ValueError") try: a, b, c = [1, 2, 3, 4] except ValueError: print("ValueError") # Generic iterable object a, b, c = range(3) print(a, b, c) try: a, b, c = range(2) except ValueError: print("ValueError") try: a, b, c = range(4) except ValueError: print("ValueError") micropython-1.12/tests/basics/set_add.py000066400000000000000000000000621357706137100204030ustar00rootroot00000000000000s = {1, 2, 3, 4} print(s.add(5)) print(sorted(s)) micropython-1.12/tests/basics/set_basic.py000066400000000000000000000003131357706137100207330ustar00rootroot00000000000000# basic sets s = {1} print(s) s = {3, 4, 3, 1} print(sorted(s)) # expression in constructor s = {1 + len(s)} print(s) # Sets are not hashable try: {s: 1} except TypeError: print("TypeError") micropython-1.12/tests/basics/set_binop.py000066400000000000000000000034171357706137100207710ustar00rootroot00000000000000# test set binary operations sets = [set(), {1}, {1, 2}, {1, 2, 3}, {2, 3}, {2, 3, 5}, {5}, {7}] for s in sets: for t in sets: print(sorted(s), '|', sorted(t), '=', sorted(s | t)) print(sorted(s), '^', sorted(t), '=', sorted(s ^ t)) print(sorted(s), '&', sorted(t), '=', sorted(s & t)) print(sorted(s), '-', sorted(t), '=', sorted(s - t)) u = s.copy() u |= t print(sorted(s), "|=", sorted(t), '-->', sorted(u)) u = s.copy() u ^= t print(sorted(s), "^=", sorted(t), '-->', sorted(u)) u = s.copy() u &= t print(sorted(s), "&=", sorted(t), "-->", sorted(u)) u = s.copy() u -= t print(sorted(s), "-=", sorted(t), "-->", sorted(u)) print(sorted(s), '==', sorted(t), '=', s == t) print(sorted(s), '!=', sorted(t), '=', s != t) print(sorted(s), '>', sorted(t), '=', s > t) print(sorted(s), '>=', sorted(t), '=', s >= t) print(sorted(s), '<', sorted(t), '=', s < t) print(sorted(s), '<=', sorted(t), '=', s <= t) print(set('abc') == 1) # make sure inplace operators modify the set s1 = s2 = set('abc') s1 |= set('ad') print(s1 is s2, len(s1)) s1 = s2 = set('abc') s1 ^= set('ad') print(s1 is s2, len(s1)) s1 = s2 = set('abc') s1 &= set('ad') print(s1 is s2, len(s1)) s1 = s2 = set('abc') s1 -= set('ad') print(s1 is s2, len(s1)) # RHS must be a set try: print(set('12') >= '1') except TypeError: print('TypeError') # RHS must be a set try: print(set('12') <= '123') except TypeError: print('TypeError') # unsupported operator try: set('abc') * set('abc') except TypeError: print('TypeError') # unsupported operator with RHS not a set try: set('abc') * 2 except TypeError: print('TypeError') micropython-1.12/tests/basics/set_clear.py000066400000000000000000000000611357706137100207400ustar00rootroot00000000000000s = {1, 2, 3, 4} print(s.clear()) print(list(s)) micropython-1.12/tests/basics/set_comprehension.py000066400000000000000000000000351357706137100225240ustar00rootroot00000000000000print({a for a in range(5)}) micropython-1.12/tests/basics/set_containment.py000066400000000000000000000002301357706137100221670ustar00rootroot00000000000000for i in 1, 2: for o in {}, {1}, {2}: print("{} in {}: {}".format(i, o, i in o)) print("{} not in {}: {}".format(i, o, i not in o)) micropython-1.12/tests/basics/set_copy.py000066400000000000000000000001241357706137100206240ustar00rootroot00000000000000s = {1, 2, 3, 4} t = s.copy() s.add(5) t.add(7) for i in s, t: print(sorted(i)) micropython-1.12/tests/basics/set_difference.py000066400000000000000000000006071357706137100217520ustar00rootroot00000000000000l = [1, 2, 3, 4] s = set(l) outs = [s.difference(), s.difference({1}), s.difference({1}, [1, 2]), s.difference({1}, {1, 2}, {2, 3})] for out in outs: print(sorted(out)) s = set(l) print(s.difference_update()) print(sorted(s)) print(s.difference_update({1})) print(sorted(s)) print(s.difference_update({1}, [2])) print(sorted(s)) s.difference_update(s) print(s) micropython-1.12/tests/basics/set_discard.py000066400000000000000000000000561357706137100212670ustar00rootroot00000000000000s = {1, 2} print(s.discard(1)) print(list(s)) micropython-1.12/tests/basics/set_intersection.py000066400000000000000000000002421357706137100223610ustar00rootroot00000000000000s = {1, 2, 3, 4} print(sorted(s)) print(sorted(s.intersection({1, 3}))) print(sorted(s.intersection([3, 4]))) print(s.intersection_update([1])) print(sorted(s)) micropython-1.12/tests/basics/set_isdisjoint.py000066400000000000000000000002321357706137100220310ustar00rootroot00000000000000s = {1, 2, 3, 4} print(s.isdisjoint({1})) print(s.isdisjoint([2])) print(s.isdisjoint([])) print(s.isdisjoint({7,8,9,10})) print(s.isdisjoint([7,8,9,1])) micropython-1.12/tests/basics/set_isfooset.py000066400000000000000000000002721357706137100215110ustar00rootroot00000000000000sets = [set(), {1}, {1, 2, 3}, {3, 4, 5}, {5, 6, 7}] args = sets + [[1], [1, 2], [1, 2 ,3]] for i in sets: for j in args: print(i.issubset(j)) print(i.issuperset(j)) micropython-1.12/tests/basics/set_iter.py000066400000000000000000000000601357706137100206140ustar00rootroot00000000000000s = {1, 2, 3, 4} l = list(s) l.sort() print(l) micropython-1.12/tests/basics/set_iter_of_iter.py000066400000000000000000000000531357706137100223250ustar00rootroot00000000000000i = iter(iter({1, 2, 3})) print(sorted(i)) micropython-1.12/tests/basics/set_pop.py000066400000000000000000000006741357706137100204620ustar00rootroot00000000000000s = {1} print(s.pop()) try: print(s.pop(), "!!!") except KeyError: pass else: print("Failed to raise KeyError") # this tests an optimisation in mp_set_remove_first # N must not be equal to one of the values in hash_allocation_sizes N = 11 s = set(range(N)) while s: print(s.pop()) # last pop() should trigger the optimisation for i in range(N): s.add(i) # check that we can add the numbers back to the set print(sorted(s)) micropython-1.12/tests/basics/set_remove.py000066400000000000000000000013771357706137100211620ustar00rootroot00000000000000# basic test s = {1} print(s.remove(1)) print(list(s)) try: print(s.remove(1), "!!!") except KeyError as er: print('KeyError', er.args[0]) else: print("failed to raise KeyError") # test sets of varying size for n in range(20): print('testing set with {} items'.format(n)) for i in range(n): # create set s = set() for j in range(n): s.add(str(j)) print(len(s)) # delete an item s.remove(str(i)) print(len(s)) # check items for j in range(n): if str(j) in s: if j == i: print(j, 'in s, but it should not be') else: if j != i: print(j, 'not in s, but it should be') micropython-1.12/tests/basics/set_specialmeth.py000066400000000000000000000001401357706137100221460ustar00rootroot00000000000000# set object with special methods s = {1, 2} print(s.__contains__(1)) print(s.__contains__(3)) micropython-1.12/tests/basics/set_symmetric_difference.py000066400000000000000000000002511357706137100240410ustar00rootroot00000000000000print(sorted({1,2}.symmetric_difference({2,3}))) print(sorted({1,2}.symmetric_difference([2,3]))) s = {1,2} print(s.symmetric_difference_update({2,3})) print(sorted(s)) micropython-1.12/tests/basics/set_type.py000066400000000000000000000003601357706137100206350ustar00rootroot00000000000000# set type # This doesn't really work as expected, because {None} # leads SyntaxError during parsing. try: set except NameError: print("SKIP") raise SystemExit print(set) print(type(set()) == set) print(type({None}) == set) micropython-1.12/tests/basics/set_union.py000066400000000000000000000000361357706137100210040ustar00rootroot00000000000000print(sorted({1}.union({2}))) micropython-1.12/tests/basics/set_unop.py000066400000000000000000000002661357706137100206420ustar00rootroot00000000000000# test set unary operations print(bool(set())) print(bool(set('abc'))) print(len(set())) print(len(set('abc'))) try: hash(set('abc')) except TypeError: print('TypeError') micropython-1.12/tests/basics/set_update.py000066400000000000000000000001451357706137100211370ustar00rootroot00000000000000s = {1} s.update() print(s) s.update([2]) print(sorted(s)) s.update([1,3], [2,2,4]) print(sorted(s)) micropython-1.12/tests/basics/slice_attrs.py000066400000000000000000000006631357706137100213230ustar00rootroot00000000000000# test builtin slice attributes access # print slice attributes class A: def __getitem__(self, idx): print(idx.start, idx.stop, idx.step) try: t = A()[1:2] except: print("SKIP") raise SystemExit A()[1:2:3] # test storing to attr (shouldn't be allowed) class B: def __getitem__(self, idx): try: idx.start = 0 except AttributeError: print('AttributeError') B()[:] micropython-1.12/tests/basics/slice_intbig.py000066400000000000000000000002331357706137100214330ustar00rootroot00000000000000# test slicing when arguments are bignums print(list(range(10))[(1<<66)>>65:]) print(list(range(10))[:(1<<66)>>65]) print(list(range(10))[::(1<<66)>>65]) micropython-1.12/tests/basics/slots_bool_len.py000066400000000000000000000004361357706137100220220ustar00rootroot00000000000000class A: def __bool__(self): print('__bool__') return True def __len__(self): print('__len__') return 1 class B: def __len__(self): print('__len__') return 0 print(bool(A())) print(len(A())) print(bool(B())) print(len(B())) micropython-1.12/tests/basics/special_methods.py000066400000000000000000000044121357706137100221460ustar00rootroot00000000000000class Cud(): def __init__(self): print("__init__ called") def __repr__(self): print("__repr__ called") return "" def __lt__(self, other): print("__lt__ called") def __le__(self, other): print("__le__ called") def __eq__(self, other): print("__eq__ called") def __ne__(self, other): print("__ne__ called") def __ge__(self, other): print("__ge__ called") def __gt__(self, other): print("__gt__ called") def __abs__(self): print("__abs__ called") def __add__(self, other): print("__add__ called") def __and__(self, other): print("__and__ called") def __floordiv__(self, other): print("__floordiv__ called") def __index__(self, other): print("__index__ called") def __inv__(self): print("__inv__ called") def __invert__(self): print("__invert__ called") def __lshift__(self, val): print("__lshift__ called") def __mod__(self, val): print("__mod__ called") def __mul__(self, other): print("__mul__ called") def __matmul__(self, other): print("__matmul__ called") def __neg__(self): print("__neg__ called") def __or__(self, other): print("__or__ called") def __pos__(self): print("__pos__ called") def __pow__(self, val): print("__pow__ called") def __rshift__(self, val): print("__rshift__ called") def __sub__(self, other): print("__sub__ called") def __truediv__(self, other): print("__truediv__ called") def __div__(self, other): print("__div__ called") def __xor__(self, other): print("__xor__ called") def __iadd__(self, other): print("__iadd__ called") return self def __isub__(self, other): print("__isub__ called") return self def __int__(self): return 42 cud1 = Cud() cud2 = Cud() str(cud1) cud1 < cud2 cud1 <= cud2 cud1 == cud2 cud1 >= cud2 cud1 > cud2 cud1 + cud2 cud1 - cud2 print(int(cud1)) class BadInt: def __int__(self): print("__int__ called") return None try: int(BadInt()) except TypeError: print("TypeError") # more in special_methods2.py micropython-1.12/tests/basics/special_methods2.py000066400000000000000000000052161357706137100222330ustar00rootroot00000000000000class Cud(): def __init__(self): #print("__init__ called") pass def __repr__(self): print("__repr__ called") return "" def __lt__(self, other): print("__lt__ called") def __le__(self, other): print("__le__ called") def __eq__(self, other): print("__eq__ called") def __ne__(self, other): print("__ne__ called") def __ge__(self, other): print("__ge__ called") def __gt__(self, other): print("__gt__ called") def __abs__(self): print("__abs__ called") def __add__(self, other): print("__add__ called") def __and__(self, other): print("__and__ called") def __floordiv__(self, other): print("__floordiv__ called") def __index__(self, other): print("__index__ called") def __inv__(self): print("__inv__ called") def __invert__(self): print("__invert__ called") def __lshift__(self, val): print("__lshift__ called") def __mod__(self, val): print("__mod__ called") def __mul__(self, other): print("__mul__ called") def __matmul__(self, other): print("__matmul__ called") def __neg__(self): print("__neg__ called") def __or__(self, other): print("__or__ called") def __pos__(self): print("__pos__ called") def __pow__(self, val): print("__pow__ called") def __rshift__(self, val): print("__rshift__ called") def __sub__(self, other): print("__sub__ called") def __truediv__(self, other): print("__truediv__ called") def __div__(self, other): print("__div__ called") def __xor__(self, other): print("__xor__ called") def __iadd__(self, other): print("__iadd__ called") return self def __isub__(self, other): print("__isub__ called") return self def __dir__(self): return ['a', 'b', 'c'] cud1 = Cud() cud2 = Cud() try: +cud1 except TypeError: print("SKIP") raise SystemExit # the following require MICROPY_PY_ALL_SPECIAL_METHODS +cud1 -cud1 ~cud1 cud1 * cud2 cud1 @ cud2 cud1 / cud2 cud2 // cud1 cud1 += cud2 cud1 -= cud2 cud1 % 2 cud1 ** 2 cud1 | cud2 cud1 & cud2 cud1 ^ cud2 cud1 << 1 cud1 >> 1 # test that dir() delegates to __dir__ special method print(dir(cud1)) # test that dir() does not delegate to __dir__ for the type print('a' in dir(Cud)) # TODO: the following operations are not supported on every ports # # ne is not supported, !(eq) is called instead #cud1 != cud2 # # in the following test, cpython still calls __eq__ # cud3=cud1 # cud3==cud1 micropython-1.12/tests/basics/special_methods2.py.exp000066400000000000000000000004531357706137100230240ustar00rootroot00000000000000__pos__ called __pos__ called __neg__ called __invert__ called __mul__ called __matmul__ called __truediv__ called __floordiv__ called __iadd__ called __isub__ called __mod__ called __pow__ called __or__ called __and__ called __xor__ called __lshift__ called __rshift__ called ['a', 'b', 'c'] False micropython-1.12/tests/basics/string1.py000066400000000000000000000014341357706137100203730ustar00rootroot00000000000000# basic strings # literals print('abc') print(r'abc') print(u'abc') print(repr('\a\b\t\n\v\f\r')) print('\z') # unrecognised escape char # construction print(str()) print(str('abc')) # inplace addition x = 'abc' print(x) x += 'def' print(x) # binary ops print('123' + "456") print('123' * 5) try: '123' * '1' except TypeError: print('TypeError') try: '123' + 1 except TypeError: print('TypeError') # subscription print('abc'[1]) print('abc'[-1]) try: 'abc'[100] except IndexError: print('IndexError') try: 'abc'[-4] except IndexError: print('IndexError') # iter print(list('str')) # comparison print('123' + '789' == '123789') print('a' + 'b' != 'a' + 'b ') print('1' + '2' > '2') print('1' + '2' < '2') # printing quote char in string print(repr('\'\"')) micropython-1.12/tests/basics/string_center.py000066400000000000000000000003461357706137100216530ustar00rootroot00000000000000try: str.center except: print("SKIP") raise SystemExit print("foo".center(0)) print("foo".center(1)) print("foo".center(3)) print("foo".center(4)) print("foo".center(5)) print("foo".center(6)) print("foo".center(20)) micropython-1.12/tests/basics/string_compare.py000066400000000000000000000021201357706137100220110ustar00rootroot00000000000000print("" == "") print("" > "") print("" < "") print("" == "1") print("1" == "") print("" > "1") print("1" > "") print("" < "1") print("1" < "") print("" >= "1") print("1" >= "") print("" <= "1") print("1" <= "") print("1" == "1") print("1" != "1") print("1" == "2") print("1" == "10") print("1" > "1") print("1" > "2") print("2" > "1") print("10" > "1") print("1/" > "1") print("1" > "10") print("1" > "1/") print("1" < "1") print("2" < "1") print("1" < "2") print("1" < "10") print("1" < "1/") print("10" < "1") print("1/" < "1") print("1" >= "1") print("1" >= "2") print("2" >= "1") print("10" >= "1") print("1/" >= "1") print("1" >= "10") print("1" >= "1/") print("1" <= "1") print("2" <= "1") print("1" <= "2") print("1" <= "10") print("1" <= "1/") print("10" <= "1") print("1/" <= "1") # this tests an internal string that doesn't have a hash with a string # that does have a hash, but the lengths of the two strings are different import sys print(sys.version == 'a long string that has a hash') # this special string would have a hash of 0 but is incremented to 1 print('Q+?' == 'Q' + '+?') micropython-1.12/tests/basics/string_count.py000066400000000000000000000024101357706137100215150ustar00rootroot00000000000000try: str.count except AttributeError: print("SKIP") raise SystemExit print("".count("")) print("".count("a")) print("a".count("")) print("a".count("a")) print("a".count("b")) print("b".count("a")) print("aaa".count("")) print("aaa".count("a")) print("aaa".count("aa")) print("aaa".count("aaa")) print("aaa".count("aaaa")) print("aaaa".count("")) print("aaaa".count("a")) print("aaaa".count("aa")) print("aaaa".count("aaa")) print("aaaa".count("aaaa")) print("aaaa".count("aaaaa")) print("aaa".count("", 1)) print("aaa".count("", 2)) print("aaa".count("", 3)) print("aaa".count("", 1, 2)) print("asdfasdfaaa".count("asdf", -100)) print("asdfasdfaaa".count("asdf", -8)) print("asdf".count('s', True)) print("asdf".count('a', True)) print("asdf".count('a', False)) print("asdf".count('a', 1 == 2)) print("hello world".count('l')) print("hello world".count('l', 5)) print("hello world".count('l', 3)) print("hello world".count('z', 3, 6)) print("aaaa".count('a')) print("aaaa".count('a', 0, 3)) print("aaaa".count('a', 0, 4)) print("aaaa".count('a', 0, 5)) print("aaaa".count('a', 1, 5)) print("aaaa".count('a', -1, 5)) print("abbabba".count("abba")) def t(): return True print("0000".count('0', t())) try: 'abc'.count(1) except TypeError: print('TypeError') micropython-1.12/tests/basics/string_cr_conversion.py000066400000000000000000000001771357706137100232460ustar00rootroot00000000000000# this file has CR line endings to test lexer's conversion of them to LF # in triple quoted strings print(repr("""abc def""")) micropython-1.12/tests/basics/string_crlf_conversion.py000066400000000000000000000002051357706137100235600ustar00rootroot00000000000000# this file has CRLF line endings to test lexer's conversion of them to LF # in triple quoted strings print(repr("""abc def""")) micropython-1.12/tests/basics/string_endswith.py000066400000000000000000000007071357706137100222210ustar00rootroot00000000000000print("foobar".endswith("bar")) print("foobar".endswith("baR")) print("foobar".endswith("bar1")) print("foobar".endswith("foobar")) print("foobar".endswith("")) print("foobar".endswith("foobarbaz")) #print("1foobar".startswith("foo", 1)) #print("1foo".startswith("foo", 1)) #print("1foo".startswith("1foo", 1)) #print("1fo".startswith("foo", 1)) #print("1fo".startswith("foo", 10)) try: "foobar".endswith(1) except TypeError: print("TypeError") micropython-1.12/tests/basics/string_endswith_upy.py000066400000000000000000000002021357706137100231040ustar00rootroot00000000000000# MicroPython doesn't support tuple argument try: "foobar".endswith(("bar", "sth")) except TypeError: print("TypeError") micropython-1.12/tests/basics/string_endswith_upy.py.exp000066400000000000000000000000121357706137100236760ustar00rootroot00000000000000TypeError micropython-1.12/tests/basics/string_escape.py000066400000000000000000000002321357706137100216250ustar00rootroot00000000000000a = "a\1b" print(len(a)) print(ord(a[1])) print(len("a\123b")) a = "a\12345b" print(len(a)) print(ord(a[1])) a = "a\xffb" print(len(a)) print(ord(a[1])) micropython-1.12/tests/basics/string_find.py000066400000000000000000000015301357706137100213070ustar00rootroot00000000000000print("hello world".find("ll")) print("hello world".find("ll", None)) print("hello world".find("ll", 1)) print("hello world".find("ll", 1, None)) print("hello world".find("ll", None, None)) print("hello world".find("ll", 1, -1)) print("hello world".find("ll", 1, 1)) print("hello world".find("ll", 1, 2)) print("hello world".find("ll", 1, 3)) print("hello world".find("ll", 1, 4)) print("hello world".find("ll", 1, 5)) print("hello world".find("ll", -100)) print("0000".find('0')) print("0000".find('0', 0)) print("0000".find('0', 1)) print("0000".find('0', 2)) print("0000".find('0', 3)) print("0000".find('0', 4)) print("0000".find('0', 5)) print("0000".find('-1', 3)) print("0000".find('1', 3)) print("0000".find('1', 4)) print("0000".find('1', 5)) print("aaaaaaaaaaa".find("bbb", 9, 2)) try: 'abc'.find(1) except TypeError: print('TypeError') micropython-1.12/tests/basics/string_format.py000066400000000000000000000032141357706137100216600ustar00rootroot00000000000000# basic functionality test for {} format string def test(fmt, *args): print('{:8s}'.format(fmt) + '>' + fmt.format(*args) + '<') test("}}{{") test("{}-{}", 1, [4, 5]) test("{0}-{1}", 1, [4, 5]) test("{1}-{0}", 1, [4, 5]) test("{:x}", 1) test("{!r}", 2) test("{:x}", 0x10) test("{!r}", "foo") test("{!s}", "foo") test("{0!r:>10s} {0!s:>10s}", "foo") test("{:4b}", 10) test("{:4c}", 48) test("{:4d}", 123) test("{:4n}", 123) test("{:4o}", 123) test("{:4x}", 123) test("{:4X}", 123) test("{:4,d}", 12345678) test("{:#4b}", 10) test("{:#4o}", 123) test("{:#4x}", 123) test("{:#4X}", 123) test("{:#4d}", 0) test("{:#4b}", 0) test("{:#4o}", 0) test("{:#4x}", 0) test("{:#4X}", 0) test("{:<6s}", "ab") test("{:>6s}", "ab") test("{:^6s}", "ab") test("{:.1s}", "ab") test("{: <6d}", 123) test("{: <6d}", -123) test("{:0<6d}", 123) test("{:0<6d}", -123) test("{:@<6d}", 123) test("{:@<6d}", -123) test("{:@< 6d}", 123) test("{:@< 6d}", -123) test("{:@<+6d}", 123) test("{:@<+6d}", -123) test("{:@<-6d}", 123) test("{:@<-6d}", -123) test("{:@>6d}", -123) test("{:@<6d}", -123) test("{:@=6d}", -123) test("{:06d}", -123) test("{:>20}", "foo") test("{:^20}", "foo") test("{:<20}", "foo") # nested format specifiers print("{:{}}".format(123, '#>10')) print("{:{}{}{}}".format(123, '#', '>', '10')) print("{0:{1}{2}}".format(123, '#>', '10')) print("{text:{align}{width}}".format(text="foo", align="<", width=20)) print("{text:{align}{width}}".format(text="foo", align="^", width=10)) print("{text:{align}{width}}".format(text="foo", align=">", width=30)) print("{foo}/foo".format(foo="bar")) print("{}".format(123, foo="bar")) print("{}-{foo}".format(123, foo="bar")) micropython-1.12/tests/basics/string_format2.py000066400000000000000000000037511357706137100217500ustar00rootroot00000000000000# comprehensive functionality test for {} format string int_tests = False # these take a while char_tests = True str_tests = True def test(fmt, *args): print('{:8s}'.format(fmt) + '>' + fmt.format(*args) + '<') def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg): fmt = '{' if conv: fmt += '!' fmt += conv fmt += ':' if alignment: fmt += fill fmt += alignment fmt += sign fmt += prefix fmt += width if precision: fmt += '.' fmt += precision fmt += type fmt += '}' test(fmt, arg) if fill == '0' and alignment == '=': fmt = '{:' fmt += sign fmt += prefix fmt += width if precision: fmt += '.' fmt += precision fmt += type fmt += '}' test(fmt, arg) if int_tests: int_nums = (-1234, -123, -12, -1, 0, 1, 12, 123, 1234, True, False) #int_nums = (-12, -1, 0, 1, 12, True, False) for type in ('', 'b', 'd', 'o', 'x', 'X'): for width in ('', '1', '3', '5', '7'): for alignment in ('', '<', '>', '=', '^'): for fill in ('', ' ', '0', '@'): for sign in ('', '+', '-', ' '): for prefix in ('', '#'): for num in int_nums: test_fmt('', fill, alignment, sign, prefix, width, '', type, num) if char_tests: for width in ('', '1', '2'): for alignment in ('', '<', '>', '^'): for fill in ('', ' ', '0', '@'): test_fmt('', fill, alignment, '', '', width, '', 'c', 48) if str_tests: for conv in ('', 'r', 's'): for width in ('', '1', '4', '10'): for alignment in ('', '<', '>', '^'): for fill in ('', ' ', '0', '@'): for str in ('', 'a', 'bcd', 'This is a test with a longer string'): test_fmt(conv, fill, alignment, '', '', width, '', 's', str) micropython-1.12/tests/basics/string_format_error.py000066400000000000000000000026071357706137100230760ustar00rootroot00000000000000# tests for errors in {} format string try: '{0:0}'.format('zzz') except (ValueError): print('ValueError') try: '{1:}'.format(1) except IndexError: print('IndexError') try: '}'.format('zzzz') except ValueError: print('ValueError') # end of format parsing conversion specifier try: '{!'.format('a') except ValueError: print('ValueError') # unknown conversion specifier try: 'abc{!d}'.format('1') except ValueError: print('ValueError') try: '{abc'.format('zzzz') except ValueError: print('ValueError') # expected ':' after specifier try: '{!s :}'.format(2) except ValueError: print('ValueError') try: '{}{0}'.format(1, 2) except ValueError: print('ValueError') try: '{1:}'.format(1) except IndexError: print('IndexError') try: '{ 0 :*^10}'.format(12) except KeyError: print('KeyError') try: '{0}{}'.format(1) except ValueError: print('ValueError') try: '{}{}'.format(1) except IndexError: print('IndexError') try: '{0:+s}'.format('1') except ValueError: print('ValueError') try: '{0:+c}'.format(1) except ValueError: print('ValueError') try: '{0:s}'.format(1) except ValueError: print('ValueError') try: '{:*"1"}'.format('zz') except ValueError: print('ValueError') # unknown format code for str arg try: '{:X}'.format('zz') except ValueError: print('ValueError') micropython-1.12/tests/basics/string_format_modulo.py000066400000000000000000000034671357706137100232510ustar00rootroot00000000000000try: '' % () except TypeError: print("SKIP") raise SystemExit print("%%" % ()) print("=%s=" % 1) print("=%s=%s=" % (1, 2)) print("=%s=" % (1,)) print("=%s=" % [1, 2]) print("=%s=" % "str") print("=%r=" % "str") try: print("=%s=%s=" % 1) except TypeError: print("TypeError") try: print("=%s=%s=%s=" % (1, 2)) except TypeError: print("TypeError") try: print("=%s=" % (1, 2)) except TypeError: print("TypeError") print("%s" % True) print("%s" % 1) print("%.1s" % "ab") print("%r" % True) print("%r" % 1) print("%c" % 48) print("%c" % 'a') print("%10s" % 'abc') print("%-10s" % 'abc') # Should be able to print dicts; in this case they aren't used # to lookup keywords in formats like %(foo)s print('%s' % {}) print('%s' % ({},)) # Cases when "*" used and there's not enough values total try: print("%*s" % 5) except TypeError: print("TypeError") try: print("%*.*s" % (1, 15)) except TypeError: print("TypeError") print("%(foo)s" % {"foo": "bar", "baz": False}) print("%s %(foo)s %(foo)s" % {"foo": 1}) try: print("%(foo)s" % {}) except KeyError: print("KeyError") # Using in "*" with dict got to fail try: print("%(foo)*s" % {"foo": "bar"}) except TypeError: print("TypeError") # When using %(foo)s format the single argument must be a dict try: '%(foo)s' % 1 except TypeError: print('TypeError') try: '%(foo)s' % ({},) except TypeError: print('TypeError') try: '%(a' % {'a':1} except ValueError: print('ValueError') try: '%.*d %.*d' % (20, 5) except TypeError: print('TypeError') try: a = '%*' % 1 except (ValueError): print('ValueError') try: '%c' % 'aa' except TypeError: print('TypeError') try: '%l' % 1 except ValueError: print('ValueError') try: 'a%' % 1 except ValueError: print('ValueError') micropython-1.12/tests/basics/string_format_modulo_int.py000066400000000000000000000016701357706137100241150ustar00rootroot00000000000000# test string modulo formatting with int values try: '' % () except TypeError: print("SKIP") raise SystemExit # basic cases print("%d" % 10) print("%+d" % 10) print("% d" % 10) print("%d" % -10) print("%d" % True) print("%i" % -10) print("%i" % True) print("%u" % -10) print("%u" % True) print("%x" % 18) print("%o" % 18) print("%X" % 18) print("%#x" % 18) print("%#X" % 18) print("%#6o" % 18) print("%#6x" % 18) print("%#06x" % 18) # with * print("%*d" % (5, 10)) print("%*.*d" % (2, 2, 20)) print("%*.*d" % (5, 8, 20)) # precision for val in (-12, 12): print(">%8.4d<" % val) print(">% 8.4d<" % val) print(">%+8.4d<" % val) print(">%08.4d<" % val) print(">%-8.4d<" % val) print(">%-08.4d<" % val) print(">%-+08.4d<" % val) # test + option with various amount of padding for pad in ('', ' ', '0'): for n in (1, 2, 3): for val in (-1, 0, 1): print(('%+' + pad + str(n) + 'd') % val) micropython-1.12/tests/basics/string_index.py000066400000000000000000000032601357706137100215000ustar00rootroot00000000000000print("hello world".index("ll")) print("hello world".index("ll", None)) print("hello world".index("ll", 1)) print("hello world".index("ll", 1, None)) print("hello world".index("ll", None, None)) print("hello world".index("ll", 1, -1)) try: print("hello world".index("ll", 1, 1)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("hello world".index("ll", 1, 2)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("hello world".index("ll", 1, 3)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") print("hello world".index("ll", 1, 4)) print("hello world".index("ll", 1, 5)) print("hello world".index("ll", -100)) print("0000".index('0')) print("0000".index('0', 0)) print("0000".index('0', 1)) print("0000".index('0', 2)) print("0000".index('0', 3)) try: print("0000".index('0', 4)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".index('0', 5)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".index('-1', 3)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".index('1', 3)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".index('1', 4)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".index('1', 5)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") micropython-1.12/tests/basics/string_istest.py000066400000000000000000000012051357706137100217010ustar00rootroot00000000000000print("".isspace()) print(" \t\n\r\v\f".isspace()) print("a".isspace()) print(" \t\n\r\v\fa".isspace()) print("".isalpha()) print("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".isalpha()) print("0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".isalpha()) print("this ".isalpha()) print("".isdigit()) print("0123456789".isdigit()) print("0123456789a".isdigit()) print("0123456789 ".isdigit()) print("".isupper()) print("CHEESE-CAKE WITH ... _FROSTING_*99".isupper()) print("aB".isupper()) print("".islower()) print("cheese-cake with ... _frosting_*99".islower()) print("aB".islower()) print("123".islower()) print("123a".islower()) micropython-1.12/tests/basics/string_join.py000066400000000000000000000013111357706137100213230ustar00rootroot00000000000000print(','.join(())) print(','.join(('a',))) print(','.join(('a', 'b'))) print(','.join([])) print(','.join(['a'])) print(','.join(['a', 'b'])) print(''.join('')) print(''.join('abc')) print(','.join('abc')) print(','.join('abc' for i in range(5))) print(b','.join([b'abc', b'123'])) try: ''.join(None) except TypeError: print("TypeError") try: print(b','.join(['abc', b'123'])) except TypeError: print("TypeError") try: print(','.join([b'abc', b'123'])) except TypeError: print("TypeError") # joined by the compiler print("a" "b") print("a" '''b''') print("a" # inline comment "b") print("a" \ "b") # the following should not be joined by the compiler x = 'a' 'b' print(x) micropython-1.12/tests/basics/string_large.py000066400000000000000000000015301357706137100214610ustar00rootroot00000000000000s1 = "long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string long string" s2 = "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" "concatenated string" micropython-1.12/tests/basics/string_mult.py000066400000000000000000000003631357706137100213530ustar00rootroot00000000000000# basic multiplication print('0' * 5) # check negative, 0, positive; lhs and rhs multiplication for i in (-4, -2, 0, 2, 4): print(i * '12') print('12' * i) # check that we don't modify existing object a = '123' c = a * 3 print(a, c) micropython-1.12/tests/basics/string_partition.py000066400000000000000000000017711357706137100224070ustar00rootroot00000000000000try: str.partition except AttributeError: print("SKIP") raise SystemExit print("asdf".partition('g')) print("asdf".partition('a')) print("asdf".partition('s')) print("asdf".partition('f')) print("asdf".partition('d')) print("asdf".partition('asd')) print("asdf".partition('sdf')) print("asdf".partition('as')) print("asdf".partition('df')) print("asdf".partition('asdf')) print("asdf".partition('asdfa')) print("asdf".partition('fasdf')) print("asdf".partition('fasdfa')) print("abba".partition('a')) print("abba".partition('b')) try: print("asdf".partition(1)) except TypeError: print("Raised TypeError") else: print("Did not raise TypeError") try: print("asdf".partition('')) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") # Bytes print(b"abba".partition(b'b')) try: print(b"abba".partition('b')) except TypeError: print("Raised TypeError") try: print("abba".partition(b'b')) except TypeError: print("Raised TypeError") micropython-1.12/tests/basics/string_replace.py000066400000000000000000000011171357706137100220030ustar00rootroot00000000000000print("".replace("a", "b")) print("aaa".replace("b", "c")) print("aaa".replace("a", "b", 0)) print("aaa".replace("a", "b", -5)) print("asdfasdf".replace("a", "b")) print("aabbaabbaabbaa".replace("aa", "cc", 3)) print("a".replace("aa", "bb")) print("testingtesting".replace("ing", "")) print("testINGtesting".replace("ing", "ING!")) print("".replace("", "1")) print("A".replace("", "1")) print("AB".replace("", "1")) print("AB".replace("", "12")) try: 'abc'.replace(1, 2) except TypeError: print('TypeError') try: 'abc'.replace('1', 2) except TypeError: print('TypeError') micropython-1.12/tests/basics/string_repr.py000066400000000000000000000002741357706137100213430ustar00rootroot00000000000000# anything above 0xa0 is printed as Unicode by CPython # the abobe is CPython implementation detail, stick to ASCII for c in range(0x80): print("0x{:02x}: {}".format(c, repr(chr(c)))) micropython-1.12/tests/basics/string_rfind.py000066400000000000000000000014571357706137100215010ustar00rootroot00000000000000print("hello world".rfind("ll")) print("hello world".rfind("ll", None)) print("hello world".rfind("ll", 1)) print("hello world".rfind("ll", 1, None)) print("hello world".rfind("ll", None, None)) print("hello world".rfind("ll", 1, -1)) print("hello world".rfind("ll", 1, 1)) print("hello world".rfind("ll", 1, 2)) print("hello world".rfind("ll", 1, 3)) print("hello world".rfind("ll", 1, 4)) print("hello world".rfind("ll", 1, 5)) print("hello world".rfind("ll", -100)) print("0000".rfind('0')) print("0000".rfind('0', 0)) print("0000".rfind('0', 1)) print("0000".rfind('0', 2)) print("0000".rfind('0', 3)) print("0000".rfind('0', 4)) print("0000".rfind('0', 5)) print("0000".rfind('-1', 3)) print("0000".rfind('1', 3)) print("0000".rfind('1', 4)) print("0000".rfind('1', 5)) print("aaaaaaaaaaa".rfind("bbb", 9, 2)) micropython-1.12/tests/basics/string_rindex.py000066400000000000000000000033071357706137100216640ustar00rootroot00000000000000print("hello world".rindex("ll")) print("hello world".rindex("ll", None)) print("hello world".rindex("ll", 1)) print("hello world".rindex("ll", 1, None)) print("hello world".rindex("ll", None, None)) print("hello world".rindex("ll", 1, -1)) try: print("hello world".rindex("ll", 1, 1)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("hello world".rindex("ll", 1, 2)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("hello world".rindex("ll", 1, 3)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") print("hello world".rindex("ll", 1, 4)) print("hello world".rindex("ll", 1, 5)) print("hello world".rindex("ll", -100)) print("0000".rindex('0')) print("0000".rindex('0', 0)) print("0000".rindex('0', 1)) print("0000".rindex('0', 2)) print("0000".rindex('0', 3)) try: print("0000".rindex('0', 4)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".rindex('0', 5)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".rindex('-1', 3)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".rindex('1', 3)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".rindex('1', 4)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") try: print("0000".rindex('1', 5)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") micropython-1.12/tests/basics/string_rpartition.py000066400000000000000000000014641357706137100225700ustar00rootroot00000000000000try: str.partition except AttributeError: print("SKIP") raise SystemExit print("asdf".rpartition('g')) print("asdf".rpartition('a')) print("asdf".rpartition('s')) print("asdf".rpartition('f')) print("asdf".rpartition('d')) print("asdf".rpartition('asd')) print("asdf".rpartition('sdf')) print("asdf".rpartition('as')) print("asdf".rpartition('df')) print("asdf".rpartition('asdf')) print("asdf".rpartition('asdfa')) print("asdf".rpartition('fasdf')) print("asdf".rpartition('fasdfa')) print("abba".rpartition('a')) print("abba".rpartition('b')) try: print("asdf".rpartition(1)) except TypeError: print("Raised TypeError") else: print("Did not raise TypeError") try: print("asdf".rpartition('')) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") micropython-1.12/tests/basics/string_rsplit.py000066400000000000000000000027661357706137100217200ustar00rootroot00000000000000# default separator (whitespace) print("a b".rsplit()) #print(" a b ".rsplit(None)) #print(" a b ".rsplit(None, 1)) #print(" a b ".rsplit(None, 2)) #print(" a b c ".rsplit(None, 1)) #print(" a b c ".rsplit(None, 0)) #print(" a b c ".rsplit(None, -1)) # empty separator should fail (this actually delegates to .split()) try: "abc".rsplit('') except ValueError: print("ValueError") # empty separator should fail (error handled in .rsplit()) try: 'a a a a'.rsplit('', 5) except ValueError: print('ValueError') # bad separator type try: 'a a a a'.rsplit(1) except TypeError: print('TypeError') # non-empty separator print("abc".rsplit("a")) print("abc".rsplit("b")) print("abc".rsplit("c")) print("abc".rsplit("z")) print("abc".rsplit("ab")) print("abc".rsplit("bc")) print("abc".rsplit("abc")) print("abc".rsplit("abcd")) print("abcabc".rsplit("bc")) print("abcabc".rsplit("bc", 0)) print("abcabc".rsplit("bc", 1)) print("abcabc".rsplit("bc", 2)) print("10/11/12".rsplit("/", 1)) print("10/11/12".rsplit("/", 2)) print("10/11/12".rsplit("/", 3)) print("10/11/12".rsplit("/", 4)) print("10/11/12".rsplit("/", 5)) print("/*10/*11/*12/*".rsplit("/*", 1)) print("/*10/*11/*12/*".rsplit("/*", 2)) print("/*10/*11/*12/*".rsplit("/*", 3)) print("/*10/*11/*12/*".rsplit("/*", 4)) print("/*10/*11/*12/*".rsplit("/*", 5)) print(b"abcabc".rsplit(b"bc", 2)) # negative "maxsplit" should delegate to .split() print('abaca'.rsplit('a', -1)) print('abaca'.rsplit('a', -2)) micropython-1.12/tests/basics/string_slice.py000066400000000000000000000010531357706137100214660ustar00rootroot00000000000000print("123"[0:1]) print("123"[0:2]) print("123"[:1]) print("123"[1:]) # Idiom for copying sequence print("123"[:]) print("123"[:-1]) # Weird cases print("123"[0:0]) print("123"[1:0]) print("123"[1:1]) print("123"[-1:-1]) print("123"[-3:]) print("123"[-3:3]) print("123"[0:]) print("123"[:0]) print("123"[:-3]) print("123"[:-4]) # Range check testing, don't segfault, please ;-) print("123"[:1000000]) print("123"[1000000:]) print("123"[:-1000000]) print("123"[-1000000:]) # No IndexError! print(""[1:1]) print(""[-1:-1]) # bytes print(b"123"[0:2]) micropython-1.12/tests/basics/string_split.py000066400000000000000000000014611357706137100215250ustar00rootroot00000000000000# default separator (whitespace) print("a b".split()) print(" a b ".split(None)) print(" a b ".split(None, 1)) print(" a b ".split(None, 2)) print(" a b c ".split(None, 1)) print(" a b c ".split(None, 0)) print(" a b c ".split(None, -1)) print("foo\n\t\x07\v\nbar".split()) print("foo\nbar\n".split()) # empty separator should fail try: "abc".split('') except ValueError: print("ValueError") # non-empty separator print("abc".split("a")) print("abc".split("b")) print("abc".split("c")) print("abc".split("z")) print("abc".split("ab")) print("abc".split("bc")) print("abc".split("abc")) print("abc".split("abcd")) print("abcabc".split("bc")) print("abcabc".split("bc", 0)) print("abcabc".split("bc", 1)) print("abcabc".split("bc", 2)) print(b"abcabc".split(b"bc", 2)) micropython-1.12/tests/basics/string_splitlines.py000066400000000000000000000017621357706137100225640ustar00rootroot00000000000000# test string.splitlines() method try: str.splitlines except: print("SKIP") raise SystemExit # test \n as newline print("foo\nbar".splitlines()) print("foo\nbar\n".splitlines()) print("foo and\nbar\n".splitlines()) print("foo\nbar\n\n".splitlines()) print("foo\n\nbar\n\n".splitlines()) print("\nfoo\nbar\n".splitlines()) # test \r as newline print("foo\rbar\r".splitlines()) print("\rfoo and\r\rbar\r".splitlines()) # test \r\n as newline print("foo\r\nbar\r\n".splitlines()) print("\r\nfoo and\r\n\r\nbar\r\n".splitlines()) # test keepends arg print("foo\nbar".splitlines(True)) print("foo\nbar\n".splitlines(True)) print("foo\nbar\n\n".splitlines(True)) print("foo\rbar".splitlines(keepends=True)) print("foo\rbar\r\r".splitlines(keepends=True)) print("foo\r\nbar".splitlines(keepends=True)) print("foo\r\nbar\r\n\r\n".splitlines(keepends=True)) # test splitting bytes objects print(b"foo\nbar".splitlines()) print(b"foo\nbar\n".splitlines()) print(b"foo\r\nbar\r\n\r\n".splitlines(True)) micropython-1.12/tests/basics/string_startswith.py000066400000000000000000000006501357706137100226050ustar00rootroot00000000000000print("foobar".startswith("foo")) print("foobar".startswith("Foo")) print("foobar".startswith("foo1")) print("foobar".startswith("foobar")) print("foobar".startswith("")) print("1foobar".startswith("foo", 1)) print("1foo".startswith("foo", 1)) print("1foo".startswith("1foo", 1)) print("1fo".startswith("foo", 1)) print("1fo".startswith("foo", 10)) try: "foobar".startswith(1) except TypeError: print("TypeError") micropython-1.12/tests/basics/string_startswith_upy.py000066400000000000000000000002041357706137100234750ustar00rootroot00000000000000# MicroPython doesn't support tuple argument try: "foobar".startswith(("foo", "sth")) except TypeError: print("TypeError") micropython-1.12/tests/basics/string_startswith_upy.py.exp000066400000000000000000000000121357706137100242650ustar00rootroot00000000000000TypeError micropython-1.12/tests/basics/string_strip.py000066400000000000000000000017341357706137100215360ustar00rootroot00000000000000print("".strip()) print(" \t\n\r\v\f".strip()) print(" T E S T".strip()) print("abcabc".strip("ce")) print("aaa".strip("b")) print("abc efg ".strip("g a")) print(' spacious '.lstrip()) print('www.example.com'.lstrip('cmowz.')) print(' spacious '.rstrip()) print('mississippi'.rstrip('ipz')) print(b'mississippi'.rstrip(b'ipz')) try: print(b'mississippi'.rstrip('ipz')) except TypeError: print("TypeError") try: print('mississippi'.rstrip(b'ipz')) except TypeError: print("TypeError") # single-char subj string used to give a problem print("a".strip()) print("a".lstrip()) print("a".rstrip()) print(" a".strip()) print(" a".lstrip()) print(" a".rstrip()) print("a ".strip()) print("a ".lstrip()) print("a ".rstrip()) # \0 used to give a problem print("\0abc\0".strip()) print("\0abc\0".lstrip()) print("\0abc\0".rstrip()) print("\0abc\0".strip("\0")) # Test that stripping unstrippable string returns original object s = "abc" print(id(s.strip()) == id(s)) micropython-1.12/tests/basics/string_upperlow.py000066400000000000000000000001601357706137100222420ustar00rootroot00000000000000print("".lower()) print(" t\tn\nr\rv\vf\f".upper()) print(" T E S T".lower()) print("*@a1b2cabc_[]/\\".upper()) micropython-1.12/tests/basics/struct1.py000066400000000000000000000044261357706137100204150ustar00rootroot00000000000000try: import ustruct as struct except: try: import struct except ImportError: print("SKIP") raise SystemExit print(struct.calcsize("bI")) print(struct.unpack(">bI", b"\x80\0\0\x01\0")) # 32-bit little-endian specific #print(struct.unpack("bI", b"\x80\xaa\x55\xaa\0\0\x01\0")) print(struct.pack("l", 1)) print(struct.pack("i", 1)) print(struct.pack("h", 1)) print(struct.pack("b", 1)) print(struct.pack("bI", -128, 256)) print(struct.calcsize("100sI")) print(struct.calcsize("97sI")) print(struct.unpack("<6sH", b"foo\0\0\0\x12\x34")) print(struct.pack("<6sH", b"foo", 10000)) s = struct.pack("BHBI", 10, 100, 200, 300) v = struct.unpack("BHBI", s) print(v == (10, 100, 200, 300)) # network byte order print(struct.pack('!i', 123)) # check that we get an error if the buffer is too small try: struct.unpack('I', b'\x00\x00\x00') except: print('struct.error') # first arg must be a string try: struct.pack(1, 2) except TypeError: print('TypeError') # make sure that unknown types are detected try: struct.pack("z", 1) except: print("Unknown type") # Initially repitition counters were supported only for strings, # but later were implemented for all. print(struct.unpack("<3B2h", b"foo\x12\x34\xff\xff")) print(struct.pack("<3B", 1, 2, 3)) # pack_into buf = bytearray(b'>>>123<<<') struct.pack_into('Q", 1)) print(struct.pack("Q", 2**64 - 1)) print(struct.pack("Q", 0xffffffffffffffff)) print(struct.pack("q", -1)) print(struct.pack("Q", 1234567890123456789)) print(struct.pack(">q", -1234567890123456789)) print(struct.unpack("Q", b"\x12\x34\x56\x78\x90\x12\x34\x56")) print(struct.unpack("q", b"\xf2\x34\x56\x78\x90\x12\x34\x56")) # check maximum unpack print(struct.unpack("----<<<<<<<') struct.pack_into('i', buf, 1, 0x30313233) print(buf) struct.pack_into('@ii', buf, 3, 0x34353637, 0x41424344) print(buf) micropython-1.12/tests/basics/struct_micropython.py000066400000000000000000000014311357706137100227600ustar00rootroot00000000000000# test MicroPython-specific features of struct try: import ustruct as struct except: try: import struct except ImportError: print("SKIP") raise SystemExit class A(): pass # pack and unpack objects o = A() s = struct.pack("subscr print(a[-1]) a[0] = -1 print(a) # Test another base type unary op print(len(a)) # Test binary op of base type, with 2nd arg being raw base type print(a + [20, 30, 40]) # Test binary op of base type, with 2nd arg being same class as 1st arg # TODO: Faults #print(a + a) def foo(): print("hello from foo") try: class myfunc(type(foo)): pass except TypeError: print("TypeError") # multiple bases with layout conflict try: class A(type, tuple): None except TypeError: print('TypeError') micropython-1.12/tests/basics/subclass_native2_list.py000066400000000000000000000011131357706137100233000ustar00rootroot00000000000000class Base1: def __init__(self, *args): print("Base1.__init__", args) class Clist1(Base1, list): pass a = Clist1() print(len(a)) # Not compliant - list assignment should happen in list.__init__, which is not called # because there's Base1.__init__, but we assign in list.__new__ #a = Clist1([1, 2, 3]) #print(len(a)) print("---") class Clist2(list, Base1): pass # Not compliant - should call list.__init__, but we don't have it #a = Clist2() #print(len(a)) # Not compliant - should call list.__init__, but we don't have it #a = Clist2([1, 2, 3]) #print(len(a)) micropython-1.12/tests/basics/subclass_native2_tuple.py000066400000000000000000000004621357706137100234640ustar00rootroot00000000000000class Base1: def __init__(self, *args): print("Base1.__init__", args) class Ctuple1(Base1, tuple): pass a = Ctuple1() print(len(a)) a = Ctuple1([1, 2, 3]) print(len(a)) print("---") class Ctuple2(tuple, Base1): pass a = Ctuple2() print(len(a)) a = Ctuple2([1, 2, 3]) print(len(a)) micropython-1.12/tests/basics/subclass_native3.py000066400000000000000000000005761357706137100222620ustar00rootroot00000000000000class MyExc(Exception): pass e = MyExc(100, "Some error") print(e) print(repr(e)) print(e.args) try: raise MyExc("Some error", 1) except MyExc as e: print("Caught exception:", repr(e)) try: raise MyExc("Some error2", 2) except Exception as e: print("Caught exception:", repr(e)) try: raise MyExc("Some error2") except: print("Caught user exception") micropython-1.12/tests/basics/subclass_native4.py000066400000000000000000000002211357706137100222460ustar00rootroot00000000000000# Test calling non-special method inherited from native type class mylist(list): pass l = mylist([1, 2, 3]) print(l) l.append(10) print(l) micropython-1.12/tests/basics/subclass_native5.py000066400000000000000000000002461357706137100222560ustar00rootroot00000000000000# Subclass from 2 bases explicitly subclasses from object class Base1(object): pass class Base2(object): pass class Sub(Base1, Base2): pass o = Sub() micropython-1.12/tests/basics/subclass_native_buffer.py000066400000000000000000000004761357706137100235270ustar00rootroot00000000000000# test when we subclass a type with the buffer protocol class my_bytes(bytes): pass b1 = my_bytes([0, 1]) b2 = my_bytes([2, 3]) b3 = bytes([4, 5]) # addition will use the buffer protocol on the RHS print(b1 + b2) print(b1 + b3) print(b3 + b1) # bytes construction will use the buffer protocol print(bytes(b1)) micropython-1.12/tests/basics/subclass_native_call.py000066400000000000000000000012641357706137100231650ustar00rootroot00000000000000# test calling a subclass of a native class that supports calling # For this test we need a native class that can be subclassed (has make_new) # and is callable (has call). The only one available is machine.Signal, which # in turns needs PinBase. try: try: import umachine as machine except ImportError: import machine machine.PinBase machine.Signal except: print("SKIP") raise SystemExit class Pin(machine.PinBase): #def __init__(self): # self.v = 0 def value(self, v=None): return 42 class MySignal(machine.Signal): pass s = MySignal(Pin()) # apply call to the subclass, which should call the native base print(s()) micropython-1.12/tests/basics/subclass_native_call.py.exp000066400000000000000000000000031357706137100237460ustar00rootroot0000000000000042 micropython-1.12/tests/basics/subclass_native_cmp.py000066400000000000000000000002521357706137100230250ustar00rootroot00000000000000# Test calling non-special method inherited from native type class mytuple(tuple): pass t = mytuple((1, 2, 3)) print(t) print(t == (1, 2, 3)) print((1, 2, 3) == t) micropython-1.12/tests/basics/subclass_native_containment.py000066400000000000000000000004611357706137100245670ustar00rootroot00000000000000# test containment operator on subclass of a native type class mylist(list): pass class mydict(dict): pass class mybytes(bytes): pass l = mylist([1, 2, 3]) print(0 in l) print(1 in l) d = mydict({1:1, 2:2}) print(0 in l) print(1 in l) b = mybytes(b'1234') print(0 in b) print(b'1' in b) micropython-1.12/tests/basics/subclass_native_init.py000066400000000000000000000015671357706137100232230ustar00rootroot00000000000000# test subclassing a native type and overriding __init__ # overriding list.__init__() class L(list): def __init__(self, a, b): super().__init__([a, b]) print(L(2, 3)) # inherits implicitly from object class A: def __init__(self): print("A.__init__") super().__init__() A() # inherits explicitly from object class B(object): def __init__(self): print("B.__init__") super().__init__() B() # multiple inheritance with object explicitly mentioned class C: pass class D(C, object): def __init__(self): print('D.__init__') super().__init__() def reinit(self): print('D.foo') super().__init__() a = D() a.__init__() a.reinit() # call __init__() after object is already init'd class L(list): def reinit(self): super().__init__(range(2)) a = L(range(5)) print(a) a.reinit() print(a) micropython-1.12/tests/basics/subclass_native_iter.py000066400000000000000000000002161357706137100232110ustar00rootroot00000000000000# test subclassing a native type which can be iterated over class mymap(map): pass m = mymap(lambda x: x + 10, range(4)) print(list(m)) micropython-1.12/tests/basics/subclass_native_specmeth.py000066400000000000000000000004321357706137100240560ustar00rootroot00000000000000# Test calling non-special method inherited from native type class mylist(list): pass l = mylist([1, 2, 3]) print(l) print([e for e in l]) class mylist2(list): def __iter__(self): return iter([10, 20, 30]) l = mylist2([1, 2, 3]) print(l) print([e for e in l]) micropython-1.12/tests/basics/syntaxerror.py000066400000000000000000000055521357706137100214110ustar00rootroot00000000000000# test syntax errors try: exec except NameError: print("SKIP") raise SystemExit def test_syntax(code): try: exec(code) print("no SyntaxError") except IndentationError: print("IndentationError") except SyntaxError: print("SyntaxError") # non-newline after line-continuation character (lexer error) test_syntax("a \\a\n") # dedent mismatch (lexer error) test_syntax("def f():\n a\n a\n") # unclosed string (lexer error) test_syntax("'abc") # invalid (lexer error) test_syntax("!") test_syntax("$") test_syntax("`") # bad indentation (lexer error) test_syntax(" a\n") # malformed integer literal (parser error) test_syntax("123z") # input doesn't match the grammar (parser error) test_syntax('1 or 2 or') test_syntax('{1:') # can't assign to literals test_syntax("1 = 2") test_syntax("'' = 1") test_syntax("{} = 1") # can't assign to comprehension test_syntax("(i for i in a) = 1") # can't assign to function test_syntax("f() = 1") # can't assign to power test_syntax("f**2 = 1") # can't assign to power of composite test_syntax("f[0]**2 = 1") # can't have *x on RHS test_syntax("x = *x") # can't have multiple *x on LHS test_syntax("*a, *b = c") # can't do augmented assignment to tuple test_syntax("a, b += c") test_syntax("(a, b) += c") # can't do augmented assignment to list test_syntax("[a, b] += c") # non-default argument can't follow default argument test_syntax("def f(a=1, b): pass") # can't delete these things test_syntax("del f()") test_syntax("del f[0]**2") test_syntax("del (a for a in a)") # must be in a "loop" test_syntax("break") test_syntax("continue") # must be in a function test_syntax("return") test_syntax("yield") test_syntax("nonlocal a") test_syntax("await 1") # error on uPy, warning on CPy #test_syntax("def f():\n a = 1\n global a") # default except must be last test_syntax("try:\n a\nexcept:\n pass\nexcept:\n pass") # LHS of keywords must be id's test_syntax("f(1=2)") # non-keyword after keyword test_syntax("f(a=1, 2)") # doesn't error on uPy but should #test_syntax("f(1, i for i in i)") # all elements of dict/set must be pairs or singles test_syntax("{1:2, 3}") test_syntax("{1, 2:3}") # can't mix non-bytes with bytes when concatenating test_syntax("'abc' b'def'") # can't reuse same name for argument test_syntax("def f(a, a): pass") # nonlocal must exist in outer function/class scope test_syntax("def f():\n def g():\n nonlocal a") # param can't be redefined as global test_syntax('def f(x):\n global x') # param can't be redefined as nonlocal test_syntax('def f(x):\n nonlocal x') # can define variable to be both nonlocal and global test_syntax('def f():\n nonlocal x\n global x') # can't have multiple *'s test_syntax('def f(x, *a, *):\n pass') test_syntax('lambda x, *a, *: 1') # **kw must be last test_syntax('def f(x, *a, **kw, r):\n pass') test_syntax('lambda x, *a, **kw, r: 1') micropython-1.12/tests/basics/sys1.py000066400000000000000000000010061357706137100176760ustar00rootroot00000000000000# test sys module import sys print(sys.__name__) print(type(sys.path)) print(type(sys.argv)) print(sys.byteorder in ('little', 'big')) try: print(sys.maxsize > 100) except AttributeError: # Effectively skip subtests print(True) try: print(sys.implementation.name in ('cpython', 'micropython')) except AttributeError: # Effectively skip subtests print(True) if hasattr(sys.implementation, 'mpy'): print(type(sys.implementation.mpy)) else: # Effectively skip subtests print(int) micropython-1.12/tests/basics/sys_exit.py000066400000000000000000000005561357706137100206570ustar00rootroot00000000000000# test sys module's exit function import sys try: sys.exit except AttributeError: print("SKIP") raise SystemExit try: raise SystemExit except SystemExit as e: print("SystemExit", e.args) try: sys.exit() except SystemExit as e: print("SystemExit", e.args) try: sys.exit(42) except SystemExit as e: print("SystemExit", e.args) micropython-1.12/tests/basics/sys_getsizeof.py000066400000000000000000000006101357706137100216740ustar00rootroot00000000000000# test sys.getsizeof() function import sys try: sys.getsizeof except AttributeError: print('SKIP') raise SystemExit print(sys.getsizeof([1, 2]) >= 2) print(sys.getsizeof({1: 2}) >= 2) class A: pass print(sys.getsizeof(A()) > 0) # Only test deque if we have it try: from ucollections import deque assert sys.getsizeof(deque((), 1)) > 0 except ImportError: pass micropython-1.12/tests/basics/true_value.py000066400000000000000000000006471357706137100211640ustar00rootroot00000000000000# Test true-ish value handling if not False: print("False") if not None: print("None") if not 0: print("0") if not "": print("Empty string") if "foo": print("Non-empty string") if not (): print("Empty tuple") if ("",): print("Non-empty tuple") if not []: print("Empty list") if [0]: print("Non-empty list") if not {}: print("Empty dict") if {0:0}: print("Non-empty dict") micropython-1.12/tests/basics/try1.py000066400000000000000000000001771357706137100177060ustar00rootroot00000000000000# basic exceptions x = 1 try: x.a() except: print(x) try: raise IndexError except IndexError: print("caught") micropython-1.12/tests/basics/try2.py000066400000000000000000000015061357706137100177040ustar00rootroot00000000000000# nested try's try: print("try 1") try: print("try 2") foo() except: print("except 2") bar() except: print("except 1") try: print("try 1") try: print("try 2") foo() except TypeError: print("except 2") bar() except NameError: print("except 1") # raised exception not contained in except tuple try: try: raise Exception except (RuntimeError, SyntaxError): print('except 2') except Exception: print('except 1') # Check that exceptions across function boundaries work as expected def func1(): try: print("try func1") func2() except NameError: print("except func1") def func2(): try: print("try func2") foo() except TypeError: print("except func2") func1() micropython-1.12/tests/basics/try3.py000066400000000000000000000003421357706137100177020ustar00rootroot00000000000000# nested exceptions def f(): try: foo() except: print("except 1") try: baz() except: print("except 2") bar() try: f() except: print("f except") micropython-1.12/tests/basics/try4.py000066400000000000000000000005121357706137100177020ustar00rootroot00000000000000# triple nested exceptions def f(): try: foo() except: print("except 1") try: bar() except: print("except 2") try: baz() except: print("except 3") bak() try: f() except: print("f except") micropython-1.12/tests/basics/try_as_var.py000066400000000000000000000002741357706137100211560ustar00rootroot00000000000000try: raise ValueError(534) except ValueError as e: print(type(e), e.args) # Var bound in except block is automatically deleted try: e except NameError: print("NameError") micropython-1.12/tests/basics/try_continue.py000066400000000000000000000003741357706137100215300ustar00rootroot00000000000000# test continue within exception handler def f(): lst = [1, 2, 3] for x in lst: print('a', x) try: if x == 2: raise Exception except Exception: continue print('b', x) f() micropython-1.12/tests/basics/try_else.py000066400000000000000000000020341357706137100206270ustar00rootroot00000000000000# test try-else statement # base case try: print(1) except: print(2) else: print(3) # basic case that should skip else try: print(1) raise Exception except: print(2) else: print(3) # uncaught exception should skip else try: try: print(1) raise ValueError except TypeError: print(2) else: print(3) except: print('caught') # nested within outer try try: print(1) try: print(2) raise Exception except: print(3) else: print(4) except: print(5) else: print(6) # nested within outer except, one else should be skipped try: print(1) raise Exception except: print(2) try: print(3) except: print(4) else: print(5) else: print(6) # nested within outer except, both else should be skipped try: print(1) raise Exception except: print(2) try: print(3) raise Exception except: print(4) else: print(5) else: print(6) micropython-1.12/tests/basics/try_else_finally.py000066400000000000000000000024121357706137100223450ustar00rootroot00000000000000# test try-else-finally statement # base case try: print(1) except: print(2) else: print(3) finally: print(4) # basic case that should skip else try: print(1) raise Exception except: print(2) else: print(3) finally: print(4) # uncaught exception should skip else try: try: print(1) raise ValueError except TypeError: print(2) else: print(3) finally: print(4) except: print('caught') # nested within outer try try: print(1) try: print(2) raise Exception except: print(3) else: print(4) finally: print(5) except: print(6) else: print(7) finally: print(8) # nested within outer except, one else should be skipped try: print(1) raise Exception except: print(2) try: print(3) except: print(4) else: print(5) finally: print(6) else: print(7) finally: print(8) # nested within outer except, both else should be skipped try: print(1) raise Exception except: print(2) try: print(3) raise Exception except: print(4) else: print(5) finally: print(6) else: print(7) finally: print(8) micropython-1.12/tests/basics/try_error.py000066400000000000000000000003301357706137100210250ustar00rootroot00000000000000# test bad exception match try: try: a except 1: pass except TypeError: print("TypeError") try: try: a except (1,): pass except TypeError: print("TypeError") micropython-1.12/tests/basics/try_except_break.py000066400000000000000000000025261357706137100223410ustar00rootroot00000000000000# test deep unwind via break from nested try-except (22 of them) while True: print(1) try: try: try: try: try: try: try: try: try: try: try: try: try: try: try: try: try: try: try: try: try: try: print(2) break print(3) except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass except: pass print(4) micropython-1.12/tests/basics/try_except_break.py.exp000066400000000000000000000000061357706137100231230ustar00rootroot000000000000001 2 4 micropython-1.12/tests/basics/try_finally1.py000066400000000000000000000030631357706137100214210ustar00rootroot00000000000000print("noexc-finally") try: print("try") finally: print("finally") print("noexc-finally-finally") try: print("try1") try: print("try2") finally: print("finally2") finally: print("finally1") print() print("noexc-finally-func-finally") def func2(): try: print("try2") finally: print("finally2") try: print("try1") func2() finally: print("finally1") print() print("exc-finally-except") try: print("try1") try: print("try2") foo() except: print("except2") finally: print("finally1") print() print("exc-finally-except-filter") try: print("try1") try: print("try2") foo() except NameError: print("except2") finally: print("finally1") print() print("exc-except-finally-finally") try: # top-level catch-all except to not fail script try: print("try1") try: print("try2") foo() finally: print("finally2") finally: print("finally1") except: print("catch-all except") print() # case where a try-except within a finally cancels the exception print("exc-finally-subexcept") try: print("try1") finally: try: print("try2") foo except: print("except2") print("finally1") print() # case where exception is raised after a finally has finished (tests that the finally doesn't run again) def func(): try: print("try") finally: print("finally") foo try: func() except: print("except") micropython-1.12/tests/basics/try_finally2.py000066400000000000000000000012551357706137100214230ustar00rootroot00000000000000# check that the Python stack does not overflow when the finally # block itself uses more stack than the rest of the function def f1(a, b): pass def test1(): val = 1 try: raise ValueError() finally: f1(2, 2) # use some stack print(val) # check that the local variable is the same try: test1() except ValueError: pass # same as above but with 3 args instead of 2, to use an extra stack entry def f2(a, b, c): pass def test2(): val = 1 try: raise ValueError() finally: f2(2, 2, 2) # use some stack print(val) # check that the local variable is the same try: test2() except ValueError: pass micropython-1.12/tests/basics/try_finally_break.py000066400000000000000000000040211357706137100224770ustar00rootroot00000000000000# test break within (nested) finally # basic case with break in finally def f(): for _ in range(2): print(1) try: pass finally: print(2) break print(3) print(4) print(5) f() # where the finally swallows an exception def f(): lst = [1, 2, 3] for x in lst: print('a', x) try: raise Exception finally: print(1) break print('b', x) f() # basic nested finally with break in inner finally def f(): for i in range(2): print('iter', i) try: raise TypeError finally: print(1) try: raise ValueError finally: break print(f()) # similar to above but more nesting def f(): for i in range(2): try: raise ValueError finally: print(1) try: raise TypeError finally: print(2) try: pass finally: break print(f()) # lots of nesting def f(): for i in range(2): try: raise ValueError finally: print(1) try: raise TypeError finally: print(2) try: raise Exception finally: break print(f()) # basic case combined with try-else def f(arg): for _ in range(2): print(1) try: if arg == 1: raise ValueError elif arg == 2: raise TypeError except ValueError: print(2) else: print(3) finally: print(4) break print(5) print(6) print(7) f(0) # no exception, else should execute f(1) # exception caught, else should be skipped f(2) # exception not caught, finally swallows exception, else should be skipped micropython-1.12/tests/basics/try_finally_break2.py000066400000000000000000000010221357706137100225570ustar00rootroot00000000000000def foo(x): for i in range(x): for j in range(x): try: print(x, i, j, 1) finally: try: try: print(x, i, j, 2) finally: try: 1 / 0 finally: print(x, i, j, 3) break finally: print(x, i, j, 4) break print(foo(4)) micropython-1.12/tests/basics/try_finally_continue.py000066400000000000000000000006051357706137100232430ustar00rootroot00000000000000def foo(x): for i in range(x): try: pass finally: try: try: print(x, i) finally: try: 1 / 0 finally: return 42 finally: print('continue') continue print(foo(4)) micropython-1.12/tests/basics/try_finally_continue.py.exp000066400000000000000000000000711357706137100240330ustar00rootroot000000000000004 0 continue 4 1 continue 4 2 continue 4 3 continue None micropython-1.12/tests/basics/try_finally_loops.py000066400000000000000000000026471357706137100225630ustar00rootroot00000000000000# Test various loop types, some may be implemented/optimized differently while True: try: break finally: print('finally 1') for i in [1, 5, 10]: try: continue finally: print('finally 2') for i in range(3): try: continue finally: print('finally 3') # Multi-level for i in range(4): print(i) try: while True: try: try: break finally: print('finally 1') finally: print('finally 2') print('here') finally: print('finnaly 3') # break from within try-finally, within for-loop for i in [1]: try: print(i) break finally: print('finally 4') # Test unwind-jump where there is nothing in the body of the try or finally. # This checks that the bytecode emitter allocates enough stack for the unwind. for i in [1]: try: break finally: pass # The following test checks that the globals dict is valid after a call to a # function that has an unwind jump. # There was a bug where an unwind jump would trash the globals dict upon return # from a function, because it used the Python-stack incorrectly. def f(): for i in [1]: try: break finally: pass def g(): global global_var f() print(global_var) global_var = 'global' g() micropython-1.12/tests/basics/try_finally_return.py000066400000000000000000000026771357706137100227510ustar00rootroot00000000000000def func1(): try: return "it worked" finally: print("finally 1") print(func1()) def func2(): try: return "it worked" finally: print("finally 2") def func3(): try: s = func2() return s + ", did this work?" finally: print("finally 3") print(func3()) # for loop within try-finally def f(): try: for i in [1, 2]: return i finally: print('finally') print(f()) # multiple for loops within try-finally def f(): try: for i in [1, 2]: for j in [3, 4]: return (i, j) finally: print('finally') print(f()) # multiple for loops and nested try-finally's def f(): try: for i in [1, 2]: for j in [3, 4]: try: for k in [5, 6]: for l in [7, 8]: return (i, j, k, l) finally: print('finally 2') finally: print('finally 1') print(f()) # multiple for loops that are optimised, and nested try-finally's def f(): try: for i in range(1, 3): for j in range(3, 5): try: for k in range(5, 7): for l in range(7, 9): return (i, j, k, l) finally: print('finally 2') finally: print('finally 1') print(f()) micropython-1.12/tests/basics/try_finally_return2.py000066400000000000000000000034521357706137100230230ustar00rootroot00000000000000# test 'return' within the finally block # it should swallow the exception # simple case def f(): try: raise ValueError() finally: print('finally') return 0 print('got here') print(f()) # nested, return in outer def f(): try: try: raise ValueError finally: print('finally 1') print('got here') finally: print('finally 2') return 2 print('got here') print(f()) # nested, return in inner def f(): try: try: raise ValueError finally: print('finally 1') return 1 print('got here') finally: print('finally 2') print('got here') print(f()) # nested, return in inner and outer def f(): try: try: raise ValueError finally: print('finally 1') return 1 print('got here') finally: print('finally 2') return 2 print('got here') print(f()) # nested with reraise def f(): try: try: raise ValueError except: raise print('got here') finally: print('finally') return 0 print('got here') print(f()) # triple nesting with reraise def f(): try: try: try: raise ValueError except: raise except: raise finally: print('finally') return 0 print(f()) # exception when matching exception def f(): try: raise ValueError except NonExistingError: pass finally: print('finally') return 0 print(f()) # raising exception class, not instance def f(): try: raise ValueError finally: print('finally') return 0 print(f()) micropython-1.12/tests/basics/try_finally_return3.py000066400000000000000000000040011357706137100230130ustar00rootroot00000000000000# test 'return' within the finally block, with nested finally's # only inactive finally's should be executed, and only once # basic nested finally's, the print should only be executed once def f(): try: raise TypeError finally: print(1) try: raise ValueError finally: return 42 print(f()) # similar to above but more nesting def f(): try: raise ValueError finally: print(1) try: raise TypeError finally: print(2) try: pass finally: return 42 print(f()) # similar to above but even more nesting def f(): try: raise ValueError finally: print(1) try: raise TypeError finally: print(2) try: raise Exception finally: print(3) return 42 print(f()) # upon return some try's are active, some finally's are active, some inactive def f(): try: try: pass finally: print(2) return 42 finally: print(1) print(f()) # same as above but raise instead of pass def f(): try: try: raise ValueError finally: print(2) return 42 finally: print(1) print(f()) # upon return exception stack holds: active finally, inactive finally, active finally def f(): try: raise Exception finally: print(1) try: try: pass finally: print(3) return 42 finally: print(2) print(f()) # same as above but raise instead of pass in innermost try block def f(): try: raise Exception finally: print(1) try: try: raise Exception finally: print(3) return 42 finally: print(2) print(f()) micropython-1.12/tests/basics/try_finally_return4.py000066400000000000000000000033411357706137100230220ustar00rootroot00000000000000# test try-finally with return, where unwinding return has to go through # another try-finally which may affect the behaviour of the return # case where a simple try-finally executes during an unwinding return def f(x): try: try: if x: return 42 finally: try: print(1) finally: print(2) print(3) print(4) finally: print(5) print(f(0)) print(f(1)) # case where an unwinding return is replaced by another one def f(x): try: try: if x: return 42 finally: try: print(1) return 43 finally: print(2) print(3) print(4) finally: print(5) print(f(0)) print(f(1)) # case where an unwinding return is cancelled by an exception def f(x): try: try: if x: return 42 finally: try: print(1) raise ValueError # cancels any active return finally: print(2) print(3) print(4) finally: print(5) try: print(f(0)) except: print('caught') try: print(f(1)) except: print('caught') # case where an unwinding return is cancelled then resumed def f(x): try: try: if x: return 42 finally: try: print(1) raise Exception # cancels any active return except: # cancels the exception and resumes any active return print(2) print(3) print(4) finally: print(5) print(f(0)) print(f(1)) micropython-1.12/tests/basics/try_finally_return5.py000066400000000000000000000006041357706137100230220ustar00rootroot00000000000000def foo(x): for i in range(x): try: pass finally: try: try: print(x, i) finally: try: 1 / 0 finally: return 42 finally: print('return') return 43 print(foo(4)) micropython-1.12/tests/basics/try_reraise.py000066400000000000000000000004331357706137100213320ustar00rootroot00000000000000# Reraising last exception with raise w/o args def f(): try: raise ValueError("val", 3) except: raise try: f() except ValueError as e: print(repr(e)) # Can reraise only in except block try: raise except RuntimeError: print("RuntimeError") micropython-1.12/tests/basics/try_reraise2.py000066400000000000000000000013521357706137100214150ustar00rootroot00000000000000# Reraise not the latest occurred exception def f(): try: raise ValueError("val", 3) except: try: print(1) raise TypeError except: print(2) try: print(3) try: print(4) raise AttributeError except: print(5) pass print(6) raise except TypeError: print(7) pass print(8) print(9) # This should raise original ValueError, not the most recently occurred AttributeError raise try: f() except ValueError as e: print(repr(e)) micropython-1.12/tests/basics/try_return.py000066400000000000000000000004301357706137100212140ustar00rootroot00000000000000# test use of return with try-except def f(): try: print(1) return except: print(2) print(3) f() def f(l, i): try: return l[i] except IndexError: print('IndexError') return -1 print(f([1], 0)) print(f([], 0)) micropython-1.12/tests/basics/tuple1.py000066400000000000000000000010601357706137100202110ustar00rootroot00000000000000# basic tuple functionality x = (1, 2, 3 * 4) print(x) try: x[0] = 4 except TypeError: print("TypeError") print(x) try: x.append(5) except AttributeError: print("AttributeError") print(x + (10, 100, 10000)) # inplace add operator x += (10, 11, 12) print(x) # construction of tuple from large iterator (tests implementation detail of uPy) print(tuple(range(20))) # unsupported unary operation try: +() except TypeError: print('TypeError') # unsupported type on RHS of add try: () + None except TypeError: print('TypeError') micropython-1.12/tests/basics/tuple_compare.py000066400000000000000000000022001357706137100216330ustar00rootroot00000000000000print(() == ()) print(() > ()) print(() < ()) print(() == (1,)) print((1,) == ()) print(() > (1,)) print((1,) > ()) print(() < (1,)) print((1,) < ()) print(() >= (1,)) print((1,) >= ()) print(() <= (1,)) print((1,) <= ()) print((1,) == (1,)) print((1,) != (1,)) print((1,) == (2,)) print((1,) == (1, 0,)) print((1,) > (1,)) print((1,) > (2,)) print((2,) > (1,)) print((1, 0,) > (1,)) print((1, -1,) > (1,)) print((1,) > (1, 0,)) print((1,) > (1, -1,)) print((1,) < (1,)) print((2,) < (1,)) print((1,) < (2,)) print((1,) < (1, 0,)) print((1,) < (1, -1,)) print((1, 0,) < (1,)) print((1, -1,) < (1,)) print((1,) >= (1,)) print((1,) >= (2,)) print((2,) >= (1,)) print((1, 0,) >= (1,)) print((1, -1,) >= (1,)) print((1,) >= (1, 0,)) print((1,) >= (1, -1,)) print((1,) <= (1,)) print((2,) <= (1,)) print((1,) <= (2,)) print((1,) <= (1, 0,)) print((1,) <= (1, -1,)) print((1, 0,) <= (1,)) print((1, -1,) <= (1,)) print((10, 0) > (1, 1)) print((10, 0) < (1, 1)) print((0, 0, 10, 0) > (0, 0, 1, 1)) print((0, 0, 10, 0) < (0, 0, 1, 1)) print(() == {}) print(() != {}) print((1,) == [1]) try: print(() < {}) except TypeError: print("TypeError") micropython-1.12/tests/basics/tuple_count.py000066400000000000000000000001271357706137100213430ustar00rootroot00000000000000a = (1, 2, 3) a = a + a + a b = (0, 0, a, 0, a, 0) print(a.count(2)) print(b.count(a)) micropython-1.12/tests/basics/tuple_index.py000066400000000000000000000006431357706137100213250ustar00rootroot00000000000000a = (1, 2, 3) print(a.index(1)) print(a.index(2)) print(a.index(3)) print(a.index(3, 2)) try: print(a.index(3, 2, 2)) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") a = a + a b = (0, 0, a) print(a.index(2)) print(b.index(a)) print(a.index(2, 2)) try: a.index(2, 2, 2) except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") micropython-1.12/tests/basics/tuple_mult.py000066400000000000000000000006071357706137100211770ustar00rootroot00000000000000# basic multiplication print((0,) * 5) # check negative, 0, positive; lhs and rhs multiplication for i in (-4, -2, 0, 2, 4): print(i * (1, 2)) print((1, 2) * i) # check that we don't modify existing tuple a = (1, 2, 3) c = a * 3 print(a, c) # inplace multiplication a = (1, 2) a *= 2 print(a) # unsupported type on RHS try: () * None except TypeError: print('TypeError') micropython-1.12/tests/basics/tuple_slice.py000066400000000000000000000001151357706137100213070ustar00rootroot00000000000000# tuple slicing x = (1, 2, 3 * 4) print(x[1:]) print(x[:-1]) print(x[2:3]) micropython-1.12/tests/basics/types1.py000066400000000000000000000007141357706137100202310ustar00rootroot00000000000000# basic types # similar test for set type is done in set_type.py print(bool) print(int) print(tuple) print(list) print(dict) print(type(bool()) == bool) print(type(int()) == int) print(type(tuple()) == tuple) print(type(list()) == list) print(type(dict()) == dict) print(type(False) == bool) print(type(0) == int) print(type(()) == tuple) print(type([]) == list) print(type({}) == dict) try: bool.foo except AttributeError: print("AttributeError") micropython-1.12/tests/basics/types2.py000066400000000000000000000003271357706137100202320ustar00rootroot00000000000000# Types are hashable print(hash(type) != 0) print(hash(int) != 0) print(hash(list) != 0) class Foo: pass print(hash(Foo) != 0) print(int == int) print(int != list) d = {} d[int] = list d[list] = int print(len(d)) micropython-1.12/tests/basics/unary_op.py000066400000000000000000000006001357706137100206320ustar00rootroot00000000000000x = 1 print(+x) print(-x) print(~x) print(not None) print(not False) print(not True) print(not 0) print(not 1) print(not -1) print(not ()) print(not (1,)) print(not []) print(not [1,]) print(not {}) print(not {1:1}) # check user instance class A: pass print(not A()) # check user instances derived from builtins class B(int): pass print(not B()) class C(list): pass print(not C()) micropython-1.12/tests/basics/unboundlocal.py000066400000000000000000000003621357706137100214700ustar00rootroot00000000000000# locals referenced before assignment def f1(): print(x) x = 1 def f2(): for i in range(0): print(i) print(i) def check(f): try: f() except NameError: print("NameError") check(f1) check(f2) micropython-1.12/tests/basics/unpack1.py000066400000000000000000000034121357706137100203440ustar00rootroot00000000000000# unpack sequences a, = 1, ; print(a) a, b = 2, 3 ; print(a, b) a, b, c = 1, 2, 3; print(a, b, c) a, = range(1); print(a) a, b = range(2); print(a, b) a, b, c = range(3); print(a, b, c) (a) = range(1); print(a) (a,) = range(1); print(a) (a, b) = range(2); print(a, b) (a, b, c) = range(3); print(a, b, c) (a, (b, c)) = [-1, range(2)]; print(a, b, c) # lists [] = [] [a] = range(1); print(a) [a, b] = range(2); print(a, b) [a, b, c] = range(3); print(a, b, c) # with star *a, = () ; print(a) *a, = 4, ; print(a) *a, = 5, 6 ; print(a) *a, b = 7, ; print(a, b) *a, b = 8, 9 ; print(a, b) *a, b = 10, 11, 12 ; print(a, b) a, *b = 13, ; print(a, b) a, *b = 14, 15 ; print(a, b) a, *b = 16, 17, 18 ; print(a, b) a, *b, c = 19, 20 ; print(a, b) a, *b, c = 21, 22, 23 ; print(a, b) a, *b, c = 24, 25, 26, 27 ; print(a, b) a = [28, 29] *b, = a print(a, b, a == b, a is b) [*a] = [1, 2, 3] print(a) try: a, *b, c = (30,) except ValueError: print("ValueError") # with star and generic iterator *a, = range(5) ; print(a) *a, b = range(5) ; print(a, b) *a, b, c = range(5) ; print(a, b, c) a, *b = range(5) ; print(a, b) a, *b, c = range(5) ; print(a, b, c) a, *b, c, d = range(5) ; print(a, b, c, d) a, b, *c = range(5) ; print(a, b, c) a, b, *c, d = range(5) ; print(a, b, c, d) a, b, *c, d, e = range(5) ; print(a, b, c, d, e) *a, = [x * 2 for x in [1, 2, 3, 4]] ; print(a) *a, b = [x * 2 for x in [1, 2, 3, 4]] ; print(a, b) a, *b = [x * 2 for x in [1, 2, 3, 4]] ; print(a, b) a, *b, c = [x * 2 for x in [1, 2, 3, 4]]; print(a, b, c) try: a, *b, c = range(0) except ValueError: print("ValueError") try: a, *b, c = range(1) except ValueError: print("ValueError") micropython-1.12/tests/basics/while1.py000066400000000000000000000002661357706137100201770ustar00rootroot00000000000000# basic while loop x = 0 while x < 2: y = 0 while y < 2: z = 0 while z < 2: z = z + 1 print(x, y, z) y = y + 1 x = x + 1 micropython-1.12/tests/basics/while_cond.py000066400000000000000000000006021357706137100211130ustar00rootroot00000000000000# test while conditions which are optimised by the compiler while 0: print(0) else: print(1) while 1: print(2) break while 2: print(3) break while -1: print(4) break while False: print('a') else: print('b') while True: print('a') break while not False: print('a') break while not True: print('a') else: print('b') micropython-1.12/tests/basics/while_nest_exc.py000066400000000000000000000003061357706137100220010ustar00rootroot00000000000000# test nested whiles within a try-except while 1: print(1) try: print(2) while 1: print(3) break except: print(4) print(5) break micropython-1.12/tests/basics/with1.py000066400000000000000000000031341357706137100200370ustar00rootroot00000000000000class CtxMgr: def __enter__(self): print("__enter__") return self def __exit__(self, a, b, c): print("__exit__", repr(a), repr(b)) with CtxMgr() as a: print(isinstance(a, CtxMgr)) try: with CtxMgr() as a: raise ValueError except ValueError: print("ValueError") class CtxMgr2: def __enter__(self): print("__enter__") return self def __exit__(self, a, b, c): print("__exit__", repr(a), repr(b)) return True try: with CtxMgr2() as a: raise ValueError print("No ValueError2") except ValueError: print("ValueError2") # These recursive try-finally tests are attempt to get some interpretation # of last phrase in http://docs.python.org/3.4/library/dis.html#opcode-WITH_CLEANUP # "If the stack represents an exception, and the function call returns a 'true' # value, this information is "zapped" and replaced with a single WHY_SILENCED # to prevent END_FINALLY from re-raising the exception. (But non-local gotos # will still be resumed.)" print("===") with CtxMgr2() as a: try: try: raise ValueError print("No ValueError3") finally: print("finally1") finally: print("finally2") print("===") try: try: with CtxMgr2() as a: try: try: raise ValueError print("No ValueError3") finally: print("finally1") finally: print("finally2") finally: print("finally3") finally: print("finally4") micropython-1.12/tests/basics/with_break.py000066400000000000000000000003761357706137100211270ustar00rootroot00000000000000class CtxMgr: def __enter__(self): print("__enter__") return self def __exit__(self, a, b, c): print("__exit__", repr(a), repr(b)) for i in range(5): print(i) with CtxMgr(): if i == 3: break micropython-1.12/tests/basics/with_continue.py000066400000000000000000000004011357706137100216540ustar00rootroot00000000000000class CtxMgr: def __enter__(self): print("__enter__") return self def __exit__(self, a, b, c): print("__exit__", repr(a), repr(b)) for i in range(5): print(i) with CtxMgr(): if i == 3: continue micropython-1.12/tests/basics/with_raise.py000066400000000000000000000014671357706137100211500ustar00rootroot00000000000000# test with when context manager raises in __enter__/__exit__ class CtxMgr: def __init__(self, id): self.id = id def __enter__(self): print("__enter__", self.id) if 10 <= self.id < 20: raise Exception('enter', self.id) return self def __exit__(self, a, b, c): print("__exit__", self.id, repr(a), repr(b)) if 15 <= self.id < 25: raise Exception('exit', self.id) # no raising try: with CtxMgr(1): pass except Exception as e: print(e) # raise in enter try: with CtxMgr(10): pass except Exception as e: print(e) # raise in enter and exit try: with CtxMgr(15): pass except Exception as e: print(e) # raise in exit try: with CtxMgr(20): pass except Exception as e: print(e) micropython-1.12/tests/basics/with_return.py000066400000000000000000000023271357706137100213600ustar00rootroot00000000000000class CtxMgr: def __init__(self, id): self.id = id def __enter__(self): print("__enter__", self.id) return self def __exit__(self, a, b, c): print("__exit__", self.id, repr(a), repr(b)) # simple case def foo(): with CtxMgr(1): return 4 print(foo()) # for loop within with (iterator needs removing upon return) def f(): with CtxMgr(1): for i in [1, 2]: return i print(f()) # multiple for loops within with def f(): with CtxMgr(1): for i in [1, 2]: for j in [3, 4]: return (i, j) print(f()) # multiple for loops within nested withs def f(): with CtxMgr(1): for i in [1, 2]: for j in [3, 4]: with CtxMgr(2): for k in [5, 6]: for l in [7, 8]: return (i, j, k, l) print(f()) # multiple for loops that are optimised, and nested withs def f(): with CtxMgr(1): for i in range(1, 3): for j in range(3, 5): with CtxMgr(2): for k in range(5, 7): for l in range(7, 9): return (i, j, k, l) print(f()) micropython-1.12/tests/cmdline/000077500000000000000000000000001357706137100165775ustar00rootroot00000000000000micropython-1.12/tests/cmdline/cmd_optimise.py000066400000000000000000000001031357706137100216170ustar00rootroot00000000000000# cmdline: -O # test optimisation output print(__debug__) assert 0 micropython-1.12/tests/cmdline/cmd_optimise.py.exp000066400000000000000000000000061357706137100224140ustar00rootroot00000000000000False micropython-1.12/tests/cmdline/cmd_parsetree.py000066400000000000000000000003731357706137100217710ustar00rootroot00000000000000# cmdline: -v -v -v # test printing of the parse-tree for i in (): pass a = None b = 'str' c = 'a very long str that will not be interned' d = b'bytes' e = b'a very long bytes that will not be interned' f = 123456789012345678901234567890 g = 123 micropython-1.12/tests/cmdline/cmd_parsetree.py.exp000066400000000000000000000030431357706137100225610ustar00rootroot00000000000000---------------- [ 4] rule(1) (n=9) tok(4) [ 4] rule(22) (n=4) id(i) [ 4] rule(44) (n=1) NULL [ 5] rule(8) (n=0) NULL [ 6] rule(5) (n=2) id(a) tok(14) [ 7] rule(5) (n=2) id(b) str(str) [ 8] rule(5) (n=2) id(c) [ 8] literal \.\+ [ 9] rule(5) (n=2) id(d) bytes(bytes) [ 10] rule(5) (n=2) id(e) [ 10] literal \.\+ [ 11] rule(5) (n=2) id(f) [ 11] literal \.\+ [ 12] rule(5) (n=2) id(g) int(123) ---------------- File cmdline/cmd_parsetree.py, code block '' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: (N_STATE 5) (N_EXC_STACK 0) bc=0 line=1 bc=0 line=4 bc=9 line=5 bc=12 line=6 bc=16 line=7 bc=22 line=8 bc=27 line=9 bc=32 line=10 bc=37 line=11 bc=42 line=12 00 BUILD_TUPLE 0 02 GET_ITER_STACK 03 FOR_ITER 12 06 STORE_NAME i 09 JUMP 3 12 LOAD_CONST_NONE 13 STORE_NAME a 16 LOAD_CONST_STRING 'str' 19 STORE_NAME b 22 LOAD_CONST_OBJ \.\+ 24 STORE_NAME c 27 LOAD_CONST_OBJ \.\+ 29 STORE_NAME d 32 LOAD_CONST_OBJ \.\+ 34 STORE_NAME e 37 LOAD_CONST_OBJ \.\+ 39 STORE_NAME f 42 LOAD_CONST_SMALL_INT 123 45 STORE_NAME g 48 LOAD_CONST_NONE 49 RETURN_VALUE mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ GC: total: \\d\+, used: \\d\+, free: \\d\+ No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ micropython-1.12/tests/cmdline/cmd_showbc.py000066400000000000000000000041031357706137100212570ustar00rootroot00000000000000# cmdline: -v -v # test printing of all bytecodes def f(): # constants a = None + False + True a = 0 a = 1000 a = -1000 # constructing data a = 1 b = (1, 2) c = [1, 2] d = {1, 2} e = {} f = {1:2} g = 'a' h = b'a' # unary/binary ops i = 1 j = 2 k = a + b l = -a m = not a m = a == b == c m = not (a == b and b == c) # attributes n = b.c b.c = n # subscript p = b[0] b[0] = p b[0] += p # slice a = b[::] # sequenc unpacking a, b = c a, *a = a # tuple swapping a, b = b, a a, b, c = c, b, a # del fast del a # globals global gl gl = a del gl # comprehensions a = (b for c in d if e) a = [b for c in d if e] a = {b:b for c in d if e} # function calls a() a(1) a(b=1) a(*b) # method calls a.b() a.b(1) a.b(c=1) a.b(*c) # jumps if a: x else: y while a: b while not a: b a = a or a # for loop for a in b: c # exceptions try: while a: break except: b finally: c while a: try: break except: pass # with with a: b # closed over variables x = 1 def closure(): nonlocal x; a = x + 1 x = 1 del x # import import a from a import b #from sys import * # tested at module scope # raise raise raise 1 # return return return 1 # function with lots of locals def f(): l1 = l2 = l3 = l4 = l5 = l6 = l7 = l8 = l9 = l10 = 1 m1 = m2 = m3 = m4 = m5 = m6 = m7 = m8 = m9 = m10 = 2 l10 + m10 # functions with default args def f(a=1): pass def f(b=2): return b + a # function which yields def f(): yield yield 1 yield from 1 # class class Class: pass # delete name del Class # load super method def f(self): super().f() # import * (needs to be in module scope) from sys import * micropython-1.12/tests/cmdline/cmd_showbc.py.exp000066400000000000000000000264311357706137100220620ustar00rootroot00000000000000File cmdline/cmd_showbc.py, code block '' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: (N_STATE 3) (N_EXC_STACK 0) bc=0 line=1 ######## bc=\\d\+ line=159 00 MAKE_FUNCTION \.\+ \\d\+ STORE_NAME f \\d\+ MAKE_FUNCTION \.\+ \\d\+ STORE_NAME f \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ BUILD_TUPLE 1 \\d\+ LOAD_NULL \\d\+ MAKE_FUNCTION_DEFARGS \.\+ \\d\+ STORE_NAME f \\d\+ MAKE_FUNCTION \.\+ \\d\+ STORE_NAME f \\d\+ LOAD_BUILD_CLASS \\d\+ MAKE_FUNCTION \.\+ \\d\+ LOAD_CONST_STRING 'Class' \\d\+ CALL_FUNCTION n=2 nkw=0 \\d\+ STORE_NAME Class \\d\+ DELETE_NAME Class \\d\+ MAKE_FUNCTION \.\+ \\d\+ STORE_NAME f \\d\+ LOAD_CONST_SMALL_INT 0 \\d\+ LOAD_CONST_STRING '*' \\d\+ BUILD_TUPLE 1 \\d\+ IMPORT_NAME 'sys' \\d\+ IMPORT_STAR \\d\+ LOAD_CONST_NONE \\d\+ RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+rg names: (N_STATE 22) (N_EXC_STACK 2) (INIT_CELL 14) (INIT_CELL 15) (INIT_CELL 16) bc=0 line=1 ######## bc=\\d\+ line=126 00 LOAD_CONST_NONE 01 LOAD_CONST_FALSE 02 BINARY_OP 27 __add__ 03 LOAD_CONST_TRUE 04 BINARY_OP 27 __add__ 05 STORE_FAST 0 06 LOAD_CONST_SMALL_INT 0 07 STORE_FAST 0 08 LOAD_CONST_SMALL_INT 1000 11 STORE_FAST 0 12 LOAD_CONST_SMALL_INT -1000 15 STORE_FAST 0 16 LOAD_CONST_SMALL_INT 1 17 STORE_FAST 0 18 LOAD_CONST_SMALL_INT 1 19 LOAD_CONST_SMALL_INT 2 20 BUILD_TUPLE 2 22 STORE_DEREF 14 24 LOAD_CONST_SMALL_INT 1 25 LOAD_CONST_SMALL_INT 2 26 BUILD_LIST 2 28 STORE_FAST 1 29 LOAD_CONST_SMALL_INT 1 30 LOAD_CONST_SMALL_INT 2 31 BUILD_SET 2 33 STORE_FAST 2 34 BUILD_MAP 0 36 STORE_DEREF 15 38 BUILD_MAP 1 40 LOAD_CONST_SMALL_INT 2 41 LOAD_CONST_SMALL_INT 1 42 STORE_MAP 43 STORE_FAST 3 44 LOAD_CONST_STRING 'a' 47 STORE_FAST 4 48 LOAD_CONST_OBJ \.\+ \\d\+ STORE_FAST 5 \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ STORE_FAST 6 \\d\+ LOAD_CONST_SMALL_INT 2 \\d\+ STORE_FAST 7 \\d\+ LOAD_FAST 0 \\d\+ LOAD_DEREF 14 58 BINARY_OP 27 __add__ \\d\+ STORE_FAST 8 \\d\+ LOAD_FAST 0 \\d\+ UNARY_OP 1 \\d\+ STORE_FAST 9 \\d\+ LOAD_FAST 0 \\d\+ UNARY_OP 3 \\d\+ STORE_FAST 10 \\d\+ LOAD_FAST 0 \\d\+ LOAD_DEREF 14 \\d\+ DUP_TOP \\d\+ ROT_THREE \\d\+ BINARY_OP 2 __eq__ \\d\+ JUMP_IF_FALSE_OR_POP \\d\+ \\d\+ LOAD_FAST 1 \\d\+ BINARY_OP 2 __eq__ \\d\+ JUMP \\d\+ \\d\+ ROT_TWO \\d\+ POP_TOP \\d\+ STORE_FAST 10 \\d\+ LOAD_FAST 0 \\d\+ LOAD_DEREF 14 \\d\+ BINARY_OP 2 __eq__ \\d\+ JUMP_IF_FALSE_OR_POP \\d\+ \\d\+ LOAD_DEREF 14 \\d\+ LOAD_FAST 1 \\d\+ BINARY_OP 2 __eq__ \\d\+ UNARY_OP 3 \\d\+ STORE_FAST 10 \\d\+ LOAD_DEREF 14 \\d\+ LOAD_ATTR c (cache=0) \\d\+ STORE_FAST 11 \\d\+ LOAD_FAST 11 \\d\+ LOAD_DEREF 14 \\d\+ STORE_ATTR c (cache=0) \\d\+ LOAD_DEREF 14 \\d\+ LOAD_CONST_SMALL_INT 0 \\d\+ LOAD_SUBSCR \\d\+ STORE_FAST 12 \\d\+ LOAD_FAST 12 \\d\+ LOAD_DEREF 14 \\d\+ LOAD_CONST_SMALL_INT 0 \\d\+ STORE_SUBSCR \\d\+ LOAD_DEREF 14 \\d\+ LOAD_CONST_SMALL_INT 0 \\d\+ DUP_TOP_TWO \\d\+ LOAD_SUBSCR \\d\+ LOAD_FAST 12 \\d\+ BINARY_OP 14 __iadd__ \\d\+ ROT_THREE \\d\+ STORE_SUBSCR \\d\+ LOAD_DEREF 14 \\d\+ LOAD_CONST_NONE \\d\+ LOAD_CONST_NONE \\d\+ BUILD_SLICE 2 \\d\+ LOAD_SUBSCR \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 1 \\d\+ UNPACK_SEQUENCE 2 \\d\+ STORE_FAST 0 \\d\+ STORE_DEREF 14 \\d\+ LOAD_FAST 0 \\d\+ UNPACK_EX 1 \\d\+ STORE_FAST 0 \\d\+ STORE_FAST 0 \\d\+ LOAD_DEREF 14 \\d\+ LOAD_FAST 0 \\d\+ ROT_TWO \\d\+ STORE_FAST 0 \\d\+ STORE_DEREF 14 \\d\+ LOAD_FAST 1 \\d\+ LOAD_DEREF 14 \\d\+ LOAD_FAST 0 \\d\+ ROT_THREE \\d\+ ROT_TWO \\d\+ STORE_FAST 0 \\d\+ STORE_DEREF 14 \\d\+ STORE_FAST 1 \\d\+ DELETE_FAST 0 \\d\+ LOAD_FAST 0 \\d\+ STORE_GLOBAL gl \\d\+ DELETE_GLOBAL gl \\d\+ LOAD_FAST 14 \\d\+ LOAD_FAST 15 \\d\+ MAKE_CLOSURE \.\+ 2 \\d\+ LOAD_FAST 2 \\d\+ GET_ITER \\d\+ CALL_FUNCTION n=1 nkw=0 \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 14 \\d\+ LOAD_FAST 15 \\d\+ MAKE_CLOSURE \.\+ 2 \\d\+ LOAD_FAST 2 \\d\+ CALL_FUNCTION n=1 nkw=0 \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 14 \\d\+ LOAD_FAST 15 \\d\+ MAKE_CLOSURE \.\+ 2 \\d\+ LOAD_FAST 2 \\d\+ CALL_FUNCTION n=1 nkw=0 \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 0 \\d\+ CALL_FUNCTION n=0 nkw=0 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ CALL_FUNCTION n=1 nkw=0 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ LOAD_CONST_STRING 'b' \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ CALL_FUNCTION n=0 nkw=1 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ LOAD_DEREF 14 \\d\+ LOAD_NULL \\d\+ CALL_FUNCTION_VAR_KW n=0 nkw=0 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ LOAD_METHOD b \\d\+ CALL_METHOD n=0 nkw=0 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ LOAD_METHOD b \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ CALL_METHOD n=1 nkw=0 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ LOAD_METHOD b \\d\+ LOAD_CONST_STRING 'c' \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ CALL_METHOD n=0 nkw=1 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ LOAD_METHOD b \\d\+ LOAD_FAST 1 \\d\+ LOAD_NULL \\d\+ CALL_METHOD_VAR_KW n=0 nkw=0 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ POP_JUMP_IF_FALSE \\d\+ \\d\+ LOAD_DEREF 16 \\d\+ POP_TOP \\d\+ JUMP \\d\+ \\d\+ LOAD_GLOBAL y (cache=0) \\d\+ POP_TOP \\d\+ JUMP \\d\+ \\d\+ LOAD_DEREF 14 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ POP_JUMP_IF_TRUE \\d\+ \\d\+ JUMP \\d\+ \\d\+ LOAD_DEREF 14 \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ POP_JUMP_IF_FALSE \\d\+ \\d\+ LOAD_FAST 0 \\d\+ JUMP_IF_TRUE_OR_POP \\d\+ \\d\+ LOAD_FAST 0 \\d\+ STORE_FAST 0 \\d\+ LOAD_DEREF 14 \\d\+ GET_ITER_STACK \\d\+ FOR_ITER \\d\+ \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 1 \\d\+ POP_TOP \\d\+ JUMP \\d\+ \\d\+ SETUP_FINALLY \\d\+ \\d\+ SETUP_EXCEPT \\d\+ \\d\+ JUMP \\d\+ \\d\+ JUMP \\d\+ \\d\+ LOAD_FAST 0 \\d\+ POP_JUMP_IF_TRUE \\d\+ \\d\+ POP_EXCEPT_JUMP \\d\+ \\d\+ POP_TOP \\d\+ LOAD_DEREF 14 \\d\+ POP_TOP \\d\+ POP_EXCEPT_JUMP \\d\+ \\d\+ END_FINALLY \\d\+ LOAD_CONST_NONE \\d\+ LOAD_FAST 1 \\d\+ POP_TOP \\d\+ END_FINALLY \\d\+ JUMP \\d\+ \\d\+ SETUP_EXCEPT \\d\+ \\d\+ UNWIND_JUMP \\d\+ 1 \\d\+ POP_EXCEPT_JUMP \\d\+ \\d\+ POP_TOP \\d\+ POP_EXCEPT_JUMP \\d\+ \\d\+ END_FINALLY \\d\+ LOAD_FAST 0 \\d\+ POP_JUMP_IF_TRUE \\d\+ \\d\+ LOAD_FAST 0 \\d\+ SETUP_WITH \\d\+ \\d\+ POP_TOP \\d\+ LOAD_DEREF 14 \\d\+ POP_TOP \\d\+ LOAD_CONST_NONE \\d\+ WITH_CLEANUP \\d\+ END_FINALLY \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ STORE_DEREF 16 \\d\+ LOAD_FAST_N 16 \\d\+ MAKE_CLOSURE \.\+ 1 \\d\+ STORE_FAST 13 \\d\+ LOAD_CONST_SMALL_INT 0 \\d\+ LOAD_CONST_NONE \\d\+ IMPORT_NAME 'a' \\d\+ STORE_FAST 0 \\d\+ LOAD_CONST_SMALL_INT 0 \\d\+ LOAD_CONST_STRING 'b' \\d\+ BUILD_TUPLE 1 \\d\+ IMPORT_NAME 'a' \\d\+ IMPORT_FROM 'b' \\d\+ STORE_DEREF 14 \\d\+ POP_TOP \\d\+ RAISE_LAST \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ RAISE_OBJ \\d\+ LOAD_CONST_NONE \\d\+ RETURN_VALUE \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+rg names: (N_STATE 22) (N_EXC_STACK 0) bc=0 line=1 ######## bc=\\d\+ line=132 00 LOAD_CONST_SMALL_INT 1 01 DUP_TOP 02 STORE_FAST 0 03 DUP_TOP 04 STORE_FAST 1 05 DUP_TOP 06 STORE_FAST 2 07 DUP_TOP 08 STORE_FAST 3 09 DUP_TOP 10 STORE_FAST 4 11 DUP_TOP 12 STORE_FAST 5 13 DUP_TOP 14 STORE_FAST 6 15 DUP_TOP 16 STORE_FAST 7 17 DUP_TOP 18 STORE_FAST 8 19 STORE_FAST 9 20 LOAD_CONST_SMALL_INT 2 21 DUP_TOP 22 STORE_FAST 10 23 DUP_TOP 24 STORE_FAST 11 25 DUP_TOP 26 STORE_FAST 12 27 DUP_TOP 28 STORE_FAST 13 29 DUP_TOP 30 STORE_FAST 14 31 DUP_TOP 32 STORE_FAST 15 33 DUP_TOP 34 STORE_FAST_N 16 36 DUP_TOP 37 STORE_FAST_N 17 39 DUP_TOP 40 STORE_FAST_N 18 42 STORE_FAST_N 19 44 LOAD_FAST 9 45 LOAD_FAST_N 19 47 BINARY_OP 27 __add__ 48 POP_TOP 49 LOAD_CONST_NONE 50 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: a (N_STATE 5) (N_EXC_STACK 0) (INIT_CELL 0) ######## bc=\\d\+ line=138 00 LOAD_CONST_SMALL_INT 2 01 BUILD_TUPLE 1 03 LOAD_NULL 04 LOAD_FAST 0 05 MAKE_CLOSURE_DEFARGS \.\+ 1 \\d\+ STORE_FAST 1 \\d\+ LOAD_CONST_NONE \\d\+ RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: (N_STATE 2) (N_EXC_STACK 0) bc=0 line=1 bc=0 line=143 bc=3 line=144 bc=6 line=145 00 LOAD_CONST_NONE 01 YIELD_VALUE 02 POP_TOP 03 LOAD_CONST_SMALL_INT 1 04 YIELD_VALUE 05 POP_TOP 06 LOAD_CONST_SMALL_INT 1 07 GET_ITER 08 LOAD_CONST_NONE 09 YIELD_FROM 10 POP_TOP 11 LOAD_CONST_NONE 12 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'Class' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: (N_STATE 1) (N_EXC_STACK 0) bc=0 line=1 ######## bc=13 line=149 00 LOAD_NAME __name__ (cache=0) 04 STORE_NAME __module__ 07 LOAD_CONST_STRING 'Class' 10 STORE_NAME __qualname__ 13 LOAD_CONST_NONE 14 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: self (N_STATE 4) (N_EXC_STACK 0) bc=0 line=1 bc=0 line=156 00 LOAD_GLOBAL super (cache=0) \\d\+ LOAD_GLOBAL __class__ (cache=0) \\d\+ LOAD_FAST 0 \\d\+ LOAD_SUPER_METHOD f \\d\+ CALL_METHOD n=0 nkw=0 \\d\+ POP_TOP \\d\+ LOAD_CONST_NONE \\d\+ RETURN_VALUE File cmdline/cmd_showbc.py, code block '' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: * * * (N_STATE 9) (N_EXC_STACK 0) bc=0 line=1 bc=0 line=59 ######## 00 LOAD_NULL 01 LOAD_FAST 2 02 LOAD_NULL 03 LOAD_NULL 04 FOR_ITER 20 07 STORE_FAST 3 08 LOAD_DEREF 1 10 POP_JUMP_IF_FALSE 4 13 LOAD_DEREF 0 15 YIELD_VALUE 16 POP_TOP 17 JUMP 4 20 LOAD_CONST_NONE 21 RETURN_VALUE File cmdline/cmd_showbc.py, code block '' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: * * * (N_STATE 10) (N_EXC_STACK 0) bc=0 line=1 bc=0 line=60 ######## 00 BUILD_LIST 0 02 LOAD_FAST 2 03 GET_ITER_STACK 04 FOR_ITER 20 07 STORE_FAST 3 08 LOAD_DEREF 1 10 POP_JUMP_IF_FALSE 4 13 LOAD_DEREF 0 15 STORE_COMP 20 17 JUMP 4 20 RETURN_VALUE File cmdline/cmd_showbc.py, code block '' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: * * * (N_STATE 11) (N_EXC_STACK 0) bc=0 line=1 ######## 00 BUILD_MAP 0 02 LOAD_FAST 2 03 GET_ITER_STACK 04 FOR_ITER 22 07 STORE_FAST 3 08 LOAD_DEREF 1 10 POP_JUMP_IF_FALSE 4 13 LOAD_DEREF 0 15 LOAD_DEREF 0 17 STORE_COMP 25 19 JUMP 4 22 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'closure' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: * (N_STATE 4) (N_EXC_STACK 0) bc=0 line=1 ######## bc=\\d\+ line=113 00 LOAD_DEREF 0 02 LOAD_CONST_SMALL_INT 1 03 BINARY_OP 27 __add__ 04 STORE_FAST 1 05 LOAD_CONST_SMALL_INT 1 06 STORE_DEREF 0 08 DELETE_DEREF 0 10 LOAD_CONST_NONE 11 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+63 arg names: * b (N_STATE 4) (N_EXC_STACK 0) bc=0 line=1 ######## bc=\\d\+ line=139 00 LOAD_FAST 1 01 LOAD_DEREF 0 03 BINARY_OP 27 __add__ 04 RETURN_VALUE mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ GC: total: \\d\+, used: \\d\+, free: \\d\+ No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ micropython-1.12/tests/cmdline/cmd_verbose.py000066400000000000000000000000601357706137100214350ustar00rootroot00000000000000# cmdline: -v -v # test verbose output print(1) micropython-1.12/tests/cmdline/cmd_verbose.py.exp000066400000000000000000000010641357706137100222350ustar00rootroot00000000000000File cmdline/cmd_verbose.py, code block '' (descriptor: \.\+, bytecode \.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): 08 \.\+ ######## \.\+63 arg names: (N_STATE 2) (N_EXC_STACK 0) bc=0 line=1 bc=0 line=3 00 LOAD_NAME print (cache=0) 04 LOAD_CONST_SMALL_INT 1 05 CALL_FUNCTION n=1 nkw=0 07 POP_TOP 08 LOAD_CONST_NONE 09 RETURN_VALUE 1 mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ GC: total: \\d\+, used: \\d\+, free: \\d\+ No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ micropython-1.12/tests/cmdline/repl_autocomplete.py000066400000000000000000000002101357706137100226650ustar00rootroot00000000000000# tests for autocompletion impo sys not_exist.  not_exist  x = '123' 1, x.isdi () i = str i.lowe ('ABC') None.  micropython-1.12/tests/cmdline/repl_autocomplete.py.exp000066400000000000000000000004541357706137100234720ustar00rootroot00000000000000MicroPython \.\+ version Use \.\+ >>> # tests for autocompletion >>> import sys >>> not_exist. >>> not_exist >>> x = '123' >>> 1, x.isdigit() (1, True) >>> i = str >>> i.lower('ABC') 'abc' >>> None. >>> micropython-1.12/tests/cmdline/repl_basic.py000066400000000000000000000000421357706137100212500ustar00rootroot00000000000000# basic REPL tests print(1)  2 micropython-1.12/tests/cmdline/repl_basic.py.exp000066400000000000000000000001441357706137100220460ustar00rootroot00000000000000MicroPython \.\+ version Use \.\+ >>> # basic REPL tests >>> print(1) 1 >>> print(1) 1 >>> 2 2 >>> micropython-1.12/tests/cmdline/repl_cont.py000066400000000000000000000004401357706137100211340ustar00rootroot00000000000000# check REPL allows to continue input 1 \ + 2 '"' "'" '\'' "\"" '\'(' "\"(" print("\"(") print('\'(') print("\'(") print('\"(') 'abc' "abc" '''abc def''' """ABC DEF""" print( 1 + 2) l = [1, 2] print(l) d = {1:'one', 2:'two'} print(d[2]) def f(x): print(x)  f(3) if1=1 if1 = 2 print(if1) micropython-1.12/tests/cmdline/repl_cont.py.exp000066400000000000000000000011311357706137100217250ustar00rootroot00000000000000MicroPython \.\+ version Use \.\+ >>> # check REPL allows to continue input >>> 1 \\\\ ... + 2 3 >>> '"' '"' >>> "'" "'" >>> '\\\\'' "'" >>> "\\\\"" '"' >>> '\\\\'(' "'(" >>> "\\\\"(" '"(' >>> print("\\\\"(") "( >>> print('\\\\'(') '( >>> print("\\\\'(") '( >>> print('\\\\"(') "( >>> 'abc' 'abc' >>> "abc" 'abc' >>> '''abc ... def''' 'abc\\\\ndef' >>> """ABC ... DEF""" 'ABC\\\\nDEF' >>> print( ... 1 + 2) 3 >>> l = [1, ... 2] >>> print(l) [1, 2] >>> d = {1:'one', ... 2:'two'} >>> print(d[2]) two >>> def f(x): ... print(x) ...  >>> f(3) 3 >>> if1=1 >>> if1 = 2 >>> print(if1) 2 >>> micropython-1.12/tests/cmdline/repl_emacs_keys.py000066400000000000000000000002101357706137100223070ustar00rootroot00000000000000# REPL tests of GNU-ish readline navigation # history buffer navigation 1 2 3   # input line motion t = 12 'boofar fbar' micropython-1.12/tests/cmdline/repl_emacs_keys.py.exp000066400000000000000000000003411357706137100231070ustar00rootroot00000000000000MicroPython \.\+ version Use \.\+ >>> # REPL tests of GNU-ish readline navigation >>> # history buffer navigation >>> 1 1 >>> 2 2 >>> 3 3 >>> 321 1 >>> 1323 3 >>> # input line motion >>> t = 121 >>> \.\+ 'foobar' >>> micropython-1.12/tests/cpydiff/000077500000000000000000000000001357706137100166105ustar00rootroot00000000000000micropython-1.12/tests/cpydiff/builtin_next_arg2.py000066400000000000000000000004651357706137100226060ustar00rootroot00000000000000""" categories: Modules,builtins description: Second argument to next() is not implemented cause: MicroPython is optimised for code space. workaround: Instead of ``val = next(it, deflt)`` use:: try: val = next(it) except StopIteration: val = deflt """ print(next(iter(range(0)), 42)) micropython-1.12/tests/cpydiff/core_class_delnotimpl.py000066400000000000000000000003701357706137100235260ustar00rootroot00000000000000""" categories: Core,Classes description: Special method __del__ not implemented for user-defined classes cause: Unknown workaround: Unknown """ import gc class Foo(): def __del__(self): print('__del__') f = Foo() del f gc.collect() micropython-1.12/tests/cpydiff/core_class_mro.py000066400000000000000000000007051357706137100221560ustar00rootroot00000000000000""" categories: Core,Classes description: Method Resolution Order (MRO) is not compliant with CPython cause: Depth first non-exhaustive method resolution order workaround: Avoid complex class hierarchies with multiple inheritance and complex method overrides. Keep in mind that many languages don't support multiple inheritance at all. """ class Foo: def __str__(self): return "Foo" class C(tuple, Foo): pass t = C((1, 2, 3)) print(t) micropython-1.12/tests/cpydiff/core_class_supermultiple.py000066400000000000000000000010411357706137100242650ustar00rootroot00000000000000""" categories: Core,Classes description: When inheriting from multiple classes super() only calls one class cause: See :ref:`cpydiff_core_class_mro` workaround: See :ref:`cpydiff_core_class_mro` """ class A: def __init__(self): print("A.__init__") class B(A): def __init__(self): print("B.__init__") super().__init__() class C(A): def __init__(self): print("C.__init__") super().__init__() class D(B,C): def __init__(self): print("D.__init__") super().__init__() D() micropython-1.12/tests/cpydiff/core_class_superproperty.py000066400000000000000000000005051357706137100243220ustar00rootroot00000000000000""" categories: Core,Classes description: Calling super() getter property in subclass will return a property object, not the value cause: Unknown workaround: Unknown """ class A: @property def p(self): return {"a":10} class AA(A): @property def p(self): return super().p a = AA() print(a.p) micropython-1.12/tests/cpydiff/core_function_argcount.py000066400000000000000000000004451357706137100237240ustar00rootroot00000000000000""" categories: Core,Functions description: Error messages for methods may display unexpected argument counts cause: MicroPython counts "self" as an argument. workaround: Interpret error messages with the information above in mind. """ try: [].append() except Exception as e: print(e) micropython-1.12/tests/cpydiff/core_function_userattr.py000066400000000000000000000004041357706137100237460ustar00rootroot00000000000000""" categories: Core,Functions description: User-defined attributes for functions are not supported cause: MicroPython is highly optimized for memory usage. workaround: Use external dictionary, e.g. ``FUNC_X[f] = 0``. """ def f(): pass f.x = 0 print(f.x) micropython-1.12/tests/cpydiff/core_generator_noexit.py000066400000000000000000000007131357706137100235470ustar00rootroot00000000000000""" categories: Core,Generator description: Context manager __exit__() not called in a generator which does not run to completion cause: Unknown workaround: Unknown """ class foo(object): def __enter__(self): print('Enter') def __exit__(self, *args): print('Exit') def bar(x): with foo(): while True: x += 1 yield x def func(): g = bar(0) for _ in range(3): print(next(g)) func() micropython-1.12/tests/cpydiff/core_import_path.py000066400000000000000000000007551357706137100225270ustar00rootroot00000000000000""" categories: Core,import description: __path__ attribute of a package has a different type (single string instead of list of strings) in MicroPython cause: MicroPython does't support namespace packages split across filesystem. Beyond that, MicroPython's import system is highly optimized for minimal memory usage. workaround: Details of import handling is inherently implementation dependent. Don't rely on such details in portable applications. """ import modules print(modules.__path__) micropython-1.12/tests/cpydiff/core_import_prereg.py000066400000000000000000000007761357706137100230620ustar00rootroot00000000000000""" categories: Core,import description: Failed to load modules are still registered as loaded cause: To make module handling more efficient, it's not wrapped with exception handling. workaround: Test modules before production use; during development, use ``del sys.modules["name"]``, or just soft or hard reset the board. """ import sys try: from modules import foo except NameError as e: print(e) try: from modules import foo print('Should not get here') except NameError as e: print(e) micropython-1.12/tests/cpydiff/core_import_split_ns_pkgs.py000066400000000000000000000013001357706137100244350ustar00rootroot00000000000000""" categories: Core,import description: MicroPython does't support namespace packages split across filesystem. cause: MicroPython's import system is highly optimized for simplicity, minimal memory usage, and minimal filesystem search overhead. workaround: Don't install modules belonging to the same namespace package in different directories. For MicroPython, it's recommended to have at most 3-component module search paths: for your current application, per-user (writable), system-wide (non-writable). """ import sys sys.path.append(sys.path[1] + "/modules") sys.path.append(sys.path[1] + "/modules2") import subpkg.foo import subpkg.bar print("Two modules of a split namespace package imported") micropython-1.12/tests/cpydiff/core_locals.py000066400000000000000000000005021357706137100214440ustar00rootroot00000000000000""" categories: Core,Runtime description: Local variables aren't included in locals() result cause: MicroPython doesn't maintain symbolic local environment, it is optimized to an array of slots. Thus, local variables can't be accessed by a name. workaround: Unknown """ def test(): val = 2 print(locals()) test() micropython-1.12/tests/cpydiff/core_locals_eval.py000066400000000000000000000007231357706137100224600ustar00rootroot00000000000000""" categories: Core,Runtime description: Code running in eval() function doesn't have access to local variables cause: MicroPython doesn't maintain symbolic local environment, it is optimized to an array of slots. Thus, local variables can't be accessed by a name. Effectively, ``eval(expr)`` in MicroPython is equivalent to ``eval(expr, globals(), globals())``. workaround: Unknown """ val = 1 def test(): val = 2 print(val) eval("print(val)") test() micropython-1.12/tests/cpydiff/modules/000077500000000000000000000000001357706137100202605ustar00rootroot00000000000000micropython-1.12/tests/cpydiff/modules/__init__.py000066400000000000000000000000001357706137100223570ustar00rootroot00000000000000micropython-1.12/tests/cpydiff/modules/foo.py000066400000000000000000000000211357706137100214060ustar00rootroot00000000000000print('foo') xxx micropython-1.12/tests/cpydiff/modules/subpkg/000077500000000000000000000000001357706137100215535ustar00rootroot00000000000000micropython-1.12/tests/cpydiff/modules/subpkg/foo.py000066400000000000000000000000001357706137100226760ustar00rootroot00000000000000micropython-1.12/tests/cpydiff/modules2/000077500000000000000000000000001357706137100203425ustar00rootroot00000000000000micropython-1.12/tests/cpydiff/modules2/subpkg/000077500000000000000000000000001357706137100216355ustar00rootroot00000000000000micropython-1.12/tests/cpydiff/modules2/subpkg/bar.py000066400000000000000000000000001357706137100227410ustar00rootroot00000000000000micropython-1.12/tests/cpydiff/modules_array_containment.py000066400000000000000000000002471357706137100244320ustar00rootroot00000000000000""" categories: Modules,array description: Looking for integer not implemented cause: Unknown workaround: Unknown """ import array print(1 in array.array('B', b'12')) micropython-1.12/tests/cpydiff/modules_array_deletion.py000066400000000000000000000002601357706137100237110ustar00rootroot00000000000000""" categories: Modules,array description: Array deletion not implemented cause: Unknown workaround: Unknown """ import array a = array.array('b', (1, 2, 3)) del a[1] print(a) micropython-1.12/tests/cpydiff/modules_array_subscrstep.py000066400000000000000000000002771357706137100243130ustar00rootroot00000000000000""" categories: Modules,array description: Subscript with step != 1 is not yet implemented cause: Unknown workaround: Unknown """ import array a = array.array('b', (1, 2, 3)) print(a[3:2:2]) micropython-1.12/tests/cpydiff/modules_deque.py000066400000000000000000000003401357706137100220120ustar00rootroot00000000000000""" categories: Modules,deque description: Deque not implemented cause: Unknown workaround: Use regular lists. micropython-lib has implementation of collections.deque. """ import collections D = collections.deque() print(D) micropython-1.12/tests/cpydiff/modules_json_nonserializable.py000066400000000000000000000004761357706137100251330ustar00rootroot00000000000000""" categories: Modules,json description: JSON module does not throw exception when object is not serialisable cause: Unknown workaround: Unknown """ import json a = bytes(x for x in range(256)) try: z = json.dumps(a) x = json.loads(z) print('Should not get here') except TypeError: print('TypeError') micropython-1.12/tests/cpydiff/modules_struct_fewargs.py000066400000000000000000000003731357706137100237570ustar00rootroot00000000000000""" categories: Modules,struct description: Struct pack with too few args, not checked by uPy cause: Unknown workaround: Unknown """ import struct try: print(struct.pack('bb', 1)) print('Should not get here') except: print('struct.error') micropython-1.12/tests/cpydiff/modules_struct_manyargs.py000066400000000000000000000004021357706137100241330ustar00rootroot00000000000000""" categories: Modules,struct description: Struct pack with too many args, not checked by uPy cause: Unknown workaround: Unknown """ import struct try: print(struct.pack('bb', 1, 2, 3)) print('Should not get here') except: print('struct.error') micropython-1.12/tests/cpydiff/modules_sys_stdassign.py000066400000000000000000000003271357706137100236110ustar00rootroot00000000000000""" categories: Modules,sys description: Overriding sys.stdin, sys.stdout and sys.stderr not possible cause: They are stored in read-only memory. workaround: Unknown """ import sys sys.stdin = None print(sys.stdin) micropython-1.12/tests/cpydiff/syntax_spaces.py000066400000000000000000000006251357706137100220510ustar00rootroot00000000000000""" categories: Syntax,Spaces description: uPy requires spaces between literal numbers and keywords, CPy doesn't cause: Unknown workaround: Unknown """ try: print(eval('1and 0')) except SyntaxError: print('Should have worked') try: print(eval('1or 0')) except SyntaxError: print('Should have worked') try: print(eval('1if 1else 0')) except SyntaxError: print('Should have worked') micropython-1.12/tests/cpydiff/syntax_unicode_nameesc.py000066400000000000000000000002361357706137100237120ustar00rootroot00000000000000""" categories: Syntax,Unicode description: Unicode name escapes are not implemented cause: Unknown workaround: Unknown """ print("\N{LATIN SMALL LETTER A}") micropython-1.12/tests/cpydiff/types_bytearray_sliceassign.py000066400000000000000000000002521357706137100247730ustar00rootroot00000000000000""" categories: Types,bytearray description: Array slice assignment with unsupported RHS cause: Unknown workaround: Unknown """ b = bytearray(4) b[0:1] = [1, 2] print(b) micropython-1.12/tests/cpydiff/types_bytes_format.py000066400000000000000000000007621357706137100231110ustar00rootroot00000000000000""" categories: Types,bytes description: bytes objects support .format() method cause: MicroPython strives to be a more regular implementation, so if both `str` and `bytes` support ``__mod__()`` (the % operator), it makes sense to support ``format()`` for both too. Support for ``__mod__`` can also be compiled out, which leaves only ``format()`` for bytes formatting. workaround: If you are interested in CPython compatibility, don't use ``.format()`` on bytes objects. """ print(b'{}'.format(1)) micropython-1.12/tests/cpydiff/types_bytes_keywords.py000066400000000000000000000003461357706137100234660ustar00rootroot00000000000000""" categories: Types,bytes description: bytes() with keywords not implemented cause: Unknown workaround: Pass the encoding as a positional parameter, e.g. ``print(bytes('abc', 'utf-8'))`` """ print(bytes('abc', encoding='utf8')) micropython-1.12/tests/cpydiff/types_bytes_subscrstep.py000066400000000000000000000003511357706137100240100ustar00rootroot00000000000000""" categories: Types,bytes description: Bytes subscription with step != 1 not implemented cause: MicroPython is highly optimized for memory usage. workaround: Use explicit loop for this very rare operation. """ print(b'123'[0:3:2]) micropython-1.12/tests/cpydiff/types_exception_chaining.py000066400000000000000000000002671357706137100242510ustar00rootroot00000000000000""" categories: Types,Exception description: Exception chaining not implemented cause: Unknown workaround: Unknown """ try: raise TypeError except TypeError: raise ValueError micropython-1.12/tests/cpydiff/types_exception_instancevar.py000066400000000000000000000004011357706137100247740ustar00rootroot00000000000000""" categories: Types,Exception description: User-defined attributes for builtin exceptions are not supported cause: MicroPython is highly optimized for memory usage. workaround: Use user-defined exception subclasses. """ e = Exception() e.x = 0 print(e.x) micropython-1.12/tests/cpydiff/types_exception_loops.py000066400000000000000000000005011357706137100236140ustar00rootroot00000000000000""" categories: Types,Exception description: Exception in while loop condition may have unexpected line number cause: Condition checks are optimized to happen at the end of loop body, and that line number is reported. workaround: Unknown """ l = ["-foo", "-bar"] i = 0 while l[i][0] == "-": print("iter") i += 1 micropython-1.12/tests/cpydiff/types_exception_subclassinit.py000066400000000000000000000005731357706137100251740ustar00rootroot00000000000000""" categories: Types,Exception description: Exception.__init__ method does not exist. cause: Subclassing native classes is not fully supported in MicroPython. workaround: Call using ``super()`` instead:: class A(Exception): def __init__(self): super().__init__() """ class A(Exception): def __init__(self): Exception.__init__(self) a = A() micropython-1.12/tests/cpydiff/types_float_rounding.py000066400000000000000000000002201357706137100234120ustar00rootroot00000000000000""" categories: Types,float description: uPy and CPython outputs formats may differ cause: Unknown workaround: Unknown """ print('%.1g' % -9.9) micropython-1.12/tests/cpydiff/types_int_subclassconv.py000066400000000000000000000005151357706137100237660ustar00rootroot00000000000000""" categories: Types,int description: No int conversion for int-derived types available cause: Unknown workaround: Avoid subclassing builtin types unless really needed. Prefer https://en.wikipedia.org/wiki/Composition_over_inheritance . """ class A(int): __add__ = lambda self, other: A(int(self) + other) a = A(42) print(a+a) micropython-1.12/tests/cpydiff/types_list_delete_subscrstep.py000066400000000000000000000003041357706137100251550ustar00rootroot00000000000000""" categories: Types,list description: List delete with step != 1 not implemented cause: Unknown workaround: Use explicit loop for this rare operation. """ l = [1, 2, 3, 4] del l[0:4:2] print(l) micropython-1.12/tests/cpydiff/types_list_store_noniter.py000066400000000000000000000004121357706137100243300ustar00rootroot00000000000000""" categories: Types,list description: List slice-store with non-iterable on RHS is not implemented cause: RHS is restricted to be a tuple or list workaround: Use ``list()`` on RHS to convert the iterable to a list """ l = [10, 20] l[0:1] = range(4) print(l) micropython-1.12/tests/cpydiff/types_list_store_subscrstep.py000066400000000000000000000003101357706137100250440ustar00rootroot00000000000000""" categories: Types,list description: List store with step != 1 not implemented cause: Unknown workaround: Use explicit loop for this rare operation. """ l = [1, 2, 3, 4] l[0:4:2] = [5, 6] print(l) micropython-1.12/tests/cpydiff/types_str_endswith.py000066400000000000000000000002551357706137100231250ustar00rootroot00000000000000""" categories: Types,str description: Start/end indices such as str.endswith(s, start) not implemented cause: Unknown workaround: Unknown """ print('abc'.endswith('c', 1)) micropython-1.12/tests/cpydiff/types_str_formatsubscr.py000066400000000000000000000002211357706137100240030ustar00rootroot00000000000000""" categories: Types,str description: Attributes/subscr not implemented cause: Unknown workaround: Unknown """ print('{a[0]}'.format(a=[1, 2])) micropython-1.12/tests/cpydiff/types_str_keywords.py000066400000000000000000000003311357706137100231420ustar00rootroot00000000000000""" categories: Types,str description: str(...) with keywords not implemented cause: Unknown workaround: Input the encoding format directly. eg ``print(bytes('abc', 'utf-8'))`` """ print(str(b'abc', encoding='utf8')) micropython-1.12/tests/cpydiff/types_str_ljust_rjust.py000066400000000000000000000005601357706137100236670ustar00rootroot00000000000000""" categories: Types,str description: str.ljust() and str.rjust() not implemented cause: MicroPython is highly optimized for memory usage. Easy workarounds available. workaround: Instead of ``s.ljust(10)`` use ``"%-10s" % s``, instead of ``s.rjust(10)`` use ``"% 10s" % s``. Alternatively, ``"{:<10}".format(s)`` or ``"{:>10}".format(s)``. """ print('abc'.ljust(10)) micropython-1.12/tests/cpydiff/types_str_rsplitnone.py000066400000000000000000000002731357706137100234750ustar00rootroot00000000000000""" categories: Types,str description: None as first argument for rsplit such as str.rsplit(None, n) not implemented cause: Unknown workaround: Unknown """ print('a a a'.rsplit(None, 1)) micropython-1.12/tests/cpydiff/types_str_subclassequality.py000066400000000000000000000003411357706137100246710ustar00rootroot00000000000000""" categories: Types,str description: Instance of a subclass of str cannot be compared for equality with an instance of a str cause: Unknown workaround: Unknown """ class S(str): pass s = S('hello') print(s == 'hello') micropython-1.12/tests/cpydiff/types_str_subscrstep.py000066400000000000000000000002301357706137100234660ustar00rootroot00000000000000""" categories: Types,str description: Subscript with step != 1 is not yet implemented cause: Unknown workaround: Unknown """ print('abcdefghi'[0:9:2]) micropython-1.12/tests/cpydiff/types_tuple_subscrstep.py000066400000000000000000000002251357706137100240130ustar00rootroot00000000000000""" categories: Types,tuple description: Tuple load with step != 1 not implemented cause: Unknown workaround: Unknown """ print((1, 2, 3, 4)[0:4:2]) micropython-1.12/tests/extmod/000077500000000000000000000000001357706137100164645ustar00rootroot00000000000000micropython-1.12/tests/extmod/btree1.py000066400000000000000000000026471357706137100202310ustar00rootroot00000000000000try: import btree import uio import uerrno except ImportError: print("SKIP") raise SystemExit #f = open("_test.db", "w+b") f = uio.BytesIO() db = btree.open(f, pagesize=512) db[b"foo3"] = b"bar3" db[b"foo1"] = b"bar1" db[b"foo2"] = b"bar2" db[b"bar1"] = b"foo1" dbstr = str(db) print(dbstr[:7], dbstr[-1:]) print(db[b"foo2"]) try: print(db[b"foo"]) except KeyError: print("KeyError") print(db.get(b"foo")) print(db.get(b"foo", b"dflt")) del db[b"foo2"] try: del db[b"foo"] except KeyError: print("KeyError") for k, v in db.items(): print((k, v)) print("---") for k, v in db.items(None, None): print((k, v)) print("---") for k, v in db.items(b"f"): print((k, v)) print("---") for k, v in db.items(b"f", b"foo3"): print((k, v)) print("---") for k, v in db.items(None, b"foo3"): print((k, v)) print("---") for k, v in db.items(b"f", b"foo3", btree.INCL): print((k, v)) print("---") for k, v in db.items(None, None, btree.DESC): print((k, v)) print(db.seq(1, b"foo1")) print(db.seq(1, b"qux")) try: db.seq(b"foo1") except OSError as e: print(e.args[0] == uerrno.EINVAL) print(list(db.keys())) print(list(db.values())) for k in db: print(k) db.put(b"baz1", b"qux1") print("foo1", "foo1" in db) print("foo2", "foo2" in db) print("baz1", "baz1" in db) try: print(db + db[b"foo1"]) except TypeError: print("TypeError") db.flush() db.close() f.close() micropython-1.12/tests/extmod/btree1.py.exp000066400000000000000000000010171357706137100210120ustar00rootroot00000000000000 b'bar2' KeyError None b'dflt' KeyError (b'bar1', b'foo1') (b'foo1', b'bar1') (b'foo3', b'bar3') --- (b'bar1', b'foo1') (b'foo1', b'bar1') (b'foo3', b'bar3') --- (b'foo1', b'bar1') (b'foo3', b'bar3') --- (b'foo1', b'bar1') --- (b'bar1', b'foo1') (b'foo1', b'bar1') --- (b'foo1', b'bar1') (b'foo3', b'bar3') --- (b'foo3', b'bar3') (b'foo1', b'bar1') (b'bar1', b'foo1') (b'foo1', b'bar1') None True [b'bar1', b'foo1', b'foo3'] [b'foo1', b'bar1', b'bar3'] b'bar1' b'foo1' b'foo3' foo1 True foo2 False baz1 True TypeError micropython-1.12/tests/extmod/framebuf1.py000066400000000000000000000041711357706137100207110ustar00rootroot00000000000000try: import framebuf except ImportError: print("SKIP") raise SystemExit w = 5 h = 16 size = w * h // 8 buf = bytearray(size) maps = {framebuf.MONO_VLSB : 'MONO_VLSB', framebuf.MONO_HLSB : 'MONO_HLSB', framebuf.MONO_HMSB : 'MONO_HMSB'} for mapping in maps.keys(): for x in range(size): buf[x] = 0 fbuf = framebuf.FrameBuffer(buf, w, h, mapping) print(maps[mapping]) # access as buffer print(memoryview(fbuf)[0]) # fill fbuf.fill(1) print(buf) fbuf.fill(0) print(buf) # put pixel fbuf.pixel(0, 0, 1) fbuf.pixel(4, 0, 1) fbuf.pixel(0, 15, 1) fbuf.pixel(4, 15, 1) print(buf) # clear pixel fbuf.pixel(4, 15, 0) print(buf) # get pixel print(fbuf.pixel(0, 0), fbuf.pixel(1, 1)) # hline fbuf.fill(0) fbuf.hline(0, 1, w, 1) print('hline', buf) # vline fbuf.fill(0) fbuf.vline(1, 0, h, 1) print('vline', buf) # rect fbuf.fill(0) fbuf.rect(1, 1, 3, 3, 1) print('rect', buf) #fill rect fbuf.fill(0) fbuf.fill_rect(0, 0, 0, 3, 1) # zero width, no-operation fbuf.fill_rect(1, 1, 3, 3, 1) print('fill_rect', buf) # line fbuf.fill(0) fbuf.line(1, 1, 3, 3, 1) print('line', buf) # line steep negative gradient fbuf.fill(0) fbuf.line(3, 3, 2, 1, 1) print('line', buf) # scroll fbuf.fill(0) fbuf.pixel(2, 7, 1) fbuf.scroll(0, 1) print(buf) fbuf.scroll(0, -2) print(buf) fbuf.scroll(1, 0) print(buf) fbuf.scroll(-1, 0) print(buf) fbuf.scroll(2, 2) print(buf) # print text fbuf.fill(0) fbuf.text("hello", 0, 0, 1) print(buf) fbuf.text("hello", 0, 0, 0) # clear print(buf) # char out of font range set to chr(127) fbuf.text(str(chr(31)), 0, 0) print(buf) print() # test invalid constructor, and stride argument try: fbuf = framebuf.FrameBuffer(buf, w, h, -1, w) except ValueError: print("ValueError") # test legacy constructor fbuf = framebuf.FrameBuffer1(buf, w, h) fbuf = framebuf.FrameBuffer1(buf, w, h, w) print(framebuf.MVLSB == framebuf.MONO_VLSB) micropython-1.12/tests/extmod/framebuf1.py.exp000066400000000000000000000057131357706137100215070ustar00rootroot00000000000000MONO_VLSB 0 bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x01\x00\x00\x00\x01\x80\x00\x00\x00\x80') bytearray(b'\x01\x00\x00\x00\x01\x80\x00\x00\x00\x00') 1 0 hline bytearray(b'\x02\x02\x02\x02\x02\x00\x00\x00\x00\x00') vline bytearray(b'\x00\xff\x00\x00\x00\x00\xff\x00\x00\x00') rect bytearray(b'\x00\x0e\n\x0e\x00\x00\x00\x00\x00\x00') fill_rect bytearray(b'\x00\x0e\x0e\x0e\x00\x00\x00\x00\x00\x00') line bytearray(b'\x00\x02\x04\x08\x00\x00\x00\x00\x00\x00') line bytearray(b'\x00\x00\x06\x08\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00') bytearray(b'\x00\x00@\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00@\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00@\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01') bytearray(b'\x00\x7f\x7f\x04\x04\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\xaaU\xaaU\xaa\x00\x00\x00\x00\x00') MONO_HLSB 0 bytearray(b'\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00') 1 0 hline bytearray(b'\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00') vline bytearray(b'@@@@@@@@@@') rect bytearray(b'\x00pPp\x00\x00\x00\x00\x00\x00') fill_rect bytearray(b'\x00ppp\x00\x00\x00\x00\x00\x00') line bytearray(b'\x00@ \x10\x00\x00\x00\x00\x00\x00') line bytearray(b'\x00 \x10\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00 \x00') bytearray(b'\x00\x00\x00\x00\x00\x00 \x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00 \x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00') bytearray(b'``x````\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'P\xa8P\xa8P\xa8P\xa8\x00\x00') MONO_HMSB 0 bytearray(b'\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00') 1 0 hline bytearray(b'\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00') vline bytearray(b'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02') rect bytearray(b'\x00\x0e\n\x0e\x00\x00\x00\x00\x00\x00') fill_rect bytearray(b'\x00\x0e\x0e\x0e\x00\x00\x00\x00\x00\x00') line bytearray(b'\x00\x02\x04\x08\x00\x00\x00\x00\x00\x00') line bytearray(b'\x00\x04\x04\x08\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00') bytearray(b'\x06\x06\x1e\x06\x06\x06\x06\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\n\x15\n\x15\n\x15\n\x15\x00\x00') ValueError True micropython-1.12/tests/extmod/framebuf16.py000066400000000000000000000020431357706137100207730ustar00rootroot00000000000000try: import framebuf except ImportError: print("SKIP") raise SystemExit def printbuf(): print("--8<--") for y in range(h): print(buf[y * w * 2:(y + 1) * w * 2]) print("-->8--") w = 4 h = 5 buf = bytearray(w * h * 2) fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.RGB565) # fill fbuf.fill(0xffff) printbuf() fbuf.fill(0x0000) printbuf() # put pixel fbuf.pixel(0, 0, 0xeeee) fbuf.pixel(3, 0, 0xee00) fbuf.pixel(0, 4, 0x00ee) fbuf.pixel(3, 4, 0x0ee0) printbuf() # get pixel print(fbuf.pixel(0, 4), fbuf.pixel(1, 1)) # scroll fbuf.fill(0x0000) fbuf.pixel(2, 2, 0xffff) printbuf() fbuf.scroll(0, 1) printbuf() fbuf.scroll(1, 0) printbuf() fbuf.scroll(-1, -2) printbuf() w2 = 2 h2 = 3 buf2 = bytearray(w2 * h2 * 2) fbuf2 = framebuf.FrameBuffer(buf2, w2, h2, framebuf.RGB565) fbuf2.fill(0x0000) fbuf2.pixel(0, 0, 0x0ee0) fbuf2.pixel(0, 2, 0xee00) fbuf2.pixel(1, 0, 0x00ee) fbuf2.pixel(1, 2, 0xe00e) fbuf.fill(0xffff) fbuf.blit(fbuf2, 3, 3, 0x0000) fbuf.blit(fbuf2, -1, -1, 0x0000) fbuf.blit(fbuf2, 16, 16, 0x0000) printbuf() micropython-1.12/tests/extmod/framebuf16.py.exp000066400000000000000000000037161357706137100215760ustar00rootroot00000000000000--8<-- bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') -->8-- --8<-- bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\xee\xee\x00\x00\x00\x00\x00\xee') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\xee\x00\x00\x00\x00\x00\xe0\x0e') -->8-- 238 0 --8<-- bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\xff\xff') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\xff\xff') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\x0e\xe0\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xe0\x0e') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') -->8-- micropython-1.12/tests/extmod/framebuf2.py000066400000000000000000000020521357706137100207060ustar00rootroot00000000000000try: import framebuf except ImportError: print("SKIP") raise SystemExit def printbuf(): print("--8<--") for y in range(h): for x in range(w): print('%u' % ((buf[(x + y * w) // 4] >> ((x & 3) << 1)) & 3), end='') print() print("-->8--") w = 8 h = 5 buf = bytearray(w * h // 4) fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS2_HMSB) # fill fbuf.fill(3) printbuf() fbuf.fill(0) printbuf() # put pixel fbuf.pixel(0, 0, 1) fbuf.pixel(3, 0, 2) fbuf.pixel(0, 4, 3) fbuf.pixel(3, 4, 2) printbuf() # get pixel print(fbuf.pixel(0, 4), fbuf.pixel(1, 1)) # scroll fbuf.fill(0) fbuf.pixel(2, 2, 3) printbuf() fbuf.scroll(0, 1) printbuf() fbuf.scroll(1, 0) printbuf() fbuf.scroll(-1, -2) printbuf() w2 = 2 h2 = 3 buf2 = bytearray(w2 * h2 // 4) fbuf2 = framebuf.FrameBuffer(buf2, w2, h2, framebuf.GS2_HMSB) # blit fbuf2.fill(0) fbuf2.pixel(0, 0, 1) fbuf2.pixel(0, 2, 2) fbuf2.pixel(1, 0, 1) fbuf2.pixel(1, 2, 2) fbuf.fill(3) fbuf.blit(fbuf2, 3, 3, 0) fbuf.blit(fbuf2, -1, -1, 0) fbuf.blit(fbuf2, 16, 16, 0) printbuf() micropython-1.12/tests/extmod/framebuf2.py.exp000066400000000000000000000007341357706137100215060ustar00rootroot00000000000000--8<-- 33333333 33333333 33333333 33333333 33333333 -->8-- --8<-- 00000000 00000000 00000000 00000000 00000000 -->8-- --8<-- 10020000 00000000 00000000 00000000 30020000 -->8-- 3 0 --8<-- 00000000 00000000 00300000 00000000 00000000 -->8-- --8<-- 00000000 00000000 00000000 00300000 00000000 -->8-- --8<-- 00000000 00000000 00000000 00030000 00000000 -->8-- --8<-- 00000000 00300000 00000000 00030000 00000000 -->8-- --8<-- 33333333 23333333 33333333 33311333 33333333 -->8-- micropython-1.12/tests/extmod/framebuf4.py000066400000000000000000000022021357706137100207050ustar00rootroot00000000000000try: import framebuf except ImportError: print("SKIP") raise SystemExit def printbuf(): print("--8<--") for y in range(h): print(buf[y * w // 2:(y + 1) * w // 2]) print("-->8--") w = 16 h = 8 buf = bytearray(w * h // 2) fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS4_HMSB) # fill fbuf.fill(0x0f) printbuf() fbuf.fill(0xa0) printbuf() # put pixel fbuf.pixel(0, 0, 0x01) printbuf() fbuf.pixel(w-1, 0, 0x02) printbuf() fbuf.pixel(w-1, h-1, 0x03) printbuf() fbuf.pixel(0, h-1, 0x04) printbuf() # get pixel print(fbuf.pixel(0, 0), fbuf.pixel(w-1, 0), fbuf.pixel(w-1, h-1), fbuf.pixel(0, h-1)) print(fbuf.pixel(1, 0), fbuf.pixel(w-2, 0), fbuf.pixel(w-2, h-1), fbuf.pixel(1, h-1)) # fill rect fbuf.fill_rect(0, 0, w, h, 0x0f) printbuf() fbuf.fill_rect(0, 0, w, h, 0xf0) fbuf.fill_rect(1, 0, w//2+1, 1, 0xf1) printbuf() fbuf.fill_rect(1, 0, w//2+1, 1, 0x10) fbuf.fill_rect(1, 0, w//2, 1, 0xf1) printbuf() fbuf.fill_rect(1, 0, w//2, 1, 0x10) fbuf.fill_rect(0, h-4, w//2+1, 4, 0xaf) printbuf() fbuf.fill_rect(0, h-4, w//2+1, 4, 0xb0) fbuf.fill_rect(0, h-4, w//2, 4, 0xaf) printbuf() fbuf.fill_rect(0, h-4, w//2, 4, 0xb0) micropython-1.12/tests/extmod/framebuf4.py.exp000066400000000000000000000103171357706137100215060ustar00rootroot00000000000000--8<-- bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') -->8-- --8<-- bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\x10\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\x10\x00\x00\x00\x00\x00\x00\x02') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\x10\x00\x00\x00\x00\x00\x00\x02') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x03') -->8-- --8<-- bytearray(b'\x10\x00\x00\x00\x00\x00\x00\x02') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'@\x00\x00\x00\x00\x00\x00\x03') -->8-- 1 2 3 4 0 0 0 0 --8<-- bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') -->8-- --8<-- bytearray(b'\x01\x11\x11\x11\x11\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\x01\x11\x11\x11\x10\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') -->8-- --8<-- bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\xff\xff\xff\xff\xf0\x00\x00\x00') bytearray(b'\xff\xff\xff\xff\xf0\x00\x00\x00') bytearray(b'\xff\xff\xff\xff\xf0\x00\x00\x00') bytearray(b'\xff\xff\xff\xff\xf0\x00\x00\x00') -->8-- --8<-- bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\xff\xff\xff\xff\x00\x00\x00\x00') bytearray(b'\xff\xff\xff\xff\x00\x00\x00\x00') bytearray(b'\xff\xff\xff\xff\x00\x00\x00\x00') bytearray(b'\xff\xff\xff\xff\x00\x00\x00\x00') -->8-- micropython-1.12/tests/extmod/framebuf8.py000066400000000000000000000011111357706137100207070ustar00rootroot00000000000000try: import framebuf except ImportError: print("SKIP") raise SystemExit def printbuf(): print("--8<--") for y in range(h): for x in range(w): print('%02x' % buf[(x + y * w)], end='') print() print("-->8--") w = 8 h = 5 buf = bytearray(w * h) fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) # fill fbuf.fill(0x55) printbuf() # put pixel fbuf.pixel(0, 0, 0x11) fbuf.pixel(w - 1, 0, 0x22) fbuf.pixel(0, h - 1, 0x33) fbuf.pixel(w - 1, h - 1, 0xff) printbuf() # get pixel print(hex(fbuf.pixel(0, h - 1)), hex(fbuf.pixel(1, 1))) micropython-1.12/tests/extmod/framebuf8.py.exp000066400000000000000000000003201357706137100215030ustar00rootroot00000000000000--8<-- 5555555555555555 5555555555555555 5555555555555555 5555555555555555 5555555555555555 -->8-- --8<-- 1155555555555522 5555555555555555 5555555555555555 5555555555555555 33555555555555ff -->8-- 0x33 0x55 micropython-1.12/tests/extmod/framebuf_subclass.py000066400000000000000000000006161357706137100225270ustar00rootroot00000000000000# test subclassing framebuf.FrameBuffer try: import framebuf except ImportError: print('SKIP') raise SystemExit class FB(framebuf.FrameBuffer): def __init__(self, n): self.n = n super().__init__(bytearray(2 * n * n), n, n, framebuf.RGB565) def foo(self): self.hline(0, 2, self.n, 0x0304) fb = FB(n=3) fb.pixel(0, 0, 0x0102) fb.foo() print(bytes(fb)) micropython-1.12/tests/extmod/framebuf_subclass.py.exp000066400000000000000000000001141357706137100233130ustar00rootroot00000000000000b'\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x03\x04\x03\x04\x03' micropython-1.12/tests/extmod/machine1.py000066400000000000000000000006431357706137100205260ustar00rootroot00000000000000# test machine module try: try: import umachine as machine except ImportError: import machine machine.mem8 except: print("SKIP") raise SystemExit print(machine.mem8) try: machine.mem16[1] except ValueError: print("ValueError") try: machine.mem16[1] = 1 except ValueError: print("ValueError") try: del machine.mem8[0] except TypeError: print("TypeError") micropython-1.12/tests/extmod/machine1.py.exp000066400000000000000000000000571357706137100213200ustar00rootroot00000000000000<8-bit memory> ValueError ValueError TypeError micropython-1.12/tests/extmod/machine_pinbase.py000066400000000000000000000007621357706137100221500ustar00rootroot00000000000000try: try: import umachine as machine except ImportError: import machine machine.PinBase except: print("SKIP") raise SystemExit class MyPin(machine.PinBase): def __init__(self): print("__init__") self.v = False def value(self, v=None): print("value:", v) if v is None: self.v = not self.v return int(self.v) p = MyPin() print(p.value()) print(p.value()) print(p.value()) p.value(1) p.value(0) micropython-1.12/tests/extmod/machine_pinbase.py.exp000066400000000000000000000001051357706137100227320ustar00rootroot00000000000000__init__ value: None 1 value: None 0 value: None 1 value: 1 value: 0 micropython-1.12/tests/extmod/machine_pulse.py000066400000000000000000000014741357706137100216600ustar00rootroot00000000000000try: try: import umachine as machine except ImportError: import machine machine.PinBase machine.time_pulse_us except: print("SKIP") raise SystemExit class ConstPin(machine.PinBase): def __init__(self, value): self.v = value def value(self, v=None): if v is None: return self.v else: self.v = v class TogglePin(machine.PinBase): def __init__(self): self.v = 0 def value(self, v=None): if v is None: self.v = 1 - self.v print("value:", self.v) return self.v p = TogglePin() t = machine.time_pulse_us(p, 1) print(type(t)) t = machine.time_pulse_us(p, 0) print(type(t)) p = ConstPin(0) print(machine.time_pulse_us(p, 1, 10)) print(machine.time_pulse_us(p, 0, 10)) micropython-1.12/tests/extmod/machine_pulse.py.exp000066400000000000000000000001171357706137100224440ustar00rootroot00000000000000value: 1 value: 0 value: 1 value: 0 value: 1 -2 -1 micropython-1.12/tests/extmod/machine_signal.py000066400000000000000000000012661357706137100220040ustar00rootroot00000000000000# test machine.Signal class try: try: import umachine as machine except ImportError: import machine machine.PinBase machine.Signal except: print("SKIP") raise SystemExit class Pin(machine.PinBase): def __init__(self): self.v = 0 def value(self, v=None): if v is None: return self.v else: self.v = int(v) # test non-inverted p = Pin() s = machine.Signal(p) s.value(0) print(p.value(), s.value()) s.value(1) print(p.value(), s.value()) # test inverted, and using on/off methods p = Pin() s = machine.Signal(p, invert=True) s.off() print(p.value(), s.value()) s.on() print(p.value(), s.value()) micropython-1.12/tests/extmod/machine_signal.py.exp000066400000000000000000000000201357706137100225620ustar00rootroot000000000000000 0 1 1 1 0 0 1 micropython-1.12/tests/extmod/ticks_diff.py000066400000000000000000000020741357706137100211460ustar00rootroot00000000000000from utime import ticks_diff, ticks_add MAX = ticks_add(0, -1) # Should be done like this to avoid small int overflow MODULO_HALF = MAX // 2 + 1 # Invariants: # if ticks_diff(a, b) = c, # then ticks_diff(b, a) = -c assert ticks_diff(1, 0) == 1, ticks_diff(1, 0) assert ticks_diff(0, 1) == -1 assert ticks_diff(0, MAX) == 1 assert ticks_diff(MAX, 0) == -1 assert ticks_diff(0, MAX - 1) == 2 # Maximum "positive" distance assert ticks_diff(MODULO_HALF, 1) == MODULO_HALF - 1, ticks_diff(MODULO_HALF, 1) # Step further, and it becomes a negative distance assert ticks_diff(MODULO_HALF, 0) == -MODULO_HALF # Offsetting that in either direction doesn't affect the result off = 100 # Cheating and skipping to use ticks_add() when we know there's no wraparound # Real apps should use always it. assert ticks_diff(MODULO_HALF + off, 1 + off) == MODULO_HALF - 1 assert ticks_diff(MODULO_HALF + off, 0 + off) == -MODULO_HALF assert ticks_diff(MODULO_HALF - off, ticks_add(1, -off)) == MODULO_HALF - 1 assert ticks_diff(MODULO_HALF - off, ticks_add(0, -off)) == -MODULO_HALF print("OK") micropython-1.12/tests/extmod/ticks_diff.py.exp000066400000000000000000000000031357706137100217270ustar00rootroot00000000000000OK micropython-1.12/tests/extmod/time_ms_us.py000066400000000000000000000007271357706137100212100ustar00rootroot00000000000000import utime try: utime.sleep_ms except AttributeError: print("SKIP") raise SystemExit utime.sleep_ms(1) utime.sleep_us(1) t0 = utime.ticks_ms() t1 = utime.ticks_ms() print(0 <= utime.ticks_diff(t1, t0) <= 1) t0 = utime.ticks_us() t1 = utime.ticks_us() print(0 <= utime.ticks_diff(t1, t0) <= 500) # ticks_cpu may not be implemented, at least make sure it doesn't decrease t0 = utime.ticks_cpu() t1 = utime.ticks_cpu() print(utime.ticks_diff(t1, t0) >= 0) micropython-1.12/tests/extmod/time_ms_us.py.exp000066400000000000000000000000171357706137100217730ustar00rootroot00000000000000True True True micropython-1.12/tests/extmod/ubinascii_a2b_base64.py000066400000000000000000000023371357706137100227010ustar00rootroot00000000000000try: try: import ubinascii as binascii except ImportError: import binascii except ImportError: print("SKIP") raise SystemExit print(binascii.a2b_base64(b'')) print(binascii.a2b_base64(b'Zg==')) print(binascii.a2b_base64(b'Zm8=')) print(binascii.a2b_base64(b'Zm9v')) print(binascii.a2b_base64(b'Zm9vYg==')) print(binascii.a2b_base64(b'Zm9vYmE=')) print(binascii.a2b_base64(b'Zm9vYmFy')) print(binascii.a2b_base64(b'AAECAwQFBgc=')) print(binascii.a2b_base64(b'CAkKCwwNDg8=')) print(binascii.a2b_base64(b'f4D/')) print(binascii.a2b_base64(b'f4D+')) # convert '+' print(binascii.a2b_base64(b'MTIzNEFCQ0RhYmNk')) # Ignore invalid characters and pad sequences print(binascii.a2b_base64(b'Zm9v\n')) print(binascii.a2b_base64(b'Zm\x009v\n')) print(binascii.a2b_base64(b'Zm9v==')) print(binascii.a2b_base64(b'Zm9v===')) print(binascii.a2b_base64(b'Zm9v===YmFy')) try: print(binascii.a2b_base64(b'abc')) except ValueError: print("ValueError") try: print(binascii.a2b_base64(b'abcde=')) except ValueError: print("ValueError") try: print(binascii.a2b_base64(b'ab*d')) except ValueError: print("ValueError") try: print(binascii.a2b_base64(b'ab=cdef=')) except ValueError: print("ValueError") micropython-1.12/tests/extmod/ubinascii_b2a_base64.py000066400000000000000000000012511357706137100226730ustar00rootroot00000000000000try: try: import ubinascii as binascii except ImportError: import binascii except ImportError: print("SKIP") raise SystemExit print(binascii.b2a_base64(b'')) print(binascii.b2a_base64(b'f')) print(binascii.b2a_base64(b'fo')) print(binascii.b2a_base64(b'foo')) print(binascii.b2a_base64(b'foob')) print(binascii.b2a_base64(b'fooba')) print(binascii.b2a_base64(b'foobar')) print(binascii.b2a_base64(b'\x00\x01\x02\x03\x04\x05\x06\x07')) print(binascii.b2a_base64(b'\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f')) print(binascii.b2a_base64(b'\x7f\x80\xff')) print(binascii.b2a_base64(b'1234ABCDabcd')) print(binascii.b2a_base64(b'\x00\x00>')) # convert into '+' micropython-1.12/tests/extmod/ubinascii_crc32.py000066400000000000000000000014021357706137100217750ustar00rootroot00000000000000try: try: import ubinascii as binascii except ImportError: import binascii except ImportError: print("SKIP") raise SystemExit try: binascii.crc32 except AttributeError: print("SKIP") raise SystemExit print(hex(binascii.crc32(b'The quick brown fox jumps over the lazy dog'))) print(hex(binascii.crc32(b'\x00' * 32))) print(hex(binascii.crc32(b'\xff' * 32))) print(hex(binascii.crc32(bytes(range(32))))) print(hex(binascii.crc32(b' over the lazy dog', binascii.crc32(b'The quick brown fox jumps')))) print(hex(binascii.crc32(b'\x00' * 16, binascii.crc32(b'\x00' * 16)))) print(hex(binascii.crc32(b'\xff' * 16, binascii.crc32(b'\xff' * 16)))) print(hex(binascii.crc32(bytes(range(16, 32)), binascii.crc32(bytes(range(16)))))) micropython-1.12/tests/extmod/ubinascii_hexlify.py000066400000000000000000000005531357706137100225370ustar00rootroot00000000000000try: try: import ubinascii as binascii except ImportError: import binascii except ImportError: print("SKIP") raise SystemExit print(binascii.hexlify(b'\x00\x01\x02\x03\x04\x05\x06\x07')) print(binascii.hexlify(b'\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f')) print(binascii.hexlify(b'\x7f\x80\xff')) print(binascii.hexlify(b'1234ABCDabcd')) micropython-1.12/tests/extmod/ubinascii_micropython.py000066400000000000000000000004641357706137100234430ustar00rootroot00000000000000try: try: import ubinascii as binascii except ImportError: import binascii except ImportError: print("SKIP") raise SystemExit # two arguments supported in uPy but not CPython a = binascii.hexlify(b'123', ':') print(a) # zero length buffer print(binascii.hexlify(b'', b':')) micropython-1.12/tests/extmod/ubinascii_micropython.py.exp000066400000000000000000000000201357706137100242220ustar00rootroot00000000000000b'31:32:33' b'' micropython-1.12/tests/extmod/ubinascii_unhexlify.py000066400000000000000000000010421357706137100230740ustar00rootroot00000000000000try: try: import ubinascii as binascii except ImportError: import binascii except ImportError: print("SKIP") raise SystemExit print(binascii.unhexlify(b'0001020304050607')) print(binascii.unhexlify(b'08090a0b0c0d0e0f')) print(binascii.unhexlify(b'7f80ff')) print(binascii.unhexlify(b'313233344142434461626364')) try: a = binascii.unhexlify(b'0') # odd buffer length except ValueError: print('ValueError') try: a = binascii.unhexlify(b'gg') # digit not hex except ValueError: print('ValueError') micropython-1.12/tests/extmod/ucryptolib_aes128_cbc.py000066400000000000000000000005421357706137100231250ustar00rootroot00000000000000try: from Crypto.Cipher import AES aes = AES.new except ImportError: try: from ucryptolib import aes except ImportError: print("SKIP") raise SystemExit crypto = aes(b"1234" * 4, 2, b"5678" * 4) enc = crypto.encrypt(bytes(range(32))) print(enc) crypto = aes(b"1234" * 4, 2, b"5678" * 4) print(crypto.decrypt(enc)) micropython-1.12/tests/extmod/ucryptolib_aes128_cbc.py.exp000066400000000000000000000003301357706137100237130ustar00rootroot00000000000000b'\x1d\x84\xfa\xaa%\x0e9\x143\x8b6\xf8\xdf^yh\xd0\x94g\xf4\xcf\x1d\xa0I)\x8a\xa0\x00u0+C' b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' micropython-1.12/tests/extmod/ucryptolib_aes128_ctr.py000066400000000000000000000010221357706137100231600ustar00rootroot00000000000000try: from ucryptolib import aes except ImportError: print("SKIP") raise SystemExit def _new(k, ctr_initial): return aes(k, 6, ctr_initial) try: _new(b'x' * 16, b'x' * 16) except ValueError as e: # is CTR support disabled? if e.args[0] == "mode": print("SKIP") raise SystemExit raise e crypto = _new(b"1234" * 4, b"5678" * 4) enc = crypto.encrypt(b'a') print(enc) enc += crypto.encrypt(b'b' * 1000) print(enc) crypto = _new(b"1234" * 4, b"5678" * 4) print(crypto.decrypt(enc)) micropython-1.12/tests/extmod/ucryptolib_aes128_ctr.py.exp000066400000000000000000000076261357706137100237730ustar00rootroot00000000000000b'\x06' b'\x06(F\x08\xc3hB\xfdO\x05;\xf6\x96\xfe\xad\xe0\xca\xe6\xd1\xa2m\t\x91v>|\xee\xe0q\xbc]\x9a`\xfal\x87\xa6e\xfb\x8a\xf4\xb2-\xc4x,\xfc@=,\x90\xf4\xe9h\xf0\xfc\xfb\xe6\x03\xf0d\xb6\xcdObZ\xde\x1b\xe2\x84-%=\xa9\xe4\x05\xab\xd7\x044\xf4$\xd0)\xfd\xd6\xdbL\xdd\xe6\x0cp\xca^p\xaaA\x8b\xb3!\xe3\x13\xfa\x7f#\xfa0\xbd\x0b\x9cX\xec\xed\x1c\xbc\x06\xa4\xa8\x17\xbfg\x98dW\xb9~\x04\xec\xe6lZ\xb0\xab\xd5\xc6v\xe4\x8f\x98G\xff\x9b\x8a\xae\xfd\xe5\xed\x96\x1b\xe2\x99u3\xeb\x9faYr;\xf0g\xf2\x9cq\x8dI\x1cL\xc9\xa8\xb0\xdeD\xd5\x06\x87u=\xcd\x10\x1c\xab\x14\x06n\x99\x13\x89\x9f5\xea\xd2\x08\x9e\xef$?\xb9\xdeQ\x0b\x90CH\xea@V\x94\x1a\xdd\x7f\x1dz\x82\xaay\xea$Lv\x07\x8e\xce\xb8oN\x15\xf8,\x05\x00\xd9H\xf4\xbe\xb8\xee\x0e\xd6Hjh\xc6\x11\xf8:\xfe\xed\xba_\xaf\x8e\'\x0c\x7fZ\xd5\xb7\xbc\xba\xd3+\xf1\x98i\xab\x0c-\xd9\xe6>\x9e\xd0\xe6>\x9f\xebn\xf0\x15\xd9:\xec\xf7aXa\xb2,CAB7\x18g\xcc#\xbc\xb8\xf9\xa7\xf4V\xba\x0baN\x88\xb1\xea\x94\x05\x0cV\x99_\xc4\xe6\xb2\xd1|\x92\x05*@U\xe4\\\x8dR\x98\xdf\xbfS\x97\x12^\tr\x1f\x12\x8f\xdfi\x8e=\xc4I\xfcB\r\x99f\xe3\xe31\xee\xa9\xcd\x91\x1a\x1ei\xfd\xf4\x84\xc6\xda\x9e\xf3\x8aKn\xaa\xf7\x9eS\xcc\xbaXZ\x0cpbk\x18\x1f\x9aAl>y\xad\xcb\xcf\xe1Wm\xe7\xdd\xcc\x10eW\xe4h\x1dY\xb5Zs\xf1\xe7\x16_\xdc:I1R\xd3\xfe\xb1)\t\xddE\xbax\x06R\xdc\x1dSdlu\xd1\x9c\x00\xaf\x87\x8d1\xbf$\x08\xc6/y\xdf\x1f\x97z(\xff\xb9\xcb\xf2,\x91\xd7\xa0W\xfc\xe3\xe2\x905\x17O\xaf\x18\xc7\xb8?\x94^\xf5@\x80\x8d\xaa*p\xbeR0i\x17\x1e\'-\xfa\xd9\xb2\x03\xb8\x1fY\x13\xc1{\x7f\xa9\x86\t\x99\xee\xa2\xba\xab\xc1\xbb\x07a\xa5J\x01\x98\xe8\x8e\xa1\x8aV\xc1)^A\xd9\xe7\xfej`\xb4\xe9\xd3C\xab\xd4\xdb\xb1\x8c\x83\xaa&\xf1\xe2\xfc\xa1Lb\xa8\xbb\xd6\x83\xb7\xd8\xc5\x9e\xb5\xed\x1b\xe6\x91\x90\xe4\xfa\xfdD\xc2\xcb\xb7U\xb3|?(\x86=\xc2\xff\xd3P\xd2\xc5y\x93\x13r\xcd>5\x80\xde\xdaJ\xdd\x8b\xfa\x14\xd1\x85\xa8P\x06(F\xb3?\xefm\x8e\xe5C\xfe\x98\xaf\xed\xd1!(\x1f.\xc6M\xba\x00\xcb\xbfg5\xc8\x9d\x97+\x14\x87\xf5\x9d4\xb4l\xd5\xc5>\x90\xf2\x06\xa2\xc1R\x89\xf0P\xb4\xe5\x97\xdb\x07\xd3\xc6q\x08\xb9\xe7\r\xf9\x13\x8215\xcb\x92\xed\x99\xc7"\x1e\xe3Zsh\x0e\xe7\xae\x10Xs&)\x1d\xe5\xd5\xbc\x95\x8e\xa3\xd6k[k\x9c\xa0%\xd4\x83%\x88}\x90\xf0\xa7\xc7\xa4(\xdaE\xb9~\xae\x05\xbd}\xe2\xd0\xa5Y\xc1aV[\xab\x93S\xa6\xacg\r\x14\xc6\xe2J\xd6\xcck"\xcc\xfb\xb3\x97\x14\x13\x0b\xd1\xf5\xe7)_\x1e\x0b\xbb\x01\xf7\x11u\x85b\xdf\xab\xe3\xbb:\x84zF\x14u\xfe\x89\x90\xbc\xcaF\x15y\xa3\xa4[\xce\xcf-\xae\x18\x97N\xaa\xed\x84A\xfc\x9e\xeb\xb3\xfcH\x8ej\xcc\x9f \x1b\xc1\x1f}\'q.\xc0^\xd99\x1e\x91b-\xf9\xed\xfd\x9a\x7f\xb6\rO\xea\xc8\x94\xea\xf6\xb4\xdb\xf5\xc7\xb3\xef\xf6D\x12>5\xf3\x9d*\xc9\xf8\x9f]\xb01{d\xe7\'\x8f\xc0\xfbKB\x8dd\xb1\x84\x804\xbe\xe2?AT\x14\xdb4eJ\x96\xc5\xb9%\xe5\x1c\xc0L\xae\xd6O\xde\x1fjJIRD\x96\xa2\xdb\xfc\xc6t\xce\xe6\xe8"\x81\xe6\xc7\x7fuz\xb3\x91\'D\xac\xb2\x93O\xee\x14\xaa7yT\xcf\x81p\x0b(\xa1d\xda\xf8\xcb\x01\x98\x07\'\xfe/\xe4\xca\xab\x03uR"zY\xfb\x1f\x02\xc5\x9c\xa0\'\x89\xffO\x88cK\xac\xb1+S0]%E\x1a\xeb\x04\xf7\x0b\xba\xa0\xbb\xbd|\x06@T\xee\xe7\x17\xa1T\xe3"\x07\x07q' b'abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' micropython-1.12/tests/extmod/ucryptolib_aes128_ecb.py000066400000000000000000000005101357706137100231220ustar00rootroot00000000000000try: from Crypto.Cipher import AES aes = AES.new except ImportError: try: from ucryptolib import aes except ImportError: print("SKIP") raise SystemExit crypto = aes(b"1234" * 4, 1) enc = crypto.encrypt(bytes(range(32))) print(enc) crypto = aes(b"1234" * 4, 1) print(crypto.decrypt(enc)) micropython-1.12/tests/extmod/ucryptolib_aes128_ecb.py.exp000066400000000000000000000003361357706137100237230ustar00rootroot00000000000000b'Iz\xfe9\x17\xac\xa4X\x12\x04\x10\xf5K~#\xc7\xac;\xf9\xc6E\xa8\xca~\xf1\xee\xd3f%\xf1\x8d\xfe' b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' micropython-1.12/tests/extmod/ucryptolib_aes128_ecb_enc.py000066400000000000000000000006401357706137100237530ustar00rootroot00000000000000# This tests minimal configuration of ucrypto module, which is # AES128 encryption (anything else, including AES128 decryption, # is optional). try: from Crypto.Cipher import AES aes = AES.new except ImportError: try: from ucryptolib import aes except ImportError: print("SKIP") raise SystemExit crypto = aes(b"1234" * 4, 1) enc = crypto.encrypt(bytes(range(32))) print(enc) micropython-1.12/tests/extmod/ucryptolib_aes128_ecb_enc.py.exp000066400000000000000000000001401357706137100245410ustar00rootroot00000000000000b'Iz\xfe9\x17\xac\xa4X\x12\x04\x10\xf5K~#\xc7\xac;\xf9\xc6E\xa8\xca~\xf1\xee\xd3f%\xf1\x8d\xfe' micropython-1.12/tests/extmod/ucryptolib_aes128_ecb_inpl.py000066400000000000000000000005001357706137100241430ustar00rootroot00000000000000# Inplace operations (input and output buffer is the same) try: from ucryptolib import aes except ImportError: print("SKIP") raise SystemExit crypto = aes(b"1234" * 4, 1) buf = bytearray(bytes(range(32))) crypto.encrypt(buf, buf) print(buf) crypto = aes(b"1234" * 4, 1) crypto.decrypt(buf, buf) print(buf) micropython-1.12/tests/extmod/ucryptolib_aes128_ecb_inpl.py.exp000066400000000000000000000003641357706137100247460ustar00rootroot00000000000000bytearray(b'Iz\xfe9\x17\xac\xa4X\x12\x04\x10\xf5K~#\xc7\xac;\xf9\xc6E\xa8\xca~\xf1\xee\xd3f%\xf1\x8d\xfe') bytearray(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f') micropython-1.12/tests/extmod/ucryptolib_aes128_ecb_into.py000066400000000000000000000005061357706137100241600ustar00rootroot00000000000000# Operations with pre-allocated output buffer try: from ucryptolib import aes except ImportError: print("SKIP") raise SystemExit crypto = aes(b"1234" * 4, 1) enc = bytearray(32) crypto.encrypt(bytes(range(32)), enc) print(enc) crypto = aes(b"1234" * 4, 1) dec = bytearray(32) crypto.decrypt(enc, dec) print(dec) micropython-1.12/tests/extmod/ucryptolib_aes128_ecb_into.py.exp000066400000000000000000000003641357706137100247550ustar00rootroot00000000000000bytearray(b'Iz\xfe9\x17\xac\xa4X\x12\x04\x10\xf5K~#\xc7\xac;\xf9\xc6E\xa8\xca~\xf1\xee\xd3f%\xf1\x8d\xfe') bytearray(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f') micropython-1.12/tests/extmod/ucryptolib_aes256_cbc.py000066400000000000000000000005421357706137100231270ustar00rootroot00000000000000try: from Crypto.Cipher import AES aes = AES.new except ImportError: try: from ucryptolib import aes except ImportError: print("SKIP") raise SystemExit crypto = aes(b"1234" * 8, 2, b"5678" * 4) enc = crypto.encrypt(bytes(range(32))) print(enc) crypto = aes(b"1234" * 8, 2, b"5678" * 4) print(crypto.decrypt(enc)) micropython-1.12/tests/extmod/ucryptolib_aes256_cbc.py.exp000066400000000000000000000003441357706137100237220ustar00rootroot00000000000000b'\xb4\x0b\xff\xdd\xfc\xb5\x03\x88[m\xc1\x01+:\x03M\x18\xb03\x0f\x971g\x10\xb1\x98>\x9b\x17\xb7-\xb2' b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' micropython-1.12/tests/extmod/ucryptolib_aes256_ecb.py000066400000000000000000000005101357706137100231240ustar00rootroot00000000000000try: from Crypto.Cipher import AES aes = AES.new except ImportError: try: from ucryptolib import aes except ImportError: print("SKIP") raise SystemExit crypto = aes(b"1234" * 8, 1) enc = crypto.encrypt(bytes(range(32))) print(enc) crypto = aes(b"1234" * 8, 1) print(crypto.decrypt(enc)) micropython-1.12/tests/extmod/ucryptolib_aes256_ecb.py.exp000066400000000000000000000003301357706137100237170ustar00rootroot00000000000000b'\xe2\xe0\xdd\xef\xc3\xcd\x88/!>\xf6\xa2\xef/\xd15z+`\xb2\xb2\xd7}!:V>\xeb\x19\xbf|\xea' b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' micropython-1.12/tests/extmod/uctypes_32bit_intbig.py000066400000000000000000000015761357706137100231020ustar00rootroot00000000000000# This test checks previously known problem values for 32-bit ports. # It's less useful for 64-bit ports. try: import uctypes except ImportError: print("SKIP") raise SystemExit buf = b"12345678abcd" struct = uctypes.struct( uctypes.addressof(buf), {"f32": uctypes.UINT32 | 0, "f64": uctypes.UINT64 | 4}, uctypes.LITTLE_ENDIAN ) struct.f32 = 0x7fffffff print(buf) struct.f32 = 0x80000000 print(buf) struct.f32 = 0xff010203 print(buf) struct.f64 = 0x80000000 print(buf) struct.f64 = 0x80000000 * 2 print(buf) print("=") buf = b"12345678abcd" struct = uctypes.struct( uctypes.addressof(buf), {"f32": uctypes.UINT32 | 0, "f64": uctypes.UINT64 | 4}, uctypes.BIG_ENDIAN ) struct.f32 = 0x7fffffff print(buf) struct.f32 = 0x80000000 print(buf) struct.f32 = 0xff010203 print(buf) struct.f64 = 0x80000000 print(buf) struct.f64 = 0x80000000 * 2 print(buf) micropython-1.12/tests/extmod/uctypes_32bit_intbig.py.exp000066400000000000000000000005721357706137100236700ustar00rootroot00000000000000b'\xff\xff\xff\x7f5678abcd' b'\x00\x00\x00\x805678abcd' b'\x03\x02\x01\xff5678abcd' b'\x03\x02\x01\xff\x00\x00\x00\x80\x00\x00\x00\x00' b'\x03\x02\x01\xff\x00\x00\x00\x00\x01\x00\x00\x00' = b'\x7f\xff\xff\xff5678abcd' b'\x80\x00\x00\x005678abcd' b'\xff\x01\x02\x035678abcd' b'\xff\x01\x02\x03\x00\x00\x00\x00\x80\x00\x00\x00' b'\xff\x01\x02\x03\x00\x00\x00\x01\x00\x00\x00\x00' micropython-1.12/tests/extmod/uctypes_array_assign_le.py000066400000000000000000000025511357706137100237570ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit desc = { # arr is array at offset 0, of UINT8 elements, array size is 2 "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), # arr2 is array at offset 0, size 2, of structures defined recursively "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}), "arr3": (uctypes.ARRAY | 2, uctypes.UINT16 | 2), # aligned "arr5": (uctypes.ARRAY | 0, uctypes.UINT32 | 1), # unaligned "arr6": (uctypes.ARRAY | 1, uctypes.UINT32 | 1), "arr7": (uctypes.ARRAY | 0, 1, {"l": uctypes.UINT32 | 0}), "arr8": (uctypes.ARRAY | 1, 1, {"l": uctypes.UINT32 | 0}) } data = bytearray(5) S = uctypes.struct(uctypes.addressof(data), desc, uctypes.LITTLE_ENDIAN) # assign byte S.arr[0] = 0x11 print(hex(S.arr[0])) assert hex(S.arr[0]) == "0x11" # assign word S.arr3[0] = 0x2233 print(hex(S.arr3[0])) assert hex(S.arr3[0]) == "0x2233" # assign word, with index S.arr3[1] = 0x4455 print(hex(S.arr3[1])) assert hex(S.arr3[1]) == "0x4455" # assign long, aligned S.arr5[0] = 0x66778899 print(hex(S.arr5[0])) assert hex(S.arr5[0]) == "0x66778899" print(S.arr5[0] == S.arr7[0].l) assert S.arr5[0] == S.arr7[0].l # assign long, unaligned S.arr6[0] = 0xAABBCCDD print(hex(S.arr6[0])) assert hex(S.arr6[0]) == "0xaabbccdd" print(S.arr6[0] == S.arr8[0].l) assert S.arr6[0] == S.arr8[0].l micropython-1.12/tests/extmod/uctypes_array_assign_le.py.exp000066400000000000000000000000631357706137100245460ustar00rootroot000000000000000x11 0x2233 0x4455 0x66778899 True 0xaabbccdd True micropython-1.12/tests/extmod/uctypes_array_assign_native_le.py000066400000000000000000000037321357706137100253270ustar00rootroot00000000000000import sys try: import uctypes except ImportError: print("SKIP") raise SystemExit if sys.byteorder != "little": print("SKIP") raise SystemExit desc = { # arr is array at offset 0, of UINT8 elements, array size is 2 "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), # arr2 is array at offset 0, size 2, of structures defined recursively "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}), "arr3": (uctypes.ARRAY | 2, uctypes.UINT16 | 2), # aligned "arr5": (uctypes.ARRAY | 0, uctypes.UINT32 | 1), "arr7": (uctypes.ARRAY | 0, 1, {"l": uctypes.UINT32 | 0}), "arr8": (uctypes.ARRAY | 0, uctypes.INT8 | 1), "arr9": (uctypes.ARRAY | 0, uctypes.INT16 | 1), "arr10": (uctypes.ARRAY | 0, uctypes.INT32 | 1), "arr11": (uctypes.ARRAY | 0, uctypes.INT64 | 1), "arr12": (uctypes.ARRAY | 0, uctypes.UINT64| 1), "arr13": (uctypes.ARRAY | 1, 1, {"l": {}}), } data = bytearray(8) S = uctypes.struct(uctypes.addressof(data), desc) # assign byte S.arr[0] = 0x11 print(hex(S.arr[0])) assert hex(S.arr[0]) == "0x11" # assign word S.arr3[0] = 0x2233 print(hex(S.arr3[0])) assert hex(S.arr3[0]) == "0x2233" # assign word, with index S.arr3[1] = 0x4455 print(hex(S.arr3[1])) assert hex(S.arr3[1]) == "0x4455" # assign long, aligned S.arr5[0] = 0x66778899 print(hex(S.arr5[0])) assert hex(S.arr5[0]) == "0x66778899" print(S.arr5[0] == S.arr7[0].l) assert S.arr5[0] == S.arr7[0].l # assign int8 S.arr8[0] = 0x11 print(hex(S.arr8[0])) assert hex(S.arr8[0]) == "0x11" # assign int16 S.arr9[0] = 0x1122 print(hex(S.arr9[0])) assert hex(S.arr9[0]) == "0x1122" # assign int32 S.arr10[0] = 0x11223344 print(hex(S.arr10[0])) assert hex(S.arr10[0]) == "0x11223344" # index out of range try: print(S.arr8[2]) except IndexError: print("IndexError") # syntax error in descriptor try: S.arr13[0].l = 0x11 except TypeError: print("TypeError") # operation not supported try: S.arr13[0] = 0x11 except TypeError: print("TypeError") micropython-1.12/tests/extmod/uctypes_array_assign_native_le.py.exp000066400000000000000000000001311357706137100261100ustar00rootroot000000000000000x11 0x2233 0x4455 0x66778899 True 0x11 0x1122 0x11223344 IndexError TypeError TypeError micropython-1.12/tests/extmod/uctypes_array_assign_native_le_intbig.py000066400000000000000000000022631357706137100266610ustar00rootroot00000000000000import sys try: import uctypes except ImportError: print("SKIP") raise SystemExit if sys.byteorder != "little": print("SKIP") raise SystemExit desc = { # arr is array at offset 0, of UINT8 elements, array size is 2 "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), # arr2 is array at offset 0, size 2, of structures defined recursively "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}), "arr3": (uctypes.ARRAY | 2, uctypes.UINT16 | 2), # aligned "arr5": (uctypes.ARRAY | 0, uctypes.UINT32 | 1), "arr7": (uctypes.ARRAY | 0, 1, {"l": uctypes.UINT32 | 0}), "arr8": (uctypes.ARRAY | 0, uctypes.INT8 | 1), "arr9": (uctypes.ARRAY | 0, uctypes.INT16 | 1), "arr10": (uctypes.ARRAY | 0, uctypes.INT32 | 1), "arr11": (uctypes.ARRAY | 0, uctypes.INT64 | 1), "arr12": (uctypes.ARRAY | 0, uctypes.UINT64| 1), "arr13": (uctypes.ARRAY | 1, 1, {"l": {}}), } data = bytearray(8) S = uctypes.struct(uctypes.addressof(data), desc) # assign int64 S.arr11[0] = 0x11223344 print(hex(S.arr11[0])) assert hex(S.arr11[0]) == "0x11223344" # assign uint64 S.arr12[0] = 0x11223344 print(hex(S.arr12[0])) assert hex(S.arr12[0]) == "0x11223344" micropython-1.12/tests/extmod/uctypes_array_assign_native_le_intbig.py.exp000066400000000000000000000000261357706137100274470ustar00rootroot000000000000000x11223344 0x11223344 micropython-1.12/tests/extmod/uctypes_bytearray.py000066400000000000000000000007271357706137100226220ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit desc = { "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), "arr2": (uctypes.ARRAY | 2, uctypes.INT8 | 2), } data = bytearray(b"01234567") S = uctypes.struct(uctypes.addressof(data), desc, uctypes.LITTLE_ENDIAN) # Arrays of UINT8 are accessed as bytearrays print(S.arr) # But not INT8, because value range is different print(type(S.arr2)) # convert to buffer print(bytearray(S)) micropython-1.12/tests/extmod/uctypes_bytearray.py.exp000066400000000000000000000000651357706137100234100ustar00rootroot00000000000000bytearray(b'01') bytearray(b'0123') micropython-1.12/tests/extmod/uctypes_byteat.py000066400000000000000000000003411357706137100221000ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit data = bytearray(b'01234567') print(uctypes.bytes_at(uctypes.addressof(data), 4)) print(uctypes.bytearray_at(uctypes.addressof(data), 4)) micropython-1.12/tests/extmod/uctypes_byteat.py.exp000066400000000000000000000000331357706137100226710ustar00rootroot00000000000000b'0123' bytearray(b'0123') micropython-1.12/tests/extmod/uctypes_error.py000066400000000000000000000015111357706137100217410ustar00rootroot00000000000000# test general errors with uctypes try: import uctypes except ImportError: print("SKIP") raise SystemExit data = bytearray(b"01234567") # del subscr not supported S = uctypes.struct(uctypes.addressof(data), {}) try: del S[0] except TypeError: print('TypeError') # list is an invalid descriptor S = uctypes.struct(uctypes.addressof(data), []) try: S.x except TypeError: print('TypeError') # can't access attribute with invalid descriptor S = uctypes.struct(uctypes.addressof(data), {'x':[]}) try: S.x except TypeError: print('TypeError') # can't assign to aggregate S = uctypes.struct(uctypes.addressof(data), {'x':(uctypes.ARRAY | 0, uctypes.INT8 | 2)}) try: S.x = 1 except TypeError: print('TypeError') # unsupported unary op try: hash(S) except TypeError: print('TypeError') micropython-1.12/tests/extmod/uctypes_error.py.exp000066400000000000000000000000621357706137100225340ustar00rootroot00000000000000TypeError TypeError TypeError TypeError TypeError micropython-1.12/tests/extmod/uctypes_le.py000066400000000000000000000043521357706137100212160ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit desc = { "s0": uctypes.UINT16 | 0, "sub": (0, { "b0": uctypes.UINT8 | 0, "b1": uctypes.UINT8 | 1, }), "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}), "bitf0": uctypes.BFUINT16 | 0 | 0 << uctypes.BF_POS | 8 << uctypes.BF_LEN, "bitf1": uctypes.BFUINT16 | 0 | 8 << uctypes.BF_POS | 8 << uctypes.BF_LEN, "bf0": uctypes.BFUINT16 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "bf1": uctypes.BFUINT16 | 0 | 4 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "bf2": uctypes.BFUINT16 | 0 | 8 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "bf3": uctypes.BFUINT16 | 0 | 12 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "ptr": (uctypes.PTR | 0, uctypes.UINT8), "ptr2": (uctypes.PTR | 0, {"b": uctypes.UINT8 | 0}), } data = bytearray(b"01") S = uctypes.struct(uctypes.addressof(data), desc, uctypes.LITTLE_ENDIAN) #print(S) print(hex(S.s0)) assert hex(S.s0) == "0x3130" #print(S.sub.b0) print(S.sub.b0, S.sub.b1) assert S.sub.b0, S.sub.b1 == (0x30, 0x31) try: S[0] assert False, "Can't index struct" except TypeError: print("TypeError") print("arr:", S.arr[0], S.arr[1]) assert (S.arr[0], S.arr[1]) == (0x30, 0x31) print("arr of struct:", S.arr2[0].b, S.arr2[1].b) assert (S.arr2[0].b, S.arr2[1].b) == (0x30, 0x31) try: S.arr[2] assert False, "Out of bounds index" except IndexError: print("IndexError") print("bf:", S.bitf0, S.bitf1) assert (S.bitf0, S.bitf1) == (0x30, 0x31) print("bf 4bit:", S.bf3, S.bf2, S.bf1, S.bf0) assert (S.bf3, S.bf2, S.bf1, S.bf0) == (3, 1, 3, 0) # Write access S.sub.b0 = ord("2") print(data) assert bytes(data) == b"21" S.bf3 = 5 print(data) assert bytes(data) == b"2Q" desc2 = { "bf8": uctypes.BFUINT8 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "bf32": uctypes.BFUINT32 | 0 | 20 << uctypes.BF_POS | 4 << uctypes.BF_LEN } data2 = bytearray(b"0123") S2 = uctypes.struct(uctypes.addressof(data2), desc2, uctypes.LITTLE_ENDIAN) # bitfield using uint8 as base type S2.bf8 = 5 print(data2) assert bytes(data2) == b"5123" # bitfield using uint32 as base type S2.bf32 = 5 print(data2) assert bytes(data2) == b"51R3" micropython-1.12/tests/extmod/uctypes_le.py.exp000066400000000000000000000002451357706137100220060ustar00rootroot000000000000000x3130 48 49 TypeError arr: 48 49 arr of struct: 48 49 IndexError bf: 48 49 bf 4bit: 3 1 3 0 bytearray(b'21') bytearray(b'2Q') bytearray(b'5123') bytearray(b'51R3') micropython-1.12/tests/extmod/uctypes_le_float.py000066400000000000000000000006351357706137100224030ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit desc = { "f32": uctypes.FLOAT32 | 0, "f64": uctypes.FLOAT64 | 0, "uf64": uctypes.FLOAT64 | 2, # unaligned } data = bytearray(10) S = uctypes.struct(uctypes.addressof(data), desc, uctypes.LITTLE_ENDIAN) S.f32 = 12.34 print('%.4f' % S.f32) S.f64 = 12.34 print('%.4f' % S.f64) S.uf64 = 12.34 print('%.4f' % S.uf64) micropython-1.12/tests/extmod/uctypes_le_float.py.exp000066400000000000000000000000301357706137100231630ustar00rootroot0000000000000012.3400 12.3400 12.3400 micropython-1.12/tests/extmod/uctypes_native_float.py000066400000000000000000000005011357706137100232610ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit desc = { "f32": uctypes.FLOAT32 | 0, "f64": uctypes.FLOAT64 | 0, } data = bytearray(8) S = uctypes.struct(uctypes.addressof(data), desc, uctypes.NATIVE) S.f32 = 12.34 print('%.4f' % S.f32) S.f64 = 12.34 print('%.4f' % S.f64) micropython-1.12/tests/extmod/uctypes_native_float.py.exp000066400000000000000000000000201357706137100240500ustar00rootroot0000000000000012.3400 12.3400 micropython-1.12/tests/extmod/uctypes_native_le.py000066400000000000000000000050021357706137100225550ustar00rootroot00000000000000# This test is exactly like uctypes_le.py, but uses native structure layout. # Codepaths for packed vs native structures are different. This test only works # on little-endian machine (no matter if 32 or 64 bit). import sys try: import uctypes except ImportError: print("SKIP") raise SystemExit if sys.byteorder != "little": print("SKIP") raise SystemExit desc = { "s0": uctypes.UINT16 | 0, "sub": (0, { "b0": uctypes.UINT8 | 0, "b1": uctypes.UINT8 | 1, }), "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}), "bitf0": uctypes.BFUINT16 | 0 | 0 << uctypes.BF_POS | 8 << uctypes.BF_LEN, "bitf1": uctypes.BFUINT16 | 0 | 8 << uctypes.BF_POS | 8 << uctypes.BF_LEN, "bf0": uctypes.BFUINT16 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "bf1": uctypes.BFUINT16 | 0 | 4 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "bf2": uctypes.BFUINT16 | 0 | 8 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "bf3": uctypes.BFUINT16 | 0 | 12 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "ptr": (uctypes.PTR | 0, uctypes.UINT8), "ptr2": (uctypes.PTR | 0, {"b": uctypes.UINT8 | 0}), } data = bytearray(b"01") S = uctypes.struct(uctypes.addressof(data), desc, uctypes.NATIVE) #print(S) print(hex(S.s0)) assert hex(S.s0) == "0x3130" #print(S.sub.b0) print(S.sub.b0, S.sub.b1) assert S.sub.b0, S.sub.b1 == (0x30, 0x31) try: S[0] assert False, "Can't index struct" except TypeError: print("TypeError") print("arr:", S.arr[0], S.arr[1]) assert (S.arr[0], S.arr[1]) == (0x30, 0x31) print("arr of struct:", S.arr2[0].b, S.arr2[1].b) assert (S.arr2[0].b, S.arr2[1].b) == (0x30, 0x31) try: S.arr[2] assert False, "Out of bounds index" except IndexError: print("IndexError") print("bf:", S.bitf0, S.bitf1) assert (S.bitf0, S.bitf1) == (0x30, 0x31) print("bf 4bit:", S.bf3, S.bf2, S.bf1, S.bf0) assert (S.bf3, S.bf2, S.bf1, S.bf0) == (3, 1, 3, 0) # Write access S.sub.b0 = ord("2") print(data) assert bytes(data) == b"21" S.bf3 = 5 print(data) assert bytes(data) == b"2Q" desc2 = { "bf8": uctypes.BFUINT8 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN, "bf32": uctypes.BFUINT32 | 0 | 20 << uctypes.BF_POS | 4 << uctypes.BF_LEN } data2 = bytearray(b"0123") S2 = uctypes.struct(uctypes.addressof(data2), desc2, uctypes.NATIVE) # bitfield using uint8 as base type S2.bf8 = 5 print(data2) assert bytes(data2) == b"5123" # bitfield using uint32 as base type S2.bf32 = 5 print(data2) assert bytes(data2) == b"51R3" micropython-1.12/tests/extmod/uctypes_native_le.py.exp000066400000000000000000000002451357706137100233540ustar00rootroot000000000000000x3130 48 49 TypeError arr: 48 49 arr of struct: 48 49 IndexError bf: 48 49 bf 4bit: 3 1 3 0 bytearray(b'21') bytearray(b'2Q') bytearray(b'5123') bytearray(b'51R3') micropython-1.12/tests/extmod/uctypes_print.py000066400000000000000000000011571357706137100217520ustar00rootroot00000000000000# test printing of uctypes objects try: import uctypes except ImportError: print("SKIP") raise SystemExit # we use an address of "0" because we just want to print something deterministic # and don't actually need to set/get any values in the struct desc = {"arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 1)} S = uctypes.struct(0, desc) print(S) desc2 = [(uctypes.ARRAY | 0, uctypes.UINT8 | 1)] S2 = uctypes.struct(0, desc2) print(S2) desc3 = ((uctypes.ARRAY | 0, uctypes.UINT8 | 1)) S3 = uctypes.struct(0, desc3) print(S3) desc4 = ((uctypes.PTR | 0, uctypes.UINT8 | 1)) S4 = uctypes.struct(0, desc4) print(S4) micropython-1.12/tests/extmod/uctypes_print.py.exp000066400000000000000000000001031357706137100225330ustar00rootroot00000000000000 micropython-1.12/tests/extmod/uctypes_ptr_le.py000066400000000000000000000015021357706137100220750ustar00rootroot00000000000000import sys try: import uctypes except ImportError: print("SKIP") raise SystemExit if sys.byteorder != "little": print("SKIP") raise SystemExit desc = { "ptr": (uctypes.PTR | 0, uctypes.UINT8), "ptr16": (uctypes.PTR | 0, uctypes.UINT16), "ptr2": (uctypes.PTR | 0, {"b": uctypes.UINT8 | 0}), } bytes = b"01" addr = uctypes.addressof(bytes) buf = addr.to_bytes(uctypes.sizeof(desc), "little") S = uctypes.struct(uctypes.addressof(buf), desc, uctypes.LITTLE_ENDIAN) print(addr == int(S.ptr)) print(addr == int(S.ptr2)) print(S.ptr[0]) assert S.ptr[0] == ord("0") print(S.ptr[1]) assert S.ptr[1] == ord("1") print(hex(S.ptr16[0])) assert hex(S.ptr16[0]) == "0x3130" print(S.ptr2[0].b, S.ptr2[1].b) print (S.ptr2[0].b, S.ptr2[1].b) print(hex(S.ptr16[0])) assert (S.ptr2[0].b, S.ptr2[1].b) == (48, 49) micropython-1.12/tests/extmod/uctypes_ptr_le.py.exp000066400000000000000000000000521357706137100226670ustar00rootroot00000000000000True True 48 49 0x3130 48 49 48 49 0x3130 micropython-1.12/tests/extmod/uctypes_ptr_native_le.py000066400000000000000000000014061357706137100234460ustar00rootroot00000000000000import sys try: import uctypes except ImportError: print("SKIP") raise SystemExit if sys.byteorder != "little": print("SKIP") raise SystemExit desc = { "ptr": (uctypes.PTR | 0, uctypes.UINT8), "ptr16": (uctypes.PTR | 0, uctypes.UINT16), "ptr2": (uctypes.PTR | 0, {"b": uctypes.UINT8 | 0}), } bytes = b"01" addr = uctypes.addressof(bytes) buf = addr.to_bytes(uctypes.sizeof(desc), "little") S = uctypes.struct(uctypes.addressof(buf), desc, uctypes.NATIVE) print(S.ptr[0]) assert S.ptr[0] == ord("0") print(S.ptr[1]) assert S.ptr[1] == ord("1") print(hex(S.ptr16[0])) assert hex(S.ptr16[0]) == "0x3130" print(S.ptr2[0].b, S.ptr2[1].b) print (S.ptr2[0].b, S.ptr2[1].b) print(hex(S.ptr16[0])) assert (S.ptr2[0].b, S.ptr2[1].b) == (48, 49) micropython-1.12/tests/extmod/uctypes_ptr_native_le.py.exp000066400000000000000000000000401357706137100242320ustar00rootroot0000000000000048 49 0x3130 48 49 48 49 0x3130 micropython-1.12/tests/extmod/uctypes_sizeof.py000066400000000000000000000023431357706137100221130ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit desc = { # arr is array at offset 0, of UINT8 elements, array size is 2 "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), # arr2 is array at offset 0, size 2, of structures defined recursively "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}), "arr3": (uctypes.ARRAY | 2, uctypes.UINT16 | 2), "arr4": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0, "w": uctypes.UINT16 | 1}), "sub": (0, { 'b1': uctypes.BFUINT8 | 0 | 4 << uctypes.BF_POS | 4 << uctypes.BF_LEN, 'b2': uctypes.BFUINT8 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN, }), } data = bytearray(b"01234567") S = uctypes.struct(uctypes.addressof(data), desc, uctypes.LITTLE_ENDIAN) print(uctypes.sizeof(S.arr)) assert uctypes.sizeof(S.arr) == 2 print(uctypes.sizeof(S.arr2)) assert uctypes.sizeof(S.arr2) == 2 print(uctypes.sizeof(S.arr3)) try: print(uctypes.sizeof(S.arr3[0])) except TypeError: print("TypeError") print(uctypes.sizeof(S.arr4)) assert uctypes.sizeof(S.arr4) == 6 print(uctypes.sizeof(S.sub)) assert uctypes.sizeof(S.sub) == 1 # invalid descriptor try: print(uctypes.sizeof([])) except TypeError: print("TypeError") micropython-1.12/tests/extmod/uctypes_sizeof.py.exp000066400000000000000000000000361357706137100227030ustar00rootroot000000000000002 2 4 TypeError 6 1 TypeError micropython-1.12/tests/extmod/uctypes_sizeof_float.py000066400000000000000000000002561357706137100233010ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit print(uctypes.sizeof({'f':uctypes.FLOAT32})) print(uctypes.sizeof({'f':uctypes.FLOAT64})) micropython-1.12/tests/extmod/uctypes_sizeof_float.py.exp000066400000000000000000000000041357706137100240630ustar00rootroot000000000000004 8 micropython-1.12/tests/extmod/uctypes_sizeof_layout.py000066400000000000000000000015031357706137100235050ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit desc = { "f1": 0 | uctypes.UINT32, "f2": 4 | uctypes.UINT8, } # uctypes.NATIVE is default print(uctypes.sizeof(desc) == uctypes.sizeof(desc, uctypes.NATIVE)) # Here we assume that that we run on a platform with convential ABI # (which rounds up structure size based on max alignment). For platforms # where that doesn't hold, this tests should be just disabled in the runner. print(uctypes.sizeof(desc, uctypes.NATIVE) > uctypes.sizeof(desc, uctypes.LITTLE_ENDIAN)) # When taking sizeof of instantiated structure, layout type param # is prohibited (because structure already has its layout type). s = uctypes.struct(0, desc, uctypes.LITTLE_ENDIAN) try: uctypes.sizeof(s, uctypes.LITTLE_ENDIAN) except TypeError: print("TypeError") micropython-1.12/tests/extmod/uctypes_sizeof_layout.py.exp000066400000000000000000000000241357706137100242750ustar00rootroot00000000000000True True TypeError micropython-1.12/tests/extmod/uctypes_sizeof_native.py000066400000000000000000000021201357706137100234520ustar00rootroot00000000000000try: import uctypes except ImportError: print("SKIP") raise SystemExit S1 = {} assert uctypes.sizeof(S1) == 0 S2 = {"a": uctypes.UINT8 | 0} assert uctypes.sizeof(S2) == 1 S3 = { "a": uctypes.UINT8 | 0, "b": uctypes.UINT8 | 1, } assert uctypes.sizeof(S3) == 2 S4 = { "a": uctypes.UINT8 | 0, "b": uctypes.UINT32 | 4, "c": uctypes.UINT8 | 8, } assert uctypes.sizeof(S4) == 12 S5 = { "a": uctypes.UINT8 | 0, "b": uctypes.UINT32 | 4, "c": uctypes.UINT8 | 8, "d": uctypes.UINT32 | 0, "sub": (4, { "b0": uctypes.UINT8 | 0, "b1": uctypes.UINT8 | 1, }), } assert uctypes.sizeof(S5) == 12 s5 = uctypes.struct(0, S5) assert uctypes.sizeof(s5) == 12 assert uctypes.sizeof(s5.sub) == 2 S6 = { "ptr": (uctypes.PTR | 0, uctypes.UINT8), } # As if there're no other arch bitnesses assert uctypes.sizeof(S6) in (4, 8) S7 = { "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 5), } assert uctypes.sizeof(S7) == 5 S8 = { "arr": (uctypes.ARRAY | 0, 3, {"a": uctypes.UINT32 | 0, "b": uctypes.UINT8 | 4}), } assert uctypes.sizeof(S8) == 24 micropython-1.12/tests/extmod/uctypes_sizeof_native.py.exp000066400000000000000000000000001357706137100242400ustar00rootroot00000000000000micropython-1.12/tests/extmod/uctypes_sizeof_od.py000066400000000000000000000024311357706137100225730ustar00rootroot00000000000000try: from ucollections import OrderedDict import uctypes except ImportError: print("SKIP") raise SystemExit desc = OrderedDict({ # arr is array at offset 0, of UINT8 elements, array size is 2 "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), # arr2 is array at offset 0, size 2, of structures defined recursively "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}), "arr3": (uctypes.ARRAY | 2, uctypes.UINT16 | 2), "arr4": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0, "w": uctypes.UINT16 | 1}), "sub": (0, { 'b1': uctypes.BFUINT8 | 0 | 4 << uctypes.BF_POS | 4 << uctypes.BF_LEN, 'b2': uctypes.BFUINT8 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN, }), }) data = bytearray(b"01234567") S = uctypes.struct(uctypes.addressof(data), desc, uctypes.LITTLE_ENDIAN) print(uctypes.sizeof(S.arr)) assert uctypes.sizeof(S.arr) == 2 print(uctypes.sizeof(S.arr2)) assert uctypes.sizeof(S.arr2) == 2 print(uctypes.sizeof(S.arr3)) try: print(uctypes.sizeof(S.arr3[0])) except TypeError: print("TypeError") print(uctypes.sizeof(S.arr4)) assert uctypes.sizeof(S.arr4) == 6 print(uctypes.sizeof(S.sub)) assert uctypes.sizeof(S.sub) == 1 # invalid descriptor try: print(uctypes.sizeof([])) except TypeError: print("TypeError") micropython-1.12/tests/extmod/uctypes_sizeof_od.py.exp000066400000000000000000000000361357706137100233650ustar00rootroot000000000000002 2 4 TypeError 6 1 TypeError micropython-1.12/tests/extmod/uhashlib_md5.py000066400000000000000000000007031357706137100214020ustar00rootroot00000000000000try: import uhashlib as hashlib except ImportError: try: import hashlib except ImportError: # This is neither uPy, nor cPy, so must be uPy with # uhashlib module disabled. print("SKIP") raise SystemExit try: hashlib.md5 except AttributeError: # MD5 is only available on some ports print("SKIP") raise SystemExit md5 = hashlib.md5(b'hello') md5.update(b'world') print(md5.digest()) micropython-1.12/tests/extmod/uhashlib_sha1.py000066400000000000000000000007111357706137100215500ustar00rootroot00000000000000try: import uhashlib as hashlib except ImportError: try: import hashlib except ImportError: # This is neither uPy, nor cPy, so must be uPy with # uhashlib module disabled. print("SKIP") raise SystemExit try: hashlib.sha1 except AttributeError: # SHA1 is only available on some ports print("SKIP") raise SystemExit sha1 = hashlib.sha1(b'hello') sha1.update(b'world') print(sha1.digest()) micropython-1.12/tests/extmod/uhashlib_sha256.py000066400000000000000000000014611357706137100217270ustar00rootroot00000000000000try: import uhashlib as hashlib except ImportError: try: import hashlib except ImportError: # This is neither uPy, nor cPy, so must be uPy with # uhashlib module disabled. print("SKIP") raise SystemExit h = hashlib.sha256() print(h.digest()) h = hashlib.sha256() h.update(b"123") print(h.digest()) h = hashlib.sha256() h.update(b"abcd" * 1000) print(h.digest()) print(hashlib.sha256(b"\xff" * 64).digest()) # 56 bytes is a boundary case in the algorithm print(hashlib.sha256(b"\xff" * 56).digest()) # TODO: running .digest() several times in row is not supported() #h = hashlib.sha256(b'123') #print(h.digest()) #print(h.digest()) # TODO: partial digests are not supported #h = hashlib.sha256(b'123') #print(h.digest()) #h.update(b'456') #print(h.digest()) micropython-1.12/tests/extmod/uheapq1.py000066400000000000000000000012031357706137100203760ustar00rootroot00000000000000try: import uheapq as heapq except: try: import heapq except ImportError: print("SKIP") raise SystemExit try: heapq.heappop([]) except IndexError: print("IndexError") try: heapq.heappush((), 1) except TypeError: print("TypeError") def pop_and_print(h): l = [] while h: l.append(str(heapq.heappop(h))) print(' '.join(l)) h = [] heapq.heappush(h, 3) heapq.heappush(h, 1) heapq.heappush(h, 2) print(h) pop_and_print(h) h = [4, 3, 8, 9, 10, 2, 7, 11, 5] heapq.heapify(h) print(h) heapq.heappush(h, 1) heapq.heappush(h, 6) heapq.heappush(h, 12) print(h) pop_and_print(h) micropython-1.12/tests/extmod/ujson_dump.py000066400000000000000000000012041357706137100212160ustar00rootroot00000000000000try: from uio import StringIO import ujson as json except: try: from io import StringIO import json except ImportError: print("SKIP") raise SystemExit s = StringIO() json.dump(False, s) print(s.getvalue()) s = StringIO() json.dump({"a": (2, [3, None])}, s) print(s.getvalue()) # dump to a small-int not allowed try: json.dump(123, 1) except (AttributeError, OSError): # CPython and uPy have different errors print('Exception') # dump to an object not allowed try: json.dump(123, {}) except (AttributeError, OSError): # CPython and uPy have different errors print('Exception') micropython-1.12/tests/extmod/ujson_dump_iobase.py000066400000000000000000000012601357706137100225420ustar00rootroot00000000000000# test ujson.dump in combination with uio.IOBase try: import uio as io import ujson as json except ImportError: try: import io, json except ImportError: print('SKIP') raise SystemExit if not hasattr(io, 'IOBase'): print('SKIP') raise SystemExit # a user stream that only has the write method class S(io.IOBase): def __init__(self): self.buf = '' def write(self, buf): if type(buf) == bytearray: # uPy passes a bytearray, CPython passes a str buf = str(buf, 'ascii') self.buf += buf return len(buf) # dump to the user stream s = S() json.dump([123, {}], s) print(s.buf) micropython-1.12/tests/extmod/ujson_dumps.py000066400000000000000000000014111357706137100214010ustar00rootroot00000000000000try: import ujson as json except ImportError: try: import json except ImportError: print("SKIP") raise SystemExit print(json.dumps(False)) print(json.dumps(True)) print(json.dumps(None)) print(json.dumps(1)) print(json.dumps('abc')) print(json.dumps('\x00\x01\x7e')) print(json.dumps([])) print(json.dumps([1])) print(json.dumps([1, 2])) print(json.dumps([1, True])) print(json.dumps(())) print(json.dumps((1,))) print(json.dumps((1, 2))) print(json.dumps((1, (2, 3)))) print(json.dumps({})) print(json.dumps({"a":1})) print(json.dumps({"a":(2,[3,None])})) print(json.dumps('"quoted"')) print(json.dumps('space\n\r\tspace')) print(json.dumps({None: -1})) print(json.dumps({False: 0})) print(json.dumps({True: 1})) print(json.dumps({1: 2})) micropython-1.12/tests/extmod/ujson_dumps_extra.py000066400000000000000000000002421357706137100226050ustar00rootroot00000000000000# test uPy ujson behaviour that's not valid in CPy try: import ujson except ImportError: print("SKIP") raise SystemExit print(ujson.dumps(b'1234')) micropython-1.12/tests/extmod/ujson_dumps_extra.py.exp000066400000000000000000000000071357706137100233770ustar00rootroot00000000000000"1234" micropython-1.12/tests/extmod/ujson_dumps_float.py000066400000000000000000000003151357706137100225700ustar00rootroot00000000000000try: import ujson as json except ImportError: try: import json except ImportError: print("SKIP") raise SystemExit print(json.dumps(1.2)) print(json.dumps({1.5: 'hi'})) micropython-1.12/tests/extmod/ujson_dumps_ordereddict.py000066400000000000000000000004351357706137100237560ustar00rootroot00000000000000try: import ujson as json from ucollections import OrderedDict except ImportError: try: import json from collections import OrderedDict except ImportError: print("SKIP") raise SystemExit print(json.dumps(OrderedDict(((1, 2), (3, 4))))) micropython-1.12/tests/extmod/ujson_load.py000066400000000000000000000005631357706137100211770ustar00rootroot00000000000000try: from uio import StringIO import ujson as json except: try: from io import StringIO import json except ImportError: print("SKIP") raise SystemExit print(json.load(StringIO('null'))) print(json.load(StringIO('"abc\\u0064e"'))) print(json.load(StringIO('[false, true, 1, -2]'))) print(json.load(StringIO('{"a":true}'))) micropython-1.12/tests/extmod/ujson_loads.py000066400000000000000000000033501357706137100213570ustar00rootroot00000000000000try: import ujson as json except ImportError: try: import json except ImportError: print("SKIP") raise SystemExit def my_print(o): if isinstance(o, dict): print('sorted dict', sorted(o.items())) else: print(o) my_print(json.loads('null')) my_print(json.loads('false')) my_print(json.loads('true')) my_print(json.loads('1')) my_print(json.loads('-2')) my_print(json.loads('"abc\\u0064e"')) my_print(json.loads('[]')) my_print(json.loads('[null]')) my_print(json.loads('[null,false,true]')) my_print(json.loads(' [ null , false , true ] ')) my_print(json.loads('{}')) my_print(json.loads('{"a":true}')) my_print(json.loads('{"a":null, "b":false, "c":true}')) my_print(json.loads('{"a":[], "b":[1], "c":{"3":4}}')) my_print(json.loads('"abc\\bdef"')) my_print(json.loads('"abc\\fdef"')) my_print(json.loads('"abc\\ndef"')) my_print(json.loads('"abc\\rdef"')) my_print(json.loads('"abc\\tdef"')) my_print(json.loads('"abc\\uabcd"')) # whitespace handling my_print(json.loads('{\n\t"a":[]\r\n, "b":[1], "c":{"3":4} \n\r\t\r\r\r\n}')) # loading nothing should raise exception try: json.loads('') except ValueError: print('ValueError') # string which is not closed try: my_print(json.loads('"abc')) except ValueError: print('ValueError') # unaccompanied closing brace try: my_print(json.loads(']')) except ValueError: print('ValueError') # unspecified object type try: my_print(json.loads('a')) except ValueError: print('ValueError') # bad property name try: my_print(json.loads('{{}:"abc"}')) except ValueError: print('ValueError') # unexpected characters after white space try: my_print(json.loads('[null] a')) except ValueError: print('ValueError') micropython-1.12/tests/extmod/ujson_loads_bytes.py000066400000000000000000000004371357706137100225700ustar00rootroot00000000000000# test loading from bytes and bytearray (introduced in Python 3.6) try: import ujson as json except ImportError: try: import json except ImportError: print("SKIP") raise SystemExit print(json.loads(b'[1,2]')) print(json.loads(bytearray(b'[null]'))) micropython-1.12/tests/extmod/ujson_loads_bytes.py.exp000066400000000000000000000000161357706137100233540ustar00rootroot00000000000000[1, 2] [None] micropython-1.12/tests/extmod/ujson_loads_float.py000066400000000000000000000005551357706137100225500ustar00rootroot00000000000000try: import ujson as json except ImportError: try: import json except ImportError: print("SKIP") raise SystemExit def my_print(o): print('%.3f' % o) my_print(json.loads('1.2')) my_print(json.loads('1e2')) my_print(json.loads('-2.3')) my_print(json.loads('-2e3')) my_print(json.loads('-2e+3')) my_print(json.loads('-2e-3')) micropython-1.12/tests/extmod/urandom_basic.py000066400000000000000000000012221357706137100216410ustar00rootroot00000000000000try: import urandom as random except ImportError: try: import random except ImportError: print("SKIP") raise SystemExit # check getrandbits returns a value within the bit range for b in (1, 2, 3, 4, 16, 32): for i in range(50): assert random.getrandbits(b) < (1 << b) # check that seed(0) gives a non-zero value random.seed(0) print(random.getrandbits(16) != 0) # check that PRNG is repeatable random.seed(1) r = random.getrandbits(16) random.seed(1) print(random.getrandbits(16) == r) # check that it throws an error for zero bits try: random.getrandbits(0) except ValueError: print('ValueError') micropython-1.12/tests/extmod/urandom_extra.py000066400000000000000000000024341357706137100217110ustar00rootroot00000000000000try: import urandom as random except ImportError: try: import random except ImportError: print("SKIP") raise SystemExit try: random.randint except AttributeError: print('SKIP') raise SystemExit print('randrange') for i in range(50): assert 0 <= random.randrange(4) < 4 assert 2 <= random.randrange(2, 6) < 6 assert -2 <= random.randrange(-2, 2) < 2 assert random.randrange(1, 9, 2) in (1, 3, 5, 7) assert random.randrange(2, 1, -1) in (1, 2) # empty range try: random.randrange(0) except ValueError: print('ValueError') # empty range try: random.randrange(2, 1) except ValueError: print('ValueError') # zero step try: random.randrange(2, 1, 0) except ValueError: print('ValueError') # empty range try: random.randrange(2, 1, 1) except ValueError: print('ValueError') print('randint') for i in range(50): assert 0 <= random.randint(0, 4) <= 4 assert 2 <= random.randint(2, 6) <= 6 assert -2 <= random.randint(-2, 2) <= 2 # empty range try: random.randint(2, 1) except ValueError: print('ValueError') print('choice') lst = [1, 2, 5, 6] for i in range(50): assert random.choice(lst) in lst # empty sequence try: random.choice([]) except IndexError: print('IndexError') micropython-1.12/tests/extmod/urandom_extra_float.py000066400000000000000000000007421357706137100230760ustar00rootroot00000000000000try: import urandom as random except ImportError: try: import random except ImportError: print("SKIP") raise SystemExit try: random.randint except AttributeError: print('SKIP') raise SystemExit print('random') for i in range(50): assert 0 <= random.random() < 1 print('uniform') for i in range(50): assert 0 <= random.uniform(0, 4) <= 4 assert 2 <= random.uniform(2, 6) <= 6 assert -2 <= random.uniform(-2, 2) <= 2 micropython-1.12/tests/extmod/ure1.py000066400000000000000000000046431357706137100177210ustar00rootroot00000000000000try: import ure as re except ImportError: try: import re except ImportError: print("SKIP") raise SystemExit r = re.compile(".+") m = r.match("abc") print(m.group(0)) try: m.group(1) except IndexError: print("IndexError") # conversion of re and match to string str(r) str(m) r = re.compile("(.+)1") m = r.match("xyz781") print(m.group(0)) print(m.group(1)) try: m.group(2) except IndexError: print("IndexError") r = re.compile("[a-cu-z]") m = r.match("a") print(m.group(0)) m = r.match("z") print(m.group(0)) m = r.match("d") print(m) m = r.match("A") print(m) print("===") r = re.compile("[^a-cu-z]") m = r.match("a") print(m) m = r.match("z") print(m) m = r.match("d") print(m.group(0)) m = r.match("A") print(m.group(0)) print("===") # '-' character within character class block print(re.match("[-a]+", "-a]d").group(0)) print(re.match("[a-]+", "-a]d").group(0)) print("===") r = re.compile("o+") m = r.search("foobar") print(m.group(0)) try: m.group(1) except IndexError: print("IndexError") m = re.match(".*", "foo") print(m.group(0)) m = re.search("w.r", "hello world") print(m.group(0)) m = re.match('a+?', 'ab'); print(m.group(0)) m = re.match('a*?', 'ab'); print(m.group(0)) m = re.match('^ab$', 'ab'); print(m.group(0)) m = re.match('a|b', 'b'); print(m.group(0)) m = re.match('a|b|c', 'c'); print(m.group(0)) # Case where anchors fail to match r = re.compile("^b|b$") m = r.search("abc") print(m) try: re.compile("*") except: print("Caught invalid regex") # bytes objects m = re.match(rb'a+?', b'ab'); print(m.group(0)) print("===") # escaping m = re.match(r'a\.c', 'a.c'); print(m.group(0) if m else '') m = re.match(r'a\.b', 'abc'); print(m is None) m = re.match(r'a\.b', 'a\\bc'); print(m is None) m = re.match(r'[a\-z]', 'abc'); print(m.group(0)) m = re.match(r'[.\]]*', '.].]a'); print(m.group(0)) m = re.match(r'[.\]+]*', '.]+.]a'); print(m.group(0)) m = re.match(r'[a-f0-9x\-yz]*', 'abxcd1-23'); print(m.group(0)) m = re.match(r'[a\\b]*', 'a\\aa\\bb\\bbab'); print(m.group(0)) m = re.search(r'[a\-z]', '-'); print(m.group(0)) m = re.search(r'[a\-z]', 'f'); print(m is None) m = re.search(r'[a\]z]', 'a'); print(m.group(0)) print(re.compile(r'[-a]').split('foo-bar')) print(re.compile(r'[a-]').split('foo-bar')) print(re.compile(r'[ax\-]').split('foo-bar')) print(re.compile(r'[a\-x]').split('foo-bar')) print(re.compile(r'[\-ax]').split('foo-bar')) print("===") micropython-1.12/tests/extmod/ure_debug.py000066400000000000000000000003051357706137100207750ustar00rootroot00000000000000# test printing debugging info when compiling try: import ure ure.DEBUG except (ImportError, AttributeError): print("SKIP") raise SystemExit ure.compile('^a|b[0-9]\w$', ure.DEBUG) micropython-1.12/tests/extmod/ure_debug.py.exp000066400000000000000000000003301357706137100215660ustar00rootroot00000000000000 0: rsplit 5 (3) 2: any 3: jmp 0 (-5) 5: save 0 7: split 14 (5) 9: assert bol 10: char a 12: jmp 23 (9) 14: char b 16: class 1 0x30-0x39 20: namedclass w 22: assert eol 23: save 1 25: match Bytes: 26, insts: 14 micropython-1.12/tests/extmod/ure_error.py000066400000000000000000000007021357706137100210410ustar00rootroot00000000000000# test errors in regex try: import ure as re except ImportError: try: import re except ImportError: print("SKIP") raise SystemExit def test_re(r): try: re.compile(r) print("OK") except: # uPy and CPy use different errors, so just ignore the type print("Error") test_re(r'?') test_re(r'*') test_re(r'+') test_re(r')') test_re(r'[') test_re(r'([') test_re(r'([)') test_re(r'[a\]') micropython-1.12/tests/extmod/ure_group.py000066400000000000000000000012211357706137100210410ustar00rootroot00000000000000# test groups, and nested groups try: import ure as re except ImportError: try: import re except ImportError: print("SKIP") raise SystemExit def print_groups(match): print('----') try: i = 0 while True: print(match.group(i)) i += 1 except IndexError: pass m = re.match(r'(([0-9]*)([a-z]*)[0-9]*)','1234hello567') print_groups(m) m = re.match(r'([0-9]*)(([a-z]*)([0-9]*))','1234hello567') print_groups(m) # optional group that matches print_groups(re.match(r'(a)?b(c)', 'abc')) # optional group that doesn't match print_groups(re.match(r'(a)?b(c)', 'bc')) micropython-1.12/tests/extmod/ure_groups.py000066400000000000000000000012121357706137100212240ustar00rootroot00000000000000# test match.groups() try: import ure as re except ImportError: try: import re except ImportError: print("SKIP") raise SystemExit try: m = re.match(".", "a") m.groups except AttributeError: print('SKIP') raise SystemExit m = re.match(r'(([0-9]*)([a-z]*)[0-9]*)','1234hello567') print(m.groups()) m = re.match(r'([0-9]*)(([a-z]*)([0-9]*))','1234hello567') print(m.groups()) # optional group that matches print(re.match(r'(a)?b(c)', 'abc').groups()) # optional group that doesn't match print(re.match(r'(a)?b(c)', 'bc').groups()) # only a single match print(re.match(r'abc', 'abc').groups()) micropython-1.12/tests/extmod/ure_namedclass.py000066400000000000000000000011511357706137100220210ustar00rootroot00000000000000# test named char classes try: import ure as re except ImportError: try: import re except ImportError: print("SKIP") raise SystemExit def print_groups(match): print('----') try: i = 0 while True: print(m.group(i)) i += 1 except IndexError: pass m = re.match(r'\w+','1234hello567 abc') print_groups(m) m = re.match(r'(\w+)\s+(\w+)','ABC \t1234hello567 abc') print_groups(m) m = re.match(r'(\S+)\s+(\D+)','ABC \thello abc567 abc') print_groups(m) m = re.match(r'(([0-9]*)([a-z]*)\d*)','1234hello567') print_groups(m) micropython-1.12/tests/extmod/ure_span.py000066400000000000000000000014271357706137100206560ustar00rootroot00000000000000# test match.span(), and nested spans try: import ure as re except ImportError: try: import re except ImportError: print("SKIP") raise SystemExit try: m = re.match(".", "a") m.span except AttributeError: print('SKIP') raise SystemExit def print_spans(match): print('----') try: i = 0 while True: print(match.span(i), match.start(i), match.end(i)) i += 1 except IndexError: pass m = re.match(r'(([0-9]*)([a-z]*)[0-9]*)','1234hello567') print_spans(m) m = re.match(r'([0-9]*)(([a-z]*)([0-9]*))','1234hello567') print_spans(m) # optional span that matches print_spans(re.match(r'(a)?b(c)', 'abc')) # optional span that doesn't match print_spans(re.match(r'(a)?b(c)', 'bc')) micropython-1.12/tests/extmod/ure_split.py000066400000000000000000000010171357706137100210430ustar00rootroot00000000000000try: import ure as re except ImportError: try: import re except ImportError: print("SKIP") raise SystemExit r = re.compile(" ") s = r.split("a b c foobar") print(s) r = re.compile(" +") s = r.split("a b c foobar") print(s) r = re.compile(" +") s = r.split("a b c foobar", 1) print(s) r = re.compile(" +") s = r.split("a b c foobar", 2) print(s) r = re.compile("[a-f]+") s = r.split("0a3b9") print(s) # bytes objects r = re.compile(b"x") s = r.split(b"fooxbar") print(s) micropython-1.12/tests/extmod/ure_split_empty.py000066400000000000000000000007551357706137100222710ustar00rootroot00000000000000# test splitting with pattern matches that can be empty # # CPython 3.5 issues a FutureWarning for these tests because their # behaviour will change in a future version. MicroPython just stops # splitting as soon as an empty match is found. try: import ure as re except ImportError: print("SKIP") raise SystemExit r = re.compile(" *") s = r.split("a b c foobar") print(s) r = re.compile("x*") s = r.split("foo") print(s) r = re.compile("x*") s = r.split("axbc") print(s) micropython-1.12/tests/extmod/ure_split_empty.py.exp000066400000000000000000000000471357706137100230560ustar00rootroot00000000000000['a b c foobar'] ['foo'] ['axbc'] micropython-1.12/tests/extmod/ure_split_notimpl.py000066400000000000000000000003161357706137100226060ustar00rootroot00000000000000try: import ure as re except ImportError: print("SKIP") raise SystemExit r = re.compile('( )') try: s = r.split("a b c foobar") except NotImplementedError: print('NotImplementedError') micropython-1.12/tests/extmod/ure_split_notimpl.py.exp000066400000000000000000000000241357706137100233750ustar00rootroot00000000000000NotImplementedError micropython-1.12/tests/extmod/ure_stack_overflow.py000066400000000000000000000003421357706137100227400ustar00rootroot00000000000000try: import ure as re except ImportError: try: import re except ImportError: print("SKIP") raise SystemExit try: re.match("(a*)*", "aaa") except RuntimeError: print("RuntimeError") micropython-1.12/tests/extmod/ure_stack_overflow.py.exp000066400000000000000000000000151357706137100235300ustar00rootroot00000000000000RuntimeError micropython-1.12/tests/extmod/ure_sub.py000066400000000000000000000023761357706137100205120ustar00rootroot00000000000000try: import ure as re except ImportError: try: import re except ImportError: print('SKIP') raise SystemExit try: re.sub except AttributeError: print('SKIP') raise SystemExit def multiply(m): return str(int(m.group(0)) * 2) print(re.sub("\d+", multiply, "10 20 30 40 50")) print(re.sub("\d+", lambda m: str(int(m.group(0)) // 2), "10 20 30 40 50")) def A(): return "A" print(re.sub('a', A(), 'aBCBABCDabcda.')) print( re.sub( r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):', 'static PyObject*\npy_\\1(void){\n return;\n}\n', '\n\ndef myfunc():\n\ndef myfunc1():\n\ndef myfunc2():' ) ) print( re.compile( '(calzino) (blu|bianco|verde) e (scarpa) (blu|bianco|verde)' ).sub( r'\g<1> colore \2 con \g<3> colore \4? ...', 'calzino blu e scarpa verde' ) ) # no matches at all print(re.sub('a', 'b', 'c')) # with maximum substitution count specified print(re.sub('a', 'b', '1a2a3a', 2)) # invalid group try: re.sub('(a)', 'b\\2', 'a') except: print('invalid group') # invalid group with very large number (to test overflow in uPy) try: re.sub('(a)', 'b\\199999999999999999999999999999999999999', 'a') except: print('invalid group') micropython-1.12/tests/extmod/ure_sub_unmatched.py000066400000000000000000000006431357706137100225350ustar00rootroot00000000000000# test re.sub with unmatched groups, behaviour changed in CPython 3.5 try: import ure as re except ImportError: try: import re except ImportError: print('SKIP') raise SystemExit try: re.sub except AttributeError: print('SKIP') raise SystemExit # first group matches, second optional group doesn't so is replaced with a blank print(re.sub(r'(a)(b)?', r'\2-\1', '1a2')) micropython-1.12/tests/extmod/ure_sub_unmatched.py.exp000066400000000000000000000000051357706137100233200ustar00rootroot000000000000001-a2 micropython-1.12/tests/extmod/uselect_poll_basic.py000066400000000000000000000017701357706137100226760ustar00rootroot00000000000000try: import usocket as socket, uselect as select, uerrno as errno except ImportError: try: import socket, select, errno select.poll # Raises AttributeError for CPython implementations without poll() except (ImportError, AttributeError): print("SKIP") raise SystemExit poller = select.poll() s = socket.socket() poller.register(s) # https://docs.python.org/3/library/select.html#select.poll.register # "Registering a file descriptor that’s already registered is not an error, # and has the same effect as registering the descriptor exactly once." poller.register(s) # 2 args are mandatory unlike register() try: poller.modify(s) except TypeError: print("modify:TypeError") poller.modify(s, select.POLLIN) poller.unregister(s) try: poller.modify(s, select.POLLIN) except OSError as e: assert e.args[0] == errno.ENOENT # poll after closing the socket, should return POLLNVAL poller.register(s) s.close() p = poller.poll(0) print(len(p), p[0][-1]) micropython-1.12/tests/extmod/ussl_basic.py000066400000000000000000000023261357706137100211700ustar00rootroot00000000000000# very basic test of ssl module, just to test the methods exist try: import uio as io import ussl as ssl except ImportError: print("SKIP") raise SystemExit # create in client mode try: ss = ssl.wrap_socket(io.BytesIO()) except OSError as er: print('wrap_socket:', repr(er)) # create in server mode (can use this object for further tests) socket = io.BytesIO() ss = ssl.wrap_socket(socket, server_side=1) # print print(repr(ss)[:12]) # setblocking() propagates call to the underlying stream object, and # io.BytesIO doesn't have setblocking() (in CPython too). #try: # ss.setblocking(False) #except NotImplementedError: # print('setblocking: NotImplementedError') #ss.setblocking(True) # write print(ss.write(b'aaaa')) # read (underlying socket has no data) print(ss.read(8)) # read (underlying socket has data, but it's bad data) socket.write(b'aaaaaaaaaaaaaaaa') socket.seek(0) try: ss.read(8) except OSError as er: print('read:', repr(er)) # close ss.close() # close 2nd time ss.close() # read on closed socket try: ss.read(10) except OSError as er: print('read:', repr(er)) # write on closed socket try: ss.write(b'aaaa') except OSError as er: print('write:', repr(er)) micropython-1.12/tests/extmod/ussl_basic.py.exp000066400000000000000000000002011357706137100217510ustar00rootroot00000000000000ssl_handshake_status: -256 wrap_socket: OSError(5,) <_SSLSocket 4 b'' read: OSError(-261,) read: OSError(9,) write: OSError(9,) micropython-1.12/tests/extmod/ussl_keycert.py000066400000000000000000000026021357706137100215520ustar00rootroot00000000000000# Test ussl with key/cert passed in try: import uio as io import ussl as ssl except ImportError: print("SKIP") raise SystemExit key = b'0\x82\x019\x02\x01\x00\x02A\x00\xf9\xe0}\xbd\xd7\x9cI\x18\x06\xc3\xcb\xb5\xec@r\xfbD\x18\x80\xaaWoZ{\xcc\xa3\xeb!"\x0fY\x9e]-\xee\xe4\t!BY\x9f{7\xf3\xf2\x8f}}\r|.\xa8<\ta\xb2\xd7W\xb3\xc9\x19A\xc39\x02\x03\x01\x00\x01\x02@\x07:\x9fh\xa6\x9c6\xe1#\x10\xf7\x0b\xc4Q\xf9\x01\x9b\xee\xb9\x8a4\r\\\xa8\xc8:\xd5\xca\x97\x99\xaa\x16\x04)\xa8\xf9\x13\xdeq\x0ev`\xa7\x83\xc5\x8b`\xdb\xef \x9d\x93\xe8g\x84\x96\xfaV\\\xf4R\xda\xd0\xa1\x02!\x00\xfeR\xbf\n\x91Su\x87L\x98{\xeb%\xed\xfb\x06u)@\xfe\x1b\xde\xa0\xc6@\xab\xc5\xedg\x8e\x10[\x02!\x00\xfb\x86=\x85\xa4\'\xde\x85\xb5L\xe0)\x99\xfaL\x8c3A\x02\xa8<\xdew\xad\x00\xe3\x1d\x05\xd8\xb4N\xfb\x02 \x08\xb0M\x04\x90hx\x88q\xcew\xd5U\xcbf\x9b\x16\xdf\x9c\xef\xd1\x85\xee\x9a7Ug\x02\xb0Z\x03\'\x02 9\xa0D\xe2$|\xf9\xefz]5\x92rs\xb5+\xfd\xe6,\x1c\xadmn\xcf\xd5?3|\x0em)\x17\x02 5Z\xcc/\xa5?\n\x04%\x9b{N\x9dX\xddI\xbe\xd2\xb0\xa0\x03BQ\x02\x82\xc2\xe0u)\xbd\xb8\xaf' # Invalid key try: ssl.wrap_socket(io.BytesIO(), key=b'!') except ValueError as er: print(repr(er)) # Valid key, no cert try: ssl.wrap_socket(io.BytesIO(), key=key) except TypeError as er: print(repr(er)) # Valid key, invalid cert try: ssl.wrap_socket(io.BytesIO(), key=key, cert=b'!') except ValueError as er: print(repr(er)) micropython-1.12/tests/extmod/ussl_keycert.py.exp000066400000000000000000000001671357706137100223510ustar00rootroot00000000000000ValueError('invalid key',) TypeError("can't convert 'NoneType' object to str implicitly",) ValueError('invalid cert',) micropython-1.12/tests/extmod/utimeq1.py000066400000000000000000000055041357706137100204270ustar00rootroot00000000000000# Test for utimeq module which implements task queue with support for # wraparound time (utime.ticks_ms() style). try: from utime import ticks_add, ticks_diff from utimeq import utimeq except ImportError: print("SKIP") raise SystemExit DEBUG = 0 MAX = ticks_add(0, -1) MODULO_HALF = MAX // 2 + 1 if DEBUG: def dprint(*v): print(*v) else: def dprint(*v): pass # Try not to crash on invalid data h = utimeq(10) try: h.push(1) assert False except TypeError: pass try: h.pop(1) assert False except IndexError: pass # unsupported unary op try: ~h assert False except TypeError: pass # pushing on full queue h = utimeq(1) h.push(1, 0, 0) try: h.push(2, 0, 0) assert False except IndexError: pass # popping into invalid type try: h.pop([]) assert False except TypeError: pass # length assert len(h) == 1 # peektime assert h.peektime() == 1 # peektime with empty queue try: utimeq(1).peektime() assert False except IndexError: pass def pop_all(h): l = [] while h: item = [0, 0, 0] h.pop(item) #print("!", item) l.append(tuple(item)) dprint(l) return l def add(h, v): h.push(v, 0, 0) dprint("-----") #h.dump() dprint("-----") h = utimeq(10) add(h, 0) add(h, MAX) add(h, MAX - 1) add(h, 101) add(h, 100) add(h, MAX - 2) dprint(h) l = pop_all(h) for i in range(len(l) - 1): diff = ticks_diff(l[i + 1][0], l[i][0]) assert diff > 0 def edge_case(edge, offset): h = utimeq(10) add(h, ticks_add(0, offset)) add(h, ticks_add(edge, offset)) dprint(h) l = pop_all(h) diff = ticks_diff(l[1][0], l[0][0]) dprint(diff, diff > 0) return diff dprint("===") diff = edge_case(MODULO_HALF - 1, 0) assert diff == MODULO_HALF - 1 assert edge_case(MODULO_HALF - 1, 100) == diff assert edge_case(MODULO_HALF - 1, -100) == diff # We expect diff to be always positive, per the definition of heappop() which should return # the smallest value. # This is the edge case where this invariant breaks, due to assymetry of two's-complement # range - there's one more negative integer than positive, so heappushing values like below # will then make ticks_diff() return the minimum negative value. We could make heappop # return them in a different order, but ticks_diff() result would be the same. Conclusion: # never add to a heap values where (a - b) == MODULO_HALF (and which are >= MODULO_HALF # ticks apart in real time of course). dprint("===") diff = edge_case(MODULO_HALF, 0) assert diff == -MODULO_HALF assert edge_case(MODULO_HALF, 100) == diff assert edge_case(MODULO_HALF, -100) == diff dprint("===") diff = edge_case(MODULO_HALF + 1, 0) assert diff == MODULO_HALF - 1 assert edge_case(MODULO_HALF + 1, 100) == diff assert edge_case(MODULO_HALF + 1, -100) == diff print("OK") micropython-1.12/tests/extmod/utimeq1.py.exp000066400000000000000000000000031357706137100212070ustar00rootroot00000000000000OK micropython-1.12/tests/extmod/utimeq_stable.py000066400000000000000000000007421357706137100216770ustar00rootroot00000000000000try: from utimeq import utimeq except ImportError: print("SKIP") raise SystemExit h = utimeq(10) # Check that for 2 same-key items, the queue is stable (pops items # in the same order they were pushed). Unfortunately, this no longer # holds for more same-key values, as the underlying heap structure # is not stable itself. h.push(100, 20, 0) h.push(100, 10, 0) res = [0, 0, 0] h.pop(res) assert res == [100, 20, 0] h.pop(res) assert res == [100, 10, 0] print("OK") micropython-1.12/tests/extmod/utimeq_stable.py.exp000066400000000000000000000000031357706137100224600ustar00rootroot00000000000000OK micropython-1.12/tests/extmod/uzlib_decompio.py000066400000000000000000000012631357706137100220440ustar00rootroot00000000000000try: import uzlib as zlib import uio as io except ImportError: print("SKIP") raise SystemExit # Raw DEFLATE bitstream buf = io.BytesIO(b'\xcbH\xcd\xc9\xc9\x07\x00') inp = zlib.DecompIO(buf, -8) print(buf.seek(0, 1)) print(inp.read(1)) print(buf.seek(0, 1)) print(inp.read(2)) print(inp.read()) print(buf.seek(0, 1)) print(inp.read(1)) print(inp.read()) print(buf.seek(0, 1)) # zlib bitstream inp = zlib.DecompIO(io.BytesIO(b'x\x9c30\xa0=\x00\x00\xb3q\x12\xc1')) print(inp.read(10)) print(inp.read()) # zlib bitstream, wrong checksum inp = zlib.DecompIO(io.BytesIO(b'x\x9c30\xa0=\x00\x00\xb3q\x12\xc0')) try: print(inp.read()) except OSError as e: print(repr(e)) micropython-1.12/tests/extmod/uzlib_decompio.py.exp000066400000000000000000000002321357706137100226320ustar00rootroot000000000000000 b'h' 2 b'el' b'lo' 7 b'' b'' 7 b'0000000000' b'000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' OSError(22,) micropython-1.12/tests/extmod/uzlib_decompio_gz.py000066400000000000000000000027701357706137100225500ustar00rootroot00000000000000try: import uzlib as zlib import uio as io except ImportError: print("SKIP") raise SystemExit # gzip bitstream buf = io.BytesIO(b'\x1f\x8b\x08\x08\x99\x0c\xe5W\x00\x03hello\x00\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x05\x00\x00\x00') inp = zlib.DecompIO(buf, 16 + 8) print(buf.seek(0, 1)) print(inp.read(1)) print(buf.seek(0, 1)) print(inp.read(2)) print(inp.read()) print(buf.seek(0, 1)) print(inp.read(1)) print(inp.read()) print(buf.seek(0, 1)) # Check FHCRC field buf = io.BytesIO(b'\x1f\x8b\x08\x02\x99\x0c\xe5W\x00\x03\x00\x00\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x05\x00\x00\x00') inp = zlib.DecompIO(buf, 16 + 8) print(inp.read()) # Check FEXTRA field buf = io.BytesIO(b'\x1f\x8b\x08\x04\x99\x0c\xe5W\x00\x03\x01\x00X\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x05\x00\x00\x00') inp = zlib.DecompIO(buf, 16 + 8) print(inp.read()) # broken header buf = io.BytesIO(b'\x1f\x8c\x08\x08\x99\x0c\xe5W\x00\x03hello\x00\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x05\x00\x00\x00') try: inp = zlib.DecompIO(buf, 16 + 8) except ValueError: print("ValueError") # broken crc32 buf = io.BytesIO(b'\x1f\x8b\x08\x08\x99\x0c\xe5W\x00\x03hello\x00\xcbH\xcd\xc9\xc9\x07\x00\x86\xa7\x106\x05\x00\x00\x00') inp = zlib.DecompIO(buf, 16 + 8) try: inp.read(6) except OSError as e: print(repr(e)) # broken uncompressed size - not checked so far #buf = io.BytesIO(b'\x1f\x8b\x08\x08\x99\x0c\xe5W\x00\x03hello\x00\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x06\x00\x00\x00') #inp = zlib.DecompIO(buf, 16 + 8) #inp.read(6) micropython-1.12/tests/extmod/uzlib_decompio_gz.py.exp000066400000000000000000000001171357706137100233340ustar00rootroot0000000000000016 b'h' 18 b'el' b'lo' 31 b'' b'' 31 b'hello' b'hello' ValueError OSError(22,) micropython-1.12/tests/extmod/uzlib_decompress.py000066400000000000000000000035741357706137100224200ustar00rootroot00000000000000try: import zlib except ImportError: try: import uzlib as zlib except ImportError: print("SKIP") raise SystemExit PATTERNS = [ # Packed results produced by CPy's zlib.compress() (b'0', b'x\x9c3\x00\x00\x001\x001'), (b'a', b'x\x9cK\x04\x00\x00b\x00b'), (b'0' * 100, b'x\x9c30\xa0=\x00\x00\xb3q\x12\xc1'), (bytes(range(64)), b'x\x9cc`dbfaec\xe7\xe0\xe4\xe2\xe6\xe1\xe5\xe3\x17\x10\x14\x12\x16\x11\x15\x13\x97\x90\x94\x92\x96\x91\x95\x93WPTRVQUS\xd7\xd0\xd4\xd2\xd6\xd1\xd5\xd370426153\xb7\xb0\xb4\xb2\xb6\xb1\xb5\xb3\x07\x00\xaa\xe0\x07\xe1'), (b'hello', b'x\x01\x01\x05\x00\xfa\xffhello\x06,\x02\x15'), # compression level 0 # adaptive/dynamic huffman tree (b'13371813150|13764518736|12345678901', b'x\x9c\x05\xc1\x81\x01\x000\x04\x04\xb1\x95\\\x1f\xcfn\x86o\x82d\x06Qq\xc8\x9d\xc5X}I}\x00\x951D>I}\x00\x951D>I}\x00\x951D>I}\x00\x951D', b'x\x9c\x05\xc11\x01\x00\x00\x00\x010\x95\x14py\x84\x12C_\x9bR\x8cV\x8a\xd1J1Z)F\x1fw`\x089'), ] for unpacked, packed in PATTERNS: assert zlib.decompress(packed) == unpacked print(unpacked) # Raw DEFLATE bitstream v = b'\xcbH\xcd\xc9\xc9\x07\x00' exp = b"hello" out = zlib.decompress(v, -15) assert(out == exp) print(exp) # Even when you ask CPython zlib.compress to produce Raw DEFLATE stream, # it returns it with adler2 and oriignal size appended, as if it was a # zlib stream. Make sure there're no random issues decompressing such. v = b'\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x05\x00\x00\x00' out = zlib.decompress(v, -15) assert(out == exp) # this should error try: zlib.decompress(b'abc') except Exception: print("Exception") # invalid block type try: zlib.decompress(b'\x07', -15) # final-block, block-type=3 (invalid) except Exception as er: print('Exception') micropython-1.12/tests/extmod/vfs_basic.py000066400000000000000000000063561357706137100210070ustar00rootroot00000000000000# test VFS functionality without any particular filesystem type try: import uos uos.mount except (ImportError, AttributeError): print("SKIP") raise SystemExit class Filesystem: def __init__(self, id): self.id = id def mount(self, readonly, mkfs): print(self.id, 'mount', readonly, mkfs) def umount(self): print(self.id, 'umount') def ilistdir(self, dir): print(self.id, 'ilistdir', dir) return iter([('a%d' % self.id, 0, 0)]) def chdir(self, dir): print(self.id, 'chdir', dir) def getcwd(self): print(self.id, 'getcwd') return 'dir%d' % self.id def mkdir(self, path): print(self.id, 'mkdir', path) def remove(self, path): print(self.id, 'remove', path) def rename(self, old_path, new_path): print(self.id, 'rename', old_path, new_path) def rmdir(self, path): print(self.id, 'rmdir', path) def stat(self, path): print(self.id, 'stat', path) return (self.id,) def statvfs(self, path): print(self.id, 'statvfs', path) return (self.id,) def open(self, file, mode): print(self.id, 'open', file, mode) # first we umount any existing mount points the target may have try: uos.umount('/') except OSError: pass for path in uos.listdir('/'): uos.umount('/' + path) # stat root dir print(uos.stat('/')) # statvfs root dir; verify that f_namemax has a sensible size print(uos.statvfs('/')[9] >= 32) # getcwd when in root dir print(uos.getcwd()) # basic mounting and listdir uos.mount(Filesystem(1), '/test_mnt') print(uos.listdir()) # ilistdir i = uos.ilistdir() print(next(i)) try: next(i) except StopIteration: print('StopIteration') try: next(i) except StopIteration: print('StopIteration') # referencing the mount point in different ways print(uos.listdir('test_mnt')) print(uos.listdir('/test_mnt')) # mounting another filesystem uos.mount(Filesystem(2), '/test_mnt2', readonly=True) print(uos.listdir()) print(uos.listdir('/test_mnt2')) # mounting over an existing mount point try: uos.mount(Filesystem(3), '/test_mnt2') except OSError: print('OSError') # mkdir of a mount point try: uos.mkdir('/test_mnt') except OSError: print('OSError') # rename across a filesystem try: uos.rename('/test_mnt/a', '/test_mnt2/b') except OSError: print('OSError') # delegating to mounted filesystem uos.chdir('test_mnt') print(uos.listdir()) print(uos.getcwd()) uos.mkdir('test_dir') uos.remove('test_file') uos.rename('test_file', 'test_file2') uos.rmdir('test_dir') print(uos.stat('test_file')) print(uos.statvfs('/test_mnt')) open('test_file') open('test_file', 'wb') # umount uos.umount('/test_mnt') uos.umount('/test_mnt2') # umount a non-existent mount point try: uos.umount('/test_mnt') except OSError: print('OSError') # root dir uos.mount(Filesystem(3), '/') print(uos.stat('/')) print(uos.statvfs('/')) print(uos.listdir()) open('test') uos.mount(Filesystem(4), '/mnt') print(uos.listdir()) print(uos.listdir('/mnt')) uos.chdir('/mnt') print(uos.listdir()) # chdir to a subdir within root-mounted vfs, and then listdir uos.chdir('/subdir') print(uos.listdir()) uos.chdir('/') uos.umount('/') print(uos.listdir('/')) uos.umount('/mnt') micropython-1.12/tests/extmod/vfs_basic.py.exp000066400000000000000000000014231357706137100215700ustar00rootroot00000000000000(16384, 0, 0, 0, 0, 0, 0, 0, 0, 0) True / 1 mount False False ['test_mnt'] ('test_mnt', 16384, 0) StopIteration StopIteration 1 ilistdir / ['a1'] 1 ilistdir / ['a1'] 2 mount True False ['test_mnt', 'test_mnt2'] 2 ilistdir / ['a2'] 3 mount False False OSError OSError OSError 1 chdir / 1 ilistdir ['a1'] 1 getcwd /test_mntdir1 1 mkdir test_dir 1 remove test_file 1 rename test_file test_file2 1 rmdir test_dir 1 stat test_file (1,) 1 statvfs / (1,) 1 open test_file r 1 open test_file wb 1 umount 2 umount OSError 3 mount False False (16384, 0, 0, 0, 0, 0, 0, 0, 0, 0) 3 statvfs / (3,) 3 ilistdir / ['a3'] 3 open test r 4 mount False False 3 ilistdir / ['mnt', 'a3'] 4 ilistdir / ['a4'] 4 chdir / 4 ilistdir ['a4'] 3 chdir /subdir 3 ilistdir ['a3'] 3 chdir / 3 umount ['mnt'] 4 umount micropython-1.12/tests/extmod/vfs_blockdev.py000066400000000000000000000030641357706137100215100ustar00rootroot00000000000000# Test for behaviour of combined standard and extended block device try: import uos uos.VfsFat uos.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit class RAMBlockDevice: ERASE_BLOCK_SIZE = 512 def __init__(self, blocks): self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) def readblocks(self, block, buf, off=0): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): buf[i] = self.data[addr + i] def writeblocks(self, block, buf, off=None): if off is None: # erase, then write off = 0 addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): self.data[addr + i] = buf[i] def ioctl(self, op, arg): if op == 4: # block count return len(self.data) // self.ERASE_BLOCK_SIZE if op == 5: # block size return self.ERASE_BLOCK_SIZE if op == 6: # erase block return 0 def test(bdev, vfs_class): print('test', vfs_class) # mkfs vfs_class.mkfs(bdev) # construction vfs = vfs_class(bdev) # statvfs print(vfs.statvfs('/')) # open, write close f = vfs.open('test', 'w') for i in range(10): f.write('some data') f.close() # ilistdir print(list(vfs.ilistdir())) # read with vfs.open('test', 'r') as f: print(f.read()) try: bdev = RAMBlockDevice(50) except MemoryError: print("SKIP") raise SystemExit test(bdev, uos.VfsFat) test(bdev, uos.VfsLfs2) micropython-1.12/tests/extmod/vfs_blockdev.py.exp000066400000000000000000000005451357706137100223040ustar00rootroot00000000000000test (512, 512, 16, 16, 16, 0, 0, 0, 0, 255) [('test', 32768, 0, 90)] some datasome datasome datasome datasome datasome datasome datasome datasome datasome data test (512, 512, 50, 48, 48, 0, 0, 0, 0, 255) [('test', 32768, 0, 90)] some datasome datasome datasome datasome datasome datasome datasome datasome datasome data micropython-1.12/tests/extmod/vfs_fat_fileio1.py000066400000000000000000000061371357706137100221050ustar00rootroot00000000000000try: import uerrno import uos except ImportError: print("SKIP") raise SystemExit try: uos.VfsFat except AttributeError: print("SKIP") raise SystemExit class RAMFS: SEC_SIZE = 512 def __init__(self, blocks): self.data = bytearray(blocks * self.SEC_SIZE) def readblocks(self, n, buf): #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) for i in range(len(buf)): buf[i] = self.data[n * self.SEC_SIZE + i] def writeblocks(self, n, buf): #print("writeblocks(%s, %x)" % (n, id(buf))) for i in range(len(buf)): self.data[n * self.SEC_SIZE + i] = buf[i] def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return len(self.data) // self.SEC_SIZE if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE try: bdev = RAMFS(50) except MemoryError: print("SKIP") raise SystemExit uos.VfsFat.mkfs(bdev) vfs = uos.VfsFat(bdev) uos.mount(vfs, '/ramdisk') uos.chdir('/ramdisk') # file IO f = open("foo_file.txt", "w") print(str(f)[:17], str(f)[-1:]) f.write("hello!") f.flush() f.close() f.close() # allowed try: f.write("world!") except OSError as e: print(e.args[0] == uerrno.EINVAL) try: f.read() except OSError as e: print(e.args[0] == uerrno.EINVAL) try: f.flush() except OSError as e: print(e.args[0] == uerrno.EINVAL) try: open("foo_file.txt", "x") except OSError as e: print(e.args[0] == uerrno.EEXIST) with open("foo_file.txt", "a") as f: f.write("world!") with open("foo_file.txt") as f2: print(f2.read()) print(f2.tell()) f2.seek(0, 0) # SEEK_SET print(f2.read(1)) f2.seek(0, 1) # SEEK_CUR print(f2.read(1)) f2.seek(2, 1) # SEEK_CUR print(f2.read(1)) f2.seek(-2, 2) # SEEK_END print(f2.read(1)) # using constructor of FileIO type to open a file # no longer working with new VFS sub-system #FileIO = type(f) #with FileIO("/ramdisk/foo_file.txt") as f: # print(f.read()) # dirs vfs.mkdir("foo_dir") try: vfs.rmdir("foo_file.txt") except OSError as e: print(e.args[0] == 20) # uerrno.ENOTDIR vfs.remove("foo_file.txt") print(list(vfs.ilistdir())) # Here we test that opening a file with the heap locked fails correctly. This # is a special case because file objects use a finaliser and allocating with a # finaliser is a different path to normal allocation. It would be better to # test this in the core tests but there are no core objects that use finaliser. import micropython micropython.heap_lock() try: vfs.open('x', 'r') except MemoryError: print('MemoryError') micropython.heap_unlock() # Here we test that the finaliser is actually called during a garbage collection. import gc N = 4 for i in range(N): n = 'x%d' % i f = vfs.open(n, 'w') f.write(n) f = None # release f without closing [0, 1, 2, 3] # use up Python stack so f is really gone gc.collect() # should finalise all N files by closing them for i in range(N): with vfs.open('x%d' % i, 'r') as f: print(f.read()) micropython-1.12/tests/extmod/vfs_fat_fileio1.py.exp000066400000000000000000000001701357706137100226670ustar00rootroot00000000000000 True True True True hello!world! 12 h e o d True [('foo_dir', 16384, 0, 0)] MemoryError x0 x1 x2 x3 micropython-1.12/tests/extmod/vfs_fat_fileio2.py000066400000000000000000000050771357706137100221100ustar00rootroot00000000000000try: import uerrno import uos except ImportError: print("SKIP") raise SystemExit try: uos.VfsFat except AttributeError: print("SKIP") raise SystemExit class RAMFS: SEC_SIZE = 512 def __init__(self, blocks): self.data = bytearray(blocks * self.SEC_SIZE) def readblocks(self, n, buf): #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) for i in range(len(buf)): buf[i] = self.data[n * self.SEC_SIZE + i] def writeblocks(self, n, buf): #print("writeblocks(%s, %x)" % (n, id(buf))) for i in range(len(buf)): self.data[n * self.SEC_SIZE + i] = buf[i] def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return len(self.data) // self.SEC_SIZE if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE try: bdev = RAMFS(50) except MemoryError: print("SKIP") raise SystemExit uos.VfsFat.mkfs(bdev) vfs = uos.VfsFat(bdev) uos.mount(vfs, '/ramdisk') uos.chdir('/ramdisk') try: vfs.mkdir("foo_dir") except OSError as e: print(e.args[0] == uerrno.EEXIST) try: vfs.remove("foo_dir") except OSError as e: print(e.args[0] == uerrno.EISDIR) try: vfs.remove("no_file.txt") except OSError as e: print(e.args[0] == uerrno.ENOENT) try: vfs.rename("foo_dir", "/null/file") except OSError as e: print(e.args[0] == uerrno.ENOENT) # file in dir with open("foo_dir/file-in-dir.txt", "w+t") as f: f.write("data in file") with open("foo_dir/file-in-dir.txt", "r+b") as f: print(f.read()) with open("foo_dir/sub_file.txt", "w") as f: f.write("subdir file") # directory not empty try: vfs.rmdir("foo_dir") except OSError as e: print(e.args[0] == uerrno.EACCES) # trim full path vfs.rename("foo_dir/file-in-dir.txt", "foo_dir/file.txt") print(list(vfs.ilistdir("foo_dir"))) vfs.rename("foo_dir/file.txt", "moved-to-root.txt") print(list(vfs.ilistdir())) # check that renaming to existing file will overwrite it with open("temp", "w") as f: f.write("new text") vfs.rename("temp", "moved-to-root.txt") print(list(vfs.ilistdir())) with open("moved-to-root.txt") as f: print(f.read()) # valid removes vfs.remove("foo_dir/sub_file.txt") vfs.rmdir("foo_dir") print(list(vfs.ilistdir())) # disk full try: bsize = vfs.statvfs("/ramdisk")[0] free = vfs.statvfs("/ramdisk")[2] + 1 f = open("large_file.txt", "wb") f.write(bytearray(bsize * free)) except OSError as e: print("ENOSPC:", e.args[0] == 28) # uerrno.ENOSPC micropython-1.12/tests/extmod/vfs_fat_fileio2.py.exp000066400000000000000000000004331357706137100226720ustar00rootroot00000000000000True True True b'data in file' True [('sub_file.txt', 32768, 0, 11), ('file.txt', 32768, 0, 12)] [('foo_dir', 16384, 0, 0), ('moved-to-root.txt', 32768, 0, 12)] [('foo_dir', 16384, 0, 0), ('moved-to-root.txt', 32768, 0, 8)] new text [('moved-to-root.txt', 32768, 0, 8)] ENOSPC: True micropython-1.12/tests/extmod/vfs_fat_more.py000066400000000000000000000050221357706137100215070ustar00rootroot00000000000000try: import uos except ImportError: print("SKIP") raise SystemExit try: uos.VfsFat except AttributeError: print("SKIP") raise SystemExit class RAMFS: SEC_SIZE = 512 def __init__(self, blocks): self.data = bytearray(blocks * self.SEC_SIZE) def readblocks(self, n, buf): #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) for i in range(len(buf)): buf[i] = self.data[n * self.SEC_SIZE + i] def writeblocks(self, n, buf): #print("writeblocks(%s, %x)" % (n, id(buf))) for i in range(len(buf)): self.data[n * self.SEC_SIZE + i] = buf[i] def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return len(self.data) // self.SEC_SIZE if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE try: bdev = RAMFS(50) bdev2 = RAMFS(50) except MemoryError: print("SKIP") raise SystemExit # first we umount any existing mount points the target may have try: uos.umount('/') except OSError: pass for path in uos.listdir('/'): uos.umount('/' + path) uos.VfsFat.mkfs(bdev) uos.mount(bdev, '/') print(uos.getcwd()) f = open('test.txt', 'w') f.write('hello') f.close() print(uos.listdir()) print(uos.listdir('/')) print(uos.stat('')[:-3]) print(uos.stat('/')[:-3]) print(uos.stat('test.txt')[:-3]) print(uos.stat('/test.txt')[:-3]) f = open('/test.txt') print(f.read()) f.close() uos.rename('test.txt', 'test2.txt') print(uos.listdir()) uos.rename('test2.txt', '/test3.txt') print(uos.listdir()) uos.rename('/test3.txt', 'test4.txt') print(uos.listdir()) uos.rename('/test4.txt', '/test5.txt') print(uos.listdir()) uos.mkdir('dir') print(uos.listdir()) uos.mkdir('/dir2') print(uos.listdir()) uos.mkdir('dir/subdir') print(uos.listdir('dir')) for exist in ('', '/', 'dir', '/dir', 'dir/subdir'): try: uos.mkdir(exist) except OSError as er: print('mkdir OSError', er.args[0] == 17) # EEXIST uos.chdir('/') print(uos.stat('test5.txt')[:-3]) uos.VfsFat.mkfs(bdev2) uos.mount(bdev2, '/sys') print(uos.listdir()) print(uos.listdir('sys')) print(uos.listdir('/sys')) uos.rmdir('dir2') uos.remove('test5.txt') print(uos.listdir()) uos.umount('/') print(uos.getcwd()) print(uos.listdir()) print(uos.listdir('sys')) # test importing a file from a mounted FS import sys sys.path.clear() sys.path.append('/sys') with open('sys/test_module.py', 'w') as f: f.write('print("test_module!")') import test_module micropython-1.12/tests/extmod/vfs_fat_more.py.exp000066400000000000000000000007131357706137100223040ustar00rootroot00000000000000/ ['test.txt'] ['test.txt'] (16384, 0, 0, 0, 0, 0, 0) (16384, 0, 0, 0, 0, 0, 0) (32768, 0, 0, 0, 0, 0, 5) (32768, 0, 0, 0, 0, 0, 5) hello ['test2.txt'] ['test3.txt'] ['test4.txt'] ['test5.txt'] ['test5.txt', 'dir'] ['test5.txt', 'dir', 'dir2'] ['subdir'] mkdir OSError True mkdir OSError True mkdir OSError True mkdir OSError True mkdir OSError True (32768, 0, 0, 0, 0, 0, 5) ['sys', 'test5.txt', 'dir', 'dir2'] [] [] ['sys', 'dir'] / ['sys'] [] test_module! micropython-1.12/tests/extmod/vfs_fat_oldproto.py000066400000000000000000000021731357706137100224130ustar00rootroot00000000000000try: import uerrno import uos except ImportError: print("SKIP") raise SystemExit try: uos.VfsFat except AttributeError: print("SKIP") raise SystemExit class RAMFS_OLD: SEC_SIZE = 512 def __init__(self, blocks): self.data = bytearray(blocks * self.SEC_SIZE) def readblocks(self, n, buf): #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) for i in range(len(buf)): buf[i] = self.data[n * self.SEC_SIZE + i] def writeblocks(self, n, buf): #print("writeblocks(%s, %x)" % (n, id(buf))) for i in range(len(buf)): self.data[n * self.SEC_SIZE + i] = buf[i] def sync(self): pass def count(self): return len(self.data) // self.SEC_SIZE try: bdev = RAMFS_OLD(50) except MemoryError: print("SKIP") raise SystemExit uos.VfsFat.mkfs(bdev) vfs = uos.VfsFat(bdev) uos.mount(vfs, "/ramdisk") # file io with vfs.open("file.txt", "w") as f: f.write("hello!") print(list(vfs.ilistdir())) with vfs.open("file.txt", "r") as f: print(f.read()) vfs.remove("file.txt") print(list(vfs.ilistdir())) micropython-1.12/tests/extmod/vfs_fat_oldproto.py.exp000066400000000000000000000000461357706137100232030ustar00rootroot00000000000000[('file.txt', 32768, 0, 6)] hello! [] micropython-1.12/tests/extmod/vfs_fat_ramdisk.py000066400000000000000000000041301357706137100221760ustar00rootroot00000000000000try: import uerrno import uos except ImportError: print("SKIP") raise SystemExit try: uos.VfsFat except AttributeError: print("SKIP") raise SystemExit class RAMFS: SEC_SIZE = 512 def __init__(self, blocks): self.data = bytearray(blocks * self.SEC_SIZE) def readblocks(self, n, buf): #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) for i in range(len(buf)): buf[i] = self.data[n * self.SEC_SIZE + i] def writeblocks(self, n, buf): #print("writeblocks(%s, %x)" % (n, id(buf))) for i in range(len(buf)): self.data[n * self.SEC_SIZE + i] = buf[i] def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return len(self.data) // self.SEC_SIZE if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE try: bdev = RAMFS(50) except MemoryError: print("SKIP") raise SystemExit uos.VfsFat.mkfs(bdev) print(b"FOO_FILETXT" not in bdev.data) print(b"hello!" not in bdev.data) vfs = uos.VfsFat(bdev) uos.mount(vfs, "/ramdisk") print("statvfs:", vfs.statvfs("/ramdisk")) print("getcwd:", vfs.getcwd()) try: vfs.stat("no_file.txt") except OSError as e: print(e.args[0] == uerrno.ENOENT) with vfs.open("foo_file.txt", "w") as f: f.write("hello!") print(list(vfs.ilistdir())) print("stat root:", vfs.stat("/")) print("stat file:", vfs.stat("foo_file.txt")[:-3]) # timestamps differ across runs print(b"FOO_FILETXT" in bdev.data) print(b"hello!" in bdev.data) vfs.mkdir("foo_dir") vfs.chdir("foo_dir") print("getcwd:", vfs.getcwd()) print(list(vfs.ilistdir())) with vfs.open("sub_file.txt", "w") as f: f.write("subdir file") try: vfs.chdir("sub_file.txt") except OSError as e: print(e.args[0] == uerrno.ENOENT) vfs.chdir("..") print("getcwd:", vfs.getcwd()) uos.umount(vfs) vfs = uos.VfsFat(bdev) print(list(vfs.ilistdir(b""))) # list a non-existent directory try: vfs.ilistdir(b"no_exist") except OSError as e: print('ENOENT:', e.args[0] == uerrno.ENOENT) micropython-1.12/tests/extmod/vfs_fat_ramdisk.py.exp000066400000000000000000000004631357706137100227760ustar00rootroot00000000000000True True statvfs: (512, 512, 16, 16, 16, 0, 0, 0, 0, 255) getcwd: / True [('foo_file.txt', 32768, 0, 6)] stat root: (16384, 0, 0, 0, 0, 0, 0, 0, 0, 0) stat file: (32768, 0, 0, 0, 0, 0, 6) True True getcwd: /foo_dir [] True getcwd: / [(b'foo_file.txt', 32768, 0, 6), (b'foo_dir', 16384, 0, 0)] ENOENT: True micropython-1.12/tests/extmod/vfs_fat_ramdisklarge.py000066400000000000000000000031731357706137100232170ustar00rootroot00000000000000# test making a FAT filesystem on a very large block device try: import uos except ImportError: print("SKIP") raise SystemExit try: uos.VfsFat except AttributeError: print("SKIP") raise SystemExit class RAMBDevSparse: SEC_SIZE = 512 def __init__(self, blocks): self.blocks = blocks self.data = {} def readblocks(self, n, buf): #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) assert len(buf) == self.SEC_SIZE if n not in self.data: self.data[n] = bytearray(self.SEC_SIZE) buf[:] = self.data[n] def writeblocks(self, n, buf): #print("writeblocks(%s, %x)" % (n, id(buf))) mv = memoryview(buf) for off in range(0, len(buf), self.SEC_SIZE): s = n + off // self.SEC_SIZE if s not in self.data: self.data[s] = bytearray(self.SEC_SIZE) self.data[s][:] = mv[off:off + self.SEC_SIZE] def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return self.blocks if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE try: bdev = RAMBDevSparse(4 * 1024 * 1024 * 1024 // RAMBDevSparse.SEC_SIZE) uos.VfsFat.mkfs(bdev) except MemoryError: print("SKIP") raise SystemExit vfs = uos.VfsFat(bdev) uos.mount(vfs, "/ramdisk") print("statvfs:", vfs.statvfs("/ramdisk")) f = open('/ramdisk/test.txt', 'w') f.write('test file') f.close() print("statvfs:", vfs.statvfs("/ramdisk")) f = open('/ramdisk/test.txt') print(f.read()) f.close() uos.umount(vfs) micropython-1.12/tests/extmod/vfs_fat_ramdisklarge.py.exp000066400000000000000000000002141357706137100240030ustar00rootroot00000000000000statvfs: (32768, 32768, 131054, 131053, 131053, 0, 0, 0, 0, 255) statvfs: (32768, 32768, 131054, 131052, 131052, 0, 0, 0, 0, 255) test file micropython-1.12/tests/extmod/vfs_lfs.py000066400000000000000000000046561357706137100205130ustar00rootroot00000000000000# Test for VfsLittle using a RAM device try: import uos uos.VfsLfs1 uos.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit class RAMBlockDevice: ERASE_BLOCK_SIZE = 1024 def __init__(self, blocks): self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) def readblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): buf[i] = self.data[addr + i] def writeblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): self.data[addr + i] = buf[i] def ioctl(self, op, arg): if op == 4: # block count return len(self.data) // self.ERASE_BLOCK_SIZE if op == 5: # block size return self.ERASE_BLOCK_SIZE if op == 6: # erase block return 0 def test(bdev, vfs_class): print('test', vfs_class) # mkfs vfs_class.mkfs(bdev) # construction vfs = vfs_class(bdev) # statvfs print(vfs.statvfs('/')) # open, write close f = vfs.open('test', 'w') f.write('littlefs') f.close() # statvfs after creating a file print(vfs.statvfs('/')) # ilistdir print(list(vfs.ilistdir())) print(list(vfs.ilistdir('/'))) print(list(vfs.ilistdir(b'/'))) # mkdir, rmdir vfs.mkdir('testdir') print(list(vfs.ilistdir())) print(list(vfs.ilistdir('testdir'))) vfs.rmdir('testdir') print(list(vfs.ilistdir())) vfs.mkdir('testdir') # stat a file print(vfs.stat('test')) # stat a dir (size seems to vary on LFS2 so don't print that) print(vfs.stat('testdir')[:6]) # read with vfs.open('test', 'r') as f: print(f.read()) # create large file with vfs.open('testbig', 'w') as f: data = 'large012' * 32 * 16 print('data length:', len(data)) for i in range(4): print('write', i) f.write(data) # stat after creating large file print(vfs.statvfs('/')) # rename vfs.rename('testbig', 'testbig2') print(list(vfs.ilistdir())) # remove vfs.remove('testbig2') print(list(vfs.ilistdir())) # getcwd, chdir print(vfs.getcwd()) vfs.chdir('/testdir') print(vfs.getcwd()) vfs.chdir('/') print(vfs.getcwd()) vfs.rmdir('testdir') bdev = RAMBlockDevice(30) test(bdev, uos.VfsLfs1) test(bdev, uos.VfsLfs2) micropython-1.12/tests/extmod/vfs_lfs.py.exp000066400000000000000000000021341357706137100212730ustar00rootroot00000000000000test (1024, 1024, 30, 26, 26, 0, 0, 0, 0, 255) (1024, 1024, 30, 25, 25, 0, 0, 0, 0, 255) [('test', 32768, 0, 8)] [('test', 32768, 0, 8)] [(b'test', 32768, 0, 8)] [('test', 32768, 0, 8), ('testdir', 16384, 0, 0)] [] [('test', 32768, 0, 8)] (32768, 0, 0, 0, 0, 0, 8, 0, 0, 0) (16384, 0, 0, 0, 0, 0) littlefs data length: 4096 write 0 write 1 write 2 write 3 (1024, 1024, 30, 6, 6, 0, 0, 0, 0, 255) [('test', 32768, 0, 8), ('testdir', 16384, 0, 0), ('testbig2', 32768, 0, 16384)] [('test', 32768, 0, 8), ('testdir', 16384, 0, 0)] / /testdir / test (1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255) (1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255) [('test', 32768, 0, 8)] [('test', 32768, 0, 8)] [(b'test', 32768, 0, 8)] [('testdir', 16384, 0, 0), ('test', 32768, 0, 8)] [] [('test', 32768, 0, 8)] (32768, 0, 0, 0, 0, 0, 8, 0, 0, 0) (16384, 0, 0, 0, 0, 0) littlefs data length: 4096 write 0 write 1 write 2 write 3 (1024, 1024, 30, 9, 9, 0, 0, 0, 0, 255) [('testbig2', 32768, 0, 16384), ('testdir', 16384, 0, 0), ('test', 32768, 0, 8)] [('testdir', 16384, 0, 0), ('test', 32768, 0, 8)] / /testdir / micropython-1.12/tests/extmod/vfs_lfs_corrupt.py000066400000000000000000000047731357706137100222710ustar00rootroot00000000000000# Test for VfsLittle using a RAM device, testing error handling from corrupt block device try: import uos uos.VfsLfs1 uos.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit class RAMBlockDevice: ERASE_BLOCK_SIZE = 1024 def __init__(self, blocks): self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) self.ret = 0 def readblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): buf[i] = self.data[addr + i] return self.ret def writeblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): self.data[addr + i] = buf[i] return self.ret def ioctl(self, op, arg): if op == 4: # block count return len(self.data) // self.ERASE_BLOCK_SIZE if op == 5: # block size return self.ERASE_BLOCK_SIZE if op == 6: # erase block return 0 def corrupt(bdev, block): addr = block * bdev.ERASE_BLOCK_SIZE for i in range(bdev.ERASE_BLOCK_SIZE): bdev.data[addr + i] = i & 0xff def create_vfs(bdev, vfs_class): bdev.ret = 0 vfs_class.mkfs(bdev) vfs = vfs_class(bdev) with vfs.open('f', 'w') as f: for i in range(100): f.write('test') return vfs def test(bdev, vfs_class): print('test', vfs_class) # statvfs vfs = create_vfs(bdev, vfs_class) corrupt(bdev, 0) corrupt(bdev, 1) try: print(vfs.statvfs('')) except OSError: print('statvfs OSError') # error during read vfs = create_vfs(bdev, vfs_class) f = vfs.open('f', 'r') bdev.ret = -5 # EIO try: f.read(10) except OSError: print('read OSError') # error during write vfs = create_vfs(bdev, vfs_class) f = vfs.open('f', 'a') bdev.ret = -5 # EIO try: f.write('test') except OSError: print('write OSError') # error during close vfs = create_vfs(bdev, vfs_class) f = vfs.open('f', 'w') f.write('test') bdev.ret = -5 # EIO try: f.close() except OSError: print('close OSError') # error during flush vfs = create_vfs(bdev, vfs_class) f = vfs.open('f', 'w') f.write('test') bdev.ret = -5 # EIO try: f.flush() except OSError: print('flush OSError') bdev.ret = 0 f.close() bdev = RAMBlockDevice(30) test(bdev, uos.VfsLfs1) test(bdev, uos.VfsLfs2) micropython-1.12/tests/extmod/vfs_lfs_corrupt.py.exp000066400000000000000000000002741357706137100230540ustar00rootroot00000000000000test statvfs OSError read OSError write OSError close OSError flush OSError test statvfs OSError read OSError write OSError close OSError flush OSError micropython-1.12/tests/extmod/vfs_lfs_error.py000066400000000000000000000051661357706137100217210ustar00rootroot00000000000000# Test for VfsLittle using a RAM device, testing error handling try: import uos uos.VfsLfs1 uos.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit class RAMBlockDevice: ERASE_BLOCK_SIZE = 1024 def __init__(self, blocks): self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) def readblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): buf[i] = self.data[addr + i] def writeblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): self.data[addr + i] = buf[i] def ioctl(self, op, arg): if op == 4: # block count return len(self.data) // self.ERASE_BLOCK_SIZE if op == 5: # block size return self.ERASE_BLOCK_SIZE if op == 6: # erase block return 0 def test(bdev, vfs_class): print('test', vfs_class) # mkfs with too-small block device try: vfs_class.mkfs(RAMBlockDevice(1)) except OSError: print('mkfs OSError') # mount with invalid filesystem try: vfs_class(bdev) except OSError: print('mount OSError') # set up for following tests vfs_class.mkfs(bdev) vfs = vfs_class(bdev) with vfs.open('testfile', 'w') as f: f.write('test') vfs.mkdir('testdir') # ilistdir try: vfs.ilistdir('noexist') except OSError: print('ilistdir OSError') # remove try: vfs.remove('noexist') except OSError: print('remove OSError') # rmdir try: vfs.rmdir('noexist') except OSError: print('rmdir OSError') # rename try: vfs.rename('noexist', 'somethingelse') except OSError: print('rename OSError') # mkdir try: vfs.mkdir('testdir') except OSError: print('mkdir OSError') # chdir to nonexistent try: vfs.chdir('noexist') except OSError: print('chdir OSError') print(vfs.getcwd()) # check still at root # chdir to file try: vfs.chdir('testfile') except OSError: print('chdir OSError') print(vfs.getcwd()) # check still at root # stat try: vfs.stat('noexist') except OSError: print('stat OSError') # error during seek with vfs.open('testfile', 'r') as f: f.seek(1 << 30) # SEEK_SET try: f.seek(1 << 30, 1) # SEEK_CUR except OSError: print('seek OSError') bdev = RAMBlockDevice(30) test(bdev, uos.VfsLfs1) test(bdev, uos.VfsLfs2) micropython-1.12/tests/extmod/vfs_lfs_error.py.exp000066400000000000000000000005561357706137100225120ustar00rootroot00000000000000test mkfs OSError mount OSError ilistdir OSError remove OSError rmdir OSError rename OSError mkdir OSError chdir OSError / chdir OSError / stat OSError seek OSError test mkfs OSError mount OSError ilistdir OSError remove OSError rmdir OSError rename OSError mkdir OSError chdir OSError / chdir OSError / stat OSError seek OSError micropython-1.12/tests/extmod/vfs_lfs_file.py000066400000000000000000000050731357706137100215040ustar00rootroot00000000000000# Test for VfsLittle using a RAM device, file IO try: import uos uos.VfsLfs1 uos.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit class RAMBlockDevice: ERASE_BLOCK_SIZE = 1024 def __init__(self, blocks): self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) def readblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): buf[i] = self.data[addr + i] def writeblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): self.data[addr + i] = buf[i] def ioctl(self, op, arg): if op == 4: # block count return len(self.data) // self.ERASE_BLOCK_SIZE if op == 5: # block size return self.ERASE_BLOCK_SIZE if op == 6: # erase block return 0 def test(bdev, vfs_class): print('test', vfs_class) # mkfs vfs_class.mkfs(bdev) # construction vfs = vfs_class(bdev) # create text, print, write, close f = vfs.open('test.txt', 'wt') print(f) f.write('littlefs') f.close() # close already-closed file f.close() # create binary, print, write, flush, close f = vfs.open('test.bin', 'wb') print(f) f.write('littlefs') f.flush() f.close() # create for append f = vfs.open('test.bin', 'ab') f.write('more') f.close() # create exclusive f = vfs.open('test2.bin', 'xb') f.close() # create exclusive with error try: vfs.open('test2.bin', 'x') except OSError: print('open OSError') # read default with vfs.open('test.txt', '') as f: print(f.read()) # read text with vfs.open('test.txt', 'rt') as f: print(f.read()) # read binary with vfs.open('test.bin', 'rb') as f: print(f.read()) # create read and write with vfs.open('test.bin', 'r+b') as f: print(f.read(8)) f.write('MORE') with vfs.open('test.bin', 'rb') as f: print(f.read()) # seek and tell f = vfs.open('test.txt', 'r') print(f.tell()) f.seek(3, 0) print(f.tell()) f.close() # open nonexistent try: vfs.open('noexist', 'r') except OSError: print('open OSError') # open multiple files at the same time f1 = vfs.open('test.txt', '') f2 = vfs.open('test.bin', 'b') print(f1.read()) print(f2.read()) f1.close() f2.close() bdev = RAMBlockDevice(30) test(bdev, uos.VfsLfs1) test(bdev, uos.VfsLfs2) micropython-1.12/tests/extmod/vfs_lfs_file.py.exp000066400000000000000000000005261357706137100222750ustar00rootroot00000000000000test open OSError littlefs littlefs b'littlefsmore' b'littlefs' b'littlefsMORE' 0 3 open OSError littlefs b'littlefsMORE' test open OSError littlefs littlefs b'littlefsmore' b'littlefs' b'littlefsMORE' 0 3 open OSError littlefs b'littlefsMORE' micropython-1.12/tests/extmod/vfs_lfs_mount.py000066400000000000000000000031461357706137100217260ustar00rootroot00000000000000# Test for VfsLittle using a RAM device, with mount/umount try: import uos uos.VfsLfs1 uos.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit class RAMBlockDevice: ERASE_BLOCK_SIZE = 1024 def __init__(self, blocks): self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) def readblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): buf[i] = self.data[addr + i] def writeblocks(self, block, buf, off): addr = block * self.ERASE_BLOCK_SIZE + off for i in range(len(buf)): self.data[addr + i] = buf[i] def ioctl(self, op, arg): if op == 4: # block count return len(self.data) // self.ERASE_BLOCK_SIZE if op == 5: # block size return self.ERASE_BLOCK_SIZE if op == 6: # erase block return 0 def test(bdev, vfs_class): print('test', vfs_class) # mkfs vfs_class.mkfs(bdev) # construction vfs = vfs_class(bdev) # mount uos.mount(vfs, '/lfs') # import with open('/lfs/lfsmod.py', 'w') as f: f.write('print("hello from lfs")\n') import lfsmod # import package uos.mkdir('/lfs/lfspkg') with open('/lfs/lfspkg/__init__.py', 'w') as f: f.write('print("package")\n') import lfspkg # umount uos.umount('/lfs') # clear imported modules sys.modules.clear() bdev = RAMBlockDevice(30) # initialise path import sys sys.path.clear() sys.path.append('/lfs') # run tests test(bdev, uos.VfsLfs1) test(bdev, uos.VfsLfs2) micropython-1.12/tests/extmod/vfs_lfs_mount.py.exp000066400000000000000000000001341357706137100225130ustar00rootroot00000000000000test hello from lfs package test hello from lfs package micropython-1.12/tests/extmod/vfs_userfs.py000066400000000000000000000030771357706137100212320ustar00rootroot00000000000000# test VFS functionality with a user-defined filesystem # also tests parts of uio.IOBase implementation import sys try: import uio uio.IOBase import uos uos.mount except (ImportError, AttributeError): print("SKIP") raise SystemExit class UserFile(uio.IOBase): def __init__(self, data): self.data = data self.pos = 0 def read(self): return self.data def readinto(self, buf): n = 0 while n < len(buf) and self.pos < len(self.data): buf[n] = self.data[self.pos] n += 1 self.pos += 1 return n def ioctl(self, req, arg): print('ioctl', req, arg) return 0 class UserFS: def __init__(self, files): self.files = files def mount(self, readonly, mksfs): pass def umount(self): pass def stat(self, path): print('stat', path) if path in self.files: return (32768, 0, 0, 0, 0, 0, 0, 0, 0, 0) raise OSError def open(self, path, mode): print('open', path, mode) return UserFile(self.files[path]) # create and mount a user filesystem user_files = { '/data.txt': b"some data in a text file\n", '/usermod1.py': b"print('in usermod1')\nimport usermod2", '/usermod2.py': b"print('in usermod2')", } uos.mount(UserFS(user_files), '/userfs') # open and read a file f = open('/userfs/data.txt') print(f.read()) # import files from the user filesystem sys.path.append('/userfs') import usermod1 # unmount and undo path addition uos.umount('/userfs') sys.path.pop() micropython-1.12/tests/extmod/vfs_userfs.py.exp000066400000000000000000000003051357706137100220140ustar00rootroot00000000000000open /data.txt r b'some data in a text file\n' stat /usermod1 stat /usermod1.py open /usermod1.py r ioctl 4 0 in usermod1 stat /usermod2 stat /usermod2.py open /usermod2.py r ioctl 4 0 in usermod2 micropython-1.12/tests/extmod/websocket_basic.py000066400000000000000000000026441357706137100221730ustar00rootroot00000000000000try: import uio import uerrno import uwebsocket except ImportError: print("SKIP") raise SystemExit # put raw data in the stream and do a websocket read def ws_read(msg, sz): ws = uwebsocket.websocket(uio.BytesIO(msg)) return ws.read(sz) # do a websocket write and then return the raw data from the stream def ws_write(msg, sz): s = uio.BytesIO() ws = uwebsocket.websocket(s) ws.write(msg) s.seek(0) return s.read(sz) # basic frame print(ws_read(b"\x81\x04ping", 4)) print(ws_read(b"\x80\x04ping", 4)) # FRAME_CONT print(ws_write(b"pong", 6)) # split frames are not supported # print(ws_read(b"\x01\x04ping", 4)) # extended payloads print(ws_read(b'\x81~\x00\x80' + b'ping' * 32, 128)) print(ws_write(b"pong" * 32, 132)) # mask (returned data will be 'mask' ^ 'mask') print(ws_read(b"\x81\x84maskmask", 4)) # close control frame s = uio.BytesIO(b'\x88\x00') # FRAME_CLOSE ws = uwebsocket.websocket(s) print(ws.read(1)) s.seek(2) print(s.read(4)) # misc control frames print(ws_read(b"\x89\x00\x81\x04ping", 4)) # FRAME_PING print(ws_read(b"\x8a\x00\x81\x04pong", 4)) # FRAME_PONG # close method ws = uwebsocket.websocket(uio.BytesIO()) ws.close() # ioctl ws = uwebsocket.websocket(uio.BytesIO()) print(ws.ioctl(8)) # GET_DATA_OPTS print(ws.ioctl(9, 2)) # SET_DATA_OPTS print(ws.ioctl(9)) try: ws.ioctl(-1) except OSError as e: print("ioctl: EINVAL:", e.args[0] == uerrno.EINVAL) micropython-1.12/tests/extmod/websocket_basic.py.exp000066400000000000000000000006131357706137100227600ustar00rootroot00000000000000b'ping' b'ping' b'\x81\x04pong' b'pingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingping' b'\x81~\x00\x80pongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpong' b'\x00\x00\x00\x00' b'' b'\x81\x02\x88\x00' b'ping' b'pong' 0 1 2 ioctl: EINVAL: True micropython-1.12/tests/feature_check/000077500000000000000000000000001357706137100177545ustar00rootroot00000000000000micropython-1.12/tests/feature_check/README000066400000000000000000000004221357706137100206320ustar00rootroot00000000000000This directory doesn't contain real tests, but code snippets to detect various interpreter features, which can't be/inconvenient to detecte by other means. Scripts here are executed by run-tests at the beginning of testsuite to decide what other test groups to run/exclude. micropython-1.12/tests/feature_check/async_check.py000066400000000000000000000001131357706137100225730ustar00rootroot00000000000000# check if async/await keywords are supported async def foo(): await 1 micropython-1.12/tests/feature_check/async_check.py.exp000066400000000000000000000000001357706137100233610ustar00rootroot00000000000000micropython-1.12/tests/feature_check/bytearray.py000066400000000000000000000001141357706137100223240ustar00rootroot00000000000000try: bytearray print("bytearray") except NameError: print("no") micropython-1.12/tests/feature_check/bytearray.py.exp000066400000000000000000000000001357706137100231110ustar00rootroot00000000000000micropython-1.12/tests/feature_check/byteorder.py000066400000000000000000000000401357706137100223170ustar00rootroot00000000000000import sys print(sys.byteorder) micropython-1.12/tests/feature_check/byteorder.py.exp000066400000000000000000000000001357706137100231060ustar00rootroot00000000000000micropython-1.12/tests/feature_check/complex.py000066400000000000000000000001111357706137100217660ustar00rootroot00000000000000try: complex print("complex") except NameError: print("no") micropython-1.12/tests/feature_check/complex.py.exp000066400000000000000000000000001357706137100225560ustar00rootroot00000000000000micropython-1.12/tests/feature_check/const.py000066400000000000000000000000151357706137100214500ustar00rootroot00000000000000x = const(1) micropython-1.12/tests/feature_check/const.py.exp000066400000000000000000000000001357706137100222350ustar00rootroot00000000000000micropython-1.12/tests/feature_check/coverage.py000066400000000000000000000001201357706137100221120ustar00rootroot00000000000000try: extra_coverage print('coverage') except NameError: print('no') micropython-1.12/tests/feature_check/coverage.py.exp000066400000000000000000000000001357706137100227020ustar00rootroot00000000000000micropython-1.12/tests/feature_check/float.py000066400000000000000000000004231357706137100214320ustar00rootroot00000000000000# detect how many bits of precision the floating point implementation has try: float except NameError: print(0) else: if float('1.0000001') == float('1.0'): print(30) elif float('1e300') == float('inf'): print(32) else: print(64) micropython-1.12/tests/feature_check/float.py.exp000066400000000000000000000000031357706137100222170ustar00rootroot0000000000000064 micropython-1.12/tests/feature_check/int_big.py000066400000000000000000000001671357706137100217450ustar00rootroot00000000000000# Check whether arbitrary-precision integers (MPZ) are supported print(1000000000000000000000000000000000000000000000) micropython-1.12/tests/feature_check/int_big.py.exp000066400000000000000000000000571357706137100225360ustar00rootroot000000000000001000000000000000000000000000000000000000000000 micropython-1.12/tests/feature_check/native_check.py000066400000000000000000000001311357706137100227440ustar00rootroot00000000000000# this test for the availability of native emitter @micropython.native def f(): pass micropython-1.12/tests/feature_check/native_check.py.exp000066400000000000000000000000001357706137100235320ustar00rootroot00000000000000micropython-1.12/tests/feature_check/repl_emacs_check.py000066400000000000000000000000601357706137100235710ustar00rootroot00000000000000# Check for emacs keys in REPL t = +11 t == 2 micropython-1.12/tests/feature_check/repl_emacs_check.py.exp000066400000000000000000000001471357706137100243720ustar00rootroot00000000000000MicroPython \.\+ version Use \.\+ >>> # Check for emacs keys in REPL >>> t = \.\+ >>> t == 2 True >>> micropython-1.12/tests/feature_check/reverse_ops.py000066400000000000000000000001651357706137100226640ustar00rootroot00000000000000class Foo: def __radd__(self, other): pass try: 5 + Foo() except TypeError: print("TypeError") micropython-1.12/tests/feature_check/reverse_ops.py.exp000066400000000000000000000000001357706137100234430ustar00rootroot00000000000000micropython-1.12/tests/feature_check/set_check.py000066400000000000000000000000571357706137100222600ustar00rootroot00000000000000# check if set literal syntax is supported {1} micropython-1.12/tests/feature_check/set_check.py.exp000066400000000000000000000000001357706137100230370ustar00rootroot00000000000000micropython-1.12/tests/feature_check/slice.py000066400000000000000000000001041357706137100214200ustar00rootroot00000000000000try: slice print("slice") except NameError: print("no") micropython-1.12/tests/feature_check/slice.py.exp000066400000000000000000000000001357706137100222060ustar00rootroot00000000000000micropython-1.12/tests/feature_check/uio_module.py000066400000000000000000000001111357706137100224600ustar00rootroot00000000000000try: import uio print("uio") except ImportError: print("no") micropython-1.12/tests/feature_check/uio_module.py.exp000066400000000000000000000000001357706137100232500ustar00rootroot00000000000000micropython-1.12/tests/float/000077500000000000000000000000001357706137100162715ustar00rootroot00000000000000micropython-1.12/tests/float/array_construct.py000066400000000000000000000004541357706137100220700ustar00rootroot00000000000000# test construction of array from array with float type try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit print(array('f', array('h', [1, 2]))) print(array('d', array('f', [1, 2]))) micropython-1.12/tests/float/builtin_float_abs.py000066400000000000000000000002751357706137100223270ustar00rootroot00000000000000# test builtin abs function with float args for val in ( '1.0', '-1.0', '0.0', '-0.0', 'nan', '-nan', 'inf', '-inf', ): print(val, abs(float(val))) micropython-1.12/tests/float/builtin_float_hash.py000066400000000000000000000006521357706137100225040ustar00rootroot00000000000000# test builtin hash function with float args # these should hash to an integer with a specific value for val in ( '0.0', '-0.0', '1.0', '2.0', '-12.0', '12345.0', ): print(val, hash(float(val))) # just check that these values are hashable for val in ( '0.1', '-0.1', '10.3', '0.4e3', '1e16', 'inf', '-inf', 'nan', ): print(val, type(hash(float(val)))) micropython-1.12/tests/float/builtin_float_minmax.py000066400000000000000000000011121357706137100230420ustar00rootroot00000000000000# test builtin min and max functions with float args try: min max except: print("SKIP") raise SystemExit print(min(0, 1.0)) print(min(1.0, 0)) print(min(0, -1.0)) print(min(-1.0, 0)) print(max(0, 1.0)) print(max(1.0, 0)) print(max(0, -1.0)) print(max(-1.0, 0)) print(min(1.5, -1.5)) print(min(-1.5, 1.5)) print(max(1.5, -1.5)) print(max(-1.5, 1.5)) print(min([1, 2.9, 4, 0, -1, 2])) print(max([1, 2.9, 4, 0, -1, 2])) print(min([1, 2.9, 4, 6.5, -1, 2])) print(max([1, 2.9, 4, 6.5, -1, 2])) print(min([1, 2.9, 4, -6.5, -1, 2])) print(max([1, 2.9, 4, -6.5, -1, 2])) micropython-1.12/tests/float/builtin_float_pow.py000066400000000000000000000003571357706137100223700ustar00rootroot00000000000000# test builtin pow function with float args print(pow(0.0, 0.0)) print(pow(0, 1.0)) print(pow(1.0, 1)) print(pow(2.0, 3.0)) print(pow(2.0, -4.0)) print(pow(0.0, float('inf'))) print(pow(0.0, float('-inf'))) print(pow(0.0, float('nan'))) micropython-1.12/tests/float/builtin_float_round.py000066400000000000000000000010121357706137100226770ustar00rootroot00000000000000# test round() with floats # check basic cases tests = [ [0.0], [1.0], [0.1], [-0.1], [123.4], [123.6], [-123.4], [-123.6], [1.234567, 5], [1.23456, 1], [1.23456, 0], [1234.56, -2] ] for t in tests: print(round(*t)) # check .5 cases for i in range(11): print(round((i - 5) / 2)) # test second arg for i in range(-1, 3): print(round(1.47, i)) # test inf and nan for val in (float('inf'), float('nan')): try: round(val) except (ValueError, OverflowError) as e: print(type(e)) micropython-1.12/tests/float/builtin_float_round_intbig.py000066400000000000000000000001541357706137100242410ustar00rootroot00000000000000# test round() with floats that return large integers for x in (-1e25, 1e25): print('%.3g' % round(x)) micropython-1.12/tests/float/bytearray_construct.py000066400000000000000000000004131357706137100227470ustar00rootroot00000000000000# test construction of bytearray from array with float type try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit print(bytearray(array('f', [1, 2.3]))) micropython-1.12/tests/float/bytes_construct.py000066400000000000000000000004071357706137100220760ustar00rootroot00000000000000# test construction of bytearray from array with float type try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit print(bytes(array('f', [1, 2.3]))) micropython-1.12/tests/float/cmath_fun.py000066400000000000000000000031561357706137100206140ustar00rootroot00000000000000# test the functions imported from cmath try: from cmath import * except ImportError: print("SKIP") raise SystemExit # make sure these constants exist in cmath print("%.5g" % e) print("%.5g" % pi) test_values_non_zero = [] base_values = (0.0, 0.5, 1.2345, 10.) for r in base_values: for i in base_values: if r != 0. or i != 0.: test_values_non_zero.append(complex(r, i)) if r != 0.: test_values_non_zero.append(complex(-r, i)) if i != 0.: test_values_non_zero.append(complex(r, -i)) if r != 0. and i != 0.: test_values_non_zero.append(complex(-r, -i)) test_values = [complex(0., 0.),] + test_values_non_zero print(test_values) functions = [ ('phase', phase, test_values), ('polar', polar, test_values), ('rect', rect, ((0, 0), (0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (-1, 1), (1, -1), (123., -456.))), ('exp', exp, test_values), ('log', log, test_values_non_zero), ('sqrt', sqrt, test_values), ('cos', cos, test_values), ('sin', sin, test_values), ] for f_name, f, test_vals in functions: print(f_name) for val in test_vals: if type(val) == tuple: ret = f(*val) else: ret = f(val) if type(ret) == float: print("%.5g" % ret) elif type(ret) == tuple: print("%.5g %.5g" % ret) else: # some test (eg cmath.sqrt(-0.5)) disagree with CPython with tiny real part real = ret.real if abs(real) < 1e-6: real = 0. print("complex(%.5g, %.5g)" % (real, ret.imag)) micropython-1.12/tests/float/cmath_fun_special.py000066400000000000000000000014731357706137100223140ustar00rootroot00000000000000# test the special functions imported from cmath try: from cmath import * log10 except (ImportError, NameError): print("SKIP") raise SystemExit test_values_non_zero = [] base_values = (0.0, 0.5, 1.2345, 10.) for r in base_values: for i in base_values: if r != 0. or i != 0.: test_values_non_zero.append(complex(r, i)) if r != 0.: test_values_non_zero.append(complex(-r, i)) if i != 0.: test_values_non_zero.append(complex(r, -i)) if r != 0. and i != 0.: test_values_non_zero.append(complex(-r, -i)) functions = [ ('log10', log10, test_values_non_zero), ] for f_name, f, test_vals in functions: print(f_name) for val in test_vals: ret = f(val) print("complex(%.5g, %.5g)" % (ret.real, ret.imag)) micropython-1.12/tests/float/complex1.py000066400000000000000000000042671357706137100204040ustar00rootroot00000000000000# test basic complex number functionality # constructor print(complex(1)) print(complex(1.2)) print(complex(1.2j)) print(complex("1")) print(complex("1.2")) print(complex("1.2j")) print(complex(1, 2)) print(complex(1j, 2j)) # unary ops print(bool(1j)) print(+(1j)) print(-(1 + 2j)) # binary ops print(1j + False) print(1j + True) print(1j + 2) print(1j + 2j) print(1j - 2) print(1j - 2j) print(1j * 2) print(1j * 2j) print(1j / 2) print((1j / 2j).real) print(1j / (1 + 2j)) ans = 0j ** 0; print("%.5g %.5g" % (ans.real, ans.imag)) ans = 0j ** 1; print("%.5g %.5g" % (ans.real, ans.imag)) ans = 0j ** 0j; print("%.5g %.5g" % (ans.real, ans.imag)) ans = 1j ** 2.5; print("%.5g %.5g" % (ans.real, ans.imag)) ans = 1j ** 2.5j; print("%.5g %.5g" % (ans.real, ans.imag)) # comparison print(1j == 1) print(1j == 1j) # comparison of nan is special nan = float('nan') * 1j print(nan == 1j) print(nan == nan) # builtin abs print(abs(1j)) print("%.5g" % abs(1j + 2)) # builtin hash print(hash(1 + 0j)) print(type(hash(1j))) # float on lhs should delegate to complex print(1.2 + 3j) # negative base and fractional power should create a complex ans = (-1) ** 2.3; print("%.5g %.5g" % (ans.real, ans.imag)) ans = (-1.2) ** -3.4; print("%.5g %.5g" % (ans.real, ans.imag)) # check printing of inf/nan print(float('nan') * 1j) print(float('-nan') * 1j) print(float('inf') * (1 + 1j)) print(float('-inf') * (1 + 1j)) # can't assign to attributes try: (1j).imag = 0 except AttributeError: print('AttributeError') # can't convert rhs to complex try: 1j + [] except TypeError: print("TypeError") # unsupported unary op try: ~(1j) except TypeError: print("TypeError") # unsupported binary op try: 1j // 2 except TypeError: print("TypeError") # unsupported binary op try: 1j < 2j except TypeError: print("TypeError") #small int on LHS, complex on RHS, unsupported op try: print(1 | 1j) except TypeError: print('TypeError') # zero division try: 1j / 0 except ZeroDivisionError: print("ZeroDivisionError") # zero division via power try: 0j ** -1 except ZeroDivisionError: print("ZeroDivisionError") try: 0j ** 1j except ZeroDivisionError: print("ZeroDivisionError") micropython-1.12/tests/float/complex1_intbig.py000066400000000000000000000002161357706137100217260ustar00rootroot00000000000000# test basic complex number functionality # convert bignum to complex on rhs ans = 1j + (1 << 70); print("%.5g %.5g" % (ans.real, ans.imag)) micropython-1.12/tests/float/float1.py000066400000000000000000000041201357706137100200260ustar00rootroot00000000000000# test basic float capabilities # literals print(.12) print(1.) print(1.2) print(0e0) print(0e+0) print(0e-0) # float construction print(float(1.2)) print(float("1.2")) print(float("+1")) print(float("1e1")) print(float("1e+1")) print(float("1e-1")) print(float("inf")) print(float("-inf")) print(float("INF")) print(float("infinity")) print(float("INFINITY")) print(float("nan")) print(float("-nan")) print(float("NaN")) try: float("") except ValueError: print("ValueError") try: float("1e+") except ValueError: print("ValueError") try: float("1z") except ValueError: print("ValueError") # construct from something with the buffer protocol print(float(b"1.2")) print(float(bytearray(b"3.4"))) # unary operators print(bool(0.0)) print(bool(1.2)) print(+(1.2)) print(-(1.2)) # division of integers x = 1 / 2 print(x) # /= operator a = 1 a /= 2 print(a) # floor division print(1.0 // 2) print(2.0 // 2) # comparison print(1.2 <= 3.4) print(1.2 <= -3.4) print(1.2 >= 3.4) print(1.2 >= -3.4) # comparison of nan is special nan = float('nan') print(nan == 1.2) print(nan == nan) try: 1.0 / 0 except ZeroDivisionError: print("ZeroDivisionError") try: 1.0 // 0 except ZeroDivisionError: print("ZeroDivisionError") try: 1.2 % 0 except ZeroDivisionError: print("ZeroDivisionError") try: 0.0 ** -1 except ZeroDivisionError: print("ZeroDivisionError") # unsupported unary ops try: ~1.2 except TypeError: print("TypeError") try: 1.2 in 3.4 except TypeError: print("TypeError") # small int on LHS, float on RHS, unsupported op try: print(1 | 1.0) except TypeError: print('TypeError') # can't convert list to float try: float([]) except TypeError: print("TypeError") # test constant float with more than 255 chars x = 1.84728699436059052516398251149631771898472869943605905251639825114963177189847286994360590525163982511496317718984728699436059052516398251149631771898472869943605905251639825114963177189847286994360590525163982511496317718984728699436059052516398251149631771898472869943605905251639825114963177189 print("%.5f" % x) micropython-1.12/tests/float/float2int_doubleprec_intbig.py000066400000000000000000000052661357706137100243160ustar00rootroot00000000000000# check cases converting float to int, requiring double precision float try: import ustruct as struct except: import struct import sys maxsize_bits = 0 maxsize = sys.maxsize while maxsize: maxsize >>= 1 maxsize_bits += 1 # work out configuration values is_64bit = maxsize_bits > 32 # 0 = none, 1 = long long, 2 = mpz ll_type = None if is_64bit: if maxsize_bits < 63: ll_type = 0 else: if maxsize_bits < 31: ll_type = 0 if ll_type is None: one = 1 if one << 65 < one << 62: ll_type = 1 else: ll_type = 2 # This case occurs with time.time() values if ll_type != 0: print(int(1418774543.)) print("%d" % 1418774543.) if ll_type == 3: print(int(2.**100)) print("%d" % 2.**100) else: print(int(1073741823.)) print("%d" % 1073741823.) testpass = True p2_rng = ((30,63,1024),(62,63,1024))[is_64bit][ll_type] for i in range(0,p2_rng): bitcnt = len(bin(int(2.**i))) - 3; if i != bitcnt: print('fail: 2**%u was %u bits long' % (i, bitcnt)); testpass = False print("power of 2 test: %s" % (testpass and 'passed' or 'failed')) testpass = True p10_rng = ((9,18,23),(18,18,23))[is_64bit][ll_type] for i in range(0,p10_rng): digcnt = len(str(int(10.**i))) - 1; if i != digcnt: print('fail: 10**%u was %u digits long' % (i, digcnt)); testpass = False print("power of 10 test: %s" % (testpass and 'passed' or 'failed')) def fp2int_test(num, name, should_fail): try: x = int(num) passed = ~should_fail except: passed = should_fail print('%s: %s' % (name, passed and 'passed' or 'failed')) if ll_type != 2: if ll_type == 0: if is_64bit: neg_bad_fp = -1.00000005*2.**62. pos_bad_fp = 2.**62. neg_good_fp = -2.**62. pos_good_fp = 0.99999993*2.**62. else: neg_bad_fp = -1.00000005*2.**30. pos_bad_fp = 2.**30. neg_good_fp = -2.**30. pos_good_fp = 0.9999999499*2.**30. else: neg_bad_fp = -0.51*2.**64. pos_bad_fp = 2.**63. neg_good_fp = -2.**63. pos_good_fp = 1.9999998*2.**62. fp2int_test(neg_bad_fp, 'neg bad', True) fp2int_test(pos_bad_fp, 'pos bad', True) fp2int_test(neg_good_fp, 'neg good', False) fp2int_test(pos_good_fp, 'pos good', False) else: fp2int_test(-1.9999999999999981*2.**1023., 'large neg', False) fp2int_test(1.9999999999999981*2.**1023., 'large pos', False) fp2int_test(float('inf'), 'inf test', True) fp2int_test(float('nan'), 'NaN test', True) # test numbers < 1 (this used to fail; see issue #1044) fp2int_test(0.0001, 'small num', False) struct.pack('I', int(1/2)) micropython-1.12/tests/float/float2int_fp30_intbig.py000066400000000000000000000051051357706137100227320ustar00rootroot00000000000000# check cases converting float to int, relying only on single precision float try: import ustruct as struct except: import struct import sys maxsize_bits = 0 maxsize = sys.maxsize while maxsize: maxsize >>= 1 maxsize_bits += 1 # work out configuration values is_64bit = maxsize_bits > 32 # 0 = none, 1 = long long, 2 = mpz ll_type = None if is_64bit: if maxsize_bits < 63: ll_type = 0 else: if maxsize_bits < 31: ll_type = 0 if ll_type is None: one = 1 if one << 65 < one << 62: ll_type = 1 else: ll_type = 2 # basic conversion print(int(14187744.)) print("%d" % 14187744.) if ll_type == 2: print(int(2.**100)) print("%d" % 2.**100) testpass = True p2_rng = ((30,63,127),(62,63,127))[is_64bit][ll_type] for i in range(0,p2_rng): bitcnt = len(bin(int(2.**i))) - 3; if i != bitcnt: print('fail: 2.**%u was %u bits long' % (i, bitcnt)); testpass = False print("power of 2 test: %s" % (testpass and 'passed' or 'failed')) # TODO why does 10**12 fail this test for single precision float? testpass = True p10_rng = 9 for i in range(0,p10_rng): digcnt = len(str(int(10.**i))) - 1; if i != digcnt: print('fail: 10.**%u was %u digits long' % (i, digcnt)); testpass = False print("power of 10 test: %s" % (testpass and 'passed' or 'failed')) def fp2int_test(num, name, should_fail): try: x = int(num) passed = ~should_fail except: passed = should_fail print('%s: %s' % (name, passed and 'passed' or 'failed')) if ll_type != 2: if ll_type == 0: if is_64bit: neg_bad_fp = -1.00000005*2.**62. pos_bad_fp = 2.**62. neg_good_fp = -2.**62. pos_good_fp = 0.99999993*2.**62. else: neg_bad_fp = -1.00000005*2.**30. pos_bad_fp = 2.**30. neg_good_fp = -2.**30. pos_good_fp = 0.9999999499*2.**30. else: neg_bad_fp = -0.51*2.**64. pos_bad_fp = 2.**63. neg_good_fp = -2.**63. pos_good_fp = 1.9999998*2.**62. fp2int_test(neg_bad_fp, 'neg bad', True) fp2int_test(pos_bad_fp, 'pos bad', True) fp2int_test(neg_good_fp, 'neg good', False) fp2int_test(pos_good_fp, 'pos good', False) else: fp2int_test(-1.999999879*2.**126., 'large neg', False) fp2int_test(1.999999879*2.**126., 'large pos', False) fp2int_test(float('inf'), 'inf test', True) fp2int_test(float('nan'), 'NaN test', True) # test numbers < 1 (this used to fail; see issue #1044) fp2int_test(0.0001, 'small num', False) struct.pack('I', int(1/2)) micropython-1.12/tests/float/float2int_intbig.py000066400000000000000000000051571357706137100221110ustar00rootroot00000000000000# check cases converting float to int, relying only on single precision float try: import ustruct as struct except: import struct import sys maxsize_bits = 0 maxsize = sys.maxsize while maxsize: maxsize >>= 1 maxsize_bits += 1 # work out configuration values is_64bit = maxsize_bits > 32 # 0 = none, 1 = long long, 2 = mpz ll_type = None if is_64bit: if maxsize_bits < 63: ll_type = 0 else: if maxsize_bits < 31: ll_type = 0 if ll_type is None: one = 1 if one << 65 < one << 62: ll_type = 1 else: ll_type = 2 # basic conversion print(int(14187745.)) print("%d" % 14187745.) if ll_type == 2: print(int(2.**100)) print("%d" % 2.**100) testpass = True p2_rng = ((30,63,127),(62,63,127))[is_64bit][ll_type] for i in range(0,p2_rng): bitcnt = len(bin(int(2.**i))) - 3; if i != bitcnt: print('fail: 2.**%u was %u bits long' % (i, bitcnt)); testpass = False print("power of 2 test: %s" % (testpass and 'passed' or 'failed')) # TODO why does 10**12 fail this test for single precision float? testpass = True p10_rng = 9 if (ll_type == 0 and ~is_64bit) else 11 for i in range(0,p10_rng): digcnt = len(str(int(10.**i))) - 1; if i != digcnt: print('fail: 10.**%u was %u digits long' % (i, digcnt)); testpass = False print("power of 10 test: %s" % (testpass and 'passed' or 'failed')) def fp2int_test(num, name, should_fail): try: x = int(num) passed = ~should_fail except: passed = should_fail print('%s: %s' % (name, passed and 'passed' or 'failed')) if ll_type != 2: if ll_type == 0: if is_64bit: neg_bad_fp = -1.00000005*2.**62. pos_bad_fp = 2.**62. neg_good_fp = -2.**62. pos_good_fp = 0.99999993*2.**62. else: neg_bad_fp = -1.00000005*2.**30. pos_bad_fp = 2.**30. neg_good_fp = -2.**30. pos_good_fp = 0.9999999499*2.**30. else: neg_bad_fp = -0.51*2.**64. pos_bad_fp = 2.**63. neg_good_fp = -2.**63. pos_good_fp = 1.9999998*2.**62. fp2int_test(neg_bad_fp, 'neg bad', True) fp2int_test(pos_bad_fp, 'pos bad', True) fp2int_test(neg_good_fp, 'neg good', False) fp2int_test(pos_good_fp, 'pos good', False) else: fp2int_test(-1.999999879*2.**127., 'large neg', False) fp2int_test(1.999999879*2.**127., 'large pos', False) fp2int_test(float('inf'), 'inf test', True) fp2int_test(float('nan'), 'NaN test', True) # test numbers < 1 (this used to fail; see issue #1044) fp2int_test(0.0001, 'small num', False) struct.pack('I', int(1/2)) micropython-1.12/tests/float/float_array.py000066400000000000000000000007151357706137100211510ustar00rootroot00000000000000try: from uarray import array except ImportError: try: from array import array except ImportError: print("SKIP") raise SystemExit def test(a): print(a) a.append(1.2) print(len(a), '%.3f' % a[0]) a.append(1) a.append(False) print(len(a), '%.3f %.3f' % (a[1], a[2])) a[-1] = 3.45 print('%.3f' % a[-1]) test(array('f')) test(array('d')) print('{:.4f}'.format(array('f', b'\xcc\xcc\xcc=')[0])) micropython-1.12/tests/float/float_compare.py000066400000000000000000000004401357706137100214540ustar00rootroot00000000000000# Extended float comparisons class Foo: pass foo = Foo() print(foo == 1.0) print(1.0 == foo) print(1.0 == Foo) print(1.0 == []) print(1.0 == {}) try: print(foo < 1.0) except TypeError: print("TypeError") try: print(1.0 < foo) except TypeError: print("TypeError") micropython-1.12/tests/float/float_divmod.py000066400000000000000000000010121357706137100213040ustar00rootroot00000000000000# test floating point floor divide and modulus # it has some tricky corner cases def test(x, y): div, mod = divmod(x, y) print('%.8f %.8f %.8f %.8f' % (x // y, x % y, div, mod)) print(div == x // y, mod == x % y, abs(div * y + mod - x) < 1e-15) test(1.23456, 0.7) test(-1.23456, 0.7) test(1.23456, -0.7) test(-1.23456, -0.7) a = 1.23456 b = 0.7 test(a, b) test(a, -b) test(-a, b) test(-a, -b) for i in range(25): x = (i - 12.5) / 6 for j in range(25): y = (j - 12.5) / 6 test(x, y) micropython-1.12/tests/float/float_divmod_relaxed.py000066400000000000000000000013011357706137100230110ustar00rootroot00000000000000# test floating point floor divide and modulus # it has some tricky corner cases # pyboard has 32-bit floating point and gives different (but still # correct) answers for certain combinations of divmod arguments. def test(x, y): div, mod = divmod(x, y) print(div == x // y, mod == x % y, abs(div * y + mod - x) < 1e-6) test(1.23456, 0.7) test(-1.23456, 0.7) test(1.23456, -0.7) test(-1.23456, -0.7) a = 1.23456 b = 0.7 test(a, b) test(a, -b) test(-a, b) test(-a, -b) for i in range(25): x = (i - 12.5) / 6 for j in range(25): y = (j - 12.5) / 6 test(x, y) # test division by zero error try: divmod(1.0, 0) except ZeroDivisionError: print('ZeroDivisionError') micropython-1.12/tests/float/float_format.py000066400000000000000000000011371357706137100213220ustar00rootroot00000000000000# test float formatting # general rounding for val in (116, 1111, 1234, 5010, 11111): print('%.0f' % val) print('%.1f' % val) print('%.3f' % val) # make sure rounding is done at the correct precision for prec in range(8): print(('%%.%df' % prec) % 6e-5) # check certain cases that had a digit value of 10 render as a ":" character print('%.2e' % float('9' * 51 + 'e-39')) print('%.2e' % float('9' * 40 + 'e-21')) # check a case that would render negative digit values, eg ")" characters # the string is converted back to a float to check for no illegal characters float('%.23e' % 1e-80) micropython-1.12/tests/float/float_parse.py000066400000000000000000000023141357706137100211420ustar00rootroot00000000000000# test parsing of floats inf = float('inf') # it shouldn't matter where the decimal point is if the exponent balances the value print(float('1234') - float('0.1234e4')) print(float('1.015625') - float('1015625e-6')) # very large integer part with a very negative exponent should cancel out print('%.4e' % float('9' * 60 + 'e-60')) print('%.4e' % float('9' * 60 + 'e-40')) # many fractional digits print(float('.' + '9' * 70)) print(float('.' + '9' * 70 + 'e20')) print(float('.' + '9' * 70 + 'e-50') == float('1e-50')) # tiny fraction with large exponent print(float('.' + '0' * 60 + '1e10') == float('1e-51')) print(float('.' + '0' * 60 + '9e25') == float('9e-36')) print(float('.' + '0' * 60 + '9e40') == float('9e-21')) # ensure that accuracy is retained when value is close to a subnormal print(float('1.00000000000000000000e-37')) print(float('10.0000000000000000000e-38')) print(float('100.000000000000000000e-39')) # very large exponent literal print(float('1e4294967301')) print(float('1e-4294967301')) print(float('1e18446744073709551621')) print(float('1e-18446744073709551621')) # check small decimals are as close to their true value as possible for n in range(1, 10): print(float('0.%u' % n) == n / 10) micropython-1.12/tests/float/float_parse_doubleprec.py000066400000000000000000000013631357706137100233510ustar00rootroot00000000000000# test parsing of floats, requiring double-precision # very large integer part with a very negative exponent should cancel out print(float('9' * 400 + 'e-100')) print(float('9' * 400 + 'e-200')) print(float('9' * 400 + 'e-400')) # many fractional digits print(float('.' + '9' * 400)) print(float('.' + '9' * 400 + 'e100')) print(float('.' + '9' * 400 + 'e-100')) # tiny fraction with large exponent print('%.14e' % float('.' + '0' * 400 + '9e100')) print('%.14e' % float('.' + '0' * 400 + '9e200')) print('%.14e' % float('.' + '0' * 400 + '9e400')) # ensure that accuracy is retained when value is close to a subnormal print(float('1.00000000000000000000e-307')) print(float('10.0000000000000000000e-308')) print(float('100.000000000000000000e-309')) micropython-1.12/tests/float/float_struct.py000066400000000000000000000007601357706137100213570ustar00rootroot00000000000000# test struct package with floats try: try: import ustruct as struct except: import struct except ImportError: print("SKIP") raise SystemExit i = 1. + 1/2 # TODO: it looks like '=' format modifier is not yet supported # for fmt in ('f', 'd', '>f', '>d', 'f', '>d', '' + fmt.format(*args) + '<') test("{:10.4}", 123.456) test("{:10.4e}", 123.456) test("{:10.4e}", -123.456) test("{:10.4f}", 123.456) test("{:10.4f}", -123.456) test("{:10.4g}", 123.456) test("{:10.4g}", -123.456) test("{:10.4n}", 123.456) test("{:e}", 100) test("{:f}", 200) test("{:g}", 300) test("{:10.4E}", 123.456) test("{:10.4E}", -123.456) test("{:10.4F}", 123.456) test("{:10.4F}", -123.456) test("{:10.4G}", 123.456) test("{:10.4G}", -123.456) test("{:06e}", float("inf")) test("{:06e}", float("-inf")) test("{:06e}", float("nan")) # The following fails right now #test("{:10.1}", 0.0) print("%.0f" % (1.750000 % 0.08333333333)) # Below isn't compatible with single-precision float #print("%.1f" % (1.750000 % 0.08333333333)) #print("%.2f" % (1.750000 % 0.08333333333)) #print("%.12f" % (1.750000 % 0.08333333333)) # tests for errors in format string try: '{:10.1b}'.format(0.0) except ValueError: print('ValueError') micropython-1.12/tests/float/string_format2.py000066400000000000000000000103541357706137100216060ustar00rootroot00000000000000# Change the following to True to get a much more comprehensive set of tests # to run, albeit, which take considerably longer. full_tests = False def test(fmt, *args): print('{:8s}'.format(fmt) + '>' + fmt.format(*args) + '<') def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg): fmt = '{' if conv: fmt += '!' fmt += conv fmt += ':' if alignment: fmt += fill fmt += alignment fmt += sign fmt += prefix fmt += width if precision: fmt += '.' fmt += precision fmt += type fmt += '}' test(fmt, arg) if fill == '0' and alignment == '=': fmt = '{:' fmt += sign fmt += prefix fmt += width if precision: fmt += '.' fmt += precision fmt += type fmt += '}' test(fmt, arg) eg_nums = (0.0, -0.0, 0.1, 1.234, 12.3459, 1.23456789, 123456789.0, -0.0, -0.1, -1.234, -12.3459, 1e4, 1e-4, 1e5, 1e-5, 1e6, 1e-6, 1e10, 1e37, -1e37, 1e-37, -1e-37, 1.23456e8, 1.23456e7, 1.23456e6, 1.23456e5, 1.23456e4, 1.23456e3, 1.23456e2, 1.23456e1, 1.23456e0, 1.23456e-1, 1.23456e-2, 1.23456e-3, 1.23456e-4, 1.23456e-5, 1.23456e-6, 1.23456e-7, 1.23456e-8, -1.23456e8, -1.23456e7, -1.23456e6, -1.23456e5, -1.23456e4, -1.23456e3, -1.23456e2, -1.23456e1, -1.23456e0, -1.23456e-1, -1.23456e-2, -1.23456e-3, -1.23456e-4, -1.23456e-5, -1.23456e-6, -1.23456e-7, -1.23456e-8) if full_tests: for type in ('e', 'E', 'g', 'G', 'n'): for width in ('', '4', '6', '8', '10'): for alignment in ('', '<', '>', '=', '^'): for fill in ('', '@', '0', ' '): for sign in ('', '+', '-', ' '): for prec in ('', '1', '3', '6'): for num in eg_nums: test_fmt('', fill, alignment, sign, '', width, prec, type, num) # Note: We use 1.23459 rather than 1.2345 because '{:3f}'.format(1.2345) # rounds differently than print("%.3f", 1.2345); f_nums = (0.0, -0.0, 0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 0.0012, 0.0123, 0.1234, 1.23459, 12.3456, -0.0001, -0.001, -0.01, -0.1, -1.0, -10.0, -0.0012, -0.0123, -0.1234, -1.23459, -12.3456) if full_tests: for type in ('f', 'F'): for width in ('', '4', '6', '8', '10'): for alignment in ('', '<', '>', '=', '^'): for fill in ('', ' ', '0', '@'): for sign in ('', '+', '-', ' '): # An empty precision defaults to 6, but when uPy is # configured to use a float, we can only use a # precision of 6 with numbers less than 10 and still # get results that compare to CPython (which uses # long doubles). for prec in ('1', '2', '3'): for num in f_nums: test_fmt('', fill, alignment, sign, '', width, prec, type, num) for num in int_nums2: test_fmt('', fill, alignment, sign, '', width, '', type, num) pct_nums1 = (0.1, 0.58, 0.99, -0.1, -0.58, -0.99) pct_nums2 = (True, False, 1, 0, -1) if full_tests: type = '%' for width in ('', '4', '6', '8', '10'): for alignment in ('', '<', '>', '=', '^'): for fill in ('', ' ', '0', '@'): for sign in ('', '+', '-', ' '): # An empty precision defaults to 6, but when uPy is # configured to use a float, we can only use a # precision of 6 with numbers less than 10 and still # get results that compare to CPython (which uses # long doubles). for prec in ('1', '2', '3'): for num in pct_nums1: test_fmt('', fill, alignment, sign, '', width, prec, type, num) for num in pct_nums2: test_fmt('', fill, alignment, sign, '', width, '', type, num) else: for num in pct_nums1: test_fmt('', '', '', '', '', '', '1', '%', num) # We don't currently test a type of '' with floats (see the detailed comment # in objstr.c) micropython-1.12/tests/float/string_format_fp30.py000066400000000000000000000017521357706137100223560ustar00rootroot00000000000000def test(fmt, *args): print('{:8s}'.format(fmt) + '>' + fmt.format(*args) + '<') test("{:10.4}", 123.456) test("{:10.4e}", 123.456) test("{:10.4e}", -123.456) #test("{:10.4f}", 123.456) #test("{:10.4f}", -123.456) test("{:10.4g}", 123.456) test("{:10.4g}", -123.456) test("{:10.4n}", 123.456) test("{:e}", 100) test("{:f}", 200) test("{:g}", 300) test("{:10.4E}", 123.456) test("{:10.4E}", -123.456) #test("{:10.4F}", 123.456) #test("{:10.4F}", -123.456) test("{:10.4G}", 123.456) test("{:10.4G}", -123.456) test("{:06e}", float("inf")) test("{:06e}", float("-inf")) test("{:06e}", float("nan")) # The following fails right now #test("{:10.1}", 0.0) print("%.0f" % (1.750000 % 0.08333333333)) # Below isn't compatible with single-precision float #print("%.1f" % (1.750000 % 0.08333333333)) #print("%.2f" % (1.750000 % 0.08333333333)) #print("%.12f" % (1.750000 % 0.08333333333)) # tests for errors in format string try: '{:10.1b}'.format(0.0) except ValueError: print('ValueError') micropython-1.12/tests/float/string_format_modulo.py000066400000000000000000000025111357706137100230770ustar00rootroot00000000000000print("%s" % 1.0) print("%r" % 1.0) print("%d" % 1.0) print("%i" % 1.0) print("%u" % 1.0) # these 3 have different behaviour in Python 3.x versions # uPy raises a TypeError, following Python 3.5 (earlier versions don't) #print("%x" % 18.0) #print("%o" % 18.0) #print("%X" % 18.0) print("%e" % 1.23456) print("%E" % 1.23456) print("%f" % 1.23456) print("%F" % 1.23456) print("%g" % 1.23456) print("%G" % 1.23456) print("%06e" % float("inf")) print("%06e" % float("-inf")) print("%06e" % float("nan")) print("%02.3d" % 123) # prec > width print("%+f %+f" % (1.23, -1.23)) # float sign print("% f % f" % (1.23, -1.23)) # float space sign print("%0f" % -1.23) # negative number with 0 padding # numbers with large negative exponents print('%f' % 1e-10) print('%f' % 1e-20) print('%f' % 1e-50) print('%f' % 1e-100) print('%f' % 1e-300) # large decimal precision should be truncated and not overflow buffer # the output depends on the FP calculation so only first 2 digits are printed # (the 'g' with small e are printed using 'f' style, so need to be checked) print(('%.40f' % 1e-300)[:2]) print(('%.40g' % 1e-1)[:2]) print(('%.40g' % 1e-2)[:2]) print(('%.40g' % 1e-3)[:2]) print(('%.40g' % 1e-4)[:2]) print("%.0g" % 1) # 0 precision 'g' print('%.1e' % 9.99) # round up with positive exponent print('%.1e' % 0.999) # round up with negative exponent micropython-1.12/tests/float/string_format_modulo2.py000066400000000000000000000015021357706137100231600ustar00rootroot00000000000000# test formatting floats with large precision, that it doesn't overflow the buffer def test(num, num_str): if num == float('inf') or num == 0.0 and num_str != '0.0': # skip numbers that overflow or underflow the FP precision return for kind in ('e', 'f', 'g'): # check precision either side of the size of the buffer (32 bytes) for prec in range(23, 36, 2): fmt = '%.' + '%d' % prec + kind s = fmt % num check = abs(float(s) - num) if num > 1: check /= num if check > 1e-6: print('FAIL', num_str, fmt, s, len(s), check) # check pure zero test(0.0, '0.0') # check some powers of 10, making sure to include exponents with 3 digits for e in range(-8, 8): num = pow(10, e) test(num, '1e%d' % e) micropython-1.12/tests/float/string_format_modulo2_intbig.py000066400000000000000000000014421357706137100245170ustar00rootroot00000000000000# test formatting floats with large precision, that it doesn't overflow the buffer def test(num, num_str): if num == float('inf') or num == 0.0 and num_str != '0.0': # skip numbers that overflow or underflow the FP precision return for kind in ('e', 'f', 'g'): # check precision either side of the size of the buffer (32 bytes) for prec in range(23, 36, 2): fmt = '%.' + '%d' % prec + kind s = fmt % num check = abs(float(s) - num) if num > 1: check /= num if check > 1e-6: print('FAIL', num_str, fmt, s, len(s), check) # check most powers of 10, making sure to include exponents with 3 digits for e in range(-101, 102): num = pow(10, e) test(num, '1e%d' % e) micropython-1.12/tests/float/string_format_modulo3.py000066400000000000000000000002051357706137100231600ustar00rootroot00000000000000# uPy and CPython outputs differ for the following print("%.1g" % -9.9) # round up 'g' with '-' sign print("%.2g" % 99.9) # round up micropython-1.12/tests/float/string_format_modulo3.py.exp000066400000000000000000000000101357706137100237450ustar00rootroot00000000000000-10 100 micropython-1.12/tests/float/true_value.py000066400000000000000000000001461357706137100210170ustar00rootroot00000000000000# Test true-ish value handling if not 0.0: print("float 0") if not 0+0j: print("complex 0") micropython-1.12/tests/float/types.py000066400000000000000000000003711357706137100200100ustar00rootroot00000000000000# float types print(float) print(complex) print(type(float()) == float) print(type(complex()) == complex) print(type(0.0) == float) print(type(1j) == complex) # hashing float types d = dict() d[float] = complex d[complex] = float print(len(d)) micropython-1.12/tests/import/000077500000000000000000000000001357706137100164765ustar00rootroot00000000000000micropython-1.12/tests/import/builtin_import.py000066400000000000000000000006271357706137100221150ustar00rootroot00000000000000# test calling builtin import function # basic test __import__('builtins') # first arg should be a string try: __import__(1) except TypeError: print('TypeError') # module name should not be empty try: __import__("") except ValueError: print('ValueError') # level argument should be non-negative try: __import__('xyz', None, None, None, -1) except ValueError: print('ValueError') micropython-1.12/tests/import/gen_context.py000066400000000000000000000001531357706137100213640ustar00rootroot00000000000000import gen_context2 GLOBAL = "GLOBAL" def gen(): print(GLOBAL) yield 1 gen_context2.call(gen()) micropython-1.12/tests/import/gen_context2.py000066400000000000000000000000311357706137100214410ustar00rootroot00000000000000def call(g): next(g) micropython-1.12/tests/import/import1a.py000066400000000000000000000000441357706137100206020ustar00rootroot00000000000000import import1b print(import1b.var) micropython-1.12/tests/import/import1b.py000066400000000000000000000000551357706137100206050ustar00rootroot00000000000000var = 123 def throw(): raise ValueError micropython-1.12/tests/import/import2a.py000066400000000000000000000001221357706137100206000ustar00rootroot00000000000000from import1b import var print(var) from import1b import var as var2 print(var2) micropython-1.12/tests/import/import3a.py000066400000000000000000000000421357706137100206020ustar00rootroot00000000000000from import1b import * print(var) micropython-1.12/tests/import/import_file.py000066400000000000000000000000511357706137100213550ustar00rootroot00000000000000import import1b print(import1b.__file__) micropython-1.12/tests/import/import_long_dyn.py000066400000000000000000000000371357706137100222530ustar00rootroot00000000000000from import_long_dyn2 import * micropython-1.12/tests/import/import_long_dyn2.py000066400000000000000000000000571357706137100223370ustar00rootroot00000000000000globals()["long_long_very_long_long_name"] = 1 micropython-1.12/tests/import/import_override.py000066400000000000000000000007341357706137100222650ustar00rootroot00000000000000# test overriding __import__ combined with importing from the filesystem def custom_import(name, globals, locals, fromlist, level): print('import', name, fromlist, level) class M: var = 456 return M orig_import = __import__ try: __import__("builtins").__import__ = custom_import except AttributeError: print("SKIP") raise SystemExit # import1a will be done via normal import which will import1b via our custom import orig_import('import1a') micropython-1.12/tests/import/import_override.py.exp000066400000000000000000000000331357706137100230500ustar00rootroot00000000000000import import1b None 0 456 micropython-1.12/tests/import/import_pkg1.py000066400000000000000000000004661357706137100213120ustar00rootroot00000000000000import pkg.mod print(pkg.__name__) print(pkg.mod.__name__) print(pkg.mod.foo()) # Import 2nd time, must be same module objects pkg_ = __import__("pkg.mod") print(pkg_ is not pkg.mod) print(pkg_ is pkg) print(pkg_.mod is pkg.mod) # import using "as" import pkg.mod as mm print(mm is pkg.mod) print(mm.foo()) micropython-1.12/tests/import/import_pkg2.py000066400000000000000000000005731357706137100213120ustar00rootroot00000000000000from pkg.mod import foo try: pkg except NameError: print("NameError") try: pkg.mod except NameError: print("NameError") print(foo()) # Import few times, must be same module objects mod_1 = __import__("pkg.mod", None, None, ("foo",)) mod_2 = __import__("pkg.mod", None, None, ("foo",)) print(mod_1 is mod_2) print(mod_1.foo is mod_2.foo) print(foo is mod_1.foo) micropython-1.12/tests/import/import_pkg3.py000066400000000000000000000001141357706137100213020ustar00rootroot00000000000000from pkg import mod print(mod.foo()) import pkg.mod print(mod is pkg.mod) micropython-1.12/tests/import/import_pkg4.py000066400000000000000000000001311357706137100213020ustar00rootroot00000000000000# Testing that "recursive" imports (pkg2/__init__.py imports from pkg2) work import pkg2 micropython-1.12/tests/import/import_pkg5.py000066400000000000000000000001751357706137100213130ustar00rootroot00000000000000# This tests relative imports as used in pkg3 import pkg3 import pkg3.mod1 import pkg3.subpkg1.mod1 pkg3.subpkg1.mod1.foo() micropython-1.12/tests/import/import_pkg6.py000066400000000000000000000000721357706137100213100ustar00rootroot00000000000000# This tests relative imports as used in pkg6 import pkg6 micropython-1.12/tests/import/import_pkg7.py000066400000000000000000000001631357706137100213120ustar00rootroot00000000000000# This tests ... relative imports as used in pkg7 and imports beyond package root import pkg7.subpkg1.subpkg2.mod3 micropython-1.12/tests/import/import_pkg8.py000066400000000000000000000000631357706137100213120ustar00rootroot00000000000000# import with no __init__.py files import pkg8.mod micropython-1.12/tests/import/import_star_error.py000066400000000000000000000005101357706137100226200ustar00rootroot00000000000000# test errors with import * # 'import *' is not allowed in function scope try: exec('def foo(): from x import *') except SyntaxError as er: print('function', 'SyntaxError') # 'import *' is not allowed in class scope try: exec('class C: from x import *') except SyntaxError as er: print('class', 'SyntaxError') micropython-1.12/tests/import/module_getattr.py000066400000000000000000000010331357706137100220640ustar00rootroot00000000000000# test __getattr__ on module # ensure that does_not_exist doesn't exist to start with this = __import__(__name__) try: this.does_not_exist assert False except AttributeError: pass # define __getattr__ def __getattr__(attr): if attr == 'does_not_exist': return False raise AttributeError # do feature test (will also test functionality if the feature exists) if not hasattr(this, 'does_not_exist'): print('SKIP') raise SystemExit # check that __getattr__ works as expected print(this.does_not_exist) micropython-1.12/tests/import/module_getattr.py.exp000066400000000000000000000000061357706137100226560ustar00rootroot00000000000000False micropython-1.12/tests/import/mpy_invalid.py000066400000000000000000000030421357706137100213620ustar00rootroot00000000000000# test importing of invalid .mpy files import sys, uio try: uio.IOBase import uos uos.mount except (ImportError, AttributeError): print("SKIP") raise SystemExit class UserFile(uio.IOBase): def __init__(self, data): self.data = data self.pos = 0 def read(self): return self.data def readinto(self, buf): n = 0 while n < len(buf) and self.pos < len(self.data): buf[n] = self.data[self.pos] n += 1 self.pos += 1 return n def ioctl(self, req, arg): return 0 class UserFS: def __init__(self, files): self.files = files def mount(self, readonly, mksfs): pass def umount(self): pass def stat(self, path): if path in self.files: return (32768, 0, 0, 0, 0, 0, 0, 0, 0, 0) raise OSError def open(self, path, mode): return UserFile(self.files[path]) # these are the test .mpy files user_files = { '/mod0.mpy': b'', # empty file '/mod1.mpy': b'M', # too short header '/mod2.mpy': b'M\x00\x00\x00', # bad version '/mod3.mpy': b'M\x00\x00\x00\x7f', # qstr window too large } # create and mount a user filesystem uos.mount(UserFS(user_files), '/userfs') sys.path.append('/userfs') # import .mpy files from the user filesystem for i in range(len(user_files)): mod = 'mod%u' % i try: __import__(mod) except ValueError as er: print(mod, 'ValueError', er) # unmount and undo path addition uos.umount('/userfs') sys.path.pop() micropython-1.12/tests/import/mpy_invalid.py.exp000066400000000000000000000002341357706137100221550ustar00rootroot00000000000000mod0 ValueError incompatible .mpy file mod1 ValueError incompatible .mpy file mod2 ValueError incompatible .mpy file mod3 ValueError incompatible .mpy file micropython-1.12/tests/import/mpy_native.py000066400000000000000000000057001357706137100212250ustar00rootroot00000000000000# test importing of .mpy files with native code (x64 only) import sys, uio try: uio.IOBase import uos uos.mount except (ImportError, AttributeError): print("SKIP") raise SystemExit if not (sys.platform == 'linux' and sys.maxsize > 2 ** 32): print("SKIP") raise SystemExit class UserFile(uio.IOBase): def __init__(self, data): self.data = data self.pos = 0 def read(self): return self.data def readinto(self, buf): n = 0 while n < len(buf) and self.pos < len(self.data): buf[n] = self.data[self.pos] n += 1 self.pos += 1 return n def ioctl(self, req, arg): return 0 class UserFS: def __init__(self, files): self.files = files def mount(self, readonly, mksfs): pass def umount(self): pass def stat(self, path): if path in self.files: return (32768, 0, 0, 0, 0, 0, 0, 0, 0, 0) raise OSError def open(self, path, mode): return UserFile(self.files[path]) # these are the test .mpy files user_files = { # bad architecture '/mod0.mpy': b'M\x05\xff\x00\x10', # test loading of viper and asm '/mod1.mpy': ( b'M\x05\x0b\x1f\x20' # header b'\x20' # n bytes, bytecode b'\x00\x08\x02m\x02m' # prelude b'\x51' # LOAD_CONST_NONE b'\x63' # RETURN_VALUE b'\x00\x02' # n_obj, n_raw_code b'\x22' # n bytes, viper code b'\x00\x00\x00\x00\x00\x00' # dummy machine code b'\x00\x00' # qstr0 b'\x01\x0c\x0aprint' # n_qstr, qstr0 b'\x00\x00\x00' # scope_flags, n_obj, n_raw_code b'\x23' # n bytes, asm code b'\x00\x00\x00\x00\x00\x00\x00\x00' # dummy machine code b'\x00\x00\x00' # scope_flags, n_pos_args, type_sig ), # test loading viper with additional scope flags and relocation '/mod2.mpy': ( b'M\x05\x0b\x1f\x20' # header b'\x20' # n bytes, bytecode b'\x00\x08\x02m\x02m' # prelude b'\x51' # LOAD_CONST_NONE b'\x63' # RETURN_VALUE b'\x00\x01' # n_obj, n_raw_code b'\x12' # n bytes(=4), viper code b'\x00\x00\x00\x00' # dummy machine code b'\x00' # n_qstr b'\x70' # scope_flags: VIPERBSS | VIPERRODATA | VIPERRELOC b'\x00\x00' # n_obj, n_raw_code b'\x06rodata' # rodata, 6 bytes b'\x04' # bss, 4 bytes b'\x03\x01\x00' # dummy relocation of rodata ), } # create and mount a user filesystem uos.mount(UserFS(user_files), '/userfs') sys.path.append('/userfs') # import .mpy files from the user filesystem for i in range(len(user_files)): mod = 'mod%u' % i try: __import__(mod) print(mod, 'OK') except ValueError as er: print(mod, 'ValueError', er) # unmount and undo path addition uos.umount('/userfs') sys.path.pop() micropython-1.12/tests/import/mpy_native.py.exp000066400000000000000000000000671357706137100220210ustar00rootroot00000000000000mod0 ValueError incompatible .mpy arch mod1 OK mod2 OK micropython-1.12/tests/import/pkg/000077500000000000000000000000001357706137100172575ustar00rootroot00000000000000micropython-1.12/tests/import/pkg/__init__.py000066400000000000000000000000001357706137100213560ustar00rootroot00000000000000micropython-1.12/tests/import/pkg/mod.py000066400000000000000000000000311357706137100204020ustar00rootroot00000000000000def foo(): return 42 micropython-1.12/tests/import/pkg2/000077500000000000000000000000001357706137100173415ustar00rootroot00000000000000micropython-1.12/tests/import/pkg2/__init__.py000066400000000000000000000000261357706137100214500ustar00rootroot00000000000000from pkg2 import mod1 micropython-1.12/tests/import/pkg2/mod1.py000066400000000000000000000000261357706137100205510ustar00rootroot00000000000000from pkg2 import mod2 micropython-1.12/tests/import/pkg2/mod2.py000066400000000000000000000000211357706137100205450ustar00rootroot00000000000000print("in mod2") micropython-1.12/tests/import/pkg3/000077500000000000000000000000001357706137100173425ustar00rootroot00000000000000micropython-1.12/tests/import/pkg3/__init__.py000066400000000000000000000000411357706137100214460ustar00rootroot00000000000000print("pkg __name__:", __name__) micropython-1.12/tests/import/pkg3/mod1.py000066400000000000000000000000651357706137100205550ustar00rootroot00000000000000print("mod1 __name__:", __name__) from . import mod2 micropython-1.12/tests/import/pkg3/mod2.py000066400000000000000000000001271357706137100205550ustar00rootroot00000000000000print("mod2 __name__:", __name__) print("in mod2") def foo(): print("mod2.foo()") micropython-1.12/tests/import/pkg3/subpkg1/000077500000000000000000000000001357706137100207165ustar00rootroot00000000000000micropython-1.12/tests/import/pkg3/subpkg1/__init__.py000066400000000000000000000000451357706137100230260ustar00rootroot00000000000000print("subpkg1 __name__:", __name__) micropython-1.12/tests/import/pkg3/subpkg1/mod1.py000066400000000000000000000001011357706137100221200ustar00rootroot00000000000000print("subpkg1.mod1 __name__:", __name__) from ..mod2 import foo micropython-1.12/tests/import/pkg6/000077500000000000000000000000001357706137100173455ustar00rootroot00000000000000micropython-1.12/tests/import/pkg6/__init__.py000066400000000000000000000000371357706137100214560ustar00rootroot00000000000000from .x import * print('init') micropython-1.12/tests/import/pkg6/x/000077500000000000000000000000001357706137100176145ustar00rootroot00000000000000micropython-1.12/tests/import/pkg6/x/__init__.py000066400000000000000000000000341357706137100217220ustar00rootroot00000000000000from .y import * print('x') micropython-1.12/tests/import/pkg6/x/y.py000066400000000000000000000000131357706137100204300ustar00rootroot00000000000000print('y') micropython-1.12/tests/import/pkg7/000077500000000000000000000000001357706137100173465ustar00rootroot00000000000000micropython-1.12/tests/import/pkg7/__init__.py000066400000000000000000000000411357706137100214520ustar00rootroot00000000000000print("pkg __name__:", __name__) micropython-1.12/tests/import/pkg7/mod1.py000066400000000000000000000000371357706137100205600ustar00rootroot00000000000000print('mod1') foo = 'mod1.foo' micropython-1.12/tests/import/pkg7/mod2.py000066400000000000000000000000371357706137100205610ustar00rootroot00000000000000print('mod2') bar = 'mod2.bar' micropython-1.12/tests/import/pkg7/subpkg1/000077500000000000000000000000001357706137100207225ustar00rootroot00000000000000micropython-1.12/tests/import/pkg7/subpkg1/__init__.py000066400000000000000000000000411357706137100230260ustar00rootroot00000000000000print("pkg __name__:", __name__) micropython-1.12/tests/import/pkg7/subpkg1/subpkg2/000077500000000000000000000000001357706137100222775ustar00rootroot00000000000000micropython-1.12/tests/import/pkg7/subpkg1/subpkg2/__init__.py000066400000000000000000000000411357706137100244030ustar00rootroot00000000000000print("pkg __name__:", __name__) micropython-1.12/tests/import/pkg7/subpkg1/subpkg2/mod3.py000066400000000000000000000003101357706137100235050ustar00rootroot00000000000000from ... import mod1 from ...mod2 import bar print(mod1.foo) print(bar) # attempted relative import beyond top-level package try: from .... import mod1 except ValueError: print('ValueError') micropython-1.12/tests/import/pkg8/000077500000000000000000000000001357706137100173475ustar00rootroot00000000000000micropython-1.12/tests/import/pkg8/mod.py000066400000000000000000000000151357706137100204740ustar00rootroot00000000000000print('foo') micropython-1.12/tests/import/rel_import_inv.py000066400000000000000000000001171357706137100220770ustar00rootroot00000000000000try: from . import foo except: print("Invalid relative import caught") micropython-1.12/tests/import/try_module.py000066400000000000000000000004521357706137100212340ustar00rootroot00000000000000# Regression test for #290 - throwing exception in another module led to # its namespace stick and namespace of current module not coming back. import import1b def func1(): print('func1') def func2(): try: import1b.throw() except ValueError: pass func1() func2() micropython-1.12/tests/inlineasm/000077500000000000000000000000001357706137100171435ustar00rootroot00000000000000micropython-1.12/tests/inlineasm/asmargs.py000066400000000000000000000007431357706137100211560ustar00rootroot00000000000000# test passing arguments @micropython.asm_thumb def arg0(): mov(r0, 1) print(arg0()) @micropython.asm_thumb def arg1(r0): add(r0, r0, 1) print(arg1(1)) @micropython.asm_thumb def arg2(r0, r1): add(r0, r0, r1) print(arg2(1, 2)) @micropython.asm_thumb def arg3(r0, r1, r2): add(r0, r0, r1) add(r0, r0, r2) print(arg3(1, 2, 3)) @micropython.asm_thumb def arg4(r0, r1, r2, r3): add(r0, r0, r1) add(r0, r0, r2) add(r0, r0, r3) print(arg4(1, 2, 3, 4)) micropython-1.12/tests/inlineasm/asmargs.py.exp000066400000000000000000000000131357706137100217370ustar00rootroot000000000000001 2 3 6 10 micropython-1.12/tests/inlineasm/asmbcc.py000066400000000000000000000005401357706137100207440ustar00rootroot00000000000000# test bcc instructions # at the moment only tests beq, narrow and wide versions @micropython.asm_thumb def f(r0): mov(r1, r0) mov(r0, 10) cmp(r1, 1) beq(end) mov(r0, 20) cmp(r1, 2) beq_n(end) mov(r0, 30) cmp(r1, 3) beq_w(end) mov(r0, 0) label(end) print(f(0)) print(f(1)) print(f(2)) print(f(3)) micropython-1.12/tests/inlineasm/asmbcc.py.exp000066400000000000000000000000131357706137100215320ustar00rootroot000000000000000 10 20 30 micropython-1.12/tests/inlineasm/asmbitops.py000066400000000000000000000003011357706137100215100ustar00rootroot00000000000000@micropython.asm_thumb def clz(r0): clz(r0, r0) print(clz(0xf0)) print(clz(0x8000)) @micropython.asm_thumb def rbit(r0): rbit(r0, r0) print(hex(rbit(0xf0))) print(hex(rbit(0x8000))) micropython-1.12/tests/inlineasm/asmbitops.py.exp000066400000000000000000000000301357706137100223020ustar00rootroot0000000000000024 16 0xf000000 0x10000 micropython-1.12/tests/inlineasm/asmblbx.py000066400000000000000000000004241357706137100211450ustar00rootroot00000000000000# test bl and bx instructions @micropython.asm_thumb def f(r0): # jump over the internal functions b(entry) label(func1) add(r0, 2) bx(lr) label(func2) sub(r0, 1) bx(lr) label(entry) bl(func1) bl(func2) print(f(0)) print(f(1)) micropython-1.12/tests/inlineasm/asmblbx.py.exp000066400000000000000000000000041357706137100217320ustar00rootroot000000000000001 2 micropython-1.12/tests/inlineasm/asmconst.py000066400000000000000000000002311357706137100213400ustar00rootroot00000000000000# test constants in assembler @micropython.asm_thumb def c1(): movwt(r0, 0xffffffff) movwt(r1, 0xf0000000) sub(r0, r0, r1) print(hex(c1())) micropython-1.12/tests/inlineasm/asmconst.py.exp000066400000000000000000000000121357706137100221300ustar00rootroot000000000000000xfffffff micropython-1.12/tests/inlineasm/asmdiv.py000066400000000000000000000004641357706137100210040ustar00rootroot00000000000000@micropython.asm_thumb def sdiv(r0, r1): sdiv(r0, r0, r1) @micropython.asm_thumb def udiv(r0, r1): udiv(r0, r0, r1) print(sdiv(1234, 3)) print(sdiv(-1234, 3)) print(sdiv(1234, -3)) print(sdiv(-1234, -3)) print(udiv(1234, 3)) print(udiv(0xffffffff, 0x7fffffff)) print(udiv(0xffffffff, 0xffffffff)) micropython-1.12/tests/inlineasm/asmdiv.py.exp000066400000000000000000000000321357706137100215660ustar00rootroot00000000000000411 -411 -411 411 411 2 1 micropython-1.12/tests/inlineasm/asmfpaddsub.py000066400000000000000000000004671357706137100220150ustar00rootroot00000000000000@micropython.asm_thumb # r0 = r0+r1-r2 def add_sub(r0, r1, r2): vmov(s0, r0) vcvt_f32_s32(s0, s0) vmov(s1, r1) vcvt_f32_s32(s1, s1) vmov(s2, r2) vcvt_f32_s32(s2, s2) vadd(s0, s0, s1) vsub(s0, s0, s2) vcvt_s32_f32(s31, s0) vmov(r0, s31) print(add_sub(100, 20, 30)) micropython-1.12/tests/inlineasm/asmfpaddsub.py.exp000066400000000000000000000000031357706137100225720ustar00rootroot0000000000000090 micropython-1.12/tests/inlineasm/asmfpcmp.py000066400000000000000000000004011357706137100213160ustar00rootroot00000000000000@micropython.asm_thumb # test vcmp, vmrs def f(r0, r1): vmov(s0, r0) vcvt_f32_s32(s0, s0) vmov(s1, r1) vcvt_f32_s32(s1, s1) vcmp(s1, s0) vmrs(r0, FPSCR) mov(r1, 28) lsr(r0, r1) print(f(0,1)) print(f(1,1)) print(f(1,0)) micropython-1.12/tests/inlineasm/asmfpcmp.py.exp000066400000000000000000000000061357706137100221120ustar00rootroot000000000000002 6 8 micropython-1.12/tests/inlineasm/asmfpldrstr.py000066400000000000000000000003511357706137100220550ustar00rootroot00000000000000import uarray as array @micropython.asm_thumb # test vldr, vstr def arrayadd(r0): vldr(s0, [r0, 0]) vldr(s1, [r0, 4]) vadd(s2, s0, s1) vstr(s2, [r0, 8]) z = array.array("f", [2, 4, 10]) arrayadd(z) print(z[2]) micropython-1.12/tests/inlineasm/asmfpldrstr.py.exp000066400000000000000000000000041357706137100226430ustar00rootroot000000000000006.0 micropython-1.12/tests/inlineasm/asmfpmuldiv.py000066400000000000000000000004741357706137100220510ustar00rootroot00000000000000@micropython.asm_thumb # r0 = (int)(r0*r1/r2) def muldiv(r0, r1, r2): vmov(s0, r0) vcvt_f32_s32(s0, s0) vmov(s1, r1) vcvt_f32_s32(s1, s1) vmov(s2, r2) vcvt_f32_s32(s2, s2) vmul(s7, s0, s1) vdiv(s8, s7, s2) vcvt_s32_f32(s31, s8) vmov(r0, s31) print(muldiv(100, 10, 50)) micropython-1.12/tests/inlineasm/asmfpmuldiv.py.exp000066400000000000000000000000031357706137100226300ustar00rootroot0000000000000020 micropython-1.12/tests/inlineasm/asmfpsqrt.py000066400000000000000000000004651357706137100215420ustar00rootroot00000000000000# test vsqrt, vneg @micropython.asm_thumb # r0 = -(int)(sqrt(r0)*r1) def sqrt_test(r0, r1): vmov(s1, r0) vcvt_f32_s32(s1, s1) vsqrt(s1, s1) vmov(s2, r1) vcvt_f32_s32(s2, s2) vmul(s0, s1, s2) vneg(s7, s0) vcvt_s32_f32(s31, s7) vmov(r0, s31) print(sqrt_test(256, 10)) micropython-1.12/tests/inlineasm/asmfpsqrt.py.exp000066400000000000000000000000051357706137100223230ustar00rootroot00000000000000-160 micropython-1.12/tests/inlineasm/asmit.py000066400000000000000000000003761357706137100206400ustar00rootroot00000000000000# test it instruction @micropython.asm_thumb def f(r0, r1): cmp(r0, r1) it(eq) mov(r0, 100) print(f(0, 0), f(1, 2)) @micropython.asm_thumb def g(r0, r1): cmp(r0, r1) ite(eq) mov(r0, 100) mov(r0, 200) print(g(0, 0), g(0, 1)) micropython-1.12/tests/inlineasm/asmit.py.exp000066400000000000000000000000161357706137100214220ustar00rootroot00000000000000100 1 100 200 micropython-1.12/tests/inlineasm/asmpushpop.py000066400000000000000000000001771357706137100217210ustar00rootroot00000000000000@micropython.asm_thumb def f(r0, r1, r2): push({r0}) push({r1, r2}) pop({r0}) pop({r1, r2}) print(f(0, 1, 2)) micropython-1.12/tests/inlineasm/asmpushpop.py.exp000066400000000000000000000000021357706137100224770ustar00rootroot000000000000001 micropython-1.12/tests/inlineasm/asmrettype.py000066400000000000000000000007421357706137100217150ustar00rootroot00000000000000# test return type of inline asm @micropython.asm_thumb def ret_obj(r0) -> object: pass ret_obj(print)(1) @micropython.asm_thumb def ret_bool(r0) -> bool: pass print(ret_bool(0), ret_bool(1)) @micropython.asm_thumb def ret_int(r0) -> int: lsl(r0, r0, 29) print(ret_int(0), hex(ret_int(1)), hex(ret_int(2)), hex(ret_int(4))) @micropython.asm_thumb def ret_uint(r0) -> uint: lsl(r0, r0, 29) print(ret_uint(0), hex(ret_uint(1)), hex(ret_uint(2)), hex(ret_uint(4))) micropython-1.12/tests/inlineasm/asmrettype.py.exp000066400000000000000000000001241357706137100225020ustar00rootroot000000000000001 False True 0 0x20000000 0x40000000 -0x80000000 0 0x20000000 0x40000000 0x80000000 micropython-1.12/tests/inlineasm/asmshift.py000066400000000000000000000007641357706137100213420ustar00rootroot00000000000000@micropython.asm_thumb def lsl1(r0): lsl(r0, r0, 1) print(hex(lsl1(0x123))) @micropython.asm_thumb def lsl23(r0): lsl(r0, r0, 23) print(hex(lsl23(1))) @micropython.asm_thumb def lsr1(r0): lsr(r0, r0, 1) print(hex(lsr1(0x123))) @micropython.asm_thumb def lsr31(r0): lsr(r0, r0, 31) print(hex(lsr31(0x80000000))) @micropython.asm_thumb def asr1(r0): asr(r0, r0, 1) print(hex(asr1(0x123))) @micropython.asm_thumb def asr31(r0): asr(r0, r0, 31) print(hex(asr31(0x80000000))) micropython-1.12/tests/inlineasm/asmshift.py.exp000066400000000000000000000000421357706137100221220ustar00rootroot000000000000000x246 0x800000 0x91 0x1 0x91 -0x1 micropython-1.12/tests/inlineasm/asmspecialregs.py000066400000000000000000000002361357706137100225200ustar00rootroot00000000000000@micropython.asm_thumb def getIPSR(): mrs(r0, IPSR) @micropython.asm_thumb def getBASEPRI(): mrs(r0, BASEPRI) print(getBASEPRI()) print(getIPSR()) micropython-1.12/tests/inlineasm/asmspecialregs.py.exp000066400000000000000000000000041357706137100233040ustar00rootroot000000000000000 0 micropython-1.12/tests/inlineasm/asmsum.py000066400000000000000000000016101357706137100210200ustar00rootroot00000000000000@micropython.asm_thumb def asm_sum_words(r0, r1): # r0 = len # r1 = ptr # r2 = sum # r3 = dummy mov(r2, 0) b(loop_entry) label(loop1) ldr(r3, [r1, 0]) add(r2, r2, r3) add(r1, r1, 4) sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) mov(r0, r2) @micropython.asm_thumb def asm_sum_bytes(r0, r1): # r0 = len # r1 = ptr # r2 = sum # r3 = dummy mov(r2, 0) b(loop_entry) label(loop1) ldrb(r3, [r1, 0]) add(r2, r2, r3) add(r1, r1, 1) sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) mov(r0, r2) import uarray as array b = array.array('l', (100, 200, 300, 400)) n = asm_sum_words(len(b), b) print(b, n) b = array.array('b', (10, 20, 30, 40, 50, 60, 70, 80)) n = asm_sum_bytes(len(b), b) print(b, n) b = b'\x01\x02\x03\x04' n = asm_sum_bytes(len(b), b) print(b, n) micropython-1.12/tests/inlineasm/asmsum.py.exp000066400000000000000000000001561357706137100216170ustar00rootroot00000000000000array('l', [100, 200, 300, 400]) 1000 array('b', [10, 20, 30, 40, 50, 60, 70, 80]) 360 b'\x01\x02\x03\x04' 10 micropython-1.12/tests/internal_bench/000077500000000000000000000000001357706137100201375ustar00rootroot00000000000000micropython-1.12/tests/internal_bench/arrayop-1-list_inplace.py000066400000000000000000000004741357706137100247750ustar00rootroot00000000000000# Array operation # Type: list, inplace operation using for. What's good about this # method is that it doesn't require any extra memory allocation. import bench def test(num): for i in iter(range(num//10000)): arr = [0] * 1000 for i in range(len(arr)): arr[i] += 1 bench.run(test) micropython-1.12/tests/internal_bench/arrayop-2-list_map.py000066400000000000000000000005401357706137100241320ustar00rootroot00000000000000# Array operation # Type: list, map() call. This method requires allocation of # the same amount of memory as original array (to hold result # array). On the other hand, input array stays intact. import bench def test(num): for i in iter(range(num//10000)): arr = [0] * 1000 arr2 = list(map(lambda x: x + 1, arr)) bench.run(test) micropython-1.12/tests/internal_bench/arrayop-3-bytearray_inplace.py000066400000000000000000000005161357706137100260230ustar00rootroot00000000000000# Array operation # Type: bytearray, inplace operation using for. What's good about this # method is that it doesn't require any extra memory allocation. import bench def test(num): for i in iter(range(num//10000)): arr = bytearray(b"\0" * 1000) for i in range(len(arr)): arr[i] += 1 bench.run(test) micropython-1.12/tests/internal_bench/arrayop-4-bytearray_map.py000066400000000000000000000005621357706137100251670ustar00rootroot00000000000000# Array operation # Type: list, map() call. This method requires allocation of # the same amount of memory as original array (to hold result # array). On the other hand, input array stays intact. import bench def test(num): for i in iter(range(num//10000)): arr = bytearray(b"\0" * 1000) arr2 = bytearray(map(lambda x: x + 1, arr)) bench.run(test) micropython-1.12/tests/internal_bench/bench.py000066400000000000000000000001621357706137100215670ustar00rootroot00000000000000import time ITERS = 20000000 def run(f): t = time.time() f(ITERS) t = time.time() - t print(t) micropython-1.12/tests/internal_bench/bytealloc-1-bytes_n.py000066400000000000000000000001521357706137100242640ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num // 1000)): bytes(10000) bench.run(test) micropython-1.12/tests/internal_bench/bytealloc-2-repeat.py000066400000000000000000000001531357706137100241030ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num // 1000)): b"\0" * 10000 bench.run(test) micropython-1.12/tests/internal_bench/bytebuf-1-inplace.py000066400000000000000000000003771357706137100237270ustar00rootroot00000000000000# Doing some operation on bytearray # Inplace - the most memory efficient way import bench def test(num): for i in iter(range(num//10000)): ba = bytearray(b"\0" * 1000) for i in range(len(ba)): ba[i] += 1 bench.run(test) micropython-1.12/tests/internal_bench/bytebuf-2-join_map_bytes.py000066400000000000000000000005771357706137100253210ustar00rootroot00000000000000# Doing some operation on bytearray # Pretty weird way - map bytearray thru function, but make sure that # function return bytes of size 1, then join them together. Surely, # this is slowest way to do it. import bench def test(num): for i in iter(range(num//10000)): ba = bytearray(b"\0" * 1000) ba2 = b''.join(map(lambda x:bytes([x + 1]), ba)) bench.run(test) micropython-1.12/tests/internal_bench/bytebuf-3-bytarray_map.py000066400000000000000000000003541357706137100250030ustar00rootroot00000000000000# Doing some operation on bytearray # No joins, but still map(). import bench def test(num): for i in iter(range(num//10000)): ba = bytearray(b"\0" * 1000) ba2 = bytearray(map(lambda x: x + 1, ba)) bench.run(test) micropython-1.12/tests/internal_bench/from_iter-1-list_bound.py000066400000000000000000000002001357706137100247650ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//10000)): l = [0] * 1000 l2 = list(l) bench.run(test) micropython-1.12/tests/internal_bench/from_iter-2-list_unbound.py000066400000000000000000000002221357706137100253350ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//10000)): l = [0] * 1000 l2 = list(map(lambda x: x, l)) bench.run(test) micropython-1.12/tests/internal_bench/from_iter-3-tuple_bound.py000066400000000000000000000002011357706137100251460ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//10000)): l = [0] * 1000 l2 = tuple(l) bench.run(test) micropython-1.12/tests/internal_bench/from_iter-4-tuple_unbound.py000066400000000000000000000002231357706137100255160ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//10000)): l = [0] * 1000 l2 = tuple(map(lambda x: x, l)) bench.run(test) micropython-1.12/tests/internal_bench/from_iter-5-bytes_bound.py000066400000000000000000000002011357706137100251450ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//10000)): l = [0] * 1000 l2 = bytes(l) bench.run(test) micropython-1.12/tests/internal_bench/from_iter-6-bytes_unbound.py000066400000000000000000000002231357706137100255150ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//10000)): l = [0] * 1000 l2 = bytes(map(lambda x: x, l)) bench.run(test) micropython-1.12/tests/internal_bench/from_iter-7-bytearray_bound.py000066400000000000000000000002051357706137100260270ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//10000)): l = [0] * 1000 l2 = bytearray(l) bench.run(test) micropython-1.12/tests/internal_bench/from_iter-8-bytearray_unbound.py000066400000000000000000000002271357706137100263770ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//10000)): l = [0] * 1000 l2 = bytearray(map(lambda x: x, l)) bench.run(test) micropython-1.12/tests/internal_bench/func_args-1.1-pos_1.py000066400000000000000000000001641357706137100237750ustar00rootroot00000000000000import bench def func(a): pass def test(num): for i in iter(range(num)): func(i) bench.run(test) micropython-1.12/tests/internal_bench/func_args-1.2-pos_3.py000066400000000000000000000002001357706137100237670ustar00rootroot00000000000000import bench def func(a, b, c): pass def test(num): for i in iter(range(num)): func(i, i, i) bench.run(test) micropython-1.12/tests/internal_bench/func_args-2-pos_default_2_of_3.py000066400000000000000000000001761357706137100262550ustar00rootroot00000000000000import bench def func(a, b=1, c=2): pass def test(num): for i in iter(range(num)): func(i) bench.run(test) micropython-1.12/tests/internal_bench/func_args-3.1-kw_1.py000066400000000000000000000001661357706137100236210ustar00rootroot00000000000000import bench def func(a): pass def test(num): for i in iter(range(num)): func(a=i) bench.run(test) micropython-1.12/tests/internal_bench/func_args-3.2-kw_3.py000066400000000000000000000002061357706137100236170ustar00rootroot00000000000000import bench def func(a, b, c): pass def test(num): for i in iter(range(num)): func(c=i, b=i, a=i) bench.run(test) micropython-1.12/tests/internal_bench/func_builtin-1-enum_pos.py000066400000000000000000000001561357706137100251550ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//20)): enumerate([1, 2], 1) bench.run(test) micropython-1.12/tests/internal_bench/func_builtin-2-enum_kw.py000066400000000000000000000001751357706137100247770ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num//20)): enumerate(iterable=[1, 2], start=1) bench.run(test) micropython-1.12/tests/internal_bench/funcall-1-inline.py000066400000000000000000000002761357706137100235540ustar00rootroot00000000000000# Function call overhead test # Establish a baseline for performing a trivial operation inline import bench def test(num): for i in iter(range(num)): a = i + 1 bench.run(test) micropython-1.12/tests/internal_bench/funcall-2-funcall.py000066400000000000000000000003251357706137100237160ustar00rootroot00000000000000# Function call overhead test # Perform the same trivial operation as global function call import bench def f(x): return x + 1 def test(num): for i in iter(range(num)): a = f(i) bench.run(test) micropython-1.12/tests/internal_bench/funcall-3-funcall-local.py000066400000000000000000000006531357706137100250130ustar00rootroot00000000000000# Function call overhead test # Perform the same trivial operation as calling function, cached in a # local variable. This is commonly known optimization for overly dynamic # languages (the idea is to cut on symbolic look up overhead, as local # variables are accessed by offset, not by name) import bench def f(x): return x + 1 def test(num): f_ = f for i in iter(range(num)): a = f_(i) bench.run(test) micropython-1.12/tests/internal_bench/loop_count-1-range.py000066400000000000000000000001241357706137100241170ustar00rootroot00000000000000import bench def test(num): for i in range(num): pass bench.run(test) micropython-1.12/tests/internal_bench/loop_count-2-range_iter.py000066400000000000000000000001321357706137100251420ustar00rootroot00000000000000import bench def test(num): for i in iter(range(num)): pass bench.run(test) micropython-1.12/tests/internal_bench/loop_count-3-while_up.py000066400000000000000000000001321357706137100246400ustar00rootroot00000000000000import bench def test(num): i = 0 while i < num: i += 1 bench.run(test) micropython-1.12/tests/internal_bench/loop_count-4-while_down_gt.py000066400000000000000000000001221357706137100256550ustar00rootroot00000000000000import bench def test(num): while num > 0: num -= 1 bench.run(test) micropython-1.12/tests/internal_bench/loop_count-5-while_down_ne.py000066400000000000000000000001231357706137100256470ustar00rootroot00000000000000import bench def test(num): while num != 0: num -= 1 bench.run(test) micropython-1.12/tests/internal_bench/loop_count-5.1-while_down_ne_localvar.py000066400000000000000000000001431357706137100276730ustar00rootroot00000000000000import bench def test(num): zero = 0 while num != zero: num -= 1 bench.run(test) micropython-1.12/tests/internal_bench/var-1-constant.py000066400000000000000000000001371357706137100232670ustar00rootroot00000000000000import bench def test(num): i = 0 while i < 20000000: i += 1 bench.run(test) micropython-1.12/tests/internal_bench/var-2-global.py000066400000000000000000000001561357706137100227000ustar00rootroot00000000000000import bench ITERS = 20000000 def test(num): i = 0 while i < ITERS: i += 1 bench.run(test) micropython-1.12/tests/internal_bench/var-3-local.py000066400000000000000000000001621357706137100225300ustar00rootroot00000000000000import bench def test(num): ITERS = 20000000 i = 0 while i < ITERS: i += 1 bench.run(test) micropython-1.12/tests/internal_bench/var-4-arg.py000066400000000000000000000001561357706137100222130ustar00rootroot00000000000000import bench def test(num): i = 0 while i < num: i += 1 bench.run(lambda n:test(20000000)) micropython-1.12/tests/internal_bench/var-5-class-attr.py000066400000000000000000000001751357706137100235210ustar00rootroot00000000000000import bench class Foo: num = 20000000 def test(num): i = 0 while i < Foo.num: i += 1 bench.run(test) micropython-1.12/tests/internal_bench/var-6-instance-attr.py000066400000000000000000000002531357706137100242160ustar00rootroot00000000000000import bench class Foo: def __init__(self): self.num = 20000000 def test(num): o = Foo() i = 0 while i < o.num: i += 1 bench.run(test) micropython-1.12/tests/internal_bench/var-6.1-instance-attr-5.py000066400000000000000000000004031357706137100245140ustar00rootroot00000000000000import bench class Foo: def __init__(self): self.num1 = 0 self.num2 = 0 self.num3 = 0 self.num4 = 0 self.num = 20000000 def test(num): o = Foo() i = 0 while i < o.num: i += 1 bench.run(test) micropython-1.12/tests/internal_bench/var-7-instance-meth.py000066400000000000000000000003331357706137100242010ustar00rootroot00000000000000import bench class Foo: def __init__(self): self._num = 20000000 def num(self): return self._num def test(num): o = Foo() i = 0 while i < o.num(): i += 1 bench.run(test) micropython-1.12/tests/internal_bench/var-8-namedtuple-1st.py000066400000000000000000000002761357706137100243140ustar00rootroot00000000000000import bench from ucollections import namedtuple T = namedtuple("Tup", ["num", "bar"]) def test(num): t = T(20000000, 0) i = 0 while i < t.num: i += 1 bench.run(test) micropython-1.12/tests/internal_bench/var-8.1-namedtuple-5th.py000066400000000000000000000003401357706137100244340ustar00rootroot00000000000000import bench from ucollections import namedtuple T = namedtuple("Tup", ["foo1", "foo2", "foo3", "foo4", "num"]) def test(num): t = T(0, 0, 0, 0, 20000000) i = 0 while i < t.num: i += 1 bench.run(test) micropython-1.12/tests/io/000077500000000000000000000000001357706137100155735ustar00rootroot00000000000000micropython-1.12/tests/io/argv.py000066400000000000000000000000331357706137100171000ustar00rootroot00000000000000import sys print(sys.argv) micropython-1.12/tests/io/builtin_print_file.py000066400000000000000000000005011357706137100220220ustar00rootroot00000000000000# test builtin print function, using file= argument import sys try: sys.stdout except AttributeError: print('SKIP') raise SystemExit print(file=sys.stdout) print('test', file=sys.stdout) try: print(file=1) except (AttributeError, OSError): # CPython and uPy differ in error message print('Error') micropython-1.12/tests/io/data/000077500000000000000000000000001357706137100165045ustar00rootroot00000000000000micropython-1.12/tests/io/data/bigfile1000066400000000000000000000135461357706137100201220ustar00rootroot00000000000000{ "info": { "maintainer": null, "docs_url": "", "requires_python": null, "maintainer_email": null, "cheesecake_code_kwalitee_id": null, "keywords": null, "package_url": "http://pypi.python.org/pypi/micropython-uasyncio", "author": "MicroPython Developers", "author_email": "micro-python@googlegroups.com", "download_url": "UNKNOWN", "platform": "UNKNOWN", "version": "0.8.1", "cheesecake_documentation_id": null, "_pypi_hidden": false, "description": "Lightweight asyncio-like library built around native Python coroutines, not around un-Python devices like callback mess.", "release_url": "http://pypi.python.org/pypi/micropython-uasyncio/0.8.1", "downloads": { "last_month": 942, "last_week": 173, "last_day": 29 }, "_pypi_ordering": 6, "classifiers": [], "name": "micropython-uasyncio", "bugtrack_url": null, "license": "MIT", "summary": "uasyncio module for MicroPython", "home_page": "https://github.com/micropython/micropython/issues/405", "stable_version": null, "cheesecake_installability_id": null }, "releases": { "0.8": [ { "has_sig": false, "upload_time": "2015-01-01T23:52:41", "comment_text": "", "python_version": "source", "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.tar.gz", "md5_digest": "5df4d0d6b5fdb7c05fc418e5785e1336", "downloads": 352, "filename": "micropython-uasyncio-0.8.tar.gz", "packagetype": "sdist", "size": 2476 } ], "0.6.2": [ { "has_sig": false, "upload_time": "2014-10-18T11:26:52", "comment_text": "", "python_version": "source", "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.2.tar.gz", "md5_digest": "c85fa7c11ef437f4e73c1fcd639db066", "downloads": 475, "filename": "micropython-uasyncio-0.6.2.tar.gz", "packagetype": "sdist", "size": 3262 } ], "0.6.1": [ { "has_sig": false, "upload_time": "2014-10-11T02:21:17", "comment_text": "", "python_version": "source", "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.1.tar.gz", "md5_digest": "48cb0db7d8249d5f4a86db9c4b302d03", "downloads": 507, "filename": "micropython-uasyncio-0.6.1.tar.gz", "packagetype": "sdist", "size": 3237 } ], "0.8.1": [ { "has_sig": false, "upload_time": "2015-01-04T20:02:03", "comment_text": "", "python_version": "source", "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.1.tar.gz", "md5_digest": "940d2647b8355289d54de543ff710b05", "downloads": 249, "filename": "micropython-uasyncio-0.8.1.tar.gz", "packagetype": "sdist", "size": 2484 } ], "0.7": [ { "has_sig": false, "upload_time": "2014-10-23T22:02:11", "comment_text": "", "python_version": "source", "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.7.tar.gz", "md5_digest": "81250a0ee6649b5117878d5788ba96d3", "downloads": 457, "filename": "micropython-uasyncio-0.7.tar.gz", "packagetype": "sdist", "size": 2277 } ], "0.7.1": [ { "has_sig": false, "upload_time": "2014-11-04T00:56:16", "comment_text": "", "python_version": "source", "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.7.1.tar.gz", "md5_digest": "21eda0501142830730cd82e1b0fa1a33", "downloads": 412, "filename": "micropython-uasyncio-0.7.1.tar.gz", "packagetype": "sdist", "size": 2474 } ], "0.6": [ { "has_sig": false, "upload_time": "2014-08-27T00:17:45", "comment_text": "", "python_version": "source", "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.tar.gz", "md5_digest": "9d0b15108c5ade3a6902c9370c9dacf1", "downloads": 668, "filename": "micropython-uasyncio-0.6.tar.gz", "packagetype": "sdist", "size": 3246 } ] }, "urls": [ { "has_sig": false, "upload_time": "2015-01-04T20:02:03", "comment_text": "", "python_version": "source", "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.1.tar.gz", "md5_digest": "940d2647b8355289d54de543ff710b05", "downloads": 249, "filename": "micropython-uasyncio-0.8.1.tar.gz", "packagetype": "sdist", "size": 2484 } ] }micropython-1.12/tests/io/data/file1000066400000000000000000000000311357706137100174210ustar00rootroot00000000000000longer line1 line2 line3 micropython-1.12/tests/io/data/file2000066400000000000000000000000041357706137100174220ustar00rootroot000000000000001234micropython-1.12/tests/io/file1.py000066400000000000000000000015071357706137100171500ustar00rootroot00000000000000f = open("io/data/file1") print(f.read(5)) print(f.readline()) print(f.read()) f = open("io/data/file1") print(f.readlines()) f = open("io/data/file1","r") print(f.readlines()) f = open("io/data/file1","rb") print(f.readlines()) f = open("io/data/file1",mode="r") print(f.readlines()) f = open("io/data/file1",mode="rb") print(f.readlines()) # write() error f = open('io/data/file1', 'r') try: f.write('x') except OSError: print('OSError') f.close() # read(n) error on binary file f = open('io/data/file1', 'ab') try: f.read(1) except OSError: print('OSError') f.close() # read(n) error on text file f = open('io/data/file1', 'at') try: f.read(1) except OSError: print('OSError') f.close() # read() w/o args error f = open('io/data/file1', 'ab') try: f.read() except OSError: print('OSError') f.close() micropython-1.12/tests/io/file_iter.py000066400000000000000000000000631357706137100201060ustar00rootroot00000000000000f = open("io/data/file1") for l in f: print(l) micropython-1.12/tests/io/file_long_read.py000066400000000000000000000000701357706137100210730ustar00rootroot00000000000000f = open("io/data/file1") b = f.read(100) print(len(b)) micropython-1.12/tests/io/file_long_read2.py000066400000000000000000000001011357706137100211500ustar00rootroot00000000000000f = open("io/data/bigfile1") b = f.read() print(len(b)) print(b) micropython-1.12/tests/io/file_long_read3.py000066400000000000000000000001121357706137100211530ustar00rootroot00000000000000f = open("io/data/bigfile1", "rb") b = f.read(512) print(len(b)) print(b) micropython-1.12/tests/io/file_readinto.py000066400000000000000000000004241357706137100207510ustar00rootroot00000000000000b = bytearray(30) f = open("io/data/file1", "rb") print(f.readinto(b)) print(b) f = open("io/data/file2", "rb") print(f.readinto(b)) print(b) # readinto() on writable file f = open('io/data/file1', 'ab') try: f.readinto(bytearray(4)) except OSError: print('OSError') micropython-1.12/tests/io/file_readinto_len.py000066400000000000000000000003311357706137100216040ustar00rootroot00000000000000b = bytearray(30) f = open("io/data/file1", "rb") # 2nd arg (length to read) is extension to CPython print(f.readinto(b, 8)) print(b) b = bytearray(4) f = open("io/data/file1", "rb") print(f.readinto(b, 8)) print(b) micropython-1.12/tests/io/file_readinto_len.py.exp000066400000000000000000000002061357706137100224000ustar00rootroot000000000000008 bytearray(b'longer l\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') 4 bytearray(b'long') micropython-1.12/tests/io/file_readline.py000066400000000000000000000004051357706137100207260ustar00rootroot00000000000000f = open("io/data/file1") print(f.readline()) print(f.readline(3)) print(f.readline(4)) print(f.readline(5)) print(f.readline()) # readline() on writable file f = open('io/data/file1', 'ab') try: f.readline() except OSError: print('OSError') f.close() micropython-1.12/tests/io/file_seek.py000066400000000000000000000010601357706137100200700ustar00rootroot00000000000000f = open("io/data/file1", "rb") print(f.seek(6)) print(f.read(5)) print(f.tell()) print(f.seek(0, 1)) print(f.read(4)) print(f.tell()) print(f.seek(-6, 2)) print(f.read(20)) print(f.tell()) print(f.seek(0, 0)) print(f.read(5)) print(f.tell()) f.close() # test text mode f = open("io/data/file1", "rt") print(f.seek(6)) print(f.read(5)) print(f.tell()) f.close() # seek closed file f = open('io/data/file1', 'r') f.close() try: f.seek(1) except (OSError, ValueError): # CPy raises ValueError, uPy raises OSError print('OSError or ValueError') micropython-1.12/tests/io/file_stdio.py000066400000000000000000000001011357706137100202560ustar00rootroot00000000000000import sys print(sys.stdin.fileno()) print(sys.stdout.fileno()) micropython-1.12/tests/io/file_with.py000066400000000000000000000006661357706137100201270ustar00rootroot00000000000000f = open("io/data/file1") with f as f2: print(f2.read()) # File should be closed try: f.read() except: # Note: CPython and us throw different exception trying to read from # close file. print("can't read file after with") # Regression test: test that exception in with initialization properly # thrown and doesn't crash. try: with open('__non_existent', 'r'): pass except OSError: print("OSError") micropython-1.12/tests/io/open_append.py000066400000000000000000000007771357706137100204500ustar00rootroot00000000000000try: import uos as os except ImportError: import os if not hasattr(os, "remove"): print("SKIP") raise SystemExit # cleanup in case testfile exists try: os.remove("testfile") except OSError: pass # Should create a file f = open("testfile", "a") f.write("foo") f.close() f = open("testfile") print(f.read()) f.close() f = open("testfile", "a") f.write("bar") f.close() f = open("testfile") print(f.read()) f.close() # cleanup try: os.remove("testfile") except OSError: pass micropython-1.12/tests/io/open_plus.py000066400000000000000000000013401357706137100201470ustar00rootroot00000000000000try: import uos as os except ImportError: import os if not hasattr(os, "remove"): print("SKIP") raise SystemExit # cleanup in case testfile exists try: os.remove("testfile") except OSError: pass try: f = open("testfile", "r+b") print("Unexpectedly opened non-existing file") except OSError: print("Expected OSError") pass f = open("testfile", "w+b") f.write(b"1234567890") f.seek(0) print(f.read()) f.close() # Open with truncation f = open("testfile", "w+b") f.write(b"abcdefg") f.seek(0) print(f.read()) f.close() # Open without truncation f = open("testfile", "r+b") f.write(b"1234") f.seek(0) print(f.read()) f.close() # cleanup try: os.remove("testfile") except OSError: pass micropython-1.12/tests/io/resource_stream.py000066400000000000000000000005171357706137100213520ustar00rootroot00000000000000import uio import sys try: uio.resource_stream except AttributeError: print('SKIP') raise SystemExit buf = uio.resource_stream("data", "file2") print(buf.read()) # resource_stream(None, ...) look ups from current dir, hence sys.path[0] hack buf = uio.resource_stream(None, sys.path[0] + "/data/file2") print(buf.read()) micropython-1.12/tests/io/resource_stream.py.exp000066400000000000000000000000121357706137100221330ustar00rootroot000000000000001234 1234 micropython-1.12/tests/jni/000077500000000000000000000000001357706137100157445ustar00rootroot00000000000000micropython-1.12/tests/jni/README000066400000000000000000000011041357706137100166200ustar00rootroot00000000000000Running "jni" module tests (as well as just using this module) requires being able to load libjvm.so, which requires path to it set via LD_LIBRARY_PATH environment variable. This path is not set automatically and there is no easy way to guess it, because there can be installed different implementations of JVM, for one implementation, there can be different versions, and single version may include different variants of JVM. For example, for OpenJDK 7 on x86_64, following may work: LD_LIBRARY_PATH=/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server ./run-tests jni/*.py micropython-1.12/tests/jni/list.py000066400000000000000000000003221357706137100172660ustar00rootroot00000000000000import jni try: ArrayList = jni.cls("java/util/ArrayList") except: print("SKIP") raise SystemExit l = ArrayList() print(l) l.add("one") l.add("two") print(l.toString()) print(l) print(l[0], l[1]) micropython-1.12/tests/jni/list.py.exp000066400000000000000000000000411357706137100200570ustar00rootroot00000000000000[] [one, two] [one, two] one two micropython-1.12/tests/jni/object.py000066400000000000000000000004301357706137100175610ustar00rootroot00000000000000import jni try: Integer = jni.cls("java/lang/Integer") except: print("SKIP") raise SystemExit # Create object i = Integer(42) print(i) # Call object method print(i.hashCode()) # Pass object to another method System = jni.cls("java/lang/System") System.out.println(i) micropython-1.12/tests/jni/object.py.exp000066400000000000000000000000111357706137100203470ustar00rootroot0000000000000042 42 42 micropython-1.12/tests/jni/system_out.py000066400000000000000000000002201357706137100205230ustar00rootroot00000000000000try: import jni System = jni.cls("java/lang/System") except: print("SKIP") raise SystemExit System.out.println("Hello, Java!") micropython-1.12/tests/jni/system_out.py.exp000066400000000000000000000000151357706137100213200ustar00rootroot00000000000000Hello, Java! micropython-1.12/tests/micropython/000077500000000000000000000000001357706137100175375ustar00rootroot00000000000000micropython-1.12/tests/micropython/const.py000066400000000000000000000004561357706137100212440ustar00rootroot00000000000000# test constant optimisation from micropython import const X = const(123) Y = const(X + 456) print(X, Y + 1) def f(): print(X, Y + 1) f() _X = const(12) _Y = const(_X + 34) print(_X, _Y) class A: Z = const(1) _Z = const(2) print(Z, _Z) print(hasattr(A, 'Z'), hasattr(A, '_Z')) micropython-1.12/tests/micropython/const.py.exp000066400000000000000000000000451357706137100220310ustar00rootroot00000000000000123 580 123 580 12 46 1 2 True False micropython-1.12/tests/micropython/const2.py000066400000000000000000000011571357706137100213250ustar00rootroot00000000000000# check that consts are not replaced in anything except standalone identifiers from micropython import const X = const(1) Y = const(2) Z = const(3) # import that uses a constant import micropython as X print(globals()['X']) # function name that matches a constant def X(): print('function X', X) globals()['X']() # arguments that match a constant def f(X, *Y, **Z): pass f(1) # class name that matches a constant class X: def f(self): print('class X', X) globals()['X']().f() # constant within a class class A: C1 = const(4) def X(self): print('method X', Y, C1, self.C1) A().X() micropython-1.12/tests/micropython/const2.py.exp000066400000000000000000000000751357706137100221160ustar00rootroot00000000000000 function X 1 class X 1 method X 2 4 4 micropython-1.12/tests/micropython/const_error.py000066400000000000000000000005011357706137100224440ustar00rootroot00000000000000# make sure syntax error works correctly for bad const definition from micropython import const def test_syntax(code): try: exec(code) except SyntaxError: print("SyntaxError") # argument not a constant test_syntax("a = const(x)") # redefined constant test_syntax("A = const(1); A = const(2)") micropython-1.12/tests/micropython/const_error.py.exp000066400000000000000000000000301357706137100232340ustar00rootroot00000000000000SyntaxError SyntaxError micropython-1.12/tests/micropython/const_intbig.py000066400000000000000000000004711357706137100225750ustar00rootroot00000000000000# test constant optimisation, with consts that are bignums from micropython import const # check we can make consts from bignums Z1 = const(0xffffffff) Z2 = const(0xffffffffffffffff) print(hex(Z1), hex(Z2)) # check arithmetic with bignum Z3 = const(Z1 + Z2) Z4 = const((1 << 100) + Z1) print(hex(Z3), hex(Z4)) micropython-1.12/tests/micropython/const_intbig.py.exp000066400000000000000000000001171357706137100233650ustar00rootroot000000000000000xffffffff 0xffffffffffffffff 0x100000000fffffffe 0x100000000000000000ffffffff micropython-1.12/tests/micropython/decorator.py000066400000000000000000000001511357706137100220700ustar00rootroot00000000000000# test micropython-specific decorators @micropython.bytecode def f(): return 'bytecode' print(f()) micropython-1.12/tests/micropython/decorator.py.exp000066400000000000000000000000111357706137100226560ustar00rootroot00000000000000bytecode micropython-1.12/tests/micropython/decorator_error.py000066400000000000000000000004301357706137100233010ustar00rootroot00000000000000# test syntax errors for uPy-specific decorators def test_syntax(code): try: exec(code) except SyntaxError: print("SyntaxError") # invalid micropython decorators test_syntax("@micropython.a\ndef f(): pass") test_syntax("@micropython.a.b\ndef f(): pass") micropython-1.12/tests/micropython/decorator_error.py.exp000066400000000000000000000000301357706137100240700ustar00rootroot00000000000000SyntaxError SyntaxError micropython-1.12/tests/micropython/emg_exc.py000066400000000000000000000012451357706137100215220ustar00rootroot00000000000000# test that emergency exceptions work import micropython import sys try: import uio except ImportError: print("SKIP") raise SystemExit # some ports need to allocate heap for the emg exc try: micropython.alloc_emergency_exception_buf(256) except AttributeError: pass def f(): micropython.heap_lock() try: raise ValueError(1) except ValueError as er: exc = er micropython.heap_unlock() # print the exception buf = uio.StringIO() sys.print_exception(exc, buf) for l in buf.getvalue().split("\n"): if l.startswith(" File "): print(l.split('"')[2]) else: print(l) f() micropython-1.12/tests/micropython/emg_exc.py.exp000066400000000000000000000001021357706137100223040ustar00rootroot00000000000000Traceback (most recent call last): , line 20, in f ValueError: 1 micropython-1.12/tests/micropython/extreme_exc.py000066400000000000000000000053461357706137100224310ustar00rootroot00000000000000# test some extreme cases of allocating exceptions and tracebacks import micropython # Check for stackless build, which can't call functions without # allocating a frame on the heap. try: def stackless(): pass micropython.heap_lock(); stackless(); micropython.heap_unlock() except RuntimeError: print("SKIP") raise SystemExit # some ports need to allocate heap for the emergency exception try: micropython.alloc_emergency_exception_buf(256) except AttributeError: pass def main(): # create an exception with many args while heap is locked # should revert to empty tuple for args micropython.heap_lock() e = Exception(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) micropython.heap_unlock() print(repr(e)) # create an exception with a long formatted error message while heap is locked # should use emergency exception buffer and truncate the message def f(): pass micropython.heap_lock() try: f(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=1) except Exception as er: e = er micropython.heap_unlock() print(repr(e)[:10]) # create an exception with a long formatted error message while heap is low # should use the heap and truncate the message lst = [] while 1: try: lst = [lst] except MemoryError: break try: f(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=1) except Exception as er: e = er lst[0] = None lst = None print(repr(e)[:10]) # raise a deep exception with the heap locked # should use emergency exception and be unable to resize traceback array def g(): g() micropython.heap_lock() try: g() except Exception as er: e = er micropython.heap_unlock() print(repr(e)[:13]) # create an exception on the heap with some traceback on the heap, but then # raise it with the heap locked so it can't allocate any more traceback exc = Exception('my exception') try: raise exc except: pass def h(e): raise e micropython.heap_lock() try: h(exc) except Exception as er: e = er micropython.heap_unlock() print(repr(e)) main() micropython-1.12/tests/micropython/extreme_exc.py.exp000066400000000000000000000001131357706137100232070ustar00rootroot00000000000000Exception() TypeError( TypeError( RuntimeError( Exception('my exception',) micropython-1.12/tests/micropython/heap_lock.py000066400000000000000000000006251357706137100220410ustar00rootroot00000000000000# check that heap_lock/heap_unlock work as expected import micropython l = [] l2 = list(range(100)) micropython.heap_lock() # general allocation on the heap try: print([]) except MemoryError: print('MemoryError') # expansion of a heap block try: l.extend(l2) except MemoryError: print('MemoryError') micropython.heap_unlock() # check that allocation works after an unlock print([]) micropython-1.12/tests/micropython/heap_lock.py.exp000066400000000000000000000000331357706137100226250ustar00rootroot00000000000000MemoryError MemoryError [] micropython-1.12/tests/micropython/heapalloc.py000066400000000000000000000020601357706137100220370ustar00rootroot00000000000000# check that we can do certain things without allocating heap memory import micropython # Check for stackless build, which can't call functions without # allocating a frame on heap. try: def stackless(): pass micropython.heap_lock(); stackless(); micropython.heap_unlock() except RuntimeError: print("SKIP") raise SystemExit def f1(a): print(a) def f2(a, b=2): print(a, b) def f3(a, b, c, d): x1 = x2 = a x3 = x4 = b x5 = x6 = c x7 = x8 = d print(x1, x3, x5, x7, x2 + x4 + x6 + x8) global_var = 1 def test(): global global_var, global_exc global_var = 2 # set an existing global variable for i in range(2): # for loop f1(i) # function call f1(i * 2 + 1) # binary operation with small ints f1(a=i) # keyword arguments f2(i) # default arg (second one) f2(i, i) # 2 args f3(1, 2, 3, 4) # function with lots of local state # call test() with heap allocation disabled micropython.heap_lock() test() micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc.py.exp000066400000000000000000000000471357706137100226350ustar00rootroot000000000000000 1 0 0 2 0 0 1 3 1 1 2 1 1 1 2 3 4 10 micropython-1.12/tests/micropython/heapalloc_bytesio.py000066400000000000000000000003521357706137100235770ustar00rootroot00000000000000try: import uio except ImportError: print("SKIP") raise SystemExit import micropython data = b"1234" * 16 buf = uio.BytesIO(64) micropython.heap_lock() buf.write(data) micropython.heap_unlock() print(buf.getvalue()) micropython-1.12/tests/micropython/heapalloc_bytesio.py.exp000066400000000000000000000001041357706137100243650ustar00rootroot00000000000000b'1234123412341234123412341234123412341234123412341234123412341234' micropython-1.12/tests/micropython/heapalloc_bytesio2.py000066400000000000000000000005741357706137100236670ustar00rootroot00000000000000# Creating BytesIO from immutable object should not immediately # copy its content. try: import uio import micropython micropython.mem_total except (ImportError, AttributeError): print("SKIP") raise SystemExit data = b"1234" * 256 before = micropython.mem_total() buf = uio.BytesIO(data) after = micropython.mem_total() print(after - before < len(data)) micropython-1.12/tests/micropython/heapalloc_bytesio2.py.exp000066400000000000000000000000051357706137100244470ustar00rootroot00000000000000True micropython-1.12/tests/micropython/heapalloc_exc_raise.py000066400000000000000000000012351357706137100240640ustar00rootroot00000000000000# Test that we can raise and catch (preallocated) exception # without memory allocation. import micropython e = ValueError("error") def func(): micropython.heap_lock() try: # This works as is because traceback is not allocated # if not possible (heap is locked, no memory). If heap # is not locked, this would allocate a traceback entry. # To avoid that, traceback should be warmed up (by raising # it once after creation) and then cleared before each # raise with: # e.__traceback__ = None raise e except Exception as e2: print(e2) micropython.heap_unlock() func() print("ok") micropython-1.12/tests/micropython/heapalloc_exc_raise.py.exp000066400000000000000000000000111357706137100246460ustar00rootroot00000000000000error ok micropython-1.12/tests/micropython/heapalloc_fail_bytearray.py000066400000000000000000000034301357706137100251160ustar00rootroot00000000000000# test handling of failed heap allocation with bytearray import micropython class GetSlice: def __getitem__(self, idx): return idx sl = GetSlice()[:] # create bytearray micropython.heap_lock() try: bytearray(4) except MemoryError: print('MemoryError: bytearray create') micropython.heap_unlock() # create bytearray from bytes micropython.heap_lock() try: bytearray(b'0123') except MemoryError: print('MemoryError: bytearray create from bytes') micropython.heap_unlock() # create bytearray from iterator r = range(4) micropython.heap_lock() try: bytearray(r) except MemoryError: print('MemoryError: bytearray create from iter') micropython.heap_unlock() # bytearray add b = bytearray(4) micropython.heap_lock() try: b + b'01' except MemoryError: print('MemoryError: bytearray.__add__') micropython.heap_unlock() # bytearray iadd b = bytearray(4) micropython.heap_lock() try: b += b'01234567' except MemoryError: print('MemoryError: bytearray.__iadd__') micropython.heap_unlock() print(b) # bytearray append b = bytearray(4) micropython.heap_lock() try: for i in range(100): b.append(1) except MemoryError: print('MemoryError: bytearray.append') micropython.heap_unlock() # bytearray extend b = bytearray(4) micropython.heap_lock() try: b.extend(b'01234567') except MemoryError: print('MemoryError: bytearray.extend') micropython.heap_unlock() # bytearray get with slice b = bytearray(4) micropython.heap_lock() try: b[sl] except MemoryError: print('MemoryError: bytearray subscr get') micropython.heap_unlock() # extend bytearray using slice subscr b = bytearray(4) micropython.heap_lock() try: b[sl] = b'01234567' except MemoryError: print('MemoryError: bytearray subscr grow') micropython.heap_unlock() print(b) micropython-1.12/tests/micropython/heapalloc_fail_bytearray.py.exp000066400000000000000000000005551357706137100257160ustar00rootroot00000000000000MemoryError: bytearray create MemoryError: bytearray create from bytes MemoryError: bytearray create from iter MemoryError: bytearray.__add__ MemoryError: bytearray.__iadd__ bytearray(b'\x00\x00\x00\x00') MemoryError: bytearray.append MemoryError: bytearray.extend MemoryError: bytearray subscr get MemoryError: bytearray subscr grow bytearray(b'\x00\x00\x00\x00') micropython-1.12/tests/micropython/heapalloc_fail_dict.py000066400000000000000000000005641357706137100240440ustar00rootroot00000000000000# test handling of failed heap allocation with dict import micropython # create dict x = 1 micropython.heap_lock() try: {x:x} except MemoryError: print('MemoryError: create dict') micropython.heap_unlock() # create dict view x = {1:1} micropython.heap_lock() try: x.items() except MemoryError: print('MemoryError: dict.items') micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc_fail_dict.py.exp000066400000000000000000000000611357706137100246270ustar00rootroot00000000000000MemoryError: create dict MemoryError: dict.items micropython-1.12/tests/micropython/heapalloc_fail_list.py000066400000000000000000000012731357706137100240720ustar00rootroot00000000000000# test handling of failed heap allocation with list import micropython class GetSlice: def __getitem__(self, idx): return idx sl = GetSlice()[:] # create slice in VM l = [1, 2, 3] micropython.heap_lock() try: print(l[0:1]) except MemoryError: print('MemoryError: list index') micropython.heap_unlock() # get from list using slice micropython.heap_lock() try: l[sl] except MemoryError: print('MemoryError: list get slice') micropython.heap_unlock() # extend list using slice subscr l = [1, 2] l2 = [3, 4, 5, 6, 7, 8, 9, 10] micropython.heap_lock() try: l[sl] = l2 except MemoryError: print('MemoryError: list extend slice') micropython.heap_unlock() print(l) micropython-1.12/tests/micropython/heapalloc_fail_list.py.exp000066400000000000000000000001321357706137100246560ustar00rootroot00000000000000MemoryError: list index MemoryError: list get slice MemoryError: list extend slice [1, 2] micropython-1.12/tests/micropython/heapalloc_fail_memoryview.py000066400000000000000000000007731357706137100253260ustar00rootroot00000000000000# test handling of failed heap allocation with memoryview import micropython class GetSlice: def __getitem__(self, idx): return idx sl = GetSlice()[:] # create memoryview micropython.heap_lock() try: memoryview(b'') except MemoryError: print('MemoryError: memoryview create') micropython.heap_unlock() # memoryview get with slice m = memoryview(b'') micropython.heap_lock() try: m[sl] except MemoryError: print('MemoryError: memoryview subscr get') micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc_fail_memoryview.py.exp000066400000000000000000000001021357706137100261030ustar00rootroot00000000000000MemoryError: memoryview create MemoryError: memoryview subscr get micropython-1.12/tests/micropython/heapalloc_fail_set.py000066400000000000000000000005461357706137100237140ustar00rootroot00000000000000# test handling of failed heap allocation with set import micropython # create set x = 1 micropython.heap_lock() try: {x,} except MemoryError: print('MemoryError: set create') micropython.heap_unlock() # set copy s = {1, 2} micropython.heap_lock() try: s.copy() except MemoryError: print('MemoryError: set copy') micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc_fail_set.py.exp000066400000000000000000000000561357706137100245030ustar00rootroot00000000000000MemoryError: set create MemoryError: set copy micropython-1.12/tests/micropython/heapalloc_fail_tuple.py000066400000000000000000000003321357706137100242430ustar00rootroot00000000000000# test handling of failed heap allocation with tuple import micropython # create tuple x = 1 micropython.heap_lock() try: (x,) except MemoryError: print('MemoryError: tuple create') micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc_fail_tuple.py.exp000066400000000000000000000000321357706137100250330ustar00rootroot00000000000000MemoryError: tuple create micropython-1.12/tests/micropython/heapalloc_inst_call.py000066400000000000000000000010371357706137100240720ustar00rootroot00000000000000# Test that calling clazz.__call__() with up to at least 3 arguments # doesn't require heap allocation. import micropython class Foo0: def __call__(self): print("__call__") class Foo1: def __call__(self, a): print("__call__", a) class Foo2: def __call__(self, a, b): print("__call__", a, b) class Foo3: def __call__(self, a, b, c): print("__call__", a, b, c) f0 = Foo0() f1 = Foo1() f2 = Foo2() f3 = Foo3() micropython.heap_lock() f0() f1(1) f2(1, 2) f3(1, 2, 3) micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc_inst_call.py.exp000066400000000000000000000000601357706137100246600ustar00rootroot00000000000000__call__ __call__ 1 __call__ 1 2 __call__ 1 2 3 micropython-1.12/tests/micropython/heapalloc_int_from_bytes.py000066400000000000000000000004631357706137100251470ustar00rootroot00000000000000# Test that int.from_bytes() for small number of bytes generates # small int. import micropython micropython.heap_lock() print(int.from_bytes(b"1", "little")) print(int.from_bytes(b"12", "little")) print(int.from_bytes(b"2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "little")) micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc_int_from_bytes.py.exp000066400000000000000000000000141357706137100257320ustar00rootroot0000000000000049 12849 50 micropython-1.12/tests/micropython/heapalloc_iter.py000066400000000000000000000026601357706137100230700ustar00rootroot00000000000000# test that iterating doesn't use the heap try: frozenset except NameError: print("SKIP") raise SystemExit try: import uarray as array except ImportError: try: import array except ImportError: print("SKIP") raise SystemExit try: from micropython import heap_lock, heap_unlock except (ImportError, AttributeError): heap_lock = heap_unlock = lambda:0 def do_iter(l): heap_lock() for i in l: print(i) heap_unlock() def gen_func(): yield 1 yield 2 # pre-create collections to iterate over ba = bytearray(b'123') ar = array.array('H', (123, 456)) t = (1, 2, 3) l = [1, 2] d = {1:2} s = set((1,)) fs = frozenset((1,)) g1 = (100 + x for x in range(2)) g2 = gen_func() # test containment (both success and failure) with the heap locked heap_lock() print(49 in b'123', 255 in b'123') print(1 in t, -1 in t) print(1 in l, -1 in l) print(1 in d, -1 in d) print(1 in s, -1 in s) heap_unlock() # test unpacking with the heap locked unp0 = unp1 = unp2 = None # preallocate slots for globals heap_lock() unp0, unp1, unp2 = t print(unp0, unp1, unp2) heap_unlock() # test certain builtins with the heap locked heap_lock() print(all(t)) print(any(t)) print(min(t)) print(max(t)) print(sum(t)) heap_unlock() # test iterating over collections with the heap locked do_iter(b'123') do_iter(ba) do_iter(ar) do_iter(t) do_iter(l) do_iter(d) do_iter(s) do_iter(fs) do_iter(g1) do_iter(g2) micropython-1.12/tests/micropython/heapalloc_str.py000066400000000000000000000004671357706137100227400ustar00rootroot00000000000000# String operations which don't require allocation import micropython micropython.heap_lock() # Concatenating empty string returns original string b"" + b"" b"" + b"1" b"2" + b"" "" + "" "" + "1" "2" + "" # If no replacements done, returns original string "foo".replace(",", "_") micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc_str.py.exp000066400000000000000000000000001357706137100235120ustar00rootroot00000000000000micropython-1.12/tests/micropython/heapalloc_super.py000066400000000000000000000010471357706137100232610ustar00rootroot00000000000000# test super() operations which don't require allocation import micropython # Check for stackless build, which can't call functions without # allocating a frame on heap. try: def stackless(): pass micropython.heap_lock(); stackless(); micropython.heap_unlock() except RuntimeError: print("SKIP") raise SystemExit class A: def foo(self): print('A foo') return 42 class B(A): def foo(self): print('B foo') print(super().foo()) b = B() micropython.heap_lock() b.foo() micropython.heap_unlock() micropython-1.12/tests/micropython/heapalloc_super.py.exp000066400000000000000000000000171357706137100240500ustar00rootroot00000000000000B foo A foo 42 micropython-1.12/tests/micropython/heapalloc_traceback.py000066400000000000000000000015671357706137100240510ustar00rootroot00000000000000# test that we can generate a traceback without allocating import micropython import sys try: import uio except ImportError: print("SKIP") raise SystemExit # preallocate exception instance with some room for a traceback global_exc = StopIteration() try: raise global_exc except: pass def test(): micropython.heap_lock() global global_exc global_exc.__traceback__ = None try: raise global_exc except StopIteration: print('StopIteration') micropython.heap_unlock() # call test() with heap allocation disabled test() # print the exception that was raised buf = uio.StringIO() sys.print_exception(global_exc, buf) for l in buf.getvalue().split("\n"): # uPy on pyboard prints as file, so remove filename. if l.startswith(" File "): l = l.split('"') print(l[0], l[2]) else: print(l) micropython-1.12/tests/micropython/heapalloc_traceback.py.exp000066400000000000000000000001351357706137100246320ustar00rootroot00000000000000StopIteration Traceback (most recent call last): File , line 23, in test StopIteration: micropython-1.12/tests/micropython/kbd_intr.py000066400000000000000000000003321357706137100217030ustar00rootroot00000000000000# test the micropython.kbd_intr() function import micropython try: micropython.kbd_intr except AttributeError: print('SKIP') raise SystemExit # just check we can actually call it micropython.kbd_intr(3) micropython-1.12/tests/micropython/kbd_intr.py.exp000066400000000000000000000000001357706137100224660ustar00rootroot00000000000000micropython-1.12/tests/micropython/meminfo.py000066400000000000000000000004411357706137100215420ustar00rootroot00000000000000# tests meminfo functions in micropython module import micropython # these functions are not always available if not hasattr(micropython, 'mem_info'): print('SKIP') else: micropython.mem_info() micropython.mem_info(1) micropython.qstr_info() micropython.qstr_info(1) micropython-1.12/tests/micropython/meminfo.py.exp000066400000000000000000000011331357706137100223340ustar00rootroot00000000000000mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ GC: total: \\d\+, used: \\d\+, free: \\d\+ No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ mem: total=\\d\+, current=\\d\+, peak=\\d\+ stack: \\d\+ out of \\d\+ GC: total: \\d\+, used: \\d\+, free: \\d\+ No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ GC memory layout; from \[0-9a-f\]\+: ######## qstr pool: n_pool=1, n_qstr=\\d, n_str_data_bytes=\\d\+, n_total_bytes=\\d\+ qstr pool: n_pool=1, n_qstr=\\d, n_str_data_bytes=\\d\+, n_total_bytes=\\d\+ ######## Q(SKIP) micropython-1.12/tests/micropython/memstats.py000066400000000000000000000006461357706137100217540ustar00rootroot00000000000000# tests meminfo functions in micropython module import micropython # these functions are not always available if not hasattr(micropython, 'mem_total'): print('SKIP') else: t = micropython.mem_total() c = micropython.mem_current() p = micropython.mem_peak() l = list(range(10000)) print(micropython.mem_total() > t) print(micropython.mem_current() > c) print(micropython.mem_peak() > p) micropython-1.12/tests/micropython/memstats.py.exp000066400000000000000000000000171357706137100225370ustar00rootroot00000000000000True True True micropython-1.12/tests/micropython/native_closure.py000066400000000000000000000010431357706137100231310ustar00rootroot00000000000000# test native emitter can handle closures correctly # basic closure @micropython.native def f(): x = 1 @micropython.native def g(): nonlocal x return x return g print(f()()) # closing over an argument @micropython.native def f(x): @micropython.native def g(): nonlocal x return x return g print(f(2)()) # closing over an argument and a normal local @micropython.native def f(x): y = 2 * x @micropython.native def g(z): return x + y + z return g print(f(2)(3)) micropython-1.12/tests/micropython/native_closure.py.exp000066400000000000000000000000061357706137100237220ustar00rootroot000000000000001 2 9 micropython-1.12/tests/micropython/native_const.py000066400000000000000000000003321357706137100226030ustar00rootroot00000000000000# test loading constants in native functions @micropython.native def f(): return b'bytes' print(f()) @micropython.native def f(): @micropython.native def g(): return 123 return g print(f()()) micropython-1.12/tests/micropython/native_const.py.exp000066400000000000000000000000151357706137100233740ustar00rootroot00000000000000b'bytes' 123 micropython-1.12/tests/micropython/native_const_intbig.py000066400000000000000000000001561357706137100241430ustar00rootroot00000000000000# check loading constants @micropython.native def f(): return 123456789012345678901234567890 print(f()) micropython-1.12/tests/micropython/native_const_intbig.py.exp000066400000000000000000000000371357706137100247340ustar00rootroot00000000000000123456789012345678901234567890 micropython-1.12/tests/micropython/native_gen.py000066400000000000000000000005421357706137100222310ustar00rootroot00000000000000# test for native generators # simple generator with yield and return @micropython.native def gen1(x): yield x yield x + 1 return x + 2 g = gen1(3) print(next(g)) print(next(g)) try: next(g) except StopIteration as e: print(e.args[0]) # using yield from @micropython.native def gen2(x): yield from range(x) print(list(gen2(3))) micropython-1.12/tests/micropython/native_gen.py.exp000066400000000000000000000000201357706137100230130ustar00rootroot000000000000003 4 5 [0, 1, 2] micropython-1.12/tests/micropython/native_misc.py000066400000000000000000000007341357706137100224160ustar00rootroot00000000000000# tests for natively compiled functions # basic test @micropython.native def native_test(x): print(1, [], x) native_test(2) # check that GC doesn't collect the native function import gc gc.collect() native_test(3) # native with 2 args @micropython.native def f(a, b): print(a + b) f(1, 2) # native with 3 args @micropython.native def f(a, b, c): print(a + b + c) f(1, 2, 3) # check not operator @micropython.native def f(a): print(not a) f(False) f(True) micropython-1.12/tests/micropython/native_misc.py.exp000066400000000000000000000000351357706137100232030ustar00rootroot000000000000001 [] 2 1 [] 3 3 6 True False micropython-1.12/tests/micropython/native_try.py000066400000000000000000000011641357706137100222770ustar00rootroot00000000000000# test native try handling # basic try-finally @micropython.native def f(): try: fail finally: print('finally') try: f() except NameError: print('NameError') # nested try-except with try-finally @micropython.native def f(): try: try: fail finally: print('finally') except NameError: print('NameError') f() # check that locals written to in try blocks keep their values @micropython.native def f(): a = 100 try: print(a) a = 200 fail except NameError: print(a) a = 300 print(a) f() micropython-1.12/tests/micropython/native_try.py.exp000066400000000000000000000000601357706137100230640ustar00rootroot00000000000000finally NameError finally NameError 100 200 300 micropython-1.12/tests/micropython/native_try_deep.py000066400000000000000000000016671357706137100233040ustar00rootroot00000000000000# test native try handling # deeply nested try (9 deep) @micropython.native def f(): try: try: try: try: try: try: try: try: try: raise ValueError finally: print(8) finally: print(7) finally: print(6) finally: print(5) finally: print(4) finally: print(3) finally: print(2) finally: print(1) except ValueError: print('ValueError') f() micropython-1.12/tests/micropython/native_try_deep.py.exp000066400000000000000000000000331357706137100240610ustar00rootroot000000000000008 7 6 5 4 3 2 1 ValueError micropython-1.12/tests/micropython/native_with.py000066400000000000000000000007661357706137100224430ustar00rootroot00000000000000# test with handling within a native function class C: def __init__(self): print('__init__') def __enter__(self): print('__enter__') def __exit__(self, a, b, c): print('__exit__', a, b, c) # basic with @micropython.native def f(): with C(): print(1) f() # nested with and try-except @micropython.native def f(): try: with C(): print(1) fail print(2) except NameError: print('NameError') f() micropython-1.12/tests/micropython/native_with.py.exp000066400000000000000000000002101357706137100232160ustar00rootroot00000000000000__init__ __enter__ 1 __exit__ None None None __init__ __enter__ 1 __exit__ name 'fail' isn't defined None NameError micropython-1.12/tests/micropython/opt_level.py000066400000000000000000000005431357706137100221040ustar00rootroot00000000000000import micropython as micropython # check we can get and set the level micropython.opt_level(0) print(micropython.opt_level()) micropython.opt_level(1) print(micropython.opt_level()) # check that the optimisation levels actually differ micropython.opt_level(0) exec('print(__debug__)') micropython.opt_level(1) exec('print(__debug__)') exec('assert 0') micropython-1.12/tests/micropython/opt_level.py.exp000066400000000000000000000000171357706137100226730ustar00rootroot000000000000000 1 True False micropython-1.12/tests/micropython/opt_level_lineno.py000066400000000000000000000003751357706137100234530ustar00rootroot00000000000000import micropython as micropython # check that level 3 doesn't store line numbers # the expected output is that any line is printed as "line 1" micropython.opt_level(3) exec('try:\n xyz\nexcept NameError as er:\n import sys\n sys.print_exception(er)') micropython-1.12/tests/micropython/opt_level_lineno.py.exp000066400000000000000000000001561357706137100242430ustar00rootroot00000000000000Traceback (most recent call last): File "", line 1, in NameError: name 'xyz' isn't defined micropython-1.12/tests/micropython/schedule.py000066400000000000000000000023631357706137100217110ustar00rootroot00000000000000# test micropython.schedule() function import micropython try: micropython.schedule except AttributeError: print('SKIP') raise SystemExit # Basic test of scheduling a function. def callback(arg): global done print(arg) done = True done = False micropython.schedule(callback, 1) while not done: pass # Test that callbacks can be scheduled from within a callback, but # that they don't execute until the outer callback is finished. def callback_inner(arg): global done print('inner') done += 1 def callback_outer(arg): global done micropython.schedule(callback_inner, 0) # need a loop so that the VM can check for pending events for i in range(2): pass print('outer') done += 1 done = 0 micropython.schedule(callback_outer, 0) while done != 2: pass # Test that scheduling too many callbacks leads to an exception. To do this we # must schedule from within a callback to guarantee that the scheduler is locked. def callback(arg): global done try: for i in range(100): micropython.schedule(lambda x:x, None) except RuntimeError: print('RuntimeError') done = True done = False micropython.schedule(callback, None) while not done: pass micropython-1.12/tests/micropython/schedule.py.exp000066400000000000000000000000331357706137100224740ustar00rootroot000000000000001 outer inner RuntimeError micropython-1.12/tests/micropython/stack_use.py000066400000000000000000000003001357706137100220630ustar00rootroot00000000000000# tests stack_use function in micropython module import micropython if not hasattr(micropython, 'stack_use'): print('SKIP') else: print(type(micropython.stack_use())) # output varies micropython-1.12/tests/micropython/stack_use.py.exp000066400000000000000000000000161357706137100226620ustar00rootroot00000000000000 micropython-1.12/tests/micropython/viper_addr.py000066400000000000000000000013741357706137100222350ustar00rootroot00000000000000# test passing addresses to viper @micropython.viper def get_addr(x:ptr) -> ptr: return x @micropython.viper def memset(dest:ptr8, c:int, n:int): for i in range(n): dest[i] = c @micropython.viper def memsum(src:ptr8, n:int) -> int: s = 0 for i in range(n): s += src[i] return s # create array and get its address ar = bytearray('0000') addr = get_addr(ar) print(type(ar)) print(type(addr)) print(ar) # pass array as an object memset(ar, ord('1'), len(ar)) print(ar) # pass direct pointer to array buffer memset(addr, ord('2'), len(ar)) print(ar) # pass direct pointer to array buffer, with offset memset(addr + 2, ord('3'), len(ar) - 2) print(ar) # pass a read-only bytes object in print(memsum(b'\x01\x02\x03\x04', 4)) micropython-1.12/tests/micropython/viper_addr.py.exp000066400000000000000000000001611357706137100230210ustar00rootroot00000000000000 bytearray(b'0000') bytearray(b'1111') bytearray(b'2222') bytearray(b'2233') 10 micropython-1.12/tests/micropython/viper_args.py000066400000000000000000000014651357706137100222600ustar00rootroot00000000000000# test calling viper functions with different number of args @micropython.viper def f0(): print(0) f0() @micropython.viper def f1(x1:int): print(x1) f1(1) @micropython.viper def f2(x1:int, x2:int): print(x1, x2) f2(1, 2) @micropython.viper def f3(x1:int, x2:int, x3:int): print(x1, x2, x3) f3(1, 2, 3) @micropython.viper def f4(x1:int, x2:int, x3:int, x4:int): print(x1, x2, x3, x4) f4(1, 2, 3, 4) @micropython.viper def f5(x1:int, x2:int, x3:int, x4:int, x5:int): print(x1, x2, x3, x4, x5) f5(1, 2, 3, 4, 5) @micropython.viper def f6(x1:int, x2:int, x3:int, x4:int, x5:int, x6:int): print(x1, x2, x3, x4, x5, x6) f6(1, 2, 3, 4, 5, 6) # test compiling *x, **x, * args (currently unsupported at runtime) @micropython.viper def f(*x, **y): pass @micropython.viper def f(*): pass micropython-1.12/tests/micropython/viper_args.py.exp000066400000000000000000000000541357706137100230440ustar00rootroot000000000000000 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 micropython-1.12/tests/micropython/viper_binop_arith.py000066400000000000000000000016701357706137100236200ustar00rootroot00000000000000# test arithmetic operators @micropython.viper def add(x:int, y:int): print(x + y) print(y + x) add(1, 2) add(42, 3) add(-1, 2) add(-42, -3) @micropython.viper def sub(x:int, y:int): print(x - y) print(y - x) sub(1, 2) sub(42, 3) sub(-1, 2) sub(-42, -3) @micropython.viper def mul(x:int, y:int): print(x * y) print(y * x) mul(0, 1) mul(1, -1) mul(1, 2) mul(8, 3) mul(-3, 4) mul(-9, -6) @micropython.viper def shl(x:int, y:int): print(x << y) shl(1, 0) shl(1, 3) shl(1, 30) shl(42, 10) shl(-42, 10) @micropython.viper def shr(x:int, y:int): print(x >> y) shr(1, 0) shr(1, 3) shr(42, 2) shr(-42, 2) @micropython.viper def and_(x:int, y:int): print(x & y, y & x) and_(1, 0) and_(1, 3) and_(0xf0, 0x3f) and_(-42, 6) @micropython.viper def or_(x:int, y:int): print(x | y, y | x) or_(1, 0) or_(1, 2) or_(-42, 5) @micropython.viper def xor(x:int, y:int): print(x ^ y, y ^ x) xor(1, 0) xor(1, 2) xor(-42, 5) micropython-1.12/tests/micropython/viper_binop_arith.py.exp000066400000000000000000000002511357706137100244050ustar00rootroot000000000000003 3 45 45 1 1 -45 -45 -1 1 39 -39 -3 3 -39 39 0 0 -1 -1 2 2 24 24 -12 -12 54 54 1 8 1073741824 43008 -43008 1 0 10 -11 0 0 1 1 48 48 6 6 1 1 3 3 -41 -41 1 1 3 3 -45 -45 micropython-1.12/tests/micropython/viper_binop_comp.py000066400000000000000000000005411357706137100234430ustar00rootroot00000000000000# test comparison operators @micropython.viper def f(x:int, y:int): if x < y: print(x, "<", y) if x > y: print(x, ">", y) if x == y: print(x, "==", y) if x <= y: print(x, "<=", y) if x >= y: print(x, ">=", y) if x != y: print(x, "!=", y) f(1, 1) f(2, 1) f(1, 2) f(2, -1) f(-2, 1) micropython-1.12/tests/micropython/viper_binop_comp.py.exp000066400000000000000000000001531357706137100242350ustar00rootroot000000000000001 == 1 1 <= 1 1 >= 1 2 > 1 2 >= 1 2 != 1 1 < 2 1 <= 2 1 != 2 2 > -1 2 >= -1 2 != -1 -2 < 1 -2 <= 1 -2 != 1 micropython-1.12/tests/micropython/viper_binop_comp_imm.py000066400000000000000000000002421357706137100243030ustar00rootroot00000000000000# comparisons with immediate boundary values @micropython.viper def f(a: int): print(a == -1, a == -255, a == -256, a == -257) f(-1) f(-255) f(-256) f(-257) micropython-1.12/tests/micropython/viper_binop_comp_imm.py.exp000066400000000000000000000001341357706137100250760ustar00rootroot00000000000000True False False False False True False False False False True False False False False True micropython-1.12/tests/micropython/viper_binop_divmod.py000066400000000000000000000005101357706137100237630ustar00rootroot00000000000000# test floor-division and modulo operators @micropython.viper def div(x:int, y:int) -> int: return x // y @micropython.viper def mod(x:int, y:int) -> int: return x % y def dm(x, y): print(div(x, y), mod(x, y)) for x in (-6, 6): for y in range(-7, 8): if y == 0: continue dm(x, y) micropython-1.12/tests/micropython/viper_binop_divmod.py.exp000066400000000000000000000002041357706137100245560ustar00rootroot000000000000000 -6 1 0 1 -1 1 -2 2 0 3 0 6 0 -6 0 -3 0 -2 0 -2 2 -2 4 -1 0 -1 1 -1 -1 -1 0 -2 -4 -2 -2 -2 0 -3 0 -6 0 6 0 3 0 2 0 1 2 1 1 1 0 0 6 micropython-1.12/tests/micropython/viper_binop_multi_comp.py000066400000000000000000000006041357706137100246550ustar00rootroot00000000000000# test multi comparison operators @micropython.viper def f(x:int, y:int): if 0 < x < y: print(x, "<", y) if 3 > x > y: print(x, ">", y) if 1 == x == y: print(x, "==", y) if -2 == x <= y: print(x, "<=", y) if 2 == x >= y: print(x, ">=", y) if 2 == x != y: print(x, "!=", y) f(1, 1) f(2, 1) f(1, 2) f(2, -1) f(-2, 1) micropython-1.12/tests/micropython/viper_binop_multi_comp.py.exp000066400000000000000000000001001357706137100254370ustar00rootroot000000000000001 == 1 2 > 1 2 >= 1 2 != 1 1 < 2 2 > -1 2 >= -1 2 != -1 -2 <= 1 micropython-1.12/tests/micropython/viper_cond.py000066400000000000000000000007611357706137100222450ustar00rootroot00000000000000# using False as a conditional @micropython.viper def f(): x = False if x: pass else: print("not x", x) f() # using True as a conditional @micropython.viper def f(): x = True if x: print("x", x) f() # using an int as a conditional @micropython.viper def g(): y = 1 if y: print("y", y) g() # using an int as a conditional that has the lower 16-bits clear @micropython.viper def h(): z = 0x10000 if z: print("z", z) h() micropython-1.12/tests/micropython/viper_cond.py.exp000066400000000000000000000000371357706137100230340ustar00rootroot00000000000000not x False x True y 1 z 65536 micropython-1.12/tests/micropython/viper_const.py000066400000000000000000000003351357706137100224450ustar00rootroot00000000000000# test loading constants in viper functions @micropython.viper def f(): return b'bytes' print(f()) @micropython.viper def f(): @micropython.viper def g() -> int: return 123 return g print(f()()) micropython-1.12/tests/micropython/viper_const.py.exp000066400000000000000000000000151357706137100232330ustar00rootroot00000000000000b'bytes' 123 micropython-1.12/tests/micropython/viper_const_intbig.py000066400000000000000000000001551357706137100240010ustar00rootroot00000000000000# check loading constants @micropython.viper def f(): return 123456789012345678901234567890 print(f()) micropython-1.12/tests/micropython/viper_const_intbig.py.exp000066400000000000000000000000371357706137100245730ustar00rootroot00000000000000123456789012345678901234567890 micropython-1.12/tests/micropython/viper_error.py000066400000000000000000000035701357706137100224540ustar00rootroot00000000000000# test syntax and type errors specific to viper code generation def test(code): try: exec(code) except (SyntaxError, ViperTypeError, NotImplementedError) as e: print(repr(e)) # viper: annotations must be identifiers test("@micropython.viper\ndef f(a:1): pass") test("@micropython.viper\ndef f() -> 1: pass") # unknown type test("@micropython.viper\ndef f(x:unknown_type): pass") # local used before type known test(""" @micropython.viper def f(): print(x) x = 1 """) # type mismatch storing to local test(""" @micropython.viper def f(): x = 1 y = [] x = y """) # can't implicitly convert type to bool test(""" @micropython.viper def f(): x = ptr(0) if x: pass """) # incorrect return type test("@micropython.viper\ndef f() -> int: return []") # can't do binary op between incompatible types test("@micropython.viper\ndef f(): 1 + []") # can't load test("@micropython.viper\ndef f(): 1[0]") test("@micropython.viper\ndef f(): 1[x]") # can't store test("@micropython.viper\ndef f(): 1[0] = 1") test("@micropython.viper\ndef f(): 1[x] = 1") test("@micropython.viper\ndef f(x:int): x[0] = x") test("@micropython.viper\ndef f(x:ptr32): x[0] = None") test("@micropython.viper\ndef f(x:ptr32): x[x] = None") # must raise an object test("@micropython.viper\ndef f(): raise 1") # unary ops not implemented test("@micropython.viper\ndef f(x:int): +x") test("@micropython.viper\ndef f(x:int): -x") test("@micropython.viper\ndef f(x:int): ~x") # binary op not implemented test("@micropython.viper\ndef f(x:int): res = x in x") # yield (from) not implemented test("@micropython.viper\ndef f(): yield") test("@micropython.viper\ndef f(): yield from f") # passing a ptr to a Python function not implemented test("@micropython.viper\ndef f(): print(ptr(1))") # cast of a casting identifier not implemented test("@micropython.viper\ndef f(): int(int)") micropython-1.12/tests/micropython/viper_error.py.exp000066400000000000000000000021411357706137100232400ustar00rootroot00000000000000SyntaxError('annotation must be an identifier',) SyntaxError('annotation must be an identifier',) ViperTypeError("unknown type 'unknown_type'",) ViperTypeError("local 'x' used before type known",) ViperTypeError("local 'x' has type 'int' but source is 'object'",) ViperTypeError("can't implicitly convert 'ptr' to 'bool'",) ViperTypeError("return expected 'int' but got 'object'",) ViperTypeError("can't do binary op between 'int' and 'object'",) ViperTypeError("can't load from 'int'",) ViperTypeError("can't load from 'int'",) ViperTypeError("can't store to 'int'",) ViperTypeError("can't store to 'int'",) ViperTypeError("can't store to 'int'",) ViperTypeError("can't store 'None'",) ViperTypeError("can't store 'None'",) ViperTypeError('must raise an object',) ViperTypeError('unary op __pos__ not implemented',) ViperTypeError('unary op __neg__ not implemented',) ViperTypeError('unary op __invert__ not implemented',) ViperTypeError('binary op not implemented',) NotImplementedError('native yield',) NotImplementedError('native yield',) NotImplementedError('conversion to object',) NotImplementedError('casting',) micropython-1.12/tests/micropython/viper_globals.py000066400000000000000000000004751357706137100227470ustar00rootroot00000000000000# test that viper functions capture their globals context gl = {} exec(""" @micropython.viper def f(): return x """, gl) # x is not yet in the globals, f should not see it try: print(gl['f']()) except NameError: print('NameError') # x is in globals, f should now see it gl['x'] = 123 print(gl['f']()) micropython-1.12/tests/micropython/viper_globals.py.exp000066400000000000000000000000161357706137100235310ustar00rootroot00000000000000NameError 123 micropython-1.12/tests/micropython/viper_import.py000066400000000000000000000002631357706137100226310ustar00rootroot00000000000000# test import within viper function @micropython.viper def f(): import micropython print(micropython.const(1)) from micropython import const print(const(2)) f() micropython-1.12/tests/micropython/viper_import.py.exp000066400000000000000000000000041357706137100234150ustar00rootroot000000000000001 2 micropython-1.12/tests/micropython/viper_misc.py000066400000000000000000000047021357706137100222540ustar00rootroot00000000000000import micropython # viper function taking and returning ints @micropython.viper def viper_int(x:int, y:int) -> int: return x + y + 3 print(viper_int(1, 2)) # viper function taking and returning objects @micropython.viper def viper_object(x:object, y:object) -> object: return x + y print(viper_object(1, 2)) # return None as non-object (should return 0) @micropython.viper def viper_ret_none() -> int: return None print(viper_ret_none()) # return Ellipsis as object @micropython.viper def viper_ret_ellipsis() -> object: return ... print(viper_ret_ellipsis()) # 3 args @micropython.viper def viper_3args(a:int, b:int, c:int) -> int: return a + b + c print(viper_3args(1, 2, 3)) # 4 args @micropython.viper def viper_4args(a:int, b:int, c:int, d:int) -> int: return a + b + c + d # viper call with 4 args not yet supported #print(viper_4args(1, 2, 3, 4)) # a local (should have automatic type int) @micropython.viper def viper_local(x:int) -> int: y = 4 return x + y print(viper_local(3)) # without type annotation, types should default to object @micropython.viper def viper_no_annotation(x, y): return x * y print(viper_no_annotation(4, 5)) # a for loop @micropython.viper def viper_for(a:int, b:int) -> int: total = 0 for x in range(a, b): total += x return total print(viper_for(10, 10000)) # accessing a global @micropython.viper def viper_access_global(): global gl gl = 1 return gl print(viper_access_global(), gl) # calling print with object and int types @micropython.viper def viper_print(x, y:int): print(x, y + 1) viper_print(1, 2) # convert constants to objects in tuple @micropython.viper def viper_tuple_consts(x): return (x, 1, False, True) print(viper_tuple_consts(0)) # making a tuple from an object and an int @micropython.viper def viper_tuple(x, y:int): return (x, y + 1) print(viper_tuple(1, 2)) # making a list from an object and an int @micropython.viper def viper_list(x, y:int): return [x, y + 1] print(viper_list(1, 2)) # making a set from an object and an int @micropython.viper def viper_set(x, y:int): return {x, y + 1} print(sorted(list(viper_set(1, 2)))) # raising an exception @micropython.viper def viper_raise(x:int): raise OSError(x) try: viper_raise(1) except OSError as e: print(repr(e)) # calling GC after defining the function @micropython.viper def viper_gc() -> int: return 1 print(viper_gc()) import gc gc.collect() print(viper_gc()) micropython-1.12/tests/micropython/viper_misc.py.exp000066400000000000000000000001401357706137100230370ustar00rootroot000000000000006 3 0 Ellipsis 6 7 20 49994955 1 1 1 3 (0, 1, False, True) (1, 3) [1, 3] [1, 3] OSError(1,) 1 1 micropython-1.12/tests/micropython/viper_misc_intbig.py000066400000000000000000000002361357706137100236060ustar00rootroot00000000000000import micropython # unsigned ints @micropython.viper def viper_uint() -> uint: return uint(-1) import sys print(viper_uint() == (sys.maxsize << 1 | 1)) micropython-1.12/tests/micropython/viper_misc_intbig.py.exp000066400000000000000000000000051357706137100243730ustar00rootroot00000000000000True micropython-1.12/tests/micropython/viper_ptr16_load.py000066400000000000000000000011261357706137100232710ustar00rootroot00000000000000# test loading from ptr16 type # only works on little endian machines @micropython.viper def get(src:ptr16) -> int: return src[0] @micropython.viper def get1(src:ptr16) -> int: return src[1] @micropython.viper def memadd(src:ptr16, n:int) -> int: sum = 0 for i in range(n): sum += src[i] return sum @micropython.viper def memadd2(src_in) -> int: src = ptr16(src_in) n = int(len(src_in)) >> 1 sum = 0 for i in range(n): sum += src[i] return sum b = bytearray(b'1234') print(b) print(get(b), get1(b)) print(memadd(b, 2)) print(memadd2(b)) micropython-1.12/tests/micropython/viper_ptr16_load.py.exp000066400000000000000000000000531357706137100240620ustar00rootroot00000000000000bytearray(b'1234') 12849 13363 26212 26212 micropython-1.12/tests/micropython/viper_ptr16_store.py000066400000000000000000000010611357706137100235040ustar00rootroot00000000000000# test ptr16 type @micropython.viper def set(dest:ptr16, val:int): dest[0] = val @micropython.viper def set1(dest:ptr16, val:int): dest[1] = val @micropython.viper def memset(dest:ptr16, val:int, n:int): for i in range(n): dest[i] = val @micropython.viper def memset2(dest_in, val:int): dest = ptr16(dest_in) n = int(len(dest_in)) >> 1 for i in range(n): dest[i] = val b = bytearray(4) print(b) set(b, 0x4242) print(b) set1(b, 0x4343) print(b) memset(b, 0x4444, len(b) // 2) print(b) memset2(b, 0x4545) print(b) micropython-1.12/tests/micropython/viper_ptr16_store.py.exp000066400000000000000000000001611357706137100242770ustar00rootroot00000000000000bytearray(b'\x00\x00\x00\x00') bytearray(b'BB\x00\x00') bytearray(b'BBCC') bytearray(b'DDDD') bytearray(b'EEEE') micropython-1.12/tests/micropython/viper_ptr32_load.py000066400000000000000000000011371357706137100232710ustar00rootroot00000000000000# test loading from ptr32 type @micropython.viper def get(src:ptr32) -> int: return src[0] @micropython.viper def get1(src:ptr32) -> int: return src[1] @micropython.viper def memadd(src:ptr32, n:int) -> int: sum = 0 for i in range(n): sum += src[i] return sum @micropython.viper def memadd2(src_in) -> int: src = ptr32(src_in) n = int(len(src_in)) >> 2 sum = 0 for i in range(n): sum += src[i] return sum b = bytearray(b'\x12\x12\x12\x12\x34\x34\x34\x34') print(b) print(hex(get(b)), hex(get1(b))) print(hex(memadd(b, 2))) print(hex(memadd2(b))) micropython-1.12/tests/micropython/viper_ptr32_load.py.exp000066400000000000000000000001171357706137100240610ustar00rootroot00000000000000bytearray(b'\x12\x12\x12\x124444') 0x12121212 0x34343434 0x46464646 0x46464646 micropython-1.12/tests/micropython/viper_ptr32_store.py000066400000000000000000000011121357706137100234770ustar00rootroot00000000000000# test store to ptr32 type @micropython.viper def set(dest:ptr32, val:int): dest[0] = val @micropython.viper def set1(dest:ptr32, val:int): dest[1] = val @micropython.viper def memset(dest:ptr32, val:int, n:int): for i in range(n): dest[i] = val @micropython.viper def memset2(dest_in, val:int): dest = ptr32(dest_in) n = int(len(dest_in)) >> 2 for i in range(n): dest[i] = val b = bytearray(8) print(b) set(b, 0x42424242) print(b) set1(b, 0x43434343) print(b) memset(b, 0x44444444, len(b) // 4) print(b) memset2(b, 0x45454545) print(b) micropython-1.12/tests/micropython/viper_ptr32_store.py.exp000066400000000000000000000002271357706137100243000ustar00rootroot00000000000000bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'BBBB\x00\x00\x00\x00') bytearray(b'BBBBCCCC') bytearray(b'DDDDDDDD') bytearray(b'EEEEEEEE') micropython-1.12/tests/micropython/viper_ptr8_load.py000066400000000000000000000010451357706137100232120ustar00rootroot00000000000000# test loading from ptr8 type @micropython.viper def get(src:ptr8) -> int: return src[0] @micropython.viper def get1(src:ptr8) -> int: return src[1] @micropython.viper def memadd(src:ptr8, n:int) -> int: sum = 0 for i in range(n): sum += src[i] return sum @micropython.viper def memadd2(src_in) -> int: src = ptr8(src_in) n = int(len(src_in)) sum = 0 for i in range(n): sum += src[i] return sum b = bytearray(b'1234') print(b) print(get(b), get1(b)) print(memadd(b, 4)) print(memadd2(b)) micropython-1.12/tests/micropython/viper_ptr8_load.py.exp000066400000000000000000000000411357706137100240000ustar00rootroot00000000000000bytearray(b'1234') 49 50 202 202 micropython-1.12/tests/micropython/viper_ptr8_store.py000066400000000000000000000010221357706137100234220ustar00rootroot00000000000000# test ptr8 type @micropython.viper def set(dest:ptr8, val:int): dest[0] = val @micropython.viper def set1(dest:ptr8, val:int): dest[1] = val @micropython.viper def memset(dest:ptr8, val:int, n:int): for i in range(n): dest[i] = val @micropython.viper def memset2(dest_in, val:int): dest = ptr8(dest_in) n = int(len(dest_in)) for i in range(n): dest[i] = val b = bytearray(4) print(b) set(b, 41) print(b) set1(b, 42) print(b) memset(b, 43, len(b)) print(b) memset2(b, 44) print(b) micropython-1.12/tests/micropython/viper_ptr8_store.py.exp000066400000000000000000000001721357706137100242220ustar00rootroot00000000000000bytearray(b'\x00\x00\x00\x00') bytearray(b')\x00\x00\x00') bytearray(b')*\x00\x00') bytearray(b'++++') bytearray(b',,,,') micropython-1.12/tests/micropython/viper_subscr.py000066400000000000000000000005261357706137100226220ustar00rootroot00000000000000# test standard Python subscr using viper types @micropython.viper def get(dest, i:int): i += 1 return dest[i] @micropython.viper def set(dest, i:int, val:int): i += 1 dest[i] = val + 1 ar = [i for i in range(3)] for i in range(len(ar)): set(ar, i - 1, i) print(ar) for i in range(len(ar)): print(get(ar, i - 1)) micropython-1.12/tests/micropython/viper_subscr.py.exp000066400000000000000000000000201357706137100234020ustar00rootroot00000000000000[1, 2, 3] 1 2 3 micropython-1.12/tests/micropython/viper_try.py000066400000000000000000000012031357706137100221300ustar00rootroot00000000000000# test try handling within a viper function # basic try-finally @micropython.viper def f(): try: fail finally: print('finally') try: f() except NameError: print('NameError') # nested try-except with try-finally @micropython.viper def f(): try: try: fail finally: print('finally') except NameError: print('NameError') f() # check that locals written to in try blocks keep their values @micropython.viper def f(): a = 100 try: print(a) a = 200 fail except NameError: print(a) a = 300 print(a) f() micropython-1.12/tests/micropython/viper_try.py.exp000066400000000000000000000000601357706137100227230ustar00rootroot00000000000000finally NameError finally NameError 100 200 300 micropython-1.12/tests/micropython/viper_types.py000066400000000000000000000006211357706137100224610ustar00rootroot00000000000000# test various type conversions import micropython # converting incoming arg to bool @micropython.viper def f1(x:bool): print(x) f1(0) f1(1) f1([]) f1([1]) # taking and returning a bool @micropython.viper def f2(x:bool) -> bool: return x print(f2([])) print(f2([1])) # converting to bool within function @micropython.viper def f3(x) -> bool: return bool(x) print(f3([])) print(f3(-1)) micropython-1.12/tests/micropython/viper_types.py.exp000066400000000000000000000000541357706137100232540ustar00rootroot00000000000000False True False True False True False True micropython-1.12/tests/micropython/viper_with.py000066400000000000000000000007631357706137100222770ustar00rootroot00000000000000# test with handling within a viper function class C: def __init__(self): print('__init__') def __enter__(self): print('__enter__') def __exit__(self, a, b, c): print('__exit__', a, b, c) # basic with @micropython.viper def f(): with C(): print(1) f() # nested with and try-except @micropython.viper def f(): try: with C(): print(1) fail print(2) except NameError: print('NameError') f() micropython-1.12/tests/micropython/viper_with.py.exp000066400000000000000000000002101357706137100230550ustar00rootroot00000000000000__init__ __enter__ 1 __exit__ None None None __init__ __enter__ 1 __exit__ name 'fail' isn't defined None NameError micropython-1.12/tests/misc/000077500000000000000000000000001357706137100161175ustar00rootroot00000000000000micropython-1.12/tests/misc/features.py000066400000000000000000000037621357706137100203170ustar00rootroot00000000000000try: str.count except AttributeError: print("SKIP") raise SystemExit # mad.py # Alf Clement 27-Mar-2014 # zero=0 three=3 print("1") print("2") print(three) print("{}".format(4)) five=25//5 print(int(five)) j=0 for i in range(4): j += i print(j) print(3+4) try: a=4//zero except: print(8) print("xxxxxxxxx".count("x")) def ten(): return 10 print(ten()) a=[] for i in range(13): a.append(i) print(a[11]) print(a[-1]) str="0123456789" print(str[1]+str[3]) def p(s): print(s) p("14") p(15) class A: def __init__(self): self.a=16 def print(self): print(self.a) def set(self,b): self.a=b a=A() a.print() a.set(17) a.print() b=A() b.set(a.a + 1) b.print() for i in range(20): pass print(i) if 20 > 30: a="1" else: a="2" if 0 < 4: print(a+"0") else: print(a+"1") a=[20,21,22,23,24] for i in a: if i < 21: continue if i > 21: break print(i) b=[a,a,a] print(b[1][2]) print(161//7) a=24 while True: try: def gcheck(): global a print(a) gcheck() class c25(): x=25 x=c25() print(x.x) raise except: print(26) print(27+zero) break print(28) k=29 def f(): global k k = yield k print(next(f())) while True: k+= 1 if k < 30: continue break print(k) for i in [1,2,3]: class A(): def __init__(self, c): self.a = i+10*c b = A(3) print(b.a) print(34) p=0 for i in range(35, -1, -1): print(i) p = p + 1 if p > 0: break p=36 while p == 36: print(p) p=37 print(p) for i in [38]: print(i) print(int(exec("def foo(): return 38") == None)+foo()) d = {} exec("def bar(): return 40", d) print(d["bar"]()) def fib2(n): result = [] a, b = 0, 1 while a < n: result.append(a) a, b = b, a+b return result print(fib2(100)[-2]-14) Answer={} Answer["ForAll"]=42 print(Answer["ForAll"]) i = 43 def f(i=i): print(i) i = 44 f() print(i) while True: try: if None != True: print(45) break else: print(0) except: print(0) print(46) print(46+1) def u(p): if p > 3: return 3*p else: return u(2*p)-3*u(p) print(u(16)) def u49(): return 49 print(u49()) micropython-1.12/tests/misc/non_compliant.py000066400000000000000000000064131357706137100213350ustar00rootroot00000000000000# tests for things that are not implemented, or have non-compliant behaviour try: import uarray as array import ustruct except ImportError: print("SKIP") raise SystemExit # when super can't find self try: exec('def f(): super()') except SyntaxError: print('SyntaxError') # store to exception attribute is not allowed try: ValueError().x = 0 except AttributeError: print('AttributeError') # array deletion not implemented try: a = array.array('b', (1, 2, 3)) del a[1] except TypeError: print('TypeError') # slice with step!=1 not implemented try: a = array.array('b', (1, 2, 3)) print(a[3:2:2]) except NotImplementedError: print('NotImplementedError') # containment, looking for integer not implemented try: print(1 in array.array('B', b'12')) except NotImplementedError: print('NotImplementedError') # uPy raises TypeError, shold be ValueError try: '%c' % b'\x01\x02' except (TypeError, ValueError): print('TypeError, ValueError') # attributes/subscr not implemented try: print('{a[0]}'.format(a=[1, 2])) except NotImplementedError: print('NotImplementedError') # str(...) with keywords not implemented try: str(b'abc', encoding='utf8') except NotImplementedError: print('NotImplementedError') # str.rsplit(None, n) not implemented try: 'a a a'.rsplit(None, 1) except NotImplementedError: print('NotImplementedError') # str.endswith(s, start) not implemented try: 'abc'.endswith('c', 1) except NotImplementedError: print('NotImplementedError') # str subscr with step!=1 not implemented try: print('abc'[1:2:3]) except NotImplementedError: print('NotImplementedError') # bytes(...) with keywords not implemented try: bytes('abc', encoding='utf8') except NotImplementedError: print('NotImplementedError') # bytes subscr with step!=1 not implemented try: b'123'[0:3:2] except NotImplementedError: print('NotImplementedError') # tuple load with step!=1 not implemented try: ()[2:3:4] except NotImplementedError: print('NotImplementedError') # list store with step!=1 not implemented try: [][2:3:4] = [] except NotImplementedError: print('NotImplementedError') # list delete with step!=1 not implemented try: del [][2:3:4] except NotImplementedError: print('NotImplementedError') # struct pack with too many args, not checked by uPy print(ustruct.pack('bb', 1, 2, 3)) # struct pack with too few args, not checked by uPy print(ustruct.pack('bb', 1)) # array slice assignment with unsupported RHS try: bytearray(4)[0:1] = [1, 2] except NotImplementedError: print('NotImplementedError') # can't assign attributes to a function def f(): pass try: f.x = 1 except AttributeError: print('AttributeError') # can't call a function type (ie make new instances of a function) try: type(f)() except TypeError: print('TypeError') # test when object explicitly listed at not-last position in parent tuple # this is not compliant with CPython because of illegal MRO class A: def foo(self): print('A.foo') class B(object, A): pass B().foo() # can't assign property (or other special accessors) to already-subclassed class class A: pass class B(A): pass try: A.bar = property() except AttributeError: print('AttributeError') micropython-1.12/tests/misc/non_compliant.py.exp000066400000000000000000000006051357706137100221250ustar00rootroot00000000000000SyntaxError AttributeError TypeError NotImplementedError NotImplementedError TypeError, ValueError NotImplementedError NotImplementedError NotImplementedError NotImplementedError NotImplementedError NotImplementedError NotImplementedError NotImplementedError NotImplementedError NotImplementedError b'\x01\x02' b'\x01\x00' NotImplementedError AttributeError TypeError A.foo AttributeError micropython-1.12/tests/misc/non_compliant_lexer.py000066400000000000000000000013121357706137100225250ustar00rootroot00000000000000# lexer tests for things that are not implemented, or have non-compliant behaviour def test(code): try: exec(code) print('no Error') except SyntaxError: print('SyntaxError') except NotImplementedError: print('NotImplementedError') # uPy requires spaces between literal numbers and keywords, CPy doesn't try: eval('1and 0') except SyntaxError: print('SyntaxError') try: eval('1or 0') except SyntaxError: print('SyntaxError') try: eval('1if 1else 0') except SyntaxError: print('SyntaxError') try: eval('1if 0else 0') except SyntaxError: print('SyntaxError') # unicode name escapes are not implemented test('"\\N{LATIN SMALL LETTER A}"') micropython-1.12/tests/misc/non_compliant_lexer.py.exp000066400000000000000000000001041357706137100233160ustar00rootroot00000000000000SyntaxError SyntaxError SyntaxError SyntaxError NotImplementedError micropython-1.12/tests/misc/print_exception.py000066400000000000000000000042751357706137100217130ustar00rootroot00000000000000import sys try: try: import uio as io except ImportError: import io except ImportError: print("SKIP") raise SystemExit if hasattr(sys, 'print_exception'): print_exception = sys.print_exception else: import traceback print_exception = lambda e, f: traceback.print_exception(None, e, sys.exc_info()[2], file=f) def print_exc(e): buf = io.StringIO() print_exception(e, buf) s = buf.getvalue() for l in s.split("\n"): # uPy on pyboard prints as file, so remove filename. if l.startswith(" File "): l = l.split('"') print(l[0], l[2]) # uPy and CPy tracebacks differ in that CPy prints a source line for # each traceback entry. In this case, we know that offending line # has 4-space indent, so filter it out. elif not l.startswith(" "): print(l) # basic exception message try: raise Exception('msg') except Exception as e: print('caught') print_exc(e) # exception message with more than 1 source-code line def f(): g() def g(): raise Exception('fail') try: f() except Exception as e: print('caught') print_exc(e) # Test that an exception propagated through a finally doesn't have a traceback added there try: try: f() finally: print('finally') except Exception as e: print('caught') print_exc(e) # Test that re-raising an exception doesn't add traceback info try: try: f() except Exception as e: print('reraise') print_exc(e) raise except Exception as e: print('caught') print_exc(e) # Here we have a function with lots of bytecode generated for a single source-line, and # there is an error right at the end of the bytecode. It should report the correct line. def f(): f([1, 2], [1, 2], [1, 2], {1:1, 1:1, 1:1, 1:1, 1:1, 1:1, 1:f.X}) return 1 try: f() except Exception as e: print_exc(e) # Test non-stream object passed as output object, only valid for uPy if hasattr(sys, 'print_exception'): try: sys.print_exception(Exception, 1) had_exception = False except OSError: had_exception = True assert had_exception micropython-1.12/tests/misc/rge_sm.py000066400000000000000000000102211357706137100177410ustar00rootroot00000000000000# evolve the RGEs of the standard model from electroweak scale up # by dpgeorge import math class RungeKutta(object): def __init__(self, functions, initConditions, t0, dh, save=True): self.Trajectory, self.save = [[t0] + initConditions], save self.functions = [lambda *args: 1.0] + list(functions) self.N, self.dh = len(self.functions), dh self.coeff = [1.0/6.0, 2.0/6.0, 2.0/6.0, 1.0/6.0] self.InArgCoeff = [0.0, 0.5, 0.5, 1.0] def iterate(self): step = self.Trajectory[-1][:] istep, iac = step[:], self.InArgCoeff k, ktmp = self.N * [0.0], self.N * [0.0] for ic, c in enumerate(self.coeff): for if_, f in enumerate(self.functions): arguments = [ (x + k[i]*iac[ic]) for i, x in enumerate(istep)] try: feval = f(*arguments) except OverflowError: return False if abs(feval) > 1e2: # stop integrating return False ktmp[if_] = self.dh * feval k = ktmp[:] step = [s + c*k[ik] for ik,s in enumerate(step)] if self.save: self.Trajectory += [step] else: self.Trajectory = [step] return True def solve(self, finishtime): while self.Trajectory[-1][0] < finishtime: if not self.iterate(): break def solveNSteps(self, nSteps): for i in range(nSteps): if not self.iterate(): break def series(self): return zip(*self.Trajectory) # 1-loop RGES for the main parameters of the SM # couplings are: g1, g2, g3 of U(1), SU(2), SU(3); yt (top Yukawa), lambda (Higgs quartic) # see arxiv.org/abs/0812.4950, eqs 10-15 sysSM = ( lambda *a: 41.0 / 96.0 / math.pi**2 * a[1]**3, # g1 lambda *a: -19.0 / 96.0 / math.pi**2 * a[2]**3, # g2 lambda *a: -42.0 / 96.0 / math.pi**2 * a[3]**3, # g3 lambda *a: 1.0 / 16.0 / math.pi**2 * (9.0 / 2.0 * a[4]**3 - 8.0 * a[3]**2 * a[4] - 9.0 / 4.0 * a[2]**2 * a[4] - 17.0 / 12.0 * a[1]**2 * a[4]), # yt lambda *a: 1.0 / 16.0 / math.pi**2 * (24.0 * a[5]**2 + 12.0 * a[4]**2 * a[5] - 9.0 * a[5] * (a[2]**2 + 1.0 / 3.0 * a[1]**2) - 6.0 * a[4]**4 + 9.0 / 8.0 * a[2]**4 + 3.0 / 8.0 * a[1]**4 + 3.0 / 4.0 * a[2]**2 * a[1]**2), # lambda ) def drange(start, stop, step): r = start while r < stop: yield r r += step def phaseDiagram(system, trajStart, trajPlot, h=0.1, tend=1.0, range=1.0): tstart = 0.0 for i in drange(0, range, 0.1 * range): for j in drange(0, range, 0.1 * range): rk = RungeKutta(system, trajStart(i, j), tstart, h) rk.solve(tend) # draw the line for tr in rk.Trajectory: x, y = trajPlot(tr) print(x, y) print() # draw the arrow continue l = (len(rk.Trajectory) - 1) / 3 if l > 0 and 2 * l < len(rk.Trajectory): p1 = rk.Trajectory[l] p2 = rk.Trajectory[2 * l] x1, y1 = trajPlot(p1) x2, y2 = trajPlot(p2) dx = -0.5 * (y2 - y1) # orthogonal to line dy = 0.5 * (x2 - x1) # orthogonal to line #l = math.sqrt(dx*dx + dy*dy) #if abs(l) > 1e-3: # l = 0.1 / l # dx *= l # dy *= l print(x1 + dx, y1 + dy) print(x2, y2) print(x1 - dx, y1 - dy) print() def singleTraj(system, trajStart, h=0.02, tend=1.0): tstart = 0.0 # compute the trajectory rk = RungeKutta(system, trajStart, tstart, h) rk.solve(tend) # print out trajectory for i in range(len(rk.Trajectory)): tr = rk.Trajectory[i] print(' '.join(["{:.4f}".format(t) for t in tr])) #phaseDiagram(sysSM, (lambda i, j: [0.354, 0.654, 1.278, 0.8 + 0.2 * i, 0.1 + 0.1 * j]), (lambda a: (a[4], a[5])), h=0.1, tend=math.log(10**17)) # initial conditions at M_Z singleTraj(sysSM, [0.354, 0.654, 1.278, 0.983, 0.131], h=0.5, tend=math.log(10**17)) # true values micropython-1.12/tests/misc/sys_atexit.py000066400000000000000000000004071357706137100206660ustar00rootroot00000000000000# test sys.atexit() function import sys try: sys.atexit except AttributeError: print('SKIP') raise SystemExit some_var = None def do_at_exit(): print("done at exit:", some_var) sys.atexit(do_at_exit) some_var = "ok" print("done before exit") micropython-1.12/tests/misc/sys_atexit.py.exp000066400000000000000000000000421357706137100214540ustar00rootroot00000000000000done before exit done at exit: ok micropython-1.12/tests/misc/sys_exc_info.py000066400000000000000000000006131357706137100211610ustar00rootroot00000000000000import sys try: sys.exc_info except: print("SKIP") raise SystemExit def f(): print(sys.exc_info()[0:2]) try: raise ValueError('value', 123) except: print(sys.exc_info()[0:2]) f() # Outside except block, sys.exc_info() should be back to None's f() # Recursive except blocks are not handled - just don't # use exc_info() at all, use explicit variables in "except". micropython-1.12/tests/misc/sys_settrace_features.py000066400000000000000000000045611357706137100231050ustar00rootroot00000000000000import sys try: sys.settrace except AttributeError: print("SKIP") raise SystemExit def print_stacktrace(frame, level=0): # Ignore CPython specific helpers. if frame.f_globals['__name__'].find('importlib') != -1: print_stacktrace(frame.f_back, level) return print("%2d: %s@%s:%s => %s:%d" % ( level, " ", frame.f_globals['__name__'], frame.f_code.co_name, # reduce full path to some pseudo-relative 'misc' + ''.join(frame.f_code.co_filename.split('tests/misc')[-1:]), frame.f_lineno, )) if frame.f_back: print_stacktrace(frame.f_back, level + 1) class _Prof: trace_count = 0; def trace_tick(self, frame, event, arg): self.trace_count += 1 print_stacktrace(frame) __prof__ = _Prof() alice_handler_set = False def trace_tick_handler_alice(frame, event, arg): print("### trace_handler::Alice event:", event) __prof__.trace_tick(frame, event, arg) return trace_tick_handler_alice bob_handler_set = False def trace_tick_handler_bob(frame, event, arg): print("### trace_handler::Bob event:", event) __prof__.trace_tick(frame, event, arg) return trace_tick_handler_bob def trace_tick_handler(frame, event, arg): # Ignore CPython specific helpers. if frame.f_globals['__name__'].find('importlib') != -1: return print("### trace_handler::main event:", event) __prof__.trace_tick(frame, event, arg) if frame.f_code.co_name != 'factorial': return trace_tick_handler global alice_handler_set if event == 'call' and not alice_handler_set: alice_handler_set = True return trace_tick_handler_alice global bob_handler_set if event == 'call' and not bob_handler_set: bob_handler_set = True return trace_tick_handler_bob return trace_tick_handler def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1) def do_tests(): # These commands are here to demonstrate some execution being traced. print("Who loves the sun?") print("Not every-", factorial(3)) from sys_settrace_subdir import trace_generic trace_generic.run_tests() return sys.settrace(trace_tick_handler) do_tests() sys.settrace(None) print("\n------------------ script exited ------------------") print("Total traces executed: ", __prof__.trace_count) micropython-1.12/tests/misc/sys_settrace_generator.py000066400000000000000000000023441357706137100232520ustar00rootroot00000000000000# test sys.settrace with generators import sys try: sys.settrace except AttributeError: print("SKIP") raise SystemExit def print_stacktrace(frame, level=0): print("%2d: %s@%s:%s => %s:%d" % ( level, " ", frame.f_globals['__name__'], frame.f_code.co_name, # reduce full path to some pseudo-relative 'misc' + ''.join(frame.f_code.co_filename.split('tests/misc')[-1:]), frame.f_lineno, )) if frame.f_back: print_stacktrace(frame.f_back, level + 1) trace_count = 0 def trace_tick_handler(frame, event, arg): global trace_count print("### trace_handler::main event:", event) trace_count += 1 print_stacktrace(frame) return trace_tick_handler def test_generator(): def make_gen(): yield 1<<0 yield 1<<1 yield 1<<2 return 1<<3 gen = make_gen() r = 0 try: r += gen.send(None) while True: r += gen.send(None) except StopIteration as e: print("test_generator", r, e) gen = make_gen() r = 0 for i in gen: r += i print(r) sys.settrace(trace_tick_handler) test_generator() sys.settrace(None) print("Total traces executed: ", trace_count) micropython-1.12/tests/misc/sys_settrace_generator.py.exp000066400000000000000000000262671357706137100240570ustar00rootroot00000000000000### trace_handler::main event: call 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:33 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:34 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:40 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:41 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:42 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:44 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: call 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:34 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:44 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:44 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: return 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:44 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: call 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: return 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: call 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: return 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: call 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:38 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: return 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:38 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: exception 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:50 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:51 1: @__main__: => miscmisc/sys_settrace_generator.py:60 test_generator 7 8 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:53 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:54 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: call 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:34 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: return 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:56 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: call 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: return 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:56 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: call 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: return 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:56 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 1: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: call 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:38 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: return 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:38 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 2: @__main__: => miscmisc/sys_settrace_generator.py:60 ### trace_handler::main event: line 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:57 1: @__main__: => miscmisc/sys_settrace_generator.py:60 7 ### trace_handler::main event: return 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:57 1: @__main__: => miscmisc/sys_settrace_generator.py:60 Total traces executed: 54 micropython-1.12/tests/misc/sys_settrace_loop.py000066400000000000000000000021041357706137100222270ustar00rootroot00000000000000# test sys.settrace with while and for loops import sys try: sys.settrace except AttributeError: print("SKIP") raise SystemExit def print_stacktrace(frame, level=0): print("%2d: %s@%s:%s => %s:%d" % ( level, " ", frame.f_globals['__name__'], frame.f_code.co_name, # reduce full path to some pseudo-relative 'misc' + ''.join(frame.f_code.co_filename.split('tests/misc')[-1:]), frame.f_lineno, )) if frame.f_back: print_stacktrace(frame.f_back, level + 1) trace_count = 0 def trace_tick_handler(frame, event, arg): global trace_count print("### trace_handler::main event:", event) trace_count += 1 print_stacktrace(frame) return trace_tick_handler def test_loop(): # for loop r = 0 for i in range(3): r += i print("test_for_loop", r) # while loop r = 0 i = 0 while i < 3: r += i i += 1 print("test_while_loop", i) sys.settrace(trace_tick_handler) test_loop() sys.settrace(None) print("Total traces executed: ", trace_count) micropython-1.12/tests/misc/sys_settrace_loop.py.exp000066400000000000000000000072101357706137100230250ustar00rootroot00000000000000### trace_handler::main event: call 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:33 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:35 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:36 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:37 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:36 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:37 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:36 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:37 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:36 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:37 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:38 1: @__main__: => miscmisc/sys_settrace_loop.py:49 test_for_loop 3 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:41 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:42 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:43 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:45 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:44 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:45 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:44 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:45 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:44 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:45 1: @__main__: => miscmisc/sys_settrace_loop.py:49 ### trace_handler::main event: line 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:46 1: @__main__: => miscmisc/sys_settrace_loop.py:49 test_while_loop 3 ### trace_handler::main event: return 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:46 1: @__main__: => miscmisc/sys_settrace_loop.py:49 Total traces executed: 23 micropython-1.12/tests/misc/sys_settrace_subdir/000077500000000000000000000000001357706137100221775ustar00rootroot00000000000000micropython-1.12/tests/misc/sys_settrace_subdir/trace_generic.py000066400000000000000000000030201357706137100253360ustar00rootroot00000000000000print("Now comes the language constructions tests.") # function def test_func(): def test_sub_func(): print("test_function") test_sub_func() # closure def test_closure(msg): def make_closure(): print(msg) return make_closure # exception def test_exception(): try: raise Exception("test_exception") except Exception: pass finally: pass # listcomp def test_listcomp(): print("test_listcomp", [x for x in range(3)]) # lambda def test_lambda(): func_obj_1 = lambda a, b: a + b print(func_obj_1(10, 20)) # import def test_import(): from sys_settrace_subdir import trace_importme trace_importme.dummy() trace_importme.saysomething() # class class TLClass(): def method(): pass pass def test_class(): class TestClass: __anynum = -9 def method(self): print("test_class_method") self.__anynum += 1 def prprty_getter(self): return self.__anynum def prprty_setter(self, what): self.__anynum = what prprty = property(prprty_getter, prprty_setter) cls = TestClass() cls.method() print("test_class_property", cls.prprty) cls.prprty = 12 print("test_class_property", cls.prprty) def run_tests(): test_func() test_closure_inst = test_closure("test_closure") test_closure_inst() test_exception() test_listcomp() test_lambda() test_class() test_import() print("And it's done!") micropython-1.12/tests/misc/sys_settrace_subdir/trace_importme.py000066400000000000000000000005451357706137100255670ustar00rootroot00000000000000print("Yep, I got imported.") try: x = const(1) except NameError: print('const not defined') const = lambda x: x _CNT01 = "CONST01" _CNT02 = const(123) A123 = const(123) a123 = const(123) def dummy(): return False def saysomething(): print("There, I said it.") def neverexecuted(): print("Never got here!") print("Yep, got here") micropython-1.12/tests/net_hosted/000077500000000000000000000000001357706137100173205ustar00rootroot00000000000000micropython-1.12/tests/net_hosted/README000066400000000000000000000007171357706137100202050ustar00rootroot00000000000000This directory contains network tests which require just "peer to peer" network connection between test host and device under test, instead of full Internet connection. Note that setup for these tests and tests themselves are WIP, and may not yet fully correspond to the functional specification above. So far, these tests are not run as part of the main testsuite and need to be run seperately (from the main test/ directory): ./run-tests net_hosted/*.py micropython-1.12/tests/net_hosted/accept_nonblock.py000066400000000000000000000005121357706137100230140ustar00rootroot00000000000000# test that socket.accept() on a non-blocking socket raises EAGAIN try: import usocket as socket except: import socket s = socket.socket() s.bind(socket.getaddrinfo('127.0.0.1', 8123)[0][-1]) s.setblocking(False) s.listen(1) try: s.accept() except OSError as er: print(er.args[0] == 11) # 11 is EAGAIN s.close() micropython-1.12/tests/net_hosted/accept_nonblock.py.exp000066400000000000000000000000051357706137100236040ustar00rootroot00000000000000True micropython-1.12/tests/net_hosted/accept_timeout.py000066400000000000000000000007241357706137100227020ustar00rootroot00000000000000# test that socket.accept() on a socket with timeout raises ETIMEDOUT try: import usocket as socket except: import socket try: socket.socket.settimeout except AttributeError: print('SKIP') raise SystemExit s = socket.socket() s.bind(socket.getaddrinfo('127.0.0.1', 8123)[0][-1]) s.settimeout(1) s.listen(1) try: s.accept() except OSError as er: print(er.args[0] in (110, 'timed out')) # 110 is ETIMEDOUT; CPython uses a string s.close() micropython-1.12/tests/net_hosted/accept_timeout.py.exp000066400000000000000000000000051357706137100234650ustar00rootroot00000000000000True micropython-1.12/tests/net_hosted/connect_nonblock.py000066400000000000000000000006521357706137100232130ustar00rootroot00000000000000# test that socket.connect() on a non-blocking socket raises EINPROGRESS try: import usocket as socket except: import socket def test(peer_addr): s = socket.socket() s.setblocking(False) try: s.connect(peer_addr) except OSError as er: print(er.args[0] == 115) # 115 is EINPROGRESS s.close() if __name__ == "__main__": test(socket.getaddrinfo('micropython.org', 80)[0][-1]) micropython-1.12/tests/net_hosted/connect_nonblock.py.exp000066400000000000000000000000051357706137100237760ustar00rootroot00000000000000True micropython-1.12/tests/net_hosted/connect_poll.py000066400000000000000000000012121357706137100223450ustar00rootroot00000000000000# test that socket.connect() has correct polling behaviour before, during and after try: import usocket as socket, uselect as select except: import socket, select def test(peer_addr): s = socket.socket() poller = select.poll() poller.register(s) # test poll before connect p = poller.poll(0) print(len(p), p[0][-1]) s.connect(peer_addr) # test poll during connection print(len(poller.poll(0))) # test poll after connection is established p = poller.poll(1000) print(len(p), p[0][-1]) s.close() if __name__ == "__main__": test(socket.getaddrinfo('micropython.org', 80)[0][-1]) micropython-1.12/tests/net_hosted/connect_poll.py.exp000066400000000000000000000000131357706137100231360ustar00rootroot000000000000001 20 1 1 4 micropython-1.12/tests/net_hosted/ssl_getpeercert.py000066400000000000000000000006231357706137100230650ustar00rootroot00000000000000# test ssl.getpeercert() method try: import usocket as socket import ussl as ssl except: import socket import ssl def test(peer_addr): s = socket.socket() s.connect(peer_addr) s = ssl.wrap_socket(s) cert = s.getpeercert(True) print(type(cert), len(cert) > 100) s.close() if __name__ == "__main__": test(socket.getaddrinfo('micropython.org', 443)[0][-1]) micropython-1.12/tests/net_hosted/ssl_getpeercert.py.exp000066400000000000000000000000251357706137100236540ustar00rootroot00000000000000 True micropython-1.12/tests/net_inet/000077500000000000000000000000001357706137100167715ustar00rootroot00000000000000micropython-1.12/tests/net_inet/README000066400000000000000000000003471357706137100176550ustar00rootroot00000000000000This directory contains network tests which require Internet connection. Note that these tests are not run as part of the main testsuite and need to be run seperately (from the main test/ directory): ./run-tests net_inet/*.py micropython-1.12/tests/net_inet/test_tls_sites.py000066400000000000000000000022771357706137100224230ustar00rootroot00000000000000try: import usocket as _socket except: import _socket try: import ussl as ssl except: import ssl # CPython only supports server_hostname with SSLContext ssl = ssl.SSLContext() def test_one(site, opts): ai = _socket.getaddrinfo(site, 443) addr = ai[0][-1] s = _socket.socket() try: s.connect(addr) if "sni" in opts: s = ssl.wrap_socket(s, server_hostname=opts["host"]) else: s = ssl.wrap_socket(s) s.write(b"GET / HTTP/1.0\r\nHost: %s\r\n\r\n" % bytes(site, 'latin')) resp = s.read(4096) # print(resp) finally: s.close() SITES = [ "google.com", "www.google.com", "api.telegram.org", {"host": "api.pushbullet.com", "sni": True}, # "w9rybpfril.execute-api.ap-southeast-2.amazonaws.com", {"host": "w9rybpfril.execute-api.ap-southeast-2.amazonaws.com", "sni": True}, ] def main(): for site in SITES: opts = {} if isinstance(site, dict): opts = site site = opts["host"] try: test_one(site, opts) print(site, "ok") except Exception as e: print(site, repr(e)) main() micropython-1.12/tests/net_inet/test_tls_sites.py.exp000066400000000000000000000002011357706137100231770ustar00rootroot00000000000000google.com ok www.google.com ok api.telegram.org ok api.pushbullet.com ok w9rybpfril.execute-api.ap-southeast-2.amazonaws.com ok micropython-1.12/tests/perf_bench/000077500000000000000000000000001357706137100172575ustar00rootroot00000000000000micropython-1.12/tests/perf_bench/benchrun.py000066400000000000000000000013031357706137100214320ustar00rootroot00000000000000def bm_run(N, M): try: from utime import ticks_us, ticks_diff except ImportError: import time ticks_us = lambda: int(time.perf_counter() * 1000000) ticks_diff = lambda a, b: a - b # Pick sensible parameters given N, M cur_nm = (0, 0) param = None for nm, p in bm_params.items(): if 10 * nm[0] <= 12 * N and nm[1] <= M and nm > cur_nm: cur_nm = nm param = p if param is None: print(-1, -1, 'no matching params') return # Run and time benchmark run, result = bm_setup(param) t0 = ticks_us() run() t1 = ticks_us() norm, out = result() print(ticks_diff(t1, t0), norm, out) micropython-1.12/tests/perf_bench/bm_chaos.py000066400000000000000000000217251357706137100214130ustar00rootroot00000000000000# Source: https://github.com/python/pyperformance # License: MIT # create chaosgame-like fractals # Copyright (C) 2005 Carl Friedrich Bolz import math import random class GVector(object): def __init__(self, x=0, y=0, z=0): self.x = x self.y = y self.z = z def Mag(self): return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) def dist(self, other): return math.sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2 + (self.z - other.z) ** 2) def __add__(self, other): if not isinstance(other, GVector): raise ValueError("Can't add GVector to " + str(type(other))) v = GVector(self.x + other.x, self.y + other.y, self.z + other.z) return v def __sub__(self, other): return self + other * -1 def __mul__(self, other): v = GVector(self.x * other, self.y * other, self.z * other) return v __rmul__ = __mul__ def linear_combination(self, other, l1, l2=None): if l2 is None: l2 = 1 - l1 v = GVector(self.x * l1 + other.x * l2, self.y * l1 + other.y * l2, self.z * l1 + other.z * l2) return v def __str__(self): return "<%f, %f, %f>" % (self.x, self.y, self.z) def __repr__(self): return "GVector(%f, %f, %f)" % (self.x, self.y, self.z) class Spline(object): """Class for representing B-Splines and NURBS of arbitrary degree""" def __init__(self, points, degree, knots): """Creates a Spline. points is a list of GVector, degree is the degree of the Spline. """ if len(points) > len(knots) - degree + 1: raise ValueError("too many control points") elif len(points) < len(knots) - degree + 1: raise ValueError("not enough control points") last = knots[0] for cur in knots[1:]: if cur < last: raise ValueError("knots not strictly increasing") last = cur self.knots = knots self.points = points self.degree = degree def GetDomain(self): """Returns the domain of the B-Spline""" return (self.knots[self.degree - 1], self.knots[len(self.knots) - self.degree]) def __call__(self, u): """Calculates a point of the B-Spline using de Boors Algorithm""" dom = self.GetDomain() if u < dom[0] or u > dom[1]: raise ValueError("Function value not in domain") if u == dom[0]: return self.points[0] if u == dom[1]: return self.points[-1] I = self.GetIndex(u) d = [self.points[I - self.degree + 1 + ii] for ii in range(self.degree + 1)] U = self.knots for ik in range(1, self.degree + 1): for ii in range(I - self.degree + ik + 1, I + 2): ua = U[ii + self.degree - ik] ub = U[ii - 1] co1 = (ua - u) / (ua - ub) co2 = (u - ub) / (ua - ub) index = ii - I + self.degree - ik - 1 d[index] = d[index].linear_combination(d[index + 1], co1, co2) return d[0] def GetIndex(self, u): dom = self.GetDomain() for ii in range(self.degree - 1, len(self.knots) - self.degree): if u >= self.knots[ii] and u < self.knots[ii + 1]: I = ii break else: I = dom[1] - 1 return I def __len__(self): return len(self.points) def __repr__(self): return "Spline(%r, %r, %r)" % (self.points, self.degree, self.knots) def write_ppm(im, w, h, filename): with open(filename, "wb") as f: f.write(b'P6\n%i %i\n255\n' % (w, h)) for j in range(h): for i in range(w): val = im[j * w + i] c = val * 255 f.write(b'%c%c%c' % (c, c, c)) class Chaosgame(object): def __init__(self, splines, thickness, subdivs): self.splines = splines self.thickness = thickness self.minx = min([p.x for spl in splines for p in spl.points]) self.miny = min([p.y for spl in splines for p in spl.points]) self.maxx = max([p.x for spl in splines for p in spl.points]) self.maxy = max([p.y for spl in splines for p in spl.points]) self.height = self.maxy - self.miny self.width = self.maxx - self.minx self.num_trafos = [] maxlength = thickness * self.width / self.height for spl in splines: length = 0 curr = spl(0) for i in range(1, subdivs + 1): last = curr t = 1 / subdivs * i curr = spl(t) length += curr.dist(last) self.num_trafos.append(max(1, int(length / maxlength * 1.5))) self.num_total = sum(self.num_trafos) def get_random_trafo(self): r = random.randrange(int(self.num_total) + 1) l = 0 for i in range(len(self.num_trafos)): if r >= l and r < l + self.num_trafos[i]: return i, random.randrange(self.num_trafos[i]) l += self.num_trafos[i] return len(self.num_trafos) - 1, random.randrange(self.num_trafos[-1]) def transform_point(self, point, trafo=None): x = (point.x - self.minx) / self.width y = (point.y - self.miny) / self.height if trafo is None: trafo = self.get_random_trafo() start, end = self.splines[trafo[0]].GetDomain() length = end - start seg_length = length / self.num_trafos[trafo[0]] t = start + seg_length * trafo[1] + seg_length * x basepoint = self.splines[trafo[0]](t) if t + 1 / 50000 > end: neighbour = self.splines[trafo[0]](t - 1 / 50000) derivative = neighbour - basepoint else: neighbour = self.splines[trafo[0]](t + 1 / 50000) derivative = basepoint - neighbour if derivative.Mag() != 0: basepoint.x += derivative.y / derivative.Mag() * (y - 0.5) * \ self.thickness basepoint.y += -derivative.x / derivative.Mag() * (y - 0.5) * \ self.thickness else: # can happen, especially with single precision float pass self.truncate(basepoint) return basepoint def truncate(self, point): if point.x >= self.maxx: point.x = self.maxx if point.y >= self.maxy: point.y = self.maxy if point.x < self.minx: point.x = self.minx if point.y < self.miny: point.y = self.miny def create_image_chaos(self, w, h, iterations, rng_seed): # Always use the same sequence of random numbers # to get reproductible benchmark random.seed(rng_seed) im = bytearray(w * h) point = GVector((self.maxx + self.minx) / 2, (self.maxy + self.miny) / 2, 0) for _ in range(iterations): point = self.transform_point(point) x = (point.x - self.minx) / self.width * w y = (point.y - self.miny) / self.height * h x = int(x) y = int(y) if x == w: x -= 1 if y == h: y -= 1 im[(h - y - 1) * w + x] = 1 return im ########################################################################### # Benchmark interface bm_params = { (100, 50): (0.25, 100, 50, 50, 50, 1234), (1000, 1000): (0.25, 200, 400, 400, 1000, 1234), (5000, 1000): (0.25, 400, 500, 500, 7000, 1234), } def bm_setup(params): splines = [ Spline([ GVector(1.597, 3.304, 0.0), GVector(1.576, 4.123, 0.0), GVector(1.313, 5.288, 0.0), GVector(1.619, 5.330, 0.0), GVector(2.890, 5.503, 0.0), GVector(2.373, 4.382, 0.0), GVector(1.662, 4.360, 0.0)], 3, [0, 0, 0, 1, 1, 1, 2, 2, 2]), Spline([ GVector(2.805, 4.017, 0.0), GVector(2.551, 3.525, 0.0), GVector(1.979, 2.620, 0.0), GVector(1.979, 2.620, 0.0)], 3, [0, 0, 0, 1, 1, 1]), Spline([ GVector(2.002, 4.011, 0.0), GVector(2.335, 3.313, 0.0), GVector(2.367, 3.233, 0.0), GVector(2.367, 3.233, 0.0)], 3, [0, 0, 0, 1, 1, 1]) ] chaos = Chaosgame(splines, params[0], params[1]) image = None def run(): nonlocal image _, _, width, height, iter, rng_seed = params image = chaos.create_image_chaos(width, height, iter, rng_seed) def result(): norm = params[4] # Images are not the same when floating point behaviour is different, # so return percentage of pixels that are set (rounded to int). #write_ppm(image, params[2], params[3], 'out-.ppm') pix = int(100 * sum(image) / len(image)) return norm, pix return run, result micropython-1.12/tests/perf_bench/bm_fannkuch.py000066400000000000000000000027211357706137100221060ustar00rootroot00000000000000# Source: https://github.com/python/pyperformance # License: MIT # The Computer Language Benchmarks Game # http://benchmarksgame.alioth.debian.org/ # Contributed by Sokolov Yura, modified by Tupteq. def fannkuch(n): count = list(range(1, n + 1)) max_flips = 0 m = n - 1 r = n check = 0 perm1 = list(range(n)) perm = list(range(n)) perm1_ins = perm1.insert perm1_pop = perm1.pop while 1: if check < 30: check += 1 while r != 1: count[r - 1] = r r -= 1 if perm1[0] != 0 and perm1[m] != m: perm = perm1[:] flips_count = 0 k = perm[0] while k: perm[:k + 1] = perm[k::-1] flips_count += 1 k = perm[0] if flips_count > max_flips: max_flips = flips_count while r != n: perm1_ins(r, perm1_pop(0)) count[r] -= 1 if count[r] > 0: break r += 1 else: return max_flips ########################################################################### # Benchmark interface bm_params = { (50, 10): (5,), (100, 10): (6,), (500, 10): (7,), (1000, 10): (8,), (5000, 10): (9,), } def bm_setup(params): state = None def run(): nonlocal state state = fannkuch(params[0]) def result(): return params[0], state return run, result micropython-1.12/tests/perf_bench/bm_fft.py000066400000000000000000000040701357706137100210670ustar00rootroot00000000000000# Copyright (c) 2019 Project Nayuki. (MIT License) # https://www.nayuki.io/page/free-small-fft-in-multiple-languages import math, cmath def transform_radix2(vector, inverse): # Returns the integer whose value is the reverse of the lowest 'bits' bits of the integer 'x'. def reverse(x, bits): y = 0 for i in range(bits): y = (y << 1) | (x & 1) x >>= 1 return y # Initialization n = len(vector) levels = int(math.log2(n)) coef = (2 if inverse else -2) * cmath.pi / n exptable = [cmath.rect(1, i * coef) for i in range(n // 2)] vector = [vector[reverse(i, levels)] for i in range(n)] # Copy with bit-reversed permutation # Radix-2 decimation-in-time FFT size = 2 while size <= n: halfsize = size // 2 tablestep = n // size for i in range(0, n, size): k = 0 for j in range(i, i + halfsize): temp = vector[j + halfsize] * exptable[k] vector[j + halfsize] = vector[j] - temp vector[j] += temp k += tablestep size *= 2 return vector ########################################################################### # Benchmark interface bm_params = { (50, 25): (2, 128), (100, 100): (3, 256), (1000, 1000): (20, 512), (5000, 1000): (100, 512), } def bm_setup(params): state = None signal = [math.cos(2 * math.pi * i / params[1]) + 0j for i in range(params[1])] fft = None fft_inv = None def run(): nonlocal fft, fft_inv for _ in range(params[0]): fft = transform_radix2(signal, False) fft_inv = transform_radix2(fft, True) def result(): nonlocal fft, fft_inv fft[1] -= 0.5 * params[1] fft[-1] -= 0.5 * params[1] fft_ok = all(abs(f) < 1e-3 for f in fft) for i in range(len(fft_inv)): fft_inv[i] -= params[1] * signal[i] fft_inv_ok = all(abs(f) < 1e-3 for f in fft_inv) return params[0] * params[1], (fft_ok, fft_inv_ok) return run, result micropython-1.12/tests/perf_bench/bm_float.py000066400000000000000000000031651357706137100214210ustar00rootroot00000000000000# Source: https://github.com/python/pyperformance # License: MIT # Artificial, floating point-heavy benchmark originally used by Factor. from math import sin, cos, sqrt class Point(object): __slots__ = ('x', 'y', 'z') def __init__(self, i): self.x = x = sin(i) self.y = cos(i) * 3 self.z = (x * x) / 2 def __repr__(self): return "" % (self.x, self.y, self.z) def normalize(self): x = self.x y = self.y z = self.z norm = sqrt(x * x + y * y + z * z) self.x /= norm self.y /= norm self.z /= norm def maximize(self, other): self.x = self.x if self.x > other.x else other.x self.y = self.y if self.y > other.y else other.y self.z = self.z if self.z > other.z else other.z return self def maximize(points): next = points[0] for p in points[1:]: next = next.maximize(p) return next def benchmark(n): points = [None] * n for i in range(n): points[i] = Point(i) for p in points: p.normalize() return maximize(points) ########################################################################### # Benchmark interface bm_params = { (50, 25): (1, 150), (100, 100): (1, 250), (1000, 1000): (10, 1500), (5000, 1000): (20, 3000), } def bm_setup(params): state = None def run(): nonlocal state for _ in range(params[0]): state = benchmark(params[1]) def result(): return params[0] * params[1], 'Point(%.4f, %.4f, %.4f)' % (state.x, state.y, state.z) return run, result micropython-1.12/tests/perf_bench/bm_hexiom.py000066400000000000000000000407531357706137100216110ustar00rootroot00000000000000# Source: https://github.com/python/pyperformance # License: MIT # Solver of Hexiom board game. # Benchmark from Laurent Vaucher. # Source: https://github.com/slowfrog/hexiom : hexiom2.py, level36.txt # (Main function tweaked by Armin Rigo.) ################################## class Dir(object): def __init__(self, x, y): self.x = x self.y = y DIRS = [Dir(1, 0), Dir(-1, 0), Dir(0, 1), Dir(0, -1), Dir(1, 1), Dir(-1, -1)] EMPTY = 7 ################################## class Done(object): MIN_CHOICE_STRATEGY = 0 MAX_CHOICE_STRATEGY = 1 HIGHEST_VALUE_STRATEGY = 2 FIRST_STRATEGY = 3 MAX_NEIGHBORS_STRATEGY = 4 MIN_NEIGHBORS_STRATEGY = 5 def __init__(self, count, empty=False): self.count = count self.cells = None if empty else [ [0, 1, 2, 3, 4, 5, 6, EMPTY] for i in range(count)] def clone(self): ret = Done(self.count, True) ret.cells = [self.cells[i][:] for i in range(self.count)] return ret def __getitem__(self, i): return self.cells[i] def set_done(self, i, v): self.cells[i] = [v] def already_done(self, i): return len(self.cells[i]) == 1 def remove(self, i, v): if v in self.cells[i]: self.cells[i].remove(v) return True else: return False def remove_all(self, v): for i in range(self.count): self.remove(i, v) def remove_unfixed(self, v): changed = False for i in range(self.count): if not self.already_done(i): if self.remove(i, v): changed = True return changed def filter_tiles(self, tiles): for v in range(8): if tiles[v] == 0: self.remove_all(v) def next_cell_min_choice(self): minlen = 10 mini = -1 for i in range(self.count): if 1 < len(self.cells[i]) < minlen: minlen = len(self.cells[i]) mini = i return mini def next_cell_max_choice(self): maxlen = 1 maxi = -1 for i in range(self.count): if maxlen < len(self.cells[i]): maxlen = len(self.cells[i]) maxi = i return maxi def next_cell_highest_value(self): maxval = -1 maxi = -1 for i in range(self.count): if (not self.already_done(i)): maxvali = max(k for k in self.cells[i] if k != EMPTY) if maxval < maxvali: maxval = maxvali maxi = i return maxi def next_cell_first(self): for i in range(self.count): if (not self.already_done(i)): return i return -1 def next_cell_max_neighbors(self, pos): maxn = -1 maxi = -1 for i in range(self.count): if not self.already_done(i): cells_around = pos.hex.get_by_id(i).links n = sum(1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0 for nid in cells_around) if n > maxn: maxn = n maxi = i return maxi def next_cell_min_neighbors(self, pos): minn = 7 mini = -1 for i in range(self.count): if not self.already_done(i): cells_around = pos.hex.get_by_id(i).links n = sum(1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0 for nid in cells_around) if n < minn: minn = n mini = i return mini def next_cell(self, pos, strategy=HIGHEST_VALUE_STRATEGY): if strategy == Done.HIGHEST_VALUE_STRATEGY: return self.next_cell_highest_value() elif strategy == Done.MIN_CHOICE_STRATEGY: return self.next_cell_min_choice() elif strategy == Done.MAX_CHOICE_STRATEGY: return self.next_cell_max_choice() elif strategy == Done.FIRST_STRATEGY: return self.next_cell_first() elif strategy == Done.MAX_NEIGHBORS_STRATEGY: return self.next_cell_max_neighbors(pos) elif strategy == Done.MIN_NEIGHBORS_STRATEGY: return self.next_cell_min_neighbors(pos) else: raise Exception("Wrong strategy: %d" % strategy) ################################## class Node(object): def __init__(self, pos, id, links): self.pos = pos self.id = id self.links = links ################################## class Hex(object): def __init__(self, size): self.size = size self.count = 3 * size * (size - 1) + 1 self.nodes_by_id = self.count * [None] self.nodes_by_pos = {} id = 0 for y in range(size): for x in range(size + y): pos = (x, y) node = Node(pos, id, []) self.nodes_by_pos[pos] = node self.nodes_by_id[node.id] = node id += 1 for y in range(1, size): for x in range(y, size * 2 - 1): ry = size + y - 1 pos = (x, ry) node = Node(pos, id, []) self.nodes_by_pos[pos] = node self.nodes_by_id[node.id] = node id += 1 def link_nodes(self): for node in self.nodes_by_id: (x, y) = node.pos for dir in DIRS: nx = x + dir.x ny = y + dir.y if self.contains_pos((nx, ny)): node.links.append(self.nodes_by_pos[(nx, ny)].id) def contains_pos(self, pos): return pos in self.nodes_by_pos def get_by_pos(self, pos): return self.nodes_by_pos[pos] def get_by_id(self, id): return self.nodes_by_id[id] ################################## class Pos(object): def __init__(self, hex, tiles, done=None): self.hex = hex self.tiles = tiles self.done = Done(hex.count) if done is None else done def clone(self): return Pos(self.hex, self.tiles, self.done.clone()) ################################## def constraint_pass(pos, last_move=None): changed = False left = pos.tiles[:] done = pos.done # Remove impossible values from free cells free_cells = (range(done.count) if last_move is None else pos.hex.get_by_id(last_move).links) for i in free_cells: if not done.already_done(i): vmax = 0 vmin = 0 cells_around = pos.hex.get_by_id(i).links for nid in cells_around: if done.already_done(nid): if done[nid][0] != EMPTY: vmin += 1 vmax += 1 else: vmax += 1 for num in range(7): if (num < vmin) or (num > vmax): if done.remove(i, num): changed = True # Computes how many of each value is still free for cell in done.cells: if len(cell) == 1: left[cell[0]] -= 1 for v in range(8): # If there is none, remove the possibility from all tiles if (pos.tiles[v] > 0) and (left[v] == 0): if done.remove_unfixed(v): changed = True else: possible = sum((1 if v in cell else 0) for cell in done.cells) # If the number of possible cells for a value is exactly the number of available tiles # put a tile in each cell if pos.tiles[v] == possible: for i in range(done.count): cell = done.cells[i] if (not done.already_done(i)) and (v in cell): done.set_done(i, v) changed = True # Force empty or non-empty around filled cells filled_cells = (range(done.count) if last_move is None else [last_move]) for i in filled_cells: if done.already_done(i): num = done[i][0] empties = 0 filled = 0 unknown = [] cells_around = pos.hex.get_by_id(i).links for nid in cells_around: if done.already_done(nid): if done[nid][0] == EMPTY: empties += 1 else: filled += 1 else: unknown.append(nid) if len(unknown) > 0: if num == filled: for u in unknown: if EMPTY in done[u]: done.set_done(u, EMPTY) changed = True # else: # raise Exception("Houston, we've got a problem") elif num == filled + len(unknown): for u in unknown: if done.remove(u, EMPTY): changed = True return changed ASCENDING = 1 DESCENDING = -1 def find_moves(pos, strategy, order): done = pos.done cell_id = done.next_cell(pos, strategy) if cell_id < 0: return [] if order == ASCENDING: return [(cell_id, v) for v in done[cell_id]] else: # Try higher values first and EMPTY last moves = list(reversed([(cell_id, v) for v in done[cell_id] if v != EMPTY])) if EMPTY in done[cell_id]: moves.append((cell_id, EMPTY)) return moves def play_move(pos, move): (cell_id, i) = move pos.done.set_done(cell_id, i) def print_pos(pos, output): hex = pos.hex done = pos.done size = hex.size for y in range(size): print(" " * (size - y - 1), end="", file=output) for x in range(size + y): pos2 = (x, y) id = hex.get_by_pos(pos2).id if done.already_done(id): c = done[id][0] if done[id][0] != EMPTY else "." else: c = "?" print("%s " % c, end="", file=output) print(end="\n", file=output) for y in range(1, size): print(" " * y, end="", file=output) for x in range(y, size * 2 - 1): ry = size + y - 1 pos2 = (x, ry) id = hex.get_by_pos(pos2).id if done.already_done(id): c = done[id][0] if done[id][0] != EMPTY else "." else: c = "?" print("%s " % c, end="", file=output) print(end="\n", file=output) OPEN = 0 SOLVED = 1 IMPOSSIBLE = -1 def solved(pos, output, verbose=False): hex = pos.hex tiles = pos.tiles[:] done = pos.done exact = True all_done = True for i in range(hex.count): if len(done[i]) == 0: return IMPOSSIBLE elif done.already_done(i): num = done[i][0] tiles[num] -= 1 if (tiles[num] < 0): return IMPOSSIBLE vmax = 0 vmin = 0 if num != EMPTY: cells_around = hex.get_by_id(i).links for nid in cells_around: if done.already_done(nid): if done[nid][0] != EMPTY: vmin += 1 vmax += 1 else: vmax += 1 if (num < vmin) or (num > vmax): return IMPOSSIBLE if num != vmin: exact = False else: all_done = False if (not all_done) or (not exact): return OPEN print_pos(pos, output) return SOLVED def solve_step(prev, strategy, order, output, first=False): if first: pos = prev.clone() while constraint_pass(pos): pass else: pos = prev moves = find_moves(pos, strategy, order) if len(moves) == 0: return solved(pos, output) else: for move in moves: # print("Trying (%d, %d)" % (move[0], move[1])) ret = OPEN new_pos = pos.clone() play_move(new_pos, move) # print_pos(new_pos) while constraint_pass(new_pos, move[0]): pass cur_status = solved(new_pos, output) if cur_status != OPEN: ret = cur_status else: ret = solve_step(new_pos, strategy, order, output) if ret == SOLVED: return SOLVED return IMPOSSIBLE def check_valid(pos): hex = pos.hex tiles = pos.tiles # fill missing entries in tiles tot = 0 for i in range(8): if tiles[i] > 0: tot += tiles[i] else: tiles[i] = 0 # check total if tot != hex.count: raise Exception( "Invalid input. Expected %d tiles, got %d." % (hex.count, tot)) def solve(pos, strategy, order, output): check_valid(pos) return solve_step(pos, strategy, order, output, first=True) # TODO Write an 'iterator' to go over all x,y positions def read_file(file): lines = [line.strip("\r\n") for line in file.splitlines()] size = int(lines[0]) hex = Hex(size) linei = 1 tiles = 8 * [0] done = Done(hex.count) for y in range(size): line = lines[linei][size - y - 1:] p = 0 for x in range(size + y): tile = line[p:p + 2] p += 2 if tile[1] == ".": inctile = EMPTY else: inctile = int(tile) tiles[inctile] += 1 # Look for locked tiles if tile[0] == "+": # print("Adding locked tile: %d at pos %d, %d, id=%d" % # (inctile, x, y, hex.get_by_pos((x, y)).id)) done.set_done(hex.get_by_pos((x, y)).id, inctile) linei += 1 for y in range(1, size): ry = size - 1 + y line = lines[linei][y:] p = 0 for x in range(y, size * 2 - 1): tile = line[p:p + 2] p += 2 if tile[1] == ".": inctile = EMPTY else: inctile = int(tile) tiles[inctile] += 1 # Look for locked tiles if tile[0] == "+": # print("Adding locked tile: %d at pos %d, %d, id=%d" % # (inctile, x, ry, hex.get_by_pos((x, ry)).id)) done.set_done(hex.get_by_pos((x, ry)).id, inctile) linei += 1 hex.link_nodes() done.filter_tiles(tiles) return Pos(hex, tiles, done) def solve_file(file, strategy, order, output): pos = read_file(file) solve(pos, strategy, order, output) LEVELS = {} LEVELS[2] = (""" 2 . 1 . 1 1 1 . """, """\ 1 1 . . . 1 1 """) LEVELS[10] = (""" 3 +.+. . +. 0 . 2 . 1+2 1 . 2 . 0+. .+.+. """, """\ . . 1 . 1 . 2 0 . 2 2 . . . . . 0 . . """) LEVELS[20] = (""" 3 . 5 4 . 2+.+1 . 3+2 3 . +2+. 5 . . 3 . """, """\ 3 3 2 4 5 . 1 3 5 2 . . 2 . . . . . . """) LEVELS[25] = (""" 3 4 . . . . 2 . 4 3 2 . 4 2 2 3 . 4 2 4 """, """\ 3 4 2 2 4 4 . . . . 4 2 . 2 4 3 . 2 . """) LEVELS[30] = (""" 4 5 5 . . 3 . 2+2 6 3 . 2 . 5 . . 3 3+4 4 . 3 4 5 4 . 5 4 5+2 . . 3 4 . . . """, """\ 3 4 3 . 4 6 5 2 . 2 5 5 . . 2 . . 5 4 . 4 3 . 3 5 4 5 4 . 2 . 3 3 . . . . """) LEVELS[36] = (""" 4 2 1 1 2 3 3 3 . . 2 3 3 . 4 . . 2 . 2 4 3 2 2 2 . . . 2 4 3 4 . . 3 2 3 3 """, """\ 3 4 3 2 3 4 4 . 3 2 . . 3 4 3 2 . 1 . 3 . 2 3 3 . 2 . 2 3 . 2 . 2 2 2 . 1 """) ########################################################################### # Benchmark interface bm_params = { (100, 100): (1, 10, DESCENDING, Done.FIRST_STRATEGY), (1000, 1000): (1, 25, DESCENDING, Done.FIRST_STRATEGY), (5000, 1000): (10, 25, DESCENDING, Done.FIRST_STRATEGY), } def bm_setup(params): try: import uio as io except ImportError: import io loops, level, order, strategy = params board, solution = LEVELS[level] board = board.strip() expected = solution.rstrip() output = None def run(): nonlocal output for _ in range(loops): stream = io.StringIO() solve_file(board, strategy, order, stream) output = stream.getvalue() stream = None def result(): norm = params[0] * params[1] out = '\n'.join(line.rstrip() for line in output.splitlines()) return norm, ((out == expected), out) return run, result micropython-1.12/tests/perf_bench/bm_nqueens.py000066400000000000000000000036401357706137100217700ustar00rootroot00000000000000# Source: https://github.com/python/pyperformance # License: MIT # Simple, brute-force N-Queens solver. # author: collinwinter@google.com (Collin Winter) # n_queens function: Copyright 2009 Raymond Hettinger # Pure-Python implementation of itertools.permutations(). def permutations(iterable, r=None): """permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)""" pool = tuple(iterable) n = len(pool) if r is None: r = n indices = list(range(n)) cycles = list(range(n - r + 1, n + 1))[::-1] yield tuple(pool[i] for i in indices[:r]) while n: for i in reversed(range(r)): cycles[i] -= 1 if cycles[i] == 0: indices[i:] = indices[i + 1:] + indices[i:i + 1] cycles[i] = n - i else: j = cycles[i] indices[i], indices[-j] = indices[-j], indices[i] yield tuple(pool[i] for i in indices[:r]) break else: return # From http://code.activestate.com/recipes/576647/ def n_queens(queen_count): """N-Queens solver. Args: queen_count: the number of queens to solve for, same as board size. Yields: Solutions to the problem, each yielded value is a N-tuple. """ cols = range(queen_count) for vec in permutations(cols): if (queen_count == len(set(vec[i] + i for i in cols)) == len(set(vec[i] - i for i in cols))): yield vec ########################################################################### # Benchmark interface bm_params = { (50, 25): (1, 5), (100, 25): (1, 6), (1000, 100): (1, 7), (5000, 100): (1, 8), } def bm_setup(params): res = None def run(): nonlocal res for _ in range(params[0]): res = len(list(n_queens(params[1]))) def result(): return params[0] * 10 ** (params[1] - 3), res return run, result micropython-1.12/tests/perf_bench/bm_pidigits.py000066400000000000000000000026011357706137100221220ustar00rootroot00000000000000# Source: https://github.com/python/pyperformance # License: MIT # Calculating some of the digits of π. # This benchmark stresses big integer arithmetic. # Adapted from code on: http://benchmarksgame.alioth.debian.org/ def compose(a, b): aq, ar, as_, at = a bq, br, bs, bt = b return (aq * bq, aq * br + ar * bt, as_ * bq + at * bs, as_ * br + at * bt) def extract(z, j): q, r, s, t = z return (q * j + r) // (s * j + t) def gen_pi_digits(n): z = (1, 0, 0, 1) k = 1 digs = [] for _ in range(n): y = extract(z, 3) while y != extract(z, 4): z = compose(z, (k, 4 * k + 2, 0, 2 * k + 1)) k += 1 y = extract(z, 3) z = compose((10, -10 * y, 0, 1), z) digs.append(y) return digs ########################################################################### # Benchmark interface bm_params = { (50, 25): (1, 35), (100, 100): (1, 65), (1000, 1000): (2, 250), (5000, 1000): (3, 350), } def bm_setup(params): state = None def run(): nonlocal state nloop, ndig = params ndig = params[1] for _ in range(nloop): state = None # free previous result state = gen_pi_digits(ndig) def result(): return params[0] * params[1], ''.join(str(d) for d in state) return run, result micropython-1.12/tests/perf_bench/misc_aes.py000066400000000000000000000167151357706137100214260ustar00rootroot00000000000000# Pure Python AES encryption routines. # # AES is integer based and inplace so doesn't use the heap. It is therefore # a good test of raw performance and correctness of the VM/runtime. # # The AES code comes first (code originates from a C version authored by D.P.George) # and then the test harness at the bottom. # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd ################################################################## # discrete arithmetic routines, mostly from a precomputed table # non-linear, invertible, substitution box aes_s_box_table = bytes(( 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16, )) # multiplication of polynomials modulo x^8 + x^4 + x^3 + x + 1 = 0x11b def aes_gf8_mul_2(x): if x & 0x80: return (x << 1) ^ 0x11b else: return x << 1 def aes_gf8_mul_3(x): return x ^ aes_gf8_mul_2(x) # non-linear, invertible, substitution box def aes_s_box(a): return aes_s_box_table[a & 0xff] # return 0x02^(a-1) in GF(2^8) def aes_r_con(a): ans = 1 while a > 1: ans <<= 1; if ans & 0x100: ans ^= 0x11b a -= 1 return ans ################################################################## # basic AES algorithm; see FIPS-197 # all inputs must be size 16 def aes_add_round_key(state, w): for i in range(16): state[i] ^= w[i] # combined sub_bytes, shift_rows, mix_columns, add_round_key # all inputs must be size 16 def aes_sb_sr_mc_ark(state, w, w_idx, temp): temp_idx = 0 for i in range(4): x0 = aes_s_box_table[state[i * 4]] x1 = aes_s_box_table[state[1 + ((i + 1) & 3) * 4]] x2 = aes_s_box_table[state[2 + ((i + 2) & 3) * 4]] x3 = aes_s_box_table[state[3 + ((i + 3) & 3) * 4]] temp[temp_idx] = aes_gf8_mul_2(x0) ^ aes_gf8_mul_3(x1) ^ x2 ^ x3 ^ w[w_idx] temp[temp_idx + 1] = x0 ^ aes_gf8_mul_2(x1) ^ aes_gf8_mul_3(x2) ^ x3 ^ w[w_idx + 1] temp[temp_idx + 2] = x0 ^ x1 ^ aes_gf8_mul_2(x2) ^ aes_gf8_mul_3(x3) ^ w[w_idx + 2] temp[temp_idx + 3] = aes_gf8_mul_3(x0) ^ x1 ^ x2 ^ aes_gf8_mul_2(x3) ^ w[w_idx + 3] w_idx += 4 temp_idx += 4 for i in range(16): state[i] = temp[i] # combined sub_bytes, shift_rows, add_round_key # all inputs must be size 16 def aes_sb_sr_ark(state, w, w_idx, temp): temp_idx = 0 for i in range(4): x0 = aes_s_box_table[state[i * 4]] x1 = aes_s_box_table[state[1 + ((i + 1) & 3) * 4]] x2 = aes_s_box_table[state[2 + ((i + 2) & 3) * 4]] x3 = aes_s_box_table[state[3 + ((i + 3) & 3) * 4]] temp[temp_idx] = x0 ^ w[w_idx] temp[temp_idx + 1] = x1 ^ w[w_idx + 1] temp[temp_idx + 2] = x2 ^ w[w_idx + 2] temp[temp_idx + 3] = x3 ^ w[w_idx + 3] w_idx += 4 temp_idx += 4 for i in range(16): state[i] = temp[i] # take state as input and change it to the next state in the sequence # state and temp have size 16, w has size 16 * (Nr + 1), Nr >= 1 def aes_state(state, w, temp, nr): aes_add_round_key(state, w) w_idx = 16 for i in range(nr - 1): aes_sb_sr_mc_ark(state, w, w_idx, temp) w_idx += 16 aes_sb_sr_ark(state, w, w_idx, temp) # expand 'key' to 'w' for use with aes_state # key has size 4 * Nk, w has size 16 * (Nr + 1), temp has size 16 def aes_key_expansion(key, w, temp, nk, nr): for i in range(4 * nk): w[i] = key[i] w_idx = 4 * nk - 4 for i in range(nk, 4 * (nr + 1)): t = temp t_idx = 0 if i % nk == 0: t[0] = aes_s_box(w[w_idx + 1]) ^ aes_r_con(i // nk) for j in range(1, 4): t[j] = aes_s_box(w[w_idx + (j + 1) % 4]) elif nk > 6 and i % nk == 4: for j in range(0, 4): t[j] = aes_s_box(w[w_idx + j]) else: t = w t_idx = w_idx w_idx += 4 for j in range(4): w[w_idx + j] = w[w_idx + j - 4 * nk] ^ t[t_idx + j] ################################################################## # simple use of AES algorithm, using output feedback (OFB) mode class AES: def __init__(self, keysize): if keysize == 128: self.nk = 4 self.nr = 10 elif keysize == 192: self.nk = 6 self.nr = 12 else: assert keysize == 256 self.nk = 8 self.nr = 14 self.state = bytearray(16) self.w = bytearray(16 * (self.nr + 1)) self.temp = bytearray(16) self.state_pos = 16 def set_key(self, key): aes_key_expansion(key, self.w, self.temp, self.nk, self.nr) self.state_pos = 16 def set_iv(self, iv): for i in range(16): self.state[i] = iv[i] self.state_pos = 16; def get_some_state(self, n_needed): if self.state_pos >= 16: aes_state(self.state, self.w, self.temp, self.nr) self.state_pos = 0 n = 16 - self.state_pos if n > n_needed: n = n_needed return n def apply_to(self, data): idx = 0 n = len(data) while n > 0: ln = self.get_some_state(n) n -= ln for i in range(ln): data[idx + i] ^= self.state[self.state_pos + i] idx += ln self.state_pos += n ########################################################################### # Benchmark interface bm_params = { (50, 25): (1, 16), (100, 100): (1, 32), (1000, 1000): (4, 256), (5000, 1000): (20, 256), } def bm_setup(params): nloop, datalen = params aes = AES(256) key = bytearray(256 // 8) iv = bytearray(16) data = bytearray(datalen) # from now on we don't use the heap def run(): for loop in range(nloop): # encrypt aes.set_key(key) aes.set_iv(iv) for i in range(2): aes.apply_to(data) # decrypt aes.set_key(key) aes.set_iv(iv) for i in range(2): aes.apply_to(data) # verify for i in range(len(data)): assert data[i] == 0 def result(): return params[0] * params[1], True return run, result micropython-1.12/tests/perf_bench/misc_mandel.py000066400000000000000000000013231357706137100221030ustar00rootroot00000000000000# Compute the Mandelbrot set, to test complex numbers def mandelbrot(w, h): def in_set(c): z = 0 for i in range(32): z = z * z + c if abs(z) > 100: return i return 0 img = bytearray(w * h) xscale = ((w - 1) / 2.4) yscale = ((h - 1) / 3.2) for v in range(h): line = memoryview(img)[v * w:v * w + w] for u in range(w): c = in_set(complex(v / yscale - 2.3, u / xscale - 1.2)) line[u] = c return img bm_params = { (100, 100): (20, 20), (1000, 1000): (80, 80), (5000, 1000): (150, 150), } def bm_setup(ps): return lambda: mandelbrot(ps[0], ps[1]), lambda: (ps[0] * ps[1], None) micropython-1.12/tests/perf_bench/misc_pystone.py000066400000000000000000000132631357706137100223520ustar00rootroot00000000000000""" "PYSTONE" Benchmark Program Version: Python/1.2 (corresponds to C/1.1 plus 3 Pystone fixes) Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg. 1013. Translated from ADA to C by Rick Richardson. Every method to preserve ADA-likeness has been used, at the expense of C-ness. Translated from C to Python by Guido van Rossum. """ __version__ = "1.2" [Ident1, Ident2, Ident3, Ident4, Ident5] = range(1, 6) class Record: def __init__(self, PtrComp = None, Discr = 0, EnumComp = 0, IntComp = 0, StringComp = 0): self.PtrComp = PtrComp self.Discr = Discr self.EnumComp = EnumComp self.IntComp = IntComp self.StringComp = StringComp def copy(self): return Record(self.PtrComp, self.Discr, self.EnumComp, self.IntComp, self.StringComp) TRUE = 1 FALSE = 0 def Setup(): global IntGlob global BoolGlob global Char1Glob global Char2Glob global Array1Glob global Array2Glob IntGlob = 0 BoolGlob = FALSE Char1Glob = '\0' Char2Glob = '\0' Array1Glob = [0]*51 Array2Glob = [x[:] for x in [Array1Glob]*51] def Proc0(loops): global IntGlob global BoolGlob global Char1Glob global Char2Glob global Array1Glob global Array2Glob global PtrGlb global PtrGlbNext PtrGlbNext = Record() PtrGlb = Record() PtrGlb.PtrComp = PtrGlbNext PtrGlb.Discr = Ident1 PtrGlb.EnumComp = Ident3 PtrGlb.IntComp = 40 PtrGlb.StringComp = "DHRYSTONE PROGRAM, SOME STRING" String1Loc = "DHRYSTONE PROGRAM, 1'ST STRING" Array2Glob[8][7] = 10 for i in range(loops): Proc5() Proc4() IntLoc1 = 2 IntLoc2 = 3 String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING" EnumLoc = Ident2 BoolGlob = not Func2(String1Loc, String2Loc) while IntLoc1 < IntLoc2: IntLoc3 = 5 * IntLoc1 - IntLoc2 IntLoc3 = Proc7(IntLoc1, IntLoc2) IntLoc1 = IntLoc1 + 1 Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3) PtrGlb = Proc1(PtrGlb) CharIndex = 'A' while CharIndex <= Char2Glob: if EnumLoc == Func1(CharIndex, 'C'): EnumLoc = Proc6(Ident1) CharIndex = chr(ord(CharIndex)+1) IntLoc3 = IntLoc2 * IntLoc1 IntLoc2 = IntLoc3 // IntLoc1 IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1 IntLoc1 = Proc2(IntLoc1) def Proc1(PtrParIn): PtrParIn.PtrComp = NextRecord = PtrGlb.copy() PtrParIn.IntComp = 5 NextRecord.IntComp = PtrParIn.IntComp NextRecord.PtrComp = PtrParIn.PtrComp NextRecord.PtrComp = Proc3(NextRecord.PtrComp) if NextRecord.Discr == Ident1: NextRecord.IntComp = 6 NextRecord.EnumComp = Proc6(PtrParIn.EnumComp) NextRecord.PtrComp = PtrGlb.PtrComp NextRecord.IntComp = Proc7(NextRecord.IntComp, 10) else: PtrParIn = NextRecord.copy() NextRecord.PtrComp = None return PtrParIn def Proc2(IntParIO): IntLoc = IntParIO + 10 while 1: if Char1Glob == 'A': IntLoc = IntLoc - 1 IntParIO = IntLoc - IntGlob EnumLoc = Ident1 if EnumLoc == Ident1: break return IntParIO def Proc3(PtrParOut): global IntGlob if PtrGlb is not None: PtrParOut = PtrGlb.PtrComp else: IntGlob = 100 PtrGlb.IntComp = Proc7(10, IntGlob) return PtrParOut def Proc4(): global Char2Glob BoolLoc = Char1Glob == 'A' BoolLoc = BoolLoc or BoolGlob Char2Glob = 'B' def Proc5(): global Char1Glob global BoolGlob Char1Glob = 'A' BoolGlob = FALSE def Proc6(EnumParIn): EnumParOut = EnumParIn if not Func3(EnumParIn): EnumParOut = Ident4 if EnumParIn == Ident1: EnumParOut = Ident1 elif EnumParIn == Ident2: if IntGlob > 100: EnumParOut = Ident1 else: EnumParOut = Ident4 elif EnumParIn == Ident3: EnumParOut = Ident2 elif EnumParIn == Ident4: pass elif EnumParIn == Ident5: EnumParOut = Ident3 return EnumParOut def Proc7(IntParI1, IntParI2): IntLoc = IntParI1 + 2 IntParOut = IntParI2 + IntLoc return IntParOut def Proc8(Array1Par, Array2Par, IntParI1, IntParI2): global IntGlob IntLoc = IntParI1 + 5 Array1Par[IntLoc] = IntParI2 Array1Par[IntLoc+1] = Array1Par[IntLoc] Array1Par[IntLoc+30] = IntLoc for IntIndex in range(IntLoc, IntLoc+2): Array2Par[IntLoc][IntIndex] = IntLoc Array2Par[IntLoc][IntLoc-1] = Array2Par[IntLoc][IntLoc-1] + 1 Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc] IntGlob = 5 def Func1(CharPar1, CharPar2): CharLoc1 = CharPar1 CharLoc2 = CharLoc1 if CharLoc2 != CharPar2: return Ident1 else: return Ident2 def Func2(StrParI1, StrParI2): IntLoc = 1 while IntLoc <= 1: if Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1: CharLoc = 'A' IntLoc = IntLoc + 1 if CharLoc >= 'W' and CharLoc <= 'Z': IntLoc = 7 if CharLoc == 'X': return TRUE else: if StrParI1 > StrParI2: IntLoc = IntLoc + 7 return TRUE else: return FALSE def Func3(EnumParIn): EnumLoc = EnumParIn if EnumLoc == Ident3: return TRUE return FALSE ########################################################################### # Benchmark interface bm_params = { (50, 10): (80,), (100, 10): (300,), (1000, 10): (4000,), (5000, 10): (20000,), } def bm_setup(params): Setup() return lambda: Proc0(params[0]), lambda: (params[0], 0) micropython-1.12/tests/perf_bench/misc_raytrace.py000066400000000000000000000161561357706137100224670ustar00rootroot00000000000000# A simple ray tracer # MIT license; Copyright (c) 2019 Damien P. George INF = 1e30 EPS = 1e-6 class Vec: def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def __neg__(self): return Vec(-self.x, -self.y, -self.z) def __add__(self, rhs): return Vec(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z) def __sub__(self, rhs): return Vec(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z) def __mul__(self, rhs): return Vec(self.x * rhs, self.y * rhs, self.z * rhs) def length(self): return (self.x ** 2 + self.y ** 2 + self.z ** 2) ** 0.5 def normalise(self): l = self.length() return Vec(self.x / l, self.y / l, self.z / l) def dot(self, rhs): return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z RGB = Vec class Ray: def __init__(self, p, d): self.p, self.d = p, d class View: def __init__(self, width, height, depth, pos, xdir, ydir, zdir): self.width = width self.height = height self.depth = depth self.pos = pos self.xdir = xdir self.ydir = ydir self.zdir = zdir def calc_dir(self, dx, dy): return (self.xdir * dx + self.ydir * dy + self.zdir * self.depth).normalise() class Light: def __init__(self, pos, colour, casts_shadows): self.pos = pos self.colour = colour self.casts_shadows = casts_shadows class Surface: def __init__(self, diffuse, specular, spec_idx, reflect, transp, colour): self.diffuse = diffuse self.specular = specular self.spec_idx = spec_idx self.reflect = reflect self.transp = transp self.colour = colour @staticmethod def dull(colour): return Surface(0.7, 0.0, 1, 0.0, 0.0, colour * 0.6) @staticmethod def shiny(colour): return Surface(0.2, 0.9, 32, 0.8, 0.0, colour * 0.3) @staticmethod def transparent(colour): return Surface(0.2, 0.9, 32, 0.0, 0.8, colour * 0.3) class Sphere: def __init__(self, surface, centre, radius): self.surface = surface self.centre = centre self.radsq = radius ** 2 def intersect(self, ray): v = self.centre - ray.p b = v.dot(ray.d) det = b ** 2 - v.dot(v) + self.radsq if det > 0: det **= 0.5 t1 = b - det if t1 > EPS: return t1 t2 = b + det if t2 > EPS: return t2 return INF def surface_at(self, v): return self.surface, (v - self.centre).normalise() class Plane: def __init__(self, surface, centre, normal): self.surface = surface self.normal = normal.normalise() self.cdotn = centre.dot(normal) def intersect(self, ray): ddotn = ray.d.dot(self.normal) if abs(ddotn) > EPS: t = (self.cdotn - ray.p.dot(self.normal)) / ddotn if t > 0: return t return INF def surface_at(self, p): return self.surface, self.normal class Scene: def __init__(self, ambient, light, objs): self.ambient = ambient self.light = light self.objs = objs def trace_scene(canvas, view, scene, max_depth): for v in range(canvas.height): y = (-v + 0.5 * (canvas.height - 1)) * view.height / canvas.height for u in range(canvas.width): x = (u - 0.5 * (canvas.width - 1)) * view.width / canvas.width ray = Ray(view.pos, view.calc_dir(x, y)) c = trace_ray(scene, ray, max_depth) canvas.put_pix(u, v, c) def trace_ray(scene, ray, depth): # Find closest intersecting object hit_t = INF hit_obj = None for obj in scene.objs: t = obj.intersect(ray) if t < hit_t: hit_t = t hit_obj = obj # Check if any objects hit if hit_obj is None: return RGB(0, 0, 0) # Compute location of ray intersection point = ray.p + ray.d * hit_t surf, surf_norm = hit_obj.surface_at(point) if ray.d.dot(surf_norm) > 0: surf_norm = -surf_norm # Compute reflected ray reflected = ray.d - surf_norm * (surf_norm.dot(ray.d) * 2) # Ambient light col = surf.colour * scene.ambient # Diffuse, specular and shadow from light source light_vec = scene.light.pos - point light_dist = light_vec.length() light_vec = light_vec.normalise() ndotl = surf_norm.dot(light_vec) ldotv = light_vec.dot(reflected) if ndotl > 0 or ldotv > 0: light_ray = Ray(point + light_vec * EPS, light_vec) light_col = trace_to_light(scene, light_ray, light_dist) if ndotl > 0: col += light_col * surf.diffuse * ndotl if ldotv > 0: col += light_col * surf.specular * ldotv ** surf.spec_idx # Reflections if depth > 0 and surf.reflect > 0: col += trace_ray(scene, Ray(point + reflected * EPS, reflected), depth - 1) * surf.reflect # Transparency if depth > 0 and surf.transp > 0: col += trace_ray(scene, Ray(point + ray.d * EPS, ray.d), depth - 1) * surf.transp return col def trace_to_light(scene, ray, light_dist): col = scene.light.colour for obj in scene.objs: t = obj.intersect(ray) if t < light_dist: col *= obj.surface.transp return col class Canvas: def __init__(self, width, height): self.width = width self.height = height self.data = bytearray(3 * width * height) def put_pix(self, x, y, c): off = 3 * (y * self.width + x) self.data[off] = min(255, max(0, int(255 * c.x))) self.data[off + 1] = min(255, max(0, int(255 * c.y))) self.data[off + 2] = min(255, max(0, int(255 * c.z))) def write_ppm(self, filename): with open(filename, 'wb') as f: f.write(bytes('P6 %d %d 255\n' % (self.width, self.height), 'ascii')) f.write(self.data) def main(w, h, d): canvas = Canvas(w, h) view = View(32, 32, 64, Vec(0, 0, 50), Vec(1, 0, 0), Vec(0, 1, 0), Vec(0, 0, -1)) scene = Scene( 0.5, Light(Vec(0, 8, 0), RGB(1, 1, 1), True), [ Plane(Surface.dull(RGB(1, 0, 0)), Vec(-10, 0, 0), Vec(1, 0, 0)), Plane(Surface.dull(RGB(0, 1, 0)), Vec(10, 0, 0), Vec(-1, 0, 0)), Plane(Surface.dull(RGB(1, 1, 1)), Vec(0, 0, -10), Vec(0, 0, 1)), Plane(Surface.dull(RGB(1, 1, 1)), Vec(0, -10, 0), Vec(0, 1, 0)), Plane(Surface.dull(RGB(1, 1, 1)), Vec(0, 10, 0), Vec(0, -1, 0)), Sphere(Surface.shiny(RGB(1, 1, 1)), Vec(-5, -4, 3), 4), Sphere(Surface.dull(RGB(0, 0, 1)), Vec(4, -5, 0), 4), Sphere(Surface.transparent(RGB(0.2, 0.2, 0.2)), Vec(6, -1, 8), 4), ] ) trace_scene(canvas, view, scene, d) return canvas # For testing #main(256, 256, 4).write_ppm('rt.ppm') ########################################################################### # Benchmark interface bm_params = { (100, 100): (5, 5, 2), (1000, 100): (18, 18, 3), (5000, 100): (40, 40, 3), } def bm_setup(params): return lambda: main(*params), lambda: (params[0] * params[1] * params[2], None) micropython-1.12/tests/perf_bench/viper_call0.py000066400000000000000000000005141357706137100220310ustar00rootroot00000000000000@micropython.viper def f0(): pass @micropython.native def call(r): f = f0 for _ in r: f() bm_params = { (50, 10): (15000,), (100, 10): (30000,), (1000, 10): (300000,), (5000, 10): (1500000,), } def bm_setup(params): return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) micropython-1.12/tests/perf_bench/viper_call1a.py000066400000000000000000000005241357706137100221740ustar00rootroot00000000000000@micropython.viper def f1a(x): return x @micropython.native def call(r): f = f1a for _ in r: f(1) bm_params = { (50, 10): (15000,), (100, 10): (30000,), (1000, 10): (300000,), (5000, 10): (1500000,), } def bm_setup(params): return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) micropython-1.12/tests/perf_bench/viper_call1b.py000066400000000000000000000005401357706137100221730ustar00rootroot00000000000000@micropython.viper def f1b(x) -> int: return int(x) @micropython.native def call(r): f = f1b for _ in r: f(1) bm_params = { (50, 10): (15000,), (100, 10): (30000,), (1000, 10): (300000,), (5000, 10): (1500000,), } def bm_setup(params): return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) micropython-1.12/tests/perf_bench/viper_call1c.py000066400000000000000000000005371357706137100222020ustar00rootroot00000000000000@micropython.viper def f1c(x:int) -> int: return x @micropython.native def call(r): f = f1c for _ in r: f(1) bm_params = { (50, 10): (15000,), (100, 10): (30000,), (1000, 10): (300000,), (5000, 10): (1500000,), } def bm_setup(params): return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) micropython-1.12/tests/perf_bench/viper_call2a.py000066400000000000000000000005321357706137100221740ustar00rootroot00000000000000@micropython.viper def f2a(x, y): return x @micropython.native def call(r): f = f2a for _ in r: f(1, 2) bm_params = { (50, 10): (15000,), (100, 10): (30000,), (1000, 10): (300000,), (5000, 10): (1500000,), } def bm_setup(params): return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) micropython-1.12/tests/perf_bench/viper_call2b.py000066400000000000000000000005551357706137100222020ustar00rootroot00000000000000@micropython.viper def f2b(x:int, y:int) -> int: return x + y @micropython.native def call(r): f = f2b for _ in r: f(1, 2) bm_params = { (50, 10): (15000,), (100, 10): (30000,), (1000, 10): (300000,), (5000, 10): (1500000,), } def bm_setup(params): return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) micropython-1.12/tests/pyb/000077500000000000000000000000001357706137100157565ustar00rootroot00000000000000micropython-1.12/tests/pyb/accel.py000066400000000000000000000002631357706137100174000ustar00rootroot00000000000000import pyb if not hasattr(pyb, 'Accel'): print('SKIP') raise SystemExit accel = pyb.Accel() print(accel) accel.x() accel.y() accel.z() accel.tilt() accel.filtered_xyz() micropython-1.12/tests/pyb/accel.py.exp000066400000000000000000000000101357706137100201610ustar00rootroot00000000000000 micropython-1.12/tests/pyb/adc.py000066400000000000000000000030031357706137100170530ustar00rootroot00000000000000from pyb import ADC, Timer adct = ADC(16) # Temperature 930 -> 20C print(str(adct)[:19]) adcv = ADC(17) # Voltage 1500 -> 3.3V print(adcv) # read single sample; 2.5V-5V is pass range val = adcv.read() assert val > 1000 and val < 2000 # timer for read_timed tim = Timer(5, freq=500) # read into bytearray buf = bytearray(b'\xff' * 50) adcv.read_timed(buf, tim) print(len(buf)) for i in buf: assert i > 50 and i < 150 # read into arrays with different element sizes import array arv = array.array('h', 25 * [0x7fff]) adcv.read_timed(arv, tim) print(len(arv)) for i in arv: assert i > 1000 and i < 2000 arv = array.array('i', 30 * [-1]) adcv.read_timed(arv, tim) print(len(arv)) for i in arv: assert i > 1000 and i < 2000 # Test read_timed_multi arv = bytearray(b'\xff'*50) art = bytearray(b'\xff'*50) ADC.read_timed_multi((adcv, adct), (arv, art), tim) for i in arv: assert i > 60 and i < 125 # Wide range: unsure of accuracy of temp sensor. for i in art: assert i > 15 and i < 200 arv = array.array('i', 25 * [-1]) art = array.array('i', 25 * [-1]) ADC.read_timed_multi((adcv, adct), (arv, art), tim) for i in arv: assert i > 1000 and i < 2000 # Wide range: unsure of accuracy of temp sensor. for i in art: assert i > 50 and i < 2000 arv = array.array('h', 25 * [0x7fff]) art = array.array('h', 25 * [0x7fff]) ADC.read_timed_multi((adcv, adct), (arv, art), tim) for i in arv: assert i > 1000 and i < 2000 # Wide range: unsure of accuracy of temp sensor. for i in art: assert i > 50 and i < 2000 micropython-1.12/tests/pyb/adc.py.exp000066400000000000000000000000641357706137100176520ustar00rootroot00000000000000 50 25 30 micropython-1.12/tests/pyb/adcall.py000066400000000000000000000012731357706137100175530ustar00rootroot00000000000000from pyb import Pin, ADCAll pins = [Pin.cpu.A0, Pin.cpu.A1, Pin.cpu.A2, Pin.cpu.A3] # set pins to IN mode, init ADCAll, then check pins are ANALOG for p in pins: p.init(p.IN) adc = ADCAll(12) for p in pins: print(p) # set pins to IN mode, init ADCAll with mask, then check some pins are ANALOG for p in pins: p.init(p.IN) adc = ADCAll(12, 0x70003) for p in pins: print(p) # init all pins to ANALOG adc = ADCAll(12) print(adc) # read all channels for c in range(19): print(type(adc.read_channel(c))) # call special reading functions print(0 < adc.read_core_temp() < 100) print(0 < adc.read_core_vbat() < 4) print(0 < adc.read_core_vref() < 2) print(0 < adc.read_vref() < 4) micropython-1.12/tests/pyb/adcall.py.exp000066400000000000000000000010471357706137100203450ustar00rootroot00000000000000Pin(Pin.cpu.A0, mode=Pin.ANALOG) Pin(Pin.cpu.A1, mode=Pin.ANALOG) Pin(Pin.cpu.A2, mode=Pin.ANALOG) Pin(Pin.cpu.A3, mode=Pin.ANALOG) Pin(Pin.cpu.A0, mode=Pin.ANALOG) Pin(Pin.cpu.A1, mode=Pin.ANALOG) Pin(Pin.cpu.A2, mode=Pin.IN) Pin(Pin.cpu.A3, mode=Pin.IN) True True True True micropython-1.12/tests/pyb/board_pybv1x.py000066400000000000000000000016171357706137100207350ustar00rootroot00000000000000# Test board-specific items on PYBv1.x import os, pyb if not 'PYBv1.' in os.uname().machine: print('SKIP') raise SystemExit # test creating UART by id/name for bus in (1, 2, 3, 4, 5, 6, 7, "XA", "XB", "YA", "YB", "Z"): try: pyb.UART(bus, 9600) print("UART", bus) except ValueError: print("ValueError", bus) # test creating SPI by id/name for bus in (1, 2, 3, "X", "Y", "Z"): try: pyb.SPI(bus) print("SPI", bus) except ValueError: print("ValueError", bus) # test creating I2C by id/name for bus in (2, 3, "X", "Y", "Z"): try: pyb.I2C(bus) print("I2C", bus) except ValueError: print("ValueError", bus) # test creating CAN by id/name for bus in (1, 2, 3, "YA", "YB", "YC"): try: pyb.CAN(bus, pyb.CAN.LOOPBACK) print("CAN", bus) except ValueError: print("ValueError", bus) micropython-1.12/tests/pyb/board_pybv1x.py.exp000066400000000000000000000003751357706137100215300ustar00rootroot00000000000000UART 1 UART 2 UART 3 UART 4 ValueError 5 UART 6 ValueError 7 UART XA UART XB UART YA UART YB ValueError Z SPI 1 SPI 2 ValueError 3 SPI X SPI Y ValueError Z I2C 2 ValueError 3 I2C X I2C Y ValueError Z CAN 1 CAN 2 ValueError 3 CAN YA CAN YB ValueError YC micropython-1.12/tests/pyb/can.py000066400000000000000000000143431357706137100170760ustar00rootroot00000000000000try: from pyb import CAN except ImportError: print('SKIP') raise SystemExit from array import array import micropython import pyb # test we can correctly create by id (2 handled in can2.py test) for bus in (-1, 0, 1, 3): try: CAN(bus, CAN.LOOPBACK) print("CAN", bus) except ValueError: print("ValueError", bus) CAN(1).deinit() CAN.initfilterbanks(14) can = CAN(1) print(can) # Test state when de-init'd print(can.state() == can.STOPPED) can.init(CAN.LOOPBACK) print(can) print(can.any(0)) # Test state when freshly created print(can.state() == can.ERROR_ACTIVE) # Test that restart can be called can.restart() # Test info returns a sensible value print(can.info()) # Catch all filter can.setfilter(0, CAN.MASK16, 0, (0, 0, 0, 0)) can.send('abcd', 123, timeout=5000) print(can.any(0), can.info()) print(can.recv(0)) can.send('abcd', -1, timeout=5000) print(can.recv(0)) can.send('abcd', 0x7FF + 1, timeout=5000) print(can.recv(0)) # Test too long message try: can.send('abcdefghi', 0x7FF, timeout=5000) except ValueError: print('passed') else: print('failed') # Test that recv can work without allocating memory on the heap buf = bytearray(10) l = [0, 0, 0, memoryview(buf)] l2 = None micropython.heap_lock() can.send('', 42) l2 = can.recv(0, l) assert l is l2 print(l, len(l[3]), buf) can.send('1234', 42) l2 = can.recv(0, l) assert l is l2 print(l, len(l[3]), buf) can.send('01234567', 42) l2 = can.recv(0, l) assert l is l2 print(l, len(l[3]), buf) can.send('abc', 42) l2 = can.recv(0, l) assert l is l2 print(l, len(l[3]), buf) micropython.heap_unlock() # Test that recv can work with different arrays behind the memoryview can.send('abc', 1) print(bytes(can.recv(0, [0, 0, 0, memoryview(array('B', range(8)))])[3])) can.send('def', 1) print(bytes(can.recv(0, [0, 0, 0, memoryview(array('b', range(8)))])[3])) # Test for non-list passed as second arg to recv can.send('abc', 1) try: can.recv(0, 1) except TypeError: print('TypeError') # Test for too-short-list passed as second arg to recv can.send('abc', 1) try: can.recv(0, [0, 0, 0]) except ValueError: print('ValueError') # Test for non-memoryview passed as 4th element to recv can.send('abc', 1) try: can.recv(0, [0, 0, 0, 0]) except TypeError: print('TypeError') # Test for read-only-memoryview passed as 4th element to recv can.send('abc', 1) try: can.recv(0, [0, 0, 0, memoryview(bytes(8))]) except ValueError: print('ValueError') # Test for bad-typecode-memoryview passed as 4th element to recv can.send('abc', 1) try: can.recv(0, [0, 0, 0, memoryview(array('i', range(8)))]) except ValueError: print('ValueError') del can # Testing extended IDs can = CAN(1, CAN.LOOPBACK, extframe = True) # Catch all filter can.setfilter(0, CAN.MASK32, 0, (0, 0)) print(can) try: can.send('abcde', 0x7FF + 1, timeout=5000) except ValueError: print('failed') else: r = can.recv(0) if r[0] == 0x7FF+1 and r[3] == b'abcde': print('passed') else: print('failed, wrong data received') # Test filters for n in [0, 8, 16, 24]: filter_id = 0b00001000 << n filter_mask = 0b00011100 << n id_ok = 0b00001010 << n id_fail = 0b00011010 << n can.clearfilter(0) can.setfilter(0, pyb.CAN.MASK32, 0, (filter_id, filter_mask)) can.send('ok', id_ok, timeout=3) if can.any(0): msg = can.recv(0) print((hex(filter_id), hex(filter_mask), hex(msg[0]), msg[3])) can.send("fail", id_fail, timeout=3) if can.any(0): msg = can.recv(0) print((hex(filter_id), hex(filter_mask), hex(msg[0]), msg[3])) del can # Test RxCallbacks can = CAN(1, CAN.LOOPBACK) can.setfilter(0, CAN.LIST16, 0, (1, 2, 3, 4)) can.setfilter(1, CAN.LIST16, 1, (5, 6, 7, 8)) def cb0(bus, reason): print('cb0') if reason == 0: print('pending') if reason == 1: print('full') if reason == 2: print('overflow') def cb1(bus, reason): print('cb1') if reason == 0: print('pending') if reason == 1: print('full') if reason == 2: print('overflow') def cb0a(bus, reason): print('cb0a') if reason == 0: print('pending') if reason == 1: print('full') if reason == 2: print('overflow') def cb1a(bus, reason): print('cb1a') if reason == 0: print('pending') if reason == 1: print('full') if reason == 2: print('overflow') can.rxcallback(0, cb0) can.rxcallback(1, cb1) can.send('11111111',1, timeout=5000) can.send('22222222',2, timeout=5000) can.send('33333333',3, timeout=5000) can.rxcallback(0, cb0a) can.send('44444444',4, timeout=5000) can.send('55555555',5, timeout=5000) can.send('66666666',6, timeout=5000) can.send('77777777',7, timeout=5000) can.rxcallback(1, cb1a) can.send('88888888',8, timeout=5000) print(can.recv(0)) print(can.recv(0)) print(can.recv(0)) print(can.recv(1)) print(can.recv(1)) print(can.recv(1)) can.send('11111111',1, timeout=5000) can.send('55555555',5, timeout=5000) print(can.recv(0)) print(can.recv(1)) del can # Testing asynchronous send can = CAN(1, CAN.LOOPBACK) can.setfilter(0, CAN.MASK16, 0, (0, 0, 0, 0)) while can.any(0): can.recv(0) can.send('abcde', 1, timeout=0) print(can.any(0)) while not can.any(0): pass print(can.recv(0)) try: can.send('abcde', 2, timeout=0) can.send('abcde', 3, timeout=0) can.send('abcde', 4, timeout=0) can.send('abcde', 5, timeout=0) except OSError as e: if str(e) == '16': print('passed') else: print('failed') pyb.delay(500) while can.any(0): print(can.recv(0)) # Testing rtr messages bus1 = CAN(1, CAN.LOOPBACK) while bus1.any(0): bus1.recv(0) bus1.setfilter(0, CAN.LIST16, 0, (1, 2, 3, 4)) bus1.setfilter(1, CAN.LIST16, 0, (5, 6, 7, 8), rtr=(True, True, True, True)) bus1.setfilter(2, CAN.MASK16, 0, (64, 64, 32, 32), rtr=(False, True)) bus1.send('',1,rtr=True) print(bus1.any(0)) bus1.send('',5,rtr=True) print(bus1.recv(0)) bus1.send('',6,rtr=True) print(bus1.recv(0)) bus1.send('',7,rtr=True) print(bus1.recv(0)) bus1.send('',16,rtr=True) print(bus1.any(0)) bus1.send('',32,rtr=True) print(bus1.recv(0)) # test HAL error, timeout can = pyb.CAN(1, pyb.CAN.NORMAL) try: can.send('1', 1, timeout=50) except OSError as e: print(repr(e)) micropython-1.12/tests/pyb/can.py.exp000066400000000000000000000025101357706137100176620ustar00rootroot00000000000000ValueError -1 ValueError 0 CAN 1 ValueError 3 CAN(1) True CAN(1, CAN.LOOPBACK, extframe=False, auto_restart=False) False True [0, 0, 0, 0, 0, 0, 0, 0] True [0, 0, 0, 0, 0, 0, 1, 0] (123, False, 0, b'abcd') (2047, False, 0, b'abcd') (0, False, 0, b'abcd') passed [42, False, 0, ] 0 bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') [42, False, 0, ] 4 bytearray(b'1234\x00\x00\x00\x00\x00\x00') [42, False, 0, ] 8 bytearray(b'01234567\x00\x00') [42, False, 0, ] 3 bytearray(b'abc34567\x00\x00') b'abc' b'def' TypeError ValueError TypeError ValueError ValueError CAN(1, CAN.LOOPBACK, extframe=True, auto_restart=False) passed ('0x8', '0x1c', '0xa', b'ok') ('0x800', '0x1c00', '0xa00', b'ok') ('0x80000', '0x1c0000', '0xa0000', b'ok') ('0x8000000', '0x1c000000', '0xa000000', b'ok') cb0 pending cb0 full cb0a overflow cb1 pending cb1 full cb1a overflow (1, False, 0, b'11111111') (2, False, 1, b'22222222') (4, False, 3, b'44444444') (5, False, 0, b'55555555') (6, False, 1, b'66666666') (8, False, 3, b'88888888') cb0a pending cb1a pending (1, False, 0, b'11111111') (5, False, 0, b'55555555') False (1, False, 0, b'abcde') passed (2, False, 0, b'abcde') (3, False, 0, b'abcde') (4, False, 0, b'abcde') False (5, True, 4, b'') (6, True, 5, b'') (7, True, 6, b'') False (32, True, 9, b'') OSError(110,) micropython-1.12/tests/pyb/can2.py000066400000000000000000000011641357706137100171550ustar00rootroot00000000000000try: from pyb import CAN CAN(2) except (ImportError, ValueError): print('SKIP') raise SystemExit # Testing rtr messages bus2 = CAN(2, CAN.LOOPBACK, extframe=True) while bus2.any(0): bus2.recv(0) bus2.setfilter(0, CAN.LIST32, 0, (1, 2), rtr=(True, True)) bus2.setfilter(1, CAN.LIST32, 0, (3, 4), rtr=(True, False)) bus2.setfilter(2, CAN.MASK32, 0, (16, 16), rtr=(False,)) bus2.setfilter(2, CAN.MASK32, 0, (32, 32), rtr=(True,)) bus2.send('',1,rtr=True) print(bus2.recv(0)) bus2.send('',2,rtr=True) print(bus2.recv(0)) bus2.send('',3,rtr=True) print(bus2.recv(0)) bus2.send('',4,rtr=True) print(bus2.any(0)) micropython-1.12/tests/pyb/can2.py.exp000066400000000000000000000000741357706137100177470ustar00rootroot00000000000000(1, True, 0, b'') (2, True, 1, b'') (3, True, 2, b'') False micropython-1.12/tests/pyb/dac.py000066400000000000000000000004621357706137100170610ustar00rootroot00000000000000import pyb if not hasattr(pyb, 'DAC'): print('SKIP') raise SystemExit dac = pyb.DAC(1) print(dac) dac.noise(100) dac.triangle(100) dac.write(0) dac.write_timed(bytearray(10), 100, mode=pyb.DAC.NORMAL) pyb.delay(20) dac.write(0) # test buffering arg dac = pyb.DAC(1, buffering=True) dac.write(0) micropython-1.12/tests/pyb/dac.py.exp000066400000000000000000000000171357706137100176500ustar00rootroot00000000000000DAC(1, bits=8) micropython-1.12/tests/pyb/extint.py000066400000000000000000000005411357706137100176430ustar00rootroot00000000000000import pyb # test basic functionality ext = pyb.ExtInt('X5', pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_DOWN, lambda l:print('line:', l)) ext.disable() ext.enable() print(ext.line()) ext.swint() # test swint while disabled, then again after re-enabled ext.disable() ext.swint() ext.enable() ext.swint() # disable now that the test is finished ext.disable() micropython-1.12/tests/pyb/extint.py.exp000066400000000000000000000000221357706137100204300ustar00rootroot000000000000004 line: 4 line: 4 micropython-1.12/tests/pyb/i2c.py000066400000000000000000000004341357706137100170060ustar00rootroot00000000000000import pyb from pyb import I2C # test we can correctly create by id for bus in (-1, 0, 1): try: I2C(bus) print("I2C", bus) except ValueError: print("ValueError", bus) i2c = I2C(1) i2c.init(I2C.MASTER, baudrate=400000) print(i2c.scan()) i2c.deinit() micropython-1.12/tests/pyb/i2c.py.exp000066400000000000000000000000441357706137100175760ustar00rootroot00000000000000ValueError -1 ValueError 0 I2C 1 [] micropython-1.12/tests/pyb/i2c_accel.py000066400000000000000000000007021357706137100201330ustar00rootroot00000000000000# use accelerometer to test i2c bus import pyb from pyb import I2C if not hasattr(pyb, 'Accel'): print('SKIP') raise SystemExit accel_addr = 76 pyb.Accel() # this will init the MMA for us i2c = I2C(1, I2C.MASTER, baudrate=400000) print(i2c.scan()) print(i2c.is_ready(accel_addr)) print(i2c.mem_read(1, accel_addr, 7, timeout=500)) i2c.mem_write(0, accel_addr, 0, timeout=500) i2c.send(7, addr=accel_addr) i2c.recv(1, addr=accel_addr) micropython-1.12/tests/pyb/i2c_accel.py.exp000066400000000000000000000000221357706137100207210ustar00rootroot00000000000000[76] True b'\x01' micropython-1.12/tests/pyb/i2c_error.py000066400000000000000000000022561357706137100202230ustar00rootroot00000000000000# test I2C errors, with polling (disabled irqs) and DMA import pyb from pyb import I2C if not hasattr(pyb, 'Accel'): print('SKIP') raise SystemExit # init accelerometer pyb.Accel() # get I2C bus i2c = I2C(1, I2C.MASTER, dma=True) # test polling mem_read pyb.disable_irq() i2c.mem_read(1, 76, 0x0a) # should succeed pyb.enable_irq() try: pyb.disable_irq() i2c.mem_read(1, 77, 0x0a) # should fail except OSError as e: pyb.enable_irq() print(repr(e)) i2c.mem_read(1, 76, 0x0a) # should succeed # test polling mem_write pyb.disable_irq() i2c.mem_write(1, 76, 0x0a) # should succeed pyb.enable_irq() try: pyb.disable_irq() i2c.mem_write(1, 77, 0x0a) # should fail except OSError as e: pyb.enable_irq() print(repr(e)) i2c.mem_write(1, 76, 0x0a) # should succeed # test DMA mem_read i2c.mem_read(1, 76, 0x0a) # should succeed try: i2c.mem_read(1, 77, 0x0a) # should fail except OSError as e: print(repr(e)) i2c.mem_read(1, 76, 0x0a) # should succeed # test DMA mem_write i2c.mem_write(1, 76, 0x0a) # should succeed try: i2c.mem_write(1, 77, 0x0a) # should fail except OSError as e: print(repr(e)) i2c.mem_write(1, 76, 0x0a) # should succeed micropython-1.12/tests/pyb/i2c_error.py.exp000066400000000000000000000000601357706137100210050ustar00rootroot00000000000000OSError(5,) OSError(5,) OSError(5,) OSError(5,) micropython-1.12/tests/pyb/irq.py000066400000000000000000000007361357706137100171310ustar00rootroot00000000000000import pyb def test_irq(): # test basic disable/enable i1 = pyb.disable_irq() print(i1) pyb.enable_irq() # by default should enable IRQ # check that interrupts are enabled by waiting for ticks pyb.delay(10) # check nested disable/enable i1 = pyb.disable_irq() i2 = pyb.disable_irq() print(i1, i2) pyb.enable_irq(i2) pyb.enable_irq(i1) # check that interrupts are enabled by waiting for ticks pyb.delay(10) test_irq() micropython-1.12/tests/pyb/irq.py.exp000066400000000000000000000000201357706137100177060ustar00rootroot00000000000000True True False micropython-1.12/tests/pyb/led.py000066400000000000000000000015411357706137100170750ustar00rootroot00000000000000import os, pyb machine = os.uname().machine if 'PYBv1.' in machine or 'PYBLITEv1.' in machine: leds = [pyb.LED(i) for i in range(1, 5)] pwm_leds = leds[2:] elif 'PYBD' in machine: leds = [pyb.LED(i) for i in range(1, 4)] pwm_leds = [] else: print('SKIP') raise SystemExit # test printing for i in range(3): print(leds[i]) # test on and off for l in leds: l.on() assert l.intensity() == 255 pyb.delay(100) l.off() assert l.intensity() == 0 pyb.delay(100) # test toggle for l in 2 * leds: l.toggle() assert l.intensity() in (0, 255) pyb.delay(100) # test intensity for l in pwm_leds: for i in range(256): l.intensity(i) assert l.intensity() == i pyb.delay(1) for i in range(255, -1, -1): l.intensity(i) assert l.intensity() == i pyb.delay(1) micropython-1.12/tests/pyb/led.py.exp000066400000000000000000000000251357706137100176640ustar00rootroot00000000000000LED(1) LED(2) LED(3) micropython-1.12/tests/pyb/modstm.py000066400000000000000000000005351357706137100176360ustar00rootroot00000000000000# test stm module import stm import pyb # test storing a full 32-bit number # turn on then off the A15(=yellow) LED BSRR = 0x18 stm.mem32[stm.GPIOA + BSRR] = 0x00008000 pyb.delay(100) print(hex(stm.mem32[stm.GPIOA + stm.GPIO_ODR] & 0x00008000)) stm.mem32[stm.GPIOA + BSRR] = 0x80000000 print(hex(stm.mem32[stm.GPIOA + stm.GPIO_ODR] & 0x00008000)) micropython-1.12/tests/pyb/modstm.py.exp000066400000000000000000000000131357706137100204200ustar00rootroot000000000000000x8000 0x0 micropython-1.12/tests/pyb/modtime.py000066400000000000000000000050121357706137100177640ustar00rootroot00000000000000import time DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] def is_leap(year): return (year % 4) == 0 def test(): seconds = 0 wday = 5 # Jan 1, 2000 was a Saturday for year in range(2000, 2034): print("Testing %d" % year) yday = 1 for month in range(1, 13): if month == 2 and is_leap(year): DAYS_PER_MONTH[2] = 29 else: DAYS_PER_MONTH[2] = 28 for day in range(1, DAYS_PER_MONTH[month] + 1): secs = time.mktime((year, month, day, 0, 0, 0, 0, 0)) if secs != seconds: print("mktime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds)) tuple = time.localtime(seconds) secs = time.mktime(tuple) if secs != seconds: print("localtime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds)) return seconds += 86400 if yday != tuple[7]: print("locatime for %d-%02d-%02d got yday %d, expecting %d" % (year, month, day, tuple[7], yday)) return if wday != tuple[6]: print("locatime for %d-%02d-%02d got wday %d, expecting %d" % (year, month, day, tuple[6], wday)) return yday += 1 wday = (wday + 1) % 7 def spot_test(seconds, expected_time): actual_time = time.localtime(seconds) for i in range(len(actual_time)): if actual_time[i] != expected_time[i]: print("time.localtime(", seconds, ") returned", actual_time, "expecting", expected_time) return print("time.localtime(", seconds, ") returned", actual_time, "(pass)") test() spot_test( 0, (2000, 1, 1, 0, 0, 0, 5, 1)) spot_test( 1, (2000, 1, 1, 0, 0, 1, 5, 1)) spot_test( 59, (2000, 1, 1, 0, 0, 59, 5, 1)) spot_test( 60, (2000, 1, 1, 0, 1, 0, 5, 1)) spot_test( 3599, (2000, 1, 1, 0, 59, 59, 5, 1)) spot_test( 3600, (2000, 1, 1, 1, 0, 0, 5, 1)) spot_test( -1, (1999, 12, 31, 23, 59, 59, 4, 365)) spot_test( 447549467, (2014, 3, 7, 23, 17, 47, 4, 66)) spot_test( -940984933, (1970, 3, 7, 23, 17, 47, 5, 66)) spot_test(-1072915199, (1966, 1, 1, 0, 0, 1, 5, 1)) spot_test(-1072915200, (1966, 1, 1, 0, 0, 0, 5, 1)) spot_test(-1072915201, (1965, 12, 31, 23, 59, 59, 4, 365)) micropython-1.12/tests/pyb/modtime.py.exp000066400000000000000000000024131357706137100205610ustar00rootroot00000000000000Testing 2000 Testing 2001 Testing 2002 Testing 2003 Testing 2004 Testing 2005 Testing 2006 Testing 2007 Testing 2008 Testing 2009 Testing 2010 Testing 2011 Testing 2012 Testing 2013 Testing 2014 Testing 2015 Testing 2016 Testing 2017 Testing 2018 Testing 2019 Testing 2020 Testing 2021 Testing 2022 Testing 2023 Testing 2024 Testing 2025 Testing 2026 Testing 2027 Testing 2028 Testing 2029 Testing 2030 Testing 2031 Testing 2032 Testing 2033 time.localtime( 0 ) returned (2000, 1, 1, 0, 0, 0, 5, 1) (pass) time.localtime( 1 ) returned (2000, 1, 1, 0, 0, 1, 5, 1) (pass) time.localtime( 59 ) returned (2000, 1, 1, 0, 0, 59, 5, 1) (pass) time.localtime( 60 ) returned (2000, 1, 1, 0, 1, 0, 5, 1) (pass) time.localtime( 3599 ) returned (2000, 1, 1, 0, 59, 59, 5, 1) (pass) time.localtime( 3600 ) returned (2000, 1, 1, 1, 0, 0, 5, 1) (pass) time.localtime( -1 ) returned (1999, 12, 31, 23, 59, 59, 4, 365) (pass) time.localtime( 447549467 ) returned (2014, 3, 7, 23, 17, 47, 4, 66) (pass) time.localtime( -940984933 ) returned (1970, 3, 7, 23, 17, 47, 5, 66) (pass) time.localtime( -1072915199 ) returned (1966, 1, 1, 0, 0, 1, 5, 1) (pass) time.localtime( -1072915200 ) returned (1966, 1, 1, 0, 0, 0, 5, 1) (pass) time.localtime( -1072915201 ) returned (1965, 12, 31, 23, 59, 59, 4, 365) (pass) micropython-1.12/tests/pyb/pin.py000066400000000000000000000010521357706137100171140ustar00rootroot00000000000000from pyb import Pin p = Pin('X8', Pin.IN) print(p) print(p.name()) print(p.pin()) print(p.port()) p = Pin('X8', Pin.IN, Pin.PULL_UP) p = Pin('X8', Pin.IN, pull=Pin.PULL_UP) p = Pin('X8', mode=Pin.IN, pull=Pin.PULL_UP) print(p) print(p.value()) p.init(p.IN, p.PULL_DOWN) p.init(p.IN, pull=p.PULL_DOWN) p.init(mode=p.IN, pull=p.PULL_DOWN) print(p) print(p.value()) p.init(p.OUT_PP) p.low() print(p.value()) p.high() print(p.value()) p.value(0) print(p.value()) p.value(1) print(p.value()) p.value(False) print(p.value()) p.value(True) print(p.value()) micropython-1.12/tests/pyb/pin.py.exp000066400000000000000000000002241357706137100177070ustar00rootroot00000000000000Pin(Pin.cpu.A7, mode=Pin.IN) A7 7 0 Pin(Pin.cpu.A7, mode=Pin.IN, pull=Pin.PULL_UP) 1 Pin(Pin.cpu.A7, mode=Pin.IN, pull=Pin.PULL_DOWN) 0 0 1 0 1 0 1 micropython-1.12/tests/pyb/pyb1.py000066400000000000000000000007641357706137100172120ustar00rootroot00000000000000# basic tests of pyb module import pyb # test delay pyb.delay(-1) pyb.delay(0) pyb.delay(1) start = pyb.millis() pyb.delay(17) print((pyb.millis() - start) // 5) # should print 3 # test udelay pyb.udelay(-1) pyb.udelay(0) pyb.udelay(1) start = pyb.millis() pyb.udelay(17000) print((pyb.millis() - start) // 5) # should print 3 # other pyb.disable_irq() pyb.enable_irq() print(pyb.have_cdc()) pyb.sync() print(len(pyb.unique_id())) pyb.wfi() pyb.fault_debug(True) pyb.fault_debug(False) micropython-1.12/tests/pyb/pyb1.py.exp000066400000000000000000000000141357706137100177710ustar00rootroot000000000000003 3 True 12 micropython-1.12/tests/pyb/pyb_f405.py000066400000000000000000000004601357706137100176600ustar00rootroot00000000000000# test pyb module on F405 MCUs import os, pyb if not 'STM32F405' in os.uname().machine: print('SKIP') raise SystemExit print(pyb.freq()) print(type(pyb.rng())) # test HAL error specific to F405 i2c = pyb.I2C(2, pyb.I2C.MASTER) try: i2c.recv(1, 1) except OSError as e: print(repr(e)) micropython-1.12/tests/pyb/pyb_f405.py.exp000066400000000000000000000001051357706137100204470ustar00rootroot00000000000000(168000000, 168000000, 42000000, 84000000) OSError(5,) micropython-1.12/tests/pyb/pyb_f411.py000066400000000000000000000002241357706137100176530ustar00rootroot00000000000000# test pyb module on F411 MCUs import os, pyb if not 'STM32F411' in os.uname().machine: print('SKIP') raise SystemExit print(pyb.freq()) micropython-1.12/tests/pyb/pyb_f411.py.exp000066400000000000000000000000511357706137100204440ustar00rootroot00000000000000(96000000, 96000000, 24000000, 48000000) micropython-1.12/tests/pyb/rtc.py000066400000000000000000000042301357706137100171170ustar00rootroot00000000000000import pyb, stm from pyb import RTC rtc = RTC() rtc.init() print(rtc) # make sure that 1 second passes correctly rtc.datetime((2014, 1, 1, 1, 0, 0, 0, 0)) pyb.delay(1002) print(rtc.datetime()[:7]) def set_and_print(datetime): rtc.datetime(datetime) print(rtc.datetime()[:7]) # make sure that setting works correctly set_and_print((2000, 1, 1, 1, 0, 0, 0, 0)) set_and_print((2000, 1, 31, 1, 0, 0, 0, 0)) set_and_print((2000, 12, 31, 1, 0, 0, 0, 0)) set_and_print((2016, 12, 31, 1, 0, 0, 0, 0)) set_and_print((2016, 12, 31, 7, 0, 0, 0, 0)) set_and_print((2016, 12, 31, 7, 1, 0, 0, 0)) set_and_print((2016, 12, 31, 7, 12, 0, 0, 0)) set_and_print((2016, 12, 31, 7, 13, 0, 0, 0)) set_and_print((2016, 12, 31, 7, 23, 0, 0, 0)) set_and_print((2016, 12, 31, 7, 23, 1, 0, 0)) set_and_print((2016, 12, 31, 7, 23, 59, 0, 0)) set_and_print((2016, 12, 31, 7, 23, 59, 1, 0)) set_and_print((2016, 12, 31, 7, 23, 59, 59, 0)) set_and_print((2099, 12, 31, 7, 23, 59, 59, 0)) # check that calibration works correctly # save existing calibration value: cal_tmp = rtc.calibration() def set_and_print_calib(cal): rtc.calibration(cal) print(rtc.calibration()) set_and_print_calib(512) set_and_print_calib(511) set_and_print_calib(345) set_and_print_calib(1) set_and_print_calib(0) set_and_print_calib(-1) set_and_print_calib(-123) set_and_print_calib(-510) set_and_print_calib(-511) # restore existing calibration value rtc.calibration(cal_tmp) # Check register settings for wakeup def set_and_print_wakeup(ms): try: rtc.wakeup(ms) wucksel = stm.mem32[stm.RTC + stm.RTC_CR] & 7 wut = stm.mem32[stm.RTC + stm.RTC_WUTR] & 0xffff except ValueError: wucksel = -1 wut = -1 print((wucksel, wut)) set_and_print_wakeup(0) set_and_print_wakeup(1) set_and_print_wakeup(4000) set_and_print_wakeup(4001) set_and_print_wakeup(8000) set_and_print_wakeup(8001) set_and_print_wakeup(16000) set_and_print_wakeup(16001) set_and_print_wakeup(32000) set_and_print_wakeup(32001) set_and_print_wakeup(0x10000*1000) set_and_print_wakeup(0x10001*1000) set_and_print_wakeup(0x1ffff*1000) set_and_print_wakeup(0x20000*1000) set_and_print_wakeup(0x20001*1000) # exception micropython-1.12/tests/pyb/rtc.py.exp000066400000000000000000000011331357706137100177110ustar00rootroot00000000000000 (2014, 1, 1, 1, 0, 0, 1) (2000, 1, 1, 1, 0, 0, 0) (2000, 1, 31, 1, 0, 0, 0) (2000, 12, 31, 1, 0, 0, 0) (2016, 12, 31, 1, 0, 0, 0) (2016, 12, 31, 7, 0, 0, 0) (2016, 12, 31, 7, 1, 0, 0) (2016, 12, 31, 7, 12, 0, 0) (2016, 12, 31, 7, 13, 0, 0) (2016, 12, 31, 7, 23, 0, 0) (2016, 12, 31, 7, 23, 1, 0) (2016, 12, 31, 7, 23, 59, 0) (2016, 12, 31, 7, 23, 59, 1) (2016, 12, 31, 7, 23, 59, 59) (2099, 12, 31, 7, 23, 59, 59) 512 511 345 1 0 -1 -123 -510 -511 (3, 0) (3, 15) (3, 65535) (2, 32775) (2, 65535) (1, 32771) (1, 65535) (0, 32769) (0, 65535) (4, 31) (4, 65535) (6, 0) (6, 65534) (6, 65535) (-1, -1) micropython-1.12/tests/pyb/servo.py000066400000000000000000000004001357706137100174600ustar00rootroot00000000000000from pyb import Servo servo = Servo(1) print(servo) servo.angle(0) servo.angle(10, 100) servo.speed(-10) servo.speed(10, 100) servo.pulse_width(1500) print(servo.pulse_width()) servo.calibration(630, 2410, 1490, 2460, 2190) print(servo.calibration()) micropython-1.12/tests/pyb/servo.py.exp000066400000000000000000000000671357706137100202640ustar00rootroot00000000000000 1500 (630, 2410, 1490, 2460, 2190) micropython-1.12/tests/pyb/spi.py000066400000000000000000000014451357706137100171270ustar00rootroot00000000000000from pyb import SPI # test we can correctly create by id for bus in (-1, 0, 1, 2): try: SPI(bus) print("SPI", bus) except ValueError: print("ValueError", bus) spi = SPI(1) print(spi) spi = SPI(1, SPI.MASTER) spi = SPI(1, SPI.MASTER, baudrate=500000) spi = SPI(1, SPI.MASTER, 500000, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) print(str(spi)[:28], str(spi)[49:]) # don't print baudrate/prescaler spi.init(SPI.SLAVE, phase=1) print(spi) try: # need to flush input before we get an error (error is what we want to test) for i in range(10): spi.recv(1, timeout=100) except OSError: print("OSError") spi.init(SPI.MASTER) spi.send(1, timeout=100) print(spi.recv(1, timeout=100)) print(spi.send_recv(1, timeout=100)) spi.deinit() micropython-1.12/tests/pyb/spi.py.exp000066400000000000000000000002611357706137100177150ustar00rootroot00000000000000ValueError -1 ValueError 0 SPI 1 SPI 2 SPI(1) SPI(1, SPI.MASTER, baudrate= , polarity=1, phase=0, bits=8) SPI(1, SPI.SLAVE, polarity=1, phase=1, bits=8) OSError b'\xff' b'\xff' micropython-1.12/tests/pyb/switch.py000066400000000000000000000001271357706137100176310ustar00rootroot00000000000000from pyb import Switch sw = Switch() print(sw()) sw.callback(print) sw.callback(None) micropython-1.12/tests/pyb/switch.py.exp000066400000000000000000000000061357706137100204200ustar00rootroot00000000000000False micropython-1.12/tests/pyb/timer.py000066400000000000000000000006041357706137100174500ustar00rootroot00000000000000# check basic functionality of the timer class import pyb from pyb import Timer tim = Timer(4) tim = Timer(4, prescaler=100, period=200) print(tim.prescaler()) print(tim.period()) tim.prescaler(300) print(tim.prescaler()) tim.period(400) print(tim.period()) # Setting and printing frequency tim = Timer(2, freq=100) print(tim.freq()) tim.freq(0.001) print('{:.3f}'.format(tim.freq())) micropython-1.12/tests/pyb/timer.py.exp000066400000000000000000000000321357706137100202360ustar00rootroot00000000000000100 200 300 400 100 0.001 micropython-1.12/tests/pyb/timer_callback.py000066400000000000000000000017511357706137100212700ustar00rootroot00000000000000# check callback feature of the timer class import pyb from pyb import Timer # callback function that disables the callback when called def cb1(t): print("cb1") t.callback(None) # callback function that disables the timer when called def cb2(t): print("cb2") t.deinit() # callback where cb4 closes over cb3.y def cb3(x): y = x def cb4(t): print("cb4", y) t.callback(None) return cb4 # create a timer with a callback, using callback(None) to stop tim = Timer(1, freq=100, callback=cb1) pyb.delay(5) print("before cb1") pyb.delay(15) # create a timer with a callback, using deinit to stop tim = Timer(2, freq=100, callback=cb2) pyb.delay(5) print("before cb2") pyb.delay(15) # create a timer, then set the freq, then set the callback tim = Timer(4) tim.init(freq=100) tim.callback(cb1) pyb.delay(5) print("before cb1") pyb.delay(15) # test callback with a closure tim.init(freq=100) tim.callback(cb3(3)) pyb.delay(5) print("before cb4") pyb.delay(15) micropython-1.12/tests/pyb/timer_callback.py.exp000066400000000000000000000000761357706137100220620ustar00rootroot00000000000000before cb1 cb1 before cb2 cb2 before cb1 cb1 before cb4 cb4 3 micropython-1.12/tests/pyb/uart.py000066400000000000000000000015261357706137100173070ustar00rootroot00000000000000from pyb import UART # test we can correctly create by id for bus in (-1, 0, 1, 2, 5, 6): try: UART(bus, 9600) print("UART", bus) except ValueError: print("ValueError", bus) uart = UART(1) uart = UART(1, 9600) uart = UART(1, 9600, bits=8, parity=None, stop=1) print(uart) uart.init(2400) print(uart) print(uart.any()) print(uart.write('123')) print(uart.write(b'abcd')) print(uart.writechar(1)) # make sure this method exists uart.sendbreak() # non-blocking mode uart = UART(1, 9600, timeout=0) print(uart.write(b'1')) print(uart.write(b'abcd')) print(uart.writechar(1)) print(uart.read(100)) # set rxbuf uart.init(9600, rxbuf=8) print(uart) uart.init(9600, rxbuf=0) print(uart) # set read_buf_len (legacy, use rxbuf instead) uart.init(9600, read_buf_len=4) print(uart) uart.init(9600, read_buf_len=0) print(uart) micropython-1.12/tests/pyb/uart.py.exp000066400000000000000000000012301357706137100200720ustar00rootroot00000000000000ValueError -1 ValueError 0 UART 1 UART 2 ValueError 5 UART 6 UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=64) UART(1, baudrate=2400, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=7, rxbuf=64) 0 3 4 None 1 4 None None UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=8) UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=0) UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=4) UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=0) micropython-1.12/tests/pybnative/000077500000000000000000000000001357706137100171655ustar00rootroot00000000000000micropython-1.12/tests/pybnative/for.py000066400000000000000000000002511357706137100203230ustar00rootroot00000000000000import pyb @micropython.native def f1(n): for i in range(n): print(i) f1(4) @micropython.native def f2(r): for i in r: print(i) f2(range(4)) micropython-1.12/tests/pybnative/for.py.exp000066400000000000000000000000201357706137100211100ustar00rootroot000000000000000 1 2 3 0 1 2 3 micropython-1.12/tests/pybnative/while.py000066400000000000000000000003371357706137100206520ustar00rootroot00000000000000import pyb @micropython.native def f(led, n, d): led.off() i = 0 while i < n: print(i) led.toggle() pyb.delay(d) i += 1 led.off() f(pyb.LED(1), 2, 150) f(pyb.LED(2), 4, 50) micropython-1.12/tests/pybnative/while.py.exp000066400000000000000000000000141357706137100214350ustar00rootroot000000000000000 1 0 1 2 3 micropython-1.12/tests/qemu-arm/000077500000000000000000000000001357706137100167105ustar00rootroot00000000000000micropython-1.12/tests/qemu-arm/native_test.py000066400000000000000000000001741357706137100216110ustar00rootroot00000000000000import native_frozen_align native_frozen_align.native_x(1) native_frozen_align.native_y(2) native_frozen_align.native_z(3) micropython-1.12/tests/qemu-arm/native_test.py.exp000066400000000000000000000000061357706137100223760ustar00rootroot000000000000002 3 4 micropython-1.12/tests/run-internalbench.py000077500000000000000000000061521357706137100211630ustar00rootroot00000000000000#! /usr/bin/env python3 import os import subprocess import sys import argparse import re from glob import glob from collections import defaultdict # Tests require at least CPython 3.3. If your default python3 executable # is of lower version, you can point MICROPY_CPYTHON3 environment var # to the correct executable. if os.name == 'nt': CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe') MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/windows/micropython.exe') else: CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython') def run_tests(pyb, test_dict): test_count = 0 testcase_count = 0 for base_test, tests in sorted(test_dict.items()): print(base_test + ":") for test_file in tests: # run MicroPython if pyb is None: # run on PC try: output_mupy = subprocess.check_output([MICROPYTHON, '-X', 'emit=bytecode', test_file[0]]) except subprocess.CalledProcessError: output_mupy = b'CRASH' else: # run on pyboard pyb.enter_raw_repl() try: output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n') except pyboard.PyboardError: output_mupy = b'CRASH' output_mupy = float(output_mupy.strip()) test_file[1] = output_mupy testcase_count += 1 test_count += 1 baseline = None for t in tests: if baseline is None: baseline = t[1] print(" %.3fs (%+06.2f%%) %s" % (t[1], (t[1] * 100 / baseline) - 100, t[0])) print("{} tests performed ({} individual testcases)".format(test_count, testcase_count)) # all tests succeeded return True def main(): cmd_parser = argparse.ArgumentParser(description='Run tests for MicroPython.') cmd_parser.add_argument('--pyboard', action='store_true', help='run the tests on the pyboard') cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() # Note pyboard support is copied over from run-tests, not testes, and likely needs revamping if args.pyboard: import pyboard pyb = pyboard.Pyboard('/dev/ttyACM0') pyb.enter_raw_repl() else: pyb = None if len(args.files) == 0: if pyb is None: # run PC tests test_dirs = ('internal_bench',) else: # run pyboard tests test_dirs = ('basics', 'float', 'pyb') tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files) else: # tests explicitly given tests = sorted(args.files) test_dict = defaultdict(lambda: []) for t in tests: m = re.match(r"(.+?)-(.+)\.py", t) if not m: continue test_dict[m.group(1)].append([t, None]) if not run_tests(pyb, test_dict): sys.exit(1) if __name__ == "__main__": main() micropython-1.12/tests/run-natmodtests.py000077500000000000000000000131751357706137100207170ustar00rootroot00000000000000#!/usr/bin/env python3 # This file is part of the MicroPython project, http://micropython.org/ # The MIT License (MIT) # Copyright (c) 2019 Damien P. George import os import subprocess import sys import argparse sys.path.append('../tools') import pyboard # Paths for host executables CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython_coverage') NATMOD_EXAMPLE_DIR = '../examples/natmod/' # Supported tests and their corresponding mpy module TEST_MAPPINGS = { 'btree': 'btree/btree_$(ARCH).mpy', 'framebuf': 'framebuf/framebuf_$(ARCH).mpy', 'uheapq': 'uheapq/uheapq_$(ARCH).mpy', 'urandom': 'urandom/urandom_$(ARCH).mpy', 'ure': 'ure/ure_$(ARCH).mpy', 'uzlib': 'uzlib/uzlib_$(ARCH).mpy', } # Code to allow a target MicroPython to import an .mpy from RAM injected_import_hook_code = """\ import sys, uos, uio class __File(uio.IOBase): def __init__(self): self.off = 0 def ioctl(self, request, arg): return 0 def readinto(self, buf): buf[:] = memoryview(__buf)[self.off:self.off + len(buf)] self.off += len(buf) return len(buf) class __FS: def mount(self, readonly, mkfs): pass def chdir(self, path): pass def stat(self, path): if path == '__injected.mpy': return tuple(0 for _ in range(10)) else: raise OSError(-2) # ENOENT def open(self, path, mode): return __File() uos.mount(__FS(), '/__remote') uos.chdir('/__remote') sys.modules['{}'] = __import__('__injected') """ class TargetSubprocess: def __init__(self, cmd): self.cmd = cmd def close(self): pass def run_script(self, script): try: p = subprocess.run(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, input=script) return p.stdout, None except subprocess.CalledProcessError as er: return b'', er class TargetPyboard: def __init__(self, pyb): self.pyb = pyb self.pyb.enter_raw_repl() def close(self): self.pyb.exit_raw_repl() self.pyb.close() def run_script(self, script): try: self.pyb.enter_raw_repl() output = self.pyb.exec_(script) output = output.replace(b'\r\n', b'\n') return output, None except pyboard.PyboardError as er: return b'', er def run_tests(target_truth, target, args, stats): for test_file in args.files: # Find supported test for k, v in TEST_MAPPINGS.items(): if test_file.find(k) != -1: test_module = k test_mpy = v.replace('$(ARCH)', args.arch) break else: print('---- {} - no matching mpy'.format(test_file)) continue # Read test script with open(test_file, 'rb') as f: test_file_data = f.read() # Create full test with embedded .mpy try: with open(NATMOD_EXAMPLE_DIR + test_mpy, 'rb') as f: test_script = b'__buf=' + bytes(repr(f.read()), 'ascii') + b'\n' except OSError: print('---- {} - mpy file not compiled'.format(test_file)) continue test_script += bytes(injected_import_hook_code.format(test_module), 'ascii') test_script += test_file_data # Run test under MicroPython result_out, error = target.run_script(test_script) # Work out result of test extra = '' if error is None and result_out == b'SKIP\n': result = 'SKIP' elif error is not None: result = 'FAIL' extra = ' - ' + str(error) else: # Check result against truth try: with open(test_file + '.exp', 'rb') as f: result_exp = f.read() error = None except OSError: result_exp, error = target_truth.run_script(test_file_data) if error is not None: result = 'TRUTH FAIL' elif result_out != result_exp: result = 'FAIL' print(result_out) else: result = 'pass' # Accumulate statistics stats['total'] += 1 if result == 'pass': stats['pass'] += 1 elif result == 'SKIP': stats['skip'] += 1 else: stats['fail'] += 1 # Print result print('{:4} {}{}'.format(result, test_file, extra)) def main(): cmd_parser = argparse.ArgumentParser(description='Run dynamic-native-module tests under MicroPython') cmd_parser.add_argument('-p', '--pyboard', action='store_true', help='run tests via pyboard.py') cmd_parser.add_argument('-d', '--device', default='/dev/ttyACM0', help='the device for pyboard.py') cmd_parser.add_argument('-a', '--arch', default='x64', help='native architecture of the target') cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() target_truth = TargetSubprocess([CPYTHON3]) if args.pyboard: target = TargetPyboard(pyboard.Pyboard(args.device)) else: target = TargetSubprocess([MICROPYTHON]) stats = {'total': 0, 'pass': 0, 'fail':0, 'skip': 0} run_tests(target_truth, target, args, stats) target.close() target_truth.close() print('{} tests performed'.format(stats['total'])) print('{} tests passed'.format(stats['pass'])) if stats['fail']: print('{} tests failed'.format(stats['fail'])) if stats['skip']: print('{} tests skipped'.format(stats['skip'])) if stats['fail']: sys.exit(1) if __name__ == "__main__": main() micropython-1.12/tests/run-perfbench.py000077500000000000000000000205711357706137100203040ustar00rootroot00000000000000#!/usr/bin/env python3 # This file is part of the MicroPython project, http://micropython.org/ # The MIT License (MIT) # Copyright (c) 2019 Damien P. George import os import subprocess import sys import argparse from glob import glob sys.path.append('../tools') import pyboard # Paths for host executables if os.name == 'nt': CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe') MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/windows/micropython.exe') else: CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython') PYTHON_TRUTH = CPYTHON3 BENCH_SCRIPT_DIR = 'perf_bench/' def compute_stats(lst): avg = 0 var = 0 for x in lst: avg += x var += x * x avg /= len(lst) var = max(0, var / len(lst) - avg ** 2) return avg, var ** 0.5 def run_script_on_target(target, script): output = b'' err = None if isinstance(target, pyboard.Pyboard): # Run via pyboard interface try: target.enter_raw_repl() output = target.exec_(script) except pyboard.PyboardError as er: err = er else: # Run local executable try: p = subprocess.run(target, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, input=script) output = p.stdout except subprocess.CalledProcessError as er: err = er return str(output.strip(), 'ascii'), err def run_feature_test(target, test): with open('feature_check/' + test + '.py', 'rb') as f: script = f.read() output, err = run_script_on_target(target, script) if err is None: return output else: return 'CRASH: %r' % err def run_benchmark_on_target(target, script): output, err = run_script_on_target(target, script) if err is None: time, norm, result = output.split(None, 2) try: return int(time), int(norm), result except ValueError: return -1, -1, 'CRASH: %r' % output else: return -1, -1, 'CRASH: %r' % err def run_benchmarks(target, param_n, param_m, n_average, test_list): skip_complex = run_feature_test(target, 'complex') != 'complex' skip_native = run_feature_test(target, 'native_check') != '' for test_file in sorted(test_list): print(test_file + ': ', end='') # Check if test should be skipped skip = ( skip_complex and test_file.find('bm_fft') != -1 or skip_native and test_file.find('viper_') != -1 ) if skip: print('skip') continue # Create test script with open(test_file, 'rb') as f: test_script = f.read() with open(BENCH_SCRIPT_DIR + 'benchrun.py', 'rb') as f: test_script += f.read() test_script += b'bm_run(%u, %u)\n' % (param_n, param_m) # Write full test script if needed if 0: with open('%s.full' % test_file, 'wb') as f: f.write(test_script) # Run MicroPython a given number of times times = [] scores = [] error = None result_out = None for _ in range(n_average): time, norm, result = run_benchmark_on_target(target, test_script) if time < 0 or norm < 0: error = result break if result_out is None: result_out = result elif result != result_out: error = 'FAIL self' break times.append(time) scores.append(1e6 * norm / time) # Check result against truth if needed if error is None and result_out != 'None': _, _, result_exp = run_benchmark_on_target(PYTHON_TRUTH, test_script) if result_out != result_exp: error = 'FAIL truth' if error is not None: print(error) else: t_avg, t_sd = compute_stats(times) s_avg, s_sd = compute_stats(scores) print('{:.2f} {:.4f} {:.2f} {:.4f}'.format(t_avg, 100 * t_sd / t_avg, s_avg, 100 * s_sd / s_avg)) if 0: print(' times: ', times) print(' scores:', scores) sys.stdout.flush() def parse_output(filename): with open(filename) as f: params = f.readline() n, m, _ = params.strip().split() n = int(n.split('=')[1]) m = int(m.split('=')[1]) data = [] for l in f: if l.find(': ') != -1 and l.find(': skip') == -1 and l.find('CRASH: ') == -1: name, values = l.strip().split(': ') values = tuple(float(v) for v in values.split()) data.append((name,) + values) return n, m, data def compute_diff(file1, file2, diff_score): # Parse output data from previous runs n1, m1, d1 = parse_output(file1) n2, m2, d2 = parse_output(file2) # Print header if diff_score: print('diff of scores (higher is better)') else: print('diff of microsecond times (lower is better)') if n1 == n2 and m1 == m2: hdr = 'N={} M={}'.format(n1, m1) else: hdr = 'N={} M={} vs N={} M={}'.format(n1, m1, n2, m2) print('{:24} {:>10} -> {:>10} {:>10} {:>7}% (error%)'.format(hdr, file1, file2, 'diff', 'diff')) # Print entries while d1 and d2: if d1[0][0] == d2[0][0]: # Found entries with matching names entry1 = d1.pop(0) entry2 = d2.pop(0) name = entry1[0].rsplit('/')[-1] av1, sd1 = entry1[1 + 2 * diff_score], entry1[2 + 2 * diff_score] av2, sd2 = entry2[1 + 2 * diff_score], entry2[2 + 2 * diff_score] sd1 *= av1 / 100 # convert from percent sd to absolute sd sd2 *= av2 / 100 # convert from percent sd to absolute sd av_diff = av2 - av1 sd_diff = (sd1 ** 2 + sd2 ** 2) ** 0.5 percent = 100 * av_diff / av1 percent_sd = 100 * sd_diff / av1 print('{:24} {:10.2f} -> {:10.2f} : {:+10.2f} = {:+7.3f}% (+/-{:.2f}%)'.format(name, av1, av2, av_diff, percent, percent_sd)) elif d1[0][0] < d2[0][0]: d1.pop(0) else: d2.pop(0) def main(): cmd_parser = argparse.ArgumentParser(description='Run benchmarks for MicroPython') cmd_parser.add_argument('-t', '--diff-time', action='store_true', help='diff time outputs from a previous run') cmd_parser.add_argument('-s', '--diff-score', action='store_true', help='diff score outputs from a previous run') cmd_parser.add_argument('-p', '--pyboard', action='store_true', help='run tests via pyboard.py') cmd_parser.add_argument('-d', '--device', default='/dev/ttyACM0', help='the device for pyboard.py') cmd_parser.add_argument('-a', '--average', default='8', help='averaging number') cmd_parser.add_argument('--emit', default='bytecode', help='MicroPython emitter to use (bytecode or native)') cmd_parser.add_argument('N', nargs=1, help='N parameter (approximate target CPU frequency)') cmd_parser.add_argument('M', nargs=1, help='M parameter (approximate target heap in kbytes)') cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() if args.diff_time or args.diff_score: compute_diff(args.N[0], args.M[0], args.diff_score) sys.exit(0) # N, M = 50, 25 # esp8266 # N, M = 100, 100 # pyboard, esp32 # N, M = 1000, 1000 # PC N = int(args.N[0]) M = int(args.M[0]) n_average = int(args.average) if args.pyboard: target = pyboard.Pyboard(args.device) target.enter_raw_repl() else: target = [MICROPYTHON, '-X', 'emit=' + args.emit] if len(args.files) == 0: tests_skip = ('benchrun.py',) if M <= 25: # These scripts are too big to be compiled by the target tests_skip += ('bm_chaos.py', 'bm_hexiom.py', 'misc_raytrace.py') tests = sorted( BENCH_SCRIPT_DIR + test_file for test_file in os.listdir(BENCH_SCRIPT_DIR) if test_file.endswith('.py') and test_file not in tests_skip ) else: tests = sorted(args.files) print('N={} M={} n_average={}'.format(N, M, n_average)) run_benchmarks(target, N, M, n_average, tests) if isinstance(target, pyboard.Pyboard): target.exit_raw_repl() target.close() if __name__ == "__main__": main() micropython-1.12/tests/run-tests000077500000000000000000000673021357706137100170660ustar00rootroot00000000000000#! /usr/bin/env python3 import os import subprocess import sys import platform import argparse import re from glob import glob # Tests require at least CPython 3.3. If your default python3 executable # is of lower version, you can point MICROPY_CPYTHON3 environment var # to the correct executable. if os.name == 'nt': CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe') MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/windows/micropython.exe') else: CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython') # mpy-cross is only needed if --via-mpy command-line arg is passed MPYCROSS = os.getenv('MICROPY_MPYCROSS', '../mpy-cross/mpy-cross') # Set PYTHONIOENCODING so that CPython will use utf-8 on systems which set another encoding in the locale os.environ['PYTHONIOENCODING'] = 'utf-8' def rm_f(fname): if os.path.exists(fname): os.remove(fname) # unescape wanted regex chars and escape unwanted ones def convert_regex_escapes(line): cs = [] escape = False for c in str(line, 'utf8'): if escape: escape = False cs.append(c) elif c == '\\': escape = True elif c in ('(', ')', '[', ']', '{', '}', '.', '*', '+', '^', '$'): cs.append('\\' + c) else: cs.append(c) # accept carriage-return(s) before final newline if cs[-1] == '\n': cs[-1] = '\r*\n' return bytes(''.join(cs), 'utf8') def run_micropython(pyb, args, test_file, is_special=False): special_tests = ( 'micropython/meminfo.py', 'basics/bytes_compare3.py', 'basics/builtin_help.py', 'thread/thread_exc2.py', ) had_crash = False if pyb is None: # run on PC if test_file.startswith(('cmdline/', 'feature_check/')) or test_file in special_tests: # special handling for tests of the unix cmdline program is_special = True if is_special: # check for any cmdline options needed for this test args = [MICROPYTHON] with open(test_file, 'rb') as f: line = f.readline() if line.startswith(b'# cmdline:'): # subprocess.check_output on Windows only accepts strings, not bytes args += [str(c, 'utf-8') for c in line[10:].strip().split()] # run the test, possibly with redirected input try: if 'repl_' in test_file: # Need to use a PTY to test command line editing try: import pty except ImportError: # in case pty module is not available, like on Windows return b'SKIP\n' import select def get(required=False): rv = b'' while True: ready = select.select([master], [], [], 0.02) if ready[0] == [master]: rv += os.read(master, 1024) else: if not required or rv: return rv def send_get(what): os.write(master, what) return get() with open(test_file, 'rb') as f: # instead of: output_mupy = subprocess.check_output(args, stdin=f) master, slave = pty.openpty() p = subprocess.Popen(args, stdin=slave, stdout=slave, stderr=subprocess.STDOUT, bufsize=0) banner = get(True) output_mupy = banner + b''.join(send_get(line) for line in f) send_get(b'\x04') # exit the REPL, so coverage info is saved # At this point the process might have exited already, but trying to # kill it 'again' normally doesn't result in exceptions as Python and/or # the OS seem to try to handle this nicely. When running Linux on WSL # though, the situation differs and calling Popen.kill after the process # terminated results in a ProcessLookupError. Just catch that one here # since we just want the process to be gone and that's the case. try: p.kill() except ProcessLookupError: pass os.close(master) os.close(slave) else: output_mupy = subprocess.check_output(args + [test_file], stderr=subprocess.STDOUT) except subprocess.CalledProcessError: return b'CRASH' else: # a standard test run on PC # create system command cmdlist = [MICROPYTHON, '-X', 'emit=' + args.emit] if args.heapsize is not None: cmdlist.extend(['-X', 'heapsize=' + args.heapsize]) # if running via .mpy, first compile the .py file if args.via_mpy: subprocess.check_output([MPYCROSS, '-mcache-lookup-bc', '-o', 'mpytest.mpy', '-X', 'emit=' + args.emit, test_file]) cmdlist.extend(['-m', 'mpytest']) else: cmdlist.append(test_file) # run the actual test try: output_mupy = subprocess.check_output(cmdlist, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as er: had_crash = True output_mupy = er.output + b'CRASH' # clean up if we had an intermediate .mpy file if args.via_mpy: rm_f('mpytest.mpy') else: # run on pyboard pyb.enter_raw_repl() try: output_mupy = pyb.execfile(test_file) except pyboard.PyboardError as e: had_crash = True if not is_special and e.args[0] == 'exception': output_mupy = e.args[1] + e.args[2] + b'CRASH' else: output_mupy = b'CRASH' # canonical form for all ports/platforms is to use \n for end-of-line output_mupy = output_mupy.replace(b'\r\n', b'\n') # don't try to convert the output if we should skip this test if had_crash or output_mupy in (b'SKIP\n', b'CRASH'): return output_mupy if is_special or test_file in special_tests: # convert parts of the output that are not stable across runs with open(test_file + '.exp', 'rb') as f: lines_exp = [] for line in f.readlines(): if line == b'########\n': line = (line,) else: line = (line, re.compile(convert_regex_escapes(line))) lines_exp.append(line) lines_mupy = [line + b'\n' for line in output_mupy.split(b'\n')] if output_mupy.endswith(b'\n'): lines_mupy = lines_mupy[:-1] # remove erroneous last empty line i_mupy = 0 for i in range(len(lines_exp)): if lines_exp[i][0] == b'########\n': # 8x #'s means match 0 or more whole lines line_exp = lines_exp[i + 1] skip = 0 while i_mupy + skip < len(lines_mupy) and not line_exp[1].match(lines_mupy[i_mupy + skip]): skip += 1 if i_mupy + skip >= len(lines_mupy): lines_mupy[i_mupy] = b'######## FAIL\n' break del lines_mupy[i_mupy:i_mupy + skip] lines_mupy.insert(i_mupy, b'########\n') i_mupy += 1 else: # a regex if lines_exp[i][1].match(lines_mupy[i_mupy]): lines_mupy[i_mupy] = lines_exp[i][0] else: #print("don't match: %r %s" % (lines_exp[i][1], lines_mupy[i_mupy])) # DEBUG pass i_mupy += 1 if i_mupy >= len(lines_mupy): break output_mupy = b''.join(lines_mupy) return output_mupy def run_feature_check(pyb, args, base_path, test_file): return run_micropython(pyb, args, base_path + "/feature_check/" + test_file, is_special=True) def run_tests(pyb, tests, args, base_path="."): test_count = 0 testcase_count = 0 passed_count = 0 failed_tests = [] skipped_tests = [] skip_tests = set() skip_native = False skip_int_big = False skip_bytearray = False skip_set_type = False skip_slice = False skip_async = False skip_const = False skip_revops = False skip_io_module = False skip_endian = False has_complex = True has_coverage = False upy_float_precision = 32 # If we're asked to --list-tests, we can't assume that there's a # connection to target, so we can't run feature checks usefully. if not (args.list_tests or args.write_exp): # Check if micropython.native is supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'native_check.py') if output == b'CRASH': skip_native = True # Check if arbitrary-precision integers are supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'int_big.py') if output != b'1000000000000000000000000000000000000000000000\n': skip_int_big = True # Check if bytearray is supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'bytearray.py') if output != b'bytearray\n': skip_bytearray = True # Check if set type (and set literals) is supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'set_check.py') if output == b'CRASH': skip_set_type = True # Check if slice is supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'slice.py') if output != b'slice\n': skip_slice = True # Check if async/await keywords are supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'async_check.py') if output == b'CRASH': skip_async = True # Check if const keyword (MicroPython extension) is supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'const.py') if output == b'CRASH': skip_const = True # Check if __rOP__ special methods are supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'reverse_ops.py') if output == b'TypeError\n': skip_revops = True # Check if uio module exists, and skip such tests if it doesn't output = run_feature_check(pyb, args, base_path, 'uio_module.py') if output != b'uio\n': skip_io_module = True # Check if emacs repl is supported, and skip such tests if it's not t = run_feature_check(pyb, args, base_path, 'repl_emacs_check.py') if not 'True' in str(t, 'ascii'): skip_tests.add('cmdline/repl_emacs_keys.py') upy_byteorder = run_feature_check(pyb, args, base_path, 'byteorder.py') upy_float_precision = int(run_feature_check(pyb, args, base_path, 'float.py')) has_complex = run_feature_check(pyb, args, base_path, 'complex.py') == b'complex\n' has_coverage = run_feature_check(pyb, args, base_path, 'coverage.py') == b'coverage\n' cpy_byteorder = subprocess.check_output([CPYTHON3, base_path + '/feature_check/byteorder.py']) skip_endian = (upy_byteorder != cpy_byteorder) # These tests don't test slice explicitly but rather use it to perform the test misc_slice_tests = ( 'builtin_range', 'class_super', 'containment', 'errno1', 'fun_str', 'generator1', 'globals_del', 'memoryview1', 'memoryview_gc', 'object1', 'python34', 'struct_endian', ) # Some tests shouldn't be run under Travis CI if os.getenv('TRAVIS') == 'true': skip_tests.add('basics/memoryerror.py') skip_tests.add('thread/thread_gc1.py') # has reliability issues skip_tests.add('thread/thread_lock4.py') # has reliability issues skip_tests.add('thread/stress_heap.py') # has reliability issues skip_tests.add('thread/stress_recurse.py') # has reliability issues if upy_float_precision == 0: skip_tests.add('extmod/uctypes_le_float.py') skip_tests.add('extmod/uctypes_native_float.py') skip_tests.add('extmod/uctypes_sizeof_float.py') skip_tests.add('extmod/ujson_dumps_float.py') skip_tests.add('extmod/ujson_loads_float.py') skip_tests.add('extmod/urandom_extra_float.py') skip_tests.add('misc/rge_sm.py') if upy_float_precision < 32: skip_tests.add('float/float2int_intbig.py') # requires fp32, there's float2int_fp30_intbig.py instead skip_tests.add('float/string_format.py') # requires fp32, there's string_format_fp30.py instead skip_tests.add('float/bytes_construct.py') # requires fp32 skip_tests.add('float/bytearray_construct.py') # requires fp32 if upy_float_precision < 64: skip_tests.add('float/float_divmod.py') # tested by float/float_divmod_relaxed.py instead skip_tests.add('float/float2int_doubleprec_intbig.py') skip_tests.add('float/float_parse_doubleprec.py') if not has_complex: skip_tests.add('float/complex1.py') skip_tests.add('float/complex1_intbig.py') skip_tests.add('float/int_big_float.py') skip_tests.add('float/true_value.py') skip_tests.add('float/types.py') if not has_coverage: skip_tests.add('cmdline/cmd_parsetree.py') # Some tests shouldn't be run on a PC if args.target == 'unix': # unix build does not have the GIL so can't run thread mutation tests for t in tests: if t.startswith('thread/mutate_'): skip_tests.add(t) # Some tests shouldn't be run on pyboard if args.target != 'unix': skip_tests.add('basics/exception_chain.py') # warning is not printed skip_tests.add('micropython/meminfo.py') # output is very different to PC output skip_tests.add('extmod/machine_mem.py') # raw memory access not supported if args.target == 'wipy': skip_tests.add('misc/print_exception.py') # requires error reporting full skip_tests.update({'extmod/uctypes_%s.py' % t for t in 'bytearray le native_le ptr_le ptr_native_le sizeof sizeof_native array_assign_le array_assign_native_le'.split()}) # requires uctypes skip_tests.add('extmod/zlibd_decompress.py') # requires zlib skip_tests.add('extmod/uheapq1.py') # uheapq not supported by WiPy skip_tests.add('extmod/urandom_basic.py') # requires urandom skip_tests.add('extmod/urandom_extra.py') # requires urandom elif args.target == 'esp8266': skip_tests.add('misc/rge_sm.py') # too large elif args.target == 'minimal': skip_tests.add('basics/class_inplace_op.py') # all special methods not supported skip_tests.add('basics/subclass_native_init.py')# native subclassing corner cases not support skip_tests.add('misc/rge_sm.py') # too large skip_tests.add('micropython/opt_level.py') # don't assume line numbers are stored elif args.target == 'nrf': skip_tests.add('basics/memoryview1.py') # no item assignment for memoryview skip_tests.add('extmod/ticks_diff.py') # unimplemented: utime.ticks_diff skip_tests.add('extmod/time_ms_us.py') # unimplemented: utime.ticks_ms skip_tests.add('extmod/urandom_basic.py') # unimplemented: urandom.seed skip_tests.add('micropython/opt_level.py') # no support for line numbers skip_tests.add('misc/non_compliant.py') # no item assignment for bytearray for t in tests: if t.startswith('basics/io_'): skip_tests.add(t) elif args.target == 'qemu-arm': skip_tests.add('misc/print_exception.py') # requires sys stdfiles # Some tests are known to fail on 64-bit machines if pyb is None and platform.architecture()[0] == '64bit': pass # Some tests use unsupported features on Windows if os.name == 'nt': skip_tests.add('import/import_file.py') # works but CPython prints forward slashes # Some tests are known to fail with native emitter # Remove them from the below when they work if args.emit == 'native': skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from_close generator_name'.split()}) # require raise_varargs, generator name skip_tests.update({'basics/async_%s.py' % t for t in 'with with2 with_break with_return'.split()}) # require async_with skip_tests.update({'basics/%s.py' % t for t in 'try_reraise try_reraise2'.split()}) # require raise_varargs skip_tests.add('basics/del_deref.py') # requires checking for unbound local skip_tests.add('basics/del_local.py') # requires checking for unbound local skip_tests.add('basics/exception_chain.py') # raise from is not supported skip_tests.add('basics/scope_implicit.py') # requires checking for unbound local skip_tests.add('basics/try_finally_return2.py') # requires raise_varargs skip_tests.add('basics/unboundlocal.py') # requires checking for unbound local skip_tests.add('misc/features.py') # requires raise_varargs skip_tests.add('misc/print_exception.py') # because native doesn't have proper traceback info skip_tests.add('misc/sys_exc_info.py') # sys.exc_info() is not supported for native skip_tests.add('micropython/emg_exc.py') # because native doesn't have proper traceback info skip_tests.add('micropython/heapalloc_traceback.py') # because native doesn't have proper traceback info skip_tests.add('micropython/opt_level_lineno.py') # native doesn't have proper traceback info skip_tests.add('micropython/schedule.py') # native code doesn't check pending events for test_file in tests: test_file = test_file.replace('\\', '/') if args.filters: # Default verdict is the opposit of the first action verdict = "include" if args.filters[0][0] == "exclude" else "exclude" for action, pat in args.filters: if pat.search(test_file): verdict = action if verdict == "exclude": continue test_basename = test_file.replace('..', '_').replace('./', '').replace('/', '_') test_name = os.path.splitext(os.path.basename(test_file))[0] is_native = test_name.startswith("native_") or test_name.startswith("viper_") is_endian = test_name.endswith("_endian") is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig") is_bytearray = test_name.startswith("bytearray") or test_name.endswith("_bytearray") is_set_type = test_name.startswith("set_") or test_name.startswith("frozenset") is_slice = test_name.find("slice") != -1 or test_name in misc_slice_tests is_async = test_name.startswith("async_") is_const = test_name.startswith("const") is_io_module = test_name.startswith("io_") skip_it = test_file in skip_tests skip_it |= skip_native and is_native skip_it |= skip_endian and is_endian skip_it |= skip_int_big and is_int_big skip_it |= skip_bytearray and is_bytearray skip_it |= skip_set_type and is_set_type skip_it |= skip_slice and is_slice skip_it |= skip_async and is_async skip_it |= skip_const and is_const skip_it |= skip_revops and test_name.startswith("class_reverse_op") skip_it |= skip_io_module and is_io_module if args.list_tests: if not skip_it: print(test_file) continue if skip_it: print("skip ", test_file) skipped_tests.append(test_name) continue # get expected output test_file_expected = test_file + '.exp' if os.path.isfile(test_file_expected): # expected output given by a file, so read that in with open(test_file_expected, 'rb') as f: output_expected = f.read() else: # run CPython to work out expected output try: output_expected = subprocess.check_output([CPYTHON3, '-B', test_file]) if args.write_exp: with open(test_file_expected, 'wb') as f: f.write(output_expected) except subprocess.CalledProcessError: output_expected = b'CPYTHON3 CRASH' # canonical form for all host platforms is to use \n for end-of-line output_expected = output_expected.replace(b'\r\n', b'\n') if args.write_exp: continue # run MicroPython output_mupy = run_micropython(pyb, args, test_file) if output_mupy == b'SKIP\n': print("skip ", test_file) skipped_tests.append(test_name) continue testcase_count += len(output_expected.splitlines()) filename_expected = test_basename + ".exp" filename_mupy = test_basename + ".out" if output_expected == output_mupy: print("pass ", test_file) passed_count += 1 rm_f(filename_expected) rm_f(filename_mupy) else: with open(filename_expected, "wb") as f: f.write(output_expected) with open(filename_mupy, "wb") as f: f.write(output_mupy) print("FAIL ", test_file) failed_tests.append(test_name) test_count += 1 if args.list_tests: return True print("{} tests performed ({} individual testcases)".format(test_count, testcase_count)) print("{} tests passed".format(passed_count)) if len(skipped_tests) > 0: print("{} tests skipped: {}".format(len(skipped_tests), ' '.join(skipped_tests))) if len(failed_tests) > 0: print("{} tests failed: {}".format(len(failed_tests), ' '.join(failed_tests))) return False # all tests succeeded return True class append_filter(argparse.Action): def __init__(self, option_strings, dest, **kwargs): super().__init__(option_strings, dest, default=[], **kwargs) def __call__(self, parser, args, value, option): if not hasattr(args, self.dest): args.filters = [] if option.startswith(("-e", "--e")): option = "exclude" else: option = "include" args.filters.append((option, re.compile(value))) def main(): cmd_parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='Run and manage tests for MicroPython.', epilog='''\ Options -i and -e can be multiple and processed in the order given. Regex "search" (vs "match") operation is used. An action (include/exclude) of the last matching regex is used: run-tests -i async - exclude all, then include tests containg "async" anywhere run-tests -e '/big.+int' - include all, then exclude by regex run-tests -e async -i async_foo - include all, exclude async, yet still include async_foo ''') cmd_parser.add_argument('--target', default='unix', help='the target platform') cmd_parser.add_argument('--device', default='/dev/ttyACM0', help='the serial device or the IP address of the pyboard') cmd_parser.add_argument('-b', '--baudrate', default=115200, help='the baud rate of the serial device') cmd_parser.add_argument('-u', '--user', default='micro', help='the telnet login username') cmd_parser.add_argument('-p', '--password', default='python', help='the telnet login password') cmd_parser.add_argument('-d', '--test-dirs', nargs='*', help='input test directories (if no files given)') cmd_parser.add_argument('-e', '--exclude', action=append_filter, metavar='REGEX', dest='filters', help='exclude test by regex on path/name.py') cmd_parser.add_argument('-i', '--include', action=append_filter, metavar='REGEX', dest='filters', help='include test by regex on path/name.py') cmd_parser.add_argument('--write-exp', action='store_true', help='save .exp files to run tests w/o CPython') cmd_parser.add_argument('--list-tests', action='store_true', help='list tests instead of running them') cmd_parser.add_argument('--emit', default='bytecode', help='MicroPython emitter to use (bytecode or native)') cmd_parser.add_argument('--heapsize', help='heapsize to use (use default if not specified)') cmd_parser.add_argument('--via-mpy', action='store_true', help='compile .py files to .mpy first') cmd_parser.add_argument('--keep-path', action='store_true', help='do not clear MICROPYPATH when running tests') cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() LOCAL_TARGETS = ('unix', 'qemu-arm',) EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266', 'esp32', 'minimal', 'nrf') if args.target in LOCAL_TARGETS or args.list_tests: pyb = None elif args.target in EXTERNAL_TARGETS: global pyboard sys.path.append('../tools') import pyboard pyb = pyboard.Pyboard(args.device, args.baudrate, args.user, args.password) pyb.enter_raw_repl() else: raise ValueError('target must be one of %s' % ", ".join(LOCAL_TARGETS + EXTERNAL_TARGETS)) if len(args.files) == 0: if args.test_dirs is None: test_dirs = ('basics', 'micropython', 'misc', 'extmod',) if args.target == 'pyboard': # run pyboard tests test_dirs += ('float', 'stress', 'pyb', 'pybnative', 'inlineasm') elif args.target in ('esp8266', 'esp32', 'minimal', 'nrf'): test_dirs += ('float',) elif args.target == 'wipy': # run WiPy tests test_dirs += ('wipy',) elif args.target == 'unix': # run PC tests test_dirs += ('float', 'import', 'io', 'stress', 'unicode', 'unix', 'cmdline',) elif args.target == 'qemu-arm': if not args.write_exp: raise ValueError('--target=qemu-arm must be used with --write-exp') # Generate expected output files for qemu run. # This list should match the test_dirs tuple in tinytest-codegen.py. test_dirs += ('float', 'inlineasm', 'qemu-arm',) else: # run tests from these directories test_dirs = args.test_dirs tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files) else: # tests explicitly given tests = args.files if not args.keep_path: # clear search path to make sure tests use only builtin modules os.environ['MICROPYPATH'] = '' # Even if we run completely different tests in a different directory, # we need to access feature_check's from the same directory as the # run-tests script itself. base_path = os.path.dirname(sys.argv[0]) or "." try: res = run_tests(pyb, tests, args, base_path) finally: if pyb: pyb.close() if not res: sys.exit(1) if __name__ == "__main__": main() micropython-1.12/tests/run-tests-exp.py000066400000000000000000000052111357706137100202730ustar00rootroot00000000000000# # This is minimal MicroPython variant of run-tests script, which uses # .exp files as generated by run-tests --write-exp. It is useful to run # testsuite on systems which have neither CPython3 nor unix shell. # This script is intended to be run by the same interpreter executable # which is to be tested, so should use minimal language functionality. # import sys import uos as os tests = [ "basics", "micropython", "float", "import", "io", " misc", "unicode", "extmod", "unix" ] if sys.platform == 'win32': MICROPYTHON = "micropython.exe" else: MICROPYTHON = "micropython" def should_skip(test): if test.startswith("native"): return True if test.startswith("viper"): return True test_count = 0 passed_count = 0 skip_count = 0 for suite in tests: #print("Running in: %s" % suite) if sys.platform == 'win32': # dir /b prints only contained filenames, one on a line # http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/dir.mspx r = os.system("dir /b %s/*.py >tests.lst" % suite) else: r = os.system("ls %s/*.py | xargs -n1 basename >tests.lst" % suite) assert r == 0 with open("tests.lst") as f: testcases = f.readlines() testcases = [l[:-1] for l in testcases] assert testcases, "No tests found in dir '%s', which is implausible" % suite #print(testcases) for t in testcases: if t == "native_check.py": continue qtest = "%s/%s" % (suite, t) if should_skip(t): print("skip " + qtest) skip_count += 1 continue exp = None try: f = open(qtest + ".exp") exp = f.read() f.close() except OSError: pass if exp is not None: #print("run " + qtest) r = os.system(MICROPYTHON + " %s >.tst.out" % qtest) if r == 0: f = open(".tst.out") out = f.read() f.close() else: out = "CRASH" if out == "SKIP\n": print("skip " + qtest) skip_count += 1 else: if out == exp: print("pass " + qtest) passed_count += 1 else: print("FAIL " + qtest) test_count += 1 else: skip_count += 1 print("%s tests performed" % test_count) print("%s tests passed" % passed_count) if test_count != passed_count: print("%s tests failed" % (test_count - passed_count)) if skip_count: print("%s tests skipped" % skip_count) micropython-1.12/tests/run-tests-exp.sh000077500000000000000000000033231357706137100202620ustar00rootroot00000000000000#!/bin/sh # # This is plain shell variant of run-tests script, which uses .exp files # as generated by run-tests --write-exp. It is useful to run testsuite # on embedded systems which don't have CPython3. # RM="rm -f" MP_PY=micropython numtests=0 numtestcases=0 numpassed=0 numskipped=0 numfailed=0 nameskipped= namefailed= if [ $# -eq 0 ] then tests="basics/*.py micropython/*.py float/*.py import/*.py io/*.py misc/*.py unicode/*.py extmod/*.py unix/*.py" else tests="$@" fi for infile in $tests do basename=`basename $infile .py` outfile=${basename}.py.out expfile=$infile.exp $MP_PY $infile > $outfile numtestcases=$(expr $numtestcases + $(cat $expfile | wc -l)) if grep -q "SKIP\|SyntaxError: invalid micropython decorator" $outfile then # we don't count tests that explicitly ask to be skipped # we don't count tests that fail due to unsupported decorator echo "skip $infile" $RM $outfile numskipped=$(expr $numskipped + 1) nameskipped="$nameskipped $basename" else diff --brief $expfile $outfile > /dev/null if [ $? -eq 0 ] then echo "pass $infile" $RM $outfile numpassed=$(expr $numpassed + 1) else echo "FAIL $infile" numfailed=$(expr $numfailed + 1) namefailed="$namefailed $basename" fi fi numtests=$(expr $numtests + 1) done echo "$numtests tests performed ($numtestcases individual testcases)" echo "$numpassed tests passed" if [ $numskipped != 0 ] then echo "$numskipped tests skipped -$nameskipped" fi if [ $numfailed != 0 ] then echo "$numfailed tests failed -$namefailed" exit 1 else exit 0 fi micropython-1.12/tests/stress/000077500000000000000000000000001357706137100165075ustar00rootroot00000000000000micropython-1.12/tests/stress/dict_copy.py000066400000000000000000000002031357706137100210310ustar00rootroot00000000000000# copying a large dictionary a = {i:2*i for i in range(1000)} b = a.copy() for i in range(1000): print(i, b[i]) print(len(b)) micropython-1.12/tests/stress/dict_create.py000066400000000000000000000001401357706137100213220ustar00rootroot00000000000000# create a large dictionary d = {} x = 1 while x < 1000: d[x] = x x += 1 print(d[500]) micropython-1.12/tests/stress/dict_create_max.py000066400000000000000000000005101357706137100221700ustar00rootroot00000000000000# The aim with this test is to hit the maximum resize/rehash size of a dict, # where there are no more primes in the table of growing allocation sizes. # This value is 54907 items. d = {} try: for i in range(54908): d[i] = i except MemoryError: pass # Just check the dict still has the first value print(d[0]) micropython-1.12/tests/stress/gc_trace.py000066400000000000000000000006031357706137100206270ustar00rootroot00000000000000# test that the GC can trace nested objects try: import gc except ImportError: print("SKIP") raise SystemExit # test a big shallow object pointing to many unique objects lst = [[i] for i in range(200)] gc.collect() print(lst) # test a deep object lst = [[[[[(i, j, k, l)] for i in range(3)] for j in range(3)] for k in range(3)] for l in range(3)] gc.collect() print(lst) micropython-1.12/tests/stress/list_sort.py000066400000000000000000000002201357706137100210750ustar00rootroot00000000000000# test large list sorting (should not stack overflow) l = list(range(2000)) l.sort() print(l[0], l[-1]) l.sort(reverse=True) print(l[0], l[-1]) micropython-1.12/tests/stress/qstr_limit.py000066400000000000000000000037021357706137100212520ustar00rootroot00000000000000# Test interning qstrs that go over the limit of the maximum qstr length # (which is 255 bytes for the default configuration) def make_id(n, base='a'): return ''.join(chr(ord(base) + i % 26) for i in range(n)) # identifiers in parser for l in range(254, 259): g = {} var = make_id(l) try: exec(var + '=1', g) except RuntimeError: print('RuntimeError', l) continue print(var in g) # calling a function with kwarg def f(**k): print(k) for l in range(254, 259): try: exec('f({}=1)'.format(make_id(l))) except RuntimeError: print('RuntimeError', l) # type construction for l in range(254, 259): id = make_id(l) try: print(type(id, (), {}).__name__) except RuntimeError: print('RuntimeError', l) # hasattr, setattr, getattr class A: pass for l in range(254, 259): id = make_id(l) a = A() try: setattr(a, id, 123) except RuntimeError: print('RuntimeError', l) try: print(hasattr(a, id), getattr(a, id)) except RuntimeError: print('RuntimeError', l) # format with keys for l in range(254, 259): id = make_id(l) try: print(('{' + id + '}').format(**{id: l})) except RuntimeError: print('RuntimeError', l) # modulo format with keys for l in range(254, 259): id = make_id(l) try: print(('%(' + id + ')d') % {id: l}) except RuntimeError: print('RuntimeError', l) # import module # (different OS's have different results so only run those that are consistent) for l in (100, 101, 256, 257, 258): try: __import__(make_id(l)) except ImportError: print('ok', l) except RuntimeError: print('RuntimeError', l) # import package for l in (100, 101, 102, 128, 129): try: exec('import ' + make_id(l) + '.' + make_id(l, 'A')) except ImportError: print('ok', l) except RuntimeError: print('RuntimeError', l) micropython-1.12/tests/stress/qstr_limit.py.exp000066400000000000000000000030251357706137100220430ustar00rootroot00000000000000True True RuntimeError 256 RuntimeError 257 RuntimeError 258 {'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst': 1} {'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu': 1} RuntimeError 256 RuntimeError 257 RuntimeError 258 abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu RuntimeError 256 RuntimeError 257 RuntimeError 258 True 123 True 123 RuntimeError 256 RuntimeError 256 RuntimeError 257 RuntimeError 257 RuntimeError 258 RuntimeError 258 254 255 RuntimeError 256 RuntimeError 257 RuntimeError 258 254 255 RuntimeError 256 RuntimeError 257 RuntimeError 258 ok 100 ok 101 RuntimeError 256 RuntimeError 257 RuntimeError 258 ok 100 ok 101 ok 102 RuntimeError 128 RuntimeError 129 micropython-1.12/tests/stress/recursion.py000066400000000000000000000001241357706137100210670ustar00rootroot00000000000000def foo(): foo() try: foo() except RuntimeError: print("RuntimeError") micropython-1.12/tests/stress/recursive_data.py000066400000000000000000000004271357706137100220640ustar00rootroot00000000000000# This tests that printing recursive data structure doesn't lead to segfault. try: import uio as io except ImportError: print("SKIP") raise SystemExit l = [1, 2, 3, None] l[-1] = l try: print(l, file=io.StringIO()) except RuntimeError: print("RuntimeError") micropython-1.12/tests/stress/recursive_data.py.exp000066400000000000000000000000151357706137100226500ustar00rootroot00000000000000RuntimeError micropython-1.12/tests/stress/recursive_gen.py000066400000000000000000000005141357706137100217210ustar00rootroot00000000000000# test deeply recursive generators # simple "yield from" recursion def gen(): yield from gen() try: list(gen()) except RuntimeError: print('RuntimeError') # recursion via an iterator over a generator def gen2(): for x in gen2(): yield x try: next(gen2()) except RuntimeError: print('RuntimeError') micropython-1.12/tests/stress/recursive_iternext.py000066400000000000000000000017671357706137100230250ustar00rootroot00000000000000# This tests that recursion with iternext doesn't lead to segfault. try: enumerate filter map max zip except: print("SKIP") raise SystemExit # We need to pick an N that is large enough to hit the recursion # limit, but not too large that we run out of heap memory. try: # large stack/heap, eg unix [0] * 80000 N = 5000 except: try: # medium, eg pyboard [0] * 10000 N = 1000 except: # small, eg esp8266 N = 100 try: x = (1, 2) for i in range(N): x = enumerate(x) tuple(x) except RuntimeError: print("RuntimeError") try: x = (1, 2) for i in range(N): x = filter(None, x) tuple(x) except RuntimeError: print("RuntimeError") try: x = (1, 2) for i in range(N): x = map(max, x, ()) tuple(x) except RuntimeError: print("RuntimeError") try: x = (1, 2) for i in range(N): x = zip(x) tuple(x) except RuntimeError: print("RuntimeError") micropython-1.12/tests/stress/recursive_iternext.py.exp000066400000000000000000000000641357706137100236050ustar00rootroot00000000000000RuntimeError RuntimeError RuntimeError RuntimeError micropython-1.12/tests/thread/000077500000000000000000000000001357706137100164335ustar00rootroot00000000000000micropython-1.12/tests/thread/mutate_bytearray.py000066400000000000000000000017651357706137100223770ustar00rootroot00000000000000# test concurrent mutating access to a shared bytearray object # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread # the shared bytearray ba = bytearray() # main thread function def th(n, lo, hi): for repeat in range(n): for i in range(lo, hi): l = len(ba) ba.append(i) assert len(ba) >= l + 1 l = len(ba) ba.extend(bytearray([i])) assert len(ba) >= l + 1 with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 4 n_finished = 0 n_repeat = 4 # use 40 for more stressful test (uses more heap) # spawn threads for i in range(n_thread): _thread.start_new_thread(th, (n_repeat, i * 256 // n_thread, (i + 1) * 256 // n_thread)) # busy wait for threads to finish while n_finished < n_thread: pass # check bytearray has correct contents print(len(ba)) count = [0 for _ in range(256)] for b in ba: count[b] += 1 print(count) micropython-1.12/tests/thread/mutate_dict.py000066400000000000000000000016271357706137100213150ustar00rootroot00000000000000# test concurrent mutating access to a shared dict object # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread # the shared dict di = {'a':'A', 'b':'B', 'c':'C', 'd':'D'} # main thread function def th(n, lo, hi): for repeat in range(n): for i in range(lo, hi): di[i] = repeat + i assert di[i] == repeat + i del di[i] assert i not in di di[i] = repeat + i assert di[i] == repeat + i assert di.pop(i) == repeat + i with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 4 n_finished = 0 # spawn threads for i in range(n_thread): _thread.start_new_thread(th, (30, i * 300, (i + 1) * 300)) # busy wait for threads to finish while n_finished < n_thread: pass # check dict has correct contents print(sorted(di.items())) micropython-1.12/tests/thread/mutate_instance.py000066400000000000000000000020671357706137100221750ustar00rootroot00000000000000# test concurrent mutating access to a shared user instance # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread # the shared user class and instance class User: def __init__(self): self.a = 'A' self.b = 'B' self.c = 'C' user = User() # main thread function def th(n, lo, hi): for repeat in range(n): for i in range(lo, hi): setattr(user, 'attr_%u' % i, repeat + i) assert getattr(user, 'attr_%u' % i) == repeat + i with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_repeat = 30 n_range = 50 # 300 for stressful test (uses more heap) n_thread = 4 n_finished = 0 # spawn threads for i in range(n_thread): _thread.start_new_thread(th, (n_repeat, i * n_range, (i + 1) * n_range)) # busy wait for threads to finish while n_finished < n_thread: pass # check user instance has correct contents print(user.a, user.b, user.c) for i in range(n_thread * n_range): assert getattr(user, 'attr_%u' % i) == n_repeat - 1 + i micropython-1.12/tests/thread/mutate_list.py000066400000000000000000000016411357706137100213410ustar00rootroot00000000000000# test concurrent mutating access to a shared list object # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread # the shared list li = list() # main thread function def th(n, lo, hi): for repeat in range(n): for i in range(lo, hi): li.append(i) assert li.count(i) == repeat + 1 li.extend([i, i]) assert li.count(i) == repeat + 3 li.remove(i) assert li.count(i) == repeat + 2 li.remove(i) assert li.count(i) == repeat + 1 with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 4 n_finished = 0 # spawn threads for i in range(n_thread): _thread.start_new_thread(th, (4, i * 60, (i + 1) * 60)) # busy wait for threads to finish while n_finished < n_thread: pass # check list has correct contents li.sort() print(li) micropython-1.12/tests/thread/mutate_set.py000066400000000000000000000013701357706137100211600ustar00rootroot00000000000000# test concurrent mutating access to a shared set object # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread # the shared set se = set([-1, -2, -3, -4]) # main thread function def th(n, lo, hi): for repeat in range(n): for i in range(lo, hi): se.add(i) assert i in se se.remove(i) assert i not in se with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 4 n_finished = 0 # spawn threads for i in range(n_thread): _thread.start_new_thread(th, (50, i * 500, (i + 1) * 500)) # busy wait for threads to finish while n_finished < n_thread: pass # check set has correct contents print(sorted(se)) micropython-1.12/tests/thread/stress_aes.py000066400000000000000000000212131357706137100211570ustar00rootroot00000000000000# Stress test for threads using AES encryption routines. # # AES was chosen because it is integer based and inplace so doesn't use the # heap. It is therefore a good test of raw performance and correctness of the # VM/runtime. It can be used to measure threading performance (concurrency is # in principle possible) and correctness (it's non trivial for the encryption/ # decryption to give the correct answer). # # The AES code comes first (code originates from a C version authored by D.P.George) # and then the test harness at the bottom. It can be tuned to be more/less # aggressive by changing the amount of data to encrypt, the number of loops and # the number of threads. # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd ################################################################## # discrete arithmetic routines, mostly from a precomputed table # non-linear, invertible, substitution box aes_s_box_table = bytes(( 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16, )) # multiplication of polynomials modulo x^8 + x^4 + x^3 + x + 1 = 0x11b def aes_gf8_mul_2(x): if x & 0x80: return (x << 1) ^ 0x11b else: return x << 1 def aes_gf8_mul_3(x): return x ^ aes_gf8_mul_2(x) # non-linear, invertible, substitution box def aes_s_box(a): return aes_s_box_table[a & 0xff] # return 0x02^(a-1) in GF(2^8) def aes_r_con(a): ans = 1 while a > 1: ans <<= 1; if ans & 0x100: ans ^= 0x11b a -= 1 return ans ################################################################## # basic AES algorithm; see FIPS-197 # # Think of it as a pseudo random number generator, with each # symbol in the sequence being a 16 byte block (the state). The # key is a parameter of the algorithm and tells which particular # sequence of random symbols you want. The initial vector, IV, # sets the start of the sequence. The idea of a strong cipher # is that it's very difficult to guess the key even if you know # a large part of the sequence. The basic AES algorithm simply # provides such a sequence. En/de-cryption is implemented here # using OCB, where the sequence is xored against the plaintext. # Care must be taken to (almost) always choose a different IV. # all inputs must be size 16 def aes_add_round_key(state, w): for i in range(16): state[i] ^= w[i] # combined sub_bytes, shift_rows, mix_columns, add_round_key # all inputs must be size 16 def aes_sb_sr_mc_ark(state, w, w_idx, temp): temp_idx = 0 for i in range(4): x0 = aes_s_box_table[state[i * 4]] x1 = aes_s_box_table[state[1 + ((i + 1) & 3) * 4]] x2 = aes_s_box_table[state[2 + ((i + 2) & 3) * 4]] x3 = aes_s_box_table[state[3 + ((i + 3) & 3) * 4]] temp[temp_idx] = aes_gf8_mul_2(x0) ^ aes_gf8_mul_3(x1) ^ x2 ^ x3 ^ w[w_idx] temp[temp_idx + 1] = x0 ^ aes_gf8_mul_2(x1) ^ aes_gf8_mul_3(x2) ^ x3 ^ w[w_idx + 1] temp[temp_idx + 2] = x0 ^ x1 ^ aes_gf8_mul_2(x2) ^ aes_gf8_mul_3(x3) ^ w[w_idx + 2] temp[temp_idx + 3] = aes_gf8_mul_3(x0) ^ x1 ^ x2 ^ aes_gf8_mul_2(x3) ^ w[w_idx + 3] w_idx += 4 temp_idx += 4 for i in range(16): state[i] = temp[i] # combined sub_bytes, shift_rows, add_round_key # all inputs must be size 16 def aes_sb_sr_ark(state, w, w_idx, temp): temp_idx = 0 for i in range(4): x0 = aes_s_box_table[state[i * 4]] x1 = aes_s_box_table[state[1 + ((i + 1) & 3) * 4]] x2 = aes_s_box_table[state[2 + ((i + 2) & 3) * 4]] x3 = aes_s_box_table[state[3 + ((i + 3) & 3) * 4]] temp[temp_idx] = x0 ^ w[w_idx] temp[temp_idx + 1] = x1 ^ w[w_idx + 1] temp[temp_idx + 2] = x2 ^ w[w_idx + 2] temp[temp_idx + 3] = x3 ^ w[w_idx + 3] w_idx += 4 temp_idx += 4 for i in range(16): state[i] = temp[i] # take state as input and change it to the next state in the sequence # state and temp have size 16, w has size 16 * (Nr + 1), Nr >= 1 def aes_state(state, w, temp, nr): aes_add_round_key(state, w) w_idx = 16 for i in range(nr - 1): aes_sb_sr_mc_ark(state, w, w_idx, temp) w_idx += 16 aes_sb_sr_ark(state, w, w_idx, temp) # expand 'key' to 'w' for use with aes_state # key has size 4 * Nk, w has size 16 * (Nr + 1), temp has size 16 def aes_key_expansion(key, w, temp, nk, nr): for i in range(4 * nk): w[i] = key[i] w_idx = 4 * nk - 4 for i in range(nk, 4 * (nr + 1)): t = temp t_idx = 0 if i % nk == 0: t[0] = aes_s_box(w[w_idx + 1]) ^ aes_r_con(i // nk) for j in range(1, 4): t[j] = aes_s_box(w[w_idx + (j + 1) % 4]) elif nk > 6 and i % nk == 4: for j in range(0, 4): t[j] = aes_s_box(w[w_idx + j]) else: t = w t_idx = w_idx w_idx += 4 for j in range(4): w[w_idx + j] = w[w_idx + j - 4 * nk] ^ t[t_idx + j] ################################################################## # simple use of AES algorithm, using output feedback (OFB) mode class AES: def __init__(self, keysize): if keysize == 128: self.nk = 4 self.nr = 10 elif keysize == 192: self.nk = 6 self.nr = 12 else: assert keysize == 256 self.nk = 8 self.nr = 14 self.state = bytearray(16) self.w = bytearray(16 * (self.nr + 1)) self.temp = bytearray(16) self.state_pos = 16 def set_key(self, key): aes_key_expansion(key, self.w, self.temp, self.nk, self.nr) self.state_pos = 16 def set_iv(self, iv): for i in range(16): self.state[i] = iv[i] self.state_pos = 16; def get_some_state(self, n_needed): if self.state_pos >= 16: aes_state(self.state, self.w, self.temp, self.nr) self.state_pos = 0 n = 16 - self.state_pos if n > n_needed: n = n_needed return n def apply_to(self, data): idx = 0 n = len(data) while n > 0: ln = self.get_some_state(n) n -= ln for i in range(ln): data[idx + i] ^= self.state[self.state_pos + i] idx += ln self.state_pos += n ################################################################## # test code try: import utime as time except ImportError: import time import _thread class LockedCounter: def __init__(self): self.lock = _thread.allocate_lock() self.value = 0 def add(self, val): self.lock.acquire() self.value += val self.lock.release() count = LockedCounter() def thread_entry(): global count aes = AES(256) key = bytearray(256 // 8) iv = bytearray(16) data = bytearray(128) # from now on we don't use the heap for loop in range(5): # encrypt aes.set_key(key) aes.set_iv(iv) for i in range(8): aes.apply_to(data) # decrypt aes.set_key(key) aes.set_iv(iv) for i in range(8): aes.apply_to(data) # verify for i in range(len(data)): assert data[i] == 0 count.add(1) if __name__ == '__main__': n_thread = 20 for i in range(n_thread): _thread.start_new_thread(thread_entry, ()) while count.value < n_thread: time.sleep(1) micropython-1.12/tests/thread/stress_create.py000066400000000000000000000006131357706137100216530ustar00rootroot00000000000000# stress test for creating many threads try: import utime as time except ImportError: import time import _thread def thread_entry(n): pass thread_num = 0 while thread_num < 500: try: _thread.start_new_thread(thread_entry, (thread_num,)) thread_num += 1 except MemoryError: pass # wait for the last threads to terminate time.sleep(1) print('done') micropython-1.12/tests/thread/stress_heap.py000066400000000000000000000021131357706137100213220ustar00rootroot00000000000000# stress test for the heap by allocating lots of objects within threads # allocates about 5mb on the heap # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime as time except ImportError: import time import _thread def last(l): return l[-1] def thread_entry(n): # allocate a bytearray and fill it data = bytearray(i for i in range(256)) # run a loop which allocates a small list and uses it each iteration lst = 8 * [0] sum = 0 for i in range(n): sum += last(lst) lst = [0, 0, 0, 0, 0, 0, 0, i + 1] # check that the bytearray still has the right data for i, b in enumerate(data): assert i == b # print the result of the loop and indicate we are finished with lock: print(sum, lst[-1]) global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 10 n_finished = 0 # spawn threads for i in range(n_thread): _thread.start_new_thread(thread_entry, (10000,)) # wait for threads to finish while n_finished < n_thread: time.sleep(1) micropython-1.12/tests/thread/stress_recurse.py000066400000000000000000000007041357706137100220610ustar00rootroot00000000000000# test hitting the function recursion limit within a thread # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread def foo(): foo() def thread_entry(): try: foo() except RuntimeError: print('RuntimeError') global finished finished = True finished = False _thread.start_new_thread(thread_entry, ()) # busy wait for thread to finish while not finished: pass print('done') micropython-1.12/tests/thread/thread_exc1.py000066400000000000000000000010641357706137100211750ustar00rootroot00000000000000# test raising and catching an exception within a thread # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread def foo(): raise ValueError def thread_entry(): try: foo() except ValueError: pass with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 4 n_finished = 0 # spawn threads for i in range(n_thread): _thread.start_new_thread(thread_entry, ()) # busy wait for threads to finish while n_finished < n_thread: pass print('done') micropython-1.12/tests/thread/thread_exc2.py000066400000000000000000000003121357706137100211710ustar00rootroot00000000000000# test raising exception within thread which is not caught import utime import _thread def thread_entry(): raise ValueError _thread.start_new_thread(thread_entry, ()) utime.sleep(1) print('done') micropython-1.12/tests/thread/thread_exc2.py.exp000066400000000000000000000002551357706137100217720ustar00rootroot00000000000000Unhandled exception in thread started by Traceback (most recent call last): File \.\+, line 6, in thread_entry ValueError: done micropython-1.12/tests/thread/thread_exit1.py000066400000000000000000000005661357706137100213750ustar00rootroot00000000000000# test _thread.exit() function # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime as time except ImportError: import time import _thread def thread_entry(): _thread.exit() _thread.start_new_thread(thread_entry, ()) _thread.start_new_thread(thread_entry, ()) # wait for threads to finish time.sleep(1) print('done') micropython-1.12/tests/thread/thread_exit2.py000066400000000000000000000006061357706137100213710ustar00rootroot00000000000000# test raising SystemExit to finish a thread # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime as time except ImportError: import time import _thread def thread_entry(): raise SystemExit _thread.start_new_thread(thread_entry, ()) _thread.start_new_thread(thread_entry, ()) # wait for threads to finish time.sleep(1) print('done') micropython-1.12/tests/thread/thread_gc1.py000066400000000000000000000015111357706137100210040ustar00rootroot00000000000000# test that we can run the garbage collector within threads # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import gc import _thread def thread_entry(n): # allocate a bytearray and fill it data = bytearray(i for i in range(256)) # do some work and call gc.collect() a few times for i in range(n): for i in range(len(data)): data[i] = data[i] gc.collect() # print whether the data remains intact and indicate we are finished with lock: print(list(data) == list(range(256))) global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 4 n_finished = 0 # spawn threads for i in range(n_thread): _thread.start_new_thread(thread_entry, (10,)) # busy wait for threads to finish while n_finished < n_thread: pass micropython-1.12/tests/thread/thread_ident1.py000066400000000000000000000007311357706137100215210ustar00rootroot00000000000000# test _thread.get_ident() function # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread def thread_entry(): tid = _thread.get_ident() print('thread', type(tid) == int, tid != 0, tid != tid_main) global finished finished = True tid_main = _thread.get_ident() print('main', type(tid_main) == int, tid_main != 0) finished = False _thread.start_new_thread(thread_entry, ()) while not finished: pass print('done') micropython-1.12/tests/thread/thread_lock1.py000066400000000000000000000016261357706137100213520ustar00rootroot00000000000000# test _thread lock object using a single thread # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread # create lock lock = _thread.allocate_lock() print(type(lock) == _thread.LockType) # should be unlocked print(lock.locked()) # basic acquire and release print(lock.acquire()) print(lock.locked()) lock.release() print(lock.locked()) # try acquire twice (second should fail) print(lock.acquire()) print(lock.locked()) print(lock.acquire(0)) print(lock.locked()) lock.release() print(lock.locked()) # test with capabilities of lock with lock: print(lock.locked()) # test that lock is unlocked if an error is rasied try: with lock: print(lock.locked()) raise KeyError except KeyError: print('KeyError') print(lock.locked()) # test that we can't release an unlocked lock try: lock.release() except RuntimeError: print('RuntimeError') micropython-1.12/tests/thread/thread_lock2.py000066400000000000000000000007211357706137100213460ustar00rootroot00000000000000# test _thread lock objects with multiple threads # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime as time except ImportError: import time import _thread lock = _thread.allocate_lock() def thread_entry(): lock.acquire() print('have it') lock.release() # spawn the threads for i in range(4): _thread.start_new_thread(thread_entry, ()) # wait for threads to finish time.sleep(1) print('done') micropython-1.12/tests/thread/thread_lock3.py000066400000000000000000000010701357706137100213450ustar00rootroot00000000000000# test thread coordination using a lock object # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread lock = _thread.allocate_lock() n_thread = 10 n_finished = 0 def thread_entry(idx): global n_finished while True: with lock: if n_finished == idx: break print('my turn:', idx) with lock: n_finished += 1 # spawn threads for i in range(n_thread): _thread.start_new_thread(thread_entry, (i,)) # busy wait for threads to finish while n_finished < n_thread: pass micropython-1.12/tests/thread/thread_lock4.py000066400000000000000000000021221357706137100213450ustar00rootroot00000000000000# test using lock to coordinate access to global mutable objects # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime as time except ImportError: import time import _thread def fac(n): x = 1 for i in range(1, n + 1): x *= i return x def thread_entry(): while True: with jobs_lock: try: f, arg = jobs.pop(0) except IndexError: return ans = f(arg) with output_lock: output.append((arg, ans)) # create a list of jobs jobs = [(fac, i) for i in range(20, 80)] jobs_lock = _thread.allocate_lock() n_jobs = len(jobs) # create a list to store the results output = [] output_lock = _thread.allocate_lock() # spawn threads to do the jobs for i in range(4): _thread.start_new_thread(thread_entry, ()) # wait for the jobs to complete while True: with jobs_lock: if len(output) == n_jobs: break time.sleep(1) # sort and print the results output.sort(key=lambda x: x[0]) for arg, ans in output: print(arg, ans) micropython-1.12/tests/thread/thread_qstr1.py000066400000000000000000000015771357706137100214200ustar00rootroot00000000000000# test concurrent interning of strings # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime as time except ImportError: import time import _thread # function to check the interned string def check(s, val): assert type(s) == str assert int(s) == val # main thread function def th(base, n): for i in range(n): # this will intern the string and check it exec("check('%u', %u)" % (base + i, base + i)) with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 4 n_finished = 0 n_qstr_per_thread = 100 # make 1000 for a more stressful test (uses more heap) # spawn threads for i in range(n_thread): _thread.start_new_thread(th, (i * n_qstr_per_thread, n_qstr_per_thread)) # wait for threads to finish while n_finished < n_thread: time.sleep(1) print('pass') micropython-1.12/tests/thread/thread_shared1.py000066400000000000000000000011331357706137100216610ustar00rootroot00000000000000# test capability for threads to access a shared immutable data structure # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread def foo(i): pass def thread_entry(n, tup): for i in tup: foo(i) with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 2 n_finished = 0 # the shared data structure tup = (1, 2, 3, 4) # spawn threads for i in range(n_thread): _thread.start_new_thread(thread_entry, (100, tup)) # busy wait for threads to finish while n_finished < n_thread: pass print(tup) micropython-1.12/tests/thread/thread_shared2.py000066400000000000000000000013101357706137100216570ustar00rootroot00000000000000# test capability for threads to access a shared mutable data structure # (without contention because they access different parts of the structure) # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import _thread def foo(lst, i): lst[i] += 1 def thread_entry(n, lst, idx): for i in range(n): foo(lst, idx) with lock: global n_finished n_finished += 1 lock = _thread.allocate_lock() n_thread = 2 n_finished = 0 # the shared data structure lst = [0, 0] # spawn threads for i in range(n_thread): _thread.start_new_thread(thread_entry, ((i + 1) * 10, lst, i)) # busy wait for threads to finish while n_finished < n_thread: pass print(lst) micropython-1.12/tests/thread/thread_sleep1.py000066400000000000000000000011441357706137100215250ustar00rootroot00000000000000# test threads sleeping # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime sleep_ms = utime.sleep_ms except ImportError: import time sleep_ms = lambda t: time.sleep(t / 1000) import _thread lock = _thread.allocate_lock() n_thread = 4 n_finished = 0 def thread_entry(t): global n_finished sleep_ms(t) sleep_ms(2 * t) with lock: n_finished += 1 for i in range(n_thread): _thread.start_new_thread(thread_entry, (10 * i,)) # wait for threads to finish while n_finished < n_thread: sleep_ms(100) print('done', n_thread) micropython-1.12/tests/thread/thread_stacksize1.py000066400000000000000000000017241357706137100224210ustar00rootroot00000000000000# test setting the thread stack size # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import sys import _thread # different implementations have different minimum sizes if sys.implementation.name == 'micropython': sz = 2 * 1024 else: sz = 32 * 1024 def foo(): pass def thread_entry(): foo() with lock: global n_finished n_finished += 1 # reset stack size to default _thread.stack_size() # test set/get of stack size print(_thread.stack_size()) print(_thread.stack_size(sz)) print(_thread.stack_size() == sz) print(_thread.stack_size()) lock = _thread.allocate_lock() n_thread = 2 n_finished = 0 # set stack size and spawn a few threads _thread.stack_size(sz) for i in range(n_thread): _thread.start_new_thread(thread_entry, ()) # reset stack size to default (for subsequent scripts on baremetal) _thread.stack_size() # busy wait for threads to finish while n_finished < n_thread: pass print('done') micropython-1.12/tests/thread/thread_start1.py000066400000000000000000000006631357706137100215570ustar00rootroot00000000000000# test basic capability to start a new thread # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime as time except ImportError: import time import _thread def foo(): pass def thread_entry(n): for i in range(n): foo() _thread.start_new_thread(thread_entry, (10,)) _thread.start_new_thread(thread_entry, (20,)) # wait for threads to finish time.sleep(1) print('done') micropython-1.12/tests/thread/thread_start2.py000066400000000000000000000011331357706137100215510ustar00rootroot00000000000000# test capability to start a thread with keyword args # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd try: import utime as time except ImportError: import time import _thread def thread_entry(a0, a1, a2, a3): print('thread', a0, a1, a2, a3) # spawn thread using kw args _thread.start_new_thread(thread_entry, (10, 20), {'a2': 0, 'a3': 1}) # wait for thread to finish time.sleep(1) # incorrect argument where dictionary is needed for keyword args try: _thread.start_new_thread(thread_entry, (), ()) except TypeError: print('TypeError') print('done') micropython-1.12/tests/unicode/000077500000000000000000000000001357706137100166125ustar00rootroot00000000000000micropython-1.12/tests/unicode/data/000077500000000000000000000000001357706137100175235ustar00rootroot00000000000000micropython-1.12/tests/unicode/data/utf-8_1.txt000066400000000000000000000000151357706137100214430ustar00rootroot00000000000000Привет micropython-1.12/tests/unicode/data/utf-8_2.txt000066400000000000000000000000251357706137100214450ustar00rootroot00000000000000aαbβcγdδ ぁ🙐 micropython-1.12/tests/unicode/file1.py000066400000000000000000000001371357706137100201650ustar00rootroot00000000000000f = open("unicode/data/utf-8_1.txt", encoding="utf-8") l = f.readline() print(l) print(len(l)) micropython-1.12/tests/unicode/file2.py000066400000000000000000000007751357706137100201760ustar00rootroot00000000000000# test reading a given number of characters def do(mode): if mode == 'rb': enc = None else: enc = 'utf-8' f = open('unicode/data/utf-8_2.txt', mode=mode, encoding=enc) print(f.read(1)) print(f.read(1)) print(f.read(2)) print(f.read(4)) # skip to end of line f.readline() # check 3-byte utf-8 char print(f.read(1 if mode == 'rt' else 3)) # check 4-byte utf-8 char print(f.read(1 if mode == 'rt' else 4)) f.close() do('rb') do('rt') micropython-1.12/tests/unicode/unicode.py000066400000000000000000000025101357706137100206100ustar00rootroot00000000000000# Test a UTF-8 encoded literal s = "asdf©qwer" for i in range(len(s)): print("s[%d]: %s %X"%(i, s[i], ord(s[i]))) # Test all three forms of Unicode escape, and # all blocks of UTF-8 byte patterns s = "a\xA9\xFF\u0123\u0800\uFFEE\U0001F44C" for i in range(-len(s), len(s)): print("s[%d]: %s %X"%(i, s[i], ord(s[i]))) print("s[:%d]: %d chars, '%s'"%(i, len(s[:i]), s[:i])) for j in range(i, len(s)): print("s[%d:%d]: %d chars, '%s'"%(i, j, len(s[i:j]), s[i:j])) print("s[%d:]: %d chars, '%s'"%(i, len(s[i:]), s[i:])) # Test UTF-8 encode and decode enc = s.encode() print(enc, enc.decode() == s) # printing of unicode chars using repr # NOTE: for some characters (eg \u10ff) we differ to CPython print(repr('a\uffff')) print(repr('a\U0001ffff')) # test invalid escape code try: eval('"\\U00110000"') except SyntaxError: print('SyntaxError') # test unicode string given to int try: int('\u0200') except ValueError: print('ValueError') # test invalid UTF-8 string try: str(b'ab\xa1', 'utf8') except UnicodeError: print('UnicodeError') try: str(b'ab\xf8', 'utf8') except UnicodeError: print('UnicodeError') try: str(bytearray(b'ab\xc0a'), 'utf8') except UnicodeError: print('UnicodeError') try: str(b'\xf0\xe0\xed\xe8', 'utf8') except UnicodeError: print('UnicodeError') micropython-1.12/tests/unicode/unicode_chr.py000066400000000000000000000001421357706137100214430ustar00rootroot00000000000000# test builtin chr with unicode characters print(chr(945)) print(chr(0x800)) print(chr(0x10000)) micropython-1.12/tests/unicode/unicode_id.py000066400000000000000000000006541357706137100212730ustar00rootroot00000000000000# test unicode in identifiers # comment # αβγδϵφζ # global identifiers α = 1 αβγ = 2 bβ = 3 βb = 4 print(α, αβγ, bβ, βb) # function, argument, local identifiers def α(β, γ): δ = β + γ print(β, γ, δ) α(1, 2) # class, method identifiers class φ: def __init__(self): pass def δ(self, ϵ): print(ϵ) zζzζz = φ() if hasattr(zζzζz, "δ"): zζzζz.δ(ϵ=123) micropython-1.12/tests/unicode/unicode_index.py000066400000000000000000000003121357706137100217750ustar00rootroot00000000000000print("Привет".find("т")) print("Привет".find("П")) print("Привет".rfind("т")) print("Привет".rfind("П")) print("Привет".index("т")) print("Привет".index("П")) micropython-1.12/tests/unicode/unicode_iter.py000066400000000000000000000001051357706137100216310ustar00rootroot00000000000000for c in "Hello": print(c) for c in "Привет": print(c) micropython-1.12/tests/unicode/unicode_ord.py000066400000000000000000000000751357706137100214600ustar00rootroot00000000000000# test builtin ord with unicode characters print(ord('α')) micropython-1.12/tests/unicode/unicode_pos.py000066400000000000000000000003031357706137100214670ustar00rootroot00000000000000# str methods with explicit start/end pos print("Привет".startswith("П")) print("Привет".startswith("р", 1)) print("абвба".find("а", 1)) print("абвба".find("а", 1, -1)) micropython-1.12/tests/unicode/unicode_str_format.py000066400000000000000000000001441357706137100230510ustar00rootroot00000000000000# test handling of unicode chars in format strings print('α'.format()) print('{α}'.format(α=1)) micropython-1.12/tests/unicode/unicode_str_modulo.py000066400000000000000000000001121357706137100230530ustar00rootroot00000000000000# test handling of unicode chars in string % formatting print('α' % ()) micropython-1.12/tests/unicode/unicode_subscr.py000066400000000000000000000005201357706137100221700ustar00rootroot00000000000000a = '¢пр' print(a[0], a[0:1]) print(a[1], a[1:2]) print(a[2], a[2:3]) try: print(a[3]) except IndexError: print("IndexError") print(a[3:4]) print(a[-1]) print(a[-2], a[-2:-1]) print(a[-3], a[-3:-2]) try: print(a[-4]) except IndexError: print("IndexError") print(a[-4:-3]) print(a[0:2]) print(a[1:3]) print(a[2:4]) micropython-1.12/tests/unix/000077500000000000000000000000001357706137100161475ustar00rootroot00000000000000micropython-1.12/tests/unix/extra_coverage.py000066400000000000000000000046111357706137100215210ustar00rootroot00000000000000try: extra_coverage except NameError: print("SKIP") raise SystemExit import uerrno import uio data = extra_coverage() # test hashing of str/bytes that have an invalid hash print(data[0], data[1]) print(hash(data[0])) print(hash(data[1])) print(hash(bytes(data[0], 'utf8'))) print(hash(str(data[1], 'utf8'))) # test streams stream = data[2] # has set_error and set_buf. Write always returns error stream.set_error(uerrno.EAGAIN) # non-blocking error print(stream.read()) # read all encounters non-blocking error print(stream.read(1)) # read 1 byte encounters non-blocking error print(stream.readline()) # readline encounters non-blocking error print(stream.readinto(bytearray(10))) # readinto encounters non-blocking error print(stream.write(b'1')) # write encounters non-blocking error print(stream.write1(b'1')) # write1 encounters non-blocking error stream.set_buf(b'123') print(stream.read(4)) # read encounters non-blocking error after successful reads stream.set_buf(b'123') print(stream.read1(4)) # read1 encounters non-blocking error after successful reads stream.set_buf(b'123') print(stream.readline(4)) # readline encounters non-blocking error after successful reads try: print(stream.ioctl(0, 0)) # ioctl encounters non-blocking error; raises OSError except OSError: print('OSError') stream.set_error(0) print(stream.ioctl(0, bytearray(10))) # successful ioctl call stream2 = data[3] # is textio print(stream2.read(1)) # read 1 byte encounters non-blocking error with textio stream # test BufferedWriter with stream errors stream.set_error(uerrno.EAGAIN) buf = uio.BufferedWriter(stream, 8) print(buf.write(bytearray(16))) # test basic import of frozen scripts import frzstr1 print(frzstr1.__file__) import frzmpy1 print(frzmpy1.__file__) # test import of frozen packages with __init__.py import frzstr_pkg1 print(frzstr_pkg1.__file__, frzstr_pkg1.x) import frzmpy_pkg1 print(frzmpy_pkg1.__file__, frzmpy_pkg1.x) # test import of frozen packages without __init__.py from frzstr_pkg2.mod import Foo print(Foo.x) from frzmpy_pkg2.mod import Foo print(Foo.x) # test raising exception in frozen script try: import frzmpy2 except ZeroDivisionError: print('ZeroDivisionError') # test loading a resource from a frozen string import uio buf = uio.resource_stream('frzstr_pkg2', 'mod.py') print(buf.read(21)) # test for MP_QSTR_NULL regression from frzqstr import returns_NULL print(returns_NULL()) micropython-1.12/tests/unix/extra_coverage.py.exp000066400000000000000000000024231357706137100223130ustar00rootroot00000000000000# mp_printf -123 +123 123 -0123 123 123 1ABCDEF ab abc false true (null) -2147483648 2147483648 80000000 80000000 abc % # GC 0 0 # vstr tests sts test tes RuntimeError: RuntimeError: # repl ame__ __class__ __name__ argv atexit byteorder exc_info exit getsizeof implementation maxsize modules path platform print_exception stderr stdin stdout version version_info ementation # attrtuple (start=1, stop=2, step=3) # str 1 # bytearray data # mpz 1 12345678 0 0 0 0 0 1 12345 6 # runtime utils TypeError: unsupported type for __abs__: 'str' TypeError: unsupported types for __divmod__: 'str', 'str' Warning: test # format float ? +1e+00 +1e+00 # binary 123 456 # VM 2 1 # scheduler sched(0)=1 sched(1)=1 sched(2)=1 sched(3)=1 sched(4)=0 unlocked 0 1 2 3 # ringbuf 99 0 98 1 22 99 0 97 2 aa55 99 0 0 99 -1 1 98 -1 2 97 0 cc99 99 0 0 11bb 0 22ff -1 -1 0123456789 b'0123456789' 7300 7300 7300 7300 None None None None None None b'123' b'123' b'123' OSError 0 None None frzstr1 frzstr1.py frzmpy1 frzmpy1.py frzstr_pkg1.__init__ frzstr_pkg1/__init__.py 1 frzmpy_pkg1.__init__ frzmpy_pkg1/__init__.py 1 frzstr_pkg2.mod 1 frzmpy_pkg2.mod 1 ZeroDivisionError b'# test frozen package' NULL micropython-1.12/tests/unix/ffi_callback.py000066400000000000000000000012041357706137100210760ustar00rootroot00000000000000try: import ffi except ImportError: print("SKIP") raise SystemExit def ffi_open(names): err = None for n in names: try: mod = ffi.open(n) return mod except OSError as e: err = e raise err libc = ffi_open(('libc.so', 'libc.so.0', 'libc.so.6', 'libc.dylib')) qsort = libc.func("v", "qsort", "piip") def cmp(pa, pb): a = ffi.as_bytearray(pa, 1) b = ffi.as_bytearray(pb, 1) #print("cmp:", a, b) return a[0] - b[0] cmp_c = ffi.callback("i", cmp, "pp") s = bytearray(b"foobar") print("org string:", s) qsort(s, len(s), 1, cmp_c) print("qsort'ed:", s) micropython-1.12/tests/unix/ffi_callback.py.exp000066400000000000000000000001001357706137100216630ustar00rootroot00000000000000org string: bytearray(b'foobar') qsort'ed: bytearray(b'abfoor') micropython-1.12/tests/unix/ffi_float.py000066400000000000000000000016601357706137100204550ustar00rootroot00000000000000# test ffi float support try: import ffi except ImportError: print("SKIP") raise SystemExit def ffi_open(names): err = None for n in names: try: mod = ffi.open(n) return mod except OSError as e: err = e raise err libc = ffi_open(('libc.so', 'libc.so.0', 'libc.so.6', 'libc.dylib')) try: strtof = libc.func("f", "strtof", "sp") except OSError: # Some libc's (e.g. Android's Bionic) define strtof as macro/inline func # in terms of strtod(). print("SKIP") raise SystemExit print('%.6f' % strtof('1.23', None)) strtod = libc.func("d", "strtod", "sp") print('%.6f' % strtod('1.23', None)) # test passing double and float args libm = ffi_open(('libm.so', 'libm.so.6', 'libc.so.0', 'libc.so.6', 'libc.dylib')) tgamma = libm.func('d', 'tgamma', 'd') for fun in (tgamma,): for val in (0.5, 1, 1.0, 1.5, 4, 4.0): print('%.6f' % fun(val)) micropython-1.12/tests/unix/ffi_float.py.exp000066400000000000000000000001101357706137100212350ustar00rootroot000000000000001.230000 1.230000 1.772454 1.000000 1.000000 0.886227 6.000000 6.000000 micropython-1.12/tests/unix/ffi_float2.py000066400000000000000000000012521357706137100205340ustar00rootroot00000000000000# test ffi float support try: import ffi except ImportError: print("SKIP") raise SystemExit def ffi_open(names): err = None for n in names: try: mod = ffi.open(n) return mod except OSError as e: err = e raise err libm = ffi_open(('libm.so', 'libm.so.6', 'libc.so.0', 'libc.so.6', 'libc.dylib')) # Some libc's implement tgammaf as header macro with tgamma(), so don't assume # it'll be in library. try: tgammaf = libm.func('f', 'tgammaf', 'f') except OSError: print("SKIP") raise SystemExit for fun in (tgammaf,): for val in (0.5, 1, 1.0, 1.5, 4, 4.0): print('%.6f' % fun(val)) micropython-1.12/tests/unix/ffi_float2.py.exp000066400000000000000000000000661357706137100213310ustar00rootroot000000000000001.772454 1.000000 1.000000 0.886227 6.000000 6.000000 micropython-1.12/tests/wipy/000077500000000000000000000000001357706137100161545ustar00rootroot00000000000000micropython-1.12/tests/wipy/adc.py000066400000000000000000000031571357706137100172630ustar00rootroot00000000000000''' ADC test for the CC3200 based boards. ''' from machine import ADC import os mch = os.uname().machine if 'LaunchPad' in mch: adc_pin = 'GP5' adc_channel = 3 elif 'WiPy' in mch: adc_pin = 'GP3' adc_channel = 1 else: raise Exception('Board not supported!') adc = ADC(0) print(adc) adc = ADC() print(adc) adc = ADC(0, bits=12) print(adc) apin = adc.channel(adc_channel) print(apin) apin = adc.channel(id=adc_channel) print(apin) apin = adc.channel(adc_channel, pin=adc_pin) print(apin) apin = adc.channel(id=adc_channel, pin=adc_pin) print(apin) print(apin.value() > 3000) print(apin() > 3000) # de-init must work apin.deinit() print(apin) adc.deinit() print(adc) print(apin) adc.init() print(adc) print(apin) apin.init() print(apin) print(apin() > 3000) # check for memory leaks... for i in range (0, 1000): adc = ADC() apin = adc.channel(adc_channel) # next ones should raise try: adc = ADC(bits=17) except: print('Exception') try: adc = ADC(id=1) except: print('Exception') try: adc = ADC(0, 16) except: print('Exception') adc = ADC() try: apin = adc.channel(4) except: print('Exception') try: apin = adc.channel(-1) except: print('Exception') try: apin = adc.channel(0, pin='GP3') except: print('Exception') apin = adc.channel(1) apin.deinit() try: apin() except: print('Exception') try: apin.value() except: print('Exception') adc.deinit() try: apin.value() except: print('Exception') try: apin = adc.channel(1) except: print('Exception') # re-init must work adc.init() apin.init() print(apin) print(apin() > 3000) micropython-1.12/tests/wipy/adc.py.exp000066400000000000000000000005631357706137100200540ustar00rootroot00000000000000ADC(0, bits=12) ADC(0, bits=12) ADC(0, bits=12) ADCChannel(1, pin=GP3) ADCChannel(1, pin=GP3) ADCChannel(1, pin=GP3) ADCChannel(1, pin=GP3) True True ADCChannel(1) ADC(0) ADCChannel(1) ADC(0, bits=12) ADCChannel(1) ADCChannel(1, pin=GP3) True Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception ADCChannel(1, pin=GP3) True micropython-1.12/tests/wipy/i2c.py000066400000000000000000000101511357706137100172010ustar00rootroot00000000000000''' I2C test for the CC3200 based boards. A MPU-9150 sensor must be connected to the I2C bus. ''' from machine import I2C import os import time mch = os.uname().machine if 'LaunchPad' in mch: i2c_pins = ('GP11', 'GP10') elif 'WiPy' in mch: i2c_pins = ('GP15', 'GP10') else: raise Exception('Board not supported!') i2c = I2C(0, I2C.MASTER, baudrate=400000) # try initing without the peripheral id i2c = I2C() print(i2c) i2c = I2C(mode=I2C.MASTER, baudrate=50000, pins=i2c_pins) print(i2c) i2c = I2C(0, I2C.MASTER, baudrate=100000) print(i2c) i2c = I2C(0, mode=I2C.MASTER, baudrate=400000) print(i2c) i2c = I2C(0, mode=I2C.MASTER, baudrate=400000, pins=i2c_pins) print(i2c) addr = i2c.scan()[0] print(addr) reg = bytearray(1) reg2 = bytearray(2) reg2_r = bytearray(2) # reset the sensor reg[0] |= 0x80 print(1 == i2c.writeto_mem(addr, 107, reg)) time.sleep_ms(100) # wait for the sensor to reset... print(1 == i2c.readfrom_mem_into(addr, 107, reg)) # read the power management register 1 print(0x40 == reg[0]) # now just read one byte data = i2c.readfrom_mem(addr, 117, 1) # read the "who am I?" register print(0x68 == data[0]) print(len(data) == 1) print(1 == i2c.readfrom_mem_into(addr, 117, reg)) # read the "who am I?" register again print(0x68 == reg[0]) # now try reading two bytes data = i2c.readfrom_mem(addr, 116, 2) # read the "who am I?" register print(0x68 == data[1]) print(data == b'\x00\x68') print(len(data) == 2) print(2 == i2c.readfrom_mem_into(addr, 116, reg2)) # read the "who am I?" register again print(0x68 == reg2[1]) print(reg2 == b'\x00\x68') print(1 == i2c.readfrom_mem_into(addr, 107, reg)) # read the power management register 1 print(0x40 == reg[0]) # clear the sleep bit reg[0] = 0 print(1 == i2c.writeto_mem(addr, 107, reg)) # read it back i2c.readfrom_mem_into(addr, 107, reg) print(0 == reg[0]) # set the sleep bit reg[0] = 0x40 print(1 == i2c.writeto_mem(addr, 107, reg)) # read it back i2c.readfrom_mem_into(addr, 107, reg) print(0x40 == reg[0]) # reset the sensor reg[0] |= 0x80 print(1 == i2c.writeto_mem(addr, 107, reg)) time.sleep_ms(100) # wait for the sensor to reset... # now read and write two register at a time print(2 == i2c.readfrom_mem_into(addr, 107, reg2)) print(0x40 == reg2[0]) print(0x00 == reg2[1]) # clear the sleep bit reg2[0] = 0 # set some other bits reg2[1] |= 0x03 print(2 == i2c.writeto_mem(addr, 107, reg2)) # read it back i2c.readfrom_mem_into(addr, 107, reg2_r) print(reg2 == reg2_r) # reset the sensor reg[0] = 0x80 print(1 == i2c.writeto_mem(addr, 107, reg)) time.sleep_ms(100) # wait for the sensor to reset... # try some raw read and writes reg[0] = 117 # register address print(1 == i2c.writeto(addr, reg, stop=False)) # just write the register address # now read print(1 == i2c.readfrom_into(addr, reg)) print(reg[0] == 0x68) reg[0] = 117 # register address print(1 == i2c.writeto(addr, reg, stop=False)) # just write the register address # now read print(0x68 == i2c.readfrom(addr, 1)[0]) i2c.readfrom_mem_into(addr, 107, reg2) print(0x40 == reg2[0]) print(0x00 == reg2[1]) reg2[0] = 107 # register address reg2[1] = 0 print(2 == i2c.writeto(addr, reg2, stop=True)) # write the register address and the data i2c.readfrom_mem_into(addr, 107, reg) # check it back print(reg[0] == 0) # check for memory leaks... for i in range (0, 1000): i2c = I2C(0, I2C.MASTER, baudrate=100000) # test deinit i2c = I2C(0, I2C.MASTER, baudrate=100000) i2c.deinit() print(i2c) # next ones should raise try: i2c.scan() except Exception: print("Exception") try: i2c.readfrom(addr, 1) except Exception: print("Exception") try: i2c.readfrom_into(addr, reg) except Exception: print("Exception") try: i2c.readfrom_mem_into(addr, 107, reg) except Exception: print("Exception") try: i2c.writeto(addr, reg, stop=False) except Exception: print("Exception") try: i2c.writeto_mem(addr, 107, reg) except Exception: print("Exception") try: i2c.readfrom_mem(addr, 116, 2) except Exception: print("Exception") try: I2C(1, I2C.MASTER, baudrate=100000) except Exception: print("Exception") # reinitialization must work i2c.init(baudrate=400000) print(i2c) micropython-1.12/tests/wipy/i2c.py.exp000066400000000000000000000007411357706137100200000ustar00rootroot00000000000000I2C(0, I2C.MASTER, baudrate=100000) I2C(0, I2C.MASTER, baudrate=50000) I2C(0, I2C.MASTER, baudrate=100000) I2C(0, I2C.MASTER, baudrate=400000) I2C(0, I2C.MASTER, baudrate=400000) 104 True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True I2C(0) Exception Exception Exception Exception Exception Exception Exception Exception I2C(0, I2C.MASTER, baudrate=400000) micropython-1.12/tests/wipy/modwipy.py000066400000000000000000000006201357706137100202140ustar00rootroot00000000000000''' wipy module test for the CC3200 based boards ''' import os import wipy mch = os.uname().machine if not 'LaunchPad' in mch and not'WiPy' in mch: raise Exception('Board not supported!') print(wipy.heartbeat() == True) wipy.heartbeat(False) print(wipy.heartbeat() == False) wipy.heartbeat(True) print(wipy.heartbeat() == True) try: wipy.heartbeat(True, 1) except: print('Exception') micropython-1.12/tests/wipy/modwipy.py.exp000066400000000000000000000000311357706137100210030ustar00rootroot00000000000000True True True Exception micropython-1.12/tests/wipy/os.py000066400000000000000000000055431357706137100171560ustar00rootroot00000000000000''' os module test for the CC3200 based boards ''' from machine import SD import os mch = os.uname().machine if 'LaunchPad' in mch: sd_pins = ('GP16', 'GP17', 'GP15') elif 'WiPy' in mch: sd_pins = ('GP10', 'GP11', 'GP15') else: raise Exception('Board not supported!') sd = SD(pins=sd_pins) os.mount(sd, '/sd') os.mkfs('/sd') os.chdir('/flash') print(os.listdir()) os.chdir('/sd') print(os.listdir()) # create a test directory in flash os.mkdir('/flash/test') os.chdir('/flash/test') print(os.getcwd()) os.chdir('..') print(os.getcwd()) os.chdir('test') print(os.getcwd()) # create a new file f = open('test.txt', 'w') test_bytes = os.urandom(1024) n_w = f.write(test_bytes) print(n_w == len(test_bytes)) f.close() f = open('test.txt', 'r') r = bytes(f.read(), 'ascii') # check that we can write and read it correctly print(r == test_bytes) f.close() os.rename('test.txt', 'newtest.txt') print(os.listdir()) os.rename('/flash/test', '/flash/newtest') print(os.listdir('/flash')) os.remove('newtest.txt') os.chdir('..') os.rmdir('newtest') # create a test directory in the sd card os.mkdir('/sd/test') os.chdir('/sd/test') print(os.getcwd()) os.chdir('..') print(os.getcwd()) os.chdir('test') print(os.getcwd()) # create a new file f = open('test.txt', 'w') test_bytes = os.urandom(1024) n_w = f.write(test_bytes) print(n_w == len(test_bytes)) f.close() f = open('test.txt', 'r') r = bytes(f.read(), 'ascii') # check that we can write and read it correctly print(r == test_bytes) f.close() print('CC3200' in os.uname().machine) print('WiPy' == os.uname().sysname) os.sync() os.stat('/flash') os.stat('/flash/sys') os.stat('/flash/boot.py') os.stat('/sd') os.stat('/') os.chdir('/sd/test') os.remove('test.txt') os.chdir('/sd') os.rmdir('test') os.listdir('/sd') print(os.listdir('/')) os.unmount('/sd') print(os.listdir('/')) os.mkfs(sd) os.mount(sd, '/sd') print(os.listdir('/')) os.chdir('/flash') # next ones must raise sd.deinit() try: os.listdir('/sd') except: print('Exception') #re-initialization must work sd.init() print(os.listdir('/sd')) try: os.mount(sd, '/sd') except: print('Exception') try: os.mount(sd, '/sd2') except: print('Exception') os.unmount('/sd') try: os.listdir('/sd') except: print('Exception') try: os.unmount('/flash') except: print('Exception') try: os.unmount('/something') except: print('Exception') try: os.unmount('something') except: print('Exception') try: os.mkfs('flash') # incorrect path format except: print('Exception') try: os.remove('/flash/nofile.txt') except: print('Exception') try: os.rename('/flash/nofile.txt', '/flash/nofile2.txt') except: print('Exception') try: os.chdir('/flash/nodir') except: print('Exception') try: os.listdir('/flash/nodir') except: print('Exception') os.mount(sd, '/sd') print(os.listdir('/')) os.unmount('/sd') micropython-1.12/tests/wipy/os.py.exp000066400000000000000000000005661357706137100177510ustar00rootroot00000000000000['main.py', 'sys', 'lib', 'cert', 'boot.py'] [] /flash/test /flash /flash/test True True ['newtest.txt'] ['main.py', 'sys', 'lib', 'cert', 'boot.py', 'newtest'] /sd/test /sd /sd/test True True True True ['flash', 'sd'] ['flash'] ['flash', 'sd'] [] Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception ['flash', 'sd'] micropython-1.12/tests/wipy/pin.py000066400000000000000000000113761357706137100173240ustar00rootroot00000000000000""" This test need a set of pins which can be set as inputs and have no external pull up or pull down connected. GP12 and GP17 must be connected together """ from machine import Pin import os mch = os.uname().machine if 'LaunchPad' in mch: pin_map = ['GP24', 'GP12', 'GP14', 'GP15', 'GP16', 'GP17', 'GP28', 'GP8', 'GP6', 'GP30', 'GP31', 'GP3', 'GP0', 'GP4', 'GP5'] max_af_idx = 15 elif 'WiPy' in mch: pin_map = ['GP23', 'GP24', 'GP12', 'GP13', 'GP14', 'GP9', 'GP17', 'GP28', 'GP22', 'GP8', 'GP30', 'GP31', 'GP0', 'GP4', 'GP5'] max_af_idx = 15 else: raise Exception('Board not supported!') # test initial value p = Pin('GP12', Pin.IN) Pin('GP17', Pin.OUT, value=1) print(p() == 1) Pin('GP17', Pin.OUT, value=0) print(p() == 0) def test_noinit(): for p in pin_map: pin = Pin(p) pin.value() def test_pin_read(pull): # enable the pull resistor on all pins, then read the value for p in pin_map: pin = Pin(p, mode=Pin.IN, pull=pull) for p in pin_map: print(pin()) def test_pin_af(): for p in pin_map: for af in Pin(p).alt_list(): if af[1] <= max_af_idx: Pin(p, mode=Pin.ALT, alt=af[1]) Pin(p, mode=Pin.ALT_OPEN_DRAIN, alt=af[1]) # test un-initialized pins test_noinit() # test with pull-up and pull-down test_pin_read(Pin.PULL_UP) test_pin_read(Pin.PULL_DOWN) # test all constructor combinations pin = Pin(pin_map[0]) pin = Pin(pin_map[0], mode=Pin.IN) pin = Pin(pin_map[0], mode=Pin.OUT) pin = Pin(pin_map[0], mode=Pin.IN, pull=Pin.PULL_DOWN) pin = Pin(pin_map[0], mode=Pin.IN, pull=Pin.PULL_UP) pin = Pin(pin_map[0], mode=Pin.OPEN_DRAIN, pull=Pin.PULL_UP) pin = Pin(pin_map[0], mode=Pin.OUT, pull=Pin.PULL_DOWN) pin = Pin(pin_map[0], mode=Pin.OUT, pull=None) pin = Pin(pin_map[0], mode=Pin.OUT, pull=Pin.PULL_UP) pin = Pin(pin_map[0], mode=Pin.OUT, pull=Pin.PULL_UP, drive=pin.LOW_POWER) pin = Pin(pin_map[0], mode=Pin.OUT, pull=Pin.PULL_UP, drive=pin.MED_POWER) pin = Pin(pin_map[0], mode=Pin.OUT, pull=Pin.PULL_UP, drive=pin.HIGH_POWER) pin = Pin(pin_map[0], mode=Pin.OUT, drive=pin.LOW_POWER) pin = Pin(pin_map[0], Pin.OUT, Pin.PULL_DOWN) pin = Pin(pin_map[0], Pin.ALT, Pin.PULL_UP) pin = Pin(pin_map[0], Pin.ALT_OPEN_DRAIN, Pin.PULL_UP) test_pin_af() # try the entire af range on all pins # test pin init and printing pin = Pin(pin_map[0]) pin.init(mode=Pin.IN) print(pin) pin.init(Pin.IN, Pin.PULL_DOWN) print(pin) pin.init(mode=Pin.OUT, pull=Pin.PULL_UP, drive=pin.LOW_POWER) print(pin) pin.init(mode=Pin.OUT, pull=Pin.PULL_UP, drive=pin.HIGH_POWER) print(pin) # test value in OUT mode pin = Pin(pin_map[0], mode=Pin.OUT) pin.value(0) pin.toggle() # test toggle print(pin()) pin.toggle() # test toggle again print(pin()) # test different value settings pin(1) print(pin.value()) pin(0) print(pin.value()) pin.value(1) print(pin()) pin.value(0) print(pin()) # test all getters and setters pin = Pin(pin_map[0], mode=Pin.OUT) # mode print(pin.mode() == Pin.OUT) pin.mode(Pin.IN) print(pin.mode() == Pin.IN) # pull pin.pull(None) print(pin.pull() == None) pin.pull(Pin.PULL_DOWN) print(pin.pull() == Pin.PULL_DOWN) # drive pin.drive(Pin.MED_POWER) print(pin.drive() == Pin.MED_POWER) pin.drive(Pin.HIGH_POWER) print(pin.drive() == Pin.HIGH_POWER) # id print(pin.id() == pin_map[0]) # all the next ones MUST raise try: pin = Pin(pin_map[0], mode=Pin.OUT, pull=Pin.PULL_UP, drive=pin.IN) # incorrect drive value except Exception: print('Exception') try: pin = Pin(pin_map[0], mode=Pin.LOW_POWER, pull=Pin.PULL_UP) # incorrect mode value except Exception: print('Exception') try: pin = Pin(pin_map[0], mode=Pin.IN, pull=Pin.HIGH_POWER) # incorrect pull value except Exception: print('Exception') try: pin = Pin('A0', Pin.OUT, Pin.PULL_DOWN) # incorrect pin id except Exception: print('Exception') try: pin = Pin(pin_map[0], Pin.IN, Pin.PULL_UP, alt=0) # af specified in GPIO mode except Exception: print('Exception') try: pin = Pin(pin_map[0], Pin.OUT, Pin.PULL_UP, alt=7) # af specified in GPIO mode except Exception: print('Exception') try: pin = Pin(pin_map[0], Pin.ALT, Pin.PULL_UP, alt=0) # incorrect af except Exception: print('Exception') try: pin = Pin(pin_map[0], Pin.ALT_OPEN_DRAIN, Pin.PULL_UP, alt=-1) # incorrect af except Exception: print('Exception') try: pin = Pin(pin_map[0], Pin.ALT_OPEN_DRAIN, Pin.PULL_UP, alt=16) # incorrect af except Exception: print('Exception') try: pin.mode(Pin.PULL_UP) # incorrect pin mode except Exception: print('Exception') try: pin.pull(Pin.OUT) # incorrect pull except Exception: print('Exception') try: pin.drive(Pin.IN) # incorrect drive strength except Exception: print('Exception') try: pin.id('ABC') # id cannot be set except Exception: print('Exception') micropython-1.12/tests/wipy/pin.py.exp000066400000000000000000000010011357706137100200770ustar00rootroot00000000000000True True 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Pin('GP23', mode=Pin.IN, pull=None, drive=Pin.MED_POWER, alt=-1) Pin('GP23', mode=Pin.IN, pull=Pin.PULL_DOWN, drive=Pin.MED_POWER, alt=-1) Pin('GP23', mode=Pin.OUT, pull=Pin.PULL_UP, drive=Pin.LOW_POWER, alt=-1) Pin('GP23', mode=Pin.OUT, pull=Pin.PULL_UP, drive=Pin.HIGH_POWER, alt=-1) 1 0 1 0 1 0 True True True True True True True Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception micropython-1.12/tests/wipy/pin_irq.py000066400000000000000000000053611357706137100201740ustar00rootroot00000000000000''' Pin IRQ test for the CC3200 based boards. ''' from machine import Pin import machine import os import time mch = os.uname().machine if 'LaunchPad' in mch: pins = ['GP16', 'GP13'] elif 'WiPy' in mch: pins = ['GP16', 'GP13'] else: raise Exception('Board not supported!') pin0 = Pin(pins[0], mode=Pin.OUT, value=1) pin1 = Pin(pins[1], mode=Pin.IN, pull=Pin.PULL_UP) def pin_handler (pin_o): global pin_irq_count_trigger global pin_irq_count_total global _trigger if _trigger & pin1_irq.flags(): pin_irq_count_trigger += 1 pin_irq_count_total += 1 pin_irq_count_trigger = 0 pin_irq_count_total = 0 _trigger = Pin.IRQ_FALLING pin1_irq = pin1.irq(trigger=_trigger, handler=pin_handler) for i in range (0, 10): pin0.toggle() time.sleep_ms(5) print(pin_irq_count_trigger == 5) print(pin_irq_count_total == 5) pin_irq_count_trigger = 0 pin_irq_count_total = 0 _trigger = Pin.IRQ_RISING pin1_irq = pin1.irq(trigger=_trigger, handler=pin_handler) for i in range (0, 200): pin0.toggle() time.sleep_ms(5) print(pin_irq_count_trigger == 100) print(pin_irq_count_total == 100) pin1_irq.disable() pin0(1) pin_irq_count_trigger = 0 pin_irq_count_total = 0 _trigger = Pin.IRQ_FALLING pin1_irq.init(trigger=_trigger, handler=pin_handler) pin0(0) time.sleep_us(50) print(pin_irq_count_trigger == 1) print(pin_irq_count_total == 1) pin0(1) time.sleep_us(50) print(pin_irq_count_trigger == 1) print(pin_irq_count_total == 1) # check the call method pin1_irq() print(pin_irq_count_trigger == 1) # no flags since the irq was manually triggered print(pin_irq_count_total == 2) pin1_irq.disable() pin_irq_count_trigger = 0 pin_irq_count_total = 0 for i in range (0, 10): pin0.toggle() time.sleep_ms(5) print(pin_irq_count_trigger == 0) print(pin_irq_count_total == 0) # test waking up from suspended mode on low level pin0(0) t0 = time.ticks_ms() pin1_irq.init(trigger=Pin.IRQ_LOW_LEVEL, wake=machine.SLEEP) machine.sleep() print(time.ticks_ms() - t0 < 10) print('Awake') # test waking up from suspended mode on high level pin0(1) t0 = time.ticks_ms() pin1_irq.init(trigger=Pin.IRQ_HIGH_LEVEL, wake=machine.SLEEP) machine.sleep() print(time.ticks_ms() - t0 < 10) print('Awake') # check for memory leaks for i in range(0, 1000): pin0_irq = pin0.irq(trigger=_trigger, handler=pin_handler) pin1_irq = pin1.irq(trigger=_trigger, handler=pin_handler) # next ones must raise try: pin1_irq.init(trigger=123456, handler=pin_handler) except: print('Exception') try: pin1_irq.init(trigger=Pin.IRQ_LOW_LEVEL, wake=1789456) except: print('Exception') try: pin0_irq = pin0.irq(trigger=Pin.IRQ_RISING, wake=machine.SLEEP) # GP16 can't wake up from DEEPSLEEP except: print('Exception') pin0_irq.disable() pin1_irq.disable() micropython-1.12/tests/wipy/pin_irq.py.exp000066400000000000000000000001601357706137100207570ustar00rootroot00000000000000True True True True True True True True True True True True True Awake True Awake Exception Exception Exception micropython-1.12/tests/wipy/reset/000077500000000000000000000000001357706137100172765ustar00rootroot00000000000000micropython-1.12/tests/wipy/reset/reset.py000066400000000000000000000005261357706137100207750ustar00rootroot00000000000000''' Reset script for the cc3200 boards This is needed to force the board to reboot with the default WLAN AP settings ''' from machine import WDT import time import os mch = os.uname().machine if not 'LaunchPad' in mch and not 'WiPy' in mch: raise Exception('Board not supported!') wdt = WDT(timeout=1000) print(wdt) time.sleep_ms(900) micropython-1.12/tests/wipy/reset/reset.py.exp000066400000000000000000000000061357706137100215610ustar00rootroot00000000000000 micropython-1.12/tests/wipy/rtc.py000066400000000000000000000051141357706137100173170ustar00rootroot00000000000000''' RTC test for the CC3200 based boards. ''' from machine import RTC import os import time mch = os.uname().machine if not 'LaunchPad' in mch and not 'WiPy' in mch: raise Exception('Board not supported!') rtc = RTC() print(rtc) print(rtc.now()[:6]) rtc = RTC(datetime=(2015, 8, 29, 9, 0, 0, 0, None)) print(rtc.now()[:6]) rtc.deinit() print(rtc.now()[:6]) rtc.init((2015, 8, 29, 9, 0, 0, 0, None)) print(rtc.now()[:6]) seconds = rtc.now()[5] time.sleep_ms(1000) print(rtc.now()[5] - seconds == 1) seconds = rtc.now()[5] time.sleep_ms(2000) print(rtc.now()[5] - seconds == 2) # initialization with shorter tuples rtc.init((2015, 9, 19, 8, 0, 0, 0)) print(rtc.now()[5]) rtc.init((2015, 9, 19, 8, 0, 0)) print(rtc.now()[5]) rtc.init((2015, 9, 19, 8, 0)) print(rtc.now()[5]) rtc.init((2015, 9, 19, 8)) print(rtc.now()[4]) rtc.init((2015, 9, 19)) print(rtc.now()[3]) def set_and_print(datetime): rtc.init(datetime) print(rtc.now()[:6]) # make sure that setting works correctly set_and_print((2000, 1, 1, 0, 0, 0, 0, None)) set_and_print((2000, 1, 31, 0, 0, 0, 0, None)) set_and_print((2000, 12, 31, 0, 0, 0, 0, None)) set_and_print((2016, 12, 31, 0, 0, 0, 0, None)) set_and_print((2016, 12, 31, 0, 0, 0, 0, None)) set_and_print((2016, 12, 31, 1, 0, 0, 0, None)) set_and_print((2016, 12, 31, 12, 0, 0, 0, None)) set_and_print((2016, 12, 31, 13, 0, 0, 0, None)) set_and_print((2016, 12, 31, 23, 0, 0, 0, None)) set_and_print((2016, 12, 31, 23, 1, 0, 0, None)) set_and_print((2016, 12, 31, 23, 59, 0, 50, None)) set_and_print((2016, 12, 31, 23, 59, 1, 900, None)) set_and_print((2016, 12, 31, 23, 59, 59, 100, None)) set_and_print((2048, 12, 31, 23, 59, 59, 99999, None)) rtc.init((2015, 8, 29, 9, 0, 0, 0, None)) rtc.alarm(0, 5000) rtc.alarm(time=2000) time.sleep_ms(1000) left = rtc.alarm_left() print(abs(left-1000) <= 10) time.sleep_ms(1000) print(rtc.alarm_left() == 0) time.sleep_ms(100) print(rtc.alarm_left(0) == 0) rtc.alarm(time=1000, repeat=True) time.sleep_ms(1500) left = rtc.alarm_left() print(abs(left-500) <= 15) rtc.init((2015, 8, 29, 9, 0, 0, 0, None)) rtc.alarm(time=(2015, 8, 29, 9, 0, 45)) time.sleep_ms(1000) left = rtc.alarm_left() print(abs(left-44000) <= 90) rtc.alarm_cancel() rtc.deinit() # next ones must raise try: rtc.alarm(5000) except: print('Exception') try: rtc.alarm_left(1) except: print('Exception') try: rtc.alarm_cancel(1) except: print('Exception') try: rtc.alarm(5000) except: print('Exception') try: rtc = RTC(200000000) except: print('Exception') try: rtc = RTC((2015, 8, 29, 9, 0, 0, 0, None)) except: print('Exception') micropython-1.12/tests/wipy/rtc.py.exp000066400000000000000000000010441357706137100201100ustar00rootroot00000000000000 (2015, 1, 1, 0, 0, 0) (2015, 8, 29, 9, 0, 0) (2015, 1, 1, 0, 0, 0) (2015, 8, 29, 9, 0, 0) True True 0 0 0 0 0 (2000, 1, 1, 0, 0, 0) (2000, 1, 31, 0, 0, 0) (2000, 12, 31, 0, 0, 0) (2016, 12, 31, 0, 0, 0) (2016, 12, 31, 0, 0, 0) (2016, 12, 31, 1, 0, 0) (2016, 12, 31, 12, 0, 0) (2016, 12, 31, 13, 0, 0) (2016, 12, 31, 23, 0, 0) (2016, 12, 31, 23, 1, 0) (2016, 12, 31, 23, 59, 0) (2016, 12, 31, 23, 59, 1) (2016, 12, 31, 23, 59, 59) (2048, 12, 31, 23, 59, 59) True True True True True Exception Exception Exception Exception Exception Exception micropython-1.12/tests/wipy/sd.py000066400000000000000000000014231357706137100171340ustar00rootroot00000000000000''' SD card test for the CC3200 based boards. ''' from machine import SD import os mch = os.uname().machine if 'LaunchPad' in mch: sd_pins = ('GP16', 'GP17', 'GP15') elif 'WiPy' in mch: sd_pins = ('GP10', 'GP11', 'GP15') else: raise Exception('Board not supported!') sd = SD(pins=sd_pins) print(sd) sd.deinit() print(sd) sd.init(sd_pins) print(sd) sd = SD(0, pins=sd_pins) sd = SD(id=0, pins=sd_pins) sd = SD(0, sd_pins) # check for memory leaks for i in range(0, 1000): sd = sd = SD(0, pins=sd_pins) # next ones should raise try: sd = SD(pins=()) except Exception: print("Exception") try: sd = SD(pins=('GP10', 'GP11', 'GP8')) except Exception: print("Exception") try: sd = SD(pins=('GP10', 'GP11')) except Exception: print("Exception") micropython-1.12/tests/wipy/sd.py.exp000066400000000000000000000000551357706137100177270ustar00rootroot00000000000000 Exception Exception Exception micropython-1.12/tests/wipy/skipped/000077500000000000000000000000001357706137100176135ustar00rootroot00000000000000micropython-1.12/tests/wipy/skipped/rtc_irq.py000066400000000000000000000036731357706137100216410ustar00rootroot00000000000000''' RTC IRQ test for the CC3200 based boards. ''' from machine import RTC import machine import os import time mch = os.uname().machine if not 'LaunchPad' in mch and not 'WiPy' in mch: raise Exception('Board not supported!') def rtc_ticks_ms(rtc): timedate = rtc.now() return (timedate[5] * 1000) + (timedate[6] // 1000) rtc_irq_count = 0 def alarm_handler (rtc_o): global rtc_irq global rtc_irq_count if rtc_irq.flags() & RTC.ALARM0: rtc_irq_count += 1 rtc = RTC() rtc.alarm(time=500, repeat=True) rtc_irq = rtc.irq(trigger=RTC.ALARM0, handler=alarm_handler) # active mode time.sleep_ms(1000) rtc.alarm_cancel() print(rtc_irq_count == 2) rtc_irq_count = 0 rtc.alarm(time=200, repeat=True) time.sleep_ms(1000) rtc.alarm_cancel() print(rtc_irq_count == 5) rtc_irq_count = 0 rtc.alarm(time=100, repeat=True) time.sleep_ms(1000) rtc.alarm_cancel() print(rtc_irq_count == 10) # deep sleep mode rtc.alarm_cancel() rtc_irq_count = 0 rtc.alarm(time=50, repeat=True) rtc_irq.init(trigger=RTC.ALARM0, handler=alarm_handler, wake=machine.SLEEP | machine.IDLE) while rtc_irq_count < 3: machine.sleep() print(rtc_irq_count == 3) # no repetition rtc.alarm_cancel() rtc_irq_count = 0 rtc.alarm(time=100, repeat=False) time.sleep_ms(250) print(rtc_irq_count == 1) rtc.alarm_cancel() t0 = rtc_ticks_ms(rtc) rtc.alarm(time=500, repeat=False) machine.sleep() t1 = rtc_ticks_ms(rtc) print(abs(t1 - t0 - 500) < 20) # deep sleep repeated mode rtc.alarm_cancel() rtc_irq_count = 0 rtc.alarm(time=500, repeat=True) t0 = rtc_ticks_ms(rtc) rtc_irq = rtc.irq(trigger=RTC.ALARM0, handler=alarm_handler, wake=machine.SLEEP) while rtc_irq_count < 3: machine.sleep() t1 = rtc_ticks_ms(rtc) print(abs(t1 - t0 - (500 * rtc_irq_count)) < 25) # next ones must raise try: rtc_irq = rtc.irq(trigger=10, handler=alarm_handler) except: print('Exception') try: rtc_irq = rtc.irq(trigger=RTC.ALARM0, wake=1789456) except: print('Exception') micropython-1.12/tests/wipy/skipped/rtc_irq.py.exp000066400000000000000000000001011357706137100224130ustar00rootroot00000000000000True True True True True True True True True Exception Exception micropython-1.12/tests/wipy/spi.py000066400000000000000000000073701357706137100173300ustar00rootroot00000000000000''' SPI test for the CC3200 based boards. ''' from machine import SPI import os mch = os.uname().machine if 'LaunchPad' in mch: spi_pins = ('GP14', 'GP16', 'GP30') elif 'WiPy' in mch: spi_pins = ('GP14', 'GP16', 'GP30') else: raise Exception('Board not supported!') spi = SPI(0, SPI.MASTER, baudrate=2000000, polarity=0, phase=0, firstbit=SPI.MSB, pins=spi_pins) print(spi) spi = SPI(baudrate=5000000) print(spi) spi = SPI(0, SPI.MASTER, baudrate=200000, bits=16, polarity=0, phase=0) print(spi) spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=0, phase=1) print(spi) spi = SPI(0, SPI.MASTER, baudrate=5000000, bits=32, polarity=1, phase=0) print(spi) spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=1, phase=1) print(spi) spi.init(baudrate=20000000, polarity=0, phase=0) print(spi) spi=SPI() print(spi) SPI(mode=SPI.MASTER) SPI(mode=SPI.MASTER, pins=spi_pins) SPI(id=0, mode=SPI.MASTER, polarity=0, phase=0, pins=('GP14', 'GP16', 'GP15')) SPI(0, SPI.MASTER, polarity=0, phase=0, pins=('GP31', 'GP16', 'GP15')) spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=0, phase=0, pins=spi_pins) print(spi.write('123456') == 6) buffer_r = bytearray(10) print(spi.readinto(buffer_r) == 10) print(spi.readinto(buffer_r, write=0x55) == 10) read = spi.read(10) print(len(read) == 10) read = spi.read(10, write=0xFF) print(len(read) == 10) buffer_w = bytearray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) print(spi.write_readinto(buffer_w, buffer_r) == 10) print(buffer_w == buffer_r) # test all polaritiy and phase combinations spi.init(polarity=1, phase=0, pins=None) buffer_r = bytearray(10) spi.write_readinto(buffer_w, buffer_r) print(buffer_w == buffer_r) spi.init(polarity=1, phase=1, pins=None) buffer_r = bytearray(10) spi.write_readinto(buffer_w, buffer_r) print(buffer_w == buffer_r) spi.init(polarity=0, phase=1, pins=None) buffer_r = bytearray(10) spi.write_readinto(buffer_w, buffer_r) print(buffer_w == buffer_r) # test 16 and 32 bit transfers buffer_w = bytearray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2]) buffer_r = bytearray(12) spi.init(SPI.MASTER, baudrate=10000000, bits=16, polarity=0, phase=0, pins=None) print(spi.write_readinto(buffer_w, buffer_r) == 12) print(buffer_w == buffer_r) buffer_r = bytearray(12) spi.init(SPI.MASTER, baudrate=10000000, bits=32, polarity=0, phase=0, pins=None) print(spi.write_readinto(buffer_w, buffer_r) == 12) print(buffer_w == buffer_r) # check for memory leaks... for i in range (0, 1000): spi = SPI(0, SPI.MASTER, baudrate=1000000) # test deinit spi = SPI(0, SPI.MASTER, baudrate=1000000) spi.deinit() print(spi) spi = SPI(0, SPI.MASTER, baudrate=1000000) # next ones must fail try: spi = SPI(0, 10, baudrate=10000000, polarity=0, phase=0) except: print("Exception") try: spi = SPI(0, mode=SPI.MASTER, baudrate=10000000, polarity=1, phase=2) except: print("Exception") try: spi = SPI(1, mode=SPI.MASTER, baudrate=10000000, polarity=1, phase=1) except: print("Exception") try: spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0) except: print("Exception") try: spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0, firstbit=2) except: print("Exception") try: spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0, pins=('GP1', 'GP2')) except: print("Exception") try: spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=0, phase=0, bits=9) except: print("Exception") spi.deinit() try: spi.read(15) except Exception: print("Exception") try: spi.spi.readinto(buffer_r) except Exception: print("Exception") try: spi.spi.write('abc') except Exception: print("Exception") try: spi.write_readinto(buffer_w, buffer_r) except Exception: print("Exception") # reinitialization must work spi.init(baudrate=500000) print(spi) micropython-1.12/tests/wipy/spi.py.exp000066400000000000000000000016621357706137100201210ustar00rootroot00000000000000SPI(0, SPI.MASTER, baudrate=2000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB) SPI(0, SPI.MASTER, baudrate=5000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB) SPI(0, SPI.MASTER, baudrate=200000, bits=16, polarity=0, phase=0, firstbit=SPI.MSB) SPI(0, SPI.MASTER, baudrate=10000000, bits=8, polarity=0, phase=1, firstbit=SPI.MSB) SPI(0, SPI.MASTER, baudrate=5000000, bits=32, polarity=1, phase=0, firstbit=SPI.MSB) SPI(0, SPI.MASTER, baudrate=10000000, bits=8, polarity=1, phase=1, firstbit=SPI.MSB) SPI(0, SPI.MASTER, baudrate=20000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB) SPI(0, SPI.MASTER, baudrate=1000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB) True True True True True True True True True True True True True True SPI(0) Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception SPI(0, SPI.MASTER, baudrate=500000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB) micropython-1.12/tests/wipy/time.py000066400000000000000000000055711357706137100174740ustar00rootroot00000000000000import time DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] def is_leap(year): return (year % 4) == 0 def test(): seconds = 0 wday = 5 # Jan 1, 2000 was a Saturday for year in range(2000, 2049): print("Testing %d" % year) yday = 1 for month in range(1, 13): if month == 2 and is_leap(year): DAYS_PER_MONTH[2] = 29 else: DAYS_PER_MONTH[2] = 28 for day in range(1, DAYS_PER_MONTH[month] + 1): secs = time.mktime((year, month, day, 0, 0, 0, 0, 0)) if secs != seconds: print("mktime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds)) tuple = time.localtime(seconds) secs = time.mktime(tuple) if secs != seconds: print("localtime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds)) return seconds += 86400 if yday != tuple[7]: print("locatime for %d-%02d-%02d got yday %d, expecting %d" % (year, month, day, tuple[7], yday)) return if wday != tuple[6]: print("locatime for %d-%02d-%02d got wday %d, expecting %d" % (year, month, day, tuple[6], wday)) return yday += 1 wday = (wday + 1) % 7 def spot_test(seconds, expected_time): actual_time = time.localtime(seconds) for i in range(len(actual_time)): if actual_time[i] != expected_time[i]: print("time.localtime(", seconds, ") returned", actual_time, "expecting", expected_time) return print("time.localtime(", seconds, ") returned", actual_time, "(pass)") test() spot_test( 0, (2000, 1, 1, 0, 0, 0, 5, 1)) spot_test( 1, (2000, 1, 1, 0, 0, 1, 5, 1)) spot_test( 59, (2000, 1, 1, 0, 0, 59, 5, 1)) spot_test( 60, (2000, 1, 1, 0, 1, 0, 5, 1)) spot_test( 3599, (2000, 1, 1, 0, 59, 59, 5, 1)) spot_test( 3600, (2000, 1, 1, 1, 0, 0, 5, 1)) spot_test( -1, (1999, 12, 31, 23, 59, 59, 4, 365)) spot_test( 447549467, (2014, 3, 7, 23, 17, 47, 4, 66)) spot_test( -940984933, (1970, 3, 7, 23, 17, 47, 5, 66)) spot_test(-1072915199, (1966, 1, 1, 0, 0, 1, 5, 1)) spot_test(-1072915200, (1966, 1, 1, 0, 0, 0, 5, 1)) spot_test(-1072915201, (1965, 12, 31, 23, 59, 59, 4, 365)) t1 = time.time() time.sleep(2) t2 = time.time() print(abs(time.ticks_diff(t1, t2) -2) <= 1) t1 = time.ticks_ms() time.sleep_ms(50) t2 = time.ticks_ms() print(abs(time.ticks_diff(t1, t2)- 50) <= 1) t1 = time.ticks_us() time.sleep_us(1000) t2 = time.ticks_us() print(time.ticks_diff(t1, t2) < 1500) print(time.ticks_diff(time.ticks_cpu(), time.ticks_cpu()) < 16384) micropython-1.12/tests/wipy/time.py.exp000066400000000000000000000027421357706137100202640ustar00rootroot00000000000000Testing 2000 Testing 2001 Testing 2002 Testing 2003 Testing 2004 Testing 2005 Testing 2006 Testing 2007 Testing 2008 Testing 2009 Testing 2010 Testing 2011 Testing 2012 Testing 2013 Testing 2014 Testing 2015 Testing 2016 Testing 2017 Testing 2018 Testing 2019 Testing 2020 Testing 2021 Testing 2022 Testing 2023 Testing 2024 Testing 2025 Testing 2026 Testing 2027 Testing 2028 Testing 2029 Testing 2030 Testing 2031 Testing 2032 Testing 2033 Testing 2034 Testing 2035 Testing 2036 Testing 2037 Testing 2038 Testing 2039 Testing 2040 Testing 2041 Testing 2042 Testing 2043 Testing 2044 Testing 2045 Testing 2046 Testing 2047 Testing 2048 time.localtime( 0 ) returned (2000, 1, 1, 0, 0, 0, 5, 1) (pass) time.localtime( 1 ) returned (2000, 1, 1, 0, 0, 1, 5, 1) (pass) time.localtime( 59 ) returned (2000, 1, 1, 0, 0, 59, 5, 1) (pass) time.localtime( 60 ) returned (2000, 1, 1, 0, 1, 0, 5, 1) (pass) time.localtime( 3599 ) returned (2000, 1, 1, 0, 59, 59, 5, 1) (pass) time.localtime( 3600 ) returned (2000, 1, 1, 1, 0, 0, 5, 1) (pass) time.localtime( -1 ) returned (1999, 12, 31, 23, 59, 59, 4, 365) (pass) time.localtime( 447549467 ) returned (2014, 3, 7, 23, 17, 47, 4, 66) (pass) time.localtime( -940984933 ) returned (1970, 3, 7, 23, 17, 47, 5, 66) (pass) time.localtime( -1072915199 ) returned (1966, 1, 1, 0, 0, 1, 5, 1) (pass) time.localtime( -1072915200 ) returned (1966, 1, 1, 0, 0, 0, 5, 1) (pass) time.localtime( -1072915201 ) returned (1965, 12, 31, 23, 59, 59, 4, 365) (pass) True True True True micropython-1.12/tests/wipy/timer.py000066400000000000000000000050351357706137100176510ustar00rootroot00000000000000''' Timer test for the CC3200 based boards. ''' from machine import Timer import os import time mch = os.uname().machine if 'LaunchPad' in mch: pwm_pin = ('GP24') elif 'WiPy' in mch: pwm_pin = ('GP24') else: raise Exception('Board not supported!') for i in range(4): tim = Timer(i, mode=Timer.PERIODIC) print(tim) ch = tim.channel(Timer.A, freq=5) print(ch) ch = tim.channel(Timer.B, freq=5) print(ch) tim = Timer(i, mode=Timer.ONE_SHOT) print(tim) ch = tim.channel(Timer.A, freq=50) print(ch) ch = tim.channel(Timer.B, freq=50) print(ch) tim = Timer(i, mode=Timer.PWM) print(tim) ch = tim.channel(Timer.A, freq=50000, duty_cycle=2000, polarity=Timer.POSITIVE) print(ch) ch = tim.channel(Timer.B, freq=50000, duty_cycle=8000, polarity=Timer.NEGATIVE) print(ch) tim.deinit() print(tim) for i in range(4): tim = Timer(i, mode=Timer.PERIODIC) tim.deinit() class TimerTest: def __init__(self): self.tim = Timer(0, mode=Timer.PERIODIC) self.int_count = 0 def timer_isr(self, tim_ch): self.int_count += 1 timer_test = TimerTest() ch = timer_test.tim.channel(Timer.A, freq=5) print(ch.freq() == 5) ch.irq(handler=timer_test.timer_isr, trigger=Timer.TIMEOUT) time.sleep_ms(1001) print(timer_test.int_count == 5) ch.freq(100) timer_test.int_count = 0 time.sleep_ms(1001) print(timer_test.int_count == 100) ch.freq(1000) time.sleep_ms(1500) timer_test.int_count = 0 time.sleep_ms(2000) print(timer_test.int_count == 2000) timer_test.tim.deinit() timer_test.tim.init(mode=Timer.ONE_SHOT) ch = timer_test.tim.channel(Timer.A, period=100000) ch.irq(handler=timer_test.timer_isr, trigger=Timer.TIMEOUT) timer_test.int_count = 0 time.sleep_ms(101) print(timer_test.int_count == 1) time.sleep_ms(101) print(timer_test.int_count == 1) timer_test.tim.deinit() print(timer_test.tim) # 32 bit modes tim = Timer(0, mode=Timer.PERIODIC, width=32) ch = tim.channel(Timer.A | Timer.B, period=5000000) # check for memory leaks... for i in range(1000): tim = Timer(0, mode=Timer.PERIODIC) ch = tim.channel(Timer.A, freq=5) # next ones must fail try: tim = Timer(0, mode=12) except: print('Exception') try: tim = Timer(4, mode=Timer.ONE_SHOT) except: print('Exception') try: tim = Timer(0, mode=Timer.PWM, width=32) except: print('Exception') tim = Timer(0, mode=Timer.PWM) try: ch = tim.channel(TIMER_A | TIMER_B, freq=10) except: print('Exception') try: ch = tim.channel(TIMER_A, freq=4) except: print('Exception') micropython-1.12/tests/wipy/timer.py.exp000066400000000000000000000032161357706137100204430ustar00rootroot00000000000000Timer(0, mode=Timer.PERIODIC) timer.channel(Timer.A, freq=5) timer.channel(Timer.B, freq=5) Timer(0, mode=Timer.ONE_SHOT) timer.channel(Timer.A, freq=50) timer.channel(Timer.B, freq=50) Timer(0, mode=Timer.PWM) timer.channel(Timer.A, freq=50000, polarity=Timer.POSITIVE, duty_cycle=20.00) timer.channel(Timer.B, freq=50000, polarity=Timer.NEGATIVE, duty_cycle=80.00) Timer(0, mode=Timer.PWM) Timer(1, mode=Timer.PERIODIC) timer.channel(Timer.A, freq=5) timer.channel(Timer.B, freq=5) Timer(1, mode=Timer.ONE_SHOT) timer.channel(Timer.A, freq=50) timer.channel(Timer.B, freq=50) Timer(1, mode=Timer.PWM) timer.channel(Timer.A, freq=50000, polarity=Timer.POSITIVE, duty_cycle=20.00) timer.channel(Timer.B, freq=50000, polarity=Timer.NEGATIVE, duty_cycle=80.00) Timer(1, mode=Timer.PWM) Timer(2, mode=Timer.PERIODIC) timer.channel(Timer.A, freq=5) timer.channel(Timer.B, freq=5) Timer(2, mode=Timer.ONE_SHOT) timer.channel(Timer.A, freq=50) timer.channel(Timer.B, freq=50) Timer(2, mode=Timer.PWM) timer.channel(Timer.A, freq=50000, polarity=Timer.POSITIVE, duty_cycle=20.00) timer.channel(Timer.B, freq=50000, polarity=Timer.NEGATIVE, duty_cycle=80.00) Timer(2, mode=Timer.PWM) Timer(3, mode=Timer.PERIODIC) timer.channel(Timer.A, freq=5) timer.channel(Timer.B, freq=5) Timer(3, mode=Timer.ONE_SHOT) timer.channel(Timer.A, freq=50) timer.channel(Timer.B, freq=50) Timer(3, mode=Timer.PWM) timer.channel(Timer.A, freq=50000, polarity=Timer.POSITIVE, duty_cycle=20.00) timer.channel(Timer.B, freq=50000, polarity=Timer.NEGATIVE, duty_cycle=80.00) Timer(3, mode=Timer.PWM) True True True True True True Timer(0, mode=Timer.ONE_SHOT) Exception Exception Exception Exception Exception micropython-1.12/tests/wipy/uart.py000066400000000000000000000075561357706137100175160ustar00rootroot00000000000000''' UART test for the CC3200 based boards. UART0 and UART1 must be connected together for this test to pass. ''' from machine import UART from machine import Pin import os import time mch = os.uname().machine if 'LaunchPad' in mch: uart_id_range = range(0, 2) uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]] elif 'WiPy' in mch: uart_id_range = range(0, 2) uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]] else: raise Exception('Board not supported!') # just in case we have the repl duplicated on any of the uarts os.dupterm(None) for uart_id in uart_id_range: uart = UART(uart_id, 38400) print(uart) uart.init(57600, 8, None, 1, pins=uart_pins[uart_id][0]) uart.init(baudrate=9600, stop=2, parity=UART.EVEN, pins=uart_pins[uart_id][1]) uart.init(baudrate=115200, parity=UART.ODD, stop=0, pins=uart_pins[uart_id][0]) uart = UART(baudrate=1000000) uart.sendbreak() uart = UART(baudrate=1000000) uart = UART() print(uart) uart = UART(baudrate=38400, pins=('GP12', 'GP13')) print(uart) uart = UART(pins=('GP12', 'GP13')) print(uart) uart = UART(pins=(None, 'GP17')) print(uart) uart = UART(baudrate=57600, pins=('GP16', 'GP17')) print(uart) # now it's time for some loopback tests between the uarts uart0 = UART(0, 1000000, pins=uart_pins[0][0]) print(uart0) uart1 = UART(1, 1000000, pins=uart_pins[1][0]) print(uart1) print(uart0.write(b'123456') == 6) print(uart1.read() == b'123456') print(uart1.write(b'123') == 3) print(uart0.read(1) == b'1') print(uart0.read(2) == b'23') print(uart0.read() == None) uart0.write(b'123') buf = bytearray(3) print(uart1.readinto(buf, 1) == 1) print(buf) print(uart1.readinto(buf) == 2) print(buf) # try initializing without the id uart0 = UART(baudrate=1000000, pins=uart_pins[0][0]) uart0.write(b'1234567890') time.sleep_ms(2) # because of the fifo interrupt levels print(uart1.any() == 10) print(uart1.readline() == b'1234567890') print(uart1.any() == 0) uart0.write(b'1234567890') print(uart1.read() == b'1234567890') # tx only mode uart0 = UART(0, 1000000, pins=('GP12', None)) print(uart0.write(b'123456') == 6) print(uart1.read() == b'123456') print(uart1.write(b'123') == 3) print(uart0.read() == None) # rx only mode uart0 = UART(0, 1000000, pins=(None, 'GP13')) print(uart0.write(b'123456') == 6) print(uart1.read() == None) print(uart1.write(b'123') == 3) print(uart0.read() == b'123') # leave pins as they were (rx only mode) uart0 = UART(0, 1000000, pins=None) print(uart0.write(b'123456') == 6) print(uart1.read() == None) print(uart1.write(b'123') == 3) print(uart0.read() == b'123') # no pin assignment uart0 = UART(0, 1000000, pins=(None, None)) print(uart0.write(b'123456789') == 9) print(uart1.read() == None) print(uart1.write(b'123456789') == 9) print(uart0.read() == None) print(Pin.board.GP12) print(Pin.board.GP13) # check for memory leaks... for i in range (0, 1000): uart0 = UART(0, 1000000) uart1 = UART(1, 1000000) # next ones must raise try: UART(0, 9600, parity=None, pins=('GP12', 'GP13', 'GP7')) except Exception: print('Exception') try: UART(0, 9600, parity=UART.ODD, pins=('GP12', 'GP7')) except Exception: print('Exception') uart0 = UART(0, 1000000) uart0.deinit() try: uart0.any() except Exception: print('Exception') try: uart0.read() except Exception: print('Exception') try: uart0.write('abc') except Exception: print('Exception') try: uart0.sendbreak('abc') except Exception: print('Exception') try: UART(2, 9600) except Exception: print('Exception') for uart_id in uart_id_range: uart = UART(uart_id, 1000000) uart.deinit() # test printing an unitialized uart print(uart) # initialize it back and check that it works again uart.init(115200) print(uart) uart.read() micropython-1.12/tests/wipy/uart.py.exp000066400000000000000000000017331357706137100203000ustar00rootroot00000000000000UART(0, baudrate=38400, bits=8, parity=None, stop=1) UART(1, baudrate=38400, bits=8, parity=None, stop=1) UART(0, baudrate=9600, bits=8, parity=None, stop=1) UART(0, baudrate=38400, bits=8, parity=None, stop=1) UART(0, baudrate=9600, bits=8, parity=None, stop=1) UART(1, baudrate=9600, bits=8, parity=None, stop=1) UART(1, baudrate=57600, bits=8, parity=None, stop=1) UART(0, baudrate=1000000, bits=8, parity=None, stop=1) UART(1, baudrate=1000000, bits=8, parity=None, stop=1) True True True True True True True bytearray(b'1\x00\x00') True bytearray(b'23\x00') True True True True True True True True True True True True True True True True True True True True Pin('GP12', mode=Pin.IN, pull=None, drive=Pin.MED_POWER, alt=-1) Pin('GP13', mode=Pin.IN, pull=None, drive=Pin.MED_POWER, alt=-1) Exception Exception Exception Exception Exception Exception Exception UART(0) UART(0, baudrate=115200, bits=8, parity=None, stop=1) UART(1) UART(1, baudrate=115200, bits=8, parity=None, stop=1) micropython-1.12/tests/wipy/uart_irq.py000066400000000000000000000067031357706137100203620ustar00rootroot00000000000000''' UART IRQ test for the CC3200 based boards. ''' from machine import UART import os import time mch = os.uname().machine if 'LaunchPad' in mch: uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]] elif 'WiPy' in mch: uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]] else: raise Exception('Board not supported!') # just in case we have stdio duplicated on any of the uarts os.dupterm(None) uart0 = UART(0, 1000000, pins=uart_pins[0][0]) uart1 = UART(1, 1000000, pins=uart_pins[1][0]) uart0_int_count = 0 uart1_int_count = 0 def uart0_handler (uart_o): global uart0_irq global uart0_int_count if (uart0_irq.flags() & UART.RX_ANY): uart0_int_count += 1 def uart1_handler (uart_o): global uart1_irq global uart1_int_count if (uart1_irq.flags() & UART.RX_ANY): uart1_int_count += 1 uart0_irq = uart0.irq(trigger=UART.RX_ANY, handler=uart0_handler) uart1_irq = uart1.irq(trigger=UART.RX_ANY, handler=uart1_handler) uart0.write(b'123') # wait for the characters to be received while not uart1.any(): pass time.sleep_us(100) print(uart1.any() == 3) print(uart1_int_count > 0) print(uart1_irq.flags() == 0) print(uart0_irq.flags() == 0) print(uart1.read() == b'123') uart1.write(b'12345') # wait for the characters to be received while not uart0.any(): pass time.sleep_us(100) print(uart0.any() == 5) print(uart0_int_count > 0) print(uart0_irq.flags() == 0) print(uart1_irq.flags() == 0) print(uart0.read() == b'12345') # do it again uart1_int_count = 0 uart0.write(b'123') # wait for the characters to be received while not uart1.any(): pass time.sleep_us(100) print(uart1.any() == 3) print(uart1_int_count > 0) print(uart1_irq.flags() == 0) print(uart0_irq.flags() == 0) print(uart1.read() == b'123') # disable the interrupt uart1_irq.disable() # do it again uart1_int_count = 0 uart0.write(b'123') # wait for the characters to be received while not uart1.any(): pass time.sleep_us(100) print(uart1.any() == 3) print(uart1_int_count == 0) # no interrupt triggered this time print(uart1_irq.flags() == 0) print(uart0_irq.flags() == 0) print(uart1.read() == b'123') # enable the interrupt uart1_irq.enable() # do it again uart1_int_count = 0 uart0.write(b'123') # wait for the characters to be received while not uart1.any(): pass time.sleep_us(100) print(uart1.any() == 3) print(uart1_int_count > 0) print(uart1_irq.flags() == 0) print(uart0_irq.flags() == 0) print(uart1.read() == b'123') uart1_irq.init(trigger=UART.RX_ANY, handler=None) # No handler # do it again uart1_int_count = 0 uart0.write(b'123') # wait for the characters to be received while not uart1.any(): pass time.sleep_us(100) print(uart1.any() == 3) print(uart1_int_count == 0) # no interrupt handler called print(uart1_irq.flags() == 0) print(uart0_irq.flags() == 0) print(uart1.read() == b'123') # check for memory leaks for i in range(0, 1000): uart0_irq = uart0.irq(trigger=UART.RX_ANY, handler=uart0_handler) uart1_irq = uart1.irq(trigger=UART.RX_ANY, handler=uart1_handler) # next ones must raise try: uart0_irq = uart0.irq(trigger=100, handler=uart0_handler) except: print('Exception') try: uart0_irq = uart0.irq(trigger=0) except: print('Exception') try: uart0_irq = uart0.irq(trigger=UART.RX_ANY, wake=Sleep.SUSPENDED) except: print('Exception') uart0_irq.disable() uart1_irq.disable() micropython-1.12/tests/wipy/uart_irq.py.exp000066400000000000000000000002641357706137100211510ustar00rootroot00000000000000True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True Exception Exception Exception micropython-1.12/tests/wipy/wdt.py000066400000000000000000000010341357706137100173220ustar00rootroot00000000000000''' WDT test for the CC3200 based boards ''' from machine import WDT import time # test the invalid cases first try: wdt = WDT(1) except Exception: print("Exception") try: wdt = WDT(0, 500) except Exception: print("Exception") try: wdt = WDT(1, timeout=2000) except Exception: print("Exception") wdt = WDT(timeout=1000) print(wdt) try: wdt = WDT(0, timeout=2000) except Exception: print("Exception") time.sleep_ms(500) wdt.feed() print(wdt) time.sleep_ms(900) wdt.feed() print(wdt) time.sleep_ms(950) micropython-1.12/tests/wipy/wdt.py.exp000066400000000000000000000000721357706137100201160ustar00rootroot00000000000000Exception Exception Exception Exception micropython-1.12/tests/wipy/wlan/000077500000000000000000000000001357706137100171155ustar00rootroot00000000000000micropython-1.12/tests/wipy/wlan/machine.py000066400000000000000000000013521357706137100210740ustar00rootroot00000000000000''' machine test for the CC3200 based boards. ''' import machine import os from network import WLAN mch = os.uname().machine if not 'LaunchPad' in mch and not'WiPy' in mch: raise Exception('Board not supported!') wifi = WLAN() print(machine) machine.idle() print(machine.freq() == (80000000,)) print(machine.unique_id() == wifi.mac()) machine.main('main.py') rand_nums = [] for i in range(0, 100): rand = machine.rng() if rand not in rand_nums: rand_nums.append(rand) else: print('RNG number repeated') break for i in range(0, 10): machine.idle() print("Active") print(machine.reset_cause() >= 0) print(machine.wake_reason() >= 0) try: machine.main(123456) except: print('Exception') micropython-1.12/tests/wipy/wlan/machine.py.exp000066400000000000000000000000711357706137100216640ustar00rootroot00000000000000 True True Active True True Exception micropython-1.12/tests/wipy/wlan/server.py000066400000000000000000000014421357706137100207760ustar00rootroot00000000000000''' network server test for the CC3200 based boards. ''' import os import network mch = os.uname().machine if not 'LaunchPad' in mch and not'WiPy' in mch: raise Exception('Board not supported!') server = network.Server() print(server.timeout() == 300) print(server.isrunning() == True) server.deinit() print(server.isrunning() == False) server.init(login=('test-user', 'test-password'), timeout=60) print(server.isrunning() == True) print(server.timeout() == 60) server.deinit() print(server.isrunning() == False) server.init() print(server.isrunning() == True) try: server.init(1) except: print('Exception') try: server.init(0, login=('0000000000011111111111222222222222333333', 'abc')) except: print('Exception') try: server.timeout(1) except: print('Exception') micropython-1.12/tests/wipy/wlan/server.py.exp000066400000000000000000000001011357706137100215600ustar00rootroot00000000000000True True True True True True True Exception Exception Exception micropython-1.12/tests/wipy/wlan/wlan.py000066400000000000000000000100241357706137100204250ustar00rootroot00000000000000''' WLAN test for the CC3200 based boards. ''' from network import WLAN import os import time import testconfig mch = os.uname().machine if not 'LaunchPad' in mch and not 'WiPy' in mch: raise Exception('Board not supported!') def wait_for_connection(wifi, timeout=10): while not wifi.isconnected() and timeout > 0: time.sleep(1) timeout -= 1 if wifi.isconnected(): print('Connected') else: print('Connection failed!') wifi = WLAN(0, WLAN.STA) print(wifi.mode() == WLAN.STA) print(wifi.antenna() == WLAN.INT_ANT) wifi = WLAN(mode=WLAN.AP) print(wifi.mode() == WLAN.AP) print(wifi.channel() == 1) print(wifi.auth() == None) print(wifi.antenna() == WLAN.INT_ANT) wifi = WLAN(0, mode=WLAN.AP, ssid='test-wlan', auth=(WLAN.WPA, '123456abc'), channel=7) print(wifi.mode() == WLAN.AP) print(wifi.channel() == 7) print(wifi.ssid() == 'test-wlan') print(wifi.auth() == (WLAN.WPA, '123456abc')) print(wifi.antenna() == WLAN.INT_ANT) wifi = WLAN(mode=WLAN.STA) print(wifi.mode() == WLAN.STA) time.sleep(5) # this ensures a full network scan scan_r = wifi.scan() print(len(scan_r) > 3) for net in scan_r: if net.ssid == testconfig.wlan_ssid: # test that the scan results contains the desired params print(len(net.bssid) == 6) print(net.channel == None) print(net.sec == testconfig.wlan_auth[0]) print(net.rssi < 0) print('Network found') break wifi.mode(WLAN.STA) print(wifi.mode() == WLAN.STA) wifi.channel(7) print(wifi.channel() == 7) wifi.ssid('t-wlan') print(wifi.ssid() == 't-wlan') wifi.auth(None) print(wifi.auth() == None) wifi.auth((WLAN.WEP, '11223344556677889900')) print(wifi.auth() == (WLAN.WEP, '11223344556677889900')) wifi.antenna(WLAN.INT_ANT) print(wifi.antenna() == WLAN.INT_ANT) wifi.antenna(WLAN.EXT_ANT) print(wifi.antenna() == WLAN.EXT_ANT) time.sleep(2) # this ensures a full network scan scan_r = wifi.scan() print(len(scan_r) > 3) for net in scan_r: if net.ssid == testconfig.wlan_ssid: print('Network found') break wifi.antenna(WLAN.INT_ANT) wifi.mode(WLAN.STA) print(wifi.mode() == WLAN.STA) wifi.connect(testconfig.wlan_ssid, auth=testconfig.wlan_auth, timeout=10000) wait_for_connection(wifi) wifi.ifconfig(config='dhcp') wait_for_connection(wifi) print('0.0.0.0' not in wifi.ifconfig()) wifi.ifconfig(0, ('192.168.178.109', '255.255.255.0', '192.168.178.1', '8.8.8.8')) wait_for_connection(wifi) print(wifi.ifconfig(0) == ('192.168.178.109', '255.255.255.0', '192.168.178.1', '8.8.8.8')) wait_for_connection(wifi) print(wifi.isconnected() == True) wifi.disconnect() print(wifi.isconnected() == False) t0 = time.ticks_ms() wifi.connect(testconfig.wlan_ssid, auth=testconfig.wlan_auth, timeout=0) print(time.ticks_ms() - t0 < 500) wifi.disconnect() print(wifi.isconnected() == False) # test init again wifi.init(WLAN.AP, ssid='www.wipy.io', auth=None, channel=5, antenna=WLAN.INT_ANT) print(wifi.mode() == WLAN.AP) # get the current instance without re-init wifi = WLAN() print(wifi.mode() == WLAN.AP) wifi = WLAN(0) print(wifi.mode() == WLAN.AP) # test the MAC address length print(len(wifi.mac()) == 6) # next ones MUST raise try: wifi.init(mode=12345) except: print('Exception') try: wifi.init(1, mode=WLAN.AP) except: print('Exception') try: wifi.init(mode=WLAN.AP, ssid=None) except: print('Exception') try: wifi = WLAN(mode=WLAN.AP, channel=12) except: print('Exception') try: wifi.antenna(2) except: print('Exception') try: wifi.mode(10) except: print('Exception') try: wifi.ssid('11111sdfasdfasdfasdf564sdf654asdfasdf123451245ssdgfsdf1111111111111111111111111234123412341234asdfasdf') except: print('Exception') try: wifi.auth((0)) except: print('Exception') try: wifi.auth((0, None)) except: print('Exception') try: wifi.auth((10, 10)) except: print('Exception') try: wifi.channel(0) except: print('Exception') try: wifi.ifconfig(1, 'dhcp') except: print('Exception') try: wifi.ifconfig(config=()) except: print('Exception') micropython-1.12/tests/wipy/wlan/wlan.py.exp000066400000000000000000000005721357706137100212270ustar00rootroot00000000000000True True True True True True True True True True True True True True True True True Network found True True True True True True True True Network found True Connected Connected True Connected True Connected True True True True True True True True Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception Exception micropython-1.12/tools/000077500000000000000000000000001357706137100151625ustar00rootroot00000000000000micropython-1.12/tools/.gitattributes000066400000000000000000000000201357706137100200450ustar00rootroot00000000000000*.tar.gz binary micropython-1.12/tools/.gitignore000066400000000000000000000002661357706137100171560ustar00rootroot00000000000000tinytest/.gitignore tinytest/.travis.yml tinytest/Makefile tinytest/Makefile.arm-cortex-m3-qemu tinytest/Makefile.avr tinytest/TODO tinytest/portable_demo.c tinytest/tinytest_demo.c micropython-1.12/tools/bootstrap_upip.sh000077500000000000000000000011721357706137100205740ustar00rootroot00000000000000# This script performs bootstrap installation of upip package manager from PyPI # All the other packages can be installed using it. saved="$PWD" if [ "$1" = "" ]; then dest=~/.micropython/lib/ else dest="$1" fi if [ -z "$TMPDIR" ]; then cd /tmp else cd $TMPDIR fi # Remove any stale old version rm -rf micropython-upip-* wget -nd -rH -l1 -D files.pythonhosted.org https://pypi.org/project/micropython-upip/ --reject=html tar xfz micropython-upip-*.tar.gz tmpd="$PWD" cd "$saved" mkdir -p "$dest" cp "$tmpd"/micropython-upip-*/upip*.py "$dest" echo "upip is installed. To use:" echo "micropython -m upip --help" micropython-1.12/tools/build-stm-latest.sh000077500000000000000000000016521357706137100207170ustar00rootroot00000000000000#!/bin/bash # function for building firmware function do_build() { descr=$1 board=$2 shift shift echo "building $descr $board" build_dir=/tmp/stm-build-$board make -B $@ BOARD=$board BUILD=$build_dir || exit 1 mv $build_dir/firmware.dfu $dest_dir/$descr-$date-$git_tag.dfu rm -rf $build_dir } # check/get parameters if [ $# != 1 ]; then echo "usage: $0 " exit 1 fi dest_dir=$1 # check we are in the correct directory if [ ! -r modpyb.c ]; then echo "must be in stm directory" exit 1 fi # get the date date=$(date '+%Y-%m-%d') # get the git tag git_tag="$(git describe --dirty || echo unknown)" # build the versions do_build pybv3 PYBV3 do_build pybv3-network PYBV3 MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1 do_build pybv10 PYBV10 do_build pybv10-network PYBV10 MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1 do_build stm32f4disc STM32F4DISC do_build espruino-pico ESPRUINO_PICO micropython-1.12/tools/cc1000077500000000000000000000207331357706137100155630ustar00rootroot00000000000000#!/usr/bin/env python3 """ This is a middle-processor for MicroPython source files. It takes the output of the C preprocessor, has the option to change it, then feeds this into the C compiler. It currently has the ability to reorder static hash tables so they are actually hashed, resulting in faster lookup times at runtime. To use, configure the Python variables below, and add the following line to the Makefile: CFLAGS += -no-integrated-cpp -B$(shell pwd)/../tools """ import sys import os import re ################################################################################ # these are the configuration variables # TODO somehow make them externally configurable # this is the path to the true C compiler cc1_path = '/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/cc1' #cc1_path = '/usr/lib/gcc/arm-none-eabi/5.3.0/cc1' # this must be the same as MICROPY_QSTR_BYTES_IN_HASH bytes_in_qstr_hash = 2 # this must be 1 or more (can be a decimal) # larger uses more code size but yields faster lookups table_size_mult = 1 # these control output during processing print_stats = True print_debug = False # end configuration variables ################################################################################ # precompile regexs re_preproc_line = re.compile(r'# [0-9]+ ') re_map_entry = re.compile(r'\{.+?\(MP_QSTR_([A-Za-z0-9_]+)\).+\},') re_mp_obj_dict_t = re.compile(r'(?P(static )?const mp_obj_dict_t (?P[a-z0-9_]+) = \{ \.base = \{&mp_type_dict\}, \.map = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$') re_mp_map_t = re.compile(r'(?P(static )?const mp_map_t (?P[a-z0-9_]+) = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$') re_mp_rom_map_elem_t = re.compile(r'static const mp_rom_map_elem_t [a-z_0-9]+\[\] = {$') # this must match the equivalent function in qstr.c def compute_hash(qstr): hash = 5381 for char in qstr: hash = (hash * 33) ^ ord(char) # Make sure that valid hash is never zero, zero means "hash not computed" return (hash & ((1 << (8 * bytes_in_qstr_hash)) - 1)) or 1 # this algo must match the equivalent in map.c def hash_insert(map, key, value): hash = compute_hash(key) pos = hash % len(map) start_pos = pos if print_debug: print(' insert %s: start at %u/%u -- ' % (key, pos, len(map)), end='') while True: if map[pos] is None: # found empty slot, so key is not in table if print_debug: print('put at %u' % pos) map[pos] = (key, value) return else: # not yet found, keep searching if map[pos][0] == key: raise AssertionError("duplicate key '%s'" % (key,)) pos = (pos + 1) % len(map) assert pos != start_pos def hash_find(map, key): hash = compute_hash(key) pos = hash % len(map) start_pos = pos attempts = 0 while True: attempts += 1 if map[pos] is None: return attempts, None elif map[pos][0] == key: return attempts, map[pos][1] else: pos = (pos + 1) % len(map) if pos == start_pos: return attempts, None def process_map_table(file, line, output): output.append(line) # consume all lines that are entries of the table and concat them # (we do it this way because there can be multiple entries on one line) table_contents = [] while True: line = file.readline() if len(line) == 0: print('unexpected end of input') sys.exit(1) line = line.strip() if len(line) == 0: # empty line continue if re_preproc_line.match(line): # preprocessor line number comment continue if line == '};': # end of table (we assume it appears on a single line) break table_contents.append(line) # make combined string of entries entries_str = ''.join(table_contents) # split into individual entries entries = [] while entries_str: # look for single entry, by matching nested braces match = None if entries_str[0] == '{': nested_braces = 0 for i in range(len(entries_str)): if entries_str[i] == '{': nested_braces += 1 elif entries_str[i] == '}': nested_braces -= 1 if nested_braces == 0: match = re_map_entry.match(entries_str[:i + 2]) break if not match: print('unknown line in table:', entries_str) sys.exit(1) # extract single entry line = match.group(0) qstr = match.group(1) entries_str = entries_str[len(line):].lstrip() # add the qstr and the whole line to list of all entries entries.append((qstr, line)) # sort entries so hash table construction is deterministic entries.sort() # create hash table map = [None] * int(len(entries) * table_size_mult) for qstr, line in entries: # We assume that qstr does not have any escape sequences in it. # This is reasonably safe, since keys in a module or class dict # should be standard identifiers. # TODO verify this and raise an error if escape sequence found hash_insert(map, qstr, line) # compute statistics total_attempts = 0 for qstr, _ in entries: attempts, line = hash_find(map, qstr) assert line is not None if print_debug: print(' %s lookup took %u attempts' % (qstr, attempts)) total_attempts += attempts if len(entries): stats = len(map), len(entries) / len(map), total_attempts / len(entries) else: stats = 0, 0, 0 if print_debug: print(' table stats: size=%d, load=%.2f, avg_lookups=%.1f' % stats) # output hash table for row in map: if row is None: output.append('{ 0, 0 },\n') else: output.append(row[1] + '\n') output.append('};\n') # skip to next non-blank line while True: line = file.readline() if len(line) == 0: print('unexpected end of input') sys.exit(1) line = line.strip() if len(line) == 0: continue break # transform the is_ordered param from 1 to 0 match = re_mp_obj_dict_t.match(line) if match is None: match = re_mp_map_t.match(line) if match is None: print('expecting mp_obj_dict_t or mp_map_t definition') print(output[0]) print(line) sys.exit(1) line = match.group('head') + '0' + match.group('tail') + '\n' output.append(line) return (match.group('id'),) + stats def process_file(filename): output = [] file_changed = False with open(filename, 'rt') as f: while True: line = f.readline() if not line: break if re_mp_rom_map_elem_t.match(line): file_changed = True stats = process_map_table(f, line, output) if print_stats: print(' [%s: size=%d, load=%.2f, avg_lookups=%.1f]' % stats) else: output.append(line) if file_changed: if print_debug: print(' modifying static maps in', output[0].strip()) with open(filename, 'wt') as f: for line in output: f.write(line) def main(): # run actual C compiler # need to quote args that have special characters in them def quote(s): if s.find('<') != -1 or s.find('>') != -1: return "'" + s + "'" else: return s ret = os.system(cc1_path + ' ' + ' '.join(quote(s) for s in sys.argv[1:])) if ret != 0: ret = (ret & 0x7f) or 127 # make it in range 0-127, but non-zero sys.exit(ret) if sys.argv[1] == '-E': # CPP has been run, now do our processing stage for i, arg in enumerate(sys.argv): if arg == '-o': return process_file(sys.argv[i + 1]) print('%s: could not find "-o" option' % (sys.argv[0],)) sys.exit(1) elif sys.argv[1] == '-fpreprocessed': # compiler has been run, nothing more to do return else: # unknown processing stage print('%s: unknown first option "%s"' % (sys.argv[0], sys.argv[1])) sys.exit(1) if __name__ == '__main__': main() micropython-1.12/tools/check_code_size.sh000077500000000000000000000012711357706137100206230ustar00rootroot00000000000000#!/bin/bash # # This script check that changes don't lead to code size regressions. # (Size of the language core (== minimal port should not grow)). # REFERENCE=$HOME/persist/firmware.bin #REFERENCE=/tmp/micropython #TRAVIS_PULL_REQUEST=false if [ -f $REFERENCE ]; then size_old=$(stat -c%s $REFERENCE) size_new=$(stat -c%s ports/minimal/build/firmware.bin) echo "Old size: $size_old new size: $size_new" if [ $size_new -gt $size_old ]; then echo "Validation failure: Core code size increased" if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then exit 1 fi fi else echo "Warning: reference file doesn't exist, code size check didn't run" fi micropython-1.12/tools/codestats.sh000077500000000000000000000122701357706137100175140ustar00rootroot00000000000000#!/bin/sh # # This script generates statistics (build size, speed) for successive # revisions of the code. It checks out git commits one an a time, compiles # various ports to determine their size, and runs pystone on the unix port. # Results are collected in the output file. # # Note: you will need to copy this file out of the tools directory before # executing because it does not exist in old revisions of the repository. # check that we are in the root directory of the repository if [ ! -d py -o ! -d ports/unix -o ! -d ports/stm32 ]; then echo "script must be run from root of the repository" exit 1 fi # output file for the data; data is appended if file already exists output=codestats.dat # utility programs RM=/bin/rm AWK=awk MAKE="make -j2" # these are the binaries that are built; some have 2 or 3 depending on version bin_unix=ports/unix/micropython bin_stm32=ports/stm32/build-PYBV10/firmware.elf bin_barearm_1=ports/bare-arm/build/flash.elf bin_barearm_2=ports/bare-arm/build/firmware.elf bin_minimal=ports/minimal/build/firmware.elf bin_cc3200_1=ports/cc3200/build/LAUNCHXL/application.axf bin_cc3200_2=ports/cc3200/build/LAUNCHXL/release/application.axf bin_cc3200_3=ports/cc3200/build/WIPY/release/application.axf # start at zero size; if build fails reuse previous valid size size_unix="0" size_stm32="0" size_barearm="0" size_minimal="0" size_cc3200="0" # start at zero pystones pystones="0" # this code runs pystone and averages the results pystoneavg=/tmp/pystoneavg.py cat > $pystoneavg << EOF import pystone samples = [pystone.pystones(300000)[1] for i in range(5)] samples.sort() stones = sum(samples[1:-1]) / (len(samples) - 2) # exclude smallest and largest print("stones %g" % stones) EOF function get_size() { if [ -r $2 ]; then size $2 | tail -n1 | $AWK '{print $1}' else echo $1 fi } function get_size2() { if [ -r $2 ]; then size $2 | tail -n1 | $AWK '{print $1}' elif [ -r $3 ]; then size $3 | tail -n1 | $AWK '{print $1}' else echo $1 fi } function get_size3() { if [ -r $2 ]; then size $2 | tail -n1 | $AWK '{print $1}' elif [ -r $3 ]; then size $3 | tail -n1 | $AWK '{print $1}' elif [ -r $4 ]; then size $4 | tail -n1 | $AWK '{print $1}' else echo $1 fi } # get the last revision in the data file; or start at v1.0 if no file if [ -r $output ]; then last_rev=$(tail -n1 $output | $AWK '{print $1}') else echo "# hash size_unix size_stm32 size_barearm size_minimal size_cc3200 pystones" > $output last_rev="v1.0" fi # get a list of hashes between last revision (exclusive) and master hashes=$(git log --format=format:"%H" --reverse ${last_rev}..master) #hashes=$(git log --format=format:"%H" --reverse ${last_rev}..master | $AWK '{if (NR % 10 == 0) print $0}') # do every 10th one for hash in $hashes; do #### checkout the revision #### git checkout $hash if [ $? -ne 0 ]; then echo "aborting" exit 1 fi #### apply patches to get it to build #### if grep -q '#if defined(MP_CLOCKS_PER_SEC) && (MP_CLOCKS_PER_SEC == 1000000) // POSIX' unix/modtime.c; then echo apply patch git apply - << EOF diff --git a/unix/modtime.c b/unix/modtime.c index 77d2945..dae0644 100644 --- a/unix/modtime.c +++ b/unix/modtime.c @@ -55,10 +55,8 @@ void msec_sleep_tv(struct timeval *tv) { #define MP_CLOCKS_PER_SEC CLOCKS_PER_SEC #endif -#if defined(MP_CLOCKS_PER_SEC) && (MP_CLOCKS_PER_SEC == 1000000) // POSIX -#define CLOCK_DIV 1000.0 -#elif defined(MP_CLOCKS_PER_SEC) && (MP_CLOCKS_PER_SEC == 1000) // WIN32 -#define CLOCK_DIV 1.0 +#if defined(MP_CLOCKS_PER_SEC) +#define CLOCK_DIV (MP_CLOCKS_PER_SEC / 1000.0F) #else #error Unsupported clock() implementation #endif EOF fi #### unix #### $RM $bin_unix $MAKE -C ports/unix CFLAGS_EXTRA=-DNDEBUG size_unix=$(get_size $size_unix $bin_unix) # undo patch if it was applied git checkout unix/modtime.c #### stm32 #### $RM $bin_stm32 $MAKE -C ports/stm32 board=PYBV10 size_stm32=$(get_size $size_stm32 $bin_stm32) #### bare-arm #### $RM $bin_barearm_1 $bin_barearm_2 $MAKE -C ports/bare-arm size_barearm=$(get_size2 $size_barearm $bin_barearm_1 $bin_barearm_2) #### minimal #### if [ -r ports/minimal/Makefile ]; then $RM $bin_minimal $MAKE -C ports/minimal CROSS=1 size_minimal=$(get_size $size_minimal $bin_minimal) fi #### cc3200 #### if [ -r ports/cc3200/Makefile ]; then $RM $bin_cc3200_1 $bin_cc3200_2 $bin_cc3200_3 $MAKE -C ports/cc3200 BTARGET=application size_cc3200=$(get_size3 $size_cc3200 $bin_cc3200_1 $bin_cc3200_2 $bin_cc3200_3) fi #### run pystone #### if [ -x $bin_unix ]; then new_pystones=$($bin_unix $pystoneavg) # only update the variable if pystone executed successfully if echo $new_pystones | grep -q "^stones"; then pystones=$(echo $new_pystones | $AWK '{print $2}') fi fi #### output data for this commit #### echo "$hash $size_unix $size_stm32 $size_barearm $size_minimal $size_cc3200 $pystones" >> $output done # checkout master and cleanup git checkout master $RM $pystoneavg micropython-1.12/tools/dfu.py000077500000000000000000000112311357706137100163130ustar00rootroot00000000000000#!/usr/bin/python # Written by Antonio Galea - 2010/11/18 # Distributed under Gnu LGPL 3.0 # see http://www.gnu.org/licenses/lgpl-3.0.txt import sys,struct,zlib,os from optparse import OptionParser DEFAULT_DEVICE="0x0483:0xdf11" def named(tuple,names): return dict(zip(names.split(),tuple)) def consume(fmt,data,names): n = struct.calcsize(fmt) return named(struct.unpack(fmt,data[:n]),names),data[n:] def cstring(string): return string.split('\0',1)[0] def compute_crc(data): return 0xFFFFFFFF & -zlib.crc32(data) -1 def parse(file,dump_images=False): print ('File: "%s"' % file) data = open(file,'rb').read() crc = compute_crc(data[:-4]) prefix, data = consume('<5sBIB',data,'signature version size targets') print ('%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix) for t in range(prefix['targets']): tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') tprefix['num'] = t if tprefix['named']: tprefix['name'] = cstring(tprefix['name']) else: tprefix['name'] = '' print ('%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix) tsize = tprefix['size'] target, data = data[:tsize], data[tsize:] for e in range(tprefix['elements']): eprefix, target = consume('<2I',target,'address size') eprefix['num'] = e print (' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix) esize = eprefix['size'] image, target = target[:esize], target[esize:] if dump_images: out = '%s.target%d.image%d.bin' % (file,t,e) open(out,'wb').write(image) print (' DUMPED IMAGE TO "%s"' % out) if len(target): print ("target %d: PARSE ERROR" % t) suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') print ('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix) if crc != suffix['crc']: print ("CRC ERROR: computed crc32 is 0x%08x" % crc) data = data[16:] if data: print ("PARSE ERROR") def build(file,targets,device=DEFAULT_DEVICE): data = b'' for t,target in enumerate(targets): tdata = b'' for image in target: # pad image to 8 bytes (needed at least for L476) pad = (8 - len(image['data']) % 8 ) % 8 image['data'] = image['data'] + bytes(bytearray(8)[0:pad]) # tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] tdata = struct.pack('<6sBI255s2I',b'Target',0,1, b'ST...',len(tdata),len(target)) + tdata data += tdata data = struct.pack('<5sBIB',b'DfuSe',1,len(data)+11,len(targets)) + data v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) data += struct.pack('<4H3sB',0,d,v,0x011a,b'UFD',16) crc = compute_crc(data) data += struct.pack('= len(class_) or section[i] != class_[i]: if i == 0: filename = section[i].replace(' ', '_').lower() rst = open(DOCPATH + filename + '.rst', 'w') rst.write(HEADER) rst.write(section[i] + '\n') rst.write(RSTCHARS[0] * len(section[i])) rst.write(time.strftime("\nGenerated %a %d %b %Y %X UTC\n\n", time.gmtime())) toctree.append(filename) else: rst.write(section[i] + '\n') rst.write(RSTCHARS[min(i, len(RSTCHARS)-1)] * len(section[i])) rst.write('\n\n') class_ = section rst.write('.. _cpydiff_%s:\n\n' % output.name.rsplit('.', 1)[0]) rst.write(output.desc + '\n') rst.write('~' * len(output.desc) + '\n\n') if output.cause != 'Unknown': rst.write('**Cause:** ' + output.cause + '\n\n') if output.workaround != 'Unknown': rst.write('**Workaround:** ' + output.workaround + '\n\n') rst.write('Sample code::\n\n' + indent(output.code, TAB) + '\n') output_cpy = indent(''.join(output.output_cpy[0:2]), TAB).rstrip() output_cpy = ('::\n\n' if output_cpy != '' else '') + output_cpy output_upy = indent(''.join(output.output_upy[0:2]), TAB).rstrip() output_upy = ('::\n\n' if output_upy != '' else '') + output_upy table = gen_table([['CPy output:', output_cpy], ['uPy output:', output_upy]]) rst.write(table) template = open(INDEXTEMPLATE, 'r') index = open(DOCPATH + INDEX, 'w') index.write(HEADER) index.write(template.read()) for section in INDEXPRIORITY: if section in toctree: index.write(indent(section + '.rst', TAB)) toctree.remove(section) for section in toctree: index.write(indent(section + '.rst', TAB)) def main(): """ Main function """ # set search path so that test scripts find the test modules (and no other ones) os.environ['PYTHONPATH'] = TESTPATH os.environ['MICROPYPATH'] = TESTPATH files = readfiles() results = run_tests(files) gen_rst(results) main() micropython-1.12/tools/gendoc.py000066400000000000000000000411431357706137100167760ustar00rootroot00000000000000""" Generate documentation for pyboard API from C files. """ import os import argparse import re import markdown # given a list of (name,regex) pairs, find the first one that matches the given line def re_match_first(regexs, line): for name, regex in regexs: match = re.match(regex, line) if match: return name, match return None, None def makedirs(d): if not os.path.isdir(d): os.makedirs(d) class Lexer: class LexerError(Exception): pass class EOF(Exception): pass class Break(Exception): pass def __init__(self, file): self.filename = file with open(file, 'rt') as f: line_num = 0 lines = [] for line in f: line_num += 1 line = line.strip() if line == '///': lines.append((line_num, '')) elif line.startswith('/// '): lines.append((line_num, line[4:])) elif len(lines) > 0 and lines[-1][1] is not None: lines.append((line_num, None)) if len(lines) > 0 and lines[-1][1] is not None: lines.append((line_num, None)) self.cur_line = 0 self.lines = lines def opt_break(self): if len(self.lines) > 0 and self.lines[0][1] is None: self.lines.pop(0) def next(self): if len(self.lines) == 0: raise Lexer.EOF else: l = self.lines.pop(0) self.cur_line = l[0] if l[1] is None: raise Lexer.Break else: return l[1] def error(self, msg): print('({}:{}) {}'.format(self.filename, self.cur_line, msg)) raise Lexer.LexerError class MarkdownWriter: def __init__(self): pass def start(self): self.lines = [] def end(self): return '\n'.join(self.lines) def heading(self, level, text): if len(self.lines) > 0: self.lines.append('') self.lines.append(level * '#' + ' ' + text) self.lines.append('') def para(self, text): if len(self.lines) > 0 and self.lines[-1] != '': self.lines.append('') if isinstance(text, list): self.lines.extend(text) elif isinstance(text, str): self.lines.append(text) else: assert False self.lines.append('') def single_line(self, text): self.lines.append(text) def module(self, name, short_descr, descr): self.heading(1, 'module {}'.format(name)) self.para(descr) def function(self, ctx, name, args, descr): proto = '{}.{}{}'.format(ctx, self.name, self.args) self.heading(3, '`' + proto + '`') self.para(descr) def method(self, ctx, name, args, descr): if name == '\\constructor': proto = '{}{}'.format(ctx, args) elif name == '\\call': proto = '{}{}'.format(ctx, args) else: proto = '{}.{}{}'.format(ctx, name, args) self.heading(3, '`' + proto + '`') self.para(descr) def constant(self, ctx, name, descr): self.single_line('`{}.{}` - {}'.format(ctx, name, descr)) class ReStructuredTextWriter: head_chars = {1:'=', 2:'-', 3:'.'} def __init__(self): pass def start(self): self.lines = [] def end(self): return '\n'.join(self.lines) def _convert(self, text): return text.replace('`', '``').replace('*', '\\*') def heading(self, level, text, convert=True): if len(self.lines) > 0: self.lines.append('') if convert: text = self._convert(text) self.lines.append(text) self.lines.append(len(text) * self.head_chars[level]) self.lines.append('') def para(self, text, indent=''): if len(self.lines) > 0 and self.lines[-1] != '': self.lines.append('') if isinstance(text, list): for t in text: self.lines.append(indent + self._convert(t)) elif isinstance(text, str): self.lines.append(indent + self._convert(text)) else: assert False self.lines.append('') def single_line(self, text): self.lines.append(self._convert(text)) def module(self, name, short_descr, descr): self.heading(1, ':mod:`{}` --- {}'.format(name, self._convert(short_descr)), convert=False) self.lines.append('.. module:: {}'.format(name)) self.lines.append(' :synopsis: {}'.format(short_descr)) self.para(descr) def function(self, ctx, name, args, descr): args = self._convert(args) self.lines.append('.. function:: ' + name + args) self.para(descr, indent=' ') def method(self, ctx, name, args, descr): args = self._convert(args) if name == '\\constructor': self.lines.append('.. class:: ' + ctx + args) elif name == '\\call': self.lines.append('.. method:: ' + ctx + args) else: self.lines.append('.. method:: ' + ctx + '.' + name + args) self.para(descr, indent=' ') def constant(self, ctx, name, descr): self.lines.append('.. data:: ' + name) self.para(descr, indent=' ') class DocValidateError(Exception): pass class DocItem: def __init__(self): self.doc = [] def add_doc(self, lex): try: while True: line = lex.next() if len(line) > 0 or len(self.doc) > 0: self.doc.append(line) except Lexer.Break: pass def dump(self, writer): writer.para(self.doc) class DocConstant(DocItem): def __init__(self, name, descr): super().__init__() self.name = name self.descr = descr def dump(self, ctx, writer): writer.constant(ctx, self.name, self.descr) class DocFunction(DocItem): def __init__(self, name, args): super().__init__() self.name = name self.args = args def dump(self, ctx, writer): writer.function(ctx, self.name, self.args, self.doc) class DocMethod(DocItem): def __init__(self, name, args): super().__init__() self.name = name self.args = args def dump(self, ctx, writer): writer.method(ctx, self.name, self.args, self.doc) class DocClass(DocItem): def __init__(self, name, descr): super().__init__() self.name = name self.descr = descr self.constructors = {} self.classmethods = {} self.methods = {} self.constants = {} def process_classmethod(self, lex, d): name = d['id'] if name == '\\constructor': dict_ = self.constructors else: dict_ = self.classmethods if name in dict_: lex.error("multiple definition of method '{}'".format(name)) method = dict_[name] = DocMethod(name, d['args']) method.add_doc(lex) def process_method(self, lex, d): name = d['id'] dict_ = self.methods if name in dict_: lex.error("multiple definition of method '{}'".format(name)) method = dict_[name] = DocMethod(name, d['args']) method.add_doc(lex) def process_constant(self, lex, d): name = d['id'] if name in self.constants: lex.error("multiple definition of constant '{}'".format(name)) self.constants[name] = DocConstant(name, d['descr']) lex.opt_break() def dump(self, writer): writer.heading(1, 'class {}'.format(self.name)) super().dump(writer) if len(self.constructors) > 0: writer.heading(2, 'Constructors') for f in sorted(self.constructors.values(), key=lambda x:x.name): f.dump(self.name, writer) if len(self.classmethods) > 0: writer.heading(2, 'Class methods') for f in sorted(self.classmethods.values(), key=lambda x:x.name): f.dump(self.name, writer) if len(self.methods) > 0: writer.heading(2, 'Methods') for f in sorted(self.methods.values(), key=lambda x:x.name): f.dump(self.name.lower(), writer) if len(self.constants) > 0: writer.heading(2, 'Constants') for c in sorted(self.constants.values(), key=lambda x:x.name): c.dump(self.name, writer) class DocModule(DocItem): def __init__(self, name, descr): super().__init__() self.name = name self.descr = descr self.functions = {} self.constants = {} self.classes = {} self.cur_class = None def new_file(self): self.cur_class = None def process_function(self, lex, d): name = d['id'] if name in self.functions: lex.error("multiple definition of function '{}'".format(name)) function = self.functions[name] = DocFunction(name, d['args']) function.add_doc(lex) #def process_classref(self, lex, d): # name = d['id'] # self.classes[name] = name # lex.opt_break() def process_class(self, lex, d): name = d['id'] if name in self.classes: lex.error("multiple definition of class '{}'".format(name)) self.cur_class = self.classes[name] = DocClass(name, d['descr']) self.cur_class.add_doc(lex) def process_classmethod(self, lex, d): self.cur_class.process_classmethod(lex, d) def process_method(self, lex, d): self.cur_class.process_method(lex, d) def process_constant(self, lex, d): if self.cur_class is None: # a module-level constant name = d['id'] if name in self.constants: lex.error("multiple definition of constant '{}'".format(name)) self.constants[name] = DocConstant(name, d['descr']) lex.opt_break() else: # a class-level constant self.cur_class.process_constant(lex, d) def validate(self): if self.descr is None: raise DocValidateError('module {} referenced but never defined'.format(self.name)) def dump(self, writer): writer.module(self.name, self.descr, self.doc) if self.functions: writer.heading(2, 'Functions') for f in sorted(self.functions.values(), key=lambda x:x.name): f.dump(self.name, writer) if self.constants: writer.heading(2, 'Constants') for c in sorted(self.constants.values(), key=lambda x:x.name): c.dump(self.name, writer) if self.classes: writer.heading(2, 'Classes') for c in sorted(self.classes.values(), key=lambda x:x.name): writer.para('[`{}.{}`]({}) - {}'.format(self.name, c.name, c.name, c.descr)) def write_html(self, dir): md_writer = MarkdownWriter() md_writer.start() self.dump(md_writer) with open(os.path.join(dir, 'index.html'), 'wt') as f: f.write(markdown.markdown(md_writer.end())) for c in self.classes.values(): class_dir = os.path.join(dir, c.name) makedirs(class_dir) md_writer.start() md_writer.para('part of the [{} module](./)'.format(self.name)) c.dump(md_writer) with open(os.path.join(class_dir, 'index.html'), 'wt') as f: f.write(markdown.markdown(md_writer.end())) def write_rst(self, dir): rst_writer = ReStructuredTextWriter() rst_writer.start() self.dump(rst_writer) with open(dir + '/' + self.name + '.rst', 'wt') as f: f.write(rst_writer.end()) for c in self.classes.values(): rst_writer.start() c.dump(rst_writer) with open(dir + '/' + self.name + '.' + c.name + '.rst', 'wt') as f: f.write(rst_writer.end()) class Doc: def __init__(self): self.modules = {} self.cur_module = None def new_file(self): self.cur_module = None for m in self.modules.values(): m.new_file() def check_module(self, lex): if self.cur_module is None: lex.error('module not defined') def process_module(self, lex, d): name = d['id'] if name not in self.modules: self.modules[name] = DocModule(name, None) self.cur_module = self.modules[name] if self.cur_module.descr is not None: lex.error("multiple definition of module '{}'".format(name)) self.cur_module.descr = d['descr'] self.cur_module.add_doc(lex) def process_moduleref(self, lex, d): name = d['id'] if name not in self.modules: self.modules[name] = DocModule(name, None) self.cur_module = self.modules[name] lex.opt_break() def process_class(self, lex, d): self.check_module(lex) self.cur_module.process_class(lex, d) def process_function(self, lex, d): self.check_module(lex) self.cur_module.process_function(lex, d) def process_classmethod(self, lex, d): self.check_module(lex) self.cur_module.process_classmethod(lex, d) def process_method(self, lex, d): self.check_module(lex) self.cur_module.process_method(lex, d) def process_constant(self, lex, d): self.check_module(lex) self.cur_module.process_constant(lex, d) def validate(self): for m in self.modules.values(): m.validate() def dump(self, writer): writer.heading(1, 'Modules') writer.para('These are the Python modules that are implemented.') for m in sorted(self.modules.values(), key=lambda x:x.name): writer.para('[`{}`]({}/) - {}'.format(m.name, m.name, m.descr)) def write_html(self, dir): md_writer = MarkdownWriter() with open(os.path.join(dir, 'module', 'index.html'), 'wt') as f: md_writer.start() self.dump(md_writer) f.write(markdown.markdown(md_writer.end())) for m in self.modules.values(): mod_dir = os.path.join(dir, 'module', m.name) makedirs(mod_dir) m.write_html(mod_dir) def write_rst(self, dir): #with open(os.path.join(dir, 'module', 'index.html'), 'wt') as f: # f.write(markdown.markdown(self.dump())) for m in self.modules.values(): m.write_rst(dir) regex_descr = r'(?P.*)' doc_regexs = ( (Doc.process_module, re.compile(r'\\module (?P[a-z][a-z0-9]*) - ' + regex_descr + r'$')), (Doc.process_moduleref, re.compile(r'\\moduleref (?P[a-z]+)$')), (Doc.process_function, re.compile(r'\\function (?P[a-z0-9_]+)(?P\(.*\))$')), (Doc.process_classmethod, re.compile(r'\\classmethod (?P\\?[a-z0-9_]+)(?P\(.*\))$')), (Doc.process_method, re.compile(r'\\method (?P\\?[a-z0-9_]+)(?P\(.*\))$')), (Doc.process_constant, re.compile(r'\\constant (?P[A-Za-z0-9_]+) - ' + regex_descr + r'$')), #(Doc.process_classref, re.compile(r'\\classref (?P[A-Za-z0-9_]+)$')), (Doc.process_class, re.compile(r'\\class (?P[A-Za-z0-9_]+) - ' + regex_descr + r'$')), ) def process_file(file, doc): lex = Lexer(file) doc.new_file() try: try: while True: line = lex.next() fun, match = re_match_first(doc_regexs, line) if fun == None: lex.error('unknown line format: {}'.format(line)) fun(doc, lex, match.groupdict()) except Lexer.Break: lex.error('unexpected break') except Lexer.EOF: pass except Lexer.LexerError: return False return True def main(): cmd_parser = argparse.ArgumentParser(description='Generate documentation for pyboard API from C files.') cmd_parser.add_argument('--outdir', metavar='', default='gendoc-out', help='ouput directory') cmd_parser.add_argument('--format', default='html', help='output format: html or rst') cmd_parser.add_argument('files', nargs='+', help='input files') args = cmd_parser.parse_args() doc = Doc() for file in args.files: print('processing', file) if not process_file(file, doc): return try: doc.validate() except DocValidateError as e: print(e) makedirs(args.outdir) if args.format == 'html': doc.write_html(args.outdir) elif args.format == 'rst': doc.write_rst(args.outdir) else: print('unknown format:', args.format) return print('written to', args.outdir) if __name__ == "__main__": main() micropython-1.12/tools/insert-usb-ids.py000066400000000000000000000022551357706137100204100ustar00rootroot00000000000000# Reads the USB VID and PID from the file specified by sys.argv[1] and then # inserts those values into the template file specified by sys.argv[2], # printing the result to stdout from __future__ import print_function import sys import re import string needed_keys = ('USB_PID_CDC_MSC', 'USB_PID_CDC_HID', 'USB_PID_CDC', 'USB_VID') def parse_usb_ids(filename): rv = dict() for line in open(filename).readlines(): line = line.rstrip('\r\n') match = re.match('^#define\s+(\w+)\s+\(0x([0-9A-Fa-f]+)\)$', line) if match and match.group(1).startswith('USBD_'): key = match.group(1).replace('USBD', 'USB') val = match.group(2) print("key =", key, "val =", val) if key in needed_keys: rv[key] = val for k in needed_keys: if k not in rv: raise Exception("Unable to parse %s from %s" % (k, filename)) return rv if __name__ == "__main__": usb_ids_file = sys.argv[1] template_file = sys.argv[2] replacements = parse_usb_ids(usb_ids_file) for line in open(template_file, 'r').readlines(): print(string.Template(line).safe_substitute(replacements), end='') micropython-1.12/tools/make-frozen.py000077500000000000000000000043521357706137100177610ustar00rootroot00000000000000#!/usr/bin/env python # # Create frozen modules structure for MicroPython. # # Usage: # # Have a directory with modules to be frozen (only modules, not packages # supported so far): # # frozen/foo.py # frozen/bar.py # # Run script, passing path to the directory above: # # ./make-frozen.py frozen > frozen.c # # Include frozen.c in your build, having defined MICROPY_MODULE_FROZEN_STR in # config. # from __future__ import print_function import sys import os def module_name(f): return f modules = [] if len(sys.argv) > 1: root = sys.argv[1].rstrip("/") root_len = len(root) for dirpath, dirnames, filenames in os.walk(root): for f in filenames: fullpath = dirpath + "/" + f st = os.stat(fullpath) modules.append((fullpath[root_len + 1:], st)) print("#include ") print("const char mp_frozen_str_names[] = {") for f, st in modules: m = module_name(f) print('"%s\\0"' % m) print('"\\0"};') print("const uint32_t mp_frozen_str_sizes[] = {") for f, st in modules: print("%d," % st.st_size) print("};") print("const char mp_frozen_str_content[] = {") for f, st in modules: data = open(sys.argv[1] + "/" + f, "rb").read() # We need to properly escape the script data to create a C string. # When C parses hex characters of the form \x00 it keeps parsing the hex # data until it encounters a non-hex character. Thus one must create # strings of the form "data\x01" "abc" to properly encode this kind of # data. We could just encode all characters as hex digits but it's nice # to be able to read the resulting C code as ASCII when possible. data = bytearray(data) # so Python2 extracts each byte as an integer esc_dict = {ord('\n'): '\\n', ord('\r'): '\\r', ord('"'): '\\"', ord('\\'): '\\\\'} chrs = ['"'] break_str = False for c in data: try: chrs.append(esc_dict[c]) except KeyError: if 32 <= c <= 126: if break_str: chrs.append('" "') break_str = False chrs.append(chr(c)) else: chrs.append('\\x%02x' % c) break_str = True chrs.append('\\0"') print(''.join(chrs)) print("};") micropython-1.12/tools/makemanifest.py000066400000000000000000000245731357706137100202130ustar00rootroot00000000000000#!/usr/bin/env python3 # # This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2019 Damien P. George # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from __future__ import print_function import sys import os import subprocess ########################################################################### # Public functions to be used in the manifest def include(manifest): """Include another manifest. The manifest argument can be a string (filename) or an iterable of strings. Relative paths are resolved with respect to the current manifest file. """ if not isinstance(manifest, str): for m in manifest: include(m) else: manifest = convert_path(manifest) with open(manifest) as f: # Make paths relative to this manifest file while processing it. # Applies to includes and input files. prev_cwd = os.getcwd() os.chdir(os.path.dirname(manifest)) exec(f.read()) os.chdir(prev_cwd) def freeze(path, script=None, opt=0): """Freeze the input, automatically determining its type. A .py script will be compiled to a .mpy first then frozen, and a .mpy file will be frozen directly. `path` must be a directory, which is the base directory to search for files from. When importing the resulting frozen modules, the name of the module will start after `path`, ie `path` is excluded from the module name. If `path` is relative, it is resolved to the current manifest.py. Use $(MPY_DIR), $(MPY_LIB_DIR), $(PORT_DIR), $(BOARD_DIR) if you need to access specific paths. If `script` is None all files in `path` will be frozen. If `script` is an iterable then freeze() is called on all items of the iterable (with the same `path` and `opt` passed through). If `script` is a string then it specifies the filename to freeze, and can include extra directories before the file. The file will be searched for in `path`. `opt` is the optimisation level to pass to mpy-cross when compiling .py to .mpy. """ freeze_internal(KIND_AUTO, path, script, opt) def freeze_as_str(path): """Freeze the given `path` and all .py scripts within it as a string, which will be compiled upon import. """ freeze_internal(KIND_AS_STR, path, None, 0) def freeze_as_mpy(path, script=None, opt=0): """Freeze the input (see above) by first compiling the .py scripts to .mpy files, then freezing the resulting .mpy files. """ freeze_internal(KIND_AS_MPY, path, script, opt) def freeze_mpy(path, script=None, opt=0): """Freeze the input (see above), which must be .mpy files that are frozen directly. """ freeze_internal(KIND_MPY, path, script, opt) ########################################################################### # Internal implementation KIND_AUTO = 0 KIND_AS_STR = 1 KIND_AS_MPY = 2 KIND_MPY = 3 VARS = {} manifest_list = [] class FreezeError(Exception): pass def system(cmd): try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) return 0, output except subprocess.CalledProcessError as er: return -1, er.output def convert_path(path): # Perform variable substituion. for name, value in VARS.items(): path = path.replace('$({})'.format(name), value) # Convert to absolute path (so that future operations don't rely on # still being chdir'ed). return os.path.abspath(path) def get_timestamp(path, default=None): try: stat = os.stat(path) return stat.st_mtime except OSError: if default is None: raise FreezeError('cannot stat {}'.format(path)) return default def get_timestamp_newest(path): ts_newest = 0 for dirpath, dirnames, filenames in os.walk(path, followlinks=True): for f in filenames: ts_newest = max(ts_newest, get_timestamp(os.path.join(dirpath, f))) return ts_newest def mkdir(path): cur_path = '' for p in path.split('/')[:-1]: cur_path += p + '/' try: os.mkdir(cur_path) except OSError as er: if er.args[0] == 17: # file exists pass else: raise er def freeze_internal(kind, path, script, opt): path = convert_path(path) if script is None and kind == KIND_AS_STR: if any(f[0] == KIND_AS_STR for f in manifest_list): raise FreezeError('can only freeze one str directory') manifest_list.append((KIND_AS_STR, path, script, opt)) elif script is None: for dirpath, dirnames, filenames in os.walk(path, followlinks=True): for f in filenames: freeze_internal(kind, path, (dirpath + '/' + f)[len(path) + 1:], opt) elif not isinstance(script, str): for s in script: freeze_internal(kind, path, s, opt) else: extension_kind = {KIND_AS_MPY: '.py', KIND_MPY: '.mpy'} if kind == KIND_AUTO: for k, ext in extension_kind.items(): if script.endswith(ext): kind = k break else: print('warn: unsupported file type, skipped freeze: {}'.format(script)) return wanted_extension = extension_kind[kind] if not script.endswith(wanted_extension): raise FreezeError('expecting a {} file, got {}'.format(wanted_extension, script)) manifest_list.append((kind, path, script, opt)) def main(): # Parse arguments import argparse cmd_parser = argparse.ArgumentParser(description='A tool to generate frozen content in MicroPython firmware images.') cmd_parser.add_argument('-o', '--output', help='output path') cmd_parser.add_argument('-b', '--build-dir', help='output path') cmd_parser.add_argument('-f', '--mpy-cross-flags', default='', help='flags to pass to mpy-cross') cmd_parser.add_argument('-v', '--var', action='append', help='variables to substitute') cmd_parser.add_argument('files', nargs='+', help='input manifest list') args = cmd_parser.parse_args() # Extract variables for substitution. for var in args.var: name, value = var.split('=', 1) if os.path.exists(value): value = os.path.abspath(value) VARS[name] = value if 'MPY_DIR' not in VARS or 'PORT_DIR' not in VARS: print('MPY_DIR and PORT_DIR variables must be specified') sys.exit(1) # Get paths to tools MAKE_FROZEN = VARS['MPY_DIR'] + '/tools/make-frozen.py' MPY_CROSS = VARS['MPY_DIR'] + '/mpy-cross/mpy-cross' MPY_TOOL = VARS['MPY_DIR'] + '/tools/mpy-tool.py' # Ensure mpy-cross is built if not os.path.exists(MPY_CROSS): print('mpy-cross not found at {}, please build it first'.format(MPY_CROSS)) sys.exit(1) # Include top-level inputs, to generate the manifest for input_manifest in args.files: try: if input_manifest.endswith('.py'): include(input_manifest) else: exec(input_manifest) except FreezeError as er: print('freeze error executing "{}": {}'.format(input_manifest, er.args[0])) sys.exit(1) # Process the manifest str_paths = [] mpy_files = [] ts_newest = 0 for kind, path, script, opt in manifest_list: if kind == KIND_AS_STR: str_paths.append(path) ts_outfile = get_timestamp_newest(path) elif kind == KIND_AS_MPY: infile = '{}/{}'.format(path, script) outfile = '{}/frozen_mpy/{}.mpy'.format(args.build_dir, script[:-3]) ts_infile = get_timestamp(infile) ts_outfile = get_timestamp(outfile, 0) if ts_infile >= ts_outfile: print('MPY', script) mkdir(outfile) res, out = system([MPY_CROSS] + args.mpy_cross_flags.split() + ['-o', outfile, '-s', script, '-O{}'.format(opt), infile]) if res != 0: print('error compiling {}: {}'.format(infile, out)) raise SystemExit(1) ts_outfile = get_timestamp(outfile) mpy_files.append(outfile) else: assert kind == KIND_MPY infile = '{}/{}'.format(path, script) mpy_files.append(infile) ts_outfile = get_timestamp(infile) ts_newest = max(ts_newest, ts_outfile) # Check if output file needs generating if ts_newest < get_timestamp(args.output, 0): # No files are newer than output file so it does not need updating return # Freeze paths as strings res, output_str = system([sys.executable, MAKE_FROZEN] + str_paths) if res != 0: print('error freezing strings {}: {}'.format(str_paths, output_str)) sys.exit(1) # Freeze .mpy files res, output_mpy = system([sys.executable, MPY_TOOL, '-f', '-q', args.build_dir + '/genhdr/qstrdefs.preprocessed.h'] + mpy_files) if res != 0: print('error freezing mpy {}: {}'.format(mpy_files, output_mpy)) sys.exit(1) # Generate output print('GEN', args.output) mkdir(args.output) with open(args.output, 'wb') as f: f.write(b'//\n// Content for MICROPY_MODULE_FROZEN_STR\n//\n') f.write(output_str) f.write(b'//\n// Content for MICROPY_MODULE_FROZEN_MPY\n//\n') f.write(output_mpy) if __name__ == '__main__': main() micropython-1.12/tools/mpy-tool.py000077500000000000000000001034561357706137100173300ustar00rootroot00000000000000#!/usr/bin/env python3 # # This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2016-2019 Damien P. George # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # Python 2/3 compatibility code from __future__ import print_function import platform if platform.python_version_tuple()[0] == '2': str_cons = lambda val, enc=None: val bytes_cons = lambda val, enc=None: bytearray(val) is_str_type = lambda o: type(o) is str is_bytes_type = lambda o: type(o) is bytearray is_int_type = lambda o: type(o) is int or type(o) is long else: str_cons = str bytes_cons = bytes is_str_type = lambda o: type(o) is str is_bytes_type = lambda o: type(o) is bytes is_int_type = lambda o: type(o) is int # end compatibility code import sys import struct from collections import namedtuple sys.path.append(sys.path[0] + '/../py') import makeqstrdata as qstrutil class FreezeError(Exception): def __init__(self, rawcode, msg): self.rawcode = rawcode self.msg = msg def __str__(self): return 'error while freezing %s: %s' % (self.rawcode.source_file, self.msg) class Config: MPY_VERSION = 5 MICROPY_LONGINT_IMPL_NONE = 0 MICROPY_LONGINT_IMPL_LONGLONG = 1 MICROPY_LONGINT_IMPL_MPZ = 2 config = Config() class QStrType: def __init__(self, str): self.str = str self.qstr_esc = qstrutil.qstr_escape(self.str) self.qstr_id = 'MP_QSTR_' + self.qstr_esc # Initialise global list of qstrs with static qstrs global_qstrs = [None] # MP_QSTRnull should never be referenced for n in qstrutil.static_qstr_list: global_qstrs.append(QStrType(n)) class QStrWindow: def __init__(self, size): self.window = [] self.size = size def push(self, val): self.window = [val] + self.window[:self.size - 1] def access(self, idx): val = self.window[idx] self.window = [val] + self.window[:idx] + self.window[idx + 1:] return val MP_CODE_BYTECODE = 2 MP_CODE_NATIVE_PY = 3 MP_CODE_NATIVE_VIPER = 4 MP_CODE_NATIVE_ASM = 5 MP_NATIVE_ARCH_NONE = 0 MP_NATIVE_ARCH_X86 = 1 MP_NATIVE_ARCH_X64 = 2 MP_NATIVE_ARCH_ARMV6 = 3 MP_NATIVE_ARCH_ARMV6M = 4 MP_NATIVE_ARCH_ARMV7M = 5 MP_NATIVE_ARCH_ARMV7EM = 6 MP_NATIVE_ARCH_ARMV7EMSP = 7 MP_NATIVE_ARCH_ARMV7EMDP = 8 MP_NATIVE_ARCH_XTENSA = 9 MP_NATIVE_ARCH_XTENSAWIN = 10 MP_BC_MASK_EXTRA_BYTE = 0x9e MP_BC_FORMAT_BYTE = 0 MP_BC_FORMAT_QSTR = 1 MP_BC_FORMAT_VAR_UINT = 2 MP_BC_FORMAT_OFFSET = 3 # extra byte if caching enabled: MP_BC_LOAD_NAME = 0x11 MP_BC_LOAD_GLOBAL = 0x12 MP_BC_LOAD_ATTR = 0x13 MP_BC_STORE_ATTR = 0x18 # this function mirrors that in py/bc.c def mp_opcode_format(bytecode, ip, count_var_uint): opcode = bytecode[ip] ip_start = ip f = ((0x000003a4 >> (2 * ((opcode) >> 4))) & 3) if f == MP_BC_FORMAT_QSTR: if config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE: if (opcode == MP_BC_LOAD_NAME or opcode == MP_BC_LOAD_GLOBAL or opcode == MP_BC_LOAD_ATTR or opcode == MP_BC_STORE_ATTR): ip += 1 ip += 3 else: extra_byte = (opcode & MP_BC_MASK_EXTRA_BYTE) == 0 ip += 1 if f == MP_BC_FORMAT_VAR_UINT: if count_var_uint: while bytecode[ip] & 0x80 != 0: ip += 1 ip += 1 elif f == MP_BC_FORMAT_OFFSET: ip += 2 ip += extra_byte return f, ip - ip_start def read_prelude_sig(read_byte): z = read_byte() # xSSSSEAA S = (z >> 3) & 0xf E = (z >> 2) & 0x1 F = 0 A = z & 0x3 K = 0 D = 0 n = 0 while z & 0x80: z = read_byte() # xFSSKAED S |= (z & 0x30) << (2 * n) E |= (z & 0x02) << n F |= ((z & 0x40) >> 6) << n A |= (z & 0x4) << n K |= ((z & 0x08) >> 3) << n D |= (z & 0x1) << n n += 1 S += 1 return S, E, F, A, K, D def read_prelude_size(read_byte): I = 0 C = 0 n = 0 while True: z = read_byte() # xIIIIIIC I |= ((z & 0x7e) >> 1) << (6 * n) C |= (z & 1) << n if not (z & 0x80): break n += 1 return I, C def extract_prelude(bytecode, ip): def local_read_byte(): b = bytecode[ip_ref[0]] ip_ref[0] += 1 return b ip_ref = [ip] # to close over ip in Python 2 and 3 n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(local_read_byte) n_info, n_cell = read_prelude_size(local_read_byte) ip = ip_ref[0] ip2 = ip ip = ip2 + n_info + n_cell # ip now points to first opcode # ip2 points to simple_name qstr return ip, ip2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args) class MPFunTable: pass class RawCode(object): # a set of all escaped names, to make sure they are unique escaped_names = set() # convert code kind number to string code_kind_str = { MP_CODE_BYTECODE: 'MP_CODE_BYTECODE', MP_CODE_NATIVE_PY: 'MP_CODE_NATIVE_PY', MP_CODE_NATIVE_VIPER: 'MP_CODE_NATIVE_VIPER', MP_CODE_NATIVE_ASM: 'MP_CODE_NATIVE_ASM', } def __init__(self, code_kind, bytecode, prelude_offset, qstrs, objs, raw_codes): # set core variables self.code_kind = code_kind self.bytecode = bytecode self.prelude_offset = prelude_offset self.qstrs = qstrs self.objs = objs self.raw_codes = raw_codes if self.prelude_offset is None: # no prelude, assign a dummy simple_name self.prelude_offset = 0 self.simple_name = global_qstrs[1] else: # extract prelude self.ip, self.ip2, self.prelude = extract_prelude(self.bytecode, self.prelude_offset) self.simple_name = self._unpack_qstr(self.ip2) self.source_file = self._unpack_qstr(self.ip2 + 2) def _unpack_qstr(self, ip): qst = self.bytecode[ip] | self.bytecode[ip + 1] << 8 return global_qstrs[qst] def dump(self): # dump children first for rc in self.raw_codes: rc.freeze('') # TODO def freeze_children(self, parent_name): self.escaped_name = parent_name + self.simple_name.qstr_esc # make sure the escaped name is unique i = 2 while self.escaped_name in RawCode.escaped_names: self.escaped_name = parent_name + self.simple_name.qstr_esc + str(i) i += 1 RawCode.escaped_names.add(self.escaped_name) # emit children first for rc in self.raw_codes: rc.freeze(self.escaped_name + '_') def freeze_constants(self): # generate constant objects for i, obj in enumerate(self.objs): obj_name = 'const_obj_%s_%u' % (self.escaped_name, i) if obj is MPFunTable: pass elif obj is Ellipsis: print('#define %s mp_const_ellipsis_obj' % obj_name) elif is_str_type(obj) or is_bytes_type(obj): if is_str_type(obj): obj = bytes_cons(obj, 'utf8') obj_type = 'mp_type_str' else: obj_type = 'mp_type_bytes' print('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};' % (obj_name, obj_type, qstrutil.compute_hash(obj, config.MICROPY_QSTR_BYTES_IN_HASH), len(obj), ''.join(('\\x%02x' % b) for b in obj))) elif is_int_type(obj): if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_NONE: # TODO check if we can actually fit this long-int into a small-int raise FreezeError(self, 'target does not support long int') elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_LONGLONG: # TODO raise FreezeError(self, 'freezing int to long-long is not implemented') elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_MPZ: neg = 0 if obj < 0: obj = -obj neg = 1 bits_per_dig = config.MPZ_DIG_SIZE digs = [] z = obj while z: digs.append(z & ((1 << bits_per_dig) - 1)) z >>= bits_per_dig ndigs = len(digs) digs = ','.join(('%#x' % d) for d in digs) print('STATIC const mp_obj_int_t %s = {{&mp_type_int}, ' '{.neg=%u, .fixed_dig=1, .alloc=%u, .len=%u, .dig=(uint%u_t*)(const uint%u_t[]){%s}}};' % (obj_name, neg, ndigs, ndigs, bits_per_dig, bits_per_dig, digs)) elif type(obj) is float: print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B') print('STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};' % (obj_name, obj)) print('#endif') elif type(obj) is complex: print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};' % (obj_name, obj.real, obj.imag)) else: raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,)) # generate constant table, if it has any entries const_table_len = len(self.qstrs) + len(self.objs) + len(self.raw_codes) if const_table_len: print('STATIC const mp_rom_obj_t const_table_data_%s[%u] = {' % (self.escaped_name, const_table_len)) for qst in self.qstrs: print(' MP_ROM_QSTR(%s),' % global_qstrs[qst].qstr_id) for i in range(len(self.objs)): if self.objs[i] is MPFunTable: print(' &mp_fun_table,') elif type(self.objs[i]) is float: print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B') print(' MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i)) print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C') n = struct.unpack('> 8,') print(' ', self.source_file.qstr_id, '& 0xff,', self.source_file.qstr_id, '>> 8,') print(' ', end='') for i in range(self.ip2 + 4, self.ip): print(' 0x%02x,' % self.bytecode[i], end='') print() ip = self.ip while ip < len(self.bytecode): f, sz = mp_opcode_format(self.bytecode, ip, True) if f == 1: qst = self._unpack_qstr(ip + 1).qstr_id extra = '' if sz == 3 else ' 0x%02x,' % self.bytecode[ip + 3] print(' ', '0x%02x,' % self.bytecode[ip], qst, '& 0xff,', qst, '>> 8,', extra) else: print(' ', ''.join('0x%02x, ' % self.bytecode[ip + i] for i in range(sz))) ip += sz print('};') self.freeze_constants() self.freeze_module() class RawCodeNative(RawCode): def __init__(self, code_kind, fun_data, prelude_offset, prelude, qstr_links, qstrs, objs, raw_codes, type_sig): super(RawCodeNative, self).__init__(code_kind, fun_data, prelude_offset, qstrs, objs, raw_codes) self.prelude = prelude self.qstr_links = qstr_links self.type_sig = type_sig if config.native_arch in (MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64, MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN): self.fun_data_attributes = '__attribute__((section(".text,\\"ax\\",@progbits # ")))' else: self.fun_data_attributes = '__attribute__((section(".text,\\"ax\\",%progbits @ ")))' # Allow single-byte alignment by default for x86/x64. # ARM needs word alignment, ARM Thumb needs halfword, due to instruction size. # Xtensa needs word alignment due to the 32-bit constant table embedded in the code. if config.native_arch in (MP_NATIVE_ARCH_ARMV6, MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN): # ARMV6 or Xtensa -- four byte align. self.fun_data_attributes += ' __attribute__ ((aligned (4)))' elif MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP: # ARMVxxM -- two byte align. self.fun_data_attributes += ' __attribute__ ((aligned (2)))' def _asm_thumb_rewrite_mov(self, pc, val): print(' (%u & 0xf0) | (%s >> 12),' % (self.bytecode[pc], val), end='') print(' (%u & 0xfb) | (%s >> 9 & 0x04),' % (self.bytecode[pc + 1], val), end='') print(' (%s & 0xff),' % (val,), end='') print(' (%u & 0x07) | (%s >> 4 & 0x70),' % (self.bytecode[pc + 3], val)) def _link_qstr(self, pc, kind, qst): if kind == 0: # Generic 16-bit link print(' %s & 0xff, %s >> 8,' % (qst, qst)) return 2 else: # Architecture-specific link is_obj = kind == 2 if is_obj: qst = '((uintptr_t)MP_OBJ_NEW_QSTR(%s))' % qst if config.native_arch in ( MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64, MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN ): print(' %s & 0xff, (%s >> 8) & 0xff, (%s >> 16) & 0xff, %s >> 24,' % (qst, qst, qst, qst)) return 4 elif MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP: if is_obj: # qstr object, movw and movt self._asm_thumb_rewrite_mov(pc, qst) self._asm_thumb_rewrite_mov(pc + 4, '(%s >> 16)' % qst) return 8 else: # qstr number, movw instruction self._asm_thumb_rewrite_mov(pc, qst) return 4 else: assert 0 def freeze(self, parent_name): if self.prelude[2] & ~0x0f: raise FreezeError('unable to freeze code with relocations') self.freeze_children(parent_name) # generate native code data print() if self.code_kind == MP_CODE_NATIVE_PY: print('// frozen native code for file %s, scope %s%s' % (self.source_file.str, parent_name, self.simple_name.str)) elif self.code_kind == MP_CODE_NATIVE_VIPER: print('// frozen viper code for scope %s' % (parent_name,)) else: print('// frozen assembler code for scope %s' % (parent_name,)) print('STATIC const byte fun_data_%s[%u] %s = {' % (self.escaped_name, len(self.bytecode), self.fun_data_attributes)) if self.code_kind == MP_CODE_NATIVE_PY: i_top = self.prelude_offset else: i_top = len(self.bytecode) i = 0 qi = 0 while i < i_top: if qi < len(self.qstr_links) and i == self.qstr_links[qi][0]: # link qstr qi_off, qi_kind, qi_val = self.qstr_links[qi] qst = global_qstrs[qi_val].qstr_id i += self._link_qstr(i, qi_kind, qst) qi += 1 else: # copy machine code (max 16 bytes) i16 = min(i + 16, i_top) if qi < len(self.qstr_links): i16 = min(i16, self.qstr_links[qi][0]) print(' ', end='') for ii in range(i, i16): print(' 0x%02x,' % self.bytecode[ii], end='') print() i = i16 if self.code_kind == MP_CODE_NATIVE_PY: print(' ', end='') for i in range(self.prelude_offset, self.ip2): print(' 0x%02x,' % self.bytecode[i], end='') print() print(' ', self.simple_name.qstr_id, '& 0xff,', self.simple_name.qstr_id, '>> 8,') print(' ', self.source_file.qstr_id, '& 0xff,', self.source_file.qstr_id, '>> 8,') print(' ', end='') for i in range(self.ip2 + 4, self.ip): print(' 0x%02x,' % self.bytecode[i], end='') print() print('};') self.freeze_constants() self.freeze_module(self.qstr_links, self.type_sig) class BytecodeBuffer: def __init__(self, size): self.buf = bytearray(size) self.idx = 0 def is_full(self): return self.idx == len(self.buf) def append(self, b): self.buf[self.idx] = b self.idx += 1 def read_byte(f, out=None): b = bytes_cons(f.read(1))[0] if out is not None: out.append(b) return b def read_uint(f, out=None): i = 0 while True: b = read_byte(f, out) i = (i << 7) | (b & 0x7f) if b & 0x80 == 0: break return i def read_qstr(f, qstr_win): ln = read_uint(f) if ln == 0: # static qstr return bytes_cons(f.read(1))[0] if ln & 1: # qstr in table return qstr_win.access(ln >> 1) ln >>= 1 data = str_cons(f.read(ln), 'utf8') global_qstrs.append(QStrType(data)) qstr_win.push(len(global_qstrs) - 1) return len(global_qstrs) - 1 def read_obj(f): obj_type = f.read(1) if obj_type == b'e': return Ellipsis else: buf = f.read(read_uint(f)) if obj_type == b's': return str_cons(buf, 'utf8') elif obj_type == b'b': return bytes_cons(buf) elif obj_type == b'i': return int(str_cons(buf, 'ascii'), 10) elif obj_type == b'f': return float(str_cons(buf, 'ascii')) elif obj_type == b'c': return complex(str_cons(buf, 'ascii')) else: assert 0 def read_prelude(f, bytecode, qstr_win): n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(lambda: read_byte(f, bytecode)) n_info, n_cell = read_prelude_size(lambda: read_byte(f, bytecode)) read_qstr_and_pack(f, bytecode, qstr_win) # simple_name read_qstr_and_pack(f, bytecode, qstr_win) # source_file for _ in range(n_info - 4 + n_cell): read_byte(f, bytecode) return n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args def read_qstr_and_pack(f, bytecode, qstr_win): qst = read_qstr(f, qstr_win) bytecode.append(qst & 0xff) bytecode.append(qst >> 8) def read_bytecode(file, bytecode, qstr_win): while not bytecode.is_full(): op = read_byte(file, bytecode) f, sz = mp_opcode_format(bytecode.buf, bytecode.idx - 1, False) sz -= 1 if f == MP_BC_FORMAT_QSTR: read_qstr_and_pack(file, bytecode, qstr_win) sz -= 2 elif f == MP_BC_FORMAT_VAR_UINT: while read_byte(file, bytecode) & 0x80: pass for _ in range(sz): read_byte(file, bytecode) def read_raw_code(f, qstr_win): kind_len = read_uint(f) kind = (kind_len & 3) + MP_CODE_BYTECODE fun_data_len = kind_len >> 2 fun_data = BytecodeBuffer(fun_data_len) if kind == MP_CODE_BYTECODE: prelude = read_prelude(f, fun_data, qstr_win) read_bytecode(f, fun_data, qstr_win) else: fun_data.buf[:] = f.read(fun_data_len) qstr_links = [] if kind in (MP_CODE_NATIVE_PY, MP_CODE_NATIVE_VIPER): # load qstr link table n_qstr_link = read_uint(f) for _ in range(n_qstr_link): off = read_uint(f) qst = read_qstr(f, qstr_win) qstr_links.append((off >> 2, off & 3, qst)) type_sig = 0 if kind == MP_CODE_NATIVE_PY: prelude_offset = read_uint(f) _, name_idx, prelude = extract_prelude(fun_data.buf, prelude_offset) fun_data.idx = name_idx # rewind to where qstrs are in prelude read_qstr_and_pack(f, fun_data, qstr_win) # simple_name read_qstr_and_pack(f, fun_data, qstr_win) # source_file else: prelude_offset = None scope_flags = read_uint(f) n_pos_args = 0 if kind == MP_CODE_NATIVE_ASM: n_pos_args = read_uint(f) type_sig = read_uint(f) prelude = (None, None, scope_flags, n_pos_args, 0) qstrs = [] objs = [] raw_codes = [] if kind != MP_CODE_NATIVE_ASM: # load constant table n_obj = read_uint(f) n_raw_code = read_uint(f) qstrs = [read_qstr(f, qstr_win) for _ in range(prelude[3] + prelude[4])] if kind != MP_CODE_BYTECODE: objs.append(MPFunTable) objs.extend([read_obj(f) for _ in range(n_obj)]) raw_codes = [read_raw_code(f, qstr_win) for _ in range(n_raw_code)] if kind == MP_CODE_BYTECODE: return RawCodeBytecode(fun_data.buf, qstrs, objs, raw_codes) else: return RawCodeNative(kind, fun_data.buf, prelude_offset, prelude, qstr_links, qstrs, objs, raw_codes, type_sig) def read_mpy(filename): with open(filename, 'rb') as f: header = bytes_cons(f.read(4)) if header[0] != ord('M'): raise Exception('not a valid .mpy file') if header[1] != config.MPY_VERSION: raise Exception('incompatible .mpy version') feature_byte = header[2] qw_size = read_uint(f) config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE = (feature_byte & 1) != 0 config.MICROPY_PY_BUILTINS_STR_UNICODE = (feature_byte & 2) != 0 mpy_native_arch = feature_byte >> 2 if mpy_native_arch != MP_NATIVE_ARCH_NONE: if config.native_arch == MP_NATIVE_ARCH_NONE: config.native_arch = mpy_native_arch elif config.native_arch != mpy_native_arch: raise Exception('native architecture mismatch') config.mp_small_int_bits = header[3] qstr_win = QStrWindow(qw_size) rc = read_raw_code(f, qstr_win) rc.mpy_source_file = filename rc.qstr_win_size = qw_size return rc def dump_mpy(raw_codes): for rc in raw_codes: rc.dump() def freeze_mpy(base_qstrs, raw_codes): # add to qstrs new = {} for q in global_qstrs: # don't add duplicates if q is None or q.qstr_esc in base_qstrs or q.qstr_esc in new: continue new[q.qstr_esc] = (len(new), q.qstr_esc, q.str) new = sorted(new.values(), key=lambda x: x[0]) print('#include "py/mpconfig.h"') print('#include "py/objint.h"') print('#include "py/objstr.h"') print('#include "py/emitglue.h"') print('#include "py/nativeglue.h"') print() print('#if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE != %u' % config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) print('#error "incompatible MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE"') print('#endif') print() print('#if MICROPY_LONGINT_IMPL != %u' % config.MICROPY_LONGINT_IMPL) print('#error "incompatible MICROPY_LONGINT_IMPL"') print('#endif') print() if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_MPZ: print('#if MPZ_DIG_SIZE != %u' % config.MPZ_DIG_SIZE) print('#error "incompatible MPZ_DIG_SIZE"') print('#endif') print() print('#if MICROPY_PY_BUILTINS_FLOAT') print('typedef struct _mp_obj_float_t {') print(' mp_obj_base_t base;') print(' mp_float_t value;') print('} mp_obj_float_t;') print('#endif') print() print('#if MICROPY_PY_BUILTINS_COMPLEX') print('typedef struct _mp_obj_complex_t {') print(' mp_obj_base_t base;') print(' mp_float_t real;') print(' mp_float_t imag;') print('} mp_obj_complex_t;') print('#endif') print() if len(new) > 0: print('enum {') for i in range(len(new)): if i == 0: print(' MP_QSTR_%s = MP_QSTRnumber_of,' % new[i][1]) else: print(' MP_QSTR_%s,' % new[i][1]) print('};') # As in qstr.c, set so that the first dynamically allocated pool is twice this size; must be <= the len qstr_pool_alloc = min(len(new), 10) print() print('extern const qstr_pool_t mp_qstr_const_pool;'); print('const qstr_pool_t mp_qstr_frozen_const_pool = {') print(' (qstr_pool_t*)&mp_qstr_const_pool, // previous pool') print(' MP_QSTRnumber_of, // previous pool size') print(' %u, // allocated entries' % qstr_pool_alloc) print(' %u, // used entries' % len(new)) print(' {') for _, _, qstr in new: print(' %s,' % qstrutil.make_bytes(config.MICROPY_QSTR_BYTES_IN_LEN, config.MICROPY_QSTR_BYTES_IN_HASH, qstr)) print(' },') print('};') for rc in raw_codes: rc.freeze(rc.source_file.str.replace('/', '_')[:-3] + '_') print() print('const char mp_frozen_mpy_names[] = {') for rc in raw_codes: module_name = rc.source_file.str print('"%s\\0"' % module_name) print('"\\0"};') print('const mp_raw_code_t *const mp_frozen_mpy_content[] = {') for rc in raw_codes: print(' &raw_code_%s,' % rc.escaped_name) print('};') def merge_mpy(raw_codes, output_file): assert len(raw_codes) <= 31 # so var-uints all fit in 1 byte merged_mpy = bytearray() if len(raw_codes) == 1: with open(raw_codes[0].mpy_source_file, 'rb') as f: merged_mpy.extend(f.read()) else: header = bytearray(5) header[0] = ord('M') header[1] = config.MPY_VERSION header[2] = (config.native_arch << 2 | config.MICROPY_PY_BUILTINS_STR_UNICODE << 1 | config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) header[3] = config.mp_small_int_bits header[4] = 32 # qstr_win_size merged_mpy.extend(header) bytecode = bytearray() bytecode_len = 6 + len(raw_codes) * 4 + 2 bytecode.append(bytecode_len << 2) # kind and length bytecode.append(0b00000000) # signature prelude bytecode.append(0b00001000) # size prelude bytecode.extend(b'\x00\x01') # MP_QSTR_ bytecode.extend(b'\x00\x01') # MP_QSTR_ for idx in range(len(raw_codes)): bytecode.append(0x32) # MP_BC_MAKE_FUNCTION bytecode.append(idx) # index raw code bytecode.extend(b'\x34\x00') # MP_BC_CALL_FUNCTION, 0 args bytecode.extend(b'\x51\x63') # MP_BC_LOAD_NONE, MP_BC_RETURN_VALUE bytecode.append(0) # n_obj bytecode.append(len(raw_codes)) # n_raw_code merged_mpy.extend(bytecode) for rc in raw_codes: with open(rc.mpy_source_file, 'rb') as f: f.read(4) # skip header read_uint(f) # skip qstr_win_size data = f.read() # read rest of mpy file merged_mpy.extend(data) if output_file is None: sys.stdout.buffer.write(merged_mpy) else: with open(output_file, 'wb') as f: f.write(merged_mpy) def main(): import argparse cmd_parser = argparse.ArgumentParser(description='A tool to work with MicroPython .mpy files.') cmd_parser.add_argument('-d', '--dump', action='store_true', help='dump contents of files') cmd_parser.add_argument('-f', '--freeze', action='store_true', help='freeze files') cmd_parser.add_argument('--merge', action='store_true', help='merge multiple .mpy files into one') cmd_parser.add_argument('-q', '--qstr-header', help='qstr header file to freeze against') cmd_parser.add_argument('-mlongint-impl', choices=['none', 'longlong', 'mpz'], default='mpz', help='long-int implementation used by target (default mpz)') cmd_parser.add_argument('-mmpz-dig-size', metavar='N', type=int, default=16, help='mpz digit size used by target (default 16)') cmd_parser.add_argument('-o', '--output', default=None, help='output file') cmd_parser.add_argument('files', nargs='+', help='input .mpy files') args = cmd_parser.parse_args() # set config values relevant to target machine config.MICROPY_LONGINT_IMPL = { 'none':config.MICROPY_LONGINT_IMPL_NONE, 'longlong':config.MICROPY_LONGINT_IMPL_LONGLONG, 'mpz':config.MICROPY_LONGINT_IMPL_MPZ, }[args.mlongint_impl] config.MPZ_DIG_SIZE = args.mmpz_dig_size config.native_arch = MP_NATIVE_ARCH_NONE # set config values for qstrs, and get the existing base set of qstrs if args.qstr_header: qcfgs, base_qstrs = qstrutil.parse_input_headers([args.qstr_header]) config.MICROPY_QSTR_BYTES_IN_LEN = int(qcfgs['BYTES_IN_LEN']) config.MICROPY_QSTR_BYTES_IN_HASH = int(qcfgs['BYTES_IN_HASH']) else: config.MICROPY_QSTR_BYTES_IN_LEN = 1 config.MICROPY_QSTR_BYTES_IN_HASH = 1 base_qstrs = {} raw_codes = [read_mpy(file) for file in args.files] if args.dump: dump_mpy(raw_codes) elif args.freeze: try: freeze_mpy(base_qstrs, raw_codes) except FreezeError as er: print(er, file=sys.stderr) sys.exit(1) elif args.merge: merged_mpy = merge_mpy(raw_codes, args.output) if __name__ == '__main__': main() micropython-1.12/tools/mpy_bin2res.py000077500000000000000000000007611357706137100177740ustar00rootroot00000000000000#!/usr/bin/env python3 # # This tool converts binary resource files passed on the command line # into a Python source file containing data from these files, which can # be accessed using standard pkg_resources.resource_stream() function # from micropython-lib: # https://github.com/micropython/micropython-lib/tree/master/pkg_resources # import sys print("R = {") for fname in sys.argv[1:]: with open(fname, "rb") as f: b = f.read() print("%r: %r," % (fname, b)) print("}") micropython-1.12/tools/mpy_cross_all.py000077500000000000000000000024151357706137100204070ustar00rootroot00000000000000#!/usr/bin/env python3 import argparse import os import os.path argparser = argparse.ArgumentParser(description="Compile all .py files to .mpy recursively") argparser.add_argument("-o", "--out", help="output directory (default: input dir)") argparser.add_argument("--target", help="select MicroPython target config") argparser.add_argument("-mcache-lookup-bc", action="store_true", help="cache map lookups in the bytecode") argparser.add_argument("dir", help="input directory") args = argparser.parse_args() TARGET_OPTS = { "unix": "-mcache-lookup-bc", "baremetal": "", } args.dir = args.dir.rstrip("/") if not args.out: args.out = args.dir path_prefix_len = len(args.dir) + 1 for path, subdirs, files in os.walk(args.dir): for f in files: if f.endswith(".py"): fpath = path + "/" + f #print(fpath) out_fpath = args.out + "/" + fpath[path_prefix_len:-3] + ".mpy" out_dir = os.path.dirname(out_fpath) if not os.path.isdir(out_dir): os.makedirs(out_dir) cmd = "mpy-cross -v -v %s -s %s %s -o %s" % (TARGET_OPTS.get(args.target, ""), fpath[path_prefix_len:], fpath, out_fpath) #print(cmd) res = os.system(cmd) assert res == 0 micropython-1.12/tools/mpy_ld.py000077500000000000000000001054011357706137100170240ustar00rootroot00000000000000#!/usr/bin/env python3 # # This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2019 Damien P. George # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ Link .o files to .mpy """ import sys, os, struct, re from elftools.elf import elffile sys.path.append(os.path.dirname(__file__) + '/../py') import makeqstrdata as qstrutil # MicroPython constants MPY_VERSION = 5 MP_NATIVE_ARCH_X86 = 1 MP_NATIVE_ARCH_X64 = 2 MP_NATIVE_ARCH_ARMV7M = 5 MP_NATIVE_ARCH_ARMV7EMSP = 7 MP_NATIVE_ARCH_ARMV7EMDP = 8 MP_NATIVE_ARCH_XTENSA = 9 MP_NATIVE_ARCH_XTENSAWIN = 10 MP_CODE_BYTECODE = 2 MP_CODE_NATIVE_VIPER = 4 MP_SCOPE_FLAG_VIPERRELOC = 0x10 MP_SCOPE_FLAG_VIPERRODATA = 0x20 MP_SCOPE_FLAG_VIPERBSS = 0x40 MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE = 1 MICROPY_PY_BUILTINS_STR_UNICODE = 2 MP_SMALL_INT_BITS = 31 QSTR_WINDOW_SIZE = 32 # ELF constants R_386_32 = 1 R_X86_64_64 = 1 R_XTENSA_32 = 1 R_386_PC32 = 2 R_X86_64_PC32 = 2 R_ARM_ABS32 = 2 R_386_GOT32 = 3 R_ARM_REL32 = 3 R_386_PLT32 = 4 R_X86_64_PLT32 = 4 R_XTENSA_PLT = 6 R_386_GOTOFF = 9 R_386_GOTPC = 10 R_ARM_THM_CALL = 10 R_XTENSA_DIFF32 = 19 R_XTENSA_SLOT0_OP = 20 R_ARM_BASE_PREL = 25 # aka R_ARM_GOTPC R_ARM_GOT_BREL = 26 # aka R_ARM_GOT32 R_ARM_THM_JUMP24 = 30 R_X86_64_REX_GOTPCRELX = 42 R_386_GOT32X = 43 ################################################################################ # Architecture configuration def asm_jump_x86(entry): return struct.pack('> 11 == 0 or b_off >> 11 == -1: # Signed value fits in 12 bits b0 = 0xe000 | (b_off >> 1 & 0x07ff) b1 = 0 else: # Use large jump b0 = 0xf000 | (b_off >> 12 & 0x07ff) b1 = 0xb800 | (b_off >> 1 & 0x7ff) return struct.pack('> 8) class ArchData: def __init__(self, name, mpy_feature, qstr_entry_size, word_size, arch_got, asm_jump): self.name = name self.mpy_feature = mpy_feature self.qstr_entry_size = qstr_entry_size self.word_size = word_size self.arch_got = arch_got self.asm_jump = asm_jump self.separate_rodata = name == 'EM_XTENSA' and qstr_entry_size == 4 ARCH_DATA = { 'x86': ArchData( 'EM_386', MP_NATIVE_ARCH_X86 << 2 | MICROPY_PY_BUILTINS_STR_UNICODE | MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE, 2, 4, (R_386_PC32, R_386_GOT32, R_386_GOT32X), asm_jump_x86, ), 'x64': ArchData( 'EM_X86_64', MP_NATIVE_ARCH_X64 << 2 | MICROPY_PY_BUILTINS_STR_UNICODE | MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE, 2, 8, (R_X86_64_REX_GOTPCRELX,), asm_jump_x86, ), 'armv7m': ArchData( 'EM_ARM', MP_NATIVE_ARCH_ARMV7M << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, 2, 4, (R_ARM_GOT_BREL,), asm_jump_arm, ), 'armv7emsp': ArchData( 'EM_ARM', MP_NATIVE_ARCH_ARMV7EMSP << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, 2, 4, (R_ARM_GOT_BREL,), asm_jump_arm, ), 'armv7emdp': ArchData( 'EM_ARM', MP_NATIVE_ARCH_ARMV7EMDP << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, 2, 4, (R_ARM_GOT_BREL,), asm_jump_arm, ), 'xtensa': ArchData( 'EM_XTENSA', MP_NATIVE_ARCH_XTENSA << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, 2, 4, (R_XTENSA_32, R_XTENSA_PLT), asm_jump_xtensa, ), 'xtensawin': ArchData( 'EM_XTENSA', MP_NATIVE_ARCH_XTENSAWIN << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, 4, 4, (R_XTENSA_32, R_XTENSA_PLT), asm_jump_xtensa, ), } ################################################################################ # Helper functions def align_to(value, align): return (value + align - 1) & ~(align - 1) def unpack_u24le(data, offset): return data[offset] | data[offset + 1] << 8 | data[offset + 2] << 16 def pack_u24le(data, offset, value): data[offset] = value & 0xff data[offset + 1] = value >> 8 & 0xff data[offset + 2] = value >> 16 & 0xff def xxd(text): for i in range(0, len(text), 16): print('{:08x}:'.format(i), end='') for j in range(4): off = i + j * 4 if off < len(text): d = int.from_bytes(text[off:off + 4], 'little') print(' {:08x}'.format(d), end='') print() # Smaller numbers are enabled first LOG_LEVEL_1 = 1 LOG_LEVEL_2 = 2 LOG_LEVEL_3 = 3 log_level = LOG_LEVEL_1 def log(level, msg): if level <= log_level: print(msg) ################################################################################ # Qstr extraction def extract_qstrs(source_files): def read_qstrs(f): with open(f) as f: vals = set() objs = set() for line in f: while line: m = re.search(r'MP_OBJ_NEW_QSTR\((MP_QSTR_[A-Za-z0-9_]*)\)', line) if m: objs.add(m.group(1)) else: m = re.search(r'MP_QSTR_[A-Za-z0-9_]*', line) if m: vals.add(m.group()) if m: s = m.span() line = line[:s[0]] + line[s[1]:] else: line = '' return vals, objs static_qstrs = ['MP_QSTR_' + qstrutil.qstr_escape(q) for q in qstrutil.static_qstr_list] qstr_vals = set() qstr_objs = set() for f in source_files: vals, objs = read_qstrs(f) qstr_vals.update(vals) qstr_objs.update(objs) qstr_vals.difference_update(static_qstrs) return static_qstrs, qstr_vals, qstr_objs ################################################################################ # Linker class LinkError(Exception): pass class Section: def __init__(self, name, data, alignment, filename=None): self.filename = filename self.name = name self.data = data self.alignment = alignment self.addr = 0 self.reloc = [] @staticmethod def from_elfsec(elfsec, filename): assert elfsec.header.sh_addr == 0 return Section(elfsec.name, elfsec.data(), elfsec.data_alignment, filename) class GOTEntry: def __init__(self, name, sym, link_addr=0): self.name = name self.sym = sym self.offset = None self.link_addr = link_addr def isexternal(self): return self.sec_name.startswith('.external') def istext(self): return self.sec_name.startswith('.text') def isrodata(self): return self.sec_name.startswith(('.rodata', '.data.rel.ro')) def isbss(self): return self.sec_name.startswith('.bss') class LiteralEntry: def __init__(self, value, offset): self.value = value self.offset = offset class LinkEnv: def __init__(self, arch): self.arch = ARCH_DATA[arch] self.sections = [] # list of sections in order of output self.literal_sections = [] # list of literal sections (xtensa only) self.known_syms = {} # dict of symbols that are defined self.unresolved_syms = [] # list of unresolved symbols self.mpy_relocs = [] # list of relocations needed in the output .mpy file def check_arch(self, arch_name): if arch_name != self.arch.name: raise LinkError('incompatible arch') def print_sections(self): log(LOG_LEVEL_2, 'sections:') for sec in self.sections: log(LOG_LEVEL_2, ' {:08x} {} size={}'.format(sec.addr, sec.name, len(sec.data))) def find_addr(self, name): if name in self.known_syms: s = self.known_syms[name] return s.section.addr + s['st_value'] raise LinkError('unknown symbol: {}'.format(name)) def build_got_generic(env): env.got_entries = {} for sec in env.sections: for r in sec.reloc: s = r.sym if not (s.entry['st_info']['bind'] == 'STB_GLOBAL' and r['r_info_type'] in env.arch.arch_got): continue s_type = s.entry['st_info']['type'] assert s_type in ('STT_NOTYPE', 'STT_FUNC', 'STT_OBJECT'), s_type assert s.name if s.name in env.got_entries: continue env.got_entries[s.name] = GOTEntry(s.name, s) def build_got_xtensa(env): env.got_entries = {} env.lit_entries = {} env.xt_literals = {} # Extract the values from the literal table for sec in env.literal_sections: assert len(sec.data) % env.arch.word_size == 0 # Look through literal relocations to find any global pointers that should be GOT entries for r in sec.reloc: s = r.sym s_type = s.entry['st_info']['type'] assert s_type in ('STT_NOTYPE', 'STT_FUNC', 'STT_OBJECT', 'STT_SECTION'), s_type assert r['r_info_type'] in env.arch.arch_got assert r['r_offset'] % env.arch.word_size == 0 # This entry is a global pointer existing = struct.unpack_from(' {}+{:08x}'.format(g.offset, g.name, g.sec_name, g.link_addr)) def populate_lit(env): log(LOG_LEVEL_2, 'LIT: {:08x}'.format(env.lit_section.addr)) for lit_entry in env.lit_entries.values(): value = lit_entry.value log(LOG_LEVEL_2, ' {:08x} = {:08x}'.format(lit_entry.offset, value)) o = env.lit_section.addr + lit_entry.offset env.full_text[o:o + env.arch.word_size] = value.to_bytes(env.arch.word_size, 'little') def do_relocation_text(env, text_addr, r): # Extract relevant info about symbol that's being relocated s = r.sym s_bind = s.entry['st_info']['bind'] s_shndx = s.entry['st_shndx'] s_type = s.entry['st_info']['type'] r_offset = r['r_offset'] + text_addr r_info_type = r['r_info_type'] try: # only for RELA sections r_addend = r['r_addend'] except KeyError: r_addend = 0 # Default relocation type and name for logging reloc_type = 'le32' log_name = None if (env.arch.name == 'EM_386' and r_info_type in (R_386_PC32, R_386_PLT32) or env.arch.name == 'EM_X86_64' and r_info_type in (R_X86_64_PC32, R_X86_64_PLT32) or env.arch.name == 'EM_ARM' and r_info_type in (R_ARM_REL32, R_ARM_THM_CALL, R_ARM_THM_JUMP24) or s_bind == 'STB_LOCAL' and env.arch.name == 'EM_XTENSA' and r_info_type == R_XTENSA_32 # not GOT ): # Standard relocation to fixed location within text/rodata if hasattr(s, 'resolved'): s = s.resolved sec = s.section if env.arch.separate_rodata and sec.name.startswith('.rodata'): raise LinkError('fixed relocation to rodata with rodata referenced via GOT') if sec.name.startswith('.bss'): raise LinkError('{}: fixed relocation to bss (bss variables can\'t be static)'.format(s.filename)) if sec.name.startswith('.external'): raise LinkError('{}: fixed relocation to external symbol: {}'.format(s.filename, s.name)) addr = sec.addr + s['st_value'] reloc = addr - r_offset + r_addend if r_info_type in (R_ARM_THM_CALL, R_ARM_THM_JUMP24): # Both relocations have the same bit pattern to rewrite: # R_ARM_THM_CALL: bl # R_ARM_THM_JUMP24: b.w reloc_type = 'thumb_b' elif (env.arch.name == 'EM_386' and r_info_type == R_386_GOTPC or env.arch.name == 'EM_ARM' and r_info_type == R_ARM_BASE_PREL ): # Relocation to GOT address itself assert s.name == '_GLOBAL_OFFSET_TABLE_' addr = env.got_section.addr reloc = addr - r_offset + r_addend elif (env.arch.name == 'EM_386' and r_info_type in (R_386_GOT32, R_386_GOT32X) or env.arch.name == 'EM_ARM' and r_info_type == R_ARM_GOT_BREL ): # Relcation pointing to GOT reloc = addr = env.got_entries[s.name].offset elif env.arch.name == 'EM_X86_64' and r_info_type == R_X86_64_REX_GOTPCRELX: # Relcation pointing to GOT got_entry = env.got_entries[s.name] addr = env.got_section.addr + got_entry.offset reloc = addr - r_offset + r_addend elif env.arch.name == 'EM_386' and r_info_type == R_386_GOTOFF: # Relocation relative to GOT addr = s.section.addr + s['st_value'] reloc = addr - env.got_section.addr + r_addend elif env.arch.name == 'EM_XTENSA' and r_info_type == R_XTENSA_SLOT0_OP: # Relocation pointing to GOT, xtensa specific sec = s.section if sec.name.startswith('.text'): # it looks like R_XTENSA_SLOT0_OP into .text is already correctly relocated return assert sec.name.startswith('.literal'), sec.name lit_idx = '{}+0x{:x}'.format(sec.filename, r_addend) lit_ptr = env.xt_literals[lit_idx] if isinstance(lit_ptr, str): addr = env.got_section.addr + env.got_entries[lit_ptr].offset log_name = 'GOT {}'.format(lit_ptr) else: addr = env.lit_section.addr + env.lit_entries[lit_ptr].offset log_name = 'LIT' reloc = addr - r_offset reloc_type = 'xtensa_l32r' elif env.arch.name == 'EM_XTENSA' and r_info_type == R_XTENSA_DIFF32: if s.section.name.startswith('.text'): # it looks like R_XTENSA_DIFF32 into .text is already correctly relocated return assert 0 else: # Unknown/unsupported relocation assert 0, r_info_type # Write relocation if reloc_type == 'le32': existing, = struct.unpack_from('= 0x400000: # 2's complement existing -= 0x800000 new = existing + reloc b_h = (b_h & 0xf800) | (new >> 12) & 0x7ff b_l = (b_l & 0xf800) | (new >> 1) & 0x7ff struct.pack_into('> 8 l32r_imm16 = (l32r_imm16 + reloc >> 2) & 0xffff l32r = l32r & 0xff | l32r_imm16 << 8 pack_u24le(env.full_text, r_offset, l32r) else: assert 0, reloc_type # Log information about relocation if log_name is None: if s_type == 'STT_SECTION': log_name = s.section.name else: log_name = s.name log(LOG_LEVEL_3, ' {:08x} {} -> {:08x}'.format(r_offset, log_name, addr)) def do_relocation_data(env, text_addr, r): s = r.sym s_type = s.entry['st_info']['type'] r_offset = r['r_offset'] + text_addr r_info_type = r['r_info_type'] try: # only for RELA sections r_addend = r['r_addend'] except KeyError: r_addend = 0 if (env.arch.name == 'EM_386' and r_info_type == R_386_32 or env.arch.name == 'EM_X86_64' and r_info_type == R_X86_64_64 or env.arch.name == 'EM_ARM' and r_info_type == R_ARM_ABS32 or env.arch.name == 'EM_XTENSA' and r_info_type == R_XTENSA_32): # Relocation in data.rel.ro to internal/external symbol if env.arch.word_size == 4: struct_type = ' {} {:08x}'.format(r_offset, log_name, addr)) if env.arch.separate_rodata: data = env.full_rodata else: data = env.full_text existing, = struct.unpack_from(struct_type, data, r_offset) if sec.name.startswith(('.text', '.rodata', '.data.rel.ro', '.bss')): struct.pack_into(struct_type, data, r_offset, existing + addr) kind = sec.name elif sec.name == '.external.mp_fun_table': assert addr == 0 kind = s.mp_fun_table_offset else: assert 0, sec.name if env.arch.separate_rodata: base = '.rodata' else: base = '.text' env.mpy_relocs.append((base, r_offset, kind)) else: # Unknown/unsupported relocation assert 0, r_info_type def load_object_file(env, felf): with open(felf, 'rb') as f: elf = elffile.ELFFile(f) env.check_arch(elf['e_machine']) # Get symbol table symtab = list(elf.get_section_by_name('.symtab').iter_symbols()) # Load needed sections from ELF file sections_shndx = {} # maps elf shndx to Section object for idx, s in enumerate(elf.iter_sections()): if s.header.sh_type in ('SHT_PROGBITS', 'SHT_NOBITS'): if s.data_size == 0: # Ignore empty sections pass elif s.name.startswith(('.literal', '.text', '.rodata', '.data.rel.ro', '.bss')): sec = Section.from_elfsec(s, felf) sections_shndx[idx] = sec if s.name.startswith('.literal'): env.literal_sections.append(sec) else: env.sections.append(sec) elif s.name.startswith('.data'): raise LinkError('{}: {} non-empty'.format(felf, s.name)) else: # Ignore section pass elif s.header.sh_type in ('SHT_REL', 'SHT_RELA'): shndx = s.header.sh_info if shndx in sections_shndx: sec = sections_shndx[shndx] sec.reloc_name = s.name sec.reloc = list(s.iter_relocations()) for r in sec.reloc: r.sym = symtab[r['r_info_sym']] # Link symbols to their sections, and update known and unresolved symbols for sym in symtab: sym.filename = felf shndx = sym.entry['st_shndx'] if shndx in sections_shndx: # Symbol with associated section sym.section = sections_shndx[shndx] if sym['st_info']['bind'] == 'STB_GLOBAL': # Defined global symbol if sym.name in env.known_syms and not sym.name.startswith('__x86.get_pc_thunk.'): raise LinkError('duplicate symbol: {}'.format(sym.name)) env.known_syms[sym.name] = sym elif sym.entry['st_shndx'] == 'SHN_UNDEF' and sym['st_info']['bind'] == 'STB_GLOBAL': # Undefined global symbol, needs resolving env.unresolved_syms.append(sym) def link_objects(env, native_qstr_vals_len, native_qstr_objs_len): # Build GOT information if env.arch.name == 'EM_XTENSA': build_got_xtensa(env) else: build_got_generic(env) # Creat GOT section got_size = len(env.got_entries) * env.arch.word_size env.got_section = Section('GOT', bytearray(got_size), env.arch.word_size) if env.arch.name == 'EM_XTENSA': env.sections.insert(0, env.got_section) else: env.sections.append(env.got_section) # Create optional literal section if env.arch.name == 'EM_XTENSA': lit_size = len(env.lit_entries) * env.arch.word_size env.lit_section = Section('LIT', bytearray(lit_size), env.arch.word_size) env.sections.insert(1, env.lit_section) # Create section to contain mp_native_qstr_val_table env.qstr_val_section = Section('.text.QSTR_VAL', bytearray(native_qstr_vals_len * env.arch.qstr_entry_size), env.arch.qstr_entry_size) env.sections.append(env.qstr_val_section) # Create section to contain mp_native_qstr_obj_table env.qstr_obj_section = Section('.text.QSTR_OBJ', bytearray(native_qstr_objs_len * env.arch.word_size), env.arch.word_size) env.sections.append(env.qstr_obj_section) # Resolve unknown symbols mp_fun_table_sec = Section('.external.mp_fun_table', b'', 0) fun_table = {key: 67 + idx for idx, key in enumerate([ 'mp_type_type', 'mp_type_str', 'mp_type_list', 'mp_type_dict', 'mp_type_fun_builtin_0', 'mp_type_fun_builtin_1', 'mp_type_fun_builtin_2', 'mp_type_fun_builtin_3', 'mp_type_fun_builtin_var', 'mp_stream_read_obj', 'mp_stream_readinto_obj', 'mp_stream_unbuffered_readline_obj', 'mp_stream_write_obj', ]) } for sym in env.unresolved_syms: assert sym['st_value'] == 0 if sym.name == '_GLOBAL_OFFSET_TABLE_': pass elif sym.name == 'mp_fun_table': sym.section = Section('.external', b'', 0) elif sym.name == 'mp_native_qstr_val_table': sym.section = env.qstr_val_section elif sym.name == 'mp_native_qstr_obj_table': sym.section = env.qstr_obj_section elif sym.name in env.known_syms: sym.resolved = env.known_syms[sym.name] else: if sym.name in fun_table: sym.section = mp_fun_table_sec sym.mp_fun_table_offset = fun_table[sym.name] else: raise LinkError('{}: undefined symbol: {}'.format(sym.filename, sym.name)) # Align sections, assign their addresses, and create full_text env.full_text = bytearray(env.arch.asm_jump(8)) # dummy, to be filled in later env.full_rodata = bytearray(0) env.full_bss = bytearray(0) for sec in env.sections: if env.arch.separate_rodata and sec.name.startswith(('.rodata', '.data.rel.ro')): data = env.full_rodata elif sec.name.startswith('.bss'): data = env.full_bss else: data = env.full_text sec.addr = align_to(len(data), sec.alignment) data.extend(b'\x00' * (sec.addr - len(data))) data.extend(sec.data) env.print_sections() populate_got(env) if env.arch.name == 'EM_XTENSA': populate_lit(env) # Fill in relocations for sec in env.sections: if not sec.reloc: continue log(LOG_LEVEL_3, '{}: {} relocations via {}:'.format(sec.filename, sec.name, sec.reloc_name)) for r in sec.reloc: if sec.name.startswith(('.text', '.rodata')): do_relocation_text(env, sec.addr, r) elif sec.name.startswith('.data.rel.ro'): do_relocation_data(env, sec.addr, r) else: assert 0, sec.name ################################################################################ # .mpy output class MPYOutput: def open(self, fname): self.f = open(fname, 'wb') self.prev_base = -1 self.prev_offset = -1 def close(self): self.f.close() def write_bytes(self, buf): self.f.write(buf) def write_uint(self, val): b = bytearray() b.insert(0, val & 0x7f) val >>= 7 while val: b.insert(0, 0x80 | (val & 0x7f)) val >>= 7 self.write_bytes(b) def write_qstr(self, s): if s in qstrutil.static_qstr_list: self.write_bytes(bytes([0, qstrutil.static_qstr_list.index(s) + 1])) else: s = bytes(s, 'ascii') self.write_uint(len(s) << 1) self.write_bytes(s) def write_reloc(self, base, offset, dest, n): need_offset = not (base == self.prev_base and offset == self.prev_offset + 1) self.prev_offset = offset + n - 1 if dest <= 2: dest = (dest << 1) | (n > 1) else: assert 6 <= dest <= 127 assert n == 1 dest = dest << 1 | need_offset assert 0 <= dest <= 0xfe, dest self.write_bytes(bytes([dest])) if need_offset: if base == '.text': base = 0 elif base == '.rodata': base = 1 self.write_uint(offset << 1 | base) if n > 1: self.write_uint(n) def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): # Write jump instruction to start of text jump = env.arch.asm_jump(entry_offset) env.full_text[:len(jump)] = jump log(LOG_LEVEL_1, 'arch: {}'.format(env.arch.name)) log(LOG_LEVEL_1, 'text size: {}'.format(len(env.full_text))) if len(env.full_rodata): log(LOG_LEVEL_1, 'rodata size: {}'.format(len(env.full_rodata))) log(LOG_LEVEL_1, 'bss size: {}'.format(len(env.full_bss))) log(LOG_LEVEL_1, 'GOT entries: {}'.format(len(env.got_entries))) #xxd(env.full_text) out = MPYOutput() out.open(fmpy) # MPY: header out.write_bytes(bytearray([ ord('M'), MPY_VERSION, env.arch.mpy_feature, MP_SMALL_INT_BITS, QSTR_WINDOW_SIZE, ])) # MPY: kind/len out.write_uint(len(env.full_text) << 2 | (MP_CODE_NATIVE_VIPER - MP_CODE_BYTECODE)) # MPY: machine code out.write_bytes(env.full_text) # MPY: n_qstr_link (assumes little endian) out.write_uint(len(native_qstr_vals) + len(native_qstr_objs)) for q in range(len(native_qstr_vals)): off = env.qstr_val_section.addr + q * env.arch.qstr_entry_size out.write_uint(off << 2) out.write_qstr(native_qstr_vals[q]) for q in range(len(native_qstr_objs)): off = env.qstr_obj_section.addr + q * env.arch.word_size out.write_uint(off << 2 | 3) out.write_qstr(native_qstr_objs[q]) # MPY: scope_flags scope_flags = MP_SCOPE_FLAG_VIPERRELOC if len(env.full_rodata): scope_flags |= MP_SCOPE_FLAG_VIPERRODATA if len(env.full_bss): scope_flags |= MP_SCOPE_FLAG_VIPERBSS out.write_uint(scope_flags) # MPY: n_obj out.write_uint(0) # MPY: n_raw_code out.write_uint(0) # MPY: rodata and/or bss if len(env.full_rodata): rodata_const_table_idx = 1 out.write_uint(len(env.full_rodata)) out.write_bytes(env.full_rodata) if len(env.full_bss): bss_const_table_idx = bool(env.full_rodata) + 1 out.write_uint(len(env.full_bss)) # MPY: relocation information prev_kind = None for base, addr, kind in env.mpy_relocs: if isinstance(kind, str) and kind.startswith('.text'): kind = 0 elif kind in ('.rodata', '.data.rel.ro'): if env.arch.separate_rodata: kind = rodata_const_table_idx else: kind = 0 elif isinstance(kind, str) and kind.startswith('.bss'): kind = bss_const_table_idx elif kind == 'mp_fun_table': kind = 6 else: kind = 7 + kind assert addr % env.arch.word_size == 0, addr offset = addr // env.arch.word_size if kind == prev_kind and base == prev_base and offset == prev_offset + 1: prev_n += 1 prev_offset += 1 else: if prev_kind is not None: out.write_reloc(prev_base, prev_offset - prev_n + 1, prev_kind, prev_n) prev_kind = kind prev_base = base prev_offset = offset prev_n = 1 if prev_kind is not None: out.write_reloc(prev_base, prev_offset - prev_n + 1, prev_kind, prev_n) # MPY: sentinel for end of relocations out.write_bytes(b'\xff') out.close() ################################################################################ # main def do_preprocess(args): if args.output is None: assert args.files[0].endswith('.c') args.output = args.files[0][:-1] + 'config.h' static_qstrs, qstr_vals, qstr_objs = extract_qstrs(args.files) with open(args.output, 'w') as f: print('#include \n' 'typedef uintptr_t mp_uint_t;\n' 'typedef intptr_t mp_int_t;\n' 'typedef uintptr_t mp_off_t;', file=f) for i, q in enumerate(static_qstrs): print('#define %s (%u)' % (q, i + 1), file=f) for i, q in enumerate(sorted(qstr_vals)): print('#define %s (mp_native_qstr_val_table[%d])' % (q, i), file=f) for i, q in enumerate(sorted(qstr_objs)): print('#define MP_OBJ_NEW_QSTR_%s ((mp_obj_t)mp_native_qstr_obj_table[%d])' % (q, i), file=f) if args.arch == 'xtensawin': qstr_type = 'uint32_t' # esp32 can only read 32-bit values from IRAM else: qstr_type = 'uint16_t' print('extern const {} mp_native_qstr_val_table[];'.format(qstr_type), file=f) print('extern const mp_uint_t mp_native_qstr_obj_table[];', file=f) def do_link(args): if args.output is None: assert args.files[0].endswith('.o') args.output = args.files[0][:-1] + 'mpy' native_qstr_vals = [] native_qstr_objs = [] if args.qstrs is not None: with open(args.qstrs) as f: for l in f: m = re.match(r'#define MP_QSTR_([A-Za-z0-9_]*) \(mp_native_', l) if m: native_qstr_vals.append(m.group(1)) else: m = re.match(r'#define MP_OBJ_NEW_QSTR_MP_QSTR_([A-Za-z0-9_]*)', l) if m: native_qstr_objs.append(m.group(1)) log(LOG_LEVEL_2, 'qstr vals: ' + ', '.join(native_qstr_vals)) log(LOG_LEVEL_2, 'qstr objs: ' + ', '.join(native_qstr_objs)) env = LinkEnv(args.arch) try: for file in args.files: load_object_file(env, file) link_objects(env, len(native_qstr_vals), len(native_qstr_objs)) build_mpy(env, env.find_addr('mpy_init'), args.output, native_qstr_vals, native_qstr_objs) except LinkError as er: print('LinkError:', er.args[0]) sys.exit(1) def main(): import argparse cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.') cmd_parser.add_argument('--verbose', '-v', action='count', default=1, help='increase verbosity') cmd_parser.add_argument('--arch', default='x64', help='architecture') cmd_parser.add_argument('--preprocess', action='store_true', help='preprocess source files') cmd_parser.add_argument('--qstrs', default=None, help='file defining additional qstrs') cmd_parser.add_argument('--output', '-o', default=None, help='output .mpy file (default to input with .o->.mpy)') cmd_parser.add_argument('files', nargs='+', help='input files') args = cmd_parser.parse_args() global log_level log_level = args.verbose if args.preprocess: do_preprocess(args) else: do_link(args) if __name__ == '__main__': main() micropython-1.12/tools/pyboard.py000077500000000000000000000510461357706137100172050ustar00rootroot00000000000000#!/usr/bin/env python # # This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2014-2019 Damien P. George # Copyright (c) 2017 Paul Sokolovsky # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ pyboard interface This module provides the Pyboard class, used to communicate with and control a MicroPython device over a communication channel. Both real boards and emulated devices (e.g. running in QEMU) are supported. Various communication channels are supported, including a serial connection, telnet-style network connection, external process connection. Example usage: import pyboard pyb = pyboard.Pyboard('/dev/ttyACM0') Or: pyb = pyboard.Pyboard('192.168.1.1') Then: pyb.enter_raw_repl() pyb.exec('import pyb') pyb.exec('pyb.LED(1).on()') pyb.exit_raw_repl() Note: if using Python2 then pyb.exec must be written as pyb.exec_. To run a script from the local machine on the board and print out the results: import pyboard pyboard.execfile('test.py', device='/dev/ttyACM0') This script can also be run directly. To execute a local script, use: ./pyboard.py test.py Or: python pyboard.py test.py """ import sys import time import os try: stdout = sys.stdout.buffer except AttributeError: # Python2 doesn't have buffer attr stdout = sys.stdout def stdout_write_bytes(b): b = b.replace(b"\x04", b"") stdout.write(b) stdout.flush() class PyboardError(Exception): pass class TelnetToSerial: def __init__(self, ip, user, password, read_timeout=None): self.tn = None import telnetlib self.tn = telnetlib.Telnet(ip, timeout=15) self.read_timeout = read_timeout if b'Login as:' in self.tn.read_until(b'Login as:', timeout=read_timeout): self.tn.write(bytes(user, 'ascii') + b"\r\n") if b'Password:' in self.tn.read_until(b'Password:', timeout=read_timeout): # needed because of internal implementation details of the telnet server time.sleep(0.2) self.tn.write(bytes(password, 'ascii') + b"\r\n") if b'for more information.' in self.tn.read_until(b'Type "help()" for more information.', timeout=read_timeout): # login successful from collections import deque self.fifo = deque() return raise PyboardError('Failed to establish a telnet connection with the board') def __del__(self): self.close() def close(self): if self.tn: self.tn.close() def read(self, size=1): while len(self.fifo) < size: timeout_count = 0 data = self.tn.read_eager() if len(data): self.fifo.extend(data) timeout_count = 0 else: time.sleep(0.25) if self.read_timeout is not None and timeout_count > 4 * self.read_timeout: break timeout_count += 1 data = b'' while len(data) < size and len(self.fifo) > 0: data += bytes([self.fifo.popleft()]) return data def write(self, data): self.tn.write(data) return len(data) def inWaiting(self): n_waiting = len(self.fifo) if not n_waiting: data = self.tn.read_eager() self.fifo.extend(data) return len(data) else: return n_waiting class ProcessToSerial: "Execute a process and emulate serial connection using its stdin/stdout." def __init__(self, cmd): import subprocess self.subp = subprocess.Popen(cmd, bufsize=0, shell=True, preexec_fn=os.setsid, stdin=subprocess.PIPE, stdout=subprocess.PIPE) # Initially was implemented with selectors, but that adds Python3 # dependency. However, there can be race conditions communicating # with a particular child process (like QEMU), and selectors may # still work better in that case, so left inplace for now. # #import selectors #self.sel = selectors.DefaultSelector() #self.sel.register(self.subp.stdout, selectors.EVENT_READ) import select self.poll = select.poll() self.poll.register(self.subp.stdout.fileno()) def close(self): import signal os.killpg(os.getpgid(self.subp.pid), signal.SIGTERM) def read(self, size=1): data = b"" while len(data) < size: data += self.subp.stdout.read(size - len(data)) return data def write(self, data): self.subp.stdin.write(data) return len(data) def inWaiting(self): #res = self.sel.select(0) res = self.poll.poll(0) if res: return 1 return 0 class ProcessPtyToTerminal: """Execute a process which creates a PTY and prints slave PTY as first line of its output, and emulate serial connection using this PTY.""" def __init__(self, cmd): import subprocess import re import serial self.subp = subprocess.Popen(cmd.split(), bufsize=0, shell=False, preexec_fn=os.setsid, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) pty_line = self.subp.stderr.readline().decode("utf-8") m = re.search(r"/dev/pts/[0-9]+", pty_line) if not m: print("Error: unable to find PTY device in startup line:", pty_line) self.close() sys.exit(1) pty = m.group() # rtscts, dsrdtr params are to workaround pyserial bug: # http://stackoverflow.com/questions/34831131/pyserial-does-not-play-well-with-virtual-port self.ser = serial.Serial(pty, interCharTimeout=1, rtscts=True, dsrdtr=True) def close(self): import signal os.killpg(os.getpgid(self.subp.pid), signal.SIGTERM) def read(self, size=1): return self.ser.read(size) def write(self, data): return self.ser.write(data) def inWaiting(self): return self.ser.inWaiting() class Pyboard: def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0): if device.startswith("exec:"): self.serial = ProcessToSerial(device[len("exec:"):]) elif device.startswith("execpty:"): self.serial = ProcessPtyToTerminal(device[len("qemupty:"):]) elif device and device[0].isdigit() and device[-1].isdigit() and device.count('.') == 3: # device looks like an IP address self.serial = TelnetToSerial(device, user, password, read_timeout=10) else: import serial delayed = False for attempt in range(wait + 1): try: self.serial = serial.Serial(device, baudrate=baudrate, interCharTimeout=1) break except (OSError, IOError): # Py2 and Py3 have different errors if wait == 0: continue if attempt == 0: sys.stdout.write('Waiting {} seconds for pyboard '.format(wait)) delayed = True time.sleep(1) sys.stdout.write('.') sys.stdout.flush() else: if delayed: print('') raise PyboardError('failed to access ' + device) if delayed: print('') def close(self): self.serial.close() def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): # if data_consumer is used then data is not accumulated and the ending must be 1 byte long assert data_consumer is None or len(ending) == 1 data = self.serial.read(min_num_bytes) if data_consumer: data_consumer(data) timeout_count = 0 while True: if data.endswith(ending): break elif self.serial.inWaiting() > 0: new_data = self.serial.read(1) if data_consumer: data_consumer(new_data) data = new_data else: data = data + new_data timeout_count = 0 else: timeout_count += 1 if timeout is not None and timeout_count >= 100 * timeout: break time.sleep(0.01) return data def enter_raw_repl(self): self.serial.write(b'\r\x03\x03') # ctrl-C twice: interrupt any running program # flush input (without relying on serial.flushInput()) n = self.serial.inWaiting() while n > 0: self.serial.read(n) n = self.serial.inWaiting() self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n>') if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'): print(data) raise PyboardError('could not enter raw repl') self.serial.write(b'\x04') # ctrl-D: soft reset data = self.read_until(1, b'soft reboot\r\n') if not data.endswith(b'soft reboot\r\n'): print(data) raise PyboardError('could not enter raw repl') # By splitting this into 2 reads, it allows boot.py to print stuff, # which will show up after the soft reboot and before the raw REPL. data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n') if not data.endswith(b'raw REPL; CTRL-B to exit\r\n'): print(data) raise PyboardError('could not enter raw repl') def exit_raw_repl(self): self.serial.write(b'\r\x02') # ctrl-B: enter friendly REPL def follow(self, timeout, data_consumer=None): # wait for normal output data = self.read_until(1, b'\x04', timeout=timeout, data_consumer=data_consumer) if not data.endswith(b'\x04'): raise PyboardError('timeout waiting for first EOF reception') data = data[:-1] # wait for error output data_err = self.read_until(1, b'\x04', timeout=timeout) if not data_err.endswith(b'\x04'): raise PyboardError('timeout waiting for second EOF reception') data_err = data_err[:-1] # return normal and error output return data, data_err def exec_raw_no_follow(self, command): if isinstance(command, bytes): command_bytes = command else: command_bytes = bytes(command, encoding='utf8') # check we have a prompt data = self.read_until(1, b'>') if not data.endswith(b'>'): raise PyboardError('could not enter raw repl') # write command for i in range(0, len(command_bytes), 256): self.serial.write(command_bytes[i:min(i + 256, len(command_bytes))]) time.sleep(0.01) self.serial.write(b'\x04') # check if we could exec command data = self.serial.read(2) if data != b'OK': raise PyboardError('could not exec command (response: %r)' % data) def exec_raw(self, command, timeout=10, data_consumer=None): self.exec_raw_no_follow(command); return self.follow(timeout, data_consumer) def eval(self, expression): ret = self.exec_('print({})'.format(expression)) ret = ret.strip() return ret def exec_(self, command, data_consumer=None): ret, ret_err = self.exec_raw(command, data_consumer=data_consumer) if ret_err: raise PyboardError('exception', ret, ret_err) return ret def execfile(self, filename): with open(filename, 'rb') as f: pyfile = f.read() return self.exec_(pyfile) def get_time(self): t = str(self.eval('pyb.RTC().datetime()'), encoding='utf8')[1:-1].split(', ') return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6]) def fs_ls(self, src): cmd = "import uos\nfor f in uos.ilistdir(%s):\n" \ " print('{:12} {}{}'.format(f[3]if len(f)>3 else 0,f[0],'/'if f[1]&0x4000 else ''))" % \ (("'%s'" % src) if src else '') self.exec_(cmd, data_consumer=stdout_write_bytes) def fs_cat(self, src, chunk_size=256): cmd = "with open('%s') as f:\n while 1:\n" \ " b=f.read(%u)\n if not b:break\n print(b,end='')" % (src, chunk_size) self.exec_(cmd, data_consumer=stdout_write_bytes) def fs_get(self, src, dest, chunk_size=256): self.exec_("f=open('%s','rb')\nr=f.read" % src) with open(dest, 'wb') as f: while True: data = bytearray() self.exec_("print(r(%u))" % chunk_size, data_consumer=lambda d:data.extend(d)) assert data.endswith(b'\r\n\x04') data = eval(str(data[:-3], 'ascii')) if not data: break f.write(data) self.exec_("f.close()") def fs_put(self, src, dest, chunk_size=256): self.exec_("f=open('%s','wb')\nw=f.write" % dest) with open(src, 'rb') as f: while True: data = f.read(chunk_size) if not data: break if sys.version_info < (3,): self.exec_('w(b' + repr(data) + ')') else: self.exec_('w(' + repr(data) + ')') self.exec_("f.close()") def fs_mkdir(self, dir): self.exec_("import uos\nuos.mkdir('%s')" % dir) def fs_rmdir(self, dir): self.exec_("import uos\nuos.rmdir('%s')" % dir) def fs_rm(self, src): self.exec_("import uos\nuos.remove('%s')" % src) # in Python2 exec is a keyword so one must use "exec_" # but for Python3 we want to provide the nicer version "exec" setattr(Pyboard, "exec", Pyboard.exec_) def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', password='python'): pyb = Pyboard(device, baudrate, user, password) pyb.enter_raw_repl() output = pyb.execfile(filename) stdout_write_bytes(output) pyb.exit_raw_repl() pyb.close() def filesystem_command(pyb, args): def fname_remote(src): if src.startswith(':'): src = src[1:] return src def fname_cp_dest(src, dest): src = src.rsplit('/', 1)[-1] if dest is None or dest == '': dest = src elif dest == '.': dest = './' + src elif dest.endswith('/'): dest += src return dest cmd = args[0] args = args[1:] try: if cmd == 'cp': srcs = args[:-1] dest = args[-1] if srcs[0].startswith('./') or dest.startswith(':'): op = pyb.fs_put fmt = 'cp %s :%s' dest = fname_remote(dest) else: op = pyb.fs_get fmt = 'cp :%s %s' for src in srcs: src = fname_remote(src) dest2 = fname_cp_dest(src, dest) print(fmt % (src, dest2)) op(src, dest2) else: op = {'ls': pyb.fs_ls, 'cat': pyb.fs_cat, 'mkdir': pyb.fs_mkdir, 'rmdir': pyb.fs_rmdir, 'rm': pyb.fs_rm}[cmd] if cmd == 'ls' and not args: args = [''] for src in args: src = fname_remote(src) print('%s :%s' % (cmd, src)) op(src) except PyboardError as er: print(str(er.args[2], 'ascii')) pyb.exit_raw_repl() pyb.close() sys.exit(1) _injected_import_hook_code = """\ import uos, uio class _FS: class File(uio.IOBase): def __init__(self): self.off = 0 def ioctl(self, request, arg): return 0 def readinto(self, buf): buf[:] = memoryview(_injected_buf)[self.off:self.off + len(buf)] self.off += len(buf) return len(buf) mount = umount = chdir = lambda *args: None def stat(self, path): if path == '_injected.mpy': return tuple(0 for _ in range(10)) else: raise OSError(-2) # ENOENT def open(self, path, mode): return self.File() uos.mount(_FS(), '/_') uos.chdir('/_') from _injected import * uos.umount('/_') del _injected_buf, _FS """ def main(): import argparse cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.') cmd_parser.add_argument('--device', default='/dev/ttyACM0', help='the serial device or the IP address of the pyboard') cmd_parser.add_argument('-b', '--baudrate', default=115200, help='the baud rate of the serial device') cmd_parser.add_argument('-u', '--user', default='micro', help='the telnet login username') cmd_parser.add_argument('-p', '--password', default='python', help='the telnet login password') cmd_parser.add_argument('-c', '--command', help='program passed in as string') cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available') cmd_parser.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]') cmd_parser.add_argument('-f', '--filesystem', action='store_true', help='perform a filesystem action') cmd_parser.add_argument('files', nargs='*', help='input files') args = cmd_parser.parse_args() # open the connection to the pyboard try: pyb = Pyboard(args.device, args.baudrate, args.user, args.password, args.wait) except PyboardError as er: print(er) sys.exit(1) # run any command or file(s) if args.command is not None or args.filesystem or len(args.files): # we must enter raw-REPL mode to execute commands # this will do a soft-reset of the board try: pyb.enter_raw_repl() except PyboardError as er: print(er) pyb.close() sys.exit(1) def execbuffer(buf): try: ret, ret_err = pyb.exec_raw(buf, timeout=None, data_consumer=stdout_write_bytes) except PyboardError as er: print(er) pyb.close() sys.exit(1) except KeyboardInterrupt: sys.exit(1) if ret_err: pyb.exit_raw_repl() pyb.close() stdout_write_bytes(ret_err) sys.exit(1) # do filesystem commands, if given if args.filesystem: filesystem_command(pyb, args.files) args.files.clear() # run the command, if given if args.command is not None: execbuffer(args.command.encode('utf-8')) # run any files for filename in args.files: with open(filename, 'rb') as f: pyfile = f.read() if filename.endswith('.mpy') and pyfile[0] == ord('M'): pyb.exec_('_injected_buf=' + repr(pyfile)) pyfile = _injected_import_hook_code execbuffer(pyfile) # exiting raw-REPL just drops to friendly-REPL mode pyb.exit_raw_repl() # if asked explicitly, or no files given, then follow the output if args.follow or (args.command is None and not args.filesystem and len(args.files) == 0): try: ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes) except PyboardError as er: print(er) sys.exit(1) except KeyboardInterrupt: sys.exit(1) if ret_err: pyb.close() stdout_write_bytes(ret_err) sys.exit(1) # close the connection to the pyboard pyb.close() if __name__ == "__main__": main() micropython-1.12/tools/pydfu.py000077500000000000000000000454061357706137100166770ustar00rootroot00000000000000#!/usr/bin/env python # This file is part of the OpenMV project. # Copyright (c) 2013/2014 Ibrahim Abdelkader # This work is licensed under the MIT license, see the file LICENSE for # details. """This module implements enough functionality to program the STM32F4xx over DFU, without requiring dfu-util. See app note AN3156 for a description of the DFU protocol. See document UM0391 for a dscription of the DFuse file. """ from __future__ import print_function import argparse import collections import re import struct import sys import usb.core import usb.util import zlib # VID/PID __VID = 0x0483 __PID = 0xdf11 # USB request __TIMEOUT __TIMEOUT = 4000 # DFU commands __DFU_DETACH = 0 __DFU_DNLOAD = 1 __DFU_UPLOAD = 2 __DFU_GETSTATUS = 3 __DFU_CLRSTATUS = 4 __DFU_GETSTATE = 5 __DFU_ABORT = 6 # DFU status __DFU_STATE_APP_IDLE = 0x00 __DFU_STATE_APP_DETACH = 0x01 __DFU_STATE_DFU_IDLE = 0x02 __DFU_STATE_DFU_DOWNLOAD_SYNC = 0x03 __DFU_STATE_DFU_DOWNLOAD_BUSY = 0x04 __DFU_STATE_DFU_DOWNLOAD_IDLE = 0x05 __DFU_STATE_DFU_MANIFEST_SYNC = 0x06 __DFU_STATE_DFU_MANIFEST = 0x07 __DFU_STATE_DFU_MANIFEST_WAIT_RESET = 0x08 __DFU_STATE_DFU_UPLOAD_IDLE = 0x09 __DFU_STATE_DFU_ERROR = 0x0a _DFU_DESCRIPTOR_TYPE = 0x21 # USB device handle __dev = None # Configuration descriptor of the device __cfg_descr = None __verbose = None # USB DFU interface __DFU_INTERFACE = 0 # Python 3 deprecated getargspec in favour of getfullargspec, but # Python 2 doesn't have the latter, so detect which one to use import inspect getargspec = getattr(inspect, 'getfullargspec', inspect.getargspec) if 'length' in getargspec(usb.util.get_string).args: # PyUSB 1.0.0.b1 has the length argument def get_string(dev, index): return usb.util.get_string(dev, 255, index) else: # PyUSB 1.0.0.b2 dropped the length argument def get_string(dev, index): return usb.util.get_string(dev, index) def find_dfu_cfg_descr(descr): if len(descr) == 9 and descr[0] == 9 and descr[1] == _DFU_DESCRIPTOR_TYPE: nt = collections.namedtuple('CfgDescr', ['bLength', 'bDescriptorType', 'bmAttributes', 'wDetachTimeOut', 'wTransferSize', 'bcdDFUVersion']) return nt(*struct.unpack(' 1: raise ValueError("Multiple DFU devices found") __dev = devices[0] __dev.set_configuration() # Claim DFU interface usb.util.claim_interface(__dev, __DFU_INTERFACE) # Find the DFU configuration descriptor, either in the device or interfaces __cfg_descr = None for cfg in __dev.configurations(): __cfg_descr = find_dfu_cfg_descr(cfg.extra_descriptors) if __cfg_descr: break for itf in cfg.interfaces(): __cfg_descr = find_dfu_cfg_descr(itf.extra_descriptors) if __cfg_descr: break # Get device into idle state for attempt in range(4): status = get_status() if status == __DFU_STATE_DFU_IDLE: break elif (status == __DFU_STATE_DFU_DOWNLOAD_IDLE or status == __DFU_STATE_DFU_UPLOAD_IDLE): abort_request() else: clr_status() def abort_request(): """Sends an abort request.""" __dev.ctrl_transfer(0x21, __DFU_ABORT, 0, __DFU_INTERFACE, None, __TIMEOUT) def clr_status(): """Clears any error status (perhaps left over from a previous session).""" __dev.ctrl_transfer(0x21, __DFU_CLRSTATUS, 0, __DFU_INTERFACE, None, __TIMEOUT) def get_status(): """Get the status of the last operation.""" stat = __dev.ctrl_transfer(0xA1, __DFU_GETSTATUS, 0, __DFU_INTERFACE, 6, 20000) # print (__DFU_STAT[stat[4]], stat) return stat[4] def mass_erase(): """Performs a MASS erase (i.e. erases the entire device.""" # Send DNLOAD with first byte=0x41 __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE, "\x41", __TIMEOUT) # Execute last command if get_status() != __DFU_STATE_DFU_DOWNLOAD_BUSY: raise Exception("DFU: erase failed") # Check command state if get_status() != __DFU_STATE_DFU_DOWNLOAD_IDLE: raise Exception("DFU: erase failed") def page_erase(addr): """Erases a single page.""" if __verbose: print("Erasing page: 0x%x..." % (addr)) # Send DNLOAD with first byte=0x41 and page address buf = struct.pack(" 0: write_size = size if not mass_erase_used: for segment in mem_layout: if addr >= segment['addr'] and \ addr <= segment['last_addr']: # We found the page containing the address we want to # write, erase it page_size = segment['page_size'] page_addr = addr & ~(page_size - 1) if addr + write_size > page_addr + page_size: write_size = page_addr + page_size - addr page_erase(page_addr) break write_memory(addr, data[:write_size], progress, elem_addr, elem_size) data = data[write_size:] addr += write_size size -= write_size if progress: progress(elem_addr, addr - elem_addr, elem_size) def cli_progress(addr, offset, size): """Prints a progress report suitable for use on the command line.""" width = 25 done = offset * width // size print("\r0x{:08x} {:7d} [{}{}] {:3d}% " .format(addr, size, '=' * done, ' ' * (width - done), offset * 100 // size), end="") try: sys.stdout.flush() except OSError: pass # Ignore Windows CLI "WinError 87" on Python 3.6 if offset == size: print("") def main(): """Test program for verifying this files functionality.""" global __verbose # Parse CMD args parser = argparse.ArgumentParser(description='DFU Python Util') #parser.add_argument("path", help="file path") parser.add_argument( "-l", "--list", help="list available DFU devices", action="store_true", default=False ) parser.add_argument( "-m", "--mass-erase", help="mass erase device", action="store_true", default=False ) parser.add_argument( "-u", "--upload", help="read file from DFU device", dest="path", default=False ) parser.add_argument( "-v", "--verbose", help="increase output verbosity", action="store_true", default=False ) args = parser.parse_args() __verbose = args.verbose if args.list: list_dfu_devices(idVendor=__VID, idProduct=__PID) return init() if args.mass_erase: print ("Mass erase...") mass_erase() if args.path: elements = read_dfu_file(args.path) if not elements: return print("Writing memory...") write_elements(elements, args.mass_erase, progress=cli_progress) print("Exiting DFU...") exit_dfu() return print("No command specified") if __name__ == '__main__': main() micropython-1.12/tools/tinytest-codegen.py000077500000000000000000000074321357706137100210320ustar00rootroot00000000000000#!/usr/bin/env python3 import os, sys from glob import glob from re import sub import argparse def escape(s): s = s.decode() lookup = { '\0': '\\0', '\t': '\\t', '\n': '\\n\"\n\"', '\r': '\\r', '\\': '\\\\', '\"': '\\\"', } return "\"\"\n\"{}\"".format(''.join([lookup[x] if x in lookup else x for x in s])) def chew_filename(t): return { 'func': "test_{}_fn".format(sub(r'/|\.|-', '_', t)), 'desc': t } def script_to_map(test_file): r = {"name": chew_filename(test_file)["func"]} with open(test_file, "rb") as f: r["script"] = escape(f.read()) with open(test_file + ".exp", "rb") as f: r["output"] = escape(f.read()) return r test_function = ( "void {name}(void* data) {{\n" " static const char pystr[] = {script};\n" " static const char exp[] = {output};\n" ' printf("\\n");\n' " upytest_set_expected_output(exp, sizeof(exp) - 1);\n" " upytest_execute_test(pystr);\n" ' printf("result: ");\n' "}}" ) testcase_struct = ( "struct testcase_t {name}_tests[] = {{\n{body}\n END_OF_TESTCASES\n}};" ) testcase_member = ( " {{ \"{desc}\", {func}, TT_ENABLED_, 0, 0 }}," ) testgroup_struct = ( "struct testgroup_t groups[] = {{\n{body}\n END_OF_GROUPS\n}};" ) testgroup_member = ( " {{ \"{name}\", {name}_tests }}," ) ## XXX: may be we could have `--without ` argument... # currently these tests are selected because they pass on qemu-arm test_dirs = ('basics', 'micropython', 'misc', 'extmod', 'float', 'inlineasm', 'qemu-arm',) # 'import', 'io',) exclude_tests = ( # pattern matching in .exp 'basics/bytes_compare3.py', 'extmod/ticks_diff.py', 'extmod/time_ms_us.py', 'extmod/uheapq_timeq.py', # unicode char issue 'extmod/ujson_loads.py', # doesn't output to python stdout 'extmod/ure_debug.py', 'extmod/vfs_basic.py', 'extmod/vfs_fat_ramdisk.py', 'extmod/vfs_fat_fileio.py', 'extmod/vfs_fat_fsusermount.py', 'extmod/vfs_fat_oldproto.py', # rounding issues 'float/float_divmod.py', # requires double precision floating point to work 'float/float2int_doubleprec_intbig.py', 'float/float_parse_doubleprec.py', # inline asm FP tests (require Cortex-M4) 'inlineasm/asmfpaddsub.py', 'inlineasm/asmfpcmp.py', 'inlineasm/asmfpldrstr.py', 'inlineasm/asmfpmuldiv.py','inlineasm/asmfpsqrt.py', # different filename in output 'micropython/emg_exc.py', 'micropython/heapalloc_traceback.py', # pattern matching in .exp 'micropython/meminfo.py', # needs sys stdfiles 'misc/print_exception.py', # settrace .exp files are too large 'misc/sys_settrace_loop.py', 'misc/sys_settrace_generator.py', 'misc/sys_settrace_features.py', ) output = [] tests = [] argparser = argparse.ArgumentParser(description='Convert native MicroPython tests to tinytest/upytesthelper C code') argparser.add_argument('--stdin', action="store_true", help='read list of tests from stdin') args = argparser.parse_args() if not args.stdin: for group in test_dirs: tests += [test for test in glob('{}/*.py'.format(group)) if test not in exclude_tests] else: for l in sys.stdin: tests.append(l.rstrip()) output.extend([test_function.format(**script_to_map(test)) for test in tests]) testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests] output.append(testcase_struct.format(name="", body='\n'.join(testcase_members))) testgroup_members = [testgroup_member.format(name=group) for group in [""]] output.append(testgroup_struct.format(body='\n'.join(testgroup_members))) ## XXX: may be we could have `--output ` argument... # Don't depend on what system locale is set, use utf8 encoding. sys.stdout.buffer.write('\n\n'.join(output).encode('utf8')) micropython-1.12/tools/uf2conv.py000077500000000000000000000243011357706137100171210ustar00rootroot00000000000000#!/usr/bin/env python3 # Microsoft UF2 # # The MIT License (MIT) # # Copyright (c) Microsoft Corporation # # All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import sys import struct import subprocess import re import os import os.path import argparse UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected UF2_MAGIC_END = 0x0AB16F30 # Ditto families = { 'SAMD21': 0x68ed2b88, 'SAMD51': 0x55114460, 'NRF52': 0x1b57745f, 'STM32F1': 0x5ee21072, 'STM32F4': 0x57755a57, 'ATMEGA32': 0x16573617, } INFO_FILE = "/INFO_UF2.TXT" appstartaddr = 0x2000 familyid = 0x0 def is_uf2(buf): w = struct.unpack(" 476: assert False, "Invalid UF2 data size at " + ptr newaddr = hd[3] if curraddr == None: appstartaddr = newaddr curraddr = newaddr padding = newaddr - curraddr if padding < 0: assert False, "Block out of order at " + ptr if padding > 10*1024*1024: assert False, "More than 10M of padding needed at " + ptr if padding % 4 != 0: assert False, "Non-word padding size at " + ptr while padding > 0: padding -= 4 outp += b"\x00\x00\x00\x00" outp += block[32 : 32 + datalen] curraddr = newaddr + datalen return outp def convert_to_carray(file_content): outp = "const unsigned char bindata[] __attribute__((aligned(16))) = {" for i in range(len(file_content)): if i % 16 == 0: outp += "\n" outp += "0x%02x, " % ord(file_content[i]) outp += "\n};\n" return outp def convert_to_uf2(file_content): global familyid datapadding = b"" while len(datapadding) < 512 - 256 - 32 - 4: datapadding += b"\x00\x00\x00\x00" numblocks = (len(file_content) + 255) // 256 outp = b"" for blockno in range(numblocks): ptr = 256 * blockno chunk = file_content[ptr:ptr + 256] flags = 0x0 if familyid: flags |= 0x2000 hd = struct.pack(b"= 3 and words[1] == "2" and words[2] == "FAT": drives.append(words[0]) else: rootpath = "/media" if sys.platform == "darwin": rootpath = "/Volumes" elif sys.platform == "linux": tmp = rootpath + "/" + os.environ["USER"] if os.path.isdir(tmp): rootpath = tmp for d in os.listdir(rootpath): drives.append(os.path.join(rootpath, d)) def has_info(d): try: return os.path.isfile(d + INFO_FILE) except: return False return list(filter(has_info, drives)) def board_id(path): with open(path + INFO_FILE, mode='r') as file: file_content = file.read() return re.search("Board-ID: ([^\r\n]*)", file_content).group(1) def list_drives(): for d in get_drives(): print(d, board_id(d)) def write_file(name, buf): with open(name, "wb") as f: f.write(buf) print("Wrote %d bytes to %s." % (len(buf), name)) def main(): global appstartaddr, familyid def error(msg): print(msg) sys.exit(1) parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.') parser.add_argument('input', metavar='INPUT', type=str, nargs='?', help='input file (HEX, BIN or UF2)') parser.add_argument('-b' , '--base', dest='base', type=str, default="0x2000", help='set base address of application for BIN format (default: 0x2000)') parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible') parser.add_argument('-d' , '--device', dest="device_path", help='select a device path to flash') parser.add_argument('-l' , '--list', action='store_true', help='list connected devices') parser.add_argument('-c' , '--convert', action='store_true', help='do not flash, just convert') parser.add_argument('-f' , '--family', dest='family', type=str, default="0x0", help='specify familyID - number or name (default: 0x0)') parser.add_argument('-C' , '--carray', action='store_true', help='convert binary file to a C array, not UF2') args = parser.parse_args() appstartaddr = int(args.base, 0) if args.family.upper() in families: familyid = families[args.family.upper()] else: try: familyid = int(args.family, 0) except ValueError: error("Family ID needs to be a number or one of: " + ", ".join(families.keys())) if args.list: list_drives() else: if not args.input: error("Need input file") with open(args.input, mode='rb') as f: inpbuf = f.read() from_uf2 = is_uf2(inpbuf) ext = "uf2" if from_uf2: outbuf = convert_from_uf2(inpbuf) ext = "bin" elif is_hex(inpbuf): outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8")) elif args.carray: outbuf = convert_to_carray(inpbuf) ext = "h" else: outbuf = convert_to_uf2(inpbuf) print("Converting to %s, output size: %d, start address: 0x%x" % (ext, len(outbuf), appstartaddr)) if args.convert: drives = [] if args.output == None: args.output = "flash." + ext else: drives = get_drives() if args.output: write_file(args.output, outbuf) else: if len(drives) == 0: error("No drive to deploy.") for d in drives: print("Flashing %s (%s)" % (d, board_id(d))) write_file(d + "/NEW.UF2", outbuf) if __name__ == "__main__": main() micropython-1.12/tools/upip.py000066400000000000000000000205221357706137100165120ustar00rootroot00000000000000# # upip - Package manager for MicroPython # # Copyright (c) 2015-2018 Paul Sokolovsky # # Licensed under the MIT license. # import sys import gc import uos as os import uerrno as errno import ujson as json import uzlib import upip_utarfile as tarfile gc.collect() debug = False index_urls = ["https://micropython.org/pi", "https://pypi.org/pypi"] install_path = None cleanup_files = [] gzdict_sz = 16 + 15 file_buf = bytearray(512) class NotFoundError(Exception): pass def op_split(path): if path == "": return ("", "") r = path.rsplit("/", 1) if len(r) == 1: return ("", path) head = r[0] if not head: head = "/" return (head, r[1]) def op_basename(path): return op_split(path)[1] # Expects *file* name def _makedirs(name, mode=0o777): ret = False s = "" comps = name.rstrip("/").split("/")[:-1] if comps[0] == "": s = "/" for c in comps: if s and s[-1] != "/": s += "/" s += c try: os.mkdir(s) ret = True except OSError as e: if e.args[0] != errno.EEXIST and e.args[0] != errno.EISDIR: raise e ret = False return ret def save_file(fname, subf): global file_buf with open(fname, "wb") as outf: while True: sz = subf.readinto(file_buf) if not sz: break outf.write(file_buf, sz) def install_tar(f, prefix): meta = {} for info in f: #print(info) fname = info.name try: fname = fname[fname.index("/") + 1:] except ValueError: fname = "" save = True for p in ("setup.", "PKG-INFO", "README"): #print(fname, p) if fname.startswith(p) or ".egg-info" in fname: if fname.endswith("/requires.txt"): meta["deps"] = f.extractfile(info).read() save = False if debug: print("Skipping", fname) break if save: outfname = prefix + fname if info.type != tarfile.DIRTYPE: if debug: print("Extracting " + outfname) _makedirs(outfname) subf = f.extractfile(info) save_file(outfname, subf) return meta def expandhome(s): if "~/" in s: h = os.getenv("HOME") s = s.replace("~/", h + "/") return s import ussl import usocket warn_ussl = True def url_open(url): global warn_ussl if debug: print(url) proto, _, host, urlpath = url.split('/', 3) try: ai = usocket.getaddrinfo(host, 443, 0, usocket.SOCK_STREAM) except OSError as e: fatal("Unable to resolve %s (no Internet?)" % host, e) #print("Address infos:", ai) ai = ai[0] s = usocket.socket(ai[0], ai[1], ai[2]) try: #print("Connect address:", addr) s.connect(ai[-1]) if proto == "https:": s = ussl.wrap_socket(s, server_hostname=host) if warn_ussl: print("Warning: %s SSL certificate is not validated" % host) warn_ussl = False # MicroPython rawsocket module supports file interface directly s.write("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (urlpath, host)) l = s.readline() protover, status, msg = l.split(None, 2) if status != b"200": if status == b"404" or status == b"301": raise NotFoundError("Package not found") raise ValueError(status) while 1: l = s.readline() if not l: raise ValueError("Unexpected EOF in HTTP headers") if l == b'\r\n': break except Exception as e: s.close() raise e return s def get_pkg_metadata(name): for url in index_urls: try: f = url_open("%s/%s/json" % (url, name)) except NotFoundError: continue try: return json.load(f) finally: f.close() raise NotFoundError("Package not found") def fatal(msg, exc=None): print("Error:", msg) if exc and debug: raise exc sys.exit(1) def install_pkg(pkg_spec, install_path): data = get_pkg_metadata(pkg_spec) latest_ver = data["info"]["version"] packages = data["releases"][latest_ver] del data gc.collect() assert len(packages) == 1 package_url = packages[0]["url"] print("Installing %s %s from %s" % (pkg_spec, latest_ver, package_url)) package_fname = op_basename(package_url) f1 = url_open(package_url) try: f2 = uzlib.DecompIO(f1, gzdict_sz) f3 = tarfile.TarFile(fileobj=f2) meta = install_tar(f3, install_path) finally: f1.close() del f3 del f2 gc.collect() return meta def install(to_install, install_path=None): # Calculate gzip dictionary size to use global gzdict_sz sz = gc.mem_free() + gc.mem_alloc() if sz <= 65536: gzdict_sz = 16 + 12 if install_path is None: install_path = get_install_path() if install_path[-1] != "/": install_path += "/" if not isinstance(to_install, list): to_install = [to_install] print("Installing to: " + install_path) # sets would be perfect here, but don't depend on them installed = [] try: while to_install: if debug: print("Queue:", to_install) pkg_spec = to_install.pop(0) if pkg_spec in installed: continue meta = install_pkg(pkg_spec, install_path) installed.append(pkg_spec) if debug: print(meta) deps = meta.get("deps", "").rstrip() if deps: deps = deps.decode("utf-8").split("\n") to_install.extend(deps) except Exception as e: print("Error installing '{}': {}, packages may be partially installed".format( pkg_spec, e), file=sys.stderr) def get_install_path(): global install_path if install_path is None: # sys.path[0] is current module's path install_path = sys.path[1] install_path = expandhome(install_path) return install_path def cleanup(): for fname in cleanup_files: try: os.unlink(fname) except OSError: print("Warning: Cannot delete " + fname) def help(): print("""\ upip - Simple PyPI package manager for MicroPython Usage: micropython -m upip install [-p ] ... | -r import upip; upip.install(package_or_list, []) If is not given, packages will be installed into sys.path[1] (can be set from MICROPYPATH environment variable, if current system supports that).""") print("Current value of sys.path[1]:", sys.path[1]) print("""\ Note: only MicroPython packages (usually, named micropython-*) are supported for installation, upip does not support arbitrary code in setup.py. """) def main(): global debug global index_urls global install_path install_path = None if len(sys.argv) < 2 or sys.argv[1] == "-h" or sys.argv[1] == "--help": help() return if sys.argv[1] != "install": fatal("Only 'install' command supported") to_install = [] i = 2 while i < len(sys.argv) and sys.argv[i][0] == "-": opt = sys.argv[i] i += 1 if opt == "-h" or opt == "--help": help() return elif opt == "-p": install_path = sys.argv[i] i += 1 elif opt == "-r": list_file = sys.argv[i] i += 1 with open(list_file) as f: while True: l = f.readline() if not l: break if l[0] == "#": continue to_install.append(l.rstrip()) elif opt == "-i": index_urls = [sys.argv[i]] i += 1 elif opt == "--debug": debug = True else: fatal("Unknown/unsupported option: " + opt) to_install.extend(sys.argv[i:]) if not to_install: help() return install(to_install) if not debug: cleanup() if __name__ == "__main__": main() micropython-1.12/tools/upip_utarfile.py000066400000000000000000000045751357706137100204170ustar00rootroot00000000000000import uctypes # http://www.gnu.org/software/tar/manual/html_node/Standard.html TAR_HEADER = { "name": (uctypes.ARRAY | 0, uctypes.UINT8 | 100), "size": (uctypes.ARRAY | 124, uctypes.UINT8 | 11), } DIRTYPE = "dir" REGTYPE = "file" def roundup(val, align): return (val + align - 1) & ~(align - 1) class FileSection: def __init__(self, f, content_len, aligned_len): self.f = f self.content_len = content_len self.align = aligned_len - content_len def read(self, sz=65536): if self.content_len == 0: return b"" if sz > self.content_len: sz = self.content_len data = self.f.read(sz) sz = len(data) self.content_len -= sz return data def readinto(self, buf): if self.content_len == 0: return 0 if len(buf) > self.content_len: buf = memoryview(buf)[:self.content_len] sz = self.f.readinto(buf) self.content_len -= sz return sz def skip(self): sz = self.content_len + self.align if sz: buf = bytearray(16) while sz: s = min(sz, 16) self.f.readinto(buf, s) sz -= s class TarInfo: def __str__(self): return "TarInfo(%r, %s, %d)" % (self.name, self.type, self.size) class TarFile: def __init__(self, name=None, fileobj=None): if fileobj: self.f = fileobj else: self.f = open(name, "rb") self.subf = None def next(self): if self.subf: self.subf.skip() buf = self.f.read(512) if not buf: return None h = uctypes.struct(uctypes.addressof(buf), TAR_HEADER, uctypes.LITTLE_ENDIAN) # Empty block means end of archive if h.name[0] == 0: return None d = TarInfo() d.name = str(h.name, "utf-8").rstrip("\0") d.size = int(bytes(h.size), 8) d.type = [REGTYPE, DIRTYPE][d.name[-1] == "/"] self.subf = d.subf = FileSection(self.f, d.size, roundup(d.size, 512)) return d def __iter__(self): return self def __next__(self): v = self.next() if v is None: raise StopIteration return v def extractfile(self, tarinfo): return tarinfo.subf

S0yaWtuP^2:2R+C1Xj^zG[ dR G\obʾU,C`lmiҔw7 ٺd+wӐƐz>$n[ȥRz]b[ɺ<`TrAt^99g*HGk0}[ӣ F!jpsii> wZUzvl|yqҮV9Sܺ;㳍Í3Р4r:nH][(TOH.)7rqiO O1?T:<_~% V3Ǩf 3T`Xk54BO$LŹ雷xNAqgkzgjJ=7z[7pIPS#F \MD]y)X Ť_@ھT@_ &Z6^ӇIZc0`d`{*M{DQ}>mՂ#ɑ=^ UxT"\0' K@mָ8%̑ 4Xӭs! s] vP5p]GtLbUH0i7d>)x8O: }CwI,Rdo)qu{zW赦ͽcJIT,r@R28k#B.ŢSJ({od{z֗@c gQ@z"%w0Ѝǹo u5i8ءƁ_]&{ !,@|V30,V>^8QH(MUi#Q:$>bt{gRt 4sZ1l>T5OJXd5 XÚmH 7:بP3cc)(Ј#9 ENLD* *C A;Ã8.l `$iat:ݡo"2l]jmn&JƻFP"J; uV/|ֹ$*0@B^12}<Z*I_]=ԨY_y ;P xҡ6=i,itc{=A?iHD=vw+jP03Y,pd:AӗϟUoVH!yG|lQ򝳍Fz-ɑyffKm=٪B)^W/lBTPdLIJ)bw{mcxBݾ3suAHRdty0j]O^hyw/wv/06?7M-J4;{GVh ;]1#:eh'zUi>zNJ gA||&=7vwk0TMȴ))Q&@,#P]TD觽DEyTr'@2/hv)?_|yDЯd֍"QFNd钳:yo0A8ssSLE l~ޭǟ?&K7K BG'LM̆?$J$a" )ByY QTd7殥i؆(=]aTmvW_N.A"µRsY[jtC#n/3jٞkqʠFmSЏnp5umCACՊ L4Aq- :,cvjA$} 0BW8ʖcj?;6 I4Ya]2Q)ÜiN ΈǨ1B LsӚtZ)ԱP _5p{Q( QB.ҊOc>2udc#E[ѭ(!,g&WQxFK{vIaAP507AI&*`5#x+.幡"8)`+2e)%FАh &p_F^! hV ur^_s@:j j`8\J?t1C[X=|[2ba$𫠨Q(Mr*M^EnG_~0n>zQ&WX[} - vq~=QEQ*BFXߨ7B"g߿I$em!v7#lIDP>{x Ƙ0"վTf5+R;n͑Q9фf96'5 hʦ*Nw@:V}vxIoK lq/ӓi B& GHSP .4PןyhPZҭMR?5JԎ])3B.( ]hp^ҁg"5V7acEKJ6N򍹩s :ھg9>?螬m_UsQ0 \l T2EXFW^: 4SM^} 1`b+lfqfqSŻa 5 Ct|B9.=|> qMX?QT#Hj!ٻC˃XƘ5O'x&F 6\xuf8DIJ,{qEhр)2 5 *9 (m=a*&&lo݄S!fâF&{0d.e` Xz˘=m~3}(esB.g2ьV2JE^0\tٟpa!lT(!l% A^gžj.x2R`16Ŏ _kK8~f/,nRFaܥ]q/KB-u'vpg4\IЯ(f~&qpo t@TURi*z̷y V xw 9)tF)QTD~_7 Z B _kԖEF2 rBIK&a|)JL#T!^ӶEgXj4d*7HMx8P-)蟁.r!gs#4C0Ï1d*RϸϥѨmDW㳬7/ث!fJ&|ɸ& !T,ܾ}ͻ3pNwUZN;-_FÕY#e_qO<{W/!m{jay]wwVk㽣=`jv (l@tɧ;o¨DiCl?hw_̛gnikgq@ wML)Bƍ[?݋π3piGBpZ~"zWKJ27_g#ML]ycrz^Q7`X]{-#P>FTEP9Lt SkT|'|R;6K؜(\Ga2A-9s޼At),Nf~yqpZor$C]JWoyq)*8ǧ 펕Q0"LIޒݎ_.Cùۂ8bt,ͨPz솁si>3)mwTí`#>3 L2)GkۻyoN^+j8399}CP84{G0Lq:2n:A=Www/9 (8؃X?c]t&<'0YjԷNvA"* r45}}n:$Rz4 "5怫.qdƢ&(R^Ų6O2bS cvJX#?G2bb*CA 6qo&wTȞ$4ˈmĵU<SgJ%(tz‡g1)glHGb\K3D6Db6oD2 zjЁ # |&"m9> e2"%# qj4$Үw&&pY!!RIxHoّ2H]@e5ʀ B oБ/ZNK2H}?q]9[valHǹJR:lWZuoX*2"&c 5THZsFá^ZWc90!gF|E9A|rtŧ3lw( #'b#u8hϟ zҡ-$񗃳24h!9 ? _T!O# Y-!FΒFUE*#| V w샩w~Ջ~͝-GDS͵MNNoW/߹n?q+ +݃'Oo?;=;)erweMMO?ſk5:?=LyGo`RKeB"~@Rmy*]V`MI䍛׀E]ȏDy 7󋓳3JHe0/>HJ个~}yvn3 g~]};C THVO֡h\(åA$zsotǀvlAT媶>Wvw_x8'aIU <=092Z -)9&*nh5oѳ͊w^k ؕFNq؉)-t؆2Cy^>hkN="ac[XAKѾL4K |vadg"MDQU ( 3eɀ6#CW_qa2b E_ FH;[aS1F8٫xѾ1@.-*nmp<6o2o:R)Ё"j:vxz3]!A-6:ˬ '.. (~)I@Mr駅o= Ae:?v >Po@*T  JYA<>3?@Fbq|h̏Q@'aIZ;^.km5JGX hm<\pB%T(hn¿C$'46Hzhυ;RlKE9a%ySKh_aCki -ltM\@?-BAq+5R`1$(` {ѳ)r|-֗gC4ߩ>rgOe1d9LɊY Xzxx?m,lD׸yѬx M:o/.*gf}H.A*񔤊(K-lЛW[oެ:2ݿ>|eccͳg< ټj}{Ç o= qzt_|?䣅Fgk+^gKY_\8生 ._o(DG|G|oy}!;hi0BA H153IL L\~jJzV#19BTΝ`2ko* ȑjDn kU\:7GK{[L8!DRDQI&\N~q:R9jX*0Vjܝ*vyuϜH\y:ŝng4Jxc`wf}WDjuVݝSsakb!*U?om/C9 DF$@T;<{{H=IEz̾Jsi8T&Z;8`G~Ϟ?XqV?{vqq6 [+o7v(LMN_"^Zf޹i!#|~k?|oKc "4Q7[@5y\"Je$huvyx㳚&ph!1DKkIaR9JXO m"o6#WYALu2 'vTEoPM_T\B M.UzC5epx8֐eHs0Bf65a;~ ]0"v/_0஋Qr]3`^. S }-s+5 #Fz38 f2q?/2,Ɗ (ıvu٫'v ldls-(.ɕ^JޛɢDx7zHr:cϹvhR:ӣMeⶠ k7uSеJ*U#5qp/Щ!c e]d F]v6q}Vm=k]Nn~vq!%w} gNN-A\@p u.HXӓ n[bw,{˗/;dDKgj\քF8ko^" (FJe󳖈G?裏ÌQy@PMϟ?I.SN˭PϒꙃEx^)iNIu\p$.^\ )ԡ"*zX P}}RЍK獃axP,|ܗN4TKԠLO0t*!8zf'|#BF ׋k;hYLON:a H0(+*QΥ̜TO۸h 7iXEy9j'1cMG0,f*_Fĩv`-Sg J&,i--lѣf: %P4@T.P@_Ho8H762tજX$>]÷RTJD~+qo?% AX8<(tHBDv$tq67Ϟ=;\[^s 빀d+ &2^et%lXUQ YOpZƖgdSƆvUA SP6* Nѡl"$'FHOXsxnW:u gNC{VI+~pu4t c`|P6P8n?8m{J0)~+5^IŐ/bN" R 1~BuHţ1eP~,pG )=<^e%nIaRN j|F=Ma ; p*87x̬Q: `(fPQ@x0/WvqO1?4DGbnE̅y\Sb#U"/M & cFNt# (z^K c abhP=Jm2=N+k:}0TRb6 ~3%6xZ9e '^BqC8ˁ@]7^džh6Džjd5jSK"[dad ߃MgA_'.BCC6"CF" _R!" w `x=`{a4cSɷ0 Pj/$&"8P5Z98_h' R7/)⒤rVWHew6nΎ$?7oބ!d?__5P e\aD(7zO>{ 餶;+\V PZ|J1ObuX U({;[ɩP>>ً–e7V)ẽZ;"'ӅL~"T4hZWr9GK$kx_)"7wE9gc= M20JYD:拌{G{s">Ppg{vad3FlNO5$Ü;F7 Tkr$tB 2v6~߿Y_ 1/]J<sνŅ%I,gP~Xm)潘*a>4[@)#3W/ܥO~41*ؐ#4[^CR9=:ΎHaU bHdcJ#?;)쵛nͅGS ~݌:TFtRkavʑK1pXwHì&!>lTpp#_sGXQx u0ƛH,h[.Nl(%s~=lUl?{!vO0% (3V!NVIr/ BHPfN0?%iP0mfwb#v/چX\ ` .s>"r(1QbnƕN$EW;VރuaÊ1Ŗd OuVG*Ұ24^p| f?Vܙ\pУ$ǥMEa^2@ pcH8I=)Ϩmkm_ m~ɒ“ԏ.& !D]p.!HbV EȐ'] ȐfuE&jHzA;Cq9:0jѠPٸes%8TŐLXV6<֘2nɡ Øע(gotZ۵8 [|q!r FEsKo5-Bv7dk6ǹ##]Ω#8-6؛<"a`aa,˂벢㐡SAv FÁVݬiKeJ[aq1\OgV*n޺kMEMeXqBHFz#܉R*@K&bˋg;09rV9ͥ|$2 wn~_|߃N p˦JxTGEN{}s D]Ɩ"porE%$N4 ᑱn9 aN7 Pr!+#bN@X\pG@+xl",*wlnn֛#hT+ELt?A9]ur0>zG8")V_lLDt7:@ꮸK})P0,|:upxìggdSYNu@mHAfGki5ͣVt@c1ֺѷ-/BZ ltެ/!捻7nͭ0{uJ9 cw[O fsN2{wFJr$XuQr%m\ no[B4/F{IePa 0eMpd]!K0N! Ş%D50ʦJ1D ғ/5܏~h,z(yHJ0g0`_b=ΨX;p({vqb1Qe9R8# v@NXA2O%C@skTI("ƿ*ɎOMNΜ>ҁB$&=:6kAJ :=S):yE1QN͌d y.D!H-m| d]5FD=XlD ;+*{̌fUh<8!|pZT ]E$A-%RtXhZy;[K/,BOdl? Tv fnG)}j?Ŭt^^ٖH(AK`t[g=fi L8讃Süƫq ;4A(q3t8@HEJGenjeͮquҮͭ='8aW;*Of9ċ\*SyWB@Ymuْ?<9,&|qldtCx;;]c#lz<+dNW߬ `c=>^_yh8GYk4`"Ki~Rko/->~)0i7H yB쐻&xя>>/&@nbv 6Y EiUSk@(n9;y2̇m6P? 6^w h@STAbKYӣRav|cFӱ$8%#DV_Vz<өM]' tĘ] }a;8Q%y|УP-M\ߡM&ffZj#,+3b3hz ^b;Q\dJ;j2:(eD) Z [y͙2ueBxĆ {]u84CO+C .QU jt[LC K2s<%~Y*a /\]-xF $: h~*a<P @P~S,Csa(sE]b>r u(5F*0|SO@ꂤʐG7$1dz}XenL [8Q,}#pbs/#Ff: K>B2i@y]k6KB)$Ҳ1 [BxZZՁTza ѭ9biܾZ9,~["$`]ϕRoޞ,?14e^2fz9c!g2I gĤノ'Gb~9d]UdtZQ9$gg8}>]vgjf:7VxC73Z u.>(m` #gMjhW䥨KdG f꫍\|㉉kccX_ӽE]9y{VW?"wi0?vùϟ&w8r*nFATNԐO[u=Т^Ru*rx8v#@>(Q9gjfsu^ό|ލVu$":]88ji^ƕxs .ZuI)~:~389=ܖszVܔA^~dTZIґy%RZ+ڙ$-̗fr+5MS"D 4ݓnγR*:*ήn\0 t@=KF Y[n3B$xxqqtl |d`oЭ@&qi2ډB_%\.LPt(hAG0EF(I&KQ77k/&2핹e/.daP*5J)^%4aY.3YmBem=L+ABz` {)H0Du4>wXr7"~P* G5C0rW̲]4^_F|:;grq*BHRhtB/:ioHh-c"☧c0uod: 3P#ٚn˥4?D?YҤpL/}I61Sѧ6A :tܰhCHP`! I8{MgDMDPK p)?-#ko7n([ OݾwCuyN 3f PiBz,~=σ?Yہ,Icg7VofrDSB6 uv^ PQĥ^#P xE:#|8cQ!g0d˫\a l|g3:ԉWkD&h.+z2 =YPrM@K#OA.qB`wq/qU"VDiv6D*B?O".?b%A2f'n'B9eYHCD"ʲ'v6NMσȧ?ڏu;¹R;&2VB&Ri!:$g8#7܇ nR-ฺie}œQ@nbrO[Փ󃭋т׫:7_,,L,[L61>9.j{0Ï>|X* yӼm&L@4ɌMD;8kזZͰnJY\uvvQE\7 NWYV_:IrN gg c3G*ݱbZ?4 tS.ܤT7JFRфdt >D@ެuhڽvCV,}r"B€L!+ R?,AzFϪ';7gyvdjԛ.T{ǕZmГCفTDq|<tt2IJ%,肱I|q<녑QWB$Y=>pjj>_w$wZZS̬ Ó\!WL¡;f[9.*[IEOipy4:&fǛAY9/eg's˝񻋋K U[dڨ X8Y@7\K` mYLl3Hs(ҋa"ӭR-;w_k@ke,Wl@5*(1r@pmć Y6 dSaUNDd >{>5&ޱxY"8\M{sb #jdc\{'՚%G LPuR^)r 7fj޴$[`vH¹զFe?1!$ Fm.`,J'b\D+i(* An ceg"`$Gl&bb- X ВÀt;sieGXri yO 4F:45cEFzqy$/2](K\z٢qrΝHX8==c4z`J#th*d"MBRhG*8  3HkAaoMri~'1;wE}KE Nj]kEQ8iHlJj|1OWx@\?XZjXI>t{~dO&ABav(TZEm&*P 1b0l{_LWbXIzt@c}ynF-n6-m,VyU 2{XV~\-Z;, iPxՐMۦ@篿ѣG)NMOx+H3CԞZ]quhl@+7~jWF4}Vm{gmjzfֽÎB@!_o,[;ך*Pvw6N<{oByaql<~skOΎ+6v@c@?;<: J߹qGT*!H) TrxE'~N#FuW+LGo ؤ^B-!~yxc7!n,F xrfu1`dvOrL88eGG<~{NU,~}p|v2`ͶfNN1P$ ;=g pl(Yf<53yr8(^oR1?͜71ີmucV)q8\땍o{{i]XEw^u{=W:.̸&8촥wnlXy]󃥙{s7i@t0uny:} TJUjGo^|u*y;>7ȵkH[B`IoWZ۠T8= r6 AJ?R#BRR2)=X@`czcr*Q~7:,=> ?iM NvAݟX NÚSǞۢx hzAoۙBá6\3"n%m zȤ33HO8zϑ5\o@U %4ǰ跇yO6bX,z.2nlD?Hē>ě #Wl_VHa++K\JRĄG)7mOO9KvӰ6 Z9 & dJQ/!mݫ%%0Σ.f9eMȘ7>PS0+>adx]^4V4LIӹ, nYila/ H]ڣB(̨gʄlŎ+ҘU8P -\3B0;JB,ȞڎQǵz~(zgZy.-0Xŝ#E!'x333 S$7)Rܿ닟T FSR< o,R`Ϙ5n4[f㣂@Si٥ݾpomeA4yܠ=,oGF|Ix.iVݽ{XO~͍7+_xuRqVHX>.4'ӯ 3@䋣Z3t&c`0 #ł;κnH.eק3i/':0L`%O!-/JʫϞkw|ј.rD!oyKR|x✘rAC[>6δgo2w6vKG%Vl7`f([Qo7jԤ:G{BeFG ˉeAƢR P KL AIRPj>wb&FE,mm InHyjr"BlEN3t `N5SS`ѕÓT[$~|\X;)s|X 7R8]n@%N 'B9c"VȤ {`-> rrSKlfm}ogo;Iݾs?ywrxrinR[`x5wOy] ]][}=s{>Ï@GOMɋͅ~ӗ^~~ȁ X* @nl/w!D{=>6<3=,"椎"gBb 0c  ~6C_͓o%<7ڤ D;yd@1i/k#Koxcc 5[, )2?ЧMG)Mظ }eBsӔ=||9y;Ea%Kmhl軚fE>aP(?*@OpR;[1h*) `bP9rRDo?"@X3;1^ g˃QɸB_ΌuÅT_{$&DnYx&p[^6%5DOP(SmDŽBf> ASe] pIt 4s$V\IJϭ&\RɵfF9^:H,?Z kul*3 /EQ k()~EɋWJ3×!|l kp:a(Ψ+akF" NnHIϪgw:Ihޟ.sY;nX `I"8J7yu[N\p^ ۵f0*G9?S>^SGm)O# SVCɏʦ[q%YB+FT^>ēL-ެmUݽwQLq!2?W!Ɠh]\̤YGdjT.<]?SHQv2NP]ȥ2䕊=;W)Ɠ=9m)/]_ȿXY9o::Xݮm(`vbng ɧSTKR5r5qAJd Y:ԡA,<[!zUݧ3kȟ ;Ƙ/Xa\ٮU`_Q-vXN XKtSwx;.woCdaFjQ?1!d\͍㉠p=d1Q FaN×xjiHV}$BMU(fE%!ᇊNGN$̀Յ epo ўj훱KGɡ>V"Y'(TC/]IL qy,BL `-K d,e p/ӰLBAzYE‚=؄sfCfOFA,Ytw]谣ier8w̔{"_NNO=t>>\_I(r16HByXB&&Z`вqφgjrEOQ(H&5o ck,];BAڡ)Ow b+mh|tPEghI\Q:\ mDB9+߄ ͸e|lvqb #Af t yq a~zqc>Ц2f=:6%CLʓ3Q3K/~?sAP;T:Vc/ً(h_v3_\TN!}d~ajvvl//\ZXޖ>{k7?yz(htdAϑ0lYKhsSs `uѼ2DTM3k 'ϟ}jdqn "'mLu@ǀ|ks79,@tKPS@Ea)e E> =[P2PD= Oat^7[erfzN:eF#YQ~o:z ourk7-ϕ^~΂ƊL&$2Tg; j;PNQ$( BpOyL)YAs@,eogYCzrj4Z:q } ՋCIn_Qs/6VaGr9%.ڡh F0J0t:`i>11JQb(> 4C8Թ) 鰇UB`+Iml;<@f"y;# pB/ G/qBi#D/I $Ώ;h5rS`e ّ0]i f$p*7&& *Y6ȊI yZE6 Nlu[?d4(>D=VI&Nx Rx{Tcu} .*WޜR. Jvq0wx>ɦNJ :RAs{{M9 VƆ?Ə>X[(;^{fl<1_ {Bwgf@ dv;~ /T4~c.Zo|ۮ3RNOuxƵ<ADYH/Rĵ[|%msv/'_n{!r~DFM?k"`}6FnP2I,'W i1$q; ,b=W,Dp{JC2<@)Q=mi@ S5c§VKL[ Ig]vBˋq&JGi6Ji'bpbwh0 |DbBJE^b¸*zQ+:RǤ9+)1h☼<̰W_wh3u&$ݎQ]M 3T̠1p'K2a 3(V/d5a& Oet~M$9&}eif^g[5ưq.i_w˨;L=V~vb 71􅁩oq? sk!u=!fR^!O e6:ʸ#+)If=;@,ٱBVݓWk 3y ǂhV.-/.ponc^qD(lC*i5ˬpz!"+! .ln'2ݧH% ͝kޚN 5HA-ᠿ$k_BO5@l@6\ Tև`:*}{=K&ehrPug&Nn^(Zʗ?KGv J_WDlwVlW+%`4M))zI=lDYzꇩJ"I_}+ JQx)/0Sة0 &z4Ą\ Q(98RW+zD?)p`Q*z}|t~vvwAuT07Zg&h Jr:dA^rnr,˼NvbitpL0+J)6Lȼ0mx\LO9ck['՚ VrP]%<[;?>}<: ;01WP.dIhG'J҇owܚu4gXnzMh 9d|@e嫯>+GAdGM@F>}|=PV~XMi0"h7]G_$)EAk !X T6Q.rZ[Nu܅|ȭas}ۍS 7'p$DV&B.#$pZFP i0e]YhՑО+[AeJ_G90ŕ [+8 +%"?‡4xaço#F{6D3^Hپ\$f ,2ۚǤ6[vG{*N FnE D@KYf aRaƢh{hsOS(P/IMBtdDxXQq-6kИT]KKF"ĝ[_Fgۺ$q!` /rt)- TDM3X#:zmⲈϸ>zGC}(5',M#bՒL%OBm)&HZ ҃/Sxg]*wck(Moa_ !z{e57w#FM${ }$ ?nę1sj$IgTM&2a)TY7' m1>&!! (Q=ag`fD_){<@ѱDog5`hRI+2d*C*gxs:oe@(E;2hm3յۈThϽ-ۻ0z+k00ۺ>|WB _o4/w\A1ya4NÅ>{=Svv&4.qe:#Ƨ[4t%u 0hr(,I8/ g8XBb1/7%>*6Z1JP|JuF߲]q23!!@p# V@DD 2%4S"~uIaQ1Kig{"nZS:u?Gf. x!T0ǐԥAHa+g]IJ VI ߾&k~3x^By$' 7C,6pzo Q"S*8Au*ޥ ékHͮQEa*|}Ge $lOL"*/*EB^ nsEjVnhzLDF% YPs܀EA@9A:kyᛩX3oPkRj)q'"#_ 7-}fؽK0+L/Q>Fm~;a s1IH(iw*Ջy 4hL&J*7'◃=2x=ǣa]^mLAB@Y73(KLW? OWlI vW+# ,E1AAF|MGCYVk+412գl1T'Z<0;ѣ0i͍lPL)Ht(#| b?\^^)f$A=:Q8sRvӥ "I٨@j{1v111:>^&&GF̈́{swo8h9K]$yT2m#sC40N*"z t5+#(z&7gb+E !( :͎53^V[;۔HMy("H.J(%N^)r) C RG@{8et#CQz‘Q TZ \)Ȳӹ(rV 74.m?pj.)N1E$w!vwa~ Q988<؃+*򞛌")Ȧ߼w53-Ez EGnn&&|{՟gw_|sz:4g)$^lr2V%玗rfMfaU9r #m G Q*CHoM0`9mA/Orcv+~+TRL4bn_C.3LV y/FЇ f n%p<ʼnqg҂.%qA̎ԌU#иݾ>Cȋ.k*`E 8~ ;RF*}]l/G Y+Yң%2dD)ރT) ^ sNprҞ py5aqtI F]cxi#5IH &P g9=D+՛"0ADP(f+\Kɳȸ  ׽Qx|( Tx oW2ԁ !Dư*1v\`Fy6.8`^ٓ'g)R!+PLT se -<>է>d־W4tCj0^Y>V5p˽<ᠿ=*ޠR[Wh~?L'GZ-=`&a2A"hjM`@`0^Man66SF'P5C=,kp8zqu|& y +W ^@6B}AP]CXHLAgVuQF Τ $ V& 9-,Ldt(R'B zlw>Yk^>".ܾ n0Jeyth8l6 D1SrO۝aqiRVCK=|I2pnnmC0d<nro{aYzgko"$HW'h-7o7O_0,Jr^8ʂ8덟 bxlUΐclix:݇C}8fBLǍQj5Cˏ. 't R궵Z晠u;5,7 z El2`1`Ҹ@@Z՛_}9hn,(3Qt's9z! ^9A;p<4w0j;NL<붏Ns jl!-x ;hn cKw5 ?f=#1=+ׁ90!~BJ n7 JF_WڭmY p@Hdd-wޜOݟ˴Cz.a;~?KǙ|ڍŇ?=ɳko67]mW\VUv ~ݼ[5 0)j'OQE]T*8ϧs͔{ww~_ nXч 9umʣzx{i |:>>"tKi&|S879iƋBn"'͍۷zr拠͎=~i^ZIEôK. :e IۓH8ԁޛ.QX*i6( `15=gfsRxԃkq1 ֵjڣ\8:b],nKABJbLήZfMpdFA:4lhsQ?< l'6h$΀=Rf'#A y8n johynq|tl _y$TKpy$p ֫O677GF?Ϧ#+^L%?6˯OA/ 4pNNwv^wG Ctz,]ˇUV?z$l:./~\^k0p9Q3Ev £CQ]iH$s[Kb: Ԥ!qY|γ%ûE]rYNQ$QuYϬW"8fW#0`@P[,) c8Xp9ẃ@v W9Y;m" X4庚p؋DЧ%0lN L0!:Dq)(XBM4OZ 5h2a F I.BxOHq/ F=~`/m_2@/]ZLA٩ȟ= .mepQ5"0PM۾hPCk՗|3Q?sɞI| ecD,# p#cۆ 0t4HgqhҮqP2mh7?ܮs C/ 2q?-S>^xlp(c/?W/;̭vtAuYlB/沒jϦ7AxM&߱zɳV:=9qΝO?Z|qXd㬶73_NT2MW'GZˑ`:t l)!8;/|*+off^1$W L{ f+f'lwt,%lK;] |[%|eGP7z2Fsq:PjQ[UbfAtxp65VTa׈x.$q|rzu/ 8q|^g\ȳMÍ؅Vak%L"2BNkU @:܀{?b'gpK2 J"""SL?H*Nj7޼CD~4(Eq :{;0vrqajnqv ωD_%u>咰(rIAp@ i6ȇs+6V51\dWZ_x]>ӗNFq"N<(-\>qiVL D0% ӚǺ1H(p=NM(`MRkJǚueUˋJjV}X\[KG^B!;0|ԗ䫨g'8LJ6kA|O.FF>9:_\\%!a‘SkfpW9r3Z&/L''g޺dフNyQ&\:UU2>rnިF B?M=BF5VfQj&]#K-O5ŝq"n& N47kmPȥ"&gRGE%|?Cn -~鑯z|fp-KSm/҉al SW>M nKM}XQkBQ [^aRr=l;HGc b 7MHzq^ҏ#eTt%$(j R )QnLMĂx=xRVqNm_sz8ӵCGFM#5{8YفeZY[FoV"2pV1Ȩ%b}M<Ɉh`=?7coŲΧu :_^yVFxF!Vؾ͆E= 2־O)`+`T*s)ga.H0t;GMa ZZ{u|hsGKX巗kp LރxQvsB,/O٧<E@`: ƒqK Ɩ:d w(J&,?z%.ccA1jt~\pZl8W" ZwY'o>y;7?|xZ'0 F)!]_vQ@8?;:;=qT/ZBjffO>Z?JuP)$/HIaeNZN|KJ':^j6t&YLyFͷ_mUk]wKh ~ \$}>^{~xzQM^H#A&Վ2xs@NKB a996NL'ъ"dT;n7U$ WP@Yf2j KT59sr' }GHc92#`꤁@ARZCT\vԑVWܑbr W@tbJcEy]\f Vpt?p݄$:8:`'~=WJ~x\LۍzvK07&ri./E) )TFY/cwHIڤNH t@eegw=g^!yxQ 67_ٓg_U6ܼ{]8m%{*%$^X^ DN^n>=ۭ\&-p hWʠz==Ƌ#%8:9jS.JK1I/ry:=GD/i念Ѓ%d!̨K9ǁ"rq>SB[> ^T,HP1LD\F7рTn`nuuk 9hۡSy sIS Df² PUH ;aDks(t {QBM C??t@h$Bvuc1*4:Pa-ؗp u11;PE$B#B$.wGY[kUҌoNO[ ^yzdlz4ZR$Y(:"TaG˅k,O)•'nFV[ZƒdWE":1SktEw +oݭri?E&Wz'+M Qąp7QQLA# M=_~ٗY)9-VO.-Ng@?'At̃B%\>;=tgxZ9e禧䋗?|{5\He[stp͌G!j4Y'~鳣txmQcʘ G14J×a::8׏qJ(Gb#Xֲs?\pt %>n."vϺ9\As?8-w/hEڣxbbl?Ԕɦ}o Q(^#V8}%#v4,4N7gao9  SU&`bah`T2~(qG b+Jnc >Ԭ49-o\U~W}"W万B[ b֪ԆQ1wT=4CeYḃ._w~ j=xl{4˲dYItwν6#CBD橪|_<2"VTexmFr(Ԙ~a#s#\ m/}{߽qft0$ sT֪HZ. xl:ptΜ9Q l^?o;'=uȓULئ;2H?O8Q(fBa0q.+&[){6C>l!Rp<Cc>>\J9 >K&檟gFPԻf%:լ75=TҶd ?eKKeܮnڵ jI@I;;GSc?۷J#Ӈ&Uaw_5?h KNJ5~z w}<z0@HZ^a=\sߓD~r3fHv__Ͼ_z3G'JiKܮGù񌛥RF'2*C;}$vOͷt-G?1Q(XftiNML.,TQy{ O}WoP?AC>I/_'wBU["D8v lSf:C:#ĶL47:N" _&l^g ƈc@ وMRhEc#mRlaW,D'dn[Q˺yßrߢ U *) X PBCuϨf$]B#5@5 hCJm}׆̌Ag QJ[蚜K.`71NVz?ɗ}QΚM= #xDjLCѳ 8Gv ^Y3OFe".WG;JD{J+GG쯤x.~x^WҖ$UFXF̶&Ԓ3P}+z?=$~,{^ɨ26Xz? ~L@=NF0Y8!ZK&F%'"oJǡ=B༅MR?`PC*e.<4U*$÷~?980j;uO8rtԆsϝ|gf.EXS'J>qj-f5:5}c3Lَ$M0Yp'9E)ˤJּj5'9`]Jo}O;?/w沿% <[m,?9|PjjQwvfB2\o4: >Gt8dSǡK"X|lS$̥['Ip8*8V45DAz /TC% 58xf(顃s'C<E[yJ 1a:!F%s׶n/o6%.O9y~f0õ;W޽Y[e*}ԱD;{PaLа[t>Ȳ2 B:D"]`$cǟ8uɃCS_x A^OQy#ɱ4VzA.WBADaMg AG0e㹩B)ЁˠIqv\8V DHJש.88p@##k^fgơwZ7n\['\x_*p{?ǿW+r8 2}p A#O:m+Ndu䓩) 9 ` qNX m$.8E2BD]x;U;O/gKG!1waJtq=ty[4#*coTLO\蠕PmI joId.u=\~@mZ je#O<rn_???_]ΏW_+/g>/0+ljR-[](˖ƧM@,EՑ@x:s9LGR0t=>`c p`UIzHQ ] ưܶa_ :6Lc1f@ae @"ޗQs".&^Mmd"„)X1 EB{-,|`I6Qsbҝoɮkbx2plJx`ET&Lb*,c!hzb͙kSNӯ2%xlW +F(( ˰U8NԬPxGOeX0 r 0DJ.ft{5B 3 ]ϢL_aNqv 4F6T dt:zhq 6ɚfѣez~]Q8##J*ƈjl9I}1J> 0aS&Xf0)%]pzT*.:a{'̻XJqYӿ>ZEb ~TmLwaҦ;_VG=sξ/.!sO1Enu&s]Dჟ9}Nꅳy:bh'@4ZvuBB$ y $CZٱ)U3MNEmwǶh~,c}/|o/?;Sko-oFQMf poyR MObʡZk׮ݿ!HlmWBqM%APRkm7LˀnnP K6e`!d&@s^N.*."!pH8| G}}A[=T@bWo!!N^8{߼r+jQ<D'Vv%-[D VЮUIM:ׯ\l rFpxq_ !*;Od1J]}gw:tf /oUGJ8) X\գvv,34k2Ba($1):0:A+3 AvBץ?Gb!$ǔ)>+gaDBf\h93ZFr5K&! Ez펆M%v$ܤp Fa0f)PwtvȈ#"}ƾ)qg2\ C0y}7ǧ4{ӳ4e ?)閞q~DQn <;鿕F@gM3e.[I^~kg8AO}F{p3d=z܁cg -_, M" PHO"2d;0,(Rq+Oo[~ corf5A!kG!Mj梲yVo wڏ?"aK8 D6\fqSt27\^ީUe0__ 8NN6ܡə`8:y L$CΩ>W#t@3sϜ}[K;(/9G2@* 0v"ܫqhS]zqGtF`WZI# voۼXY 㳇=uh)f}|WZhxÇNGҩ˖0 S4*׮?i,..k.X-d _W/ 'N?sO.dK톷Q } HQpq&;l۞n2UbRy%Iɒ|/_~XLRbTMĖV~^zgj3Ͽz3NjCW+!+ +('v֑:hp~'GAqlHb8iN;f钛,2;s8 ؾ3ʀ0n:4` *x2hV ؿVHqCWm~ֲ٬(?71="E!٣J O8G9Rp*!q1!KohjE TD.1GG%)op aFFWd/:=|/8ܯtp~.'&b c]?x=kv'=V:jD"~nYaMsOY ETe.qthREA1qmyь.rpjABKqS*#dكgɔoG+=`ߡuAkf4xIY) W=KGX(Ky }?:A$WZVSkZP)7vL]:t)t SG'N(S[;Kfxms=qg^/|́J<471S2\frJEIZۀ<У͖HBs8 ;HP6㕫.lmwr|X"aan"bHZaV̱鱃kW_" [$T $p0Q3]& p;&`E]uY"(R%ӻ5pqAZM$D9 xҾw杭 6wk %:jFv՛nmuu? @1]P!;Q፻k}<3vbxbFZ 8,;Ep"hB?%<^* ׹86gHߪabPd9VZpuD#ǜ[N &IL~h9l8nf?=b1~$^u}R)?f!1cfa0W .$]b羪bI߼A'EH*i8䟦uz'F3P=^JhG+zzF+ P(R<= \ZlȣM`K1AZ;n{x,- LD I Z7Eŧ@YIW {1>}|'dH0$v>ztzI3k nb.W橋Ƃ`̣{qrUSn@bUI&e:>G!$=J迉FSϟHhJ&ccI]љͰ)zBo~@5 #,6:cO4?3X{VDixDkbK]Ǚ{GBbFUpRLخWGd3PjaStIM6E}V(N7֕8.u|7]CyO, qIh_GYq&BݓGOD?QWJR GNɠ[APpﲘ;0(PeOͷA #_)Բ!:^ J sΜ+O>k8)&&vZKw.?`@眜=t _ONgJӹ!+[{xƝFewVV704:v͒0"DLgwgscGGFҊ'ęwZuIAnZM=qKK+Zr*. R4촵< $b)~zv@0'R11u\hJ-csA!DŽa# jCB!k(Znn;BɃ'w++$ˁg%q6;~@(]n{~;Eѹg;[nV;߇fH$YvK#\n_|ÇBvg 7n^_ߩA0R9jN әɥ+W}cږ5 NǎAŪ-݃tﰶ2k oBZ\įH0 ,z`>Jm!=@7b j; W7A쪑ljE=ݡC1U BKMge85$z5 hY Q=͟= 9 ml"L*_9f/+ 1 Ġus]i=Lɣ~5LoA [х-a2.{'RX&y|2|sÇ `!\ܼQDh6N<*c^p @R4ڷn~;7Ti5'8xph|Rt`ED>&gF|\~;^xՇI)kW>!}g|02ea4),ΕӐփdt]$`jx g>bqc,GBa qV?u^c&(<4DZuB Z#Ett:v bl-?xx i9%H<F)Ӆ0it(@ថq Y{^GByP__/w?aŽ \=_`r`)#>CXs1>9˦L)_m.d5q/r8u )ҎqdhDErxF$4*~q[lz){WࢅpC`3*1CĂ f!EԻ{ :U.W5MVЉa6"؛Ї灙<ÀEF;FתW5!,$qub|p\MuKu] mۖ<9,ZzH4\-`A4Ń|_ҋ9_x3_7?;_GJ۫~p]z)Q凟y';VHڮ,)pvb|:sN\A<;:>- }'yT8xtsJpW G$}g)Kaa ?* n%b,ބ, Bxyek \s3'Oz3-kAPk; +cȐzʢ|{ T" yg Dpyc;+PMMNgl[)9=E۪YD=L=0spxxDbsu]I;p0$"\T$O$\bPr3NWb6fAG<ŕ;p>FO$RgR)ïΥ87>gҩ\D OʼncS/>cXp}wP"6ud:^XC^;?ޡ_|oʯ/}đB l>9[&dgfRB.m~a[qEhJ˱+Wq-i>:{~ɧI,_4% &2}?pRI \?}qν ^rix?{d~xPrX+333>BՠMm[z#->pDqPK'.o&f=QeDGr OFQ8UXҟv=|Y?q>ŅEC]`{40T\ 3(];訙(dq#K0f.lx)WUd?si޷6$7V@hK7w`&JKy5H_y' E}??Gaq簏L[tiU8A ]^.YL˜%:$Hdm(=ҟ=\HM^5f7Ǒ{N̲f]xl I;17=*7NUÞA;R+i|.N 05!MbLj,[6Z.T۱Ea ,ذޱ\׎&d 6L FòJ]R I f _sL c^\ iYTьl; 'N<!cN}_ѿ?/o]8qܯ{~?~+-'Q JfxBm on]GY\~ ?T,$lYk*<?wBɇJCCpo<\;`ue7;C'9x ;Rr}pmbGGG',e9ơ'LJ1%!-ȽP={)H+Cc$!EH*@5#E:(2YeC) 'ݝMm[#iW^oҗ452jarث3O3Ɇrr,--t†m&N խ"DL&,$7xɟʼns___z '~.d 3Ux%. JN::X_LNπwnyar*}Ĵ;6$ CC#T.f;mTih|sgfw_GڏX9ww ˗xh͎:Vm{^`YNZ]_X]]\ۄ@ojMh`:$#= ^e/2~\+{}\#G3 lqzE99ߣ$GEj38 a#"8yL0c7tun8a¦K"<0 '] Is&|Ԑf\7QXE,zZ)P $I( KJEڱ1 Z1PoкG;# {2n#q~ ߁V; 'li7xfvGЮžk|i"mha:k2\#h`dw* %!Hu׳,j'%czn`lc6]Mz$FoVWB͙gޏ8<4wsJFS9 ƅ gW\Ag5iRΫ)9~`~ruLS]=D'//5zڽPF`^VR6$J>@ Hr (]$ہo!-,zpY)( Ņ.ǵyMah*a!S[ԉŪ4!1 ".\WI\uBz0]>=q}_Q3MH7H哈8Q}H|25qs2}*c=+T<y h,=#$JBJjשON:~tfzRrc}pqıH0MvҦ %g^ywŭw jywP:ca+D\:Ix :C)޺'8p06:V-{E$-H ct\_cV@S%HaN_D0hVL}Zqu}txL:N$bm4$gff޾7>cC#ەAJmp€zi[P.v ҫ\S'όG7:N+[/gpbHq-ZmcO=5P2|Q% ˴V ( !_FԜ3XatUdGMK_1s/sv=VNxi L+;Mu((jG:,;txʃ\^x˟yT^Q!w¢ T5WUR(nw0":o#1HPGjmb3'f{fDz 2l!O$Z;#7O0FTq0B tg̍N?x]"E\"rE9ՈB <, Sfʳ%GQtBP3oO._8q֞OϞ=_K z蘠bdaɟ}'=IE?5]O ݟ/Pdd?Ez=iBfZ >?3Q=#V{\4iS[T~L/p݂ 2gtc&5I3rf{E-DްĮUo7ZS Xi1lX1zCŀ -b2a摲DGOUq-F0 .3e.#y.fߍOFuK2VOG\0%O H._ KRabeal[ʼn#Vd2qaStnXoT]Ֆ-[2_ݸyy}mqfbbvr\Wy, Fn|;oV[3~7kyМW^|ݝM#yaK(y<$ad(`wkҥK[u啇tv @Q\J=HXlҼkpS\PDlQQ-/˫[+tH:v|rj nU}mv*:+r#sصdݽڄc/(MIWVvnݾ q0:;s8I)bgw1/AτV!9ZΎBbQ D5E m2LfH&**PpI$>sSO>hީi4 #~.-L^yØ[aǠ2 vRo I%IbDqlG盷.,t()åz/_8{F!r%J ͵s*z>_d ;z Y.2"N aloV6,,\}ʭ[Kkz D.鞜}~7~KݻܜH>utx.== )9/w- | "PI=|xbd2Nf\sGދ}(R`x3޾^WgD њN{źKqDg/q8/OD5a`"$q4;Ѱ7Z`vSpb!9,P1PǒG-JvO=t2^Po'jyGf)#?3:Zj+L _Q%ҝPsY<"Qc-刮Яk>":$87WѻP.I0gNf%8)ͅ(-34æ[zx}f+f՞Hē z|HL>7$DG1:0dXiT[ vk%frsy<@Q"q$/^g>L  0a )p4E& Mݶ.Fc@A^Le$]XF`S40]fA0JD~tS/ 6 n6|j"2l&8=G!Ef"TƧ .%ba=ߤxvv ҷ7UWD CZ*_;He;o'{Kν_oƯ|;Ko_i3,Fmxbm=V%Z#Fk\K~xpaVzv@u_|7ކ9 !'-3YٮA_>XP.Ģ̦%ugŭ ]kF;Ld^y|CFp>X~7F~陑$`<>$8qf3``/#MOS)dy2튥Ri4 !E&%MB !K$^xqvzn{c{q~ ^.rR[""J{AFج|Xꞹu^0UJbD4 0g^ܫR2ܮZ([ QMFmC w-hFFF'B/;ﴃ28Bmxid=MJ.Bܤ*PfA waeAA%JƊCg=2IשUkѨcĨP!jmonCY*Cd}}=|rd&egg5*;7S*<;~SR#Οwg6r0={gOO;:t`ȁs3g/̙_=r#ŧ+L>ʧ<5$M$A`dldSկeGXBM{q G1-Gy\k?&=pj!B? Pτ/7۟f8\;ß\&)8&&s*L1VC!,J"΅MgbfxSRn`hx>|3=__޽;;kJ299?;>1d48}ĎP9讛] ?͌dT/ !B[ ; 1'qDH7B9 GfDo9s/l )ЧDߧZ1^&FSldFH7, NE0fǃfRK}:шeE¦40-3Eˁ.}]Pyfa-&* .W8 ML_(/3Ir=w3?UI{K®>s3s425"z@k twdey`^40I& m{t)Cٌ+͛.m76DP C/JWwnfnygKoo]Qع~z?{΃őٯ;}cK05<)$PsZNS&a;Շ2vk]|+Aba;ӟ|oq.%1 DzEʤk,I*PhV{KbQApw-_:Iުtn]~{quZ-\_z!rw2sϾr$;ꪛA"QW*(;z4urk>>=;0]]ZX^"rlՙ D*NX0-L ;%qaK/o_/o.ZHtfHEbd[SY$Q/ :>'́}~Ӝ>TQNb^> fޑw37F+a?Ooŏ/~`dz-Ƭ*h="# \>9Ξ?k:sm (|TW%αJ P*$,T% -y8D'7:6q2j ~Pim%|1q {w:y !??LYIf;ڨlv) V /=t'|qmv>6 QZj:L N OV+;zぢ*f|x,yx3[!fGfb6=ܮm@2"l9R̯/L:ȑ#~.-.^zpCO0sa621\ѭn U!>Q ]k-n4,®ח~R&/ [ R*ZlUO06,T,Ux{1L`&=w\Eʑ RxHbI>^NR+eu cp8C(`* v+KVCFdi"|*8wعG;p<DzF.> |[Krla5%V*FPrxJqʵ`/^իmm?l7 tslV hP!(9R`L;}63݂ɞEw8iSȫN :7'<ĻDc.ш9<~GbN?n-џhJ"G<EOL=0-yc1WL5[9,PԣLQZ5ܸ_fwTֶ]_u,edH4 SܯjcBܐKޠ547RrYW_͘`4|jq2@{W^}I;<:B_)5T%Tdaƨ{ ӦE-Z=w3n^B:5fdv9 %N4 {Ke׾GQjj=xچ-NDr$zP!baBayLrҢy3?B}yP 奅f6<26O =hPk ٓ(CjE$<}[} NJm|\ GN(HU4S*"0-n-a&K[' ;|蕏 |/bϵ.dC< ;Mp2|~8#ã~3j*3ɂd`F)H(,)q* vw 6*^^!ٴl-j;sss' -'m~e *+5pNH`AlUf_P aLϮll/y) =m3\UkV|ZNkk)jYo/8!9چ BIpG2oyťKBvt`xX&ӊ/[+f Rqd4no֘ӐbЯa;&P"ʍ,eK 9LN+<o,X27L1LEr}TȘFcb,! c>18v1\gpʡkKu(WәeopK Jz"9;3/?sben"ܚw;V"UQ9Ψġ naHhQ,r166V+k`+Dbl`½݂$Α<ԍ [K:61 &0=ry`w1A%|erXcdHHfF%p;0&IU<ݸ}D~sGNۭ͝2"lV"brw}82<16FX}(p܀O)CB%fYH:ʵ7\@zH&^6@KASSD!-c!_ NQqmzϻ8о?S*(kF@H{b Z3GsAg>U% $LQ Ֆ~CNvS4㠣0StusP9&)#:H]DZX+tF1꣰1KuΊХFyTjA]GQV r/2zLM*.)l)x$0b$ú!x^|DͿ)}gGrϲQEM'B|gECStxGIS Tb re|?0:J?A$Hm;LNNT;q `&t1øE0ƚGFԔZjd,'UQ-}\(tusgpN@z(!8f@9 ]o#ۚ uaQjzʈ9mŞS{jB^>lL&"=+Ƃ94O B{#g=L$QHqf|vg-[˲Fc PE  Jg0660GwlDj 撥Dzm $2 cXȡ@PbD6BVu}? so@'j[U;JeD$ٮl቎ͶZe{73 8l-O? bE BBQ!CP8|nj8\ !/zpu{kgfz %SpmUkN½v35=Me:S>i. L Xq26I HP;&:vnm9']5v+aLpa dS6c#{[<=u(}}J  Sa1LHwrDA?Ȍra y)яhsУڳ}"وl@ pZH%v]o5pO0 c {$-cs ):GgO'"Oi@jȷmmmn$__˯mwH 5iS k(W#TQ.(3 tΝw>4w.d}kKLn윘'gνxA8o& L`#(aRPF3(<:%r0i]"nCcx ,-aH 66BęN5fX.T{z."Dfb.̍)| :X[ J>}znv`jG pHBQLyZ2 S"^F|}2>Et~y8% y1qm<ǼqcqN+^'G8Dݘh꩜?{6\aƒ)b`jq$ӕUA.Dh$vmSv "nC)b]??x|+Ǐ9Eqe6E)<=~ѹm!)wpie 8W+n. e+- & V/-oT*FHZJYZL% Q^o2Y"a |eJD: 0w&Ssf +KuPCBE6}L M\~vw߽5mSG.JIWV>tޝߜ/>yܩcBQZ[r\Q EgMQ\_ y}!Tu,NěfPݩNɥ~,u}kKC%@s`{q[E)Q}"PQ1W#OϾ_e8jebdM X"R(9>dPzo~;?oq)RiҲ@$=+_BbH0TNJF| aڎQG@2N`'?έahф*.Pom(ױ'&kAm>?Qj&aL.8!dϳoH 6N-c=$ťͻv,vcBSč@0,0ny. !GG:q 4pV]%䈛HCcjl{ifzcIT=*V'c*M "х%#ń4fG jjya.Ɗ#QO=g>{Ti솲-dXY\lmHsE2s2lu[kO=|S r)_8u S@v&6Ω `2m#&lǵL32%$ez⚞Ha?hIxuۇAoxGo8^J b.H@&>Zj=Bf<Ĩr sP'U²k:( e:b (:u2$ԓ'Diu ".]=s™O<0>:6=6*qlR$bUL諁n$%"Y0p/4tRS&&gC%ة[!T^|O Xq%9kMQf+9<V:Y=" L6术+( whx,_ʍN+U v#ōvSk3ژR W\b .Vc͡lvrtyf&P}ap]]j m(tmJUe [rYSM$r3=3H~9S:~(]k oQB:I8A:N;}E,F@įUh,STb@h$y'y }>pW͑ƺٶ+'W^"z u'W/dh 6\jK9V)JK|ŁLM4!` .J"QiA}X#bAD1~GG& eh0 0u.EuҁjA7&ʩJ kF(Ա(TD'*<sPDZmGC"A5CᐫEXuzԄWT,#.eg*e_46^!j5 zX8u_sZ+] ͵U =}I 1J[m ,EHT`}]m@tDv7ugD0CBBMg$3Ou7@%INoa`( aBed"4ܐaPdO!B+!M!ؘ0D^ܩn2b>"%>#vMQbEkBdAjGR`'& XIXJ6ԑ!4 QH Qf!/ B.ᡇ~װC SGoW^6#s@mwVWM]b$uOx8to͛W^;3sO?;=spl`*l]B)U$0 IPfOll=/8tDC~JO QϘ`!Uˠje4J%? $s)-i>jS<3W՜l)w݂g1;r2hT;U-ب \ !JD˶à{>rb!s(6ց'M;1ml^kB.aZ\ȥLJ+: sl 9jL R-ltR@D{h-'_a0XPHB?Ξ& YL"$9H2oI7SJ,̈́6~ zzֲnf؆#S_׎:c[Jw/Ed6^Xv_cH 4AUQ b&30+; FAN6Nʙ tr- IZ]^o̙B kRaMdNdXjlh>{Pe陙tr y2\t0Vq(#Ȅ26vUM828$dHPzr<6ۣE9,G?#~wA ť$qsC3!C&"%8KF1JhJL&RaFC0!2 D$9CtJyD{;lp{XH/q]fc# |vac lQA̦K. &S ׺3S0CIZYZ5014aחRZaCEV- ȓ3H^z W5Yq{F#FN\ށX@M "\t3%15:#A*,f|Om@G B`?LqAR1j?mAVCI>{#H$aI*Eˍ͝P!= FKN`jj*f޹7p-(C\^@62l2$H`MwNMN=R2xtum}V ael˵vQ -A A(}d{l:$T6sBR :s͞",x^'{#po}n T1?{ B1-ƝcYw0.\X\dc^H@lSPf_Y|r3<{,47N#IՊ-:ZV )sN#<abKy6Wll'0MjyZ '2-rSppݠ('1mȅjLoˆ) xTHpCX/H/*O=F4@WD' WKDĔ$3>r/gNhMRM:c~CfB( Ic&LΌ:F ᮽ9+i KCĤJCt" 5"Ąa 4D"ld."J<^:JiqI`3A2EMnaܢCmbNha<4,$=τ,;/nRwq?ʸ.M݁{w76Wf}>3[ܳ}&""AURijMjZ[[":7a!Ze$ aL夳{loB]/6 !s]a({:vac rd. AKa L$meJ2Л dSREly<S6{3V{2@(1wb=rCA1J$"ǂ)UV.À|LH#ƅc>cϒzl#@V\IUc*awWQo7v`?s? ==0+/gFo_?8ms?&d LHh̕چ9ţ"P wrYA$O XM  :{μ#ğiUm?q45qn˷3?/~s_\k8)Tݸvڛ?)ȗ|qvKVggㇼ7n-7H*!TCrtCkN疝V@8yęZ 3ہ Q;HA(c尼S^_`~fnbkQkAB"K P(F,uAյrX(NLLlڪV7Y+dk`'Xs&I[n׀ sPk4Ƹf6T"3Bĩ0 jNbk`*IGG&魵504:@j35L7i "UÁha\+u= ~ˍxD~Kb>a٤T ;὇7&'@v{g-e;Sd^U ,(4* F@nn|/g^|ԉ'̝8 c[`jwظ8k6nC#K-O$OL._zBiddȵ(DDs^w ߓkD:L"*W?ed޹X)ɔM;ﺮyG&9hB"bc$ I,# 𤔽)|s˘-%{eϮFfj֫:uO"J!?]Il9PwO&?іHZ&Jk: Ǟ+\!`ˆp)ZrUm*`Uȱ0&hhb!i5ץ8m\Lj#M CӆO+`)GB!EavC8Q5@3OBMݦ.=q(%#,LQ#-(o%{yUWy&L/_7~WkRz( FGD C8s"{덆,ki]CĦC0 "QaGѱ IRTnojn$MTAFƈR[}!y"i%]@#Jfz\FSƬHHONVq,8k58>n0+G%'3FhQW F4^=R$T4ѾzQl9 d;yUQm aEۉBTjT-vQ;'HJmYq@dp.< D4wd#ͶWdG4r}B֓oc:f=޹fX~ah10+@2GhJ 1D_q&2+%.01=p9S[M}ښ ;mA2Xe;6g l$C≙oݹ{ֽ/_H0=zŕPݽsyyu1dnJ ;>>1-B:haqqp}ɝа wx19"/SU9NR [CCytbϲZkjZf7 6N%~Ne@hwڋQ2:1;̅m GyP/,DUl,~U 8heWAb nQha4o¨JRJMJ8pl}y 0ׁ c%ncquub(a9s);ڭ qӲT`#DGP{Q5D C^zϿoB@W:nh^['C\_ΥҎLIL"6 Qgf ]yZ;;,BPT*.H %gd&w\4?|򹐇nƞ?v f][zα4$5pThBbu[UC+M^M&Pv*DDfgL]x ^"ʳgH{ uz "ԏ&(B SuAqiդD09| 5'Z K6j! Nġ>7S3*XLB} [i&$"~ka1zUϺJv&41i헯71ZQ|D|adWn6tzC!N@p(4BާJjH0FH wNF{pzTـ>!]Oӿ;1>8 D1$`!,tCwH ~Է;1Jz 4Hl>B t*`_hz "=cS t"\bPlG-.?Q c C0*5%R`jԵ->S|C3PVGR,ڮc^Q54O Weuo/I*\XÃF4ݩq"<8V#4]4 io.HtQ^IoRZ7BlKU`Y)pqwO!2l 0 iv3j>6R npitbhYz7"k i74.pˈ"W$ƑIRLhH: 0D%juăɨnV?]a8w,'sd/<-mZdTby2H9I`nmB0ܔS*{yyUJ93=ˎT>p9rɉ9$p-Ca Pp䫰d8H'ٚm`3ƈ %L31 pi~w~MC\L2sS>oҹau C!NCHUlm&)F*|&xx~gc-q(@Bl./JlTbW`bMU`͍_m<2[̧~%%V/cåTZ`ԑ ijPBi KFΛ#Gʻ90735} %$8Rh hiMێ "z٣jM (nEv9o:'D)L{$\P fSBQ"}>1KNEؐq(dQEUxĀi' ,)JmBE$Q ԩHH"72IӎIM `U.) ichi~\#zGtxBH/@H 7xA`4n.:=2ۀ?oqW^A3@X6~9L;m f}afq4e|l@ IVK:tͳ9"MHV.d$aB0;n4޼l7'6e6B({ݗ01TЄ p5BUAq:m |:!a GنATqL#qD|q.JXDާx(5Qd߇r!W!eNQå{Esi9T{'eѱА z6*7 u%ӽX Z3LFm^SnjI U"Tg h?#n },]z^ ^[{tt\=Nݬ3eT?UZ-⻣кJ)Jaіk9s30Ԭvnum}qKg{S% eͯ]GW.^n-Tח.o.Xt&W&S8 1n]h8&C:rlg/@yU0zI $ez|t(_\Y[dVXDJdrpgR5:R͂]b1"%T̀gftl-;b/1'a%SKLԃtFPKgT6Hrf4uKfK˲'v@9o{wdyk{ii n0Fή_m,mgSL>jY!% AQk]DE偊D Mf5N~SZ"6΂0JV*5R\n4j?} +" Ep`a{cu $};VHm{vm8'@9#gxS~yڍyq[)!_. K( SS!kVڔZow-}bM>1Q׫;s-neY(ܤDuf#J0~RhŴHNpkt#8es Y òXHؤZ IYȒN"!"̌K䇚e:2lw0#5sf bTKcCUp7HewM،a`Je 0A/{j,Σpm  afT)e"4(Pb[GHC#Cz =}3@AtMxh hD*~]]"" In69,߭燦Nkͫ.>Գ?(FQЊOMύzwo޸}_j1*tbtvJ?h.UIIYAl\B2H 9:<:l{pi @cض>19zvу'yu቗l]خTKlw:~*)  S4FA}oE CJO_I\Ee_bKJۦ鄛NV_!t(oP;@`7匞?xܸr>\.,ԛE. zu r!hW@~\4 Ԟ={̺&ORT}S(BdvscK%K:E6 BME`((j.n NmI֛>dj(使. Vvyr)j zm?zsj^})-dmw 3Rڔ&o߼0TH9hL}sagC Nw@7Ƅ|@vVͺSv056K/=ؾѭo^ʼn<}EE(li,Bl[IF3ΔÓTZ/voƇ׵rI,uLi|*k/[W9QG # DX* SҞpRD?둕*zp9օbDإ tdJkڜn$BTo8r tpWӦm υ1wKAϲ+m:+(pDxܣ* !SUx ̰0ȴE1Bw|O3i*fIWT2lZ'4@=wqdh/nE20)j%*ܹ}{gw %Xj}䩓'OO>η{__,cп;4$/;W^116΀zGalGm =3(ij%vۃU9pr{h.f7W!J.Nv_~UDzPBDͼUȧ1"N;sJ>< i}p Pt#"]baL!M)(&ƥ!,ccVv!ET\3|SRHWEKa-.KJ t"2Q$Eo ]YS_[U+^bm\$-B!֧T@QzÎc,-{b'Ŀv*fGi*['Ă !(sZ6%nX+zϝ~y3PRƨ =~j+._x4 [Cc[V00fS#k6sPq8;:>4a}Ull/-ݿpπdBdksijϼ!r>'\i0BQ\i;;[9Wl7kl{v3sDZ\Al.:DǸGH6c~ru"4a۩aexp@4~e^ou g붷,+A:}/}oW^N<~3{sMb'8oo&xl@suLN #]@6KCÅ嵶Ȍ58ya@]B>;95JT Y5USS @{!䃶vFI9)X` .JMg_C@e_:,O.ԥEBpL.[^[:2T'>{Y:?#9srchzQͯJ 5Ϸ[cGNNA$`hgOMW 93723uߡ$>ep.M W A mӺE$D'7xma_SSGI fܩR.QAL׆_?xpiu +# >ql{bdb0̔@ iȢxeHMRA|( ǂF߰:@ ='PZ=Z"Y`}/;E_%:u1ۑ =ߜcA6:K*ղDV\5'nTKG2u-q V|&}%'u""ִP(JI1t: `cUB-k;'Aa33ăuL(+lE@DNjbXm& 7dDE61gi{Yz~n٣=z7xk׮C?0d/~K\/--W3g| sbnv7d1nݸ/ſ8 W&EfWg0!צ5w )dkV¾XoYPe@mhҜLi0gyUK. ;4X|oڝ2s?2Dr41pY=J5=~K-R4IoLh ,ħ611]G?ZkڢtXBq;(zF ZAPjIÎQuU؉K*Qe@°VUPX[[;instu3Pm6B= lͪè9K xLWcem?<VZR^LƔ}~,~}{{-?`|<1g!u uAh( ֮~бx\]n5k|ʶ,Hl0V|M0۾`Lb),w|O{/Гʍ61Ph+;]AA;iv+졙CTk"@($jf{N@7ECiJu/=83I"dy.ToE7+!q|b~^bhoj.j$SAqye?:0W+wӮgPۇ{ !?P 3иZ΀`CC8AiPL6aLŝB-ވGj]ȁ4*уe1 yu„Z>ciD6^pШ"1 vk&t(?MZXbzZ=0  t veh`03>z1&u##޿%S/!}[7F"fꆻIDgxa &-Qa(>6cT #v7,{ U^/|/\ ?ĸ~US 2T}P.{ox SϠJL1;̭H%<\a.DJZ7+D\ }s]‚HKp$ԯUw3H8RyQuuеjwPŽp 9YldԶ, I |D.S>mgo ¶YJvƖvwWJ ]vXηu(͚?Ӱ7ca0t_J1sylؾ_"wiGXjgoO"4J,K=h{wƸ8!ľyFCTP s#3uShC_o˗v-LOMӳ!U BWniIwߺyѳΜ>:sꍫ`z ^ ܸs[CNE"\401u Ic780r:7w2S(zPZbeݻ6 hB%ǎpq1?T,e!Qu\&L $8I}N_bA:enAfs5AhUV4V7Tl!# K =0{_r}ƒ^{sah?62 eVIn9 <ʮrs9H)LQpmLgxu rt"X)ܤR'SȧU>bpwSH# mRoGsl!3Tc{מ{s?0Y[ZY @@yctdȢlyimcu!\J;8>C;۫Iۙ;81=fJY d-hV3܀#Bvf:q]e0D02F3!ho`z]0t@0ث&-fE6Ռ=bxS8;Us  t7>: ݌JZ- }7L @*[\t'{W>O>(}E_!${ ahAnsÛ4GkK/6%V?05PA)e)׶DDFX[.׮ xAy;m 2Jy/HkANnŸKe`˂:*%M UoV'Pt(^+sbV|nŏBA Ld# >pAQBFR|josx* ޯ#D@`b/}d릣[ԛAp'EBip`W2g0r&9*Xcj$Vsw¹2, E4Ǫ (BjX̍פK%nkF {)pk$,h:a@gm{Yy*L%<Ũ0s-bYvrkcKAkgO~ع3_xK·?YX\j^J<($.sKkJz936G[6׮]zOSx'}MVh0jizZUJ}榡P]nZC)+6/Iר"Ih!hZ W;Yy!%nHR-dHswֽuZ]|᷿= /n?k@o$ɈD4Iֽ Q,'&l@&ڄdEY*|躠>vf6_ $璊\>?Ldanzoc㦫2 b&n"g )M &R0<Vt,W*[`.GB[">,?1gЈ'bSB@ %Vz4؂ 7;\i c`=Y_^WX0506snn4XvxE8-xG7m6&쥃APx 48CrEwéP)P;6lHbF (4 u3?c0jR=y,um"eiTjC70lАR,gs;bXN dP7*ex4?&,.Dvv' J5o& WR­-޹7"0Q#h?nwB-Ƚ?%YXZ:q/ t hڕO>xN 7anҠK@l>IB Z@_G\WSְJ Z FDs0ݯ5+$KM]"tڪJ:";\qҤ[ m>y̹'yO'=M$j].'FFڭNζx 6 =|aJsG r?Y5tq˰#f);J.i J0[tGH%dP)B\+ổf;43=s1?v2=JNڮ?=qhjl6y̺yʵ]+Ͼ|I+H xyի/@ĉS<;c0NX^_[_ܭòW8+={4K8'VtSn2M;LR9c%)e2:c5I[< `~Aū(*t1YOQ.YLs*lx|ļN ƿ%aqmt<80 ĹVLm"(l=rEfel=5!}Q5ե 5k*K1PP! \jXt2;PƖ n*]І =.(b j(@q4(R(l{vĥ ジ!l9 %P֬u٤ZE++D0I~º~7QFGQ>ҿW0,gSA=>??+捛7THKWFG+ zַE|='9iG\ USA 4V8* W^H"K@ Pzny4~l:E!KؖȰ,]`9>Lxp8q9"4cBg@wM56kk.tj#w56Va0D1k9hs>m۰C:*#ߢ6IrizGG~yx4"~)ꮩ #veD ~P{@21=AD;M\B.`:c*:ȈK%l?h6]iByܷ,X**R$ 6c x6 1LD^=qMDl(O%.c<ȉղ /?h/ðkI&F ːO,^)&V JxX4?4s4'm]ZcνNÅI2U٫՛Ǝ XA7Y @\\:\'c t֦Fn^N`|(Ҽ+k aHQ.e _*d]{!(a bI"<5K؁ƆG׷Jl,v쉑Z>S֛e@\=*.H.a0"Ppߒ h#8!`i$.kX: `>D. v Ӵ`K=fraJhßA"@ =VRsXyy;RI֥@Gx&lئ6 =1)qu矐Y5䑥*;Jb w{i&k0%'?c ?!q?/}KX1V)Ͽ<aol?o޼hB {vK/} __G?~g&<Қ 6#aT"†AFaAC~qD5"cѰD04Fa{]GӑCT#0) 8rX$.f_uG| l0ZlVMEY'w- (H VWlfI.=U3 ""TS׉ẻU}$#x/G|0z{ʹ؋Va4~JN"NBu#- t凾ΰkjQ_YšZ_8p%Ck! `u~;@$^]`tyf!rh1nUAMxMMWTxufao.oa#Mxs?fzkw5(:SLHMbJ kHln&euɒnkZcʥSǎ; Wq,w Aˬo7e f꘰#'n]ot;W8pY 7ap H>̟ |߿׾/,2zpyn~dF)YTgG5w* rN./$T`0,++KzC+X LɸQ!f)7 JS%lW''i2ۨNecײ]p9z)mmqܾtr… ZG46ܷW!M͌zDYŻ7?J|sGI$Yc_,8Z$5#ZA4 Rϑ',GbFp"zpZM#tqnL:GEٶz͸ z0EϏ4U K'g#H$tBkGVMt)"T(D Inɮ7X(0UmXAP#đCG4,ѣL6lմ0Q?TRM5L#X"T`<,kk溶ڬJ.0@,Ii"=/A`yj`=q9<~ z?ӧO߼~2|`<&Bφү( l_/;?TPٓ2h5°<!InT2 w+sB%T>JB@1} GpB"_X>HŲ5B 9DsԡulT"Dp8s{ `ݔk`DnqH#zb)z&2)ۡam[}*lJ$GS) ;E}WE`sӇ9gS5rP:Yllm #/u;w4DI9CcCeH9 jv@Kb.WTaU{!^-.EF'869ǥE8{sf{՗o4{:237u` .d(Ő%d[ #M'&l䇭0ZwQf"(AKORNB<`x-' |Ms齪Y;yO_7 K 1HBV2NI_t6WS0Obذ9]_ ݦ ܤMV`J8t2 nZty˜Pkgw})\PqsE}NYC L " [Xt [ `2n | W7:*'UY U_ү3z粓NN5Λo~>z0,W? 2mձq\$ z#| \ۡt3L<\,ciq(7 Tfp&GaɥLRBm&TM4JغBSMIܙAtŷz7ZŅssf\m4UwWz&77L!$釁@ռk}Åy?bavc 81;yOuweFʆ}䒆SE["i3[($bQ2H}; +3GNz!4jφ,W[,u3 THguHl_,B+]qmƒʃr} +EBE+FrݻkTnءts`5NnBνDiFL'+$Q 3WkpȀ'8Φ#Z X@oĪQ٠7P)1)j#_P14#dp6!pԼX6kbmK>,wU]#n) ']lef/WE<,DwE>JX`밮9P-*|)B(XO -3],uR;k1 ,?]_#B9ӗ T({/9>XJaO?̫?Yhxm%D&oƌ_NG;UMu!lw{w[i9*kV[PZxtÇy2jC6ڙJMsJ֑P ˲ a\ 4(P{pDMGKjz}h2p$q]عh FF϶#1^_G$DBp' v`B,a=q[du7 ? 2ЇsѼIp4~]=?h_8[C~7[mAhV) \GC\C뵪8l+3Slax1E!'Z"E s,a@( ¸P`]-с6?{ܟ)eI?%Q\lē ElƈMk 7"{Ri  /_]}o++Ͼz٩q+>=!TnN|49^/!U|^dDaI177pX3\ ؐ~֍ܜ(TuKPsH)[V]r\GB\Krm R k׎?#}p?|bkk6[O\8~~7҅'CmO<gxU$q&Ws-!T<NJSPCԆ5ЁPnyyb 盶F(rS$i"␅P<IjECу33ڵkC$p\0AP;~N%ȸ~P~Y?st DNhX}?O_`*"+5ǾN##G^|/~sg_  k~~q#d*W۝j"P( 'X̘02@ +:aN4ޙ'Se[ֽwܹ'%n!Kf,,IoQ~{dIn^wNʋ/ΌM9zO޿rZ[kSF-_ 9F6V)uS@B1lۗT)KS"9O8Da(Iz^&/c=Xnqh%SNE1=}ͯ S[U?ƏM-4#UZ[̵):D\C[߫jW ` )e:*W # % 6"o,SUÍ6ҡ5WT-hm1ЈX[>J! {W`?v [WUsA=G;fxo\vʘ;0g=A\\^x1??yg;;kY|i}}PHC)ܩUPQ_pT@JY޲䈨 $>X,NŠQ#TP!UJOjeИ0W=(ufAnV8aWA2FqmDaÉyvVW(B6 uijyضE! ʶmʨA PIP&glxȡC;Fbv.nj\ZLQU |#z(È:H Qk"-UQޣ$a>sl!B-Q&+1:j=AHbXĎVYQo@qx*$%#+°U*CJ8YrCkC]\:g9@~$A.tӪUQˁ'pww[7NP13hsp^Z*xs״fSn:/'wڿo=g7~n%d֭]5C}7KK/"?O>sϾ Wx f|Cxa~9fagimC6}&H&6fbH3dZ~Hd ac{0!X+wC5lCI=5 bʵ*D"p" n/03[՟ɟ/,iP,(#G@ڗ}O.Փg^ʻ/~xڵ7fxOYZ?|{- fFD?l +kXMGf&Vb# %l]#O5@Q5cy_fRj^)xDZT5c >$cgC2^z9<{=B_Ѕ2i4)쪩q:lik9<$8-ިyH+f{n` 4}]Xi҅Ta#e./*okfwH5nL!׍.a0a:a\>fcfO$&ѣn6ԩS~zD"0= \[oA @w!2F-RO' v=T+ɇ^Uf]$c4&+tDp]XpȍbCiu޹-D{KP:+~JEDZr4 ǻm`LoC )n AF;[ ؏RQʺP/Fu,PK f/ф+L$+hRNw\Ghs|Շ\x3mnj`v9-KLrCI݃Qu cLIǟv*_VM0Y'?=zWt潛.SJ?.P-fU\ăJTtrn *fVy YdD !on,m J6eRZّU5ϐ:q|ݬEUw253H݆?Mdzh *՞RD@3Ŀ~f,.AM~/—{ A|[W^ ?__}o޸~pϞ{,@iaa\m:yv֓5=9,LbZ*򥙩i$BVZ.SK;n$?y,e-.L(+4rj%SN*aTJK Z:JQ͘z}ŧf'*9Ht%MNT82hur럽plxh'WWJKu^]̋U&8/\:IQCBp(wn.-wۛ"hGsH MQIx??,l}āc#2HםɠdM[ f#ZpesI:ynbl(-:nO^Jpn/ ܅˽O_J~~vxG-pH$}f%M^xBhO\Gc0L=oxW ]Cg1N"cj$J{SJ*ab)i>lBnؔ?zJD|Bm[m.Ō"PO T5wbu*W;EhKI1~2w-9kWVWV0`}u Wm#SE*/菴rm`:.i.ta('O8{K?$ $xrIv0ivfACPlwv aBzц@,7U(܋- DC˄wgen+y(=^̆D +!D]F1UĶ m;LԥH wRC܄6CM mnؘN `8%R|zܼRM@ P?l9,'S+kC#QƘy՝D̦Ds=yιʞ7 3,. J; k= xH:vEtd X>\R5tL(Ʒ0L|~o0 )  てE'Tl1(n>2xF#RZ[Fލa5Əz  ? †%z~"GߚG>RuNHOx<׵{j,bZ&H#^z[%xaؕXwlrthx|bc @, ["saJ:*WϚq 'O>\xw.Ƿ?yG%ňGk6qN0Ddr|PYs {SmlA"FcYk7M̤pqc{k{{k]GAiz#CJ\,+vwJ`n?wj#\47֪vzkg>g7n~rT6CTIxJ=ݫؘ [JBQ4+.^3=2tNjǟ}kG=j?fo7y3[_3Oӷ䏿:|8xW_kW._yG,g~V |l"u`jIΑ㇆r卵f)Bń24z6Z ԬIpc иm%V5/EDRvxj 6W`}Ξ>D@"幧yXw.9kյT넫ǯonW_ϼ|~זy:G[jMqS.T>3`Y1!}^nSc!*;Ii6Bmp&ik6;NPisvl>sk^N`jf`y{Їe섛9pُFSc քLjXMZ&i1=~xD!1ě}Z#ISD\"#ƱX7C z=0Uh (:c74Az?haQLhAjB1"He4We6몭 cGԘVh+#a0Hۮ=͈Ă9GD=ڷ4Gx6.RpUQc;Џ4 -&uA ܱmFb < 8T]~$\'ʣѯ$3X l De09Oڬs8pOa±MmeUcs,΃`O1(^T@?U9bP/ 鍍f˃&MdfRa.O;oX|n~8<܁dJpBI7n~Ͼ77@Xqhxqa瞏ҙғϽB2W^<wݺXaGFUV)qCC0yd-ov`֫Vxġ Z`?ppU!.y`^\ fSvڮln"JZѕX i9{zf FPyᑩsӔ! )B(.o·5}O̎* aD=j%hQ#2џgSTsDa=6@]E0}~pbzRO\<$hAQf"ԚC))"^$hyR#~ (j9i(ό ЈK<4B%ޢB3S.5lQ}gclJd$xBΔHh"N0 Ff$DPHJf1<7Dh )@/@w>hĆo1d aϾ#aH 6 x Fg_ !c?eskZ{/y JvRiPjSIu3sSC`Û/ ^̓ ςl\h1<ʜ!%%<H؉Vzɱ0Z+cXzWoᄧ|lRKAyHT泩IKWV@Bz4pBF" $Gpb;plFt]c3@ހI$s pO']2TX DO `OuyRBl-\NHQD1a&2U(BЮ}ְ"6榧FA+Cpm-եmBlI 2=EzΤtOآgG{P,HtYĈ:tۢc?BA=9;t<&`nz{ft>QݔhQ#*bj/ x,`=<2n"ʼn-oV@ |}xiIIP6?yɱёåKW7>7N>wQ%C><*&yymnVsfNT5=Ξ=;<5 ܻwn. o1"K"mꨵWx_HsS?{[n{>uT7\x,XF:9dz̲   ,0rk @H7byqw_PtO:}yHW3So]띟@d.7^z3FY7DJh:C'6>q`wk k[pG@)-H\I&#‰ðBeuݩ4+m JJM$󨶛q .@oe)YTu$:43>(cBZޭO.]+[)%li{:#6a ,6b!ۛW_['MRR2. L޺}[mIuͬw+foz`$;K-L$GLML(B !7oTړS3PCІ:0^$",BJ̐kOw1kIEp[dP~խz4~ =2JJ]YXT;GYSqHԫynIbP EØ=XI"Dy܁(x 'E'Of"[[Xp}=O鍰K\`BhZ잀P6C0r,B^R`q+֗.* NB"PI\xp;k?{n_?uǗJsgf읥Jx4v)xw0w:LLޭ[cZ,߽NFGs`\(]>_Elסka uLa7 6-W ? 0kːX]u,]Nz?޻0쨇8^~rB%[ ab!Ps-=J&!lImq[Za.V6ܼ.{Ջޣ=Ӈ@:,:}ziyzPoҩ_{퍷z@ h_y^)8q+_e΃>Ra8RR:#y;Ȩe@X33L2VUe&T-7Dͫ+ HdVs`b173Ype҂iSΌ֡c043ɤ iﮬnPbx`2zZP$1$ePvd>ӱTyFvG . Maj%Tims \ RjMw*)WCjoݹw1vQ:x'~^t';y왳2@!F"Xcf#;vE \#\eI;թӳ'1N@PH(&^3<g_Ć CאQ;e,m=Iݯȁu24~*,tj1}BP3o">C|Ex1PRjH 4P&03#}Voh d"r/k'ƴR=74p!vBAHo()R<ەJUX "uJ!a侨p@[lLP!'2P]VDrlN972D8"xPXH'}(l0 zO!v=F@\J5DKRtp!:} HgΞ- Ahҕː {>ff,s^&0l04 tuV,sPAyVri«E:&AxR]o+F-?w=@|[Dt-PHOZ m=HcY X=W3ܒmg"Ecg4[\\tWb3 ERx̳ID<6r+ ,P tVo\ZTSScð'oCd87"wX4Kͭ. ҃On^f-$KY GG8f; PM ٩U߻tiei…sҽ{ 'x{sz!B4ˏZmW;a!L819> +ˋ@6w*!=<2]̏1[ww~7@^_qhfZ o~z2pdHH7"4 pt{},C$Cø$%ֶ7! )ǘZD5FL x mfu2Qq@Ä .:%P&YD"lZ4eD*1T^k8p"Od2 6UAMjrb8͕E,-C ]noonKqm''3<ۍKW77:p|=IȨpI:đ52z[M$0PaN`Aj,] w.M{~؅$B3(!Bg*`ϐ̢{lOe#+(7 1 LK! ftT `*qKF._іRu^a+҄. :XPCZ;yFaM B`CYDrU7uiRX`\nr\T'E JAtA\s(dV:")Rs5 Ø38DQ7-ծ0tzv& |-"(V@p6jwqګS*,2hdh8|c.sh,D/k үAG@?8bԆ5p&'Bw+RVW@a; \ƮFCp;T)2T'%a04W`1N5hގ\8UUI&Llj }ޔzj6 .)"|P^1|?0$Et>LxF IBR.do=q':4{ DQYY]}w-{:qzitGZ! Pٽ{ͫjEL$KAH'.oKPAs$+|,wRopRGvY'=$ܩXnzl. y2[\TB "zƲ k5ȝ"kbb];k?}G[[/|˄D|'}/-oHudH(G={2.&̽謮.r(":a3]XOf!@ݍuCyn=5]@j0#t)8ʄPvpa# @N:4Ο~W(&.jT8֩q?`CK^foW*AI%–lVÎQȄ| 5J37yr'pP؄SI >Yva3R$b`4y+ 0;{̹F } g߲0ID%R4V*cqmPB3+)9bvl<.X['n>ӷ*QFAxq*Crϟ D #gp 94 #m30' P8='&I$v 4q@=\Zm_ea3 0aYBX *X^ls?U_orw5j*`#r.WŒhNU<no)ٲ"ho[afA˨;}Q Z L!i?qV3SEmM[6L)2۾'۝0*5&s$u%i;A!nb;I D*e QCLō$" wL()p<)XLbpJ<#$U<,8!30 ŷ76:p èGu|ȱ)\)^~*H-Gcs4adY>4]ܦGP?s79&@%$%DTʅLG3`^|nyȱLxMll0Kb l+A`6|+&: Ip(UƆ ,@-32E"ꩈHcDlFa^jD$ yG ݽ(:/$TF/tGV<FL(0&KΈua8#wy*PK[X |2uӜp ^ߩ <<\J{g^z3aQ` gO8}k|r>S]H݅- _=\^ƍrcܩl=aDHy};z̉{ K;Kk[C4h8Աf dbx G! Zv*Wd C|uZ]֮h~zfա'~郏.r C cʹ3Ic.RWazn P+~wЇM]f/^oB<>~|8?R`pTa~.,,YC:i /䆇Sٜu'G.\az8=ۍ~`R%z&Zތ0D&g!alrQ/?8d+΃ ҡcGmN(nt6uzzAlWM.J#6 TD +/=x}O==;}$ FGpq]OlS[Ե.2Ʋl kJC}8?rlvv,=jSE]jD1(OfԠhg2>dڏ?{g_Bau~oDc!񞳉N4^jpYpfpHO{Sl]FppSN l{cJYNoo Cy H/G0"+!*1 w_&jS*Bb TXO,[A 0!# )2}P o Qt-AU`PY#`=PN@2@+Wy4 ':iEb&*Ƒ1v P lJ+@\QÅ| xK+v/~,B#$F'Ƈ)`L:@hMA אOg2m[uv>37'Nib+eQxKװj?Փޣ`O;J`L`Vil'( l7\a ߫4UwLvI .#L0,sp~6p߬_-PqQDvD 3U0EMs. f$uo;#70rALs(V3S8 <px $:^ރf)]ɲ0]=(%@p9h^wL25DY鹃gNo]߿zɉtv^|竍Jū&!뒝r݆<Mp l@/ҫǯ]ϴptz([Hg~JKwV YIr)|0{]CNoQ"(sIf>ZYX_c $Cӭ6@2X_ڸwA4Jxb<‹Ν)8¿G@8y ϿoƁG?۷=zuݟ}9~܎ܼ~C >11ΰ~I7][Nn$fMY{[k;En52$gBb9Rw/Sҹn85:xmkC;~՗}΂0!eP{:_W&H 2^dJ0$Pmn.o4BV6t~|l:B-X;xخ3TSl\f|&vc-%Hdrc% [tŕ?x0O~O=يh._~C fBRm7ddo%\I0ܶWpש5 f3)=p[YHV!0 H}wAx޲7IĻb"(`C(<0:,5 ƧM1\g8s#қo/o ߃HjC" H+!!"nPQI* ˲s5%`# $M&$,J GxB=Dҵ]DL!Xh=jIc[ϨE "=Lp<Lj#& LH8ڶmh 5Q%.h h*]“kb,rÇVGj)qrUs-э XJw%co߳C \04Qe$ReF`BR{(2M+&X*#3Rp]hGaW73Bn†pٖ^Юv$D?p0V7jRrL+s/ 9uFH!I܇ahHK\p\DZC+KD)RuxtlN1eE- BW~=ǫERVjR&͊< [YXxc MnFd $94I?60уeڻgI``A7lc`ƔwD|6%fޛ *7G JyU;L&9o,SwH5) ?PᣖO4լ;+ֵ+q$nx"bbc{9,@%z+feBl.5DMm+T:XpLx@CPB- ^[/ n%sG'v^xv6 6DQi.^hht G jM@l*Jսd, .юY߮Zc~'.^~ﭏ, +cS}7ŪaxuNڄ%:yᣇUko^Hg7n߂P~jvM1onn™Ao&W/ko}< a_)AJV:i^bC.RJ:y({Å\ $Z[^vRG) ud6W;$(H!#Vl,t%{(pRVE޽PgBwl,^a>pwE RVbЗa(kaq0jcxsu-)4B[nhB-Zi.ml.nm[PuT3&q!}@HkB#YZp0fH |ca=#$x&@$ԜX*IU[TDHY=ISvdv^b Q%z 2CgiЛG\GMN!TgkH ] D@gɧA fܾ+WCp*25ݨגf©^Mr\#T[GJ,Av~B r ,ZkTj׀ᜉ\Wk(I<"vӣeQZcaA:93NY!L@ cVJ"J`fa!.eztSGKeuv„ɧ=j p=#=–h?V_pf2C[LԖz(Z)|jD  %!caOt`\.[Ad^CՇd~7,%zFE3D 2 hE-?ij^B%J}_gg|^!0l/) @Z<@iS`_%:0[]p'uAt/lgDHIjix:!om<ڪN 8Q da"$)[{{;Հ+ t' gN=;=1y3/}];ՃfS-˧VV"Z0B+a픗7VBRzAukCJnUH"]Y+?|1S&;T֪lvZ8T PZeck;P@I%!SWvֽe* ;;{'_(2ɏܾ9.C8O~6[rܾɬ0E2vk%B1:P/Eh1m6ʨklo,?ޏWV^җ~m~.AƎsŗ_~( ?0PqT W~~ݯ}k*[t~SSI75=; ; i[^]X҆ Ào?s M9ku=XXsWe'̻ѹՍX[xIHPA&\@Aő;'oF1*cq=J*ۿ!?$Ĥ7N0b><<^doECYzbνkivqOZil`>C&ҨXHP7nt L  U LD'Q ; $g ZC@,E:ڰiZ6]یKP*-MKUjvocQGٴ:GՠZS"C=Pa2$XO,xad'6%c}bN?я?\vma~Ç?.\xZӟg}S`*W}OQ1֓ 7NmFßJ3zC`PB3 P]4D¸ ͮezoKE,ŅnfmIF(A݁DL&yr""%Jж@5&hƣ1& -R4NR>7vDŽRCЌXƇAy_Ot\\kϽrΜsQ!Ë+)@3 feYJ#$$GdFJM½F V)z$Vab$\j--޿7kb!;w_{gVկ .߂w}=s[oyk /_+[ ,6P/T 3S3'ۭ2D>sSqz b+5: mFQ |ڸྒྷt@̓I0ܩGͺW¯;y<`ч޸|u}qqr ]كlz*ۺYo\]aI!?X"͏fCE'?ȌKjY&qM'aJ#< #`^5{Ź;O#}ʰ008951! F~>G3nkP)֯\!6T#z6nK'M/^BbTo|Ѷ(ARXBÖ˨2%9 CK *[5mVVg-OBtpܓ* &d"TYKxhRvw튷zapޡK%x'8rU2.FRK[m :YN[3HZi3 D 悀Acqq 0YMBguG#2}Ni8j|@-ʀvSD#hhǺj0]<}F2~|supyb͟)Jfi gۣL飧qotӜfaRtv&=L▀? F>@4Hlo1*Fۗ.}??xz}K_! p *СWdQ%zSUȉב&tE 0C qeJ=fGčN(B5^p=p]ÅW^~ Ͽ\*+[K:F-0x'~ rՇi;w_O>&ڪ)Hw;z3:+*~;w}WosO]I ƈ?wk/BbSh@}95?=8^ͣhQ }nM 0D'WpQwjն)f7dQ.,,Bx*5RkG_:~DͶ䒸 ct 03)%)Qu:AIkU[JH?t`ܨ9ͰbQ? t/L,+/R@q%TUp[[[?WyxO7~9i|{֯F!<1xͧXQ.LK"Y;QJ:a/ "ҘBmBDjL:+c,SY&c[R<c4H1W?P$pK-g2< #FQ4^Z]IoܾPbt*ODBA xHPB{ \ȧXHL-pq)ƐKFl)u>ڿ0C dOM_]C7LԨz) E~) *-u7R+Ω]֥gϲ=.+;j3r" ԁXG]\(fU(Yl`=,4IsC2@ۉÌmgiXX63HXM ڃZcGGB쐒N6"J8óƙ􃛷} 0YXaN)վTCҔMG.*t: $MŸڡḴ$F'_r ɑ{#+}`|S}+_?-|65>ч}~W^x_8jݻb;k[Ӳl!dRt)<} O}٧i@Zc:iV-,!$}Ҧ@vo}SJl3W3sJWVg> + <:_]xXdρ/# ~#BP0MGGO;y|pueZSg.C/t-I `2-:V"!HX;S3uŢq# .(reYȃ7F*S7ҿq>/lG~.r'N{ɨ<.S;/c"<H!,'33Ⱦ\4ޥ@K>AaK.澺y[ꆳSun(a0VyҔ˲: E(UpabV7V!&(#Z8p$J ? 1g(!h(|h;(~;w!Xr`:+&b?sԠ=9biA?'k"14򻤆*33Smmŭt΍SB#?9H&a1ɾ`Q5"ii*Ew-xn*7Bw~ՠnHyEWOIt p=^M8A]lQz)_`'(ŌFsyL݊͋F<8롏@STlvD!g=c#ؓ&'cXY|%!=VwҤG2XAuq?`1ԘܼFfJKFm/nD $DOϻ%T%ND aL@ aEܱb۬o-~֏-?#Rrԁs+W*sU-NLQ)LR* IFC]hDJ*ٌhf P{[[ej{cTPWy9wVV!.fSзIyP}emsgp6ɉbnƾVjjyiqz왬;2ZrY7O? Jű O~)"ݫ>Z,Ƙ N0uDwתM!žPߧ0]DՏ ;\fgrF$0+@ _I%]][/y{W^y3Д//9p'\w{ʕWAm䅝ʭѯdso}O@rllScݶ,ua>V[Ż#d!&uš G榨X~V*>6Os^loG9Kuv94F10!XWX)O~Kvsuz<3:1ME(w7+w١B ؉S2p ;:x?z 瓖l)ؖ0!;9r ,ݺ}_yJ|Asc8:a["` D9PqkF:5959Sȏ8*c!ԸH0 m;۽'"sebR4Gjh}OL#GhLk:{tilOg_oDMH܎ Ѳ&_\2A(5ͩbvƸ[wC+-A5j[b[qBqHqBzm V'|AA(сA9ޱOTĜ0u|IrK Qt*t< yG⨲1XDXi]5ˌgF`j<2ORPI|o~w z[w_W_ qP~c@rdP TJ"xk<5Ѩ?-tԤB!wޤ)ifD{F"J1 $L3 »j "Bf C]; .T\ cxWRjJ"9&m<65bIE`ND8hR}{htbדĬlQL=]Pˆ=bCJTvK#3EGV='[>2)阨uPGG \h&~Fr"f!83bqD9:0w6mEdT1:-CN X$ NwnxW@..?vSv+[YYᘤ]RLd;Bqԅ@Q> f'a 㷈IƁ)R~\i4Jfi^%w X|C}^ݑߨ.;T̲biުA {@>Pa(7T՝m(FI&aᡉ0?3<bs/ CsI/ny^yXCv/?2ాFaÌ\Nc`iu#{ U%$99}_[YA ]?+T__>}{֋'y o.o?YH{ͷ3n٧:?|ݛ!>99K~ 泇'J֪/ДwB3͡GyitX HiP*Ð0B)%46`! aF*TuEošE20YUq@?OxX.4}qcD~^Ƴ c̻CweV!"*DaONCvnsz! nRdΝsKYPJimTҕӑMZtXX'@㎗(Xu-º'Jx&򸨵݆Y-C^a~ ;*j?~/#5xW>Hi4Уݺukeq#FzVQ<ܼu+nᇐ5h,Ν ĒM>u,DI$<}1I]>bO4A"flff5}QB ^t+*@mIh2;8C-wU3{]r 矜<982 9xlHV z3kf? 0TMTB\q3^mӬ$/eCĖ:ԗ )w6(.7r4_Uq8| z֚ͫk+=|xٳ3S#C7n|A\:|f ƹ#d!jJaӂHD}*1e:3HZtl;ÉB(]`¨I~Z0$7o޾{~ _~v˧7>~^P)w쩕~;|W}۷o'=ӄZ@z87)0΁ͥ(@# 7  BLY0[kf@]p(A)H7Pe\(=(ݵM,Y"O?Yt ڶ@"ps CJݝF| @ _X(7`h::4<y\ḙW^\y|K(m:*O%GGw䵟~rΆ@6+/>sԉ#SSG=z7_[]hcrj1NaqJ[њ6I&A[_Bt-B$ 痛Oz(Fl=  ^"MO])Qa9 iڶ=,F!)e$5wbTf8yݱiBџIQt"B3hzap&MB%G\D=C 6KV[YfBfdB*Ѹҫgm /^qcZu[R)rD3i; OC˕ܽsGnO?sh'%fL1Ң!Qo؝=ཽItcj60Z(=#_̰X[ny͙cBW77vt XXڬl7I}l&@dF g=RH3p6+n晄2`*Mh2=X\scCcǟ?tI%|t/&ct8`0N¤^Gکr/a+]JBq463Rq @I۶ǡP`4ʼnz 4EE@ᡗ:oO^ƍkgϝ>qB6?|]<3ew}$/~A/|Wo[kb@^^ rx,eIk} 0##&wlPDkv"i~oTbF̟啦B~4$34> HQ"@B~H/~t}j)$I6C]uO)kv( tmb0xL#Rk7N>w֍+3_Y]``$R\/?{}kw'Nw*7ބtL{8zpv23tTiljo?[[^eMN3Zowh uh+l,4HXόXa7PU(Z""thGzLA LT"J T.pf@6X]/=ӻ C- 5 BŲ!Er`H!lM K&/xR:>'Fq RÕF6AU KJ?01_up'*E-'--/|k.5SZ0lQeJ2[J٬P,!B1wlu p( yDi| voLML24T.[z{a;z{=_ih@\FFxo_xieHyK_B_cBJS_FKa'Ran<پgX,՘ P@Ѥk{E_pbtA[CM2eAyhR3i!X&joVNd ͬ8Zh&"Ն8XE| VĀlac{qi|{KU{(=S-J,=.۽h{ڙ1E˧ߵ-X'c1X[ނ@k9=LbChݏѽ=(86$/"=F,\ 3Q/1^E X /N9g ]+37٢xf<$3\WoÚv-Fg3),-%yhbYsJc3G@H||_xgΝqb(}vwm9w߿wHMMMO;庅;nG&&p66U_ FE] O,,.֠9JgRBTP Wַ7w^.BEe`%0VԩLD% ͇Wy޺uҵO.N|?+o/,A*{}]+ wp\k,VD v7R]ww&c).LQo|,ɟI6/5{hr=WvK; 7U:ɝ m 顡TrD#k*~/!,+OLIg],R̓tD Єxpo/>hPzu^y7˨-|idz,WaH=xxǢ̰ewݻ}V r_ZZ-gӀii k/X{ cdZ݅Sq?$Jn,ށowFGS#CS^خ6Ae~Og9l{#G- b I053I"uEoO7 ?L?Je{G;K"|>[2ȕ0@'8~X!C"-+ٖ!EZ(' }QW5GAouّR=A(("q,=#IuY<;+<*da;4bRa !^$ڝL )VXcvRTQ`2 =7|R |_I룻woVOr{pP_|;C?L?^)a??iucP*E&av:pAvazHi )2/fE?&+ C߇?YWJ( Z lTN4(D* yoGR sT}߄͟qe4K~j~"h Ddr<: TA 6gQqc1G^`L*mSU, 쩈(a> C*f0X53Zy'=ǿ1I!îHH.ڥe6;8:y X}7\};x \ꈪ7p(+/h"NL@)(p&?-/P 45ֱ l's 3ݕū+D:'GD"Kg ')޸o tԡSgΝ)$XʵB(CW7ӟ;C̍d!:pГiw3ZaɱQM$b)<[^\J@ 0Q [rkO8Å0eg 0vNBwʻ 46<<O*f66*ۻs@ZLg'  o+/ ~͈~oGڻ:cƨm T Q%^=B{kԱ,'4sV?wDZ܁S1SK\̵)Ōb*D(!v>7415crNX uFWWˇOA~meڑ?]|'y~[ׯݻ_}Ei<9\(z=x~c]W=yr}wgw3N/4Řј.,W*VO=V'qa/M${:jD|?"slLwԆOjGOz $/eEu@fE=Cq]4ZDGrbyuq]r5iUq -QxA݃8\6T#Xߦxb6.(BDԏ#y3g07=X.zGgS}AXΡZ#(̰eQe$m7;eILVZ=hԐvw7Qy 8fm70Bd0>ppȡ#'ϭ.-|;[n=x浧>CGHW^'ު6aã,iwv(SÇ2qf>{ΜR#-) 1> V/o(|`'W[f2Ӡ)WK4$:^!݇}ҋ/^ՏO:=T:~B, 9:573%Qkֲ׬>0~hC"S_=p?hsUF'JSC #dDzv:9VMD+"G]9:5 \[;~dƶ+;ꊅ8aržy%FN*͘C5(ehf%};Zc3HAmUs#-*LH^OZ8cqu ^#!JM'&=)YLaLT@pEw4$6=Y*t#*kیK䲫)"E8烏"瑎 &&]ٲY@L1(CveQ+c' rSF)HDZ3WMBRh*q7M3A,17nk}wA|OLMwHlC F,Xſп7V2>t_ݹ{?Oӟ)ro|+_AT>h۳#r)ƻC,j'`{ogsw"O?n1- `Ǿ]qJ (yQyգި+>2`Dv-tlQї 0Ć8pԈ˦4q{UHpAE =c?F$~&l6Oά7Y@ .VP^PIz-a3sb5)0d<'6lҟ$Ի#^c? _x@"ʎcs3ӅPQ_|'[2j'Qrݩ,^̀FR(mܹ3߿SFF[ilWWcvU(dJc#n6 WJ{qrqtvRJ 9:6:>KVS`^2 ]WO;$H̆1Ng]d"(,J%ۃd͍NsglgTT>*ܪl#[ )xoRABdPL&ק0zk]~ Cގ?hhv==Εj;WiFFP†n|x/,އY;[-~=7_ηm C|&٣fsW0CsO?q*?w*oUHS/$P!KqqNVV>#Z{˯mCNLbX_nNϾ7BO?}m iTCݺqU?.2YbٹgΏOܺq"N: NiwV-QlsmZݼ˱o[ i$^A%^c8Qa)k_8c3CLy |iGBzRBB9FKWP*TWn huۼ qVm<0)\U|[[ݩ>+¦KB[vXbqݶhm*6BRq}.i9HH¹0pĐcCu'dkXcJfODX & woܺs;[N=H(ʕ&wm'J4\s ;?c!]4?0@ $!BB]#=O6LkCτݦ$Gba6&9Y}fw>_,O&TRl, зG\}f8/CӉ"l{Q#"\.ѱн̋\pg.]튪lܨTw8A:d&537~ĉ & Bi'\Xa ZY٩bl8phbbZb$(f|'%+ekvnՙTtGE6&Qe+m`l>#2g7˄TYD{ҘTm pfgR׶Va 3!0)ڲqǦ-*COё1NƻP̑>*궨vՔX!ZݖlT7Bh,MT̥ oaidJ1"`b "2TB;˽'8]yn%X?_iwߟ=wrQT/ /'tOÇ+_Gſ777Mt+7nXd*٩d>IefJ#gV[/-w#/_Llm-2T Nw?6>xovvڭۄ'O xZLrzj8|~8{0 da g LVSݗPnr-0֝1S?GXOĬ׶ veժQQTP,Xdಇ?(7@70 == yC@ l<4Hp bX凞\a)T`ME#N\$8O~UϘ(Byϡr28NmYl!LW (%MK yԔf1\bD(؂}cXl T`K77V#o+;1/]7ȉV*q{)LHHǟ_Wdzgϙր1ߠ{Vcnnvffo&pPW}K_oW^}f99=emۇ~~aBR")Zrqb9Spw~_"h:_ơ7A$lۆJl УD9>B׶k-ժ( l:cL!މ0m:&$%B]'GZsQr=3ΑfYbb0Z F_3wnvh/߃k٩hKjK|_ݯH*$Fʔ=8&)QDgm1TXU213q_]lxD0Pc>P .m&{wGQtKs vx-H(uKe~݆؂0|<d|w GZċ UE KP +)0۴,Ϟ*`Aq 1_x+g&6C\,7ޙ{S˷Aڥ۷/?h{ǒǀqWg瞶wo Å,W'@,zN*S:vX&)mn8{ZLO;{8_*4[yJ bajgzAڐ yoww$0pp`ł5PlU®+ eK/x9퟽o~jt:(o|XkrN``/#q[ #ue}7&Jp4 qCAā `hGM<6R?% ɥ- _W9s=.ͻ.^%\]ja6(rs{F0 ^ǎa.۶Bقh5/[L2yPˀE}gss)B!Qݭm'\a(oRYwdc<54><:41L'yS;pN=x`s{v6OM^͖:t:"4wWܹtg<|졹fjcw:={7d6_ڮNNP! Z,Ͻ͘e5`ZeYڱl 'T ]/.!z`ݜƳ |z&O\MQF#0Y0 Xz"F$6K}-"glGcuIW˔1'SL _u7R XEP0EJv{הHB~BB=:kJB=e!ic&2M92 D(Dϱms}u6p,Xᮢ20dex#}BܒaI" [d=:UK UQ,I- bH؄EIR)3xB$cw@O~MaBNт@5@>?Νc8}W~g0'`~Sk 5ٟ韾{_ͱ9Pz'[^}/r V9YlM! %#Ir Ioa*Ï^<,6&;GI#͞u2l`?B{.j iSoz]_hoʬ7w鄄1\sm="`PK(AK8SS df'1V`ꨡg?9ѡɹ#3OO^Na!ƽ@dz}$UpMMvjN ";^ +5benu>|&ڝNRNd3NX8-/w9|4 1A6(S.O?Zϼs|S:=}lb|7W;asl`3MuZ((in &c'ޤWx.^Ǚ7[jTBi(}\aIVb ²0:UsD!a9D9Q|.N 1/)?hDȣ68&+\s~: V"ʰWY]R6'C F>ukR-!JJ}3yKIX5NH AhD#Bdyh#o q(,N'^HPGɹB\D ጘԅ_\n2}\/ Y!cP~eٳZ/O>o$E4??O ŒHޙ'U*T $H^ErAϘ鷾 dFbAL(/m3-CTeL:I )i4kuH6*+qjըS'(Ё ,NPʨ1(_M`lAu$]K8cExZET7^0 3`SJ{3zz˔ĭdE2Y s1?np"Vt?qL`,m)[8`:T9A%2ꇠ! d8y$#$cIA#i@?U= Zn Pk Z}PzT<=3d&&& aPe})BS dXZ_]\Xh7L~饗~ڵ+W>tß Ľ1)r gPVtŶ@}%|N(޼y)-r!pƯHZ ~"|W242}=vW~'a;SåHR0!kr! 0o Y95( w6[+@+fO\83^qڕ?y¹ӿ/<4* /\8cyy[r,TW(BȔ(-,G^HOPBD_ж^H*1.RkDUX=EG^Dpkת1G犊n-|R; _{pyg?g&|"t!$8N}ᇕfNzeou6ffÉqJy6vd"76:DJ{>wG xZm ˦g,nÓX٩>yH }_Tdv8]y D:cQ<|p{{s[N؉FK ˤsH19F _=ubky+7g/3Gϟ:t$0Ofƍoƍ[;qʙӐs=0k w(Npk"\Ua{ a͞z\KG(Dq KПnɬ M4%9OL"e80'; E{iY/O #WǕpя NZ#Ť fn^:[pB@B$p$ S)%< D:@dat,i m'0tZHV=T)t`Qx2`$C8c,uN@}Na7PDH4DEw0"n\ 6+sg}ɺD ]F.bI@Ɓgל , .#@7wp"lRHr7C0AŶ_a>AulqĹs@!RRKM{B)5ؔ02LBX(Y KG&yNIR$pc1 *\12/CJ$`p*gϞm[]5u`!A0Q75YU1]=I_/bn[ pI0~w#!Q;7G;w7ՉjlRy`9:nd[goُeY\1z./rupP+J%Q<|4Q=5zp $3R޺y1=5933T/ Mܜ^ʍ3RJ~je{a>C.n1 whEbx'??nZ/!$ Lzp$l9~XU^~Fsm+[wo߿lpw[S>}g7W8pO =Wl WPKQGRCA:-3HEhݯ~fZDPbzeS͐XӍD2Z:56O ?Y+ `4M'iMEw\% )lj|p ( )p]wj!z8a!ILT x]O\gܿ%;F=R&!DPlA$|7$h"YZZˆR8 N,Q32DۡĨ)?@ǖ0 rD@Pp3 3scI$GQ`>Pp7/-L`qIohD{ wi4]aA\Ü`),{dЯ:R`\ + B!qLMe$YX;;>cs/1(k"-q> BT_wܮ}7v)'?Pkl'`nhulYty:!M lu=O>t|ɫ7,im\\[bԨ`[l`HrV'\.dTXno R./C*Wytt ͱTqd\]ݹPO=wCǏoo^3T2wwN8 })f%yhH܋9ˆ%" (@"6t0fM/dH*%($M1yU*VR@0Pks=SM5 [t{!\Z*QSnn=|ushi|=p \ru8Ag$gRVz:AF;Pvfrtt&7[l~MiQZ49nڮ.]QtG?$VqgsF3cJkO°S]vNuSٗΜl01ҭZGjۂ[H%r~L9[t5VU " R˱ 9%eAZy\UؑKR3V•@dJ⢔;B5j=G_8YG օuKQ?R{HC)[H[8;'W bVhc ?:~$~Nޖ?MpbuSCo͐o$QBޞDYIDBXD `EGw,[" '1Sz+|̋/u20%1(0"F.:$.4ÆaPNn(_*=p Xꗇ 4.h=82P~Ӹ}F::?vDGBtRx?56F&@v k[*OL:g1`yԪxo[7"T`{Z. ,v.|f:0R&k*UsXSǘb֓w[l˦:z-A1#mi:`x-_0\;AGev< =RMTrPfo!όU=0i _ A,:AN9q R/%9u(Bv")v]|cwB!@s@,v9>V-fSm ҌSLe,m0f@{W2Gv{{^=vh2Eʀ6ScBRl95pm\JeKxkplN[[;kۋK榲li"7ʷ\|W_zmR.H;77o5;mXR@xnRCGrxu#t2Law*v  zR2prBXt-q XX@ʨIg~ rll+ΆA:>-0N=UR(?ҹ3~~g.m,ܮ<}vO>~]_ܟ>Ç,`Vn|Iov!}= 0ll]`@lt >1vLgt-h*~)-i` ?Ta/b)G E- 1SUa]a0Oa8QĚYc&e{CIWkGr%Yt}/LdQA!kM^ ޳}, (^{DT?p?0grԤ:+N߻B˪NXB9JHRdGCqT9f3OV4;lqD1$'uK&8|H)LpP<뎝@ 3۔7a(}O b(Z]zZ?]~FgU#ĥzljYk[?˩eM ['_t)8:x;GҮh9:eTxD .K\pVL] Px8zߕhUIpe~s/J"H2B%QSq\U3Ol@o ;60up.4X`lkl6e_퓇K&U1ߢuTLHBY"њ~qDЂ?/|VAX7u`(]x)qE'E=Ո 0F(gxc"xl?$Xh];Ŀ#9<(b^ɻx&JbkGz˞]ʘss1L.!/àՂ9(F"2M%a'&aPUx?/*X=[#sn +C@9^eF9 }\~+F'Aزf#ܨu $ϖ,~GoG՝f쁣C#% }߁h5*L\u˅<0qObW 9P*[MNaʍ=DBP#y+U1\Pf1 X]LmM%H)+٥,ItVDr?&2|q?l_Jt ٤ pE*+vBj%JՍ[K :~4l]ǥƎt(Y~U^닋B'e=ߩ&;/xg̵jK◾r1A2 <~D6Nr[xvM8-N80wp|q]Am3|?,WԚI&ӣMS3A/ I*iLE+)P,@$M!:`cT*!pYJZBB4쇊'" eHmDryJcױY"TB#nѺ72 nh7,GBPFUig6;ɏ0Dmѽ?7!!,ʺuh\Ag_E6bKAk3 |=FB($X5EaOl]@CTxuOzw-i z=nLLEtF%.a9j u,3h"If Jԍvۯx>1C8 P{ ^L"N%8P!~Lc$R EsfB*0fsoue1md$:~t0 ˍ!Lu1tek GeGUXcV#^' |.gUP1@-9M{2_62Oȝ|vVһP0PODY#4 Wv(6Q>jGK(vTPIno}})UXo1ץm! ^=d dϛITDZ5p+͓ B-p-<P.|,О$P#>F#BL!;cpCt2C|ے`񃎍l,,Fbi'~Kh-f[IjwnTQ,A[770-0I0,.@j la¥waY2MUmڔ1λaV:8\LĘkanoێǁ u'nWTk1wR0ҕ}e3( 38hpώr%0Ghcl aW{.l/#EH@RRmnmoNᇭ5Rql#hb#Пjh,^)$=s]CDI` sU&~<|dh$r/Q^DJdiy꥟x套y PH dY^+TwF@|уs Lx~NmP(֦V"%%$ z !vPG&IC" A'xplq锥I2PÅ2pvA~-nTvw[[q& kͥf?X̫_x'O~LčO>yxpr.D mĥM9PZNl? 7&M&V"C00b/՚]#qKsHHSX'BNZ,Zd]f iN:e3; 8~z" հCJ$ ( s= rcYksxxt<$w7Ƀ\:}t =SA#ቱgZ<~h^ 3sa ؘfV곴Bm_pp㕥/]{͏߿;9}phJR<4h#I73H ;BRK_'gٔ@` )螼!1?e ] βT'l.<"v)Pu37HBdGeO٠_H'CQj2?6*b\ 9PĈ1C͆ :GڢȸHOK)3[P8 Q \٢`D]'HuD dto1m?^w\A"37vY]3@xf20$8 y"Zz"{&L X5yC1 ILT4M"&*),Sә} 2B(5_yǛ{ףrνu OP( eQd !1aQg0Xi$&s#$a˹>n@AGu;8쨎dCt$Vw#YQơ[w$sqX5n E`&™m\s{=ySTqa$8?#Z{,tH`F[ -Ȋ:T{J=FJ10W,i_SڋAH Df"fg)qohfQ?֏ Vm`D,l1> J5b &4BX e_QL⑴ko2`eeQ|5vϥ!ٕI.&Ja(@{3G&5 `{Ƙ9C~0=ED;Pvj5(2eEȰ0y3*I]ƪۣF38Hool+-༩F́fcDi; , m{~9="g84E}!B&V4XHp\kg)ИH8X:V틌 ό!u]T^Ǥ5,SǏ^8bNؔI$d"Rn5; -=>2_\nRkC%U5VO@MqXv^G)ʧJ9O2Tz@n6;2pw e Ydd._-o567u ȓIN|j4]Z[_XY}{n??7{T ϼ/ͽV,^MVV-y @@,q]^!:Lrl__,2f"Rm"eⲑN'l7[86ʒJl'N?9kvuy{3=DjacZB!T6Z]LdRWiW6׭;6=I-+MۢP+?b[IXf3(@bN ݛ9N}r&C#FuJ8]w<ޭPϽCG/ە.%NRm{ Xȶm%D_ھ&fB*M<3SCnU$9L?kb.BNG.V\'ELvcE6 ^78mO矞gDwA?E^P(2}8\D騴\%Jy@1 ޶mcj*殚g.`ωYg,1k53;=:a @3ěZ}8@0LY"@TU%IpV(8kanݝMa54Ֆ߬Ze <=O칡e=6C_Cy<@G+ 2NSfFFөbX?&Bz謭_Y\N8ϼXfN#NRdjeI&ia3z0N(T61:Sfݾ}{yaR/*l2@P&ΛbtbM[KcaڎXX]iCSF Rnlml.Re[>x؅g=@Z߻}GT8{ /_ Fu)6Zl}4k*) F{_'1J)La!4aCDHՎ(‚B>ua@)S.BRaO>:v.Mu&9vh8=jջ`h39Jeu]W;RNXT_`f;)u>r%o^٨NN\FhNKl#]X]..ײC̱Y?|j#80w<ݍ^{ &F"T!.N]xGz1¹[O+BoK?o,C&ƨR:NL٣e bd詃+>$𘆳.X.xyT`oq|H*E u1D+*`OCr"ޗo֋ǵвGv4#j`0pϯנ\'S^b<$9P sP!M!^ſuE #*( T;h6$!{4dX0.M[IQ7ڕ$L &Mx+PtxI +HP˒QbŰ&F]׺qʨs QA 2LoA'00fHXv DG^ rtU4$rS˓[ U85%×m͓BŬx Jb r-Dgi ɚ4Lq%('WwT ZfH~OnuO ]>M ;/_ɽk' mȧ4*habvbؽLt3&d1P{18C~򘆰=nvo.ߟpS B 3j3,d-InZV%,0@-FcUYl`VjeܬA#NA>͉pozڿnUQX.4|$C 0"&t%$9Q{(%$x[ۀAWs cnx0oSŢ'+-8xNm[ĢjPr驩D2 /_(JSghECCA*E^[!nV-UpJX]W]+ T2|"Jp Yyν;w? ..tZ]<KɈ ͺRxCLK]Y\Zip܅Շ52}BT`d+ä,om_:{!@!VzjtHX݌xU]l=r9mA4/?Ra~|:NJCnb#Ա3HGo|ѨZ AթC_@J.''=5ɩ6+MaBUrxJfDum;r""?cqHkA nR0FOh)?Döc ?AjZ8>=8?'\ ,5V޸N'j^FdU ZBy6la7s8?DF{T,ǂ lnmJmc;kKK1b3J'Cy`=*1|N ufZm( ;~pvEz^Lu]l8|xSI;9{y;~Qtl||2gp?Ba_gy9Ǘ.?H߻\  Q"D3}ZCOhބ 8\Tue2 Z&l~I$}gcSO7;>pj%0(ܼz-Ź\80Dmp\.upײ^p4{u!7iS&0$Okm>69|1kwd*ÚQl,OxEz"q!PuF+b@Q3̨31G0qWI׼I$=y#oٕ}Ď)CaбK~DBO,7I* H Gba`E=a-`A,ԛ&Q^:)݁_BlD)IfÍfhp@N L"7P BBRXQp0b&ȥ4i[6l$8 `;&xaMdRJբ xj.BIf@#!̒D%N.bh7KU<ꨰk/  PQtFE!ѴPP|dj N.p G2´'9A:Sgvt:3rI4ؤ:1DGx-2+8ץ& CC?{< ,6Z !JGSU5k(qKҍYpS]}+œ0cdaB (iɩ7r`@X3tHtA (Xf,ž0 IX{#qȼ%P$aReLah_DDx`̮絶tQC&ZJiG76 $K& _ :2:D],)'k֚]Gk=\qҁ'&Mܿsw,uXƎ\~fQa6>GV lEy[zFPb`}QY]BRIX,W*Jfq3=xp߽|^yrzsO>̙3Sxv!U5{}#w܃>mۉD(PJ^Z./z@(X;+w/l< "ܬlRAiҕkn(=7&SR0E-k^ @jT>67f3q~WnfX1}_ʸ.}[߾[3[Ke:KͶw۾ǑQ݉ bcD<(8 ByŶC51G 7 xm1imNΜ_Xغ~ꃹc#Ö$Rq%Іdo M5H5 4 0$GrѡDD 0ඓ%8^PHQ.ί$,{jt(Msoo5l42:Skm7; GNls ہV5`)e8moW*`kXx{o;}|hh%>jvmw Ky˰ӨA蚱 QVCNzy&&DqlmnlP֚c'&@:h $XNIv!܈uxˣOΣA@˟ܨpT{Y*|1 x%X>S GcW)Rۼ`netc4UѪZX\zeH0„±TG~D@5՝ M?l)Gm!|\+èmШWĦy6RN G.w"(H{ۭ=)=?1Qt2O`p0ev $CcI!u&9m1*ǁ` @P,sV} ]a* ( MB"\LlĘW 䙧DCYp$\}ޯ~DnnZ/ Ǒ${]E(?Ƶݣ;~Q{ddP*ХuՉĵhA\вK3@ғNԟ2ĄtL}'#94ň,(ySCr]5R9C\µ͍ŷW޹qc.FUݻg??[uS鵙'm6VLtB^)<Ĺ3~92VX_X^ 6ڻ#m{|RmkCC㣧&f nÇZ єR&\n+xx4969WStsgq ?gQGdy@owy8RP~t")O(KU f$%l L8PІa^ngq9T!F&:6߫6kRJM=<<6>6c[[>rMݾ "N0beKb);]io[Yi 39z$JE) Oz3|p).?ۮO;4My@[lzS03/;B߅,9|)p[z'6Q¡CFwfyFgO~OL=~6f-84;{N | #;:=K2׉C {9H+0Zqjng6o=l{[@Luk 9`{8K4M P?'EA[ ^}CAⲭ1JǛxlWF#De$F@=1ʁn?{p?z'J73A);;E\CI0,i}hX阜;X&B29k"2dQC# qܥ-ԧMkE,#4)EQh0aɥ* `qY(Uo" LMՆSӤ24GFpHUіVa bҖ!sĒ* veR6*]%v0 0b#I_򶄏$|4C-==5NR #Nen䈖Vl&g\Nڼ5+-A`W|lj1ޮv? WFa:LZ!*t 5f@{|ѥ%g|M3XKk#'#q;*Nq!)ME6YҭmGP"V!κ1AhsKuErX[YA Vlv,Ĩ)|_l6HA+v@x{dNC sb\PGc; va&KF>m ?殓[_(Χspb󑐊dRDG]u,Y `p.5hqIez⺎ࣔ7Jk/(`aP^OQZլ,PZR*((X;=;mi7͞Kس0qOC(knDa%@]*7vK+W֝}ءlPwvk<#[4X~Z;mȨ5ި~8'FsҩGsϜ|cAwYVQi*nC=D-O2tnU h+f0!t1zY=#$fHܰ*=+4L~"M>!@@Jo_-8uSw^q=t*~ȱ Hj4 ;;^Bq@"2'B/`iz*en\> :u:Å|FVo_ɏX"z#fɵ]&n^[|A(å,P[`y~ ZT`u ©%8ue{>Jn&={&LJrrDۡRF<*]-@F=TZ$2SspK*WxyX nI~\pgMl@R <6ZI!R- 'vybQhkU$?G>nY)i!={[=6Z E6K=ʇ."Υ3Ļ5UH#T V[sC*F.L"EqF{N(E]* A֑RAZ PLǐ2CH@,a9*,*W"iFۊi4Sa$0&Y6MSva:G0JBg6B_8g+{zǦmW(Fh~ KB.3z,L1fӘC>C|Z(qHd!#I(I0˩AuE(xn7a2IbTMQ`i Whhcbh'cDg(4JD>B]CTa-|(Q({B:r[#[YY끹*Kp|]M(R`t4&Nf0\ 1 MTY Q͖]lvNHA_VrX@ ,L& :tڝPu`$R!`AhKMp3B)R>AIˊ(=V4y(b8Ta=)__[( EtKۈ 6U*ɔfay#G|_v]R?ZO>Ws疾s4|yk ҋBbA'-wA4yD,:fs˫nܾÇ&vù;>o/ fn~x2߮,mѡL+W/޺sZM?Kg5jﯮolw,)ãSçTYā)POD)^~O܄)\B:cMLB Qdu~Q"5 whhNë$3Iry@P$D6h3%r2\sBn}?M;janr) QBbs4Z/ZGL7&\@^"@%#9.QLl6 >"Cµ-&-Vpn5m8'mI{ad6HF{YHFQT[D%aXa²aTEU4aBǪy6Sͅ{ xݳHpu<Ojopz#dvCT *P͝ aKWG ) VD&0tڸ1DG}*s`l\'AaqcGy,Hj樀% x_ -!$IT[ h Oo+阭?>uYѾՏ-fk Jjk !R2lp76 Ji&"HT^hh {QZB>5PFuQ$%Ұtz-Fܼ6"acGFFpbՕ"n%\ b±U Be3{A'hkt Tq? pw[]^|;CR[pc@Psaa $Z@ Pf)խl HAq@|`^X6Hg$߿),`M-"ΎK&H]!N->$alW樘  IPWw-j뇐PDzե982Mt6x}eA ZjE0ܒʥ._7۷w3'OM O~ _"dRi+б ;A 9voI% [k>A4a&l+BkxD#a>>8aYzapc_gaPt3 aH6G@xq/>j\``0 x% )B{WT \Q\>- ur4NSt_FҖp^|A(=6J"[zB XW]\Rwv*C/aAH$d4NLWzSH(0iivqD-"`*d8m\,m! T:D) uqDq #8HJEږD HISq k4hqOZIP\|ˎ$LL;K'R\Bz"B?_w="Hd[א>G/ڔd6bݬ)59đMF ~/ vlwDsyMb'#ăbɽ$= ]+p(R4+}H'.K0PD(Q$c3#^)eVVgJFM<']U\5>"OBFnRn0vkg[q}o4[Xb&djJ4L:iX0[aL0 kL,R*f z! 8լNlp! ͵K 8I)JmSm(c) QPB*$RKDU#^lGY8\13OeM@֠ a@( JJC &IB iVntZC 7v Ղ%*[ېmvCcbd{|ye]ުәz'# D=$R8~zsgn^rś7ܺs{FRZ}GxW6/&p&/N$ಫ><6rcY_X'N3岩g4\H+[; ua{0N'6L=5z-Xbd*5q 8=5U1 }M\ͥWS/M3wב #UlӂSp\ͥݠ^pƥÇPO>| kos)Y 1g9F0D..K8ӝX6{t+}s~xI5$B@ Sz9S-. 2a9ˆxI̤?ᘶվqCl`S~@4ZblXm"}" S#M7a±ӗƋ{bDg-!yb"F!(hf gbV>{%\ ӎ 3<0HKRhFm 91}4=7NA$ c+pE U+]I̶)iYPs"T3gxjs\B0(j XpmMw[8BA}5D*!L6p`sc9rZ CƴSN#Rz\tqF4 iAh JP>H!lK)&@1I2$sSo1:y6!v|BAoi8A.phh˖!, H!a,'|iI+by Fi򝻷aC%0 |կ,>ȰKl y׭ U$\-\]P:F"^mxcG8򃥕5;|gT1U.l&V*3z0?3ƥ]uKw)[ 2pnc䉓S T5Yy'xKU (?}L TىOkoXY ,?_\]MձRĥv:~ı#lyv֦g&sFR7}3g>+u|;M̐,ݾ*_ƑThopD̫~m}>'V 2Yvf\'"x[[}M' \˞7~}H_~U!Cuܹsw _|_/<~2;:'hB,.mTCKͭ%)$sSdPT #3/WW$2k6߮{~|Сӧcc9X`8?49 8yꩧ5编h(КjJPUNHOZqꝵխ +?xo8y OJc:YTwMsm70*~r[%N图6KiJ4^9ŵTɩ8D!x0O}h?,3G~ذX(R*ـQ95 |hB@u/җI&R6gC$*<+=0fq/Q `3M1>/"r:}O`a]-M !i32DƎ$T01+'%рIa<UTBa"OṬNDjOHMx5()A`cb%BHKm&-A m5iY$Z|ȝL L\;%ݞzD $)ӈݎ$Nx3 R$xHEP4˪'QTk#HI-PVW&՗=)"e!C#u*CîF']!|S,͑i<ݟ9MvYT04|0T 0*c㬹'umum7v;ʨMUq@Q| Ʀf洖m fƼ/Ȳ)ķ>8 g4x!cն8t\j4FG`ƹQmA0~ZV)9B*AʲԖfM;8"lmmfj*Lj;E aaOƍ0 Xnll Řd9m'"&w ǖV-R1l ӹi`<7@u"H2(v )! VJ1ǡ }(b9/У78'~arJ׶pk'ÄBޟߠ̰@pmxftM;@fRxl J".xZl%f*a7#/8ߊz`B`AXȢNžNaf˻VB$$ m_c*vWC`F54v(I@FaaB-l#233-7H>־jp.\&`a^\ k+7/#3:vǧξ0qg짫E@N!0띺,N[*AD8ӳ)[mōe_r'W7 qq+׶V  G*z R¶mf f@#$UJC+Wo:| Ro{!=z@2~ɧy@uڭ~|o^˟)0:m1;uܸyKYߥvBIk?Ga3(741dL}@wj\ J͖]2k!/b y3S'ی^zƕk~C>=䓀WWܨU %YOM[ő\"w+dJ;tw-tPU`cCD.I e0};ΞLf#^ëMdnI­Ɂ߄3yݪLfjqS'?33s嗃}'?zll{mQ4ѳDzp8umo|g<|ݓ3_:tj~66֮_o7;y٧̤9;P Nāɡ0T@P!*gD1J"V\,@pʀa?K|/ VQJL׽o_X~ 9@,N"8ó waU1Ei1uOw6mÎ81jᛸ% uv/V*1KtLʯď=@bZBCVaDZKIeAXX N&z.EWCJkǮY/,FqW\hDgGI" A&"yɜ"ǯ 0H&thK ZM1j#jajI}z VBKV(}ð^z_њw؆? uo% )JcmxLPkf%sQelFqL)tmG믱!=Ucj%QMm'6[ \yut12TB>R =Qj cT14)7.pJuWu]TϋBw(KuFzXG`%1ҎIDӣ;z>iP{@| gI%9ro f ڝ\ABGe*Ww{kyi1q1Qa &0ꞛv$jy { +% (\l<džR%pXkalP%(5ln 8 kmG(]'7~޾v#>ʋ>O>/,]aݻwWVkM{w3^MTB^ L}_?jht臲<2:U]h T-`?grlvx̂@#8 no?LX-B7qTu͌-Aq(I;9RxA]@W)>sOeS`ч~wPiNO 29>2K'BWlEtM.=DcOd>G%5vj8b#[8F3Ow wOVVv寞;r?|~u.Ci R!7 :u@Ă9\m7ʙ#G %;[ asfF,dž/76 ɺF\'ub qڍʅoj\AP8;1u`nbP*k.]y042 wqrőJuû 6ccӐ(K'! VB0'٧}fx8]YU<ټe9RĈT0WԒ@:#0 V EPH}#%>2e\>4%{m2jaqZsܲOu/FgS t: Qh ~iLatc"JIT)œ қ;nN\mut b+?7?B*-CΔ,,G1&< `fn6%e=WA}=y4 7&1G+qD9I]**L2X~-Ī NcZP Dba%{(a @9Aā5HbXth $$%F:kDFNhvG"X}K֔_D$K[ʥٱZ_G 1oQ *5q5? RHUGD10W5 #聯֖{h}h[!~)| MsBq0г:: kFGGx465P 3(:xtrP+5PҧI-{># 6drh$$1 ҆S8d lU 'yIXT'*Z}#L4H37TI7jUx=J=H`IUa%@1߯K#&lD"]0 ෯n4RU,HjL+Ui,K@Uʖ⡄{a0 x ;*] *4d/TPo~l`sH@!JSPo!a@O([BϲT`Z~QHhYMH( _^<lj&;WD oFԃD1E8Ia ~4hzMS <B3)-q4խf ǏOm4xV:PX"@ ܓ2^Zx7N;v*~[f{Gg1 ?O^vZ%i83߲)$>slo-/poam}޵Veĉg46>"3Kk[3+\&cå2L'&ٖwv+\H=tl@x4k8 T j\7_z!83?ԹǞ9q읟ݭlўKo~7vT1h}jd3k#αm~I=l baH?^0 G ҈_JVwdl h/^_ltʵzU 驃gN^X׶kU0COB rtY% 9ŝr8c[^[r|SG0wwoǏ;|63,QBV2&N9cq \/Ͻ'8wЬDĘ'.@G;tg(ؽOI'/4@_:dr vK81o`!$YPΌ#`uK&j0pL(GK'#~N#7a>(/oѻTwL8=BT7 ZL%`*vZ.x{R (e0Ml75\ܕĂJWXZZIi6 9DYH")cҀe>bk.fP}˜xa 6F\R1ED&ہ\hY {%9xj?)\ L-ꌻd$ _oĬH|w܆cl[P/G-PH\M 5eB$mT:䚑ckӚ^fv4#~` @8 L`KqNΐ[aM ]Vv0y5i 5t660-hs0%`mhxVv*Rt Qض]Jl?N8. 8R4-D < XCp?jrw *bh3`3 m-a 6_7Ckd%/ ڠQ@Z/3{B% Q LmN%r-eE8*`tj{,b#T^ǻRtMJ!0zekYjlBp v,;SS),ć _1VfN \u MMy =f|- ױ*Å YuWi a;mE̫pbJeC.1"L s'f @Dj~LnCi˰43(lxa kpL |QAv3(GIOt,uAF.&!L>I)VւԹ3A\)q'G&4.M8GI{ !B*Z[;P$"4+ݵ0letLv"U͝JG %@0vxʵ6L8|o eFKGZpqᓧNx DNut&TJ]|n an䍥VO|b(=iBVV9쓇S껍zY8Vd!f > *y@I&|!4oEbsFJ~ktZ&O΂z㭏~ b7/}@ˇbh{:Ӏ^K駟}pǓ|7o]~Js>/:qJC]6ԊJp.!HeG$-?! CG'T.<@/T%8LġC@-凷{*J'*i"Cn޹EeO={޶Ws"/}/)HS8d ׮pWۺ-Ț4=:3<|ڕ+;o[ T !CG axFёY _ t:{=.o1R%h_~q>2*F[f(EcSD&ԣ}oJƺEV1{4煉9$*gZ`D zz +P#Ya$F,U8BTpJF_#' 3 s\JWG$-– Ƕ 3];Absi$&錴,._CX~yNgS ŨnB6aM`BXihP 8DKG"%cX&(=!4*h`CR|KR[R$ʎ1DRZMO aϒ8pVQX:5}K|xM ]6VHY^4U`󌺌:A+i 2t)ujFSQutB6`V`0 qP+sZ R7m8/.KZ67`AP#J. ,ly*[H 98jRJRaltVZ(2(.&ܥ)pNĢ^;j(B!'13Su)iN'9r?́?;\0 !g@T1ԌU֐郀a A+D3$D2y~ #.2^Lbp=/^)"mgCg4Д= ІaK`k(b\"ڜ`;YVx^2R*+wn=x]/%`gV[^|chHe=0/&aѪop6W_?n!SpezͶw#_z`z`f X>m!"ZJucggkɴ&\ڂzcaa}S% hS&pW}h,/\~efrg_jֽCg&b>;ӟџލ[1ڐ[FYζQT1u apu1qpax34Ǭt =;?V;f]WeeS`❍Ny{rnfQ{nMɣG4/[W.l{X ;:k[kk;גG%`4R.0I탻Y\0Zrڝ-^8N/i`ʵ IR[rgfo =KwW=_:s).C/T6XNtءO7^޸x=VڝR}N t$f0脾ar>^BFΞ~%B'þwA `82=TˤfAqoXtנeŠO=bEQHB>P1P%#`C h^ 23,.Y-udw(!BvMC'"UVr*l$"b1WhBcC |GD R$a\F(\ňr?!78MYIjn!#j-{k0̕IJ"7`-z/dI]}%~J2burxݺ|^[SL\,S) -cGU%m$ZGY\}!0A82eE"_g^V{Q\GZ}-$R վ=H1b C-$ێ &(Cx Uh3XbHe8Jgmӄ3] *B& @4ԱJbRNGF]}"_(m!;vuR6GTT;4'afLMN:irCDa B]~(b$KEE0Y< N.x8ОЏv98Ѡgth8TLE`]cQ0YS֨4RPzRU5g)@uЖ"X@h9\9 :8yכNևa X) peض,OpCdrTqπCQ(c0 w`d,=#$ N?p x`3@3j*!E𧚫M m}`{+ XFm'qBҐK%v椘#.E[diajgjoaEAF@MwT+nC[&PbS2PH5r xA3/d J {b"V>jy(ߐ bںW_ޭnܥa؞P i;h}z#Xխag2ئ1),E9ȰVw SI,or2 ; 8 ??ZNX)Sw^Lw'pgLJq@;cO=y .I!Ȕr&5x]"H}pƢcNEL>ЧCca.[ i>s,κD)m wa]o[f3,N d")[IeOdNzssR$7=ϸN[C _Oܽ^Dq߫)vp,"౔u'BPrt s#9(:)*,mS!TڱiPs;|ŗ_~g8t{}xev:;7@zTjayk ZxS=5H.|Jn,9nzzz*^v1q216:kց3r6ZgΟ?{jmI(V !rK/>С0Tr$S!,;=L0xW AzYg$s+xodo/JWh|a*n4[B%#,JiqÍF )b IB')CJG@HM#6ǖHH! \B5`"$H g KP~%HmɩX˔`KYpB[ͻX,NDl0}t3$M(DOr`1ed]ARʾDHeKXjrdBt%L'$abɤhp,KtS9DƺSjQfFPm"ؤH_]i+-XWڋJ˦t&hRf2NfUklk 4!h`8bSHuကx}!!+aۖfj#)p6_@%@ߺ"HV0UnpP3OR@ JdAP p/ JaDURNSp.-K192hڦ8e!ԫО9 $I7 R!VL N1 #p^ֆm%mK](cB,)IHң(^0*:#V1J]g4dNugͲ B` JCp&C>4>|=*MeOPX;T,tY]\Ly(2dRyШ3ÂZEf, PM Or E Kcj9*C CfT$v7k$lq"kM9stJ3N=U԰[YLM:<]ȧx $ dFrU(8uiq(J"%ny띏x $!KHآGV NT| Jt3}Ac# TzBfJ`=b^M0 W;4LN`}{C?KbDo^qC~g%t@bwk{tbdxtP̏O J)oCO^]$))Nֶ7\4?|CJsc7SN Ye⳹ʝ8dC:"DmԽ r|:P4GzÏ^\[WnF-/ $! CA@V ȂlL:Y ךBZ JD<I//>]ׇl+ǭBsP҃`=qpO=q`~½Z8ԃ"j8"Z7|*(P2 wJKh]nhB5$6С*P(#0KG#GZIG[5P712Sؽk8R6<gR $ ILjkb8jeM_RdQ ˧gusCL?dIbf&K-=M0 0" =8 @:Rs%ňm; Ŭ^kE*)Dpݝ ŀ!RFY[c0FCQPI)ͦ T2]aB `3օ%@He@R!DK"Q  ,C(Af"yV&2 {`A((TUKI>-ӶKBG*C(y7 ^!pt2?c?HEю8(~qMM:I-+ G •65Q13lmPWBaxw ZOuBE(c卸B40dd*1#BȮus̨ D8a*G-Ŭt2;A7l-ve( #nJ]þSQ ap,02v͖a7l{A (xkD.Ʉ505;֫ ='1#BztPJl"HHWۀx!Z*4]JeSBcGaiZ(I"1GU {HWV(Hqfem?nܻS/N ' W_?ៗ+Ƭ0Fv`Xdz/f3PVސe /-єǹER$2PH]8N 80;T޻p߅ϝ>>>1Ehwww )&fMLSa?h+[g!-o @'<ɓgƆ(<2\ٸ?CK?Z_-dT.NML:[z:9<>1;11u?\nli6] -0^*9% ?݅O"m8}WK3޹w{jgfX2L<J,C㧲)9ۢ@y ?&naE⏱My 1a,GFQؾ@ˋ}3{ y#t8Xq1GACH{W Bܡ.X1P-kx+b~Ev֝ՕRi鳮M]K-{Ϝ=tU}y+ͭ93;92Z<}i^'K` LI"SjSixkL&Z5yC;ggp3oI{~ts)Cʜ١!p.5gjK7w 0LY$V^zk}Z(>B :MJS9Dy8ȱwBxvA3=GG ѲIrnBP8hPT+wԛˠ%B ϕl9p8t# F՟ZfX>'DM躦Lmx(R_wU΂ C$ '0cV T([{q!}uxK %WL0xi4`Ը-$IX&[10UNFOm>LjsoFNJ.0eS`:d dK[&b`2Eg $&WtOa3}gsC "M^͸T>PP-b:&Ͱ6*ahKBW!:2R[wtd% Dta!]x^Oy5`31][ZڥϫU\}i2Τ cԂRq$mPp,[v<\V" ;T hvBvC3,Bj( G7Ba@P~՛<0AWM*‰Ye6 VB>^n6BA f[@Å<0R L0ڐ ٶD * e968J? r͢|wlRβaS1dDl&~ˁAk 2)3f'5M }: 2 1NY+Fbl (jSJ5I9hqY& v5WldI'U*͈':g-K/߁I7C{/9gQA\ 1b(T $4++COve1ёB B12~f%85T84<6{`?}wo\2w-SAD=]?up3^v:g^pd:yrn|nAXkm6ڮ*pr}뺢"_qݺvh/}kO?_}|zNp^7z ƘJm15 kOPpK-E#?0'$3^ ͧ$`}40 uwlvzA7w~w_҅'=bfqnbQ'L-lJ\15Z_ h h]V=t"$EmZ͉vws͏&P&M6!!퐷B ۖ*@pP+c;6 Dh6`"S#*"C rX 麞$ }-탞WL}+N-4 4Qg&ZZr.H05,mEG $j#TdI#!t|h~  K*3r yFN-(I~,%.XHU$LIȻXfI%2md-H?˄ jzz(R.V}y rHEX)C B&. Ӏjp(7bBl#,@dҹYNSkROp"@8ӮPQĈ֜fҿ 3&?ᬔ1МUhy_r6h^Ȉe]yck:hAt'1ݟT%-28ln x*H N7a[tX.)N &uVS;\N9WQ`uhg DrЈ&)@4 ʄ{;mշn-g[ZRעD*(e T{%ҺC"-mJ r00\R(qJ!oV]_IJTC RT<{ f\NuLFE̶~l:lT#@m䬞FCObvs|r<CgBPIO+bt/JynV'O<;2:)P+`M%~Z葙Ӆ$nol^^:xs/V]"ε[7/ݼcYt(\8{ɓ܇14w`ʵO..Vj9Jrunsj@% ;~gFgwwoktdM_6,oVwypqzf|`S;[z{g'ت. s2 ulm4?֐ܞRtj9v,S:#ϏMM--8"3ӓӻ5$'Glݿsiq Oq>|եM%Y=xx3ρ͑~خ_bKerڻF/[ /N:vӋ7 :xl 2<0peVz||z40LOsѰj`h3/rAhw<ڻi!Y$>%Q0(vP_GaJه8ܧ8b~C<奧i>59fHTb6a)Tb"8ĘY ӹJT 0&chC0eY]DSL+ґ8NKe`a#ؿ@ATE_-։T.]w@t '2U"CC'1>Ƅ`mjQ$ ED`"PJ+y)V dLCXؚa!A"iDƵY]\i? ֨ӰR=Xo(epI?3FpjO0(%p'VtyE`!aVZ@ @ M17jhkkF͌BסS(JC9!D-C|a+bݰrO{Y6ehS40)bsJ$ymF!I9 Baf۰_ աf̃aPv]8#J}J,w#|Vwѹ]fu "5O* 4lAu| _n*:G̅%r%x BjNfDbv߄MGIQ{!PL q M"06#"$.NDýVI L=P"Q65C*bs5{ "!2zbRBu\)Lm,5K&Q1R*W1a^x6lK^1424b( >Q$U!jNt,=.A=y9\NL zΥ]#8' OJ#.N?z+/=~XoߛiB24[,-M|?{A<492dE{ijY02dS NgTk^ Udmq4s.͍l66Zirn)\UQf"0kdjbSSAXn`O|Cn9V?5Z?q, bG n?Rtl `6fbzƸubHXwpGH ?PCik й`\0DJ3\%ׁZJHJN"⸜R#m6 kڭ6mR((V!$et[aZy{wÇn*h4/Y)@)f{K#:[HJY8֋Pr7PI0A#Aʵ!74ƒȼeҡ \ߗVVA@\(V\!+zL\"`](hMY' Xcr(f*ӔcMU.Dh3bjfVD/ X4W2^a8)  >iQH=eĹd9LP\W5°VanS CS0zBA 4 XB `R hmx>Cɖ~F-+LFus7moZ :8dԁ#<|nw~|+CzO<$ ۼ{Gƛ?Y]_fy)drS%fO<756|Y|vذ,/T*]|ﷄoa6*?|kd˯|S;lf/5TvtM^si}̩ÖMEظɓGA*/F_Vn4/\88ʃ%m3C36J>riJ]#Ӗ}w+ aMJ [[ѱY%/T!5ݕQ4!J"(B,*fԉj*-u`úHS8 6M?gq E'/8Zwb>9jEuj.dyGϑ Yo>۫+[,l+ڎhVH$~po(4ED* )3Rt[D\{޳hKu` =)= 6vQv%9IZ +vTi g`oMe," 0M ũm<CKF9ktbe̿饴5 Ik2QϷ!eBFӍ1st[GMXs ̎0XL̰ [Z IHT0DR4`+9W6TgvРFUے|YMR2t0jh91mh2HP,.DyH$!DP/ L~,¬@pJM-7ƀ+{̱lJZ3cC m%Z˥`ٰ(+,"OmU~±@cV *yu` P)CxH@¸Ver6wgѩ7Av:~DvRԤ=nt}k6P_)VQ)o#uXTk%eJlj &p844P Ć~:0r&Y&C=Q=(h!QFʣ 1b6 M0GQ&D>ջ1HvbO{a܈>ӊ=B`7::؊DL9Ip빚BUH](&$␜qq`С٥mBk;0w?Zw)?h2顃g^==<ɽKK0{r.a.2~~,yAt_R=!͵U)ĽD&r.jduTŭkpX*Qvejpca2n9Տ%T^\_x8>x3Kcʟ:r W+k'+5!ARzKÁSXf4Nl+YHN>ſо;u sM;m/MO0% _kN0LJ%XLHP6ZI'JS=ǛvcwmMm&RD+YTdŻn$ Wt %fbב3T4}rH7`$ Y$Y E`op5=Jq"#{륞|8( iJFTcmч"{9\?^ &\|0BtDh( &dK\CbM1f9wK/Bu1(s5zhoPHղ_ݤLlXBF{~]) >]`&!}.<* ☄A`>).^C'!^鯌Vk?xr{e~#`q'Jq/nV- }+$9uIwb2Hb¨:<[련ÃПۅ[uj` jtG9sӝV Ɵr-{Ԅ;ͭzdD&6/-uFGJ81;=`w}{<~R -h8n ޺݀lfKÉ\nl{ݨO#DDpedKTW!= ?8CKFvi7>=aj\ķ_]W.Dj 飣D : Z!DłIg8kjs'x)\]]\ßMNWsywxIU ;Hrd89V;,lVkrHT4nΤq " >ܹhU/-<\)9w)Yn#L妓ȑ@K˫/mިEmBJdS&2HO;*Z~¡C/}+s+LMM0&f[n4УÅad@( ";gR,۵(\h AiD x6s{mг1:d\b`ka=zj=O@bJ)]Nh%F!{hQ$ (X>l gEU@UV2 t먣a sY4ӜGiD~=??ѱPY T2ؠLzVj=8,Ik;J݈B?gBMM)K`'O&,=I[Eyh2wKsaiLq^&& I$,LD!DJɌ1*4߉ZA$;?jPj5c+F\(E륚cѥo@J-m"62,"( HMCx \OHi k[J~5 t]mnz^_Y%%m[Hh Nrx;;p&eEGI!a1j(H _^P㉼ ?DǁrD@`G9bfp La 4TЦ(Abk"D'zIކ'QuQ8 A."I6(jJECPTӨgnC^Y`|@mJcm:a_ʐ0pY-)恰m U^&8 FlY(8!eI0W!HrSP/_}40Mf ?>gDʤ |d=,M 28߻:Lk`O{B'f>aU]ih&HcV,Y_>qrzzRՖ^xIѽwoYYZlo춶u/5)HN3Ǹܹs{ii{mt@ @R.'C3Nˡ^-āiyc7yLı' cz(8][?G߫7Q},> KS㣇G s=(1zM .,njxt Ze˱EllL!XuBBHX&+e{px~QUov]0!LP T`07Iz3~0}EK+dQ&w_8 W.|ǯ@N>z۫k˿Gۯ7Z52ZF*qp]I62uV![p_tfgN;~!`ݹ*Se'zpnBa;Q%A@.hQQTڸf&tS;;yA5OHfa?m3?ho,)tjv TUK—fxߊjXR\V`bӢ C=@aˠDK؆LL:r!Á/0T"nhv8J30SMIۇ-4HGuUn0Dl$VVuH3 Ҕ7oERj$`%"|ft,X+X0榶!ԞvLF<XʈJsf`jhR+OgO+@N FD-FNiqfL5Cq 9heNu~?tԜQdk/W}Ttnn  B}4"^Wj["VL+r}i$h,Ͼl'R9ҶCnv>>[.n 9i{3 Eո{{/J#N&F](t?HY9[g<5]Y,v]ڝk@g(FOKj}ʱ\za}]^\'}&'N~)LpXC6( V+30I];M| 8On\!"VoRŋ=Jdj[GD#=nȐmFTꊇǍ#y21eBZ/ZJ@"O_@:53˿Ս7~__9q|v?O~M0%a* onaZ%3̙Z ;Ggf cBpT0B\{>Jܽzz*i)؉vvoݺc^ҠIn ri}{:4םb:Y=rw\y#]8pX);myV CO SL%3,7o~ry@bK+]pQIPņhXfs=Y\uM%$j.$|0Eę$'B=EcfYWeK9\ϛ:_i[Dq0) 5QnX@?JO"@ (-¸))B,z`ulgh+\(1#F_h+y*hK5/#Nu}ڀ0 TbA.]&;Ɉq/`3\H4:_/y? J!2>*x`jS"xAo\䇩I9G$&ȰRA%=OEDĠ cbv{x"[`8QFm$;:O J";LλX@몭R$ ê@HzuNP߱kf8*ױ :wF!ѳD1A1 ^GZڻ5 {2 , YTAŁ5BP&i-Kijg],&(P10`Xn\2B}(#{iV(IϓS%.q˔e#`l7E[(a.+\H ;BpDz{Vox^-ԸH251#'$"vC{(}^9sا1$$P rTNz(a-{tK7Fv+69l 7iOhp7+Ke `wD|ιq}5a243& ).$씷=/A5Hz:}G/8 0oH[& Vr4z||ݾss HW;wl(H # 򚭊(w9.2[˗oragڼ׮`97Rvob{3g/_i_ qFrWo: &`[YtNKFF7A aV۪rن[td"޾~݇2SqcJ+pcq.FVD #^=$-5^!̍~`f&L=`Ec0M e3?^[s__}?gO_/}+)lkݩ7{YXiAtgwkPL?6<4HozsAYr(?iUH,mRkse) .8zͻKw><A{b[2r- ܽq{"uG@\[ނU^oçGKaf^zk;?v/ҙs/c|HKf27jwl{BFPc#KDu^W g{e)&[׈N4y\I' $XmԒT"F1#Mڞ%?> RwoO+`2sȅʼjbN>Q1 "HD%Ha@MLcQJD<<mwJy vΐБm#f/o'd'9L Pby2~^Axr(mHdTw*w$l˖.&#N3 Xuc Urrt'Tq,TYh͊!x(,nTm1--:1V lL()V7Bl&;:FjC02MJ cti;M3\-F(|\}ڶKDIF6q HI;HsAI:J{qzhX˛0 x\fm+Gh6!DwMdTIefD*pν ԁp6$5ĜsU$řN'VT ;ưCA6:dO$QnAm@SMbxQ[uq:=1u𰏬N/sS鍭˗lП>x3ν2w_y*,`)I$-25:`i~}wc*eRn3nVv@Ntnl|Í5 eN2341}dqe; Pm=,M%8knW^:]~}n]{i6˻$8Dzb6Y|z15>6spvyu AesCA+- 0FZ81,b (r2MdOEc/<#f1A=:ѐHP8S RhX-1CHX.˩S'޽ KK+wWmKp͛o<9]C& bGfD[Pol՝rhtT;ݵrGJE  нNց'&CZP7AhჇLSN&͕ |/~|FC[aKtĊYZZ8g4dzlu⃻KKtN=HM% ۭ;w}|7/K $i y[qb:ݾ GK}LhO]0'8;Кix {)%#! ԛכ6'SgЍX ̢~U gXJ\_d q\e%X,8Ha+"a %jq)쳄α%%LkM sG~SV4Rr|*"da#B)ƲqsPNf-Jɒ)JK7!-fs22Ϧj1 eztlLƩSHoKswnwVG}e 5fBP`I#TsHƳQH zQ(gxaKum}>W!W ea:\I]D(usFd~E ]&& 43QO 0r_uj|OV)%kpզV[ߑL@Д-l ᫐2SiqGGu{2jFOf-;I씕ʀ:uB.Q!s}#7 k-jxl'#㣀݁NBW 3j{'Yn2P"03R,BSʨz,HwnO/S=nzl@=TOA* rnce ?1cHʧhIcsjD\yʽUY?pzdH#?~56/F GO٘ɩ6O'}R(B4Bdi2.WAJTa|qlAnYm!TsŎd}uɏ_4:籱'Νx3ziff bvn߸{J  :0\}HɌq7l)D>(4 @C cal \'ùùK l_e:d>{@hp1l`s-=XY[ҲY"3BV냏Xxx)|r1k6D'IPc=8w+_;V+t1\8:Id,qsKLZhƦ1#BױKǴ?gzc)q35&:070Ֆ{PѢѬٟÇ~\/zCgf{{m.-ailll&5lw*;r5/# `C0tZl(ffK dٞϭFPoݵg^Dҕ+CgfZ3%$!SRJÉ>tvQg߾zsGLOLA+,V>x{C%¡nia.pyms~}F6mi--/Z\1S!!Fn85)"MU+ bt vB*{ƨͩVxL plhKgBbЎF:Z:l%b u=a0I$ԓ@jH~Fmyt3:a`́s4'uMeZ`iE1w-M&+$hs] 2"0Le=Z] ZB$H!O {Ҍd-+ʠ`o"DP)eF~=B3#%θps$|*Tvt-YrvBºB}-T@k AYTwMhItʵ%/*ba1 tؚحS ed{S6ՓB]$> (Qԑd(Y;;D n`Fc vch(dִ: oʵ[3aؘeh  d- 15=Arl il4 rmw ~*_v-6\b·BHY\ y9؉h\ 8zn(=4_Ki)]XO6n (T˪HDZ3+`cXr0{Cԑ$fÑL3%.a^dK#@#cPzf)؆gLoSL `qJIL|=>[s)E;?&bF sD<t ÷L%dh E$a HggP*YfNV¢>ڭT{QLN72}#X*771=*dǦEIF@~ &(rՠc;);>f -B$LLs[䳇Jܾ$ppMMͺ%'$ߎ %ɣ8z Ʌ7?جy_z ҚLQt Sa&!]$6ZXBcONdt99ve +{$ Ha"eG{ نO?"(M>zNQX>ph hw(p%{o(Or>7e?VnAmms=6:942tqw[+`WrzDa4m7wj;˾dK)R/2"K'\zgGFVvN a'_^[ݰX4|Fgkk_y|3W8wUBY7|;߮on-3͑`bnnf*>99s:\]][*I8"c64<126qid]ڭ5əP#eHHpا uFX#Q B:$hl o) i^9LfQ@Xs]zp|v~T?Yu֭}whc葎wY{b8'x[~ѽ!Z {ຈPt.%;+9 `"JҒvH4SᔰPB{=P"J2+i18a{ jPMhʎw0AAؓ7  ubԥjU1"dy?q7qntH P$4Lq1#\gv:v >W6 HhR I6F"_b_~Dj æE ʂf{>-vn@bϏo7.gϝf2 eh{DOEI2H ʄM4SAx'! 5ZD?r߼/ߌV!оGrS`5禽hW̢/@^aD'/Q}R=ZKAFaf$?ʃUxJy `yT[F?T=:H(8C"]$?ECGڕn=_g_G(}{Uq\sAYLAA8_ g#<(qЯHOqdQ_q^#G:Bf B aYyH:~]WE[˫ە!P :֎׮ Jt{KƝ奅V[[#ső&ؒ$N877sFFᣠS6FJ&)dkkЧs9RBBFCAZmxhh>笮n=XUš;՛?,Z+d'gGcHMm춘/H띭7KҙB@@͉Y p`"Zã#g')VygW7*2AZIXT<н̏qܠd1!# ^lPAx|Ѽ'U+As;y@D7*V zs_3o~Kṣ|'Ў 0-t46 REMx+zb%y40vFrىnz^+JSc&&z3Ͽx{[nݾg[[P*˛ SvnBeh/nqh!pj|b( D&[:bsnnmCO»*.Q1&fh]n ]RCoN"h_`7 F%ǜhH̀kt;<VaSqtK3-g=g{SPG%N}z=~##+uKrBw{I6^uFJis@(QVKfn*Jwn/DI`gN! ͔}l1'B_QbIʝdϨzA };vAe/H?DwQy{n[>F)FǮCs TF* 0 a(O&}GK,ZRzxpP*?}/_c[+nxA3r`o+b9H 9ECXmLDtiDKLĚ!mG]p/P%,}73XQlU tA%v9|+PqtfgBuoEcTqMJ+ӚqlMhF$BTm S|׺]Kh^ uDԑ,ė(Fie}lcނAt .JX#MCQ!!!Dyy?5?9N2zb~gJ}6={)gB5Lt )3!B*UuF;鴍q&FM0XNS4&Ճ!jzywp$.6 HZV@ 2FGO< 5/m̶} q O+*WP=ڭ.U@FTyX PNsYI<<,$tEFڊWZs-kN@mj-kY^خ'Do_[WW0&T>RMCUHHn rl(7o[AԄ=XiȞ !JwPUća:$R=PzMcPqxYs=ׯ G*d;ok?SW w`|n̳O>?wn޹ulAE? iT7DF2p{ J}qvC Ӂ3Ɏu`8< XWӉkׯ\zunn`2uVb(~}D јoz~[6Oҗ _zR|Ȁ[:`;<;}'?wKWݸqsih8 >sG+ uZ})Am%3@nG:st[Pqdnrk bcR=){\ĈjAuN M3,Z%#A~**? 3ÚX$ _H UcjmM{*t#(]wP1aQKX>mxdjX6}%:eƍj BÚں e<,Tf=basb2gG Pho/WQ8R'jEUZжDc8xwSu /c *'jV;1S ,ԻZt.p.:,I ϕv[U8rpfjA)kZZFL3?D7y >}?zyeٳg>;_9s±NmWv>rfqssG>Puv^qygs:ltbzsӳŬn߸wJyPhix ira|ƭ?dwrtp1SݸwH`7]Y4ZL2,Bs}*`]d:GpT ̹^__/S';o; &}guuag6kSE4x&>*.7KᙑCgHVnBkq +ѭ(?ע!Iue#DaʍҴtƇ;mKgN>jx9 F6 vdtlS:(2w Q ĄbWy'" nc.Uam'  ED0f~JɂoXP!a,QdڃPK\(|BA@)h%4{*HK 8 EYv 7kec+;jJ:p"l ,X[vYD2vyQJˍead uՂʕI:On bbNG[[[5ݒ?y^/昛ྡྷ" :Kh:!Ēk1 $%W&Փn(jiUiK_} h`SwcF"Ek!,.Zwr&ܽrit9}0ks]نzQv/9ߥGqIL4NV+5XGa` j4npKhE-MÀ"A`%@ m0ھW;.uʈGkBTeN 9F8jUŰCHfco5(#+`b8J#9q>iRPITAGM5+ݯۑc_7of bs#Lׇ1>`Q.9pHM,كS٤?|gd{O\x啗|H൦סv[ l=bk nc|AALsE'Vt2<nlny7}Q.RS0im|ǿ_?WO>O_) /ߺ[QSg''&Ex""b$ȁ3'l¢FSc7Pv47x7CNJ95LVl :# %3W_TnYbb5>s"eQfb}fG˩g\6n1h }E ]N]̥*[6_]f Ho sA#|k6 C@8HJy ʵe*8Rkuz Ɩ𶯩%SsSRT,+5yш,;:&&2I' zo['VEaUB%K x2CtU(u[h41yL=eXdY MjBu.fH /29Qq3=fE kK葇FH2:4v㇯lV IDX8[$ w `^p0H H$ͯڿk_t )@Ao"!8491ư79'%W! s}_TX N]Cî^/ ;!"5n34#_(Zx)Xź9EA(f ^oNQЮj]K)s P؋pm OH1sHy#Eam&TuQ/r$&pt eS FAv q̂a8-Ѐoj@HGF}GKj".h~09q`Y_9:.g~=fHr8 j!hxzz/kW?/LO@\Xjʞk |2>q(Uց..wK7W6lbp޺qnmb5 AE-Bs%A .BJpD ⸘ѧDz ٘"NV6]`ޕnܼPJEv~, ^65=b}u}a1qP[Ŝ`פ^_ds )D`Zy @erȉU#,L Wm @ |C*=l:o~_ַyѣG_y~}_4MTײ,P,kY/ZL_ެ_]pifniͦVP#Fbލ;7f&8xfrp:AqO qҟO;F`aRp~`T/bȱ8K+\W*Z_[TU M 45(X=7xJG?wXY Gg~8bU [f݁D|~㩃6WMR$Ӆ|qP7Ү͛ sIg16bmPRڌ;f^-VR5 9|)뵺hͭo3|>?P,D"qlY2 <02KqmSQAGPKiVʴV^|3=ԓO#h2UdI֚[[TᄮkX}9UUX㎖D?)wuP-Unmzc &ܹ.U&e-IJH%(,XW)R5@OAD)۶ !b=:FkBH8P襜$/ FF' dz,DwMpwem 8!]v]/㋶00 Cv܎P <"Π= C)(@!a!H\P5i56#|Q` q13, .&.Ta<s(Bx b9H lT$$k*ĚB9'v,*B 8U ^G=Y"'.Q1tˣ?XuE O;w~X-ۤ 2 C9q1Pu(@H01@=\ 4%H vyuXPpnRAl*ÙMF9b d4/-}~G)a{gF.бN$:9*dqG]~"&,@-GZ,#xg3XBb >e]mGA>Ow0pe>o]!+3V$?z*9=ԋQr|{ A" Ȃ>{ύ `?h(]2.$lRpݻ+䁈5u* w3#6B > eVG^f,50{G N.]\'O=LѲ`H:SH b[KZ!dEIi6fd՛L&#IesmsA  t=ΩVݠ`R#01>4KiuoߩM̸y`*+hjLa7R Q& CM&0= h7oxwKө!_yqy%`4@v"s(HMBqiRNv;!fYԢ-K?a'CS1eNN>|;3~2}N>lmmeu;3gt# ۖ2iv۞I= XVe5-f{ְ6M[|c'oAJ LX\5T!U"R^^RÙ=>1:]-Ug$ҡҰͣgMX_3[@kyPCk"Cwue~muޱtrd0GY`ZmivasR‰3on5/^1ݖED|yU#(&ىuʲ9o[ &=gVU@!0慇 ~={&Kv{ϡLJo9![o/`n@&ѳ FLRoR!T+A XX) y.İ9vF";pE0(E$L-\@P\|$J(E*C;QƆsA,Xx+rQKcOV'= ؒ@QD8MSo3Ul3T~Ё_zpRA!:i-C -?ı'YP`7 dp%@T\?.9Ti#vpH:U{`s\5Ț &'panmW)XY{V5`rǞ=#Riw"/Q0/0j Dr&+hvt] c5J>H{jhCgmwpKZ=rV!`$1D.P*@zo4`3{nC>S[Wr7mHah׷YyC^wA$K@z YO,@ v#(qwҀ 2l,5dtD)Yvx{}~1kYa9#Y_F][/>r:yH<V33?~{ ,g>LX\'Z -"*!DVdYP6̢ bڱt$6(Ì$!A,&zM ^ B+I6-RC="B($$EhcE1 (KH=)B8%S~X:FMG|qbkR2A(G?b 2WΚ/\,,ޞ^1 &FCy%rw<AU6RD6j*<@67P/7jvyQ,̮RjȧGO 7T&"3;N<=5> p8rP NNy4μ5N6(e `o'*BxC$)R0erLXPΝ@WAґIU4և3j[,<@пů象R;Xq-W>f!OFDlOmP61Pa̭5F4IzZ[c@? ?= A}4sJ37q0zVs{"_ 3Gu`waMBGC-Rivc@!F}Εk6}3?t`?s}~oW.\]3[k[8|Wtr`/m_8pd'>A )[[^+ c#sG39%VdL;PTLJ+˦r X"3x>'ɤms{}ժUG2Cx䳿x3U]R\Р5gHd6%UWo*?7+]}cmO|S_/:q|d聉<̓=}Yv%vQ*ͭoܾ~歷MFG8f(ݕNNuuqy!=כowwtG"tqxoJߊ+']{ς"1#Z(G m!L3w`CDï_Fȟn0D x@F2Fs@%jDLZR۶6rP&b z!R Kx`+Gwh( l!X_!rP;*z"qı- ,ij[հya&QL(ϺZAq,# <ٌm0$(݈ 5,iaL\vb0TEz-rf6c66Is\@vlzcNe K Uڜ8ɁŁ t 2pE[U0jO/4G}gP F;YMsK0CӚ)ve$DC@Yƈ?#N]%L@w5Rݮ(@ʦ=L !(9W1*.iмKtq/>$^YPDJX^<|Dv3z+[W,|t2v__$zԁ'2qw ;S(&&AAP`@fnNgRJu(s#GFEi[7r2?s~j__.X͍ŅW.^+VݚMgF҃Z&R#G릋fs/\}=M% *]|?겏ldf'|#"uLl,jfsll٬V"1FVWK[͍ܵXLlbd|#}Fl^|IPMT1qR=#` c`,7W.n=ZZ3 ldy0 ׵Kry~hptpxV}䇟~b齷ޒy_R_V+W>4:>uʕd2b:9x qpx@jē228,w9%3"+jž>)XŒ1yB̓P>vȀxq]W-9Y^zɃ?==؄o]|?|O>18SO&OO,/%tctxLN XVxA2C]`]? OeG!2#V ޢaxhJP$4e/ߐ"I)RK~H)M)GA"KT,DQay42)$!ђ{\aܳA(zs2hX 6DP.%(ɒ"X.0&msB92WXPt!Yb W?cc +r+ {K=#c4po`Uȓi_L꿾,4i&)55ڳkɠ` 05͵D QpߵLz6pl %Z1! V39)h?5ՀGmPyq^!V뉮 rZ'A_6R}TJCw9zo:i{2]Kz oݞ.{$$I< R҅(N.{2yY=o NÈreѪH2k5Ӫ[vPٶMя>}L:7 rYS&w' %N n7R621:ui diuW]sSf9$߼uo|xMx"nVʵ䕗_~?SGO|?̳sS٬ikkkmt!T(%1Y=G@) b% Kh)'T"&X($PrwK0m$˚Au&I7_%=t`:]|>B_@x#g soS\̦2i4(ތo*YHIl\kSjSۥ(qURcי |;j1Q3HBRofs/ 7;"%KRgt501u%I`.{8YϾ­{ĉ~`]3b11BbģLyz}yq1>92~}嵭; &:a$<ۡbZJ!IގAWz{āpṽe94bpvz_d ڻ^TW@j!D wtٿK+B;i6ɮǘ:\h BRzTD s%I;*A@97kڹ82cг_Z?4=uXgY㒄d-Y(?Pw/^x׮om_O'9:64<|F(3G8۔m}>e)W60bf6Գ8#KL:nV K &ǒپABܖZl`(Dzz<|6}Q6ã|?c)0Zc@l6IeKhB:g g s\.KJ:UUI=X5S>w ?4~_Oׯ^{JzTуG[}[3z쀪Lf V7Vg]2Bax(WLRmՆ'xLϧ lTfޮ7ڎS7,VEVW+1|ٗν9z$}#J*r"l\Rd)% %d0tq k}˳oq; o<'O?\Tah$] B0Jks774]/TƥD|t˩<) Zh!PBGfڻG{I?_>{cvLٽ6!D 7Al$YDaquQ=C:tyQ64͊H ,4H~#Lh'NQv8`$ MH8C$4b(`2>>K?a+AOR-nZhUEF2 q84 VAp$*JPF\{%'Q`qpK|jĥi{-m/-˩ 3kz@(6\,; +y4 zYE:Dr`!Zb884 8d`1_+_j191/}ֈŃNlz(R*'L1 zz}:Ǒ/"Ιc>[aI.޻c;3AxcwUPꢓEKGJGZ`7=K,^8xo] x3awmum&QJeBs1Zy};cIʹa*WQ@!Hf.v'R6 SF 'QEy%gnWJge2Ɂ"gm:ꭆ Z?262.Ci TD8VBЈ ~:5vCW.]8wٷV. eCŔˆ|h&Fj:ƶoQ*A+ ʈeMF(GRNSi Ȏ"D0yjࡉ1Eӷ%\fʜ-JVJ&dڷV@V/,gW |6YIIA.3I1v@,f2%㚦4- jzVR:} pPRǞh7&ȡw9sw~+~&F -oJpʮ\{ܾ xg[~ɧzʍ[6s[G/. pIvCP Zd cu]Ψ~kkІ/5jLJ/򹜟_(t^x˝9۪k ~jMT옚JqkiD2$2JU=bJPNeU} /$aƹ>@!? ݟ+ skG>t%CACƠ[/s@Yҫ˷ji3|~td@U%W%)Hӗm{0lTɰvi<ZD7$T|7z匄g ?:K6uaDӵV f +$d@ " %,{*V<#?' N2V۴=*Ɉ|0AAlnuDܙ,(.ZxIA,uX}^y+AY*^Z}7P_{x0/FxX"sBۨ@M݈^=7H8O:28r% #f}}s#D$6_U+Oxw%ɩ1P f|9;IF`SC<#N;|z#nyu=%Sجvsd㉴ yl:NcV00/,DvoQ3}JaQ4e!ܢ!$`_o"ndҩf\nNe2\fݬomzzmc賊l1vauUYd2'vIg RjjFu[w?r7×&|1W}O #߆̣ٗ^?'ڹwJsO=O>tKW.d3)ƈmf\(jpr;ĕ;(D@Qm!Q D. 惿qCA2&޼1ʏO8r|_]_.UO}o}eq/Q$ܗq?AUl nolYmΦd6YY>]^]Φ}FFbBhUj篭bUKSMmˉ W]qǞͥ3囶\/_>_47I@%Xot7اeN<+7֖oW|zy՛O;]+pV>s[)o-eƌDRť͹mC b6+Az;[%.QX @gdjaߝy;/ 82a rqmzky[=8}#Np70ڇt]"ED4);ã :'/s9 y6%RO`U j3_˹$%νk} }4:Sgr@8R@Y̫caOSJ(= $L`BP@#0 (@&7~+n _۟`JYd@E}qj)߷uR*GQ˞id>=Qb1Ro2 ^]pb ؝8`Dž9da!= g{cEUo K0,jc*u[-(Хu޳>cB{4oȁPLBý Nt !@j `#8#μGX='GA=e튦D"2ڬs&'?.HH w&D憢9{݋7/]:;zg>gzȑf|%qK+?|㹥-ed"dt+*%q1=ńQ=YT,qdЍcGmb@s}d]_Y[mTZv0$)s䙴J!tze}mskkL$RxgG*VQު+r& F,Sf1ۖ S$AU5s%ӥ۫sQ Z}\ۂn7m=~SoƁO~m???/~n}e,fQ~gF=?HHt>V7߼y&roD@5 ñ qhX_ĤA=#Z#H5p7J9#A2#<M,~{߾tA}C?髾/2}Szz)_w~_A1[*3ɾ|gDZY.WWˉ10X(F|5u^nooW|Zs/ś'մ4 k\C1mˣ3fk F8,>DbȾ(f-Jdh9KN8Q{<%≴ x(s+˳l8龁@䙭ͥٹ~ ͙r) 6ZQ\UrcS\acm[-(C1Dd 'ML)E0aC4B@!իv)(]yrY<_("R*%؇Mn(bU  Yojʽ)Y%+ߜmQƲ"<|I$8|^ Ow . *6 dP&3{.wJ?D$*I u5}A B[Y?tV.o-/"xSsP? *)N)oCey5f1zG$8B&/~BUU~oɮhp? t/w+N½]h8 wWyr`D){%+>Hq/C T޽(مkC.3Žk諃}W{2S29Sͱ[;f[-э"=Y,!!5>t*#Jw?q@`9 e krcERPx|ac%$@ #SϽqŋ%7Kz*>8,͆{*^ ]UÉT",GsB{,820٬,UjB(]3SG_agm53)cvK\T]Q5Uk}9}}3V7ZmgRml!KUziH2F` 8 IflXm6V׶-,%MLBd-[ۍ3';vLQ{񕟬mm|3_;g Wu}wr39yB6qZa!|^xմo\SO/.;A5[ 8d 1A=򗇝F! :i3qBO0%Hwsѯ|gss=W}/~g~ ˿ 7~/䝷_f{6*oۉD:ЁA:MZ^^LRãd'_&DcOm{uӽ:" Gkh-"LJ ^=b]ꔠdМF O# w`׽4cɏsvA8b2,!eەjc=44Z܊jmzVhZ ɸYz­; % kr\Yt;FGaК:|C>:3_kl82&&6caģFG9dLV$s0JӦn3Ֆy|6Q+[U##ƺeW2Y q@9pF0b|*T+VnU7ZOS-iz_Mi^n7*)獴jdt;N^ku`ٶC \JIhvh2٦k m9uک\*RܼW_zl.>24<g C{/=Љ3/] 8̼ߺP"ڨ;޽t͒~--,\L*ƀT*fs*A=_1\@ zNHEa$ ,+{FiPsZ#>ݹyjy3>w_p|4=}ȴgc)mW77e995- ]̶Yf4nsYu>tPe.oߊ'B!xq mNjK o#0uXjm7tCw!~#Orb|PuQ$'sř{ s䒏G&rLz(O11<1&x0B1`N@@AkM `.> [}B4tkly_ݻU(~Q+fPϊ \uh6:BpbW#r q́C ? pڶL2I=]/rP% ɁF(';CoP0}*X/KءA*,7 '4\ڎM-wNqFF1;{&c,iĜ:.\,;SGKr@ H+Њ!ID dBbG~w-AḿcM* HX A <X_,7 Ax{aWcp`剧>J%@%v {FvABe Y..*Qwo_.G0 .@=/@ Ϟ __gÌ"C:퓺|`Fp#gDB5tp;"a%hi4Q,4B85zo띂Į-^ Ȱ"=rB,v;\!`7PvЎfW9?%p>(iZDBIh5V0.WGL Lv] $ 9i7zN8#p-DPhC0ȚG}e_,]:Xm&DxF!+ 0Be c^-!1#"kض.㞢bqu3OdOei͒+(8kfБ!CD9P"61U]U\qtʚuܭ8/07Z.; k#TTzi9DdR%x<ZRTZ6i$c^3' ~}~?8/[GNLWO}~{b^.FI ߚ׫F\>ph`&ک>|R]FPG(ݾ5GO~cO|gw/򥫯\f2'S\/+FToom/Ra=f:vbp\XYؤR >K.tF"b0z`` I#F޸+-<'yv]NrLd 7nޜ'>s sP8u(Fc}쫯l o|J'eU9m¤*dRQZ52CvR}ulH2mc] L0q a<d S+B H*1(sBW^ C2ݬ0yA m^hvX*^Ç %Y@9>jCM94R#7]'vM\4Xq]BHd z@PBk,C])w=P ;x RI⚊1 0$p\Qdq /c;+p`5$BMSc1Y7n=GCs$IsN{Ѣ>Оqo.F6.b LwAt>&VM)X`{-h*r|" a b̙sc3B: C0Ĺ(z[p^BJyuy~WgyƗ98 h(Mf3ih[RdVϧxBCvq9|tu-QmTdQw,IkY5*%)B#Af⬕<8}C햳dXb1D⁺2`(AGr)VАk Z`qfjzL&M\7/ׇ̾o wUE7x_eU 5M7jMgQ K^!SThԶ1MVo;k`F]z }?}wߜ:|T.,AU> hvPs}ݙymhdS/?k7f2a>۶M8<%)(`XܒJ \וeٱi6Y'?^Q?'>Z_mсt>0;wgIYT^HpFNclʕf+糙D2vKnJVu{#Y\28<}lT*zZ֪r*dSY)62ڎ;劖QtMRd w%㫭Kk6z(pEq5tKҒӆ'cg_7/lF(HQ0Ua+ Pk6W֚Mkox`uvw ( q+X(jqMg+q9+Bg;WX$D]zp6Kr{?dcg0_f4R$RnG"cBX@=2!C)Zy )eAeicfo!e?@,@ 'Ùb Xa["vP 2qmP:2qFBFb&$ ˺AE_]] J\b(z!/X,я~~V:s4 @ |m.t =GG.&}n |/.yC9%5eU9UFkW.ߪ'[oIO#=Ra IrVTJ9eSt;8IO ,a,S׵͖_E>>goy̗|3I~ҏ1rTqx4'͉ZZ]LYi94[,>90{VPu5Z2R;~F[M&әp-_n*Z218ɲZYi&+#6.]~?g;i٪€smŵz Պ4 "#}~Is/.nU^z_[yP1RSf}ZI-"M$$fp-ׂHtE:{g#) 86G^/6y?QIpo I~?/=sT*./o$|jw1ʎ$3V YCE((A x/ss\PgQ8E1a$h r$d %0qJmDz,tŃTJ08F~b`R<)ixqĨGl>29.ol?X!/}7_%'/ ס])x>E%m+{{0.?Π̑UġtFjLaԪnZʭsw(275E=w I6ۑa` /%#*cgɞ2^uGoApwy' cOwdsn ޹-yt׻$w=z{3{'0dhyhƤ{Wj h:juP%̈ J)Kԇ[GiÆw/aZ0OwPB ?vtu;:)Ԯn[jQ%U5eZlqh2+MY,Yf`)j_qbol\ÇO;:1wieh֩,|ydtdخE!3Tq =Uo4+[kR"795r C AE3 ![ 96_XʡDK-VϣGl[S.jv帮(r2ꖏ*-d`avКi'K>j^&gS CSTMkmyŁ*JiQ3M#.^051^]x兗T*?/}kycY<tͧ?KʹZ^tohF>qړO=W~/_9ƛo:e mV-s%@#](zA@s\m6}:ӟbY[}_\7VxZdTJdRU\޼93ne?<ュ啍TeGGJԨ5ZR($$oot,3N/,˪[lZw|>ttdl|qej"ip@!dx6+M{ogeBlOS?'{#3|7..]dcrt }Jz-˄j/N.aT-¸ "tCizg E-";?NwtԻm9B]؁EI}po,𽫃vQayP>z> ;QL԰ DD.a My3َ縄q% Ev#1B<ΑΙ8f;EE[(:bAX: 9V\ԡ\vpw-u @ %I3HPHA C.8PIE6 1}4;o nG<1[Rq'ABS[9ok]1d^Tc\J J (>ZMA$UVs 6.؉`8e,O}c_y.I wDk|aޔ+ ^zfir5㻗sp_ D-vaz!FQ]ݜu:b/JUd%G!2 HEKʒ:dLINGSz:ON{ .ѳɉ/HۇG+ `Fk B[7uph8x"(\λGHn@nZ pCur[+P)eTPȌŕ" YIH(J2ƥ />pceKE,+t2s]Fݺs)HU5*qr%KpwojLfvTbSe,I%M 2D2 &ArRڮ+%axxXLQ%ES(juR6qP6v]Sx1)xP=n!-kt9_SJl[^m%Ro9Mɲ|mKF7URX j +V{c6-"}9sVes PQ4 դt[~UÇӪ&b $SG iRl7[RUڸH ^*ng,R|!H>oo\_ m(DxmJ4V&Z_"0ǪVY (qψ|j fym#O=.Lݗ&=wfRIEW3eSC$UiL MC}CMA`*xqʂzRC*Z O^ igqwja%Hcz:^$`f_.+sN.cve*bڱekɞRg&A#;͈@ж\!K  *Tbk{_߁) b65Aq8#TFPc'~ا4Cs$?7oֿ ! DӜ〮P2@ s<t= ss@ȈN,Έ#ygxlf=<=wC^ntџ.EHZѮ54ZsqtG1@H ;wlekwW,Vm{ |Dr b$׺GO&d{;E2Z582,K|#,C’g%F>e (3g\YBz͡0w#JsR0Z$X+X ARbUQF1dqQPY RJ2O,uUSML5OQlXm6QG\)+GԶ+ l.7%u۞mnQbY%G9{>Z]|ƱS'?y臧Y1C\8@0![/_]X\:z|*LANڞV@7:6=04]Yv#pz*RF(EHshjҊaFZUeG̵̬i=-P&͡;3ך%y Hݐ$bRn4\isYvtmL$+XqZܢR( k#' \\NJ])~*Wm!wlAcʝa۵ɴUzKze{kW?쳿˿8;5!ҟOߑeouPRscsaCBO\Zkzh17Dl4)c p(.<(DL˜Q*^"bn0{zw.k*}%,K"͉Dޙ|@^ rGu,[SYs~H_  C*rVۗ:OqqϺllŶ<ﲆ=-BA?OеѠ ]ƾf=E{-bzo*C_(;XV?! ^~  F=uaλʈѲ8add:+dH:e ~O  P#a5v7V%@TB&ز? e.:P¨zL g=(+IgoN*wUjmv`*c0`A9uU5J=Ӷ 㓧O:9į>95TIX\@mO?lחWrK9}+S Az9l!h!@x+|y$[٬)l$XM0N,ops1*nͪy!ICL0ְzu!Ʋ0F>ԣ+_|wkTjCRbloTm32z")UyfV[1#L'ƒ}ZR6=N¥F)u<%wqd Qf,WאJ/3JkmJx'npkB<5ε,fk/.c3}6S̾s+}' wqǎYX]^YMLL_=wƝ_u`d_^?jLr$Yx@(w^َB_Kj&G8'NoJ~ֵ˧w׿Go+O|0N尽k4z]}f:/gpzcǼv,k|G Y^,zy۬Tj o4?[lڦ<_X1CL*7&g6$L! aEFV)0@<쫏yh؁ H2^Ek@@t<נ Q@)C̙3?&R-|D#MhGu-A 1HFVh뚚J*=z8рh_D*^ÇUO@ ib~ȂuȀ( (@ Y`y|='&H4MY܃@"f4lJaI!;2N>e^{42N+~hW[K[g$Žr[P ->3)(4[)ŒЇ8Ͻh>l1zСp G<]` 5x6?؟Jp*E-o=]<ꥫ|r8O3(.J[WUY\AL$dLUdB4[3'xeٔdx$>d$P |3Rpx(%K-.¶1XP@i!D!˨#=H0B6S!VH~@e1o).H$A&N}XR(PQW BsE8B&,c6$K9ܬ|[6a ]:8- ! J (@'$y8f _{ng}8gA%Fw?-1ޥ#3,QDD!Px׵+pjáiZ95'8߿@wv :gP0CPc@m ѯcHf@94C"k [ 'f`12UG c.'!RT5Xkvg)# zQIԉ۳>"N쫸029pO^`0bq}hGNW{X)iQGe\V,I;. @Ed{R/`i:`!u9^GJpD)\b&3TFFkci3V5 뫋۹eުEj>釆:tճ7/9w{ -t=^)Wg?<9#`YN=(docVisxϧDMqaj`Ҙl7}Դxi-EӰMSY4F,9>yF 'NJ!37Vg˽RiUVfRSP1 Åt"1pHЕ$&tsڬmm7VIgj|$'oZN[Սfw\Ԗfk3]/S]QojtBھ\z$Yeiefն$t[X' \+߸7?qAgG'}GF,680<73^CO|g~܅7(*W|nr5U׶񍿬Z7n}g/>/|rvs7$({7%A1gŲ{n'>:|7+g?w&ieIK w?V.W7n  ri{ y* zq [XSZ-}Th rƈa7ۭ\084D _Xl{咪yXOϾ SЇ}EU!y#ȩvymRlJZ5䌪='s` lq@H's6`N@nӮCÓ#SxcyHݍUXd9-NE9bzoVAhq} iؑAp/"!LH>}}xV3Oc.D=ѱЂÏ;N]!ߓP9РB; ' >{=v`x @SaE vh8Ũ~!K2s$v`(@~$cYHF".5|ԍXhkB©Ǧ'&.\X,G3 >+Wd**2y )ed8$&84Qe]CnxuI$S%1^v=vTݺ=?8͕=@S}^?yT@&A08 K1D)q{+xC+p3 IA;!~PP| >,iO2J`al4@H1hz XFClOJB$> T[;XUѫHR\A3cw` Z,l߯jrO$Df᠐;vcIw#@x؞Jm#38F+FQwFe_ҝ y^0AUVVF']a&+pɧNBJMYqu;_V.7Ad23C}'sf7|Cgϙݳmz{X"GN$ m7 Riߔla~j7vxH32;UcUC<$5jVHL{ǏlW|RS0`D$,KXk>.d!kϽ dħ?795~_:=xunzKGb6:f^lԷ[[ wx?nrisvmnf|XnzlZTY*ܜ][^M%l(WkRU^𖷁,mgJ/565Z,#h_SN9xhrbb|؇lp{%Ba豓K*%CB(C F^H &E͍2dp(ח(O4 >gށ}}ΣKhers5sOݫ!un8\z8NCZY‡t8r L'9x:h #H`YPBx PbC;5HdQӱI )Hh`PgQyC!TEaI 68Bݷ'p~pONc|:p,Dr`}*,lԹ$A,sC oY$Gq|Jӥ]?̭y6 ktA}h*hީDt^s?~A"U0<{xU@G%87@0lJ {⦉n$t0ݫztj{+E~B-)=)%{;si'rQ"ޕ.н)i<%@pڢ6̄Tۉ(;0΄,%$>!Q2޷;Z8ʲ9<9WdxF€EQd*{0-#c(Z$0"lO3D9=%ޱL@(ysB|Ή+R|7…vIޖnj\.t2klb^6l& #%tY.=poީ)ĩP%]grb?C.,/.,Y[_n@"U;ee[Mb5g)ۮCx* ͺiqr+[MxRM$p]ǭ6Yg0MF\YQFGVo\uZنd|^Qubg]X[Qe)PE2vBi׵̰#FULfpJdKMUfۮ.#-Eج;BuKVlk8̥S q=UٞPoz89m:Ѫ3 Ӫ4[*|w_F[+ZǞ/[o^T_^V~KO>Xmtt 'vhb^8wnumͿR>zDۮO8`b`hޜ]C1ٔu9X@ϥV? si2˕ouwȰteEy:۴*KK0] ) r&RU(b&D򵹶E,n5Vʞ1XR~gʸؼQ)&ӵKppϒFum}uHgSD7=%~++>{{X][ZMڵkc~TrO<}.,,ܞG ziv_.U ̜pSу3+kׯ_>ɏҝ۫p%`Hb1wq_s]6ec韽<|frb۾+ /0cQ^SJ&rL$~SCɄV,3յRecO&2ٱ>0]3resZDH߆g'&G*ŎoN{DڞyYZjĵ`봩$)lA5=_{'s7gFOO>x?` %Ƹ3+ģJ=/G./^/1=א7gm!]D+-csE@{^xDPNwl|: U0Bud9DIU{0&b­."Dh{ 7X.]h|D8x!{ʽtႻJP$>ߝn[s9ر_ QKq ;҈REBK (-/@Dag%:1bhF २ 8a]ߟUEWedr"ɲj`0:6AFiU`P@ 2 IjBb ]w9 q0Y'42%?k׮ Ǭ?a@Tq]r{6R3i1 k@艫kKGBy4J@R,p_݅Uz_]zw !ɟ8"z k|J6)w84k@H*aҮK:;FީPa]XyΊt]+N+ES$.]:G0"dQP~3<-QW H/1=b%][VM!GpF0`0=x#@Ő}!{Hb| QwPG%r۳@Q$t!ZI04:%<4Zllp3CSZ_[ёCCՊ R A`)V;<10.+V~ׯzC5.W2 N\ѰU 9+ƹ!QdD8kkK3>8pdzT4S.m4ٗ, AU^]Z]]]_dxCm[R3jK[3k>#ݺ3Ĉ,KRqcRPyNVL)ŵ۷֦/gTjdM*&`w0 UMħj:./[pLiC߽.O ZrmbzڴyJG}DW_?ژ<2:ph|fɇVek؎4U|ƗHd ke}!^.VնcIj;riLsN^|/d(_ٟo~3ű_ߙws굯|+u?+r2Ɗ*elkkiڔ<mm(2('TZOǎ8'q?sѴScvK~mȿL K J^]咕U t P(>7JKk7#龁d2}\P)7kb40PO%tZfҶCGM8XkCsF ܼyPGb1xЉ%;nmm'r3f+JJ5Obt2ܾyiks7{3=|ca8'V8wJfCIm8&kr*R)Sz.P@ e "ZPDhC-(,|G!׽A;d >u{w +`!.@'#G?J[h ('uYޜk^v{Y'G>B%ݻZ^Ȑ N8] +gΧfB]1@o~C xS/NgD( @T^b$[8ڤȁw(4s]AŒ*Fky`1dP8e$5<魦 Ѣ)">r!@qfA8&EVx' hc7<{qz{zrRYѬ6n6ۄP8બAJmR.sBۮe \ aaI6ɍ囊>v.ŹOp]pႿ٥\o@Q4¨iv.1#!Kgq7>]g>JnlooKŎnħFُ7jj}nHkqBl;^ۢX8E\鸀!Kdܩ:--mU*L6?qز1ϱt$hg X/]>{@ŸxOWwwO^O4}Y{N>~3dLܨ@ HY-,龁Ԥm5G|OKrYX̚tJp=VVW[b.ޟ16+U: r܈FjO%RK|%Sp<=d$vseiqu{u2DG<9WPbO3FNz+ם";tgacb71vxhqq/9VT-m˲ v.?0ؗbGGoo/_6;x[+7f^?x h*To}; A4M'-=l !9B#I0Qgz~v!}4|rsWYaAB8[J4Gb~2PTǍ;0 )=ߕzQzǻd]w<G?xK w04 "'t6!cc(n"@M@#bP'@TjQªdK(E) o؞=1vI)~P8|wj*nJ&e4-fH >Mh9f8_<;:D6vsLzXՒp*ez9v9-*r~] ˽r3pv$f%9\.ϭ6\'XriahR$-C{K+-`^{/!8?gDڸs{6|g80'zpzsvR>Oƹj֭ۗffQT@q!!.XRFfhmK "I|&Nz8;[wR# g+>TsdnX<:qBV2rM2ġcSECڪ_fHv]r\k`pӓ\~Xj,,,6V5{辣ĉKkVfA2,U$MR?q׷,.{'O;}c=Rx7^F263&0P& ɒ }>D󾇁bJMAcg.1Cw"A8>ַ#VHws!K*! y<#QbE[JG{JP3D`5 B:Jg!p@iTdz ЏZTtoO\B6^ &(1,ACDq=s"! B Js@r 0ɊSIJ)~|7>Hװs֌ | /E~7;(.eZ ßS .رOϵ/H-, DCF!0P`Fr7$Iޕd\h1J?ٖN]:"3$Iӕ_gɺwq0 !F,)ë'Ip}@MD]DՆ (v9Eqi Y:2a!zҢ(0 .١?BS QWF){v@⿠yeӵ3M ;]*љEQݓa`7z+S>3tݱ *[=jE kC7!g篮5%NZ\y6Vui3043re޸qn74}豇GNߙK/޺xnsQ;):byĮvsu<͆mrVhZTj4j|:&t/w;oLO>}2~ޮH.WK%OTwy?jH5IU3Jm!Rmql 讧#gN fff Pm Tq\&ø&Tuج%XC2fVrY/on^&2>ß,xWre-g٭{j,ʹ[Ji5b|<ըm) 4>{ǁNe Ӛ[Z[6TtIilR>YܦY{o,.ƯkWk&W~Ƨ~9_uc[|<[c$Y_oyrS>t{;W._G%q-(xs ;,U2֖IӪf6?9u!]ULV(-Q\WNolڕh5b>=I]VX_:n44M3  OhrT=Azwk%߰R'b٪4fcq\-.a^,Rmڅ-++[1oˎl'Wf P_>;ZYj֠$e* *c:`o+S(Į|W1 zu$^侫몲Bׂhѝ@r$$At=FJH(2#AB )$۶-rG0QR@ QLJ ܼكGvKak3qXQ\G@(.LLeS.z(I80~+ifj6UMMRXL? rQΊ;2Lݭ‹ãgo__bPr0 AY08 tǠ#Krm.9 b+ԺrOx/ͬm 6{%eM” aԷ!J ކuP z?q@eǻYT ᅢ=$yʨ]A!] h!3E?zU9bkĞ3TT$Bc9(;fQ3{0a FuL{ qd5+4t^'3Y.Ȉ&}Hd_7˓%6>x4%yENF}y.P$HF!F;pλtҴIee3}clpz +/}o}TNk[[PfVv}>SY' dˆM)5msq9O63­FjՈ%bTn_y 玟8t`rƭK[Oԧ?C1]$!3:Ixp}egϾ53wzmam9Yb}K`DlXwZ$.쬖PF5Ltin}EHcHscFѨqfrZ&[!w$,@皚}~wd$JܮNlUJk2FPG v@ `ݤMc+x"]=t~o}mh~ėĻzcrvݨrL2cGVM6)[M2?l r:M_~;nίbʖ&#?I/O 5xJUU"|Y?jnd,9eV1]iԷ+>ijKZ&[L$աl6kfZuxk۴%2/YĔREҗV}#=TnrsS"IU&$ۥDrN;H߾g"\q{v}|ӟ?s/>75 ԛliլU-^prsPk5IiE*F-ӆ*W6s#CL/Rm;cmcEb2ZIC`ֻWQ'HؓeN u9nl xhK݇Ll/m:?j"&'ZYkr&C@6VixNJ s<2&0ӓ >0=*t݅a8BI"BIߣ%8f.B~ONP@Y6Cr {ThOp(\ÁDP.tlχ@Chشg>LՀAwGߖ >YD] R;1ЫHPLN0TE0rs30CȠCBǔ" b"! hkHn#W4w~,'wl67<<|ȑӇ$:yʯuۅ ?`ѩSs*`.9Alpwڜ@؈~vkTQ pFH(@W?G%e FaZ wb'". gA`c󤘡cH8Tw+Z)"_a AD/P( R 1zoGT~pwv=sO- zTQq.)+hz],$8%&%"/_c߷T䐙zE LFlTgviW 1DQu1 &] ¡ "P<:tI u f "S2q'R/)#fʃPG.[vȺ+[H ko\t5W ɠmMI)5&n5R^zJ>#zRN\ XR`a b$aoѩF1O2x vF2qjdao~cU%"dNYP؈)<ϓhLWɎ:^Wkg2uX̊9@_լ[3M2Z3Wזr '>͘) ~:xt 9#d2YF{QƊ=В$eըmӤUʹ1V$23 `f9>gk6q'rdX.[Eq6Vh2œ'Bڐ3{;(U+Fw]:ի>ȅ]xѩ|ganu$Լ/ )Paf^CWb|$6 WmO T"]6Ui.EvKE !VeeS00\^6~oܪ5CÅ|KeMKL'bz_NSG- c(5iҵfvuu44j釛.G|ySMu1\v @Vg'ضQ8S?8{Uumie)77n+ lmFOl%Sl*CH ۅ0PH4{Q' Q<T}O)DauG0npV։*πbٻ{ n1g>cbb-mY8N8<$R]Ñ<=}0 ъӷx3ׂK'b9B+]wΆ%XF^p z|XřVUҷ| ry<@YUU4m!@ B|IRr$=/1E*X"(QΘacIcqUiBɮJFbvnD"+Ep#J-%h%e .0nc5ƆLP >Gz[fOsO+eN*B!J/s% 㺌hD`,E؎Ĝ!Сj F noMDxa&߲oT׾ESÅŃU!!6 UCxǶUYJ% UAVJM{~e[&T_==OON䒉DLQJ}6XB:)]+O&baAJ0ɸ˜ZRA[v\+[Ã'?HP6`G.Iqŀk9k >T2O^XiU+YKMLyٱ%]죵K]i 1ǒB=)ӴHku&acȁBU|릪{ßPPln,f$v+o߼k>KGFRl4@Vo[@apfpҦ&4' ֬k$Oj:@u8d͕U:U(qIwC>΅^b9W~+K?>w51huKz_.ooYk:\ƀqm+A7Ȏ[,d)_VNյۨ7cC6:rD!L.B--˒a]F !JgXG )Lѵ0 SВIňvw'T ]$^Qs ԫb٦i&Z5yG5 cO D)ڸD٧3yťU@7f @G\|S hm8dR4҃F$]fXjy`:R6ڥGlo_U$i*yyp;ͷk)˗ YX$XVH;[^xeHNfuBH+?_!6Ŗ}BTqg4}g{a qvoa='00(=v83Bzk܃^xw홡8wz#9.0 C ʊg8WWj-˾" .dPL+ݣ%L{.W[ *O)2o5Zy{ 4c ]RpLɘ݆7_X[jVrѴL'9)'̶R؍ky̡j8y۲f7&|jV' "ZMVdkc}aqByltBFjVM9q.nNdbFۃ;JrVo75i`0ۗEbvuMa>a&2ThC1z < RYRl1KƠjfeU$k%a L# V$'9P+3.әbi_r;U%N?#IIc)@Ysd3s v;>>O8tx``d؝+{ Wda(fj&irXY_ŗs)P1D)t!<|&>4K'"lf@! ,KkwOLGco[ʀV1&)ɒĮQ[ӄP̣V8I*$SC/>onX BTԛ”{p`KhDD%;cTx v w0J(sϲmHop}Q0`C&1V'.A =ui;mF`I`Jt5@ cXR1 BB_*K(db#R"eaz p kb˕Vy'atbH6m3rqfE,)c ?Mz;s?qUU8¯)?92z=g Da * on@\fۑuI&=B)ǚٍom\ !g?+?믿Oj7frr駞eB=GKD*s(aE\ 9 DD:&3⿄ q8p(w8IaG%E1kYgU$-ݽ=Hf?R4B.P&SHtZR3Y裬ZJm ĽZ JD%U1{vO}ßԇO=2xrafhE#Hz" !tm*1]*i? h:(RdM*mIu!.KXW%sB\JD\q+n^0gS ɒm16n..?G 9`M5MS8d6#p\*[H2d@s~5W6lusk/ d׷.HEI3C=nU&LO (l<=ZXmT<t914|k.ϼZzxz!0FJA F\5u|bjI4,#Cc>iZ,%.U@Fli%ZB'Ae@PXmyBqJj}lz}ξO^~Cz_f(6}F*'??Wc^RA ;ygpnA.wrd'P8t9WP1 0rWEo 2FN죏-o~oi*rEw&xQbB,l]-D<֪ΛoΏ_o5q;|SO<1߯8! @nl zc8t), 2O w'QFPvOf4|c &As*謘0X Bw]Y `=C^GpvIVXcwbg0u>=p@oh{ =bV:]} D!GoD1k  YֶB+r̝Y#GFr'I@V15,)JvMf1ripFu++o6jdJ?thPT(oNؗo4*^._㣎z+|;Mܧn/9݋Eضqƈjǵt6YAPAryc(Cv=v Y=PoDȄL=_Ps%PP,@xFPaN1xAJ7g<yv>l۶.uw\Qn;zݲα A&2,# 5c _ $J`rQ :P5%2 (kA$viIJB({Db@ CDZD13BAM%]Y)SGC(K-ηͶ8*~Bt(jp-0 ҌaQ]n$)e}bjZxN9|!I?NO&R k?G9c]f+{(.CDD{}8 D.#ùp,(8q>ܸy^WFw,aT/= z~~ꫮKB?2ʡ<]|G|+a2}Bn6? h CйF2|@3&b囱gm}ЙΨȶCs= {h+ +ݬnZtjh_صW/8KQXܫՎ·a{^ 4Z.H9u\lhZj[ĨY߾4Gfo^~ac}дmRxbdǒ~$XѬT۫||uWqRYX+348}eZ{DV0xQ۷_^[Y,izb!A]Qے-r)+"k=2^>.aůxM!hKW7-1ږ%el8fZk~Ȥj449V7)Uw KISE׵%lIJnHqIj t)+ٖ47͙R&񉥅s?;61YzmqV+%H3t,덎rE j"=4ʲm7V(YNvӪ6&e- -ƉȒFbrzPwt*QM" [PoܜKủ*IjQ2l\USJUU҉!d1YUNg&$L$[&I9ǪWiVۦ$+4I <#J//mnr}bPbZ X\Yǖhe{ݨl5 W˥;r~?$@j٫7~Qb~2$Ԅgy6>oU_-kX̉AIG Mm,3.q=@FżOC]ss]nٮ$ +hK ` B'A>ysd1$Hr0RZ<5yV1Jrc (ǘ#"## 䊢esFcPPX\[^RTՈ:}X7çQ @;J0a vyB, !k+kNkFs[ƌzY/KcYZJ[K9?ӳS#F*CFRbr"+ y5Fh4Z[6XJy1 -jmync`0j7ݹyVbz =TvyneuˮU)ㄔU|WNj"RA" JYEQ0t  ONMOno5,|/W]puqjLajv sgd"}XahGlR[_ϮϴiO'EF=f):N6Lwwk旷ҩz,K/n5ꍙ7|27N>zpx(AV&3)-dFŪۼy-IgrT?QkV}6ѨnTID6>4v\-[Prx'3`ZpwFN%3L\.AĒɸJ(LܬudcCLj$MQe 5׫oȹl %ej؄Ѷ㨉d_&3hJ|!Mjm]$LPcX23!ʡ1o"E::*bDw[Y[5̭3~U'x6,}]64- r$v}}cUDHJQʥVs C04ZvKˋ׿rgGODc|ncmUQ:bɩGgKQbG] \x]llm= d{h`:a,]GzW瘉P Q41"\o#|_jso^WUYo- ]?a؞>Qɢ6v0 h%;i&kY s}9QQ`i:d(hYd b!q۶cc aMm:(d*ߟ˱63{OT'ucԳ8"Fdk-PK6ejv 3cfԣ$s{U 1z޻|74I Eґa"#$!4 HۛnhZ ELIxY $8b[| MD4 :'E>Q$ds 83c^V`7|̒0A1 rд3g^ 9|L z:#CJ1;2.ׯssѮ&f[~?y5 ҇S+|6B˨¸FPUH&KOCn0&gOܣb&8'U溷]x J7B\/)lޒP"P x eOt7ڥ--ů$4!  v&,u>. )ÓFeN#ѣ,w>bPIIw$ag}htl>k u 8vgsFgN"gE ~azE 8+>b}{rF-RCqwI8, {.B#bY7A ݍGaJJP>)nO9At(=IzBDݟ6;c< MqsZ2 mߓ>[wcP9ygJ;TS@8:;0|׮_z²<~#N~%v3yY:eRP*-mpڬޮԨ!!e1P=$%!bșY_ƛϟpa~ytz2t"0[fHf JjZ.%kgmO>R`pϾvڕ(ċ 'o~/0TIhGgx&rծV 3<=06#P'|~?gb88__ZݟAAv 6Xo]/2]ڻ}\zmFUף ss@]^Q{0P{o״Wj嘻޲]aM {v W o7Y8 ?|lБl6(W"}ͼ~/.msJWe'|( n\[_ٛSE#x#t=ٞ)cZ3]LN?(WGSf=hSdis4Iζm|ܥŹfJ0r@5r U ɡC'':H,W=ti~u贚pMVխW]^_*PƏO<{,566u֜&즽ުՁ2ԉO#G'>tb.Z_^]JUt([`ѐ@M2(؉tBU$cT&Kp5UO0UJuw퍼uB͍MxI͐d}CZ<^ZۢK2*kznj2)q,egnnRvúWrmZ6m6V&Hgǎ{4 4./nnT\z0Ivna(9<8on?'G}vr[*S@ k~w;46?:6Hb'V* uj_7UR(:aD(';,{!?BpFLubw~Vn!a !E^D.^g"ʰ?zXC{M?z~}cRp$d8j CЃgdキ"N:b `4Az1d 1d3s[fsř&ӟǵ;6mOb;g\'ill8J\ 8\`D91drX2*j^H4[ſS'As-Orf h5o+t{/jjc,'7֮ߠf >(+Hwa=#LyN!80^ĀK( } -Kf2$ZN~a?λ׏'wQB:÷+kgxăPOF`Q9͹_c,v{_:x.^t ^U:49O.xڳl˵ʦ(뫕m˲ XbV>#)>f1[V"?s/]XZ^nؖW,d>/mox784>>9?j +zZT@^uJBI(N?csswn}žDLwe@V-$UMb>G|vUi^[(ZȦ=8ΦKLLIzۑ9WؖOzlަݶʍ6T](xVtZCVN1_YgG'YZ\X٬#ޠ$LBt\dL1dkJVj8pbtp`5}'>tCܮX+HH@]<\,[vu,UPNǵbItreclL*aի@W(zǥx.^` zdl4ni+\I>()2HȍRb7ӟQsvkuu;HM@kd:q#%SѤ>\Z][Ox$W8_Uc x߱܁ZͲ_|fag:U,VZ]x-/bdL6MHt葡|V5 BPQ2~R!^#"hJjaŧvOV']fn@|#DOPE .`Lp*3&ED9]{TXd; f(t8L y{{,CRA W&P- 8lgQ ##$ULӴm;8f*P9;P!`Ib ΫѺ9gwCΗ PEiyvUv!Ɇ(@"(_q\Z?US ="I Cp9ζ<UDV%=޶ُUܲ8X>8zDQ@`@`1FeQcm ϒKrW~k?¡!Z[[E.">9X1~dt8pP瀁*ߪ.%1&@aаlčkۛG>#`[N(@!+>/_ל^y# ̍+_s?|j!%pB{2)*+PmӦ e0&Ƞm 6Š&]UI~H3{3 n^7pgעxt^O)yQ^,ZhpgxF~Dמ>(V3ݻiW3*:%q;?dE2pM9!B2J{n$ٲͶe{ّiKUʛ~8S8odٶ2 )>$}f*rSC3|jouxҵۍMw4Hu$jC qkͶN:Rٰ)J@A#&cš%sؘХ^:9pXdi|*]+`q{]wڵ6ljtzxq-,(sp:ɸ j\Y\P!:ursA aICLBEN 8jZ)yM8?Gj;v]Z>tѶ%ɘ +C5$'8&XڬlWU$ rjsN ]ߪW$eqڐ iem9n륒lyr03% :ŒIz˫4j+ϛM?ϱd^ܼs{7G%tDa6 *t2䴤gDI)Cjct)M7ZzxDUVafɊa͊& vZ)7-bj\v0L'UqT+ Gvk/SoSB16Զ쑱qZ]Y5[R(Fp\޶P>[LyѾzJ}ǒ;xwsa:/ӎٖkC>74ݵz{k\!Eߴۿ#=pp­k+5ju(q峉T\cH11TD2ٱNaب^V{TrӒJ½ p^T^FBލ|vo gxaT^XQ]PweAyw ѷ@]{ sq%Pl1mO$)u0' aA*s1C (Ntj(6!m5) % IС*Vb81LZ7*#(H"1ENAWBR /4!Qe?Xʥ:uAT@DH #J0bس]AKz֚Tޘό*F7n?p쩏8<9(0@Q $vA˄JIA@ӽF]^Vk`bWm?O~3cYZg]dN|tlxlZG'j_ߚYX *z/& o@䰖&hJ;Б㠇D9 ٲb$lCǕW4 b}v@np}zO"vGLT146d{Bߣݓ:ut=[#J%=x =н"zB(?4].{=OݽlB] ;Õ3&Zv#wS&(6K=:\xU/mj517g[mx6i|V:;o,c$;kF^&|~7^\\N(_ɺZkB;@nsm-R[A(iH. lMJ*Riʵ[ bF fSq-v{7?s+S4m?:NRf;uĊ"j*U3͖O n_rm}I6!Ő^7vR6<66>ȷJz\T7Tp9M<(Rq2̈Ϻ7=frxׯ]LT[s%YD:m65lz19)UJNfm۶+t\$zYmoLY N\&A`srտ.V^8{ႦIYNtZ[2-Y>t$;8U[>;3Fu[X:6PӹtkuFKZoW+B&=:2!D0hɍM{cu@Kfo/Im˭n\ϪlGG\R_9x22~sAf[嵵e*> " W۵JaPAҪӲMO.,.SϜ<#OiI2{so_|~u2抍\q,Ȥs#MXյJekykjU$Nq)ELjÿj"uj}CdNUb`J&w"|O+ (Q"!Z(X. },ԋv0gw$vs5F==^;71NIbXF=ӈ ^i2ϒJW%p-Cs 0xRJ[g+,$:z:`c&9V < v{W94e6cnPnUZ 0 ]NULa:.BA)F|; #X`dcیUk#Ђc?UoRB)~5R?/>ȣP*}*HN#$D1$e09k4@ mODMf `!e{oAeKWο+f "qvrrcA DqlP^5<ŲdB ݳӴcOdYՙ?gnjJbC2C>O}XLQwy;$?/ҭo[^2[&j;#|Wbr#A@ NNom1A}⿾o{OO_~ϟR6=_Wz聶Y_[_ǔ2eνg~on^n̙#'ɩx$SlqTYImmmo}V>橧? `W\^\Xu!d;rJ."ɲmknW~'?g3s\94FGabލ۾i(@.,ۨg.y7;R*-m YmuU3}R,udCڭz[}7__mB]k rT}S:Rlik[pW~dž+:d2KgiYGsɼtxܣ˗/+? 앥2@SKf,̦a>%Ŕ%w'C<#*eYV>ewY]U]vtc4Ihf4 ' 'x!>3Ǽ '%h\7mjS]ޤ7^{6<'͸zV։7:k__zyj{PE;gvGod$g<9cەiEw!̐K;`9%; z"dGG.^]a5uttA!p2-)u.66 25᎚@sLJL1p;440ϦQ3}Cu} :\̠A y(M1Ll$6G.:nR.ή8z#Xe^P?55Кa(S@J:Z"@if!_iDd).la aib 4RJ6JV⚩7I59Ҳ贒`x_Ӛݽ~lvaЛ/#J9lr + COL~Vvo>|߻~Wy"Ob/&ac7Tt7'Q~ӵ_DCec=17fK+1@i  `9DrQ(M<ܯ.410_K JL?X !ȊX3eSGAG% 3Ai 6$(:$3*ubwՏdJu Q讶C|_D|h y^Ҧ=GՏ֪^ϗ[Y[sg yqk_{sܩ1`=[U)jckK a[o[mb*]fͨIHⅻ^HH ,wΚ5(?wlZv"&㻁J*nqwyԴBz]5ڠBၿֲn!fȆ`nj`@28|Yo$Q#[Xݥ=3}ǧ{'{q󽽣5o"/CFu)N.\&<9'|تŎDZ3lZ[0LDXKě[! wvŜu!sIw2 V_ZZOVu/'4xã37n[^;sG?s/*Jt ٥!B썀L ֒: តqF˜pfH !7~z{DمCoQߙ0] C5q.8'hZ洞2%h 2ߨU m-0Ȁy=qi@a0 PC,7R!@)A#s_s03+MCC8(ct@5u8 "oZ!'nB}oܹj h(_<{/ 'lOMUiHf3d;}ޏLli% h9`Ae%es |45S C!V 4`*2׮/<CC}8}:_,r?:(E~X,g[+co &1wtzu>:ڷ4ΨUoƘGT6t@liFSyg'dCr:(j"TdDgu b4#.`΀ 2 toH5|)z qH@I&s5qxM1G(1Jum{?S˿3Nj#5E>2L1aJ*f#Ag*X g /toGW~`,)U7P$0*9i<"O jnQQii=+1iUSfD&CZVd'{yk:qr,mE@L6CZwTPoKr(涡=L_7~k}S3W7kQ\7!F$қە̠Ӳe !p^d%NpiWF<*6+;?r}8Z"L63vC{SZיҵ.HS:qu 㠏3 -]Ϗ]º/t u~z>,뾨;ԚyOݱ#́`>".&”Nø!m@mHFWRVHqȄq{덞B<~%֨<}V}-a"bK\a zj鉼pAm OՆ+Z~l`V*l'n\Rnue~rfxx/UVN8Vձ'gd08?*-])c\?1̻V^_s˕^.MONwn4w.^|8Cs'`FxL8)^Wc?[p0K"t\ $P1Ēz ps8y?l&FHcWg/?7Ӎn,_W|}r9&//7&?s?͝RA7^`9B%C.28)4 On/^MpO<-\NIfF݌"N3v\q v}W~?S??/J)Нjٰ9I(Zg2zq)C:HᐙYx<㹳R>kyGUW<ƣJdؑxۏ|xrx*!J:CP34A]p9$qi(ik ory,^13Ӄu/|/O>W}s /O=s|b||/^~|= .-%f{`omܼ~qiVRhJ=E[+"SE_TJl+=cO||N9Wp}}?=56iRoow܅O=zU[kk{*qVWw&ȟ\xgΜL\[{m >-zCr.`rTΫ5bѢP.7zu&hp/(*ct\ńD(?pjh pyݍ#cR2J#C'֗ϭ6&v khzjZEJGJ%LB[a#NtrB3FX]"%vr%+2:0P,Ks'?{:対t?~}Xn)\$@6` X`a\s7BQ3`s̵L4&9)kJ3|؅q#0 l$ 1B@!c`4e5'eM8b_FW/Oޏ>Y8Áɋ ctJ2<ũ Ot&'EW'52la?b+?cxm# lhyuw9F&dYg}K_|]+tǿggsYl޺| W?/:0KHIqc%ދ CC h RzI7.R`\fQ @܊-gC5CET` ԛOZɟ~KJǟ8,@1ծk6+:zΫR;%5ldMDWW<^kP !^gBG! ID_Eժmݪ,_-VGZf!* PEmN'ccHЃ0B.O#R-ңrޢbR29B"H{^1,Ȏr2(,Ҿ*JF h]W0%R6,Шz$ r30IՈBS* z&˜Kڋ/rezb}OOVެ;R\)%R(SDyW_\j:{djȠک|^&> povGXlkֽ6q{iccW^+ xbzw?yB[Bſo޽3?tV1@ľ'N؃S,ڮjf+W, 3:&DE&z{s7߈[kaT$wW\y_خ,e!e,isl /KfJaep0raH0&1$@˰|jhy]zw+Ò3BDPyj5πd+e>d+iVOL8>ton`HZvTC"ur99Hi7h*e"))):F9Bz]33B9HKX((`)Ϡ 0J^ [RAr}Yl3$!Gb 549`F$bY%#k"44<; ڻ_^cpWWɆu0!E X bnD)3AjXj sI/ŮteRSJK5@zoX PaTWkO}O>uX^;q/37Ɲ3lw?| WwqVͤp9̾MxEqgaxXK[o}~ßXQ@t^JbL3 1?D#41|[o~ˢLnG4G(;fyv;,>^@ 66~T}V_aæUx{Q2O{q*@fkMPI>Ei: vt:sdoӊWtm@IPWbe| A3i(e]TR4gJ#$2j%q3QW$I\N0VcX&q)kWw=}ĉ3ggNJ9hR1(?kQ0׊5Ꞗ+AZ_|auuotm|LFl,ܼ=i-EIR]{as&(W+Z__7<680;;y~x`?2' 86rScB[On9"7ocD8q\ƸJ|G͕us$)]#3ţ;Rdš@=dg >JP:C}GE;[LG/)cTBdcB)6vŘSu9 G2i  sBK/d2@(;0\bODL 5pb)UF,e )aw'IFkQF;#fK%*e tK& @,2&QDd9z2=BhiC+sb[skg?}޿CHsI|G˥Dn$6Cp@@9[2l.дC0#ր(%K.@/ܘc+{}g1ͥAUC_C|r"?5&( 8t??.zKǾKoz=d399)h T1ai @.K7^BM`yFD\NMid=һ( } '~7o cIq\7{_̜3olYI.@nz|B<;]vhQG # ~P_kylh NjČ0;ASvgɊs#8y<,پzF36ityY[u$}#beRH*LM&1Q+R:DI)(Qr% \I[AN'rAsP1*Y2(8{DD~Y{aqVEJcGGǢ0_:y򗿴Q(H#薡cr#S};+;bT*r[(͆Ys}oXBLqD7ҡt>q8p{5S&Nx^ͷSȆL@3={j԰p{JOU*<˛\bSkmqs(+牋z7_y}o7ڶ+hfxb'շeh!^mbG|OA q̙Q,ܞ[=ql1 Lv[r |o}k;ѱ%ʹv7VexYYY f1--,mm)``Dn؈e,MF&k WW쬿S3OiKv[[gNQ9ʲ._^^^uJOo`hoeV>/{˹WnU;vsiaᶉgaXpm#hi]we2@Hü2솄!]WoW8QUt8a2`o}ҎΦl7M]Ǘ9\rGdnZ CᖛE"1Y 8iFnQӊZ%aLp&xQ2 !#F<O `Q 0 _d1HhHYH~kq ]P `Z+^Klp'=+jjr09\kR $x+L!dbMT)`0 C&朹觿)U t5r 2` @V8^j6: `mT_$mhHHB0& ^*pWL3PR?n߹/?܌p7Ǝ_,}饵v<3O;w_}u?| IYrާa-0 @i"r\x [0I@.@BY?Zӿ3o"6.(qE5oz_F6Cljtu dD!̸4: @ι+I!q9h% 8Fr,+qr޼zCر7ͭWCo9'8ntwvK/ޛc9\)[ ~;8:ݹ޾c3V3q vq|OAkͦl`dv4EFW//\{͹& ?zN`V7kwnn6$ 8DPpDF tH/ۋd4z H瑶2mJ@YdE# }?eVgBi*}Y^oj26>9~\;tk:{F67Wt(; pY!"A&cUN 1h_B0{}ơ$8ʇ0l2!GbYEg@=4NikfO.;+G?-xFF$J5E)mRVBd?gJ39}}8"hoUdRfurh.Jqh9CCjs[ :QgD}?0N/.޳~(#z{x_X[w{o޾k7^=qq_/jk{X)p֫ |=+qY B J|9/:+u"QRsh3<>7yTD>c܅su~[lQ'<,/ȉ|ē_VވO mn5v3'G.z.? e(&˃>KdžJ ,Xx*ؕ@`sfg{WJu,5gbᛀJ O['~W#Sꭐ O577ߙ6.w=Ͼ]SŲ NY?=<[݅B5֩ , 4qΘ!aT!G.ZׯWk!\pkԢ(z--[34>4>u4WDxPP_a,=G˅ Y麵jG+ sO,ɒ@V6o߻9b!0ܛ[qvsO6~˷۴vc;#\cCgU>ۺ[]?hI;mTzrmءN242hȞ|+cvvo=}S'~'zmzz/^仦<'FH]'NW[s\Ooh@{q@IР]&, fP٘,;ӷdm|;bD&ۈ#L.HG\ף t<>zwVv!# H߹|(z2_y3фw<a .kP_рԤɠf4(LϘl1;h.ga+N| ^JE~oW>|2nBTOX?K_1/^~n>pqdAPjΐ2IG5sxiM22+6 !CnfmVMI+M?5ÈO?kepB)v9UXc4!5*!,1n|:G u3w%ذC"Yo!<C??2_޹l$kmV'Zsγvly{r0C;(:}@QÒ\ DJXu$x=R s 27@Np8ZrtEÍ<+B ԃ}rwQ{{-׫Z&8NՊe%z؊5lZ7w{z-?`NB =[ 6_-w3'[N5O[&p\ FR019^̧sAKpce "TZ)G< l"gwi G3z>CC9+272k{U@mtf3#~oronᬧR>1;[P[׮-ͯ!`'S7[C<}D&vL^&=#@KsB~DROuqu@&Z-!@3VSRl GGJjRH=Kn3=sINa~ּˋ垊55 Q޼9 <x^:}0[>o4zП77w{Õn=,彙Qhny;4$w'''sjQ Iyv[[Z^gNw҆S.tvv/׾k. gO} OwTv/$ $(ڀㆭ|=~3(ׇ'˩fPtWpcSDpRZ-.UR˔Fq YuBˏgHwH~xjףԝ,6R?Rn̚42p&t{{ӧIi|:Jbz}<'Ft֖ AQ!j"C e]= Ckgf+ƤиT&e-Qi.K~8Kpfy)10l/+es%{R8f2k Һ@j3 >E0f])0 CX~y+|zIqafx5ۑkQSA +4;m@s.(j׀*h1hHCLn VK6qH{|ew? G6#'c=|ҥ>hc7iҎ81*R+t'Oo}_#&QBv#$0N?!}c0!=q^Ȣ"|j~M2@ i.DrW z cC04o8Q  /'?S?Ql0u'U?l![bvБ H2UY#=\?qds,qu/e:eUm ~Glt )U$hR$Vi.bJlbW\Ns^/ݢ3Yr<8MI_![ D΃1cu<8*+QaM;t:6T&}Yk2 hTD.@3!8pƔ1F{;.gpA}*a.7OJe¨3DD\ج X޾͜4R B(T]EWq\*b;*w EOxB+&sR+aJ)eѥAGycGG3pExN9-tBQy)Hư&EjGHjӊ!7 522"b4ic?7CriO`6)EHhU1#z9fb@8d*0N㈔gJh&*uXS-Z()VE;˸Ј.qdVi,Lolo%ꓫV2I7aѢHYC a`= BF 3 "FGtN H!]| M;e4,ԓW>*'*}ػ.:x=SNլUΎUuCe8pt . 6He.wFC (btܥDB΍t?@^q Q 5ފȢS}-]ojԉ82@*&bl|C׮=Kg$kqpB @1NHZ aKݵo߾aMr$Y"2Ȑ.j8f;81Fv6\"s^/rrDž$R_{C"q`o@D&T-s}[Ҩlc d+x6ZQub8f#Hn=gtf z^/`"}.Y4FV"bP6$K,(2Wlgڟ:4A5Ip8TGgm o ױq37KD=b.P#]!"$vȁcЦe+ q L<rD=n0q9 >Z2DʍzRިJny}Œ("F`abkW NmyYޮBZGzso+-$ĩjbةrJ,#cEQrk2X.AxB =p{J͗vxN:1;;ed 0< \ptĉ68wHHs7YH)Ɯ-'%"犅ހHW_ysmscdlONre._PVWVWl[6pP9ׂ`BRmp3n& ^X_YxIwutb$`2LUrǏs\5֍8}s]#xl xYXȸBE1!2+_(;daiaF3[)`nؒ6NZVȀr^r ű1|kcMH a3'G?qkKY6 P%_)lomݻs^w<%$~]41?}z}~6Ij_|fIaRTqoltxV0Jjw2\+J+O,_r杙g~nfz6r sH@XD&=wW6wj8UmIO$!0@E!6aR*1]LnAg03p` FCLit)uWDt!{'-ƀiHɏA)xҪyLd{1KmFD&ص{73$ ;n$ˣyvz%irkIcu?+s&0.4fHO^݂* :@|_(" ch: 3dFBUf)$ Eg'q}3^~e?(0G$Iꐌ 5 >R JiuĻ1dHEx.*7_XZ>p='z&5g}]T3e͐ي bqM]X"XE!4 4E۩P^ N~x7NW8}Dl$z}P1i\Q5mIihj#$ܔ+3O\9ūk !cP ՉBgc>ScU}e@C?rx I ~v4eb%2)(k'[jY"}_ #3=,,޺%T2Cc݄GۍQ 6:5+n\b]6cQ^>/" r$ZU|.j4qL;<+_f3vo3GN BLLs3gfb/V&4 @C|с%h"@Rפ3 l[Wn?܈kB!vsO~ $NJj8 z^Z)JlnX`,d$^RoF?{xFK|BqEƁEDiQB%-0wŷj7qiO \H䁴#.Pa_ρ<(ٌ`$zAIt,GSk-i (~P(r\s_E0nbvR.gvY.;@&ieL ذR70 #VǑBx9w-`\h#%Ut$%Qݢհ\O yo=Wxcrղr- {eejDc=tlfn9 ?Rx ůݻ/9(6ޗSJJ9Q*1Fe9#9G4&]IR.X،WWV-eة_>=?c+@_[ Ȗwz_~KN 21]nna~n N_7wwQGl\iYN=t]^孭X춶#rqk{Ӳ syAaf9wR߻s7em3vy˚l$;yb|wys~'&ٮomsW@JlP; CJfK2s3f&,X3VWX^rK;75zlܚzsss;{%Koޭ|y J,р1;;yViD # JcpMt6A#?֙+&IgAM8"vWp$ K0%4ŇVhK\0]1Їچ73;+lJYS142.ٴ5z8cE`?@IakW2@ 0C.JLA~e˄K"EIz hQfuihG_ޕ5y;xh sRJeۆ;@2Ael|\)4i # &2MS04piɰ4 0"뀯MYK8]#) w ;^trnTs UAe@Hc6ɖ>_aO[FkX]kJlm5EP1DSdZ:ȹDpqS LV_3N&)3!F$(J!g0Ƞrs7?_5|InhZ0p\r U !\^18prJ 8peAk:Bnݼ>~cڽmɠbƲBr˸m1SN.Ù#]v^PMֆ;qu3ul'1tD,Χ]tT@ ӮJ%} qv]XTt` 8@[Abh(-v4fXBP:_ o)e"i}+dNwhc -ӚK ]]O cF!򊽁kaW[Q1@eL;]U,*# fkWUr;<;Q6&ܼ/g Y4[\X|7- :<a]F=l8c ZNY6 f2 L8W.Xw톷7'ΝΏGEJRޥفYh^[b~dWUrp5Bpש>7pƧ+ӹK LZ&=a''Ƭ]s;MqwlH nĨ@qB0"ʌ=ͪ$1D qƘ$6]/plW* mNYfʮ^S+,`_Ow=B7Zk;ۻw-Jfzonmky}Iz{oELo:^Ш'`|_tmui6wO㷭~2&OΜ:u3oa'.eptRYZݨ"zcszg.N;ߘ??ult97?6={vnaΊKj̭VV:1QJ}Ǐ_x))y1L)ڦC?pMdB&N 0FFq,m 5΂E<\Jv#ݜGi"ㆈK[cOrFnjlw밶R,,H hh3}1i4!80F0L$4! f.vuш <|if(DC H)_#Is&&uXꔝCH##pbkI7׷ P`n~kM_ nP3 '41H "2 3#8  FAK Ѐ X@*bDCT@zp 89MNu=ԛ!xqZzd%m1(Ȣp `_ e/h ڏ JY7Bph 8LKTM1'H(Ak#ӛ9T ƫho}Ž?bЧ~'g3 >A>pWV37eJBJ &#R)([7 !e8Ewlw @P0҈?yO$x@-U\Y^4Z!tZa: ה ҅Ѩ$1421 b,K:3?t$${I-.@;ݥwA˜v)G9>=cf%o"EN:k.,<fs1sN)CzyإqH,94hv!4<֒3L7IXǃپn7u0B{h2iW"24OL &DP4j" cOe%F+Wue|sƑ-J[Jp:[7-jXFRA;w>WnKˋU2sg|!ζ6&ϓLڨsF=o-t꺎 e2Tqh[HF*u}7޾ڛoܼs  q$ǧd{;co_^Yv[{}}'&F1̸B-(ګUJ,MRw}umK"C%u!d) [c'LOZ 4\eW`HNDhBMKd!N+WDʭYO;ipa hW( 6==HFcZs}Mhvwv77GG{&:VY<>900duJ8cVވP8Pߐmd%Oe[vUG烙аkk7bQ++NBusKN0X?[Qa2ԓ#}#Qݸ:_o'ܻ/?i̋RJ{;z/5V~i᱉BpO`_XtjD-lll,\i~;Bq{r9qjddfbr#[L$a &GQ$̑M[}ݏGZ:aG9v̏ל"jȤ!e]gL˺v~X(Nx@WP&k 2>xBGu'A5\`2z=tHP4, 1&LC 3v0}*#h<@Wq U)㰐 MA7fL1QQ8BEHȥs[s"Zz?lNL?ENr>M qFDS`@G%Q.gIB21jRI=BdaAKClN.qH&Qa}M h}TTC `,Mҩ|-c2 >XwOuJGu8:ڵZfJpB`#Ϩ 1#T #;! ̢Ch!48Z+HNvfSYw%mp,dotҏq_>DhD"#'%Q4Dzh=iGt5 ;qˌ4Av33$tsB8} #q҆F8r([HMy.4Pl0I"Q0Ir}gcQkVKًgzz˅,F]*>o5rX!A_%Sϟ=V#_,3:i Jܨ};7a`VdР (e88169; eKhշ|7)Wz0O^yo89ys垁Dpymg{ueVGO=g+~RcfG{#r8f{ۻՕuNkBY%ILjrdXOO .턟oߴ ('L$0JLj;)gL :citI:9(g9ם cGWKKWmGVF de‚ϋncߴJrۻ`*HVeb/mvfPlTfooO__mO rส&t_-yWJq=h۩PSOiՂ;}/(/^dܸyoM]Ob9-u݁ _W^}k7ޑ^k On ýÓ##Ssbχe­5{.rA z}I}3VК@:HQ'&(rmO܇t<u>\瀿3UfyRݘMy<}huNwY? u :QeN6m#æeЭ3y}64F́vlQƴr@y b IXm䚡Rq-uMk MADLA0>y0Bh9V!kW7%{Jw<Npᒨ jagiD02H@.'lGBZ}e^ԊHZ遁r9HAe y5իX[dm}'='|ENӄþ`!L~ IˊD /,@9_0 Vߺuk}oaDԬV.πFNRI;oi;[;r>gΟtogZg%R@B+w3 OC2![>P@S À(}E0t"a\dy3Fk 8c8N9Q1p{˾a_9V_nMjV- b{Aș'-땮c{~7nYY^Mw=ˇv[_y7=#ΰwK dˮ9I ˖lidk~xLc-ٖ,KZju1փbːpT2n?3aō 8>kcCNk_JxOe"oᣇNM7VMG!*]2+Yo-E0DĦق1ry!J2 l {%n!8G;F+m"%ʋ`/`8lӕhH'!yYԚv@u[!z k.H[6) fZCWl"$Bkmtx Ԫ<9jG lw[Ж߷=o;ox~yE]{ҷ8E5&CC*BG1T%T"r3jPadĊcXP0QÝD&qzY0yQ?B*y+SKV^մH)@ՠREDv0u<94 *0)ļh VHNVz[&h$?鍎BJoP+VlL 8|}?ٚ𜧲y!2!AFo"B5D"9[Pk 06 %y5=,$-޸q ͕:G9MD5) kRi.*Y~=>LJ+ 'n;I^- PRnSn5(!$ ҦB|#$$.GI3$E+ y乁C*DPA ~q>WffQrV\pjF2DXXĕH`=S(`k5b wnՄ[4aB4m%]?d0d!b:Q I܍aĎ ;gcuRAV!{o<}ⵍ EQ&Q|~ཻjGt&tͦB('"EFB 9%V1L#RҌX^bhjwR9 nIT33Qp *Kg2 ̹{6]VjXhLihRq7b6v3Z:ļxsUXeI4f'eI P=;`K%l 7,"TV̐io`'G(R51g0>ѢK$HӘ9Az8,Q43^^BJP A`SG3BE FuNrnV-op{ a,PmREgtYIf!g\a PaN`>s FH8YatDNe0'[!3 XBUP<\_4 rz$MIk Uk$i^Z$Rañ46$%k @;aRFf@Ajm6J A^?3o@?>}KOR:Uu ɦeE6+TÃHE*`6 1_P!vY %3ƈbiFCjπ)10*DN@nmòBH A! W7u"cB?9{[+[З^3"*AՃ[pz5lZ/gvYDn X8Oʕv [&!߷g~os\Ijo-q[m6,Fyba0^(o2nh[HҀMXQ$HU f= u}C6I<9y{f\_]HW~ ΪpFC)U/iIZe=+kl]Gιka}LkUO+6&$IPJiDb\OP3sAmr/PS6ГPIlC =^n:ۘww?;H}ĕ.nҍ/}3/3|rt05-$I&ssq]Gfbb&K?߸)ꕺaˁnצؑ:ppl}ҩ𐝛"(pAGD:DJX$1BL1y@$~.JRdm^!"P5UT '&g<KW/hwL/\veOG5&3N z\Z^E7x餽1Fm[?5S'\j"tG !!$% 5TuHJF( J`MSv "h-f*ֶ,,yA` aja!m$iM`@ $X7@v(h̙7Y+)X D{\HHc,t*Wt&`7W2IeR)ݿ؄7;WdBsqe 3g@Ƒj%;Ee J&q*c0g*T*{cs;3'>3[D&8no.-e+7m?Pw/ݻmuE47VbMSkT|kV Ce9D)$Cu JQjy*_}n豙ƫ/zk_J: NinVZb^^Zʗ^׾6ۭ0ԫKO>]<^x羑%wwLN$^1#xA5囈6WV:aXgv" P^ٛIX\ٽ`6 [*efq)'8JuJg@mtm۝ ]WFŁPEnkP%hauEAYMzo#QÆ[?\{h\~[˶}( u!h/Dls-v>JLΜ ,Q5@C+1鴤vl=Y)M-ifԵdKW6B7Ωel +< $}fVud-(B(lRֹwOpS_~O8!~_|{> cAuwGx#", ;wX;k,q '6,8/Hj)ĺ#:m|UY}/xOٝHH"Ew^i,)\<2ĄA"h<Fаd8OP , :2@Nd҃60Xy7kV!y (+p?Վf#,vW)~E<$4+m~<*,רձX6if2#g9ZӺ!&qݪ9N<™ك1M*0B? {3SI'*U tP*aA#0g"GZk9u5QTd|k`Zk".Vگ xګe=:rױJZc,ٹ|k^vcژڛ_mwc`=}Q4kF}ڍ̉eX$ܕ).,72DvV016Jk1).Z 1SЏH/A&rxH,H˩‚WMؿ]Ȼ;#N]Z՛Q1=^fn٩}vӧ-9wB528X4+h]$ Z3SVgOg^~替3u:ihܝ| n>ڧ>=$Y73^yT ~'㻿}#ukW:7{wݽ>99{Wj'VS8H,<4Q-=NUIԺl" X,_T'D?)u3X r`H#IU?2bƑӀȗp3^GzQP)@_TlѡV]آBhX &51'MXF4Q'eys(ej`eDTdN'Ȗr^. ZKyFږ᮵Dq)x!ȸl&% ]/v0?P")zL\.mO| 4v_kT- )$'xce"XwF_- t -١a_Սxi5 DCC&?jj|q?yԩEcNy[ٱ+{k?{*!DjMwG8xqpޓi)sĻ|=`lm_ !" Rz)'џ]A2"N_yǪoPOVwh-bzZmhRgCMkh@s`BTܟŤfFp(61Jp_7| +Rѝ/B,iWķLк4cdMKn=H.mw t  dZ٤[VWZ%a5a^7z#c,LLf)ɉX#6J}N63+fwDqRۻsώٰ(XuO ۙc?|hvbX [ { yK#:P0\t SYi떯K;R/٨OTDPS:fFΦq w;FR-WDnJc@z}}#-aE{y#R̡m{3 HtTz9)'8ptl㜿 ba!̻YĚ/Og7ӣImHQEaUea~O#؇>mscSc^Mxcvl,iEY*O7&J뵍7Q@SsSs 9t4YQC6eSN+5O`9i7m ěd׮=KOyՠ2։!jm^{ T$V;^~/(R w뻿>k̵6Ll*NL'^{ܯ|햒ΌIJkw ,NXl ꧲%Y6@V4D"X8=؅>JJ2%,"L Lֈ[]9rƨ4r+@>"h-10i'$ f\oie9 lo |s0Sp-Y󏉁N7Ɯ b]DEXT=0TVKPfөY iS-=Of4 )@3Ncri1|D!RNI܂wu'eO陻)$叼[{O B܊'>럩JesGLR8ryH"ݫoDe_8'KJ ݡN#5`+EMݴֈa6\RՓ* Z|Mo7oR+\_D.\Jy((V 5E`Iq[kҭ-x1qKq5DC}/dW-yg?K6#q%O>@d^ᨘ)>-88uЌ'Bno0[6A,c?iDk`x##6dnye*N gHnx|*rF>!zdd*|N3R"Y#ZzdLOس'UA1>6YeX\DVaALMdt*ڢa{rR;f,R6S v"b"캸"’!|#D C@kArUi:Dׯ/]\ cIW8VљNxQGdN=gU>k']k׮.Lk \Ŧlx~;t_ Ҥ= B bᢀG=3 #B¶ \eH93 _bY@s+s]<3+gO^Y0K dY넓/m;'ۻNsބ4&L=EM?Tn(IE**(Eq5#X&f37xa7_^{vL2ik-W†.utWñ= ʢV<XLژ޷vku%#W‰J &0j7Vy в"z0/`,{(gW+""! 4G.cn1-fPm+B@C"Qu 1mHd'3c*ε\X <7茉Rf ϤV~ag$52 H)B*^D[Mk;$U!`Āȱ zTЂG(qBl02BJRP 400H!I)cS+R#A6@9+)CJId~엾h6jV~%*tm%mm%+xWn^wo{b'&knZ銵tƱ_Xyq<ӷa QRV{"H 5I-XCik%[6^@Oi[y#~\mƈ[\+v`F, 0u]C2XƎЍ0c QAwMDYCgþ|IR{w؎8JDȚܩG? 0-~Wq p{Ν# SDCz' gZ1X +~{ g>)0bVbLj}/=sڃ=O NH3<Ċ4f j8c*S0VkS$)(ҵ2ިEQbLL>|رcY1I|A.c\:E}"ҠI>iEdľWiْ0 N]0#(67V}ť4R*M&cDWԬm$qj3nk>Gw;l%3+D$Կ$%T\X-@}=(AwhlO = XF"s85")5ll w{v8IXv76n^ cEfp>·ߨ!ʎLH1Mw@QfsB6IB_c0 Wnt7K•0h;W__]Z=.65Cdy6W BhGFj\!3ڒJ+eY! wPh;#f; *:l֖w Nr:/$f@[k8?qN$ty^E30ƌ̛(n]G`ݑzQ3XdM24jB PnlFL~:-0Jόj*aTMkE(mWZBZ0|sAVvLԚQđA{Z~gVjC_{}/]rD/^?V;uΖ5ǎOϚM<_I?Mw-:trK dГ }7Xl߄mmܜF1m) 'Q,tB{ x/g?l/gtFLQ3k M =ont*XF^^i]vʃbé8#?Y`}/DDpn)e|^;PURWpZ~b6w;ba gj7Mn7|zjG6w̌j-pudd#vn^w߁kkO:TToxͭwpVԮVZtRSu/+W.W bn `angVy^7DHаE&Fw DC\-]T.ѝKO j1/{sXOLS)i!$ "Ha|X k:wE(E GlrѷF& x)R,vRʭ`cMZ?r– bLP- D)G01nA!P:&h*O[+Jb!+ O$*@TK 4A  I859C}HZK ^NOΗ.e" Ÿ|x?&GMR]a{rTw_K.%l|>o*fqAR16P(3GW1_ Rld6`y qOTD>8u>})G؊{p<ΣNW]lIf%F| Mv^y^u׌~a) U(D~1"i] {၊ =1l [ް"tE2dLUV\MrO~bw=D-~ FSRDDf S $mz \-Hhy~F3u8N%j6бqWĩr#%+׷6[''3F΅]NE,ܱ[ڱ=n_v{޼~f3jݱUWyӕ$˗[VwږI Dž۷^A812.AwQrєEq?EBr"@$tJlBUOP$gvWFksRK䅫7663L!6(ݹz7*5YZ=j4&ƦOַVc]_it@= PZ7jG`O}]t=^{y*<7\@5w}]*ZN7xPy^HWxQy33SZZK(Thg(C.u8hʌ2g3,ͩm@d@uu1HT(z`u1*zG 9Num)Zc&a_#Λ6)E"enJXzق;`hw`%Sz9J]\] eٞ Bdcv1ƴ(+)@@H" 0ZTU R6vg+I;D4!496*U^H &Z TIXVHq U,c^eZRILC>ni `O7=(JI!lү|żz 2' xy/}GսJ&)Xu" vYl`F%#'.y~znWxI*-J**o @)/`TD ;w|kwR Rh¡/eE3pGӓx7QFc}e4QX<WgdP8ڶH5Ƴ;_8:>*GºzdNQvգ{O.zJ}{m _$ itR-}cSVےS,C([J2ʵ :ĜX~k!u4Mᦼ7H]Djb!ylðp$(b~@eZy9S-qw|p l kF@3qC|`}Ozl~~aq_W`%as,QfwHObO_FaVq'z Qۧšv=,?2=z#P87JyH K:ڲֺ؈m R ˳ش] Y`2n 荭ͥKWؘX{1c(ٟ$ݤK|Ջ#[ z@я-F(roSD,zq9J$f;[grr^yO8q^~'}ߞybk@h mdE'>?<1ٻ(ucr56ֳTe VHjkE)At=&du2r|e@Af1bHYA(ވR~ʩhc^KQ<\^ Gz. ѤUZǦalz]Oga;Ȭ 'NL]kn5Z͵uM?NLV omfWZJ5AmC{փtXtciCەZ=5ЉتcG='Ξ9}+_>v=C#iflS@P65Zk־teJtC>¾s ;7CļSr2IUy؞H3R/Hit=)lE۵jˣ4J$I !N l3Ps[Sø. 0gw8Ӝ;@g9[\/gRP@S0*Ĉ<N.zҏq;A"4L$q)lӉfsEv͸ϵu)leKV7ZfM[8"(Q`` TjB\  Э T8zTXT`mkӘH4k4b"~g-.w @ty1nhe/؍EWԕ|;O:qֿ_Glw y0ix>"hb-+(GD5͋L$b@91(ztkRDPg hDXp9O$ 6Bg`. f1Ŵ۵+j|>}es_1e%fNA~;²TְmӮ#3w=>ݨSBǞzAC]%] 6!G;(]0D0]s:k ǧ~_|aV q { n @ܱw>Zo?G<Q*eA~P~(! hM9XGI_ۋ ,a}Zxon;NN./^p܇d$N}Dp)pyLL.]VgPfZb-|>gqbZSP@w;/]΄-VW̖ZpDIpSE:*ߝMSr`w;}j([8(痙2vݯ}|._p0S9cV <4)W0S>'nU\S.'͌l @;&駴u.Xloo̯|K_:wR'I|?'~{՚ҳo:Q*3юL21Uk,znrIbFyq.GiM8˯gSeْlCb,Ԁ"m!a5Й3穉 OiBB!Mv:sR V[ i/ZkˍC!gP/߱  HU%@&Ģ!"`srWT6V;.;jK'_ޱia2V u1cb` )eNs {f&gV7V*} ʦI-bMe֣yCݳtԙ3O?ҫ/\:~G~}?80+ >ū;fM|ŕ0xzzv[J$vs 2ˈhHa3HP(-0I:e66Qw}wt.-1IRV0/:Q R䑉f*Dppp[(}`dPd"GZI6 O鑭^[[h.bOeBw{/ВɛKEi?HBYhBB*n= SNU[,QB= { ;sPR 4wB)ܫ}jG6/b#jJrkBIh!(7j_rc+zԾʇ1t~"ܳkA+g^A4l-pǯn3q ~ _z^үީw`lf@K-kP}aAF bK'@ `l"4R#?+@"MfLIDn>"ZH BeuWl'6LVzO0e=։{o Ed@J-)$1&1$[L c_lYX b$UcƖ(@n9 IO+U O7R`7w܄Znw͞{o|MT,eY<GūoOyD`_׊ %yuU#N\ y 'Fnu= 9J[nW,"1t{  @~bv۟s iGqFON*ףᓶB1:^! "_"^yUnI og4OuYC0t]tX^5 fjF ּ,u=6v+5C @O7Ji+ 0 -i!WΜ:$pw{vKH!*ԫ+'xŌujlTvؤ[ >ǒMz 옽tFZIQ&eE hM,3.VjDuU {T pԎj?92?g Kކv\{(9oo ]B:wc;wm%]\NM+n^O7N vozf._t}O^=~-`[W.y+f*vLܼ~96+{Zj&mL:qsTՌzRh0+(O#xdQFYf]*B8G~4V)@U;!yJؠ!TR6l"xڌAG-&@ >,p)" EK 410<,2"Ra!JVqjB$&ץWLZelGʱmu:8R!# @C4 p.W]&.701얟v;nj!UڅKVk 'fVǟwVà kM_V6"oN޷bW~#orP ?|,NQ tAYCEb!_Q~[^e&髆!h8aD;]۴ؾuݏڍՈ :Ux/BAf<&I2GDZݮkZ 03p֓ԓ'k %D XaF g}V943\?`+Ξ:tVs[ c!Qk]zחo\_YZ|\}]TبxW Cq<@~nL혋u̥60/,zַZs. ڊe'偅c)i.x"D[W)L@`b Y9,*:œJNѴk-ɂ@yX F%XqZјpzjZl,nqҦB+&55&QD{"Q0#*A1[ +v'1)$1[;;ר/\^YY]W؎ٱsfv~llڽz .eW^y _9FfްSą]뵉..gtl֭*kkumȝ!4(e] R 0(JzGla;'B%,nע<omw%AoJ904Auuz"ePr$?Z 4E 9D"$$mTȱ"ͱMO`$אJYeZSSRx"9L!@&BKeL k9niG1Sѱn*֊ ! D!'BK0#5XfP~u,Dʃ!l3ɢԦ+}5~zeVEhZjsk=_ ؜M s: D#f+Ͽ٩׉͖jb'Ht>RKv??Oӧ/y Nds3tC)~GLmS+RSXR.L!g7#L ,ZKI1P"BC'-*iUpNAd#(=XP$N*Y$!Jun%VaQ=W$½fX03y4}LӖuK-kn-N*/~6S:זWϝX2M0V #쭯hHߖLEb8c7xH ,{ _6CW~qjǎ XC*#Ҷat{Px= m3BYb[?.LR7;02>$.f qT~ɢT^o{6@OApK[^Yr+bIAy^QqwiwڨgqI[$'H*幜"ټuXc,Bd'LCO*PT!˧DٳgnA0cZk]VG51TWo~՛KSY^TkkK[fcؘTuH+7oFPY^XmP5Td&Aak|Wfgv|}8ie,+b- z^004pJ/ )JZ%E1R!bl .cmJ?WB:(6c ?|];#Q Mnfs$L"HwSjWڛQ; Zmjlfzzn6AS?DQv,9+/=cm;j_ +W~=7Wݸsϑ#Go'c>6~Dʍ.l]jP߻g{ˠpv~6ZzE}g|(5\dLDńz|=>΂T].=,P5Q, ^r+*w12}֔@6e1ԎF 6Kg3(\@F 'qthQF.("ksS#a3ޣ$3ErIY%vB̬<@鯀D.áY@)a6~ mzn'j[BUU}w7]]@A'ъڸY: F|XM~ڳ܍f;=._s7?̼t],zqvnq`K?T}7j~ƥheD|`{{72t ;,u`-tHKi#f7^]؈Y qO5A3!F&JG@#zس 0F kQA@{ E@+:}IS !$\$$}ah'@ $hH%U溹BҊ<}^Zpi%?RxݍnKA~v5v;=K77 ?Fk@<"](˽Hߧg;ֆ4g_x'G䑦V4i!<ӳ FV#SFm>K=L ul{I]e4-taHcl>w*6R0ZAd c8k'd8-k< `恗 cx5[Ԝ=~WDA.D#WwhL'S 9 -2ţ^9u thI/"+:4j1!St-a_9@w\bUȑs̄]6;b:_aR>An"4\RZ)>ɦgqݕ{6wJ|24V ju}"ڲxZe F֧s 즀!"} lbA2A!UQ`<QQ^^ $Z*m`HbvI ̈="&PRK ;{*\="tڳ|mYGp1ג6S1ɝP?{$wEɡ)LͮYZYsO  Ou=^cJ|#><4V# 0@ Naf7;=)|0R*lg&~6 !Pso2Q$P$-,FB|!tzgm>f_v=\3,[A: +,wpUkn_#S"'ìk&TM0@m56I(n3HjǍ$KWǷaβ7Wƈa! I|SJa!6Evv֙jg+c*, )ڍ'_>f x3\|R״[sݩ{ msj&S]]]ߘѫV@Ig*Ϝ'*=_k̤iI9DSy9hfB$g0W\Sϫ@4a6iM*Dl-eQ" {H@AdB.} w﮽fldZ7Ϗë_qj3hǦ<M|WB3y>rur+=v{>t\AՌA~?{/>Wx酛7_q%;vvfKq@ 7;BE1]=wnqeyu}رv"9h6ZY [ku]M | |p ۑZFEg H4H͚9SGZF2ET*%D(B" @ÒXZkmK;o[!3G3j"η,KqjcJ}i`9Db $,Gqe DqHLDR4DN;U1̚f!`٥3j,!xrbd/ܿ{}j&y(P@68(]{۽;{~^>yjuuquI7kfkcV 8MR3/էoؚfXlL75c녺9\Qm˶84}/R GaMkl{7y<\!"c}OcA;RE`ي\l0BF&1)>wi[+F`r" 0Z8v7ȯ(cRk] @-2"V #ib+@t-3jŁ-FKH0Aeqԍ;Sڎ_?ƆKGC#8kM 4܌$ZeO82"'@rdm!!<_:zyZMC A쑐XJ$]`+ۖ! css'WDӿJv`Dm{-9i`" *P36-˓ $VM(QJ#'MLE xb-"$b QYPC$bmfl ܑazF"?~WkQ@JO)nK@>ޭT.]MW?zyݼqB.>Wc{'~cߜ=u <#|'H Ybn^z\{k.wW>ϯTJȣަ Do9ZmUcn^ߺp^yy$[. -s#Tbq]y/v7XiG:Gq%ZSZ&#yBgBW& )2b4vںe'Wq;t}< 7t^5FD M$y"QuwkXl4U^JkSp=weξ'ӈz!nWKziV@&sՐe/_j81\lTOIlaZ Bu,sczkN]{ycGgq6Q +vDI)pj M=z=GFniB8X7lV.Q.JwCW@H|<&`F"8H^uS]]&'@Z^&k7nf%~\=Q}C^ٵg7NK.ա5*l؎RBB&pֵ+/]<wG;=|YsξKofyjDIB=/I[כVS4:ύZCb<$;p%m,7p"M}++‘!+v~䕇Ë#&PI)_ @$F;paP6cHY}ܔܶ">\*x N#"lP&A`EdT#"Ns'P%vL`q[ XBRE@@b5Ak!ҠDy]l0V%qO+'u3*NE,i_:YD7:RV)>k,.2`W_smn,EњؖU+d}{7N^2y@H"*EiJRӢi[vmn$ F7;mq{IԊM}+d_n3ztɄϪW+ UDUrƊ!U 5lF&q<Z ܹ37n^ #809VW,ղ6sJ&mvQ#Idm QA%ĩF1:Mxӊ=DF6,}?M A5Ͽ SxzL`cY4"@i@%@ $k鹟*q&\vǹd!#E&;;qp%DBa[fi%Nc1K2:rt>}gJ'xyiڵ"gV6,Ya.\Xj8wm=#{[3'|;qp~8(m=H41/^מzՓ7n,rjw}x}ƍk/>엿/fHJczn-Qn/omv&g$ʹljL'@p[v'seHn-7!R6`0E-2H z"X-Z ܝaQDX{.QM 0@G x@qyX@`7Kf5=ҭRt48*}CΟBrb%Yt;3C o,sXCjH5K7Sq Vu'AK_Ͻ~0)hJeVKP9}ߵ7wr]^/%?f2ao^nm^=q} s+b3\b[kQ5Mk5b1bW0M`v.eKo\5IO:GjZF!  X[:Z4ubPʑ3 H2 ;*?mҼv=c3d|ǔD7j@@? Sig7Ν/~x~w>O/kExw ~!F1ugPrGM.f,_v]@)Ti.!x{m3 .W].ܖ$=ڧP+@>9HZjv@޾s2 @Jw8Wūtx}nR[Pl'?z䅄ekD+AinlGo5it@o\L9AjOҨH$iwƝD;lw%zh "FVkcyG#÷[Ө!35!)Qi_|_ W:-sޣ;&Ksk7ojٽ@kzvk͓{o_IY@H2jvX -Q}fzrs#\kLU'Iق ab:uLۦOK/<Gٳw>*44yEB HiRөz>Bi6o%= Qֺܵ/O;br1b!Gz./E 6A71=$FH^ ܃M}[+f;FĖ+_>y;KcʗNpJmKSqwv?}r菛Vf.,|C_Wō}hb@Fɲݤ[\o\\KR>v^TCwx ]r_ B?4FF%aooضf"S\)?,FAQ5ّj1'|v:(Vhjb9z'xU|fH5ˉyw$$bef%;6nM1da"a9_/:!EQF֊Hm6Xe@T~lzu9Sΐgt(Xbl)ԴҴ &3'_u ?ѺMW̢! jab<bD#R<1}SïDktg&޿ɇɹ]3cF{~ ÓwW$*8ɗǏ+kSZ}x`Fnv&W;A[_ZVoHIǦ%30 gmKK^)Dd $Pm*a!- Fݙ!#i+7Ÿ)MkyYw.rz;ƫwu`G 47<4U4k8RGk%=Gƍ~™WWn' u-t2Av+J" Y.C ˾5;fƃ͕uaaWh_ `E ERK6SQ@p(#e^h;M(Gҩ%fx@ NHooR̈1Q/(X.v-.Fh?R!W’RT$8ҖREq?[M(pZZf0顼@ (|OLh!*Bv]O8G{˷5ێX5YgKFΨaͷ ޭ5M Z81I'6RIvw|{梅>՚ئW\qxW~hؚ؎j7Wx'_Z9cz84WqjDk,jϒXmQjڌ#]JNfЀ "̬N+[+n;9{s`znnԎ0jwF3f6dA|iZ\5Ra$i]TJP{2RWۡ`!Hנ`~wMo.#ݻvmA,a8T+9\gHoiMvmd<:E2~+U8 | F6dYJOGqfFnZ[,)S\\pRvH4꿷2ږy䘯!MV-Nr FQ69;X7卦urN1s$Mq;lqt(@VScdxsBab6NVռr+G]ښ}=Vo*Vxk(Y$QWۿ閖o}Gd"rJFW_>ɥot܂Pވ2K_v>saErJ":E_,z$~U*>!QGWJhOEq ! PI&}WScUcN M/Df?=q&zMmԲbiH9'^!!YIWBE\[@|9k R5=G":3I" jKlm& <2qSTrkgNg~ɻsjM}ݨb;ViT}?fj4AL&F ' _t E򈪱5|Sųcvz$|j5uB%) >""ž*;6p`߼PvJ#Z`\~ϝm;\wR Ay o+TZSHbE(LD(UĐ9V.#KV"2Bd$fZ Pn-WxNT횸m[7֥$&HUwp7U5ZnW/$J$' \fܕi?{;YEūKϿg?S7O??Om6" [ F=x|BMQk[-x+m4뗒vt͛KzW^ė{ =W}mg_*lvNMܷwv ?Y:2@HES+qMF#8&MV [KPRQPH x?W?G/ĝp_磌w:K}[67hO#+V^o_&ړn|z>_N9뒽nċ } |H%8#+Edt i|kH@ìa7<[=Fk8 4Bg kU><Ŷf161**G.bNN^f**OfI p:BW|d\+pM@MjRN}Qun'F`E65Q̅{yqfzk++++g/?wK/ߢ'/ooܽ/|h\s7v^r٥&aVV.]pܩ~ SD@aUP^l86ְZIQ% kܵ.MLӎckI7 ꕐSr}+Ƌ?3og~O4;V5/l1)1|ڻer9WY6@k]?[+Dn*P]JAJ#Nئ H64& ^MikK[ѩ׳ 蚶T'ofsumfǎ}g>=<2ɉݻfoglJchLwwChsN-(זЯquylv[-{jlԮݡQ~5)}#3Ј(Bp>#goEyrbfQYq׍lN @pQ(Qxs+;V(e1JRS)^ojwZ*İE/de<T, B^dGp( \2M'VyY)K˒ tmvkaA`WO_Hr! ݠxDBV8+bu*zmRX KH4\Y%0 T|n1NvA^NoV^_&W_ZY%^HWa;btlh'<5kS;E"X`̚ c6&?>ݢݳQoma@ËtO :4 jx G< Ȥq ¨Ť&o;b} ouAHkUQb$} ?[Yugxo_I$;M<&ji^dܴXwx}gxfl/.Rm>ށ`B`$_!?N8=: y@j (E55L'T/t?3sڞy\4CX\ }+pXGi,iCf[|D+;(aF1GERxs X;E}5t&9=%3;,VwT~'h\% `)ߟ'f,"1٨OOf \Pwn~\6%=4>q Pp2U+7.\r2S٭0=;;DgΞqbwsy|J횟U8R T`Ӊ P1o^Y\Yjcam=/LY WwF/61KTr˺ׁUy}q/v}w=}wߓ۹s~zl"In5O)dd=٘\֕Qk VX#̜ -q|V1y\ !3"qWӞ'=$ҷ 2}iԛs;}T*Vohl.tmܫ[٪)v:ٹ-^Z~رCsc[ӳq+R\+|}޿gZxyw.]~&j=z`a2KZOӘŌMxW]L] \YnEG&beoETEHjvBY-X0oD"%ӂ8& 'u omb@HwEC"C0EeWj&b{ucxU&LJH-v;l 8a;DU6AdK 0N" k? KB_cxZxu_^ǟ~|#sd[+б1N؞lCcksף}]bсY5PY8J!sLǂ@|aSZ<И>UpӓSPRUW@K67YyEҗ乗yu n0|*Zn7`=;aWWEZݿwLlTLqYNEqlZ S` q,hQ/ B^>˽'A@)6VYʡ'",4ɃE6F`Н]566EB0b에2QN l m*+EE!bA 19,EpǞ绕G^!Y=d6wR;8u)l/(Ώ ŰL5nΐ0ifc @"RZNiDoEu'h'Ы$Ia$MU+"V8- k ~^om֧Z[j:3ݨV`j/mQB%!LsW.\rT*"3w.FT[wQxgC֤Xh/nZ~e"I8"Hfa [kM. (7ѥ W3}.Co{=ٱcƯTm>6I$ZJTf4,8]*sd^-?Eh0*J$,R61]Ɨ ͭU 6mD5n33j3SD'zw#G=2_?6Z#JbXQC0g,u6ׯ_cX~3qaDs$)ǁȅLXt{(ʭOv!825yiz @'@'!u2 CB%lQ@.IKU=4AV56c%1!xPYO8I RwZXS`hWai*yh$aJEIvօ h3v$}|UbEElY>͍_?{?|>vC=ɚ^X8Ix!??4>}bȯ?@uҕ3˧īxZ绫-@D"x@(0EѸɚ7 b75w^/CZ/za BOd@\˗%^^8"0_ة^?P绠fw5vs8_9y5E O8ފd]B-O"Z@@5x. YX6NIOD|ٝJL}y<ȵ F_IJ zMi1X.ʯr匔`C/bRH㥥Jb_  9bx<&,4݄$J#`8dӈ?E)o Ꭱ(,oYSH56 -#Iĺm'|06вRy#$?V {oSBIJ̓.m9q&$Qf+N:~ T*AoӁ:nv*Z݊(p}kzl>VUzϘnuXTf|f7JDE\ZKWU{ɱjA!F< Ty$Bpk'Oa$rl-`=#HZ)p=NkovW3K7_|ݏ>v=ǎ۷o)Mi{sICDV6"VkO:+i.FSc8jYRw-ϊH\Yx(g$bZkD0nz j_Ŷ5>/읯MVοvLA>y(72龥6w ZM\`5)NߑtW:{[xZMpG0=,+~gojm0i*yWe{7[_'2{U EA'Hg*KGQ"OqU'WIxY 1 xH)ISYTQq& 槧^vNMc܁X/$dN 6+ T$Dz/<-઒kZؕU<C('O \>B;pm+~X={C{ꕚ*a |ҕP]\Y[էƃzC/]?;KQ6II``9TqŬJ7"2=)s]xmSW_ &1!*IHS("О ]?mCJeîq,w< I¥եM2;Fb;mZwR;`%M};*y&®>⽋r!0HHLA\Y#޲"} R ;VLdŊ0(d% -LzŬ}}4'E"(=^ M͢XWo% Rx֩(b D̑>)e e+-l9|x:jwBSЭE\AJtj/ޑ]B"(O&vEt " )X"*rx&ۄ?Y#eNqr{퇗kY$Q}k ŅpO<577Vo4M)F$k^ @yIXRARi|דUm~ ro$Ɯ8EjL\̵XzB9 t5گ(ϷQ7s<9s͵S*3g&ڍ)|j۵# ;VO}_~^?}ԓ?~ڳp}G,l+75D]JS_P}pǡs/^|@shv&̍t~Qyo,lkI (eF @N JKn@Xx][dAGG:v Ⱦ6# `er*Fk=Geyr̦.cPX@bǞ2('"Poyzsk4:a`3@6Y  T3tw$%poV$NSmfe)©zcVy$ͨsnrE"`aUShb _c#,[@}BXБ}̡DVTk[]#B u_ߴQifN&y JQ`syH; W_8f!-D8@44M خtge7#ӕ LtT@']^ZVFY asP6p43)@oWwZؙ*AbH8]cEpB1jmj"7s7+®k+6^Nһ<88A#`ֵf́@'(IBRdD}L뚆",r_떧2AbNtx|\#֪-Q;ҍkIL mn]ޝ<_?rlܞ93YM*UvUijPoD`Z{^7N 0O@+Vf$Rʝ؊K}=c|;wONP5%6u:P Jq%1[fA$w{IdDEIr#FzaacIsV6:J(_ɤVu+W]]B8SgsH =Fc|G6 4sY;wt]፫ז/~=tG!*tB3`1Be~ګ/^[4{New;55wprQ ;WU> J-[Ŕ٤ h,-v'n4 ?)J~UX!4Œ.kIȮ=F,0B."oJY[wh~]@h Rֺ>uZ|G-;myyy{W .b0tr`~ۗYiMWnk}uuks-()<3fk:r =:Ș F$>ȀXk/!}З:^GĤ vZi G1{ S`e0eO ȩ&a+A&A%XQ V0X@9H`-€B$l"`>oWpMћ,/\n"KEmqje}E (  1?g;PYo7=8wi,+qלxch߼`[BdwΛ i264 ͳB! ʈ邤e~g6LJ`N.n&ˉnba0Rg OQ"$,e_p݈NsTs/\! Ur4V(  Ly9hח9cu~2%@SSiTT !FeN/`4-]@41Dg"q[$l@eYp1DJr;e3-ާ`őZ|QIhπ!V@)o$oS|3d^k~Іm?$TXb"Jy{.JD<ߩඌ=ZU\e @~ iQ3Ƙ0 }O{667QyzXn657j ڙx{ݻv ׯ>SZ;t=kT|kmnqā{jc$nT2d -,sV AFAI&g=> mTNW'm/Ӵ&V4:qmFׯɇz=g}cSuOK7j-rA7u<] XEQXca!k(%t "-kn-V jݦť+VZNTcaNڻsIkq[MM,`ٱjp]׮_8{n7n;}G>]Gݹ4zZtWWOy󕗞rձFjՕJqI7bWc,Cj9;FT &5%x\*%rÃm ;cJ[کs+ tPpȖetyOeGPlfF$p{wEnjPlʥv[{t!J+|y-\X.VQ{^`[fm0X [tȷ1#*dĘ0R$i]@ovN+!knjP4$M]CF@۶=^TJ Pg$?L+ AG@"C IbH"@Op.)\U5΋" wA8ɣS{^S}XX]=lrqґ7ǘR @fFG= R?O*|i6宑λh#6%HmP*WZҎY4WV-G\n0`n *@(h8*͗K? >ES51瓄acV+ ǨrS_ЭBQ߁"bp;u'RoZҳ )(h^fXg*|]WsQZEKáwlXrY(r*W%J(ܠs8hdNA pT\X/ 5(8l9e1 ߍ^ wQX P4հv,Zl݌ya:>$KQ֙-Ym]S';zl= ;QH(&D*@ !ջpZrQl<Il$ +R!Vj[nl'6MMDTU/iv[ )'>Qᄍgϼ~K/xOD~U[k1n-Ȧ'Oi9k:yJeNT%&JZ+lmR-$idrTp x*叐Q{z [Z7qzsiSxf>o߾?^Ja)f΍+ϵ Byb*i(US>&Ǔ A2[ABNDf¥K+kVZ7kF1Tj7o\`(@)(0-0 QPF4AcL/ĩ@ZK8(ϥ[N'Sjm&Ijw@izJlRZzEx-Օ+W.hH8._*HXU_Gݎ J $id%B{՜V'l 4O^S>P/:%)C@dg%-f89x]y?믯:iEV}G?/ݸqƅKLƠb|<䔳ifK= 5(IB01-S6 iMDl94[xFD + d[S!iat` $kWO^F'Z BMH_[Z\]lM.YZ^}Fȓw=#wlnd_r򵗞\6p3wܵg߁cc`lcv|Б#浫7\μw1VΝ{{jr6 ,qc}kh:{fÆYQE:J<Ѷ)%G9s!0\{4&Ɠu_MG;~B}'yT*COm0H u]&IW4 b%_PIFqO5%},AԾR(j6q+2pf}h Ίw<ϥrr}J%}p͛8lF H(Z ē x,('1P`8eq/ +`".HW?Ὀb]C@&*b|3WE20ɰ)\͑fڕ.pEy\: 8"*aVКgVe9%Q 0PEࡵ=h@T@BAXwE@!T0ټt5v0iMY=:H@8T .O1#h@߰g MAH!+9U݉ML"BZ=[{}ō3WՆR~# +/kGԝJTUP$@j}۝ 8/1ox"JTEt"y6I߲vj8 n42\> :xKw.8]2l푪VDts|b#c /{چyI)㨸 +SՀئF{kAJd1N9IX :5 f)Ed$ Vłn}>\(8ȑ#<;Cm>o^r^`wݻԪ+7o^y٥գ;wI3JA"[!MS@#aJCiNutOrWd,E QK]vKvXJBol4:6~Zl?񻦦g-wI7>G^z饧g]:ZZZ߹^Mٽ_=Qj;IK3{lru߫B#P¬pԌIN!!+Hf~ B(ίZy D?D[6$awԫbNU bw=W{{<Ñ3d"Jdd]@F*ҏNl{uA#qf68ʠ9u4Zymp#CER,6Ci_$'u_v_ठ"BEwII Ӱ-E0Qqk4Yp/y X"ʹȞCHs=mv 7ÑqYҦA%N!LJv/p0r;mOp1zʈ3X P1@F˻ȷH%846LcԾ׃j)" IRfhJ~@DհR9AHDcS][hرvэ̹$t$MR:P2J%v11]LLTêR鬑4XHBE+ZS8A@ə~Lkm,g=4cO-˵ ɮ|K.^:E(|ͻ{ԮkK7^yJSR{w5=V `FvyHDPBQ+0 eנ11$PVPNt왳v6)B('jͬp;(FT2a'=~'>pO+S'.[>7>1=\k4T؞m8im ovM1c;{fhTbJӷ6RHj<$Uoo۶)v4qٖ,۟oxA ,ޓ\TlXEXמe&KjYB <+lҤg n@+b/" |/3!dQR7BD烠259svkk)2C+x4w{ON^n'}lXp A tXZm01TN![6V#:|Q50/%`(E&u zDwhG`|d)B"h!@5*ytt-JH@9^9:n 7M0BOTL+DRw{J1؀n}ݏaE4*Os BƉE!b|LHF""d$ԲL 0NC EI  " ȭ% | 5tE@P+dCe i*n4aP!P?wkMW㚽t778s?dcW X+w4f׽8G QX(!B]kU4[%\NF׊EZѕ'@~R>чG|ʢFha7D&RnExt3oPordނ* Y  7saÃWmWll gGo TSp)g%_CnC pY4RQNCA% AJ;tY2EDeII^2BNmwf6"zo!jeyIM 1_ynfZJ~G4upڌW`f#unQ(ԀVXĤV (ԮBO |{;Kč1ndACHz_fVNxҫ'޼=cG'f;NR\^Ycʘ8YP)0>*CB* _8s+76V6ơޤ沀uWa-`čB`NO bwQ%Z(ZE(D,EqZj I*bN}Nu2`y% P x,$âiB.CEu};ARAWԧU|xF#؂ H| @P@EQ XAA& 9QGGh PHC ,( ," lF0uk0-B6Q=5!(jPCfxdRcITCWc-@A>z(RM%wrgff7JōMnlnC cC45 (ʟphD,QCf XPdD-ϣI.`߽#Pdm ~VnOtw $*g⥰fkny,門-3(@䄊(q|,w sR葉Q,,&‚oS,;Z_E9^uN+b~ XJ50"Ԫ8U$z [XIHjaK.`/@u?UwR*X,,Zfz5֦eA8I4[݈nwv'fA F$6VHX;kWomTnaV׮]I(ZQmmn,-ONٵ;K]<iz|#S (VATUp}ګO<\˸>to|g:ukWvBz5U'[+lNkֵT)oѣ{v(jmjWa AH( &ro.Fx sa}>r 0#w3A`n\@za{&(}}xH2E>{ (Y0r?h{jǝ[wQiHȪu70Ph]mE5nFI5 !0BIv8ICT [XW!dUsbH*_HagΖ\PҬUZM @)2>vas+ƒ>N,fG7;Lq: M^] #xDt*IeDP,Vk@1k :J33V, eB(Xqo(E ShAȖm~ `"`ѕ[gB`O~C R+SC0=F NMOH4a5vqmZpɦ(W"IrS$K7#`AȖ$D9%rYR)ogʈ]XSS6l$F$z5ψ͏D@!*&j dt ;7?[V殾lSj1|׾_į+]wu:B'U!/ 39ˠz Bilfks⹬DYDQGmx_d}:rrJR#*mSQHԭx>v %1y"o0\h/e.XΔ'Mc;M HUFU7$4M[VNj9XVq;VjMTؘ5oRcȤ #z,|/>aV9੩w}qsW^xŋ$ViHB(IMRm[6mեyW]8p`_@԰o\\mWf'wѨO@$f&eIֹ'[aP^7ʊe\\Reiz~/?{E`[zq1czZm_FbU}|b|xז۝V>1Ӥ $a =J\mhIe z~lWP9ג`Y{nGG;ݕ%)Ghij",v]FR ZMX8 4!$"*5>*-E=R!(Hүq 7rH9OqlTlRAX;=뿘\v!/_?AQψQ7!zAUoN5WO!a z{& r E2T ; S0S2A$Q#FG@ `njUk΃ rCԀW}`{4ϱc Ʀ=Y"ä4>0{Y( 0JR(Ei\Z8WW *nY:fP3 $ Cl!eA͍+'$70لFu(T kYh\5+鍎}ןqKϼz_x4MWo^]vyEeDDq7͕͵k./ 3_fQmez6O4ibrzpR<()%eǞ/'R*cʪp䢴$r߽,qߺc *܅*+幉Hg*Mm|<.6c8!*P㹝 UH;k1(OoWkiXkod c (4Nx))Σq#Ujf)})bMLn/b nGn^j1ÌJU뵩lʲȷJVmǧ&wc&y,T>ƜvL1iXՒ8#\~s#$tI;S/8|w;Zcȭ)JBwv_vzE}oлwUҔM`?}OoǣVo CS;xK웯qe)ƮR~`sp,y@bE l"+y  R~%766=.}~ont&f׋`zv/]hr9ZfP`sc̙ΞGjؘ;orz4 f}~ۿ{gZxbnI8>>o=yLU±!jwkU&Nl2m!72վSHޝVnedkP7T]3u327?<GEAls"ŻD(~..P^F,r?,q)9g%@L})Z Ypj8 @+xq(&kR+ J*Hݚ9/xa5eaր< ]JtZ3DM+;h5O8=}z "6md6qЕ g S7lA+YAL:@h+lI< f@"a a د >`@7(L$YrWRDz#$` U@lUM 0R ,CK*"bp R$@̸d A?0`Ģ@|P5 YKzLEhC˳$r$ >5p1p9(" 5BD1p/]?6cS=WozJI00'˅ fu'f$M%]yf %"k*ݬ/j=}SZ^^vZ10׮@洤v#{+7jOo➻G/aɜ^k*Rg,Y ^*V 5J- p{]d+,yqŗ$ᶈ~x-8JԵUHw5=,FC#".TBS?Pp3X *ݒbaI*܉Q,%*nW^lp c` %jAtLEE@(y!\I&y!ou1v Ubr25T3w. ;(WaGzElfu$4֢tK" tcI /`LaGzp[Em6}דY3ԼWNpzcvǻ}pιCgyO?ͧ i\;|;O:o;#O#vAΜTkEb#^0c@:$mH $JHDZc ʫPT7/N/.3¿'] qcfg&^x; o^[RLث4' XcqsƇ_~V~\""Erv7Q;2t!'\e iy쀡I[nORĶJq(EZ7Sg Rɻy·o)|xWP<TH >h|E0*FGTOh 0ۆ(Rb buMd%&G(vD:֊I4;@tJh?߷@&N75=%q~_yF=8Aa8܍7#=G<o|g8u_K/>{S֘So/'/xu4#{9z`LU6MI16ָ(5iE}j$$RԚ`9TbQQ0c](E[n%i $A8 @l$6 fRy6_Si T\1Vɞ_-~L.o:~~Oa#I$DU`)-A<E 8hg*NIh  ?z *B 4 p[&$d 9 "08)%3,ҶI|!;D4_eB8 }T5 C;6e_ZZߜx)AR% ',,HV4FDbH()"] 韱R<,3>䧿x ߿c_p,^3nx#zTOǟ_:r{ _;NHqv@ZZ3pXODLKr+ణ,.<6}CFOdu931Jh8e6%Dj2]h-#jBϕ7e mhې1rSmሸ͠JY{x rrPSoYR/vq{ @ "AՅL^,~r? DU~.AvijkXٵӉ5&"J:q.#9Pd s̓GOsﱃ{ƛ&gwߑ]sׯ_?Rf) +LΞg{/>|hiDm%Q~SIb8H=7DXct8['ҙMϳzH6]v3j5<1#w[ ;& oW?}G>rȁ|Я3匁4jPkrY2HYqT:ӜmLN(@%ve]JbG=A!"!O& D:/(H n[6 X 1" nsT01 aofvntq|B<R>whhޡYp@ۇ.w*) Ҙ[X~둸e"Kx Co&oC,K.dcDIj>(DFCªCrD(q\!kY$yZya"m/%qZ.Fkk &6V볡FQ\5s=BMl큿'ީK><#K |$|4=4SMXĸZ1P5D Xg- )B!$bOBP=!`#@i @ ĀM$j'Y-X@  jQomÀk1cmD!@z"H|}{ S߾>44WmkZ6PA"!?W١ `L %@R 5o?+'O@?4#G=:VC'vG֠|@ V!y@ %HDK F`X`i2c0ɖ6nFF6y_?yµvϞ;lӨm+ɘ$5Iߏַ{w|o5puxBnx(ў<okWI ()8 ܮ ** Fl//"U\SdaxeenE^69?1: y@1,·/*~)ls4p?X^DzDy>' K"'Q; c)8Pu¥ K7Z:MAUMLff~B33;@fEn޼zr]xb3j= >?o{۽gϞ_gNyZMZ{ח}{}G힞+jv:u5NV4)͟AqlCTӁ6W\:{Lwj x+.1lNZSժdM&‡+ ooۻ/>z> ΁Lw=ʒw>3E6s,la+r[Q#>Pޠdmvרoo~VF-Z;^ψNӴ;!WHeK}~Cں]*'A=ރ)<J*?4Eݞ8եTH;pѭ0r֨ yeUV %fX `OPJ,X̂Tu ĒdٲM*x2 1&+ I7+eX,K^rБ Ac{OLdlKϽ⮝{>CJVxmC ''벵S_.vO=~gඎnu%2v6S@eM2ROYD74[cYX{0ZQ3VSo__4?m FWƀnalm$FJ;u`-D~+# #wo-߇2 #Zjڮ0LfAOPȭO'mGIUJ)WD6`1LwB42~+>Ie4.O$&D]"gqxKMɀQe96)!T^/3ՉPg!0p&\icIӑkҗUiώӝ BFRV[c9&+jP]B6}mם HJaRLj-v)~ 1s6}/?]+0ɃI> eʰ r<?\ziy·1nם(#lI啵t)[+tCi|zK7C,nwͮVvwsmSY[MfA kcdg+Xwuϡ ϝ:JFhOk/~{yɣw=ؘS 7^{gY][|ӸƛkgM*ӳ +qkPol˒An}C(#(BQev~J> oPDÅڑkJGC{nii\n͑Yr 9!>! XŒߟ wyKy YE`{uvg|d0pƶarT-@usjR`E \8aa5A:xe"-zs k-c9o7R[+0b{rܪQ`\-X!50("\N>% 4Dvɍex'Ur@<YO.@U=+U?tT+SƧ~w^zyHw>]?s*Nuu·QΦ/7.^ȼEXCHN%=]?v'7ֲ&ܼt}z]{3FDPi+ _{z^C.^TVKcAX?{j_9y js}֕xRj;fV66;[Yƽ2;SVUurs,-_8ʍg_ɫo|}jo|҉4f&SZZ9tWn?xCPŠ<\)B_nA':F0KQs틔MVYM J\pJK[D㎼]Q"6q{0,?ۘ@$"$q/lG-r,yw(ZU?J hQ!0"NvV{>Ak{eN=o[&͎/t$2Y$Q l[qiHgӻx}AYq! IyPkUoa)0Yq$ڳ "[vSQ(CIC!BM#oo4-8i_/:{oEߴ9XRALژ4=4<ߧJxO?"Y"ΠSLS.M0AhBd۫g2G]Dy 8PSF~9ВHȽU̾ ~WL_㕯<mi3Rs"$#O㯼z$V)?x\={zCg0!kF_ozM?GOP:73lvE8:`.f@d2,u\H\O?odpˎ)Xp *] Zh3b~G޼ ^͑<7ݷF(d#nabAZ;p67T}1:ƶ# +zDWŀ[vJ[<_ D3Aۦ;-U,X%Bp|b\xC>sέV'7?}%Z?v}Ї3Oů?<?o;z8ڥ_U&<55W{~ǻu~:Y[Λ:F-PZ;tzaϞ}>=ҫoi:cz#nsuuycmʍA9t޻MMdi4*R+N>꩓o^\\KW3W.;J;=Gvܻo^*oڙKj8c&7ܱ0gf؎?҉7O-l\z&U (ٜ176^hLyk&5†BM (Hˢ ty<ay7pu7J0TB?9PY15-w b6Etk'v[DqΣ<ق)/TyA.j57eA7݌EQ@űmlKC-Jb(^Iij(ns14qqgэ$i2< 9Zl7c%z&,(gP)0@THx+Yj I=,hDMmvJ]ƶ G6fD@6]SAA z~}?ً|fW|!<@!@beϻy\A1%Z@M ϭi!7NL4Ekd,JC| blĀɢx P TRXE $xΚ]|==wOu Kh VP ?wmB89ܑN>02[Ѿ T|+)~+N՗NP:9W c' ѱzMu7kc-HTΟ;w#I;U;GP)@J< ʻWYOZͤiS4b(WK_.A" Q3yw-76IDBE}ݓ/ZS1=|{?=քgsK'Jfڌ̽̏`P Vd,8RPKYjz5CnϬ.KlN{#kGjGepa$7ȶ9A7øTd1YTQ7 G.&Uu3uY[L *%%˂z۲w0ƅSn^^?ph[bT CT-DiNg`$g(+*ř[^όµK>ͱiΝɓo|}vg|f9t]QSg <|c3/=믞y'X^ {G^xj@QǹӸnXGe~y}?\VG}xLٳ{/<3=G:oo%1PڵLm#M7Vkk|rKzsUt9Ο9vc؇Njw3K.dU/?i'sTuzۘɅiwk̥s˩^əGQmuZ\7Ĭ Uf]]P %&Pn6W}Zhn|WW9nœT)Պ?u }ϲ$vڻ7XeEA=4Gc(X@D78@{#Dp$ Z VgJ穏 ŧ1Ўw[x ~UXC Z٧23$1I]͛ފ(Q6q]fR=OGDRY NX'(X7kx+V(J)@VIœjS+J+--񍩩79kkK,H m >s}w~#9wM]-Hr,^6🯺a[!B7 ":V@*<* (Bc"Kh\=oVxiW H5WZP;X=+T!_I}p{pʫ)gBňaaLѣ<ɦ݊L+ɤM8ka^옫&NџFfzO|GX_W X@ ՑjWUjcफ़ gcRgW.rm)OgʚIbvһk|;'7ZɪkF-X1Ϝ\k٥kڻ]pv-A8vllmk|މ!7 f"&BPyHv{A3@u6|8RPB}]I)|@H92seyh@]3>n waGև9($0l+:;% Ķԗ`8s?Ȝf 9,bl6"2v?YAcq^KK>(̃;AM:bd<15۞=|o\9p`;jk+g.fhR=tWW^?Ʃ7}Cǂ*rKkW/S8\]W{+tO혝YXX?{Ɩ40 !xFm?k߯=v>{oq*vOyؑ3)Gkթ7 `{sx޻?OjFMz]ZWqeG9SȖ|ˉdBNc `"Idv{]FRAƦ$iY{b|Ȯh%Ay)1<@eSc; $.1~}℗c  Lj}3IuGӮSKybLZX3\m^g 膄m X];u5jwcIA?<|ARfr8tH )v+=q5ձW5E w͏#NܼkW<x/roϼ 0IM{_ⷿ]z&7%uF!#I"*'YM|f΁@"IA~N)R GG&?j WH}QswrX& 0e6j$z0c/v=.$]v  rę (w@,%}}Z)w{M#;Eo Dܶm>q]3ƺ{_dR觟4IL$Y* -! s`#=N/ml|_g?6 X2 _<wCMs^Eck?x$"no-^=̛jvؽ&?67 zz| \te}53gnNz}u@UPPX(Q&)O, ) d\7,J%HFhFۡ:c(=A-張V JhH!p1JYnSGQ`<_kcra\ES,mLo#b/:2REAPT1},╗d0"Bxy^Jut# |'UͧqƷec</F,( 6 I?3PE4I]cP .Y5oaybISIMdA? #_B؊V0 R8Ee+~׶Zl5{-Ŀ+ϝ>g{ƉrW<1A0< AKs'o#=f<sWbBjJN'"W`֤RJ Z@P8U_POan| .n@I xfݎw͇fP>r{(AD0*DYIPPYƓDb+,(Bu}bY~?-_-O!MgSr 6 D@:?oM|++Ŏt#Ic3ssLti9q_df]ڼޕcK`ek\~1H|dviԙ3\}, lF+DH&to޼c!+!@ؕ2N#: @n$a ;5gʆJ|?CNW-#"Z 1)ۍqZ+˻X(rCν{u {;;˟*'ۗavҕJcgg/-"y $el^R!Pil$`01Hre~L5;f^¹'@4kf 4z$[gOt 0n\m3q<]t굵 =6]_ؽTk/_v}}#|B϶m|%L,:5ݩZv8{;/\ܺ|}qԉt)f5S ;Qn' N7#aK,)LҎ@$Jb[.o _>xj:?GZ2S+f3% jVז'U,O_}ފ@mHX7rm^Waqr,.D\5}tt.|lf '047f| vC}z_B1 *oRgiԂ݌H ~N* C Hy)jh?[b Msj& A+acPiNuMc'&緞1EQk:j ?mp;JS{ÿGJ~ݝ*MVpלO_]P{7Dކ ݊gĴ jpᨇk j\ߵwA'd'~>v4Za53rXk!YZ\,1Pe)1pXmjHo9i 0t}*!,+@m*\z@̨wS3貋 cA^uc8Pygo.-\~_qfz߼x|U_iY6w:p2̚IR@7I763dT7lA&&v홟mUjLW G;klm-~ؘ$ĉƙ7S3 Xuj{ 2T#l>vaC6 bPkkWO/-%l榏>wj.]7tJ6M:&6W6ՙ]Ě马RVP؂IRM&T!5ԁ< mAkvhMjz&/Jy#̂[3GJ9vF肵XXY: I;i Sc@vkGy#|AAžuTiaՠ,l.y:t`1_rcS]*̴(4ֈ"i5"lAAaGGR%DF@jB-fLAJ$LNjAtwMl5uOMxH[N -tgVS/Ql cy_+Ϝ;{ZVc5q!zCO_| g'ۏa$ScppAP1Y4ŭ /Ŷ:B+pa(%BTH|]c2O}*gv[ ̸߹)ZkYi P mh맫?捶5Nw'Ntr }ȮO=ꅛph烬1]Z6+&im > OfWͦ3"snœ r†ߊ|y2$nֶlVz9?{)o o~J|K_<@{σ x~8p@[oLL\r+_מx6#u.E|[pd5Dn+BN'cHmoS,x'7KذqI13NYw`t`y+bD7s[k.b[ <Տa-njTۃB QV'EKn$ SY}lڡÇ="- n4ךp+T՚_'v~՗_z!ro|ܸi݈`bj{ylfמ4Mn.^>wasy̽lS`@41~%lL7wL;=\lmnuv/׀8AWB%"vj|gO_huR>yY9o.g,ѵXcӱa~l\x7^kw،#9Y&Q nF-0RP^@፠c݉8H9zrQkF+rhL.@)U4B.NYrH۷V#"=6̀6e3IZA& , fs<, Zh@&Hc< 2G%Nd#nmnimebiT4`~>JE+bs%e-H*S锺Vs_<ޭ 3xT4clBm0\2gtN%zxzW?~~j {Ҩ7L4 kV+2fsk }_@Eܼ]!(]H~q|#m B1&e ,"yA!4s-<߳-3޵ ._< Mt=`|6! 'kAIhC7n<‹O?bOLK˫?XwL;zӟkozPy(cĠ7c|grڵ+}NM67"!R{ U˚ 0hT<H(", G"1Xcd%h sE LΗ>Q2sOԌvS"\fZk˩sl|"EnV}Ne=`^gNIW?Wu3|\JFr~;]FΜvP[;Bb-ۑƎ 1H| 2k<@}bݿ?oE15/||ZYK<}X5M m6tӼ QAO^_kgz~lӭt8]>?/Sk:I7Hخ:_\N]^D%/hU}V+XA<S0,jV?^ЛnOg?ݽoo߈3\T1JAyw,G'ǟ fxEI!y333ꤗꪑ(-gprr|QpsiۣƏS 4ZAXd [Hp_o@U^jSc@)k_'ţ@ȶ--bt/fha {ş54PtXd7y Qf\3UnG t-jE}O))NPgB_reiӇv:Xto MlijP8'9+QP{Zz{֦F؁],ug׶6l5E&u&$==_Qy TJ$D"&ϯ÷y晛}{~}>opy\&'t-T@$yn?^Ow_kK5hLX G ,B&$%200-~O:1+|:p <K.Am #/J\X_}z'O;fpz޿w_g׾v' U$V_{o} 4v@#A]lUֻV/}e/yu?㓟Џw<ZI66\Z7;+ZWԈI[iM$MGz,_I]UkO7ew??瑏B_?O~Cab6C:DuL7IN_^{ͥ=kW~>S7zDz/$AG˶~R;~cٗqw@X-y[nyRZ'5CW_+T~xGb틟k݊2͖v\!? nɝy \L"a=XDh 8m+lyǖhqb.~@Jq &), Ÿ ے9u)ɂ0f( EgSyeF&u>)0yXkGBq'3 cYA,p~|b_Ob&6cgEVĝNgN@Z@|" J Q@!y ޽[<ި%itٕ%P({ra$j;sA8=#??}_g>ɛWh* @^J791Xe/}~?sϾko|__~7W 9V&'WQ~ 4:-진sV7QtzF{{Vګ}3j;#;I-eFEk+gnT&*MZݷ@PhRlmF-;PSg]z-fS33vtDi6SsY:O.=L%D,"2 =MP98⟶HKs[.,h}<&bB",kywzŠSaMPG]#*@=0:YI(S CWn Y^Ͼ]d/Nl'4U5,V`fSפ4%VV Z(*6" l34:ͨ緘}?v! 3 @D +pBĀ̯߸*HXsL6]O)Tt^l5U6ҕ+勤 ;_;/X @, :_",]}zz޼t^~w_u($\5-PܩWӋ띭@?{]o[; $*^H\az??ů/>_:꫗POTgl8502Iي@xkV"DIEcJ)@V sJS)Ec 4)EZ^D^]>5=yܹz_?EȝZX*kF S2ϯ(&Xé%s!EvL(  ѯ"ZkKewuw{ |wTC#GcIؠ:8pٞ=e 1@'G?e~K766H/ml\p~sWΝR],M'>/gD 0ZjJqb]qCy}Ⅷ/?sv}, ȊcPyyZ.h-i+`Ϟ&i{ZEs.'tEy޻惘^}bѣ\7+ZaGvwm+"N)!a,C=f۴ )AfAM݂eQ2RAh  *栴t"bPYڿwPhk*50t>MXϸ`c QAYdW<=4JJؤ,xb@ 'uk#um`rH2 v'e,;_KmFG*+Icc\U0BCArԏu@AqlL2x(u}smMP%6G?w.^bz3M2+kb 7]E0]P!$G+_63]Y7iw1Z6l:]t׿Mcm 嘝?^s&Beb@hiͿ|+/kW \kKD#8 vbPB+?Z{#&51z&.SECaڢV}}W w~տ\ ??ąKYN(McFgd("Z&ַBw{~꥗n..|ػx";5gDRd$${jyyZq"ZvfZv]tqg&{0hU P;dG׍&"gB"Ce#ϣJ;S)'.4E_B}Ƶ"Xĥ [ȑ[+|\>VqeZkk *T)#xZi1@>y@PwNqVyl_MEDXo.];uc񉻎۷{{n=Ԏ6WNVvs};ƀijZ#>97?;9}ilBu;k1HZiLJeV$8N\CGq(Ԙeh3M=w!TikɍģGߕW7H"/BW^\\tTfa)ds"[[.lQ땪)H2@pv,b{s>=RXNbۯP衐b#S"#X}3W֎ NdbGZ`.P,lU8|1j0wgy_ɯ6 v#HEQTx݁w[(I$Zk sBQzXwCXh-֫SϤgUmuk KZN*;6SUfg(JkkS:b{ر|{]k{\R;w^PXŨ!mGW/_{f7ԁ_a )[RQ`tg'əLovvᙧ_l޷裦_ׯȵzI|O{ʊ6|M6V CQkuDW/n5_{Yع^4[=s\p^}=zM={ٹ^7g(&M-ZHՕ8Ldж1VwL*n}NaXUhAz3c|Vt@4-74fjI T0)gOYy ̤(٫W(˯f_jw=iGJ9>a0]y\7[KxׇD},J@80|{pq}m7ܟ]?_{~V+mC!Jb;l?~Gv?yo01)lIXXI6.o(2}35wnܴinrˀ`|JoS{wNXkpGsLioo%嫛ʙ˧_hDoq 7#VZnGQY- EQ络i*='Ɖ *{vZ_wؼj1{..-ށԌ8tzZK6X,k`Нh`af;ِ=h`o  T[@B]j4lE$GR*1 y-EүfmӕC/ !0psk"vS_Q# &D(PcL6XH;ffȟEcjަ=v;6iwڈHKSrnV\*-A)SyXk]- C"r2wI=;E^yp}*M_i@ {>*mxZS9Q*G6l+^EٹZ2k۹kii_:,AR&ZS-1 V+jE H8ĂE"/(EE4?}|ck׮~sc?G?}VV7,C?!*/ *M@*ӍF[[?t|bvlшqūMOn7cb{w휞=ud~ ;ɛZ5)%rb6T\JyQlI3k ڽsǼ^M9sVHyƔ l=PFT<pwOuoE20@ueMk=C|'Ζݚ}Bݙt~^TA82+vKN'pĈJ|G4Ϧʡe9XcuJu:M xu$"BMh  "zI$12N(oS˨I ysyAW5 IJo&;[[t[A<9?,E Ȁ$<}ym )ͣ.-meS絧cP?sGp}G=fǎTHr iO?(d[bwO}+U?е/oT?'~|߾9/0X ;mB+oD.]V xU\+9ٛ7zaxO=O_]xK[ʲ"㭯jwtҹWmn7I:Q'j q0s 0 *(.gR^q|uщ]wݧCAA]kBk{WU#88 3w6<أO2 EFќe+l#݌ ʙMo Jyn~f>B7OD`kFQQ)*@,dq#X#zˌ@;VDn+V0o,,J4S"r| cyv/c]rX)YX@]޵]0 Tok"[$@؞y%a.nE k͓uP B#Fd/N)e~tZ{"_+ҾaF[ش1myxj~ǃ?t9k0?}cgNEPaXCݤaV֦4m'6~f >5cjr<~}miIMCקgrjbr WN?iZ0Tdz {w> "IM|\IҘrk/^hnuܻojMDQ9 "5rN*R98Êý0;$Na!ߓʃENKZ#Lì34 = Vf|S.}$%ϓ D)d-U쮜EڻXCѥFʣlb`LHu0$ bӱ"H֧%.5rPBÉ˒V(ql6q*kjd[)j>>1jF@2 ˎݻzX* إ_ܗϜ:B$ r'e?Gajm-ٻ~ŧ_̃@{ִ`kbk"~V{:i\_V*˫xE4ZQJ*$``ŦʧsSv)Soח6iv:[+191Ӳ8m,o9ʚrک+ڏ/pѫTuõW(Vm޽BN'\#GN@Â*ݹ0މ4rGT~)(@6 "n+04c08rwv?#a/qR8 dkMJFZB2\nqBA"yka-MDKDH$ٻ7۽wC&vykdbG[Y^o..aE*ڄ l `=?d6IAR%a;ph}wLv:++W+!ݸY ܱwaQ ck?s;f?orzQilyn|bkO/ՂJU*iw$XjuR7jꞝFn 3RK4DqO@@.'j!eF#$b BǸA > (#NN(["B)䡢jFH0cQ^З{ Kmv"5DNL))*hm8rm)Slk()&oٍaiwm+2h&Fb҂Ejl(B3XjQh- H(B'͇&4V_+T"1[ݴl4Ynmu[6M:1T!iրĤI@, r5~;JOZ'm`I tSOS'z˲@)BdfERڵk-@ƌG4, C ~XXnvR:Oڣ'x"{-UUE^lAǹ7۝(WI2'BD 8߭D6w?. BVoI}OD̠8g kD4jk8BkSD5R DR ;0(ҁ+Q \* 2peX\#e[ͱiMnlG`KA+Hػ]Ct~ DvR K̀ ǀJJ{{dA=(AbN{>1X^^"G@R>68|)"!;+`1ArBcE]Ě[[e 衰w;E@y$f =s~̙J}'=pddof Ϝ<_xᕻzhzbj/^^_[s!\Bc|͂Pv8|~߁1$jwvۘ?Ok_[[^\C%") $~oU*~dOn/OO^7w{챏?zW=r̹W_z7.,݌q.><ύMƵC77-\&(+>rhom|B7m:RuksU5ޘQšAyO|sZ!K£Wc6lrLC#Tso0_ng#STuY%T l[ձ*cՓODs?b ʚTgp GZ*nO(L HDr>b%e6dH:Lv׏A#u [q&"Hz %cd 1|BqL( IKB$%b@')5 0c$H&X"LQX ŠA6B?K1_vIJ4Z]M@-8R#b,0ft~)y{?^1bEY+>3gp {NtQ@q,5DPĻ=TԲ)X̂XVSʷSJrl@T R_"Hy{޲E6᷸ۻ#uj"$s҅- :+'CeGr"Q%Z)3wz"(GӶ!46jX$C$Rzvb":s}3xϻ?hh:/>y<{s?sfgvmn/|3Cπ1j֤R[T2C>qOL\~A Zڍ_vs7O9y1mK@OFOLN5=W+,>67wC!ր{xsgNX/Xyq~} v}{ҙVQ+ vMO9zwcbvuu¥k˾@0kKS & }b95ȅ{Q.p[UҥWwHX ע`~H 亻js4cRO 5JBX<σзe{50.)PwVG!)}khf‹mqQ6lݫb|AʝRdL8F$  ]JJ55@hsWh"0nPFy{&p2Nhſ N#/ũ[>9TWICDTzt(IY3|Zܒ,@|(Prr@{!.9FEoG()=e!CbC%.0(nοZE8"{a*K<R148G"1䨒GY 5n(VחW(PugA^sH4Z퍵8N=X$ԾGڥ˿>K~8z346&3S{{sS|W^u x)6ť\ڱq Q;bSFY:]cL{sS߸~7Ȗ嚱*ws2 i'&0kד(VX?> "2Zڧ3oq~W8kv9 T%`m6kca褓}VV$Իw{QwmMYMA-corA)ݑlQh$wqhA+7XvԿSy=,[wlG: fIftf}*l@Ь 8~kΣ&V17 H=`yk-Smߤ0?&%F4QQq*U奝$y`X *U ,Јa~5D @ƤI9įVqbEi{DdlbLJE RbdW/ڳH)&<'59ѨV})A1Z17>JD#s^x/ O$x{\KH!!iDyF  IPSٶ9mVyEED߯g-;"@@0֤6v&ItmCi_n])-S2$p;g89'/G]Чⷋb.nbT+ v%;κR*╕λF*}7Ѓ t%s>u+:431K9 rjx7o~IyA͕7N4ٻkϓ5gΟ}z(1yVX%JSgĊedvLܪ ԙ "[~uWI~WΝ;:޵5Ԫbw{s{bT^NE8U=0]}Ξ5Μ;BtǦ2U(L=ڸrBXm5Ac|$S-;EUz=auN( hlGhB5Md,ώKR#[䍊<' BR餑A#K>\氹5 n@KC"6>ȴ[{A3Am|L66:7z4DiEA,ֲZ!@P,lSFD{өAa PX5Ĝv ׂz۴jR0V 5Zt%e8A!`z MOYU ) ?9p>tjՌMڋ^xR=wх`|'[XinEȤD6O8 l'tb-+VmKOJXqxZ3=P<ͳVATc*00>f?|{+*޸ٴ#@B+ BG~w{_zp:0}w|m\~y\]|፫Kܷk~1n~*53trž*:"1QJk4!yL&cnn$ đ[K|82˔EJ[C) 7+ =  'eq?IpJ2е{,cߢͷTX{ 0r't6\TGDZ1U~sBÕ9Hc@TQ0b1)o~]z#Q܊(US0f_ow `s@Y4r(Cu"jtY|_+$eEZIkQwvZ d[W;mit[ 3/ۆQA[TBapg1 Z[S[[䤍wي[VtsA:`{*!7\_ε;HiYvEQTccle$Id g… s;$If!k$㢭f*֌x."{ZE1\ >di+6%|;ԏ  XR$Et{!.担>C;7 .k98}^M'IR]-W#+NQh{W`=dFlK~xyyTJ1j~ 8~&f; j:fBr FX1*7+o}ҙ^}מ ۗ}O_xkϮo*.]8{ҙoߵбzęTx.kf0FR Gsfs^~}EAPMhbjCw'OٗW *`M B#m2$:rtw}\v3Si'lel&uZԘ $|o~s_XZY_ tG?v:vgΜyg|㕳>ZYع3 )KjEz>Y}H^ ‡wh桵Ƭdx P ܐ5TaYEiIG۞DB^pyBy>i9êPe+S=bfwZNh "5X "Vۯ7&g;0FZ-6솎IYWE236! (X1ƯY*Ny:NmJ+Ux ~t\C +&տ*B Zm>oT:tʁ-XvY0NSI&зՆ LSy4Go/Zm f .;S anZ \Zj'1ڜ 2[V6R,s')9@ _ed{){{ )̦DD@b 43zo2Ѩ8Mq}وD/#활6aJfݺQxR~#@r_,2bˆ`fYdƵe7|3Zs$k3LgC4͖9r_~l5gyJ~_OxrzӁ0}fad-SZyצi<-}E}eBR5yfya] ڢ)t%#۶۠2؞+B@Wew^RSت<@(.B-hc("v2VeR\;:(4܌!f9ݭǝP)"-eCfM1{ h 7apSE!XY3 yK7+t'ϛ3W\Ϻv^qrr^XJ%+7/^\~ճv=x#U]Gv9|K&58Tnaг ;m}5z]_2#Q9Sl,R+i(T80RSD$ I#ZV>zk/Xsa6Msx=A[ ?\*Rdd!;j`h-x^_b"~jX_kW`aecMaN\6x>--F6Z&Ƶ$-XFuܙ,ݢLMzԳO`RH-@($b`qq &$lq^ɞ#A)8'xlt~=B3>=`pU2jsǎNz76JbuS?sbe, ;0[DZ <0 YRA@]iSVW\r:Voi3 B,1g\KKK .GvdP4)D$Xcr*mbeE"ȁa)P jZf r014ʯHlnR<Ȳߗfp~PÊE*Jmz1iZXN o |34 S]|0P)\Ul@?|ғ :$Ϸ'hϢ\4-.6BXwTs/$HEJ{JzPLǰNJCׂEH)G[Vm,#(~%Xl드_>=/m4v[Q)>@Hk!DƝ}/[=_UIl30 iIb!KWcÙCJ:TƑSh4jW^΄겤|)Cg4ׯ0^x{;$b߫4*Vӧmg+R^?gOJ)`4 qbyMBAHQeA>)e^ !{ \ &hTZkGZ*I> =ol1H*/b@jN9[Va*{c?ؽ|7*ܵ0פEVWVn^ HL ݾl_ G9vC{={ױϜ/cA>ܗ\[Xad Pn߂=:|M75TYV@+rt;gٲuTIQ,"ҷ ƛvI|@W,@Y($]T=C (Z  +nc nl!);v 2@&8>^߷>3THƩJl3w(eK@Ȁ O!IOVh!{xDŽt|/ܔ\_hPP‰]Վȃl 4yy%MPMSh GCUBGb tqKYI5>p{گt@b #(^ʉqH vIh*7p/6[ oĴX!Ӏ"lZVt A.P8az,eH啴5:]WZFg__\ RHn2`bjrv'r܍k󯼺xw.}W< n(]IŋZA5y=3kq/le:Vjb17?}I|ݷ}~ 0MwIX48k! (0η$3zZ.2+JKEXQo#V}V=weyiΩE7`pŰu3M8QE7:S >wYŰ 탇8㢖: }'{i9($4PZ,Z 5Sc4 VY1AB5*KpjmQ0&hS@ZFE3M)aĒm Ice~Q p?E]xE)Ysf ܯ3ωHMn ْ(;,aUªӍ@HX ]D &HR,#.oݎ,B$D{TT.m"pj ίB#E@<,~ࣇ]>l$:O}"M8z4 _ak0vJ/`",#0k1rE}$PaQ[o"rnX!H7RTɆvI@*m}{;kkT PNs@ayJIrj7#߸rgX:ۼ]ǿ0֞t^mlkvЦDX)_L (r"o`A1uI&efi|xck_jM\}Pc; [_zħ~3o9 J+T]w/~񳯿b{+S͸p'XtqʹGEUzX(zXR۸t5Nwh6- C߽=W7xc;v-|໿^]]5X T5`$P*^6& ;n %|@PW!ic:T]foxJQ"D Ӈs ;Q}Waq!ٱ/$`-fa)^9ֺ=UF{X8 =b#^{ Qzo\`s̹ [tc82.2Z VRW]j&I(#D]"ȏpb(61ACXOr3 (:a0ȫЕ 5]M]ḓEDuƈ{& ُ+-/̕k7R9w܁0 ŋo9zԩS{RjsyYc!Ja"&|U% TmmwR q ƀe=1K>0D& 0|~ q0<1!چ OkhlؒlL YN^ٜ r66+,<Ѝ[9"k nM[h@@<}ӫ2OȉXż0$i\QksVP@" "*ZV"LW2]_-NΝSQs2H %\ξen$;1=_uVL?ex֖}C]&b_{5s+_UomJS0Q3ɎLH+ 㓤<Q,_vyArjb+LZJ1"p(qh`qYX̺l BfF g4?Z- ǷNsm[N_J~W4:Fv`@x 9* Ÿn{1 ޑ2GyA\43T l{ԩ83!B <ρ?֕jո,vT ΗSbDP{: (Z7LcOy{iNUR}gIv@\x;BQ?7`a|PH'Ivs鳟kW/<Ç2Ffwaj>~_X]sUt _0>!z}i4`;W.IPݸvƷvm}Օ7}) ME~# lo[&N[BKI x&^2)jS,kYkwx}bzj\:ԍ 'N<ǟxOPI'[ FHc2&|nTiaNʊ&Is B'OItd Bz<%ydCAtHئM:njB;$i *@s*lV `/<3Xj S'dIe>8Uo|Y!R /]>y./U@BA&IZ;ǰH!.0P=pdtUy 4ٴ%bEh2ݾX *lp37n& ;̬`Ha&,NSÄn'#zd铮&#0$hl9mm(}3E<<յt6N%eH, 1Ģ7w1NIֻk .: )jZ^Hy*@]g" [gׂc}r~ޭY k32Dl4Ɖ[z!vۇc//w:-ٲq!ݻk+;24nڵZ2sX n((yo>"*f.`]mC@d{;xel HAҸS77_ o-37Lk7,7HuaD82 ]Y#W9wȴ #f#X壴3|ÿ1@9yJiZ<5pUo2 yڽ7Оp_(ǔUx!A`cT+}e搽'Bn^x\^8`'ҙSY7{ci<т<()ϓ<_?uy>k7?O6ɻ{>fkBdS&[$PUqcm } wƂUOkw߿վq'xO}{}ms# *uPmuy}R,^^ۼu"xZ2c6ᴹN:ތnO{R#Ȋ"Je4zX|`fa[2dh1R.5Ezֵzr~,&7Ztj')]0Bk '@@~Rڃ+3J- ؏»3(Xƥ6eȀ$k53 a7k-˚(ecL-}bMAMQEI~Ӿ~y A‚%hRZX+c;uksE    NJknטJ:ݸ~5= 4 :)wNĤ=G͌9{N"׾bp9 CCug{NgW4yg U|G*`st0FHd;Hd Oe9@!<@B+(sFtNP-'=CYFqrfqوFT !4`k2"ç_ܮ=y&w7/a 3r>lR r=0B`r D\ї3[n7D$KHGQ=۩Bfǝ}Rztx+ǎ޵j--uVQtRm~JQ;DCަEl5d9xqarvaàp?io(2A@.2g#ć)e+2kݒA[H$Q6(vD A9 >7kgbŋlH0eAR1nVEʍRHImuo-.]||u6V@4 F슞-"j3>}w;'N];檟˯@u\̕*a8g{$ F)y.6\Ƙc>9NWxLW=|;gzJ_=}WΟ>t cVij Bl} j> y\ 㳳g;)`'J.~еx;X+we;1;lßE脏 )}C= ω +Q^^ԡS(#)+1o#c7b8 ,2KARO}Af-5_GCiJ Q |`Òd3P!r{eIBvFtkۍ<`$ل>AEa a$Uql{gkl.QڂV&g5R"*6$}~.WPd, 0Cvyy9+ÐPgCYXZJR`۱W^ZX~s_z6ʟJ@"sZE+$ TDvO\ :*ea t:m{r]x^p]`/mS ð\P((E )nZIMc8\lC!B)J@"Nx~ zb]:_N!n^1Q[p13GY\3#s~'?pv܈A[!BaeDZ&3F:~Z,ْl4#!b{׿'xعk~|rV l gN^ʗvܥ#w:~Q A^o[[_mݵsBeJ\cd$‚D;:+8{᢫+jfaA,ƥEPؖXzjT.=(n1p eZ _UQYhO7K!W_(&<[ .Rh폯Bn;J{ى@#1 hz1S}$JPzV; |DZ1NzT.e$ U4iB'"H \-V[pF'fA9&J״dd?Ե uL 6@!)䭉e!"ҹDւzR;kw \\\\^\\W2At^;y$κW/_oIs͏LfhT裏~_tc}J^F`#MptA~Tk (u$Ѷ@jpk|bb@[ 0QɲRZ"rM48O8@5Rذqi ´#Mss Hf\䉋XSsy @{f%62s ^J@n{2X^]^Avo֦Pv9I\%_i"JgC0=z7#=/j{Ix٧ 755h[FGKǫ!Q0Eg0tEzt ɿ*9"H`,,~ V:f&.&ի+i"ӂMZ,a ];e;vh9%ԾiC\Vk{ *Y<օ1hȆ&W1][,rΆD"o# IWVş6-mHX򫯝xIjU݈nq?`ssP1Jxջ )Z1V"[th,2J3+g ϑr2 R@v`;m\WXfJ@9"}ߘ)_6ZJ!3֊E"$*,VաUH:|BP{p"RXː ("Z)\%,8'<_$iO'vZЇ?]I|s &,uZid%.;||RuҬt(jgݦԨ)81nn+Օ񉨁YX՘CGWZV輺!jyV//\nu`ñQ[Y6`EWm5$lPOgłSqqK0+F HEŭR~ҹǧ~^o. e @\n:^p34Q&n)Fze}snG_}Y %Z^]1S(֖eZoID17Gf?zЫ{/àwZzy\h# [N\~ WdYkF0 H(Vi76qtkvǏܨzG/5NՋٛ&cG܏q'2"{xX/uE:0SD8ǭT(,K9M2{Bz4ZG@<#l=HRt+2!nH# VDPf(.X@Ȼ ш@2HܡR#pK._FAqpGF 3,^#K U1ݫ!2-G =jz3Re!⸆'ܿ,|90dxGEl҄ {0i*< ++vGyZęwk[U㉱C̉u<5 Fa-6ld )ŏ "ODOۙDd&׶3<ͻGlI2e{ΐ\w$󕡫p~U6W2SGF9nރM<846 ;@Vz#1sKq/jxxOQm?SCgBH5,ꘈ>ӊ -roA:6*TҺ*OcxXԊ½)FiJC7*JJ)C*lQ(̽(ؠVիH7jR!ԗȼ od`O}<B(шBL22d˫זwmlٻg7r[ *9Uٟ*v+mauM(Y>ttT*N9 |6t?REGܵRt2fi=?dY2)9@,JXbw$0``.@޸·;` _x_ARW4{~}ϭ}+_AuًłLD @_|K_ʛ&LOf7vt*-Xlr5t&"DEV;O!o~HYLDũPN>JL'8iKL<0vq4ٶmWiR25̮ά/ϯ]]@6c뵡h[ȍppb;ҢkۗVw&ݱc8\6pG\A* ~۽ {ӧ0Iޠ\&Z `d[ƗOUwiTNбft0OWl =WK;4Z3ּg;ap3IJ1WP'Í2J5G1@d, MHcA\=VDɥl` kVLaulT׭e5xWCLJH죠UW~1T 06Z;UX8YjN42+ڵP55kV}VJd (PU+xP>7wq6 > 3ŷn';T=63'Aر9/?F1B yR;Jf7:0Bc6_ʝ:m:rgM>ݵk}ݳmvNxyqH$?aw=V OVzU#fVP_x& T7,)xΟAgijMۉtc{>x(}0` [KJ4mk0!&v{'ju@X'$gڝobfYS嘙PCbh =8'g)Y}0Q M~ZZm+"U'{wXՕ?3wBuN/rrXa'++&loL7n*'8`c\ѧM{o-yMЮ~5vR/U|HI&kHo8J+^ݖmfx>˥,ڇXICuRL< %mzZ MzA?3&Lvm.;p`ϭwrs/~Gn g>'?^q^=H/xk],>T1ƶԭ^"pq}y굫 A`b=)`m^YU]WN\[ݾkgF1 |Ԏ LT .<;8<k"4ZWue I6Vq˩L  'i84@JKvg+[zʪFA\j uU\|?6lUh,[}s^yp[/Cj#2h΍џLr] G7IIcee6Xh驗zO*=tiopՏMy67)8ѻڹa= p@P:~5٩`A p%S4 ܽҽdD=tD%i0}6(lU{<ult{p h" a;gjڌ !#:@W^q5f _49v&V+K}-&+\]+L"V[Ea5ūƺvu}tU_d֬LXذW/hGQ3kˇMU5ƝE̩0|FjХkxFȹ=߽<>h9wgTaˑ =>.5rYkkK2ݱԝJF ln|k`>eTaKOՎi6\E MnIӧ*2SmV8+JAD+,/^X_/P'^fӥK%X-VrdfIOi&M] e]e'xK@GX9Xz|tSܼ6 pázh_b#.7cϝ^YH#(I>7|3v~@0Ş>rrAڱcQwԩ\]]VΟ=un y mKKL9|<6 O=$;2 gNgؽk1BQD-NJfmιʥh*Wcz{gf| \޾݈rӊ5V+bȍBR|3i HU{m#y$so-8+XeJaѳa4 Oq:ۭGŸzpp t>SX+Լ0 ,(&:̩+k $=/_<KǏ`D ֡΋Od!$/4=ӻ~޻sӧN>k.5K9lt1gOy۳oy}|gfZҥ C=#JGqP q䄎~ӰA't(YPVoٹB {?ٳOv8J< u^z g~o$j&P+ Cy \g?KWz0D P"|j8v:fa3,P|^g`dV )ȭ4SؙCvhtApi#ֲ»b{ 59t4tYcf6Il_ɾjςe)2KihK;76$@osWwm+i4B5:SN/9'Jصo2xN_q L 1Puc: ։R xjjDp*L/cy ͊*EvJqK8*4W`/0a|Q`i3eX0:/7^R{ԙN#W @9+tԣ?W.^F.8;"x(`tY#""5|t/X]Y|bt@Ѵ=(4@Oaf:LM: eZ6|8V aѣp* :s\3<,U@_ggW<tFaCI6!NJޘOˆ㟈{H&לu%alO" mVJ䶼 ÌfD׶=VZ8{0i|) {q0u;hED69mM\CfqV%=ED{V/!O}t%r>TS8z>q S͹H3'5%aH*gxhحWz:J҄aڄ"!*=Fi:?? Tvm4 $-~͘g>Z[X_]@JQ8žb}=cOx1Y=wۜ* s ?wݳ>7h@Fs|+{ ={yӍIhozӛ`02ecz(J lX*KHؽ}}5= H><5$۹s;ɯ|pA závvAS={{A8_ŧ:j t^i%H Ypi8T9<,5mj/F#uُ!6!;`g/6!sژӕx Z\8Pu*w66'2Dsӯg߶7%tnB[YK;<";0oۓ )sռR-cIdXaJX\z6޲98(O9"&Fp` R 󈢘CP X|W._CŪĎApR} YħCߦwɬX37̊Ƃ%Y;7||C+QfIymH:;U5貐" qz QN3:*(8[!i^Ó0 Ս*lxEZ0@\!t v`UzQxvUU}5" n,Ҝټܱ͡-je>Ę.C?g}2͊$,F?>+ [Pb,4Cﴪ&{Ui%UR: !h"`W[3;k Fh@o V T[KS]=Fu8cNV2iM [%#P Y(I2@ZTBnvF'<3RۓzMnl<ԓΝg-F3J[Di็/\X_[YE}w{؁፭ Yy╌H8 <݃3 R̖-sJ{1P&qinp/w;qE|fqC|GqPOOoeGSO?9*1/#90_ ?/{/} 3g0h:Cas.i=)RUe@C ++˨@N~vX^DkS|n0$1oO^4'Ԃn=5EFè"Ke\Q9m! ~ʭX[PG\&)m};|GD=>7 sҥhwn+2uǙ0 F̓x ]&t 7~!q]_-UbPrn?~Mx@ldb Ke!]ߙ+3+˫W@EܠuҹR!z4k+t;f;y L ]*Mw{)9B 6윎d?9Q }HWQdN"0({񐁭]ö v9XZbWjUɍMjj` h-c#_ |Z`ޓZ+< N4Zlz3 ~E݀pL?)ԪryڇxiG[Z|Ԍܞ]\’$d %]HrS1ěHML kc3J[1LOR :<@aty6"gS3c$Plhs&?fI-܀tdMVQ֖qA`Y̫$W1 p,Gڹcrg;r9O:XnshjЌ%OkQܟS!\mjpZ9]gLaCfE[Nie6AnP[{O~z$or>'x ,78$V>?>w{~*}GnkkћHDW`@P s@Y*9r׾57tf?l~{.6&=G箥X/C[@m@L8xpXX}0,>ǀ=Ox&k裏~k'_؏}Fo?8(x?7TX14#ݘĊlKK‚_ɾm6UΨ!(ѳ*kaezepeC]٠e͞X{6&  K4ISlil> 8Jn1y\ * >~2O|fɊ+?kq{vlrBr2qdkjw8ɲԎ}Iuc4/DwͲ).v!=oӞx4ܨ]z(1ĉ#uF/Kmg2>[{J.G!U hIl1rjYMX9H ڍ3,lQrX,@%>)+]+XcGygq 0qfwډu᥆-Ϯݿ K|*8y4 կ}ꩧbz AQX>Jv;jmq2$2"ַ0Kla^O\MOg :""L:5|k) Vb}#=Ʈ;@~Ю \et5E58.^)gΞ=NTT>pdMj o^qDޠƂcOܾ̊CpU̱7,@o߾ O+[E쵡B6Yi:wFNZާ ԶvMP#l[+wζmu9C`yC6r{+|8WL73;-OI65^-4 +gwcG<{Lb,,of;tt*R v"2a1,\ś_nUaRQ] ,ڳ3: oh,/N%&ZCwЩb @UQwذʣ^Fh%[um?6Ƣ8d ^!-<(M ~Xc-[%7=;(y(եr X>h"ahOV]J{ jkNBri!^4HlR7ZN3TPUyqu+쫕St:i`TiFͻDR1( 7fLONAɇ?)ֈkI 2P8yW Yqekamx5MfS .QQ@G^8D8~gAݾc|ʐZofL8Dus7W(???p~#BG4!p~'y?O!_pYٙ ig[oE "lѤ RDx咦^NՍucq- `=@ȷ>KUZ3Q$Ж}:eИ I4M WS!IA 5wH-3 ں,t~0`VI 5d2LZa2TI%Hu.h^0󛾑v!6y{^)si{Po#LgugI_'UonWc68&)!bxFqEs/bN琈+,r.n)pLxr'-)"֕Jm-pևQy+MtNfԤk+\Yjښ% m؜9NJkLѧ7hYs[)PTh9VZ;S8j,G||j"Kҷ,#eo _XaUsvVc= ΋ jj竴gE wzm,WFwS];-+z*u)LnFrlκa'UkN9  F: ^DHw?JCMy9%t&zQBJRzNȪɃjdͿV?@F?⮆Ma0nn[֐-ƗPCC_mږryLVRU5ZCN7D@]}ا$U(U*ym}0iRnl8M:)g'=tQ7;'Ō1ST;9ƙ7:rF{[l??Y@gD`wpt<R,1Mf4 |饗PaY|D3}+zw-L%H O1Fj FįpSgϟO(KkG߿cǮ'U0D)mQqq.d(r]A6)ȫrqM"%o} 8髼žf\WWK.Zc%+ LA=!eoϞݻw%ԍ_WQB>ʛ_[ڹ󾗽bznO>z%pAVN:A0@%xI|\(s㑣$042ztezu{ExB$ NH<|FQ2_a>-G/[+iSz F0)c52'kx0n/[M擡 i2xhoq|Ab-}!Rl鰆= OnIK&[xjL/g-@XtU wڷ.HTϮ/PH"T*X,5hCzZaQ / U*_ąiIGZ,Ƕ`,O^8>J%G)OЪ¹s뜦w1B28}sڹcla;v`l߹a=Б;rn;no:~mrpߴg]ƣwvGs*sz85fxqr8h񿼥tʓBy9-3#dy8ħ'hBЂ*_-R&êA՛ ՈxkX3ZjS*o">ǒD"aJU澗0IBT L7ru;?+xeMF; T>61X*?.BIکPiՊV+k[*c*vuO)Ț(&LQ(JDo1Z_gaXV1G̯ZUPXZ&"1[ ;{H*GΜ;\rù9 <A?#wu<)7Z{3Oq`ڙsW֔{jӟ/k#H?Ν{{iծ;}g!18JKms5`RtuSëǘqifqqhDhe9 Lruז/`6 'e|*sl{Nؠ@N?n??Cm_;?6%Lr>אx?G?MV(;{磿۠_xwlKC? 3e5(HiBpk@%"Aq[ƒg @WZtxá@E &3}bS:賩vZq]bβ k_G2 .xlL._Vn&EmSCa4 lj|e׆ڢI@ZRK+SK$'7̬mF%jysY^gKyD5AIOb=g+'=8F)iȳ1BjﴯՉf57zux +hkb I Q%*<3&jʛa=D! d836\4a'Pz˝wqz!Q8AtS[&[Yl]! ?sg1p,tkh2o.FVcv66E (J&9dC r(۩݉,8 F2Cy'x&?He8– ,F?딐φ;LFI6jC[c~~ROhdI ;od"A[瑃 StZQ$\PHfõ⸮0b4Y.0LaGʦ3eP6H8[qYVZoPH" gGڄ.@!u)*64 =ⷀQP]1;p#/{ Q5eↂ\# O?WU"#?܋BGш-΁4z;R|-Қ]]c  ]2 'Oz'Ξv3ή\[EV@++붹ŝ;wUp-+%8sw~ ! G4b)I["gD+P1qc0o.zÇ|~ 7pE^z_?m2ߡma۞{~?n:jLJ #AǩܳJ@/YZ i I>y !~lgBe瞻oo %:ɣxQQWGc''Z>EPh*BM (ǭ|GSƿ2֒րPj'dSuӸ4ulM[./s7t egYmmj07܇A畄V5/Z'aX?akcSVT| ~%ͅ6J&WBQmH0# zԓ|%3@82!f@{=ͫWU6swسsTf#=/J1QH JBH)9|먙X.?ĴԘ9qf&=nEcDw _Wj{6(5 nY4O{)R]\T`'/n۱mi綥ݘ*^\ؽmGȱt#w{ -ZZgbsè@Mj_ɝ@K~{4^RAJ&Ŵ\~[('_GyQɺ.˟Ak(۴"c'Xi n%7D''5~^'TB=2:_FI5UL )* A40 6yӄ8uESp֐#/SA~آ,H*>0J>sjhX4yE[bzS1xYkV}k ) 2.PPcq05[U JS@c} 4ME0]+DzSp쁗 _ D0[APW`J `)t0MyPmKmem֫JlPcQaq5xYMa'n-C=C@ar&lDgXF?&C-Jve ČNKD)y"|;p1IU&5U䁏)\:0YV\.Üg#k{9ՙ51jLN1f~@:}2'w11(KAInX1ܩxtmz}w#AP1.v gmt2sߘDT{ LҹeO?|(ؖ%zPa]l^sn{&Ϩ?]"8L"|(@79ּ? @/[@q큮SpӧŒ-O{3N{.]jЭjف4d\?N^UٜG&m :4>>)xq2`%XnHҖ:ԝl20'hjAiO/.U:x<9BerWAa؈0F"Mk5+=]' ۣ c4"C-":“Yzp<Űrp`?{ PN*(`zPa)S'c1<G}$Ul/ SO"+x?B&q ZXڠt!; nIDX"kc7rŪ@WCgҾ{'No ?}О:c۞w>GKuHvYٸc2]bEQh}mw`ZEtΚG]U }]U%BL m1'9{uhVFS5{ ^Q^\Uo38_j5@Ĕ<{ vK!#)7<_BdJ{FPLm 俶Of"Ed/\WRFҶde$m:k%kơh3Y| oC. /m D^9  "8y |'^嫗~ԇ>(ڇk1|o>n/~(ie"(\ctU?^e\oMPp^ޖ jj ;wgRAf ԁH!"Vajo¿FHj但[Gcϴ_cdFc/EXn:Ed=,ћ7ySҮ&Ɇ83KiRā\y!9=u"ufJ@y:_Y,hԨsck(?M>Hb AB&[\UGмO:aawۧf6zT{fVcvQJ~%%OtY\ ;Px5^0)i3L 'Cot^̑wNQa+i#Cp7VkU?,3Zv)oҵ0]Q5cGEP6ZZʪPGSP}C3Q*AJAdj=L%=;4oơ7.LpU!"b!iS4bi}cY# 44._ყNAG}NPA  3Mڞ>s 5T_7JcpIqk+@NHzWgO\_thA7vsQ N !ʏFLb?KO@^hM Is.=`kW|_\ז`X¯"Ȯ$FBkkuλ@گZ[;`lۿ?ZYy(Jb3yͫi)9Iڠ(!Is3J0e;%AGĿ,E^!D<ūo:)Ql=B;;Ƅ:s#ukfq \@-#m*ISgMO}pFJ>󛀌'j8-':[^g6hn3;97yj6+_۾7P2:ƣ r*ǟ[%ɇް^ro*юu&3mU nz N;5ke.yWZDr@B%+ eΡWְځ[9DVc $S΁15:eL7l\F6jaģ6nT`$86ҊM, E|XCTejˆJ#|W՝Ԭ|BKi4oD1,xSYm9 ^9~uz`4o5%a>6>ѿdA;LnLod)0?avd}+W5<}bcL;ϘߍYgϟD#x6o;'U!3 -l,og5)Z=wK$TQEY^tz4\5 H}h@TaR !R R hHS <\ Tڅ\YuNOym0nj`־%%KsFM25QʗZJفtTF26_1s +AńKg*??Evk Դ(O=B~ c~,r[pĈDdk0 =_|Z T{A׿u")7Q~#fynL|qQ5KQ+WB@ci&7՟CTeDJq嶈jkƤ8Tv N yCeO'wޏnt>L8eqlB&j9yR| -G>+"\Y#נRw&)U 3}?H*$dH\X@ʏ` C xIS_`7F 8y1Џ\駟x 1}< >,;,ItKl<5KnloI/o`Ic %[&,K[t4u^V ȎZ2v154yk&IDV,X;%=FHHT)ka|r5Sk"Gd\6M55=i8.sUי&ztlzLu֚5T#$zeJit+-"CCFo*UXh]j@g3E, , Jx6q>2pDK}p(x|#{)6E??-\ FikuG!V]1/n:z=?ɫ+?o?|vNķ ~ !m ?WLVɐ jX]YW~&xgϟ;-=Mǎ^>҈|?~w0dz7zT{7jQ?AGqPFcCx:VNL0 @lM[kV?u{ Z NOp#X"85Ӄ:BaQ 4 ;6yzWlNaT﯏~79~{sI~o5)fotEnQ>Ojoމ^DPct<=uB45xKIs7wQMn{nV^2'0GhXhxEeieOg5!H{@G WiJQH;XsU'+ *sNdrPg]s$'|i z[ȍ}&iM`ZgZ8t3NR8c1ຬ3 l̐ܲe^+{03Cy3kˊ3.ǃBkg@ń1Sƥ.G(%>A @7f0);TǘL?s>U^AR6羓z!%pNIO"\`wogץ>`mAx 2ѧ<-2l dW:o<;YH-3 K?:3xw弗`3*M;WviV4Ka* &^YFn9h:IPћkWqc^!:(+¶?3n "r*MvE1\{'>ܫ^jGֹp^|  Ppv`NCAY6y~{^~Az./I|"[qGLAҎ@ݷ`"DQ\DžovO~{<,9=㵿vQ{Eg 8׾r5=܊sٵZKK;ח!V.Ҥ3pN!NsƖ~o,Z籶 kT #?z2~Ubiq:#Ac5!0Xc}i_ZQbE1h?ӯP-at`R>|Q$(O?`Kc Jw2D2 h<٨t$(p H.vᲞ9{9lw|ev`|=Ö8iN踵r Vdp7: D^Ȣ_rQLn=āȪ=0LI-pEx=2#{ NQә<~.LyLG`uý6G@RG\>߼Ax]>]!x2cUQR +r5}ʫ?yK N.9)T-4Jm'^((ש 7`=hfK,G:+wk[>l`4h)lƖEH N}T]K>/™ r&gbyT~~<o)J06QFƳ=˞x85pP:67{^W"V~)[T-ɵәI; ܔ"0wrdRNs< i$ѳh̥i8 C9V4ص` 2)=7D:B̟έ9i;Bm︬S't:;}ĝ{y&ۼ趎rWȼΟgiCsi|0P_vu{  X%QB[C&arAba :9ego}kqlc\\F0OV+pV3\m'3 ?(S+ )[ ؅j%(&p e'{œ|[CPZ% >|?SUzG?QG]z%WXr*2?߅g8*}x՞dbb_3dY_6 mXMp61KXsŎ@)pLIȃu@?ɰ'n5L&͙C5: 3sKUࡂєfIϱ:N{Tjw&A6lq!hrR}x9n0r>񊑚YS[S{m`5 !8Ē9܉?dET86?]3\ΐCIql󵓌r*av^{GtYubwTĀb` bWJy6ִuLQϩa>gITY{[i +xnoҠ!GE8 &w$Ӳe|E*!ig{:y -5Q2ߜ~AxtdvT8n,5Fui_ފ-=ѓFc.{|„A^t?7 yQwmͺi|Vrӌ8u`|-iɌUmU+(4T7/ ԃzu#C9^)ZS(3)oB0'+0z`Z[ -陠gG_yTN9I}6ee? 2WWWPzCcj镵eNR U0hc1m2+6^p~'(P& [8!-{$%}^//3I!*`PFNAkK@r)*0s`cWO rçϜCDl VXZYx~VOC8u51\eR O؄^.sF(P0yFWЕ/n{Aو3A."j3[G ލX&+sc_)$FM9P A9JE*EI V#1.2-3yzs=H$/|d= 6kQk%BsysHEqiVFR<+\L һ*qCUeQ & :DPw`pVF,8֡3V&U<1hD3 k@|`VFW6HR ȣ aY>U!:QV*u)dt}s/3,P|gvWYnƘW/(\.tʷ4ՏЍ??_m s9oD_ُ \z_zB Z?|Ћ$z()M]cW¡H}^o> |2^6?65]7 p8q 'fUg?)w2_wIq$L21Chd=EEM$pb|`-D83jM ?^lfxjb|#ddCzrSKz׻zS=_;3Dkz;JjXux, lbX7>CvW 7 :p6]H*6Map2,d _5숅ҡytCgWHTnl':́|A?PDz\G 3uQK<Ʉ<%k<}>GN9g8ron5Ydk\]N&_E5j޵qWL:9oIH$4.'}(t"3p'/QBh"> 18QNh*|z9MtϽwyg!BF :`4<Hw xv> Ov @"]Jvw,>XPV$N= zsĥ.pu._zx;D36S#X| ۖ7$'Lh:er+7wRT/FYnꀍDh(Dr^8܉NPW3t6JciZ'[uqĕasq{K ΀g㍱0ddp¼ܫ8>[#v}`VǜdUmQwNtzgr@UإǴFZ M<: 2̐ \O*}f])0CT]Kwi2hnE6Q>ɀ!7FAy8=dQO?#s&eRtV 58AInނOf^.2>L0@2K(BS< MPIO={Za+Z~̰#?kEul#0_i-҈l_h?9sjCM.ȏn]-z-ڃXS%69'(bξq[r[sKyLjVؠlJ{MAg-fXu|*6KE C] o"*;uAE5tuYx9^ K%RWMT0pҊh\LѺC^bf'jf9ؿ'h33;})!:xpaW{)ʐP 3=t2jʵev≓VVncrԩߟUH=x@*Mm{1^ŋIPyMo?RF>"sO'*70" U=+JNBϛݮ6ng4pL0 {؋=WW=Dҗpio*jc.|ꬪaMcH4]Ud 』{DgعWoGپoA@ir@E`.(gD?Cg`"۷#µ%.mgpF|὇{өA pa~v`UivJ0T>N 1 3s,'!8^݃NFrn{C*õeeǓ Vۨ)}S.X,1^zH-Q9?᳅|xG:3>S4WߔPP~尿=aL6M唨ZX<3aH‡BF^Hw]s$Tޞm_qF|L/mS'+3njMӥu$&򔌅8a:DL4NP+gqktmӅ ry ™ UJaR';=K7^DvdDγ:ؠ(ʻ;c/ĝ[IJi@5˓^4^h^*6;+vrM6D2ߤXORn)5O[ƻM0u$^7svv t6Kmg /^j]Ү6=q&wtwzfSfc 5Zj#@okai8h>kW+bA?bd*҇)kL$qBqQnl6Td}j5VzGI"UTiTP;L NYOaQp-j6 *T̈pعg[g),)ՁpD Lܿo~zq>K@Hgk􈝆G dá=]Yض\SWeCFQHH4,pH->tՕγ#+&бu42?'TPpXg曏EsIE_ =r#غ=sO?|5sns0$EZ8Q_z^RP +"MoV*~:"sӍLI:H/h@xYMkM-–E[xdޣA @w S}*IGܽ7u],ypI_8œ' ی=P^h}v:$Ԏ"g(k#ba S5Nt.gup Za>!eoԩS/u׽֖bZ;{JNf KUJUddPKFu΅g sZ[=jc;g@Д?:7)^KןsK0u0 6ΥMP+lj{}暙7ZJfHu[0I/?f~ փ'S(] L>z)cg2A4١ojl /Jptch01 10|䄑r8_,(!&Lrz]'pd\aƴ&Xםc|]\2f  +SҸi۩D[&@$FķbP.ЌXSQ6f?v 6",e?mm #oR"Xzkm;HhǏTXG5xԧҁt\tNHYe DzBz96~Řrꑈm&MW{2j,V-Basߞ% ,LAIҰ54vgԎֹN/`_tw/\g׼5>Z) _;CUpGPidzD]zܹ3輞~9IܱWDko< ǎD\aFkaT HwYsGW $ wi/+aXs>DQлwz*b Me30v򎝻rDbD^9`M {丹{ў>W._cToΆ?`K3)>JWqmXηW5~nRSU^7`Gcuvdwua\H˨m@:rQ8(=p#;Sp_P>EɥOnt27Myi{ujmIh`|e #- Ŭu"7id Npud7|Cgݿv%%ZҖYu 3VTLN$8٢S擏\fio1Н85xbXF %IR l>$xhnlρc[Pj q0&=|;-R=Yv\12;X:jvjTKЧAl0kh=O=KNHH 63YlYT?x;x y(YaX^s<[r)C ,mR*W7C.!j1E[M(gS-kޮmbī<~lLדvj"mR|Kw莽Ƒ!7s#`R^d vnZpQZ׺34IT#Wa)⌶pvh}{dSXe#"cYz8Wσ+R<J,z[ߌi= s?Gx́%!zT5B_Ww-=ٳCD'eAhI"8ᆃe1g=x7!;oubfWZv\|g8M(zPJASN_^p2=C^i9 y~v!Fބ7U%8E(ByiT猁]+l6F;VqrQ4N I8"ʵ)kY(+Iĉ# |56#@NvF> Mo(( L wy6OxH }FIO)HwKcל[cL ZdLU&۝]zۜ$ZފQ]R3X`ܾ$ߙoL;1ds;>naKͺ4y9%d^|OTxuBl@$>l.dLnBTӇJ Rd|D3'c*ˁ+`~bwW j/EgMԦ@08|J|u肉Ψ[i `NEjkL-[!¦ҒAOukWc6vLSe2y楘Jd%#mQg hH0EnaöAT2,Q­JzTIDb#8H;pGCiBy3 C.I2K挚EYh0(OTx+KF/){}p-cv8NIQ(,O׀Q!>} s>s@f@r^YKpfK%{׻i Df5vf[cuY]ɓ9a!Rc;C9ɩS'0`oqib 7hOpIM:J-ɟ kM 7w߃B7dk.]hFzi4ق0[I8+Xw77%/Mu(|m[S`|Gcyd0IJ?2SF\`g{lho~|;1#ba?=?h vi-)u | @h4\3gO^w6&8xn=qnh !؇3)4aG)ěCh9Kf#3gDk# T{KuCG||Y:.2SuW)ɱɏ+ ):NJQk8\8cOމ'L"[oe|$>3cq _$:\c_>S׊ɹ0⫦BZ2fu)Ϻ-lN8iW|f-JL̔&gձ+z Mdt _@‰ ƳߢLȂ\p5Rs02F榫Yx {۱;D@apLNcgA-r.18(@7HX )`xի^+QOk lgOc0pZի(9r!Ѣ/ESQ/g()ט#s+8|?gkC Yl9xY18r0s%]/CF]ݽwPʯN◿|;k`}J5C=no>E4=[)G[,5Kb4R\@&_;$7cqN]B)9io=EGق:nTitB>2mXvpIfdJvY q,?: w o>oT"ϭy.xGcNo=ubaicM,ܷs|Wg< LIb[alL.&Բr(=9s"j0!nS0OܓW.훝x.`j r ;&H 'pgpmycf.MMHCgl:+DYFxqqd5zJ4 /2Z;g{&W:"j=[{=]ZÔ=_W;O0<ӧ_|.)hd(0I3dWQFH2vsւ`+W/hwϽ׀z@o .yc ~+#hVLbw #quyw>o8V){taf//cj ǿ. (!`9w4 `Snz`+x!;Dvk lR]YNkjAï#d"o@37O=w5mccџ/ p|'r8 r?5kdַ{.XKh٩FPO?W_!ɷW5h[c$'EXX.o\5\V0m1|8;c %UF)w%p T.k CAьl sCL2 /:6{nzYDJ)^V9]J[`BDJ_ЙSKZy/%# FeBI۽Kt[mOPv -k6׫*%W٦G7\uw`P'artRA:HЁ)i,Ӳ[{ W`7ʵ3 (6'"o~lH<^L|#TX9Lqh@(m]K؈Ia8Y0^B۵W.QNO$:q^e8ϕ2٢7XF5n^ !|{͇HU4װ\"I4M?[:q,tpm#nwj':D&;-_EUiлexs A|[%cN-0ga:j؅ͯN!@"5 )w$Ͷ n<- Ըr Ÿ.xT4`WǛOMT0XHX\OX)*6™U4)`c*IU6,܋/}ks7Vd17*;73fҎ׼@ @ H}7}  PRSuBt~߫d''ww_h73 d5H_|/sWuC{|;c'_c7LQ:&oL'},Yfb~N@ %107<~ͯzWMy_v=wܵsBוLCnE*܋XNRaMjgMmu~RmWvXU*2!x<)CE. ցh-V+~Uz:m;gp-vʘovPTEĥ9/=7qf qk&_1B@z]F:@3kT{;bK(ݷwnmy I& ߽{/ܦūOr؊^xƣ,lc؟ <{oܤ݈˄(4=;WKo`0tzWno\: Z}_2>w-B\tȘ޳qǎmo{[#>{{hkR)#%:u n 2A%LLaduy`M "4d(0Z 7ǫ.>?ހ ҡ?ݿѣyGsmuʵ$k$ ;Dk_C}_?k 6f8#aIFW=y@@@ a8#ݐfbϱc7TI TH׊\rZ4 ȴT>.@mwL̀e*Aϴ;w]f9"B]5b=,(Q֔ 1:AL芞8Qpϗ/S9Sc7^PWܐNشSՕJfڬ q4D47\q{H>siqtwN9Gv#yNR<Zȫ\H?*\ǺO ]Da7$s4Aa 6wc )>~EՊj2Ɯyn˲ġM' k̼޹H~8[O[xɵ$ٽAOT!bჇ ]U &}8Lً>e޶4moJ@D: GF"zЖ5#%p!kwo%qx{ڂݮdR ԑZ~tq7KBgE+AN~1ψqB2xAR7Sk23.t;ժR⥌:QV }m= . %;Xʤ YT *:^ ьn UHj}sNSdXY.ce8y}-xg:;K;.n~a2v3 ~NF_ f-%(bkXKuu.0%U?YaiY kuM۷]}"sjmewc3O _`,@zOG&N<Ҩۛw=;m ݱtS 7;؉֐Rݭmm!+|䶗tT8Z7t0gN=NxǚnnaSY/lb]S[\K7&y@~(C,6.k]l`tLdKб .p#!=j,{`}u {N y/|*KbW۷y 'uZ p n KqGSH6_hJ&Ȓe`&rSC[/}x֘Ɉvs'D:3aIί5H 2:Nf:+|V Veء-2s!lTI|f_>Ea],'uf7&> WHӮV1JUJԠy/ cCYf5PZOVz:)r?q / 9rqzlq]/9{<~Q}׽o~;pԗy > w?o菿ped{,-,$~?WzSh偀!g꧃{ X_$w]{6oɔڹcկyi^okz 5a e sd uL!]ҥqמ"F=/>E`įxr.<{gz󭷠)@4 ؀ƘϜ> ?F Ï|CGCP[\\XJvl0O1kU}]ww{*#mBw|`cz_Af8=W B:^Q)@?59_q^O!TJ̎+?# )#݈hqa(fYy|Ս^oe2!gÒ!TjLf34Q|l2)W#fM`Yd'+)iy-=VJbN.]<^m'#dיų'Y&9 I.x|c{75|Tn;z&zQ9j4x+1 l 5A2'iĞ﫦>T@O80\9bz4 O/n5qH9i!ѕ҆l1S3.vͷzӓO>wϽ0}Sw${`cm=̄إ>iB27cp77n9]m16Gb0.$G*CITw}Z٭1u&y:kADd-ZA;o.\BsuF SJOڵ: hN61ާz`)O"n5x˩v77+KXiD7YʓXLB幚S!~D≁(0\h5K5>Rz.Jpд6n <H$S(6fM5iC~kLztxm#5Z7iKp:@$N} ԟ.5vkWΖ{`[4*ӻ< ҉g՟u~s,e̎p?  _*zj~qd<3błwS^x%F@ 2(~ ~, g?󗟭 곟/zM_ g}{F/}Ku'k+>I84)(upn.*FYa{ߙsgAan-!8o\¯vڋa @^\P0mSɹL[69v*v3+lVaHFf*Y8;C[ đ3hi ?R3,˂]Ft ou ^݄?qsN'Qpll׺s.ظp)-NdE6VvS-X͟nM갌>g=)ww#t@F9r Mw]v*q( '48ϻ@ɘOZ9qlW+]9OX*V5+TQvk4>MAJSR''Wi3~E5WQtJuV` S%;YrDzFX P6՛2) |Ǚ;~\p۲CO)ɗ.ᣏ> d^a@QhSXBXJLlG>A-F1P2:uvߙb4~?O!ȞS4Ud0O||ܜJ_̇x>ZWnh lѡ (X"p~kU|`:1(<s_V`zId{?ի<,_4!2[޹K`7P #SES$KUO@n -Ԟ;8RB3|7g~)Xt 9x)c(2\ Q_@(Ƞ!Ӧqo/ng|m9 ؇t`_UtQKo)/-m:7WgYFpMS.M:yO5QK:㝍)qNEa_ B۔FX)V5*hsInHHBGybF ޶/V"m(%[қ(O̰ݩwCqt_\'^-1?#6]+`R^T^2;r-Cv:ڡc; -tv:Qy 0m(m7dXQnvTYnY-;Vy[} wdߡn8y+/]FΩ{9vGA4ez lհ1`k qa@"g<,caםMdeäZ-2Bòl5!,ʐRFV(mǜ&`McwMHēO{AC(z*-Gg;I>'C)Bcj v큿sTN| D>I,#7Mzؼ จD A:Q $h;Pq%yWb=΍Qiy%g2f$N8R7TXKHwNJFLeV>8kWsۖn*gj)mBA-FWۣFuc!ș_$ar83iR.VxԅXPSIe, V%.ha Q)>c 9;|7^t>sI0QUD.jԼDn0z -rPi5d2GCJ^4ZVΨKô()FF_oIlωi(<|HkE6GR~PQ0^W&{JRĚHo?K-s0̑J4`k\>'Z(z3)QDV=3qP_[xkV^^uu8_lC|1Qϔ w GΟ?\w\ض{9i `GǭF2Uuky{YxU3ּ3&hNP۱2J)兩!\׾tWXCfz;t2@ njn{ϟ~眫T?O 3e3j >/8@0 r]8"7Ps; N *3q|b\`;x?X[0OA@ oxRF&kLuG׾{W׾t1HBut@ 73ϻFUq.p;ߘ8) 1VW1l /Oj޽8Ms(96Ț &[[wj&Έ떳sO~20h+zhd=_n.{ɭ\bmdb*l)/[?( ms\Smu=TC#[!:m"qI}sUT>pIע sb%tƫjK>t#%lL}=6ΒOg|Sl }> N,AC扤܌)uR4AuҪ7W4FOWt)Y0!\oHznL9rgI7*xL<]f̅Kwll$y8PZ&4+QPP"oi0J2 I.(7;ÿy!RceSPEo}4#E}0~>WVțg5Ů[G M7`pXe]Q1ja̿ZjCȴ5 o =UPlFRڳ:Z_OF$7LaevN;3V/ KE HLX:6vhFe/ZVFZec`|׿;|b~KaCR{pG}^ &.=6niMB4/_<;,KJC&>NMLzt20ffjqǿāXj A/zi I^R7l0X{GQf" ?SgOAPI駞yCK{2s D:h(;ChS@M#h$ Hgp+V~O8Qɛ&tTRBxyu}f vkK{%=*>aq2 ɄcH.lg[*zw ;ZTF<46L1"4uGXQNͲ*`!S^*fG}8J:;*Č}En ە]bUz ^%g21VAKϤek5$?j]*6Ѡ U* UpYAա_"@ql(Sわ>pKDdgfzaJk rОgM"MlN*)6 m߹ 0hl77LiW[Xkp嫗 e{>-V)h<,uT>!I8' ٹP)huGq\siR_Oĩ7>4=1t9}QlBEOT]Ҝ1,7&T֨3\ )At5 qc8_|@/P,maoDt&ZW~#$wsK)r Kk߆L~׎W,HdB8n!QgVy׮K-j*=z] "tPNBrf;p椊TA6,fi6o+(y>!d-:D6 @ޝe/ 6Ȩ@iP>6%@̘˛9 j_Ml5zs̢M܈hhF[cf7i\Iv'EE?oWd'N2th8sh}o{sź1LXѵO/ c-QX/zM2#>=|)JwXic-KܘnC\d,*|K,ymI5ޏqVLWM "`>"aeD0J``) þNuGUTԬ[<322=30%F< s y j'|:Ul EagҔ#2(WHupZ7KZzm/8+)Jl5qo w ,+P&k3릃MXXdJ}&]quW2!XcpںnJ|A&?%Ź*Nȕ;VQd Wpeb2aw-)d ^iq.0emD7F CϋPd)<-_k#Flm`$Ih>Bv&C^%љ A7h')!b7._ `3)Ғ1AMJz7?;8?5?ןFNqB~fBA &PlmM7 2f_7n߹Kvxj55KT=|AR5&!˛2(TΣ|rG\(gTܾڡqſO=d  K:˿wuG~b8]J䓿{t2)_@2gM p67q}U83;?xٵs -,.?ϡB2Td%84H;!+uzx_4R%Z Axꩧ>OA#6rRpF܍2raދ Ӆ &6V#R[5ˤF;{^[ϮeS?eҠ'Sɕly[Ev<> Mn[߭.\$xK[7^9N~:F.=̳̠`15HG'+vlVEԹpab7MvJ\ iUq)鏝 p su 猯vɡ;u.{|B6Q 4P&| cU^n~ IYuOɐݷ~\S7x퀌1){8$=ϛ<yX S1eRM}V;MFjk{t˃(j'0dIc1M dmvęoXߨqo~WVcP= A뗿pl',(`HtI@c\<1Ej`-o1޳gf"&n\vv0A o 8_W>, < ~\azATp`/J[(cr)fX7a"ێ*oٻc^Zr\_#74g}ӯ{vS]^ڶ=-Vcfn]wG?Co@9Fy >~_ݱslEx=a->3qquoABjNt&#oB{{5mivujj$;G]ʹ5ĒA&}O*N10/o:϶LJ#,'򿓧h_~sҊEk~}J[;c}:QW გ -UߚLW&QB q_\L\j8؍\&Pg :6rFV1}\2-¤8>G$evʛ:V[9nN0eܓиO"5-bF!oq1(AR0E[Bh<Vdϛ!Y/o2NCt0:o֓eH_͜26S&&3'Y9]8h}v2,;ؒKF4HQ%\\YI湊0CK2ԉ]2pJڅ++kjZmGo䍮Jt^<5Q_6$!"~hĔ7tMƤO|;O~D.x*8.Gquek\YjL&u,pؔa%|ߨ]|7^y?'g_Foyg=v Öj=z]ؾ}8/K4]w`C;aɄsn}e=44 _k@`N:1"vGtUѷp0#9s<{ vu^m>YRl0k'*5ѳ򿡳>1hɵ2'|HUoS|< Z>QMCi?nge gclFf>uLfOTU@ƮOdSӀm`t8=Ђry[=^q}}( vN G;d`6s:p60kA335ީdž(c.b6Y'iTL%͟gU 褳UR!n)INFxnJL69|tЀg#`-&Bx}vrTpaY-36*AJ|Ld>Vڴu_uFPzE81YF[0%&1&SPkeS|m͓ v$3ސ.45Hrܠ.DiCqu)q'% &eS[FZcO6qfØ!(30h*T-)QE\';ԵҎ,MH; ZJ$tGK6l+@vhϣ< 7ɯǧ?g_ʗ~Z˗/ٲ|k_gMkd8TkS 1qd<ղ?3 %7ƽGO!H48bfFSuph 7Ú!.vjn??yPŹ%pQn4yoVֽVp.#bvnz#+'8 ЀK!ڳk7a= . C?xzn^u}Jh}DmdSkHM\ړyK( 0=mWĖO9K>C¦0RW&3V[M ȨpP(s4&;]w߃ղ qYs7}ޓ;/? ΕEcgVOuĸ1o+<;VxY#?3J"Xl3ՓbVC)yOr\' KƵ:5=&2Sh>4 HsT:ǷQd^G=@lii Pl!m:Unpq7|g~6[5sqZQBT\50I4C0D5l ;9.KUt-(:yTL-[r:V0p96()ĕ7BQ G&ư/xV,IB?TG[̨P=٩4!#Aq\d؆rִYg"*HT{"x-`-]}gl@cL,Q}$sNJJ{掜l+jQi&R%UhS-֔uўS=ke/v=u ruyH{"oөZ 4R/]TvLTT v}Jq lEo@zM鲘\0&v58Q/f\epw>eH|Z7JɎ p^oyH*G=pgzj3)o,33m3~hpgsgX@1FPtVm_ܧ=~O_1Dp'}ahB+6_W ]+fr .\x7HAMpiRa-~+>@K^r =:GU\ph1KJ|wyJ٧:q6 ޱc{O4RA\ՒmB&Q&dTӂ#PtHNOmWGƷƈ{+AO넷nҔukFݮKN0穦A3UxnF^Q2{HIޟ? GwCsaZ8t O'ƺҕ5#9dz6S0)_ZRn*U.߇ch0'g .f7UhoelFwwZlzD%HRXr$BlO,ԗH }|=&|AI쫚VPSp$ՉIe\\+z ee刱"N$˟ =phV+tI9o˞Rff$2KfHhu6b*nw;=v|˭C%Ҙ?UBm sav7J̩5)2A{Wxɋ.}_A`ҎŸss =}~L..g_NiMp~>]\\8~z{~?w!u6~&b>(Ñ}x>P 7:t-"8Ν; ?W?C?B h]nnkD6l{l N97"[cSfU-Ay`V<#ngFn-ݮѴXb;4>.ŋ?$['68¿fujZ)YoE7K\\\)~SdAPYM,ē(ߵ,VVi,&|x$# Mݸ1۾S$k䩑 \0Sca jdxY6d.O#M\?]_n+XC%KP5>/TS{}z-yAjس-caRL\'8F=%yNLfy$zXϋmMR= 'glwJX[L7^'ߩk-l[8Y;d~euaf\ L'$K0WLɏiER{LׁAH!딫ljq_1o) m:hUkg;gGơL"}"B%6p }˗k0m\aK IRz 2}%5uIX L1VL&cLrS?-/{o ~/?Ȓ-:~v3z^3G\U?͇>yN2m]4&(L\XXWN|]Vo}L/ ^/C991!b6jA"FٳgwI7pwXg<}Ms3@niî*f;36/k)I %ܱ,dUm}[9%{{!#p7-3IwIh?+APE!۱^ۘb.JK=isق$;k0bA5%UJb:]K7de"O`-eRX[)޳{MYcnw*1N l&v!pAt˕^p"턐K DH'](&`쟍\QXlwɴ\65 |="uXKm bLX R|MPE#)Ӷ>FZf 2z&[tgP#R˰U DM`}12N̩ &=]4qq@̦k0$1SV #NJqbIYdso[-a1I<:GA zζ ;rn$'CRd +g\vBB@)ٗX~k}MٚgKFQݝˍzAr_TQԗwGQ)/x+O>:T;{0 Јx'?g~;>wDŽDQar"_w㵗/ѕ+WlŃN,j=+⋿?39܄>;E}Hȡ*O=0ޘEݸCUH3CGyog7l5O꾴9YO+2MMaWډ9Z. H]ܷܿfXЄ =Z@Os(D/VBK'Dck.iEVPgb[Fx,V^J@,,Kqe"t),Xoyj ="X/K(h14FPe hX-6oȋ8g-E-IpDVbH,=b Jk1l4D+0~=g;D-۹C.,FQR&3`Qw1Z8EAT \_ZP!i%8oꗬ7[t)r+NmL)G]EHM } Ta28a`_.!eEjeCJq7b\b.\{4."Sb=Jͣ[I_U>!TAȰ gJƛn=Z"RwY`{ɪZ{WwʻTߪG>o秞]UvMoQ\Uu]C4vyKuPVXdw` '<'wo}$;S3.4$qZ[Ի|6z\&"6x ! asSyH؈mL0OkR6Z V*x7,YQݙ(ګDܳϤ |ʀvԷ_Myg?b")-c;?5yKPk>6FD5ark!*BAMzɟGuUϖ^QD`~<)( jڸuO5W_VEy-)+lafW(%wE(k7T&3K]kj03{L}Y)Yr3|@8)NVY[=!`X7R& I]c?+  2pw÷.EL`Ӣ$6sED|]`>7qݲcNa슼VO"R`A񈘋s#n81ei aFQb,G %νZJK34-!ETSf$0!pCp`(f}]z,r8,'aܙGWxi1E4-'Ɏ)80I(2aw+QlN6>RLv,Y*h3L,Q@\]rwK0Z-*o?aZ09#¯}_7Khڣ|w&b9i1{5G}}{ݭRjs5y7lW%`?>W ;|,Ed67nTuv$Z*0iv*Q'M?zM=H×}~;2oIW51<%oA~B/&&i->Lɥ=eֳ٢xʫ&@Cl@&#? 0bvĚDN4ѱ1,b_!&^ɔvHt )9#5x& Ox eX??Zk"{٬pum|=s}[!a V o?~ N?^r6.ӬM-ʯOy)Qɟqs),$--7tӍCԮ̬FՇd /}鯥|,]ҩ(oR};MMhjU_8YͮY^n/춰Ms#-T*ʢ|LR՞[m݆Ű\`tmt7jv>%o )%_w${몝};G*yaXoq=UV)V'@-l\!∲ynjpi}h~z#}1N64ɡ7h'т9O,ȺC20 e{6SWa!h[SP=rXF*jv$9͇Z(ݨE2SFP7GMuM͇ޑpgzkBW!`7bplw?<Yav|îBOaCbśթҥUZjZr&(W}x?γ>K?䡇:QǀvFymBD^p(frL"EaJEbcB}-o)J9e%"oek-fϥz#tY?QB  uM#+bYAN l k+|t}hVH'l~qJ0v+OñV&/Y3ܻͯ6e$#.F!Q7NLg]&VMtᡚ\R JRdOk[ ukwwM&aFWD!XYUx=ZHeׂr2x=MUDyK:IS8=SZ\ bq[1%ytmlgHQN:ٯQdaD\C’ kBO0Ɲ3[RLnih aԸ 4z%M W`'}_.D4ZRpt>]?X#~ɯ\3 1Fv_O)t @9dGW5]5\G~mj[#Pw7e~MovHFjmf|9:<2tYvx@k8**P`vk^$oE(,KVA͎uO 8rQ+cܡRгzc XFqĜIrBeXq,( uM Z{y`ř}9n0BEʭlC<*d6G!бU}Ϫdiq;u?XfnA]݅wWA3i^н#ѥQM!Sn+ͳ K]xY )u|y}"o~>߫9[ZZnS Og32oxL)nf@R?)qm@3Wv@ZT2 ZqrU@2Bd,@H` q4 1u '|ċR]q4A0"l"4 i.B,m2%<2H8Kw)M]] :`.>*64ěnqUan=D1@2{W YOʨth!G?.Cl+7rQ5Mā1-w] yP&20^YHݼD[MT%Ϋ\5ТOp 7w`L.m 6A/YUB{&nО}gwèE2 --`A:&\eCBRs؝0̲n9uOqY=:"ܩ?iS3x[hrAv:]g#Br]L@@zh3Q0U G VukMA3b_~5RO6CW},5*);r}(zͷIgZyi3h \E92tٝD8|+hsף'/,kVl\GNl 0yRot֧g&>!4K.:+I&yؚƇK糛Wo2J]% zI-OrPi0H dū)Ôd`/Ѐl/CLC#)$,V㈀WZ<)$Ɇy a4 㰷?M,XA,ƷM}$f4(L01ˮt~}o'~~mgT__λu+ӟTevS7APݙ^ n hN9::xzop zV}7\GsVȢۋD%@]S/2p0ZboUA#BFZva6k`Jܟz p5l{$ w=l-21rX9Sw0-t˗ĮMTvU`iYj^FY2a7܀VRe %^9u֜hwDy$]*sGWe3cRK8/U7op$CIK\֌/_0@ㆹ-u/_JNtbM'GvF ?<|(\ >} AVE] D z3 0a8!wtXʹI5a؏awA !0 #-.\{{)b3'!P*= "Z!:”uMǁM7Y$]5@ڧ>'3z<Mow|: c)mܽDbxk$274 CTq rG>9s"B?fAJ|t r ިYb fHRەwJ0rY)g4g%CP7Qܜ ]~E}&.1a@ Y/TԹnJzAEZf+b4%OƺG-)3!q* zFO*vxsVJQ\fW83 wSZu*O?E4  k 7v [̦~$#gbmmĮǩ^5ލƴQ&f- `mgw>[΄Ҧ8~/zuyS=1Ǜ!?w3dzk7#ES2h3I6zVTNQ> %P+xⰀU`||YGY=qW< Q Yupd,] !.>XɣK{ ;iy*ę(/]{J|DZ%Qugq@S\^F  cŐ`|w1)Ɖh pp8ricK#8ĈhbDL! 1!1=J 꿡D'(,3H4fjS,.|s.V<[~f٫GWxO5y.b&Pyl3e > 5qoHکqMff|Ȧ78Q `-XI,]HS+1_#>+TҼzz4QAFMJِ gVޛ\z7BbL>q6zߘR㠖EV*p rH9)r X t!tSC4뙲vxe tezBQ 2+CѮ˼\ xJ=Af\v#~㪼6k&s~*=]٨F-ErViJɤb׊5P׿iA}jTkI)X "[IZ[͞c̿Ӂ[u"P gڷxڂx[}df8#F5mk&P@Efz)RaK3"۷bT+ӓ@R[“9ҷ쑅]Ա0 Xtb J{cu}t30EiJX!|| WiLJi wY<]3\8H)1YfZ*9p(FmF($qXH ~D:5q C 'XNO Z,f3<.9-,4CFc&sVflWAϫk4S#<:j;mWΫxiCYS]Rۿ|@""M8{k4Of$}K!Ӄefv>?:=׉vL&R*;̦xXqQLke6*j}w]nRwA%e(F2q&>["r;eb ]n.2AAE& 1v?m*!}BH$6e~k âxb>zP3A 7H~[5uFDaԬ5cl>=?c#ot#G(CXD b 2oȌievI90YF[lJX}z>SYM9o/:N&{}WAec=~\ QCS~ւ焍QlskI{ l ٜmnXl]yȧȗ.YX!L1]^rE|SUR/K/gY^y黚?/+(EkD! 8Č %q!|}`Ж$Ki\qzHqdAca 4J^ǵ' J1F<+~%i;2p:rOUSw>?v-{.vz2va0n0rT>ۀl-m)Ko J7*.҆فL1JDy}`V]fḵ܎Y~drrT47PTH gqE Y P1tV QZSHit=--./֢n!fE kM-{E!Chܝx%bb,x>>}Q#xRPrCo,82%=MȊډ Bn.lʧ %V-C9McЫ0V{k Z=odމ٥jHjkΙ9E1U_uS>sEmc)vomREW0>ؔˤ;_Q1օTC0o=TI`ڛK$ IENDB`micropython-1.12/logo/vector-logo-2-BW.svg000066400000000000000000001101601357706137100204070ustar00rootroot00000000000000 image/svg+xml micropython-1.12/logo/vector-logo-2.png000066400000000000000000002650071357706137100201010ustar00rootroot00000000000000PNG  IHDRxsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATxwUf` D`]+kx1<氮ia5 E\E@APQ$03fCUwUup/Nszꔱ""";p,phӀpz""Q(_Ƙ@$Ͷ}sCxR Hf1{iZ l ~F"")rWpk\ED$r1ƜLǩ@Sc;żn$P."ƘׁS i`\V?cvEDs;! 7`1f 5_n\DD)1 9]i i'""KHvGx*[k9cQ(Ɂ@>RJk#ȮJ\D$dƘB \bGYkDDDvE ""!3<\cȐ!x4kGƍYr%/o/d,^m=[2dF\D$DƘn8/S^=͛7c?kL'""S( 1f0`׿~az6m`֭ɚ[k?j0D\D$ƘCqnJQQr ]w5j}7|ÑGW@OkEDf L=K.5*d=P~dM|ٍh 9Ғَ!"R(S]+{&,X^zeK:{fZn8 8;ER< fu,bWH. e /((7=P`cm߹S`990 98/ˌ17x.R."ć@a5kdќqO,Ʋeԩ;v$\_m-Kv~o~\OTkZ) 16 .yzx뭷B[f 1sx 9'Ƙ""9P."qT7nɓ9ꨣBRb}MuƘzƘ\O]S d[}DRs$pEv[fҤIt%Y%שST0 ..2Y0Ƙbkm!'"S)1>0h]&M>}z@ŋM|br0HhT""[Iȋ;vl$9@vpIvE1ED- #UFE~BUz7nįߚcݻ7wݺu1c={6Ǐg̙%%^`1 k&_&*"1*_1e !?\sMH3r/`|c gqz*G}4M6M{ի4i/cƌq;ڳ2H)(U!Csυ4#Ǝ)ѹ{G堃xwy. i~(ՔmۖÇ5O{4jԈ#F0cƌ93g7t5kLcL r,cnmaȑ4h YxbO_%\BA?ԪU[o?-ZjZJT; ""Y0JkgB4i|0ǏqƁ̥k׮L8 jv1@& "#)ɂ1*Ɏу3fPVg… k\ׯ'Ndv xV0uT Ė-[5 GLD dS\?r'}e„ rpV_}U5h'6ED2w.&O?8܄v1aׯŒ~u1jr1&ij'*_ɐ1s EEE|tQXVZqPAASLC qf*))G̛7/Y+9' h\D$Ƙ$ ^zi9kN^{m9@aa!{o&co=d38&ѱ hѢv(K~>}z={O>IU#<)S$;|vbVDD<2K@QOk׮s=@pcIv0""r@ڵKÜKF|ɔ^tlիNvTcaGDo ""c$;~yE~g}6c=/<6١Z"";Քx`=xsΥ[n!ȻT7 jҤ sIwرcM4aƍZ{@sVED9/فAE>|wI=c 5kc.K "".cZIꪫBM:tz!ƛO>9߄5|ED%c߀fwؑE!$R:uŋyݻwo{=իYf6mJYYYß[k{='?h\DĽ+guVrG&/&L| hԨ;vLvxcLIB\DcLw`d:g?ɓ'gѤI\Oɵݻ';d#CoED9=ف:лw0#8;\Oœ}My=!"'rwJv V]rP(G\D$Coߞ=kԹsgjժ!aED/ ""%x0l$ np9E\D$ sRAw k""~Q(IByn(HuP."Z7]ٺukڷol:gXBHjI듵J;iVcR6r#(M(#yE\D$ 幓|la)"U ""%\)/,,[naEʹX)W(P."ZDok׎°"EQ(IcS'K.W˜_ED 0칧v%HuP."\䧕R(F\D$5 幥WDQ(IN+b\5"WEDKۡCMY$$[&Z)P."\B֭\$֭[5Q(P."\•r[vm "+rH P&yE\D$Y^!qEQ(I;pXc 幷nݺtMV1z""Qci<4JtAz8&tEDWDdd) xG jm۶qI'z>>`L:ڵk{>̞=ŋӠA:uĹKn<4z:NDP(]1;΅er5/Ėpgg+̚5?r2֯_GW|'r%K'=rqy^_r%GqK.vYK3aCD/ "Rccb?eȑU駟N1c:t(yfn,f7}{KለD\D-cL-}yԩS}̙3Yre,YE]uߣGfƌYsS/"EZ2Lѿ_{2|_eeĉ޻m%﫯:~2_:K "Rco5̙3}gѢEJ1ϟ/[1Ǐ?/fN5?)Hbi L9Δ)S|gѢEy>b|7?R."ՑBTƘB%M}nzhwPeG}{}ceΜZ)P."aX\ !mmƴi2o 7nܘ?}'>Tlݺ5]GFϟ?{,^7&;.鈈F\Dcx(L)pd(aqoF{VZŔ)S7ocƌ8Nm۶튊2e 'NK/u=ɓ'nI&:OqQFi\xvmiS*SN/Nz^NmݨQFv#G䮻裏fvmWm[Z*]e "ܵIW͸$NQQk׮n̷A߲e [w}#Lfxb:w\.]{8YN֮]K͚5+i&ڴiv œN:cǦlӴiSvܙɟCϴR."Q<pnyUW+TO >wܙvnԩSΝ;lӼy:vH-衇;zU9@zҥKyA{뭷Rr1(JD$ "1x9Oz KXIߝw͛L^z}Ѥn*[3rgVz﨣N:UOˬYR wioMWO^/1&m1EDrA\DՃ@պ=c^ z R{}vZ/SNYfI :J}9rd\s W^,...fU6i$3fO;hJnt+c pJ""R(c9s8?̓v5Ofݺuw}^SIQQmSVVƃ>H&M޽;W\q~)joT޷o_n\~va0`vZvg3H; rAm3j(ƫEDv_b|SJcN7o)׭[Yf瞙-ήZ.]j*Wc{׹:t(^xa`z)ynF;0f̘Aݻ7֭_W箻r3u9/fzG@km_ Bc̝ ^y7r7][R]ҹ{2mڴ%!< 2uC9c ڴwrJuK@ZjdZln͚5^zUэD$T""yps*+QIWRHɯ-ZI'֭[LkJ*~!-R_رc3]w]`ذar0(H>q-fo}`cN>gQ ]0`ڵhLlða2>߭iӦ1n8s_M\D1f]Z-' 6z3o#_+TQF |In֔rǏOx7?pN}z9<9db~^:mۿF}>Kڳ&"/H| s1Ux+c0k,Ζ-n/McȐ!/m Áwy}v *w)K3,cLNVE$1 8V&+M/iw}kذ!\p]v;wNB~;3{ֆN;4~}vN;4Əm2/˼OkOBD1ZxP,%8e,s]1r%pҪUoٲy1zhFv;C7k/ƌC׮]˭;vpoj[&R2p*"rcL^ҭܞ3 +,~vهtؑN:ѩS'//YdI %'cĈwyoݺu < &jxL%VOg{SzZmXED|P."SU+n ^a<7.~qs_:,,Y Sy}Z6ڵOɞ.(K?mr\ xhe5m4g IDAT }{ĈS ȣ8;+VE$R1̀ؤ90e0VWଘ㲏Rq%pWdt!*M5jÇgΜ9-Ĺw/mc<Wy &"=rcPMM\4m.enGapޢc=caM6ԬYJm۶rJ.]?3<ƍ3i$(lw."rcTn<3R.о?[J+&सˀGqK迠-[Ү];V\O?qw\}ˬ#&"r cn"6~ls0/s#cޏew!ˋ8WJr͟Ip,z;ED${SD//$ 8ӵI78H}fV1 ?ycLwQ]VE$&_4uӾ% {j~͸_nVy߭8K^>+&U!o?bcXPsEodG+"p 視v? \Sb⇆߀<-󞉳j~OAQ84T""S(1ߐ0M8s:ٕXs.p-^g`;ol Ǽc$9HT""`Y vӶ^c~n:-S5iΫ@׀ 箘S\ /Endt?2`wkdG\Dr+,+unڕ>Yn(ǹx˸%:=_Bvy<=8Z;)""S(3 ەp.lhv.cg5n.c\w),6~} @w<~nEDr6<h:JٴKm;/c1o9`0gpۮ~X譹HvE$1q[tbOlg8t"3=pJI&܉5?CMU{HT""9exmZO%*+ù1`2Bz\8:(%k wim]z"s]҇ʥ+*BXjkڥk]&cݮGہr PޠԍiW+#s=c&{/XDT()H<x+]q:\/l&e$A"= "4OeKW_Ƽ)#EͼP((Hмdžr%UMIGL:Be$nje IM\DP."1JyP+ٖt˘nȧ1%aCvJ  jz9EALVjùM: Z)R( zBˊݬ*6Fbx~"1="" r Rc'TZ)뒎\YHb}/"S( ypԮ"?Y,{JxP."AʋIOy{񯣰:iGuTgcMJ@\D9/"lLjnϷ1ݎCVE$p "$O\Kr9a cZXPW "8r P^\@ijIFu\} y%).5r BS(Sʡ/#q"/%3P((Hxi\;>窤Ce$S3qKWYkwz>KD#rJ+~Ǿ鈕tlx~|I3Z" r+剞Wη\2~C* MM\DBP."Q;Jy<ByEzhaBDBD/+չ3˜q? oH8E$2jRy+^$13_vBs>DD|ו AD%r W$}g+I:cKp,;_[kPq!bSD$HJXjMaWf | %$?uӝf^3ga{fED\JiosuA=I%Ks*]Z6BUW2 V}Ü,?%+{s7BZ3M7'ˠ_{wO>Ig"R_@ZH1S_&?E$'E$lq}:Ƽ&C$A1Ѱr*ȅnjD||%L>XIJ+HN\D橮8u'} ?nLWuU; f>1MGqy]DZ)rQ`rg;vI33յeܨJbRY%ΉoR$95I|k1ך]7*VE$T5^yc.Wcvk)G>>OʞևU[ډh~7,,Y옾쨒;,\Ra= "3 " #4~S\Wf*}se5iےG3F}r3Lz&},(µ|NtBBKf?XNڠKYWl!uuX_ކ)~ p8yBB^ 4X,u+6P5(\E{*stg+t|b2/gwY=,֮6E$W\o?m'{ IRדCL(zE;UVŽԟwNjU̹Br6:篆+ǧ=˟utoK\DrZkg3|@ :kiWlH|n+Ao*q34U-~{n^|p&pEܟ""P(\ 5 /Oud#~f{'՘^>ԯ_; '}OU(̓D$gc>q{o¹Vtk\b=NAɞݟ-]u3gGc)n&or' w|w9 mKCY Ny]s S(+"s*_־n/9?  |}Klhӄգg-' k\DrN+"7yiz ֪AɊvPcu[4L2fDvx~x?O: t*k7FBD-OwmMEM2-pPRxEH0E$RcC)ʵp0xo8lBhP=](?Uigipqv\IC(Z,DDT Sg_%5ޮy-;RL?0G?y#hF`n6 h\D"ZsNK~s(wu[H~' Gd{_G{!qG\D"Z;s۠[gط3 A=_šјgOo&o2n.{(]ٌv^Q((8[࣑бu4Hq;)I*<3km|(HdŔ|2?àQ2.=ydm3<+>sf86`nyRƀ2UO." =E$Ҭx=o28f\WNojg0f=3uﯙb^JH9cwr< hmƹk hg x#H()/8'6tB88 C?`p*r>kAGDo ""Ic7l:Rt G?/{X*o+OӅm@{k{ DC`7wwgļ%xD!o#r1}qJYN}Gc_%UW!zA<ֻjwMw9($ai-wKW~及+UpHģ_tkf""r)ι@+}̣ж'<ւ'P3U؎J0i)pws BHƘ}W uk@qA@-@1ΣPlG3l ڔBQIU(T[eHJkf"",rnƇ*w@8%I[} XE*O$% R`󁷂HT""RYsJhp_i5*O܏\~XWD0z^ KWܖ/& M=*v[ WDD*s ~$ǂ<o?\\D1Ɣ5r=B WKqnSہڕMED$'R."RՖ\O k qW W'*R H\D,a \<]XFof!";}ED@Byb8  {k/8ؾ#q\ X_d\`ED"A5""q1}uS8;AJuKVuë3j e{0ʯG[k]*"EDcN-N]7{7 xs"/KpXk{8H\D%a(y^w\EfhˬS% ?{Eoߘ /{ ""UMMnKT<&f Xn`a%'I"&TDAQ`<&cœsVtTTT$"bB $ ߏf{g;Tu.Pu35=z1 (i;+zUX,zAD'%A`&fmBdBq4_zUpgQ X,ŒAD:w|XMI3D%]/)gַY]nǼxAܑ!-cEb"xm2e>CTttȄϨ1.zU_w۔oX,5;b(9d)_ p7{oz qtf팚3̞iTlD-h4Ȕ:Y}=X,XQnX6xDb$m̜ {A[~P9)LЫ:q1)rGD@w`2PD:3>X,+eFDz%m'Q|6gof'߃= \;cb@DE`y }p;p4ѫ|BD Ed_yvXeXreCI]Pf%~J mS4 ϡ3q _'%"ƿN萻gRZ,)X,$"`ڛ9;v"nB0M37I̞I{Ę/֫4N""ǐ҅uD8%[, LT3{͆캃~&+$F>|ADdBEK!"2oX;CPX7P9 (`ϯva5 i  4qPPXT.EëE8OKŢe@D6ҩ[T^ ;!e7еN^c)@0wK1ie]1pvgAՊjs8f!j*C3eso/9k[EMqHEbX6FiHvuuFj׊wWRJ4j\Y7\'|1~ԯZ}dBTNANyTȟPIϡ /)yYYó b1rŲ#"\Hzmezti 9zѓc|;6m_=:v/V "R_D`\ J|OM, q2wZ Q31:i"R˰X,""Q(]A%8&"pNsPF8܇t&1j26nי@SCYǢfX,yĊr "@`WOљT/ %Ч;]:nrV⠃c;EX~ $vr@u\f=׍!7?P5(F!"[L:M~TܡUق ]:+-cER H1+*Bc]`L5P -rFҤ\ٟPwM3ikMx[ KO"w4RŠg&INyny6<_wg~""P '!? 5h3vƣq.KaJu$jX41KF"r)#pЙt/wCMD^2yn>sw^|pt[smi- xA'˚i03xȾ"2`cSUdu( 7NčgǑ+͒5EZ,XXQn) 5{<?U`\#"yˡ\8 u"N2O'~PH1&HiM=&I `~fWO&"PMz8̮"L*¼bg]@ٯ:RDqbKhMf]"c""7ֿ4(SFkxXǟRAsS^=ۯ;:9 C5PYD(g|\gG`()*T6;;}! ~&"bTŊr%$`KRl{*"VwrmVz3OBG|}:qKQfϺny+ xLjzH;yf8 >@@MP7r5z'3[WnXbEŒDq3*_MP]KyEDvC~i ; Ǽfs趟yfd}Xc ]='N<{F+8$!"|N8:7 aXHM :Ork5cߎIDjK2"P3%8T\8ΨU/IO3waJxbd{8Tz[.i+qW!6 Y;y)" P 'GcQ) a0n*42`Bu7bYbI!ȷ@lQbJy YϏ,CO{o`̠lj&F`+ӝ^-  <<h #ғ;Ob2qWIzĠm. qW7GD. Xҧp2jDqS̄oŷ@m(XKE@8ݩ*g>[;tf^xy?qb6_D=JbT x?[vEpa0dhx+;kN+i8~.>J\̝,GQLΩ3kO*З#E_W3)VzJQ902h~)3ۼ-tÁWЌU= %\0ug ŭ@KϧѻƔ *7*'n6 -E EL]D]@G .`fX VԞN THئ!.NK[`_5\."GeƋX,5V[,p#q]QQڦ1>J;+Fc^DnFIiJ*}τo׻Thk0W<2t%B[SfwXm~ݛr4Kf5'Qy wNb-ɈK-[S`СP4 KICTLJ^;E˓jR!wMC-+ pDJ %Q*) 4r}wX&Wsh <L=3K(Xsp*ar.\p aw`!"fs "-t(p_Pܡs6"tp8oy_iýP."_jh_^T;m Px=wGx&1C>TRpMz8nL(yajDsƒqݺsIR85߀y;b`Epa-ԜuwQ98/rMT "ǡVY}hT(ȸؚB.YW29GM͚J3;5=m,]W:p13C3Rx@DZ,5Ų.!"̀cu+"/CAA|Z@ ^,~:4 Q'*a"r*|uk_Cx=QCe%ʹ5H^  (owb9ٶ_;yXx;P: \A B0\:WO7Dqƞ[PWxKQU )-E8qֱM- V[,fBٽ6*[U>9ID>P$v9N"qH +"Ehzgo꩝-^ҫ[p XvT~pA۲B,MB]r遚F~E],Er=TW@zO6킲 +"g½ "L`4% I Ma |uAڟ A*m쥨/ }̤q'"K<(X[G q5Q=ܝ]T\JK9OD|wM+u8D@a;1>qGu{$4#̱uEy;nab[GL&0q*>#hy 36j򟼿{ IDAT:M/j%4;H yH0E>|UN  Tڦ5eڣ&:KD9M'A^+T~^i>bzؿ_EP/b7u0.3(QPmPs]|is}/iI=gg۶ J#UxzQa] m7ՆPqKrE-Q8J`8n<-;I[A |+"wx@gط`:K]1yW3y1oSGo|`Γ88QLpH΍V1u pW;06hҰ?LԬAg'ytw;Wn짿KYE4_*T|)QVW5wat85`6uOEPߨl{} a0K`Ee@DE>5sZmfA}tܧ^>ymrwC>MV>-öX'*xkD!D_VU79;0m+-Ql=1ݺulR?>)`_sV-x+a!3>%GH'q`$Ɗr:G=;`Q#4%R.λon{r=mE :L^?\E\sڳr̀^ gךSNy۶Xp.>(AWki \gÙoƋD]q>tm@kVu=NWbIHAuwb1EDڋȭlTJ%>Z+q )R)O[1jmSz2MxDϽbOB4@qk{j¶b$04`(YҮ:5ln.󅫠7, ?47@G [׺. ZՎ}zcm$:uiį|1rV7-~W)e9ۦ^\yN 1 é›!Vqaz~ MsSz'[VbSJfLtM\nS=6|֯C&ǣ~DC[y <30i5b+)xDS92xs!5<^T8L] "O97 v.«)Aq=W&;KazФC:ZeT~nye3sA}ԭ9q;Lw>xd:|sLBD}YSt+-5#"?ƞx:6xz!uC bim1s9<22#2u'W `nH]`P8`:EKO~a]+=_G{C'EWy%s(Ч,^OQ/$KuR؍su|ϥ %Y.(bIQuwbFD PyQllUhj*b&8 / +긶TCSj4%hU@;FZg̈́;Agpp۷h7 GY.1ɽ¾eOs9]#t2NG*ιuz2j:w?1$е_Du iF=g9\<9P\  H]v4l%nag8pr#D8&?K"((D#vo:? 5a)p,Jl  Ƴnv1Iy-/s4ϩ 6vc9Y|y \v2s,>1:ttyJ&Wj( NVU(>6=Q!+قOfl8]m { 64w<{]0<0TB~^-u7 oUshoqWt~˲2VFY:ѫ&-v L?”Jɡ;Υ@zE89X*S]bI PwFe8u fGiQ5uu*tS >1ƾRXO[ֻV%һl`LNAYyHϿY~imǽ0`^D!:>AnP/}>>'ueazә4Mw~m{O^}F@Gůr#ȷ^BGzrq>S= b: BVJQC_!\T:$ZJ u;,_' PĹPɈ8KEm̹C;}st%cofU!a:quB,01nlCTx:zÈo00$:;^wNPꎵ0cX{Y,ؘrKQ3wktڐAL#$5IӤ`E%KQ "iʑ܈p|\ruiQ>=Z΄${Faąpp*Obe/}ap@wO O_V|nkܫ?VE0{3*AE,˝𕳀K{`#B >v `ď0dL1)2;~<ۑ, EgKV笰2 t^V[tƣPJPS{w&i(wGsq*yl$7_k 7WKûsj5s-LCoߣ>Qb?=IEx2js!3ʲry!B:6 L_ޯ`l"Q.cg/!4H%+-d`SʇF(pfAu*R@ǁX]wq iuǢ-}my^Z? wӧ^##=uWgd-΍3>j2;>o<<8~M/@Tf$/WB\V[r\rIQ?+Zڒ/W<C`&': 7gw󈚸;G)aްfhԨ~ηRSQ#%!1L~ZPz]: Z ;R)W5MDyKԀМ!.w"w L)!$. ЊrKNܒD)p>kQYG,B[銇C?Q\o~RBSʷ+:Ar =3O\oR;?xBjO U%,N^6k9`U|; ~ָ ءYW/hsNh@w<O(W ]Ά~2x9`/3oquz6|ŒS(`m"Ey<Ж}?0dx-l'vjpuu\[-?W}cwGFp\ U=կ [n [x8x]O!;)z9*'0 &ݴB ޚ<cBԄhim뎇Bxo*wcLb?`\μزbܻO׀Ж Axd}9 ܿr0tiIe[w'(MG۝eWP_7Re󰔆 / >׿=:=Fi!x) _~WBSB:Bۺ!%S۹ XSb&*V[rE7>^ #\g/ Жɑnt5;&=EBMeW\7zwk͇0O(Ӿ8^MEyEIJBN ? ^-6| 5ֽbqu1qw`硗4jXQnIhbˁZqeM mrʙSip^OL,qBS[< Iw LZ .ffLB̦Pq~;>hbܝ U(+-%Ai!xDyMmxYN+;CQCS \C{#~uaLdR0^7Z)LO>{]wP^ ly.8hCB{t@Sݢ16|ŒS(X|xr jKXvCׄЖgG,3_=ĝN܉b s:]σ@-*~2l0r$Ӿ(4M^"(TJ`fUg)0e9LZ5T{i%5O q!7 °N%XQnD9m3Wdkmz!0RV@9L_߁3YBR~ /Bjp>Qwsw_D`(딻mګ8NOmx<`j7&Ic8 ;W=A{ᆤΆ>)+-""?clL+^HخR/"%NhK!.tf=q.߅>{M}u IDAT~)8=ICV<\oeо)#UdԮ+Щ>jXCܭ390xR2;R8p -[VQfLϔMɍΫ;^)EwCC޸N%XQnI$ \2E^!dR+-7ǁ;H|8d[lG2q}0S~:vh r >yiϰH#H8d=O/1x0#PTr)uvuxu 7]O:喜bE%m"CW\!-Q?Qb$\S%yx/NGqWDz8*;vL7ܳqr9&Sfàz8&y7.^?"`۳M DthbQ;J(S?wo %o[zD~ݠn\;T [r8κgiț0@ 36Z/*;an\ *;CCZN-ᴝQ5,^ lׁATU.Qˤ":A4B Qը5ǫ,7Gj5@x$xqu5 a0wUoxLu'?/V[RED>DMdGab|vnp5\{0040 \ ~QZ }]{BE'J~:ဝJ2D(%) vlQ߇`!Zցqi l)_ X 5GX'?EA8?̫U^m [] 8``c-i BhRׇ"]8 :5^O 6C<]^PjŬziPCeiѝݔ_UiR m }-ᴷ=2w'L"n9E>}yյ[SExvu%\Pw&ST5Mhk%a]Cq`p0[s`?n:J9K,sgu,(M(o*pG 7;+HHَN Aӎ+΃B[ u5yh8~ h9<*"1)+!/û `T٢:)lv/ &~ElQS\e9,P*sОu|81^E,DcYcP[ܒs(M(Eŏr <3>$Q,"~-&q;IiLLLw'EU1籉0ϕEN:č`Ϝ}Ey*WtFeB};kjK9ºk %6E)pBw*~,%(#V[RCD6Bu D9@;%, cx+ّ\ť) ѵP|l,]'oO y6L%f_aҔX ]e{F-1jJ`EQ1܍J3*wÅhѾN πMi 5ޗC{lqIc":G?g4([rYNFT>I+v%h}AhKɄM7Hv )+-i.u\,)}aT8 XYI "ڨv)잛⺂S^MGC-Zs¸` ŸƧ`뾰9}"Pk^脮lrl}쀢#Kd'q<㏽W$1}x a~0:*9LdA: ũ9[AD: ~"_޹ ΂;^?қ8' ǁQҴ!pr8l.?d^)->Af]~d]_mV|Ҟ\!̜]H*t^Z.g^;9TAJ;0s\b:}rKN%MB@ JN7ytc~6P`<ߎwҥXC_GM&!qsxB1/4gp.۞펅=3oʨIHM2?j2΢< 1WZ⎗m{'ȏFߣrxk)"p",N%%[${**"quswdRf7Nwh'Zé6eH*~_yATpj(toqg٪ 9.O w fv&?S[ОЫ+ZE-A]qCW/).G[-\Zw|m{8bPPלG(Yzg[u3 N_%$*jD`E%MB繢\Cg/ `(XS< S~Nby(CCetyɄb[? sQ#$LYz^Zg7'`TNERxMU6m @ﮰ}{ؼ54 6e2YU+rS^B;j3| 5oЬ!<2YA/tT[Xܒ&oc5j}/a& vu:.8Ѣ9*) -*}[!=`pK¨tν4|C 8|ؤ4)Qhyܰz^͗lb o;saT!| OHShJ[wܿ8pϤ{C3w~hs#)"rpu-ĊrKjWS;6wEM8N셿 sَwaDԸ/ oyܞ 3X4ݱ=  ^ށ ;kKT+7Ǜ3_]4Emv:DWuBW (B[knCY#Y6H(IUи>Uw0Wz|st{Q2)ť BҠQ}xx8mSUI!ʋ3F ќonqOɴ3wx%X8Zp>'~bu>˕Ñ g 5`K0?qqK(V[$T{;f mꎯ,)rWG᮳ٱ&y>D2n?bi{LWh\ʂ90Oo`5@~,X ~ g0k5[@m<+ ^(w aSGGG] | mº%rC/Y7wUsŢ%0s80b|&MQW~tz4 ?l>?{&EO.9 II 1ÝPO1`0`F3(* LiY.f==3=}zzwfo!Чq}ZT[wSC87S<*>v3#ƼOm6ii7o ށ`}Ë駥`NIU>w W(@3!eO`BB(u+~X MjRn]wo jOky\0Bp*A!,!@K?ې''gR6J6ggË#ṫwC~ .pn*'D旸p XF6gy6rr_hX_vem[Amo^<] ϠwL&P.,2f`Z8ZXe{z !\t By(OB | "6\0>qEҽ +SQ8B hǬ*Vs}/n|9 4fK'=V\K}\Xڊ}f7s1+}o LgefuROT|}lޮ۱^{1QPBy(B| TwUo΅6ܵ󻵀ac0]**W>ð/) f@nU( ¸~e.&ѶomFw܀mAceYx Am߭^]L⵪':|=| w?7!0-|<{Z|m_4|Ncm;O t$2yT$TzPYBӀwpЫßk][aZ~-x+\{6bxu*LCOCFOň"<"u,w[G9vr+F^1mnܸ:cSn\b2`~/ 8 8 1kAwN?dR&u@nw͎ !j~C)K1xi :5(ˉ]`0=5q&Q1L.w_SU#]%Х* mB[ujV!:nH*+`mDTIRd-f fNFٕ`кiP9U劶<\ML1WF.Z; B+N!Rb( all`=2[GWM'Cʂ;· OQ{?wQ1L MNyԬsOu|Э55Nc&| ͇.jF`Pi%נ4|6x?%%\|-vI~ppsM3A079F/㽏x%IU}ȷ.T@qiy=TBy2BƇ%r <7,23Q# ʕ֋!$vyˇqotpzf-p:P5ӌM6@kc`JٌY辢Ur>m@X}E`*fpp)ȇVϸt1rS*p%ŋD5k%8IӴ$POAN.< 'G?Fefᛥܘ# cE~Z"ӭxW]z &@g|MabT,Yu@yKy6 "k~|-ϗIQз7j :79 !hǡJSPꠄG\ {P 2z>7iߠV5<`o~4f/1pqz޹5Ygr7eKy,Cjx 8hp: ;A[M:ZW 0g=Y W}Dv-Rrh{68еstg!}/e#}UH8WT5}N4T }xoe"Ȳq5zL'vZ7 y LuS>!; O\\.qhXNX;vmsRtJٖ3FJdjqXl2mNL'n}ftSo;y* u,p2 XT9 EAB5M{3A & <Bs*9&?tiy;ξoGW]`Kk7dʩ'w=nФ6ʋt^<(E\ ~Hέg~(: ޛK@|}*!I0j$?I0aSR9ݪ12M=)\ӴmSPbp%e-l{@J2eTxn~^f,~EhEx>Z&_78pjTj>ê{gs!\{J lJۀ@}z0P XU}R/:5`>Xim<3 بa8,y8펹wc By?Hd0xOI}` v*P!!SLUP 8oapxFr"`[2`q^比a #;qqAuZg"5 O*zgL5G >Jٰܪ82ѳ(v^Ϥ-R}ʝe"(`G.M%v/M P:0L8l"e'Ȏ)N 7a'Txt=#NeB4M>Qc lP ̇[3OAJ79w)[CK\ qYb=/Ÿ;1AKFÂ_dz]Y־8tn\S 5MТ>+,J Ѯd2ߦBEX qC6t)a#;´F-^Twpbکf |72"wv5)CO\Z\=P!%{ՂP rqMӸ aM=6 ce`ʄQ=WEpC1~UR@|6^yL})Vuraprgݢɭcn0=8461>*\7ah] |B2N_l?gcKJH+N,q`7o]HM;D lo3VT=OuT_ek; j x](J?1|K~Bbc\i|XRh)5D23ن8 g++LVL>GFЁo `_6)]?N;v`hn,܅c!c_BU ?nA1?rcCM qbڀ\ukT),Cݵ'Y! 45V m\G!Vu/pj vRDUâE|VrHkZ.zF"# rfͷ?_&ԨW o>-k+e .6A**? jnr,S)1 r(LJCDɶDO+iHc}؉W^֟Qu7m[ m{óR݁{jp}v4R, CjP;mqUW\7-AC3a[7SՁl~jւ!gøg_a2qTw^>s>y]* |=¹jHPծؤ30W}uPwNǿ^ċo׫G8,?퓼@Y .tf W*2~XY f_D # w? \] 9m&y6Y8޶=]/#t#̙ɴdI0їg?B$S ~KR^g2kյ <1T ڵe:0hz]~nucQwxK908!P}VqlS  BiOMBB(: ,i1lVk# ֖p3ȋ0L 8=P&qg*3=V_`P_V{X (^{A@ٱ(]X(Xr307}*WBY+;ڷ/ ;B6rÏщv1ϼ MS[m6ѪA$R(m^=T+-K+yJ~ ^;/SVA d: +S#!#zBF;E%LA픑:t%۷@z ԗ,{]Wm?@=iF8 EeP&?uj嚆{KyU )bYSgyK^΅Ga8n<E\'zF :]|@yVq/-Ƽ +_T2ԭ u\ݰaiaʽ{]zRPm 昔/^ H?99ү^ o(8WP \<$T:+򊭦VRODzMJ=q͍ڶ^_H%=/ߺM1jXSH ωh[\1&} m6mz= 0XǍJ˖r.4}{ qrT|([Ԓ+]rӲ:P5w#Xm[ )~6L}Px p]mÇo (˕d W2MY[[^?×ByQ[ e88N{sV I0'Tx5 fԼyr}ч_ g_feg ʻ !4mzP+ -ɞ/3>OENI{JY:,%^{]/)pp RP)M V&cr<+SX`3.oeP&WP l$b(jfCvf+ m @\%eޟY~}@ZАk.&/7D(?fT9)(`]W bv%?&^KxAx*"' 5kwг'dU"e@Rj  7 ל 5phI~0ȩ ;߁5LAUq7+) Ext*Nh &l<\÷ΰ/6IB.4X|^{SZǃvH]2@Ͼ=LBCwjPS(v_MԳs։q$yZN<ed+PӦp$ 7k; DZ5ao~<8M.f,z 7+St 6Jrp36ڎPf؞9Kԥ eL|.x}LFQ@_ԾrfǜꝌ+(ogzPC_pPg c~,s2l)_? 5JByπ{2$vC࿓ap8fJ1DX8 Ybv¦B1;$7+("m=2-Cm N`9yYI5b!4ʾwd%JԼ9}4@v=Lޟ3 vN@oi?r ҶBy9W[|d'#@{@g ?/HKQGE$>ы`Lxj\bڻ^Lʕ1p 08]s.Dx]K{6oŔv%C/ DL.ojf `0g.b&Bxgz<;;#?Q UCB(ڀto+?c~QKhLE9Oիezm :I@Ml ESfNSP~(,0-}0;"u3OV D{Ř7\Ps_1K&uܸ 4!z%"(2O}Vm %u,F`y0=ŋك媽L8YӨ $D/>*#C !h9T[ ep RBEHC:8s%*ڭZIHoٲdfMKZT$vS: }ԯ G/੏`tKJ4G G Gw $<r 5to)6b3w #|‹(mU/1Ht2rYxKϋe-fVJX=%A` 3QK0B*&SUQ6WP`9Y}uItЂ+TB%xX%=JŵVgϾK ҽk$GTD-bDo|OyfM@#ԏzPon o•X]ԆAUʺwX盍GqYVz*b63Ƣ?˸D~^h*ʯ;ƞ,^'h:xC)Cj ωnǔn g_*eӀ q޳C-)VO@#'! |Kj'[c<-3 \y*\yq!߅4^(Ӕ%ejAzаՃuHú%=+wB>J ׿l`P3l}M'Pr^]˝ ch>EU)S*7DBHN:r*2o*ByŖm3Ktu6ՑCG˖#}&0i,[nȶ0f50Kx#X"eZbZpH.Sx@&]H5mc[djnN=AF`҄Ҁ!s 79hZqmf?퉤صX9t q-A=bd ̛U*8Ƞ~h4]B̤YѷG7T~:l.9P.J4o%,KzA#(0bpҭ@DVI^.eщ\m@?.tˬ\!=* KӴB(1`S AjUhj`I4-FFsRryAEB:4F'|)UA!<:?-txWGN+yWʀYPIEzns˦.( -TX7† ~7l tLvw2hY:oP2+k+"rCM -6i7GZ?D) \ŧM\Yc- i?>&l)U$"]cԯ_ۼjYk 5%]Fա܍iۓN1|ϋrضlnD[R.mTG2s_vZZ7 . <㔹I$x:M"_-?_h<>H>;P#TB=;ɤ i?Y( nuжw1շ0Yȱ 4 K]W;oױtFINEFdG ~ڗP}P+4M[uamv` rCPwop8p!|A=6[H; aI]te= ~X,a}/- ]jՀn!⡥Q -`ƿe ]Bg_UEN،-N՗-ojj-ZϺ\*P #0~y O{i#Ѥ?އѴYpl7i}E픻Tjpn_b}$|/pk:uFC:MܙkBScȭ OUH.̦HW24AmB3P J\XLANۧ;ۗU*HfC~{?!} }FEwN,+Nw+}F&}4k(6m~?X߽<>Q}8- = #*o.{*h k+ S˵rnx,~"!;`9i}鿗9rސ!CP ME]X3;Ƀc}7+[L=f.jYY ծka{9& IDATo JbFuٕBŚܪТ)FxͨZi\g*Sh)/_"gyeHlWPi\υ35  tub?#y!T ByR4mb׮ި}\7s㾡LCP/7m܄E\j)Y+8Ou i\gnX'ti5X%Jk*jU!sNNW .3ox$ϏIX8T2By(3MWBx % f ^Xڸ5`k&c>ΕJֆaëKK3!H.&ǫgAʰPEXAR4}%{)ە7Y+Ð(˝Llzi`)4IVu Ea>g&b2}y~?&<ؖQ%b?TW>^_Ŕ% .u>?ի[k9e/!dYq$e.Ra&V(+/ -HӴ-Bv ڐie ʌU,}a_M۰+B>Jٰ8o9|0h.aRf 7 }7rfcF2ҩdR涾eq܁_P@+\%TE"CqB'p'ޢnhf-ڎ}}y~~cn|>ln)L[LE}#8inX$|>滫2~gO*pzxn ZJ P!Áa,TUl|/w<Z>[(g֏PS!:ܪ阮jJa.QzK(_ t$-dӨy=V^JDRVaض+s[?enXhpXY4e&BB(BnDFs- d ,l ba#u u7mJ&2wU/awV-M\\ÑG@$f,NNRx|!9byjBn1Ծ|OA٬,Ao \m~h i}D뜫JGP^A%h \m,7çM bf5ܱsTYMPt_EC]gz#TfiBr}XҾ7Kt~F(0X%gu(_+&OPҗJA, X`]X1QT*ʓ~nzl'>#^u/m륍Y{RwZ[;X*.,\ʳ_s&RE Wӫky@pI2esPH*9B+,!:|׽[1l4 ?A4Pv,q\GrJ \!'(7~/|Q^(1 kaO@ޫ Z˩Br,!&pZӾ?&r}җ|ƒ2W0vǭ ɞ̋O`-5!7v+ZK5YeڇsgYLtY?Og ΄qgP B(/Bd%E jV~!L n|VXڷpPQ,k^s'Pc f"عjdRݤt _nR` 6M9czw{g .>w+!SEJ !r7!Br&%2L_’BmeKL\XdcwWɭMٹtMvc*<Sb NϧWrR-(l9\6SԵ1һtKK0!ġZJ P^$' %P=ۺή"(|=nQ Խu>x iV{B(% ya+7ÐI~#!;Bi SgMGOCNe<h 昰jQ{ب{v8xl;?;xW1Z0Km8s߆< t_F?iȈ-^JB(Om.*6QC'OL]&.KG@n0^ĭc:ǏCj(gRGZwS +h9'L-pGa7uMwx|DAQ: <>i00E 0 ,n1C(qS/`aӧih}uE(Vs3 |Gԡ ,{= cدt1r%i xR ex?i!*.W,x\8p]d7O| kAxBy$@.{;W5OKm?Js!~K@-}rn>ÍJ jÛB.XGBKe¼8Uth!'{@qha4(~&n_pME_ L*K1h2:<<ΕP;WmI035**4m~S^BB4EޗZRraЬ6eAP=p0e}?TgzBF8Ƀ|p0Sv#Ъ6=F |+Z 9`2׊>m Z7,(`Ix cԍXȉN?\£ᅋ!;pNds:mo)gp_z M! !DG6"rtf<٘V а2i'4Y-M"P\pтApN`m7KUש7Lk(W6CoNJfx0NV_qa`AD?(cmR#X8OJ*å=u3,ED=\ƒb i~z>VXP"'ow9N>> hh6 {F%102lpP^!:KBscªMK@ʣBtFN<Hp*Մ/a&p>axCTe9A?AP'MSX:YNf\z/oR808xpnS8a˅-^O -|;ef@px;MMqm61h_k7J7œ->a}x!8o1WA48+P~odO]| ;&.NB ω*^P . `Iq΂΁;Εo, 1 oM ]bV k`Wr!DcR< ʕ)e%G¯ Uթ 0 :jTu7 x- Ch2+eeIukAZPvt6Ԫ.QT$Cl(|Xlᛷ%*U}wB~pg_kݻf}Z<.^G#S~@WJ;WN;e᳥2X{aSSʷ|Э&t9e+g_"h$i ~'\U((Bd#7ڥx8tʈψD?τU.fe03ـ@pPA}rэsOyZ\5~]_A\r{;l;D\fma61w4y)Ζr>ԑe IDATWJ??Q=dɓZK ωCںX%F᳛5cF}(}-ƄInmRq;7:㚦hKU(BTF7R7ZcC:Ct+7+?>2Sʊnz:W^g?K';2"pYpeP-ׁ.ǡ鸀B8:{X(S">iLWr!DC$jx8px!h.&LE /΀зe`@+] w FܳƼ OLyM-1:x7PuЪ=:Hk 7S6V Gݢ'i`Zٯ1< %`Q; n;37C"@VʮψC!D"#J`r BHKlZahX}־mFw矖“o_B)[Ԅmwskk$?ٕ`kС7wƧא_ N9!Z`h/<_s#tzB!@YªH pLD.P%`dNֹ d=] sWܿ`j/H]W .Ym鶅;G^kءj&2bZyW !ANL*չ,t.qPr[Ӄ%n3<6>l8u$m 󎏬*NKMlM,DQ"E' bATlX*bGҗe]%l%d83drg料$9Νs)w2>yP|2Tn ,]QQ< uxel;n> }(ob\(?v k@ZԩKNj7`` %wi&5~bWmWK p.;~t-,7_aLXb7O0.B+v?3sL?Ƅdb?7{ټ@ӂQ\F8\7G~>} 7ë{H5 F K&]e~1 _[n7{?Đwq/dDV8_eA a9u4@C b(AnAx+1v#ӕ"oUUM_XQ( $OGXyQ[] %p1pq΄]0iT@e7~XShٰi-.:6[Xe,+yꆚ%: `b)f]\h}$ ׼O}„%f~LUU5R'En< 7a1bQ` |%d;p?bq]dq1aޝpa`]ʄ`_ZBGg#pfx$L0ol[C@N@[7/*yX¤Q(׾"nƐ/_@d ae/pAa@D)6[ F-XȾϛӣ!T7*bKg~Eܬ~컱a nUU)ٓ1Ì劢A$\D"0f焊h!cso?"ת[@ \:j:/9 OdB]VoƆsM/Tㅡa#J /x&Mk]r`j@uQ96LE` v+ǓH] qG^o% g }UU${2FHyQ(JYhk?428Hߑw36\NhyZ< sUl z@d!?l=pיʂdiǍA"'uף/7H,+O"N |ro Nn nJ]UU_Jd\Qg3Y|6#¨#ڟ>9?> BDa8-ĭ&QD+9J-qdO$)'E9 I]L7$ez'ÏoL_.=/҂8߹~{cӳppG-&cDww•@gcXB^~p\xak3<O׋H.K<8yHy%, |8pQ8?_ O`~~wUUS(%D( B8-ӑ 'O!'B|G8ab0EpC* v#MQxvxǛH%: Yq] >\tb},S1qv_/N aJ`R'L{9ktx'!q'ݟ{Ot!}TMq*{pWL荻(7qcb% NW_E9c"V,wCU8-D^hm@l=&+$q:`I6yy˺ 员Oc9p/eYL7s'Ɍu>\Qyg m`ILOf:B pAgk{/DfB-$ V:,zEj+ʇ~O ` ,u#-")O\/?ƴY^Fx_pjLG(\ߢo \yonzno @&ސ=#; Cw=3;Lq>U!{y dgKІk~5>#rQqtढ़pٵt|$3/p/"5hBE(ka /A+IX]kH|p'Bs>xLFCYV_.~xsj*Ib / ,dZİihe<\WBX u&rKa}#@k0g;7 3o[/$pL!Cz9~5XV ycS E {̿/7\Pr@ ׌ _1OE.>r[1c W^HP頻5у%D+r&"޹$n#NM ߑx-Fڿx .*dRg·%FGߘ\^Ȩ $O tJr>}6Y/l"\K SMWÚƛݭv}>=lb4D<[b59_Pd tsbkYˣ ɏ?!'fnfEpm51:΋du)ʙ(~v7~W&qoThp ;ZG w'gQ} ̭n6K "bXE(i$؁tY-.܌*C!}k*OK8jHݏQwݱǾp&;62*}_P{!!ރۨw1p9PN.˴@c_o4-LXoiXNpJ$?ﮁ{φtݑXFa.2SuUE A-v77M:1cۡ="-5iD3Ly^d>Q[|3x]#{?ao%@:[UxthZ+|HGY~\4Kx( 0f lJ> pA9+)B/u_]:Dp4JuO]. a=}+w?u7X'} uh?k1'@)ȓPjpaB?=_@L8yZp>7"Dc}[h .B=edO@? \ )p]ؖwxӢaNX㪅_}N[7GISN(7)i%}L̲=J1cv{gMFEm(V鈺rv_ƴd7#]Z+<׏G׳teO!RU+!5.<'zRAÕN_`scI$:~unhɰ- lR>DN)g Ylö|xn k_ï_MO'w`ipb'6}guF#a9uZm6IXwHxO~ N+\d~sX .7,PZ j|U|@.0u _E:6%ts.{M /΅Ec\icSMSO`voS# r|jppRK,kw(Seކ-劢I̸LQT~t |v=RplO>E΅/~NZ.K[mov&x%H)FZjM[w7 SS"p(7S[,5: [};>&M_3.x yZTe7e,VK&=vQGT+}<#ȷ>_zh VX1xaWk Mo-d>XVh3y36֏=$T|Yvpvó"DS6§?`zi xt)|>&VwNZ"h/uܰ 22 E!&3`N`c }}pɰoXo {-D$\y(v3~]Sd埍=LhCAA(^~ο6ƅi`+KL-(u~?\ Rb\7z *b???#HR'5[UUQe3p%pP<$ ^Wj샻 Vľd|C?8Da"Wv?䶓Sp'. a˄@_.r =" "\U~/<N껦lhmLc8$赐 sD/x,ПlDIQVO>>c kuNJ /'s fnu&oG.}zO !P"Iq!bjBdCQ%~=#Gz2\x.|J8@e@N=/߅O~hrIjHم\'-.חr*eQh>iixi}WHbr 7C}jCpFL^w$@<\xaYo ? I?b)\1}3zb8B ÀiM:>o1cq:'DMAt$Η:Pe(ȃ|կk(u=P_k~ x(~v=qrǪӝ38>V^0758U"6/nd͠(p{1_\28nWS iAa<γlpo=C>PVO1\9cB[=Og(qls.e^$JDUq*Ȇ Uj3  )`uWay<[i־N>4D2:B<{(<׿d:x>djnӅc$nq:ᅇajjVuꎶKd\ 9ŸoؼXȸufb܀__{k/[!e౎'_b< bv&p2:%Hu ]H(hJ!uaFGGs#o?g$%uꓐ"1tb!k޺? s(f@iC`&10\}LO ^{t8(TzLYz`ঽ IDATt9yTGgL gm w7_#U&Vhu{/ Wyn]{ESID}1|3(0~DCO~TUx_sgԃi.HO\7Nly {(E,x֊z_"xH6˪oAm\Yز]۟~ >}iHEю}O}j\,:!DxnG#H"8"乤("ŹD v:(KCN{F ߂Jǥ7nC\ iiq",ȏ0>p:X2PHR"%uYh]u#^kʥf #"@N2TH$D ^L+>N{ /øn(1*u,L{pŁ%Î+u m_ ?UkH$h %IEf(E t$,K ?<(n<ϝ8& 6 UUd q(^ϬYR] 7^@e*X͔:xqطOJ]%yf":R00 X9?GO@񉲣%J$A/3<0f(H$)! GcKЇՕp#'i><ϟ+_떋p>x^_/>˚{Bp$J%9a/\1M)f(2Օpu: 8w w%%dCQtoH$y\DyA>0{p=, 1)H$QhE/JDlH D"1Mu%Y<|QEa><"|w=mnhj$ɜ'{"f6rD"Lz:x˩P@1b%WUf| noہ .I$!;b;ck\Z%e a~) ^A`3:"<(SwD"$?p b;+k<)%D"HR6s,C]"H$$9È0s)%D"H$Ӎ@q{HQi=H$D"*OH\R)!D"H$9ڀ4 7Ie(7D"H$FdOd ED"H$$]?qa Ri=H$D2# \T$&냞>!;M1U\D(HfkWQNq?~[CKaªʰN{_wdf;*W8 .Q <Ar$WUg? lSo;Kmm(Ga@k;+yߧ"u܈Uʥľk 0AyalvBUU,6jQ;Wfe156Oiijӓ;Q\"ʊϝ m C:33`Ӛ}DuE`U\ Z٧}Fg/XqFQK=$l2c>!&1Q7-^*/ ~pxJK `*pT3-gf-O2GA{[_[EunixD\'9R:cIR)%RkBqfQhjr03⏓EXRg;y!>n$}qr<LtM~ O?[X!"}+A酡U<'"42_("̈(7A^Nu)A¼f嵰.b`mGw{jsegwas:'Ϟ5Uxz60$},G.H@ V-LB⨃N+g$\3,ӵ+X?m3oE` &-4RFS3B Z .OK{GB CdN 3ق)H,.կUv?Ϊ¥)bc%eF`K oN6?QGrJ;iٙ(QK^chJ थ(4' \'Qy|#'MFnwOxX{{A.tn n3Q]e3`2xq8p-}n9E807GZ}v- d#lY(HL悍a~3dgU1|<`Bq D."hiֈhS Hm"2wNi3wFx熰Ts7l<t7Uu M" na{V$Jn0`ށ7TF`X67P 9Y1O:Ip xy ЇXǜtQHQ.`<ذLI_:ݡ#[6 &:Ef~o?>c^8pjx6qt\,"u.Qb8l3c]S tB'=/ʃYalf&!" C]"ohZV՟ ZM7Uaq98jpa1ֶpƚ&}pvO0 #mJB\"1kAU`>e1h$1SF~ <D](-пRJiTdiCYkb_cv]XYO >!>8­A cϨ91m/Q1@ D c}Y<Uɨj)J?}&Bp &XQ͐6h"~DbDCG2)%˃Kc$!^ݧ47WFob(/#ȫ6@ N!ɹ Q,^uccQ1o]tYm -{}\1e@F,ؔ)ȐI 6X^cQ ױxI&E37(fÁ- ŖʱyV/Uvh4+-MDxǡxy s3E":JiXŢ!!nV\~.xr2؏Ğ&o5w.8cES Z:XD #MxK2R.s(@Q6t /(p)+!7R2Hȋ28l=0,4 V@ebɕǬOxHT2g.T-b^uuxE! 1ϟ8(BB.Oݙ!" p\T!*^aY1,Kr"glѬwLzU{4h^M7mr3 ;tV0VnVZX8#b_Uak J*GJpCeCK$Fx(**t^/tvvrqdf(/++c…8:Ann.ՕJHsmE9" aVTi2TWCX0]0%M5 a~0~C y来"b /0,cvHw 'ddMj.9Z(p1c. ѝTD[gL'(2 dɔHR?ЋVZE~ăI~~>̟?zMyyy֒=2cǎ ` I860 2+[U5U8>z`,Ƨi =RX& yPY,"*(aUoh *7kILA3tw[`S2v_ˆ1$AX s%''k`Zňۡ.b!7#'S$cQ\af_ň<Ǎe_^ٯQ<Ȳs[h=e2{ S5WUajUU>Br.5߬:=xa۩`l:]Hf>UDP FQQr!~ [Gf# 3i ;pҢY*(X9|3PNkN(4WgH4M]be8&\2Yv 0=(=>Q72Cc03RbA/'TBVb( ,ٺQ=`1ɓLII ո\ ##|6PU3o\X ~GEta> dt#d ,IOa}U-u*-8`O쏿lY"2bt GKrAm2UICAfQ+v:`x 51im7@$~ -- ؘf===txq$DEH >W*rp9@Gv6ӫ*}}>eee,X RK$qBaBExP<HvΜ$ONE5@ΛtXcܽݧ‹aW %`&$zn1@&H`O5EXcp8Xp!eee(appG\ի-Ncc###32^gnUU_P(ށw.j~Iؿ?IRWWqhWWw<D2sq9D|ʡaM"Ёx5}V_'OX ydMM1n(כ|9ΔЂiʄ@MXg??2nVZá}ICCC7n$3ڲFOKK G7k"\QUu)|AEއo"El6 ,B馦&WS]]ͼybLccH$M.:%yPE|z@$CU,0> /j2lB;!)n,"Xq ð?L^{R^ăpQuA+R%K4u`ٲe#xhllDjĢ!TUtbTQ>DE>0ISJ__O9f٨4`tdd_~$Ý%’^;|>}8=!j 䁦izZP HnG(ɧLُ'.Q^4G:6 >䃑#} "dr)(@s޼yTWW'\M3{{TUe-'5R?/4܁ #77r_&-͘0۶mW{aXA&6z-y!g7~4v@\2dNA|,Lz%?? Ԥ)CYlv|477Ң)srrY/ tttX+ <'nI*J C?w\^\A:RQ˩ݻw)cQT"D<;ex/?Xt}p̤" d*BvPϒkYeRirc~f#ZsssYz50!Aoa(z~w7BBDe3z~tl6V^mڅ$?KUPP@mmxq+ k.?r0 UeeeL?22ۭ|X$$*E ԅ=q lcL2OZL('J$q!ĥ4p8ؼysLCCCXti\sOO N]c۩ra^y啈FT : KAE@b_POhʱchjjPPP`z A ?naa!555]SD"rE^U(Q$) "Ib2-K}}=S ,[UUĉ>|wkvzz:Z1{X.a.,aDA% ӂvN;-bXtuuQ__xpPUU%kkkMݔ\"$`t$ x?q$0~9##˂`ll&;iˣ6bBXofP?qGRD ˁegg׭_pG)++c…8nwwwS__Wl6.D"IU|`N=Ib6M+))aɒ%h5^~~>qY844D}}=S(QUUeX~{CLG֑`.Cxyyo냑Kmm-ٖM[`cǎ"tRUUEIIɸ㡫["H$8ҏ\Pv;IUUehh6ZZZ t! A.Zpa\"uvvWOgy! Ɖ姟~f@כ D_UlGSSSDoJ1v1nzB2J$D )3Ht:ٰaC444:ϟoy.\f:|a5u޲eK-,GF<^^^Nmm8qƈ jjj(**fMHQ.H$DCLO zaÆZȑ#[^R\\zhh_TTpʢr3)xرL?N1V455 f:yVVWFFFƏѣGikkyQXXHKK G <::ʁ8~A. Q$f(EUծO?wyyyXԣp٩FGGKKKZעX444DP)Dd0+رcGĈ6D"V x™?>uuuv;^N' P۩ -ZZZhnnz9tи`ֲfQYYIII {~vIqq1պi޼yݻ'X+ cǎ<##˗[}}}l߾Lƍ"[ZZhii<ƲeXfMԘX\$D2c>#d7R]]E^/۷oLcXZdpp]vwވ7zIKKc͚5ym6Kctf\/t#|d\R{Cccc((EEE!DH16 ***tGfMz$H$YB+Lӎֵ2^RRBcc#]^xDZK"--K2|X;::hVTT6Zl6JKKill<>׵ǜ噙[.6innY󃕕e1PXb͛GMMG[D"5xpO<w\,Yd\0?줻rMBn:Z[[illsZ[[-G/w?7,`Nک/TU=X | h4+ٶmMMMSy0DPF)&tsyzz:q )H$>iQC\"q:eٌfڵFm۶M$b$8þ}عsB]ioUU=EU_XLF(׋|FoہX bΟ?*K0AihhЌt:֝P njjjQK$dZBXȔ !r1[LGO)))fZZZD4ٿ?ǎ3$>+LcS9\UULOp"Ey~zs^f֪ vիW[qB:tHsaYٿBD\.x>Ngg'Ǐw3339uY#LLLP[[KMMMM씔v BOO =z4qI(O `Өռ/)@vv6^,//1'z0 9"\!v ¬= ށV;b.iӴ&%NAAϟ_/#8odeee}ҤOaa!#)NI(Oң>z*{˿ kzM؂IB!1lf!u.:|Ο?o;Hj0<a !f<'.); ??5`vD\}Ʒ>6m `n|>*++msiooO:WY|6fïk~'p!|;h''њ6B'ZK~~>MMM8-oW<qz}S!8DN<@ [R[[ux^*++m;XFGqٜ9s&!~xwZzmWRmF;^S_XXKFtuuEle'ߪE?u= !_H+((̙3a!433s=0&''m|0dbb`u4"077zGjGO)**"088Z(Z}YZ' ѡۆsN@^VV8kpǁ< qi pMMMQw|"uZ΍񔩨rhnnzovPYFvo BtwwB à)!]Γ]xzZl?رc~H`>>w ®geezQp2@!~l_"n^kA6222s$ּЦoh\YYk< v]RVVnܸ0;XJJJn`;HRQQACCCB" 7 !>yu!A|Wegg'tM$0{^GOhjjZ/t}rr)G"4luBᐄ]>|0 YYY ׭؎ܵDe~~e;,\.`ԱBb+*Caa!qw𚙙aqq1=̖Ξ=8ݛxtt*++EEEVmy)&c I(#7w?ǶkIFFz[VVV޽{;8m0005444lzc" BBX#wv~Vވ-ccc$}<11A cծRRRBQQojٸ۷󑟟+m)Oi,H(c133Ý;w"Gv~_z`p<2005T[A9vpQ!D Ά;a^ZZ(++s4¨h>墶2^vNlvvg}R㚾]]];w<Ď+*yzz:Ov-..… 466pyc斖ۮ&`{k׮EKlccc\vOv)0VӧhqqFGGm{X>>$555&Yx())=Ec)0B@< j OvY]]ݻܽ{Lnn.MMMҶ0VOqB%.5,3K GGettMVWWgxxƈc)// '~ |"ݷBl-Ps x++c@71m\qjuu{qMux܄lٕl9sssBJeW|呞N0daa!C摑miPVVFII7odpp7 0 u'5x]BRĚs;Oϝ?W:0G]'KZZ4&#i^Wk-!āy_4:cluu]WefEnܸ~@3'UEE݌m033CGG466&tv- ]Z?f_0kd k3)Z˾tȑد2O244d{rqm)U ܹs'b𯮮q🟟ڵkw\bp1nܸhB}z<).vPzz:---ag\.eeeGr===ajpL`*##'ORZZʍ7N###S[[KMMM\g^|D)4ЋYS+c6 \)%+Ν;9ѣGr5˗myQQ/^:䳳\zu(ds'*GkByk'BeeeQ/F588HWWq>ĺI6QJ} 8 |gVS߶[e/XQJ5LG$~x=fֵ$@6 {<멪r4 >|> }!ľ.6wa oXyhh^ϳvz8Z_ee%300 raak׮QPPKjvS\\lq2p4&'R:o~Q_)J PnQJ%3/A연IW_q3!333&''îAee%I(6CCC,bVVVu< B-V0kaՀ/-- *%Z3>>Twxs~~>MMMtz<^/iۓX.i~NƝR9ȞIٓnwֺ  ㌌^6? cppLMM]CCOWVVH;P.ǓIvťF|z7 [^^?}2::tX\|y>d(++f&''fnnn֚AFGG~򛑑q-:޽ϗ_\M6 Se_Zد!Z[[v.,՜={q B._l pMMM9 ׬BuuuԩS2Hԑ:ɓaӜ|\p!jq5 gΜ!;;;zR"pm-|§ߗ@?ĸ~sBZ"\^ޠjKsM5~z}kG"lVVO月P(͛7moth4E7OXݫinnx_kMgg'sc涶2 ǏGh777Ggg̷> nk3|/asuWO*#KOO'OtT===M ݵvQSS-FY233>D"ԉQXXZj^?餱5碬>6y^JQQ>QXߨp`ƀN}J\N:@)TY,++1* we$ twwGl?UQQACCxuuu\Mx IDATNcqR' |r>ssshjjZ7Z"399UUU'u*--Ν;[wg0k/\o!`R~@RPL/=@)Y{xOI s3 +233ˣVVVO=ˣɶgmb0(**"++Yfggm qX6 }j䐟`0bF=z4᧓iii=zt=0omvLvٳݽ#FwtttCW"n7G+/_Z}lkRJqq;.0EKc,gX{c4?qvdd‡fddz#NwKJyyy|>Ս)HCiGFFy/>쐴4Zf(brr⤾wnn.zhi|0SVِg[(&oxهREzzL<{ܼy6geeq…m d p8qG}q 8wǏ݉///'V0KT@xJ;wζ_nn.gϞ=jk}x2JJJx" au\ryҘY}Y_ vcuFڐHr{"/}x{ rݸqxhnnvpff&bw\qŤ{n4<<̭[l%(((p! N:q9"1jF i[Xs<̙3{M[JZ 6ROǀb>R]޸V.z7M;7oޤ6F$uV.uiiiI(; Y۫rhsWڶ=sq5ScmVJ__QT Ð6QJbfc/^ )H)u})W/^O>"1;E1<'sss)..faa`0H0@/v SX露C Xn@l5::ԙX=0ǻIyy9%%%qI~<ٔ*&;q7mZ_Cvb=9~> D`ж7-<.QWW>d🝝خђCSSSXBttt0?/D_.4eGzE`e%l׺*:890vihh¶uU. sWC$ljʯ_OZ0exx8Snm]࿴DWWWĝXpi\"=NS +**ZlYZZQw'Mcc#QvzԩSp֭a>4]|4:|$u9\>C(k5¡ᰱ566:VOH-x"^q tvvvKKK̝lE6~ғջ /^5\~=z<|Yrrr®[-h޽&8jkkmÃ}aZ/-R]!|(VR/~sȐ(˔R%++`ZQQQ7xX,Z[[C}oinnv) /_& ];K6> <EEEq6V`:lG`.((455ռbV0 g2:0.|oRJ ysAJo\J)g}~{+H{ cm]㡾vG g[jf,6:=$-- +}4+0 5+0[5N(AUUeee188׮]gA!,/ ȜmSJcPÔR|z\_@Z a233\frxee% a;Botp\  H̤)~^癝%77Vc ]]][(NMmn1==M{{;'>σVh~I/IAyjI(ߛ>9kb!z/zыx\(aYijjrtòlau uт__}}}IXAdW|Ǹnꨮ޴222p(l vNFٜ9s 7msSXX͛7KB@`|&rҧ]&<ljʿ<A=H)1#=6OJopIoߎȏ9!Z[[w^X u(+P۷o322b{=ڡ?NFF=ǪyOgCx(瞋>ѺFYa%(r\0µ.52]s7=J)YISJIm6L{71 ӧO'|jnڗKk:$].׶ [{=EwIYYYܻz`/0funnN#+++vYlԴR1mY◤&w=L)5~ҽeg\yQ K3VXXX'bv ְLOOl[)njkkIÅ8N|Ig }؞ի@MKKѣ4MLL099Iuu5݉s*++owjjj~E8֦RgP$-Oqzx?~0avou +++ܽ{{s<ڲ`;Qϲ?Pr(..&//`0icO 233׻ų<::JMMM+V`djjj[& #066FOO o=܆Qb2*;;C(>\Z? ^Ͻ{yWLIvHBWY3o@Nj_ߌύcN0==n\b#G8 <ŎGSSSXY5sssdgG^]55E xȑ#;wǏgeeqIÕ+222xGm[ZɓQGVVR.^HCCCXI5=x\.8wz߻~zs Ο?= )d-G $IRSֹ\.N:帋Lo<[ZZb(ׯ_-]I$R]]x=BlB}}):::-0~؟gvԓñc"^cttpm2`P~@)ƀa\Ɓ ZZ"m=^ZZ͛ttt]d_m1o-;I6KKEqPrQ__10ͭfs3228q>䱱1utƣ0ϲID)=knk+>k;Oj~z޽{ 懠WY`NM*>QPP,--yII ^7ba!DPZ@ ̦cccLLLP[[Kmm֫yyy;waz{{YZzxouu~FFFhllLwn9UUU?=鿀D)5C݇C a Ԝ:o6 jౌNkٍw>pZoKżvNFF555,//3;;XRXV`',01<<(0[***(--?lP"7n`pp0PkOV1^ PC@C$>E$1^#[lhg05|%/yd9=0~[m|ﴃ֝0|>' ׯ_]D\vyGg$)))M$]wDnM}Hz [JqKv'f_VJs {yMM@̝;whoo Xo8A:;; fzor8y򤣵aUb/RRbp+pƍ]Ӝ={ôr]Su)--fmD,tE܋$R8y'<2Գ$++* Mkk6geeLss1G˗mw Nv }P933SNE ̣ڂΟ?OSSiiiY-lG=Q1:&\.MR0 < |E "bRxn Z0: \NYv=TUU9>0fpp> YYY|>B8LP+0 ׷i7ycə磸8Yeceee}xB|>_RA IOOߺ sܧ=O|ȁ@)w{bP.v@$A0[~߮b~~@ d50U%crr DfddP^^Nffz;b)))`0=%֔IBP¥Y]]]lwx|[|OMMqe*++ihhHb999,--`Fn q~R@B)_YZBk%/OcWVVc``v9??&G-i}v:Â4~@D lFZkƒ>+0OOOޞT`*;;3g099I z*5::~P:255>s17 a>abGHMkeoKZ30g Ml)((X#P(Dww7mmm 8µO([*#)_;F)u? x09pbx<[ZZz9ĉ߿@ lxGc-CCC~FlWv [+I100@__ߦzܹ>60^7]b^oݍn7i\@#0T!: t}7&[6&CȠuw=x)f.+逋twwG eee466ץ2'Sly1a$LMMQ]]M]]]R`˷_.?~< bRJc!?"$jkA 5Z a|a*ݻw#a>r> %-- כpJ??>>x}ɶ4D Z@EER\\lvii7ovڦ {59Ei^iohsssܾ};b'۽-[ I$ڙ͛}ܼy3x ̷nbpp&G].vFbff+WPVVy`v%`jxO#D@Se foح^J84661ɓ'r+ܸq#,\.hiiٖ@>::իWcq ---Hggg#;MT^^ڞ[;V̆[-TJR*!#;bZ o>a>~RJf$///6N%zzzW^/I,w)= >,x^Gg 2228qz̦룣S[[Kmmm;HmR_J℈r)vqk0̺ǀc`w'cuumwsrr|:Ғm q011180}9eiii*}}} z)- 8SZZEEE[6<鼼~!鿀D)x/! 5ҽeu/^ཆaXFFƛ[{ӈpKZZ:ֶy JKKg```S"ׯ__?h\&&&0'F^ZZ~ucmcNZ5RS.xv*)hZPPxL0.@^]]MKK mmmtwwK ?Ĭ|nF.\@qqqέ["NеSXXYJk{0)x镝^IB8R@h9Y̙䫫ܹs|'lZ_"q8=x`=0o,AIFVVO^ga`` wkm1OOR!vrqнjԍ@ZZZbpp0a6ʨs=B@˗/G B ʽ{"{WMMMֈ+++ܽϼo{)S!ROB8ДRNam~߮] ==}6pر֚IAK|+++tww䤣E/.)Ro ?^rC}@zO)o.kQk0~E-/21==M   nja1??իW),,󑝝(--Ν;? .`?_:{@l#T{ Y饖bzYk5J?fee%\"4??OWW=r/_& %VxS\ IDAT Z=;;;Ӟ]VK0 r!"PJ:blsBk=ǏQfee._X3[[[J %Zh?6 t)CQH("Xަ޹`||V޽Giyy۷ow {;}M)5y^'E)Zr!{`nqSkxxq+;! izޤtMFz ~,Wt͵4<`"xzu Rׁ bWX)]]r!6gv{YCC7~0 F.]^8xnOUWW𧻼E)Y೻!#)_bg݉5 }u@kZ&Ǒ~™ #ǴZ]0ybI(bg}*״*)ֿ^UWA0~ xP~_vyM{gxO $ >O $LzIk0C̑ZW͗V|}HZ8$ ~JԮjZOj?~ps^"ۘ>VqRJ \1B< B0gc[~|৕R#Nk}GkgZk"o SՉg|8KR0?7io~V)5kⰐ+BRjxn Z? I(b{7l~_)ZS}OkCo1HHۼݱU߬v;C+6ޣg^bIM{R󘇰.'J;5`Kkì?]]#։VR3[~ǁ`~:MH(bPJ}nZ[?bQpFqWv0^Z3]$@)Չ9TIMBw>% <9SǁjK zO! B`JE8^*u6)oa֟_ϣ[ *Zh״W: )ġ \/MJgR}LkW*wُ7c|2':T;p-Kzwh9B]$\`_~5d_´Zk 8UnG/ZLn&14[^!9)~%OJ̝.J\~afK.lgM_|jFJdȏ)_BxCKk}CkNi ~i/M;!P.QJ 7!CkZ?M"ן[u-SR'n[@N\*#8$ !R!Z۸uJT-fZk?~f?n?Uxtk>%3%DB㤦\ ?r\RJ7({fv%B8Ch !RWcfwNӻ*!ގЦznwW%8L7w,W2=+|ĀBH0`v/"R$196p!HLB^qt*7~qU@?k`#""q{DDf~N֎r0qb)̀Hx4/"R<hл~cL7c} )jc̗Ƙ;1m#HED7 n>D8fM=pnD1f1A V)Ƙ\IP&kHc 8,x1pv#BH1 ΊvT2ƴԣam3)~ ""RT182`k$"9Hi-GH\(HY1cN8""/""EZ;c|8HED]&vNg8""҅""RԌ1݁#7zZ{H@C B*Ƙ:87޴+YFkHSy*rk߁nY?*`)HdZ{:p)Ό~:BH`T#""1iRw3Z[DD~/ǒzƿ>#K_DD־ #EDjc~w-0#{=?E= Fu?8 k_`"ƄGcM "Rt!H1tY~ îˁ[0ƌKxiv#"/~"ai\e<:pvN+@ƘCw^ndxDDN"`9 \Mlfc1dkmѩ7ӎQED ""8n)iS1|Bp%qB,~e < \pW]1'VC^jXDD/"R1̀SC)1撐kՏF9|(cL;`[.^c̹!kzt`07ለLc8ZVc1X/"R 1pJm8Z;5ꁈHv ""hX,v֮z ""BHcv;vO[nhт-[ҲeK7n̂ ;w.s>c̘1Z֞DD$ ""1f!v82dGu%%ngԨQ >-[dۥm(Ę1 wy\i&Ν˕W^ѣ35^FDDbH_D$1nO6mx8}ѣ! ǽ|Bٳ?I~2D;3]t~)?hܸ0`EDBH1;ej3h N;F͂ <{0az)ڴisߥ\|̜9O<1[zƘ:9w("RED8kڧԮ];8o͛_Δ)S8蠃|Cv=z4#G$㟳_Dj9ݑWD$dƘ_f9CK .C_}~~a=7c_t֮ t ""1~A߿]vYl?/m`Ȑ!qBDVLHg?Om۶̙3 VDw.誫⮻Jy#Z}C􋈄LoX+V0qĬ~߇N=t78LHH1yGԩS]#FpgflөS'MFӦMTٳgӳgO***Rmv yX""_2u=zt%%%92.d,#􋈄 XLGy$ovhmۖmnGڲeڵ+k׮My=Z!aD&SJ""ci?SO=1tS'vB`cL0#"%~nCN8KNh=3aDN_D$@]8 /4f)_oѢ=XȣqbO cH_v""Oqy8ܹsׇNVB{eees16q8""Q VҞN;f͚9~C+(Ҥ;.HEDb8$A73ƴRc8BB0!"~] {aEPQ_ڥb<0!6lHYYkt k,""QP_p4m4fHQSB e)i8DD/"⿔"m۶ev {,R-K8DD/"{֫WG#(HQSWttQx4/"BKkW-,NXB֐h?Z*L_D_iec2./"RED2Yc9m]y5/"EK_D_)kHvqGׯX$AP]1~N,4Ij"HRWd%7fk/"EK_D_)}ƍ$YzuCBڦzQ?zVdeBO1%@T%on k,""aSQ@T%k""QЍHDD|`w.V1cWfݛ::U#"EM_D$ƘLšwxGy嗷Y]vq\z4o3zȑ#]_v->^x!+nT#"{DD\24򺯋"s2sLNJ'x*++ys{}0vؔ`˖-{ 0 Qp2qDE_D$ c8a|r%X6moZ 7'Ⱥu\W_Ceҥ>2?.B0!"~1w Ͷ{'H;Ӟ#F0{6m7Ϗ?c9*?,HEDcn~~+UYYSO=r۟g^{=eF~X,c,=~Ƙ+>gok#F]w6l8ˌ%_5(T3\sw]߭^ڷ5g̘q},Y"67n+؋/殻X6mZ͚/"cY3L2ŗc̙Çg+{ &eL1k_DBzƘc&~y_ϗ㤒СC}=ƍ}[qȋkߦ\ |hDD/"1+9><xlݻロk[ r%Kn5~lOiա9aGD$ #ZƘv _tU&M:uOJJܟ.йsgMf^͛7?kDGDjHd1@\STu 6lG}Kw[qn;^y֭[W_}o… ꪫ2סCn&;wfذaL21cpa3\oi.ZA_Djk^wj߁l P8"~G7 65c wq=z?ڵ+͚5KۦiӦL4!CлwoǸq8C]?̺72vLM4/"B:Ƙ[*p<ۆ+p ?.իWM6cM/N{Ivh߾}9ڶmk㪱|rWM6ej~EV1l<O;:@iL0/orM[n}IA~zܽ{w:wݑG;ju7^~lMc""QS^mV N. a?Ռ3`4Ǫr=#Nǎ3]SݝU8R߳gϔg;٨QVٚ]gfIw&"RE0O'&܅į3W_i]#GV^^ccǎ[.3cƌO5bV\`1^CB Ƙ&8V(8Yjdk eg*+dTTTl˼yz[oucۗMnz˖-S9jԨlæI&Yo`1A@CBwp[c7A?d^y]Ի^{e_r%C I&\,\C9N;m_}ʕwԩÅ^ur.lvذa)Oy䑔_I3l0,XuC˹.""Es(0m3zZó2ݻ7'O~ns/K>#֭_̬Y3ZE]_<5kYt);3;33gt5 8cņ ҥK>Z""F_D1nc{`\9}6 ^tDs<7p7xcN}K 8\nL<9}_aεz*3H;J9xl}iFͥ^ex[{֭O>d}=9Rޜvk}~j1(?$" "RWct=Adw[_R}lワqf͘4iq]IZ~Zow{aժU~ xz}R)ZƘKpwx lWdigOv֭[ǟ'72p 7p 7t|p֭Z~>ҥKҥ ׯ >%~TD$l "R1̀n-p\-++sqym͛7{w>7ҸqcN:$N9:txQJ=\}:}aAwGkAw""]+"<@7żɯFqX#G2`:,V\M!C0qDLzξO> -oذA {c@ܺH4/"EgRu-=)Iu!oJ$SּysxN9%yZf ?8 'NjUV<tI)]b+Wcǎԭ[7q&;ydz x"`0{cZSD Bcyn۷j.3;'8 rD䡇E9^ee%Ço˖e `Сn1gSOڮ  tgɸY&vDD)w߽>/^]g/K/ңG}ٴu^W^wyY?87ѣof-`}Or\[<ɭDID`(H19m8%[n.-[~;t*2qDG͌3v۾%ERl ƫ8K eS 4K.?}]3fW_f{N;3}9~O?N8U~#1'㭵zMD$| "R1}܈sDaDoԛ<^\c4hv;fCK/e˖-7YMk~9w6 ""/"Xscݬ_?{ikwpT~p IDAT[.\p]wo%?֭s8'TQSrlokTﻉKH1p"NW63xXoٲ{w.]pwuc9sp饗ұcGρn~q_ DDbF3"R1p+c T {opB%8'#/w|1_ߟC9vډSNUUU|r~f͚7n\N5)閥]#/u3="">~)hƘ8JlM{YڸIb%$''}[I)ɡ}+%%%mۖvڱ~z.]˩Gghq5ZkzMD$< "RЌ1⬾߁l3z, <¬oO1D/G\"<_\}^oK_D 1k\ސ0 hZP{8 MwgS_#ŹU^=xx]Dkv .e9w=j0. `k.'p$0/>jwQg2n""QB;/{?Oj 'xyY< <ݎ-}Fm}WMǁ؟m/Y| "[ "RȎu۰Ћ~>:oݾ$ pΐ\Ȝxk>`O N6h al}ѱ_?f%HT/"0mkl?vE1~=3)ȱ} \ q_>Z#=\^i7 B$|ƶkG:8@8;Cm p/Np\x gšLy !6M B$c~n>Jxl_M]#85^b;v]DD¡~)8Ƙn m;}9n8f|_YMqN""aSBk<PoI*ù@M.kZ'\p'PLJ]S<_8/"/"Ӫ=π\lҵms!tA`o)NY!1yxVRMcL]`[X7פx=qϷfU~f}x=gyҎ@';(G1DP4ż"G "RP1GaQi83^Ew{iSlK&j뾹H8T#"8 w[JKi*L&v~Yt\D$ "Rh\kavI/"/"m#9[XjCc-ϲO1ji<~) k[Xؼ6̟GG\@k{wED¡/"uiO3[*nǟG',%hBČB^]xm(EB~GQݮS6IZxk."<~)M6>"(d.]A,G<^[s)H!8K{8)K]żP,$LĎB6QbrM' Zy(RK_D Bĝ ;%VTƓ=U?J{3S Pvfa~\D$x "[Ƙ@7qSړy?ҞLxroWVUvՒ׏B~xSK{=#GgjC "RE$<]ΨqQq}f:~b_yC]BĎBRMu۾Nuڌڧ [;_[E$vID'nյ JS1^ZĄ'<5 iEv 4/"/"q婴{M=P>],WQ ~/"1/"qO{M<$?ӎ r[:SڭͰ_~~+Oz8)PJ^VfG@u^OPlH{2~~cx)@zl}cAg:~vDl'3oNf1Za`)H.5u& ̦f-iyҍ)R<]+",~]4nSMUfKn(> K}V[ PE$VE$xi-y?e6nGt{ T/"/"q)Y'Qm-r(t<'pZo=/"1/"qmC\J^TfQyH'pk5/"N_DbS tOfp5f%/m9جK';}X/%x&UM?i=v1( k~H(HxhLAn'֌zP}{RM }&Kq2n5E$VE$n<657 1>>ݎO}RTBĊB͎^whx7VfˉMӎa?U""QK%ЬN?fk˅q3YN֤hEG_DS"ޠgӵ/> &>!}}N~~OuE5vgc\fOfUk)Hx KI?O4uǵLϰ*X-p HE$nb+eF=>Xf>a]W "; "7C򍹊guK{@_DbH_DbSheɡTfDA|g+HPU/u?t,܇O}N߂W "; "Rж) &L<8~²j_DBekMťO}Rɲ|2dsH(HA_Uf[̨GL>y3LĎBmjIx W[fx9ySf&DD/"ɯ,~1)@}n05%9%" ~T,U8-ulMP$紗HE$N6xaSoU(mǵLg3i#Z""QذVc6'>b &fԃ3sc~3q-*RYE>?28x9>:',*b<=ED/"q hTq()ҞL&>__UD"K "74TIwÅz>b竫ɕE$E$nębQ,~}F *JXR}?3MMgiG>ǯ )wG_DbI_DS\kSMťO}ӎWV8{*XRK?sO2d*>++RfE$E$nfzihNKɋ. /sG7-)wO3"K "7BͰB҄ %>#N=y~xXRX~gY4qϢеY$y1Ϩז$3s ~)~Y>n/]OxPl!>Qf>S<{?D_Dh&B __e6ˌzk~Lߥ87""Q8~1e;S2}z9>:ϏWÌuK_DbK_Dh ד]6dE\fx>B0ח@_DLMKK\Z}#>WӋfE$E$@7 sq-yɶO}f:~ПvDѧ~*fE$E$vƘi?{%T@i0l,?bt}Qd)T o~^_DbK_Dj&.C zHxQe6Q]saُav/G Bĕ)Kg'*O~g/XSoF=B*ycsR͍.XSl%lg* dA|’*E߹LĚB,RGT7% t. O)Ɵ;H)H,Yk7cܴ_#YvH>,y%3icˏfE$E$>eħ[Ufd6M[7}2TI'/Mw~"">*DD$24Z͗Iz^<+}sm2m86>Yk-fE$< z*#ϡy8_(1gZ\fZϿX o.o L_DbZ?c\|Vls)ðzRI 'i?<񅫱my@yRSy;nVVqWd*ρ९Z.ﲝl3I.v< "{ "wJ|^kGaɺ75L:Z\g*TT{D$\w[SZB׬_?߬xG٤?}&Kc&xߛqըDD/"f]l 7p.X5)OSK}Zg.~M|AǓ'CMMXlkG{DxK~.)뉏k6YDe6xK6oM8}sHAPB੮/o?nm#.\G)lOz}^= z5}s~)*B0'5rxrhbҜz'Hf8FSmˣeX?Շ_CקS,_Z=wE"R4/"g]>}Yg>IzeS˄IO3VCǜf3<3 z=[zPfX puO~) "R(GK`7鏱s+(bT_At}z<)8cOQ`5*Dt£%۾t3qN\Xkp~ "~)ߺmt-<152CD SۄaR9// tvRd4fCᐈHE Xk-0>yڢf ?Hz<Ŭ|@}Zo~k)O3MED/"dJ?&!m@7S.taC׀Aiݓaܼ59@BGzB k<`}i~V+ߥa yˑ~tW S{`]?֓HtE^:{o[|/"Z0>C_/Upt3j{QR-˫Oӟ嶻E@f,^""/".`pZ6]|PٔŽ.whC,Z y6p&I?Z[""Rd]eódz[(S}j<~Bz+aZ{'_="RpE`()=v]]~} ^KB~a0%Q#@;6xE)H֮e+'Rov9ldyӀxFٿGZ YGRVsSuL~)tZ}vcޣ3x 4j@IAC^ۧ_'9[, x~K x|P/@D$Z.q/kjcpWG0QB25Z~ǩVu7 >q+F`,mb9 vfeCpZ%ts'B>lpqE%  }vi\ `C> )H8Z̦nwxU/8T!uϏaSWmFnC!M[+w:yHE(Xkc.9B[q ~|U;։pIWɳӏ98m뢭z8]+"EZ}6lWnLxɪߋ}"g+r {Ze{XkHD$z "Rlxa7\cҎ}V+̪ޗN0:=psjrW=,~)*48RE,fsZkh4q+|tz,?_D Bkx;_|P}.Is7Fᆳ3D$u| 8X1O(}@cMtt/" "RKٌ|P}.KSsкE@3Չ@Ir]pCν~kGD Vd-7 >yɗazxР^ACzб;6N: >#۬0FjcsVܭғl՟긣)hƦ+)ƘG@sj/xm84ߎ[3ckz۠ax;`&rr7r }6%9v%"9~)zƘ0!ܽ y:MxP(=(>o W?H~\I5_Oʱ+XPZs&x.i Cqܬ+>ι-&g;c7Z{S]DJ_Dj c_qJ=+-.k/6up}r/}VD$2 "Rc.ƹeC~O_c(Y\p'|.XJ'~lkvVZZOcz`9px^8{xPG^a~>?hfEV2 $ɏG.^,PԱnz|*K{.c\8cED"/"18^ԯW'  FKGdxV&?qJ|\oc""QZs8 (tw EC1 A"$<,lqd'}w7R " ~1qj;{;՗@¡" U{0fTYS Ysmx!ׁHEDcLskp:4l!9n/_ >\T IDATÞo⫖M@PwZs2{`G?"R$EDcJp+9.陬I@8p@31)qxrxe ~ O |wv< u>kŁ FD$d ""I1F^TwM-vv BH Ƙq{qn;QGQG!C)N}&Äa7"?{7k=*D@_D$ cL#짬 {pzX4ìals>6V`p Γ=xWHED0 <VeeK7uWh ZvZpmJ V@I l+WŠbe|5f΂zI8pXk*hB Ƙpfψz,p!})#rJk݁ FD$" ""Tauc)pjOJ#7+H*) ׀Q%QIDo+s,p7=Es">wG5/ӃHTED`)YFENR8XHED|`i \ \ԏx8h TLeٛ7[7c8DL_DGƘ8Y4D<5Κ5A?+\cl@#"1~cG=|5j'7pPA˲9g־`DDb .""v 0vz{༁p>H,ݩy$|EY5ȥE6PQ{/zv~giT3|~D=.~cOZRnsgt%:y>۬~'/)ڷHL(BjU_pԷο,4uB~*P e`OOk7YiZC_DƘ&~k OyWE¿i^O>o6+ό~fֻkRc "R$ǹ!m^:6eK:öi%*mg mV׉H-/"==~к![sJ{l=maX\ ""7*G|v=Tgm~=n {yMV7QG35I9!=W0y |6W|ˠs t2cpH- kXDDH_D$OƘF@\-5ԑP \+ፅ0yL^_ i]^f78_PzZ%ēuL""1SR]c j xrlw{|n}tK{zٞmY N~t%Z1!ĎfED= Zvyj.> {G'mϵ?۾axW`Vɓ1 ;zRbv0gc/8w2k Ueٛn:YkxH""%;EDq&f[!-.?s "R)oSŹ<\{op?~d_nOg;4`㭵H)`/ \S8<߃HaP_h3%Ъ_ƇRmn~.' ZLrt&0&a -)"@B:kgدv ;A Z|/ #߀˹8 keDDdH1%;C:<]_3 |[ÿ;f5=\VwZED fEDgA.;:Լ_`Np0jq<}*5_[^6` ОfmÏ8YlƙwHqӅ"" Sͱ4_]y;\X.t1gì(>;3 9'E VL ր955g]QT# FT@A2H3Q}zҭ~uԩQh ~'7 *7 t%I蛠ms[hXJK GRZܚ. Cň~`HlL _`ޮ9(Z(yz C7-˚B`D`0$@DJg6Q2=%m9Cj.υle0 1`0q-CB?ϲT=žG+3xV\|c' &Zv`0 # !&"p^L38ĶKuwTzQ}Ur\+ $l`0KL~`t%6[[RQCҰzvVm5;:,NZa:Ck0 x:f+D)h4q$~? # !""R<4[ >:o8AB3^_8T<|w~>lC$gP{4˲,}oD'=@XDkY֧9`3ƽ`0sjD.>o_8se*6+4U^"rL4Nmh)"`0# !"2%3OB0JK68ć? [5?F&"dZKS~S?"2JD"L C1b{ A ܗV}i-үsJeHǵg5JkR؟C!@w56{Dx˲F=7 }UQEm fn1k( ,M="%+@Z/ȡeyf0# A9{ujO)}˦Э#0M/n\.P x5Y/QOBP0>4nͿeWئ{xg@fX?BUk/1&90]/25"CDn~G(R)"#!F C8WdlTG\'sߦϦXs>iD"H]Apѣl.@ت~/ؓbڛq}aYָMBY[,5jb-;OD6K!ϩ: 7Jw~p[HJ 2NЅ'E9gYZe 3ȓ&>yK>dU`P%LT܋Zs`0c7 lvNᙋj|.^ ~ѿEh=dÃD S8DdSyNx&kס})OߙL:Ձ%QDvO!go0 4` a4m^ݯ4I>FKi/捰1˲g?"2PD^&Ǣ" ;4jSˁԼRMgPR;@2x X3y!e%:`0 " ;gcR R`*J||[bЈQ{Cһ+|v;d~#g WWxq$; :̳V\r*}R5n&'u eY`E_s9w|CQ3T}%xy.'*neMMe `| Z~?GY_PeMIGk!v»u> 2{{TxGQ3դ_Ew`֑. v Bs"N໏.߼No ,F j9i>`%HOA?b_O[57zk"r-pNvŸ=.\5u ~19t ~e}}~k``^,)EDnPrQcNxzߔ`wOz,Zu `| "GD$\`{"WD r?xNucA;0}~_B?oVz1H< $&R"r0 G)ŸTJ.ul d0# "EDyjy_"R}JrЮ5հ<8JF?kP{Llۇ{!o0"R&"١]igl\99Gh[n^C/ʬPxw(~w!~I{( ,""uD Ԃ+ь0`GлR|4@-EDPڈHKߺo<B-:Ѻݗ n3@=y4A$_1e=9"cP.psN bPED@.ܣX=RrKT`0!F Et@XP8^D ݡ&͘KuQgwpФAx7=NGzg fu_hU_4L~B$;`/*"ftB}& D;uO??~c0)&dPȦ F@o'4_Rev*Ge8 ""W[y~ E?Vuᨽa:<4 O=N~Y5a:ggv\%p:O{^Qx|BrFy#xY Dz,͠!_C6gD$C- % Z;s~j.0-xԲIɪ/"RlQgAyjp~<<^]a./z"=Εo''^V Ue^xH_-WmھvG" {pƜ\+H/seYF*a0r DD#  w_kR7ÁP{)SeE|b ~г34Yw]w wT߇Nutqgzm4ڂxP/ktDj?rQ) r9Du_cím٩߹9S) L3-c4B1~ԞD4'܊ڇ(KX<Ί_Mn.%nD8u0H vAw3rce1y~z]yͲHrlr`+AMC# {'M+P97k5+P"Fm0/ څYk09Mg(ދE#vʀ"ro_!r5u|L58;6x38h!@Z*FWn&k~B[|RrD\X"W5g yAԍǙx]~7֌tQuH,{<lBםHXM?qd`=6< {{ Zo0k6an@-:?j^k3i)"pݪCv5kƧPFoh,h<|8^ml̥#惮E i4"H GYKZ]7GPߙ Q˺A'x+R8 QD_# <#"}P/dK}Sn =C Zn "|ws=V'!0>8oPsl|xNQk¸?.';_~^DN ?",$MW" E{}x3yˎ$"R ܏l|lݣ.ѣ=<{ |}s `7_x X|x8#U|ԶӚhYjEAYOJ,@-r}XjM&oNiNW`K`D'Dj]n wgK7.Db%eԍWg4[(:©n2uOCa­0s^s 'a} e-d(\ icDcl_c[~??-!L}(. \L]WC7UCTlTcP_sgcDZb} D xMie}^9}nO6kϐEI&7M%PK !M{{aPFf3Q~tZfPjDoȥVHP=/}{O';|> u!D#Ͼn"V׵m`^ӠacP9^ D.ew;[#ܜP!9缂 iU:W@kzjq?+`03 'QiY(um<,0.)MmA2j%F N~><6( ʿ7;D.if5)c+8yA+5|Z2񰀹 #VDڬc˲KDDnFьqT(+-zD}*I{&im ̉7Ǡ'JG+4)SabC8ODH:!o0=s"˨U?\ p(U.?(A-ADBkqPVڱ2k|Msxh줟BB#_a}koiuQ{D598aϭ;iL⃟XoF5ɞ!k~{1&uisY5]6f0# ܢ%A?$O?-k}?lr[Gh=mt4Lcr90#Q2x&lIkb\kO7z׵{!EۚNc6>SA^GlOkerSǢ }WMSP35SD J?Aq<>R+kP c;CyUV,Ov@- x҃V C/wѹ"~Kx N7,|[MX5WD:o=Vg;F} @Xq=% ~#`xcnXa2~竽F8_^׵3dIU!V`D@D ً`gwgqeYٰZW~s%)^2^|3lrkOLj 53cj2A˷ ao>RDƣ&~՘RYUG /g rpern<0owv1-gXro_(w>z}'!u_hE]S1Lźw] ))uCcD/4DlruQX] *z>2RTH=J6pPjs\#3o!{, I{x:(qL7~_٭"NJ sb<ՎAyVeMOICx6hڈjm|+jM5l!R-8!:Y(G]Ud"0XN#*JPcgL' ׹atouoP+GuJ yĈ~zEaUwB捻j_@] 'Kl˼n1lwOt0 8b߲) {8}#[4\{r"0b[f[g$Dz@+yiORʏpʫ{P 1n:us 9"reY1E !`HFD~@)ZsƯ< I L0-82p=,^Nxw}\Cxm34Xo>ylYUٞhL<ϗ,_5|tq/lotx?ۿ@^w΢n?_ x>/ti]gĤ]lYJ';x e^>L܇Պg=N8 N}w~N2ʊҶ8B^;/Y}HOM;Οh{ζC< E VDE7/t`/A2}R񯑒(-H+~?%~x)u6<:ʿfs[q1fI n>}:dK5Ų\ < 7~ :$‘guca;ᡯt*bV/8O}2_zN+j0Bw`H45ch86CY0W+NjP͵KvӺo_sp8_DW?K;R%0GXd𯓠{>G4V܊PǿvxS(s~(#x;` LʃMPc6ACPכ=b "reS3ZdP6]r#D;@3YIQBR3s`*P o}(?qſO]+oO, z WPxp9ЫGyVO} 5,L컯}O2T\kv- kϕ?7aD[P4&IDzRu0r̍Vw1K y~CED: R;ĭ *nkWF;y\2߁XD iE6~τdPǶNp.0p+:|2p/,w"Bl _Ԟ›ѦuLf, ߅'шPr {3)+S,}pp̛T7)Fj%BݧQ~ʢCQg9 M28qf'Y0rr)f˭/ ?mƧArŹ_+8>h2{'wg^IX p?ޢ1@ȟO2p=^Z7|7 +o$I];XsGoM ڹWD[5#rI!ou1":' 3o~C]w/ ҟK\^d9vNL@=z=[?Bs|؃{@kf5e1'>Y9u#~u+ω}ё'̥K 9&`(D8ԾLUx/GuLxyQwFct )C^n0I,Q820>7R\rGqJe6r!]\!3_P$p8zznT9~okuڑyG}o;AD*i0# r"`$"!(M&|eu>dHW% $['cέ5 OPe jyc?LYw 東yspE JLBG+RXZ 7~ ނߗ0.8 u9Ʉ9q㜠& ^5OC1P+Sc-E SQb;%?NH\ta1?N3Fp`u_&Ʀ\A.8 Epڀ< |qaI7/78䏲@8n[q5ǫOgJ(+e^׏O5Q+FeїskUok{8֍O`c_ma2ԇt Ns~ @f|3䕷ڭxQDip8s,Z`5܄sDg·;]zrw+ns#˲zF.e0c7="r_gC;Ow;zlLg)CxD(+ |x=} [Bpsx<+$\|2<* /k{H+1OKߺ5OTsCOr+3=a.|qBo&"b4r{G]GIFVዣcCY-YZ#wmSIM3dQ20gyxcKvApiC?t ,Y6/ImøcrU}?تzѨ3Qɠ,;к>WY+Ưayʡ7 t"O$";ˠ"seY/D.e0# E6F'0ԭ\' ko"ǖm CqI*"Ѿ|s#4`g y m dv>s㛟O3AAym?B7q:Ղ֓}: B ꘱ n 3 VE*xneRw^ ݖe7-"r&mPhJPa ص<Rsh<96/ 'i?`bZ]Z5=anP a < x ZLYNG'Ú́ۀnֺ_mU[Eu?f.-.(M,+^!o(Jc1DG7˲ӗwќ8^mLTzka5x)ݪEB"$Q}9 n n +q qإs tEbۈQkFkmȣu?xXZ`4{"[āI@T(P.q 5^h#Z31X{;C8Fy U(À)n~Px>Хq$lbr@ÇA9L:"Xg]{\\+ቷa/Сv.s;:m vSo+":ۗn;[Uo((%u?0O:?s%<<0 f(:L~UU8('-,ˊf0CDvD3wC`@+~i*цV #o[j^W?Ms!TWku/{rDrh5Mich֤y3yХMc<<ݎ@ :۵uYB}K)[#pdxgXχPbW ycݯMaur}˲R2 (-t x@ V!KPaF'p v/xхLIJIʊwk\́n\k><v;o ^(\Vy5ܯ:4{jk"D\KM$H{^) #@ C Crj8\TdH3?r|~gb_4"p1eFGK[j uᙫ]mZc wӝ'){N0jú] :u| |OZ^:?oސ`Vc(*DTPJy-h']pEеxu'N~vƱ;X<5J@Yݻ|G / >eQ S߽7ާJh,X\Q ,J*ܳί[w*=aݏbf=4_l\Yo܌u\ KW#ZkY֫h0Ĥ0H#`2дB~.]r 4]w|:nߚ;َ)hu4_O79Wf }F~]8pVcOcкiQ)_CTHJ} j߅&v͉8u9gx< MY`ԟv![&5^hA?c(7vעnu;úOyT\'0 wЪA{>|Zu^pxb?D8a.*!j5L&?%F Fе# N<Ԏ}oC e췪C_ވaoucEA~s]VUWdq1 F -,?N' p)ʀ8xy |: lxIDn[?k꽶.q,2)RomVV¥0o![ ;-Z@ʲz1c7@W{ ` *R=&SsJ"cN|0F΂W~yEsTT$ƺ_cugC-ň~CQ "~Q\ k셜abv%01إ+ܼԫP;aeO+5-|-}]pL h-Bf-|Uxڃ9yK 9,,xXy)4N_Qhe}xC-C| `DXCJ%\;bs)ݩ8jkfOذr6Ѽ>$>D!m| V a)G'Rb!ٵGQ&fW;sau \5):_/~b}JaGpoR|m0ba8>]}Jw}/ן p87<%<7 9^M._^tX1j ֝!o@j챆2xmj3W_.èq܉s Z̔Sa>o(7 D+vG|q\r+ *ڗ8u*~XзLV—W,5 IDAT+eJOͽpKL9?_ yb]_C޴teYY"l( PpD 1?(y3Bۅ'H;1ӶKSq2.{N &{M0L =aAeSFj~C1H'z,uK"櫬q&0lBEIcUk_gw8w 쾱x&#Sb5&\z}B y*G$㋯%q=ݖ4@sS<~NuR0m{#P4~C1߂{#֒x~i+zڮ@4x-dУ5-E_TEq8 郷/UM<&9<v<7P~;oMj}0p/9Ʌשu½}J᧙1ocXmYǞCa0PpDd>՗k%!BqF0q/eaKM)u& | XAðm`GjR>w=iq]]3ߡND8-\J#?ʪ޻ B^"?e> h91 ,j`F JJdk.ClWoAl//1jf^wM[ÉQ[ArDV 6h o\nD_E-BBm e"|5_D ha.|,/p/>0W(=@ &+lYVإ 1PPD!^淁O+2v6 H\#ן݀f{ :PnڌDU0dmx[6&@w;ZR !Y_9S _~ {sa=Jࡡf-D:,2f!4 WJ { 7 gwKnfuwa=&T\YR놰_v uJY'O};0o v%z1Nu%%"pEw'Y#F@3T8Ψܨ8O>x{X)^aʘ1s`Masa0# qXuP \Fπ7oа]*TR:aW` +2sC_ԨTw鶵x9/n(6x?eBugHka?\s{fk)} .}6ml4 =!/˿__+ppĦeCYзP /_0Qi!e7P!(s[ !>{Hq=JJlO]ן?;b#g'+V7&CCT!s,K ߱lP*nbBbZu #܋Ⱥ?o r: ^?6iÈ~CaDЄԥڟˆ%cȭ~E[Hu*g 0 %? Ƣg8scAtnRN)j!YVZ+.nD -Zk}>7q*8b8$X`2xB8y8w!3ec,0)X7GU2|*ڝ.M@^>F81"l .~^F aA[\)nyn~$̑Ų`p XذfEzLn]AO_E/ v-Tcmv5I\kLlh\F\;oXwr~3T[Vr+?K0~C \[g]<ݱ^WKǠ“F=e }]Wn(]vqrd0|;'`m< t l;"=6uz[gnU *uOiiF ƺ1KNvs`ݟ;?&޿vފjo6!YZ˲&`H# &X;\BIܶ=<4* o7;^ERB셿Q&!`ΰUEUc068x{R_ $t;.;Oh7|Dz:4ݛlz.| AbSC8-IOlu]{ȽWaӝᙑ$f0^ؼ+54//O0MCaDЄ[5ΗCgƯ{TEz}IJ \gRLP( Oa K[xسwz)lr <1ZMr%FGwk uJkR`EEQ y[bao3c`~ [;TK ݯxIq1F Mt~`zz7aaQݛz(g/Ż&ey-MTr/Y}8xŲ>^։hNc7D5"VkOdcB/k1z2fV4^{Ĕd3 NB= xH<=y0~CbDꃕ,f&6¤T J穞$?Xg9j{^g<9vO_ˏM#v EKPxp$,qD ˻:^˚/υ/Z!yӺsa;dwPXwI M¨~~$ ?͂kO# EGi;`h韽?D9:~n֊hi6 > EEqF7u籤f>#8%wD߁ 7',PU~(<"L5bg[νv;m ;7"=M.Ysj=DZ=^2҆]z>պEI|-?RM7iнttkOU1K&{`tq1!F Mtѯ)~e;C$+u&~;"=0_bOBw:?oeЭ-o/qp, ƌ[_7 g0ՇDG'tߪOE~HZ1iXZk^!kwOYS 㿃χqФ5[{G{~ `DUDk3lr+0Wx hӀ*#uwJ"=W V;l'ŭ9 )[_m2 xx3U }F͕o6ԸؤjA4BfϪ{7Q\F]"?_)I0xgjZ%Y J?e]zCL7=ѵ Zcc&BϳaHs2P@{Aȝ~}qmm?nQyܬ37:xS~Y o G5Κu檝H"E-53}4O.qX8tw\hٔ\A- 8VX$~9JD:'[6'- 0Phf$\\%pwұgwi<qLіxwа^GVMᒣU7x}6bS̈́b뚫1hQ/]BZՕZ}By/] 77?",}&y.zF}^<8h'"ͺ ƈ~C EOŏIpϩpP??"=~hQ{J2px Π#U%NYGCa|>=@b;#7jD4qhOeufZmO)yC& ^G;w45X</",#/- o(""h֝4+ì?p0dgdhQfϳHϕKkka~}s;N"Osf 戊9N} ΐqqpAI_%;%=j*?,.!T.\"? wAZhTtg뽢tхB Ø;ĘĢ?&(3;Bx[-+BI _MgFov M/r x[dz*m5iT.=E~~? 3懿#'?Z:QUtQs~:zhB^Mlݯ>xYN)'\^E/Xg2e(80{n0Šg.A~:9У%dnn-lVq +\w6Э7[S-ց꺼 aRWc\8Ƀ£MIiC@KbҺQ\xp9g,89 3@ٗrw?_ !ZY'ݚXd. hq֍SW8\l١޶z} \ "2oM!]xrp8W_چyn.4o{+O9U]ˉ;~Pa]IrK0x(B֘4N;0LM 1ধ "0Cz2 #Kabv'bgm0m% jRZן{f/N c:ahxv؉_ouɴBE;' ;AkH0MtEy"=elcYաf>'"^HA;u9!&˴^{~ ,!Leo6a  //cUzba!bSpB܏X3~=ôI7rOemIi=뇙Jau5Kv|W/~>Ұy%Ħj*i r{_:)Q9:ٗdg/ s)s+T{77zyh}_  )'Vt-:o_{+h;r_l-EGH}itj any (统p% !N1 c[SELZ1}gd~;zmzw[1h~9Zݗ:݈?vi\zg>u?>mCEzҏf[۳% 8\ƮOt_g܄EfH̟ ;àY?7>BdFwbv7b6̟(NP=:+0Exl<4pi) FK[R;?λF |F9[Շ(/SةT&a6a̷),[{:ٟ_ҟU!&4~&~ɺ*xs hq5x$72y&M8 n|<0@m9p'TÁQBa*fw$1iAQ Ww?:tm(s 8>ˊUs}$s?aN;ɺJ6dDh8b:5M{$N~Jdغv~ ? \b.vaҟ鷆| LɺӀѓaW0f )WR!3ۯ{ǀeRMdŧ~^y/3A p5E10) .&XDŽ!08^?6d` }P&mQF}uaI_ݯcg מ탻W+\yzwYD;K9ޙoF^.\pv50L#* wA+=[_nOƧ0)rpTxW0pL$1a|q$܌ڪ^ 4A~XMP:z"AU9:^ jZŭȱ2uW O5PM4wT1IZ՗EULگnmS֏"=l,:[n{ZͲmO^%!#`ݟ ޙo~ L<кYhyTYErKݳ lGƯ֠xOqa{ĔPB h}(,7`O]]磮 & Tx7Oh7v7=x::ًX3q)JqړtM/a&yKD1 -^=}{!U#aٺcfi<ֆk// q\#1Ic~OTitb׬Rnʪ2bc}dOe& ̠/WA37WooNxcw+π'@tXs`Roݚ-D[]i pN<&".VWdRW50f KϦY^4ik.:I1/ Z5bMWð9 P3`^׬7<&FXǤLn:xVH?*~OZpוp_j=F.t8xO}M\}k~voi\uv BEz)k MN"_}\*">HjPυ1sٰ"h5ôm^ իnٷca )lQ' OkfW !MC͈ELJ!#%GZp{@ћa@x`4*;viώ^u~XM_X4Eߞ[EjT(`؅Y{(alNRP|T#2[L] c_EP 9n oF@]ʗy S$N O MKB} HR*L"4pXܔ$7Z-G}^>[ )sFvJ^*D%7_?,$f-'s$"Lc{=/0yМtӵ!m+߸"~ZOe߫No}?)rթ\, ;ס10\8tS){:խ7& H߽11ZĖ!srST>žS;w^Q39&Ծ  n}$}'1ZuRШ^sӯց$RiEDzhhW c*UA [?0eLY ?fEኁpG%J]G?wit?7FFRunB4 4 + Txir72f/J _?u pi>W S]Ǻra_zv7=:(EB%o[RUHW82!tSS%\' 4,y([S!|;XS4JX!okgjx8H<]7Fս'2> 3Mr J,c!H.p;}`%Չ@>M;iRAQfDT(-gtKдu77tk/- >/\ Bpo:!"*7"?'pC j l;, Kwȴl,K7lMZpI08H[M'IQr Z,`zpKψb ʥ^OZl,JC8r1Tmß923?F 1:1_MqHX}.@zr@"f,  !0y!<1 ydiү+ǖ󼯠8ʈvntp"{p?ࠋ:WOaPܒ~^Z8<%Ԁsφށa8r}AQ \tr6lᯉ?b&'#dM8ibHUp- [ȌW*ص ŚлݵBbvg-fnO's"`xucot8fyc2`4-SEq+r|\}5t⃇ț@߿O $?"=lDa1ޮQ~a]1S3vgy*QX8ZuCp27WMסqS '&ƕ8zO.]h$cvq;5`$f = M Z {jI`ס3dXNa4ϟ%Y<-BBă!'>{#Ne~׺" Wcԇs 0֩7ٝE.]8R吹@ufsa~m _sÍ@p G=V2dUav5D`tXᯊRx 鞹bW(b4m ]VMc)a"fCY?77au&͵\^ޔ"⃈~EXUuMLLbK )kjOQi20x$,Kej N8N< 9T޴xjԈ`~EWҥ'' 4h5x7 8 +4K0atoJ$d_ߙ5MZxܺ_ gO8r< |86&96>-:=Շ{q!1v*$ 5񟎉@r# 'ɲ0r>ppЭ $|J+%u?(_N2 4SWHFRa@oȝjթY6)MupŐk ckj;5sף$G]fTNC  0| {JmLa 8aU(<ɹBAaŔ#1:4rP@j=6ٚ""|.s{ PlwɂBd¯߉m;aHt.\y NZSxR~ #0PA},nͤcoXy5ꅐ+=^Ͳ ?ewޕB⏦ Ph\ |tv:Zp"{5&fU /?]} >&`dͣ ȸطҺuDkppYиFa޳rtiQϿj.v86k(~sBJ~cĀ?=M$[{°WP\A-Κ <#ҳĢ?F,cB!][f_yHKRK\CϿ)v=V}!/Ͽ}dïߍ7`$|hӔJ!+1fsA=[H-{OR`-eޞ{MDy^R ֪,7O\,:)W=Α>}m!&Af ah\<Ejgk_UHGQ{կ|2 1Vb )W&|6c!42Gi\7i< xpQЧ P]~o;xy)-Cbxn.?vL-r~ ukCO7jN_vC5xuﱤfǶm'&q80wPvm)v7 PM ,at1f΄/>(QScte&E,ct&"d,cd3 S)`YVUX'[ܚÅ`"!96&9!q3L. vJ%r#K{4| ZBݚP&ԭujשi0 w.A';N5XD}?L' /CUFH~g#+`۔BFahĽ#j{lD!Dr˝N{p7إr6vLKZо0iԂ Kx /knm;`W04; aֆ3Q㾃cǡO;v, ]s[ԵP!fuZԩmH5M0g<$L+eo?vaX Vt,9s`΀/B%&p2A!]E?HרhqacTEbKa!q> ؄T6wtվp pelD* o5knF\|L۟`V%NCN ,]VC *á{OP li٪`}NH(_sbfزQO@,cb`p9Uq"trіuC_"' Q6 BIptGek`0Grlؒ$BS5)R3 Uӯ)P5ðP=~xT}BR 4V}q4P1'Ģ?&c-@-#WBDra𾔑lS/ 9 9鏵XGf6[r+h.=.=En5y64SCc(p{6@A5F2c1EB4·Uw[1##z#]vZEHGm<Rk~v֪SeE6aB|t}: "]7}e{,m%ЋX':tn~s '!kƢ IDAT>{C}()yK`<>fkjՔwoR1Qj ~_E8$qgK /c¡ Rlة=|{5ÀKg[|%y& 8&t@ >M oҥF.fnL,caNgHp*7HdXm&f"qo8˱=^T%egg{~e=\۳oJM-䯰}B?<*7]}Em<5DEEL*E<\Л;N[kamk96lt"x}):g1=Ktj_gb/|cJ`odc{,{ks҉cbca8]\\ggS|CG B!:. yoAqAXy6qSvf.kH=鍌*HYL@Z#>(_I.d_Y`OP"5 *J.>y2kķSOu,tMDi'CAl16FY:!H4sE[zW);{9'HKAL4CwB O@Wƾ2=ְne aߺot1Ix+3RQQU'1qYv#oI Nд|z ۹l{`Vhh ͼn"av#}R'DWFE f1UXǤgȎ*<\+a0dn6I$kXtұBږ)UEjMcPsޢ]pXݒYgZXh;06`+r0XLf6 r|#KhG~Ⱦ}~neKaHp[cba.>Yfr,<&6V].w=-l}z]Wɳ} c^c;fw/ujNNN@.0R`XmW!wKE!o=o >TqվB$|Dz6 ǖXDŽH<ݶVϟ$Ģ?&u (B\UbZ'.X>q4Ea~\W!=J[ᗅp`ʄаٞBUTo6teKY^Y Ϯ$UbKL,cBc$>pRuO ^y"`9NDƪ²G}"5vYCFT8pno&xԺz&؎BC3u (T/Efl&uTr#Δ5ߩl&fa[cb_"kxUZ] o7BEk~<Xq};cNmhV3֓qXyؿ~IURKfC@WƾvTkS"8cic0I!xv8.IѿwiXtvn/E}sʋFl`X!Ct~0zw]~:V~6Tk@+'|dRFE\G4 LM6)`~MkA0'T5c,l "8V08u`vZS2,^G\KH2%(Ym&P/h_mK3QgϴtDT֏R*KYEƼt!*<˯}=/z+P'}Tվ\ᝇ,ϳ%t%i~_<0폪Xǐb*B!ĹBsmA(ԍ'cэ4* ~k"l1fs1נjNĜlU( *OQ#mM=6j^ ۋ8ؽ'F !Dr]SfF!ܴ ADzCR>*kP;O+]|5҉"Mu⑂Heow1:5M XMU;W>*s_T7jl\\?0BxƢ?&1!7?/Ԅ uLOwD Y G5z509tne0TQ>Ҩkxnl_ط'*m.W!UGeEa/((\OE<Mbpp%i{ h%S;nm")| tnm8hcQoz/w#X}RF0B4EoDǓ l[7a|ױP`*7MeUb: *1BnBאo&zpTHtu@aʱ^O_6 EQ' vk:rC?Q6T*7,$o}}UE ߪ :Å7ؽ'F/2f7l+{@*[ YEzVׯ멖~TYHT=sb69Dwz)U˂^ 'վʽ,AK6A/aj|] ^<켸T&EJTubѿ#@?$kRVou?vVyfaPߘS_F mu-nY aNk ڌ6yLVoB}5t88u[Blt슛Iw(;o.k/CtZBqB~Zc ߍBB o{f[ a| hk&+W҉Ͽސn>MDg_pFP"Oj7)uUPqJs㛟i0' iz8X%jOlA=V>BLB' SL#BB%`6+L\ __ z?vB6T': }M"80{BDzJ[~.ڈ'S=kKtOF*;ۓ {}|܎ wttX0ľ|!ĵB)yb_BB<,Uk~Љ~X 1ظN Vġv&H/G$EL sYVa))槔 [4I]ixxX,K b_B+x\ Dj.%ECsw3aJݠ9n=Y˒Upme;U^r =:-ׯ+-Iׯ;5?㉜5ߩ,c,΁A1P dhN/X~;%BByĤa%G"#TE:ww 0s,~|P;x3 2ǩ~vG{LOFHm(|-},a=yޱ=(.+,Yϱ[п=AFXe>W1~z/ևw{y@`b"#QbK,+)BjB+9(OQ\  m oGi#?BFGtn=!LHQHκvQDoC{p,]ʃ%㤑7?D c|q1+FIRw4_7 =n$`;!)?1ؽ!\ h~F+N2gb em}F@qgxD %/{{BRVaj?`;F\Xg_~BfwﱺX{S ;v@ӏa7rW)7Q* Z?"c\ޟ6ka?ouQ1=8 <eF1)J90+P' QPNl\g ku#z^uPe"rKKb9?F?uj+Sړ\XX<[8roŋo[+OW3X-WJ}EioF"8צ͟u-Vl Bf~WaL{Rd!al`bEBt\TpFZ}вRrV|a9OWv 5q[ o!} F? M\NZD~  ѧ\z\r$ze߾- *8|}X W> |3E03?{R`ن`Lg Xĸ"腌seU#/0/-;60'EM㉀`3ႥK0afFj(N6m?&eֆU/@N1兿7s:E{PGˈj_}ho1 Ջ΄\=_ڪ`L3ہ׀' =ۃH,#x?"C Dw~+^;۷^ ȞD ׽pFB%?}L*(H$-¯MH?aBcܝpd'ʻ؅];5PzEte?b׵,?)L]F`9˒◃; }Ĕ nCnےq3OBpKw{ FNql:%py%l8Ƒ%QW9&=Ģ? !#76q0niL R-xnO5HMcHj7_2 tDuع5&ży7){Op$m / #(EZ~kR y0:*}9 ((ˀ5ߚ~Y çC)p>0d 4Js;,餇`ƒeOobџAmˑb<xVʹ`X&0;Yo?:pmw$#`꣨-u!9|7IƱNQ} /FSN7_Zm5ҽ%z`y-Aϥ _툘Og_QQS~2[*2ٯ`bkfjÓ;/\J}La%4a! q#@{(r*ǀ{8hHQͫ`zNpfA";\]O=wߣ{! f QcpH;ʄ&Ϝ*O%$B=ž&Z.uɴj w<X= :7>&d'p!62 cySՉEBӟ_1p \y2儾=~/GuzA<GL`GqK |(ÐeS Hwtҽ;7FNPixs_OP낾0EN&ݳ0n,L K?j *&GBN{qjK¡;ἇ_D)D0_=J,CF!boS%IA 1|oZ@`:H9[ 57\x#`!pjpřpE*Cߺ.<^ o1? yB~}` ` y"ʍ"5Sx\`*2gVz}i[8OS'I0bPi^fSY{_Fg3tR |cSՈEH!H7nYNF| Cnco :օ;{]-_D=28)[\0GI,"h\U:&th c-/.'úMѱ.f')ӎQMkpe8p8 {"sL"w鰳035m O? 眮>F<wݯvo!%O\5(\Z;_ޒ~LPCjе=Y:CVШ>4j9)B˹l?Vҕryp |_؅/GzICѿf-۷s@oxs FO_*F!tеeN)}9 IDAT `&)kg HԮj~E=g!?bH0Q8Y`/n{a@whE@`Gu"0t  o?@/gߟM2P4I@Z(.yQ<.*ߨΤˡwC,UW[-? rQ"&hAl k)Mg^dfK\زҬ><~we^Kz_6 0%Le >!FF96c)O^.r߯lb~DBwZ.ig1K{&t I >3 w*7{.8~e/sUb`a{Ģ!D8)pb|t>g3gH?m`}ɢid`-"ώnL,b~$%WrslL0w*8 FCq %dغ_oK,ẁNĀH% 6 & ([7/_),23քo_jol-Ǡ>ʖ=OW#:ӥb\MFdy]n$I qM w1x|L>w |sb-K^- /5͂ތr^ꤥJp:j'\X SuzJ Ǫ8dpVÙ*x/ǞW Oip nHDacOe[\_7ҙ&Cvk"t_~CV, Oݯ+ ٩{rG {}x° enP!pG >1'`d }e(#v]v;$x6|h7/’LA(\WØ8rENȌha5yN{?[ g.BMΠ`l}ź✪:Xr0em(/I\iӋ$y3Kb@<X01?ވqѯ!-u7klvg`^6cœ)0g2̝+[wUa3'u>4c6(D,=鳢_i-c"#TYhǿ .'a}eM-_Jlo"V"Q-%˲񨪆1WCA!։*&a.4›g`iyNW~x%ìk3fOO x Ċkv)CsൟTu.~+r7ω~I#2v[l.^ˈ{3ǀPjxp@Y񯱯 :<7崱θH ňnqo '(#1DZ{MRNo;zJ >=6/WX%>mA}&s¤Q:in204*;3J7C| 9IaUW_fg&~<%rCO~IrslCLq7Z>zn*, >,eI|ؽp085J<>1iTyx:P bhu> @l &)cD9u,LSC[zo~1sߧW;D;ꎞvr+?E$Ims'rslT#B>WnO5[WS߅AGľ5(zlO ΣÑty/HWObςc:P #A/,164wv *c,,j^I$5 q?e L zu+xW`$cZ/}^eDy!&E$I/Cz96,Gto(x#kC33߀;? qx^YoWqs0g" b۲`#X kW1kXUgN5<qNm4<%,C*&ƪmm36ɿ$:!}8?2Fe>MgMq,è<(1tJ&/ofx筷Ŧϳ{o7D$]|HQYBg,t\{7V9\/KgD4Ĉl" ʤ#鑊diJ8 j LDB|u4v'Igk0k$QT\CP$/5A}>!&베Z, qXŲv/,8p?0l¨xVu6xma]Ŧ` Վ7ބ{";-Dn5?&D$I〇Ymbہ? 4uJ'⵶sa 5 *qp_u'l20׀ HO1{[FSas"c^? , o~\>Wr; ? "w&xǍǿKgQ1(١0pq$~x0,FL6XV˿6UxG'c6WG} {UK1גM sǁIH~z"P\~~oh #WlxnS ~kpáp&l{繭B5t. .b>?#{Ăr ֞@)˰ll݊a<~$;,L+# ` bͅ~H nqݮGgy|ۢfӰj^kv}j鮛_V@mv'&0jvH?_b$+s,گm~IV"Ҩ9.؞ IzWokSV<#Ri??|N?nbKGol9In_lק1hτv xWxO얉2Kƻ+O0[9\)\/Bl8 ߳Vv9 V6L0ts$) < d6}$lfH~]CpoFuPs)D %#s8{QwBkLu{Nxo7WDG!#YjE̴4 f3yG{C2/a(}緊&Si$%:"`#{)?z*犧vfIJ0x@lG:[Ø_sю#'_ ##UVο/.]<0Fy|>02ӱ$#.-t<$D_=ow^~VX0u~41Zd7'@ 3(FRr g69Xag|x 2qnB07~mjkc"6u aϴpd3 ԿOy%ibƏO~~>+V 55ǃ륽׋ƍ)((VI^3m$aӈ!6}~g`H?BGdk={l<"ĬAhf3*Bd ;vB[k4' ̘Kҹ0gt@eK+ /CFnaC ŰA xpHdD5)=+-G%(q T0\N81(Qꭇ!%?GNÌOYbks2|ൿ'~H``ccKnn.GjmƦM'sYF}a~I \6ˇ{f]諲xu;64[Tu0f$|vt0~_Kz2^56@zuF\uyC}u% & QN/:]?t#QJ)#q+l ; M'%*Ei!(/U'GC~<#"ukNΆ] {Mo$?~%tn[ {juzu>U%2w'b-3Tݡd";> >ͭP^/t{bc… c^:---ݻ۷SWWp_,{iePE`f8 =?2 *R&(70%MWS{S;F3.xoW/מz/(un~8z=R gL#a0b( @dP"` eu )#`M0!o4/kݻD?\&@PO|vL`2C_7Vd_-끥g$\D$IɈ32~:lb8'LC}^ϼ Lfg^{|b njRT5괎 /s = : 0b&R&$}b=>^lw'*HO0>0yZZ3YfM`Y`3/Zma0.CxWχ⇺fanLsGٟoצx;la ޣ7^Tx?נ$k66j233Yj}'&QץƖ-[8yd Bm%{foU1eƣ~.Q W0gp}|v1/?t f&l8u$p}·m[n({ڹ=E v|fƒWzaR=̺ƿQP퇥wbZfڡ%O023Dlk\űpB5k,wZV׫j|^xؽ{7'N4-̾ jGWހT gݺ+ >_ k s0^|C--= .H'f g,>ο9 EvXvv~O1j9dTʨȟ቗B;ヅ}G0+ ~^O}|[mleҤIlٲnV$ IDAT}'藽^/>ORv*++ټysy>`,-;w.;w*]q6+o&rL(~ 8DRGi'`gΤ Pr(-RQ!XJޛr? cgÔEF`H6.Pi.RQPu? Dk g% Б}gȑl;Zx{u~[lYϛy}an;t㉏;vꫯ[ojβ;1Ɗ0oM KMz4ŵob!b2)1/#-۰hQ= w } ?Ɣ(~:VȽf`x1f]llzxzfѳhe e x}8|>MMM;w"M?~xX∏rqn79uؘ?­zciïas?E6,ا{p~&Ծr=(~9W 99Wp '=w1fkYdI}'??\-R{^dYy<݈㡼B***ӣ'|Ϝ9.N'NvYf I迍MÞ 0}*=St˓?~ s)Eq m[d.`3_Btz`p@վfoDokE??ëR\^] oluDYUc66F8p 1|nYZiXeY/MCG"..˥+˅$I߿;66Is#7BrHNTA=4L\J_|!xૐ䯴*# wBdiS`͓070FskB_3 F?~n/#$&282P: k7ڍ" x-ZD~~>]wfVh;Jx())0ؘX=#~#<% Q;vvٺu^X$)Q7.107O^^ ~+ t|QWhYZ曡3\l+4އ}oHC0ۿ~%$| Pյ ;¶SRfM66F2e yyy;2hv=#,kjj8w[::̘1Oz+ER#Jʎ墱7vٳg` ᣫ= }:_~ "=㯆7p" p> _+$'?Mn~nz@B0D'R|7˪Ű&!,gaﻰ}lc,eСDڮcd\Hʾe@3([[[)..KLe#jիWru% C=в9Xv-nÇk5؄$ VØ`hF < hn#'կ Iª."A`,Y$tǀojsG!oZ>m~9Ç2֑Q m3Pkݧ ݙB8[g.3NDxn1cF;ʴʺ^^_xsQ^^vtDѣ^tb_ г:ȿVۍܹsZͱ;66a2m2|Fș3;{Cm{`گ'p8 % !e$$29I!!=]! tbC&2XiJ}'1׈Əg3.Sჵ՟^Iރq1ߙB!O> ˬ==$SN%??%K4Vt_K }ɳ f )..zFռy'Ng7ۏWG5kp1ƨ0kH 3R;cD}o J"Riy{ Š5!^~5EEoZz$EiX2थzdРA!CtkE̐,f@k),,_#G̙32آw:A-?Z?}>{졠 6d/i0Ntˌib0+#/[O~ R܄7S7_#G̝w77z()"ĶBBBBڪcľc&@=hhh;):?;;NR+^'@k Sr@\\V|M ضmmmh!hrA@ag ,:ӡ?s_F:8`GEB{^t:W)8y&zy`&7p ݲzH)++`h$YYY8qjWIPWW)((`߾}ZVlM ̄1!P.祗.+O$?JOtYX2GGgff>1v؇N'L@=Xk$5kPPP>&&_bc@_ ='pV$Gbb"K,!77ӧkwDZjNKJJ"j3RDGbȑt:8_K+`~ 5ӟ>}͚5k(..6zmlll10Jſ烳gQ߱6n#666exb59Fg5<C)|^j )//㱐牎OMMC>z_-|΀ `u&vn:Mv=fƒn!^@Q=&cBȵocccm; <ؐ}GϮcBc%Zj@~Bџj@]je׮]n6m6669Np -:ك!.0)}2T*rQ.*'ƦIJJbɒ%1mڴn]o`3*ZQ{ؗE땕QQQT":?11g x$ Ŀ^pV*@fyfn7;w8666}I;Svd"uvdOdcc7$}'...}G7bQ~}Gc_&(..fdd<Z-m@z_KSt֭vV&>Ő!CcժU <#;ꉳB})**ŋ}]EG$55;q/IRPgQoM|:QPP믿|`}INNL:Kr2-3\>z )++߲Ht:J/I}Fl6'':2\H̙3gѢE\.IBKNr2𴷷SZZJqq1555$r7: ?,߿멭551yVVVm Ze^eHF;>b9fWlwkECf 5闞WGi?JΎ;plݺ淚M̲eeʔ)Al=j{VG@-UbY~[[%%%PWWoYѯ!">P uQlܸ͞={znlllllll$quuwNm'}'X4_%/^TE@z@'R?>Kkv9|& >|VXԾcf\u^iQ}?_)[ZZ(..+{J`?P~#?:'@QQn͹sL66666666=EJJ ˖-#//ɓ'wyɳZ_kΠ\;Zb󔔔\6#E~%JAm5)@Z_l௖K pю @.\XpC^^ .}Go=}G/_wLeѲ\tikk-_q.;TPi?d13ؠ_x`?}>{va}+mlllllll\4զv0^ϧ'뭭PZZJ}}}oeLJPIzV #:L ʶmpl۶\~6=Ijj*˗/'77I&ujN0o~ +tWTTtwAV転_,t:i?ձan7mlllzx2K2! !zbԹ! A/9Dٱ/J|^!׽Ns'5 FvhkXom]g&//wwB@\Hf;PVVf=sy~%J?R;;Ʀq(xp.gg]`;/οޮ=&ڙom"LJ ,_ b%EB AlPZ[$E0tH{ ¥ZeC9&#GȾԟ(--rW3_= zCyԊ+Sri (((8oeLz?):H/%0|eE$lacl $'wix{?WAzzg]?( exc\2~N|䭀@m\ʋPT":6#--˗DŽ :2ݦot@D_ˢ'}>PYYi;"+Ŀ?u-_˗/r[@+O_+̾SVVFII %pyr~%Ki6SmK,'@KK 7ovsNNKKKomWW#IR73p?V AzuԔQPP)a+!#~x% .N^VI`0$4|^ Yx{`7\Ç98ܛbpd׊.'\">C0RWoL,[9?eOw3 a@7 vhs>8r6~ˉ1ctw5ErCDC }v(--߲+[ptH/O8?,@F8q͚5k(/75Ra$D54<#LS'?Ʋ'>Ρ0iIxaONtCUs8xs^Xom$K ++7 &a' 1"\7J>$iI(kjLQCatklsϕ¾M"ރhi`A~Xr%yyy\}9w:fT_iѳTUUQRRBEEm߉ loJp:@$+evY~=&HLae%a@$b֗oea!?]ib,%tGn j=KŠovs괈 Œ!2SX M v"Lz)]Pmk?^krn`Wi9^# vZo`t2ofϰ !bGýokAQqpybkY]LSMq)leN90l"Eݓʄwdo^,g#ĹDG&xςkLĨӑVT[S/, r,$4@TvZL90v؎ɳt(ו|:=߾=60fE8w=H@W>5Xi 7vٳg.J80nLlK"Zg45{V1_~݊^/&5XoF|\Aӏoru p)I|-ƅi9>~:] ~rBx}8yƏ!lt]`:샫. OeFfì)[רwa x >c!hlJh7==þ3v.3Υoľw,}[G tNidpOTw bڵn!e$0j|>!k aWF<=љx(#_ MNJ4w.ĐI6}X 5"/ Zj?uM㳫:$1F ?kaə cE}1~)r@JR7|}>xM8|xN /ŽwE #C$ PTE:Y`̙3It~(RZZjEOtO=*_/g?j@QQnΞ= Gj2̞ 2B[O:&CBUD5 ۃ|/TV>~Kxͮ1ܙ.u mjɠ9!+|ZYps]WQ ML|h˂k#C8w~3y<8[.,`V3 f+пƍ#??e˖u@+}/ܻDw***()) ȓ IDATڶ]L~Ӷ\>8---]ĵzM֦G+Oj1b{/{/Gt…^\=YUi 1Wq%8Uh^' +KsuE߅P1ȹ!Ū,o&`u=׻MBQ! >7߄vغ˸O!]kPjk%>&C^ ⫦)c"цpUWg&k!)xpXƨ g,&{dI[lO 엞W˘1c:655Y!W˺uIOkw)--ܶ\آ$kyZ`?D.I {'ERG_k z-zC Ł,QLx}"kRAy!-) E17s"$9V%5ONOOy5 0Xo@==SGC]k~um%<̙}-N`[m|z%TF{ֳ+G@8?f}ʎm۶vٶmmV!/cF\D:z o]炕DG4}2Bķ V*cODq#uq_s1Ha>(50yÙ >fE\&M-Rr k)E,^|*68k 9 ܃O,<9AƖ(%l?þ4뎖?XD_]k {u4?p}ʶp8HKK&/=?R?Zk McÆ nۇ/ʗ qbP4w&DXm#lg|̉bUFfhhe}x q+$%LaOAiW g 27Kc$%!e(# "-RJu],보$5AtEwN|bQ^ o[t)3>'CE _Z?UVr.`5M̾)ɲLMMM}=cl&NHrr2$ŋ9~x_J_nXBtO#NGLO @ǎ;d7Jq:,|FʀEV3J"{J_44fhloh1 L7{%_n#' 5m 4~pтKpn"w]mjʲ<] 83R;: r { *.YkoF ,qX`yyy̚5 כ} (..' p/0IVN3B#,RR*nP$)}cs?YELsX̕} w1r`za41롦} $rKK |ƛ`Qa@(*o'DzeHIIWʺ_d');zQ}-Nee%\p 55˗w^FOQEo_tE+?kEn֭[Guu/!LIcam7s,*1vڔ1b#5/ SU'~3aTV$\10:հ}qL&psjLNM%vJ=B4toܦ@MDп&ZQFiNKiԾ^eZJJJ(//YdԩL8{nzZآ?R\.OΔ)ShnnrN>^5X(P0\c%ڤk. شiSLM CAv5þR&:؀ܨD̀x 뛄V!AJ$ SBH O(0jd _qDp;KXb F(.gUB m(>~C qqq,\>믿  }Fitttq)88k+W<OM϶LOsOj?ӋZ[ f  z(a:D섧@C>9(T'r!ϐ!*!4v] $ffq0A~7z}LAHLLT*Eff&b g#>|GՒzނ3}6QbhhZ,ի2bHRDtBq ܸqQモ"9Q__RSSeV?WLMMaϞ=P*mԑNx$I:umtFH `&EVVh4h4AGG4K #55uׯ?BF?lOz0fiAףUUU8z p6\@߯N*8ֆ%v6 b 3 >w5dݨdb#`ȔIqm`uWR(' =~_\QsݧiĂ PTT|Yyk&>lDoNjjh캼QQQHJJ$D@mm-kXa ~WW1*$ PQQD8|0ӭ0I= 87Nd ))))(..Cd_bdd---H$Bjj*!HxsUZ7 BJJ 188~ܾ}vٲZ=\ 鏝ai ARUUUqN8WLg9.8<w>Y~-1C.0pw-pANsDHI@3"oXaaa(**B^^!&[ޚ|J6:j->I|Gp߱H$ŋ777<00ׯ[%"۷o'o ZӧQWWȣ/^M6aѢEd>=`(}wQ[[k1Aظq#m???;8uT[ouS4|<[U#pCTTX2Ihkky#++a (b1AHOOGeeQok3o&#OO>b%ڵym;1H? $0?"Or2Q455=A 99tk4q+ %%%X|]wuu?V@?وG?Ie W\AUU:$;<6>Ea *bP{5#` fHRdddńӛg??%ߡo ͳGNN̙cjףQƼd! H$Bkk+cppbbQ2gΜ~;lق'xHId%w C_^^D ZZZX5x'pBɾRDkk+c 4n:^ݨn^̖le'pNùsP]]G Kp]`(d H"//ث-Ϥg+Υ>dxbb(ߙo( J"###8w#ߒH$Xn֬Yc<qAuu5?$$;wDJJ ϯVo^{eV2T 0_H?7mÙ$jttt1Cii)}Jtww[$:…&Ȉ>?l?L?'j 8vd2Ν;'d/PPP&rϠ7f}k|N$Rߏ>aܹ(,,EpiYZϝ;RiE"&''o>:u>3!!vBhh(s__8y$}W- ϋz5k>P ? ICSSk6677yyyƥHGu{{{ƨZh^Es뭒ˠ cɒ%9suuuN>(3ic'ks:Lkt IDAT9  @ RSSQXXkZ|.۴yS<`"𰐈1A?>z=199&HǦM0g^\ӡ_}ҥ(//Gpp0o?uۋw}7nܰxꩧe_kӧO7߼}l6͖?΅?o/^z饏ZSZƅ pqPXXhh"wAKK ce%j*W&&&pEƠ0.EjjQ64_|`Uo^g D"nLO?55tuu 2OmFaa!rsskA2e;\w;g|1w\,_a$ىVhV[Wƚ5k"JGaLD"dffDo|2}||eYҵ###'^|\8'g ^<kڧi:uul߾$+a/t㻺bÆ ظqSVr9H5k ??6ǚg}ZaLP:|D(:jɤoe]\\,$?βWB& x$0g磠QQQ)Fwׇ~ƤV<==ׯxDb9# L兊 dee1 2mA#jjjǮ]oǢŇ^g4N$'~&lj aVx PYYi<^2RىNƥÄzdttz8K[VV`c/[$ B cG1ʀj?g[+-τ$$$?1Μ9*?~\(& @+QXX5kր  3SZM9zN>u?44d0X"""˜b"bׯG\\,T*8pXv-k0d?D}}=d2 |<36\_|CCCuOwypYQla%\V o`ԥq\.Gkk+c O`Ib`9(GII VX?Uj)Bas (I[ 5 _z6l 099#G@&6 @FLL qF@5ctȿ>M0z&o.3wVaaaV 9=|TVV& t:sב+V8$| ;v Z^5ksNOI V[;l0'Gs@ A/(C"Hj=D\PQb]:W0A_Eun߾Hb16n܈כ.C0 <<!!!S.$IB@`rrD+o~g??OkEXڲDEE***022jd2f(((@AA""" Y}.}3ttׇ}Yx{{[M1˗cٲeG}} !þ}Ѐ,\G"`˖-G}~\|ݟ?-- o6]03wN$E[#,Jt Irm*Le{zz#4͂Xۛ͛7YPTT///1|ijj)퉎FqqE7oNlT*qoM5%=\?͋~gų>Nd2TUUA.;  @֭[B$''$It:D->|Gbhhr###eUz6c?>&''T*P(LLZR,$&&ԩS.7֬Y"-Xp!~F}pI<̴͇a I4z˖!E" ȓ~[D Wj$7n`%ȉַNyݻw<<< 5Gբ۪ܹsQ\\e˖1εpBٳ}i1==msif'%qyߚŋ>݋˗/ "5QTTlcJ(ߡ}~j?-H}ݻw!100@5aŊ7!A7nܰZtm^. ͛721/!IuuuvR)6n777 į\o=?ƹ ~СCؽ{7.]jISO=ku*!=>oK" Ȓ~.JX/>aaaؼy3lVkж߼y ())16 sjtvvZuJ$ ==9Zt)r9nݺj)"͔S G? WիꫯӐd8y`G'@ 2wBCC)Den9៚2mew$''ۛ|;w?[lABBqٲ"HHHsO~Ll߾`AYr=j#Ks D" pJKKM.xk4ܺu AectKگ>"AHNNFAA<<<8wh \LOs6O굶?VbƍظqX&… ""@X,HR$&&;sBDw,=@0hZ @.cttg?l%H8\pbE_T>Cnn.bccӷ׭[9r555&~+WgAhh(>g[٤!(//GHHq5}bO>$駟Z4ܺv_R7o.Dxyyq&gZ M>Wsh$o X@=޽{hjj0{Z`*++ Vٟ@[[Œ??? >>Xg[CBBߏ90zc0\˼'sd+5'L@pp0o6 P]],NC*7o>"~,&O'֊r'''!ׇɇ}Yz }[=** QQQz*Ο?oӃXz5!>z ?Nغu+rss"-- ǎCA[nTTʰ8s@ ]_FA|rFL9466͛ѣ(--/o~XXك7nڤ0z-a˖-zm&7xB[[[c˖-,>6o޼.&8GZC1S+Bs.A'|ȋ~1؎wss B.]d$ 5 Aqq1:V#@u f(D"ddd ''nnn{ `Vh8Δy ͛yf 2 { @;<== TxO'2wJ`H֎T&>55˗/Dž k10>#_V2ݲ7HJJBBBN:Ç$'#''6m2iEqqqw7i48pַfDZD1+ ʙ/8xxxGa( .Vqm3?dee!//tre˖`̼ V6y0`'fi.?Cs=fTUU|߆7@RRRQS~]Kwߡss0wڱ0.yXGDƃ;ΝݻwMƚ‘#GpU 22G$2X| 339Xȑ#ꫯeš5kDĈZ|ߞ1fj@ <k$Ip =C"T*>44&&&+V@EE̙c }BV`hRVVKM\b11A.," LNNdm'ߖ'b /:TUUȑ#Bfaaa(,,D~~>Νk5oN䙲l.r}E?kpww7s!шƕ+WP[[kĻヒ84ܲ7 ??>:::󌏏Ç{n p)!-- 'NvMx;)Z=>H?r? a+ $I?j;\Y3!!!x'd#[<997o2}iiie^>z~!JmZC-FѣGquߑ=*0/e&pdZ `dj)4k8qpil 999J3f͉97'}IkǦ=^Wxyy!44N8iiiXjjjjpU Jcc#Z[[\;]|9~ٳxM[xױvZܹ 1118q${?ѝQ=ӁYkd+m&&fܺu%<</"pSv B*B"MMM܄ .d `0222#~ ٙlߖ'rD"Aaa! q]:tUUUtϷdD"@*bݺupqqVkb.1'L}]R>!0r9:9mpssÒ%Kh")(?$Xw /Xj8z(.^ Y®˼vZ|ؿIQWWK.pwwg=gtjժIkz =LXv >LYz{ qX#صkEV| [ 3** vxa||MMM|}}QXXh5Ojj* k`L[̙[b֭EUU9^G(,,D^^]RY>SN?!mE>K,kXW^ŢE0w\}xx8كׯۻww3gm6,^lpww۱l2&I:F}ɓx駑$͍Q/ ggʧ6}:[O'|s 8 +۶myk޽jR#dzz\]] 6q t:`F}\? k _ك={2 &5w-[f"yc&H>s"t4'4XP ?SQlff&PWW!1駟"33V╉Ǐ~ua֭z{kٳ) ڵk‹s!lpjLوǖSrgdĒap ˍ8emqb1rss !hӃN~(..4zh(`Xmɶ `OsP6O-O`GL&ѣGY MHdxZXXT&rBNG3LE~&?88>ZR2D‰/X6mB[[+UmZcǎڵkŋy7"/g$q\x6mBII \\\x}LFu:Nʇ;njsvT*\|D~~>?$I"((}JofO.&Oz&1cbcttL&իWrxC~~> mgS'sv}|gjjʨg?Θ7o͛ (Jܽ{f k׮[#d8q&655͛Dnn.<<V=|\ofzc7]K43jj;6rXBفA.]~[pj_ٺ_yyypuu3Zƕ+WX}E"YNNb13g8g\a7?-zΖ' \C۷cL&L&CwwϷ3777k֬1(F)d:.q"((ڊ6VR711,\ '00O=q!9V'NF}>>uK,ҥKqE>|$q566{gϞ֭[i&xxx`ǎHII~+^ÇٳسgRSSmf齼Xat*ƯfzKP((9 C N(L?נA,@;w bQ4773y桼111)000ƹ<2#FUP`s-j-6OkVl>4!! Ξ= LǏ >%ߙ\.G__ڦJ% rrr088Z!;;v|_)))8rjjjLn/~ w}&b۶mx뭷իWzjd^̕ϔ󎣫so( /Q&\3joGw4υ48 ^^^]Dڊ>sT ΝJUx0 04CFFz~$ߡ-g*uSإ'dee!++ 8z(d2jkk` AAA/_n$tD>g$u8DMsGZb W`ڛ";388VF fHRgtt-Z7"22ׇǏ ^oL"03lg_l}lDyy9122B&+@9\\\Tjb955(ߡ}~U]>[fz<:: \A$GP*{8Xbjkkqe߉nFRRY%?HP˸~:>CQT裏pqرvv///$%%ڥpI?_̗~g bBu׏2 T"p^eiqWT*edY.v ֭[]{)wZ[[Y>-^ 1"|Q*hhh`=~~~(**Š+L󃧧'b1o3h:&T0?2\?mXbΝعs':;;{{{v[F 1O3I_{AX,FTT\]]1>>1( ]]]Xl2Dbt;v:::c$zܸqyyyX~ݶd^G~j"o8ڵ IDmm%$IۖőV\~Y?ଥxIR%^~onv{.\{.~7h4F{{;c0wj˗/3aÆ 49"-- Ν\ lğ`'`݋{ːd8tk!T*E~~>BCCʓsBD}[dWUD.DqADttHeRk׮app~hZB^[!!!رcq!4PWWM6!>>܇ꗔ ++ }=jw؈Bnn.mX襤?kOL3c9Z# x~%@3 ޝ@R)&jυњwvv~www޽nnnnֆannn&r` PXXֱ"""fS7Dpss;cVɚ|_. kHLLDbb"~̙3d8qc&񆧧'6n܈\H)oMæӧȻg%ִj&!!!Xb#q;w.6n܈>\t/^ǩSPTTd8WX|W8z?`Ŋزe ,X`sl\lܸQQQH$BNNpA?$Yw kæMmr=HKKCSS:d>;$kqfijiBP?{a@B{YGSP*2kJ}X)33gy$HD8aiRDss3kp<N|M>>>(,,իx"pA3gݻrә6c+f1?tuֈ?u fdQUUeR7K.T*Enn.goKj &b϶yt:K;w۶mCNN݄BVV# nZX͹!S(?o$iBQF~hou=3s%f$ ~ND2gbJƕ$j֭[(--ERRZ !ׯGNN\]]y{WmDrr21==~tttiԚSibbH%ci+J2q7ovލݻwGUUUGAAA(((@~~>"""LH>u4"߱ j)V3044$wx$I+9(((իqIF~x뭷vZ\+/^?Q__?7a||o>]v!..PA?ovj-ΧY=+ >3_ u9Np%JR ce0JrTp9zl$?*Ze6aJHH!Xg>PVV9sX7>>˗/[=+W4Pt/T*ꬎa/fbb(QN@ζ&o;0Px饗P[[ѣ6l`$sYdS(Mo'H=gsQ*YBט7o055RwJ;)T* aѢEvPܹMMM8q\:ϟիWQXX4㵑OTTWWc߾}&۷k!55;vy83$x뭷8KÅiwd[ vүETZjBf U 6!޽{sK&&&ꌴ`bѢEVx ֭[6/{*bi~23?E"ӑI9r(T*!s"FHw,Ⱦ^o8qqq rׯ_jMz-DGGZ 8{,Ξ=krݞg} O>$.]KVu7mڄl{8s稭ECCPYY Dymϙ3g1݃pqf]#`h<_kүT*k (8Ӟ-Vb911aa׮] D'''b؄'R)Ҡ"* ]]]}6RR)D3BY+r$SL5L?jkDEE***000LL=GTTR)`r-1war1Ӄ33{[d_axxrB ɂ2ŋ#""---hlldDkk+V\[OR)qA\rd\HJJSO= ! {ELL 򗿘VF?'Oݻ ^X̸<6ie=X)*Q(zde?5Ry;wx2Rɫ6G ` .U4cʕH$vujtvv2vD@~~>$m'b``mmmHu֙pɦt&ә6kiY!!!xsϡ1::;w.QPP(|m-O/ޗP)omͧA.>jBHHMzjƢ"'I'OD?[]v֭[cZЀk׮ T:\~Q|Je53,o;ӧ}ݿ |&'T*5ǡ$,,Y^3#2|lv~y$ x @! ?$!+GׇfF 5_Ouf#(--q.{g=LyG$b4lIWgm8˿ N>ɓ{H$ʂT*իA4 +ѧ|sro٧tNgz$ILMMr ^3"""B[ꀛ3gX8`\˖-ësa&zFx駱~z ?,F`+ZaWcO.=pp'κ*`82C2727w 56x홚Z ?; $IjIϐ$ޞUB&Ɔay}4x͛2,Y٧nlt`V5 ׳Fz0Ri$M[_柫'*Sqtqq1/q%ϯAQTTL0u -Ow>=88\;wX `^طEO gΜĄq4tBAxMރuүpb&wԦKj~޻wgjz-2>550~4lڴ}KXzxx ??iiiFwe-ac!Fb޼yؿSI&*975'2ؼy36oތnd28pB ;"""PXX<Zm5~sϔtkmEJ݃\.sK,1>>a秫 qsΡ΄߽{}PQQ0d>mwwwܹRpM+okbwvwwT3%BރBP7òTQ@g0ރAc K=JHP*cޫ?%fOR|!-`"pu۱.rJJ}vޙ}V10v ?zO<Y 8cccy&< 0!22hdd$"jN?.1'|s E٤@\n[$8qߏ3g&B,cݺu(,,Ě5k|;v ?{ 1 `@RlP`9 >MJ7`Nqձ[FP +WŅfzz}6* eeewSsP֢)))}Р)]&g j5__ X,6ʕŐJJEuu58zժU(,,Ć Ngӧ67̵LY|k r9j!E 4);w. Q[[kѧ޽{OdY8,_ϟMSSSOPSS~III^\|;ػw/󃃃Œ%Klwka[;!{P(Ka݊SHT*8߇=H#YJkĔk#֑$ 0< 0HxcX,Fnn.6l`srAgg'U$2X;M$!::G?7H$[c[T` رcv؁v8p2 G(**B~~>-tlZ|kğF;FM:QHHbN|ňč7pZƩSp5#&&_$!'' IDATd8y oD>;{OB6A eGf B$ҊzZU~[꽽ں\b٪,*DY,$!,I8@e2Ɍ3g&+ 2g{f||?OЉ?Gǟ8q{/"GGGL\}zU(O?R"%%~ܹkײyf=zܹs])Y6k׮,z_O;9s \pAwBZIq,--QFc<_pUV1x`. P'qqq,ZٳgosG}8x s{[n!^{Gf+h nC$QUumj4밫b`PHz#bҥW\@7-K.ڵ+ Z._ls)Cqqqu]L0͛7s 󖔔__qdeeѭ[7Sv( ~+puذa۶md̙>B8)pۺR&\ϡ /d 4b'0_gsBFORQ3餱nĻuր pm%9vn@||(lܸUZvo޽{aԩErr3zh>V\Q[[+>|-tSRR>Bo߶G ׌=8b_HZ)۞ٹ~ 4ߣ bҌM$O#۝wɘ1c=q aE}lhђoL0z]Rg#`[`@?];-A-j7c=c=Ƒ#GXv-6l]-HJJ";;9sp-~G;b[ >}w1@N!Z%]LJfС$''̩$''sk.^ȧ~zO13f Fb۶m|'>+Wj*>3xo]t!77C=ĉ"8}Njj*999P&0`?wF?>Çӟ۷f1ZX,233bȑ~r;^ ͦ4 r͝>}ϷnG"**xǤI>|8vӧse6nڵk}V FϞ=Nll,v*9z(y܅f̝;t\}oQֳoojjRܫޢ{v4Ms-kRtKn Drrr8y$;v)bTUUj* ƬYիi~bb"wdժUy\/0|M= =lpcKG 7R媪?6;`_CՑcsh h?HTٌpwNnlldT$;}eee~'#̚5iӦ(t@Ѣ>ุ8Wn7=4?1c0ydx"O={"PsL `FEF*G,X p)Wɓ]~/^?9/7o6lɓqy&NH=\vݰ}Gz_}0vI] Eٹs]ә1cqqq5SSSyg/xw<,Zlݺ r?99}7*!DիZ\Iҕ0p91瓴Rw`4MhX6dk,Dq7S ץK #BBFd-Zb񨢛555d+„ ;w.~/ h)߿?999.wCCߟ$ػwoПS[8[l6@8zwߟ'x'x{f6npmRy ?Νw Ջݻ{wc6U~xw@}BfQ]]y1dV+W\} DEE>ydƌC~~>Vl6>S˼y?~.3f =={zTU3~!K,aȐ!_7N߾}WVV#f}FZ=ںRŹσ͜2#E-4mgk zp|F,B'OYݝ޽{djvچܗw2h WSpe u*޽;se̘1lqQUUũS-󙠷XLLlgO7nƍW[ne͚5i+,,'w呓Cbb_1xXHn7 '5M3gDd  AHMMuUm5OEFN>M 84i~˗/b >s,X@rrr>g>::|L^{5{[ii)/:uˋBO,^hч^z%&ùͤ飯zjFTUm?iHG@׶m͏kqC ,BH||<>(]t1mihhr1׳gOrss5jTbPQQkڥK222>}:QQQk:JJJ~wvͤk5˜9s3g.\'k֬ȑ#~_7`„ dgg3zho[`QzyW\;IHH`ԨQ999RPP#GNKK^L'z|СClذjU^^΋/ɓ{Zng,_kzlBϮ]Xd 3g4R)׵ ֌ v||+I/Rwp4Mk~`X $uͫ5"96Cll>|8={4%ƝոbŘfΜ!څ9uǎӝ9ln"ҍ+WHHH0[kxCի?0?0[uC$`׮]ڵDN]6 `bsiC_Oz뭺|Ə7 ñcᣏ> !ٻw/̛7#7E磏>{'/Sem1f+N#Ox㍻ bS賩%+F& a}v:QU j]#:p8oAa|LZ꺑s !_)Tᨨ⌊WRTTӧ}~?> zQTT!֭YYYaMI r-L8[osQYYIyy9'NzQ.lN@z¿?9|駼+!Lg޽{ׯ'OJ6wcޓΟ?OUUnBBBB׮]㦛n I0PPP@~~ٳ,[#Gk1rn9s|r?1/2by k.5ko̟??]j7T>ԉG$;;Dv1X, F>% ;n>tҺ'`;FiiȠA~f6#rATT̚5˵rYPeegCѣ])2 ׏1cưf͚ 'z 9gC; 7 Ђ_f?7gٳe˖m66,;UQQ{ァtޝѣG3rHQNSS ?sQ]]&FBBC%))(^Jmm-%%%AcHIII17n#G>cCQTTČ31cFŻ]kOKK#--͵/UBPmm-};wd <صbد\|MPUUU#^}Ӈqynٓ^z1p@9tߪި(qqqdggw-_l޼={pwfL߹;Ⱙu֑G=Lã>JII k׮ܹskoy8p`-… ;v,/Oʕ+lٲg'XBEJќ~3@slE_TU7z2IFtg,˫]C_5Mke;=7VNEYp?>66oٔwTVV'++)Smjhhĉ?~ѧO8p`P}׶%q.( $$$CI1RRIII,]{^ze˖[[[KmmmK=zp7'OfܹV]]˙2e iiiNFپ};|DŽdddp}aZ lz3|pxnXӇsH)0*͠WVIx&l~hĒN4M+8;UNM ѣGo޽a60ңGhM#Bp1)&W5?wG[ڵOCp "--$Ξ='4` >=otJwـ?/ٓo~EIII6ԩSs lݺ2g bڃٳIOOgڵl۶%8l۶ݻwo}+ddԩX{411񦆆fIJ5 g5[0>qPs#mZ/p+_voNH)%90#>t#`=X&!5EQn~~Q1~ tB)))>+/_DEEqwIllIEzżyHMMu׵kWѣywuBn],!!.]'k&;/"I<9{MRRRHIIa߾}ر_SSÊ+2do6wNl,Yœ9sx7)((p]ڵk[lٲŋ3~bb"Çw)ԫ)U0ڢ?TPP?n I:4RKe | @P1|jp.j3al())ԩS~'V撘ֵ)-+̙32e Fed͚5{&s7ӌoO= @aaaD_FTT [nիhƅ t\tZM )S0vXmW_}!=ʟ'ә;w.]v 799_޽e˖yLϞ=˿ۿ1zhyguB>|5-!Wۍ&o"T4]͞ ]"14bG@FOLr`T0YYY?>,ɓ')--{911<vCpmm-yEaܸqdeeѵkנ狉aСrU``njxUر#^N޽9r$(zVUUq.]{|AA3g4݀w͔)SذaG4n'??{ԩS]Fĉ7n?x<x駙3gwݺu|]voK noѭQ1;^UճVc6O=K$_ ųbxPӴ&"fol6[@6vXf̘of||! 33c<>|uyX4Mcʕl߾zaÆN bbbX` Ƕ&>o… 9s&+t[Z `h;!6_lHL E$l4MkX#9^RYv|csge!7кW =(ĉh6sFGYn ;;۵Ww+]aSIDATLnkg1:0o2[QQ-[صkw3 1bC a߾}sIMرc9oرcٸqD?L0 zC%--SRRⳭu1mڴ8>!=d%p -gUU]e7RK"i&f`]3p)6v}O Ǒ I,V)--~?{HJJrU胝[o[mm->.]0yب(E};0tPF+Wٳ={6䟹7,[_vr`Y32p@[|\\ӦMcl߾SNyڵklܸ}Mrr)\Mի=ݻٷo̟?8S?##ïjwᄅpDTz[4zhX TUmZˀlUU} )%큵Sd{bDl8jB~(q'=l555ʧNjVƌfSN|=yѽ{wÓ WVVrɀ?d͛M7:nȑl6>#8]$`K.bgz?HY`eeelݺgso0brrrի!㏓Ųe<Yz5[n塇"###wkz9 8w>Xtmfٌht\TU$SH/il}Ӯb# !xҥl`稩ȑ#+ydeefžfm۷/s K766rE>lZfI&QSSCEEw(8s*# h6-Ih3qDSCʞ={ؾ}Ç)**bƌ̙3TÆ '??~#… fƍ,Yzv]#M]!W/fw$p[bo%J$@~IiZb3{]^4[sLW7@(79Tۧ;ɓ'3o޼+:\X ȟl5[SAQUUE~L[qMFZZ[la޽w6-[{no2iҤ|85i$^~e<%%% ##z^nߐ+kʰ5ȏ@?8OOI+"E]i,K>懫Mm60xWCm z_vMClY\\㑏"##Yfc3g())kM7nsΥ[nEތbu߈(FRb?\WSlUxEQZp=q%^um… III{n#8~Ν;=9Wݵk?O1bDe#HGza@UUaZW?٥$V@~IAӴ,K08ޜ !pX=ި85{FVx%EdeedJ;}>aÆqwӻwo׾fŋ)**ҵ&ߟ̙33fǝ3+i&6nBݻ?>999Ą<#Fлwo=׮Ɔpr0O}##HLUUjYOUՂ/ D)%u ¬h@qX,W/Cp nLNNӧOnrqNj"p5_|csն~D4֮]W_}ży8p)OTco}[̜9+WTXb}-bĉ!UQnv6o|[Bz?T n&#?9K1QU)tI"E3!pN[i,Tt37BJ򓟼hD(_zBN>wlgf-<ϝ;Gqq"^NFży\l@aa ;#Nҽ +;\^}EO><sqk?_|#Fdnրcs111u4 }`pc5|h5蝂 ]@;H)%M,˟_Xěj4i62i8<_}yƌCfffXEx߾}#999lJJJ:TeCCUwOG޽{9|0gvn"Æ ^?7>|gyYfqӽ{waÆ7~&9fL:y />r IA~I@ӴZ,pܒ-϶،-\$z4\xQl6¹sz'Ov}N0wCCǏ׍\rCT:ڪ!z 6_`&N1WQ233IIIYani&ye~KYk"dH/6U:RUPN(gt4MeX&#cim8w84`"gϞoX"a`qqq$$$Vcc#'Ng#p}N:ٳgVԧX PgGi~ƒ^z[xb?***s 8 >۝ܑZM7AUUjX4kv;N,St*4MA݃bsCi t|~E(cp<􉉉 ^UUő#G;aÆq=лwoS;>5wT뉍nEgdffУGS6m֭G 6"6ц;@GVsNj&0GQM}HZ)%AiH, L :iB+X}}|#EՋ{wTl68R]FIInqGf*v]v-[c^vIII9sy[p,]V=Z;?fb OU8>$Ne9v#b7&`3<)ӧOsѫWB766>;]ASSBgMl:*W^eٲelٲŋ3nܸucn>}9s !kvͫF1m&ƑQU.\7H/8|d٦4Mk/5T} 0ZxyTT-gϞa{y u>;Ro*++رcYx1r>5?яoS}#)[Zy.zjntwr4.\WH/eX#ir|F6 &0`}ggUUUϿ"p}I~ٷodѢEdggz?H 졎y/<˗HF~ MޱX,7S=-q]Z#fѵk@$#))ɔbݸΎnDQQEw$w{[,Z 5NHU/L\"H/xiUj&Xe2Fοf#66D(=oH(qqq!zN8ѣGEׯ#!@T@UU߱Z'pڡ6Ik ED6KsBӴvQjēP:77ExH󆆆F~UU\t_$ +^{[Jܑ6)M޹ȾId8 v}{3s!Izjb}}}^466~*+e(r X lnN'*`;9™4XjnWʃlH$! ED4M[,eVRyC9>J(cpN ~I{DH{X|'֚pE$9oҿ=gKH$А_"b6?lǑ'@Ӵvjw>Tx( h\}IY˛X$\O~{X 7P# UU˭V ]g :D"1I4mb#FPiZ]J]Ci 6@ijj}'WIkRʁF5z;9pwXx1WI ^Q\I "EDauׇxi> e0}`v!+C?$Dz`F!pqõ;G(=#gV8X嘪H$.HZ,u}Av=Rc715-p`(O㸻0ćd$؁çb' RL"ő_"i?I`gM`BEϚ]݂z`(7 pL ((}#ybp"7Np\nteVDҎ_"i?l⼶}G9fͦ!.(@`! SOLrpxxS.joWU:A",RK$Ml/,˫8OueGJ1 w)2mjFOw>BDƬ5`]!ES 吢_"ighVFpo) 0]1]I !ąּpN{#c|8&7zm%I䑢_"<\#58b@F15k6pGO@Ҟ),mAD2LO`z쎪j};_}DqH:kAi׷ۃEvF4S%)-CQ]\+ܞf1zc7jd_DҶH/t$11h5iC0 EQ&ZHl^Ѯp' H$A~)g[@ӴVQkm __(#owj}_%nFz !PM6$I{& H"ilNl4mc[(׻[#hBB>oaI$`b۳hw;+;b6oSeG"tJD҉hbyj֮ h/bBxxYQp?.ç=C!F\>mUUbZ/m*<1H$)%Ni5@M ~EU{#8<<([r\[Z!ĵ6im 7UUWXu|PjU. HRK$'A)kt$+CهçRq "e3X"trH$NX7[Zi,\W76XǣxGL wE]UU+V+^;DW"8y`chtd5B !&CpDoagL`gQF\ܨ%Ig@~Di0½B mH dA`ζc@$uąig4M[LM~mpZ!|&.{u88, !! !Z UpӀ۷XL@:T" /H|4m!4MX,AvW_EI6V V_H%TjfZWvUUF"+$,otB!&UD!7 GU]7;bjRK$#H/H"J@o1&>MNx:BBinnoqD.nB,BlBD.\ ǺI$"ED"͂M}x4/cL,q$B,Bhm=q40⠪1Dr =$hVcX!XŚ4!EGMZ 㸳B/IFq,@n+E"\'(H$IKaXdY[c<EQZuZ-`yhX;?#TUUfK$#ED"i7X,_hd Di[c<EQ ^G/!p4_'_XhMpXJUUE_",˭8kMӴΈ:y8&sYC/B$D҆H/He+0]gA y`IE xvUpnI$_"+,8b+DMdI(2 _\l>B\o+K$u]bXҀG @{5Mж4sX>j[K"H$-D"H$I'G.%H$D"trH$D"H:9RK$D"H$)%D"H$ND"H$I'G~D"H$#ED"H$Dɑ_"H$D"H/H$D"trH$D"H:9RK$D"H$Y:T⹊IENDB`micropython-1.12/logo/vector-logo-R2000.dxf000066400000000000000000010515571357706137100204440ustar00rootroot00000000000000 0 SECTION 2 HEADER 9 $ACADVER 1 AC1015 9 $ACADMAINTVER 70 6 9 $DWGCODEPAGE 3 ANSI_1252 9 $INSBASE 10 0.0 20 0.0 30 0.0 9 $EXTMIN 10 0.1721479520991333 20 0.1940338359368368 30 0.0 9 $EXTMAX 10 3.827852047900866 20 3.91966423026812 30 0.0 9 $LIMMIN 10 0.0 20 0.0 9 $LIMMAX 10 12.0 20 9.0 9 $ORTHOMODE 70 0 9 $REGENMODE 70 1 9 $FILLMODE 70 1 9 $QTEXTMODE 70 0 9 $MIRRTEXT 70 0 9 $LTSCALE 40 1.0 9 $ATTMODE 70 1 9 $TEXTSIZE 40 0.2 9 $TRACEWID 40 0.05 9 $TEXTSTYLE 7 Standard 9 $CLAYER 8 0 9 $CELTYPE 6 ByLayer 9 $CECOLOR 62 256 9 $CELTSCALE 40 1.0 9 $DISPSILH 70 0 9 $DIMSCALE 40 1.0 9 $DIMASZ 40 0.18 9 $DIMEXO 40 0.0625 9 $DIMDLI 40 0.38 9 $DIMRND 40 0.0 9 $DIMDLE 40 0.0 9 $DIMEXE 40 0.18 9 $DIMTP 40 0.0 9 $DIMTM 40 0.0 9 $DIMTXT 40 0.18 9 $DIMCEN 40 0.09 9 $DIMTSZ 40 0.0 9 $DIMTOL 70 0 9 $DIMLIM 70 0 9 $DIMTIH 70 1 9 $DIMTOH 70 1 9 $DIMSE1 70 0 9 $DIMSE2 70 0 9 $DIMTAD 70 0 9 $DIMZIN 70 0 9 $DIMBLK 1 9 $DIMASO 70 1 9 $DIMSHO 70 1 9 $DIMPOST 1 9 $DIMAPOST 1 9 $DIMALT 70 0 9 $DIMALTD 70 2 9 $DIMALTF 40 25.4 9 $DIMLFAC 40 1.0 9 $DIMTOFL 70 0 9 $DIMTVP 40 0.0 9 $DIMTIX 70 0 9 $DIMSOXD 70 0 9 $DIMSAH 70 0 9 $DIMBLK1 1 9 $DIMBLK2 1 9 $DIMSTYLE 2 Standard 9 $DIMCLRD 70 0 9 $DIMCLRE 70 0 9 $DIMCLRT 70 0 9 $DIMTFAC 40 1.0 9 $DIMGAP 40 0.09 9 $DIMJUST 70 0 9 $DIMSD1 70 0 9 $DIMSD2 70 0 9 $DIMTOLJ 70 1 9 $DIMTZIN 70 0 9 $DIMALTZ 70 0 9 $DIMALTTZ 70 0 9 $DIMUPT 70 0 9 $DIMDEC 70 4 9 $DIMTDEC 70 4 9 $DIMALTU 70 2 9 $DIMALTTD 70 2 9 $DIMTXSTY 7 Standard 9 $DIMAUNIT 70 0 9 $DIMADEC 70 0 9 $DIMALTRND 40 0.0 9 $DIMAZIN 70 0 9 $DIMDSEP 70 46 9 $DIMATFIT 70 3 9 $DIMFRAC 70 0 9 $DIMLDRBLK 1 9 $DIMLUNIT 70 2 9 $DIMLWD 70 -2 9 $DIMLWE 70 -2 9 $DIMTMOVE 70 0 9 $LUNITS 70 2 9 $LUPREC 70 4 9 $SKETCHINC 40 0.1 9 $FILLETRAD 40 0.0196850393700787 9 $AUNITS 70 0 9 $AUPREC 70 0 9 $MENU 1 . 9 $ELEVATION 40 0.0 9 $PELEVATION 40 0.0 9 $THICKNESS 40 0.0 9 $LIMCHECK 70 0 9 $CHAMFERA 40 0.0 9 $CHAMFERB 40 0.0 9 $CHAMFERC 40 0.0 9 $CHAMFERD 40 0.0 9 $SKPOLY 70 0 9 $TDCREATE 40 2452642.813384259 9 $TDUCREATE 40 2452643.063384271 9 $TDUPDATE 40 2456660.752361111 9 $TDUUPDATE 40 2456661.002361111 9 $TDINDWG 40 0.0 9 $TDUSRTIMER 40 2456661.001018519 9 $USRTIMER 70 1 9 $ANGBASE 50 0.0 9 $ANGDIR 70 0 9 $PDMODE 70 0 9 $PDSIZE 40 0.0 9 $PLINEWID 40 0.0 9 $SPLFRAME 70 0 9 $SPLINETYPE 70 6 9 $SPLINESEGS 70 8 9 $HANDSEED 5 1B45 9 $SURFTAB1 70 6 9 $SURFTAB2 70 6 9 $SURFTYPE 70 6 9 $SURFU 70 6 9 $SURFV 70 6 9 $UCSBASE 2 9 $UCSNAME 2 9 $UCSORG 10 0.0 20 0.0 30 0.0 9 $UCSXDIR 10 1.0 20 0.0 30 0.0 9 $UCSYDIR 10 0.0 20 1.0 30 0.0 9 $UCSORTHOREF 2 9 $UCSORTHOVIEW 70 0 9 $UCSORGTOP 10 0.0 20 0.0 30 0.0 9 $UCSORGBOTTOM 10 0.0 20 0.0 30 0.0 9 $UCSORGLEFT 10 0.0 20 0.0 30 0.0 9 $UCSORGRIGHT 10 0.0 20 0.0 30 0.0 9 $UCSORGFRONT 10 0.0 20 0.0 30 0.0 9 $UCSORGBACK 10 0.0 20 0.0 30 0.0 9 $PUCSBASE 2 9 $PUCSNAME 2 9 $PUCSORG 10 0.0 20 0.0 30 0.0 9 $PUCSXDIR 10 1.0 20 0.0 30 0.0 9 $PUCSYDIR 10 0.0 20 1.0 30 0.0 9 $PUCSORTHOREF 2 9 $PUCSORTHOVIEW 70 0 9 $PUCSORGTOP 10 0.0 20 0.0 30 0.0 9 $PUCSORGBOTTOM 10 0.0 20 0.0 30 0.0 9 $PUCSORGLEFT 10 0.0 20 0.0 30 0.0 9 $PUCSORGRIGHT 10 0.0 20 0.0 30 0.0 9 $PUCSORGFRONT 10 0.0 20 0.0 30 0.0 9 $PUCSORGBACK 10 0.0 20 0.0 30 0.0 9 $USERI1 70 0 9 $USERI2 70 0 9 $USERI3 70 0 9 $USERI4 70 0 9 $USERI5 70 0 9 $USERR1 40 0.0 9 $USERR2 40 0.0 9 $USERR3 40 0.0 9 $USERR4 40 0.0 9 $USERR5 40 0.0 9 $WORLDVIEW 70 1 9 $SHADEDGE 70 3 9 $SHADEDIF 70 70 9 $TILEMODE 70 1 9 $MAXACTVP 70 64 9 $PINSBASE 10 0.0 20 0.0 30 0.0 9 $PLIMCHECK 70 0 9 $PEXTMIN 10 0.0 20 0.0 30 0.0 9 $PEXTMAX 10 0.0 20 0.0 30 0.0 9 $PLIMMIN 10 0.0 20 0.0 9 $PLIMMAX 10 0.0 20 0.0 9 $UNITMODE 70 0 9 $VISRETAIN 70 1 9 $PLINEGEN 70 0 9 $PSLTSCALE 70 1 9 $TREEDEPTH 70 3020 9 $CMLSTYLE 2 Standard 9 $CMLJUST 70 0 9 $CMLSCALE 40 1.0 9 $PROXYGRAPHICS 70 1 9 $MEASUREMENT 70 0 9 $CELWEIGHT 370 -1 9 $ENDCAPS 280 0 9 $JOINSTYLE 280 0 9 $LWDISPLAY 290 0 9 $INSUNITS 70 1 9 $HYPERLINKBASE 1 9 $STYLESHEET 1 9 $XEDIT 290 1 9 $CEPSNTYPE 380 0 9 $PSTYLEMODE 290 1 9 $FINGERPRINTGUID 2 {FDEAD576-A652-11D2-9A35-0060089B3A3F} 9 $VERSIONGUID 2 {FBC2AE19-5C5C-49EC-81BC-71B1A3362A02} 9 $EXTNAMES 290 1 9 $PSVPSCALE 40 0.0 9 $OLESTARTUP 290 0 0 ENDSEC 0 SECTION 2 CLASSES 0 CLASS 1 ACDBDICTIONARYWDFLT 2 AcDbDictionaryWithDefault 3 ObjectDBX Classes 90 0 280 0 281 0 0 CLASS 1 ACDBPLACEHOLDER 2 AcDbPlaceHolder 3 ObjectDBX Classes 90 0 280 0 281 0 0 CLASS 1 LAYOUT 2 AcDbLayout 3 ObjectDBX Classes 90 0 280 0 281 0 0 CLASS 1 DICTIONARYVAR 2 AcDbDictionaryVar 3 ObjectDBX Classes 90 0 280 0 281 0 0 CLASS 1 TABLESTYLE 2 AcDbTableStyle 3 ObjectDBX Classes 90 4095 280 0 281 0 0 CLASS 1 MATERIAL 2 AcDbMaterial 3 ObjectDBX Classes 90 1153 280 0 281 0 0 CLASS 1 VISUALSTYLE 2 AcDbVisualStyle 3 ObjectDBX Classes 90 4095 280 0 281 0 0 CLASS 1 SCALE 2 AcDbScale 3 ObjectDBX Classes 90 1153 280 0 281 0 0 CLASS 1 CELLSTYLEMAP 2 AcDbCellStyleMap 3 ObjectDBX Classes 90 1152 280 0 281 0 0 CLASS 1 RASTERVARIABLES 2 AcDbRasterVariables 3 ISM 90 0 280 0 281 0 0 CLASS 1 SUN 2 AcDbSun 3 SCENEOE 90 1153 280 0 281 0 0 CLASS 1 IMAGEDEF 2 AcDbRasterImageDef 3 ISM 90 0 280 0 281 0 0 CLASS 1 IMAGE 2 AcDbRasterImage 3 ISM 90 127 280 0 281 1 0 CLASS 1 IMAGEDEF_REACTOR 2 AcDbRasterImageDefReactor 3 ISM 90 1 280 0 281 0 0 CLASS 1 SORTENTSTABLE 2 AcDbSortentsTable 3 ObjectDBX Classes 90 0 280 0 281 0 0 ENDSEC 0 SECTION 2 TABLES 0 TABLE 2 VPORT 5 8 330 0 100 AcDbSymbolTable 70 1 0 VPORT 5 94 330 8 100 AcDbSymbolTableRecord 100 AcDbViewportTableRecord 2 *Active 70 0 10 0.0 20 0.0 11 1.0 21 1.0 12 29.66959356597982 22 21.59555199096451 13 0.0 23 0.0 14 0.5 24 0.5 15 0.5 25 0.5 16 0.0 26 0.0 36 1.0 17 -27.66959356597982 27 -19.53870295786203 37 0.0 40 3.800143002217909 41 2.172519083969465 42 50.0 43 0.0 44 0.0 50 0.0 51 0.0 71 16 72 1000 73 1 74 3 75 0 76 0 77 0 78 1 281 5 65 1 110 0.0 120 0.0 130 0.0 111 1.0 121 0.0 131 0.0 112 0.0 122 1.0 132 0.0 79 0 146 0.0 0 ENDTAB 0 TABLE 2 LTYPE 5 5 330 0 100 AcDbSymbolTable 70 1 0 LTYPE 5 14 330 5 100 AcDbSymbolTableRecord 100 AcDbLinetypeTableRecord 2 ByBlock 70 0 3 72 65 73 0 40 0.0 0 LTYPE 5 15 330 5 100 AcDbSymbolTableRecord 100 AcDbLinetypeTableRecord 2 ByLayer 70 0 3 72 65 73 0 40 0.0 0 LTYPE 5 16 330 5 100 AcDbSymbolTableRecord 100 AcDbLinetypeTableRecord 2 Continuous 70 0 3 Solid line 72 65 73 0 40 0.0 0 ENDTAB 0 TABLE 2 LAYER 5 2 102 {ACAD_XDICTIONARY 360 133 102 } 330 0 100 AcDbSymbolTable 70 8 0 LAYER 5 10 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 0 70 0 62 7 6 Continuous 370 -3 390 F 0 LAYER 5 4B2 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 OUTLINE 70 0 62 3 6 Continuous 370 -3 390 F 1001 AcAecLayerStandard 1000 1000 0 LAYER 5 B85 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 HATCH-BLACK 70 0 62 -178 6 Continuous 370 -3 390 F 1001 AcAecLayerStandard 1000 1000 0 LAYER 5 B86 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 HATCH-RED 70 0 62 -1 6 Continuous 370 -3 390 F 1001 AcAecLayerStandard 1000 1000 0 LAYER 5 B87 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 HATCH-YELLOW 70 0 62 -2 6 Continuous 370 -3 390 F 1001 AcAecLayerStandard 1000 1000 0 LAYER 5 C34 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 HATCH-WHITE 70 0 62 -7 6 Continuous 370 -3 390 F 1001 AcAecLayerStandard 1000 1000 0 LAYER 5 C35 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 CENTERLINE 70 0 62 5 6 Continuous 370 -3 390 F 1001 AcAecLayerStandard 1000 1000 0 ENDTAB 0 TABLE 2 STYLE 5 3 330 0 100 AcDbSymbolTable 70 1 0 STYLE 5 11 330 3 100 AcDbSymbolTableRecord 100 AcDbTextStyleTableRecord 2 Standard 70 0 40 0.0 41 1.0 50 0.0 71 0 42 0.2 3 arial.ttf 4 1001 ACAD 1000 Arial 1071 0 0 ENDTAB 0 TABLE 2 VIEW 5 6 330 0 100 AcDbSymbolTable 70 0 0 ENDTAB 0 TABLE 2 UCS 5 7 330 0 100 AcDbSymbolTable 70 0 0 ENDTAB 0 TABLE 2 APPID 5 9 330 0 100 AcDbSymbolTable 70 2 0 APPID 5 12 330 9 100 AcDbSymbolTableRecord 100 AcDbRegAppTableRecord 2 ACAD 70 0 0 APPID 5 4B3 330 9 100 AcDbSymbolTableRecord 100 AcDbRegAppTableRecord 2 AcAecLayerStandard 70 0 0 ENDTAB 0 TABLE 2 DIMSTYLE 5 A 330 0 100 AcDbSymbolTable 70 1 100 AcDbDimStyleTable 0 DIMSTYLE 105 27 330 A 100 AcDbSymbolTableRecord 100 AcDbDimStyleTableRecord 2 Standard 70 0 178 0 340 11 0 ENDTAB 0 TABLE 2 BLOCK_RECORD 5 1 330 0 100 AcDbSymbolTable 70 1 0 BLOCK_RECORD 5 1F 102 {ACAD_XDICTIONARY 360 C3A 102 } 330 1 100 AcDbSymbolTableRecord 100 AcDbBlockTableRecord 2 *Model_Space 340 22 0 BLOCK_RECORD 5 58 330 1 100 AcDbSymbolTableRecord 100 AcDbBlockTableRecord 2 *Paper_Space 340 59 0 BLOCK_RECORD 5 5D 330 1 100 AcDbSymbolTableRecord 100 AcDbBlockTableRecord 2 *Paper_Space0 340 5E 0 ENDTAB 0 ENDSEC 0 SECTION 2 BLOCKS 0 BLOCK 5 20 330 1F 100 AcDbEntity 8 0 100 AcDbBlockBegin 2 *Model_Space 70 0 10 0.0 20 0.0 30 0.0 3 *Model_Space 1 *Model_Space 0 ENDBLK 5 21 330 1F 100 AcDbEntity 8 0 100 AcDbBlockEnd 0 BLOCK 5 5A 330 58 100 AcDbEntity 67 1 8 0 100 AcDbBlockBegin 2 *Paper_Space 70 0 10 0.0 20 0.0 30 0.0 3 *Paper_Space 1 *Paper_Space 0 ENDBLK 5 5B 330 58 100 AcDbEntity 67 1 8 0 100 AcDbBlockEnd 0 BLOCK 5 5F 330 5D 100 AcDbEntity 8 0 100 AcDbBlockBegin 2 *Paper_Space0 70 0 10 0.0 20 0.0 30 0.0 3 *Paper_Space0 1 *Paper_Space0 0 ENDBLK 5 60 330 5D 100 AcDbEntity 8 0 100 AcDbBlockEnd 0 ENDSEC 0 SECTION 2 ENTITIES 0 LWPOLYLINE 5 12A 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 12 70 1 43 0.0 10 2.051456726858387 20 3.24742480916928 10 2.123046084816941 20 3.189691455976897 42 0.4158687069147495 10 2.238512791201705 20 3.202392793679222 42 0.26959558438999 10 2.297400811457934 20 3.601907597770506 42 0.5584229650981822 10 2.131128754263874 20 3.630774274366697 42 0.0728974356199314 10 2.083688019187524 20 3.556961618598168 10 2.102120376925607 20 3.616965010523272 42 0.2082143708428352 10 2.078212672061864 20 3.708788569361961 42 0.3964961476078332 10 1.961304941181418 20 3.726524255462661 42 0.3247796006490571 10 1.824130493996318 20 3.336662468025144 42 0.2118780432517558 10 1.926924729355354 20 3.21641832666371 42 0.2797558288082047 10 2.010060757952385 20 3.224731929523413 0 LWPOLYLINE 5 137 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.002382887993199 20 2.593662641184479 42 0.1140103683665206 10 2.015684652568724 20 2.695642836263502 0 LWPOLYLINE 5 138 102 {ACAD_REACTORS 330 C20 330 C24 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.020828542221933 20 2.58678815101607 42 0.1140103683665206 10 2.035276511011441 20 2.697555911735634 42 1.000000000000011 10 1.996092794126006 20 2.693729760791369 42 -0.1140103683665206 10 1.983937233764465 20 2.600537131352887 42 0.9999999999999872 0 LWPOLYLINE 5 14D 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.722674860472906 20 2.732887777074972 42 0.0678677703915072 10 1.716999440920682 20 2.659580274525414 0 LWPOLYLINE 5 14E 102 {ACAD_REACTORS 330 C20 330 C25 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 1.697347802700083 20 2.658434024008193 42 -0.0678677703915072 10 1.703433819452505 20 2.73704507372698 42 -0.999999999999989 10 1.741915901493307 20 2.728730480422965 42 0.0678677703915072 10 1.736651079141282 20 2.660726525042634 42 -0.9999999999999999 0 LWPOLYLINE 5 164 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 11 70 0 43 0.0 10 1.811731838460656 20 3.397331983591354 42 0.2124467312467683 10 1.672244722447104 20 3.269516246350102 42 0.1056357518612903 10 1.585025186716269 20 2.838970667001557 42 0.1451314237734208 10 1.646476928687697 20 2.639513658809246 42 0.1600067868781768 10 1.833948673174001 20 2.492097314767818 42 0.1190176972929128 10 1.973432454486796 20 2.47639384269949 42 0.0768957533116813 10 2.089822894522638 20 2.509648254138302 42 0.0709021530444379 10 2.251476283461308 20 2.614030156710129 42 0.2070922264234396 10 2.404700602833892 20 2.933295599864002 42 0.0419975136654783 10 2.393883717863114 20 3.174067136850973 42 0.2398427593227676 10 2.300258287041964 20 3.311026577316722 42 0.027034225506599 0 LWPOLYLINE 5 1D5 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.848504434043273 20 2.228690132322405 42 -0.3662698243153691 10 1.793291568736173 20 2.065168888754275 0 LWPOLYLINE 5 1E1 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 4 70 0 43 0.0 10 1.838460881357442 20 2.490495972621108 42 0.1790279848154445 10 1.825573029994973 20 2.288268448973123 42 0.0769094708198934 10 1.880276536811822 20 2.173319033432963 42 -0.3080726058837938 10 1.880276536811822 20 2.030140317515856 0 LWPOLYLINE 5 21B 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.842082767727739 20 1.084629450592382 42 0.1471000450502847 10 2.973927140373517 20 1.328615998752327 42 0.012522411014275 0 LWPOLYLINE 5 222 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.698425240848715 20 1.242823919320058 42 -0.1015039731478666 10 2.611250576927156 20 1.057272707094957 42 -0.0126876031091603 0 LWPOLYLINE 5 225 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.242747987090025 20 1.529761688692975 42 0.0725476044851412 10 2.257696032217536 20 1.639194230959991 42 0.0343380551866947 0 LWPOLYLINE 5 226 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.495551054582072 20 1.53241438712026 42 0.1036418617890253 10 2.558948542514864 20 1.68753297643855 42 0.053253313175051 0 LWPOLYLINE 5 227 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.821324146542795 20 1.632324731905094 42 0.1131246587363501 10 2.830405427290065 20 1.811571024886944 42 0.0627672114645879 0 LWPOLYLINE 5 22E 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 13 70 0 43 0.0 10 2.093724705533888 20 1.557613530636603 42 0.2441872791679012 10 3.026855656910417 20 1.767371768597087 42 -0.2679491924311224 10 3.157725822448509 20 1.69686877794936 42 -0.1202060689774955 10 3.218222973836714 20 1.510442253718783 42 -0.1376749084255927 10 3.164885690739821 20 1.246107314101505 42 -0.1576175352251851 10 3.093739724933785 20 1.174961348295469 42 -0.0918492106817739 10 2.728380896324767 20 1.066112269787028 42 -0.0504127972198909 10 2.347761134221376 20 1.063970822126171 42 -0.1916344722089164 10 2.225767565997291 20 1.163124980703929 42 -0.1572294045872512 10 2.090834049478103 20 1.818212016772601 42 -0.082508630093775 10 2.21598539544255 20 2.26448668874584 42 0.000862340954801 10 2.279411658998576 20 2.40050474988379 42 0.1021773121869368 10 2.404700602833892 20 2.933295599864003 42 0.1021773121869368 0 LWPOLYLINE 5 231 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 4 70 0 43 0.0 10 2.099277124665835 20 3.285428055915363 42 0.5205670505517482 10 2.139077350685995 20 3.338013952617782 42 0.1061689985690478 10 2.120029457222835 20 3.371005871873133 42 0.613270554273111 10 2.068634698539837 20 3.335369986556996 0 LWPOLYLINE 5 232 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 4 70 0 43 0.0 10 1.973661171909946 20 3.292995281984995 42 -0.3922502215719873 10 1.946797519362752 20 3.372829517019611 42 -0.7101707266102861 10 2.015384873593222 20 3.366828901063208 42 -0.0639643640494128 10 2.018358052101874 20 3.342323304531541 0 LWPOLYLINE 5 235 102 {ACAD_REACTORS 330 BFB 330 C40 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 8 70 1 43 0.0 10 2.098548696321338 20 3.265756498601605 42 0.5205670505517482 10 2.157811705099888 20 3.344057522729578 42 0.1134405246031883 10 2.132468959817252 20 3.3865310504764 42 0.6360781342605795 10 2.049130653843808 20 3.332706714979239 42 0.9999999999999999 10 2.088138743235865 20 3.338033258134752 42 -0.5492430075431818 10 2.107983316870547 20 3.354815495403025 42 -0.0921948717360171 10 2.120342996272102 20 3.331970382505986 42 -0.5205670505517482 10 2.100005553010331 20 3.305099613229121 42 0.999999999999977 0 LWPOLYLINE 5 267 102 {ACAD_REACTORS 330 BFC 330 C40 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 8 70 1 43 0.0 10 1.998673497536078 20 3.342461458603947 42 0.0639643640494127 10 1.996304467484263 20 3.361987529592359 42 0.7101707266102861 10 1.964747355896155 20 3.364748419109942 42 0.3922502215719873 10 1.983074304769177 20 3.310283824571807 42 -0.9999999999999997 10 1.964248039050714 20 3.275706739398183 42 -0.3922502215719873 10 1.92884768282935 20 3.380910614929281 42 -0.7101707266102861 10 2.034465279702181 20 3.371670272534057 42 -0.0639643640494129 10 2.038042606667671 20 3.342185150459134 42 -0.9999999999999888 0 LWPOLYLINE 5 2AF 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.085608292827229 20 1.648485389947214 42 0.2371550452328881 10 3.038263728075514 20 1.980095333928444 42 0.0363699080748577 0 LWPOLYLINE 5 2B5 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.428981511922024 20 1.228952354254482 42 -0.1215147796354945 10 2.347761134221376 20 1.063970822126171 42 -0.0158934016013214 0 LWPOLYLINE 5 34A 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 6 70 0 43 0.0 10 2.100129120524675 20 1.887439157700382 42 0.1601220285391677 10 2.669056601079002 20 2.103591135847005 42 0.3249446074510534 10 2.710306617856964 20 2.257538294275427 42 0.3057060432679023 10 2.64763418517673 20 2.301422004076068 42 0.1122985838264234 10 2.540456015841269 20 2.279007501710551 42 0.067059303923133 10 2.127272926405246 20 2.017804783046922 42 0.0105768622903034 0 LWPOLYLINE 5 34C 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 5 70 0 43 0.0 10 2.669056601079002 20 2.103591135847005 10 2.735759906135099 20 2.150297292870786 42 -0.2679491924311215 10 2.905437956246976 20 2.165142198704758 42 -0.3152987888789877 10 3.038801514311188 20 1.93414974025938 42 -0.0857659994463428 10 2.98610429311309 20 1.734756081375588 42 -0.0017098342482428 0 LWPOLYLINE 5 38C 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.169209475319699 20 1.278410952985928 42 0.2549125200517152 10 3.219511504449442 20 1.483099110977059 42 0.0218867276949896 0 LWPOLYLINE 5 44D 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.380970941004577 20 3.751630247646181 42 0.2679491924311219 10 2.309791821489833 20 3.828814460633206 0 LWPOLYLINE 5 44E 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 2.028658926483394 20 3.899981872009325 42 0.1316524975873958 10 1.971574507059384 20 3.857657770838914 0 LWPOLYLINE 5 44F 102 {ACAD_REACTORS 330 BFE 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.035890886983224 20 3.881673417068221 42 0.1316524975873958 10 1.986991796041955 20 3.84541816400579 42 -1.000000000000004 10 1.956157218076813 20 3.869897377672038 42 -0.1316524975873958 10 2.021426965983563 20 3.918290326950429 42 -1.0 0 LWPOLYLINE 5 451 102 {ACAD_REACTORS 330 BFD 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.36176616039695 20 3.747308537705142 42 0.2679491924311219 10 2.303932141782747 20 3.810021777782375 42 -1.000000000000003 10 2.315651501196919 20 3.847607143484037 42 -0.2679491924311219 10 2.400175721612204 20 3.755951957587221 42 -1.0 0 LWPOLYLINE 5 480 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 15 70 0 43 0.0 10 2.164414868289778 20 1.116788876483231 42 -0.1509933859269548 10 2.011994434051636 20 1.339405082556968 42 -0.1070963951594745 10 1.964337309124437 20 1.884128513074088 42 -0.0569571948585108 10 1.999005825805648 20 2.025855120814207 42 0.1145587361047281 10 2.02996377257399 20 2.271091588487681 42 0.1238858905685379 10 1.988035257076031 20 2.386289238049577 42 0.3726487049030961 10 1.897599265772163 20 2.410521488886157 42 0.1535645609181053 10 1.752129598807603 20 2.273262792103868 42 0.013230494041686 10 1.679912845283239 20 2.135632504011972 42 -0.0334295576837925 10 1.547372627715803 20 1.906066113138941 42 0.1212729089747999 10 1.459245452693659 20 1.663938689725279 42 0.142060045402927 10 1.535615350530265 20 1.230823476558462 42 0.2110002865385294 10 1.767733703190374 20 1.036053052451884 42 0.0977925466168199 10 1.905714464335645 20 1.023981300066994 42 0.1523642735345087 10 2.225767565997291 20 1.16312498070393 42 0.0131161693340735 0 LWPOLYLINE 5 489 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.726540556633805 20 2.226489993047315 42 0.1491830429238438 10 1.791794192050712 20 2.183894323205893 0 LWPOLYLINE 5 48A 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.654521263715424 20 2.085752782994799 42 0.2936017206055124 10 1.910780338072042 20 1.973525769477851 0 LWPOLYLINE 5 48B 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.551496630284455 20 1.912244632638939 42 0.2413057746814911 10 1.835672170020508 20 1.78904239903142 0 LWPOLYLINE 5 48C 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.460547644534427 20 1.674926403649493 42 0.2628135643200116 10 1.85610884645455 20 1.543874911031386 0 LWPOLYLINE 5 48D 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.476099861503821 20 1.396361427764304 42 0.4559232792117359 10 1.995510222782983 20 1.397313095656098 42 0.0249343028351756 0 LWPOLYLINE 5 48E 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.940182455435743 20 1.155046537921709 42 -0.1735068790932082 10 1.591939878857363 20 1.147027352610094 42 -0.0902466536252015 0 LWPOLYLINE 5 48F 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 5 70 0 43 0.0 10 1.685157252816573 20 1.071176985228859 42 -0.0967671337827555 10 1.386905873969099 20 1.073654945933856 42 -0.1283919655451407 10 0.9396849704065366 20 1.293355139281928 42 -0.2277426076900994 10 0.8184698262111015 20 1.571535724136809 42 -0.2585706959153292 10 0.9396146897297675 20 1.77228158619182 42 -0.0016259949892818 0 LWPOLYLINE 5 490 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 6 70 0 43 0.0 10 1.454805769320285 20 1.564461529127514 42 -0.1581711632332484 10 1.079130851571503 20 1.639243530487171 42 -0.1439729528407531 10 0.9262274383574314 20 1.795491369527463 42 -0.2034041621669866 10 0.9154532561194422 20 1.918640836027165 42 -0.194428280448302 10 1.041151067775051 20 2.068441654648967 42 -0.1994742666452343 10 1.19286906097098 20 2.082870785844477 42 -0.0611756567655047 0 LWPOLYLINE 5 492 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 5 70 0 43 0.0 10 1.527535040931072 20 1.87410829973367 42 -0.1177728459219032 10 1.312388080418405 20 1.947278913508062 42 -0.1120190572174949 10 1.206886139482316 20 2.052780854444151 42 -0.6961980985337713 10 1.357198164134302 20 2.248853535690163 42 -0.1138630283068457 10 1.650613743929805 20 2.078374984748495 42 -0.0035904482483965 0 LWPOLYLINE 5 4AD 102 {ACAD_REACTORS 330 BAE 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 5 70 1 43 0.0 10 2.991096081171635 20 1.314895048081054 42 0.0536325233126152 10 3.198865278725419 20 1.441471338442461 42 -0.1019234865027202 10 3.147359585391412 20 1.255070371967993 42 -0.1576175352251851 10 3.084776667067298 20 1.19248745364388 42 -0.0487853903884156 10 2.898805094451518 20 1.119232145882148 42 0.1091929375390922 0 LWPOLYLINE 5 4B5 102 {ACAD_REACTORS 330 BBA 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 6 70 1 43 0.0 10 2.183868006181016 20 1.294456920706576 42 0.2503802653463202 10 3.199550468590465 20 1.49218169636237 42 0.0087756063211912 10 3.19859257272434 20 1.508976604658183 42 0.1202060689774955 10 3.140975326177503 20 1.686528485415947 42 0.2542613217194215 10 3.034045022847889 20 1.747720550442733 42 -0.2349955175811071 10 2.117425810875627 20 1.531432319991749 42 0.0576901279999135 0 LWPOLYLINE 5 4B9 102 {ACAD_REACTORS 330 BAD 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 5 70 1 43 0.0 10 2.714378415408047 20 1.225693872673844 42 -0.0759384074577222 10 2.650179425501943 20 1.079126736500261 42 0.0101996300129822 10 2.726291014277126 20 1.085686057566314 42 0.0261370793966787 10 2.832212463468567 20 1.102630606438461 42 0.1222814332374564 10 2.945078532962091 20 1.294462394011187 42 -0.0530654994633163 0 LWPOLYLINE 5 4BA 102 {ACAD_REACTORS 330 BAC 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.385206484967541 20 1.080514837710239 42 0.0878528142492813 10 2.44424140664477 20 1.208278724252974 42 0.0501038956066548 10 2.671374519065504 20 1.218555099887139 42 -0.0813315417893164 10 2.600965728709292 20 1.076545040917626 42 -0.0288327089816677 0 LWPOLYLINE 5 4BC 102 {ACAD_REACTORS 330 BAB 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.204441612310571 20 1.2474540192852 42 0.0447207077553119 10 2.404217085512474 20 1.211187767388987 42 -0.0963940214031873 10 2.341193762157614 20 1.087133059592365 42 -0.1740198039637825 10 2.242925650927047 20 1.172774016895618 42 -0.0196351821885444 0 LWPOLYLINE 5 4C0 102 {ACAD_REACTORS 330 BAF 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.111590265540881 20 1.573348926544125 42 0.0291422971591348 10 2.228085740598704 20 1.551356274330868 42 0.0473221239695471 10 2.237652044114153 20 1.619229653732975 42 -0.0287252676909968 10 2.106626866510892 20 1.626116355527945 42 0.0123842072538969 0 LWPOLYLINE 5 4C1 102 {ACAD_REACTORS 330 BB0 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.267503548545168 20 1.547048928709969 42 0.0533543951524521 10 2.484089073429926 20 1.550784222461052 42 0.0768690501849397 10 2.532391987223791 20 1.659393561191435 42 -0.0566860153224456 10 2.277093772004332 20 1.620104770218732 42 -0.0458852076194563 0 LWPOLYLINE 5 4C3 102 {ACAD_REACTORS 330 BB1 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.575978434475863 20 1.672202312238555 42 -0.0711923834185597 10 2.534187811152101 20 1.558291292956125 42 0.0701806584121727 10 2.804649062203535 20 1.646049204465365 42 0.0880028594988734 10 2.815004646385387 20 1.779090298343385 42 -0.0574665063324246 0 LWPOLYLINE 5 4C7 102 {ACAD_REACTORS 330 BBB 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 7 70 1 43 0.0 10 2.10461778187463 20 1.665965877260762 42 -0.0351389292849169 10 2.110402761135924 20 1.8160751267299 42 -0.0095038145827776 10 2.117156173606469 20 1.868640946110094 42 0.1557808751637161 10 2.680907394207461 20 2.087858154687554 10 2.747050780866419 20 2.134172252628876 42 -0.2679491924311215 10 2.897118699126096 20 2.147301494235533 42 -0.2502096061484992 10 3.017490352158867 20 1.987010103205812 42 -0.2309255538296563 0 LWPOLYLINE 5 4C8 102 {ACAD_REACTORS 330 BBC 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 6 70 1 43 0.0 10 2.123645620818254 20 1.90852967158985 42 0.1535620368154201 10 2.656669093820602 20 2.118889842946778 42 0.3249446074510534 10 2.691929368331739 20 2.250482978911167 42 0.3057060432679023 10 2.647289746908166 20 2.281739978334781 42 0.1122985838264234 10 2.548658946753702 20 2.261113013747846 42 0.0661825067963756 10 2.144771760651222 20 2.006772737968957 42 0.0180243406510753 0 LWPOLYLINE 5 4C9 102 {ACAD_REACTORS 330 C20 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 17 70 1 43 0.0 10 1.795927086013099 20 3.369886028656918 42 0.1834763883041901 10 1.690295415947398 20 3.261663015221454 42 0.1056357518612903 10 1.604709116716065 20 2.839179652083978 42 0.1451314237734208 10 1.66286553317314 20 2.650418447574797 42 0.1600067868781768 10 1.84068071995552 20 2.510595431459335 42 0.1190176972929128 10 1.970981934519221 20 2.495925758296534 42 0.0768957533116813 10 2.081584776821197 20 2.527526570382813 42 0.0709021530444379 10 2.238571559817636 20 2.628895178831943 42 0.2070922264234396 10 2.385030570405729 20 2.934064104435615 42 0.0419975136654783 10 2.374361839564172 20 3.171537899281493 42 0.2041023265544078 10 2.30953573868931 20 3.281794913306262 42 -0.0638786287537656 10 2.253905428386551 20 3.190122198930097 42 -0.4158687069147495 10 2.110688753100606 20 3.174368364648643 10 2.049360338450518 20 3.223826763560005 10 2.020698206844207 20 3.208114453397319 42 -0.275738643742557 10 1.918435234414153 20 3.198657998664349 42 -0.2118780432517558 10 1.805265959929118 20 3.331038401042169 42 -0.0269158367577847 0 LWPOLYLINE 5 4CB 102 {ACAD_REACTORS 330 C28 330 C40 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 13 70 1 43 0.0 10 2.053553115266256 20 3.271022854778554 10 2.135403416533275 20 3.205014547305152 42 0.4158687069147495 10 2.223120154016859 20 3.214663388428346 42 0.26959558438999 10 2.279122382999181 20 3.59460007917116 42 0.5581360462772155 10 2.145920537005866 20 3.617785434351675 42 0.0728307330332283 10 2.101616152707511 20 3.548832485588364 42 -0.9381223686609327 10 2.064870809553132 20 3.562742050811843 10 2.082872800905891 20 3.621344458486482 42 0.2046959930292842 10 2.062725504642901 20 3.696637502728181 42 0.3964961476078332 10 1.972491420232154 20 3.71032661793588 42 0.3247796006490571 10 1.842995028063519 20 3.342286535008118 42 0.2118780432517558 10 1.935414224296555 20 3.23417865466307 42 0.2856103122495783 10 1.999267568517967 20 3.241264030153233 0 LWPOLYLINE 5 4CD 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.541590875260533 20 1.219181584929098 42 -0.2584842710932977 10 0.820082757115996 20 1.522632196851646 42 -0.0230272271526239 0 LWPOLYLINE 5 4CE 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.458123574270783 20 1.652827431708805 42 -0.2951443317480729 10 0.941461714899275 20 1.974891353638494 42 -0.0281477710443027 0 LWPOLYLINE 5 4CF 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.149191552360515 20 1.154795257187257 42 0.1554073147032292 10 0.735992563639889 20 1.096559104863405 42 -0.383579166426189 10 0.9194102381455578 20 1.312304764434089 42 -0.023050174561539 0 LWPOLYLINE 5 4D0 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.24989523667859 20 1.240900333949516 42 0.1256439210154252 10 1.345357819803049 20 1.083069957917427 42 0.0704007111098051 0 LWPOLYLINE 5 4D1 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.037864942416157 20 1.3303917414282 42 0.0872453218025478 10 1.042370972787492 20 1.21582065403204 42 0.0971278145482142 0 LWPOLYLINE 5 4D2 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.252136016103313 20 1.688388482710066 42 0.0590285034647111 10 1.266518295486159 20 1.571079816805446 42 0.040710128897272 0 LWPOLYLINE 5 4D3 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.052845021272466 20 1.816519721371516 42 0.1113687809723345 10 1.031596064763292 20 1.670646745988808 42 0.1054872080523193 0 LWPOLYLINE 5 4E7 102 {ACAD_REACTORS 330 BB6 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 1.055916139802069 20 1.183858027338503 42 0.1086902960134493 10 0.7572717136065252 20 1.127799089885956 42 -0.3246303955088655 10 0.9126882033208936 20 1.29130332219202 42 0.0129078914938259 10 0.9268235401588977 20 1.278452643283383 42 0.0398388581973403 0 LWPOLYLINE 5 4EB 102 {ACAD_REACTORS 330 BA6 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 1.060018004406812 20 1.22781950439698 42 -0.056608990335621 10 1.05478008384554 20 1.297904456500116 42 0.0588177228710549 10 1.234398517271265 20 1.224686922587824 42 0.0753850106847673 10 1.287966831577129 20 1.11990052780729 42 -0.0655149355972575 0 LWPOLYLINE 5 4EE 102 {ACAD_REACTORS 330 BB7 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 6 70 1 43 0.0 10 0.9337884234626875 20 1.745337488462597 42 0.1140426130224996 10 1.069517024899449 20 1.622065780002278 42 0.1496103246747427 10 1.435800351452426 20 1.542762378894283 42 0.098469544262505 10 1.511203238184653 20 1.236207952572697 42 -0.2469581287149142 10 0.8391304022153184 20 1.53029339160826 42 -0.0306677320577088 10 0.8381414565311932 20 1.570809270042459 42 -0.2364748902496887 0 LWPOLYLINE 5 4F0 102 {ACAD_REACTORS 330 BA5 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 0.8557672849696794 20 1.451424859785045 42 0.0630395648108045 10 1.01685683292838 20 1.320182987586002 42 0.0445931465006306 10 1.016312593127104 20 1.257746897185134 42 -0.0210506403179615 10 0.9525464006541762 20 1.308257635280474 42 -0.1329522052869259 0 LWPOLYLINE 5 4F3 102 {ACAD_REACTORS 330 C01 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 17 70 1 43 0.0 10 1.84986913761158 20 2.466300860817559 42 0.0673153145939977 10 1.833988541120499 20 2.395045529905472 42 -0.0456048674756574 10 1.889008320037764 20 2.428232966136522 42 -0.3726487049030961 10 2.004330972949735 20 2.397332354419744 42 -0.1238858905685379 10 2.049545393540757 20 2.273106754812188 42 -0.1145587361047281 10 2.017472341220017 20 2.019036867118983 42 0.0569571948585108 10 1.983866015583199 20 1.881652548807571 42 0.1070963951594745 10 2.030796508895675 20 1.345234555651572 42 0.1426114747077699 10 2.165557450307532 20 1.141311124747446 42 0.019413333947305 10 2.200668024179765 20 1.167752668813839 42 -0.1534467262547569 10 2.071265337820281 20 1.820348906815302 42 -0.082508630093775 10 2.198159065568731 20 2.272836703011166 42 0.000862340954801 10 2.261556633001577 20 2.408793225114376 42 0.0606801155133229 10 2.360970556998814 20 2.715554284918385 42 -0.0817679966984111 10 2.264381007104979 20 2.599165134588315 42 -0.0709021530444379 10 2.098061012224078 20 2.49176993789379 42 -0.0768957533116813 10 1.97588297445437 20 2.456861927102445 42 -0.1001198017354382 0 LWPOLYLINE 5 4F4 102 {ACAD_REACTORS 330 BB3 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 11 70 1 43 0.0 10 1.985708655480637 20 1.35859138415058 42 -0.3682846044885977 10 1.514588534428652 20 1.333441193996956 42 0.0330251139842943 10 1.553282361892708 20 1.239505497320984 42 0.0639008891509803 10 1.603183045430495 20 1.164065854453502 42 0.1707629002601277 10 1.933126177068946 20 1.17342341770615 42 -1.000000000000009 10 1.94723873380254 20 1.136669658137267 42 -0.1354090889595181 10 1.663131530982194 20 1.10889954806288 42 0.0869057462878126 10 1.77321598022121 20 1.054959279298051 42 0.0977925466168199 10 1.903598507249911 20 1.043552286261177 42 0.1070337225744706 10 2.131038389154381 20 1.11916439867858 42 -0.1361955436546222 10 1.993192359207598 20 1.333575609462363 42 -0.0049803061650251 0 LWPOLYLINE 5 4F7 102 {ACAD_REACTORS 330 BB4 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 36 70 1 43 0.0 10 1.800080314455621 20 2.308917195085585 42 0.0437118087611369 10 1.769312650034374 20 2.26365844280057 42 0.0033308209162503 10 1.750572816609542 20 2.229600425683039 42 0.1199820129190778 10 1.797274715454282 20 2.202801058466759 42 -0.9999999999999999 10 1.786313668647142 20 2.164987587945027 42 -0.1021140647943497 10 1.731552642365071 20 2.193892004093673 42 0.0064323953109214 10 1.697579856645681 20 2.12695048324945 42 -0.0055509425268816 10 1.677510563493305 20 2.087231690238655 42 0.2805803818424905 10 1.907675826757856 20 1.99296446245093 42 -1.000000000000002 10 1.913884849386228 20 1.954087076504771 42 -0.2626963580826674 10 1.65730585773017 20 2.04932297149283 42 -0.0197119133471879 10 1.576111447954835 20 1.913814831608159 42 0.229407728918388 10 1.834403866994767 20 1.808686537659429 42 -1.000000000000006 10 1.836940473046249 20 1.76939826040341 42 -0.2218376429216039 10 1.55389731810562 20 1.879874561474816 42 0.1027759246248995 10 1.481321802657222 20 1.68147851322532 42 0.2567981434431833 10 1.852312329231318 20 1.563190377165427 42 -0.9999999999999999 10 1.859905363677781 20 1.524559444897346 42 -0.2372321476697851 10 1.476143434862462 20 1.631501691187762 42 0.0739602798598165 10 1.494131551859586 20 1.40568894806263 42 0.4420288920812132 10 1.973843248718476 20 1.402603074502723 42 -0.0932841665178725 10 1.944808602665675 20 1.886604477340606 42 -0.0569571948585108 10 1.98053931039128 20 2.032673374509431 42 0.1145587361047281 10 2.010382151607223 20 2.269076422163175 42 0.1238858905685379 10 1.971739541202327 20 2.375246121679411 42 0.3726487049030961 10 1.906190211506561 20 2.392810011635793 42 0.0692252662755674 10 1.834372402647776 20 2.344740013080819 42 0.0476713025068407 10 1.844432384008702 20 2.293909862021855 42 0.0769094708198934 10 1.896548904341149 20 2.184396525477287 42 -0.3080726058837938 10 1.896548904341149 20 2.019062825471532 42 -0.9999999999999999 10 1.864004169282495 20 2.041217809560179 42 0.2582998793018828 10 1.873587490264647 20 2.144928461209456 42 -0.2026932661734018 10 1.803462564620088 20 2.048315057803096 42 -0.999999999999995 10 1.783120572852258 20 2.082022719705455 42 0.3646986474062371 10 1.830429247500239 20 2.220863495048448 42 -0.0379960309145583 10 1.806713675981244 20 2.282627035924392 42 -0.0217555693507311 0 LWPOLYLINE 5 505 102 {ACAD_REACTORS 330 BB8 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 7 70 1 43 0.0 10 1.496545734250796 20 1.858090362879029 42 0.0874292139153708 10 1.440409322525223 20 1.672501008241135 42 -0.2810079005908725 10 0.963992618224232 20 1.973488406523313 42 -0.1221105918102025 10 1.050391027094316 20 2.051059942225276 42 -0.1855272393840248 10 1.177801591011496 20 2.066644978446405 42 0.0452485050555582 10 1.190231879786862 20 2.04228626493346 42 0.1120190572174949 10 1.301893490907713 20 1.930624653812608 42 0.1031607726849441 0 LWPOLYLINE 5 507 102 {ACAD_REACTORS 330 BA9 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 5 70 1 43 0.0 10 1.232680305288136 20 1.674823294981787 42 0.0376631697644602 10 1.24092624183496 20 1.596731177563018 42 -0.0683286784235571 10 1.088744678243557 20 1.656421280972064 42 -0.0308076295927463 10 1.050667583615558 20 1.680925971586079 42 -0.0803202890882193 10 1.061814443246697 20 1.780967062069061 42 0.0873178465018551 0 LWPOLYLINE 5 509 102 {ACAD_REACTORS 330 BA8 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 5 70 1 43 0.0 10 1.03011243645825 20 1.811587717464269 42 0.0701949736097343 10 1.011360717734072 20 1.714273589617648 42 -0.0772792890158624 10 0.9436091507811217 20 1.804731328846728 42 -0.2034041621669866 10 0.9341754033724281 20 1.912559555139139 42 -0.021365350595909 10 0.9413736096183022 20 1.931870968260919 42 0.0646639173137995 0 LWPOLYLINE 5 50B 102 {ACAD_REACTORS 330 BB9 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 6 70 1 43 0.0 10 1.517012100394491 20 1.895029973752357 42 -0.1110664831625005 10 1.322882669929097 20 1.963933173203516 42 -0.1120190572174949 10 1.22354039917777 20 2.063275443954843 42 -0.6961980985337713 10 1.351388497511153 20 2.230045331397104 42 -0.1086664830114359 10 1.62603521686569 20 2.074220841935225 42 -0.0233827832969574 10 1.531020271498053 20 1.917025183406504 42 0.0116709324309886 0 LWPOLYLINE 5 510 102 {ACAD_REACTORS 330 BB2 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 2.84997659259958 20 1.669588479790926 42 0.0790070326196522 10 2.851886405500074 20 1.80192109397708 42 0.0465967056483061 10 3.018962226551324 20 1.933310565196752 42 -0.0825476832350667 10 2.970238833200536 20 1.747438830578402 42 -0.0352296221604151 0 LWPOLYLINE 5 559 102 {ACAD_REACTORS 330 BA7 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 5 70 1 43 0.0 10 1.355385427777645 20 1.100872595462885 42 -0.0964781721945481 10 1.280659164315312 20 1.213328327577104 42 0.0761322456062632 10 1.530692586565761 20 1.198306536487731 42 0.0982025130561956 10 1.632063828471465 20 1.082968026772228 42 -0.0801281899540377 10 1.390840639583887 20 1.092942724306655 42 -0.009398208639944 0 LWPOLYLINE 5 620 102 {ACAD_REACTORS 330 BAA 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 4 70 1 43 0.0 10 1.272750873165488 20 1.660423889558836 42 0.0720111964992741 10 1.436797603060258 20 1.633190144890045 42 0.0157631540077514 10 1.434991753420616 20 1.582208383349729 42 -0.0636343006390252 10 1.282776238934902 20 1.588169636138475 42 -0.0378416081317004 0 LWPOLYLINE 5 8B3 102 {ACAD_REACTORS 330 C28 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 48 70 1 43 0.0 10 3.027996198643118 20 1.787090153383295 42 -0.2652120571486825 10 3.174476318719514 20 1.707209070482774 42 -0.1202060689774955 10 3.237853374949089 20 1.511907902779382 42 -0.1376749084255928 10 3.182411796088231 20 1.237144256235018 42 -0.1576175352251852 10 3.102702782800273 20 1.157435242947061 42 -0.091849210681774 10 2.73047077837241 20 1.046538482007744 42 -0.0506776859186796 10 2.34388013009181 20 1.044567731825123 42 -0.1678583337512084 10 2.221067012551395 20 1.133620430754517 42 -0.1427259380349648 10 1.907830421421379 20 1.004410313872811 42 -0.0977925466168198 10 1.762251426159538 20 1.017146825605717 42 -0.0554068829065345 10 1.681692239060136 20 1.050537537701288 42 -0.0944908669632265 10 1.382971108354313 20 1.054367167561056 42 -0.063211812705244 10 1.14310982680291 20 1.135855466777803 42 0.1543252686721255 10 0.7445258947417084 20 1.078819797230121 42 -0.5434510775266247 10 0.7163152163407374 20 1.096008851948713 42 -0.3401781029993987 10 0.8820862850200285 20 1.324403005153777 42 -0.182531460234485 10 0.79879819589101 20 1.572262178231159 42 -0.2383486190805098 10 0.9129246094229353 20 1.778768451782942 42 -0.0052329189934023 10 0.9088457259337407 20 1.786251410208198 42 -0.2034041621669866 10 0.8967311088664565 20 1.92472211691519 42 -0.194428280448302 10 1.031911108455786 20 2.085823367072657 42 -0.1617232608950327 10 1.167586754433075 20 2.108823943952719 42 -0.5347302517393296 10 1.363007830757451 20 2.267661739983221 42 -0.105444424534756 10 1.644986728674037 20 2.110043533348865 42 0.0048822169168032 10 1.662245833920796 20 2.144314524774496 42 -0.013230494041686 10 1.734946547580834 20 2.282867141407166 42 -0.0694197792179022 10 1.793844951212572 20 2.360618102610478 42 -0.097214664119097 10 1.812670378378858 20 2.479214960413685 42 -0.1500723642402677 10 1.630088324202255 20 2.628608870043696 42 -0.1451314237734207 10 1.565341256716473 20 2.838761681919137 42 -0.1056357518612903 10 1.65419402894681 20 3.277369477478751 42 -0.1962234048498945 10 1.790739940431784 20 3.410546342344788 42 -0.2655031168224304 10 1.950118462130682 20 3.742721892989442 42 -0.3964961476078332 10 2.093699839480827 20 3.720939635995741 42 -0.1405234862865436 10 2.122456164203622 20 3.650189734969364 42 -0.5343574555981587 10 2.315679239916688 20 3.609215116369852 42 -0.1773163153754776 10 2.324179645939324 20 3.319578756296038 42 -0.2178846001444296 10 2.413405596162056 20 3.176596374420452 42 -0.0419776577731284 10 2.424375140175325 20 2.932642516763373 42 -0.1021560486223639 10 2.297266684995574 20 2.392216274653201 42 -0.0008623409548011 10 2.233811725316336 20 2.256136674480434 42 0.0354069305283612 10 2.162996833972185 20 2.072072274041452 42 -0.0586147259804529 10 2.532253084928835 20 2.296901989673256 42 -0.1122985838264234 10 2.647978623445294 20 2.321104029817356 42 -0.3057060432679023 10 2.728683867382189 20 2.264593609639688 42 -0.1508928720957283 10 2.734821253334247 20 2.173180071930798 42 -0.2505867392793861 10 2.913757213367856 20 2.182982903173984 42 -0.3152987888789875 10 3.058411646163387 20 1.932434076032064 42 -0.0595813595316129 0 HATCH 5 BA5 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 1.454717916970981 20 2.022108206218515 40 0.8272976136018175 50 223.615566083045 51 238.0440774153107 73 1 72 2 10 1.365920530767478 20 1.285919869338796 40 0.3507412528077177 50 174.3939645983117 51 184.6071947080589 73 1 72 2 10 1.584035429735767 20 2.039961850738251 40 0.9665244191271588 50 125.9717238731088 51 130.7954628287447 73 0 72 2 10 1.168606309785878 20 1.558605525778289 40 0.3306901126594289 50 130.7954628287448 51 161.0882096390424 73 0 97 1 330 4F0 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BA6 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 1.365920530767478 20 1.285919869338796 40 0.3113711740675595 50 169.2458500319289 51 182.205842988757 73 0 72 2 10 1.454717916970979 20 2.022108206218515 40 0.827297613601817 50 241.09054843511 51 254.5550649161042 73 1 72 2 10 1.606711922375474 20 1.348933253591385 40 0.3924976718251174 50 198.4545948543501 51 215.6989500329358 73 1 72 2 10 1.584035429735761 20 2.039961850738243 40 0.9665244191271488 50 107.8377726397921 51 122.8312626374707 73 0 97 1 330 4EB 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BA7 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 5 72 2 10 1.606711922375474 20 1.348933253591385 40 0.3531275930849602 50 135.3746912145926 51 157.4176362906217 73 0 72 2 10 1.454717916970981 20 2.022108206218514 40 0.827297613601817 50 257.8545362072944 51 275.2691677284761 73 1 72 2 10 1.872170704325741 20 1.396215376152876 40 0.3946836881941063 50 210.0950891144055 51 232.5295145799341 73 1 72 2 10 1.542373482613905 20 1.835739673019258 40 0.75809597646572 50 83.20542127045559 51 101.5302981560868 73 0 72 2 10 1.584035429735767 20 2.039961850738253 40 0.9665244191271609 50 101.5302981560871 51 103.684145503982 73 0 97 1 330 559 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BA8 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 5 72 2 10 1.365613936631296 20 1.696475315724716 40 0.3547000446188475 50 161.0626247765776 51 177.1237827075663 73 1 72 2 10 1.26836984905495 20 1.977371145189359 40 0.3677961627452389 50 134.3293201388803 51 152.0052969205894 73 0 72 2 10 1.065938622495786 20 1.869760556959495 40 0.1385398865270621 50 152.0052969205897 51 197.9947030794107 73 0 72 2 10 1.163637847655055 20 1.838026139816656 40 0.2412638458944715 50 197.9947030794104 51 202.8905358909278 73 0 72 2 10 1.448830865211249 20 2.213371853903019 40 0.5803064835681331 50 209.0183706588869 51 223.8176444671686 73 1 97 1 330 509 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BA9 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 5 72 2 10 1.75442661167109 20 1.690434343062299 40 0.5219798013778194 50 181.7138221824677 51 190.3415069086127 73 1 72 2 10 1.382209127764958 20 2.180776385554784 40 0.6008907212088186 50 103.5988396513469 51 119.2343164314062 73 0 72 2 10 1.26836984905495 20 1.977371145189357 40 0.3677961627452375 50 119.2343164314065 51 126.2926725539458 73 0 72 2 10 1.365613936631298 20 1.696475315724717 40 0.3153299658786926 50 177.17352188641 51 195.5421431149888 73 0 72 2 10 1.448830865211245 20 2.213371853903018 40 0.5803064835681301 50 228.1704174204192 51 248.1315658423051 73 1 97 1 330 507 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BAA 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 1.448830865211245 20 2.213371853903018 40 0.5803064835681306 50 252.3365152710513 51 268.8118268997819 73 1 72 2 10 2.244252791706375 20 1.579066020312691 40 0.8092671391653076 50 176.1651718242215 51 179.7775214345853 73 1 72 2 10 1.382209127764961 20 2.180776385554781 40 0.6008907212088166 50 84.96060718028212 51 99.52487731460255 73 0 72 2 10 1.754426611671092 20 1.690434343062297 40 0.4826097226376628 50 167.7663152513758 51 176.4348368363554 73 0 97 1 330 620 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BAB 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 2.506661351932914 20 2.343882490801417 40 1.137317969685164 50 254.5896536710559 51 264.8320604814776 73 1 72 2 10 2.053956362533489 20 1.311094011306244 40 0.3642304650017842 50 15.91994768566973 51 37.94378452603665 73 0 72 2 10 2.41136725018985 20 1.266852136052575 40 0.1929333171495304 50 111.3287610035634 51 150.8157377309437 73 0 72 2 10 3.174161319020494 20 1.699913413586516 40 1.070082152487879 50 150.4873427015391 51 154.9868167954895 73 0 97 1 330 4BC 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BAC 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 2.05395636253349 20 1.311094011306242 40 0.40360054374194 50 325.1586938734879 51 345.2415144983743 73 1 72 2 10 2.506661351932912 20 2.343882490801414 40 1.137317969685161 50 266.8538285473494 51 278.3272010683704 73 1 72 2 10 2.202541654133556 20 1.362543685931675 40 0.4904456831815359 50 17.0728403884595 51 35.67171941040231 73 0 72 2 10 2.527478440588521 20 2.947760106017855 40 1.87265752378095 50 87.75100742187989 51 94.35714735717728 73 0 97 1 330 4BA 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BAD 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 5 72 2 10 2.202541654133554 20 1.362543685931673 40 0.5298157619216942 50 14.96903515149527 51 32.33949759932654 73 0 72 2 10 2.527478440588518 20 2.947760106017868 40 1.872657523780963 50 273.7568474686516 51 276.0943494215687 73 1 72 2 10 2.617288604059703 20 2.10660015529557 40 1.026716669960875 50 276.0943494215687 51 282.0831632762506 73 1 72 2 10 2.502316662315184 20 1.425846770903515 40 0.4618440522407246 50 315.5859663701619 51 343.4723636742463 73 1 72 2 10 2.506661351932922 20 2.3438824908014 40 1.137317969685146 50 67.32624731613089 51 79.47656760874074 73 0 97 1 330 4B9 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BAE 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 5 72 2 10 2.506661351932912 20 2.343882490801413 40 1.137317969685161 50 295.2104838476032 51 307.4903876208237 73 1 72 2 10 2.72065401068705 20 1.473292657067691 40 0.4792688318657009 50 3.806985506611603 51 27.08574039713036 73 0 72 2 10 3.019270278182163 20 1.32057676085313 40 0.1438678477148946 50 27.08574039713062 51 62.91425960287042 73 0 72 2 10 2.617288604059699 20 2.106600155295566 40 1.026716669960872 50 62.91425960286999 51 74.08618998756283 73 0 72 2 10 2.502316662315185 20 1.425846770903515 40 0.5012141309808816 50 322.28430360547 51 347.21072780023 73 1 97 1 330 4AD 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BAF 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 2.358343856922912 20 2.56087150497244 40 1.017884167165223 50 255.9706947110459 51 262.6477274601202 73 1 72 2 10 1.875100795739507 20 1.635718008880588 40 0.3629259890852237 50 346.5587102880505 51 357.396057379031 73 1 72 2 10 2.23202592329045 20 2.762062415766459 40 1.142846610535554 50 89.71793740532951 51 96.29947398788597 73 0 72 2 10 3.174161319020505 20 1.699913413586497 40 1.070082152487882 50 183.9544802865682 51 186.7925864334441 73 1 97 1 330 4C0 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB0 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 2.35834385692291 20 2.560871504972433 40 1.017884167165215 50 264.8798691909198 51 277.0962125668474 73 1 72 2 10 2.157099264484859 20 1.761255447038774 40 0.3888707645596128 50 327.2321171951457 51 344.8146293833702 73 1 72 2 10 2.232025923290449 20 2.762062415766465 40 1.14284661053556 50 74.76238100741742 51 87.73997032522614 73 0 72 2 10 1.875100795739506 20 1.635718008880588 40 0.4022960678253824 50 2.224226079808037 51 12.73296995122379 73 0 97 1 330 4C1 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB1 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 2.157099264484858 20 1.761255447038777 40 0.4282408432997721 50 12.00230574940428 51 28.29091643485702 73 0 72 2 10 2.358343856922911 20 2.560871504972434 40 1.017884167165216 50 279.9480036533407 51 296.005896865796 73 1 72 2 10 2.43480848147727 20 1.74176023846554 40 0.3820244196138822 50 345.4907424301736 51 365.6076870699981 73 1 72 2 10 2.232025923290445 20 2.762062415766465 40 1.142846610535562 50 59.32877074017064 51 72.48465458233305 73 0 97 1 330 4C3 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB2 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 2.434808481477273 20 1.741760238465535 40 0.4213944983540373 50 350.138398092684 51 368.2079411900966 73 1 72 2 10 2.232025923290449 20 2.76206241576646 40 1.142846610535555 50 302.8460023643591 51 313.5174616433824 73 1 72 2 10 2.435514026542539 20 1.986930556286178 40 0.5859069085937808 50 5.250840664227033 51 24.12657987446927 73 0 72 2 10 2.358343856922903 20 2.560871504972432 40 1.017884167165218 50 53.04812421612736 51 61.11882105703474 73 0 97 1 330 510 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB3 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 11 72 2 10 1.735391678484751 20 1.622446814297793 40 0.3637008069698632 50 46.50828210019076 51 127.3801843342055 73 0 72 2 10 2.244252791706377 20 1.579066020312692 40 0.7698970604251519 50 198.604632170139 51 206.170680909061 73 1 72 2 10 1.87217070432574 20 1.396215376152875 40 0.3553136094539483 50 206.170680909061 51 220.7958011940912 73 1 72 2 10 1.754854449164134 20 1.637701886096329 40 0.4973281664865742 50 252.2434918237404 51 291.0055844420299 73 1 72 2 10 1.940182455435743 20 1.155046537921708 40 0.0196850393700786 50 248.9944155579697 51 428.9944155579707 73 0 72 2 10 1.754854449164133 20 1.637701886096329 40 0.5366982452267322 50 68.99441555797011 51 99.84027979757452 73 0 72 2 10 1.872170704325739 20 1.396215376152874 40 0.3553136094539469 50 233.9619057741986 51 253.8293190909382 73 1 72 2 10 1.867289566555308 20 1.379382243234548 40 0.3377870618823355 50 253.8293190909384 51 276.1706809090611 73 1 72 2 10 1.842733556184505 20 1.606506575382589 40 0.5662349988373994 50 276.170680909061 51 300.6079669543535 73 1 72 2 10 2.448387279831183 20 1.47470612641788 40 0.4765713362946238 50 131.7514141291648 51 162.7742566190203 73 0 72 2 10 3.245154141911026 20 1.721739021653879 40 1.31075517924367 50 162.7742566190193 51 163.9156492780123 73 0 97 1 330 4F4 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB4 330 1F 100 AcDbEntity 8 HATCH-YELLOW 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 36 72 2 10 2.043049297315998 20 2.110655210550977 40 0.3135948678531067 50 140.7856547310828 51 150.7972901196548 73 1 72 2 10 4.316192387813921 20 0.8400973818280717 40 2.91772556849152 50 150.7972901196538 51 151.5606552199046 73 1 72 2 10 1.82896029060598 20 2.312110103765454 40 0.1138088004365485 50 226.4676036039469 51 253.8346334294888 73 1 72 2 10 1.791794192050712 20 2.183894323205893 40 0.0196850393700787 50 286.1653665705111 51 466.1653665705111 73 0 72 2 10 1.82896029060598 20 2.312110103765454 40 0.153178879176706 50 106.1653665705111 51 129.487348884315 73 0 72 2 10 4.31619238781396 20 0.8400973818280881 40 2.917725568491546 50 152.3551430085055 51 153.8293190909382 73 1 72 2 10 -0.1012307034243785 20 3.010931950741638 40 2.004281084551068 50 26.17068090906094 51 27.44285015917365 73 0 72 2 10 1.869973878918131 20 2.229032723885394 40 0.2390599525801008 50 216.3816426472188 51 279.0739534633693 73 1 72 2 10 1.910780338072042 20 1.973525769477851 40 0.0196850393700789 50 260.9260465366305 51 440.9260465366307 73 0 72 2 10 1.869973878918132 20 2.229032723885395 40 0.278430031320259 50 80.92604653663092 51 139.8013610445865 73 0 72 2 10 -0.101230703424352 20 3.01093195074165 40 2.004281084551049 50 28.67087156360686 51 33.18792433993601 73 0 72 2 10 1.813793246529746 20 2.127914574971419 40 0.3198926968250738 50 222.0119914468626 51 273.6941141002521 73 1 72 2 10 1.835672170020508 20 1.78904239903142 40 0.0196850393700788 50 266.3058858997472 51 446.3058858997478 73 0 72 2 10 1.813793246529746 20 2.127914574971419 40 0.3592627755652315 50 86.30588589974785 51 136.3371185375852 73 0 72 2 10 1.995105659775399 20 1.606003070595645 40 0.5192979821599312 50 148.1708625321174 51 171.6429565217715 73 1 72 2 10 1.774379750743404 20 1.9596864265737 40 0.4040824222682091 50 223.5109336967462 51 281.1199173397384 73 1 72 2 10 1.85610884645455 20 1.543874911031386 40 0.0196850393700787 50 258.8800826602615 51 438.8800826602615 73 0 72 2 10 1.774379750743404 20 1.9596864265737 40 0.4434525010083663 50 78.88008266026162 51 132.2628434475095 73 0 72 2 10 2.244252791706375 20 1.579066020312694 40 0.7698970604251502 50 176.0947114644605 51 193.0143530481955 73 1 72 2 10 1.735391678484751 20 1.622446814297793 40 0.3243307282297058 50 221.9378076910892 51 317.3250616801697 73 1 72 2 10 3.245154141910992 20 1.721739021653846 40 1.310755179243628 50 165.9082787983328 51 187.2257433809798 73 0 72 2 10 2.601728566753492 20 1.803316300498068 40 0.6621787973190414 50 187.2257433809798 51 200.265282453191 73 0 72 2 10 1.486332025585369 20 2.215145842661859 40 0.5268178451693419 50 339.734717546809 51 365.875687911445 73 1 72 2 10 1.780100104900293 20 2.245377841414935 40 0.231498258665186 50 5.875687911445098 51 34.12431208855465 73 1 72 2 10 1.928818024879454 20 2.346159501416084 40 0.0518487033762426 50 34.12431208855484 51 115.8756879114452 73 1 72 2 10 2.043049297315996 20 2.110655210550977 40 0.3135948678531048 50 115.8756879114451 51 131.7156800642676 73 1 72 2 10 2.105362384851459 20 2.371962053549119 40 0.2723538322513749 50 185.7363493931126 51 196.6535421822968 73 1 72 2 10 2.224366300494004 20 2.407559786221583 40 0.3965678834278744 50 196.6535421822967 51 214.2452636527788 73 1 72 2 10 1.775114796299714 20 2.101729675474409 40 0.1469014999420266 50 325.7547363472213 51 394.2452636527789 73 0 72 2 10 1.880276536811822 20 2.030140317515856 40 0.0196850393700786 50 34.24526365277875 51 214.2452636527787 73 0 72 2 10 1.775114796299714 20 2.101729675474409 40 0.1075314212018693 50 325.7547363472211 51 383.6864830926802 73 1 72 2 10 1.724258670730545 20 2.179559731729328 40 0.1532919477378671 50 13.05681211459937 51 58.88974415557702 73 0 72 2 10 1.793291568736173 20 2.065168888754275 40 0.0196850393700787 50 58.88974415557702 51 238.8897441555765 73 0 72 2 10 1.724258670730541 20 2.179559731729329 40 0.1139218689977123 50 301.1102558444241 51 381.2576330469557 73 1 72 2 10 2.224366300494005 20 2.407559786221586 40 0.435937962168034 50 154.6425959514791 51 163.3464578177032 73 0 72 2 10 2.105362384851463 20 2.371962053549115 40 0.3117239109915352 50 163.3464578177044 51 168.3316806257954 73 0 97 1 330 4F7 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB6 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 1.034012571047431 20 0.4770274671951757 40 0.7071698573021327 50 88.2250617963899 51 113.037640194644 73 1 72 2 10 0.9476260308821789 20 1.102477175547732 40 0.1920311575011529 50 187.577294301379 51 259.5173177193701 73 0 72 2 10 1.168606309785881 20 1.558605525778299 40 0.3700601913995948 50 226.2464306309096 51 229.2045371712558 73 1 72 2 10 1.584035429735768 20 2.03996185073825 40 1.005894497867316 50 229.2045371712552 51 238.3301051192357 73 1 97 1 330 4E7 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB7 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 6 72 2 10 1.268369849054951 20 1.97737114518936 40 0.4071662414853972 50 214.7414744545867 51 240.7656835685936 73 1 72 2 10 1.382209127764962 20 2.180776385554782 40 0.6402607999489762 50 240.7656835685933 51 274.8013992041994 73 1 72 2 10 2.244252791706376 20 1.579066020312693 40 0.8092671391653085 50 182.5711456908801 51 205.0661840751609 73 1 72 2 10 1.454717916970982 20 2.022108206218515 40 0.78792753486166 50 85.88902674875129 51 141.3773954764613 73 0 72 2 10 1.168606309785876 20 1.558605525778289 40 0.3306901126594269 50 175.0885918849935 51 182.1149161181871 73 0 72 2 10 1.060157361703603 20 1.562610439508386 40 0.2221672409957212 50 182.1149161181872 51 235.3333452342021 73 0 97 1 330 4EE 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB8 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 7 72 2 10 1.995105659775398 20 1.606003070595649 40 0.5586680609000869 50 153.1774302023765 51 173.1639087815069 73 1 72 2 10 1.448830865211247 20 2.213371853903018 40 0.5409364048279738 50 90.89204265530425 51 153.6751728635248 73 0 72 2 10 1.163637847655053 20 1.838026139816656 40 0.2412638458944706 50 214.15747754694 51 242.0052969205898 73 0 72 2 10 1.134374454956795 20 1.893074853652674 40 0.1789203855540918 50 242.0052969205894 51 284.046994134434 73 0 72 2 10 1.318324160529892 20 2.123002906229338 40 0.1514028023784195 50 201.853727881165 51 212.2168526331622 73 1 72 2 10 1.492137893232153 20 2.232530667257897 40 0.3568475494804613 50 212.2168526331617 51 237.7831473668378 73 1 72 2 10 1.573128668857933 20 2.361057982102735 40 0.5087645544459671 50 237.7831473668379 51 261.3425166986952 73 1 97 1 330 505 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BB9 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 6 72 2 10 1.573128668857933 20 2.361057982102735 40 0.4693944757058101 50 96.86618894004766 51 122.2168526331621 73 0 72 2 10 1.492137893232154 20 2.232530667257898 40 0.3174774707403054 50 122.2168526331621 51 147.7831473668382 73 0 72 2 10 1.318324160529893 20 2.123002906229338 40 0.1120327236382623 50 147.783147366838 51 287.1653967341294 73 0 72 2 10 1.134452552508394 20 1.527737292608446 40 0.7350495123332927 50 287.1653967341295 51 311.9725813008354 73 0 72 2 10 -0.1012307034243558 20 3.010931950741639 40 1.964911005810889 50 28.47135626072658 51 33.82931909093841 73 0 72 2 10 1.9951056597754 20 1.606003070595648 40 0.5586680609000885 50 146.1706809090616 51 148.8453401595469 73 1 97 1 330 50B 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BBA 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 6 72 2 10 2.506661351932914 20 2.343882490801411 40 1.097947890945 50 252.9025993502986 51 309.129589783908 73 1 72 2 10 2.720654010687031 20 1.473292657067699 40 0.4792688318657188 50 2.258737765182703 51 4.269906958171121 73 1 72 2 10 2.805854019540959 20 1.479653877718507 40 0.3938316816506187 50 4.26990695817209 51 31.68755658158391 73 1 72 2 10 3.031233358735755 20 1.618783385319762 40 0.1289678177105734 50 31.68755658158397 51 88.75077942665364 73 1 72 2 10 2.358343856922911 20 2.560871504972435 40 1.057254245905374 50 50.27455552545634 51 103.1717867618754 73 0 72 2 10 3.174161319020478 20 1.699913413586489 40 1.070082152487853 50 189.0587348045097 51 202.2656996106713 73 1 97 1 330 4B5 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BBB 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 7 72 2 10 3.174161319020492 20 1.69991341358649 40 1.070082152487867 50 178.182030269148 51 186.2319675330486 73 0 72 2 10 3.496410384846752 20 1.66472403412841 40 1.394246852682911 50 186.2319675330462 51 188.4100158185151 73 0 72 2 10 2.05576545700618 20 2.861012413940887 40 0.994268550367224 50 273.5399568619239 51 308.9576328012706 73 1 72 1 10 2.680907394207461 20 2.087858154687554 11 2.747050780866419 21 2.134172252628876 72 2 10 2.833454996760046 20 2.010774243926277 40 0.1506411533278984 50 235.0000000000002 51 295.0 73 0 72 2 10 2.807174025728471 20 1.954414519671351 40 0.2128272285895981 50 294.9999999999998 51 351.1901840561478 73 0 72 2 10 2.232025923290446 20 2.76206241576646 40 1.1034765317954 50 44.6177154324492 51 96.63019658365178 73 0 97 1 330 4C7 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BBC 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 6 72 2 10 2.05576545700618 20 2.861012413940887 40 0.9548984716270655 50 274.0763809413058 51 308.9974179950865 73 1 72 2 10 2.583746606177169 20 2.208949913643178 40 0.1158814287879965 50 308.9974179950865 51 381.0025820049136 73 1 72 2 10 2.64643710148901 20 2.233017781588249 40 0.0487296568838581 50 21.00258200491355 51 88.99741799508618 73 1 72 2 10 2.643315164634613 20 2.054622849494738 40 0.2271519040571613 50 88.99741799508604 51 114.6269796357359 73 1 72 2 10 3.303260542295614 20 0.6149685670603082 40 1.810860322430921 50 114.6269796357358 51 129.7728051417874 73 1 72 2 10 3.496410384846758 20 1.664724034128341 40 1.394246852682927 50 165.7987430109054 51 169.9291703474848 73 1 97 1 330 4C8 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BFB 330 1F 100 AcDbEntity 8 HATCH-BLACK 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 8 72 2 10 2.10076671703864 20 3.325655213407455 40 0.0599397668605327 50 267.8793336511986 51 377.8793336511989 73 1 72 2 10 2.052741812238583 20 3.310162719091439 40 0.1104017214519507 50 17.87933365119892 51 43.7673166448306 73 1 72 2 10 2.103395451769339 20 3.340116557206334 40 0.0547683672910658 50 57.93744139888317 51 187.77563216475 73 1 72 2 10 2.068634698539837 20 3.335369986556996 40 0.0196850393700788 50 187.7756321647501 51 367.7756321647502 73 1 72 2 10 2.103395451769339 20 3.340116557206334 40 0.0153982885509082 50 172.2243678352504 51 287.334302618237 73 0 72 2 10 2.052741812238584 20 3.310162719091439 40 0.0710316427117921 50 321.0507208994834 51 342.1206663488011 73 0 72 2 10 2.100766717038639 20 3.325655213407456 40 0.0205696881203755 50 342.1206663488009 51 452.1206663488013 73 0 72 2 10 2.099277124665835 20 3.285428055915363 40 0.0196850393700787 50 87.8793336512005 51 267.8793336511979 73 1 97 1 330 235 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BFC 330 1F 100 AcDbEntity 8 HATCH-BLACK 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 8 72 2 10 1.921485017130019 20 3.343003198213819 40 0.0771903814552135 50 359.5978819190761 51 374.2374903606301 73 1 72 2 10 1.980044176928186 20 3.357861720825169 40 0.0167755580220592 50 14.23749036062933 51 155.7625096393687 73 1 72 2 10 2.003282808101446 20 3.34739958355454 40 0.0422606574936387 50 155.7625096393692 51 241.4329313324614 73 1 72 2 10 1.973661171909946 20 3.292995281984995 40 0.0196850393700789 50 298.5670686675385 51 478.5670686675385 73 0 72 2 10 2.003282808101446 20 3.34739958355454 40 0.0816307362337962 50 118.5670686675387 51 204.2374903606309 73 0 72 2 10 1.980044176928186 20 3.357861720825169 40 0.0561456367622165 50 204.2374903606306 51 345.7625096393699 73 0 72 2 10 1.921485017130019 20 3.34300319821382 40 0.1165604601953712 50 345.76250963937 51 360.4021180809241 73 0 72 2 10 2.018358052101874 20 3.342323304531541 40 0.0196850393700787 50 0.4021180809244088 51 180.4021180809231 73 0 97 1 330 267 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BFD 330 1F 100 AcDbEntity 8 HATCH-BLACK 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 2.278537892029333 20 3.728579428420916 40 0.0853095785363673 50 12.6821846844064 51 72.68218468440622 73 1 72 2 10 2.309791821489833 20 3.828814460633206 40 0.0196850393700787 50 107.3178153155941 51 287.3178153155944 73 0 72 2 10 2.278537892029333 20 3.728579428420916 40 0.1246796572765245 50 287.3178153155936 51 347.3178153155935 73 0 72 2 10 2.380970941004577 20 3.751630247646181 40 0.0196850393700789 50 347.3178153155935 51 527.3178153155935 73 0 97 1 330 451 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 BFE 330 1F 100 AcDbEntity 8 HATCH-BLACK 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 2.07909456474772 20 3.772298844618632 40 0.1175982774997528 50 111.5543469318192 51 141.5543469318192 73 1 72 2 10 1.971574507059384 20 3.857657770838914 40 0.0196850393700788 50 38.44565306818044 51 218.4456530681808 73 0 72 2 10 2.079094564747719 20 3.772298844618632 40 0.1569683562399099 50 218.4456530681809 51 248.4456530681809 73 0 72 2 10 2.028658926483394 20 3.899981872009325 40 0.0196850393700786 50 248.4456530681804 51 428.4456530681804 73 0 97 1 330 44F 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 C01 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 17 72 2 10 2.10536238485146 20 2.371962053549118 40 0.2723538322513761 50 159.7337422418206 51 175.1380365575864 73 1 72 2 10 2.043049297315996 20 2.110655210550977 40 0.352964946593263 50 233.6796832772765 51 244.1243120885548 73 0 72 2 10 1.928818024879453 20 2.346159501416084 40 0.0912187821164004 50 244.1243120885551 51 325.8756879114455 73 0 72 2 10 1.780100104900293 20 2.245377841414934 40 0.2708683374053446 50 325.8756879114452 51 354.1243120885547 73 0 72 2 10 1.486332025585371 20 2.215145842661859 40 0.5661879239094977 50 354.124312088555 51 380.265282453191 73 0 72 2 10 2.601728566753494 20 1.803316300498069 40 0.622808718578886 50 159.7347175468091 51 172.7742566190203 73 1 72 2 10 3.245154141910993 20 1.721739021653846 40 1.271385100503472 50 172.7742566190202 51 197.2257433809798 73 1 72 2 10 2.448387279831183 20 1.474706126417881 40 0.4372012575544668 50 197.2257433809797 51 229.6909739682446 73 1 72 2 10 1.84273355618451 20 1.606506575382588 40 0.5662349988373949 50 304.7588400511317 51 309.2074896477569 73 1 72 2 10 3.174161319020478 20 1.699913413586492 40 1.109452231228011 50 151.3367493281762 51 186.2319675330486 73 0 72 2 10 3.49641038484678 20 1.664724034128332 40 1.433616931423104 50 186.2319675330492 51 205.0988169699291 73 0 72 2 10 -37.1850685335689 20 20.72029698200291 40 43.48962412887072 50 334.901183030072 51 335.0988169699286 73 1 72 2 10 1.05207209728287 20 2.970247608757844 40 1.33344811187206 50 335.0988169699285 51 348.9886439523909 73 1 72 2 10 1.959203223948364 20 2.950701101027533 40 0.4655223034750759 50 30.33963089325502 51 49.03787718203768 73 0 72 2 10 1.804450685812644 20 3.128961400613438 40 0.701583910831935 50 49.03787718203728 51 65.26030603284518 73 0 72 2 10 1.924151714798596 20 2.869186907390315 40 0.4155574720721139 50 65.26030603284511 51 82.84890216530907 73 0 72 2 10 1.936208898089171 20 2.773084900679216 40 0.318702057340656 50 82.84890216530943 51 105.7184590811235 73 0 97 1 330 4F3 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 C20 330 1F 100 AcDbEntity 8 HATCH-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 3 92 1 93 17 72 2 10 1.885608931176688 20 3.176688874055116 40 0.2129975912966591 50 114.9006616575818 51 156.4878117659684 73 1 72 2 10 2.636203773812854 20 2.850131072655588 40 1.031552791296577 50 156.4878117659688 51 180.6082887577103 73 1 72 2 10 1.952094170360633 20 2.842867853274917 40 0.3474046319836055 50 180.6082887577101 51 213.6393369978933 73 1 72 2 10 1.964644164547905 20 2.851218474936612 40 0.3624789557242355 50 213.6393369978933 51 250.0019612921961 73 1 72 2 10 1.936208898089171 20 2.773084900679217 40 0.2793319786004991 50 250.001961292196 51 277.1510978346906 73 1 72 2 10 1.924151714798597 20 2.869186907390317 40 0.3761873933319576 50 277.1510978346908 51 294.7396939671547 73 1 72 2 10 1.804450685812644 20 3.128961400613437 40 0.6622138320917775 50 294.7396939671549 51 310.9621228179628 73 1 72 2 10 1.959203223948364 20 2.950701101027533 40 0.4261522247349184 50 310.9621228179625 51 357.7626023297964 73 1 72 2 10 0.9685713550985386 20 2.989404907072427 40 1.417539880590719 50 357.7626023297966 51 367.3820705420636 73 1 72 2 10 2.2125235694189 20 3.150570273791624 40 0.1631908912969642 50 7.382070542063584 51 53.5251061991567 73 1 72 2 10 1.924407631021267 20 3.452788946261674 40 0.4213817967382122 50 23.94086726929591 51 38.56090658709021 73 0 72 2 10 2.174464534980624 20 3.253450334179865 40 0.1015938396722196 50 38.56090658709 51 128.8844964337146 73 0 72 1 10 2.110688753100606 20 3.174368364648643 11 2.049360338450518 21 3.223826763560005 72 1 10 2.049360338450518 20 3.223826763560005 11 2.020698206844207 21 3.208114453397319 72 2 10 1.961644849992286 20 3.289054064709398 40 0.1001924130602254 50 53.88559445512062 51 115.5479523260344 73 0 72 2 10 2.0110372932182 20 3.39238482801838 40 0.2147212744613677 50 115.5479523260344 51 163.3991489022965 73 0 72 2 10 2.161160122792123 20 3.437140815427867 40 0.371373635976537 50 163.3991489022961 51 169.5663152899231 73 0 97 1 330 4C9 92 16 93 4 72 2 10 1.788320029910184 20 2.673441487468005 40 0.2481310319481923 50 339.5601350117603 51 365.5770490458945 73 1 72 2 10 2.015684652568724 20 2.695642836263502 40 0.0196850393700789 50 5.57704904589411 51 185.5770490458954 73 1 72 2 10 1.788320029910183 20 2.673441487468005 40 0.2087609532080352 50 354.4229509541054 51 380.4398649882396 73 0 72 2 10 2.002382887993199 20 2.593662641184479 40 0.0196850393700787 50 159.5601350117616 51 339.5601350117602 73 1 97 1 330 138 92 16 93 4 72 2 10 1.988631326711838 20 2.675424154108706 40 0.2917786076489145 50 176.6618056290539 51 192.1921376659049 73 0 72 2 10 1.722674860472906 20 2.732887777074972 40 0.0196850393700788 50 192.1921376659057 51 372.1921376659045 73 0 72 2 10 1.988631326711838 20 2.675424154108705 40 0.2524085289087564 50 167.807862334095 51 183.338194370946 73 1 72 2 10 1.716999440920682 20 2.659580274525414 40 0.0196850393700787 50 356.6618056290538 51 536.6618056290539 73 0 97 1 330 14E 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 C24 330 1F 100 AcDbEntity 8 HATCH-BLACK 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 1.788320029910184 20 2.673441487468005 40 0.2481310319481923 50 339.5601350117603 51 365.5770490458945 73 1 72 2 10 2.015684652568724 20 2.695642836263502 40 0.0196850393700789 50 5.57704904589411 51 185.5770490458954 73 1 72 2 10 1.788320029910183 20 2.673441487468005 40 0.2087609532080352 50 354.4229509541054 51 380.4398649882396 73 0 72 2 10 2.002382887993199 20 2.593662641184479 40 0.0196850393700787 50 159.5601350117616 51 339.5601350117602 73 1 97 1 330 138 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 C25 330 1F 100 AcDbEntity 8 HATCH-BLACK 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 4 72 2 10 1.988631326711838 20 2.675424154108706 40 0.2917786076489145 50 176.6618056290539 51 192.1921376659049 73 0 72 2 10 1.722674860472906 20 2.732887777074972 40 0.0196850393700788 50 192.1921376659057 51 372.1921376659045 73 0 72 2 10 1.988631326711838 20 2.675424154108705 40 0.2524085289087564 50 167.807862334095 51 183.338194370946 73 1 72 2 10 1.716999440920682 20 2.659580274525414 40 0.0196850393700787 50 356.6618056290538 51 536.6618056290539 73 0 97 1 330 14E 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 C28 330 1F 100 AcDbEntity 8 HATCH-BLACK 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 27 92 1 93 48 72 2 10 3.031233358735754 20 1.618783385319762 40 0.1683378964507315 50 268.8981266360797 51 328.3124434184161 73 0 72 2 10 2.805854019540958 20 1.479653877718506 40 0.4332017603907771 50 328.312443418416 51 355.7300930418278 73 0 72 2 10 2.720654010687053 20 1.47329265706769 40 0.5186389106058562 50 355.7300930418277 51 387.0857403971304 73 0 72 2 10 3.019270278182164 20 1.320576760853129 40 0.1832379264550515 50 27.08574039713041 51 62.91425960287025 73 0 72 2 10 2.617288604059704 20 2.106600155295556 40 1.066086748701018 50 62.91425960286999 51 83.90565057843106 73 0 72 2 10 2.527478440588518 20 2.94776010601788 40 1.912027602521132 50 83.90565057843116 51 95.51019307772863 73 0 72 2 10 2.411367250189849 20 1.266852136052576 40 0.2323033958896882 50 106.8886617051031 51 145.0036277051946 73 0 72 2 10 1.842733556184506 20 1.606506575382589 40 0.6056050775775568 50 51.33837874710574 51 83.82931909093898 73 0 72 2 10 1.867289566555309 20 1.379382243234547 40 0.3771571406224918 50 83.82931909093904 51 106.1706809090618 73 0 72 2 10 1.872170704325742 20 1.396215376152872 40 0.3946836881941034 50 106.1706809090621 51 118.8560326885956 73 0 72 2 10 1.542373482613905 20 1.83573967301926 40 0.7974660552058795 50 79.93869473201835 51 101.5302981560868 73 0 72 2 10 1.584035429735764 20 2.039961850738246 40 1.00589449786731 50 101.530298156087 51 115.9981291148674 73 0 72 2 10 1.03401257104743 20 0.477027467195177 40 0.6677997785619737 50 80.5975463145049 51 115.6894538187781 73 1 72 2 10 0.7359925636398887 20 1.096559104863404 40 0.0196850393700787 50 64.3105461812228 51 178.3982111381467 73 0 72 2 10 0.9476260308821786 20 1.102477175547731 40 0.2314012362413102 50 178.3982111381469 51 253.5469306045596 73 0 72 2 10 1.168606309785877 20 1.558605525778289 40 0.3700601913995847 50 140.7373098431768 51 182.1149161181871 73 0 72 2 10 1.060157361703604 20 1.562610439508386 40 0.2615373197358793 50 182.1149161181871 51 235.7398592611448 73 0 72 2 10 1.268369849054956 20 1.977371145189359 40 0.4071662414854006 50 150.8060111759436 51 152.0052969205898 73 0 72 2 10 1.065938622495786 20 1.869760556959495 40 0.1779099652672192 50 152.0052969205898 51 197.9947030794108 73 0 72 2 10 1.163637847655054 20 1.838026139816656 40 0.2806339246346285 50 197.9947030794104 51 242.0052969205895 73 0 72 2 10 1.134374454956794 20 1.893074853652674 40 0.2182904642942491 50 242.0052969205897 51 278.7513848946688 73 0 72 2 10 1.318324160529893 20 2.123002906229338 40 0.1514028023784197 50 174.626341759492 51 287.1653967341294 73 0 72 2 10 1.134452552508395 20 1.527737292608446 40 0.7744195910734504 50 287.1653967341294 51 311.2425077735102 73 0 72 2 10 -0.1012307034243847 20 3.010931950741654 40 1.964911005810923 50 332.7104062850323 51 333.8293190909388 73 1 72 2 10 4.316192387813981 20 0.8400973818280608 40 2.957095647231735 50 206.1706809090621 51 209.2027098803458 73 0 72 2 10 2.043049297315993 20 2.110655210550981 40 0.3529649465932583 50 209.2027098803451 51 225.0870679104569 73 0 72 2 10 2.105362384851456 20 2.371962053549119 40 0.3117239109915287 50 177.914487685338 51 200.1246558462194 73 0 72 2 10 1.964644164547905 20 2.851218474936612 40 0.4018490344643929 50 112.2213810159718 51 146.3606630021067 73 0 72 2 10 1.952094170360633 20 2.842867853274918 40 0.3867747107237632 50 146.3606630021067 51 179.3917112422899 73 0 72 2 10 2.636203773812854 20 2.850131072655586 40 1.070922870036734 50 179.3917112422899 51 203.5121882340314 73 0 72 2 10 1.885608931176689 20 3.176688874055116 40 0.2523676700368166 50 203.5121882340314 51 247.919074760323 73 0 72 2 10 2.161160122792124 20 3.437140815427865 40 0.3713736359765378 50 175.8934715069597 51 235.3701061614485 73 0 72 2 10 2.010334078755422 20 3.655531747894149 40 0.1059624550830902 50 235.3701061614487 51 321.8826468892163 73 0 72 2 10 1.984695044370156 20 3.635415634546031 40 0.1385510742689834 50 321.8826468892165 51 353.8787479269093 73 0 72 2 10 2.205371433700895 20 3.565115244906948 40 0.1187965099453075 50 225.7363985376375 51 338.2090024626373 73 0 72 2 10 1.924407631021267 20 3.452788946261673 40 0.4213817967382119 50 338.2090024626376 51 378.4288669894065 73 0 72 2 10 2.2125235694189 20 3.150570273791623 40 0.2025609700371219 50 303.4508923017655 51 352.6179294579363 73 0 72 2 10 0.968571355098534 20 2.989404907072428 40 1.456909959330881 50 352.6179294579365 51 362.2328550433406 73 0 72 2 10 1.052072097282865 20 2.970247608757846 40 1.372818190612224 50 1.569678067828868 51 24.90118303007151 73 0 72 2 10 -37.185068533585 20 20.72029698201224 40 43.52899420762941 50 24.90118303007369 51 25.09881696993027 73 0 72 2 10 3.496410384846288 20 1.664724034128535 40 1.394246852682421 50 154.9011830300731 51 163.0124653299814 73 1 72 2 10 3.303260542295614 20 0.6149685670603104 40 1.850230401171077 50 231.9548675004806 51 245.3730203642641 73 0 72 2 10 2.643315164634613 20 2.054622849494737 40 0.2665219827973205 50 245.373020364264 51 271.0025820049138 73 0 72 2 10 2.646437101489009 20 2.233017781588249 40 0.0880997356240162 50 271.0025820049141 51 338.9974179950867 73 0 72 2 10 2.583746606177169 20 2.208949913643178 40 0.1552515075281532 50 338.9974179950864 51 373.3205824975591 73 0 72 2 10 2.833454996760046 20 2.010774243926277 40 0.1900112320680552 50 238.728482917094 51 295.0 73 0 72 2 10 2.807174025728471 20 1.954414519671351 40 0.2521973073297553 50 294.9999999999998 51 365.0000000000006 73 0 72 2 10 2.435514026542535 20 1.986930556286176 40 0.6252769873339419 50 5.000000000000452 51 18.63891789885247 73 0 97 1 330 8B3 92 16 93 5 72 2 10 2.506661351932912 20 2.343882490801413 40 1.137317969685161 50 295.2104838476032 51 307.4903876208237 73 1 72 2 10 2.72065401068705 20 1.473292657067691 40 0.4792688318657009 50 3.806985506611603 51 27.08574039713036 73 0 72 2 10 3.019270278182163 20 1.32057676085313 40 0.1438678477148946 50 27.08574039713062 51 62.91425960287042 73 0 72 2 10 2.617288604059699 20 2.106600155295566 40 1.026716669960872 50 62.91425960286999 51 74.08618998756283 73 0 72 2 10 2.502316662315185 20 1.425846770903515 40 0.5012141309808816 50 322.28430360547 51 347.21072780023 73 1 97 1 330 4AD 92 0 93 4 72 2 10 2.35834385692291 20 2.560871504972433 40 1.017884167165215 50 264.8798691909198 51 277.0962125668474 73 1 72 2 10 2.157099264484859 20 1.761255447038774 40 0.3888707645596128 50 327.2321171951457 51 344.8146293833702 73 1 72 2 10 2.232025923290449 20 2.762062415766465 40 1.14284661053556 50 74.76238100741742 51 87.73997032522614 73 0 72 2 10 1.875100795739506 20 1.635718008880588 40 0.4022960678253824 50 2.224226079808037 51 12.73296995122379 73 0 97 1 330 4C1 92 16 93 6 72 2 10 2.506661351932914 20 2.343882490801411 40 1.097947890945 50 252.9025993502986 51 309.129589783908 73 1 72 2 10 2.720654010687031 20 1.473292657067699 40 0.4792688318657188 50 2.258737765182703 51 4.269906958171121 73 1 72 2 10 2.805854019540959 20 1.479653877718507 40 0.3938316816506187 50 4.26990695817209 51 31.68755658158391 73 1 72 2 10 3.031233358735755 20 1.618783385319762 40 0.1289678177105734 50 31.68755658158397 51 88.75077942665364 73 1 72 2 10 2.358343856922911 20 2.560871504972435 40 1.057254245905374 50 50.27455552545634 51 103.1717867618754 73 0 72 2 10 3.174161319020478 20 1.699913413586489 40 1.070082152487853 50 189.0587348045097 51 202.2656996106713 73 1 97 1 330 4B5 92 16 93 5 72 2 10 2.202541654133554 20 1.362543685931673 40 0.5298157619216942 50 14.96903515149527 51 32.33949759932654 73 0 72 2 10 2.527478440588518 20 2.947760106017868 40 1.872657523780963 50 273.7568474686516 51 276.0943494215687 73 1 72 2 10 2.617288604059703 20 2.10660015529557 40 1.026716669960875 50 276.0943494215687 51 282.0831632762506 73 1 72 2 10 2.502316662315184 20 1.425846770903515 40 0.4618440522407246 50 315.5859663701619 51 343.4723636742463 73 1 72 2 10 2.506661351932922 20 2.3438824908014 40 1.137317969685146 50 67.32624731613089 51 79.47656760874074 73 0 97 1 330 4B9 92 16 93 4 72 2 10 2.05395636253349 20 1.311094011306242 40 0.40360054374194 50 325.1586938734879 51 345.2415144983743 73 1 72 2 10 2.506661351932912 20 2.343882490801414 40 1.137317969685161 50 266.8538285473494 51 278.3272010683704 73 1 72 2 10 2.202541654133556 20 1.362543685931675 40 0.4904456831815359 50 17.0728403884595 51 35.67171941040231 73 0 72 2 10 2.527478440588521 20 2.947760106017855 40 1.87265752378095 50 87.75100742187989 51 94.35714735717728 73 0 97 1 330 4BA 92 16 93 4 72 2 10 2.506661351932914 20 2.343882490801417 40 1.137317969685164 50 254.5896536710559 51 264.8320604814776 73 1 72 2 10 2.053956362533489 20 1.311094011306244 40 0.3642304650017842 50 15.91994768566973 51 37.94378452603665 73 0 72 2 10 2.41136725018985 20 1.266852136052575 40 0.1929333171495304 50 111.3287610035634 51 150.8157377309437 73 0 72 2 10 3.174161319020494 20 1.699913413586516 40 1.070082152487879 50 150.4873427015391 51 154.9868167954895 73 0 97 1 330 4BC 92 0 93 4 72 2 10 2.358343856922912 20 2.56087150497244 40 1.017884167165223 50 255.9706947110459 51 262.6477274601202 73 1 72 2 10 1.875100795739507 20 1.635718008880588 40 0.3629259890852237 50 346.5587102880505 51 357.396057379031 73 1 72 2 10 2.23202592329045 20 2.762062415766459 40 1.142846610535554 50 89.71793740532951 51 96.29947398788597 73 0 72 2 10 3.174161319020505 20 1.699913413586497 40 1.070082152487882 50 183.9544802865682 51 186.7925864334441 73 1 97 1 330 4C0 92 16 93 4 72 2 10 2.157099264484858 20 1.761255447038777 40 0.4282408432997721 50 12.00230574940428 51 28.29091643485702 73 0 72 2 10 2.358343856922911 20 2.560871504972434 40 1.017884167165216 50 279.9480036533407 51 296.005896865796 73 1 72 2 10 2.43480848147727 20 1.74176023846554 40 0.3820244196138822 50 345.4907424301736 51 365.6076870699981 73 1 72 2 10 2.232025923290445 20 2.762062415766465 40 1.142846610535562 50 59.32877074017064 51 72.48465458233305 73 0 97 1 330 4C3 92 16 93 7 72 2 10 3.174161319020492 20 1.69991341358649 40 1.070082152487867 50 178.182030269148 51 186.2319675330486 73 0 72 2 10 3.496410384846752 20 1.66472403412841 40 1.394246852682911 50 186.2319675330462 51 188.4100158185151 73 0 72 2 10 2.05576545700618 20 2.861012413940887 40 0.994268550367224 50 273.5399568619239 51 308.9576328012706 73 1 72 1 10 2.680907394207461 20 2.087858154687554 11 2.747050780866419 21 2.134172252628876 72 2 10 2.833454996760046 20 2.010774243926277 40 0.1506411533278984 50 235.0000000000002 51 295.0 73 0 72 2 10 2.807174025728471 20 1.954414519671351 40 0.2128272285895981 50 294.9999999999998 51 351.1901840561478 73 0 72 2 10 2.232025923290446 20 2.76206241576646 40 1.1034765317954 50 44.6177154324492 51 96.63019658365178 73 0 97 1 330 4C7 92 16 93 6 72 2 10 2.05576545700618 20 2.861012413940887 40 0.9548984716270655 50 274.0763809413058 51 308.9974179950865 73 1 72 2 10 2.583746606177169 20 2.208949913643178 40 0.1158814287879965 50 308.9974179950865 51 381.0025820049136 73 1 72 2 10 2.64643710148901 20 2.233017781588249 40 0.0487296568838581 50 21.00258200491355 51 88.99741799508618 73 1 72 2 10 2.643315164634613 20 2.054622849494738 40 0.2271519040571613 50 88.99741799508604 51 114.6269796357359 73 1 72 2 10 3.303260542295614 20 0.6149685670603082 40 1.810860322430921 50 114.6269796357358 51 129.7728051417874 73 1 72 2 10 3.496410384846758 20 1.664724034128341 40 1.394246852682927 50 165.7987430109054 51 169.9291703474848 73 1 97 1 330 4C8 92 16 93 4 72 2 10 1.034012571047431 20 0.4770274671951757 40 0.7071698573021327 50 88.2250617963899 51 113.037640194644 73 1 72 2 10 0.9476260308821789 20 1.102477175547732 40 0.1920311575011529 50 187.577294301379 51 259.5173177193701 73 0 72 2 10 1.168606309785881 20 1.558605525778299 40 0.3700601913995948 50 226.2464306309096 51 229.2045371712558 73 1 72 2 10 1.584035429735768 20 2.03996185073825 40 1.005894497867316 50 229.2045371712552 51 238.3301051192357 73 1 97 1 330 4E7 92 16 93 4 72 2 10 1.365920530767478 20 1.285919869338796 40 0.3113711740675595 50 169.2458500319289 51 182.205842988757 73 0 72 2 10 1.454717916970979 20 2.022108206218515 40 0.827297613601817 50 241.09054843511 51 254.5550649161042 73 1 72 2 10 1.606711922375474 20 1.348933253591385 40 0.3924976718251174 50 198.4545948543501 51 215.6989500329358 73 1 72 2 10 1.584035429735761 20 2.039961850738243 40 0.9665244191271488 50 107.8377726397921 51 122.8312626374707 73 0 97 1 330 4EB 92 0 93 4 72 2 10 1.454717916970981 20 2.022108206218515 40 0.8272976136018175 50 223.615566083045 51 238.0440774153107 73 1 72 2 10 1.365920530767478 20 1.285919869338796 40 0.3507412528077177 50 174.3939645983117 51 184.6071947080589 73 1 72 2 10 1.584035429735767 20 2.039961850738251 40 0.9665244191271588 50 125.9717238731088 51 130.7954628287447 73 0 72 2 10 1.168606309785878 20 1.558605525778289 40 0.3306901126594289 50 130.7954628287448 51 161.0882096390424 73 0 97 1 330 4F0 92 0 93 4 72 2 10 1.448830865211245 20 2.213371853903018 40 0.5803064835681306 50 252.3365152710513 51 268.8118268997819 73 1 72 2 10 2.244252791706375 20 1.579066020312691 40 0.8092671391653076 50 176.1651718242215 51 179.7775214345853 73 1 72 2 10 1.382209127764961 20 2.180776385554781 40 0.6008907212088166 50 84.96060718028212 51 99.52487731460255 73 0 72 2 10 1.754426611671092 20 1.690434343062297 40 0.4826097226376628 50 167.7663152513758 51 176.4348368363554 73 0 97 1 330 620 92 16 93 6 72 2 10 1.268369849054951 20 1.97737114518936 40 0.4071662414853972 50 214.7414744545867 51 240.7656835685936 73 1 72 2 10 1.382209127764962 20 2.180776385554782 40 0.6402607999489762 50 240.7656835685933 51 274.8013992041994 73 1 72 2 10 2.244252791706376 20 1.579066020312693 40 0.8092671391653085 50 182.5711456908801 51 205.0661840751609 73 1 72 2 10 1.454717916970982 20 2.022108206218515 40 0.78792753486166 50 85.88902674875129 51 141.3773954764613 73 0 72 2 10 1.168606309785876 20 1.558605525778289 40 0.3306901126594269 50 175.0885918849935 51 182.1149161181871 73 0 72 2 10 1.060157361703603 20 1.562610439508386 40 0.2221672409957212 50 182.1149161181872 51 235.3333452342021 73 0 97 1 330 4EE 92 16 93 11 72 2 10 1.735391678484751 20 1.622446814297793 40 0.3637008069698632 50 46.50828210019076 51 127.3801843342055 73 0 72 2 10 2.244252791706377 20 1.579066020312692 40 0.7698970604251519 50 198.604632170139 51 206.170680909061 73 1 72 2 10 1.87217070432574 20 1.396215376152875 40 0.3553136094539483 50 206.170680909061 51 220.7958011940912 73 1 72 2 10 1.754854449164134 20 1.637701886096329 40 0.4973281664865742 50 252.2434918237404 51 291.0055844420299 73 1 72 2 10 1.940182455435743 20 1.155046537921708 40 0.0196850393700786 50 248.9944155579697 51 428.9944155579707 73 0 72 2 10 1.754854449164133 20 1.637701886096329 40 0.5366982452267322 50 68.99441555797011 51 99.84027979757452 73 0 72 2 10 1.872170704325739 20 1.396215376152874 40 0.3553136094539469 50 233.9619057741986 51 253.8293190909382 73 1 72 2 10 1.867289566555308 20 1.379382243234548 40 0.3377870618823355 50 253.8293190909384 51 276.1706809090611 73 1 72 2 10 1.842733556184505 20 1.606506575382589 40 0.5662349988373994 50 276.170680909061 51 300.6079669543535 73 1 72 2 10 2.448387279831183 20 1.47470612641788 40 0.4765713362946238 50 131.7514141291648 51 162.7742566190203 73 0 72 2 10 3.245154141911026 20 1.721739021653879 40 1.31075517924367 50 162.7742566190193 51 163.9156492780123 73 0 97 1 330 4F4 92 16 93 36 72 2 10 2.043049297315998 20 2.110655210550977 40 0.3135948678531067 50 140.7856547310828 51 150.7972901196548 73 1 72 2 10 4.316192387813921 20 0.8400973818280717 40 2.91772556849152 50 150.7972901196538 51 151.5606552199046 73 1 72 2 10 1.82896029060598 20 2.312110103765454 40 0.1138088004365485 50 226.4676036039469 51 253.8346334294888 73 1 72 2 10 1.791794192050712 20 2.183894323205893 40 0.0196850393700787 50 286.1653665705111 51 466.1653665705111 73 0 72 2 10 1.82896029060598 20 2.312110103765454 40 0.153178879176706 50 106.1653665705111 51 129.487348884315 73 0 72 2 10 4.31619238781396 20 0.8400973818280881 40 2.917725568491546 50 152.3551430085055 51 153.8293190909382 73 1 72 2 10 -0.1012307034243785 20 3.010931950741638 40 2.004281084551068 50 26.17068090906094 51 27.44285015917365 73 0 72 2 10 1.869973878918131 20 2.229032723885394 40 0.2390599525801008 50 216.3816426472188 51 279.0739534633693 73 1 72 2 10 1.910780338072042 20 1.973525769477851 40 0.0196850393700789 50 260.9260465366305 51 440.9260465366307 73 0 72 2 10 1.869973878918132 20 2.229032723885395 40 0.278430031320259 50 80.92604653663092 51 139.8013610445865 73 0 72 2 10 -0.101230703424352 20 3.01093195074165 40 2.004281084551049 50 28.67087156360686 51 33.18792433993601 73 0 72 2 10 1.813793246529746 20 2.127914574971419 40 0.3198926968250738 50 222.0119914468626 51 273.6941141002521 73 1 72 2 10 1.835672170020508 20 1.78904239903142 40 0.0196850393700788 50 266.3058858997472 51 446.3058858997478 73 0 72 2 10 1.813793246529746 20 2.127914574971419 40 0.3592627755652315 50 86.30588589974785 51 136.3371185375852 73 0 72 2 10 1.995105659775399 20 1.606003070595645 40 0.5192979821599312 50 148.1708625321174 51 171.6429565217715 73 1 72 2 10 1.774379750743404 20 1.9596864265737 40 0.4040824222682091 50 223.5109336967462 51 281.1199173397384 73 1 72 2 10 1.85610884645455 20 1.543874911031386 40 0.0196850393700787 50 258.8800826602615 51 438.8800826602615 73 0 72 2 10 1.774379750743404 20 1.9596864265737 40 0.4434525010083663 50 78.88008266026162 51 132.2628434475095 73 0 72 2 10 2.244252791706375 20 1.579066020312694 40 0.7698970604251502 50 176.0947114644605 51 193.0143530481955 73 1 72 2 10 1.735391678484751 20 1.622446814297793 40 0.3243307282297058 50 221.9378076910892 51 317.3250616801697 73 1 72 2 10 3.245154141910992 20 1.721739021653846 40 1.310755179243628 50 165.9082787983328 51 187.2257433809798 73 0 72 2 10 2.601728566753492 20 1.803316300498068 40 0.6621787973190414 50 187.2257433809798 51 200.265282453191 73 0 72 2 10 1.486332025585369 20 2.215145842661859 40 0.5268178451693419 50 339.734717546809 51 365.875687911445 73 1 72 2 10 1.780100104900293 20 2.245377841414935 40 0.231498258665186 50 5.875687911445098 51 34.12431208855465 73 1 72 2 10 1.928818024879454 20 2.346159501416084 40 0.0518487033762426 50 34.12431208855484 51 115.8756879114452 73 1 72 2 10 2.043049297315996 20 2.110655210550977 40 0.3135948678531048 50 115.8756879114451 51 131.7156800642676 73 1 72 2 10 2.105362384851459 20 2.371962053549119 40 0.2723538322513749 50 185.7363493931126 51 196.6535421822968 73 1 72 2 10 2.224366300494004 20 2.407559786221583 40 0.3965678834278744 50 196.6535421822967 51 214.2452636527788 73 1 72 2 10 1.775114796299714 20 2.101729675474409 40 0.1469014999420266 50 325.7547363472213 51 394.2452636527789 73 0 72 2 10 1.880276536811822 20 2.030140317515856 40 0.0196850393700786 50 34.24526365277875 51 214.2452636527787 73 0 72 2 10 1.775114796299714 20 2.101729675474409 40 0.1075314212018693 50 325.7547363472211 51 383.6864830926802 73 1 72 2 10 1.724258670730545 20 2.179559731729328 40 0.1532919477378671 50 13.05681211459937 51 58.88974415557702 73 0 72 2 10 1.793291568736173 20 2.065168888754275 40 0.0196850393700787 50 58.88974415557702 51 238.8897441555765 73 0 72 2 10 1.724258670730541 20 2.179559731729329 40 0.1139218689977123 50 301.1102558444241 51 381.2576330469557 73 1 72 2 10 2.224366300494005 20 2.407559786221586 40 0.435937962168034 50 154.6425959514791 51 163.3464578177032 73 0 72 2 10 2.105362384851463 20 2.371962053549115 40 0.3117239109915352 50 163.3464578177044 51 168.3316806257954 73 0 97 1 330 4F7 92 16 93 7 72 2 10 1.995105659775398 20 1.606003070595649 40 0.5586680609000869 50 153.1774302023765 51 173.1639087815069 73 1 72 2 10 1.448830865211247 20 2.213371853903018 40 0.5409364048279738 50 90.89204265530425 51 153.6751728635248 73 0 72 2 10 1.163637847655053 20 1.838026139816656 40 0.2412638458944706 50 214.15747754694 51 242.0052969205898 73 0 72 2 10 1.134374454956795 20 1.893074853652674 40 0.1789203855540918 50 242.0052969205894 51 284.046994134434 73 0 72 2 10 1.318324160529892 20 2.123002906229338 40 0.1514028023784195 50 201.853727881165 51 212.2168526331622 73 1 72 2 10 1.492137893232153 20 2.232530667257897 40 0.3568475494804613 50 212.2168526331617 51 237.7831473668378 73 1 72 2 10 1.573128668857933 20 2.361057982102735 40 0.5087645544459671 50 237.7831473668379 51 261.3425166986952 73 1 97 1 330 505 92 16 93 5 72 2 10 1.75442661167109 20 1.690434343062299 40 0.5219798013778194 50 181.7138221824677 51 190.3415069086127 73 1 72 2 10 1.382209127764958 20 2.180776385554784 40 0.6008907212088186 50 103.5988396513469 51 119.2343164314062 73 0 72 2 10 1.26836984905495 20 1.977371145189357 40 0.3677961627452375 50 119.2343164314065 51 126.2926725539458 73 0 72 2 10 1.365613936631298 20 1.696475315724717 40 0.3153299658786926 50 177.17352188641 51 195.5421431149888 73 0 72 2 10 1.448830865211245 20 2.213371853903018 40 0.5803064835681301 50 228.1704174204192 51 248.1315658423051 73 1 97 1 330 507 92 16 93 5 72 2 10 1.365613936631296 20 1.696475315724716 40 0.3547000446188475 50 161.0626247765776 51 177.1237827075663 73 1 72 2 10 1.26836984905495 20 1.977371145189359 40 0.3677961627452389 50 134.3293201388803 51 152.0052969205894 73 0 72 2 10 1.065938622495786 20 1.869760556959495 40 0.1385398865270621 50 152.0052969205897 51 197.9947030794107 73 0 72 2 10 1.163637847655055 20 1.838026139816656 40 0.2412638458944715 50 197.9947030794104 51 202.8905358909278 73 0 72 2 10 1.448830865211249 20 2.213371853903019 40 0.5803064835681331 50 209.0183706588869 51 223.8176444671686 73 1 97 1 330 509 92 16 93 6 72 2 10 1.573128668857933 20 2.361057982102735 40 0.4693944757058101 50 96.86618894004766 51 122.2168526331621 73 0 72 2 10 1.492137893232154 20 2.232530667257898 40 0.3174774707403054 50 122.2168526331621 51 147.7831473668382 73 0 72 2 10 1.318324160529893 20 2.123002906229338 40 0.1120327236382623 50 147.783147366838 51 287.1653967341294 73 0 72 2 10 1.134452552508394 20 1.527737292608446 40 0.7350495123332927 50 287.1653967341295 51 311.9725813008354 73 0 72 2 10 -0.1012307034243558 20 3.010931950741639 40 1.964911005810889 50 28.47135626072658 51 33.82931909093841 73 0 72 2 10 1.9951056597754 20 1.606003070595648 40 0.5586680609000885 50 146.1706809090616 51 148.8453401595469 73 1 97 1 330 50B 92 16 93 4 72 2 10 2.434808481477273 20 1.741760238465535 40 0.4213944983540373 50 350.138398092684 51 368.2079411900966 73 1 72 2 10 2.232025923290449 20 2.76206241576646 40 1.142846610535555 50 302.8460023643591 51 313.5174616433824 73 1 72 2 10 2.435514026542539 20 1.986930556286178 40 0.5859069085937808 50 5.250840664227033 51 24.12657987446927 73 0 72 2 10 2.358343856922903 20 2.560871504972432 40 1.017884167165218 50 53.04812421612736 51 61.11882105703474 73 0 97 1 330 510 92 16 93 5 72 2 10 1.606711922375474 20 1.348933253591385 40 0.3531275930849602 50 135.3746912145926 51 157.4176362906217 73 0 72 2 10 1.454717916970981 20 2.022108206218514 40 0.827297613601817 50 257.8545362072944 51 275.2691677284761 73 1 72 2 10 1.872170704325741 20 1.396215376152876 40 0.3946836881941063 50 210.0950891144055 51 232.5295145799341 73 1 72 2 10 1.542373482613905 20 1.835739673019258 40 0.75809597646572 50 83.20542127045559 51 101.5302981560868 73 0 72 2 10 1.584035429735767 20 2.039961850738253 40 0.9665244191271609 50 101.5302981560871 51 103.684145503982 73 0 97 1 330 559 92 16 93 17 72 2 10 2.10536238485146 20 2.371962053549118 40 0.2723538322513761 50 159.7337422418206 51 175.1380365575864 73 1 72 2 10 2.043049297315996 20 2.110655210550977 40 0.352964946593263 50 233.6796832772765 51 244.1243120885548 73 0 72 2 10 1.928818024879453 20 2.346159501416084 40 0.0912187821164004 50 244.1243120885551 51 325.8756879114455 73 0 72 2 10 1.780100104900293 20 2.245377841414934 40 0.2708683374053446 50 325.8756879114452 51 354.1243120885547 73 0 72 2 10 1.486332025585371 20 2.215145842661859 40 0.5661879239094977 50 354.124312088555 51 380.265282453191 73 0 72 2 10 2.601728566753494 20 1.803316300498069 40 0.622808718578886 50 159.7347175468091 51 172.7742566190203 73 1 72 2 10 3.245154141910993 20 1.721739021653846 40 1.271385100503472 50 172.7742566190202 51 197.2257433809798 73 1 72 2 10 2.448387279831183 20 1.474706126417881 40 0.4372012575544668 50 197.2257433809797 51 229.6909739682446 73 1 72 2 10 1.84273355618451 20 1.606506575382588 40 0.5662349988373949 50 304.7588400511317 51 309.2074896477569 73 1 72 2 10 3.174161319020478 20 1.699913413586492 40 1.109452231228011 50 151.3367493281762 51 186.2319675330486 73 0 72 2 10 3.49641038484678 20 1.664724034128332 40 1.433616931423104 50 186.2319675330492 51 205.0988169699291 73 0 72 2 10 -37.1850685335689 20 20.72029698200291 40 43.48962412887072 50 334.901183030072 51 335.0988169699286 73 1 72 2 10 1.05207209728287 20 2.970247608757844 40 1.33344811187206 50 335.0988169699285 51 348.9886439523909 73 1 72 2 10 1.959203223948364 20 2.950701101027533 40 0.4655223034750759 50 30.33963089325502 51 49.03787718203768 73 0 72 2 10 1.804450685812644 20 3.128961400613438 40 0.701583910831935 50 49.03787718203728 51 65.26030603284518 73 0 72 2 10 1.924151714798596 20 2.869186907390315 40 0.4155574720721139 50 65.26030603284511 51 82.84890216530907 73 0 72 2 10 1.936208898089171 20 2.773084900679216 40 0.318702057340656 50 82.84890216530943 51 105.7184590811235 73 0 97 1 330 4F3 92 16 93 17 72 2 10 1.885608931176688 20 3.176688874055116 40 0.2129975912966591 50 114.9006616575818 51 156.4878117659684 73 1 72 2 10 2.636203773812854 20 2.850131072655588 40 1.031552791296577 50 156.4878117659688 51 180.6082887577103 73 1 72 2 10 1.952094170360633 20 2.842867853274917 40 0.3474046319836055 50 180.6082887577101 51 213.6393369978933 73 1 72 2 10 1.964644164547905 20 2.851218474936612 40 0.3624789557242355 50 213.6393369978933 51 250.0019612921961 73 1 72 2 10 1.936208898089171 20 2.773084900679217 40 0.2793319786004991 50 250.001961292196 51 277.1510978346906 73 1 72 2 10 1.924151714798597 20 2.869186907390317 40 0.3761873933319576 50 277.1510978346908 51 294.7396939671547 73 1 72 2 10 1.804450685812644 20 3.128961400613437 40 0.6622138320917775 50 294.7396939671549 51 310.9621228179628 73 1 72 2 10 1.959203223948364 20 2.950701101027533 40 0.4261522247349184 50 310.9621228179625 51 357.7626023297964 73 1 72 2 10 0.9685713550985386 20 2.989404907072427 40 1.417539880590719 50 357.7626023297966 51 367.3820705420636 73 1 72 2 10 2.2125235694189 20 3.150570273791624 40 0.1631908912969642 50 7.382070542063584 51 53.5251061991567 73 1 72 2 10 1.924407631021267 20 3.452788946261674 40 0.4213817967382122 50 23.94086726929591 51 38.56090658709021 73 0 72 2 10 2.174464534980624 20 3.253450334179865 40 0.1015938396722196 50 38.56090658709 51 128.8844964337146 73 0 72 1 10 2.110688753100606 20 3.174368364648643 11 2.049360338450518 21 3.223826763560005 72 1 10 2.049360338450518 20 3.223826763560005 11 2.020698206844207 21 3.208114453397319 72 2 10 1.961644849992286 20 3.289054064709398 40 0.1001924130602254 50 53.88559445512062 51 115.5479523260344 73 0 72 2 10 2.0110372932182 20 3.39238482801838 40 0.2147212744613677 50 115.5479523260344 51 163.3991489022965 73 0 72 2 10 2.161160122792123 20 3.437140815427867 40 0.371373635976537 50 163.3991489022961 51 169.5663152899231 73 0 97 1 330 4C9 92 16 93 13 72 1 10 2.053553115266256 20 3.271022854778554 11 2.135403416533275 21 3.205014547305152 72 2 10 2.174464534980624 20 3.253450334179865 40 0.0622237609320623 50 231.1155035662852 51 321.4390934129098 73 1 72 2 10 1.924407631021268 20 3.452788946261673 40 0.3820117179980535 50 321.4390934129098 51 381.7909975373624 73 1 72 2 10 2.205371433700895 20 3.565115244906947 40 0.0794264312051501 50 21.79099753736259 51 138.4608414339663 73 1 72 2 10 2.359201923855247 20 3.432035664951207 40 0.2828284405938025 50 138.9469336075647 51 155.609089205736 73 1 72 2 10 2.083688019187524 20 3.556961618598168 40 0.0196850393700788 50 24.39091079426373 51 197.0763607466141 73 0 72 1 10 2.064870809553132 20 3.562742050811843 11 2.082872800905891 21 3.621344458486482 72 2 10 1.984695044370157 20 3.635415634546031 40 0.099180995528825 50 351.8437155425206 51 398.1173531107838 73 1 72 2 10 2.010334078755422 20 3.655531747894149 40 0.066592376342933 50 38.11735311078365 51 124.6298938385513 73 1 72 2 10 2.161160122792124 20 3.437140815427865 40 0.3320035572363805 50 124.6298938385515 51 196.6008510977037 73 1 72 2 10 2.011037293218199 20 3.39238482801838 40 0.1753511957212102 50 196.6008510977036 51 244.4520476739657 73 1 72 2 10 1.961644849992285 20 3.289054064709398 40 0.0608223343200681 50 244.4520476739658 51 308.2116001220994 73 1 72 1 10 1.999267568517967 20 3.241264030153233 11 2.053553115266256 21 3.271022854778554 97 1 330 4CB 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 C40 330 1F 100 AcDbEntity 8 HATCH-WHITE 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 3 92 1 93 13 72 1 10 2.053553115266256 20 3.271022854778554 11 2.135403416533275 21 3.205014547305152 72 2 10 2.174464534980624 20 3.253450334179865 40 0.0622237609320623 50 231.1155035662852 51 321.4390934129098 73 1 72 2 10 1.924407631021268 20 3.452788946261673 40 0.3820117179980535 50 321.4390934129098 51 381.7909975373624 73 1 72 2 10 2.205371433700895 20 3.565115244906947 40 0.0794264312051501 50 21.79099753736259 51 138.4608414339663 73 1 72 2 10 2.359201923855247 20 3.432035664951207 40 0.2828284405938025 50 138.9469336075647 51 155.609089205736 73 1 72 2 10 2.083688019187524 20 3.556961618598168 40 0.0196850393700788 50 24.39091079426373 51 197.0763607466141 73 0 72 1 10 2.064870809553132 20 3.562742050811843 11 2.082872800905891 21 3.621344458486482 72 2 10 1.984695044370157 20 3.635415634546031 40 0.099180995528825 50 351.8437155425206 51 398.1173531107838 73 1 72 2 10 2.010334078755422 20 3.655531747894149 40 0.066592376342933 50 38.11735311078365 51 124.6298938385513 73 1 72 2 10 2.161160122792124 20 3.437140815427865 40 0.3320035572363805 50 124.6298938385515 51 196.6008510977037 73 1 72 2 10 2.011037293218199 20 3.39238482801838 40 0.1753511957212102 50 196.6008510977036 51 244.4520476739657 73 1 72 2 10 1.961644849992285 20 3.289054064709398 40 0.0608223343200681 50 244.4520476739658 51 308.2116001220994 73 1 72 1 10 1.999267568517967 20 3.241264030153233 11 2.053553115266256 21 3.271022854778554 97 1 330 4CB 92 16 93 8 72 2 10 2.10076671703864 20 3.325655213407455 40 0.0599397668605327 50 267.8793336511986 51 377.8793336511989 73 1 72 2 10 2.052741812238583 20 3.310162719091439 40 0.1104017214519507 50 17.87933365119892 51 43.7673166448306 73 1 72 2 10 2.103395451769339 20 3.340116557206334 40 0.0547683672910658 50 57.93744139888317 51 187.77563216475 73 1 72 2 10 2.068634698539837 20 3.335369986556996 40 0.0196850393700788 50 187.7756321647501 51 367.7756321647502 73 1 72 2 10 2.103395451769339 20 3.340116557206334 40 0.0153982885509082 50 172.2243678352504 51 287.334302618237 73 0 72 2 10 2.052741812238584 20 3.310162719091439 40 0.0710316427117921 50 321.0507208994834 51 342.1206663488011 73 0 72 2 10 2.100766717038639 20 3.325655213407456 40 0.0205696881203755 50 342.1206663488009 51 452.1206663488013 73 0 72 2 10 2.099277124665835 20 3.285428055915363 40 0.0196850393700787 50 87.8793336512005 51 267.8793336511979 73 1 97 1 330 235 92 16 93 8 72 2 10 1.921485017130019 20 3.343003198213819 40 0.0771903814552135 50 359.5978819190761 51 374.2374903606301 73 1 72 2 10 1.980044176928186 20 3.357861720825169 40 0.0167755580220592 50 14.23749036062933 51 155.7625096393687 73 1 72 2 10 2.003282808101446 20 3.34739958355454 40 0.0422606574936387 50 155.7625096393692 51 241.4329313324614 73 1 72 2 10 1.973661171909946 20 3.292995281984995 40 0.0196850393700789 50 298.5670686675385 51 478.5670686675385 73 0 72 2 10 2.003282808101446 20 3.34739958355454 40 0.0816307362337962 50 118.5670686675387 51 204.2374903606309 73 0 72 2 10 1.980044176928186 20 3.357861720825169 40 0.0561456367622165 50 204.2374903606306 51 345.7625096393699 73 0 72 2 10 1.921485017130019 20 3.34300319821382 40 0.1165604601953712 50 345.76250963937 51 360.4021180809241 73 0 72 2 10 2.018358052101874 20 3.342323304531541 40 0.0196850393700787 50 0.4021180809244088 51 180.4021180809231 73 0 97 1 330 267 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 LWPOLYLINE 5 CB7 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 2 70 0 43 0.0 10 1.999999999999999 20 0.5021900451212454 10 1.999999999999998 20 0.2137188753069325 0 LWPOLYLINE 5 129E 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.699999999999999 20 0.4263456413348424 10 1.590116389297469 20 0.3629043091162095 10 1.590116389297469 20 0.2153520942475884 0 LWPOLYLINE 5 12B7 102 {ACAD_REACTORS 330 1B2B 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 68 70 1 43 0.0 10 0.211518030839291 20 1.132195865069596 10 0.2115180308392921 20 0.8856214579511849 10 0.3800563547419098 20 0.8242785247175163 10 0.4819904717841743 20 0.8831302146314739 42 -0.9999999999999999 10 0.501675511154253 20 0.8490347262935038 10 0.4283509058011884 20 0.8067007456546893 10 0.4606008219772955 20 0.7949627361090064 10 0.56253493901956 20 0.8538144260229641 42 -0.9999999999999999 10 0.5822199783896387 20 0.8197189376849939 10 0.5088953730365742 20 0.7773849570461795 10 0.5411452892126811 20 0.7656469475004968 10 0.6430794062549456 20 0.8244986374144544 42 -0.9999999999999999 10 0.6627644456250243 20 0.7904031490764842 10 0.5894398402719598 20 0.7480691684376697 10 0.6216897564480669 20 0.736331158891987 10 0.7236238734903314 20 0.7951828488059446 42 -0.9999999999999999 10 0.7433089128604101 20 0.7610873604679744 10 0.6699843075073457 20 0.7187533798291599 10 0.7022342236834526 20 0.7070153702834772 10 0.8041683407257171 20 0.7658670601974349 42 -0.9999999999999999 10 0.8238533800957958 20 0.7317715718594647 10 0.7505287747427313 20 0.6894375912206502 10 0.7827786909188382 20 0.6776995816749674 10 0.8847128079611027 20 0.7365512715889251 42 -0.9999999999999999 10 0.9043978473311814 20 0.7024557832509549 10 0.8310732419781172 20 0.6601218026121404 10 0.8633231581542239 20 0.6483837930664577 10 0.9652572751964884 20 0.7072354829804153 42 -0.9999999999999999 10 0.9849423145665671 20 0.6731399946424452 10 0.9116177092135024 20 0.6308060140036307 10 0.9438676253896097 20 0.619068004457948 10 1.045801742431874 20 0.6779196943719056 42 -0.9999999999999999 10 1.065486781801953 20 0.6438242060339354 10 0.992162176448888 20 0.6014902253951211 10 1.024412092624995 20 0.5897522158494382 10 1.12634620966726 20 0.6486039057633959 42 -0.9999999999999999 10 1.146031249037339 20 0.6145084174254256 10 1.072706643684274 20 0.5721744367866111 10 1.104956559860381 20 0.5604364272409283 10 1.206890676902646 20 0.6192881171548861 42 -0.9999999999999999 10 1.226575716272724 20 0.5851926288169159 10 1.15325111091966 20 0.5428586481781015 10 1.185501027095767 20 0.5311206386324185 10 1.287435144138031 20 0.5899723285463763 42 -0.9999999999999999 10 1.30712018350811 20 0.5558768402084061 10 1.233795578155045 20 0.5135428595695918 10 1.266045494331153 20 0.5018048500239088 10 1.367979611373417 20 0.5606565399378665 42 -0.9999999999999999 10 1.387664650743496 20 0.5265610515998964 10 1.314340045390431 20 0.4842270709610819 10 1.346589961566538 20 0.4724890614153991 10 1.448524078608803 20 0.5313407513293568 42 -0.9999999999999999 10 1.468209117978881 20 0.4972452629913866 10 1.394884512625817 20 0.4549112823525721 10 1.427134428801924 20 0.4431732728068893 10 1.529068545844188 20 0.5020249627208471 42 -0.9999999999999999 10 1.548753585214267 20 0.4679294743828769 10 1.475428979861203 20 0.4255954937440624 10 1.50767889603731 20 0.4138574841983796 10 1.609613013079574 20 0.4727091741123373 42 -0.9999999999999999 10 1.629298052449653 20 0.4386136857743671 10 1.555973447096588 20 0.3962797051355528 10 1.588223363272695 20 0.3845416955898698 10 1.69015748031496 20 0.4433933855038275 42 -0.9999999999999999 10 1.709842519685038 20 0.4092978971658573 10 1.636517914331974 20 0.366963916527043 10 1.980314960629922 20 0.2418320250459505 10 1.980314960629921 20 0.4884064321643613 0 LWPOLYLINE 5 12FB 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 0.4918329914692137 20 0.8660824704624889 10 0.3819493807666841 20 0.802641138243856 10 0.3819493807666836 20 0.6550889233752348 0 LWPOLYLINE 5 133B 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.619455532764613 20 0.4556614299433522 10 1.509571922062084 20 0.3922200977247193 10 1.509571922062083 20 0.2446678828560982 0 LWPOLYLINE 5 136A 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.538911065529228 20 0.4849772185518619 10 1.429027454826698 20 0.421535886333229 10 1.429027454826698 20 0.2739836714646079 0 LWPOLYLINE 5 1399 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.458366598293842 20 0.5142930071603717 10 1.348482987591312 20 0.4508516749417388 10 1.348482987591312 20 0.3032994600731177 0 LWPOLYLINE 5 13C8 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.377822131058456 20 0.5436087957688814 10 1.267938520355927 20 0.4801674635502485 10 1.267938520355926 20 0.3326152486816275 0 LWPOLYLINE 5 13F7 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.297277663823071 20 0.5729245843773911 10 1.187394053120541 20 0.5094832521587582 10 1.18739405312054 20 0.3619310372901372 0 LWPOLYLINE 5 1426 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.216733196587685 20 0.6022403729859009 10 1.106849585885155 20 0.538799040767268 10 1.106849585885155 20 0.391246825898647 0 LWPOLYLINE 5 1455 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.136188729352299 20 0.6315561615944107 10 1.02630511864977 20 0.5681148293757778 10 1.026305118649769 20 0.4205626145071568 0 LWPOLYLINE 5 1484 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 1.055644262116914 20 0.6608719502029206 10 0.9457606514143839 20 0.5974306179842876 10 0.9457606514143835 20 0.4498784031156665 0 LWPOLYLINE 5 14B3 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 0.9750997948815278 20 0.6901877388114303 10 0.8652161841789981 20 0.6267464065927973 10 0.8652161841789977 20 0.4791941917241763 0 LWPOLYLINE 5 14E2 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 0.8945553276461421 20 0.71950352741994 10 0.7846717169436125 20 0.656062195201307 10 0.784671716943612 20 0.508509980332686 0 LWPOLYLINE 5 1511 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 0.8140108604107564 20 0.7488193160284498 10 0.7041272497082268 20 0.6853779838098168 10 0.7041272497082264 20 0.5378257689411958 0 LWPOLYLINE 5 1540 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 0.7334663931753708 20 0.7781351046369596 10 0.6235827824728412 20 0.7146937724183267 10 0.6235827824728407 20 0.5671415575497055 0 LWPOLYLINE 5 156F 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 0.652921925939985 20 0.8074508932454694 10 0.5430383152374554 20 0.7440095610268365 10 0.5430383152374549 20 0.5964573461582153 0 LWPOLYLINE 5 159E 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 0.5723774587045993 20 0.836766681853979 10 0.4624938480020697 20 0.773325349635346 10 0.4624938480020693 20 0.625773134766725 0 LWPOLYLINE 5 19B1 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.300000000000002 20 0.4263456413348424 10 2.409883610702532 20 0.3629043091162095 10 2.409883610702533 20 0.2153520942475884 0 LWPOLYLINE 5 19B2 102 {ACAD_REACTORS 330 1B2B 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 68 70 1 43 0.0 10 3.788481969160711 20 1.132195865069596 10 3.78848196916071 20 0.8856214579511849 10 3.619943645258092 20 0.8242785247175163 10 3.518009528215828 20 0.8831302146314739 42 0.9999999999999999 10 3.498324488845749 20 0.8490347262935038 10 3.571649094198813 20 0.8067007456546893 10 3.539399178022706 20 0.7949627361090064 10 3.437465060980442 20 0.8538144260229641 42 0.9999999999999999 10 3.417780021610363 20 0.8197189376849939 10 3.491104626963428 20 0.7773849570461795 10 3.458854710787321 20 0.7656469475004968 10 3.356920593745056 20 0.8244986374144544 42 0.9999999999999999 10 3.337235554374978 20 0.7904031490764842 10 3.410560159728042 20 0.7480691684376697 10 3.378310243551935 20 0.736331158891987 10 3.27637612650967 20 0.7951828488059446 42 0.9999999999999999 10 3.256691087139592 20 0.7610873604679744 10 3.330015692492656 20 0.7187533798291599 10 3.297765776316549 20 0.7070153702834772 10 3.195831659274285 20 0.7658670601974349 42 0.9999999999999999 10 3.176146619904206 20 0.7317715718594647 10 3.24947122525727 20 0.6894375912206502 10 3.217221309081164 20 0.6776995816749674 10 3.115287192038899 20 0.7365512715889251 42 0.9999999999999999 10 3.09560215266882 20 0.7024557832509549 10 3.168926758021885 20 0.6601218026121404 10 3.136676841845778 20 0.6483837930664577 10 3.034742724803513 20 0.7072354829804153 42 0.9999999999999999 10 3.015057685433435 20 0.6731399946424452 10 3.0883822907865 20 0.6308060140036307 10 3.056132374610392 20 0.619068004457948 10 2.954198257568128 20 0.6779196943719056 42 0.9999999999999999 10 2.934513218198049 20 0.6438242060339354 10 3.007837823551114 20 0.6014902253951211 10 2.975587907375006 20 0.5897522158494382 10 2.873653790332742 20 0.6486039057633959 42 0.9999999999999999 10 2.853968750962663 20 0.6145084174254256 10 2.927293356315728 20 0.5721744367866111 10 2.895043440139621 20 0.5604364272409283 10 2.793109323097356 20 0.6192881171548861 42 0.9999999999999999 10 2.773424283727278 20 0.5851926288169159 10 2.846748889080342 20 0.5428586481781015 10 2.814498972904235 20 0.5311206386324185 10 2.712564855861971 20 0.5899723285463763 42 0.9999999999999999 10 2.692879816491892 20 0.5558768402084061 10 2.766204421844956 20 0.5135428595695918 10 2.733954505668849 20 0.5018048500239088 10 2.632020388626585 20 0.5606565399378665 42 0.9999999999999999 10 2.612335349256506 20 0.5265610515998964 10 2.68565995460957 20 0.4842270709610819 10 2.653410038433464 20 0.4724890614153991 10 2.551475921391199 20 0.5313407513293568 42 0.9999999999999999 10 2.53179088202112 20 0.4972452629913866 10 2.605115487374185 20 0.4549112823525721 10 2.572865571198078 20 0.4431732728068893 10 2.470931454155814 20 0.5020249627208471 42 0.9999999999999999 10 2.451246414785735 20 0.4679294743828769 10 2.524571020138799 20 0.4255954937440624 10 2.492321103962692 20 0.4138574841983796 10 2.390386986920428 20 0.4727091741123373 42 0.9999999999999999 10 2.370701947550349 20 0.4386136857743671 10 2.444026552903414 20 0.3962797051355528 10 2.411776636727307 20 0.3845416955898698 10 2.309842519685042 20 0.4433933855038275 42 0.9999999999999999 10 2.290157480314964 20 0.4092978971658573 10 2.363482085668028 20 0.366963916527043 10 2.01968503937008 20 0.2418320250459505 10 2.019685039370081 20 0.4884064321643613 0 LWPOLYLINE 5 19B3 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.461088934470774 20 0.4849772185518619 10 2.570972545173304 20 0.421535886333229 10 2.570972545173304 20 0.2739836714646079 0 LWPOLYLINE 5 19B4 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.380544467235389 20 0.4556614299433522 10 2.490428077937918 20 0.3922200977247193 10 2.490428077937918 20 0.2446678828560982 0 LWPOLYLINE 5 19B5 102 {ACAD_REACTORS 330 1B2B 102 } 330 1F 100 AcDbEntity 8 OUTLINE 100 AcDbPolyline 90 145 70 1 43 0.0 10 0.1721479520991344 20 0.8718378449943008 42 0.3152987888789827 10 0.1851003114824874 20 0.8533399587583579 10 0.3622643413966053 20 0.7888575252869718 10 0.3622643413966049 20 0.6550889233752349 42 0.9999999999999999 10 0.4016344201367623 20 0.6550889233752348 10 0.4016344201367628 20 0.7745279885048381 10 0.442808808631991 20 0.759541736678462 10 0.4428088086319906 20 0.625773134766725 42 0.9999999999999999 10 0.482178887372148 20 0.625773134766725 10 0.4821788873721484 20 0.7452121998963283 10 0.5233532758673767 20 0.7302259480699523 10 0.5233532758673762 20 0.5964573461582154 42 0.9999999999999999 10 0.5627233546075336 20 0.5964573461582152 10 0.5627233546075341 20 0.7158964112878186 10 0.6038977431027625 20 0.7009101594614425 10 0.603897743102762 20 0.5671415575497056 42 0.9999999999999999 10 0.6432678218429194 20 0.5671415575497054 10 0.6432678218429199 20 0.6865806226793086 10 0.6844422103381481 20 0.6715943708529328 10 0.6844422103381477 20 0.5378257689411958 42 0.9999999999999999 10 0.7238122890783051 20 0.5378257689411958 10 0.7238122890783055 20 0.6572648340707989 10 0.7649866775735338 20 0.642278582244423 10 0.7649866775735333 20 0.508509980332686 42 0.9999999999999999 10 0.8043567563136907 20 0.508509980332686 10 0.8043567563136912 20 0.6279490454622892 10 0.8455311448089194 20 0.6129627936359132 10 0.845531144808919 20 0.4791941917241763 42 0.9999999999999999 10 0.8849012235490764 20 0.4791941917241762 10 0.8849012235490769 20 0.5986332568537795 10 0.9260756120443052 20 0.5836470050274035 10 0.9260756120443048 20 0.4498784031156666 42 0.9999999999999999 10 0.9654456907844622 20 0.4498784031156665 10 0.9654456907844626 20 0.5693174682452696 10 1.006620079279691 20 0.5543312164188938 10 1.00662007927969 20 0.4205626145071568 42 0.9999999999999999 10 1.045990158019848 20 0.4205626145071567 10 1.045990158019848 20 0.5400016796367598 10 1.087164546515077 20 0.525015427810384 10 1.087164546515076 20 0.3912468258986471 42 0.9999999999999999 10 1.126534625255234 20 0.391246825898647 10 1.126534625255234 20 0.5106858910282501 10 1.167709013750462 20 0.4956996392018742 10 1.167709013750462 20 0.3619310372901373 42 0.9999999999999999 10 1.207079092490619 20 0.3619310372901371 10 1.20707909249062 20 0.4813701024197403 10 1.248253480985848 20 0.4663838505933645 10 1.248253480985848 20 0.3326152486816275 42 0.9999999999999999 10 1.287623559726005 20 0.3326152486816274 10 1.287623559726006 20 0.4520543138112305 10 1.328797948221234 20 0.4370680619848547 10 1.328797948221233 20 0.3032994600731178 42 0.9999999999999999 10 1.368168026961391 20 0.3032994600731176 10 1.368168026961391 20 0.4227385252027208 10 1.409342415456619 20 0.407752273376345 10 1.409342415456619 20 0.273983671464608 42 0.9999999999999999 10 1.448712494196776 20 0.2739836714646079 10 1.448712494196777 20 0.393422736594211 10 1.489886882692005 20 0.3784364847678352 10 1.489886882692005 20 0.2446678828560983 42 0.9999999999999999 10 1.529256961432162 20 0.2446678828560981 10 1.529256961432162 20 0.3641069479857013 10 1.570431349927391 20 0.3491206961593254 10 1.57043134992739 20 0.2153520942475885 42 0.9999999999999999 10 1.609801428667548 20 0.2153520942475884 10 1.609801428667548 20 0.3347911593771915 10 1.993267320013264 20 0.1952209890709761 42 0.1763269807087526 10 2.006732679986736 20 0.1952209890709762 10 2.390198571332454 20 0.3347911593771915 10 2.390198571332454 20 0.2153520942475884 42 0.9999999999999999 10 2.429568650072611 20 0.2153520942475885 10 2.429568650072611 20 0.3491206961593254 10 2.470743038567839 20 0.3641069479857013 10 2.47074303856784 20 0.2446678828560981 42 0.9999999999999999 10 2.510113117307997 20 0.2446678828560983 10 2.510113117307997 20 0.3784364847678352 10 2.551287505803225 20 0.393422736594211 10 2.551287505803225 20 0.2739836714646079 42 0.9999999999999999 10 2.590657584543383 20 0.273983671464608 10 2.590657584543382 20 0.407752273376345 10 2.631831973038611 20 0.4227385252027208 10 2.631831973038611 20 0.3032994600731176 42 0.9999999999999999 10 2.671202051778768 20 0.3032994600731178 10 2.671202051778768 20 0.4370680619848547 10 2.712376440273996 20 0.4520543138112305 10 2.712376440273997 20 0.3326152486816274 42 0.9999999999999999 10 2.751746519014154 20 0.3326152486816275 10 2.751746519014154 20 0.4663838505933645 10 2.792920907509382 20 0.4813701024197403 10 2.792920907509383 20 0.3619310372901371 42 0.9999999999999999 10 2.83229098624954 20 0.3619310372901373 10 2.832290986249539 20 0.4956996392018742 10 2.873465374744768 20 0.5106858910282501 10 2.873465374744768 20 0.391246825898647 42 0.9999999999999999 10 2.912835453484925 20 0.3912468258986471 10 2.912835453484925 20 0.525015427810384 10 2.954009841980153 20 0.5400016796367598 10 2.954009841980154 20 0.4205626145071567 42 0.9999999999999999 10 2.993379920720312 20 0.4205626145071568 10 2.993379920720311 20 0.5543312164188938 10 3.034554309215539 20 0.5693174682452696 10 3.034554309215539 20 0.4498784031156665 42 0.9999999999999999 10 3.073924387955697 20 0.4498784031156666 10 3.073924387955697 20 0.5836470050274035 10 3.115098776450925 20 0.5986332568537795 10 3.115098776450925 20 0.4791941917241762 42 0.9999999999999999 10 3.154468855191083 20 0.4791941917241763 10 3.154468855191082 20 0.6129627936359132 10 3.195643243686311 20 0.6279490454622892 10 3.195643243686311 20 0.508509980332686 42 0.9999999999999999 10 3.235013322426469 20 0.508509980332686 10 3.235013322426468 20 0.642278582244423 10 3.276187710921696 20 0.6572648340707989 10 3.276187710921697 20 0.5378257689411958 42 0.9999999999999999 10 3.315557789661854 20 0.5378257689411958 10 3.315557789661854 20 0.6715943708529328 10 3.356732178157082 20 0.6865806226793086 10 3.356732178157082 20 0.5671415575497054 42 0.9999999999999999 10 3.39610225689724 20 0.5671415575497056 10 3.396102256897239 20 0.7009101594614425 10 3.437276645392468 20 0.7158964112878186 10 3.437276645392468 20 0.5964573461582152 42 0.9999999999999999 10 3.476646724132626 20 0.5964573461582154 10 3.476646724132625 20 0.7302259480699523 10 3.517821112627853 20 0.7452121998963283 10 3.517821112627854 20 0.625773134766725 42 0.9999999999999999 10 3.557191191368011 20 0.625773134766725 10 3.557191191368011 20 0.759541736678462 10 3.598365579863239 20 0.7745279885048381 10 3.598365579863239 20 0.6550889233752348 42 0.9999999999999999 10 3.637735658603397 20 0.6550889233752349 10 3.637735658603396 20 0.7888575252869718 10 3.814899688517512 20 0.853339958758357 42 0.3152987888789825 10 3.827852047900865 20 0.8718378449942998 10 3.827852047900866 20 1.160309014808614 42 0.2914734195860939 10 3.816486265651666 20 1.17814971927784 10 3.302025394556464 20 1.418046763290625 42 0.9999999999999994 10 3.285386880314704 20 1.382365354352174 10 3.756776480718013 20 1.162552773709486 10 2.0 20 0.5231384264691965 10 0.2432235192819858 20 1.162552773709486 10 0.7689601562847856 20 1.407707793716547 42 1.000000000000008 10 0.7523216420430257 20 1.443389202654997 10 0.1835137343483321 20 1.178149719277839 42 0.2914734195860883 10 0.1721479520991333 20 1.160309014808614 0 LWPOLYLINE 5 19B6 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.702722336176931 20 0.5729245843773911 10 2.812605946879461 20 0.5094832521587582 10 2.812605946879462 20 0.3619310372901372 0 LWPOLYLINE 5 19B7 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.622177868941545 20 0.5436087957688814 10 2.732061479644075 20 0.4801674635502485 10 2.732061479644075 20 0.3326152486816275 0 LWPOLYLINE 5 19B8 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.54163340170616 20 0.5142930071603717 10 2.651517012408689 20 0.4508516749417388 10 2.65151701240869 20 0.3032994600731177 0 LWPOLYLINE 5 19B9 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.863811270647703 20 0.6315561615944107 10 2.973694881350232 20 0.5681148293757778 10 2.973694881350233 20 0.4205626145071568 0 LWPOLYLINE 5 19BA 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.783266803412317 20 0.6022403729859009 10 2.893150414114847 20 0.538799040767268 10 2.893150414114847 20 0.391246825898647 0 LWPOLYLINE 5 19BB 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 3.10544467235386 20 0.71950352741994 10 3.215328283056389 20 0.656062195201307 10 3.21532828305639 20 0.508509980332686 0 LWPOLYLINE 5 19BC 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 2.944355737883088 20 0.6608719502029206 10 3.054239348585618 20 0.5974306179842876 10 3.054239348585618 20 0.4498784031156665 0 LWPOLYLINE 5 19BD 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 3.024900205118474 20 0.6901877388114303 10 3.134783815821004 20 0.6267464065927973 10 3.134783815821004 20 0.4791941917241763 0 LWPOLYLINE 5 19BE 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 3.508167008530788 20 0.8660824704624889 10 3.618050619233318 20 0.802641138243856 10 3.618050619233318 20 0.6550889233752348 0 LWPOLYLINE 5 19BF 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 3.185989139589245 20 0.7488193160284498 10 3.295872750291775 20 0.6853779838098168 10 3.295872750291776 20 0.5378257689411958 0 LWPOLYLINE 5 19C0 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 3.266533606824631 20 0.7781351046369596 10 3.376417217527161 20 0.7146937724183267 10 3.376417217527161 20 0.5671415575497055 0 LWPOLYLINE 5 19C1 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 3.347078074060017 20 0.8074508932454694 10 3.456961684762546 20 0.7440095610268365 10 3.456961684762547 20 0.5964573461582153 0 LWPOLYLINE 5 19C2 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 3 70 0 43 0.0 10 3.427622541295403 20 0.836766681853979 10 3.537506151997932 20 0.773325349635346 10 3.537506151997933 20 0.625773134766725 0 LWPOLYLINE 5 1A86 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 5 70 0 43 0.0 10 3.808167008530787 20 1.160309014808614 10 3.808167008530789 20 0.8718378449943008 10 2.000000000000001 20 0.2137188753069324 10 0.1918329914692131 20 0.8718378449943008 10 0.1918329914692121 20 1.160309014808614 0 LWPOLYLINE 5 1A88 330 1F 100 AcDbEntity 8 CENTERLINE 100 AcDbPolyline 90 5 70 0 43 0.0 10 0.7606408991639058 20 1.425548498185772 10 0.1918329914692121 20 1.160309014808614 10 1.999999999999999 20 0.5021900451212454 10 3.808167008530787 20 1.160309014808614 10 3.293706137435584 20 1.4002060588214 0 HATCH 5 1B2B 330 1F 100 AcDbEntity 8 HATCH-BLACK 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 3 92 1 93 145 72 2 10 0.1918329914692131 20 0.871837844994301 40 0.0196850393700787 50 180.0000000000002 51 250.0 73 1 72 1 10 0.1851003114824874 20 0.8533399587583579 11 0.3622643413966053 21 0.7888575252869718 72 1 10 0.3622643413966053 20 0.7888575252869718 11 0.3622643413966049 21 0.6550889233752349 72 2 10 0.3819493807666836 20 0.6550889233752349 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 0.4016344201367623 20 0.6550889233752348 11 0.4016344201367628 21 0.7745279885048381 72 1 10 0.4016344201367628 20 0.7745279885048381 11 0.442808808631991 21 0.759541736678462 72 1 10 0.442808808631991 20 0.759541736678462 11 0.4428088086319906 21 0.625773134766725 72 2 10 0.4624938480020693 20 0.625773134766725 40 0.0196850393700787 50 180.0 51 360.0 73 1 72 1 10 0.482178887372148 20 0.625773134766725 11 0.4821788873721484 21 0.7452121998963283 72 1 10 0.4821788873721484 20 0.7452121998963283 11 0.5233532758673767 21 0.7302259480699523 72 1 10 0.5233532758673767 20 0.7302259480699523 11 0.5233532758673762 21 0.5964573461582154 72 2 10 0.5430383152374549 20 0.5964573461582153 40 0.0196850393700787 50 179.9999999999997 51 359.9999999999997 73 1 72 1 10 0.5627233546075336 20 0.5964573461582152 11 0.5627233546075341 21 0.7158964112878186 72 1 10 0.5627233546075341 20 0.7158964112878186 11 0.6038977431027625 21 0.7009101594614425 72 1 10 0.6038977431027625 20 0.7009101594614425 11 0.603897743102762 21 0.5671415575497056 72 2 10 0.6235827824728407 20 0.5671415575497055 40 0.0196850393700787 50 179.9999999999997 51 359.9999999999997 73 1 72 1 10 0.6432678218429194 20 0.5671415575497054 11 0.6432678218429199 21 0.6865806226793086 72 1 10 0.6432678218429199 20 0.6865806226793086 11 0.6844422103381481 21 0.6715943708529328 72 1 10 0.6844422103381481 20 0.6715943708529328 11 0.6844422103381477 21 0.5378257689411958 72 2 10 0.7041272497082264 20 0.5378257689411958 40 0.0196850393700787 50 180.0 51 360.0 73 1 72 1 10 0.7238122890783051 20 0.5378257689411958 11 0.7238122890783055 21 0.6572648340707989 72 1 10 0.7238122890783055 20 0.6572648340707989 11 0.7649866775735338 21 0.642278582244423 72 1 10 0.7649866775735338 20 0.642278582244423 11 0.7649866775735333 21 0.508509980332686 72 2 10 0.784671716943612 20 0.508509980332686 40 0.0196850393700787 50 180.0 51 360.0 73 1 72 1 10 0.8043567563136907 20 0.508509980332686 11 0.8043567563136912 21 0.6279490454622892 72 1 10 0.8043567563136912 20 0.6279490454622892 11 0.8455311448089194 21 0.6129627936359132 72 1 10 0.8455311448089194 20 0.6129627936359132 11 0.845531144808919 21 0.4791941917241763 72 2 10 0.8652161841789977 20 0.4791941917241763 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 0.8849012235490764 20 0.4791941917241762 11 0.8849012235490769 21 0.5986332568537795 72 1 10 0.8849012235490769 20 0.5986332568537795 11 0.9260756120443052 21 0.5836470050274035 72 1 10 0.9260756120443052 20 0.5836470050274035 11 0.9260756120443048 21 0.4498784031156666 72 2 10 0.9457606514143835 20 0.4498784031156665 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 0.9654456907844622 20 0.4498784031156665 11 0.9654456907844626 21 0.5693174682452696 72 1 10 0.9654456907844626 20 0.5693174682452696 11 1.006620079279691 21 0.5543312164188938 72 1 10 1.006620079279691 20 0.5543312164188938 11 1.00662007927969 21 0.4205626145071568 72 2 10 1.026305118649769 20 0.4205626145071568 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 1.045990158019848 20 0.4205626145071567 11 1.045990158019848 21 0.5400016796367598 72 1 10 1.045990158019848 20 0.5400016796367598 11 1.087164546515077 21 0.525015427810384 72 1 10 1.087164546515077 20 0.525015427810384 11 1.087164546515076 21 0.3912468258986471 72 2 10 1.106849585885155 20 0.391246825898647 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 1.126534625255234 20 0.391246825898647 11 1.126534625255234 21 0.5106858910282501 72 1 10 1.126534625255234 20 0.5106858910282501 11 1.167709013750462 21 0.4956996392018742 72 1 10 1.167709013750462 20 0.4956996392018742 11 1.167709013750462 21 0.3619310372901373 72 2 10 1.18739405312054 20 0.3619310372901372 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 1.207079092490619 20 0.3619310372901371 11 1.20707909249062 21 0.4813701024197403 72 1 10 1.20707909249062 20 0.4813701024197403 11 1.248253480985848 21 0.4663838505933645 72 1 10 1.248253480985848 20 0.4663838505933645 11 1.248253480985848 21 0.3326152486816275 72 2 10 1.267938520355926 20 0.3326152486816275 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 1.287623559726005 20 0.3326152486816274 11 1.287623559726006 21 0.4520543138112305 72 1 10 1.287623559726006 20 0.4520543138112305 11 1.328797948221234 21 0.4370680619848547 72 1 10 1.328797948221234 20 0.4370680619848547 11 1.328797948221233 21 0.3032994600731178 72 2 10 1.348482987591312 20 0.3032994600731177 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 1.368168026961391 20 0.3032994600731176 11 1.368168026961391 21 0.4227385252027208 72 1 10 1.368168026961391 20 0.4227385252027208 11 1.409342415456619 21 0.407752273376345 72 1 10 1.409342415456619 20 0.407752273376345 11 1.409342415456619 21 0.273983671464608 72 2 10 1.429027454826698 20 0.2739836714646079 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 1.448712494196776 20 0.2739836714646079 11 1.448712494196777 21 0.393422736594211 72 1 10 1.448712494196777 20 0.393422736594211 11 1.489886882692005 21 0.3784364847678352 72 1 10 1.489886882692005 20 0.3784364847678352 11 1.489886882692005 21 0.2446678828560983 72 2 10 1.509571922062083 20 0.2446678828560982 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 1.529256961432162 20 0.2446678828560981 11 1.529256961432162 21 0.3641069479857013 72 1 10 1.529256961432162 20 0.3641069479857013 11 1.570431349927391 21 0.3491206961593254 72 1 10 1.570431349927391 20 0.3491206961593254 11 1.57043134992739 21 0.2153520942475885 72 2 10 1.590116389297469 20 0.2153520942475884 40 0.0196850393700787 50 179.9999999999998 51 359.9999999999998 73 1 72 1 10 1.609801428667548 20 0.2153520942475884 11 1.609801428667548 21 0.3347911593771915 72 1 10 1.609801428667548 20 0.3347911593771915 11 1.993267320013264 21 0.1952209890709761 72 2 10 2.0 20 0.2137188753069149 40 0.0196850393700781 50 249.9999999999685 51 290.0000000000325 73 1 72 1 10 2.006732679986736 20 0.1952209890709762 11 2.390198571332454 21 0.3347911593771915 72 1 10 2.390198571332454 20 0.3347911593771915 11 2.390198571332454 21 0.2153520942475884 72 2 10 2.409883610702533 20 0.2153520942475884 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 2.429568650072611 20 0.2153520942475885 11 2.429568650072611 21 0.3491206961593254 72 1 10 2.429568650072611 20 0.3491206961593254 11 2.470743038567839 21 0.3641069479857013 72 1 10 2.470743038567839 20 0.3641069479857013 11 2.47074303856784 21 0.2446678828560981 72 2 10 2.490428077937918 20 0.2446678828560982 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 2.510113117307997 20 0.2446678828560983 11 2.510113117307997 21 0.3784364847678352 72 1 10 2.510113117307997 20 0.3784364847678352 11 2.551287505803225 21 0.393422736594211 72 1 10 2.551287505803225 20 0.393422736594211 11 2.551287505803225 21 0.2739836714646079 72 2 10 2.570972545173304 20 0.2739836714646079 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 2.590657584543383 20 0.273983671464608 11 2.590657584543382 21 0.407752273376345 72 1 10 2.590657584543382 20 0.407752273376345 11 2.631831973038611 21 0.4227385252027208 72 1 10 2.631831973038611 20 0.4227385252027208 11 2.631831973038611 21 0.3032994600731176 72 2 10 2.65151701240869 20 0.3032994600731177 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 2.671202051778768 20 0.3032994600731178 11 2.671202051778768 21 0.4370680619848547 72 1 10 2.671202051778768 20 0.4370680619848547 11 2.712376440273996 21 0.4520543138112305 72 1 10 2.712376440273996 20 0.4520543138112305 11 2.712376440273997 21 0.3326152486816274 72 2 10 2.732061479644075 20 0.3326152486816275 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 2.751746519014154 20 0.3326152486816275 11 2.751746519014154 21 0.4663838505933645 72 1 10 2.751746519014154 20 0.4663838505933645 11 2.792920907509382 21 0.4813701024197403 72 1 10 2.792920907509382 20 0.4813701024197403 11 2.792920907509383 21 0.3619310372901371 72 2 10 2.812605946879462 20 0.3619310372901372 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 2.83229098624954 20 0.3619310372901373 11 2.832290986249539 21 0.4956996392018742 72 1 10 2.832290986249539 20 0.4956996392018742 11 2.873465374744768 21 0.5106858910282501 72 1 10 2.873465374744768 20 0.5106858910282501 11 2.873465374744768 21 0.391246825898647 72 2 10 2.893150414114847 20 0.391246825898647 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 2.912835453484925 20 0.3912468258986471 11 2.912835453484925 21 0.525015427810384 72 1 10 2.912835453484925 20 0.525015427810384 11 2.954009841980153 21 0.5400016796367598 72 1 10 2.954009841980153 20 0.5400016796367598 11 2.954009841980154 21 0.4205626145071567 72 2 10 2.973694881350233 20 0.4205626145071568 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 2.993379920720312 20 0.4205626145071568 11 2.993379920720311 21 0.5543312164188938 72 1 10 2.993379920720311 20 0.5543312164188938 11 3.034554309215539 21 0.5693174682452696 72 1 10 3.034554309215539 20 0.5693174682452696 11 3.034554309215539 21 0.4498784031156665 72 2 10 3.054239348585618 20 0.4498784031156665 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 3.073924387955697 20 0.4498784031156666 11 3.073924387955697 21 0.5836470050274035 72 1 10 3.073924387955697 20 0.5836470050274035 11 3.115098776450925 21 0.5986332568537795 72 1 10 3.115098776450925 20 0.5986332568537795 11 3.115098776450925 21 0.4791941917241762 72 2 10 3.134783815821004 20 0.4791941917241763 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 3.154468855191083 20 0.4791941917241763 11 3.154468855191082 21 0.6129627936359132 72 1 10 3.154468855191082 20 0.6129627936359132 11 3.195643243686311 21 0.6279490454622892 72 1 10 3.195643243686311 20 0.6279490454622892 11 3.195643243686311 21 0.508509980332686 72 2 10 3.21532828305639 20 0.508509980332686 40 0.0196850393700787 50 180.0 51 360.0 73 1 72 1 10 3.235013322426469 20 0.508509980332686 11 3.235013322426468 21 0.642278582244423 72 1 10 3.235013322426468 20 0.642278582244423 11 3.276187710921696 21 0.6572648340707989 72 1 10 3.276187710921696 20 0.6572648340707989 11 3.276187710921697 21 0.5378257689411958 72 2 10 3.295872750291776 20 0.5378257689411958 40 0.0196850393700787 50 180.0 51 360.0 73 1 72 1 10 3.315557789661854 20 0.5378257689411958 11 3.315557789661854 21 0.6715943708529328 72 1 10 3.315557789661854 20 0.6715943708529328 11 3.356732178157082 21 0.6865806226793086 72 1 10 3.356732178157082 20 0.6865806226793086 11 3.356732178157082 21 0.5671415575497054 72 2 10 3.376417217527161 20 0.5671415575497055 40 0.0196850393700787 50 180.0000000000003 51 360.0000000000003 73 1 72 1 10 3.39610225689724 20 0.5671415575497056 11 3.396102256897239 21 0.7009101594614425 72 1 10 3.396102256897239 20 0.7009101594614425 11 3.437276645392468 21 0.7158964112878186 72 1 10 3.437276645392468 20 0.7158964112878186 11 3.437276645392468 21 0.5964573461582152 72 2 10 3.456961684762547 20 0.5964573461582153 40 0.0196850393700787 50 180.0000000000003 51 360.0000000000003 73 1 72 1 10 3.476646724132626 20 0.5964573461582154 11 3.476646724132625 21 0.7302259480699523 72 1 10 3.476646724132625 20 0.7302259480699523 11 3.517821112627853 21 0.7452121998963283 72 1 10 3.517821112627853 20 0.7452121998963283 11 3.517821112627854 21 0.625773134766725 72 2 10 3.537506151997933 20 0.625773134766725 40 0.0196850393700787 50 180.0 51 360.0 73 1 72 1 10 3.557191191368011 20 0.625773134766725 11 3.557191191368011 21 0.759541736678462 72 1 10 3.557191191368011 20 0.759541736678462 11 3.598365579863239 21 0.7745279885048381 72 1 10 3.598365579863239 20 0.7745279885048381 11 3.598365579863239 21 0.6550889233752348 72 2 10 3.618050619233318 20 0.6550889233752349 40 0.0196850393700787 50 180.0000000000002 51 360.0000000000002 73 1 72 1 10 3.637735658603397 20 0.6550889233752349 11 3.637735658603396 21 0.7888575252869718 72 1 10 3.637735658603396 20 0.7888575252869718 11 3.814899688517512 21 0.853339958758357 72 2 10 3.808167008530786 20 0.8718378449942998 40 0.0196850393700785 50 290.0000000000003 51 360.0000000000001 73 1 72 1 10 3.827852047900865 20 0.8718378449942998 11 3.827852047900866 21 1.160309014808614 72 2 10 3.808167008530787 20 1.160309014808614 40 0.0196850393700788 50 359.9999999999999 51 425.0000000000013 73 1 72 1 10 3.816486265651666 20 1.17814971927784 11 3.302025394556464 21 1.418046763290625 72 2 10 3.293706137435584 20 1.4002060588214 40 0.0196850393700788 50 65.00000000000018 51 245.0000000000001 73 1 72 1 10 3.285386880314704 20 1.382365354352174 11 3.756776480718013 21 1.162552773709486 72 1 10 3.756776480718013 20 1.162552773709486 11 2.0 21 0.5231384264691965 72 1 10 2.0 20 0.5231384264691965 11 0.2432235192819858 21 1.162552773709486 72 1 10 0.2432235192819858 20 1.162552773709486 11 0.7689601562847856 21 1.407707793716547 72 2 10 0.7606408991639058 20 1.425548498185772 40 0.0196850393700788 50 294.9999999999998 51 475.0000000000007 73 1 72 1 10 0.7523216420430257 20 1.443389202654997 11 0.1835137343483322 21 1.178149719277839 72 2 10 0.1918329914692121 20 1.160309014808614 40 0.0196850393700788 50 115.0000000000001 51 180.0000000000002 73 1 72 1 10 0.1721479520991333 20 1.160309014808614 11 0.1721479520991344 21 0.8718378449943008 97 1 330 19B5 92 16 93 68 72 1 10 3.788481969160711 20 1.132195865069596 11 3.78848196916071 21 0.8856214579511849 72 1 10 3.78848196916071 20 0.8856214579511849 11 3.619943645258092 21 0.8242785247175163 72 1 10 3.619943645258092 20 0.8242785247175163 11 3.518009528215828 21 0.8831302146314739 72 2 10 3.508167008530788 20 0.8660824704624889 40 0.0196850393700787 50 60.00000000000008 51 240.0000000000001 73 1 72 1 10 3.498324488845749 20 0.8490347262935038 11 3.571649094198813 21 0.8067007456546893 72 1 10 3.571649094198813 20 0.8067007456546893 11 3.539399178022706 21 0.7949627361090064 72 1 10 3.539399178022706 20 0.7949627361090064 11 3.437465060980442 21 0.8538144260229641 72 2 10 3.427622541295402 20 0.836766681853979 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 3.417780021610363 20 0.8197189376849939 11 3.491104626963428 21 0.7773849570461795 72 1 10 3.491104626963428 20 0.7773849570461795 11 3.458854710787321 21 0.7656469475004968 72 1 10 3.458854710787321 20 0.7656469475004968 11 3.356920593745056 21 0.8244986374144544 72 2 10 3.347078074060017 20 0.8074508932454694 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 3.337235554374978 20 0.7904031490764842 11 3.410560159728042 21 0.7480691684376697 72 1 10 3.410560159728042 20 0.7480691684376697 11 3.378310243551935 21 0.736331158891987 72 1 10 3.378310243551935 20 0.736331158891987 11 3.27637612650967 21 0.7951828488059446 72 2 10 3.266533606824631 20 0.7781351046369596 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 3.256691087139592 20 0.7610873604679744 11 3.330015692492656 21 0.7187533798291599 72 1 10 3.330015692492656 20 0.7187533798291599 11 3.297765776316549 21 0.7070153702834772 72 1 10 3.297765776316549 20 0.7070153702834772 11 3.195831659274285 21 0.7658670601974349 72 2 10 3.185989139589245 20 0.7488193160284498 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 3.176146619904206 20 0.7317715718594647 11 3.24947122525727 21 0.6894375912206502 72 1 10 3.24947122525727 20 0.6894375912206502 11 3.217221309081164 21 0.6776995816749674 72 1 10 3.217221309081164 20 0.6776995816749674 11 3.115287192038899 21 0.7365512715889251 72 2 10 3.10544467235386 20 0.71950352741994 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 3.09560215266882 20 0.7024557832509549 11 3.168926758021885 21 0.6601218026121404 72 1 10 3.168926758021885 20 0.6601218026121404 11 3.136676841845778 21 0.6483837930664577 72 1 10 3.136676841845778 20 0.6483837930664577 11 3.034742724803513 21 0.7072354829804153 72 2 10 3.024900205118474 20 0.6901877388114303 40 0.0196850393700787 50 60.00000000000008 51 240.0000000000001 73 1 72 1 10 3.015057685433435 20 0.6731399946424452 11 3.0883822907865 21 0.6308060140036307 72 1 10 3.0883822907865 20 0.6308060140036307 11 3.056132374610392 21 0.619068004457948 72 1 10 3.056132374610392 20 0.619068004457948 11 2.954198257568128 21 0.6779196943719056 72 2 10 2.944355737883088 20 0.6608719502029206 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 2.934513218198049 20 0.6438242060339354 11 3.007837823551114 21 0.6014902253951211 72 1 10 3.007837823551114 20 0.6014902253951211 11 2.975587907375006 21 0.5897522158494382 72 1 10 2.975587907375006 20 0.5897522158494382 11 2.873653790332742 21 0.6486039057633959 72 2 10 2.863811270647703 20 0.6315561615944107 40 0.0196850393700788 50 60.00000000000023 51 240.0000000000002 73 1 72 1 10 2.853968750962663 20 0.6145084174254256 11 2.927293356315728 21 0.5721744367866111 72 1 10 2.927293356315728 20 0.5721744367866111 11 2.895043440139621 21 0.5604364272409283 72 1 10 2.895043440139621 20 0.5604364272409283 11 2.793109323097356 21 0.6192881171548861 72 2 10 2.783266803412317 20 0.6022403729859009 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 2.773424283727278 20 0.5851926288169159 11 2.846748889080342 21 0.5428586481781015 72 1 10 2.846748889080342 20 0.5428586481781015 11 2.814498972904235 21 0.5311206386324185 72 1 10 2.814498972904235 20 0.5311206386324185 11 2.712564855861971 21 0.5899723285463763 72 2 10 2.702722336176931 20 0.5729245843773911 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 2.692879816491892 20 0.5558768402084061 11 2.766204421844956 21 0.5135428595695918 72 1 10 2.766204421844956 20 0.5135428595695918 11 2.733954505668849 21 0.5018048500239088 72 1 10 2.733954505668849 20 0.5018048500239088 11 2.632020388626585 21 0.5606565399378665 72 2 10 2.622177868941546 20 0.5436087957688814 40 0.0196850393700787 50 60.00000000000008 51 240.0000000000001 73 1 72 1 10 2.612335349256506 20 0.5265610515998964 11 2.68565995460957 21 0.4842270709610819 72 1 10 2.68565995460957 20 0.4842270709610819 11 2.653410038433464 21 0.4724890614153991 72 1 10 2.653410038433464 20 0.4724890614153991 11 2.551475921391199 21 0.5313407513293568 72 2 10 2.541633401706159 20 0.5142930071603717 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 2.53179088202112 20 0.4972452629913866 11 2.605115487374185 21 0.4549112823525721 72 1 10 2.605115487374185 20 0.4549112823525721 11 2.572865571198078 21 0.4431732728068893 72 1 10 2.572865571198078 20 0.4431732728068893 11 2.470931454155814 21 0.5020249627208471 72 2 10 2.461088934470774 20 0.4849772185518619 40 0.0196850393700788 50 60.00000000000018 51 240.0000000000002 73 1 72 1 10 2.451246414785735 20 0.4679294743828769 11 2.524571020138799 21 0.4255954937440624 72 1 10 2.524571020138799 20 0.4255954937440624 11 2.492321103962692 21 0.4138574841983796 72 1 10 2.492321103962692 20 0.4138574841983796 11 2.390386986920428 21 0.4727091741123373 72 2 10 2.380544467235388 20 0.4556614299433522 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 2.370701947550349 20 0.4386136857743671 11 2.444026552903414 21 0.3962797051355528 72 1 10 2.444026552903414 20 0.3962797051355528 11 2.411776636727307 21 0.3845416955898698 72 1 10 2.411776636727307 20 0.3845416955898698 11 2.309842519685042 21 0.4433933855038275 72 2 10 2.300000000000003 20 0.4263456413348424 40 0.0196850393700788 50 60.00000000000015 51 240.0000000000001 73 1 72 1 10 2.290157480314964 20 0.4092978971658573 11 2.363482085668028 21 0.366963916527043 72 1 10 2.363482085668028 20 0.366963916527043 11 2.01968503937008 21 0.2418320250459505 72 1 10 2.01968503937008 20 0.2418320250459505 11 2.019685039370081 21 0.4884064321643613 72 1 10 2.019685039370081 20 0.4884064321643613 11 3.788481969160711 21 1.132195865069596 97 1 330 19B2 92 16 93 68 72 1 10 0.211518030839291 20 1.132195865069596 11 0.2115180308392921 21 0.8856214579511849 72 1 10 0.2115180308392921 20 0.8856214579511849 11 0.3800563547419098 21 0.8242785247175163 72 1 10 0.3800563547419098 20 0.8242785247175163 11 0.4819904717841743 21 0.8831302146314739 72 2 10 0.4918329914692137 20 0.8660824704624889 40 0.0196850393700787 50 240.0 51 420.0 73 0 72 1 10 0.501675511154253 20 0.8490347262935038 11 0.4283509058011884 21 0.8067007456546893 72 1 10 0.4283509058011884 20 0.8067007456546893 11 0.4606008219772955 21 0.7949627361090064 72 1 10 0.4606008219772955 20 0.7949627361090064 11 0.56253493901956 21 0.8538144260229641 72 2 10 0.5723774587045993 20 0.836766681853979 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 0.5822199783896387 20 0.8197189376849939 11 0.5088953730365742 21 0.7773849570461795 72 1 10 0.5088953730365742 20 0.7773849570461795 11 0.5411452892126811 21 0.7656469475004968 72 1 10 0.5411452892126811 20 0.7656469475004968 11 0.6430794062549456 21 0.8244986374144544 72 2 10 0.652921925939985 20 0.8074508932454694 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 0.6627644456250243 20 0.7904031490764842 11 0.5894398402719598 21 0.7480691684376697 72 1 10 0.5894398402719598 20 0.7480691684376697 11 0.6216897564480669 21 0.736331158891987 72 1 10 0.6216897564480669 20 0.736331158891987 11 0.7236238734903314 21 0.7951828488059446 72 2 10 0.7334663931753708 20 0.7781351046369596 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 0.7433089128604101 20 0.7610873604679744 11 0.6699843075073457 21 0.7187533798291599 72 1 10 0.6699843075073457 20 0.7187533798291599 11 0.7022342236834526 21 0.7070153702834772 72 1 10 0.7022342236834526 20 0.7070153702834772 11 0.8041683407257171 21 0.7658670601974349 72 2 10 0.8140108604107564 20 0.7488193160284498 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 0.8238533800957958 20 0.7317715718594647 11 0.7505287747427313 21 0.6894375912206502 72 1 10 0.7505287747427313 20 0.6894375912206502 11 0.7827786909188382 21 0.6776995816749674 72 1 10 0.7827786909188382 20 0.6776995816749674 11 0.8847128079611027 21 0.7365512715889251 72 2 10 0.8945553276461421 20 0.71950352741994 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 0.9043978473311814 20 0.7024557832509549 11 0.8310732419781172 21 0.6601218026121404 72 1 10 0.8310732419781172 20 0.6601218026121404 11 0.8633231581542239 21 0.6483837930664577 72 1 10 0.8633231581542239 20 0.6483837930664577 11 0.9652572751964884 21 0.7072354829804153 72 2 10 0.9750997948815278 20 0.6901877388114303 40 0.0196850393700787 50 240.0 51 420.0 73 0 72 1 10 0.9849423145665671 20 0.6731399946424452 11 0.9116177092135024 21 0.6308060140036307 72 1 10 0.9116177092135024 20 0.6308060140036307 11 0.9438676253896097 21 0.619068004457948 72 1 10 0.9438676253896097 20 0.619068004457948 11 1.045801742431874 21 0.6779196943719056 72 2 10 1.055644262116914 20 0.6608719502029206 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 1.065486781801953 20 0.6438242060339354 11 0.992162176448888 21 0.6014902253951211 72 1 10 0.992162176448888 20 0.6014902253951211 11 1.024412092624995 21 0.5897522158494382 72 1 10 1.024412092624995 20 0.5897522158494382 11 1.12634620966726 21 0.6486039057633959 72 2 10 1.136188729352299 20 0.6315561615944107 40 0.0196850393700788 50 240.0000000000002 51 420.0000000000003 73 0 72 1 10 1.146031249037339 20 0.6145084174254256 11 1.072706643684274 21 0.5721744367866111 72 1 10 1.072706643684274 20 0.5721744367866111 11 1.104956559860381 21 0.5604364272409283 72 1 10 1.104956559860381 20 0.5604364272409283 11 1.206890676902646 21 0.6192881171548861 72 2 10 1.216733196587685 20 0.6022403729859009 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 1.226575716272724 20 0.5851926288169159 11 1.15325111091966 21 0.5428586481781015 72 1 10 1.15325111091966 20 0.5428586481781015 11 1.185501027095767 21 0.5311206386324185 72 1 10 1.185501027095767 20 0.5311206386324185 11 1.287435144138031 21 0.5899723285463763 72 2 10 1.297277663823071 20 0.5729245843773911 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 1.30712018350811 20 0.5558768402084061 11 1.233795578155045 21 0.5135428595695918 72 1 10 1.233795578155045 20 0.5135428595695918 11 1.266045494331153 21 0.5018048500239088 72 1 10 1.266045494331153 20 0.5018048500239088 11 1.367979611373417 21 0.5606565399378665 72 2 10 1.377822131058456 20 0.5436087957688814 40 0.0196850393700787 50 240.0 51 420.0 73 0 72 1 10 1.387664650743496 20 0.5265610515998964 11 1.314340045390431 21 0.4842270709610819 72 1 10 1.314340045390431 20 0.4842270709610819 11 1.346589961566538 21 0.4724890614153991 72 1 10 1.346589961566538 20 0.4724890614153991 11 1.448524078608803 21 0.5313407513293568 72 2 10 1.458366598293842 20 0.5142930071603717 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 1.468209117978881 20 0.4972452629913866 11 1.394884512625817 21 0.4549112823525721 72 1 10 1.394884512625817 20 0.4549112823525721 11 1.427134428801924 21 0.4431732728068893 72 1 10 1.427134428801924 20 0.4431732728068893 11 1.529068545844188 21 0.5020249627208471 72 2 10 1.538911065529228 20 0.4849772185518619 40 0.0196850393700788 50 240.0000000000002 51 420.0000000000002 73 0 72 1 10 1.548753585214267 20 0.4679294743828769 11 1.475428979861203 21 0.4255954937440624 72 1 10 1.475428979861203 20 0.4255954937440624 11 1.50767889603731 21 0.4138574841983796 72 1 10 1.50767889603731 20 0.4138574841983796 11 1.609613013079574 21 0.4727091741123373 72 2 10 1.619455532764613 20 0.4556614299433522 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 1.629298052449653 20 0.4386136857743671 11 1.555973447096588 21 0.3962797051355528 72 1 10 1.555973447096588 20 0.3962797051355528 11 1.588223363272695 21 0.3845416955898698 72 1 10 1.588223363272695 20 0.3845416955898698 11 1.69015748031496 21 0.4433933855038275 72 2 10 1.699999999999999 20 0.4263456413348424 40 0.0196850393700788 50 240.0000000000001 51 420.0000000000001 73 0 72 1 10 1.709842519685038 20 0.4092978971658573 11 1.636517914331974 21 0.366963916527043 72 1 10 1.636517914331974 20 0.366963916527043 11 1.980314960629922 21 0.2418320250459505 72 1 10 1.980314960629922 20 0.2418320250459505 11 1.980314960629921 21 0.4884064321643613 72 1 10 1.980314960629921 20 0.4884064321643613 11 0.211518030839291 21 1.132195865069596 97 1 330 12B7 75 0 76 1 98 1 10 0.0 20 0.0 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 ENDSEC 0 SECTION 2 OBJECTS 0 DICTIONARY 5 C 330 0 100 AcDbDictionary 281 1 3 ACAD_DETAILVIEWSTYLE 350 122 3 ACAD_GROUP 350 D 3 ACAD_IMAGE_DICT 350 124 3 ACAD_IMAGE_VARS 350 DC 3 ACAD_LAYOUT 350 1A 3 ACAD_MLINESTYLE 350 17 3 ACAD_PLOTSETTINGS 350 19 3 ACAD_PLOTSTYLENAME 350 E 3 ACAD_SCALELIST 350 B6 3 ACAD_SECTIONVIEWSTYLE 350 123 3 AcDbVariableDictionary 350 66 3 APPDATA 350 E1 3 DWGPROPS 350 1B44 0 DICTIONARY 5 133 330 2 100 AcDbDictionary 280 1 281 1 3 ACAD_LAYERSTATES 360 134 3 ACLYDICTIONARY 360 C6B 0 DICTIONARY 5 C3A 330 1F 100 AcDbDictionary 280 1 281 1 3 ACAD_SORTENTS 360 C3B 0 DICTIONARY 5 122 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 DICTIONARY 5 D 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 DICTIONARY 5 124 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 RASTERVARIABLES 5 DC 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbRasterVariables 90 0 70 1 71 1 72 5 0 DICTIONARY 5 1A 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 Model 350 22 3 Sheet1 350 59 3 Sheet2 350 5E 0 DICTIONARY 5 17 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 Standard 350 18 0 DICTIONARY 5 19 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 ACDBDICTIONARYWDFLT 5 E 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 Normal 350 F 100 AcDbDictionaryWithDefault 340 F 0 DICTIONARY 5 B6 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 A0 350 B7 3 A1 350 B8 3 A2 350 B9 3 A3 350 BA 3 A4 350 BB 3 A5 350 BC 3 A6 350 BD 3 A7 350 BE 3 A8 350 BF 3 A9 350 C0 3 B0 350 C1 3 B1 350 C2 3 B2 350 C3 3 B3 350 C4 3 B4 350 C5 3 B5 350 C6 3 B6 350 C7 3 B7 350 C8 3 B8 350 C9 3 B9 350 CA 3 C0 350 CB 3 C1 350 CC 3 C2 350 CD 3 C3 350 CE 3 C4 350 CF 3 C5 350 D0 3 C6 350 D1 3 C7 350 D2 3 C8 350 D3 3 C9 350 D4 3 D0 350 D5 3 D1 350 D6 3 D2 350 D7 0 DICTIONARY 5 123 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 DICTIONARY 5 66 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 DIMASSOC 350 67 3 HIDETEXT 350 6B 0 DICTIONARY 5 E1 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 XRECORD 5 1B44 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbXrecord 280 1 1 DWGPROPS COOKIE 2 vector-logo 3 4 Jonathan Greig 6 Original Art by Damien George 7 micropython logo 8 9 300 = 301 = 302 = 303 = 304 = 305 = 306 = 307 = 308 = 309 = 40 0.0 41 2452643.063384271 42 2456661.002361111 1 90 0 0 DICTIONARY 5 134 102 {ACAD_REACTORS 330 133 102 } 330 133 100 AcDbDictionary 281 1 3 ARGON_LAYERP_1 350 135 3 ARGON_LAYERP_10 350 C21 3 ARGON_LAYERP_11 350 C22 3 ARGON_LAYERP_12 350 C23 3 ARGON_LAYERP_13 350 C26 3 ARGON_LAYERP_14 350 C29 3 ARGON_LAYERP_15 350 C2A 3 ARGON_LAYERP_16 350 C2B 3 ARGON_LAYERP_17 350 C2D 3 ARGON_LAYERP_18 350 C30 3 ARGON_LAYERP_19 350 C31 3 ARGON_LAYERP_2 350 4B1 3 ARGON_LAYERP_20 350 C33 3 ARGON_LAYERP_21 350 C38 3 ARGON_LAYERP_22 350 C3C 3 ARGON_LAYERP_23 350 C3D 3 ARGON_LAYERP_24 350 C3E 3 ARGON_LAYERP_25 350 C41 3 ARGON_LAYERP_26 350 C42 3 ARGON_LAYERP_27 350 C43 3 ARGON_LAYERP_28 350 C44 3 ARGON_LAYERP_29 350 C46 3 ARGON_LAYERP_3 350 6CF 3 ARGON_LAYERP_30 350 C49 3 ARGON_LAYERP_31 350 C4C 3 ARGON_LAYERP_32 350 C4F 3 ARGON_LAYERP_33 350 C52 3 ARGON_LAYERP_34 350 C54 3 ARGON_LAYERP_35 350 C55 3 ARGON_LAYERP_36 350 C56 3 ARGON_LAYERP_37 350 C57 3 ARGON_LAYERP_38 350 C58 3 ARGON_LAYERP_39 350 C59 3 ARGON_LAYERP_4 350 B84 3 ARGON_LAYERP_40 350 C5A 3 ARGON_LAYERP_41 350 C5B 3 ARGON_LAYERP_42 350 C5D 3 ARGON_LAYERP_43 350 C5F 3 ARGON_LAYERP_44 350 C60 3 ARGON_LAYERP_45 350 C61 3 ARGON_LAYERP_46 350 C62 3 ARGON_LAYERP_47 350 C63 3 ARGON_LAYERP_48 350 C64 3 ARGON_LAYERP_49 350 C65 3 ARGON_LAYERP_5 350 B89 3 ARGON_LAYERP_50 350 C66 3 ARGON_LAYERP_51 350 C67 3 ARGON_LAYERP_52 350 C68 3 ARGON_LAYERP_53 350 C6A 3 ARGON_LAYERP_54 350 C6F 3 ARGON_LAYERP_55 350 C70 3 ARGON_LAYERP_56 350 C71 3 ARGON_LAYERP_57 350 C72 3 ARGON_LAYERP_58 350 C73 3 ARGON_LAYERP_59 350 D92 3 ARGON_LAYERP_6 350 BB5 3 ARGON_LAYERP_60 350 D93 3 ARGON_LAYERP_61 350 1244 3 ARGON_LAYERP_62 350 1B1D 3 ARGON_LAYERP_63 350 1B1E 3 ARGON_LAYERP_64 350 1B1F 3 ARGON_LAYERP_65 350 1B20 3 ARGON_LAYERP_66 350 1B21 3 ARGON_LAYERP_67 350 1B22 3 ARGON_LAYERP_68 350 1B23 3 ARGON_LAYERP_69 350 1B24 3 ARGON_LAYERP_7 350 BF7 3 ARGON_LAYERP_70 350 1B25 3 ARGON_LAYERP_71 350 1B26 3 ARGON_LAYERP_72 350 1B27 3 ARGON_LAYERP_73 350 1B28 3 ARGON_LAYERP_74 350 1B29 3 ARGON_LAYERP_75 350 1B2C 3 ARGON_LAYERP_76 350 1B2D 3 ARGON_LAYERP_77 350 1B2E 3 ARGON_LAYERP_78 350 1B2F 3 ARGON_LAYERP_79 350 1B30 3 ARGON_LAYERP_8 350 BF9 3 ARGON_LAYERP_80 350 1B31 3 ARGON_LAYERP_81 350 1B32 3 ARGON_LAYERP_82 350 1B33 3 ARGON_LAYERP_83 350 1B34 3 ARGON_LAYERP_84 350 1B35 3 ARGON_LAYERP_85 350 1B36 3 ARGON_LAYERP_86 350 1B37 3 ARGON_LAYERP_87 350 1B38 3 ARGON_LAYERP_88 350 1B39 3 ARGON_LAYERP_89 350 1B3A 3 ARGON_LAYERP_9 350 BFF 3 ARGON_LAYERP_90 350 1B3B 3 ARGON_LAYERP_91 350 1B3C 3 ARGON_LAYERP_92 350 1B3D 3 ARGON_LAYERP_93 350 1B3E 0 DICTIONARY 5 C6B 102 {ACAD_REACTORS 330 133 102 } 330 133 100 AcDbDictionary 281 1 1001 ACAD 1000 image/svg+xml micropython-1.12/logo/vector-logo.svg000066400000000000000000001131061357706137100177450ustar00rootroot00000000000000 image/svg+xml micropython-1.12/logo/vector-text-R2000.dxf000066400000000000000000002602011357706137100204530ustar00rootroot00000000000000 0 SECTION 2 HEADER 9 $ACADVER 1 AC1015 9 $ACADMAINTVER 70 6 9 $DWGCODEPAGE 3 ANSI_1252 9 $INSBASE 10 0.0 20 0.0 30 0.0 9 $EXTMIN 10 0.0000000000000001 20 0.0 30 0.0 9 $EXTMAX 10 3.692708053216686 20 0.6839852852251591 30 0.0 9 $LIMMIN 10 0.0 20 0.0 9 $LIMMAX 10 12.0 20 9.0 9 $ORTHOMODE 70 0 9 $REGENMODE 70 1 9 $FILLMODE 70 1 9 $QTEXTMODE 70 0 9 $MIRRTEXT 70 1 9 $LTSCALE 40 1.0 9 $ATTMODE 70 1 9 $TEXTSIZE 40 0.2 9 $TRACEWID 40 0.05 9 $TEXTSTYLE 7 Standard 9 $CLAYER 8 TEXT-RED 9 $CELTYPE 6 ByLayer 9 $CECOLOR 62 256 9 $CELTSCALE 40 1.0 9 $DISPSILH 70 0 9 $DIMSCALE 40 1.0 9 $DIMASZ 40 0.18 9 $DIMEXO 40 0.0625 9 $DIMDLI 40 0.38 9 $DIMRND 40 0.0 9 $DIMDLE 40 0.0 9 $DIMEXE 40 0.18 9 $DIMTP 40 0.0 9 $DIMTM 40 0.0 9 $DIMTXT 40 0.18 9 $DIMCEN 40 0.09 9 $DIMTSZ 40 0.0 9 $DIMTOL 70 0 9 $DIMLIM 70 0 9 $DIMTIH 70 1 9 $DIMTOH 70 1 9 $DIMSE1 70 0 9 $DIMSE2 70 0 9 $DIMTAD 70 0 9 $DIMZIN 70 0 9 $DIMBLK 1 9 $DIMASO 70 1 9 $DIMSHO 70 1 9 $DIMPOST 1 9 $DIMAPOST 1 9 $DIMALT 70 0 9 $DIMALTD 70 2 9 $DIMALTF 40 25.4 9 $DIMLFAC 40 1.0 9 $DIMTOFL 70 0 9 $DIMTVP 40 0.0 9 $DIMTIX 70 0 9 $DIMSOXD 70 0 9 $DIMSAH 70 0 9 $DIMBLK1 1 9 $DIMBLK2 1 9 $DIMSTYLE 2 Standard 9 $DIMCLRD 70 0 9 $DIMCLRE 70 0 9 $DIMCLRT 70 0 9 $DIMTFAC 40 1.0 9 $DIMGAP 40 0.09 9 $DIMJUST 70 0 9 $DIMSD1 70 0 9 $DIMSD2 70 0 9 $DIMTOLJ 70 1 9 $DIMTZIN 70 0 9 $DIMALTZ 70 0 9 $DIMALTTZ 70 0 9 $DIMUPT 70 0 9 $DIMDEC 70 3 9 $DIMTDEC 70 3 9 $DIMALTU 70 2 9 $DIMALTTD 70 2 9 $DIMTXSTY 7 Standard 9 $DIMAUNIT 70 0 9 $DIMADEC 70 0 9 $DIMALTRND 40 0.0 9 $DIMAZIN 70 0 9 $DIMDSEP 70 46 9 $DIMATFIT 70 3 9 $DIMFRAC 70 0 9 $DIMLDRBLK 1 9 $DIMLUNIT 70 2 9 $DIMLWD 70 -2 9 $DIMLWE 70 -2 9 $DIMTMOVE 70 2 9 $LUNITS 70 2 9 $LUPREC 70 3 9 $SKETCHINC 40 0.1 9 $FILLETRAD 40 0.5 9 $AUNITS 70 0 9 $AUPREC 70 0 9 $MENU 1 . 9 $ELEVATION 40 0.0 9 $PELEVATION 40 0.0 9 $THICKNESS 40 0.0 9 $LIMCHECK 70 0 9 $CHAMFERA 40 0.0 9 $CHAMFERB 40 0.0 9 $CHAMFERC 40 0.0 9 $CHAMFERD 40 0.0 9 $SKPOLY 70 0 9 $TDCREATE 40 2456662.269745891 9 $TDUCREATE 40 2456662.519745903 9 $TDUPDATE 40 2456662.282164352 9 $TDUUPDATE 40 2456662.532164352 9 $TDINDWG 40 0.0000000116 9 $TDUSRTIMER 40 2456662.519895833 9 $USRTIMER 70 1 9 $ANGBASE 50 0.0 9 $ANGDIR 70 0 9 $PDMODE 70 0 9 $PDSIZE 40 0.0 9 $PLINEWID 40 0.0 9 $SPLFRAME 70 0 9 $SPLINETYPE 70 6 9 $SPLINESEGS 70 8 9 $HANDSEED 5 1D7 9 $SURFTAB1 70 6 9 $SURFTAB2 70 6 9 $SURFTYPE 70 6 9 $SURFU 70 6 9 $SURFV 70 6 9 $UCSBASE 2 9 $UCSNAME 2 9 $UCSORG 10 0.0 20 0.0 30 0.0 9 $UCSXDIR 10 1.0 20 0.0 30 0.0 9 $UCSYDIR 10 0.0 20 1.0 30 0.0 9 $UCSORTHOREF 2 9 $UCSORTHOVIEW 70 0 9 $UCSORGTOP 10 0.0 20 0.0 30 0.0 9 $UCSORGBOTTOM 10 0.0 20 0.0 30 0.0 9 $UCSORGLEFT 10 0.0 20 0.0 30 0.0 9 $UCSORGRIGHT 10 0.0 20 0.0 30 0.0 9 $UCSORGFRONT 10 0.0 20 0.0 30 0.0 9 $UCSORGBACK 10 0.0 20 0.0 30 0.0 9 $PUCSBASE 2 9 $PUCSNAME 2 9 $PUCSORG 10 0.0 20 0.0 30 0.0 9 $PUCSXDIR 10 1.0 20 0.0 30 0.0 9 $PUCSYDIR 10 0.0 20 1.0 30 0.0 9 $PUCSORTHOREF 2 9 $PUCSORTHOVIEW 70 0 9 $PUCSORGTOP 10 0.0 20 0.0 30 0.0 9 $PUCSORGBOTTOM 10 0.0 20 0.0 30 0.0 9 $PUCSORGLEFT 10 0.0 20 0.0 30 0.0 9 $PUCSORGRIGHT 10 0.0 20 0.0 30 0.0 9 $PUCSORGFRONT 10 0.0 20 0.0 30 0.0 9 $PUCSORGBACK 10 0.0 20 0.0 30 0.0 9 $USERI1 70 0 9 $USERI2 70 0 9 $USERI3 70 0 9 $USERI4 70 0 9 $USERI5 70 0 9 $USERR1 40 0.0 9 $USERR2 40 0.0 9 $USERR3 40 0.0 9 $USERR4 40 0.0 9 $USERR5 40 0.0 9 $WORLDVIEW 70 1 9 $SHADEDGE 70 3 9 $SHADEDIF 70 70 9 $TILEMODE 70 1 9 $MAXACTVP 70 64 9 $PINSBASE 10 0.0 20 0.0 30 0.0 9 $PLIMCHECK 70 0 9 $PEXTMIN 10 1.000000000000000E+20 20 1.000000000000000E+20 30 1.000000000000000E+20 9 $PEXTMAX 10 -1.000000000000000E+20 20 -1.000000000000000E+20 30 -1.000000000000000E+20 9 $PLIMMIN 10 0.0 20 0.0 9 $PLIMMAX 10 0.0 20 0.0 9 $UNITMODE 70 0 9 $VISRETAIN 70 1 9 $PLINEGEN 70 0 9 $PSLTSCALE 70 1 9 $TREEDEPTH 70 3020 9 $CMLSTYLE 2 Standard 9 $CMLJUST 70 0 9 $CMLSCALE 40 1.0 9 $PROXYGRAPHICS 70 1 9 $MEASUREMENT 70 0 9 $CELWEIGHT 370 -1 9 $ENDCAPS 280 0 9 $JOINSTYLE 280 0 9 $LWDISPLAY 290 0 9 $INSUNITS 70 0 9 $HYPERLINKBASE 1 9 $STYLESHEET 1 9 $XEDIT 290 1 9 $CEPSNTYPE 380 0 9 $PSTYLEMODE 290 1 9 $FINGERPRINTGUID 2 {394BC0E0-D500-95D9-65ED-9BB4C8BE75F1} 9 $VERSIONGUID 2 {FAEB1C32-E019-11D5-929B-00C0DF256EC4} 9 $EXTNAMES 290 1 9 $PSVPSCALE 40 0.0 9 $OLESTARTUP 290 0 0 ENDSEC 0 SECTION 2 CLASSES 0 CLASS 1 ACDBDICTIONARYWDFLT 2 AcDbDictionaryWithDefault 3 ObjectDBX Classes 90 0 280 0 281 0 0 CLASS 1 SCALE 2 AcDbScale 3 ObjectDBX Classes 90 1153 280 0 281 0 0 CLASS 1 VISUALSTYLE 2 AcDbVisualStyle 3 ObjectDBX Classes 90 4095 280 0 281 0 0 CLASS 1 MATERIAL 2 AcDbMaterial 3 ObjectDBX Classes 90 1153 280 0 281 0 0 CLASS 1 TABLESTYLE 2 AcDbTableStyle 3 ObjectDBX Classes 90 4095 280 0 281 0 0 CLASS 1 SUN 2 AcDbSun 3 SCENEOE 90 1153 280 0 281 0 0 CLASS 1 RASTERVARIABLES 2 AcDbRasterVariables 3 ISM 90 0 280 0 281 0 0 CLASS 1 DICTIONARYVAR 2 AcDbDictionaryVar 3 ObjectDBX Classes 90 0 280 0 281 0 0 CLASS 1 ACDBPLACEHOLDER 2 AcDbPlaceHolder 3 ObjectDBX Classes 90 0 280 0 281 0 0 CLASS 1 LAYOUT 2 AcDbLayout 3 ObjectDBX Classes 90 0 280 0 281 0 0 ENDSEC 0 SECTION 2 TABLES 0 TABLE 2 VPORT 5 8 330 0 100 AcDbSymbolTable 70 1 0 VPORT 5 22 330 8 100 AcDbSymbolTableRecord 100 AcDbViewportTableRecord 2 *ACTIVE 70 0 10 0.0 20 0.0 11 1.0 21 1.0 12 1.846354026608343 22 0.3419926426125796 13 0.0 23 0.0 14 10.0 24 10.0 15 10.0 25 10.0 16 0.0 26 0.0 36 1.0 17 0.0 27 0.0 37 0.0 40 1.733730323509535 41 2.172519083969465 42 50.0 43 0.0 44 0.0 50 0.0 51 0.0 71 16 72 100 73 1 74 1 75 0 76 0 77 0 78 0 281 0 65 0 110 0.0 120 0.0 130 0.0 111 1.0 121 0.0 131 0.0 112 0.0 122 1.0 132 0.0 79 0 146 0.0 0 ENDTAB 0 TABLE 2 LTYPE 5 5 330 0 100 AcDbSymbolTable 70 1 0 LTYPE 5 14 330 5 100 AcDbSymbolTableRecord 100 AcDbLinetypeTableRecord 2 ByBlock 70 0 3 72 65 73 0 40 0.0 0 LTYPE 5 15 330 5 100 AcDbSymbolTableRecord 100 AcDbLinetypeTableRecord 2 ByLayer 70 0 3 72 65 73 0 40 0.0 0 LTYPE 5 16 330 5 100 AcDbSymbolTableRecord 100 AcDbLinetypeTableRecord 2 CONTINUOUS 70 0 3 Solid line 72 65 73 0 40 0.0 0 ENDTAB 0 TABLE 2 LAYER 5 2 102 {ACAD_XDICTIONARY 360 1B3 102 } 330 0 100 AcDbSymbolTable 70 3 0 LAYER 5 10 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 0 70 0 62 7 6 CONTINUOUS 370 -3 390 F 0 LAYER 5 21 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 TEXT-GRAY 70 0 62 254 6 CONTINUOUS 370 -3 390 F 0 LAYER 5 1B9 330 2 100 AcDbSymbolTableRecord 100 AcDbLayerTableRecord 2 TEXT-RED 70 0 62 1 6 CONTINUOUS 370 -3 390 F 1001 AcAecLayerStandard 1000 1000 0 ENDTAB 0 TABLE 2 STYLE 5 3 330 0 100 AcDbSymbolTable 70 1 0 STYLE 5 11 330 3 100 AcDbSymbolTableRecord 100 AcDbTextStyleTableRecord 2 Standard 70 0 40 0.0 41 1.0 50 0.0 71 0 42 0.2 3 txt 4 0 ENDTAB 0 TABLE 2 VIEW 5 6 330 0 100 AcDbSymbolTable 70 0 0 ENDTAB 0 TABLE 2 UCS 5 7 330 0 100 AcDbSymbolTable 70 0 0 ENDTAB 0 TABLE 2 APPID 5 9 330 0 100 AcDbSymbolTable 70 2 0 APPID 5 12 330 9 100 AcDbSymbolTableRecord 100 AcDbRegAppTableRecord 2 ACAD 70 0 0 APPID 5 1BA 330 9 100 AcDbSymbolTableRecord 100 AcDbRegAppTableRecord 2 AcAecLayerStandard 70 0 0 ENDTAB 0 TABLE 2 DIMSTYLE 5 A 330 0 100 AcDbSymbolTable 70 1 100 AcDbDimStyleTable 0 DIMSTYLE 105 23 330 A 100 AcDbSymbolTableRecord 100 AcDbDimStyleTableRecord 2 Standard 70 0 178 0 340 11 0 ENDTAB 0 TABLE 2 BLOCK_RECORD 5 1 330 0 100 AcDbSymbolTable 70 0 0 BLOCK_RECORD 5 1D 330 1 100 AcDbSymbolTableRecord 100 AcDbBlockTableRecord 2 *Model_Space 340 1E 0 BLOCK_RECORD 5 1B 330 1 100 AcDbSymbolTableRecord 100 AcDbBlockTableRecord 2 *Paper_Space 340 1C 0 ENDTAB 0 ENDSEC 0 SECTION 2 BLOCKS 0 BLOCK 5 18D 330 1D 100 AcDbEntity 8 0 100 AcDbBlockBegin 2 *Model_Space 70 0 10 0.0 20 0.0 30 0.0 3 *Model_Space 1 *Model_Space 0 ENDBLK 5 18E 330 1D 100 AcDbEntity 8 0 100 AcDbBlockEnd 0 BLOCK 5 18F 330 1B 100 AcDbEntity 67 1 8 0 100 AcDbBlockBegin 2 *Paper_Space 70 0 10 0.0 20 0.0 30 0.0 3 *Paper_Space 1 *Paper_Space 0 ENDBLK 5 190 330 1B 100 AcDbEntity 67 1 8 0 100 AcDbBlockEnd 0 ENDSEC 0 SECTION 2 ENTITIES 0 LWPOLYLINE 5 24 102 {ACAD_REACTORS 330 1BD 102 } 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbPolyline 90 14 70 1 43 0.0 10 0.0000000000000001 20 0.1752767944487085 10 0.0416193345059499 20 0.6506897567371471 10 0.1681431038010463 20 0.6506897567371471 10 0.247338516041492 20 0.3260572124180542 10 0.3260590389156172 20 0.6506897567371471 10 0.4521056357224397 20 0.6506897567371471 10 0.4963403625301471 20 0.1752767944487085 10 0.4066806413363264 20 0.1752767944487085 10 0.3752877144762009 20 0.4930112663057366 10 0.2987087599944248 20 0.1752767944487085 10 0.1973944622688229 20 0.1752767944487085 10 0.1174851938975943 20 0.4930112663057366 10 0.0896600256100814 20 0.1752767944487085 10 0.0000000000000001 20 0.1752767944487085 0 LWPOLYLINE 5 34 102 {ACAD_REACTORS 330 1BE 102 } 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbPolyline 90 5 70 1 43 0.0 10 0.5505660310062117 20 0.1752767944487085 10 0.5505660310062117 20 0.5201225784624666 10 0.6416519423802962 20 0.5201225784624666 10 0.6416519423802962 20 0.1752767944487085 10 0.5505660310062117 20 0.1752767944487085 0 LWPOLYLINE 5 3B 102 {ACAD_REACTORS 330 1BF 102 } 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbPolyline 90 13 70 1 43 0.0 10 0.5474731617999196 20 0.5714928224153991 10 0.5474731617999196 20 0.6288098380164536 42 -0.1883074803638932 10 0.5513377262264826 20 0.6414735544516654 42 -0.2159435161643535 10 0.5629314195061711 20 0.6456942859029685 10 0.6311876334269211 20 0.6456942859029685 42 -0.2288445935800111 10 0.6418909091447587 20 0.6414735544516654 42 -0.1763562374232752 10 0.6454571456360689 20 0.6288098380164536 10 0.6454571456360689 20 0.5714928224153991 42 -0.1943541296589125 10 0.6418909091447587 20 0.5602568182417533 42 -0.2096410684182619 10 0.6311876334269211 20 0.5565109761567706 10 0.5629314195061711 20 0.5565109761567706 42 -0.1965331617699563 10 0.551636054161735 20 0.5604349017541234 42 -0.2135460038275524 10 0.5474731617999196 20 0.5714928224153991 0 LWPOLYLINE 5 4A 102 {ACAD_REACTORS 330 1C5 102 } 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbPolyline 90 12 70 1 43 0.0 10 1.855753791898883 20 0.5703040769182958 10 1.749208100737245 20 0.5703040769182958 10 1.749208100737245 20 0.4311767133994287 10 1.855281946695168 20 0.4311767133994287 42 0.1378892503752188 10 1.880487613061407 20 0.4371219629662482 42 0.1061516643405155 10 1.890061504452931 20 0.4460702789425233 42 0.0752237691491799 10 1.896895649500299 20 0.460071904842465 42 0.0778530288832081 10 1.902359921375588 20 0.5032381305759515 42 0.0564276025149389 10 1.899452746088178 20 0.5325792918405643 42 0.095076106856608 10 1.890715999412924 20 0.5535383513733607 42 0.1319298941216669 10 1.876149681349825 20 0.5661122650117364 42 0.1129501247093477 10 1.855753791898883 20 0.5703040769182958 0 LWPOLYLINE 5 58 102 {ACAD_REACTORS 330 1C7 102 } 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbPolyline 90 23 70 1 43 0.0 10 2.401085080890193 20 0.451391475175396 10 2.401085080890193 20 0.502049385078848 10 2.456975906310984 20 0.5208364345932495 10 2.471953186325706 20 0.6169178168015124 10 2.547828939245814 20 0.6169178168015124 10 2.547828939245814 20 0.5208364345932495 10 2.625120227777072 20 0.5208364345932495 10 2.625120227777072 20 0.451391475175396 10 2.547828939245814 20 0.451391475175396 10 2.547828939245814 20 0.312977967787312 42 0.0356379455033458 10 2.549609774369517 20 0.2833386307955768 42 0.0811642329835157 10 2.554952279740622 20 0.2643422951021078 42 0.1858874482849488 10 2.577068121063173 20 0.244721753866562 42 0.0076184446139192 10 2.607448863857263 20 0.2345547073915278 42 0.0469611640188665 10 2.620599646309214 20 0.2311657933719365 10 2.620599646309214 20 0.1752767944487085 10 2.541405756150071 20 0.1752767944487085 42 -0.1146121843643247 10 2.504464842943029 20 0.1829913113213321 42 -0.132229815857891 10 2.478071953160988 20 0.2061345575229422 42 -0.0940182241125145 10 2.462242307616974 20 0.2447068374697993 42 -0.0555506677049525 10 2.456975906310984 20 0.2987081511619036 10 2.456975906310984 20 0.451391475175396 10 2.401085080890193 20 0.451391475175396 0 LWPOLYLINE 5 71 102 {ACAD_REACTORS 330 1CA 102 } 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbPolyline 90 22 70 1 43 0.0 10 3.589495720107105 20 0.5260693501105883 42 -0.0932412511784359 10 3.634655872346617 20 0.5185183047698327 42 -0.1254375778784052 10 3.666908775142547 20 0.4958651687475662 42 -0.1084619648488494 10 3.686254428494896 20 0.4581099420437885 42 -0.0689905889343237 10 3.692708053216686 20 0.4052541467398021 10 3.692708053216686 20 0.1752767944487085 10 3.601870241094878 20 0.1752767944487085 10 3.601870241094878 20 0.4064428922369056 42 0.0660852200863579 10 3.59946535263723 20 0.4269407611351025 42 0.1056585132217627 10 3.592296349703354 20 0.4415816611820138 42 0.1272161701661909 10 3.580317569854181 20 0.4503655923776398 42 0.0972102752618352 10 3.56357467552878 20 0.4532940768032824 42 0.0885878555139059 10 3.519221226379493 20 0.4465162487641 42 0.077710311269079 10 3.480332049105495 20 0.4233288622047228 10 3.480332049105495 20 0.1752767944487085 10 3.389479016170664 20 0.1752767944487085 10 3.389479016170664 20 0.5201225784624666 10 3.462264944047086 20 0.5201225784624666 10 3.480332049105495 20 0.4832608134831443 42 -0.0353892151285229 10 3.522843779878989 20 0.5102534032982943 42 -0.0728322192286089 10 3.555720736008866 20 0.5227390362211358 42 -0.0544633437581111 10 3.589495720107105 20 0.5260693501105883 0 LWPOLYLINE 5 89 102 {ACAD_REACTORS 330 1C6 102 } 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbPolyline 90 17 70 1 43 0.0 10 2.026516093204943 20 0.5201225784624666 10 2.12187448679461 20 0.5201225784624666 10 2.181814048479542 20 0.2784929327615455 42 0.1680883445175794 10 2.192925241986399 20 0.2601209548182838 42 0.1691212946679427 10 2.213442897941526 20 0.2539970129065732 42 0.0518086164809523 10 2.216060877781497 20 0.2532834611920508 10 2.285026381589124 20 0.5201225784624666 10 2.379912929975073 20 0.5201225784624666 10 2.2602925604266 20 0.0661149499446615 10 2.21297105273781 20 0.0 10 2.147795531372934 20 0.0 10 2.196547795485895 20 0.1752767944487085 42 -0.0815316895695442 10 2.160444026995122 20 0.1807616144215795 42 -0.0970784439939463 10 2.131326611681949 20 0.1972162265483224 42 -0.0875143454723418 10 2.109195549546374 20 0.2246403264126769 42 -0.0638836232247607 10 2.094050840588399 20 0.2630342184309034 10 2.026516093204943 20 0.5201225784624666 0 LWPOLYLINE 5 9C 102 {ACAD_REACTORS 330 1C8 102 } 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbPolyline 90 22 70 1 43 0.0 10 2.66863653221009 20 0.1752767944487085 10 2.66863653221009 20 0.683985285225159 10 2.758774186932835 20 0.683985285225159 10 2.758774186932835 20 0.4832608134831443 42 -0.0349812911378511 10 2.80104238469796 20 0.5100159586151339 42 -0.0697958386932639 10 2.834162873836206 20 0.5227390362211358 42 -0.0522006296457192 10 2.868653236146531 20 0.5260693501105883 42 -0.0932412511784358 10 2.913798167573019 20 0.5185183047698327 42 -0.1254375778784047 10 2.946066291181972 20 0.4958651687475662 42 -0.1084619648488494 10 2.965411944534321 20 0.4581099420437885 42 -0.0689905889343073 10 2.971865569256112 20 0.4052541467398021 10 2.971865569256112 20 0.1752767944487085 10 2.881012536321281 20 0.1752767944487085 10 2.881012536321281 20 0.4064428922369056 42 0.0660852200863579 10 2.878622868676655 20 0.4269407611351025 42 0.1056585132217627 10 2.871438644929757 20 0.4415816611820138 42 0.1272161701661909 10 2.859475085893608 20 0.4503655923776398 42 0.0972102752618352 10 2.842716970755184 20 0.4532940768032824 42 0.088587855513906 10 2.798363521605896 20 0.4465162487641 42 0.0777103112690791 10 2.759489565144921 20 0.4233288622047228 10 2.759489565144921 20 0.1752767944487085 10 2.66863653221009 20 0.1752767944487085 0 LWPOLYLINE 5 B4 102 {ACAD_REACTORS 330 1C0 102 } 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbPolyline 90 34 70 1 43 0.0 10 0.6946873432779551 20 0.3481760979032103 42 -0.0229891281782208 10 0.6967086672474216 20 0.3959192221127403 42 -0.0328228697904816 10 0.7027741612371234 20 0.4354583281028243 42 -0.0483316739793035 10 0.7128214199136659 20 0.4666716493692773 42 -0.0727828188712317 10 0.7267941262688635 20 0.489443507733124 42 -0.1227899169725496 10 0.762229701067922 20 0.5157237634987931 42 -0.0944303865644604 10 0.8083670295035159 20 0.5234528923519188 42 -0.0315898411800418 10 0.8956492597031299 20 0.5183995824282526 42 -0.0456865147865019 10 0.9667593760657095 20 0.5032381305759515 10 0.9667593760657095 20 0.448776539498029 42 0.0070437593452633 10 0.8389882611433709 20 0.4484492920180325 42 0.0290350112768282 10 0.82418297631581 20 0.4474675495780431 42 0.0847606935358247 10 0.8076546954540353 20 0.4410458885636011 42 0.1825489438203349 10 0.7945739287419907 20 0.4249924970681467 42 0.0517789759014607 10 0.7877961007028083 20 0.3930348780448645 42 0.0296456838705223 10 0.7855358099688792 20 0.3499599771895165 42 0.0216618761660938 10 0.7870822445720254 20 0.3081910220915498 42 0.0471796273319681 10 0.7917200263001613 20 0.280157633081881 42 0.072662787539697 10 0.7993608744377529 20 0.262588400817457 42 0.1214661602111968 10 0.8099134641066621 20 0.2522132858283972 42 0.0832516876593145 10 0.8254021634389597 20 0.247129686486815 42 0.0435906078463293 10 0.8478467743228099 20 0.2454353055810845 42 0.021166726074658 10 0.9539175761181276 20 0.2499539083432495 10 0.9712784354522652 20 0.2513808595641643 10 0.9712784354522652 20 0.1940650616281518 42 -0.0978017422898016 10 0.9130101190372676 20 0.1759903461632311 42 -0.0233934475797722 10 0.8395225116804813 20 0.1719472415999074 10 0.8357173084247086 20 0.1719472415999074 42 -0.1019475670653864 10 0.7625265069218723 20 0.1805684623043164 42 -0.117873950403685 10 0.7277454270828068 20 0.2064319722094134 42 -0.0715503088956374 10 0.7132826105482655 20 0.2296496481867064 42 -0.0491245187935067 10 0.7029522447494936 20 0.2610127422533067 42 -0.0334830700706472 10 0.6967528076051885 20 0.3005215588254747 42 -0.023527584931374 10 0.6946873432779551 20 0.3481760979032103 0 LWPOLYLINE 5 D8 102 {ACAD_REACTORS 330 1C1 102 } 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbPolyline 90 16 70 1 43 0.0 10 1.020746077777311 20 0.1752767944487085 10 1.020746077777311 20 0.5201225784624666 10 1.097325032259088 20 0.5201225784624666 10 1.111594544468236 20 0.4766017077855419 42 -0.0805753976673698 10 1.160646658597752 20 0.5117404767306502 42 -0.1124747672601628 10 1.210292384435168 20 0.5234528923519188 42 -0.0241299749672376 10 1.233896821271378 20 0.5225015915379756 42 -0.060832138395251 10 1.248581861676056 20 0.519647689096146 10 1.248581861676056 20 0.4318905695302117 42 0.0248536783236681 10 1.199353186115472 20 0.4337931711580981 42 0.0387057739818888 10 1.170873522867967 20 0.4317718471886316 42 0.0551847743452131 10 1.147743975398077 20 0.4257063531989297 42 0.080499651857314 10 1.128480514436053 20 0.4141126599192412 42 0.0645077730986141 10 1.111594544468236 20 0.39550369391721 10 1.111594544468236 20 0.1752767944487085 10 1.020746077777311 20 0.1752767944487085 0 LWPOLYLINE 5 EA 102 {ACAD_REACTORS 330 1C9 102 } 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbPolyline 90 30 70 1 43 0.0 10 3.020617833369073 20 0.3410405807579851 42 -0.0409081205529831 10 3.025732026544832 20 0.4159559003763376 42 -0.0781599297384411 10 3.041896529975355 20 0.4673261443292702 42 -0.1364366144086533 10 3.072459922525721 20 0.5006216728172821 42 -0.0882009175036989 10 3.116752488422916 20 0.5177450874682596 42 -0.0529086836461284 10 3.177818390271558 20 0.5234528923519188 42 -0.0321103580647159 10 3.218868922994835 20 0.5210145181056196 42 -0.0444041287441238 10 3.253054869044698 20 0.5137024395293266 42 -0.0605636228964518 10 3.280406670047193 20 0.5015136124604352 42 -0.0762678881360705 10 3.300893884376273 20 0.4844495589802478 42 -0.0695139514449708 10 3.315825501951926 20 0.4611571488110112 42 -0.0499044136612151 10 3.326495291881113 20 0.4302847737562754 42 -0.0350340529330662 10 3.332888033350811 20 0.3918309117347381 42 -0.0250615206333876 10 3.335018947174044 20 0.3457970848277011 42 -0.0247570817049555 10 3.332933695789881 20 0.2998822846785048 42 -0.035093333100506 10 3.326632279198321 20 0.2617856551386192 42 -0.0509721690967282 10 3.316160359838434 20 0.2315076528324352 42 -0.0726634493786117 10 3.301487496084174 20 0.2090479733436921 42 -0.0773754337522631 10 3.281182931511371 20 0.1928163461277374 42 -0.0591962390389137 10 3.253800688882829 20 0.1812223484317884 42 -0.0423681953096553 10 3.219355989011574 20 0.174265980255845 42 -0.0302514249026995 10 3.177818390271558 20 0.1719472415999074 42 -0.0327640807112059 10 3.136935286491535 20 0.1744296039958433 42 -0.0448781589059774 10 3.10273411962865 20 0.1818763867673907 42 -0.060332284523739 10 3.075214889682901 20 0.1942878943308099 42 -0.0746618379907621 10 3.054392817467312 20 0.2116639744779708 42 -0.0666236365557017 10 3.03961340802189 20 0.2341087375699512 42 -0.0504061851560683 10 3.029065384596889 20 0.2631532451887439 42 -0.0367317311855017 10 3.022733526379283 20 0.2987971929180886 42 -0.0269050519350767 10 3.020617833369073 20 0.3410405807579851 0 LWPOLYLINE 5 10A 102 {ACAD_REACTORS 330 1C2 102 } 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbPolyline 90 21 70 1 43 0.0 10 1.390325682953593 20 0.4318905695302117 42 0.0242919032698246 10 1.38033778544784 20 0.3839084785562191 42 0.0375411437912006 10 1.377007471558388 20 0.3446083393305977 42 0.0398730504554166 10 1.38033778544784 20 0.2901464438364147 42 0.0541422102818605 10 1.38500448672072 20 0.2730230291854372 42 0.0823828350418203 10 1.392347006923059 20 0.2606561186041756 42 0.1602559612730944 10 1.412086879332706 20 0.2480513067153631 42 0.0555482263236158 10 1.442053616012568 20 0.2454353055810845 42 0.0316904222703728 10 1.470353673666401 20 0.2467432300441587 42 0.1007429782984575 10 1.488551677716809 20 0.2532834611920508 42 0.1818370389300056 10 1.501154510899928 20 0.2694555750290851 42 0.0526041808970857 10 1.507395044239396 20 0.2969244240837275 42 0.0324432335036989 10 1.50948029562356 20 0.3327178401969589 42 0.018652937942289 10 1.507927772695204 20 0.3912220792138144 42 0.0530768467862457 10 1.502463500819915 20 0.4224962837323597 42 0.1914595274942226 10 1.48998243414098 20 0.4402133100912379 42 0.0889989641192241 10 1.472167994578754 20 0.4475269107488332 42 0.0570509400215991 10 1.448236310262548 20 0.4499652849951324 42 0.0204219730568417 10 1.425137204418705 20 0.4491616260675131 42 0.045760246847436 10 1.409828110680079 20 0.4467536934472601 42 0.1785155631256146 10 1.390325682953593 20 0.4318905695302117 0 LWPOLYLINE 5 121 102 {ACAD_REACTORS 330 1C9 102 } 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbPolyline 90 21 70 1 43 0.0 10 3.124789077699108 20 0.4318905695302117 42 0.0242919032698246 10 3.114804224355961 20 0.3839084785562191 42 0.0375411437912007 10 3.111470866303904 20 0.3446083393305977 42 0.0398730504554166 10 3.114804224355961 20 0.2901464438364147 42 0.0541422102818607 10 3.119461793141027 20 0.2730230291854372 42 0.0823828350418199 10 3.12681344583118 20 0.2606561186041756 42 0.1602559612730945 10 3.146539619509106 20 0.2480513067153631 42 0.0555482263236158 10 3.176509400351572 20 0.2454353055810845 42 0.0316904222703728 10 3.204820112574522 20 0.2467432300441587 42 0.1007429782984576 10 3.223008984137115 20 0.2532834611920508 42 0.1818370389300056 10 3.235611817320236 20 0.2694555750290851 42 0.0526041808970857 10 3.241852350659703 20 0.2969244240837275 42 0.0324432335036989 10 3.243937602043866 20 0.3327178401969589 42 0.018652937942289 10 3.242385079115511 20 0.3912220792138144 42 0.0530768467862456 10 3.236920807240222 20 0.4224962837323597 42 0.1914595274942226 10 3.224439740561286 20 0.4402133100912379 42 0.0889989641192241 10 3.20663138932427 20 0.4475269107488332 42 0.0570509400215991 10 3.182689050438947 20 0.4499652849951324 42 0.0204219730568417 10 3.159599077082918 20 0.4491616260675131 42 0.045760246847436 10 3.144286939181689 20 0.4467536934472601 42 0.178515563125615 10 3.124789077699108 20 0.4318905695302117 0 LWPOLYLINE 5 138 102 {ACAD_REACTORS 330 1C5 102 } 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbPolyline 90 17 70 1 43 0.0 10 1.658111534794044 20 0.1752767944487085 10 1.658111534794044 20 0.6506897567371471 10 1.862892353206713 20 0.6506897567371471 42 -0.0918352741933524 10 1.923821267738147 20 0.6408190594916725 42 -0.133922059302927 10 1.965389308104209 20 0.6112100119178533 42 -0.1060028202258852 10 1.987322499670483 20 0.566558234833313 42 -0.0661506729116568 10 1.99464371073459 20 0.5039519867067345 42 -0.0710178368558241 10 1.985846080807243 20 0.4324841812381122 42 -0.0374247138640044 10 1.976089539659442 20 0.4061156447569091 42 -0.057718769966508 10 1.964430396883754 20 0.3867030198272586 42 -0.1271250474471338 10 1.932329702218055 20 0.3624456101123582 42 -0.110827379232239 10 1.875723498585179 20 0.3505535888974171 42 -0.0258396192335467 10 1.802480946318064 20 0.3564988384642365 42 -0.0037744416271255 10 1.763835302052436 20 0.3612568646152548 42 -0.0304647996844293 10 1.749208100737245 20 0.3636343556094617 10 1.749208100737245 20 0.1752767944487085 10 1.658111534794044 20 0.1752767944487085 0 LWPOLYLINE 5 14B 102 {ACAD_REACTORS 330 1C2 102 } 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbPolyline 90 30 70 1 43 0.0 10 1.286159004867464 20 0.3410405807579851 42 -0.040908120552983 10 1.29127167596192 20 0.4159559003763376 42 -0.0781599297384411 10 1.307443789798954 20 0.4673261443292702 42 -0.1364366144086534 10 1.338004138186717 20 0.5006216728172821 42 -0.088200917503699 10 1.382299748246516 20 0.5177450874682596 42 -0.0529086836461285 10 1.443361083851251 20 0.5234528923519188 42 -0.0321103580647177 10 1.484408572411924 20 0.5210145181056196 42 -0.0444041287441238 10 1.518597562624391 20 0.5137024395293266 42 -0.0605636228964518 10 1.545949363626886 20 0.5015136124604352 42 -0.0762678881361016 10 1.566436577955966 20 0.4844495589802478 42 -0.0695139514449315 10 1.581368195531619 20 0.4611571488110112 42 -0.0499044136612151 10 1.592037985460806 20 0.4302847737562754 42 -0.0350340529330662 10 1.598430726930504 20 0.3918309117347381 42 -0.0250615206333974 10 1.600561640753737 20 0.3457970848277011 42 -0.0247570817049556 10 1.59846116855655 20 0.2998822846785048 42 -0.035093333100506 10 1.592174972778014 20 0.2617856551386192 42 -0.0509721690967282 10 1.581703053418127 20 0.2315076528324352 42 -0.0726634493786118 10 1.567030189663867 20 0.2090479733436921 42 -0.0773754337522942 10 1.546725625091063 20 0.1928163461277374 42 -0.0591962390389137 10 1.519343382462522 20 0.1812223484317884 42 -0.0423681953096553 10 1.484891072184755 20 0.174265980255845 42 -0.0302514249026978 10 1.443361083851251 20 0.1719472415999074 42 -0.0327640807112059 10 1.402470369664717 20 0.1744296039958433 42 -0.0448781589059774 10 1.368267680720529 20 0.1818763867673907 42 -0.060332284523739 10 1.340754539099989 20 0.1942878943308099 42 -0.0746618379907621 10 1.319929422721796 20 0.2116639744779708 42 -0.0666236365556613 10 1.305154579520281 20 0.2341087375699512 42 -0.0504061851560684 10 1.294601989851372 20 0.2631532451887439 42 -0.0367317311855017 10 1.288268609552464 20 0.2987971929180886 42 -0.0269050519351071 10 1.286159004867464 20 0.3410405807579851 0 HATCH 5 1BD 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 14 72 1 10 0.0000000000000001 20 0.1752767944487085 11 0.0416193345059499 21 0.6506897567371471 72 1 10 0.0416193345059499 20 0.6506897567371471 11 0.1681431038010463 21 0.6506897567371471 72 1 10 0.1681431038010463 20 0.6506897567371471 11 0.247338516041492 21 0.3260572124180542 72 1 10 0.247338516041492 20 0.3260572124180542 11 0.3260590389156172 21 0.6506897567371471 72 1 10 0.3260590389156172 20 0.6506897567371471 11 0.4521056357224397 21 0.6506897567371471 72 1 10 0.4521056357224397 20 0.6506897567371471 11 0.4963403625301471 21 0.1752767944487085 72 1 10 0.4963403625301471 20 0.1752767944487085 11 0.4066806413363264 21 0.1752767944487085 72 1 10 0.4066806413363264 20 0.1752767944487085 11 0.3752877144762009 21 0.4930112663057366 72 1 10 0.3752877144762009 20 0.4930112663057366 11 0.2987087599944248 21 0.1752767944487085 72 1 10 0.2987087599944248 20 0.1752767944487085 11 0.1973944622688229 21 0.1752767944487085 72 1 10 0.1973944622688229 20 0.1752767944487085 11 0.1174851938975943 21 0.4930112663057366 72 1 10 0.1174851938975943 20 0.4930112663057366 11 0.0896600256100814 21 0.1752767944487085 72 1 10 0.0896600256100814 20 0.1752767944487085 11 0.0000000000000001 21 0.1752767944487085 72 1 10 0.0000000000000001 20 0.1752767944487085 11 0.0000000000000001 21 0.1752767944487085 97 1 330 24 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1BE 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 5 72 1 10 0.5505660310062117 20 0.1752767944487085 11 0.5505660310062117 21 0.5201225784624666 72 1 10 0.5505660310062117 20 0.5201225784624666 11 0.6416519423802962 21 0.5201225784624666 72 1 10 0.6416519423802962 20 0.5201225784624666 11 0.6416519423802962 21 0.1752767944487085 72 1 10 0.6416519423802962 20 0.1752767944487085 11 0.5505660310062117 21 0.1752767944487085 72 1 10 0.5505660310062117 20 0.1752767944487085 11 0.5505660310062117 21 0.1752767944487085 97 1 330 34 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1BF 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 13 72 1 10 0.5474731617999196 20 0.5714928224153991 11 0.5474731617999196 21 0.6288098380164536 72 2 10 0.5656218268345913 20 0.630192970755272 40 0.0182012938747197 50 175.6418407014946 51 218.2992114073367 73 0 72 2 10 0.5617930966007493 20 0.6307876795407876 40 0.0149500064305679 50 225.6246753032742 51 274.3668398711414 73 0 72 1 10 0.5629314195061711 20 0.6456942859029685 11 0.6311876334269211 21 0.6456942859029685 72 2 10 0.6321698296440981 20 0.6325035330064808 40 0.0132272699898821 50 265.7415594617891 51 317.3010585925538 73 0 72 2 10 0.6262804611730807 20 0.6302434840168466 40 0.0192301993709753 50 324.2689673804306 51 364.2754703081528 73 0 72 1 10 0.6454571456360689 20 0.6288098380164536 11 0.6454571456360689 21 0.5714928224153991 72 2 10 0.6297669641888812 20 0.5702888340215038 40 0.0157363077593922 50 355.611999000231 51 399.6062175218991 73 0 72 2 10 0.6322686211170757 20 0.5705867464421508 40 0.0141172179806454 50 47.03124341518984 51 94.39156764264102 73 0 72 1 10 0.6311876334269211 20 0.5565109761567706 11 0.5629314195061711 21 0.5565109761567706 72 2 10 0.5620823708457157 20 0.572286229491247 40 0.0157980853711685 50 86.91922452913958 51 131.3944660406891 73 0 72 2 10 0.5619098596911134 20 0.570615150925454 40 0.0144633520750158 50 135.2620677004958 51 183.4789850614727 73 0 72 1 10 0.5474731617999196 20 0.5714928224153991 11 0.5474731617999196 21 0.5714928224153991 97 1 330 3B 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1C0 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 34 72 2 10 1.214616030315336 20 0.350077974119305 40 0.5199321655154222 50 179.7904154992175 51 185.0582076977404 73 0 72 2 10 1.000572124284262 20 0.3695398595471971 40 0.3050063463138826 50 184.961591177561 51 192.4813391512255 73 0 72 2 10 0.8688743989493632 20 0.3992160253637114 40 0.170008215907044 50 192.3087569665484 51 203.3769478223085 73 0 72 2 10 0.7976119460679242 20 0.4303172999651613 40 0.0922554716323781 50 203.2074684948184 51 219.8587008780153 73 0 72 2 10 0.7972117188097253 20 0.4315246663413517 40 0.0911769133466147 50 219.4374770529955 51 247.4386863416477 73 0 72 2 10 0.8055784036639897 20 0.398531115770543 40 0.124952897918856 50 249.7009350090099 51 271.2787999327404 73 0 72 2 10 0.8120564786102148 20 -0.1691304899318403 40 0.6925932092147039 50 269.6947835186498 51 276.9322349981942 73 0 72 2 10 0.8484128964611991 20 0.1225112149529162 40 0.3986964678983381 50 276.8042143326444 51 287.2675164228719 73 0 72 1 10 0.9667593760657095 20 0.5032381305759515 11 0.9667593760657095 21 0.448776539498029 72 2 10 0.9144880443227094 20 -4.086066981505726 40 4.535144766389704 50 89.3396036583715 51 90.9538876909594 73 1 72 2 10 0.8400315841062043 20 0.3205880251107224 40 0.1278655234922502 50 90.46751199340585 51 97.1199774171112 73 1 72 2 10 0.8347233227483223 20 0.3958571165940125 40 0.0526757600392865 50 101.54272561012 51 120.9221245987022 73 1 72 2 10 0.8223667308685831 20 0.4157021086294436 40 0.029304456442492 50 120.1351163505028 51 161.5166003585789 73 1 72 2 10 0.9450695696956614 20 0.3763766174814469 40 0.1581532222056973 50 162.0975481756131 51 173.9538270794763 73 1 72 2 10 1.149594366372439 20 0.3524533042818777 40 0.3640670943255288 50 173.6000944629489 51 180.3923953532557 73 1 72 2 10 1.268138893295446 20 0.346914547227496 40 0.4826126922076991 50 179.638444150984 51 184.6022041776311 73 1 72 2 10 0.9376165336263994 20 0.3186947544718952 40 0.1509003001157511 50 183.9914206989488 51 194.7961827171795 73 1 72 2 10 0.8556691262907683 20 0.2975229405501065 40 0.0662649326044679 50 195.1922580686626 51 211.8161260167849 73 1 72 2 10 0.8256760335810848 20 0.2787995943136916 40 0.0309077724093995 50 211.6347351863199 51 239.3370203444206 73 1 72 2 10 0.8328177638353177 20 0.2958607887822569 40 0.0492921034260791 50 242.3114767787511 51 261.3474606529535 73 1 72 2 10 0.8463235842781011 20 0.3747617950344397 40 0.1293354591063143 50 260.6908797927596 51 270.6747908046021 73 1 72 2 10 0.8475369120546362 20 1.499934543466537 40 1.25449927615356 50 270.0141521009336 51 274.864484102984 73 1 72 1 10 0.9539175761181276 20 0.2499539083432495 11 0.9712784354522652 21 0.2513808595641643 72 1 10 0.9712784354522652 20 0.2513808595641643 11 0.9712784354522652 21 0.1940650616281518 72 2 10 0.8963837746081258 20 0.3325480038481863 40 0.1574380370459314 50 61.59448955636654 51 83.93793890179708 73 0 72 2 10 0.8330823004026875 20 0.9588829323823655 40 0.7869620433976263 50 84.17070136778845 51 89.53110693540054 73 0 72 1 10 0.8395225116804813 20 0.1719472415999074 11 0.8357173084247086 21 0.1719472415999074 72 2 10 0.8200434901136805 20 0.3538739274501789 40 0.1826006232325358 50 85.075865127039 51 108.3600821200968 73 0 72 2 10 0.7992279764644755 20 0.2662427996310877 40 0.093204559668334 50 113.1894915396505 51 140.0801272454766 73 0 72 2 10 0.8012223158134221 20 0.2683158374418412 40 0.0960649049009913 50 139.8951733394063 51 156.2653987660679 73 0 72 2 10 0.867342438096846 20 0.2977766777590661 40 0.168450950198126 50 156.1444339138709 51 167.3939009796797 73 0 72 2 10 0.99451280167804 20 0.3270031053307328 40 0.2989352544876143 50 167.2468323736907 51 174.9177209790342 73 0 72 2 10 1.20180856877263 20 0.3462839419889538 40 0.5071247554608478 50 174.8226486749857 51 180.2137793480696 73 0 72 1 10 0.6946873432779551 20 0.3481760979032103 11 0.6946873432779551 21 0.3481760979032103 97 1 330 B4 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1C1 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 16 72 1 10 1.020746077777311 20 0.1752767944487085 11 1.020746077777311 21 0.5201225784624666 72 1 10 1.020746077777311 20 0.5201225784624666 11 1.097325032259088 21 0.5201225784624666 72 1 10 1.097325032259088 20 0.5201225784624666 11 1.111594544468236 21 0.4766017077855419 72 2 10 1.244437268897258 20 0.3429659792394641 40 0.1884295554783436 50 225.1705040479414 51 243.5972159016927 73 0 72 2 10 1.211173613045121 20 0.4086440720149234 40 0.114812202274129 50 243.8907918763913 51 269.5602281386679 73 0 72 2 10 1.212244334515651 20 0.2785645037372034 40 0.2448961677679514 50 269.5433179430547 51 275.0724278925614 73 0 72 2 10 1.229554147138809 20 0.4609473043473566 40 0.0617072855517635 50 274.0355485122913 51 287.9600884366593 73 0 72 1 10 1.248581861676056 20 0.519647689096146 11 1.248581861676056 21 0.4318905695302117 72 2 10 1.204841316941958 20 -0.0620372588614032 40 0.4958608019528185 50 84.9392850010685 51 90.63415610337293 73 1 72 2 10 1.198149495755201 20 0.2491083832840643 40 0.1846887103819838 50 89.62657779356016 51 98.49286189291752 73 1 72 2 10 1.186703181985212 20 0.32427591283572 40 0.1086552070090232 50 98.37706810352306 51 111.0116715202816 73 1 72 2 10 1.173884337196004 20 0.3604725103818166 40 0.070276402608659 50 111.8368548044861 51 130.2463188715139 73 1 72 2 10 1.191856507616234 20 0.3396388865736808 40 0.0977898738515406 50 130.3972532514171 51 145.1608900952568 73 1 72 1 10 1.111594544468236 20 0.39550369391721 11 1.111594544468236 21 0.1752767944487085 72 1 10 1.111594544468236 20 0.1752767944487085 11 1.020746077777311 21 0.1752767944487085 72 1 10 1.020746077777311 20 0.1752767944487085 11 1.020746077777311 21 0.1752767944487085 97 1 330 D8 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1C2 330 1D 100 AcDbEntity 8 TEXT-GRAY 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 2 92 1 93 30 72 2 10 1.745775880860402 20 0.3473056857538349 40 0.4596595742917985 50 179.219041199578 51 188.5892672078823 73 0 72 2 10 1.462665276168372 20 0.3902293883547505 40 0.1733136452000416 50 188.5364777731353 51 206.4130707393759 73 0 72 2 10 1.382597433515457 20 0.4290189590384098 40 0.0843534860499277 50 207.0087701028281 51 238.085854021312 73 0 72 2 10 1.408309618919584 20 0.3846069642931946 40 0.1356549785854117 50 238.7839320009168 51 258.9459185787553 73 0 72 2 10 1.439724993974423 20 0.2328843812063898 40 0.29059126074079 50 258.6024639297659 51 270.7169453069864 73 0 72 2 10 1.444920074652102 20 0.2029818501508946 40 0.3204748341784855 50 269.7212762564572 51 277.0779005236373 73 0 72 2 10 1.460416453713881 20 0.3252503357550985 40 0.1972288945641309 50 276.9871111277841 51 287.1571071678799 73 0 72 2 10 1.482143870267849 20 0.3951169191449219 40 0.1240620704779083 50 287.0876504098538 51 300.9508770078874 73 0 72 2 10 1.500583736465673 20 0.4262167749073336 40 0.0879070752171196 50 301.0685629566324 51 318.5141019927507 73 0 72 2 10 1.490538341293795 20 0.4193627680062952 40 0.0999841621843878 50 319.38514811862 51 335.2909851831375 73 0 72 2 10 1.432430719209494 20 0.3924029450769723 40 0.1640411911207225 50 335.220473520381 51 346.6482421759119 73 0 72 2 10 1.321167690210193 20 0.3654957782609066 40 0.2785109168173717 50 346.5482508793782 51 354.5741818072581 73 0 72 2 10 1.140576365463508 20 0.34757052037717 40 0.459988693945271 50 354.4784226911817 51 360.2208980900735 73 0 72 2 10 1.136142388530695 20 0.3440375062016253 40 0.4644225855321327 50 359.7829203976418 51 365.4556667991741 73 0 72 2 10 1.324257241032597 20 0.3255607991203732 40 0.2754036673203588 50 5.350003779949623 51 13.38950403845408 73 0 72 2 10 1.438822228558409 20 0.2978741757969074 40 0.1575418848528459 50 13.24247481022855 51 24.9143339913515 73 0 72 2 10 1.49750166023149 20 0.2704935387993822 40 0.0927888674313809 50 24.84449572776879 51 41.46851456153187 73 0 72 2 10 1.504747507691185 20 0.2661434323058319 40 0.0844927447051385 50 42.51194694689715 51 60.20982750498259 73 0 72 2 10 1.484241834436404 20 0.3022559330899828 40 0.1260208208552944 50 60.27608629427618 51 73.82705129133484 73 0 72 2 10 1.461143797848464 20 0.3806703565348255 40 0.2077659731176355 50 73.73258141531123 51 83.43685270361343 73 0 72 2 10 1.444981387538941 20 0.5159994031828512 40 0.3440559769484268 50 83.33882871764017 51 90.26983081888446 73 0 72 2 10 1.441836581268094 20 0.4848621958152928 40 0.3129186678351786 50 89.72086066320244 51 97.22714964633519 73 0 72 2 10 1.426768810557204 20 0.3683000729345016 40 0.1953872384683834 50 97.14382290172345 51 107.4222425802834 73 0 72 2 10 1.405753699036433 20 0.3016738701941614 40 0.1255254500273459 50 107.3755052356472 51 121.1859060075268 73 0 72 2 10 1.388200250824436 20 0.2723186857145772 40 0.091323052757868 50 121.3012045363258 51 138.3807483919028 73 0 72 2 10 1.396390386155313 20 0.2780817143578742 40 0.1012797862356359 50 139.0208188923022 51 154.2673000625914 73 0 72 2 10 1.443564578953644 20 0.3008357842563767 40 0.153654894821596 50 154.2614231301619 51 165.8039007823683 73 0 72 2 10 1.533704415876427 20 0.3240227080426966 40 0.2467287207424286 50 165.7173228384291 51 174.1318325417901 73 0 72 2 10 1.679452490871063 20 0.3395070071807061 40 0.3932964759323175 50 174.0587164483615 51 180.2234129253398 73 0 72 1 10 1.286159004867464 20 0.3410405807579851 11 1.286159004867464 21 0.3410405807579851 97 1 330 14B 92 16 93 21 72 2 10 1.87884778741299 20 0.3051697834906549 40 0.5046900079850218 50 165.4581922653545 51 171.0243917073363 73 1 72 2 10 1.640017569701684 20 0.3421119050184488 40 0.2630219456806235 50 170.856419407449 51 179.4561773269252 73 1 72 2 10 1.719600323247084 20 0.3382249259339413 40 0.342652316488281 50 178.9325511963493 51 188.0659430044691 73 1 72 2 10 1.461506204624639 20 0.3030699205237911 40 0.0821908055767169 50 189.0465869719995 51 201.4429641704123 73 1 72 2 10 1.425949825821255 20 0.2889700547677836 40 0.0439411927350844 50 201.2794750422889 51 220.1176890207309 73 1 72 2 10 1.421375505703486 20 0.2843571418367111 40 0.0374752217300239 50 219.2307545260716 51 255.6490576647813 73 1 72 2 10 1.438807477461641 20 0.3811952640733502 40 0.1357987619432282 50 258.6520849549118 51 271.3697308658793 73 1 72 2 10 1.445896027874007 20 0.4691190853840432 40 0.2237167796028082 50 269.0158770897956 51 276.276357003502 73 1 72 2 10 1.463387403735492 20 0.2947145002894463 40 0.0484744436347309 50 278.2625944015626 51 301.2735466815289 73 1 72 2 10 1.473353916121774 20 0.2781237012056268 40 0.0291206023535156 50 301.4591386210279 51 342.6827079184787 73 1 72 2 10 1.374091031750538 20 0.3127659022243659 40 0.1342419911030445 50 341.1780241039497 51 353.2229122868627 73 1 72 2 10 1.232912256678613 20 0.3308726804904729 40 0.2765741939881523 50 352.9494162843384 51 360.3822505868759 73 1 72 2 10 0.7248612462910731 20 0.3411691780724345 40 0.7846645638024572 50 359.3828759745637 51 363.6573187603917 73 1 72 2 10 1.358304373290006 20 0.3811941386031548 40 0.1499590652226746 50 3.834298057692314 51 15.98721166096502 73 1 72 2 10 1.473936824340389 20 0.4156549366241289 40 0.0293355637618033 50 13.48613242730697 51 56.84075856181408 73 1 72 2 10 1.460693878894012 20 0.3942253340844751 40 0.054522595367914 50 57.50799133160251 51 77.8514521481949 73 1 72 2 10 1.449551855505779 20 0.3442176219715277 40 0.1057558456740848 50 77.65179244717869 51 90.71274674017063 73 1 72 2 10 1.446520818841627 20 0.1669086878434607 40 0.2830617955533721 50 89.65275773185921 51 94.33247869604129 73 1 72 2 10 1.430610265978255 20 0.3644952794934767 40 0.0848430589089613 50 93.69860806412952 51 104.1787730439532 73 1 72 2 10 1.420228457430697 20 0.4128805599428683 40 0.0354338310931719 50 107.0684876277999 51 147.5547663680418 73 1 72 1 10 1.390325682953593 20 0.4318905695302117 11 1.390325682953593 21 0.4318905695302117 97 1 330 10A 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1C5 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 2 92 1 93 17 72 1 10 1.658111534794044 20 0.1752767944487085 11 1.658111534794044 21 0.6506897567371471 72 1 10 1.658111534794044 20 0.6506897567371471 11 1.862892353206713 21 0.6506897567371471 72 2 10 1.866712771298765 20 0.4812885811102773 40 0.1694442501183315 50 268.7080565864779 51 289.696280270266 73 0 72 2 10 1.890323704356795 20 0.5498088066581733 40 0.0969791362784035 50 290.2068256429989 51 320.7179581453081 73 0 72 2 10 1.872231214265821 20 0.5377375192902893 40 0.1186450067238793 50 321.7376468722154 51 345.941318148983 73 0 72 2 10 1.755413737650509 20 0.5077074919349243 40 0.239259448802611 50 345.7608112632561 51 360.8993727822122 73 0 72 2 10 1.739929769421669 20 0.4990316766439469 40 0.2547614597035357 50 358.8933548673149 51 375.1421636632072 73 0 72 2 10 1.805070643979139 20 0.4843830829172414 40 0.1880777885766737 50 16.01826700445136 51 24.59137858751017 73 0 72 2 10 1.886457278838033 20 0.4467408832612785 40 0.098409106202089 50 24.38210075542359 51 37.59560803165674 73 0 72 2 10 1.901447144532471 20 0.4366823005906129 40 0.0804040955571766 50 38.43315571073376 51 67.41262732859074 73 0 72 2 10 1.877530541683213 20 0.482621245957908 40 0.1320800191028363 50 65.48738102872184 51 90.78391246376287 73 0 72 2 10 1.89658449370416 20 1.061679540017775 40 0.711431865658397 50 91.68029910103571 51 97.60098612101147 73 0 72 2 10 2.098301318614009 20 2.918534187606983 40 2.579056963876972 50 96.58637858697409 51 97.45141278012369 73 0 72 2 10 1.776013741879782 20 0.4823678310216308 40 0.1217217342158525 50 95.74213501202033 51 102.7219939836472 73 0 72 1 10 1.749208100737245 20 0.3636343556094617 11 1.749208100737245 21 0.1752767944487085 72 1 10 1.749208100737245 20 0.1752767944487085 11 1.658111534794044 21 0.1752767944487085 72 1 10 1.658111534794044 20 0.1752767944487085 11 1.658111534794044 21 0.1752767944487085 97 1 330 138 92 16 93 12 72 1 10 1.855753791898883 20 0.5703040769182958 11 1.749208100737245 21 0.5703040769182958 72 1 10 1.749208100737245 20 0.5703040769182958 11 1.749208100737245 21 0.4311767133994287 72 1 10 1.749208100737245 20 0.4311767133994287 11 1.855281946695168 21 0.4311767133994287 72 2 10 1.857310696196809 20 0.4789795547126073 40 0.0478458719447492 50 267.5698291459668 51 298.9736848744403 73 1 72 2 10 1.864437662714773 20 0.4638897212446849 40 0.0312107960389064 50 300.9469057674883 51 325.1843100261158 73 1 72 2 10 1.847208640489655 20 0.4756552874383635 40 0.0520734162270339 50 325.3793523193102 51 342.5869620344669 73 1 72 2 10 1.761853469548879 20 0.499095419473726 40 0.1405675106851083 50 343.8821453186945 51 361.6888272002417 73 1 72 2 10 1.771325527872711 20 0.505069610767784 40 0.1310471922643137 50 359.1992235790916 51 372.1177778779552 73 1 72 2 10 1.840471280377904 20 0.5202934512206887 40 0.0602474495482526 50 11.76645972748428 51 33.49099599484823 73 1 72 2 10 1.86002067419837 20 0.5327033580204925 40 0.0370985166555385 50 34.16739135196509 51 64.22988058382727 73 1 72 2 10 1.856792087819456 20 0.5236405260900577 40 0.0466751007960158 50 65.49764645855024 51 91.27465994990668 73 1 72 1 10 1.855753791898883 20 0.5703040769182958 11 1.855753791898883 21 0.5703040769182958 97 1 330 4A 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1C6 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 17 72 1 10 2.026516093204943 20 0.5201225784624666 11 2.12187448679461 21 0.5201225784624666 72 1 10 2.12187448679461 20 0.5201225784624666 11 2.181814048479542 21 0.2784929327615455 72 2 10 2.213922500215711 20 0.2853658521330381 40 0.0328357989636449 50 192.0820235727047 51 230.2482576268844 73 1 72 2 10 2.211977736162895 20 0.2865212844941371 40 0.0325572563546005 50 234.1829062182941 51 272.5793312178134 73 1 72 2 10 2.218185855487651 20 0.2662392650291758 40 0.0131289140189778 50 248.8223744883709 51 260.6854283382104 73 1 72 1 10 2.216060877781497 20 0.2532834611920508 11 2.285026381589124 21 0.5201225784624666 72 1 10 2.285026381589124 20 0.5201225784624666 11 2.379912929975073 21 0.5201225784624666 72 1 10 2.379912929975073 20 0.5201225784624666 11 2.2602925604266 21 0.0661149499446615 72 1 10 2.2602925604266 20 0.0661149499446615 11 2.21297105273781 21 0.0 72 1 10 2.21297105273781 20 0.0 11 2.147795531372934 21 0.0 72 1 10 2.147795531372934 20 0.0 11 2.196547795485895 21 0.1752767944487085 72 2 10 2.195202176373045 20 0.2879880150203464 40 0.1127192527190687 50 89.31599859402309 51 107.9604459396842 73 0 72 2 10 2.187860498124107 20 0.2632664971382323 40 0.0869408911919764 50 108.3817089051841 51 130.5609495896915 73 0 72 2 10 2.198002807128255 20 0.2736653212156158 40 0.101440520082671 50 131.0937856248721 51 151.0996267706195 73 0 72 2 10 2.251259362016389 20 0.3028621870346081 40 0.1621751716283119 50 151.1623473832895 51 165.7835266974244 73 0 72 1 10 2.094050840588399 20 0.2630342184309034 11 2.026516093204943 21 0.5201225784624666 72 1 10 2.026516093204943 20 0.5201225784624666 11 2.026516093204943 21 0.5201225784624666 97 1 330 89 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1C7 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 23 72 1 10 2.401085080890193 20 0.451391475175396 11 2.401085080890193 21 0.502049385078848 72 1 10 2.401085080890193 20 0.502049385078848 11 2.456975906310984 21 0.5208364345932495 72 1 10 2.456975906310984 20 0.5208364345932495 11 2.471953186325706 21 0.6169178168015124 72 1 10 2.471953186325706 20 0.6169178168015124 11 2.547828939245814 21 0.6169178168015124 72 1 10 2.547828939245814 20 0.6169178168015124 11 2.547828939245814 21 0.5208364345932495 72 1 10 2.547828939245814 20 0.5208364345932495 11 2.625120227777072 21 0.5208364345932495 72 1 10 2.625120227777072 20 0.5208364345932495 11 2.625120227777072 21 0.451391475175396 72 1 10 2.625120227777072 20 0.451391475175396 11 2.547828939245814 21 0.451391475175396 72 1 10 2.547828939245814 20 0.451391475175396 11 2.547828939245814 21 0.312977967787312 72 2 10 2.756375078424425 20 0.3106349819782397 40 0.208559300317214 50 179.3563172584847 51 187.5204775666663 73 1 72 2 10 2.610407599922477 20 0.2901879066221412 40 0.0611824171745163 50 186.4276465021346 51 204.9884326299174 73 1 72 2 10 2.591486060141609 20 0.2832478516776391 40 0.0411355950463604 50 207.3607300982318 51 249.4822289731461 73 1 72 2 10 2.925871745813213 20 1.236527392855755 40 1.05135264976578 50 250.6239679589966 51 252.369953071448 73 1 72 2 10 2.632025513918952 20 0.3027146749676596 40 0.0724554546479011 50 250.172060625216 51 260.9268652271251 73 1 72 1 10 2.620599646309214 20 0.2311657933719365 11 2.620599646309214 21 0.1752767944487085 72 1 10 2.620599646309214 20 0.1752767944487085 11 2.541405756150071 21 0.1752767944487085 72 2 10 2.539541691321775 20 0.2586536504670411 40 0.0833976909583584 50 88.71924580725035 51 114.8723068619946 73 0 72 2 10 2.534259066943731 20 0.2435901096002027 40 0.0675271066805567 50 116.1816665503854 51 146.3117142175992 73 0 72 2 10 2.571816472169667 20 0.2671405893161746 40 0.1118470865035182 50 146.9451672649385 51 168.4294027765594 73 0 72 2 10 2.701886448180166 20 0.2953352474010394 40 0.2449337665542188 50 168.070822892956 51 180.7890266060776 73 0 72 1 10 2.456975906310984 20 0.2987081511619036 11 2.456975906310984 21 0.451391475175396 72 1 10 2.456975906310984 20 0.451391475175396 11 2.401085080890193 21 0.451391475175396 72 1 10 2.401085080890193 20 0.451391475175396 11 2.401085080890193 21 0.451391475175396 97 1 330 58 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1C8 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 22 72 1 10 2.66863653221009 20 0.1752767944487085 11 2.66863653221009 21 0.6839852852251591 72 1 10 2.66863653221009 20 0.683985285225159 11 2.758774186932835 21 0.683985285225159 72 1 10 2.758774186932835 20 0.683985285225159 11 2.758774186932835 21 0.4832608134831443 72 2 10 2.970884692343786 20 0.1949308647558484 40 0.3579455626750722 50 233.6598667174819 51 241.6737203338166 73 0 72 2 10 2.862953103918855 20 0.398321949096261 40 0.1277046941848677 50 241.0008951743301 51 256.9710241053807 73 0 72 2 10 2.867314180648163 20 0.3596725627348979 40 0.1664021752218955 50 258.5084157090225 51 270.4610700343784 73 0 72 2 10 2.871155730201377 20 0.4023028257494028 40 0.1237918213330042 50 268.8416672957483 51 290.1493812176847 73 0 72 2 10 2.88549439287798 20 0.4438925273392474 40 0.0798129708700709 50 290.7705399537808 51 319.3693426350027 73 0 72 2 10 2.86973875277353 20 0.4329212526250472 40 0.0989334609539707 50 320.4891190671877 51 345.2499775321184 73 0 72 2 10 2.778017766714932 20 0.4084074663129932 40 0.1938734483480787 50 345.1454837561613 51 360.9319474711875 73 0 72 1 10 2.971865569256112 20 0.4052541467398021 11 2.971865569256112 21 0.1752767944487085 72 1 10 2.971865569256112 20 0.1752767944487085 11 2.881012536321281 21 0.1752767944487085 72 1 10 2.881012536321281 20 0.1752767944487085 11 2.881012536321281 21 0.4064428922369056 72 2 10 2.802613036220481 20 0.4076912084297279 40 0.0784094376294883 50 359.0877849241664 51 374.2114110518409 73 1 72 2 10 2.840775464266772 20 0.4174522933113873 40 0.0390186755568009 50 14.07416101436572 51 38.19979694511947 73 1 72 2 10 2.848474408609313 20 0.4228438207727886 40 0.0296388733419943 50 39.21298268016682 51 68.21300572178883 73 1 72 2 10 2.843635884024977 20 0.4091395078042849 40 0.0441641298463429 50 68.98305490508943 51 91.1922266305568 73 1 72 2 10 2.839517556631515 20 0.3257194842430624 40 0.1276147049428117 50 88.56339333889899 51 108.8133720429226 73 1 72 2 10 2.853071660183995 20 0.3106172986056333 40 0.146497457591775 50 111.9279820567162 51 129.7021521663467 73 1 72 1 10 2.759489565144921 20 0.4233288622047228 11 2.759489565144921 21 0.1752767944487085 72 1 10 2.759489565144921 20 0.1752767944487085 11 2.66863653221009 21 0.1752767944487085 72 1 10 2.66863653221009 20 0.1752767944487085 11 2.66863653221009 21 0.1752767944487085 97 1 330 9C 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1C9 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 2 92 1 93 30 72 2 10 3.480235470402663 20 0.3472963994916086 40 0.4596602087851077 50 179.2201999001178 51 188.5904259084221 73 0 72 2 10 3.197121821548028 20 0.3902535820648669 40 0.1733062924357386 50 188.5287545821982 51 206.4053475484388 73 0 72 2 10 3.11705169577316 20 0.4290134848926255 40 0.084357328189102 50 207.0116131808711 51 238.088697099355 73 0 72 2 10 3.142763881177286 20 0.3846155256577634 40 0.1356468679361114 50 238.7826076590414 51 258.9445942368799 73 0 72 2 10 3.174180017272777 20 0.2328628655440478 40 0.2906128032937941 50 258.6028609455173 51 270.7173423227377 73 0 72 2 10 3.179378903153711 20 0.2029581738044638 40 0.3204985176522159 50 269.7210247461867 51 277.0776490133664 73 0 72 2 10 3.19487528221549 20 0.325267440923209 40 0.1972121016147459 50 276.9881545773719 51 287.1581506174676 73 0 72 2 10 3.216601176688156 20 0.3951169191449229 40 0.1240620704779073 50 287.0876504098541 51 300.9508770078876 73 0 72 2 10 3.235041042885957 20 0.4262167749073067 40 0.0879070752171545 50 301.0685629566362 51 318.5141019927475 73 0 72 2 10 3.22499564771415 20 0.4193627680063226 40 0.0999841621843335 50 319.385148118614 51 335.2909851831404 73 0 72 2 10 3.166888025629801 20 0.3924029450769745 40 0.1640411911207218 50 335.2204735203817 51 346.6482421759127 73 0 72 2 10 3.055624996630501 20 0.3654957782609082 40 0.2785109168173713 50 346.5482508793785 51 354.5741818072585 73 0 72 2 10 2.875033671883636 20 0.3475705203771616 40 0.4599886939454501 50 354.4784226911829 51 360.2208980900725 73 0 72 2 10 2.870607305357513 20 0.3438838987998202 40 0.4644155825717984 50 359.7639661566379 51 365.4367125581701 73 0 72 2 10 3.058722157859415 20 0.3256690965276672 40 0.2754213630050057 50 5.372287081245953 51 13.41178733975041 73 0 72 2 10 3.173279534978716 20 0.2978741757969097 40 0.1575418848528468 50 13.24247481022931 51 24.91433399135224 73 0 72 2 10 3.231958966651797 20 0.27049353879938 40 0.0927888674313799 50 24.84449572776762 51 41.46851456153065 73 0 72 2 10 3.239204814111471 20 0.2661434323058576 40 0.0844927447051714 50 42.51194694690035 51 60.20982750497873 73 0 72 2 10 3.218699140856711 20 0.3022559330899847 40 0.1260208208552961 50 60.27608629427653 51 73.8270512913352 73 0 72 2 10 3.195604909472027 20 0.3806255307799783 40 0.207721876247583 50 73.73012549511914 51 83.43439678342133 73 0 72 2 10 3.179442499162505 20 0.5160622385854792 40 0.3441188295924385 50 83.33941300651419 51 90.27041510775888 73 0 72 2 10 3.176297692891656 20 0.4848041884129171 40 0.3128606426025486 50 89.72150576644664 51 97.22779474957937 73 0 72 2 10 3.161234488424673 20 0.3682916110468403 40 0.1953789369211231 50 97.14435294680244 51 107.4227726253624 73 0 72 2 10 3.140217093781949 20 0.301699006668967 40 0.1255485308215694 50 107.370753656409 51 121.1811544282885 73 0 72 2 10 3.12266212348865 20 0.2723085493673603 40 0.0913151827909786 50 121.3053248468621 51 138.3848687024391 73 0 72 2 10 3.130851497778824 20 0.2780987727770228 40 0.1012892502687907 50 139.0126872013657 51 154.2591683716641 73 0 72 2 10 3.178025690577206 20 0.3008131945580285 40 0.1536471429745666 50 154.2693808990751 51 165.8118585512815 73 0 72 2 10 3.268168571662594 20 0.3240123625755021 40 0.2467269061818614 50 165.7196946403268 51 174.1342043436877 73 0 72 2 10 3.413914363535721 20 0.3395635385525735 40 0.3932993037049538 50 174.0504793005304 51 180.2151757775018 73 0 72 1 10 3.020617833369073 20 0.3410405807579851 11 3.020617833369073 21 0.3410405807579851 97 1 330 EA 92 16 93 21 72 2 10 3.613312704239808 20 0.3052010939876257 40 0.5046836205998101 50 165.4616764010741 51 171.0278758430559 73 1 72 2 10 3.374482486528501 20 0.3420916614133984 40 0.2630236606104225 50 170.85201298578 51 179.4517709052564 73 1 72 2 10 3.454065240073902 20 0.3382439821810626 40 0.3426534838299237 50 178.9357418182288 51 188.0691336263486 73 1 72 2 10 3.195968077288853 20 0.3030278751539043 40 0.0821796951545775 50 189.0181381128171 51 201.4145153112299 73 1 72 2 10 3.160411698485469 20 0.2889975802415061 40 0.0439554436806379 50 201.3107480863471 51 220.1489620647889 73 1 72 2 10 3.155835095245747 20 0.2843363205812091 40 0.037456749731058 50 219.2127101386138 51 255.6310132773234 73 1 72 2 10 3.173261739719343 20 0.3812089223380726 40 0.1358124526943521 50 258.6525891616267 51 271.3702350725942 73 1 72 2 10 3.180357139497569 20 0.4692030529375931 40 0.2238008263021876 50 269.0148826539333 51 276.2753625676396 73 1 72 2 10 3.197849276399706 20 0.2946920674583943 40 0.0484529004947375 50 278.2717501461559 51 301.2827024261222 73 1 72 2 10 3.207811222542081 20 0.2781237012056277 40 0.0291206023535162 50 301.4591386210265 51 342.6827079184772 73 1 72 2 10 3.108548338170845 20 0.3127659022243659 40 0.1342419911030445 50 341.1780241039497 51 353.2229122868627 73 1 72 2 10 2.967369563098919 20 0.330872680490466 40 0.2765741939881519 50 352.9494162843399 51 360.3822505868774 73 1 72 2 10 2.459318552711379 20 0.3411691780724464 40 0.7846645638024574 50 359.3828759745628 51 363.6573187603909 73 1 72 2 10 3.092761679710313 20 0.3811941386031558 40 0.1499590652226746 50 3.834298057691928 51 15.98721166096461 73 1 72 2 10 3.208394130760695 20 0.4156549366241278 40 0.029335563761804 50 13.48613242730889 51 56.84075856181601 73 1 72 2 10 3.195154229476923 20 0.3942423008569769 40 0.0545066495896497 50 57.50110974384233 51 77.84457056043473 73 1 72 2 10 3.184009922966737 20 0.344171085093621 40 0.1058024453263516 50 77.65436364628005 51 90.71531793927198 73 1 72 2 10 3.180978125261934 20 0.1670204385423348 40 0.2829500192598661 50 89.65354521146901 51 94.33326617565109 73 1 72 2 10 3.165070616561166 20 0.3644786832754941 40 0.084859522413094 50 93.69685967486203 51 104.1770246546857 73 1 72 2 10 3.15468956905426 20 0.4128867508985087 40 0.0354285831761041 50 107.0749560136262 51 147.5612347538681 73 1 72 1 10 3.124789077699108 20 0.4318905695302117 11 3.124789077699108 21 0.4318905695302117 97 1 330 121 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 HATCH 5 1CA 330 1D 100 AcDbEntity 8 TEXT-RED 100 AcDbHatch 10 0.0 20 0.0 30 0.0 210 0.0 220 0.0 230 1.0 2 SOLID 70 1 71 1 91 1 92 1 93 22 72 2 10 3.592005824568463 20 0.4022623702532142 40 0.1238324225952604 50 268.8385251676425 51 290.1462390895788 73 0 72 2 10 3.606344487245067 20 0.4439223854568978 40 0.0797877541011788 50 290.7832534290268 51 319.3820561102488 73 0 72 2 10 3.590581236734105 20 0.4329212526250472 40 0.0989334609539707 50 320.4891190671877 51 345.2499775321184 73 0 72 2 10 3.498860250675552 20 0.4084074663130021 40 0.1938734483480326 50 345.1454837561604 51 360.9319474711903 73 0 72 1 10 3.692708053216686 20 0.4052541467398021 11 3.692708053216686 21 0.1752767944487085 72 1 10 3.692708053216686 20 0.1752767944487085 11 3.601870241094878 21 0.1752767944487085 72 1 10 3.601870241094878 20 0.1752767944487085 11 3.601870241094878 21 0.4064428922369056 72 2 10 3.523463130587567 20 0.4076338796510298 40 0.0784161554089863 50 359.1297561618085 51 374.2533822894829 73 1 72 2 10 3.561625558633858 20 0.4174879054254667 40 0.0390026472343202 50 14.02613509500026 51 38.15177102575402 73 1 72 2 10 3.569324502976398 20 0.4228143935386817 40 0.029663379390137 50 39.24772886833219 51 68.2477519099542 73 1 72 2 10 3.564485978392062 20 0.4091782819430569 40 0.0441252062777969 50 68.97422263922098 51 91.18339436468834 73 1 72 2 10 3.560375261405112 20 0.3257194842430623 40 0.1276147049428117 50 88.56339333889899 51 108.8133720429226 73 1 72 2 10 3.573921754551081 20 0.3105686277924473 40 0.1465397674015583 50 111.9181151967782 51 129.6922853064086 73 1 72 1 10 3.480332049105495 20 0.4233288622047228 11 3.480332049105495 21 0.1752767944487085 72 1 10 3.480332049105495 20 0.1752767944487085 11 3.389479016170664 21 0.1752767944487085 72 1 10 3.389479016170664 20 0.1752767944487085 11 3.389479016170664 21 0.5201225784624666 72 1 10 3.389479016170664 20 0.5201225784624666 11 3.462264944047086 21 0.5201225784624666 72 1 10 3.462264944047086 20 0.5201225784624666 11 3.480332049105495 21 0.4832608134831443 72 2 10 3.692032830344103 20 0.1968176418438357 40 0.3561838168078713 50 233.5331050519283 51 241.6403323622616 73 0 72 2 10 3.581912438010629 20 0.4042431550954748 40 0.1213560014894028 50 240.8735520743203 51 257.5360464861715 73 0 72 2 10 3.587849834142919 20 0.3698286725878678 40 0.1562493464094038 50 258.1337893490277 51 270.603548530042 73 0 72 1 10 3.589495720107105 20 0.5260693501105883 11 3.589495720107105 21 0.5260693501105883 97 1 330 71 75 0 76 1 98 1 10 -0.0349603810164775 20 0.1524455749140718 1001 ACAD 1010 0.0 1020 0.0 1030 0.0 0 ENDSEC 0 SECTION 2 OBJECTS 0 DICTIONARY 5 C 330 0 100 AcDbDictionary 281 1 3 ACAD_DETAILVIEWSTYLE 350 1D4 3 ACAD_GROUP 350 D 3 ACAD_IMAGE_VARS 350 1B2 3 ACAD_LAYOUT 350 1A 3 ACAD_MLINESTYLE 350 17 3 ACAD_PLOTSETTINGS 350 19 3 ACAD_PLOTSTYLENAME 350 E 3 ACAD_SCALELIST 350 16B 3 ACAD_SECTIONVIEWSTYLE 350 1D5 3 AcDbVariableDictionary 350 1CF 3 APPDATA 350 1B0 3 DWGPROPS 350 1D6 0 DICTIONARY 5 1B3 330 2 100 AcDbDictionary 280 1 281 1 3 ACAD_LAYERSTATES 360 1B4 3 ACLYDICTIONARY 360 1BB 0 DICTIONARY 5 1D4 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 DICTIONARY 5 D 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 RASTERVARIABLES 5 1B2 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbRasterVariables 90 0 70 1 71 1 72 0 0 DICTIONARY 5 1A 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 Model 350 1E 3 Sheet 1 350 1C 0 DICTIONARY 5 17 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 Standard 350 18 0 DICTIONARY 5 19 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 ACDBDICTIONARYWDFLT 5 E 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 Normal 350 F 100 AcDbDictionaryWithDefault 340 F 0 DICTIONARY 5 16B 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 3 A0 350 16C 3 A1 350 16D 3 A2 350 16E 3 A3 350 16F 3 A4 350 170 3 A5 350 171 3 A6 350 172 3 A7 350 173 3 A8 350 174 3 A9 350 175 3 B0 350 176 3 B1 350 177 3 B2 350 178 3 B3 350 179 3 B4 350 17A 3 B5 350 17B 3 B6 350 17C 3 B7 350 17D 3 B8 350 17E 3 B9 350 17F 3 C0 350 180 3 C1 350 181 3 C2 350 182 3 C3 350 183 3 C4 350 184 3 C5 350 185 3 C6 350 186 3 C7 350 187 3 C8 350 188 3 C9 350 189 3 D0 350 18A 3 D1 350 18B 3 D2 350 18C 0 DICTIONARY 5 1D5 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 DICTIONARY 5 1CF 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 DICTIONARY 5 1B0 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbDictionary 281 1 0 XRECORD 5 1D6 102 {ACAD_REACTORS 330 C 102 } 330 C 100 AcDbXrecord 280 1 1 DWGPROPS COOKIE 2 vector-text 3 4 Jonathan Greig 6 Generated outlines with CNCFontFab using the "Exo Bold" font. 7 MicroPython Text 8 9 300 = 301 = 302 = 303 = 304 = 305 = 306 = 307 = 308 = 309 = 40 0.0 41 2456662.519745903 42 2456662.532164352 1 90 0 0 DICTIONARY 5 1B4 102 {ACAD_REACTORS 330 1B3 102 } 330 1B3 100 AcDbDictionary 281 1 3 ARGON_LAYERP_1 350 1B5 3 ARGON_LAYERP_2 350 1B8 3 ARGON_LAYERP_3 350 1C3 0 DICTIONARY 5 1BB 102 {ACAD_REACTORS 330 1B3 102 } 330 1B3 100 AcDbDictionary 281 1 1001 ACAD 1000 image/svg+xml micropython-1.12/mpy-cross/000077500000000000000000000000001357706137100157565ustar00rootroot00000000000000micropython-1.12/mpy-cross/.gitignore000066400000000000000000000000121357706137100177370ustar00rootroot00000000000000mpy-cross micropython-1.12/mpy-cross/Makefile000066400000000000000000000027441357706137100174250ustar00rootroot00000000000000include ../py/mkenv.mk # define main target PROG = mpy-cross # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # OS name, for simple autoconfig UNAME_S := $(shell uname -s) # include py core make definitions include $(TOP)/py/py.mk INC += -I. INC += -I$(BUILD) INC += -I$(TOP) # compiler settings CWARN = -Wall -Werror CWARN += -Wpointer-arith -Wuninitialized CFLAGS = $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables # Debugging/Optimization ifdef DEBUG CFLAGS += -g COPT = -O0 else COPT = -Os #-DNDEBUG endif # On OSX, 'gcc' is a symlink to clang unless a real gcc is installed. # The unix port of MicroPython on OSX must be compiled with clang, # while cross-compile ports require gcc, so we test here for OSX and # if necessary override the value of 'CC' set in py/mkenv.mk ifeq ($(UNAME_S),Darwin) CC = clang # Use clang syntax for map file LDFLAGS_ARCH = -Wl,-map,$@.map -Wl,-dead_strip else # Use gcc syntax for map file LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) # source files SRC_C = \ main.c \ gccollect.c \ # Add fmode when compiling with mingw gcc COMPILER_TARGET := $(shell $(CC) -dumpmachine) ifneq (,$(findstring mingw,$(COMPILER_TARGET))) SRC_C += ports/windows/fmode.c endif OBJ = $(PY_CORE_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) include $(TOP)/py/mkrules.mk micropython-1.12/mpy-cross/README.md000066400000000000000000000021261357706137100172360ustar00rootroot00000000000000MicroPython cross compiler ========================== This directory contains the MicroPython cross compiler, which runs under any Unix-like system and compiles .py scripts into .mpy files. Build it as usual: $ make The compiler is called `mpy-cross`. Invoke it as: $ ./mpy-cross foo.py This will create a file foo.mpy which can then be copied to a place accessible by the target MicroPython runtime (eg onto a pyboard's filesystem), and then imported like any other Python module using `import foo`. Different target runtimes may require a different format of the compiled bytecode, and such options can be passed to the cross compiler. For example, the unix port of MicroPython requires the following: $ ./mpy-cross -mcache-lookup-bc foo.py If the Python code contains `@native` or `@viper` annotations, then you must specify `-march` to match the target architecture. Run `./mpy-cross -h` to get a full list of options. The optimisation level is 0 by default. Optimisation levels are detailed in https://docs.micropython.org/en/latest/library/micropython.html#micropython.opt_level micropython-1.12/mpy-cross/gccollect.c000066400000000000000000000105651357706137100200700ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "py/mpstate.h" #include "py/gc.h" #if MICROPY_ENABLE_GC // Even if we have specific support for an architecture, it is // possible to force use of setjmp-based implementation. #if !MICROPY_GCREGS_SETJMP // We capture here callee-save registers, i.e. ones which may contain // interesting values held there by our callers. It doesn't make sense // to capture caller-saved registers, because they, well, put on the // stack already by the caller. #if defined(__x86_64__) typedef mp_uint_t regs_t[6]; STATIC void gc_helper_get_regs(regs_t arr) { register long rbx asm ("rbx"); register long rbp asm ("rbp"); register long r12 asm ("r12"); register long r13 asm ("r13"); register long r14 asm ("r14"); register long r15 asm ("r15"); #ifdef __clang__ // TODO: // This is dirty workaround for Clang. It tries to get around // uncompliant (wrt to GCC) behavior of handling register variables. // Application of this patch here is random, and done only to unbreak // MacOS build. Better, cross-arch ways to deal with Clang issues should // be found. asm("" : "=r"(rbx)); asm("" : "=r"(rbp)); asm("" : "=r"(r12)); asm("" : "=r"(r13)); asm("" : "=r"(r14)); asm("" : "=r"(r15)); #endif arr[0] = rbx; arr[1] = rbp; arr[2] = r12; arr[3] = r13; arr[4] = r14; arr[5] = r15; } #elif defined(__i386__) typedef mp_uint_t regs_t[4]; STATIC void gc_helper_get_regs(regs_t arr) { register long ebx asm ("ebx"); register long esi asm ("esi"); register long edi asm ("edi"); register long ebp asm ("ebp"); arr[0] = ebx; arr[1] = esi; arr[2] = edi; arr[3] = ebp; } #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) typedef mp_uint_t regs_t[10]; STATIC void gc_helper_get_regs(regs_t arr) { register long r4 asm ("r4"); register long r5 asm ("r5"); register long r6 asm ("r6"); register long r7 asm ("r7"); register long r8 asm ("r8"); register long r9 asm ("r9"); register long r10 asm ("r10"); register long r11 asm ("r11"); register long r12 asm ("r12"); register long r13 asm ("r13"); arr[0] = r4; arr[1] = r5; arr[2] = r6; arr[3] = r7; arr[4] = r8; arr[5] = r9; arr[6] = r10; arr[7] = r11; arr[8] = r12; arr[9] = r13; } #else // If we don't have architecture-specific optimized support, // just fall back to setjmp-based implementation. #undef MICROPY_GCREGS_SETJMP #define MICROPY_GCREGS_SETJMP (1) #endif // Arch-specific selection #endif // !MICROPY_GCREGS_SETJMP // If MICROPY_GCREGS_SETJMP was requested explicitly, or if // we enabled it as a fallback above. #if MICROPY_GCREGS_SETJMP #include typedef jmp_buf regs_t; STATIC void gc_helper_get_regs(regs_t arr) { setjmp(arr); } #endif // MICROPY_GCREGS_SETJMP void gc_collect(void) { gc_collect_start(); regs_t regs; gc_helper_get_regs(regs); // GC stack (and regs because we captured them) void **regs_ptr = (void**)(void*)®s; gc_collect_root(regs_ptr, ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)®s) / sizeof(mp_uint_t)); gc_collect_end(); } #endif //MICROPY_ENABLE_GC micropython-1.12/mpy-cross/main.c000066400000000000000000000324241357706137100170530ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "py/compile.h" #include "py/persistentcode.h" #include "py/runtime.h" #include "py/gc.h" #include "py/stackctrl.h" #include "genhdr/mpversion.h" #ifdef _WIN32 #include "ports/windows/fmode.h" #endif // Command line options, with their defaults STATIC uint emit_opt = MP_EMIT_OPT_NONE; mp_uint_t mp_verbose_flag = 0; // Heap size of GC heap (if enabled) // Make it larger on a 64 bit machine, because pointers are larger. long heap_size = 1024*1024 * (sizeof(mp_uint_t) / 4); STATIC void stderr_print_strn(void *env, const char *str, mp_uint_t len) { (void)env; ssize_t dummy = write(STDERR_FILENO, str, len); (void)dummy; } STATIC const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; STATIC int compile_and_save(const char *file, const char *output_file, const char *source_file) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_file(file); qstr source_name; if (source_file == NULL) { source_name = lex->source_name; } else { source_name = qstr_from_str(source_file); } #if MICROPY_PY___FILE__ mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); #endif mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_raw_code_t *rc = mp_compile_to_raw_code(&parse_tree, source_name, false); vstr_t vstr; vstr_init(&vstr, 16); if (output_file == NULL) { vstr_add_str(&vstr, file); vstr_cut_tail_bytes(&vstr, 2); vstr_add_str(&vstr, "mpy"); } else { vstr_add_str(&vstr, output_file); } mp_raw_code_save_file(rc, vstr_null_terminated_str(&vstr)); vstr_clear(&vstr); nlr_pop(); return 0; } else { // uncaught exception mp_obj_print_exception(&mp_stderr_print, (mp_obj_t)nlr.ret_val); return 1; } } STATIC int usage(char **argv) { printf( "usage: %s [] [-X ] \n" "Options:\n" "--version : show version information\n" "-o : output file for compiled bytecode (defaults to input with .mpy extension)\n" "-s : source filename to embed in the compiled bytecode (defaults to input file)\n" "-v : verbose (trace various operations); can be multiple\n" "-O[N] : apply bytecode optimizations of level N\n" "\n" "Target specific options:\n" "-msmall-int-bits=number : set the maximum bits used to encode a small-int\n" "-mno-unicode : don't support unicode in compiled strings\n" "-mcache-lookup-bc : cache map lookups in the bytecode\n" "-march= : set architecture for native emitter; x86, x64, armv6, armv7m, armv7em, armv7emsp, armv7emdp, xtensa, xtensawin\n" "\n" "Implementation specific options:\n", argv[0] ); int impl_opts_cnt = 0; printf( #if MICROPY_EMIT_NATIVE " emit={bytecode,native,viper} -- set the default code emitter\n" #else " emit=bytecode -- set the default code emitter\n" #endif ); impl_opts_cnt++; printf( " heapsize= -- set the heap size for the GC (default %ld)\n" , heap_size); impl_opts_cnt++; if (impl_opts_cnt == 0) { printf(" (none)\n"); } return 1; } // Process options which set interpreter init options STATIC void pre_process_options(int argc, char **argv) { for (int a = 1; a < argc; a++) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-X") == 0) { if (a + 1 >= argc) { exit(usage(argv)); } if (strcmp(argv[a + 1], "emit=bytecode") == 0) { emit_opt = MP_EMIT_OPT_BYTECODE; #if MICROPY_EMIT_NATIVE } else if (strcmp(argv[a + 1], "emit=native") == 0) { emit_opt = MP_EMIT_OPT_NATIVE_PYTHON; } else if (strcmp(argv[a + 1], "emit=viper") == 0) { emit_opt = MP_EMIT_OPT_VIPER; #endif } else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) { char *end; heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0); // Don't bring unneeded libc dependencies like tolower() // If there's 'w' immediately after number, adjust it for // target word size. Note that it should be *before* size // suffix like K or M, to avoid confusion with kilowords, // etc. the size is still in bytes, just can be adjusted // for word size (taking 32bit as baseline). bool word_adjust = false; if ((*end | 0x20) == 'w') { word_adjust = true; end++; } if ((*end | 0x20) == 'k') { heap_size *= 1024; } else if ((*end | 0x20) == 'm') { heap_size *= 1024 * 1024; } if (word_adjust) { heap_size = heap_size * BYTES_PER_WORD / 4; } } else { exit(usage(argv)); } a++; } } } } MP_NOINLINE int main_(int argc, char **argv) { mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); pre_process_options(argc, argv); char *heap = malloc(heap_size); gc_init(heap, heap + heap_size); mp_init(); #ifdef _WIN32 set_fmode_binary(); #endif mp_obj_list_init(mp_sys_path, 0); mp_obj_list_init(mp_sys_argv, 0); #if MICROPY_EMIT_NATIVE // Set default emitter options MP_STATE_VM(default_emit_opt) = emit_opt; #else (void)emit_opt; #endif // set default compiler configuration mp_dynamic_compiler.small_int_bits = 31; mp_dynamic_compiler.opt_cache_map_lookup_in_bytecode = 0; mp_dynamic_compiler.py_builtins_str_unicode = 1; #if defined(__i386__) mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86; #elif defined(__x86_64__) mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64; mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN); #elif defined(__arm__) && !defined(__thumb2__) mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; #else mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_NONE; mp_dynamic_compiler.nlr_buf_num_regs = 0; #endif const char *input_file = NULL; const char *output_file = NULL; const char *source_file = NULL; // parse main options for (int a = 1; a < argc; a++) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-X") == 0) { a += 1; } else if (strcmp(argv[a], "--version") == 0) { printf("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "\n"); return 0; } else if (strcmp(argv[a], "-v") == 0) { mp_verbose_flag++; } else if (strncmp(argv[a], "-O", 2) == 0) { if (unichar_isdigit(argv[a][2])) { MP_STATE_VM(mp_optimise_value) = argv[a][2] & 0xf; } else { MP_STATE_VM(mp_optimise_value) = 0; for (char *p = argv[a] + 1; *p && *p == 'O'; p++, MP_STATE_VM(mp_optimise_value)++); } } else if (strcmp(argv[a], "-o") == 0) { if (a + 1 >= argc) { exit(usage(argv)); } a += 1; output_file = argv[a]; } else if (strcmp(argv[a], "-s") == 0) { if (a + 1 >= argc) { exit(usage(argv)); } a += 1; source_file = argv[a]; } else if (strncmp(argv[a], "-msmall-int-bits=", sizeof("-msmall-int-bits=") - 1) == 0) { char *end; mp_dynamic_compiler.small_int_bits = strtol(argv[a] + sizeof("-msmall-int-bits=") - 1, &end, 0); if (*end) { return usage(argv); } // TODO check that small_int_bits is within range of host's capabilities } else if (strcmp(argv[a], "-mno-cache-lookup-bc") == 0) { mp_dynamic_compiler.opt_cache_map_lookup_in_bytecode = 0; } else if (strcmp(argv[a], "-mcache-lookup-bc") == 0) { mp_dynamic_compiler.opt_cache_map_lookup_in_bytecode = 1; } else if (strcmp(argv[a], "-mno-unicode") == 0) { mp_dynamic_compiler.py_builtins_str_unicode = 0; } else if (strcmp(argv[a], "-municode") == 0) { mp_dynamic_compiler.py_builtins_str_unicode = 1; } else if (strncmp(argv[a], "-march=", sizeof("-march=") - 1) == 0) { const char *arch = argv[a] + sizeof("-march=") - 1; if (strcmp(arch, "x86") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86; } else if (strcmp(arch, "x64") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64; mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN); } else if (strcmp(arch, "armv6") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; } else if (strcmp(arch, "armv7m") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7M; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; } else if (strcmp(arch, "armv7em") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EM; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; } else if (strcmp(arch, "armv7emsp") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EMSP; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; } else if (strcmp(arch, "armv7emdp") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EMDP; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; } else if (strcmp(arch, "xtensa") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSA; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSA; } else if (strcmp(arch, "xtensawin") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSAWIN; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSAWIN; } else { return usage(argv); } } else { return usage(argv); } } else { if (input_file != NULL) { mp_printf(&mp_stderr_print, "multiple input files\n"); exit(1); } input_file = argv[a]; } } if (input_file == NULL) { mp_printf(&mp_stderr_print, "no input file\n"); exit(1); } int ret = compile_and_save(input_file, output_file, source_file); #if MICROPY_PY_MICROPYTHON_MEM_INFO if (mp_verbose_flag) { mp_micropython_mem_info(0, NULL); } #endif mp_deinit(); return ret & 0xff; } int main(int argc, char **argv) { mp_stack_ctrl_init(); return main_(argc, argv); } uint mp_import_stat(const char *path) { (void)path; return MP_IMPORT_STAT_NO_EXIST; } void nlr_jump_fail(void *val) { printf("FATAL: uncaught NLR %p\n", val); exit(1); } micropython-1.12/mpy-cross/mpconfigport.h000066400000000000000000000131561357706137100206440ustar00rootroot00000000000000/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2013-2015 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // options to control how MicroPython is built #define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_PERSISTENT_CODE_LOAD (0) #define MICROPY_PERSISTENT_CODE_SAVE (1) #define MICROPY_EMIT_X64 (1) #define MICROPY_EMIT_X86 (1) #define MICROPY_EMIT_THUMB (1) #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_EMIT_INLINE_THUMB_ARMV7M (1) #define MICROPY_EMIT_INLINE_THUMB_FLOAT (1) #define MICROPY_EMIT_ARM (1) #define MICROPY_EMIT_XTENSA (1) #define MICROPY_EMIT_INLINE_XTENSA (1) #define MICROPY_EMIT_XTENSAWIN (1) #define MICROPY_DYNAMIC_COMPILER (1) #define MICROPY_COMP_CONST_FOLDING (1) #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_CONST (1) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_RETURN_IF_EXPR (1) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #define MICROPY_READER_POSIX (1) #define MICROPY_ENABLE_RUNTIME (0) #define MICROPY_ENABLE_GC (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_HELPER_LEXER_UNIX (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) #define MICROPY_WARNINGS (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_CPYTHON_COMPAT (1) #define MICROPY_USE_INTERNAL_PRINTF (0) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) // Define to 1 to use undertested inefficient GC helper implementation // (if more efficient arch-specific one is not available). #ifndef MICROPY_GCREGS_SETJMP #ifdef __mips__ #define MICROPY_GCREGS_SETJMP (1) #else #define MICROPY_GCREGS_SETJMP (0) #endif #endif #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_GC (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_SYS (0) // type definitions for the specific machine #ifdef __LP64__ typedef long mp_int_t; // must be pointer size typedef unsigned long mp_uint_t; // must be pointer size #elif defined ( __MINGW32__ ) && defined( _WIN64 ) #include typedef __int64 mp_int_t; typedef unsigned __int64 mp_uint_t; #elif defined ( _MSC_VER ) && defined( _WIN64 ) typedef __int64 mp_int_t; typedef unsigned __int64 mp_uint_t; #else // These are definitions for machines where sizeof(int) == sizeof(void*), // regardless for actual size. typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size #endif // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; #else typedef long mp_off_t; #endif #define MP_PLAT_PRINT_STRN(str, len) (void)0 // We need to provide a declaration/definition of alloca() #ifdef __FreeBSD__ #include #elif defined( _WIN32 ) #include #else #include #endif #include // MSVC specifics - see windows/mpconfigport.h for explanation #ifdef _MSC_VER #define MP_ENDIANNESS_LITTLE (1) #define NORETURN __declspec(noreturn) #define MP_NOINLINE __declspec(noinline) #define MP_LIKELY(x) (x) #define MP_UNLIKELY(x) (x) #define MICROPY_PORT_CONSTANTS { "dummy", 0 } #ifdef _WIN64 #define MP_SSIZE_MAX _I64_MAX #else #define MP_SSIZE_MAX _I32_MAX #endif #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)(p)) //Avoid compiler warning about different const qualifiers #define restrict #define inline __inline #define alignof(t) __alignof(t) #undef MICROPY_ALLOC_PATH_MAX #define MICROPY_ALLOC_PATH_MAX 260 #define PATH_MAX MICROPY_ALLOC_PATH_MAX #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #ifdef _WIN64 #define SSIZE_MAX _I64_MAX typedef __int64 ssize_t; #else #define SSIZE_MAX _I32_MAX typedef int ssize_t; #endif typedef mp_off_t off_t; #endif micropython-1.12/mpy-cross/mphalport.h000066400000000000000000000000771357706137100201410ustar00rootroot00000000000000// prevent including extmod/virtpin.h #define mp_hal_pin_obj_t micropython-1.12/mpy-cross/mpy-cross.vcxproj000066400000000000000000000125601357706137100213330ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 {740F3A30-3B6C-4B59-9C50-AE4D5A4A9D12} mpy-cross True $(MSBuildThisFileDirectory)build\ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)..\ports\windows\msvc\ Application $(DefaultPlatformToolset) Application $(DefaultPlatformToolset) Application $(DefaultPlatformToolset) Application $(DefaultPlatformToolset) msvc/user.props micropython-1.12/mpy-cross/qstrdefsport.h000066400000000000000000000000371357706137100206670ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/000077500000000000000000000000001357706137100151715ustar00rootroot00000000000000micropython-1.12/ports/bare-arm/000077500000000000000000000000001357706137100166575ustar00rootroot00000000000000micropython-1.12/ports/bare-arm/Makefile000066400000000000000000000020261357706137100203170ustar00rootroot00000000000000include ../../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk CROSS_COMPILE = arm-none-eabi- INC += -I. INC += -I$(TOP) INC += -I$(BUILD) CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) CSUPEROPT = -Os # save some code space #Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -O0 -ggdb else CFLAGS += -Os -DNDEBUG endif LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref LIBS = SRC_C = \ main.c \ # printf.c \ string0.c \ malloc0.c \ gccollect.c \ SRC_S = \ # startup_stm32f40xx.s \ gchelper.s \ OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o)) all: $(BUILD)/firmware.elf $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ include $(TOP)/py/mkrules.mk micropython-1.12/ports/bare-arm/main.c000066400000000000000000000056401357706137100177540ustar00rootroot00000000000000#include #include #include #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" #include "py/mperrno.h" void do_str(const char *src, mp_parse_input_kind_t input_kind) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } } int main(int argc, char **argv) { mp_init(); do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT); do_str("for i in range(10):\n print(i)", MP_PARSE_FILE_INPUT); mp_deinit(); return 0; } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { mp_raise_OSError(MP_ENOENT); } mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void nlr_jump_fail(void *val) { while (1); } void NORETURN __fatal_error(const char *msg) { while (1); } #ifndef NDEBUG void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); __fatal_error("Assertion failed"); } #endif /* int _lseek() {return 0;} int _read() {return 0;} int _write() {return 0;} int _close() {return 0;} void _exit(int x) {for(;;){}} int _sbrk() {return 0;} int _kill() {return 0;} int _getpid() {return 0;} int _fstat() {return 0;} int _isatty() {return 0;} */ void *malloc(size_t n) {return NULL;} void *calloc(size_t nmemb, size_t size) {return NULL;} void *realloc(void *ptr, size_t size) {return NULL;} void free(void *p) {} int printf(const char *m, ...) {return 0;} void *memcpy(void *dest, const void *src, size_t n) {return NULL;} int memcmp(const void *s1, const void *s2, size_t n) {return 0;} void *memmove(void *dest, const void *src, size_t n) {return NULL;} void *memset(void *s, int c, size_t n) {return NULL;} int strcmp(const char *s1, const char* s2) {return 0;} int strncmp(const char *s1, const char* s2, size_t n) {return 0;} size_t strlen(const char *s) {return 0;} char *strcat(char *dest, const char *src) {return NULL;} char *strchr(const char *dest, int c) {return NULL;} #include int vprintf(const char *format, va_list ap) {return 0;} int vsnprintf(char *str, size_t size, const char *format, va_list ap) {return 0;} #undef putchar int putchar(int c) {return 0;} int puts(const char *s) {return 0;} void _start(void) {main(0, NULL);} micropython-1.12/ports/bare-arm/mpconfigport.h000066400000000000000000000047451357706137100215510ustar00rootroot00000000000000#include // options to control how MicroPython is built #define MICROPY_QSTR_BYTES_IN_HASH (1) #define MICROPY_ALLOC_PATH_MAX (512) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (0) #define MICROPY_COMP_CONST (0) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_ENABLE_GC (0) #define MICROPY_HELPER_REPL (0) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_BUILTINS_BYTEARRAY (0) #define MICROPY_PY_BUILTINS_DICT_FROMKEYS (0) #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) #define MICROPY_PY_BUILTINS_ENUMERATE (0) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_SET (0) #define MICROPY_PY_BUILTINS_SLICE (0) #define MICROPY_PY_BUILTINS_PROPERTY (0) #define MICROPY_PY_BUILTINS_STR_COUNT (0) #define MICROPY_PY_BUILTINS_STR_OP_MODULO (0) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_GC (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS (0) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_USE_INTERNAL_PRINTF (0) // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) #define UINT_FMT "%lu" #define INT_FMT "%ld" typedef int32_t mp_int_t; // must be pointer size typedef uint32_t mp_uint_t; // must be pointer size typedef long mp_off_t; // dummy print #define MP_PLAT_PRINT_STRN(str, len) (void)0 // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, // We need to provide a declaration/definition of alloca() #include micropython-1.12/ports/bare-arm/mphalport.h000066400000000000000000000000161357706137100210330ustar00rootroot00000000000000// empty file micropython-1.12/ports/bare-arm/qstrdefsport.h000066400000000000000000000000371357706137100215700ustar00rootroot00000000000000// qstrs specific to this port micropython-1.12/ports/bare-arm/stm32f405.ld000066400000000000000000000067131357706137100205560ustar00rootroot00000000000000/* GNU linker script for STM32F405 */ /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x100000 /* entire flash, 1 MiB */ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 0x004000 /* sector 0, 16 KiB */ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 0x080000 /* sectors 5,6,7,8, 4*128KiB = 512 KiB (could increase it more) */ CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 0x010000 /* 64 KiB */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x020000 /* 128 KiB */ } /* top end of the stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); /* RAM extents for the garbage collector */ _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_end = 0x2001c000; /* tunable */ /* define output sections */ SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH_ISR /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ /* *(.glue_7t) */ /* glue thumb to arm code */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ _sidata = _etext; /* This is used by the startup in order to initialize the .data secion */ } >FLASH_TEXT /* .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH */ /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ .data : AT ( _sidata ) { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ _ram_start = .; /* create a global symbol at ram start for garbage collector */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM /* Uninitialized data section */ .bss : { . = ALIGN(4); _sbss = .; /* define a global symbol at bss start; used by startup code */ *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end; used by startup code */ } >RAM /* this is to define the start of the heap, and make sure we have a minimum size */ .heap : { . = ALIGN(4); _heap_start = .; /* define a global symbol at heap start */ } >RAM /* this just checks there is enough RAM for the stack */ .stack : { . = ALIGN(4); } >RAM /* Remove information from the standard libraries */ /* /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } */ .ARM.attributes 0 : { *(.ARM.attributes) } } micropython-1.12/ports/cc3200/000077500000000000000000000000001357706137100160635ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/000077500000000000000000000000001357706137100174545ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/FreeRTOSConfig.h000066400000000000000000000172441357706137100223540ustar00rootroot00000000000000/* FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that has become a de facto standard. * * * * Help yourself get started quickly and support the FreeRTOS * * project by purchasing a FreeRTOS tutorial book, reference * * manual, or both from: http://www.FreeRTOS.org/Documentation * * * * Thank you! * * * *************************************************************************** This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available from the following link: http://www.freertos.org/a00114.html 1 tab == 4 spaces! *************************************************************************** * * * Having a problem? Start by reading the FAQ "My application does * * not run, what could be wrong?" * * * * http://www.FreeRTOS.org/FAQHelp.html * * * *************************************************************************** http://www.FreeRTOS.org - Documentation, books, training, latest versions, license and Real Time Engineers Ltd. contact details. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H /*----------------------------------------------------------- * Application specific definitions. * * These definitions should be adjusted for your particular hardware and * application requirements. * * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. * * See http://www.freertos.org/a00110.html. *----------------------------------------------------------*/ #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 1 #define configUSE_TICK_HOOK 1 #define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 ) #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 72 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( \ 16384 /* 16kbytes for FreeRTOS data structures and heap */ \ - sizeof(StaticTask_t) - configMINIMAL_STACK_SIZE * sizeof(StackType_t) /* TCB+stack for idle task */ \ - sizeof(StaticTask_t) - 1024 /* TCB+stack for servers task */ \ - sizeof(StaticTask_t) - 6656 /* TCB+stack for main MicroPython task */ \ - sizeof(StaticTask_t) - 896 /* TCB+stack for simplelink spawn task */ \ ) ) #define configMAX_TASK_NAME_LEN ( 8 ) #define configUSE_TRACE_FACILITY 0 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 #define configUSE_CO_ROUTINES 0 #define configUSE_MUTEXES 0 #define configUSE_RECURSIVE_MUTEXES 0 #ifdef DEBUG #define configCHECK_FOR_STACK_OVERFLOW 1 #else #define configCHECK_FOR_STACK_OVERFLOW 0 #endif #define configUSE_QUEUE_SETS 0 #define configUSE_COUNTING_SEMAPHORES 0 #define configUSE_ALTERNATIVE_API 0 #define configMAX_PRIORITIES ( 4UL ) #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) #define configQUEUE_REGISTRY_SIZE 0 /* Timer related defines. */ #define configUSE_TIMERS 0 #define configTIMER_TASK_PRIORITY 2 #define configTIMER_QUEUE_LENGTH 20 #define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) #ifdef DEBUG #define configUSE_MALLOC_FAILED_HOOK 1 #else #define configUSE_MALLOC_FAILED_HOOK 0 #endif #define configENABLE_BACKWARD_COMPATIBILITY 0 /* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ #define INCLUDE_vTaskPrioritySet 0 #define INCLUDE_uxTaskPriorityGet 0 #define INCLUDE_vTaskDelete 0 #define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskSuspend 0 #define INCLUDE_vTaskDelayUntil 0 #define INCLUDE_vTaskDelay 1 #ifdef DEBUG #define INCLUDE_uxTaskGetStackHighWaterMark 1 #else #define INCLUDE_uxTaskGetStackHighWaterMark 0 #endif #define INCLUDE_xTaskGetSchedulerState 0 #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 #ifdef DEBUG #define INCLUDE_xTaskGetIdleTaskHandle 1 #else #define INCLUDE_xTaskGetIdleTaskHandle 0 #endif #define INCLUDE_pcTaskGetTaskName 0 #define INCLUDE_eTaskGetState 0 #define INCLUDE_xSemaphoreGetMutexHolder 0 #define configKERNEL_INTERRUPT_PRIORITY ( 7 << 5 ) /* Priority 7, or 255 as only the top three bits are implemented. This is the lowest priority. */ /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( 1 << 5 ) /* Priority 5, or 160 as only the top three bits are implemented. */ /* Use the Cortex-M3 optimised task selection rather than the generic C code version. */ #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 /* We provide a definition of ucHeap so it can go in a special segment. */ #define configAPPLICATION_ALLOCATED_HEAP 1 /* We use static versions of functions (like xTaskCreateStatic) */ #define configSUPPORT_STATIC_ALLOCATION 1 /* For threading */ #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1 #undef configUSE_MUTEXES #define configUSE_MUTEXES 1 #undef INCLUDE_vTaskDelete #define INCLUDE_vTaskDelete 1 #endif /* FREERTOS_CONFIG_H */ micropython-1.12/ports/cc3200/FreeRTOS/License/000077500000000000000000000000001357706137100210365ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/License/license.txt000066400000000000000000000502501357706137100232230ustar00rootroot00000000000000The FreeRTOS open source license covers the FreeRTOS source files, which are located in the /FreeRTOS/Source directory of the official FreeRTOS download. It also covers most of the source files in the demo application projects, which are located in the /FreeRTOS/Demo directory of the official FreeRTOS download. The demo projects may also include third party software that is not part of FreeRTOS and is licensed separately to FreeRTOS. Examples of third party software includes header files provided by chip or tools vendors, linker scripts, peripheral drivers, etc. All the software in subdirectories of the /FreeRTOS directory is either open source or distributed with permission, and is free for use. For the avoidance of doubt, refer to the comments at the top of each source file. ---------------------------------------------------------------------------- NOTE: The modification to the GPL is included to allow you to distribute a combined work that includes FreeRTOS without being obliged to provide the source code for proprietary components. ---------------------------------------------------------------------------- Applying to FreeRTOS V8.2.3 up to the latest version, the FreeRTOS GPL Exception Text follows: Any FreeRTOS *source code*, whether modified or in it's original release form, or whether in whole or in part, can only be distributed by you under the terms of the GNU General Public License plus this exception. An independent module is a module which is not derived from or based on FreeRTOS. Clause 1: Linking FreeRTOS with other modules is making a combined work based on FreeRTOS. Thus, the terms and conditions of the GNU General Public License V2 cover the whole combination. As a special exception, the copyright holders of FreeRTOS give you permission to link FreeRTOS with independent modules to produce a statically linked executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on FreeRTOS. Clause 2: FreeRTOS may not be used for any competitive or comparative purpose, including the publication of any form of run time or compile time metric, without the express permission of Real Time Engineers Ltd. (this is the norm within the industry and is intended to ensure information accuracy). -------------------------------------------------------------------- The standard GPL V2 text: GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License** as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. micropython-1.12/ports/cc3200/FreeRTOS/Source/000077500000000000000000000000001357706137100207145ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/Source/croutine.c000066400000000000000000000360201357706137100227110ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #include "FreeRTOS.h" #include "task.h" #include "croutine.h" /* Remove the whole file is co-routines are not being used. */ #if( configUSE_CO_ROUTINES != 0 ) /* * Some kernel aware debuggers require data to be viewed to be global, rather * than file scope. */ #ifdef portREMOVE_STATIC_QUALIFIER #define static #endif /* Lists for ready and blocked co-routines. --------------------*/ static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */ static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ /* Other file private variables. --------------------------------*/ CRCB_t * pxCurrentCoRoutine = NULL; static UBaseType_t uxTopCoRoutineReadyPriority = 0; static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; /* The initial state of the co-routine when it is created. */ #define corINITIAL_STATE ( 0 ) /* * Place the co-routine represented by pxCRCB into the appropriate ready queue * for the priority. It is inserted at the end of the list. * * This macro accesses the co-routine ready lists and therefore must not be * used from within an ISR. */ #define prvAddCoRoutineToReadyQueue( pxCRCB ) \ { \ if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ { \ uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ } \ vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ } /* * Utility to ready all the lists used by the scheduler. This is called * automatically upon the creation of the first co-routine. */ static void prvInitialiseCoRoutineLists( void ); /* * Co-routines that are readied by an interrupt cannot be placed directly into * the ready lists (there is no mutual exclusion). Instead they are placed in * in the pending ready list in order that they can later be moved to the ready * list by the co-routine scheduler. */ static void prvCheckPendingReadyList( void ); /* * Macro that looks at the list of co-routines that are currently delayed to * see if any require waking. * * Co-routines are stored in the queue in the order of their wake time - * meaning once one co-routine has been found whose timer has not expired * we need not look any further down the list. */ static void prvCheckDelayedList( void ); /*-----------------------------------------------------------*/ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ) { BaseType_t xReturn; CRCB_t *pxCoRoutine; /* Allocate the memory that will store the co-routine control block. */ pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); if( pxCoRoutine ) { /* If pxCurrentCoRoutine is NULL then this is the first co-routine to be created and the co-routine data structures need initialising. */ if( pxCurrentCoRoutine == NULL ) { pxCurrentCoRoutine = pxCoRoutine; prvInitialiseCoRoutineLists(); } /* Check the priority is within limits. */ if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) { uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; } /* Fill out the co-routine control block from the function parameters. */ pxCoRoutine->uxState = corINITIAL_STATE; pxCoRoutine->uxPriority = uxPriority; pxCoRoutine->uxIndex = uxIndex; pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; /* Initialise all the other co-routine control block parameters. */ vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); /* Set the co-routine control block as a link back from the ListItem_t. This is so we can get back to the containing CRCB from a generic item in a list. */ listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); /* Event lists are always in priority order. */ listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); /* Now the co-routine has been initialised it can be added to the ready list at the correct priority. */ prvAddCoRoutineToReadyQueue( pxCoRoutine ); xReturn = pdPASS; } else { xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; } return xReturn; } /*-----------------------------------------------------------*/ void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) { TickType_t xTimeToWake; /* Calculate the time to wake - this may overflow but this is not a problem. */ xTimeToWake = xCoRoutineTickCount + xTicksToDelay; /* We must remove ourselves from the ready list before adding ourselves to the blocked list as the same list item is used for both lists. */ ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); /* The list item will be inserted in wake time order. */ listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); if( xTimeToWake < xCoRoutineTickCount ) { /* Wake time has overflowed. Place this item in the overflow list. */ vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); } else { /* The wake time has not overflowed, so we can use the current block list. */ vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); } if( pxEventList ) { /* Also add the co-routine to an event list. If this is done then the function must be called with interrupts disabled. */ vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); } } /*-----------------------------------------------------------*/ static void prvCheckPendingReadyList( void ) { /* Are there any co-routines waiting to get moved to the ready list? These are co-routines that have been readied by an ISR. The ISR cannot access the ready lists itself. */ while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) { CRCB_t *pxUnblockedCRCB; /* The pending ready list can be accessed by an ISR. */ portDISABLE_INTERRUPTS(); { pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); } portENABLE_INTERRUPTS(); ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); } } /*-----------------------------------------------------------*/ static void prvCheckDelayedList( void ) { CRCB_t *pxCRCB; xPassedTicks = xTaskGetTickCount() - xLastTickCount; while( xPassedTicks ) { xCoRoutineTickCount++; xPassedTicks--; /* If the tick count has overflowed we need to swap the ready lists. */ if( xCoRoutineTickCount == 0 ) { List_t * pxTemp; /* Tick count has overflowed so we need to swap the delay lists. If there are any items in pxDelayedCoRoutineList here then there is an error! */ pxTemp = pxDelayedCoRoutineList; pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; pxOverflowDelayedCoRoutineList = pxTemp; } /* See if this tick has made a timeout expire. */ while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) { pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) { /* Timeout not yet expired. */ break; } portDISABLE_INTERRUPTS(); { /* The event could have occurred just before this critical section. If this is the case then the generic list item will have been moved to the pending ready list and the following line is still valid. Also the pvContainer parameter will have been set to NULL so the following lines are also valid. */ ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); /* Is the co-routine waiting on an event also? */ if( pxCRCB->xEventListItem.pvContainer ) { ( void ) uxListRemove( &( pxCRCB->xEventListItem ) ); } } portENABLE_INTERRUPTS(); prvAddCoRoutineToReadyQueue( pxCRCB ); } } xLastTickCount = xCoRoutineTickCount; } /*-----------------------------------------------------------*/ void vCoRoutineSchedule( void ) { /* See if any co-routines readied by events need moving to the ready lists. */ prvCheckPendingReadyList(); /* See if any delayed co-routines have timed out. */ prvCheckDelayedList(); /* Find the highest priority queue that contains ready co-routines. */ while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) { if( uxTopCoRoutineReadyPriority == 0 ) { /* No more co-routines to check. */ return; } --uxTopCoRoutineReadyPriority; } /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines of the same priority get an equal share of the processor time. */ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); /* Call the co-routine. */ ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); return; } /*-----------------------------------------------------------*/ static void prvInitialiseCoRoutineLists( void ) { UBaseType_t uxPriority; for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) { vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); } vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 ); vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 ); vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); /* Start with pxDelayedCoRoutineList using list1 and the pxOverflowDelayedCoRoutineList using list2. */ pxDelayedCoRoutineList = &xDelayedCoRoutineList1; pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; } /*-----------------------------------------------------------*/ BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ) { CRCB_t *pxUnblockedCRCB; BaseType_t xReturn; /* This function is called from within an interrupt. It can only access event lists and the pending ready list. This function assumes that a check has already been made to ensure pxEventList is not empty. */ pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) { xReturn = pdTRUE; } else { xReturn = pdFALSE; } return xReturn; } #endif /* configUSE_CO_ROUTINES == 0 */ micropython-1.12/ports/cc3200/FreeRTOS/Source/event_groups.c000066400000000000000000000616331357706137100236110ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /* Standard includes. */ #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining all the API functions to use the MPU wrappers. That should only be done when task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* FreeRTOS includes. */ #include "FreeRTOS.h" #include "task.h" #include "timers.h" #include "event_groups.h" /* Lint e961 and e750 are suppressed as a MISRA exception justified because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the header files above, but not in this file, in order to generate the correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ /* The following bit fields convey control information in a task's event list item value. It is important they don't clash with the taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ #if configUSE_16_BIT_TICKS == 1 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U #define eventWAIT_FOR_ALL_BITS 0x0400U #define eventEVENT_BITS_CONTROL_BYTES 0xff00U #else #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL #define eventWAIT_FOR_ALL_BITS 0x04000000UL #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL #endif typedef struct xEventGroupDefinition { EventBits_t uxEventBits; List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ #if( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxEventGroupNumber; #endif #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ #endif } EventGroup_t; /*-----------------------------------------------------------*/ /* * Test the bits set in uxCurrentEventBits to see if the wait condition is met. * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the * wait condition is met if any of the bits set in uxBitsToWait for are also set * in uxCurrentEventBits. */ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; /*-----------------------------------------------------------*/ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) { EventGroup_t *pxEventBits; /* A StaticEventGroup_t object must be provided. */ configASSERT( pxEventGroupBuffer ); /* The user has provided a statically allocated event group - use it. */ pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */ if( pxEventBits != NULL ) { pxEventBits->uxEventBits = 0; vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) { /* Both static and dynamic allocation can be used, so note that this event group was created statically in case the event group is later deleted. */ pxEventBits->ucStaticallyAllocated = pdTRUE; } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ traceEVENT_GROUP_CREATE( pxEventBits ); } else { traceEVENT_GROUP_CREATE_FAILED(); } return ( EventGroupHandle_t ) pxEventBits; } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) EventGroupHandle_t xEventGroupCreate( void ) { EventGroup_t *pxEventBits; /* Allocate the event group. */ pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); if( pxEventBits != NULL ) { pxEventBits->uxEventBits = 0; vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { /* Both static and dynamic allocation can be used, so note this event group was allocated statically in case the event group is later deleted. */ pxEventBits->ucStaticallyAllocated = pdFALSE; } #endif /* configSUPPORT_STATIC_ALLOCATION */ traceEVENT_GROUP_CREATE( pxEventBits ); } else { traceEVENT_GROUP_CREATE_FAILED(); } return ( EventGroupHandle_t ) pxEventBits; } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) { EventBits_t uxOriginalBitValue, uxReturn; EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; BaseType_t xAlreadyYielded; BaseType_t xTimeoutOccurred = pdFALSE; configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( uxBitsToWaitFor != 0 ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) { configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); } #endif vTaskSuspendAll(); { uxOriginalBitValue = pxEventBits->uxEventBits; ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) { /* All the rendezvous bits are now set - no need to block. */ uxReturn = ( uxOriginalBitValue | uxBitsToSet ); /* Rendezvous always clear the bits. They will have been cleared already unless this is the only task in the rendezvous. */ pxEventBits->uxEventBits &= ~uxBitsToWaitFor; xTicksToWait = 0; } else { if( xTicksToWait != ( TickType_t ) 0 ) { traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); /* Store the bits that the calling task is waiting for in the task's event list item so the kernel knows when a match is found. Then enter the blocked state. */ vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); /* This assignment is obsolete as uxReturn will get set after the task unblocks, but some compilers mistakenly generate a warning about uxReturn being returned without being set if the assignment is omitted. */ uxReturn = 0; } else { /* The rendezvous bits were not set, but no block time was specified - just return the current event bit value. */ uxReturn = pxEventBits->uxEventBits; } } } xAlreadyYielded = xTaskResumeAll(); if( xTicksToWait != ( TickType_t ) 0 ) { if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } /* The task blocked to wait for its required bits to be set - at this point either the required bits were set or the block time expired. If the required bits were set they will have been stored in the task's event list item, and they should now be retrieved then cleared. */ uxReturn = uxTaskResetEventItemValue(); if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) { /* The task timed out, just return the current event bit value. */ taskENTER_CRITICAL(); { uxReturn = pxEventBits->uxEventBits; /* Although the task got here because it timed out before the bits it was waiting for were set, it is possible that since it unblocked another task has set the bits. If this is the case then it needs to clear the bits before exiting. */ if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) { pxEventBits->uxEventBits &= ~uxBitsToWaitFor; } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); xTimeoutOccurred = pdTRUE; } else { /* The task unblocked because the bits were set. */ } /* Control bits might be set as the task had blocked should not be returned. */ uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; } traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); return uxReturn; } /*-----------------------------------------------------------*/ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) { EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; EventBits_t uxReturn, uxControlBits = 0; BaseType_t xWaitConditionMet, xAlreadyYielded; BaseType_t xTimeoutOccurred = pdFALSE; /* Check the user is not attempting to wait on the bits used by the kernel itself, and that at least one bit is being requested. */ configASSERT( xEventGroup ); configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( uxBitsToWaitFor != 0 ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) { configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); } #endif vTaskSuspendAll(); { const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; /* Check to see if the wait condition is already met or not. */ xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); if( xWaitConditionMet != pdFALSE ) { /* The wait condition has already been met so there is no need to block. */ uxReturn = uxCurrentEventBits; xTicksToWait = ( TickType_t ) 0; /* Clear the wait bits if requested to do so. */ if( xClearOnExit != pdFALSE ) { pxEventBits->uxEventBits &= ~uxBitsToWaitFor; } else { mtCOVERAGE_TEST_MARKER(); } } else if( xTicksToWait == ( TickType_t ) 0 ) { /* The wait condition has not been met, but no block time was specified, so just return the current value. */ uxReturn = uxCurrentEventBits; } else { /* The task is going to block to wait for its required bits to be set. uxControlBits are used to remember the specified behaviour of this call to xEventGroupWaitBits() - for use when the event bits unblock the task. */ if( xClearOnExit != pdFALSE ) { uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; } else { mtCOVERAGE_TEST_MARKER(); } if( xWaitForAllBits != pdFALSE ) { uxControlBits |= eventWAIT_FOR_ALL_BITS; } else { mtCOVERAGE_TEST_MARKER(); } /* Store the bits that the calling task is waiting for in the task's event list item so the kernel knows when a match is found. Then enter the blocked state. */ vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); /* This is obsolete as it will get set after the task unblocks, but some compilers mistakenly generate a warning about the variable being returned without being set if it is not done. */ uxReturn = 0; traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); } } xAlreadyYielded = xTaskResumeAll(); if( xTicksToWait != ( TickType_t ) 0 ) { if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } /* The task blocked to wait for its required bits to be set - at this point either the required bits were set or the block time expired. If the required bits were set they will have been stored in the task's event list item, and they should now be retrieved then cleared. */ uxReturn = uxTaskResetEventItemValue(); if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) { taskENTER_CRITICAL(); { /* The task timed out, just return the current event bit value. */ uxReturn = pxEventBits->uxEventBits; /* It is possible that the event bits were updated between this task leaving the Blocked state and running again. */ if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) { if( xClearOnExit != pdFALSE ) { pxEventBits->uxEventBits &= ~uxBitsToWaitFor; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); /* Prevent compiler warnings when trace macros are not used. */ xTimeoutOccurred = pdFALSE; } else { /* The task unblocked because the bits were set. */ } /* The task blocked so control bits may have been set. */ uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; } traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); return uxReturn; } /*-----------------------------------------------------------*/ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) { EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; EventBits_t uxReturn; /* Check the user is not attempting to clear the bits used by the kernel itself. */ configASSERT( xEventGroup ); configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); taskENTER_CRITICAL(); { traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); /* The value returned is the event group value prior to the bits being cleared. */ uxReturn = pxEventBits->uxEventBits; /* Clear the bits. */ pxEventBits->uxEventBits &= ~uxBitsToClear; } taskEXIT_CRITICAL(); return uxReturn; } /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) { BaseType_t xReturn; traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); return xReturn; } #endif /*-----------------------------------------------------------*/ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) { UBaseType_t uxSavedInterruptStatus; EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; EventBits_t uxReturn; uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { uxReturn = pxEventBits->uxEventBits; } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return uxReturn; } /*-----------------------------------------------------------*/ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) { ListItem_t *pxListItem, *pxNext; ListItem_t const *pxListEnd; List_t *pxList; EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; BaseType_t xMatchFound = pdFALSE; /* Check the user is not attempting to set the bits used by the kernel itself. */ configASSERT( xEventGroup ); configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); pxList = &( pxEventBits->xTasksWaitingForBits ); pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ vTaskSuspendAll(); { traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); pxListItem = listGET_HEAD_ENTRY( pxList ); /* Set the bits. */ pxEventBits->uxEventBits |= uxBitsToSet; /* See if the new bit value should unblock any tasks. */ while( pxListItem != pxListEnd ) { pxNext = listGET_NEXT( pxListItem ); uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); xMatchFound = pdFALSE; /* Split the bits waited for from the control bits. */ uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) { /* Just looking for single bit being set. */ if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) { xMatchFound = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) { /* All bits are set. */ xMatchFound = pdTRUE; } else { /* Need all bits to be set, but not all the bits were set. */ } if( xMatchFound != pdFALSE ) { /* The bits match. Should the bits be cleared on exit? */ if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) { uxBitsToClear |= uxBitsWaitedFor; } else { mtCOVERAGE_TEST_MARKER(); } /* Store the actual event flag value in the task's event list item before removing the task from the event list. The eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows that is was unblocked due to its required bits matching, rather than because it timed out. */ ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); } /* Move onto the next list item. Note pxListItem->pxNext is not used here as the list item may have been removed from the event list and inserted into the ready/pending reading list. */ pxListItem = pxNext; } /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT bit was set in the control word. */ pxEventBits->uxEventBits &= ~uxBitsToClear; } ( void ) xTaskResumeAll(); return pxEventBits->uxEventBits; } /*-----------------------------------------------------------*/ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) { EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); vTaskSuspendAll(); { traceEVENT_GROUP_DELETE( xEventGroup ); while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) { /* Unblock the task, returning 0 as the event list is being deleted and cannot therefore have any bits set. */ configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); } #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) { /* The event group can only have been allocated dynamically - free it again. */ vPortFree( pxEventBits ); } #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) { /* The event group could have been allocated statically or dynamically, so check before attempting to free the memory. */ if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) { vPortFree( pxEventBits ); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } ( void ) xTaskResumeAll(); } /*-----------------------------------------------------------*/ /* For internal use only - execute a 'set bits' command that was pended from an interrupt. */ void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) { ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); } /*-----------------------------------------------------------*/ /* For internal use only - execute a 'clear bits' command that was pended from an interrupt. */ void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) { ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); } /*-----------------------------------------------------------*/ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) { BaseType_t xWaitConditionMet = pdFALSE; if( xWaitForAllBits == pdFALSE ) { /* Task only has to wait for one bit within uxBitsToWaitFor to be set. Is one already set? */ if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) { xWaitConditionMet = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { /* Task has to wait for all the bits in uxBitsToWaitFor to be set. Are they set already? */ if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) { xWaitConditionMet = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } return xWaitConditionMet; } /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) { BaseType_t xReturn; traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); return xReturn; } #endif /*-----------------------------------------------------------*/ #if (configUSE_TRACE_FACILITY == 1) UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) { UBaseType_t xReturn; EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; if( xEventGroup == NULL ) { xReturn = 0; } else { xReturn = pxEventBits->uxEventGroupNumber; } return xReturn; } #endif micropython-1.12/ports/cc3200/FreeRTOS/Source/include/000077500000000000000000000000001357706137100223375ustar00rootroot00000000000000micropython-1.12/ports/cc3200/FreeRTOS/Source/include/FreeRTOS.h000066400000000000000000001014421357706137100241030ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef INC_FREERTOS_H #define INC_FREERTOS_H /* * Include the generic headers required for the FreeRTOS port being used. */ #include /* * If stdint.h cannot be located then: * + If using GCC ensure the -nostdint options is *not* being used. * + Ensure the project's include path includes the directory in which your * compiler stores stdint.h. * + Set any compiler options necessary for it to support C99, as technically * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any * other way). * + The FreeRTOS download includes a simple stdint.h definition that can be * used in cases where none is provided by the compiler. The files only * contains the typedefs required to build FreeRTOS. Read the instructions * in FreeRTOS/source/stdint.readme for more information. */ #include /* READ COMMENT ABOVE. */ #ifdef __cplusplus extern "C" { #endif /* Application specific configuration options. */ #include "FreeRTOSConfig.h" /* Basic FreeRTOS definitions. */ #include "projdefs.h" /* Definitions specific to the port being used. */ #include "portable.h" /* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */ #ifndef configUSE_NEWLIB_REENTRANT #define configUSE_NEWLIB_REENTRANT 0 #endif /* Required if struct _reent is used. */ #if ( configUSE_NEWLIB_REENTRANT == 1 ) #include #endif /* * Check all the required application specific macros have been defined. * These macros are application specific and (as downloaded) are defined * within FreeRTOSConfig.h. */ #ifndef configMINIMAL_STACK_SIZE #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. #endif #ifndef configMAX_PRIORITIES #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_PREEMPTION #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_IDLE_HOOK #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_TICK_HOOK #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_16_BIT_TICKS #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configMAX_PRIORITIES #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. #endif #ifndef configUSE_CO_ROUTINES #define configUSE_CO_ROUTINES 0 #endif #ifndef INCLUDE_vTaskPrioritySet #define INCLUDE_vTaskPrioritySet 0 #endif #ifndef INCLUDE_uxTaskPriorityGet #define INCLUDE_uxTaskPriorityGet 0 #endif #ifndef INCLUDE_vTaskDelete #define INCLUDE_vTaskDelete 0 #endif #ifndef INCLUDE_vTaskSuspend #define INCLUDE_vTaskSuspend 0 #endif #ifndef INCLUDE_vTaskDelayUntil #define INCLUDE_vTaskDelayUntil 0 #endif #ifndef INCLUDE_vTaskDelay #define INCLUDE_vTaskDelay 0 #endif #ifndef INCLUDE_xTaskGetIdleTaskHandle #define INCLUDE_xTaskGetIdleTaskHandle 0 #endif #ifndef INCLUDE_xTaskAbortDelay #define INCLUDE_xTaskAbortDelay 0 #endif #ifndef INCLUDE_xQueueGetMutexHolder #define INCLUDE_xQueueGetMutexHolder 0 #endif #ifndef INCLUDE_xSemaphoreGetMutexHolder #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder #endif #ifndef INCLUDE_xTaskGetHandle #define INCLUDE_xTaskGetHandle 0 #endif #ifndef INCLUDE_uxTaskGetStackHighWaterMark #define INCLUDE_uxTaskGetStackHighWaterMark 0 #endif #ifndef INCLUDE_eTaskGetState #define INCLUDE_eTaskGetState 0 #endif #ifndef INCLUDE_xTaskResumeFromISR #define INCLUDE_xTaskResumeFromISR 1 #endif #ifndef INCLUDE_xTimerPendFunctionCall #define INCLUDE_xTimerPendFunctionCall 0 #endif #ifndef INCLUDE_xTaskGetSchedulerState #define INCLUDE_xTaskGetSchedulerState 0 #endif #ifndef INCLUDE_xTaskGetCurrentTaskHandle #define INCLUDE_xTaskGetCurrentTaskHandle 0 #endif #if configUSE_CO_ROUTINES != 0 #ifndef configMAX_CO_ROUTINE_PRIORITIES #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. #endif #endif #ifndef configUSE_DAEMON_TASK_STARTUP_HOOK #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 #endif #ifndef configUSE_APPLICATION_TASK_TAG #define configUSE_APPLICATION_TASK_TAG 0 #endif #ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 #endif #ifndef configUSE_RECURSIVE_MUTEXES #define configUSE_RECURSIVE_MUTEXES 0 #endif #ifndef configUSE_MUTEXES #define configUSE_MUTEXES 0 #endif #ifndef configUSE_TIMERS #define configUSE_TIMERS 0 #endif #ifndef configUSE_COUNTING_SEMAPHORES #define configUSE_COUNTING_SEMAPHORES 0 #endif #ifndef configUSE_ALTERNATIVE_API #define configUSE_ALTERNATIVE_API 0 #endif #ifndef portCRITICAL_NESTING_IN_TCB #define portCRITICAL_NESTING_IN_TCB 0 #endif #ifndef configMAX_TASK_NAME_LEN #define configMAX_TASK_NAME_LEN 16 #endif #ifndef configIDLE_SHOULD_YIELD #define configIDLE_SHOULD_YIELD 1 #endif #if configMAX_TASK_NAME_LEN < 1 #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h #endif #ifndef configASSERT #define configASSERT( x ) #define configASSERT_DEFINED 0 #else #define configASSERT_DEFINED 1 #endif /* The timers module relies on xTaskGetSchedulerState(). */ #if configUSE_TIMERS == 1 #ifndef configTIMER_TASK_PRIORITY #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. #endif /* configTIMER_TASK_PRIORITY */ #ifndef configTIMER_QUEUE_LENGTH #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. #endif /* configTIMER_QUEUE_LENGTH */ #ifndef configTIMER_TASK_STACK_DEPTH #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. #endif /* configTIMER_TASK_STACK_DEPTH */ #endif /* configUSE_TIMERS */ #ifndef portSET_INTERRUPT_MASK_FROM_ISR #define portSET_INTERRUPT_MASK_FROM_ISR() 0 #endif #ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue #endif #ifndef portCLEAN_UP_TCB #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB #endif #ifndef portPRE_TASK_DELETE_HOOK #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) #endif #ifndef portSETUP_TCB #define portSETUP_TCB( pxTCB ) ( void ) pxTCB #endif #ifndef configQUEUE_REGISTRY_SIZE #define configQUEUE_REGISTRY_SIZE 0U #endif #if ( configQUEUE_REGISTRY_SIZE < 1 ) #define vQueueAddToRegistry( xQueue, pcName ) #define vQueueUnregisterQueue( xQueue ) #define pcQueueGetName( xQueue ) #endif #ifndef portPOINTER_SIZE_TYPE #define portPOINTER_SIZE_TYPE uint32_t #endif /* Remove any unused trace macros. */ #ifndef traceSTART /* Used to perform any necessary initialisation - for example, open a file into which trace is to be written. */ #define traceSTART() #endif #ifndef traceEND /* Use to close a trace, for example close a file into which trace has been written. */ #define traceEND() #endif #ifndef traceTASK_SWITCHED_IN /* Called after a task has been selected to run. pxCurrentTCB holds a pointer to the task control block of the selected task. */ #define traceTASK_SWITCHED_IN() #endif #ifndef traceINCREASE_TICK_COUNT /* Called before stepping the tick count after waking from tickless idle sleep. */ #define traceINCREASE_TICK_COUNT( x ) #endif #ifndef traceLOW_POWER_IDLE_BEGIN /* Called immediately before entering tickless idle. */ #define traceLOW_POWER_IDLE_BEGIN() #endif #ifndef traceLOW_POWER_IDLE_END /* Called when returning to the Idle task after a tickless idle. */ #define traceLOW_POWER_IDLE_END() #endif #ifndef traceTASK_SWITCHED_OUT /* Called before a task has been selected to run. pxCurrentTCB holds a pointer to the task control block of the task being switched out. */ #define traceTASK_SWITCHED_OUT() #endif #ifndef traceTASK_PRIORITY_INHERIT /* Called when a task attempts to take a mutex that is already held by a lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task that holds the mutex. uxInheritedPriority is the priority the mutex holder will inherit (the priority of the task that is attempting to obtain the muted. */ #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) #endif #ifndef traceTASK_PRIORITY_DISINHERIT /* Called when a task releases a mutex, the holding of which had resulted in the task inheriting the priority of a higher priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the mutex. uxOriginalPriority is the task's configured (base) priority. */ #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) #endif #ifndef traceBLOCKING_ON_QUEUE_RECEIVE /* Task is about to block because it cannot read from a queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore upon which the read was attempted. pxCurrentTCB points to the TCB of the task that attempted the read. */ #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) #endif #ifndef traceBLOCKING_ON_QUEUE_SEND /* Task is about to block because it cannot write to a queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore upon which the write was attempted. pxCurrentTCB points to the TCB of the task that attempted the write. */ #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) #endif #ifndef configCHECK_FOR_STACK_OVERFLOW #define configCHECK_FOR_STACK_OVERFLOW 0 #endif /* The following event macros are embedded in the kernel API calls. */ #ifndef traceMOVED_TASK_TO_READY_STATE #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) #endif #ifndef tracePOST_MOVED_TASK_TO_READY_STATE #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) #endif #ifndef traceQUEUE_CREATE #define traceQUEUE_CREATE( pxNewQueue ) #endif #ifndef traceQUEUE_CREATE_FAILED #define traceQUEUE_CREATE_FAILED( ucQueueType ) #endif #ifndef traceCREATE_MUTEX #define traceCREATE_MUTEX( pxNewQueue ) #endif #ifndef traceCREATE_MUTEX_FAILED #define traceCREATE_MUTEX_FAILED() #endif #ifndef traceGIVE_MUTEX_RECURSIVE #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) #endif #ifndef traceGIVE_MUTEX_RECURSIVE_FAILED #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) #endif #ifndef traceTAKE_MUTEX_RECURSIVE #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) #endif #ifndef traceTAKE_MUTEX_RECURSIVE_FAILED #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) #endif #ifndef traceCREATE_COUNTING_SEMAPHORE #define traceCREATE_COUNTING_SEMAPHORE() #endif #ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED #define traceCREATE_COUNTING_SEMAPHORE_FAILED() #endif #ifndef traceQUEUE_SEND #define traceQUEUE_SEND( pxQueue ) #endif #ifndef traceQUEUE_SEND_FAILED #define traceQUEUE_SEND_FAILED( pxQueue ) #endif #ifndef traceQUEUE_RECEIVE #define traceQUEUE_RECEIVE( pxQueue ) #endif #ifndef traceQUEUE_PEEK #define traceQUEUE_PEEK( pxQueue ) #endif #ifndef traceQUEUE_PEEK_FROM_ISR #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) #endif #ifndef traceQUEUE_RECEIVE_FAILED #define traceQUEUE_RECEIVE_FAILED( pxQueue ) #endif #ifndef traceQUEUE_SEND_FROM_ISR #define traceQUEUE_SEND_FROM_ISR( pxQueue ) #endif #ifndef traceQUEUE_SEND_FROM_ISR_FAILED #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) #endif #ifndef traceQUEUE_RECEIVE_FROM_ISR #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) #endif #ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) #endif #ifndef traceQUEUE_PEEK_FROM_ISR_FAILED #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) #endif #ifndef traceQUEUE_DELETE #define traceQUEUE_DELETE( pxQueue ) #endif #ifndef traceTASK_CREATE #define traceTASK_CREATE( pxNewTCB ) #endif #ifndef traceTASK_CREATE_FAILED #define traceTASK_CREATE_FAILED() #endif #ifndef traceTASK_DELETE #define traceTASK_DELETE( pxTaskToDelete ) #endif #ifndef traceTASK_DELAY_UNTIL #define traceTASK_DELAY_UNTIL( x ) #endif #ifndef traceTASK_DELAY #define traceTASK_DELAY() #endif #ifndef traceTASK_PRIORITY_SET #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) #endif #ifndef traceTASK_SUSPEND #define traceTASK_SUSPEND( pxTaskToSuspend ) #endif #ifndef traceTASK_RESUME #define traceTASK_RESUME( pxTaskToResume ) #endif #ifndef traceTASK_RESUME_FROM_ISR #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) #endif #ifndef traceTASK_INCREMENT_TICK #define traceTASK_INCREMENT_TICK( xTickCount ) #endif #ifndef traceTIMER_CREATE #define traceTIMER_CREATE( pxNewTimer ) #endif #ifndef traceTIMER_CREATE_FAILED #define traceTIMER_CREATE_FAILED() #endif #ifndef traceTIMER_COMMAND_SEND #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) #endif #ifndef traceTIMER_EXPIRED #define traceTIMER_EXPIRED( pxTimer ) #endif #ifndef traceTIMER_COMMAND_RECEIVED #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) #endif #ifndef traceMALLOC #define traceMALLOC( pvAddress, uiSize ) #endif #ifndef traceFREE #define traceFREE( pvAddress, uiSize ) #endif #ifndef traceEVENT_GROUP_CREATE #define traceEVENT_GROUP_CREATE( xEventGroup ) #endif #ifndef traceEVENT_GROUP_CREATE_FAILED #define traceEVENT_GROUP_CREATE_FAILED() #endif #ifndef traceEVENT_GROUP_SYNC_BLOCK #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) #endif #ifndef traceEVENT_GROUP_SYNC_END #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred #endif #ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) #endif #ifndef traceEVENT_GROUP_WAIT_BITS_END #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred #endif #ifndef traceEVENT_GROUP_CLEAR_BITS #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) #endif #ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) #endif #ifndef traceEVENT_GROUP_SET_BITS #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) #endif #ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) #endif #ifndef traceEVENT_GROUP_DELETE #define traceEVENT_GROUP_DELETE( xEventGroup ) #endif #ifndef tracePEND_FUNC_CALL #define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret) #endif #ifndef tracePEND_FUNC_CALL_FROM_ISR #define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret) #endif #ifndef traceQUEUE_REGISTRY_ADD #define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName) #endif #ifndef traceTASK_NOTIFY_TAKE_BLOCK #define traceTASK_NOTIFY_TAKE_BLOCK() #endif #ifndef traceTASK_NOTIFY_TAKE #define traceTASK_NOTIFY_TAKE() #endif #ifndef traceTASK_NOTIFY_WAIT_BLOCK #define traceTASK_NOTIFY_WAIT_BLOCK() #endif #ifndef traceTASK_NOTIFY_WAIT #define traceTASK_NOTIFY_WAIT() #endif #ifndef traceTASK_NOTIFY #define traceTASK_NOTIFY() #endif #ifndef traceTASK_NOTIFY_FROM_ISR #define traceTASK_NOTIFY_FROM_ISR() #endif #ifndef traceTASK_NOTIFY_GIVE_FROM_ISR #define traceTASK_NOTIFY_GIVE_FROM_ISR() #endif #ifndef configGENERATE_RUN_TIME_STATS #define configGENERATE_RUN_TIME_STATS 0 #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ #ifndef portGET_RUN_TIME_COUNTER_VALUE #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ #endif /* portGET_RUN_TIME_COUNTER_VALUE */ #endif /* configGENERATE_RUN_TIME_STATS */ #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() #endif #ifndef configUSE_MALLOC_FAILED_HOOK #define configUSE_MALLOC_FAILED_HOOK 0 #endif #ifndef portPRIVILEGE_BIT #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) #endif #ifndef portYIELD_WITHIN_API #define portYIELD_WITHIN_API portYIELD #endif #ifndef portSUPPRESS_TICKS_AND_SLEEP #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) #endif #ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 #endif #if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 #endif #ifndef configUSE_TICKLESS_IDLE #define configUSE_TICKLESS_IDLE 0 #endif #ifndef configPRE_SLEEP_PROCESSING #define configPRE_SLEEP_PROCESSING( x ) #endif #ifndef configPOST_SLEEP_PROCESSING #define configPOST_SLEEP_PROCESSING( x ) #endif #ifndef configUSE_QUEUE_SETS #define configUSE_QUEUE_SETS 0 #endif #ifndef portTASK_USES_FLOATING_POINT #define portTASK_USES_FLOATING_POINT() #endif #ifndef configUSE_TIME_SLICING #define configUSE_TIME_SLICING 1 #endif #ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 #endif #ifndef configUSE_STATS_FORMATTING_FUNCTIONS #define configUSE_STATS_FORMATTING_FUNCTIONS 0 #endif #ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() #endif #ifndef configUSE_TRACE_FACILITY #define configUSE_TRACE_FACILITY 0 #endif #ifndef mtCOVERAGE_TEST_MARKER #define mtCOVERAGE_TEST_MARKER() #endif #ifndef mtCOVERAGE_TEST_DELAY #define mtCOVERAGE_TEST_DELAY() #endif #ifndef portASSERT_IF_IN_ISR #define portASSERT_IF_IN_ISR() #endif #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 #endif #ifndef configAPPLICATION_ALLOCATED_HEAP #define configAPPLICATION_ALLOCATED_HEAP 0 #endif #ifndef configUSE_TASK_NOTIFICATIONS #define configUSE_TASK_NOTIFICATIONS 1 #endif #ifndef portTICK_TYPE_IS_ATOMIC #define portTICK_TYPE_IS_ATOMIC 0 #endif #ifndef configSUPPORT_STATIC_ALLOCATION /* Defaults to 0 for backward compatibility. */ #define configSUPPORT_STATIC_ALLOCATION 0 #endif #ifndef configSUPPORT_DYNAMIC_ALLOCATION /* Defaults to 1 for backward compatibility. */ #define configSUPPORT_DYNAMIC_ALLOCATION 1 #endif /* Sanity check the configuration. */ #if( configUSE_TICKLESS_IDLE != 0 ) #if( INCLUDE_vTaskSuspend != 1 ) #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 #endif /* INCLUDE_vTaskSuspend */ #endif /* configUSE_TICKLESS_IDLE */ #if( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) ) #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1. #endif #if( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) ) #error configUSE_MUTEXES must be set to 1 to use recursive mutexes #endif #if( portTICK_TYPE_IS_ATOMIC == 0 ) /* Either variables of tick type cannot be read atomically, or portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when the tick count is returned to the standard critical section macros. */ #define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL() #define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL() #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) #else /* The tick type can be read atomically, so critical sections used when the tick count is returned can be defined away. */ #define portTICK_TYPE_ENTER_CRITICAL() #define portTICK_TYPE_EXIT_CRITICAL() #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x #endif /* Definitions to allow backward compatibility with FreeRTOS versions prior to V8 if desired. */ #ifndef configENABLE_BACKWARD_COMPATIBILITY #define configENABLE_BACKWARD_COMPATIBILITY 1 #endif #if configENABLE_BACKWARD_COMPATIBILITY == 1 #define eTaskStateGet eTaskGetState #define portTickType TickType_t #define xTaskHandle TaskHandle_t #define xQueueHandle QueueHandle_t #define xSemaphoreHandle SemaphoreHandle_t #define xQueueSetHandle QueueSetHandle_t #define xQueueSetMemberHandle QueueSetMemberHandle_t #define xTimeOutType TimeOut_t #define xMemoryRegion MemoryRegion_t #define xTaskParameters TaskParameters_t #define xTaskStatusType TaskStatus_t #define xTimerHandle TimerHandle_t #define xCoRoutineHandle CoRoutineHandle_t #define pdTASK_HOOK_CODE TaskHookFunction_t #define portTICK_RATE_MS portTICK_PERIOD_MS #define pcTaskGetTaskName pcTaskGetName #define pcTimerGetTimerName pcTimerGetName #define pcQueueGetQueueName pcQueueGetName #define vTaskGetTaskInfo vTaskGetInfo /* Backward compatibility within the scheduler code only - these definitions are not really required but are included for completeness. */ #define tmrTIMER_CALLBACK TimerCallbackFunction_t #define pdTASK_CODE TaskFunction_t #define xListItem ListItem_t #define xList List_t #endif /* configENABLE_BACKWARD_COMPATIBILITY */ #if( configUSE_ALTERNATIVE_API != 0 ) #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0 #endif /* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even if floating point hardware is otherwise supported by the FreeRTOS port in use. This constant is not supported by all FreeRTOS ports that include floating point support. */ #ifndef configUSE_TASK_FPU_SUPPORT #define configUSE_TASK_FPU_SUPPORT 1 #endif /* * In line with software engineering best practice, FreeRTOS implements a strict * data hiding policy, so the real structures used by FreeRTOS to maintain the * state of tasks, queues, semaphores, etc. are not accessible to the application * code. However, if the application writer wants to statically allocate such * an object then the size of the object needs to be know. Dummy structures * that are guaranteed to have the same size and alignment requirements of the * real objects are used for this purpose. The dummy list and list item * structures below are used for inclusion in such a dummy structure. */ struct xSTATIC_LIST_ITEM { TickType_t xDummy1; void *pvDummy2[ 4 ]; }; typedef struct xSTATIC_LIST_ITEM StaticListItem_t; /* See the comments above the struct xSTATIC_LIST_ITEM definition. */ struct xSTATIC_MINI_LIST_ITEM { TickType_t xDummy1; void *pvDummy2[ 2 ]; }; typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t; /* See the comments above the struct xSTATIC_LIST_ITEM definition. */ typedef struct xSTATIC_LIST { UBaseType_t uxDummy1; void *pvDummy2; StaticMiniListItem_t xDummy3; } StaticList_t; /* * In line with software engineering best practice, especially when supplying a * library that is likely to change in future versions, FreeRTOS implements a * strict data hiding policy. This means the Task structure used internally by * FreeRTOS is not accessible to application code. However, if the application * writer wants to statically allocate the memory required to create a task then * the size of the task object needs to be know. The StaticTask_t structure * below is provided for this purpose. Its sizes and alignment requirements are * guaranteed to match those of the genuine structure, no matter which * architecture is being used, and no matter how the values in FreeRTOSConfig.h * are set. Its contents are somewhat obfuscated in the hope users will * recognise that it would be unwise to make direct use of the structure members. */ typedef struct xSTATIC_TCB { void *pxDummy1; #if ( portUSING_MPU_WRAPPERS == 1 ) xMPU_SETTINGS xDummy2; #endif StaticListItem_t xDummy3[ 2 ]; UBaseType_t uxDummy5; void *pxDummy6; uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; #if ( portSTACK_GROWTH > 0 ) void *pxDummy8; #endif #if ( portCRITICAL_NESTING_IN_TCB == 1 ) UBaseType_t uxDummy9; #endif #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxDummy10[ 2 ]; #endif #if ( configUSE_MUTEXES == 1 ) UBaseType_t uxDummy12[ 2 ]; #endif #if ( configUSE_APPLICATION_TASK_TAG == 1 ) void *pxDummy14; #endif #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) uint32_t ulDummy16; #endif #if ( configUSE_NEWLIB_REENTRANT == 1 ) struct _reent xDummy17; #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) uint32_t ulDummy18; uint8_t ucDummy19; #endif #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t uxDummy20; #endif } StaticTask_t; /* * In line with software engineering best practice, especially when supplying a * library that is likely to change in future versions, FreeRTOS implements a * strict data hiding policy. This means the Queue structure used internally by * FreeRTOS is not accessible to application code. However, if the application * writer wants to statically allocate the memory required to create a queue * then the size of the queue object needs to be know. The StaticQueue_t * structure below is provided for this purpose. Its sizes and alignment * requirements are guaranteed to match those of the genuine structure, no * matter which architecture is being used, and no matter how the values in * FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope * users will recognise that it would be unwise to make direct use of the * structure members. */ typedef struct xSTATIC_QUEUE { void *pvDummy1[ 3 ]; union { void *pvDummy2; UBaseType_t uxDummy2; } u; StaticList_t xDummy3[ 2 ]; UBaseType_t uxDummy4[ 3 ]; uint8_t ucDummy5[ 2 ]; #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucDummy6; #endif #if ( configUSE_QUEUE_SETS == 1 ) void *pvDummy7; #endif #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxDummy8; uint8_t ucDummy9; #endif } StaticQueue_t; typedef StaticQueue_t StaticSemaphore_t; /* * In line with software engineering best practice, especially when supplying a * library that is likely to change in future versions, FreeRTOS implements a * strict data hiding policy. This means the event group structure used * internally by FreeRTOS is not accessible to application code. However, if * the application writer wants to statically allocate the memory required to * create an event group then the size of the event group object needs to be * know. The StaticEventGroup_t structure below is provided for this purpose. * Its sizes and alignment requirements are guaranteed to match those of the * genuine structure, no matter which architecture is being used, and no matter * how the values in FreeRTOSConfig.h are set. Its contents are somewhat * obfuscated in the hope users will recognise that it would be unwise to make * direct use of the structure members. */ typedef struct xSTATIC_EVENT_GROUP { TickType_t xDummy1; StaticList_t xDummy2; #if( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxDummy3; #endif #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucDummy4; #endif } StaticEventGroup_t; /* * In line with software engineering best practice, especially when supplying a * library that is likely to change in future versions, FreeRTOS implements a * strict data hiding policy. This means the software timer structure used * internally by FreeRTOS is not accessible to application code. However, if * the application writer wants to statically allocate the memory required to * create a software timer then the size of the queue object needs to be know. * The StaticTimer_t structure below is provided for this purpose. Its sizes * and alignment requirements are guaranteed to match those of the genuine * structure, no matter which architecture is being used, and no matter how the * values in FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in * the hope users will recognise that it would be unwise to make direct use of * the structure members. */ typedef struct xSTATIC_TIMER { void *pvDummy1; StaticListItem_t xDummy2; TickType_t xDummy3; UBaseType_t uxDummy4; void *pvDummy5[ 2 ]; #if( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxDummy6; #endif #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucDummy7; #endif } StaticTimer_t; #ifdef __cplusplus } #endif #endif /* INC_FREERTOS_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/StackMacros.h000066400000000000000000000202731357706137100247260ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef STACK_MACROS_H #define STACK_MACROS_H /* * Call the stack overflow hook function if the stack of the task being swapped * out is currently overflowed, or looks like it might have overflowed in the * past. * * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check * the current stack state only - comparing the current top of stack value to * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 * will also cause the last few stack bytes to be checked to ensure the value * to which the bytes were set when the task was created have not been * overwritten. Note this second test does not guarantee that an overflowed * stack will always be recognised. */ /*-----------------------------------------------------------*/ #if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) ) /* Only the current stack state is to be checked. */ #define taskCHECK_FOR_STACK_OVERFLOW() \ { \ /* Is the currently saved stack pointer within the stack limit? */ \ if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ { \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ } \ } #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ /*-----------------------------------------------------------*/ #if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) /* Only the current stack state is to be checked. */ #define taskCHECK_FOR_STACK_OVERFLOW() \ { \ \ /* Is the currently saved stack pointer within the stack limit? */ \ if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ { \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ } \ } #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ /*-----------------------------------------------------------*/ #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) #define taskCHECK_FOR_STACK_OVERFLOW() \ { \ const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \ \ if( ( pulStack[ 0 ] != ulCheckValue ) || \ ( pulStack[ 1 ] != ulCheckValue ) || \ ( pulStack[ 2 ] != ulCheckValue ) || \ ( pulStack[ 3 ] != ulCheckValue ) ) \ { \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ } \ } #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ /*-----------------------------------------------------------*/ #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) #define taskCHECK_FOR_STACK_OVERFLOW() \ { \ int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ \ \ pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ \ /* Has the extremity of the task stack ever been written over? */ \ if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ { \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ } \ } #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ /*-----------------------------------------------------------*/ /* Remove stack overflow macro if not being used. */ #ifndef taskCHECK_FOR_STACK_OVERFLOW #define taskCHECK_FOR_STACK_OVERFLOW() #endif #endif /* STACK_MACROS_H */ micropython-1.12/ports/cc3200/FreeRTOS/Source/include/croutine.h000066400000000000000000000673231357706137100243530ustar00rootroot00000000000000/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ #ifndef CO_ROUTINE_H #define CO_ROUTINE_H #ifndef INC_FREERTOS_H #error "include FreeRTOS.h must appear in source files before include croutine.h" #endif #include "list.h" #ifdef __cplusplus extern "C" { #endif /* Used to hide the implementation of the co-routine control block. The control block structure however has to be included in the header due to the macro implementation of the co-routine functionality. */ typedef void * CoRoutineHandle_t; /* Defines the prototype to which co-routine functions must conform. */ typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t ); typedef struct corCoRoutineControlBlock { crCOROUTINE_CODE pxCoRoutineFunction; ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */ UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ uint16_t uxState; /*< Used internally by the co-routine implementation. */ } CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */ /** * croutine. h *